Version 2.11.0-213.1.beta

Merge commit 'e256855d07ba9cad5048f012f38a05446ca2fe09' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 12e1c33..f280248 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-08-18T15:38:52.410101",
+  "generated": "2020-10-09T10:15:45.502457",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -136,7 +136,7 @@
       "name": "build_integration",
       "rootUri": "../pkg/build_integration",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.1"
     },
     {
       "name": "charcode",
@@ -178,13 +178,13 @@
       "name": "csslib",
       "rootUri": "../third_party/pkg/csslib",
       "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "languageVersion": "2.11"
     },
     {
       "name": "dart2js_info",
       "rootUri": "../third_party/pkg/dart2js_info",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.3"
     },
     {
       "name": "dart2js_tools",
@@ -208,7 +208,7 @@
       "name": "dart_style",
       "rootUri": "../third_party/pkg_tested/dart_style",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.9"
     },
     {
       "name": "dartdev",
@@ -220,7 +220,7 @@
       "name": "dartdoc",
       "rootUri": "../third_party/pkg/dartdoc",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.10"
     },
     {
       "name": "dartfix",
@@ -348,8 +348,7 @@
     {
       "name": "js_runtime",
       "rootUri": "../sdk/lib/_internal/js_runtime",
-      "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "packageUri": "lib/"
     },
     {
       "name": "json_rpc_2",
@@ -426,7 +425,7 @@
       "name": "native_stack_traces",
       "rootUri": "../pkg/native_stack_traces",
       "packageUri": "lib/",
-      "languageVersion": "2.8"
+      "languageVersion": "2.10"
     },
     {
       "name": "nnbd_migration",
@@ -447,11 +446,22 @@
       "languageVersion": "2.2"
     },
     {
+      "name": "observatory_2",
+      "rootUri": "../runtime/observatory_2",
+      "packageUri": "lib/",
+      "languageVersion": "2.2"
+    },
+    {
       "name": "observatory_test_package",
       "rootUri": "../runtime/observatory/tests/service/observatory_test_package",
       "languageVersion": "2.7"
     },
     {
+      "name": "observatory_test_package_2",
+      "rootUri": "../runtime/observatory_2/tests/service_2/observatory_test_package_2",
+      "languageVersion": "2.7"
+    },
+    {
       "name": "package_config",
       "rootUri": "../third_party/pkg_tested/package_config",
       "packageUri": "lib/",
@@ -485,7 +495,7 @@
       "name": "pub",
       "rootUri": "../third_party/pkg/pub",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.9"
     },
     {
       "name": "pub_semver",
@@ -508,8 +518,7 @@
     {
       "name": "sdk_library_metadata",
       "rootUri": "../sdk/lib/_internal/sdk_library_metadata",
-      "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "packageUri": "lib/"
     },
     {
       "name": "shelf",
diff --git a/.gitignore b/.gitignore
index 2bc7008..0ad331e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@
 .gdb_history
 
 # Clangd files
+.cache/clangd
 .clangd
 
 # Built by chromebot and downloaded from Google Storage
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9b56ce5..01c6f7a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,59 @@
-## 2.10.0
+## 2.11.0
+
+### Core libraries
+
+#### `dart:io`
+
+*   `HttpRequest` will now correctly follow HTTP 308 redirects
+    (`HttpStatus.permanentRedirect`).
+
+### Dart VM
+
+### Dart2JS
+
+* Removed `--no-defer-class-types` and `--no-new-deferred-split`.
+
+### Tools
+
+#### Dartanalyzer
+
+* Removed the `--use-fasta-parser`, `--preview-dart-2`, and
+  `--enable-assert-initializers` command line options. These options haven't
+  been supported in a while and were no-ops.
+
+#### Linter
+
+Updated the Linter to `0.1.121`, which includes:
+
+# 0.1.121
+
+* Performance improvements to `always_use_package_imports`, 
+  `avoid_renaming_method_parameters`, `prefer_relative_imports` and
+  `public_member_api_docs`.
+* (internal): updates to analyzer `0.40.4` APIs
+* New lint: `cast_nullable_to_non_nullable`.
+* New lint: `null_check_on_nullable_type_parameter`.
+* New lint: `tighten_type_of_initializing_formals`.
+* Updates to `public_member_apis` to check generic type aliases.
+* (Internal): updates to adopt new analyzer APIs.
+* Fixed `close_sinks` to handle `this`-prefixed property accesses.
+* New lint: `unnecessary_null_checks`.
+* Fixed `unawaited_futures` to handle `Future` subtypes.
+* New lint: `avoid_type_to_string`.
+
+## 2.10.1 - 2020-10-06
+
+This is a patch release that fixes the following issues:
+* crashes when developing Flutter applications (issue [#43464][]).
+* non-deterministic incorrect program behaviour and/or crashes (issue
+  [flutter/flutter#66672][]).
+* uncaught TypeErrors in DDC (issue [#43661][]).
+
+[#43464]: https://github.com/dart-lang/sdk/issues/43464
+[flutter/flutter#66672]: https://github.com/flutter/flutter/issues/66672
+[#43661]: https://github.com/dart-lang/sdk/issues/43661
+
+## 2.10.0 - 2020-09-28
 
 ### Core libraries
 
@@ -8,7 +63,7 @@
     to cancel outgoing HTTP requests and stop following IO operations.
 *   A validation check is added to `path` of class `Cookie`. Having characters
     ranging from 0x00 to 0x1f and 0x3b (";") will lead to a `FormatException`.
-*   The `HttpClient` and `HttpServer` clasess now have a 1 MiB limit for the
+*   The `HttpClient` and `HttpServer` classes now have a 1 MiB limit for the
     total size of the HTTP headers when parsing a request or response, instead
     of the former 8 KiB limit for each header name and value. This limit cannot
     be configured at this time.
@@ -36,7 +91,7 @@
     deferred loading of types, pass `--no-defer-class-types`. See the original
     post on the [unsoundness in the deferred loading algorithm][].
 *   Enables a new sound deferred splitting algorithm. To explicitly disable
-    the new deferred splitting algorithm, pass `--no-new-deferred-split'.
+    the new deferred splitting algorithm, pass `--no-new-deferred-split`.
     See the original post on the
     [unsoundness in the deferred loading algorithm][].
 
@@ -130,9 +185,14 @@
 *   [Abstract Unix Domain Socket][] is supported on Linux/Android now. Using an
     `InternetAddress` with `address` starting with '@' and type being
     `InternetAddressType.Unix` will create an abstract Unix Domain Socket.
+*   On Windows, file APIs can now handle files and directories identified by
+    long paths (greater than 260 characters). It complies with all restrictions
+    from [Long Path on Windows][]. Note that `Directory.current` does not work
+    with long path.
 
 [#42006]: https://github.com/dart-lang/sdk/issues/42006
 [Abstract Unix Domain Socket]: http://man7.org/linux/man-pages/man7/unix.7.html
+[Long Path on Windows]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
 
 #### `dart:html`
 
diff --git a/DEPS b/DEPS
index 8d2dda6..8d44494 100644
--- a/DEPS
+++ b/DEPS
@@ -39,12 +39,12 @@
 
   # Checked-in SDK version. The checked-in SDK is a Dart SDK distribution in a
   # cipd package used to run Dart scripts in the build and test infrastructure.
-  "sdk_tag": "version:2.10.0-79.0.dev",
+  "sdk_tag": "version:2.11.0-190.0.dev",
 
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "d21ed3a1dd64107916db68afdce21709df65e85f",
+  "co19_rev": "0d84277b464e91f09326292b2943381dfa6056ed",
   "co19_2_rev": "e48b3090826cf40b8037648f19d211e8eab1b4b6",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
@@ -66,7 +66,7 @@
 
   # Revisions of /third_party/* dependencies.
   "args_tag": "1.6.0",
-  "async_rev": "128c461a97dbdbd9336ba000ba5a5c02e79b8651",
+  "async_rev": "38ace5fa83697928d5f29911e346e6311dd00857",
   "bazel_worker_rev": "26680d5e249b249c7216ab2fed0ac8ed4ee285c5",
   "benchmark_harness_rev": "ec6b646f5443faa871e126ac1ba248c94ca06257",
   "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
@@ -76,10 +76,10 @@
   "charcode_rev": "4a685faba42d86ebd9d661eadd1e79d0a1c34c43",
   "chrome_rev" : "19997",
   "cli_util_tag" : "0.2.0",
-  "collection_rev": "583693680fc067e34ca5b72503df25e8b80579f9",
+  "collection_rev": "52e219581f72a3eac013d6f5550c580962677425",
   "convert_rev": "c1b01f832835d3d8a06b0b246a361c0eaab35d3c",
   "crypto_rev": "f7c48b334b1386bc5ab0f706fbcd6df8496a87fc",
-  "csslib_rev": "681a6603f86bbbe64e8af42d722aef63b028d241",
+  "csslib_rev": "6f77b3dcee957d3e2d5083f666221a220e9ed1f1",
   "dart2js_info_rev" : "0632a623b08e1f601c7eba99e0186a581ae799e9",
 
   # Note: Updates to dart_style have to be coordinated with the infrastructure
@@ -97,24 +97,24 @@
   "dart_style_tag": "1.3.7",  # Please see the note above before updating.
 
   "chromedriver_tag": "83.0.4103.39",
-  "dartdoc_rev" : "b039e21a7226b61ca2de7bd6c7a07fc77d4f64a9",
+  "dartdoc_rev" : "8f5f30e58bbc0f11f104888ee87f11cbd6b82cc7",
   "ffi_rev": "454ab0f9ea6bd06942a983238d8a6818b1357edb",
   "fixnum_rev": "16d3890c6dc82ca629659da1934e412292508bba",
   "glob_rev": "e9f4e6b7ae8abe5071461cf8f47191bb19cf7ef6",
-  "html_rev": "083a36cd801a4b787ba156b7c6e4c8b2e2daed4a",
+  "html_rev": "22f17e97fedeacaa1e945cf84d8016284eed33a6",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev" : "ea269f79321d659208402088f3297e8920a88ee6",
   "http_parser_rev": "6e63a97b5aaa2b4d1215fe01683e51fb73258e54",
   "http_retry_tag": "0.1.1",
-  "http_rev": "7b55a2c62a5f6fb680ad7a4607bab7281a235563",
+  "http_rev": "ca418355b5fc60cf981de3bd7364ec0dd943fa8f",
   "http_throttle_tag" : "1.0.2",
   "icu_rev" : "79326efe26e5440f530963704c3c0ff965b3a4ac",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.16.1",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "8f189db8f0c299187a0e8fa959dba7e9b0254be5",
-  "linter_tag": "0.1.118",
-  "logging_rev": "9561ba016ae607747ae69b846c0e10958ca58ed4",
+  "linter_tag": "0.1.121",
+  "logging_rev": "1590ba0b648a51e7eb3895c612e4b72f72623b6f",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "dbeafd47759e7dd0a167602153bb9c49fb5e5fe7",
   "matcher_rev": "9cae8faa7868bf3a88a7ba45eb0bd128e66ac515",
@@ -142,9 +142,9 @@
   "source_map_stack_trace_rev": "1c3026f69d9771acf2f8c176a1ab750463309cce",
   "source_maps-0.9.4_rev": "38524",
   "source_maps_rev": "53eb92ccfe6e64924054f83038a534b959b12b3e",
-  "source_span_rev": "94833d6cbf4552ebe5d2aa6714acecd93834e53a",
+  "source_span_rev": "cc7c4288a83f71ecef3414199947b52a8c112c65",
   "sse_tag": "e5cf68975e8e87171a3dc297577aa073454a91dc",
-  "stack_trace_tag": "d3813ca0a77348e0faf0d6af0cc17913e36afa39",
+  "stack_trace_tag": "45319bfd2a6da228d8c32b06e1da02ad199373c7",
   "stagehand_tag": "v3.3.9",
   "stream_channel_tag": "c446774fd077c9bdbd6235a7aadc661ef60a9727",
   "string_scanner_rev": "1b63e6e5db5933d7be0a45da6e1129fe00262734",
@@ -154,7 +154,7 @@
   "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
   "test_reflective_loader_tag": "0.1.9",
   "test_rev": "e37a93bbeae23b215972d1659ac865d71287ff6a",
-  "tflite_native_rev": "3c777c40608a2a9f1427bfe0028ab48e7116b4c1",
+  "tflite_native_rev": "0.4.0+1",
   "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719",
   "usage_tag": "3.4.0",
   "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
@@ -525,16 +525,6 @@
     "dep_type": "cipd",
   },
 
-  Var("dart_root") + "/pkg/front_end/testcases/old_dills/dills": {
-    "packages": [
-      {
-        "package": "dart/cfe/dart2js_dills",
-        "version": "binary_version:45",
-      }
-    ],
-    "dep_type": "cipd",
-  },
-
   # TODO(37531): Remove these cipd packages and build with sdk instead when
   # benchmark runner gets support for that.
   Var("dart_root") + "/benchmarks/FfiBoringssl/native/out/": {
diff --git a/benchmarks/EventLoopLatencyJson/dart/EventLoopLatencyJson.dart b/benchmarks/EventLoopLatencyJson/dart/EventLoopLatencyJson.dart
new file mode 100644
index 0000000..7a8c5ee
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart/EventLoopLatencyJson.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+import 'json_benchmark.dart';
+import 'latency.dart';
+
+main() async {
+  // Start GC pressure from helper isolate.
+  final exitPort = ReceivePort();
+  final exitFuture = exitPort.first;
+  final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
+
+  // Measure event loop latency.
+  const tickDuration = const Duration(milliseconds: 1);
+  const numberOfTicks = 8 * 1000; // min 8 seconds.
+  final EventLoopLatencyStats stats =
+      await measureEventLoopLatency(tickDuration, numberOfTicks);
+
+  // Kill isolate & wait until it's dead.
+  isolate.kill(priority: Isolate.immediate);
+  await exitFuture;
+
+  // Report event loop latency statistics.
+  stats.report('EventLoopLatencyJson');
+}
+
+void run(dynamic msg) {
+  while (true) {
+    JsonRoundTripBenchmark().run();
+  }
+}
diff --git a/benchmarks/EventLoopLatencyJson/dart/json_benchmark.dart b/benchmarks/EventLoopLatencyJson/dart/json_benchmark.dart
new file mode 100644
index 0000000..c29a5b5
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart/json_benchmark.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+import 'dart:convert';
+
+class JsonRoundTripBenchmark {
+  void run() {
+    final res = json.decode(jsonData);
+    final out = json.encode(res);
+    if (out[0] != jsonData[0]) {
+      throw 'json conversion error';
+    }
+  }
+}
+
+// Builds around 4.5 MB of json data - big enough so the decoded object graph
+// does not fit into new space.
+final String jsonData = () {
+  final rnd = Random(42);
+  dynamic buildTree(int depth) {
+    final int coin = rnd.nextInt(1000);
+    if (depth == 0) {
+      if (coin % 2 == 0) return coin;
+      return 'foo-$coin';
+    }
+
+    if (coin % 2 == 0) {
+      final map = <String, dynamic>{};
+      final int length = rnd.nextInt(18);
+      for (int i = 0; i < length; ++i) {
+        map['bar-$i'] = buildTree(depth - 1);
+      }
+      return map;
+    } else {
+      final list = <dynamic>[];
+      final int length = rnd.nextInt(18);
+      for (int i = 0; i < length; ++i) {
+        list.add(buildTree(depth - 1));
+      }
+      return list;
+    }
+  }
+
+  return json.encode({'data': buildTree(6)});
+}();
diff --git a/benchmarks/EventLoopLatencyJson/dart/latency.dart b/benchmarks/EventLoopLatencyJson/dart/latency.dart
new file mode 100644
index 0000000..c368802
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart/latency.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math' as math;
+import 'dart:typed_data';
+
+/// Measures event loop responsiveness.
+///
+/// Schedules new timer events, [tickDuration] in the future, and measures how
+/// long it takes for these events to actually arrive.
+///
+/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
+Future<EventLoopLatencyStats> measureEventLoopLatency(
+    Duration tickDuration, int numberOfTicks) {
+  final completer = Completer<EventLoopLatencyStats>();
+
+  final tickDurationInUs = tickDuration.inMicroseconds;
+  final buffer = _TickLatencies(numberOfTicks);
+  final sw = Stopwatch()..start();
+  int lastTimestamp = 0;
+
+  void trigger() {
+    final int currentTimestamp = sw.elapsedMicroseconds;
+
+    // Every tick we missed to schedule we'll add with difference to when we
+    // would've scheduled it and when we became responsive again.
+    bool done = false;
+    while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
+      done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
+      lastTimestamp += tickDurationInUs;
+    }
+
+    if (!done) {
+      lastTimestamp = currentTimestamp;
+      Timer(tickDuration, trigger);
+    } else {
+      completer.complete(buffer.makeStats());
+    }
+  }
+
+  Timer(tickDuration, trigger);
+
+  return completer.future;
+}
+
+/// Result of the event loop latency measurement.
+class EventLoopLatencyStats {
+  /// Minimum latency between scheduling a tick and it's arrival (in ms).
+  final double minLatency;
+
+  /// Average latency between scheduling a tick and it's arrival (in ms).
+  final double avgLatency;
+
+  /// Maximum latency between scheduling a tick and it's arrival (in ms).
+  final double maxLatency;
+
+  /// The 50th percentile (median) (in ms).
+  final double percentile50th;
+
+  /// The 90th percentile (in ms).
+  final double percentile90th;
+
+  /// The 95th percentile (in ms).
+  final double percentile95th;
+
+  /// The 99th percentile (in ms).
+  final double percentile99th;
+
+  /// The maximum RSS of the process.
+  final int maxRss;
+
+  EventLoopLatencyStats(
+      this.minLatency,
+      this.avgLatency,
+      this.maxLatency,
+      this.percentile50th,
+      this.percentile90th,
+      this.percentile95th,
+      this.percentile99th,
+      this.maxRss);
+
+  void report(String name) {
+    print('$name.Min(RunTime): $minLatency ms.');
+    print('$name.Avg(RunTime): $avgLatency ms.');
+    print('$name.Percentile50(RunTime): $percentile50th ms.');
+    print('$name.Percentile90(RunTime): $percentile90th ms.');
+    print('$name.Percentile95(RunTime): $percentile95th ms.');
+    print('$name.Percentile99(RunTime): $percentile99th ms.');
+    print('$name.Max(RunTime): $maxLatency ms.');
+    print('$name.MaxRss(MemoryUse): $maxRss');
+  }
+}
+
+/// Accumulates tick latencies and makes statistics for it.
+class _TickLatencies {
+  final Uint64List _timestamps;
+  int _index = 0;
+
+  _TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
+
+  /// Returns `true` while the buffer has not been filled yet.
+  bool add(int latencyInUs) {
+    _timestamps[_index++] = latencyInUs;
+    return _index < _timestamps.length;
+  }
+
+  EventLoopLatencyStats makeStats() {
+    if (_index != _timestamps.length) {
+      throw 'Buffer has not been fully filled yet.';
+    }
+
+    _timestamps.sort();
+    final length = _timestamps.length;
+    final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
+    final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
+    final int max = _timestamps.fold(0, math.max);
+    final percentile50th = _timestamps[50 * length ~/ 100];
+    final percentile90th = _timestamps[90 * length ~/ 100];
+    final percentile95th = _timestamps[95 * length ~/ 100];
+    final percentile99th = _timestamps[99 * length ~/ 100];
+
+    return EventLoopLatencyStats(
+        min / 1000,
+        avg / 1000,
+        max / 1000,
+        percentile50th / 1000,
+        percentile90th / 1000,
+        percentile95th / 1000,
+        percentile99th / 1000,
+        ProcessInfo.maxRss);
+  }
+}
diff --git a/benchmarks/EventLoopLatencyJson/dart2/EventLoopLatencyJson.dart b/benchmarks/EventLoopLatencyJson/dart2/EventLoopLatencyJson.dart
new file mode 100644
index 0000000..7a8c5ee
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart2/EventLoopLatencyJson.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+import 'json_benchmark.dart';
+import 'latency.dart';
+
+main() async {
+  // Start GC pressure from helper isolate.
+  final exitPort = ReceivePort();
+  final exitFuture = exitPort.first;
+  final isolate = await Isolate.spawn(run, null, onExit: exitPort.sendPort);
+
+  // Measure event loop latency.
+  const tickDuration = const Duration(milliseconds: 1);
+  const numberOfTicks = 8 * 1000; // min 8 seconds.
+  final EventLoopLatencyStats stats =
+      await measureEventLoopLatency(tickDuration, numberOfTicks);
+
+  // Kill isolate & wait until it's dead.
+  isolate.kill(priority: Isolate.immediate);
+  await exitFuture;
+
+  // Report event loop latency statistics.
+  stats.report('EventLoopLatencyJson');
+}
+
+void run(dynamic msg) {
+  while (true) {
+    JsonRoundTripBenchmark().run();
+  }
+}
diff --git a/benchmarks/EventLoopLatencyJson/dart2/json_benchmark.dart b/benchmarks/EventLoopLatencyJson/dart2/json_benchmark.dart
new file mode 100644
index 0000000..c29a5b5
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart2/json_benchmark.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+import 'dart:convert';
+
+class JsonRoundTripBenchmark {
+  void run() {
+    final res = json.decode(jsonData);
+    final out = json.encode(res);
+    if (out[0] != jsonData[0]) {
+      throw 'json conversion error';
+    }
+  }
+}
+
+// Builds around 4.5 MB of json data - big enough so the decoded object graph
+// does not fit into new space.
+final String jsonData = () {
+  final rnd = Random(42);
+  dynamic buildTree(int depth) {
+    final int coin = rnd.nextInt(1000);
+    if (depth == 0) {
+      if (coin % 2 == 0) return coin;
+      return 'foo-$coin';
+    }
+
+    if (coin % 2 == 0) {
+      final map = <String, dynamic>{};
+      final int length = rnd.nextInt(18);
+      for (int i = 0; i < length; ++i) {
+        map['bar-$i'] = buildTree(depth - 1);
+      }
+      return map;
+    } else {
+      final list = <dynamic>[];
+      final int length = rnd.nextInt(18);
+      for (int i = 0; i < length; ++i) {
+        list.add(buildTree(depth - 1));
+      }
+      return list;
+    }
+  }
+
+  return json.encode({'data': buildTree(6)});
+}();
diff --git a/benchmarks/EventLoopLatencyJson/dart2/latency.dart b/benchmarks/EventLoopLatencyJson/dart2/latency.dart
new file mode 100644
index 0000000..c368802
--- /dev/null
+++ b/benchmarks/EventLoopLatencyJson/dart2/latency.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:math' as math;
+import 'dart:typed_data';
+
+/// Measures event loop responsiveness.
+///
+/// Schedules new timer events, [tickDuration] in the future, and measures how
+/// long it takes for these events to actually arrive.
+///
+/// Runs [numberOfTicks] times before completing with [EventLoopLatencyStats].
+Future<EventLoopLatencyStats> measureEventLoopLatency(
+    Duration tickDuration, int numberOfTicks) {
+  final completer = Completer<EventLoopLatencyStats>();
+
+  final tickDurationInUs = tickDuration.inMicroseconds;
+  final buffer = _TickLatencies(numberOfTicks);
+  final sw = Stopwatch()..start();
+  int lastTimestamp = 0;
+
+  void trigger() {
+    final int currentTimestamp = sw.elapsedMicroseconds;
+
+    // Every tick we missed to schedule we'll add with difference to when we
+    // would've scheduled it and when we became responsive again.
+    bool done = false;
+    while (!done && lastTimestamp < (currentTimestamp - tickDurationInUs)) {
+      done = !buffer.add(currentTimestamp - lastTimestamp - tickDurationInUs);
+      lastTimestamp += tickDurationInUs;
+    }
+
+    if (!done) {
+      lastTimestamp = currentTimestamp;
+      Timer(tickDuration, trigger);
+    } else {
+      completer.complete(buffer.makeStats());
+    }
+  }
+
+  Timer(tickDuration, trigger);
+
+  return completer.future;
+}
+
+/// Result of the event loop latency measurement.
+class EventLoopLatencyStats {
+  /// Minimum latency between scheduling a tick and it's arrival (in ms).
+  final double minLatency;
+
+  /// Average latency between scheduling a tick and it's arrival (in ms).
+  final double avgLatency;
+
+  /// Maximum latency between scheduling a tick and it's arrival (in ms).
+  final double maxLatency;
+
+  /// The 50th percentile (median) (in ms).
+  final double percentile50th;
+
+  /// The 90th percentile (in ms).
+  final double percentile90th;
+
+  /// The 95th percentile (in ms).
+  final double percentile95th;
+
+  /// The 99th percentile (in ms).
+  final double percentile99th;
+
+  /// The maximum RSS of the process.
+  final int maxRss;
+
+  EventLoopLatencyStats(
+      this.minLatency,
+      this.avgLatency,
+      this.maxLatency,
+      this.percentile50th,
+      this.percentile90th,
+      this.percentile95th,
+      this.percentile99th,
+      this.maxRss);
+
+  void report(String name) {
+    print('$name.Min(RunTime): $minLatency ms.');
+    print('$name.Avg(RunTime): $avgLatency ms.');
+    print('$name.Percentile50(RunTime): $percentile50th ms.');
+    print('$name.Percentile90(RunTime): $percentile90th ms.');
+    print('$name.Percentile95(RunTime): $percentile95th ms.');
+    print('$name.Percentile99(RunTime): $percentile99th ms.');
+    print('$name.Max(RunTime): $maxLatency ms.');
+    print('$name.MaxRss(MemoryUse): $maxRss');
+  }
+}
+
+/// Accumulates tick latencies and makes statistics for it.
+class _TickLatencies {
+  final Uint64List _timestamps;
+  int _index = 0;
+
+  _TickLatencies(int numberOfTicks) : _timestamps = Uint64List(numberOfTicks);
+
+  /// Returns `true` while the buffer has not been filled yet.
+  bool add(int latencyInUs) {
+    _timestamps[_index++] = latencyInUs;
+    return _index < _timestamps.length;
+  }
+
+  EventLoopLatencyStats makeStats() {
+    if (_index != _timestamps.length) {
+      throw 'Buffer has not been fully filled yet.';
+    }
+
+    _timestamps.sort();
+    final length = _timestamps.length;
+    final double avg = _timestamps.fold(0, (int a, int b) => a + b) / length;
+    final int min = _timestamps.fold(0x7fffffffffffffff, math.min);
+    final int max = _timestamps.fold(0, math.max);
+    final percentile50th = _timestamps[50 * length ~/ 100];
+    final percentile90th = _timestamps[90 * length ~/ 100];
+    final percentile95th = _timestamps[95 * length ~/ 100];
+    final percentile99th = _timestamps[99 * length ~/ 100];
+
+    return EventLoopLatencyStats(
+        min / 1000,
+        avg / 1000,
+        max / 1000,
+        percentile50th / 1000,
+        percentile90th / 1000,
+        percentile95th / 1000,
+        percentile99th / 1000,
+        ProcessInfo.maxRss);
+  }
+}
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 336445e..ee58748 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -425,9 +425,6 @@
     configs = []  # Prevent list overwriting warning.
     configs = invoker.configs
 
-    # See above call.
-    set_sources_assignment_filter([])
-
     if (defined(invoker.all_dependent_configs)) {
       all_dependent_configs = invoker.all_dependent_configs
     }
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni
index df8080e..85f7b92 100644
--- a/build/config/mac/rules.gni
+++ b/build/config/mac/rules.gni
@@ -72,7 +72,6 @@
   _resources = invoker.resources
 
   copy(target_name) {
-    set_sources_assignment_filter([])
     sources = _resources
     outputs = [ "$root_build_dir/$_app_name.app/$_bundle_directory/Contents/Resources/{{source_file_part}}" ]
 
diff --git a/build/config/templates/templates.gni b/build/config/templates/templates.gni
index cd310ce..a8815f8 100644
--- a/build/config/templates/templates.gni
+++ b/build/config/templates/templates.gni
@@ -17,8 +17,6 @@
 #     variables = "app_name=chrome_shell app_version=1"
 #   }
 template("file_template") {
-  set_sources_assignment_filter([])
-
   if (defined(invoker.testonly)) {
     testonly = invoker.testonly
   }
diff --git a/build/rust/rust.gni b/build/rust/rust.gni
index c3fb4dc..0a8cdc1 100644
--- a/build/rust/rust.gni
+++ b/build/rust/rust.gni
@@ -74,7 +74,7 @@
   } else {
     if (is_win) {
       output_file = "${invoker.lib_name}.lib"
-    }else {
+    } else {
       output_file = "lib${invoker.lib_name}.a"
     }
   }
@@ -89,7 +89,7 @@
   config("${target_name}_cargo_config") {
     if (!shared) {
       libs = [ invoker.lib_name ]
-      lib_dirs = [ out_dir ]
+      lib_dirs = [ target_out_dir ]
     }
   }
 
@@ -97,7 +97,7 @@
   # So we need to copy it to target_out_dir to make it easier for dependees to
   # locate the library.
   copy(target_name) {
-    deps = [ ":${target_name}_cargo" ]
+    public_deps = [ ":${target_name}_cargo" ]
     sources = [ "${cargo_out_dir}/${output_file}" ]
     outputs = [ "${target_out_dir}/${output_file}" ]
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index e6e8921..f809b87 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -46,9 +46,8 @@
 
   /// This method should be called during pre-traversal, to mark the start of a
   /// loop statement, switch statement, try statement, loop collection element,
-  /// local function, or closure which might need to be queried later.
-  ///
-  /// [isClosure] should be true if the node is a local function or closure.
+  /// local function, closure, or late variable initializer which might need to
+  /// be queried later.
   ///
   /// The span between the call to [beginNode] and [endNode] should cover any
   /// statements and expressions that might be crossed by a backwards jump.  So
@@ -71,23 +70,26 @@
 
   /// This method may be called during pre-traversal, to mark the end of a
   /// loop statement, switch statement, try statement, loop collection element,
-  /// local function, or closure which might need to be queried later.
+  /// local function, closure, or late variable initializer which might need to
+  /// be queried later.
   ///
-  /// [isClosure] should be true if the node is a local function or closure.
+  /// [isClosureOrLateVariableInitializer] should be true if the node is a local
+  /// function or closure, or a late variable initializer.
   ///
   /// In contrast to [endNode], this method doesn't store the data gathered for
   /// the node for later use; instead it returns it to the caller.  At a later
   /// time, the caller should pass the returned data to [storeNodeInfo].
   ///
   /// See [beginNode] for more details.
-  AssignedVariablesNodeInfo<Variable> deferNode({bool isClosure: false}) {
+  AssignedVariablesNodeInfo<Variable> deferNode(
+      {bool isClosureOrLateVariableInitializer: false}) {
     AssignedVariablesNodeInfo<Variable> info = _stack.removeLast();
     info._written.removeAll(info._declared);
     info._captured.removeAll(info._declared);
     AssignedVariablesNodeInfo<Variable> last = _stack.last;
     last._written.addAll(info._written);
     last._captured.addAll(info._captured);
-    if (isClosure) {
+    if (isClosureOrLateVariableInitializer) {
       last._captured.addAll(info._written);
       _anywhere._captured.addAll(info._written);
     }
@@ -117,16 +119,22 @@
 
   /// This method should be called during pre-traversal, to mark the end of a
   /// loop statement, switch statement, try statement, loop collection element,
-  /// local function, or closure which might need to be queried later.
+  /// local function, closure, or late variable initializer which might need to
+  /// be queried later.
   ///
-  /// [isClosure] should be true if the node is a local function or closure.
+  /// [isClosureOrLateVariableInitializer] should be true if the node is a local
+  /// function or closure, or a late variable initializer.
   ///
   /// This is equivalent to a call to [deferNode] followed immediately by a call
   /// to [storeInfo].
   ///
   /// See [beginNode] for more details.
-  void endNode(Node node, {bool isClosure: false}) {
-    storeInfo(node, deferNode(isClosure: isClosure));
+  void endNode(Node node, {bool isClosureOrLateVariableInitializer: false}) {
+    storeInfo(
+        node,
+        deferNode(
+            isClosureOrLateVariableInitializer:
+                isClosureOrLateVariableInitializer));
   }
 
   /// Call this after visiting the code to be analyzed, to check invariants.
@@ -147,6 +155,22 @@
     }());
   }
 
+  /// Call this method between calls to [beginNode] and [endNode]/[deferNode],
+  /// if it is necessary to temporarily process some code outside the current
+  /// node.  Returns a data structure that should be passed to [pushNode].
+  ///
+  /// This is used by the front end when building for-elements in lists, maps,
+  /// and sets; their initializers are partially built after building their
+  /// loop conditions but before completely building their bodies.
+  AssignedVariablesNodeInfo<Variable> popNode() {
+    return _stack.removeLast();
+  }
+
+  /// Call this method to un-do the effect of [popNode].
+  void pushNode(AssignedVariablesNodeInfo<Variable> node) {
+    _stack.add(node);
+  }
+
   /// Call this method to register that the node [from] for which information
   /// has been stored is replaced by the node [to].
   // TODO(johnniwinther): Remove this when unified collections are encoded as
@@ -327,6 +351,9 @@
   /// Call this method when visiting a boolean literal expression.
   void booleanLiteral(Expression expression, bool value);
 
+  /// Call this method just before visiting a conditional expression ("?:").
+  void conditional_conditionBegin();
+
   /// Call this method upon reaching the ":" part of a conditional expression
   /// ("?:").  [thenExpression] should be the expression preceding the ":".
   void conditional_elseBegin(Expression thenExpression);
@@ -449,6 +476,26 @@
   /// collection element.  See [forEach_bodyBegin] for details.
   void forEach_end();
 
+  /// Call this method to forward information on [oldExpression] to
+  /// [newExpression].
+  ///
+  /// This can be used to preserve promotions through a replacement from
+  /// [oldExpression] to [newExpression]. For instance when rewriting
+  ///
+  ///    method(int i) {
+  ///      if (i is int) { ... } else { ... }
+  ///    }
+  ///
+  ///  to
+  ///
+  ///    method(int i) {
+  ///      if (i is int || throw ...) { ... } else { ... }
+  ///    }
+  ///
+  ///  the promotion `i is int` can be forwarded to `i is int || throw ...` and
+  ///  there preserved in the surrounding if statement.
+  void forwardExpression(Expression newExpression, Expression oldExpression);
+
   /// Call this method just before visiting the body of a function expression or
   /// local function.
   ///
@@ -492,6 +539,25 @@
   bool ifNullExpression_rightBegin(
       Expression leftHandSide, Type leftHandSideType);
 
+  /// Call this method before visiting the condition part of an if statement.
+  ///
+  /// The order of visiting an if statement with no "else" part should be:
+  /// - Call [ifStatement_conditionBegin]
+  /// - Visit the condition
+  /// - Call [ifStatement_thenBegin]
+  /// - Visit the "then" statement
+  /// - Call [ifStatement_end], passing `false` for `hasElse`.
+  ///
+  /// The order of visiting an if statement with an "else" part should be:
+  /// - Call [ifStatement_conditionBegin]
+  /// - Visit the condition
+  /// - Call [ifStatement_thenBegin]
+  /// - Visit the "then" statement
+  /// - Call [ifStatement_elseBegin]
+  /// - Visit the "else" statement
+  /// - Call [ifStatement_end], passing `true` for `hasElse`.
+  void ifStatement_conditionBegin();
+
   /// Call this method after visiting the "then" part of an if statement, and
   /// before visiting the "else" part.
   void ifStatement_elseBegin();
@@ -501,20 +567,6 @@
 
   /// Call this method after visiting the condition part of an if statement.
   /// [condition] should be the if statement's condition.
-  ///
-  /// The order of visiting an if statement with no "else" part should be:
-  /// - Visit the condition
-  /// - Call [ifStatement_thenBegin]
-  /// - Visit the "then" statement
-  /// - Call [ifStatement_end], passing `false` for `hasElse`.
-  ///
-  /// The order of visiting an if statement with an "else" part should be:
-  /// - Visit the condition
-  /// - Call [ifStatement_thenBegin]
-  /// - Visit the "then" statement
-  /// - Call [ifStatement_elseBegin]
-  /// - Visit the "else" statement
-  /// - Call [ifStatement_end], passing `true` for `hasElse`.
   void ifStatement_thenBegin(Expression condition);
 
   /// Return whether the [variable] is definitely assigned in the current state.
@@ -549,6 +601,16 @@
   /// Call this method after visiting a labeled statement.
   void labeledStatement_end();
 
+  /// Call this method just before visiting the initializer of a late variable.
+  void lateInitializer_begin(Node node);
+
+  /// Call this method just after visiting the initializer of a late variable.
+  void lateInitializer_end();
+
+  /// Call this method before visiting the LHS of a logical binary operation
+  /// ("||" or "&&").
+  void logicalBinaryOp_begin();
+
   /// Call this method after visiting the RHS of a logical binary operation
   /// ("||" or "&&").
   /// [wholeExpression] should be the whole logical binary expression.
@@ -609,6 +671,11 @@
   void parenthesizedExpression(
       Expression outerExpression, Expression innerExpression);
 
+  /// Attempt to promote [variable] to [type].  The client may use this to
+  /// ensure that a variable declaration of the form `var x = expr;` promotes
+  /// `x` to type `X&T` in the circumstance where the type of `expr` is `X&T`.
+  void promote(Variable variable, Type type);
+
   /// Retrieves the type that the [variable] is promoted to, if the [variable]
   /// is currently promoted.  Otherwise returns `null`.
   Type promotedType(Variable variable);
@@ -749,7 +816,12 @@
 
   /// Register write of the given [variable] in the current state.
   /// [writtenType] should be the type of the value that was written.
-  void write(Variable variable, Type writtenType);
+  ///
+  /// This should also be used for the implicit write to a non-final variable in
+  /// its initializer, to ensure that the type is promoted to non-nullable if
+  /// necessary; in this case, [viaInitializer] should be `true`.
+  void write(Variable variable, Type writtenType,
+      {bool viaInitializer = false});
 }
 
 /// Alternate implementation of [FlowAnalysis] that prints out inputs and output
@@ -802,6 +874,12 @@
   }
 
   @override
+  void conditional_conditionBegin() {
+    _wrap('conditional_conditionBegin()',
+        () => _wrapped.conditional_conditionBegin());
+  }
+
+  @override
   void conditional_elseBegin(Expression thenExpression) {
     _wrap('conditional_elseBegin($thenExpression',
         () => _wrapped.conditional_elseBegin(thenExpression));
@@ -906,6 +984,12 @@
   }
 
   @override
+  void forwardExpression(Expression newExpression, Expression oldExpression) {
+    return _wrap('forwardExpression($newExpression, $oldExpression)',
+        () => _wrapped.forwardExpression(newExpression, oldExpression));
+  }
+
+  @override
   void functionExpression_begin(Node node) {
     _wrap('functionExpression_begin($node)',
         () => _wrapped.functionExpression_begin(node));
@@ -949,6 +1033,12 @@
   }
 
   @override
+  void ifStatement_conditionBegin() {
+    return _wrap('ifStatement_conditionBegin()',
+        () => _wrapped.ifStatement_conditionBegin());
+  }
+
+  @override
   void ifStatement_elseBegin() {
     return _wrap(
         'ifStatement_elseBegin()', () => _wrapped.ifStatement_elseBegin());
@@ -984,7 +1074,8 @@
 
   @override
   bool isUnassigned(Variable variable) {
-    return _wrap('isUnassigned($variable)', () => _wrapped.isAssigned(variable),
+    return _wrap(
+        'isUnassigned($variable)', () => _wrapped.isUnassigned(variable),
         isQuery: true);
   }
 
@@ -1001,6 +1092,22 @@
   }
 
   @override
+  void lateInitializer_begin(Node node) {
+    _wrap('lateInitializer_begin($node)',
+        () => _wrapped.lateInitializer_begin(node));
+  }
+
+  @override
+  void lateInitializer_end() {
+    _wrap('lateInitializer_end()', () => _wrapped.lateInitializer_end());
+  }
+
+  @override
+  void logicalBinaryOp_begin() {
+    _wrap('logicalBinaryOp_begin()', () => _wrapped.logicalBinaryOp_begin());
+  }
+
+  @override
   void logicalBinaryOp_end(Expression wholeExpression, Expression rightOperand,
       {@required bool isAnd}) {
     _wrap(
@@ -1055,6 +1162,11 @@
   }
 
   @override
+  void promote(Variable variable, Type type) {
+    _wrap('promote($variable, $type', () => _wrapped.promote(variable, type));
+  }
+
+  @override
   Type promotedType(Variable variable) {
     return _wrap(
         'promotedType($variable)', () => _wrapped.promotedType(variable),
@@ -1156,9 +1268,12 @@
   }
 
   @override
-  void write(Variable variable, Type writtenType) {
-    _wrap('write($variable, $writtenType)',
-        () => _wrapped.write(variable, writtenType));
+  void write(Variable variable, Type writtenType,
+      {bool viaInitializer = false}) {
+    _wrap(
+        'write($variable, $writtenType, viaInitializer: $viaInitializer)',
+        () => _wrapped.write(variable, writtenType,
+            viaInitializer: viaInitializer));
   }
 
   T _wrap<T>(String description, T callback(),
@@ -1192,8 +1307,7 @@
 /// the state actually leave `this` unchanged and return a new state object.
 @visibleForTesting
 class FlowModel<Variable, Type> {
-  /// Indicates whether this point in the control flow is reachable.
-  final bool reachable;
+  final Reachability reachable;
 
   /// For each variable being tracked by flow analysis, the variable's model.
   ///
@@ -1217,14 +1331,16 @@
   /// Creates a state object with the given [reachable] status.  All variables
   /// are assumed to be unpromoted and already assigned, so joining another
   /// state with this one will have no effect on it.
-  FlowModel(bool reachable)
-      : this._(
+  FlowModel(Reachability reachable)
+      : this.withInfo(
           reachable,
           const {},
         );
 
-  FlowModel._(this.reachable, this.variableInfo)
+  @visibleForTesting
+  FlowModel.withInfo(this.reachable, this.variableInfo)
       : _freshVariableInfo = new VariableModel.fresh() {
+    assert(reachable != null);
     assert(() {
       for (VariableModel<Variable, Type> value in variableInfo.values) {
         assert(value != null);
@@ -1285,7 +1401,7 @@
 
     FlowModel<Variable, Type> result = newVariableInfo == null
         ? this
-        : new FlowModel<Variable, Type>._(reachable, newVariableInfo);
+        : new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
 
     return result;
   }
@@ -1308,6 +1424,41 @@
   VariableModel<Variable, Type> infoFor(Variable variable) =>
       variableInfo[variable] ?? _freshVariableInfo;
 
+  /// Builds a [FlowModel] based on `this`, but extending the `tested` set to
+  /// include types from [other].  This is used at the bottom of certain kinds
+  /// of loops, to ensure that types tested within the body of the loop are
+  /// consistently treated as "of interest" in code that follows the loop,
+  /// regardless of the type of loop.
+  @visibleForTesting
+  FlowModel<Variable, Type> inheritTested(
+      TypeOperations<Variable, Type> typeOperations,
+      FlowModel<Variable, Type> other) {
+    Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
+        <Variable, VariableModel<Variable, Type>>{};
+    Map<Variable, VariableModel<Variable, Type>> otherVariableInfo =
+        other.variableInfo;
+    bool changed = false;
+    for (MapEntry<Variable, VariableModel<Variable, Type>> entry
+        in variableInfo.entries) {
+      Variable variable = entry.key;
+      VariableModel<Variable, Type> variableModel = entry.value;
+      VariableModel<Variable, Type> otherVariableModel =
+          otherVariableInfo[variable];
+      VariableModel<Variable, Type> newVariableModel =
+          otherVariableModel == null
+              ? variableModel
+              : VariableModel.inheritTested(
+                  typeOperations, variableModel, otherVariableModel.tested);
+      newVariableInfo[variable] = newVariableModel;
+      if (!identical(newVariableModel, variableModel)) changed = true;
+    }
+    if (changed) {
+      return new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
+    } else {
+      return this;
+    }
+  }
+
   /// Updates the state to indicate that variables that are not definitely
   /// unassigned in the [other], are also not definitely unassigned in the
   /// result.
@@ -1335,7 +1486,7 @@
 
     if (newVariableInfo == null) return this;
 
-    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
+    return new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
   }
 
   /// Updates the state to reflect a control path that is known to have
@@ -1362,7 +1513,8 @@
       TypeOperations<Variable, Type> typeOperations,
       FlowModel<Variable, Type> other,
       Set<Variable> unsafe) {
-    bool newReachable = reachable && other.reachable;
+    Reachability newReachable =
+        Reachability.restrict(reachable, other.reachable);
 
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         <Variable, VariableModel<Variable, Type>>{};
@@ -1404,14 +1556,19 @@
     return _identicalOrNew(this, other, newReachable, newVariableInfo);
   }
 
-  /// Updates the state to indicate whether the control flow path is
-  /// [reachable].
-  FlowModel<Variable, Type> setReachable(bool reachable) {
-    if (this.reachable == reachable) return this;
+  /// Updates the state to indicate that the control flow path is unreachable.
+  FlowModel<Variable, Type> setUnreachable() {
+    if (!reachable.locallyReachable) return this;
 
-    return new FlowModel<Variable, Type>._(reachable, variableInfo);
+    return new FlowModel<Variable, Type>.withInfo(
+        reachable.setUnreachable(), variableInfo);
   }
 
+  /// Returns a [FlowModel] indicating the result of creating a control flow
+  /// split.  See [Reachability.split] for more information.
+  FlowModel<Variable, Type> split() =>
+      new FlowModel<Variable, Type>.withInfo(reachable.split(), variableInfo);
+
   @override
   String toString() => '($reachable, $variableInfo)';
 
@@ -1507,9 +1664,17 @@
     }
 
     Type factoredType = typeOperations.factor(previousType, type);
-    Type typeIfFailed = typeOperations.isSameType(factoredType, previousType)
-        ? null
-        : factoredType;
+    Type typeIfFailed;
+    if (typeOperations.isNever(factoredType)) {
+      // Promoting to `Never` would mark the code as unreachable.  But it might
+      // be reachable due to mixed mode unsoundness.  So don't promote.
+      typeIfFailed = null;
+    } else if (typeOperations.isSameType(factoredType, previousType)) {
+      // No change to the type, so don't promote.
+      typeIfFailed = null;
+    } else {
+      typeIfFailed = factoredType;
+    }
     FlowModel<Variable, Type> modelIfFailed =
         _finishTypeTest(typeOperations, variable, info, type, typeIfFailed);
 
@@ -1517,6 +1682,22 @@
         this, modelIfSuccessful, modelIfFailed);
   }
 
+  /// Returns a [FlowModel] indicating the result of removing a control flow
+  /// split.  See [Reachability.unsplit] for more information.
+  FlowModel<Variable, Type> unsplit() =>
+      new FlowModel<Variable, Type>.withInfo(reachable.unsplit(), variableInfo);
+
+  /// Removes control flow splits until a [FlowModel] is obtained whose
+  /// reachability has the given [parent].
+  FlowModel<Variable, Type> unsplitTo(Reachability parent) {
+    if (identical(this.reachable.parent, parent)) return this;
+    Reachability reachable = this.reachable.unsplit();
+    while (!identical(reachable.parent, parent)) {
+      reachable = reachable.unsplit();
+    }
+    return new FlowModel<Variable, Type>.withInfo(reachable, variableInfo);
+  }
+
   /// Updates the state to indicate that an assignment was made to the given
   /// [variable].  The variable is marked as definitely assigned, and any
   /// previous type promotion is removed.
@@ -1557,12 +1738,12 @@
     }
 
     List<Type> newPromotedTypes = info.promotedTypes;
-    bool newReachable = reachable;
+    Reachability newReachable = reachable;
     if (promotedType != null) {
       newPromotedTypes =
           VariableModel._addToPromotedTypes(info.promotedTypes, promotedType);
       if (typeOperations.isNever(promotedType)) {
-        newReachable = false;
+        newReachable = reachable.setUnreachable();
       }
     }
 
@@ -1581,12 +1762,12 @@
   /// with [model].
   FlowModel<Variable, Type> _updateVariableInfo(
       Variable variable, VariableModel<Variable, Type> model,
-      {bool reachable}) {
+      {Reachability reachable}) {
     reachable ??= this.reachable;
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         new Map<Variable, VariableModel<Variable, Type>>.from(variableInfo);
     newVariableInfo[variable] = model;
-    return new FlowModel<Variable, Type>._(reachable, newVariableInfo);
+    return new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
   }
 
   /// Forms a new state to reflect a control flow path that might have come from
@@ -1607,10 +1788,18 @@
     if (first == null) return second;
     if (second == null) return first;
 
-    if (first.reachable && !second.reachable) return first;
-    if (!first.reachable && second.reachable) return second;
+    assert(identical(first.reachable.parent, second.reachable.parent));
+    if (first.reachable.locallyReachable &&
+        !second.reachable.locallyReachable) {
+      return first;
+    }
+    if (!first.reachable.locallyReachable &&
+        second.reachable.locallyReachable) {
+      return second;
+    }
 
-    bool newReachable = first.reachable || second.reachable;
+    Reachability newReachable =
+        Reachability.join(first.reachable, second.reachable);
     Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
         FlowModel.joinVariableInfo(typeOperations, first.variableInfo,
             second.variableInfo, emptyVariableMap);
@@ -1659,12 +1848,43 @@
     return result;
   }
 
+  /// Models the result of joining the flow models [first] and [second] at the
+  /// merge of two control flow paths.
+  static FlowModel<Variable, Type> merge<Variable, Type>(
+    TypeOperations<Variable, Type> typeOperations,
+    FlowModel<Variable, Type> first,
+    FlowModel<Variable, Type> second,
+    Map<Variable, VariableModel<Variable, Type>> emptyVariableMap,
+  ) {
+    if (first == null) return second.unsplit();
+    if (second == null) return first.unsplit();
+
+    assert(identical(first.reachable.parent, second.reachable.parent));
+    if (first.reachable.locallyReachable &&
+        !second.reachable.locallyReachable) {
+      return first.unsplit();
+    }
+    if (!first.reachable.locallyReachable &&
+        second.reachable.locallyReachable) {
+      return second.unsplit();
+    }
+
+    Reachability newReachable =
+        Reachability.join(first.reachable, second.reachable).unsplit();
+    Map<Variable, VariableModel<Variable, Type>> newVariableInfo =
+        FlowModel.joinVariableInfo(typeOperations, first.variableInfo,
+            second.variableInfo, emptyVariableMap);
+
+    return FlowModel._identicalOrNew(
+        first, second, newReachable, newVariableInfo);
+  }
+
   /// Creates a new [FlowModel] object, unless it is equivalent to either
   /// [first] or [second], in which case one of those objects is re-used.
   static FlowModel<Variable, Type> _identicalOrNew<Variable, Type>(
       FlowModel<Variable, Type> first,
       FlowModel<Variable, Type> second,
-      bool newReachable,
+      Reachability newReachable,
       Map<Variable, VariableModel<Variable, Type>> newVariableInfo) {
     if (first.reachable == newReachable &&
         identical(first.variableInfo, newVariableInfo)) {
@@ -1675,7 +1895,8 @@
       return second;
     }
 
-    return new FlowModel<Variable, Type>._(newReachable, newVariableInfo);
+    return new FlowModel<Variable, Type>.withInfo(
+        newReachable, newVariableInfo);
   }
 
   /// Determines whether the given "variableInfo" maps are equivalent.
@@ -1699,6 +1920,101 @@
   }
 }
 
+/// Immutable data structure modeling the reachability of the given point in the
+/// source code.  Reachability is tracked relative to checkpoints occurring
+/// previously along the control flow path leading up to the current point in
+/// the program.  A given point is said to be "locally reachable" if it is
+/// reachable from the most recent checkpoint, and "overall reachable" if it is
+/// reachable from the top of the function.
+@visibleForTesting
+class Reachability {
+  /// Model of the initial reachability state of the function being analyzed.
+  static const Reachability initial = const Reachability._initial();
+
+  /// Reachability of the checkpoint this reachability is relative to, or `null`
+  /// if there is no checkpoint.  Reachabilities form a tree structure that
+  /// mimics the control flow of the code being analyzed, so this is called the
+  /// "parent".
+  final Reachability parent;
+
+  /// Whether this point in the source code is considered reachable from the
+  /// most recent checkpoint.
+  final bool locallyReachable;
+
+  /// Whether this point in the source code is considered reachable from the
+  /// beginning of the function being analyzed.
+  final bool overallReachable;
+
+  Reachability._(this.parent, this.locallyReachable, this.overallReachable) {
+    assert(overallReachable ==
+        (locallyReachable && (parent?.overallReachable ?? true)));
+  }
+
+  const Reachability._initial()
+      : parent = null,
+        locallyReachable = true,
+        overallReachable = true;
+
+  /// Returns a reachability with the same checkpoint as `this`, but where the
+  /// current point in the program is considered locally unreachable.
+  Reachability setUnreachable() {
+    if (!locallyReachable) return this;
+    return new Reachability._(parent, false, false);
+  }
+
+  /// Returns a new reachability whose checkpoint is the current point of
+  /// execution.  This models flow control within a control flow split, e.g.
+  /// inside an `if` statement.
+  Reachability split() => new Reachability._(this, true, overallReachable);
+
+  @override
+  String toString() {
+    List<bool> values = [];
+    for (Reachability node = this; node != null; node = node.parent) {
+      values.add(node.locallyReachable);
+    }
+    return '[${values.join(', ')}]';
+  }
+
+  /// Returns a reachability that drops the most recent checkpoint but maintains
+  /// the same notion of reachability relative to the previous two checkpoints.
+  Reachability unsplit() {
+    if (locallyReachable) {
+      return parent;
+    } else {
+      return parent.setUnreachable();
+    }
+  }
+
+  /// Combines two reachabilities (both of which must be based on the same
+  /// checkpoint), where the code is considered reachable from the checkpoint
+  /// iff either argument is reachable from the checkpoint.
+  ///
+  /// This is used as part of the "join" operation.
+  static Reachability join(Reachability r1, Reachability r2) {
+    assert(identical(r1.parent, r2.parent));
+    if (r2.locallyReachable) {
+      return r2;
+    } else {
+      return r1;
+    }
+  }
+
+  /// Combines two reachabilities (both of which must be based on the same
+  /// checkpoint), where the code is considered reachable from the checkpoint
+  /// iff both arguments are reachable from the checkpoint.
+  ///
+  /// This is used as part of the "restrict" operation.
+  static Reachability restrict(Reachability r1, Reachability r2) {
+    assert(identical(r1.parent, r2.parent));
+    if (r2.locallyReachable) {
+      return r1;
+    } else {
+      return r2;
+    }
+  }
+}
+
 /// Enum representing the different classifications of types that can be
 /// returned by [TypeOperations.classifyType].
 enum TypeClassification {
@@ -1733,11 +2049,6 @@
           List<Type> newPromotedTypes) =>
       false;
 
-  /// Return `true` if the [variable] is a local variable (not a formal
-  /// parameter), and it has no declared type (no explicit type, and not
-  /// initializer).
-  bool isLocalVariableWithoutDeclaredType(Variable variable);
-
   /// Determines whether the given [type] is equivalent to the `Never` type.
   ///
   /// A type is equivalent to `Never` if it:
@@ -1948,11 +2259,6 @@
           promotedTypes, tested, true, false, writeCaptured);
     }
 
-    if (_isPromotableViaInitialization(typeOperations, variable)) {
-      return new VariableModel<Variable, Type>(
-          [writtenType], tested, true, false, writeCaptured);
-    }
-
     List<Type> newPromotedTypes = _demoteViaAssignment(
       writtenType,
       typeOperations,
@@ -2004,26 +2310,6 @@
     }
   }
 
-  /// We say that a variable `x` is promotable via initialization given
-  /// variable model `VM` if `x` is a local variable (not a formal parameter)
-  /// and:
-  /// * VM = VariableModel(declared, promoted, tested,
-  ///                      assigned, unassigned, captured)
-  /// * and `captured` is false
-  /// * and `promoted` is empty
-  /// * and `x` is declared with no explicit type and no initializer
-  /// * and `assigned` is false and `unassigned` is true
-  bool _isPromotableViaInitialization<Variable>(
-    TypeOperations<Variable, Type> typeOperations,
-    Variable variable,
-  ) {
-    return !writeCaptured &&
-        !assigned &&
-        unassigned &&
-        promotedTypes == null &&
-        typeOperations.isLocalVariableWithoutDeclaredType(variable);
-  }
-
   /// Determines whether a variable with the given [promotedTypes] should be
   /// promoted to [writtenType] based on types of interest.  If it should,
   /// returns an updated promotion chain; otherwise returns [promotedTypes]
@@ -2139,6 +2425,22 @@
     return promotedTypes;
   }
 
+  /// Builds a [VariableModel] based on [model], but extending the [tested] set
+  /// to include types from [tested].  This is used at the bottom of certain
+  /// kinds of loops, to ensure that types tested within the body of the loop
+  /// are consistently treated as "of interest" in code that follows the loop,
+  /// regardless of the type of loop.
+  @visibleForTesting
+  static VariableModel<Variable, Type> inheritTested<Variable, Type>(
+      TypeOperations<Variable, Type> typeOperations,
+      VariableModel<Variable, Type> model,
+      List<Type> tested) {
+    List<Type> newTested = joinTested(tested, model.tested, typeOperations);
+    if (identical(newTested, model.tested)) return model;
+    return new VariableModel<Variable, Type>(model.promotedTypes, newTested,
+        model.assigned, model.unassigned, model.writeCaptured);
+  }
+
   /// Joins two variable models.  See [FlowModel.join] for details.
   static VariableModel<Variable, Type> join<Variable, Type>(
       TypeOperations<Variable, Type> typeOperations,
@@ -2323,9 +2625,17 @@
   /// `null` if no `continue` statements have been seen yet.
   FlowModel<Variable, Type> _continueModel;
 
+  /// The reachability checkpoint associated with this loop or switch statement.
+  /// When analyzing deeply nested `break` and `continue` statements, their flow
+  /// models need to be unsplit to this point before joining them to the control
+  /// flow paths for the loop or switch.
+  final Reachability _checkpoint;
+
+  _BranchTargetContext(this._checkpoint);
+
   @override
   String toString() => '_BranchTargetContext(breakModel: $_breakModel, '
-      'continueModel: $_continueModel)';
+      'continueModel: $_continueModel, checkpoint: $_checkpoint)';
 }
 
 /// [_FlowContext] representing a conditional expression.
@@ -2389,11 +2699,11 @@
   final AssignedVariables<Node, Variable> _assignedVariables;
 
   _FlowAnalysisImpl(this.typeOperations, this._assignedVariables) {
-    _current = new FlowModel<Variable, Type>(true);
+    _current = new FlowModel<Variable, Type>(Reachability.initial);
   }
 
   @override
-  bool get isReachable => _current.reachable;
+  bool get isReachable => _current.reachable.overallReachable;
 
   @override
   void asExpression_end(Expression subExpression, Type type) {
@@ -2419,6 +2729,7 @@
 
   @override
   void assert_begin() {
+    _current = _current.split();
     _stack.add(new _AssertContext<Variable, Type>(_current));
   }
 
@@ -2426,12 +2737,12 @@
   void assert_end() {
     _AssertContext<Variable, Type> context =
         _stack.removeLast() as _AssertContext<Variable, Type>;
-    _current = _join(context._previous, context._conditionInfo.ifTrue);
+    _current = _merge(context._previous, context._conditionInfo.ifTrue);
   }
 
   @override
   void booleanLiteral(Expression expression, bool value) {
-    FlowModel<Variable, Type> unreachable = _current.setReachable(false);
+    FlowModel<Variable, Type> unreachable = _current.setUnreachable();
     _storeExpressionInfo(
         expression,
         value
@@ -2440,6 +2751,11 @@
   }
 
   @override
+  void conditional_conditionBegin() {
+    _current = _current.split();
+  }
+
+  @override
   void conditional_elseBegin(Expression thenExpression) {
     _ConditionalContext<Variable, Type> context =
         _stack.last as _ConditionalContext<Variable, Type>;
@@ -2457,9 +2773,9 @@
     _storeExpressionInfo(
         conditionalExpression,
         new ExpressionInfo(
-            _join(thenInfo.after, elseInfo.after),
-            _join(thenInfo.ifTrue, elseInfo.ifTrue),
-            _join(thenInfo.ifFalse, elseInfo.ifFalse)));
+            _merge(thenInfo.after, elseInfo.after),
+            _merge(thenInfo.ifTrue, elseInfo.ifTrue),
+            _merge(thenInfo.ifFalse, elseInfo.ifFalse)));
   }
 
   @override
@@ -2479,9 +2795,9 @@
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(doStatement);
     _BranchTargetContext<Variable, Type> context =
-        new _BranchTargetContext<Variable, Type>();
+        new _BranchTargetContext<Variable, Type>(_current.reachable);
     _stack.add(context);
-    _current = _current.conservativeJoin(info._written, info._captured);
+    _current = _current.conservativeJoin(info._written, info._captured).split();
     _statementToContext[doStatement] = context;
   }
 
@@ -2496,7 +2812,7 @@
   void doStatement_end(Expression condition) {
     _BranchTargetContext<Variable, Type> context =
         _stack.removeLast() as _BranchTargetContext<Variable, Type>;
-    _current = _join(_expressionEnd(condition).ifFalse, context._breakModel);
+    _current = _merge(_expressionEnd(condition).ifFalse, context._breakModel);
   }
 
   @override
@@ -2523,8 +2839,11 @@
         (rightOperandTypeClassification ==
                 TypeClassification.nullOrEquivalent &&
             leftOperandTypeClassification == TypeClassification.nonNullable)) {
-      booleanLiteral(wholeExpression, notEqual);
-      return false;
+      // In strong mode the test is guaranteed to produce a "not equal" result,
+      // but weak mode it might produce an "equal" result.  We don't want flow
+      // analysis behavior to depend on mode, so we conservatively assume that
+      // either result is possible.
+      return true;
     } else if (lhsInfo is _NullInfo<Variable, Type> &&
         rhsInfo is _VariableReadInfo<Variable, Type>) {
       assert(
@@ -2540,7 +2859,7 @@
     }
     _storeExpressionInfo(wholeExpression,
         notEqual ? equalityInfo : ExpressionInfo.invert(equalityInfo));
-    return equalityInfo.ifFalse.reachable;
+    return true;
   }
 
   @override
@@ -2552,15 +2871,16 @@
   @override
   void finish() {
     assert(_stack.isEmpty);
+    assert(_current.reachable.parent == null);
   }
 
   @override
   void for_bodyBegin(Statement node, Expression condition) {
     ExpressionInfo<Variable, Type> conditionInfo = condition == null
-        ? new ExpressionInfo(_current, _current, _current.setReachable(false))
+        ? new ExpressionInfo(_current, _current, _current.setUnreachable())
         : _expressionEnd(condition);
-    _WhileContext<Variable, Type> context =
-        new _WhileContext<Variable, Type>(conditionInfo);
+    _WhileContext<Variable, Type> context = new _WhileContext<Variable, Type>(
+        _current.reachable.parent, conditionInfo);
     _stack.add(context);
     if (node != null) {
       _statementToContext[node] = context;
@@ -2572,7 +2892,7 @@
   void for_conditionBegin(Node node) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(node);
-    _current = _current.conservativeJoin(info._written, info._captured);
+    _current = _current.conservativeJoin(info._written, info._captured).split();
   }
 
   @override
@@ -2583,7 +2903,8 @@
     FlowModel<Variable, Type> breakState = context._breakModel;
     FlowModel<Variable, Type> falseCondition = context._conditionInfo.ifFalse;
 
-    _current = _join(falseCondition, breakState);
+    _current = _merge(falseCondition, breakState)
+        .inheritTested(typeOperations, _current);
   }
 
   @override
@@ -2597,10 +2918,11 @@
   void forEach_bodyBegin(Node node, Variable loopVariable, Type writtenType) {
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(node);
+    _current = _current.conservativeJoin(info._written, info._captured).split();
     _SimpleStatementContext<Variable, Type> context =
-        new _SimpleStatementContext<Variable, Type>(_current);
+        new _SimpleStatementContext<Variable, Type>(
+            _current.reachable.parent, _current);
     _stack.add(context);
-    _current = _current.conservativeJoin(info._written, info._captured);
     if (loopVariable != null) {
       _current = _current.write(loopVariable, writtenType, typeOperations);
     }
@@ -2610,7 +2932,14 @@
   void forEach_end() {
     _SimpleStatementContext<Variable, Type> context =
         _stack.removeLast() as _SimpleStatementContext<Variable, Type>;
-    _current = _join(_current, context._previous);
+    _current = _merge(_current, context._previous);
+  }
+
+  @override
+  void forwardExpression(Expression newExpression, Expression oldExpression) {
+    if (identical(_expressionWithInfo, oldExpression)) {
+      _expressionWithInfo = newExpression;
+    }
   }
 
   @override
@@ -2619,7 +2948,7 @@
         _assignedVariables._getInfoForNode(node);
     ++_functionNestingLevel;
     _current = _current.conservativeJoin(const [], info._written);
-    _stack.add(new _SimpleContext(_current));
+    _stack.add(new _FunctionExpressionContext(_current));
     _current = _current.conservativeJoin(_assignedVariables._anywhere._written,
         _assignedVariables._anywhere._captured);
   }
@@ -2628,41 +2957,44 @@
   void functionExpression_end() {
     --_functionNestingLevel;
     assert(_functionNestingLevel >= 0);
-    FlowModel<Variable, Type> afterBody = _current;
     _SimpleContext<Variable, Type> context =
-        _stack.removeLast() as _SimpleContext<Variable, Type>;
+        _stack.removeLast() as _FunctionExpressionContext<Variable, Type>;
     _current = context._previous;
-    _current = _current.joinUnassigned(afterBody);
   }
 
   @override
   void handleBreak(Statement target) {
     _BranchTargetContext<Variable, Type> context = _statementToContext[target];
     if (context != null) {
-      context._breakModel = _join(context._breakModel, _current);
+      context._breakModel =
+          _join(context._breakModel, _current.unsplitTo(context._checkpoint));
     }
-    _current = _current.setReachable(false);
+    _current = _current.setUnreachable();
   }
 
   @override
   void handleContinue(Statement target) {
     _BranchTargetContext<Variable, Type> context = _statementToContext[target];
     if (context != null) {
-      context._continueModel = _join(context._continueModel, _current);
+      context._continueModel = _join(
+          context._continueModel, _current.unsplitTo(context._checkpoint));
     }
-    _current = _current.setReachable(false);
+    _current = _current.setUnreachable();
   }
 
   @override
   void handleExit() {
-    _current = _current.setReachable(false);
+    _current = _current.setUnreachable();
   }
 
   @override
   void ifNullExpression_end() {
+    // TODO(paulberry): CFE sometimes calls ifNullExpression_end and
+    // nullAwareAccess_end out of order, so as a workaround we cast to the
+    // common base class.  See https://github.com/dart-lang/sdk/issues/43725.
     _SimpleContext<Variable, Type> context =
         _stack.removeLast() as _SimpleContext<Variable, Type>;
-    _current = _join(_current, context._previous);
+    _current = _merge(_current, context._previous);
   }
 
   @override
@@ -2670,6 +3002,7 @@
       Expression leftHandSide, Type leftHandSideType) {
     ExpressionInfo<Variable, Type> lhsInfo = _getExpressionInfo(leftHandSide);
     FlowModel<Variable, Type> promoted;
+    _current = _current.split();
     if (lhsInfo is _VariableReadInfo<Variable, Type>) {
       ExpressionInfo<Variable, Type> promotionInfo =
           _current.tryMarkNonNullable(typeOperations, lhsInfo._variable);
@@ -2678,12 +3011,13 @@
     } else {
       promoted = _current;
     }
-    if (typeOperations.classifyType(leftHandSideType) ==
-        TypeClassification.nonNullable) {
-      _current = _current.setReachable(false);
-    }
-    _stack.add(new _SimpleContext<Variable, Type>(promoted));
-    return _current.reachable;
+    _stack.add(new _IfNullExpressionContext<Variable, Type>(promoted));
+    return true;
+  }
+
+  @override
+  void ifStatement_conditionBegin() {
+    _current = _current.split();
   }
 
   @override
@@ -2707,7 +3041,7 @@
       afterThen = _current; // no `else`, so `then` is still current
       afterElse = context._conditionInfo.ifFalse;
     }
-    _current = _join(afterThen, afterElse);
+    _current = _merge(afterThen, afterElse);
   }
 
   @override
@@ -2737,7 +3071,7 @@
         _current.tryPromoteForTypeCheck(typeOperations, variable, type);
     _storeExpressionInfo(isExpression,
         isNot ? ExpressionInfo.invert(expressionInfo) : expressionInfo);
-    return expressionInfo.ifFalse.reachable;
+    return true;
   }
 
   @override
@@ -2747,8 +3081,9 @@
 
   @override
   void labeledStatement_begin(Node node) {
+    _current = _current.split();
     _BranchTargetContext<Variable, Type> context =
-        new _BranchTargetContext<Variable, Type>();
+        new _BranchTargetContext<Variable, Type>(_current.reachable.parent);
     _stack.add(context);
     _statementToContext[node] = context;
   }
@@ -2757,7 +3092,32 @@
   void labeledStatement_end() {
     _BranchTargetContext<Variable, Type> context =
         _stack.removeLast() as _BranchTargetContext<Variable, Type>;
-    _current = _join(_current, context._breakModel);
+    _current = _merge(_current, context._breakModel);
+  }
+
+  @override
+  void lateInitializer_begin(Node node) {
+    // Late initializers are treated the same as function expressions.
+    // Essentially we act as though `late x = expr;` is syntactic sugar for
+    // `late x = LAZY_MAGIC(() => expr);` (where `LAZY_MAGIC` creates a lazy
+    // evaluation thunk that gets replaced by the result of `expr` once it is
+    // evaluated).
+    functionExpression_begin(node);
+  }
+
+  @override
+  void lateInitializer_end() {
+    // Late initializers are treated the same as function expressions.
+    // Essentially we act as though `late x = expr;` is syntactic sugar for
+    // `late x = LAZY_MAGIC(() => expr);` (where `LAZY_MAGIC` creates a lazy
+    // evaluation thunk that gets replaced by the result of `expr` once it is
+    // evaluated).
+    functionExpression_end();
+  }
+
+  @override
+  void logicalBinaryOp_begin() {
+    _current = _current.split();
   }
 
   @override
@@ -2778,8 +3138,8 @@
     }
     _storeExpressionInfo(
         wholeExpression,
-        new ExpressionInfo(
-            _join(trueResult, falseResult), trueResult, falseResult));
+        new ExpressionInfo(_merge(trueResult, falseResult),
+            trueResult.unsplit(), falseResult.unsplit()));
   }
 
   @override
@@ -2808,22 +3168,19 @@
 
   @override
   void nullAwareAccess_end() {
+    // TODO(paulberry): CFE sometimes calls ifNullExpression_end and
+    // nullAwareAccess_end out of order, so as a workaround we cast to the
+    // common base class.  See https://github.com/dart-lang/sdk/issues/43725.
     _SimpleContext<Variable, Type> context =
         _stack.removeLast() as _SimpleContext<Variable, Type>;
-    _current = _join(_current, context._previous);
+    _current = _merge(_current, context._previous);
   }
 
   @override
   bool nullAwareAccess_rightBegin(Expression target, Type targetType) {
     assert(targetType != null);
-    bool shortingIsReachable = true;
-    FlowModel<Variable, Type> shortingModel = _current;
-    if (typeOperations.classifyType(targetType) ==
-        TypeClassification.nonNullable) {
-      shortingModel = shortingModel.setReachable(false);
-      shortingIsReachable = false;
-    }
-    _stack.add(new _SimpleContext<Variable, Type>(shortingModel));
+    _current = _current.split();
+    _stack.add(new _NullAwareAccessContext<Variable, Type>(_current));
     if (target != null) {
       ExpressionInfo<Variable, Type> targetInfo = _getExpressionInfo(target);
       if (targetInfo is _VariableReadInfo<Variable, Type>) {
@@ -2832,7 +3189,7 @@
             .ifTrue;
       }
     }
-    return shortingIsReachable;
+    return true;
   }
 
   @override
@@ -2843,9 +3200,13 @@
   @override
   void parenthesizedExpression(
       Expression outerExpression, Expression innerExpression) {
-    if (identical(_expressionWithInfo, innerExpression)) {
-      _expressionWithInfo = outerExpression;
-    }
+    forwardExpression(outerExpression, innerExpression);
+  }
+
+  @override
+  void promote(Variable variable, Type type) {
+    _current =
+        _current.tryPromoteForTypeCheck(typeOperations, variable, type).ifTrue;
   }
 
   @override
@@ -2880,19 +3241,22 @@
     // And, if there is an implicit fall-through default, join it to any breaks.
     if (!isExhaustive) breakState = _join(breakState, context._previous);
 
-    _current = breakState;
+    _current = breakState.unsplit();
   }
 
   @override
   void switchStatement_expressionEnd(Statement switchStatement) {
+    _current = _current.split();
     _SimpleStatementContext<Variable, Type> context =
-        new _SimpleStatementContext<Variable, Type>(_current);
+        new _SimpleStatementContext<Variable, Type>(
+            _current.reachable.parent, _current);
     _stack.add(context);
     _statementToContext[switchStatement] = context;
   }
 
   @override
   void tryCatchStatement_bodyBegin() {
+    _current = _current.split();
     _stack.add(new _TryContext<Variable, Type>(_current));
   }
 
@@ -2939,7 +3303,7 @@
   void tryCatchStatement_end() {
     _TryContext<Variable, Type> context =
         _stack.removeLast() as _TryContext<Variable, Type>;
-    _current = context._afterBodyAndCatches;
+    _current = context._afterBodyAndCatches.unsplit();
   }
 
   @override
@@ -2978,8 +3342,8 @@
   void whileStatement_bodyBegin(
       Statement whileStatement, Expression condition) {
     ExpressionInfo<Variable, Type> conditionInfo = _expressionEnd(condition);
-    _WhileContext<Variable, Type> context =
-        new _WhileContext<Variable, Type>(conditionInfo);
+    _WhileContext<Variable, Type> context = new _WhileContext<Variable, Type>(
+        _current.reachable.parent, conditionInfo);
     _stack.add(context);
     _statementToContext[whileStatement] = context;
     _current = conditionInfo.ifTrue;
@@ -2987,6 +3351,7 @@
 
   @override
   void whileStatement_conditionBegin(Node node) {
+    _current = _current.split();
     AssignedVariablesNodeInfo<Variable> info =
         _assignedVariables._getInfoForNode(node);
     _current = _current.conservativeJoin(info._written, info._captured);
@@ -2996,15 +3361,19 @@
   void whileStatement_end() {
     _WhileContext<Variable, Type> context =
         _stack.removeLast() as _WhileContext<Variable, Type>;
-    _current = _join(context._conditionInfo.ifFalse, context._breakModel);
+    _current = _merge(context._conditionInfo.ifFalse, context._breakModel)
+        .inheritTested(typeOperations, _current);
   }
 
   @override
-  void write(Variable variable, Type writtenType) {
-    assert(
-        _assignedVariables._anywhere._written.contains(variable),
-        "Variable is written to, but was not included in "
-        "_variablesWrittenAnywhere: $variable");
+  void write(Variable variable, Type writtenType,
+      {bool viaInitializer = false}) {
+    if (!viaInitializer) {
+      assert(
+          _assignedVariables._anywhere._written.contains(variable),
+          "Variable is written to, but was not included in "
+          "_variablesWrittenAnywhere: $variable");
+    }
     _current = _current.write(variable, writtenType, typeOperations);
   }
 
@@ -3044,6 +3413,11 @@
           FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
       FlowModel.join(typeOperations, first, second, _current._emptyVariableMap);
 
+  FlowModel<Variable, Type> _merge(
+          FlowModel<Variable, Type> first, FlowModel<Variable, Type> second) =>
+      FlowModel.merge(
+          typeOperations, first, second, _current._emptyVariableMap);
+
   /// Associates [expression], which should be the most recently visited
   /// expression, with the given [expressionInfo] object, and updates the
   /// current flow model state to correspond to it.
@@ -3059,6 +3433,16 @@
 /// language for which flow analysis information needs to be tracked.
 abstract class _FlowContext {}
 
+/// [_FlowContext] representing a function expression.
+class _FunctionExpressionContext<Variable, Type>
+    extends _SimpleContext<Variable, Type> {
+  _FunctionExpressionContext(FlowModel<Variable, Type> previous)
+      : super(previous);
+
+  @override
+  String toString() => '_FunctionExpressionContext(previous: $_previous)';
+}
+
 /// [_FlowContext] representing an `if` statement.
 class _IfContext<Variable, Type> extends _BranchContext<Variable, Type> {
   /// Flow model associated with the state of program execution after the `if`
@@ -3073,6 +3457,25 @@
       '_IfContext(conditionInfo: $_conditionInfo, afterThen: $_afterThen)';
 }
 
+/// [_FlowContext] representing an "if-null" (`??`) expression.
+class _IfNullExpressionContext<Variable, Type>
+    extends _SimpleContext<Variable, Type> {
+  _IfNullExpressionContext(FlowModel<Variable, Type> previous)
+      : super(previous);
+
+  @override
+  String toString() => '_IfNullExpressionContext(previous: $_previous)';
+}
+
+/// [_FlowContext] representing a null aware access (`?.`).
+class _NullAwareAccessContext<Variable, Type>
+    extends _SimpleContext<Variable, Type> {
+  _NullAwareAccessContext(FlowModel<Variable, Type> previous) : super(previous);
+
+  @override
+  String toString() => '_NullAwareAccessContext(previous: $_previous)';
+}
+
 /// [ExpressionInfo] representing a `null` literal.
 class _NullInfo<Variable, Type> implements ExpressionInfo<Variable, Type> {
   @override
@@ -3090,7 +3493,7 @@
 /// [_FlowContext] representing a language construct for which flow analysis
 /// must store a flow model state to be retrieved later, such as a `try`
 /// statement, function expression, or "if-null" (`??`) expression.
-class _SimpleContext<Variable, Type> extends _FlowContext {
+abstract class _SimpleContext<Variable, Type> extends _FlowContext {
   /// The stored state.  For a `try` statement, this is the state from the
   /// beginning of the `try` block.  For a function expression, this is the
   /// state at the point the function expression was created.  For an "if-null"
@@ -3099,9 +3502,6 @@
   final FlowModel<Variable, Type> _previous;
 
   _SimpleContext(this._previous);
-
-  @override
-  String toString() => '_SimpleContext(previous: $_previous)';
 }
 
 /// [_FlowContext] representing a language construct that can be targeted by
@@ -3115,11 +3515,13 @@
   /// after evaluation of the switch expression.
   final FlowModel<Variable, Type> _previous;
 
-  _SimpleStatementContext(this._previous);
+  _SimpleStatementContext(Reachability checkpoint, this._previous)
+      : super(checkpoint);
 
   @override
   String toString() => '_SimpleStatementContext(breakModel: $_breakModel, '
-      'continueModel: $_continueModel, previous: $_previous)';
+      'continueModel: $_continueModel, previous: $_previous, '
+      'checkpoint: $_checkpoint)';
 }
 
 /// [_FlowContext] representing a try statement.
@@ -3172,9 +3574,11 @@
   /// Flow models associated with the loop condition.
   final ExpressionInfo<Variable, Type> _conditionInfo;
 
-  _WhileContext(this._conditionInfo);
+  _WhileContext(Reachability checkpoint, this._conditionInfo)
+      : super(checkpoint);
 
   @override
   String toString() => '_WhileContext(breakModel: $_breakModel, '
-      'continueModel: $_continueModel, conditionInfo: $_conditionInfo)';
+      'continueModel: $_continueModel, conditionInfo: $_conditionInfo, '
+      'checkpoint: $_checkpoint)';
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index afd418a..a7d67b8 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -295,6 +295,36 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
+        String string,
+        String
+            string2)> templateBinaryOperatorWrittenOut = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Binary operator '#string' is written as '#string2' instead of the written out word.""",
+    tipTemplate: r"""Try replacing '#string' with '#string2'.""",
+    withArguments: _withArgumentsBinaryOperatorWrittenOut);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeBinaryOperatorWrittenOut =
+    const Code<Message Function(String string, String string2)>(
+        "BinaryOperatorWrittenOut", templateBinaryOperatorWrittenOut,
+        index: 112);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBinaryOperatorWrittenOut(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeBinaryOperatorWrittenOut,
+      message:
+          """Binary operator '${string}' is written as '${string2}' instead of the written out word.""",
+      tip: """Try replacing '${string}' with '${string2}'.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
         String name,
         String
             name2)> templateBoundIssueViaCycleNonSimplicity = const Template<
@@ -657,7 +687,7 @@
     templateCantInferReturnTypeDueToInconsistentOverrides =
     const Template<Message Function(String name)>(
         messageTemplate:
-            r"""Can't infer a return type for '#name' as some of the inherited members have different types.""",
+            r"""Can't infer a return type for '#name' as some of the overridden members have different types.""",
         tipTemplate: r"""Try adding an explicit type.""",
         withArguments:
             _withArgumentsCantInferReturnTypeDueToInconsistentOverrides);
@@ -677,7 +707,38 @@
   name = demangleMixinApplicationName(name);
   return new Message(codeCantInferReturnTypeDueToInconsistentOverrides,
       message:
-          """Can't infer a return type for '${name}' as some of the inherited members have different types.""",
+          """Can't infer a return type for '${name}' as some of the overridden members have different types.""",
+      tip: """Try adding an explicit type.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateCantInferReturnTypeDueToNoCombinedSignature =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Can't infer a return type for '#name' as the overridden members don't have a combined signature.""",
+        tipTemplate: r"""Try adding an explicit type.""",
+        withArguments:
+            _withArgumentsCantInferReturnTypeDueToNoCombinedSignature);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeCantInferReturnTypeDueToNoCombinedSignature =
+    const Code<Message Function(String name)>(
+        "CantInferReturnTypeDueToNoCombinedSignature",
+        templateCantInferReturnTypeDueToNoCombinedSignature,
+        analyzerCodes: <String>[
+      "COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCantInferReturnTypeDueToNoCombinedSignature(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCantInferReturnTypeDueToNoCombinedSignature,
+      message:
+          """Can't infer a return type for '${name}' as the overridden members don't have a combined signature.""",
       tip: """Try adding an explicit type.""",
       arguments: {'name': name});
 }
@@ -714,7 +775,7 @@
     templateCantInferTypeDueToInconsistentOverrides =
     const Template<Message Function(String name)>(
         messageTemplate:
-            r"""Can't infer a type for '#name' as some of the inherited members have different types.""",
+            r"""Can't infer a type for '#name' as some of the overridden members have different types.""",
         tipTemplate: r"""Try adding an explicit type.""",
         withArguments: _withArgumentsCantInferTypeDueToInconsistentOverrides);
 
@@ -732,7 +793,39 @@
   name = demangleMixinApplicationName(name);
   return new Message(codeCantInferTypeDueToInconsistentOverrides,
       message:
-          """Can't infer a type for '${name}' as some of the inherited members have different types.""",
+          """Can't infer a type for '${name}' as some of the overridden members have different types.""",
+      tip: """Try adding an explicit type.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateCantInferTypeDueToNoCombinedSignature = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Can't infer a type for '#name' as the overridden members don't have a combined signature.""",
+    tipTemplate: r"""Try adding an explicit type.""",
+    withArguments: _withArgumentsCantInferTypeDueToNoCombinedSignature);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeCantInferTypeDueToNoCombinedSignature =
+    const Code<Message Function(String name)>(
+        "CantInferTypeDueToNoCombinedSignature",
+        templateCantInferTypeDueToNoCombinedSignature,
+        analyzerCodes: <String>[
+      "COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE"
+    ]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsCantInferTypeDueToNoCombinedSignature(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeCantInferTypeDueToNoCombinedSignature,
+      message:
+          """Can't infer a type for '${name}' as the overridden members don't have a combined signature.""",
       tip: """Try adding an explicit type.""",
       arguments: {'name': name});
 }
@@ -1081,17 +1174,17 @@
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const MessageCode messageConstConstructorLateFinalFieldCause =
     const MessageCode("ConstConstructorLateFinalFieldCause",
-        severity: Severity.context,
-        message: r"""Field is late, but constructor is 'const'.""");
+        severity: Severity.context, message: r"""This constructor is const.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstConstructorLateFinalFieldError =
     messageConstConstructorLateFinalFieldError;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstConstructorLateFinalFieldError =
-    const MessageCode("ConstConstructorLateFinalFieldError",
-        message: r"""Constructor is marked 'const' so fields can't be late.""");
+const MessageCode messageConstConstructorLateFinalFieldError = const MessageCode(
+    "ConstConstructorLateFinalFieldError",
+    message:
+        r"""Can't have a late final field in a class with a const constructor.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstConstructorNonFinalField =
@@ -1164,33 +1257,32 @@
 const Template<
     Message Function(
         String
-            name)> templateConstEvalDeferredLibrary = const Template<
-        Message Function(String name)>(
+            nameOKEmpty)> templateConstEvalDeferredLibrary = const Template<
+        Message Function(String nameOKEmpty)>(
     messageTemplate:
-        r"""'#name' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
+        r"""'#nameOKEmpty' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
     tipTemplate:
         r"""Try moving the constant from the deferred library, or removing 'deferred' from the import.
 """,
     withArguments: _withArgumentsConstEvalDeferredLibrary);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeConstEvalDeferredLibrary =
-    const Code<Message Function(String name)>(
+const Code<Message Function(String nameOKEmpty)> codeConstEvalDeferredLibrary =
+    const Code<Message Function(String nameOKEmpty)>(
         "ConstEvalDeferredLibrary", templateConstEvalDeferredLibrary,
         analyzerCodes: <String>[
       "NON_CONSTANT_DEFAULT_VALUE_FROM_DEFERRED_LIBRARY"
     ]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalDeferredLibrary(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
+Message _withArgumentsConstEvalDeferredLibrary(String nameOKEmpty) {
+  if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalDeferredLibrary,
       message:
-          """'${name}' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
+          """'${nameOKEmpty}' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.""",
       tip: """Try moving the constant from the deferred library, or removing 'deferred' from the import.
 """,
-      arguments: {'name': name});
+      arguments: {'nameOKEmpty': nameOKEmpty});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1213,53 +1305,53 @@
     message: r"""This assertion failed.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string)>
+const Template<Message Function(String stringOKEmpty)>
     templateConstEvalFailedAssertionWithMessage =
-    const Template<Message Function(String string)>(
-        messageTemplate: r"""This assertion failed with message: #string""",
+    const Template<Message Function(String stringOKEmpty)>(
+        messageTemplate:
+            r"""This assertion failed with message: #stringOKEmpty""",
         withArguments: _withArgumentsConstEvalFailedAssertionWithMessage);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
+const Code<Message Function(String stringOKEmpty)>
     codeConstEvalFailedAssertionWithMessage =
-    const Code<Message Function(String string)>(
+    const Code<Message Function(String stringOKEmpty)>(
         "ConstEvalFailedAssertionWithMessage",
         templateConstEvalFailedAssertionWithMessage,
         analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalFailedAssertionWithMessage(String string) {
-  if (string.isEmpty) throw 'No string provided';
+Message _withArgumentsConstEvalFailedAssertionWithMessage(
+    String stringOKEmpty) {
+  if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   return new Message(codeConstEvalFailedAssertionWithMessage,
-      message: """This assertion failed with message: ${string}""",
-      arguments: {'string': string});
+      message: """This assertion failed with message: ${stringOKEmpty}""",
+      arguments: {'stringOKEmpty': stringOKEmpty});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<
-    Message Function(
-        String
-            name)> templateConstEvalInvalidStaticInvocation = const Template<
-        Message Function(String name)>(
-    messageTemplate:
-        r"""The invocation of '#name' is not allowed in a constant expression.""",
-    withArguments: _withArgumentsConstEvalInvalidStaticInvocation);
+const Template<Message Function(String nameOKEmpty)>
+    templateConstEvalInvalidStaticInvocation =
+    const Template<Message Function(String nameOKEmpty)>(
+        messageTemplate:
+            r"""The invocation of '#nameOKEmpty' is not allowed in a constant expression.""",
+        withArguments: _withArgumentsConstEvalInvalidStaticInvocation);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeConstEvalInvalidStaticInvocation =
-    const Code<Message Function(String name)>(
+const Code<Message Function(String nameOKEmpty)>
+    codeConstEvalInvalidStaticInvocation =
+    const Code<Message Function(String nameOKEmpty)>(
         "ConstEvalInvalidStaticInvocation",
         templateConstEvalInvalidStaticInvocation,
         analyzerCodes: <String>["CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalInvalidStaticInvocation(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
+Message _withArgumentsConstEvalInvalidStaticInvocation(String nameOKEmpty) {
+  if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalInvalidStaticInvocation,
       message:
-          """The invocation of '${name}' is not allowed in a constant expression.""",
-      arguments: {'name': name});
+          """The invocation of '${nameOKEmpty}' is not allowed in a constant expression.""",
+      arguments: {'nameOKEmpty': nameOKEmpty});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1298,27 +1390,27 @@
 const Template<
     Message Function(
         String
-            string)> templateConstEvalNonConstantVariableGet = const Template<
-        Message Function(String string)>(
+            nameOKEmpty)> templateConstEvalNonConstantVariableGet = const Template<
+        Message Function(String nameOKEmpty)>(
     messageTemplate:
-        r"""The variable '#string' is not a constant, only constant expressions are allowed.""",
+        r"""The variable '#nameOKEmpty' is not a constant, only constant expressions are allowed.""",
     withArguments: _withArgumentsConstEvalNonConstantVariableGet);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string)>
+const Code<Message Function(String nameOKEmpty)>
     codeConstEvalNonConstantVariableGet =
-    const Code<Message Function(String string)>(
+    const Code<Message Function(String nameOKEmpty)>(
         "ConstEvalNonConstantVariableGet",
         templateConstEvalNonConstantVariableGet,
         analyzerCodes: <String>["NON_CONSTANT_VALUE_IN_INITIALIZER"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsConstEvalNonConstantVariableGet(String string) {
-  if (string.isEmpty) throw 'No string provided';
+Message _withArgumentsConstEvalNonConstantVariableGet(String nameOKEmpty) {
+  if (nameOKEmpty == null || nameOKEmpty.isEmpty) nameOKEmpty = '(unnamed)';
   return new Message(codeConstEvalNonConstantVariableGet,
       message:
-          """The variable '${string}' is not a constant, only constant expressions are allowed.""",
-      arguments: {'string': string});
+          """The variable '${nameOKEmpty}' is not a constant, only constant expressions are allowed.""",
+      arguments: {'nameOKEmpty': nameOKEmpty});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -1880,14 +1972,14 @@
         message: r"""This is the inherited member.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeDeclaredMemberConflictsWithInheritedMembersCause =
-    messageDeclaredMemberConflictsWithInheritedMembersCause;
+const Code<Null> codeDeclaredMemberConflictsWithOverriddenMembersCause =
+    messageDeclaredMemberConflictsWithOverriddenMembersCause;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageDeclaredMemberConflictsWithInheritedMembersCause =
-    const MessageCode("DeclaredMemberConflictsWithInheritedMembersCause",
+const MessageCode messageDeclaredMemberConflictsWithOverriddenMembersCause =
+    const MessageCode("DeclaredMemberConflictsWithOverriddenMembersCause",
         severity: Severity.context,
-        message: r"""This is one of the inherited members.""");
+        message: r"""This is one of the overridden members.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeDefaultListConstructorError =
@@ -2807,6 +2899,7 @@
 const Template<Message Function(Token token)> templateExpectedIdentifier =
     const Template<Message Function(Token token)>(
         messageTemplate: r"""Expected an identifier, but got '#lexeme'.""",
+        tipTemplate: r"""Try inserting an identifier before '#lexeme'.""",
         withArguments: _withArgumentsExpectedIdentifier);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2820,6 +2913,36 @@
   String lexeme = token.lexeme;
   return new Message(codeExpectedIdentifier,
       message: """Expected an identifier, but got '${lexeme}'.""",
+      tip: """Try inserting an identifier before '${lexeme}'.""",
+      arguments: {'token': token});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        Token
+            token)> templateExpectedIdentifierButGotKeyword = const Template<
+        Message Function(
+            Token token)>(
+    messageTemplate:
+        r"""'#lexeme' can't be used as an identifier because it's a keyword.""",
+    tipTemplate:
+        r"""Try renaming this to be an identifier that isn't a keyword.""",
+    withArguments: _withArgumentsExpectedIdentifierButGotKeyword);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(Token token)> codeExpectedIdentifierButGotKeyword =
+    const Code<Message Function(Token token)>("ExpectedIdentifierButGotKeyword",
+        templateExpectedIdentifierButGotKeyword,
+        index: 113);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsExpectedIdentifierButGotKeyword(Token token) {
+  String lexeme = token.lexeme;
+  return new Message(codeExpectedIdentifierButGotKeyword,
+      message:
+          """'${lexeme}' can't be used as an identifier because it's a keyword.""",
+      tip: """Try renaming this to be an identifier that isn't a keyword.""",
       arguments: {'token': token});
 }
 
@@ -3125,6 +3248,14 @@
         r"""Null safe libraries are not allowed to export declarations from of opt-out libraries.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeExportedMain = messageExportedMain;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageExportedMain = const MessageCode("ExportedMain",
+    severity: Severity.context,
+    message: r"""This is exported 'main' declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeExpressionNotMetadata = messageExpressionNotMetadata;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3952,6 +4083,58 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFinalNotAssignedError = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Final variable '#name' must be assigned before it can be used.""",
+    withArguments: _withArgumentsFinalNotAssignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFinalNotAssignedError =
+    const Code<Message Function(String name)>(
+        "FinalNotAssignedError", templateFinalNotAssignedError,
+        analyzerCodes: <String>["READ_POTENTIALLY_UNASSIGNED_FINAL"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalNotAssignedError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalNotAssignedError,
+      message:
+          """Final variable '${name}' must be assigned before it can be used.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateFinalPossiblyAssignedError = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Final variable '#name' might already be assigned at this point.""",
+    withArguments: _withArgumentsFinalPossiblyAssignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFinalPossiblyAssignedError =
+    const Code<Message Function(String name)>(
+        "FinalPossiblyAssignedError", templateFinalPossiblyAssignedError,
+        analyzerCodes: <String>["ASSIGNMENT_TO_FINAL_LOCAL"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFinalPossiblyAssignedError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFinalPossiblyAssignedError,
+      message:
+          """Final variable '${name}' might already be assigned at this point.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeForInLoopExactlyOneVariable =
     messageForInLoopExactlyOneVariable;
 
@@ -5218,6 +5401,78 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInvalidGetterSetterTypeFieldContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""This is the declaration of the field '#name'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeFieldContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeInvalidGetterSetterTypeFieldContext =
+    const Code<Message Function(String name)>(
+        "InvalidGetterSetterTypeFieldContext",
+        templateInvalidGetterSetterTypeFieldContext,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeFieldContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvalidGetterSetterTypeFieldContext,
+      message: """This is the declaration of the field '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInvalidGetterSetterTypeGetterContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""This is the declaration of the getter '#name'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeGetterContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeInvalidGetterSetterTypeGetterContext =
+    const Code<Message Function(String name)>(
+        "InvalidGetterSetterTypeGetterContext",
+        templateInvalidGetterSetterTypeGetterContext,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeGetterContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvalidGetterSetterTypeGetterContext,
+      message: """This is the declaration of the getter '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateInvalidGetterSetterTypeSetterContext =
+    const Template<Message Function(String name)>(
+        messageTemplate: r"""This is the declaration of the setter '#name'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeSetterContext);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)>
+    codeInvalidGetterSetterTypeSetterContext =
+    const Code<Message Function(String name)>(
+        "InvalidGetterSetterTypeSetterContext",
+        templateInvalidGetterSetterTypeSetterContext,
+        severity: Severity.context);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeSetterContext(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeInvalidGetterSetterTypeSetterContext,
+      message: """This is the declaration of the setter '${name}'.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeInvalidHexEscape = messageInvalidHexEscape;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5583,6 +5838,17 @@
     tip: r"""Try annotating with `external`.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeJsInteropNonExternalMember =
+    messageJsInteropNonExternalMember;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageJsInteropNonExternalMember = const MessageCode(
+    "JsInteropNonExternalMember",
+    message:
+        r"""This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.""",
+    tip: r"""Try annotating the member with `external`.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(String name)> templateLabelNotFound = const Template<
         Message Function(String name)>(
@@ -5697,6 +5963,57 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name)>
+    templateLateDefinitelyAssignedError =
+    const Template<Message Function(String name)>(
+        messageTemplate:
+            r"""Late final variable '#name' definitely assigned.""",
+        withArguments: _withArgumentsLateDefinitelyAssignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeLateDefinitelyAssignedError =
+    const Code<Message Function(String name)>(
+  "LateDefinitelyAssignedError",
+  templateLateDefinitelyAssignedError,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsLateDefinitelyAssignedError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeLateDefinitelyAssignedError,
+      message: """Late final variable '${name}' definitely assigned.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String
+            name)> templateLateDefinitelyUnassignedError = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Late variable '#name' without initializer is definitely unassigned.""",
+    withArguments: _withArgumentsLateDefinitelyUnassignedError);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeLateDefinitelyUnassignedError =
+    const Code<Message Function(String name)>(
+  "LateDefinitelyUnassignedError",
+  templateLateDefinitelyUnassignedError,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsLateDefinitelyUnassignedError(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeLateDefinitelyUnassignedError,
+      message:
+          """Late variable '${name}' without initializer is definitely unassigned.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeLibraryDirectiveNotFirst = messageLibraryDirectiveNotFirst;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5803,6 +6120,63 @@
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainNotFunctionDeclaration =
+    messageMainNotFunctionDeclaration;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainNotFunctionDeclaration = const MessageCode(
+    "MainNotFunctionDeclaration",
+    message: r"""The 'main' declaration must be a function declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainNotFunctionDeclarationExported =
+    messageMainNotFunctionDeclarationExported;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainNotFunctionDeclarationExported = const MessageCode(
+    "MainNotFunctionDeclarationExported",
+    message:
+        r"""The exported 'main' declaration must be a function declaration.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainRequiredNamedParameters =
+    messageMainRequiredNamedParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainRequiredNamedParameters = const MessageCode(
+    "MainRequiredNamedParameters",
+    message: r"""The 'main' method cannot have required named parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainRequiredNamedParametersExported =
+    messageMainRequiredNamedParametersExported;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainRequiredNamedParametersExported = const MessageCode(
+    "MainRequiredNamedParametersExported",
+    message:
+        r"""The exported 'main' method cannot have required named parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainTooManyRequiredParameters =
+    messageMainTooManyRequiredParameters;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainTooManyRequiredParameters = const MessageCode(
+    "MainTooManyRequiredParameters",
+    message: r"""The 'main' method must have at most 2 required parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeMainTooManyRequiredParametersExported =
+    messageMainTooManyRequiredParametersExported;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageMainTooManyRequiredParametersExported = const MessageCode(
+    "MainTooManyRequiredParametersExported",
+    message:
+        r"""The exported 'main' method must have at most 2 required parameters.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeMapLiteralTypeArgumentMismatch =
     messageMapLiteralTypeArgumentMismatch;
 
@@ -6281,6 +6655,45 @@
         r"""Try removing this native clause and adding @native() or @native('native-name') before the declaration.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNeverReachableSwitchDefaultError =
+    messageNeverReachableSwitchDefaultError;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNeverReachableSwitchDefaultError = const MessageCode(
+    "NeverReachableSwitchDefaultError",
+    message:
+        r"""`null` encountered as case in a switch expression with a non-nullable enum type.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNeverReachableSwitchDefaultWarning =
+    messageNeverReachableSwitchDefaultWarning;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNeverReachableSwitchDefaultWarning = const MessageCode(
+    "NeverReachableSwitchDefaultWarning",
+    severity: Severity.warning,
+    message:
+        r"""The default case is not reachable with sound null safety because the switch expression is non-nullable.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNeverValueError = messageNeverValueError;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNeverValueError = const MessageCode("NeverValueError",
+    message:
+        r"""`null` encountered as the result from expression with type `Never`.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeNeverValueWarning = messageNeverValueWarning;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageNeverValueWarning = const MessageCode(
+    "NeverValueWarning",
+    severity: Severity.warning,
+    message:
+        r"""The expression can not result in a value with sound null safety because the expression type is `Never`.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(Token token)> templateNoFormals = const Template<
         Message Function(Token token)>(
@@ -6432,58 +6845,6 @@
     message: r"""Can only use type variables in instance methods.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateNonNullableLateDefinitelyAssignedError =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Non-nullable late final variable '#name' definitely assigned.""",
-        withArguments: _withArgumentsNonNullableLateDefinitelyAssignedError);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeNonNullableLateDefinitelyAssignedError =
-    const Code<Message Function(String name)>(
-  "NonNullableLateDefinitelyAssignedError",
-  templateNonNullableLateDefinitelyAssignedError,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonNullableLateDefinitelyAssignedError(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNonNullableLateDefinitelyAssignedError,
-      message:
-          """Non-nullable late final variable '${name}' definitely assigned.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String name)>
-    templateNonNullableLateDefinitelyUnassignedError =
-    const Template<Message Function(String name)>(
-        messageTemplate:
-            r"""Non-nullable late variable '#name' without initializer is definitely unassigned.""",
-        withArguments: _withArgumentsNonNullableLateDefinitelyUnassignedError);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)>
-    codeNonNullableLateDefinitelyUnassignedError =
-    const Code<Message Function(String name)>(
-  "NonNullableLateDefinitelyUnassignedError",
-  templateNonNullableLateDefinitelyUnassignedError,
-);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsNonNullableLateDefinitelyUnassignedError(String name) {
-  if (name.isEmpty) throw 'No name provided';
-  name = demangleMixinApplicationName(name);
-  return new Message(codeNonNullableLateDefinitelyUnassignedError,
-      message:
-          """Non-nullable late variable '${name}' without initializer is definitely unassigned.""",
-      arguments: {'name': name});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         String
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
index 7b8ebfb..5c94a3f 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/identifier_context_impl.dart
@@ -67,12 +67,16 @@
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -112,12 +116,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -152,8 +160,9 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
+      // Use the keyword as the identifier.
       parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
+          identifier, codes.templateExpectedIdentifierButGotKeyword);
     }
     return identifier;
   }
@@ -189,12 +198,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -224,12 +237,16 @@
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -250,15 +267,21 @@
     }
 
     // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
     if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
         isOneOfOrEof(identifier, const [',', '}'])) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
       return parser.rewriter.insertSyntheticIdentifier(token);
     } else if (!identifier.isKeywordOrIdentifier) {
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifier);
       // When in doubt, consume the token to ensure we make progress
       // but insert a synthetic identifier to satisfy listeners.
       return parser.rewriter.insertSyntheticIdentifier(identifier);
+    } else {
+      // Use the keyword as the identifier.
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifierButGotKeyword);
     }
     return identifier;
   }
@@ -296,16 +319,20 @@
     }
 
     // Recovery
-    parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
+    Token reportErrorAt = identifier;
     if (optional(r'$', token) &&
         identifier.isKeyword &&
         identifier.next.kind == STRING_TOKEN) {
       // Keyword used as identifier in string interpolation
+      parser.reportRecoverableErrorWithToken(
+          identifier, codes.templateExpectedIdentifierButGotKeyword);
       return identifier;
     } else if (!looksLikeStatementStart(identifier)) {
       if (identifier.isKeywordOrIdentifier) {
         if (isContinuation || !isOneOfOrEof(identifier, const ['as', 'is'])) {
+          // Use the keyword as the identifier.
+          parser.reportRecoverableErrorWithToken(
+              identifier, codes.templateExpectedIdentifierButGotKeyword);
           return identifier;
         }
       } else if (!identifier.isOperator &&
@@ -316,6 +343,10 @@
         identifier = token.next;
       }
     }
+
+    parser.reportRecoverableErrorWithToken(
+        reportErrorAt, codes.templateExpectedIdentifier);
+
     // Insert a synthetic identifier to satisfy listeners.
     return parser.rewriter.insertSyntheticIdentifier(token);
   }
@@ -337,6 +368,7 @@
     // Recovery
     if (isOneOfOrEof(identifier, const [';', '=', ',', '}']) ||
         looksLikeStartOfNextClassMember(identifier)) {
+      // TODO(jensj): Why aren't an error reported here?
       return parser.insertSyntheticIdentifier(token, this);
     } else if (!identifier.isKeywordOrIdentifier) {
       // When in doubt, consume the token to ensure we make progress
@@ -345,8 +377,9 @@
           message: codes.templateExpectedIdentifier.withArguments(identifier),
           messageOnToken: identifier);
     } else {
+      // Use the keyword as the identifier.
       parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
+          identifier, codes.templateExpectedIdentifierButGotKeyword);
       return identifier;
     }
   }
@@ -360,13 +393,13 @@
       return identifier;
     }
     // If not recovered, recover as normal.
-    if (!isRecovered || !token.isKeywordOrIdentifier) {
+    if (!isRecovered || !identifier.isKeywordOrIdentifier) {
       return ensureIdentifier(token, parser);
     }
 
     // If already recovered, use the given token.
     parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
+        identifier, codes.templateExpectedIdentifierButGotKeyword);
     return identifier;
   }
 }
@@ -425,12 +458,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -469,12 +506,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -528,12 +569,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -560,12 +605,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -590,12 +639,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -644,12 +697,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -677,12 +734,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -719,12 +780,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -768,8 +833,9 @@
           message: codes.templateExpectedIdentifier.withArguments(identifier),
           messageOnToken: identifier);
     } else {
+      // Use the keyword as the identifier.
       parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
+          identifier, codes.templateExpectedIdentifierButGotKeyword);
       return identifier;
     }
   }
@@ -783,13 +849,13 @@
       return identifier;
     }
     // If not recovered, recover as normal.
-    if (!isRecovered || !token.isKeywordOrIdentifier) {
+    if (!isRecovered || !identifier.isKeywordOrIdentifier) {
       return ensureIdentifier(token, parser);
     }
 
     // If already recovered, use the given token.
     parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
+        identifier, codes.templateExpectedIdentifierButGotKeyword);
     return identifier;
   }
 }
@@ -813,12 +879,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -858,12 +928,16 @@
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -883,13 +957,13 @@
       }
     }
     // If not recovered, recover as normal.
-    if (!isRecovered || !token.isKeywordOrIdentifier) {
+    if (!isRecovered || !identifier.isKeywordOrIdentifier) {
       return ensureIdentifier(token, parser);
     }
 
     // If already recovered, use the given token.
     parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
+        identifier, codes.templateExpectedIdentifierButGotKeyword);
     return identifier;
   }
 }
@@ -907,7 +981,7 @@
     if (identifier.type.isPseudo) {
       if (optional('Function', identifier)) {
         parser.reportRecoverableErrorWithToken(
-            identifier, codes.templateExpectedIdentifier);
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
       return identifier;
     }
@@ -923,12 +997,16 @@
       identifier = parser.insertSyntheticIdentifier(token, this,
           message: codes.templateExpectedIdentifier.withArguments(identifier));
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
@@ -942,19 +1020,19 @@
     if (identifier.type.isPseudo) {
       if (optional('Function', identifier)) {
         parser.reportRecoverableErrorWithToken(
-            identifier, codes.templateExpectedIdentifier);
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
       return identifier;
     }
 
     // If not recovered, recover as normal.
-    if (!isRecovered || !token.isKeywordOrIdentifier) {
+    if (!isRecovered || !identifier.isKeywordOrIdentifier) {
       return ensureIdentifier(token, parser);
     }
 
     // If already recovered, use the given token.
     parser.reportRecoverableErrorWithToken(
-        identifier, codes.templateExpectedIdentifier);
+        identifier, codes.templateExpectedIdentifierButGotKeyword);
     return identifier;
   }
 }
@@ -1045,12 +1123,16 @@
       parser.reportRecoverableErrorWithToken(
           identifier, codes.templateBuiltInIdentifierInDeclaration);
     } else {
-      parser.reportRecoverableErrorWithToken(
-          identifier, codes.templateExpectedIdentifier);
       if (!identifier.isKeywordOrIdentifier) {
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifier);
         // When in doubt, consume the token to ensure we make progress
         // but insert a synthetic identifier to satisfy listeners.
         identifier = parser.rewriter.insertSyntheticIdentifier(identifier);
+      } else {
+        // Use the keyword as the identifier.
+        parser.reportRecoverableErrorWithToken(
+            identifier, codes.templateExpectedIdentifierButGotKeyword);
       }
     }
     return identifier;
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 09d8ad1..9c829d4 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -4615,13 +4615,22 @@
       token = typeArg.parseArguments(bangToken, this);
       assert(optional('(', token.next));
     }
+
+    return _parsePrecedenceExpressionLoop(
+        precedence, allowCascades, typeArg, token);
+  }
+
+  Token _parsePrecedenceExpressionLoop(int precedence, bool allowCascades,
+      TypeParamOrArgInfo typeArg, Token token) {
     Token next = token.next;
     TokenType type = next.type;
     int tokenLevel = _computePrecedence(next);
+    bool enteredLoop = false;
     for (int level = tokenLevel; level >= precedence; --level) {
       int lastBinaryExpressionLevel = -1;
       Token lastCascade;
       while (identical(tokenLevel, level)) {
+        enteredLoop = true;
         Token operator = next;
         if (identical(tokenLevel, CASCADE_PRECEDENCE)) {
           if (!allowCascades) {
@@ -4725,10 +4734,103 @@
         type = next.type;
         tokenLevel = _computePrecedence(next);
       }
+      if (_recoverAtPrecedenceLevel && !_currentlyRecovering) {
+        // Attempt recovery
+        if (_attemptPrecedenceLevelRecovery(
+            token, precedence, level, allowCascades, typeArg)) {
+          // Recovered - try again at same level with the replacement token.
+          level++;
+          next = token.next;
+          type = next.type;
+          tokenLevel = _computePrecedence(next);
+        }
+      }
+    }
+
+    if (!enteredLoop && _recoverAtPrecedenceLevel && !_currentlyRecovering) {
+      // Attempt recovery
+      if (_attemptPrecedenceLevelRecovery(
+          token, precedence, /*currentLevel = */ -1, allowCascades, typeArg)) {
+        return _parsePrecedenceExpressionLoop(
+            precedence, allowCascades, typeArg, token);
+      }
     }
     return token;
   }
 
+  /// Attempt a recovery where [token.next] is replaced.
+  bool _attemptPrecedenceLevelRecovery(Token token, int precedence,
+      int currentLevel, bool allowCascades, TypeParamOrArgInfo typeArg) {
+    // Attempt recovery.
+    assert(_token_recovery_replacements.containsKey(token.next.lexeme));
+    TokenType replacement = _token_recovery_replacements[token.next.lexeme];
+    if (currentLevel >= 0) {
+      // Check that the new precedence and currentLevel would have accepted this
+      // replacement here.
+      int newLevel = replacement.precedence;
+      // The loop it would normally have gone through is something like
+      // for (; ; --level) {
+      //   while (identical(tokenLevel, level)) {
+      //   }
+      // }
+      // So if the new tokens level <= the "old" (current) level, [level] (in
+      // the above code snippet) would get down to it and accept it.
+      // But if the new tokens level > the "old" (current) level, normally we
+      // would never get to it - so we shouldn't here either. As the loop starts
+      // by taking the first tokens tokenLevel as level, recursing below won't
+      // weed that out so we need to do it here.
+      if (newLevel > currentLevel) return false;
+    }
+
+    _currentlyRecovering = true;
+    _recoverAtPrecedenceLevel = false;
+    Listener originalListener = listener;
+    TokenStreamRewriter originalRewriter = cachedRewriter;
+    NullListener nullListener = listener = new NullListener();
+    UndoableTokenStreamRewriter undoableTokenStreamRewriter =
+        new UndoableTokenStreamRewriter();
+    cachedRewriter = undoableTokenStreamRewriter;
+    rewriter.replaceNextTokenWithSyntheticToken(token, replacement);
+    bool acceptRecovery = false;
+    Token afterExpression = _parsePrecedenceExpressionLoop(
+        precedence, allowCascades, typeArg, token);
+
+    if (!nullListener.hasErrors &&
+        isOneOfOrEof(afterExpression.next, const [';', ',', ')', '{', '}'])) {
+      // Seems good!
+      acceptRecovery = true;
+    }
+
+    // Undo all changes and reset.
+    _currentlyRecovering = false;
+    undoableTokenStreamRewriter.undo();
+    listener = originalListener;
+    cachedRewriter = originalRewriter;
+
+    if (acceptRecovery) {
+      // Report and redo recovery.
+      reportRecoverableError(
+          token.next,
+          codes.templateBinaryOperatorWrittenOut
+              .withArguments(token.next.lexeme, replacement.lexeme));
+      rewriter.replaceNextTokenWithSyntheticToken(token, replacement);
+      return true;
+    }
+    return false;
+  }
+
+  bool _recoverAtPrecedenceLevel = false;
+  bool _currentlyRecovering = false;
+  static const Map<String, TokenType> _token_recovery_replacements = const {
+    // E.g. in Kotlin these are written out, see.
+    // https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-int/.
+    "xor": TokenType.CARET,
+    "and": TokenType.AMPERSAND,
+    "or": TokenType.BAR,
+    "shl": TokenType.LT_LT,
+    "shr": TokenType.GT_GT,
+  };
+
   int _computePrecedence(Token token) {
     TokenType type = token.type;
     if (identical(type, TokenType.BANG)) {
@@ -4751,7 +4853,15 @@
       if (!isConditional) {
         return SELECTOR_PRECEDENCE;
       }
+    } else if (identical(type, TokenType.IDENTIFIER)) {
+      // An identifier at this point is not right. So some recovery is going to
+      // happen soon. The question is, if we can do a better recovery here.
+      if (!_currentlyRecovering &&
+          _token_recovery_replacements.containsKey(token.lexeme)) {
+        _recoverAtPrecedenceLevel = true;
+      }
     }
+
     return type.precedence;
   }
 
@@ -6369,6 +6479,8 @@
     assert(optional('in', inKeyword) || optional(':', inKeyword));
 
     if (!identifier.isIdentifier) {
+      // TODO(jensj): This should probably (sometimes) be
+      // templateExpectedIdentifierButGotKeyword instead.
       reportRecoverableErrorWithToken(
           identifier, codes.templateExpectedIdentifier);
     } else if (identifier != token) {
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
index cc5cbce..df1e467 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/token_stream_rewriter.dart
@@ -9,6 +9,7 @@
         BeginToken,
         CommentToken,
         Keyword,
+        ReplacementToken,
         SimpleToken,
         SyntheticBeginToken,
         SyntheticKeywordToken,
@@ -17,7 +18,7 @@
         Token,
         TokenType;
 
-abstract class TokenStreamRewriter with _TokenStreamMixin {
+abstract class TokenStreamRewriter {
   /// Insert a synthetic open and close parenthesis and return the new synthetic
   /// open parenthesis. If [insertIdentifier] is true, then a synthetic
   /// identifier is included between the open and close parenthesis.
@@ -113,6 +114,47 @@
     return current;
   }
 
+  /// Insert a new simple synthetic token of [newTokenType] after
+  /// [previousToken] instead of the token actually coming after it and return
+  /// the new token.
+  /// The old token will be linked from the new one though, so it's not totally
+  /// gone.
+  ReplacementToken replaceNextTokenWithSyntheticToken(
+      Token previousToken, TokenType newTokenType) {
+    assert(newTokenType is! Keyword,
+        'use an unwritten variation of insertSyntheticKeyword instead');
+
+    // [token] <--> [a] <--> [b]
+    ReplacementToken replacement =
+        new ReplacementToken(newTokenType, previousToken.next);
+    insertToken(previousToken, replacement);
+    // [token] <--> [replacement] <--> [a] <--> [b]
+    _setNext(replacement, replacement.next.next);
+    // [token] <--> [replacement] <--> [b]
+
+    return replacement;
+  }
+
+  /// Insert a synthetic identifier after [token] and return the new identifier.
+  Token insertSyntheticIdentifier(Token token, [String value]) {
+    return insertToken(
+        token,
+        new SyntheticStringToken(TokenType.IDENTIFIER, value ?? '',
+            token.next.charOffset, /* _length = */ 0));
+  }
+
+  /// Insert a new synthetic [keyword] after [token] and return the new token.
+  Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
+      token, new SyntheticKeywordToken(keyword, token.next.charOffset));
+
+  /// Insert a new simple synthetic token of [newTokenType] after [token]
+  /// and return the new token.
+  Token insertSyntheticToken(Token token, TokenType newTokenType) {
+    assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
+    return insertToken(
+        token, new SyntheticToken(newTokenType, token.next.charOffset));
+  }
+
   Token _setNext(Token setOn, Token nextToken);
   void _setEndGroup(BeginToken setOn, Token endGroup);
   void _setOffset(Token setOn, int offset);
@@ -164,117 +206,6 @@
   }
 }
 
-/// Provides the capability of adding tokens that lead into a token stream
-/// without modifying the original token stream and not setting the any token's
-/// `previous` field.
-class TokenStreamGhostWriter
-    with _TokenStreamMixin
-    implements TokenStreamRewriter {
-  @override
-  Token insertParens(Token token, bool includeIdentifier) {
-    Token next = token.next;
-    int offset = next.charOffset;
-    BeginToken leftParen =
-        next = new SyntheticBeginToken(TokenType.OPEN_PAREN, offset);
-    if (includeIdentifier) {
-      Token identifier = new SyntheticStringToken(
-          TokenType.IDENTIFIER, '', offset, /* _length = */ 0);
-      next.next = identifier;
-      next = identifier;
-    }
-    Token rightParen = new SyntheticToken(TokenType.CLOSE_PAREN, offset);
-    next.next = rightParen;
-    rightParen.next = token.next;
-
-    return leftParen;
-  }
-
-  @override
-  Token insertToken(Token token, Token newToken) {
-    newToken.next = token.next;
-    return newToken;
-  }
-
-  @override
-  Token moveSynthetic(Token token, Token endGroup) {
-    Token newEndGroup =
-        new SyntheticToken(endGroup.type, token.next.charOffset);
-    newEndGroup.next = token.next;
-    return newEndGroup;
-  }
-
-  @override
-  Token replaceTokenFollowing(Token previousToken, Token replacementToken) {
-    Token replacedToken = previousToken.next;
-
-    (replacementToken as SimpleToken).precedingComments =
-        replacedToken.precedingComments;
-
-    _lastTokenInChain(replacementToken).next = replacedToken.next;
-    return replacementToken;
-  }
-
-  /// Given the [firstToken] in a chain of tokens to be inserted, return the
-  /// last token in the chain.
-  Token _lastTokenInChain(Token firstToken) {
-    Token current = firstToken;
-    while (current.next != null && current.next.type != TokenType.EOF) {
-      current = current.next;
-    }
-    return current;
-  }
-
-  @override
-  void _setEndGroup(BeginToken setOn, Token endGroup) {
-    throw new UnimplementedError("_setEndGroup");
-  }
-
-  @override
-  Token _setNext(Token setOn, Token nextToken) {
-    throw new UnimplementedError("_setNext");
-  }
-
-  @override
-  void _setOffset(Token setOn, int offset) {
-    throw new UnimplementedError("_setOffset");
-  }
-
-  @override
-  void _setPrecedingComments(SimpleToken setOn, CommentToken comment) {
-    throw new UnimplementedError("_setPrecedingComments");
-  }
-
-  @override
-  void _setPrevious(Token setOn, Token previous) {
-    throw new UnimplementedError("_setPrevious");
-  }
-}
-
-mixin _TokenStreamMixin {
-  /// Insert a synthetic identifier after [token] and return the new identifier.
-  Token insertSyntheticIdentifier(Token token, [String value]) {
-    return insertToken(
-        token,
-        new SyntheticStringToken(TokenType.IDENTIFIER, value ?? '',
-            token.next.charOffset, /* _length = */ 0));
-  }
-
-  /// Insert a new synthetic [keyword] after [token] and return the new token.
-  Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
-      token, new SyntheticKeywordToken(keyword, token.next.charOffset));
-
-  /// Insert a new simple synthetic token of [newTokenType] after [token]
-  /// and return the new token.
-  Token insertSyntheticToken(Token token, TokenType newTokenType) {
-    assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
-    return insertToken(
-        token, new SyntheticToken(newTokenType, token.next.charOffset));
-  }
-
-  /// Insert [newToken] after [token] and return [newToken].
-  Token insertToken(Token token, Token newToken);
-}
-
 abstract class TokenStreamChange {
   void undo();
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
index 9f501af..38f0335 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -804,6 +804,32 @@
   Token copy() => new SyntheticToken(type, offset);
 }
 
+/// A token used to replace another token in the stream, while still keeping the
+/// old token around (in [replacedToken]). Automatically sets the offset and
+/// precedingComments from the data available on [replacedToken].
+class ReplacementToken extends SyntheticToken {
+  /// The token that this token replaces. This will normally be the token
+  /// representing what the user actually wrote.
+  final Token replacedToken;
+
+  ReplacementToken(TokenType type, this.replacedToken)
+      : super(type, replacedToken.offset) {
+    precedingComments = replacedToken.precedingComments;
+  }
+
+  @override
+  Token beforeSynthetic;
+
+  @override
+  bool get isSynthetic => true;
+
+  @override
+  int get length => 0;
+
+  @override
+  Token copy() => new ReplacementToken(type, replacedToken);
+}
+
 /**
  * A token that was scanned from the input. Each token knows which tokens
  * precede and follow it, acting as a link in a doubly linked list of tokens.
diff --git a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
index 7725a34..79072a1 100644
--- a/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/testing/features.dart
@@ -9,6 +9,25 @@
   Map<String, Object> _features = {};
   Set<String> _unsorted = new Set<String>();
 
+  Features();
+
+  /// Creates a [Features] registering each key in [featuresMap] as a features
+  /// with the corresponding value(s) in the map. Note: values are expected to
+  /// be either a single `String` value or a `List<String>`.
+  factory Features.fromMap(Map<String, dynamic> featuresMap) {
+    Features features = new Features();
+    featuresMap.forEach((key, value) {
+      if (value is List) {
+        for (dynamic v in value) {
+          features.addElement(key, v);
+        }
+      } else {
+        features.add(key, value: value);
+      }
+    });
+    return features;
+  }
+
   /// Mark the feature [key] as existing. If [value] is provided, the feature
   /// [key] is set to have this value.
   void add(String key, {var value: ''}) {
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index 864c0a6..7d75dfd 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
 name: _fe_analyzer_shared
-version: 9.0.0
+version: 11.0.0
 description: Logic that is shared between the front_end and analyzer packages.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
 
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart
index 35a845a..f9d2545 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for.dart
@@ -23,7 +23,7 @@
   }
 }
 
-/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b, c}*/
+/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b}*/
 forEachWithDeclaration(int a, int b) {
   /*assigned={b}*/ for (var c in [a = 0]) {
     b = 0;
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
index 86b2e15..cb3d20b 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables/data/for_element.dart
@@ -7,11 +7,21 @@
   [/*assigned={b, c, d}*/ for (a = 0; (b = 0) != 0; c = 0) (d = 0)];
 }
 
+/*member: cStyle_unparenthesized:declared={a, b, c, d, e}, assigned={a, b, d, e}*/
+cStyle_unparenthesized(int a, bool b, bool c, int d, int e) {
+  [/*assigned={b, d, e}*/ for (a = 0; b = c; d = 0) e = 0];
+}
+
 /*member: cStyleWithDeclaration:declared={a, b, c, d, e}, assigned={a, b, c, d}*/
 cStyleWithDeclaration(int a, int b, int c, int d) {
   [/*assigned={b, c, d}*/ for (int e = (a = 0); (b = 0) != 0; c = 0) (d = 0)];
 }
 
+/*member: cStyleWithDeclaration_unparenthesized:declared={a, b, c, d, e, f}, assigned={a, b, d, e}*/
+cStyleWithDeclaration_unparenthesized(int a, bool b, bool c, int d, int e) {
+  [/*assigned={b, d, e}*/ for (int f = a = 0; b = c; d = 0) e = 0];
+}
+
 /*member: forEach:declared={a, b, c}, assigned={a, b, c}*/
 forEach(int a, int b, int c) {
   [
@@ -19,9 +29,23 @@
   ];
 }
 
-/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b, c}*/
+/*member: forEach_unparenthesized:declared={a, b, c}, assigned={a, b, c}*/
+forEach_unparenthesized(int a, int b, int c) {
+  [
+    /*assigned={c}*/ for (a in [b = 0]) c = 0
+  ];
+}
+
+/*member: forEachWithDeclaration:declared={a, b, c}, assigned={a, b}*/
 forEachWithDeclaration(int a, int b) {
   [
     /*assigned={b}*/ for (var c in [a = 0]) (b = 0)
   ];
 }
+
+/*member: forEachWithDeclaration_unparenthesized:declared={a, b, c}, assigned={a, b}*/
+forEachWithDeclaration_unparenthesized(int a, int b) {
+  [
+    /*assigned={b}*/ for (var c in [a = 0]) b = 0
+  ];
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
index f17b730..10196f4 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/assigned_variables_test.dart
@@ -17,7 +17,8 @@
     assignedVariables.write(v1);
     assignedVariables.beginNode();
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.write(v3);
     assignedVariables.finish();
     expect(assignedVariables.capturedAnywhere, {v2});
@@ -32,7 +33,8 @@
     assignedVariables.declare(v2);
     assignedVariables.write(v1);
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.finish();
     expect(assignedVariables.capturedAnywhere, {v1});
   });
@@ -48,7 +50,8 @@
     assignedVariables.write(v1);
     assignedVariables.beginNode();
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.write(v3);
     assignedVariables.finish();
     expect(assignedVariables.writtenAnywhere, {v1, v2, v3});
@@ -102,7 +105,7 @@
     assignedVariables.beginNode();
     assignedVariables.write(v1);
     var node = _Node();
-    assignedVariables.endNode(node, isClosure: true);
+    assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
     assignedVariables.finish();
     expect(assignedVariables.writtenInNode(node), {v1});
   });
@@ -115,13 +118,15 @@
     assignedVariables.declare(v2);
     assignedVariables.beginNode();
     assignedVariables.write(v1);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.beginNode();
     var node = _Node();
     assignedVariables.endNode(node);
     assignedVariables.beginNode();
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.finish();
     expect(assignedVariables.capturedInNode(node), isEmpty);
   });
@@ -133,7 +138,8 @@
     assignedVariables.beginNode();
     assignedVariables.beginNode();
     assignedVariables.write(v1);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     var node = _Node();
     assignedVariables.endNode(node);
     assignedVariables.finish();
@@ -153,9 +159,11 @@
       assignedVariables.write(v1);
       assignedVariables.beginNode();
       assignedVariables.write(v2);
-      assignedVariables.endNode(_Node(), isClosure: true);
+      assignedVariables.endNode(_Node(),
+          isClosureOrLateVariableInitializer: true);
       var innerNode = _Node();
-      assignedVariables.endNode(innerNode, isClosure: false);
+      assignedVariables.endNode(innerNode,
+          isClosureOrLateVariableInitializer: false);
       var outerNode = _Node();
       assignedVariables.endNode(outerNode);
       assignedVariables.finish();
@@ -176,9 +184,11 @@
       assignedVariables.write(v1);
       assignedVariables.beginNode();
       assignedVariables.write(v2);
-      assignedVariables.endNode(_Node(), isClosure: true);
+      assignedVariables.endNode(_Node(),
+          isClosureOrLateVariableInitializer: true);
       var innerNode = _Node();
-      assignedVariables.endNode(innerNode, isClosure: true);
+      assignedVariables.endNode(innerNode,
+          isClosureOrLateVariableInitializer: true);
       var outerNode = _Node();
       assignedVariables.endNode(outerNode);
       assignedVariables.finish();
@@ -233,7 +243,8 @@
     assignedVariables.beginNode();
     assignedVariables.write(v1);
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     assignedVariables.discardNode();
     assignedVariables.endNode(node);
     assignedVariables.finish();
@@ -254,7 +265,8 @@
     assignedVariables.declare(v3);
     assignedVariables.beginNode();
     assignedVariables.write(v2);
-    assignedVariables.endNode(_Node(), isClosure: true);
+    assignedVariables.endNode(_Node(),
+        isClosureOrLateVariableInitializer: true);
     var info = assignedVariables.deferNode();
     assignedVariables.beginNode();
     assignedVariables.write(v4);
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/late_initializer.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/late_initializer.dart
new file mode 100644
index 0000000..b9d96c7
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_assignment/data/late_initializer.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test checks that flow analysis understands that two late initializers
+// may execute independently, so an assignment in one doesn't place the variable
+// into the "assigned" state in the other.
+
+twoEagerVariables() {
+  late int x;
+  int y = (x = 0), z = x;
+}
+
+twoLateVariables() {
+  late int x;
+  late int y = (x = 0), z = /*unassigned*/ x;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
index 0ebc102..4f1dc0a 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/for_each.dart
@@ -69,3 +69,14 @@
     for (int i in [0, 1, 2]) i
   ];
 }
+
+forEach_contains_unreachable_assignment() {
+  late Object v1;
+  for (var _ in [0, 1, 2]) {
+    break;
+    v1 = 0;
+  }
+  // v1 is considered potentially assigned here, for consistency with how we
+  // would analyze the equivalent desugared loop.
+  v1;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue43006.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue43006.dart
new file mode 100644
index 0000000..76c6b78
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/issue43006.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+test() {
+  late int x;
+  late int y;
+  var f = () => x;
+  int z0 = /*unassigned*/ x;
+  int z1 = /*unassigned*/ y;
+  x = 3;
+  y = 3;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/late_initializer.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/late_initializer.dart
new file mode 100644
index 0000000..3b9c964
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/definite_unassignment/data/late_initializer.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test checks that flow analysis understands that a late initializer
+// doesn't execute immediately, so it may refer to other late variables that
+// aren't assigned yet.
+
+void use(Object? x) {}
+
+eagerInitializerRefersToLateVar() {
+  late int x;
+  int y = /*unassigned*/ x;
+  x = 0;
+}
+
+lateInitializerRefersToLateVar() {
+  late int x;
+  late int y = x;
+  x = 0;
+}
+
+lateInitializerIsAssignment() {
+  late int y;
+  late int z1 = y = 3;
+  use(y);
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
index d512956..8b5ee79 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/flow_analysis_test.dart
@@ -76,6 +76,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.conditional_conditionBegin();
         flow.conditional_thenBegin(h.notNull(x, _Type('int?'))());
         expect(flow.promotedType(x).type, 'int');
         flow.conditional_elseBegin(_Expression());
@@ -90,6 +91,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.conditional_conditionBegin();
         flow.conditional_thenBegin(h.eqNull(x, _Type('int?'))());
         expect(flow.promotedType(x), isNull);
         flow.conditional_elseBegin(_Expression());
@@ -109,6 +111,7 @@
         h.declare(x, initialized: true);
         h.declare(y, initialized: true);
         h.declare(z, initialized: true);
+        flow.conditional_conditionBegin();
         flow.conditional_thenBegin(_Expression());
         h.promote(x, 'int');
         h.promote(y, 'int');
@@ -179,6 +182,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
         flow.equalityOp_rightBegin(varExpr, _Type('int?'));
@@ -203,6 +207,7 @@
       var x = h.addVar('x', 'int');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
         flow.equalityOp_rightBegin(varExpr, _Type('int'));
@@ -211,12 +216,14 @@
         var expr = _Expression();
         var successIsReachable =
             flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: true);
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.ifStatement_elseBegin();
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.ifStatement_end(true);
       });
@@ -225,6 +232,7 @@
     test('equalityOp(<expr> == <expr>) has no special effect', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         flow.equalityOp_rightBegin(_Expression(), _Type('int?'));
         var expr = _Expression();
         var successIsReachable = flow.equalityOp_end(
@@ -242,6 +250,7 @@
     test('equalityOp(<expr> != <expr>) has no special effect', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         flow.equalityOp_rightBegin(_Expression(), _Type('int?'));
         var expr = _Expression();
         var successIsReachable = flow
@@ -260,6 +269,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
         flow.equalityOp_rightBegin(varExpr, _Type('int?'));
@@ -279,6 +289,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
         flow.equalityOp_rightBegin(varExpr, _Type('int?'));
@@ -303,6 +314,7 @@
       var x = h.addVar('x', 'int');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var varExpr = _Expression();
         flow.variableRead(varExpr, x);
         flow.equalityOp_rightBegin(varExpr, _Type('int'));
@@ -311,9 +323,11 @@
         var expr = _Expression();
         var successIsReachable =
             flow.equalityOp_end(expr, nullExpr, _Type('Null'), notEqual: false);
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         expect(flow.promotedType(x), isNull);
         flow.ifStatement_elseBegin();
         expect(flow.isReachable, true);
@@ -327,6 +341,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var nullExpr = _Expression();
         flow.nullLiteral(nullExpr);
         flow.equalityOp_rightBegin(nullExpr, _Type('Null'));
@@ -347,6 +362,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var nullExpr = _Expression();
         flow.equalityOp_rightBegin(nullExpr, _Type('Null'));
         var varExpr = _Expression();
@@ -366,6 +382,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var nullExpr = _Expression();
         flow.nullLiteral(nullExpr);
         flow.equalityOp_rightBegin(nullExpr, _Type('Null'));
@@ -384,6 +401,7 @@
     test('equalityOp(null == null) equivalent to true', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
@@ -402,6 +420,7 @@
     test('equalityOp(null != null) equivalent to false', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
@@ -417,73 +436,85 @@
       });
     });
 
-    test('equalityOp(null == non-null) equivalent to false', () {
+    test('equalityOp(null == non-null) is not equivalent to false', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
         var successIsReachable = flow.equalityOp_end(expr, null2, _Type('int'));
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
         expect(flow.isReachable, true);
         flow.ifStatement_end(true);
       });
     });
 
-    test('equalityOp(null != non-null) equivalent to true', () {
+    test('equalityOp(null != non-null) is not equivalent to true', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('Null'));
         var null2 = _Expression();
         var expr = _Expression();
         var successIsReachable =
             flow.equalityOp_end(expr, null2, _Type('int'), notEqual: true);
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         flow.ifStatement_end(true);
       });
     });
 
-    test('equalityOp(non-null == null) equivalent to false', () {
+    test('equalityOp(non-null == null) is not equivalent to false', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('int'));
         var null2 = _Expression();
         var expr = _Expression();
         var successIsReachable =
             flow.equalityOp_end(expr, null2, _Type('Null'));
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
         expect(flow.isReachable, true);
         flow.ifStatement_end(true);
       });
     });
 
-    test('equalityOp(non-null != null) equivalent to true', () {
+    test('equalityOp(non-null != null) is not equivalent to true', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var null1 = _Expression();
         flow.equalityOp_rightBegin(null1, _Type('int'));
         var null2 = _Expression();
         var expr = _Expression();
         var successIsReachable =
             flow.equalityOp_end(expr, null2, _Type('Null'), notEqual: true);
-        expect(successIsReachable, false);
+        // The `== null` case is considered reachable due to mixed mode
+        // unsoundness
+        expect(successIsReachable, true);
         flow.ifStatement_thenBegin(expr);
         expect(flow.isReachable, true);
         flow.ifStatement_elseBegin();
-        expect(flow.isReachable, false);
+        expect(flow.isReachable, true);
         flow.ifStatement_end(true);
       });
     });
@@ -587,6 +618,7 @@
       var h = _Harness();
       var expr = _Expression();
       var flow = h.createFlow();
+      flow.ifStatement_conditionBegin();
       flow.ifStatement_thenBegin(expr);
       expect(() => flow.finish(), _asserts);
     });
@@ -810,6 +842,29 @@
       });
     });
 
+    test('forEach_bodyBegin() pushes conservative join state', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      var forStatement = _Statement();
+      h.assignedVariables(
+          (vars) => vars.nest(forStatement, () => vars.write(x)));
+      h.run((flow) {
+        h.declare(x, initialized: false);
+        expect(flow.isUnassigned(x), true);
+        flow.forEach_bodyBegin(forStatement, null, _Type('int'));
+        // Since a write to x occurs somewhere in the loop, x should no longer
+        // be considered unassigned.
+        expect(flow.isUnassigned(x), false);
+        flow.handleBreak(forStatement);
+        flow.write(x, _Type('int'));
+        flow.forEach_end();
+        // Even though the write to x is unreachable (since it occurs after a
+        // break), x should still be considered "possibly assigned" because of
+        // the conservative join done at the top of the loop.
+        expect(flow.isUnassigned(x), false);
+      });
+    });
+
     test('forEach_end() restores state before loop', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
@@ -979,6 +1034,120 @@
       });
     });
 
+    test(
+        'functionExpression_end does not propagate "definitely unassigned" '
+        'data', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int');
+      var functionNode = _Node();
+      h.assignedVariables((vars) {
+        vars.function(functionNode, () {});
+        vars.write(x);
+      });
+      h.run((flow) {
+        flow.declare(x, false);
+        expect(flow.isUnassigned(x), true);
+        flow.functionExpression_begin(functionNode);
+        // The function expression could be called at any time, so x might be
+        // assigned now.
+        expect(flow.isUnassigned(x), false);
+        flow.functionExpression_end();
+        // But now that we are back outside the function expression, we once
+        // again know that x is unassigned.
+        expect(flow.isUnassigned(x), true);
+        flow.write(x, _Type('int'));
+        expect(flow.isUnassigned(x), false);
+      });
+    });
+
+    test('handleBreak handles deep nesting', () {
+      var h = _Harness();
+      var whileStatement = _Statement();
+      h.assignedVariables((vars) {
+        vars.nest(whileStatement, () {});
+      });
+      h.run((flow) {
+        flow.whileStatement_conditionBegin(whileStatement);
+        flow.whileStatement_bodyBegin(whileStatement, h.booleanLiteral(true)());
+        h.if_(h.expr, () {
+          h.if_(h.expr, () {
+            flow.handleBreak(whileStatement);
+          });
+        });
+        flow.handleExit();
+        expect(flow.isReachable, false);
+        flow.whileStatement_end();
+        expect(flow.isReachable, true);
+      });
+    });
+
+    test('handleBreak handles mixed nesting', () {
+      var h = _Harness();
+      var whileStatement = _Statement();
+      h.assignedVariables((vars) {
+        vars.nest(whileStatement, () {});
+      });
+      h.run((flow) {
+        flow.whileStatement_conditionBegin(whileStatement);
+        flow.whileStatement_bodyBegin(whileStatement, h.booleanLiteral(true)());
+        h.if_(h.expr, () {
+          h.if_(h.expr, () {
+            flow.handleBreak(whileStatement);
+          });
+          flow.handleBreak(whileStatement);
+        });
+        flow.handleBreak(whileStatement);
+        expect(flow.isReachable, false);
+        flow.whileStatement_end();
+        expect(flow.isReachable, true);
+      });
+    });
+
+    test('handleContinue handles deep nesting', () {
+      var h = _Harness();
+      var doStatement = _Statement();
+      h.assignedVariables((vars) {
+        vars.nest(doStatement, () {});
+      });
+      h.run((flow) {
+        flow.doStatement_bodyBegin(doStatement);
+        h.if_(h.expr, () {
+          h.if_(h.expr, () {
+            flow.handleContinue(doStatement);
+          });
+        });
+        flow.handleExit();
+        expect(flow.isReachable, false);
+        flow.doStatement_conditionBegin();
+        expect(flow.isReachable, true);
+        flow.doStatement_end(h.booleanLiteral(true)());
+        expect(flow.isReachable, false);
+      });
+    });
+
+    test('handleContinue handles mixed nesting', () {
+      var h = _Harness();
+      var doStatement = _Statement();
+      h.assignedVariables((vars) {
+        vars.nest(doStatement, () {});
+      });
+      h.run((flow) {
+        flow.doStatement_bodyBegin(doStatement);
+        h.if_(h.expr, () {
+          h.if_(h.expr, () {
+            flow.handleContinue(doStatement);
+          });
+          flow.handleContinue(doStatement);
+        });
+        flow.handleContinue(doStatement);
+        expect(flow.isReachable, false);
+        flow.doStatement_conditionBegin();
+        expect(flow.isReachable, true);
+        flow.doStatement_end(h.booleanLiteral(true)());
+        expect(flow.isReachable, false);
+      });
+    });
+
     test('ifNullExpression allows ensure guarding', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
@@ -1031,13 +1200,15 @@
       });
     });
 
-    test('ifNullExpression detects when RHS is unreachable', () {
+    test('ifNullExpression does not detect when RHS is unreachable', () {
       var h = _Harness();
       h.run((flow) {
         var rhsIsReachable =
             flow.ifNullExpression_rightBegin(h.expr(), _Type('int'));
-        expect(rhsIsReachable, false);
-        expect(flow.isReachable, false);
+        // We can't treat the RHS as unreachable because of mixed mode
+        // unsoundness
+        expect(rhsIsReachable, true);
+        expect(flow.isReachable, true);
         flow.ifNullExpression_end();
         expect(flow.isReachable, true);
       });
@@ -1056,11 +1227,28 @@
       });
     });
 
+    test('ifStatement with early exit promotes in unreachable code', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'int?');
+      h.run((flow) {
+        h.declare(x, initialized: true);
+        flow.handleExit();
+        expect(flow.isReachable, false);
+        flow.ifStatement_conditionBegin();
+        flow.ifStatement_thenBegin(h.eqNull(x, _Type('int?'))());
+        flow.handleExit();
+        flow.ifStatement_end(false);
+        expect(flow.isReachable, false);
+        expect(flow.promotedType(x).type, 'int');
+      });
+    });
+
     test('ifStatement_end(false) keeps else branch if then branch exits', () {
       var h = _Harness();
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         flow.ifStatement_thenBegin(h.eqNull(x, _Type('int?'))());
         flow.handleExit();
         flow.ifStatement_end(false);
@@ -1068,32 +1256,29 @@
       });
     });
 
-    void _checkIs(
-        String declaredType,
-        String tryPromoteType,
-        String expectedPromotedTypeThen,
-        String expectedPromotedTypeElse,
-        bool expectedFailureReachable,
+    void _checkIs(String declaredType, String tryPromoteType,
+        String expectedPromotedTypeThen, String expectedPromotedTypeElse,
         {bool inverted = false}) {
       var h = _Harness();
       var x = h.addVar('x', declaredType);
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
         var read = _Expression();
         flow.variableRead(read, x);
         var expr = _Expression();
         var failureReachable =
             flow.isExpression_end(expr, read, inverted, _Type(tryPromoteType));
-        expect(failureReachable, expectedFailureReachable);
+        expect(failureReachable, true);
         flow.ifStatement_thenBegin(expr);
-        expect(flow.isReachable, inverted ? expectedFailureReachable : true);
+        expect(flow.isReachable, true);
         if (expectedPromotedTypeThen == null) {
           expect(flow.promotedType(x), isNull);
         } else {
           expect(flow.promotedType(x).type, expectedPromotedTypeThen);
         }
         flow.ifStatement_elseBegin();
-        expect(flow.isReachable, inverted ? true : expectedFailureReachable);
+        expect(flow.isReachable, true);
         if (expectedPromotedTypeElse == null) {
           expect(flow.promotedType(x), isNull);
         } else {
@@ -1104,33 +1289,34 @@
     }
 
     test('isExpression_end promotes to a subtype', () {
-      _checkIs('int?', 'int', 'int', 'Never?', true);
+      _checkIs('int?', 'int', 'int', 'Never?');
     });
 
     test('isExpression_end promotes to a subtype, inverted', () {
-      _checkIs('int?', 'int', 'Never?', 'int', true, inverted: true);
+      _checkIs('int?', 'int', 'Never?', 'int', inverted: true);
     });
 
     test('isExpression_end does not promote to a supertype', () {
-      _checkIs('int', 'int?', null, 'Never', false);
+      _checkIs('int', 'int?', null, null);
     });
 
     test('isExpression_end does not promote to a supertype, inverted', () {
-      _checkIs('int', 'int?', 'Never', null, false, inverted: true);
+      _checkIs('int', 'int?', null, null, inverted: true);
     });
 
     test('isExpression_end does not promote to an unrelated type', () {
-      _checkIs('int', 'String', null, null, true);
+      _checkIs('int', 'String', null, null);
     });
 
     test('isExpression_end does not promote to an unrelated type, inverted',
         () {
-      _checkIs('int', 'String', null, null, true, inverted: true);
+      _checkIs('int', 'String', null, null, inverted: true);
     });
 
     test('isExpression_end does nothing if applied to a non-variable', () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var subExpr = _Expression();
         var expr = _Expression();
         var failureReachable =
@@ -1148,6 +1334,7 @@
         () {
       var h = _Harness();
       h.run((flow) {
+        flow.ifStatement_conditionBegin();
         var subExpr = _Expression();
         var expr = _Expression();
         var failureReachable =
@@ -1234,6 +1421,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.logicalBinaryOp_begin();
         flow.logicalBinaryOp_rightBegin(h.notNull(x, _Type('int?'))(),
             isAnd: true);
         expect(flow.promotedType(x).type, 'int');
@@ -1246,6 +1434,8 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
+        flow.logicalBinaryOp_begin();
         flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: true);
         var wholeExpr = _Expression();
         flow.logicalBinaryOp_end(wholeExpr, h.notNull(x, _Type('int?'))(),
@@ -1262,6 +1452,8 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.ifStatement_conditionBegin();
+        flow.logicalBinaryOp_begin();
         flow.logicalBinaryOp_rightBegin(_Expression(), isAnd: false);
         var wholeExpr = _Expression();
         flow.logicalBinaryOp_end(wholeExpr, h.eqNull(x, _Type('int?'))(),
@@ -1278,6 +1470,7 @@
       var x = h.addVar('x', 'int?');
       h.run((flow) {
         h.declare(x, initialized: true);
+        flow.logicalBinaryOp_begin();
         flow.logicalBinaryOp_rightBegin(h.eqNull(x, _Type('int?'))(),
             isAnd: false);
         expect(flow.promotedType(x).type, 'int');
@@ -1377,7 +1570,9 @@
         var lhs = _Expression();
         var shortIsReachable =
             flow.nullAwareAccess_rightBegin(lhs, _Type('int'));
-        expect(shortIsReachable, false);
+        // We can't treat the short as unreachable because of mixed mode
+        // unsoundness
+        expect(shortIsReachable, true);
         expect(flow.isReachable, true);
         expect(flow.promotedType(x).type, 'int');
         flow.write(x, _Type('int?'));
@@ -1394,14 +1589,16 @@
         h.declare(x, initialized: true);
         var shortIsReachable =
             flow.nullAwareAccess_rightBegin(_Expression(), _Type('int'));
-        expect(shortIsReachable, false);
+        // We can't treat the RHS as unreachable because of mixed mode
+        // unsoundness
+        expect(shortIsReachable, true);
         expect(flow.isReachable, true);
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
         flow.nullAwareAccess_end();
-        // `x` should still be promoted because the target was non-nullable, so
-        // the null shorting path was unreachable.
-        expect(flow.promotedType(x).type, 'int');
+        // Since the null-shorting path was reachable, promotion of `x` should
+        // be cancelled.
+        expect(flow.promotedType(x), isNull);
       });
     });
 
@@ -1420,6 +1617,54 @@
       });
     });
 
+    test('promote promotes to a subtype and sets type of interest', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'num?');
+      h.assignedVariables((vars) {
+        vars.write(x);
+      });
+      h.run((flow) {
+        flow.declare(x, true);
+        expect(flow.promotedType(x), isNull);
+        flow.promote(x, _Type('num'));
+        expect(flow.promotedType(x).type, 'num');
+        // Check that it's a type of interest by promoting and de-promoting.
+        h.if_(h.isType(h.variableRead(x), 'int'), () {
+          expect(flow.promotedType(x).type, 'int');
+          flow.write(x, _Type('num'));
+          expect(flow.promotedType(x).type, 'num');
+        });
+      });
+    });
+
+    test('promote does not promote to a non-subtype', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'num?');
+      h.run((flow) {
+        flow.declare(x, true);
+        expect(flow.promotedType(x), isNull);
+        flow.promote(x, _Type('String'));
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
+    test('promote does not promote if variable is write-captured', () {
+      var h = _Harness();
+      var x = h.addVar('x', 'num?');
+      var functionNode = _Node();
+      h.assignedVariables(
+          (vars) => vars.function(functionNode, () => vars.write(x)));
+      h.run((flow) {
+        flow.declare(x, true);
+        expect(flow.promotedType(x), isNull);
+        flow.functionExpression_begin(functionNode);
+        flow.write(x, _Type('num'));
+        flow.functionExpression_end();
+        flow.promote(x, _Type('num'));
+        expect(flow.promotedType(x), isNull);
+      });
+    });
+
     test('promotedType handles not-yet-seen variables', () {
       // Note: this is needed for error recovery in the analyzer.
       var h = _Harness();
@@ -2052,6 +2297,7 @@
         h.promote(x, 'int');
         expect(flow.promotedType(x).type, 'int');
         // if (false) {
+        flow.ifStatement_conditionBegin();
         var falseExpression = _Expression();
         flow.booleanLiteral(falseExpression, false);
         flow.ifStatement_thenBegin(falseExpression);
@@ -2099,59 +2345,200 @@
     });
   });
 
+  group('Reachability', () {
+    test('initial state', () {
+      expect(Reachability.initial.parent, isNull);
+      expect(Reachability.initial.locallyReachable, true);
+      expect(Reachability.initial.overallReachable, true);
+    });
+
+    test('split', () {
+      var reachableSplit = Reachability.initial.split();
+      expect(reachableSplit.parent, same(Reachability.initial));
+      expect(reachableSplit.overallReachable, true);
+      expect(reachableSplit.locallyReachable, true);
+      var unreachable = reachableSplit.setUnreachable();
+      var unreachableSplit = unreachable.split();
+      expect(unreachableSplit.parent, same(unreachable));
+      expect(unreachableSplit.overallReachable, false);
+      expect(unreachableSplit.locallyReachable, true);
+    });
+
+    test('unsplit', () {
+      var base = Reachability.initial.split();
+      var reachableSplit = base.split();
+      var reachableSplitUnsplit = reachableSplit.unsplit();
+      expect(reachableSplitUnsplit.parent, same(base.parent));
+      expect(reachableSplitUnsplit.overallReachable, true);
+      expect(reachableSplitUnsplit.locallyReachable, true);
+      var reachableSplitUnreachable = reachableSplit.setUnreachable();
+      var reachableSplitUnreachableUnsplit =
+          reachableSplitUnreachable.unsplit();
+      expect(reachableSplitUnreachableUnsplit.parent, same(base.parent));
+      expect(reachableSplitUnreachableUnsplit.overallReachable, false);
+      expect(reachableSplitUnreachableUnsplit.locallyReachable, false);
+      var unreachable = base.setUnreachable();
+      var unreachableSplit = unreachable.split();
+      var unreachableSplitUnsplit = unreachableSplit.unsplit();
+      expect(unreachableSplitUnsplit, same(unreachable));
+      var unreachableSplitUnreachable = unreachableSplit.setUnreachable();
+      var unreachableSplitUnreachableUnsplit =
+          unreachableSplitUnreachable.unsplit();
+      expect(unreachableSplitUnreachableUnsplit, same(unreachable));
+    });
+
+    test('setUnreachable', () {
+      var reachable = Reachability.initial.split();
+      var unreachable = reachable.setUnreachable();
+      expect(unreachable.parent, same(reachable.parent));
+      expect(unreachable.locallyReachable, false);
+      expect(unreachable.overallReachable, false);
+      expect(unreachable.setUnreachable(), same(unreachable));
+      var provisionallyReachable = unreachable.split();
+      var provisionallyUnreachable = provisionallyReachable.setUnreachable();
+      expect(
+          provisionallyUnreachable.parent, same(provisionallyReachable.parent));
+      expect(provisionallyUnreachable.locallyReachable, false);
+      expect(provisionallyUnreachable.overallReachable, false);
+      expect(provisionallyUnreachable.setUnreachable(),
+          same(provisionallyUnreachable));
+    });
+
+    test('restrict', () {
+      var previous = Reachability.initial.split();
+      var reachable = previous.split();
+      var unreachable = reachable.setUnreachable();
+      expect(Reachability.restrict(reachable, reachable), same(reachable));
+      expect(Reachability.restrict(reachable, unreachable), same(unreachable));
+      expect(Reachability.restrict(unreachable, reachable), same(unreachable));
+      expect(
+          Reachability.restrict(unreachable, unreachable), same(unreachable));
+    });
+
+    test('join', () {
+      var previous = Reachability.initial.split();
+      var reachable = previous.split();
+      var unreachable = reachable.setUnreachable();
+      expect(Reachability.join(reachable, reachable), same(reachable));
+      expect(Reachability.join(reachable, unreachable), same(reachable));
+      expect(Reachability.join(unreachable, reachable), same(reachable));
+      expect(Reachability.join(unreachable, unreachable), same(unreachable));
+    });
+  });
+
   group('State', () {
     var intVar = _Var('x', _Type('int'));
     var intQVar = _Var('x', _Type('int?'));
     var objectQVar = _Var('x', _Type('Object?'));
     var nullVar = _Var('x', _Type('Null'));
-    group('setReachable', () {
-      var unreachable = FlowModel<_Var, _Type>(false);
-      var reachable = FlowModel<_Var, _Type>(true);
+    group('setUnreachable', () {
+      var unreachable =
+          FlowModel<_Var, _Type>(Reachability.initial.setUnreachable());
+      var reachable = FlowModel<_Var, _Type>(Reachability.initial);
       test('unchanged', () {
-        expect(unreachable.setReachable(false), same(unreachable));
-        expect(reachable.setReachable(true), same(reachable));
+        expect(unreachable.setUnreachable(), same(unreachable));
       });
 
       test('changed', () {
-        void _check(FlowModel<_Var, _Type> initial, bool newReachability) {
-          var s = initial.setReachable(newReachability);
+        void _check(FlowModel<_Var, _Type> initial) {
+          var s = initial.setUnreachable();
           expect(s, isNot(same(initial)));
-          expect(s.reachable, newReachability);
+          expect(s.reachable.overallReachable, false);
           expect(s.variableInfo, same(initial.variableInfo));
         }
 
-        _check(unreachable, true);
-        _check(reachable, false);
+        _check(reachable);
+      });
+    });
+
+    test('split', () {
+      var s1 = FlowModel<_Var, _Type>(Reachability.initial);
+      var s2 = s1.split();
+      expect(s2.reachable.parent, same(s1.reachable));
+    });
+
+    test('unsplit', () {
+      var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+      var s2 = s1.unsplit();
+      expect(s2.reachable, same(Reachability.initial));
+    });
+
+    group('unsplitTo', () {
+      test('no change', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var result = s1.unsplitTo(s1.reachable.parent);
+        expect(result, same(s1));
+      });
+
+      test('unsplit once, reachable', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var s2 = s1.split();
+        var result = s2.unsplitTo(s1.reachable.parent);
+        expect(result.reachable, same(s1.reachable));
+      });
+
+      test('unsplit once, unreachable', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var s2 = s1.split().setUnreachable();
+        var result = s2.unsplitTo(s1.reachable.parent);
+        expect(result.reachable.locallyReachable, false);
+        expect(result.reachable.parent, same(s1.reachable.parent));
+      });
+
+      test('unsplit twice, reachable', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var s2 = s1.split();
+        var s3 = s2.split();
+        var result = s3.unsplitTo(s1.reachable.parent);
+        expect(result.reachable, same(s1.reachable));
+      });
+
+      test('unsplit twice, top unreachable', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var s2 = s1.split();
+        var s3 = s2.split().setUnreachable();
+        var result = s3.unsplitTo(s1.reachable.parent);
+        expect(result.reachable.locallyReachable, false);
+        expect(result.reachable.parent, same(s1.reachable.parent));
+      });
+
+      test('unsplit twice, previous unreachable', () {
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial.split());
+        var s2 = s1.split().setUnreachable();
+        var s3 = s2.split();
+        var result = s3.unsplitTo(s1.reachable.parent);
+        expect(result.reachable.locallyReachable, false);
+        expect(result.reachable.parent, same(s1.reachable.parent));
       });
     });
 
     group('tryPromoteForTypeCheck', () {
       test('unpromoted -> unchanged (same)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('int')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (supertype)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('Object')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> unchanged (unrelated)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intVar, _Type('String')).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryPromoteForTypeCheck(h, intQVar, _Type('int')).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           intQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int'])
         });
@@ -2159,7 +2546,7 @@
 
       test('promoted -> unchanged (same)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
@@ -2168,7 +2555,7 @@
 
       test('promoted -> unchanged (supertype)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 =
@@ -2178,7 +2565,7 @@
 
       test('promoted -> unchanged (unrelated)', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 =
@@ -2188,11 +2575,11 @@
 
       test('promoted -> subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
         var s2 = s1.tryPromoteForTypeCheck(h, objectQVar, _Type('int')).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['int?', 'int'], ofInterest: ['int?', 'int'])
@@ -2206,23 +2593,25 @@
       test('without declaration', () {
         // This should not happen in valid code, but test that we don't crash.
         var h = _Harness();
-        var s =
-            FlowModel<_Var, _Type>(true).write(objectQVar, _Type('Object?'), h);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .write(objectQVar, _Type('Object?'), h);
         expect(s.variableInfo[objectQVar], isNull);
       });
 
       test('unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, true);
         var s2 = s1.write(objectQVar, _Type('Object?'), h);
         expect(s2, same(s1));
       });
 
       test('marks as assigned', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, false);
         var s2 = s1.write(objectQVar, _Type('int?'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(
             s2.infoFor(objectQVar),
             _matchVariableModel(
@@ -2234,13 +2623,13 @@
 
       test('un-promotes fully', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         expect(s1.variableInfo, contains(objectQVar));
         var s2 = s1.write(objectQVar, _Type('int?'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: null,
@@ -2252,7 +2641,7 @@
 
       test('un-promotes partially, when no exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2266,7 +2655,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['num?', 'num'],
@@ -2278,7 +2667,7 @@
 
       test('un-promotes partially, when exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2294,7 +2683,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(
               chain: ['num?', 'num'],
@@ -2306,7 +2695,7 @@
 
       test('leaves promoted, when exact match', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2320,13 +2709,13 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('num'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, same(s1.variableInfo));
       });
 
       test('leaves promoted, when writing a subtype', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2340,7 +2729,7 @@
               unassigned: false)
         });
         var s2 = s1.write(objectQVar, _Type('int'), h);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, same(s1.variableInfo));
       });
 
@@ -2349,7 +2738,8 @@
           var h = _Harness();
           var x = _Var('x', _Type('int?'));
 
-          var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s1 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           expect(s1.variableInfo, {
             x: _matchVariableModel(chain: null),
           });
@@ -2364,7 +2754,8 @@
           var h = _Harness();
           var x = h.addVar('x', 'int?');
 
-          var s1 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s1 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           expect(s1.variableInfo, {
             x: _matchVariableModel(chain: null),
           });
@@ -2383,7 +2774,7 @@
 
         test('when promoted', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifTrue;
@@ -2404,7 +2795,7 @@
 
         test('when not promoted', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
               .ifFalse;
@@ -2426,7 +2817,7 @@
 
       test('Promotes to type of interest when not previously promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifFalse;
@@ -2447,7 +2838,7 @@
 
       test('Promotes to type of interest when previously promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(objectQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
             .ifTrue
@@ -2515,7 +2906,7 @@
           test('; first', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('B?'))
                 .ifFalse
@@ -2540,7 +2931,7 @@
           test('; second', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('A?'))
                 .ifFalse
@@ -2565,7 +2956,7 @@
           test('; nullable and non-nullable', () {
             var x = _Var('x', _Type('Object?'));
 
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(x, true)
                 .tryPromoteForTypeCheck(h, x, _Type('A'))
                 .ifFalse
@@ -2591,7 +2982,7 @@
         group('; ambiguous', () {
           test('; no promotion', () {
             var h = _Harness();
-            var s1 = FlowModel<_Var, _Type>(true)
+            var s1 = FlowModel<_Var, _Type>(Reachability.initial)
                 .declare(objectQVar, true)
                 .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
                 .ifFalse
@@ -2612,7 +3003,7 @@
 
         test('exact match', () {
           var h = _Harness();
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(objectQVar, true)
               .tryPromoteForTypeCheck(h, objectQVar, _Type('num?'))
               .ifFalse
@@ -2635,21 +3026,6 @@
           });
         });
       });
-
-      test('promote via initialization', () {
-        var h = _Harness();
-        var x = _Var('x', null, isLocalVariableWithoutDeclaredType: true);
-
-        var s1 = FlowModel<_Var, _Type>(true).declare(x, false);
-        expect(s1.variableInfo, {
-          x: _matchVariableModel(chain: null),
-        });
-
-        var s2 = s1.write(x, _Type('int'), h);
-        expect(s2.variableInfo, {
-          x: _matchVariableModel(chain: ['int']),
-        });
-      });
     });
 
     group('demotion, to NonNull', () {
@@ -2658,7 +3034,7 @@
 
         var h = _Harness();
 
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(x, true)
             .tryPromoteForTypeCheck(h, x, _Type('num?'))
             .ifTrue
@@ -2685,14 +3061,16 @@
       var objectQVar = _Var('x', _Type('Object?'));
 
       test('initialized', () {
-        var s = FlowModel<_Var, _Type>(true).declare(objectQVar, true);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, true);
         expect(s.variableInfo, {
           objectQVar: _matchVariableModel(assigned: true, unassigned: false),
         });
       });
 
       test('not initialized', () {
-        var s = FlowModel<_Var, _Type>(true).declare(objectQVar, false);
+        var s = FlowModel<_Var, _Type>(Reachability.initial)
+            .declare(objectQVar, false);
         expect(s.variableInfo, {
           objectQVar: _matchVariableModel(assigned: false, unassigned: true),
         });
@@ -2702,23 +3080,23 @@
     group('markNonNullable', () {
       test('unpromoted -> unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, intVar).ifTrue;
         expect(s2, same(s1));
       });
 
       test('unpromoted -> promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, intQVar).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.infoFor(intQVar),
             _matchVariableModel(chain: ['int'], ofInterest: []));
       });
 
       test('promoted -> unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
@@ -2727,11 +3105,11 @@
 
       test('promoted -> re-promoted', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int?'))
             .ifTrue;
         var s2 = s1.tryMarkNonNullable(h, objectQVar).ifTrue;
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar:
               _matchVariableModel(chain: ['int?', 'int'], ofInterest: ['int?'])
@@ -2740,9 +3118,9 @@
 
       test('promote to Never', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true);
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial);
         var s2 = s1.tryMarkNonNullable(h, nullVar).ifTrue;
-        expect(s2.reachable, false);
+        expect(s2.reachable.overallReachable, false);
         expect(s2.infoFor(nullVar),
             _matchVariableModel(chain: ['Never'], ofInterest: []));
       });
@@ -2756,7 +3134,7 @@
           var a = _Var('a', _Type('int'));
           var b = _Var('b', _Type('int'));
 
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(a, false)
               .declare(b, false)
               .write(a, _Type('int'), h);
@@ -2782,7 +3160,7 @@
           var b = _Var('b', _Type('int'));
           var c = _Var('c', _Type('int'));
 
-          var s1 = FlowModel<_Var, _Type>(true)
+          var s1 = FlowModel<_Var, _Type>(Reachability.initial)
               .declare(a, false)
               .declare(b, false)
               .declare(c, false)
@@ -2813,7 +3191,7 @@
     group('conservativeJoin', () {
       test('unchanged', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(intQVar, true)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue;
@@ -2823,13 +3201,13 @@
 
       test('written', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
             .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([intQVar], []);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
           intQVar: _matchVariableModel(chain: null, ofInterest: ['int'])
@@ -2838,13 +3216,13 @@
 
       test('write captured', () {
         var h = _Harness();
-        var s1 = FlowModel<_Var, _Type>(true)
+        var s1 = FlowModel<_Var, _Type>(Reachability.initial)
             .tryPromoteForTypeCheck(h, objectQVar, _Type('int'))
             .ifTrue
             .tryPromoteForTypeCheck(h, intQVar, _Type('int'))
             .ifTrue;
         var s2 = s1.conservativeJoin([], [intQVar]);
-        expect(s2.reachable, true);
+        expect(s2.reachable.overallReachable, true);
         expect(s2.variableInfo, {
           objectQVar: _matchVariableModel(chain: ['int'], ofInterest: ['int']),
           intQVar: _matchVariableModel(
@@ -2856,11 +3234,11 @@
     group('restrict', () {
       test('reachability', () {
         var h = _Harness();
-        var reachable = FlowModel<_Var, _Type>(true);
-        var unreachable = reachable.setReachable(false);
+        var reachable = FlowModel<_Var, _Type>(Reachability.initial);
+        var unreachable = reachable.setUnreachable();
         expect(reachable.restrict(h, reachable, Set()), same(reachable));
         expect(reachable.restrict(h, unreachable, Set()), same(unreachable));
-        expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
+        expect(unreachable.restrict(h, reachable, Set()), same(unreachable));
         expect(unreachable.restrict(h, unreachable, Set()), same(unreachable));
       });
 
@@ -2870,7 +3248,7 @@
         var b = _Var('b', _Type('int'));
         var c = _Var('c', _Type('int'));
         var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true)
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(a, false)
             .declare(b, false)
             .declare(c, false)
@@ -2890,7 +3268,7 @@
         var b = _Var('b', _Type('int'));
         var c = _Var('c', _Type('int'));
         var d = _Var('d', _Type('int'));
-        var s0 = FlowModel<_Var, _Type>(true)
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial)
             .declare(a, false)
             .declare(b, false)
             .declare(c, false)
@@ -2922,7 +3300,8 @@
             List<String> expectedChain) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var s0 = FlowModel<_Var, _Type>(true).declare(x, true);
+          var s0 =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           var s1 = thisType == null
               ? s0
               : s0.tryPromoteForTypeCheck(h, x, _Type(thisType)).ifTrue;
@@ -2974,7 +3353,8 @@
             List<String> inFinally, List<String> expectedResult) {
           var h = _Harness();
           var x = _Var('x', _Type('Object?'));
-          var initialModel = FlowModel<_Var, _Type>(true).declare(x, true);
+          var initialModel =
+              FlowModel<_Var, _Type>(Reachability.initial).declare(x, true);
           for (var t in before) {
             initialModel =
                 initialModel.tryPromoteForTypeCheck(h, x, _Type(t)).ifTrue;
@@ -3027,7 +3407,7 @@
       test('variable present in one state but not the other', () {
         var h = _Harness();
         var x = _Var('x', _Type('Object?'));
-        var s0 = FlowModel<_Var, _Type>(true);
+        var s0 = FlowModel<_Var, _Type>(Reachability.initial);
         var s1 = s0.declare(x, true);
         expect(s0.restrict(h, s1, {}), same(s0));
         expect(s0.restrict(h, s1, {x}), same(s0));
@@ -3385,6 +3765,142 @@
       });
     });
   });
+
+  group('merge', () {
+    var x = _Var('x', _Type('Object?'));
+    var intType = _Type('int');
+    var stringType = _Type('String');
+    const emptyMap = const <_Var, VariableModel<_Var, _Type>>{};
+
+    VariableModel<_Var, _Type> varModel(List<_Type> promotionChain,
+            {bool assigned = false}) =>
+        VariableModel<_Var, _Type>(
+          promotionChain,
+          promotionChain ?? [],
+          assigned,
+          !assigned,
+          false,
+        );
+
+    test('first is null', () {
+      var h = _Harness();
+      var s1 = FlowModel.withInfo(Reachability.initial.split(), {});
+      var result = FlowModel.merge(h, null, s1, emptyMap);
+      expect(result.reachable, same(Reachability.initial));
+    });
+
+    test('second is null', () {
+      var h = _Harness();
+      var splitPoint = Reachability.initial.split();
+      var afterSplit = splitPoint.split();
+      var s1 = FlowModel.withInfo(afterSplit, {});
+      var result = FlowModel.merge(h, s1, null, emptyMap);
+      expect(result.reachable, same(splitPoint));
+    });
+
+    test('both are reachable', () {
+      var h = _Harness();
+      var splitPoint = Reachability.initial.split();
+      var afterSplit = splitPoint.split();
+      var s1 = FlowModel.withInfo(afterSplit, {
+        x: varModel([intType])
+      });
+      var s2 = FlowModel.withInfo(afterSplit, {
+        x: varModel([stringType])
+      });
+      var result = FlowModel.merge(h, s1, s2, emptyMap);
+      expect(result.reachable, same(splitPoint));
+      expect(result.variableInfo[x].promotedTypes, isNull);
+    });
+
+    test('first is unreachable', () {
+      var h = _Harness();
+      var splitPoint = Reachability.initial.split();
+      var afterSplit = splitPoint.split();
+      var s1 = FlowModel.withInfo(afterSplit.setUnreachable(), {
+        x: varModel([intType])
+      });
+      var s2 = FlowModel.withInfo(afterSplit, {
+        x: varModel([stringType])
+      });
+      var result = FlowModel.merge(h, s1, s2, emptyMap);
+      expect(result.reachable, same(splitPoint));
+      expect(result.variableInfo, same(s2.variableInfo));
+    });
+
+    test('second is unreachable', () {
+      var h = _Harness();
+      var splitPoint = Reachability.initial.split();
+      var afterSplit = splitPoint.split();
+      var s1 = FlowModel.withInfo(afterSplit, {
+        x: varModel([intType])
+      });
+      var s2 = FlowModel.withInfo(afterSplit.setUnreachable(), {
+        x: varModel([stringType])
+      });
+      var result = FlowModel.merge(h, s1, s2, emptyMap);
+      expect(result.reachable, same(splitPoint));
+      expect(result.variableInfo, same(s1.variableInfo));
+    });
+
+    test('both are unreachable', () {
+      var h = _Harness();
+      var splitPoint = Reachability.initial.split();
+      var afterSplit = splitPoint.split();
+      var s1 = FlowModel.withInfo(afterSplit.setUnreachable(), {
+        x: varModel([intType])
+      });
+      var s2 = FlowModel.withInfo(afterSplit.setUnreachable(), {
+        x: varModel([stringType])
+      });
+      var result = FlowModel.merge(h, s1, s2, emptyMap);
+      expect(result.reachable.locallyReachable, false);
+      expect(result.reachable.parent, same(splitPoint.parent));
+      expect(result.variableInfo[x].promotedTypes, isNull);
+    });
+  });
+
+  group('inheritTested', () {
+    var x = _Var('x', _Type('Object?'));
+    var intType = _Type('int');
+    var stringType = _Type('String');
+    const emptyMap = const <_Var, VariableModel<_Var, _Type>>{};
+
+    VariableModel<_Var, _Type> model(List<_Type> typesOfInterest) =>
+        VariableModel<_Var, _Type>(null, typesOfInterest, true, false, false);
+
+    test('inherits types of interest from other', () {
+      var h = _Harness();
+      var m1 = FlowModel.withInfo(Reachability.initial, {
+        x: model([intType])
+      });
+      var m2 = FlowModel.withInfo(Reachability.initial, {
+        x: model([stringType])
+      });
+      expect(m1.inheritTested(h, m2).variableInfo[x].tested,
+          _matchOfInterestSet(['int', 'String']));
+    });
+
+    test('handles variable missing from other', () {
+      var h = _Harness();
+      var m1 = FlowModel.withInfo(Reachability.initial, {
+        x: model([intType])
+      });
+      var m2 = FlowModel.withInfo(Reachability.initial, emptyMap);
+      expect(m1.inheritTested(h, m2), same(m1));
+    });
+
+    test('returns identical model when no changes', () {
+      var h = _Harness();
+      var m1 = FlowModel.withInfo(Reachability.initial, {
+        x: model([intType])
+      });
+      var m2 = FlowModel.withInfo(Reachability.initial, {
+        x: model([intType])
+      });
+      expect(m1.inheritTested(h, m2), same(m1));
+    });
+  });
 }
 
 /// Returns the appropriate matcher for expecting an assertion error to be
@@ -3467,7 +3983,7 @@
   void function(_Node node, void Function() callback) {
     _assignedVariables.beginNode();
     callback();
-    _assignedVariables.endNode(node, isClosure: true);
+    _assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
   }
 
   void nest(_Node node, void Function() callback) {
@@ -3634,6 +4150,7 @@
   LazyExpression and(LazyExpression lhs, LazyExpression rhs) {
     return () {
       var expr = _Expression();
+      _flow.logicalBinaryOp_begin();
       _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: true);
       _flow.logicalBinaryOp_end(expr, rhs(), isAnd: true);
       return expr;
@@ -3644,6 +4161,12 @@
     callback(_AssignedVariablesHarness(_assignedVariables));
   }
 
+  LazyExpression booleanLiteral(bool value) => () {
+        var expr = _Expression();
+        _flow.booleanLiteral(expr, value);
+        return expr;
+      };
+
   @override
   TypeClassification classifyType(_Type type) {
     if (isSubtypeOf(type, _Type('Object'))) {
@@ -3661,6 +4184,7 @@
       LazyExpression cond, LazyExpression ifTrue, LazyExpression ifFalse) {
     return () {
       var expr = _Expression();
+      _flow.conditional_conditionBegin();
       _flow.conditional_thenBegin(cond());
       _flow.conditional_elseBegin(ifTrue());
       _flow.conditional_end(expr, ifFalse());
@@ -3706,6 +4230,7 @@
 
   /// Invokes flow analysis of an `if` statement with no `else` part.
   void if_(LazyExpression cond, void ifTrue()) {
+    _flow.ifStatement_conditionBegin();
     _flow.ifStatement_thenBegin(cond());
     ifTrue();
     _flow.ifStatement_end(false);
@@ -3713,6 +4238,7 @@
 
   /// Invokes flow analysis of an `if` statement with an `else` part.
   void ifElse(LazyExpression cond, void ifTrue(), void ifFalse()) {
+    _flow.ifStatement_conditionBegin();
     _flow.ifStatement_thenBegin(cond());
     ifTrue();
     _flow.ifStatement_elseBegin();
@@ -3726,11 +4252,6 @@
   }
 
   @override
-  bool isLocalVariableWithoutDeclaredType(_Var variable) {
-    return variable.isLocalVariableWithoutDeclaredType;
-  }
-
-  @override
   bool isNever(_Type type) {
     return type.type == 'Never';
   }
@@ -3806,6 +4327,7 @@
   LazyExpression or(LazyExpression lhs, LazyExpression rhs) {
     return () {
       var expr = _Expression();
+      _flow.logicalBinaryOp_begin();
       _flow.logicalBinaryOp_rightBegin(lhs(), isAnd: false);
       _flow.logicalBinaryOp_end(expr, rhs(), isAnd: false);
       return expr;
@@ -3892,13 +4414,8 @@
 class _Var {
   final String name;
   final _Type type;
-  final bool isLocalVariableWithoutDeclaredType;
 
-  _Var(
-    this.name,
-    this.type, {
-    this.isLocalVariableWithoutDeclaredType = false,
-  });
+  _Var(this.name, this.type);
 
   @override
   String toString() => '$type $name';
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/equality_operator.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/equality_operator.dart
index 195e679..30a2a57 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/equality_operator.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/equality_operator.dart
@@ -35,8 +35,9 @@
 }
 
 void nonNullableValue(int x) {
-  if (x == null) /*unreachable*/ {
-    /*stmt: unreachable*/ 1;
+  if (x == null) {
+    // Reachable since the value of x might come from legacy code
+    1;
   } else {
     2;
   }
@@ -67,8 +68,9 @@
 }
 
 void nonNullableTypeVar<T extends Object>(T x) {
-  if (x == null) /*unreachable*/ {
-    /*stmt: unreachable*/ 1;
+  if (x == null) {
+    // Reachable since the value of x might come from legacy code
+    1;
   } else {
     2;
   }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart
index 0cc336e..fa2053d 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/if_null.dart
@@ -11,20 +11,19 @@
 }
 
 void variable_if_null_unreachable(int i) {
-  i ?? /*unreachable*/ 0;
+  // Reachable since the value of i might come from legacy code
+  i ?? 0;
 }
 
 void variable_if_null_assign_unreachable(int i) {
-  // Note: CFE reports that the update to `i` is unreachable; analyzer does not.
-  // This is ok; what matters is that the RHS is unreachable.
-  /*cfe.update: unreachable*/ i ??= /*unreachable*/ 0;
+  // Reachable since the value of i might come from legacy code
+  i ??= 0;
 }
 
 void variable_if_null_assign_unreachable_due_to_promotion(int? i) {
   if (i == null) return;
-  // Note: CFE reports that the update to `i` is unreachable; analyzer does not.
-  // This is ok; what matters is that the RHS is unreachable.
-  /*cfe.update: unreachable*/ i ??= /*unreachable*/ 0;
+  // Reachable since the value of i might come from legacy code
+  i ??= 0;
 }
 
 /*member: topLevelNullable:doesNotComplete*/
@@ -44,14 +43,15 @@
 }
 
 void top_level_if_null_unreachable() {
-  topLevelNonNullGet ?? /*unreachable*/ 0;
+  // Reachable since the value returned by topLevelNonNullGet might come from
+  // legacy code
+  topLevelNonNullGet ?? 0;
 }
 
 void top_level_if_null_assign_unreachable() {
-  // Note: CFE reports that the update to `topLevelNonNullGet` is unreachable;
-  // analyzer does not.  This is ok; what matters is that the RHS is
-  // unreachable.
-  topLevelNonNullGet /*cfe.update: unreachable*/ ??= /*unreachable*/ 0;
+  // Reachable since the value returned by topLevelNonNullGet might come from
+  // legacy code
+  topLevelNonNullGet ??= 0;
 }
 
 class HasProperty<T> {
@@ -69,11 +69,13 @@
 }
 
 void property_if_null_unreachable(HasProperty<int> x) {
-  x.prop ?? /*unreachable*/ 0;
+  // Reachable since the value returned by prop might come from legacy code
+  x.prop ?? 0;
 }
 
 void property_if_null_assign_unreachable(HasProperty<int> x) {
-  x.prop ??= /*unreachable*/ 0;
+  // Reachable since the value returned by prop might come from legacy code
+  x.prop ??= 0;
 }
 
 void null_aware_property_if_null_reachable(HasProperty<int?>? x) {
@@ -85,12 +87,14 @@
 }
 
 void null_aware_property_if_null_not_shortened(HasProperty<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by prop might come from legacy code.
+  // Also since `??` doesn't participate in null shortening.
   x?.prop ?? 0;
 }
 
 void null_aware_property_if_null_assign_unreachable(HasProperty<int>? x) {
-  x?.prop ??= /*unreachable*/ 0;
+  // Reachable since the value returned by prop might come from legacy code.
+  x?.prop ??= 0;
 }
 
 class SuperIntQuestionProperty extends HasProperty<int?> {
@@ -105,11 +109,13 @@
 
 class SuperIntProperty extends HasProperty<int> {
   void if_null_unreachable() {
-    super.prop ?? /*unreachable*/ 0;
+    // Reachable since the value returned by prop might come from legacy code.
+    super.prop ?? 0;
   }
 
   void if_null_assign_unreachable() {
-    super.prop ??= /*unreachable*/ 0;
+    // Reachable since the value returned by prop might come from legacy code.
+    super.prop ??= 0;
   }
 }
 
@@ -130,11 +136,15 @@
 }
 
 void extended_property_if_null_unreachable(HasProperty<int> x) {
-  x.extendedProp ?? /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  x.extendedProp ?? 0;
 }
 
 void extended_property_if_null_assign_unreachable(HasProperty<int> x) {
-  x.extendedProp ??= /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  x.extendedProp ??= 0;
 }
 
 void null_aware_extended_property_if_null_reachable(HasProperty<int?>? x) {
@@ -147,13 +157,16 @@
 }
 
 void null_aware_extended_property_if_null_not_shortened(HasProperty<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code, and because `??` doesn't participate in null shortening.
   x?.extendedProp ?? 0;
 }
 
 void null_aware_extended_property_if_null_assign_unreachable(
     HasProperty<int>? x) {
-  x?.extendedProp ??= /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  x?.extendedProp ??= 0;
 }
 
 void explicit_extended_property_if_null_reachable(HasProperty<int?> x) {
@@ -165,11 +178,15 @@
 }
 
 void explicit_extended_property_if_null_unreachable(HasProperty<int> x) {
-  ExtensionProperty(x).extendedProp ?? /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  ExtensionProperty(x).extendedProp ?? 0;
 }
 
 void explicit_extended_property_if_null_assign_unreachable(HasProperty<int> x) {
-  ExtensionProperty(x).extendedProp ??= /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  ExtensionProperty(x).extendedProp ??= 0;
 }
 
 void null_aware_explicit_extended_property_if_null_reachable(
@@ -184,13 +201,16 @@
 
 void null_aware_explicit_extended_property_if_null_not_shortened(
     HasProperty<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code, and because `??` doesn't participate in null shortening.
   ExtensionProperty(x)?.extendedProp ?? 0;
 }
 
 void null_aware_explicit_extended_property_if_null_assign_unreachable(
     HasProperty<int>? x) {
-  ExtensionProperty(x)?.extendedProp ??= /*unreachable*/ 0;
+  // Reachable since the value returned by extendedProp might come from legacy
+  // code.
+  ExtensionProperty(x)?.extendedProp ??= 0;
 }
 
 class Indexable<T> {
@@ -204,7 +224,9 @@
 }
 
 void index_if_null_unreachable(Indexable<int> x) {
-  x[0] ?? /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x[0] ?? 0;
 }
 
 void index_if_null_assign_reachable(Indexable<int?> x) {
@@ -212,7 +234,9 @@
 }
 
 void index_if_null_assign_unreachable(Indexable<int> x) {
-  x[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x[0] ??= 0;
 }
 
 void null_aware_index_if_null_reachable(Indexable<int?>? x) {
@@ -220,7 +244,8 @@
 }
 
 void null_aware_index_if_null_unreachable(Indexable<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by operator[] might come from legacy
+  // code, and because `??` doesn't participate in null shortening.
   x?[0] ?? 0;
 }
 
@@ -229,7 +254,9 @@
 }
 
 void null_aware_index_if_null_assign_unreachable(Indexable<int>? x) {
-  x?[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x?[0] ??= 0;
 }
 
 class SuperIntQuestionIndex extends Indexable<int?> {
@@ -244,11 +271,15 @@
 
 class SuperIntIndex extends Indexable<int> {
   void if_null_unreachable() {
-    super[0] ?? /*unreachable*/ 0;
+    // Reachable since the value returned by operator[] might come from legacy
+    // code.
+    super[0] ?? 0;
   }
 
   void if_null_assign_unreachable() {
-    super[0] ??= /*unreachable*/ 0;
+    // Reachable since the value returned by operator[] might come from legacy
+    // code.
+    super[0] ??= 0;
   }
 }
 
@@ -269,11 +300,15 @@
 }
 
 void extended_index_if_null_unreachable(HasProperty<int> x) {
-  x[0] ?? /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x[0] ?? 0;
 }
 
 void extended_index_if_null_assign_unreachable(HasProperty<int> x) {
-  x[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x[0] ??= 0;
 }
 
 void null_aware_extended_index_if_null_reachable(HasProperty<int?>? x) {
@@ -285,12 +320,15 @@
 }
 
 void null_aware_extended_index_if_null_not_shortened(HasProperty<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by operator[] might come from legacy
+  // code, and because `??` doesn't participate in null shortening.
   x?[0] ?? 0;
 }
 
 void null_aware_extended_index_if_null_assign_unreachable(HasProperty<int>? x) {
-  x?[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  x?[0] ??= 0;
 }
 
 void explicit_extended_index_if_null_reachable(HasProperty<int?> x) {
@@ -302,11 +340,15 @@
 }
 
 void explicit_extended_index_if_null_unreachable(HasProperty<int> x) {
-  ExtensionIndex(x)[0] ?? /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  ExtensionIndex(x)[0] ?? 0;
 }
 
 void explicit_extended_index_if_null_assign_unreachable(HasProperty<int> x) {
-  ExtensionIndex(x)[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  ExtensionIndex(x)[0] ??= 0;
 }
 
 void null_aware_explicit_extended_index_if_null_reachable(
@@ -321,11 +363,14 @@
 
 void null_aware_explicit_extended_index_if_null_not_shortened(
     HasProperty<int>? x) {
-  // If `??` participated in null-shortening, `0` would be unreachable.
+  // Reachable since the value returned by operator[] might come from legacy
+  // code, and because `??` doesn't participate in null shortening.
   ExtensionIndex(x)?[0] ?? 0;
 }
 
 void null_aware_explicit_extended_index_if_null_assign_unreachable(
     HasProperty<int>? x) {
-  ExtensionIndex(x)?[0] ??= /*unreachable*/ 0;
+  // Reachable since the value returned by operator[] might come from legacy
+  // code.
+  ExtensionIndex(x)?[0] ??= 0;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart
index a204bf8..43c8e2e 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/reachability/data/null_aware_access.dart
@@ -7,10 +7,10 @@
   0;
 }
 
-/*member: index_unreachable:doesNotComplete*/
 void index_unreachable(List<int> f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?[throw ''];
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void cascaded_index_reachable(List<int>? f()) {
@@ -18,10 +18,10 @@
   0;
 }
 
-/*member: cascaded_index_unreachable:doesNotComplete*/
 void cascaded_index_unreachable(List<int> f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?..[throw ''];
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void method_invocation_reachable(int? f()) {
@@ -29,10 +29,10 @@
   0;
 }
 
-/*member: method_invocation_unreachable:doesNotComplete*/
 void method_invocation_unreachable(int f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?.remainder(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void cascaded_method_invocation_reachable(int? f()) {
@@ -40,10 +40,10 @@
   0;
 }
 
-/*member: cascaded_method_invocation_unreachable:doesNotComplete*/
 void cascaded_method_invocation_unreachable(int f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?..remainder(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void property_get_reachable(int? f()) {
@@ -51,10 +51,10 @@
   0;
 }
 
-/*member: property_get_unreachable:doesNotComplete*/
 void property_get_unreachable(int f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?.hashCode.remainder(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void cascaded_property_get_reachable(int? f()) {
@@ -62,10 +62,10 @@
   0;
 }
 
-/*member: cascaded_property_get_unreachable:doesNotComplete*/
 void cascaded_property_get_unreachable(int f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?..hashCode.remainder(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void property_get_invocation_reachable(List<void Function(dynamic)>? f()) {
@@ -76,13 +76,13 @@
   0;
 }
 
-/*member: property_get_invocation_unreachable:doesNotComplete*/
 void property_get_invocation_unreachable(List<void Function(dynamic)> f()) {
+  // Reachable since the value returned by f() might come from legacy code
   // We need a special test case for this because it parses like a method
   // invocation but the analyzer rewrites it as a property access followed by a
   // function expression invocation.
   f()?.first(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void cascaded_property_get_invocation_reachable(
@@ -94,14 +94,14 @@
   0;
 }
 
-/*member: cascaded_property_get_invocation_unreachable:doesNotComplete*/
 void cascaded_property_get_invocation_unreachable(
     List<void Function(dynamic)> f()) {
+  // Reachable since the value returned by f() might come from legacy code
   // We need a special test case for this because it parses like a method
   // invocation but the analyzer rewrites it as a property access followed by a
   // function expression invocation.
   f()?..first(throw '');
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 class C {
@@ -113,10 +113,10 @@
   0;
 }
 
-/*member: property_set_unreachable:doesNotComplete*/
 void property_set_unreachable(C f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?.field = throw '';
-  /*stmt: unreachable*/ 0;
+  0;
 }
 
 void cascaded_property_set_reachable(C? f()) {
@@ -124,8 +124,8 @@
   0;
 }
 
-/*member: cascaded_property_set_unreachable:doesNotComplete*/
 void cascaded_property_set_unreachable(C f()) {
+  // Reachable since the value returned by f() might come from legacy code
   f()?..field = throw '';
-  /*stmt: unreachable*/ 0;
+  0;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart
new file mode 100644
index 0000000..45304e0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void forEachStatement(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    for (x in [0]) {
+      /*int*/ x;
+    }
+  }
+}
+
+forEachElementInListLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return [
+      for (x in [0]) /*int*/ x
+    ];
+  }
+}
+
+forEachElementInMapLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return {
+      for (x in [0]) /*int*/ x: /*int*/ x
+    };
+  }
+}
+
+forEachElementInSetLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return {
+      for (x in [0]) /*int*/ x
+    };
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug43136.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug43136.dart
new file mode 100644
index 0000000..297392b
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug43136.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+List<int Function()> f(List<num> nums) {
+  List<int Function()> result = [];
+  for (var n in nums) {
+    if (n is int) {
+      result.add(() => /*int*/ n);
+    }
+  }
+  return result;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
index 9b8e497..4f93355 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/conditional.dart
@@ -29,3 +29,19 @@
   x is int? ? /*int?*/ x : /*num*/ x;
   x;
 }
+
+void conditional_join_then(bool b, Object x) {
+  if (b ? x is int : x is int) {
+    /*int*/ x;
+  } else {
+    x;
+  }
+}
+
+void conditional_join_else(bool b, Object x) {
+  if (b ? x is! int : x is! int) {
+    x;
+  } else {
+    /*int*/ x;
+  }
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
index de0fa50..1a8f3e9 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/if.dart
@@ -87,7 +87,12 @@
   if (v is int?) {
     v;
   } else {
-    /*Never*/ v;
+    // Type promotion never promotes a variable to type `Never`, since that
+    // could lead to code being deemed unreachable when in fact it is reachable
+    // due to mixed mode unsoundness.  (In this particular case mixed mode
+    // unsoundness couldn't cause this "else" block to be reached, but flow
+    // analysis isn't smart enough to know that.)
+    v;
   }
   v;
 }
@@ -96,7 +101,12 @@
   if (v is num?) {
     v;
   } else {
-    /*Never*/ v;
+    // Type promotion never promotes a variable to type `Never`, since that
+    // could lead to code being deemed unreachable when in fact it is reachable
+    // due to mixed mode unsoundness.  (In this particular case mixed mode
+    // unsoundness couldn't cause this "else" block to be reached, but flow
+    // analysis isn't smart enough to know that.)
+    v;
   }
   v;
 }
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
index 6425744..35f2d63 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/initialization.dart
@@ -8,7 +8,7 @@
 localVariable() {
   var x;
   x = 1;
-  /*int*/ x;
+  x;
   x = 2.3;
   x;
 }
@@ -35,10 +35,10 @@
   var x;
   if (a) {
     x = 0;
-    /*int*/ x;
+    x;
   } else {
     x = 1.2;
-    /*double*/ x;
+    x;
   }
   x;
 }
@@ -47,12 +47,95 @@
   var x;
   if (a) {
     x = 0;
-    /*int*/ x;
+    x;
   } else {
     x = 1;
-    /*int*/ x;
+    x;
   }
-  /*int*/ x;
+  x;
+}
+
+localVariable_initialized_nonNull() {
+  num? x = 0;
+  /*num*/ x;
+  x = null;
+  x;
+}
+
+localVariable_initialized_nonNull_final() {
+  final num? x = 0;
+  x;
+}
+
+localVariable_initialized_promoted_type_var<T>(T t) {
+  if (t is num) {
+    var x = /*T & num*/ t;
+    /*T & num*/ x;
+    // Check that it is a type of interest by promoting and then writing to it
+    if (/*T & num*/ x is int) {
+      /*T & int*/ x;
+      x = /*T & num*/ t;
+      /*T & num*/ x;
+    }
+  }
+}
+
+localVariable_initialized_unpromoted_type_var<T>(T t) {
+  var x = t;
+  x;
+  // Check that `T & Object` is a type of interest, by promoting and then
+  // writing to it
+  if (x is int && t is num) {
+    /*T & int*/ x;
+    x = /*T & num*/ t;
+    /*T & Object*/ x;
+  }
+}
+
+localVariable_initialized_unpromoted_type_var_with_bound<T extends num?>(T t) {
+  var x = t;
+  x;
+  // Check that `T & num` is a type of interest, by promoting and then writing
+  // to it
+  if (x is int && t is double) {
+    /*T & int*/ x;
+    x = /*T & double*/ t;
+    /*T & num*/ x;
+  }
+}
+
+localVariable_initialized_promoted_type_var_typed<T>(T t) {
+  if (t is num) {
+    // This should promote to `T & Object`, because that's the non-nullable
+    // version of T, but it shouldn't promote to `T & num`.
+    T x = /*T & num*/ t;
+    /*T & Object*/ x;
+    // Check that `T & Object` is a type of interest by promoting and then
+    // writing to it
+    if (/*T & Object*/ x is int) {
+      /*T & int*/ x;
+      x = /*T & num*/ t;
+      /*T & Object*/ x;
+    }
+  }
+}
+
+localVariable_initialized_promoted_type_var_final<T>(T t) {
+  if (t is num) {
+    final x = /*T & num*/ t;
+    /*T & num*/ x;
+    // Note: it's not observable whether it's a type of interest because we
+    // can't write to it again.
+  }
+}
+
+localVariable_initialized_promoted_type_var_final_typed<T>(T t) {
+  if (t is num) {
+    final T x = /*T & num*/ t;
+    x;
+    // Note: it's not observable whether it's a type of interest because we
+    // can't write to it again.
+  }
 }
 
 localVariable_notDefinitelyUnassigned(bool a) {
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/late_initializer.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/late_initializer.dart
new file mode 100644
index 0000000..9bd1cde
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/late_initializer.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test checks that a variable assigned in the initializer of a late
+// variable is considered captured, just as it would be if the assignment
+// appeared inside a closure.
+
+eagerVariableInitializerDoesNotCapture(Object x) {
+  f() {
+    if (x is String) {
+      // Promotion is ok because we know exactly when x might change.
+      /*String*/ x;
+    }
+  }
+
+  int y = (x = 0);
+  if (x is String) {
+    /*String*/ x;
+  }
+  f();
+}
+
+lateVariableInitializerCaptures(Object x) {
+  f() {
+    if (x is String) {
+      // x is not promoted because its value might change at any time.
+      x;
+    }
+  }
+
+  late int y = (x = 0);
+  if (x is String) {
+    // x is not promoted because its value might change at any time.
+    x;
+  }
+  f();
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/loop_type_of_interest.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/loop_type_of_interest.dart
new file mode 100644
index 0000000..81cb1b1
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/loop_type_of_interest.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that a type comparison happening in the body of a loop
+// causes the type to be of interest after the loop, regardless of the type of
+// loop.
+
+doLoop(Object o, bool f()) {
+  do {
+    if (o is int) print('');
+  } while (f());
+  o = 1;
+  /*int*/ o;
+}
+
+forEachLoop(Object o, List values) {
+  for (var _ in values) {
+    if (o is int) print('');
+  }
+  o = 1;
+  /*int*/ o;
+}
+
+forLoop(Object o, int count) {
+  for (int i = 0; i < count; i++) {
+    if (o is int) print('');
+  }
+  o = 1;
+  /*int*/ o;
+}
+
+whileloop(Object o, bool f()) {
+  while (f()) {
+    if (o is int) print('');
+  }
+  o = 1;
+  /*int*/ o;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart
new file mode 100644
index 0000000..31091b0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/mixed_if_null_and_null_aware.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test verifies that we don't crash when trying to analyze an expression
+// that combines if-null with null-aware access.
+
+f(int? i, List? l) => i ?? l?.length;
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
new file mode 100644
index 0000000..21f9263
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/promotion_in_dead_code.dart
@@ -0,0 +1,289 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// These tests verify that the kinds of constructs we expect to cause type
+// promotion continue to function properly even when used inside unreachable
+// code.
+
+abstract class C {
+  void f(Object x, Object y);
+}
+
+andExpression_alwaysFalse(Object o) {
+  return;
+  o is! int && (throw 'x');
+  /*int*/ o;
+}
+
+andExpression_alwaysTrue(Object o) {
+  return;
+  true && (o is int || (throw 'x'));
+  /*int*/ o;
+}
+
+andExpression_lhsAlwaysTrue(Object o) {
+  return;
+  if (true && o is! int) {
+    o;
+  } else {
+    /*int*/ o;
+  }
+}
+
+andExpression_rhsAlwaysTrue(Object o) {
+  return;
+  if (o is! int && true) {
+    o;
+  } else {
+    /*int*/ o;
+  }
+}
+
+assertAlwaysThrows(Object o, Object p, bool Function(Object, Object) f) {
+  if (o is! int) return;
+  return;
+  assert(f(o = p, throw 'x'));
+  /*int*/ o;
+}
+
+class AssertAlwaysThrows_Constructor {
+  Object a;
+  Object b;
+
+  AssertAlwaysThrows_Constructor(
+      Object o, Object p, bool Function(Object, Object) f)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert(f(o = p, throw 'x')) {
+    /*int*/ o;
+  }
+}
+
+assertFailsButMessageRepromotes(Object? o) {
+  if (o is! int) return;
+  return;
+  assert((o = null) != null, o is int ? 'ok' : throw 'x');
+  /*int*/ o;
+}
+
+class AssertFailsButMessageRepromotes_Constructor {
+  Object a;
+  Object b;
+
+  AssertFailsButMessageRepromotes_Constructor(Object? o)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert((o = null) != null, o is int ? 'ok' : throw 'x') {
+    /*int*/ o;
+  }
+}
+
+assertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b) {
+  if (o is! int) return;
+  return;
+  assert(b, throw (o = p));
+  /*int*/ o;
+}
+
+class AssertMessageDepromotesButAlwaysThrows {
+  Object a;
+  Object b;
+
+  AssertMessageDepromotesButAlwaysThrows(Object o, Object p, bool b)
+      : a = o is int ? true : throw 'x',
+        b = throw 'x',
+        assert(b, throw (o = p)) {
+    /*int*/ o;
+  }
+}
+
+conditionalIs(Object o) {
+  return;
+  o is int ? null : throw 'bad';
+  /*int*/ o;
+}
+
+conditionalIsNot(Object o) {
+  return;
+  o is! int ? throw 'bad' : null;
+  /*int*/ o;
+}
+
+conditionalJoinFalse(Object o, bool b) {
+  return;
+  if (b ? o is! int : o is! int) return;
+  /*int*/ o;
+}
+
+conditionalJoinTrue(Object o, bool b) {
+  return;
+  if (!(b ? o is int : o is int)) return;
+  /*int*/ o;
+}
+
+doBreak(Object o) {
+  return;
+  do {
+    if (o is int) break;
+  } while (true);
+  /*int*/ o;
+}
+
+doContinue(Object o) {
+  return;
+  do {
+    if (o is int) continue;
+    return;
+  } while (false);
+  /*int*/ o;
+}
+
+doCondition(Object o) {
+  return;
+  do {} while (o is! int);
+  /*int*/ o;
+}
+
+forBreak(Object o) {
+  return;
+  for (;;) {
+    if (o is int) break;
+  }
+  /*int*/ o;
+}
+
+forContinue(Object o) {
+  return;
+  for (;; /*int*/ o) {
+    if (o is int) continue;
+    return;
+  }
+}
+
+ifIsNot(Object o) {
+  return;
+  if (o is! int) return;
+  /*int*/ o;
+}
+
+ifIsNot_listElement(Object o) {
+  return;
+  [if (o is! int) throw 'x'];
+  /*int*/ o;
+}
+
+ifIsNot_setElement(Object o) {
+  return;
+  ({if (o is! int) throw 'x'});
+  /*int*/ o;
+}
+
+ifIsNot_mapElement(Object o) {
+  return;
+  ({if (o is! int) 0: throw 'x'});
+  /*int*/ o;
+}
+
+ifNull(Object o, Object? p, Object q, void Function(Object, Object) f) {
+  return;
+  (o is int ? p : throw 'x') ?? f(o = q, throw 'x');
+  /*int*/ o;
+}
+
+labeledStatement(Object o) {
+  return;
+  label:
+  {
+    if (o is int) break label;
+    return;
+  }
+  /*int*/ o;
+}
+
+nullAwareAccess(Object o, C? p, Object q) {
+  return;
+  (o is int ? p : throw 'x')?.f(o = q, throw 'x');
+  /*int*/ o;
+}
+
+orExpression_alwaysFalse(Object o) {
+  return;
+  false || (o is! int && (throw 'x'));
+  /*int*/ o;
+}
+
+orExpression_alwaysTrue(Object o) {
+  return;
+  o is int || (throw 'x');
+  /*int*/ o;
+}
+
+orExpression_lhsAlwaysFalse(Object o) {
+  return;
+  if (false || o is int) {
+    /*int*/ o;
+  } else {
+    o;
+  }
+}
+
+orExpression_rhsAlwaysFalse(Object o) {
+  return;
+  if (o is int || false) {
+    /*int*/ o;
+  } else {
+    o;
+  }
+}
+
+switchPromoteInCase(Object o, int i) {
+  return;
+  switch (i) {
+    case 0:
+      if (o is! int) return;
+      break;
+    default:
+      return;
+  }
+  /*int*/ o;
+}
+
+switchPromoteInImplicitDefault(Object o, int i, Object p) {
+  return;
+  if (o is! int) return;
+  switch (i) {
+    case 0:
+      o = p;
+      return;
+  }
+  /*int*/ o;
+}
+
+tryCatchPromoteInTry(Object o) {
+  return;
+  try {
+    if (o is! int) return;
+  } catch (_) {
+    return;
+  }
+  /*int*/ o;
+}
+
+tryCatchPromoteInCatch(Object o) {
+  return;
+  try {
+    return;
+  } catch (_) {
+    if (o is! int) return;
+  }
+  /*int*/ o;
+}
+
+whileBreak(Object o) {
+  return;
+  while (true) {
+    if (o is int) break;
+  }
+  /*int*/ o;
+}
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
index d750821..1b4354d 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
@@ -12,7 +12,7 @@
   void promoteNullable(T? t) {
     T? s;
     if (t is int) {
-      s = /*T & int*/ t;
+      s = /*analyzer.T? & int*/ /*cfe.T & int*/ t;
     }
   }
 
@@ -50,7 +50,7 @@
 class F<S, T extends S> {
   void nonNull(T t) {
     if (t != null) {
-      /*T & S*/ t;
+      /*analyzer.T & S & Object*/ /*cfe.T & S*/ t;
     }
   }
 }
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 2355b50..922d458 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -13,33 +13,64 @@
         messageJsInteropEnclosingClassJSAnnotationContext,
         messageJsInteropIndexNotSupported,
         messageJsInteropNamedParameters,
-        messageJsInteropNonExternalConstructor;
+        messageJsInteropNonExternalConstructor,
+        messageJsInteropNonExternalMember;
 
 import 'src/js_interop.dart';
 
 class JsInteropChecks extends RecursiveVisitor<void> {
   final DiagnosticReporter<Message, LocatedMessage> _diagnosticsReporter;
+  bool _classHasJSAnnotation = false;
+  bool _libraryHasJSAnnotation = false;
 
   JsInteropChecks(this._diagnosticsReporter);
 
   @override
   void defaultMember(Member member) {
-    _checkMemberJSInteropAnnotation(member);
+    _checkJSInteropAnnotation(member);
+    // TODO(43530): Disallow having JS interop annotations on non-external
+    // members (class members or otherwise). Currently, they're being ignored.
     super.defaultMember(member);
   }
 
   @override
-  void visitProcedure(Procedure procedure) {
-    _checkMemberJSInteropAnnotation(procedure);
+  void visitClass(Class cls) {
+    _classHasJSAnnotation = hasJSInteropAnnotation(cls);
+    super.visitClass(cls);
+    _classHasJSAnnotation = false;
+  }
 
-    if (!procedure.isExternal || !isJSInteropMember(procedure)) return;
+  @override
+  void visitLibrary(Library lib) {
+    _libraryHasJSAnnotation = hasJSInteropAnnotation(lib);
+    super.visitLibrary(lib);
+    _libraryHasJSAnnotation = false;
+  }
+
+  @override
+  void visitProcedure(Procedure procedure) {
+    _checkJSInteropAnnotation(procedure);
+    if (_classHasJSAnnotation && !procedure.isExternal) {
+      // If not one of few exceptions, member is not allowed to exclude
+      // `external` inside of a JS interop class.
+      if (!(procedure.isAbstract ||
+          procedure.isFactory ||
+          procedure.isStatic)) {
+        _diagnosticsReporter.report(
+            messageJsInteropNonExternalMember,
+            procedure.fileOffset,
+            procedure.name.text.length,
+            procedure.location.file);
+      }
+    }
+    if (!_isJSInteropMember(procedure)) return;
 
     if (!procedure.isStatic &&
-        (procedure.name.name == '[]=' || procedure.name.name == '[]')) {
+        (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
       _diagnosticsReporter.report(
           messageJsInteropIndexNotSupported,
           procedure.fileOffset,
-          procedure.name.name.length,
+          procedure.name.text.length,
           procedure.location.file);
     }
 
@@ -65,17 +96,18 @@
 
   @override
   void visitConstructor(Constructor constructor) {
-    _checkMemberJSInteropAnnotation(constructor);
-
-    if (!isJSInteropMember(constructor)) return;
-
-    if (!constructor.isExternal && !constructor.isSynthetic) {
+    _checkJSInteropAnnotation(constructor);
+    if (_classHasJSAnnotation &&
+        !constructor.isExternal &&
+        !constructor.isSynthetic) {
+      // Non-synthetic constructors must be annotated with `external`.
       _diagnosticsReporter.report(
           messageJsInteropNonExternalConstructor,
           constructor.fileOffset,
-          constructor.name.name.length,
+          constructor.name.text.length,
           constructor.location.file);
     }
+    if (!_isJSInteropMember(constructor)) return;
 
     _checkNoNamedParameters(constructor.function);
   }
@@ -92,14 +124,18 @@
     }
   }
 
-  /// Reports an error if [m] has a JS interop annotation and is part of a class
-  /// that does not.
-  void _checkMemberJSInteropAnnotation(Member m) {
-    if (!hasJSInteropAnnotation(m)) return;
-    var enclosingClass = m.enclosingClass;
-    if (enclosingClass != null && !hasJSInteropAnnotation(enclosingClass)) {
+  /// Reports an error if [member] does not correctly use the JS interop
+  /// annotation or the keyword `external`.
+  void _checkJSInteropAnnotation(Member member) {
+    var enclosingClass = member.enclosingClass;
+
+    if (!_classHasJSAnnotation &&
+        enclosingClass != null &&
+        hasJSInteropAnnotation(member)) {
+      // If in a class that is not JS interop, this member is not allowed to be
+      // JS interop.
       _diagnosticsReporter.report(messageJsInteropEnclosingClassJSAnnotation,
-          m.fileOffset, m.name.name.length, m.location.file,
+          member.fileOffset, member.name.text.length, member.location.file,
           context: <LocatedMessage>[
             messageJsInteropEnclosingClassJSAnnotationContext.withLocation(
                 enclosingClass.location.file,
@@ -108,4 +144,15 @@
           ]);
     }
   }
+
+  /// Returns whether [member] is considered to be a JS interop member.
+  bool _isJSInteropMember(Member member) {
+    if (!member.isExternal) return false;
+    if (_classHasJSAnnotation) return true;
+    if (!_classHasJSAnnotation && member.enclosingClass != null) return false;
+    // In the case where the member does not belong to any class, a JS
+    // annotation is not needed on the library to be considered JS interop as
+    // long as the member has an annotation.
+    return hasJSInteropAnnotation(member) || _libraryHasJSAnnotation;
+  }
 }
diff --git a/pkg/_js_interop_checks/lib/src/js_interop.dart b/pkg/_js_interop_checks/lib/src/js_interop.dart
index f8ea46f..33ab00b 100644
--- a/pkg/_js_interop_checks/lib/src/js_interop.dart
+++ b/pkg/_js_interop_checks/lib/src/js_interop.dart
@@ -9,17 +9,6 @@
 bool hasJSInteropAnnotation(Annotatable a) =>
     a.annotations.any(_isPublicJSAnnotation);
 
-/// Returns true if [m] belongs to a JS interop context. Checks if either the
-/// member or the surrounding context has a JS interop annotation.
-bool isJSInteropMember(Member m) {
-  if (hasJSInteropAnnotation(m)) return true;
-  var enclosingClass = m.enclosingClass;
-  if (enclosingClass != null) return hasJSInteropAnnotation(enclosingClass);
-  var enclosingLibrary = m.enclosingLibrary;
-  if (enclosingLibrary != null) return hasJSInteropAnnotation(enclosingLibrary);
-  return false;
-}
-
 /// Returns true if [m] belongs to an anonymous class.
 bool isAnonymousClassMember(Member m) {
   var enclosingClass = m.enclosingClass;
diff --git a/pkg/analysis_server/analysis_options.yaml b/pkg/analysis_server/analysis_options.yaml
index dd243d9..254951f 100644
--- a/pkg/analysis_server/analysis_options.yaml
+++ b/pkg/analysis_server/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
+include: package:pedantic/analysis_options.1.9.0.yaml
 
 analyzer:
   # This currently finds ~1,200 implicit-casts issues when enabled.
@@ -15,25 +15,13 @@
 
 linter:
   rules:
+    - await_only_futures
+    - avoid_single_cascade_in_expression_statements
     - empty_statements
+    - iterable_contains_unrelated_type
+    - list_remove_unrelated_type
+    - prefer_initializing_formals
+    - prefer_typing_uninitialized_variables
     - unnecessary_brace_in_string_interps
-    #
-    # Delta from pedantic 1.8.0 to 1.9.0
-    #
-    - always_declare_return_types
-    - always_require_non_null_named_parameters
-    - annotate_overrides
-    - avoid_null_checks_in_equality_operators
-    - camel_case_extensions
-    - omit_local_variable_types
-    - prefer_adjacent_string_concatenation
-    - prefer_collection_literals
-    - prefer_conditional_assignment
-    - prefer_final_fields
-    - prefer_for_elements_to_map_fromIterable
-    - prefer_generic_function_type_aliases
-    - prefer_if_null_operators
-    - prefer_single_quotes
-    - prefer_spread_collections
-    - unnecessary_this
-    - use_function_type_syntax_for_parameters
+    - unnecessary_overrides
+    - void_checks
diff --git a/pkg/analysis_server/benchmark/integration/input_converter.dart b/pkg/analysis_server/benchmark/integration/input_converter.dart
index 5c04dd7..7f7ca06 100644
--- a/pkg/analysis_server/benchmark/integration/input_converter.dart
+++ b/pkg/analysis_server/benchmark/integration/input_converter.dart
@@ -334,7 +334,7 @@
 
 class _InputSink extends ChunkedConversionSink<String> {
   final Converter<String, Operation> converter;
-  final outSink;
+  final Sink<Operation> outSink;
 
   _InputSink(this.converter, this.outSink);
 
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 8af47db..37b095d9 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.29.0
+  1.30.0
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -2267,6 +2267,13 @@
       Return the set of fixes that are available for the errors at
       a given offset in a given file.
     </p>
+    <p>
+      If a request is made for a file which does not exist, or
+      which is not currently subject to analysis (e.g. because it
+      is not associated with any analysis root specified to
+      analysis.setAnalysisRoots), an error of type
+      <tt>GET_FIXES_INVALID_FILE</tt> will be generated.
+    </p>
     
     
   <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
@@ -5216,6 +5223,13 @@
           which does not match a file currently subject to
           analysis.
         </p>
+      </dd><dt class="value">GET_FIXES_INVALID_FILE</dt><dd>
+        
+        <p>
+          An "edit.getFixes" request specified a FilePath
+          which does not match a file currently subject to
+          analysis.
+        </p>
       </dd><dt class="value">GET_IMPORTED_ELEMENTS_INVALID_FILE</dt><dd>
         
         <p>
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index 8842cc5..5c97433 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -118,7 +118,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['label'] = label ?? (throw 'label is required but was not set');
     return __result;
   }
@@ -507,7 +508,7 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (range != null) {
-      __result['range'] = range;
+      __result['range'] = range.toJson();
     }
     __result['name'] = name ?? (throw 'name is required but was not set');
     __result['kind'] = kind ?? (throw 'kind is required but was not set');
@@ -715,11 +716,12 @@
       __result['attributes'] = attributes;
     }
     if (dartElement != null) {
-      __result['dartElement'] = dartElement;
+      __result['dartElement'] = dartElement.toJson();
     }
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['codeRange'] =
-        codeRange ?? (throw 'codeRange is required but was not set');
+        codeRange?.toJson() ?? (throw 'codeRange is required but was not set');
     if (children != null) {
       __result['children'] = children;
     }
@@ -919,7 +921,7 @@
     __result['name'] = name ?? (throw 'name is required but was not set');
     __result['label'] = label ?? (throw 'label is required but was not set');
     if (valueRange != null) {
-      __result['valueRange'] = valueRange;
+      __result['valueRange'] = valueRange.toJson();
     }
     return __result;
   }
@@ -1045,10 +1047,11 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['element'] =
-        element ?? (throw 'element is required but was not set');
-    __result['range'] = range ?? (throw 'range is required but was not set');
+        element?.toJson() ?? (throw 'element is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['codeRange'] =
-        codeRange ?? (throw 'codeRange is required but was not set');
+        codeRange?.toJson() ?? (throw 'codeRange is required but was not set');
     if (children != null) {
       __result['children'] = children;
     }
@@ -1282,7 +1285,7 @@
     var __result = <String, dynamic>{};
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
     __result['outline'] =
-        outline ?? (throw 'outline is required but was not set');
+        outline?.toJson() ?? (throw 'outline is required but was not set');
     return __result;
   }
 
@@ -1376,7 +1379,7 @@
     var __result = <String, dynamic>{};
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
     __result['outline'] =
-        outline ?? (throw 'outline is required but was not set');
+        outline?.toJson() ?? (throw 'outline is required but was not set');
     return __result;
   }
 
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 1a6a820..6578de6 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -54,7 +54,8 @@
     if (label != null) {
       __result['label'] = label;
     }
-    __result['edit'] = edit ?? (throw 'edit is required but was not set');
+    __result['edit'] =
+        edit?.toJson() ?? (throw 'edit is required but was not set');
     return __result;
   }
 
@@ -317,13 +318,13 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (workspace != null) {
-      __result['workspace'] = workspace;
+      __result['workspace'] = workspace.toJson();
     }
     if (textDocument != null) {
-      __result['textDocument'] = textDocument;
+      __result['textDocument'] = textDocument.toJson();
     }
     if (window != null) {
-      __result['window'] = window;
+      __result['window'] = window.toJson();
     }
     if (experimental != null) {
       __result['experimental'] = experimental;
@@ -556,19 +557,19 @@
       __result['applyEdit'] = applyEdit;
     }
     if (workspaceEdit != null) {
-      __result['workspaceEdit'] = workspaceEdit;
+      __result['workspaceEdit'] = workspaceEdit.toJson();
     }
     if (didChangeConfiguration != null) {
-      __result['didChangeConfiguration'] = didChangeConfiguration;
+      __result['didChangeConfiguration'] = didChangeConfiguration.toJson();
     }
     if (didChangeWatchedFiles != null) {
-      __result['didChangeWatchedFiles'] = didChangeWatchedFiles;
+      __result['didChangeWatchedFiles'] = didChangeWatchedFiles.toJson();
     }
     if (symbol != null) {
-      __result['symbol'] = symbol;
+      __result['symbol'] = symbol.toJson();
     }
     if (executeCommand != null) {
-      __result['executeCommand'] = executeCommand;
+      __result['executeCommand'] = executeCommand.toJson();
     }
     if (workspaceFolders != null) {
       __result['workspaceFolders'] = workspaceFolders;
@@ -784,7 +785,7 @@
     var __result = <String, dynamic>{};
     __result['title'] = title ?? (throw 'title is required but was not set');
     if (kind != null) {
-      __result['kind'] = kind;
+      __result['kind'] = kind.toJson();
     }
     if (diagnostics != null) {
       __result['diagnostics'] = diagnostics;
@@ -793,10 +794,10 @@
       __result['isPreferred'] = isPreferred;
     }
     if (edit != null) {
-      __result['edit'] = edit;
+      __result['edit'] = edit.toJson();
     }
     if (command != null) {
-      __result['command'] = command;
+      __result['command'] = command.toJson();
     }
     return __result;
   }
@@ -949,7 +950,7 @@
       __result['dynamicRegistration'] = dynamicRegistration;
     }
     if (codeActionLiteralSupport != null) {
-      __result['codeActionLiteralSupport'] = codeActionLiteralSupport;
+      __result['codeActionLiteralSupport'] = codeActionLiteralSupport.toJson();
     }
     if (isPreferredSupport != null) {
       __result['isPreferredSupport'] = isPreferredSupport;
@@ -1132,8 +1133,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['codeActionKind'] =
-        codeActionKind ?? (throw 'codeActionKind is required but was not set');
+    __result['codeActionKind'] = codeActionKind?.toJson() ??
+        (throw 'codeActionKind is required but was not set');
     return __result;
   }
 
@@ -1530,11 +1531,12 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['context'] =
-        context ?? (throw 'context is required but was not set');
+        context?.toJson() ?? (throw 'context is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -1811,9 +1813,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (command != null) {
-      __result['command'] = command;
+      __result['command'] = command.toJson();
     }
     if (data != null) {
       __result['data'] = data;
@@ -2080,8 +2083,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -2455,8 +2458,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
-    __result['color'] = color ?? (throw 'color is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    __result['color'] =
+        color?.toJson() ?? (throw 'color is required but was not set');
     return __result;
   }
 
@@ -2566,7 +2571,7 @@
     var __result = <String, dynamic>{};
     __result['label'] = label ?? (throw 'label is required but was not set');
     if (textEdit != null) {
-      __result['textEdit'] = textEdit;
+      __result['textEdit'] = textEdit.toJson();
     }
     if (additionalTextEdits != null) {
       __result['additionalTextEdits'] = additionalTextEdits;
@@ -2714,10 +2719,12 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
-    __result['color'] = color ?? (throw 'color is required but was not set');
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['color'] =
+        color?.toJson() ?? (throw 'color is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -3001,10 +3008,10 @@
       __result['dynamicRegistration'] = dynamicRegistration;
     }
     if (completionItem != null) {
-      __result['completionItem'] = completionItem;
+      __result['completionItem'] = completionItem.toJson();
     }
     if (completionItemKind != null) {
-      __result['completionItemKind'] = completionItemKind;
+      __result['completionItemKind'] = completionItemKind.toJson();
     }
     if (contextSupport != null) {
       __result['contextSupport'] = contextSupport;
@@ -3171,7 +3178,7 @@
       __result['preselectSupport'] = preselectSupport;
     }
     if (tagSupport != null) {
-      __result['tagSupport'] = tagSupport;
+      __result['tagSupport'] = tagSupport.toJson();
     }
     return __result;
   }
@@ -3466,8 +3473,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['triggerKind'] =
-        triggerKind ?? (throw 'triggerKind is required but was not set');
+    __result['triggerKind'] = triggerKind?.toJson() ??
+        (throw 'triggerKind is required but was not set');
     if (triggerCharacter != null) {
       __result['triggerCharacter'] = triggerCharacter;
     }
@@ -3706,7 +3713,7 @@
     var __result = <String, dynamic>{};
     __result['label'] = label ?? (throw 'label is required but was not set');
     if (kind != null) {
-      __result['kind'] = kind;
+      __result['kind'] = kind.toJson();
     }
     if (tags != null) {
       __result['tags'] = tags;
@@ -3733,10 +3740,10 @@
       __result['insertText'] = insertText;
     }
     if (insertTextFormat != null) {
-      __result['insertTextFormat'] = insertTextFormat;
+      __result['insertTextFormat'] = insertTextFormat.toJson();
     }
     if (textEdit != null) {
-      __result['textEdit'] = textEdit;
+      __result['textEdit'] = textEdit.toJson();
     }
     if (additionalTextEdits != null) {
       __result['additionalTextEdits'] = additionalTextEdits;
@@ -3745,10 +3752,10 @@
       __result['commitCharacters'] = commitCharacters;
     }
     if (command != null) {
-      __result['command'] = command;
+      __result['command'] = command.toJson();
     }
     if (data != null) {
-      __result['data'] = data;
+      __result['data'] = data.toJson();
     }
     return __result;
   }
@@ -4393,12 +4400,12 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (context != null) {
-      __result['context'] = context;
+      __result['context'] = context.toJson();
     }
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -4890,9 +4897,9 @@
   static const jsonHandler =
       LspJsonHandler(CreateFile.canParse, CreateFile.fromJson);
 
-  CreateFile({@required this.kind, @required this.uri, this.options}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+  CreateFile({this.kind = 'create', @required this.uri, this.options}) {
+    if (kind != 'create') {
+      throw 'kind may only be the literal \'create\'';
     }
     if (uri == null) {
       throw 'uri is required but was not provided';
@@ -4921,7 +4928,7 @@
     __result['kind'] = kind ?? (throw 'kind is required but was not set');
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
     if (options != null) {
-      __result['options'] = options;
+      __result['options'] = options.toJson();
     }
     return __result;
   }
@@ -4938,8 +4945,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'create')) {
+          reporter.reportError('must be the literal \'create\'');
           return false;
         }
       } finally {
@@ -5290,10 +5297,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -5716,10 +5723,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -5915,9 +5922,9 @@
   static const jsonHandler =
       LspJsonHandler(DeleteFile.canParse, DeleteFile.fromJson);
 
-  DeleteFile({@required this.kind, @required this.uri, this.options}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+  DeleteFile({this.kind = 'delete', @required this.uri, this.options}) {
+    if (kind != 'delete') {
+      throw 'kind may only be the literal \'delete\'';
     }
     if (uri == null) {
       throw 'uri is required but was not provided';
@@ -5946,7 +5953,7 @@
     __result['kind'] = kind ?? (throw 'kind is required but was not set');
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
     if (options != null) {
-      __result['options'] = options;
+      __result['options'] = options.toJson();
     }
     return __result;
   }
@@ -5963,8 +5970,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'delete')) {
+          reporter.reportError('must be the literal \'delete\'');
           return false;
         }
       } finally {
@@ -6181,9 +6188,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (severity != null) {
-      __result['severity'] = severity;
+      __result['severity'] = severity.toJson();
     }
     if (code != null) {
       __result['code'] = code;
@@ -6369,7 +6377,7 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['location'] =
-        location ?? (throw 'location is required but was not set');
+        location?.toJson() ?? (throw 'location is required but was not set');
     __result['message'] =
         message ?? (throw 'message is required but was not set');
     return __result;
@@ -6694,8 +6702,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['contentChanges'] =
         contentChanges ?? (throw 'contentChanges is required but was not set');
     return __result;
@@ -7030,7 +7038,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['event'] = event ?? (throw 'event is required but was not set');
+    __result['event'] =
+        event?.toJson() ?? (throw 'event is required but was not set');
     return __result;
   }
 
@@ -7101,8 +7110,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     return __result;
   }
 
@@ -7173,8 +7182,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     return __result;
   }
 
@@ -7250,8 +7259,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (text != null) {
       __result['text'] = text;
     }
@@ -7487,8 +7496,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -7967,10 +7976,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['options'] =
-        options ?? (throw 'options is required but was not set');
+        options?.toJson() ?? (throw 'options is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -8180,9 +8189,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (kind != null) {
-      __result['kind'] = kind;
+      __result['kind'] = kind.toJson();
     }
     return __result;
   }
@@ -8465,10 +8475,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -8707,7 +8717,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (target != null) {
       __result['target'] = target;
     }
@@ -9014,8 +9025,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -9438,11 +9449,11 @@
     var __result = <String, dynamic>{};
     __result['ch'] = ch ?? (throw 'ch is required but was not set');
     __result['options'] =
-        options ?? (throw 'options is required but was not set');
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+        options?.toJson() ?? (throw 'options is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     return __result;
   }
 
@@ -9873,11 +9884,12 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['options'] =
-        options ?? (throw 'options is required but was not set');
+        options?.toJson() ?? (throw 'options is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -10164,13 +10176,15 @@
     if (detail != null) {
       __result['detail'] = detail;
     }
-    __result['kind'] = kind ?? (throw 'kind is required but was not set');
+    __result['kind'] =
+        kind?.toJson() ?? (throw 'kind is required but was not set');
     if (deprecated != null) {
       __result['deprecated'] = deprecated;
     }
-    __result['range'] = range ?? (throw 'range is required but was not set');
-    __result['selectionRange'] =
-        selectionRange ?? (throw 'selectionRange is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
+    __result['selectionRange'] = selectionRange?.toJson() ??
+        (throw 'selectionRange is required but was not set');
     if (children != null) {
       __result['children'] = children;
     }
@@ -10356,7 +10370,7 @@
       __result['dynamicRegistration'] = dynamicRegistration;
     }
     if (symbolKind != null) {
-      __result['symbolKind'] = symbolKind;
+      __result['symbolKind'] = symbolKind.toJson();
     }
     if (hierarchicalDocumentSymbolSupport != null) {
       __result['hierarchicalDocumentSymbolSupport'] =
@@ -10619,8 +10633,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -11419,7 +11433,7 @@
     __result['globPattern'] =
         globPattern ?? (throw 'globPattern is required but was not set');
     if (kind != null) {
-      __result['kind'] = kind;
+      __result['kind'] = kind.toJson();
     }
     return __result;
   }
@@ -11546,7 +11560,7 @@
       __result['endCharacter'] = endCharacter;
     }
     if (kind != null) {
-      __result['kind'] = kind;
+      __result['kind'] = kind.toJson();
     }
     return __result;
   }
@@ -11902,8 +11916,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -12304,7 +12318,7 @@
     __result['contents'] =
         contents ?? (throw 'contents is required but was not set');
     if (range != null) {
-      __result['range'] = range;
+      __result['range'] = range.toJson();
     }
     return __result;
   }
@@ -12561,10 +12575,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -12948,10 +12962,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -13198,7 +13212,10 @@
     final capabilities = json['capabilities'] != null
         ? ClientCapabilities.fromJson(json['capabilities'])
         : null;
-    final trace = json['trace'];
+    final trace = const {null, 'off', 'messages', 'verbose'}
+            .contains(json['trace'])
+        ? json['trace']
+        : throw '''${json['trace']} was not one of (null, 'off', 'messages', 'verbose')''';
     final workspaceFolders = json['workspaceFolders']
         ?.map((item) => item != null ? WorkspaceFolder.fromJson(item) : null)
         ?.cast<WorkspaceFolder>()
@@ -13264,7 +13281,7 @@
     var __result = <String, dynamic>{};
     __result['processId'] = processId;
     if (clientInfo != null) {
-      __result['clientInfo'] = clientInfo;
+      __result['clientInfo'] = clientInfo.toJson();
     }
     if (rootPath != null) {
       __result['rootPath'] = rootPath;
@@ -13273,8 +13290,8 @@
     if (initializationOptions != null) {
       __result['initializationOptions'] = initializationOptions;
     }
-    __result['capabilities'] =
-        capabilities ?? (throw 'capabilities is required but was not set');
+    __result['capabilities'] = capabilities?.toJson() ??
+        (throw 'capabilities is required but was not set');
     if (trace != null) {
       __result['trace'] = trace;
     }
@@ -13363,8 +13380,12 @@
       }
       reporter.push('trace');
       try {
-        if (obj['trace'] != null && !(obj['trace'] is String)) {
-          reporter.reportError('must be of type String');
+        if (obj['trace'] != null &&
+            !((obj['trace'] == 'off' ||
+                obj['trace'] == 'messages' ||
+                obj['trace'] == 'verbose'))) {
+          reporter.reportError(
+              'must be one of the literals \'off\', \'messages\', \'verbose\'');
           return false;
         }
       } finally {
@@ -13551,10 +13572,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['capabilities'] =
-        capabilities ?? (throw 'capabilities is required but was not set');
+    __result['capabilities'] = capabilities?.toJson() ??
+        (throw 'capabilities is required but was not set');
     if (serverInfo != null) {
-      __result['serverInfo'] = serverInfo;
+      __result['serverInfo'] = serverInfo.toJson();
     }
     return __result;
   }
@@ -13807,7 +13828,8 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['uri'] = uri ?? (throw 'uri is required but was not set');
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     return __result;
   }
 
@@ -13934,13 +13956,13 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (originSelectionRange != null) {
-      __result['originSelectionRange'] = originSelectionRange;
+      __result['originSelectionRange'] = originSelectionRange.toJson();
     }
     __result['targetUri'] =
         targetUri ?? (throw 'targetUri is required but was not set');
-    __result['targetRange'] =
-        targetRange ?? (throw 'targetRange is required but was not set');
-    __result['targetSelectionRange'] = targetSelectionRange ??
+    __result['targetRange'] = targetRange?.toJson() ??
+        (throw 'targetRange is required but was not set');
+    __result['targetSelectionRange'] = targetSelectionRange?.toJson() ??
         (throw 'targetSelectionRange is required but was not set');
     return __result;
   }
@@ -14068,7 +14090,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['type'] = type ?? (throw 'type is required but was not set');
+    __result['type'] =
+        type?.toJson() ?? (throw 'type is required but was not set');
     __result['message'] =
         message ?? (throw 'message is required but was not set');
     return __result;
@@ -14186,7 +14209,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['kind'] = kind ?? (throw 'kind is required but was not set');
+    __result['kind'] =
+        kind?.toJson() ?? (throw 'kind is required but was not set');
     __result['value'] = value ?? (throw 'value is required but was not set');
     return __result;
   }
@@ -14704,7 +14728,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['method'] = method ?? (throw 'method is required but was not set');
+    __result['method'] =
+        method?.toJson() ?? (throw 'method is required but was not set');
     if (params != null) {
       __result['params'] = params;
     }
@@ -15146,10 +15171,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     return __result;
   }
 
@@ -15357,7 +15382,7 @@
       __result['relatedInformation'] = relatedInformation;
     }
     if (tagSupport != null) {
-      __result['tagSupport'] = tagSupport;
+      __result['tagSupport'] = tagSupport.toJson();
     }
     if (versionSupport != null) {
       __result['versionSupport'] = versionSupport;
@@ -15663,8 +15688,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['start'] = start ?? (throw 'start is required but was not set');
-    __result['end'] = end ?? (throw 'end is required but was not set');
+    __result['start'] =
+        start?.toJson() ?? (throw 'start is required but was not set');
+    __result['end'] =
+        end?.toJson() ?? (throw 'end is required but was not set');
     return __result;
   }
 
@@ -15754,7 +15781,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['placeholder'] =
         placeholder ?? (throw 'placeholder is required but was not set');
     return __result;
@@ -16090,11 +16118,11 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['context'] =
-        context ?? (throw 'context is required but was not set');
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+        context?.toJson() ?? (throw 'context is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -16587,12 +16615,12 @@
       LspJsonHandler(RenameFile.canParse, RenameFile.fromJson);
 
   RenameFile(
-      {@required this.kind,
+      {this.kind = 'rename',
       @required this.oldUri,
       @required this.newUri,
       this.options}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+    if (kind != 'rename') {
+      throw 'kind may only be the literal \'rename\'';
     }
     if (oldUri == null) {
       throw 'oldUri is required but was not provided';
@@ -16630,7 +16658,7 @@
     __result['oldUri'] = oldUri ?? (throw 'oldUri is required but was not set');
     __result['newUri'] = newUri ?? (throw 'newUri is required but was not set');
     if (options != null) {
-      __result['options'] = options;
+      __result['options'] = options.toJson();
     }
     return __result;
   }
@@ -16647,8 +16675,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'rename')) {
+          reporter.reportError('must be the literal \'rename\'');
           return false;
         }
       } finally {
@@ -16949,10 +16977,10 @@
     var __result = <String, dynamic>{};
     __result['newName'] =
         newName ?? (throw 'newName is required but was not set');
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -17213,7 +17241,8 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['id'] = id ?? (throw 'id is required but was not set');
-    __result['method'] = method ?? (throw 'method is required but was not set');
+    __result['method'] =
+        method?.toJson() ?? (throw 'method is required but was not set');
     if (params != null) {
       __result['params'] = params;
     }
@@ -17386,7 +17415,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['code'] = code ?? (throw 'code is required but was not set');
+    __result['code'] =
+        code?.toJson() ?? (throw 'code is required but was not set');
     __result['message'] =
         message ?? (throw 'message is required but was not set');
     if (data != null) {
@@ -17689,9 +17719,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (parent != null) {
-      __result['parent'] = parent;
+      __result['parent'] = parent.toJson();
     }
     return __result;
   }
@@ -17940,8 +17971,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['positions'] =
         positions ?? (throw 'positions is required but was not set');
     if (workDoneToken != null) {
@@ -18576,13 +18607,13 @@
       __result['textDocumentSync'] = textDocumentSync;
     }
     if (completionProvider != null) {
-      __result['completionProvider'] = completionProvider;
+      __result['completionProvider'] = completionProvider.toJson();
     }
     if (hoverProvider != null) {
       __result['hoverProvider'] = hoverProvider;
     }
     if (signatureHelpProvider != null) {
-      __result['signatureHelpProvider'] = signatureHelpProvider;
+      __result['signatureHelpProvider'] = signatureHelpProvider.toJson();
     }
     if (declarationProvider != null) {
       __result['declarationProvider'] = declarationProvider;
@@ -18609,10 +18640,10 @@
       __result['codeActionProvider'] = codeActionProvider;
     }
     if (codeLensProvider != null) {
-      __result['codeLensProvider'] = codeLensProvider;
+      __result['codeLensProvider'] = codeLensProvider.toJson();
     }
     if (documentLinkProvider != null) {
-      __result['documentLinkProvider'] = documentLinkProvider;
+      __result['documentLinkProvider'] = documentLinkProvider.toJson();
     }
     if (colorProvider != null) {
       __result['colorProvider'] = colorProvider;
@@ -18626,7 +18657,7 @@
     }
     if (documentOnTypeFormattingProvider != null) {
       __result['documentOnTypeFormattingProvider'] =
-          documentOnTypeFormattingProvider;
+          documentOnTypeFormattingProvider.toJson();
     }
     if (renameProvider != null) {
       __result['renameProvider'] = renameProvider;
@@ -18635,7 +18666,7 @@
       __result['foldingRangeProvider'] = foldingRangeProvider;
     }
     if (executeCommandProvider != null) {
-      __result['executeCommandProvider'] = executeCommandProvider;
+      __result['executeCommandProvider'] = executeCommandProvider.toJson();
     }
     if (selectionRangeProvider != null) {
       __result['selectionRangeProvider'] = selectionRangeProvider;
@@ -18644,7 +18675,7 @@
       __result['workspaceSymbolProvider'] = workspaceSymbolProvider;
     }
     if (workspace != null) {
-      __result['workspace'] = workspace;
+      __result['workspace'] = workspace.toJson();
     }
     if (experimental != null) {
       __result['experimental'] = experimental;
@@ -19065,7 +19096,7 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (workspaceFolders != null) {
-      __result['workspaceFolders'] = workspaceFolders;
+      __result['workspaceFolders'] = workspaceFolders.toJson();
     }
     return __result;
   }
@@ -19138,7 +19169,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['type'] = type ?? (throw 'type is required but was not set');
+    __result['type'] =
+        type?.toJson() ?? (throw 'type is required but was not set');
     __result['message'] =
         message ?? (throw 'message is required but was not set');
     return __result;
@@ -19243,7 +19275,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['type'] = type ?? (throw 'type is required but was not set');
+    __result['type'] =
+        type?.toJson() ?? (throw 'type is required but was not set');
     __result['message'] =
         message ?? (throw 'message is required but was not set');
     if (actions != null) {
@@ -19511,7 +19544,7 @@
       __result['dynamicRegistration'] = dynamicRegistration;
     }
     if (signatureInformation != null) {
-      __result['signatureInformation'] = signatureInformation;
+      __result['signatureInformation'] = signatureInformation.toJson();
     }
     if (contextSupport != null) {
       __result['contextSupport'] = contextSupport;
@@ -19690,7 +19723,7 @@
       __result['documentationFormat'] = documentationFormat;
     }
     if (parameterInformation != null) {
-      __result['parameterInformation'] = parameterInformation;
+      __result['parameterInformation'] = parameterInformation.toJson();
     }
     return __result;
   }
@@ -19813,15 +19846,15 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['triggerKind'] =
-        triggerKind ?? (throw 'triggerKind is required but was not set');
+    __result['triggerKind'] = triggerKind?.toJson() ??
+        (throw 'triggerKind is required but was not set');
     if (triggerCharacter != null) {
       __result['triggerCharacter'] = triggerCharacter;
     }
     __result['isRetrigger'] =
         isRetrigger ?? (throw 'isRetrigger is required but was not set');
     if (activeSignatureHelp != null) {
-      __result['activeSignatureHelp'] = activeSignatureHelp;
+      __result['activeSignatureHelp'] = activeSignatureHelp.toJson();
     }
     return __result;
   }
@@ -20096,12 +20129,12 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (context != null) {
-      __result['context'] = context;
+      __result['context'] = context.toJson();
     }
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -20662,12 +20695,13 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['name'] = name ?? (throw 'name is required but was not set');
-    __result['kind'] = kind ?? (throw 'kind is required but was not set');
+    __result['kind'] =
+        kind?.toJson() ?? (throw 'kind is required but was not set');
     if (deprecated != null) {
       __result['deprecated'] = deprecated;
     }
     __result['location'] =
-        location ?? (throw 'location is required but was not set');
+        location?.toJson() ?? (throw 'location is required but was not set');
     if (containerName != null) {
       __result['containerName'] = containerName;
     }
@@ -20867,7 +20901,7 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     __result['syncKind'] =
-        syncKind ?? (throw 'syncKind is required but was not set');
+        syncKind?.toJson() ?? (throw 'syncKind is required but was not set');
     __result['documentSelector'] = documentSelector;
     return __result;
   }
@@ -21140,70 +21174,70 @@
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
     if (synchronization != null) {
-      __result['synchronization'] = synchronization;
+      __result['synchronization'] = synchronization.toJson();
     }
     if (completion != null) {
-      __result['completion'] = completion;
+      __result['completion'] = completion.toJson();
     }
     if (hover != null) {
-      __result['hover'] = hover;
+      __result['hover'] = hover.toJson();
     }
     if (signatureHelp != null) {
-      __result['signatureHelp'] = signatureHelp;
+      __result['signatureHelp'] = signatureHelp.toJson();
     }
     if (declaration != null) {
-      __result['declaration'] = declaration;
+      __result['declaration'] = declaration.toJson();
     }
     if (definition != null) {
-      __result['definition'] = definition;
+      __result['definition'] = definition.toJson();
     }
     if (typeDefinition != null) {
-      __result['typeDefinition'] = typeDefinition;
+      __result['typeDefinition'] = typeDefinition.toJson();
     }
     if (implementation != null) {
-      __result['implementation'] = implementation;
+      __result['implementation'] = implementation.toJson();
     }
     if (references != null) {
-      __result['references'] = references;
+      __result['references'] = references.toJson();
     }
     if (documentHighlight != null) {
-      __result['documentHighlight'] = documentHighlight;
+      __result['documentHighlight'] = documentHighlight.toJson();
     }
     if (documentSymbol != null) {
-      __result['documentSymbol'] = documentSymbol;
+      __result['documentSymbol'] = documentSymbol.toJson();
     }
     if (codeAction != null) {
-      __result['codeAction'] = codeAction;
+      __result['codeAction'] = codeAction.toJson();
     }
     if (codeLens != null) {
-      __result['codeLens'] = codeLens;
+      __result['codeLens'] = codeLens.toJson();
     }
     if (documentLink != null) {
-      __result['documentLink'] = documentLink;
+      __result['documentLink'] = documentLink.toJson();
     }
     if (colorProvider != null) {
-      __result['colorProvider'] = colorProvider;
+      __result['colorProvider'] = colorProvider.toJson();
     }
     if (formatting != null) {
-      __result['formatting'] = formatting;
+      __result['formatting'] = formatting.toJson();
     }
     if (rangeFormatting != null) {
-      __result['rangeFormatting'] = rangeFormatting;
+      __result['rangeFormatting'] = rangeFormatting.toJson();
     }
     if (onTypeFormatting != null) {
-      __result['onTypeFormatting'] = onTypeFormatting;
+      __result['onTypeFormatting'] = onTypeFormatting.toJson();
     }
     if (rename != null) {
-      __result['rename'] = rename;
+      __result['rename'] = rename.toJson();
     }
     if (publishDiagnostics != null) {
-      __result['publishDiagnostics'] = publishDiagnostics;
+      __result['publishDiagnostics'] = publishDiagnostics.toJson();
     }
     if (foldingRange != null) {
-      __result['foldingRange'] = foldingRange;
+      __result['foldingRange'] = foldingRange.toJson();
     }
     if (selectionRange != null) {
-      __result['selectionRange'] = selectionRange;
+      __result['selectionRange'] = selectionRange.toJson();
     }
     return __result;
   }
@@ -21568,7 +21602,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     if (rangeLength != null) {
       __result['rangeLength'] = rangeLength;
     }
@@ -21754,8 +21789,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['edits'] = edits ?? (throw 'edits is required but was not set');
     return __result;
   }
@@ -22126,10 +22161,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     return __result;
   }
 
@@ -22694,7 +22729,7 @@
       __result['openClose'] = openClose;
     }
     if (change != null) {
-      __result['change'] = change;
+      __result['change'] = change.toJson();
     }
     if (willSave != null) {
       __result['willSave'] = willSave;
@@ -22822,7 +22857,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['range'] = range ?? (throw 'range is required but was not set');
+    __result['range'] =
+        range?.toJson() ?? (throw 'range is required but was not set');
     __result['newText'] =
         newText ?? (throw 'newText is required but was not set');
     return __result;
@@ -23101,10 +23137,10 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['position'] =
-        position ?? (throw 'position is required but was not set');
+        position?.toJson() ?? (throw 'position is required but was not set');
     if (workDoneToken != null) {
       __result['workDoneToken'] = workDoneToken;
     }
@@ -23655,8 +23691,8 @@
 
   Map<String, dynamic> toJson() {
     var __result = <String, dynamic>{};
-    __result['textDocument'] =
-        textDocument ?? (throw 'textDocument is required but was not set');
+    __result['textDocument'] = textDocument?.toJson() ??
+        (throw 'textDocument is required but was not set');
     __result['reason'] = reason ?? (throw 'reason is required but was not set');
     return __result;
   }
@@ -23732,13 +23768,13 @@
       WorkDoneProgressBegin.canParse, WorkDoneProgressBegin.fromJson);
 
   WorkDoneProgressBegin(
-      {@required this.kind,
+      {this.kind = 'begin',
       @required this.title,
       this.cancellable,
       this.message,
       this.percentage}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+    if (kind != 'begin') {
+      throw 'kind may only be the literal \'begin\'';
     }
     if (title == null) {
       throw 'title is required but was not provided';
@@ -23813,8 +23849,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'begin')) {
+          reporter.reportError('must be the literal \'begin\'');
           return false;
         }
       } finally {
@@ -24052,9 +24088,9 @@
   static const jsonHandler = LspJsonHandler(
       WorkDoneProgressEnd.canParse, WorkDoneProgressEnd.fromJson);
 
-  WorkDoneProgressEnd({@required this.kind, this.message}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+  WorkDoneProgressEnd({this.kind = 'end', this.message}) {
+    if (kind != 'end') {
+      throw 'kind may only be the literal \'end\'';
     }
   }
   static WorkDoneProgressEnd fromJson(Map<String, dynamic> json) {
@@ -24090,8 +24126,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'end')) {
+          reporter.reportError('must be the literal \'end\'');
           return false;
         }
       } finally {
@@ -24397,9 +24433,9 @@
       WorkDoneProgressReport.canParse, WorkDoneProgressReport.fromJson);
 
   WorkDoneProgressReport(
-      {@required this.kind, this.cancellable, this.message, this.percentage}) {
-    if (kind == null) {
-      throw 'kind is required but was not provided';
+      {this.kind = 'report', this.cancellable, this.message, this.percentage}) {
+    if (kind != 'report') {
+      throw 'kind may only be the literal \'report\'';
     }
   }
   static WorkDoneProgressReport fromJson(Map<String, dynamic> json) {
@@ -24464,8 +24500,8 @@
           reporter.reportError('must not be null');
           return false;
         }
-        if (!(obj['kind'] is String)) {
-          reporter.reportError('must be of type String');
+        if (!(obj['kind'] == 'report')) {
+          reporter.reportError('must be the literal \'report\'');
           return false;
         }
       } finally {
@@ -24712,7 +24748,7 @@
       __result['resourceOperations'] = resourceOperations;
     }
     if (failureHandling != null) {
-      __result['failureHandling'] = failureHandling;
+      __result['failureHandling'] = failureHandling.toJson();
     }
     return __result;
   }
@@ -25117,7 +25153,7 @@
       __result['dynamicRegistration'] = dynamicRegistration;
     }
     if (symbolKind != null) {
-      __result['symbolKind'] = symbolKind;
+      __result['symbolKind'] = symbolKind.toJson();
     }
     return __result;
   }
diff --git a/pkg/analysis_server/lib/protocol/protocol.dart b/pkg/analysis_server/lib/protocol/protocol.dart
index d45f7d3..f995858 100644
--- a/pkg/analysis_server/lib/protocol/protocol.dart
+++ b/pkg/analysis_server/lib/protocol/protocol.dart
@@ -305,7 +305,7 @@
   /// with the given [id].  If [_result] is provided, it will be used as the
   /// result; otherwise an empty result will be used.  If an [error] is provided
   /// then the response will represent an error condition.
-  Response(this.id, {Map<String, Object> result, this.error}) : result = result;
+  Response(this.id, {this.result, this.error});
 
   /// Create and return the `DEBUG_PORT_COULD_NOT_BE_OPENED` error response.
   Response.debugPortCouldNotBeOpened(Request request, dynamic error)
@@ -366,6 +366,13 @@
                 'Error during `analysis.getErrors`: invalid file.'));
 
   /// Initialize a newly created instance to represent the
+  /// GET_FIXES_INVALID_FILE error condition.
+  Response.getFixesInvalidFile(Request request)
+      : this(request.id,
+            error: RequestError(RequestErrorCode.GET_FIXES_INVALID_FILE,
+                'Error during `edit.getFixes`: invalid file.'));
+
+  /// Initialize a newly created instance to represent the
   /// GET_IMPORTED_ELEMENTS_INVALID_FILE error condition.
   Response.getImportedElementsInvalidFile(Request request)
       : this(request.id,
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 8bfb877..25f5a64 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.29.0';
+const String PROTOCOL_VERSION = '1.30.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 51ece87..06c3551 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -17810,6 +17810,7 @@
 ///   FORMAT_INVALID_FILE
 ///   FORMAT_WITH_ERRORS
 ///   GET_ERRORS_INVALID_FILE
+///   GET_FIXES_INVALID_FILE
 ///   GET_IMPORTED_ELEMENTS_INVALID_FILE
 ///   GET_KYTHE_ENTRIES_INVALID_FILE
 ///   GET_NAVIGATION_INVALID_FILE
@@ -17891,6 +17892,11 @@
   static const RequestErrorCode GET_ERRORS_INVALID_FILE =
       RequestErrorCode._('GET_ERRORS_INVALID_FILE');
 
+  /// An "edit.getFixes" request specified a FilePath which does not match a
+  /// file currently subject to analysis.
+  static const RequestErrorCode GET_FIXES_INVALID_FILE =
+      RequestErrorCode._('GET_FIXES_INVALID_FILE');
+
   /// An "analysis.getImportedElements" request specified a FilePath that does
   /// not match a file currently subject to analysis.
   static const RequestErrorCode GET_IMPORTED_ELEMENTS_INVALID_FILE =
@@ -18022,6 +18028,7 @@
     FORMAT_INVALID_FILE,
     FORMAT_WITH_ERRORS,
     GET_ERRORS_INVALID_FILE,
+    GET_FIXES_INVALID_FILE,
     GET_IMPORTED_ELEMENTS_INVALID_FILE,
     GET_KYTHE_ENTRIES_INVALID_FILE,
     GET_NAVIGATION_INVALID_FILE,
@@ -18076,6 +18083,8 @@
         return FORMAT_WITH_ERRORS;
       case 'GET_ERRORS_INVALID_FILE':
         return GET_ERRORS_INVALID_FILE;
+      case 'GET_FIXES_INVALID_FILE':
+        return GET_FIXES_INVALID_FILE;
       case 'GET_IMPORTED_ELEMENTS_INVALID_FILE':
         return GET_IMPORTED_ELEMENTS_INVALID_FILE;
       case 'GET_KYTHE_ENTRIES_INVALID_FILE':
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 3e87f9c..2c9e1e4 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -639,9 +639,6 @@
   /// ML completion is enabled if this is non-null.
   String completionModelFolder;
 
-  /// Whether to enable parsing via the Fasta parser.
-  bool useFastaParser = true;
-
   /// Return `true` if the new relevance computations should be used when
   /// computing code completion suggestions.
   bool useNewRelevance = true;
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index c56feb0..e18292c 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -162,7 +162,6 @@
       sdkLanguageVersion: analyzer_features.ExperimentStatus.currentVersion,
       flags: options.enabledExperiments,
     );
-    defaultContextOptions.useFastaParser = options.useFastaParser;
 
     {
       var name = options.newAnalysisDriverLog;
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 26e9582..7864fa2 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -107,7 +107,7 @@
           });
 
           performance.getDataInt('count').add(result.length);
-          return result;
+          return result.toList();
         },
       );
 
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index 6c2f036..8da528f 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.dart
@@ -80,11 +80,13 @@
 
   ParameterInfo _convertParam(ParameterElement param) {
     return ParameterInfo(
-        param.isOptionalPositional
-            ? ParameterKind.OPTIONAL
-            : param.isPositional
-                ? ParameterKind.REQUIRED
-                : ParameterKind.NAMED,
+        param.isOptionalNamed
+            ? ParameterKind.OPTIONAL_NAMED
+            : param.isOptionalPositional
+                ? ParameterKind.OPTIONAL_POSITIONAL
+                : param.isRequiredNamed
+                    ? ParameterKind.REQUIRED_NAMED
+                    : ParameterKind.REQUIRED_POSITIONAL,
         param.displayName,
         param.type.getDisplayString(withNullability: false),
         defaultValue: param.defaultValueCode);
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 9b61e31..1d527b0 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -7,6 +7,8 @@
 import 'dart:core';
 
 import 'package:analysis_server/src/plugin/notification_manager.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_parser.dart';
+import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
@@ -20,6 +22,8 @@
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
+import 'package:analyzer/src/lint/linter.dart';
+import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/manifest/manifest_validator.dart';
 import 'package:analyzer/src/pubspec/pubspec_validator.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -104,10 +108,9 @@
   /// added to the context.
   Map<String, Source> sources = HashMap<String, Source>();
 
-  ContextInfo(ContextManagerImpl contextManager, this.parent, Folder folder,
+  ContextInfo(ContextManagerImpl contextManager, this.parent, this.folder,
       File packagespecFile, this.disposition)
-      : folder = folder,
-        pathFilter = PathFilter(
+      : pathFilter = PathFilter(
             folder.path, null, contextManager.resourceProvider.pathContext) {
     packageDescriptionPath = packagespecFile.path;
     parent.children.add(this);
@@ -328,6 +331,9 @@
 /// Class that maintains a mapping from included/excluded paths to a set of
 /// folders that should correspond to analysis contexts.
 class ContextManagerImpl implements ContextManager {
+  /// The name of the data file used to specify data-driven fixes.
+  static const String dataFileName = 'fix_data.yaml';
+
   /// The name of the `doc` directory.
   static const String DOC_DIR_NAME = 'doc';
 
@@ -738,6 +744,31 @@
   }
 
   /// Use the given analysis [driver] to analyze the content of the
+  /// data file at the given [path].
+  void _analyzeDataFile(AnalysisDriver driver, String path) {
+    List<protocol.AnalysisError> convertedErrors;
+    try {
+      var file = resourceProvider.getFile(path);
+      var packageName = file.parent.parent.shortName;
+      var content = _readFile(path);
+      var errorListener = RecordingErrorListener();
+      var errorReporter = ErrorReporter(errorListener, file.createSource());
+      var parser = TransformSetParser(errorReporter, packageName);
+      parser.parse(content);
+      var converter = AnalyzerConverter();
+      convertedErrors = converter.convertAnalysisErrors(errorListener.errors,
+          lineInfo: _computeLineInfo(content), options: driver.analysisOptions);
+    } catch (exception) {
+      // If the file cannot be analyzed, fall through to clear any previous
+      // errors.
+    }
+    callbacks.notificationManager.recordAnalysisErrors(
+        NotificationManager.serverId,
+        path,
+        convertedErrors ?? const <protocol.AnalysisError>[]);
+  }
+
+  /// Use the given analysis [driver] to analyze the content of the
   /// AndroidManifest file at the given [path].
   void _analyzeManifestFile(AnalysisDriver driver, String path) {
     List<protocol.AnalysisError> convertedErrors;
@@ -776,6 +807,41 @@
         var converter = AnalyzerConverter();
         convertedErrors = converter.convertAnalysisErrors(errors,
             lineInfo: lineInfo, options: driver.analysisOptions);
+
+        if (driver.analysisOptions.lint) {
+          var visitors = <LintRule, PubspecVisitor>{};
+          for (var linter in driver.analysisOptions.lintRules) {
+            if (linter is LintRule) {
+              var visitor = linter.getPubspecVisitor();
+              if (visitor != null) {
+                visitors[linter] = visitor;
+              }
+            }
+          }
+          // todo (pq): re-enable once `sort_pub_dependencies` is fixed
+          // see: https://github.com/dart-lang/linter/issues/2271
+          // see: See: https://github.com/dart-lang/sdk/issues/43529
+          //   if (visitors.isNotEmpty) {
+          //     var sourceUri = resourceProvider.pathContext.toUri(path);
+          //     var pubspecAst = Pubspec.parse(content,
+          //         sourceUrl: sourceUri, resourceProvider: resourceProvider);
+          //     var listener = RecordingErrorListener();
+          //     var reporter = ErrorReporter(listener,
+          //         resourceProvider.getFile(path).createSource(sourceUri),
+          //         isNonNullableByDefault: false);
+          //     for (var entry in visitors.entries) {
+          //       entry.key.reporter = reporter;
+          //       pubspecAst.accept(entry.value);
+          //     }
+          //     if (listener.errors.isNotEmpty) {
+          //       convertedErrors ??= <protocol.AnalysisError>[];
+          //       convertedErrors.addAll(converter.convertAnalysisErrors(
+          //           listener.errors,
+          //           lineInfo: lineInfo,
+          //           options: driver.analysisOptions));
+          //     }
+          //   }
+        }
       }
     } catch (exception) {
       // If the file cannot be analyzed, fall through to clear any previous
@@ -802,6 +868,19 @@
     }
   }
 
+  void _checkForDataFileUpdate(String path, ContextInfo info) {
+    if (_isDataFile(path)) {
+      var driver = info.analysisDriver;
+      if (driver == null) {
+        // I suspect that this happens as a result of a race condition: server
+        // has determined that the file (at [path]) is in a context, but hasn't
+        // yet created a driver for that context.
+        return;
+      }
+      _analyzeDataFile(driver, path);
+    }
+  }
+
   void _checkForManifestUpdate(String path, ContextInfo info) {
     if (_isManifest(path)) {
       var driver = info.analysisDriver;
@@ -949,6 +1028,11 @@
     if (optionsFile != null) {
       _analyzeAnalysisOptionsFile(info.analysisDriver, optionsFile.path);
     }
+    var dataFile =
+        folder.getChildAssumingFolder('lib').getChildAssumingFile(dataFileName);
+    if (dataFile.exists) {
+      _analyzeDataFile(info.analysisDriver, dataFile.path);
+    }
     var pubspecFile = folder.getChildAssumingFile(PUBSPEC_NAME);
     if (pubspecFile.exists) {
       _analyzePubspecFile(info.analysisDriver, pubspecFile.path);
@@ -1035,7 +1119,7 @@
   /// given [folder].
   SourceFactory _createSourceFactory(AnalysisOptions options, Folder folder) {
     var builder = callbacks.createContextBuilder(folder, options);
-    return builder.createSourceFactory(folder.path, options);
+    return builder.createSourceFactory(folder.path);
   }
 
   /// Clean up and destroy the context associated with the given folder.
@@ -1279,6 +1363,7 @@
     }
     _checkForPackagespecUpdate(path, info);
     _checkForAnalysisOptionsUpdate(path, info);
+    _checkForDataFileUpdate(path, info);
     _checkForPubspecUpdate(path, info);
     _checkForManifestUpdate(path, info);
   }
@@ -1308,6 +1393,10 @@
     return false;
   }
 
+  /// Return `true` if the [path] appears to be the name of the data file used
+  /// to specify data-driven fixes.
+  bool _isDataFile(String path) => pathContext.basename(path) == dataFileName;
+
   /// Returns `true` if the given [path] is excluded by [excludedPaths].
   bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path);
 
@@ -1398,7 +1487,7 @@
         callbacks.createContextBuilder(info.folder, defaultContextOptions);
     var options = builder.getAnalysisOptions(contextRoot,
         contextRoot: driver.contextRoot);
-    var factory = builder.createSourceFactory(contextRoot, options);
+    var factory = builder.createSourceFactory(contextRoot);
     driver.configure(analysisOptions: options, sourceFactory: factory);
     callbacks.analysisOptionsUpdated(driver);
   }
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 8ce7662..b702179 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -42,9 +42,11 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/results.dart' as engine;
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/error/codes.dart' as engine;
 import 'package:analyzer/src/exception/exception.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
@@ -105,15 +107,21 @@
         }
       }
 
-      var paths = <String>[];
-      for (var include in params.included) {
-        var resource = server.resourceProvider.getResource(include);
-        resource.collectDartFilePaths(paths);
-      }
-
       var workspace = DartChangeWorkspace(server.currentSessions);
       var processor = BulkFixProcessor(workspace);
-      var changeBuilder = await processor.fixErrorsInLibraries(paths);
+
+      String sdkPath;
+      var sdk = server.findSdk();
+      if (sdk is FolderBasedDartSdk) {
+        sdkPath = sdk.directory.path;
+      }
+      var collection = AnalysisContextCollectionImpl(
+        includedPaths: params.included,
+        resourceProvider: server.resourceProvider,
+        sdkPath: sdkPath,
+      );
+      var changeBuilder = await processor.fixErrors(collection.contexts);
+
       var response = EditBulkFixesResult(changeBuilder.sourceChange.edits)
           .toResponse(request.id);
       server.sendResponse(response);
@@ -280,6 +288,12 @@
     if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
       return;
     }
+
+    if (!server.contextManager.isInAnalysisRoot(file)) {
+      server.sendResponse(Response.getFixesInvalidFile(request));
+      return;
+    }
+
     //
     // Allow plugins to start computing fixes.
     //
@@ -555,7 +569,7 @@
     }
 
     // Prepare the file information.
-    var result = await server.getParsedUnit(file);
+    var result = server.getParsedUnit(file);
     if (result == null) {
       server.sendResponse(Response.fileNotAnalyzed(request, file));
       return;
@@ -1309,15 +1323,3 @@
 /// [_RefactoringManager] throws instances of this class internally to stop
 /// processing in a manager that was reset.
 class _ResetError {}
-
-extension ResourceExtension on Resource {
-  void collectDartFilePaths(List<String> paths) {
-    if (this is File && AnalysisEngine.isDartFileName(path)) {
-      paths.add(path);
-    } else if (this is Folder) {
-      for (var child in (this as Folder).getChildren()) {
-        child.collectDartFilePaths(paths);
-      }
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
index fff1df7..a4243a9 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
@@ -28,7 +28,7 @@
     }
   }
 
-  void processPackage(Folder pkgFolder) async {
+  Future<void> processPackage(Folder pkgFolder) async {
     for (var task in _codeTasks) {
       await task.processPackage(pkgFolder);
     }
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index ebf42b7..55bfaf5 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -7,6 +7,19 @@
 class LspClientConfiguration {
   final Map<String, dynamic> _settings = <String, dynamic>{};
 
+  List<String> get analysisExcludedFolders {
+    // This setting is documented as a string array, but because editors are
+    // unlikely to provide validation, support single strings for convenience.
+    final value = _settings['analysisExcludedFolders'];
+    if (value is String) {
+      return [value];
+    } else if (value is List && value.every((s) => s is String)) {
+      return value.cast<String>();
+    } else {
+      return const [];
+    }
+  }
+
   bool get enableSdkFormatter => _settings['enableSdkFormatter'] ?? true;
   int get lineLength => _settings['lineLength'];
 
@@ -17,6 +30,13 @@
   bool get previewCommitCharacters =>
       _settings['previewCommitCharacters'] ?? false;
 
+  /// Returns whether or not the provided new configuration changes any values
+  /// that would require analysis roots to be updated.
+  bool affectsAnalysisRoots(Map<String, dynamic> newConfig) {
+    return _settings['analysisExcludedFolders'] !=
+        newConfig['analysisExcludedFolders'];
+  }
+
   void replace(Map<String, dynamic> newConfig) {
     _settings
       ..clear()
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 5440da6..27abeb9 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 
 /// The characters that will cause the editor to automatically commit the selected
 /// completion item.
@@ -48,6 +49,9 @@
 /// Characters to trigger formatting when format-on-type is enabled.
 const dartTypeFormattingCharacters = ['}', ';'];
 
+/// A [ProgressToken] used for reporting progress when the server is analyzing.
+final analyzingProgressToken = Either2<num, String>.t2('ANALYZING');
+
 /// Constants for command IDs that are exchanged between LSP client/server.
 abstract class Commands {
   /// A list of all commands IDs that can be sent to the client to inform which
@@ -74,6 +78,8 @@
   static const PublishFlutterOutline =
       Method('dart/textDocument/publishFlutterOutline');
   static const Super = Method('dart/textDocument/super');
+  // TODO(dantup): Remove custom AnalyzerStatus status method soon as no clients
+  // should be relying on it and we now support proper $/progress events.
   static const AnalyzerStatus = Method(r'$/analyzerStatus');
 }
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 85f8c67..c1c00de 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -6,7 +6,9 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/services/correction/organize_imports.dart';
 
 class OrganizeImportsCommandHandler extends SimpleEditCommandHandler {
@@ -16,7 +18,8 @@
   String get commandName => 'Organize Imports';
 
   @override
-  Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
+  Future<ErrorOr<void>> handle(List<dynamic> arguments,
+      ProgressReporter reporter, CancellationToken cancellationToken) async {
     if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
       return ErrorOr.error(ResponseError(
         code: ServerErrorCodes.InvalidCommandArguments,
@@ -32,6 +35,11 @@
     final docIdentifier = server.getVersionedDocumentIdentifier(path);
 
     final result = await requireResolvedUnit(path);
+
+    if (cancellationToken.isCancellationRequested) {
+      return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
+    }
+
     return result.mapResult((result) {
       final code = result.content;
       final unit = result.unit;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index c81db2e..bd880eb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -6,11 +6,16 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+
+final _manager = _RefactorManager();
 
 class PerformRefactorCommandHandler extends SimpleEditCommandHandler {
   PerformRefactorCommandHandler(LspAnalysisServer server) : super(server);
@@ -19,7 +24,8 @@
   String get commandName => 'Perform Refactor';
 
   @override
-  Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
+  Future<ErrorOr<void>> handle(List<dynamic> arguments,
+      ProgressReporter reporter, CancellationToken cancellationToken) async {
     if (arguments == null ||
         arguments.length != 6 ||
         arguments[0] is! String || // kind
@@ -49,24 +55,50 @@
       return _getRefactoring(
               RefactoringKind(kind), result, offset, length, options)
           .mapResult((refactoring) async {
-        final status = await refactoring.checkAllConditions();
-
-        if (status.hasError) {
-          return error(ServerErrorCodes.RefactorFailed, status.message);
+        // If the token we were given is not cancellable, replace it with one that
+        // is for the rest of this request, as a future refactor may need to cancel
+        // this request.
+        if (cancellationToken is! CancelableToken) {
+          cancellationToken = CancelableToken();
         }
+        _manager.begin(cancellationToken);
 
-        final change = await refactoring.createChange();
+        try {
+          reporter.begin('Refactoring…');
+          final status = await refactoring.checkAllConditions();
 
-        // If the file changed while we were validating and preparing the change,
-        // we should fail to avoid sending bad edits.
-        if (docVersion != null &&
-            docVersion != server.getVersionedDocumentIdentifier(path).version) {
+          if (status.hasError) {
+            return error(ServerErrorCodes.RefactorFailed, status.message);
+          }
+
+          if (cancellationToken.isCancellationRequested) {
+            return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
+          }
+
+          final change = await refactoring.createChange();
+
+          if (cancellationToken.isCancellationRequested) {
+            return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
+          }
+
+          // If the file changed while we were validating and preparing the change,
+          // we should fail to avoid sending bad edits.
+          if (docVersion != null &&
+              docVersion !=
+                  server.getVersionedDocumentIdentifier(path).version) {
+            return error(ErrorCodes.ContentModified,
+                'Content was modified before refactor was applied');
+          }
+
+          final edit = createWorkspaceEdit(server, change.edits);
+          return await sendWorkspaceEditToClient(edit);
+        } on InconsistentAnalysisException {
           return error(ErrorCodes.ContentModified,
               'Content was modified before refactor was applied');
+        } finally {
+          _manager.end(cancellationToken);
+          reporter.end();
         }
-
-        final edit = createWorkspaceEdit(server, change.edits);
-        return await sendWorkspaceEditToClient(edit);
       });
     });
   }
@@ -112,3 +144,22 @@
     }
   }
 }
+
+/// Manages a running refactor to help ensure only one refactor runs at a time.
+class _RefactorManager {
+  /// The cancellation token for the current in-progress refactor (or null).
+  CancelableToken _currentRefactoringCancellationToken;
+
+  /// Begins a new refactor, cancelling any other in-progress refactors.
+  void begin(CancelableToken cancelToken) {
+    _currentRefactoringCancellationToken?.cancel();
+    _currentRefactoringCancellationToken = cancelToken;
+  }
+
+  /// Marks a refactor as no longer current.
+  void end(CancelableToken cancelToken) {
+    if (_currentRefactoringCancellationToken == cancelToken) {
+      _currentRefactoringCancellationToken = null;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
index c918eb6..c4eda52 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/send_workspace_edit.dart
@@ -6,7 +6,9 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 
 /// This command allows a client to request the server send it a
 /// workspace/applyEdit command, simply passing through the edits provided
@@ -22,7 +24,8 @@
   String get commandName => 'Send Workspace Edit';
 
   @override
-  Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
+  Future<ErrorOr<void>> handle(List<dynamic> arguments,
+      ProgressReporter reporter, CancellationToken cancellationToken) async {
     if (arguments == null ||
         arguments.length != 1 ||
         arguments[0] is! Map<String, dynamic>) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
index c1a5b8f..ca10fa4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
@@ -6,7 +6,9 @@
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/commands/simple_edit_handler.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/services/correction/sort_members.dart';
 
 class SortMembersCommandHandler extends SimpleEditCommandHandler {
@@ -16,7 +18,8 @@
   String get commandName => 'Sort Members';
 
   @override
-  Future<ErrorOr<void>> handle(List<dynamic> arguments) async {
+  Future<ErrorOr<void>> handle(List<dynamic> arguments,
+      ProgressReporter reporter, CancellationToken cancellationToken) async {
     if (arguments == null || arguments.length != 1 || arguments[0] is! String) {
       return ErrorOr.error(ResponseError(
         code: ServerErrorCodes.InvalidCommandArguments,
@@ -33,6 +36,11 @@
 
     var driver = server.getAnalysisDriver(path);
     final result = await driver?.parseFile(path);
+
+    if (cancellationToken.isCancellationRequested) {
+      return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
+    }
+
     if (result == null) {
       return ErrorOr.error(ResponseError(
         code: ServerErrorCodes.FileNotAnalyzed,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 6fb0452..0e5a949 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -44,6 +44,11 @@
       return success(const []);
     }
 
+    final path = pathOfDoc(params.textDocument);
+    if (!path.isError && !server.isAnalyzedFile(path.result)) {
+      return success(const []);
+    }
+
     final capabilities = server?.clientCapabilities?.textDocument;
 
     final clientSupportsWorkspaceApplyEdit =
@@ -60,7 +65,6 @@
     final clientSupportedDiagnosticTags = HashSet<DiagnosticTag>.of(
         capabilities?.publishDiagnostics?.tagSupport?.valueSet ?? []);
 
-    final path = pathOfDoc(params.textDocument);
     final unit = await path.mapResult(requireResolvedUnit);
 
     return unit.mapResult((unit) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index 22b99d1..967e8e8 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -11,6 +11,7 @@
 import 'package:analysis_server/src/lsp/handlers/commands/sort_members.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 
 /// Handles workspace/executeCommand messages by delegating to a specific handler
 /// based on the command.
@@ -35,12 +36,18 @@
 
   @override
   Future<ErrorOr<Object>> handle(
-      ExecuteCommandParams params, CancellationToken token) async {
+      ExecuteCommandParams params, CancellationToken cancellationToken) async {
     final handler = commandHandlers[params.command];
     if (handler == null) {
       return error(ServerErrorCodes.UnknownCommand,
           '${params.command} is not a valid command identifier', null);
     }
-    return handler.handle(params.arguments);
+
+    final progress = params.workDoneToken != null
+        ? ProgressReporter.clientProvided(server, params.workDoneToken)
+        : server.clientCapabilities.window?.workDoneProgress == true
+            ? ProgressReporter.serverCreated(server)
+            : ProgressReporter.noop;
+    return handler.handle(params.arguments, progress, cancellationToken);
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index c87b9c7..41f20f4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -13,6 +13,7 @@
 import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
 import 'package:analysis_server/src/lsp/json_parsing.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart';
@@ -47,7 +48,8 @@
     this.server = server;
   }
 
-  Future<ErrorOr<void>> handle(List<dynamic> arguments);
+  Future<ErrorOr<void>> handle(List<dynamic> arguments,
+      ProgressReporter progress, CancellationToken cancellationToken);
 }
 
 mixin Handler<P, R> {
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 027f52e..85debf8 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -25,6 +25,7 @@
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
 import 'package:analysis_server/src/lsp/notification_manager.dart';
+import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/lsp/server_capabilities_computer.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart' as protocol;
@@ -48,6 +49,7 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
+import 'package:path/path.dart';
 import 'package:watcher/watcher.dart';
 
 /// Instances of the class [LspAnalysisServer] implement an LSP-based server
@@ -117,6 +119,9 @@
   /// The set of analysis roots explicitly added to the workspace.
   final _explicitAnalysisRoots = HashSet<String>();
 
+  /// A progress reporter for analysis status.
+  ProgressReporter analyzingProgressReporter;
+
   /// Initialize a newly created server to send and receive messages to the
   /// given [channel].
   LspAnalysisServer(
@@ -150,6 +155,9 @@
     channel.listen(handleMessage, onDone: done, onError: socketError);
     _pluginChangeSubscription =
         pluginManager.pluginsChanged.listen((_) => _onPluginsChanged());
+
+    analyzingProgressReporter =
+        ProgressReporter.serverCreated(this, analyzingProgressToken);
   }
 
   /// The capabilities of the LSP client. Will be null prior to initialization.
@@ -218,7 +226,15 @@
           result is List<dynamic> &&
           result.length == 1 &&
           result.first is Map<String, dynamic>) {
-        clientConfiguration.replace(result.first);
+        final newConfig = result.first;
+        final refreshRoots =
+            clientConfiguration.affectsAnalysisRoots(newConfig);
+
+        clientConfiguration.replace(newConfig);
+
+        if (refreshRoots) {
+          _refreshAnalysisRoots();
+        }
       }
     }
 
@@ -320,6 +336,15 @@
     }, socketError);
   }
 
+  /// Returns `true` if the [file] with the given absolute path is included
+  /// in an analysis root and not excluded.
+  bool isAnalyzedFile(String file) {
+    return contextManager.isInAnalysisRoot(file) &&
+        // Dot folders are not analyzed (skipped over in _handleWatchEventImpl)
+        !contextManager.isContainedInDotFolder(file) &&
+        !contextManager.isIgnored(file);
+  }
+
   /// Logs the error on the client using window/logMessage.
   void logErrorToClient(String message) {
     channel.sendNotification(NotificationMessage(
@@ -477,7 +502,8 @@
     channel.sendNotification(notification);
   }
 
-  /// Send the given [request] to the client and wait for a response.
+  /// Send the given [request] to the client and wait for a response. Completes
+  /// with the raw [ResponseMessage] which could be an error response.
   Future<ResponseMessage> sendRequest(Method method, Object params) {
     final requestId = nextRequestId++;
     final completer = Completer<ResponseMessage>();
@@ -512,11 +538,23 @@
   /// Send status notification to the client. The state of analysis is given by
   /// the [status] information.
   void sendStatusNotification(nd.AnalysisStatus status) {
-    channel.sendNotification(NotificationMessage(
-      method: CustomMethods.AnalyzerStatus,
-      params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
-      jsonrpc: jsonRpcVersion,
-    ));
+    // Send old custom notifications to clients that do not support $/progress.
+    // TODO(dantup): Remove this custom notification (and related classes) when
+    // it's unlikely to be in use by any clients.
+    if (clientCapabilities.window?.workDoneProgress != true) {
+      channel.sendNotification(NotificationMessage(
+        method: CustomMethods.AnalyzerStatus,
+        params: AnalyzerStatusParams(isAnalyzing: status.isAnalyzing),
+        jsonrpc: jsonRpcVersion,
+      ));
+      return;
+    }
+
+    if (status.isAnalyzing) {
+      analyzingProgressReporter.begin('Analyzing…');
+    } else {
+      analyzingProgressReporter.end();
+    }
   }
 
   /// Returns `true` if closing labels should be sent for [file] with the given
@@ -532,12 +570,7 @@
   /// Returns `true` if errors should be reported for [file] with the given
   /// absolute path.
   bool shouldSendErrorsNotificationFor(String file) {
-    // Errors should not be reported for things that are explicitly skipped
-    // during normal analysis (for example dot folders are skipped over in
-    // _handleWatchEventImpl).
-    return contextManager.isInAnalysisRoot(file) &&
-        !contextManager.isContainedInDotFolder(file) &&
-        !contextManager.isIgnored(file);
+    return isAnalyzedFile(file);
   }
 
   /// Returns `true` if Flutter outlines should be sent for [file] with the
@@ -614,9 +647,19 @@
       ..addAll(_temporaryAnalysisRoots.values)
       ..toList();
 
+    final excludedPaths = clientConfiguration.analysisExcludedFolders
+        .expand((excludePath) => isAbsolute(excludePath)
+            ? [excludePath]
+            // Apply the relative path to each open workspace folder.
+            // TODO(dantup): Consider supporting per-workspace config by
+            // calling workspace/configuration whenever workspace folders change
+            // and caching the config for each one.
+            : _explicitAnalysisRoots.map((root) => join(root, excludePath)))
+        .toList();
+
     declarationsTracker?.discardContexts();
-    notificationManager.setAnalysisRoots(includedPaths.toList(), []);
-    contextManager.setRoots(includedPaths.toList(), []);
+    notificationManager.setAnalysisRoots(includedPaths.toList(), excludedPaths);
+    contextManager.setRoots(includedPaths.toList(), excludedPaths);
     addContextsToDeclarationsTracker();
   }
 
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 0f44750..f710272 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -1073,27 +1073,31 @@
   ///     String s = 'foo'
   String getParamLabel(server.ParameterInfo p) {
     final def = p.defaultValue != null ? ' = ${p.defaultValue}' : '';
-    return '${p.type} ${p.name}$def';
+    final prefix =
+        p.kind == server.ParameterKind.REQUIRED_NAMED ? 'required ' : '';
+    return '$prefix${p.type} ${p.name}$def';
   }
 
   /// Gets the full signature label in the form
   ///     foo(String s, int i, bool a = true)
   String getSignatureLabel(server.AnalysisGetSignatureResult resp) {
-    final req = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.REQUIRED)
+    final positionalRequired = signature.parameters
+        .where((p) => p.kind == server.ParameterKind.REQUIRED_POSITIONAL)
         .toList();
-    final opt = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.OPTIONAL)
+    final positionalOptional = signature.parameters
+        .where((p) => p.kind == server.ParameterKind.OPTIONAL_POSITIONAL)
         .toList();
     final named = signature.parameters
-        .where((p) => p.kind == server.ParameterKind.NAMED)
+        .where((p) =>
+            p.kind == server.ParameterKind.OPTIONAL_NAMED ||
+            p.kind == server.ParameterKind.REQUIRED_NAMED)
         .toList();
     final params = [];
-    if (req.isNotEmpty) {
-      params.add(req.map(getParamLabel).join(', '));
+    if (positionalRequired.isNotEmpty) {
+      params.add(positionalRequired.map(getParamLabel).join(', '));
     }
-    if (opt.isNotEmpty) {
-      params.add('[' + opt.map(getParamLabel).join(', ') + ']');
+    if (positionalOptional.isNotEmpty) {
+      params.add('[' + positionalOptional.map(getParamLabel).join(', ') + ']');
     }
     if (named.isNotEmpty) {
       params.add('{' + named.map(getParamLabel).join(', ') + '}');
diff --git a/pkg/analysis_server/lib/src/lsp/progress.dart b/pkg/analysis_server/lib/src/lsp/progress.dart
new file mode 100644
index 0000000..585c391
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/progress.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+/// Reports progress of long-running operations to the LSP client.
+abstract class ProgressReporter {
+  /// A no-op reporter that does nothing.
+  static final noop = _NoopProgressReporter();
+
+  /// Creates a reporter for a token that was supplied by the client and does
+  /// not need creating prior to use.
+  factory ProgressReporter.clientProvided(
+          LspAnalysisServer server, Either2<num, String> token) =>
+      _TokenProgressReporter(server, token);
+
+  /// Creates a reporter for a new token that must be created prior to being
+  /// used.
+  ///
+  /// If [token] is not supplied, a random identifier will be used.
+  factory ProgressReporter.serverCreated(LspAnalysisServer server,
+          [Either2<num, String> token]) =>
+      _ServerCreatedProgressReporter(server, token);
+
+  ProgressReporter._();
+
+  // TODO(dantup): Add support for cancellable progress notifications.
+  void begin(String title, {String message});
+
+  void end([String message]);
+}
+
+class _NoopProgressReporter extends ProgressReporter {
+  _NoopProgressReporter() : super._();
+  @override
+  void begin(String title, {String message}) {}
+  @override
+  void end([String message]) {}
+}
+
+class _ServerCreatedProgressReporter extends _TokenProgressReporter {
+  static final _random = Random();
+  Future<ResponseMessage> _tokenCreateRequest;
+
+  _ServerCreatedProgressReporter(
+    LspAnalysisServer server,
+    Either2<num, String> token,
+  ) : super(
+          server,
+          token ?? Either2<num, String>.t2(_randomTokenIdentifier()),
+        );
+
+  @override
+  void begin(String title, {String message}) {
+    // Create the token lazily so we don't create it if it's not required.
+    _tokenCreateRequest ??= _server.sendRequest(
+        Method.window_workDoneProgress_create,
+        WorkDoneProgressCreateParams(token: _token));
+
+    // Chain onto the end of tokenCreateRequest so we do not try to use
+    // the token without the client accepting it.
+    _tokenCreateRequest.then((response) {
+      if (response.error != null) return;
+      super.begin(title, message: message);
+    });
+  }
+
+  @override
+  void end([String message]) {
+    // Chain onto the end of tokenCreateRequest so we do not try to use
+    // the token without the client accepting it.
+    _tokenCreateRequest.then((response) {
+      if (response.error != null) return;
+      super.end(message);
+    });
+  }
+
+  static String _randomTokenIdentifier() {
+    final millisecondsSinceEpoch = DateTime.now().millisecondsSinceEpoch;
+    final random = _random.nextInt(0x3fffffff);
+    return '$millisecondsSinceEpoch$random';
+  }
+}
+
+class _TokenProgressReporter extends ProgressReporter {
+  final LspAnalysisServer _server;
+  final Either2<num, String> _token;
+  bool _needsEnd = false;
+
+  _TokenProgressReporter(this._server, this._token) : super._();
+
+  @override
+  void begin(String title, {String message}) {
+    _needsEnd = true;
+    _sendNotification(
+        WorkDoneProgressBegin(title: title ?? 'Working…', message: message));
+  }
+
+  @override
+  void end([String message]) {
+    if (!_needsEnd) return;
+    _needsEnd = false;
+    _sendNotification(WorkDoneProgressEnd(message: message));
+  }
+
+  void _sendNotification(ToJsonable value) async {
+    _server.sendNotification(NotificationMessage(
+        method: Method.progress,
+        params: ProgressParams(
+          token: _token,
+          value: value,
+        ),
+        jsonrpc: jsonRpcVersion));
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index 2dd8cd2..2a7a501e 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -201,6 +201,7 @@
             ),
       executeCommandProvider: ExecuteCommandOptions(
         commands: Commands.serverSupportedCommands,
+        workDoneProgress: true,
       ),
       workspaceSymbolProvider: true,
       workspace: ServerCapabilitiesWorkspace(
@@ -224,6 +225,8 @@
         language: 'yaml', scheme: 'file', pattern: '**/pubspec.yaml');
     final analysisOptionsFile = DocumentFilter(
         language: 'yaml', scheme: 'file', pattern: '**/analysis_options.yaml');
+    final fixDataFile = DocumentFilter(
+        language: 'yaml', scheme: 'file', pattern: '**/lib/fix_data.yaml');
 
     final pluginTypes = _server.pluginManager.plugins
         .expand((plugin) => plugin.currentSession?.interestingFiles ?? const [])
@@ -243,6 +246,7 @@
       ...allTypes,
       pubspecFile,
       analysisOptionsFile,
+      fixDataFile,
     }.toList();
 
     final registrations = <Registration>[];
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index 93b2db4..9dd70bf 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -25,9 +25,7 @@
 
   /// Initialize a newly created handler to handle requests for the given
   /// [server].
-  SearchDomainHandler(AnalysisServer server)
-      : server = server,
-        searchEngine = server.searchEngine;
+  SearchDomainHandler(this.server) : searchEngine = server.searchEngine;
 
   Future findElementReferences(protocol.Request request) async {
     var params =
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 44939fc..298fd30 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -110,6 +110,7 @@
   void addOption(String name,
       {String abbr,
       String help,
+      String valueHelp,
       List<String> allowed,
       Map<String, String> allowedHelp,
       String defaultsTo,
@@ -118,6 +119,7 @@
     _parser.addOption(name,
         abbr: abbr,
         help: help,
+        valueHelp: valueHelp,
         allowed: allowed,
         allowedHelp: allowedHelp,
         defaultsTo: defaultsTo,
@@ -276,9 +278,6 @@
   /// The path to the data cache.
   static const String CACHE_FOLDER = 'cache';
 
-  /// Whether to enable parsing via the Fasta parser.
-  static const String USE_FASTA_PARSER = 'use-fasta-parser';
-
   /// The name of the flag to use the Language Server Protocol (LSP).
   static const String USE_LSP = 'lsp';
 
@@ -341,7 +340,6 @@
       analysisServerOptions.enabledExperiments =
           (results[ENABLE_EXPERIMENT_OPTION] as List).cast<String>().toList();
     }
-    analysisServerOptions.useFastaParser = results[USE_FASTA_PARSER];
     analysisServerOptions.useNewRelevance = results[USE_NEW_RELEVANCE];
 
     // Read in any per-SDK overrides specified in <sdk>/config/settings.json.
@@ -747,9 +745,15 @@
   /// Create and return the parser used to parse the command-line arguments.
   CommandLineParser _createArgParser() {
     var parser = CommandLineParser();
+    parser.addFlag(HELP_OPTION,
+        help: 'print this help message without starting a server',
+        abbr: 'h',
+        defaultsTo: false,
+        negatable: false);
     parser.addOption(CLIENT_ID,
-        help: 'an identifier used to identify the client');
-    parser.addOption(CLIENT_VERSION, help: 'the version of the client');
+        valueHelp: 'name', help: 'an identifier used to identify the client');
+    parser.addOption(CLIENT_VERSION,
+        valueHelp: 'version', help: 'the version of the client');
     parser.addFlag(DARTPAD_OPTION,
         help: 'enable DartPad specific functionality',
         defaultsTo: false,
@@ -774,18 +778,15 @@
         help: 'enable sending instrumentation information to a server',
         defaultsTo: false,
         negatable: false);
-    parser.addFlag(HELP_OPTION,
-        help: 'print this help message without starting a server',
-        abbr: 'h',
-        defaultsTo: false,
-        negatable: false);
     parser.addOption(INSTRUMENTATION_LOG_FILE,
+        valueHelp: 'file path',
         help: 'write instrumentation data to the given file');
     parser.addFlag(INTERNAL_PRINT_TO_CONSOLE,
         help: 'enable sending `print` output to the console',
         defaultsTo: false,
         negatable: false);
     parser.addOption(NEW_ANALYSIS_DRIVER_LOG,
+        valueHelp: 'path',
         help: "set a destination for the new analysis driver's log");
     parser.addFlag(ANALYTICS_FLAG,
         help: 'enable or disable sending analytics information to Google',
@@ -795,9 +796,11 @@
         help: 'suppress analytics for this session',
         hide: !telemetry.SHOW_ANALYTICS_UI);
     parser.addOption(PORT_OPTION,
+        valueHelp: 'port',
         help: 'the http diagnostic port on which the server provides'
             ' status and performance information');
-    parser.addOption(SDK_OPTION, help: '[path] the path to the sdk');
+    parser.addOption(SDK_OPTION,
+        valueHelp: 'path', help: 'Path to the Dart sdk');
     parser.addFlag(USE_ANALYSIS_HIGHLIGHT2,
         help: 'enable version 2 of semantic highlight',
         defaultsTo: false,
@@ -806,6 +809,7 @@
         help: 'an option for reading files (some clients normalize eol '
             'characters, which make the file offset and range information '
             'incorrect)',
+        valueHelp: 'mode',
         allowed: ['as-is', 'normalize-eol-always'],
         allowedHelp: {
           'as-is': 'file contents are read as-is',
@@ -814,21 +818,21 @@
         },
         defaultsTo: 'as-is');
     parser.addOption(CACHE_FOLDER,
-        help: '[path] path to the location where to cache data');
-    parser.addFlag('preview-dart-2',
-        help: 'Enable the Dart 2.0 preview (deprecated)', hide: true);
-    parser.addFlag(USE_FASTA_PARSER,
-        defaultsTo: true,
-        help: 'Whether to enable parsing via the Fasta parser');
+        valueHelp: 'path', help: 'Path to the location to write cache data');
     parser.addFlag(USE_LSP,
-        defaultsTo: false, help: 'Whether to use the Language Server Protocol');
+        defaultsTo: false,
+        negatable: false,
+        help: 'Whether to use the Language Server Protocol');
     parser.addFlag(ENABLE_COMPLETION_MODEL,
         help: 'Whether or not to turn on ML ranking for code completion');
     parser.addOption(COMPLETION_MODEL_FOLDER,
-        help: '[path] path to the location of a code completion model');
+        valueHelp: 'path',
+        help: 'Path to the location of a code completion model');
     parser.addOption(TRAIN_USING,
+        valueHelp: 'path',
         help: 'Pass in a directory to analyze for purposes of training an '
             'analysis server snapshot.');
+
     //
     // Temporary flags.
     //
@@ -836,6 +840,12 @@
         defaultsTo: true,
         help: 'Use the new relevance computation for code completion.');
 
+    //
+    // Deprecated options - no longer read from.
+    //
+    parser.addFlag('use-fasta-parser', defaultsTo: true, hide: true);
+    parser.addFlag('preview-dart-2', hide: true);
+
     return parser;
   }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 5339b4d..a84b968 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -40,9 +40,8 @@
   /// Initialize a newly created completion request based on the given
   /// arguments.
   CompletionRequestImpl(
-      this.result, int offset, this.useNewRelevance, this.performance)
-      : offset = offset,
-        replacementOffset = offset,
+      this.result, this.offset, this.useNewRelevance, this.performance)
+      : replacementOffset = offset,
         replacementLength = 0;
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 979b63f..3d8234d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/utilities/extensions/ast.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
@@ -169,7 +170,7 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    var previousMember;
+    SyntacticEntity previousMember;
     for (var member in node.childEntities) {
       if (entity == member) {
         break;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index 9bbc308..f638e9a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -44,8 +44,6 @@
     var suggestLocalFields = node is ConstructorDeclaration &&
         node.initializers.contains(request.target.entity);
 
-    var localVisitor;
-
     // Collect suggestions from the specific child [AstNode] that contains the
     // completion offset and all of its parents recursively.
     if (!opType.isPrefixed) {
@@ -67,10 +65,10 @@
           node = node.parent.parent;
         }
 
-        localVisitor = _LocalVisitor(request, builder, visibilityTracker,
-            suggestLocalFields: suggestLocalFields);
         try {
           builder.laterReplacesEarlier = false;
+          var localVisitor = _LocalVisitor(request, builder, visibilityTracker,
+              suggestLocalFields: suggestLocalFields);
           localVisitor.visit(node);
         } finally {
           builder.laterReplacesEarlier = true;
@@ -451,7 +449,7 @@
   @override
   void visitExtendsClause(ExtendsClause node) {
     inExtendsClause = true;
-    return super.visitExtendsClause(node);
+    super.visitExtendsClause(node);
   }
 
   /// Return `true` if the [identifier] is composed of one or more underscore
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 6583dcd..ae57075 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -786,7 +786,8 @@
   void suggestNamedArgument(ParameterElement parameter,
       {@required bool appendColon, @required bool appendComma}) {
     var name = parameter.name;
-    var type = parameter.type?.getDisplayString(withNullability: false);
+    var type = parameter.type?.getDisplayString(
+        withNullability: request.libraryElement.isNonNullableByDefault);
 
     var completion = name;
     if (appendColon) {
@@ -799,7 +800,9 @@
     var element = parameter.enclosingElement;
     if (element is ConstructorElement) {
       if (Flutter.instance.isWidget(element.enclosingElement)) {
-        var defaultValue = getDefaultStringParameterValue(parameter);
+        // Don't bother with nullability. It won't affect default list values.
+        var defaultValue =
+            getDefaultStringParameterValue(parameter, withNullability: false);
         // TODO(devoncarew): Should we remove the check here? We would then
         // suggest values for param types like closures.
         if (defaultValue != null && defaultValue.text == '[]') {
@@ -934,7 +937,7 @@
 
   /// Add a suggestion for a [prefix] associated with a [library].
   void suggestPrefix(LibraryElement library, String prefix) {
-    var relevance;
+    int relevance;
     if (request.useNewRelevance) {
       var elementKind = _computeElementKind(library);
       // TODO(brianwilkerson) If we are in a constant context it would be nice
@@ -1286,7 +1289,8 @@
         var paramType = parameter.type;
         // Gracefully degrade if type not resolved yet
         return paramType != null
-            ? paramType.getDisplayString(withNullability: false)
+            ? paramType.getDisplayString(
+                withNullability: request.libraryElement.isNonNullableByDefault)
             : 'var';
       }).toList();
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index deea96b..e829ce1 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -15,6 +15,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol
     show Element, ElementKind;
+import 'package:meta/meta.dart';
 
 /// The name of the type `dynamic`;
 const DYNAMIC = 'dynamic';
@@ -55,7 +56,7 @@
       FunctionType type = param.type;
 
       var rangeStart = offset;
-      var rangeLength;
+      int rangeLength;
 
       // todo (pq): consider adding ranges for params
       // pending: https://github.com/dart-lang/sdk/issues/40207
@@ -168,22 +169,28 @@
       returnType: nameForType(id, returnType));
 }
 
-DefaultArgument getDefaultStringParameterValue(ParameterElement param) {
-  if (param != null) {
-    var type = param.type;
-    if (type is InterfaceType && type.isDartCoreList) {
-      return DefaultArgument('[]', cursorPosition: 1);
+/// Return a default argument value for the given [parameter].
+DefaultArgument getDefaultStringParameterValue(ParameterElement parameter,
+    {@required bool withNullability}) {
+  if (parameter != null) {
+    var type = parameter.type;
+    if (type is InterfaceType) {
+      if (type.isDartCoreList) {
+        return DefaultArgument('[]', cursorPosition: 1);
+      } else if (type.isDartCoreMap) {
+        return DefaultArgument('{}', cursorPosition: 1);
+      } else if (type.isDartCoreString) {
+        return DefaultArgument("''", cursorPosition: 1);
+      }
     } else if (type is FunctionType) {
       var params = type.parameters
-          .map((p) => '${getTypeString(p.type)}${p.name}')
+          .map((p) =>
+              '${getTypeString(p.type, withNullability: withNullability)}${p.name}')
           .join(', ');
       // TODO(devoncarew): Support having this method return text with newlines.
       var text = '($params) {  }';
       return DefaultArgument(text, cursorPosition: text.length - 2);
     }
-
-    // TODO(pq): support map literals
-
   }
 
   return null;
@@ -205,11 +212,11 @@
   return content.substring(lineStartOffset, notWhitespaceOffset);
 }
 
-String getTypeString(DartType type) {
+String getTypeString(DartType type, {@required bool withNullability}) {
   if (type.isDynamic) {
     return '';
   } else {
-    return type.getDisplayString(withNullability: false) + ' ';
+    return type.getDisplayString(withNullability: withNullability) + ' ';
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 403fbb3..b648f7f 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -8,10 +8,12 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -444,7 +446,18 @@
     if (astNode is ThrowExpression) {
       var expr = astNode;
       var type = expr.expression.staticType;
-      return type.getDisplayString(withNullability: false);
+
+      // Only print nullability for non-legacy types in non-legacy libraries.
+      var showNullability = type.nullabilitySuffix != NullabilitySuffix.star &&
+          (astNode.root as CompilationUnit)
+              .declaredElement
+              .library
+              .isNonNullableByDefault;
+
+      // Can't catch nullable types, strip `?`s now that we've checked for `*`s.
+      return (type as TypeImpl)
+          .withNullability(NullabilitySuffix.none)
+          .getDisplayString(withNullability: showNullability);
     }
     return 'Exception';
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart b/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart
index 8316e43..44c3ad9 100644
--- a/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/token_details/token_detail_builder.dart
@@ -115,6 +115,8 @@
     } else if (type is InterfaceType) {
       Element element = type.element;
       if (element == null || element.isSynthetic) {
+        assert(false, 'untested branch may print nullable types wrong');
+        // TODO: test this, use the the library's nullability (not tracked yet).
         buffer.write(type.getDisplayString(withNullability: false));
       } else {
 //        String uri = element.library.source.uri.toString();
@@ -132,7 +134,9 @@
         }
       }
     } else {
-      // Handle `void` and `dynamic`.
+      // Handle `void` and `dynamic`. Nullability doesn't affect this.
+      assert(type.getDisplayString(withNullability: false) ==
+          type.getDisplayString(withNullability: true));
       buffer.write(type.getDisplayString(withNullability: false));
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 357c58f..6f994e4 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -192,7 +192,8 @@
     Future<void> compute(CorrectionProducer producer) async {
       producer.configure(context);
 
-      var builder = ChangeBuilder(workspace: context.workspace);
+      var builder = ChangeBuilder(
+          workspace: context.workspace, eol: context.utils.endOfLine);
       await producer.compute(builder);
 
       _addAssistFromBuilder(builder, producer.assistKind,
@@ -246,7 +247,8 @@
         var producer = generator();
         producer.configure(context);
 
-        var builder = ChangeBuilder(workspace: context.workspace);
+        var builder = ChangeBuilder(
+            workspace: context.workspace, eol: context.utils.endOfLine);
         await producer.compute(builder);
         _addAssistFromBuilder(builder, producer.assistKind,
             args: producer.assistArguments);
@@ -256,7 +258,8 @@
       var multiProducer = multiGenerator();
       multiProducer.configure(context);
       for (var producer in multiProducer.producers) {
-        var builder = ChangeBuilder(workspace: context.workspace);
+        var builder = ChangeBuilder(
+            workspace: context.workspace, eol: context.utils.endOfLine);
         producer.configure(context);
         await producer.compute(builder);
         _addAssistFromBuilder(builder, producer.assistKind,
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index 08fc72b..0de1a9d 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -9,6 +9,7 @@
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
 import 'package:analysis_server/src/services/correction/dart/add_await.dart';
 import 'package:analysis_server/src/services/correction/dart/add_const.dart';
+import 'package:analysis_server/src/services/correction/dart/add_diagnostic_property_reference.dart';
 import 'package:analysis_server/src/services/correction/dart/add_override.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_add_all_to_spread.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_conditional_expression_to_if_element.dart';
@@ -19,10 +20,15 @@
 import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_if_null.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
 import 'package:analysis_server/src/services/correction/dart/create_method.dart';
+import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
+import 'package:analysis_server/src/services/correction/dart/inline_invocation.dart';
 import 'package:analysis_server/src/services/correction/dart/make_final.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_argument.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_await.dart';
@@ -55,75 +61,266 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer/dart/analysis/analysis_context.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
+import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 
 /// A fix producer that produces changes to fix multiple diagnostics.
 class BulkFixProcessor {
-  /// A map from the name of a lint rule to a generator used to create the
-  /// correction producer used to build a fix for that diagnostic. The
+  /// A map from the name of a lint rule to a list of generators used to create
+  /// the correction producer used to build a fix for that diagnostic. The
   /// generators used for non-lint diagnostics are in the [nonLintProducerMap].
-  static const Map<String, ProducerGenerator> lintProducerMap = {
-    LintNames.annotate_overrides: AddOverride.newInstance,
-    LintNames.avoid_annotating_with_dynamic: RemoveTypeAnnotation.newInstance,
-    LintNames.avoid_empty_else: RemoveEmptyElse.newInstance,
-    LintNames.avoid_init_to_null: RemoveInitializer.newInstance,
-    LintNames.avoid_redundant_argument_values: RemoveArgument.newInstance,
-    LintNames.avoid_return_types_on_setters: RemoveTypeAnnotation.newInstance,
-    LintNames.avoid_single_cascade_in_expression_statements:
-        ReplaceCascadeWithDot.newInstance,
-    LintNames.avoid_types_on_closure_parameters:
-        RemoveTypeAnnotation.newInstance,
-    LintNames.await_only_futures: RemoveAwait.newInstance,
-    LintNames.curly_braces_in_flow_control_structures:
-        UseCurlyBraces.newInstance,
-    LintNames.empty_catches: RemoveEmptyCatch.newInstance,
-    LintNames.empty_constructor_bodies: RemoveEmptyConstructorBody.newInstance,
-    LintNames.empty_statements: RemoveEmptyStatement.newInstance,
-    LintNames.hash_and_equals: CreateMethod.equalsOrHashCode,
-    LintNames.no_duplicate_case_values: RemoveDuplicateCase.newInstance,
-    LintNames.non_constant_identifier_names: RenameToCamelCase.newInstance,
-    LintNames.null_closures: ReplaceNullWithClosure.newInstance,
-    LintNames.omit_local_variable_types: ReplaceWithVar.newInstance,
-    LintNames.prefer_adjacent_string_concatenation: RemoveOperator.newInstance,
-    LintNames.prefer_conditional_assignment:
-        ReplaceWithConditionalAssignment.newInstance,
-    LintNames.prefer_const_constructors_in_immutables: AddConst.newInstance,
-    LintNames.prefer_const_declarations: ReplaceFinalWithConst.newInstance,
-    LintNames.prefer_contains: ConvertToContains.newInstance,
-    LintNames.prefer_equal_for_default_values:
-        ReplaceColonWithEquals.newInstance,
-    LintNames.prefer_final_fields: MakeFinal.newInstance,
-    LintNames.prefer_final_locals: MakeFinal.newInstance,
-    LintNames.prefer_for_elements_to_map_fromIterable:
-        ConvertMapFromIterableToForLiteral.newInstance,
-    LintNames.prefer_generic_function_type_aliases:
-        ConvertToGenericFunctionSyntax.newInstance,
-    LintNames.prefer_if_elements_to_conditional_expressions:
-        ConvertConditionalExpressionToIfElement.newInstance,
-    LintNames.prefer_if_null_operators: ConvertToIfNull.newInstance,
-    LintNames.prefer_int_literals: ConvertToIntLiteral.newInstance,
-    LintNames.prefer_is_empty: ReplaceWithIsEmpty.newInstance,
-    LintNames.prefer_is_not_empty: UesIsNotEmpty.newInstance,
-    LintNames.prefer_iterable_whereType: ConvertToWhereType.newInstance,
-    LintNames.prefer_null_aware_operators: ConvertToNullAware.newInstance,
-    LintNames.prefer_relative_imports: ConvertToRelativeImport.newInstance,
-    LintNames.prefer_single_quotes: ConvertToSingleQuotes.newInstance,
-    LintNames.prefer_spread_collections: ConvertAddAllToSpread.newInstance,
-    LintNames.slash_for_doc_comments: ConvertDocumentationIntoLine.newInstance,
-    LintNames.sort_child_properties_last: SortChildPropertyLast.newInstance,
-    LintNames.type_init_formals: RemoveTypeAnnotation.newInstance,
-    LintNames.unawaited_futures: AddAwait.newInstance,
-    LintNames.unnecessary_brace_in_string_interps:
-        RemoveInterpolationBraces.newInstance,
-    LintNames.unnecessary_const: RemoveUnnecessaryConst.newInstance,
-    LintNames.unnecessary_lambdas: ReplaceWithTearOff.newInstance,
-    LintNames.unnecessary_new: RemoveUnnecessaryNew.newInstance,
-    LintNames.unnecessary_overrides: RemoveMethodDeclaration.newInstance,
-    LintNames.unnecessary_this: RemoveThisExpression.newInstance,
-    LintNames.use_rethrow_when_possible: UseRethrow.newInstance,
+  ///
+  /// Most entries will have only one generator. In cases where there is more
+  /// than one, they will be applied in series and the expectation is that only
+  /// one will produce a change for a given fix. If more than one change is
+  /// produced the result will almost certainly be invalid code.
+  static const Map<String, List<ProducerGenerator>> lintProducerMap = {
+    LintNames.annotate_overrides: [
+      AddOverride.newInstance,
+    ],
+    LintNames.avoid_annotating_with_dynamic: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.avoid_empty_else: [
+      RemoveEmptyElse.newInstance,
+    ],
+    LintNames.avoid_init_to_null: [
+      RemoveInitializer.newInstance,
+    ],
+    LintNames.avoid_redundant_argument_values: [
+      RemoveArgument.newInstance,
+    ],
+    LintNames.avoid_return_types_on_setters: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.avoid_single_cascade_in_expression_statements: [
+      ReplaceCascadeWithDot.newInstance,
+    ],
+    LintNames.avoid_types_on_closure_parameters: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.await_only_futures: [
+      RemoveAwait.newInstance,
+    ],
+    LintNames.curly_braces_in_flow_control_structures: [
+      UseCurlyBraces.newInstance,
+    ],
+    LintNames.diagnostic_describe_all_properties: [
+      AddDiagnosticPropertyReference.newInstance,
+    ],
+    LintNames.empty_catches: [
+      RemoveEmptyCatch.newInstance,
+    ],
+    LintNames.empty_constructor_bodies: [
+      RemoveEmptyConstructorBody.newInstance,
+    ],
+    LintNames.empty_statements: [
+      RemoveEmptyStatement.newInstance,
+    ],
+    LintNames.hash_and_equals: [CreateMethod.equalsOrHashCode],
+    LintNames.no_duplicate_case_values: [
+      RemoveDuplicateCase.newInstance,
+    ],
+    LintNames.non_constant_identifier_names: [
+      RenameToCamelCase.newInstance,
+    ],
+    LintNames.null_closures: [
+      ReplaceNullWithClosure.newInstance,
+    ],
+    LintNames.omit_local_variable_types: [
+      ReplaceWithVar.newInstance,
+    ],
+    LintNames.prefer_adjacent_string_concatenation: [
+      RemoveOperator.newInstance,
+    ],
+    LintNames.prefer_collection_literals: [
+      ConvertToListLiteral.newInstance,
+      ConvertToMapLiteral.newInstance,
+      ConvertToSetLiteral.newInstance,
+    ],
+    LintNames.prefer_conditional_assignment: [
+      ReplaceWithConditionalAssignment.newInstance,
+    ],
+    // TODO (pq): can produce results incompatible w/ `unnecessary_const`
+    // LintNames.prefer_const_constructors: [
+    //   AddConst.newInstance,
+    //   ReplaceNewWithConst.newInstance,
+    // ],
+    LintNames.prefer_const_constructors_in_immutables: [
+      AddConst.newInstance,
+    ],
+    LintNames.prefer_const_declarations: [
+      ReplaceFinalWithConst.newInstance,
+    ],
+    LintNames.prefer_contains: [
+      ConvertToContains.newInstance,
+    ],
+    LintNames.prefer_equal_for_default_values: [
+      ReplaceColonWithEquals.newInstance,
+    ],
+    LintNames.prefer_final_fields: [
+      MakeFinal.newInstance,
+    ],
+    LintNames.prefer_final_locals: [
+      MakeFinal.newInstance,
+    ],
+    LintNames.prefer_for_elements_to_map_fromIterable: [
+      ConvertMapFromIterableToForLiteral.newInstance,
+    ],
+    LintNames.prefer_generic_function_type_aliases: [
+      ConvertToGenericFunctionSyntax.newInstance,
+    ],
+    LintNames.prefer_if_elements_to_conditional_expressions: [
+      ConvertConditionalExpressionToIfElement.newInstance,
+    ],
+    LintNames.prefer_if_null_operators: [
+      ConvertToIfNull.newInstance,
+    ],
+    LintNames.prefer_inlined_adds: [
+      ConvertAddAllToSpread.newInstance,
+      InlineInvocation.newInstance,
+    ],
+    LintNames.prefer_int_literals: [
+      ConvertToIntLiteral.newInstance,
+    ],
+    LintNames.prefer_is_empty: [
+      ReplaceWithIsEmpty.newInstance,
+    ],
+    LintNames.prefer_is_not_empty: [
+      UesIsNotEmpty.newInstance,
+    ],
+    LintNames.prefer_iterable_whereType: [
+      ConvertToWhereType.newInstance,
+    ],
+    LintNames.prefer_null_aware_operators: [
+      ConvertToNullAware.newInstance,
+    ],
+    LintNames.prefer_relative_imports: [
+      ConvertToRelativeImport.newInstance,
+    ],
+    LintNames.prefer_single_quotes: [
+      ConvertToSingleQuotes.newInstance,
+    ],
+    LintNames.prefer_spread_collections: [
+      ConvertAddAllToSpread.newInstance,
+    ],
+    LintNames.slash_for_doc_comments: [
+      ConvertDocumentationIntoLine.newInstance,
+    ],
+    LintNames.sort_child_properties_last: [
+      SortChildPropertyLast.newInstance,
+    ],
+    LintNames.type_init_formals: [
+      RemoveTypeAnnotation.newInstance,
+    ],
+    LintNames.unawaited_futures: [
+      AddAwait.newInstance,
+    ],
+    LintNames.unnecessary_brace_in_string_interps: [
+      RemoveInterpolationBraces.newInstance,
+    ],
+    LintNames.unnecessary_const: [
+      RemoveUnnecessaryConst.newInstance,
+    ],
+    LintNames.unnecessary_lambdas: [
+      ReplaceWithTearOff.newInstance,
+    ],
+    LintNames.unnecessary_new: [
+      RemoveUnnecessaryNew.newInstance,
+    ],
+    LintNames.unnecessary_overrides: [
+      RemoveMethodDeclaration.newInstance,
+    ],
+    LintNames.unnecessary_this: [
+      RemoveThisExpression.newInstance,
+    ],
+    LintNames.use_rethrow_when_possible: [
+      UseRethrow.newInstance,
+    ],
+  };
+
+  /// A map from an error code to a list of generators used to create multiple
+  /// correction producers used to build fixes for those diagnostics. The
+  /// generators used for lint rules are in the [lintMultiProducerMap].
+  ///
+  /// The expectation is that only one of the correction producers will produce
+  /// a change for a given fix. If more than one change is produced the result
+  /// will almost certainly be invalid code.
+  static const Map<ErrorCode, List<MultiProducerGenerator>>
+      nonLintMultiProducerMap = {
+    CompileTimeErrorCode.EXTENDS_NON_CLASS: [
+      DataDriven.newInstance,
+    ],
+    // TODO(brianwilkerson) The following fix fails if an invocation of the
+    //  function is the argument that needs to be removed.
+    // CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS: [
+    //   DataDriven.newInstance,
+    // ],
+    // TODO(brianwilkerson) The following fix fails if an invocation of the
+    //  function is the argument that needs to be updated.
+    // CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED: [
+    //   DataDriven.newInstance,
+    // ],
+    CompileTimeErrorCode.IMPLEMENTS_NON_CLASS: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.INVALID_OVERRIDE: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.MIXIN_OF_NON_CLASS: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_CLASS: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_FUNCTION: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_GETTER: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_IDENTIFIER: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_METHOD: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.UNDEFINED_SETTER: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION: [
+      DataDriven.newInstance,
+    ],
+    CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD: [
+      DataDriven.newInstance,
+    ],
+    HintCode.DEPRECATED_MEMBER_USE: [
+      DataDriven.newInstance,
+    ],
+    HintCode.DEPRECATED_MEMBER_USE_WITH_MESSAGE: [
+      DataDriven.newInstance,
+    ],
+    HintCode.OVERRIDE_ON_NON_OVERRIDING_METHOD: [
+      DataDriven.newInstance,
+    ],
   };
 
   /// A map from an error code to a generator used to create the correction
@@ -131,27 +328,45 @@
   /// lint rules are in the [lintProducerMap].
   static const Map<ErrorCode, ProducerGenerator> nonLintProducerMap = {};
 
+  /// Information about the workspace containing the libraries in which changes
+  /// will be produced.
   final DartChangeWorkspace workspace;
 
   /// The change builder used to build the changes required to fix the
   /// diagnostics.
   ChangeBuilder builder;
 
+  /// Initialize a newly created processor to create fixes for diagnostics in
+  /// libraries in the [workspace].
   BulkFixProcessor(this.workspace) {
     builder = ChangeBuilder(workspace: workspace);
   }
 
-  Future<ChangeBuilder> fixErrorsInLibraries(List<String> libraryPaths) async {
-    for (var path in libraryPaths) {
-      var session = workspace.getSession(path);
-      var libraryResult = await session.getResolvedLibrary(path);
-      await _fixErrorsInLibrary(libraryResult);
+  /// Return a change builder that has been used to create fixes for the
+  /// diagnostics in the libraries in the given [contexts].
+  Future<ChangeBuilder> fixErrors(List<AnalysisContext> contexts) async {
+    for (var context in contexts) {
+      for (var path in context.contextRoot.analyzedFiles()) {
+        if (!AnalysisEngine.isDartFileName(path)) {
+          continue;
+        }
+        var kind = await context.currentSession.getSourceKind(path);
+        if (kind != SourceKind.LIBRARY) {
+          continue;
+        }
+        var library = await context.currentSession.getResolvedLibrary(path);
+        await _fixErrorsInLibrary(library);
+      }
     }
+
     return builder;
   }
 
-  Future<void> _fixErrorsInLibrary(ResolvedLibraryResult libraryResult) async {
-    for (var unitResult in libraryResult.units) {
+  /// Use the change [builder] to create fixes for the diagnostics in the
+  /// library associated with the analysis [result].
+  Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
+    var analysisOptions = result.session.analysisContext.analysisOptions;
+    for (var unitResult in result.units) {
       final fixContext = DartFixContextImpl(
         workspace,
         unitResult,
@@ -159,19 +374,26 @@
         (name) => [],
       );
       for (var error in unitResult.errors) {
-        await _fixSingleError(fixContext, unitResult, error);
+        var processor = ErrorProcessor.getProcessor(analysisOptions, error);
+        // Only fix errors not filtered out in analysis options.
+        if (processor == null || processor.severity != null) {
+          await _fixSingleError(fixContext, unitResult, error);
+        }
       }
     }
   }
 
+  /// Use the change [builder] and the [fixContext] to create a fix for the
+  /// given [diagnostic] in the compilation unit associated with the analysis
+  /// [result].
   Future<void> _fixSingleError(DartFixContext fixContext,
-      ResolvedUnitResult unitResult, AnalysisError error) async {
+      ResolvedUnitResult result, AnalysisError diagnostic) async {
     var context = CorrectionProducerContext(
       dartFixContext: fixContext,
-      diagnostic: error,
-      resolvedResult: unitResult,
-      selectionOffset: error.offset,
-      selectionLength: error.length,
+      diagnostic: diagnostic,
+      resolvedResult: result,
+      selectionOffset: diagnostic.offset,
+      selectionLength: diagnostic.length,
       workspace: workspace,
     );
 
@@ -185,17 +407,29 @@
       await producer.compute(builder);
     }
 
-    var errorCode = error.errorCode;
+    var errorCode = diagnostic.errorCode;
     if (errorCode is LintCode) {
-      var generator = lintProducerMap[errorCode.name];
-      if (generator != null) {
-        await compute(generator());
+      var generators = lintProducerMap[errorCode.name];
+      if (generators != null) {
+        for (var generator in generators) {
+          await compute(generator());
+        }
       }
     } else {
       var generator = nonLintProducerMap[errorCode];
       if (generator != null) {
         await compute(generator());
       }
+      var multiGenerators = nonLintMultiProducerMap[errorCode];
+      if (multiGenerators != null) {
+        for (var multiGenerator in multiGenerators) {
+          var multiProducer = multiGenerator();
+          multiProducer.configure(context);
+          for (var producer in multiProducer.producers) {
+            await compute(producer);
+          }
+        }
+      }
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
index 30ae5ef..af47d5d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_diagnostic_property_reference.dart
@@ -42,8 +42,8 @@
       return;
     }
 
-    var constructorId;
-    var typeArgs;
+    String constructorId;
+    List<DartType> typeArgs;
     var constructorName = '';
 
     if (type.element is FunctionTypedElement) {
@@ -133,8 +133,8 @@
     if (body is BlockFunctionBody) {
       var functionBody = body;
 
-      var offset;
-      var prefix;
+      int offset;
+      String prefix;
       if (functionBody.block.statements.isEmpty) {
         offset = functionBody.block.leftBracket.offset;
         prefix = utils.getLinePrefix(offset) + utils.getIndent(1);
@@ -144,7 +144,7 @@
       }
 
       var parameters = debugFillProperties.parameters.parameters;
-      var propertiesBuilderName;
+      String propertiesBuilderName;
       for (var parameter in parameters) {
         if (parameter is SimpleFormalParameter) {
           final type = parameter.type;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
index a8ec84f..93c14bd 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
@@ -44,7 +44,7 @@
     }
   }
 
-  void _insertAt(ChangeBuilder builder, int offset) async {
+  Future<void> _insertAt(ChangeBuilder builder, int offset) async {
     await builder.addDartFileEdit(file, (builder) {
       builder.addSimpleInsertion(offset, 'late ');
     });
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
index 065deff..40e8f6f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_missing_required_argument.dart
@@ -43,7 +43,7 @@
     }
 
     if (targetElement is ExecutableElement) {
-      // Format: "Missing required argument 'foo"
+      // Format: "Missing required argument 'foo'."
       var messageParts = diagnostic.problemMessage.message.split("'");
       if (messageParts.length < 2) {
         return;
@@ -78,6 +78,9 @@
           }
         }
       }
+      var defaultValue = getDefaultStringParameterValue(missingParameter,
+          withNullability: libraryElement.isNonNullableByDefault &&
+              missingParameter.library.isNonNullableByDefault);
 
       await builder.addDartFileEdit(file, (builder) {
         builder.addInsertion(offset, (builder) {
@@ -87,7 +90,6 @@
 
           builder.write('$_missingParameterName: ');
 
-          var defaultValue = getDefaultStringParameterValue(missingParameter);
           // Use defaultValue.cursorPosition if it's not null.
           if (defaultValue?.cursorPosition != null) {
             builder.write(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart
index 7ce7207..20b8972 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart
@@ -22,7 +22,7 @@
       if (identifier.parent is FormalParameter) {
         final exp = identifier.parent.thisOrAncestorMatching(
             (node) => node is FunctionExpression || node is MethodDeclaration);
-        var body;
+        FunctionBody body;
         if (exp is FunctionExpression) {
           body = exp.body;
         } else if (exp is MethodDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_documentation_into_line.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_documentation_into_line.dart
index 7459fdb..d2c7fd5 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_documentation_into_line.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_documentation_into_line.dart
@@ -32,7 +32,7 @@
       return null;
     }
     var text = token.lexeme;
-    var lines = text.split('\n');
+    var lines = text.split(eol);
     var prefix = utils.getNodePrefix(comment);
     var newLines = <String>[];
     var firstLine = true;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
index 8455340..55986c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_if_null.dart
@@ -16,27 +16,28 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var conditional = node.thisOrAncestorOfType<ConditionalExpression>();
-    if (conditional == null) {
-      return;
-    }
-    var condition = conditional.condition as BinaryExpression;
-    Expression nullableExpression;
-    Expression defaultExpression;
-    if (condition.operator.type == TokenType.EQ_EQ) {
-      nullableExpression = conditional.elseExpression;
-      defaultExpression = conditional.thenExpression;
-    } else {
-      nullableExpression = conditional.thenExpression;
-      defaultExpression = conditional.elseExpression;
-    }
-    await builder.addDartFileEdit(file, (builder) {
-      builder.addReplacement(range.node(conditional), (builder) {
-        builder.write(utils.getNodeText(nullableExpression));
-        builder.write(' ?? ');
-        builder.write(utils.getNodeText(defaultExpression));
+    var node = this.node;
+    if (node is ConditionalExpression &&
+        node.offset == errorOffset &&
+        node.length == errorLength) {
+      var condition = node.condition as BinaryExpression;
+      Expression nullableExpression;
+      Expression defaultExpression;
+      if (condition.operator.type == TokenType.EQ_EQ) {
+        nullableExpression = node.elseExpression;
+        defaultExpression = node.thenExpression;
+      } else {
+        nullableExpression = node.thenExpression;
+        defaultExpression = node.elseExpression;
+      }
+      await builder.addDartFileEdit(file, (builder) {
+        builder.addReplacement(range.node(node), (builder) {
+          builder.write(utils.getNodeText(nullableExpression));
+          builder.write(' ?? ');
+          builder.write(utils.getNodeText(defaultExpression));
+        });
       });
-    });
+    }
   }
 
   /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
index 4cf4b5c..17509ff 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
@@ -41,7 +41,7 @@
     if (methodDecl != null && classDecl != null) {
       final classElement = classDecl.declaredElement;
 
-      var element;
+      ExecutableElement element;
       if (methodDecl.name.name == 'hashCode') {
         _memberName = '==';
         element = classElement.lookUpInheritedMethod(
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
index b9bfecb..176d2c6 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/data_driven.dart
@@ -4,11 +4,14 @@
 
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/element.dart' show LibraryElement;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:meta/meta.dart';
@@ -21,43 +24,106 @@
   @override
   Iterable<CorrectionProducer> get producers sync* {
     var name = _name;
-    var importedUris = <String>[];
+    var importedUris = <Uri>[];
     var library = resolvedResult.libraryElement;
     for (var importElement in library.imports) {
       // TODO(brianwilkerson) Filter based on combinators to help avoid making
       //  invalid suggestions.
-      importedUris.add(importElement.uri);
+      var uri = importElement.uri;
+      if (uri != null) {
+        // The [uri] is `null` if the literal string is not a valid URI.
+        importedUris.add(Uri.parse(uri));
+      }
     }
+    var matcher =
+        ElementMatcher(importedUris: importedUris, name: name, kinds: _kinds);
     for (var set in _availableTransformSetsForLibrary(library)) {
-      for (var transform in set.transformsFor(name, importedUris)) {
+      for (var transform in set.transformsFor(matcher)) {
         yield DataDrivenFix(transform);
       }
     }
   }
 
+  List<ElementKind> get _kinds {
+    AstNode child;
+    var node = this.node;
+    while (node != null) {
+      if (node is ConstructorName) {
+        return const [ElementKind.constructorKind];
+      } else if (node is ExtensionOverride) {
+        return const [ElementKind.extensionKind];
+      } else if (node is InstanceCreationExpression) {
+        return const [ElementKind.constructorKind];
+      } else if (node is MethodInvocation) {
+        if (node.target == child) {
+          return const [
+            ElementKind.classKind,
+            ElementKind.enumKind,
+            ElementKind.mixinKind
+          ];
+        } else if (node.realTarget != null) {
+          return const [ElementKind.constructorKind, ElementKind.methodKind];
+        }
+        return const [
+          ElementKind.classKind,
+          ElementKind.extensionKind,
+          ElementKind.functionKind,
+          ElementKind.methodKind
+        ];
+      } else if (node is NamedType) {
+        var parent = node.parent;
+        if (parent is ConstructorName && parent.name == null) {
+          return const [ElementKind.classKind, ElementKind.constructorKind];
+        }
+        return const [
+          ElementKind.classKind,
+          ElementKind.enumKind,
+          ElementKind.mixinKind,
+          ElementKind.typedefKind
+        ];
+      }
+      child = node;
+      node = node.parent;
+    }
+    return null;
+  }
+
   /// Return the name of the element that was changed.
   String get _name {
+    String nameFromParent(AstNode node) {
+      var parent = node.parent;
+      if (parent is MethodInvocation) {
+        return parent.methodName.name;
+      } else if (parent is InstanceCreationExpression) {
+        var constructorName = parent.constructorName;
+        if (constructorName.name != null) {
+          return constructorName.name.name;
+        }
+        return constructorName.type.name.name;
+      } else if (parent is ExtensionOverride) {
+        return parent.extensionName.name;
+      }
+      return null;
+    }
+
     var node = this.node;
     if (node is SimpleIdentifier) {
+      var parent = node.parent;
+      if (parent is Label && parent.parent is NamedExpression) {
+        // The parent of the named expression is an argument list. Because we
+        // don't represent parameters as elements, the element we need to match
+        // against is the invocation containing those arguments.
+        return nameFromParent(parent.parent.parent);
+      }
       return node.name;
     } else if (node is ConstructorName) {
       return node.name.name;
     } else if (node is NamedType) {
       return node.name.name;
     } else if (node is TypeArgumentList) {
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        return parent.methodName.name;
-      } else if (parent is ExtensionOverride) {
-        return parent.extensionName.name;
-      }
+      return nameFromParent(node);
     } else if (node is ArgumentList) {
-      var parent = node.parent;
-      if (parent is MethodInvocation) {
-        return parent.methodName.name;
-      } else if (parent is ExtensionOverride) {
-        return parent.extensionName.name;
-      }
+      return nameFromParent(node);
     }
     return null;
   }
@@ -83,6 +149,9 @@
 
   DataDrivenFix(this._transform);
 
+  /// Return a description of the element that was changed.
+  ElementDescriptor get element => _transform.element;
+
   @override
   List<Object> get fixArguments => [_transform.title];
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
index 2025838..5bcc3fc 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
@@ -60,7 +60,8 @@
       if (newlineLoc == childArgSrc.length) {
         newlineLoc -= 1;
       }
-      String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+      String indentOld =
+          getLinePrefix(childArg.offset + eol.length + newlineLoc);
       var indentNew = '$indentOld${getIndent(1)}';
       // The separator includes 'child:' but that has no newlines.
       String separator =
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
index 6b0ac1a..5fcd235 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
@@ -28,7 +28,7 @@
     if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) {
       return; // Lists need to be in multi-line format already.
     }
-    var indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx);
+    var indentOld = utils.getLinePrefix(node.offset + eol.length + newlineIdx);
     var indentArg = '$indentOld${utils.getIndent(1)}';
     var indentList = '$indentOld${utils.getIndent(2)}';
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
new file mode 100644
index 0000000..5a4d2ec
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/make_variable_nullable.dart
@@ -0,0 +1,106 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class MakeVariableNullable extends CorrectionProducer {
+  /// The name of the variable whose type is to be made nullable.
+  String _variableName;
+
+  @override
+  List<Object> get fixArguments => [_variableName];
+
+  @override
+  FixKind get fixKind => DartFixKind.MAKE_VARIABLE_NULLABLE;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var node = coveredNode;
+    var parent = node?.parent;
+    if (unit.featureSet.isEnabled(Feature.non_nullable) &&
+        parent is AssignmentExpression &&
+        parent.rightHandSide == node) {
+      var leftHandSide = parent.leftHandSide;
+      if (leftHandSide is SimpleIdentifier) {
+        var element = leftHandSide.staticElement;
+        if (element is LocalVariableElement) {
+          var oldType = element.type;
+          var newType = (node as Expression).staticType;
+          if (node is NullLiteral) {
+            newType = (oldType as InterfaceTypeImpl)
+                .withNullability(NullabilitySuffix.question);
+          } else if (!typeSystem.isAssignableTo(
+              oldType, typeSystem.promoteToNonNull(newType))) {
+            return;
+          }
+          var declarationList =
+              _findDeclaration(element, parent.thisOrAncestorOfType<Block>());
+          if (declarationList == null || declarationList.variables.length > 1) {
+            return;
+          }
+          var variable = declarationList.variables[0];
+          _variableName = variable.name.name;
+          await builder.addDartFileEdit(file, (builder) {
+            var keyword = declarationList.keyword;
+            if (keyword != null && keyword.type == Keyword.VAR) {
+              builder.addReplacement(range.token(keyword), (builder) {
+                builder.writeType(newType);
+              });
+            } else if (keyword == null) {
+              if (declarationList.type == null) {
+                builder.addInsertion(variable.offset, (builder) {
+                  builder.writeType(newType);
+                  builder.write(' ');
+                });
+              } else {
+                builder.addSimpleInsertion(declarationList.type.end, '?');
+              }
+            }
+          });
+        }
+      }
+    }
+  }
+
+  /// Return the list of variable declarations containing the declaration of the
+  /// given [variable] that is located in the given [block] or in a surrounding
+  /// block. Return `null` if the declaration can't be found.
+  VariableDeclarationList _findDeclaration(
+      LocalVariableElement variable, Block block) {
+    if (variable == null) {
+      return null;
+    }
+    var currentBlock = block;
+    while (currentBlock != null) {
+      for (var statement in block.statements) {
+        if (statement is VariableDeclarationStatement) {
+          var variableList = statement.variables;
+          if (variableList != null) {
+            var variables = variableList.variables;
+            for (var declaration in variables) {
+              if (declaration.declaredElement == variable) {
+                return variableList;
+              }
+            }
+          }
+        }
+      }
+      currentBlock = currentBlock.parent.thisOrAncestorOfType<Block>();
+    }
+    return null;
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static MakeVariableNullable newInstance() => MakeVariableNullable();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
index d40a8a5..6a6d159 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_annotation.dart
@@ -21,7 +21,7 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    void addFix(Annotation node) async {
+    Future<void> addFix(Annotation node) async {
       if (node == null) {
         return;
       }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
new file mode 100644
index 0000000..080bc4f9
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_comparison.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveComparison extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_COMPARISON;
+
+  /// Return `true` if the null comparison will always return `false`.
+  bool get _conditionIsFalse =>
+      (diagnostic as AnalysisError).errorCode ==
+      HintCode.UNNECESSARY_NULL_COMPARISON_FALSE;
+
+  /// Return `true` if the null comparison will always return `true`.
+  bool get _conditionIsTrue =>
+      (diagnostic as AnalysisError).errorCode ==
+      HintCode.UNNECESSARY_NULL_COMPARISON_TRUE;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    if (node is! BinaryExpression) {
+      return;
+    }
+    var binaryExpression = node as BinaryExpression;
+    var parent = binaryExpression.parent;
+    if (parent is AssertInitializer && _conditionIsTrue) {
+      var constructor = parent.parent as ConstructorDeclaration;
+      var list = constructor.initializers;
+      if (list.length == 1) {
+        await builder.addDartFileEdit(file, (builder) {
+          builder.addDeletion(range.endEnd(constructor.parameters, parent));
+        });
+      } else {
+        await builder.addDartFileEdit(file, (builder) {
+          builder.addDeletion(range.nodeInList(list, parent));
+        });
+      }
+    } else if (parent is AssertStatement && _conditionIsTrue) {
+      await builder.addDartFileEdit(file, (builder) {
+        builder.addDeletion(utils.getLinesRange(range.node(parent)));
+      });
+    } else if (parent is BinaryExpression) {
+      if (parent.operator.type == TokenType.AMPERSAND_AMPERSAND &&
+          _conditionIsTrue) {
+        await _removeOperatorAndOperand(builder, parent, node);
+      } else if (parent.operator.type == TokenType.BAR_BAR &&
+          _conditionIsFalse) {
+        await _removeOperatorAndOperand(builder, parent, node);
+      }
+    } else if (parent is IfStatement) {
+      if (parent.elseStatement == null && _conditionIsTrue) {
+        var body = _extractBody(parent);
+        body = utils.indentSourceLeftRight(body);
+        await builder.addDartFileEdit(file, (builder) {
+          builder.addSimpleReplacement(
+              range.startOffsetEndOffset(
+                  parent.offset, utils.getLineContentEnd(parent.end)),
+              body);
+        });
+      }
+    }
+  }
+
+  String _extractBody(IfStatement statement) {
+    var body = statement.thenStatement;
+    if (body is Block) {
+      var statements = body.statements;
+      return utils.getRangeText(range.startOffsetEndOffset(
+          statements.first.offset,
+          utils.getLineContentEnd(statements.last.end)));
+    }
+    return utils.getNodeText(body);
+  }
+
+  /// Use the [builder] to add an edit to delete the operator and given
+  /// [operand] from the [binary] expression.
+  Future<void> _removeOperatorAndOperand(ChangeBuilder builder,
+      BinaryExpression binary, Expression operand) async {
+    SourceRange operatorAndOperand;
+    if (binary.leftOperand == node) {
+      operatorAndOperand = range.startStart(node, binary.rightOperand);
+    } else {
+      operatorAndOperand = range.endEnd(binary.leftOperand, node);
+    }
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addDeletion(operatorAndOperand);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static RemoveComparison newInstance() => RemoveComparison();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart
index d90106e..790b766 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused.dart
@@ -33,7 +33,7 @@
       final references = _findAllReferences(unit, element);
       // todo (pq): consider filtering for references that are limited to within the class.
       if (references.length == 1) {
-        var sourceRange;
+        SourceRange sourceRange;
         if (referencedNode is VariableDeclaration) {
           VariableDeclarationList parent = referencedNode.parent;
           if (parent.variables.length == 1) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart
index 7adfbe7..2bafcfb 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_null_with_closure.dart
@@ -17,7 +17,7 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var nodeToFix;
+    AstNode nodeToFix;
     var parameters = const <ParameterElement>[];
     if (coveredNode is NamedExpression) {
       NamedExpression namedExpression = coveredNode;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 0f67130..534d910 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -323,6 +323,8 @@
       'Move type arguments to after class name');
   static const MAKE_VARIABLE_NOT_FINAL = FixKind(
       'dart.fix.makeVariableNotFinal', 50, "Make variable '{0}' not final");
+  static const MAKE_VARIABLE_NULLABLE =
+      FixKind('dart.fix.makeVariableNullable', 50, "Make '{0}' nullable");
   static const ORGANIZE_IMPORTS =
       FixKind('dart.fix.organize.imports', 50, 'Organize Imports');
   static const QUALIFY_REFERENCE =
@@ -333,6 +335,8 @@
       FixKind('dart.fix.remove.argument', 50, 'Remove argument');
   static const REMOVE_AWAIT =
       FixKind('dart.fix.remove.await', 50, 'Remove await');
+  static const REMOVE_COMPARISON =
+      FixKind('dart.fix.remove.comparison', 50, 'Remove comparison');
   static const REMOVE_CONST =
       FixKind('dart.fix.remove.const', 50, 'Remove const');
   static const REMOVE_DEAD_CODE =
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
index 32381fa..b176935 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/analysis_options/fix_generator.dart
@@ -87,7 +87,7 @@
     return fixes;
   }
 
-  void _addFix_removeSetting() async {
+  Future<void> _addFix_removeSetting() async {
     if (coveringNodePath[0] is YamlScalar) {
       SourceRange deletionRange;
       var index = 1;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
index e40be74..936237a 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/add_type_parameter.dart
@@ -4,7 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 import 'package:meta/meta.dart';
@@ -20,29 +20,28 @@
 
   /// The name of the type that the type parameter extends, or `null` if the
   /// type parameter doesn't have a bound.
-  final String extendedType;
+  final CodeTemplate extendedType;
 
-  /// The value extractor used to compute the value of the type argument.
-  final ValueExtractor value;
+  /// The code template used to compute the value of the type argument.
+  final CodeTemplate argumentValue;
 
   /// Initialize a newly created change to describe adding a type parameter to a
   /// type or a function.
-  // TODO(brianwilkerson) Support adding multiple type parameters.
   AddTypeParameter(
       {@required this.index,
       @required this.name,
-      @required this.value,
-      this.extendedType})
+      @required this.argumentValue,
+      @required this.extendedType})
       : assert(index >= 0),
         assert(name != null),
-        assert(value != null);
+        assert(argumentValue != null);
 
   @override
   void apply(DartFileEditBuilder builder, DataDrivenFix fix, _Data data) {
     if (data is _TypeArgumentData) {
-      _applyToTypeArguments(builder, data);
+      _applyToTypeArguments(builder, fix, data);
     } else if (data is _TypeParameterData) {
-      _applyToTypeParameters(builder, data);
+      _applyToTypeParameters(builder, fix, data);
     } else {
       throw StateError('Unsupported class of data: ${data.runtimeType}');
     }
@@ -51,23 +50,23 @@
   @override
   _Data validate(DataDrivenFix fix) {
     var node = fix.node;
+    var context = TemplateContext(node, fix.utils);
     if (node is NamedType) {
       // wrong_number_of_type_arguments
       // wrong_number_of_type_arguments_constructor
-      var argument = value.from(node, fix.utils);
-      if (argument == null) {
+      if (!argumentValue.validate(context)) {
         return null;
       }
       var typeArguments = node.typeArguments;
       if (_isInvalidIndex(typeArguments?.arguments)) {
         return null;
       }
-      return _TypeArgumentData(typeArguments, argument, node.name.end);
+      return _TypeArgumentData(typeArguments, node.name.end);
     }
     var parent = node.parent;
     if (parent is InvocationExpression) {
       // wrong_number_of_type_arguments_method
-      var argument = value.from(parent, fix.utils);
+      var argument = argumentValue.validate(context);
       if (argument == null) {
         return null;
       }
@@ -75,10 +74,12 @@
       if (_isInvalidIndex(typeArguments?.arguments)) {
         return null;
       }
-      return _TypeArgumentData(
-          typeArguments, argument, parent.argumentList.offset);
+      return _TypeArgumentData(typeArguments, parent.argumentList.offset);
     } else if (parent is MethodDeclaration) {
       // invalid_override
+      if (extendedType != null && !extendedType.validate(context)) {
+        return null;
+      }
       var typeParameters = parent.typeParameters;
       if (_isInvalidIndex(typeParameters?.typeParameters)) {
         return null;
@@ -86,55 +87,81 @@
       return _TypeParameterData(typeParameters, parent.name.end);
     } else if (node is TypeArgumentList && parent is ExtensionOverride) {
       // wrong_number_of_type_arguments_extension
-      var argument = value.from(node, fix.utils);
+      var argument = argumentValue.validate(context);
       if (argument == null) {
         return null;
       }
       if (_isInvalidIndex(node?.arguments)) {
         return null;
       }
-      return _TypeArgumentData(node, argument, parent.extensionName.end);
+      return _TypeArgumentData(node, parent.extensionName.end);
     }
     return null;
   }
 
   void _applyToTypeArguments(
-      DartFileEditBuilder builder, _TypeArgumentData data) {
+      DartFileEditBuilder builder, DataDrivenFix fix, _TypeArgumentData data) {
+    var context = TemplateContext(fix.node, fix.utils);
     var typeArguments = data.typeArguments;
-    var argumentValue = data.argumentValue;
     if (typeArguments == null) {
       // Adding the first type argument.
-      builder.addSimpleInsertion(data.newListOffset, '<$argumentValue>');
+      builder.addInsertion(data.newListOffset, (builder) {
+        builder.write('<');
+        argumentValue.writeOn(builder, context);
+        builder.write('>');
+      });
     } else {
       if (index == 0) {
         // Inserting the type argument at the beginning of the list.
-        builder.addSimpleInsertion(
-            typeArguments.leftBracket.end, '$argumentValue, ');
+        builder.addInsertion(typeArguments.leftBracket.end, (builder) {
+          argumentValue.writeOn(builder, context);
+          builder.write(', ');
+        });
       } else {
         // Inserting the type argument after an existing type argument.
         var previous = typeArguments.arguments[index - 1];
-        builder.addSimpleInsertion(previous.end, ', $argumentValue');
+        builder.addInsertion(previous.end, (builder) {
+          builder.write(', ');
+          argumentValue.writeOn(builder, context);
+        });
       }
     }
   }
 
   void _applyToTypeParameters(
-      DartFileEditBuilder builder, _TypeParameterData data) {
-    var argumentValue =
-        extendedType == null ? name : '$name extends $extendedType';
+      DartFileEditBuilder builder, DataDrivenFix fix, _TypeParameterData data) {
+    var context = TemplateContext(fix.node, fix.utils);
+
+    void writeParameter(DartEditBuilder builder) {
+      builder.write(name);
+      if (extendedType != null) {
+        builder.write(' extends ');
+        extendedType.writeOn(builder, context);
+      }
+    }
+
     var typeParameters = data.typeParameters;
     if (typeParameters == null) {
       // Adding the first type argument.
-      builder.addSimpleInsertion(data.newListOffset, '<$argumentValue>');
+      builder.addInsertion(data.newListOffset, (builder) {
+        builder.write('<');
+        writeParameter(builder);
+        builder.write('>');
+      });
     } else {
       if (index == 0) {
         // Inserting the type argument at the beginning of the list.
-        builder.addSimpleInsertion(
-            typeParameters.leftBracket.end, '$argumentValue, ');
+        builder.addInsertion(typeParameters.leftBracket.end, (builder) {
+          writeParameter(builder);
+          builder.write(', ');
+        });
       } else {
         // Inserting the type argument after an existing type argument.
         var previous = typeParameters.typeParameters[index - 1];
-        builder.addSimpleInsertion(previous.end, ', $argumentValue');
+        builder.addInsertion(previous.end, (builder) {
+          builder.write(', ');
+          writeParameter(builder);
+        });
       }
     }
   }
@@ -154,15 +181,12 @@
   /// `null` if the first type argument is being added.
   final TypeArgumentList typeArguments;
 
-  /// The value of the type argument being added.
-  final String argumentValue;
-
   /// The offset at which the type argument list should be inserted if
   /// [typeArguments] is `null`.
   final int newListOffset;
 
   /// Initialize newly created data.
-  _TypeArgumentData(this.typeArguments, this.argumentValue, this.newListOffset);
+  _TypeArgumentData(this.typeArguments, this.newListOffset);
 }
 
 /// The data returned when updating a type parameter list.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
new file mode 100644
index 0000000..b5936f4
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/code_template.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+/// An object used to generate code to be inserted.
+class CodeTemplate {
+  /// The kind of code that will be generated by this template.
+  final CodeTemplateKind kind;
+
+  /// The components of the template.
+  final List<TemplateComponent> components;
+
+  /// Initialize a newly generated code template with the given [kind] and
+  /// [components].
+  CodeTemplate(this.kind, this.components)
+      : assert(kind != null),
+        assert(components != null);
+
+  /// Use the [context] to validate that this template will be able to generate
+  /// a value.
+  bool validate(TemplateContext context) {
+    for (var component in components) {
+      if (!component.validate(context)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void writeOn(DartEditBuilder builder, TemplateContext context) {
+    for (var component in components) {
+      component.writeOn(builder, context);
+    }
+  }
+}
+
+/// The kinds of code that can be generated by a template.
+enum CodeTemplateKind {
+  expression,
+  statements,
+}
+
+/// An object used to compute some portion of a template.
+abstract class TemplateComponent {
+  /// Use the [context] to validate that this component will be able to generate
+  /// a value.
+  bool validate(TemplateContext context);
+
+  /// Write the text contributed by this component to the given [builder], using
+  /// the [context] to access needed information that isn't already known to
+  /// this component.
+  void writeOn(DartEditBuilder builder, TemplateContext context);
+}
+
+/// The context in which a template is being evaluated.
+class TemplateContext {
+  /// The node in the AST that is being transformed.
+  final AstNode node;
+
+  /// The utilities used to help extract the code associated with various nodes.
+  final CorrectionUtils utils;
+
+  /// Initialize a newly created variable support.
+  TemplateContext(this.node, this.utils);
+}
+
+/// Literal text within a template.
+class TemplateText extends TemplateComponent {
+  /// The literal text to be included in the resulting code.
+  final String text;
+
+  /// Initialize a newly create template text with the given [text].
+  TemplateText(this.text);
+
+  @override
+  bool validate(TemplateContext context) {
+    return true;
+  }
+
+  @override
+  void writeOn(DartEditBuilder builder, TemplateContext context) {
+    builder.write(text);
+  }
+}
+
+/// A reference to a variable within a template.
+class TemplateVariable extends TemplateComponent {
+  /// The generator used to compute the value of the variable.
+  final ValueGenerator generator;
+
+  /// Initialize a newly created template variable with the given [generator].
+  TemplateVariable(this.generator);
+
+  @override
+  bool validate(TemplateContext context) {
+    return generator.validate(context);
+  }
+
+  @override
+  void writeOn(DartEditBuilder builder, TemplateContext context) {
+    generator.writeOn(builder, context);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index b8f0b84..7fb93d9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -2,32 +2,29 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:meta/meta.dart';
 
 /// The path to an element.
 class ElementDescriptor {
   /// The URIs of the library in which the element is defined.
-  final List<String> libraryUris;
+  final List<Uri> libraryUris;
+
+  /// The kind of element that was changed.
+  final ElementKind kind;
 
   /// The components that uniquely identify the element within its library.
   final List<String> components;
 
   /// Initialize a newly created element descriptor to describe an element
   /// accessible via any of the [libraryUris] where the path to the element
-  /// within the library is given by the list of [components].
-  ElementDescriptor({@required this.libraryUris, @required this.components});
+  /// within the library is given by the list of [components]. The [kind] of the
+  /// element is represented by the key used in the data file.
+  ElementDescriptor(
+      {@required this.libraryUris,
+      @required this.kind,
+      @required this.components});
 
-  /// Return `true` if this descriptor matches an element with the given [name]
-  /// in a library that imports the [importedUris].
-  bool matches(String name, List<String> importedUris) {
-    if (components.last != name) {
-      return false;
-    }
-    for (var importedUri in importedUris) {
-      if (libraryUris.contains(importedUri)) {
-        return true;
-      }
-    }
-    return false;
-  }
+  /// Return `true` if the described element is a constructor.
+  bool get isConstructor => kind == ElementKind.constructorKind;
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
new file mode 100644
index 0000000..c0233f7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// An indication of the kind of an element.
+enum ElementKind {
+  classKind,
+  constantKind,
+  constructorKind,
+  enumKind,
+  extensionKind,
+  fieldKind,
+  functionKind,
+  getterKind,
+  methodKind,
+  mixinKind,
+  setterKind,
+  typedefKind,
+  variableKind
+}
+
+extension ElementKindUtilities on ElementKind {
+  /// Return the element kind corresponding to the given [name].
+  static ElementKind fromName(String name) {
+    for (var kind in ElementKind.values) {
+      if (kind.toString() == 'ElementKind.${name}Kind') {
+        return kind;
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
new file mode 100644
index 0000000..aac5dff
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
+import 'package:meta/meta.dart';
+
+/// An object that can be used to determine whether an element is appropriate
+/// for a given reference.
+class ElementMatcher {
+  /// The URIs of the libraries that are imported in the library containing the
+  /// reference.
+  final List<Uri> importedUris;
+
+  /// The name of the element being referenced.
+  final String name;
+
+  /// A list of the kinds of elements that are appropriate for some given
+  /// location in the code An empty list represents all kinds rather than no
+  /// kinds.
+  List<ElementKind> validKinds;
+
+  /// Initialize a newly created matcher representing a reference to an element
+  /// with the given [name] in a library that imports the [importedUris].
+  ElementMatcher(
+      {@required this.importedUris,
+      @required this.name,
+      List<ElementKind> kinds})
+      : validKinds = kinds ?? const [];
+
+  /// Return `true` if this matcher matches the given [element].
+  bool matches(ElementDescriptor element) {
+    var components = element.components;
+    var lastComponent = components.last;
+    if (lastComponent.isEmpty) {
+      if (components[components.length - 2] != name) {
+        return false;
+      }
+    } else if (lastComponent != name) {
+      return false;
+    }
+
+    if (validKinds.isNotEmpty && !validKinds.contains(element.kind)) {
+      return false;
+    }
+
+    var libraryUris = element.libraryUris;
+    for (var importedUri in importedUris) {
+      if (libraryUris.contains(importedUri)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
index 9423b2e..3cd6143 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
@@ -4,8 +4,8 @@
 
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
@@ -26,22 +26,18 @@
   /// A flag indicating whether the parameter is a positional parameter.
   final bool isPositional;
 
-  /// The default value of the parameter, or `null` if the parameter doesn't
-  /// have a default value.
-  final ValueExtractor defaultValue;
-
-  /// The value of the new argument in invocations of the function, or `null` if
-  /// the parameter is optional and no argument needs to be added. The only time
-  /// an argument needs to be added for an optional parameter is if the
-  /// parameter is positional and there are pre-existing optional positional
-  /// parameters after the ones being added.
-  final ValueExtractor argumentValue;
+  /// The code template used to compute the value of the new argument in
+  /// invocations of the function, or `null` if the parameter is optional and no
+  /// argument needs to be added. The only time an argument needs to be added
+  /// for an optional parameter is if the parameter is positional and there are
+  /// pre-existing optional positional parameters after the ones being added.
+  final CodeTemplate argumentValue;
 
   /// Initialize a newly created parameter modification to represent the
   /// addition of a parameter. If provided, the [argumentValue] will be used as
   /// the value of the new argument in invocations of the function.
   AddParameter(this.index, this.name, this.isRequired, this.isPositional,
-      this.defaultValue, this.argumentValue)
+      this.argumentValue)
       : assert(index >= 0),
         assert(name != null);
 }
@@ -95,12 +91,12 @@
     /// Write to the [builder] the argument associated with a single
     /// [parameter].
     void writeArgument(DartEditBuilder builder, AddParameter parameter) {
-      var value = parameter.argumentValue.from(argumentList, fix.utils);
       if (!parameter.isPositional) {
         builder.write(parameter.name);
         builder.write(': ');
       }
-      builder.write(value);
+      parameter.argumentValue
+          .writeOn(builder, TemplateContext(argumentList, fix.utils));
     }
 
     var insertionRanges = argumentsToInsert.contiguousSubRanges.toList();
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename.dart
index 46135f0..13b32f3 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/rename.dart
@@ -21,7 +21,45 @@
   @override
   void apply(DartFileEditBuilder builder, DataDrivenFix fix,
       SimpleIdentifier nameNode) {
-    builder.addSimpleReplacement(range.node(nameNode), newName);
+    if (fix.element.isConstructor) {
+      var parent = nameNode.parent;
+      if (parent is ConstructorName) {
+        if (nameNode != null && newName.isEmpty) {
+          // The constructor was renamed from a named constructor to an unnamed
+          // constructor.
+          builder.addDeletion(range.startEnd(parent.period, parent));
+        } else if (nameNode == null && newName.isNotEmpty) {
+          // The constructor was renamed from an unnamed constructor to a named
+          // constructor.
+          builder.addSimpleInsertion(parent.end, '.$newName');
+        } else {
+          // The constructor was renamed from a named constructor to another
+          // named constructor.
+          builder.addSimpleReplacement(range.node(nameNode), newName);
+        }
+      } else if (parent is MethodInvocation) {
+        if (newName.isEmpty) {
+          // The constructor was renamed from a named constructor to an unnamed
+          // constructor.
+          builder.addDeletion(range.startEnd(parent.operator, nameNode));
+        } else {
+          // The constructor was renamed from a named constructor to another
+          // named constructor.
+          builder.addSimpleReplacement(range.node(nameNode), newName);
+        }
+      } else if (parent is TypeName && parent.parent is ConstructorName) {
+        // The constructor was renamed from an unnamed constructor to a named
+        // constructor.
+        builder.addSimpleInsertion(parent.end, '.$newName');
+      } else {
+        // The constructor was renamed from a named constructor to another named
+        // constructor.
+        builder.addSimpleReplacement(range.node(nameNode), newName);
+      }
+    } else {
+      // The name is a simple identifier.
+      builder.addSimpleReplacement(range.node(nameNode), newName);
+    }
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
index 251dcb3..cae363d 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform.dart
@@ -4,13 +4,17 @@
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:meta/meta.dart';
 
-/// The behavior common to all of the data used to construct fixes.
+/// A description of a set of changes to a single element of the API.
 class Transform {
   /// The human-readable title describing the transform.
   final String title;
 
+  /// The date on which the API was changed.
+  final DateTime date;
+
   /// The element being transformed.
   final ElementDescriptor element;
 
@@ -20,12 +24,14 @@
   /// Initialize a newly created transform to describe a transformation of the
   /// [element].
   Transform(
-      {@required this.title, @required this.element, @required this.changes});
+      {@required this.title,
+      this.date,
+      @required this.element,
+      @required this.changes});
 
   /// Return `true` if this transform can be applied to fix an issue related to
-  /// an element with the given [name] in a library that imports the
-  /// [importedUris].
-  bool appliesTo(String name, List<String> importedUris) {
-    return element.matches(name, importedUris);
+  /// an element that matches the given [matcher].
+  bool appliesTo(ElementMatcher matcher) {
+    return matcher.matches(element);
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
index e5c7445..df26be6 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 
 /// A set of transforms used to aid in the construction of fixes for issues
@@ -16,12 +17,11 @@
     _transforms.add(transform);
   }
 
-  /// Return a list of the transforms that apply for a reference to the given
-  /// [name] in a library that imports the [importedUris].
-  List<Transform> transformsFor(String name, List<String> importedUris) {
+  /// Return a list of the transforms that match the [matcher].
+  List<Transform> transformsFor(ElementMatcher matcher) {
     var result = <Transform>[];
     for (var transform in _transforms) {
-      if (transform.appliesTo(name, importedUris)) {
+      if (transform.appliesTo(matcher)) {
         result.add(transform);
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
index f44c739..8394acd 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
@@ -15,22 +15,51 @@
    * 0: the actual type of the value
    */
   static const TransformSetErrorCode invalidValue = TransformSetErrorCode(
-      'invalidValue',
+      'invalid_value',
       "The value of '{0}' should be of type '{1}' but is of type '{2}'.");
 
   /**
    * Parameters:
+   * 0: the key with which the value is associated
+   * 1: the allowed values as a comma-separated list
+   */
+  static const TransformSetErrorCode invalidValueOneOf = TransformSetErrorCode(
+      'invalid_value_one_of',
+      "The value of '{0}' must be one of the following: '{1}'.");
+
+  /**
+   * Parameters:
+   * 0: the missing key
+   */
+  static const TransformSetErrorCode missingKey =
+      TransformSetErrorCode('missing_key', "Missing the required key '{0}'.");
+
+  /**
+   * No parameters.
+   */
+  static const TransformSetErrorCode missingTemplateEnd = TransformSetErrorCode(
+      'missing_template_end', "Missing the end brace for the template.");
+
+  /**
+   * Parameters:
+   * 0: the missing key
+   */
+  static const TransformSetErrorCode undefinedVariable = TransformSetErrorCode(
+      'undefined_variable', "The variable '{0}' is not defined.");
+
+  /**
+   * Parameters:
    * 0: the unsupported key
    */
-  static const TransformSetErrorCode unsupportedKey =
-      TransformSetErrorCode('unsupportedKey', "The key '{0}' isn't supported.");
+  static const TransformSetErrorCode unsupportedKey = TransformSetErrorCode(
+      'unsupported_key', "The key '{0}' isn't supported.");
 
   /**
    * Parameters:
    * 0: the message produced by the YAML parser
    */
   static const TransformSetErrorCode yamlSyntaxError =
-      TransformSetErrorCode('yamlSyntaxError', "Parse error: {0}");
+      TransformSetErrorCode('yaml_syntax_error', "Parse error: {0}");
 
   /// Initialize a newly created error code.
   const TransformSetErrorCode(String name, String message,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
index 52cecbb..b477af8 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
@@ -25,6 +25,9 @@
     var workspace = library.session.analysisContext.workspace;
     var libraryPath = library.source.fullName;
     var package = workspace.findPackageFor(libraryPath);
+    if (package == null) {
+      return transformSets;
+    }
     var packageMap = package.packagesAvailableTo(libraryPath);
     for (var entry in packageMap.entries) {
       var directory = entry.value[0];
@@ -45,8 +48,10 @@
     try {
       // TODO(brianwilkerson) Consider caching the transform sets.
       var content = file.readAsStringSync();
-      var parser = TransformSetParser(ErrorReporter(
-          AnalysisErrorListener.NULL_LISTENER, file.createSource()));
+      var parser = TransformSetParser(
+          ErrorReporter(
+              AnalysisErrorListener.NULL_LISTENER, file.createSource()),
+          file.parent.parent.shortName);
       return parser.parse(content);
     } on FileSystemException {
       // Fall through to return `null`.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
index b81936e..30d05a2 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_parser.dart
@@ -4,18 +4,35 @@
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/change.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/modify_parameters.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
 import 'package:analysis_server/src/utilities/extensions/yaml.dart';
 import 'package:analyzer/error/listener.dart';
+import 'package:meta/meta.dart';
 import 'package:yaml/yaml.dart';
 
+/// Information used to report errors when translating a node.
+class ErrorContext {
+  /// The name of the key used to identify the node that has an error associated
+  /// with it.
+  final String key;
+
+  /// The node that should be used to compute the highlight region for the
+  /// diagnostic.
+  final YamlNode parentNode;
+
+  /// Initialize a newly created error context.
+  ErrorContext({@required this.key, @required this.parentNode});
+}
+
 /// A parser used to read a transform set from a file.
 class TransformSetParser {
   static const String _argumentValueKey = 'argumentValue';
@@ -23,9 +40,11 @@
   static const String _classKey = 'class';
   static const String _constantKey = 'constant';
   static const String _constructorKey = 'constructor';
-  static const String _defaultValueKey = 'defaultValue';
+  static const String _dateKey = 'date';
   static const String _elementKey = 'element';
   static const String _enumKey = 'enum';
+  static const String _expressionKey = 'expression';
+  static const String _extendsKey = 'extends';
   static const String _extensionKey = 'extension';
   static const String _fieldKey = 'field';
   static const String _functionKey = 'function';
@@ -41,12 +60,14 @@
   static const String _nameKey = 'name';
   static const String _newNameKey = 'newName';
   static const String _setterKey = 'setter';
+  static const String _statementsKey = 'statements';
   static const String _styleKey = 'style';
   static const String _titleKey = 'title';
   static const String _transformsKey = 'transforms';
   static const String _typedefKey = 'typedef';
   static const String _urisKey = 'uris';
-  static const String _valueKey = 'value';
+  static const String _variableKey = 'variable';
+  static const String _variablesKey = 'variables';
   static const String _versionKey = 'version';
 
   /// A table mapping top-level keys for member elements to the list of keys for
@@ -63,21 +84,39 @@
   static const String _addParameterKind = 'addParameter';
   static const String _addTypeParameterKind = 'addTypeParameter';
   static const String _argumentKind = 'argument';
+  static const String _importKind = 'import';
   static const String _removeParameterKind = 'removeParameter';
   static const String _renameKind = 'rename';
 
+  /// The valid values for the [_styleKey] in an [_addParameterKind] change.
+  static const List<String> validStyles = [
+    'optional_named',
+    'optional_positional',
+    'required_named',
+    'required_positional'
+  ];
+
+  static const String _openComponent = '{%';
+  static const String _closeComponent = '%}';
+
+  /// The highest file version supported by this parser. The version needs to be
+  /// incremented any time the parser is updated to disallow input that would
+  /// have been valid in the most recently published version of server. This
+  /// includes removing support for keys and adding a new required key.
   static const int currentVersion = 1;
 
   /// The error reporter to which diagnostics will be reported.
   final ErrorReporter errorReporter;
 
+  final String packageName;
+
   /// The parameter modifications associated with the current transform, or
   /// `null` if the current transform does not yet have any such modifications.
   List<ParameterModification> _parameterModifications;
 
   /// Initialize a newly created parser to report diagnostics to the
   /// [errorReporter].
-  TransformSetParser(this.errorReporter);
+  TransformSetParser(this.errorReporter, this.packageName);
 
   /// Return the result of parsing the file [content] into a transform set, or
   /// `null` if the content does not represent a valid transform set.
@@ -91,6 +130,52 @@
     return _translateTransformSet(map);
   }
 
+  /// Convert the given [template] into a list of components. Variable
+  /// references in the template are looked up in the map of [generators].
+  List<TemplateComponent> _extractTemplateComponents(String template,
+      Map<String, ValueGenerator> generators, int templateOffset) {
+    var components = <TemplateComponent>[];
+    var textStart = 0;
+    var variableStart = template.indexOf(_openComponent);
+    while (variableStart >= 0) {
+      if (textStart < variableStart) {
+        // TODO(brianwilkerson) Check for an end brace without a start brace.
+        components
+            .add(TemplateText(template.substring(textStart, variableStart)));
+      }
+      var endIndex = template.indexOf(_closeComponent, variableStart + 2);
+      if (endIndex < 0) {
+        errorReporter.reportErrorForOffset(
+            TransformSetErrorCode.missingTemplateEnd,
+            templateOffset + variableStart,
+            2);
+        // Ignore the invalid component, treating it as if it extended to the
+        // end of the template.
+        return components;
+      } else {
+        var name = template.substring(variableStart + 2, endIndex).trim();
+        var generator = generators[name];
+        if (generator == null) {
+          errorReporter.reportErrorForOffset(
+              TransformSetErrorCode.undefinedVariable,
+              templateOffset + template.indexOf(name, variableStart),
+              name.length,
+              [name]);
+          // Ignore the invalid component.
+        } else {
+          components.add(TemplateVariable(generator));
+        }
+      }
+      textStart = endIndex + 2;
+      variableStart = template.indexOf(_openComponent, textStart);
+    }
+    if (textStart < template.length) {
+      // TODO(brianwilkerson) Check for an end brace without a start brace.
+      components.add(TemplateText(template.substring(textStart)));
+    }
+    return components;
+  }
+
   /// Return a textual description of the type of value represented by the
   /// [node].
   String _nodeType(YamlNode node) {
@@ -127,17 +212,38 @@
         code, span.start.offset, span.length, arguments);
   }
 
+  /// Report that the value represented by the [node] does not have the
+  /// [expectedType], using the [context] to get the key to use in the message.
+  Null _reportInvalidValue(
+      YamlNode node, ErrorContext context, String expectedType) {
+    _reportError(TransformSetErrorCode.invalidValue, node,
+        [context.key, expectedType, _nodeType(node)]);
+    return null;
+  }
+
+  /// Report that the value represented by the [node] does not have the
+  /// [expectedType], using the [context] to get the key to use in the message.
+  Null _reportInvalidValueOneOf(
+      YamlNode node, ErrorContext context, List<String> allowedValues) {
+    _reportError(TransformSetErrorCode.invalidValueOneOf, node,
+        [context.key, allowedValues.join(', ')]);
+    return null;
+  }
+
+  /// Report that a required key is missing, using the [context] to locate the
+  /// node associated with the diagnostic and the key to use in the message.
+  Null _reportMissingKey(ErrorContext context) {
+    _reportError(
+        TransformSetErrorCode.missingKey, context.parentNode, [context.key]);
+    return null;
+  }
+
   /// Report any keys in the [map] whose values are not in [validKeys].
   void _reportUnsupportedKeys(YamlMap map, Set<String> validKeys) {
     for (var keyNode in map.nodes.keys) {
-      if (keyNode is YamlScalar && keyNode.value is String) {
-        var key = keyNode.value as String;
-        if (key != null && !validKeys.contains(key)) {
-          _reportError(TransformSetErrorCode.unsupportedKey, keyNode, [key]);
-        }
-      } else {
-        // TODO(brianwilkerson) Report the invalidKey.
-        //  "Keys must be of type 'String' but found the type '{0}'."
+      var key = _translateKey(keyNode);
+      if (key != null && !validKeys.contains(key)) {
+        _reportError(TransformSetErrorCode.unsupportedKey, keyNode, [key]);
       }
     }
   }
@@ -146,9 +252,7 @@
   /// is in the map and return it. If more than one of the keys is in the map,
   /// report a diagnostic.
   String _singleKey(YamlMap map, List<String> validKeys) {
-    if (validKeys == null) {
-      return null;
-    }
+    assert(validKeys != null);
     var foundKeys = <String>[];
     var keyToNodeMap = <String, YamlNode>{};
     for (var keyNode in map.nodes.keys) {
@@ -161,6 +265,7 @@
       }
     }
     if (foundKeys.isEmpty) {
+      // TODO(brianwilkerson) Report the problem.
       return null;
     }
     for (var i = 1; i < foundKeys.length; i++) {
@@ -172,34 +277,30 @@
 
   /// Translate the [node] into a add-parameter modification.
   void _translateAddParameterChange(YamlMap node) {
-    _singleKey(node, [_indexKey, _nameKey]);
-    _reportUnsupportedKeys(node, const {_indexKey, _kindKey, _nameKey});
-    var index = _translateInteger(node.valueAt(_indexKey), _indexKey);
+    _reportUnsupportedKeys(node,
+        const {_argumentValueKey, _indexKey, _kindKey, _nameKey, _styleKey});
+    var index = _translateInteger(node.valueAt(_indexKey),
+        ErrorContext(key: _indexKey, parentNode: node));
     if (index == null) {
       return;
     }
-    var name = _translateString(node.valueAt(_nameKey), _nameKey);
+    var name = _translateString(
+        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
     if (name == null) {
       return;
     }
-    var style = _translateString(node.valueAt(_styleKey), _styleKey);
+    var style = _translateString(node.valueAt(_styleKey),
+        ErrorContext(key: _styleKey, parentNode: node));
     if (style == null) {
       return;
+    } else if (!validStyles.contains(style)) {
+      // TODO(brianwilkerson) Report the invalid style.
+      return;
     }
     var isRequired = style.startsWith('required_');
     var isPositional = style.endsWith('_positional');
-    // TODO(brianwilkerson) I originally thought we'd need a default value, but
-    //  it seems like we ought to be able to get it from the overridden method,
-    //  so investigate removing this field.
-    var defaultValue = _translateValueExtractor(
-        node.valueAt(_defaultValueKey), _defaultValueKey);
-    if (isRequired && defaultValue != null) {
-      // TODO(brianwilkerson) Report that required parameters can't have a
-      //  default value.
-      return;
-    }
-    var argumentValue = _translateValueExtractor(
-        node.valueAt(_argumentValueKey), _argumentValueKey);
+    var argumentValue = _translateCodeTemplate(node.valueAt(_argumentValueKey),
+        ErrorContext(key: _argumentValueKey, parentNode: node));
     // TODO(brianwilkerson) We really ought to require an argument value for
     //  optional positional parameters too for the case where the added
     //  parameter is being added before the end of the list and call sites might
@@ -212,8 +313,8 @@
       return;
     }
     _parameterModifications ??= [];
-    _parameterModifications.add(AddParameter(
-        index, name, isRequired, isPositional, defaultValue, argumentValue));
+    _parameterModifications.add(
+        AddParameter(index, name, isRequired, isPositional, argumentValue));
   }
 
   /// Translate the [node] into an add-type-parameter change. Return the
@@ -221,45 +322,56 @@
   /// add-type-parameter change.
   AddTypeParameter _translateAddTypeParameterChange(YamlMap node) {
     _reportUnsupportedKeys(
-        node, const {_indexKey, _kindKey, _nameKey, _valueKey});
-    var index = _translateInteger(node.valueAt(_indexKey), _indexKey);
-    if (index == null) {
+        node, const {_indexKey, _kindKey, _nameKey, _argumentValueKey});
+    var index = _translateInteger(node.valueAt(_indexKey),
+        ErrorContext(key: _indexKey, parentNode: node));
+    var name = _translateString(
+        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
+    var extendedType = _translateCodeTemplate(node.valueAt(_extendsKey),
+        ErrorContext(key: _extendsKey, parentNode: node),
+        required: false);
+    var argumentValue = _translateCodeTemplate(node.valueAt(_argumentValueKey),
+        ErrorContext(key: _argumentValueKey, parentNode: node));
+    if (index == null || name == null || argumentValue == null) {
+      // The error has already been reported.
       return null;
     }
-    var name = _translateString(node.valueAt(_nameKey), _nameKey);
-    if (name == null) {
-      return null;
-    }
-    var value = _translateValueExtractor(node.valueAt(_valueKey), _valueKey);
-    if (value == null) {
-      return null;
-    }
-    return AddTypeParameter(index: index, name: name, value: value);
+    // TODO(brianwilkerson) In order to support adding multiple type parameters
+    //  we might need to introduce a `TypeParameterModification` change, similar
+    //  to `ParameterModification`. That becomes more likely if we add support
+    //  for removing type parameters.
+    return AddTypeParameter(
+        index: index,
+        name: name,
+        extendedType: extendedType,
+        argumentValue: argumentValue);
   }
 
   /// Translate the [node] into a value extractor. Return the resulting
   /// extractor, or `null` if the [node] does not represent a valid value
   /// extractor.
-  ValueExtractor _translateArgumentExtractor(YamlMap node) {
+  ValueGenerator _translateArgumentExtractor(YamlMap node) {
     var indexNode = node.valueAt(_indexKey);
     if (indexNode != null) {
       _reportUnsupportedKeys(node, const {_indexKey, _kindKey});
-      var index = _translateInteger(indexNode, _indexKey);
+      var index = _translateInteger(
+          indexNode, ErrorContext(key: _indexKey, parentNode: node));
       if (index == null) {
         // The error has already been reported.
         return null;
       }
-      return ArgumentExtractor(PositionalParameterReference(index));
+      return ArgumentExpression(PositionalParameterReference(index));
     }
     var nameNode = node.valueAt(_nameKey);
     if (nameNode != null) {
       _reportUnsupportedKeys(node, const {_nameKey, _kindKey});
-      var name = _translateString(nameNode, _nameKey);
+      var name = _translateString(
+          nameNode, ErrorContext(key: _nameKey, parentNode: node));
       if (name == null) {
         // The error has already been reported.
         return null;
       }
-      return ArgumentExtractor(NamedParameterReference(name));
+      return ArgumentExpression(NamedParameterReference(name));
     }
     // TODO(brianwilkerson) Report the missing YAML.
     return null;
@@ -267,48 +379,117 @@
 
   /// Translate the [node] into a change. Return the resulting change, or `null`
   /// if the [node] does not represent a valid change. If the [node] is not
-  /// valid, use the name of the associated [key] to report the error.
-  Change _translateChange(YamlNode node, String key) {
+  /// valid, use the [context] to report the error.
+  Change _translateChange(YamlNode node, ErrorContext context) {
+    assert(node != null);
     if (node is YamlMap) {
-      var kind = _translateString(node.valueAt(_kindKey), _kindKey);
-      if (kind == _addTypeParameterKind) {
-        return _translateAddTypeParameterChange(node);
-      } else if (kind == _renameKind) {
-        return _translateRenameChange(node);
+      var kind = _translateString(node.valueAt(_kindKey),
+          ErrorContext(key: _kindKey, parentNode: node));
+      if (kind == null) {
+        return null;
       } else if (kind == _addParameterKind) {
         _translateAddParameterChange(node);
         return null;
+      } else if (kind == _addTypeParameterKind) {
+        return _translateAddTypeParameterChange(node);
       } else if (kind == _removeParameterKind) {
         _translateRemoveParameterChange(node);
         return null;
+      } else if (kind == _renameKind) {
+        return _translateRenameChange(node);
       }
-      // TODO(brianwilkerson) Report the invalid change kind.
-      return null;
+      return _reportInvalidValueOneOf(node, context, [
+        _addParameterKind,
+        _addTypeParameterKind,
+        _removeParameterKind,
+        _renameKind,
+      ]);
+    } else {
+      return _reportInvalidValue(node, context, 'Map');
+    }
+  }
+
+  /// Translate the [node] into a code template. Return the resulting template,
+  /// or `null` if the [node] does not represent a valid code template. If the
+  /// [node] is not valid, use the [context] to report the error.
+  CodeTemplate _translateCodeTemplate(YamlNode node, ErrorContext context,
+      {bool required = true}) {
+    if (node is YamlMap) {
+      CodeTemplateKind kind;
+      int templateOffset;
+      String template;
+      var expressionNode = node.valueAt(_expressionKey);
+      if (expressionNode != null) {
+        _reportUnsupportedKeys(node, const {_expressionKey, _variablesKey});
+        kind = CodeTemplateKind.expression;
+        // TODO(brianwilkerson) We add 1 to account for the quotes around the
+        //  string, but quotes aren't required, so we need to find out what
+        //  style of node [expressionNode] is to get the right offset.
+        templateOffset = expressionNode.span.start.offset + 1;
+        template = _translateString(expressionNode,
+            ErrorContext(key: _expressionKey, parentNode: node));
+      } else {
+        var statementsNode = node.valueAt(_statementsKey);
+        if (statementsNode != null) {
+          _reportUnsupportedKeys(node, const {_statementsKey, _variablesKey});
+          kind = CodeTemplateKind.statements;
+          // TODO(brianwilkerson) We add 1 to account for the quotes around the
+          //  string, but quotes aren't required, so we need to find out what
+          //  style of node [expressionNode] is to get the right offset.
+          templateOffset = statementsNode.span.start.offset + 1;
+          template = _translateString(statementsNode,
+              ErrorContext(key: _statementsKey, parentNode: node));
+        } else {
+          // TODO(brianwilkerson) Report the missing key.
+          return null;
+        }
+      }
+      // TODO(brianwilkerson) We should report unreferenced variables.
+      var generators = _translateTemplateVariables(node.valueAt(_variablesKey),
+          ErrorContext(key: _variablesKey, parentNode: node));
+      var components =
+          _extractTemplateComponents(template, generators, templateOffset);
+      return CodeTemplate(kind, components);
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
+      if (required) {
+        _reportMissingKey(context);
+      }
       return null;
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'Map', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'Map');
+    }
+  }
+
+  /// Translate the [node] into a date. Return the resulting date, or `null`
+  /// if the [node] does not represent a valid date. If the [node] is not
+  /// valid, use the [context] to report the error.
+  DateTime _translateDate(YamlNode node, ErrorContext context) {
+    if (node is YamlScalar) {
+      var value = node.value;
+      if (value is String) {
+        try {
+          return DateTime.parse(value);
+        } on FormatException {
+          // Fall through to report the invalid value.
+        }
+      }
+      return _reportInvalidValue(node, context, 'Date');
+    } else if (node == null) {
+      return _reportMissingKey(context);
+    } else {
+      return _reportInvalidValue(node, context, 'Date');
     }
   }
 
   /// Translate the [node] into an element descriptor. Return the resulting
   /// descriptor, or `null` if the [node] does not represent a valid element
-  /// descriptor. If the [node] is not valid, use the name of the associated
-  /// [key] to report the error.
-  ElementDescriptor _translateElement(YamlNode node, String key) {
+  /// descriptor. If the [node] is not valid, use the [context] to report the
+  /// error.
+  ElementDescriptor _translateElement(YamlNode node, ErrorContext context) {
     if (node is YamlMap) {
-      var uris =
-          _translateList(node.valueAt(_urisKey), _urisKey, _translateString);
-      if (uris == null) {
-        // The error has already been reported.
-        // TODO(brianwilkerson) Returning here prevents other errors from being
-        //  reported.
-        return null;
-      }
-      var elementKey = _singleKey(node, [
+      var uris = _translateList(node.valueAt(_urisKey),
+          ErrorContext(key: _urisKey, parentNode: node), _translateUri);
+      var elementKey = _singleKey(node, const [
         _classKey,
         _constantKey,
         _constructorKey,
@@ -320,97 +501,144 @@
         _methodKey,
         _mixinKey,
         _setterKey,
-        _typedefKey
+        _typedefKey,
+        _variableKey
       ]);
-      var elementName = _translateString(node.valueAt(elementKey), elementKey);
+      if (elementKey == null) {
+        // The error has already been reported.
+        return null;
+      }
+      var elementName = _translateString(node.valueAt(elementKey),
+          ErrorContext(key: elementKey, parentNode: node));
       if (elementName == null) {
         // The error has already been reported.
         return null;
       }
       var components = [elementName];
-      var containerKey = _singleKey(node, _containerKeyMap[elementKey]);
-      var containerName =
-          _translateString(node.valueAt(containerKey), containerKey);
-      if (containerName == null) {
-        if ([_constructorKey, _constantKey, _methodKey, _fieldKey]
-            .contains(elementKey)) {
-          // TODO(brianwilkerson) Report that no container was found.
-          return null;
+      if (_containerKeyMap.containsKey(elementKey)) {
+        var containerKey = _singleKey(node, _containerKeyMap[elementKey]);
+        var containerName = _translateString(node.valueAt(containerKey),
+            ErrorContext(key: containerKey, parentNode: node),
+            required: false);
+        if (containerName == null) {
+          if ([_constructorKey, _constantKey, _methodKey, _fieldKey]
+              .contains(elementKey)) {
+            // TODO(brianwilkerson) Report that no container was found.
+            return null;
+          }
+        } else {
+          components.insert(0, containerName);
         }
-      } else {
-        components.insert(0, containerName);
       }
-      return ElementDescriptor(libraryUris: uris, components: components);
+      if (uris == null) {
+        // The error has already been reported.
+        return null;
+      }
+      return ElementDescriptor(
+          libraryUris: uris,
+          kind: ElementKindUtilities.fromName(elementKey),
+          components: components);
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
-      return null;
+      return _reportMissingKey(context);
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'Map', _nodeType(node)]);
+      return _reportInvalidValue(node, context, 'Map');
+    }
+  }
+
+  /// Translate the [node] into a value extractor. Return the resulting
+  /// extractor, or `null` if the [node] does not represent a valid value
+  /// extractor.
+  ValueGenerator _translateImportValue(YamlMap node) {
+    _reportUnsupportedKeys(node, const {_kindKey, _nameKey, _urisKey});
+    var uris = _translateList(node.valueAt(_urisKey),
+        ErrorContext(key: _urisKey, parentNode: node), _translateUri);
+    var name = _translateString(
+        node.valueAt(_nameKey), ErrorContext(key: _nameKey, parentNode: node));
+    if (uris == null || name == null) {
+      // The error has already been reported.
       return null;
     }
+    if (uris.isEmpty) {
+      // TODO(brianwilkerson) Report an empty list unless it's only empty
+      //  because the elements generated errors. This probably needs to be done
+      //  in [_translateList].
+      return null;
+    }
+    return ImportedName(uris, name);
   }
 
   /// Translate the [node] into an integer. Return the resulting integer, or
   /// `null` if the [node] does not represent a valid integer. If the [node] is
-  /// not valid, use the name of the associated [key] to report the error.
-  int _translateInteger(YamlNode node, String key) {
+  /// not valid, use the [context] to report the error.
+  int _translateInteger(YamlNode node, ErrorContext context) {
     if (node is YamlScalar) {
       var value = node.value;
       if (value is int) {
         return value;
       }
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'int', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'int');
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML. For the best UX we
-      //  probably need to pass in the code to report.
-      return null;
+      return _reportMissingKey(context);
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'int', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'int');
     }
   }
 
+  /// Translate the given [node] as a key.
+  String _translateKey(YamlNode node) {
+    if (node is YamlScalar && node.value is String) {
+      return node.value as String;
+    }
+    // TODO(brianwilkerson) Report the invalidKey.
+    //  "Keys must be of type 'String' but found the type '{0}'."
+    return null;
+  }
+
   /// Translate the [node] into a list of objects using the [elementTranslator].
   /// Return the resulting list, or `null` if the [node] does not represent a
   /// valid list. If any of the elements of the list can't be translated, they
-  /// will be omitted from the list, the name of the associated [key] will be
-  /// used to report the error, and the valid elements will be returned.
-  List<R> _translateList<R>(YamlNode node, String key,
-      R Function(YamlNode, String) elementTranslator) {
+  /// will be omitted from the list, the [context] will be used to report the
+  /// error, and the valid elements will be returned.
+  List<R> _translateList<R>(YamlNode node, ErrorContext context,
+      R Function(YamlNode, ErrorContext) elementTranslator) {
     if (node is YamlList) {
       var translatedList = <R>[];
       for (var element in node.nodes) {
-        var result = elementTranslator(element, key);
+        var result = elementTranslator(element, context);
         if (result != null) {
           translatedList.add(result);
         }
       }
       return translatedList;
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
-      return null;
+      return _reportMissingKey(context);
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'List', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'List');
     }
   }
 
   /// Translate the [node] into a remove-parameter modification.
   void _translateRemoveParameterChange(YamlMap node) {
-    _singleKey(node, [_indexKey, _nameKey]);
     _reportUnsupportedKeys(node, const {_indexKey, _kindKey, _nameKey});
     ParameterReference reference;
-    var index = _translateInteger(node.valueAt(_indexKey), _indexKey);
-    if (index != null) {
+    var parameterSpecKey = _singleKey(node, const [_nameKey, _indexKey]);
+    if (parameterSpecKey == null) {
+      // The error has already been reported.
+      return null;
+    }
+    if (parameterSpecKey == _indexKey) {
+      var index = _translateInteger(node.valueAt(_indexKey),
+          ErrorContext(key: _indexKey, parentNode: node));
+      if (parameterSpecKey == null) {
+        // The error has already been reported.
+        return null;
+      }
       reference = PositionalParameterReference(index);
     } else {
-      var name = _translateString(node.valueAt(_nameKey), _nameKey);
+      var name = _translateString(node.valueAt(_nameKey),
+          ErrorContext(key: _nameKey, parentNode: node));
       if (name == null) {
+        // The error has already been reported.
         return;
       }
       reference = NamedParameterReference(name);
@@ -423,7 +651,8 @@
   /// `null` if the [node] does not represent a valid rename change.
   Rename _translateRenameChange(YamlMap node) {
     _reportUnsupportedKeys(node, const {_kindKey, _newNameKey});
-    var newName = _translateString(node.valueAt(_newNameKey), _newNameKey);
+    var newName = _translateString(node.valueAt(_newNameKey),
+        ErrorContext(key: _newNameKey, parentNode: node));
     if (newName == null) {
       return null;
     }
@@ -432,38 +661,68 @@
 
   /// Translate the [node] into a string. Return the resulting string, or `null`
   /// if the [node] does not represent a valid string. If the [node] is not
-  /// valid, use the name of the associated [key] to report the error.
-  String _translateString(YamlNode node, String key) {
+  /// valid, use the [context] to report the error.
+  String _translateString(YamlNode node, ErrorContext context,
+      {bool required = true}) {
     if (node is YamlScalar) {
       var value = node.value;
       if (value is String) {
         return value;
       }
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'String', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'String');
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML. For the best UX we
-      //  probably need to pass in the code to report.
+      if (required) {
+        return _reportMissingKey(context);
+      }
       return null;
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'String', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'String');
+    }
+  }
+
+  /// Translate the [node] into a list of template components. Return the
+  /// resulting list, or `null` if the [node] does not represent a valid
+  /// variables map. If the [node] is not valid, use the [context] to report the
+  /// error.
+  Map<String, ValueGenerator> _translateTemplateVariables(
+      YamlNode node, ErrorContext context) {
+    if (node is YamlMap) {
+      var generators = <String, ValueGenerator>{};
+      for (var entry in node.nodes.entries) {
+        var name = _translateKey(entry.key);
+        if (name != null) {
+          var value = _translateValueGenerator(
+              entry.value, ErrorContext(key: name, parentNode: node));
+          if (value != null) {
+            generators[name] = value;
+          }
+        }
+      }
+      return generators;
+    } else if (node == null) {
+      return const {};
+    } else {
+      return _reportInvalidValue(node, context, 'Map');
     }
   }
 
   /// Translate the [node] into a transform. Return the resulting transform, or
   /// `null` if the [node] does not represent a valid transform. If the [node]
-  /// is not valid, use the name of the associated [key] to report the error.
-  Transform _translateTransform(YamlNode node, String key) {
+  /// is not valid, use the [context] to report the error.
+  Transform _translateTransform(YamlNode node, ErrorContext context) {
+    assert(node != null);
     if (node is YamlMap) {
-      _reportUnsupportedKeys(node, const {_changesKey, _elementKey, _titleKey});
-      var title = _translateString(node.valueAt(_titleKey), _titleKey);
-      var element = _translateElement(node.valueAt(_elementKey), _elementKey);
-      var changes = _translateList(
-          node.valueAt(_changesKey), _changesKey, _translateChange);
-      if (changes == null) {
+      _reportUnsupportedKeys(
+          node, const {_changesKey, _dateKey, _elementKey, _titleKey});
+      var title = _translateString(node.valueAt(_titleKey),
+          ErrorContext(key: _titleKey, parentNode: node));
+      var date = _translateDate(node.valueAt(_dateKey),
+          ErrorContext(key: _dateKey, parentNode: node));
+      var element = _translateElement(node.valueAt(_elementKey),
+          ErrorContext(key: _elementKey, parentNode: node));
+      var changes = _translateList(node.valueAt(_changesKey),
+          ErrorContext(key: _changesKey, parentNode: node), _translateChange);
+      if (title == null || date == null || element == null || changes == null) {
         // The error has already been reported.
         return null;
       }
@@ -471,68 +730,100 @@
         changes.add(ModifyParameters(modifications: _parameterModifications));
         _parameterModifications = null;
       }
-      return Transform(title: title, element: element, changes: changes);
-    } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
-      return null;
+      return Transform(
+          title: title, date: date, element: element, changes: changes);
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'Map', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'Map');
     }
   }
 
   /// Translate the [node] into a transform set. Return the resulting transform
   /// set, or `null` if the [node] does not represent a valid transform set.
   TransformSet _translateTransformSet(YamlNode node) {
+    assert(node != null);
     if (node is YamlMap) {
       _reportUnsupportedKeys(node, const {_transformsKey, _versionKey});
-      var set = TransformSet();
+      var version = _translateInteger(node.valueAt(_versionKey),
+          ErrorContext(key: _versionKey, parentNode: node));
+      if (version == null) {
+        // The error has already been reported.
+        return null;
+      } else if (version > currentVersion) {
+        // TODO(brianwilkerson) Report that the version is unsupported.
+        return null;
+      }
       // TODO(brianwilkerson) Version information is currently being ignored,
       //  but needs to be used to select a translator.
-      var version = _translateInteger(node.valueAt(_versionKey), _versionKey);
-      if (version != currentVersion) {
-        // TODO(brianwilkerson) Report the unsupported version.
-      }
-      var transformations = _translateList(
-          node.valueAt(_transformsKey), _transformsKey, _translateTransform);
-      if (transformations == null) {
+      var transforms = _translateList(
+          node.valueAt(_transformsKey),
+          ErrorContext(key: _transformsKey, parentNode: node),
+          _translateTransform);
+      if (transforms == null) {
         // The error has already been reported.
         return null;
       }
-      for (var transform in transformations) {
+      transforms.sort((first, second) => first.date.compareTo(second.date));
+      var set = TransformSet();
+      for (var transform in transforms) {
         set.addTransform(transform);
       }
       return set;
-    } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
-      return null;
     } else {
+      // TODO(brianwilkerson) Consider having a different error code for the
+      //  top-level node (instead of using 'file' as the "key").
       _reportError(TransformSetErrorCode.invalidValue, node,
           ['file', 'Map', _nodeType(node)]);
       return null;
     }
   }
 
-  /// Translate the [node] into a value extractor. Return the resulting
-  /// extractor, or `null` if the [node] does not represent a valid value
-  /// extractor. If the [node] is not valid, use the name of the associated
-  /// [key] to report the error.
-  ValueExtractor _translateValueExtractor(YamlNode node, String key) {
-    if (node is YamlMap) {
-      var kind = _translateString(node.valueAt(_kindKey), _kindKey);
-      if (kind == _argumentKind) {
-        return _translateArgumentExtractor(node);
+  /// Translate the [node] into a URI. Return the resulting URI, or `null` if
+  /// the [node] does not represent a valid URI. If the [node] is not valid, use
+  /// the [context] to report the error.
+  Uri _translateUri(YamlNode node, ErrorContext context,
+      {bool required = true}) {
+    if (node is YamlScalar) {
+      var value = node.value;
+      if (value is String) {
+        if (!(value.startsWith('dart:') || value.startsWith('package:'))) {
+          value = 'package:$packageName/$value';
+        }
+        return Uri.parse(value);
       }
-      // TODO(brianwilkerson) Report the invalid extractor kind.
-      return null;
+      return _reportInvalidValue(node, context, 'URI');
     } else if (node == null) {
-      // TODO(brianwilkerson) Report the missing YAML.
+      if (required) {
+        return _reportMissingKey(context);
+      }
       return null;
     } else {
-      _reportError(TransformSetErrorCode.invalidValue, node,
-          [key, 'Map', _nodeType(node)]);
-      return null;
+      return _reportInvalidValue(node, context, 'URI');
+    }
+  }
+
+  /// Translate the [node] into a value extractor. Return the resulting
+  /// extractor, or `null` if the [node] does not represent a valid value
+  /// extractor. If the [node] is not valid, use the [context] to report the
+  /// error.
+  ValueGenerator _translateValueGenerator(YamlNode node, ErrorContext context) {
+    if (node is YamlMap) {
+      var kind = _translateString(node.valueAt(_kindKey),
+          ErrorContext(key: _kindKey, parentNode: node));
+      if (kind == null) {
+        return null;
+      } else if (kind == _argumentKind) {
+        return _translateArgumentExtractor(node);
+      } else if (kind == _importKind) {
+        return _translateImportValue(node);
+      }
+      return _reportInvalidValueOneOf(node, context, [
+        _argumentKind,
+        _importKind,
+      ]);
+    } else if (node == null) {
+      return _reportMissingKey(context);
+    } else {
+      return _reportInvalidValue(node, context, 'Map');
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_extractor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_extractor.dart
deleted file mode 100644
index cc9b79f..0000000
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_extractor.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
-import 'package:analysis_server/src/services/correction/util.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-
-/// A value extractor used to extract a specified argument from an invocation.
-class ArgumentExtractor extends ValueExtractor {
-  /// The parameter corresponding to the argument from the original invocation,
-  /// or `null` if the value of the argument can't be taken from the original
-  /// invocation.
-  final ParameterReference parameter;
-
-  /// Initialize a newly created extractor to extract the argument that
-  /// corresponds to the given [parameter].
-  ArgumentExtractor(this.parameter) : assert(parameter != null);
-
-  @override
-  String from(AstNode node, CorrectionUtils utils) {
-    var argumentList = _getArgumentList(node);
-    if (argumentList != null) {
-      var expression = parameter.argumentFrom(argumentList);
-      if (expression != null) {
-        return utils.getNodeText(expression);
-      }
-    }
-    return null;
-  }
-
-  /// Return the argument list associated with the given [node].
-  ArgumentList _getArgumentList(AstNode node) {
-    if (node is ArgumentList) {
-      return node;
-    } else if (node is InvocationExpression) {
-      return node.argumentList;
-    } else if (node is InstanceCreationExpression) {
-      return node.argumentList;
-    }
-    return null;
-  }
-}
-
-/// A value extractor that returns a pre-computed piece of code.
-class LiteralExtractor extends ValueExtractor {
-  /// The code to be returned.
-  final String code;
-
-  /// Initialize a newly created extractor to return the given [code].
-  LiteralExtractor(this.code);
-
-  @override
-  String from(AstNode node, CorrectionUtils utils) {
-    return code;
-  }
-}
-
-/// An object used to extract an expression from an AST node.
-abstract class ValueExtractor {
-  /// Return code extracted from the given [node], or `null` if no code could be
-  /// extracted.
-  String from(AstNode node, CorrectionUtils utils);
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
new file mode 100644
index 0000000..1214e8b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/value_generator.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+/// Use a specified argument from an invocation as the value of a template
+/// variable.
+class ArgumentExpression extends ValueGenerator {
+  /// The parameter corresponding to the argument from the original invocation,
+  /// or `null` if the value of the argument can't be taken from the original
+  /// invocation.
+  final ParameterReference parameter;
+
+  /// Initialize a newly created extractor to extract the argument that
+  /// corresponds to the given [parameter].
+  ArgumentExpression(this.parameter) : assert(parameter != null);
+
+  @override
+  bool validate(TemplateContext context) {
+    var argumentList = _getArgumentList(context.node);
+    if (argumentList == null) {
+      return false;
+    }
+    var expression = parameter.argumentFrom(argumentList);
+    if (expression != null) {
+      return false;
+    }
+    return true;
+  }
+
+  @override
+  void writeOn(DartEditBuilder builder, TemplateContext context) {
+    var argumentList = _getArgumentList(context.node);
+    if (argumentList != null) {
+      var expression = parameter.argumentFrom(argumentList);
+      if (expression != null) {
+        builder.write(context.utils.getNodeText(expression));
+      }
+    }
+  }
+
+  /// Return the argument list associated with the given [node].
+  ArgumentList _getArgumentList(AstNode node) {
+    if (node is ArgumentList) {
+      return node;
+    } else if (node is InvocationExpression) {
+      return node.argumentList;
+    } else if (node is InstanceCreationExpression) {
+      return node.argumentList;
+    } else if (node is TypeArgumentList) {
+      var parent = node.parent;
+      if (parent is InvocationExpression) {
+        return parent.argumentList;
+      } else if (parent is ExtensionOverride) {
+        return parent.argumentList;
+      }
+    }
+    return null;
+  }
+}
+
+/// Use a name that might need to be imported from a different library as the
+/// value of a template variable.
+class ImportedName extends ValueGenerator {
+  /// The URIs of the libraries from which the name can be imported.
+  final List<Uri> uris;
+
+  /// The name to be used.
+  final String name;
+
+  ImportedName(this.uris, this.name);
+
+  @override
+  bool validate(TemplateContext context) {
+    // TODO(brianwilkerson) Validate that the import can be added.
+    return true;
+  }
+
+  @override
+  void writeOn(DartEditBuilder builder, TemplateContext context) {
+    builder.writeImportedName(uris, name);
+  }
+}
+
+/// An object used to generate the value of a template variable.
+abstract class ValueGenerator {
+  /// Use the [context] to validate that this generator will be able to generate
+  /// a value.
+  bool validate(TemplateContext context);
+
+  /// Write the value generated by this generator to the given [builder], using
+  /// the [context] to access needed information that isn't already known to
+  /// this generator.
+  void writeOn(DartEditBuilder builder, TemplateContext context);
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index a979965..d04d443 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -80,12 +80,14 @@
 import 'package:analysis_server/src/services/correction/dart/make_final.dart';
 import 'package:analysis_server/src/services/correction/dart/make_return_type_nullable.dart';
 import 'package:analysis_server/src/services/correction/dart/make_variable_not_final.dart';
+import 'package:analysis_server/src/services/correction/dart/make_variable_nullable.dart';
 import 'package:analysis_server/src/services/correction/dart/move_type_arguments_to_class.dart';
 import 'package:analysis_server/src/services/correction/dart/organize_imports.dart';
 import 'package:analysis_server/src/services/correction/dart/qualify_reference.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_annotation.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_argument.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_await.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_comparison.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_const.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_dead_code.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_dead_if_null.dart';
@@ -251,7 +253,7 @@
         List.from(fixList[0].change.linkedEditGroups);
     for (var i = 1; i < fixList.length; i++) {
       edits.addAll(fixList[i].change.edits[0].edits);
-      sourceChange.linkedEditGroups..addAll(fixList[i].change.linkedEditGroups);
+      sourceChange.linkedEditGroups.addAll(fixList[i].change.linkedEditGroups);
     }
     // Sort the list of SourceEdits so that when the edits are applied, they
     // are applied from the end of the file to the top of the file.
@@ -528,6 +530,9 @@
     CompileTimeErrorCode.NEW_WITH_NON_TYPE: [
       ImportLibrary.forType,
     ],
+    CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT: [
+      DataDriven.newInstance,
+    ],
     CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT: [
       AddSuperConstructorInvocation.newInstance,
     ],
@@ -713,6 +718,7 @@
       AddExplicitCast.newInstance,
       AddNullCheck.newInstance,
       ChangeTypeAnnotation.newInstance,
+      MakeVariableNullable.newInstance,
     ],
     CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION: [
       RemoveParenthesesInGetterInvocation.newInstance,
@@ -720,6 +726,9 @@
     CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER: [
       AddRequiredKeyword.newInstance,
     ],
+    CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT: [
+      AddMissingRequiredArgument.newInstance,
+    ],
     CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE: [
       ExtendClassForMixin.newInstance,
     ],
@@ -1004,12 +1013,21 @@
     HintCode.UNNECESSARY_CAST: [
       RemoveUnnecessaryCast.newInstance,
     ],
-    // TODO(brianwilkerson) Add a fix to remove the method.
-//    HintCode.UNNECESSARY_NO_SUCH_METHOD: [],
-    // TODO(brianwilkerson) Add a fix to remove the type check.
-//    HintCode.UNNECESSARY_TYPE_CHECK_FALSE: [],
-    // TODO(brianwilkerson) Add a fix to remove the type check.
-//    HintCode.UNNECESSARY_TYPE_CHECK_TRUE: [],
+//    HintCode.UNNECESSARY_NO_SUCH_METHOD: [
+// TODO(brianwilkerson) Add a fix to remove the method.
+//    ],
+    HintCode.UNNECESSARY_NULL_COMPARISON_FALSE: [
+      RemoveComparison.newInstance,
+    ],
+    HintCode.UNNECESSARY_NULL_COMPARISON_TRUE: [
+      RemoveComparison.newInstance,
+    ],
+//    HintCode.UNNECESSARY_TYPE_CHECK_FALSE: [
+// TODO(brianwilkerson) Add a fix to remove the type check.
+//    ],
+//    HintCode.UNNECESSARY_TYPE_CHECK_TRUE: [
+// TODO(brianwilkerson) Add a fix to remove the type check.
+//    ],
     HintCode.UNUSED_CATCH_CLAUSE: [
       RemoveUnusedCatchClause.newInstance,
     ],
@@ -1108,7 +1126,8 @@
 
     Future<void> compute(CorrectionProducer producer) async {
       producer.configure(context);
-      var builder = ChangeBuilder(workspace: context.workspace);
+      var builder = ChangeBuilder(
+          workspace: context.workspace, eol: context.utils.endOfLine);
       await producer.compute(builder);
       _addFixFromBuilder(builder, producer.fixKind,
           args: producer.fixArguments);
diff --git a/pkg/analysis_server/lib/src/services/correction/sort_members.dart b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
index 34e0ba4..cf3db41 100644
--- a/pkg/analysis_server/lib/src/services/correction/sort_members.dart
+++ b/pkg/analysis_server/lib/src/services/correction/sort_members.dart
@@ -262,10 +262,8 @@
   final int end;
   final String text;
 
-  _MemberInfo(this.item, this.name, int offset, int length, this.text)
-      : offset = offset,
-        length = length,
-        end = offset + length;
+  _MemberInfo(this.item, this.name, this.offset, this.length, this.text)
+      : end = offset + length;
 
   @override
   String toString() {
diff --git a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
index 398620c..f2f430f 100644
--- a/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/kythe/kythe_visitors.dart
@@ -1083,7 +1083,7 @@
         _enclosingVName =
             _vNameFromElement(_enclosingElement, schema.FUNCTION_KIND);
       }
-      return f();
+      f();
     } finally {
       _enclosingElement = outerEnclosingElement;
       _enclosingClassElement = outerEnclosingClassElement;
@@ -1225,7 +1225,7 @@
         addNodeAndFacts(schema.TAPP_KIND, element: functionElement);
     addEdge(funcTypeVName, schema.PARAM_EDGE, fnBuiltin, ordinalIntValue: i++);
 
-    var returnTypeVName;
+    KytheVName returnTypeVName;
     if (returnNode is TypeName) {
       // MethodDeclaration and FunctionDeclaration both return a TypeName from
       // returnType
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 886804c..d626bd2 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -754,7 +754,7 @@
   }
 
   Future<void> _initializeReturnType() async {
-    var typeProvider = await resolveResult.typeProvider;
+    var typeProvider = resolveResult.typeProvider;
     if (_selectionFunctionExpression != null) {
       variableType = '';
       returnType = '';
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 58adedd5..09b73f8 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -141,7 +141,8 @@
 
   @override
   Future<SourceChange> createChange() async {
-    var builder = ChangeBuilder(session: sessionHelper.session);
+    var builder =
+        ChangeBuilder(session: sessionHelper.session, eol: utils.endOfLine);
     await builder.addDartFileEdit(resolveResult.path, (builder) {
       if (_expression != null) {
         builder.addReplacement(range.node(_expression), (builder) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 7cfe3fe..7f96d3a 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -148,10 +148,9 @@
         elementKind = ElementKind.METHOD;
 
   _ClassMemberValidator.forRename(
-      this.searchEngine, this.sessionHelper, Element element, this.name)
+      this.searchEngine, this.sessionHelper, this.element, this.name)
       : isRename = true,
         library = element.library,
-        element = element,
         elementClass = element.enclosingElement,
         elementKind = element.kind;
 
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
index 3a4a3a5..6187abe 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
@@ -104,10 +104,9 @@
   final List<SearchMatch> references = <SearchMatch>[];
 
   _ExtensionMemberValidator.forRename(
-      this.searchEngine, this.sessionHelper, Element element, this.name)
+      this.searchEngine, this.sessionHelper, this.element, this.name)
       : isRename = true,
         library = element.library,
-        element = element,
         elementExtension = element.enclosingElement,
         elementKind = element.kind;
 
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index dcbc8f0..bd39067 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -391,7 +391,7 @@
           raw: true);
       return;
     }
-    var file = await server.resourceProvider.getFile(filePath);
+    var file = server.resourceProvider.getFile(filePath);
     if (!file.exists) {
       p('The file <code>${escape(filePath)}</code> does not exist.', raw: true);
       return;
@@ -500,16 +500,6 @@
 
     buf.writeln('</div>');
 
-    buf.writeln('<div class="column one-half">');
-    var sdk = driver?.sourceFactory?.dartSdk;
-    AnalysisOptionsImpl sdkOptions = sdk?.context?.analysisOptions;
-    if (sdkOptions != null) {
-      h3('SDK analysis options');
-      p(describe(sdkOptions), raw: true);
-    }
-
-    buf.writeln('</div>');
-
     buf.writeln('</div>');
 
     h3('Lints');
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index d5a48c5..9243a189 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -95,7 +95,8 @@
       if (newlineLoc == childArgSrc.length) {
         newlineLoc -= 1;
       }
-      String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+      String indentOld =
+          getLinePrefix(childArg.offset + eol.length + newlineLoc);
       var indentNew = '$indentOld${getIndent(1)}';
       // The separator includes 'child:' but that has no newlines.
       String separator =
@@ -136,7 +137,8 @@
       if (newlineLoc == childArgSrc.length) {
         newlineLoc -= 1;
       }
-      String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+      String indentOld =
+          getLinePrefix(childArg.offset + eol.length + newlineLoc);
       var indentNew = '$indentOld${getIndent(1)}';
       // The separator includes 'child:' but that has no newlines.
       String separator =
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
index 786162f..97d5420 100644
--- a/pkg/analysis_server/lib/src/utilities/mocks.dart
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -128,7 +128,7 @@
 }
 
 class ServerError implements Exception {
-  final message;
+  final String message;
 
   ServerError(this.message);
 
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 842ac85..da3e6a6 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -35,5 +35,5 @@
   logging: any
   matcher: any
   mockito: any
-  pedantic: ^1.8.0
+  pedantic: ^1.9.0
   test_reflective_loader: any
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index 5b10d92..d40c389 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -7,12 +7,14 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:test/test.dart';
 
 import 'abstract_context.dart';
@@ -20,6 +22,9 @@
 class AbstractSingleUnitTest extends AbstractContextTest {
   bool verifyNoTestUnitErrors = true;
 
+  /// Whether to rewrite line endings in test code based on platform.
+  bool useLineEndingsForPlatform = false;
+
   String testCode;
   String testFile;
   Source testSource;
@@ -29,6 +34,14 @@
   LibraryElement testLibraryElement;
   FindNode findNode;
 
+  @override
+  Source addSource(String path, String content, [Uri uri]) {
+    if (useLineEndingsForPlatform) {
+      content = normalizeNewlinesForPlatform(content);
+    }
+    return super.addSource(path, content, uri);
+  }
+
   void addTestSource(String code, [Uri uri]) {
     testCode = code;
     testSource = addSource(testFile, code, uri);
@@ -106,7 +119,18 @@
     return length;
   }
 
+  @override
+  File newFile(String path, {String content = ''}) {
+    if (useLineEndingsForPlatform) {
+      content = normalizeNewlinesForPlatform(content);
+    }
+    return super.newFile(path, content: content);
+  }
+
   Future<void> resolveTestUnit(String code) async {
+    if (useLineEndingsForPlatform) {
+      code = normalizeNewlinesForPlatform(code);
+    }
     addTestSource(code);
     testAnalysisResult = await session.getResolvedUnit(testFile);
     testUnit = testAnalysisResult.unit;
diff --git a/pkg/analysis_server/test/analysis/get_signature_test.dart b/pkg/analysis_server/test/analysis/get_signature_test.dart
index 0579563..da09214 100644
--- a/pkg/analysis_server/test/analysis/get_signature_test.dart
+++ b/pkg/analysis_server/test/analysis/get_signature_test.dart
@@ -54,7 +54,7 @@
 class MyClass {
   /// MyClass constructor doc
   MyClass(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass("Danny", /*^*/);
 }
@@ -63,10 +63,12 @@
     expect(result.name, equals('MyClass'));
     expect(result.dartdoc, equals('MyClass constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_constructor_factory() async {
@@ -79,7 +81,7 @@
   factory MyClass(String name, {int length}) {
     return new MyClass._();
   }
-} 
+}
 main() {
   var a = new MyClass("Danny", /*^*/);
 }
@@ -88,10 +90,12 @@
     expect(result.name, equals('MyClass'));
     expect(result.dartdoc, equals('MyClass factory constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_constructor_named() async {
@@ -100,7 +104,7 @@
 class MyClass {
   /// MyClass.foo constructor doc
   MyClass.foo(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass.foo("Danny", /*^*/);
 }
@@ -109,10 +113,12 @@
     expect(result.name, equals('MyClass.foo'));
     expect(result.dartdoc, equals('MyClass.foo constructor doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_does_not_walk_up_over_closure() async {
@@ -170,8 +176,10 @@
     expect(result.name, equals('f'));
     expect(result.dartdoc, equals('f doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 's', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 's', 'String')));
   }
 
   Future<void> test_function_from_other_file() async {
@@ -192,10 +200,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_irrelevant_parens() async {
@@ -210,10 +222,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_named() async {
@@ -228,10 +244,12 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_function_named_with_default_int() async {
@@ -246,11 +264,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int',
             defaultValue: '1')));
   }
 
@@ -266,11 +286,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'email', 'String',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'email', 'String',
             defaultValue: '"a@b.c"')));
   }
 
@@ -289,8 +311,10 @@
     expect(result.name, equals('two'));
     expect(result.dartdoc, equals('two doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'two', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'two', 'String')));
   }
 
   Future<void> test_function_nested_call_outer() async {
@@ -308,8 +332,10 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(1));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'one', 'String')));
+    expect(
+        result.parameters[0],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'one', 'String')));
   }
 
   Future<void> test_function_no_dart_doc() async {
@@ -323,10 +349,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, isNull);
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_optional() async {
@@ -341,10 +371,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.OPTIONAL, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.OPTIONAL_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_optional_with_default() async {
@@ -359,11 +393,13 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(
         result.parameters[1],
-        equals(ParameterInfo(ParameterKind.OPTIONAL, 'length', 'int',
+        equals(ParameterInfo(ParameterKind.OPTIONAL_POSITIONAL, 'length', 'int',
             defaultValue: '11')));
   }
 
@@ -379,10 +415,14 @@
     expect(result.name, equals('one'));
     expect(result.dartdoc, equals('one doc'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
-    expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'length', 'int')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
+    expect(
+        result.parameters[1],
+        equals(
+            ParameterInfo(ParameterKind.REQUIRED_POSITIONAL, 'length', 'int')));
   }
 
   Future<void> test_function_zero_arguments() async {
@@ -427,7 +467,7 @@
   MyClass(String name, {int length}) {}
   /// MyClass instance method
   myMethod(String name, {int length}) {}
-} 
+}
 main() {
   var a = new MyClass("Danny");
   a.myMethod("Danny", /*^*/);
@@ -437,10 +477,12 @@
     expect(result.name, equals('myMethod'));
     expect(result.dartdoc, equals('MyClass instance method'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 
   Future<void> test_method_static() async {
@@ -451,7 +493,7 @@
   MyClass(String name, {int length}) {}
   /// MyClass static method
   static void myStaticMethod(String name, {int length}) {}
-} 
+}
 main() {
   MyClass.myStaticMethod("Danny", /*^*/);
 }
@@ -460,9 +502,11 @@
     expect(result.name, equals('myStaticMethod'));
     expect(result.dartdoc, equals('MyClass static method'));
     expect(result.parameters, hasLength(2));
-    expect(result.parameters[0],
-        equals(ParameterInfo(ParameterKind.REQUIRED, 'name', 'String')));
+    expect(
+        result.parameters[0],
+        equals(ParameterInfo(
+            ParameterKind.REQUIRED_POSITIONAL, 'name', 'String')));
     expect(result.parameters[1],
-        equals(ParameterInfo(ParameterKind.NAMED, 'length', 'int')));
+        equals(ParameterInfo(ParameterKind.OPTIONAL_NAMED, 'length', 'int')));
   }
 }
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index b07322c..3e49eab 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -164,6 +164,29 @@
     expect(errors, isNull);
   }
 
+  Future<void> test_dataFile() async {
+    var filePath = join(projectPath, 'lib', 'fix_data.yaml');
+    var dataFile = newFile(filePath, content: '''
+version: 1
+transforms:
+''').path;
+
+    var request =
+        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
+    handleSuccessfulRequest(request);
+    await waitForTasksFinished();
+    await pumpEventQueue();
+    //
+    // Verify the error result.
+    //
+    var errors = filesErrors[dataFile];
+    expect(errors, hasLength(1));
+    var error = errors[0];
+    expect(error.location.file, filePath);
+    expect(error.severity, AnalysisErrorSeverity.ERROR);
+    expect(error.type, AnalysisErrorType.COMPILE_TIME_ERROR);
+  }
+
   Future<void> test_dotFolder_priority() async {
     // Files inside dotFolders should not generate error notifications even
     // if they are added to priority (priority affects only priority, not what
@@ -180,7 +203,7 @@
 
     // Add to priority files and give chance for the file to be analyzed (if
     // it would).
-    await setPriorityFiles([brokenFile]);
+    setPriorityFiles([brokenFile]);
     await waitForTasksFinished();
     await pumpEventQueue(times: 5000);
 
@@ -459,6 +482,58 @@
     expect(errors, hasLength(0));
   }
 
+  /// Re-enable once `sort_pub_dependencies` is fixed
+  /// See: https://github.com/dart-lang/sdk/issues/43529
+  /// See: https://github.com/dart-lang/linter/issues/2271
+  @failingTest
+  Future<void> test_pubspecFile_lint() async {
+    var optionsPath = join(projectPath, 'analysis_options.yaml');
+    newFile(optionsPath, content: '''
+linter:
+  rules:
+    - sort_pub_dependencies
+''');
+
+    var filePath = join(projectPath, 'pubspec.yaml');
+    var pubspecFile = newFile(filePath, content: '''
+name: sample
+    
+dependencies:
+  b: any
+  a: any
+''').path;
+
+    var setRootsRequest =
+        AnalysisSetAnalysisRootsParams([projectPath], []).toRequest('0');
+    handleSuccessfulRequest(setRootsRequest);
+    await waitForTasksFinished();
+    await pumpEventQueue();
+    //
+    // Verify the error result.
+    //
+    var errors = filesErrors[pubspecFile];
+    expect(errors, hasLength(1));
+    var error = errors[0];
+    expect(error.location.file, filePath);
+    expect(error.severity, AnalysisErrorSeverity.INFO);
+    expect(error.type, AnalysisErrorType.LINT);
+    //
+    // Fix the error and verify the new results.
+    //
+    modifyFile(pubspecFile, '''
+name: sample
+    
+dependencies:
+  a: any
+  b: any
+''');
+    await waitForTasksFinished();
+    await pumpEventQueue();
+
+    errors = filesErrors[pubspecFile];
+    expect(errors, hasLength(0));
+  }
+
   Future<void> test_StaticWarning() async {
     createProject();
     addTestFile('''
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 9bae3c4..c00d24e 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -866,12 +866,12 @@
     extends AbstractCompletionDomainTest {
   String testFileUri;
 
-  void expectTokens(String content, List<TokenDetails> expectedTokens) async {
+  Future<void> expectTokens(String content, List<TokenDetails> expected) async {
     newFile(testFile, content: content);
     var request = CompletionListTokenDetailsParams(testFile).toRequest('0');
     var response = await waitResponse(request);
     List<Map<String, dynamic>> tokens = response.result['tokens'];
-    _compareTokens(tokens, expectedTokens);
+    _compareTokens(tokens, expected);
   }
 
   @override
diff --git a/pkg/analysis_server/test/domain_completion_util.dart b/pkg/analysis_server/test/domain_completion_util.dart
index 81f936f..7d42cf0 100644
--- a/pkg/analysis_server/test/domain_completion_util.dart
+++ b/pkg/analysis_server/test/domain_completion_util.dart
@@ -46,7 +46,7 @@
       bool isPotential = false,
       int selectionOffset,
       ElementKind elementKind}) {
-    var cs;
+    CompletionSuggestion cs;
     suggestions.forEach((s) {
       if (elementKind != null && s.element?.kind != elementKind) {
         return;
diff --git a/pkg/analysis_server/test/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
index c1d8b75..18f2356 100644
--- a/pkg/analysis_server/test/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/edit_domain.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:linter/src/rules.dart';
 import 'package:test/test.dart';
@@ -27,15 +28,88 @@
     expect(editedSource, expectedSource);
   }
 
+  Future<void> assertNoEdits() async {
+    await waitForTasksFinished();
+    var edits = await _getBulkEdits();
+    expect(edits, isEmpty);
+  }
+
   @override
   void setUp() {
     super.setUp();
     registerLintRules();
     handler = EditDomainHandler(server);
+    createProject();
+  }
+
+  Future<void> test_annotateOverrides_excludedSubProject() async {
+    // Root project.
+    addAnalysisOptionsFile('''
+analyzer:
+  exclude:
+    - test/data/**
+''');
+
+    // Sub-project.
+    var subprojectRoot = '$projectPath/test/data/subproject';
+    newFile('$subprojectRoot/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}',
+        content: '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+
+    newFile('$subprojectRoot/${AnalysisEngine.PUBSPEC_YAML_FILE}', content: '''
+name: subproject
+''');
+
+    newFile('$subprojectRoot/test.dart', content: '''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+
+    await assertNoEdits();
+  }
+
+  Future<void> test_annotateOverrides_subProject() async {
+    var subprojectRoot = '$projectPath/test/data/subproject';
+    newFile('$subprojectRoot/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}',
+        content: '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+
+    newFile('$subprojectRoot/${AnalysisEngine.PUBSPEC_YAML_FILE}', content: '''
+name: subproject
+''');
+
+    testFile = '$subprojectRoot/test.dart';
+    addTestFile('''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+
+    await assertEditEquals('''
+class A {
+  void f() {}
+}
+class B extends A {
+  @override
+  void f() { }
+}
+''');
   }
 
   Future<void> test_unnecessaryNew() async {
-    createProject();
     addAnalysisOptionsFile('''
 linter:
   rules:
@@ -52,8 +126,38 @@
 ''');
   }
 
+  Future<void> test_unnecessaryNew_ignoredInOptions() async {
+    addAnalysisOptionsFile('''
+analyzer:
+  errors:
+    unnecessary_new: ignore
+linter:
+  rules:
+    - unnecessary_new
+''');
+    addTestFile('''
+class A {}
+A f() => new A();
+''');
+    await assertNoEdits();
+  }
+
+  Future<void> test_unnecessaryNew_ignoredInSource() async {
+    addAnalysisOptionsFile('''
+linter:
+  rules:
+    - unnecessary_new
+''');
+    addTestFile('''
+class A {}
+//ignore: unnecessary_new
+A f() => new A();
+''');
+    await assertNoEdits();
+  }
+
   Future<List<SourceFileEdit>> _getBulkEdits() async {
-    var request = EditBulkFixesParams([testFile]).toRequest('0');
+    var request = EditBulkFixesParams([projectPath]).toRequest('0');
     var response = await waitResponse(request);
     var result = EditBulkFixesResult.fromResponse(response);
     return result.edits;
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 7de1b0d..19588f5 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -29,6 +29,24 @@
     handler = EditDomainHandler(server);
   }
 
+  Future<void> test_fileOutsideRoot() async {
+    final outsideFile = '/foo/test.dart';
+    newFile(outsideFile, content: 'bad code to create error');
+
+    // Set up the original project, as the code fix code won't run at all
+    // if there are no contexts.
+    createProject();
+    await waitForTasksFinished();
+
+    var request =
+        EditGetFixesParams(convertPath(outsideFile), 0).toRequest('0');
+    var response = await waitResponse(request);
+    expect(
+      response,
+      isResponseFailure('0', RequestErrorCode.GET_FIXES_INVALID_FILE),
+    );
+  }
+
   Future<void> test_fixUndefinedClass() async {
     createProject();
     addTestFile('''
diff --git a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
index 922c0c8..9b42331 100644
--- a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -27,11 +28,23 @@
     standardAnalysisSetup();
   }
 
-  @failingTest
   Future<void> test_bulk_fix_override() async {
-    setupTarget();
+    writeFile(sourcePath(AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE), '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+    writeFile(sourcePath('test.dart'), '''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+    standardAnalysisSetup();
 
     var result = await sendEditBulkFixes([sourceDirectory.path]);
-    expect(result.edits.length, 1);
+    expect(result.edits, hasLength(1));
   }
 }
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index 4e79f93..e69a2bc 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -5,7 +5,6 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/channel/lsp_byte_stream_channel.dart';
 import 'package:analyzer/instrumentation/instrumentation.dart';
@@ -25,24 +24,17 @@
   /// Sends a request to the server and unwraps the result. Throws if the
   /// response was not successful or returned an error.
   @override
-  Future<T> expectSuccessfulResponseTo<T>(RequestMessage request) async {
+  Future<T> expectSuccessfulResponseTo<T, R>(
+      RequestMessage request, T Function(R) fromJson) async {
     final resp = await sendRequestToServer(request);
     if (resp.error != null) {
       throw resp.error;
-      // TODO(dantup): It would be better if we had some code-gen'd way
-      // to be able to deserialise into the correct types. We could either
-      // code-gen this list, or code-gen the LSP client (used in tests) to
-      // give strongly typed sendXxx functions that return the correct types.
-    } else if (T == DartDiagnosticServer) {
-      return DartDiagnosticServer.fromJson(resp.result) as T;
     } else if (T == Null) {
       return resp.result == null
           ? null
           : throw 'Expected Null response but got ${resp.result}';
     } else {
-      throw 'Unable to deserialise ${resp.result.runtimeType} into $T.\n\n'
-          'You may need to extend expectSuccessfulResponseTo in '
-          'AbstractLspAnalysisServerIntegrationTest';
+      return fromJson(resp.result);
     }
   }
 
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 9799790..c6f966e 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1708,6 +1708,11 @@
   /// Return the set of fixes that are available for the errors at a given
   /// offset in a given file.
   ///
+  /// If a request is made for a file which does not exist, or which is not
+  /// currently subject to analysis (e.g. because it is not associated with any
+  /// analysis root specified to analysis.setAnalysisRoots), an error of type
+  /// GET_FIXES_INVALID_FILE will be generated.
+  ///
   /// Parameters
   ///
   /// file: FilePath
diff --git a/pkg/analysis_server/test/integration/support/integration_tests.dart b/pkg/analysis_server/test/integration/support/integration_tests.dart
index e51eace..8f34d32 100644
--- a/pkg/analysis_server/test/integration/support/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/support/integration_tests.dart
@@ -479,7 +479,7 @@
       }
 
       _recordStdio('<== $trimmedLine');
-      var message;
+      Map message;
       try {
         message = json.decoder.convert(trimmedLine);
       } catch (exception) {
@@ -487,9 +487,8 @@
         return;
       }
       outOfTestExpect(message, isMap);
-      Map messageAsMap = message;
-      if (messageAsMap.containsKey('id')) {
-        outOfTestExpect(messageAsMap['id'], isString);
+      if (message.containsKey('id')) {
+        outOfTestExpect(message['id'], isString);
         String id = message['id'];
         var completer = _pendingCommands[id];
         if (completer == null) {
@@ -497,10 +496,10 @@
         } else {
           _pendingCommands.remove(id);
         }
-        if (messageAsMap.containsKey('error')) {
-          completer.completeError(ServerErrorMessage(messageAsMap));
+        if (message.containsKey('error')) {
+          completer.completeError(ServerErrorMessage(message));
         } else {
-          completer.complete(messageAsMap['result']);
+          completer.complete(message['result']);
         }
         // Check that the message is well-formed.  We do this after calling
         // completer.complete() or completer.completeError() so that we don't
@@ -509,9 +508,9 @@
       } else {
         // Message is a notification.  It should have an event and possibly
         // params.
-        outOfTestExpect(messageAsMap, contains('event'));
-        outOfTestExpect(messageAsMap['event'], isString);
-        notificationProcessor(messageAsMap['event'], messageAsMap['params']);
+        outOfTestExpect(message, contains('event'));
+        outOfTestExpect(message['event'], isString);
+        notificationProcessor(message['event'], message['params']);
         // Check that the message is well-formed.  We do this after calling
         // notificationController.add() so that we don't stall the test in the
         // event of an error.
@@ -690,9 +689,7 @@
   /// Iterable matcher which we use to test the contents of the list.
   final Matcher iterableMatcher;
 
-  _ListOf(elementMatcher)
-      : elementMatcher = elementMatcher,
-        iterableMatcher = everyElement(elementMatcher);
+  _ListOf(this.elementMatcher) : iterableMatcher = everyElement(elementMatcher);
 
   @override
   Description describe(Description description) =>
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ffeed70..534a918 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1206,12 +1206,17 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
-final Matcher isParameterKind =
-    MatchesEnum('ParameterKind', ['NAMED', 'OPTIONAL', 'REQUIRED']);
+final Matcher isParameterKind = MatchesEnum('ParameterKind', [
+  'OPTIONAL_NAMED',
+  'OPTIONAL_POSITIONAL',
+  'REQUIRED_NAMED',
+  'REQUIRED_POSITIONAL'
+]);
 
 /// Position
 ///
@@ -1365,6 +1370,7 @@
 ///   FORMAT_INVALID_FILE
 ///   FORMAT_WITH_ERRORS
 ///   GET_ERRORS_INVALID_FILE
+///   GET_FIXES_INVALID_FILE
 ///   GET_IMPORTED_ELEMENTS_INVALID_FILE
 ///   GET_KYTHE_ENTRIES_INVALID_FILE
 ///   GET_NAVIGATION_INVALID_FILE
@@ -1401,6 +1407,7 @@
   'FORMAT_INVALID_FILE',
   'FORMAT_WITH_ERRORS',
   'GET_ERRORS_INVALID_FILE',
+  'GET_FIXES_INVALID_FILE',
   'GET_IMPORTED_ELEMENTS_INVALID_FILE',
   'GET_KYTHE_ENTRIES_INVALID_FILE',
   'GET_NAVIGATION_INVALID_FILE',
diff --git a/pkg/analysis_server/test/lsp/analyzer_status_test.dart b/pkg/analysis_server/test/lsp/analyzer_status_test.dart
index dec6895..40cb5e4 100644
--- a/pkg/analysis_server/test/lsp/analyzer_status_test.dart
+++ b/pkg/analysis_server/test/lsp/analyzer_status_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -9,19 +10,40 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(AnalyzerStatusTest);
+    defineReflectiveTests(AnalysisStandardProgressTest);
+    defineReflectiveTests(AnalyzerCustomStatusTest);
   });
 }
 
+/// Tests analysis status notifications using LSP-standard $/progress
+/// notifications.
 @reflectiveTest
-class AnalyzerStatusTest extends AbstractLspAnalysisServerTest {
+class AnalysisStandardProgressTest extends AnalyzerStatusTest {
+  @override
+  bool get progressSupport => true;
+}
+
+/// Tests analysis status notifications using (legacy) custom notifications.
+@reflectiveTest
+class AnalyzerCustomStatusTest extends AnalyzerStatusTest {
+  @override
+  bool get progressSupport => false;
+}
+
+abstract class AnalyzerStatusTest extends AbstractLspAnalysisServerTest {
+  bool get progressSupport;
+
+  ClientCapabilitiesWindow get _windowCapabilities => progressSupport
+      ? withWorkDoneProgressSupport(emptyWindowClientCapabilities)
+      : emptyWindowClientCapabilities;
+
   Future<void> test_afterDocumentEdits() async {
     const initialContents = 'int a = 1;';
     newFile(mainFilePath, content: initialContents);
 
     final initialAnalysis = waitForAnalysisComplete();
 
-    await initialize();
+    await initialize(windowCapabilities: _windowCapabilities);
     await initialAnalysis;
 
     // Set up futures to wait for the new events.
diff --git a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
index 95e11f4..414c52d 100644
--- a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
+++ b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
@@ -65,7 +65,7 @@
         join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
     final nestedFilePath = join(nestedFolderPath, 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     await initialize(allowEmptyRootUri: true);
     await openFile(nestedFileUri, '');
@@ -98,7 +98,7 @@
         join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
     final nestedFilePath = join(nestedFolderPath, 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     await initialize(allowEmptyRootUri: true);
     await openFile(nestedFileUri, '');
@@ -132,7 +132,7 @@
         join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
     final nestedFilePath = join(nestedFolderPath, 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     await initialize(workspaceFolders: [workspaceFolder1Uri]);
 
@@ -164,7 +164,7 @@
         join(workspaceFolder1Path, 'nested', 'deeply', 'in', 'folders');
     final nestedFilePath = join(nestedFolderPath, 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     await initialize(workspaceFolders: [workspaceFolder1Uri]);
 
@@ -201,10 +201,10 @@
     // the pub cache folder being added as an analysis root, it should be analyzed
     // by the existing project's driver.
     final workspace1FilePath = join(workspaceFolder1Path, 'test.dart');
-    await newFile(workspace1FilePath);
+    newFile(workspace1FilePath);
     final workspace2FilePath = join(workspaceFolder2Path, 'test.dart');
     final workspace2FileUri = Uri.file(workspace2FilePath);
-    await newFile(workspace2FilePath);
+    newFile(workspace2FilePath);
 
     await initialize(workspaceFolders: [workspaceFolder1Uri]);
 
diff --git a/pkg/analysis_server/test/lsp/code_actions_abstract.dart b/pkg/analysis_server/test/lsp/code_actions_abstract.dart
index 5c3cd8c..df1425e 100644
--- a/pkg/analysis_server/test/lsp/code_actions_abstract.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_abstract.dart
@@ -79,14 +79,16 @@
   /// the expected content.
   Future verifyCodeActionEdits(Either2<Command, CodeAction> codeAction,
       String content, String expectedContent,
-      {bool expectDocumentChanges = false}) async {
+      {bool expectDocumentChanges = false,
+      Either2<num, String> workDoneToken}) async {
     final command = codeAction.map(
       (command) => command,
       (codeAction) => codeAction.command,
     );
 
     await verifyCommandEdits(command, content, expectedContent,
-        expectDocumentChanges: expectDocumentChanges);
+        expectDocumentChanges: expectDocumentChanges,
+        workDoneToken: workDoneToken);
   }
 
   /// Verifies that executing the given command on the server results in an edit
@@ -94,13 +96,15 @@
   /// content.
   Future<void> verifyCommandEdits(
       Command command, String content, String expectedContent,
-      {bool expectDocumentChanges = false}) async {
+      {bool expectDocumentChanges = false,
+      Either2<num, String> workDoneToken}) async {
     ApplyWorkspaceEditParams editParams;
 
     final commandResponse = await handleExpectedRequest<Object,
         ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
       Method.workspace_applyEdit,
-      () => executeCommand(command),
+      ApplyWorkspaceEditParams.fromJson,
+      () => executeCommand(command, workDoneToken: workDoneToken),
       handler: (edit) {
         // When the server sends the edit back, just keep a copy and say we
         // applied successfully (it'll be verified below).
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 0ed0c88..03def9f 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -29,7 +29,7 @@
 
     Future f;
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -70,7 +70,7 @@
 
     Future f;
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -97,7 +97,7 @@
   }
 
   Future<void> test_nonDartFile() async {
-    await newFile(pubspecFilePath, content: simplePubspecContent);
+    newFile(pubspecFilePath, content: simplePubspecContent);
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index ac4a575..c424137 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -31,7 +31,7 @@
 
     Future foo;
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -71,7 +71,7 @@
 
     Future foo;
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -100,7 +100,7 @@
     var a = [Test, Test, Te[[]]st];
     ''';
 
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -120,7 +120,7 @@
     var a = [Test, Test, Te[[]]st];
     ''';
 
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -137,7 +137,7 @@
   }
 
   Future<void> test_nonDartFile() async {
-    await newFile(pubspecFilePath, content: simplePubspecContent);
+    newFile(pubspecFilePath, content: simplePubspecContent);
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -172,7 +172,7 @@
 Completer a;
 ProcessInfo b;
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize(
       textDocumentCapabilities: withCodeActionKinds(
           emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
@@ -195,4 +195,17 @@
     applyChanges(contents, fixAction.edit.changes);
     expect(contents[mainFilePath], equals(expectedContent));
   }
+
+  Future<void> test_outsideRoot() async {
+    final otherFilePath = '/home/otherProject/foo.dart';
+    final otherFileUri = Uri.file(otherFilePath);
+    newFile(otherFilePath, content: 'bad code to create error');
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions = await getCodeActions(otherFileUri.toString());
+    expect(codeActions, isEmpty);
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index b733be9..07d6afb3 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -2,11 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/json_parsing.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/utilities/mock_packages.dart';
+import '../tool/lsp_spec/matchers.dart';
 import 'code_actions_abstract.dart';
 
 void main() {
@@ -19,6 +24,32 @@
 @reflectiveTest
 class ExtractMethodRefactorCodeActionsTest extends AbstractCodeActionsTest {
   final extractMethodTitle = 'Extract Method';
+
+  /// A stream of strings (CREATE, BEGIN, END) corresponding to progress requests
+  /// and notifications for convenience in testing.
+  Stream<String> get progressUpdates {
+    final controller = StreamController<String>();
+
+    requestsFromServer
+        .where((r) => r.method == Method.window_workDoneProgress_create)
+        .listen((request) async {
+      controller.add('CREATE');
+    }, onDone: controller.close);
+    notificationsFromServer
+        .where((n) => n.method == Method.progress)
+        .listen((notification) {
+      final params = ProgressParams.fromJson(notification.params);
+      if (WorkDoneProgressBegin.canParse(params.value, nullLspJsonReporter)) {
+        controller.add('BEGIN');
+      } else if (WorkDoneProgressEnd.canParse(
+          params.value, nullLspJsonReporter)) {
+        controller.add('END');
+      }
+    });
+
+    return controller.stream;
+  }
+
   Future<void> test_appliesCorrectEdits() async {
     const content = '''
 main() {
@@ -36,7 +67,7 @@
   print('Test!');
 }
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString(),
@@ -49,13 +80,92 @@
         codeAction, withoutMarkers(content), expectedContent);
   }
 
+  Future<void> test_cancelsInProgress() async {
+    const content = '''
+main() {
+  print('Test!');
+  [[print('Test!');]]
+}
+    ''';
+    const expectedContent = '''
+main() {
+  print('Test!');
+  newMethod();
+}
+
+void newMethod() {
+  print('Test!');
+}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    expect(codeAction, isNotNull);
+
+    // Respond to any applyEdit requests from the server with successful responses
+    // and capturing the last edit.
+    WorkspaceEdit edit;
+    requestsFromServer.listen((request) async {
+      if (request.method == Method.workspace_applyEdit) {
+        final params = ApplyWorkspaceEditParams.fromJson(request.params);
+        edit = params.edit;
+        respondTo(request, ApplyWorkspaceEditResponse(applied: true));
+      }
+    });
+
+    // Send two requests together.
+    final req1 = executeCodeAction(codeAction);
+    final req2 = executeCodeAction(codeAction);
+
+    // Expect the first will have cancelled the second.
+    await expectLater(
+        req1, throwsA(isResponseError(ErrorCodes.RequestCancelled)));
+    await req2;
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyChanges(contents, edit.changes);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_contentModified() async {
+    const content = '''
+main() {
+  print('Test!');
+  [[print('Test!');]]
+}
+    ''';
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    expect(codeAction, isNotNull);
+
+    // Send an edit request immediately after the refactor request.
+    final req1 = executeCodeAction(codeAction);
+    await replaceFile(100, mainFileUri, 'new test content');
+
+    // Expect the first to fail because of the modified content.
+    await expectLater(
+        req1, throwsA(isResponseError(ErrorCodes.ContentModified)));
+  }
+
   Future<void> test_invalidLocation() async {
     const content = '''
 import 'dart:convert';
 ^
 main() {}
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
@@ -63,6 +173,128 @@
         findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
     expect(codeAction, isNull);
   }
+
+  Future<void> test_progress_clientProvided() async {
+    const content = '''
+main() {
+  print('Test!');
+  [[print('Test!');]]
+}
+    ''';
+    const expectedContent = '''
+main() {
+  print('Test!');
+  newMethod();
+}
+
+void newMethod() {
+  print('Test!');
+}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+        windowCapabilities:
+            withWorkDoneProgressSupport(emptyWindowClientCapabilities));
+
+    // Expect begin/end progress updates without a create, since the
+    // token was supplied by us (the client).
+    expect(progressUpdates, emitsInOrder(['BEGIN', 'END']));
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent,
+        workDoneToken: testWorkDoneToken);
+  }
+
+  Future<void> test_progress_notSupported() async {
+    const content = '''
+main() {
+  print('Test!');
+  [[print('Test!');]]
+}
+    ''';
+    const expectedContent = '''
+main() {
+  print('Test!');
+  newMethod();
+}
+
+void newMethod() {
+  print('Test!');
+}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    var didGetProgressNotifications = false;
+    notificationsFromServer
+        .where((n) => n.method == Method.progress)
+        .listen((_) => didGetProgressNotifications = true);
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+
+    expect(didGetProgressNotifications, isFalse);
+  }
+
+  Future<void> test_progress_serverGenerated() async {
+    const content = '''
+main() {
+  print('Test!');
+  [[print('Test!');]]
+}
+    ''';
+    const expectedContent = '''
+main() {
+  print('Test!');
+  newMethod();
+}
+
+void newMethod() {
+  print('Test!');
+}
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+        windowCapabilities:
+            withWorkDoneProgressSupport(emptyWindowClientCapabilities));
+
+    // Capture progress-related messages in a list in the order they arrive.
+    final progressRequests = <String>[];
+    requestsFromServer
+        .where((r) => r.method == Method.window_workDoneProgress_create)
+        .listen((request) async {
+      progressRequests.add('CREATE');
+    });
+    notificationsFromServer
+        .where((n) => n.method == Method.progress)
+        .listen((notification) {
+      final params = ProgressParams.fromJson(notification.params);
+      if (WorkDoneProgressBegin.canParse(params.value, nullLspJsonReporter)) {
+        progressRequests.add('BEGIN');
+      } else if (WorkDoneProgressEnd.canParse(
+          params.value, nullLspJsonReporter)) {
+        progressRequests.add('END');
+      }
+    });
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, extractMethodTitle);
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+
+    // Ensure the progress messages came through and in the correct order.
+    expect(progressRequests, equals(['CREATE', 'BEGIN', 'END']));
+  }
 }
 
 @reflectiveTest
@@ -136,7 +368,7 @@
   }
 }
     ''';
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString(),
@@ -155,7 +387,7 @@
 ^
 main() {}
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index 1c15d8b..12838ed 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -35,7 +35,7 @@
 Completer foo;
 int minified(int x, int y) => min(x, y);
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities: withApplyEditSupport(
             withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
@@ -64,7 +64,7 @@
 Completer foo;
 int minified(int x, int y) => min(x, y);
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -77,7 +77,7 @@
   }
 
   Future<void> test_availableAsCodeActionLiteral() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -93,7 +93,7 @@
   }
 
   Future<void> test_availableAsCommand() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -108,7 +108,7 @@
 
   Future<void> test_failsSilentlyIfFileHasErrors() async {
     final content = 'invalid dart code';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -136,7 +136,7 @@
 Completer foo;
 int minified(int x, int y) => min(x, y);
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -158,7 +158,7 @@
   }
 
   Future<void> test_unavailableWhenNotRequested() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -171,7 +171,7 @@
   }
 
   Future<void> test_unavailableWithoutApplyEditSupport() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
@@ -191,7 +191,7 @@
     String a;
     String b;
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities: withApplyEditSupport(
             withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
@@ -213,7 +213,7 @@
     String a;
     String b;
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -226,7 +226,7 @@
   }
 
   Future<void> test_availableAsCodeActionLiteral() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -242,7 +242,7 @@
   }
 
   Future<void> test_availableAsCommand() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -260,7 +260,7 @@
     String b;
     String a;
     ''';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -277,6 +277,7 @@
     final commandResponse = handleExpectedRequest<Object,
         ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
       Method.workspace_applyEdit,
+      ApplyWorkspaceEditParams.fromJson,
       () => executeCommand(command),
       // Claim that we failed tpo apply the edits. This is what the client
       // would do if the edits provided were for an old version of the
@@ -293,7 +294,7 @@
 
   Future<void> test_failsIfFileHasErrors() async {
     final content = 'invalid dart code';
-    await newFile(mainFilePath, content: content);
+    newFile(mainFilePath, content: content);
     await initialize(
         workspaceCapabilities:
             withApplyEditSupport(emptyWorkspaceClientCapabilities));
@@ -314,7 +315,7 @@
   }
 
   Future<void> test_nonDartFile() async {
-    await newFile(pubspecFilePath, content: simplePubspecContent);
+    newFile(pubspecFilePath, content: simplePubspecContent);
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
@@ -327,7 +328,7 @@
   }
 
   Future<void> test_unavailableWhenNotRequested() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize(
         textDocumentCapabilities: withCodeActionKinds(
             emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
@@ -340,7 +341,7 @@
   }
 
   Future<void> test_unavailableWithoutApplyEditSupport() async {
-    await newFile(mainFilePath);
+    newFile(mainFilePath);
     await initialize();
 
     final codeActions = await getCodeActions(mainFileUri.toString());
diff --git a/pkg/analysis_server/test/lsp/completion_test.dart b/pkg/analysis_server/test/lsp/completion_test.dart
index 478aaf0..07446e9 100644
--- a/pkg/analysis_server/test/lsp/completion_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_test.dart
@@ -53,7 +53,7 @@
 
     // By default, there should be no commit characters.
     var reg = registration(Method.textDocument_completion);
-    var options = reg.registerOptions as CompletionRegistrationOptions;
+    var options = CompletionRegistrationOptions.fromJson(reg.registerOptions);
     expect(options.allCommitCharacters, isNull);
 
     // When we change config, we should get a re-registration (unregister then
@@ -61,7 +61,7 @@
     await monitorDynamicReregistration(
         registrations, () => updateConfig({'previewCommitCharacters': true}));
     reg = registration(Method.textDocument_completion);
-    options = reg.registerOptions as CompletionRegistrationOptions;
+    options = CompletionRegistrationOptions.fromJson(reg.registerOptions);
     expect(options.allCommitCharacters, equals(dartCompletionCommitCharacters));
   }
 
@@ -935,6 +935,7 @@
     final commandResponse = await handleExpectedRequest<Object,
         ApplyWorkspaceEditParams, ApplyWorkspaceEditResponse>(
       Method.workspace_applyEdit,
+      ApplyWorkspaceEditParams.fromJson,
       () => executeCommand(resolved.command),
       handler: (edit) {
         // When the server sends the edit back, just keep a copy and say we
diff --git a/pkg/analysis_server/test/lsp/configuration_test.dart b/pkg/analysis_server/test/lsp/configuration_test.dart
index 16ea16e..2c91650 100644
--- a/pkg/analysis_server/test/lsp/configuration_test.dart
+++ b/pkg/analysis_server/test/lsp/configuration_test.dart
@@ -48,6 +48,29 @@
     expect(registration, isNull);
   }
 
+  Future<void> test_configurationDidChange_refreshesRoots() async {
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+              withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+      {}, // Empty config
+    );
+
+    // Ensure the roots are as expected before we udpate the config.
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+    expect(server.contextManager.excludedPaths, isEmpty);
+
+    // Notify the server of updated config that includes an excluded path.
+    final excludedFolderPath = join(projectFolderPath, 'excluded');
+    await updateConfig({
+      'analysisExcludedFolders': [excludedFolderPath]
+    });
+
+    // Ensure the roots were updated by the config change.
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+    expect(server.contextManager.excludedPaths, equals([excludedFolderPath]));
+  }
+
   Future<void> test_configurationDidChange_supported() async {
     final registrations = <Registration>[];
     await monitorDynamicRegistrations(
@@ -63,12 +86,15 @@
   }
 
   Future<void> test_configurationRequest_notSupported() async {
-    final configRequest = requestsFromServer
-        .firstWhere((n) => n.method == Method.workspace_configuration);
-    expect(configRequest, doesNotComplete);
+    var didGetConfigRequest = false;
+    requestsFromServer
+        .where((n) => n.method == Method.workspace_configuration)
+        .listen((_) => didGetConfigRequest = true);
 
     await initialize();
     pumpEventQueue();
+
+    expect(didGetConfigRequest, isFalse);
   }
 
   Future<void> test_configurationRequest_supported() async {
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 565fd21..6364bc0 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -171,7 +171,7 @@
 
     // Deleting the file should result in an update to remove the diagnostics.
     final secondDiagnosticsUpdate = waitForDiagnostics(mainFileUri);
-    await deleteFile(mainFilePath);
+    deleteFile(mainFilePath);
     final updatedDiagnostics = await secondDiagnosticsUpdate;
     expect(updatedDiagnostics, hasLength(0));
   }
@@ -250,6 +250,21 @@
     expect(diagnostics, isNull);
   }
 
+  Future<void> test_fixDataFile() async {
+    var fixDataPath = join(projectFolderPath, 'lib', 'fix_data.yaml');
+    var fixDataUri = Uri.file(fixDataPath);
+    newFile(fixDataPath, content: '''
+version: latest
+''').path;
+
+    final firstDiagnosticsUpdate = waitForDiagnostics(fixDataUri);
+    await initialize();
+    final initialDiagnostics = await firstDiagnosticsUpdate;
+    expect(initialDiagnostics, hasLength(1));
+    expect(initialDiagnostics.first.severity, DiagnosticSeverity.Error);
+    expect(initialDiagnostics.first.code, 'invalid_value');
+  }
+
   Future<void> test_fromPlugins_dartFile() async {
     await checkPluginErrorsForFile(mainFilePath);
   }
diff --git a/pkg/analysis_server/test/lsp/document_symbols_test.dart b/pkg/analysis_server/test/lsp/document_symbols_test.dart
index e571578..f66964d 100644
--- a/pkg/analysis_server/test/lsp/document_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/document_symbols_test.dart
@@ -154,8 +154,10 @@
     await initialize();
 
     final result = await getDocumentSymbols(pubspecFileUri.toString());
+    // Since the list is empty, it will deserialise into whatever the first
+    // type is, so just accept both types.
     final symbols = result.map(
-      (docsymbols) => throw 'Expected SymbolInformations, got DocumentSymbols',
+      (docsymbols) => docsymbols,
       (symbolInfos) => symbolInfos,
     );
     expect(symbols, isEmpty);
diff --git a/pkg/analysis_server/test/lsp/file_modification_test.dart b/pkg/analysis_server/test/lsp/file_modification_test.dart
index 9afc443..3c9dac5 100644
--- a/pkg/analysis_server/test/lsp/file_modification_test.dart
+++ b/pkg/analysis_server/test/lsp/file_modification_test.dart
@@ -25,7 +25,7 @@
     // Since this is a notification and not a request, the server cannot
     // respond with an error, but instead sends a ShowMessage notification
     // to alert the user to something failing.
-    final error = await expectErrorNotification<ShowMessageParams>(() async {
+    final error = await expectErrorNotification(() async {
       await changeFile(222, mainFileUri, [
         Either2<TextDocumentContentChangeEvent1,
             TextDocumentContentChangeEvent2>.t1(TextDocumentContentChangeEvent1(
@@ -87,7 +87,7 @@
       text: 'test',
     ));
     await initialize();
-    final notificationParams = await expectErrorNotification<ShowMessageParams>(
+    final notificationParams = await expectErrorNotification(
       () => changeFile(222, mainFileUri, [simpleEdit]),
     );
     expect(notificationParams, isNotNull);
@@ -133,7 +133,7 @@
   Future<void> test_open_invalidPath() async {
     await initialize();
 
-    final notificationParams = await expectErrorNotification<ShowMessageParams>(
+    final notificationParams = await expectErrorNotification(
       () => openFile(Uri.http('localhost', 'not-a-file'), ''),
     );
     expect(notificationParams, isNotNull);
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 72596b7..4caaecc 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/json_parsing.dart';
 import 'package:analysis_server/src/lsp/server_capabilities_computer.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:path/path.dart' as path;
@@ -25,7 +26,8 @@
     List<Registration> registrations,
     Method method,
   ) {
-    return registrationFor(registrations, method)?.registerOptions;
+    return TextDocumentRegistrationOptions.fromJson(
+        registrationFor(registrations, method)?.registerOptions);
   }
 
   Future<void> test_dynamicRegistration_containsAppropriateSettings() async {
@@ -45,7 +47,7 @@
     // Because we support dynamic registration for synchronisation, we won't send
     // static registrations for them.
     // https://github.com/dart-lang/sdk/issues/38490
-    InitializeResult initResult = initResponse.result;
+    final initResult = InitializeResult.fromJson(initResponse.result);
     expect(initResult.serverInfo.name, 'Dart SDK LSP Analysis Server');
     expect(initResult.serverInfo.version, isNotNull);
     expect(initResult.capabilities, isNotNull);
@@ -86,16 +88,14 @@
     // Set a flag if any registerCapability request comes through.
     var didGetRegisterCapabilityRequest = false;
     requestsFromServer
-        .firstWhere((n) => n.method == Method.client_registerCapability)
-        .then((params) {
-      didGetRegisterCapabilityRequest = true;
-    });
+        .where((n) => n.method == Method.client_registerCapability)
+        .listen((_) => didGetRegisterCapabilityRequest = true);
 
     // Initialize with no dynamic registrations advertised.
     final initResponse = await initialize();
     await pumpEventQueue();
 
-    InitializeResult initResult = initResponse.result;
+    final initResult = InitializeResult.fromJson(initResponse.result);
     expect(initResult.capabilities, isNotNull);
     // When dynamic registration is not supported, we will always statically
     // request text document open/close and incremental updates.
@@ -151,7 +151,7 @@
               emptyTextDocumentClientCapabilities)),
     );
 
-    InitializeResult initResult = initResponse.result;
+    final initResult = InitializeResult.fromJson(initResponse.result);
     expect(initResult.capabilities, isNotNull);
 
     // Ensure no static registrations. This list should include all server equivilents
@@ -196,7 +196,8 @@
       pluginManager.pluginsChangedController.add(null);
     });
     final unregistrations =
-        (unregisterRequest.params as UnregistrationParams).unregisterations;
+        UnregistrationParams.fromJson(unregisterRequest.params)
+            .unregisterations;
 
     // folding method should have been unregistered as the server now supports
     // *.foo files for it as well.
@@ -226,7 +227,7 @@
         .firstWhere((r) => r.method == Method.client_unregisterCapability)
         .then((request) {
       respondTo(request, null);
-      return (request.params as UnregistrationParams).unregisterations;
+      return UnregistrationParams.fromJson(request.params).unregisterations;
     });
 
     final request = await expectRequest(Method.client_registerCapability, () {
@@ -236,36 +237,35 @@
       pluginManager.pluginsChangedController.add(null);
     });
 
-    final registrations = (request.params as RegistrationParams).registrations;
+    final registrations =
+        RegistrationParams.fromJson(request.params).registrations;
 
     final documentFilterSql =
         DocumentFilter(scheme: 'file', pattern: '**/*.sql');
     final documentFilterDart = DocumentFilter(language: 'dart', scheme: 'file');
-    final expectedFoldingRegistration =
-        isA<TextDocumentRegistrationOptions>().having(
-      (o) => o.documentSelector,
-      'documentSelector',
-      containsAll([documentFilterSql, documentFilterDart]),
-    );
 
     expect(
       registrations,
       contains(isA<Registration>()
           .having((r) => r.method, 'method', 'textDocument/foldingRange')
-          .having((r) => r.registerOptions, 'registerOptions',
-              expectedFoldingRegistration)),
+          .having(
+            (r) => TextDocumentRegistrationOptions.fromJson(r.registerOptions)
+                .documentSelector,
+            'registerOptions.documentSelector',
+            containsAll([documentFilterSql, documentFilterDart]),
+          )),
     );
   }
 
   Future<void> test_emptyAnalysisRoots_multipleOpenFiles() async {
     final file1 = join(projectFolderPath, 'file1.dart');
     final file1Uri = Uri.file(file1);
-    await newFile(file1);
+    newFile(file1);
     final file2 = join(projectFolderPath, 'file2.dart');
     final file2Uri = Uri.file(file2);
-    await newFile(file2);
+    newFile(file2);
     final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    await newFile(pubspecPath);
+    newFile(pubspecPath);
 
     await initialize(allowEmptyRootUri: true);
 
@@ -288,7 +288,7 @@
     final nestedFilePath = join(
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     // The project folder shouldn't be added to start with.
     await initialize(allowEmptyRootUri: true);
@@ -304,9 +304,9 @@
     final nestedFilePath = join(
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
     final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    await newFile(pubspecPath);
+    newFile(pubspecPath);
 
     // The project folder shouldn't be added to start with.
     await initialize(allowEmptyRootUri: true);
@@ -329,13 +329,61 @@
     expect(server.contextManager.includedPaths, equals([]));
   }
 
+  Future<void> test_excludedFolders_absolute() async {
+    final excludedFolderPath = join(projectFolderPath, 'excluded');
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities:
+              withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      // Exclude the folder with a relative path.
+      {
+        'analysisExcludedFolders': [excludedFolderPath]
+      },
+    );
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+    expect(server.contextManager.excludedPaths, equals([excludedFolderPath]));
+  }
+
+  Future<void> test_excludedFolders_nonList() async {
+    final excludedFolderPath = join(projectFolderPath, 'excluded');
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities:
+              withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      // Include a single string instead of an array since it's an easy mistake
+      // to make without editor validation of settings.
+      {'analysisExcludedFolders': 'excluded'},
+    );
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+    expect(server.contextManager.excludedPaths, equals([excludedFolderPath]));
+  }
+
+  Future<void> test_excludedFolders_relative() async {
+    final excludedFolderPath = join(projectFolderPath, 'excluded');
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities:
+              withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      // Exclude the folder with a relative path.
+      {
+        'analysisExcludedFolders': ['excluded']
+      },
+    );
+    expect(server.contextManager.includedPaths, equals([projectFolderPath]));
+    expect(server.contextManager.excludedPaths, equals([excludedFolderPath]));
+  }
+
   Future<void> test_initialize() async {
     final response = await initialize();
     expect(response, isNotNull);
     expect(response.error, isNull);
     expect(response.result, isNotNull);
-    expect(response.result, TypeMatcher<InitializeResult>());
-    InitializeResult result = response.result;
+    expect(InitializeResult.canParse(response.result, nullLspJsonReporter),
+        isTrue);
+    final result = InitializeResult.fromJson(response.result);
     expect(result.capabilities, isNotNull);
     // Check some basic capabilities that are unlikely to change.
     expect(result.capabilities.textDocumentSync, isNotNull);
@@ -393,12 +441,12 @@
   Future<void> test_onlyAnalyzeProjectsWithOpenFiles_multipleFiles() async {
     final file1 = join(projectFolderPath, 'file1.dart');
     final file1Uri = Uri.file(file1);
-    await newFile(file1);
+    newFile(file1);
     final file2 = join(projectFolderPath, 'file2.dart');
     final file2Uri = Uri.file(file2);
-    await newFile(file2);
+    newFile(file2);
     final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    await newFile(pubspecPath);
+    newFile(pubspecPath);
 
     await initialize(
       rootUri: projectFolderUri,
@@ -424,7 +472,7 @@
     final nestedFilePath = join(
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
 
     // The project folder shouldn't be added to start with.
     await initialize(
@@ -443,9 +491,9 @@
     final nestedFilePath = join(
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
-    await newFile(nestedFilePath);
+    newFile(nestedFilePath);
     final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    await newFile(pubspecPath);
+    newFile(pubspecPath);
 
     // The project folder shouldn't be added to start with.
     await initialize(
diff --git a/pkg/analysis_server/test/lsp/rename_test.dart b/pkg/analysis_server/test/lsp/rename_test.dart
index 0896bf2..41469c8 100644
--- a/pkg/analysis_server/test/lsp/rename_test.dart
+++ b/pkg/analysis_server/test/lsp/rename_test.dart
@@ -290,7 +290,7 @@
     final a = new [[Ob^ject]]();
     ''';
 
-    await newFile(mainFilePath, content: withoutMarkers(content));
+    newFile(mainFilePath, content: withoutMarkers(content));
     await initialize();
 
     final request = makeRequest(
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index f7ec998..4ec3477 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -3,13 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:convert';
 
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
+import 'package:analysis_server/src/lsp/json_parsing.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
@@ -48,6 +48,10 @@
   TestPluginManager pluginManager;
   LspAnalysisServer server;
 
+  final testWorkDoneToken = Either2<num, String>.t2('test');
+
+  AnalysisServerOptions get serverOptions => AnalysisServerOptions();
+
   @override
   Stream<Message> get serverToClient => channel.serverToClient;
 
@@ -77,12 +81,13 @@
   /// Sends a request to the server and unwraps the result. Throws if the
   /// response was not successful or returned an error.
   @override
-  Future<T> expectSuccessfulResponseTo<T>(RequestMessage request) async {
+  Future<T> expectSuccessfulResponseTo<T, R>(
+      RequestMessage request, T Function(R) fromJson) async {
     final resp = await sendRequestToServer(request);
     if (resp.error != null) {
       throw resp.error;
     } else {
-      return resp.result as T;
+      return resp.result == null ? null : fromJson(resp.result);
     }
   }
 
@@ -119,7 +124,7 @@
     server = LspAnalysisServer(
         channel,
         resourceProvider,
-        AnalysisServerOptions(),
+        serverOptions,
         DartSdkManager(convertPath('/sdk')),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE);
@@ -151,16 +156,13 @@
 
   final emptyWorkspaceClientCapabilities = ClientCapabilitiesWorkspace();
 
+  final emptyWindowClientCapabilities = ClientCapabilitiesWindow();
+
   TextDocumentClientCapabilities extendTextDocumentCapabilities(
     TextDocumentClientCapabilities source,
     Map<String, dynamic> textDocumentCapabilities,
   ) {
-    // TODO(dantup): Figure out why we need to do this to get a map...
-    // source.toJson() doesn't recursively called toJson() so we end up with
-    // objects (instead of maps) in child properties, which means multiple
-    // calls to this function do not work correctly. For now, calling jsonEncode
-    // then jsonDecode will force recursive serialisation.
-    final json = jsonDecode(jsonEncode(source));
+    final json = source.toJson();
     if (textDocumentCapabilities != null) {
       textDocumentCapabilities.keys.forEach((key) {
         json[key] = textDocumentCapabilities[key];
@@ -169,13 +171,24 @@
     return TextDocumentClientCapabilities.fromJson(json);
   }
 
+  ClientCapabilitiesWindow extendWindowCapabilities(
+    ClientCapabilitiesWindow source,
+    Map<String, dynamic> windowCapabilities,
+  ) {
+    final json = source.toJson();
+    if (windowCapabilities != null) {
+      windowCapabilities.keys.forEach((key) {
+        json[key] = windowCapabilities[key];
+      });
+    }
+    return ClientCapabilitiesWindow.fromJson(json);
+  }
+
   ClientCapabilitiesWorkspace extendWorkspaceCapabilities(
     ClientCapabilitiesWorkspace source,
     Map<String, dynamic> workspaceCapabilities,
   ) {
-    // TODO(dantup): As above - it seems like this round trip should be
-    // unnecessary.
-    final json = jsonDecode(jsonEncode(source));
+    final json = source.toJson();
     if (workspaceCapabilities != null) {
       workspaceCapabilities.keys.forEach((key) {
         json[key] = workspaceCapabilities[key];
@@ -369,6 +382,11 @@
       'synchronization': {'dynamicRegistration': true}
     });
   }
+
+  ClientCapabilitiesWindow withWorkDoneProgressSupport(
+      ClientCapabilitiesWindow source) {
+    return extendWindowCapabilities(source, {'workDoneProgress': true});
+  }
 }
 
 mixin LspAnalysisServerTestMixin implements ClientCapabilitiesHelperMixin {
@@ -388,6 +406,13 @@
       start: Position(line: 0, character: 0),
       end: Position(line: 0, character: 0));
 
+  /// The client capabilities sent to the server during initialization.
+  ///
+  /// null if an initialization request has not yet been sent.
+  ClientCapabilities _clientCapabilities;
+
+  final validProgressTokens = <Either2<num, String>>{};
+
   /// A stream of [NotificationMessage]s from the server that may be errors.
   Stream<NotificationMessage> get errorNotificationsFromServer {
     return notificationsFromServer.where(_isErrorNotification);
@@ -567,15 +592,26 @@
     await sendNotificationToServer(notification);
   }
 
-  Future<Object> executeCommand(Command command) async {
+  Future<Object> executeCodeAction(
+      Either2<Command, CodeAction> codeAction) async {
+    final command = codeAction.map(
+      (command) => command,
+      (codeAction) => codeAction.command,
+    );
+    return executeCommand(command);
+  }
+
+  Future<Object> executeCommand(Command command,
+      {Either2<num, String> workDoneToken}) async {
     final request = makeRequest(
       Method.workspace_executeCommand,
       ExecuteCommandParams(
         command: command.command,
         arguments: command.arguments,
+        workDoneToken: workDoneToken,
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(request, (result) => result);
   }
 
   void expectDocumentVersion(
@@ -617,7 +653,7 @@
     );
   }
 
-  Future<T> expectErrorNotification<T>(
+  Future<ShowMessageParams> expectErrorNotification(
     FutureOr<void> Function() f, {
     Duration timeout = const Duration(seconds: 5),
   }) async {
@@ -627,7 +663,7 @@
     final notificationFromServer = await firstError.timeout(timeout);
 
     expect(notificationFromServer, isNotNull);
-    return notificationFromServer.params as T;
+    return ShowMessageParams.fromJson(notificationFromServer.params);
   }
 
   Future<T> expectNotification<T>(
@@ -660,7 +696,8 @@
     return requestFromServer;
   }
 
-  Future<T> expectSuccessfulResponseTo<T>(RequestMessage request);
+  Future<T> expectSuccessfulResponseTo<T, R>(
+      RequestMessage request, T Function(R) fromJson);
 
   Future<List<TextEdit>> formatDocument(String fileUri) {
     final request = makeRequest(
@@ -672,7 +709,8 @@
             insertSpaces: true), // These currently don't do anything
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(TextEdit.fromJson));
   }
 
   Future<List<TextEdit>> formatOnType(
@@ -688,7 +726,8 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(TextEdit.fromJson));
   }
 
   Future<List<Either2<Command, CodeAction>>> getCodeActions(
@@ -707,7 +746,11 @@
         context: CodeActionContext(diagnostics: [], only: kinds),
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+      request,
+      _fromJsonList(_generateFromJsonFor(Command.canParse, Command.fromJson,
+          CodeAction.canParse, CodeAction.fromJson)),
+    );
   }
 
   Future<List<CompletionItem>> getCompletion(Uri uri, Position pos,
@@ -720,7 +763,8 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<List<CompletionItem>>(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(CompletionItem.fromJson));
   }
 
   Future<Either2<List<Location>, List<LocationLink>>> getDefinition(
@@ -732,7 +776,14 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+      request,
+      _generateFromJsonFor(
+          _canParseList(Location.canParse),
+          _fromJsonList(Location.fromJson),
+          _canParseList(LocationLink.canParse),
+          _fromJsonList(LocationLink.fromJson)),
+    );
   }
 
   Future<List<Location>> getDefinitionAsLocation(Uri uri, Position pos) async {
@@ -757,7 +808,7 @@
       CustomMethods.DiagnosticServer,
       null,
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(request, DartDiagnosticServer.fromJson);
   }
 
   Future<List<DocumentHighlight>> getDocumentHighlights(Uri uri, Position pos) {
@@ -768,7 +819,8 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<List<DocumentHighlight>>(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(DocumentHighlight.fromJson));
   }
 
   Future<Either2<List<DocumentSymbol>, List<SymbolInformation>>>
@@ -779,7 +831,14 @@
         textDocument: TextDocumentIdentifier(uri: fileUri),
       ),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+      request,
+      _generateFromJsonFor(
+          _canParseList(DocumentSymbol.canParse),
+          _fromJsonList(DocumentSymbol.fromJson),
+          _canParseList(SymbolInformation.canParse),
+          _fromJsonList(SymbolInformation.fromJson)),
+    );
   }
 
   Future<List<FoldingRange>> getFoldingRegions(Uri uri) {
@@ -789,7 +848,8 @@
         textDocument: TextDocumentIdentifier(uri: uri.toString()),
       ),
     );
-    return expectSuccessfulResponseTo<List<FoldingRange>>(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(FoldingRange.fromJson));
   }
 
   Future<Hover> getHover(Uri uri, Position pos) {
@@ -799,7 +859,7 @@
           textDocument: TextDocumentIdentifier(uri: uri.toString()),
           position: pos),
     );
-    return expectSuccessfulResponseTo<Hover>(request);
+    return expectSuccessfulResponseTo(request, Hover.fromJson);
   }
 
   Future<List<Location>> getImplementations(
@@ -814,7 +874,8 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<List<Location>>(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(Location.fromJson));
   }
 
   Future<List<Location>> getReferences(
@@ -830,7 +891,8 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<List<Location>>(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(Location.fromJson));
   }
 
   Future<SignatureHelp> getSignatureHelp(Uri uri, Position pos,
@@ -843,7 +905,7 @@
         context: context,
       ),
     );
-    return expectSuccessfulResponseTo<SignatureHelp>(request);
+    return expectSuccessfulResponseTo(request, SignatureHelp.fromJson);
   }
 
   Future<Location> getSuper(
@@ -857,7 +919,7 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<Location>(request);
+    return expectSuccessfulResponseTo(request, Location.fromJson);
   }
 
   Future<List<SymbolInformation>> getWorkspaceSymbols(String query) {
@@ -865,7 +927,8 @@
       Method.workspace_symbol,
       WorkspaceSymbolParams(query: query),
     );
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(
+        request, _fromJsonList(SymbolInformation.fromJson));
   }
 
   /// Executes [f] then waits for a request of type [method] from the server which
@@ -889,21 +952,29 @@
   /// response to the request it sends (3).
   Future<T> handleExpectedRequest<T, R, RR>(
     Method method,
+    R Function(Map<String, dynamic>) fromJson,
     Future<T> Function() f, {
     @required FutureOr<RR> Function(R) handler,
     Duration timeout = const Duration(seconds: 5),
   }) async {
-    FutureOr<T> outboundRequest;
+    Future<T> outboundRequest;
 
     // Run [f] and wait for the incoming request from the server.
     final incomingRequest = await expectRequest(method, () {
       // Don't return/await the response yet, as this may not complete until
       // after we have handled the request that comes from the server.
       outboundRequest = f();
+
+      // Because we don't await this future until "later", if it throws the
+      // error is treated as unhandled and will fail the test. Attaching an
+      // error handler prevents that, though since the Future completed with
+      // an error it will still be handled as such when the future is later
+      // awaited.
+      outboundRequest.catchError((_) {});
     });
 
     // Handle the request from the server and send the response back.
-    final clientsResponse = await handler(incomingRequest.params as R);
+    final clientsResponse = await handler(fromJson(incomingRequest.params));
     respondTo(incomingRequest, clientsResponse);
 
     // Return a future that completes when the response to the original request
@@ -927,6 +998,20 @@
     bool throwOnFailure = true,
     bool allowEmptyRootUri = false,
   }) async {
+    _clientCapabilities = ClientCapabilities(
+      workspace: workspaceCapabilities,
+      textDocument: textDocumentCapabilities,
+      window: windowCapabilities,
+    );
+
+    // Handle any standard incoming requests that aren't test-specific, for example
+    // accepting requests to create progress tokens.
+    requestsFromServer.listen((request) async {
+      if (request.method == Method.window_workDoneProgress_create) {
+        respondTo(request, await _handleWorkDoneProgressCreate(request));
+      }
+    });
+
     // Assume if none of the project options were set, that we want to default to
     // opening the test project folder.
     if (rootPath == null &&
@@ -941,11 +1026,7 @@
           rootPath: rootPath,
           rootUri: rootUri?.toString(),
           initializationOptions: initializationOptions,
-          capabilities: ClientCapabilities(
-            workspace: workspaceCapabilities,
-            textDocument: textDocumentCapabilities,
-            window: windowCapabilities,
-          ),
+          capabilities: _clientCapabilities,
           workspaceFolders: workspaceFolders?.map(toWorkspaceFolder)?.toList(),
         ));
     final response = await sendRequestToServer(request);
@@ -996,6 +1077,7 @@
   ) {
     return handleExpectedRequest<ResponseMessage, RegistrationParams, void>(
       Method.client_registerCapability,
+      RegistrationParams.fromJson,
       f,
       handler: (registrationParams) {
         registrations.addAll(registrationParams.registrations);
@@ -1021,6 +1103,7 @@
   ) {
     return handleExpectedRequest<ResponseMessage, UnregistrationParams, void>(
       Method.client_unregisterCapability,
+      UnregistrationParams.fromJson,
       f,
       handler: (unregistrationParams) {
         registrations.removeWhere((element) => unregistrationParams
@@ -1070,7 +1153,7 @@
         position: pos,
       ),
     );
-    return expectSuccessfulResponseTo<RangeAndPlaceholder>(request);
+    return expectSuccessfulResponseTo(request, RangeAndPlaceholder.fromJson);
   }
 
   /// Calls the supplied function and responds to any `workspace/configuration`
@@ -1080,6 +1163,7 @@
     return handleExpectedRequest<ResponseMessage, ConfigurationParams,
         List<Map<String, dynamic>>>(
       Method.workspace_configuration,
+      ConfigurationParams.fromJson,
       f,
       handler: (configurationParams) async => [await config],
     );
@@ -1155,7 +1239,7 @@
     String newName,
   ) {
     final request = makeRenameRequest(version, uri, pos, newName);
-    return expectSuccessfulResponseTo<WorkspaceEdit>(request);
+    return expectSuccessfulResponseTo(request, WorkspaceEdit.fromJson);
   }
 
   Future<ResponseMessage> renameRaw(
@@ -1185,7 +1269,7 @@
       Method.completionItem_resolve,
       item,
     );
-    return expectSuccessfulResponseTo<CompletionItem>(request);
+    return expectSuccessfulResponseTo(request, CompletionItem.fromJson);
   }
 
   /// Sends [responseParams] to the server as a successful response to
@@ -1216,7 +1300,7 @@
 
   Future<Null> sendShutdown() {
     final request = makeRequest(Method.shutdown, null);
-    return expectSuccessfulResponseTo(request);
+    return expectSuccessfulResponseTo(request, (result) => result);
   }
 
   WorkspaceFolder toWorkspaceFolder(Uri uri) {
@@ -1235,23 +1319,56 @@
     );
   }
 
-  Future<AnalyzerStatusParams> waitForAnalysisComplete() =>
-      waitForAnalysisStatus(false);
+  Future<void> waitForAnalysisComplete() => waitForAnalysisStatus(false);
 
-  Future<AnalyzerStatusParams> waitForAnalysisStart() =>
-      waitForAnalysisStatus(true);
+  Future<void> waitForAnalysisStart() => waitForAnalysisStatus(true);
 
-  Future<AnalyzerStatusParams> waitForAnalysisStatus(bool analyzing) async {
-    AnalyzerStatusParams params;
+  Future<void> waitForAnalysisStatus(bool analyzing) async {
     await serverToClient.firstWhere((message) {
-      if (message is NotificationMessage &&
-          message.method == CustomMethods.AnalyzerStatus) {
-        params = _convertParams(message, AnalyzerStatusParams.fromJson);
-        return params.isAnalyzing == analyzing;
+      if (message is NotificationMessage) {
+        if (message.method == CustomMethods.AnalyzerStatus) {
+          if (_clientCapabilities.window?.workDoneProgress == true) {
+            throw Exception(
+                'Recieved ${CustomMethods.AnalyzerStatus} notification '
+                'but client supports workDoneProgress');
+          }
+
+          final params = AnalyzerStatusParams.fromJson(message.params);
+          return params.isAnalyzing == analyzing;
+        } else if (message.method == Method.progress) {
+          if (_clientCapabilities.window?.workDoneProgress != true) {
+            throw Exception(
+                'Recieved ${CustomMethods.AnalyzerStatus} notification '
+                'but client supports workDoneProgress');
+          }
+
+          final params = ProgressParams.fromJson(message.params);
+          if (!validProgressTokens.contains(params.token)) {
+            throw Exception('Server sent a progress notification for a token '
+                'that has not been created: ${params.token}');
+          }
+
+          // Skip unrelated progress notifications.
+          if (params.token != analyzingProgressToken) {
+            return false;
+          }
+
+          if (params.value is Map<String, dynamic>) {
+            final isDesiredStatusMessage = analyzing
+                ? WorkDoneProgressBegin.canParse(
+                    params.value, nullLspJsonReporter)
+                : WorkDoneProgressEnd.canParse(
+                    params.value, nullLspJsonReporter);
+
+            return isDesiredStatusMessage;
+          } else {
+            throw Exception('\$/progress params value was not valid');
+          }
+        }
       }
+      // Message is not what we're waiting for.
       return false;
     });
-    return params;
   }
 
   Future<List<ClosingLabel>> waitForClosingLabels(Uri uri) async {
@@ -1260,7 +1377,7 @@
       if (message is NotificationMessage &&
           message.method == CustomMethods.PublishClosingLabels) {
         closingLabelsParams =
-            _convertParams(message, PublishClosingLabelsParams.fromJson);
+            PublishClosingLabelsParams.fromJson(message.params);
 
         return closingLabelsParams.uri == uri.toString();
       }
@@ -1274,13 +1391,12 @@
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
           message.method == Method.textDocument_publishDiagnostics) {
-        diagnosticParams =
-            _convertParams(message, PublishDiagnosticsParams.fromJson);
+        diagnosticParams = PublishDiagnosticsParams.fromJson(message.params);
         return diagnosticParams.uri == uri.toString();
       }
       return false;
-    });
-    return diagnosticParams.diagnostics;
+    }, orElse: () => null);
+    return diagnosticParams?.diagnostics;
   }
 
   Future<FlutterOutline> waitForFlutterOutline(Uri uri) async {
@@ -1288,8 +1404,7 @@
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
           message.method == CustomMethods.PublishFlutterOutline) {
-        outlineParams =
-            _convertParams(message, PublishFlutterOutlineParams.fromJson);
+        outlineParams = PublishFlutterOutlineParams.fromJson(message.params);
 
         return outlineParams.uri == uri.toString();
       }
@@ -1303,7 +1418,7 @@
     await serverToClient.firstWhere((message) {
       if (message is NotificationMessage &&
           message.method == CustomMethods.PublishOutline) {
-        outlineParams = _convertParams(message, PublishOutlineParams.fromJson);
+        outlineParams = PublishOutlineParams.fromJson(message.params);
 
         return outlineParams.uri == uri.toString();
       }
@@ -1321,14 +1436,26 @@
   String withoutRangeMarkers(String contents) =>
       contents.replaceAll(rangeMarkerStart, '').replaceAll(rangeMarkerEnd, '');
 
-  /// A helper to simplify processing of results for both in-process tests (where
-  /// we'll get the real type back), and out-of-process integration tests (where
-  /// params is `Map<String, dynamic>` and needs to be fromJson'd).
-  T _convertParams<T>(
-    IncomingMessage message,
-    T Function(Map<String, dynamic>) fromJson,
-  ) {
-    return message.params is T ? message.params : fromJson(message.params);
+  bool Function(List<dynamic>, LspJsonReporter) _canParseList<T>(
+          bool Function(Map<String, dynamic>, LspJsonReporter) canParse) =>
+      (input, reporter) => input
+          .cast<Map<String, dynamic>>()
+          .every((item) => canParse(item, reporter));
+
+  List<T> Function(List<dynamic>) _fromJsonList<T>(
+          T Function(Map<String, dynamic>) fromJson) =>
+      (input) => input.cast<Map<String, dynamic>>().map(fromJson).toList();
+
+  Future<void> _handleWorkDoneProgressCreate(RequestMessage request) async {
+    if (_clientCapabilities.window?.workDoneProgress != true) {
+      throw Exception('Server sent ${Method.window_workDoneProgress_create} '
+          'but client capabilities do not allow');
+    }
+    final params = WorkDoneProgressCreateParams.fromJson(request.params);
+    if (validProgressTokens.contains(params.token)) {
+      throw Exception('Server tried to create the same progress token twice');
+    }
+    validProgressTokens.add(params.token);
   }
 
   /// Checks whether a notification is likely an error from the server (for
@@ -1339,4 +1466,24 @@
     return notification.method == Method.window_logMessage ||
         notification.method == Method.window_showMessage;
   }
+
+  /// Creates a `fromJson()` function for an `Either2<T1, T2>` using
+  /// the `canParse` and `fromJson` functions for each type.
+  static Either2<T1, T2> Function(R) _generateFromJsonFor<T1, T2, R>(
+      bool Function(R, LspJsonReporter) canParse1,
+      T1 Function(R) fromJson1,
+      bool Function(R, LspJsonReporter) canParse2,
+      T2 Function(R) fromJson2,
+      [LspJsonReporter reporter]) {
+    reporter ??= nullLspJsonReporter;
+    return (input) {
+      if (canParse1(input, reporter)) {
+        return Either2<T1, T2>.t1(fromJson1(input));
+      }
+      if (canParse2(input, reporter)) {
+        return Either2<T1, T2>.t2(fromJson2(input));
+      }
+      throw '$input was not one of ($T1, $T2)';
+    };
+  }
 }
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index 3e7a202..8b0bd596 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -22,7 +22,7 @@
     await openFile(mainFileUri, '');
     // Attempt to make an illegal modification to the file. This indicates the
     // client and server are out of sync and we expect the server to shut down.
-    final error = await expectErrorNotification<ShowMessageParams>(() async {
+    final error = await expectErrorNotification(() async {
       await changeFile(222, mainFileUri, [
         Either2<TextDocumentContentChangeEvent1,
                 TextDocumentContentChangeEvent2>.t1(
@@ -58,7 +58,7 @@
     final notification =
         makeNotification(Method.fromJson(r'some/randomNotification'), null);
 
-    final notificationParams = await expectErrorNotification<ShowMessageParams>(
+    final notificationParams = await expectErrorNotification(
       () => channel.sendNotificationToServer(notification),
     );
     expect(notificationParams, isNotNull);
diff --git a/pkg/analysis_server/test/lsp/signature_help_test.dart b/pkg/analysis_server/test/lsp/signature_help_test.dart
index 889f9e8..fbac555 100644
--- a/pkg/analysis_server/test/lsp/signature_help_test.dart
+++ b/pkg/analysis_server/test/lsp/signature_help_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/src/analysis_server.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,11 +12,48 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SignatureHelpTest);
+    defineReflectiveTests(SignatureHelpWithNullSafetyTest);
   });
 }
 
+mixin SignatureHelpMixin on AbstractLspAnalysisServerTest {
+  Future<void> testSignature(
+    String fileContent,
+    String expectedLabel,
+    String expectedDoc,
+    List<ParameterInformation> expectedParams, {
+    MarkupKind expectedFormat = MarkupKind.Markdown,
+    SignatureHelpContext context,
+  }) async {
+    final res = await getSignatureHelp(
+        mainFileUri, positionFromMarker(fileContent), context);
+
+    // TODO(dantup): Update this when there is clarification on how to handle
+    // no valid selected parameter.
+    expect(res.activeParameter, -1);
+    expect(res.activeSignature, equals(0));
+    expect(res.signatures, hasLength(1));
+    final sig = res.signatures.first;
+    expect(sig.label, equals(expectedLabel));
+    expect(sig.parameters, equals(expectedParams));
+
+    // Test the format matches the tests expectation.
+    // For clients that don't support MarkupContent it'll be a plain string,
+    // but otherwise it'll be a MarkupContent of type PlainText or Markdown.
+    final doc = sig.documentation;
+    if (expectedFormat == null) {
+      // Plain string.
+      expect(doc.valueEquals(expectedDoc), isTrue);
+    } else {
+      final expected = MarkupContent(kind: expectedFormat, value: expectedDoc);
+      expect(doc.valueEquals(expected), isTrue);
+    }
+  }
+}
+
 @reflectiveTest
-class SignatureHelpTest extends AbstractLspAnalysisServerTest {
+class SignatureHelpTest extends AbstractLspAnalysisServerTest
+    with SignatureHelpMixin {
   Future<void> test_dartDocMacro() async {
     final content = '''
     /// {@template template_name}
@@ -405,37 +443,40 @@
       ],
     );
   }
+}
 
-  Future<void> testSignature(
-    String fileContent,
-    String expectedLabel,
-    String expectedDoc,
-    List<ParameterInformation> expectedParams, {
-    MarkupKind expectedFormat = MarkupKind.Markdown,
-    SignatureHelpContext context,
-  }) async {
-    final res = await getSignatureHelp(
-        mainFileUri, positionFromMarker(fileContent), context);
+@reflectiveTest
+class SignatureHelpWithNullSafetyTest extends AbstractLspAnalysisServerTest
+    with SignatureHelpMixin {
+  @override
+  AnalysisServerOptions get serverOptions =>
+      AnalysisServerOptions()..enabledExperiments = ['non-nullable'];
 
-    // TODO(dantup): Update this when there is clarification on how to handle
-    // no valid selected parameter.
-    expect(res.activeParameter, -1);
-    expect(res.activeSignature, equals(0));
-    expect(res.signatures, hasLength(1));
-    final sig = res.signatures.first;
-    expect(sig.label, equals(expectedLabel));
-    expect(sig.parameters, equals(expectedParams));
-
-    // Test the format matches the tests expectation.
-    // For clients that don't support MarkupContent it'll be a plain string,
-    // but otherwise it'll be a MarkupContent of type PlainText or Markdown.
-    final doc = sig.documentation;
-    if (expectedFormat == null) {
-      // Plain string.
-      expect(doc.valueEquals(expectedDoc), isTrue);
-    } else {
-      final expected = MarkupContent(kind: expectedFormat, value: expectedDoc);
-      expect(doc.valueEquals(expected), isTrue);
+  Future<void> test_params_requiredNamed() async {
+    // This test requires support for the "required" keyword.
+    final content = '''
+    /// Does foo.
+    foo(String s, {bool b = true, required bool a}) {
+      foo(^);
     }
+    ''';
+
+    final expectedLabel = 'foo(String s, {bool b = true, required bool a})';
+    final expectedDoc = 'Does foo.';
+
+    await initialize(
+        textDocumentCapabilities: withSignatureHelpContentFormat(
+            emptyTextDocumentClientCapabilities, [MarkupKind.Markdown]));
+    await openFile(mainFileUri, withoutMarkers(content));
+    await testSignature(
+      content,
+      expectedLabel,
+      expectedDoc,
+      [
+        ParameterInformation(label: 'String s'),
+        ParameterInformation(label: 'bool b = true'),
+        ParameterInformation(label: 'required bool a'),
+      ],
+    );
   }
 }
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 11ad43c..c166c2c 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -8,7 +8,6 @@
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_special.dart';
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
@@ -81,13 +80,12 @@
     if (!_closed.isCompleted) {
       _closed.complete();
     }
-  }
-
-  /// Run the object through JSON serialisation to catch any
-  /// issues like fields that are unserialisable types. This is used for
-  /// messages going server-to-client.
-  void ensureMessageCanBeJsonSerialized(ToJsonable message) {
-    jsonEncode(message.toJson());
+    if (!_serverToClient.isClosed) {
+      _serverToClient.close();
+    }
+    if (!_clientToServer.isClosed) {
+      _clientToServer.close();
+    }
   }
 
   @override
@@ -103,7 +101,7 @@
       return;
     }
 
-    ensureMessageCanBeJsonSerialized(notification);
+    notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
 
     _serverToClient.add(notification);
   }
@@ -127,7 +125,7 @@
       return;
     }
 
-    ensureMessageCanBeJsonSerialized(request);
+    request = _convertJson(request, lsp.RequestMessage.fromJson);
 
     _serverToClient.add(request);
   }
@@ -155,7 +153,7 @@
       return;
     }
 
-    ensureMessageCanBeJsonSerialized(response);
+    response = _convertJson(response, lsp.ResponseMessage.fromJson);
 
     // Wrap send response in future to simulate WebSocket.
     Future(() => _serverToClient.add(response));
@@ -188,7 +186,8 @@
         (throwOnError &&
             message is lsp.NotificationMessage &&
             message.method == Method.window_showMessage &&
-            message.params?.type == MessageType.Error));
+            lsp.ShowMessageParams.fromJson(message.params).type ==
+                MessageType.Error));
 
     if (response is lsp.ResponseMessage) {
       return response;
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index e8ae0d7..197842e 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/arglist_contributor.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -1077,6 +1078,50 @@
     assertNoSuggestions();
   }
 
+  Future<void> test_ArgumentList_nnbd_function_named_param() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addTestSource(r'''
+f({int? nullable, int nonnullable}) {}
+main() { f(^);}');
+''');
+    await computeSuggestions();
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'nullable': 'int?',
+      'nonnullable': 'int',
+    });
+  }
+
+  Future<void> test_ArgumentList_nnbd_function_named_param_imported() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addSource('/home/test/lib/a.dart', '''
+f({int? nullable, int nonnullable}) {}''');
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addTestSource(r'''
+import "a.dart";
+main() { f(^);}');
+''');
+    await computeSuggestions();
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'nullable': 'int?',
+      'nonnullable': 'int',
+    });
+  }
+
+  Future<void> test_ArgumentList_nnbd_function_named_param_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addSource('/home/test/lib/a.dart', '''
+// @dart = 2.8
+f({int named}) {}''');
+    addTestSource(r'''
+import "a.dart";
+main() { f(^);}');
+''');
+    await computeSuggestions();
+    assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+      'named': 'int*',
+    });
+  }
+
   Future<void> test_superConstructorInvocation() async {
     addTestSource('''
 class A {
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 7e7ce51..1ae4849 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -5,6 +5,7 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -2302,6 +2303,69 @@
     expect(suggestion.hasNamedParameters, true);
   }
 
+  Future<void> test_function_parameters_nnbd_required() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    resolveSource('/home/test/lib/a.dart', '''
+void m(int? nullable, int nonNullable) {}
+''');
+    addTestSource('''
+import 'a.dart';
+
+main() {^}
+''');
+    await computeSuggestions();
+    var suggestion = assertSuggestFunction('m', 'void');
+    expect(suggestion.parameterNames, hasLength(2));
+    expect(suggestion.parameterNames[0], 'nullable');
+    expect(suggestion.parameterTypes[0], 'int?');
+    expect(suggestion.parameterNames[1], 'nonNullable');
+    expect(suggestion.parameterTypes[1], 'int');
+    expect(suggestion.requiredParameterCount, 2);
+    expect(suggestion.hasNamedParameters, false);
+  }
+
+  Future<void> test_function_parameters_nnbd_required_into_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    resolveSource('/home/test/lib/a.dart', '''
+void m(int? nullable, int nonNullable) {}
+''');
+    addTestSource('''
+// @dart = 2.8
+import 'a.dart';
+
+main() {^}
+''');
+    await computeSuggestions();
+    var suggestion = assertSuggestFunction('m', 'void');
+    expect(suggestion.parameterNames, hasLength(2));
+    expect(suggestion.parameterNames[0], 'nullable');
+    expect(suggestion.parameterTypes[0], 'int');
+    expect(suggestion.parameterNames[1], 'nonNullable');
+    expect(suggestion.parameterTypes[1], 'int');
+    expect(suggestion.requiredParameterCount, 2);
+    expect(suggestion.hasNamedParameters, false);
+  }
+
+  Future<void> test_function_parameters_nnbd_required_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    resolveSource('/home/test/lib/a.dart', '''
+// @dart = 2.8
+void m(int param) {}
+''');
+    addTestSource('''
+import 'a.dart';
+
+main() {^}
+''');
+    await computeSuggestions();
+    var suggestion = assertSuggestFunction('m', 'void');
+    expect(suggestion.parameterNames, hasLength(1));
+    expect(suggestion.parameterNames[0], 'param');
+    expect(suggestion.parameterTypes[0], 'int*');
+    expect(suggestion.requiredParameterCount, 1);
+    expect(suggestion.hasNamedParameters, false);
+  }
+
   Future<void> test_function_parameters_none() async {
     resolveSource('/home/test/lib/a.dart', '''
 void m() {}
diff --git a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
index 44c2b39..07d36a2 100644
--- a/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
+++ b/pkg/analysis_server/test/services/completion/postfix/postfix_completion_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/services/completion/postfix/postfix_completion.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -708,6 +709,162 @@
 ''');
   }
 
+  Future<void> test_tryonThrowStatement_nnbd() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    await _prepareCompletion('.tryon', '''
+f() {
+  throw 'error';.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+f() {
+  try {
+    throw 'error';/*caret*/
+  } on String catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_into_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    newFile('/home/test/lib/a.dart', content: r'''
+String? x;
+''');
+    await _prepareCompletion('.tryon', '''
+// @dart = 2.8
+import 'a.dart';
+f() {
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+// @dart = 2.8
+import 'a.dart';
+f() {
+  try {
+    throw x;/*caret*/
+  } on String catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_into_legacy_nested() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    newFile('/home/test/lib/a.dart', content: r'''
+List<String?> x;
+''');
+    await _prepareCompletion('.tryon', '''
+// @dart = 2.8
+import 'a.dart';
+f() {
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+// @dart = 2.8
+import 'a.dart';
+f() {
+  try {
+    throw x;/*caret*/
+  } on List<String> catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    newFile('/home/test/lib/a.dart', content: r'''
+// @dart = 2.8
+String x;
+''');
+    await _prepareCompletion('.tryon', '''
+import 'a.dart';
+f() {
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+import 'a.dart';
+f() {
+  try {
+    throw x;/*caret*/
+  } on String catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_legacy_nested() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    newFile('/home/test/lib/a.dart', content: r'''
+// @dart = 2.8
+List<String> x;
+''');
+    await _prepareCompletion('.tryon', '''
+import 'a.dart';
+f() {
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+import 'a.dart';
+f() {
+  try {
+    throw x;/*caret*/
+  } on List<String> catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_nullable() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    await _prepareCompletion('.tryon', '''
+f() {
+  String? x;
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+f() {
+  String? x;
+  try {
+    throw x;/*caret*/
+  } on String catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
+  Future<void> test_tryonThrowStatement_nnbd_nullable_nested() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    await _prepareCompletion('.tryon', '''
+f() {
+  List<String?>? x;
+  throw x;.tryon
+}
+''');
+    _assertHasChange('Expand .tryon', '''
+f() {
+  List<String?>? x;
+  try {
+    throw x;/*caret*/
+  } on List<String?> catch (e, s) {
+    print(s);
+  }
+}
+''');
+  }
+
   Future<void> test_tryonThrowString() async {
     await _prepareCompletion('.tryon', '''
 f() {
diff --git a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
index 1353f6d..9f40c52 100644
--- a/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
+++ b/pkg/analysis_server/test/services/refactoring/abstract_refactoring.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show RefactoringProblemSeverity, SourceChange, SourceEdit;
 import 'package:test/test.dart';
@@ -38,6 +39,9 @@
   /// Asserts that [refactoringChange] contains a [FileEdit] for the file
   /// with the given [path], and it results the [expectedCode].
   void assertFileChangeResult(String path, String expectedCode) {
+    if (useLineEndingsForPlatform) {
+      expectedCode = normalizeNewlinesForPlatform(expectedCode);
+    }
     // prepare FileEdit
     var fileEdit = refactoringChange.getFileEdit(convertPath(path));
     expect(fileEdit, isNotNull, reason: 'No file edit for $path');
@@ -112,6 +116,9 @@
   /// Asserts that [refactoringChange] contains a [FileEdit] for [testFile], and
   /// it results the [expectedCode].
   void assertTestChangeResult(String expectedCode) {
+    if (useLineEndingsForPlatform) {
+      expectedCode = normalizeNewlinesForPlatform(expectedCode);
+    }
     // prepare FileEdit
     var fileEdit = refactoringChange.getFileEdit(testFile);
     expect(fileEdit, isNotNull);
@@ -131,6 +138,8 @@
   @override
   void setUp() {
     super.setUp();
+    // TODO(dantup): Get these tests passing with either line ending and change this to true.
+    useLineEndingsForPlatform = false;
     searchEngine = SearchEngineImpl([driver]);
   }
 }
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index 5f53c00..9db1931 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -2923,7 +2923,8 @@
   }
 
   void _createRefactoringForStartEndComments() {
-    var offset = findEnd('// start') + '\n'.length;
+    final eol = testCode.contains('\r\n') ? '\r\n' : '\r';
+    var offset = findEnd('// start') + eol.length;
     var end = findOffset('// end');
     _createRefactoring(offset, end - offset);
   }
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
index b25f74c..8c1da18 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -442,7 +442,7 @@
   Widget build(BuildContext context) {
     return createColumn();
   }
-  
+
   Widget createColumn() {
     var a = new Text('AAA');
     var b = new Text('BBB');
@@ -499,7 +499,7 @@
       ],
     );
   }
-  
+
   Widget createColumn(String p1, int p2) {
     var a = new Text('$foo $p1');
     var b = new Text('$p2');
@@ -571,7 +571,7 @@
       ],
     );
   }
-  
+
   Widget createColumn({String p1, int p2}) {
     var a = new Text('$foo $p1');
     var b = new Text('$p2');
diff --git a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
index a119979..614fe4f 100644
--- a/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
+++ b/pkg/analysis_server/test/src/lsp/lsp_packet_transformer_test.dart
@@ -74,10 +74,10 @@
       final payload = '{ json payload }';
       final lspPacket =
           makeLspPacket(payload, 'application/vscode-jsonrpc; charset=ascii');
-      final outputStream = await Stream.fromIterable([lspPacket])
-          .transform(LspPacketTransformer());
+      final outputStream =
+          Stream.fromIterable([lspPacket]).transform(LspPacketTransformer());
 
-      expectLater(outputStream.toList(),
+      await expectLater(outputStream.toList(),
           throwsA(const TypeMatcher<InvalidEncodingError>()));
     });
   });
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
index 78926b0..d0d30dd 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/add_type_annotation_test.dart
@@ -50,7 +50,7 @@
   var f = 0;
 }
 ''');
-    await await assertHasAssistAt('var ', '''
+    await assertHasAssistAt('var ', '''
 class A {
   int f = 0;
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
index 3a9e20f..478f098 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/assist_processor.dart
@@ -6,6 +6,7 @@
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
+import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
@@ -53,6 +54,11 @@
   /// have been applied.
   Future<void> assertHasAssist(String expected,
       {Map<String, List<String>> additionallyChangedFiles}) async {
+    if (useLineEndingsForPlatform) {
+      expected = normalizeNewlinesForPlatform(expected);
+      additionallyChangedFiles = additionallyChangedFiles?.map((key, value) =>
+          MapEntry(key, value.map(normalizeNewlinesForPlatform).toList()));
+    }
     var assist = await _assertHasAssist();
     _change = assist.change;
     expect(_change.id, kind.id);
@@ -80,6 +86,9 @@
   /// given [snippet] which produces the [expected] code when applied to [testCode].
   Future<void> assertHasAssistAt(String snippet, String expected,
       {int length = 0}) async {
+    if (useLineEndingsForPlatform) {
+      expected = normalizeNewlinesForPlatform(expected);
+    }
     _offset = findOffset(snippet);
     _length = length;
     var assist = await _assertHasAssist();
@@ -134,6 +143,10 @@
 
   @override
   Future<void> resolveTestUnit(String code) async {
+    if (useLineEndingsForPlatform) {
+      code = normalizeNewlinesForPlatform(code);
+    }
+    final eol = code.contains('\r\n') ? '\r\n' : '\n';
     var offset = code.indexOf('/*caret*/');
     if (offset >= 0) {
       var endOffset = offset + '/*caret*/'.length;
@@ -141,13 +154,13 @@
       _offset = offset;
       _length = 0;
     } else {
-      var startOffset = code.indexOf('// start\n');
-      var endOffset = code.indexOf('// end\n');
+      var startOffset = code.indexOf('// start$eol');
+      var endOffset = code.indexOf('// end$eol');
       if (startOffset >= 0 && endOffset >= 0) {
-        var startLength = '// start\n'.length;
+        var startLength = '// start$eol'.length;
         code = code.substring(0, startOffset) +
             code.substring(startOffset + startLength, endOffset) +
-            code.substring(endOffset + '// end\n'.length);
+            code.substring(endOffset + '// end$eol'.length);
         _offset = startOffset;
         _length = endOffset - startLength - _offset;
       } else {
@@ -158,6 +171,12 @@
     return super.resolveTestUnit(code);
   }
 
+  @override
+  void setUp() {
+    super.setUp();
+    useLineEndingsForPlatform = true;
+  }
+
   /// Computes assists and verifies that there is an assist of the given kind.
   Future<Assist> _assertHasAssist() async {
     var assists = await _computeAssists();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
index 11b0ee0..2eb4fa8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,6 +12,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AddMissingRequiredArgumentTest);
+    defineReflectiveTests(AddMissingRequiredArgumentWithNullSafetyTest);
   });
 }
 
@@ -248,6 +250,99 @@
 ''');
   }
 
+  Future<void> test_constructor_single_closure_nnbd() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addMetaPackage();
+    addSource('/home/test/lib/a.dart', r'''
+import 'package:meta/meta.dart';
+
+typedef int Callback(int? a);
+
+class A {
+  A({@required Callback callback}) {}
+}
+''');
+    await resolveTestUnit('''
+import 'package:test/a.dart';
+
+main() {
+  A a = new A();
+  print(a);
+}
+''');
+    await assertHasFix('''
+import 'package:test/a.dart';
+
+main() {
+  A a = new A(callback: (int? a) {  });
+  print(a);
+}
+''');
+  }
+
+  Future<void> test_constructor_single_closure_nnbd_from_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addMetaPackage();
+    addSource('/home/test/lib/a.dart', r'''
+// @dart = 2.8
+import 'package:meta/meta.dart';
+
+typedef int Callback(int a);
+
+class A {
+  A({@required Callback callback}) {}
+}
+''');
+    await resolveTestUnit('''
+import 'package:test/a.dart';
+
+main() {
+  A a = new A();
+  print(a);
+}
+''');
+    await assertHasFix('''
+import 'package:test/a.dart';
+
+main() {
+  A a = new A(callback: (int a) {  });
+  print(a);
+}
+''');
+  }
+
+  Future<void> test_constructor_single_closure_nnbd_into_legacy() async {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    addMetaPackage();
+    addSource('/home/test/lib/a.dart', r'''
+import 'package:meta/meta.dart';
+
+typedef int Callback(int? a);
+
+class A {
+  A({@required Callback callback}) {}
+}
+''');
+    await resolveTestUnit('''
+// @dart = 2.8
+import 'package:test/a.dart';
+
+main() {
+  A a = new A();
+  print(a);
+}
+''');
+    await assertHasFix('''
+// @dart = 2.8
+import 'package:test/a.dart';
+
+main() {
+  A a = new A(callback: (int a) {  });
+  print(a);
+}
+''');
+  }
+
   Future<void> test_constructor_single_list() async {
     addMetaPackage();
     addSource('/home/test/lib/a.dart', r'''
@@ -362,7 +457,7 @@
 
 build() {
   return new MyWidget(
-    foo: null,
+    foo: '',
     child: null,
   );
 }
@@ -396,7 +491,7 @@
 
 build() {
   return new MyWidget(
-    foo: null,
+    foo: '',
     children: null,
   );
 }
@@ -464,3 +559,42 @@
 ''');
   }
 }
+
+@reflectiveTest
+class AddMissingRequiredArgumentWithNullSafetyTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.ADD_MISSING_REQUIRED_ARGUMENT;
+
+  Future<void> test_nonNullable() async {
+    await resolveTestUnit('''
+void f({required int x}) {}
+void g() {
+  f();
+}
+''');
+    await assertHasFix('''
+void f({required int x}) {}
+void g() {
+  f(x: null);
+}
+''');
+  }
+
+  Future<void> test_nullable() async {
+    await resolveTestUnit('''
+void f({required int? x}) {}
+void g() {
+  f();
+}
+''');
+    await assertHasFix('''
+void f({required int? x}) {}
+void g() {
+  f(x: null);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/add_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_const_test.dart
index 7962f4f..735e1c5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/add_const_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_const_test.dart
@@ -9,11 +9,37 @@
 
 void main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(AddConstToConstructorTest);
     defineReflectiveTests(AddConstToImmutableConstructorTest);
   });
 }
 
 @reflectiveTest
+class AddConstToConstructorTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_const_constructors;
+
+  /// Disabled in BulkFixProcessor.
+  @failingTest
+  Future<void> test_singleFile() async {
+    addMetaPackage();
+    await resolveTestUnit(r'''
+class C {
+  const C([C c]);
+}
+var c = C(C());
+''');
+    // TODO (pq): results are incompatible w/ `unnecessary_const`
+    await assertHasFix(r'''
+class C {
+  const C([C c]);
+}
+var c = const C(const C());
+''');
+  }
+}
+
+@reflectiveTest
 class AddConstToImmutableConstructorTest extends BulkFixProcessorTest {
   @override
   String get lintCode => LintNames.prefer_const_constructors_in_immutables;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/add_diagnostic_property_reference_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_diagnostic_property_reference_test.dart
new file mode 100644
index 0000000..cda5640
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/add_diagnostic_property_reference_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddDiagnosticPropertyReferenceTest);
+  });
+}
+
+@reflectiveTest
+class AddDiagnosticPropertyReferenceTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.diagnostic_describe_all_properties;
+
+  Future<void> test_singleFile() async {
+    addFlutterPackage();
+    await resolveTestUnit('''
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+
+class C extends Widget with Diagnosticable {
+  bool get absorbing => _absorbing;
+  bool _absorbing;
+  bool ignoringSemantics;
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
+  }
+}
+
+class D extends Widget with Diagnosticable {
+  bool ignoringSemantics;
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+  }
+}
+''');
+    await assertHasFix('''
+import 'package:flutter/foundation.dart';
+import 'package:flutter/widgets.dart';
+
+class C extends Widget with Diagnosticable {
+  bool get absorbing => _absorbing;
+  bool _absorbing;
+  bool ignoringSemantics;
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+    properties.add(DiagnosticsProperty<bool>('absorbing', absorbing));
+    properties.add(DiagnosticsProperty<bool>('ignoringSemantics', ignoringSemantics));
+  }
+}
+
+class D extends Widget with Diagnosticable {
+  bool ignoringSemantics;
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    properties.add(DiagnosticsProperty<bool>('ignoringSemantics', ignoringSemantics));
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
index ef3a83a..bd51bc3 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
@@ -58,7 +58,7 @@
     var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
     tracker.addContext(driver.analysisContext);
     var changeBuilder =
-        await BulkFixProcessor(workspace).fixErrorsInLibraries([testFile]);
+        await BulkFixProcessor(workspace).fixErrors([driver.analysisContext]);
     return changeBuilder.sourceChange;
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart
new file mode 100644
index 0000000..8810f14
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_list_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToListLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToListLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+List l = List();
+var l2 = List<int>();
+''');
+    await assertHasFix('''
+List l = [];
+var l2 = <int>[];
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart
new file mode 100644
index 0000000..066755e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_map_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToMapLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToMapLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+Map m = Map();
+var m2 = Map<String, int>();
+''');
+    await assertHasFix('''
+Map m = {};
+var m2 = <String, int>{};
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart
new file mode 100644
index 0000000..526e697
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_set_literal_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToSetLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToSetLiteralTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_collection_literals;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+Set s = Set();
+var s1 = Set<int>();
+''');
+    await assertHasFix('''
+Set s = {};
+var s1 = <int>{};
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
new file mode 100644
index 0000000..67caf6c
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/data_driven_test.dart
@@ -0,0 +1,1135 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtendsNonClassTest);
+    defineReflectiveTests(ExtraPositionalArgumentsCouldBeNamedTest);
+    defineReflectiveTests(ExtraPositionalArgumentsTest);
+    defineReflectiveTests(ImplementsNonClassTest);
+    defineReflectiveTests(InvalidOverrideTest);
+    defineReflectiveTests(MixinOfNonClassTest);
+    defineReflectiveTests(NewWithUndefinedConstructorDefaultTest);
+    defineReflectiveTests(NotEnoughPositionalArgumentsTest);
+    defineReflectiveTests(OverrideOnNonOverridingMethodTest);
+    defineReflectiveTests(UndefinedClassTest);
+    defineReflectiveTests(UndefinedFunctionTest);
+    defineReflectiveTests(UndefinedGetterTest);
+    defineReflectiveTests(UndefinedIdentifierTest);
+    defineReflectiveTests(UndefinedMethodTest);
+    defineReflectiveTests(UndefinedSetterTest);
+    defineReflectiveTests(WrongNumberOfTypeArgumentsConstructorTest);
+    defineReflectiveTests(WrongNumberOfTypeArgumentsExtensionTest);
+    defineReflectiveTests(WrongNumberOfTypeArgumentsMethodTest);
+    defineReflectiveTests(WrongNumberOfTypeArgumentsTest);
+  });
+}
+
+@reflectiveTest
+class ExtendsNonClassTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {}
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A extends Old {}
+class B extends Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A extends New {}
+class B extends New {}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A extends Old {}
+class B extends Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A extends New {}
+class B extends New {}
+''');
+  }
+}
+
+@reflectiveTest
+class ExtraPositionalArgumentsCouldBeNamedTest extends _DataDrivenTest {
+  @failingTest
+  Future<void> test_replaceParameter() async {
+    // This fails for two reasons. First, we grab the argument from the outer
+    // invocation before we modify it, which causes the unmodified version of
+    // the argument to be used for the added named parameter. Second, we produce
+    // overlapping edits.
+    setPackageContent('''
+int f(int x, {int y = 0}) => x;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Replace parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 1
+      name: 'y'
+      style: required_named
+      argumentValue:
+        expression: '{% old %}'
+        variables:
+          old:
+            kind: 'argument'
+            index: 1
+    - kind: 'removeParameter'
+      index: 1
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void g() {
+  f(0, f(1, 2));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void g() {
+  f(0, y: f(1, y: 2));
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ExtraPositionalArgumentsTest extends _DataDrivenTest {
+  @failingTest
+  Future<void> test_removeParameter() async {
+    // This fails because we delete the extra argument from the inner invocation
+    // (`, 2`) before deleting the argument from the outer invocation, which
+    // results in three characters too many being deleted.
+    setPackageContent('''
+int f(int x) => x;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Remove parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    function: 'f'
+  changes:
+    - kind: 'removeParameter'
+      index: 1
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void g() {
+  f(0, f(1, 2));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void g() {
+  f(0);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class ImplementsNonClassTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {}
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A implements Old {}
+class B implements Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A implements New {}
+class B implements New {}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A implements Old {}
+class B implements Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A implements New {}
+class B implements New {}
+''');
+  }
+}
+
+@reflectiveTest
+class InvalidOverrideTest extends _DataDrivenTest {
+  @failingTest
+  Future<void> test_addParameter() async {
+    // This functionality hasn't been implemented yet.
+    setPackageContent('''
+class C {
+  void m(int x, int y) {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'm'
+    inClass: 'C'
+  changes:
+    - kind: 'addParameter'
+      index: 1
+      name: 'y'
+      style: required_positional
+      argumentValue:
+        expression: '0'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A extends C {
+  @override
+  void m(int x) {}
+}
+class B extends C {
+  @override
+  void m(int x) {}
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A extends C {
+  @override
+  void m(int x, int y) {}
+}
+class B extends C {
+  @override
+  void m(int x, int y) {}
+}
+''');
+  }
+
+  Future<void> test_addTypeParameter() async {
+    setPackageContent('''
+class C {
+  void m<T>() {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'm'
+    inClass: 'C'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 0
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A extends C {
+  @override
+  void m() {}
+}
+class B extends C {
+  @override
+  void m() {}
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A extends C {
+  @override
+  void m<T>() {}
+}
+class B extends C {
+  @override
+  void m<T>() {}
+}
+''');
+  }
+}
+
+@reflectiveTest
+class MixinOfNonClassTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {}
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A with Old {}
+class B with Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A with New {}
+class B with New {}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class A with Old {}
+class B with Old {}
+''');
+    await assertHasFix('''
+import '$importUri';
+class A with New {}
+class B with New {}
+''');
+  }
+}
+
+@reflectiveTest
+class NewWithUndefinedConstructorDefaultTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  C([C c]);
+  C.new([C c]);
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    constructor: ''
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+C c() => C(C());
+''');
+    await assertHasFix('''
+import '$importUri';
+C c() => C.new(C.new());
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class C {
+  C.new([C c]);
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    constructor: ''
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+C c() => C(C());
+''');
+    await assertHasFix('''
+import '$importUri';
+C c() => C.new(C.new());
+''');
+  }
+}
+
+@reflectiveTest
+class NotEnoughPositionalArgumentsTest extends _DataDrivenTest {
+  Future<void> test_addParameter() async {
+    setPackageContent('''
+int f(int x, int y) => x + y;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 1
+      name: 'y'
+      style: required_positional
+      argumentValue:
+        expression: '0'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void g() {
+  f(f(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void g() {
+  f(f(0, 0), 0);
+}
+''');
+  }
+}
+
+@reflectiveTest
+class OverrideOnNonOverridingMethodTest extends _DataDrivenTest {
+  Future<void> test_rename() async {
+    setPackageContent('''
+class C {
+  int new(int x) => x + 1;
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+class D extends C {
+  @override
+  int old(int x) => x + 2;
+}
+class E extends C {
+  @override
+  int old(int x) => x + 3;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+class D extends C {
+  @override
+  int new(int x) => x + 2;
+}
+class E extends C {
+  @override
+  int new(int x) => x + 3;
+}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedClassTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {}
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(Old a, Old b) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(New a, New b) {}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class New {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to New'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'Old'
+  changes:
+    - kind: 'rename'
+      newName: 'New'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(Old a, Old b) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(New a, New b) {}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedFunctionTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+@deprecated
+int old(int x) => x + 1;
+int new(int x) => x + 1;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    function: 'old'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f() {
+  old(old(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f() {
+  new(new(0));
+}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+int new(int x) => x + 1;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    function: 'old'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f() {
+  old(old(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f() {
+  new(new(0));
+}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedGetterTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  int get old => 0;
+  int get new => 0;
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    getter: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old + b.old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new + b.new;
+}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class C {
+  int get new => 0;
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    getter: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old + b.old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new + b.new;
+}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedIdentifierTest extends _DataDrivenTest {
+  Future<void> test_rename_topLevelVariable_deprecated() async {
+    setPackageContent('''
+@deprecated
+int old = 0;
+int new = 0;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    variable: 'old'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f() {
+  old + old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f() {
+  new + new;
+}
+''');
+  }
+
+  Future<void> test_rename_topLevelVariable_removed() async {
+    setPackageContent('''
+int new = 0;
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    variable: 'old'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f() {
+  old + old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f() {
+  new + new;
+}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedMethodTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  int old(int x) => x + 1;
+  int new(int x) => x + 1;
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old(b.old(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new(b.new(0));
+}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class C {
+  int new(int x) => x + 1;
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old(b.old(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new(b.new(0));
+}
+''');
+  }
+}
+
+@reflectiveTest
+class UndefinedSetterTest extends _DataDrivenTest {
+  Future<void> test_rename_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  set new(int x) {}
+  set new(int x) {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    setter: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old = b.old = 1;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new = b.new = 1;
+}
+''');
+  }
+
+  Future<void> test_rename_removed() async {
+    setPackageContent('''
+class C {
+  set new(int x) {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Rename to new'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    setter: 'old'
+    inClass: 'C'
+  changes:
+    - kind: 'rename'
+      newName: 'new'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C a, C b) {
+  a.old = b.old = 1;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C a, C b) {
+  a.new = b.new = 1;
+}
+''');
+  }
+}
+
+@reflectiveTest
+class WrongNumberOfTypeArgumentsConstructorTest extends _DataDrivenTest {
+  Future<void> test_addTypeParameter() async {
+    setPackageContent('''
+class C<S, T> {
+  C.c([C c]);
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'C'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 1
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+C f() => C<String>.c(C<String>.c());
+''');
+    await assertHasFix('''
+import '$importUri';
+C f() => C<String, int>.c(C<String, int>.c());
+''');
+  }
+}
+
+@reflectiveTest
+class WrongNumberOfTypeArgumentsExtensionTest extends _DataDrivenTest {
+  Future<void> test_addTypeParameter() async {
+    setPackageContent('''
+extension E<S, T> on String {
+  int m(int x) {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    extension: 'E'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 1
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(String s) {
+  E<String>(s).m(E<String>(s).m(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(String s) {
+  E<String, int>(s).m(E<String, int>(s).m(0));
+}
+''');
+  }
+}
+
+@reflectiveTest
+class WrongNumberOfTypeArgumentsMethodTest extends _DataDrivenTest {
+  Future<void> test_addTypeParameter() async {
+    setPackageContent('''
+class C {
+  int m<S, T>(int x) {}
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    method: 'm'
+    inClass: 'C'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 1
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C c) {
+  c.m<String>(c.m<String>(0));
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C c) {
+  c.m<String, int>(c.m<String, int>(0));
+}
+''');
+  }
+}
+
+@reflectiveTest
+class WrongNumberOfTypeArgumentsTest extends _DataDrivenTest {
+  Future<void> test_addTypeParameter() async {
+    setPackageContent('''
+class C<S, T> {}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'C'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 1
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+void f(C<String> c) {}
+''');
+    await assertHasFix('''
+import '$importUri';
+void f(C<String, int> c) {}
+''');
+  }
+
+  Future<void> test_addTypeParameter_unnamedConstructor() async {
+    setPackageContent('''
+class C<S, T> {
+  C([C c]);
+}
+''');
+    addPackageDataFile('''
+version: 1
+transforms:
+- title: 'Add type parameter'
+  date: 2020-09-01
+  element:
+    uris: ['$importUri']
+    class: 'C'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 1
+      name: 'T'
+      argumentValue:
+        expression: 'int'
+''');
+    await resolveTestUnit('''
+import '$importUri';
+C f() => C<String>(C<String>());
+''');
+    await assertHasFix('''
+import '$importUri';
+C f() => C<String, int>(C<String, int>());
+''');
+  }
+}
+
+class _DataDrivenTest extends BulkFixProcessorTest {
+  /// Return the URI used to import the library created by [setPackageContent].
+  String get importUri => 'package:p/lib.dart';
+
+  /// Add the file containing the data used by the data-driven fix with the
+  /// given [content].
+  void addPackageDataFile(String content) {
+    addPackageFile('p', TransformSetManager.dataFileName, content);
+  }
+
+  /// Set the content of the library that defines the element referenced by the
+  /// data on which this test is based.
+  void setPackageContent(String content) {
+    addPackageFile('p', 'lib.dart', content);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_invocation_test.dart
new file mode 100644
index 0000000..2e6ed1b
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/inline_invocation_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InlineInvocationTest);
+  });
+}
+
+@reflectiveTest
+class InlineInvocationTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_inlined_adds;
+
+  Future<void> test_singleFile() async {
+    await resolveTestUnit('''
+var l = []..add('a')..add('b');
+var l2 = ['a', 'b']..add('c');
+var l3 = ['a']..addAll(['b', 'c']);
+''');
+    await assertHasFix('''
+var l = ['a']..add('b');
+var l2 = ['a', 'b', 'c'];
+var l3 = ['a', 'b', 'c'];
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/replace_new_with_const_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/replace_new_with_const_test.dart
new file mode 100644
index 0000000..a6c5170
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/replace_new_with_const_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReplaceNewWithConstTest);
+  });
+}
+
+@reflectiveTest
+class ReplaceNewWithConstTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.prefer_const_constructors;
+
+  /// Disabled in BulkFixProcessor.
+  @failingTest
+  Future<void> test_singleFile() async {
+    await resolveTestUnit(r'''
+class C {
+  const C();
+}
+main() {
+  print('${new C()} ${new C()}');
+}
+''');
+    await assertHasFix(r'''
+class C {
+  const C();
+}
+main() {
+  print('${const C()} ${const C()}');
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
index 7c7d235..e2ae5f5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
@@ -6,6 +6,8 @@
 
 import 'add_await_test.dart' as add_await;
 import 'add_const_test.dart' as add_const;
+import 'add_diagnostic_property_reference_test.dart'
+    as add_diagnostic_property_reference;
 import 'add_override_test.dart' as add_override;
 import 'convert_documentation_into_line_test.dart'
     as convert_documentation_into_line;
@@ -17,13 +19,18 @@
 import 'convert_to_if_element_test.dart' as convert_to_if_element;
 import 'convert_to_if_null_test.dart' as convert_to_if_null;
 import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
+import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
+import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
 import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
 import 'convert_to_relative_import_test.dart' as convert_to_relative_import;
+import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_strings_test.dart'
     as convert_to_single_quoted_strings;
 import 'convert_to_spread_test.dart' as convert_to_spread;
 import 'convert_to_where_type_test.dart' as convert_to_where_type;
 import 'create_method_test.dart' as create_method;
+import 'data_driven_test.dart' as data_driven;
+import 'inline_invocation_test.dart' as inline_invocation;
 import 'make_final_test.dart' as make_final;
 import 'remove_argument_test.dart' as remove_argument;
 import 'remove_await_test.dart' as remove_await;
@@ -44,6 +51,7 @@
 import 'rename_to_camel_case_test.dart' as rename_to_camel_case;
 import 'replace_colon_with_equals_test.dart' as replace_colon_with_equals;
 import 'replace_final_with_const_test.dart' as replace_final_with_const;
+import 'replace_new_with_const_test.dart' as replace_new_with_const;
 import 'replace_null_with_closure_test.dart' as replace_null_with_closure;
 import 'replace_with_conditional_assignment_test.dart'
     as replace_with_conditional_assignment;
@@ -59,6 +67,7 @@
   defineReflectiveSuite(() {
     add_await.main();
     add_const.main();
+    add_diagnostic_property_reference.main();
     add_override.main();
     convert_documentation_into_line.main();
     convert_map_from_iterable_to_for_literal.main();
@@ -67,12 +76,17 @@
     convert_to_if_element.main();
     convert_to_if_null.main();
     convert_to_int_literal.main();
+    convert_to_list_literal.main();
+    convert_to_map_literal.main();
     convert_to_null_aware.main();
     convert_to_relative_import.main();
+    convert_to_set_literal.main();
     convert_to_single_quoted_strings.main();
     convert_to_spread.main();
     convert_to_where_type.main();
     create_method.main();
+    data_driven.main();
+    inline_invocation.main();
     make_final.main();
     remove_argument.main();
     remove_await.main();
@@ -93,6 +107,7 @@
     replace_with_conditional_assignment.main();
     replace_colon_with_equals.main();
     replace_final_with_const.main();
+    replace_new_with_const.main();
     replace_null_with_closure.main();
     replace_with_is_empty.main();
     replace_with_tear_off.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_if_null_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_if_null_test.dart
index ba18148..81c4960 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_if_null_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_if_null_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -36,6 +37,33 @@
 ''');
   }
 
+  Future<void> test_malformed() async {
+    await resolveTestUnit('''
+void f(String s, bool b) {
+  print(b ? s != null ? s : : null);
+}
+''');
+    await assertNoFix(errorFilter: (error) {
+      var code = error.errorCode;
+      return code is LintCode &&
+          code.name == LintNames.prefer_if_null_operators;
+    });
+  }
+
+  Future<void> test_malformed_parentheses() async {
+    // https://github.com/dart-lang/sdk/issues/43432
+    await resolveTestUnit('''
+void f(String s, bool b) {
+  print(b ? (s != null ? s : ) : null);
+}
+''');
+    await assertNoFix(errorFilter: (error) {
+      var code = error.errorCode;
+      return code is LintCode &&
+          code.name == LintNames.prefer_if_null_operators;
+    });
+  }
+
   Future<void> test_notEqual() async {
     await resolveTestUnit('''
 void f(String s) {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart
index e9253d7..a57a686 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_local_variable_test.dart
@@ -20,6 +20,13 @@
   @override
   FixKind get kind => DartFixKind.CREATE_LOCAL_VARIABLE;
 
+  @override
+  void setUp() {
+    super.setUp();
+    // TODO(dantup): Get these tests passing with either line ending.
+    useLineEndingsForPlatform = false;
+  }
+
   Future<void> test_functionType_named() async {
     await resolveTestUnit('''
 typedef MY_FUNCTION(int p);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
index 6bb0fd9..1ca73821 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_missing_overrides_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -12,6 +13,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(CreateMissingOverridesTest);
+    defineReflectiveTests(CreateMissingOverridesWithNullSafetyTest);
   });
 }
 
@@ -476,6 +478,35 @@
 ''');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/43667')
+  Future<void> test_method_withTypedef() async {
+    // This fails because the element representing `Base.closure` has a return
+    // type that has forgotten that it was declared using the typedef `Closure`.
+    await resolveTestUnit('''
+typedef Closure = T Function<T>(T input);
+
+abstract class Base {
+  Closure closure();
+}
+
+class Concrete extends Base {}
+''');
+    await assertHasFix('''
+typedef Closure = T Function<T>(T input);
+
+abstract class Base {
+  Closure closure();
+}
+
+class Concrete extends Base {
+  @override
+  Closure closure() {
+    // TODO: implement closure
+  }
+}
+''');
+  }
+
   Future<void> test_methods_reverseOrder() async {
     await resolveTestUnit('''
 abstract class A {
@@ -578,3 +609,58 @@
 ''');
   }
 }
+
+@reflectiveTest
+class CreateMissingOverridesWithNullSafetyTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.CREATE_MISSING_OVERRIDES;
+
+  Future<void> test_method_generic_nullable_dynamic() async {
+    // https://github.com/dart-lang/sdk/issues/43535
+    await resolveTestUnit('''
+class A {
+  void doSomething(Map<String, dynamic>? m) {}
+}
+
+class B implements A {}
+''');
+    await assertHasFix('''
+class A {
+  void doSomething(Map<String, dynamic>? m) {}
+}
+
+class B implements A {
+  @override
+  void doSomething(Map<String, dynamic>? m) {
+    // TODO: implement doSomething
+  }
+}
+''');
+  }
+
+  Future<void> test_method_generic_nullable_Never() async {
+    // https://github.com/dart-lang/sdk/issues/43535
+    await resolveTestUnit('''
+class A {
+  void doSomething(Map<String, Never>? m) {}
+}
+
+class B implements A {}
+''');
+    await assertHasFix('''
+class A {
+  void doSomething(Map<String, Never>? m) {}
+}
+
+class B implements A {
+  @override
+  void doSomething(Map<String, Never>? m) {
+    // TODO: implement doSomething
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index a296cb0..e90178e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -4,8 +4,8 @@
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'data_driven_test_support.dart';
@@ -23,6 +23,9 @@
 
 @reflectiveTest
 class AddTypeParameterToClassTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'class';
+
   Future<void> test_constructorInvocation_removed() async {
     setPackageContent('''
 class C<S, T> {
@@ -134,6 +137,9 @@
 
 @reflectiveTest
 class AddTypeParameterToExtensionTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'extension';
+
   Future<void> test_override_removed() async {
     setPackageContent('''
 class C {}
@@ -161,6 +167,9 @@
 
 @reflectiveTest
 class AddTypeParameterToMethodTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'method';
+
   Future<void> test_first_deprecated() async {
     setPackageContent('''
 class C {
@@ -333,6 +342,9 @@
 
 @reflectiveTest
 class AddTypeParameterToMixinTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'mixin';
+
   Future<void> test_inWith_removed() async {
     setPackageContent('''
 mixin M<S, T> {}
@@ -353,6 +365,9 @@
 
 @reflectiveTest
 class AddTypeParameterToTopLevelFunctionTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'function';
+
   Future<void> test_only_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -378,6 +393,9 @@
 
 @reflectiveTest
 class AddTypeParameterToTypedefTest extends _AddTypeParameterChange {
+  @override
+  String get _kind => 'typedef';
+
   @failingTest
   Future<void> test_functionType_removed() async {
     // The test fails because the change is to the typedef `F`, not to the
@@ -455,16 +473,22 @@
 }
 
 abstract class _AddTypeParameterChange extends DataDrivenFixProcessorTest {
+  /// Return the kind of element whose parameters are being modified.
+  String get _kind;
+
   Transform _add(int index, {List<String> components, String extendedType}) =>
       Transform(
           title: 'title',
           element: ElementDescriptor(
-              libraryUris: [importUri], components: components ?? ['C', 'm']),
+              libraryUris: [Uri.parse(importUri)],
+              kind: ElementKindUtilities.fromName(_kind),
+              components: components ?? ['C', 'm']),
           changes: [
             AddTypeParameter(
-                extendedType: extendedType,
                 index: index,
                 name: 'T',
-                value: LiteralExtractor('String')),
+                extendedType:
+                    extendedType == null ? null : codeTemplate(extendedType),
+                argumentValue: codeTemplate('String')),
           ]);
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
new file mode 100644
index 0000000..4802e4a
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'data_driven_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(CodeTemplateTest);
+  });
+}
+
+@reflectiveTest
+class CodeTemplateTest extends DataDrivenFixProcessorTest {
+  Future<void> test_text_variable() async {
+    await _assertTemplateResult('a0', [
+      _text('a'),
+      _variable(0),
+    ]);
+  }
+
+  Future<void> test_text_variable_text() async {
+    await _assertTemplateResult('a0b', [
+      _text('a'),
+      _variable(0),
+      _text('b'),
+    ]);
+  }
+
+  Future<void> test_textOnly() async {
+    await _assertTemplateResult('a', [
+      _text('a'),
+    ]);
+  }
+
+  Future<void> test_variable_text() async {
+    await _assertTemplateResult('0a', [
+      _variable(0),
+      _text('a'),
+    ]);
+  }
+
+  Future<void> test_variable_text_variable() async {
+    await _assertTemplateResult('0a1', [
+      _variable(0),
+      _text('a'),
+      _variable(1),
+    ]);
+  }
+
+  Future<void> test_variableOnly() async {
+    await _assertTemplateResult('0', [
+      _variable(0),
+    ]);
+  }
+
+  Future<void> _assertTemplateResult(
+      String expectedResult, List<TemplateComponent> components) async {
+    await resolveTestUnit('''
+void f() {
+  g(0, 1);
+}
+void g(int x, int y) {}
+''');
+    var unit = testAnalysisResult.unit;
+    var function = unit.declarations[0] as FunctionDeclaration;
+    var body = function.functionExpression.body as BlockFunctionBody;
+    var statement = body.block.statements[0] as ExpressionStatement;
+    var node = statement.expression;
+    var template = CodeTemplate(CodeTemplateKind.expression, components);
+    var builder = ChangeBuilder(session: session);
+    var context = TemplateContext(node, CorrectionUtils(testAnalysisResult));
+    await builder.addDartFileEdit(testFile, (builder) {
+      builder.addInsertion(0, (builder) {
+        template.writeOn(builder, context);
+      });
+    });
+    var result = builder.sourceChange.edits[0].edits[0].replacement;
+    expect(result, expectedResult);
+  }
+
+  TemplateText _text(String text) => TemplateText(text);
+
+  TemplateVariable _variable(int index) =>
+      TemplateVariable(ArgumentExpression(PositionalParameterReference(index)));
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
index 4e48e50..fe452ec 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test_support.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
@@ -28,6 +29,11 @@
     addPackageFile('p', TransformSetManager.dataFileName, content);
   }
 
+  /// Return a code template that will produce the given [text].
+  CodeTemplate codeTemplate(String text) {
+    return CodeTemplate(CodeTemplateKind.expression, [TemplateText(text)]);
+  }
+
   /// A method that can be used as an error filter to ignore any unused_import
   /// diagnostics.
   bool ignoreUnusedImport(AnalysisError error) =>
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
new file mode 100644
index 0000000..2e606bb
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_one_of_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidValueOneOfTest);
+  });
+}
+
+@reflectiveTest
+class InvalidValueOneOfTest extends AbstractTransformSetParserTest {
+  void test_changeKind() {
+    assertErrors('''
+version: 1
+transforms:
+- title: 'Rename A'
+  date: 2020-09-08
+  element:
+    uris: ['test.dart']
+    class: 'A'
+  changes:
+    - kind: 'invalid'
+''', [
+      error(TransformSetErrorCode.invalidValueOneOf, 129, 16),
+    ]);
+  }
+
+  void test_valueKind() {
+    assertErrors('''
+version: 1
+transforms:
+- title: 'Rename A'
+  date: 2020-09-08
+  element:
+    uris: ['test.dart']
+    class: 'A'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 0
+      name: 'T'
+      argumentValue: 
+        expression: ''
+        variables:
+          x:
+            kind: 'invalid'
+''', [
+      error(TransformSetErrorCode.invalidValueOneOf, 274, 16),
+    ]);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_test.dart
index 2c7d94c..1bd6446 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/invalid_value_test.dart
@@ -20,14 +20,14 @@
 version: 1
 transforms:
 - title: 'Rename A'
+  date: 2020-09-08
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - 'rename'
 ''', [
-      error(TransformSetErrorCode.invalidValue, 123, 8),
+      error(TransformSetErrorCode.invalidValue, 129, 8),
     ]);
   }
 
@@ -36,12 +36,13 @@
 version: 1
 transforms:
 - title: 'Rename A'
+  date: 2020-09-08
   element: 5
   changes:
     - kind: 'rename'
       newName: 'B'
 ''', [
-      error(TransformSetErrorCode.invalidValue, 54, 1),
+      error(TransformSetErrorCode.invalidValue, 73, 1),
     ]);
   }
 
@@ -52,8 +53,7 @@
 - title: 'Rename A'
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       newName: 'B'
@@ -69,8 +69,7 @@
 - title: 'Rename A'
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       newName: 'B'
@@ -93,10 +92,10 @@
 version: 1
 transforms:
 - title: 0
+  date: 2020-09-08
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       newName: 'B'
@@ -110,10 +109,10 @@
 version: 1
 transforms:
 - title: []
+  date: 2020-09-08
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       newName: 'B'
@@ -145,17 +144,17 @@
 version: 1
 transforms:
 - title: 'Rename A'
+  date: 2020-09-08
   element:
     uris: ['test.dart']
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'addTypeParameter'
       index: 1
       name: 'T'
-      value: 'int'
+      argumentValue: 'int'
 ''', [
-      error(TransformSetErrorCode.invalidValue, 192, 5),
+      error(TransformSetErrorCode.invalidValue, 206, 5),
     ]);
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_key_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_key_test.dart
new file mode 100644
index 0000000..148f8a4
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_key_test.dart
@@ -0,0 +1,273 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MissingKeyTest);
+  });
+}
+
+@reflectiveTest
+class MissingKeyTest extends AbstractTransformSetParserTest {
+  void test_addParameterChange_argumentValue() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'a'
+      style: required_positional
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 85),
+    ]);
+  }
+
+  void test_addParameterChange_index() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      name: 'a'
+      style: required_positional
+      argumentValue:
+        kind: 'argument'
+        index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 133),
+    ]);
+  }
+
+  void test_addParameterChange_name() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      style: required_positional
+      argumentValue:
+        kind: 'argument'
+        index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 132),
+    ]);
+  }
+
+  void test_addParameterChange_style() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'a'
+      argumentValue:
+        kind: 'argument'
+        index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 115),
+    ]);
+  }
+
+  void test_addTypeParameterChange_argumentValue() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 0
+      name: 'a'
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 56),
+    ]);
+  }
+
+  void test_addTypeParameterChange_index() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addTypeParameter'
+      name: 'a'
+      argumentValue:
+        kind: 'argument'
+        index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 104),
+    ]);
+  }
+
+  void test_addTypeParameterChange_name() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 0
+      argumentValue:
+        kind: 'argument'
+        index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 103),
+    ]);
+  }
+
+  void test_change_kind() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - index: 0
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 9),
+    ]);
+  }
+
+  void test_element_uris() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    function: 'f'
+  changes: []
+''', [
+      error(TransformSetErrorCode.missingKey, 69, 16),
+    ]);
+  }
+
+  void test_renameChange_newName() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'rename'
+''', [
+      error(TransformSetErrorCode.missingKey, 124, 15),
+    ]);
+  }
+
+  void test_transform_changes() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+''', [
+      error(TransformSetErrorCode.missingKey, 25, 82),
+    ]);
+  }
+
+  void test_transform_date() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes: []
+''', [
+      error(TransformSetErrorCode.missingKey, 25, 77),
+    ]);
+  }
+
+  void test_transform_element() {
+    assertErrors('''
+version: 1
+transforms:
+- title: ''
+  date: 2020-09-14
+  changes: []
+''', [
+      error(TransformSetErrorCode.missingKey, 25, 43),
+    ]);
+  }
+
+  void test_transform_title() {
+    assertErrors('''
+version: 1
+transforms:
+- date: 2020-09-14
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes: []
+''', [
+      error(TransformSetErrorCode.missingKey, 25, 84),
+    ]);
+  }
+
+  void test_transformSet_transforms() {
+    assertErrors('''
+version: 1
+''', [
+      error(TransformSetErrorCode.missingKey, 0, 11),
+    ]);
+  }
+
+  void test_transformSet_version() {
+    assertErrors('''
+transforms: []
+''', [
+      error(TransformSetErrorCode.missingKey, 0, 15),
+    ]);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_template_end_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_template_end_test.dart
new file mode 100644
index 0000000..0301220
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/missing_template_end_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MissingTemplateEndTest);
+  });
+}
+
+@reflectiveTest
+class MissingTemplateEndTest extends AbstractTransformSetParserTest {
+  void test_missing() {
+    assertErrors('''
+version: 1
+transforms:
+- date: 2020-09-19
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  title: ''
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'a'
+      style: optional_positional
+      argumentValue:
+        expression: 'a{% x b'
+''', [
+      error(TransformSetErrorCode.missingTemplateEnd, 252, 2),
+    ]);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
index a570f51..e8bbf94 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/test_all.dart
@@ -4,13 +4,21 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'invalid_value_one_of_test.dart' as invalid_value_one_of;
 import 'invalid_value_test.dart' as invalid_value;
+import 'missing_key_test.dart' as missing_key;
+import 'missing_template_end_test.dart' as missing_template_end;
+import 'undefined_variable_test.dart' as undefined_variable;
 import 'unsupported_key_test.dart' as unsupported_key;
 import 'yaml_syntax_error_test.dart' as yaml_syntax_error;
 
 void main() {
   defineReflectiveSuite(() {
+    invalid_value_one_of.main();
     invalid_value.main();
+    missing_key.main();
+    missing_template_end.main();
+    undefined_variable.main();
     unsupported_key.main();
     yaml_syntax_error.main();
   });
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/undefined_variable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/undefined_variable_test.dart
new file mode 100644
index 0000000..19334c8
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/undefined_variable_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../transform_set_parser_test_support.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedVariableTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedVariableTest extends AbstractTransformSetParserTest {
+  void test_missingVariable() {
+    assertErrors('''
+version: 1
+transforms:
+- date: 2020-09-19
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  title: ''
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'a'
+      style: optional_positional
+      argumentValue:
+        expression: '{%xyz%}'
+        variables:
+          zyx:
+            kind: 'argument'
+            index: 0
+''', [
+      error(TransformSetErrorCode.undefinedVariable, 253, 3),
+    ]);
+  }
+
+  void test_noVariables() {
+    assertErrors('''
+version: 1
+transforms:
+- date: 2020-09-19
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  title: ''
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'a'
+      style: optional_positional
+      argumentValue:
+        expression: '{%xyz%}'
+''', [
+      error(TransformSetErrorCode.undefinedVariable, 253, 3),
+    ]);
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart
index 9358bee..64d724e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/diagnostics/unsupported_key_test.dart
@@ -20,17 +20,17 @@
 version: 1
 transforms:
 - title: 'Rename A'
+  date: 2020-08-21
   element:
     uris:
       - 'test.dart'
-    components:
-      - 'A'
+    class: 'A'
   changes:
     - kind: 'rename'
       oldName: 'A'
       newName: 'B'
 ''', [
-      error(TransformSetErrorCode.unsupportedKey, 150, 7),
+      error(TransformSetErrorCode.unsupportedKey, 156, 7),
     ]);
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
index b5ae21c..aad57fa 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/end_to_end_test.dart
@@ -24,6 +24,7 @@
 version: 1
 transforms:
 - title: 'Add parameter'
+  date: 2020-09-09
   element:
     uris: ['$importUri']
     method: 'm'
@@ -34,8 +35,11 @@
       name: 'y'
       style: required_positional
       argumentValue:
-        kind: 'argument'
-        index: 0
+        expression: '{% y %}'
+        variables:
+          y:
+            kind: 'argument'
+            index: 0
 ''');
     await resolveTestUnit('''
 import '$importUri';
@@ -63,6 +67,7 @@
 version: 1
 transforms:
 - title: 'Add type argument'
+  date: 2020-09-03
   element:
     uris:
       - '$importUri'
@@ -72,9 +77,12 @@
     - kind: 'addTypeParameter'
       index: 1
       name: 'T'
-      value:
-        kind: 'argument'
-        index: 0
+      argumentValue:
+        expression: '{% t %}'
+        variables:
+          t:
+            kind: 'argument'
+            index: 0
 ''');
     await resolveTestUnit('''
 import '$importUri';
@@ -102,6 +110,7 @@
 version: 1
 transforms:
 - title: 'Add argument'
+  date: 2020-09-09
   element:
     uris: ['$importUri']
     method: 'm'
@@ -134,6 +143,7 @@
 version: 1
 transforms:
 - title: 'Rename to New'
+  date: 2020-09-01
   element:
     uris:
       - '$importUri'
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
index 2287a48..dd56d2c 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
@@ -3,11 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/modify_parameters.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'data_driven_test_support.dart';
@@ -21,6 +21,9 @@
 
 @reflectiveTest
 class ModifyParametersOfMethodTest extends _ModifyParameters {
+  @override
+  String get _kind => 'method';
+
   Future<void> test_add_first_optionalNamed_deprecated() async {
     setPackageContent('''
 class C {
@@ -30,7 +33,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(0, 'a', false, false, null, null)],
+        ['C', 'm'], [AddParameter(0, 'a', false, false, null)],
         newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -56,12 +59,9 @@
   void m2([int a, int b]) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(0, 'a', false, true, null, LiteralExtractor('0'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(0, 'a', false, true, codeTemplate('0'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -86,12 +86,9 @@
   void m2({int a, int b}) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(0, 'a', true, false, null, LiteralExtractor('0'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(0, 'a', true, false, codeTemplate('0'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -116,12 +113,9 @@
   void m2(int a, int b) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -147,7 +141,7 @@
 }
 ''');
     setPackageData(_modify(
-        ['C', 'm'], [AddParameter(1, 'b', false, false, null, null)],
+        ['C', 'm'], [AddParameter(1, 'b', false, false, null)],
         newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -173,12 +167,9 @@
   void m2(int a, [int b]) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(1, 'b', false, true, null, LiteralExtractor('1'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(1, 'b', false, true, codeTemplate('1'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -203,12 +194,9 @@
   void m2(int a, {int b}) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(1, 'b', true, false, null, LiteralExtractor('1'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(1, 'b', true, false, codeTemplate('1'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -233,12 +221,9 @@
   void m2(int a, int b) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(1, 'b', true, true, null, LiteralExtractor('1'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(1, 'b', true, true, codeTemplate('1'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -267,9 +252,9 @@
       'C',
       'm'
     ], [
-      AddParameter(1, 'b', true, true, null, LiteralExtractor('1')),
-      AddParameter(2, 'c', true, true, null, LiteralExtractor('2')),
-      AddParameter(4, 'e', true, true, null, LiteralExtractor('4')),
+      AddParameter(1, 'b', true, true, codeTemplate('1')),
+      AddParameter(2, 'c', true, true, codeTemplate('2')),
+      AddParameter(4, 'e', true, true, codeTemplate('4')),
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -293,12 +278,9 @@
   void m2(int a, int b) {}
 }
 ''');
-    setPackageData(_modify([
-      'C',
-      'm'
-    ], [
-      AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))
-    ], newName: 'm2'));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))],
+        newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -321,8 +303,8 @@
   void m(int a, int b) {}
 }
 ''');
-    setPackageData(_modify(['C', 'm'],
-        [AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))]));
+    setPackageData(_modify(
+        ['C', 'm'], [AddParameter(0, 'a', true, true, codeTemplate('0'))]));
     await resolveTestUnit('''
 import '$importUri';
 
@@ -352,7 +334,7 @@
       'm'
     ], [
       RemoveParameter(PositionalParameterReference(0)),
-      AddParameter(2, 'c', true, true, null, LiteralExtractor('2'))
+      AddParameter(2, 'c', true, true, codeTemplate('2'))
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -383,7 +365,7 @@
       'm'
     ], [
       RemoveParameter(PositionalParameterReference(1)),
-      AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))
+      AddParameter(0, 'a', true, true, codeTemplate('0'))
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -415,7 +397,7 @@
     ], [
       RemoveParameter(PositionalParameterReference(0)),
       RemoveParameter(PositionalParameterReference(1)),
-      AddParameter(0, 'c', true, true, null, LiteralExtractor('2')),
+      AddParameter(0, 'c', true, true, codeTemplate('2')),
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -447,7 +429,7 @@
     ], [
       RemoveParameter(PositionalParameterReference(1)),
       RemoveParameter(PositionalParameterReference(2)),
-      AddParameter(1, 'd', true, true, null, LiteralExtractor('3')),
+      AddParameter(1, 'd', true, true, codeTemplate('3')),
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -477,10 +459,10 @@
       'C',
       'm1'
     ], [
-      AddParameter(0, 'a', true, true, null, LiteralExtractor('0')),
+      AddParameter(0, 'a', true, true, codeTemplate('0')),
       RemoveParameter(PositionalParameterReference(1)),
       RemoveParameter(PositionalParameterReference(3)),
-      AddParameter(2, 'd', true, true, null, LiteralExtractor('3')),
+      AddParameter(2, 'd', true, true, codeTemplate('3')),
     ], newName: 'm2'));
     await resolveTestUnit('''
 import '$importUri';
@@ -839,6 +821,9 @@
 /// applied to top-level functions, but are not intended to be exhaustive.
 @reflectiveTest
 class ModifyParametersOfTopLevelFunctionTest extends _ModifyParameters {
+  @override
+  String get _kind => 'function';
+
   Future<void> test_add_first_requiredNamed_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -848,7 +833,7 @@
     setPackageData(_modify([
       'f'
     ], [
-      AddParameter(0, 'a', true, true, null, LiteralExtractor('0')),
+      AddParameter(0, 'a', true, true, codeTemplate('0')),
     ], newName: 'g'));
     await resolveTestUnit('''
 import '$importUri';
@@ -893,12 +878,17 @@
 }
 
 abstract class _ModifyParameters extends DataDrivenFixProcessorTest {
+  /// Return the kind of element whose parameters are being modified.
+  String get _kind;
+
   Transform _modify(List<String> originalComponents,
           List<ParameterModification> modifications, {String newName}) =>
       Transform(
           title: 'title',
           element: ElementDescriptor(
-              libraryUris: [importUri], components: originalComponents),
+              libraryUris: [Uri.parse(importUri)],
+              kind: ElementKindUtilities.fromName(_kind),
+              components: originalComponents),
           changes: [
             ModifyParameters(modifications: modifications),
             if (newName != null) Rename(newName: newName),
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 74bda48..39fd964 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -15,6 +16,7 @@
     defineReflectiveTests(RenameConstructorTest);
     defineReflectiveTests(RenameExtensionTest);
     defineReflectiveTests(RenameFieldTest);
+    defineReflectiveTests(RenameGetterTest);
     defineReflectiveTests(RenameMethodTest);
     defineReflectiveTests(RenameMixinTest);
     defineReflectiveTests(RenameTopLevelFunctionTest);
@@ -24,6 +26,109 @@
 
 @reflectiveTest
 class RenameClassTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'class';
+
+  Future<void> test_constructor_named_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {
+  Old.c();
+}
+class New {
+  New.c();
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  Old.c();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  New.c();
+}
+''');
+  }
+
+  Future<void> test_constructor_named_removed() async {
+    setPackageContent('''
+class New {
+  New.c();
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  Old.c();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  New.c();
+}
+''', errorFilter: ignoreUnusedImport);
+  }
+
+  Future<void> test_constructor_unnamed_deprecated() async {
+    setPackageContent('''
+@deprecated
+class Old {
+  Old();
+}
+class New {
+  New();
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  Old();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  New();
+}
+''');
+  }
+
+  Future<void> test_constructor_unnamed_removed() async {
+    setPackageContent('''
+class New {
+  New();
+}
+''');
+    setPackageData(_rename(['Old'], 'New'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  Old();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  New();
+}
+''', errorFilter: ignoreUnusedImport);
+  }
+
   Future<void> test_inExtends_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -249,7 +354,10 @@
 
 @reflectiveTest
 class RenameConstructorTest extends _AbstractRenameTest {
-  Future<void> test_named_deprecated() async {
+  @override
+  String get _kind => 'constructor';
+
+  Future<void> test_named_named_deprecated() async {
     setPackageContent('''
 class C {
   @deprecated
@@ -274,7 +382,7 @@
 ''');
   }
 
-  Future<void> test_named_removed() async {
+  Future<void> test_named_named_removed() async {
     setPackageContent('''
 class C {
   C.new();
@@ -297,59 +405,108 @@
 ''');
   }
 
-  Future<void> test_unnamed_deprecated() async {
+  Future<void> test_named_unnamed_deprecated() async {
     setPackageContent('''
-@deprecated
-class Old {
-  Old();
-}
-class New {
-  New();
+class C {
+  @deprecated
+  C.old();
+  C();
 }
 ''');
-    setPackageData(_rename(['Old'], 'New'));
+    setPackageData(_rename(['C', 'old'], ''));
     await resolveTestUnit('''
 import '$importUri';
 
 void f() {
-  Old();
+  C.old();
 }
 ''');
     await assertHasFix('''
 import '$importUri';
 
 void f() {
-  New();
+  C();
 }
 ''');
   }
 
-  Future<void> test_unnamed_removed() async {
+  Future<void> test_named_unnamed_removed() async {
     setPackageContent('''
-class New {
-  New();
+class C {
+  C();
 }
 ''');
-    setPackageData(_rename(['Old'], 'New'));
+    setPackageData(_rename(['C', 'old'], ''));
     await resolveTestUnit('''
 import '$importUri';
 
 void f() {
-  Old();
+  C.old();
 }
 ''');
     await assertHasFix('''
 import '$importUri';
 
 void f() {
-  New();
+  C();
 }
-''', errorFilter: ignoreUnusedImport);
+''');
+  }
+
+  Future<void> test_unnamed_named_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  C();
+  C.new();
+}
+''');
+    setPackageData(_rename(['C', ''], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  C();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  C.new();
+}
+''');
+  }
+
+  Future<void> test_unnamed_named_removed() async {
+    setPackageContent('''
+class C {
+  C.new();
+}
+''');
+    setPackageData(_rename(['C', ''], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  C();
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  C.new();
+}
+''');
   }
 }
 
 @reflectiveTest
 class RenameExtensionTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'extension';
+
   Future<void> test_override_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -437,6 +594,9 @@
 
 @reflectiveTest
 class RenameFieldTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'field';
+
   Future<void> test_instance_reference_deprecated() async {
     setPackageContent('''
 class C {
@@ -583,7 +743,151 @@
 }
 
 @reflectiveTest
+class RenameGetterTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'getter';
+
+  Future<void> test_instance_nonReference_method_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  int get a => 0;
+  int get b => 1;
+}
+class D {
+  @deprecated
+  void a(int b) {}
+}
+''');
+    setPackageData(_rename(['C', 'a'], 'b'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f(D d) {
+  d.a(2);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_instance_nonReference_parameter_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  int get a => 0;
+  int get b => 1;
+}
+class D {
+  D({@deprecated int a; int c});
+}
+''');
+    setPackageData(_rename(['C', 'a'], 'b'));
+    await resolveTestUnit('''
+import '$importUri';
+
+D d = D(a: 2);
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_instance_reference_deprecated() async {
+    setPackageContent('''
+class C {
+  @deprecated
+  int get old => 0;
+  int get new => 1;
+}
+''');
+    setPackageData(_rename(['C', 'old'], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+  c.old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+  c.new;
+}
+''');
+  }
+
+  Future<void> test_instance_reference_removed() async {
+    setPackageContent('''
+class C {
+  int get new => 1;
+}
+''');
+    setPackageData(_rename(['C', 'old'], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+  c.old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+  c.new;
+}
+''');
+  }
+
+  Future<void> test_topLevel_reference_deprecated() async {
+    setPackageContent('''
+@deprecated
+int get old => 0;
+int get new => 1;
+''');
+    setPackageData(_rename(['old'], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  new;
+}
+''');
+  }
+
+  Future<void> test_topLevel_reference_removed() async {
+    setPackageContent('''
+int get new => 1;
+''');
+    setPackageData(_rename(['old'], 'new'));
+    await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+  old;
+}
+''');
+    await assertHasFix('''
+import '$importUri';
+
+void f() {
+  new;
+}
+''', errorFilter: ignoreUnusedImport);
+  }
+}
+
+@reflectiveTest
 class RenameMethodTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'method';
+
   @failingTest
   Future<void> test_instance_override_deprecated() async {
     setPackageContent('''
@@ -736,6 +1040,9 @@
 
 @reflectiveTest
 class RenameMixinTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'mixin';
+
   Future<void> test_inWith_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -775,6 +1082,9 @@
 
 @reflectiveTest
 class RenameTopLevelFunctionTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'function';
+
   Future<void> test_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -822,6 +1132,9 @@
 
 @reflectiveTest
 class RenameTypedefTest extends _AbstractRenameTest {
+  @override
+  String get _kind => 'typedef';
+
   Future<void> test_deprecated() async {
     setPackageContent('''
 @deprecated
@@ -859,11 +1172,16 @@
   }
 }
 
-class _AbstractRenameTest extends DataDrivenFixProcessorTest {
+abstract class _AbstractRenameTest extends DataDrivenFixProcessorTest {
+  /// Return the kind of element being renamed.
+  String get _kind;
+
   Transform _rename(List<String> components, String newName) => Transform(
           title: 'title',
           element: ElementDescriptor(
-              libraryUris: [importUri], components: components),
+              libraryUris: [Uri.parse(importUri)],
+              kind: ElementKindUtilities.fromName(_kind),
+              components: components),
           changes: [
             Rename(newName: newName),
           ]);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
index 6b9b51a..bd85ebe 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/test_all.dart
@@ -5,6 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'add_type_parameter_test.dart' as add_type_parameter_change;
+import 'code_template_test.dart' as code_template;
 import 'diagnostics/test_all.dart' as diagnostics;
 import 'end_to_end_test.dart' as end_to_end;
 import 'modify_parameters_test.dart' as modify_parameters;
@@ -15,6 +16,7 @@
 void main() {
   defineReflectiveSuite(() {
     add_type_parameter_change.main();
+    code_template.main();
     diagnostics.main();
     end_to_end.main();
     modify_parameters.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
index e5e8e1f..a1341eb 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test.dart
@@ -3,11 +3,14 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix/data_driven/add_type_parameter.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/code_template.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/element_matcher.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/modify_parameters.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/rename.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/transform.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_error_code.dart';
-import 'package:analysis_server/src/services/correction/fix/data_driven/value_extractor.dart';
+import 'package:analysis_server/src/services/correction/fix/data_driven/value_generator.dart';
 import 'package:matcher/matcher.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -22,11 +25,14 @@
 
 @reflectiveTest
 class TransformSetParserTest extends AbstractTransformSetParserTest {
+  List<Uri> get uris => [Uri.parse('package:myPackage/test.dart')];
+
   void test_addParameter_optionalNamed() {
     parse('''
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -36,10 +42,13 @@
       name: 'p'
       style: optional_named
       argumentValue:
-        kind: 'argument'
-        index: 1
+        expression: '{% p %}'
+        variables:
+          p:
+            kind: 'argument'
+            index: 1
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -52,7 +61,10 @@
     expect(modification.name, 'p');
     expect(modification.isRequired, false);
     expect(modification.isPositional, false);
-    var value = modification.argumentValue as ArgumentExtractor;
+    var components = modification.argumentValue.components;
+    expect(components, hasLength(1));
+    var value =
+        (components[0] as TemplateVariable).generator as ArgumentExpression;
     var parameter = value.parameter as PositionalParameterReference;
     expect(parameter.index, 1);
   }
@@ -62,6 +74,7 @@
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -70,11 +83,8 @@
       index: 0
       name: 'p'
       style: optional_positional
-      defaultValue:
-        kind: 'argument'
-        index: 1
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -87,9 +97,6 @@
     expect(modification.name, 'p');
     expect(modification.isRequired, false);
     expect(modification.isPositional, true);
-    var value = modification.defaultValue as ArgumentExtractor;
-    var parameter = value.parameter as PositionalParameterReference;
-    expect(parameter.index, 1);
   }
 
   void test_addParameter_requiredNamed() {
@@ -97,6 +104,7 @@
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -106,10 +114,13 @@
       name: 'p'
       style: required_named
       argumentValue:
-        kind: 'argument'
-        index: 1
+        expression: '{% p %}'
+        variables:
+          p:
+            kind: 'argument'
+            index: 1
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -122,7 +133,10 @@
     expect(modification.name, 'p');
     expect(modification.isRequired, true);
     expect(modification.isPositional, false);
-    var value = modification.argumentValue as ArgumentExtractor;
+    var components = modification.argumentValue.components;
+    expect(components, hasLength(1));
+    var value =
+        (components[0] as TemplateVariable).generator as ArgumentExpression;
     var parameter = value.parameter as PositionalParameterReference;
     expect(parameter.index, 1);
   }
@@ -132,6 +146,7 @@
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -141,10 +156,13 @@
       name: 'p'
       style: required_positional
       argumentValue:
-        kind: 'argument'
-        index: 1
+        expression: '{% p %}'
+        variables:
+          p:
+            kind: 'argument'
+            index: 1
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -157,16 +175,108 @@
     expect(modification.name, 'p');
     expect(modification.isRequired, true);
     expect(modification.isPositional, true);
-    var value = modification.argumentValue as ArgumentExtractor;
+    var components = modification.argumentValue.components;
+    expect(components, hasLength(1));
+    var value =
+        (components[0] as TemplateVariable).generator as ArgumentExpression;
     var parameter = value.parameter as PositionalParameterReference;
     expect(parameter.index, 1);
   }
 
+  void test_addParameter_requiredPositional_complexTemplate() {
+    parse('''
+version: 1
+transforms:
+- title: 'Add'
+  date: 2020-09-09
+  element:
+    uris: ['test.dart']
+    function: 'f'
+  changes:
+    - kind: 'addParameter'
+      index: 0
+      name: 'p'
+      style: required_positional
+      argumentValue:
+        expression: '{% a %}({% b %})'
+        variables:
+          a:
+            kind: 'argument'
+            index: 1
+          b:
+            kind: 'argument'
+            index: 2
+''');
+    var transforms = _transforms('f');
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Add');
+    expect(transform.changes, hasLength(1));
+    var change = transform.changes[0] as ModifyParameters;
+    var modifications = change.modifications;
+    expect(modifications, hasLength(1));
+    var modification = modifications[0] as AddParameter;
+    expect(modification.index, 0);
+    expect(modification.name, 'p');
+    expect(modification.isRequired, true);
+    expect(modification.isPositional, true);
+    var components = modification.argumentValue.components;
+    expect(components, hasLength(4));
+    var extractorA =
+        (components[0] as TemplateVariable).generator as ArgumentExpression;
+    var parameterA = extractorA.parameter as PositionalParameterReference;
+    expect(parameterA.index, 1);
+    expect((components[1] as TemplateText).text, '(');
+    var extractorB =
+        (components[2] as TemplateVariable).generator as ArgumentExpression;
+    var parameterB = extractorB.parameter as PositionalParameterReference;
+    expect(parameterB.index, 2);
+    expect((components[3] as TemplateText).text, ')');
+  }
+
+  void test_addTypeParameter_fromImportedName() {
+    parse('''
+version: 1
+transforms:
+- date: 2020-09-03
+  element:
+    uris:
+      - 'test.dart'
+    class: 'A'
+  title: 'Add'
+  changes:
+    - kind: 'addTypeParameter'
+      index: 0
+      name: 'T'
+      argumentValue:
+        expression: '{% t %}'
+        variables:
+          t:
+            kind: 'import'
+            uris: ['dart:core']
+            name: 'String'
+''');
+    var transforms = _transforms('A');
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Add');
+    expect(transform.changes, hasLength(1));
+    var change = transform.changes[0] as AddTypeParameter;
+    expect(change.index, 0);
+    expect(change.name, 'T');
+    var components = change.argumentValue.components;
+    expect(components, hasLength(1));
+    var value = (components[0] as TemplateVariable).generator as ImportedName;
+    expect(value.uris, [Uri.parse('dart:core')]);
+    expect(value.name, 'String');
+  }
+
   void test_addTypeParameter_fromNamedArgument() {
     parse('''
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-03
   element:
     uris:
       - 'test.dart'
@@ -175,11 +285,14 @@
     - kind: 'addTypeParameter'
       index: 0
       name: 'T'
-      value:
-        kind: 'argument'
-        name: 'p'
+      argumentValue:
+        expression: '{% t %}'
+        variables:
+          t:
+            kind: 'argument'
+            name: 'p'
 ''');
-    var transforms = result.transformsFor('A', ['test.dart']);
+    var transforms = _transforms('A');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -187,7 +300,12 @@
     var change = transform.changes[0] as AddTypeParameter;
     expect(change.index, 0);
     expect(change.name, 'T');
-    var value = change.value as ArgumentExtractor;
+    expect(change.extendedType, null);
+
+    var components = change.argumentValue.components;
+    expect(components, hasLength(1));
+    var value =
+        (components[0] as TemplateVariable).generator as ArgumentExpression;
     var parameter = value.parameter as NamedParameterReference;
     expect(parameter.name, 'p');
   }
@@ -197,6 +315,7 @@
 version: 1
 transforms:
 - title: 'Add'
+  date: 2020-09-03
   element:
     uris:
       - 'test.dart'
@@ -205,11 +324,16 @@
     - kind: 'addTypeParameter'
       index: 0
       name: 'T'
-      value:
-        kind: 'argument'
-        index: 2
+      extends:
+        expression: 'Object'
+      argumentValue:
+        expression: '{% t %}'
+        variables:
+          t:
+            kind: 'argument'
+            index: 2
 ''');
-    var transforms = result.transformsFor('A', ['test.dart']);
+    var transforms = _transforms('A');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Add');
@@ -217,23 +341,50 @@
     var change = transform.changes[0] as AddTypeParameter;
     expect(change.index, 0);
     expect(change.name, 'T');
-    var value = change.value as ArgumentExtractor;
+
+    var extendsComponents = change.extendedType.components;
+    expect(extendsComponents, hasLength(1));
+    expect((extendsComponents[0] as TemplateText).text, 'Object');
+
+    var argumentComponents = change.argumentValue.components;
+    expect(argumentComponents, hasLength(1));
+    var value = (argumentComponents[0] as TemplateVariable).generator
+        as ArgumentExpression;
     var parameter = value.parameter as PositionalParameterReference;
     expect(parameter.index, 2);
   }
 
+  void test_date() {
+    parse('''
+version: 1
+transforms:
+- title: 'Rename g'
+  date: 2020-09-10
+  element:
+    uris: ['test.dart']
+    getter: 'g'
+  changes: []
+''');
+    var transforms = _transforms('g');
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Rename g');
+    expect(transform.changes, isEmpty);
+  }
+
   void test_element_getter_inMixin() {
     parse('''
 version: 1
 transforms:
 - title: 'Rename g'
+  date: 2020-09-02
   element:
     uris: ['test.dart']
     getter: 'g'
     inMixin: 'A'
   changes: []
 ''');
-    var transforms = result.transformsFor('g', ['test.dart']);
+    var transforms = _transforms('g');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Rename g');
@@ -245,12 +396,13 @@
 version: 1
 transforms:
 - title: 'Rename g'
+  date: 2020-09-02
   element:
     uris: ['test.dart']
     getter: 'g'
   changes: []
 ''');
-    var transforms = result.transformsFor('g', ['test.dart']);
+    var transforms = _transforms('g');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Rename g');
@@ -262,19 +414,38 @@
 version: 1
 transforms:
 - title: 'Rename m'
+  date: 2020-09-02
   element:
     uris: ['test.dart']
     method: 'm'
     inClass: 'A'
   changes: []
 ''');
-    var transforms = result.transformsFor('m', ['test.dart']);
+    var transforms = _transforms('m');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Rename m');
     expect(transform.changes, isEmpty);
   }
 
+  void test_element_variable() {
+    parse('''
+version: 1
+transforms:
+- title: 'Rename v'
+  date: 2020-10-01
+  element:
+    uris: ['test.dart']
+    variable: 'v'
+  changes: []
+''');
+    var transforms = _transforms('v');
+    expect(transforms, hasLength(1));
+    var transform = transforms[0];
+    expect(transform.title, 'Rename v');
+    expect(transform.changes, isEmpty);
+  }
+
   void test_incomplete() {
     parse('''
 version: 1
@@ -301,6 +472,7 @@
 version: 1
 transforms:
 - title: 'Remove'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -308,7 +480,7 @@
     - kind: 'removeParameter'
       name: 'p'
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Remove');
@@ -326,6 +498,7 @@
 version: 1
 transforms:
 - title: 'Remove'
+  date: 2020-09-09
   element:
     uris: ['test.dart']
     function: 'f'
@@ -333,7 +506,7 @@
     - kind: 'removeParameter'
       index: 0
 ''');
-    var transforms = result.transformsFor('f', ['test.dart']);
+    var transforms = _transforms('f');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Remove');
@@ -351,6 +524,7 @@
 version: 1
 transforms:
 - title: 'Rename A'
+  date: 2020-08-21
   element:
     uris:
       - 'test.dart'
@@ -359,7 +533,7 @@
     - kind: 'rename'
       newName: 'B'
 ''');
-    var transforms = result.transformsFor('A', ['test.dart']);
+    var transforms = _transforms('A');
     expect(transforms, hasLength(1));
     var transform = transforms[0];
     expect(transform.title, 'Rename A');
@@ -367,4 +541,10 @@
     var rename = transform.changes[0] as Rename;
     expect(rename.newName, 'B');
   }
+
+  ElementMatcher _matcher(String name) =>
+      ElementMatcher(importedUris: uris, name: name);
+
+  List<Transform> _transforms(String name) =>
+      result.transformsFor(_matcher(name));
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
index 1fa4200..789ef46 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
@@ -37,7 +37,7 @@
   void parse(String content) {
     errorListener = GatheringErrorListener();
     var errorReporter = ErrorReporter(errorListener, MockSource('data.yaml'));
-    var parser = TransformSetParser(errorReporter);
+    var parser = TransformSetParser(errorReporter, 'myPackage');
     result = parser.parse(content);
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index f5d7d59..ca983e6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/services/available_declarations.dart';
+import 'package:analyzer/src/test_utilities/platform.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide AnalysisError;
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -86,6 +87,9 @@
       String target,
       int expectedNumberOfFixesForKind,
       String matchFixMessage}) async {
+    if (useLineEndingsForPlatform) {
+      expected = normalizeNewlinesForPlatform(expected);
+    }
     var error = await _findErrorToFix(errorFilter, length: length);
     var fix = await _assertHasFix(error,
         expectedNumberOfFixesForKind: expectedNumberOfFixesForKind,
@@ -106,8 +110,11 @@
     expect(resultCode, expected);
   }
 
-  void assertHasFixAllFix(ErrorCode errorCode, String expected,
+  Future<void> assertHasFixAllFix(ErrorCode errorCode, String expected,
       {String target}) async {
+    if (useLineEndingsForPlatform) {
+      expected = normalizeNewlinesForPlatform(expected);
+    }
     var error = await _findErrorToFixOfType(errorCode);
     var fix = await _assertHasFixAllFix(error);
     change = fix.change;
@@ -169,6 +176,7 @@
   void setUp() {
     super.setUp();
     verifyNoTestUnitErrors = false;
+    useLineEndingsForPlatform = true;
     _createAnalysisOptionsFile();
   }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
new file mode 100644
index 0000000..133daf5
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/make_variable_nullable_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MakeVariableNullableTest);
+  });
+}
+
+@reflectiveTest
+class MakeVariableNullableTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.MAKE_VARIABLE_NULLABLE;
+
+  Future<void> test_lhsNotIdentifier() async {
+    await resolveTestUnit('''
+void f(C c) {
+  c.s = null;
+}
+class C {
+  String s = '';
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_lhsNotLocalVariable() async {
+    await resolveTestUnit('''
+var s = '';
+void f() {
+  s = null;
+  print(s);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_multipleVariables() async {
+    await resolveTestUnit('''
+void f() {
+  var s = '', t = '';
+  s = null;
+  print(s);
+  print(t);
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_noKeywordOrType() async {
+    await resolveTestUnit('''
+void f() {
+  late s = '';
+  s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  late String? s = '';
+  s = null;
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_type() async {
+    await resolveTestUnit('''
+void f() {
+  String s = '';
+  s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  String? s = '';
+  s = null;
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_var() async {
+    await resolveTestUnit('''
+void f() {
+  var s = '';
+  s = null;
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f() {
+  String? s = '';
+  s = null;
+  print(s);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
new file mode 100644
index 0000000..67590ce
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_comparison_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveComparisonTest);
+  });
+}
+
+@reflectiveTest
+class RemoveComparisonTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.REMOVE_COMPARISON;
+
+  Future<void> test_assertInitializer_first() async {
+    await resolveTestUnit('''
+class C {
+  String t;
+  C(String s) : assert(s != null), t = s;
+}
+''');
+    await assertHasFix('''
+class C {
+  String t;
+  C(String s) : t = s;
+}
+''');
+  }
+
+  Future<void> test_assertInitializer_last() async {
+    await resolveTestUnit('''
+class C {
+  String t;
+  C(String s) : t = s, assert(s != null);
+}
+''');
+    await assertHasFix('''
+class C {
+  String t;
+  C(String s) : t = s;
+}
+''');
+  }
+
+  Future<void> test_assertInitializer_middle() async {
+    await resolveTestUnit('''
+class C {
+  String t;
+  String u;
+  C(String s) : t = s, assert(s != null), u = s;
+}
+''');
+    await assertHasFix('''
+class C {
+  String t;
+  String u;
+  C(String s) : t = s, u = s;
+}
+''');
+  }
+
+  Future<void> test_assertInitializer_only() async {
+    await resolveTestUnit('''
+class C {
+  C(String s) : assert(s != null);
+}
+''');
+    await assertHasFix('''
+class C {
+  C(String s);
+}
+''');
+  }
+
+  Future<void> test_assertStatement() async {
+    await resolveTestUnit('''
+void f(String s) {
+  assert(s != null);
+  print(s);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s);
+}
+''');
+  }
+
+  Future<void> test_binaryExpression_and_left() async {
+    await resolveTestUnit('''
+void f(String s) {
+  print(s != null && s.isNotEmpty);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s.isNotEmpty);
+}
+''');
+  }
+
+  Future<void> test_binaryExpression_and_right() async {
+    await resolveTestUnit('''
+void f(String s) {
+  print(s.isNotEmpty && s != null);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s.isNotEmpty);
+}
+''');
+  }
+
+  Future<void> test_binaryExpression_or_left() async {
+    await resolveTestUnit('''
+void f(String s) {
+  print(s == null || s.isEmpty);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s.isEmpty);
+}
+''');
+  }
+
+  Future<void> test_binaryExpression_or_right() async {
+    await resolveTestUnit('''
+void f(String s) {
+  print(s.isEmpty || s == null);
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s.isEmpty);
+}
+''');
+  }
+
+  Future<void> test_ifStatement() async {
+    await resolveTestUnit('''
+void f(String s) {
+  if (s != null) {
+    print(s);
+  }
+}
+''');
+    await assertHasFix('''
+void f(String s) {
+  print(s);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart
index 6d4e023..93bea41 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_dead_code_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -11,6 +12,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(RemoveDeadCodeTest);
+    defineReflectiveTests(RemoveDeadCodeWithNullSafetyTest);
   });
 }
 
@@ -136,3 +138,48 @@
 ''');
   }
 }
+
+@reflectiveTest
+class RemoveDeadCodeWithNullSafetyTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.REMOVE_DEAD_CODE;
+
+  @failingTest
+  Future<void> test_do_returnInBody() async {
+    // https://github.com/dart-lang/sdk/issues/43511
+    await resolveTestUnit('''
+void f(bool c) {
+  do {
+    print(c);
+    return;
+  } while (c);
+}
+''');
+    await assertHasFix('''
+void f(bool c) {
+  print(c);
+}
+''');
+  }
+
+  @failingTest
+  Future<void> test_for_returnInBody() async {
+    // https://github.com/dart-lang/sdk/issues/43511
+    await resolveTestUnit('''
+void f() {
+  for (int i = 0; i < 2; i++) {
+    print(i);
+    return;
+  }
+}
+''');
+    await assertHasFix('''
+void f() {
+  print(0);
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
index 28948d0..32b927a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_if_null_operator_test.dart
@@ -5,7 +5,6 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
-import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -32,10 +31,7 @@
 ''');
     await assertHasFix('''
 int f(int a, int b) => a;
-''', errorFilter: (e) {
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      return e.errorCode != HintCode.DEAD_CODE;
-    });
+''');
   }
 
   Future<void> test_nestedChild() async {
@@ -44,10 +40,7 @@
 ''');
     await assertHasFix('''
 int f(int a, int b) => a;
-''', errorFilter: (e) {
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      return e.errorCode != HintCode.DEAD_CODE;
-    });
+''');
   }
 }
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart
index f3f154c..f54560f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_import_test.dart
@@ -20,6 +20,13 @@
   @override
   FixKind get kind => DartFixKind.REMOVE_UNUSED_IMPORT;
 
+  @override
+  void setUp() {
+    super.setUp();
+    // TODO(dantup): Get these tests passing with either line ending.
+    useLineEndingsForPlatform = false;
+  }
+
   Future<void> test_all_diverseImports() async {
     await resolveTestUnit('''
 import 'dart:math';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
index 3d8e7ef..f35360f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
@@ -63,7 +63,7 @@
 class C {
   C(int b = 1,);
 }
-''', errorFilter: (e) => e.offset == 14);
+''', errorFilter: (e) => e.offset == testCode.indexOf('int a'));
   }
 
   Future<void> test_first_requiredPositional_second_optionalNamed() async {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 64dde02..d795e61 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -94,12 +94,14 @@
 import 'make_final_test.dart' as make_final;
 import 'make_return_type_nullable_test.dart' as make_return_type_nullable;
 import 'make_variable_not_final_test.dart' as make_variable_not_final;
+import 'make_variable_nullable_test.dart' as make_variable_nullable;
 import 'move_type_arguments_to_class_test.dart' as move_type_arguments_to_class;
 import 'organize_imports_test.dart' as organize_imports;
 import 'qualify_reference_test.dart' as qualify_reference;
 import 'remove_annotation_test.dart' as remove_annotation;
 import 'remove_argument_test.dart' as remove_argument;
 import 'remove_await_test.dart' as remove_await;
+import 'remove_comparison_test.dart' as remove_comparison;
 import 'remove_const_test.dart' as remove_const;
 import 'remove_dead_code_test.dart' as remove_dead_code;
 import 'remove_duplicate_case_test.dart' as remove_duplicate_case;
@@ -249,12 +251,14 @@
     make_final.main();
     make_return_type_nullable.main();
     make_variable_not_final.main();
+    make_variable_nullable.main();
     move_type_arguments_to_class.main();
     organize_imports.main();
     qualify_reference.main();
     remove_annotation.main();
     remove_argument.main();
     remove_await.main();
+    remove_comparison.main();
     remove_const.main();
     remove_dead_code.main();
     remove_duplicate_case.main();
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 64c5ea0..cc487bb 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -512,7 +512,7 @@
   /// Return a list of operations to be sent to the server.
   List<ServerOperation> getOperations() {
     var operations = <ServerOperation>[];
-    void addUpdateContent(var overlay) {
+    void addUpdateContent(Object overlay) {
       operations.add(Analysis_UpdateContent(filePath, overlay));
     }
 
@@ -522,7 +522,7 @@
     addUpdateContent(AddContentOverlay(content));
     for (var editList in editLists.reversed) {
       for (var edit in editList.reversed) {
-        var overlay;
+        Object overlay;
         if (overlayStyle == OverlayStyle.change) {
           overlay = ChangeContentOverlay([edit]);
         } else if (overlayStyle == OverlayStyle.multipleAdd) {
diff --git a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
index da31eff..1334077 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/json_test.dart
@@ -142,6 +142,50 @@
       expect(canParse, isTrue);
     });
 
+    test('canParse allows matching literal strings', () {
+      // The CreateFile type is defined with `{ kind: 'create' }` so the only
+      // allowed value for `kind` is "create".
+      final canParse = CreateFile.canParse({
+        'kind': 'create',
+        'uri': 'file:///temp/foo',
+      }, nullLspJsonReporter);
+      expect(canParse, isTrue);
+    });
+
+    test('canParse disallows non-matching literal strings', () {
+      // The CreateFile type is defined with `{ kind: 'create' }` so the only
+      // allowed value for `kind` is "create".
+      final canParse = CreateFile.canParse({
+        'kind': 'not-create',
+        'uri': 'file:///temp/foo',
+      }, nullLspJsonReporter);
+      expect(canParse, isFalse);
+    });
+
+    test('canParse handles unions of literals', () {
+      // Key = value to test
+      // Value whether expected to parse
+      const testTraceValues = {
+        'off': true,
+        'messages': true,
+        'verbose': true,
+        null: true,
+        'invalid': false,
+      };
+      for (final testValue in testTraceValues.keys) {
+        final expected = testTraceValues[testValue];
+        final canParse = InitializeParams.canParse({
+          'processId': null,
+          'rootUri': null,
+          'capabilities': <String, Object>{},
+          'trace': testValue,
+        }, nullLspJsonReporter);
+        expect(canParse, expected,
+            reason: 'InitializeParams.canParse returned $canParse with a '
+                '"trace" value of "$testValue" but expected $expected');
+      }
+    });
+
     test('canParse validates optional fields', () {
       expect(
         RenameFileOptions.canParse(<String, Object>{}, nullLspJsonReporter),
@@ -336,7 +380,7 @@
           InitializeParamsClientInfo(name: 'server name', version: '1.2.3'),
       rootPath: '!root',
       capabilities: ClientCapabilities(),
-      trace: '!trace',
+      trace: 'off',
       workspaceFolders: [
         WorkspaceFolder(uri: '!uri1', name: '!name1'),
         WorkspaceFolder(uri: '!uri2', name: '!name2'),
diff --git a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
index 9744f04..e5ed507 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/matchers.dart
@@ -9,6 +9,9 @@
 
 Matcher isArrayOf(Matcher matcher) => ArrayTypeMatcher(wrapMatcher(matcher));
 
+Matcher isLiteralOf(Matcher typeMatcher, Object value) =>
+    LiteralTypeMatcher(typeMatcher, value);
+
 Matcher isMapOf(Matcher indexMatcher, Matcher valueMatcher) =>
     MapTypeMatcher(wrapMatcher(indexMatcher), wrapMatcher(valueMatcher));
 
@@ -43,6 +46,25 @@
   }
 }
 
+class LiteralTypeMatcher extends Matcher {
+  final Matcher _typeMatcher;
+  final String _value;
+  LiteralTypeMatcher(this._typeMatcher, this._value);
+
+  @override
+  Description describe(Description description) => description
+      .add('a literal where type is ')
+      .addDescriptionOf(_typeMatcher)
+      .add(' and value is $_value');
+
+  @override
+  bool matches(item, Map matchState) {
+    return item is LiteralType &&
+        _typeMatcher.matches(item.type, matchState) &&
+        item.literal == _value;
+  }
+}
+
 class MapTypeMatcher extends Matcher {
   final Matcher _indexMatcher, _valueMatcher;
   const MapTypeMatcher(this._indexMatcher, this._valueMatcher);
diff --git a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
index 843ac88..b439e68 100644
--- a/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
+++ b/pkg/analysis_server/test/tool/lsp_spec/typescript_test.dart
@@ -385,5 +385,49 @@
       expect(output[0].commentNode.token.lexeme, equals('''// This is line 1
 // This is line 2'''));
     });
+
+    test('parses literal string values', () {
+      final input = '''
+export interface MyType {
+	kind: 'one';
+}
+    ''';
+      final output = parseString(input);
+      expect(output, hasLength(1));
+      expect(output[0], const TypeMatcher<Interface>());
+      final Interface interface = output[0];
+      expect(interface.name, equals('MyType'));
+      expect(interface.members, hasLength(1));
+      expect(interface.members[0], const TypeMatcher<Field>());
+      final Field field = interface.members[0];
+      expect(field.name, equals('kind'));
+      expect(field.allowsNull, isFalse);
+      expect(field.allowsUndefined, isFalse);
+      expect(field.type, isLiteralOf(isSimpleType('string'), "'one'"));
+    });
+
+    test('parses literal union values', () {
+      final input = '''
+export interface MyType {
+	kind: 'one' | 'two';
+}
+    ''';
+      final output = parseString(input);
+      expect(output, hasLength(1));
+      expect(output[0], const TypeMatcher<Interface>());
+      final Interface interface = output[0];
+      expect(interface.name, equals('MyType'));
+      expect(interface.members, hasLength(1));
+      expect(interface.members[0], const TypeMatcher<Field>());
+      final Field field = interface.members[0];
+      expect(field.name, equals('kind'));
+      expect(field.allowsNull, isFalse);
+      expect(field.allowsUndefined, isFalse);
+      expect(field.type, const TypeMatcher<LiteralUnionType>());
+      LiteralUnionType union = field.type;
+      expect(union.types, hasLength(2));
+      expect(union.types[0], isLiteralOf(isSimpleType('string'), "'one'"));
+      expect(union.types[1], isLiteralOf(isSimpleType('string'), "'two'"));
+    });
   });
 }
diff --git a/pkg/analysis_server/tool/bulk_fix/supported_lints.dart b/pkg/analysis_server/tool/bulk_fix/supported_lints.dart
new file mode 100644
index 0000000..7d6fbb3
--- /dev/null
+++ b/pkg/analysis_server/tool/bulk_fix/supported_lints.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
+
+/// Print lints that are bulk-fixable in a format that can be included in
+/// analysis options.
+void main() {
+  print('    # bulk-fixable lints');
+  for (var lintName in BulkFixProcessor.lintProducerMap.keys) {
+    print('    - $lintName');
+  }
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
index 1ae1151..0876be9 100644
--- a/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/code_metrics.dart
@@ -1356,7 +1356,7 @@
   CodeShapeMetricsComputer();
 
   /// Compute the metrics for the file(s) in the [rootPath].
-  void compute(String rootPath) async {
+  Future<void> compute(String rootPath) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1380,7 +1380,7 @@
   /// separate context collection to prevent accumulating memory. The metrics
   /// should be captured in the [collector]. Include additional details in the
   /// output if [verbose] is `true`.
-  void _computeInContext(
+  Future<void> _computeInContext(
       ContextRoot root, CodeShapeDataCollector collector) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
index 309d8a1..13f27be 100644
--- a/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/completion_metrics.dart
@@ -506,15 +506,11 @@
       bool doPrintMissedCompletions) {
     assert(suggestions != null);
 
-    var rank;
-
     var place = placementInSuggestionList(suggestions, expectedCompletion);
 
     metrics.mrrComputer.addRank(place.rank);
 
     if (place.denominator != 0) {
-      rank = place.rank;
-
       metrics.completionCounter.count('successful');
 
       metrics.recordCompletionResult(CompletionResult(place, request, listener,
@@ -527,9 +523,9 @@
           _computeCharsBeforeTop(expectedCompletion, suggestions, minRank: 5));
       metrics.insertionLengthTheoretical
           .addValue(expectedCompletion.completion.length - charsBeforeTop);
-    } else {
-      rank = -1;
 
+      return place.rank;
+    } else {
       metrics.completionCounter.count('unsuccessful');
 
       metrics.completionMissedTokenCounter.count(expectedCompletion.completion);
@@ -538,7 +534,7 @@
           .count(expectedCompletion.elementKind.toString());
 
       if (doPrintMissedCompletions) {
-        var closeMatchSuggestion;
+        protocol.CompletionSuggestion closeMatchSuggestion;
         for (var suggestion in suggestions) {
           if (suggestion.completion == expectedCompletion.completion) {
             closeMatchSuggestion = suggestion;
@@ -553,8 +549,9 @@
         }
         print('');
       }
+
+      return -1;
     }
-    return rank;
   }
 
   void printMetrics(CompletionMetrics metrics) {
@@ -713,7 +710,7 @@
       [DeclarationsTracker declarationsTracker,
       protocol.CompletionAvailableSuggestionsParams
           availableSuggestionsParams]) async {
-    var suggestions;
+    List<protocol.CompletionSuggestion> suggestions;
 
     if (declarationsTracker == null) {
       // available suggestions == false
@@ -801,8 +798,8 @@
 
     // Set the DeclarationsTracker, only call doWork to build up the available
     // suggestions if doComputeCompletionsFromAnalysisServer is true.
-    var declarationsTracker;
-    var availableSuggestionsParams;
+    DeclarationsTracker declarationsTracker;
+    protocol.CompletionAvailableSuggestionsParams availableSuggestionsParams;
     if (availableSuggestions) {
       declarationsTracker = DeclarationsTracker(
           MemoryByteStore(), PhysicalResourceProvider.INSTANCE);
@@ -912,7 +909,7 @@
 
             // First we compute the completions useNewRelevance set to
             // false:
-            var oldRank;
+            int oldRank;
             if (!skipOldRelevance) {
               oldRank = await handleExpectedCompletion(
                   metrics: metricsOldMode,
diff --git a/pkg/analysis_server/tool/completion_metrics/corpus.dart b/pkg/analysis_server/tool/completion_metrics/corpus.dart
index c79b368..71e09fb 100644
--- a/pkg/analysis_server/tool/completion_metrics/corpus.dart
+++ b/pkg/analysis_server/tool/completion_metrics/corpus.dart
@@ -74,7 +74,7 @@
   final name =
       _trimName(repo.split('https://github.com/').last.replaceAll('/', '_'));
   final cloneDir = path.join(_appDir, name);
-  var result;
+  ProcessResult result;
   if (Directory(cloneDir).existsSync()) {
     if (!updateExistingClones) {
       return CloneResult(0, cloneDir);
diff --git a/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart b/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
index 8ff6195..dee0616 100644
--- a/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/flutter_metrics.dart
@@ -172,7 +172,7 @@
   FlutterMetricsComputer();
 
   /// Compute the metrics for the file(s) in the [rootPath].
-  void compute(String rootPath) async {
+  Future<void> compute(String rootPath) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
diff --git a/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
index 4b9b1c0..c788082 100644
--- a/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
@@ -139,7 +139,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  void compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {@required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -170,7 +170,8 @@
   /// separate context collection to prevent accumulating memory. The metrics
   /// should be captured in the [collector]. Include additional details in the
   /// output if [verbose] is `true`.
-  void _computeInContext(ContextRoot root, ImpliedTypeCollector collector,
+  Future<void> _computeInContext(
+      ContextRoot root, ImpliedTypeCollector collector,
       {@required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
index e043511..2664da1 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_metrics.dart
@@ -1869,7 +1869,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  void compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {@required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1929,7 +1929,8 @@
   /// separate context collection to prevent accumulating memory. The metrics
   /// should be captured in the [collector]. Include additional details in the
   /// output if [verbose] is `true`.
-  void _computeInContext(ContextRoot root, RelevanceDataCollector collector,
+  Future<void> _computeInContext(
+      ContextRoot root, RelevanceDataCollector collector,
       {@required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
index 846e22d..b746fb6 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
@@ -1350,7 +1350,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  void compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {@required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -1365,7 +1365,8 @@
   /// separate context collection to prevent accumulating memory. The metrics
   /// should be captured in the [collector]. Include additional details in the
   /// output if [verbose] is `true`.
-  void _computeInContext(ContextRoot root, RelevanceDataCollector collector,
+  Future<void> _computeInContext(
+      ContextRoot root, RelevanceDataCollector collector,
       {@required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
diff --git a/pkg/analysis_server/tool/completion_metrics/visitors.dart b/pkg/analysis_server/tool/completion_metrics/visitors.dart
index b234a9b..0b130f7 100644
--- a/pkg/analysis_server/tool/completion_metrics/visitors.dart
+++ b/pkg/analysis_server/tool/completion_metrics/visitors.dart
@@ -571,7 +571,7 @@
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
     if (_doIncludeSimpleIdentifier(node)) {
-      var elementKind;
+      protocol.ElementKind elementKind;
       if (node.staticElement?.kind != null) {
         elementKind = protocol.convertElementKind(node.staticElement.kind);
 
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 41df728..051abb3 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -127,13 +127,17 @@
 
 Returns the location of the super definition of the class or method at the provided position or `null` if there isn't one.
 
-### $/analyzerStatus Notification
+### $/analyzerStatus Notification (Deprecated)
 
 Direction: Server -> Client
 Params: `{ isAnalyzing: boolean }`
 
 Notifies the client when analysis starts/completes.
 
+This notification is not sent if the client capabilities include `window.workDoneProgress == true` because analyzing status events will be sent using `$/progress`.
+
+This notification may be removed in a future Dart SDK release and should not be depended on.
+
 ### dart/textDocument/publishClosingLabels Notification
 
 Direction: Server -> Client
diff --git a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
index cefcce6..a9f9ce5 100644
--- a/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
+++ b/pkg/analysis_server/tool/lsp_spec/codegen_dart.dart
@@ -120,6 +120,16 @@
   return sortedList;
 }
 
+String _getTypeCheckFailureMessage(TypeBase type) {
+  if (type is LiteralType) {
+    return 'must be the literal ${type.literal}';
+  } else if (type is LiteralUnionType) {
+    return 'must be one of the literals ${type.literalTypes.map((t) => t.literal).join(', ')}';
+  } else {
+    return 'must be of type ${type.dartTypeWithTypeArgs}';
+  }
+}
+
 bool _isSimpleType(TypeBase type) {
   const literals = ['num', 'String', 'bool'];
   return type is Type && literals.contains(type.dartType);
@@ -224,7 +234,7 @@
       ..write(')) {')
       ..indent()
       ..writeIndentedln(
-          "reporter.reportError('must be of type ${field.type.dartTypeWithTypeArgs}');")
+          "reporter.reportError('${_getTypeCheckFailureMessage(field.type).replaceAll("'", "\\'")}');")
       ..writeIndentedln('return false;')
       ..outdent()
       ..writeIndentedln('}')
@@ -262,25 +272,42 @@
   buffer
     ..writeIndented('${interface.name}({')
     ..write(allFields.map((field) {
-      final annotation =
-          !field.allowsNull && !field.allowsUndefined ? '@required' : '';
-      return '$annotation this.${field.name}';
+      final isLiteral = field.type is LiteralType;
+      final isRequired =
+          !isLiteral && !field.allowsNull && !field.allowsUndefined;
+      final annotation = isRequired ? '@required' : '';
+      final valueCode =
+          isLiteral ? ' = ${(field.type as LiteralType).literal}' : '';
+      return '$annotation this.${field.name}$valueCode';
     }).join(', '))
     ..write('})');
-  final fieldsWithValidation =
-      allFields.where((f) => !f.allowsNull && !f.allowsUndefined).toList();
+  final fieldsWithValidation = allFields
+      .where(
+          (f) => (!f.allowsNull && !f.allowsUndefined) || f.type is LiteralType)
+      .toList();
   if (fieldsWithValidation.isNotEmpty) {
     buffer
       ..writeIndentedln(' {')
       ..indent();
     for (var field in fieldsWithValidation) {
-      buffer
-        ..writeIndentedln('if (${field.name} == null) {')
-        ..indent()
-        ..writeIndentedln(
-            "throw '${field.name} is required but was not provided';")
-        ..outdent()
-        ..writeIndentedln('}');
+      final type = field.type;
+      if (type is LiteralType) {
+        buffer
+          ..writeIndentedln('if (${field.name} != ${type.literal}) {')
+          ..indent()
+          ..writeIndentedln(
+              "throw '${field.name} may only be the literal ${type.literal.replaceAll("'", "\\'")}';")
+          ..outdent()
+          ..writeIndentedln('}');
+      } else if (!field.allowsNull && !field.allowsUndefined) {
+        buffer
+          ..writeIndentedln('if (${field.name} == null) {')
+          ..indent()
+          ..writeIndentedln(
+              "throw '${field.name} is required but was not provided';")
+          ..outdent()
+          ..writeIndentedln('}');
+      }
     }
     buffer
       ..outdent()
@@ -310,8 +337,13 @@
   final consts = namespace.members.cast<Const>().toList();
   final allowsAnyValue = enumClassAllowsAnyValue(namespace.name);
   final constructorName = allowsAnyValue ? '' : '._';
+  final firstValueType = consts.first.type;
+  // Enums can have constant values in their fields so if a field is a literal
+  // use its underlying type for type checking.
+  final requiredValueType =
+      firstValueType is LiteralType ? firstValueType.type : firstValueType;
   final typeOfValues =
-      resolveTypeAlias(consts.first.type, resolveEnumClasses: true);
+      resolveTypeAlias(requiredValueType, resolveEnumClasses: true);
 
   buffer
     ..writeln('class ${namespace.name} {')
@@ -333,7 +365,7 @@
       ..writeIndentedln('switch (obj) {')
       ..indent();
     consts.forEach((cons) {
-      buffer..writeIndentedln('case ${cons.valueAsLiteral}:');
+      buffer.writeIndentedln('case ${cons.valueAsLiteral}:');
     });
     buffer
       ..indent()
@@ -348,9 +380,8 @@
     ..writeIndentedln('}');
   namespace.members.whereType<Const>().forEach((cons) {
     _writeDocCommentsAndAnnotations(buffer, cons);
-    buffer
-      ..writeIndentedln(
-          'static const ${_makeValidIdentifier(cons.name)} = ${namespace.name}$constructorName(${cons.valueAsLiteral});');
+    buffer.writeIndentedln(
+        'static const ${_makeValidIdentifier(cons.name)} = ${namespace.name}$constructorName(${cons.valueAsLiteral});');
   });
   buffer
     ..writeln()
@@ -449,6 +480,9 @@
     _writeFromJsonCode(buffer, type.valueType, 'value', allowsNull: allowsNull);
     buffer.write(
         '))?.cast<${type.indexType.dartTypeWithTypeArgs}, ${type.valueType.dartTypeWithTypeArgs}>()');
+  } else if (type is LiteralUnionType) {
+    _writeFromJsonCodeForLiteralUnion(buffer, type, valueCode,
+        allowsNull: allowsNull);
   } else if (type is UnionType) {
     _writeFromJsonCodeForUnion(buffer, type, valueCode, allowsNull: allowsNull);
   } else {
@@ -456,6 +490,18 @@
   }
 }
 
+void _writeFromJsonCodeForLiteralUnion(
+    IndentableStringBuffer buffer, LiteralUnionType union, String valueCode,
+    {bool allowsNull}) {
+  final allowedValues = [
+    if (allowsNull) null,
+    ...union.literalTypes.map((t) => t.literal)
+  ];
+  buffer.write(
+      "const {${allowedValues.join(', ')}}.contains($valueCode) ? $valueCode : "
+      "throw '''\${$valueCode} was not one of (${allowedValues.join(', ')})'''");
+}
+
 void _writeFromJsonCodeForUnion(
     IndentableStringBuffer buffer, UnionType union, String valueCode,
     {bool allowsNull}) {
@@ -611,7 +657,11 @@
       ..writeIndentedln('if (${field.name} != null) {')
       ..indent();
   }
-  buffer..writeIndented('''$mapName['${field.name}'] = ${field.name}''');
+  // Suppress the ? operator if we've output a null check already.
+  final nullOp = shouldBeOmittedIfNoValue ? '' : '?';
+  final valueCode =
+      _isSpecType(field.type) ? '${field.name}$nullOp.toJson()' : field.name;
+  buffer.writeIndented('''$mapName['${field.name}'] = $valueCode''');
   if (!field.allowsUndefined && !field.allowsNull) {
     buffer.write(''' ?? (throw '${field.name} is required but was not set')''');
   }
@@ -720,6 +770,8 @@
     buffer.write('true');
   } else if (_isSimpleType(type)) {
     buffer.write('$valueCode is $fullDartType');
+  } else if (type is LiteralType) {
+    buffer.write('$valueCode == ${type.literal}');
   } else if (_isSpecType(type)) {
     buffer.write('$dartType.canParse($valueCode, $reporter)');
   } else if (type is ArrayType) {
@@ -739,7 +791,7 @@
       buffer..write(' && (')..write('$valueCode.keys.every((item) => ');
       _writeTypeCheckCondition(
           buffer, interface, 'item', type.indexType, reporter);
-      buffer..write('&& $valueCode.values.every((item) => ');
+      buffer.write('&& $valueCode.values.every((item) => ');
       _writeTypeCheckCondition(
           buffer, interface, 'item', type.valueType, reporter);
       buffer.write(')))');
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
index 1f510d6..9e9d814 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript_parser.dart
@@ -29,6 +29,8 @@
 bool isAnyType(TypeBase t) =>
     t is Type && (t.name == 'any' || t.name == 'object');
 
+bool isLiteralType(TypeBase t) => t is LiteralType;
+
 bool isNullType(TypeBase t) => t is Type && t.name == 'null';
 
 bool isUndefinedType(TypeBase t) => t is Type && t.name == 'undefined';
@@ -85,6 +87,7 @@
   Token valueToken;
   Const(Comment comment, this.nameToken, this.type, this.valueToken)
       : super(comment);
+
   @override
   String get name => nameToken.lexeme;
 
@@ -172,6 +175,36 @@
       : '';
 }
 
+class LiteralType extends TypeBase {
+  final Type type;
+  final String literal;
+
+  LiteralType(this.type, this.literal);
+
+  @override
+  String get dartType => type.dartType;
+
+  @override
+  String get typeArgsString => type.typeArgsString;
+
+  @override
+  String get uniqueTypeIdentifier => '$literal:${super.uniqueTypeIdentifier}';
+}
+
+/// A special class of Union types where the values are all literals of the same
+/// type so the Dart field can be the base type rather than an EitherX<>.
+class LiteralUnionType extends UnionType {
+  final List<LiteralType> literalTypes;
+
+  LiteralUnionType(this.literalTypes) : super(literalTypes);
+
+  @override
+  String get dartType => types.first.dartType;
+
+  @override
+  String get typeArgsString => types.first.typeArgsString;
+}
+
 class MapType extends TypeBase {
   final TypeBase indexType;
   final TypeBase valueType;
@@ -180,6 +213,7 @@
 
   @override
   String get dartType => 'Map';
+
   @override
   String get typeArgsString =>
       '<${indexType.dartTypeWithTypeArgs}, ${valueType.dartTypeWithTypeArgs}>';
@@ -364,9 +398,7 @@
       // simplify the unions.
       remainingTypes.removeWhere((t) => !allowTypeInSignatures(t));
 
-      type = remainingTypes.length > 1
-          ? UnionType(remainingTypes)
-          : remainingTypes.single;
+      type = _simplifyUnionTypes(remainingTypes);
     } else if (isAnyType(type)) {
       // There are values in the spec marked as `any` that allow nulls (for
       // example, the result field on ResponseMessage can be null for a
@@ -376,25 +408,6 @@
     return Field(leadingComment, name, type, canBeNull, canBeUndefined);
   }
 
-  /// Remove any duplicate types (for ex. if we map multiple types into dynamic)
-  /// we don't want to end up with `dynamic | dynamic`. Key on dartType to
-  /// ensure we different types that will map down to the same type.
-  List<TypeBase> _getUniqueTypes(List<TypeBase> types) {
-    final uniqueTypes = Map.fromEntries(
-      types.map((t) => MapEntry(t.dartTypeWithTypeArgs, t)),
-    ).values.toList();
-
-    // If our list includes something that maps to dynamic as well as other
-    // types, we should just treat the whole thing as dynamic as we get no value
-    // typing Either4<bool, String, num, dynamic> but it becomes much more
-    // difficult to use.
-    if (uniqueTypes.any(isAnyType)) {
-      return [uniqueTypes.firstWhere(isAnyType)];
-    }
-
-    return uniqueTypes;
-  }
-
   Indexer _indexer(String containerName, Comment leadingComment) {
     final indexer = _field(containerName, leadingComment);
     _consume(TokenType.RIGHT_BRACKET, 'Expected ]');
@@ -490,6 +503,29 @@
   /// Returns the next token without advancing.
   Token _peek() => _tokenAt(_current);
 
+  /// Remove any duplicate types (for ex. if we map multiple types into dynamic)
+  /// we don't want to end up with `dynamic | dynamic`. Key on dartType to
+  /// ensure we different types that will map down to the same type.
+  TypeBase _simplifyUnionTypes(List<TypeBase> types) {
+    final uniqueTypes = Map.fromEntries(
+      types.map((t) => MapEntry(t.uniqueTypeIdentifier, t)),
+    ).values.toList();
+
+    // If our list includes something that maps to dynamic as well as other
+    // types, we should just treat the whole thing as dynamic as we get no value
+    // typing Either4<bool, String, num, dynamic> but it becomes much more
+    // difficult to use.
+    if (uniqueTypes.any(isAnyType)) {
+      return uniqueTypes.firstWhere(isAnyType);
+    }
+
+    return uniqueTypes.length == 1
+        ? uniqueTypes.single
+        : uniqueTypes.every(isLiteralType)
+            ? LiteralUnionType(uniqueTypes.cast<LiteralType>())
+            : UnionType(uniqueTypes);
+  }
+
   Token _tokenAt(int index) =>
       index < _tokens.length ? _tokens[index] : Token.EOF;
 
@@ -562,17 +598,17 @@
         // Some types are in (parens), so we just parse the contents as a nested type.
         type = _type(containerName, fieldName);
         _consume(TokenType.RIGHT_PAREN, 'Expected )');
-      } else if (_match([TokenType.STRING])) {
+      } else if (_check(TokenType.STRING)) {
+        final token = _advance();
         // In TS and the spec, literal strings can be types:
         // export const PlainText: 'plaintext' = 'plaintext';
         // trace?: 'off' | 'messages' | 'verbose';
-        // the best we can do is use their base type (string).
-        type = Type.identifier('string');
-      } else if (_match([TokenType.NUMBER])) {
+        type = LiteralType(Type.identifier('string'), token.lexeme);
+      } else if (_check(TokenType.NUMBER)) {
+        final token = _advance();
         // In TS and the spec, literal numbers can be types:
         // export const Invoked: 1 = 1;
-        // the best we can do is use their base type (number).
-        type = Type.identifier('number');
+        type = LiteralType(Type.identifier('number'), token.lexeme);
       } else if (_match([TokenType.LEFT_BRACKET])) {
         // Tuples will just be converted to List/Array.
         final tupleElementTypes = <TypeBase>[];
@@ -583,10 +619,7 @@
         }
         _consume(TokenType.RIGHT_BRACKET, 'Expected ]');
 
-        final uniqueTypes = _getUniqueTypes(tupleElementTypes);
-        var tupleType = uniqueTypes.length == 1
-            ? uniqueTypes.single
-            : UnionType(uniqueTypes);
+        var tupleType = _simplifyUnionTypes(tupleElementTypes);
         type = ArrayType(tupleType);
       } else {
         var typeName = _consume(TokenType.IDENTIFIER, 'Expected identifier');
@@ -629,10 +662,7 @@
       }
     }
 
-    final uniqueTypes = _getUniqueTypes(types);
-
-    var type =
-        uniqueTypes.length == 1 ? uniqueTypes.single : UnionType(uniqueTypes);
+    var type = _simplifyUnionTypes(types);
 
     // Handle improved type mappings for things that aren't very tight in the spec.
     if (improveTypes) {
@@ -957,6 +987,10 @@
   String get dartType;
   String get dartTypeWithTypeArgs => '$dartType$typeArgsString';
   String get typeArgsString;
+
+  /// A unique identifier for this type. Used for folding types together
+  /// (for example two types that resolve to "dynamic" in Dart).
+  String get uniqueTypeIdentifier => dartTypeWithTypeArgs;
 }
 
 class UnionType extends TypeBase {
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index ee2d987..f3f3dd1 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -574,6 +574,10 @@
    *
    * Return the set of fixes that are available for the errors at a given offset in a given file.
    *
+   * If a request is made for a file which does not exist, or which is not currently subject to
+   * analysis (e.g. because it is not associated with any analysis root specified to
+   * analysis.setAnalysisRoots), an error of type GET_FIXES_INVALID_FILE will be generated.
+   *
    * @param file The file containing the errors for which fixes are being requested.
    * @param offset The offset used to select the errors for which fixes will be returned.
    */
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java b/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
index 43f3e4d..f29aafb 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ParameterKind.java
@@ -16,18 +16,23 @@
 public class ParameterKind {
 
   /**
-   * A named parameter.
+   * An optional named parameter.
    */
-  public static final String NAMED = "NAMED";
+  public static final String OPTIONAL_NAMED = "OPTIONAL_NAMED";
 
   /**
-   * An optional parameter.
+   * An optional positional parameter.
    */
-  public static final String OPTIONAL = "OPTIONAL";
+  public static final String OPTIONAL_POSITIONAL = "OPTIONAL_POSITIONAL";
 
   /**
-   * A required parameter.
+   * A required named parameter.
    */
-  public static final String REQUIRED = "REQUIRED";
+  public static final String REQUIRED_NAMED = "REQUIRED_NAMED";
+
+  /**
+   * A required positional parameter.
+   */
+  public static final String REQUIRED_POSITIONAL = "REQUIRED_POSITIONAL";
 
 }
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index 0129bac..44da4d7 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -77,6 +77,12 @@
   public static final String GET_ERRORS_INVALID_FILE = "GET_ERRORS_INVALID_FILE";
 
   /**
+   * An "edit.getFixes" request specified a FilePath which does not match a file currently subject to
+   * analysis.
+   */
+  public static final String GET_FIXES_INVALID_FILE = "GET_FIXES_INVALID_FILE";
+
+  /**
    * An "analysis.getImportedElements" request specified a FilePath that does not match a file
    * currently subject to analysis.
    */
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 0247bb1..eb8cf23 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.29.0</version>
+  <version>1.30.0</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -2345,6 +2345,13 @@
       Return the set of fixes that are available for the errors at
       a given offset in a given file.
     </p>
+    <p>
+      If a request is made for a file which does not exist, or
+      which is not currently subject to analysis (e.g. because it
+      is not associated with any analysis root specified to
+      analysis.setAnalysisRoots), an error of type
+      <tt>GET_FIXES_INVALID_FILE</tt> will be generated.
+    </p>
     <params>
       <field name="file">
         <ref>FilePath</ref>
@@ -5004,6 +5011,14 @@
         </p>
       </value>
       <value>
+        <code>GET_FIXES_INVALID_FILE</code>
+        <p>
+          An "edit.getFixes" request specified a FilePath
+          which does not match a file currently subject to
+          analysis.
+        </p>
+      </value>
+      <value>
         <code>GET_IMPORTED_ELEMENTS_INVALID_FILE</code>
         <p>
           An "analysis.getImportedElements" request specified a FilePath that
diff --git a/pkg/analysis_server_client/analysis_options.yaml b/pkg/analysis_server_client/analysis_options.yaml
index fe1ff59..fd37fb4 100644
--- a/pkg/analysis_server_client/analysis_options.yaml
+++ b/pkg/analysis_server_client/analysis_options.yaml
@@ -4,6 +4,7 @@
 
 linter:
   rules:
+    - await_only_futures
     - empty_statements
     - unnecessary_brace_in_string_interps
     #
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 8bfb877..25f5a64 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.29.0';
+const String PROTOCOL_VERSION = '1.30.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 29ae9ac..b6d697f 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -17810,6 +17810,7 @@
 ///   FORMAT_INVALID_FILE
 ///   FORMAT_WITH_ERRORS
 ///   GET_ERRORS_INVALID_FILE
+///   GET_FIXES_INVALID_FILE
 ///   GET_IMPORTED_ELEMENTS_INVALID_FILE
 ///   GET_KYTHE_ENTRIES_INVALID_FILE
 ///   GET_NAVIGATION_INVALID_FILE
@@ -17891,6 +17892,11 @@
   static const RequestErrorCode GET_ERRORS_INVALID_FILE =
       RequestErrorCode._('GET_ERRORS_INVALID_FILE');
 
+  /// An "edit.getFixes" request specified a FilePath which does not match a
+  /// file currently subject to analysis.
+  static const RequestErrorCode GET_FIXES_INVALID_FILE =
+      RequestErrorCode._('GET_FIXES_INVALID_FILE');
+
   /// An "analysis.getImportedElements" request specified a FilePath that does
   /// not match a file currently subject to analysis.
   static const RequestErrorCode GET_IMPORTED_ELEMENTS_INVALID_FILE =
@@ -18022,6 +18028,7 @@
     FORMAT_INVALID_FILE,
     FORMAT_WITH_ERRORS,
     GET_ERRORS_INVALID_FILE,
+    GET_FIXES_INVALID_FILE,
     GET_IMPORTED_ELEMENTS_INVALID_FILE,
     GET_KYTHE_ENTRIES_INVALID_FILE,
     GET_NAVIGATION_INVALID_FILE,
@@ -18076,6 +18083,8 @@
         return FORMAT_WITH_ERRORS;
       case 'GET_ERRORS_INVALID_FILE':
         return GET_ERRORS_INVALID_FILE;
+      case 'GET_FIXES_INVALID_FILE':
+        return GET_FIXES_INVALID_FILE;
       case 'GET_IMPORTED_ELEMENTS_INVALID_FILE':
         return GET_IMPORTED_ELEMENTS_INVALID_FILE;
       case 'GET_KYTHE_ENTRIES_INVALID_FILE':
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 7353b55..2a979a6 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,14 @@
+## 0.40.4
+* Deprecated `IndexExpression.auxiliaryElements` and
+  `SimpleIdentifier.auxiliaryElements`. Use `CompoundAssignmentExpression`.
+* Removed internal `getReadType`, use `CompoundAssignmentExpression`.
+* Bug fixes: 34699, 43524, 42990.
+
+## 0.40.3
+* Updated the current language version to `2.11`.
+* Bug fixes: 43541, 27896, 28066, 28066, 43497, 43478, 28066, 43465,
+  43462, 43439, 43162, 43397, 43200.
+
 ## 0.40.2
 * Require `meta: ^1.2.3`.
 
diff --git a/pkg/analyzer/analysis_options.yaml b/pkg/analyzer/analysis_options.yaml
index 62f4670..3f9b8e3 100644
--- a/pkg/analyzer/analysis_options.yaml
+++ b/pkg/analyzer/analysis_options.yaml
@@ -27,7 +27,11 @@
 linter:
   rules:
     - avoid_unused_constructor_parameters
+    - await_only_futures
     - empty_statements
+    - iterable_contains_unrelated_type
+    - list_remove_unrelated_type
     - prefer_typing_uninitialized_variables
     - unnecessary_brace_in_string_interps
+    - unnecessary_overrides
     - unnecessary_parenthesis
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 2c91951..aa20e8b 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -3241,11 +3241,15 @@
   /// The auxiliary elements hold the static and propagated elements associated
   /// with the getter context.
   // TODO(brianwilkerson) Replace this API.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   AuxiliaryElements get auxiliaryElements;
 
   /// Set the auxiliary elements associated with this identifier to the given
   /// [elements].
   // TODO(brianwilkerson) Replace this API.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   set auxiliaryElements(AuxiliaryElements elements);
 
   /// Return the expression used to compute the index.
@@ -4599,11 +4603,15 @@
   /// The auxiliary elements hold the static and propagated elements associated
   /// with the getter context.
   // TODO(brianwilkerson) Replace this API.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   AuxiliaryElements get auxiliaryElements;
 
   /// Set the auxiliary elements associated with this identifier to the given
   /// [elements].
   // TODO(brianwilkerson) Replace this API.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   set auxiliaryElements(AuxiliaryElements elements);
 
   /// Return `true` if this identifier is the "name" part of a prefixed
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 71b8251..9e50585 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -534,6 +534,9 @@
   /// Return `true` if this element has an annotation of the form `@factory`.
   bool get hasFactory;
 
+  /// Return `true` if this element has an annotation of the form `@internal`.
+  bool get hasInternal;
+
   /// Return `true` if this element has an annotation of the form `@isTest`.
   bool get hasIsTest;
 
@@ -717,6 +720,10 @@
   /// subclasses as being immutable.
   bool get isImmutable;
 
+  /// Return `true` if this annotation marks the associated element as being
+  /// internal to its package.
+  bool get isInternal;
+
   /// Return `true` if this annotation marks the associated member as running
   /// a single test.
   bool get isIsTest;
diff --git a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
index 8f2757b..8705915 100644
--- a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
+++ b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
@@ -5,11 +5,13 @@
 import 'dart:typed_data';
 
 import 'package:_fe_analyzer_shared/src/sdk/allowed_experiments.dart';
+import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/utilities.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
@@ -38,7 +40,6 @@
     resourceProvider,
     resourceProvider.getFolder(sdkPath),
   );
-  sdk.analysisOptions = AnalysisOptionsImpl();
 
   // Append libraries from the embedder.
   if (embedderYamlPath != null) {
@@ -62,8 +63,13 @@
     return sdk.mapDartUri(e.shortName);
   }).toList();
 
+  var analysisContext = AnalysisContextImpl(
+    SynchronousSession(AnalysisOptionsImpl(), DeclaredVariables()),
+    SourceFactory([DartUriResolver(sdk)]),
+  );
+
   return _Builder(
-    sdk.context,
+    analysisContext,
     sdk.allowedExperimentsJson,
     sdk.languageVersion,
     librarySources,
@@ -71,7 +77,7 @@
 }
 
 class _Builder {
-  final AnalysisContext context;
+  final AnalysisContextImpl context;
   final String allowedExperimentsJson;
   final Iterable<Source> librarySources;
 
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 5d9f60a..ab4089c 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -142,7 +142,6 @@
   CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH,
   CompileTimeErrorCode.COULD_NOT_INFER,
   CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR,
-  CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
   CompileTimeErrorCode.DEFAULT_VALUE_IN_REDIRECTING_FACTORY_CONSTRUCTOR,
   CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
   CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
@@ -261,6 +260,10 @@
   CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR,
   CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED,
   CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
+  CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE,
+  CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS,
+  CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
+  CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION,
   CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
   CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
   CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
@@ -492,10 +495,13 @@
   HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE,
   HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
   HintCode.INVALID_ANNOTATION_TARGET,
+  HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+  HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
   HintCode.INVALID_FACTORY_ANNOTATION,
   HintCode.INVALID_FACTORY_METHOD_DECL,
   HintCode.INVALID_FACTORY_METHOD_IMPL,
   HintCode.INVALID_IMMUTABLE_ANNOTATION,
+  HintCode.INVALID_INTERNAL_ANNOTATION,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER,
@@ -512,6 +518,7 @@
   HintCode.INVALID_REQUIRED_OPTIONAL_POSITIONAL_PARAM,
   HintCode.INVALID_REQUIRED_POSITIONAL_PARAM,
   HintCode.INVALID_SEALED_ANNOTATION,
+  HintCode.INVALID_USE_OF_INTERNAL_MEMBER,
   HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
   HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER,
   HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER,
@@ -536,6 +543,7 @@
   HintCode.OVERRIDE_ON_NON_OVERRIDING_SETTER,
   HintCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT,
   HintCode.RECEIVER_OF_TYPE_NEVER,
+  HintCode.RETURN_OF_DO_NOT_STORE,
   HintCode.SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT,
   HintCode.SDK_VERSION_ASYNC_EXPORTED_FROM_CORE,
   HintCode.SDK_VERSION_BOOL_OPERATOR_IN_CONST_CONTEXT,
@@ -597,6 +605,7 @@
   ParserErrorCode.ANNOTATION_ON_TYPE_ARGUMENT,
   ParserErrorCode.ANNOTATION_WITH_TYPE_ARGUMENTS,
   ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
+  ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT,
   ParserErrorCode.BREAK_OUTSIDE_OF_LOOP,
   ParserErrorCode.CATCH_SYNTAX,
   ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
@@ -632,6 +641,7 @@
   ParserErrorCode.EXPECTED_CLASS_MEMBER,
   ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
   ParserErrorCode.EXPECTED_EXECUTABLE,
+  ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD,
   ParserErrorCode.EXPECTED_INSTEAD,
   ParserErrorCode.EXPECTED_LIST_OR_MAP_LITERAL,
   ParserErrorCode.EXPECTED_STRING_LITERAL,
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 091943f..d852cb0 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -20,6 +20,7 @@
       HashMap<String, _MemoryResource>();
   final Map<String, Uint8List> _pathToBytes = HashMap<String, Uint8List>();
   final Map<String, int> _pathToTimestamp = HashMap<String, int>();
+  final Map<String, String> _pathToLinkedPath = {};
   final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
       HashMap<String, List<StreamController<WatchEvent>>>();
   int nextStamp = 0;
@@ -176,6 +177,13 @@
     }
   }
 
+  /// Create a link from the [path] to the [target].
+  void newLink(String path, String target) {
+    _ensureAbsoluteAndNormalized(path);
+    _ensureAbsoluteAndNormalized(target);
+    _pathToLinkedPath[path] = target;
+  }
+
   File updateFile(String path, String content, [int stamp]) {
     _ensureAbsoluteAndNormalized(path);
     newFolder(pathContext.dirname(path));
@@ -276,6 +284,30 @@
     return newFile;
   }
 
+  String _resolveLinks(String path) {
+    var linkTarget = _pathToLinkedPath[path];
+    if (linkTarget != null) {
+      return linkTarget;
+    }
+
+    var parentPath = _pathContext.dirname(path);
+    if (parentPath == path) {
+      return path;
+    }
+
+    var canonicalParentPath = _resolveLinks(parentPath);
+
+    var baseName = _pathContext.basename(path);
+    var result = _pathContext.join(canonicalParentPath, baseName);
+
+    linkTarget = _pathToLinkedPath[result];
+    if (linkTarget != null) {
+      return linkTarget;
+    }
+
+    return result;
+  }
+
   void _setFileContent(_MemoryFile file, List<int> bytes) {
     String path = file.path;
     _pathToResource[path] = file;
@@ -370,7 +402,10 @@
       : super(provider, path);
 
   @override
-  bool get exists => provider._pathToResource[path] is _MemoryFile;
+  bool get exists {
+    var canonicalPath = provider._resolveLinks(path);
+    return provider._pathToResource[canonicalPath] is _MemoryFile;
+  }
 
   @override
   int get lengthSync {
@@ -379,7 +414,8 @@
 
   @override
   int get modificationStamp {
-    int stamp = provider._pathToTimestamp[path];
+    var canonicalPath = provider._resolveLinks(path);
+    int stamp = provider._pathToTimestamp[canonicalPath];
     if (stamp == null) {
       throw FileSystemException(path, 'File "$path" does not exist.');
     }
@@ -412,7 +448,8 @@
 
   @override
   Uint8List readAsBytesSync() {
-    Uint8List content = provider._pathToBytes[path];
+    var canonicalPath = provider._resolveLinks(path);
+    Uint8List content = provider._pathToBytes[canonicalPath];
     if (content == null) {
       throw FileSystemException(path, 'File "$path" does not exist.');
     }
@@ -421,7 +458,8 @@
 
   @override
   String readAsStringSync() {
-    Uint8List content = provider._pathToBytes[path];
+    var canonicalPath = provider._resolveLinks(path);
+    Uint8List content = provider._pathToBytes[canonicalPath];
     if (content == null) {
       throw FileSystemException(path, 'File "$path" does not exist.');
     }
@@ -434,7 +472,16 @@
   }
 
   @override
-  File resolveSymbolicLinksSync() => this;
+  File resolveSymbolicLinksSync() {
+    var canonicalPath = provider._resolveLinks(path);
+    var result = provider.getFile(canonicalPath);
+
+    if (!result.exists) {
+      throw FileSystemException(path, 'File "$path" does not exist.');
+    }
+
+    return result;
+  }
 
   @override
   void writeAsBytesSync(List<int> bytes) {
@@ -538,7 +585,10 @@
   }
 
   @override
-  Folder resolveSymbolicLinksSync() => this;
+  Folder resolveSymbolicLinksSync() {
+    var canonicalPath = provider._resolveLinks(path);
+    return provider.getFolder(canonicalPath);
+  }
 
   @override
   Uri toUri() => provider.pathContext.toUri(path + '/');
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 839db04..7a43df7 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -114,7 +114,7 @@
     if (builderOptions.librarySummaryPaths != null) {
       summaryData = SummaryDataStore(builderOptions.librarySummaryPaths);
     }
-    final sf = createSourceFactory(path, options, summaryData: summaryData);
+    final sf = createSourceFactory(path, summaryData: summaryData);
 
     AnalysisDriver driver = AnalysisDriver(
       analysisDriverScheduler,
@@ -198,11 +198,11 @@
     }
   }
 
-  SourceFactory createSourceFactory(String rootPath, AnalysisOptions options,
+  SourceFactory createSourceFactory(String rootPath,
       {SummaryDataStore summaryData}) {
     Workspace workspace =
         ContextBuilder.createWorkspace(resourceProvider, rootPath, this);
-    DartSdk sdk = findSdk(workspace, options);
+    DartSdk sdk = findSdk(workspace);
     if (summaryData != null && sdk is SummaryBasedDartSdk) {
       summaryData.addBundle(null, sdk.bundle);
     }
@@ -220,10 +220,8 @@
   }
 
   /// Return the SDK that should be used to analyze code. Use the given
-  /// [workspace] and [analysisOptions] to locate the SDK.
-  ///
-  /// TODO(scheglov) Remove [analysisOptions]?
-  DartSdk findSdk(Workspace workspace, AnalysisOptions analysisOptions) {
+  /// [workspace] to locate the SDK.
+  DartSdk findSdk(Workspace workspace) {
     String summaryPath = builderOptions.dartSdkSummaryPath;
     if (summaryPath != null) {
       return SummaryBasedDartSdk(summaryPath, true,
@@ -235,12 +233,10 @@
       String sdkPath = sdkManager.defaultSdkDirectory;
       SdkDescription description = SdkDescription(sdkPath);
       folderSdk = sdkManager.getSdk(description, () {
-        var sdk = FolderBasedDartSdk(
+        return FolderBasedDartSdk(
           resourceProvider,
           resourceProvider.getFolder(sdkPath),
         );
-        sdk.analysisOptions = analysisOptions;
-        return sdk;
       });
     }
 
diff --git a/pkg/analyzer/lib/src/context/context.dart b/pkg/analyzer/lib/src/context/context.dart
index 78b0a00..28cdb0c 100644
--- a/pkg/analyzer/lib/src/context/context.dart
+++ b/pkg/analyzer/lib/src/context/context.dart
@@ -70,12 +70,3 @@
     );
   }
 }
-
-/// An [AnalysisContext] that only contains sources for a Dart SDK.
-class SdkAnalysisContext extends AnalysisContextImpl {
-  /// Initialize a newly created SDK analysis context with the given [options].
-  /// Analysis options cannot be changed afterwards.  If the given [options] are
-  /// `null`, then default options are used.
-  SdkAnalysisContext(AnalysisOptions options, SourceFactory sourceFactory)
-      : super(SynchronousSession(options, DeclaredVariables()), sourceFactory);
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index a369c9c..8e30f1f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -85,7 +85,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 110;
+  static const int DATA_VERSION = 112;
 
   /// The length of the list returned by [_computeDeclaredVariablesSignature].
   static const int _declaredVariablesSignatureLength = 4;
@@ -1450,6 +1450,8 @@
       resourceProvider: _resourceProvider,
       packages: _packages,
       packageDefaultFeatureSet: _analysisOptions.contextFeatures,
+      nonPackageDefaultLanguageVersion:
+          _analysisOptions.nonPackageLanguageVersion,
       nonPackageDefaultFeatureSet: _analysisOptions.nonPackageFeatureSet,
     );
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index fd36922..9f390a8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -8,7 +8,7 @@
 
 /// The current version of the Dart language (or, for non-stable releases, the
 /// version of the language currently in the process of being developed).
-const _currentVersion = '2.10.0';
+const _currentVersion = '2.11.0';
 
 /// A map containing information about all known experimental flags.
 final _knownFeatures = <String, ExperimentalFeature>{
@@ -68,7 +68,7 @@
     isExpired: IsExpired.constant_update_2018,
     documentation: 'Enhanced constant expressions',
     experimentalReleaseVersion: null,
-    releaseVersion: Version.parse('2.4.1'),
+    releaseVersion: Version.parse('2.0.0'),
   );
 
   static final control_flow_collections = ExperimentalFeature(
@@ -78,7 +78,7 @@
     isExpired: IsExpired.control_flow_collections,
     documentation: 'Control Flow Collections',
     experimentalReleaseVersion: null,
-    releaseVersion: Version.parse('2.2.2'),
+    releaseVersion: Version.parse('2.0.0'),
   );
 
   static final extension_methods = ExperimentalFeature(
@@ -118,7 +118,7 @@
     isExpired: IsExpired.set_literals,
     documentation: 'Set Literals',
     experimentalReleaseVersion: null,
-    releaseVersion: Version.parse('2.2.0'),
+    releaseVersion: Version.parse('2.0.0'),
   );
 
   static final spread_collections = ExperimentalFeature(
@@ -128,7 +128,7 @@
     isExpired: IsExpired.spread_collections,
     documentation: 'Spread Collections',
     experimentalReleaseVersion: null,
-    releaseVersion: Version.parse('2.2.2'),
+    releaseVersion: Version.parse('2.0.0'),
   );
 
   static final triple_shift = ExperimentalFeature(
diff --git a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
index 45de3c8..16a57bd 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -23,6 +23,7 @@
   final ResourceProvider _resourceProvider;
   final Packages _packages;
   final FeatureSet _packageDefaultFeatureSet;
+  final Version _nonPackageDefaultLanguageVersion;
   final FeatureSet _nonPackageDefaultFeatureSet;
 
   FeatureSetProvider._({
@@ -31,12 +32,14 @@
     @required ResourceProvider resourceProvider,
     @required Packages packages,
     @required FeatureSet packageDefaultFeatureSet,
+    @required Version nonPackageDefaultLanguageVersion,
     @required FeatureSet nonPackageDefaultFeatureSet,
   })  : _sdkLanguageVersion = sdkLanguageVersion,
         _allowedExperiments = allowedExperiments,
         _resourceProvider = resourceProvider,
         _packages = packages,
         _packageDefaultFeatureSet = packageDefaultFeatureSet,
+        _nonPackageDefaultLanguageVersion = nonPackageDefaultLanguageVersion,
         _nonPackageDefaultFeatureSet = nonPackageDefaultFeatureSet;
 
   FeatureSet featureSetForExperiments(List<String> experiments) {
@@ -90,9 +93,10 @@
       if (languageVersion != null) {
         return languageVersion;
       }
+      return ExperimentStatus.currentVersion;
     }
 
-    return ExperimentStatus.currentVersion;
+    return _nonPackageDefaultLanguageVersion;
   }
 
   /// Return the package corresponding to the [uri] or [path], `null` if none.
@@ -130,6 +134,7 @@
     @required ResourceProvider resourceProvider,
     @required Packages packages,
     @required FeatureSet packageDefaultFeatureSet,
+    @required Version nonPackageDefaultLanguageVersion,
     @required FeatureSet nonPackageDefaultFeatureSet,
   }) {
     var sdk = sourceFactory.dartSdk;
@@ -140,6 +145,7 @@
       resourceProvider: resourceProvider,
       packages: packages,
       packageDefaultFeatureSet: packageDefaultFeatureSet,
+      nonPackageDefaultLanguageVersion: nonPackageDefaultLanguageVersion,
       nonPackageDefaultFeatureSet: nonPackageDefaultFeatureSet,
     );
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index db34b39..0a3dee5 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -115,7 +115,7 @@
   final FeatureSet _contextFeatureSet;
 
   /// The language version for the package that contains this file.
-  final Version _packageLanguageVersion;
+  final Version packageLanguageVersion;
 
   int id = fileObjectId++;
   int refreshId;
@@ -156,7 +156,7 @@
     this.source,
     this.workspacePackage,
     this._contextFeatureSet,
-    this._packageLanguageVersion,
+    this.packageLanguageVersion,
   ) : isInExternalSummaries = false;
 
   FileState._external(this._fsState, this.uri)
@@ -166,7 +166,7 @@
         workspacePackage = null,
         _exists = true,
         _contextFeatureSet = null,
-        _packageLanguageVersion = null {
+        packageLanguageVersion = null {
     _apiSignature = Uint8List(16);
     _libraryCycle = LibraryCycle.external();
   }
@@ -375,7 +375,7 @@
       var signature = ApiSignature();
       signature.addUint32List(_fsState._saltForUnlinked);
       signature.addFeatureSet(_contextFeatureSet);
-      signature.addLanguageVersion(_packageLanguageVersion);
+      signature.addLanguageVersion(packageLanguageVersion);
       signature.addString(_contentHash);
       signature.addBool(_exists);
       contentSignature = signature.toByteList();
@@ -510,7 +510,7 @@
     unit.lineInfo = LineInfo(const <int>[0]);
 
     unit.languageVersion = LibraryLanguageVersion(
-      package: _packageLanguageVersion,
+      package: packageLanguageVersion,
       override: null,
     );
 
@@ -561,7 +561,7 @@
       ..configureFeatures(
         featureSetForOverriding: _contextFeatureSet,
         featureSet: _contextFeatureSet.restrictToVersion(
-          _packageLanguageVersion,
+          packageLanguageVersion,
         ),
       );
     Token token = scanner.tokenize(reportScannerErrors: false);
@@ -640,7 +640,7 @@
 
     var unitImpl = unit as CompilationUnitImpl;
     unitImpl.languageVersion = LibraryLanguageVersion(
-      package: _packageLanguageVersion,
+      package: packageLanguageVersion,
       override: overrideVersion,
     );
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index 95e4972..dfcfb0d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -125,6 +125,7 @@
     for (var node in scc) {
       cycle.libraries.add(node.file);
 
+      signature.addLanguageVersion(node.file.packageLanguageVersion);
       signature.addString(node.file.uriStr);
 
       signature.addInt(node.file.libraryFiles.length);
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 31236b3..a2e9ade 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -67,6 +67,7 @@
     ElementKind kind = element.kind;
     if (kind == ElementKind.CLASS ||
         kind == ElementKind.CONSTRUCTOR ||
+        kind == ElementKind.ENUM ||
         kind == ElementKind.EXTENSION ||
         kind == ElementKind.FUNCTION_TYPE_ALIAS ||
         kind == ElementKind.SETTER) {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 57401d2..fdce821 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -4346,6 +4346,19 @@
 
   /// Return the kind of this parameter.
   ParameterKind get kind;
+
+  static void setDeclaredElement(
+    FormalParameter node,
+    ParameterElement element,
+  ) {
+    if (node is DefaultFormalParameter) {
+      setDeclaredElement(node.parameter, element);
+    } else if (node is SimpleFormalParameterImpl) {
+      node.declaredElement = element;
+    } else {
+      node.identifier.staticElement = element;
+    }
+  }
 }
 
 /// The formal parameter list of a method declaration, function declaration, or
@@ -5810,6 +5823,8 @@
   /// If this expression is both in a getter and setter context, the
   /// [AuxiliaryElements] will be set to hold onto the static element from the
   /// getter context.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   @override
   AuxiliaryElements auxiliaryElements;
 
@@ -8092,8 +8107,7 @@
   }
 
   @override
-  bool _extendsNullShorting(Expression child) =>
-      operator.type != TokenType.BANG && identical(child, operand);
+  bool _extendsNullShorting(Expression child) => identical(child, operand);
 }
 
 /// An identifier that is prefixed or an access to an object property where the
@@ -8821,6 +8835,8 @@
   /// If this expression is both in a getter and setter context, the
   /// [AuxiliaryElements] will be set to hold onto the static element from the
   /// getter context.
+  @Deprecated('Use CompoundAssignmentExpression.readElement and/or '
+      'CompoundAssignmentExpression.writeElement')
   @override
   AuxiliaryElements auxiliaryElements;
 
diff --git a/pkg/analyzer/lib/src/dart/ast/extensions.dart b/pkg/analyzer/lib/src/dart/ast/extensions.dart
index fd66ae4..0c42457 100644
--- a/pkg/analyzer/lib/src/dart/ast/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/ast/extensions.dart
@@ -5,6 +5,24 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 
+extension FormalParameterExtension on FormalParameter {
+  FormalParameter get notDefault {
+    var self = this;
+    if (self is DefaultFormalParameter) {
+      return self.parameter;
+    }
+    return self;
+  }
+
+  AstNode get typeOrSelf {
+    var self = this;
+    if (self is SimpleFormalParameter) {
+      return self.type;
+    }
+    return self;
+  }
+}
+
 extension ListOfFormalParameterExtension on List<FormalParameter> {
   Iterable<FormalParameterImpl> get asImpl {
     return cast<FormalParameterImpl>();
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index d407077..4a4bd24 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -4738,6 +4738,7 @@
         _isEqualTokens(node.leftBracket, toNode.leftBracket),
         _isEqualNodes(node.index, toNode.index),
         _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
+      // ignore: deprecated_member_use_from_same_package
       toNode.auxiliaryElements = node.auxiliaryElements;
       toNode.staticElement = node.staticElement;
       toNode.staticType = node.staticType;
@@ -5136,6 +5137,7 @@
     if (_isEqualTokens(node.token, toNode.token)) {
       toNode.staticElement = node.staticElement;
       toNode.staticType = node.staticType;
+      // ignore: deprecated_member_use_from_same_package
       toNode.auxiliaryElements = node.auxiliaryElements;
       (toNode as SimpleIdentifierImpl).tearOffTypeArgumentTypes =
           node.tearOffTypeArgumentTypes;
diff --git a/pkg/analyzer/lib/src/dart/constant/compute.dart b/pkg/analyzer/lib/src/dart/constant/compute.dart
index 81df16c..e81acbb 100644
--- a/pkg/analyzer/lib/src/dart/constant/compute.dart
+++ b/pkg/analyzer/lib/src/dart/constant/compute.dart
@@ -77,13 +77,7 @@
   }
 
   ConstantEvaluationEngine _getEvaluationEngine(_ConstantNode node) {
-    var library = node.constant.library;
-    return ConstantEvaluationEngine(
-      library.typeProvider,
-      declaredVariables,
-      typeSystem: library.typeSystem,
-      experimentStatus: experimentStatus,
-    );
+    return ConstantEvaluationEngine(declaredVariables);
   }
 
   _ConstantNode _getNode(ConstantEvaluationTarget constant) {
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index ffccab6..ad1100b 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -78,9 +78,7 @@
       : _constantUpdate2018Enabled =
             featureSet.isEnabled(Feature.constant_update_2018),
         _intType = _typeProvider.intType,
-        _evaluationEngine = ConstantEvaluationEngine(
-            _typeProvider, declaredVariables,
-            typeSystem: _typeSystem, experimentStatus: featureSet);
+        _evaluationEngine = ConstantEvaluationEngine(declaredVariables);
 
   bool get _isNonNullableByDefault => _currentLibrary.isNonNullableByDefault;
 
@@ -139,8 +137,9 @@
       ConstructorElement constructor = node.constructorName.staticElement;
       if (constructor != null) {
         ConstantVisitor constantVisitor =
-            ConstantVisitor(_evaluationEngine, _errorReporter);
+            ConstantVisitor(_evaluationEngine, _currentLibrary, _errorReporter);
         _evaluationEngine.evaluateConstructorCall(
+            _currentLibrary,
             node,
             node.argumentList.arguments,
             constructor,
@@ -406,6 +405,12 @@
     }
   }
 
+  /// Check if the object [obj] matches the type [type] according to runtime
+  /// type checking rules.
+  bool _runtimeTypeMatch(DartObjectImpl obj, DartType type) {
+    return _evaluationEngine.runtimeTypeMatch(_currentLibrary, obj, type);
+  }
+
   /// Validate that the given expression is a compile time constant. Return the
   /// value of the compile time constant, or `null` if the expression is not a
   /// compile time constant.
@@ -421,8 +426,8 @@
       _errorReporter.source,
       isNonNullableByDefault: _currentLibrary.isNonNullableByDefault,
     );
-    DartObjectImpl result =
-        expression.accept(ConstantVisitor(_evaluationEngine, subErrorReporter));
+    DartObjectImpl result = expression.accept(
+        ConstantVisitor(_evaluationEngine, _currentLibrary, subErrorReporter));
     _reportErrors(errorListener.errors, errorCode);
     return result;
   }
@@ -520,8 +525,8 @@
               _errorReporter.source,
               isNonNullableByDefault: _currentLibrary.isNonNullableByDefault,
             );
-            DartObjectImpl result = initializer
-                .accept(ConstantVisitor(_evaluationEngine, subErrorReporter));
+            DartObjectImpl result = initializer.accept(ConstantVisitor(
+                _evaluationEngine, _currentLibrary, subErrorReporter));
             if (result == null) {
               _errorReporter.reportErrorForToken(
                   CompileTimeErrorCode
@@ -789,7 +794,7 @@
   }
 
   bool _validateListExpression(Expression expression, DartObjectImpl value) {
-    if (!verifier._evaluationEngine.runtimeTypeMatch(value, listElementType)) {
+    if (!verifier._runtimeTypeMatch(value, listElementType)) {
       verifier._errorReporter.reportErrorForNode(
         CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
         expression,
@@ -866,7 +871,7 @@
     if (keyValue != null) {
       var keyType = keyValue.type;
 
-      if (!verifier._evaluationEngine.runtimeTypeMatch(keyValue, mapKeyType)) {
+      if (!verifier._runtimeTypeMatch(keyValue, mapKeyType)) {
         verifier._errorReporter.reportErrorForNode(
           CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
           keyExpression,
@@ -895,8 +900,7 @@
     }
 
     if (valueValue != null) {
-      if (!verifier._evaluationEngine
-          .runtimeTypeMatch(valueValue, mapValueType)) {
+      if (!verifier._runtimeTypeMatch(valueValue, mapValueType)) {
         verifier._errorReporter.reportErrorForNode(
           CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
           valueExpression,
@@ -944,7 +948,7 @@
   }
 
   bool _validateSetExpression(Expression expression, DartObjectImpl value) {
-    if (!verifier._evaluationEngine.runtimeTypeMatch(value, setElementType)) {
+    if (!verifier._runtimeTypeMatch(value, setElementType)) {
       verifier._errorReporter.reportErrorForNode(
         CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE,
         expression,
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index ead4938..33034f0 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -5,6 +5,7 @@
 import 'dart:collection';
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
 import 'package:analyzer/dart/ast/token.dart';
@@ -14,10 +15,8 @@
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/constant/from_environment_evaluator.dart';
 import 'package:analyzer/src/dart/constant/has_type_parameter_reference.dart';
 import 'package:analyzer/src/dart/constant/potentially_constant.dart';
@@ -63,63 +62,15 @@
   static final RegExp _PUBLIC_SYMBOL_PATTERN = RegExp(
       "^(?:$_OPERATOR_RE\$|$_PUBLIC_IDENTIFIER_RE(?:=?\$|[.](?!\$)))+?\$");
 
-  /// The type provider used to access the known types.
-  final TypeProvider typeProvider;
+  /// The set of variables declared on the command line using '-D'.
+  final DeclaredVariables _declaredVariables;
 
-  /// The type system.  This is used to guess the types of constants when their
-  /// exact value is unknown.
-  final TypeSystemImpl typeSystem;
-
-  /// The helper for evaluating variables declared on the command line
-  /// using '-D', and represented as [DeclaredVariables].
-  FromEnvironmentEvaluator _fromEnvironmentEvaluator;
-
-  /// Return the object representing the state of active experiments.
-  final ExperimentStatus experimentStatus;
-
-  /// Validator used to verify correct dependency analysis when running unit
-  /// tests.
-  final ConstantEvaluationValidator validator;
-
-  /// Initialize a newly created [ConstantEvaluationEngine].  The [typeProvider]
-  /// is used to access known types.  [_fromEnvironmentEvaluator] is the set of
-  /// variables declared on the command line using '-D'.  The [validator], if
-  /// given, is used to verify correct dependency analysis when running unit
-  /// tests.
-  ConstantEvaluationEngine(
-      TypeProvider typeProvider, DeclaredVariables declaredVariables,
-      {ConstantEvaluationValidator validator,
-      ExperimentStatus experimentStatus,
-      TypeSystem typeSystem,
-      // TODO(brianwilkerson) Remove the unused parameter `forAnalysisDriver`.
-      @deprecated bool forAnalysisDriver})
-      : typeProvider = typeProvider,
-        validator = validator ?? ConstantEvaluationValidator_ForProduction(),
-        typeSystem = typeSystem ??
-            TypeSystemImpl(
-              implicitCasts: true,
-              isNonNullableByDefault: false,
-              strictInference: false,
-              typeProvider: typeProvider,
-            ),
-        experimentStatus = experimentStatus ?? ExperimentStatus() {
-    _fromEnvironmentEvaluator = FromEnvironmentEvaluator(
-      typeSystem,
-      declaredVariables,
-    );
-  }
-
-  bool get _isNonNullableByDefault {
-    return typeSystem.isNonNullableByDefault;
-  }
-
-  DartObjectImpl get _nullObject {
-    return DartObjectImpl(
-      typeSystem,
-      typeProvider.nullType,
-      NullState.NULL_STATE,
-    );
-  }
+  /// Initialize a newly created [ConstantEvaluationEngine].
+  ///
+  /// [declaredVariables] is the set of variables declared on the command
+  /// line using '-D'.
+  ConstantEvaluationEngine(DeclaredVariables declaredVariables)
+      : _declaredVariables = declaredVariables;
 
   /// Check that the arguments to a call to fromEnvironment() are correct. The
   /// [arguments] are the AST nodes of the arguments. The [argumentValues] are
@@ -129,6 +80,7 @@
   /// "defaultValue" is always allowed to be null. Return `true` if the
   /// arguments are correct, `false` if there is an error.
   bool checkFromEnvironmentArguments(
+      LibraryElementImpl library,
       NodeList<Expression> arguments,
       List<DartObjectImpl> argumentValues,
       Map<String, DartObjectImpl> namedArgumentValues,
@@ -140,7 +92,7 @@
     if (arguments[0] is NamedExpression) {
       return false;
     }
-    if (argumentValues[0].type != typeProvider.stringType) {
+    if (argumentValues[0].type != library.typeProvider.stringType) {
       return false;
     }
     if (argumentCount == 2) {
@@ -152,7 +104,7 @@
         ParameterizedType defaultValueType =
             namedArgumentValues[_DEFAULT_VALUE_PARAM].type;
         if (!(defaultValueType == expectedDefaultValueType ||
-            defaultValueType == typeProvider.nullType)) {
+            defaultValueType == library.typeProvider.nullType)) {
           return false;
         }
       } else {
@@ -168,6 +120,7 @@
   /// values of the named arguments. Return `true` if the arguments are correct,
   /// `false` if there is an error.
   bool checkSymbolArguments(
+      LibraryElementImpl library,
       NodeList<Expression> arguments,
       List<DartObjectImpl> argumentValues,
       Map<String, DartObjectImpl> namedArgumentValues) {
@@ -177,7 +130,7 @@
     if (arguments[0] is NamedExpression) {
       return false;
     }
-    if (argumentValues[0].type != typeProvider.stringType) {
+    if (argumentValues[0].type != library.typeProvider.stringType) {
       return false;
     }
     String name = argumentValues[0].toStringValue();
@@ -186,13 +139,12 @@
 
   /// Compute the constant value associated with the given [constant].
   void computeConstantValue(ConstantEvaluationTarget constant) {
-    validator.beforeComputeValue(constant);
-
     if (constant is Element) {
       var element = constant as Element;
       constant = element.declaration as ConstantEvaluationTarget;
     }
 
+    var library = constant.library;
     if (constant is ParameterElementImpl) {
       if (constant.isOptional) {
         Expression defaultValue = constant.constantInitializer;
@@ -201,14 +153,16 @@
           ErrorReporter errorReporter = ErrorReporter(
             errorListener,
             constant.source,
-            isNonNullableByDefault: _isNonNullableByDefault,
+            isNonNullableByDefault: library.isNonNullableByDefault,
           );
-          DartObjectImpl dartObject =
-              defaultValue.accept(ConstantVisitor(this, errorReporter));
+          DartObjectImpl dartObject = defaultValue
+              .accept(ConstantVisitor(this, library, errorReporter));
           constant.evaluationResult =
               EvaluationResultImpl(dartObject, errorListener.errors);
         } else {
-          constant.evaluationResult = EvaluationResultImpl(_nullObject);
+          constant.evaluationResult = EvaluationResultImpl(
+            _nullObject(library),
+          );
         }
       }
     } else if (constant is VariableElementImpl) {
@@ -218,16 +172,16 @@
         ErrorReporter errorReporter = ErrorReporter(
           errorListener,
           constant.source,
-          isNonNullableByDefault: _isNonNullableByDefault,
+          isNonNullableByDefault: library.isNonNullableByDefault,
         );
-        DartObjectImpl dartObject =
-            constantInitializer.accept(ConstantVisitor(this, errorReporter));
+        DartObjectImpl dartObject = constantInitializer
+            .accept(ConstantVisitor(this, library, errorReporter));
         // Only check the type for truly const declarations (don't check final
         // fields with initializers, since their types may be generic.  The type
         // of the final field will be checked later, when the constructor is
         // invoked).
         if (dartObject != null && constant.isConst) {
-          if (!runtimeTypeMatch(dartObject, constant.type)) {
+          if (!runtimeTypeMatch(library, dartObject, constant.type)) {
             // TODO(brianwilkerson) This should not be reported if
             //  CompileTimeErrorCode.INVALID_ASSIGNMENT has already been
             //  reported (that is, if the static types are also wrong).
@@ -272,10 +226,12 @@
         ErrorReporter errorReporter = ErrorReporter(
           errorListener,
           constant.source,
-          isNonNullableByDefault: _isNonNullableByDefault,
+          isNonNullableByDefault: library.isNonNullableByDefault,
         );
-        ConstantVisitor constantVisitor = ConstantVisitor(this, errorReporter);
+        ConstantVisitor constantVisitor =
+            ConstantVisitor(this, library, errorReporter);
         DartObjectImpl result = evaluateConstructorCall(
+            library,
             constNode,
             constNode.arguments.arguments,
             element,
@@ -419,6 +375,7 @@
   }
 
   DartObjectImpl evaluateConstructorCall(
+      LibraryElementImpl library,
       AstNode node,
       List<Expression> arguments,
       ConstructorElement constructor,
@@ -443,7 +400,7 @@
       // circularities (e.g. "compile-time constant expression depends on
       // itself")
       return DartObjectImpl.validWithUnknownValue(
-        typeSystem,
+        library.typeSystem,
         constructor.returnType,
       );
     }
@@ -475,46 +432,57 @@
     );
 
     constructor = followConstantRedirectionChain(constructor);
-    InterfaceType definingClass = constructor.returnType;
+    InterfaceType definingType = constructor.returnType;
+    ClassElement definingClass = constructor.enclosingElement;
     if (constructor.isFactory) {
       // We couldn't find a non-factory constructor.
       // See if it's because we reached an external const factory constructor
       // that we can emulate.
       if (constructor.name == "fromEnvironment") {
         if (!checkFromEnvironmentArguments(
-            arguments, argumentValues, namedValues, definingClass)) {
+            library, arguments, argumentValues, namedValues, definingType)) {
           errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
           return null;
         }
         String variableName =
             argumentCount < 1 ? null : argumentValues[0].toStringValue();
-        if (definingClass == typeProvider.boolType) {
-          return _fromEnvironmentEvaluator.getBool2(
-              variableName, namedValues, constructor);
-        } else if (definingClass == typeProvider.intType) {
-          return _fromEnvironmentEvaluator.getInt2(
-              variableName, namedValues, constructor);
-        } else if (definingClass == typeProvider.stringType) {
-          return _fromEnvironmentEvaluator.getString2(
-              variableName, namedValues, constructor);
+        if (definingClass == library.typeProvider.boolElement) {
+          return FromEnvironmentEvaluator(
+            library.typeSystem,
+            _declaredVariables,
+          ).getBool2(variableName, namedValues, constructor);
+        } else if (definingClass == library.typeProvider.intElement) {
+          return FromEnvironmentEvaluator(
+            library.typeSystem,
+            _declaredVariables,
+          ).getInt2(variableName, namedValues, constructor);
+        } else if (definingClass == library.typeProvider.stringElement) {
+          return FromEnvironmentEvaluator(
+            library.typeSystem,
+            _declaredVariables,
+          ).getString2(variableName, namedValues, constructor);
         }
       } else if (constructor.name == 'hasEnvironment' &&
-          definingClass == typeProvider.boolType) {
+          definingClass == library.typeProvider.boolElement) {
         var name = argumentCount < 1 ? null : argumentValues[0].toStringValue();
-        return _fromEnvironmentEvaluator.hasEnvironment(name);
+        return FromEnvironmentEvaluator(
+          library.typeSystem,
+          _declaredVariables,
+        ).hasEnvironment(name);
       } else if (constructor.name == "" &&
-          definingClass == typeProvider.symbolType &&
+          definingClass == library.typeProvider.symbolElement &&
           argumentCount == 1) {
-        if (!checkSymbolArguments(arguments, argumentValues, namedValues)) {
+        if (!checkSymbolArguments(
+            library, arguments, argumentValues, namedValues)) {
           errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
           return null;
         }
         String argumentValue = argumentValues[0].toStringValue();
         return DartObjectImpl(
-          typeSystem,
-          definingClass,
+          library.typeSystem,
+          definingType,
           SymbolState(argumentValue),
         );
       }
@@ -524,10 +492,12 @@
       // In the former case, the best we can do is consider it an unknown value.
       // In the latter case, the error has already been reported, so considering
       // it an unknown value will suppress further errors.
-      return DartObjectImpl.validWithUnknownValue(typeSystem, definingClass);
+      return DartObjectImpl.validWithUnknownValue(
+        library.typeSystem,
+        definingType,
+      );
     }
     ConstructorElementImpl constructorBase = constructor.declaration;
-    validator.beforeGetConstantInitializers(constructorBase);
     List<ConstructorInitializer> initializers =
         constructorBase.constantInitializers;
     if (initializers == null) {
@@ -536,7 +506,10 @@
       // const instance using a non-const constructor, or the node we're
       // visiting is involved in a cycle).  The error has already been reported,
       // so consider it an unknown value to suppress further errors.
-      return DartObjectImpl.validWithUnknownValue(typeSystem, definingClass);
+      return DartObjectImpl.validWithUnknownValue(
+        library.typeSystem,
+        definingType,
+      );
     }
 
     var fieldMap = HashMap<String, DartObjectImpl>();
@@ -550,7 +523,7 @@
     var externalErrorReporter = ErrorReporter(
       externalErrorListener,
       constructor.source,
-      isNonNullableByDefault: _isNonNullableByDefault,
+      isNonNullableByDefault: library.isNonNullableByDefault,
     );
 
     // Start with final fields that are initialized at their declaration site.
@@ -560,8 +533,6 @@
       if ((field.isFinal || field.isConst) &&
           !field.isStatic &&
           field is ConstFieldElementImpl) {
-        validator.beforeGetFieldEvaluationResult(field);
-
         DartObjectImpl fieldValue = field.evaluationResult?.value;
 
         // It is possible that the evaluation result is null.
@@ -573,7 +544,8 @@
         // Match the value and the type.
         DartType fieldType =
             FieldMember.from(field, constructor.returnType).type;
-        if (fieldValue != null && !runtimeTypeMatch(fieldValue, fieldType)) {
+        if (fieldValue != null &&
+            !runtimeTypeMatch(library, fieldValue, fieldType)) {
           errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
               node,
@@ -607,18 +579,16 @@
       if (argumentValue == null && baseParameter is ParameterElementImpl) {
         // The parameter is an optional positional parameter for which no value
         // was provided, so use the default value.
-        validator.beforeGetParameterDefault(baseParameter);
-
         EvaluationResultImpl evaluationResult = baseParameter.evaluationResult;
         if (evaluationResult == null) {
           // No default was provided, so the default value is null.
-          argumentValue = _nullObject;
+          argumentValue = _nullObject(library);
         } else if (evaluationResult.value != null) {
           argumentValue = evaluationResult.value;
         }
       }
       if (argumentValue != null) {
-        if (!runtimeTypeMatch(argumentValue, parameter.type)) {
+        if (!runtimeTypeMatch(library, argumentValue, parameter.type)) {
           errorReporter.reportErrorForNode(
               CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
               errorTarget,
@@ -632,7 +602,7 @@
               // We've already checked that the argument can be assigned to the
               // parameter; we also need to check that it can be assigned to
               // the field.
-              if (!runtimeTypeMatch(argumentValue, fieldType)) {
+              if (!runtimeTypeMatch(library, argumentValue, fieldType)) {
                 errorReporter.reportErrorForNode(
                     CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
                     errorTarget,
@@ -653,9 +623,10 @@
     }
     ConstantVisitor initializerVisitor = ConstantVisitor(
       this,
+      constructor.library,
       externalErrorReporter,
       lexicalEnvironment: parameterMap,
-      substitution: Substitution.fromInterfaceType(definingClass),
+      substitution: Substitution.fromInterfaceType(definingType),
     );
     String superName;
     NodeList<Expression> superArguments;
@@ -672,10 +643,10 @@
                 CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
           }
           fieldMap[fieldName] = evaluationResult;
-          PropertyAccessorElement getter = definingClass.getGetter(fieldName);
+          PropertyAccessorElement getter = definingType.getGetter(fieldName);
           if (getter != null) {
             PropertyInducingElement field = getter.variable;
-            if (!runtimeTypeMatch(evaluationResult, field.type)) {
+            if (!runtimeTypeMatch(library, evaluationResult, field.type)) {
               errorReporter.reportErrorForNode(
                   CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
                   node,
@@ -698,9 +669,10 @@
         ConstructorElement constructor = initializer.staticElement;
         if (constructor != null && constructor.isConst) {
           // Instantiate the constructor with the in-scope type arguments.
-          constructor = ConstructorMember.from(constructor, definingClass);
+          constructor = ConstructorMember.from(constructor, definingType);
 
           DartObjectImpl result = evaluateConstructorCall(
+              library,
               node,
               initializer.argumentList.arguments,
               constructor,
@@ -730,7 +702,7 @@
       }
     }
     // Evaluate explicit or implicit call to super().
-    InterfaceType superclass = definingClass.superclass;
+    InterfaceType superclass = definingType.superclass;
     if (superclass != null && !superclass.isDartCoreObject) {
       ConstructorElement superConstructor =
           superclass.lookUpConstructor(superName, constructor.library);
@@ -741,7 +713,7 @@
           superConstructor = Member.legacy(superConstructor);
         }
 
-        evaluateSuperConstructorCall(node, fieldMap, superConstructor,
+        evaluateSuperConstructorCall(library, node, fieldMap, superConstructor,
             superArguments, initializerVisitor, externalErrorReporter);
       }
     }
@@ -750,13 +722,14 @@
           CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, node);
     }
     return DartObjectImpl(
-      typeSystem,
-      definingClass,
+      library.typeSystem,
+      definingType,
       GenericState(fieldMap, invocation: invocation),
     );
   }
 
   void evaluateSuperConstructorCall(
+      LibraryElementImpl library,
       AstNode node,
       Map<String, DartObjectImpl> fieldMap,
       ConstructorElement superConstructor,
@@ -764,7 +737,7 @@
       ConstantVisitor initializerVisitor,
       ErrorReporter errorReporter) {
     if (superConstructor != null && superConstructor.isConst) {
-      DartObjectImpl evaluationResult = evaluateConstructorCall(node,
+      DartObjectImpl evaluationResult = evaluateConstructorCall(library, node,
           superArguments, superConstructor, initializerVisitor, errorReporter);
       if (evaluationResult != null) {
         fieldMap[GenericState.SUPERCLASS_FIELD] = evaluationResult;
@@ -808,14 +781,16 @@
   /// compile-time constant because it references at least one of the constants
   /// in the given [cycle], each of which directly or indirectly references the
   /// constant.
-  void generateCycleError(Iterable<ConstantEvaluationTarget> cycle,
-      ConstantEvaluationTarget constant) {
+  void generateCycleError(
+    Iterable<ConstantEvaluationTarget> cycle,
+    ConstantEvaluationTarget constant,
+  ) {
     if (constant is VariableElement) {
       RecordingErrorListener errorListener = RecordingErrorListener();
       ErrorReporter errorReporter = ErrorReporter(
         errorListener,
         constant.source,
-        isNonNullableByDefault: _isNonNullableByDefault,
+        isNonNullableByDefault: constant.library.isNonNullableByDefault,
       );
       // TODO(paulberry): It would be really nice if we could extract enough
       // information from the 'cycle' argument to provide the user with a
@@ -844,6 +819,7 @@
     if (!constructor.isFactory) {
       return null;
     }
+    var typeProvider = constructor.library.typeProvider;
     if (constructor.enclosingElement == typeProvider.symbolElement) {
       // The dart:core.Symbol has a const factory constructor that redirects
       // to dart:_internal.Symbol.  That in turn redirects to an external
@@ -869,12 +845,24 @@
 
   /// Check if the object [obj] matches the type [type] according to runtime
   /// type checking rules.
-  bool runtimeTypeMatch(DartObjectImpl obj, DartType type) {
+  bool runtimeTypeMatch(
+    LibraryElementImpl library,
+    DartObjectImpl obj,
+    DartType type,
+  ) {
     if (obj.isNull) {
       return true;
     }
     var objType = obj.type;
-    return typeSystem.isSubtypeOf2(objType, type);
+    return library.typeSystem.isSubtypeOf2(objType, type);
+  }
+
+  DartObjectImpl _nullObject(LibraryElementImpl library) {
+    return DartObjectImpl(
+      library.typeSystem,
+      library.typeProvider.nullType,
+      NullState.NULL_STATE,
+    );
   }
 
   /// Determine whether the given string is a valid name for a public symbol
@@ -953,6 +941,9 @@
   /// type provider.
   final ConstantEvaluationEngine evaluationEngine;
 
+  /// The library that contains the constant expression being evaluated.
+  final LibraryElement _library;
+
   final Map<String, DartObjectImpl> _lexicalEnvironment;
   final Substitution _substitution;
 
@@ -973,25 +964,30 @@
   /// The [substitution] is specified for instance creations.
   ConstantVisitor(
     this.evaluationEngine,
+    this._library,
     this._errorReporter, {
     Map<String, DartObjectImpl> lexicalEnvironment,
     Substitution substitution,
   })  : _lexicalEnvironment = lexicalEnvironment,
         _substitution = substitution {
-    _dartObjectComputer = DartObjectComputer(_errorReporter, evaluationEngine);
+    _dartObjectComputer = DartObjectComputer(
+      _library.typeSystem,
+      _errorReporter,
+    );
   }
 
-  /// Return the object representing the state of active experiments.
-  ExperimentStatus get experimentStatus => evaluationEngine.experimentStatus;
-
   /// Convenience getter to gain access to the [evaluationEngine]'s type system.
-  TypeSystemImpl get typeSystem => evaluationEngine.typeSystem;
+  TypeSystemImpl get typeSystem => _library.typeSystem;
+
+  bool get _isEnabledConstantUpdate2018 {
+    return _library.featureSet.isEnabled(Feature.constant_update_2018);
+  }
 
   bool get _isNonNullableByDefault => typeSystem.isNonNullableByDefault;
 
   /// Convenience getter to gain access to the [evaluationEngine]'s type
   /// provider.
-  TypeProvider get _typeProvider => evaluationEngine.typeProvider;
+  TypeProvider get _typeProvider => _library.typeProvider;
 
   @override
   DartObjectImpl visitAdjacentStrings(AdjacentStrings node) {
@@ -1009,7 +1005,7 @@
 
   @override
   DartObjectImpl visitAsExpression(AsExpression node) {
-    if (experimentStatus.constant_update_2018) {
+    if (_isEnabledConstantUpdate2018) {
       DartObjectImpl expressionResult = node.expression.accept(this);
       DartObjectImpl typeResult = node.type.accept(this);
       return _dartObjectComputer.castToType(node, expressionResult, typeResult);
@@ -1031,7 +1027,7 @@
       return _dartObjectComputer.lazyOr(
           node, leftResult, () => node.rightOperand.accept(this));
     } else if (operatorType == TokenType.QUESTION_QUESTION) {
-      if (experimentStatus.constant_update_2018) {
+      if (_isEnabledConstantUpdate2018) {
         return _dartObjectComputer.lazyQuestionQuestion(
             node, leftResult, () => node.rightOperand.accept(this));
       } else {
@@ -1043,17 +1039,17 @@
     DartObjectImpl rightResult = node.rightOperand.accept(this);
     if (operatorType == TokenType.AMPERSAND) {
       return _dartObjectComputer.eagerAnd(
-          node, leftResult, rightResult, experimentStatus.constant_update_2018);
+          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
     } else if (operatorType == TokenType.BANG_EQ) {
       return _dartObjectComputer.notEqual(node, leftResult, rightResult);
     } else if (operatorType == TokenType.BAR) {
       return _dartObjectComputer.eagerOr(
-          node, leftResult, rightResult, experimentStatus.constant_update_2018);
+          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
     } else if (operatorType == TokenType.CARET) {
       return _dartObjectComputer.eagerXor(
-          node, leftResult, rightResult, experimentStatus.constant_update_2018);
+          node, leftResult, rightResult, _isEnabledConstantUpdate2018);
     } else if (operatorType == TokenType.EQ_EQ) {
-      if (experimentStatus.constant_update_2018) {
+      if (_isEnabledConstantUpdate2018) {
         return _dartObjectComputer.lazyEqualEqual(
             node, leftResult, rightResult);
       }
@@ -1106,7 +1102,7 @@
   DartObjectImpl visitConditionalExpression(ConditionalExpression node) {
     Expression condition = node.condition;
     DartObjectImpl conditionResult = condition.accept(this);
-    if (experimentStatus.constant_update_2018) {
+    if (_isEnabledConstantUpdate2018) {
       if (conditionResult == null) {
         return conditionResult;
       } else if (!conditionResult.isBool) {
@@ -1187,8 +1183,8 @@
       return null;
     }
 
-    return evaluationEngine.evaluateConstructorCall(
-        node, node.argumentList.arguments, constructor, this, _errorReporter);
+    return evaluationEngine.evaluateConstructorCall(_library, node,
+        node.argumentList.arguments, constructor, this, _errorReporter);
   }
 
   @override
@@ -1228,7 +1224,7 @@
 
   @override
   DartObjectImpl visitIsExpression(IsExpression node) {
-    if (experimentStatus.constant_update_2018) {
+    if (_isEnabledConstantUpdate2018) {
       DartObjectImpl expressionResult = node.expression.accept(this);
       DartObjectImpl typeResult = node.type.accept(this);
       return _dartObjectComputer.typeTest(node, expressionResult, typeResult);
@@ -1300,7 +1296,7 @@
 
   @override
   DartObjectImpl visitNullLiteral(NullLiteral node) {
-    return evaluationEngine._nullObject;
+    return evaluationEngine._nullObject(_library);
   }
 
   @override
@@ -1724,7 +1720,7 @@
   /// [identifier] is "length".
   bool _isStringLength(
       DartObjectImpl targetResult, SimpleIdentifier identifier) {
-    if (targetResult == null || targetResult.type != _typeProvider.stringType) {
+    if (targetResult?.type?.element != _typeProvider.stringElement) {
       return false;
     }
     return identifier.name == 'length' &&
@@ -1753,23 +1749,19 @@
     if (expressionValue != null) {
       return expressionValue;
     }
-    return evaluationEngine._nullObject;
+    return evaluationEngine._nullObject(_library);
   }
 }
 
 /// A utility class that contains methods for manipulating instances of a Dart
 /// class and for collecting errors during evaluation.
 class DartObjectComputer {
+  final TypeSystemImpl _typeSystem;
+
   /// The error reporter that we are using to collect errors.
   final ErrorReporter _errorReporter;
 
-  /// The evaluation engine used to access the type system, and type provider.
-  final ConstantEvaluationEngine _evaluationEngine;
-
-  DartObjectComputer(this._errorReporter, this._evaluationEngine);
-
-  /// Convenience getter to gain access to the [evaluationEngine]'s type system.
-  TypeSystem get _typeSystem => _evaluationEngine.typeSystem;
+  DartObjectComputer(this._typeSystem, this._errorReporter);
 
   DartObjectImpl add(BinaryExpression node, DartObjectImpl leftOperand,
       DartObjectImpl rightOperand) {
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index dcdf36e..5625a7b 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -8,6 +8,7 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/element_type_provider.dart';
 import 'package:meta/meta.dart';
 
@@ -171,8 +172,9 @@
 
   void writeTypeParameter(TypeParameterElement element) {
     if (element is TypeParameterElementImpl) {
-      if (!element.isLegacyCovariant) {
-        _write(element.variance.toKeywordString());
+      var variance = element.variance;
+      if (!element.isLegacyCovariant && variance != Variance.unrelated) {
+        _write(variance.toKeywordString());
         _write(' ');
       }
     }
@@ -188,6 +190,11 @@
   void writeTypeParameterType(TypeParameterTypeImpl type) {
     _write(type.element.displayName);
     _writeNullability(type.nullabilitySuffix);
+
+    if (type.promotedBound != null) {
+      _write(' & ');
+      _writeType(type.promotedBound);
+    }
   }
 
   void writeUnknownInferredType() {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 0dfd4db..09790fa 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -486,7 +486,13 @@
 
   ClassElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
       Reference reference, AstNode linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (linkedNode is ClassDeclaration) {
+      linkedNode.name.staticElement = this;
+    } else if (linkedNode is ClassTypeAlias) {
+      linkedNode.name.staticElement = this;
+    }
+  }
 
   @override
   List<PropertyAccessorElement> get accessors {
@@ -543,10 +549,9 @@
       _constructors = context.getConstructors(linkedNode).map((node) {
         var name = node.name?.name ?? '';
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as ConstructorElement;
-        }
-        return ConstructorElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement;
+        element ??= ConstructorElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
 
       if (_constructors.isEmpty) {
@@ -783,10 +788,9 @@
           .map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as MethodElement;
-        }
-        return MethodElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement as MethodElement;
+        element ??= MethodElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
 
@@ -856,18 +860,19 @@
   InterfaceType get supertype {
     if (_supertype != null) return _supertype;
 
+    if (hasModifier(Modifier.DART_CORE_OBJECT)) {
+      return null;
+    }
+
     if (linkedNode != null) {
-      var context = enclosingUnit.linkedContext;
-
-      var coreTypes = context.bundleContext.elementFactory.coreTypes;
-      if (identical(this, coreTypes.objectClass)) {
-        return null;
-      }
-
-      var type = context.getSuperclass(linkedNode)?.type;
+      var type = linkedContext.getSuperclass(linkedNode)?.type;
       if (_isInterfaceTypeClass(type)) {
         return _supertype = type;
       }
+      if (library.isDartCore && name == 'Object') {
+        setModifier(Modifier.DART_CORE_OBJECT, true);
+        return null;
+      }
       return _supertype = library.typeProvider.objectType;
     }
     return _supertype;
@@ -1240,9 +1245,10 @@
         super(null, -1);
 
   CompilationUnitElementImpl.forLinkedNode(LibraryElementImpl enclosingLibrary,
-      this.linkedContext, Reference reference, CompilationUnit linkedNode)
+      this.linkedContext, Reference reference, CompilationUnitImpl linkedNode)
       : super.forLinkedNode(enclosingLibrary, reference, linkedNode) {
     _nameOffset = -1;
+    linkedNode.declaredElement = this;
   }
 
   @override
@@ -1302,10 +1308,9 @@
       _enums = linkedNode.declarations.whereType<EnumDeclaration>().map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as EnumElementImpl;
-        }
-        return EnumElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement;
+        element ??= EnumElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
 
@@ -1334,13 +1339,9 @@
         if (node is ExtensionDeclaration) {
           var refName = linkedContext.getExtensionRefName(node);
           var reference = containerRef.getChild(refName);
-          if (reference.hasElementFor(node)) {
-            _extensions.add(reference.element);
-          } else {
-            _extensions.add(
-              ExtensionElementImpl.forLinkedNode(this, reference, node),
-            );
-          }
+          var element = node.declaredElement;
+          element ??= ExtensionElementImpl.forLinkedNode(this, reference, node);
+          _extensions.add(element);
         }
       }
       return _extensions;
@@ -1370,10 +1371,9 @@
           .map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as FunctionElementImpl;
-        }
-        return FunctionElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement as FunctionElement;
+        element ??= FunctionElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
     return _functions ?? const <FunctionElement>[];
@@ -1395,22 +1395,23 @@
     if (linkedNode != null) {
       CompilationUnit linkedNode = this.linkedNode;
       var containerRef = reference.getChild('@typeAlias');
-      return _typeAliases = linkedNode.declarations.where((node) {
-        return node is FunctionTypeAlias || node is GenericTypeAlias;
-      }).map((node) {
+      _typeAliases = <FunctionTypeAliasElement>[];
+      for (var node in linkedNode.declarations) {
         String name;
         if (node is FunctionTypeAlias) {
           name = node.name.name;
+        } else if (node is GenericTypeAlias) {
+          name = node.name.name;
         } else {
-          name = (node as GenericTypeAlias).name.name;
+          continue;
         }
 
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as GenericTypeAliasElementImpl;
-        }
-        return GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
-      }).toList();
+        var element = node.declaredElement as GenericTypeAliasElement;
+        element ??=
+            GenericTypeAliasElementImpl.forLinkedNode(this, reference, node);
+        _typeAliases.add(element);
+      }
     }
 
     return _typeAliases ?? const <FunctionTypeAliasElement>[];
@@ -1447,10 +1448,9 @@
       return _mixins = declarations.whereType<MixinDeclaration>().map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as MixinElementImpl;
-        }
-        return MixinElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement as MixinElementImpl;
+        element ??= MixinElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
 
@@ -1506,21 +1506,18 @@
       var containerRef = reference.getChild('@class');
       _types = <ClassElement>[];
       for (var node in linkedNode.declarations) {
-        String name;
         if (node is ClassDeclaration) {
-          name = node.name.name;
+          var name = node.name.name;
+          var reference = containerRef.getChild(name);
+          var element = node.declaredElement;
+          element ??= ClassElementImpl.forLinkedNode(this, reference, node);
+          _types.add(element);
         } else if (node is ClassTypeAlias) {
-          name = node.name.name;
-        } else {
-          continue;
-        }
-        var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          _types.add(reference.element);
-        } else {
-          _types.add(
-            ClassElementImpl.forLinkedNode(this, reference, node),
-          );
+          var name = node.name.name;
+          var reference = containerRef.getChild(name);
+          var element = node.declaredElement;
+          element ??= ClassElementImpl.forLinkedNode(this, reference, node);
+          _types.add(element);
         }
       }
       return _types;
@@ -1919,6 +1916,7 @@
 
 /// A concrete implementation of a [ConstructorElement].
 class ConstructorElementImpl extends ExecutableElementImpl
+    with ConstructorElementMixin
     implements ConstructorElement {
   /// The constructor to which this constructor is redirecting.
   ConstructorElement _redirectedConstructor;
@@ -1947,8 +1945,10 @@
   ConstructorElementImpl(String name, int offset) : super(name, offset);
 
   ConstructorElementImpl.forLinkedNode(ClassElementImpl enclosingClass,
-      Reference reference, ConstructorDeclaration linkedNode)
-      : super.forLinkedNode(enclosingClass, reference, linkedNode);
+      Reference reference, ConstructorDeclarationImpl linkedNode)
+      : super.forLinkedNode(enclosingClass, reference, linkedNode) {
+    linkedNode?.declaredElement = this;
+  }
 
   /// Return the constant initializers for this element, which will be empty if
   /// there are no initializers, or `null` if there was an error in the source.
@@ -2008,23 +2008,6 @@
   }
 
   @override
-  bool get isDefaultConstructor {
-    // unnamed
-    String name = this.name;
-    if (name != null && name.isNotEmpty) {
-      return false;
-    }
-    // no required parameters
-    for (ParameterElement parameter in parameters) {
-      if (parameter.isNotOptional) {
-        return false;
-      }
-    }
-    // OK, can be used as default constructor
-    return true;
-  }
-
-  @override
   bool get isFactory {
     if (linkedNode != null) {
       ConstructorDeclaration linkedNode = this.linkedNode;
@@ -2164,6 +2147,26 @@
   }
 }
 
+/// Common implementation for methods defined in [ConstructorElement].
+mixin ConstructorElementMixin implements ConstructorElement {
+  @override
+  bool get isDefaultConstructor {
+    // unnamed
+    var name = this.name;
+    if (name != null && name.isNotEmpty) {
+      return false;
+    }
+    // no required parameters
+    for (ParameterElement parameter in parameters) {
+      if (parameter.isNotOptional) {
+        return false;
+      }
+    }
+    // OK, can be used as default constructor
+    return true;
+  }
+}
+
 /// A [TopLevelVariableElement] for a top-level 'const' variable that has an
 /// initializer.
 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
@@ -2309,6 +2312,10 @@
   /// as being immutable.
   static const String _IMMUTABLE_VARIABLE_NAME = "immutable";
 
+  /// The name of the top-level variable used to mark an element as being
+  /// internal to its package.
+  static const String _INTERNAL_VARIABLE_NAME = "internal";
+
   /// The name of the top-level variable used to mark a constructor as being
   /// literal.
   static const String _LITERAL_VARIABLE_NAME = "literal";
@@ -2456,6 +2463,12 @@
       element.library?.name == _META_LIB_NAME;
 
   @override
+  bool get isInternal =>
+      element is PropertyAccessorElement &&
+      element.name == _INTERNAL_VARIABLE_NAME &&
+      element.library?.name == _META_LIB_NAME;
+
+  @override
   bool get isIsTest =>
       element is PropertyAccessorElement &&
       element.name == _IS_TEST_VARIABLE_NAME &&
@@ -2744,6 +2757,18 @@
   }
 
   @override
+  bool get hasInternal {
+    var metadata = this.metadata;
+    for (var i = 0; i < metadata.length; i++) {
+      var annotation = metadata[i];
+      if (annotation.isInternal) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
   bool get hasIsTest {
     var metadata = this.metadata;
     for (var i = 0; i < metadata.length; i++) {
@@ -3304,7 +3329,9 @@
 
   EnumElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
       Reference reference, EnumDeclaration linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    linkedNode.name.staticElement = this;
+  }
 
   @override
   List<PropertyAccessorElement> get accessors {
@@ -3317,11 +3344,6 @@
   }
 
   @override
-  set accessors(List<PropertyAccessorElement> accessors) {
-    super.accessors = accessors;
-  }
-
-  @override
   List<InterfaceType> get allSupertypes => <InterfaceType>[supertype];
 
   @override
@@ -3374,11 +3396,6 @@
   }
 
   @override
-  set fields(List<FieldElement> fields) {
-    super.fields = fields;
-  }
-
-  @override
   bool get hasNonFinalField => false;
 
   @override
@@ -3532,7 +3549,13 @@
   /// Initialize using the given linked node.
   ExecutableElementImpl.forLinkedNode(
       ElementImpl enclosing, Reference reference, AstNode linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    if (linkedNode is MethodDeclaration) {
+      linkedNode.name.staticElement = this;
+    } else if (linkedNode is FunctionDeclaration) {
+      linkedNode.name.staticElement = this;
+    }
+  }
 
   @override
   int get codeLength {
@@ -3834,11 +3857,6 @@
   ElementKind get kind => ElementKind.EXPORT;
 
   @override
-  set metadata(List<ElementAnnotation> metadata) {
-    super.metadata = metadata;
-  }
-
-  @override
   int get nameOffset {
     if (linkedNode != null) {
       return linkedContext.getDirectiveOffset(linkedNode);
@@ -3890,8 +3908,10 @@
 
   /// Initialize using the given linked information.
   ExtensionElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
-      Reference reference, AstNode linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      Reference reference, ExtensionDeclarationImpl linkedNode)
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    linkedNode.declaredElement = this;
+  }
 
   @override
   List<PropertyAccessorElement> get accessors {
@@ -4021,10 +4041,9 @@
           .map((node) {
         var name = node.name.name;
         var reference = containerRef.getChild(name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as MethodElement;
-        }
-        return MethodElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement as MethodElement;
+        element ??= MethodElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
     return _methods = const <MethodElement>[];
@@ -4349,7 +4368,9 @@
 
   FunctionElementImpl.forLinkedNode(ElementImpl enclosing, Reference reference,
       FunctionDeclaration linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    linkedNode.name.staticElement = this;
+  }
 
   /// Initialize a newly created function element to have no name and the given
   /// [nameOffset]. This is used for function expressions, that have no name.
@@ -4594,7 +4615,13 @@
       CompilationUnitElementImpl enclosingUnit,
       Reference reference,
       AstNode linkedNode)
-      : super.forLinkedNode(enclosingUnit, reference, linkedNode);
+      : super.forLinkedNode(enclosingUnit, reference, linkedNode) {
+    if (linkedNode is FunctionTypeAlias) {
+      linkedNode.name.staticElement = this;
+    } else {
+      (linkedNode as GenericTypeAlias).name.staticElement = this;
+    }
+  }
 
   @override
   int get codeLength {
@@ -4913,11 +4940,6 @@
   ElementKind get kind => ElementKind.IMPORT;
 
   @override
-  set metadata(List<ElementAnnotation> metadata) {
-    super.metadata = metadata;
-  }
-
-  @override
   int get nameOffset {
     if (linkedNode != null) {
       return linkedContext.getDirectiveOffset(linkedNode);
@@ -4981,11 +5003,6 @@
   }
 
   @override
-  set uri(String uri) {
-    super.uri = uri;
-  }
-
-  @override
   T accept<T>(ElementVisitor<T> visitor) => visitor.visitImportElement(this);
 
   @override
@@ -5681,7 +5698,9 @@
 
   MethodElementImpl.forLinkedNode(TypeParameterizedElementMixin enclosingClass,
       Reference reference, MethodDeclaration linkedNode)
-      : super.forLinkedNode(enclosingClass, reference, linkedNode);
+      : super.forLinkedNode(enclosingClass, reference, linkedNode) {
+    linkedNode.name.staticElement = this;
+  }
 
   @override
   MethodElement get declaration => this;
@@ -5792,7 +5811,9 @@
 
   MixinElementImpl.forLinkedNode(CompilationUnitElementImpl enclosing,
       Reference reference, MixinDeclaration linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    linkedNode.name.staticElement = this;
+  }
 
   @override
   bool get isAbstract => true;
@@ -5878,61 +5899,65 @@
   /// Indicates that the modifier 'covariant' was applied to the element.
   static const Modifier COVARIANT = Modifier('COVARIANT', 3);
 
+  /// Indicates that the class is `Object` from `dart:core`.
+  static const Modifier DART_CORE_OBJECT = Modifier('DART_CORE_OBJECT', 4);
+
   /// Indicates that the import element represents a deferred library.
-  static const Modifier DEFERRED = Modifier('DEFERRED', 4);
+  static const Modifier DEFERRED = Modifier('DEFERRED', 5);
 
   /// Indicates that a class element was defined by an enum declaration.
-  static const Modifier ENUM = Modifier('ENUM', 5);
+  static const Modifier ENUM = Modifier('ENUM', 6);
 
   /// Indicates that a class element was defined by an enum declaration.
-  static const Modifier EXTERNAL = Modifier('EXTERNAL', 6);
+  static const Modifier EXTERNAL = Modifier('EXTERNAL', 7);
 
   /// Indicates that the modifier 'factory' was applied to the element.
-  static const Modifier FACTORY = Modifier('FACTORY', 7);
+  static const Modifier FACTORY = Modifier('FACTORY', 8);
 
   /// Indicates that the modifier 'final' was applied to the element.
-  static const Modifier FINAL = Modifier('FINAL', 8);
+  static const Modifier FINAL = Modifier('FINAL', 9);
 
   /// Indicates that an executable element has a body marked as being a
   /// generator.
-  static const Modifier GENERATOR = Modifier('GENERATOR', 9);
+  static const Modifier GENERATOR = Modifier('GENERATOR', 10);
 
   /// Indicates that the pseudo-modifier 'get' was applied to the element.
-  static const Modifier GETTER = Modifier('GETTER', 10);
+  static const Modifier GETTER = Modifier('GETTER', 11);
 
   /// A flag used for libraries indicating that the defining compilation unit
   /// contains at least one import directive whose URI uses the "dart-ext"
   /// scheme.
-  static const Modifier HAS_EXT_URI = Modifier('HAS_EXT_URI', 11);
+  static const Modifier HAS_EXT_URI = Modifier('HAS_EXT_URI', 12);
 
   /// Indicates that the associated element did not have an explicit type
   /// associated with it. If the element is an [ExecutableElement], then the
   /// type being referred to is the return type.
-  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 12);
+  static const Modifier IMPLICIT_TYPE = Modifier('IMPLICIT_TYPE', 13);
 
   /// Indicates that modifier 'lazy' was applied to the element.
-  static const Modifier LATE = Modifier('LATE', 13);
+  static const Modifier LATE = Modifier('LATE', 14);
 
   /// Indicates that a class is a mixin application.
-  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 14);
+  static const Modifier MIXIN_APPLICATION = Modifier('MIXIN_APPLICATION', 15);
 
   /// Indicates that the pseudo-modifier 'set' was applied to the element.
-  static const Modifier SETTER = Modifier('SETTER', 15);
+  static const Modifier SETTER = Modifier('SETTER', 16);
 
   /// Indicates that the modifier 'static' was applied to the element.
-  static const Modifier STATIC = Modifier('STATIC', 16);
+  static const Modifier STATIC = Modifier('STATIC', 17);
 
   /// Indicates that the element does not appear in the source code but was
   /// implicitly created. For example, if a class does not define any
   /// constructors, an implicit zero-argument constructor will be created and it
   /// will be marked as being synthetic.
-  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 17);
+  static const Modifier SYNTHETIC = Modifier('SYNTHETIC', 18);
 
   static const List<Modifier> values = [
     ABSTRACT,
     ASYNCHRONOUS,
     CONST,
     COVARIANT,
+    DART_CORE_OBJECT,
     DEFERRED,
     ENUM,
     EXTERNAL,
@@ -6017,6 +6042,9 @@
   bool get hasFactory => false;
 
   @override
+  bool get hasInternal => false;
+
+  @override
   bool get hasIsTest => false;
 
   @override
@@ -6244,11 +6272,6 @@
     return super.hasImplicitType;
   }
 
-  @override
-  set hasImplicitType(bool hasImplicitType) {
-    super.hasImplicitType = hasImplicitType;
-  }
-
   bool get hasInitializer {
     return linkedNode != null && linkedContext.hasInitializer(linkedNode);
   }
@@ -6328,7 +6351,9 @@
 
   ParameterElementImpl.forLinkedNode(
       ElementImpl enclosing, Reference reference, FormalParameter linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    FormalParameterImpl.setDeclaredElement(linkedNode, this);
+  }
 
   factory ParameterElementImpl.forLinkedNodeFactory(
       ElementImpl enclosing, Reference reference, FormalParameter node) {
@@ -6402,11 +6427,6 @@
     return super.hasImplicitType;
   }
 
-  @override
-  set hasImplicitType(bool hasImplicitType) {
-    super.hasImplicitType = hasImplicitType;
-  }
-
   /// True if this parameter inherits from a covariant parameter. This happens
   /// when it overrides a method in a supertype that has a corresponding
   /// covariant parameter.
@@ -6556,10 +6576,10 @@
       return _typeParameters =
           typeParameters.typeParameters.map<TypeParameterElement>((node) {
         var reference = containerRef.getChild(node.name.name);
-        if (reference.hasElementFor(node)) {
-          return reference.element as TypeParameterElement;
-        }
-        return TypeParameterElementImpl.forLinkedNode(this, reference, node);
+        var element = node.declaredElement;
+        element ??=
+            TypeParameterElementImpl.forLinkedNode(this, reference, node);
+        return element;
       }).toList();
     }
 
@@ -6599,6 +6619,11 @@
     }
 
     return formalParameters.map((node) {
+      var element = node.declaredElement;
+      if (element != null) {
+        return element;
+      }
+
       if (node is DefaultFormalParameter) {
         NormalFormalParameter parameterNode = node.parameter;
         var name = parameterNode.identifier?.name ?? '';
@@ -6967,21 +6992,7 @@
   }
 
   @override
-  DartType get returnTypeInternal {
-    var returnType = variable.type;
-
-    // While performing inference during linking, the first step is to collect
-    // dependencies. During this step we resolve the expression, but we might
-    // reference elements that don't have their types inferred yet. So, here
-    // we give some type. A better solution would be to infer recursively, but
-    // we are not doing this yet.
-    if (returnType == null) {
-      assert(linkedContext.isLinking);
-      return DynamicTypeImpl.instance;
-    }
-
-    return returnType;
-  }
+  DartType get returnTypeInternal => variable.type;
 
   @override
   FunctionType get type => ElementTypeProvider.current.getExecutableType(this);
@@ -7138,7 +7149,19 @@
   DartType get typeInternal {
     if (linkedNode != null) {
       if (_type != null) return _type;
-      return _type = linkedContext.getType(linkedNode);
+      _type = linkedContext.getType(linkedNode);
+
+      // While performing inference during linking, the first step is to collect
+      // dependencies. During this step we resolve the expression, but we might
+      // reference elements that don't have their types inferred yet. So, here
+      // we give some type. A better solution would be to infer recursively, but
+      // we are not doing this yet.
+      if (_type == null) {
+        assert(linkedContext.isLinking);
+        return DynamicTypeImpl.instance;
+      }
+
+      return _type;
     }
     if (isSynthetic && _type == null) {
       if (getter != null) {
@@ -7338,7 +7361,9 @@
 
   TypeParameterElementImpl.forLinkedNode(
       ElementImpl enclosing, Reference reference, TypeParameter linkedNode)
-      : super.forLinkedNode(enclosing, reference, linkedNode);
+      : super.forLinkedNode(enclosing, reference, linkedNode) {
+    linkedNode.name.staticElement = this;
+  }
 
   /// Initialize a newly created synthetic type parameter element to have the
   /// given [name], and with [synthetic] set to true.
@@ -7434,10 +7459,7 @@
     if (_variance != null) return _variance;
 
     if (linkedNode != null) {
-      var varianceKeyword = linkedContext.getTypeParameterVariance(linkedNode);
-      if (varianceKeyword != null) {
-        _variance = Variance.fromKeywordString(varianceKeyword.lexeme);
-      }
+      _variance = linkedContext.getTypeParameterVariance(linkedNode);
     }
 
     return _variance ?? Variance.covariant;
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index 641f80f..f778aef 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
 import 'package:analyzer/src/dart/element/type_constraint_gatherer.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/error/codes.dart'
@@ -477,9 +476,12 @@
   void _nonNullifyTypes(List<DartType> types) {
     if (_typeSystem.isNonNullableByDefault) {
       for (var i = 0; i < types.length; i++) {
-        types[i] = nonNullifyType(_typeSystem, types[i]);
+        types[i] = _typeSystem.nonNullifyLegacy(types[i]);
       }
     }
+    for (var i = 0; i < types.length; i++) {
+      types[i] = _typeSystem.demoteType(types[i]);
+    }
   }
 
   /// If in a legacy library, return the legacy version of the [type].
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index c713b70..2cb1bde 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -439,8 +439,6 @@
     );
   }
 
-  InterfaceType get _objectType => _typeSystem.typeProvider.objectType;
-
   /// Compute the least upper bound of two types.
   ///
   /// https://github.com/dart-lang/language
@@ -669,10 +667,19 @@
       return _functionType(T1, T2);
     }
 
-    // UP(T Function<...>(...), T2) = Object
-    // UP(T1, T Function<...>(...)) = Object
-    if (T1 is FunctionType || T2 is FunctionType) {
-      return _typeSystem.objectNone;
+    // UP(T Function<...>(...), T2) = UP(Object, T2)
+    if (T1 is FunctionType) {
+      return getLeastUpperBound(_typeSystem.objectNone, T2);
+    }
+
+    // UP(T1, T Function<...>(...)) = UP(T1, Object)
+    if (T2 is FunctionType) {
+      return getLeastUpperBound(T1, _typeSystem.objectNone);
+    }
+
+    var futureOrResult = _futureOr(T1, T2);
+    if (futureOrResult != null) {
+      return futureOrResult;
     }
 
     // UP(T1, T2) = T2 if T1 <: T2
@@ -804,13 +811,70 @@
     );
   }
 
+  DartType _futureOr(DartType T1, DartType T2) {
+    var T1_futureOr = T1 is InterfaceType && T1.isDartAsyncFutureOr
+        ? T1.typeArguments[0]
+        : null;
+
+    var T1_future = T1 is InterfaceType && T1.isDartAsyncFuture
+        ? T1.typeArguments[0]
+        : null;
+
+    var T2_futureOr = T2 is InterfaceType && T2.isDartAsyncFutureOr
+        ? T2.typeArguments[0]
+        : null;
+
+    var T2_future = T2 is InterfaceType && T2.isDartAsyncFuture
+        ? T2.typeArguments[0]
+        : null;
+
+    // UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (T1_futureOr != null && T2_futureOr != null) {
+      var T3 = getLeastUpperBound(T1_futureOr, T2_futureOr);
+      return _typeSystem.typeProvider.futureOrType2(T3);
+    }
+
+    // UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (T1_future != null && T2_futureOr != null) {
+      var T3 = getLeastUpperBound(T1_future, T2_futureOr);
+      return _typeSystem.typeProvider.futureOrType2(T3);
+    }
+
+    // UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (T1_futureOr != null && T2_future != null) {
+      var T3 = getLeastUpperBound(T1_futureOr, T2_future);
+      return _typeSystem.typeProvider.futureOrType2(T3);
+    }
+
+    // UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (T2_futureOr != null) {
+      var T3 = getLeastUpperBound(T1, T2_futureOr);
+      return _typeSystem.typeProvider.futureOrType2(T3);
+    }
+
+    // UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (T1_futureOr != null) {
+      var T3 = getLeastUpperBound(T1_futureOr, T2);
+      return _typeSystem.typeProvider.futureOrType2(T3);
+    }
+
+    return null;
+  }
+
   DartType _parameterType(ParameterElement a, ParameterElement b) {
     return _typeSystem.getGreatestLowerBound(a.type, b.type);
   }
 
+  /// TODO(scheglov) Use greatest closure.
+  /// See https://github.com/dart-lang/language/pull/1195
   DartType _typeParameterResolveToObjectBounds(DartType type) {
     var element = type.element;
-    type = type.resolveToBound(_objectType);
-    return Substitution.fromMap({element: _objectType}).substituteType(type);
+
+    var objectType = _typeSystem.isNonNullableByDefault
+        ? _typeSystem.objectQuestion
+        : _typeSystem.objectStar;
+
+    type = type.resolveToBound(objectType);
+    return Substitution.fromMap({element: objectType}).substituteType(type);
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 29c863b..db5240f 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -7,10 +7,12 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/display_string_builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -19,14 +21,17 @@
 
 /// A constructor element defined in a parameterized type where the values of
 /// the type parameters are known.
-class ConstructorMember extends ExecutableMember implements ConstructorElement {
+class ConstructorMember extends ExecutableMember
+    with ConstructorElementMixin
+    implements ConstructorElement {
   /// Initialize a newly created element to represent a constructor, based on
   /// the [declaration], and applied [substitution].
   ConstructorMember(
+    TypeProviderImpl typeProvider,
     ConstructorElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
-  ) : super(declaration, substitution, isLegacy,
+  ) : super(typeProvider, declaration, substitution, isLegacy,
             const <TypeParameterElement>[]);
 
   @deprecated
@@ -46,9 +51,6 @@
   bool get isConstantEvaluated => declaration.isConstantEvaluated;
 
   @override
-  bool get isDefaultConstructor => declaration.isDefaultConstructor;
-
-  @override
   bool get isFactory => declaration.isFactory;
 
   @override
@@ -80,7 +82,7 @@
       substitution = _substitution;
     }
 
-    return ConstructorMember(declaration, substitution, false);
+    return ConstructorMember(_typeProvider, declaration, substitution, false);
   }
 
   @override
@@ -119,6 +121,7 @@
     }
 
     return ConstructorMember(
+      constructor.library.typeProvider,
       constructor,
       Substitution.fromInterfaceType(definingType),
       isLegacy,
@@ -142,11 +145,12 @@
   /// their bounds.  The [substitution] includes replacing [declaration] type
   /// parameters with the provided fresh [typeParameters].
   ExecutableMember(
+    TypeProviderImpl typeProvider,
     ExecutableElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
     this.typeParameters,
-  ) : super(declaration, substitution, isLegacy);
+  ) : super(typeProvider, declaration, substitution, isLegacy);
 
   @deprecated
   @override
@@ -186,9 +190,10 @@
   List<ParameterElement> get parameters {
     return declaration.parameters.map<ParameterElement>((p) {
       if (p is FieldFormalParameterElement) {
-        return FieldFormalParameterMember(p, _substitution, isLegacy);
+        return FieldFormalParameterMember(
+            _typeProvider, p, _substitution, isLegacy);
       }
-      return ParameterMember(p, _substitution, isLegacy);
+      return ParameterMember(_typeProvider, p, _substitution, isLegacy);
     }).toList();
   }
 
@@ -223,11 +228,13 @@
       return null;
     }
 
+    TypeProvider typeProvider;
     var isLegacy = false;
     var combined = substitution;
     if (element is ExecutableMember) {
       ExecutableMember member = element;
       element = member.declaration;
+      typeProvider = member._typeProvider;
 
       isLegacy = member.isLegacy;
 
@@ -237,6 +244,8 @@
       }
       map.addAll(substitution.map);
       combined = Substitution.fromMap(map);
+    } else {
+      typeProvider = element.library.typeProvider;
     }
 
     if (!isLegacy && combined.map.isEmpty) {
@@ -244,11 +253,11 @@
     }
 
     if (element is ConstructorElement) {
-      return ConstructorMember(element, combined, isLegacy);
+      return ConstructorMember(typeProvider, element, combined, isLegacy);
     } else if (element is MethodElement) {
-      return MethodMember(element, combined, isLegacy);
+      return MethodMember(typeProvider, element, combined, isLegacy);
     } else if (element is PropertyAccessorElement) {
-      return PropertyAccessorMember(element, combined, isLegacy);
+      return PropertyAccessorMember(typeProvider, element, combined, isLegacy);
     } else {
       throw UnimplementedError('(${element.runtimeType}) $element');
     }
@@ -260,6 +269,7 @@
 class FieldFormalParameterMember extends ParameterMember
     implements FieldFormalParameterElement {
   factory FieldFormalParameterMember(
+    TypeProviderImpl typeProvider,
     FieldFormalParameterElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
@@ -269,6 +279,7 @@
       substitution,
     );
     return FieldFormalParameterMember._(
+      typeProvider,
       declaration,
       freshTypeParameters.substitution,
       isLegacy,
@@ -277,11 +288,18 @@
   }
 
   FieldFormalParameterMember._(
+    TypeProviderImpl typeProvider,
     FieldFormalParameterElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
     List<TypeParameterElement> typeParameters,
-  ) : super._(declaration, substitution, isLegacy, typeParameters);
+  ) : super._(
+          typeProvider,
+          declaration,
+          substitution,
+          isLegacy,
+          typeParameters,
+        );
 
   @override
   FieldElement get field {
@@ -290,7 +308,7 @@
       return null;
     }
 
-    return FieldMember(field, _substitution, isLegacy);
+    return FieldMember(_typeProvider, field, _substitution, isLegacy);
   }
 
   @override
@@ -310,10 +328,11 @@
   /// Initialize a newly created element to represent a field, based on the
   /// [declaration], with applied [substitution].
   FieldMember(
+    TypeProviderImpl typeProvider,
     FieldElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
-  ) : super(declaration, substitution, isLegacy);
+  ) : super(typeProvider, declaration, substitution, isLegacy);
 
   @deprecated
   @override
@@ -331,7 +350,8 @@
     if (baseGetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseGetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseGetter, _substitution, isLegacy);
   }
 
   @override
@@ -355,7 +375,8 @@
     if (baseSetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseSetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseSetter, _substitution, isLegacy);
   }
 
   @override
@@ -371,6 +392,7 @@
       return field;
     }
     return FieldMember(
+      field.library.typeProvider,
       field,
       Substitution.fromInterfaceType(definingType),
       false,
@@ -384,13 +406,16 @@
     if (substitution.map.isEmpty) {
       return element;
     }
-    return FieldMember(element, substitution, false);
+    var typeProvider = element.library.typeProvider;
+    return FieldMember(typeProvider, element, substitution, false);
   }
 }
 
 class FunctionMember extends ExecutableMember implements FunctionElement {
-  FunctionMember(FunctionElement declaration, bool isLegacy)
+  FunctionMember(
+      TypeProviderImpl typeProvider, FunctionElement declaration, bool isLegacy)
       : super(
+          typeProvider,
           declaration,
           Substitution.empty,
           isLegacy,
@@ -412,6 +437,9 @@
 /// An element defined in a parameterized type where the values of the type
 /// parameters are known.
 abstract class Member implements Element {
+  /// A type provider (might be legacy, might be null-safe).
+  final TypeProviderImpl _typeProvider;
+
   /// The element on which the parameterized element was created.
   final Element _declaration;
 
@@ -423,7 +451,8 @@
 
   /// Initialize a newly created element to represent a member, based on the
   /// [declaration], and applied [_substitution].
-  Member(this._declaration, this._substitution, this.isLegacy) {
+  Member(this._typeProvider, this._declaration, this._substitution,
+      this.isLegacy) {
     if (_declaration is Member) {
       throw StateError('Members must be created from a declarations.');
     }
@@ -461,6 +490,9 @@
   bool get hasFactory => _declaration.hasFactory;
 
   @override
+  bool get hasInternal => _declaration.hasInternal;
+
+  @override
   bool get hasIsTest => _declaration.hasIsTest;
 
   @override
@@ -597,8 +629,7 @@
   /// Otherwise, return the type unchanged.
   DartType _toLegacyType(DartType type) {
     if (isLegacy) {
-      var typeProvider = declaration.library.typeProvider;
-      return NullabilityEliminator.perform(typeProvider, type);
+      return NullabilityEliminator.perform(_typeProvider, type);
     } else {
       return type;
     }
@@ -615,18 +646,24 @@
       } else if (element is Member) {
         var member = element as Member;
         return ConstructorMember(
+          member._typeProvider,
           member._declaration,
           member._substitution,
           true,
         );
       } else {
-        return ConstructorMember(element, Substitution.empty, true);
+        var typeProvider = element.library.typeProvider;
+        return ConstructorMember(
+            typeProvider, element, Substitution.empty, true);
       }
     } else if (element is FunctionElement) {
       if (!element.library.isNonNullableByDefault) {
         return element;
       } else {
-        return FunctionMember(element.declaration, true);
+        var typeProvider = element is Member
+            ? (element as Member)._typeProvider
+            : element.library.typeProvider;
+        return FunctionMember(typeProvider, element.declaration, true);
       }
     } else if (element is MethodElement) {
       if (!element.library.isNonNullableByDefault) {
@@ -634,12 +671,14 @@
       } else if (element is Member) {
         var member = element as Member;
         return MethodMember(
+          member._typeProvider,
           member._declaration,
           member._substitution,
           true,
         );
       } else {
-        return MethodMember(element, Substitution.empty, true);
+        var typeProvider = element.library.typeProvider;
+        return MethodMember(typeProvider, element, Substitution.empty, true);
       }
     } else if (element is PropertyAccessorElement) {
       if (!element.library.isNonNullableByDefault) {
@@ -647,12 +686,15 @@
       } else if (element is Member) {
         var member = element as Member;
         return PropertyAccessorMember(
+          member._typeProvider,
           member._declaration,
           member._substitution,
           true,
         );
       } else {
-        return PropertyAccessorMember(element, Substitution.empty, true);
+        var typeProvider = element.library.typeProvider;
+        return PropertyAccessorMember(
+            typeProvider, element, Substitution.empty, true);
       }
     } else {
       return element;
@@ -664,6 +706,7 @@
 /// type parameters are known.
 class MethodMember extends ExecutableMember implements MethodElement {
   factory MethodMember(
+    TypeProviderImpl typeProvider,
     MethodElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
@@ -673,6 +716,7 @@
       substitution,
     );
     return MethodMember._(
+      typeProvider,
       declaration,
       freshTypeParameters.substitution,
       isLegacy,
@@ -681,11 +725,12 @@
   }
 
   MethodMember._(
+    TypeProviderImpl typeProvider,
     MethodElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
     List<TypeParameterElement> typeParameters,
-  ) : super(declaration, substitution, isLegacy, typeParameters);
+  ) : super(typeProvider, declaration, substitution, isLegacy, typeParameters);
 
   @deprecated
   @override
@@ -710,7 +755,9 @@
       return method;
     }
 
+    var typeProvider = method.library.typeProvider;
     return MethodMember(
+      typeProvider,
       method,
       Substitution.fromInterfaceType(definingType),
       false,
@@ -724,7 +771,8 @@
     if (substitution.map.isEmpty) {
       return element;
     }
-    return MethodMember(element, substitution, false);
+    var typeProvider = element.library.typeProvider;
+    return MethodMember(typeProvider, element, substitution, false);
   }
 }
 
@@ -737,6 +785,7 @@
   final List<TypeParameterElement> typeParameters;
 
   factory ParameterMember(
+    TypeProviderImpl typeProvider,
     ParameterElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
@@ -746,6 +795,7 @@
       substitution,
     );
     return ParameterMember._(
+      typeProvider,
       declaration,
       freshTypeParameters.substitution,
       isLegacy,
@@ -756,11 +806,12 @@
   /// Initialize a newly created element to represent a parameter, based on the
   /// [declaration], with applied [substitution].
   ParameterMember._(
+    TypeProviderImpl typeProvider,
     ParameterElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
     this.typeParameters,
-  ) : super(declaration, substitution, isLegacy);
+  ) : super(typeProvider, declaration, substitution, isLegacy);
 
   @deprecated
   @override
@@ -787,25 +838,15 @@
   @override
   bool get isInitializingFormal => declaration.isInitializingFormal;
 
-  @override
-  bool get isOptionalNamed {
-    if (isLegacy) {
-      return super.isNamed;
-    }
-    return super.isOptionalNamed;
-  }
-
-  @override
-  bool get isRequiredNamed {
-    if (isLegacy) {
-      return false;
-    }
-    return super.isRequiredNamed;
-  }
-
   @deprecated
   @override
-  ParameterKind get parameterKind => declaration.parameterKind;
+  ParameterKind get parameterKind {
+    var kind = declaration.parameterKind;
+    if (isLegacy && kind == ParameterKind.NAMED_REQUIRED) {
+      return ParameterKind.NAMED;
+    }
+    return kind;
+  }
 
   @override
   List<ParameterElement> get parameters {
@@ -836,6 +877,7 @@
 class PropertyAccessorMember extends ExecutableMember
     implements PropertyAccessorElement {
   factory PropertyAccessorMember(
+    TypeProviderImpl typeProvider,
     PropertyAccessorElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
@@ -845,6 +887,7 @@
       substitution,
     );
     return PropertyAccessorMember._(
+      typeProvider,
       declaration,
       freshTypeParameters.substitution,
       isLegacy,
@@ -853,11 +896,12 @@
   }
 
   PropertyAccessorMember._(
+    TypeProviderImpl typeProvider,
     PropertyAccessorElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
     List<TypeParameterElement> typeParameters,
-  ) : super(declaration, substitution, isLegacy, typeParameters);
+  ) : super(typeProvider, declaration, substitution, isLegacy, typeParameters);
 
   @deprecated
   @override
@@ -869,7 +913,8 @@
     if (baseGetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseGetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseGetter, _substitution, isLegacy);
   }
 
   @override
@@ -878,7 +923,8 @@
     if (baseSetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseSetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseSetter, _substitution, isLegacy);
   }
 
   @override
@@ -899,9 +945,10 @@
     // TODO
     PropertyInducingElement variable = declaration.variable;
     if (variable is FieldElement) {
-      return FieldMember(variable, _substitution, isLegacy);
+      return FieldMember(_typeProvider, variable, _substitution, isLegacy);
     } else if (variable is TopLevelVariableElement) {
-      return TopLevelVariableMember(variable, _substitution, isLegacy);
+      return TopLevelVariableMember(
+          _typeProvider, variable, _substitution, isLegacy);
     }
     return variable;
   }
@@ -929,7 +976,9 @@
       return accessor;
     }
 
+    var typeProvider = accessor.library.typeProvider;
     return PropertyAccessorMember(
+      typeProvider,
       accessor,
       Substitution.fromInterfaceType(definingType),
       false,
@@ -940,10 +989,11 @@
 class TopLevelVariableMember extends VariableMember
     implements TopLevelVariableElement {
   TopLevelVariableMember(
+    TypeProviderImpl typeProvider,
     VariableElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
-  ) : super(declaration, substitution, isLegacy);
+  ) : super(typeProvider, declaration, substitution, isLegacy);
 
   @override
   TopLevelVariableElement get declaration => _declaration;
@@ -954,7 +1004,8 @@
     if (baseGetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseGetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseGetter, _substitution, isLegacy);
   }
 
   @override
@@ -969,7 +1020,8 @@
     if (baseSetter == null) {
       return null;
     }
-    return PropertyAccessorMember(baseSetter, _substitution, isLegacy);
+    return PropertyAccessorMember(
+        _typeProvider, baseSetter, _substitution, isLegacy);
   }
 
   @override
@@ -986,10 +1038,11 @@
   /// Initialize a newly created element to represent a variable, based on the
   /// [declaration], with applied [substitution].
   VariableMember(
+    TypeProviderImpl typeProvider,
     VariableElement declaration,
     MapSubstitution substitution,
     bool isLegacy,
-  ) : super(declaration, substitution, isLegacy);
+  ) : super(typeProvider, declaration, substitution, isLegacy);
 
   @deprecated
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
index 7e5e457..5dd6961 100644
--- a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/replacement_visitor.dart';
+import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:meta/meta.dart';
 
@@ -54,6 +55,16 @@
   }
 
   @override
+  DartType visitTypeParameterType(TypeParameterType type) {
+    if (!_isCovariant && _typeSystem.isNonNullableByDefault) {
+      if (_typeSystem.isSubtypeOf2(type, NeverTypeImpl.instance)) {
+        return _typeSystem.objectQuestion;
+      }
+    }
+    return null;
+  }
+
+  @override
   DartType visitVoidType(VoidType type) {
     return _isCovariant ? _bottomType : null;
   }
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index c550ccd..c90174a 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -13,18 +13,24 @@
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_visitor.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
 import 'package:meta/meta.dart';
 
 /// Helper visitor that clones a type if a nested type is replaced, and
 /// otherwise returns `null`.
 class ReplacementVisitor
-    implements TypeVisitor<DartType>, InferenceTypeVisitor<DartType> {
+    implements
+        TypeVisitor<DartType>,
+        InferenceTypeVisitor<DartType>,
+        LinkingTypeVisitor<DartType> {
   const ReplacementVisitor();
 
   void changeVariance() {}
 
   DartType createFunctionType({
     @required FunctionType type,
+    @required List<DartType> newTypeArguments,
     @required List<TypeParameterElement> newTypeParameters,
     @required List<ParameterElement> newParameters,
     @required DartType newReturnType,
@@ -41,6 +47,29 @@
       parameters: newParameters ?? type.parameters,
       returnType: newReturnType ?? type.returnType,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
+      element: type.element,
+      typeArguments: newTypeArguments ?? type.typeArguments,
+    );
+  }
+
+  DartType createFunctionTypeBuilder({
+    @required FunctionTypeBuilder type,
+    @required List<TypeParameterElement> newTypeParameters,
+    @required List<ParameterElement> newParameters,
+    @required DartType newReturnType,
+    @required NullabilitySuffix newNullability,
+  }) {
+    if (newNullability == null &&
+        newReturnType == null &&
+        newParameters == null) {
+      return null;
+    }
+
+    return FunctionTypeBuilder(
+      newTypeParameters ?? type.typeFormals,
+      newParameters ?? type.parameters,
+      newReturnType ?? type.returnType,
+      newNullability ?? type.nullabilitySuffix,
     );
   }
 
@@ -60,6 +89,23 @@
     );
   }
 
+  NamedTypeBuilder createNamedTypeBuilder({
+    @required NamedTypeBuilder type,
+    @required List<DartType> newTypeArguments,
+    @required NullabilitySuffix newNullability,
+  }) {
+    if (newTypeArguments == null && newNullability == null) {
+      return null;
+    }
+
+    return NamedTypeBuilder(
+      type.typeSystem,
+      type.element,
+      newTypeArguments ?? type.arguments,
+      newNullability ?? type.nullabilitySuffix,
+    );
+  }
+
   DartType createNeverType({
     @required NeverTypeImpl type,
     @required NullabilitySuffix newNullability,
@@ -160,6 +206,15 @@
 
     var newReturnType = visitType(node.returnType);
 
+    List<DartType> newTypeArguments;
+    for (var i = 0; i < node.typeArguments.length; i++) {
+      var substitution = node.typeArguments[i].accept(this);
+      if (substitution != null) {
+        newTypeArguments ??= node.typeArguments.toList(growable: false);
+        newTypeArguments[i] = substitution;
+      }
+    }
+
     changeVariance();
 
     List<ParameterElement> newParameters;
@@ -186,6 +241,93 @@
 
     return createFunctionType(
       type: node,
+      newTypeArguments: newTypeArguments,
+      newTypeParameters: newTypeParameters,
+      newParameters: newParameters,
+      newReturnType: newReturnType,
+      newNullability: newNullability,
+    );
+  }
+
+  @override
+  DartType visitFunctionTypeBuilder(FunctionTypeBuilder node) {
+    var newNullability = visitNullability(node);
+
+    List<TypeParameterElement> newTypeParameters;
+    for (var i = 0; i < node.typeFormals.length; i++) {
+      var typeParameter = node.typeFormals[i];
+      var bound = typeParameter.bound;
+      if (bound != null) {
+        var newBound = bound.accept(this);
+        if (newBound != null) {
+          newTypeParameters ??= node.typeFormals.toList(growable: false);
+          newTypeParameters[i] = TypeParameterElementImpl.synthetic(
+            typeParameter.name,
+          )..bound = newBound;
+        }
+      }
+    }
+
+    Substitution substitution;
+    if (newTypeParameters != null) {
+      var map = <TypeParameterElement, DartType>{};
+      for (var i = 0; i < newTypeParameters.length; ++i) {
+        var typeParameter = node.typeFormals[i];
+        var newTypeParameter = newTypeParameters[i];
+        map[typeParameter] = newTypeParameter.instantiate(
+          nullabilitySuffix: NullabilitySuffix.none,
+        );
+      }
+
+      substitution = Substitution.fromMap(map);
+
+      for (var i = 0; i < newTypeParameters.length; i++) {
+        var newTypeParameter = newTypeParameters[i];
+        var bound = newTypeParameter.bound;
+        if (bound != null) {
+          var newBound = substitution.substituteType(bound);
+          (newTypeParameter as TypeParameterElementImpl).bound = newBound;
+        }
+      }
+    }
+
+    DartType visitType(DartType type) {
+      if (type == null) return null;
+      var result = type.accept(this);
+      if (substitution != null) {
+        result = substitution.substituteType(result ?? type);
+      }
+      return result;
+    }
+
+    var newReturnType = visitType(node.returnType);
+
+    changeVariance();
+
+    List<ParameterElement> newParameters;
+    for (var i = 0; i < node.parameters.length; i++) {
+      var parameter = node.parameters[i];
+
+      var type = parameter.type;
+      var newType = visitType(type);
+
+      // ignore: deprecated_member_use_from_same_package
+      var kind = parameter.parameterKind;
+      var newKind = visitParameterKind(kind);
+
+      if (newType != null || newKind != null) {
+        newParameters ??= node.parameters.toList(growable: false);
+        newParameters[i] = parameter.copyWith(
+          type: newType,
+          kind: newKind,
+        );
+      }
+    }
+
+    changeVariance();
+
+    return createFunctionTypeBuilder(
+      type: node,
       newTypeParameters: newTypeParameters,
       newParameters: newParameters,
       newReturnType: newReturnType,
@@ -197,14 +339,10 @@
   DartType visitInterfaceType(InterfaceType type) {
     var newNullability = visitNullability(type);
 
-    List<DartType> newTypeArguments;
-    for (var i = 0; i < type.typeArguments.length; i++) {
-      var substitution = type.typeArguments[i].accept(this);
-      if (substitution != null) {
-        newTypeArguments ??= type.typeArguments.toList(growable: false);
-        newTypeArguments[i] = substitution;
-      }
-    }
+    var newTypeArguments = _typeArguments(
+      type.element.typeParameters,
+      type.typeArguments,
+    );
 
     return createInterfaceType(
       type: type,
@@ -214,6 +352,26 @@
   }
 
   @override
+  DartType visitNamedTypeBuilder(NamedTypeBuilder type) {
+    var newNullability = visitNullability(type);
+
+    var parameters = const <TypeParameterElement>[];
+    var element = type.element;
+    if (element is ClassElement) {
+      parameters = element.typeParameters;
+    } else if (element is FunctionTypeAliasElement) {
+      parameters = element.typeParameters;
+    }
+
+    var newArguments = _typeArguments(parameters, type.arguments);
+    return createNamedTypeBuilder(
+      type: type,
+      newTypeArguments: newArguments,
+      newNullability: newNullability,
+    );
+  }
+
+  @override
   DartType visitNeverType(NeverType type) {
     var newNullability = visitNullability(type);
 
@@ -231,6 +389,11 @@
     return null;
   }
 
+  DartType visitTypeArgument(
+      TypeParameterElement parameter, DartType argument) {
+    return argument.accept(this);
+  }
+
   @override
   DartType visitTypeParameterType(TypeParameterType type) {
     var newNullability = visitNullability(type);
@@ -260,4 +423,28 @@
   DartType visitVoidType(VoidType type) {
     return null;
   }
+
+  List<DartType> _typeArguments(
+    List<TypeParameterElement> parameters,
+    List<DartType> arguments,
+  ) {
+    if (arguments == null) {
+      return null;
+    }
+
+    if (arguments.length != parameters.length) {
+      return null;
+    }
+
+    List<DartType> newArguments;
+    for (var i = 0; i < arguments.length; i++) {
+      var substitution = visitTypeArgument(parameters[i], arguments[i]);
+      if (substitution != null) {
+        newArguments ??= arguments.toList(growable: false);
+        newArguments[i] = substitution;
+      }
+    }
+
+    return newArguments;
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index fa08358..d04ddfa 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -184,12 +184,16 @@
   final Map<String, Element> _getters = {};
   final Map<String, Element> _setters = {};
   final Set<ExtensionElement> _extensions = {};
+  LibraryElement _deferredLibrary;
 
   PrefixScope(this._library, PrefixElement prefix) {
     for (var import in _library.imports) {
       if (import.prefix == prefix) {
         var elements = impl.NamespaceBuilder().getImportedElements(import);
         elements.forEach(_add);
+        if (import.isDeferred) {
+          _deferredLibrary ??= import.importedLibrary;
+        }
       }
     }
   }
@@ -203,6 +207,10 @@
 
   @override
   ScopeLookupResult lookup2(String id) {
+    if (_deferredLibrary != null && id == FunctionElement.LOAD_LIBRARY_NAME) {
+      return ScopeLookupResult(_deferredLibrary.loadLibraryFunction, null);
+    }
+
     var getter = _getters[id];
     var setter = _setters[id];
     return ScopeLookupResult(getter, setter);
diff --git a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
index 21cdd9c..c3040b2 100644
--- a/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_constraint_gatherer.dart
@@ -139,8 +139,19 @@
 
     // If `Q` is a legacy type `Q0*` then the match holds under constraint
     // set `C`:
-    //   Only if `P` is a subtype match for `Q?` under constraint set `C`.
     if (Q_nullability == NullabilitySuffix.star) {
+      // If `P` is `dynamic` or `void` and `P` is a subtype match
+      // for `Q0` under constraint set `C`.
+      if (identical(P, DynamicTypeImpl.instance) ||
+          identical(P, VoidTypeImpl.instance)) {
+        var rewind = _constraints.length;
+        var Q0 = (Q as TypeImpl).withNullability(NullabilitySuffix.none);
+        if (trySubtypeMatch(P, Q0, leftSchema)) {
+          return true;
+        }
+        _constraints.length = rewind;
+      }
+      // Or if `P` is a subtype match for `Q0?` under constraint set `C`.
       var Qq = (Q as TypeImpl).withNullability(NullabilitySuffix.question);
       return trySubtypeMatch(P, Qq, leftSchema);
     }
@@ -201,6 +212,16 @@
         _constraints.length = rewind;
       }
 
+      // Or if `P` is `dynamic` or `void` and `Object` is a subtype match
+      // for `Q0` under constraint set `C`.
+      if (identical(P, DynamicTypeImpl.instance) ||
+          identical(P, VoidTypeImpl.instance)) {
+        if (trySubtypeMatch(_typeSystem.objectNone, Q0, leftSchema)) {
+          return true;
+        }
+        _constraints.length = rewind;
+      }
+
       // Or if `P` is a subtype match for `Q0` under non-empty
       // constraint set `C`.
       var P_matches_Q0 = trySubtypeMatch(P, Q0, leftSchema);
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
index 581f22b..9421190 100644
--- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -2,55 +2,23 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE.md file.
 
-import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/dart/element/type_visitor.dart';
 import 'package:analyzer/src/dart/element/replacement_visitor.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
-
-/// Returns [type] in which all promoted type variables have been replace with
-/// their unpromoted equivalents, and, if [library] is non-nullable by default,
-/// replaces all legacy types with their non-nullable equivalents.
-DartType demoteType(LibraryElement library, DartType type) {
-  if (library.isNonNullableByDefault) {
-    var visitor = const _DemotionNonNullification();
-    return type.accept(visitor) ?? type;
-  } else {
-    var visitor = const _DemotionNonNullification(nonNullifyTypes: false);
-    return type.accept(visitor) ?? type;
-  }
-}
-
-/// Returns `true` if type contains a promoted type variable.
-bool hasPromotedTypeVariable(DartType type) {
-  return type.accept(
-    const _HasPromotedTypeVariableVisitor(),
-  );
-}
-
-/// Returns [type] in which all legacy types have been replaced with
-/// non-nullable types.
-DartType nonNullifyType(TypeSystemImpl typeSystem, DartType type) {
-  if (typeSystem.isNonNullableByDefault && type != null) {
-    var visitor = const _DemotionNonNullification(demoteTypeVariables: false);
-    return type.accept(visitor) ?? type;
-  }
-  return type;
-}
+import 'package:meta/meta.dart';
 
 /// Visitor that replaces all promoted type variables the type variable itself
 /// and/or replaces all legacy types with non-nullable types.
 ///
 /// The visitor returns `null` if the type wasn't changed.
-class _DemotionNonNullification extends ReplacementVisitor {
+class DemotionNonNullificationVisitor extends ReplacementVisitor {
   final bool demoteTypeVariables;
   final bool nonNullifyTypes;
 
-  const _DemotionNonNullification({
-    this.demoteTypeVariables = true,
-    this.nonNullifyTypes = true,
+  const DemotionNonNullificationVisitor({
+    @required this.demoteTypeVariables,
+    @required this.nonNullifyTypes,
   }) : assert(demoteTypeVariables || nonNullifyTypes);
 
   @override
@@ -81,41 +49,3 @@
     );
   }
 }
-
-/// Visitor that returns `true` if a type contains a promoted type variable.
-class _HasPromotedTypeVariableVisitor extends UnifyingTypeVisitor<bool> {
-  const _HasPromotedTypeVariableVisitor();
-
-  @override
-  bool visitDartType(DartType type) => false;
-
-  @override
-  bool visitFunctionType(FunctionType type) {
-    if (type.returnType.accept(this)) {
-      return true;
-    }
-
-    for (var parameter in type.parameters) {
-      if (parameter.type.accept(this)) {
-        return true;
-      }
-    }
-
-    return false;
-  }
-
-  @override
-  bool visitInterfaceType(InterfaceType type) {
-    for (var typeArgument in type.typeArguments) {
-      if (typeArgument.accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  bool visitTypeParameterType(TypeParameterType type) {
-    return (type as TypeParameterTypeImpl).promotedBound != null;
-  }
-}
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index f27c23b..c38172a 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -11,7 +11,7 @@
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart' as public;
+import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/error/listener.dart' show ErrorReporter;
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/generic_inferrer.dart';
@@ -25,400 +25,21 @@
 import 'package:analyzer/src/dart/element/top_merge.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_schema.dart';
 import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
 import 'package:meta/meta.dart';
 
-/// The interface `TypeSystem` defines the behavior of an object representing
-/// the type system.  This provides a common location to put methods that act on
-/// types but may need access to more global data structures, and it paves the
-/// way for a possible future where we may wish to make the type system
-/// pluggable.
-// TODO(brianwilkerson) Rename this class to TypeSystemImpl.
-abstract class TypeSystem2 implements public.TypeSystem {
+/// The [TypeSystem] implementation.
+class TypeSystemImpl implements TypeSystem {
   /// If `true`, then NNBD type rules should be used.
   /// If `false`, then legacy type rules should be used.
   final bool isNonNullableByDefault;
 
-  TypeSystem2({@required this.isNonNullableByDefault});
+  /// The provider of types for the system.
+  final TypeProviderImpl typeProvider;
 
-  /// The provider of types for the system
-  TypeProvider get typeProvider;
-
-  @override
-  TypeImpl flatten(DartType type) {
-    if (identical(type, UnknownInferredType.instance)) {
-      return type;
-    }
-
-    // if T is S? then flatten(T) = flatten(S)?
-    // if T is S* then flatten(T) = flatten(S)*
-    NullabilitySuffix nullabilitySuffix = type.nullabilitySuffix;
-    if (nullabilitySuffix != NullabilitySuffix.none) {
-      var S = (type as TypeImpl).withNullability(NullabilitySuffix.none);
-      return flatten(S).withNullability(nullabilitySuffix);
-    }
-
-    if (type is InterfaceType) {
-      // Implement the cases:
-      //  - "If T = FutureOr<S> then flatten(T) = S."
-      //  - "If T = Future<S> then flatten(T) = S."
-      if (type.isDartAsyncFutureOr || type.isDartAsyncFuture) {
-        return type.typeArguments.isNotEmpty
-            ? type.typeArguments[0]
-            : DynamicTypeImpl.instance;
-      }
-      // Implement the case: "Otherwise if T <: Future then let S be a type
-      // such that T << Future<S> and for all R, if T << Future<R> then S << R.
-      // Then flatten(T) = S."
-      //
-      // In other words, given the set of all types R such that T << Future<R>,
-      // let S be the most specific of those types, if any such S exists.
-      //
-      // Since we only care about the most specific type, it is sufficient to
-      // look at the types appearing as a parameter to Future in the type
-      // hierarchy of T.  We don't need to consider the supertypes of those
-      // types, since they are by definition less specific.
-      List<DartType> candidateTypes =
-          _searchTypeHierarchyForFutureTypeParameters(type);
-      DartType flattenResult =
-          InterfaceTypeImpl.findMostSpecificType(candidateTypes, this);
-      if (flattenResult != null) {
-        return flattenResult;
-      }
-    }
-    // Implement the case: "In any other circumstance, flatten(T) = T."
-    return type;
-  }
-
-  DartType futureOrBase(DartType type) {
-    // If `T` is `FutureOr<S>` for some `S`,
-    // then `futureOrBase(T)` = `futureOrBase(S)`
-    if (type is InterfaceType && type.isDartAsyncFutureOr) {
-      return futureOrBase(
-        type.typeArguments[0],
-      );
-    }
-
-    // Otherwise `futureOrBase(T)` = `T`.
-    return type;
-  }
-
-  List<InterfaceType> gatherMixinSupertypeConstraintsForInference(
-      ClassElement mixinElement) {
-    List<InterfaceType> candidates;
-    if (mixinElement.isMixin) {
-      candidates = mixinElement.superclassConstraints;
-    } else {
-      candidates = [mixinElement.supertype];
-      candidates.addAll(mixinElement.mixins);
-      if (mixinElement.isMixinApplication) {
-        candidates.removeLast();
-      }
-    }
-    return candidates
-        .where((type) => type.element.typeParameters.isNotEmpty)
-        .toList();
-  }
-
-  /// Compute the least upper bound of two types.
-  DartType getLeastUpperBound(DartType type1, DartType type2);
-
-  /// Given a [DartType] [type], instantiate it with its bounds.
-  ///
-  /// The behavior of this method depends on the type system, for example, in
-  /// classic Dart `dynamic` will be used for all type arguments, whereas
-  /// strong mode prefers the actual bound type if it was specified.
-  DartType instantiateToBounds(DartType type, {List<bool> hasError});
-
-  /// Given a [DartType] [type] and a list of types
-  /// [typeArguments], instantiate the type formals with the
-  /// provided actuals.  If [type] is not a parameterized type,
-  /// no instantiation is done.
-  DartType instantiateType(DartType type, List<DartType> typeArguments) {
-    if (type is FunctionType) {
-      return type.instantiate(typeArguments);
-    } else if (type is InterfaceTypeImpl) {
-      // TODO(scheglov) Use `ClassElement.instantiate()`, don't use raw types.
-      return type.element.instantiate(
-        typeArguments: typeArguments,
-        nullabilitySuffix: type.nullabilitySuffix,
-      );
-    } else {
-      return type;
-    }
-  }
-
-  /// Given uninstantiated [typeFormals], instantiate them to their bounds.
-  List<DartType> instantiateTypeFormalsToBounds(
-      List<TypeParameterElement> typeFormals,
-      {List<bool> hasError});
-
-  /// Return `true` if the [leftType] is assignable to the [rightType] (that is,
-  /// if leftType <==> rightType).
-  @override
-  bool isAssignableTo(DartType leftType, DartType rightType);
-
-  /// Return `true` if the [leftType] is more specific than the [rightType]
-  /// (that is, if leftType << rightType), as defined in the Dart language spec.
-  ///
-  /// In strong mode, this is equivalent to [isSubtypeOf].
-  @Deprecated('Use isSubtypeOf() instead.')
-  bool isMoreSpecificThan(DartType leftType, DartType rightType);
-
-  @override
-  bool isNonNullable(DartType type) {
-    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
-      return false;
-    } else if (type is TypeParameterTypeImpl && type.promotedBound != null) {
-      return isNonNullable(type.promotedBound);
-    } else if (type.nullabilitySuffix == NullabilitySuffix.question) {
-      return false;
-    } else if (type is InterfaceType && type.isDartAsyncFutureOr) {
-      return isNonNullable(type.typeArguments[0]);
-    } else if (type is TypeParameterType) {
-      var bound = type.element.bound;
-      return bound != null && isNonNullable(bound);
-    }
-    return true;
-  }
-
-  @override
-  bool isNullable(DartType type) {
-    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
-      return true;
-    } else if (type is TypeParameterTypeImpl && type.promotedBound != null) {
-      return isNullable(type.promotedBound);
-    } else if (type.nullabilitySuffix == NullabilitySuffix.question) {
-      return true;
-    } else if (type.isDartAsyncFutureOr) {
-      return isNullable((type as InterfaceType).typeArguments[0]);
-    }
-    return false;
-  }
-
-  @override
-  bool isPotentiallyNonNullable(DartType type) => !isNullable(type);
-
-  @override
-  bool isPotentiallyNullable(DartType type) => !isNonNullable(type);
-
-  @override
-  bool isStrictlyNonNullable(DartType type) {
-    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
-      return false;
-    } else if (type.nullabilitySuffix != NullabilitySuffix.none) {
-      return false;
-    } else if (type is InterfaceType && type.isDartAsyncFutureOr) {
-      return isStrictlyNonNullable(type.typeArguments[0]);
-    } else if (type is TypeParameterType) {
-      return isStrictlyNonNullable(type.bound);
-    }
-    return true;
-  }
-
-  /// Return `true` if the [leftType] is a subtype of the [rightType] (that is,
-  /// if leftType <: rightType).
-  @override
-  bool isSubtypeOf(DartType leftType, DartType rightType);
-
-  @override
-  DartType leastUpperBound(DartType leftType, DartType rightType) {
-    if (!NullSafetyUnderstandingFlag.isEnabled) {
-      leftType = NullabilityEliminator.perform(typeProvider, leftType);
-      rightType = NullabilityEliminator.perform(typeProvider, rightType);
-    }
-    return getLeastUpperBound(leftType, rightType);
-  }
-
-  /// Returns a nullable version of [type].  The result would be equivalent to
-  /// the union `type | Null` (if we supported union types).
-  DartType makeNullable(TypeImpl type) {
-    // TODO(paulberry): handle type parameter types
-    return type.withNullability(NullabilitySuffix.question);
-  }
-
-  /// Attempts to find the appropriate substitution for the [mixinElement]
-  /// type parameters that can be applied to [srcTypes] to make it equal to
-  /// [destTypes].  If no such substitution can be found, `null` is returned.
-  List<DartType> matchSupertypeConstraints(
-    ClassElement mixinElement,
-    List<DartType> srcTypes,
-    List<DartType> destTypes,
-  ) {
-    var typeParameters = mixinElement.typeParameters;
-    var inferrer = GenericInferrer(this, typeParameters);
-    for (int i = 0; i < srcTypes.length; i++) {
-      inferrer.constrainReturnType(srcTypes[i], destTypes[i]);
-      inferrer.constrainReturnType(destTypes[i], srcTypes[i]);
-    }
-
-    var inferredTypes = inferrer.infer(
-      typeParameters,
-      considerExtendsClause: false,
-    );
-    var substitution = Substitution.fromPairs(typeParameters, inferredTypes);
-
-    for (int i = 0; i < srcTypes.length; i++) {
-      var srcType = substitution.substituteType(srcTypes[i]);
-      var destType = destTypes[i];
-      if (isNonNullableByDefault) {
-        // TODO(scheglov) waiting for the spec
-        // https://github.com/dart-lang/sdk/issues/42605
-      } else {
-        srcType = toLegacyType(srcType);
-        destType = toLegacyType(destType);
-      }
-      if (srcType != destType) {
-        // Failed to find an appropriate substitution
-        return null;
-      }
-    }
-
-    return inferredTypes;
-  }
-
-  /// Returns a non-nullable version of [type].  This is equivalent to the
-  /// operation `NonNull` defined in the spec.
-  @override
-  DartType promoteToNonNull(DartType type) {
-    if (type.isDartCoreNull) return NeverTypeImpl.instance;
-
-    if (type is TypeParameterTypeImpl) {
-      var element = type.element;
-
-      // NonNull(X & T) = X & NonNull(T)
-      if (type.promotedBound != null) {
-        var promotedBound = promoteToNonNull(type.promotedBound);
-        return TypeParameterTypeImpl(
-          element: element,
-          nullabilitySuffix: NullabilitySuffix.none,
-          promotedBound: promotedBound,
-        );
-      }
-
-      // NonNull(X) = X & NonNull(B), where B is the bound of X
-      var promotedBound = element.bound != null
-          ? promoteToNonNull(element.bound)
-          : typeProvider.objectType;
-      if (identical(promotedBound, element.bound)) {
-        promotedBound = null;
-      }
-      return TypeParameterTypeImpl(
-        element: element,
-        nullabilitySuffix: NullabilitySuffix.none,
-        promotedBound: promotedBound,
-      );
-    }
-
-    return (type as TypeImpl).withNullability(NullabilitySuffix.none);
-  }
-
-  /// Determine the type of a binary expression with the given [operator] whose
-  /// left operand has the type [leftType] and whose right operand has the type
-  /// [rightType], given that resolution has so far produced the [currentType].
-  DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
-      DartType rightType, DartType currentType, MethodElement operatorElement);
-
-  /// Determines the context type for the parameters of a method invocation
-  /// where the type of the target is [targetType], the method being invoked is
-  /// [methodElement], the context surrounding the method invocation is
-  /// [invocationContext], and the context type produced so far by resolution is
-  /// [currentType].
-  DartType refineNumericInvocationContext(DartType targetType,
-      Element methodElement, DartType invocationContext, DartType currentType);
-
-  /// Determines the type of a method invocation where the type of the target is
-  /// [targetType], the method being invoked is [methodElement], the types of
-  /// the arguments passed to the method are [argumentTypes], and the type
-  /// produced so far by resolution is [currentType].
-  DartType refineNumericInvocationType(
-      DartType targetType,
-      MethodElement methodElement,
-      List<DartType> argumentTypes,
-      DartType currentType);
-
-  @override
-  DartType resolveToBound(DartType type) {
-    if (type is TypeParameterTypeImpl) {
-      var element = type.element;
-
-      var bound = element.bound;
-      if (bound == null) {
-        return typeProvider.objectType;
-      }
-
-      NullabilitySuffix nullabilitySuffix = type.nullabilitySuffix;
-      NullabilitySuffix newNullabilitySuffix;
-      if (nullabilitySuffix == NullabilitySuffix.question ||
-          bound.nullabilitySuffix == NullabilitySuffix.question) {
-        newNullabilitySuffix = NullabilitySuffix.question;
-      } else if (nullabilitySuffix == NullabilitySuffix.star ||
-          bound.nullabilitySuffix == NullabilitySuffix.star) {
-        newNullabilitySuffix = NullabilitySuffix.star;
-      } else {
-        newNullabilitySuffix = NullabilitySuffix.none;
-      }
-
-      var resolved = resolveToBound(bound) as TypeImpl;
-      return resolved.withNullability(newNullabilitySuffix);
-    }
-
-    return type;
-  }
-
-  DartType toLegacyType(DartType type) {
-    if (isNonNullableByDefault) return type;
-    return NullabilityEliminator.perform(typeProvider, type);
-  }
-
-  /// Tries to promote from the first type from the second type, and returns the
-  /// promoted type if it succeeds, otherwise null.
-  DartType tryPromoteToType(DartType to, DartType from);
-
-  /// Given a [DartType] type, return the [TypeParameterElement]s corresponding
-  /// to its formal type parameters (if any).
-  ///
-  /// @param type the type whose type arguments are to be returned
-  /// @return the type arguments associated with the given type
-  List<TypeParameterElement> typeFormalsAsElements(DartType type) {
-    if (type is FunctionType) {
-      return type.typeFormals;
-    } else if (type is InterfaceType) {
-      return type.element.typeParameters;
-    } else {
-      return const <TypeParameterElement>[];
-    }
-  }
-
-  /// Starting from the given [type], search its class hierarchy for types of
-  /// the form Future<R>, and return a list of the resulting R's.
-  List<DartType> _searchTypeHierarchyForFutureTypeParameters(DartType type) {
-    List<DartType> result = <DartType>[];
-    HashSet<ClassElement> visitedClasses = HashSet<ClassElement>();
-    void recurse(InterfaceTypeImpl type) {
-      if (type.isDartAsyncFuture && type.typeArguments.isNotEmpty) {
-        result.add(type.typeArguments[0]);
-      }
-      if (visitedClasses.add(type.element)) {
-        if (type.superclass != null) {
-          recurse(type.superclass);
-        }
-        for (InterfaceType interface in type.interfaces) {
-          recurse(interface);
-        }
-        visitedClasses.remove(type.element);
-      }
-    }
-
-    recurse(type);
-    return result;
-  }
-}
-
-/// The [public.TypeSystem] implementation.
-class TypeSystemImpl extends TypeSystem2 {
   /// False if implicit casts should always be disallowed.
   ///
   /// This affects the behavior of [isAssignableTo].
@@ -429,9 +50,6 @@
   /// This option is experimental and subject to change.
   bool strictInference;
 
-  @override
-  final TypeProviderImpl typeProvider;
-
   /// The cached instance of `Object?`.
   InterfaceTypeImpl _objectQuestion;
 
@@ -452,11 +70,10 @@
 
   TypeSystemImpl({
     @required this.implicitCasts,
-    @required bool isNonNullableByDefault,
+    @required this.isNonNullableByDefault,
     @required this.strictInference,
     @required TypeProvider typeProvider,
-  })  : typeProvider = typeProvider as TypeProviderImpl,
-        super(isNonNullableByDefault: isNonNullableByDefault) {
+  }) : typeProvider = typeProvider as TypeProviderImpl {
     _greatestLowerBoundHelper = GreatestLowerBoundHelper(this);
     _leastUpperBoundHelper = LeastUpperBoundHelper(this);
     _subtypeHelper = SubtypeHelper(this);
@@ -499,6 +116,25 @@
     return ft.parameters.any((p) => predicate(p.type));
   }
 
+  /// Returns [type] in which all promoted type variables have been replaced
+  /// with their unpromoted equivalents, and, if non-nullable by default,
+  /// replaces all legacy types with their non-nullable equivalents.
+  DartType demoteType(DartType type) {
+    if (isNonNullableByDefault) {
+      var visitor = const DemotionNonNullificationVisitor(
+        demoteTypeVariables: true,
+        nonNullifyTypes: true,
+      );
+      return type.accept(visitor) ?? type;
+    } else {
+      var visitor = const DemotionNonNullificationVisitor(
+        demoteTypeVariables: true,
+        nonNullifyTypes: false,
+      );
+      return type.accept(visitor) ?? type;
+    }
+  }
+
   /// Eliminates type variables from the context [type], replacing them with
   /// `Null` or `Object` as appropriate.
   ///
@@ -578,6 +214,65 @@
     return T;
   }
 
+  @override
+  TypeImpl flatten(DartType type) {
+    if (identical(type, UnknownInferredType.instance)) {
+      return type;
+    }
+
+    // if T is S? then flatten(T) = flatten(S)?
+    // if T is S* then flatten(T) = flatten(S)*
+    NullabilitySuffix nullabilitySuffix = type.nullabilitySuffix;
+    if (nullabilitySuffix != NullabilitySuffix.none) {
+      var S = (type as TypeImpl).withNullability(NullabilitySuffix.none);
+      return flatten(S).withNullability(nullabilitySuffix);
+    }
+
+    if (type is InterfaceType) {
+      // Implement the cases:
+      //  - "If T = FutureOr<S> then flatten(T) = S."
+      //  - "If T = Future<S> then flatten(T) = S."
+      if (type.isDartAsyncFutureOr || type.isDartAsyncFuture) {
+        return type.typeArguments.isNotEmpty
+            ? type.typeArguments[0]
+            : DynamicTypeImpl.instance;
+      }
+      // Implement the case: "Otherwise if T <: Future then let S be a type
+      // such that T << Future<S> and for all R, if T << Future<R> then S << R.
+      // Then flatten(T) = S."
+      //
+      // In other words, given the set of all types R such that T << Future<R>,
+      // let S be the most specific of those types, if any such S exists.
+      //
+      // Since we only care about the most specific type, it is sufficient to
+      // look at the types appearing as a parameter to Future in the type
+      // hierarchy of T.  We don't need to consider the supertypes of those
+      // types, since they are by definition less specific.
+      List<DartType> candidateTypes =
+          _searchTypeHierarchyForFutureTypeParameters(type);
+      DartType flattenResult =
+          InterfaceTypeImpl.findMostSpecificType(candidateTypes, this);
+      if (flattenResult != null) {
+        return flattenResult;
+      }
+    }
+    // Implement the case: "In any other circumstance, flatten(T) = T."
+    return type;
+  }
+
+  DartType futureOrBase(DartType type) {
+    // If `T` is `FutureOr<S>` for some `S`,
+    // then `futureOrBase(T)` = `futureOrBase(S)`
+    if (type is InterfaceType && type.isDartAsyncFutureOr) {
+      return futureOrBase(
+        type.typeArguments[0],
+      );
+    }
+
+    // Otherwise `futureOrBase(T)` = `T`.
+    return type;
+  }
+
   /// Compute "future value type" of [T].
   ///
   /// https://github.com/dart-lang/language/
@@ -613,6 +308,23 @@
     return objectQuestion;
   }
 
+  List<InterfaceType> gatherMixinSupertypeConstraintsForInference(
+      ClassElement mixinElement) {
+    List<InterfaceType> candidates;
+    if (mixinElement.isMixin) {
+      candidates = mixinElement.superclassConstraints;
+    } else {
+      candidates = [mixinElement.supertype];
+      candidates.addAll(mixinElement.mixins);
+      if (mixinElement.isMixinApplication) {
+        candidates.removeLast();
+      }
+    }
+    return candidates
+        .where((type) => type.element.typeParameters.isNotEmpty)
+        .toList();
+  }
+
   /// Given a type t, if t is an interface type with a call method defined,
   /// return the function type for the call method, otherwise return null.
   FunctionType getCallMethodType(DartType t) {
@@ -631,7 +343,6 @@
   ///
   /// https://github.com/dart-lang/language
   /// See `resources/type-system/upper-lower-bounds.md`
-  @override
   DartType getLeastUpperBound(DartType T1, DartType T2) {
     return _leastUpperBoundHelper.getLeastUpperBound(T1, T2);
   }
@@ -775,7 +486,6 @@
   /// https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397
   // TODO(scheglov) Move this method to elements for classes, typedefs,
   //  and generic functions; compute lazily and cache.
-  @override
   DartType instantiateToBounds(DartType type,
       {List<bool> hasError, Map<TypeParameterElement, DartType> knownTypes}) {
     List<TypeParameterElement> typeFormals = typeFormalsAsElements(type);
@@ -817,11 +527,28 @@
     }
   }
 
+  /// Given a [DartType] [type] and a list of types
+  /// [typeArguments], instantiate the type formals with the
+  /// provided actuals.  If [type] is not a parameterized type,
+  /// no instantiation is done.
+  DartType instantiateType(DartType type, List<DartType> typeArguments) {
+    if (type is FunctionType) {
+      return type.instantiate(typeArguments);
+    } else if (type is InterfaceTypeImpl) {
+      // TODO(scheglov) Use `ClassElement.instantiate()`, don't use raw types.
+      return type.element.instantiate(
+        typeArguments: typeArguments,
+        nullabilitySuffix: type.nullabilitySuffix,
+      );
+    } else {
+      return type;
+    }
+  }
+
   /// Given uninstantiated [typeFormals], instantiate them to their bounds.
   /// See the issue for the algorithm description.
   ///
   /// https://github.com/dart-lang/sdk/issues/27526#issuecomment-260021397
-  @override
   List<DartType> instantiateTypeFormalsToBounds(
       List<TypeParameterElement> typeFormals,
       {List<bool> hasError,
@@ -1028,6 +755,56 @@
     return false;
   }
 
+  /// A dynamic bounded type is either `dynamic` itself, or a type variable
+  /// whose bound is dynamic bounded, or an intersection (promoted type
+  /// parameter type) whose second operand is dynamic bounded.
+  bool isDynamicBounded(DartType type) {
+    if (identical(type, DynamicTypeImpl.instance)) {
+      return true;
+    }
+
+    if (type is TypeParameterTypeImpl) {
+      var bound = type.element.bound;
+      if (bound != null && isDynamicBounded(bound)) {
+        return true;
+      }
+
+      var promotedBound = type.promotedBound;
+      if (promotedBound != null && isDynamicBounded(promotedBound)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /// A function bounded type is either `Function` itself, or a type variable
+  /// whose bound is function bounded, or an intersection (promoted type
+  /// parameter type) whose second operand is function bounded.
+  bool isFunctionBounded(DartType type) {
+    if (type is FunctionType) {
+      return type.nullabilitySuffix != NullabilitySuffix.question;
+    }
+
+    if (type is InterfaceType && type.isDartCoreFunction) {
+      return type.nullabilitySuffix != NullabilitySuffix.question;
+    }
+
+    if (type is TypeParameterTypeImpl) {
+      var bound = type.element.bound;
+      if (bound != null && isFunctionBounded(bound)) {
+        return true;
+      }
+
+      var promotedBound = type.promotedBound;
+      if (promotedBound != null && isFunctionBounded(promotedBound)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
   /// Defines an (almost) total order on bottom and `Null` types. This does not
   /// currently consistently order two different type variables with the same
   /// bound.
@@ -1135,8 +912,14 @@
     return false;
   }
 
-  @override
-  bool isMoreSpecificThan(DartType t1, DartType t2) => isSubtypeOf2(t1, t2);
+  /// Return `true` if the [leftType] is more specific than the [rightType]
+  /// (that is, if leftType << rightType), as defined in the Dart language spec.
+  ///
+  /// In strong mode, this is equivalent to [isSubtypeOf].
+  @Deprecated('Use isSubtypeOf() instead.')
+  bool isMoreSpecificThan(DartType leftType, DartType rightType) {
+    return isSubtypeOf2(leftType, rightType);
+  }
 
   /// Defines a total order on top and Object types.
   bool isMoreTop(DartType T, DartType S) {
@@ -1227,6 +1010,23 @@
     return false;
   }
 
+  @override
+  bool isNonNullable(DartType type) {
+    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
+      return false;
+    } else if (type is TypeParameterTypeImpl && type.promotedBound != null) {
+      return isNonNullable(type.promotedBound);
+    } else if (type.nullabilitySuffix == NullabilitySuffix.question) {
+      return false;
+    } else if (type is InterfaceType && type.isDartAsyncFutureOr) {
+      return isNonNullable(type.typeArguments[0]);
+    } else if (type is TypeParameterType) {
+      var bound = type.element.bound;
+      return bound != null && isNonNullable(bound);
+    }
+    return true;
+  }
+
   /// Return `true` for things in the equivalence class of `Null`.
   bool isNull(DartType type) {
     var typeImpl = type as TypeImpl;
@@ -1251,6 +1051,20 @@
     return false;
   }
 
+  @override
+  bool isNullable(DartType type) {
+    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
+      return true;
+    } else if (type is TypeParameterTypeImpl && type.promotedBound != null) {
+      return isNullable(type.promotedBound);
+    } else if (type.nullabilitySuffix == NullabilitySuffix.question) {
+      return true;
+    } else if (type.isDartAsyncFutureOr) {
+      return isNullable((type as InterfaceType).typeArguments[0]);
+    }
+    return false;
+  }
+
   /// Return `true` for any type which is in the equivalence class of `Object`.
   bool isObject(DartType type) {
     TypeImpl typeImpl = type;
@@ -1273,6 +1087,26 @@
     return false;
   }
 
+  @override
+  bool isPotentiallyNonNullable(DartType type) => !isNullable(type);
+
+  @override
+  bool isPotentiallyNullable(DartType type) => !isNonNullable(type);
+
+  @override
+  bool isStrictlyNonNullable(DartType type) {
+    if (type.isDynamic || type.isVoid || type.isDartCoreNull) {
+      return false;
+    } else if (type.nullabilitySuffix != NullabilitySuffix.none) {
+      return false;
+    } else if (type is InterfaceType && type.isDartAsyncFutureOr) {
+      return isStrictlyNonNullable(type.typeArguments[0]);
+    } else if (type is TypeParameterType) {
+      return isStrictlyNonNullable(type.bound);
+    }
+    return true;
+  }
+
   /// Check if [leftType] is a subtype of [rightType].
   ///
   /// Implements:
@@ -1361,6 +1195,74 @@
     }
   }
 
+  @override
+  DartType leastUpperBound(DartType leftType, DartType rightType) {
+    if (!NullSafetyUnderstandingFlag.isEnabled) {
+      leftType = NullabilityEliminator.perform(typeProvider, leftType);
+      rightType = NullabilityEliminator.perform(typeProvider, rightType);
+    }
+    return getLeastUpperBound(leftType, rightType);
+  }
+
+  /// Returns a nullable version of [type].  The result would be equivalent to
+  /// the union `type | Null` (if we supported union types).
+  DartType makeNullable(TypeImpl type) {
+    // TODO(paulberry): handle type parameter types
+    return type.withNullability(NullabilitySuffix.question);
+  }
+
+  /// Attempts to find the appropriate substitution for the [mixinElement]
+  /// type parameters that can be applied to [srcTypes] to make it equal to
+  /// [destTypes].  If no such substitution can be found, `null` is returned.
+  List<DartType> matchSupertypeConstraints(
+    ClassElement mixinElement,
+    List<DartType> srcTypes,
+    List<DartType> destTypes,
+  ) {
+    var typeParameters = mixinElement.typeParameters;
+    var inferrer = GenericInferrer(this, typeParameters);
+    for (int i = 0; i < srcTypes.length; i++) {
+      inferrer.constrainReturnType(srcTypes[i], destTypes[i]);
+      inferrer.constrainReturnType(destTypes[i], srcTypes[i]);
+    }
+
+    var inferredTypes = inferrer.infer(
+      typeParameters,
+      considerExtendsClause: false,
+    );
+    var substitution = Substitution.fromPairs(typeParameters, inferredTypes);
+
+    for (int i = 0; i < srcTypes.length; i++) {
+      var srcType = substitution.substituteType(srcTypes[i]);
+      var destType = destTypes[i];
+      if (isNonNullableByDefault) {
+        // TODO(scheglov) waiting for the spec
+        // https://github.com/dart-lang/sdk/issues/42605
+      } else {
+        srcType = toLegacyType(srcType);
+        destType = toLegacyType(destType);
+      }
+      if (srcType != destType) {
+        // Failed to find an appropriate substitution
+        return null;
+      }
+    }
+
+    return inferredTypes;
+  }
+
+  /// Replace legacy types in [type] with non-nullable types.
+  DartType nonNullifyLegacy(DartType type) {
+    if (isNonNullableByDefault) {
+      var visitor = const DemotionNonNullificationVisitor(
+        demoteTypeVariables: false,
+        nonNullifyTypes: true,
+      );
+      return type.accept(visitor) ?? type;
+    }
+    return type;
+  }
+
   /// Compute the canonical representation of [T].
   ///
   /// https://github.com/dart-lang/language
@@ -1369,7 +1271,45 @@
     return NormalizeHelper(this).normalize(T);
   }
 
+  /// Returns a non-nullable version of [type].  This is equivalent to the
+  /// operation `NonNull` defined in the spec.
   @override
+  DartType promoteToNonNull(DartType type) {
+    if (type.isDartCoreNull) return NeverTypeImpl.instance;
+
+    if (type is TypeParameterTypeImpl) {
+      var element = type.element;
+
+      // NonNull(X & T) = X & NonNull(T)
+      if (type.promotedBound != null) {
+        var promotedBound = promoteToNonNull(type.promotedBound);
+        return TypeParameterTypeImpl(
+          element: element,
+          nullabilitySuffix: NullabilitySuffix.none,
+          promotedBound: promotedBound,
+        );
+      }
+
+      // NonNull(X) = X & NonNull(B), where B is the bound of X
+      var promotedBound = element.bound != null
+          ? promoteToNonNull(element.bound)
+          : typeProvider.objectType;
+      if (identical(promotedBound, element.bound)) {
+        promotedBound = null;
+      }
+      return TypeParameterTypeImpl(
+        element: element,
+        nullabilitySuffix: NullabilitySuffix.none,
+        promotedBound: promotedBound,
+      );
+    }
+
+    return (type as TypeImpl).withNullability(NullabilitySuffix.none);
+  }
+
+  /// Determine the type of a binary expression with the given [operator] whose
+  /// left operand has the type [leftType] and whose right operand has the type
+  /// [rightType], given that resolution has so far produced the [currentType].
   DartType refineBinaryExpressionType(DartType leftType, TokenType operator,
       DartType rightType, DartType currentType, MethodElement operatorElement) {
     if (isNonNullableByDefault) {
@@ -1382,7 +1322,11 @@
     }
   }
 
-  @override
+  /// Determines the context type for the parameters of a method invocation
+  /// where the type of the target is [targetType], the method being invoked is
+  /// [methodElement], the context surrounding the method invocation is
+  /// [invocationContext], and the context type produced so far by resolution is
+  /// [currentType].
   DartType refineNumericInvocationContext(DartType targetType,
       Element methodElement, DartType invocationContext, DartType currentType) {
     if (methodElement is MethodElement && isNonNullableByDefault) {
@@ -1394,7 +1338,12 @@
     }
   }
 
-  @override
+  /// Determines the type of a method invocation where the type of the target is
+  /// [targetType], the method being invoked is [methodElement], the types of
+  /// the arguments passed to the method are [argumentTypes], and the type
+  /// produced so far by resolution is [currentType].
+  ///
+  /// TODO(scheglov) I expected that [methodElement] is [MethodElement].
   DartType refineNumericInvocationType(
       DartType targetType,
       Element methodElement,
@@ -1430,6 +1379,35 @@
     }
   }
 
+  @override
+  DartType resolveToBound(DartType type) {
+    if (type is TypeParameterTypeImpl) {
+      var element = type.element;
+
+      var bound = element.bound;
+      if (bound == null) {
+        return typeProvider.objectType;
+      }
+
+      NullabilitySuffix nullabilitySuffix = type.nullabilitySuffix;
+      NullabilitySuffix newNullabilitySuffix;
+      if (nullabilitySuffix == NullabilitySuffix.question ||
+          bound.nullabilitySuffix == NullabilitySuffix.question) {
+        newNullabilitySuffix = NullabilitySuffix.question;
+      } else if (nullabilitySuffix == NullabilitySuffix.star ||
+          bound.nullabilitySuffix == NullabilitySuffix.star) {
+        newNullabilitySuffix = NullabilitySuffix.star;
+      } else {
+        newNullabilitySuffix = NullabilitySuffix.none;
+      }
+
+      var resolved = resolveToBound(bound) as TypeImpl;
+      return resolved.withNullability(newNullabilitySuffix);
+    }
+
+    return type;
+  }
+
   /// Return `true` if runtime types [T1] and [T2] are equal.
   ///
   /// nnbd/feature-specification.md#runtime-type-equality-operator
@@ -1437,6 +1415,11 @@
     return RuntimeTypeEqualityHelper(this).equal(T1, T2);
   }
 
+  DartType toLegacyType(DartType type) {
+    if (isNonNullableByDefault) return type;
+    return NullabilityEliminator.perform(typeProvider, type);
+  }
+
   /// Merges two types into a single type.
   /// Compute the canonical representation of [T].
   ///
@@ -1447,7 +1430,8 @@
     return TopMergeHelper(this).topMerge(T, S);
   }
 
-  @override
+  /// Tries to promote from the first type from the second type, and returns the
+  /// promoted type if it succeeds, otherwise null.
   DartType tryPromoteToType(DartType to, DartType from) {
     // Allow promoting to a subtype, for example:
     //
@@ -1478,6 +1462,21 @@
     return null;
   }
 
+  /// Given a [DartType] type, return the [TypeParameterElement]s corresponding
+  /// to its formal type parameters (if any).
+  ///
+  /// @param type the type whose type arguments are to be returned
+  /// @return the type arguments associated with the given type
+  List<TypeParameterElement> typeFormalsAsElements(DartType type) {
+    if (type is FunctionType) {
+      return type.typeFormals;
+    } else if (type is InterfaceType) {
+      return type.element.typeParameters;
+    } else {
+      return const <TypeParameterElement>[];
+    }
+  }
+
   void updateOptions({
     @required bool implicitCasts,
     @required bool strictInference,
@@ -1785,6 +1784,30 @@
     // No special rules apply.
     return currentType;
   }
+
+  /// Starting from the given [type], search its class hierarchy for types of
+  /// the form Future<R>, and return a list of the resulting R's.
+  List<DartType> _searchTypeHierarchyForFutureTypeParameters(DartType type) {
+    List<DartType> result = <DartType>[];
+    HashSet<ClassElement> visitedClasses = HashSet<ClassElement>();
+    void recurse(InterfaceTypeImpl type) {
+      if (type.isDartAsyncFuture && type.typeArguments.isNotEmpty) {
+        result.add(type.typeArguments[0]);
+      }
+      if (visitedClasses.add(type.element)) {
+        if (type.superclass != null) {
+          recurse(type.superclass);
+        }
+        for (InterfaceType interface in type.interfaces) {
+          recurse(interface);
+        }
+        visitedClasses.remove(type.element);
+      }
+    }
+
+    recurse(type);
+    return result;
+  }
 }
 
 class _TypeVariableEliminator extends Substitution {
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 7aef562..04450e8 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -577,6 +577,32 @@
       "The annotation '{0}' can only be used on {1}");
 
   /**
+   * This hint is generated anywhere where an element annotated with `@internal`
+   * is exported as a part of a package's public API.
+   *
+   * Parameters:
+   * 0: the name of the element
+   */
+  static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT = HintCode(
+      'INVALID_EXPORT_OF_INTERNAL_ELEMENT',
+      "The member '{0}' can't be exported as a part of a package's public "
+          "API.",
+      correction: "Try using a hide clause to hide '{0}'.");
+
+  /**
+   * This hint is generated anywhere where an element annotated with `@internal`
+   * is exported indirectly as a part of a package's public API.
+   *
+   * Parameters:
+   * 0: the name of the element
+   */
+  static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY = HintCode(
+      'INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY',
+      "The member '{0}' can't be exported as a part of a package's public "
+          "API, but is indirectly exported as part of the signature of '{1}'.",
+      correction: "Try using a hide clause to hide '{0}'.");
+
+  /**
    * This hint is generated anywhere a @factory annotation is associated with
    * anything other than a method.
    */
@@ -612,6 +638,15 @@
       'INVALID_IMMUTABLE_ANNOTATION',
       "Only classes can be annotated as being immutable.");
 
+  /**
+   * This hint is generated anywhere a @internal annotation is associated with
+   * an element found in a package's public API.
+   */
+  static const HintCode INVALID_INTERNAL_ANNOTATION = HintCode(
+      'INVALID_INTERNAL_ANNOTATION',
+      "Only public elements in a package's private API can be annotated as "
+          "being internal.");
+
   /// Invalid Dart language version comments don't follow the specification [1].
   /// If a comment begins with "@dart" or "dart" (letters in any case),
   /// followed by optional whitespace, followed by optional non-alphanumeric,
@@ -921,8 +956,19 @@
       correction: "Remove @sealed.");
 
   /**
+   * This hint is generated anywhere where a member annotated with `@internal`
+   * is used outside of the package in which it is declared.
+   *
+   * Parameters:
+   * 0: the name of the member
+   */
+  static const HintCode INVALID_USE_OF_INTERNAL_MEMBER = HintCode(
+      'INVALID_USE_OF_INTERNAL_MEMBER',
+      "The member '{0}' can only be used within its package.");
+
+  /**
    * This hint is generated anywhere where a member annotated with `@protected`
-   * is used outside an instance member of a subclass.
+   * is used outside of an instance member of a subclass.
    *
    * Parameters:
    * 0: the name of the member
@@ -1132,7 +1178,7 @@
   //
   // #### Examples
   //
-  // If the package 'p' defines a sealed class:
+  // If the package `p` defines a sealed class:
   //
   // ```dart
   // %uri="package:p/p.dart"
@@ -1142,7 +1188,7 @@
   // class C {}
   // ```
   //
-  // Then, the following code, when in a package other than 'p', produces this
+  // Then, the following code, when in a package other than `p`, produces this
   // diagnostic:
   //
   // ```dart
@@ -1555,6 +1601,16 @@
           "receiver");
 
   /**
+   * Users should not return values marked `@doNotStore` from functions,
+   * methods or getters not marked `@doNotStore`.
+   */
+  static const HintCode RETURN_OF_DO_NOT_STORE = HintCode(
+      'RETURN_OF_DO_NOT_STORE',
+      "'{0}' is annotated with 'doNotStore' and shouldn't be returned unless "
+          "'{1}' is also annotated.",
+      correction: "Annotate '{1}' with 'doNotStore'.");
+
+  /**
    * No parameters.
    */
   // #### Description
@@ -2532,9 +2588,14 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when a private class, enum, mixin,
-  // typedef, top level variable, top level function, or method is declared but
-  // never referenced.
+  // The analyzer produces this diagnostic when a private declaration isn't
+  // referenced in the library that contains the declaration. The following
+  // kinds of declarations are analyzed:
+  // - Private top-level declarations, such as classes, enums, mixins, typedefs,
+  //   top-level variables, and top-level functions
+  // - Private static and instance methods
+  // - Optional parameters of private functions for which a value is never
+  //   passed, even when the parameter doesn't have a private name
   //
   // #### Examples
   //
@@ -2545,11 +2606,30 @@
   // class [!_C!] {}
   // ```
   //
+  // Assuming that no code in the library passes a value for `y` in any
+  // invocation of `_m`, the following code produces this diagnostic:
+  //
+  // ```dart
+  // class C {
+  //   void _m(int x, [int [!y!]]) {}
+  //
+  //   void n() => _m(0);
+  // }
+  // ```
+  //
   // #### Common fixes
   //
-  // If the declaration isn't needed, then remove it.
+  // If the declaration isn't needed, then remove it:
   //
-  // If the declaration was intended to be used, then add the missing code.
+  // ```dart
+  // class C {
+  //   void _m(int x) {}
+  //
+  //   void n() => _m(0);
+  // }
+  // ```
+  //
+  // If the declaration is intended to be used, then add the code to use it.
   static const HintCode UNUSED_ELEMENT = HintCode(
       'UNUSED_ELEMENT', "The declaration '{0}' isn't referenced.",
       correction: "Try removing the declaration of '{0}'.",
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index adc7492..46bede3 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -72,6 +72,9 @@
           "The keywords 'await' and 'yield' can't be used as "
               "identifiers in an asynchronous or generator function.");
 
+  static const ParserErrorCode BINARY_OPERATOR_WRITTEN_OUT =
+      _BINARY_OPERATOR_WRITTEN_OUT;
+
   static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = _BREAK_OUTSIDE_OF_LOOP;
 
   static const ParserErrorCode CATCH_SYNTAX = _CATCH_SYNTAX;
@@ -128,10 +131,39 @@
           "Top-level declarations can't be declared to be covariant.",
           correction: "Try removing the keyword 'covariant'.");
 
+  /**
+   * No parameters.
+   */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a function type associated with
+  // a parameter includes optional parameters that have a default value. This
+  // isn't allowed because the default values of parameters aren't part of the
+  // function's type, and therefore including them doesn't provide any value.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the parameter `p` has a
+  // default value even though it's part of the type of the parameter `g`:
+  //
+  // ```dart
+  // void f(void Function([int p [!=!] 0]) g) {
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the default value from the function-type's parameter:
+  //
+  // ```dart
+  // void f(void Function([int p]) g) {
+  // }
+  // ```
   static const ParserErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPE = ParserErrorCode(
       'DEFAULT_VALUE_IN_FUNCTION_TYPE',
-      "Parameters in a function type cannot have default values",
-      correction: "Try removing the default value.");
+      "Parameters in a function type can't have default values.",
+      correction: "Try removing the default value.",
+      hasPublishedDocs: true);
 
   static const ParserErrorCode DEFERRED_AFTER_PREFIX = _DEFERRED_AFTER_PREFIX;
 
@@ -182,6 +214,9 @@
       correction:
           "This appears to be incomplete code. Try removing it or completing it.");
 
+  static const ParserErrorCode EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD =
+      _EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD;
+
   static const ParserErrorCode EXPECTED_INSTEAD = _EXPECTED_INSTEAD;
 
   static const ParserErrorCode EXPECTED_LIST_OR_MAP_LITERAL = ParserErrorCode(
@@ -503,7 +538,7 @@
   //
   // #### Common fixes
   //
-  // Remove the 'covariant' keyword:
+  // Remove the `covariant` keyword:
   //
   // ```dart
   // extension E on String {
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index 0698c8b..23291d0 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -119,6 +119,8 @@
   _EXTERNAL_LATE_FIELD,
   _ABSTRACT_EXTERNAL_FIELD,
   _ANNOTATION_ON_TYPE_ARGUMENT,
+  _BINARY_OPERATOR_WRITTEN_OUT,
+  _EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD,
 ];
 
 const ParserErrorCode _ABSTRACT_CLASS_MEMBER = ParserErrorCode(
@@ -148,6 +150,11 @@
     'ANNOTATION_WITH_TYPE_ARGUMENTS',
     r"An annotation (metadata) can't use type arguments.");
 
+const ParserErrorCode _BINARY_OPERATOR_WRITTEN_OUT = ParserErrorCode(
+    'BINARY_OPERATOR_WRITTEN_OUT',
+    r"Binary operator '#string' is written as '#string2' instead of the written out word.",
+    correction: "Try replacing '#string' with '#string2'.");
+
 const ParserErrorCode _BREAK_OUTSIDE_OF_LOOP = ParserErrorCode(
     'BREAK_OUTSIDE_OF_LOOP',
     r"A break statement can't be used outside of a loop or switch statement.",
@@ -263,6 +270,11 @@
 const ParserErrorCode _EXPECTED_ELSE_OR_COMMA =
     ParserErrorCode('EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
 
+const ParserErrorCode _EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD = ParserErrorCode(
+    'EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD',
+    r"'#lexeme' can't be used as an identifier because it's a keyword.",
+    correction: "Try renaming this to be an identifier that isn't a keyword.");
+
 const ParserErrorCode _EXPECTED_INSTEAD =
     ParserErrorCode('EXPECTED_INSTEAD', r"Expected '#string' instead of this.");
 
diff --git a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
index 5d97366..57531d9 100644
--- a/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/micro/cider_byte_store.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/analysis/cache.dart';
 import 'package:collection/collection.dart';
 
 /// Store of bytes associated with string keys and a hash.
@@ -23,19 +24,16 @@
   void put(String key, List<int> signature, List<int> bytes);
 }
 
-class CiderCacheEntry {
-  final List<int> signature;
-  final List<int> bytes;
+class CiderCachedByteStore implements CiderByteStore {
+  final Cache<String, CiderCacheEntry> _cache;
 
-  CiderCacheEntry(this.signature, this.bytes);
-}
-
-class CiderMemoryByteStore implements CiderByteStore {
-  final Map<String, CiderCacheEntry> _map = {};
+  CiderCachedByteStore(int maxCacheSize)
+      : _cache =
+            Cache<String, CiderCacheEntry>(maxCacheSize, (v) => v.bytes.length);
 
   @override
   List<int> get(String key, List<int> signature) {
-    var entry = _map[key];
+    var entry = _cache.get(key, () => null);
 
     if (entry != null &&
         const ListEquality<int>().equals(entry.signature, signature)) {
@@ -46,6 +44,13 @@
 
   @override
   void put(String key, List<int> signature, List<int> bytes) {
-    _map[key] = CiderCacheEntry(signature, bytes);
+    _cache.put(key, CiderCacheEntry(signature, bytes));
   }
 }
+
+class CiderCacheEntry {
+  final List<int> signature;
+  final List<int> bytes;
+
+  CiderCacheEntry(this.signature, this.bytes);
+}
diff --git a/pkg/analyzer/lib/src/dart/micro/libraries_log.dart b/pkg/analyzer/lib/src/dart/micro/libraries_log.dart
new file mode 100644
index 0000000..a67988b
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/micro/libraries_log.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+class ChangeFileLoadEntry extends LibrariesLogEntry {
+  /// The path of the file that was reported as changed.
+  final String target;
+
+  /// The files that depend transitively on the [target]. These files are
+  /// removed from the state, and from the element factory.
+  final List<LibrariesLogFile> removed = [];
+
+  ChangeFileLoadEntry._(this.target);
+
+  void addRemoved({
+    @required String path,
+    @required Uri uri,
+  }) {
+    removed.add(
+      LibrariesLogFile._(path, uri),
+    );
+  }
+
+  @override
+  String toString() {
+    return 'Change(target: $target, removed: $removed)';
+  }
+}
+
+class LibrariesLog {
+  final List<LibrariesLogEntry> entries = [];
+
+  ChangeFileLoadEntry changeFile(String path) {
+    var entry = ChangeFileLoadEntry._(path);
+    entries.add(entry);
+    return entry;
+  }
+
+  LoadLibrariesForTargetLogEntry loadForTarget({
+    @required String path,
+    @required Uri uri,
+  }) {
+    var entry = LoadLibrariesForTargetLogEntry._(
+      LibrariesLogFile._(path, uri),
+    );
+    entries.add(entry);
+    return entry;
+  }
+}
+
+abstract class LibrariesLogEntry {
+  final DateTime time = DateTime.now();
+}
+
+class LibrariesLogFile {
+  final String path;
+  final Uri uri;
+
+  LibrariesLogFile._(this.path, this.uri);
+
+  @override
+  String toString() {
+    return '(path: $path, uri: $uri)';
+  }
+}
+
+class LoadLibrariesForTargetLogEntry extends LibrariesLogEntry {
+  final LibrariesLogFile target;
+  final List<LibrariesLogFile> loaded = [];
+
+  LoadLibrariesForTargetLogEntry._(this.target);
+
+  void addLibrary({
+    @required String path,
+    @required Uri uri,
+  }) {
+    loaded.add(
+      LibrariesLogFile._(path, uri),
+    );
+  }
+
+  @override
+  String toString() {
+    return 'Load(target: $target, loaded: $loaded)';
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 5e5d888..c61b3c9 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -277,7 +277,7 @@
         typeSystem: _typeSystem,
         inheritanceManager: _inheritance,
         analysisOptions: _context.analysisOptions,
-        workspacePackage: null, // TODO(scheglov) implement it
+        workspacePackage: _library.workspacePackage,
       ),
     );
 
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index d7e63f2..b870957 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -30,9 +30,11 @@
     show DependencyWalker, Node;
 import 'package:analyzer/src/summary2/informative_data.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:collection/collection.dart';
 import 'package:convert/convert.dart';
 import 'package:meta/meta.dart';
+import 'package:pub_semver/pub_semver.dart';
 
 /// Ensure that the [FileState.libraryCycle] for the [file] and anything it
 /// depends on is computed.
@@ -53,6 +55,24 @@
   /// The [Source] of the file with the [uri].
   final Source source;
 
+  /// The [WorkspacePackage] that contains this file.
+  ///
+  /// It might be `null` if the file is outside of the workspace.
+  final WorkspacePackage workspacePackage;
+
+  /// The [FeatureSet] for all files in the analysis context.
+  ///
+  /// Usually it is the feature set of the latest language version, plus
+  /// possibly additional enabled experiments (from the analysis options file,
+  /// or from SDK allowed experiments).
+  ///
+  /// This feature set is then restricted, with the [_packageLanguageVersion],
+  /// or with a `@dart` language override token in the file header.
+  final FeatureSet _contextFeatureSet;
+
+  /// The language version for the package that contains this file.
+  final Version _packageLanguageVersion;
+
   /// Files that reference this file.
   final List<FileState> referencingFiles = [];
 
@@ -70,7 +90,15 @@
   UnlinkedUnit2 unlinked2;
   LibraryCycle _libraryCycle;
 
-  FileState._(this._fsState, this.path, this.uri, this.source);
+  FileState._(
+    this._fsState,
+    this.path,
+    this.uri,
+    this.source,
+    this.workspacePackage,
+    this._contextFeatureSet,
+    this._packageLanguageVersion,
+  );
 
   List<int> get apiSignature => _apiSignature;
 
@@ -135,14 +163,14 @@
 
   CompilationUnit parse(AnalysisErrorListener errorListener, String content) {
     AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
-    FeatureSet featureSet =
-        _fsState.featureSetProvider.getFeatureSet(path, uri);
 
     CharSequenceReader reader = CharSequenceReader(content);
     Scanner scanner = Scanner(source, reader, errorListener)
       ..configureFeatures(
-        featureSetForOverriding: featureSet,
-        featureSet: featureSet,
+        featureSetForOverriding: _contextFeatureSet,
+        featureSet: _contextFeatureSet.restrictToVersion(
+          _packageLanguageVersion,
+        ),
       );
     Token token = scanner.tokenize(reportScannerErrors: false);
     LineInfo lineInfo = LineInfo(scanner.lineStarts);
@@ -415,6 +443,7 @@
   final ResourceProvider _resourceProvider;
   final CiderByteStore _byteStore;
   final SourceFactory _sourceFactory;
+  final Workspace _workspace;
   final AnalysisOptions _analysisOptions;
   final Uint32List _linkedSalt;
 
@@ -440,6 +469,7 @@
     this._resourceProvider,
     this._byteStore,
     this._sourceFactory,
+    this._workspace,
     this._analysisOptions,
     this._linkedSalt,
     this.featureSetProvider,
@@ -470,6 +500,21 @@
     }
   }
 
+  FeatureSet contextFeatureSet(
+    String path,
+    Uri uri,
+    WorkspacePackage workspacePackage,
+  ) {
+    var workspacePackageExperiments = workspacePackage?.enabledExperiments;
+    if (workspacePackageExperiments != null) {
+      return featureSetProvider.featureSetForExperiments(
+        workspacePackageExperiments,
+      );
+    }
+
+    return featureSetProvider.getFeatureSet(path, uri);
+  }
+
   FileState getFileForPath({
     @required String path,
     @required OperationPerformanceImpl performance,
@@ -482,7 +527,12 @@
       );
 
       var source = _sourceFactory.forUri2(uri);
-      file = FileState._(this, path, uri, source);
+      var workspacePackage = _workspace?.findPackageFor(path);
+      var featureSet = contextFeatureSet(path, uri, workspacePackage);
+      var packageLanguageVersion =
+          featureSetProvider.getLanguageVersion(path, uri);
+      file = FileState._(this, path, uri, source, workspacePackage, featureSet,
+          packageLanguageVersion);
 
       _pathToFile[path] = file;
       _uriToFile[uri] = file;
@@ -508,7 +558,13 @@
       }
       var path = source.fullName;
 
-      file = FileState._(this, path, uri, source);
+      var workspacePackage = _workspace?.findPackageFor(path);
+      var featureSet = contextFeatureSet(path, uri, workspacePackage);
+      var packageLanguageVersion =
+          featureSetProvider.getLanguageVersion(path, uri);
+
+      file = FileState._(this, path, uri, source, workspacePackage, featureSet,
+          packageLanguageVersion);
       _pathToFile[path] = file;
       _uriToFile[uri] = file;
 
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 007b4dc..53409d0 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -6,6 +6,7 @@
 import 'dart:typed_data';
 
 import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/null_safety_understanding_flag.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
@@ -14,13 +15,16 @@
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart' show ErrorEncoding;
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/micro/analysis_context.dart';
 import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
+import 'package:analyzer/src/dart/micro/libraries_log.dart';
 import 'package:analyzer/src/dart/micro/library_analyzer.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
+import 'package:analyzer/src/exception/exception.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
@@ -37,6 +41,9 @@
 import 'package:meta/meta.dart';
 import 'package:yaml/yaml.dart';
 
+const M = 1024 * 1024 /*1 MiB*/;
+const memoryCacheSize = 200 * M;
+
 class FileContext {
   final AnalysisOptionsImpl analysisOptions;
   final FileState file;
@@ -72,6 +79,8 @@
 
   MicroContextObjects contextObjects;
 
+  final LibrariesLog _librariesLog = LibrariesLog();
+
   _LibraryContext libraryContext;
 
   FileResolver(
@@ -108,7 +117,7 @@
         getFileDigest = getFileDigest,
         prefetchFiles = prefetchFiles,
         workspace = workspace {
-    byteStore ??= CiderMemoryByteStore();
+    byteStore ??= CiderCachedByteStore(memoryCacheSize);
     this.byteStore = byteStore;
     _libraryContextReset = _LibraryContextReset(
       fileResolver: this,
@@ -116,6 +125,10 @@
     );
   }
 
+  List<LibrariesLogEntry> get librariesLogEntries {
+    return _librariesLog.entries;
+  }
+
   /// Update the resolver to reflect the fact that the file with the given
   /// [path] was changed. We need to make sure that when this file, of any file
   /// that directly or indirectly referenced it, is resolved, we used the new
@@ -129,12 +142,19 @@
     var removedFiles = <FileState>[];
     fsState.changeFile(path, removedFiles);
 
+    // Update the log.
+    var logEntry = _librariesLog.changeFile(path);
+    for (var removedFile in removedFiles) {
+      logEntry.addRemoved(
+        path: removedFile.path,
+        uri: removedFile.uri,
+      );
+    }
+
     // Remove libraries represented by removed files.
     // If we need these libraries later, we will relink and reattach them.
     if (libraryContext != null) {
-      libraryContext.elementFactory.removeLibraries(
-        removedFiles.map((e) => e.uriStr).toList(),
-      );
+      libraryContext.remove(removedFiles);
     }
   }
 
@@ -306,13 +326,28 @@
             (file) => file.getContentWithSameDigest(),
           );
 
-          results = performance.run('analyze', (performance) {
-            return libraryAnalyzer.analyzeSync(
-              completionPath: completionOffset != null ? path : null,
-              completionOffset: completionOffset,
-              performance: performance,
+          try {
+            results = performance.run('analyze', (performance) {
+              return NullSafetyUnderstandingFlag.enableNullSafetyTypes(() {
+                return libraryAnalyzer.analyzeSync(
+                  completionPath: completionOffset != null ? path : null,
+                  completionOffset: completionOffset,
+                  performance: performance,
+                );
+              });
+            });
+          } catch (exception, stackTrace) {
+            var fileContentMap = <String, String>{};
+            for (var file in libraryFile.libraryFiles) {
+              var path = file.path;
+              fileContentMap[path] = _getFileContent(path);
+            }
+            throw CaughtExceptionWithFiles(
+              exception,
+              stackTrace,
+              fileContentMap,
             );
-          });
+          }
         });
         UnitAnalysisResult fileResult = results[file];
 
@@ -359,6 +394,7 @@
         resourceProvider: resourceProvider,
         packages: Packages.empty,
         packageDefaultFeatureSet: analysisOptions.contextFeatures,
+        nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
         nonPackageDefaultFeatureSet: analysisOptions.nonPackageFeatureSet,
       );
 
@@ -366,6 +402,7 @@
         resourceProvider,
         byteStore,
         sourceFactory,
+        workspace,
         analysisOptions,
         Uint32List(0),
         // linkedSalt
@@ -394,6 +431,7 @@
         resourceProvider,
         byteStore,
         contextObjects,
+        _librariesLog,
       );
     }
   }
@@ -424,10 +462,17 @@
   }) {
     YamlMap optionMap;
 
-    var optionsFile = performance.run('findOptionsFile', (_) {
-      var folder = resourceProvider.getFile(path).parent;
-      return _findOptionsFile(folder);
-    });
+    var separator = resourceProvider.pathContext.separator;
+    var isThirdParty =
+        path.contains('${separator}third_party${separator}dart$separator');
+
+    File optionsFile;
+    if (!isThirdParty) {
+      optionsFile = performance.run('findOptionsFile', (_) {
+        var folder = resourceProvider.getFile(path).parent;
+        return _findOptionsFile(folder);
+      });
+    }
 
     if (optionsFile != null) {
       performance.run('getOptionsFromFile', (_) {
@@ -441,9 +486,7 @@
     } else {
       var source = performance.run('defaultOptions', (_) {
         if (workspace is WorkspaceWithDefaultAnalysisOptions) {
-          var separator = resourceProvider.pathContext.separator;
-          if (path
-              .contains('${separator}third_party${separator}dart$separator')) {
+          if (isThirdParty) {
             return sourceFactory.forUri(
               WorkspaceWithDefaultAnalysisOptions.thirdPartyUri,
             );
@@ -535,6 +578,7 @@
   final ResourceProvider resourceProvider;
   final CiderByteStore byteStore;
   final MicroContextObjects contextObjects;
+  final LibrariesLog librariesLog;
 
   LinkedElementFactory elementFactory;
 
@@ -545,9 +589,13 @@
     this.resourceProvider,
     this.byteStore,
     this.contextObjects,
+    this.librariesLog,
   ) {
-    // TODO(scheglov) remove it?
-    _createElementFactory();
+    elementFactory = LinkedElementFactory(
+      contextObjects.analysisContext,
+      contextObjects.analysisSession,
+      Reference.root(),
+    );
   }
 
   /// Load data required to access elements of the given [targetLibrary].
@@ -561,9 +609,21 @@
     var librariesLinkedTimer = Stopwatch();
     var inputsTimer = Stopwatch();
 
+    var logEntry = librariesLog.loadForTarget(
+      path: targetLibrary.path,
+      uri: targetLibrary.uri,
+    );
+
     void loadBundle(LibraryCycle cycle) {
       if (!loadedBundles.add(cycle)) return;
 
+      for (var library in cycle.libraries) {
+        logEntry.addLibrary(
+          path: library.path,
+          uri: library.uri,
+        );
+      }
+
       performance.getDataInt('cycleCount').increment();
       performance.getDataInt('libraryCount').add(cycle.libraries.length);
 
@@ -636,8 +696,9 @@
       // the element factory - it is empty anyway.
       if (!elementFactory.hasDartCore) {
         contextObjects.analysisContext.clearTypeProvider();
-        _createElementFactory();
+        elementFactory.declareDartCoreDynamicNever();
       }
+
       var cBundle = CiderLinkedLibraryCycle.fromBuffer(bytes);
       inputBundles.add(cBundle.bundle);
       elementFactory.addBundle(
@@ -665,29 +726,19 @@
         '[librariesLinkedTimer: ${librariesLinkedTimer.elapsedMilliseconds} ms]',
       );
     });
-
-    // There might be a rare (and wrong) situation, when the external summaries
-    // already include the [targetLibrary]. When this happens, [loadBundle]
-    // exists without doing any work. But the type provider must be created.
-    _createElementFactoryTypeProvider();
   }
 
-  void _createElementFactory() {
-    elementFactory = LinkedElementFactory(
-      contextObjects.analysisContext,
-      contextObjects.analysisSession,
-      Reference.root(),
+  /// Remove libraries represented by the [removed] files.
+  /// If we need these libraries later, we will relink and reattach them.
+  void remove(List<FileState> removed) {
+    elementFactory.removeLibraries(
+      removed.map((e) => e.uriStr).toList(),
     );
-  }
 
-  /// Ensure that type provider is created.
-  void _createElementFactoryTypeProvider() {
-    var analysisContext = contextObjects.analysisContext;
-    if (analysisContext.typeProviderNonNullableByDefault == null) {
-      var dartCore = elementFactory.libraryOfUri('dart:core');
-      var dartAsync = elementFactory.libraryOfUri('dart:async');
-      elementFactory.createTypeProviders(dartCore, dartAsync);
-    }
+    var removedSet = removed.toSet();
+    loadedBundles.removeWhere((cycle) {
+      return cycle.libraries.any(removedSet.contains);
+    });
   }
 
   static CiderLinkedLibraryCycleBuilder serializeBundle(
diff --git a/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
new file mode 100644
index 0000000..92fef68
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/annotation_resolver.dart
@@ -0,0 +1,343 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/constant/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+class AnnotationResolver {
+  final ResolverVisitor _resolver;
+
+  AnnotationResolver(this._resolver);
+
+  LibraryElement get _definingLibrary => _resolver.definingLibrary;
+
+  ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+  void resolve(Annotation node) {
+    AstNode parent = node.parent;
+
+    _resolve1(node);
+
+    node.constructorName?.accept(_resolver);
+    Element element = node.element;
+    if (element is ExecutableElement) {
+      InferenceContext.setType(node.arguments, element.type);
+    }
+    node.arguments?.accept(_resolver);
+
+    ElementAnnotationImpl elementAnnotationImpl = node.elementAnnotation;
+    if (elementAnnotationImpl == null) {
+      // Analyzer ignores annotations on "part of" directives.
+      assert(parent is PartOfDirective);
+    } else {
+      elementAnnotationImpl.annotationAst = _createCloner().cloneNode(node);
+    }
+  }
+
+  /// Return a newly created cloner that can be used to clone constant
+  /// expressions.
+  ///
+  /// TODO(scheglov) this is duplicate
+  ConstantAstCloner _createCloner() {
+    return ConstantAstCloner();
+  }
+
+  InterfaceType _instantiateAnnotationClass(ClassElement element) {
+    return element.instantiate(
+      typeArguments: List.filled(
+        element.typeParameters.length,
+        DynamicTypeImpl.instance,
+      ),
+      nullabilitySuffix: _resolver.noneOrStarSuffix,
+    );
+  }
+
+  void _resolve1(Annotation node) {
+    var nodeName = node.name;
+
+    if (nodeName is PrefixedIdentifier) {
+      var prefix = nodeName.prefix;
+      var identifier = nodeName.identifier;
+
+      prefix.accept(_resolver);
+      var prefixElement = prefix.staticElement;
+
+      if (prefixElement is ClassElement && node.arguments != null) {
+        var element = prefixElement.getNamedConstructor(identifier.name);
+        element = _resolver.toLegacyElement(element);
+
+        identifier.staticElement = element;
+        identifier.staticType = element?.type ?? DynamicTypeImpl.instance;
+        // TODO(scheglov) error?
+      } else if (prefixElement is PrefixElement) {
+        var resolver = PropertyElementResolver(_resolver);
+        var result = resolver.resolvePrefixedIdentifier(
+          node: nodeName,
+          hasRead: true,
+          hasWrite: false,
+          forAnnotation: true,
+        );
+
+        var element = result.readElement;
+        identifier.staticElement = element;
+
+        if (element == null) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.UNDEFINED_ANNOTATION,
+            node,
+            [identifier.name],
+          );
+        }
+      } else {
+        var resolver = PropertyElementResolver(_resolver);
+        var result = resolver.resolvePrefixedIdentifier(
+          node: nodeName,
+          hasRead: true,
+          hasWrite: false,
+          forAnnotation: true,
+        );
+
+        var element = result.readElement;
+        identifier.staticElement = element;
+
+        DartType type;
+        if (element is PropertyAccessorElement && element.isGetter) {
+          type = element.returnType;
+        } else {
+          type = DynamicTypeImpl.instance;
+        }
+        identifier.staticType = type;
+      }
+    } else {
+      var identifier = nodeName as SimpleIdentifier;
+
+      var resolver = PropertyElementResolver(_resolver);
+      var result = resolver.resolveSimpleIdentifier(
+        node: identifier,
+        hasRead: true,
+        hasWrite: false,
+      );
+
+      var element = result.readElement;
+      identifier.staticElement = element;
+
+      if (element == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_ANNOTATION,
+          node,
+          [identifier.name],
+        );
+      }
+
+      DartType type;
+      if (element is ClassElement) {
+        type = _resolver.typeProvider.typeType;
+      } else if (element is PropertyAccessorElement && element.isGetter) {
+        type = element.returnType;
+      } else {
+        type = DynamicTypeImpl.instance;
+      }
+      identifier.staticType = type;
+    }
+
+    _resolveAnnotationElement(node);
+  }
+
+  void _resolveAnnotationConstructorInvocationArguments(
+      Annotation annotation, ConstructorElement constructor) {
+    ArgumentList argumentList = annotation.arguments;
+    // error will be reported in ConstantVerifier
+    if (argumentList == null) {
+      return;
+    }
+    // resolve arguments to parameters
+    List<ParameterElement> parameters =
+        _resolveArgumentsToFunction(argumentList, constructor);
+    if (parameters != null) {
+      argumentList.correspondingStaticParameters = parameters;
+    }
+  }
+
+  /// Continues resolution of the given [annotation].
+  void _resolveAnnotationElement(Annotation annotation) {
+    SimpleIdentifier nameNode1;
+    SimpleIdentifier nameNode2;
+    {
+      Identifier annName = annotation.name;
+      if (annName is PrefixedIdentifier) {
+        nameNode1 = annName.prefix;
+        nameNode2 = annName.identifier;
+      } else {
+        nameNode1 = annName as SimpleIdentifier;
+        nameNode2 = null;
+      }
+    }
+    SimpleIdentifier nameNode3 = annotation.constructorName;
+    ConstructorElement constructor;
+    bool undefined = false;
+    //
+    // CONST or Class(args)
+    //
+    if (nameNode1 != null && nameNode2 == null && nameNode3 == null) {
+      Element element1 = nameNode1.staticElement;
+      // TODO(scheglov) Must be const.
+      if (element1 is VariableElement) {
+        return;
+      }
+      // CONST
+      if (element1 is PropertyAccessorElement) {
+        _resolveAnnotationElementGetter(annotation, element1);
+        return;
+      }
+      // Class(args)
+      if (element1 is ClassElement) {
+        constructor = _instantiateAnnotationClass(element1)
+            .lookUpConstructor(null, _definingLibrary);
+        constructor = _resolver.toLegacyElement(constructor);
+      } else if (element1 == null) {
+        undefined = true;
+      }
+    }
+    //
+    // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args)
+    //
+    if (nameNode1 != null && nameNode2 != null && nameNode3 == null) {
+      Element element1 = nameNode1.staticElement;
+      Element element2 = nameNode2.staticElement;
+      // Class.CONST - not resolved yet
+      if (element1 is ClassElement) {
+        element2 = element1.lookUpGetter(nameNode2.name, _definingLibrary);
+        element2 = _resolver.toLegacyElement(element2);
+      }
+      // prefix.CONST or Class.CONST
+      if (element2 is PropertyAccessorElement) {
+        nameNode2.staticElement = element2;
+        annotation.element = element2;
+        _resolveAnnotationElementGetter(annotation, element2);
+        return;
+      }
+      // prefix.Class()
+      if (element2 is ClassElement) {
+        constructor = element2.unnamedConstructor;
+        constructor = _resolver.toLegacyElement(constructor);
+      }
+      // Class.constructor(args)
+      if (element1 is ClassElement) {
+        constructor = _instantiateAnnotationClass(element1)
+            .lookUpConstructor(nameNode2.name, _definingLibrary);
+        constructor = _resolver.toLegacyElement(constructor);
+        nameNode2.staticElement = constructor;
+      }
+      if (element1 is PrefixElement && element2 == null) {
+        undefined = true;
+      }
+      if (element1 == null && element2 == null) {
+        undefined = true;
+      }
+    }
+    //
+    // prefix.Class.CONST or prefix.Class.constructor(args)
+    //
+    if (nameNode1 != null && nameNode2 != null && nameNode3 != null) {
+      Element element2 = nameNode2.staticElement;
+      // element2 should be ClassElement
+      if (element2 is ClassElement) {
+        String name3 = nameNode3.name;
+        // prefix.Class.CONST
+        PropertyAccessorElement getter =
+            element2.lookUpGetter(name3, _definingLibrary);
+        if (getter != null) {
+          getter = _resolver.toLegacyElement(getter);
+          nameNode3.staticElement = getter;
+          annotation.element = getter;
+          _resolveAnnotationElementGetter(annotation, getter);
+          return;
+        }
+        // prefix.Class.constructor(args)
+        constructor = _instantiateAnnotationClass(element2)
+            .lookUpConstructor(name3, _definingLibrary);
+        constructor = _resolver.toLegacyElement(constructor);
+        nameNode3.staticElement = constructor;
+      } else if (element2 == null) {
+        undefined = true;
+      }
+    }
+    // we need constructor
+    if (constructor == null) {
+      if (!undefined) {
+        // If the class was not found then we've already reported the error.
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      }
+      return;
+    }
+    // record element
+    annotation.element = constructor;
+    // resolve arguments
+    _resolveAnnotationConstructorInvocationArguments(annotation, constructor);
+  }
+
+  void _resolveAnnotationElementGetter(
+      Annotation annotation, PropertyAccessorElement accessorElement) {
+    // accessor should be synthetic
+    if (!accessorElement.isSynthetic) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, annotation);
+      return;
+    }
+    // variable should be constant
+    VariableElement variableElement = accessorElement.variable;
+    if (!variableElement.isConst) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
+      return;
+    }
+    // no arguments
+    if (annotation.arguments != null) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
+          annotation.name,
+          [annotation.name]);
+    }
+    // OK
+    return;
+  }
+
+  /// Given an [argumentList] and the [executableElement] that will be invoked
+  /// using those argument, compute the list of parameters that correspond to
+  /// the list of arguments. An error will be reported if any of the arguments
+  /// cannot be matched to a parameter. Return the parameters that correspond to
+  /// the arguments, or `null` if no correspondence could be computed.
+  ///
+  /// TODO(scheglov) this is duplicate
+  List<ParameterElement> _resolveArgumentsToFunction(
+      ArgumentList argumentList, ExecutableElement executableElement) {
+    if (executableElement == null) {
+      return null;
+    }
+    List<ParameterElement> parameters = executableElement.parameters;
+    return _resolveArgumentsToParameters(argumentList, parameters);
+  }
+
+  /// Given an [argumentList] and the [parameters] related to the element that
+  /// will be invoked using those arguments, compute the list of parameters that
+  /// correspond to the list of arguments. An error will be reported if any of
+  /// the arguments cannot be matched to a parameter. Return the parameters that
+  /// correspond to the arguments.
+  ///
+  /// TODO(scheglov) this is duplicate
+  List<ParameterElement> _resolveArgumentsToParameters(
+      ArgumentList argumentList, List<ParameterElement> parameters) {
+    return ResolverVisitor.resolveArgumentsToParameters(
+        argumentList, parameters, _errorReporter.reportErrorForNode);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 4fd07d6..6fd621d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -10,18 +10,13 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/error/nullable_dereference_verifier.dart';
-import 'package:analyzer/src/generated/migration.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:meta/meta.dart';
 
 /// Helper for resolving [AssignmentExpression]s.
@@ -48,56 +43,68 @@
 
   bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
 
-  MigrationResolutionHooks get _migrationResolutionHooks {
-    return _resolver.migrationResolutionHooks;
-  }
-
-  NullableDereferenceVerifier get _nullableDereferenceVerifier =>
-      _resolver.nullableDereferenceVerifier;
-
   TypeProvider get _typeProvider => _resolver.typeProvider;
 
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   void resolve(AssignmentExpressionImpl node) {
+    var operator = node.operator.type;
+    var hasRead = operator != TokenType.EQ;
+    var isIfNull = operator == TokenType.QUESTION_QUESTION_EQ;
+
+    var leftResolution = _resolver.resolveForWrite(
+      node: node.leftHandSide,
+      hasRead: hasRead,
+    );
+
     var left = node.leftHandSide;
     var right = node.rightHandSide;
 
-    if (left is SimpleIdentifier) {
-      _resolve_SimpleIdentifier(node, left);
-      return;
+    var readElement = leftResolution.readElement;
+    var writeElement = leftResolution.writeElement;
+
+    if (hasRead) {
+      _resolver.setReadElement(left, readElement);
+    }
+    _resolver.setWriteElement(left, writeElement);
+    _resolver.migrationResolutionHooks
+        ?.setCompoundAssignmentExpressionTypes(node);
+
+    _resolver.setAssignmentBackwardCompatibility(
+      assignment: node,
+      left: left,
+      hasRead: hasRead,
+    );
+
+    _resolveOperator(node);
+
+    {
+      var leftType = node.writeType;
+      if (writeElement is VariableElement) {
+        leftType = _resolver.localVariableTypeProvider.getType(left);
+      }
+      _setRhsContext(node, leftType, operator, right);
     }
 
-    left?.accept(_resolver);
-    left = node.leftHandSide;
+    var flow = _flowAnalysis?.flow;
+    if (flow != null && isIfNull) {
+      flow.ifNullExpression_rightBegin(left, node.readType);
+    }
 
-    var operator = node.operator.type;
-    if (operator != TokenType.EQ) {
-      if (node.readElement == null || node.readType == null) {
-        _resolver.setReadElement(left, null);
+    right.accept(_resolver);
+
+    _resolveTypes(node);
+
+    if (flow != null) {
+      if (writeElement is VariableElement) {
+        flow.write(writeElement, node.staticType);
+      }
+      if (isIfNull) {
+        flow.ifNullExpression_end();
       }
     }
-    if (node.writeElement == null || node.writeType == null) {
-      _resolver.setWriteElement(left, null);
-    }
 
-    _resolve1(node, getReadType(left));
-
-    _setRhsContext(node, left.staticType, operator, right);
-
-    _flowAnalysis?.assignmentExpression(node);
-
-    if (operator != TokenType.EQ &&
-        operator != TokenType.QUESTION_QUESTION_EQ) {
-      _nullableDereferenceVerifier.expression(left);
-    }
-
-    right?.accept(_resolver);
-    right = node.rightHandSide;
-
-    _resolve2(node);
-
-    _flowAnalysis?.assignmentExpression_afterRight(node);
+    _resolver.nullShortingTermination(node);
   }
 
   void _checkForInvalidAssignment(
@@ -105,11 +112,6 @@
     Expression right,
     DartType rightType,
   ) {
-    // TODO(scheglov) should not happen
-    if (writeType == null) {
-      return;
-    }
-
     if (!writeType.isVoid && _checkForUseOfVoidResult(right)) {
       return;
     }
@@ -149,131 +151,23 @@
     return true;
   }
 
-  /// Record that the static type of the given node is the given type.
-  ///
-  /// @param expression the node whose type is to be recorded
-  /// @param type the static type of the node
-  ///
-  /// TODO(scheglov) this is duplication
-  void _recordStaticType(Expression expression, DartType type) {
-    if (_resolver.migrationResolutionHooks != null) {
-      // TODO(scheglov) type cannot be null
-      type = _migrationResolutionHooks.modifyExpressionType(
-        expression,
-        type ?? DynamicTypeImpl.instance,
-      );
-    }
+  void _resolveOperator(AssignmentExpressionImpl node) {
+    var left = node.leftHandSide;
+    var operator = node.operator;
+    var operatorType = operator.type;
 
-    // TODO(scheglov) type cannot be null
-    if (type == null) {
-      expression.staticType = DynamicTypeImpl.instance;
-    } else {
-      expression.staticType = type;
-      if (_typeSystem.isBottom(type)) {
-        _flowAnalysis?.flow?.handleExit();
-      }
-    }
-  }
-
-  void _reportNotSetter(
-    Expression left,
-    Element requested,
-    Element recovery,
-  ) {
-    if (requested != null) {
-      if (requested is VariableElement) {
-        if (requested.isConst) {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
-            left,
-          );
-        } else if (requested.isFinal) {
-          if (_isNonNullableByDefault) {
-            // Handled during resolution, with flow analysis.
-          } else {
-            _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
-              left,
-              [requested.name],
-            );
-          }
-        }
-      }
-      return;
-    }
-
-    if (recovery is ClassElement ||
-        recovery is DynamicElementImpl ||
-        recovery is FunctionTypeAliasElement ||
-        recovery is TypeParameterElement) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
-        left,
-      );
-    } else if (recovery is FunctionElement) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION,
-        left,
-      );
-    } else if (recovery is MethodElement) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
-        left,
-      );
-    } else if (recovery is PrefixElement) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-        left,
-        [recovery.name],
-      );
-    } else if (recovery is PropertyAccessorElement && recovery.isGetter) {
-      var variable = recovery.variable;
-      if (variable.isConst) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
-          left,
-        );
-      } else if (variable is FieldElement && variable.isSynthetic) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
-          left,
-          [variable.name, variable.enclosingElement.displayName],
-        );
-      } else {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL,
-          left,
-          [variable.name],
-        );
-      }
-    } else if (recovery is MultiplyDefinedElementImpl) {
-      // Will be reported in ErrorVerifier.
-    } else {
-      if (left is SimpleIdentifier && !left.isSynthetic) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
-          left,
-          [left.name],
-        );
-      }
-    }
-  }
-
-  void _resolve1(AssignmentExpressionImpl node, DartType leftType) {
-    Token operator = node.operator;
-    TokenType operatorType = operator.type;
-    Expression leftHandSide = node.leftHandSide;
-
+    var leftType = node.readType;
     if (identical(leftType, NeverTypeImpl.instance)) {
       return;
     }
 
-    _assignmentShared.checkFinalAlreadyAssigned(leftHandSide);
+    // TODO(scheglov) Use VariableElement and do in resolveForWrite() ?
+    _assignmentShared.checkFinalAlreadyAssigned(left);
 
-    // For any compound assignments to a void or nullable variable, report it.
-    // Example: `y += voidFn()`, not allowed.
+    // Values of the type void cannot be used.
+    // Example: `y += 0`, is not allowed.
     if (operatorType != TokenType.EQ) {
-      if (leftType != null && leftType.isVoid) {
+      if (leftType.isVoid) {
         _errorReporter.reportErrorForToken(
           CompileTimeErrorCode.USE_OF_VOID_RESULT,
           operator,
@@ -282,39 +176,41 @@
       }
     }
 
-    if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ &&
-        operatorType != TokenType.BAR_BAR_EQ &&
-        operatorType != TokenType.EQ &&
-        operatorType != TokenType.QUESTION_QUESTION_EQ) {
-      operatorType = operatorFromCompoundAssignment(operatorType);
-      if (leftHandSide != null) {
-        String methodName = operatorType.lexeme;
-        // TODO(brianwilkerson) Change the [methodNameNode] from the left hand
-        //  side to the operator.
-        var result = _typePropertyResolver.resolve(
-          receiver: leftHandSide,
-          receiverType: leftType,
-          name: methodName,
-          receiverErrorNode: leftHandSide,
-          nameErrorNode: leftHandSide,
-        );
-        node.staticElement = result.getter;
-        if (_shouldReportInvalidMember(leftType, result)) {
-          _errorReporter.reportErrorForToken(
-            CompileTimeErrorCode.UNDEFINED_OPERATOR,
-            operator,
-            [methodName, leftType],
-          );
-        }
-      }
+    if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operatorType == TokenType.BAR_BAR_EQ ||
+        operatorType == TokenType.EQ ||
+        operatorType == TokenType.QUESTION_QUESTION_EQ) {
+      return;
+    }
+
+    var binaryOperatorType = operatorFromCompoundAssignment(operatorType);
+    var methodName = binaryOperatorType.lexeme;
+
+    var result = _typePropertyResolver.resolve(
+      receiver: left,
+      receiverType: leftType,
+      name: methodName,
+      receiverErrorNode: left,
+      nameErrorEntity: operator,
+    );
+    node.staticElement = result.getter;
+    if (result.needsGetterError) {
+      _errorReporter.reportErrorForToken(
+        CompileTimeErrorCode.UNDEFINED_OPERATOR,
+        operator,
+        [methodName, leftType],
+      );
     }
   }
 
-  void _resolve2(AssignmentExpressionImpl node) {
-    TokenType operator = node.operator.type;
+  void _resolveTypes(AssignmentExpressionImpl node) {
+    DartType assignedType;
+    DartType nodeType;
+
+    var operator = node.operator.type;
     if (operator == TokenType.EQ) {
-      var rightType = node.rightHandSide.staticType;
-      _inferenceHelper.recordStaticType(node, rightType);
+      assignedType = node.rightHandSide.staticType;
+      nodeType = assignedType;
     } else if (operator == TokenType.QUESTION_QUESTION_EQ) {
       var leftType = node.readType;
 
@@ -323,124 +219,38 @@
         leftType = _typeSystem.promoteToNonNull(leftType);
       }
 
-      var rightType = node.rightHandSide.staticType;
-      var result = _typeSystem.getLeastUpperBound(leftType, rightType);
-
-      _inferenceHelper.recordStaticType(node, result);
+      assignedType = node.rightHandSide.staticType;
+      nodeType = _typeSystem.getLeastUpperBound(leftType, assignedType);
     } else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
         operator == TokenType.BAR_BAR_EQ) {
-      _inferenceHelper.recordStaticType(node, _typeProvider.boolType);
+      assignedType = _typeProvider.boolType;
+      nodeType = assignedType;
     } else {
-      var rightType = node.rightHandSide.staticType;
-
-      var leftReadType = getReadType(node.leftHandSide);
-      if (identical(leftReadType, NeverTypeImpl.instance)) {
-        _inferenceHelper.recordStaticType(node, rightType);
-        return;
-      }
-
       var operatorElement = node.staticElement;
-      var type = operatorElement?.returnType ?? DynamicTypeImpl.instance;
-      type = _typeSystem.refineBinaryExpressionType(
-        leftReadType,
-        operator,
-        rightType,
-        type,
-        operatorElement,
-      );
-      _inferenceHelper.recordStaticType(node, type);
-
-      var leftWriteType = _getWriteType(node.leftHandSide);
-      if (!_typeSystem.isAssignableTo2(type, leftWriteType)) {
-        _resolver.errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ASSIGNMENT,
-          node.rightHandSide,
-          [type, leftWriteType],
+      if (operatorElement != null) {
+        var leftType = node.readType;
+        var rightType = node.rightHandSide.staticType;
+        assignedType = _typeSystem.refineBinaryExpressionType(
+          leftType,
+          operator,
+          rightType,
+          operatorElement.returnType,
+          operatorElement,
         );
-      }
-    }
-    _resolver.nullShortingTermination(node);
-  }
-
-  void _resolve_SimpleIdentifier(
-    AssignmentExpressionImpl node,
-    SimpleIdentifier left,
-  ) {
-    var right = node.rightHandSide;
-    var operator = node.operator.type;
-
-    if (operator != TokenType.EQ) {
-      var readLookup = _resolver.lexicalLookup(node: left, setter: false);
-      var readElement = readLookup.requested;
-      _resolver.setReadElement(left, readElement);
-    }
-
-    var writeLookup = _resolver.lexicalLookup(node: left, setter: true);
-    var writeElement = writeLookup.requested ?? writeLookup.recovery;
-    _resolver.setWriteElement(left, writeElement);
-    _reportNotSetter(left, writeLookup.requested, writeLookup.recovery);
-
-    // TODO(scheglov) This is mostly necessary for backward compatibility.
-    // Although we also use `staticElement` for `getType(left)` below.
-    {
-      if (operator != TokenType.EQ) {
-        var readElement = node.readElement;
-        if (readElement is PropertyAccessorElement) {
-          left.auxiliaryElements = AuxiliaryElements(readElement);
-        }
-      }
-      left.staticElement = node.writeElement;
-      if (node.readElement is VariableElement) {
-        var leftType = _resolver.localVariableTypeProvider.getType(left);
-        _recordStaticType(left, leftType);
       } else {
-        _recordStaticType(left, node.writeType);
+        assignedType = DynamicTypeImpl.instance;
       }
+      nodeType = assignedType;
     }
 
-    if (operator != TokenType.EQ) {
-      // TODO(scheglov) Change this method to work with elements.
-      _resolver.checkReadOfNotAssignedLocalVariable(left);
-    }
+    _inferenceHelper.recordStaticType(node, nodeType);
 
-    _resolve1(node, node.readType);
-
-    {
-      var leftType = node.writeType;
-      if (node.writeElement is VariableElement) {
-        leftType = _resolver.localVariableTypeProvider.getType(left);
-      }
-      _setRhsContext(node, leftType, operator, right);
-    }
-
-    var flow = _flowAnalysis?.flow;
-    if (flow != null && operator == TokenType.QUESTION_QUESTION_EQ) {
-      flow.ifNullExpression_rightBegin(left, node.readType);
-    }
-
-    right?.accept(_resolver);
-    right = node.rightHandSide;
-
-    _resolve2(node);
-
-    // TODO(scheglov) inline into resolve2().
-    DartType assignedType;
-    if (operator == TokenType.EQ ||
-        operator == TokenType.QUESTION_QUESTION_EQ) {
-      assignedType = right.staticType;
-    } else {
-      assignedType = node.staticType;
-    }
-    _checkForInvalidAssignment(node.writeType, right, assignedType);
-
-    if (flow != null) {
-      if (writeElement is VariableElement) {
-        flow.write(writeElement, node.staticType);
-      }
-      if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
-        flow.ifNullExpression_end();
-      }
-    }
+    // TODO(scheglov) Remove from ErrorVerifier?
+    _checkForInvalidAssignment(
+      node.writeType,
+      node.rightHandSide,
+      assignedType,
+    );
   }
 
   void _setRhsContext(AssignmentExpressionImpl node, DartType leftType,
@@ -468,33 +278,6 @@
         break;
     }
   }
-
-  /// Return `true` if we should report an error for the lookup [result] on
-  /// the [type].
-  // TODO(scheglov) this is duplicate
-  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
-    if (result.isNone && type != null && !type.isDynamic) {
-      if (_typeSystem.isNonNullableByDefault &&
-          _typeSystem.isPotentiallyNullable(type)) {
-        return false;
-      }
-      return true;
-    }
-    return false;
-  }
-
-  /// The type of the RHS assigned to [left] must be subtype of the return.
-  static DartType _getWriteType(Expression left) {
-    // We are writing, so ignore promotions.
-    if (left is SimpleIdentifier) {
-      var element = left.staticElement;
-      if (element is PromotableElement) {
-        return element.type;
-      }
-    }
-
-    return left.staticType;
-  }
 }
 
 class AssignmentExpressionShared {
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index ddab194..7572eeb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -18,7 +18,6 @@
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/type_promotion_manager.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:meta/meta.dart';
 
 /// Helper for resolving [BinaryExpression]s.
@@ -107,29 +106,6 @@
     );
   }
 
-  /// Gets the definite type of expression, which can be used in cases where
-  /// the most precise type is desired, for example computing the least upper
-  /// bound.
-  ///
-  /// See [getExpressionType] for more information. Without strong mode, this is
-  /// equivalent to [_getStaticType].
-  ///
-  /// TODO(scheglov) this is duplicate
-  DartType _getExpressionType(Expression expr, {bool read = false}) =>
-      getExpressionType(expr, _typeSystem, _typeProvider, read: read);
-
-  /// Return the static type of the given [expression] that is to be used for
-  /// type analysis.
-  ///
-  /// TODO(scheglov) this is duplicate
-  DartType _getStaticType(Expression expression, {bool read = false}) {
-    if (expression is NullLiteral) {
-      return _typeProvider.nullType;
-    }
-    DartType type = read ? getReadType(expression) : expression.staticType;
-    return _resolveTypeParameter(type);
-  }
-
   void _resolveEqual(BinaryExpressionImpl node, {@required bool notEqual}) {
     var left = node.leftOperand;
     left.accept(_resolver);
@@ -170,7 +146,7 @@
 
     left.accept(_resolver);
     left = node.leftOperand;
-    var leftType = _getExpressionType(left, read: false);
+    var leftType = left.staticType;
 
     var rightContextType = InferenceContext.getContext(node);
     if (rightContextType == null || rightContextType.isDynamic) {
@@ -183,9 +159,7 @@
     right = node.rightOperand;
     flow?.ifNullExpression_end();
 
-    // TODO(scheglov) This (and above) is absolutely wrong, and convoluted.
-    // This is just the status quo, until we can make types straight.
-    var rightType = _getExpressionType(right, read: false);
+    var rightType = right.staticType;
     if (_isNonNullableByDefault) {
       var promotedLeftType = _typeSystem.promoteToNonNull(leftType);
       _analyzeLeastUpperBoundTypes(node, promotedLeftType, rightType);
@@ -202,6 +176,7 @@
     InferenceContext.setType(left, _typeProvider.boolType);
     InferenceContext.setType(right, _typeProvider.boolType);
 
+    flow?.logicalBinaryOp_begin();
     left.accept(_resolver);
     left = node.leftOperand;
 
@@ -239,6 +214,7 @@
     InferenceContext.setType(left, _typeProvider.boolType);
     InferenceContext.setType(right, _typeProvider.boolType);
 
+    flow?.logicalBinaryOp_begin();
     left.accept(_resolver);
     left = node.leftOperand;
 
@@ -320,7 +296,8 @@
       return;
     }
 
-    var leftType = _getStaticType(leftOperand);
+    var leftType = leftOperand.staticType;
+    leftType = _resolveTypeParameter(leftType);
 
     if (identical(leftType, NeverTypeImpl.instance)) {
       _resolver.errorReporter.reportErrorForNode(
@@ -339,12 +316,12 @@
       receiverType: leftType,
       name: methodName,
       receiverErrorNode: leftOperand,
-      nameErrorNode: node,
+      nameErrorEntity: node,
     );
 
     node.staticElement = result.getter;
     node.staticInvokeType = result.getter?.type;
-    if (_shouldReportInvalidMember(leftType, result)) {
+    if (result.needsGetterError) {
       if (leftOperand is SuperExpression) {
         _errorReporter.reportErrorForToken(
           CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR,
@@ -362,16 +339,21 @@
   }
 
   void _resolveUserDefinableType(BinaryExpressionImpl node) {
-    if (identical(node.leftOperand.staticType, NeverTypeImpl.instance)) {
+    var leftOperand = node.leftOperand;
+
+    var leftType = leftOperand.staticType;
+    leftType = _resolveTypeParameter(leftType);
+
+    if (identical(leftType, NeverTypeImpl.instance)) {
       _inferenceHelper.recordStaticType(node, NeverTypeImpl.instance);
       return;
     }
 
     DartType staticType =
         node.staticInvokeType?.returnType ?? DynamicTypeImpl.instance;
-    if (node.leftOperand is! ExtensionOverride) {
+    if (leftOperand is! ExtensionOverride) {
       staticType = _typeSystem.refineBinaryExpressionType(
-        _getStaticType(node.leftOperand),
+        leftType,
         node.operator.type,
         node.rightOperand.staticType,
         staticType,
@@ -380,18 +362,4 @@
     }
     _inferenceHelper.recordStaticType(node, staticType);
   }
-
-  /// Return `true` if we should report an error for the lookup [result] on
-  /// the [type].
-  ///
-  /// TODO(scheglov) this is duplicate
-  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
-    if (result.isNone && type != null && !type.isDynamic) {
-      if (_isNonNullableByDefault && _typeSystem.isPotentiallyNullable(type)) {
-        return false;
-      }
-      return true;
-    }
-    return false;
-  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart b/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart
index 6b5aaf4..b470871 100644
--- a/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/body_inference_context.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:meta/meta.dart';
 
@@ -137,7 +136,7 @@
     }
 
     // Otherwise, let `S` be `R`.
-    return nonNullifyType(_typeSystem, R);
+    return _typeSystem.nonNullifyLegacy(R);
   }
 
   DartType _computeActualReturnedType({
diff --git a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
index 59e5543..a35cc79 100644
--- a/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/extension_member_resolver.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -40,12 +41,12 @@
   ///
   /// If no applicable extensions, return [ResolutionResult.none].
   ///
-  /// If the match is ambiguous, report an error and return
-  /// [ResolutionResult.ambiguous].
+  /// If the match is ambiguous, report an error on the [nameEntity], and
+  /// return [ResolutionResult.ambiguous].
   ResolutionResult findExtension(
     DartType type,
+    SyntacticEntity nameEntity,
     String name,
-    Expression target,
   ) {
     var extensions = _getApplicable(type, name);
 
@@ -62,9 +63,10 @@
       return extension.asResolutionResult;
     }
 
-    _errorReporter.reportErrorForNode(
+    _errorReporter.reportErrorForOffset(
       CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS,
-      target,
+      nameEntity.offset,
+      nameEntity.length,
       [
         name,
         extensions[0].extension.name,
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
index 915f509..0fab9d3 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis_visitor.dart
@@ -341,13 +341,6 @@
   }
 
   @override
-  bool isLocalVariableWithoutDeclaredType(PromotableElement variable) {
-    return variable is LocalVariableElement &&
-        variable.hasImplicitType &&
-        !variable.hasInitializer;
-  }
-
-  @override
   bool isNever(DartType type) {
     return typeSystem.isBottom(type);
   }
@@ -443,7 +436,7 @@
     assignedVariables.beginNode();
     _declareParameters(node.functionExpression.parameters);
     super.visitFunctionDeclaration(node);
-    assignedVariables.endNode(node, isClosure: true);
+    assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
   }
 
   @override
@@ -457,7 +450,7 @@
     assignedVariables.beginNode();
     _declareParameters(node.parameters);
     super.visitFunctionExpression(node);
-    assignedVariables.endNode(node, isClosure: true);
+    assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
   }
 
   @override
@@ -530,8 +523,15 @@
         grandParent is FieldDeclaration) {
       throw StateError('Should not visit top level declarations');
     }
-    assignedVariables.declare(node.declaredElement);
-    super.visitVariableDeclaration(node);
+    var declaredElement = node.declaredElement;
+    assignedVariables.declare(declaredElement);
+    if (declaredElement.isLate && node.initializer != null) {
+      assignedVariables.beginNode();
+      super.visitVariableDeclaration(node);
+      assignedVariables.endNode(node, isClosureOrLateVariableInitializer: true);
+    } else {
+      super.visitVariableDeclaration(node);
+    }
   }
 
   @override
@@ -576,7 +576,6 @@
       } else if (forLoopParts is ForEachPartsWithDeclaration) {
         var variable = forLoopParts.loopVariable.declaredElement;
         assignedVariables.declare(variable);
-        assignedVariables.write(variable);
       } else {
         throw StateError('Unrecognized for loop parts');
       }
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index 454eeef..8946ab4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -100,7 +100,7 @@
     if (identifier != null) {
       identifierElement = identifier.staticElement;
       if (identifierElement is VariableElement) {
-        valueType = identifierElement.type;
+        valueType = _resolver.localVariableTypeProvider.getType(identifier);
       } else if (identifierElement is PropertyAccessorElement) {
         var parameters = identifierElement.parameters;
         if (parameters.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
index b87deb7..9c98040 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_invocation_resolver.dart
@@ -121,7 +121,7 @@
       receiverType: receiverType,
       name: FunctionElement.CALL_METHOD_NAME,
       receiverErrorNode: function,
-      nameErrorNode: function,
+      nameErrorEntity: function,
     );
     var callElement = result.getter;
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index f496a13..0f3a2b1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -7,7 +7,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
@@ -112,7 +111,7 @@
           inferredType = _migrationResolutionHooks.modifyInferredParameterType(
               p, inferredType);
         } else {
-          inferredType = nonNullifyType(_typeSystem, inferredType);
+          inferredType = _typeSystem.nonNullifyLegacy(inferredType);
         }
         if (!inferredType.isDynamic) {
           p.type = inferredType;
diff --git a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
index 2329df1..1b4b7a0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/invocation_inference_helper.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -22,7 +21,6 @@
   final ErrorReporter _errorReporter;
   final FlowAnalysisHelper _flowAnalysis;
   final TypeSystemImpl _typeSystem;
-  final TypeProviderImpl _typeProvider;
   final MigrationResolutionHooks _migrationResolutionHooks;
 
   List<DartType> _typeArgumentTypes;
@@ -37,7 +35,6 @@
       : _resolver = resolver,
         _errorReporter = errorReporter,
         _typeSystem = typeSystem,
-        _typeProvider = typeSystem.typeProvider,
         _flowAnalysis = flowAnalysis,
         _migrationResolutionHooks = migrationResolutionHooks;
 
@@ -157,43 +154,29 @@
     return null;
   }
 
-  /// Given a method invocation [node], attempt to infer a better
-  /// type for the result if the target is dynamic and the method
-  /// being called is one of the object methods.
-  bool inferMethodInvocationObject(MethodInvocation node) {
-    // If we have a call like `toString()` or `libraryPrefix.toString()`, don't
-    // infer it.
-    Expression target = node.realTarget;
-    if (target == null ||
-        target is SimpleIdentifier && target.staticElement is PrefixElement) {
-      return false;
-    }
-    DartType nodeType = node.staticInvokeType;
-    if (nodeType == null ||
-        !nodeType.isDynamic ||
-        node.argumentList.arguments.isNotEmpty) {
-      return false;
-    }
-    // Object methods called on dynamic targets can have their types improved.
-    String name = node.methodName.name;
-    MethodElement inferredElement =
-        _typeProvider.objectType.element.getMethod(name);
-    if (inferredElement == null || inferredElement.isStatic) {
-      return false;
-    }
-    inferredElement = _resolver.toLegacyElement(inferredElement);
-    DartType inferredType = inferredElement.type;
-    if (inferredType is FunctionType) {
-      DartType returnType = inferredType.returnType;
-      if (inferredType.parameters.isEmpty &&
-          returnType is InterfaceType &&
-          _typeProvider.nonSubtypableClasses.contains(returnType.element)) {
-        node.staticInvokeType = inferredType;
-        recordStaticType(node, inferredType.returnType);
-        return true;
+  /// Given an uninstantiated generic function type, referenced by the
+  /// [identifier] in the tear-off [expression], try to infer the instantiated
+  /// generic function type from the surrounding context.
+  DartType inferTearOff(
+    Expression expression,
+    SimpleIdentifier identifier,
+    DartType tearOffType,
+  ) {
+    var context = InferenceContext.getContext(expression);
+    if (context is FunctionType && tearOffType is FunctionType) {
+      var typeArguments = _typeSystem.inferFunctionTypeInstantiation(
+        context,
+        tearOffType,
+        errorReporter: _resolver.errorReporter,
+        errorNode: expression,
+      );
+      (identifier as SimpleIdentifierImpl).tearOffTypeArgumentTypes =
+          typeArguments;
+      if (typeArguments.isNotEmpty) {
+        return tearOffType.instantiate(typeArguments);
       }
     }
-    return false;
+    return tearOffType;
   }
 
   /// Record that the static type of the given node is the given type.
diff --git a/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart b/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart
index 19e6a7e..9e2cd18 100644
--- a/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart
@@ -58,7 +58,7 @@
       receiverType: thisType,
       name: id,
       receiverErrorNode: node,
-      nameErrorNode: node,
+      nameErrorEntity: node,
     );
 
     if (setter) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index a0725e4..2344a75 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -136,27 +136,14 @@
     }
 
     DartType receiverType = receiver.staticType;
-    receiverType = _resolveTypeParameter(receiverType);
 
-    if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
-        _typeSystem.isNonNullableByDefault) {
-      receiverType = _typeSystem.promoteToNonNull(receiverType);
-    }
-
-    if (receiverType is InterfaceType) {
-      _resolveReceiverInterfaceType(
-          node, receiver, receiverType, nameNode, name);
+    if (_typeSystem.isDynamicBounded(receiverType)) {
+      _resolveReceiverDynamicBounded(node);
       return;
     }
 
-    if (receiverType is DynamicTypeImpl) {
-      _resolveReceiverDynamic(node, name);
-      return;
-    }
-
-    if (receiverType is FunctionType) {
-      _resolveReceiverFunctionType(
-          node, receiver, receiverType, nameNode, name);
+    if (receiverType is NeverTypeImpl) {
+      _resolveReceiverNever(node, receiver, receiverType);
       return;
     }
 
@@ -165,10 +152,25 @@
       return;
     }
 
-    if (receiverType is NeverTypeImpl) {
-      _resolveReceiverNever(node, receiver, receiverType);
+    if (_migratableAstInfoProvider.isMethodInvocationNullAware(node) &&
+        _typeSystem.isNonNullableByDefault) {
+      receiverType = _typeSystem.promoteToNonNull(receiverType);
+    }
+
+    if (_typeSystem.isFunctionBounded(receiverType)) {
+      _resolveReceiverFunctionBounded(
+          node, receiver, receiverType, nameNode, name);
       return;
     }
+
+    _resolveReceiverType(
+      node: node,
+      receiver: receiver,
+      receiverType: receiverType,
+      nameNode: nameNode,
+      name: name,
+      receiverErrorNode: receiver,
+    );
   }
 
   bool _isCoreFunction(DartType type) {
@@ -291,15 +293,10 @@
       node.methodName.staticType,
     );
 
-    // TODO(scheglov) Call this only when member lookup failed?
-    var inferred = _inferenceHelper.inferMethodInvocationObject(node);
-
-    if (!inferred) {
-      DartType staticStaticType = _inferenceHelper.computeInvokeReturnType(
-        node.staticInvokeType,
-      );
-      _inferenceHelper.recordStaticType(node, staticStaticType);
-    }
+    DartType staticStaticType = _inferenceHelper.computeInvokeReturnType(
+      node.staticInvokeType,
+    );
+    _inferenceHelper.recordStaticType(node, staticStaticType);
   }
 
   /// Given that we are accessing a property of the given [classElement] with the
@@ -387,12 +384,42 @@
     _setResolution(node, member.type);
   }
 
-  void _resolveReceiverDynamic(MethodInvocation node, String name) {
-    _setDynamicResolution(node);
+  void _resolveReceiverDynamicBounded(MethodInvocation node) {
+    var nameNode = node.methodName;
+
+    var objectElement = _typeSystem.typeProvider.objectElement;
+    var target = objectElement.getMethod(nameNode.name);
+
+    var hasMatchingObjectMethod = false;
+    if (target is MethodElement) {
+      var arguments = node.argumentList.arguments;
+      hasMatchingObjectMethod = arguments.length == target.parameters.length &&
+          !arguments.any((e) => e is NamedExpression);
+      if (hasMatchingObjectMethod) {
+        target = _resolver.toLegacyElement(target);
+        nameNode.staticElement = target;
+        node.staticInvokeType = target.type;
+        node.staticType = target.returnType;
+      }
+    }
+
+    if (!hasMatchingObjectMethod) {
+      nameNode.staticType = DynamicTypeImpl.instance;
+      node.staticInvokeType = DynamicTypeImpl.instance;
+      node.staticType = DynamicTypeImpl.instance;
+    }
+
+    _setExplicitTypeArgumentTypes();
+    node.argumentList.accept(_resolver);
   }
 
-  void _resolveReceiverFunctionType(MethodInvocation node, Expression receiver,
-      FunctionType receiverType, SimpleIdentifier nameNode, String name) {
+  void _resolveReceiverFunctionBounded(
+    MethodInvocation node,
+    Expression receiver,
+    DartType receiverType,
+    SimpleIdentifier nameNode,
+    String name,
+  ) {
     if (name == FunctionElement.CALL_METHOD_NAME) {
       _setResolution(node, receiverType);
       // TODO(scheglov) Replace this with using FunctionType directly.
@@ -412,28 +439,6 @@
     );
   }
 
-  void _resolveReceiverInterfaceType(MethodInvocation node, Expression receiver,
-      InterfaceType receiverType, SimpleIdentifier nameNode, String name) {
-    if (_isCoreFunction(receiverType) &&
-        name == FunctionElement.CALL_METHOD_NAME) {
-      _resolver.nullableDereferenceVerifier.expression(
-        receiver,
-        type: receiverType,
-      );
-      _setDynamicResolution(node);
-      return;
-    }
-
-    _resolveReceiverType(
-      node: node,
-      receiver: receiver,
-      receiverType: receiverType,
-      nameNode: nameNode,
-      name: name,
-      receiverErrorNode: receiver,
-    );
-  }
-
   void _resolveReceiverNever(
     MethodInvocation node,
     Expression receiver,
@@ -485,8 +490,6 @@
 
   void _resolveReceiverNull(
       MethodInvocation node, SimpleIdentifier nameNode, String name) {
-    _resolver.checkReadOfNotAssignedLocalVariable(nameNode);
-
     var element = nameScope.lookup2(name).getter;
     if (element != null) {
       element = _resolver.toLegacyElement(element);
@@ -502,6 +505,7 @@
         return _setResolution(node, element.type);
       }
       if (element is VariableElement) {
+        _resolver.checkReadOfNotAssignedLocalVariable(nameNode, element);
         var targetType = _localVariableTypeProvider.getType(nameNode);
         return _rewriteAsFunctionExpressionInvocation(node, targetType);
       }
@@ -638,14 +642,9 @@
       receiverType: receiverType,
       name: name,
       receiverErrorNode: receiverErrorNode,
-      nameErrorNode: nameNode,
+      nameErrorEntity: nameNode,
     );
 
-    if (result.isAmbiguous) {
-      _setDynamicResolution(node);
-      return;
-    }
-
     var target = result.getter;
     if (target != null) {
       nameNode.staticElement = target;
@@ -666,6 +665,10 @@
 
     _setDynamicResolution(node);
 
+    if (!result.needsGetterError) {
+      return;
+    }
+
     String receiverClassName = '<unknown>';
     if (receiverType is InterfaceType) {
       receiverClassName = receiverType.element.name;
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index ebe40fd..dbc01c0 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -14,11 +14,9 @@
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:meta/meta.dart';
 
 /// Helper for resolving [PostfixExpression]s.
@@ -53,26 +51,28 @@
       return;
     }
 
-    node.operand.accept(_resolver);
+    var operandResolution = _resolver.resolveForWrite(
+      node: node.operand,
+      hasRead: true,
+    );
+
+    var readElement = operandResolution.readElement;
+    var writeElement = operandResolution.writeElement;
 
     var operand = node.operand;
-    if (operand is SimpleIdentifier) {
-      var element = operand.staticElement;
-      // ElementResolver does not set it.
-      if (element is VariableElement) {
-        _resolver.setReadElement(operand, element);
-        _resolver.setWriteElement(operand, element);
-      }
-    }
+    _resolver.setReadElement(operand, readElement);
+    _resolver.setWriteElement(operand, writeElement);
+    _resolver.migrationResolutionHooks
+        ?.setCompoundAssignmentExpressionTypes(node);
 
-    if (node.readElement == null || node.readType == null) {
-      _resolver.setReadElement(operand, null);
-    }
-    if (node.writeElement == null || node.writeType == null) {
-      _resolver.setWriteElement(operand, null);
-    }
+    _resolver.setAssignmentBackwardCompatibility(
+      assignment: node,
+      left: operand,
+      hasRead: true,
+    );
 
-    _assignmentShared.checkFinalAlreadyAssigned(node.operand);
+    // TODO(scheglov) Use VariableElement and do in resolveForWrite() ?
+    _assignmentShared.checkFinalAlreadyAssigned(operand);
 
     var receiverType = node.readType;
     _resolve1(node, receiverType);
@@ -84,8 +84,8 @@
   ///
   /// TODO(scheglov) this is duplicate
   void _checkForInvalidAssignmentIncDec(
-      AstNode node, Expression operand, DartType type) {
-    var operandWriteType = _getWriteType(operand);
+      PostfixExpression node, Expression operand, DartType type) {
+    var operandWriteType = node.writeType;
     if (!_typeSystem.isAssignableTo2(type, operandWriteType)) {
       _resolver.errorReporter.reportErrorForNode(
         CompileTimeErrorCode.INVALID_ASSIGNMENT,
@@ -131,16 +131,6 @@
     }
   }
 
-  DartType _getWriteType(Expression node) {
-    if (node is SimpleIdentifier) {
-      var element = node.staticElement;
-      if (element is PromotableElement) {
-        return element.type;
-      }
-    }
-    return node.staticType;
-  }
-
   void _resolve1(PostfixExpression node, DartType receiverType) {
     Expression operand = node.operand;
 
@@ -158,10 +148,10 @@
       receiverType: receiverType,
       name: methodName,
       receiverErrorNode: operand,
-      nameErrorNode: operand,
+      nameErrorEntity: operand,
     );
     node.staticElement = result.getter;
-    if (_shouldReportInvalidMember(receiverType, result)) {
+    if (result.needsGetterError) {
       if (operand is SuperExpression) {
         _errorReporter.reportErrorForToken(
           CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR,
@@ -229,25 +219,12 @@
     operand.accept(_resolver);
     operand = node.operand;
 
-    var operandType = getReadType(operand);
+    var operandType = operand.staticType;
 
     var type = _typeSystem.promoteToNonNull(operandType);
     _inferenceHelper.recordStaticType(node, type);
 
+    _resolver.nullShortingTermination(node);
     _flowAnalysis?.flow?.nonNullAssert_end(operand);
   }
-
-  /// Return `true` if we should report an error for the lookup [result] on
-  /// the [type].
-  ///
-  /// TODO(scheglov) this is duplicate
-  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
-    if (result.isNone && type != null && !type.isDynamic) {
-      if (_isNonNullableByDefault && _typeSystem.isPotentiallyNullable(type)) {
-        return false;
-      }
-      return true;
-    }
-    return false;
-  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index cd5deb0..c3c161a 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -42,40 +41,42 @@
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
-  bool get _isNonNullableByDefault => _typeSystem.isNonNullableByDefault;
-
   TypeProvider get _typeProvider => _resolver.typeProvider;
 
   TypeSystemImpl get _typeSystem => _resolver.typeSystem;
 
   void resolve(PrefixExpressionImpl node) {
     var operator = node.operator.type;
+
     if (operator == TokenType.BANG) {
       _resolveNegation(node);
       return;
     }
 
-    node.operand.accept(_resolver);
-
-    var operand = node.operand;
-    if (operand is SimpleIdentifier) {
-      var element = operand.staticElement;
-      // ElementResolver does not set it.
-      if (element is VariableElement) {
-        _resolver.setReadElement(operand, element);
-        _resolver.setWriteElement(operand, element);
-      }
-    }
-
-    if (node.readElement == null || node.readType == null) {
-      _resolver.setReadElement(operand, null);
-    }
-    if (node.writeElement == null || node.writeType == null) {
-      _resolver.setWriteElement(operand, null);
-    }
-
     if (operator.isIncrementOperator) {
+      var operandResolution = _resolver.resolveForWrite(
+        node: node.operand,
+        hasRead: true,
+      );
+
+      var readElement = operandResolution.readElement;
+      var writeElement = operandResolution.writeElement;
+
+      var operand = node.operand;
+      _resolver.setReadElement(operand, readElement);
+      _resolver.setWriteElement(operand, writeElement);
+      _resolver.migrationResolutionHooks
+          ?.setCompoundAssignmentExpressionTypes(node);
+
+      _resolver.setAssignmentBackwardCompatibility(
+        assignment: node,
+        left: operand,
+        hasRead: true,
+      );
+
       _assignmentShared.checkFinalAlreadyAssigned(node.operand);
+    } else {
+      node.operand.accept(_resolver);
     }
 
     _resolve1(node);
@@ -137,17 +138,6 @@
     }
   }
 
-  /// Return the non-nullable variant of the [type] if NNBD is enabled, otherwise
-  /// return the type itself.
-  ///
-  /// TODO(scheglov) this is duplicate
-  DartType _nonNullable(DartType type) {
-    if (_isNonNullableByDefault) {
-      return _typeSystem.promoteToNonNull(type);
-    }
-    return type;
-  }
-
   /// Record that the static type of the given node is the given type.
   ///
   /// @param expression the node whose type is to be recorded
@@ -192,10 +182,10 @@
         receiverType: readType,
         name: methodName,
         receiverErrorNode: operand,
-        nameErrorNode: operand,
+        nameErrorEntity: operand,
       );
       node.staticElement = result.getter;
-      if (_shouldReportInvalidMember(readType, result)) {
+      if (result.needsGetterError) {
         if (operand is SuperExpression) {
           _errorReporter.reportErrorForToken(
             CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR,
@@ -226,7 +216,7 @@
         // No special handling for incremental operators.
       } else if (operator.isIncrementOperator) {
         if (node.readType.isDartCoreInt) {
-          staticType = _nonNullable(_typeProvider.intType);
+          staticType = _typeProvider.intType;
         } else {
           _checkForInvalidAssignmentIncDec(node, staticType);
         }
@@ -251,23 +241,8 @@
 
     _resolver.boolExpressionVerifier.checkForNonBoolNegationExpression(operand);
 
-    _recordStaticType(node, _nonNullable(_typeProvider.boolType));
+    _recordStaticType(node, _typeProvider.boolType);
 
     _flowAnalysis?.flow?.logicalNot_end(node, operand);
   }
-
-  /// Return `true` if we should report an error for the lookup [result] on
-  /// the [type].
-  ///
-  /// TODO(scheglov) this is duplicate
-  bool _shouldReportInvalidMember(DartType type, ResolutionResult result) {
-    if (result.isNone && type != null && !type.isDynamic) {
-      if (_typeSystem.isNonNullableByDefault &&
-          _typeSystem.isPotentiallyNullable(type)) {
-        return false;
-      }
-      return true;
-    }
-    return false;
-  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
new file mode 100644
index 0000000..54a67e4
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/prefixed_identifier_resolver.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+class PrefixedIdentifierResolver {
+  final ResolverVisitor _resolver;
+
+  PrefixedIdentifierResolver(this._resolver);
+
+  InvocationInferenceHelper get _inferenceHelper => _resolver.inferenceHelper;
+
+  TypeProviderImpl get _typeProvider => _resolver.typeProvider;
+
+  void resolve(PrefixedIdentifier node) {
+    node.prefix.accept(_resolver);
+
+    var resolver = PropertyElementResolver(_resolver);
+    var result = resolver.resolvePrefixedIdentifier(
+      node: node,
+      hasRead: true,
+      hasWrite: false,
+    );
+
+    var identifier = node.identifier;
+    identifier.staticElement = result.readElement;
+
+    _resolve2(node);
+  }
+
+  /// Return the type that should be recorded for a node that resolved to the given accessor.
+  ///
+  /// @param accessor the accessor that the node resolved to
+  /// @return the type that should be recorded for a node that resolved to the given accessor
+  ///
+  /// TODO(scheglov) this is duplicate
+  DartType _getTypeOfProperty(PropertyAccessorElement accessor) {
+    FunctionType functionType = accessor.type;
+    if (functionType == null) {
+      // TODO(brianwilkerson) Report this internal error. This happens when we
+      // are analyzing a reference to a property before we have analyzed the
+      // declaration of the property or when the property does not have a
+      // defined type.
+      return DynamicTypeImpl.instance;
+    }
+    if (accessor.isSetter) {
+      List<DartType> parameterTypes = functionType.normalParameterTypes;
+      if (parameterTypes != null && parameterTypes.isNotEmpty) {
+        return parameterTypes[0];
+      }
+      PropertyAccessorElement getter = accessor.variable.getter;
+      if (getter != null) {
+        functionType = getter.type;
+        if (functionType != null) {
+          return functionType.returnType;
+        }
+      }
+      return DynamicTypeImpl.instance;
+    }
+    return functionType.returnType;
+  }
+
+  /// Return `true` if the given [node] is not a type literal.
+  ///
+  /// TODO(scheglov) this is duplicate
+  bool _isExpressionIdentifier(Identifier node) {
+    var parent = node.parent;
+    if (node is SimpleIdentifier && node.inDeclarationContext()) {
+      return false;
+    }
+    if (parent is ConstructorDeclaration) {
+      if (parent.name == node || parent.returnType == node) {
+        return false;
+      }
+    }
+    if (parent is ConstructorName ||
+        parent is MethodInvocation ||
+        parent is PrefixedIdentifier && parent.prefix == node ||
+        parent is PropertyAccess ||
+        parent is TypeName) {
+      return false;
+    }
+    return true;
+  }
+
+  /// Record that the static type of the given node is the given type.
+  ///
+  /// @param expression the node whose type is to be recorded
+  /// @param type the static type of the node
+  ///
+  /// TODO(scheglov) this is duplicate
+  void _recordStaticType(Expression expression, DartType type) {
+    _inferenceHelper.recordStaticType(expression, type);
+  }
+
+  void _resolve2(PrefixedIdentifier node) {
+    SimpleIdentifier prefixedIdentifier = node.identifier;
+    Element staticElement = prefixedIdentifier.staticElement;
+
+    if (staticElement is ExtensionElement) {
+      _setExtensionIdentifierType(node);
+      return;
+    }
+
+    if (identical(node.prefix.staticType, NeverTypeImpl.instance)) {
+      _recordStaticType(prefixedIdentifier, NeverTypeImpl.instance);
+      _recordStaticType(node, NeverTypeImpl.instance);
+      return;
+    }
+
+    DartType staticType = DynamicTypeImpl.instance;
+    if (staticElement is ClassElement) {
+      if (_isExpressionIdentifier(node)) {
+        var type = _typeProvider.typeType;
+        node.staticType = type;
+        node.identifier.staticType = type;
+      }
+      return;
+    } else if (staticElement is DynamicElementImpl) {
+      var type = _typeProvider.typeType;
+      node.staticType = type;
+      node.identifier.staticType = type;
+      return;
+    } else if (staticElement is FunctionTypeAliasElement) {
+      if (node.parent is TypeName) {
+        // no type
+      } else {
+        var type = _typeProvider.typeType;
+        node.staticType = type;
+        node.identifier.staticType = type;
+      }
+      return;
+    } else if (staticElement is MethodElement) {
+      staticType = staticElement.type;
+    } else if (staticElement is PropertyAccessorElement) {
+      staticType = _getTypeOfProperty(staticElement);
+    } else if (staticElement is ExecutableElement) {
+      staticType = staticElement.type;
+    } else if (staticElement is VariableElement) {
+      staticType = staticElement.type;
+    }
+
+    staticType =
+        _inferenceHelper.inferTearOff(node, node.identifier, staticType);
+
+    _recordStaticType(prefixedIdentifier, staticType);
+    _recordStaticType(node, staticType);
+  }
+
+  /// TODO(scheglov) this is duplicate
+  void _setExtensionIdentifierType(Identifier node) {
+    if (node is SimpleIdentifier && node.inDeclarationContext()) {
+      return;
+    }
+
+    var parent = node.parent;
+
+    if (parent is PrefixedIdentifier && parent.identifier == node) {
+      node = parent;
+      parent = node.parent;
+    }
+
+    if (parent is CommentReference ||
+        parent is ExtensionOverride && parent.extensionName == node ||
+        parent is MethodInvocation && parent.target == node ||
+        parent is PrefixedIdentifier && parent.prefix == node ||
+        parent is PropertyAccess && parent.target == node) {
+      return;
+    }
+
+    _resolver.errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
+      node,
+      [node.name],
+    );
+
+    if (node is PrefixedIdentifier) {
+      node.identifier.staticType = DynamicTypeImpl.instance;
+      node.staticType = DynamicTypeImpl.instance;
+    } else if (node is SimpleIdentifier) {
+      node.staticType = DynamicTypeImpl.instance;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
new file mode 100644
index 0000000..48c20cd
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -0,0 +1,716 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
+import 'package:analyzer/src/dart/resolver/resolution_result.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/error/assignment_verifier.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/super_context.dart';
+import 'package:meta/meta.dart';
+
+class PropertyElementResolver {
+  final ResolverVisitor _resolver;
+
+  PropertyElementResolver(this._resolver);
+
+  LibraryElement get _definingLibrary => _resolver.definingLibrary;
+
+  ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+  ExtensionMemberResolver get _extensionResolver => _resolver.extensionResolver;
+
+  TypeSystemImpl get _typeSystem => _resolver.typeSystem;
+
+  PropertyElementResolverResult resolveIndexExpression({
+    @required IndexExpression node,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    var target = node.realTarget;
+    var targetType = target.staticType;
+    targetType = _resolveTypeParameter(targetType);
+
+    if (target is ExtensionOverride) {
+      var result = _extensionResolver.getOverrideMember(target, '[]');
+
+      // TODO(scheglov) Change ExtensionResolver to set `needsGetterError`.
+      if (hasRead && result.getter == null && !result.isAmbiguous) {
+        _reportUnresolvedIndex(
+          node,
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
+          ['[]', target.staticElement.name],
+        );
+      }
+
+      if (hasWrite && result.setter == null && !result.isAmbiguous) {
+        _reportUnresolvedIndex(
+          node,
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
+          ['[]=', target.staticElement.name],
+        );
+      }
+
+      return _toIndexResult(result);
+    }
+
+    if (targetType.isVoid) {
+      // TODO(scheglov) Report directly in TypePropertyResolver?
+      _reportUnresolvedIndex(
+        node,
+        CompileTimeErrorCode.USE_OF_VOID_RESULT,
+      );
+      return PropertyElementResolverResult();
+    }
+
+    if (identical(targetType, NeverTypeImpl.instance)) {
+      // TODO(scheglov) Report directly in TypePropertyResolver?
+      _errorReporter.reportErrorForNode(
+        HintCode.RECEIVER_OF_TYPE_NEVER,
+        target,
+      );
+      return PropertyElementResolverResult();
+    }
+
+    if (node.isNullAware) {
+      if (target is ExtensionOverride) {
+        // https://github.com/dart-lang/language/pull/953
+      } else {
+        targetType = _typeSystem.promoteToNonNull(targetType);
+      }
+    }
+
+    var result = _resolver.typePropertyResolver.resolve(
+      receiver: target,
+      receiverType: targetType,
+      name: '[]',
+      receiverErrorNode: target,
+      nameErrorEntity: target,
+    );
+
+    if (hasRead && result.needsGetterError) {
+      _reportUnresolvedIndex(
+        node,
+        target is SuperExpression
+            ? CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR
+            : CompileTimeErrorCode.UNDEFINED_OPERATOR,
+        ['[]', targetType],
+      );
+    }
+
+    if (hasWrite && result.needsSetterError) {
+      _reportUnresolvedIndex(
+        node,
+        target is SuperExpression
+            ? CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR
+            : CompileTimeErrorCode.UNDEFINED_OPERATOR,
+        ['[]=', targetType],
+      );
+    }
+
+    return _toIndexResult(result);
+  }
+
+  PropertyElementResolverResult resolvePrefixedIdentifier({
+    @required PrefixedIdentifier node,
+    @required bool hasRead,
+    @required bool hasWrite,
+    bool forAnnotation = false,
+  }) {
+    var prefix = node.prefix;
+    var identifier = node.identifier;
+
+    var prefixElement = prefix.staticElement;
+    if (prefixElement is PrefixElement) {
+      return _resolveTargetPrefixElement(
+        target: prefixElement,
+        identifier: identifier,
+        hasRead: hasRead,
+        hasWrite: hasWrite,
+        forAnnotation: forAnnotation,
+      );
+    }
+
+    return _resolve(
+      target: prefix,
+      isCascaded: false,
+      isNullAware: false,
+      propertyName: identifier,
+      hasRead: hasRead,
+      hasWrite: hasWrite,
+    );
+  }
+
+  PropertyElementResolverResult resolvePropertyAccess({
+    @required PropertyAccess node,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    var target = node.realTarget;
+    var propertyName = node.propertyName;
+
+    if (target is ExtensionOverride) {
+      return _resolveTargetExtensionOverride(
+        target: target,
+        propertyName: propertyName,
+        hasRead: hasRead,
+        hasWrite: hasWrite,
+      );
+    }
+
+    if (target is SuperExpression) {
+      return _resolveTargetSuperExpression(
+        target: target,
+        propertyName: propertyName,
+        hasRead: hasRead,
+        hasWrite: hasWrite,
+      );
+    }
+
+    return _resolve(
+      target: target,
+      isCascaded: node.target == null,
+      isNullAware: node.isNullAware,
+      propertyName: propertyName,
+      hasRead: hasRead,
+      hasWrite: hasWrite,
+    );
+  }
+
+  PropertyElementResolverResult resolveSimpleIdentifier({
+    @required SimpleIdentifier node,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    Element readElementRequested;
+    Element readElementRecovery;
+    if (hasRead) {
+      var readLookup = _resolver.lexicalLookup(node: node, setter: false);
+      readElementRequested = readLookup.requested;
+      _resolver.checkReadOfNotAssignedLocalVariable(node, readElementRequested);
+    }
+
+    Element writeElementRequested;
+    Element writeElementRecovery;
+    if (hasWrite) {
+      var writeLookup = _resolver.lexicalLookup(node: node, setter: true);
+      writeElementRequested = writeLookup.requested;
+      writeElementRecovery = writeLookup.recovery;
+
+      AssignmentVerifier(_resolver.definingLibrary, _errorReporter).verify(
+        node: node,
+        requested: writeElementRequested,
+        recovery: writeElementRecovery,
+        receiverTypeObject: null,
+      );
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElementRequested,
+      readElementRecovery: readElementRecovery,
+      writeElementRequested: writeElementRequested,
+      writeElementRecovery: writeElementRecovery,
+    );
+  }
+
+  void _checkExtensionOverrideStaticMember(
+    SimpleIdentifier propertyName,
+    ExecutableElement element,
+  ) {
+    if (element != null && element.isStatic) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+        propertyName,
+      );
+    }
+  }
+
+  /// If the [element] is not static, report the error on the [identifier].
+  void _checkForStaticAccessToInstanceMember(
+    SimpleIdentifier identifier,
+    ExecutableElement element,
+  ) {
+    if (element.isStatic) return;
+
+    _errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
+      identifier,
+      [identifier.name],
+    );
+  }
+
+  DartType _computeIndexContextType({
+    @required ExecutableElement readElement,
+    @required ExecutableElement writeElement,
+  }) {
+    var method = writeElement ?? readElement;
+    var parameters = method is MethodElement ? method.parameters : null;
+
+    if (parameters != null && parameters.isNotEmpty) {
+      return parameters[0].type;
+    }
+
+    return null;
+  }
+
+  bool _isAccessible(ExecutableElement element) {
+    return element.isAccessibleIn(_definingLibrary);
+  }
+
+  void _reportUnresolvedIndex(
+    IndexExpression node,
+    ErrorCode errorCode, [
+    List<Object> arguments = const [],
+  ]) {
+    var leftBracket = node.leftBracket;
+    var rightBracket = node.rightBracket;
+    var offset = leftBracket.offset;
+    var length = rightBracket.end - offset;
+
+    _errorReporter.reportErrorForOffset(errorCode, offset, length, arguments);
+  }
+
+  PropertyElementResolverResult _resolve({
+    @required Expression target,
+    @required bool isCascaded,
+    @required bool isNullAware,
+    @required SimpleIdentifier propertyName,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    //
+    // If this property access is of the form 'C.m' where 'C' is a class,
+    // then we don't call resolveProperty(...) which walks up the class
+    // hierarchy, instead we just look for the member in the type only.  This
+    // does not apply to conditional property accesses (i.e. 'C?.m').
+    //
+    if (target is Identifier) {
+      var targetElement = target.staticElement;
+      if (targetElement is ClassElement) {
+        if (isCascaded) {
+          targetElement = _resolver.typeProvider.typeType.element;
+        }
+        return _resolveTargetClassElement(
+          typeReference: targetElement,
+          propertyName: propertyName,
+          hasRead: hasRead,
+          hasWrite: hasWrite,
+        );
+      }
+    }
+
+    //
+    // If this property access is of the form 'E.m' where 'E' is an extension,
+    // then look for the member in the extension. This does not apply to
+    // conditional property accesses (i.e. 'C?.m').
+    //
+    if (target is Identifier) {
+      var targetElement = target.staticElement;
+      if (targetElement is ExtensionElement) {
+        return _resolveTargetExtensionElement(
+          extension: targetElement,
+          propertyName: propertyName,
+          hasRead: hasRead,
+          hasWrite: hasWrite,
+        );
+      }
+    }
+
+    var targetType = target.staticType;
+
+    if (targetType.isVoid) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.USE_OF_VOID_RESULT,
+        propertyName,
+      );
+      return PropertyElementResolverResult();
+    }
+
+    if (isNullAware) {
+      targetType = _typeSystem.promoteToNonNull(targetType);
+    }
+
+    var result = _resolver.typePropertyResolver.resolve(
+      receiver: target,
+      receiverType: targetType,
+      name: propertyName.name,
+      receiverErrorNode: target,
+      nameErrorEntity: propertyName,
+    );
+
+    if (hasRead && result.needsGetterError) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNDEFINED_GETTER,
+        propertyName,
+        [propertyName.name, targetType],
+      );
+    }
+
+    if (hasWrite && result.needsSetterError) {
+      AssignmentVerifier(_definingLibrary, _errorReporter).verify(
+        node: propertyName,
+        requested: null,
+        recovery: result.getter,
+        receiverTypeObject: targetType,
+      );
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: result.getter,
+      readElementRecovery: result.setter,
+      writeElementRequested: result.setter,
+      writeElementRecovery: result.getter,
+    );
+  }
+
+  PropertyElementResolverResult _resolveTargetClassElement({
+    @required ClassElement typeReference,
+    @required SimpleIdentifier propertyName,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    ExecutableElement readElement;
+    if (hasRead) {
+      readElement = typeReference.getGetter(propertyName.name);
+      if (readElement != null && !_isAccessible(readElement)) {
+        readElement = null;
+      }
+
+      if (readElement == null) {
+        readElement = typeReference.getMethod(propertyName.name);
+        if (readElement != null && !_isAccessible(readElement)) {
+          readElement = null;
+        }
+      }
+
+      if (readElement != null) {
+        readElement = _resolver.toLegacyElement(readElement);
+        _checkForStaticAccessToInstanceMember(propertyName, readElement);
+      } else {
+        var code = typeReference.isEnum
+            ? CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT
+            : CompileTimeErrorCode.UNDEFINED_GETTER;
+        _errorReporter.reportErrorForNode(
+          code,
+          propertyName,
+          [propertyName.name, typeReference.name],
+        );
+      }
+    }
+
+    ExecutableElement writeElement;
+    ExecutableElement writeElementRecovery;
+    if (hasWrite) {
+      writeElement = typeReference.getSetter(propertyName.name);
+      if (writeElement != null) {
+        writeElement = _resolver.toLegacyElement(writeElement);
+        if (!_isAccessible(writeElement)) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.PRIVATE_SETTER,
+            propertyName,
+            [propertyName.name, typeReference.name],
+          );
+        }
+        _checkForStaticAccessToInstanceMember(propertyName, writeElement);
+      } else {
+        // Recovery, try to use getter.
+        writeElementRecovery = typeReference.getGetter(propertyName.name);
+        AssignmentVerifier(_definingLibrary, _errorReporter).verify(
+          node: propertyName,
+          requested: null,
+          recovery: writeElementRecovery,
+          receiverTypeObject: typeReference.displayName,
+        );
+      }
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      writeElementRequested: writeElement,
+      writeElementRecovery: writeElementRecovery,
+    );
+  }
+
+  PropertyElementResolverResult _resolveTargetExtensionElement({
+    @required ExtensionElement extension,
+    @required SimpleIdentifier propertyName,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    var memberName = propertyName.name;
+
+    ExecutableElement readElement;
+    if (hasRead) {
+      readElement ??= extension.getGetter(memberName);
+      readElement ??= extension.getMethod(memberName);
+
+      if (readElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
+          propertyName,
+          [memberName, extension.name],
+        );
+      } else {
+        readElement = _resolver.toLegacyElement(readElement);
+        _checkForStaticAccessToInstanceMember(propertyName, readElement);
+      }
+    }
+
+    ExecutableElement writeElement;
+    if (hasWrite) {
+      writeElement = extension.getSetter(memberName);
+
+      if (writeElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
+          propertyName,
+          [memberName, extension.name],
+        );
+      } else {
+        writeElement = _resolver.toLegacyElement(writeElement);
+        _checkForStaticAccessToInstanceMember(propertyName, writeElement);
+      }
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      writeElementRequested: writeElement,
+    );
+  }
+
+  PropertyElementResolverResult _resolveTargetExtensionOverride({
+    @required ExtensionOverride target,
+    @required SimpleIdentifier propertyName,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    if (target.parent is CascadeExpression) {
+      // Report this error and recover by treating it like a non-cascade.
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+        target.extensionName,
+      );
+    }
+
+    ExtensionElement element = target.extensionName.staticElement;
+    String memberName = propertyName.name;
+
+    var result = _extensionResolver.getOverrideMember(target, memberName);
+
+    ExecutableElement readElement;
+    if (hasRead) {
+      readElement = result.getter;
+      if (readElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
+          propertyName,
+          [memberName, element.name],
+        );
+      }
+      _checkExtensionOverrideStaticMember(propertyName, readElement);
+    }
+
+    ExecutableElement writeElement;
+    if (hasWrite) {
+      writeElement = result.setter;
+      if (writeElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
+          propertyName,
+          [memberName, element.name],
+        );
+      }
+      _checkExtensionOverrideStaticMember(propertyName, writeElement);
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      writeElementRequested: writeElement,
+    );
+  }
+
+  PropertyElementResolverResult _resolveTargetPrefixElement({
+    @required PrefixElement target,
+    @required SimpleIdentifier identifier,
+    @required bool hasRead,
+    @required bool hasWrite,
+    @required bool forAnnotation,
+  }) {
+    var lookupResult = target.scope.lookup2(identifier.name);
+
+    var readElement = _resolver.toLegacyElement(lookupResult.getter);
+    var writeElement = _resolver.toLegacyElement(lookupResult.setter);
+
+    if (hasRead && readElement == null || hasWrite && writeElement == null) {
+      if (!forAnnotation &&
+          !_resolver.nameScope.shouldIgnoreUndefined2(
+            prefix: target.name,
+            name: identifier.name,
+          )) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
+          identifier,
+          [identifier.name, target.name],
+        );
+      }
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      readElementRecovery: null,
+      writeElementRequested: writeElement,
+      writeElementRecovery: null,
+    );
+  }
+
+  PropertyElementResolverResult _resolveTargetSuperExpression({
+    @required SuperExpression target,
+    @required SimpleIdentifier propertyName,
+    @required bool hasRead,
+    @required bool hasWrite,
+  }) {
+    if (SuperContext.of(target) != SuperContext.valid) {
+      return PropertyElementResolverResult();
+    }
+    var targetType = target.staticType;
+
+    ExecutableElement readElement;
+    ExecutableElement writeElement;
+
+    if (targetType is InterfaceTypeImpl) {
+      if (hasRead) {
+        var name = Name(_definingLibrary.source.uri, propertyName.name);
+        readElement = _resolver.inheritance
+            .getMember2(targetType.element, name, forSuper: true);
+
+        if (readElement != null) {
+          readElement = _resolver.toLegacyElement(readElement);
+        } else {
+          // We were not able to find the concrete dispatch target.
+          // But we would like to give the user at least some resolution.
+          // So, we retry simply looking for an inherited member.
+          readElement =
+              _resolver.inheritance.getInherited2(targetType.element, name);
+          if (readElement != null) {
+            _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
+              propertyName,
+              [readElement.kind.displayName, propertyName.name],
+            );
+          } else {
+            _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.UNDEFINED_SUPER_GETTER,
+              propertyName,
+              [propertyName.name, targetType],
+            );
+          }
+        }
+      }
+
+      if (hasWrite) {
+        writeElement = targetType.lookUpSetter2(
+          propertyName.name,
+          _definingLibrary,
+          concrete: true,
+          inherited: true,
+        );
+
+        if (writeElement != null) {
+          writeElement = _resolver.toLegacyElement(writeElement);
+        } else {
+          // We were not able to find the concrete dispatch target.
+          // But we would like to give the user at least some resolution.
+          // So, we retry without the "concrete" requirement.
+          writeElement = targetType.lookUpSetter2(
+            propertyName.name,
+            _definingLibrary,
+            inherited: true,
+          );
+          if (writeElement != null) {
+            ClassElementImpl receiverSuperClass =
+                targetType.element.supertype.element;
+            if (!receiverSuperClass.hasNoSuchMethod) {
+              _errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
+                propertyName,
+                [writeElement.kind.displayName, propertyName.name],
+              );
+            }
+          } else {
+            _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.UNDEFINED_SUPER_SETTER,
+              propertyName,
+              [propertyName.name, targetType],
+            );
+          }
+        }
+      }
+    }
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      writeElementRequested: writeElement,
+    );
+  }
+
+  /// If the given [type] is a type parameter, replace with its bound.
+  /// Otherwise, return the original type.
+  DartType _resolveTypeParameter(DartType type) {
+    if (type is TypeParameterType) {
+      return type.resolveToBound(_resolver.typeProvider.objectType);
+    }
+    return type;
+  }
+
+  PropertyElementResolverResult _toIndexResult(ResolutionResult result) {
+    var readElement = result.getter;
+    var writeElement = result.setter;
+
+    return PropertyElementResolverResult(
+      readElementRequested: readElement,
+      writeElementRequested: writeElement,
+      indexContextType: _computeIndexContextType(
+        readElement: readElement,
+        writeElement: writeElement,
+      ),
+    );
+  }
+}
+
+class PropertyElementResolverResult {
+  final Element readElementRequested;
+  final Element readElementRecovery;
+  final Element writeElementRequested;
+  final Element writeElementRecovery;
+
+  /// If [IndexExpression] is resolved, the context type of the index.
+  /// Might be `null` if `[]` or `[]=` are not resolved or invalid.
+  final DartType indexContextType;
+
+  PropertyElementResolverResult({
+    this.readElementRequested,
+    this.readElementRecovery,
+    this.writeElementRequested,
+    this.writeElementRecovery,
+    this.indexContextType,
+  });
+
+  Element get readElement {
+    return readElementRequested ?? readElementRecovery;
+  }
+
+  Element get writeElement {
+    return writeElementRequested ?? writeElementRecovery;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
index f87810c..3a19d28 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_result.dart
@@ -20,38 +20,48 @@
   /// Return the element that is invoked for reading.
   final ExecutableElement getter;
 
+  /// If `true`, then the [getter] is `null`, and this is an error that has
+  /// not yet been reported, and the client should report it.
+  ///
+  /// If `false`, then the [getter] is valid. Usually this means that the
+  /// correct target has been found. But the [getter] still might be `null`,
+  /// when there was an error, and it has already been reported (e.g. when
+  /// ambiguous extension);  or when `null` is the only possible result (e.g.
+  /// when `dynamicTarget.foo`, or `functionTyped.call`).
+  final bool needsGetterError;
+
   /// Return the element that is invoked for writing.
   final ExecutableElement setter;
 
+  /// If `true`, then the [setter] is `null`, and this is an error that has
+  /// not yet been reported, and the client should report it.
+  ///
+  /// If `false`, then the [setter] is valid. Usually this means that the
+  /// correct target has been found. But the [setter] still might be `null`,
+  /// when there was an error, and it has already been reported (e.g. when
+  /// ambiguous extension);  or when `null` is the only possible result (e.g.
+  /// when `dynamicTarget.foo`).
+  final bool needsSetterError;
+
   /// Initialize a newly created result to represent resolving a single
   /// reading and / or writing result.
-  ResolutionResult({this.getter, this.setter})
-      : assert(getter != null || setter != null),
-        state = _ResolutionResultState.single;
+  ResolutionResult({
+    this.getter,
+    this.needsGetterError,
+    this.setter,
+    this.needsSetterError,
+  }) : state = _ResolutionResultState.single;
 
   /// Initialize a newly created result with no elements and the given [state].
   const ResolutionResult._(this.state)
       : getter = null,
-        setter = null;
+        needsGetterError = true,
+        setter = null,
+        needsSetterError = true;
 
   /// Return `true` if this result represents the case where multiple ambiguous
   /// elements were found.
   bool get isAmbiguous => state == _ResolutionResultState.ambiguous;
-
-  /// Return `true` if this result represents the case where no element was
-  /// found.
-  bool get isNone => state == _ResolutionResultState.none;
-
-  /// Return `true` if this result represents the case where a single element
-  /// was found.
-  bool get isSingle => state == _ResolutionResultState.single;
-
-  /// If this is a property, return `true` is the property is static.
-  /// If this is a function, return `true` is the function is static.
-  /// Otherwise return `false`.
-  bool get isStatic {
-    return getter?.isStatic ?? setter?.isStatic ?? false;
-  }
 }
 
 /// The state of a [ResolutionResult].
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 81255f6..858f235 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -462,11 +462,11 @@
         element.isFinal = node.isFinal;
         element.parameterKind = node.kind;
         _setCodeRange(element, node);
-        element.metadata = _createElementAnnotations(node.metadata);
       }
       nameNode.staticElement = element;
     }
 
+    element.metadata = _createElementAnnotations(node.metadata);
     node.metadata.accept(this);
     _setElementAnnotations(node.metadata, element.metadata);
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
new file mode 100644
index 0000000..c32b116
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -0,0 +1,336 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
+import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+class SimpleIdentifierResolver {
+  final ResolverVisitor _resolver;
+  final FlowAnalysisHelper _flowAnalysis;
+
+  SimpleIdentifierResolver(this._resolver, this._flowAnalysis);
+
+  ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+  InvocationInferenceHelper get _inferenceHelper => _resolver.inferenceHelper;
+
+  TypeProviderImpl get _typeProvider => _resolver.typeProvider;
+
+  void resolve(SimpleIdentifier node) {
+    if (node.inDeclarationContext()) {
+      return;
+    }
+
+    _resolver.checkUnreachableNode(node);
+
+    _resolver.checkReadOfNotAssignedLocalVariable(node, node.staticElement);
+
+    _resolve1(node);
+    _resolve2(node);
+  }
+
+  /// Return the type that should be recorded for a node that resolved to the given accessor.
+  ///
+  /// @param accessor the accessor that the node resolved to
+  /// @return the type that should be recorded for a node that resolved to the given accessor
+  ///
+  /// TODO(scheglov) this is duplicate
+  DartType _getTypeOfProperty(PropertyAccessorElement accessor) {
+    FunctionType functionType = accessor.type;
+    if (functionType == null) {
+      // TODO(brianwilkerson) Report this internal error. This happens when we
+      // are analyzing a reference to a property before we have analyzed the
+      // declaration of the property or when the property does not have a
+      // defined type.
+      return DynamicTypeImpl.instance;
+    }
+    if (accessor.isSetter) {
+      List<DartType> parameterTypes = functionType.normalParameterTypes;
+      if (parameterTypes != null && parameterTypes.isNotEmpty) {
+        return parameterTypes[0];
+      }
+      PropertyAccessorElement getter = accessor.variable.getter;
+      if (getter != null) {
+        functionType = getter.type;
+        if (functionType != null) {
+          return functionType.returnType;
+        }
+      }
+      return DynamicTypeImpl.instance;
+    }
+    return functionType.returnType;
+  }
+
+  /// Return `true` if the given [node] is not a type literal.
+  ///
+  /// TODO(scheglov) this is duplicate
+  bool _isExpressionIdentifier(Identifier node) {
+    var parent = node.parent;
+    if (node is SimpleIdentifier && node.inDeclarationContext()) {
+      return false;
+    }
+    if (parent is ConstructorDeclaration) {
+      if (parent.name == node || parent.returnType == node) {
+        return false;
+      }
+    }
+    if (parent is ConstructorName ||
+        parent is MethodInvocation ||
+        parent is PrefixedIdentifier && parent.prefix == node ||
+        parent is PropertyAccess ||
+        parent is TypeName) {
+      return false;
+    }
+    return true;
+  }
+
+  /// Return `true` if the given [node] can validly be resolved to a prefix:
+  /// * it is the prefix in an import directive, or
+  /// * it is the prefix in a prefixed identifier.
+  bool _isValidAsPrefix(SimpleIdentifier node) {
+    AstNode parent = node.parent;
+    if (parent is ImportDirective) {
+      return identical(parent.prefix, node);
+    } else if (parent is PrefixedIdentifier) {
+      return true;
+    } else if (parent is MethodInvocation) {
+      return identical(parent.target, node) &&
+          parent.operator?.type == TokenType.PERIOD;
+    }
+    return false;
+  }
+
+  /// Record that the static type of the given node is the given type.
+  ///
+  /// @param expression the node whose type is to be recorded
+  /// @param type the static type of the node
+  ///
+  /// TODO(scheglov) this is duplicate
+  void _recordStaticType(Expression expression, DartType type) {
+    if (_resolver.migrationResolutionHooks != null) {
+      // TODO(scheglov) type cannot be null
+      type = _resolver.migrationResolutionHooks.modifyExpressionType(
+        expression,
+        type ?? DynamicTypeImpl.instance,
+      );
+    }
+
+    // TODO(scheglov) type cannot be null
+    if (type == null) {
+      expression.staticType = DynamicTypeImpl.instance;
+    } else {
+      expression.staticType = type;
+      if (_resolver.typeSystem.isBottom(type)) {
+        _flowAnalysis?.flow?.handleExit();
+      }
+    }
+  }
+
+  void _resolve1(SimpleIdentifier node) {
+    //
+    // Synthetic identifiers have been already reported during parsing.
+    //
+    if (node.isSynthetic) {
+      return;
+    }
+
+    //
+    // Ignore nodes that should have been resolved before getting here.
+    //
+    if (node.inDeclarationContext()) {
+      return;
+    }
+    if (node.staticElement is LocalVariableElement ||
+        node.staticElement is ParameterElement) {
+      return;
+    }
+    AstNode parent = node.parent;
+    if (parent is FieldFormalParameter) {
+      return;
+    } else if (parent is ConstructorFieldInitializer &&
+        parent.fieldName == node) {
+      return;
+    } else if (parent is Annotation && parent.constructorName == node) {
+      return;
+    }
+
+    //
+    // Otherwise, the node should be resolved.
+    //
+
+    // TODO(scheglov) Special-case resolution of ForStatement, don't use this.
+    var hasRead = true;
+    var hasWrite = false;
+    {
+      var parent = node.parent;
+      if (parent is ForEachPartsWithIdentifier && parent.identifier == node) {
+        hasRead = false;
+        hasWrite = true;
+      }
+    }
+
+    var resolver = PropertyElementResolver(_resolver);
+    var result = resolver.resolveSimpleIdentifier(
+      node: node,
+      hasRead: hasRead,
+      hasWrite: hasWrite,
+    );
+
+    // Element element = _resolver.elementResolver.resolveSimpleIdentifier(node);
+    Element element = hasRead ? result.readElement : result.writeElement;
+
+    ClassElement enclosingClass = _resolver.enclosingClass;
+    if (_isFactoryConstructorReturnType(node) &&
+        !identical(element, enclosingClass)) {
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node);
+    } else if (_isConstructorReturnType(node) &&
+        !identical(element, enclosingClass)) {
+      // This error is now reported by the parser.
+      element = null;
+    } else if (element == null ||
+        (element is PrefixElement && !_isValidAsPrefix(node))) {
+      // TODO(brianwilkerson) Recover from this error.
+      if (_isConstructorReturnType(node)) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
+      } else if (parent is Annotation) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
+      } else if (element != null) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+            node,
+            [element.name]);
+      } else if (node.name == "await" && _resolver.enclosingFunction != null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
+          node,
+        );
+      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+          node,
+          [node.name],
+        );
+      }
+    }
+    node.staticElement = element;
+  }
+
+  void _resolve2(SimpleIdentifier node) {
+    Element element = node.staticElement;
+
+    if (element is ExtensionElement) {
+      _setExtensionIdentifierType(node);
+      return;
+    }
+
+    DartType staticType = DynamicTypeImpl.instance;
+    if (element is ClassElement) {
+      if (_isExpressionIdentifier(node)) {
+        node.staticType = _typeProvider.typeType;
+      }
+      return;
+    } else if (element is FunctionTypeAliasElement) {
+      if (node.inDeclarationContext() || node.parent is TypeName) {
+        // no type
+      } else {
+        node.staticType = _typeProvider.typeType;
+      }
+      return;
+    } else if (element is MethodElement) {
+      staticType = element.type;
+    } else if (element is PropertyAccessorElement) {
+      staticType = _getTypeOfProperty(element);
+    } else if (element is ExecutableElement) {
+      staticType = element.type;
+    } else if (element is TypeParameterElement) {
+      staticType = _typeProvider.typeType;
+    } else if (element is VariableElement) {
+      staticType = _resolver.localVariableTypeProvider.getType(node);
+    } else if (element is PrefixElement) {
+      var parent = node.parent;
+      if (parent is PrefixedIdentifier && parent.prefix == node ||
+          parent is MethodInvocation && parent.target == node) {
+        return;
+      }
+      staticType = _typeProvider.dynamicType;
+    } else if (element is DynamicElementImpl) {
+      staticType = _typeProvider.typeType;
+    } else {
+      staticType = DynamicTypeImpl.instance;
+    }
+    staticType = _inferenceHelper.inferTearOff(node, node, staticType);
+    _recordStaticType(node, staticType);
+  }
+
+  /// TODO(scheglov) this is duplicate
+  void _setExtensionIdentifierType(Identifier node) {
+    if (node is SimpleIdentifier && node.inDeclarationContext()) {
+      return;
+    }
+
+    var parent = node.parent;
+
+    if (parent is PrefixedIdentifier && parent.identifier == node) {
+      node = parent;
+      parent = node.parent;
+    }
+
+    if (parent is CommentReference ||
+        parent is ExtensionOverride && parent.extensionName == node ||
+        parent is MethodInvocation && parent.target == node ||
+        parent is PrefixedIdentifier && parent.prefix == node ||
+        parent is PropertyAccess && parent.target == node) {
+      return;
+    }
+
+    _resolver.errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
+      node,
+      [node.name],
+    );
+
+    if (node is PrefixedIdentifier) {
+      node.identifier.staticType = DynamicTypeImpl.instance;
+      node.staticType = DynamicTypeImpl.instance;
+    } else if (node is SimpleIdentifier) {
+      node.staticType = DynamicTypeImpl.instance;
+    }
+  }
+
+  /// Return `true` if the given [identifier] is the return type of a
+  /// constructor declaration.
+  static bool _isConstructorReturnType(SimpleIdentifier identifier) {
+    AstNode parent = identifier.parent;
+    if (parent is ConstructorDeclaration) {
+      return identical(parent.returnType, identifier);
+    }
+    return false;
+  }
+
+  /// Return `true` if the given [identifier] is the return type of a factory
+  /// constructor.
+  static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) {
+    AstNode parent = identifier.parent;
+    if (parent is ConstructorDeclaration) {
+      return identical(parent.returnType, identifier) &&
+          parent.factoryKeyword != null;
+    }
+    return false;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index dbbcb96..dcf0d9d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -24,10 +25,18 @@
   final ExtensionMemberResolver _extensionResolver;
 
   Expression _receiver;
+  SyntacticEntity _nameErrorEntity;
   String _name;
-  AstNode _nameErrorNode;
 
-  ResolutionResult _result = ResolutionResult.none;
+  bool _needsGetterError;
+  bool _reportedGetterError;
+  ExecutableElement _getterRequested;
+  ExecutableElement _getterRecovery;
+
+  bool _needsSetterError;
+  bool _reportedSetterError;
+  ExecutableElement _setterRequested;
+  ExecutableElement _setterRecovery;
 
   TypePropertyResolver(this._resolver)
       : _definingLibrary = _resolver.definingLibrary,
@@ -36,6 +45,10 @@
         _typeProvider = _resolver.typeProvider,
         _extensionResolver = _resolver.extensionResolver;
 
+  bool get _hasGetterOrSetter {
+    return _getterRequested != null || _setterRequested != null;
+  }
+
   /// Look up the property with the given [name] in the [receiverType].
   ///
   /// The [receiver] might be `null`, used to identify `super`.
@@ -43,119 +56,186 @@
   /// The [receiverErrorNode] is the node to report nullable dereference,
   /// if the [receiverType] is potentially nullable.
   ///
-  /// The [nameErrorNode] is used to report the ambiguous extension issue.
+  /// The [nameErrorEntity] is used to report the ambiguous extension issue.
   ResolutionResult resolve({
     @required Expression receiver,
     @required DartType receiverType,
     @required String name,
     @required AstNode receiverErrorNode,
-    @required Expression nameErrorNode,
+    @required SyntacticEntity nameErrorEntity,
   }) {
     assert(receiverType != null);
     _receiver = receiver;
     _name = name;
-    _nameErrorNode = nameErrorNode;
-    _result = ResolutionResult.none;
+    _nameErrorEntity = nameErrorEntity;
+    _resetResult();
 
-    receiverType = _resolveTypeParameter(receiverType);
+    receiverType = _resolveTypeParameter(receiverType, ifLegacy: true);
+
+    if (_typeSystem.isDynamicBounded(receiverType)) {
+      _lookupInterfaceType(_typeProvider.objectType);
+      _needsGetterError = false;
+      _needsSetterError = false;
+      return _toResult();
+    }
 
     if (_isNonNullableByDefault &&
         _typeSystem.isPotentiallyNullable(receiverType)) {
+      _lookupInterfaceType(_typeProvider.objectType);
+      if (_hasGetterOrSetter) {
+        return _toResult();
+      }
+
       _lookupExtension(receiverType);
-
-      if (_result.isNone) {
-        _lookupInterfaceType(_typeProvider.objectType);
+      if (_hasGetterOrSetter) {
+        return _toResult();
       }
 
-      if (_result.isNone && !receiverType.isDynamic) {
-        _resolver.nullableDereferenceVerifier.report(
-          receiverErrorNode,
-          receiverType,
-        );
-        // Recovery, get some resolution.
-        _lookupType(receiverType);
+      _resolver.nullableDereferenceVerifier.report(
+        receiverErrorNode,
+        receiverType,
+      );
+      _reportedGetterError = true;
+      _reportedSetterError = true;
+
+      // Recovery, get some resolution.
+      receiverType = _resolveTypeParameter(receiverType, ifNullSafe: true);
+      if (receiverType is InterfaceType) {
+        _lookupInterfaceType(receiverType);
       }
 
-      _toLegacy();
-      return _result;
+      return _toResult();
     } else {
-      _lookupType(receiverType);
+      var receiverTypeResolved =
+          _resolveTypeParameter(receiverType, ifNullSafe: true);
 
-      if (_result.isNone) {
-        _lookupExtension(receiverType);
+      if (receiverTypeResolved is InterfaceType) {
+        _lookupInterfaceType(receiverTypeResolved);
+        if (_hasGetterOrSetter) {
+          return _toResult();
+        }
+        if (receiverTypeResolved.isDartCoreFunction && _name == 'call') {
+          _needsGetterError = false;
+          _needsSetterError = false;
+          return _toResult();
+        }
       }
 
-      if (_result.isNone) {
+      if (receiverTypeResolved is FunctionType && _name == 'call') {
+        return _toResult();
+      }
+
+      if (receiverTypeResolved is NeverType) {
         _lookupInterfaceType(_typeProvider.objectType);
+        _needsGetterError = false;
+        _needsSetterError = false;
+        return _toResult();
       }
 
-      _toLegacy();
-      return _result;
+      _lookupExtension(receiverType);
+      if (_hasGetterOrSetter) {
+        return _toResult();
+      }
+
+      _lookupInterfaceType(_typeProvider.objectType);
+
+      return _toResult();
     }
   }
 
   void _lookupExtension(DartType type) {
-    _result = _extensionResolver.findExtension(type, _name, _nameErrorNode);
+    var result =
+        _extensionResolver.findExtension(type, _nameErrorEntity, _name);
+    _reportedGetterError = result.isAmbiguous;
+    _reportedSetterError = result.isAmbiguous;
+
+    if (result.getter != null) {
+      _needsGetterError = false;
+      _getterRequested = result.getter;
+    }
+
+    if (result.setter != null) {
+      _needsSetterError = false;
+      _setterRequested = result.setter;
+    }
   }
 
   void _lookupInterfaceType(InterfaceType type) {
     var isSuper = _receiver is SuperExpression;
 
-    ExecutableElement typeGetter;
-    ExecutableElement typeSetter;
+    var getterName = Name(_definingLibrary.source.uri, _name);
+    _getterRequested =
+        _resolver.inheritance.getMember(type, getterName, forSuper: isSuper);
+    _needsGetterError = _getterRequested == null;
 
-    if (_name == '[]') {
-      typeGetter = type.lookUpMethod2(
-        '[]',
-        _definingLibrary,
-        concrete: isSuper,
-        inherited: isSuper,
-      );
-
-      typeSetter = type.lookUpMethod2(
-        '[]=',
-        _definingLibrary,
-        concrete: isSuper,
-        inherited: isSuper,
-      );
-    } else {
+    if (_getterRequested == null) {
       var classElement = type.element as AbstractClassElementImpl;
-      var getterName = Name(_definingLibrary.source.uri, _name);
-      var setterName = Name(_definingLibrary.source.uri, '$_name=');
-      typeGetter = _resolver.inheritance
-              .getMember(type, getterName, forSuper: isSuper) ??
+      _getterRecovery ??=
           classElement.lookupStaticGetter(_name, _definingLibrary) ??
-          classElement.lookupStaticMethod(_name, _definingLibrary);
-      typeSetter = _resolver.inheritance
-              .getMember(type, setterName, forSuper: isSuper) ??
-          classElement.lookupStaticSetter(_name, _definingLibrary);
+              classElement.lookupStaticMethod(_name, _definingLibrary);
+      _needsGetterError = _getterRecovery == null;
     }
 
-    if (typeGetter != null || typeSetter != null) {
-      _result = ResolutionResult(getter: typeGetter, setter: typeSetter);
+    var setterName = Name(_definingLibrary.source.uri, '$_name=');
+    _setterRequested =
+        _resolver.inheritance.getMember(type, setterName, forSuper: isSuper);
+    _needsSetterError = _setterRequested == null;
+
+    if (_setterRequested == null) {
+      var classElement = type.element as AbstractClassElementImpl;
+      _setterRecovery ??=
+          classElement.lookupStaticSetter(_name, _definingLibrary);
+      _needsSetterError = _setterRecovery == null;
     }
   }
 
-  void _lookupType(DartType type) {
-    if (type is InterfaceType) {
-      _lookupInterfaceType(type);
-    } else if (type is FunctionType) {
-      _lookupInterfaceType(_typeProvider.functionType);
-    }
+  void _resetResult() {
+    _needsGetterError = false;
+    _reportedGetterError = false;
+    _getterRequested = null;
+    _getterRecovery = null;
+
+    _needsSetterError = false;
+    _reportedSetterError = false;
+    _setterRequested = null;
+    _setterRecovery = null;
   }
 
   /// If the given [type] is a type parameter, replace it with its bound.
   /// Otherwise, return the original type.
-  DartType _resolveTypeParameter(DartType type) {
-    return type?.resolveToBound(_typeProvider.objectType);
+  ///
+  /// See https://github.com/dart-lang/language/issues/1182
+  /// There was a bug in the analyzer (and CFE) - we were always resolving
+  /// types to bounds before searching for a property.  But  extensions should
+  /// be applied to original types.  Fixing this would be a breaking change,
+  /// so we fix it together with null safety.
+  DartType _resolveTypeParameter(
+    DartType type, {
+    bool ifLegacy = false,
+    bool ifNullSafe = false,
+  }) {
+    if (_typeSystem.isNonNullableByDefault ? ifNullSafe : ifLegacy) {
+      return type?.resolveToBound(_typeProvider.objectType);
+    } else {
+      return type;
+    }
   }
 
-  void _toLegacy() {
-    if (_result.isSingle) {
-      _result = ResolutionResult(
-        getter: _resolver.toLegacyElement(_result.getter),
-        setter: _resolver.toLegacyElement(_result.setter),
-      );
-    }
+  ResolutionResult _toResult() {
+    _getterRequested = _resolver.toLegacyElement(_getterRequested);
+    _getterRecovery = _resolver.toLegacyElement(_getterRecovery);
+
+    _setterRequested = _resolver.toLegacyElement(_setterRequested);
+    _setterRecovery = _resolver.toLegacyElement(_setterRecovery);
+
+    var getter = _getterRequested ?? _getterRecovery;
+    var setter = _setterRequested ?? _setterRecovery;
+
+    return ResolutionResult(
+      getter: getter,
+      needsGetterError: _needsGetterError && !_reportedGetterError,
+      setter: setter,
+      needsSetterError: _needsSetterError && !_reportedSetterError,
+    );
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index fb59963..91c8cba 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/src/dart/constant/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -52,6 +51,8 @@
     InferenceContext.setTypeFromNode(initializer, node);
     if (isTopLevel) {
       _flowAnalysis?.topLevelDeclaration_enter(node, null, null);
+    } else if (element.isLate) {
+      _flowAnalysis?.flow?.lateInitializer_begin(node);
     }
 
     initializer.accept(_resolver);
@@ -63,6 +64,8 @@
 
     if (isTopLevel) {
       _flowAnalysis?.topLevelDeclaration_exit();
+    } else if (element.isLate) {
+      _flowAnalysis?.flow?.lateInitializer_end();
     }
 
     // Note: in addition to cloning the initializers for const variables, we
@@ -81,10 +84,7 @@
         initializerType = DynamicTypeImpl.instance;
       }
 
-      var inferredType = demoteType(
-        _resolver.definingLibrary,
-        initializerType,
-      );
+      var inferredType = _resolver.typeSystem.demoteType(initializerType);
       element.type = inferredType;
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
index 34962c9..b248774 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variance.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -204,4 +204,20 @@
             'Missing keyword lexeme representation for variance: $this');
     }
   }
+
+  @override
+  String toString() {
+    switch (this) {
+      case contravariant:
+        return 'contravariant';
+      case invariant:
+        return 'invariant';
+      case covariant:
+        return 'covariant';
+      case unrelated:
+        return 'unrelated';
+      default:
+        throw UnimplementedError('encoding: $_encoding');
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index a5db15b..5c3e5c9 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/exception/exception.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
@@ -35,37 +34,9 @@
   /// A mapping from Dart library URI's to the library represented by that URI.
   LibraryMap libraryMap = LibraryMap();
 
-  /// The [AnalysisOptions] to use to create the [context].
-  AnalysisOptions _analysisOptions;
-
-  /// The [AnalysisContext] which is used for all of the sources in this SDK.
-  SdkAnalysisContext _analysisContext;
-
   /// The mapping from Dart URI's to the corresponding sources.
   final Map<String, Source> _uriToSourceMap = HashMap<String, Source>();
 
-  /// Return the analysis options for this SDK analysis context.
-  AnalysisOptions get analysisOptions => _analysisOptions;
-
-  /// Set the [options] for this SDK analysis context.  Throw [StateError] if
-  /// the context has been already created.
-  set analysisOptions(AnalysisOptions options) {
-    if (_analysisContext != null) {
-      throw StateError(
-          'Analysis options cannot be changed after context creation.');
-    }
-    _analysisOptions = options;
-  }
-
-  @override
-  AnalysisContext get context {
-    if (_analysisContext == null) {
-      var factory = SourceFactory([DartUriResolver(this)]);
-      _analysisContext = SdkAnalysisContext(_analysisOptions, factory);
-    }
-    return _analysisContext;
-  }
-
   @override
   List<SdkLibrary> get sdkLibraries => libraryMap.sdkLibraries;
 
diff --git a/pkg/analyzer/lib/src/error/assignment_verifier.dart b/pkg/analyzer/lib/src/error/assignment_verifier.dart
new file mode 100644
index 0000000..54f0b21
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/assignment_verifier.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:meta/meta.dart';
+
+/// Helper for verifying resolution of assignments, in form of explicit
+/// an [AssignmentExpression], or a [PrefixExpression] or [PostfixExpression]
+/// when the operator is an increment operator.
+class AssignmentVerifier {
+  final LibraryElement _definingLibrary;
+  final ErrorReporter _errorReporter;
+
+  AssignmentVerifier(this._definingLibrary, this._errorReporter);
+
+  /// We resolved [node] and found that it references the [requested] element.
+  /// Verify that this element is actually writable.
+  ///
+  /// If the [requested] element is `null`, we might have the [recovery]
+  /// element, which is definitely not a valid write target. We want to report
+  /// a good error about this.
+  ///
+  /// The [receiverTypeObject] might be a [DartType] or [String], and when
+  /// it is not `null`, we report [CompileTimeErrorCode.UNDEFINED_SETTER]
+  /// instead of a more generic [CompileTimeErrorCode.UNDEFINED_IDENTIFIER].
+  void verify({
+    @required SimpleIdentifier node,
+    @required Element requested,
+    @required Element recovery,
+    @required Object receiverTypeObject,
+  }) {
+    if (requested != null) {
+      if (requested is VariableElement) {
+        if (requested.isConst) {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
+            node,
+          );
+        } else if (requested.isFinal) {
+          if (_definingLibrary.isNonNullableByDefault) {
+            // Handled during resolution, with flow analysis.
+          } else {
+            _errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
+              node,
+              [requested.name],
+            );
+          }
+        }
+      }
+      return;
+    }
+
+    if (recovery is ClassElement ||
+        recovery is DynamicElementImpl ||
+        recovery is FunctionTypeAliasElement ||
+        recovery is TypeParameterElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
+        node,
+      );
+    } else if (recovery is FunctionElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION,
+        node,
+      );
+    } else if (recovery is MethodElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
+        node,
+      );
+    } else if (recovery is PrefixElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+        node,
+        [recovery.name],
+      );
+    } else if (recovery is PropertyAccessorElement && recovery.isGetter) {
+      var variable = recovery.variable;
+      if (variable.isConst) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
+          node,
+        );
+      } else if (variable is FieldElement && variable.isSynthetic) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
+          node,
+          [variable.name, variable.enclosingElement.displayName],
+        );
+      } else {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.ASSIGNMENT_TO_FINAL,
+          node,
+          [variable.name],
+        );
+      }
+    } else if (recovery is MultiplyDefinedElementImpl) {
+      // Will be reported in ErrorVerifier.
+    } else if (node is SimpleIdentifier) {
+      if (node.isSynthetic) {
+        return;
+      }
+      if (receiverTypeObject != null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_SETTER,
+          node,
+          [node.name, receiverTypeObject],
+        );
+      } else {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+          node,
+          [node.name],
+        );
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 8cfc83d..7b3407fd 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -21,7 +21,9 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/error/must_call_super_verifier.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -47,6 +49,10 @@
   /// is deprecated.
   bool _inDeprecatedMember;
 
+  /// A flag indicating whether a surrounding member is annotated as
+  /// `@doNotStore`.
+  bool _inDoNotStoreMember;
+
   /// The error reporter by which errors will be reported.
   final ErrorReporter _errorReporter;
 
@@ -64,6 +70,8 @@
 
   final _InvalidAccessVerifier _invalidAccessVerifier;
 
+  final MustCallSuperVerifier _mustCallSuperVerifier;
+
   /// The [WorkspacePackage] in which [_currentLibrary] is declared.
   final WorkspacePackage _workspacePackage;
 
@@ -96,10 +104,12 @@
         _strictInference =
             (analysisOptions as AnalysisOptionsImpl).strictInference,
         _inheritanceManager = inheritanceManager,
-        _invalidAccessVerifier =
-            _InvalidAccessVerifier(_errorReporter, _currentLibrary),
+        _invalidAccessVerifier = _InvalidAccessVerifier(
+            _errorReporter, _currentLibrary, workspacePackage),
+        _mustCallSuperVerifier = MustCallSuperVerifier(_errorReporter),
         _workspacePackage = workspacePackage {
     _inDeprecatedMember = _currentLibrary.hasDeprecated;
+    _inDoNotStoreMember = _currentLibrary.hasDoNotStore;
 
     _linterContext = LinterContextImpl(
       null /* allUnits */,
@@ -113,6 +123,11 @@
     );
   }
 
+  bool get _inPublicPackageApi {
+    return _workspacePackage != null &&
+        _workspacePackage.sourceIsInPublicApi(_currentLibrary.source);
+  }
+
   @override
   void visitAnnotation(Annotation node) {
     ElementAnnotation element = node.elementAnnotation;
@@ -132,6 +147,35 @@
         _errorReporter.reportErrorForNode(
             HintCode.INVALID_IMMUTABLE_ANNOTATION, node, []);
       }
+    } else if (element.isInternal) {
+      var parentElement = parent is Declaration ? parent.declaredElement : null;
+      if (parent is TopLevelVariableDeclaration) {
+        for (VariableDeclaration variable in parent.variables.variables) {
+          if (Identifier.isPrivateName(variable.declaredElement.name)) {
+            _errorReporter.reportErrorForNode(
+                HintCode.INVALID_INTERNAL_ANNOTATION, variable, []);
+          }
+        }
+      } else if (parent is FieldDeclaration) {
+        for (VariableDeclaration variable in parent.fields.variables) {
+          if (Identifier.isPrivateName(variable.declaredElement.name)) {
+            _errorReporter.reportErrorForNode(
+                HintCode.INVALID_INTERNAL_ANNOTATION, variable, []);
+          }
+        }
+      } else if (parent is ConstructorDeclaration) {
+        var class_ = parent.declaredElement.enclosingElement;
+        if (class_.isPrivate || (parentElement?.isPrivate ?? false)) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+        }
+      } else if (parentElement?.isPrivate ?? false) {
+        _errorReporter
+            .reportErrorForNode(HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+      } else if (_inPublicPackageApi) {
+        _errorReporter
+            .reportErrorForNode(HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+      }
     } else if (element.isLiteral == true) {
       if (parent is! ConstructorDeclaration ||
           (parent as ConstructorDeclaration).constKeyword == null) {
@@ -270,9 +314,13 @@
     _invalidAccessVerifier._enclosingClass = element;
 
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
 
     try {
       // Commented out until we decide that we want this hint in the analyzer
@@ -284,6 +332,7 @@
       _enclosingClass = null;
       _invalidAccessVerifier._enclosingClass = null;
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -319,10 +368,17 @@
   @override
   void visitExportDirective(ExportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
+    _checkForInternalExport(node);
     super.visitExportDirective(node);
   }
 
   @override
+  void visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _checkForReturnOfDoNotStore(node.expression);
+    super.visitExpressionFunctionBody(node);
+  }
+
+  @override
   void visitFieldDeclaration(FieldDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
     if (_hasDeprecatedAnnotation(node.metadata)) {
@@ -361,35 +417,14 @@
               [field.name, overriddenElement.enclosingElement.name]);
         }
 
-        var expression = field.initializer;
-
-        Element element;
-        if (expression is PropertyAccess) {
-          element = expression.propertyName.staticElement;
-          // Tear-off.
-          if (element is FunctionElement || element is MethodElement) {
-            element = null;
-          }
-        } else if (expression is MethodInvocation) {
-          element = expression.methodName.staticElement;
-        } else if (expression is Identifier) {
-          element = expression.staticElement;
-          // Tear-off.
-          if (element is FunctionElement || element is MethodElement) {
-            element = null;
-          }
-        }
-        if (element != null) {
-          if (element is PropertyAccessorElement && element.isSynthetic) {
-            element = (element as PropertyAccessorElement).variable;
-          }
-          if (element.hasOrInheritsDoNotStore) {
-            _errorReporter.reportErrorForNode(
-              HintCode.ASSIGNMENT_OF_DO_NOT_STORE,
-              expression,
-              [element.name],
-            );
-          }
+        var expressionMap =
+            _getSubExpressionsMarkedDoNotStore(field.initializer);
+        for (var entry in expressionMap.entries) {
+          _errorReporter.reportErrorForNode(
+            HintCode.ASSIGNMENT_OF_DO_NOT_STORE,
+            entry.key,
+            [entry.value.name],
+          );
         }
       }
     } finally {
@@ -406,10 +441,14 @@
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     ExecutableElement element = node.declaredElement;
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
     try {
       _checkForMissingReturn(
           node.returnType, node.functionExpression.body, element, node);
@@ -423,6 +462,7 @@
       super.visitFunctionDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -497,6 +537,7 @@
     if (importElement != null && importElement.isDeferred) {
       _checkForLoadLibraryFunction(node, importElement);
     }
+    _invalidAccessVerifier.verifyImport(node);
     super.visitImportDirective(node);
   }
 
@@ -521,6 +562,7 @@
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
     bool wasInDeprecatedMember = _inDeprecatedMember;
+    bool wasInDoNotStoreMember = _inDoNotStoreMember;
     ExecutableElement element = node.declaredElement;
     Element enclosingElement = element?.enclosingElement;
 
@@ -544,10 +586,14 @@
     if (element != null && element.hasDeprecated) {
       _inDeprecatedMember = true;
     }
+    if (element != null && element.hasDoNotStore) {
+      _inDoNotStoreMember = true;
+    }
     try {
       // This was determined to not be a good hint, see: dartbug.com/16029
       //checkForOverridingPrivateMember(node);
       _checkForMissingReturn(node.returnType, node.body, element, node);
+      _mustCallSuperVerifier.checkMethodDeclaration(node);
       _checkForUnnecessaryNoSuchMethod(node);
 
       if (!node.isSetter && !elementIsOverride()) {
@@ -570,6 +616,7 @@
       super.visitMethodDeclaration(node);
     } finally {
       _inDeprecatedMember = wasInDeprecatedMember;
+      _inDoNotStoreMember = wasInDoNotStoreMember;
     }
   }
 
@@ -626,6 +673,12 @@
   }
 
   @override
+  void visitReturnStatement(ReturnStatement node) {
+    _checkForReturnOfDoNotStore(node.expression);
+    super.visitReturnStatement(node);
+  }
+
+  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     _checkForDuplications(node);
     super.visitSetOrMapLiteral(node);
@@ -641,6 +694,7 @@
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     _checkForDeprecatedMemberUse(node.staticElement, node);
+    _invalidAccessVerifier.verifySuperConstructorInvocation(node);
     super.visitSuperConstructorInvocation(node);
   }
 
@@ -997,6 +1051,47 @@
     }
   }
 
+  /// Check that the namespace exported by [node] does not include any elements
+  /// annotated with `@internal`.
+  void _checkForInternalExport(ExportDirective node) {
+    if (!_inPublicPackageApi) return;
+
+    var libraryElement = node.uriElement;
+    if (libraryElement == null) return;
+    if (libraryElement.hasInternal) {
+      _errorReporter.reportErrorForNode(
+          HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+          node,
+          [libraryElement.displayName]);
+    }
+    var exportNamespace =
+        NamespaceBuilder().createExportNamespaceForDirective(node.element);
+    exportNamespace.definedNames.forEach((String name, Element element) {
+      if (element.hasInternal) {
+        _errorReporter.reportErrorForNode(
+            HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+            node,
+            [element.displayName]);
+      } else if (element is FunctionElement) {
+        var signatureTypes = [
+          ...element.parameters.map((p) => p.type),
+          element.returnType,
+          ...element.typeParameters.map((tp) => tp.bound),
+        ];
+        for (var type in signatureTypes) {
+          var typeElement = type?.element?.enclosingElement;
+          if (typeElement is GenericTypeAliasElement &&
+              typeElement.hasInternal) {
+            _errorReporter.reportErrorForNode(
+                HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
+                node,
+                [typeElement.name, element.displayName]);
+          }
+        }
+      }
+    });
+  }
+
   void _checkForInvalidFactory(MethodDeclaration decl) {
     // Check declaration.
     // Note that null return types are expected to be flagged by other analyses.
@@ -1298,6 +1393,24 @@
     }
   }
 
+  void _checkForReturnOfDoNotStore(Expression expression) {
+    if (_inDoNotStoreMember) {
+      return;
+    }
+    var expressionMap = _getSubExpressionsMarkedDoNotStore(expression);
+    if (expressionMap.isNotEmpty) {
+      Declaration parent = expression.thisOrAncestorMatching(
+          (e) => e is FunctionDeclaration || e is MethodDeclaration);
+      for (var entry in expressionMap.entries) {
+        _errorReporter.reportErrorForNode(
+          HintCode.RETURN_OF_DO_NOT_STORE,
+          entry.key,
+          [entry.value.name, parent.declaredElement.displayName],
+        );
+      }
+    }
+  }
+
   /// Generate a hint for `noSuchMethod` methods that do nothing except of
   /// calling another `noSuchMethod` that is not defined by `Object`.
   ///
@@ -1441,6 +1554,50 @@
     }
   }
 
+  /// Return subexpressions that are marked `@doNotStore`, as a map so that
+  /// corresponding elements can be used in the diagnostic message.
+  Map<Expression, Element> _getSubExpressionsMarkedDoNotStore(
+      Expression expression,
+      {Map<Expression, Element> addTo}) {
+    var expressions = addTo ?? <Expression, Element>{};
+
+    Element element;
+    if (expression is PropertyAccess) {
+      element = expression.propertyName.staticElement;
+      // Tear-off.
+      if (element is FunctionElement || element is MethodElement) {
+        element = null;
+      }
+    } else if (expression is MethodInvocation) {
+      element = expression.methodName.staticElement;
+    } else if (expression is Identifier) {
+      element = expression.staticElement;
+      // Tear-off.
+      if (element is FunctionElement || element is MethodElement) {
+        element = null;
+      }
+    } else if (expression is ConditionalExpression) {
+      _getSubExpressionsMarkedDoNotStore(expression.elseExpression,
+          addTo: expressions);
+      _getSubExpressionsMarkedDoNotStore(expression.thenExpression,
+          addTo: expressions);
+    } else if (expression is BinaryExpression) {
+      _getSubExpressionsMarkedDoNotStore(expression.leftOperand,
+          addTo: expressions);
+      _getSubExpressionsMarkedDoNotStore(expression.rightOperand,
+          addTo: expressions);
+    }
+    if (element is PropertyAccessorElement && element.isSynthetic) {
+      element = (element as PropertyAccessorElement).variable;
+    }
+
+    if (element != null && element.hasOrInheritsDoNotStore) {
+      expressions[expression] = element;
+    }
+
+    return expressions;
+  }
+
   bool _isLibraryInWorkspacePackage(LibraryElement library) {
     if (_workspacePackage == null || library == null) {
       // Better to not make a big claim that they _are_ in the same package,
@@ -1647,13 +1804,15 @@
 
   final ErrorReporter _errorReporter;
   final LibraryElement _library;
+  final WorkspacePackage _workspacePackage;
 
   bool _inTemplateSource;
   bool _inTestDirectory;
 
   ClassElement _enclosingClass;
 
-  _InvalidAccessVerifier(this._errorReporter, this._library) {
+  _InvalidAccessVerifier(
+      this._errorReporter, this._library, this._workspacePackage) {
     var path = _library.source.fullName;
     _inTemplateSource = path.contains(_templateExtension);
     _inTestDirectory = path.contains(_testDir) ||
@@ -1661,20 +1820,19 @@
         path.contains(_testingDir);
   }
 
-  /// Produces a hint if [identifier] is accessed from an invalid location. In
-  /// particular:
+  /// Produces a hint if [identifier] is accessed from an invalid location.
   ///
-  /// * if the given identifier is a protected closure, field or
-  ///   getter/setter, method closure or invocation accessed outside a subclass,
-  ///   or accessed outside the library wherein the identifier is declared, or
-  /// * if the given identifier is a closure, field, getter, setter, method
-  ///   closure or invocation which is annotated with `visibleForTemplate`, and
-  ///   is accessed outside of the defining library, and the current library
-  ///   does not have the suffix '.template' in its source path, or
-  /// * if the given identifier is a closure, field, getter, setter, method
-  ///   closure or invocation which is annotated with `visibleForTesting`, and
-  ///   is accessed outside of the defining library, and the current library
-  ///   does not have a directory named 'test' or 'testing' in its path.
+  /// In particular, a hint is produced in either of the two following cases:
+  ///
+  /// * The element associated with [identifier] is annotated with [internal],
+  ///   and is accessed from outside the package in which the element is
+  ///   declared.
+  /// * The element associated with [identifier] is annotated with [protected],
+  ///   [visibleForTesting], and/or [visibleForTemplate], and is accessed from a
+  ///   location which is invalid as per the rules of each such annotation.
+  ///   Conversely, if the element is annotated with more than one of these
+  ///   annotations, the access is valid (and no hint will be produced) if it
+  ///   conforms to the rules of at least one of the annotations.
   void verify(SimpleIdentifier identifier) {
     if (identifier.inDeclarationContext() || _inCommentReference(identifier)) {
       return;
@@ -1688,24 +1846,64 @@
     }
     AstNode grandparent = parent?.parent;
 
-    Element element;
-    String name;
-    AstNode node;
-
-    if (grandparent is ConstructorName) {
-      element = grandparent.staticElement;
-      name = grandparent.toSource();
-      node = grandparent;
-    } else {
-      element = identifier.staticElement;
-      name = identifier.name;
-      node = identifier;
-    }
+    var element = grandparent is ConstructorName
+        ? grandparent.staticElement
+        : identifier.staticElement;
 
     if (element == null || _inCurrentLibrary(element)) {
       return;
     }
 
+    _checkForInvalidInternalAccess(identifier, element);
+    _checkForOtherInvalidAccess(identifier, element);
+  }
+
+  void verifyImport(ImportDirective node) {
+    var element = node.uriElement;
+    if (_hasInternal(element) &&
+        !_isLibraryInWorkspacePackage(element.library)) {
+      _errorReporter.reportErrorForNode(HintCode.INVALID_USE_OF_INTERNAL_MEMBER,
+          node, [node.uri.stringValue]);
+    }
+  }
+
+  void verifySuperConstructorInvocation(SuperConstructorInvocation node) {
+    if (node.constructorName != null) {
+      // Named constructor calls are handled by [verify].
+      return;
+    }
+    var element = node.staticElement;
+    if (_hasInternal(element) &&
+        !_isLibraryInWorkspacePackage(element.library)) {
+      _errorReporter.reportErrorForNode(
+          HintCode.INVALID_USE_OF_INTERNAL_MEMBER, node, [element.name]);
+    }
+  }
+
+  void _checkForInvalidInternalAccess(
+      SimpleIdentifier identifier, Element element) {
+    if (_hasInternal(element) &&
+        !_isLibraryInWorkspacePackage(element.library)) {
+      String name;
+      AstNode node;
+
+      var grandparent = identifier.parent?.parent;
+
+      if (grandparent is ConstructorName) {
+        name = grandparent.toSource();
+        node = grandparent;
+      } else {
+        name = identifier.name;
+        node = identifier;
+      }
+
+      _errorReporter.reportErrorForNode(
+          HintCode.INVALID_USE_OF_INTERNAL_MEMBER, node, [name]);
+    }
+  }
+
+  void _checkForOtherInvalidAccess(
+      SimpleIdentifier identifier, Element element) {
     bool hasProtected = _hasProtected(element);
     if (hasProtected) {
       ClassElement definingClass = element.enclosingElement;
@@ -1729,8 +1927,22 @@
     }
 
     // At this point, [identifier] was not cleared as protected access, nor
-    // cleared as access for templates or testing. Report the appropriate
-    // violation(s).
+    // cleared as access for templates or testing. Report a violation for each
+    // annotation present.
+
+    String name;
+    AstNode node;
+
+    var grandparent = identifier.parent?.parent;
+
+    if (grandparent is ConstructorName) {
+      name = grandparent.toSource();
+      node = grandparent;
+    } else {
+      name = identifier.name;
+      node = identifier;
+    }
+
     Element definingClass = element.enclosingElement;
     if (hasProtected) {
       _errorReporter.reportErrorForNode(
@@ -1753,6 +1965,19 @@
     }
   }
 
+  bool _hasInternal(Element element) {
+    if (element == null) {
+      return false;
+    }
+    if (element.hasInternal) {
+      return true;
+    }
+    if (element is PropertyAccessorElement && element.variable.hasInternal) {
+      return true;
+    }
+    return false;
+  }
+
   bool _hasProtected(Element element) {
     if (element is PropertyAccessorElement &&
         element.enclosingElement is ClassElement &&
@@ -1814,6 +2039,15 @@
   bool _inExportDirective(SimpleIdentifier identifier) =>
       identifier.parent is Combinator &&
       identifier.parent.parent is ExportDirective;
+
+  bool _isLibraryInWorkspacePackage(LibraryElement library) {
+    if (_workspacePackage == null || library == null) {
+      // Better to not make a big claim that they _are_ in the same package,
+      // if we were unable to determine what package [_currentLibrary] is in.
+      return false;
+    }
+    return _workspacePackage.contains(library.source);
+  }
 }
 
 /// A visitor that determines, upon visiting a function body and/or a
@@ -1855,7 +2089,7 @@
       case TargetKind.function:
         return 'top-level functions';
       case TargetKind.library:
-        return 'librarys';
+        return 'libraries';
       case TargetKind.getter:
         return 'getters';
       case TargetKind.method:
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 3fa6b6d..1832823 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -22,16 +22,24 @@
  * when appropriate, how the problem can be corrected.
  */
 class CompileTimeErrorCode extends AnalyzerErrorCode {
+  /**
+   * No parameters.
+   */
   static const CompileTimeErrorCode ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER =
-      CompileTimeErrorCode('ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER',
-          'Abstract fields cannot have initializers.',
+      CompileTimeErrorCodeWithUniqueName(
+          'ABSTRACT_FIELD_INITIALIZER',
+          'ABSTRACT_FIELD_CONSTRUCTOR_INITIALIZER',
+          "Abstract fields can't have initializers.",
           correction:
               "Try removing the field initializer or the 'abstract' keyword "
               "from the field declaration.");
 
+  /**
+   * No parameters.
+   */
   static const CompileTimeErrorCode ABSTRACT_FIELD_INITIALIZER =
       CompileTimeErrorCode('ABSTRACT_FIELD_INITIALIZER',
-          'Abstract fields cannot have initializers.',
+          "Abstract fields can't have initializers.",
           correction:
               "Try removing the initializer or the 'abstract' keyword.");
 
@@ -697,17 +705,56 @@
               "or removing the 'await' before the for loop.");
 
   /**
-   * nnbd/feature-specification.md
-   *
-   * It is an error for the initializer expression of a `late` local variable
-   * to use a prefix `await` expression.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a local variable that has the
+  // `late` modifier uses an `await` expression in the initializer.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because an `await` expression
+  // is used in the initializer for `v`, a local variable that is marked `late`:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // Future<int> f() async {
+  //   late v = [!await!] 42;
+  //   return v;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the initializer can be rewritten to not use `await`, then rewrite it:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // Future<int> f() async {
+  //   late v = 42;
+  //   return v;
+  // }
+  // ```
+  //
+  // If the initializer can't be rewritten, then remove the `late` modifier:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // Future<int> f() async {
+  //   var v = await 42;
+  //   return v;
+  // }
+  // ```
   static const CompileTimeErrorCode AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER =
-      CompileTimeErrorCode('AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER',
-          "The await expression can't be used in a 'late' local variable.",
+      CompileTimeErrorCode(
+          'AWAIT_IN_LATE_LOCAL_VARIABLE_INITIALIZER',
+          "The 'await' expression can't be used in a 'late' local variable's "
+              "initializer.",
           correction:
               "Try removing the 'late' modifier, or rewriting the initializer "
-              "without using the 'await' expression.");
+              "without using the 'await' expression.",
+          hasPublishedDocs: true);
 
   /**
    * 16.30 Await Expressions: It is a compile-time error if the function
@@ -1372,21 +1419,56 @@
               "removing the keyword 'const'.");
 
   /**
-   * 10.6.3 Constant Constructors: It is a compile-time error if a constant
-   * constructor is declared by a class C if any instance variable declared in C
-   * is initialized with an expression that is not a constant expression.
-   *
    * Parameters:
    * 0: the name of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a constructor has the keyword
+  // `const`, but a field in the class is initialized to a non-constant value.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the field `s` is
+  // initialized to a non-constant value:
+  //
+  // ```dart
+  // class C {
+  //   final String s = 3.toString();
+  //   [!const!] C();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the field can be initialized to a constant value, then change the
+  // initializer to a constant expression:
+  //
+  // ```dart
+  // class C {
+  //   final String s = '3';
+  //   const C();
+  // }
+  // ```
+  //
+  // If the field can't be initialized to a constant value, then remove the
+  // keyword `const` from the constructor:
+  //
+  // ```dart
+  // class C {
+  //   final String s = 3.toString();
+  //   C();
+  // }
+  // ```
   static const CompileTimeErrorCode
       CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST =
       CompileTimeErrorCode(
           'CONST_CONSTRUCTOR_WITH_FIELD_INITIALIZED_BY_NON_CONST',
-          "Can't define the const constructor because the field '{0}' "
-              "is initialized with a non-constant value.",
+          "Can't define the 'const' constructor because the field '{0}' is "
+              "initialized with a non-constant value.",
           correction: "Try initializing the field to a constant value, or "
-              "removing the keyword 'const' from the constructor.");
+              "removing the keyword 'const' from the constructor.",
+          hasPublishedDocs: true);
 
   /**
    * 7.6.3 Constant Constructors: The superinitializer that appears, explicitly
@@ -1618,7 +1700,7 @@
   //
   // The analyzer produces this diagnostic when a value that isn't statically
   // known to be a constant is assigned to a variable that's declared to be a
-  // 'const' variable.
+  // `const` variable.
   //
   // #### Examples
   //
@@ -1927,15 +2009,6 @@
           hasPublishedDocs: true);
 
   /**
-   * 16.12.2 Const: It is a compile-time error if <i>T</i> is not a class
-   * accessible in the current scope, optionally followed by type arguments.
-   *
-   * 16.12.2 Const: If <i>e</i> is of the form <i>const T.id(a<sub>1</sub>,
-   * &hellip;, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, &hellip;
-   * x<sub>n+k</sub>: a<sub>n+k</sub>)</i> it is a compile-time error if
-   * <i>T</i> is not a class accessible in the current scope, optionally
-   * followed by type arguments.
-   *
    * Parameters:
    * 0: the name of the non-type element
    */
@@ -1943,6 +2016,7 @@
       CompileTimeErrorCodeWithUniqueName('CREATION_WITH_NON_TYPE',
           'CONST_WITH_NON_TYPE', "The name '{0}' isn't a class.",
           correction: "Try correcting the name to match an existing class.",
+          hasPublishedDocs: true,
           isUnresolvedIdentifier: true);
 
   /**
@@ -2037,17 +2111,6 @@
           hasPublishedDocs: true);
 
   /**
-   * 6.2.1 Required Formals: By means of a function signature that names the
-   * parameter and describes its type as a function type. It is a compile-time
-   * error if any default values are specified in the signature of such a
-   * function type.
-   */
-  static const CompileTimeErrorCode DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER =
-      CompileTimeErrorCode('DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER',
-          "Default values aren't allowed in function typed parameters.",
-          correction: "Try removing the default value.");
-
-  /**
    * 7.6.2 Factories: It is a compile-time error if <i>k</i> explicitly
    * specifies a default value for an optional parameter.
    */
@@ -2113,10 +2176,9 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when
-  // [definite assignment](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md)
-  // analysis shows that a local variable that's marked as `late` is read before
-  // being assigned.
+  // The analyzer produces this diagnostic when [definite assignment][] analysis
+  // shows that a local variable that's marked as `late` is read before being
+  // assigned.
   //
   // #### Example
   //
@@ -2601,13 +2663,66 @@
    * Parameters:
    * 0: The name of the disallowed type
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when one of the restricted classes is
+  // used in either an `extends`, `implements`, `with`, or `on` clause. The
+  // classes `bool`, `double`, `FutureOr`, `int`, `Null`, `num`, and `String`
+  // are all restricted in this way, to allow for more efficient
+  // implementations.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `String` is used in an
+  // `extends` clause:
+  //
+  // ```dart
+  // class A extends [!String!] {}
+  // ```
+  //
+  // The following code produces this diagnostic because `String` is used in an
+  // `implements` clause:
+  //
+  // ```dart
+  // class B implements [!String!] {}
+  // ```
+  //
+  // The following code produces this diagnostic because `String` is used in a
+  // `with` clause:
+  //
+  // ```dart
+  // class C with [!String!] {}
+  // ```
+  //
+  // The following code produces this diagnostic because `String` is used in an
+  // `on` clause:
+  //
+  // ```dart
+  // mixin M on [!String!] {}
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If a different type should be specified, then replace the type:
+  //
+  // ```dart
+  // class A extends Object {}
+  // ```
+  //
+  // If there isn't a different type that would be appropriate, then remove the
+  // type, and possibly the whole clause:
+  //
+  // ```dart
+  // class B {}
+  // ```
   static const CompileTimeErrorCode EXTENDS_DISALLOWED_CLASS =
       // TODO(scheglov) We might want to restore specific code with FrontEnd.
       //  https://github.com/dart-lang/sdk/issues/31821
       CompileTimeErrorCodeWithUniqueName('SUBTYPE_OF_DISALLOWED_TYPE',
           'EXTENDS_DISALLOWED_CLASS', "Classes can't extend '{0}'.",
           correction: "Try specifying a different superclass, or "
-              "removing the extends clause.");
+              "removing the extends clause.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -2903,7 +3018,7 @@
   //
   // #### Common fixes
   //
-  // Use '.' rather than '..':
+  // Use `.` rather than `..`:
   //
   // ```dart
   // extension E on int {
@@ -3578,25 +3693,66 @@
           correction: "Try changing the types so that they are compatible.");
 
   /**
-   * nnbd/feature-specification.md
-   *
-   * It is an error if a class has a setter and a getter with the same basename
-   * where the return type of the getter is not a subtype of the argument type
-   * of the setter. Note that this error specifically requires subtyping and
-   * not assignability and hence makes no exception for `dynamic`.
-   *
    * Parameters:
    * 0: the name of the getter
    * 1: the type of the getter
    * 2: the type of the setter
    * 3: the name of the setter
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the return type of a getter
+  // isn't a subtype of the type of the parameter of a setter with the same
+  // name.
+  //
+  // The subtype relationship is a requirement whether the getter and setter are
+  // in the same class or whether one of them is in a superclass of the other.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the return type of the
+  // getter `x` is `num`, the parameter type of the setter `x` is `int`, and
+  // `num` isn't a subtype of `int`:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // class C {
+  //   num get [!x!] => 0;
+  //
+  //   set x(int y) {}
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the getter is correct, then change the type of the setter:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // class C {
+  //   num get x => 0;
+  //
+  //   set x(num y) {}
+  // }
+  // ```
+  //
+  // If the type of the setter is correct, then change the type of the getter:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // class C {
+  //   int get x => 0;
+  //
+  //   set x(int y) {}
+  // }
+  // ```
   static const CompileTimeErrorCode GETTER_NOT_SUBTYPE_SETTER_TYPES =
       CompileTimeErrorCode(
           'GETTER_NOT_SUBTYPE_SETTER_TYPES',
           "The return type of getter '{0}' is '{1}' which isn't a subtype "
               "of the type '{2}' of its setter '{3}'.",
-          correction: "Try changing the types so that they are compatible.");
+          correction: "Try changing the types so that they are compatible.",
+          hasPublishedDocs: true);
 
   static const CompileTimeErrorCode IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY =
       CompileTimeErrorCode(
@@ -3701,7 +3857,8 @@
           'IMPLEMENTS_DISALLOWED_CLASS',
           "Classes and mixins can't implement '{0}'.",
           correction: "Try specifying a different interface, or "
-              "remove the class from the list.");
+              "remove the class from the list.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -4371,15 +4528,79 @@
               "-9,223,372,036,854,775,808.");
 
   /**
-   * 15 Metadata: Metadata consists of a series of annotations, each of which
-   * begin with the character @, followed by a constant expression that must be
-   * either a reference to a compile-time constant variable, or a call to a
-   * constant constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an annotation is found that is
+  // using something that is neither a variable marked as `const` or the
+  // invocation of a `const` constructor.
+  //
+  // Getters can't be used as annotations.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the variable `v` isn't
+  // a `const` variable:
+  //
+  // ```dart
+  // var v = 0;
+  //
+  // [!@v!]
+  // void f() {
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because `f` isn't a variable:
+  //
+  // ```dart
+  // [!@f!]
+  // void f() {
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because `f` isn't a
+  // constructor:
+  //
+  // ```dart
+  // [!@f()!]
+  // void f() {
+  // }
+  // ```
+  //
+  // The following code produces this diagnostic because `g` is a getter:
+  //
+  // ```dart
+  // [!@g!]
+  // int get g => 0;
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the annotation is referencing a variable that isn't a `const`
+  // constructor, add the keyword `const` to the variable's declaration:
+  //
+  // ```dart
+  // const v = 0;
+  //
+  // @v
+  // void f() {
+  // }
+  // ```
+  //
+  // If the annotation isn't referencing a variable, then remove it:
+  //
+  // ```dart
+  // int v = 0;
+  //
+  // void f() {
+  // }
+  // ```
   static const CompileTimeErrorCode INVALID_ANNOTATION = CompileTimeErrorCode(
       'INVALID_ANNOTATION',
       "Annotation must be either a const variable reference or const "
-          "constructor invocation.");
+          "constructor invocation.",
+      hasPublishedDocs: true);
 
   /**
    * 15 Metadata: Metadata consists of a series of annotations, each of which
@@ -4404,7 +4625,8 @@
   static const CompileTimeErrorCode INVALID_ANNOTATION_GETTER =
       CompileTimeErrorCodeWithUniqueName('INVALID_ANNOTATION',
           'INVALID_ANNOTATION_GETTER', "Getters can't be used as annotations.",
-          correction: "Try using a top-level variable or a field.");
+          correction: "Try using a top-level variable or a field.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -5099,28 +5321,117 @@
           "correcting the name to match an existing label.");
 
   /**
-   * nnbd/feature-specification.md
-   *
-   * It is an error for a class with a `const` constructor to have a
-   * `late final` field.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a class that has at least one
+  // `const` constructor also has a field marked both `late` and `final`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the class `A` has a
+  // `const` constructor and the `final` field `f` is marked as `late`:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // class A {
+  //   [!late!] final int f;
+  //
+  //   const A();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the field doesn't need to be marked `late`, then remove the `late`
+  // modifier from the field:
+  //
+  // ```dart
+  // class A {
+  //   final int f = 0;
+  //
+  //   const A();
+  // }
+  // ```
+  //
+  // If the field must be marked `late`, then remove the `const` modifier from
+  // the constructors:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // class A {
+  //   late final int f;
+  //
+  //   A();
+  // }
+  // ```
   static const CompileTimeErrorCode LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR =
       CompileTimeErrorCode('LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR',
           "Can't have a late final field in a class with a const constructor.",
           correction: "Try removing the 'late' modifier, or don't declare "
-              "'const' constructors.");
+              "'const' constructors.",
+          hasPublishedDocs: true);
 
   /**
-   * nnbd/feature-specification.md
-   *
-   * It is a compile time error to assign a value to a local variable marked
-   * `late` and `final` when the variable is definitely assigned.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the analyzer can prove that a
+  // local variable marked as both `late` and `final` was already assigned a
+  // value at the point where another assignment occurs.
+  //
+  // Because `final` variables can only be assigned once, subsequent assignments
+  // are guaranteed to fail, so they're flagged.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the `final` variable
+  // `v` is assigned a value in two places:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // int f() {
+  //   late final int v;
+  //   v = 0;
+  //   [!v!] += 1;
+  //   return v;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you need to be able to reassign the variable, then remove the `final`
+  // keyword:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // int f() {
+  //   late int v;
+  //   v = 0;
+  //   v += 1;
+  //   return v;
+  // }
+  // ```
+  //
+  // If you don't need to reassign the variable, then remove all except the
+  // first of the assignments:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // int f() {
+  //   late final int v;
+  //   v = 0;
+  //   return v;
+  // }
+  // ```
   static const CompileTimeErrorCode LATE_FINAL_LOCAL_ALREADY_ASSIGNED =
       CompileTimeErrorCode('LATE_FINAL_LOCAL_ALREADY_ASSIGNED',
-          "The late final local variable is already definitely assigned.",
+          "The late final local variable is already assigned.",
           correction: "Try removing the 'final' modifier, or don't reassign "
-              "the value.");
+              "the value.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -5167,6 +5478,36 @@
           "The element type '{0}' can't be assigned to the list type '{1}'.",
           hasPublishedDocs: true);
 
+  static const CompileTimeErrorCode MAIN_FIRST_POSITIONAL_PARAMETER_TYPE =
+      CompileTimeErrorCode(
+    'MAIN_FIRST_POSITIONAL_PARAMETER_TYPE',
+    "The type of the first positional parameter of the 'main' function "
+        "must be a supertype of List<String>.",
+    correction: "Try changing the type of the parameter.",
+  );
+
+  static const CompileTimeErrorCode MAIN_HAS_REQUIRED_NAMED_PARAMETERS =
+      CompileTimeErrorCode(
+    'MAIN_HAS_REQUIRED_NAMED_PARAMETERS',
+    "The function 'main' can't have any required named parameters.",
+    correction: "Try using a different name for the function, "
+        "or removing the 'required' modifier.",
+  );
+
+  static const CompileTimeErrorCode
+      MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS = CompileTimeErrorCode(
+    'MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS',
+    "The function 'main' can't have more than two required positional parameters.",
+    correction: "Try using a different name for the function, "
+        "or removing extra parameters.",
+  );
+
+  static const CompileTimeErrorCode MAIN_IS_NOT_FUNCTION = CompileTimeErrorCode(
+    'MAIN_IS_NOT_FUNCTION',
+    "The declaration named 'main' must be a function.",
+    correction: "Try using a different name for this declaration.",
+  );
+
   /**
    * No parameters.
    */
@@ -5564,7 +5905,8 @@
       CompileTimeErrorCodeWithUniqueName('SUBTYPE_OF_DISALLOWED_TYPE',
           'MIXIN_OF_DISALLOWED_CLASS', "Classes can't mixin '{0}'.",
           correction: "Try specifying a different class or mixin, or "
-              "remove the class or mixin from the list.");
+              "remove the class or mixin from the list.",
+          hasPublishedDocs: true);
 
   /**
    * No parameters.
@@ -5617,9 +5959,10 @@
       CompileTimeErrorCodeWithUniqueName(
           'SUBTYPE_OF_DISALLOWED_TYPE',
           'MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS',
-          "'{0}' can't be used as a super-class constraint.",
+          "''{0}' can't be used as a superclass constraint.",
           correction: "Try specifying a different super-class constraint, or "
-              "remove the 'on' clause.");
+              "remove the 'on' clause.",
+          hasPublishedDocs: true);
 
   /**
    * No parameters.
@@ -5692,16 +6035,55 @@
           correction: "Try removing all but one of the 'super' initializers.");
 
   /**
-   * 12.11.1 New: It is a static warning if <i>T</i> is not a class accessible
-   * in the current scope, optionally followed by type arguments.
-   *
    * Parameters:
    * 0: the name of the non-type element
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an instance creation using
+  // either `new` or `const` specifies a name that isn't defined as a class.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `f` is a function
+  // rather than a class:
+  //
+  // ```dart
+  // int f() => 0;
+  //
+  // void g() {
+  //   new [!f!]();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If a class should be created, then replace the invalid name with the name
+  // of a valid class:
+  //
+  // ```dart
+  // int f() => 0;
+  //
+  // void g() {
+  //   new Object();
+  // }
+  // ```
+  //
+  // If the name is the name of a function and you want that function to be
+  // invoked, then remove the `new` or `const` keyword:
+  //
+  // ```dart
+  // int f() => 0;
+  //
+  // void g() {
+  //   f();
+  // }
+  // ```
   static const CompileTimeErrorCode NEW_WITH_NON_TYPE =
       CompileTimeErrorCodeWithUniqueName('CREATION_WITH_NON_TYPE',
           'NEW_WITH_NON_TYPE', "The name '{0}' isn't a class.",
           correction: "Try correcting the name to match an existing class.",
+          hasPublishedDocs: true,
           isUnresolvedIdentifier: true);
 
   /**
@@ -5820,24 +6202,67 @@
           hasPublishedDocs: true);
 
   /**
-   * A method `m` of a class `C` is subject to override inference if it is
-   * missing one or more component types of its signature, and one or more of
-   * the direct superinterfaces of `C` has a member named `m` (*that is, `C.m`
-   * overrides one or more declarations*).  Each missing type is filled in with
-   * the corresponding type from the combined member signature `s` of `m` in
-   * the direct superinterfaces of `C`.
-   *
-   * A compile-time error occurs if `s` does not exist.
-   *
    * Parameters:
    * 0: the name of the class where override error was detected
    * 1: the list of candidate signatures which cannot be combined
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when there is a method declaration
+  // for which one or more types needs to be inferred, and those types can't be
+  // inferred because none of the overridden methods has a function type that is
+  // a supertype of all the other overridden methods, as specified by
+  // [override inference][].
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the method `m` declared
+  // in the class `C` is missing both the return type and the type of the
+  // parameter `a`, and neither of the missing types can be inferred for it:
+  //
+  // ```dart
+  // abstract class A {
+  //   A m(String a);
+  // }
+  //
+  // abstract class B {
+  //   B m(int a);
+  // }
+  //
+  // abstract class C implements A, B {
+  //   [!m!](a);
+  // }
+  // ```
+  //
+  // In this example, override inference can't be performed because the
+  // overridden methods are incompatible in these ways:
+  // - Neither parameter type (`String` and `int`) is a supertype of the other.
+  // - Neither return type is a subtype of the other.
+  //
+  // #### Common fixes
+  //
+  // If possible, add types to the method in the subclass that are consistent
+  // with the types from all the overridden methods:
+  //
+  // ```dart
+  // abstract class A {
+  //   A m(String a);
+  // }
+  //
+  // abstract class B {
+  //   B m(int a);
+  // }
+  //
+  // abstract class C implements A, B {
+  //   C m(Object a);
+  // }
+  // ```
   static const CompileTimeErrorCode NO_COMBINED_SUPER_SIGNATURE =
       CompileTimeErrorCode('NO_COMBINED_SUPER_SIGNATURE',
-          "No valid combined signature in superinterfaces of '{0}': {1}.",
+          "Can't infer missing types in '{0}' from overridden methods: {1}.",
           correction: "Try providing explicit types for this method's "
-              "parameters and return type.");
+              "parameters and return type.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -6773,8 +7198,7 @@
   // - Doesn't have an initializer.
   // - Isn't marked as `late`.
   // - The analyzer can't prove that the local variable will be assigned before
-  //   the reference based on the specification of
-  //   [definite assignment](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md).
+  //   the reference based on the specification of [definite assignment.][]
   //
   // #### Example
   //
@@ -7485,16 +7909,52 @@
               "different part.");
 
   /**
-   * 14.1 Imports: It is a compile-time error if the current library declares a
-   * top-level member named <i>p</i>.
+   * Parameters:
+   * 0: The name of the prefix
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a name is used as both an import
+  // prefix and the name of a top-level declaration in the same library.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `f` is used as both an
+  // import prefix and the name of a function:
+  //
+  // ```dart
+  // import 'dart:math' as f;
+  //
+  // int [!f!]() => f.min(0, 1);
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If you want to use the name for the import prefix, then rename the
+  // top-level declaration:
+  //
+  // ```dart
+  // import 'dart:math' as f;
+  //
+  // int g() => f.min(0, 1);
+  // ```
+  //
+  // If you want to use the name for the top-level declaration, then rename the
+  // import prefix:
+  //
+  // ```dart
+  // import 'dart:math' as math;
+  //
+  // int f() => math.min(0, 1);
+  // ```
   static const CompileTimeErrorCode PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER =
       CompileTimeErrorCode(
           'PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER',
           "The name '{0}' is already used as an import prefix and can't be "
               "used to name a top-level element.",
           correction:
-              "Try renaming either the top-level element or the prefix.");
+              "Try renaming either the top-level element or the prefix.",
+          hasPublishedDocs: true);
 
   /**
    * Parameters:
@@ -9679,9 +10139,9 @@
    */
   // #### Description
   //
-  // The analyzer produces this diagnostic when an inherited member is
-  // referenced using `super`, but there’s no member with that name in the
-  // superclass chain.
+  // The analyzer produces this diagnostic when an inherited member (method,
+  // getter, setter, or operator) is referenced using `super`, but there’s no
+  // member with that name in the superclass chain.
   //
   // #### Examples
   //
@@ -9715,8 +10175,8 @@
   // If the member you intend to invoke is defined in the same class, then
   // remove the `super.`.
   //
-  // If not, then either add the member to one of the superclasses or remove the
-  // invocation.
+  // If the member isn’t defined, then either add the member to one of the
+  // superclasses or remove the invocation.
   static const CompileTimeErrorCode UNDEFINED_SUPER_METHOD =
       CompileTimeErrorCodeWithUniqueName(
           'UNDEFINED_SUPER_MEMBER',
@@ -10213,20 +10673,61 @@
           correction: "Try adjusting the number of type arguments.");
 
   /**
-   * It will be a static type warning if <i>m</i> is not a generic method with
-   * exactly <i>n</i> type parameters.
-   *
    * Parameters:
    * 0: the name of the method being referenced (<i>G</i>)
    * 1: the number of type parameters that were declared
    * 2: the number of type arguments provided
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a method or function is invoked
+  // with a different number of type arguments than the number of type
+  // parameters specified in its declaration. There must either be no type
+  // arguments or the number of arguments must match the number of parameters.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the invocation of the
+  // method `m` has two type arguments, but the declaration of `m` only has one
+  // type parameter:
+  //
+  // ```dart
+  // class C {
+  //   int m<A>(A a) => 0;
+  // }
+  //
+  // int f(C c) => c.m[!<int, int>!](2);
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type arguments are necessary, then make them match the number of
+  // type parameters by either adding or removing type arguments:
+  //
+  // ```dart
+  // class C {
+  //   int m<A>(A a) => 0;
+  // }
+  //
+  // int f(C c) => c.m<int>(2);
+  // ```
+  //
+  // If the type arguments aren't necessary, then remove them:
+  //
+  // ```dart
+  // class C {
+  //   int m<A>(A a) => 0;
+  // }
+  //
+  // int f(C c) => c.m(2);
+  // ```
   static const CompileTimeErrorCode WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD =
       CompileTimeErrorCode(
           'WRONG_NUMBER_OF_TYPE_ARGUMENTS_METHOD',
-          "The method '{0}' is declared with {1} type parameters, "
-              "but {2} type arguments were given.",
-          correction: "Try adjusting the number of type arguments.");
+          "The method '{0}' is declared with {1} type parameters, but {2} type "
+              "arguments are given.",
+          correction: "Try adjusting the number of type arguments.",
+          hasPublishedDocs: true);
 
   /**
    * Let `C` be a generic class that declares a formal type parameter `X`, and
@@ -10538,7 +11039,7 @@
   // #### Description
   //
   // The analyzer produces this diagnostic when a null-aware operator (`?.`,
-  // `?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
+  // `?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
   // non-nullable.
   //
   // #### Example
@@ -10560,6 +11061,26 @@
   // var b = [[!...?!]a];
   // ```
   //
+  // The following code produces this diagnostic because `s?.length` can't
+  // return `null`:
+  //
+  // ```dart
+  // %experiments=non-nullable
+  // void f(String? s) {
+  //   s?.length[!?.!]isEven;
+  // }
+  // ```
+  //
+  // The reason `s?.length` can't return `null` is because the null-aware
+  // operator following `s` short-circuits the evaluation of both `length` and
+  // `isEven` if `s` is `null`. In other words, if `s` is `null`, then neither
+  // `length` nor `isEven` will be invoked, and if `s` is non-`null`, then
+  // `length` can't return a `null` value. Either way, `isEven` can't be invoked
+  // on a `null` value, so the null-aware operator is neither necessary nor
+  // allowed. See
+  // [Understanding null safety](/null-safety/understanding-null-safety#smarter-null-aware-methods)
+  // for more details.
+  //
   // #### Common fixes
   //
   // Replace the null-aware operator with a non-null-aware equivalent; for
diff --git a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
new file mode 100644
index 0000000..f3a5942
--- /dev/null
+++ b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+
+class MustCallSuperVerifier {
+  final ErrorReporter _errorReporter;
+
+  MustCallSuperVerifier(this._errorReporter);
+
+  void checkMethodDeclaration(MethodDeclaration node) {
+    if (node.isStatic || node.isAbstract) {
+      return;
+    }
+    ExecutableElement overridden =
+        _findOverriddenMemberWithMustCallSuper(node.declaredElement);
+    if (overridden != null && _hasConcreteSuperMethod(node.declaredElement)) {
+      _SuperCallVerifier verifier = _SuperCallVerifier(overridden.name);
+      node.accept(verifier);
+      if (!verifier.superIsCalled) {
+        _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, node.name,
+            [overridden.enclosingElement.name]);
+      }
+    }
+  }
+
+  /// Find a method which is overridden by [node] and which is annotated with
+  /// `@mustCallSuper`.
+  ///
+  /// As per the definition of `mustCallSuper` [1], every method which overrides
+  /// a method annotated with `@mustCallSuper` is implicitly annotated with
+  /// `@mustCallSuper`.
+  ///
+  /// [1]: https://pub.dev/documentation/meta/latest/meta/mustCallSuper-constant.html
+  ExecutableElement _findOverriddenMemberWithMustCallSuper(
+      ExecutableElement element) {
+    //Element member = node.declaredElement;
+    if (element.enclosingElement is! ClassElement) {
+      return null;
+    }
+    ClassElement classElement = element.enclosingElement;
+    String name = element.name;
+
+    // Walk up the type hierarchy from [classElement], ignoring direct
+    // interfaces.
+    Queue<ClassElement> superclasses =
+        Queue.of(classElement.mixins.map((i) => i.element))
+          ..addAll(classElement.superclassConstraints.map((i) => i.element))
+          ..add(classElement.supertype?.element);
+    var visitedClasses = <ClassElement>{};
+    while (superclasses.isNotEmpty) {
+      ClassElement ancestor = superclasses.removeFirst();
+      if (ancestor == null || !visitedClasses.add(ancestor)) {
+        continue;
+      }
+      ExecutableElement member = ancestor.getMethod(name) ??
+          ancestor.getGetter(name) ??
+          ancestor.getSetter(name);
+      if (member is MethodElement && member.hasMustCallSuper) {
+        return member;
+      }
+      superclasses
+        ..addAll(ancestor.mixins.map((i) => i.element))
+        ..addAll(ancestor.superclassConstraints.map((i) => i.element))
+        ..add(ancestor.supertype?.element);
+    }
+    return null;
+  }
+
+  /// Returns whether [node] overrides a concrete method.
+  bool _hasConcreteSuperMethod(MethodElement element) {
+    ClassElement classElement = element.enclosingElement;
+    String name = element.name;
+
+    bool isConcrete(ClassElement element) =>
+        element.lookUpConcreteMethod(name, element.library) != null;
+
+    if (classElement.mixins.map((i) => i.element).any(isConcrete)) {
+      return true;
+    }
+    if (classElement.superclassConstraints
+        .map((i) => i.element)
+        .any(isConcrete)) {
+      return true;
+    }
+    if (classElement.supertype != null &&
+        isConcrete(classElement.supertype.element)) {
+      return true;
+    }
+
+    return false;
+  }
+}
+
+/// Recursively visits an AST, looking for method invocations.
+class _SuperCallVerifier extends RecursiveAstVisitor<void> {
+  bool superIsCalled = false;
+
+  final String name;
+
+  _SuperCallVerifier(this.name);
+
+  @override
+  void visitBinaryExpression(BinaryExpression node) {
+    if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
+      superIsCalled = true;
+    }
+    super.visitBinaryExpression(node);
+  }
+
+  @override
+  void visitMethodInvocation(MethodInvocation node) {
+    if (node.target is SuperExpression && node.methodName.name == name) {
+      superIsCalled = true;
+    }
+    super.visitMethodInvocation(node);
+  }
+}
diff --git a/pkg/analyzer/lib/src/error/return_type_verifier.dart b/pkg/analyzer/lib/src/error/return_type_verifier.dart
index 9d78748..af65202 100644
--- a/pkg/analyzer/lib/src/error/return_type_verifier.dart
+++ b/pkg/analyzer/lib/src/error/return_type_verifier.dart
@@ -152,7 +152,7 @@
     // `T` is the declared return type.
     // `S` is the static type of the expression.
     var T = enclosingExecutable.returnType;
-    var S = getStaticType(expression);
+    var S = expression.staticType;
 
     void reportTypeError() {
       if (enclosingExecutable.isClosure) {
@@ -253,7 +253,7 @@
     // `T` is the declared return type.
     // `S` is the static type of the expression.
     var T = enclosingExecutable.returnType;
-    var S = getStaticType(expression);
+    var S = expression.staticType;
 
     void reportTypeError() {
       if (enclosingExecutable.isClosure) {
@@ -398,19 +398,6 @@
     return _typeSystem.isSubtypeOf2(lowerBound, returnType);
   }
 
-  /// Return the static type of the given [expression] that is to be used for
-  /// type analysis.
-  ///
-  /// TODO(scheglov) this is duplicate
-  static DartType getStaticType(Expression expression) {
-    DartType type = expression.staticType;
-    if (type == null) {
-      // TODO(brianwilkerson) This should never happen.
-      return DynamicTypeImpl.instance;
-    }
-    return type;
-  }
-
   static bool _isVoidDynamic(DartType type) {
     return type.isVoid || type.isDynamic;
   }
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 90abe81..cb4d7fb 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -4,12 +4,11 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/type_provider.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/constant/evaluation.dart';
 import 'package:analyzer/src/dart/constant/value.dart';
-import 'package:analyzer/src/dart/element/type_system.dart' show TypeSystemImpl;
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/engine.dart' show RecordingErrorListener;
 import 'package:analyzer/src/generated/source.dart' show Source;
@@ -99,36 +98,26 @@
   /// The source containing the expression(s) that will be evaluated.
   final Source _source;
 
-  /// The type provider used to access the known types.
-  final TypeProvider _typeProvider;
-
-  /// The type system primitives.
-  final TypeSystemImpl _typeSystem;
+  /// The library containing the expression(s) that will be evaluated.
+  final LibraryElement _library;
 
   /// Initialize a newly created evaluator to evaluate expressions in the given
   /// [source]. The [typeProvider] is the type provider used to access known
   /// types.
-  ConstantEvaluator(this._source, TypeProvider typeProvider,
-      {TypeSystemImpl typeSystem})
-      : _typeSystem = typeSystem ??
-            TypeSystemImpl(
-              implicitCasts: true,
-              isNonNullableByDefault: false,
-              strictInference: false,
-              typeProvider: typeProvider,
-            ),
-        _typeProvider = typeProvider;
+  ConstantEvaluator(this._source, LibraryElement library) : _library = library;
 
   EvaluationResult evaluate(Expression expression) {
     RecordingErrorListener errorListener = RecordingErrorListener();
     ErrorReporter errorReporter = ErrorReporter(
       errorListener,
       _source,
-      isNonNullableByDefault: _typeSystem.isNonNullableByDefault,
+      isNonNullableByDefault: _library.isNonNullableByDefault,
     );
     DartObjectImpl result = expression.accept(ConstantVisitor(
-        ConstantEvaluationEngine(_typeProvider, DeclaredVariables(),
-            typeSystem: _typeSystem),
+        ConstantEvaluationEngine(
+          DeclaredVariables(),
+        ),
+        _library,
         errorReporter));
     List<AnalysisError> errors = errorListener.errors;
     if (errors.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index 0ae3509..9939ed4 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -3,27 +3,19 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
-import 'package:analyzer/src/dart/resolver/resolution_result.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/super_context.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
-import 'package:meta/meta.dart';
 
 /// An object used by instances of [ResolverVisitor] to resolve references
 /// within the AST structure to the elements being referenced. The requirements
@@ -88,19 +80,10 @@
   /// The element for the library containing the compilation unit being visited.
   final LibraryElement _definingLibrary;
 
-  /// The type representing the type 'dynamic'.
-  DartType _dynamicType;
-
-  /// The type representing the type 'Type'.
-  InterfaceType _typeType;
-
   /// Whether constant evaluation errors should be reported during resolution.
   @Deprecated('This field is no longer used')
   final bool reportConstEvaluationErrors;
 
-  /// Helper for extension method resolution.
-  final ExtensionMemberResolver _extensionResolver;
-
   /// Helper for resolving properties on types.
   final TypePropertyResolver _typePropertyResolver;
 
@@ -113,10 +96,7 @@
       MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()})
       : _definingLibrary = _resolver.definingLibrary,
-        _extensionResolver = _resolver.extensionResolver,
         _typePropertyResolver = _resolver.typePropertyResolver {
-    _dynamicType = _typeProvider.dynamicType;
-    _typeType = _typeProvider.typeType;
     _methodInvocationResolver = MethodInvocationResolver(
       _resolver,
       migratableAstInfoProvider,
@@ -138,8 +118,6 @@
 
   TypeProviderImpl get _typeProvider => _resolver.typeProvider;
 
-  TypeSystemImpl get _typeSystem => _resolver.typeSystem;
-
   @override
   void visitBreakStatement(BreakStatement node) {
     node.target = _lookupBreakOrContinueTarget(node, node.label, false);
@@ -391,68 +369,6 @@
   }
 
   @override
-  void visitIndexExpression(IndexExpression node) {
-    Expression target = node.realTarget;
-    DartType targetType = _getStaticType(target);
-
-    if (identical(targetType, NeverTypeImpl.instance)) {
-      _resolver.errorReporter.reportErrorForNode(
-        HintCode.RECEIVER_OF_TYPE_NEVER,
-        target,
-      );
-      return;
-    }
-
-    if (node.isNullAware) {
-      if (target is ExtensionOverride) {
-        // https://github.com/dart-lang/language/pull/953
-      } else {
-        targetType = _typeSystem.promoteToNonNull(targetType);
-      }
-    }
-
-    String getterMethodName = TokenType.INDEX.lexeme;
-    String setterMethodName = TokenType.INDEX_EQ.lexeme;
-
-    ResolutionResult result;
-    if (target is ExtensionOverride) {
-      result = _extensionResolver.getOverrideMember(target, getterMethodName);
-    } else {
-      result = _typePropertyResolver.resolve(
-        receiver: target,
-        receiverType: targetType,
-        name: getterMethodName,
-        receiverErrorNode: target,
-        nameErrorNode: target,
-      );
-    }
-
-    bool isInGetterContext = node.inGetterContext();
-    bool isInSetterContext = node.inSetterContext();
-    if (isInGetterContext && isInSetterContext) {
-      node.staticElement = result.setter;
-      node.auxiliaryElements = AuxiliaryElements(result.getter);
-      _resolver.setReadElement(node, result.getter);
-      _resolver.setWriteElement(node, result.setter);
-    } else if (isInGetterContext) {
-      node.staticElement = result.getter;
-      _resolver.setReadElement(node, result.getter);
-    } else if (isInSetterContext) {
-      node.staticElement = result.setter;
-      _resolver.setWriteElement(node, result.setter);
-    }
-
-    if (isInGetterContext) {
-      _checkForUndefinedIndexOperator(
-          node, target, getterMethodName, result, result.getter, targetType);
-    }
-    if (isInSetterContext) {
-      _checkForUndefinedIndexOperator(
-          node, target, setterMethodName, result, result.setter, targetType);
-    }
-  }
-
-  @override
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
     ConstructorElement invokedConstructor = node.constructorName.staticElement;
     ArgumentList argumentList = node.argumentList;
@@ -489,172 +405,6 @@
   }
 
   @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    SimpleIdentifier prefix = node.prefix;
-    SimpleIdentifier identifier = node.identifier;
-    //
-    // First, check the "lib.loadLibrary" case
-    //
-    if (identifier.name == FunctionElement.LOAD_LIBRARY_NAME &&
-        _isDeferredPrefix(prefix)) {
-      LibraryElement importedLibrary = _getImportedLibrary(prefix);
-      var element = importedLibrary?.loadLibraryFunction;
-      element = _resolver.toLegacyElement(element);
-      identifier.staticElement = element;
-      return;
-    }
-    //
-    // Check to see whether the prefix is really a prefix.
-    //
-    Element prefixElement = prefix.staticElement;
-    if (prefixElement is PrefixElement) {
-      var lookupResult = prefixElement.scope.lookup2(identifier.name);
-
-      if (identifier.inGetterContext()) {
-        _resolver.setReadElement(
-          node,
-          _resolver.toLegacyElement(lookupResult.getter),
-        );
-      }
-
-      if (identifier.inSetterContext()) {
-        _resolver.setWriteElement(
-          node,
-          _resolver.toLegacyElement(lookupResult.setter),
-        );
-      }
-
-      var element = lookupResult.getter;
-      if (element == null && identifier.inSetterContext()) {
-        element = lookupResult.setter;
-      }
-      element = _resolver.toLegacyElement(element);
-      if (element == null && _resolver.nameScope.shouldIgnoreUndefined(node)) {
-        return;
-      }
-      if (element == null) {
-        AstNode parent = node.parent;
-        if (parent is Annotation) {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_ANNOTATION,
-              parent,
-              [identifier.name]);
-        } else {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
-              identifier,
-              [identifier.name, prefixElement.name]);
-        }
-        return;
-      }
-      Element accessor = element;
-      if (accessor is PropertyAccessorElement && identifier.inSetterContext()) {
-        PropertyInducingElement variable = accessor.variable;
-        if (variable != null) {
-          PropertyAccessorElement setter = variable.setter;
-          if (setter != null) {
-            element = setter;
-          }
-        }
-      }
-      // TODO(brianwilkerson) The prefix needs to be resolved to the element for
-      // the import that defines the prefix, not the prefix's element.
-      identifier.staticElement = element;
-      // Validate annotation element.
-      AstNode parent = node.parent;
-      if (parent is Annotation) {
-        _resolveAnnotationElement(parent);
-      }
-      return;
-    }
-    // May be annotation, resolve invocation of "const" constructor.
-    AstNode parent = node.parent;
-    if (parent is Annotation) {
-      _resolveAnnotationElement(parent);
-      return;
-    }
-    //
-    // Otherwise, the prefix is really an expression that happens to be a simple
-    // identifier and this is really equivalent to a property access node.
-    //
-    _resolvePropertyAccess(
-      node,
-      prefix,
-      identifier,
-      isCascaded: false,
-      isNullAware: false,
-    );
-  }
-
-  @override
-  void visitPropertyAccess(PropertyAccess node) {
-    Expression target = node.realTarget;
-    if (target is SuperExpression &&
-        SuperContext.of(target) != SuperContext.valid) {
-      return;
-    } else if (target is ExtensionOverride) {
-      if (target.parent is CascadeExpression) {
-        // Report this error and recover by treating it like a non-cascade.
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
-          target.extensionName,
-        );
-      }
-      ExtensionElement element = target.extensionName.staticElement;
-      SimpleIdentifier propertyName = node.propertyName;
-      String memberName = propertyName.name;
-      ExecutableElement member;
-      var result = _extensionResolver.getOverrideMember(target, memberName);
-      if (propertyName.inSetterContext()) {
-        _resolver.setWriteElement(node, result.setter);
-        member = result.setter;
-        if (member == null) {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
-              propertyName,
-              [memberName, element.name]);
-        }
-        if (propertyName.inGetterContext()) {
-          _resolver.setReadElement(node, result.getter);
-          ExecutableElement getter = result.getter;
-          if (getter == null) {
-            _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
-                propertyName,
-                [memberName, element.name]);
-          }
-          propertyName.auxiliaryElements = AuxiliaryElements(getter);
-        }
-      } else if (propertyName.inGetterContext()) {
-        _resolver.setReadElement(node, result.getter);
-        member = result.getter;
-        if (member == null) {
-          _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
-              propertyName,
-              [memberName, element.name]);
-        }
-      }
-      if (member != null && member.isStatic) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
-            propertyName);
-      }
-
-      propertyName.staticElement = member;
-      return;
-    }
-    SimpleIdentifier propertyName = node.propertyName;
-    _resolvePropertyAccess(
-      node,
-      target,
-      propertyName,
-      isCascaded: node.isCascaded,
-      isNullAware: node.isNullAware,
-    );
-  }
-
-  @override
   void visitRedirectingConstructorInvocation(
       RedirectingConstructorInvocation node) {
     ClassElement enclosingClass = _resolver.enclosingClass;
@@ -692,113 +442,6 @@
   }
 
   @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    //
-    // Synthetic identifiers have been already reported during parsing.
-    //
-    if (node.isSynthetic) {
-      return;
-    }
-    //
-    // Ignore nodes that should have been resolved before getting here.
-    //
-    if (node.inDeclarationContext()) {
-      return;
-    }
-    if (node.staticElement is LocalVariableElement ||
-        node.staticElement is ParameterElement) {
-      return;
-    }
-    AstNode parent = node.parent;
-    if (parent is FieldFormalParameter) {
-      return;
-    } else if (parent is ConstructorFieldInitializer &&
-        parent.fieldName == node) {
-      return;
-    } else if (parent is Annotation && parent.constructorName == node) {
-      return;
-    }
-    //
-    // Otherwise, the node should be resolved.
-    //
-    Element element = _resolveSimpleIdentifier(node);
-    ClassElement enclosingClass = _resolver.enclosingClass;
-    if (_isFactoryConstructorReturnType(node) &&
-        !identical(element, enclosingClass)) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLASS, node);
-    } else if (_isConstructorReturnType(node) &&
-        !identical(element, enclosingClass)) {
-      // This error is now reported by the parser.
-      element = null;
-    } else if (element == null ||
-        (element is PrefixElement && !_isValidAsPrefix(node))) {
-      // TODO(brianwilkerson) Recover from this error.
-      if (_isConstructorReturnType(node)) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node);
-      } else if (parent is Annotation) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_ANNOTATION, parent, [node.name]);
-      } else if (element != null) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
-            node,
-            [element.name]);
-      } else if (node.name == "await" && _resolver.enclosingFunction != null) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
-          node,
-        );
-      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
-          node,
-          [node.name],
-        );
-      }
-    }
-    node.staticElement = element;
-
-    _resolver.setWriteElement(node, element);
-
-    Element getter;
-    var inGetterContext = node.inGetterContext();
-    if (inGetterContext) {
-      if (element is PropertyAccessorElement &&
-          element.enclosingElement is CompilationUnitElement) {
-        getter = element.variable.getter;
-      }
-    }
-
-    if (node.inSetterContext() && inGetterContext && enclosingClass != null) {
-      InterfaceType enclosingType = enclosingClass.thisType;
-      var result = _typePropertyResolver.resolve(
-        receiver: null,
-        receiverType: enclosingType,
-        name: node.name,
-        receiverErrorNode: node,
-        nameErrorNode: node,
-      );
-      node.auxiliaryElements = AuxiliaryElements(
-        result.getter,
-      );
-      getter ??= result.getter;
-    }
-
-    if (inGetterContext) {
-      _resolver.setReadElement(node, getter);
-    }
-
-    //
-    // Validate annotation element.
-    //
-    if (parent is Annotation) {
-      _resolveAnnotationElement(parent);
-    }
-  }
-
-  @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     ClassElementImpl enclosingClass = _resolver.enclosingClass;
     if (enclosingClass == null) {
@@ -861,7 +504,7 @@
   @override
   void visitSuperExpression(SuperExpression node) {
     var context = SuperContext.of(node);
-    if (context == SuperContext.static) {
+    if (context == SuperContext.annotation || context == SuperContext.static) {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, node);
     } else if (context == SuperContext.extension) {
@@ -886,143 +529,6 @@
     _resolveAnnotations(node.metadata);
   }
 
-  /// If the [element] is not static, report the error on the [identifier].
-  void _checkForStaticAccessToInstanceMember(
-    SimpleIdentifier identifier,
-    ExecutableElement element,
-  ) {
-    if (element.isStatic) return;
-
-    _errorReporter.reportErrorForNode(
-      CompileTimeErrorCode.STATIC_ACCESS_TO_INSTANCE_MEMBER,
-      identifier,
-      [identifier.name],
-    );
-  }
-
-  /// Check that the given index [expression] was resolved, otherwise a
-  /// [CompileTimeErrorCode.UNDEFINED_OPERATOR] is generated. The [target] is
-  /// the target of the expression. The [methodName] is the name of the operator
-  /// associated with the context of using of the given index expression.
-  void _checkForUndefinedIndexOperator(
-      IndexExpression expression,
-      Expression target,
-      String methodName,
-      ResolutionResult result,
-      ExecutableElement element,
-      DartType staticType) {
-    if (result.isAmbiguous) {
-      return;
-    }
-    if (element != null) {
-      return;
-    }
-    if (target is! ExtensionOverride) {
-      if (staticType == null || staticType.isDynamic) {
-        return;
-      }
-    }
-
-    var leftBracket = expression.leftBracket;
-    var rightBracket = expression.rightBracket;
-    var offset = leftBracket.offset;
-    var length = rightBracket.end - offset;
-    if (target is ExtensionOverride) {
-      _errorReporter.reportErrorForOffset(
-        CompileTimeErrorCode.UNDEFINED_EXTENSION_OPERATOR,
-        offset,
-        length,
-        [methodName, target.staticElement.name],
-      );
-    } else if (target is SuperExpression) {
-      _errorReporter.reportErrorForOffset(
-        CompileTimeErrorCode.UNDEFINED_SUPER_OPERATOR,
-        offset,
-        length,
-        [methodName, staticType],
-      );
-    } else if (staticType.isVoid) {
-      _errorReporter.reportErrorForOffset(
-        CompileTimeErrorCode.USE_OF_VOID_RESULT,
-        offset,
-        length,
-      );
-    } else if (identical(staticType, NeverTypeImpl.instance)) {
-      _resolver.errorReporter.reportErrorForNode(
-        HintCode.RECEIVER_OF_TYPE_NEVER,
-        target,
-      );
-    } else {
-      _errorReporter.reportErrorForOffset(
-        CompileTimeErrorCode.UNDEFINED_OPERATOR,
-        offset,
-        length,
-        [methodName, staticType],
-      );
-    }
-  }
-
-  /// Assuming that the given [identifier] is a prefix for a deferred import,
-  /// return the library that is being imported.
-  LibraryElement _getImportedLibrary(SimpleIdentifier identifier) {
-    PrefixElement prefixElement = identifier.staticElement as PrefixElement;
-    List<ImportElement> imports =
-        prefixElement.enclosingElement.getImportsWithPrefix(prefixElement);
-    return imports[0].importedLibrary;
-  }
-
-  /// Return the static type of the given [expression] that is to be used for
-  /// type analysis.
-  DartType _getStaticType(Expression expression, {bool read = false}) {
-    if (expression is NullLiteral) {
-      return _typeProvider.nullType;
-    }
-    DartType type = read ? getReadType(expression) : expression.staticType;
-    return _resolveTypeParameter(type);
-  }
-
-  InterfaceType _instantiateAnnotationClass(ClassElement element) {
-    return element.instantiate(
-      typeArguments: List.filled(
-        element.typeParameters.length,
-        _dynamicType,
-      ),
-      nullabilitySuffix: _resolver.noneOrStarSuffix,
-    );
-  }
-
-  /// Return `true` if the given [expression] is a prefix for a deferred import.
-  bool _isDeferredPrefix(Expression expression) {
-    if (expression is SimpleIdentifier) {
-      Element element = expression.staticElement;
-      if (element is PrefixElement) {
-        List<ImportElement> imports =
-            element.enclosingElement.getImportsWithPrefix(element);
-        if (imports.length != 1) {
-          return false;
-        }
-        return imports[0].isDeferred;
-      }
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [node] can validly be resolved to a prefix:
-  /// * it is the prefix in an import directive, or
-  /// * it is the prefix in a prefixed identifier.
-  bool _isValidAsPrefix(SimpleIdentifier node) {
-    AstNode parent = node.parent;
-    if (parent is ImportDirective) {
-      return identical(parent.prefix, node);
-    } else if (parent is PrefixedIdentifier) {
-      return true;
-    } else if (parent is MethodInvocation) {
-      return identical(parent.target, node) &&
-          parent.operator?.type == TokenType.PERIOD;
-    }
-    return false;
-  }
-
   /// Return the target of a break or continue statement, and update the static
   /// element of its label (if any). The [parentNode] is the AST node of the
   /// break or continue statement. The [labelNode] is the label contained in
@@ -1063,159 +569,6 @@
     }
   }
 
-  void _resolveAnnotationConstructorInvocationArguments(
-      Annotation annotation, ConstructorElement constructor) {
-    ArgumentList argumentList = annotation.arguments;
-    // error will be reported in ConstantVerifier
-    if (argumentList == null) {
-      return;
-    }
-    // resolve arguments to parameters
-    List<ParameterElement> parameters =
-        _resolveArgumentsToFunction(argumentList, constructor);
-    if (parameters != null) {
-      argumentList.correspondingStaticParameters = parameters;
-    }
-  }
-
-  /// Continues resolution of the given [annotation].
-  void _resolveAnnotationElement(Annotation annotation) {
-    SimpleIdentifier nameNode1;
-    SimpleIdentifier nameNode2;
-    {
-      Identifier annName = annotation.name;
-      if (annName is PrefixedIdentifier) {
-        nameNode1 = annName.prefix;
-        nameNode2 = annName.identifier;
-      } else {
-        nameNode1 = annName as SimpleIdentifier;
-        nameNode2 = null;
-      }
-    }
-    SimpleIdentifier nameNode3 = annotation.constructorName;
-    ConstructorElement constructor;
-    bool undefined = false;
-    //
-    // CONST or Class(args)
-    //
-    if (nameNode1 != null && nameNode2 == null && nameNode3 == null) {
-      Element element1 = nameNode1.staticElement;
-      // CONST
-      if (element1 is PropertyAccessorElement) {
-        _resolveAnnotationElementGetter(annotation, element1);
-        return;
-      }
-      // Class(args)
-      if (element1 is ClassElement) {
-        constructor = _instantiateAnnotationClass(element1)
-            .lookUpConstructor(null, _definingLibrary);
-        constructor = _resolver.toLegacyElement(constructor);
-      } else if (element1 == null) {
-        undefined = true;
-      }
-    }
-    //
-    // prefix.CONST or prefix.Class() or Class.CONST or Class.constructor(args)
-    //
-    if (nameNode1 != null && nameNode2 != null && nameNode3 == null) {
-      Element element1 = nameNode1.staticElement;
-      Element element2 = nameNode2.staticElement;
-      // Class.CONST - not resolved yet
-      if (element1 is ClassElement) {
-        element2 = element1.lookUpGetter(nameNode2.name, _definingLibrary);
-        element2 = _resolver.toLegacyElement(element2);
-      }
-      // prefix.CONST or Class.CONST
-      if (element2 is PropertyAccessorElement) {
-        nameNode2.staticElement = element2;
-        annotation.element = element2;
-        _resolveAnnotationElementGetter(annotation, element2);
-        return;
-      }
-      // prefix.Class()
-      if (element2 is ClassElement) {
-        constructor = element2.unnamedConstructor;
-        constructor = _resolver.toLegacyElement(constructor);
-      }
-      // Class.constructor(args)
-      if (element1 is ClassElement) {
-        constructor = _instantiateAnnotationClass(element1)
-            .lookUpConstructor(nameNode2.name, _definingLibrary);
-        constructor = _resolver.toLegacyElement(constructor);
-        nameNode2.staticElement = constructor;
-      }
-      if (element1 == null && element2 == null) {
-        undefined = true;
-      }
-    }
-    //
-    // prefix.Class.CONST or prefix.Class.constructor(args)
-    //
-    if (nameNode1 != null && nameNode2 != null && nameNode3 != null) {
-      Element element2 = nameNode2.staticElement;
-      // element2 should be ClassElement
-      if (element2 is ClassElement) {
-        String name3 = nameNode3.name;
-        // prefix.Class.CONST
-        PropertyAccessorElement getter =
-            element2.lookUpGetter(name3, _definingLibrary);
-        if (getter != null) {
-          getter = _resolver.toLegacyElement(getter);
-          nameNode3.staticElement = getter;
-          annotation.element = getter;
-          _resolveAnnotationElementGetter(annotation, getter);
-          return;
-        }
-        // prefix.Class.constructor(args)
-        constructor = _instantiateAnnotationClass(element2)
-            .lookUpConstructor(name3, _definingLibrary);
-        constructor = _resolver.toLegacyElement(constructor);
-        nameNode3.staticElement = constructor;
-      } else if (element2 == null) {
-        undefined = true;
-      }
-    }
-    // we need constructor
-    if (constructor == null) {
-      if (!undefined) {
-        // If the class was not found then we've already reported the error.
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
-      }
-      return;
-    }
-    // record element
-    annotation.element = constructor;
-    // resolve arguments
-    _resolveAnnotationConstructorInvocationArguments(annotation, constructor);
-  }
-
-  void _resolveAnnotationElementGetter(
-      Annotation annotation, PropertyAccessorElement accessorElement) {
-    // accessor should be synthetic
-    if (!accessorElement.isSynthetic) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ANNOTATION_GETTER, annotation);
-      return;
-    }
-    // variable should be constant
-    VariableElement variableElement = accessorElement.variable;
-    if (!variableElement.isConst) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.INVALID_ANNOTATION, annotation);
-      return;
-    }
-    // no arguments
-    if (annotation.arguments != null) {
-      _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.ANNOTATION_WITH_NON_CLASS,
-          annotation.name,
-          [annotation.name]);
-    }
-    // OK
-    return;
-  }
-
   /// Given an [argumentList] and the [executableElement] that will be invoked
   /// using those argument, compute the list of parameters that correspond to
   /// the list of arguments. An error will be reported if any of the arguments
@@ -1283,311 +636,6 @@
     _resolveAnnotations(node.metadata);
   }
 
-  void _resolvePropertyAccess(
-    Expression node,
-    Expression target,
-    SimpleIdentifier propertyName, {
-    @required bool isCascaded,
-    @required bool isNullAware,
-  }) {
-    DartType staticType = _getStaticType(target);
-
-    //
-    // If this property access is of the form 'E.m' where 'E' is an extension,
-    // then look for the member in the extension. This does not apply to
-    // conditional property accesses (i.e. 'C?.m').
-    //
-    if (target is Identifier && target.staticElement is ExtensionElement) {
-      ExtensionElement extension = target.staticElement;
-      String memberName = propertyName.name;
-
-      if (propertyName.inGetterContext()) {
-        ExecutableElement element;
-        element ??= extension.getGetter(memberName);
-        element ??= extension.getMethod(memberName);
-        if (element != null) {
-          element = _resolver.toLegacyElement(element);
-          propertyName.staticElement = element;
-          _checkForStaticAccessToInstanceMember(propertyName, element);
-        } else {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_EXTENSION_GETTER,
-            propertyName,
-            [memberName, extension.name],
-          );
-        }
-      }
-
-      if (propertyName.inSetterContext()) {
-        var element = extension.getSetter(memberName);
-        if (element != null) {
-          element = _resolver.toLegacyElement(element);
-          propertyName.staticElement = element;
-          _checkForStaticAccessToInstanceMember(propertyName, element);
-        } else {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_EXTENSION_SETTER,
-            propertyName,
-            [memberName, extension.name],
-          );
-        }
-      }
-
-      return;
-    }
-
-    //
-    // If this property access is of the form 'C.m' where 'C' is a class,
-    // then we don't call resolveProperty(...) which walks up the class
-    // hierarchy, instead we just look for the member in the type only.  This
-    // does not apply to conditional property accesses (i.e. 'C?.m').
-    //
-    ClassElement typeReference = getTypeReference(target);
-    if (typeReference != null) {
-      if (isCascaded) {
-        typeReference = _typeType.element;
-      }
-
-      if (propertyName.inGetterContext()) {
-        ExecutableElement element;
-
-        if (element == null) {
-          var getter = typeReference.getGetter(propertyName.name);
-          if (getter != null && getter.isAccessibleIn(_definingLibrary)) {
-            element = getter;
-          }
-        }
-
-        if (element == null) {
-          var method = typeReference.getMethod(propertyName.name);
-          if (method != null && method.isAccessibleIn(_definingLibrary)) {
-            element = method;
-          }
-        }
-
-        element = _resolver.toLegacyElement(element);
-        _resolver.setReadElement(node, element);
-
-        if (element != null) {
-          propertyName.staticElement = element;
-          _checkForStaticAccessToInstanceMember(propertyName, element);
-        } else {
-          var code = typeReference.isEnum
-              ? CompileTimeErrorCode.UNDEFINED_ENUM_CONSTANT
-              : CompileTimeErrorCode.UNDEFINED_GETTER;
-          _errorReporter.reportErrorForNode(
-            code,
-            propertyName,
-            [propertyName.name, typeReference.name],
-          );
-        }
-      }
-
-      if (propertyName.inSetterContext()) {
-        ExecutableElement element;
-
-        var setter = typeReference.getSetter(propertyName.name);
-        setter = _resolver.toLegacyElement(setter);
-
-        _resolver.setWriteElement(node, setter);
-
-        if (setter != null) {
-          element = setter;
-          if (!setter.isAccessibleIn(_definingLibrary)) {
-            _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.PRIVATE_SETTER,
-              propertyName,
-              [propertyName.name, typeReference.name],
-            );
-          }
-        }
-
-        if (element != null) {
-          propertyName.staticElement = element;
-          _checkForStaticAccessToInstanceMember(propertyName, element);
-        } else {
-          var getter = typeReference.getGetter(propertyName.name);
-          if (getter != null) {
-            propertyName.staticElement = getter;
-            _resolver.setWriteElement(node, getter);
-            // The error will be reported in ErrorVerifier.
-          } else {
-            _errorReporter.reportErrorForNode(
-              CompileTimeErrorCode.UNDEFINED_SETTER,
-              propertyName,
-              [propertyName.name, typeReference.name],
-            );
-          }
-        }
-      }
-
-      return;
-    }
-
-    if (target is SuperExpression) {
-      if (staticType is InterfaceTypeImpl) {
-        if (propertyName.inGetterContext()) {
-          var name = Name(_definingLibrary.source.uri, propertyName.name);
-          var element = _resolver.inheritance
-              .getMember2(staticType.element, name, forSuper: true);
-          _resolver.setReadElement(node, element);
-
-          if (element != null) {
-            element = _resolver.toLegacyElement(element);
-            propertyName.staticElement = element;
-          } else {
-            // We were not able to find the concrete dispatch target.
-            // But we would like to give the user at least some resolution.
-            // So, we retry simply looking for an inherited member.
-            var element =
-                _resolver.inheritance.getInherited2(staticType.element, name);
-            if (element != null) {
-              propertyName.staticElement = element;
-              _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
-                propertyName,
-                [element.kind.displayName, propertyName.name],
-              );
-            } else {
-              _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.UNDEFINED_SUPER_GETTER,
-                propertyName,
-                [propertyName.name, staticType],
-              );
-            }
-          }
-        }
-
-        if (propertyName.inSetterContext()) {
-          var element = staticType.lookUpSetter2(
-            propertyName.name,
-            _definingLibrary,
-            concrete: true,
-            inherited: true,
-          );
-          _resolver.setWriteElement(node, element);
-
-          if (element != null) {
-            element = _resolver.toLegacyElement(element);
-            propertyName.staticElement = element;
-          } else {
-            // We were not able to find the concrete dispatch target.
-            // But we would like to give the user at least some resolution.
-            // So, we retry without the "concrete" requirement.
-            var element = staticType.lookUpSetter2(
-              propertyName.name,
-              _definingLibrary,
-              inherited: true,
-            );
-            if (element != null) {
-              propertyName.staticElement = element;
-              ClassElementImpl receiverSuperClass =
-                  staticType.element.supertype.element;
-              if (!receiverSuperClass.hasNoSuchMethod) {
-                _errorReporter.reportErrorForNode(
-                  CompileTimeErrorCode.ABSTRACT_SUPER_MEMBER_REFERENCE,
-                  propertyName,
-                  [element.kind.displayName, propertyName.name],
-                );
-              }
-            } else {
-              _errorReporter.reportErrorForNode(
-                CompileTimeErrorCode.UNDEFINED_SUPER_SETTER,
-                propertyName,
-                [propertyName.name, staticType],
-              );
-            }
-          }
-        }
-      }
-
-      return;
-    }
-
-    if (staticType == null || staticType.isDynamic) {
-      return;
-    }
-
-    if (isNullAware) {
-      staticType = _typeSystem.promoteToNonNull(staticType);
-    }
-
-    if (staticType.isVoid) {
-      _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.USE_OF_VOID_RESULT,
-        propertyName,
-      );
-      return;
-    }
-
-    var result = _typePropertyResolver.resolve(
-      receiver: target,
-      receiverType: staticType,
-      name: propertyName.name,
-      receiverErrorNode: target,
-      nameErrorNode: propertyName,
-    );
-
-    if (propertyName.inGetterContext()) {
-      _resolver.setReadElement(node, result.getter);
-      var shouldReportUndefinedGetter = false;
-      if (result.isSingle) {
-        var getter = result.getter;
-        if (getter != null) {
-          propertyName.staticElement = getter;
-        } else {
-          shouldReportUndefinedGetter = true;
-        }
-      } else if (result.isNone) {
-        if (staticType is FunctionType &&
-            propertyName.name == FunctionElement.CALL_METHOD_NAME) {
-          // Referencing `.call` on a `Function` type is OK.
-        } else if (staticType is InterfaceType &&
-            staticType.isDartCoreFunction &&
-            propertyName.name == FunctionElement.CALL_METHOD_NAME) {
-          // Referencing `.call` on a `Function` type is OK.
-        } else if (staticType is NeverTypeImpl) {
-          shouldReportUndefinedGetter = false;
-        } else {
-          shouldReportUndefinedGetter = true;
-        }
-      }
-      if (shouldReportUndefinedGetter) {
-        _errorReporter.reportErrorForNode(
-          CompileTimeErrorCode.UNDEFINED_GETTER,
-          propertyName,
-          [propertyName.name, staticType],
-        );
-      }
-    }
-
-    if (propertyName.inSetterContext()) {
-      _resolver.setWriteElement(node, result.setter);
-      if (result.isSingle) {
-        var setter = result.setter;
-        if (setter != null) {
-          propertyName.staticElement = setter;
-          propertyName.auxiliaryElements = AuxiliaryElements(result.getter);
-        } else {
-          var getter = result.getter;
-          propertyName.staticElement = getter;
-          _resolver.setWriteElement(node, getter);
-          // A more specific error will be reported in ErrorVerifier.
-        }
-      } else if (result.isNone) {
-        if (staticType is NeverTypeImpl) {
-          // OK
-        } else {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_SETTER,
-            propertyName,
-            [propertyName.name, staticType],
-          );
-        }
-      }
-    }
-  }
-
   /// Resolve the given simple [identifier] if possible. Return the element to
   /// which it could be resolved, or `null` if it could not be resolved. This
   /// does not record the results of the resolution.
@@ -1611,7 +659,7 @@
             receiverType: enclosingClass.thisType,
             name: identifier.name,
             receiverErrorNode: identifier,
-            nameErrorNode: identifier,
+            nameErrorEntity: identifier,
           );
           setter = result.setter;
         }
@@ -1652,7 +700,7 @@
           receiverType: enclosingType,
           name: identifier.name,
           receiverErrorNode: identifier,
-          nameErrorNode: identifier,
+          nameErrorEntity: identifier,
         );
         if (identifier.inSetterContext() ||
             identifier.parent is CommentReference) {
@@ -1683,27 +731,6 @@
     return null;
   }
 
-  /// Return `true` if the given [identifier] is the return type of a
-  /// constructor declaration.
-  static bool _isConstructorReturnType(SimpleIdentifier identifier) {
-    AstNode parent = identifier.parent;
-    if (parent is ConstructorDeclaration) {
-      return identical(parent.returnType, identifier);
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [identifier] is the return type of a factory
-  /// constructor.
-  static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) {
-    AstNode parent = identifier.parent;
-    if (parent is ConstructorDeclaration) {
-      return identical(parent.returnType, identifier) &&
-          parent.factoryKeyword != null;
-    }
-    return false;
-  }
-
   /// Resolve each of the annotations in the given list of [annotations].
   static void _resolveAnnotations(NodeList<Annotation> annotations) {
     for (Annotation annotation in annotations) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 4bbf974..f1baaf4 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -287,6 +287,12 @@
 
   ExperimentStatus _contextFeatures = ExperimentStatus();
 
+  /// The language version to use for libraries that are not in a package.
+  ///
+  /// If a library is in a package, this language version is *not* used,
+  /// even if the package does not specify the language version.
+  Version nonPackageLanguageVersion = ExperimentStatus.currentVersion;
+
   /// The set of features to use for libraries that are not in a package.
   ///
   /// If a library is in a package, this feature set is *not* used, even if the
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 8abc401..dfc4756 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -17,6 +17,7 @@
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/class_hierarchy.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
@@ -40,7 +41,6 @@
 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary;
 import 'package:analyzer/src/generated/this_access_tracker.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:meta/meta.dart';
 
 class EnclosingExecutableContext {
@@ -305,6 +305,16 @@
   }
 
   @override
+  void visitAssertInitializer(AssertInitializer node) {
+    _isInConstructorInitializer = true;
+    try {
+      super.visitAssertInitializer(node);
+    } finally {
+      _isInConstructorInitializer = false;
+    }
+  }
+
+  @override
   void visitAssignmentExpression(AssignmentExpression node) {
     TokenType operatorType = node.operator.type;
     Expression lhs = node.leftHandSide;
@@ -319,10 +329,16 @@
       _checkForArgumentTypeNotAssignableForArgument(rhs);
     }
     if (operatorType == TokenType.QUESTION_QUESTION_EQ) {
-      _checkForDeadNullCoalesce(
-          getReadType(node.leftHandSide), node.rightHandSide);
+      _checkForDeadNullCoalesce(node.readType, node.rightHandSide);
     }
     _checkForAssignmentToFinal(lhs);
+    if (lhs is IndexExpression) {
+      _checkIndexExpressionIndex(
+        lhs.index,
+        readElement: node.readElement,
+        writeElement: node.writeElement,
+      );
+    }
     super.visitAssignmentExpression(node);
   }
 
@@ -355,8 +371,7 @@
     }
 
     if (type == TokenType.QUESTION_QUESTION) {
-      _checkForDeadNullCoalesce(
-          getReadType(node.leftOperand), node.rightOperand);
+      _checkForDeadNullCoalesce(node.leftOperand.staticType, node.rightOperand);
     }
 
     _checkForUseOfVoidResult(node.leftOperand);
@@ -435,6 +450,7 @@
       _checkForFinalNotInitializedInClass(members);
       _checkForBadFunctionUse(node);
       _checkForWrongTypeParameterVarianceInSuperinterfaces();
+      _checkForMainFunction(node.name);
       super.visitClassDeclaration(node);
     } finally {
       _isInNativeClass = false;
@@ -452,6 +468,7 @@
       _enclosingClass = node.declaredElement;
       _checkClassInheritance(
           node, node.superclass, node.withClause, node.implementsClause);
+      _checkForMainFunction(node.name);
       _checkForWrongTypeParameterVarianceInSuperinterfaces();
     } finally {
       _enclosingClass = outerClassElement;
@@ -533,7 +550,6 @@
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
     _checkForInvalidAssignment(node.identifier, node.defaultValue);
-    _checkForDefaultValueInFunctionTypedParameter(node);
     super.visitDefaultFormalParameter(node);
   }
 
@@ -711,6 +727,7 @@
       _checkForTypeAnnotationDeferredClass(returnType);
       _returnTypeVerifier.verifyReturnType(returnType);
       _checkForImplicitDynamicReturn(node.name, node.declaredElement);
+      _checkForMainFunction(node.name);
       super.visitFunctionDeclaration(node);
     });
   }
@@ -757,6 +774,7 @@
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
     _checkForBuiltInIdentifierAsName(
         node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
+    _checkForMainFunction(node.name);
     _checkForTypeAliasCannotReferenceItself(node, node.declaredElement);
     super.visitFunctionTypeAlias(node);
   }
@@ -792,6 +810,7 @@
   void visitGenericTypeAlias(GenericTypeAlias node) {
     _checkForBuiltInIdentifierAsName(
         node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME);
+    _checkForMainFunction(node.name);
     _checkForTypeAliasCannotReferenceItself(node, node.declaredElement);
     super.visitGenericTypeAlias(node);
   }
@@ -820,21 +839,11 @@
 
   @override
   void visitIndexExpression(IndexExpression node) {
-    void checkIndexExpression(MethodElement method) {
-      if (method != null) {
-        var parameters = method.parameters;
-        if (parameters.isNotEmpty) {
-          _checkForArgumentTypeNotAssignableForArgument2(
-            argument: node.index,
-            parameter: parameters[0],
-            promoteParameterToNullable: false,
-          );
-        }
-      }
-    }
-
-    checkIndexExpression(node.staticElement);
-    checkIndexExpression(node.auxiliaryElements?.staticElement);
+    _checkIndexExpressionIndex(
+      node.index,
+      readElement: node.staticElement,
+      writeElement: null,
+    );
 
     if (node.isNullAware) {
       _checkForUnnecessaryNullAware(
@@ -842,6 +851,7 @@
         node.question ?? node.period ?? node.leftBracket,
       );
     }
+
     super.visitIndexExpression(node);
   }
 
@@ -919,7 +929,6 @@
       _checkForTypeAnnotationDeferredClass(returnType);
       _returnTypeVerifier.verifyReturnType(returnType);
       _checkForImplicitDynamicReturn(node, node.declaredElement);
-      _checkForMustCallSuper(node);
       _checkForWrongTypeParameterVarianceInMethod(node);
       super.visitMethodDeclaration(node);
     });
@@ -966,6 +975,7 @@
 
       _checkForConflictingClassMembers();
       _checkForFinalNotInitializedInClass(members);
+      _checkForMainFunction(node.name);
       _checkForWrongTypeParameterVarianceInSuperinterfaces();
       //      _checkForBadFunctionUse(node);
       super.visitMixinDeclaration(node);
@@ -993,12 +1003,20 @@
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
+    var operand = node.operand;
     if (node.operator.type == TokenType.BANG) {
       _checkForUseOfVoidResult(node);
-      _checkForUnnecessaryNullAware(node.operand, node.operator);
+      _checkForUnnecessaryNullAware(operand, node.operator);
     } else {
-      _checkForAssignmentToFinal(node.operand);
-      _checkForIntNotAssignable(node.operand);
+      _checkForAssignmentToFinal(operand);
+      _checkForIntNotAssignable(operand);
+    }
+    if (operand is IndexExpression) {
+      _checkIndexExpressionIndex(
+        operand.index,
+        readElement: node.readElement,
+        writeElement: node.writeElement,
+      );
     }
     super.visitPostfixExpression(node);
   }
@@ -1026,6 +1044,13 @@
       _checkForUseOfVoidResult(operand);
       _checkForIntNotAssignable(operand);
     }
+    if (operand is IndexExpression) {
+      _checkIndexExpressionIndex(
+        operand.index,
+        readElement: node.readElement,
+        writeElement: node.writeElement,
+      );
+    }
     super.visitPrefixExpression(node);
   }
 
@@ -1174,6 +1199,11 @@
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
     _checkForFinalNotInitialized(node.variables);
     _checkForNotInitializedNonNullableVariable(node.variables);
+
+    for (var declaration in node.variables.variables) {
+      _checkForMainFunction(declaration.name);
+    }
+
     super.visitTopLevelVariableDeclaration(node);
   }
 
@@ -1568,7 +1598,7 @@
   void _checkForArgumentTypeNotAssignableWithExpectedTypes(
       Expression expression, DartType expectedStaticType, ErrorCode errorCode) {
     _checkForArgumentTypeNotAssignable(
-        expression, expectedStaticType, getStaticType(expression), errorCode);
+        expression, expectedStaticType, expression.staticType, errorCode);
   }
 
   /// Verify that the arguments in the given [argumentList] can be assigned to
@@ -1590,7 +1620,7 @@
 
   bool _checkForAssignableExpression(
       Expression expression, DartType expectedStaticType, ErrorCode errorCode) {
-    DartType actualStaticType = getStaticType(expression);
+    DartType actualStaticType = expression.staticType;
     return actualStaticType != null &&
         _checkForAssignableExpressionAtType(
             expression, actualStaticType, expectedStaticType, errorCode);
@@ -1628,6 +1658,9 @@
   /// [StaticWarningCode.ASSIGNMENT_TO_FINAL], and
   /// [StaticWarningCode.ASSIGNMENT_TO_METHOD].
   void _checkForAssignmentToFinal(Expression expression) {
+    // TODO(scheglov) Check SimpleIdentifier(s) as all other nodes.
+    if (expression is! SimpleIdentifier) return;
+
     // Already handled in the assignment resolver.
     if (expression is SimpleIdentifier &&
         expression.parent is AssignmentExpression) {
@@ -2215,26 +2248,6 @@
     }
   }
 
-  /// Verify that the given default formal [parameter] is not part of a function
-  /// typed parameter.
-  ///
-  /// See [CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER].
-  void _checkForDefaultValueInFunctionTypedParameter(
-      DefaultFormalParameter parameter) {
-    // OK, not in a function typed parameter.
-    if (!_isInFunctionTypedFormalParameter) {
-      return;
-    }
-    // OK, no default value.
-    if (parameter.defaultValue == null) {
-      return;
-    }
-
-    _errorReporter.reportErrorForNode(
-        CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER,
-        parameter);
-  }
-
   /// Report a diagnostic if there are any extensions in the imported library
   /// that are not hidden.
   void _checkForDeferredImportOfExtensions(
@@ -2290,7 +2303,7 @@
       return false;
     }
 
-    DartType iterableType = getStaticType(node.iterable);
+    DartType iterableType = node.iterable.staticType;
 
     // TODO(scheglov) use NullableDereferenceVerifier
     if (_isNonNullableByDefault) {
@@ -2528,7 +2541,7 @@
       return;
     }
     // test the static type of the expression
-    DartType staticType = getStaticType(expression);
+    DartType staticType = expression.staticType;
     if (staticType == null) {
       return;
     }
@@ -2969,7 +2982,7 @@
     } else {
       VariableElement leftVariableElement = getVariableElement(lhs);
       leftType = (leftVariableElement == null)
-          ? getStaticType(lhs)
+          ? lhs.staticType
           : leftVariableElement.type;
     }
 
@@ -3092,6 +3105,64 @@
     }
   }
 
+  void _checkForMainFunction(SimpleIdentifier nameNode) {
+    if (!_currentLibrary.isNonNullableByDefault) {
+      return;
+    }
+
+    var element = nameNode.staticElement;
+
+    // We should only check exported declarations, i.e. top-level.
+    if (element.enclosingElement is! CompilationUnitElement) {
+      return;
+    }
+
+    if (element.displayName != 'main') {
+      return;
+    }
+
+    if (element is! FunctionElement) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION,
+        nameNode,
+      );
+      return;
+    }
+
+    var functionDeclaration = nameNode.parent as FunctionDeclaration;
+    var functionExpression = functionDeclaration.functionExpression;
+    var parameters = functionExpression.parameters.parameters;
+    var positional = parameters.where((e) => e.isPositional).toList();
+    var requiredPositional =
+        parameters.where((e) => e.isRequiredPositional).toList();
+
+    if (requiredPositional.length > 2) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
+        nameNode,
+      );
+    }
+
+    if (parameters.any((e) => e.isRequiredNamed)) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS,
+        nameNode,
+      );
+    }
+
+    if (positional.isNotEmpty) {
+      var first = positional.first;
+      var type = first.declaredElement.type;
+      var listOfString = _typeProvider.listType2(_typeProvider.stringType);
+      if (!_typeSystem.isSubtypeOf2(listOfString, type)) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE,
+          first.notDefault.typeOrSelf,
+        );
+      }
+    }
+  }
+
   void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {
     // Determine the map's key and value types. We base this on the static type
     // and not the literal's type arguments because in strong mode, the type
@@ -3135,7 +3206,7 @@
   void _checkForMissingEnumConstantInSwitch(SwitchStatement statement) {
     // TODO(brianwilkerson) This needs to be checked after constant values have
     // been computed.
-    var expressionType = getStaticType(statement.expression);
+    var expressionType = statement.expression.staticType;
 
     var hasCaseNull = false;
     if (expressionType is InterfaceType) {
@@ -3413,21 +3484,6 @@
     }
   }
 
-  void _checkForMustCallSuper(MethodDeclaration node) {
-    if (node.isStatic || node.isAbstract) {
-      return;
-    }
-    MethodElement element = _findOverriddenMemberThatMustCallSuper(node);
-    if (element != null && _hasConcreteSuperMethod(node)) {
-      _InvocationCollector collector = _InvocationCollector();
-      node.accept(collector);
-      if (!collector.superCalls.contains(element.name)) {
-        _errorReporter.reportErrorForNode(HintCode.MUST_CALL_SUPER, node.name,
-            [element.enclosingElement.name]);
-      }
-    }
-  }
-
   /// Checks to ensure that the given native function [body] is in SDK code.
   ///
   /// See [ParserErrorCode.NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE].
@@ -3500,6 +3556,8 @@
     // try to find default generative super constructor
     ConstructorElement superUnnamedConstructor =
         superElement.unnamedConstructor;
+    superUnnamedConstructor =
+        _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
     if (superUnnamedConstructor != null) {
       if (superUnnamedConstructor.isFactory) {
         _errorReporter.reportErrorForNode(
@@ -4140,7 +4198,7 @@
     }
 
     // prepare 'switch' expression type
-    DartType expressionType = getStaticType(expression);
+    DartType expressionType = expression.staticType;
     if (expressionType == null) {
       return;
     }
@@ -4153,7 +4211,7 @@
     }
 
     Expression caseExpression = switchCase.expression;
-    DartType caseType = getStaticType(caseExpression);
+    DartType caseType = caseExpression.staticType;
 
     // check types
     if (!_typeSystem.isAssignableTo2(expressionType, caseType)) {
@@ -4306,6 +4364,8 @@
     }
     ConstructorElement superUnnamedConstructor =
         superElement.unnamedConstructor;
+    superUnnamedConstructor =
+        _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
     if (superUnnamedConstructor != null) {
       if (superUnnamedConstructor.isFactory) {
         _errorReporter.reportErrorForNode(
@@ -4826,6 +4886,34 @@
     }
   }
 
+  void _checkIndexExpressionIndex(
+    Expression index, {
+    @required ExecutableElement readElement,
+    @required ExecutableElement writeElement,
+  }) {
+    if (readElement is MethodElement) {
+      var parameters = readElement.parameters;
+      if (parameters.isNotEmpty) {
+        _checkForArgumentTypeNotAssignableForArgument2(
+          argument: index,
+          parameter: parameters[0],
+          promoteParameterToNullable: false,
+        );
+      }
+    }
+
+    if (writeElement is MethodElement) {
+      var parameters = writeElement.parameters;
+      if (parameters.isNotEmpty) {
+        _checkForArgumentTypeNotAssignableForArgument2(
+          argument: index,
+          parameter: parameters[0],
+          promoteParameterToNullable: false,
+        );
+      }
+    }
+  }
+
   void _checkMixinInference(
       NamedCompilationUnitMember node, WithClause withClause) {
     if (withClause == null) {
@@ -5047,47 +5135,6 @@
     return result;
   }
 
-  /// Find a method which is overridden by [node] and which is annotated with
-  /// `@mustCallSuper`.
-  ///
-  /// As per the definition of `mustCallSuper` [1], every method which overrides
-  /// a method annotated with `@mustCallSuper` is implicitly annotated with
-  /// `@mustCallSuper`.
-  ///
-  /// [1] https://pub.dev/documentation/meta/latest/meta/mustCallSuper-constant.html
-  MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
-    Element member = node.declaredElement;
-    if (member.enclosingElement is! ClassElement) {
-      return null;
-    }
-    ClassElement classElement = member.enclosingElement;
-    String name = member.name;
-
-    // Walk up the type hierarchy from [classElement], ignoring direct interfaces.
-    Queue<ClassElement> superclasses =
-        Queue.of(classElement.mixins.map((i) => i.element))
-          ..addAll(classElement.superclassConstraints.map((i) => i.element))
-          ..add(classElement.supertype?.element);
-    Set<ClassElement> visitedClasses = <ClassElement>{};
-    while (superclasses.isNotEmpty) {
-      ClassElement ancestor = superclasses.removeFirst();
-      if (ancestor == null || !visitedClasses.add(ancestor)) {
-        continue;
-      }
-      ExecutableElement member = ancestor.getMethod(name) ??
-          ancestor.getGetter(name) ??
-          ancestor.getSetter(name);
-      if (member is MethodElement && member.hasMustCallSuper) {
-        return member;
-      }
-      superclasses
-        ..addAll(ancestor.mixins.map((i) => i.element))
-        ..addAll(ancestor.superclassConstraints.map((i) => i.element))
-        ..add(ancestor.supertype?.element);
-    }
-    return null;
-  }
-
   /// Given an [expression] in a switch case whose value is expected to be an
   /// enum constant, return the name of the constant.
   String _getConstantName(Expression expression) {
@@ -5172,21 +5219,6 @@
     return buffer.toString();
   }
 
-  /// Returns whether [node] overrides a concrete method.
-  bool _hasConcreteSuperMethod(MethodDeclaration node) {
-    ClassElement classElement = node.declaredElement.enclosingElement;
-    String name = node.declaredElement.name;
-
-    Queue<ClassElement> superclasses =
-        Queue.of(classElement.mixins.map((i) => i.element))
-          ..addAll(classElement.superclassConstraints.map((i) => i.element));
-    if (classElement.supertype != null) {
-      superclasses.add(classElement.supertype.element);
-    }
-    return superclasses.any(
-        (parent) => parent.lookUpConcreteMethod(name, parent.library) != null);
-  }
-
   /// Return `true` if the given [constructor] redirects to itself, directly or
   /// indirectly.
   bool _hasRedirectingFactoryConstructorCycle(ConstructorElement constructor) {
@@ -5319,17 +5351,6 @@
     return fields.toList();
   }
 
-  /// Return the static type of the given [expression] that is to be used for
-  /// type analysis.
-  static DartType getStaticType(Expression expression) {
-    DartType type = expression.staticType;
-    if (type == null) {
-      // TODO(brianwilkerson) This should never happen.
-      return DynamicTypeImpl.instance;
-    }
-    return type;
-  }
-
   /// Return the variable element represented by the given [expression], or
   /// `null` if there is no such element.
   static VariableElement getVariableElement(Expression expression) {
@@ -5384,19 +5405,6 @@
   }
 }
 
-/// Recursively visits an AST, looking for method invocations.
-class _InvocationCollector extends RecursiveAstVisitor<void> {
-  final List<String> superCalls = <String>[];
-
-  @override
-  void visitMethodInvocation(MethodInvocation node) {
-    if (node.target is SuperExpression) {
-      superCalls.add(node.methodName.name);
-    }
-    super.visitMethodInvocation(node);
-  }
-}
-
 /// Recursively visits a type annotation, looking uninstantiated bounds.
 class _UninstantiatedBoundChecker extends RecursiveAstVisitor<void> {
   final ErrorReporter _errorReporter;
diff --git a/pkg/analyzer/lib/src/generated/migration.dart b/pkg/analyzer/lib/src/generated/migration.dart
index 8ea9925..93d82cc 100644
--- a/pkg/analyzer/lib/src/generated/migration.dart
+++ b/pkg/analyzer/lib/src/generated/migration.dart
@@ -31,6 +31,10 @@
   DartType modifyInferredParameterType(
       ParameterElement parameter, DartType type);
 
+  /// Called after the resolver has determined the read and write types
+  /// of the assignment expression.
+  void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node);
+
   /// Called when the resolver starts or stops making use of a [FlowAnalysis]
   /// instance.
   void setFlowAnalysis(
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 208d851..89c2ca2 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -145,8 +145,7 @@
 
   /// A flag indicating whether the analyzer [Parser] factory method
   /// will return a fasta based parser or an analyzer based parser.
-  static const bool useFasta =
-      bool.fromEnvironment("useFastaParser", defaultValue: true);
+  static const bool useFasta = true;
 
   /// The source being parsed.
   final Source _source;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index d1fedd3..46728e7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -24,6 +24,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/resolver/annotation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/binary_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
@@ -37,7 +38,10 @@
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/postfix_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/prefix_expression_resolver.dart';
+import 'package:analyzer/src/dart/resolver/prefixed_identifier_resolver.dart';
+import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/dart/resolver/simple_identifier_resolver.dart';
 import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
 import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
 import 'package:analyzer/src/dart/resolver/variable_declaration_resolver.dart';
@@ -175,6 +179,7 @@
   FunctionExpressionResolver _functionExpressionResolver;
   ForResolver _forResolver;
   PostfixExpressionResolver _postfixExpressionResolver;
+  PrefixedIdentifierResolver _prefixedIdentifierResolver;
   PrefixExpressionResolver _prefixExpressionResolver;
   VariableDeclarationResolver _variableDeclarationResolver;
   YieldStatementResolver _yieldStatementResolver;
@@ -350,6 +355,7 @@
       resolver: this,
       flowAnalysis: _flowAnalysis,
     );
+    _prefixedIdentifierResolver = PrefixedIdentifierResolver(this);
     _prefixExpressionResolver = PrefixExpressionResolver(
       resolver: this,
       flowAnalysis: _flowAnalysis,
@@ -371,8 +377,8 @@
         reportConstEvaluationErrors: reportConstEvaluationErrors,
         migratableAstInfoProvider: _migratableAstInfoProvider);
     inferenceContext = InferenceContext._(this);
-    typeAnalyzer = StaticTypeAnalyzer(
-        this, featureSet, _flowAnalysis, migrationResolutionHooks);
+    typeAnalyzer =
+        StaticTypeAnalyzer(this, _flowAnalysis, migrationResolutionHooks);
   }
 
   /// Return the element representing the function containing the current node,
@@ -444,7 +450,10 @@
     }
   }
 
-  void checkReadOfNotAssignedLocalVariable(SimpleIdentifier node) {
+  void checkReadOfNotAssignedLocalVariable(
+    SimpleIdentifier node,
+    Element element,
+  ) {
     if (_flowAnalysis?.flow == null) {
       return;
     }
@@ -453,7 +462,6 @@
       return;
     }
 
-    var element = node.staticElement;
     if (element is VariableElement) {
       var assigned = _flowAnalysis.isDefinitelyAssigned(node, element);
       var unassigned = _flowAnalysis.isDefinitelyUnassigned(node, element);
@@ -580,6 +588,69 @@
     _thisType = enclosingClass?.thisType;
   }
 
+  /// Resolve LHS [node] of an assignment, an explicit [AssignmentExpression],
+  /// or implicit [PrefixExpression] or [PostfixExpression].
+  PropertyElementResolverResult resolveForWrite({
+    @required AstNode node,
+    @required bool hasRead,
+  }) {
+    if (node is IndexExpression) {
+      node.target?.accept(this);
+      startNullAwareIndexExpression(node);
+
+      var resolver = PropertyElementResolver(this);
+      var result = resolver.resolveIndexExpression(
+        node: node,
+        hasRead: hasRead,
+        hasWrite: true,
+      );
+
+      InferenceContext.setType(node.index, result.indexContextType);
+      node.index.accept(this);
+
+      return result;
+    } else if (node is PrefixedIdentifier) {
+      node.prefix?.accept(this);
+
+      var resolver = PropertyElementResolver(this);
+      return resolver.resolvePrefixedIdentifier(
+        node: node,
+        hasRead: hasRead,
+        hasWrite: true,
+      );
+    } else if (node is PropertyAccess) {
+      node.target?.accept(this);
+      startNullAwarePropertyAccess(node);
+
+      var resolver = PropertyElementResolver(this);
+      return resolver.resolvePropertyAccess(
+        node: node,
+        hasRead: hasRead,
+        hasWrite: true,
+      );
+    } else if (node is SimpleIdentifier) {
+      var resolver = PropertyElementResolver(this);
+      var result = resolver.resolveSimpleIdentifier(
+        node: node,
+        hasRead: hasRead,
+        hasWrite: true,
+      );
+
+      if (hasRead && result.readElementRequested == null) {
+        errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+          node,
+          [node.name],
+        );
+      }
+
+      return result;
+    } else {
+      node.accept(this);
+      return PropertyElementResolverResult();
+    }
+  }
+
   /// Visit the given [comment] if it is not `null`.
   void safelyVisitComment(Comment comment) {
     if (comment != null) {
@@ -587,6 +658,55 @@
     }
   }
 
+  /// TODO(scheglov) This is mostly necessary for backward compatibility.
+  /// Although we also use `staticElement` for `getType(left)` below.
+  void setAssignmentBackwardCompatibility({
+    @required CompoundAssignmentExpression assignment,
+    @required AstNode left,
+    @required bool hasRead,
+  }) {
+    if (left is IndexExpression) {
+      if (hasRead) {
+        left.staticElement = assignment.writeElement;
+        // ignore: deprecated_member_use_from_same_package
+        left.auxiliaryElements = AuxiliaryElements(assignment.readElement);
+      } else {
+        left.staticElement = assignment.writeElement;
+      }
+      inferenceHelper.recordStaticType(left, assignment.writeType);
+      return;
+    }
+
+    SimpleIdentifier leftIdentifier;
+    if (left is PrefixedIdentifier) {
+      leftIdentifier = left.identifier;
+      inferenceHelper.recordStaticType(left, assignment.writeType);
+    } else if (left is PropertyAccess) {
+      leftIdentifier = left.propertyName;
+      inferenceHelper.recordStaticType(left, assignment.writeType);
+    } else if (left is SimpleIdentifier) {
+      leftIdentifier = left;
+    } else {
+      return;
+    }
+
+    if (hasRead) {
+      var readElement = assignment.readElement;
+      if (readElement is PropertyAccessorElement) {
+        // ignore: deprecated_member_use_from_same_package
+        leftIdentifier.auxiliaryElements = AuxiliaryElements(readElement);
+      }
+    }
+
+    leftIdentifier.staticElement = assignment.writeElement;
+    if (assignment.readElement is VariableElement) {
+      var leftType = localVariableTypeProvider.getType(leftIdentifier);
+      inferenceHelper.recordStaticType(leftIdentifier, leftType);
+    } else {
+      inferenceHelper.recordStaticType(leftIdentifier, assignment.writeType);
+    }
+  }
+
   void setReadElement(Expression node, Element element) {
     DartType readType = DynamicTypeImpl.instance;
     if (node is IndexExpression) {
@@ -664,6 +784,31 @@
     }
   }
 
+  void startNullAwareIndexExpression(IndexExpression node) {
+    if (_migratableAstInfoProvider.isIndexExpressionNullAware(node) &&
+        _isNonNullableByDefault) {
+      _flowAnalysis.flow.nullAwareAccess_rightBegin(
+          node.target, node.realTarget.staticType ?? typeProvider.dynamicType);
+      _unfinishedNullShorts.add(node.nullShortingTermination);
+    }
+  }
+
+  void startNullAwarePropertyAccess(
+    PropertyAccess node,
+  ) {
+    if (_migratableAstInfoProvider.isPropertyAccessNullAware(node) &&
+        _isNonNullableByDefault) {
+      var target = node.target;
+      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
+        // `?.` to access static methods is equivalent to `.`, so do nothing.
+      } else {
+        _flowAnalysis.flow.nullAwareAccess_rightBegin(
+            target, node.realTarget.staticType ?? typeProvider.dynamicType);
+        _unfinishedNullShorts.add(node.nullShortingTermination);
+      }
+    }
+  }
+
   /// If in a legacy library, return the legacy view on the [element].
   /// Otherwise, return the original element.
   T toLegacyElement<T extends Element>(T element) {
@@ -686,22 +831,7 @@
         identical(parent, _enclosingMixinDeclaration)) {
       return;
     }
-    node.name?.accept(this);
-    node.constructorName?.accept(this);
-    Element element = node.element;
-    if (element is ExecutableElement) {
-      InferenceContext.setType(node.arguments, element.type);
-    }
-    node.arguments?.accept(this);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-    ElementAnnotationImpl elementAnnotationImpl = node.elementAnnotation;
-    if (elementAnnotationImpl == null) {
-      // Analyzer ignores annotations on "part of" directives.
-      assert(parent is PartOfDirective);
-    } else {
-      elementAnnotationImpl.annotationAst = _createCloner().cloneNode(node);
-    }
+    AnnotationResolver(this).resolve(node);
   }
 
   @override
@@ -963,6 +1093,7 @@
   void visitConditionalExpression(ConditionalExpression node) {
     Expression condition = node.condition;
     var flow = _flowAnalysis?.flow;
+    flow?.conditional_conditionBegin();
 
     // TODO(scheglov) Do we need these checks for null?
     condition?.accept(this);
@@ -1368,6 +1499,7 @@
 
   @override
   void visitIfElement(IfElement node) {
+    _flowAnalysis?.flow?.ifStatement_conditionBegin();
     Expression condition = node.condition;
     InferenceContext.setType(condition, typeProvider.boolType);
     // TODO(scheglov) Do we need these checks for null?
@@ -1405,6 +1537,7 @@
   @override
   void visitIfStatement(IfStatement node) {
     checkUnreachableNode(node);
+    _flowAnalysis?.flow?.ifStatement_conditionBegin();
 
     Expression condition = node.condition;
 
@@ -1446,23 +1579,32 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     node.target?.accept(this);
-    if (_migratableAstInfoProvider.isIndexExpressionNullAware(node) &&
-        _isNonNullableByDefault) {
-      _flowAnalysis.flow.nullAwareAccess_rightBegin(
-          node.target, node.realTarget.staticType ?? typeProvider.dynamicType);
-      _unfinishedNullShorts.add(node.nullShortingTermination);
-    }
-    node.accept(elementResolver);
-    var method = node.staticElement;
-    if (method != null) {
-      var parameters = method.parameters;
-      if (parameters.isNotEmpty) {
-        var indexParam = parameters[0];
-        InferenceContext.setType(node.index, indexParam.type);
-      }
-    }
+    startNullAwareIndexExpression(node);
+
+    var resolver = PropertyElementResolver(this);
+    var result = resolver.resolveIndexExpression(
+      node: node,
+      hasRead: true,
+      hasWrite: false,
+    );
+
+    var element = result.readElement;
+    node.staticElement = element;
+
+    InferenceContext.setType(node.index, result.indexContextType);
     node.index?.accept(this);
-    node.accept(typeAnalyzer);
+
+    DartType type;
+    if (identical(node.realTarget.staticType, NeverTypeImpl.instance)) {
+      type = NeverTypeImpl.instance;
+    } else if (element is MethodElement) {
+      type = element.returnType;
+    } else {
+      type = DynamicTypeImpl.instance;
+    }
+    inferenceHelper.recordStaticType(node, type);
+
+    nullShortingTermination(node);
   }
 
   @override
@@ -1620,13 +1762,7 @@
 
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    //
-    // We visit the prefix, but do not visit the identifier because it needs to
-    // be visited in the context of the prefix.
-    //
-    node.prefix?.accept(this);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+    _prefixedIdentifierResolver.resolve(node);
   }
 
   @override
@@ -1636,24 +1772,36 @@
 
   @override
   void visitPropertyAccess(PropertyAccess node) {
-    //
-    // We visit the target, but do not visit the property name because it needs
-    // to be visited in the context of the property access node.
-    //
-    var target = node.target;
-    target?.accept(this);
-    if (_migratableAstInfoProvider.isPropertyAccessNullAware(node) &&
-        _isNonNullableByDefault) {
-      if (target is SimpleIdentifier && target.staticElement is ClassElement) {
-        // `?.` to access static methods is equivalent to `.`, so do nothing.
-      } else {
-        _flowAnalysis.flow.nullAwareAccess_rightBegin(
-            target, node.realTarget.staticType ?? typeProvider.dynamicType);
-        _unfinishedNullShorts.add(node.nullShortingTermination);
-      }
+    node.target?.accept(this);
+    startNullAwarePropertyAccess(node);
+
+    var resolver = PropertyElementResolver(this);
+    var result = resolver.resolvePropertyAccess(
+      node: node,
+      hasRead: true,
+      hasWrite: false,
+    );
+
+    var element = result.readElement;
+
+    var propertyName = node.propertyName;
+    propertyName.staticElement = element;
+
+    DartType type;
+    if (element is MethodElement) {
+      type = element.type;
+    } else if (element is PropertyAccessorElement && element.isGetter) {
+      type = element.returnType;
+    } else {
+      type = DynamicTypeImpl.instance;
     }
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
+
+    type = inferenceHelper.inferTearOff(node, propertyName, type);
+
+    inferenceHelper.recordStaticType(propertyName, type);
+    inferenceHelper.recordStaticType(node, type);
+
+    nullShortingTermination(node);
   }
 
   @override
@@ -1700,13 +1848,7 @@
 
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.inDeclarationContext()) {
-      return;
-    }
-
-    checkReadOfNotAssignedLocalVariable(node);
-
-    super.visitSimpleIdentifier(node);
+    SimpleIdentifierResolver(this, _flowAnalysis).resolve(node);
   }
 
   @override
@@ -1859,8 +2001,24 @@
   void visitVariableDeclaration(VariableDeclaration node) {
     _variableDeclarationResolver.resolve(node);
 
+    var declaredElement = node.declaredElement;
     if (node.parent.parent is ForParts) {
-      _define(node.declaredElement);
+      _define(declaredElement);
+    }
+
+    var initializer = node.initializer;
+    var parent = node.parent as VariableDeclarationList;
+    TypeAnnotation declaredType = parent.type;
+    if (initializer != null) {
+      var initializerStaticType = initializer.staticType;
+      if (declaredType == null) {
+        if (initializerStaticType is TypeParameterType) {
+          _flowAnalysis?.flow?.promote(declaredElement, initializerStaticType);
+        }
+      } else if (!parent.isFinal) {
+        _flowAnalysis?.flow?.write(declaredElement, initializerStaticType,
+            viaInitializer: true);
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index 1f141f7..2ac5298 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -6,7 +6,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
 import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:pub_semver/pub_semver.dart';
 
@@ -32,9 +31,6 @@
   /// if the file cannot be read, e.g. does not exist.
   String get allowedExperimentsJson;
 
-  /// Return the analysis context used for all of the sources in this [DartSdk].
-  AnalysisContext get context;
-
   /// Return the language version of this SDK, or throws an exception.
   ///
   /// The language version has only major/minor components, the patch number
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 3f662eb..6a45033 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -2,25 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
-import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migration.dart';
 import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/variable_type_provider.dart';
-import 'package:analyzer/src/task/strong/checker.dart'
-    show getExpressionType, getReadType;
 
 /// Instances of the class `StaticTypeAnalyzer` perform two type-related tasks. First, they
 /// compute the static type of every expression. Second, they look for any static type errors or
@@ -33,9 +27,6 @@
   /// The resolver driving the resolution and type analysis.
   final ResolverVisitor _resolver;
 
-  /// The feature set that should be used to resolve types.
-  final FeatureSet _featureSet;
-
   final MigrationResolutionHooks _migrationResolutionHooks;
 
   /// The object providing access to the types defined by the language.
@@ -47,27 +38,19 @@
   /// The type representing the type 'dynamic'.
   DartType _dynamicType;
 
-  /// The object providing promoted or declared types of variables.
-  LocalVariableTypeProvider _localVariableTypeProvider;
-
   final FlowAnalysisHelper _flowAnalysis;
 
   /// Initialize a newly created static type analyzer to analyze types for the
   /// [_resolver] based on the
   ///
   /// @param resolver the resolver driving this participant
-  StaticTypeAnalyzer(this._resolver, this._featureSet, this._flowAnalysis,
-      this._migrationResolutionHooks) {
+  StaticTypeAnalyzer(
+      this._resolver, this._flowAnalysis, this._migrationResolutionHooks) {
     _typeProvider = _resolver.typeProvider;
     _typeSystem = _resolver.typeSystem;
     _dynamicType = _typeProvider.dynamicType;
-    _localVariableTypeProvider = _resolver.localVariableTypeProvider;
   }
 
-  /// Is `true` if the library being analyzed is non-nullable by default.
-  bool get _isNonNullableByDefault =>
-      _featureSet.isEnabled(Feature.non_nullable);
-
   /// Given a constructor for a generic type, returns the equivalent generic
   /// function type that we could use to forward to the constructor, or for a
   /// non-generic type simply returns the constructor type.
@@ -120,7 +103,7 @@
   /// `String`.</blockquote>
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
-    recordStaticType(node, _nonNullable(_typeProvider.stringType));
+    recordStaticType(node, _typeProvider.stringType);
   }
 
   /// The Dart Language Specification, 12.32: <blockquote>... the cast expression <i>e as T</i> ...
@@ -140,7 +123,7 @@
   ///   the static type of e.
   @override
   void visitAwaitExpression(AwaitExpression node) {
-    DartType resultType = _getStaticType(node.expression);
+    DartType resultType = node.expression.staticType;
     if (resultType != null) resultType = _typeSystem.flatten(resultType);
     recordStaticType(node, resultType);
   }
@@ -149,7 +132,7 @@
   /// bool.</blockquote>
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
-    recordStaticType(node, _nonNullable(_typeProvider.boolType));
+    recordStaticType(node, _typeProvider.boolType);
   }
 
   /// The Dart Language Specification, 12.15.2: <blockquote>A cascaded method invocation expression
@@ -157,7 +140,7 @@
   /// t;}(e)</i>.</blockquote>
   @override
   void visitCascadeExpression(CascadeExpression node) {
-    recordStaticType(node, _getStaticType(node.target));
+    recordStaticType(node, node.target.staticType);
   }
 
   /// The Dart Language Specification, 12.19: <blockquote> ... a conditional expression <i>c</i> of
@@ -176,7 +159,7 @@
   /// double.</blockquote>
   @override
   void visitDoubleLiteral(DoubleLiteral node) {
-    recordStaticType(node, _nonNullable(_typeProvider.doubleType));
+    recordStaticType(node, _typeProvider.doubleType);
   }
 
   @override
@@ -215,32 +198,6 @@
   @override
   void visitFunctionExpression(FunctionExpression node) {}
 
-  /// The Dart Language Specification, 12.29: <blockquote>An assignable expression of the form
-  /// <i>e<sub>1</sub>[e<sub>2</sub>]</i> is evaluated as a method invocation of the operator method
-  /// <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</blockquote>
-  @override
-  void visitIndexExpression(IndexExpression node) {
-    if (identical(node.realTarget.staticType, NeverTypeImpl.instance)) {
-      recordStaticType(node, NeverTypeImpl.instance);
-    } else {
-      DartType type;
-      if (node.inSetterContext()) {
-        var parameters = node.staticElement?.parameters;
-        if (parameters?.length == 2) {
-          type = parameters[1].type;
-        }
-      } else {
-        type = node.staticElement?.returnType;
-      }
-
-      type ??= _dynamicType;
-
-      recordStaticType(node, type);
-    }
-
-    _resolver.nullShortingTermination(node);
-  }
-
   /// The Dart Language Specification, 12.11.1: <blockquote>The static type of a new expression of
   /// either the form <i>new T.id(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> or the form <i>new
   /// T(a<sub>1</sub>, &hellip;, a<sub>n</sub>)</i> is <i>T</i>.</blockquote>
@@ -277,9 +234,9 @@
     if (context == null ||
         _typeSystem.isAssignableTo2(_typeProvider.intType, context) ||
         !_typeSystem.isAssignableTo2(_typeProvider.doubleType, context)) {
-      recordStaticType(node, _nonNullable(_typeProvider.intType));
+      recordStaticType(node, _typeProvider.intType);
     } else {
-      recordStaticType(node, _nonNullable(_typeProvider.doubleType));
+      recordStaticType(node, _typeProvider.doubleType);
     }
   }
 
@@ -289,7 +246,7 @@
   /// The static type of an is-expression is `bool`.</blockquote>
   @override
   void visitIsExpression(IsExpression node) {
-    recordStaticType(node, _nonNullable(_typeProvider.boolType));
+    recordStaticType(node, _typeProvider.boolType);
   }
 
   @override
@@ -300,7 +257,7 @@
   @override
   void visitNamedExpression(NamedExpression node) {
     Expression expression = node.expression;
-    recordStaticType(node, _getStaticType(expression));
+    recordStaticType(node, expression.staticType);
   }
 
   /// The Dart Language Specification, 12.2: <blockquote>The static type of `null` is bottom.
@@ -313,124 +270,7 @@
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
     Expression expression = node.expression;
-    recordStaticType(node, _getStaticType(expression));
-  }
-
-  /// See [visitSimpleIdentifier].
-  @override
-  void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    SimpleIdentifier prefixedIdentifier = node.identifier;
-    Element staticElement = prefixedIdentifier.staticElement;
-
-    if (staticElement is ExtensionElement) {
-      _setExtensionIdentifierType(node);
-      return;
-    }
-
-    if (identical(node.prefix.staticType, NeverTypeImpl.instance)) {
-      recordStaticType(prefixedIdentifier, NeverTypeImpl.instance);
-      recordStaticType(node, NeverTypeImpl.instance);
-      return;
-    }
-
-    DartType staticType = _dynamicType;
-    if (staticElement is ClassElement) {
-      if (_isExpressionIdentifier(node)) {
-        var type = _nonNullable(_typeProvider.typeType);
-        node.staticType = type;
-        node.identifier.staticType = type;
-      }
-      return;
-    } else if (staticElement is DynamicElementImpl) {
-      var type = _nonNullable(_typeProvider.typeType);
-      node.staticType = type;
-      node.identifier.staticType = type;
-      return;
-    } else if (staticElement is FunctionTypeAliasElement) {
-      if (node.parent is TypeName) {
-        // no type
-      } else {
-        var type = _nonNullable(_typeProvider.typeType);
-        node.staticType = type;
-        node.identifier.staticType = type;
-      }
-      return;
-    } else if (staticElement is MethodElement) {
-      staticType = staticElement.type;
-    } else if (staticElement is PropertyAccessorElement) {
-      staticType = _getTypeOfProperty(staticElement);
-    } else if (staticElement is ExecutableElement) {
-      staticType = staticElement.type;
-    } else if (staticElement is VariableElement) {
-      staticType = staticElement.type;
-    }
-
-    staticType = _inferTearOff(node, node.identifier, staticType);
-    if (!_inferObjectAccess(node, staticType, prefixedIdentifier)) {
-      recordStaticType(prefixedIdentifier, staticType);
-      recordStaticType(node, staticType);
-    }
-  }
-
-  /// The Dart Language Specification, 12.13: <blockquote> Property extraction allows for a member of
-  /// an object to be concisely extracted from the object. If <i>o</i> is an object, and if <i>m</i>
-  /// is the name of a method member of <i>o</i>, then
-  /// * <i>o.m</i> is defined to be equivalent to: <i>(r<sub>1</sub>, &hellip;, r<sub>n</sub>,
-  /// {p<sub>1</sub> : d<sub>1</sub>, &hellip;, p<sub>k</sub> : d<sub>k</sub>}){return
-  /// o.m(r<sub>1</sub>, &hellip;, r<sub>n</sub>, p<sub>1</sub>: p<sub>1</sub>, &hellip;,
-  /// p<sub>k</sub>: p<sub>k</sub>);}</i> if <i>m</i> has required parameters <i>r<sub>1</sub>,
-  /// &hellip;, r<sub>n</sub></i>, and named parameters <i>p<sub>1</sub> &hellip; p<sub>k</sub></i>
-  /// with defaults <i>d<sub>1</sub>, &hellip;, d<sub>k</sub></i>.
-  /// * <i>(r<sub>1</sub>, &hellip;, r<sub>n</sub>, [p<sub>1</sub> = d<sub>1</sub>, &hellip;,
-  /// p<sub>k</sub> = d<sub>k</sub>]){return o.m(r<sub>1</sub>, &hellip;, r<sub>n</sub>,
-  /// p<sub>1</sub>, &hellip;, p<sub>k</sub>);}</i> if <i>m</i> has required parameters
-  /// <i>r<sub>1</sub>, &hellip;, r<sub>n</sub></i>, and optional positional parameters
-  /// <i>p<sub>1</sub> &hellip; p<sub>k</sub></i> with defaults <i>d<sub>1</sub>, &hellip;,
-  /// d<sub>k</sub></i>.
-  /// Otherwise, if <i>m</i> is the name of a getter member of <i>o</i> (declared implicitly or
-  /// explicitly) then <i>o.m</i> evaluates to the result of invoking the getter. </blockquote>
-  ///
-  /// The Dart Language Specification, 12.17: <blockquote> ... a getter invocation <i>i</i> of the
-  /// form <i>e.m</i> ...
-  ///
-  /// Let <i>T</i> be the static type of <i>e</i>. It is a static type warning if <i>T</i> does not
-  /// have a getter named <i>m</i>.
-  ///
-  /// The static type of <i>i</i> is the declared return type of <i>T.m</i>, if <i>T.m</i> exists;
-  /// otherwise the static type of <i>i</i> is dynamic.
-  ///
-  /// ... a getter invocation <i>i</i> of the form <i>C.m</i> ...
-  ///
-  /// It is a static warning if there is no class <i>C</i> in the enclosing lexical scope of
-  /// <i>i</i>, or if <i>C</i> does not declare, implicitly or explicitly, a getter named <i>m</i>.
-  ///
-  /// The static type of <i>i</i> is the declared return type of <i>C.m</i> if it exists or dynamic
-  /// otherwise.
-  ///
-  /// ... a top-level getter invocation <i>i</i> of the form <i>m</i>, where <i>m</i> is an
-  /// identifier ...
-  ///
-  /// The static type of <i>i</i> is the declared return type of <i>m</i>.</blockquote>
-  @override
-  void visitPropertyAccess(PropertyAccess node) {
-    SimpleIdentifier propertyName = node.propertyName;
-    Element staticElement = propertyName.staticElement;
-    DartType staticType = _dynamicType;
-    if (staticElement is MethodElement) {
-      staticType = staticElement.type;
-    } else if (staticElement is PropertyAccessorElement) {
-      staticType = _getTypeOfProperty(staticElement);
-    } else {
-      // TODO(brianwilkerson) Report this internal error.
-    }
-
-    staticType = _inferTearOff(node, node.propertyName, staticType);
-
-    if (!_inferObjectAccess(node, staticType, propertyName)) {
-      recordStaticType(propertyName, staticType);
-      recordStaticType(node, staticType);
-      _resolver.nullShortingTermination(node);
-    }
+    recordStaticType(node, expression.staticType);
   }
 
   /// The Dart Language Specification, 12.9: <blockquote>The static type of a rethrow expression is
@@ -440,102 +280,18 @@
     recordStaticType(node, _typeProvider.bottomType);
   }
 
-  /// The Dart Language Specification, 12.30: <blockquote>Evaluation of an identifier expression
-  /// <i>e</i> of the form <i>id</i> proceeds as follows:
-  ///
-  /// Let <i>d</i> be the innermost declaration in the enclosing lexical scope whose name is
-  /// <i>id</i>. If no such declaration exists in the lexical scope, let <i>d</i> be the declaration
-  /// of the inherited member named <i>id</i> if it exists.
-  /// * If <i>d</i> is a class or type alias <i>T</i>, the value of <i>e</i> is the unique instance
-  /// of class `Type` reifying <i>T</i>.
-  /// * If <i>d</i> is a type parameter <i>T</i>, then the value of <i>e</i> is the value of the
-  /// actual type argument corresponding to <i>T</i> that was passed to the generative constructor
-  /// that created the current binding of this. We are assured that this is well defined, because if
-  /// we were in a static member the reference to <i>T</i> would be a compile-time error.
-  /// * If <i>d</i> is a library variable then:
-  /// * If <i>d</i> is of one of the forms <i>var v = e<sub>i</sub>;</i>, <i>T v =
-  /// e<sub>i</sub>;</i>, <i>final v = e<sub>i</sub>;</i>, <i>final T v = e<sub>i</sub>;</i>, and no
-  /// value has yet been stored into <i>v</i> then the initializer expression <i>e<sub>i</sub></i> is
-  /// evaluated. If, during the evaluation of <i>e<sub>i</sub></i>, the getter for <i>v</i> is
-  /// referenced, a CyclicInitializationError is thrown. If the evaluation succeeded yielding an
-  /// object <i>o</i>, let <i>r = o</i>, otherwise let <i>r = null</i>. In any case, <i>r</i> is
-  /// stored into <i>v</i>. The value of <i>e</i> is <i>r</i>.
-  /// * If <i>d</i> is of one of the forms <i>const v = e;</i> or <i>const T v = e;</i> the result
-  /// of the getter is the value of the compile time constant <i>e</i>. Otherwise
-  /// * <i>e</i> evaluates to the current binding of <i>id</i>.
-  /// * If <i>d</i> is a local variable or formal parameter then <i>e</i> evaluates to the current
-  /// binding of <i>id</i>.
-  /// * If <i>d</i> is a static method, top level function or local function then <i>e</i>
-  /// evaluates to the function defined by <i>d</i>.
-  /// * If <i>d</i> is the declaration of a static variable or static getter declared in class
-  /// <i>C</i>, then <i>e</i> is equivalent to the getter invocation <i>C.id</i>.
-  /// * If <i>d</i> is the declaration of a top level getter, then <i>e</i> is equivalent to the
-  /// getter invocation <i>id</i>.
-  /// * Otherwise, if <i>e</i> occurs inside a top level or static function (be it function,
-  /// method, getter, or setter) or variable initializer, evaluation of e causes a NoSuchMethodError
-  /// to be thrown.
-  /// * Otherwise <i>e</i> is equivalent to the property extraction <i>this.id</i>.
-  /// </blockquote>
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    Element element = node.staticElement;
-
-    if (element is ExtensionElement) {
-      _setExtensionIdentifierType(node);
-      return;
-    }
-
-    DartType staticType = _dynamicType;
-    if (element is ClassElement) {
-      if (_isExpressionIdentifier(node)) {
-        node.staticType = _nonNullable(_typeProvider.typeType);
-      }
-      return;
-    } else if (element is FunctionTypeAliasElement) {
-      if (node.inDeclarationContext() || node.parent is TypeName) {
-        // no type
-      } else {
-        node.staticType = _nonNullable(_typeProvider.typeType);
-      }
-      return;
-    } else if (element is MethodElement) {
-      staticType = element.type;
-    } else if (element is PropertyAccessorElement) {
-      staticType = _getTypeOfProperty(element);
-    } else if (element is ExecutableElement) {
-      staticType = element.type;
-    } else if (element is TypeParameterElement) {
-      staticType = _nonNullable(_typeProvider.typeType);
-    } else if (element is VariableElement) {
-      staticType = _localVariableTypeProvider.getType(node);
-    } else if (element is PrefixElement) {
-      var parent = node.parent;
-      if (parent is PrefixedIdentifier && parent.prefix == node ||
-          parent is MethodInvocation && parent.target == node) {
-        return;
-      }
-      staticType = _typeProvider.dynamicType;
-    } else if (element is DynamicElementImpl) {
-      staticType = _nonNullable(_typeProvider.typeType);
-    } else {
-      staticType = _dynamicType;
-    }
-    staticType = _inferTearOff(node, node, staticType);
-    recordStaticType(node, staticType);
-  }
-
   /// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
   /// `String`.</blockquote>
   @override
   void visitSimpleStringLiteral(SimpleStringLiteral node) {
-    recordStaticType(node, _nonNullable(_typeProvider.stringType));
+    recordStaticType(node, _typeProvider.stringType);
   }
 
   /// The Dart Language Specification, 12.5: <blockquote>The static type of a string literal is
   /// `String`.</blockquote>
   @override
   void visitStringInterpolation(StringInterpolation node) {
-    recordStaticType(node, _nonNullable(_typeProvider.stringType));
+    recordStaticType(node, _typeProvider.stringType);
   }
 
   @override
@@ -552,7 +308,7 @@
 
   @override
   void visitSymbolLiteral(SymbolLiteral node) {
-    recordStaticType(node, _nonNullable(_typeProvider.symbolType));
+    recordStaticType(node, _typeProvider.symbolType);
   }
 
   /// The Dart Language Specification, 12.10: <blockquote>The static type of `this` is the
@@ -578,10 +334,9 @@
   /// Set the static type of [node] to be the least upper bound of the static
   /// types of subexpressions [expr1] and [expr2].
   void _analyzeLeastUpperBound(
-      Expression node, Expression expr1, Expression expr2,
-      {bool read = false}) {
-    DartType staticType1 = _getExpressionType(expr1, read: read);
-    DartType staticType2 = _getExpressionType(expr2, read: read);
+      Expression node, Expression expr1, Expression expr2) {
+    DartType staticType1 = expr1.staticType;
+    DartType staticType2 = expr2.staticType;
 
     _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
   }
@@ -605,41 +360,6 @@
     recordStaticType(node, staticType);
   }
 
-  /// Gets the definite type of expression, which can be used in cases where
-  /// the most precise type is desired, for example computing the least upper
-  /// bound.
-  ///
-  /// See [getExpressionType] for more information. Without strong mode, this is
-  /// equivalent to [_getStaticType].
-  DartType _getExpressionType(Expression expr, {bool read = false}) =>
-      getExpressionType(expr, _typeSystem, _typeProvider, read: read);
-
-  /// Return the static type of the given [expression].
-  DartType _getStaticType(Expression expression, {bool read = false}) {
-    DartType type;
-    if (read) {
-      type = getReadType(expression);
-    } else {
-      if (expression is SimpleIdentifier && expression.inSetterContext()) {
-        var element = expression.staticElement;
-        if (element is PromotableElement) {
-          // We're writing to the element so ignore promotions.
-          type = element.type;
-        } else {
-          type = expression.staticType;
-        }
-      } else {
-        type = expression.staticType;
-      }
-    }
-    if (type == null) {
-      // TODO(brianwilkerson) Determine the conditions for which the static type
-      // is null.
-      return _dynamicType;
-    }
-    return type;
-  }
-
   /// Return the type represented by the given type [annotation].
   DartType _getType(TypeAnnotation annotation) {
     DartType type = annotation.type;
@@ -651,36 +371,6 @@
     return type;
   }
 
-  /// Return the type that should be recorded for a node that resolved to the given accessor.
-  ///
-  /// @param accessor the accessor that the node resolved to
-  /// @return the type that should be recorded for a node that resolved to the given accessor
-  DartType _getTypeOfProperty(PropertyAccessorElement accessor) {
-    FunctionType functionType = accessor.type;
-    if (functionType == null) {
-      // TODO(brianwilkerson) Report this internal error. This happens when we
-      // are analyzing a reference to a property before we have analyzed the
-      // declaration of the property or when the property does not have a
-      // defined type.
-      return _dynamicType;
-    }
-    if (accessor.isSetter) {
-      List<DartType> parameterTypes = functionType.normalParameterTypes;
-      if (parameterTypes != null && parameterTypes.isNotEmpty) {
-        return parameterTypes[0];
-      }
-      PropertyAccessorElement getter = accessor.variable.getter;
-      if (getter != null) {
-        functionType = getter.type;
-        if (functionType != null) {
-          return functionType.returnType;
-        }
-      }
-      return _dynamicType;
-    }
-    return functionType.returnType;
-  }
-
   /// Given an instance creation of a possibly generic type, infer the type
   /// arguments using the current context type as well as the argument types.
   void _inferInstanceCreationExpression(InstanceCreationExpression node) {
@@ -737,125 +427,4 @@
       constructor.staticElement = constructorElement;
     }
   }
-
-  /// Given a property access [node] with static type [nodeType],
-  /// and [id] is the property name being accessed, infer a type for the
-  /// access itself and its constituent components if the access is to one of the
-  /// methods or getters of the built in 'Object' type, and if the result type is
-  /// a sealed type. Returns true if inference succeeded.
-  bool _inferObjectAccess(
-      Expression node, DartType nodeType, SimpleIdentifier id) {
-    // If we have an access like `libraryPrefix.hashCode` don't infer it.
-    if (node is PrefixedIdentifier &&
-        node.prefix.staticElement is PrefixElement) {
-      return false;
-    }
-    // Search for Object accesses.
-    String name = id.name;
-    PropertyAccessorElement inferredElement =
-        _typeProvider.objectType.element.getGetter(name);
-    if (inferredElement == null || inferredElement.isStatic) {
-      return false;
-    }
-    inferredElement = _resolver.toLegacyElement(inferredElement);
-    DartType inferredType = inferredElement.returnType;
-    if (nodeType != null &&
-        nodeType.isDynamic &&
-        inferredType is InterfaceType &&
-        _typeProvider.nonSubtypableClasses.contains(inferredType.element)) {
-      recordStaticType(id, inferredType);
-      recordStaticType(node, inferredType);
-      return true;
-    }
-    return false;
-  }
-
-  /// Given an uninstantiated generic function type, referenced by the
-  /// [identifier] in the tear-off [expression], try to infer the instantiated
-  /// generic function type from the surrounding context.
-  DartType _inferTearOff(
-    Expression expression,
-    SimpleIdentifier identifier,
-    DartType tearOffType,
-  ) {
-    var context = InferenceContext.getContext(expression);
-    if (context is FunctionType && tearOffType is FunctionType) {
-      var typeArguments = _typeSystem.inferFunctionTypeInstantiation(
-        context,
-        tearOffType,
-        errorReporter: _resolver.errorReporter,
-        errorNode: expression,
-      );
-      (identifier as SimpleIdentifierImpl).tearOffTypeArgumentTypes =
-          typeArguments;
-      if (typeArguments.isNotEmpty) {
-        return tearOffType.instantiate(typeArguments);
-      }
-    }
-    return tearOffType;
-  }
-
-  /// Return `true` if the given [node] is not a type literal.
-  bool _isExpressionIdentifier(Identifier node) {
-    var parent = node.parent;
-    if (node is SimpleIdentifier && node.inDeclarationContext()) {
-      return false;
-    }
-    if (parent is ConstructorDeclaration) {
-      if (parent.name == node || parent.returnType == node) {
-        return false;
-      }
-    }
-    if (parent is ConstructorName ||
-        parent is MethodInvocation ||
-        parent is PrefixedIdentifier && parent.prefix == node ||
-        parent is PropertyAccess ||
-        parent is TypeName) {
-      return false;
-    }
-    return true;
-  }
-
-  /// Return the non-nullable variant of the [type] if NNBD is enabled, otherwise
-  /// return the type itself.
-  DartType _nonNullable(DartType type) {
-    if (_isNonNullableByDefault) {
-      return _typeSystem.promoteToNonNull(type);
-    }
-    return type;
-  }
-
-  void _setExtensionIdentifierType(Identifier node) {
-    if (node is SimpleIdentifier && node.inDeclarationContext()) {
-      return;
-    }
-
-    var parent = node.parent;
-
-    if (parent is PrefixedIdentifier && parent.identifier == node) {
-      node = parent;
-      parent = node.parent;
-    }
-
-    if (parent is CommentReference ||
-        parent is ExtensionOverride && parent.extensionName == node ||
-        parent is MethodInvocation && parent.target == node ||
-        parent is PrefixedIdentifier && parent.prefix == node ||
-        parent is PropertyAccess && parent.target == node) {
-      return;
-    }
-
-    _resolver.errorReporter.reportErrorForNode(
-      CompileTimeErrorCode.EXTENSION_AS_EXPRESSION,
-      node,
-      [node.name],
-    );
-
-    if (node is PrefixedIdentifier) {
-      node.identifier.staticType = _dynamicType;
-      node.staticType = _dynamicType;
-    } else if (node is SimpleIdentifier) {
-      node.staticType = _dynamicType;
-    }
-  }
 }
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index edabdfa..abd18b1 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -5,6 +5,7 @@
 import 'dart:io';
 
 import 'package:analyzer/dart/analysis/declared_variables.dart';
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/constant/value.dart';
@@ -267,6 +268,9 @@
   /// Return the result of evaluating the given expression.
   LinterConstantEvaluationResult evaluateConstant(Expression node);
 
+  /// Return `true` if the [feature] is enabled in the library being linted.
+  bool isEnabled(Feature feature);
+
   /// Resolve the name `id` or `id=` (if [setter] is `true`) an the location
   /// of the [node], according to the "16.35 Lexical Lookup" of the language
   /// specification.
@@ -354,11 +358,8 @@
     );
 
     var visitor = ConstantVisitor(
-      ConstantEvaluationEngine(
-        typeProvider,
-        declaredVariables,
-        typeSystem: typeSystem,
-      ),
+      ConstantEvaluationEngine(declaredVariables),
+      libraryElement,
       errorReporter,
     );
 
@@ -367,6 +368,10 @@
   }
 
   @override
+  bool isEnabled(Feature feature) =>
+      currentUnit.unit.declaredElement.library.featureSet.isEnabled(feature);
+
+  @override
   LinterNameInScopeResolutionResult resolveNameInScope(
       String id, bool setter, AstNode node) {
     Scope scope;
@@ -632,8 +637,7 @@
   }
 
   void reportPubLint(PSNode node) {
-    Source source = createSource(node.span.sourceUrl);
-
+    var source = node.source;
     // Cache error and location info for creating AnalysisErrorInfos
     AnalysisError error = AnalysisError(
         source, node.span.start.offset, node.span.length, lintCode);
diff --git a/pkg/analyzer/lib/src/lint/project.dart b/pkg/analyzer/lib/src/lint/project.dart
index 18a944b..b3cc575 100644
--- a/pkg/analyzer/lib/src/lint/project.dart
+++ b/pkg/analyzer/lib/src/lint/project.dart
@@ -120,7 +120,7 @@
     return false;
   }
 
-  void _calculate() async {
+  Future<void> _calculate() async {
     if (sources == null || sources.isEmpty) {
       return;
     }
diff --git a/pkg/analyzer/lib/src/lint/pub.dart b/pkg/analyzer/lib/src/lint/pub.dart
index ab19e57..9d5f459 100644
--- a/pkg/analyzer/lib/src/lint/pub.dart
+++ b/pkg/analyzer/lib/src/lint/pub.dart
@@ -4,31 +4,38 @@
 
 import 'dart:collection';
 
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:source_span/source_span.dart';
 import 'package:yaml/yaml.dart';
 
-PSEntry _findEntry(YamlMap map, String key) {
+PSEntry _findEntry(YamlMap map, String key, ResourceProvider resourceProvider) {
   PSEntry entry;
   map.nodes.forEach((k, v) {
     if (k is YamlScalar && key == k.toString()) {
-      entry = _processScalar(k, v);
+      entry = _processScalar(k, v, resourceProvider);
     }
   });
   return entry;
 }
 
-PSDependencyList _processDependencies(YamlScalar key, YamlNode v) {
+PSDependencyList _processDependencies(
+    YamlScalar key, YamlNode v, ResourceProvider resourceProvider) {
   if (v is! YamlMap) {
     return null;
   }
   YamlMap depsMap = v;
 
-  _PSDependencyList deps = _PSDependencyList(_PSNode(key));
-  depsMap.nodes.forEach((k, v) => deps.add(_PSDependency(k, v)));
+  _PSDependencyList deps = _PSDependencyList(_PSNode(key, resourceProvider));
+  depsMap.nodes.forEach((k, v) {
+    if (k is YamlScalar) deps.add(_PSDependency(k, v, resourceProvider));
+  });
   return deps;
 }
 
-PSGitRepo _processGitRepo(YamlScalar key, YamlNode v) {
+PSGitRepo _processGitRepo(
+    YamlScalar key, YamlNode v, ResourceProvider resourceProvider) {
   if (v is! YamlMap) {
     return null;
   }
@@ -36,13 +43,14 @@
   // url: git://github.com/munificent/kittens.git
   // ref: some-branch
   _PSGitRepo repo = _PSGitRepo();
-  repo.token = _PSNode(key);
-  repo.ref = _findEntry(hostMap, 'ref');
-  repo.url = _findEntry(hostMap, 'url');
+  repo.token = _PSNode(key, resourceProvider);
+  repo.ref = _findEntry(hostMap, 'ref', resourceProvider);
+  repo.url = _findEntry(hostMap, 'url', resourceProvider);
   return repo;
 }
 
-PSHost _processHost(YamlScalar key, YamlNode v) {
+PSHost _processHost(
+    YamlScalar key, YamlNode v, ResourceProvider resourceProvider) {
   if (v is! YamlMap) {
     return null;
   }
@@ -50,27 +58,31 @@
   // name: transmogrify
   // url: http://your-package-server.com
   _PSHost host = _PSHost();
-  host.token = _PSNode(key);
-  host.name = _findEntry(hostMap, 'name');
-  host.url = _findEntry(hostMap, 'url');
+  host.token = _PSNode(key, resourceProvider);
+  host.name = _findEntry(hostMap, 'name', resourceProvider);
+  host.url = _findEntry(hostMap, 'url', resourceProvider);
   return host;
 }
 
-PSNodeList _processList(YamlScalar key, YamlNode v) {
+PSNodeList _processList(
+    YamlScalar key, YamlNode v, ResourceProvider resourceProvider) {
   if (v is! YamlList) {
     return null;
   }
   YamlList nodeList = v;
 
-  return _PSNodeList(_PSNode(key), nodeList.nodes.map((n) => _PSNode(n)));
+  return _PSNodeList(_PSNode(key, resourceProvider),
+      nodeList.nodes.map((n) => _PSNode(n, resourceProvider)));
 }
 
-PSEntry _processScalar(YamlScalar key, YamlNode value) {
+PSEntry _processScalar(
+    YamlScalar key, YamlNode value, ResourceProvider resourceProvider) {
   if (value is! YamlScalar) {
     return null;
     //WARN?
   }
-  return PSEntry(_PSNode(key), _PSNode(value));
+  return PSEntry(
+      _PSNode(key, resourceProvider), _PSNode(value, resourceProvider));
 }
 
 abstract class PSDependency {
@@ -105,6 +117,7 @@
 }
 
 abstract class PSNode {
+  Source get source;
   SourceSpan get span;
   String get text;
 }
@@ -116,8 +129,10 @@
 }
 
 abstract class Pubspec {
-  factory Pubspec.parse(String source, {Uri sourceUrl}) =>
-      _Pubspec(source, sourceUrl: sourceUrl);
+  factory Pubspec.parse(String source,
+          {Uri sourceUrl, ResourceProvider resourceProvider}) =>
+      _Pubspec(source,
+          sourceUrl: sourceUrl, resourceProvider: resourceProvider);
   PSEntry get author;
   PSNodeList get authors;
   PSDependencyList get dependencies;
@@ -159,25 +174,21 @@
   @override
   PSGitRepo git;
 
-  factory _PSDependency(dynamic k, YamlNode v) {
-    if (k is! YamlScalar) {
-      return null;
-    }
-    YamlScalar key = k;
-
+  factory _PSDependency(
+      YamlScalar key, YamlNode value, ResourceProvider resourceProvider) {
     _PSDependency dep = _PSDependency._();
 
-    dep.name = _PSNode(key);
+    dep.name = _PSNode(key, resourceProvider);
 
-    if (v is YamlScalar) {
+    if (value is YamlScalar) {
       // Simple version
-      dep.version = PSEntry(null, _PSNode(v));
-    } else if (v is YamlMap) {
+      dep.version = PSEntry(null, _PSNode(value, resourceProvider));
+    } else if (value is YamlMap) {
       // hosted:
       //   name: transmogrify
       //   url: http://your-package-server.com
       //   version: '>=0.4.0 <1.0.0'
-      YamlMap details = v;
+      YamlMap details = value;
       details.nodes.forEach((k, v) {
         if (k is! YamlScalar) {
           return;
@@ -185,16 +196,16 @@
         YamlScalar key = k;
         switch (key.toString()) {
           case 'path':
-            dep.path = _processScalar(key, v);
+            dep.path = _processScalar(key, v, resourceProvider);
             break;
           case 'version':
-            dep.version = _processScalar(key, v);
+            dep.version = _processScalar(key, v, resourceProvider);
             break;
           case 'hosted':
-            dep.host = _processHost(key, v);
+            dep.host = _processHost(key, v, resourceProvider);
             break;
           case 'git':
-            dep.git = _processGitRepo(key, v);
+            dep.git = _processGitRepo(key, v, resourceProvider);
             break;
         }
       });
@@ -282,11 +293,18 @@
   @override
   final SourceSpan span;
 
-  _PSNode(YamlNode node)
+  final ResourceProvider resourceProvider;
+
+  _PSNode(YamlNode node, this.resourceProvider)
       : text = node.value?.toString(),
         span = node.span;
 
   @override
+  Source get source => (resourceProvider ?? PhysicalResourceProvider.INSTANCE)
+      .getFile(span.sourceUrl.toFilePath())
+      .createSource(span.sourceUrl);
+
+  @override
   String toString() => '$text';
 }
 
@@ -328,9 +346,9 @@
   @override
   PSDependencyList dependencyOverrides;
 
-  _Pubspec(String src, {Uri sourceUrl}) {
+  _Pubspec(String src, {Uri sourceUrl, ResourceProvider resourceProvider}) {
     try {
-      _parse(src, sourceUrl: sourceUrl);
+      _parse(src, sourceUrl: sourceUrl, resourceProvider: resourceProvider);
     } on Exception {
       // ignore
     }
@@ -388,7 +406,7 @@
     return sb.toString();
   }
 
-  void _parse(String src, {Uri sourceUrl}) {
+  void _parse(String src, {Uri sourceUrl, ResourceProvider resourceProvider}) {
     var yaml = loadYamlNode(src, sourceUrl: sourceUrl);
     if (yaml is! YamlMap) {
       return;
@@ -401,34 +419,34 @@
       YamlScalar key = k;
       switch (key.toString()) {
         case 'author':
-          author = _processScalar(key, v);
+          author = _processScalar(key, v, resourceProvider);
           break;
         case 'authors':
-          authors = _processList(key, v);
+          authors = _processList(key, v, resourceProvider);
           break;
         case 'homepage':
-          homepage = _processScalar(key, v);
+          homepage = _processScalar(key, v, resourceProvider);
           break;
         case 'name':
-          name = _processScalar(key, v);
+          name = _processScalar(key, v, resourceProvider);
           break;
         case 'description':
-          description = _processScalar(key, v);
+          description = _processScalar(key, v, resourceProvider);
           break;
         case 'documentation':
-          documentation = _processScalar(key, v);
+          documentation = _processScalar(key, v, resourceProvider);
           break;
         case 'dependencies':
-          dependencies = _processDependencies(key, v);
+          dependencies = _processDependencies(key, v, resourceProvider);
           break;
         case 'dev_dependencies':
-          devDependencies = _processDependencies(key, v);
+          devDependencies = _processDependencies(key, v, resourceProvider);
           break;
         case 'dependency_overrides':
-          dependencyOverrides = _processDependencies(key, v);
+          dependencyOverrides = _processDependencies(key, v, resourceProvider);
           break;
         case 'version':
-          version = _processScalar(key, v);
+          version = _processScalar(key, v, resourceProvider);
           break;
       }
     });
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index b7ea31c..5227a27 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -704,15 +704,31 @@
 
   _File _getFileByUri(DeclarationsContext context, Uri uri) {
     var file = _uriToFile[uri];
-    if (file == null) {
-      var path = context._resolveUri(uri);
-      if (path != null) {
-        file = _File(this, path, uri);
-        _pathToFile[path] = file;
-        _uriToFile[uri] = file;
-        file.refresh(context);
-      }
+    if (file != null) {
+      return file;
     }
+
+    var path = context._resolveUri(uri);
+    if (path == null) {
+      return null;
+    }
+
+    try {
+      path = _resolveLinks(path);
+    } on FileSystemException {
+      // Not existing file, or the link target.
+    }
+
+    file = _pathToFile[path];
+    if (file != null) {
+      return file;
+    }
+
+    file = _File(this, path, uri);
+    _pathToFile[path] = file;
+    _uriToFile[uri] = file;
+
+    file.refresh(context);
     return file;
   }
 
@@ -791,6 +807,13 @@
       LibraryChange._(changedLibraries, removedLibraries),
     );
   }
+
+  /// Return the [path] with resolved file system links.
+  String _resolveLinks(String path) {
+    var resource = _resourceProvider.getFile(path);
+    resource = resource.resolveSymbolicLinksSync();
+    return resource.path;
+  }
 }
 
 class Libraries {
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 8898a83..cddf91d 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -6702,6 +6702,12 @@
     return _variantField_15 ??= 0;
   }
 
+  @override
+  int get typeParameter_variance {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    return _variantField_15 ??= 0;
+  }
+
   set assignmentExpression_element(int value) {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
     assert(value == null || value >= 0);
@@ -6774,6 +6780,12 @@
     _variantField_15 = value;
   }
 
+  set typeParameter_variance(int value) {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    assert(value == null || value >= 0);
+    _variantField_15 = value;
+  }
+
   @override
   idl.UnlinkedTokenType get assignmentExpression_operator {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
@@ -6804,12 +6816,6 @@
     return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
   }
 
-  @override
-  idl.UnlinkedTokenType get typeParameter_variance {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    return _variantField_28 ??= idl.UnlinkedTokenType.NOTHING;
-  }
-
   set assignmentExpression_operator(idl.UnlinkedTokenType value) {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
     _variantField_28 = value;
@@ -6835,11 +6841,6 @@
     _variantField_28 = value;
   }
 
-  set typeParameter_variance(idl.UnlinkedTokenType value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_28 = value;
-  }
-
   @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
@@ -8619,13 +8620,13 @@
   LinkedNodeBuilder.typeParameter({
     List<LinkedNodeBuilder> annotatedNode_metadata,
     LinkedNodeBuilder typeParameter_bound,
-    idl.UnlinkedTokenType typeParameter_variance,
+    int typeParameter_variance,
     int informativeId,
     LinkedNodeTypeBuilder typeParameter_defaultType,
   })  : _kind = idl.LinkedNodeKind.typeParameter,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = typeParameter_bound,
-        _variantField_28 = typeParameter_variance,
+        _variantField_15 = typeParameter_variance,
         _variantField_36 = informativeId,
         _variantField_23 = typeParameter_defaultType;
 
@@ -10668,12 +10669,10 @@
       }
       signature.addBool(this.typeParameter_bound != null);
       this.typeParameter_bound?.collectApiSignature(signature);
+      signature.addInt(this.typeParameter_variance ?? 0);
       signature.addInt(this.flags ?? 0);
       signature.addBool(this.typeParameter_defaultType != null);
       this.typeParameter_defaultType?.collectApiSignature(signature);
-      signature.addInt(this.typeParameter_variance == null
-          ? 0
-          : this.typeParameter_variance.index);
       signature.addString(this.name ?? '');
     } else if (kind == idl.LinkedNodeKind.typeParameterList) {
       signature.addInt(this.kind == null ? 0 : this.kind.index);
@@ -12712,6 +12711,14 @@
   }
 
   @override
+  int get typeParameter_variance {
+    assert(kind == idl.LinkedNodeKind.typeParameter);
+    _variantField_15 ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 15, 0);
+    return _variantField_15;
+  }
+
+  @override
   idl.UnlinkedTokenType get assignmentExpression_operator {
     assert(kind == idl.LinkedNodeKind.assignmentExpression);
     _variantField_28 ??= const _UnlinkedTokenTypeReader()
@@ -12752,14 +12759,6 @@
   }
 
   @override
-  idl.UnlinkedTokenType get typeParameter_variance {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
-    _variantField_28 ??= const _UnlinkedTokenTypeReader()
-        .vTableGet(_bc, _bcOffset, 28, idl.UnlinkedTokenType.NOTHING);
-    return _variantField_28;
-  }
-
-  @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 ??=
@@ -14797,9 +14796,8 @@
       if (typeParameter_bound != null) {
         _result["typeParameter_bound"] = typeParameter_bound.toJson();
       }
-      if (typeParameter_variance != idl.UnlinkedTokenType.NOTHING) {
-        _result["typeParameter_variance"] =
-            typeParameter_variance.toString().split('.')[1];
+      if (typeParameter_variance != 0) {
+        _result["typeParameter_variance"] = typeParameter_variance;
       }
       if (informativeId != 0) {
         _result["informativeId"] = informativeId;
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index c89630c..4b84de9 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -1557,8 +1557,8 @@
   @VariantId(23, variant: LinkedNodeKind.typeParameter)
   LinkedNodeType get typeParameter_defaultType;
 
-  @VariantId(28, variant: LinkedNodeKind.typeParameter)
-  UnlinkedTokenType get typeParameter_variance;
+  @VariantId(15, variant: LinkedNodeKind.typeParameter)
+  int get typeParameter_variance;
 
   @VariantId(2, variant: LinkedNodeKind.typeParameterList)
   List<LinkedNode> get typeParameterList_typeParameters;
diff --git a/pkg/analyzer/lib/src/summary/summary_sdk.dart b/pkg/analyzer/lib/src/summary/summary_sdk.dart
index 80cd239..809db0f 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -3,11 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/file_system/file_system.dart' show ResourceProvider;
-import 'package:analyzer/src/context/context.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart'
-    show DartUriResolver, Source, SourceFactory;
+import 'package:analyzer/src/generated/source.dart' show Source;
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
 import 'package:pub_semver/pub_semver.dart';
@@ -22,9 +19,6 @@
   PackageBundle _bundle;
   ResourceProvider resourceProvider;
 
-  /// The [AnalysisContext] which is used for all of the sources in this sdk.
-  SdkAnalysisContext _analysisContext;
-
   SummaryBasedDartSdk(String summaryPath, bool _, {this.resourceProvider}) {
     _dataStore = SummaryDataStore(<String>[summaryPath],
         resourceProvider: resourceProvider);
@@ -49,16 +43,6 @@
   PackageBundle get bundle => _bundle;
 
   @override
-  AnalysisContext get context {
-    if (_analysisContext == null) {
-      var analysisOptions = AnalysisOptionsImpl();
-      var factory = SourceFactory([DartUriResolver(this)]);
-      _analysisContext = SdkAnalysisContext(analysisOptions, factory);
-    }
-    return _analysisContext;
-  }
-
-  @override
   Version get languageVersion {
     var version = _bundle.sdk.languageVersion;
     return Version(version.major, version.minor, 0);
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 65a5737..4df499f 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -1598,12 +1599,13 @@
     // TODO (kallentu) : Clean up AstFactoryImpl casting once variance is
     // added to the interface.
     var node = (astFactory as AstFactoryImpl).typeParameter2(
-        comment: _readDocumentationComment(data),
-        metadata: _readNodeListLazy(data.annotatedNode_metadata),
-        name: _declaredIdentifier(data),
-        extendsKeyword: _Tokens.EXTENDS,
-        bound: _readNodeLazy(data.typeParameter_bound),
-        varianceKeyword: _varianceKeyword(data));
+      comment: _readDocumentationComment(data),
+      metadata: _readNodeListLazy(data.annotatedNode_metadata),
+      name: _declaredIdentifier(data),
+      extendsKeyword: _Tokens.EXTENDS,
+      bound: _readNodeLazy(data.typeParameter_bound),
+    );
+    LazyAst.setVariance(node, _decodeVariance(data.typeParameter_variance));
     LazyTypeParameter.setData(node, data);
     return node;
   }
@@ -1959,11 +1961,20 @@
     return _unitContext.readType(data);
   }
 
-  Token _varianceKeyword(LinkedNode data) {
-    if (data.typeParameter_variance != UnlinkedTokenType.NOTHING) {
-      return _Tokens.fromType(data.typeParameter_variance);
+  static Variance _decodeVariance(int encoding) {
+    if (encoding == 0) {
+      return null;
+    } else if (encoding == 1) {
+      return Variance.unrelated;
+    } else if (encoding == 2) {
+      return Variance.covariant;
+    } else if (encoding == 3) {
+      return Variance.contravariant;
+    } else if (encoding == 4) {
+      return Variance.invariant;
+    } else {
+      throw UnimplementedError('encoding: $encoding');
     }
-    return null;
   }
 
   static ParameterKind _toParameterKind(LinkedNodeFormalParameterKind kind) {
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index e3a4384..0035dd8 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/ast_binary_flags.dart';
@@ -1377,7 +1378,7 @@
     var builder = LinkedNodeBuilder.typeParameter(
       typeParameter_bound: node.bound?.accept(this),
       typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
-      typeParameter_variance: _getVarianceToken(node),
+      typeParameter_variance: _encodeVariance(LazyAst.getVariance(node)),
       informativeId: getInformativeId(node),
     );
     builder.name = node.name.name;
@@ -1508,15 +1509,6 @@
     return _ElementComponents(elementIndex, null);
   }
 
-  UnlinkedTokenType _getVarianceToken(TypeParameter parameter) {
-    // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
-    // added to the interface.
-    var parameterImpl = parameter as TypeParameterImpl;
-    return parameterImpl.varianceKeyword != null
-        ? TokensWriter.astToBinaryTokenType(parameterImpl.varianceKeyword.type)
-        : null;
-  }
-
   int _indexOfElement(Element element) {
     return _linkingContext.indexOfElement(element);
   }
@@ -1712,6 +1704,22 @@
     return _linkingContext.writeType(type);
   }
 
+  static int _encodeVariance(Variance variance) {
+    if (variance == null) {
+      return 0;
+    } else if (variance == Variance.unrelated) {
+      return 1;
+    } else if (variance == Variance.covariant) {
+      return 2;
+    } else if (variance == Variance.contravariant) {
+      return 3;
+    } else if (variance == Variance.invariant) {
+      return 4;
+    } else {
+      throw UnimplementedError('$variance');
+    }
+  }
+
   /// Return `true` if the expression might be successfully serialized.
   ///
   /// This does not mean that the expression is constant, it just means that
diff --git a/pkg/analyzer/lib/src/summary2/core_types.dart b/pkg/analyzer/lib/src/summary2/core_types.dart
deleted file mode 100644
index 289ea8e..0000000
--- a/pkg/analyzer/lib/src/summary2/core_types.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
-
-class CoreTypes {
-  final LinkedElementFactory _elementFactory;
-
-  LibraryElement _coreLibrary;
-  ClassElement _objectClass;
-
-  CoreTypes(this._elementFactory);
-
-  LibraryElement get coreLibrary {
-    return _coreLibrary ??= _elementFactory.libraryOfUri('dart:core');
-  }
-
-  ClassElement get objectClass {
-    return _objectClass ??= _getCoreClass('Object');
-  }
-
-  ClassElement _getCoreClass(String name) {
-    return coreLibrary.getType(name);
-  }
-}
diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
index ce0b852..d06952b 100644
--- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart
@@ -6,13 +6,15 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/element/replacement_visitor.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_algebra.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
 import 'package:analyzer/src/summary2/type_builder.dart';
 import 'package:analyzer/src/util/graph.dart';
+import 'package:meta/meta.dart';
 
 class DefaultTypesBuilder {
   void build(List<AstNode> nodes) {
@@ -152,12 +154,14 @@
     if (parameterList == null) return;
 
     var typeProvider = declarationElement.library.typeProvider;
-    var dynamicType = typeProvider.dynamicType;
-    var nullType = typeProvider.nullType;
+    var dynamicType = DynamicTypeImpl.instance;
+    var bottomType = declarationElement.library.isNonNullableByDefault
+        ? NeverTypeImpl.instance
+        : typeProvider.nullType;
 
     var nodes = parameterList.typeParameters;
     var length = nodes.length;
-    var elements = List<TypeParameterElement>(length);
+    var elements = List<TypeParameterElementImpl>(length);
     var bounds = List<DartType>(length);
     for (int i = 0; i < length; i++) {
       var node = nodes[i];
@@ -173,15 +177,17 @@
       for (var i in component) {
         var element = elements[i];
         dynamicSubstitution[element] = dynamicType;
-        nullSubstitution[element] = nullType;
+        nullSubstitution[element] = bottomType;
       }
 
-      var substitution = Substitution.fromUpperAndLowerBounds(
-        dynamicSubstitution,
-        nullSubstitution,
-      );
       for (var i in component) {
-        bounds[i] = substitution.substituteType(bounds[i]);
+        var variable = elements[i];
+        var visitor = _UpperLowerReplacementVisitor(
+          upper: dynamicSubstitution,
+          lower: nullSubstitution,
+          variance: variable.variance,
+        );
+        bounds[i] = visitor.run(bounds[i]);
       }
     }
 
@@ -190,14 +196,16 @@
       var nullSubstitution = <TypeParameterElement, DartType>{};
       var element = elements[i];
       thisSubstitution[element] = bounds[i];
-      nullSubstitution[element] = nullType;
+      nullSubstitution[element] = bottomType;
 
-      var substitution = Substitution.fromUpperAndLowerBounds(
-        thisSubstitution,
-        nullSubstitution,
-      );
       for (var j = 0; j < length; j++) {
-        bounds[j] = substitution.substituteType(bounds[j]);
+        var variable = elements[j];
+        var visitor = _UpperLowerReplacementVisitor(
+          upper: thisSubstitution,
+          lower: nullSubstitution,
+          variance: variable.variance,
+        );
+        bounds[j] = visitor.run(bounds[j]);
       }
     }
 
@@ -355,3 +363,55 @@
     }
   }
 }
+
+class _UpperLowerReplacementVisitor extends ReplacementVisitor {
+  final Map<TypeParameterElement, DartType> _upper;
+  final Map<TypeParameterElement, DartType> _lower;
+  Variance _variance;
+
+  _UpperLowerReplacementVisitor({
+    @required Map<TypeParameterElement, DartType> upper,
+    @required Map<TypeParameterElement, DartType> lower,
+    @required Variance variance,
+  })  : _upper = upper,
+        _lower = lower,
+        _variance = variance;
+
+  @override
+  void changeVariance() {
+    if (_variance == Variance.covariant) {
+      _variance = Variance.contravariant;
+    } else if (_variance == Variance.contravariant) {
+      _variance = Variance.covariant;
+    }
+  }
+
+  DartType run(DartType type) {
+    return type.accept(this) ?? type;
+  }
+
+  @override
+  DartType visitTypeArgument(
+    TypeParameterElement parameter,
+    DartType argument,
+  ) {
+    var savedVariance = _variance;
+    try {
+      _variance = _variance.combine(
+        (parameter as TypeParameterElementImpl).variance,
+      );
+      return super.visitTypeArgument(parameter, argument);
+    } finally {
+      _variance = savedVariance;
+    }
+  }
+
+  @override
+  DartType visitTypeParameterType(TypeParameterType type) {
+    if (_variance == Variance.contravariant) {
+      return _lower[type.element];
+    } else {
+      return _upper[type.element];
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index 74cf1fd..a4c8987 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -53,7 +53,7 @@
   ) {
     return FunctionTypeBuilder(
       _getTypeParameters(node.typeParameters),
-      _getParameters(isNNBD, node.parameters),
+      getParameters(isNNBD, node.parameters),
       _getNodeType(node.returnType),
       nullabilitySuffix,
       node: node,
@@ -138,6 +138,20 @@
     );
   }
 
+  /// [isNNBD] indicates whether the containing library is opted into NNBD.
+  static List<ParameterElementImpl> getParameters(
+    bool isNNBD,
+    FormalParameterList node,
+  ) {
+    return node.parameters.asImpl.map((parameter) {
+      return ParameterElementImpl.synthetic(
+        parameter.identifier?.name ?? '',
+        _getParameterType(isNNBD, parameter),
+        parameter.kind,
+      );
+    }).toList();
+  }
+
   /// If the [type] is a [TypeBuilder], build it; otherwise return as is.
   static DartType _buildType(DartType type) {
     if (type is TypeBuilder) {
@@ -156,20 +170,6 @@
     }
   }
 
-  /// [isNNBD] indicates whether the containing library is opted into NNBD.
-  static List<ParameterElementImpl> _getParameters(
-    bool isNNBD,
-    FormalParameterList node,
-  ) {
-    return node.parameters.asImpl.map((parameter) {
-      return ParameterElementImpl.synthetic(
-        parameter.identifier?.name ?? '',
-        _getParameterType(isNNBD, parameter),
-        parameter.kind,
-      );
-    }).toList();
-  }
-
   /// Return the type of the [node] as is, possibly a [TypeBuilder].
   ///
   /// [isNNBD] indicates whether the containing library is opted into NNBD.
@@ -190,7 +190,7 @@
 
       return FunctionTypeBuilder(
         _getTypeParameters(node.typeParameters),
-        _getParameters(isNNBD, node.parameters),
+        getParameters(isNNBD, node.parameters),
         _getNodeType(node.returnType),
         nullabilitySuffix,
       );
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 43008b7..dea4fa9 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -6,6 +6,7 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/ast_binary_flags.dart';
@@ -16,7 +17,7 @@
 /// Accessor for reading AST lazily, or read data that is stored in IDL, but
 /// cannot be stored in AST, like inferred types.
 class LazyAst {
-  static const _defaultTypedKey = 'lazyAst_defaultType';
+  static const _defaultTypeKey = 'lazyAst_defaultType';
   static const _genericFunctionTypeIdKey = 'lazyAst_genericFunctionTypeId';
   static const _hasOverrideInferenceKey = 'lazyAst_hasOverrideInference';
   static const _inheritsCovariantKey = 'lazyAst_isCovariant';
@@ -27,13 +28,14 @@
   static const _returnTypeKey = 'lazyAst_returnType';
   static const _typeInferenceErrorKey = 'lazyAst_typeInferenceError';
   static const _typeKey = 'lazyAst_type';
+  static const _varianceKey = 'lazyAst_variance';
 
   final LinkedNode data;
 
   LazyAst(this.data);
 
   static DartType getDefaultType(TypeParameter node) {
-    return node.getProperty(_defaultTypedKey);
+    return node.getProperty(_defaultTypeKey);
   }
 
   static int getGenericFunctionTypeId(GenericFunctionType node) {
@@ -60,6 +62,10 @@
     return node.getProperty(_typeInferenceErrorKey);
   }
 
+  static Variance getVariance(TypeParameter node) {
+    return node.getProperty(_varianceKey);
+  }
+
   static bool hasOperatorEqualParameterTypeFromObject(AstNode node) {
     return node.getProperty(_isOperatorEqualParameterTypeFromObjectKey) ??
         false;
@@ -74,7 +80,7 @@
   }
 
   static void setDefaultType(TypeParameter node, DartType type) {
-    node.setProperty(_defaultTypedKey, type);
+    node.setProperty(_defaultTypeKey, type);
   }
 
   static void setGenericFunctionTypeId(GenericFunctionType node, int id) {
@@ -113,6 +119,10 @@
       AstNode node, TopLevelInferenceError error) {
     node.setProperty(_typeInferenceErrorKey, error);
   }
+
+  static void setVariance(TypeParameter node, Variance variance) {
+    return node.setProperty(_varianceKey, variance);
+  }
 }
 
 class LazyClassDeclaration {
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 3f34f0d..281f0dc 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -19,6 +19,7 @@
 import 'package:analyzer/src/summary2/top_level_inference.dart';
 import 'package:analyzer/src/summary2/type_alias.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
+import 'package:analyzer/src/summary2/variance_builder.dart';
 
 var timerLinkingLinkingBundle = Stopwatch();
 var timerLinkingRemoveBundle = Stopwatch();
@@ -227,6 +228,7 @@
     for (var library in builders.values) {
       library.resolveTypes(nodesToBuildType);
     }
+    VarianceBuilder().perform(this);
     computeSimplyBounded(bundleContext, builders.values);
     TypesBuilder().build(nodesToBuildType);
   }
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index caeb168..b074a62 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/summary/idl.dart';
-import 'package:analyzer/src/summary2/core_types.dart';
 import 'package:analyzer/src/summary2/lazy_ast.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
@@ -22,8 +21,6 @@
   final Reference rootReference;
   final Map<String, LinkedLibraryContext> libraryMap = {};
 
-  CoreTypes _coreTypes;
-
   LinkedElementFactory(
     this.analysisContext,
     this.analysisSession,
@@ -31,13 +28,7 @@
   ) {
     ArgumentError.checkNotNull(analysisContext, 'analysisContext');
     ArgumentError.checkNotNull(analysisSession, 'analysisSession');
-    var dartCoreRef = rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-  }
-
-  CoreTypes get coreTypes {
-    return _coreTypes ??= CoreTypes(this);
+    declareDartCoreDynamicNever();
   }
 
   Reference get dynamicRef {
@@ -104,6 +95,12 @@
     }
   }
 
+  void declareDartCoreDynamicNever() {
+    var dartCoreRef = rootReference.getChild('dart:core');
+    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+  }
+
   Element elementOfReference(Reference reference) {
     if (reference.element != null) {
       return reference.element;
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 1a6410a..24a749f 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/standard_ast_factory.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -13,6 +12,7 @@
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -683,10 +683,8 @@
     }
   }
 
-  Token getTypeParameterVariance(TypeParameter node) {
-    // TODO (kallentu) : Clean up TypeParameterImpl casting once variance is
-    // added to the interface.
-    return (node as TypeParameterImpl).varianceKeyword;
+  Variance getTypeParameterVariance(TypeParameter node) {
+    return LazyAst.getVariance(node);
   }
 
   WithClause getWithClause(AstNode node) {
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index 013ec70..2844249 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/nullability_suffix.dart';
@@ -67,11 +66,11 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@class').getChild(name);
-
-    ClassElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as ClassElementImpl;
+    reference = element.reference;
+    element.accessors; // create elements
+    element.constructors; // create elements
+    element.methods; // create elements
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -104,11 +103,8 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@class').getChild(name);
-
-    ClassElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as ClassElementImpl;
+    reference = element.reference;
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -135,15 +131,9 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name?.name ?? '';
-    reference = reference.getChild('@constructor').getChild(name);
-
-    var element = ConstructorElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
-    (node as ConstructorDeclarationImpl).declaredElement = element;
+    var element = node.declaredElement as ConstructorElementImpl;
+    reference = element.reference;
+    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -181,11 +171,8 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var refName = LazyExtensionDeclaration.get(node).refName;
-    reference = reference.getChild('@extension').getChild(refName);
-
-    ExtensionElementImpl element = reference.element;
-    node.name?.staticElement = element;
+    var element = node.declaredElement as ExtensionElementImpl;
+    reference = element.reference;
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -219,16 +206,9 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.identifier.name;
-    reference = reference.getChild('@parameter').getChild(name);
-    reference.node = node;
-
-    var element = FieldFormalParameterElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
-    node.identifier.staticElement = element;
+    var element = node.declaredElement as FieldFormalParameterElementImpl;
+    reference = element.reference;
+    element.parameters; // create elements
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -252,19 +232,9 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var container = '@function';
-    var propertyKeyword = node.propertyKeyword?.keyword;
-    if (propertyKeyword == Keyword.GET) {
-      container = '@getter';
-    } else if (propertyKeyword == Keyword.SET) {
-      container = '@setter';
-    }
-
-    var name = node.name.name;
-    reference = reference.getChild(container).getChild(name);
-
-    ExecutableElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as ExecutableElementImpl;
+    reference = element.reference;
+    element.parameters; // create elements
 
     _createTypeParameterElements(node.functionExpression.typeParameters);
     scope = TypeParameterScope(outerScope, element.typeParameters);
@@ -289,11 +259,8 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@typeAlias').getChild(name);
-
-    GenericTypeAliasElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as GenericTypeAliasElementImpl;
+    reference = element.reference;
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element.typeParameters);
@@ -301,8 +268,9 @@
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
 
-    reference = reference.getChild('@function');
-    reference.element = element;
+    var functionElement = element.function;
+    reference = functionElement.reference;
+    functionElement.parameters; // create elements
     node.parameters.accept(this);
 
     nodesToBuildType.addDeclaration(node);
@@ -316,16 +284,9 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.identifier.name;
-    reference = reference.getChild('@parameter').getChild(name);
-    reference.node = node;
-
-    var element = ParameterElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
-    node.identifier.staticElement = element;
+    var element = node.declaredElement as ParameterElementImpl;
+    reference = element.reference;
+    element.parameters; // create elements
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -356,6 +317,7 @@
       node,
     );
     (node as GenericFunctionTypeImpl).declaredElement = element;
+    element.parameters; // create elements
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element.typeParameters);
@@ -378,11 +340,8 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@typeAlias').getChild(name);
-
-    GenericTypeAliasElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as GenericTypeAliasElementImpl;
+    reference = element.reference;
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(outerScope, element.typeParameters);
@@ -405,23 +364,10 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var container = '@method';
-    var propertyKeyword = node.propertyKeyword?.keyword;
-    if (propertyKeyword == Keyword.GET) {
-      container = '@getter';
-    } else if (propertyKeyword == Keyword.SET) {
-      container = '@setter';
-    }
+    var element = node.declaredElement as ExecutableElementImpl;
+    reference = element.reference;
+    element.parameters; // create elements
 
-    var name = node.name.name;
-    reference = reference.getChild(container).getChild(name);
-
-    var element = MethodElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
-    node.name.staticElement = element;
     _createTypeParameterElements(node.typeParameters);
 
     scope = TypeParameterScope(scope, element.typeParameters);
@@ -441,11 +387,11 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = node.name.name;
-    reference = reference.getChild('@mixin').getChild(name);
-
-    MixinElementImpl element = reference.element;
-    node.name.staticElement = element;
+    var element = node.declaredElement as MixinElementImpl;
+    reference = element.reference;
+    element.accessors; // create elements
+    element.constructors; // create elements
+    element.methods; // create elements
 
     _createTypeParameterElements(node.typeParameters);
     scope = TypeParameterScope(scope, element.typeParameters);
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index 0918c70..6639055 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -9,7 +9,6 @@
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/summary/format.dart';
@@ -450,7 +449,7 @@
     }
 
     if (_typeSystem.isNonNullableByDefault) {
-      return nonNullifyType(_typeSystem, type);
+      return _typeSystem.nonNullifyLegacy(type);
     } else {
       if (type.isBottom) {
         return DynamicTypeImpl.instance;
diff --git a/pkg/analyzer/lib/src/summary2/variance_builder.dart b/pkg/analyzer/lib/src/summary2/variance_builder.dart
new file mode 100644
index 0000000..704bd83
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/variance_builder.dart
@@ -0,0 +1,245 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
+import 'package:analyzer/src/summary2/function_type_builder.dart';
+import 'package:analyzer/src/summary2/lazy_ast.dart';
+import 'package:analyzer/src/summary2/link.dart';
+import 'package:analyzer/src/summary2/named_type_builder.dart';
+import 'package:meta/meta.dart';
+
+class VarianceBuilder {
+  final Set<TypeAlias> _pending = Set.identity();
+  final Set<TypeAlias> _visit = Set.identity();
+
+  void perform(Linker linker) {
+    for (var builder in linker.builders.values) {
+      for (var unitContext in builder.context.units) {
+        for (var node in unitContext.unit.declarations) {
+          if (node is FunctionTypeAlias || node is GenericTypeAlias) {
+            _pending.add(node);
+          }
+        }
+      }
+    }
+
+    for (var builder in linker.builders.values) {
+      for (var unitContext in builder.context.units) {
+        for (var node in unitContext.unit.declarations) {
+          if (node is ClassTypeAlias) {
+            _typeParameters(node.typeParameters);
+          } else if (node is ClassDeclaration) {
+            _typeParameters(node.typeParameters);
+          } else if (node is FunctionTypeAlias) {
+            _functionTypeAlias(node);
+          } else if (node is GenericTypeAlias) {
+            _genericTypeAlias(node);
+          } else if (node is MixinDeclaration) {
+            _typeParameters(node.typeParameters);
+          }
+        }
+      }
+    }
+  }
+
+  Variance _compute(TypeParameterElement variable, DartType type) {
+    if (type is TypeParameterType) {
+      var element = type.element;
+      if (element is TypeParameterElement) {
+        if (element == variable) {
+          return Variance.covariant;
+        } else {
+          return Variance.unrelated;
+        }
+      }
+    } else if (type is NamedTypeBuilder) {
+      var element = type.element;
+      if (element is ClassElement) {
+        var result = Variance.unrelated;
+        if (type.arguments.isNotEmpty) {
+          var parameters = element.typeParameters;
+          for (int i = 0; i < type.arguments.length; ++i) {
+            var parameter = parameters[i] as TypeParameterElementImpl;
+            result = result.meet(
+              parameter.variance.combine(
+                _compute(variable, type.arguments[i]),
+              ),
+            );
+          }
+        }
+        return result;
+      } else if (element is GenericTypeAliasElementImpl) {
+        _functionTypeAliasElement(element);
+
+        var result = Variance.unrelated;
+
+        if (type.arguments.isNotEmpty) {
+          var parameters = element.typeParameters;
+          for (var i = 0; i < type.arguments.length; ++i) {
+            var parameter = parameters[i] as TypeParameterElementImpl;
+            var parameterVariance = parameter.variance;
+            result = result.meet(
+              parameterVariance.combine(
+                _compute(variable, type.arguments[i]),
+              ),
+            );
+          }
+        }
+        return result;
+      }
+    } else if (type is FunctionTypeBuilder) {
+      return _computeFunctionType(
+        variable,
+        returnType: type.returnType,
+        typeFormals: type.typeFormals,
+        parameters: type.parameters,
+      );
+    }
+    return Variance.unrelated;
+  }
+
+  Variance _computeFunctionType(
+    TypeParameterElement variable, {
+    @required DartType returnType,
+    @required List<TypeParameterElement> typeFormals,
+    @required List<ParameterElement> parameters,
+  }) {
+    var result = Variance.unrelated;
+
+    if (result != null) {
+      result = result.meet(
+        _compute(variable, returnType),
+      );
+    }
+
+    // If [variable] is referenced in a bound at all, it makes the
+    // variance of [variable] in the entire type invariant.
+    if (typeFormals != null) {
+      for (var parameter in typeFormals) {
+        var bound = parameter.bound;
+        if (bound != null && _compute(variable, bound) != Variance.unrelated) {
+          result = Variance.invariant;
+        }
+      }
+    }
+
+    for (var parameter in parameters) {
+      result = result.meet(
+        Variance.contravariant.combine(
+          _compute(variable, parameter.type),
+        ),
+      );
+    }
+
+    return result;
+  }
+
+  void _functionTypeAlias(FunctionTypeAlias node) {
+    var parameterList = node.typeParameters;
+    if (parameterList == null) {
+      return;
+    }
+
+    // Recursion detected, recover.
+    if (_visit.contains(node)) {
+      for (var parameter in parameterList.typeParameters) {
+        LazyAst.setVariance(parameter, Variance.covariant);
+      }
+      return;
+    }
+
+    // Not being linked, or already linked.
+    if (!_pending.remove(node)) {
+      return;
+    }
+
+    _visit.add(node);
+    try {
+      for (var parameter in parameterList.typeParameters) {
+        var variance = _computeFunctionType(
+          parameter.declaredElement,
+          returnType: node.returnType?.type,
+          typeFormals: null,
+          parameters: FunctionTypeBuilder.getParameters(
+            false,
+            node.parameters,
+          ),
+        );
+        LazyAst.setVariance(parameter, variance);
+      }
+    } finally {
+      _visit.remove(node);
+    }
+  }
+
+  void _functionTypeAliasElement(GenericTypeAliasElementImpl element) {
+    var node = element.linkedNode;
+    if (node is GenericTypeAlias) {
+      _genericTypeAlias(node);
+    } else if (node is FunctionTypeAlias) {
+      _functionTypeAlias(node);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+
+  void _genericTypeAlias(GenericTypeAlias node) {
+    var parameterList = node.typeParameters;
+    if (parameterList == null) {
+      return;
+    }
+
+    // Recursion detected, recover.
+    if (_visit.contains(node)) {
+      for (var parameter in parameterList.typeParameters) {
+        LazyAst.setVariance(parameter, Variance.covariant);
+      }
+      return;
+    }
+
+    // Not being linked, or already linked.
+    if (!_pending.remove(node)) {
+      return;
+    }
+
+    var type = node.functionType?.type;
+
+    // Not a function type, recover.
+    if (type == null) {
+      for (var parameter in parameterList.typeParameters) {
+        LazyAst.setVariance(parameter, Variance.covariant);
+      }
+    }
+
+    _visit.add(node);
+    try {
+      for (var parameter in parameterList.typeParameters) {
+        var variance = _compute(parameter.declaredElement, type);
+        LazyAst.setVariance(parameter, variance);
+      }
+    } finally {
+      _visit.remove(node);
+    }
+  }
+
+  void _typeParameters(TypeParameterList parameterList) {
+    if (parameterList == null) {
+      return;
+    }
+
+    for (var parameter in parameterList.typeParameters) {
+      var parameterImpl = parameter as TypeParameterImpl;
+      var varianceKeyword = parameterImpl.varianceKeyword;
+      if (varianceKeyword != null) {
+        var variance = Variance.fromKeywordString(varianceKeyword.lexeme);
+        LazyAst.setVariance(parameter, variance);
+      }
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index bbef02e..0aaf16d 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -48,7 +48,7 @@
         ];
         errors.add(AnalysisError(
             initialSource,
-            initialIncludeSpan.start.column + 1,
+            initialIncludeSpan.start.offset,
             initialIncludeSpan.length,
             AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING,
             args));
@@ -68,7 +68,7 @@
     if (includedSource == null || !includedSource.exists()) {
       errors.add(AnalysisError(
           initialSource,
-          initialIncludeSpan.start.column + 1,
+          initialIncludeSpan.start.offset,
           initialIncludeSpan.length,
           AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND,
           [includeUri, source.fullName]));
@@ -89,7 +89,7 @@
       // on the include directive located in the initial options file.
       errors.add(AnalysisError(
           initialSource,
-          initialIncludeSpan.start.column + 1,
+          initialIncludeSpan.start.offset,
           initialIncludeSpan.length,
           AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR,
           args));
@@ -101,7 +101,7 @@
     validate(source, options);
   } on OptionsFormatException catch (e) {
     SourceSpan span = e.span;
-    errors.add(AnalysisError(source, span.start.column + 1, span.length,
+    errors.add(AnalysisError(source, span.start.offset, span.length,
         AnalysisOptionsErrorCode.PARSE_ERROR, [e.message]));
   }
   return errors;
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 4e67d44..a744bab4 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -20,64 +20,7 @@
 import 'package:analyzer/src/error/codes.dart'
     show CompileTimeErrorCode, StrongModeCode;
 import 'package:analyzer/src/summary/idl.dart';
-
-/// Given an [expression] and a corresponding [typeSystem] and [typeProvider],
-/// gets the known static type of the expression.
-DartType getExpressionType(
-    Expression expression, TypeSystemImpl typeSystem, TypeProvider typeProvider,
-    {bool read = false}) {
-  DartType type;
-  if (read) {
-    type = getReadType(expression);
-  } else {
-    type = expression.staticType;
-  }
-  type ??= DynamicTypeImpl.instance;
-  return type;
-}
-
-DartType getReadType(Expression expression) {
-  if (expression is IndexExpression) {
-    var aux = expression.auxiliaryElements;
-    if (aux != null) {
-      var staticElement = aux.staticElement;
-      return staticElement == null
-          ? DynamicTypeImpl.instance
-          : staticElement.returnType;
-    }
-    return expression.staticType;
-  }
-  {
-    Element setter;
-    if (expression is PrefixedIdentifier) {
-      setter = expression.staticElement;
-    } else if (expression is PropertyAccess) {
-      setter = expression.propertyName.staticElement;
-    } else if (expression is SimpleIdentifier) {
-      setter = expression.staticElement;
-    }
-    if (setter is PropertyAccessorElement && setter.isSetter) {
-      var getter = setter.variable.getter;
-      if (getter != null) {
-        var type = getter.returnType;
-        // The return type might be `null` when we perform top-level inference.
-        // The first stage collects references to build the dependency graph.
-        // TODO(scheglov) Maybe preliminary set types to `dynamic`?
-        return type ?? DynamicTypeImpl.instance;
-      }
-    }
-  }
-  if (expression is SimpleIdentifier) {
-    var aux = expression.auxiliaryElements;
-    if (aux != null) {
-      var staticElement = aux.staticElement;
-      return staticElement == null
-          ? DynamicTypeImpl.instance
-          : staticElement.returnType;
-    }
-  }
-  return expression.staticType;
-}
+import 'package:meta/meta.dart';
 
 DartType _elementType(Element e) {
   if (e == null) {
@@ -148,8 +91,8 @@
     }
   }
 
-  void checkAssignment(Expression expr, DartType type) {
-    checkForCast(expr, type);
+  void checkAssignment(Expression expr, DartType to) {
+    checkForCast(expr, from: expr.staticType, to: to);
   }
 
   /// Analyzer checks boolean conversions, but we need to check too, because
@@ -176,20 +119,26 @@
 
       var exprType = element.expression.staticType;
       var asIterableType = exprType.asInstanceOf(typeProvider.iterableElement);
-      var elementType =
-          asIterableType == null ? null : asIterableType.typeArguments[0];
-      // Items in the spread will then potentially be downcast to the expected
-      // type.
-      _checkImplicitCast(element.expression, expectedType,
-          from: elementType, forSpread: true);
+
+      if (asIterableType != null) {
+        var elementType = asIterableType.typeArguments[0];
+        // Items in the spread will then potentially be downcast to the expected
+        // type.
+        _checkImplicitCast(element.expression,
+            to: expectedType, from: elementType, forSpread: true);
+      }
     }
   }
 
-  void checkForCast(Expression expr, DartType type) {
+  void checkForCast(
+    Expression expr, {
+    @required DartType from,
+    @required DartType to,
+  }) {
     if (expr is ParenthesizedExpression) {
-      checkForCast(expr.expression, type);
+      checkForCast(expr.expression, from: from, to: to);
     } else {
-      _checkImplicitCast(expr, type);
+      _checkImplicitCast(expr, from: from, to: to);
     }
   }
 
@@ -214,16 +163,18 @@
       var exprType = element.expression.staticType;
       var asMapType = exprType.asInstanceOf(typeProvider.mapElement);
 
-      var elementKeyType =
-          asMapType == null ? null : asMapType.typeArguments[0];
-      var elementValueType =
-          asMapType == null ? null : asMapType.typeArguments[1];
-      // Keys and values in the spread will then potentially be downcast to
-      // the expected types.
-      _checkImplicitCast(element.expression, expectedKeyType,
-          from: elementKeyType, forSpreadKey: true);
-      _checkImplicitCast(element.expression, expectedValueType,
-          from: elementValueType, forSpreadValue: true);
+      if (asMapType != null) {
+        var elementKeyType = asMapType.typeArguments[0];
+        var elementValueType = asMapType.typeArguments[1];
+        // Keys and values in the spread will then potentially be downcast to
+        // the expected types.
+        _checkImplicitCast(element.expression,
+            to: expectedKeyType, from: elementKeyType, forSpreadKey: true);
+        _checkImplicitCast(element.expression,
+            to: expectedValueType,
+            from: elementValueType,
+            forSpreadValue: true);
+      }
     }
   }
 
@@ -241,16 +192,17 @@
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
+    var left = node.leftHandSide;
+    var right = node.rightHandSide;
     Token operator = node.operator;
     TokenType operatorType = operator.type;
     if (operatorType == TokenType.EQ ||
         operatorType == TokenType.QUESTION_QUESTION_EQ) {
-      DartType staticType = _getExpressionType(node.leftHandSide);
-      checkAssignment(node.rightHandSide, staticType);
+      checkForCast(right, from: right.staticType, to: node.writeType);
     } else if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
         operatorType == TokenType.BAR_BAR_EQ) {
-      checkAssignment(node.leftHandSide, typeProvider.boolType);
-      checkAssignment(node.rightHandSide, typeProvider.boolType);
+      checkBoolean(left);
+      checkBoolean(right);
     } else {
       _checkCompoundAssignment(node);
     }
@@ -457,7 +409,8 @@
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
-    _checkUnary(node.operand, node.operator, node.staticElement);
+    _checkUnary(node.operand, node.operator, node.staticElement,
+        readType: node.readType, writeType: node.writeType);
     node.visitChildren(this);
   }
 
@@ -466,7 +419,8 @@
     if (node.operator.type == TokenType.BANG) {
       checkBoolean(node.operand);
     } else {
-      _checkUnary(node.operand, node.operator, node.staticElement);
+      _checkUnary(node.operand, node.operator, node.staticElement,
+          readType: node.readType, writeType: node.writeType);
     }
     node.visitChildren(this);
   }
@@ -588,7 +542,8 @@
       for (VariableDeclaration variable in node.variables) {
         var initializer = variable.initializer;
         if (initializer != null) {
-          checkForCast(initializer, type.type);
+          checkForCast(initializer,
+              from: initializer.staticType, to: type.type);
         }
       }
     }
@@ -622,10 +577,9 @@
       assert(functionType.optionalParameterTypes.isEmpty);
 
       // Refine the return type.
-      var rhsType = _getExpressionType(expr.rightHandSide);
-      var lhsType = _getExpressionType(expr.leftHandSide);
+      var rhsType = expr.rightHandSide.staticType;
       var returnType = rules.refineBinaryExpressionType(
-        lhsType,
+        expr.readType,
         op,
         rhsType,
         functionType.returnType,
@@ -633,7 +587,7 @@
       );
 
       // Check the argument for an implicit cast.
-      _checkImplicitCast(expr.rightHandSide, paramTypes[0], from: rhsType);
+      _checkImplicitCast(expr.rightHandSide, to: paramTypes[0], from: rhsType);
 
       // Check the return type for an implicit cast.
       //
@@ -643,8 +597,8 @@
       //     y = /*implicit cast*/(y + 42);
       //     /*implicit assignment cast*/y += 42;
       //
-      _checkImplicitCast(expr.leftHandSide, lhsType,
-          from: returnType, opAssign: true);
+      _checkImplicitCast(expr.leftHandSide,
+          to: expr.writeType, from: returnType, opAssign: true);
     }
   }
 
@@ -694,8 +648,9 @@
   ///
   /// If [expr] does not require an implicit cast because it is not related to
   /// [to] or is already a subtype of it, does nothing.
-  void _checkImplicitCast(Expression expr, DartType to,
-      {DartType from,
+  void _checkImplicitCast(Expression expr,
+      {@required DartType to,
+      @required DartType from,
       bool opAssign = false,
       bool forSpread = false,
       bool forSpreadKey = false,
@@ -704,9 +659,7 @@
       return;
     }
 
-    from ??= _getExpressionType(expr);
-
-    if (_needsImplicitCast(expr, to, from: from) == true) {
+    if (_needsImplicitCast(expr, to: to, from: from) == true) {
       _recordImplicitCast(expr, to,
           from: from,
           opAssign: opAssign,
@@ -730,7 +683,8 @@
     if (expression != null) checkAssignment(expression, type);
   }
 
-  void _checkUnary(Expression operand, Token op, MethodElement element) {
+  void _checkUnary(Expression operand, Token op, MethodElement element,
+      {@required DartType readType, @required DartType writeType}) {
     bool isIncrementAssign = op.type.isIncrementOperator;
     if (op.isUserDefinableOperator || isIncrementAssign) {
       if (element != null && isIncrementAssign) {
@@ -744,9 +698,8 @@
         // Refine the return type.
         var functionType = element.type;
         var rhsType = typeProvider.intType;
-        var lhsType = _getExpressionType(operand);
         var returnType = rules.refineBinaryExpressionType(
-          lhsType,
+          readType,
           TokenType.PLUS,
           rhsType,
           functionType.returnType,
@@ -763,7 +716,8 @@
         //     y = /*implicit cast*/(y + 1);
         //     /*implicit assignment cast*/y++;
         //
-        _checkImplicitCast(operand, lhsType, from: returnType, opAssign: true);
+        _checkImplicitCast(operand,
+            to: writeType, from: returnType, opAssign: true);
       }
     }
   }
@@ -827,9 +781,6 @@
     }
   }
 
-  DartType _getExpressionType(Expression expr) =>
-      getExpressionType(expr, rules, typeProvider);
-
   DartType _getInstanceTypeArgument(
       DartType expressionType, ClassElement instanceType) {
     var asInstanceType = expressionType.asInstanceOf(instanceType);
@@ -860,9 +811,8 @@
   /// downcast implicitly).
   ///
   /// If [from] is omitted, uses the static type of [expr]
-  bool _needsImplicitCast(Expression expr, DartType to, {DartType from}) {
-    from ??= _getExpressionType(expr);
-
+  bool _needsImplicitCast(Expression expr,
+      {@required DartType from, @required DartType to}) {
     // Void is considered Top, but may only be *explicitly* cast.
     if (from.isVoid) return null;
 
@@ -886,8 +836,8 @@
     if (to.isDartAsyncFutureOr) {
       var to1 = (to as InterfaceType).typeArguments[0];
       var to2 = typeProvider.futureType2(to1);
-      return _needsImplicitCast(expr, to1, from: from) == true ||
-          _needsImplicitCast(expr, to2, from: from) == true;
+      return _needsImplicitCast(expr, to: to1, from: from) == true ||
+          _needsImplicitCast(expr, to: to2, from: from) == true;
     }
 
     // Anything else is an illegal sideways cast.
@@ -1021,7 +971,7 @@
     var sequenceElement = awaitKeyword != null
         ? typeProvider.streamElement
         : typeProvider.iterableElement;
-    var iterableType = _getExpressionType(node.iterable);
+    var iterableType = node.iterable.staticType;
     var elementType = _getInstanceTypeArgument(iterableType, sequenceElement);
 
     // If the sequence is not an Iterable (or Stream for await for) but is a
@@ -1043,8 +993,8 @@
     if (elementType != null) {
       // Insert a cast from the sequence's element type to the loop variable's
       // if needed.
-      _checkImplicitCast(loopVariable, loopVariableElement.type,
-          from: elementType);
+      _checkImplicitCast(loopVariable,
+          to: loopVariableElement.type, from: elementType);
     }
   }
 }
diff --git a/pkg/analyzer/lib/src/task/strong_mode.dart b/pkg/analyzer/lib/src/task/strong_mode.dart
index fe58576..2f72a64 100644
--- a/pkg/analyzer/lib/src/task/strong_mode.dart
+++ b/pkg/analyzer/lib/src/task/strong_mode.dart
@@ -10,7 +10,6 @@
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_algebra.dart';
-import 'package:analyzer/src/dart/element/type_demotion.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/summary/format.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -141,7 +140,7 @@
       );
       if (combinedGetter != null) {
         var returnType = combinedGetter.returnType;
-        return nonNullifyType(typeSystem, returnType);
+        return typeSystem.nonNullifyLegacy(returnType);
       }
       return DynamicTypeImpl.instance;
     }
@@ -155,7 +154,7 @@
       );
       if (combinedSetter != null) {
         var type = combinedSetter.parameters[0].type;
-        return nonNullifyType(typeSystem, type);
+        return typeSystem.nonNullifyLegacy(type);
       }
       return DynamicTypeImpl.instance;
     }
@@ -282,7 +281,7 @@
 
           if (getterType == setterType) {
             var type = getterType;
-            type = nonNullifyType(typeSystem, type);
+            type = typeSystem.nonNullifyLegacy(type);
             field.type = type;
           } else {
             LazyAst.setTypeInferenceError(
@@ -443,7 +442,7 @@
     if (element.hasImplicitReturnType && element.displayName != '[]=') {
       if (combinedSignatureType != null) {
         var returnType = combinedSignatureType.returnType;
-        returnType = nonNullifyType(typeSystem, returnType);
+        returnType = typeSystem.nonNullifyLegacy(returnType);
         element.returnType = returnType;
       } else {
         element.returnType = DynamicTypeImpl.instance;
@@ -490,7 +489,7 @@
       );
       if (matchingParameter != null) {
         var type = matchingParameter.type;
-        type = nonNullifyType(typeSystem, type);
+        type = typeSystem.nonNullifyLegacy(type);
         parameter.type = type;
       } else {
         parameter.type = DynamicTypeImpl.instance;
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index 2f054b5..9482e66 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -28,6 +28,7 @@
 const _DoNotStore doNotStore = _DoNotStore();
 const _Factory factory = const _Factory();
 const Immutable immutable = const Immutable();
+const _Internal internal = const Internal();
 const _Literal literal = const _Literal();
 const _MustCallSuper mustCallSuper = const _MustCallSuper();
 const _NonVirtual nonVirtual = const _NonVirtual();
@@ -50,6 +51,9 @@
   final String reason;
   const Immutable([this.reason]);
 }
+class _Internal {
+  const Internal();
+}
 class _Literal {
   const _Literal();
 }
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index a4ebb6e..0d6aca6 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -4,9 +4,7 @@
 
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
-import 'package:analyzer/src/context/context.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:meta/meta.dart';
@@ -1081,11 +1079,6 @@
 
   final Map<String, String> uriMap = {};
 
-  final AnalysisOptionsImpl _analysisOptions;
-
-  /// The [AnalysisContextImpl] which is used for all of the sources.
-  AnalysisContextImpl _analysisContext;
-
   @override
   final List<SdkLibrary> sdkLibraries = [];
 
@@ -1095,9 +1088,8 @@
   /// their units are relative (will be put into `sdkRoot/lib`).
   MockSdk({
     @required this.resourceProvider,
-    AnalysisOptionsImpl analysisOptions,
     List<MockSdkLibrary> additionalLibraries = const [],
-  }) : _analysisOptions = analysisOptions ?? AnalysisOptionsImpl() {
+  }) {
     _versionFile = resourceProvider
         .getFolder(resourceProvider.convertPath(sdkRoot))
         .getChildAssumingFile('version');
@@ -1190,15 +1182,6 @@
   }
 
   @override
-  AnalysisContextImpl get context {
-    if (_analysisContext == null) {
-      var factory = SourceFactory([DartUriResolver(this)]);
-      _analysisContext = SdkAnalysisContext(_analysisOptions, factory);
-    }
-    return _analysisContext;
-  }
-
-  @override
   Version get languageVersion {
     var sdkVersionStr = _versionFile.readAsStringSync();
     return languageVersionFromSdkVersion(sdkVersionStr);
diff --git a/pkg/analyzer/lib/src/test_utilities/platform.dart b/pkg/analyzer/lib/src/test_utilities/platform.dart
new file mode 100644
index 0000000..11507ee
--- /dev/null
+++ b/pkg/analyzer/lib/src/test_utilities/platform.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+/// The EOL character to be used for source code in tests.
+final platformEol = Platform.isWindows ? '\r\n' : '\n';
+
+/// Normalizes content to use platform-specific newlines to ensure that
+/// when running on Windows \r\n is used even though source files are checked
+/// out using \n.
+String normalizeNewlinesForPlatform(String input) {
+  // Skip normalising for other platforms, as the gitattributes for the SDK
+  // will ensure all files are \n.
+  if (!Platform.isWindows) {
+    return input;
+  }
+
+  final newlinePattern = RegExp(r'\r?\n'); // either \r\n or \n
+  return input.replaceAll(newlinePattern, platformEol);
+}
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart
index fb02a62..5f3be2a 100644
--- a/pkg/analyzer/lib/src/workspace/basic.dart
+++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -80,4 +80,12 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace.packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    // Since every source file in a BasicPackage is in the same directory, they
+    // are all in the public API of the package. A file in a subdirectory
+    // is in a separate package.
+    return true;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 615fb32..2c474e6 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -78,6 +78,10 @@
         return null;
       }
 
+      if (uriPath.contains('//') || uriPath.contains('..')) {
+        return null;
+      }
+
       String packageName = uriPath.substring(0, slash);
       String fileUriPart = uriPath.substring(slash + 1);
       String filePath = fileUriPart.replaceAll('/', _context.separator);
@@ -256,6 +260,19 @@
   WorkspacePackage findPackageFor(String filePath) {
     path.Context context = provider.pathContext;
     Folder folder = provider.getFolder(context.dirname(filePath));
+    if (!context.isWithin(root, folder.path)) {
+      return null;
+    }
+
+    // Handle files which are given with their location in "bazel-bin", etc.
+    // This does not typically happen during usual analysis, but it still could,
+    // and it can come up in tests.
+    if ([genfiles, ...binPaths]
+        .any((binPath) => context.isWithin(binPath, folder.path))) {
+      var relative = context.relative(filePath, from: root);
+      return findPackageFor(
+          context.joinAll([root, ...context.split(relative).skip(1)]));
+    }
 
     while (true) {
       Folder parent = folder.parent;
@@ -296,7 +313,8 @@
       // [folder]'s path, relative to [root]. For example, "foo/bar".
       String relative = context.relative(folder.path, from: root);
       for (String bin in binPaths) {
-        Folder binChild = provider.getFolder(context.join(bin, relative));
+        Folder binChild =
+            provider.getFolder(context.normalize(context.join(bin, relative)));
         if (binChild.exists &&
             binChild.getChildren().any((c) => c.path.endsWith('.packages'))) {
           // [folder]'s sister folder within [bin] contains a ".packages" file.
@@ -544,4 +562,41 @@
   //  lists.
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       <String, List<Folder>>{};
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$root/lib" is public iff it is not in "$root/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    var relativeRoot =
+        workspace.provider.pathContext.relative(root, from: workspace.root);
+    for (var binPath in workspace.binPaths) {
+      libFolder =
+          workspace.provider.pathContext.join(binPath, relativeRoot, 'lib');
+      if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+        // A file in "$bin/lib" is public iff it is not in "$bin/lib/src".
+        var libSrcFolder =
+            workspace.provider.pathContext.join(libFolder, 'src');
+        return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+      }
+    }
+
+    libFolder = workspace.provider.pathContext
+        .join(workspace.genfiles, relativeRoot, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$genfiles/lib" is public iff it is not in
+      // "$genfiles/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index cca441f..fe78cc0 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -237,4 +237,17 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace.packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      var libSrcFolder =
+          workspace.provider.pathContext.join(root, 'lib', 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index 60eb742..7240390 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -137,6 +137,12 @@
   /// package:build does it.
   static const String _pubspecName = 'pubspec.yaml';
 
+  static const List<String> _generatedPathParts = [
+    '.dart_tool',
+    'build',
+    'generated'
+  ];
+
   /// The resource provider used to access the file system.
   final ResourceProvider provider;
 
@@ -286,7 +292,7 @@
           final yaml = loadYaml(pubspec.readAsStringSync());
           final packageName = yaml['name'] as String;
           final generatedRootPath = provider.pathContext
-              .join(folder.path, '.dart_tool', 'build', 'generated');
+              .joinAll([folder.path, ..._generatedPathParts]);
           final generatedThisPath =
               provider.pathContext.join(generatedRootPath, packageName);
           return PackageBuildWorkspace._(provider, packageMap, folder.path,
@@ -334,4 +340,26 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace._packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$root/lib" is public iff it is not in "$root/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    libFolder = workspace.provider.pathContext.joinAll(
+        [root, ...PackageBuildWorkspace._generatedPathParts, 'test', 'lib']);
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$generated/lib" is public iff it is not in
+      // "$generated/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index f47327d..1fed22e 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -120,4 +120,20 @@
     //  [libraryPath] is inside the `lib` directory.
     return workspace.packageMap;
   }
+
+  @override
+
+  /// A Pub package's public API consists of libraries found in the top-level
+  /// "lib" directory, and any subdirectories, excluding the "src" directory
+  /// just inside the top-level "lib" directory.
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (!workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      return false;
+    }
+    var libSrcFolder = workspace.provider.pathContext.join(root, 'lib', 'src');
+    return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart
index d9dc17a..0b83b88 100644
--- a/pkg/analyzer/lib/src/workspace/workspace.dart
+++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -67,6 +67,9 @@
   /// path of the root of those packages for all of the packages that could
   /// validly be imported by the library with the given [libraryPath].
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath);
+
+  /// Return whether [source] is located in this package's public API.
+  bool sourceIsInPublicApi(Source source);
 }
 
 /// An interface for a workspace that contains a default analysis options file.
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 0cff7cf..6cb8815 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.40.2
+version: 0.40.4
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
@@ -7,7 +7,7 @@
   sdk: '>=2.7.0 <3.0.0'
 
 dependencies:
-  _fe_analyzer_shared: ^9.0.0
+  _fe_analyzer_shared: ^11.0.0
   args: ^1.0.0
   charcode: ^1.1.2
   cli_util: '>=0.1.4 <0.3.0'
diff --git a/pkg/analyzer/test/file_system/file_system_test_support.dart b/pkg/analyzer/test/file_system/file_system_test_support.dart
index 9fcb311..fe6b6c9 100644
--- a/pkg/analyzer/test/file_system/file_system_test_support.dart
+++ b/pkg/analyzer/test/file_system/file_system_test_support.dart
@@ -269,6 +269,8 @@
 
   test_resolveSymbolicLinksSync_links_existing();
 
+  test_resolveSymbolicLinksSync_links_notExisting();
+
   test_resolveSymbolicLinksSync_noLinks_existing() {
     File file = getFile(exists: true);
 
diff --git a/pkg/analyzer/test/file_system/memory_file_system_test.dart b/pkg/analyzer/test/file_system/memory_file_system_test.dart
index 00d30bc..4b25786 100644
--- a/pkg/analyzer/test/file_system/memory_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/memory_file_system_test.dart
@@ -251,19 +251,37 @@
     expect(newFile.readAsStringSync(), defaultFileContent);
   }
 
-  @failingTest
   @override
   test_resolveSymbolicLinksSync_links_existing() {
-    // TODO(brianwilkerson) Decide how to test this given that we cannot
-    // create a link in a MemoryResourceProvider.
-    fail('Not tested');
+    var a = provider.convertPath('/test/lib/a.dart');
+    var b = provider.convertPath('/test/lib/b.dart');
+
+    provider.newLink(b, a);
+    provider.newFile(a, 'aaa');
+
+    var resolved = provider.getFile(b).resolveSymbolicLinksSync();
+    expect(resolved.path, a);
+  }
+
+  @override
+  test_resolveSymbolicLinksSync_links_notExisting() {
+    var a = provider.convertPath('/test/lib/a.dart');
+    var b = provider.convertPath('/test/lib/b.dart');
+
+    provider.newLink(b, a);
+
+    expect(() {
+      provider.getFile(b).resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
   }
 
   @override
   test_resolveSymbolicLinksSync_noLinks_notExisting() {
     File file = getFile(exists: false);
 
-    expect(file.resolveSymbolicLinksSync(), file);
+    expect(() {
+      file.resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
   }
 
   @override
@@ -286,7 +304,18 @@
 }
 
 @reflectiveTest
-class MemoryFolderTest extends BaseTest with FolderTestMixin {}
+class MemoryFolderTest extends BaseTest with FolderTestMixin {
+  test_resolveSymbolicLinksSync() {
+    var lib = provider.convertPath('/test/lib');
+    var foo = provider.convertPath('/test/lib/foo');
+
+    provider.newLink(foo, lib);
+    provider.newFolder(lib);
+
+    var resolved = provider.getFolder(foo).resolveSymbolicLinksSync();
+    expect(resolved.path, lib);
+  }
+}
 
 @reflectiveTest
 class MemoryResourceProviderTest extends BaseTest
@@ -369,6 +398,36 @@
     expect(() => provider.newFolder('not/absolute'), throwsArgumentError);
   }
 
+  test_newLink_folder() {
+    provider.newLink(
+      provider.convertPath('/test/lib/foo'),
+      provider.convertPath('/test/lib'),
+    );
+
+    provider.newFile(
+      provider.convertPath('/test/lib/a.dart'),
+      'aaa',
+    );
+
+    {
+      var path = '/test/lib/foo/a.dart';
+      var convertedPath = provider.convertPath(path);
+      var file = provider.getFile(convertedPath);
+      expect(file.exists, true);
+      expect(file.modificationStamp, isNonNegative);
+      expect(file.readAsStringSync(), 'aaa');
+    }
+
+    {
+      var path = '/test/lib/foo/foo/a.dart';
+      var convertedPath = provider.convertPath(path);
+      var file = provider.getFile(convertedPath);
+      expect(file.exists, true);
+      expect(file.modificationStamp, isNonNegative);
+      expect(file.readAsStringSync(), 'aaa');
+    }
+  }
+
   @override
   test_pathContext() {
     if (path.style == path.Style.windows) {
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index e3bb73d..5819681 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -10,6 +10,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'file_system_test_support.dart';
+
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(FileTest);
@@ -333,13 +335,26 @@
   }
 
   void test_resolveSymbolicLinksSync_noLinks_notExisting_withoutOverlay() {
-    _resolveSymbolicLinksSync_noLinks(
-        _file(exists: false, path: '/temp/a/b/test.txt'));
+    var file = _file(
+      exists: false,
+      path: '/temp/a/b/test.txt',
+    );
+
+    expect(() {
+      file.resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
   }
 
   void test_resolveSymbolicLinksSync_noLinks_notExisting_withOverlay() {
-    _resolveSymbolicLinksSync_noLinks(
-        _file(exists: false, path: '/temp/a/b/test.txt', withOverlay: true));
+    var file = _file(
+      exists: false,
+      path: '/temp/a/b/test.txt',
+      withOverlay: true,
+    );
+
+    expect(() {
+      file.resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
   }
 
   test_shortName() {
diff --git a/pkg/analyzer/test/file_system/physical_file_system_test.dart b/pkg/analyzer/test/file_system/physical_file_system_test.dart
index 03e0f0c..60e698a 100644
--- a/pkg/analyzer/test/file_system/physical_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/physical_file_system_test.dart
@@ -145,11 +145,24 @@
   }
 
   @override
+  test_resolveSymbolicLinksSync_links_notExisting() {
+    var a = join(tempPath, 'a.dart');
+    var b = join(tempPath, 'b.dart');
+
+    io.Link(b).createSync(a, recursive: true);
+
+    expect(() {
+      provider.getFile(b).resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
+  }
+
+  @override
   test_resolveSymbolicLinksSync_noLinks_notExisting() {
     File file = getFile(exists: false);
 
-    expect(
-        () => file.resolveSymbolicLinksSync(), throwsA(isFileSystemException));
+    expect(() {
+      file.resolveSymbolicLinksSync();
+    }, throwsA(isFileSystemException));
   }
 
   @override
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 097479c..996f5cc 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -501,8 +501,7 @@
     var file = getFile(result.path);
     var evaluator = ConstantEvaluator(
       file.createSource(result.uri),
-      result.typeProvider,
-      typeSystem: result.typeSystem,
+      result.libraryElement,
     );
 
     return evaluator.evaluate(expression);
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index f9ae380..75588bf 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -370,48 +370,6 @@
     _createResolver();
   }
 
-  test_lookUpMethodInInterfaces() async {
-    InterfaceType intType = _typeProvider.intType;
-    //
-    // abstract class A { int operator[](int index); }
-    //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    MethodElement operator =
-        ElementFactory.methodElement("[]", intType, [intType]);
-    classA.methods = <MethodElement>[operator];
-    //
-    // class B implements A {}
-    //
-    ClassElementImpl classB = ElementFactory.classElement2("B");
-    _encloseElement(classB);
-    classB.interfaces = <InterfaceType>[interfaceTypeStar(classA)];
-    //
-    // class C extends Object with B {}
-    //
-    ClassElementImpl classC = ElementFactory.classElement2("C");
-    _encloseElement(classC);
-    classC.mixins = <InterfaceType>[interfaceTypeStar(classB)];
-    //
-    // class D extends C {}
-    //
-    ClassElementImpl classD =
-        ElementFactory.classElement("D", interfaceTypeStar(classC));
-    _encloseElement(classD);
-    //
-    // D a;
-    // a[i];
-    //
-    SimpleIdentifier array = AstTestFactory.identifier3("a");
-    array.staticType = interfaceTypeStar(classD);
-    IndexExpression expression = AstTestFactory.indexExpression(
-      target: array,
-      index: AstTestFactory.identifier3("i"),
-    );
-    expect(_resolveIndexExpression(expression), same(operator));
-    _listener.assertNoErrors();
-  }
-
   test_visitBreakStatement_withLabel() async {
     // loop: while (true) {
     //   break loop;
@@ -706,195 +664,6 @@
     _listener.assertNoErrors();
   }
 
-  test_visitPrefixedIdentifier_nonDynamic() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    String getterName = "b";
-    PropertyAccessorElement getter =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getter];
-    SimpleIdentifier target = AstTestFactory.identifier3("a");
-    VariableElementImpl variable = ElementFactory.localVariableElement(target);
-    variable.type = interfaceTypeStar(classA);
-    target.staticElement = variable;
-    target.staticType = interfaceTypeStar(classA);
-    PrefixedIdentifier identifier = AstTestFactory.identifier(
-        target, AstTestFactory.identifier3(getterName));
-    _resolveNode(identifier);
-    expect(identifier.staticElement, same(getter));
-    expect(identifier.identifier.staticElement, same(getter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPrefixedIdentifier_staticClassMember_getter() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    // set accessors
-    String propName = "b";
-    PropertyAccessorElement getter =
-        ElementFactory.getterElement(propName, true, _typeProvider.intType);
-    PropertyAccessorElement setter =
-        ElementFactory.setterElement(propName, true, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getter, setter];
-    // prepare "A.b"
-    SimpleIdentifier target = AstTestFactory.identifier3("A");
-    target.staticElement = classA;
-    target.staticType = interfaceTypeStar(classA);
-    PrefixedIdentifier identifier =
-        AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
-    // resolve
-    _resolveNode(identifier);
-    expect(identifier.staticElement, same(getter));
-    expect(identifier.identifier.staticElement, same(getter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPrefixedIdentifier_staticClassMember_method() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    // set methods
-    String propName = "m";
-    var method = ElementFactory.methodElement("m", _typeProvider.intType);
-    method.isStatic = true;
-    classA.methods = <MethodElement>[method];
-    // prepare "A.m"
-    SimpleIdentifier target = AstTestFactory.identifier3("A");
-    target.staticElement = classA;
-    target.staticType = interfaceTypeStar(classA);
-    PrefixedIdentifier identifier =
-        AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
-    AstTestFactory.expressionStatement(identifier);
-    // resolve
-    _resolveNode(identifier);
-    expect(identifier.staticElement, same(method));
-    expect(identifier.identifier.staticElement, same(method));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPrefixedIdentifier_staticClassMember_setter() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    // set accessors
-    String propName = "b";
-    PropertyAccessorElement getter =
-        ElementFactory.getterElement(propName, true, _typeProvider.intType);
-    PropertyAccessorElement setter =
-        ElementFactory.setterElement(propName, true, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getter, setter];
-    // prepare "A.b = null"
-    SimpleIdentifier target = AstTestFactory.identifier3("A");
-    target.staticElement = classA;
-    target.staticType = interfaceTypeStar(classA);
-    PrefixedIdentifier identifier =
-        AstTestFactory.identifier(target, AstTestFactory.identifier3(propName));
-    AstTestFactory.assignmentExpression(
-        identifier, TokenType.EQ, AstTestFactory.nullLiteral());
-    // resolve
-    _resolveNode(identifier);
-    expect(identifier.staticElement, same(setter));
-    expect(identifier.identifier.staticElement, same(setter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPropertyAccess_getter_identifier() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    String getterName = "b";
-    PropertyAccessorElement getter =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getter];
-    SimpleIdentifier target = AstTestFactory.identifier3("a");
-    target.staticType = interfaceTypeStar(classA);
-    PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
-    _resolveNode(access);
-    expect(access.propertyName.staticElement, same(getter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPropertyAccess_getter_super() async {
-    //
-    // class A {
-    //  int get b;
-    // }
-    // class B {
-    //   ... super.m ...
-    // }
-    //
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    String getterName = "b";
-    PropertyAccessorElement getter =
-        ElementFactory.getterElement(getterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[getter];
-    SuperExpression target = AstTestFactory.superExpression();
-    var classB = ElementFactory.classElement("B", interfaceTypeStar(classA));
-    _encloseElement(classB);
-    target.staticType = interfaceTypeStar(classB);
-    PropertyAccess access = AstTestFactory.propertyAccess2(target, getterName);
-    AstTestFactory.methodDeclaration2(
-        null,
-        null,
-        null,
-        null,
-        AstTestFactory.identifier3("m"),
-        AstTestFactory.formalParameterList(),
-        AstTestFactory.expressionFunctionBody(access));
-    _resolveNode(access);
-    expect(access.propertyName.staticElement, same(getter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitPropertyAccess_setter_this() async {
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    String setterName = "b";
-    PropertyAccessorElement setter =
-        ElementFactory.setterElement(setterName, false, _typeProvider.intType);
-    classA.accessors = <PropertyAccessorElement>[setter];
-    ThisExpression target = AstTestFactory.thisExpression();
-    target.staticType = interfaceTypeStar(classA);
-    PropertyAccess access = AstTestFactory.propertyAccess2(target, setterName);
-    AstTestFactory.assignmentExpression(
-        access, TokenType.EQ, AstTestFactory.integer(0));
-    _resolveNode(access);
-    expect(access.propertyName.staticElement, same(setter));
-    _listener.assertNoErrors();
-  }
-
-  test_visitSimpleIdentifier_classScope() async {
-    InterfaceType doubleType = _typeProvider.doubleType;
-    String fieldName = 'nan';
-    SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
-    _resolveInClass(node, doubleType.element);
-    expect(node.staticElement, doubleType.getGetter(fieldName));
-    _listener.assertNoErrors();
-  }
-
-  test_visitSimpleIdentifier_lexicalScope() async {
-    SimpleIdentifier node = AstTestFactory.identifier3("i");
-    VariableElementImpl element = ElementFactory.localVariableElement(node);
-    expect(_resolveIdentifier(node, [element]), same(element));
-    _listener.assertNoErrors();
-  }
-
-  test_visitSimpleIdentifier_lexicalScope_field_setter() async {
-    InterfaceType intType = _typeProvider.intType;
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    _encloseElement(classA);
-    String fieldName = "a";
-    FieldElement field =
-        ElementFactory.fieldElement(fieldName, false, false, false, intType);
-    classA.fields = <FieldElement>[field];
-    classA.accessors = <PropertyAccessorElement>[field.getter, field.setter];
-    SimpleIdentifier node = AstTestFactory.identifier3(fieldName);
-    AstTestFactory.assignmentExpression(
-        node, TokenType.EQ, AstTestFactory.integer(0));
-    _resolveInClass(node, classA);
-    PropertyAccessorElement element = node.staticElement;
-    expect(element.isSetter, isTrue);
-    _listener.assertNoErrors();
-  }
-
   test_visitSuperConstructorInvocation() async {
     ClassElementImpl superclass = ElementFactory.classElement2("A");
     _encloseElement(superclass);
@@ -1008,18 +777,6 @@
   /// has resolved the identifier.
   ///
   /// @param node the expression to be resolved
-  /// @param definedElements the elements that are to be defined in the scope in
-  ///          which the element is being resolved
-  /// @return the element to which the expression was resolved
-  Element _resolveIdentifier(Identifier node, [List<Element> definedElements]) {
-    _resolveNode(node, definedElements);
-    return node.staticElement;
-  }
-
-  /// Return the element associated with the given identifier after the resolver
-  /// has resolved the identifier.
-  ///
-  /// @param node the expression to be resolved
   /// @param enclosingClass the element representing the class enclosing the
   ///          identifier
   /// @return the element to which the expression was resolved
@@ -1039,19 +796,6 @@
     }
   }
 
-  /// Return the element associated with the given expression after the resolver
-  /// has resolved the expression.
-  ///
-  /// @param node the expression to be resolved
-  /// @param definedElements the elements that are to be defined in the scope in
-  ///          which the element is being resolved
-  /// @return the element to which the expression was resolved
-  Element _resolveIndexExpression(IndexExpression node,
-      [List<Element> definedElements]) {
-    _resolveNode(node, definedElements);
-    return node.staticElement;
-  }
-
   /// Return the element associated with the given identifier after the resolver
   /// has resolved the identifier.
   ///
diff --git a/pkg/analyzer/test/generated/invalid_code_test.dart b/pkg/analyzer/test/generated/invalid_code_test.dart
index 5f397fd..a116216 100644
--- a/pkg/analyzer/test/generated/invalid_code_test.dart
+++ b/pkg/analyzer/test/generated/invalid_code_test.dart
@@ -326,6 +326,17 @@
 ''');
   }
 
+  test_localFunction_defaultFieldFormalParameter_metadata() async {
+    await _assertCanBeAnalyzed(r'''
+const my = 0;
+
+void foo() {
+  // ignore:unused_element
+  void bar({@my this.x}) {}
+}
+''');
+  }
+
   test_typeBeforeAnnotation() async {
     await _assertCanBeAnalyzed('''
 class A {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index fa9fb23..3046a23 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -1114,6 +1114,17 @@
 @reflectiveTest
 class ComplexParserTest_Fasta extends FastaParserTestCase
     with ComplexParserTestMixin {
+  void test_binary_operator_written_out_expression() {
+    BinaryExpression expression = parseExpression('x xor y', errors: [
+      expectedError(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 2, 3),
+    ]);
+    SimpleIdentifier lhs = expression.leftOperand;
+    expect(lhs.name, 'x');
+    expect(expression.operator.lexeme, '^');
+    SimpleIdentifier rhs = expression.rightOperand;
+    expect(rhs.name, 'y');
+  }
+
   void test_conditionalExpression_precedence_nullableType_as2() {
     ExpressionStatement statement = parseStatement('x as bool? ? (x + y) : z;');
     ConditionalExpression expression = statement.expression;
@@ -1420,7 +1431,7 @@
     parseExpression('n=<.["\$assert', errors: [
       expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 3, 1),
       expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 4, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 6),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 6),
       expectedError(ScannerErrorCode.UNTERMINATED_STRING_LITERAL, 12, 1),
       expectedError(ScannerErrorCode.EXPECTED_TOKEN, 13, 1),
     ]);
@@ -1434,26 +1445,6 @@
     ]);
   }
 
-  void test_listLiteral_spread_disabled() {
-    ListLiteral list =
-        parseExpression('[1, ...[2]]', featureSet: beforeUiAsCode, errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 3),
-    ]);
-    expect(list.elements, hasLength(1));
-    IntegerLiteral first = list.elements[0];
-    expect(first.value, 1);
-  }
-
-  void test_listLiteral_spreadQ_disabled() {
-    ListLiteral list =
-        parseExpression('[1, ...?[2]]', featureSet: beforeUiAsCode, errors: [
-      expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 4),
-    ]);
-    expect(list.elements, hasLength(1));
-    IntegerLiteral first = list.elements[0];
-    expect(first.value, 1);
-  }
-
   void test_lt_dot_bracket_quote() {
     // https://github.com/dart-lang/sdk/issues/37674
     ListLiteral list = parseExpression('<.["', errors: [
@@ -1500,17 +1491,6 @@
     expect(value.value, 6);
   }
 
-  void test_mapLiteral_invalid_set_entry_uiAsCodeDisabled() {
-    SetOrMapLiteral map =
-        parseExpression('<int, int>{1}', featureSet: beforeUiAsCode, errors: [
-      expectedError(ParserErrorCode.EXPECTED_TOKEN, 12, 1),
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 12, 1),
-    ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(1));
-  }
-
   @failingTest
   void test_mapLiteral_invalid_too_many_type_arguments1() {
     SetOrMapLiteral map = parseExpression('<int, int, int>{}', errors: [
@@ -1541,72 +1521,6 @@
     expect(map.elements, hasLength(0));
   }
 
-  void test_mapLiteral_spread2_typed_disabled() {
-    SetOrMapLiteral map = parseExpression('<int, int>{1: 2, ...{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 3),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spread_disabled() {
-    SetOrMapLiteral map = parseExpression('{1: 2, ...{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 3),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spread_typed_disabled() {
-    SetOrMapLiteral map = parseExpression('<int, int>{...{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 3),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(0));
-  }
-
-  void test_mapLiteral_spreadQ2_typed_disabled() {
-    SetOrMapLiteral map = parseExpression('<int, int>{1: 2, ...?{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 17, 4),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ_disabled() {
-    SetOrMapLiteral map = parseExpression('{1: 2, ...?{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 7, 4),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ_typed_disabled() {
-    SetOrMapLiteral map = parseExpression('<int, int>{...?{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [
-          expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 11, 4),
-        ]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.elements, hasLength(0));
-  }
-
   void test_parseConstructorInitializer_functionExpression() {
     // https://github.com/dart-lang/sdk/issues/37414
     parseCompilationUnit('class C { C.n() : this()(); }', errors: [
@@ -1617,8 +1531,9 @@
   void test_parseStringLiteral_interpolated_void() {
     Expression expression = parseStringLiteral(r"'<html>$void</html>'");
     expect(expression, isNotNull);
-    assertErrors(
-        errors: [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 4)]);
+    assertErrors(errors: [
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 4)
+    ]);
     expect(expression, isStringInterpolation);
     StringInterpolation literal = expression;
     NodeList<InterpolationElement> elements = literal.elements;
@@ -1679,18 +1594,6 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_invalid_map_entry_beforeUiAsCode() {
-    SetOrMapLiteral set =
-        parseExpression('<int>{1: 1}', featureSet: beforeUiAsCode, errors: [
-      expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 1),
-    ]);
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments.arguments, hasLength(1));
-    NamedType typeArg = set.typeArguments.arguments[0];
-    expect(typeArg.name.name, 'int');
-    expect(set.elements.length, 1);
-  }
-
   void test_setLiteral_nested_typeArgument() {
     SetOrMapLiteral set = parseExpression('<Set<int>>{{3}}');
     expect(set.constKeyword, isNull);
@@ -1707,46 +1610,6 @@
     expect(value.value, 3);
   }
 
-  void test_setLiteral_spread2_disabled() {
-    SetOrMapLiteral set = parseExpression('{3, ...[4]}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 3)]);
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(1));
-    IntegerLiteral value = set.elements[0];
-    expect(value.value, 3);
-  }
-
-  void test_setLiteral_spread2Q_disabled() {
-    SetOrMapLiteral set = parseExpression('{3, ...?[4]}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 4, 4)]);
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNull);
-    expect(set.elements, hasLength(1));
-    IntegerLiteral value = set.elements[0];
-    expect(value.value, 3);
-  }
-
-  void test_setLiteral_spread_typed_disabled() {
-    SetOrMapLiteral set = parseExpression('<int>{...[3]}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 6, 3)]);
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNotNull);
-    expect(set.elements, hasLength(0));
-  }
-
-  void test_setLiteral_spreadQ_typed_disabled() {
-    SetOrMapLiteral set = parseExpression('<int>{...?[3]}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 6, 4)]);
-    expect(set.constKeyword, isNull);
-    expect(set.typeArguments, isNotNull);
-    expect(set.elements, hasLength(0));
-  }
-
   void test_setLiteral_typed() {
     SetOrMapLiteral set = parseExpression('<int>{3}');
     expect(set.constKeyword, isNull);
@@ -1757,24 +1620,6 @@
     IntegerLiteral value = set.elements[0];
     expect(value.value, 3);
   }
-
-  void test_setOrMapLiteral_spread_disabled() {
-    SetOrMapLiteral map = parseExpression('{...{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 3)]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(0));
-  }
-
-  void test_setOrMapLiteral_spreadQ_disabled() {
-    SetOrMapLiteral map = parseExpression('{...?{3: 4}}',
-        featureSet: beforeUiAsCode,
-        errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 1, 4)]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
-    expect(map.elements, hasLength(0));
-  }
 }
 
 @reflectiveTest
@@ -3025,7 +2870,7 @@
 
   test_fuzz_38113() async {
     // https://github.com/dart-lang/sdk/issues/38113
-    await parseCompilationUnit(r'+t{{r?this}}', errors: [
+    parseCompilationUnit(r'+t{{r?this}}', errors: [
       expectedError(ParserErrorCode.EXPECTED_EXECUTABLE, 0, 1),
       expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 1, 1),
       expectedError(ParserErrorCode.MISSING_IDENTIFIER, 6, 4),
@@ -4887,7 +4732,8 @@
   void test_function_disabled() {
     parseCompilationUnit('void A(in int value) {}',
         errors: [
-          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 2),
+          expectedError(
+              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
           expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
         ],
         featureSet: FeatureSet.forTesting(sdkVersion: '2.5.0'));
@@ -4895,7 +4741,7 @@
 
   void test_function_enabled() {
     parseCompilationUnit('void A(in int value) {}', errors: [
-      expectedError(ParserErrorCode.MISSING_IDENTIFIER, 7, 2),
+      expectedError(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 7, 2),
       expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 3),
     ]);
   }
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 0a08957..3f1b6d7 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -607,7 +607,10 @@
     ClassMember member = parser.parseClassMember('C');
     expect(member, isNotNull);
     listener.assertErrors(usingFastaParser
-        ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3)]
+        ? [
+            expectedError(
+                ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 4, 3)
+          ]
         : [
             expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 3),
             expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 4, 3)
@@ -3633,7 +3636,8 @@
           errors: usingFastaParser
               ? [
                   expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5),
-                  expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 5)
+                  expectedError(
+                      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 9, 5)
                 ]
               : [expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 9, 5)]);
     }
@@ -3976,7 +3980,8 @@
     expectNotNullIfNoErrors(member);
     listener.assertErrors([
       usingFastaParser
-          ? expectedError(ParserErrorCode.MISSING_IDENTIFIER, 2, 4)
+          ? expectedError(
+              ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 2, 4)
           : expectedError(ParserErrorCode.INVALID_CONSTRUCTOR_NAME, 0, 1)
     ]);
   }
@@ -5453,7 +5458,7 @@
   void test_typedef_namedFunction() {
     parseCompilationUnit('typedef void Function();',
         codes: usingFastaParser
-            ? [ParserErrorCode.MISSING_IDENTIFIER]
+            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
             : [
                 ParserErrorCode.UNEXPECTED_TOKEN,
                 ParserErrorCode.MISSING_IDENTIFIER,
@@ -11347,9 +11352,7 @@
     // TODO(brianwilkerson) We could do better with this.
     parseCompilationUnit("do() {}",
         codes: usingFastaParser
-            // fasta reports ExpectedIdentifier
-            // which gets mapped to MISSING_IDENTIFIER
-            ? [ParserErrorCode.MISSING_IDENTIFIER]
+            ? [ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD]
             : [
                 ParserErrorCode.EXPECTED_EXECUTABLE,
                 ParserErrorCode.UNEXPECTED_TOKEN
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index db7b889..147d0ebd 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -538,37 +538,6 @@
     verifyTestResolved();
   }
 
-  test_getter_and_setter_fromMixins_property_access() async {
-    await assertNoErrorsInCode(r'''
-class B {}
-class M1 {
-  get x => null;
-  set x(value) {}
-}
-class M2 {
-  get x => null;
-  set x(value) {}
-}
-class C extends B with M1, M2 {}
-void main() {
-  new C().x += 1;
-}
-''');
-    verifyTestResolved();
-
-    // Verify that both the getter and setter for "x" in "new C().x" refer to
-    // the accessors defined in M2.
-    var leftHandSide = findNode.simple('x +=');
-    expect(
-      leftHandSide.staticElement,
-      findElement.setter('x', of: 'M2'),
-    );
-    expect(
-      leftHandSide.auxiliaryElements.staticElement,
-      findElement.getter('x', of: 'M2'),
-    );
-  }
-
   test_getter_fromMixins_bare_identifier() async {
     await assertNoErrorsInCode('''
 class B {}
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 5d380c9..408930a 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -588,59 +588,6 @@
     _listener.assertNoErrors();
   }
 
-  void test_visitPrefixedIdentifier_getter() {
-    DartType boolType = _typeProvider.boolType;
-    PropertyAccessorElementImpl getter =
-        ElementFactory.getterElement("b", false, boolType);
-    PrefixedIdentifier node = AstTestFactory.identifier5("a", "b");
-    node.identifier.staticElement = getter;
-    expect(_analyze(node), same(boolType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitPrefixedIdentifier_setter() {
-    DartType boolType = _typeProvider.boolType;
-    FieldElementImpl field =
-        ElementFactory.fieldElement("b", false, false, false, boolType);
-    PropertyAccessorElement setter = field.setter;
-    PrefixedIdentifier node = AstTestFactory.identifier5("a", "b");
-    node.identifier.staticElement = setter;
-    expect(_analyze(node), same(boolType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitPrefixedIdentifier_variable() {
-    VariableElementImpl variable = ElementFactory.localVariableElement2("b");
-    variable.type = _typeProvider.boolType;
-    PrefixedIdentifier node = AstTestFactory.identifier5("a", "b");
-    node.identifier.staticElement = variable;
-    expect(_analyze(node), same(_typeProvider.boolType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitPropertyAccess_static_getter() {
-    DartType boolType = _typeProvider.boolType;
-    PropertyAccessorElementImpl getter =
-        ElementFactory.getterElement("b", false, boolType);
-    PropertyAccess node =
-        AstTestFactory.propertyAccess2(AstTestFactory.identifier3("a"), "b");
-    node.propertyName.staticElement = getter;
-    expect(_analyze(node), same(boolType));
-    _listener.assertNoErrors();
-  }
-
-  void test_visitPropertyAccess_static_setter() {
-    DartType boolType = _typeProvider.boolType;
-    FieldElementImpl field =
-        ElementFactory.fieldElement("b", false, false, false, boolType);
-    PropertyAccessorElement setter = field.setter;
-    PropertyAccess node =
-        AstTestFactory.propertyAccess2(AstTestFactory.identifier3("a"), "b");
-    node.propertyName.staticElement = setter;
-    expect(_analyze(node), same(boolType));
-    _listener.assertNoErrors();
-  }
-
   void test_visitSimpleStringLiteral() {
     // "a"
     Expression node = _resolvedString("a");
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index f219504..7f232fc 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -3495,36 +3495,36 @@
   }
 
   test_instantiateToBounds_class_error_recursion() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class C<T0 extends List<T1>, T1 extends List<T0>> {}
 C c;
-''', []);
+''');
     _assertTopVarType('c', 'C<List<dynamic>, List<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_recursion_self() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class C<T extends C<T>> {}
 C c;
-''', []);
+''');
     _assertTopVarType('c', 'C<C<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_recursion_self2() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class A<E> {}
 class C<T extends A<T>> {}
 C c;
-''', []);
+''');
     _assertTopVarType('c', 'C<A<dynamic>>');
   }
 
   test_instantiateToBounds_class_error_typedef() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 typedef T F<T>(T x);
 class C<T extends F<T>> {}
 C c;
-''', []);
+''');
     _assertTopVarType('c', 'C<dynamic Function(dynamic)>');
   }
 
diff --git a/pkg/analyzer/test/id_tests/type_promotion_test.dart b/pkg/analyzer/test/id_tests/type_promotion_test.dart
index 067dc95..692be35 100644
--- a/pkg/analyzer/test/id_tests/type_promotion_test.dart
+++ b/pkg/analyzer/test/id_tests/type_promotion_test.dart
@@ -71,14 +71,7 @@
 
   @override
   String getText(DartType actualData, [String indentation]) {
-    if (actualData is TypeParameterTypeImpl) {
-      var element = actualData.element;
-      var promotedBound = actualData.promotedBound;
-      if (promotedBound != null) {
-        return '${element.name} & ${_typeToString(promotedBound)}';
-      }
-    }
-    return _typeToString(actualData);
+    return actualData.getDisplayString(withNullability: true);
   }
 
   @override
@@ -93,8 +86,4 @@
 
   @override
   bool isEmpty(DartType actualData) => actualData == null;
-
-  String _typeToString(DartType type) {
-    return type.getDisplayString(withNullability: true);
-  }
 }
diff --git a/pkg/analyzer/test/src/context/builder_test.dart b/pkg/analyzer/test/src/context/builder_test.dart
index 0884c88..7872242 100644
--- a/pkg/analyzer/test/src/context/builder_test.dart
+++ b/pkg/analyzer/test/src/context/builder_test.dart
@@ -309,9 +309,7 @@
     newFolder('/workspace/bazel-genfiles');
     newFolder(projectPath);
 
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
-    SourceFactoryImpl factory =
-        builder.createSourceFactory(projectPath, options);
+    SourceFactoryImpl factory = builder.createSourceFactory(projectPath);
     expect(factory.resolvers,
         contains(predicate((r) => r is BazelFileUriResolver)));
     expect(factory.resolvers,
@@ -326,9 +324,7 @@
     newFolder(projectPath);
     newFile(join(projectPath, '.packages'));
 
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
-    SourceFactoryImpl factory =
-        builder.createSourceFactory(projectPath, options);
+    SourceFactoryImpl factory = builder.createSourceFactory(projectPath);
     expect(factory.resolvers,
         contains(predicate((r) => r is ResourceUriResolver)));
     expect(factory.resolvers,
@@ -356,9 +352,8 @@
 sky_engine:${resourceProvider.pathContext.toUri(skyEnginePath)}
 b:${resourceProvider.pathContext.toUri(packageB)}
 ''');
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
 
-    SourceFactory factory = builder.createSourceFactory(projectPath, options);
+    SourceFactory factory = builder.createSourceFactory(projectPath);
 
     Source dartSource = factory.forUri('dart:async');
     expect(dartSource, isNotNull);
@@ -385,9 +380,8 @@
 a:${resourceProvider.pathContext.toUri(packageA)}
 b:${resourceProvider.pathContext.toUri(packageB)}
 ''');
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
 
-    SourceFactory factory = builder.createSourceFactory(projectPath, options);
+    SourceFactory factory = builder.createSourceFactory(projectPath);
 
     Source dartSource = factory.forUri('dart:core');
     expect(dartSource, isNotNull);
@@ -486,12 +480,12 @@
   }
 
   void test_findSdk_noPackageMap() {
-    DartSdk sdk = builder.findSdk(null, AnalysisOptionsImpl());
+    DartSdk sdk = builder.findSdk(null);
     expect(sdk, isNotNull);
   }
 
   void test_findSdk_noPackageMap_html_strong() {
-    DartSdk sdk = builder.findSdk(null, AnalysisOptionsImpl());
+    DartSdk sdk = builder.findSdk(null);
     expect(sdk, isNotNull);
     Source htmlSource = sdk.mapDartUri('dart:html');
     expect(htmlSource.fullName,
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
index 9fca7de..5a7be88 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_caching_test.dart
@@ -23,6 +23,8 @@
   }
 
   test_lints() async {
+    useEmptyByteStore();
+
     newFile(testFilePath, content: r'''
 void f() {
   ![0].isEmpty;
diff --git a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
index edcdbb7..b304d11 100644
--- a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
@@ -83,6 +83,7 @@
       resourceProvider: resourceProvider,
       packages: packages,
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -130,6 +131,7 @@
       resourceProvider: resourceProvider,
       packages: packages,
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -177,6 +179,7 @@
       resourceProvider: resourceProvider,
       packages: packages,
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -245,6 +248,7 @@
       resourceProvider: resourceProvider,
       packages: packages,
       packageDefaultFeatureSet: ExperimentStatus.latestWithNullSafety,
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -275,6 +279,7 @@
       resourceProvider: resourceProvider,
       packages: findPackagesFrom(resourceProvider, getFolder('/test')),
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -307,6 +312,7 @@
       resourceProvider: resourceProvider,
       packages: findPackagesFrom(resourceProvider, getFolder('/test')),
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
@@ -323,6 +329,7 @@
       resourceProvider: resourceProvider,
       packages: findPackagesFrom(resourceProvider, getFolder('/test')),
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
 
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 0432c93..b2a098a 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/library_graph.dart';
@@ -76,6 +77,7 @@
       resourceProvider: resourceProvider,
       packages: Packages.empty,
       packageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
+      nonPackageDefaultLanguageVersion: ExperimentStatus.currentVersion,
       nonPackageDefaultFeatureSet: FeatureSet.latestLanguageVersion(),
     );
     fileSystemState = FileSystemState(
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index d7c8abd..70061ed 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -510,6 +510,22 @@
       ..isReferencedAt('A.field); // 3', false);
   }
 
+  test_isReferencedBy_ClassElement_enum() async {
+    await _indexTestUnit('''
+enum MyEnum {a}
+
+main(MyEnum p) {
+  MyEnum v;
+  MyEnum.a;
+}
+''');
+    ClassElement element = findElement('MyEnum');
+    assertThat(element)
+      ..isReferencedAt('MyEnum p) {', false)
+      ..isReferencedAt('MyEnum v;', false)
+      ..isReferencedAt('MyEnum.a;', false);
+  }
+
   test_isReferencedBy_ClassElement_fromExtension() async {
     await _indexTestUnit('''
 class A<T> {}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index c3174e4..e5fefd3 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -280,6 +280,29 @@
     await _verifyReferences(element, expected);
   }
 
+  test_searchReferences_ClassElement_enum() async {
+    await _resolveTestUnit('''
+enum MyEnum {a}
+
+main(MyEnum p) {
+  MyEnum v;
+  MyEnum.a;
+}
+''');
+    var element = findElement.enum_('MyEnum');
+    var main = findElement.function('main');
+    var expected = [
+      _expectId(
+        findElement.parameter('p'),
+        SearchResultKind.REFERENCE,
+        'MyEnum p',
+      ),
+      _expectId(main, SearchResultKind.REFERENCE, 'MyEnum v'),
+      _expectId(main, SearchResultKind.REFERENCE, 'MyEnum.a'),
+    ];
+    await _verifyReferences(element, expected);
+  }
+
   test_searchReferences_ClassElement_mixin() async {
     await _resolveTestUnit('''
 mixin A {}
diff --git a/pkg/analyzer/test/src/dart/analysis/session_test.dart b/pkg/analyzer/test/src/dart/analysis/session_test.dart
index 5e5655f..ed80e60 100644
--- a/pkg/analyzer/test/src/dart/analysis/session_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/session_test.dart
@@ -124,7 +124,7 @@
     var typeProvider = resolvedUnit.typeProvider;
     var intClass = typeProvider.intType.element;
 
-    var parsedLibrary = await session.getParsedLibrary(testPath);
+    var parsedLibrary = session.getParsedLibrary(testPath);
 
     expect(() {
       parsedLibrary.getElementDeclaration(intClass);
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 47a4b20..0e1dca2 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -568,6 +568,7 @@
     MethodElement staticElement = ElementFactory.methodElement(
         "m", interfaceTypeStar(ElementFactory.classElement2('C')));
     AuxiliaryElements auxiliaryElements = AuxiliaryElements(staticElement);
+    // ignore: deprecated_member_use_from_same_package
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
     DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
@@ -577,6 +578,7 @@
       index: AstTestFactory.integer(0),
     );
     ResolutionCopier.copyResolutionData(fromNode, toNode);
+    // ignore: deprecated_member_use_from_same_package
     expect(toNode.auxiliaryElements, same(auxiliaryElements));
     expect(toNode.staticElement, same(staticElement));
     expect(toNode.staticType, same(staticType));
@@ -850,12 +852,14 @@
     MethodElement staticElement = ElementFactory.methodElement(
         "m", interfaceTypeStar(ElementFactory.classElement2('C')));
     AuxiliaryElements auxiliaryElements = AuxiliaryElements(staticElement);
+    // ignore: deprecated_member_use_from_same_package
     fromNode.auxiliaryElements = auxiliaryElements;
     fromNode.staticElement = staticElement;
     DartType staticType = interfaceTypeStar(ElementFactory.classElement2('C'));
     fromNode.staticType = staticType;
     SimpleIdentifier toNode = AstTestFactory.identifier3("x");
     ResolutionCopier.copyResolutionData(fromNode, toNode);
+    // ignore: deprecated_member_use_from_same_package
     expect(toNode.auxiliaryElements, same(auxiliaryElements));
     expect(toNode.staticElement, same(staticElement));
     expect(toNode.staticType, same(staticType));
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 6cd1ae9..cb7aa88 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -306,8 +305,6 @@
     Map<String, String> declaredVariables = const {},
     Map<String, DartObjectImpl> lexicalEnvironment,
   }) {
-    var analysisContext = contextFor(this.result.path);
-    var options = analysisContext.analysisOptions as AnalysisOptionsImpl;
     var expression = findNode.topVariableDeclarationByName(name).initializer;
 
     var source = this.result.unit.declaredElement.source;
@@ -321,11 +318,9 @@
     DartObjectImpl result = expression.accept(
       ConstantVisitor(
         ConstantEvaluationEngine(
-          typeProvider,
           DeclaredVariables.fromMap(declaredVariables),
-          experimentStatus: options.experimentStatus,
-          typeSystem: this.result.typeSystem,
         ),
+        this.result.libraryElement,
         errorReporter,
         lexicalEnvironment: lexicalEnvironment,
       ),
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index a5956bb..c86ea47 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -1469,29 +1469,6 @@
     expect(typeA.getMethod(methodName), same(methodM));
   }
 
-  void test_getMethod_parameterized_doesNotUseTypeParameter() {
-    //
-    // class A<E> { B m() {} }
-    // class B {}
-    //
-    var classA = ElementFactory.classElement2("A", ["E"]);
-    InterfaceType typeB = interfaceTypeStar(class_(name: 'B'));
-    String methodName = "m";
-    MethodElementImpl methodM =
-        ElementFactory.methodElement(methodName, typeB, []);
-    classA.methods = <MethodElement>[methodM];
-    //
-    // A<I>
-    //
-    InterfaceType typeI = interfaceTypeStar(class_(name: 'I'));
-    InterfaceTypeImpl typeAI =
-        interfaceTypeStar(classA, typeArguments: <DartType>[typeI]);
-    MethodElement method = typeAI.getMethod(methodName);
-    expect(method, isNotNull);
-    FunctionType methodType = method.type;
-    expect(methodType.typeArguments, isEmpty);
-  }
-
   void test_getMethod_parameterized_usesTypeParameter() {
     //
     // class A<E> { E m(E p) {} }
diff --git a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
index 970191b..428784d 100644
--- a/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/generic_inferrer_test.dart
@@ -192,6 +192,27 @@
     );
   }
 
+  /// https://github.com/dart-lang/language/issues/1182#issuecomment-702272641
+  void test_demoteType() {
+    // <T>(T x) -> void
+    var T = typeParameter('T');
+    var rawType = functionTypeNone(
+      typeFormals: [T],
+      parameters: [
+        requiredParameter(type: typeParameterTypeNone(T)),
+      ],
+      returnType: voidNone,
+    );
+
+    var S = typeParameter('S');
+    var S_and_int = typeParameterTypeNone(S, promotedBound: intNone);
+
+    var inferredTypes = _inferCall(rawType, [S_and_int]);
+    var inferredType = inferredTypes[0] as TypeParameterTypeImpl;
+    expect(inferredType.element, S);
+    expect(inferredType.promotedBound, isNull);
+  }
+
   void test_fromLegacy_nonNullableBound() {
     typeSystem = analysisContext.typeSystemLegacy;
 
diff --git a/pkg/analyzer/test/src/dart/element/nullable_test.dart b/pkg/analyzer/test/src/dart/element/nullable_test.dart
index d385bae..d690043 100644
--- a/pkg/analyzer/test/src/dart/element/nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/element/nullable_test.dart
@@ -647,12 +647,11 @@
   test_typeParameter_bound_dynamic() {
     var element = typeParameter('T', bound: dynamicNone);
 
-    var result = typeSystem.promoteToNonNull(
+    _checkTypeParameter(
       typeParameterTypeNone(element),
-    ) as TypeParameterTypeImpl;
-    expect(result.element, same(element));
-    expect(result.promotedBound, isNull);
-    expect(result.nullabilitySuffix, NullabilitySuffix.none);
+      element: element,
+      promotedBound: null,
+    );
   }
 
   test_typeParameter_bound_none() {
diff --git a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
index e3a64cf..4851abd 100644
--- a/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
+++ b/pkg/analyzer/test/src/dart/element/replace_top_bottom_test.dart
@@ -79,11 +79,22 @@
     // Not contravariant.
     _check(neverNone, 'Never');
 
-    _check(
-      functionTypeNone(returnType: intNone, parameters: [
-        requiredParameter(type: neverNone),
-      ]),
-      'int Function(Object?)',
+    void checkContravariant(DartType type, String expectedStr) {
+      _check(
+        functionTypeNone(returnType: intNone, parameters: [
+          requiredParameter(type: type),
+        ]),
+        'int Function($expectedStr)',
+      );
+    }
+
+    checkContravariant(neverNone, 'Object?');
+
+    checkContravariant(
+      typeParameterTypeNone(
+        typeParameter('T', bound: neverNone),
+      ),
+      'Object?',
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 452060b..4cb55f1 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -2482,7 +2482,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intStar),
       futureOrStar(numStar),
-      strT0: 'T, T & int*',
+      strT0: 'T & int*',
       strT1: 'FutureOr<num*>*',
     );
   }
@@ -2493,7 +2493,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, futureStar(numStar)),
       futureOrStar(numStar),
-      strT0: 'T, T & Future<num*>*',
+      strT0: 'T & Future<num*>*',
       strT1: 'FutureOr<num*>*',
     );
   }
@@ -2504,7 +2504,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, futureStar(intStar)),
       futureOrStar(numStar),
-      strT0: 'T, T & Future<int*>*',
+      strT0: 'T & Future<int*>*',
       strT1: 'FutureOr<num*>*',
     );
   }
@@ -2515,7 +2515,7 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, numStar),
       futureOrStar(intStar),
-      strT0: 'T, T & num*',
+      strT0: 'T & num*',
       strT1: 'FutureOr<int*>*',
     );
   }
@@ -2526,7 +2526,7 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, futureStar(numStar)),
       futureOrStar(intStar),
-      strT0: 'T, T & Future<num*>*',
+      strT0: 'T & Future<num*>*',
       strT1: 'FutureOr<int*>*',
     );
   }
@@ -2537,7 +2537,7 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, futureOrStar(numStar)),
       futureOrStar(intStar),
-      strT0: 'T, T & FutureOr<num*>*',
+      strT0: 'T & FutureOr<num*>*',
       strT1: 'FutureOr<int*>*',
     );
   }
@@ -2824,7 +2824,7 @@
       listNone(
         typeParameterTypeNone(T),
       ),
-      strT0: 'List<T>, T extends Object?, T & int',
+      strT0: 'List<T & int>, T extends Object?',
       strT1: 'List<T>, T extends Object?',
     );
   }
@@ -2839,7 +2839,7 @@
       listNone(
         typeParameterTypeNone(T),
       ),
-      strT0: 'List<T>, T extends Object?, T & int?',
+      strT0: 'List<T & int?>, T extends Object?',
       strT1: 'List<T>, T extends Object?',
     );
   }
@@ -3288,7 +3288,7 @@
     isSubtype(
       promotedTypeParameterTypeStar(T, intStar),
       futureOrStar(numStar),
-      strT0: 'T*, T extends Object*, T & int*',
+      strT0: 'T* & int*, T extends Object*',
       strT1: 'FutureOr<num*>*',
     );
 
@@ -3296,19 +3296,19 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object, T & int',
+      strT0: 'T & int, T extends Object',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object, T & int',
+      strT0: 'T & int, T extends Object',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object, T & int',
+      strT0: 'T & int, T extends Object',
       strT1: 'FutureOr<num>?',
     );
 
@@ -3316,19 +3316,19 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object?, T & int',
+      strT0: 'T & int, T extends Object?',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object?, T & int',
+      strT0: 'T & int, T extends Object?',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intNone),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object?, T & int',
+      strT0: 'T & int, T extends Object?',
       strT1: 'FutureOr<num>?',
     );
 
@@ -3336,19 +3336,19 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, intQuestion),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object?, T & int?',
+      strT0: 'T & int?, T extends Object?',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intQuestion),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object?, T & int?',
+      strT0: 'T & int?, T extends Object?',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, intQuestion),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object?, T & int?',
+      strT0: 'T & int?, T extends Object?',
       strT1: 'FutureOr<num>?',
     );
 
@@ -3357,19 +3357,19 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, typeParameterTypeNone(S)),
       futureOrNone(objectNone),
-      strT0: 'T, T extends Object?, T & S',
+      strT0: 'T & S, T extends Object?',
       strT1: 'FutureOr<Object>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, typeParameterTypeNone(S)),
       futureOrNone(objectQuestion),
-      strT0: 'T, T extends Object?, T & S',
+      strT0: 'T & S, T extends Object?',
       strT1: 'FutureOr<Object?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, typeParameterTypeNone(S)),
       futureOrQuestion(objectNone),
-      strT0: 'T, T extends Object?, T & S',
+      strT0: 'T & S, T extends Object?',
       strT1: 'FutureOr<Object>?',
     );
 
@@ -3377,13 +3377,13 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, futureStar(numStar)),
       futureOrStar(numStar),
-      strT0: 'T, T extends Object*, T & Future<num*>*',
+      strT0: 'T & Future<num*>*, T extends Object*',
       strT1: 'FutureOr<num*>*',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureStar(intStar)),
       futureOrStar(numStar),
-      strT0: 'T, T extends Object*, T & Future<int*>*',
+      strT0: 'T & Future<int*>*, T extends Object*',
       strT1: 'FutureOr<num*>*',
     );
 
@@ -3391,19 +3391,19 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object',
       strT1: 'FutureOr<num>?',
     );
 
@@ -3411,38 +3411,38 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object?, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object?',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object?, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object?',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intNone)),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object?, T & Future<int>',
+      strT0: 'T & Future<int>, T extends Object?',
       strT1: 'FutureOr<num>?',
     );
 
     isNotSubtype(
       promotedTypeParameterTypeNone(T, futureQuestion(intNone)),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT0: 'T & Future<int>?, T extends Object?',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureQuestion(intNone)),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT0: 'T & Future<int>?, T extends Object?',
       strT1: 'FutureOr<num?>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureQuestion(intNone)),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object?, T & Future<int>?',
+      strT0: 'T & Future<int>?, T extends Object?',
       strT1: 'FutureOr<num>?',
     );
 
@@ -3450,19 +3450,19 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intQuestion)),
       futureOrNone(numNone),
-      strT0: 'T, T extends Object, T & Future<int?>',
+      strT0: 'T & Future<int?>, T extends Object',
       strT1: 'FutureOr<num>',
     );
     isSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intQuestion)),
       futureOrNone(numQuestion),
-      strT0: 'T, T extends Object, T & Future<int?>',
+      strT0: 'T & Future<int?>, T extends Object',
       strT1: 'FutureOr<num?>',
     );
     isNotSubtype(
       promotedTypeParameterTypeNone(T, futureNone(intQuestion)),
       futureOrQuestion(numNone),
-      strT0: 'T, T extends Object, T & Future<int?>',
+      strT0: 'T & Future<int?>, T extends Object',
       strT1: 'FutureOr<num>?',
     );
   }
@@ -3632,7 +3632,7 @@
       typeParameterTypeStar(T),
       promotedTypeParameterTypeStar(T, intStar),
       strT0: 'T*, T extends int*',
-      strT1: 'T*, T extends int*, T & int*',
+      strT1: 'T* & int*, T extends int*',
     );
 
     T = typeParameter('T', bound: intNone);
@@ -3640,13 +3640,13 @@
       typeParameterTypeNone(T),
       promotedTypeParameterTypeNone(T, intNone),
       strT0: 'T, T extends int',
-      strT1: 'T, T extends int, T & int',
+      strT1: 'T & int, T extends int',
     );
     isNotSubtype(
       typeParameterTypeQuestion(T),
       promotedTypeParameterTypeNone(T, intNone),
       strT0: 'T?, T extends int',
-      strT1: 'T, T extends int, T & int',
+      strT1: 'T & int, T extends int',
     );
 
     T = typeParameter('T', bound: intQuestion);
@@ -3654,19 +3654,19 @@
       typeParameterTypeNone(T),
       promotedTypeParameterTypeNone(T, intNone),
       strT0: 'T, T extends int?',
-      strT1: 'T, T extends int?, T & int',
+      strT1: 'T & int, T extends int?',
     );
     isSubtype(
       typeParameterTypeNone(T),
       promotedTypeParameterTypeNone(T, intQuestion),
       strT0: 'T, T extends int?',
-      strT1: 'T, T extends int?, T & int?',
+      strT1: 'T & int?, T extends int?',
     );
     isNotSubtype(
       typeParameterTypeQuestion(T),
       promotedTypeParameterTypeNone(T, intQuestion),
       strT0: 'T?, T extends int?',
-      strT1: 'T, T extends int?, T & int?',
+      strT1: 'T & int?, T extends int?',
     );
 
     T = typeParameter('T', bound: numStar);
@@ -3756,7 +3756,7 @@
       neverNone,
       promotedTypeParameterTypeStar(T, numStar),
       strT0: 'Never',
-      strT1: 'T*, T extends Object*, T & num*',
+      strT1: 'T* & num*, T extends Object*',
     );
   }
 
@@ -3766,7 +3766,7 @@
     isNotSubtype(
       promotedTypeParameterTypeStar(T, numStar),
       neverNone,
-      strT0: 'T*, T extends Object*, T & num*',
+      strT0: 'T* & num*, T extends Object*',
       strT1: 'Never',
     );
   }
@@ -3788,7 +3788,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, neverNone),
       neverNone,
-      strT0: 'T, T extends Object, T & Never',
+      strT0: 'T & Never, T extends Object',
       strT1: 'Never',
     );
   }
@@ -4048,7 +4048,7 @@
       nullQuestion,
       promotedTypeParameterTypeStar(T, numStar),
       strT0: 'Null?',
-      strT1: 'T*, T extends Object*, T & num*',
+      strT1: 'T* & num*, T extends Object*',
     );
   }
 
@@ -4059,7 +4059,7 @@
       nullQuestion,
       promotedTypeParameterTypeNone(T, numNone),
       strT0: 'Null?',
-      strT1: 'T, T extends Object?, T & num',
+      strT1: 'T & num, T extends Object?',
     );
   }
 
@@ -4070,7 +4070,7 @@
       nullQuestion,
       promotedTypeParameterTypeNone(T, numQuestion),
       strT0: 'Null?',
-      strT1: 'T, T extends Object?, T & num?',
+      strT1: 'T & num?, T extends Object?',
     );
   }
 
@@ -4081,7 +4081,7 @@
       nullQuestion,
       promotedTypeParameterTypeNone(T, numNone),
       strT0: 'Null?',
-      strT1: 'T, T extends Object, T & num',
+      strT1: 'T & num, T extends Object',
     );
   }
 
@@ -4093,7 +4093,7 @@
       nullQuestion,
       promotedTypeParameterTypeNone(T, typeParameterTypeNone(S)),
       strT0: 'Null?',
-      strT1: 'T, T extends Object?, T & S',
+      strT1: 'T & S, T extends Object?',
     );
   }
 
@@ -4317,8 +4317,8 @@
     isSubtype(
       type,
       type,
-      strT0: 'T, T extends Object*, T & int?',
-      strT1: 'T, T extends Object*, T & int?',
+      strT0: 'T & int?, T extends Object*',
+      strT1: 'T & int?, T extends Object*',
     );
   }
 
@@ -4328,8 +4328,8 @@
     isSubtype(
       type,
       type,
-      strT0: 'T?, T extends Object, T & int?',
-      strT1: 'T?, T extends Object, T & int?',
+      strT0: 'T? & int?, T extends Object',
+      strT1: 'T? & int?, T extends Object',
     );
   }
 
@@ -4589,7 +4589,7 @@
       functionTypeStar(
         returnType: voidNone,
       ),
-      strT0: 'T, T & void Function()*',
+      strT0: 'T & void Function()*',
       strT1: 'void Function()*',
     );
   }
@@ -4607,7 +4607,7 @@
       functionTypeStar(
         returnType: dynamicNone,
       ),
-      strT0: 'T, T & void Function()*',
+      strT0: 'T & void Function()*',
       strT1: 'dynamic Function()*',
     );
   }
@@ -4625,7 +4625,7 @@
       functionTypeStar(
         returnType: objectStar,
       ),
-      strT0: 'T, T & void Function()*',
+      strT0: 'T & void Function()*',
       strT1: 'Object* Function()*',
     );
   }
@@ -4649,7 +4649,7 @@
         ],
         returnType: voidNone,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'void Function(void)*',
     );
   }
@@ -4673,7 +4673,7 @@
         ],
         returnType: dynamicNone,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'dynamic Function(dynamic)*',
     );
   }
@@ -4697,7 +4697,7 @@
         ],
         returnType: objectStar,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'Object* Function(Object*)*',
     );
   }
@@ -4721,7 +4721,7 @@
         ],
         returnType: dynamicNone,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'dynamic Function(Iterable<int*>*)*',
     );
   }
@@ -4745,7 +4745,7 @@
         ],
         returnType: objectStar,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'Object* Function(int*)*',
     );
   }
@@ -4769,7 +4769,7 @@
         ],
         returnType: intStar,
       ),
-      strT0: 'T, T & void Function(void)*',
+      strT0: 'T & void Function(void)*',
       strT1: 'int* Function(int*)*',
     );
   }
@@ -4884,7 +4884,7 @@
       voidNone,
       promotedTypeParameterTypeNone(T, voidNone),
       strT0: 'void',
-      strT1: 'T, T & void',
+      strT1: 'T & void',
     );
   }
 
@@ -4895,7 +4895,7 @@
       voidNone,
       promotedTypeParameterTypeNone(T, voidNone),
       strT0: 'void',
-      strT1: 'T, T extends void, T & void',
+      strT1: 'T & void, T extends void',
     );
   }
 
@@ -4905,8 +4905,8 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intStar),
       promotedTypeParameterTypeNone(T, intStar),
-      strT0: 'T, T & int*',
-      strT1: 'T, T & int*',
+      strT0: 'T & int*',
+      strT1: 'T & int*',
     );
   }
 
@@ -4916,8 +4916,8 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intStar),
       promotedTypeParameterTypeNone(T, numStar),
-      strT0: 'T, T & int*',
-      strT1: 'T, T & num*',
+      strT0: 'T & int*',
+      strT1: 'T & num*',
     );
   }
 
@@ -4927,8 +4927,8 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, numStar),
       promotedTypeParameterTypeNone(T, numStar),
-      strT0: 'T, T & num*',
-      strT1: 'T, T & num*',
+      strT0: 'T & num*',
+      strT1: 'T & num*',
     );
   }
 
@@ -4938,8 +4938,8 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, numStar),
       promotedTypeParameterTypeNone(T, intStar),
-      strT0: 'T, T & num*',
-      strT1: 'T, T & int*',
+      strT0: 'T & num*',
+      strT1: 'T & int*',
     );
   }
 
@@ -4950,7 +4950,7 @@
       nullQuestion,
       promotedTypeParameterTypeNone(T, numStar),
       strT0: 'Null?',
-      strT1: 'T, T & num*',
+      strT1: 'T & num*',
     );
   }
 
@@ -4960,7 +4960,7 @@
     isSubtype(
       promotedTypeParameterTypeStar(T, intStar),
       typeParameterTypeStar(T),
-      strT0: 'T*, T extends int*, T & int*',
+      strT0: 'T* & int*, T extends int*',
       strT1: 'T*, T extends int*',
     );
   }
@@ -4971,7 +4971,7 @@
     isSubtype(
       promotedTypeParameterTypeStar(T, intStar),
       typeParameterTypeStar(T),
-      strT0: 'T*, T extends num*, T & int*',
+      strT0: 'T* & int*, T extends num*',
       strT1: 'T*, T extends num*',
     );
   }
@@ -4982,7 +4982,7 @@
     isSubtype(
       promotedTypeParameterTypeStar(T, numStar),
       typeParameterTypeStar(T),
-      strT0: 'T*, T extends num*, T & num*',
+      strT0: 'T* & num*, T extends num*',
       strT1: 'T*, T extends num*',
     );
   }
@@ -4994,7 +4994,7 @@
       typeParameterTypeStar(T),
       promotedTypeParameterTypeStar(T, intStar),
       strT0: 'T*, T extends int*',
-      strT1: 'T*, T extends int*, T & int*',
+      strT1: 'T* & int*, T extends int*',
     );
   }
 
@@ -5005,7 +5005,7 @@
       typeParameterTypeStar(T),
       promotedTypeParameterTypeStar(T, numStar),
       strT0: 'T*, T extends int*',
-      strT1: 'T*, T extends int*, T & num*',
+      strT1: 'T* & num*, T extends int*',
     );
   }
 
@@ -5016,7 +5016,7 @@
       typeParameterTypeStar(T),
       promotedTypeParameterTypeStar(T, intStar),
       strT0: 'T*, T extends num*',
-      strT1: 'T*, T extends num*, T & int*',
+      strT1: 'T* & int*, T extends num*',
     );
   }
 
@@ -5125,7 +5125,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intStar),
       intStar,
-      strT0: 'T, T & int*',
+      strT0: 'T & int*',
       strT1: 'int*',
     );
   }
@@ -5136,7 +5136,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, intStar),
       numStar,
-      strT0: 'T, T & int*',
+      strT0: 'T & int*',
       strT1: 'num*',
     );
   }
@@ -5147,7 +5147,7 @@
     isSubtype(
       promotedTypeParameterTypeNone(T, numStar),
       numStar,
-      strT0: 'T, T & num*',
+      strT0: 'T & num*',
       strT1: 'num*',
     );
   }
@@ -5158,7 +5158,7 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(T, numStar),
       intStar,
-      strT0: 'T, T & num*',
+      strT0: 'T & num*',
       strT1: 'int*',
     );
   }
@@ -5170,7 +5170,7 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(S, numStar),
       typeParameterTypeNone(T),
-      strT0: 'S, S & num*',
+      strT0: 'S & num*',
       strT1: 'T',
     );
   }
@@ -5182,8 +5182,8 @@
     isNotSubtype(
       promotedTypeParameterTypeNone(S, numStar),
       promotedTypeParameterTypeNone(T, numStar),
-      strT0: 'S, S & num*',
-      strT1: 'T, T & num*',
+      strT0: 'S & num*',
+      strT1: 'T & num*',
     );
   }
 
@@ -5251,7 +5251,7 @@
       typeParameterTypeStar(S),
       promotedTypeParameterTypeNone(T, numStar),
       strT0: 'S*, S extends num*',
-      strT1: 'T, T & num*',
+      strT1: 'T & num*',
     );
   }
 
@@ -5262,7 +5262,7 @@
       dynamicNone,
       promotedTypeParameterTypeNone(T, dynamicNone),
       strT0: 'dynamic',
-      strT1: 'T, T extends dynamic, T & dynamic',
+      strT1: 'T & dynamic, T extends dynamic',
     );
   }
 
@@ -5280,7 +5280,7 @@
         ),
       ),
       strT0: 'T Function()*',
-      strT1: 'T, T & T Function()*',
+      strT1: 'T & T Function()*',
     );
   }
 
@@ -5292,8 +5292,8 @@
         promotedTypeParameterTypeNone(T, stringStar),
       ),
       promotedTypeParameterTypeNone(T, stringStar),
-      strT0: 'FutureOr<T>*, T & String*',
-      strT1: 'T, T & String*',
+      strT0: 'FutureOr<T & String*>*',
+      strT1: 'T & String*',
     );
   }
 
@@ -5327,19 +5327,19 @@
     isNotSubtype(
       type,
       numNone,
-      strT0: 'T, T extends Object?, T & num?',
+      strT0: 'T & num?, T extends Object?',
       strT1: 'num',
     );
     isSubtype(
       type,
       numQuestion,
-      strT0: 'T, T extends Object?, T & num?',
+      strT0: 'T & num?, T extends Object?',
       strT1: 'num?',
     );
     isSubtype(
       type,
       numStar,
-      strT0: 'T, T extends Object?, T & num?',
+      strT0: 'T & num?, T extends Object?',
       strT1: 'num*',
     );
   }
@@ -6015,9 +6015,8 @@
   void visitTypeParameterType(TypeParameterType type) {
     if (!functionTypeParameters.contains(type.element)) {
       var bound = type.element.bound;
-      var promotedBound = (type as TypeParameterTypeImpl).promotedBound;
 
-      if (bound == null && promotedBound == null) {
+      if (bound == null) {
         return;
       }
 
@@ -6028,16 +6027,6 @@
         str += '${type.element.name} extends ' + boundStr;
       }
 
-      if (promotedBound != null) {
-        var promotedBoundStr = promotedBound.getDisplayString(
-          withNullability: true,
-        );
-        if (str.isNotEmpty) {
-          str += ', ';
-        }
-        str += '${type.element.name} & ' + promotedBoundStr;
-      }
-
       typeParameters.add(str);
     }
   }
diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart
index f59885f..6efd3dd 100644
--- a/pkg/analyzer/test/src/dart/element/test_all.dart
+++ b/pkg/analyzer/test/src/dart/element/test_all.dart
@@ -22,6 +22,7 @@
 import 'subtype_test.dart' as subtype;
 import 'top_merge_test.dart' as top_merge;
 import 'type_algebra_test.dart' as type_algebra;
+import 'type_bounded_test.dart' as type_bounded;
 import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer;
 import 'type_parameter_element_test.dart' as type_parameter_element;
 import 'type_visitor_test.dart' as type_visitor;
@@ -48,6 +49,7 @@
     subtype.main();
     top_merge.main();
     type_algebra.main();
+    type_bounded.main();
     type_constraint_gatherer.main();
     type_parameter_element.main();
     type_visitor.main();
diff --git a/pkg/analyzer/test/src/dart/element/type_bounded_test.dart b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
new file mode 100644
index 0000000..e851ca6
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/element/type_bounded_test.dart
@@ -0,0 +1,240 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/element/type.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/type_system_test.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DynamicBoundedTest);
+    defineReflectiveTests(FunctionBoundedTest);
+  });
+}
+
+@reflectiveTest
+class DynamicBoundedTest extends AbstractTypeSystemNullSafetyTest {
+  test_dynamic() {
+    _assertDynamicBounded(dynamicNone);
+  }
+
+  test_dynamic_typeParameter_hasBound_dynamic() {
+    var T = typeParameter('T', bound: dynamicNone);
+
+    _assertDynamicBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasBound_notDynamic() {
+    var T = typeParameter('T', bound: intNone);
+
+    _assertNotDynamicBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_dynamic() {
+    var T = typeParameter('T');
+
+    _assertDynamicBounded(
+      typeParameterTypeNone(T, promotedBound: dynamicNone),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_notDynamic() {
+    var T = typeParameter('T');
+
+    _assertNotDynamicBounded(
+      typeParameterTypeNone(T, promotedBound: intNone),
+    );
+  }
+
+  test_dynamic_typeParameter_noBound() {
+    var T = typeParameter('T');
+
+    _assertNotDynamicBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_functionType() {
+    _assertNotDynamicBounded(
+      functionTypeNone(returnType: voidNone),
+    );
+
+    _assertNotDynamicBounded(
+      functionTypeNone(returnType: dynamicNone),
+    );
+  }
+
+  test_interfaceType() {
+    _assertNotDynamicBounded(intNone);
+    _assertNotDynamicBounded(intQuestion);
+    _assertNotDynamicBounded(intStar);
+  }
+
+  test_never() {
+    _assertNotDynamicBounded(neverNone);
+    _assertNotDynamicBounded(neverQuestion);
+    _assertNotDynamicBounded(neverStar);
+  }
+
+  test_void() {
+    _assertNotDynamicBounded(voidNone);
+  }
+
+  void _assertDynamicBounded(DartType type) {
+    expect(typeSystem.isDynamicBounded(type), isTrue);
+  }
+
+  void _assertNotDynamicBounded(DartType type) {
+    expect(typeSystem.isDynamicBounded(type), isFalse);
+  }
+}
+
+@reflectiveTest
+class FunctionBoundedTest extends AbstractTypeSystemNullSafetyTest {
+  test_dynamic() {
+    _assertNotFunctionBounded(dynamicNone);
+  }
+
+  test_dynamic_typeParameter_hasBound_functionType_none() {
+    var T = typeParameter(
+      'T',
+      bound: functionTypeNone(returnType: voidNone),
+    );
+
+    _assertFunctionBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasBound_functionType_question() {
+    var T = typeParameter(
+      'T',
+      bound: functionTypeQuestion(returnType: voidNone),
+    );
+
+    _assertNotFunctionBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasBound_functionType_star() {
+    var T = typeParameter(
+      'T',
+      bound: functionTypeStar(returnType: voidNone),
+    );
+
+    _assertFunctionBounded(
+      typeParameterTypeStar(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasBound_notFunction() {
+    var T = typeParameter('T', bound: intNone);
+
+    _assertNotFunctionBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_functionType_none() {
+    var T = typeParameter('T');
+
+    _assertFunctionBounded(
+      typeParameterTypeNone(
+        T,
+        promotedBound: functionTypeNone(
+          returnType: voidNone,
+        ),
+      ),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_functionType_question() {
+    var T = typeParameter('T');
+
+    _assertNotFunctionBounded(
+      typeParameterTypeStar(
+        T,
+        promotedBound: functionTypeQuestion(
+          returnType: voidNone,
+        ),
+      ),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_functionType_star() {
+    var T = typeParameter('T');
+
+    _assertFunctionBounded(
+      typeParameterTypeStar(
+        T,
+        promotedBound: functionTypeStar(
+          returnType: voidNone,
+        ),
+      ),
+    );
+  }
+
+  test_dynamic_typeParameter_hasPromotedBound_notFunction() {
+    var T = typeParameter('T');
+
+    _assertNotFunctionBounded(
+      typeParameterTypeNone(T, promotedBound: intNone),
+    );
+  }
+
+  test_dynamic_typeParameter_noBound() {
+    var T = typeParameter('T');
+
+    _assertNotFunctionBounded(
+      typeParameterTypeNone(T),
+    );
+  }
+
+  test_functionType() {
+    _assertFunctionBounded(
+      functionTypeNone(returnType: voidNone),
+    );
+    _assertNotFunctionBounded(
+      functionTypeQuestion(returnType: voidNone),
+    );
+    _assertFunctionBounded(
+      functionTypeStar(returnType: voidNone),
+    );
+
+    _assertFunctionBounded(
+      functionTypeNone(returnType: dynamicNone),
+    );
+  }
+
+  test_interfaceType() {
+    _assertNotFunctionBounded(intNone);
+    _assertNotFunctionBounded(intQuestion);
+    _assertNotFunctionBounded(intStar);
+  }
+
+  test_never() {
+    _assertNotFunctionBounded(neverNone);
+    _assertNotFunctionBounded(neverQuestion);
+    _assertNotFunctionBounded(neverStar);
+  }
+
+  test_void() {
+    _assertNotFunctionBounded(voidNone);
+  }
+
+  void _assertFunctionBounded(DartType type) {
+    expect(typeSystem.isFunctionBounded(type), isTrue);
+  }
+
+  void _assertNotFunctionBounded(DartType type) {
+    expect(typeSystem.isFunctionBounded(type), isFalse);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
index 87109c8b..63715f5 100644
--- a/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_constraint_gatherer_test.dart
@@ -841,6 +841,29 @@
     _checkMatch([T], numStar, T_star, true, ['num <: T <: _']);
   }
 
+  /// If `Q` is a legacy type `Q0*` then the match holds under constraint
+  /// set `C`:
+  ///   If `P` is `dynamic` or `void` and `P` is a subtype match for `Q0`
+  ///   under constraint set `C`.
+  test_left_top_right_legacy() {
+    var U = typeParameter('U', bound: objectNone);
+    var U_star = typeParameterTypeStar(U);
+
+    _checkMatch([U], dynamicNone, U_star, false, ['dynamic <: U <: _']);
+    _checkMatch([U], voidNone, U_star, false, ['void <: U <: _']);
+  }
+
+  /// If `Q` is `Q0?` the match holds under constraint set `C`:
+  ///   Or if `P` is `dynamic` or `void` and `Object` is a subtype match
+  ///   for `Q0` under constraint set `C`.
+  test_left_top_right_nullable() {
+    var U = typeParameter('U', bound: objectNone);
+    var U_question = typeParameterTypeQuestion(U);
+
+    _checkMatch([U], dynamicNone, U_question, false, ['Object <: U <: _']);
+    _checkMatch([U], voidNone, U_question, false, ['Object <: U <: _']);
+  }
+
   /// If `P` is a type variable `X` in `L`, then the match holds:
   ///   Under constraint `_ <: X <: Q`.
   test_left_typeParameter() {
diff --git a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
index 6454cda..3372610 100644
--- a/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
+++ b/pkg/analyzer/test/src/dart/element/upper_lower_bound_test.dart
@@ -2000,6 +2000,20 @@
       );
     }
   }
+
+  test_unrelated() {
+    var T1 = functionTypeNone(returnType: intNone);
+
+    _checkLeastUpperBound(T1, intNone, objectNone);
+    _checkLeastUpperBound(T1, intQuestion, objectQuestion);
+    _checkLeastUpperBound(T1, intStar, objectStar);
+
+    _checkLeastUpperBound(
+      T1,
+      futureOrNone(functionQuestion),
+      objectQuestion,
+    );
+  }
 }
 
 @reflectiveTest
@@ -2594,6 +2608,50 @@
     );
   }
 
+  /// UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+  /// UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+  test_futureOr_future() {
+    void check(DartType T1, DartType T2, DartType expected) {
+      _checkLeastUpperBound(
+        futureNone(T1),
+        futureOrNone(T2),
+        futureOrNone(expected),
+      );
+    }
+
+    check(intNone, doubleNone, numNone);
+    check(intNone, stringNone, objectNone);
+  }
+
+  /// UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+  test_futureOr_futureOr() {
+    void check(DartType T1, DartType T2, DartType expected) {
+      _checkLeastUpperBound(
+        futureOrNone(T1),
+        futureOrNone(T2),
+        futureOrNone(expected),
+      );
+    }
+
+    check(intNone, doubleNone, numNone);
+    check(intNone, stringNone, objectNone);
+  }
+
+  /// UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+  /// UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
+  test_futureOr_other() {
+    void check(DartType T1, DartType T2, DartType expected) {
+      _checkLeastUpperBound(
+        futureOrNone(T1),
+        T2,
+        futureOrNone(expected),
+      );
+    }
+
+    check(intNone, doubleNone, numNone);
+    check(intNone, stringNone, objectNone);
+  }
+
   test_identical() {
     void check(DartType type) {
       _checkLeastUpperBound(type, type, type);
@@ -2943,7 +3001,7 @@
     _checkLeastUpperBound(
       S_none,
       typeParameterTypeNone(U),
-      interfaceTypeNone(A, typeArguments: [objectNone]),
+      interfaceTypeNone(A, typeArguments: [objectQuestion]),
     );
   }
 
@@ -2983,14 +3041,22 @@
     _checkLeastUpperBound(typeT, C_none, A_none);
   }
 
-  void test_typeParameter_interface_noBound() {
+  void test_typeParameter_interface_bounded_objectQuestion() {
     var T = typeParameter('T', bound: objectQuestion);
 
-    var A = class_(name: 'A');
-
     _checkLeastUpperBound(
       typeParameterTypeNone(T),
-      interfaceTypeNone(A),
+      intNone,
+      objectQuestion,
+    );
+  }
+
+  void test_typeParameter_interface_noBound() {
+    var T = typeParameter('T');
+
+    _checkLeastUpperBound(
+      typeParameterTypeNone(T),
+      intNone,
       objectQuestion,
     );
   }
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 3e90ad5..250b588 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -22,7 +22,8 @@
 class FileResolutionTest with ResourceProviderMixin, ResolutionTest {
   static final String _testFile = '/workspace/dart/test/lib/test.dart';
 
-  final CiderByteStore byteStore = CiderMemoryByteStore();
+  final CiderByteStore byteStore =
+      CiderCachedByteStore(20 * 1024 * 1024 /* 20 MB */);
 
   final StringBuffer logBuffer = StringBuffer();
   PerformanceLog logger;
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index ae592bc..45500b8 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer/src/dart/micro/libraries_log.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:matcher/matcher.dart';
@@ -23,6 +25,10 @@
   String bPath;
   String cPath;
 
+  String get _asyncLibraryPath => futureElement.library.source.fullName;
+
+  String get _coreLibraryPath => intElement.library.source.fullName;
+
   @override
   void setUp() {
     super.setUp();
@@ -31,6 +37,57 @@
     cPath = convertPath('/workspace/dart/test/lib/c.dart');
   }
 
+  test_changeFile_log() async {
+    newFile(aPath, content: r'''
+class A {}
+''');
+
+    newFile(bPath, content: r'''
+import 'a.dart';
+A a;
+B b;
+''');
+
+    result = await resolveFile(bPath);
+    assertErrorsInResolvedUnit(result, [
+      error(CompileTimeErrorCode.UNDEFINED_CLASS, 22, 1),
+    ]);
+
+    newFile(aPath, content: r'''
+class A {}
+class B {}
+''');
+    fileResolver.changeFile(aPath);
+
+    result = await resolveFile(bPath);
+    assertErrorsInResolvedUnit(result, []);
+
+    // The failure of this check will be reported badly.
+    expect(fileResolver.librariesLogEntries, [
+      predicate((LoadLibrariesForTargetLogEntry entry) {
+        expect(entry.target.path, bPath);
+        var loadedPathSet = entry.loaded.map((f) => f.path).toSet();
+        expect(loadedPathSet, contains(aPath));
+        expect(loadedPathSet, contains(bPath));
+        expect(loadedPathSet, contains(_asyncLibraryPath));
+        expect(loadedPathSet, contains(_coreLibraryPath));
+        return true;
+      }),
+      predicate((ChangeFileLoadEntry entry) {
+        expect(entry.target, aPath);
+        var removedPathSet = entry.removed.map((f) => f.path).toSet();
+        expect(removedPathSet, {aPath, bPath});
+        return true;
+      }),
+      predicate((LoadLibrariesForTargetLogEntry entry) {
+        expect(entry.target.path, bPath);
+        var loadedPathSet = entry.loaded.map((f) => f.path).toSet();
+        expect(loadedPathSet, {aPath, bPath});
+        return true;
+      }),
+    ]);
+  }
+
   test_changeFile_refreshedFiles() async {
     newFile(aPath, content: r'''
 class A {}
@@ -214,6 +271,9 @@
 
 @reflectiveTest
 class FileResolverTest extends FileResolutionTest {
+  @override
+  bool typeToStringWithNullability = false;
+
   test_analysisOptions_default_fromPackageUri() async {
     newFile('/workspace/dart/analysis_options/lib/default.yaml', content: r'''
 analyzer:
@@ -252,6 +312,13 @@
     implicit-casts: false
 ''');
 
+    newFile('/workspace/thid_party/dart/aaa/analysis_options.yaml',
+        content: r'''
+analyzer:
+  strong-mode:
+    implicit-casts: true
+''');
+
     var aPath = convertPath('/workspace/third_party/dart/aaa/lib/a.dart');
     await assertErrorsInFile(aPath, r'''
 num a = 0;
@@ -397,6 +464,44 @@
     ]);
   }
 
+  test_nullSafety_enabled() async {
+    typeToStringWithNullability = true;
+
+    newFile('/workspace/dart/test/BUILD', content: r'''
+dart_package(
+  null_safety = True,
+)
+''');
+
+    await assertNoErrorsInCode(r'''
+void f(int? a) {
+  if (a != null) {
+    a.isEven;
+  }
+}
+''');
+
+    assertType(
+      findElement.parameter('a').type,
+      'int?',
+    );
+  }
+
+  test_nullSafety_notEnabled() async {
+    typeToStringWithNullability = true;
+
+    await assertErrorsInCode(r'''
+void f(int? a) {}
+''', [
+      error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 10, 1),
+    ]);
+
+    assertType(
+      findElement.parameter('a').type,
+      'int*',
+    );
+  }
+
   test_resolve_part_of() async {
     newFile('/workspace/dart/test/lib/a.dart', content: r'''
 part 'test.dart';
@@ -475,6 +580,21 @@
     ]);
   }
 
+  test_switchCase_implementsEquals_enum() async {
+    await assertNoErrorsInCode(r'''
+enum MyEnum {a, b, c}
+
+void f(MyEnum myEnum) {
+  switch (myEnum) {
+    case MyEnum.a:
+      break;
+    default:
+      break;
+  }
+}
+''');
+  }
+
   test_unknown_uri() async {
     await assertErrorsInCode(r'''
 import 'foo:bar';
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index d8b9392..3c5983e 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -352,7 +352,6 @@
 ''', [
       error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 35, 5),
       error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 35, 5),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 44, 1),
     ]);
 
     var assignment = findNode.assignment('= c');
@@ -362,11 +361,8 @@
       readType: 'dynamic',
       writeElement: null,
       writeType: 'dynamic',
-      operatorElement: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isNullSafetySdkAndLegacyLibrary,
-      ),
-      type: 'double',
+      operatorElement: null,
+      type: 'dynamic',
     );
 
     assertElement(findNode.simple('a +'), findElement.parameter('a'));
@@ -382,7 +378,6 @@
 ''', [
       error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 35, 7),
       error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 35, 7),
-      error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 46, 1),
     ]);
 
     var assignment = findNode.assignment('= c');
@@ -392,11 +387,8 @@
       readType: 'dynamic',
       writeElement: null,
       writeType: 'dynamic',
-      operatorElement: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isNullSafetySdkAndLegacyLibrary,
-      ),
-      type: 'double',
+      operatorElement: null,
+      type: 'dynamic',
     );
   }
 
@@ -461,11 +453,8 @@
       readType: 'dynamic',
       writeElement: null,
       writeType: 'dynamic',
-      operatorElement: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isNullSafetySdkAndLegacyLibrary,
-      ),
-      type: 'num',
+      operatorElement: null,
+      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
@@ -477,21 +466,14 @@
   }
 
   test_notLValue_postfixIncrement_compound_ifNull() async {
-    await assertErrorsInCode(
-      '''
+    await assertErrorsInCode('''
 void f(num x, int y) {
   x++ ??= y;
 }
-''',
-      expectedErrorsByNullability(nullable: [
-        error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
-        error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
-        error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
-      ], legacy: [
-        error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
-        error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
-      ]),
-    );
+''', [
+      error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
+    ]);
 
     assertAssignment(
       findNode.assignment('= y'),
@@ -555,11 +537,8 @@
       readType: 'dynamic',
       writeElement: null,
       writeType: 'dynamic',
-      operatorElement: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isNullSafetySdkAndLegacyLibrary,
-      ),
-      type: 'num',
+      operatorElement: null,
+      type: 'dynamic',
     );
 
     assertSimpleIdentifier(
@@ -571,21 +550,14 @@
   }
 
   test_notLValue_prefixIncrement_compound_ifNull() async {
-    await assertErrorsInCode(
-      '''
+    await assertErrorsInCode('''
 void f(num x, int y) {
   ++x ??= y;
 }
-''',
-      expectedErrorsByNullability(nullable: [
-        error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
-        error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
-        error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
-      ], legacy: [
-        error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
-        error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
-      ]),
-    );
+''', [
+      error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 25, 3),
+      error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 25, 3),
+    ]);
 
     assertAssignment(
       findNode.assignment('= y'),
@@ -1122,6 +1094,43 @@
     assertType(assignment.rightHandSide, 'int');
   }
 
+  test_propertyAccess_instance_fromMixins_compound() async {
+    await assertNoErrorsInCode('''
+class M1 {
+  int get x => 0;
+  set x(num _) {}
+}
+
+class M2 {
+  int get x => 0;
+  set x(num _) {}
+}
+
+class C with M1, M2 {
+}
+
+void f(C c) {
+  (c).x += 2;
+}
+''');
+
+    var assignment = findNode.assignment('x += 2');
+    assertAssignment(
+      assignment,
+      readElement: findElement.getter('x', of: 'M2'),
+      readType: 'int',
+      writeElement: findElement.setter('x', of: 'M2'),
+      writeType: 'num',
+      operatorElement: elementMatcher(
+        numElement.getMethod('+'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      type: 'int',
+    );
+
+    assertType(assignment.rightHandSide, 'int');
+  }
+
   test_propertyAccess_instance_simple() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -1803,7 +1812,7 @@
 
   test_simpleIdentifier_parameter_compound_refineType_int_int() async {
     await assertNoErrorsInCode(r'''
-main(int x) {
+void f(int x) {
   x += 1;
   x -= 1;
   x *= 1;
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index 38ca656..b484064 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -735,7 +735,7 @@
 
   test_ifNull_nullableInt_int() async {
     await assertNoErrorsInCode(r'''
-main(int? x, int y) {
+void f(int? x, int y) {
   x ?? y;
 }
 ''');
@@ -749,7 +749,7 @@
 
   test_ifNull_nullableInt_nullableDouble() async {
     await assertNoErrorsInCode(r'''
-main(int? x, double? y) {
+void f(int? x, double? y) {
   x ?? y;
 }
 ''');
@@ -763,7 +763,7 @@
 
   test_ifNull_nullableInt_nullableInt() async {
     await assertNoErrorsInCode(r'''
-main(int? x) {
+void f(int? x) {
   x ?? x;
 }
 ''');
@@ -776,11 +776,11 @@
   }
 
   test_plus_int_never() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 f(int a, Never b) {
   a + b;
 }
-''', []);
+''');
 
     assertBinaryExpression(findNode.binary('a + b'),
         element: numElement.getMethod('+'), type: 'num');
diff --git a/pkg/analyzer/test/src/dart/resolution/constant_test.dart b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
index cfe11e5..34b271d 100644
--- a/pkg/analyzer/test/src/dart/resolution/constant_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/constant_test.dart
@@ -232,6 +232,25 @@
     var a = findElement.topVar('a') as ConstVariableElement;
     expect(a.computeConstantValue().toIntValue(), 42);
   }
+
+  /// See https://github.com/dart-lang/sdk/issues/43462
+  test_useLanguageVersionOfEnclosingLibrary() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class Wrapper {
+  final int value;
+  const Wrapper(Object value) : value = value as int;
+}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart = 2.4
+import 'a.dart';
+
+void f() {
+  const Wrapper(0);
+}
+''');
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 4e85656..4c28ad0 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -24,6 +24,7 @@
 import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 
+import 'context_collection_resolution_caching.dart';
 import 'resolution.dart';
 
 class AnalysisOptionsFileConfig {
@@ -127,7 +128,7 @@
     with ResourceProviderMixin, ResolutionTest {
   static bool _lintRulesAreRegistered = false;
 
-  final ByteStore _byteStore = MemoryByteStore();
+  ByteStore _byteStore = getContextResolutionTestByteStore();
 
   Map<String, String> _declaredVariables = {};
   AnalysisContextCollection _analysisContextCollection;
@@ -218,6 +219,12 @@
     );
   }
 
+  /// Call this method if the test needs to use the empty byte store, without
+  /// any information cached.
+  void useEmptyByteStore() {
+    _byteStore = MemoryByteStore();
+  }
+
   void verifyCreatedCollection() {}
 
   /// Create all analysis contexts in [collectionIncludedPaths].
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution_caching.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution_caching.dart
new file mode 100644
index 0000000..9f2dc62
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution_caching.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
+
+final _sharedByteStore = MemoryByteStore();
+final _useSharedByteStore = false;
+
+ByteStore getContextResolutionTestByteStore() {
+  if (_useSharedByteStore) {
+    return _sharedByteStore;
+  } else {
+    return MemoryByteStore();
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart b/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
index 9bf497b..ddcd447 100644
--- a/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/extension_override_test.dart
@@ -593,6 +593,7 @@
       if (access.propertyName.inGetterContext()) {
         PropertyAccessorElement expectedGetter = extension.getGetter('s');
         Element actualGetter =
+            // ignore: deprecated_member_use_from_same_package
             access.propertyName.auxiliaryElements.staticElement;
         expect(actualGetter, expectedGetter);
       }
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index 6d80f3d..a1bfdde 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -58,7 +58,7 @@
   void call<T>(T t) {}
 }
 
-main(A a) {
+void f(A a) {
   a(0);
 }
 ''');
@@ -102,7 +102,7 @@
   }
 }
 
-main(A a, int context) {
+void f(A a, int context) {
   context = a();
 }
 ''');
@@ -124,7 +124,7 @@
   }
 }
 
-main(A a) {
+void f(A a) {
   a<int>();
 }
 ''');
@@ -140,11 +140,11 @@
 
   test_never() async {
     await assertErrorsInCode(r'''
-main(Never x) {
+void f(Never x) {
   x<int>(1 + 2);
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 18, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
     ]);
 
     assertFunctionExpressionInvocation(
@@ -160,11 +160,11 @@
 
   test_neverQ() async {
     await assertErrorsInCode(r'''
-main(Never? x) {
+void f(Never? x) {
   x<int>(1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 19, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertFunctionExpressionInvocation(
diff --git a/pkg/analyzer/test/src/dart/resolution/if_element_test.dart b/pkg/analyzer/test/src/dart/resolution/if_element_test.dart
index 785f95a..7b76cf5 100644
--- a/pkg/analyzer/test/src/dart/resolution/if_element_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/if_element_test.dart
@@ -17,7 +17,7 @@
 class IfElementTest extends PubPackageResolutionTest {
   test_condition_rewrite() async {
     await assertNoErrorsInCode(r'''
-main(bool Function() b) {
+void f(bool Function() b) {
   <int>[if ( b() ) 0];
 }
 ''');
diff --git a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
index a297211..77238af 100644
--- a/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/index_expression_test.dart
@@ -22,7 +22,7 @@
   bool operator[](int index) => false;
 }
 
-main(A a) {
+void f(A a) {
   a[0];
 }
 ''');
@@ -48,7 +48,7 @@
   T operator[](int index) => throw 42;
 }
 
-main(A<double> a) {
+void f(A<double> a) {
   a[0];
 }
 ''');
@@ -78,7 +78,7 @@
   void operator[]=(int index, num value) {}
 }
 
-main(A a) {
+void f(A a) {
   a[0] += 1.2;
 }
 ''');
@@ -125,7 +125,7 @@
   void operator[]=(int index, T value) {}
 }
 
-main(A<double> a) {
+void f(A<double> a) {
   a[0] += 1.2;
 }
 ''');
@@ -183,7 +183,7 @@
   void operator[]=(int index, num value) {}
 }
 
-main(A a) {
+void f(A a) {
   a[0] = 1.2;
 }
 ''');
@@ -221,7 +221,7 @@
   void operator[]=(int index, T value) {}
 }
 
-main(A<double> a) {
+void f(A<double> a) {
   a[0] = 1.2;
 }
 ''');
@@ -269,7 +269,7 @@
   bool operator[](int index) => false;
 }
 
-main(A? a) {
+void f(A? a) {
   a?..[0]..[1];
 }
 ''');
@@ -299,7 +299,7 @@
   bool operator[](int index) => false;
 }
 
-main(A? a) {
+void f(A? a) {
   a?[0];
 }
 ''');
@@ -322,7 +322,7 @@
   void operator[]=(int index, num value) {}
 }
 
-main(A? a) {
+void f(A? a) {
   a?[0] += 1.2;
 }
 ''');
@@ -365,7 +365,7 @@
   void operator[]=(int index, A a) {}
 }
 
-main(A? a) {
+void f(A? a) {
   a?..[0] = a..[1] = a;
 }
 ''');
@@ -395,7 +395,7 @@
   void operator[]=(int index, num value) {}
 }
 
-main(A? a) {
+void f(A? a) {
   a?[0] = 1.2;
 }
 ''');
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index d9eda13..a51df3a 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -9,12 +9,36 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InstanceCreationDriverResolutionTest);
+    defineReflectiveTests(InstanceCreationTest);
+    defineReflectiveTests(InstanceCreationWithNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class InstanceCreationDriverResolutionTest extends PubPackageResolutionTest {
+class InstanceCreationTest extends PubPackageResolutionTest
+    with InstanceCreationTestCases {}
+
+mixin InstanceCreationTestCases on PubPackageResolutionTest {
+  test_demoteType() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  A(T t);
+}
+
+void f<S>(S s) {
+  if (s is int) {
+    A(s);
+  }
+}
+
+''');
+
+    assertType(
+      findNode.instanceCreation('A(s)'),
+      'A<S>',
+    );
+  }
+
   test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async {
     await assertErrorsInCode(r'''
 final foo = Map<int>();
@@ -147,3 +171,7 @@
     );
   }
 }
+
+@reflectiveTest
+class InstanceCreationWithNullSafetyTest extends PubPackageResolutionTest
+    with WithNullSafetyMixin, InstanceCreationTestCases {}
diff --git a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
index 3545088..7e27085 100644
--- a/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/local_variable_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -30,9 +28,7 @@
 }
 ''');
 
-    var type = findNode.simple('o; // ref').staticType;
-    assertType(type, 'T');
-    _assertPromotedBound(type, isNull);
+    assertType(findNode.simple('o; // ref'), 'T');
   }
 
   test_element_block() async {
@@ -99,12 +95,6 @@
     expect(x.isLate, isFalse);
     expect(x.isStatic, isFalse);
   }
-
-  void _assertPromotedBound(DartType type, Matcher promotedBound) {
-    if (type is TypeParameterTypeImpl) {
-      expect(type.promotedBound, promotedBound);
-    }
-  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index e9936dd..18dc935 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -393,6 +393,24 @@
         expectedType: 'String');
   }
 
+  test_demoteType() async {
+    await assertNoErrorsInCode(r'''
+void test<T>(T t) {}
+
+void f<S>(S s) {
+  if (s is int) {
+    test(s);
+  }
+}
+
+''');
+
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('test(s)'),
+      ['S'],
+    );
+  }
+
   test_error_ambiguousImport_topFunction() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 void foo(int _) {}
@@ -447,11 +465,11 @@
   static void foo(int _) {}
 }
 
-main(A a) {
+void f(A a) {
   a.foo(0);
 }
 ''', [
-      error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 57, 3),
+      error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 59, 3),
     ]);
     assertMethodInvocation2(
       findNode.methodInvocation('a.foo(0)'),
@@ -468,11 +486,11 @@
   void Function() call = throw Error();
 }
 
-main(C c) {
+void f(C c) {
   c();
 }
 ''', [
-      error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 67, 1),
+      error(CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, 69, 1),
     ]);
 
     var invocation = findNode.functionExpressionInvocation('c();');
@@ -491,7 +509,7 @@
   var foo;
 }
 
-main(C c) {
+void f(C c) {
   c.foo();
 }
 ''');
@@ -921,8 +939,9 @@
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE, 11, 4),
-      error(CompileTimeErrorCode.UNDEFINED_METHOD, 16, 3),
+        error(CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE, 11, 4)
+      else
+        error(CompileTimeErrorCode.UNDEFINED_METHOD, 16, 3),
     ]);
     _assertUnresolvedMethodInvocation('foo();');
   }
@@ -1071,13 +1090,13 @@
   C(this.foo);
 }
 
-main(C<void> c) {
+void f(C<void> c) {
   c.foo();
 }
 ''', [
       if (typeToStringWithNullability)
-        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 59, 5),
-      error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 59, 5),
+        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 61, 5),
+      error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 61, 5),
     ]);
 
     var invocation = findNode.functionExpressionInvocation('foo();');
@@ -1164,11 +1183,12 @@
 ''', [
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 23, 3),
     ]);
-    // TODO(scheglov) Resolve fully, or don't resolve at all.
-    assertMethodInvocation(
+    assertMethodInvocation2(
       findNode.methodInvocation('toString()'),
-      null,
-      'String Function()',
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
     );
   }
 
@@ -1181,16 +1201,16 @@
 ''', [
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 23, 3),
     ]);
-    // TODO(scheglov) Resolve fully, or don't resolve at all.
-    assertMethodInvocation(
+    assertMethodInvocation2(
       findNode.methodInvocation('toString()'),
-      null,
-      'String Function()',
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
     );
   }
 
   test_error_useOfVoidResult_receiver_withNull() async {
-    var question = typeToStringWithNullability ? '?' : '';
     await assertErrorsInCode(r'''
 main() {
   void foo;
@@ -1199,12 +1219,12 @@
 ''', [
       error(CompileTimeErrorCode.USE_OF_VOID_RESULT, 23, 3),
     ]);
-    // TODO(scheglov) Resolve fully, or don't resolve at all.
-    assertMethodInvocation(
+    assertMethodInvocation2(
       findNode.methodInvocation('toString()'),
-      null,
-      'String Function()',
-      expectedType: 'String$question',
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
     );
   }
 
@@ -1428,7 +1448,7 @@
 
   test_hasReceiver_instance_Function_call_localVariable() async {
     await assertNoErrorsInCode(r'''
-void main(Function getFunction()) {
+void f(Function getFunction()) {
   Function foo = getFunction();
 
   foo.call(0);
@@ -1454,7 +1474,7 @@
   double Function(int) get foo => throw Error();
 }
 
-main(C c) {
+void f(C c) {
   c.foo(0);
 }
 ''');
@@ -1476,7 +1496,7 @@
   void foo(int _) {}
 }
 
-main(C c) {
+void f(C c) {
   c.foo(0);
 }
 ''');
@@ -1499,7 +1519,7 @@
   }
 }
 
-main(C c) {
+void f(C c) {
   c.foo(0);
 }
 ''');
@@ -1531,7 +1551,7 @@
   void foo(Object o) {}
 }
 
-void main(C c) {
+void f(C c) {
   c.foo('hi');
 }
 ''');
@@ -1777,7 +1797,7 @@
   void call(int _) {}
 }
 
-main(C c) {
+void f(C c) {
   c(0);
 }
 ''');
@@ -1854,7 +1874,7 @@
 
   test_noReceiver_parameter() async {
     await assertNoErrorsInCode(r'''
-main(void Function(int) foo) {
+void f(void Function(int) foo) {
   foo(0);
 }
 ''');
@@ -1943,14 +1963,39 @@
     assertType(foo, 'void Function(int)');
   }
 
-  test_objectMethodOnDynamic() async {
+  test_objectMethodOnDynamic_argumentsDontMatch() async {
     await assertNoErrorsInCode(r'''
-main() {
-  var v;
-  v.toString(42);
+void f(a, int b) {
+  a.toString(b);
 }
 ''');
-    _assertUnresolvedMethodInvocation('toString(42);');
+    assertMethodInvocation2(
+      findNode.methodInvocation('toString(b)'),
+      element: null,
+      typeArgumentTypes: [],
+      invokeType: 'dynamic',
+      type: 'dynamic',
+    );
+
+    assertType(findNode.simple('b);'), 'int');
+  }
+
+  test_objectMethodOnDynamic_argumentsMatch() async {
+    await assertNoErrorsInCode(r'''
+void f(a) {
+  a.toString();
+}
+''');
+    assertMethodInvocation2(
+      findNode.methodInvocation('toString()'),
+      element: elementMatcher(
+        objectElement.getMethod('toString'),
+        isLegacy: isNullSafetySdkAndLegacyLibrary,
+      ),
+      typeArgumentTypes: [],
+      invokeType: 'String Function()',
+      type: 'String',
+    );
   }
 
   test_objectMethodOnFunction() async {
@@ -2287,7 +2332,7 @@
 
   test_hasReceiver_interfaceQ_Function_call_checked() async {
     await assertNoErrorsInCode(r'''
-void main(Function? foo) {
+void f(Function? foo) {
   foo?.call();
 }
 ''');
@@ -2303,11 +2348,11 @@
 
   test_hasReceiver_interfaceQ_Function_call_unchecked() async {
     await assertErrorsInCode(r'''
-void main(Function? foo) {
+void f(Function? foo) {
   foo.call();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 29, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 3),
     ]);
 
     assertMethodInvocation2(
@@ -2354,11 +2399,11 @@
   void foo() {}
 }
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 44, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 46, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2380,11 +2425,11 @@
   void foo() {}
 }
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 82, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 84, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2406,7 +2451,7 @@
   void foo() {}
 }
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''');
@@ -2426,7 +2471,7 @@
   T foo() => throw 0;
 }
 
-main(int? a) {
+void f(int? a) {
   a.foo();
 }
 ''');
@@ -2447,12 +2492,11 @@
     await assertErrorsInCode(r'''
 class A {}
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 27, 1),
-      error(CompileTimeErrorCode.UNDEFINED_METHOD, 29, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 29, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2472,12 +2516,11 @@
   void foo() {}
 }
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 65, 1),
-      error(CompileTimeErrorCode.UNDEFINED_METHOD, 67, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 67, 1),
     ]);
 
     assertMethodInvocation2(
@@ -2497,7 +2540,7 @@
   void foo() {}
 }
 
-main(A? a) {
+void f(A? a) {
   a.foo();
 }
 ''');
@@ -2511,6 +2554,24 @@
     );
   }
 
+  test_hasReceiver_typeParameter_promotedToNonNullable() async {
+    await assertNoErrorsInCode('''
+void f<T>(T? t) {
+  if (t is int) {
+    t.abs();
+  }
+}
+''');
+
+    assertMethodInvocation2(
+      findNode.methodInvocation('t.abs()'),
+      element: intElement.getMethod('abs'),
+      typeArgumentTypes: [],
+      invokeType: 'int Function()',
+      type: 'int',
+    );
+  }
+
   test_nullShorting_cascade_firstMethodInvocation() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -2518,7 +2579,7 @@
   int bar() => 0;
 }
 
-main(A? a) {
+void f(A? a) {
   a?..foo()..bar();
 }
 ''');
@@ -2549,7 +2610,7 @@
   int bar() => 0;
 }
 
-main(A? a) {
+void f(A? a) {
   a?..foo..bar();
 }
 ''');
@@ -2601,4 +2662,34 @@
 
     assertType(findNode.cascade('A()'), 'A');
   }
+
+  test_typeArgumentTypes_generic_inferred_leftTop_dynamic() async {
+    await assertNoErrorsInCode('''
+void foo<T extends Object>(T? value) {}
+
+void f(dynamic o) {
+  foo(o);
+}
+''');
+
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo(o)'),
+      ['Object'],
+    );
+  }
+
+  test_typeArgumentTypes_generic_inferred_leftTop_void() async {
+    await assertNoErrorsInCode('''
+void foo<T extends Object>(List<T?> value) {}
+
+void f(List<void> o) {
+  foo(o);
+}
+''');
+
+    assertTypeArgumentTypes(
+      findNode.methodInvocation('foo(o)'),
+      ['Object'],
+    );
+  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 08048f9..c705570 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -164,13 +164,13 @@
 
   test_local_typeParameter() async {
     await assertErrorsInCode('''
-main<T>(T a) {
+void f<T>(T a) {
   T x = a;
   T? y;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 1),
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 31, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 21, 1),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 33, 1),
     ]);
 
     assertType(findNode.typeName('T x'), 'T');
@@ -290,7 +290,7 @@
 
   test_parameter_genericFunctionType() async {
     await assertNoErrorsInCode('''
-main(int? Function(bool, String?)? a) {
+void f(int? Function(bool, String?)? a) {
 }
 ''');
 
@@ -302,8 +302,8 @@
 
   test_parameter_getterNullAwareAccess_interfaceType() async {
     await assertNoErrorsInCode(r'''
-main(int? x) {
-  return x?.isEven;
+void f(int? x) {
+  x?.isEven;
 }
 ''');
 
@@ -312,7 +312,7 @@
 
   test_parameter_interfaceType() async {
     await assertNoErrorsInCode('''
-main(int? a, int b) {
+void f(int? a, int b) {
 }
 ''');
 
@@ -322,7 +322,7 @@
 
   test_parameter_interfaceType_generic() async {
     await assertNoErrorsInCode('''
-main(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
+void f(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
 }
 ''');
 
@@ -338,8 +338,8 @@
   bool x() => true;
 }
 
-main(C? c) {
-  return c?.x();
+void f(C? c) {
+  c?.x();
 }
 ''');
 
@@ -348,7 +348,7 @@
 
   test_parameter_nullCoalesceAssign_nullableInt_int() async {
     await assertNoErrorsInCode(r'''
-main(int? x, int y) {
+void f(int? x, int y) {
   x ??= y;
 }
 ''');
@@ -357,7 +357,7 @@
 
   test_parameter_nullCoalesceAssign_nullableInt_nullableInt() async {
     await assertNoErrorsInCode(r'''
-main(int? x) {
+void f(int? x) {
   x ??= x;
 }
 ''');
@@ -366,7 +366,7 @@
 
   test_parameter_typeParameter() async {
     await assertNoErrorsInCode('''
-main<T>(T a, T? b) {
+void f<T>(T a, T? b) {
 }
 ''');
 
@@ -409,7 +409,7 @@
     await assertNoErrorsInCode('''
 typedef F<T> = int Function(T)?;
 
-main(F<int> a, F<double>? b) {}
+void f(F<int> a, F<double>? b) {}
 ''');
 
     assertType(findNode.typeName('F<int>'), 'int Function(int)?');
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 3cfa0ac..61a0e67 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -3,10 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'context_collection_resolution.dart';
@@ -141,7 +139,27 @@
     );
   }
 
-  test_inc_notLValue_typeLiteral_typeParameter() async {
+  test_inc_notLValue_simpleIdentifier_typeLiteral() async {
+    await assertErrorsInCode(r'''
+void f() {
+  int++;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
+    ]);
+
+    assertPostfixExpression(
+      findNode.postfix('int++'),
+      readElement: intElement,
+      readType: 'dynamic',
+      writeElement: intElement,
+      writeType: 'dynamic',
+      element: null,
+      type: 'dynamic',
+    );
+  }
+
+  test_inc_notLValue_simpleIdentifier_typeLiteral_typeParameter() async {
     await assertErrorsInCode(r'''
 void f<T>() {
   T++;
@@ -153,7 +171,7 @@
     var postfix = findNode.postfix('T++');
     assertPostfixExpression(
       postfix,
-      readElement: null,
+      readElement: findElement.typeParameter('T'),
       readType: 'dynamic',
       writeElement: findElement.typeParameter('T'),
       writeType: 'dynamic',
@@ -165,7 +183,7 @@
       postfix.operand,
       readElement: findElement.typeParameter('T'),
       writeElement: findElement.typeParameter('T'),
-      type: 'Type',
+      type: 'dynamic',
     );
   }
 
@@ -474,26 +492,6 @@
       type: 'num',
     );
   }
-
-  test_inc_simpleIdentifier_typeLiteral() async {
-    await assertErrorsInCode(r'''
-void f() {
-  int++;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
-    ]);
-
-    assertPostfixExpression(
-      findNode.postfix('int++'),
-      readElement: null,
-      readType: 'dynamic',
-      writeElement: intElement,
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
-  }
 }
 
 @reflectiveTest
@@ -641,6 +639,67 @@
     );
   }
 
+  /// See https://github.com/dart-lang/language/issues/1163
+  test_nullCheck_participatesNullShorting() async {
+    await assertErrorsInCode('''
+class A {
+  int zero;
+  int? zeroOrNull;
+
+  A(this.zero, [this.zeroOrNull]);
+}
+
+void test1(A? a) => a?.zero!;
+void test2(A? a) => a?.zeroOrNull!;
+void test3(A? a) => a?.zero!.isEven;
+void test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+
+  Foo(this.bar);
+
+  Bar? operator [](int? index) => null;
+}
+
+class Bar {
+  int baz;
+
+  Bar(this.baz);
+
+  int operator [](int index) => index;
+}
+
+void test5(Foo? foo) => foo?.bar!;
+void test6(Foo? foo) => foo?.bar!.baz;
+void test7(Foo? foo, int a) => foo?.bar![a];
+void test8(Foo? foo, int? a) => foo?[a]!;
+void test9(Foo? foo, int? a) => foo?[a]!.baz;
+void test10(Foo? foo, int? a, int b) => foo?[a]![b];
+''', [
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 107, 1),
+      error(StaticWarningCode.UNNECESSARY_NON_NULL_ASSERTION, 173, 1),
+    ]);
+
+    void assertTestType(int index, String expected) {
+      var function = findNode.functionDeclaration('test$index(');
+      var body = function.functionExpression.body as ExpressionFunctionBody;
+      assertType(body.expression, expected);
+    }
+
+    assertTestType(1, 'int?');
+    assertTestType(2, 'int?');
+    assertTestType(3, 'bool?');
+    assertTestType(4, 'bool?');
+
+    assertTestType(5, 'Bar?');
+    assertTestType(6, 'int?');
+    assertTestType(7, 'int?');
+    assertTestType(8, 'Bar?');
+    assertTestType(9, 'int?');
+    assertTestType(10, 'int?');
+  }
+
   test_nullCheck_superExpression() async {
     await assertErrorsInCode(r'''
 class A {
@@ -692,14 +751,8 @@
       writeElement: null,
       writeType: null,
       element: null,
-      type: 'T',
+      type: 'T & Object',
     );
-    expect(
-        postfixExpression.staticType,
-        TypeMatcher<TypeParameterType>().having(
-            (t) => t.bound.getDisplayString(withNullability: true),
-            'bound',
-            'Object'));
   }
 
   test_nullCheck_typeParameter_already_promoted() async {
@@ -719,13 +772,7 @@
       writeElement: null,
       writeType: null,
       element: null,
-      type: 'T',
+      type: 'T & num',
     );
-    expect(
-        postfixExpression.staticType,
-        TypeMatcher<TypeParameterType>().having(
-            (t) => t.bound.getDisplayString(withNullability: true),
-            'bound',
-            'num'));
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 14ddc4ca..b6b4dec 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -215,6 +215,26 @@
     );
   }
 
+  test_plusPlus_notLValue_simpleIdentifier_typeLiteral() async {
+    await assertErrorsInCode(r'''
+void f() {
+  ++int;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 15, 3),
+    ]);
+
+    assertPrefixExpression(
+      findNode.prefix('++int'),
+      readElement: intElement,
+      readType: 'dynamic',
+      writeElement: intElement,
+      writeType: 'dynamic',
+      element: null,
+      type: 'dynamic',
+    );
+  }
+
   test_plusPlus_prefixedIdentifier_instance() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -580,26 +600,6 @@
     );
   }
 
-  test_plusPlus_simpleIdentifier_typeLiteral() async {
-    await assertErrorsInCode(r'''
-void f() {
-  ++int;
-}
-''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 15, 3),
-    ]);
-
-    assertPrefixExpression(
-      findNode.prefix('++int'),
-      readElement: null,
-      readType: 'dynamic',
-      writeElement: intElement,
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
-  }
-
   /// Verify that we get all necessary types when building the dependencies
   /// graph during top-level inference.
   test_plusPlus_topLevelInference() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
index ed5052e..2d0516f 100644
--- a/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/property_access_test.dart
@@ -440,6 +440,62 @@
     );
   }
 
+  test_targetTypeParameter_dynamicBounded() async {
+    await assertNoErrorsInCode('''
+class A<T extends dynamic> {
+  void f(T t) {
+    (t).foo;
+  }
+}
+''');
+
+    var propertyAccess = findNode.propertyAccess('.foo');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: null,
+      type: 'dynamic',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: null,
+      type: 'dynamic',
+    );
+  }
+
+  test_targetTypeParameter_noBound() async {
+    await resolveTestCode('''
+class C<T> {
+  void f(T t) {
+    (t).foo;
+  }
+}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(
+      nullable: [
+        error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 33, 3),
+      ],
+      legacy: [
+        error(CompileTimeErrorCode.UNDEFINED_GETTER, 37, 3),
+      ],
+    ));
+
+    var propertyAccess = findNode.propertyAccess('.foo');
+    assertPropertyAccess2(
+      propertyAccess,
+      element: null,
+      type: 'dynamic',
+    );
+
+    assertSimpleIdentifier(
+      propertyAccess.propertyName,
+      readElement: null,
+      writeElement: null,
+      type: 'dynamic',
+    );
+  }
+
   test_tearOff_method() async {
     await assertNoErrorsInCode('''
 class A {
@@ -489,7 +545,7 @@
   int get bar => 0;
 }
 
-main(A? a) {
+void f(A? a) {
   a?..foo..bar;
 }
 ''');
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index cb4d4f8..2fdf8ba 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -112,23 +112,6 @@
     assertType(node, type);
   }
 
-  void assertAuxElement(AstNode node, Element expected) {
-    var auxElements = getNodeAuxElements(node);
-    expect(auxElements?.staticElement, same(expected));
-  }
-
-  void assertAuxMember(
-    Expression node,
-    Element expectedBase,
-    Map<String, String> expectedSubstitution,
-  ) {
-    var actual = getNodeAuxElements(node)?.staticElement as ExecutableMember;
-
-    expect(actual.declaration, same(expectedBase));
-
-    assertSubstitution(actual.substitution, expectedSubstitution);
-  }
-
   void assertBinaryExpression(
     BinaryExpression node, {
     @required Object element,
@@ -350,6 +333,17 @@
     assertType(node, type);
   }
 
+  /// We have a contract with the Angular team that FunctionType(s) from
+  /// typedefs carry the element of the typedef, and the type arguments.
+  void assertFunctionTypeTypedef(
+    FunctionType type, {
+    @required FunctionTypeAliasElement element,
+    @required List<String> typeArguments,
+  }) {
+    assertElement2(type.element, declaration: element.function);
+    assertElementTypeStrings(type.typeArguments, typeArguments);
+  }
+
   void assertHasTestErrors() {
     expect(result.errors, isNotEmpty);
   }
@@ -386,6 +380,7 @@
     var isRead = node.inGetterContext();
     var isWrite = node.inSetterContext();
     if (isRead && isWrite) {
+      // ignore: deprecated_member_use_from_same_package
       assertElement(node.auxiliaryElements?.staticElement, readElement);
       assertElement(node.staticElement, writeElement);
     } else if (isRead) {
@@ -708,7 +703,9 @@
 
   void assertType(Object typeOrNode, String expected) {
     DartType actual;
-    if (typeOrNode is DartType) {
+    if (typeOrNode == null) {
+      actual = typeOrNode;
+    } else if (typeOrNode is DartType) {
       actual = typeOrNode;
     } else if (typeOrNode is Expression) {
       actual = typeOrNode.staticType;
@@ -813,14 +810,6 @@
     }
   }
 
-  AuxiliaryElements getNodeAuxElements(AstNode node) {
-    if (node is IndexExpression) {
-      return node.auxiliaryElements;
-    } else {
-      fail('Unsupported node: (${node.runtimeType}) $node');
-    }
-  }
-
   Element getNodeElement(AstNode node) {
     if (node is Annotation) {
       return node.element;
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
index ac8f412..d52a86d 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -43,8 +43,8 @@
 
   test_type() async {
     await assertNoErrorsInCode('''
-main(bool b) {
-  return b ? 42 : null;
+void f(bool b) {
+  b ? 42 : null;
 }
 ''');
     assertType(findNode.conditionalExpression('b ?'), 'int?');
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
index cf8638c..43c92f8 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/extension_methods_test.dart
@@ -6,15 +6,20 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../context_collection_resolution.dart';
+import '../resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ExtensionMethodsTest);
+    defineReflectiveTests(ExtensionMethodsWithNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class ExtensionMethodsTest extends PubPackageResolutionTest {
+class ExtensionMethodsTest extends PubPackageResolutionTest
+    with ExtensionMethodsTestCases {}
+
+mixin ExtensionMethodsTestCases on ResolutionTest {
   test_implicit_getter() async {
     await assertNoErrorsInCode('''
 class A<T> {}
@@ -89,7 +94,7 @@
   Map<T, U> foo<U>(U value) => <T, U>{};
 }
 
-main(String a) {
+void f(String a) {
   a.foo(0);
 }
 ''');
@@ -150,6 +155,118 @@
     );
   }
 
+  test_implicit_targetTypeParameter_hasBound_methodInvocation() async {
+    await assertNoErrorsInCode('''
+extension Test<T> on T {
+  T Function(T) test() => throw 0;
+}
+
+void f<S extends num>(S x) {
+  x.test();
+}
+''');
+
+    if (result.libraryElement.isNonNullableByDefault) {
+      assertMethodInvocation2(
+        findNode.methodInvocation('test();'),
+        element: elementMatcher(
+          findElement.method('test'),
+          substitution: {'T': 'S'},
+        ),
+        typeArgumentTypes: [],
+        invokeType: 'S Function(S) Function()',
+        type: 'S Function(S)',
+      );
+    } else {
+      assertMethodInvocation2(
+        findNode.methodInvocation('test();'),
+        element: elementMatcher(
+          findElement.method('test'),
+          substitution: {'T': 'num'},
+        ),
+        typeArgumentTypes: [],
+        invokeType: 'num Function(num) Function()',
+        type: 'num Function(num)',
+      );
+    }
+  }
+
+  test_implicit_targetTypeParameter_hasBound_propertyAccess_getter() async {
+    await assertNoErrorsInCode('''
+extension Test<T> on T {
+  T Function(T) get test => throw 0;
+}
+
+void f<S extends num>(S x) {
+  (x).test;
+}
+''');
+
+    if (result.libraryElement.isNonNullableByDefault) {
+      assertPropertyAccess2(
+        findNode.propertyAccess('.test'),
+        element: elementMatcher(
+          findElement.getter('test'),
+          substitution: {'T': 'S'},
+        ),
+        type: 'S Function(S)',
+      );
+    } else {
+      assertPropertyAccess2(
+        findNode.propertyAccess('.test'),
+        element: elementMatcher(
+          findElement.getter('test'),
+          substitution: {'T': 'num'},
+        ),
+        type: 'num Function(num)',
+      );
+    }
+  }
+
+  test_implicit_targetTypeParameter_hasBound_propertyAccess_setter() async {
+    await assertNoErrorsInCode('''
+extension Test<T> on T {
+  void set test(T _) {}
+}
+
+T g<T>() => throw 0;
+
+void f<S extends num>(S x) {
+  (x).test = g();
+}
+''');
+
+    if (result.libraryElement.isNonNullableByDefault) {
+      assertPropertyAccess2(
+        findNode.propertyAccess('.test'),
+        element: elementMatcher(
+          findElement.setter('test'),
+          substitution: {'T': 'S'},
+        ),
+        type: 'S',
+      );
+
+      assertTypeArgumentTypes(
+        findNode.methodInvocation('g()'),
+        ['S'],
+      );
+    } else {
+      assertPropertyAccess2(
+        findNode.propertyAccess('.test'),
+        element: elementMatcher(
+          findElement.setter('test'),
+          substitution: {'T': 'num'},
+        ),
+        type: 'num',
+      );
+
+      assertTypeArgumentTypes(
+        findNode.methodInvocation('g()'),
+        ['num'],
+      );
+    }
+  }
+
   test_override_downward_hasTypeArguments() async {
     await assertNoErrorsInCode('''
 extension E<T> on Set<T> {
@@ -425,3 +542,7 @@
     );
   }
 }
+
+@reflectiveTest
+class ExtensionMethodsWithNullSafetyTest extends PubPackageResolutionTest
+    with WithNullSafetyMixin, ExtensionMethodsTestCases {}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
index 53cb664..6e1258e 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/list_literal_test.dart
@@ -273,7 +273,7 @@
     await assertNoErrorsInCode(r'''
 mixin L on List<int> {}
 
-main(L l1) {
+void f(L l1) {
   // ignore:unused_local_variable
   var l2 = [...l1];
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
index 594ad86..eb7d745 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/map_literal_test.dart
@@ -292,7 +292,7 @@
     await assertNoErrorsInCode(r'''
 mixin M on Map<String, int> {}
 
-main(M m1) {
+void f(M m1) {
   // ignore:unused_local_variable
   var m2 = {...m1};
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/type_name_test.dart b/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
index f50eea9..502c43d 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_name_test.dart
@@ -382,10 +382,15 @@
 f(F a) {}
 ''');
 
-    assertTypeName(
-      findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
-      'int* Function(bool*)*',
+    var element = import_a.functionTypeAlias('F');
+
+    var typeName = findNode.typeName('F a');
+    assertTypeName(typeName, element, 'int* Function(bool*)*');
+
+    assertFunctionTypeTypedef(
+      typeName.type,
+      element: element,
+      typeArguments: [],
     );
   }
 
@@ -401,10 +406,15 @@
 f(F a) {}
 ''');
 
-    assertTypeName(
-      findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
-      'dynamic Function(bool*)*',
+    var element = import_a.functionTypeAlias('F');
+
+    var typeName = findNode.typeName('F a');
+    assertTypeName(typeName, element, 'dynamic Function(bool*)*');
+
+    assertFunctionTypeTypedef(
+      typeName.type,
+      element: element,
+      typeArguments: ['dynamic'],
     );
   }
 
@@ -420,10 +430,15 @@
 f(F a) {}
 ''');
 
-    assertTypeName(
-      findNode.typeName('F a'),
-      import_a.functionTypeAlias('F'),
-      'num* Function(bool*)*',
+    var element = import_a.functionTypeAlias('F');
+
+    var typeName = findNode.typeName('F a');
+    assertTypeName(typeName, element, 'num* Function(bool*)*');
+
+    assertFunctionTypeTypedef(
+      typeName.type,
+      element: element,
+      typeArguments: ['num*'],
     );
   }
 
@@ -439,10 +454,15 @@
 f(F<int> a) {}
 ''');
 
-    assertTypeName(
-      findNode.typeName('F<int> a'),
-      import_a.functionTypeAlias('F'),
-      'int* Function(bool*)*',
+    var element = import_a.functionTypeAlias('F');
+
+    var typeName = findNode.typeName('F<int> a');
+    assertTypeName(typeName, element, 'int* Function(bool*)*');
+
+    assertFunctionTypeTypedef(
+      typeName.type,
+      element: element,
+      typeArguments: ['int*'],
     );
   }
 
diff --git a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
index 01403ad..db9c3b4 100644
--- a/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
+++ b/pkg/analyzer/test/src/dart/sdk/sdk_test.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
 import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -135,24 +134,6 @@
     })));
   }
 
-  void test_analysisOptions_afterContextCreation() {
-    FolderBasedDartSdk sdk = _createDartSdk();
-    sdk.context;
-    expect(() {
-      sdk.analysisOptions = AnalysisOptionsImpl();
-    }, throwsStateError);
-  }
-
-  void test_analysisOptions_beforeContextCreation() {
-    FolderBasedDartSdk sdk = _createDartSdk();
-    sdk.analysisOptions = AnalysisOptionsImpl();
-    sdk.context;
-    // cannot change "analysisOptions" in the context
-    expect(() {
-      sdk.context.analysisOptions = AnalysisOptionsImpl();
-    }, throwsStateError);
-  }
-
   void test_creation() {
     FolderBasedDartSdk sdk = _createDartSdk();
     expect(sdk, isNotNull);
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
index 8fc046c..d4bc4a4 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_extension_member_access_test.dart
@@ -144,7 +144,6 @@
   }
 
   test_operator_binary() async {
-    // There is no error reported.
     await assertErrorsInCode('''
 class A {}
 
@@ -162,6 +161,26 @@
     ]);
   }
 
+  test_operator_binary_compoundAssignment() async {
+    await assertErrorsInCode('''
+class A {}
+
+extension E1 on A {
+  A operator +(_) => this;
+}
+
+extension E2 on A {
+  A operator +(_) => this;
+}
+
+void f(A a) {
+  a += 0;
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_EXTENSION_MEMBER_ACCESS, 130, 2),
+    ]);
+  }
+
   test_operator_index_index() async {
     await assertErrorsInCode('''
 class A {}
diff --git a/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart b/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
index 61d593a..01e301c 100644
--- a/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/ambiguous_import_test.dart
@@ -219,34 +219,99 @@
     ]);
   }
 
-  test_varRead() async {
-    newFile("$testPackageLibPath/lib1.dart", content: '''
-library lib1;
-var v;''');
-    newFile("$testPackageLibPath/lib2.dart", content: '''
-library lib2;
-var v;''');
+  test_variable_read() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+var x;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+var x;
+''');
+
     await assertErrorsInCode('''
-import 'lib1.dart';
-import 'lib2.dart';
-f() { g(v); }
-g(p) {}''', [
+import 'a.dart';
+import 'b.dart';
+
+void f() {
+  x;
+}
+''', [
       error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 48, 1),
     ]);
   }
 
-  test_varWrite() async {
-    newFile("$testPackageLibPath/lib1.dart", content: '''
-library lib1;
-var v;''');
-    newFile("$testPackageLibPath/lib2.dart", content: '''
-library lib2;
-var v;''');
+  test_variable_read_prefixed() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+var x;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+var x;
+''');
+
     await assertErrorsInCode('''
-import 'lib1.dart';
-import 'lib2.dart';
-f() { v = 0; }''', [
-      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 46, 1),
+import 'a.dart' as p;
+import 'b.dart' as p;
+
+void f() {
+  p.x;
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 60, 1),
+    ]);
+  }
+
+  test_variable_write() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+var x;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+var x;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart';
+import 'b.dart';
+
+void f() {
+  x = 0;
+  x += 1;
+  ++x;
+  x++;
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 48, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 57, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 69, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 74, 1),
+    ]);
+  }
+
+  test_variable_write_prefixed() async {
+    newFile('$testPackageLibPath/a.dart', content: '''
+var x;
+''');
+
+    newFile('$testPackageLibPath/b.dart', content: '''
+var x;
+''');
+
+    await assertErrorsInCode('''
+import 'a.dart' as p;
+import 'b.dart' as p;
+
+void f() {
+  p.x = 0;
+  p.x += 1;
+  ++p.x;
+  p.x++;
+}
+''', [
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 60, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 71, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 85, 1),
+      error(CompileTimeErrorCode.AMBIGUOUS_IMPORT, 92, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/analysis_options/analysis_options_test_support.dart b/pkg/analyzer/test/src/diagnostics/analysis_options/analysis_options_test_support.dart
new file mode 100644
index 0000000..c510595
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/analysis_options/analysis_options_test_support.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/base/errors.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/task/options.dart';
+
+import '../../../generated/test_support.dart';
+
+class AbstractAnalysisOptionsTest {
+  Future<void> assertErrorsInCode(
+      String code, List<ExpectedError> expectedErrors) async {
+    var diagnostics =
+        analyzeAnalysisOptions(TestSource(), code, SourceFactory([]));
+    var errorListener = GatheringErrorListener();
+    errorListener.addAll(diagnostics);
+    errorListener.assertErrors(expectedErrors);
+  }
+
+  ExpectedError error(ErrorCode code, int offset, int length,
+          {String text,
+          Pattern messageContains,
+          List<ExpectedContextMessage> contextMessages =
+              const <ExpectedContextMessage>[]}) =>
+      ExpectedError(code, offset, length,
+          message: text,
+          messageContains: messageContains,
+          expectedContextMessages: contextMessages);
+}
diff --git a/pkg/analyzer/test/src/diagnostics/analysis_options/include_file_not_found.dart b/pkg/analyzer/test/src/diagnostics/analysis_options/include_file_not_found.dart
new file mode 100644
index 0000000..976fc62
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/analysis_options/include_file_not_found.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/analysis_options/error/option_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'analysis_options_test_support.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(IncludeFileNotFoundTest);
+  });
+}
+
+@reflectiveTest
+class IncludeFileNotFoundTest extends AbstractAnalysisOptionsTest {
+  void test_notFound() {
+    assertErrorsInCode('''
+# We don't depend on pedantic, but we should consider adding it.
+include: package:pedantic/analysis_options.yaml
+''', [error(AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND, 74, 38)]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 5ece142..d62e2fa 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -194,8 +194,12 @@
 }
 f(A a) {
   a['0'] += 0;
+  ++a['0'];
+  a['0']++;
 }''', [
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 103, 3),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 120, 3),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 130, 3),
     ]);
   }
 
@@ -219,8 +223,12 @@
 }
 f(A a) {
   a['0'] += 0;
+  ++a['0'];
+  a['0']++;
 }''', [
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 103, 3),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 120, 3),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 130, 3),
     ]);
   }
 
@@ -440,15 +448,15 @@
   bool operator==(covariant A other) => false;
 }
 
-main(A a, A? aq) {
+void f(A a, A? aq) {
   a == 0;
   aq == 1;
   aq == aq;
   aq == null;
 }
 ''', [
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 86, 1),
-      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 97, 1),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 88, 1),
+      error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 99, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
index ef2c8c2..ccdfcf5 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_of_do_not_store_test.dart
@@ -34,7 +34,8 @@
   String f = A().v;
 }
 ''', [
-      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 106, 5),
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 106, 5,
+          messageContains: "'v'"),
     ]);
   }
 
@@ -176,4 +177,59 @@
       error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 83, 1),
     ]);
   }
+
+  test_topLevelVariable_binaryExpression() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+final v = '';
+
+class A {
+  final f = v ?? v;
+}
+''', [
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 83, 1),
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 88, 1),
+    ]);
+  }
+
+  test_topLevelVariable_libraryAnnotation() async {
+    testFilePath;
+    newFile('$testPackageLibPath/library.dart', content: '''
+@doNotStore
+library lib;
+
+import 'package:meta/meta.dart';
+
+final v = '';
+''');
+
+    await assertErrorsInCode('''
+import 'library.dart';
+
+class A {
+  final f = v;
+}
+''', [
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 46, 1),
+    ]);
+  }
+
+  test_topLevelVariable_ternary() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+final v = '';
+
+class A {
+  static bool c;
+  final f = c ? v : v;
+}
+''', [
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 104, 1),
+      error(HintCode.ASSIGNMENT_OF_DO_NOT_STORE, 108, 1),
+    ]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
index c4da4a8..9a30b49 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_const_test.dart
@@ -24,7 +24,7 @@
 f() {
   A.v = 1;
 }''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_CONST, 42, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_CONST, 44, 1),
     ]);
   }
 
@@ -36,7 +36,7 @@
 f() {
   A.v += 1;
 }''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_CONST, 42, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_CONST, 44, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
index 3d229b4..60d039d 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_method_test.dart
@@ -25,23 +25,57 @@
   void set foo(int _) {}
 }
 
-f(C c) {
+void f(C c) {
   c.foo = 0;
+  c.foo += 1;
+  c.foo++;
+  --c.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 87, 5),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 94, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 107, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 121, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 134, 3),
     ]);
   }
 
-  test_method() async {
+  test_prefixedIdentifier_instanceMethod() async {
     await assertErrorsInCode('''
 class A {
-  m() {}
+  void foo() {}
 }
-f(A a) {
-  a.m = () {};
-}''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 32, 3),
+
+void f(A a) {
+  a.foo = 0;
+  a.foo += 1;
+  a.foo++;
+  ++a.foo;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 47, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 60, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 74, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 87, 3),
+    ]);
+  }
+
+  test_propertyAccess_instanceMethod() async {
+    await assertErrorsInCode('''
+class A {
+  void foo() {}
+}
+
+void f(A a) {
+  (a).foo = 0;
+  (a).foo += 1;
+  (a).foo++;
+  ++(a).foo;
+}
+''', [
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 49, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 64, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 80, 3),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 95, 3),
     ]);
   }
 
@@ -59,7 +93,7 @@
   }
 }
 ''', [
-      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 86, 8),
+      error(CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, 91, 3),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/binary_operator_written_out_test.dart b/pkg/analyzer/test/src/diagnostics/binary_operator_written_out_test.dart
new file mode 100644
index 0000000..e5abe38
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/binary_operator_written_out_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(BinaryOperatorWrittenOutTest);
+  });
+}
+
+@reflectiveTest
+class BinaryOperatorWrittenOutTest extends PubPackageResolutionTest {
+  test_using_and() async {
+    await assertErrorsInCode(r'''
+f(var x, var y) {
+  return x and y;
+}
+''', [
+      error(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 29, 3),
+    ]);
+  }
+
+  test_using_and_no_error() async {
+    await assertNoErrorsInCode(r'''
+f(var x, var y) {
+  return x & y;
+}
+''');
+  }
+
+  test_using_or() async {
+    await assertErrorsInCode(r'''
+f(var x, var y) {
+  return x or y;
+}
+''', [
+      error(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 29, 2),
+    ]);
+  }
+
+  test_using_or_no_error() async {
+    await assertNoErrorsInCode(r'''
+f(var x, var y) {
+  return x | y;
+}
+''');
+  }
+
+  test_using_shl() async {
+    await assertErrorsInCode(r'''
+f(var x) {
+  return x shl 2;
+}
+''', [
+      error(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 22, 3),
+    ]);
+  }
+
+  test_using_shl_no_error() async {
+    await assertNoErrorsInCode(r'''
+f(var x) {
+  return x << 2;
+}
+''');
+  }
+
+  test_using_shr() async {
+    await assertErrorsInCode(r'''
+f(var x) {
+  return x shr 2;
+}
+''', [
+      error(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 22, 3),
+    ]);
+  }
+
+  test_using_shr_no_error() async {
+    await assertNoErrorsInCode(r'''
+f(var x) {
+  return x >> 2;
+}
+''');
+  }
+
+  test_using_xor() async {
+    await assertErrorsInCode(r'''
+f(var x, var y) {
+  return x xor y;
+}
+''', [
+      error(ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT, 29, 3),
+    ]);
+  }
+
+  test_using_xor_no_error() async {
+    await assertNoErrorsInCode(r'''
+f(var x, var y) {
+  return x ^ y;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/built_in_identifier_as_typedef_name_test.dart b/pkg/analyzer/test/src/diagnostics/built_in_identifier_as_typedef_name_test.dart
index 7ba99f5..5e344f1 100644
--- a/pkg/analyzer/test/src/diagnostics/built_in_identifier_as_typedef_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/built_in_identifier_as_typedef_name_test.dart
@@ -30,7 +30,7 @@
     await assertErrorsInCode(r'''
 typedef void as();
 ''', [
-      error(ParserErrorCode.MISSING_IDENTIFIER, 13, 2),
+      error(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 13, 2),
       error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, 13, 2),
     ]);
   }
@@ -40,7 +40,7 @@
 typedef as = void Function();
 ''', [
       error(CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME, 8, 2),
-      error(ParserErrorCode.MISSING_IDENTIFIER, 8, 2)
+      error(ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD, 8, 2)
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
index a2d7705..23be73a 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_throws_exception_test.dart
@@ -10,7 +10,6 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ConstEvalThrowsExceptionTest_language24);
     defineReflectiveTests(ConstEvalThrowsExceptionTest);
     defineReflectiveTests(ConstEvalThrowsExceptionWithNullSafetyTest);
   });
@@ -19,9 +18,6 @@
 @reflectiveTest
 class ConstEvalThrowsExceptionTest extends PubPackageResolutionTest
     with ConstEvalThrowsExceptionTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-
   test_binaryMinus_null() async {
     await assertErrorsInCode('''
 const dynamic D = null;
@@ -78,26 +74,7 @@
 }
 
 @reflectiveTest
-class ConstEvalThrowsExceptionTest_language24 extends PubPackageResolutionTest
-    with ConstEvalThrowsExceptionTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
-
-@reflectiveTest
 mixin ConstEvalThrowsExceptionTestCases on PubPackageResolutionTest {
-  /// The expected state of this feature in the test.
-  bool get _constant_update_2018;
-
   test_assertInitializerThrows() async {
     await assertErrorsInCode(r'''
 class A {
@@ -278,77 +255,44 @@
   }
 
   test_ifElement_false_thenNotEvaluated() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic nil = null;
 const c = [if (1 < 0) nil + 1];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 37, 18),
-              ]);
+''');
   }
 
   test_ifElement_nonBoolCondition_list() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic nonBool = 3;
 const c = const [if (nonBool) 'a'];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 48, 7),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 16),
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 48, 7),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 48, 7),
+    ]);
   }
 
   test_ifElement_nonBoolCondition_map() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic nonBool = null;
 const c = const {if (nonBool) 'a' : 1};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 51, 7),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 20),
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 51, 7),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 51, 7),
+    ]);
   }
 
   test_ifElement_nonBoolCondition_set() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic nonBool = 'a';
 const c = const {if (nonBool) 3};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 50, 7),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 46, 14),
-                error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 50, 7),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 50, 7),
+    ]);
   }
 
   test_ifElement_true_elseNotEvaluated() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic nil = null;
 const c = [if (0 < 1) 3 else nil + 1];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 37, 25),
-              ]);
+''');
   }
 
   test_invalid_constructorFieldInitializer_fromSeparateLibrary() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
index 054355c..817d86c 100644
--- a/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_set_element_type_implements_equals_test.dart
@@ -9,38 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest_language24);
     defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
   });
 }
 
 @reflectiveTest
 class ConstSetElementTypeImplementsEqualsTest extends PubPackageResolutionTest
-    with ConstSetElementTypeImplementsEqualsTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class ConstSetElementTypeImplementsEqualsTest_language24
-    extends PubPackageResolutionTest
-    with ConstSetElementTypeImplementsEqualsTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with ConstSetElementTypeImplementsEqualsTestCases {}
 
 mixin ConstSetElementTypeImplementsEqualsTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_constField() async {
     await assertErrorsInCode(r'''
 class A {
@@ -135,8 +112,7 @@
   }
 
   test_spread_list() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -145,23 +121,14 @@
 main() {
   const {...[A()]};
 }
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                    75,
-                    8),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 75, 8),
-              ]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 75, 8),
+    ]);
   }
 
   test_spread_set() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 class A {
   const A();
   operator ==(other) => false;
@@ -170,23 +137,10 @@
 main() {
   const {...{A()}};
 }
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                    79,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 75, 8),
-                error(
-                    CompileTimeErrorCode
-                        .CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS,
-                    79,
-                    3),
-              ]);
+''', [
+      error(
+          CompileTimeErrorCode.CONST_SET_ELEMENT_TYPE_IMPLEMENTS_EQUALS, 79, 3),
+    ]);
   }
 
   test_super() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
index d2470d0..0b71d6d 100644
--- a/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_list_or_set_test.dart
@@ -10,209 +10,108 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstSpreadExpectedListOrSetTest);
-    defineReflectiveTests(ConstSpreadExpectedListOrSetTest_language24);
   });
 }
 
 @reflectiveTest
 class ConstSpreadExpectedListOrSetTest extends PubPackageResolutionTest
-    with ConstSpreadExpectedListOrSetTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class ConstSpreadExpectedListOrSetTest_language24
-    extends PubPackageResolutionTest
-    with ConstSpreadExpectedListOrSetTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with ConstSpreadExpectedListOrSetTestCases {}
 
 mixin ConstSpreadExpectedListOrSetTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_listInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 5;
 var b = const <int>[...a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    44, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 41, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 44, 1),
+    ]);
   }
 
   test_const_listList() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = [5];
 var b = const <int>[...a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 4),
-              ]);
+''');
   }
 
   test_const_listMap() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = <int, int>{0: 1};
 var b = const <int>[...a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 59, 1),
+    ]);
   }
 
   test_const_listNull() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = null;
 var b = const <int>[...a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 47, 1),
+    ]);
   }
 
   test_const_listNull_nullable() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = null;
 var b = const <int>[...?a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 44, 5),
-              ]);
+''');
   }
 
   test_const_listSet() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = <int>{5};
 var b = const <int>[...a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 48, 4),
-              ]);
+''');
   }
 
   test_const_setInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 5;
 var b = const <int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    44, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 44, 1),
+    ]);
   }
 
   test_const_setList() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = <int>[5];
 var b = const <int>{...a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 48, 4),
-              ]);
+''');
   }
 
   test_const_setMap() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = <int, int>{1: 2};
 var b = const <int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 59, 1),
+    ]);
   }
 
   test_const_setNull() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = null;
 var b = const <int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
-                    47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 44, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET, 47, 1),
+    ]);
   }
 
   test_const_setNull_nullable() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = null;
 var b = const <int>{...?a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 44, 5),
-              ]);
+''');
   }
 
   test_const_setSet() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = <int>{5};
 var b = const <int>{...a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 48, 4),
-              ]);
+''');
   }
 
   test_nonConst_listInt() async {
diff --git a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
index 937a847..841c131 100644
--- a/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_spread_expected_map_test.dart
@@ -10,64 +10,30 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstSpreadExpectedMapTest);
-    defineReflectiveTests(ConstSpreadExpectedMapTest_language24);
   });
 }
 
 @reflectiveTest
 class ConstSpreadExpectedMapTest extends PubPackageResolutionTest
-    with ConstSpreadExpectedMapTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class ConstSpreadExpectedMapTest_language24 extends PubPackageResolutionTest
-    with ConstSpreadExpectedMapTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with ConstSpreadExpectedMapTestCases {}
 
 mixin ConstSpreadExpectedMapTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_mapInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 5;
 var b = const <int, int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 49, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 49, 1),
+    ]);
   }
 
   test_const_mapList() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = <int>[5];
 var b = const <int, int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
+    ]);
   }
 
   test_const_mapMap() async {
@@ -78,18 +44,12 @@
   }
 
   test_const_mapNull() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = null;
 var b = const <int, int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 52, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 52, 1),
+    ]);
   }
 
   test_const_mapNull_nullable() async {
@@ -100,18 +60,12 @@
   }
 
   test_const_mapSet() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = <int>{5};
 var b = const <int, int>{...a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP, 56, 1),
+    ]);
   }
 
   test_nonConst_mapInt() async {
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index b261479..effa025 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -404,7 +404,7 @@
 
   test_flowEnd_ifStatement() async {
     await assertErrorsInCode(r'''
-main(bool a) {
+void f(bool a) {
   if (a) {
     return;
     1;
@@ -412,7 +412,7 @@
   2;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 42, 2),
+      error(HintCode.DEAD_CODE, 44, 2),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart b/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
index e60e478..c1e4746 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_null_aware_expression_test.dart
@@ -22,16 +22,13 @@
 var x = 0;
 ''');
 
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 import 'a.dart';
 
 f() {
   x ??= 0;
 }
-''', [
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 32, 2),
-    ]);
+''');
   }
 
   test_assignCompound_map() async {
@@ -54,8 +51,6 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 19, 1),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 19, 2),
     ]);
   }
 
@@ -73,16 +68,13 @@
 var x = 0;
 ''');
 
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 import 'a.dart';
 
 f() {
   x ?? 0;
 }
-''', [
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 31, 2),
-    ]);
+''');
   }
 
   test_binary_nonNullable() async {
@@ -92,8 +84,6 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 18, 1),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 18, 2),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/default_value_in_function_typed_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/default_value_in_function_typed_parameter_test.dart
deleted file mode 100644
index 746f479..0000000
--- a/pkg/analyzer/test/src/diagnostics/default_value_in_function_typed_parameter_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../dart/resolution/context_collection_resolution.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(DefaultValueInFunctionTypedParameterTest);
-  });
-}
-
-@reflectiveTest
-class DefaultValueInFunctionTypedParameterTest
-    extends PubPackageResolutionTest {
-  test_named() async {
-    await assertErrorsInCode('''
-f(g({p: null})) {}
-''', [
-      error(
-          CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, 5, 7),
-      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 6, 1),
-    ]);
-  }
-
-  test_positional() async {
-    await assertErrorsInCode('''
-f(g([p = null])) {}
-''', [
-      error(
-          CompileTimeErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER, 5, 8),
-      error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 7, 1),
-    ]);
-  }
-}
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index 1a4ba96..f9f9e2e 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -833,11 +833,6 @@
   }
 
   @override
-  void setUp() {
-    super.setUp();
-  }
-
-  @override
   void verifyCreatedCollection() {
     super.verifyCreatedCollection();
     assertPackageBuildWorkspaceFor(testFilePath);
diff --git a/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart b/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
index 726859c..381dc33 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_elements_in_const_set_test.dart
@@ -10,36 +10,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(EqualElementsInConstSetTest);
-    defineReflectiveTests(EqualElementsInConstSetTest_language24);
   });
 }
 
 @reflectiveTest
 class EqualElementsInConstSetTest extends PubPackageResolutionTest
-    with EqualElementsInConstSetTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class EqualElementsInConstSetTest_language24 extends PubPackageResolutionTest
-    with EqualElementsInConstSetTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with EqualElementsInConstSetTestCases {}
 
 mixin EqualElementsInConstSetTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_entry() async {
     await assertErrorsInCode('''
 var c = const {1, 2, 1};
@@ -50,85 +28,45 @@
   }
 
   test_const_ifElement_thenElseFalse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1, if (1 < 0) 2 else 1};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 36, 1,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 36, 1,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_onlyElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {if (0 < 1) 1 else 1};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 15, 19),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseTrue() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {1, if (0 < 1) 2 else 1};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 19),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseTrue_onlyThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {if (0 < 1) 1 else 1};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 15, 19),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {2, if (1 < 0) 2};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1, if (0 < 1) 1};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 29, 1,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 29, 1,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_const_instanceCreation_equalTypeArgs() async {
@@ -156,32 +94,18 @@
   }
 
   test_const_spread__noDuplicate() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {1, ...{2}};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 6),
-              ]);
+''');
   }
 
   test_const_spread_hasDuplicate() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1, ...{1}};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 21, 3,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 18, 6),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 21, 3,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_nonConst_entry() async {
diff --git a/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart b/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
index 2cc1a89..24da1be 100644
--- a/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/equal_keys_in_const_map_test.dart
@@ -10,36 +10,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(EqualKeysInConstMapTest);
-    defineReflectiveTests(EqualKeysInConstMapTest_language24);
   });
 }
 
 @reflectiveTest
 class EqualKeysInConstMapTest extends PubPackageResolutionTest
-    with EqualKeysInConstMapTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class EqualKeysInConstMapTest_language24 extends PubPackageResolutionTest
-    with EqualKeysInConstMapTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with EqualKeysInConstMapTestCases {}
 
 mixin EqualKeysInConstMapTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_entry() async {
     await assertErrorsInCode('''
 var c = const {1: null, 2: null, 1: null};
@@ -50,85 +28,45 @@
   }
 
   test_const_ifElement_thenElseFalse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1: null, if (1 < 0) 2: null else 1: null};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 48, 1,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 31),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 48, 1,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_onlyElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {if (0 < 1) 1: null else 1: null};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 15, 31),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseTrue() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {1: null, if (0 < 1) 2: null else 1: null};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 31),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseTrue_onlyThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {if (0 < 1) 1: null else 1: null};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 15, 31),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {2: null, if (1 < 0) 2: 2};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 15),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1: null, if (0 < 1) 1: null};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 35, 1,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 18),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 35, 1,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_const_instanceCreation_equalTypeArgs() async {
@@ -156,32 +94,18 @@
   }
 
   test_const_spread__noDuplicate() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var c = const {1: null, ...{2: null}};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 12),
-              ]);
+''');
   }
 
   test_const_spread_hasDuplicate() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var c = const {1: null, ...{1: null}};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 27, 9,
-                    contextMessages: [
-                      message('$testPackageLibPath/test.dart', 15, 1)
-                    ]),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 24, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 27, 9,
+          contextMessages: [message('$testPackageLibPath/test.dart', 15, 1)]),
+    ]);
   }
 
   test_nonConst_entry() async {
diff --git a/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
index 3d332b9..c85d229 100644
--- a/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/if_element_condition_from_deferred_library_test.dart
@@ -10,62 +10,30 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(IfElementConditionFromDeferredLibraryTest);
-    defineReflectiveTests(IfElementConditionFromDeferredLibraryTest_language24);
   });
 }
 
 @reflectiveTest
 class IfElementConditionFromDeferredLibraryTest extends PubPackageResolutionTest
-    with IfElementConditionFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class IfElementConditionFromDeferredLibraryTest_language24
-    extends PubPackageResolutionTest
-    with IfElementConditionFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with IfElementConditionFromDeferredLibraryTestCases {}
 
 mixin IfElementConditionFromDeferredLibraryTestCases
     on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_inList_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const [if(a.c) 0];
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 9),
-              ]);
+}''', [
+      error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
+          3),
+    ]);
   }
 
   test_inList_nonConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -75,45 +43,30 @@
   }
 
   test_inList_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const [if(a.c) 0];
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 9),
-              ]);
+}''');
   }
 
   test_inMap_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const {if(a.c) 0 : 0};
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 13),
-              ]);
+}''', [
+      error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
+          3),
+    ]);
   }
 
   test_inMap_notConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -123,45 +76,30 @@
   }
 
   test_inMap_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const {if(a.c) 0 : 0};
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 13),
-              ]);
+}''');
   }
 
   test_inSet_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const {if(a.c) 0};
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 9),
-              ]);
+}''', [
+      error(CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY, 59,
+          3),
+    ]);
   }
 
   test_inSet_notConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -171,18 +109,12 @@
   }
 
   test_inSet_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const bool c = true;''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const {if(a.c) 0};
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 47, 9),
-              ]);
+}''');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
index 3b81868..45493d4 100644
--- a/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/implicit_this_reference_in_initializer_test.dart
@@ -36,6 +36,43 @@
 ''');
   }
 
+  test_constructorInitializer_assert_superClass() async {
+    await assertErrorsInCode(r'''
+class A {
+  int get f => 0;
+}
+
+class B extends A {
+  B() : assert(f != 0);
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 66, 1),
+    ]);
+  }
+
+  test_constructorInitializer_assert_thisClass() async {
+    await assertErrorsInCode(r'''
+class A {
+  A() : assert(f != 0);
+  int get f => 0;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 25, 1),
+    ]);
+  }
+
+  test_constructorInitializer_field() async {
+    await assertErrorsInCode(r'''
+class A {
+  var v;
+  A() : v = f;
+  var f;
+}
+''', [
+      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
+    ]);
+  }
+
   test_constructorName() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -48,18 +85,6 @@
 ''');
   }
 
-  test_field() async {
-    await assertErrorsInCode(r'''
-class A {
-  var v;
-  A() : v = f;
-  var f;
-}
-''', [
-      error(CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER, 31, 1),
-    ]);
-  }
-
   test_field2() async {
     await assertErrorsInCode(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
new file mode 100644
index 0000000..b960a44
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
@@ -0,0 +1,550 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/test_utilities/mock_packages.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidExportOfInternalElement_BazelPackageTest);
+    defineReflectiveTests(
+        InvalidExportOfInternalElement_PackageBuildPackageTest);
+    defineReflectiveTests(InvalidExportOfInternalElement_PubPackageTest);
+  });
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_BazelPackageTest
+    extends BazelWorkspaceResolutionTest
+    with InvalidExportOfInternalElementTest {
+  String get testPackageBazelBinPath => '$workspaceRootPath/bazel-bin/dart/my';
+
+  String get testPackageGenfilesPath =>
+      '$workspaceRootPath/bazel-genfiles/dart/my';
+
+  @override
+  String get testPackageLibPath => myPackageLibPath;
+
+  @override
+  void setUp() async {
+    super.setUp();
+    var metaPath = '$workspaceThirdPartyDartPath/meta';
+    MockPackages.addMetaPackageFiles(
+      getFolder(metaPath),
+    );
+    newFile('$testPackageBazelBinPath/my.packages');
+    newFolder('$workspaceRootPath/bazel-out');
+  }
+
+  void test_exporterIsInBazelBinLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageBazelBinPath/lib/bar.dart', r'''
+export 'src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInBazelBinLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageBazelBinPath/lib/src/bar.dart', r'''
+export 'foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_exporterIsInGenfilesLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageGenfilesPath/lib/bar.dart', r'''
+export 'src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInGenfilesLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageGenfilesPath/lib/src/bar.dart', r'''
+export 'foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_exporterIsInLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageLibPath/bar.dart', r'''
+export 'src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageLibPath/src/bar.dart', r'''
+export 'foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_exporterIsInTest() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$myPackageRootPath/test/foo_test.dart', r'''
+export 'package:dart.my/src/foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_internalIsInBazelBin() async {
+    newFile('$testPackageBazelBinPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+
+  void test_internalIsInGenfiles() async {
+    newFile('$testPackageGenfilesPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+
+  void test_internalIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_PackageBuildPackageTest
+    extends InvalidExportOfInternalElement_PubPackageTest {
+  String get testPackageDartToolPath =>
+      '$testPackageRootPath/.dart_tool/build/generated/test';
+
+  @FailingTest(reason: r'''
+We try to analyze a file in .dart_tool, which is implicitly excluded from
+analysis. So, there is no context to analyze it.
+''')
+  void test_exporterInGeneratedLib() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageDartToolPath/lib/bar.dart', r'''
+export 'package:test/src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  @FailingTest(reason: r'''
+We try to analyze a file in .dart_tool, which is implicitly excluded from
+analysis. So, there is no context to analyze it.
+''')
+  void test_exporterInGeneratedLibSrc() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageDartToolPath/lib/src/bar.dart', r'''
+export 'package:test/src/foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_exporterInLib() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageRootPath/lib/bar.dart', r'''
+export 'package:test/src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  void test_exporterInLibSrc() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageRootPath/lib/src/bar.dart', r'''
+export 'package:test/src/foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_internalIsInGeneratedLibSrc() async {
+    newFile('$testPackageDartToolPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  @override
+  void test_internalIsLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_PubPackageTest
+    extends PubPackageResolutionTest with InvalidExportOfInternalElementTest {
+  @override
+  void setUp() async {
+    super.setUp();
+    writeTestPackageConfigWithMeta();
+    newFile('$testPackageRootPath/pubspec.yaml', content: r'''
+name: test
+version: 0.0.1
+''');
+  }
+
+  void test_exporterIsInLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageLibPath/bar.dart', r'''
+export 'src/foo.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageLibPath/src/bar.dart', r'''
+export 'foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_exporterIsInTest() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await resolveFileCode('$testPackageRootPath/test/foo_test.dart', r'''
+export 'package:test/src/foo.dart';
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_internalIsLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+}
+
+mixin InvalidExportOfInternalElementTest on ContextResolutionTest {
+  String get testPackageImplementationFilePath =>
+      '$testPackageLibPath/src/foo.dart';
+
+  String get testPackageLibPath;
+
+  void test_hideCombinator_internalHidden() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart' hide One;
+''');
+  }
+
+  void test_hideCombinator_internalNotHidden() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' hide Two;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 31),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_parameter() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+int func(IntFunc f, int x) => f(x);
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_parameter_generic() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef IntFunc = int Function(int);
+int func(IntFunc f, int x) => f(x);
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_parameter_generic_typeArg() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef IntFunc<T> = int Function(T);
+int func(IntFunc<num> f, int x) => f(x);
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_returnType() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+IntFunc func() => (int x) => x;
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_typeArgument_bounded() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+void func<T extends IntFunc>() {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY, 0, 32),
+    ]);
+  }
+
+  void test_indirectlyViaFunction_typeArgument_unbounded() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal typedef int IntFunc(int x);
+void func<T>() {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart' show func;
+''');
+  }
+
+  void test_noCombinators() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_indirectExport() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+export 'bar.dart';
+''');
+
+    newFile('$testPackageLibPath/src/bar.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_library() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+@internal
+library foo;
+
+import 'package:meta/meta.dart';
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_library_notInternal() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+library foo;
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart';
+''');
+  }
+
+  void test_noCombinators_noInternal() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+class One {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart';
+''');
+  }
+
+  void test_showCombinator_internalNotShown() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart' show Two;
+''');
+  }
+
+  void test_showCombinator_internalShown() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show One;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 31),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
new file mode 100644
index 0000000..8a3ca44
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidInternalAnnotationTest);
+  });
+}
+
+@reflectiveTest
+class InvalidInternalAnnotationTest extends PubPackageResolutionTest {
+  String get testPackageLibSrcFilePath => '$testPackageLibPath/src/foo.dart';
+
+  @override
+  void setUp() async {
+    super.setUp();
+    writeTestPackageConfigWithMeta();
+    newFile('$testPackageRootPath/pubspec.yaml', content: r'''
+name: test
+version: 0.0.1
+''');
+  }
+
+  void test_annotationInLib() async {
+    await resolveFileCode('$testPackageLibPath/foo.dart', r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_annotationInLib_onLibrary() async {
+    await resolveFileCode('$testPackageLibPath/foo.dart', r'''
+@internal
+library foo;
+import 'package:meta/meta.dart';
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 0, 9),
+    ]);
+  }
+
+  void test_annotationInLibSrc() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_annotationInLibSrcSubdirectory() async {
+    await resolveFileCode('$testPackageLibPath/src/foo/foo.dart', r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_annotationInLibSubdirectory() async {
+    await resolveFileCode('$testPackageLibPath/foo/foo.dart', r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_annotationInTest() async {
+    await resolveFileCode('$testPackageRootPath/test/foo_test.dart', r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    assertNoErrorsInResult();
+  }
+
+  void test_privateClass() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal class _One {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 49, 4),
+    ]);
+  }
+
+  void test_privateClassConstructor_named() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal _C.named();
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 46, 9),
+    ]);
+  }
+
+  void test_privateClassConstructor_unnamed() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal _C();
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 46, 9),
+    ]);
+  }
+
+  void test_privateConstructor() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal C._f();
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+    ]);
+  }
+
+  void test_privateEnum() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal enum _E {one}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 48, 2),
+      error(HintCode.UNUSED_FIELD, 52, 3),
+    ]);
+  }
+
+  void test_privateEnumValue() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+enum E {@internal _one}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 41, 9),
+      error(HintCode.UNUSED_FIELD, 51, 4),
+    ]);
+  }
+
+  void test_privateExtension() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal extension _One on String {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_privateExtension_unnamed() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal extension on String {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_privateField_instance() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal int _i = 0;
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_FIELD, 59, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 59, 6),
+    ]);
+  }
+
+  void test_privateField_static() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal static int _i = 0;
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_FIELD, 66, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 66, 6),
+    ]);
+  }
+
+  void test_privateGetter() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal int get _i => 0;
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 63, 2),
+    ]);
+  }
+
+  void test_privateMethod_instance() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal void _f() {}
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 60, 2),
+    ]);
+  }
+
+  void test_privateMethod_static() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal static void _f() {}
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 67, 2),
+    ]);
+  }
+
+  void test_privateMixin() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal mixin _One {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 49, 4),
+    ]);
+  }
+
+  void test_privateTopLevelFunction() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal void _f() {}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 48, 2),
+    ]);
+  }
+
+  void test_privateTopLevelVariable() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal int _i = 1;
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 47, 6),
+      error(HintCode.UNUSED_ELEMENT, 47, 2),
+    ]);
+  }
+
+  void test_privateTypedef() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+@internal typedef _T = void Function();
+''');
+
+    assertErrorsInResult([
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 51, 2),
+    ]);
+  }
+
+  void test_publicMethod_privateClass() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal void f() {}
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+    ]);
+  }
+
+  void test_publicMethod_privateClass_static() async {
+    await resolveFileCode(testPackageLibSrcFilePath, r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal static void f() {}
+}
+''');
+
+    assertErrorsInResult([
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.UNUSED_ELEMENT, 68, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart
new file mode 100644
index 0000000..ac816b9
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_use_of_internal_member_test.dart
@@ -0,0 +1,623 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidUseOfInternalMemberTest);
+  });
+}
+
+@reflectiveTest
+class InvalidUseOfInternalMemberTest extends PubPackageResolutionTest {
+  String get fooPackageRootPath => '$workspaceRootPath/foo';
+
+  @override
+  String get testPackageRootPath => '/home/my';
+
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackagePubspecYamlFile(PubspecYamlFileConfig());
+    writeTestPackageConfig(
+        PackageConfigFileBuilder()
+          ..add(name: 'foo', rootPath: fooPackageRootPath),
+        meta: true);
+  }
+
+  test_insidePackage() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+class A {}
+''');
+    newFile('$fooPackageRootPath/lib/a.dart', content: '''
+import 'src/a.dart';
+
+A a = A();
+''');
+    await resolveFile2('$fooPackageRootPath/lib/a.dart');
+
+    assertNoErrorsInResult();
+  }
+
+  test_outsidePackage_class() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+class A {}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+A a = A();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 34, 1),
+    ]);
+  }
+
+  test_outsidePackage_constructor_named() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  C.named();
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+C a = C.named();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 40, 7),
+    ]);
+  }
+
+  test_outsidePackage_constructor_unnamed() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  C();
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+C a = C();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 40, 1),
+    ]);
+  }
+
+  test_outsidePackage_enum() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+enum E {one}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+void f(E value) {}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 41, 1),
+    ]);
+  }
+
+  test_outsidePackage_enumValue() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+enum E {@internal one}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+E f() => E.one;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 45, 3),
+    ]);
+  }
+
+  test_outsidePackage_extensionMethod() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+extension E on String {
+  @internal
+  int f() => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = 'hello'.f();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 50, 1),
+    ]);
+  }
+
+  test_outsidePackage_function() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a() => 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int b = a() + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
+    ]);
+  }
+
+  test_outsidePackage_function_generic() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a<T>() => 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int b = a<void>() + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
+    ]);
+  }
+
+  test_outsidePackage_function_generic_tearoff() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a<T>() => 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int Function() b = a;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 53, 1),
+    ]);
+  }
+
+  test_outsidePackage_function_tearoff() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a() => 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int Function() b = a;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 53, 1),
+    ]);
+  }
+
+  test_outsidePackage_functionLiteralForInternalTypedef() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+@internal
+typedef IntFunc = int Function(int);
+int foo(IntFunc f, int x) => f(x);
+''');
+
+    await assertNoErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int g() => foo((x) => 2*x, 7);
+''');
+  }
+
+  test_outsidePackage_inCommentReference() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int get a => 1;
+''');
+
+    await assertNoErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+/// This is quite similar to [a].
+int b = 1;
+''');
+  }
+
+  test_outsidePackage_library() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+@internal
+library a;
+import 'package:meta/meta.dart';
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 0, 32),
+      error(HintCode.UNUSED_IMPORT, 7, 24),
+    ]);
+  }
+
+  test_outsidePackage_method() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  int m() => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = C().m();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_method_generic() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  int m<T>() => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = C().m<void>();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_method_subclassed() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal int f() => 1;
+}
+
+class D extends C {}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = D().f();
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_method_subclassed_overridden() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal int f() => 1;
+}
+
+class D extends C {
+  int f() => 2;
+}
+''');
+
+    await assertNoErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = D().f();
+''');
+  }
+
+  test_outsidePackage_method_tearoff() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  int m() => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int Function() a = C().m;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 57, 1),
+    ]);
+  }
+
+  test_outsidePackage_methodParameter_named() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int m({@internal int a = 0}) => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = C().m(a: 5);
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 48, 1),
+    ]);
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/28066')
+  test_outsidePackage_methodParameter_positional() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int m([@internal int a = 0]) => 1;
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int a = C().m(5);
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 48, 1),
+    ]);
+  }
+
+  test_outsidePackage_mixin() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+mixin A {}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+class C with A {}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 47, 1),
+    ]);
+  }
+
+  test_outsidePackage_pairedWithProtected() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  @protected
+  void f() {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+class D extends C {
+  void g() => f();
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 68, 1),
+    ]);
+  }
+
+  test_outsidePackage_redirectingFactoryConstructor() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+class D implements C {
+  @internal D();
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+class C {
+  factory C() = D;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 60, 1),
+    ]);
+  }
+
+  test_outsidePackage_setter() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s = 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_setter_compound() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int get s() => 1;
+
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s += 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_setter_questionQuestion() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  int get s() => 1;
+
+  @internal
+  set s(int value) {}
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+f() {
+  C().s ??= 7;
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 46, 1),
+    ]);
+  }
+
+  test_outsidePackage_superConstructor() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal C();
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+class D extends C {
+  D() : super();
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 62, 7),
+    ]);
+  }
+
+  test_outsidePackage_superConstructor_named() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+class C {
+  @internal C.named();
+}
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+class D extends C {
+  D() : super.named();
+}
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 68, 5),
+    ]);
+  }
+
+  test_outsidePackage_topLevelGetter() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int get a => 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int b = a + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
+    ]);
+  }
+
+  test_outsidePackage_typedef() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+typedef t = void Function();
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+t func = () {};
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 34, 1),
+    ]);
+  }
+
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/28066')
+  test_outsidePackage_typedefParameter() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+typedef T = void Function({@internal int a = 1});
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+void f(T t) => t(a: 5);
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
+    ]);
+  }
+
+  test_outsidePackage_variable() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a = 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart';
+
+int b = a + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 42, 1),
+    ]);
+  }
+
+  test_outsidePackage_variable_prefixed() async {
+    newFile('$fooPackageRootPath/lib/src/a.dart', content: '''
+import 'package:meta/meta.dart';
+@internal
+int a = 1;
+''');
+
+    await assertErrorsInCode('''
+import 'package:foo/src/a.dart' as foo;
+
+int b = foo.a + 1;
+''', [
+      error(HintCode.INVALID_USE_OF_INTERNAL_MEMBER, 53, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
index f2526bd..6c69432 100644
--- a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -10,137 +10,67 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ListElementTypeNotAssignableTest);
-    defineReflectiveTests(ListElementTypeNotAssignableTest_language24);
   });
 }
 
 @reflectiveTest
 class ListElementTypeNotAssignableTest extends PubPackageResolutionTest
-    with ListElementTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class ListElementTypeNotAssignableTest_language24
-    extends PubPackageResolutionTest
-    with ListElementTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with ListElementTypeNotAssignableTestCases {}
 
 mixin ListElementTypeNotAssignableTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 0;
 var v = const <int>[if (1 < 0) a else b];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 62, 19),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseFalse_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <int>[if (1 < 0) a else b];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 82,
-                    1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 64, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 82, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var v = const <int>[if (1 < 0) 'a'];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 31,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 20, 14),
-                error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 31,
-                    3),
-              ]);
+''', [
+      error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int>[if (1 < 0) a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int>[if (true) a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 41, 11),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int>[if (true) a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 53,
-                    1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 43, 11),
-              ]);
+''', [
+      error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 53, 1),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var v = const <int>[...[0, 1]];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 20, 9),
-              ]);
+''');
   }
 
   test_const_stringInt() async {
diff --git a/pkg/analyzer/test/src/diagnostics/main_first_positional_parameter_type_test.dart b/pkg/analyzer/test/src/diagnostics/main_first_positional_parameter_type_test.dart
new file mode 100644
index 0000000..43b7fa9
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/main_first_positional_parameter_type_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MainFirstPositionalParameterTest);
+    defineReflectiveTests(MainFirstPositionalParameterWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class MainFirstPositionalParameterTest extends PubPackageResolutionTest
+    with MainFirstPositionalParameterTestCases {}
+
+mixin MainFirstPositionalParameterTestCases on PubPackageResolutionTest {
+  test_positionalOptional_listOfInt() async {
+    await resolveTestCode('''
+void main([List<int> args = const []]) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE, 11, 9),
+    ], legacy: []));
+  }
+
+  test_positionalRequired_dynamic() async {
+    await assertNoErrorsInCode('''
+void main(dynamic args) {}
+''');
+  }
+
+  test_positionalRequired_functionTypedFormal() async {
+    await resolveTestCode('''
+void main(void args()) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE, 10, 11),
+    ], legacy: []));
+  }
+
+  test_positionalRequired_iterableOfString() async {
+    await assertNoErrorsInCode('''
+void main(Iterable<String> args) {}
+''');
+  }
+
+  test_positionalRequired_listOfInt() async {
+    await resolveTestCode('''
+void main(List<int> args) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_FIRST_POSITIONAL_PARAMETER_TYPE, 10, 9),
+    ], legacy: []));
+  }
+
+  test_positionalRequired_listOfString() async {
+    await assertNoErrorsInCode('''
+void main(List<String> args) {}
+''');
+  }
+
+  test_positionalRequired_object() async {
+    await assertNoErrorsInCode('''
+void main(Object args) {}
+''');
+  }
+}
+
+@reflectiveTest
+class MainFirstPositionalParameterWithNullSafetyTest
+    extends PubPackageResolutionTest
+    with WithNullSafetyMixin, MainFirstPositionalParameterTestCases {
+  test_positionalRequired_listOfStringQuestion() async {
+    await assertNoErrorsInCode('''
+void main(List<String?> args) {}
+''');
+  }
+
+  test_positionalRequired_listQuestionOfString() async {
+    await assertNoErrorsInCode('''
+void main(List<String>? args) {}
+''');
+  }
+
+  test_positionalRequired_objectQuestion() async {
+    await assertNoErrorsInCode('''
+void main(Object? args) {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/main_has_required_named_parameters_test.dart b/pkg/analyzer/test/src/diagnostics/main_has_required_named_parameters_test.dart
new file mode 100644
index 0000000..dab48b2
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/main_has_required_named_parameters_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MainHasRequiredNamedParametersTest);
+    defineReflectiveTests(MainHasRequiredNamedParametersWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class MainHasRequiredNamedParametersTest extends PubPackageResolutionTest
+    with MainHasRequiredNamedParametersTestCases {}
+
+mixin MainHasRequiredNamedParametersTestCases on PubPackageResolutionTest {
+  test_namedOptional() async {
+    await resolveTestCode('''
+void main({int a = 0}) {}
+''');
+    assertNoErrorsInResult();
+  }
+}
+
+@reflectiveTest
+class MainHasRequiredNamedParametersWithNullSafetyTest
+    extends PubPackageResolutionTest
+    with WithNullSafetyMixin, MainHasRequiredNamedParametersTestCases {
+  test_namedRequired() async {
+    await assertErrorsInCode('''
+void main({required List<String> a}) {}
+''', [
+      error(CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS, 5, 4),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/main_has_too_many_required_positional_parameters_test.dart b/pkg/analyzer/test/src/diagnostics/main_has_too_many_required_positional_parameters_test.dart
new file mode 100644
index 0000000..6457de5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/main_has_too_many_required_positional_parameters_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MainHasTooManyRequiredPositionalParametersTest);
+    defineReflectiveTests(
+      MainHasTooManyRequiredPositionalParametersWithNullSafetyTest,
+    );
+  });
+}
+
+@reflectiveTest
+class MainHasTooManyRequiredPositionalParametersTest
+    extends PubPackageResolutionTest
+    with MainHasTooManyRequiredPositionalParametersTestCases {}
+
+mixin MainHasTooManyRequiredPositionalParametersTestCases
+    on PubPackageResolutionTest {
+  test_namedOptional_1() async {
+    await resolveTestCode('''
+void main({int a = 0}) {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalOptional_1() async {
+    await resolveTestCode('''
+void f([int a = 0]) {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalRequired_0() async {
+    await resolveTestCode('''
+void main() {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalRequired_1() async {
+    await resolveTestCode('''
+void main(args) {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalRequired_2() async {
+    await resolveTestCode('''
+void main(args, int a) {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalRequired_2_positionalOptional_1() async {
+    await resolveTestCode('''
+void main(args, int a, [int b = 0]) {}
+''');
+    assertNoErrorsInResult();
+  }
+
+  test_positionalRequired_3() async {
+    await resolveTestCode('''
+void main(args, int a, int b) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(
+          CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
+          5,
+          4),
+    ], legacy: []));
+  }
+
+  test_positionalRequired_3_namedOptional_1() async {
+    await resolveTestCode('''
+void main(args, int a, int b, {int c = 0}) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(
+          CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
+          5,
+          4),
+    ], legacy: []));
+  }
+}
+
+@reflectiveTest
+class MainHasTooManyRequiredPositionalParametersWithNullSafetyTest
+    extends PubPackageResolutionTest
+    with
+        WithNullSafetyMixin,
+        MainHasTooManyRequiredPositionalParametersTestCases {
+  test_positionalRequired_3_namedRequired_1() async {
+    await resolveTestCode('''
+void main(args, int a, int b, {required int c}) {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS, 5, 4),
+      error(
+          CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
+          5,
+          4),
+    ], legacy: []));
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/main_is_not_function_test.dart b/pkg/analyzer/test/src/diagnostics/main_is_not_function_test.dart
new file mode 100644
index 0000000..6b5921d
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/main_is_not_function_test.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(MainIsNotFunctionTest);
+    defineReflectiveTests(MainIsNotFunctionWithNullSafetyTest);
+  });
+}
+
+@reflectiveTest
+class MainIsNotFunctionTest extends PubPackageResolutionTest
+    with MainIsNotFunctionTestCases {}
+
+mixin MainIsNotFunctionTestCases on PubPackageResolutionTest {
+  test_class() async {
+    await resolveTestCode('''
+class main {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 6, 4),
+    ], legacy: []));
+  }
+
+  test_classAlias() async {
+    await resolveTestCode('''
+class A {}
+mixin M {}
+class main = A with M;
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 28, 4),
+    ], legacy: []));
+  }
+
+  test_function() async {
+    await assertNoErrorsInCode('''
+void main() {}
+''');
+  }
+
+  test_getter() async {
+    await resolveTestCode('''
+int get main => 0;
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 8, 4),
+    ], legacy: []));
+  }
+
+  test_mixin() async {
+    await resolveTestCode('''
+class A {}
+mixin main on A {}
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 17, 4),
+    ], legacy: []));
+  }
+
+  test_typedef() async {
+    await resolveTestCode('''
+typedef main = void Function();
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 8, 4),
+    ], legacy: []));
+  }
+
+  test_typedef_legacy() async {
+    await resolveTestCode('''
+typedef void main();
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 13, 4),
+    ], legacy: []));
+  }
+
+  test_variable() async {
+    await resolveTestCode('''
+var main = 0;
+''');
+    assertErrorsInResult(expectedErrorsByNullability(nullable: [
+      error(CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION, 4, 4),
+    ], legacy: []));
+  }
+}
+
+@reflectiveTest
+class MainIsNotFunctionWithNullSafetyTest extends PubPackageResolutionTest
+    with WithNullSafetyMixin, MainIsNotFunctionTestCases {}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index 515fb56..55fcfd1 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -10,135 +10,70 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapKeyTypeNotAssignableTest);
-    defineReflectiveTests(MapKeyTypeNotAssignableTest_language24);
   });
 }
 
 @reflectiveTest
 class MapKeyTypeNotAssignableTest extends PubPackageResolutionTest
-    with MapKeyTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class MapKeyTypeNotAssignableTest_language24 extends PubPackageResolutionTest
-    with MapKeyTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with MapKeyTypeNotAssignableTestCases {}
 
 mixin MapKeyTypeNotAssignableTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 0;
 var v = const <int, bool>{if (1 < 0) a: true else b: false};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <int, bool>{if (1 < 0) a: true else b: false};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 94, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 94, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int, bool>{if (1 < 0) a: true};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var v = const <int, bool>{if (1 < 0) 'a': true};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
+    ]);
   }
 
   test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int, bool>{if (true) a: true};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int, bool>{if (true) a: true};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 59, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final a = 0;
 var v = const <int, bool>{if (1 < 2) a: true};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 50, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 50, 1),
+    ]);
   }
 
   test_const_intInt_dynamic() async {
@@ -166,31 +101,18 @@
   }
 
   test_const_spread_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var v = const <int, String>{...{1: 'a'}};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 28, 11),
-              ]);
+''');
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int, String>{...{a: 'a'}};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 51, 11),
-                error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
+    ]);
   }
 
   test_key_type_is_assignable() async {
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index fb15c1f..443ce2b 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -10,139 +10,70 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapValueTypeNotAssignableTest);
-    defineReflectiveTests(MapValueTypeNotAssignableTest_language24);
   });
 }
 
 @reflectiveTest
 class MapValueTypeNotAssignableTest extends PubPackageResolutionTest
-    with MapValueTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class MapValueTypeNotAssignableTest_language24 extends PubPackageResolutionTest
-    with MapValueTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with MapValueTypeNotAssignableTestCases {}
 
 mixin MapValueTypeNotAssignableTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_intInt_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 0;
 var v = const <bool, int>{if (1 < 0) true: a else false: b};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <bool, int>{if (1 < 0) true: a else false: b};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 101, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 101, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 'a';
 var v = const <bool, int>{if (1 < 0) true: a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_intString_value() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var v = const <bool, int>{if (1 < 0) true: 'a'};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
+    ]);
   }
 
   test_const_ifElement_thenTrue_intInt_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <bool, int>{if (true) true: a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <bool, int>{if (true) true: a};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 65, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 65, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_notConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final a = 0;
 var v = const <bool, int>{if (1 < 2) true: a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 56, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 56, 1),
+    ]);
   }
 
   test_const_intInt_dynamic() async {
@@ -170,33 +101,18 @@
   }
 
   test_const_spread_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var v = const <bool, int>{...{true: 1}};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 12),
-              ]);
+''');
   }
 
   test_const_spread_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <bool, int>{...{true: a}};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 12),
-                error(
-                    CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
-              ]);
+''', [
+      error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
+    ]);
   }
 
   test_nonConst_ifElement_thenElseFalse_intInt_dynamic() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index eda7bec..44f695f 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -46,8 +46,7 @@
 }
 class B extends A {
   @override
-  void a()
-  {}
+  void a() {}
 }
 ''', [
       error(HintCode.MUST_CALL_SUPER, 115, 1),
@@ -82,6 +81,68 @@
 ''');
   }
 
+  test_fromExtendingClass_genericClass() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A<T> {
+  @mustCallSuper
+  void a() {}
+}
+class B extends A<int> {
+  @override
+  void a() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 123, 1),
+    ]);
+  }
+
+  test_fromExtendingClass_genericMethod() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  void a<T>() {}
+}
+class B extends A {
+  @override
+  void a<T>() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 118, 1),
+    ]);
+  }
+
+  test_fromExtendingClass_operator() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  operator ==(Object o) => o is A;
+}
+class B extends A {
+  @override
+  operator ==(Object o) => o is B;
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 140, 2),
+    ]);
+  }
+
+  test_fromExtendingClass_operator_containsSuperCall() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  operator ==(Object o) => o is A;
+}
+class B extends A {
+  @override
+  operator ==(Object o) => o is B && super == o;
+}
+''');
+  }
+
   test_fromInterface() async {
     await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
@@ -112,6 +173,23 @@
     ]);
   }
 
+  test_fromMixin_throughExtendingClass() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+mixin M {
+  @mustCallSuper
+  void a() {}
+}
+class C with M {}
+class D extends C {
+  @override
+  void a() {}
+}
+''', [
+      error(HintCode.MUST_CALL_SUPER, 133, 1),
+    ]);
+  }
+
   test_indirectlyInherited() async {
     await assertErrorsInCode(r'''
 import 'package:meta/meta.dart';
diff --git a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
index 4995806..3643e02 100644
--- a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
@@ -10,11 +10,15 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NoDefaultSuperConstructorTest);
+    defineReflectiveTests(NoDefaultSuperConstructorWithNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class NoDefaultSuperConstructorTest extends PubPackageResolutionTest {
+class NoDefaultSuperConstructorTest extends PubPackageResolutionTest
+    with NoDefaultSuperConstructorTestCases {}
+
+mixin NoDefaultSuperConstructorTestCases on PubPackageResolutionTest {
   test_explicitDefaultSuperConstructor() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -81,3 +85,38 @@
     ]);
   }
 }
+
+@reflectiveTest
+class NoDefaultSuperConstructorWithNullSafetyTest
+    extends PubPackageResolutionTest
+    with NoDefaultSuperConstructorTestCases, WithNullSafetyMixin {
+  test_super_requiredParameter_legacySubclass_explicitConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  A({required String s});
+}
+''');
+    await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_requiredParameter_legacySubclass_implicitConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  A({required String s});
+}
+''');
+    await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
index 28ae14c..080f941 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_from_deferred_library_test.dart
@@ -9,37 +9,21 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(NonConstantListValueFromDeferredLibraryTest);
-    defineReflectiveTests(
-        NonConstantListElementFromDeferredLibraryTest_language24);
+    defineReflectiveTests(NonConstantListElementFromDeferredLibraryTest);
   });
 }
 
 @reflectiveTest
-class NonConstantListElementFromDeferredLibraryTest_language24
+class NonConstantListElementFromDeferredLibraryTest
     extends PubPackageResolutionTest
-    with NonConstantListElementFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantListElementFromDeferredLibraryTestCases {}
 
 mixin NonConstantListElementFromDeferredLibraryTestCases
     on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   @failingTest
   test_const_ifElement_thenTrue_deferredElse() async {
     // reports wrong error code (which is not crucial to fix)
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -54,29 +38,22 @@
   }
 
   test_const_ifElement_thenTrue_deferredThen() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const [ if (cond) a.c ];
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
-                    79,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 69, 13),
-              ]);
+''', [
+      error(
+          CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT_FROM_DEFERRED_LIBRARY,
+          79,
+          3),
+    ]);
   }
 
   test_const_topLevel_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -90,7 +67,7 @@
   }
 
   test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -103,11 +80,3 @@
     ]);
   }
 }
-
-@reflectiveTest
-class NonConstantListValueFromDeferredLibraryTest
-    extends PubPackageResolutionTest
-    with NonConstantListElementFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
index f9038cd..5e51730 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_list_element_test.dart
@@ -10,36 +10,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantListElementTest);
-    defineReflectiveTests(NonConstantListElementTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantListElementTest extends PubPackageResolutionTest
-    with NonConstantListElementTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantListElementTest_language24 extends PubPackageResolutionTest
-    with NonConstantListElementTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantListElementTestCases {}
 
 mixin NonConstantListElementTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_forElement() async {
     await assertErrorsInCode(r'''
 const Set set = {};
@@ -50,119 +28,71 @@
   }
 
   test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 < 0) 0 else a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 < 0) a else 0];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 > 0) 0 else a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 54, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 > 0) a else 0];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const [if (1 < 0) a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 < 0) a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const [if (1 > 0) a];
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const [if (1 > 0) a];
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 36, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 1),
+    ]);
   }
 
   test_const_topVar() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
index 26828b8..f60e50d 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_element_test.dart
@@ -10,40 +10,16 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapElementTest);
-    defineReflectiveTests(NonConstantMapElementTest_language24);
     defineReflectiveTests(NonConstantMapKeyTest);
-    defineReflectiveTests(NonConstantMapKeyTest_language24);
     defineReflectiveTests(NonConstantMapValueTest);
-    defineReflectiveTests(NonConstantMapValueTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantMapElementTest extends PubPackageResolutionTest
-    with NonConstantMapElementTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapElementTest_language24 extends PubPackageResolutionTest
-    with NonConstantMapElementTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapElementTestCases {}
 
 mixin NonConstantMapElementTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_forElement_cannotBeConst() async {
     await assertErrorsInCode('''
 void main() {
@@ -56,21 +32,14 @@
   }
 
   test_forElement_nested_cannotBeConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 void main() {
   const {1: null, if (true) for (final x in const []) null: null};
 }
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 42, 36),
-                error(HintCode.UNUSED_LOCAL_VARIABLE, 53, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 46),
-                error(HintCode.UNUSED_LOCAL_VARIABLE, 53, 1),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 42, 36),
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 53, 1),
+    ]);
   }
 
   test_forElement_notConst_noError() async {
@@ -83,238 +52,133 @@
   }
 
   test_ifElement_mayBeConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 void main() {
   const {1: null, if (true) null: null};
 }
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 20),
-              ]);
+''');
   }
 
   test_ifElement_nested_mayBeConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 void main() {
   const {1: null, if (true) if (true) null: null};
 }
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 30),
-              ]);
+''');
   }
 
   test_ifElement_notConstCondition() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 void main() {
   bool notConst = true;
   const {1: null, if (notConst) null: null};
 }
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 60, 8),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 24),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 60, 8),
+    ]);
   }
 
   test_ifElementWithElse_mayBeConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 void main() {
   const isTrue = true;
   const {1: null, if (isTrue) null: null else null: null};
 }
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 38),
-              ]);
+''');
   }
 
   test_spreadElement_mayBeConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 void main() {
   const {1: null, ...{null: null}};
 }
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 32, 15),
-              ]);
+''');
   }
 
   test_spreadElement_notConst() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 void main() {
   var notConst = {};
   const {1: null, ...notConst};
 }
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 8),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 53, 11),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 8),
+    ]);
   }
 }
 
 @reflectiveTest
 class NonConstantMapKeyTest extends PubPackageResolutionTest
-    with NonConstantMapKeyTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapKeyTest_language24 extends PubPackageResolutionTest
-    with NonConstantMapKeyTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapKeyTestCases {}
 
 @reflectiveTest
 mixin NonConstantMapKeyTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) 0: 0 else a: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 67, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 67, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) a: 0 else 0: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) 0: 0 else a: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 67, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 67, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) a: 0 else 0: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int, int>{if (1 < 0) a: 0};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) a: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int, int>{if (1 > 0) a: 0};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) a: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 57, 1),
+    ]);
   }
 
   test_const_topVar() async {
@@ -336,144 +200,75 @@
 
 @reflectiveTest
 class NonConstantMapValueTest extends PubPackageResolutionTest
-    with NonConstantMapValueTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapValueTest_language24 extends PubPackageResolutionTest
-    with NonConstantMapValueTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapValueTestCases {}
 
 mixin NonConstantMapValueTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) 0: 0 else 0: a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 70, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 70, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) 0: a else 0: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) 0: 0 else 0: a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 70, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 70, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) 0: a else 0: 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int, int>{if (1 < 0) 0: a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 < 0) 0: a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int, int>{if (1 > 0) 0: a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int, int>{if (1 > 0) 0: a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 46, 15),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 60, 1),
+    ]);
   }
 
   test_const_topVar() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
index f6526ff..cc4d444 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_from_deferred_library_test.dart
@@ -10,42 +10,19 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapKeyFromDeferredLibraryTest);
-    defineReflectiveTests(NonConstantMapKeyFromDeferredLibraryTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantMapKeyFromDeferredLibraryTest extends PubPackageResolutionTest
-    with NonConstantMapKeyFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapKeyFromDeferredLibraryTest_language24
-    extends PubPackageResolutionTest
-    with NonConstantMapKeyFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapKeyFromDeferredLibraryTestCases {}
 
 mixin NonConstantMapKeyFromDeferredLibraryTestCases
     on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   @failingTest
   test_const_ifElement_thenTrue_deferredElse() async {
 // reports wrong error code
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -58,29 +35,20 @@
   }
 
   test_const_ifElement_thenTrue_deferredThen() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const { if (cond) a.c : 0};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY,
-                    79,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 69, 17),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY, 79,
+          3),
+    ]);
   }
 
   test_const_topLevel_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -92,7 +60,7 @@
   }
 
   test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
index f8b166b..8d42bf8 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_key_test.dart
@@ -10,66 +10,32 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapKeyTest);
-    defineReflectiveTests(NonConstantMapKeyTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantMapKeyTest extends PubPackageResolutionTest
-    with NonConstantMapKeyTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapKeyTest_language24 extends PubPackageResolutionTest
-    with NonConstantMapKeyTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapKeyTestCases {}
 
 mixin NonConstantMapKeyTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenTrue_elseFinal() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 0: 1 else a : 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 75, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 25),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 75, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_thenFinal() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) a : 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 65, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 15),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 65, 1),
+    ]);
   }
 
   test_const_topLevel() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
index ad0ec5b..aec5701 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_from_deferred_library_test.dart
@@ -10,44 +10,20 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapValueFromDeferredLibraryTest);
-    defineReflectiveTests(
-        NonConstantMapValueFromDeferredLibraryTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantMapValueFromDeferredLibraryTest
     extends PubPackageResolutionTest
-    with NonConstantMapValueFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapValueFromDeferredLibraryTest_language24
-    extends PubPackageResolutionTest
-    with NonConstantMapValueFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapValueFromDeferredLibraryTestCases {}
 
 mixin NonConstantMapValueFromDeferredLibraryTestCases
     on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   @failingTest
   test_const_ifElement_thenTrue_elseDeferred() async {
     // reports wrong error code
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -60,29 +36,20 @@
   }
 
   test_const_ifElement_thenTrue_thenDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const { if (cond) 'a' : a.c};
-''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
-                    85,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 69, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE_FROM_DEFERRED_LIBRARY,
+          85, 3),
+    ]);
   }
 
   test_const_topLevel_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -94,7 +61,7 @@
   }
 
   test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
index 74c3160..26a41df 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_map_value_test.dart
@@ -10,67 +10,32 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantMapValueTest);
-    defineReflectiveTests(NonConstantMapValueTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantMapValueTest extends PubPackageResolutionTest
-    with NonConstantMapValueTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantMapValueTest_language24 extends PubPackageResolutionTest
-    with NonConstantMapValueTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantMapValueTestCases {}
 
 mixin NonConstantMapValueTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifTrue_elseFinal() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 'a': 'b', 'c' : a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 81, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 18),
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 81, 1),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 81, 1),
+    ]);
   }
 
   test_const_ifTrue_thenFinal() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 final dynamic a = 0;
 const cond = true;
 var v = const {if (cond) 'a' : a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 71, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 55, 17),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 71, 1),
+    ]);
   }
 
   test_const_topLevel() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
index 8adf61f..5e28579 100644
--- a/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_constant_set_element_test.dart
@@ -10,36 +10,14 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantSetElementTest);
-    defineReflectiveTests(NonConstantSetElementTest_language24);
   });
 }
 
 @reflectiveTest
 class NonConstantSetElementTest extends PubPackageResolutionTest
-    with NonConstantSetElementTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class NonConstantSetElementTest_language24 extends PubPackageResolutionTest
-    with NonConstantSetElementTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with NonConstantSetElementTestCases {}
 
 mixin NonConstantSetElementTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_forElement() async {
     await assertErrorsInCode(r'''
 const Set set = {};
@@ -50,119 +28,71 @@
   }
 
   test_const_ifElement_thenElseFalse_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 < 0) 0 else a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 < 0) a else 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalElse() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 > 0) 0 else a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 59, 1),
+    ]);
   }
 
   test_const_ifElement_thenElseTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 > 0) a else 0};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int>{if (1 < 0) a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenFalse_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 < 0) a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+    ]);
   }
 
   test_const_ifElement_thenTrue_constThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int>{if (1 > 0) a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_finalThen() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 final dynamic a = 0;
 var v = const <int>{if (1 > 0) a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 12),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 52, 1),
+    ]);
   }
 
   test_const_parameter() async {
@@ -175,18 +105,12 @@
   }
 
   test_const_spread_final() async {
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 final Set x = null;
 var v = const {...x};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 38, 1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 35, 4),
-              ]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 38, 1),
+    ]);
   }
 
   test_const_topVar() async {
diff --git a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
index df5882b..3154db5 100644
--- a/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_assigned_potentially_non_nullable_local_variable_test.dart
@@ -84,8 +84,6 @@
 }
 ''', [
       _notAssignedError(22, 1),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 28, 2),
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
     ]);
   }
@@ -98,8 +96,6 @@
 }
 ''', [
       _notAssignedError(22, 1),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 28, 2),
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 28, 1),
       _notAssignedError(28, 1),
     ]);
@@ -124,8 +120,6 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 33, 1),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 33, 7),
     ]);
   }
 
@@ -138,15 +132,13 @@
 }
 ''', [
       error(StaticWarningCode.DEAD_NULL_AWARE_EXPRESSION, 32, 7),
-      // See https://github.com/dart-lang/sdk/issues/43263.
-      error(HintCode.DEAD_CODE, 32, 13),
       _notAssignedError(43, 1),
     ]);
   }
 
   test_binaryExpression_logicalAnd_left() async {
     await assertNoErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   ((v = 0) >= 0) && c;
   v;
@@ -156,19 +148,19 @@
 
   test_binaryExpression_logicalAnd_right() async {
     await assertErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   c && ((v = 0) >= 0);
   v;
 }
 ''', [
-      _notAssignedError(49, 1),
+      _notAssignedError(51, 1),
     ]);
   }
 
   test_binaryExpression_logicalOr_left() async {
     await assertNoErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   ((v = 0) >= 0) || c;
   v;
@@ -178,13 +170,13 @@
 
   test_binaryExpression_logicalOr_right() async {
     await assertErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   c || ((v = 0) >= 0);
   v;
 }
 ''', [
-      _notAssignedError(49, 1),
+      _notAssignedError(51, 1),
     ]);
   }
 
@@ -842,7 +834,7 @@
 
   test_if_then() async {
     await assertErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   if (c) {
     v = 0;
@@ -850,13 +842,13 @@
   v;
 }
 ''', [
-      _notAssignedError(52, 1),
+      _notAssignedError(54, 1),
     ]);
   }
 
   test_if_thenElse_all() async {
     await assertNoErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   if (c) {
     v = 0;
@@ -872,7 +864,7 @@
 
   test_if_thenElse_else() async {
     await assertErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   if (c) {
     // not assigned
@@ -882,13 +874,13 @@
   v;
 }
 ''', [
-      _notAssignedError(83, 1),
+      _notAssignedError(85, 1),
     ]);
   }
 
   test_if_thenElse_then() async {
     await assertErrorsInCode(r'''
-main(bool c) {
+void f(bool c) {
   int v;
   if (c) {
     v = 0;
@@ -898,7 +890,7 @@
   v;
 }
 ''', [
-      _notAssignedError(83, 1),
+      _notAssignedError(85, 1),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index a5edc42..3574235 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -19,12 +19,12 @@
     with WithNullSafetyMixin {
   test_binaryExpression_never_eqEq() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x == 1 + 2;
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 28, 6),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 25, 6),
     ]);
 
     assertBinaryExpression(
@@ -38,12 +38,12 @@
 
   test_binaryExpression_never_plus() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x + (1 + 2);
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 27, 8),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 24, 8),
     ]);
 
     assertBinaryExpression(
@@ -57,7 +57,7 @@
 
   test_binaryExpression_neverQ_eqEq() async {
     await assertNoErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x == 1 + 2;
 }
 ''');
@@ -73,11 +73,11 @@
 
   test_binaryExpression_neverQ_plus() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x + (1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertBinaryExpression(
@@ -91,7 +91,7 @@
 
   test_conditionalExpression_falseBranch() async {
     await assertNoErrorsInCode(r'''
-void main(bool c, Never x) {
+void f(bool c, Never x) {
   c ? 0 : x;
 }
 ''');
@@ -99,7 +99,7 @@
 
   test_conditionalExpression_trueBranch() async {
     await assertNoErrorsInCode(r'''
-void main(bool c, Never x) {
+void f(bool c, Never x) {
   c ? x : 0;
 }
 ''');
@@ -107,32 +107,32 @@
 
   test_functionExpressionInvocation_never() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x();
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
     ]);
   }
 
   test_functionExpressionInvocation_neverQ() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x();
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
   }
 
   test_indexExpression_never_read() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x[0];
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 25, 3),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 22, 3),
     ]);
 
     assertIndexExpression(
@@ -145,19 +145,19 @@
 
   test_indexExpression_never_readWrite() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x[0] += 1 + 2;
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 25, 12),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 22, 12),
     ]);
 
     assertIndexExpression(
       findNode.index('x[0]'),
       readElement: null,
       writeElement: null,
-      type: 'Never',
+      type: 'dynamic',
     );
 
     assertType(findNode.binary('1 + 2'), 'int');
@@ -165,12 +165,12 @@
 
   test_indexExpression_never_write() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x[0] = 1 + 2;
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 25, 11),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 22, 11),
     ]);
 
     assertIndexExpression(
@@ -185,12 +185,11 @@
 
   test_indexExpression_neverQ_read() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x[0];
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 25, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertIndexExpression(
@@ -203,13 +202,11 @@
 
   test_indexExpression_neverQ_readWrite() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x[0] += 1 + 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 25, 3),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 25, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertIndexExpression(
@@ -224,12 +221,11 @@
 
   test_indexExpression_neverQ_write() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x[0] = 1 + 2;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 25, 3),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertIndexExpression(
@@ -244,20 +240,20 @@
 
   test_invocationArgument() async {
     await assertNoErrorsInCode(r'''
-void main(f, Never x) {
-  f(x);
+void f(g, Never x) {
+  g(x);
 }
 ''');
   }
 
   test_methodInvocation_never() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.foo(1 + 2);
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 28, 8),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 25, 8),
     ]);
 
     assertMethodInvocation(
@@ -273,12 +269,12 @@
 
   test_methodInvocation_never_toString() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.toString(1 + 2);
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
-      error(HintCode.DEAD_CODE, 33, 8),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
+      error(HintCode.DEAD_CODE, 30, 8),
     ]);
 
     assertMethodInvocation(
@@ -294,11 +290,11 @@
 
   test_methodInvocation_neverQ_toString() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x.toString(1 + 2);
 }
 ''', [
-      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 34, 7),
+      error(CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, 31, 7),
     ]);
 
     assertMethodInvocation(
@@ -314,11 +310,11 @@
 
   test_postfixExpression_never_plusPlus() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x++;
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 23, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
     ]);
 
     assertPostfixExpression(
@@ -334,11 +330,11 @@
 
   test_postfixExpression_neverQ_plusPlus() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x++;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertPostfixExpression(
@@ -355,11 +351,11 @@
   test_prefixExpression_never_plusPlus() async {
     // Reports 'undefined operator'
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   ++x;
 }
 ''', [
-      error(HintCode.RECEIVER_OF_TYPE_NEVER, 25, 1),
+      error(HintCode.RECEIVER_OF_TYPE_NEVER, 22, 1),
     ]);
 
     assertPrefixExpression(
@@ -375,11 +371,11 @@
 
   test_prefixExpression_neverQ_plusPlus() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   ++x;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 26, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 23, 1),
     ]);
 
     assertPrefixExpression(
@@ -395,7 +391,7 @@
 
   test_propertyAccess_never_read() async {
     await assertNoErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.foo;
 }
 ''');
@@ -410,7 +406,7 @@
 
   test_propertyAccess_never_read_hashCode() async {
     await assertNoErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.hashCode;
 }
 ''');
@@ -425,18 +421,18 @@
 
   test_propertyAccess_never_readWrite() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.foo += 0;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 32, 2),
+      error(HintCode.DEAD_CODE, 29, 2),
     ]);
 
     assertSimpleIdentifier(
       findNode.simple('foo'),
       readElement: null,
       writeElement: null,
-      type: 'Never',
+      type: 'dynamic',
     );
 
     assertAssignment(
@@ -446,13 +442,13 @@
       writeElement: null,
       writeType: 'dynamic',
       operatorElement: null,
-      type: 'int',
+      type: 'dynamic',
     );
   }
 
   test_propertyAccess_never_tearOff_toString() async {
     await assertNoErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.toString;
 }
 ''');
@@ -467,11 +463,11 @@
 
   test_propertyAccess_never_write() async {
     await assertErrorsInCode(r'''
-void main(Never x) {
+void f(Never x) {
   x.foo = 0;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 31, 2),
+      error(HintCode.DEAD_CODE, 28, 2),
     ]);
 
     assertSimpleIdentifier(
@@ -494,11 +490,11 @@
 
   test_propertyAccess_neverQ_read() async {
     await assertErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x.foo;
 }
 ''', [
-      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 24, 1),
+      error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 21, 1),
     ]);
 
     assertSimpleIdentifier(
@@ -511,7 +507,7 @@
 
   test_propertyAccess_neverQ_read_hashCode() async {
     await assertNoErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x.hashCode;
 }
 ''');
@@ -526,7 +522,7 @@
 
   test_propertyAccess_neverQ_tearOff_toString() async {
     await assertNoErrorsInCode(r'''
-void main(Never? x) {
+void f(Never? x) {
   x.toString;
 }
 ''');
@@ -544,7 +540,7 @@
 class InvalidUseOfNeverTest_Legacy extends PubPackageResolutionTest {
   test_binaryExpression_eqEq() async {
     await assertNoErrorsInCode(r'''
-void main() {
+void f() {
   (throw '') == 1 + 2;
 }
 ''');
@@ -562,13 +558,11 @@
   }
 
   test_binaryExpression_plus() async {
-    await assertErrorsInCode(r'''
-void main() {
+    await assertNoErrorsInCode(r'''
+void f() {
   (throw '') + (1 + 2);
 }
-''', [
-      error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 27, 1),
-    ]);
+''');
 
     assertBinaryExpression(
       findNode.binary('+ ('),
@@ -581,7 +575,7 @@
 
   test_methodInvocation_toString() async {
     await assertNoErrorsInCode(r'''
-void main() {
+void f() {
   (throw '').toString();
 }
 ''');
@@ -596,7 +590,7 @@
 
   test_propertyAccess_toString() async {
     await assertNoErrorsInCode(r'''
-void main() {
+void f() {
   (throw '').toString;
 }
 ''');
@@ -614,7 +608,7 @@
 
   test_throw_getter_hashCode() async {
     await assertNoErrorsInCode(r'''
-void main() {
+void f() {
   (throw '').hashCode;
 }
 ''');
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart
new file mode 100644
index 0000000..c747e6a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/return_of_do_not_store_test.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ReturnOfDoNotStoreTest);
+  });
+}
+
+@reflectiveTest
+class ReturnOfDoNotStoreTest extends PubPackageResolutionTest {
+  @override
+  void setUp() {
+    super.setUp();
+    writeTestPackageConfigWithMeta();
+  }
+
+  test_returnFromFunction() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String v = '';
+
+String getV() {
+  return v;
+}
+
+String getV2() => v;
+
+@doNotStore
+String getV3() => v;
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 87, 1, messageContains: 'getV'),
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 111, 1, messageContains: 'getV2'),
+    ]);
+  }
+
+  test_returnFromGetter() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String _v = '';
+
+String get v {
+  return _v;
+}
+
+String get v2 => _v;
+
+@doNotStore
+String get v3 => _v;
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 87, 2, messageContains: 'v'),
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 111, 2, messageContains: 'v2'),
+    ]);
+  }
+
+  test_returnFromGetter_binaryExpression() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String _v = '';
+
+@doNotStore
+String _v2 = '';
+
+var b = true;
+
+String get v => _v ?? _v2;
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 124, 2, messageContains: '_v'),
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 130, 3, messageContains: '_v2'),
+    ]);
+  }
+
+  test_returnFromGetter_ternary() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+@doNotStore
+String _v = '';
+
+@doNotStore
+String _v2 = '';
+
+var b = true;
+
+String get v => b ? _v : _v2;
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 128, 2),
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 133, 3),
+    ]);
+  }
+
+  test_returnFromMethod() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta.dart';
+
+class A {
+  @doNotStore
+  String _v = '';
+
+  String getV() {
+    return _v;
+  }
+
+  String getV2() => _v;
+  
+  @doNotStore
+  String getV3() => _v;
+}
+''', [
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 106, 2, messageContains: 'getV'),
+      error(HintCode.RETURN_OF_DO_NOT_STORE, 135, 2, messageContains: 'getV2'),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
index 1a89d0a..e5e1fd7 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_from_deferred_library_test.dart
@@ -10,41 +10,18 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetElementFromDeferredLibraryTest);
-    defineReflectiveTests(SetElementFromDeferredLibraryTest_language24);
   });
 }
 
 @reflectiveTest
 class SetElementFromDeferredLibraryTest extends PubPackageResolutionTest
-    with SetElementFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class SetElementFromDeferredLibraryTest_language24
-    extends PubPackageResolutionTest
-    with SetElementFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with SetElementFromDeferredLibraryTestCases {}
 
 mixin SetElementFromDeferredLibraryTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   @failingTest
   test_const_ifElement_thenTrue_elseDeferred() async {
     // reports wrong error code
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -56,26 +33,19 @@
   }
 
   test_const_ifElement_thenTrue_thenDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 const cond = true;
 var v = const {if (cond) a.c};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY,
-                    78, 3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 68, 13),
-              ]);
+''', [
+      error(CompileTimeErrorCode.SET_ELEMENT_FROM_DEFERRED_LIBRARY, 78, 3),
+    ]);
   }
 
   test_const_topLevel_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -86,7 +56,7 @@
   }
 
   test_const_topLevel_deferred_nested() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const int c = 1;''');
     await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
index d7349b8..1d34872 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -10,136 +10,67 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetElementTypeNotAssignableTest);
-    defineReflectiveTests(SetElementTypeNotAssignableTest_language24);
   });
 }
 
 @reflectiveTest
 class SetElementTypeNotAssignableTest extends PubPackageResolutionTest
-    with SetElementTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class SetElementTypeNotAssignableTest_language24
-    extends PubPackageResolutionTest with SetElementTypeNotAssignableTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with SetElementTypeNotAssignableTestCases {}
 
 mixin SetElementTypeNotAssignableTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_const_ifElement_thenElseFalse_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 0;
 var v = const <int>{if (1 < 0) a else b};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 62, 19),
-              ]);
+''');
   }
 
   test_const_ifElement_thenElseFalse_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 0;
 const dynamic b = 'b';
 var v = const <int>{if (1 < 0) a else b};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 82,
-                    1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 64, 19),
-              ]);
+''', [
+      error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 82, 1),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 var v = const <int>{if (1 < 0) 'a'};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 31,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 20, 14),
-                error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 31,
-                    3),
-              ]);
+''', [
+      error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 31, 3),
+    ]);
   }
 
   test_const_ifElement_thenFalse_intString_dynamic() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int>{if (1 < 0) a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 43, 12),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 const dynamic a = 0;
 var v = const <int>{if (true) a};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 41, 11),
-              ]);
+''');
   }
 
   test_const_ifElement_thenTrue_intString() async {
-    await assertErrorsInCode(
-        '''
+    await assertErrorsInCode('''
 const dynamic a = 'a';
 var v = const <int>{if (true) a};
-''',
-        _constant_update_2018
-            ? [
-                error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 53,
-                    1),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 43, 11),
-              ]);
+''', [
+      error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 53, 1),
+    ]);
   }
 
   test_const_spread_intInt() async {
-    await assertErrorsInCode(
-        '''
+    await assertNoErrorsInCode('''
 var v = const <int>{...[0, 1]};
-''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 20, 9),
-              ]);
+''');
   }
 
   test_explicitTypeArgs_const() async {
diff --git a/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart b/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
index 3c9b2a3..cf83fc1 100644
--- a/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/spread_expression_from_deferred_library_test.dart
@@ -10,61 +10,29 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SpreadExpressionFromDeferredLibraryTest);
-    defineReflectiveTests(SpreadExpressionFromDeferredLibraryTest_language24);
   });
 }
 
 @reflectiveTest
 class SpreadExpressionFromDeferredLibraryTest extends PubPackageResolutionTest
-    with SpreadExpressionFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => true;
-}
-
-@reflectiveTest
-class SpreadExpressionFromDeferredLibraryTest_language24
-    extends PubPackageResolutionTest
-    with SpreadExpressionFromDeferredLibraryTestCases {
-  @override
-  bool get _constant_update_2018 => false;
-
-  @override
-  void setUp() {
-    super.setUp();
-    writeTestPackageConfig(
-      PackageConfigFileBuilder(),
-      languageVersion: '2.4',
-    );
-  }
-}
+    with SpreadExpressionFromDeferredLibraryTestCases {}
 
 mixin SpreadExpressionFromDeferredLibraryTestCases on PubPackageResolutionTest {
-  bool get _constant_update_2018;
-
   test_inList_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const List c = [];''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const [...a.c];
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 56, 6),
-              ]);
+}''', [
+      error(
+          CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+    ]);
   }
 
   test_inList_deferred_notConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const List c = [];''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -74,45 +42,30 @@
   }
 
   test_inList_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const List c = [];''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const [...a.c];
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 47, 6),
-              ]);
+}''');
   }
 
   test_inMap_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Map c = <int, int>{};''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const {...a.c};
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 56, 6),
-              ]);
+}''', [
+      error(
+          CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+    ]);
   }
 
   test_inMap_notConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Map c = <int, int>{};''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -122,45 +75,30 @@
   }
 
   test_inMap_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Map c = <int, int>{};''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const {...a.c};
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 6),
-              ]);
+}''');
   }
 
   test_inSet_deferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Set c = <int>{};''');
-    await assertErrorsInCode(
-        r'''
+    await assertErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
 f() {
   return const {...a.c};
-}''',
-        _constant_update_2018
-            ? [
-                error(
-                    CompileTimeErrorCode
-                        .SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY,
-                    59,
-                    3),
-              ]
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 56, 6),
-              ]);
+}''', [
+      error(
+          CompileTimeErrorCode.SPREAD_EXPRESSION_FROM_DEFERRED_LIBRARY, 59, 3),
+    ]);
   }
 
   test_inSet_notConst() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Set c = <int>{};''');
     await assertNoErrorsInCode(r'''
 import 'lib1.dart' deferred as a;
@@ -170,18 +108,12 @@
   }
 
   test_inSet_notDeferred() async {
-    newFile(convertPath('$testPackageLibPath/lib1.dart'), content: r'''
+    newFile('$testPackageLibPath/lib1.dart', content: r'''
 const Set c = <int>{};''');
-    await assertErrorsInCode(
-        r'''
+    await assertNoErrorsInCode(r'''
 import 'lib1.dart' as a;
 f() {
   return const {...a.c};
-}''',
-        _constant_update_2018
-            ? []
-            : [
-                error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 47, 6),
-              ]);
+}''');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart b/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
index 3b2acfa..9322aa2 100644
--- a/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/subtype_of_sealed_class_test.dart
@@ -28,7 +28,7 @@
       meta: true,
     );
 
-    await newFile('$workspaceRootPath/foo/lib/foo.dart', content: r'''
+    newFile('$workspaceRootPath/foo/lib/foo.dart', content: r'''
 import 'package:meta/meta.dart';
 @sealed class Foo {}
 ''');
@@ -156,7 +156,7 @@
   }
 
   test_withinPackageLibDirectory_OK() async {
-    await newFile('$testPackageLibPath/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'package:meta/meta.dart';
 @sealed class Foo {}
 ''');
@@ -172,7 +172,7 @@
   }
 
   test_withinPackageTestDirectory_OK() async {
-    await newFile('$testPackageLibPath/a.dart', content: r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'package:meta/meta.dart';
 @sealed class Foo {}
 ''');
@@ -198,7 +198,7 @@
 @sealed class Foo {}
 ''');
 
-    await newFile(partPath, content: r'''
+    newFile(partPath, content: r'''
 part of 'a.dart';
 class Bar1 extends Foo {}
 class Bar2 implements Foo {}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 94870ce..6d57dca 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -37,6 +37,7 @@
 import 'await_in_late_local_variable_initializer_test.dart'
     as await_in_late_local_variable_initializer;
 import 'await_in_wrong_context_test.dart' as await_in_wrong_context;
+import 'binary_operator_written_out_test.dart' as binary_operator_written_out;
 import 'body_might_complete_normally_test.dart' as body_might_complete_normally;
 import 'built_in_identifier_as_extension_name_test.dart'
     as built_in_as_extension_name;
@@ -113,8 +114,6 @@
 import 'default_list_constructor_test.dart' as default_list_constructor;
 import 'default_value_in_function_type_test.dart'
     as default_value_in_function_type;
-import 'default_value_in_function_typed_parameter_test.dart'
-    as default_value_in_function_typed_parameter;
 import 'default_value_in_redirecting_factory_constructor_test.dart'
     as default_value_in_redirecting_factory_constructor;
 import 'default_value_on_required_parameter_test.dart'
@@ -278,6 +277,8 @@
 import 'invalid_constant_test.dart' as invalid_constant;
 import 'invalid_constructor_name_test.dart' as invalid_constructor_name;
 import 'invalid_exception_value_test.dart' as invalid_exception_value;
+import 'invalid_export_of_internal_element_test.dart'
+    as invalid_export_of_internal_element;
 import 'invalid_extension_argument_count_test.dart'
     as invalid_extension_argument_count;
 import 'invalid_factory_annotation_test.dart' as invalid_factory_annotation;
@@ -286,6 +287,7 @@
     as invalid_factory_name_not_a_class;
 import 'invalid_field_type_in_struct_test.dart' as invalid_field_type_in_struct;
 import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
+import 'invalid_internal_annotation_test.dart' as invalid_internal_annotation;
 import 'invalid_language_override_greater_test.dart'
     as invalid_language_override_greater;
 import 'invalid_language_override_test.dart' as invalid_language_override;
@@ -320,6 +322,8 @@
 import 'invalid_uri_test.dart' as invalid_uri;
 import 'invalid_use_of_covariant_in_extension_test.dart'
     as invalid_use_of_covariant_in_extension;
+import 'invalid_use_of_internal_member_test.dart'
+    as invalid_use_of_internal_member;
 import 'invalid_use_of_protected_member_test.dart'
     as invalid_use_of_protected_member;
 import 'invalid_use_of_visible_for_template_member_test.dart'
@@ -340,6 +344,13 @@
     as late_final_local_already_assigned;
 import 'list_element_type_not_assignable_test.dart'
     as list_element_type_not_assignable;
+import 'main_first_positional_parameter_type_test.dart'
+    as main_first_positional_parameter_type;
+import 'main_has_required_named_parameters_test.dart'
+    as main_has_required_named_parameters;
+import 'main_has_too_many_required_positional_parameters_test.dart'
+    as main_has_too_many_required_positional_parameters;
+import 'main_is_not_function_test.dart' as main_is_not_function;
 import 'map_entry_not_in_map_test.dart' as map_entry_not_in_map;
 import 'map_key_type_not_assignable_test.dart' as map_key_type_not_assignable;
 import 'map_value_type_not_assignable_test.dart'
@@ -518,6 +529,7 @@
 import 'return_in_generative_constructor_test.dart'
     as return_in_generative_constructor;
 import 'return_in_generator_test.dart' as return_in_generator;
+import 'return_of_do_not_store_test.dart' as return_of_do_not_store;
 import 'return_of_invalid_type_test.dart' as return_of_invalid_type;
 import 'return_without_value_test.dart' as return_without_value;
 import 'sdk_version_as_expression_in_const_context_test.dart'
@@ -668,6 +680,7 @@
     async_keyword_used_as_identifier.main();
     await_in_late_local_variable_initializer.main();
     await_in_wrong_context.main();
+    binary_operator_written_out.main();
     body_might_complete_normally.main();
     built_in_as_extension_name.main();
     built_in_as_prefix_name.main();
@@ -717,7 +730,6 @@
     dead_null_aware_expression.main();
     default_list_constructor.main();
     default_value_in_function_type.main();
-    default_value_in_function_typed_parameter.main();
     default_value_in_redirecting_factory_constructor.main();
     default_value_on_required_parameter.main();
     deferred_import_of_extension.main();
@@ -825,12 +837,14 @@
     invalid_constant.main();
     invalid_constructor_name.main();
     invalid_exception_value.main();
+    invalid_export_of_internal_element.main();
     invalid_extension_argument_count.main();
     invalid_factory_annotation.main();
     invalid_factory_method_impl.main();
     invalid_factory_name_not_a_class.main();
     invalid_field_type_in_struct.main();
     invalid_immutable_annotation.main();
+    invalid_internal_annotation.main();
     invalid_language_override_greater.main();
     invalid_language_override.main();
     invalid_literal_annotation.main();
@@ -853,6 +867,7 @@
     invalid_type_argument_in_const_set.main();
     invalid_uri.main();
     invalid_use_of_covariant_in_extension.main();
+    invalid_use_of_internal_member.main();
     invalid_use_of_protected_member.main();
     invalid_use_of_visible_for_template_member.main();
     invalid_use_of_visible_for_testing_member.main();
@@ -864,6 +879,10 @@
     late_final_field_with_const_constructor.main();
     late_final_local_already_assigned.main();
     list_element_type_not_assignable.main();
+    main_first_positional_parameter_type.main();
+    main_has_required_named_parameters.main();
+    main_has_too_many_required_positional_parameters.main();
+    main_is_not_function.main();
     map_entry_not_in_map.main();
     map_key_type_not_assignable.main();
     map_value_type_not_assignable.main();
@@ -982,6 +1001,7 @@
     rethrow_outside_catch.main();
     return_in_generative_constructor.main();
     return_in_generator.main();
+    return_of_do_not_store.main();
     return_of_invalid_type.main();
     return_without_value.main();
     set_element_from_deferred_library.main();
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_annotation_test.dart
index 779d2d2..711ac51 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_annotation_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_annotation_test.dart
@@ -15,6 +15,16 @@
 
 @reflectiveTest
 class UndefinedAnnotationTest extends PubPackageResolutionTest {
+  test_identifier1_localVariable_const() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  const a = 0;
+  g(@a x) {}
+  g(0);
+}
+''');
+  }
+
   test_unresolved_identifier() async {
     await assertErrorsInCode(r'''
 @unresolved
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
index a668a46..baf399c 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -123,11 +123,11 @@
     // Referencing `.call` on a `Function` type works similarly to referencing
     // it on `dynamic`--the reference is accepted at compile time, and all type
     // checking is deferred until runtime.
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 f(Function f) {
   return f.call;
 }
-''', []);
+''');
   }
 
   test_ifElement_inList_notPromoted() async {
@@ -235,7 +235,6 @@
 ''',
         expectedErrorsByNullability(nullable: [
           error(CompileTimeErrorCode.INVALID_USE_OF_NULL_VALUE, 22, 5),
-          error(CompileTimeErrorCode.UNDEFINED_GETTER, 28, 3),
         ], legacy: [
           error(CompileTimeErrorCode.UNDEFINED_GETTER, 28, 3),
         ]));
@@ -263,6 +262,26 @@
     ]);
   }
 
+  test_propertyAccess_functionClass_call() async {
+    await assertNoErrorsInCode('''
+void f(Function a) {
+  return (a).call;
+}
+''');
+  }
+
+  test_propertyAccess_functionType_call() async {
+    await assertNoErrorsInCode('''
+class A {
+  void staticMethod() {}
+}
+
+void f(A a) {
+  return a.staticMethod.call;
+}
+''');
+  }
+
   test_proxy_annotation_fakeProxy() async {
     await assertErrorsInCode(r'''
 library L;
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index a173cf5..6195779 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
@@ -28,6 +28,28 @@
     ]);
   }
 
+  test_compoundAssignment_noGetter_hasSetter() async {
+    await assertErrorsInCode('''
+set foo(int _) {}
+
+void f() {
+  foo += 0;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 32, 3),
+    ]);
+  }
+
+  test_compoundAssignment_noGetter_noSetter() async {
+    await assertErrorsInCode('''
+void f() {
+  foo += 0;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 13, 3),
+    ]);
+  }
+
   test_for() async {
     await assertErrorsInCode('''
 f(var l) {
@@ -126,6 +148,30 @@
     ]);
   }
 
+  test_postfixExpression_increment_noGetter_hasSetter() async {
+    await assertErrorsInCode('''
+set foo(int _) {}
+
+void f() {
+  foo++;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 32, 3),
+    ]);
+  }
+
+  test_prefixExpression_increment_noGetter_hasSetter() async {
+    await assertErrorsInCode('''
+set foo(int _) {}
+
+void f() {
+  ++foo;
+}
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 34, 3),
+    ]);
+  }
+
   test_private_getter() async {
     newFile('$testPackageLibPath/lib.dart', content: '''
 library lib;
@@ -175,13 +221,13 @@
   test_synthetic_whenMethodName_defined() async {
     await assertErrorsInCode(r'''
 print(x) {}
-main(int p) {
+void f(int p) {
   p.();
 }
 ''', [
-      error(ParserErrorCode.MISSING_IDENTIFIER, 30, 1),
-      error(CompileTimeErrorCode.UNDEFINED_GETTER, 30, 1),
-      error(ParserErrorCode.MISSING_IDENTIFIER, 31, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 32, 1),
+      error(CompileTimeErrorCode.UNDEFINED_GETTER, 32, 1),
+      error(ParserErrorCode.MISSING_IDENTIFIER, 33, 1),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
index e59a967..a022829 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
@@ -624,7 +624,6 @@
 }
 ''', [
       error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 58, 1),
-      error(CompileTimeErrorCode.UNDEFINED_GETTER, 60, 3),
     ]);
   }
 
@@ -876,7 +875,6 @@
 }
 ''', [
       error(CompileTimeErrorCode.UNCHECKED_USE_OF_NULLABLE_VALUE, 54, 1),
-      error(CompileTimeErrorCode.UNDEFINED_METHOD, 56, 3),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
index 95b1703..1d0363e 100644
--- a/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/invalid_code_test.dart
@@ -29,9 +29,13 @@
   void test_default_asVariableName() {
     testRecovery('''
 const default = const Object();
-''', [ParserErrorCode.MISSING_IDENTIFIER], '''
+''', [
+      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+    ], '''
 const default = const Object();
-''', expectedErrorsInValidCode: [ParserErrorCode.MISSING_IDENTIFIER]);
+''', expectedErrorsInValidCode: [
+      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+    ]);
   }
 
   void test_expressionInPlaceOfTypeName() {
@@ -82,12 +86,16 @@
 g() {
   f(with: 3);
 }
-''', [ParserErrorCode.MISSING_IDENTIFIER], '''
+''', [
+      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+    ], '''
 f() {}
 g() {
   f(with: 3);
 }
-''', expectedErrorsInValidCode: [ParserErrorCode.MISSING_IDENTIFIER]);
+''', expectedErrorsInValidCode: [
+      ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+    ]);
   }
 
   @failingTest
diff --git a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
index c8a02f7..1b663a6 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -2,9 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:pub_semver/pub_semver.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'recovery_test_support.dart';
@@ -58,31 +56,6 @@
 /// Test how well the parser recovers when tokens are missing in a map literal.
 @reflectiveTest
 class MapLiteralTest extends AbstractRecoveryTest {
-  final beforeUiAsCode = FeatureSet.fromEnableFlags2(
-    sdkLanguageVersion: Version.parse('2.2.0'),
-    flags: [],
-  );
-
-  void test_extraComma() {
-    testRecovery('''
-f() => {a: b, , c: d};
-''', [
-      ParserErrorCode.MISSING_IDENTIFIER,
-      ParserErrorCode.EXPECTED_TOKEN,
-      ParserErrorCode.MISSING_IDENTIFIER
-    ], '''
-f() => {a: b, _s_: _s_, c: d};
-''', featureSet: beforeUiAsCode);
-  }
-
-  void test_missingColonAndValue_last() {
-    testRecovery('''
-f() => {a: b, c };
-''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER], '''
-f() => {a: b, c: _s_};
-''', featureSet: beforeUiAsCode);
-  }
-
   void test_missingComma() {
     testRecovery('''
 f() => {a: b, c: d e: f};
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index e21ccd8..3e2aa12 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -201,6 +201,39 @@
     expect(library.uriStr, 'package:test/test.dart');
   }
 
+  test_getLibrary_export_notExisting() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+export 'b.dart';
+class A {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+
+    var id = uriToLibrary['package:test/a.dart'].id;
+    var library = tracker.getLibrary(id);
+    expect(library.id, id);
+  }
+
+  test_getLibrary_exportViaRecursiveLink() async {
+    resourceProvider.newLink(
+      convertPath('/home/test/lib/foo'),
+      convertPath('/home/test/lib'),
+    );
+
+    newFile('/home/test/lib/a.dart', content: r'''
+export 'foo/a.dart';
+class A {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+
+    var id = uriToLibrary['package:test/a.dart'].id;
+    var library = tracker.getLibrary(id);
+    expect(library.id, id);
+  }
+
   test_readByteStore() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 1158676..d4fd128 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -12,6 +12,7 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 
 import 'resolved_ast_printer.dart';
@@ -55,6 +56,7 @@
   bool withSyntheticAccessors = false,
   bool withSyntheticFields = false,
   bool withTypes = false,
+  bool withTypeParameterVariance = false,
   bool annotateNullability = false,
 }) {
   var writer = _ElementWriter(
@@ -67,6 +69,7 @@
     withSyntheticAccessors: withSyntheticAccessors,
     withSyntheticFields: withSyntheticFields,
     withTypes: withTypes,
+    withTypeParameterVariance: withTypeParameterVariance,
     annotateNullability: annotateNullability,
   );
   writer.writeLibraryElement(library);
@@ -136,6 +139,7 @@
   final bool withSyntheticAccessors;
   final bool withSyntheticFields;
   final bool withTypes;
+  final bool withTypeParameterVariance;
   final bool annotateNullability;
   final StringBuffer buffer = StringBuffer();
 
@@ -151,6 +155,7 @@
     this.withSyntheticAccessors = false,
     this.withSyntheticFields = false,
     this.withTypes = false,
+    this.withTypeParameterVariance,
     this.annotateNullability = false,
   });
 
@@ -200,7 +205,7 @@
 
     writeName(e);
     writeCodeRange(e);
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: true);
 
     if (e.supertype != null && e.supertype.element.name != 'Object' ||
         e.mixins.isNotEmpty) {
@@ -365,7 +370,7 @@
     buffer.write('extension ');
     writeName(e);
     writeCodeRange(e);
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     if (e.extendedType != null) {
       buffer.write(' on ');
       writeType(e.extendedType);
@@ -400,7 +405,7 @@
     writeName(e);
     writeCodeRange(e);
 
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     writeParameterElements(e.parameters);
 
     writeBodyModifiers(e);
@@ -417,7 +422,7 @@
       buffer.write('typedef ');
       writeName(e);
       writeCodeRange(e);
-      writeTypeParameterElements(e.typeParameters);
+      writeTypeParameterElements(e.typeParameters, withDefault: true);
 
       buffer.write(' = ');
 
@@ -425,7 +430,7 @@
       if (function != null) {
         writeType(function.returnType);
         buffer.write(' Function');
-        writeTypeParameterElements(function.typeParameters);
+        writeTypeParameterElements(function.typeParameters, withDefault: false);
         writeParameterElements(function.parameters);
       } else {
         buffer.write('<null>');
@@ -535,7 +540,7 @@
     writeCodeRange(e);
     writeTypeInferenceError(e);
 
-    writeTypeParameterElements(e.typeParameters);
+    writeTypeParameterElements(e.typeParameters, withDefault: false);
     writeParameterElements(e.parameters);
 
     writeBodyModifiers(e);
@@ -1042,30 +1047,45 @@
     }
   }
 
-  void writeTypeParameterElement(TypeParameterElement e) {
+  void writeTypeParameterElement(
+    TypeParameterElement e, {
+    @required bool withDefault,
+  }) {
+    var impl = e as TypeParameterElementImpl;
+
     writeMetadata(e, '', '\n');
+
     // TODO (kallentu) : Clean up TypeParameterElementImpl casting once
     // variance is added to the interface.
-    if (!(e as TypeParameterElementImpl).isLegacyCovariant) {
-      buffer.write(
-          (e as TypeParameterElementImpl).variance.toKeywordString() + ' ');
+    if (withTypeParameterVariance) {
+      var variance = impl.variance;
+      buffer.write(variance.toString() + ' ');
     }
+
     writeName(e);
     writeCodeRange(e);
     if (e.bound != null && !e.bound.isDartCoreObject) {
       buffer.write(' extends ');
       writeType(e.bound);
     }
-    // TODO(scheglov) print the default type
-//    if (e is TypeParameterElementImpl && e.defaultType != null) {
-//      buffer.write(' = ');
-//      writeType(e.defaultType);
-//    }
+
+    if (withDefault) {
+      var defaultType = impl.defaultType;
+      if (defaultType is! DynamicTypeImpl) {
+        buffer.write(' = ');
+        writeType(defaultType);
+      }
+    }
   }
 
-  void writeTypeParameterElements(List<TypeParameterElement> elements) {
+  void writeTypeParameterElements(
+    List<TypeParameterElement> elements, {
+    @required bool withDefault,
+  }) {
     if (!withFullyResolvedAst) {
-      writeList('<', '>', elements, ', ', writeTypeParameterElement);
+      writeList('<', '>', elements, ', ', (e) {
+        writeTypeParameterElement(e, withDefault: withDefault);
+      });
     }
   }
 
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 98788a3..af3b5a9 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -770,10 +770,6 @@
     _writeln('IndexExpression');
     _withIndent(() {
       var properties = _Properties();
-      properties.addAuxiliaryElements(
-        'auxiliaryElements',
-        node.auxiliaryElements,
-      );
       properties.addNode('index', node.index);
       properties.addToken('period', node.period);
       properties.addNode('target', node.target);
@@ -1152,7 +1148,6 @@
     _writeNextCodeLine(node);
     _writeln('SimpleIdentifier');
     _withIndent(() {
-      _writeAuxiliaryElements('auxiliaryElements', node.auxiliaryElements);
       _writeElement('staticElement', node.staticElement);
       _writeType('staticType', node.staticType);
       _writeToken('token', node.token);
@@ -1681,14 +1676,6 @@
     _indent = indent;
   }
 
-  void _writeAuxiliaryElements(String name, AuxiliaryElements elements) {
-    if (elements != null) {
-      _sink.write(_indent);
-      _sink.write('$name: ');
-      _writeElement0(elements.staticElement);
-    }
-  }
-
   void _writeElement(String name, Element element) {
     _sink.write(_indent);
     _sink.write('$name: ');
@@ -1801,17 +1788,6 @@
   }
 }
 
-class _AuxiliaryElementsProperty extends _Property {
-  final AuxiliaryElements elements;
-
-  _AuxiliaryElementsProperty(String name, this.elements) : super(name);
-
-  @override
-  void write(ResolvedAstPrinter printer) {
-    printer._writeAuxiliaryElements(name, elements);
-  }
-}
-
 class _ElementProperty extends _Property {
   final Element element;
 
@@ -1848,12 +1824,6 @@
 class _Properties {
   final properties = <_Property>[];
 
-  void addAuxiliaryElements(String name, AuxiliaryElements elements) {
-    properties.add(
-      _AuxiliaryElementsProperty(name, elements),
-    );
-  }
-
   void addElement(String name, Element element) {
     properties.add(
       _ElementProperty(name, element),
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 2a30b09..863692f 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1289,7 +1289,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(C<dynamic> value);
-notSimplyBounded class C<T extends dynamic Function(C<dynamic>)> {
+notSimplyBounded class C<T extends dynamic Function(C<dynamic>) = dynamic Function(C<dynamic>)> {
 }
 ''');
   }
@@ -1301,7 +1301,7 @@
 class C<T extends C<dynamic>> {}
 ''');
     checkElementText(library, r'''
-class C<T extends C<dynamic>> {
+class C<T extends C<dynamic> = C<dynamic>> {
 }
 ''');
   }
@@ -1325,7 +1325,7 @@
 class D<T extends D> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends D<dynamic>> {
+notSimplyBounded class C<T extends D<dynamic> = D<dynamic>> {
 }
 notSimplyBounded class D<T extends D<dynamic>> {
 }
@@ -1338,7 +1338,7 @@
 class D<T> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends D<T>> {
+notSimplyBounded class C<T extends D<T> = D<dynamic>> {
 }
 class D<T> {
 }
@@ -1353,9 +1353,9 @@
 class D<T extends D<T>> {}
 ''');
     checkElementText(library, r'''
-class C<T extends D<dynamic>> {
+class C<T extends D<dynamic> = D<dynamic>> {
 }
-notSimplyBounded class D<T extends D<T>> {
+notSimplyBounded class D<T extends D<T> = D<dynamic>> {
 }
 ''');
   }
@@ -1365,7 +1365,7 @@
 class C<T extends void Function(T)> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends void Function(T)> {
+notSimplyBounded class C<T extends void Function(T) = void Function(Null)> {
 }
 ''');
   }
@@ -1375,7 +1375,7 @@
 class C<T extends T Function()> {}
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends T Function()> {
+notSimplyBounded class C<T extends T Function() = dynamic Function()> {
 }
 ''');
   }
@@ -1385,7 +1385,7 @@
 class C<T extends void Function()> {}
 ''');
     checkElementText(library, r'''
-class C<T extends void Function()> {
+class C<T extends void Function() = void Function()> {
 }
 ''');
   }
@@ -1402,7 +1402,7 @@
     checkElementText(library, r'''
 notSimplyBounded typedef F = dynamic Function(dynamic Function(dynamic) value);
 notSimplyBounded typedef G = dynamic Function(dynamic value);
-notSimplyBounded class C<T extends dynamic Function(dynamic Function(dynamic))> {
+notSimplyBounded class C<T extends dynamic Function(dynamic Function(dynamic)) = dynamic Function(dynamic Function(dynamic))> {
 }
 ''');
   }
@@ -1435,7 +1435,7 @@
 class D<T> {}
 ''');
     checkElementText(library, r'''
-class C<T extends D<dynamic>> {
+class C<T extends D<dynamic> = D<dynamic>> {
 }
 class D<T> {
 }
@@ -1675,7 +1675,7 @@
 class D {}
 ''');
     checkElementText(library, r'''
-class C<T, U extends D> {
+class C<T = Object, U extends D = D> {
 }
 class D {
 }
@@ -1709,7 +1709,7 @@
   test_class_type_parameters_f_bound_complex() async {
     var library = await checkLibrary('class C<T extends List<U>, U> {}');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends List<U>, U> {
+notSimplyBounded class C<T extends List<U> = List<dynamic>, U> {
 }
 ''');
   }
@@ -1724,32 +1724,173 @@
 
   test_class_type_parameters_variance_contravariant() async {
     var library = await checkLibrary('class C<in T> {}');
-    checkElementText(library, r'''
-class C<in T> {
+    checkElementText(
+        library,
+        r'''
+class C<contravariant T> {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_class_type_parameters_variance_covariant() async {
     var library = await checkLibrary('class C<out T> {}');
-    checkElementText(library, r'''
-class C<out T> {
+    checkElementText(
+        library,
+        r'''
+class C<covariant T> {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_class_type_parameters_variance_invariant() async {
     var library = await checkLibrary('class C<inout T> {}');
-    checkElementText(library, r'''
-class C<inout T> {
+    checkElementText(
+        library,
+        r'''
+class C<invariant T> {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_class_type_parameters_variance_multiple() async {
     var library = await checkLibrary('class C<inout T, in U, out V> {}');
+    checkElementText(
+        library,
+        r'''
+class C<invariant T, contravariant U, covariant V> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_functionTypeAlias_contravariant_legacy() async {
+    var library = await checkLibrary(r'''
+typedef F<X> = void Function(X);
+
+class A<X extends F<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<contravariant X> = void Function(X );
+notSimplyBounded class A<covariant X extends void Function(X) = void Function(Null)> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_functionTypeAlias_contravariant_nullSafe() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+typedef F<X> = void Function(X);
+
+class A<X extends F<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<contravariant X> = void Function(X );
+notSimplyBounded class A<covariant X extends void Function(X) = void Function(Never)> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_functionTypeAlias_invariant_legacy() async {
+    var library = await checkLibrary(r'''
+typedef F<X> = X Function(X);
+
+class A<X extends F<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<invariant X> = X Function(X );
+notSimplyBounded class A<covariant X extends X Function(X) = dynamic Function(dynamic)> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_functionTypeAlias_invariant_nullSafe() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+typedef F<X> = X Function(X);
+
+class A<X extends F<X>> {}
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<invariant X> = X Function(X );
+notSimplyBounded class A<covariant X extends X Function(X) = dynamic Function(dynamic)> {
+}
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_both_legacy() async {
+    var library = await checkLibrary(r'''
+class A<X extends X Function(X)> {}
+''');
     checkElementText(library, r'''
-class C<inout T, in U, out V> {
+notSimplyBounded class A<X extends X Function(X) = dynamic Function(Null)> {
+}
+''');
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_both_nullSafe() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+class A<X extends X Function(X)> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class A<X extends X Function(X) = dynamic Function(Never)> {
+}
+''');
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_contravariant_legacy() async {
+    var library = await checkLibrary(r'''
+class A<X extends void Function(X)> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class A<X extends void Function(X) = void Function(Null)> {
+}
+''');
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_contravariant_nullSafe() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+class A<X extends void Function(X)> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class A<X extends void Function(X) = void Function(Never)> {
+}
+''');
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_covariant_legacy() async {
+    var library = await checkLibrary(r'''
+class A<X extends X Function()> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class A<X extends X Function() = dynamic Function()> {
+}
+''');
+  }
+
+  test_class_typeParameters_defaultType_genericFunctionType_covariant_nullSafe() async {
+    featureSet = enableNnbd;
+    var library = await checkLibrary(r'''
+class A<X extends X Function()> {}
+''');
+    checkElementText(library, r'''
+notSimplyBounded class A<X extends X Function() = dynamic Function()> {
 }
 ''');
   }
@@ -6606,6 +6747,136 @@
 ''');
   }
 
+  test_functionTypeAlias_typeParameters_variance_contravariant() async {
+    var library = await checkLibrary(r'''
+typedef void F<T>(T a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<contravariant T> = void Function(T a);
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_contravariant2() async {
+    var library = await checkLibrary(r'''
+typedef void F1<T>(T a);
+typedef F1<T> F2<T>();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T a);
+typedef F2<contravariant T> = void Function(T) Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_contravariant3() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> F2<T>();
+typedef void F1<T>(T a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F2<contravariant T> = void Function(T) Function();
+typedef F1<contravariant T> = void Function(T a);
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_covariant() async {
+    var library = await checkLibrary(r'''
+typedef T F<T>();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = T Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_covariant2() async {
+    var library = await checkLibrary(r'''
+typedef List<T> F<T>();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = List<T> Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_covariant3() async {
+    var library = await checkLibrary(r'''
+typedef T F1<T>();
+typedef F1<T> F2<T>();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<covariant T> = T Function() Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_covariant4() async {
+    var library = await checkLibrary(r'''
+typedef void F1<T>(T a);
+typedef void F2<T>(F1<T> a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T a);
+typedef F2<covariant T> = void Function(void Function(T) a);
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_invariant() async {
+    var library = await checkLibrary(r'''
+typedef T F<T>(T a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<invariant T> = T Function(T a);
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_invariant2() async {
+    var library = await checkLibrary(r'''
+typedef T F1<T>();
+typedef F1<T> F2<T>(T a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<invariant T> = T Function() Function(T a);
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_functionTypeAlias_typeParameters_variance_unrelated() async {
+    var library = await checkLibrary(r'''
+typedef void F<T>(int a);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<unrelated T> = void Function(int a);
+''',
+        withTypeParameterVariance: true);
+  }
+
   test_futureOr() async {
     var library = await checkLibrary('import "dart:async"; FutureOr<int> x;');
     checkElementText(library, r'''
@@ -6788,6 +7059,122 @@
 ''');
   }
 
+  test_genericTypeAlias_typeParameters_variance_contravariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = void Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<contravariant T> = void Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_contravariant2() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = void Function(T);
+typedef F2<T> = F1<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T );
+typedef F2<contravariant T> = void Function(T) Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_covariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = T Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = T Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_covariant2() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = List<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<covariant T> = List<T> Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_covariant3() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = T Function();
+typedef F2<T> = F1<T> Function();
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<covariant T> = T Function() Function();
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_covariant4() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = void Function(T);
+typedef F2<T> = void Function(F1<T>);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<contravariant T> = void Function(T );
+typedef F2<covariant T> = void Function(void Function(T) );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_invariant() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = T Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<invariant T> = T Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_invariant2() async {
+    var library = await checkLibrary(r'''
+typedef F1<T> = T Function();
+typedef F2<T> = F1<T> Function(T);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F1<covariant T> = T Function();
+typedef F2<invariant T> = T Function() Function(T );
+''',
+        withTypeParameterVariance: true);
+  }
+
+  test_genericTypeAlias_typeParameters_variance_unrelated() async {
+    var library = await checkLibrary(r'''
+typedef F<T> = void Function(int);
+''');
+    checkElementText(
+        library,
+        r'''
+typedef F<unrelated T> = void Function(int );
+''',
+        withTypeParameterVariance: true);
+  }
+
   test_getter_documented() async {
     var library = await checkLibrary('''
 // Extra comment so doc comment offset != 0
@@ -7210,7 +7597,7 @@
 }
 class B extends A {
 }
-class S<T extends A> {
+class S<T extends A = A> {
   S(T _);
 }
 S<B> s;
@@ -7882,7 +8269,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<S extends num, T extends C<S, T>> {
+notSimplyBounded class C<S extends num = num, T extends C<S, T> = C<num, dynamic>> {
 }
 C<num, C<num, dynamic>> c;
 ''');
@@ -7898,7 +8285,7 @@
 }
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 class B {
   C<C<dynamic>> c3;
@@ -7914,7 +8301,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-notSimplyBounded class C<T extends C<T, U>, U extends num> {
+notSimplyBounded class C<T extends C<T, U> = C<dynamic, num>, U extends num = num> {
 }
 C<C<dynamic, num>, num> c;
 ''');
@@ -7948,7 +8335,7 @@
 F f;
 ''');
     checkElementText(library, r'''
-typedef F<T extends num> = dynamic Function(T p);
+typedef F<T extends num = num> = dynamic Function(T p);
 dynamic Function(num) f;
 ''');
   }
@@ -7962,7 +8349,7 @@
     checkElementText(library, r'''
 class A<T> {
 }
-notSimplyBounded class B<T extends int Function(), U extends A<T>> {
+notSimplyBounded class B<T extends int Function() = int Function(), U extends A<T> = A<int Function()>> {
 }
 B<int Function(), A<int Function()>> b;
 ''');
@@ -7974,7 +8361,7 @@
 F f;
 ''');
     checkElementText(library, r'''
-typedef F<T extends num> = S Function<S>(T p);
+typedef F<T extends num = num> = S Function<S>(T p);
 S Function<S>(num) f;
 ''');
   }
@@ -7987,10 +8374,10 @@
 class B<T extends num> {}
 ''');
     checkElementText(library, r'''
-class A<R extends B<num>> {
+class A<R extends B<num> = B<num>> {
   final List<B<num>> values;
 }
-class B<T extends num> {
+class B<T extends num = num> {
 }
 ''');
   }
@@ -8001,7 +8388,7 @@
 C c;
 ''');
     checkElementText(library, r'''
-class C<T extends num> {
+class C<T extends num = num> {
 }
 C<num> c;
 ''');
@@ -9367,7 +9754,7 @@
 }
 class D {
 }
-mixin M<T extends num, U> on A, B implements C, D {
+mixin M<T extends num = num, U> on A, B implements C, D {
   T f;
   U get g {}
   void set s(int v) {}
@@ -9528,34 +9915,46 @@
 
   test_mixin_type_parameters_variance_contravariant() async {
     var library = await checkLibrary('mixin M<in T> {}');
-    checkElementText(library, r'''
-mixin M<in T> on Object {
+    checkElementText(
+        library,
+        r'''
+mixin M<contravariant T> on Object {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_mixin_type_parameters_variance_covariant() async {
     var library = await checkLibrary('mixin M<out T> {}');
-    checkElementText(library, r'''
-mixin M<out T> on Object {
+    checkElementText(
+        library,
+        r'''
+mixin M<covariant T> on Object {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_mixin_type_parameters_variance_invariant() async {
     var library = await checkLibrary('mixin M<inout T> {}');
-    checkElementText(library, r'''
-mixin M<inout T> on Object {
+    checkElementText(
+        library,
+        r'''
+mixin M<invariant T> on Object {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_mixin_type_parameters_variance_multiple() async {
     var library = await checkLibrary('mixin M<inout T, in U, out V> {}');
-    checkElementText(library, r'''
-mixin M<inout T, in U, out V> on Object {
+    checkElementText(
+        library,
+        r'''
+mixin M<invariant T, contravariant U, covariant V> on Object {
 }
-''');
+''',
+        withTypeParameterVariance: true);
   }
 
   test_nameConflict_exportedAndLocal() async {
@@ -10335,6 +10734,20 @@
 ''');
   }
 
+  test_type_inference_assignmentExpression_references_onTopLevelVariable() async {
+    var library = await checkLibrary('''
+var a = () {
+  b += 0;
+  return 0;
+};
+var b = 0;
+''');
+    checkElementText(library, '''
+int Function() a;
+int b;
+''');
+  }
+
   test_type_inference_based_on_loadLibrary() async {
     addLibrarySource('/a.dart', '');
     var library = await checkLibrary('''
@@ -10496,7 +10909,7 @@
 }
 class B extends A {
 }
-class C<T extends A> {
+class C<T extends A = A> {
   final T f;
   const C(T this.f);
 }
@@ -11005,7 +11418,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11019,7 +11432,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> );
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11033,7 +11446,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = void Function(C<C<dynamic>> c);
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11047,7 +11460,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11061,7 +11474,7 @@
 ''');
     checkElementText(library, r'''
 notSimplyBounded typedef F = C<C<dynamic>> Function();
-notSimplyBounded class C<T extends C<T>> {
+notSimplyBounded class C<T extends C<T> = C<dynamic>> {
 }
 ''');
   }
@@ -11154,7 +11567,7 @@
     var library = await checkLibrary(
         'typedef U F<T extends Object, U extends D>(T t); class D {}');
     checkElementText(library, r'''
-typedef F<T, U extends D> = U Function(T t);
+typedef F<T = Object, U extends D = D> = U Function(T t);
 class D {
 }
 ''');
@@ -11179,14 +11592,14 @@
   test_typedef_type_parameters_f_bound_complex() async {
     var library = await checkLibrary('typedef U F<T extends List<U>, U>(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends List<U>, U> = U Function(T t);
+notSimplyBounded typedef F<T extends List<U> = List<Null>, U> = U Function(T t);
 ''');
   }
 
   test_typedef_type_parameters_f_bound_simple() async {
     var library = await checkLibrary('typedef U F<T extends U, U>(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends U, U> = U Function(T t);
+notSimplyBounded typedef F<T extends U = Null, U> = U Function(T t);
 ''');
   }
 
@@ -11194,7 +11607,7 @@
     var library =
         await checkLibrary('typedef F<T extends U, U> = U Function(T t);');
     checkElementText(library, r'''
-notSimplyBounded typedef F<T extends U, U> = U Function(T t);
+notSimplyBounded typedef F<T extends U = Null, U> = U Function(T t);
 ''');
   }
 
diff --git a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
index 0c61468..4adaadd 100644
--- a/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_text_printer_test.dart
@@ -61,7 +61,7 @@
   }
 
   test_extensionOverride() async {
-    await assertParseCodeAndPrintAst(this, '''
+    assertParseCodeAndPrintAst(this, '''
 extension E on Object {
   int f() => 0;
 }
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index 41ea625..b71fb4b 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -418,7 +418,7 @@
 
   test_constantGenericTypeArg_infer() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/26141
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 abstract class Equality<Q> {}
 abstract class EqualityBase<R> implements Equality<R> {
   final C<R> c = const C();
@@ -439,7 +439,7 @@
 main() {
   const SetEquality<String>();
 }
-''', []);
+''');
   }
 
   test_constructorInvalid() async {
@@ -2298,7 +2298,7 @@
   }
 
   test_genericMethodOverride() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 class Future<T> {
   S then<S>(S onValue(T t)) => null;
 }
@@ -2318,7 +2318,7 @@
 class DerivedFuture4<A> extends Future<A> {
   B then<B>(Object onValue(A a)) => null;
 }
-''', []);
+''');
   }
 
   test_genericMethodSuper() async {
@@ -2348,7 +2348,7 @@
   }
 
   test_genericMethodSuperSubstitute() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class Cloneable<T> {}
 class G<T> {
   create<A extends Cloneable<T>, B extends Iterable<A>>() => null;
@@ -2356,7 +2356,7 @@
 class H extends G<num> {
   create2() => super.create<Cloneable<int>, List<Cloneable<int>>>();
 }
-''', []);
+''');
   }
 
   test_getterGetterOverride() async {
@@ -3103,7 +3103,7 @@
 
   test_implicitDynamic_static() async {
     _disableTestPackageImplicitDynamic();
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class C {
   static void test(int body()) {}
 }
@@ -3113,7 +3113,7 @@
     return 42;
   });
 }
-''', []);
+''');
   }
 
   test_implicitDynamic_type() async {
@@ -3223,7 +3223,7 @@
 
   test_interfacesFromMixinsOnlyConsiderMostDerivedMember() {
     // Regression test for dart2js interface pattern in strong mode.
-    return assertErrorsInCode(r'''
+    return assertNoErrorsInCode(r'''
 abstract class I1 { num get x; }
 abstract class I2 extends I1 { int get x; }
 
@@ -3234,7 +3234,7 @@
 class Child extends Base with M2 implements I2 {}
 
 class C extends Object with M1, M2 implements I1, I2 {}
-''', []);
+''');
   }
 
   test_interfacesFromMixinsUsedTwiceAreChecked() {
@@ -3548,7 +3548,7 @@
     // This is a regression test for a bug in an earlier implementation were
     // names were hiding errors if the first mixin override looked correct,
     // but subsequent ones did not.
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 class A {}
 class B {}
 
@@ -3571,7 +3571,7 @@
 class T1 extends Base with M1, M2, M3 {}
 
 class U1 = Base with M1, M2, M3;
-''', []);
+''');
   }
 
   test_invalidOverrides_noErrorsIfSubclassCorrectlyOverrideBaseAndInterface() async {
@@ -3785,14 +3785,14 @@
 
   test_methodTearoffStrictArrow() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/26393
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   void foo(dynamic x) {}
   void test(void f(int x)) {
     test(foo);
   }
 }
-''', []);
+''');
   }
 
   test_mixinApplicationIsConcrete() {
@@ -4092,7 +4092,7 @@
   }
 
   test_nullCoalescingOperator() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 class A {}
 class C<T> {}
 main() {
@@ -4105,11 +4105,11 @@
   c ??= new C();
   d = d ?? new C();
 }
-''', []);
+''');
   }
 
   test_nullCoalescingStrictArrow() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 bool _alwaysTrue(x) => true;
 typedef bool TakesA<T>(T t);
 class C<T> {
@@ -4118,7 +4118,7 @@
     : g = f ?? _alwaysTrue;
   C.a() : g = _alwaysTrue;
 }
-''', []);
+''');
   }
 
   test_optionalParams() async {
@@ -4155,13 +4155,13 @@
 
   test_overrideNarrowsType_legalWithChecked() async {
     // Regression test for https://github.com/dart-lang/sdk/issues/25232
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 abstract class A { void test(A arg) { } }
 abstract class B extends A { void test(covariant B arg) { } }
 abstract class X implements A { }
 class C extends B with X { }
 class D extends B implements A { }
-''', []);
+''');
   }
 
   test_overrideNarrowsType_noDuplicateError() {
@@ -4643,7 +4643,7 @@
   }
 
   test_tearOffTreatedConsistentlyAsStrictArrow() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 void foo(void f(String x)) {}
 
 class A {
@@ -4666,11 +4666,11 @@
   foo(baz2);
   foo(baz3);
 }
-''', []);
+''');
   }
 
   test_tearOffTreatedConsistentlyAsStrictArrowNamedParam() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 typedef void Handler(String x);
 void foo({Handler f}) {}
 
@@ -4694,7 +4694,7 @@
   foo(f: baz2);
   foo(f: baz3);
 }
-''', []);
+''');
   }
 
   test_ternaryOperator() async {
diff --git a/pkg/analyzer/test/src/workspace/bazel_test.dart b/pkg/analyzer/test/src/workspace/bazel_test.dart
index 868084b..0b33c83 100644
--- a/pkg/analyzer/test/src/workspace/bazel_test.dart
+++ b/pkg/analyzer/test/src/workspace/bazel_test.dart
@@ -205,6 +205,26 @@
         exists: true);
   }
 
+  void test_resolveAbsolute_null_doubleDot() {
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-genfiles/',
+    ]);
+    var uri = Uri.parse('package:foo..bar/baz.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_null_doubleSlash() {
+    _addResources([
+      '/workspace/WORKSPACE',
+      '/workspace/bazel-genfiles/',
+    ]);
+    var uri = Uri.parse('package:foo//bar/baz.dart');
+    Source source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
   void test_resolveAbsolute_null_noSlash() {
     _addResources([
       '/workspace/WORKSPACE',
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
index 6e5236c..975bbf2 100644
--- a/pkg/analyzer/test/verify_docs_test.dart
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -44,11 +44,11 @@
     snippetPath = provider.pathContext.join(snippetDirPath, 'snippet.dart');
   }
 
-  void verify() async {
+  Future<void> verify() async {
     await verifyFolder(docFolder);
   }
 
-  void verifyFile(File file) async {
+  Future<void> verifyFile(File file) async {
     String content = file.readAsStringSync();
     List<String> lines = const LineSplitter().convert(content);
     List<String> codeLines = [];
@@ -73,7 +73,7 @@
     }
   }
 
-  void verifyFolder(Folder folder) async {
+  Future<void> verifyFolder(Folder folder) async {
     for (Resource child in folder.getChildren()) {
       if (child is File) {
         if (child.shortName.endsWith('.md')) {
@@ -85,7 +85,7 @@
     }
   }
 
-  void verifySnippet(File file, String snippet) async {
+  Future<void> verifySnippet(File file, String snippet) async {
     // TODO(brianwilkerson) When the files outside of 'src' contain only public
     //  API, write code to compute the list of imports so that new public API
     //  will automatically be allowed.
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index e0b0db5..a09ddb7 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -15,9 +15,16 @@
 
 ## Glossary
 
-This page uses the following terms.
+This page uses the following terms:
+
+* [constant context][]
+* [definite assignment][]
+* [override inference][]
+* [potentially non-nullable][]
 
 [constant context]: #constant-context
+[definite assignment]: #definite-assignment
+[override inference]: #override-inference
 [potentially non-nullable]: #potentially-non-nullable
 
 ### Constant context
@@ -60,6 +67,151 @@
   }
   ```
 
+### Definite assignment
+
+Definite assignment analysis is the process of determining, for each local
+variable at each point in the code, which of the following is true:
+- The variable has definitely been assigned a value (_definitely assigned_).
+- The variable has definitely not been assigned a value (_definitely
+  unassigned_).
+- The variable might or might not have been assigned a value, depending on the
+  execution path taken to arrive at that point.
+
+Definite assignment analysis helps find problems in code, such as places where a
+variable that might not have been assigned a value is being referenced, or
+places where a variable that can only be assigned a value one time is being
+assigned after it might already have been assigned a value.
+
+For example, in the following code the variable `s` is definitely unassigned
+when it’s passed as an argument to `print`:
+
+```dart
+void f() {
+  String s;
+  print(s);
+}
+```
+
+But in the following code, the variable `s` is definitely assigned:
+
+```dart
+void f(String name) {
+  String s = 'Hello $name!';
+  print(s);
+}
+```
+
+Definite assignment analysis can even tell whether a variable is definitely
+assigned (or unassigned) when there are multiple possible execution paths. In
+the following code the `print` function is called if execution goes through
+either the true or the false branch of the `if` statement, but because `s` is
+assigned no matter which branch is taken, it’s definitely assigned before it’s
+passed to `print`:
+
+```dart
+void f(String name, bool casual) {
+  String s;
+  if (casual) {
+    s = 'Hi $name!';
+  } else {
+    s = 'Hello $name!';
+  }
+  print(s);
+}
+```
+
+In flow analysis, the end of the `if` statement is referred to as a _join_—a
+place where two or more execution paths merge back together. Where there's a
+join, the analysis says that a variable is definitely assigned if it’s
+definitely assigned along all of the paths that are merging, and definitely
+unassigned if it’s definitely unassigned along all of the paths.
+
+Sometimes a variable is assigned a value on one path but not on another, in
+which case the variable might or might not have been assigned a value. In the
+following example, the true branch of the `if` statement might or might not be
+executed, so the variable might or might be assigned a value:
+
+```dart
+void f(String name, bool casual) {
+  String s;
+  if (casual) {
+    s = 'Hi $name!';
+  }
+  print(s);
+}
+```
+
+The same is true if there is a false branch that doesn’t assign a value to `s`.
+
+The analysis of loops is a little more complicated, but it follows the same
+basic reasoning. For example, the condition in a `while` loop is always
+executed, but the body might or might not be. So just like an `if` statement,
+there's a join at the end of the `while` statement between the path in which the
+condition is `true` and the path in which the condition is `false`.
+
+For additional details, see the
+[specification of definite assignment][definiteAssignmentSpec].
+
+[definiteAssignmentSpec](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md)
+
+### Override inference
+
+Override inference is the process by which any missing types in a method
+declaration are inferred based on the corresponding types from the method or
+methods that it overrides.
+
+If a candidate method (the method that's missing type information) overrides a
+single inherited method, then the corresponding types from the overridden method
+are inferred. For example, consider the following code:
+
+```dart
+class A {
+  int m(String s) => 0;
+}
+
+class B extends A {
+  @override
+  m(s) => 1;
+}
+```
+
+The declaration of `m` in `B` is a candidate because it's missing both the
+return type and the parameter type. Because it overrides a single method (the
+method `m` in `A`), the types from the overridden method will be used to infer
+the missing types and it will be as if the method in `B` had been declared as
+`int m(String s) => 1;`.
+
+If a candidate method overrides multiple methods, and the function type one of
+those overridden methods, M<sub>s</sub>, is a supertype of the function types of
+all of the other overridden methods, then M<sub>s</sub> is used to infer the
+missing types. For example, consider the following code:
+
+```dart
+class A {
+  int m(num n) => 0;
+}
+
+class B {
+  num m(int i) => 0;
+}
+
+class C implements A, B {
+  @override
+  m(n) => 1;
+}
+```
+
+The declaration of `m` in `C` is a candidate for override inference because it's
+missing both the return type and the parameter type. It overrides both `m` in
+`A` and `m` in `B`, so we need to choose one of them from which the missing
+types can be inferred. But because the function type of `m` in `A`
+(`int Function(num)`) is a supertype of the function type of `m` in `B`
+(`num Function(int)`), the function in `A` is used to infer the missing types.
+The result is the same as declaring the method in `C` as `int m(num n) => 1;`.
+
+It is an error if none of the overridden methods has a function type that is a
+supertype of all the other overridden methods.
+
 ### Potentially non-nullable
 
 A type is _potentially non-nullable_ if it's either explicitly non-nullable or
@@ -576,6 +728,47 @@
 
 Rewrite the code so that there isn't an assignment to a method.
 
+### await_in_late_local_variable_initializer
+
+_The 'await' expression can't be used in a 'late' local variable's initializer._
+
+#### Description
+
+The analyzer produces this diagnostic when a local variable that has the
+`late` modifier uses an `await` expression in the initializer.
+
+#### Example
+
+The following code produces this diagnostic because an `await` expression
+is used in the initializer for `v`, a local variable that is marked `late`:
+
+{% prettify dart tag=pre+code %}
+Future<int> f() async {
+  late v = [!await!] 42;
+  return v;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the initializer can be rewritten to not use `await`, then rewrite it:
+
+{% prettify dart tag=pre+code %}
+Future<int> f() async {
+  late v = 42;
+  return v;
+}
+{% endprettify %}
+
+If the initializer can't be rewritten, then remove the `late` modifier:
+
+{% prettify dart tag=pre+code %}
+Future<int> f() async {
+  var v = await 42;
+  return v;
+}
+{% endprettify %}
+
 ### body_might_complete_normally
 
 _The body might complete normally, causing 'null' to be returned, but the return
@@ -910,6 +1103,50 @@
 }
 {% endprettify %}
 
+### const_constructor_with_field_initialized_by_non_const
+
+_Can't define the 'const' constructor because the field '{0}' is initialized
+with a non-constant value._
+
+#### Description
+
+The analyzer produces this diagnostic when a constructor has the keyword
+`const`, but a field in the class is initialized to a non-constant value.
+
+#### Example
+
+The following code produces this diagnostic because the field `s` is
+initialized to a non-constant value:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final String s = 3.toString();
+  [!const!] C();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field can be initialized to a constant value, then change the
+initializer to a constant expression:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final String s = '3';
+  const C();
+}
+{% endprettify %}
+
+If the field can't be initialized to a constant value, then remove the
+keyword `const` from the constructor:
+
+{% prettify dart tag=pre+code %}
+class C {
+  final String s = 3.toString();
+  C();
+}
+{% endprettify %}
+
 ### const_constructor_with_non_final_field
 
 _Can't define a const constructor for a class with non-final fields._
@@ -964,7 +1201,7 @@
 
 The analyzer produces this diagnostic when a value that isn't statically
 known to be a constant is assigned to a variable that's declared to be a
-'const' variable.
+`const` variable.
 
 #### Examples
 
@@ -1196,6 +1433,54 @@
 C f(int i) => C(i);
 {% endprettify %}
 
+### creation_with_non_type
+
+_The name '{0}' isn't a class._
+
+_The name '{0}' isn't a class._
+
+#### Description
+
+The analyzer produces this diagnostic when an instance creation using
+either `new` or `const` specifies a name that isn't defined as a class.
+
+#### Example
+
+The following code produces this diagnostic because `f` is a function
+rather than a class:
+
+{% prettify dart tag=pre+code %}
+int f() => 0;
+
+void g() {
+  new [!f!]();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If a class should be created, then replace the invalid name with the name
+of a valid class:
+
+{% prettify dart tag=pre+code %}
+int f() => 0;
+
+void g() {
+  new Object();
+}
+{% endprettify %}
+
+If the name is the name of a function and you want that function to be
+invoked, then remove the `new` or `const` keyword:
+
+{% prettify dart tag=pre+code %}
+int f() => 0;
+
+void g() {
+  f();
+}
+{% endprettify %}
+
 ### dead_code
 
 _Dead code._
@@ -1468,16 +1753,45 @@
 var l = List.generate(3, (i) => i);
 {% endprettify %}
 
+### default_value_in_function_type
+
+_Parameters in a function type can't have default values._
+
+#### Description
+
+The analyzer produces this diagnostic when a function type associated with
+a parameter includes optional parameters that have a default value. This
+isn't allowed because the default values of parameters aren't part of the
+function's type, and therefore including them doesn't provide any value.
+
+#### Example
+
+The following code produces this diagnostic because the parameter `p` has a
+default value even though it's part of the type of the parameter `g`:
+
+{% prettify dart tag=pre+code %}
+void f(void Function([int p [!=!] 0]) g) {
+}
+{% endprettify %}
+
+#### Common fixes
+
+Remove the default value from the function-type's parameter:
+
+{% prettify dart tag=pre+code %}
+void f(void Function([int p]) g) {
+}
+{% endprettify %}
+
 ### definitely_unassigned_late_local_variable
 
 _The late local variable '{0}' is definitely unassigned at this point._
 
 #### Description
 
-The analyzer produces this diagnostic when
-[definite assignment](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md)
-analysis shows that a local variable that's marked as `late` is read before
-being assigned.
+The analyzer produces this diagnostic when [definite assignment][] analysis
+shows that a local variable that's marked as `late` is read before being
+assigned.
 
 #### Example
 
@@ -2370,7 +2684,7 @@
 
 #### Common fixes
 
-Use '.' rather than '..':
+Use `.` rather than `..`:
 
 {% prettify dart tag=pre+code %}
 extension E on int {
@@ -2730,6 +3044,56 @@
 }
 {% endprettify %}
 
+### getter_not_subtype_setter_types
+
+_The return type of getter '{0}' is '{1}' which isn't a subtype of the type
+'{2}' of its setter '{3}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the return type of a getter
+isn't a subtype of the type of the parameter of a setter with the same
+name.
+
+The subtype relationship is a requirement whether the getter and setter are
+in the same class or whether one of them is in a superclass of the other.
+
+#### Example
+
+The following code produces this diagnostic because the return type of the
+getter `x` is `num`, the parameter type of the setter `x` is `int`, and
+`num` isn't a subtype of `int`:
+
+{% prettify dart tag=pre+code %}
+class C {
+  num get [!x!] => 0;
+
+  set x(int y) {}
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the getter is correct, then change the type of the setter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  num get x => 0;
+
+  set x(num y) {}
+}
+{% endprettify %}
+
+If the type of the setter is correct, then change the type of the getter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int get x => 0;
+
+  set x(int y) {}
+}
+{% endprettify %}
+
 ### illegal_async_return_type
 
 _Functions marked 'async' must have a return type assignable to 'Future'._
@@ -3232,6 +3596,80 @@
 If there's a concrete subclass of the abstract class that can be used, then
 create an instance of the concrete subclass.
 
+### invalid_annotation
+
+_Annotation must be either a const variable reference or const constructor
+invocation._
+
+_Getters can't be used as annotations._
+
+#### Description
+
+The analyzer produces this diagnostic when an annotation is found that is
+using something that is neither a variable marked as `const` or the
+invocation of a `const` constructor.
+
+Getters can't be used as annotations.
+
+#### Example
+
+The following code produces this diagnostic because the variable `v` isn't
+a `const` variable:
+
+{% prettify dart tag=pre+code %}
+var v = 0;
+
+[!@v!]
+void f() {
+}
+{% endprettify %}
+
+The following code produces this diagnostic because `f` isn't a variable:
+
+{% prettify dart tag=pre+code %}
+[!@f!]
+void f() {
+}
+{% endprettify %}
+
+The following code produces this diagnostic because `f` isn't a
+constructor:
+
+{% prettify dart tag=pre+code %}
+[!@f()!]
+void f() {
+}
+{% endprettify %}
+
+The following code produces this diagnostic because `g` is a getter:
+
+{% prettify dart tag=pre+code %}
+[!@g!]
+int get g => 0;
+{% endprettify %}
+
+#### Common fixes
+
+If the annotation is referencing a variable that isn't a `const`
+constructor, add the keyword `const` to the variable's declaration:
+
+{% prettify dart tag=pre+code %}
+const v = 0;
+
+@v
+void f() {
+}
+{% endprettify %}
+
+If the annotation isn't referencing a variable, then remove it:
+
+{% prettify dart tag=pre+code %}
+int v = 0;
+
+void f() {
+}
+{% endprettify %}
+
 ### invalid_assignment
 
 _A value of type '{0}' can't be assigned to a variable of type '{1}'._
@@ -3453,7 +3891,7 @@
 #### Description
 
 The analyzer produces this diagnostic when a null-aware operator (`?.`,
-`?..`, `?[`, `?..[`, or `...?`) is used on a receiver that's known to be
+`?..`, `?[`, `?..[`, or `...?`) is used on a target that's known to be
 non-nullable.
 
 #### Example
@@ -3473,6 +3911,25 @@
 var b = [[!...?!]a];
 {% endprettify %}
 
+The following code produces this diagnostic because `s?.length` can't
+return `null`:
+
+{% prettify dart tag=pre+code %}
+void f(String? s) {
+  s?.length[!?.!]isEven;
+}
+{% endprettify %}
+
+The reason `s?.length` can't return `null` is because the null-aware
+operator following `s` short-circuits the evaluation of both `length` and
+`isEven` if `s` is `null`. In other words, if `s` is `null`, then neither
+`length` nor `isEven` will be invoked, and if `s` is non-`null`, then
+`length` can't return a `null` value. Either way, `isEven` can't be invoked
+on a `null` value, so the null-aware operator is neither necessary nor
+allowed. See
+[Understanding null safety](/null-safety/understanding-null-safety#smarter-null-aware-methods)
+for more details.
+
 #### Common fixes
 
 Replace the null-aware operator with a non-null-aware equivalent; for
@@ -3627,7 +4084,7 @@
 
 #### Common fixes
 
-Remove the 'covariant' keyword:
+Remove the `covariant` keyword:
 
 {% prettify dart tag=pre+code %}
 extension E on String {
@@ -3828,6 +4285,104 @@
 var y = f();
 {% endprettify %}
 
+### late_final_field_with_const_constructor
+
+_Can't have a late final field in a class with a const constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when a class that has at least one
+`const` constructor also has a field marked both `late` and `final`.
+
+#### Example
+
+The following code produces this diagnostic because the class `A` has a
+`const` constructor and the `final` field `f` is marked as `late`:
+
+{% prettify dart tag=pre+code %}
+class A {
+  [!late!] final int f;
+
+  const A();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the field doesn't need to be marked `late`, then remove the `late`
+modifier from the field:
+
+{% prettify dart tag=pre+code %}
+class A {
+  final int f = 0;
+
+  const A();
+}
+{% endprettify %}
+
+If the field must be marked `late`, then remove the `const` modifier from
+the constructors:
+
+{% prettify dart tag=pre+code %}
+class A {
+  late final int f;
+
+  A();
+}
+{% endprettify %}
+
+### late_final_local_already_assigned
+
+_The late final local variable is already assigned._
+
+#### Description
+
+The analyzer produces this diagnostic when the analyzer can prove that a
+local variable marked as both `late` and `final` was already assigned a
+value at the point where another assignment occurs.
+
+Because `final` variables can only be assigned once, subsequent assignments
+are guaranteed to fail, so they're flagged.
+
+#### Example
+
+The following code produces this diagnostic because the `final` variable
+`v` is assigned a value in two places:
+
+{% prettify dart tag=pre+code %}
+int f() {
+  late final int v;
+  v = 0;
+  [!v!] += 1;
+  return v;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If you need to be able to reassign the variable, then remove the `final`
+keyword:
+
+{% prettify dart tag=pre+code %}
+int f() {
+  late int v;
+  v = 0;
+  v += 1;
+  return v;
+}
+{% endprettify %}
+
+If you don't need to reassign the variable, then remove all except the
+first of the assignments:
+
+{% prettify dart tag=pre+code %}
+int f() {
+  late final int v;
+  v = 0;
+  return v;
+}
+{% endprettify %}
+
 ### list_element_type_not_assignable
 
 _The element type '{0}' can't be assigned to the list type '{1}'._
@@ -4236,7 +4791,7 @@
 
 #### Examples
 
-If the package 'p' defines a sealed class:
+If the package `p` defines a sealed class:
 
 {% prettify dart tag=pre+code %}
 import 'package:meta/meta.dart';
@@ -4245,7 +4800,7 @@
 class C {}
 {% endprettify %}
 
-Then, the following code, when in a package other than 'p', produces this
+Then, the following code, when in a package other than `p`, produces this
 diagnostic:
 
 {% prettify dart tag=pre+code %}
@@ -5069,8 +5624,7 @@
 - Doesn't have an initializer.
 - Isn't marked as `late`.
 - The analyzer can't prove that the local variable will be assigned before
-  the reference based on the specification of
-  [definite assignment](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md).
+  the reference based on the specification of [definite assignment.][]
 
 #### Example
 
@@ -5455,6 +6009,62 @@
 var x;
 {% endprettify %}
 
+### no_combined_super_signature
+
+_Can't infer missing types in '{0}' from overridden methods: {1}._
+
+#### Description
+
+The analyzer produces this diagnostic when there is a method declaration
+for which one or more types needs to be inferred, and those types can't be
+inferred because none of the overridden methods has a function type that is
+a supertype of all the other overridden methods, as specified by
+[override inference][].
+
+#### Example
+
+The following code produces this diagnostic because the method `m` declared
+in the class `C` is missing both the return type and the type of the
+parameter `a`, and neither of the missing types can be inferred for it:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  A m(String a);
+}
+
+abstract class B {
+  B m(int a);
+}
+
+abstract class C implements A, B {
+  [!m!](a);
+}
+{% endprettify %}
+
+In this example, override inference can't be performed because the
+overridden methods are incompatible in these ways:
+- Neither parameter type (`String` and `int`) is a supertype of the other.
+- Neither return type is a subtype of the other.
+
+#### Common fixes
+
+If possible, add types to the method in the subclass that are consistent
+with the types from all the overridden methods:
+
+{% prettify dart tag=pre+code %}
+abstract class A {
+  A m(String a);
+}
+
+abstract class B {
+  B m(int a);
+}
+
+abstract class C implements A, B {
+  C m(Object a);
+}
+{% endprettify %}
+
 ### nullable_type_in_catch_clause
 
 _A potentially nullable type can't be used in an 'on' clause because it isn't
@@ -5760,6 +6370,47 @@
 import 'a.dart';
 {% endprettify %}
 
+### prefix_collides_with_top_level_member
+
+_The name '{0}' is already used as an import prefix and can't be used to name a
+top-level element._
+
+#### Description
+
+The analyzer produces this diagnostic when a name is used as both an import
+prefix and the name of a top-level declaration in the same library.
+
+#### Example
+
+The following code produces this diagnostic because `f` is used as both an
+import prefix and the name of a function:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' as f;
+
+int [!f!]() => f.min(0, 1);
+{% endprettify %}
+
+#### Common fixes
+
+If you want to use the name for the import prefix, then rename the
+top-level declaration:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' as f;
+
+int g() => f.min(0, 1);
+{% endprettify %}
+
+If you want to use the name for the top-level declaration, then rename the
+import prefix:
+
+{% prettify dart tag=pre+code %}
+import 'dart:math' as math;
+
+int f() => math.min(0, 1);
+{% endprettify %}
+
 ### prefix_identifier_not_followed_by_dot
 
 _The name '{0}' refers to an import prefix, so it must be followed by '.'._
@@ -6689,6 +7340,69 @@
 int f(C c) => c.b;
 {% endprettify %}
 
+### subtype_of_disallowed_type
+
+_''{0}' can't be used as a superclass constraint._
+
+_Classes and mixins can't implement '{0}'._
+
+_Classes can't extend '{0}'._
+
+_Classes can't mixin '{0}'._
+
+#### Description
+
+The analyzer produces this diagnostic when one of the restricted classes is
+used in either an `extends`, `implements`, `with`, or `on` clause. The
+classes `bool`, `double`, `FutureOr`, `int`, `Null`, `num`, and `String`
+are all restricted in this way, to allow for more efficient
+implementations.
+
+#### Example
+
+The following code produces this diagnostic because `String` is used in an
+`extends` clause:
+
+{% prettify dart tag=pre+code %}
+class A extends [!String!] {}
+{% endprettify %}
+
+The following code produces this diagnostic because `String` is used in an
+`implements` clause:
+
+{% prettify dart tag=pre+code %}
+class B implements [!String!] {}
+{% endprettify %}
+
+The following code produces this diagnostic because `String` is used in a
+`with` clause:
+
+{% prettify dart tag=pre+code %}
+class C with [!String!] {}
+{% endprettify %}
+
+The following code produces this diagnostic because `String` is used in an
+`on` clause:
+
+{% prettify dart tag=pre+code %}
+mixin M on [!String!] {}
+{% endprettify %}
+
+#### Common fixes
+
+If a different type should be specified, then replace the type:
+
+{% prettify dart tag=pre+code %}
+class A extends Object {}
+{% endprettify %}
+
+If there isn't a different type that would be appropriate, then remove the
+type, and possibly the whole clause:
+
+{% prettify dart tag=pre+code %}
+class B {}
+{% endprettify %}
+
 ### super_in_extension
 
 _The 'super' keyword can't be used in an extension because an extension doesn't
@@ -7819,9 +8533,9 @@
 
 #### Description
 
-The analyzer produces this diagnostic when an inherited member is
-referenced using `super`, but there’s no member with that name in the
-superclass chain.
+The analyzer produces this diagnostic when an inherited member (method,
+getter, setter, or operator) is referenced using `super`, but there’s no
+member with that name in the superclass chain.
 
 #### Examples
 
@@ -7855,8 +8569,8 @@
 If the member you intend to invoke is defined in the same class, then
 remove the `super.`.
 
-If not, then either add the member to one of the superclasses or remove the
-invocation.
+If the member isn’t defined, then either add the member to one of the
+superclasses or remove the invocation.
 
 ### unnecessary_cast
 
@@ -8126,9 +8840,14 @@
 
 #### Description
 
-The analyzer produces this diagnostic when a private class, enum, mixin,
-typedef, top level variable, top level function, or method is declared but
-never referenced.
+The analyzer produces this diagnostic when a private declaration isn't
+referenced in the library that contains the declaration. The following
+kinds of declarations are analyzed:
+- Private top-level declarations, such as classes, enums, mixins, typedefs,
+  top-level variables, and top-level functions
+- Private static and instance methods
+- Optional parameters of private functions for which a value is never
+  passed, even when the parameter doesn't have a private name
 
 #### Examples
 
@@ -8139,11 +8858,30 @@
 class [!_C!] {}
 {% endprettify %}
 
+Assuming that no code in the library passes a value for `y` in any
+invocation of `_m`, the following code produces this diagnostic:
+
+{% prettify dart tag=pre+code %}
+class C {
+  void _m(int x, [int [!y!]]) {}
+
+  void n() => _m(0);
+}
+{% endprettify %}
+
 #### Common fixes
 
-If the declaration isn't needed, then remove it.
+If the declaration isn't needed, then remove it:
 
-If the declaration was intended to be used, then add the missing code.
+{% prettify dart tag=pre+code %}
+class C {
+  void _m(int x) {}
+
+  void n() => _m(0);
+}
+{% endprettify %}
+
+If the declaration is intended to be used, then add the code to use it.
 
 ### unused_field
 
@@ -8542,6 +9280,55 @@
 void f(C<int> x) {}
 {% endprettify %}
 
+### wrong_number_of_type_arguments_method
+
+_The method '{0}' is declared with {1} type parameters, but {2} type arguments
+are given._
+
+#### Description
+
+The analyzer produces this diagnostic when a method or function is invoked
+with a different number of type arguments than the number of type
+parameters specified in its declaration. There must either be no type
+arguments or the number of arguments must match the number of parameters.
+
+#### Example
+
+The following code produces this diagnostic because the invocation of the
+method `m` has two type arguments, but the declaration of `m` only has one
+type parameter:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int m<A>(A a) => 0;
+}
+
+int f(C c) => c.m[!<int, int>!](2);
+{% endprettify %}
+
+#### Common fixes
+
+If the type arguments are necessary, then make them match the number of
+type parameters by either adding or removing type arguments:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int m<A>(A a) => 0;
+}
+
+int f(C c) => c.m<int>(2);
+{% endprettify %}
+
+If the type arguments aren't necessary, then remove them:
+
+{% prettify dart tag=pre+code %}
+class C {
+  int m<A>(A a) => 0;
+}
+
+int f(C c) => c.m(2);
+{% endprettify %}
+
 ### undefined_super_method
 
-See [undefined_super_member](#undefined-super-member).
+See [undefined_super_member](#undefined_super_member).
diff --git a/pkg/analyzer/tool/diagnostics/generate.dart b/pkg/analyzer/tool/diagnostics/generate.dart
index 59b6c0e..b3401a9 100644
--- a/pkg/analyzer/tool/diagnostics/generate.dart
+++ b/pkg/analyzer/tool/diagnostics/generate.dart
@@ -390,19 +390,26 @@
 
 ### undefined_super_method
 
-See [undefined_super_member](#undefined-super-member).
+See [undefined_super_member](#undefined_super_member).
 ''');
   }
 
   /// Write the glossary.
   void _writeGlossary(StringSink sink) {
-    sink.write('''
+    sink.write(r'''
 
 ## Glossary
 
-This page uses the following terms.
+This page uses the following terms:
+
+* [constant context][]
+* [definite assignment][]
+* [override inference][]
+* [potentially non-nullable][]
 
 [constant context]: #constant-context
+[definite assignment]: #definite-assignment
+[override inference]: #override-inference
 [potentially non-nullable]: #potentially-non-nullable
 
 ### Constant context
@@ -445,6 +452,151 @@
   }
   ```
 
+### Definite assignment
+
+Definite assignment analysis is the process of determining, for each local
+variable at each point in the code, which of the following is true:
+- The variable has definitely been assigned a value (_definitely assigned_).
+- The variable has definitely not been assigned a value (_definitely
+  unassigned_).
+- The variable might or might not have been assigned a value, depending on the
+  execution path taken to arrive at that point.
+
+Definite assignment analysis helps find problems in code, such as places where a
+variable that might not have been assigned a value is being referenced, or
+places where a variable that can only be assigned a value one time is being
+assigned after it might already have been assigned a value.
+
+For example, in the following code the variable `s` is definitely unassigned
+when it’s passed as an argument to `print`:
+
+```dart
+void f() {
+  String s;
+  print(s);
+}
+```
+
+But in the following code, the variable `s` is definitely assigned:
+
+```dart
+void f(String name) {
+  String s = 'Hello $name!';
+  print(s);
+}
+```
+
+Definite assignment analysis can even tell whether a variable is definitely
+assigned (or unassigned) when there are multiple possible execution paths. In
+the following code the `print` function is called if execution goes through
+either the true or the false branch of the `if` statement, but because `s` is
+assigned no matter which branch is taken, it’s definitely assigned before it’s
+passed to `print`:
+
+```dart
+void f(String name, bool casual) {
+  String s;
+  if (casual) {
+    s = 'Hi $name!';
+  } else {
+    s = 'Hello $name!';
+  }
+  print(s);
+}
+```
+
+In flow analysis, the end of the `if` statement is referred to as a _join_—a
+place where two or more execution paths merge back together. Where there's a
+join, the analysis says that a variable is definitely assigned if it’s
+definitely assigned along all of the paths that are merging, and definitely
+unassigned if it’s definitely unassigned along all of the paths.
+
+Sometimes a variable is assigned a value on one path but not on another, in
+which case the variable might or might not have been assigned a value. In the
+following example, the true branch of the `if` statement might or might not be
+executed, so the variable might or might be assigned a value:
+
+```dart
+void f(String name, bool casual) {
+  String s;
+  if (casual) {
+    s = 'Hi $name!';
+  }
+  print(s);
+}
+```
+
+The same is true if there is a false branch that doesn’t assign a value to `s`.
+
+The analysis of loops is a little more complicated, but it follows the same
+basic reasoning. For example, the condition in a `while` loop is always
+executed, but the body might or might not be. So just like an `if` statement,
+there's a join at the end of the `while` statement between the path in which the
+condition is `true` and the path in which the condition is `false`.
+
+For additional details, see the
+[specification of definite assignment][definiteAssignmentSpec].
+
+[definiteAssignmentSpec](https://github.com/dart-lang/language/blob/master/resources/type-system/flow-analysis.md)
+
+### Override inference
+
+Override inference is the process by which any missing types in a method
+declaration are inferred based on the corresponding types from the method or
+methods that it overrides.
+
+If a candidate method (the method that's missing type information) overrides a
+single inherited method, then the corresponding types from the overridden method
+are inferred. For example, consider the following code:
+
+```dart
+class A {
+  int m(String s) => 0;
+}
+
+class B extends A {
+  @override
+  m(s) => 1;
+}
+```
+
+The declaration of `m` in `B` is a candidate because it's missing both the
+return type and the parameter type. Because it overrides a single method (the
+method `m` in `A`), the types from the overridden method will be used to infer
+the missing types and it will be as if the method in `B` had been declared as
+`int m(String s) => 1;`.
+
+If a candidate method overrides multiple methods, and the function type one of
+those overridden methods, M<sub>s</sub>, is a supertype of the function types of
+all of the other overridden methods, then M<sub>s</sub> is used to infer the
+missing types. For example, consider the following code:
+
+```dart
+class A {
+  int m(num n) => 0;
+}
+
+class B {
+  num m(int i) => 0;
+}
+
+class C implements A, B {
+  @override
+  m(n) => 1;
+}
+```
+
+The declaration of `m` in `C` is a candidate for override inference because it's
+missing both the return type and the parameter type. It overrides both `m` in
+`A` and `m` in `B`, so we need to choose one of them from which the missing
+types can be inferred. But because the function type of `m` in `A`
+(`int Function(num)`) is a supertype of the function type of `m` in `B`
+(`num Function(int)`), the function in `A` is used to infer the missing types.
+The result is the same as declaring the method in `C` as `int m(num n) => 1;`.
+
+It is an error if none of the overridden methods has a function type that is a
+supertype of all the other overridden methods.
+
 ### Potentially non-nullable
 
 A type is _potentially non-nullable_ if it's either explicitly non-nullable or
diff --git a/pkg/analyzer_cli/analysis_options.yaml b/pkg/analyzer_cli/analysis_options.yaml
index a8a1d4b..ee6055a 100644
--- a/pkg/analyzer_cli/analysis_options.yaml
+++ b/pkg/analyzer_cli/analysis_options.yaml
@@ -12,5 +12,13 @@
     - test/data/**
 linter:
   rules:
+    - avoid_single_cascade_in_expression_statements
+    - avoid_unused_constructor_parameters
+    - await_only_futures
     - empty_statements
+    - iterable_contains_unrelated_type
+    - list_remove_unrelated_type
+    - provide_deprecation_message
     - unnecessary_brace_in_string_interps
+    - unnecessary_overrides
+    - void_checks
diff --git a/pkg/analyzer_cli/lib/src/context_cache.dart b/pkg/analyzer_cli/lib/src/context_cache.dart
index bdbe19a..6c0bb25 100644
--- a/pkg/analyzer_cli/lib/src/context_cache.dart
+++ b/pkg/analyzer_cli/lib/src/context_cache.dart
@@ -86,19 +86,21 @@
   String get analysisRoot => _analysisRoot ??= _getAnalysisRoot();
 
   void _buildContextFeatureSet(AnalysisOptionsImpl analysisOptions) {
-    var sdkLanguageVersion = ExperimentStatus.currentVersion;
-    if (clOptions.defaultLanguageVersion != null) {
-      sdkLanguageVersion = Version.parse(
-        clOptions.defaultLanguageVersion + '.0',
-      );
-    }
-
     var featureSet = FeatureSet.fromEnableFlags2(
-      sdkLanguageVersion: sdkLanguageVersion,
+      sdkLanguageVersion: ExperimentStatus.currentVersion,
       flags: clOptions.enabledExperiments,
     );
 
     analysisOptions.contextFeatures = featureSet;
+
+    if (clOptions.defaultLanguageVersion != null) {
+      var nonPackageLanguageVersion = Version.parse(
+        clOptions.defaultLanguageVersion + '.0',
+      );
+      analysisOptions.nonPackageLanguageVersion = nonPackageLanguageVersion;
+      analysisOptions.nonPackageFeatureSet = FeatureSet.latestLanguageVersion()
+          .restrictToVersion(nonPackageLanguageVersion);
+    }
   }
 
   /// The actual calculation to get the [AnalysisOptionsImpl], with no caching.
@@ -111,7 +113,6 @@
 
     _buildContextFeatureSet(contextOptions);
     contextOptions.hint = !clOptions.disableHints;
-    contextOptions.useFastaParser = clOptions.useFastaParser;
     return contextOptions;
   }
 
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 832785a..3e86667 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -51,11 +51,9 @@
 import 'package:yaml/yaml.dart';
 
 /// Shared IO sink for standard error reporting.
-@visibleForTesting
 StringSink errorSink = io.stderr;
 
 /// Shared IO sink for standard out reporting.
-@visibleForTesting
 StringSink outSink = io.stdout;
 
 /// Test this option map to see if it specifies lint rules.
@@ -96,9 +94,7 @@
   PathFilter pathFilter;
 
   /// Create a new Driver instance.
-  ///
-  /// [isTesting] is true if we're running in a test environment.
-  Driver({bool isTesting = false});
+  Driver({@Deprecated('This parameter has no effect') bool isTesting = false});
 
   /// Converts the given [filePath] into absolute and normalized.
   String normalizePath(String filePath) {
@@ -439,7 +435,6 @@
       } else {
         // The embedder uri resolver has mappings, use it instead of the default
         // Dart SDK uri resolver.
-        embedderSdk.analysisOptions = analysisOptions;
         resolvers.add(DartUriResolver(embedderSdk));
       }
     }
@@ -648,10 +643,10 @@
         sdk = SummaryBasedDartSdk(options.dartSdkSummaryPath, true);
       } else {
         var dartSdkPath = options.dartSdkPath;
-        var dartSdk = FolderBasedDartSdk(
-            resourceProvider, resourceProvider.getFolder(dartSdkPath));
-        dartSdk.analysisOptions = analysisOptions;
-        sdk = dartSdk;
+        sdk = FolderBasedDartSdk(
+          resourceProvider,
+          resourceProvider.getFolder(dartSdkPath),
+        );
       }
     }
   }
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index e54f8ae..cff668d 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -104,9 +104,6 @@
   /// (Or null if not enabled.)
   final String perfReport;
 
-  /// Whether to enable parsing via the Fasta parser.
-  final bool useFastaParser;
-
   /// Batch mode (for unit testing)
   final bool batchMode;
 
@@ -177,7 +174,6 @@
         log = cast(args['log']),
         machineFormat = args['format'] == 'machine',
         perfReport = cast(args['x-perf-report']),
-        useFastaParser = cast(args['use-fasta-parser']),
         batchMode = cast(args['batch']),
         showPackageWarnings = cast(args['show-package-warnings']) ||
             cast(args['package-warnings']) ||
@@ -443,14 +439,6 @@
           defaultsTo: false,
           negatable: false,
           hide: true)
-      // TODO(brianwilkerson) Remove the following option after we're sure that
-      // it's no longer being used.
-      ..addFlag('enable-assert-initializers',
-          help:
-              'Enable parsing of asserts in constructor initializers (deprecated).',
-          defaultsTo: null,
-          negatable: false,
-          hide: hide)
       ..addFlag('use-analysis-driver-memory-byte-store',
           help: 'Use memory byte store, not the file system cache.',
           defaultsTo: false,
@@ -477,15 +465,6 @@
               'of "libraryUri".',
           splitCommas: false,
           hide: hide)
-      ..addFlag('use-fasta-parser',
-          help: 'Whether to enable parsing via the Fasta parser.',
-          defaultsTo: true,
-          hide: hide)
-      ..addFlag('preview-dart-2',
-          help: 'Enable the Dart 2.0 preview.',
-          defaultsTo: true,
-          hide: hide,
-          negatable: true)
       ..addFlag('train-snapshot',
           help: 'Analyze the given source for the purposes of training a '
               'dartanalyzer snapshot.',
diff --git a/pkg/analyzer_cli/test/analysis_options_test.dart b/pkg/analyzer_cli/test/analysis_options_test.dart
index d112a6e..0c68a22 100644
--- a/pkg/analyzer_cli/test/analysis_options_test.dart
+++ b/pkg/analyzer_cli/test/analysis_options_test.dart
@@ -75,7 +75,7 @@
   String get stdout => _stdout.toString();
 
   Future<void> run2(List<String> args) async {
-    await Driver(isTesting: true).start(args);
+    await Driver().start(args);
     if (stderr.isNotEmpty) {
       fail('Unexpected output to stderr:\n$stderr');
     }
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index b19066c..126856d 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -27,12 +27,9 @@
     defineReflectiveTests(BuildModeTest);
     defineReflectiveTests(BuildModeSummaryDependenciesTest);
     defineReflectiveTests(ExitCodesTest);
-    defineReflectiveTests(ExitCodesTest_PreviewDart2);
     defineReflectiveTests(LinterTest);
-    defineReflectiveTests(LinterTest_PreviewDart2);
     defineReflectiveTests(NonDartFilesTest);
     defineReflectiveTests(OptionsTest);
-    defineReflectiveTests(OptionsTest_PreviewDart2);
   }, name: 'Driver');
 }
 
@@ -93,8 +90,6 @@
 
   AnalysisOptions get analysisOptions => driver.analysisDriver.analysisOptions;
 
-  bool get usePreviewDart2 => false;
-
   /// Normalize text with bullets.
   String bulletToDash(StringSink item) => '$item'.replaceAll('•', '-');
 
@@ -118,7 +113,7 @@
   }) async {
     options = _posixToPlatformPath(options);
 
-    driver = Driver(isTesting: true);
+    driver = Driver();
     var cmd = <String>[];
     if (options != null) {
       cmd = <String>[
@@ -127,9 +122,6 @@
       ];
     }
     cmd..addAll(sources.map(_adjustFileSpec))..addAll(args);
-    if (usePreviewDart2) {
-      cmd.insert(0, '--preview-dart-2');
-    }
 
     await driver.start(cmd);
   }
@@ -750,7 +742,7 @@
       var origWorkingDir = Directory.current;
       try {
         Directory.current = path.join(tempDirPath, 'proj');
-        var driver = Driver(isTesting: true);
+        var driver = Driver();
         try {
           await driver.start([
             path.join('lib', 'file.dart'),
@@ -772,12 +764,6 @@
     });
   }
 
-  Future<void> test_enableAssertInitializer() async {
-    await drive('data/file_with_assert_initializers.dart',
-        args: ['--enable-assert-initializers']);
-    expect(exitCode, 0);
-  }
-
   Future<void> test_fatalErrors() async {
     await drive('data/file_with_error.dart');
     expect(exitCode, 3);
@@ -826,7 +812,7 @@
   }
 
   Future<void> test_partFile_reversed() async {
-    var driver = Driver(isTesting: true);
+    var driver = Driver();
     await driver.start([
       path.join(testDirectory, 'data/library_and_parts/part1.dart'),
       path.join(testDirectory, 'data/library_and_parts/lib.dart')
@@ -836,12 +822,6 @@
 }
 
 @reflectiveTest
-class ExitCodesTest_PreviewDart2 extends ExitCodesTest {
-  @override
-  bool get usePreviewDart2 => true;
-}
-
-@reflectiveTest
 class LinterTest extends BaseTest {
   String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
 
@@ -938,12 +918,6 @@
 }
 
 @reflectiveTest
-class LinterTest_PreviewDart2 extends LinterTest {
-  @override
-  bool get usePreviewDart2 => true;
-}
-
-@reflectiveTest
 class NonDartFilesTest extends BaseTest {
   Future<void> test_analysisOptionsYaml() async {
     await withTempDirAsync((tempDir) async {
@@ -1133,12 +1107,6 @@
   }
 }
 
-@reflectiveTest
-class OptionsTest_PreviewDart2 extends OptionsTest {
-  @override
-  bool get usePreviewDart2 => true;
-}
-
 class TestSource implements Source {
   TestSource();
 
diff --git a/pkg/analyzer_cli/test/embedder_test.dart b/pkg/analyzer_cli/test/embedder_test.dart
index 120af72..8b554b0 100644
--- a/pkg/analyzer_cli/test/embedder_test.dart
+++ b/pkg/analyzer_cli/test/embedder_test.dart
@@ -32,7 +32,7 @@
 
     test('resolution', wrap(() async {
       var testDir = path.join(testDirectory, 'data', 'embedder_client');
-      await Driver(isTesting: true).start([
+      await Driver().start([
         '--packages',
         path.join(testDir, '_packages'),
         path.join(testDir, 'embedder_yaml_user.dart')
@@ -44,7 +44,7 @@
 
     test('sdk setup', wrap(() async {
       var testDir = path.join(testDirectory, 'data', 'embedder_client');
-      var driver = Driver(isTesting: true);
+      var driver = Driver();
       await driver.start([
         '--packages',
         path.join(testDir, '_packages'),
diff --git a/pkg/analyzer_cli/test/errors_reported_once_test.dart b/pkg/analyzer_cli/test/errors_reported_once_test.dart
index cb5ba53..d25a78e 100644
--- a/pkg/analyzer_cli/test/errors_reported_once_test.dart
+++ b/pkg/analyzer_cli/test/errors_reported_once_test.dart
@@ -41,7 +41,7 @@
 
   Future<void> test_once() async {
     var testDir = path.join(testDirectory, 'data', 'errors_reported_once');
-    var driver = Driver(isTesting: true);
+    var driver = Driver();
     await driver.start(
         [path.join(testDir, 'foo.dart'), path.join(testDir, 'bar.dart')]);
 
@@ -56,7 +56,7 @@
 
   Future<void> test_once_machine() async {
     var testDir = path.join(testDirectory, 'data', 'errors_reported_once');
-    var driver = Driver(isTesting: true);
+    var driver = Driver();
     await driver.start([
       '--format',
       'machine',
diff --git a/pkg/analyzer_cli/test/errors_upgrade_fails_cli_test.dart b/pkg/analyzer_cli/test/errors_upgrade_fails_cli_test.dart
index 81e671d..16d79dd 100644
--- a/pkg/analyzer_cli/test/errors_upgrade_fails_cli_test.dart
+++ b/pkg/analyzer_cli/test/errors_upgrade_fails_cli_test.dart
@@ -41,7 +41,7 @@
 
   Future<void> test_once() async {
     var testDir = path.join(testDirectory, 'data', 'error_upgrade_fails_cli');
-    var driver = Driver(isTesting: true);
+    var driver = Driver();
     await driver.start([path.join(testDir, 'foo.dart')]);
 
     expect(exitCode, 3);
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 188a92f..12ff74c 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -257,11 +257,6 @@
         expect(failureMessage, equals('Invalid Dart SDK path: &&&&&'));
       });
 
-      test('--use-fasta-parser', () {
-        var options = parse(['--use-fasta-parser', 'foo.dart']);
-        expect(options.useFastaParser, isTrue);
-      });
-
       test('--train-snapshot', () {
         var options = parse(['--train-snapshot', 'foo.dart']);
         expect(options.trainSnapshot, isTrue);
diff --git a/pkg/analyzer_cli/test/package_prefix_test.dart b/pkg/analyzer_cli/test/package_prefix_test.dart
index fbe8aac..157ffe9 100644
--- a/pkg/analyzer_cli/test/package_prefix_test.dart
+++ b/pkg/analyzer_cli/test/package_prefix_test.dart
@@ -64,7 +64,7 @@
   String get stdout => _stdout.toString();
 
   Future<void> run2(List<String> args) async {
-    await Driver(isTesting: true).start(args);
+    await Driver().start(args);
     if (stderr.isNotEmpty) {
       fail('Unexpected output to stderr:\n$stderr');
     }
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 60d65bb..8f0d5e3 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -4,6 +4,7 @@
 - Deprecated the method `ChangeBuilder.addFileEdit` and introduced
   `ChangeBuilder.addDartFileEdit` and `ChangeBuilder.addGenericFileEdit` to be
   the replacements for it.
+- Bump maximum supported version of the analyzer to `<0.41.0`.
 
 ## 0.3.0
 - Removed deprecated `Plugin.getResolveResult`. Use `getResolvedUnitResult`.
diff --git a/pkg/analyzer_plugin/analysis_options.yaml b/pkg/analyzer_plugin/analysis_options.yaml
index 42406ef..ac616cb 100644
--- a/pkg/analyzer_plugin/analysis_options.yaml
+++ b/pkg/analyzer_plugin/analysis_options.yaml
@@ -3,6 +3,7 @@
     implicit-casts: false
 linter:
   rules:
+    - await_only_futures
     - empty_statements
     - unnecessary_brace_in_string_interps
     #
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 7e2bab3..6e2aeae 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -4358,27 +4358,34 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
 class ParameterKind implements Enum {
-  /// A named parameter.
-  static const ParameterKind NAMED = ParameterKind._('NAMED');
+  /// An optional named parameter.
+  static const ParameterKind OPTIONAL_NAMED = ParameterKind._('OPTIONAL_NAMED');
 
-  /// An optional parameter.
-  static const ParameterKind OPTIONAL = ParameterKind._('OPTIONAL');
+  /// An optional positional parameter.
+  static const ParameterKind OPTIONAL_POSITIONAL =
+      ParameterKind._('OPTIONAL_POSITIONAL');
 
-  /// A required parameter.
-  static const ParameterKind REQUIRED = ParameterKind._('REQUIRED');
+  /// A required named parameter.
+  static const ParameterKind REQUIRED_NAMED = ParameterKind._('REQUIRED_NAMED');
+
+  /// A required positional parameter.
+  static const ParameterKind REQUIRED_POSITIONAL =
+      ParameterKind._('REQUIRED_POSITIONAL');
 
   /// A list containing all of the enum values that are defined.
   static const List<ParameterKind> VALUES = <ParameterKind>[
-    NAMED,
-    OPTIONAL,
-    REQUIRED
+    OPTIONAL_NAMED,
+    OPTIONAL_POSITIONAL,
+    REQUIRED_NAMED,
+    REQUIRED_POSITIONAL
   ];
 
   @override
@@ -4388,12 +4395,14 @@
 
   factory ParameterKind(String name) {
     switch (name) {
-      case 'NAMED':
-        return NAMED;
-      case 'OPTIONAL':
-        return OPTIONAL;
-      case 'REQUIRED':
-        return REQUIRED;
+      case 'OPTIONAL_NAMED':
+        return OPTIONAL_NAMED;
+      case 'OPTIONAL_POSITIONAL':
+        return OPTIONAL_POSITIONAL;
+      case 'REQUIRED_NAMED':
+        return REQUIRED_NAMED;
+      case 'REQUIRED_POSITIONAL':
+        return REQUIRED_POSITIONAL;
     }
     throw Exception('Illegal enum value: $name');
   }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
index c16d12f..ed00442 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_core.dart
@@ -23,7 +23,7 @@
 
   /// The end-of-line marker used in the file being edited, or `null` if the
   /// default marker should be used.
-  String eol;
+  final String eol;
 
   /// A table mapping group ids to the associated linked edit groups.
   final Map<String, LinkedEditGroup> _linkedEditGroups =
@@ -49,7 +49,8 @@
   /// Initialize a newly created change builder. If the builder will be used to
   /// create changes for Dart files, then either a [session] or a [workspace]
   /// must be provided (but not both).
-  ChangeBuilderImpl({AnalysisSession session, ChangeWorkspace workspace})
+  ChangeBuilderImpl(
+      {AnalysisSession session, ChangeWorkspace workspace, this.eol})
       : assert(session == null || workspace == null),
         workspace = workspace ?? _SingleSessionWorkspace(session);
 
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 3f3db93..4b00e14 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
@@ -309,6 +307,29 @@
   }
 
   @override
+  void writeImportedName(List<Uri> uris, String name) {
+    assert(uris.isNotEmpty);
+    var imports = <ImportElement>[];
+    for (var uri in uris) {
+      imports.addAll(dartFileEditBuilder._getImportsForUri(uri));
+    }
+    var import = _getBestImportForName(imports, name);
+    if (import == null) {
+      var library = dartFileEditBuilder._importLibrary(uris[0]);
+      if (library.prefix != null) {
+        write(library.prefix);
+        write('.');
+      }
+    } else {
+      if (import.prefix != null) {
+        write(import.prefix.displayName);
+        write('.');
+      }
+    }
+    write(name);
+  }
+
+  @override
   void writeLocalVariableDeclaration(String name,
       {void Function() initializerWriter,
       bool isConst = false,
@@ -940,6 +961,33 @@
     return name;
   }
 
+  /// Given a list of [imports] that do, or can, make the [name] visible in
+  /// scope, return the one that will lead to the cleanest code.
+  ImportElement _getBestImportForName(
+      List<ImportElement> imports, String name) {
+    if (imports.isEmpty) {
+      return null;
+    } else if (imports.length == 1) {
+      return imports[0];
+    }
+    imports.sort((first, second) {
+      // Prefer imports that make the name visible.
+      var firstDefinesName = first.namespace.definedNames.containsKey(name);
+      var secondDefinesName = second.namespace.definedNames.containsKey(name);
+      if (firstDefinesName != secondDefinesName) {
+        return firstDefinesName ? -1 : 1;
+      }
+      // Prefer imports without prefixes.
+      var firstHasPrefix = first.prefix != null;
+      var secondHasPrefix = second.prefix != null;
+      if (firstHasPrefix != secondHasPrefix) {
+        return firstHasPrefix ? 1 : -1;
+      }
+      return 0;
+    });
+    return imports[0];
+  }
+
   /// Returns all variants of names by removing leading words one by one.
   List<String> _getCamelWordCombinations(String name) {
     var result = <String>[];
@@ -1100,24 +1148,41 @@
   /// If a [methodBeingCopied] is provided, then the type parameters of that
   /// method will be duplicated in the copy and will therefore be visible.
   ///
+  /// If [required] it `true`, then the type will be written even if it would
+  /// normally be omitted, such as with `dynamic`.
+  ///
   /// Causes any libraries whose elements are used by the generated code, to be
   /// imported.
-  bool _writeType(DartType type, {ExecutableElement methodBeingCopied}) {
+  bool _writeType(DartType type,
+      {ExecutableElement methodBeingCopied, bool required = false}) {
     type = _getVisibleType(type, methodBeingCopied: methodBeingCopied);
 
     // If not a useful type, don't write it.
-    if (type == null || type.isDynamic || type.isBottom) {
+    if (type == null) {
       return false;
     }
-
-    var element = type.element;
-
+    if (type.isDynamic) {
+      if (required) {
+        write('dynamic');
+        return true;
+      }
+      return false;
+    }
+    if (type.isBottom) {
+      var library = dartFileEditBuilder.resolvedUnit.libraryElement;
+      if (library.isNonNullableByDefault) {
+        write('Never');
+        return true;
+      }
+      return false;
+    }
     // The type `void` does not have an element.
     if (type is VoidType) {
       write('void');
       return true;
     }
 
+    var element = type.element;
     // Typedef(s) are represented as GenericFunctionTypeElement(s).
     if (element is GenericFunctionTypeElement &&
         element.typeParameters.isEmpty &&
@@ -1143,9 +1208,6 @@
     // Write the simple name.
     var name = element.displayName;
     write(name);
-    if (type.nullabilitySuffix == NullabilitySuffix.question) {
-      write('?');
-    }
 
     // Write type arguments.
     if (type is ParameterizedType) {
@@ -1167,12 +1229,17 @@
           if (i != 0) {
             write(', ');
           }
-          _writeType(argument, methodBeingCopied: methodBeingCopied);
+          _writeType(argument,
+              required: true, methodBeingCopied: methodBeingCopied);
         }
         write('>');
       }
     }
 
+    if (type.nullabilitySuffix == NullabilitySuffix.question) {
+      write('?');
+    }
+
     return true;
   }
 }
@@ -1535,6 +1602,15 @@
     return null;
   }
 
+  Iterable<ImportElement> _getImportsForUri(Uri uri) sync* {
+    for (var import in resolvedUnit.libraryElement.imports) {
+      var importUri = import.importedLibrary.source.uri;
+      if (importUri == uri) {
+        yield import;
+      }
+    }
+  }
+
   /// Computes the best URI to import [uri] into the target library.
   String _getLibraryUriText(Uri uri) {
     if (uri.scheme == 'file') {
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
index 0d0914f..0d310b5 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_core.dart
@@ -16,8 +16,10 @@
   /// Initialize a newly created change builder. If the builder will be used to
   /// create changes for Dart files, then either a [session] or a [workspace]
   /// must be provided (but not both).
-  factory ChangeBuilder({AnalysisSession session, ChangeWorkspace workspace}) =
-      ChangeBuilderImpl;
+  factory ChangeBuilder(
+      {AnalysisSession session,
+      ChangeWorkspace workspace,
+      String eol}) = ChangeBuilderImpl;
 
   /// Return the range of the selection for the change being built, or `null` if
   /// there is no selection.
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index fef21a1..1b513a2 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -148,6 +148,10 @@
       DartType returnType,
       String returnTypeGroupName});
 
+  /// Write the given [name], possibly with a prefix, assuming that the name can
+  /// be imported from any of the given [uris].
+  void writeImportedName(List<Uri> uris, String name);
+
   /// Write the code for a declaration of a local variable with the given
   /// [name]. If an [initializerWriter] is provided, it will be invoked to write
   /// the content of the initializer. (The equal sign separating the variable
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 1c02eab..1620c64 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -8,7 +8,7 @@
   sdk: '>=2.3.0 <3.0.0'
 
 dependencies:
-  analyzer: '^0.39.12'
+  analyzer: '>=0.39.12 <0.41.0'
   charcode: '^1.1.0'
   dart_style: '^1.2.0'
   pub_semver: '^1.3.2'
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 53cebf0..092d411 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -666,12 +666,17 @@
 /// ParameterKind
 ///
 /// enum {
-///   NAMED
-///   OPTIONAL
-///   REQUIRED
+///   OPTIONAL_NAMED
+///   OPTIONAL_POSITIONAL
+///   REQUIRED_NAMED
+///   REQUIRED_POSITIONAL
 /// }
-final Matcher isParameterKind =
-    MatchesEnum('ParameterKind', ['NAMED', 'OPTIONAL', 'REQUIRED']);
+final Matcher isParameterKind = MatchesEnum('ParameterKind', [
+  'OPTIONAL_NAMED',
+  'OPTIONAL_POSITIONAL',
+  'REQUIRED_NAMED',
+  'REQUIRED_POSITIONAL'
+]);
 
 /// Position
 ///
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 764a691..4a5ae22 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -538,6 +538,65 @@
     expect(position.offset, equals(20));
   }
 
+  Future<void> test_writeImportedName_hasImport_first() async {
+    // addSource(convertPath('/home/test/lib/foo.dart'), '');
+    var path = convertPath('/home/test/lib/test.dart');
+    addSource(path, '''
+import 'foo.dart';
+''');
+
+    var builder = newBuilder();
+    await builder.addDartFileEdit(path, (builder) {
+      builder.addInsertion(0, (builder) {
+        builder.writeImportedName([
+          Uri.parse('package:test/foo.dart'),
+          Uri.parse('package:test/bar.dart')
+        ], 'Foo');
+      });
+    });
+    var edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('Foo'));
+  }
+
+  Future<void> test_writeImportedName_hasImport_second() async {
+    var path = convertPath('/home/test/lib/test.dart');
+    addSource(path, '''
+import 'bar.dart';
+''');
+
+    var builder = newBuilder();
+    await builder.addDartFileEdit(path, (builder) {
+      builder.addInsertion(0, (builder) {
+        builder.writeImportedName([
+          Uri.parse('package:test/foo.dart'),
+          Uri.parse('package:test/bar.dart')
+        ], 'Foo');
+      });
+    });
+    var edit = getEdit(builder);
+    expect(edit.replacement, equalsIgnoringWhitespace('Foo'));
+  }
+
+  Future<void> test_writeImportedName_needsImport() async {
+    var path = convertPath('/home/test/lib/test.dart');
+    addSource(path, '');
+
+    var builder = newBuilder();
+    await builder.addDartFileEdit(path, (builder) {
+      builder.addInsertion(0, (builder) {
+        builder.writeImportedName([
+          Uri.parse('package:test/foo.dart'),
+          Uri.parse('package:test/bar.dart')
+        ], 'Foo');
+      });
+    });
+    var edits = getEdits(builder);
+    expect(edits, hasLength(2));
+    expect(edits[0].replacement,
+        equalsIgnoringWhitespace("import 'package:test/foo.dart';\n"));
+    expect(edits[1].replacement, equalsIgnoringWhitespace('Foo'));
+  }
+
   Future<void> test_writeLocalVariableDeclaration_noType_initializer() async {
     var path = convertPath('/home/test/lib/test.dart');
     var content = '''
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index c49dce7..f4acea4 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -6,7 +6,7 @@
 </head>
 <body>
 <h1>Common Types</h1>
-<version>1.2.0</version>
+<version>1.3.0</version>
 <p>
   This document contains a specification of the types that are common between
   the analysis server wire protocol and the analysis server plugin wire
@@ -1253,21 +1253,27 @@
     </p>
     <enum>
       <value>
-        <code>NAMED</code>
+        <code>OPTIONAL_NAMED</code>
         <p>
-          A named parameter.
+          An optional named parameter.
         </p>
       </value>
       <value>
-        <code>OPTIONAL</code>
+        <code>OPTIONAL_POSITIONAL</code>
         <p>
-          An optional parameter.
+          An optional positional parameter.
         </p>
       </value>
       <value>
-        <code>REQUIRED</code>
+        <code>REQUIRED_NAMED</code>
         <p>
-          A required parameter.
+          A required named parameter.
+        </p>
+      </value>
+      <value>
+        <code>REQUIRED_POSITIONAL</code>
+        <p>
+          A required positional parameter.
         </p>
       </value>
     </enum>
diff --git a/pkg/build_integration/lib/file_system/single_root.dart b/pkg/build_integration/lib/file_system/single_root.dart
index 175379d..03c73df 100644
--- a/pkg/build_integration/lib/file_system/single_root.dart
+++ b/pkg/build_integration/lib/file_system/single_root.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:front_end/src/api_unstable/build_integration.dart';
 
 /// A [FileSystem] that resolves custom URIs to entities under a specified root
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index 7d5fb5db..7bef2ba 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -6,7 +6,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.0.0 <3.0.0'
+  sdk: '>=2.1.0 <3.0.0'
 
 dependencies:
   front_end: ^0.1.0
diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md
index f4e2a49..6c9621a 100644
--- a/pkg/compiler/README.md
+++ b/pkg/compiler/README.md
@@ -327,36 +327,14 @@
   AI: consider deleting this file.
 
 
-* Constants: the compiler has a constant system that delays evaluation of
-  constants and provides different semantics depending on the embedder, this
-  abstraction was especially necessary when dart2js was used as a front-end for
-  non-JS systems like dart2dart and dartino.
+* Constants: the compiler has a constant system that evaluates constant
+  expressions based on JS semantics.
 
   * `lib/src/constants/value.dart`: this is the represented value of a constant
-    after it has been evaluated. The resulting value is specific to the target
-    of the compiler and will no longer have environment placeholders. For
-    example, when the target is Dart (dart2dart) `1 == 1.0` is evaluated to
-    `false`, and when the target is JavaScript it is evaluated to `true`. This
-    specific example is a result of the way dart2js compiles numbers as
-    JavaScript Numbers.
+    after it has been evaluated.
 
-  * `lib/src/constants/constant_system.dart`: an abstraction that defines how
-    expressions may be folded. Different implementations of the constant system
-    are used to target Dart or JavaScript.
-
-  * `lib/src/compile_time_constants.dart`: defines how constant expressions are
-    created from a parsed AST.
-
-  * `lib/src/constant_system_dart.dart`: defines an implementation of a constant
-    system with the Dart semantics (where `1 == 1.0` is true).
-
-  * `lib/src/js_backend/constant_system_javascript.dart`: defines an
-    implementation of a constant system with the JavaScript semantics (where
-    `1 == 1.0` is false).
-
-  AI: consider deleting `constant_system_dart.dart` now that it is no longer
-  used, or move under testing, if it might be used for unittests of the constant
-  expressions.
+  * `lib/src/constants/constant_system.dart`: implements evaluating constant
+    Dart expressions and produces values.
 
 * Common elements: the compiler often refers to certain elements during
   compilation either because they are first-class in the language or because
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index a0395e5..1c52968 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -23,6 +23,7 @@
   static const String enableCheckedMode = '--enable-checked-mode';
   static const String enableAsserts = '--enable-asserts';
   static const String enableNullAssertions = '--null-assertions';
+  static const String enableNativeNullAssertions = '--native-null-assertions';
   static const String enableDiagnosticColors = '--enable-diagnostic-colors';
   static const String experimentalTrackAllocations =
       '--experimental-track-allocations';
@@ -42,6 +43,11 @@
   // Experimentally rely on JavaScript ToBoolean conversions.
   static const String experimentToBoolean = '--experiment-code-3';
 
+  // Experiment to make methods that are inferred as unreachable throw an
+  // exception rather than generate suspect code.
+  static const String experimentUnreachableMethodsThrow =
+      '--experiment-unreachable-throw';
+
   // Add instrumentation to log every method call.
   static const String experimentCallInstrumentation =
       '--experiment-call-instrumentation';
@@ -107,13 +113,6 @@
   static const String soundNullSafety = '--sound-null-safety';
   static const String noSoundNullSafety = '--no-sound-null-safety';
 
-  static const String newDeferredSplit = '--new-deferred-split';
-  static const String noNewDeferredSplit = '--no-new-deferred-split';
-  static const String reportInvalidInferredDeferredTypes =
-      '--report-invalid-deferred-types';
-  static const String deferClassTypes = '--defer-class-types';
-  static const String noDeferClassTypes = '--no-defer-class-types';
-
   /// Flag for a combination of flags for 'production' mode.
   static const String benchmarkingProduction = '--benchmarking-production';
 
diff --git a/pkg/compiler/lib/src/common/names.dart b/pkg/compiler/lib/src/common/names.dart
index 6d9b83a..3cad4cb 100644
--- a/pkg/compiler/lib/src/common/names.dart
+++ b/pkg/compiler/lib/src/common/names.dart
@@ -61,6 +61,9 @@
 
   /// The name of the 'DART_CLOSURE_TO_JS' foreign function.
   static const String DART_CLOSURE_TO_JS = 'DART_CLOSURE_TO_JS';
+
+  /// The name of the 'RAW_DART_FUNCTION_REF' foreign function.
+  static const String RAW_DART_FUNCTION_REF = 'RAW_DART_FUNCTION_REF';
 }
 
 /// [Name]s commonly used.
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 59261b0..7b7387c 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -441,6 +441,8 @@
 
   FunctionEntity get defineProperty;
 
+  FunctionEntity get throwLateInitializationError;
+
   bool isExtractTypeArguments(FunctionEntity member);
 
   ClassEntity getInstantiationClass(int typeArgumentCount);
@@ -586,11 +588,12 @@
   /// compilation.
   bool isUnnamedListConstructor(ConstructorEntity element);
 
-  /// Returns `true` if [element] is the 'filled' constructor of `List`.
+  /// Returns `true` if [element] is the named constructor of `List`,
+  /// e.g. `List.of`.
   ///
   /// This will not resolve the constructor if it hasn't been seen yet during
   /// compilation.
-  bool isFilledListConstructor(ConstructorEntity element);
+  bool isNamedListConstructor(String name, ConstructorEntity element);
 
   bool isDefaultEqualityImplementation(MemberEntity element);
 
@@ -879,8 +882,8 @@
   /// This will not resolve the constructor if it hasn't been seen yet during
   /// compilation.
   @override
-  bool isFilledListConstructor(ConstructorEntity element) =>
-      element.name == 'filled' && element.enclosingClass == listClass;
+  bool isNamedListConstructor(String name, ConstructorEntity element) =>
+      element.name == name && element.enclosingClass == listClass;
 
   @override
   DynamicType get dynamicType => _env.dynamicType;
@@ -1777,6 +1780,10 @@
   FunctionEntity get defineProperty => _findHelperFunction('defineProperty');
 
   @override
+  FunctionEntity get throwLateInitializationError =>
+      _findHelperFunction('throwLateInitializationError');
+
+  @override
   bool isExtractTypeArguments(FunctionEntity member) {
     return member.name == 'extractTypeArguments' &&
         member.library == internalLibrary;
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c1bfac7..3bd43ed 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -444,9 +444,10 @@
         (_) => setCheckedMode(Flags.enableCheckedMode)),
     new OptionHandler(Flags.enableAsserts, passThrough),
     new OptionHandler(Flags.enableNullAssertions, passThrough),
+    new OptionHandler(Flags.enableNativeNullAssertions, passThrough),
     new OptionHandler(Flags.trustTypeAnnotations, setTrustTypeAnnotations),
     new OptionHandler(Flags.trustPrimitives, passThrough),
-    new OptionHandler(Flags.trustJSInteropTypeAnnotations, passThrough),
+    new OptionHandler(Flags.trustJSInteropTypeAnnotations, ignoreOption),
     new OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
     new OptionHandler('--packages=.+', setPackageConfig),
     new OptionHandler(Flags.noSourceMaps, passThrough),
@@ -467,10 +468,6 @@
     new OptionHandler(Flags.disableRtiOptimization, passThrough),
     new OptionHandler(Flags.terse, passThrough),
     new OptionHandler('--deferred-map=.+', passThrough),
-    new OptionHandler(Flags.newDeferredSplit, passThrough),
-    new OptionHandler(Flags.reportInvalidInferredDeferredTypes, passThrough),
-    new OptionHandler(Flags.deferClassTypes, passThrough),
-    new OptionHandler(Flags.noDeferClassTypes, passThrough),
     new OptionHandler('${Flags.dumpInfo}|${Flags.dumpInfo}=.+', setDumpInfo),
     new OptionHandler('--disallow-unsafe-eval', ignoreOption),
     new OptionHandler(Option.showPackageWarnings, passThrough),
@@ -516,6 +513,7 @@
     new OptionHandler(Flags.experimentLocalNames, ignoreOption),
     new OptionHandler(Flags.experimentStartupFunctions, passThrough),
     new OptionHandler(Flags.experimentToBoolean, passThrough),
+    new OptionHandler(Flags.experimentUnreachableMethodsThrow, passThrough),
     new OptionHandler(Flags.experimentCallInstrumentation, passThrough),
     new OptionHandler(Flags.experimentNewRti, ignoreOption),
 
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index d47da8e..364fe9a 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -7,6 +7,8 @@
 import 'dart:collection' show Queue;
 
 import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
+import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
 
 import 'common/metrics.dart' show Metric, Metrics, CountMetric, DurationMetric;
 import 'common/tasks.dart' show CompilerTask;
@@ -18,12 +20,13 @@
     show
         ConstantValue,
         ConstructedConstantValue,
-        TypeConstantValue,
         DeferredGlobalConstantValue,
         InstantiationConstantValue;
 import 'elements/types.dart';
 import 'elements/entities.dart';
+import 'ir/util.dart';
 import 'kernel/kelements.dart' show KLocalFunction;
+import 'kernel/element_map.dart';
 import 'serialization/serialization.dart';
 import 'options.dart';
 import 'universe/use.dart';
@@ -102,7 +105,7 @@
 /// For each deferred import, find elements and constants to be loaded when that
 /// import is loaded. Elements that are used by several deferred imports are in
 /// shared OutputUnits.
-abstract class DeferredLoadTask extends CompilerTask {
+class DeferredLoadTask extends CompilerTask {
   @override
   String get name => 'Deferred Loading';
 
@@ -149,17 +152,15 @@
 
   final Compiler compiler;
 
+  KernelToElementMap _elementMap;
+
   @override
   final _DeferredLoadTaskMetrics metrics = _DeferredLoadTaskMetrics();
 
   bool get disableProgramSplit => compiler.options.disableProgramSplit;
-  bool get newDeferredSplit => compiler.options.newDeferredSplit;
-  bool get reportInvalidInferredDeferredTypes =>
-      compiler.options.reportInvalidInferredDeferredTypes;
-  bool get deferClassTypes => compiler.options.deferClassTypes;
 
-  DeferredLoadTask(this.compiler) : super(compiler.measurer) {
-    _mainOutputUnit = OutputUnit(true, 'main', <ImportEntity>{});
+  DeferredLoadTask(this.compiler, this._elementMap) : super(compiler.measurer) {
+    _mainOutputUnit = OutputUnit(true, 'main', {});
     importSets.mainSet.unit = _mainOutputUnit;
     _allOutputUnits.add(_mainOutputUnit);
   }
@@ -172,27 +173,6 @@
 
   DiagnosticReporter get reporter => compiler.reporter;
 
-  /// Given [imports] that refer to an element from a library, determine whether
-  /// the element is explicitly deferred.
-  static bool _isExplicitlyDeferred(Iterable<ImportEntity> imports) {
-    // If the element is not imported explicitly, it is implicitly imported
-    // not deferred.
-    if (imports.isEmpty) return false;
-    // An element could potentially be loaded by several imports. If all of them
-    // is explicitly deferred, we say the element is explicitly deferred.
-    // TODO(sigurdm): We might want to give a warning if the imports do not
-    // agree.
-    return imports.every((ImportEntity import) => import.isDeferred);
-  }
-
-  /// Returns every [ImportEntity] that imports [element] into [library].
-  Iterable<ImportEntity> classImportsTo(
-      ClassEntity element, LibraryEntity library);
-
-  /// Returns every [ImportEntity] that imports [element] into [library].
-  Iterable<ImportEntity> memberImportsTo(
-      MemberEntity element, LibraryEntity library);
-
   /// Collects all direct dependencies of [element].
   ///
   /// The collected dependent elements and constants are are added to
@@ -275,30 +255,37 @@
     // they are processed as part of the class.
   }
 
-  /// Extract the set of constants that are used in annotations of [element].
-  ///
-  /// If the underlying system doesn't support mirrors, then no constants are
-  /// added.
-  void collectConstantsFromMetadata(
-      Entity element, Set<ConstantValue> constants);
-
   /// Extract the set of constants that are used in the body of [element].
-  void collectConstantsInBody(MemberEntity element, Dependencies dependencies);
+  void collectConstantsInBody(MemberEntity element, Dependencies dependencies) {
+    ir.Member node = _elementMap.getMemberNode(element);
+
+    // Fetch the internal node in order to skip annotations on the member.
+    // TODO(sigmund): replace this pattern when the kernel-ast provides a better
+    // way to skip annotations (issue 31565).
+    var visitor = new ConstantCollector(
+        _elementMap, _elementMap.getStaticTypeContext(element), dependencies);
+    if (node is ir.Field) {
+      node.initializer?.accept(visitor);
+      return;
+    }
+
+    if (node is ir.Constructor) {
+      node.initializers.forEach((i) => i.accept(visitor));
+    }
+    node.function?.accept(visitor);
+  }
 
   /// Recursively collects all the dependencies of [type].
   void _collectTypeDependencies(DartType type, Dependencies dependencies,
       [ImportEntity import]) {
-    TypeDependencyVisitor(dependencies, import, commonElements,
-            collectClassesAndTypes: !deferClassTypes)
-        .visit(type);
+    TypeDependencyVisitor(dependencies, import, commonElements).visit(type);
   }
 
   void _collectTypeArgumentDependencies(
       Iterable<DartType> typeArguments, Dependencies dependencies,
       [ImportEntity import]) {
     if (typeArguments == null) return;
-    TypeDependencyVisitor(dependencies, import, commonElements,
-            collectClassesAndTypes: !deferClassTypes)
+    TypeDependencyVisitor(dependencies, import, commonElements)
         .visitList(typeArguments);
   }
 
@@ -600,62 +587,6 @@
   /// same nodes we have already seen.
   _shouldAddDeferredDependency(ImportSet newSet) => newSet.length <= 1;
 
-  void _fixDependencyInfo(DependencyInfo info, List<ImportEntity> imports,
-      String prefix, String name, Spannable context) {
-    var isDeferred = _isExplicitlyDeferred(imports);
-    if (isDeferred) {
-      if (!newDeferredSplit) {
-        info.isDeferred = true;
-        info.imports = imports;
-      }
-      if (reportInvalidInferredDeferredTypes) {
-        reporter.reportErrorMessage(context, MessageKind.GENERIC, {
-          'text': "$prefix '$name' is deferred but appears to be inferred as"
-              " a return type or a type parameter (dartbug.com/35311)."
-        });
-      }
-    }
-  }
-
-  // The following 3 methods are used to check whether the new deferred split
-  // algorithm and the old one match. Because of a soundness bug in the old
-  // algorithm the new algorithm can pull in a lot of code to the main output
-  // unit. This logic detects it and will make it easier for us to migrate code
-  // off it incrementally.
-  // Note: we only expect discrepancies on class-dependency-info due to how
-  // inferred types expose deferred types in type-variables and return types
-  // (Issue #35311). We added the other two methods to test our transition, but
-  // we don't expect to detect any mismatches there.
-  //
-  // TODO(sigmund): delete once the new implementation is on by default.
-  void _fixClassDependencyInfo(DependencyInfo info, ClassEntity cls,
-      LibraryEntity library, Spannable context) {
-    if (info.isDeferred) return;
-    if (newDeferredSplit && !reportInvalidInferredDeferredTypes) return;
-    var imports = classImportsTo(cls, library);
-    _fixDependencyInfo(info, imports, "Class", cls.name, context);
-  }
-
-  void _fixMemberDependencyInfo(DependencyInfo info, MemberEntity member,
-      LibraryEntity library, Spannable context) {
-    if (info.isDeferred || compiler.options.newDeferredSplit) return;
-    var imports = memberImportsTo(member, library);
-    _fixDependencyInfo(info, imports, "Member", member.name, context);
-  }
-
-  void _fixConstantDependencyInfo(DependencyInfo info, ConstantValue constant,
-      LibraryEntity library, Spannable context) {
-    if (info.isDeferred || compiler.options.newDeferredSplit) return;
-    if (constant is TypeConstantValue) {
-      var type = constant.representedType.withoutNullability;
-      if (type is InterfaceType) {
-        var imports = classImportsTo(type.element, library);
-        _fixDependencyInfo(
-            info, imports, "Class (in constant) ", type.element.name, context);
-      }
-    }
-  }
-
   void _processDependencies(
       KClosedWorld closedWorld,
       LibraryEntity library,
@@ -665,7 +596,6 @@
       WorkQueue queue,
       Spannable context) {
     dependencies.classes.forEach((ClassEntity cls, DependencyInfo info) {
-      _fixClassDependencyInfo(info, cls, library, context);
       if (info.isDeferred) {
         if (_shouldAddDeferredDependency(newSet)) {
           for (ImportEntity deferredImport in info.imports) {
@@ -678,7 +608,6 @@
     });
 
     dependencies.classType.forEach((ClassEntity cls, DependencyInfo info) {
-      _fixClassDependencyInfo(info, cls, library, context);
       if (info.isDeferred) {
         if (_shouldAddDeferredDependency(newSet)) {
           for (ImportEntity deferredImport in info.imports) {
@@ -691,7 +620,6 @@
     });
 
     dependencies.members.forEach((MemberEntity member, DependencyInfo info) {
-      _fixMemberDependencyInfo(info, member, library, context);
       if (info.isDeferred) {
         if (_shouldAddDeferredDependency(newSet)) {
           for (ImportEntity deferredImport in info.imports) {
@@ -709,7 +637,6 @@
 
     dependencies.constants
         .forEach((ConstantValue constant, DependencyInfo info) {
-      _fixConstantDependencyInfo(info, constant, library, context);
       if (info.isDeferred) {
         if (_shouldAddDeferredDependency(newSet)) {
           for (ImportEntity deferredImport in info.imports) {
@@ -948,10 +875,8 @@
     _localFunctionToSet = null;
     _constantToSet = null;
     importSets = null;
-    cleanup();
     return OutputUnitData(
         this.isProgramSplit && !disableProgramSplit,
-        deferClassTypes,
         this._mainOutputUnit,
         classMap,
         classTypeMap,
@@ -964,15 +889,11 @@
         _deferredImportDescriptions);
   }
 
-  /// Frees up strategy-specific temporary data.
-  void cleanup() {}
-
   void beforeResolution(Uri rootLibraryUri, Iterable<Uri> libraries) {
     measureSubtask('prepare', () {
       for (Uri uri in libraries) {
         LibraryEntity library = elementEnvironment.lookupLibrary(uri);
         reporter.withCurrentElement(library, () {
-          checkForDeferredErrorCases(library);
           for (ImportEntity import in elementEnvironment.getImports(library)) {
             if (import.isDeferred) {
               _deferredImportDescriptions[import] =
@@ -985,13 +906,6 @@
     });
   }
 
-  /// Detects errors like duplicate uses of a prefix or using the old deferred
-  /// loading syntax.
-  ///
-  /// These checks are already done by the shared front-end, so they can be
-  /// skipped by the new compiler pipeline.
-  void checkForDeferredErrorCases(LibraryEntity library);
-
   bool ignoreEntityInDump(Entity element) => false;
 
   /// Creates a textual representation of the output unit content.
@@ -1014,7 +928,7 @@
     });
     _memberToSet.forEach((MemberEntity element, ImportSet importSet) {
       if (ignoreEntityInDump(element)) return;
-      var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
+      var elements = elementMap.putIfAbsent(importSet.unit, () => []);
       var id = element.name ?? '$element';
       var cls = element.enclosingClass?.name;
       if (cls != null) id = '$cls.$id';
@@ -1024,7 +938,7 @@
     });
     _localFunctionToSet.forEach((Local element, ImportSet importSet) {
       if (ignoreEntityInDump(element)) return;
-      var elements = elementMap.putIfAbsent(importSet.unit, () => <String>[]);
+      var elements = elementMap.putIfAbsent(importSet.unit, () => []);
       var id = element.name ?? '$element';
       var context = (element as dynamic).memberContext.name;
       id = element.name == null || element.name == '' ? '<anonymous>' : id;
@@ -1037,7 +951,7 @@
       // if they are shared, they end up duplicated anyways across output units.
       if (value.isPrimitive) return;
       constantMap
-          .putIfAbsent(importSet.unit, () => <String>[])
+          .putIfAbsent(importSet.unit, () => [])
           .add(value.toStructuredText(dartTypes));
     });
 
@@ -1464,7 +1378,6 @@
   static const String tag = 'output-unit-data';
 
   final bool isProgramSplit;
-  final bool deferClassTypes;
   final OutputUnit mainOutputUnit;
   final Map<ClassEntity, OutputUnit> _classToUnit;
   final Map<ClassEntity, OutputUnit> _classTypeToUnit;
@@ -1489,7 +1402,6 @@
 
   OutputUnitData(
       this.isProgramSplit,
-      this.deferClassTypes,
       this.mainOutputUnit,
       this._classToUnit,
       this._classTypeToUnit,
@@ -1532,13 +1444,12 @@
 
     return OutputUnitData(
         other.isProgramSplit,
-        other.deferClassTypes,
         other.mainOutputUnit,
         classToUnit,
         classTypeToUnit,
         memberToUnit,
         // Local functions only make sense in the K-world model.
-        const <Local, OutputUnit>{},
+        const {},
         constantToUnit,
         other.outputUnits,
         other._importDeferName,
@@ -1550,7 +1461,6 @@
   factory OutputUnitData.readFromDataSource(DataSource source) {
     source.begin(tag);
     bool isProgramSplit = source.readBool();
-    bool deferClassTypes = source.readBool();
     List<OutputUnit> outputUnits = source.readList(() {
       bool isMainOutput = source.readBool();
       String name = source.readString();
@@ -1589,13 +1499,12 @@
     source.end(tag);
     return OutputUnitData(
         isProgramSplit,
-        deferClassTypes,
         mainOutputUnit,
         classToUnit,
         classTypeToUnit,
         memberToUnit,
         // Local functions only make sense in the K-world model.
-        const <Local, OutputUnit>{},
+        const {},
         constantToUnit,
         outputUnits,
         importDeferName,
@@ -1607,7 +1516,6 @@
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
     sink.writeBool(isProgramSplit);
-    sink.writeBool(deferClassTypes);
     Map<OutputUnit, int> outputUnitIndices = {};
     sink.writeList(outputUnits, (OutputUnit outputUnit) {
       outputUnitIndices[outputUnit] = outputUnitIndices.length;
@@ -1661,18 +1569,13 @@
   // TODO(joshualitt): see above TODO regarding allowNull.
   OutputUnit outputUnitForClassType(ClassEntity cls, {bool allowNull: false}) {
     if (!isProgramSplit) return mainOutputUnit;
-    OutputUnit unit;
-    if (deferClassTypes) {
-      unit = _classTypeToUnit[cls];
-    } else {
-      unit = _classToUnit[cls];
-    }
+    OutputUnit unit = _classTypeToUnit[cls];
     assert(allowNull || unit != null, 'No output unit for type $cls');
     return unit ?? mainOutputUnit;
   }
 
   OutputUnit outputUnitForClassTypeForTesting(ClassEntity cls) =>
-      deferClassTypes ? _classTypeToUnit[cls] : _classToUnit[cls];
+      _classTypeToUnit[cls];
 
   /// Returns the [OutputUnit] where [member] belongs.
   OutputUnit outputUnitForMember(MemberEntity member) {
@@ -1801,10 +1704,8 @@
 
       Map<String, dynamic> libraryMap = mapping.putIfAbsent(
           description.importingUri,
-          () => <String, dynamic>{
-                "name": getName(description._importingLibrary),
-                "imports": <String, List<String>>{}
-              });
+          () =>
+              {"name": getName(description._importingLibrary), "imports": {}});
 
       List<String> partFileNames = outputUnits
           .where((outputUnit) => !omittedUnits.contains(outputUnit))
@@ -1874,16 +1775,11 @@
 }
 
 class TypeDependencyVisitor implements DartTypeVisitor<void, Null> {
-  // If true, collect classes and types, otherwise just collect types.
-  // Note: When collecting classes, types are added implicitly by the
-  // dependencies class.
-  final bool collectClassesAndTypes;
   final Dependencies _dependencies;
   final ImportEntity _import;
   final CommonElements _commonElements;
 
-  TypeDependencyVisitor(this._dependencies, this._import, this._commonElements,
-      {this.collectClassesAndTypes});
+  TypeDependencyVisitor(this._dependencies, this._import, this._commonElements);
 
   @override
   void visit(DartType type, [_]) {
@@ -1906,11 +1802,7 @@
 
   @override
   void visitFutureOrType(FutureOrType type, Null argument) {
-    if (collectClassesAndTypes) {
-      _dependencies.addClass(_commonElements.futureClass);
-    } else {
-      _dependencies.addClassType(_commonElements.futureClass);
-    }
+    _dependencies.addClassType(_commonElements.futureClass);
     visit(type.typeArgument);
   }
 
@@ -1937,11 +1829,7 @@
   @override
   void visitInterfaceType(InterfaceType type, Null argument) {
     visitList(type.typeArguments);
-    if (collectClassesAndTypes) {
-      _dependencies.addClass(type.element, _import);
-    } else {
-      _dependencies.addClassType(type.element, _import);
-    }
+    _dependencies.addClassType(type.element, _import);
   }
 
   @override
@@ -1970,3 +1858,108 @@
     // Nothing to add.
   }
 }
+
+class ConstantCollector extends ir.RecursiveVisitor {
+  final KernelToElementMap elementMap;
+  final Dependencies dependencies;
+  final ir.StaticTypeContext staticTypeContext;
+
+  ConstantCollector(this.elementMap, this.staticTypeContext, this.dependencies);
+
+  CommonElements get commonElements => elementMap.commonElements;
+
+  void add(ir.Expression node, {bool required: true}) {
+    ConstantValue constant = elementMap
+        .getConstantValue(staticTypeContext, node, requireConstant: required);
+    if (constant != null) {
+      dependencies.addConstant(
+          constant, elementMap.getImport(getDeferredImport(node)));
+    }
+  }
+
+  @override
+  void visitIntLiteral(ir.IntLiteral literal) {}
+
+  @override
+  void visitDoubleLiteral(ir.DoubleLiteral literal) {}
+
+  @override
+  void visitBoolLiteral(ir.BoolLiteral literal) {}
+
+  @override
+  void visitStringLiteral(ir.StringLiteral literal) {}
+
+  @override
+  void visitSymbolLiteral(ir.SymbolLiteral literal) => add(literal);
+
+  @override
+  void visitNullLiteral(ir.NullLiteral literal) {}
+
+  @override
+  void visitListLiteral(ir.ListLiteral literal) {
+    if (literal.isConst) {
+      add(literal);
+    } else {
+      super.visitListLiteral(literal);
+    }
+  }
+
+  @override
+  void visitSetLiteral(ir.SetLiteral literal) {
+    if (literal.isConst) {
+      add(literal);
+    } else {
+      super.visitSetLiteral(literal);
+    }
+  }
+
+  @override
+  void visitMapLiteral(ir.MapLiteral literal) {
+    if (literal.isConst) {
+      add(literal);
+    } else {
+      super.visitMapLiteral(literal);
+    }
+  }
+
+  @override
+  void visitConstructorInvocation(ir.ConstructorInvocation node) {
+    if (node.isConst) {
+      add(node);
+    } else {
+      super.visitConstructorInvocation(node);
+    }
+  }
+
+  @override
+  void visitTypeParameter(ir.TypeParameter node) {
+    // We avoid visiting metadata on the type parameter declaration. The bound
+    // cannot hold constants so we skip that as well.
+  }
+
+  @override
+  void visitVariableDeclaration(ir.VariableDeclaration node) {
+    // We avoid visiting metadata on the parameter declaration by only visiting
+    // the initializer. The type cannot hold constants so can kan skip that
+    // as well.
+    node.initializer?.accept(this);
+  }
+
+  @override
+  void visitTypeLiteral(ir.TypeLiteral node) {
+    if (node.type is! ir.TypeParameterType) add(node);
+  }
+
+  @override
+  void visitInstantiation(ir.Instantiation node) {
+    // TODO(johnniwinther): The CFE should mark constant instantiations as
+    // constant.
+    add(node, required: false);
+    super.visitInstantiation(node);
+  }
+
+  @override
+  void visitConstantExpression(ir.ConstantExpression node) {
+    add(node);
+  }
+}
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index d6a7e2f..0271281 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -74,7 +74,6 @@
   INVALID_PACKAGE_URI,
   INVALID_STRING_FROM_ENVIRONMENT_DEFAULT_VALUE_TYPE,
   JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS,
-  JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
   JS_INTEROP_FIELD_NOT_SUPPORTED,
   JS_INTEROP_NON_EXTERNAL_MEMBER,
   JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
@@ -200,25 +199,6 @@
           MessageKind.JS_INTEROP_NON_EXTERNAL_MEMBER,
           "Js-interop members must be 'external'."),
 
-      MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER: const MessageTemplate(
-          MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
-          "Member '#{member}' in js-interop class '#{cls}' is not external.",
-          howToFix: "Try adding 'external' to '#{member}'.",
-          examples: const [
-            """
-              import 'package:js/js.dart';
-
-              @JS()
-              class Foo {
-                bar() {}
-              }
-
-              main() {
-                new Foo().bar();
-              }
-              """
-          ]),
-
       MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED:
           const MessageTemplate(
               MessageKind.IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED,
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 2b45419..7cb8bc2 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -1734,7 +1734,6 @@
   /// The types defined in 'dart:core'.
   CommonElements get commonElements;
 
-  bool get useNullSafety;
   bool get useLegacySubtyping;
 
   DartType bottomType() =>
@@ -1844,7 +1843,7 @@
     } else if (typeArgument.isNull) {
       DartType futureOfNull =
           commonElements.futureType(commonElements.nullType);
-      result = useNullSafety ? nullableType(futureOfNull) : futureOfNull;
+      result = nullableType(futureOfNull);
     } else {
       result = FutureOrType._(typeArgument);
     }
@@ -2281,14 +2280,10 @@
     if (isCovariant) {
       // A covariant parameter has type `Object` in the method signature.
       var objectType = commonElements.objectType;
-      if (useNullSafety) {
-        if (isNonNullableByDefaultLibrary) {
-          return nullableType(objectType);
-        } else {
-          return legacyType(objectType);
-        }
+      if (isNonNullableByDefaultLibrary) {
+        return nullableType(objectType);
       } else {
-        return objectType;
+        return legacyType(objectType);
       }
     }
     return type;
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index 274cf1d..a034e30 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -161,6 +161,11 @@
   /// at runtime.
   AbstractValue get fixedListType;
 
+  /// The [AbstractValue] that represents the union of [growableListType] and
+  /// [fixedListType], i.e. JavaScript arrays that may have their elements
+  /// assigned.
+  AbstractValue get mutableArrayType;
+
   /// The [AbstractValue] that represents a non-null 31-bit unsigned integer at
   /// runtime.
   AbstractValue get uint31Type;
diff --git a/pkg/compiler/lib/src/inferrer/builder_kernel.dart b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
index ceb5d63..f11b3fb 100644
--- a/pkg/compiler/lib/src/inferrer/builder_kernel.dart
+++ b/pkg/compiler/lib/src/inferrer/builder_kernel.dart
@@ -206,7 +206,7 @@
 
   TypeInformation run() {
     if (_analyzedMember.isField) {
-      if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) {
+      if (_analyzedNode == null || isNullLiteral(_analyzedNode)) {
         // Eagerly bailout, because computing the closure data only
         // works for functions and field assignments.
         return _types.nullType;
@@ -301,8 +301,7 @@
           assert(definition.kind == MemberKind.regular);
           ir.Field node = definition.node;
           if (type == null &&
-              (node.initializer == null ||
-                  node.initializer is ir.NullLiteral)) {
+              (node.initializer == null || isNullLiteral(node.initializer))) {
             _inferrer.recordTypeOfField(member, _types.nullType);
           }
         }
@@ -1188,7 +1187,34 @@
     return null;
   }
 
-  /// Returns `true` if
+  /// Find the base type for a system List constructor from the value passed to
+  /// the 'growable' argument. [defaultGrowable] is the default value of the
+  /// 'growable' parameter.
+  TypeInformation _listBaseType(ir.Arguments arguments,
+      {bool defaultGrowable}) {
+    TypeInformation finish(bool /*?*/ growable) {
+      if (growable == true) return _types.growableListType;
+      if (growable == false) return _types.fixedListType;
+      return _types.mutableArrayType;
+    }
+
+    for (ir.NamedExpression named in arguments.named) {
+      if (named.name == 'growable') {
+        ir.Expression argument = named.value;
+        if (argument is ir.BoolLiteral) return finish(argument.value);
+        if (argument is ir.ConstantExpression) {
+          ir.Constant constant = argument.constant;
+          if (constant is ir.BoolConstant) return finish(constant.value);
+        }
+        // 'growable' is present, but indeterminate.
+        return finish(null);
+      }
+    }
+    // 'growable' is missing.
+    return finish(defaultGrowable);
+  }
+
+  /// Returns `true` for constructors of typed arrays.
   bool _isConstructorOfTypedArraySubclass(ConstructorEntity constructor) {
     ClassEntity cls = constructor.enclosingClass;
     return cls.library.canonicalUri == Uris.dart__native_typed_data &&
@@ -1208,7 +1234,15 @@
       ArgumentsTypes argumentsTypes) {
     TypeInformation returnType =
         handleStaticInvoke(node, selector, constructor, argumentsTypes);
-    if (_elementMap.commonElements.isUnnamedListConstructor(constructor)) {
+
+    // See if we can replace the returned type with one that better describes
+    // the operation. For system List constructors we can treat this as the
+    // allocation point of a new collection. The static invoke above ensures
+    // that the implementation of the constructor sees the arguments.
+
+    var commonElements = _elementMap.commonElements;
+
+    if (commonElements.isUnnamedListConstructor(constructor)) {
       // We have `new List(...)`.
       if (arguments.positional.isEmpty && arguments.named.isEmpty) {
         // We have `new List()`.
@@ -1224,18 +1258,52 @@
             () => _types.allocateList(_types.fixedListType, node,
                 _analyzedMember, _types.nullType, length));
       }
-    } else if (_elementMap.commonElements
-        .isFilledListConstructor(constructor)) {
-      // We have `new Uint32List(len, fill)`.
+    }
+
+    if (commonElements.isNamedListConstructor('filled', constructor)) {
+      // We have something like `List.filled(len, fill)`.
       int length = _findLength(arguments);
       TypeInformation elementType = argumentsTypes.positional[1];
-
+      TypeInformation baseType =
+          _listBaseType(arguments, defaultGrowable: false);
       return _inferrer.concreteTypes.putIfAbsent(
           node,
-          () => _types.allocateList(_types.fixedListType, node, _analyzedMember,
-              elementType, length));
-    } else if (_isConstructorOfTypedArraySubclass(constructor)) {
-      // We have something like `new List.filled(len, fill)`.
+          () => _types.allocateList(
+              baseType, node, _analyzedMember, elementType, length));
+    }
+
+    if (commonElements.isNamedListConstructor('generate', constructor)) {
+      // We have something like `List.generate(len, generator)`.
+      int length = _findLength(arguments);
+      // TODO(sra): What we really want here is the result of calling the
+      // `generator` parameter with a non-negative integer.
+      TypeInformation elementType = _types.dynamicType;
+      TypeInformation baseType =
+          _listBaseType(arguments, defaultGrowable: true);
+      return _inferrer.concreteTypes.putIfAbsent(
+          node,
+          () => _types.allocateList(
+              baseType, node, _analyzedMember, elementType, length));
+    }
+
+    if (commonElements.isNamedListConstructor('empty', constructor)) {
+      // We have something like `List.empty(growable: true)`.
+      TypeInformation baseType =
+          _listBaseType(arguments, defaultGrowable: false);
+      return _inferrer.concreteTypes.putIfAbsent(
+          node,
+          () => _types.allocateList(
+              baseType, node, _analyzedMember, _types.nonNullEmpty(), 0));
+    }
+    if (commonElements.isNamedListConstructor('of', constructor) ||
+        commonElements.isNamedListConstructor('from', constructor)) {
+      // We have something like `List.of(elements)`.
+      TypeInformation baseType =
+          _listBaseType(arguments, defaultGrowable: true);
+      return baseType;
+    }
+    if (_isConstructorOfTypedArraySubclass(constructor)) {
+      // We have something like `Uint32List(len)`.
       int length = _findLength(arguments);
       MemberEntity member = _elementMap.elementEnvironment
           .lookupClassMember(constructor.enclosingClass, '[]');
@@ -1248,9 +1316,9 @@
               _analyzedMember,
               elementType,
               length));
-    } else {
-      return returnType;
     }
+
+    return returnType;
   }
 
   TypeInformation handleStaticInvoke(ir.Node node, Selector selector,
@@ -1386,13 +1454,6 @@
   }
 
   @override
-  TypeInformation visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    TypeInformation receiverType = thisType;
-    return handlePropertyGet(node, node.receiver, receiverType, node.target,
-        isThis: true);
-  }
-
-  @override
   TypeInformation visitPropertySet(ir.PropertySet node) {
     TypeInformation receiverType = visit(node.receiver);
     Selector selector = _elementMap.getSelector(node);
@@ -1522,7 +1583,7 @@
 
   @override
   TypeInformation visitLogicalExpression(ir.LogicalExpression node) {
-    if (node.operator == '&&') {
+    if (node.operatorEnum == ir.LogicalExpressionOperator.AND) {
       LocalState stateBefore = _state;
       _state = new LocalState.childPath(stateBefore);
       TypeInformation leftInfo = handleCondition(node.left);
@@ -1547,7 +1608,7 @@
       }
       // TODO(sra): Add a selector/mux node to improve precision.
       return _types.boolType;
-    } else if (node.operator == '||') {
+    } else if (node.operatorEnum == ir.LogicalExpressionOperator.OR) {
       LocalState stateBefore = _state;
       _state = new LocalState.childPath(stateBefore);
       TypeInformation leftInfo = handleCondition(node.left);
@@ -1574,7 +1635,7 @@
       return _types.boolType;
     }
     failedAt(CURRENT_ELEMENT_SPANNABLE,
-        "Unexpected logical operator '${node.operator}'.");
+        "Unexpected logical operator '${node.operatorEnum}'.");
     return null;
   }
 
diff --git a/pkg/compiler/lib/src/inferrer/closure_tracer.dart b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
index 0a01c9b..809b850 100644
--- a/pkg/compiler/lib/src/inferrer/closure_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/closure_tracer.dart
@@ -84,6 +84,8 @@
       String name = called.name;
       if (name == Identifiers.JS || name == Identifiers.DART_CLOSURE_TO_JS) {
         bailout('Used in JS ${info.debugName}');
+      } else if (name == Identifiers.RAW_DART_FUNCTION_REF) {
+        bailout('Escaped raw function reference');
       }
     }
     if (called.isGetter &&
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
index f91a311..946412a 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powerset_bits.dart
@@ -449,12 +449,10 @@
     }
 
     if (type is NullableType) {
-      assert(dartTypes.useNullSafety);
       return _createFromStaticType(type.baseType, classRelation, true);
     }
 
     if (type is LegacyType) {
-      assert(dartTypes.useNullSafety);
       DartType baseType = type.baseType;
       if (baseType is NeverType) {
         // Never* is same as Null, for both 'is' and 'as'.
@@ -589,6 +587,10 @@
   int get growableListType => _growableListType ??=
       createNonNullExact(commonElements.jsExtendableArrayClass);
 
+  int _mutableArrayType;
+  int get mutableArrayType => _mutableArrayType ??=
+      createNonNullSubtype(commonElements.jsMutableArrayClass);
+
   int get nullType => nullValue;
 
   int get nonNullType => powersetTop & ~nullValue;
diff --git a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
index 61a5124..22dc603 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/powersets.dart
@@ -745,6 +745,11 @@
       _powersetBitsDomain.growableListType);
 
   @override
+  AbstractValue get mutableArrayType => PowersetValue(
+      _abstractValueDomain.mutableArrayType,
+      _powersetBitsDomain.mutableArrayType);
+
+  @override
   AbstractValue get nullType => PowersetValue(
       _abstractValueDomain.nullType, _powersetBitsDomain.nullType);
 
diff --git a/pkg/compiler/lib/src/inferrer/powersets/wrapped.dart b/pkg/compiler/lib/src/inferrer/powersets/wrapped.dart
index e7df0d2..977bef0 100644
--- a/pkg/compiler/lib/src/inferrer/powersets/wrapped.dart
+++ b/pkg/compiler/lib/src/inferrer/powersets/wrapped.dart
@@ -542,6 +542,10 @@
       WrappedAbstractValue(_abstractValueDomain.growableListType);
 
   @override
+  AbstractValue get mutableArrayType =>
+      WrappedAbstractValue(_abstractValueDomain.mutableArrayType);
+
+  @override
   AbstractValue get nullType =>
       WrappedAbstractValue(_abstractValueDomain.nullType);
 
diff --git a/pkg/compiler/lib/src/inferrer/trivial.dart b/pkg/compiler/lib/src/inferrer/trivial.dart
index afb7a7e..8ddb82b 100644
--- a/pkg/compiler/lib/src/inferrer/trivial.dart
+++ b/pkg/compiler/lib/src/inferrer/trivial.dart
@@ -402,6 +402,9 @@
   AbstractValue get growableListType => const TrivialAbstractValue();
 
   @override
+  AbstractValue get mutableArrayType => const TrivialAbstractValue();
+
+  @override
   AbstractValue get nullType => const TrivialAbstractValue();
 
   @override
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
index 62e0b11..d1e4239 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_inferrer.dart
@@ -154,9 +154,8 @@
       parameterResults[parameter] = type;
     });
 
-    Map<ir.TreeNode, AbstractValue> allocatedLists =
-        <ir.TreeNode, AbstractValue>{};
-    Set<ir.TreeNode> checkedForGrowableLists = new Set<ir.TreeNode>();
+    Map<ir.TreeNode, AbstractValue> allocatedLists = {};
+    Set<ir.TreeNode> checkedForGrowableLists = {};
     inferrer.types.allocatedLists
         .forEach((ir.TreeNode node, ListTypeInformation typeInformation) {
       ListTypeInformation info = inferrer.types.allocatedLists[node];
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 4aa804c..365500e 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -1502,7 +1502,20 @@
   }
 
   @override
-  AbstractValue computeType(InferrerEngine inferrer) => safeType(inferrer);
+  AbstractValue computeType(InferrerEngine inferrer) {
+    AbstractValueDomain abstractValueDomain = inferrer.abstractValueDomain;
+    AbstractValue closureType = closure.type;
+    // We are not tracking closure calls, but if the receiver is not callable,
+    // the call will fail. The abstract value domain does not have a convenient
+    // method for detecting callable types, but we know `null` and unreachable
+    // code have no result type.  This is helpful for propagating
+    // unreachability, i.e. tree-shaking.
+    if (abstractValueDomain.isEmpty(closureType).isDefinitelyTrue ||
+        abstractValueDomain.isNull(closureType).isDefinitelyTrue) {
+      return abstractValueDomain.emptyType;
+    }
+    return safeType(inferrer);
+  }
 
   @override
   Iterable<MemberEntity> get callees {
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index 3817dc9..32b3081 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -218,6 +218,10 @@
         getConcreteTypeFor(_abstractValueDomain.growableListType);
   }
 
+  TypeInformation _mutableArrayType;
+  TypeInformation get mutableArrayType => _mutableArrayType ??=
+      getConcreteTypeFor(_abstractValueDomain.mutableArrayType);
+
   TypeInformation setTypeCache;
   TypeInformation get setType =>
       setTypeCache ??= getConcreteTypeFor(_abstractValueDomain.setType);
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
index f20f16d..b8840fb 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/masks.dart
@@ -131,7 +131,7 @@
 
   @override
   TypeMask get listType => _listType ??=
-      new TypeMask.nonNullExact(commonElements.jsArrayClass, _closedWorld);
+      new TypeMask.nonNullSubtype(commonElements.jsArrayClass, _closedWorld);
 
   @override
   TypeMask get constListType => _constListType ??= new TypeMask.nonNullExact(
@@ -197,6 +197,7 @@
   TypeMask get readableArrayType => _readableArrayType ??=
       new TypeMask.nonNullSubclass(commonElements.jsArrayClass, _closedWorld);
 
+  @override
   TypeMask get mutableArrayType =>
       _mutableArrayType ??= new TypeMask.nonNullSubclass(
           commonElements.jsMutableArrayClass, _closedWorld);
@@ -277,12 +278,10 @@
     }
 
     if (type is NullableType) {
-      assert(dartTypes.useNullSafety);
       return _createFromStaticType(type.baseType, classRelation, true);
     }
 
     if (type is LegacyType) {
-      assert(dartTypes.useNullSafety);
       DartType baseType = type.baseType;
       if (baseType is NeverType) {
         // Never* is same as Null, for both 'is' and 'as'.
@@ -999,7 +998,11 @@
     // a null value we accidentally printed out.
     if (type.isEmptyOrNull) return type.isNullable ? 'Null' : 'Empty';
     String nullFlag = type.isNullable ? '?' : '';
-    String subFlag = type.isExact ? '' : type.isSubclass ? '+' : '*';
+    String subFlag = type.isExact
+        ? ''
+        : type.isSubclass
+            ? '+'
+            : '*';
     return '${type.base.name}$nullFlag$subFlag';
   }
   if (type is UnionTypeMask) {
diff --git a/pkg/compiler/lib/src/inferrer/types.dart b/pkg/compiler/lib/src/inferrer/types.dart
index 25305e4..bafd5cc3 100644
--- a/pkg/compiler/lib/src/inferrer/types.dart
+++ b/pkg/compiler/lib/src/inferrer/types.dart
@@ -310,22 +310,29 @@
   @override
   AbstractValue resultTypeOfSelector(
       Selector selector, AbstractValue receiver) {
-    // Bailout for closure calls. We're not tracking types of
-    // closures.
-    if (selector.isClosureCall)
-      return closedWorld.abstractValueDomain.dynamicType;
+    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+
+    // Bailout for closure calls. We're not tracking types of closures.
+    if (selector.isClosureCall) {
+      // But if the receiver is not callable, the call will fail.
+      if (abstractValueDomain.isEmpty(receiver).isDefinitelyTrue ||
+          abstractValueDomain.isNull(receiver).isDefinitelyTrue) {
+        return abstractValueDomain.emptyType;
+      }
+      return abstractValueDomain.dynamicType;
+    }
     if (selector.isSetter || selector.isIndexSet) {
-      return closedWorld.abstractValueDomain.dynamicType;
+      return abstractValueDomain.dynamicType;
     }
     if (returnsListElementType(selector, receiver)) {
-      return closedWorld.abstractValueDomain.getContainerElementType(receiver);
+      return abstractValueDomain.getContainerElementType(receiver);
     }
     if (returnsMapValueType(selector, receiver)) {
-      return closedWorld.abstractValueDomain.getMapValueType(receiver);
+      return abstractValueDomain.getMapValueType(receiver);
     }
 
     if (closedWorld.includesClosureCall(selector, receiver)) {
-      return closedWorld.abstractValueDomain.dynamicType;
+      return abstractValueDomain.dynamicType;
     } else {
       Iterable<MemberEntity> elements =
           closedWorld.locateMembers(selector, receiver);
@@ -334,7 +341,7 @@
         AbstractValue type = typeOfMemberWithSelector(element, selector);
         types.add(type);
       }
-      return closedWorld.abstractValueDomain.unionOfMany(types);
+      return abstractValueDomain.unionOfMany(types);
     }
   }
 
diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart
index f8d5341..6600d21 100644
--- a/pkg/compiler/lib/src/io/kernel_source_information.dart
+++ b/pkg/compiler/lib/src/io/kernel_source_information.dart
@@ -93,7 +93,7 @@
         } else {
           extensionName = extension.name;
         }
-        String memberName = descriptor.name.name;
+        String memberName = descriptor.name.text;
         return '$extensionName.$memberName';
       }
     }
diff --git a/pkg/compiler/lib/src/ir/annotations.dart b/pkg/compiler/lib/src/ir/annotations.dart
index 637bd63..fa04392 100644
--- a/pkg/compiler/lib/src/ir/annotations.dart
+++ b/pkg/compiler/lib/src/ir/annotations.dart
@@ -77,7 +77,7 @@
     _jsInteropLibraryNames.forEach((ir.Library library, _) {
       for (ir.Member member in library.members) {
         if (member.isExternal) {
-          f(member, _jsInteropMemberNames[member] ?? member.name.name);
+          f(member, _jsInteropMemberNames[member] ?? member.name.text);
         }
       }
     });
@@ -86,7 +86,7 @@
         if (member is ir.Field) continue;
         String name = _jsInteropMemberNames[member];
         if (member.isExternal) {
-          name ??= member.name.name;
+          name ??= member.name.text;
         }
         f(member, name);
       }
@@ -99,7 +99,7 @@
           f) {
     for (ir.Member node in _nativeMembers) {
       if (node is! ir.Field) {
-        String name = _nativeMemberNames[node] ?? node.name.name;
+        String name = _nativeMemberNames[node] ?? node.name.text;
         f(node, name, getCreatesAnnotations(node), getReturnsAnnotations(node));
       }
     }
@@ -112,7 +112,7 @@
     for (ir.Class cls in _nativeClassNames.keys) {
       for (ir.Field field in cls.fields) {
         if (field.isInstanceMember) {
-          String name = _nativeMemberNames[field] ?? field.name.name;
+          String name = _nativeMemberNames[field] ?? field.name.text;
           f(field, name, getCreatesAnnotations(field),
               getReturnsAnnotations(field));
         }
@@ -348,9 +348,9 @@
     ir.Constant optionsValue;
     value.fieldValues.forEach((ir.Reference reference, ir.Constant fieldValue) {
       ir.Field field = reference.asField;
-      if (field.name.name == 'name') {
+      if (field.name.text == 'name') {
         nameValue = fieldValue;
-      } else if (field.name.name == 'options') {
+      } else if (field.name.text == 'options') {
         optionsValue = fieldValue;
       }
     });
diff --git a/pkg/compiler/lib/src/ir/cached_static_type.dart b/pkg/compiler/lib/src/ir/cached_static_type.dart
index aa385c4..9e12e6c 100644
--- a/pkg/compiler/lib/src/ir/cached_static_type.dart
+++ b/pkg/compiler/lib/src/ir/cached_static_type.dart
@@ -52,10 +52,6 @@
   ir.DartType visitPropertyGet(ir.PropertyGet node) => _getStaticType(node);
 
   @override
-  ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) =>
-      _getStaticType(node);
-
-  @override
   ir.DartType visitSuperPropertyGet(ir.SuperPropertyGet node) =>
       _getStaticType(node);
 
@@ -64,10 +60,6 @@
       _getStaticType(node);
 
   @override
-  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) =>
-      _getStaticType(node);
-
-  @override
   ir.DartType visitStaticInvocation(ir.StaticInvocation node) =>
       _getStaticType(node);
 
diff --git a/pkg/compiler/lib/src/ir/constants.dart b/pkg/compiler/lib/src/ir/constants.dart
index c63a3b4..d1ddfd7 100644
--- a/pkg/compiler/lib/src/ir/constants.dart
+++ b/pkg/compiler/lib/src/ir/constants.dart
@@ -37,16 +37,28 @@
   @override
   ErrorReporter get errorReporter => super.errorReporter;
 
+  /// Evaluates [node] to a constant in the given [staticTypeContext].
+  ///
+  /// If [requireConstant] is `true`, an error is reported if [node] is not
+  /// a valid constant. Otherwise, `null` if [node] is not a valid constant.
+  ///
+  /// If [replaceImplicitConstant] is `true`, if [node] is not a constant
+  /// expression but evaluates to a constant, [node] is replaced with an
+  /// [ir.ConstantExpression] holding the constant. Otherwise the [node] is not
+  /// replaced even when it evaluated to a constant.
   @override
   ir.Constant evaluate(
       ir.StaticTypeContext staticTypeContext, ir.Expression node,
-      {bool requireConstant: true}) {
+      {ir.TreeNode contextNode,
+      bool requireConstant: true,
+      bool replaceImplicitConstant: true}) {
     errorReporter.requiresConstant = requireConstant;
     if (node is ir.ConstantExpression) {
       ir.Constant constant = node.constant;
       if (constant is ir.UnevaluatedConstant) {
-        ir.Constant result =
-            super.evaluate(staticTypeContext, constant.expression);
+        ir.Constant result = super.evaluate(
+            staticTypeContext, constant.expression,
+            contextNode: contextNode);
         assert(
             result is ir.UnevaluatedConstant ||
                 !result.accept(const UnevaluatedConstantFinder()),
@@ -59,16 +71,21 @@
       return constant;
     }
     if (requireConstant) {
-      return super.evaluate(staticTypeContext, node);
+      return super.evaluate(staticTypeContext, node, contextNode: contextNode);
     } else {
       try {
-        ir.Constant constant = super.evaluate(staticTypeContext, node);
+        ir.Constant constant =
+            super.evaluate(staticTypeContext, node, contextNode: contextNode);
         if (constant is ir.UnevaluatedConstant &&
             constant.expression is ir.InvalidExpression) {
           return null;
         }
-        // TODO(johnniwinther,sigmund): Replace [node] with an
-        // `ir.ConstantExpression` holding the [constant].
+        if (constant != null && replaceImplicitConstant) {
+          // Note: Using [replaceWith] is slow and should be avoided.
+          node.replaceWith(ir.ConstantExpression(
+              constant, node.getStaticType(staticTypeContext))
+            ..fileOffset = node.fileOffset);
+        }
         return constant;
       } catch (e) {
         return null;
diff --git a/pkg/compiler/lib/src/ir/debug.dart b/pkg/compiler/lib/src/ir/debug.dart
index 27fad8e..01fc1f0 100644
--- a/pkg/compiler/lib/src/ir/debug.dart
+++ b/pkg/compiler/lib/src/ir/debug.dart
@@ -29,7 +29,7 @@
   @override
   void visitName(Name node) {
     openAndCloseNode(node, '${node.runtimeType}',
-        {'name': node.name, 'library': node.library?.name});
+        {'name': node.text, 'library': node.library?.name});
   }
 
   @override
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index c176e35..0dfcc55 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -542,7 +542,7 @@
             positionArguments, namedArguments, typeArguments);
         // TODO(johnniwinther): Avoid treating a known function call as a
         // dynamic call when CFE provides a way to distinguish the two.
-        if (operatorFromString(node.name.name) == null &&
+        if (operatorFromString(node.name.text) == null &&
             receiverType is ir.DynamicType) {
           // We might implicitly call a getter that returns a function.
           registerFunctionInvocation(const ir.DynamicType(), positionArguments,
@@ -565,21 +565,6 @@
   }
 
   @override
-  void handleDirectMethodInvocation(
-      ir.DirectMethodInvocation node,
-      ir.DartType receiverType,
-      ArgumentTypes argumentTypes,
-      ir.DartType returnType) {
-    registerInstanceInvocation(
-        receiverType,
-        ClassRelation.exact,
-        node.target,
-        node.arguments.positional.length,
-        _getNamedArguments(node.arguments),
-        node.arguments.types);
-  }
-
-  @override
   void handlePropertyGet(
       ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
     ClassRelation relation = computeClassRelationFromType(receiverType);
@@ -591,12 +576,6 @@
   }
 
   @override
-  void handleDirectPropertyGet(ir.DirectPropertyGet node,
-      ir.DartType receiverType, ir.DartType resultType) {
-    registerInstanceGet(receiverType, ClassRelation.exact, node.target);
-  }
-
-  @override
   void handlePropertySet(
       ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
     ClassRelation relation = computeClassRelationFromType(receiverType);
@@ -608,12 +587,6 @@
   }
 
   @override
-  void handleDirectPropertySet(ir.DirectPropertySet node,
-      ir.DartType receiverType, ir.DartType valueType) {
-    registerInstanceSet(receiverType, ClassRelation.exact, node.target);
-  }
-
-  @override
   void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
       ArgumentTypes argumentTypes, ir.DartType returnType) {
     registerSuperInvocation(node.name, node.arguments.positional.length,
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
index a76ff95..b5a7e94 100644
--- a/pkg/compiler/lib/src/ir/impact_data.dart
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -392,31 +392,31 @@
 
   @override
   void registerSymbolLiteral(String value) {
-    _data._symbolLiterals ??= [];
+    _data._symbolLiterals ??= {};
     _data._symbolLiterals.add(value);
   }
 
   @override
   void registerStringLiteral(String value) {
-    _data._stringLiterals ??= [];
+    _data._stringLiterals ??= {};
     _data._stringLiterals.add(value);
   }
 
   @override
   void registerBoolLiteral(bool value) {
-    _data._boolLiterals ??= [];
+    _data._boolLiterals ??= {};
     _data._boolLiterals.add(value);
   }
 
   @override
   void registerDoubleLiteral(double value) {
-    _data._doubleLiterals ??= [];
+    _data._doubleLiterals ??= {};
     _data._doubleLiterals.add(value);
   }
 
   @override
   void registerIntLiteral(int value) {
-    _data._intLiterals ??= [];
+    _data._intLiterals ??= {};
     _data._intLiterals.add(value);
   }
 
@@ -508,11 +508,11 @@
   List<_MapLiteral> _mapLiterals;
   List<_ContainerLiteral> _listLiterals;
   List<_ContainerLiteral> _setLiterals;
-  List<String> _symbolLiterals;
-  List<String> _stringLiterals;
-  List<bool> _boolLiterals;
-  List<double> _doubleLiterals;
-  List<int> _intLiterals;
+  Set<String> _symbolLiterals;
+  Set<String> _stringLiterals;
+  Set<bool> _boolLiterals;
+  Set<double> _doubleLiterals;
+  Set<int> _intLiterals;
   List<_RuntimeTypeUse> _runtimeTypeUses;
   List<_ForInData> _forInData;
 
@@ -599,13 +599,16 @@
     _setLiterals = source.readList(
         () => new _ContainerLiteral.fromDataSource(source),
         emptyAsNull: true);
-    _symbolLiterals = source.readStrings(emptyAsNull: true);
-    _stringLiterals = source.readStrings(emptyAsNull: true);
-    _boolLiterals = source.readList(() => source.readBool(), emptyAsNull: true);
-    _doubleLiterals =
-        source.readList(() => source.readDoubleValue(), emptyAsNull: true);
-    _intLiterals =
-        source.readList(() => source.readIntegerValue(), emptyAsNull: true);
+    _symbolLiterals = source.readStrings(emptyAsNull: true).toSet();
+    _stringLiterals = source.readStrings(emptyAsNull: true).toSet();
+    _boolLiterals =
+        source.readList(() => source.readBool(), emptyAsNull: true).toSet();
+    _doubleLiterals = source
+        .readList(() => source.readDoubleValue(), emptyAsNull: true)
+        .toSet();
+    _intLiterals = source
+        .readList(() => source.readIntegerValue(), emptyAsNull: true)
+        .toSet();
     _runtimeTypeUses = source.readList(
         () => new _RuntimeTypeUse.fromDataSource(source),
         emptyAsNull: true);
diff --git a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
index d7e1d75..b62aafc 100644
--- a/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
+++ b/pkg/compiler/lib/src/ir/runtime_type_analysis.dart
@@ -84,7 +84,7 @@
 
   /// Returns `true` if [node] is of the form `e.runtimeType`.
   bool isGetRuntimeType(ir.TreeNode node) {
-    return node is ir.PropertyGet && node.name.name == Identifiers.runtimeType_;
+    return node is ir.PropertyGet && node.name.text == Identifiers.runtimeType_;
   }
 
   /// Returns [node] if [node] is of the form `e.runtimeType` and `null`
@@ -95,7 +95,7 @@
 
   /// Returns `true` if [node] is of the form `e.toString()`.
   bool isInvokeToString(ir.TreeNode node) {
-    return node is ir.MethodInvocation && node.name.name == 'toString';
+    return node is ir.MethodInvocation && node.name.text == 'toString';
   }
 
   assert(isGetRuntimeType(node));
@@ -141,7 +141,7 @@
       } else if (nullAware.parent is ir.MethodInvocation) {
         ir.MethodInvocation methodInvocation = nullAware.parent;
         if (methodInvocation.receiver == nullAware.let &&
-            methodInvocation.name.name == '==') {
+            methodInvocation.name.text == '==') {
           // Detected
           //
           //  e0?.runtimeType == other
@@ -202,7 +202,7 @@
       } else if (nullAware.parent is ir.Arguments &&
           nullAware.parent.parent is ir.MethodInvocation) {
         ir.MethodInvocation methodInvocation = nullAware.parent.parent;
-        if (methodInvocation.name.name == '==' &&
+        if (methodInvocation.name.text == '==' &&
             methodInvocation.arguments.positional.first == nullAware.let) {
           // [nullAware] is the right hand side of ==.
 
@@ -290,7 +290,7 @@
     }
   } else if (node.parent is ir.MethodInvocation) {
     ir.MethodInvocation methodInvocation = node.parent;
-    if (methodInvocation.name.name == '==' &&
+    if (methodInvocation.name.text == '==' &&
         methodInvocation.receiver == node) {
       // [node] is the left hand side of ==.
 
@@ -340,7 +340,7 @@
   } else if (node.parent is ir.Arguments &&
       node.parent.parent is ir.MethodInvocation) {
     ir.MethodInvocation methodInvocation = node.parent.parent;
-    if (methodInvocation.name.name == '==' &&
+    if (methodInvocation.name.text == '==' &&
         methodInvocation.arguments.positional.first == node) {
       // [node] is the right hand side of ==.
       ir.PropertyGet otherGetRuntimeType =
diff --git a/pkg/compiler/lib/src/ir/scope.dart b/pkg/compiler/lib/src/ir/scope.dart
index 2a9cee6..90bc23a 100644
--- a/pkg/compiler/lib/src/ir/scope.dart
+++ b/pkg/compiler/lib/src/ir/scope.dart
@@ -10,7 +10,7 @@
 class ScopeModel {
   final ClosureScopeModel closureScopeModel;
   final VariableScopeModel variableScopeModel;
-  final InitializerComplexity initializerComplexity;
+  final EvaluationComplexity initializerComplexity;
 
   const ScopeModel(
       {this.closureScopeModel,
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 7ef94b7..74ac0b9 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -6,6 +6,7 @@
 import 'package:kernel/type_environment.dart' as ir;
 import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
 
+import '../ir/constants.dart';
 import 'closure.dart';
 import 'scope.dart';
 
@@ -13,9 +14,9 @@
 /// assigned/captured/free at various points to build a [ClosureScopeModel] and
 /// a [VariableScopeModel] that can respond to queries about how a particular
 /// variable is being used at any point in the code.
-class ScopeModelBuilder extends ir.Visitor<InitializerComplexity>
+class ScopeModelBuilder extends ir.Visitor<EvaluationComplexity>
     with VariableCollectorMixin {
-  final ir.ConstantEvaluator _constantEvaluator;
+  final Dart2jsConstantEvaluator _constantEvaluator;
   ir.StaticTypeContext _staticTypeContext;
 
   final ClosureScopeModel _model = new ClosureScopeModel();
@@ -84,7 +85,7 @@
   ScopeModel computeModel(ir.Member node) {
     if (node.isAbstract && !node.isExternal) {
       return const ScopeModel(
-          initializerComplexity: const InitializerComplexity.lazy());
+          initializerComplexity: const EvaluationComplexity.lazy());
     }
 
     _staticTypeContext =
@@ -99,13 +100,13 @@
       _hasThisLocal = false;
     }
 
-    InitializerComplexity initializerComplexity =
-        const InitializerComplexity.lazy();
+    EvaluationComplexity initializerComplexity =
+        const EvaluationComplexity.lazy();
     if (node is ir.Field) {
       if (node.initializer != null) {
         initializerComplexity = node.accept(this);
       } else {
-        initializerComplexity = const InitializerComplexity.constant();
+        initializerComplexity = const EvaluationComplexity.constant();
         _model.scopeInfo = new KernelScopeInfo(_hasThisLocal);
       }
     } else {
@@ -119,21 +120,91 @@
   }
 
   @override
-  InitializerComplexity defaultNode(ir.Node node) =>
+  EvaluationComplexity defaultNode(ir.Node node) =>
       throw UnsupportedError('Unhandled node $node (${node.runtimeType})');
 
-  InitializerComplexity visitNode(ir.Node node) {
+  EvaluationComplexity visitNode(ir.Node node) {
     return node?.accept(this);
   }
 
-  InitializerComplexity visitNodes(List<ir.Node> nodes) {
-    InitializerComplexity complexity = const InitializerComplexity.constant();
+  /// Tries to evaluate [node] as a constant expression.
+  ///
+  /// If [node] it succeeds, an [EvaluationComplexity] containing the new
+  /// constant is returned. Otherwise a 'lazy' [EvaluationComplexity] is
+  /// returned, signaling that [node] is not a constant expression.
+  ///
+  /// This method should be called in the visit methods of all expressions that
+  /// could potentially be constant to bubble up the constness of expressions.
+  ///
+  /// For instance in `var a = 1 + 2` [visitIntLiteral] calls this method
+  /// for `1` and `2` to convert these from int literals to int constants, and
+  /// [visitMethodInvocation] call this method, when seeing that all of its
+  /// subexpressions are constant, and it itself therefore is potentially
+  /// constant, thus computing that `1 + 2` can be replaced by the int constant
+  /// `3`.
+  ///
+  /// Note that [node] is _not_ replaced with a new constant expression. It is
+  /// the responsibility of the caller to do so. This is needed for performance
+  /// reasons since calling `TreeNode.replaceChild` searches linearly through
+  /// the children of the parent node, which lead to a O(n^2) complexity that
+  /// is severe and observable for instance for large list literals.
+  EvaluationComplexity _evaluateImplicitConstant(ir.Expression node) {
+    ir.Constant constant = _constantEvaluator.evaluate(_staticTypeContext, node,
+        requireConstant: false, replaceImplicitConstant: false);
+    if (constant != null) {
+      return new EvaluationComplexity.constant(constant);
+    }
+    return const EvaluationComplexity.lazy();
+  }
+
+  /// The evaluation complexity of the last visited expression.
+  EvaluationComplexity _lastExpressionComplexity;
+
+  /// Visit [node] and returns the corresponding `ConstantExpression` if [node]
+  /// evaluated to a constant.
+  ///
+  /// This method stores the complexity of [node] in [_lastExpressionComplexity]
+  /// and sets the parent of the created `ConstantExpression` to the parent
+  /// of [node]. The caller must replace [node] within the parent node. This
+  /// is done to avoid calling `Node.replaceChild` which searches linearly
+  /// through the children nodes `node.parent` in order to replace `node` which
+  /// results in O(n^2) complexity of replacing elements in for instance a list
+  /// of `n` elements.
+  ir.Expression _handleExpression(ir.Expression node) {
+    _lastExpressionComplexity = visitNode(node);
+    if (_lastExpressionComplexity.isFreshConstant) {
+      return new ir.ConstantExpression(_lastExpressionComplexity.constant,
+          node.getStaticType(_staticTypeContext))
+        ..fileOffset = node.fileOffset
+        ..parent = node.parent;
+    }
+    return node;
+  }
+
+  /// Visit all [nodes] returning the combined complexity.
+  EvaluationComplexity visitNodes(List<ir.Node> nodes) {
+    EvaluationComplexity complexity = const EvaluationComplexity.constant();
     for (ir.Node node in nodes) {
       complexity = complexity.combine(visitNode(node));
     }
     return complexity;
   }
 
+  /// Visit all [nodes] returning the combined complexity.
+  ///
+  /// If subexpressions can be evaluated as constants, they are replaced by
+  /// constant expressions in [nodes].
+  EvaluationComplexity visitExpressions(List<ir.Expression> nodes) {
+    EvaluationComplexity combinedComplexity =
+        const EvaluationComplexity.constant();
+    for (int i = 0; i < nodes.length; i++) {
+      nodes[i] = _handleExpression(nodes[i]);
+      combinedComplexity =
+          combinedComplexity.combine(_lastExpressionComplexity);
+    }
+    return combinedComplexity;
+  }
+
   /// Update the [CapturedScope] object corresponding to
   /// this node if any variables are captured.
   void attachCapturedScopeVariables(ir.TreeNode node) {
@@ -211,12 +282,13 @@
   }
 
   @override
-  InitializerComplexity visitNamedExpression(ir.NamedExpression node) {
-    return visitNode(node.value);
+  EvaluationComplexity visitNamedExpression(ir.NamedExpression node) {
+    throw UnsupportedError(
+        'NamedExpression should be handled through visitArguments');
   }
 
   @override
-  InitializerComplexity visitTryCatch(ir.TryCatch node) {
+  EvaluationComplexity visitTryCatch(ir.TryCatch node) {
     bool oldInTry = _inTry;
     _inTry = true;
     visitInVariableScope(node, () {
@@ -224,11 +296,11 @@
     });
     visitNodes(node.catches);
     _inTry = oldInTry;
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitTryFinally(ir.TryFinally node) {
+  EvaluationComplexity visitTryFinally(ir.TryFinally node) {
     bool oldInTry = _inTry;
     _inTry = true;
     visitInVariableScope(node, () {
@@ -236,24 +308,24 @@
     });
     visitNode(node.finalizer);
     _inTry = oldInTry;
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitVariableGet(ir.VariableGet node) {
+  EvaluationComplexity visitVariableGet(ir.VariableGet node) {
     _markVariableAsUsed(node.variable, VariableUse.explicit);
     // Don't visit `node.promotedType`.
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitVariableSet(ir.VariableSet node) {
+  EvaluationComplexity visitVariableSet(ir.VariableSet node) {
     _mutatedVariables.add(node.variable);
     _markVariableAsUsed(node.variable, VariableUse.explicit);
     visitInContext(node.variable.type, VariableUse.localType);
-    visitNode(node.value);
+    node.value = _handleExpression(node.value);
     registerAssignedVariable(node.variable);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   void _handleVariableDeclaration(
@@ -263,13 +335,15 @@
     }
 
     visitInContext(node.type, usage);
-    visitNode(node.initializer);
+    if (node.initializer != null) {
+      node.initializer = _handleExpression(node.initializer);
+    }
   }
 
   @override
-  InitializerComplexity visitVariableDeclaration(ir.VariableDeclaration node) {
+  EvaluationComplexity visitVariableDeclaration(ir.VariableDeclaration node) {
     _handleVariableDeclaration(node, VariableUse.localType);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   /// Add this variable to the set of free variables if appropriate and add to
@@ -304,15 +378,15 @@
   }
 
   @override
-  InitializerComplexity visitThisExpression(ir.ThisExpression thisExpression) {
+  EvaluationComplexity visitThisExpression(ir.ThisExpression thisExpression) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
     }
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitTypeParameter(ir.TypeParameter typeParameter) {
+  EvaluationComplexity visitTypeParameter(ir.TypeParameter typeParameter) {
     TypeVariableTypeWithContext typeVariable(ir.Library library) =>
         new TypeVariableTypeWithContext(
             ir.TypeParameterType.withDefaultNullabilityForLibrary(
@@ -348,7 +422,7 @@
 
     visitNode(typeParameter.bound);
 
-    return const InitializerComplexity.constant();
+    return const EvaluationComplexity.constant();
   }
 
   /// Add `this` as a variable that needs to be accessed (and thus may become a
@@ -367,7 +441,7 @@
   }
 
   @override
-  InitializerComplexity visitForInStatement(ir.ForInStatement node) {
+  EvaluationComplexity visitForInStatement(ir.ForInStatement node) {
     // We need to set `inTry` to true if this is an async for-in because we
     // desugar it into a try-finally in the SSA phase.
     bool oldInTry = _inTry;
@@ -377,40 +451,40 @@
     enterNewScope(node, () {
       visitNode(node.variable);
       visitInVariableScope(node, () {
-        visitNode(node.iterable);
+        node.iterable = _handleExpression(node.iterable);
         visitNode(node.body);
       });
     });
     if (node.isAsync) {
       _inTry = oldInTry;
     }
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitWhileStatement(ir.WhileStatement node) {
+  EvaluationComplexity visitWhileStatement(ir.WhileStatement node) {
     enterNewScope(node, () {
       visitInVariableScope(node, () {
-        visitNode(node.condition);
+        node.condition = _handleExpression(node.condition);
         visitNode(node.body);
       });
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitDoStatement(ir.DoStatement node) {
+  EvaluationComplexity visitDoStatement(ir.DoStatement node) {
     enterNewScope(node, () {
       visitInVariableScope(node, () {
         visitNode(node.body);
-        visitNode(node.condition);
+        node.condition = _handleExpression(node.condition);
       });
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitForStatement(ir.ForStatement node) {
+  EvaluationComplexity visitForStatement(ir.ForStatement node) {
     List<ir.VariableDeclaration> boxedLoopVariables =
         <ir.VariableDeclaration>[];
     enterNewScope(node, () {
@@ -418,7 +492,7 @@
       // check if a loop variable was captured in one of these subexpressions.
       visitNodes(node.variables);
       visitInVariableScope(node, () {
-        visitNodes(node.updates);
+        visitExpressions(node.updates);
       });
 
       // Loop variables that have not been captured yet can safely be flagged as
@@ -433,7 +507,9 @@
       // This must happen after the above, so any loop variables mutated in the
       // condition or body are indeed flagged as mutated.
       visitInVariableScope(node, () {
-        visitNode(node.condition);
+        if (node.condition != null) {
+          node.condition = _handleExpression(node.condition);
+        }
         visitNode(node.body);
       });
 
@@ -460,11 +536,11 @@
           scope.thisUsedAsFreeVariableIfNeedsRti,
           scope.hasThisLocal);
     }
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSuperMethodInvocation(
+  EvaluationComplexity visitSuperMethodInvocation(
       ir.SuperMethodInvocation node) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
@@ -473,26 +549,25 @@
       visitNodesInContext(node.arguments.types,
           new VariableUse.staticTypeArgument(node.interfaceTarget));
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return const InitializerComplexity.lazy();
+    visitArguments(node.arguments);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
+  EvaluationComplexity visitSuperPropertySet(ir.SuperPropertySet node) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
     }
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+    node.value = _handleExpression(node.value);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
+  EvaluationComplexity visitSuperPropertyGet(ir.SuperPropertyGet node) {
     if (_hasThisLocal) {
       _registerNeedsThis(VariableUse.explicit);
     }
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   void visitInvokable(ir.TreeNode node, void f()) {
@@ -565,170 +640,183 @@
   }
 
   @override
-  InitializerComplexity visitField(ir.Field node) {
+  EvaluationComplexity visitField(ir.Field node) {
     _currentTypeUsage = VariableUse.fieldType;
-    InitializerComplexity complexity;
+    EvaluationComplexity complexity;
     visitInvokable(node, () {
-      complexity = visitNode(node.initializer);
+      node.initializer = _handleExpression(node.initializer);
+      complexity = _lastExpressionComplexity;
     });
     _currentTypeUsage = null;
     return complexity;
   }
 
   @override
-  InitializerComplexity visitConstructor(ir.Constructor node) {
+  EvaluationComplexity visitConstructor(ir.Constructor node) {
     visitInvokable(node, () {
       visitNodes(node.initializers);
       visitNode(node.function);
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitProcedure(ir.Procedure node) {
+  EvaluationComplexity visitProcedure(ir.Procedure node) {
     visitInvokable(node, () {
       visitNode(node.function);
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitFunctionExpression(ir.FunctionExpression node) {
+  EvaluationComplexity visitFunctionExpression(ir.FunctionExpression node) {
     visitInvokable(node, () {
       visitInVariableScope(node, () {
         visitNode(node.function);
       });
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitFunctionDeclaration(ir.FunctionDeclaration node) {
+  EvaluationComplexity visitFunctionDeclaration(ir.FunctionDeclaration node) {
     visitInvokable(node, () {
       visitInVariableScope(node, () {
         visitNode(node.function);
       });
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitDynamicType(ir.DynamicType node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitDynamicType(ir.DynamicType node) =>
+      const EvaluationComplexity.constant();
 
   @override
-  InitializerComplexity visitBottomType(ir.BottomType node) =>
-      const InitializerComplexity.lazy();
+  EvaluationComplexity visitBottomType(ir.BottomType node) =>
+      const EvaluationComplexity.lazy();
 
   @override
-  InitializerComplexity visitNeverType(ir.NeverType node) =>
-      const InitializerComplexity.lazy();
+  EvaluationComplexity visitNeverType(ir.NeverType node) =>
+      const EvaluationComplexity.lazy();
 
   @override
-  InitializerComplexity visitInvalidType(ir.InvalidType node) =>
-      const InitializerComplexity.lazy();
+  EvaluationComplexity visitInvalidType(ir.InvalidType node) =>
+      const EvaluationComplexity.lazy();
 
   @override
-  InitializerComplexity visitVoidType(ir.VoidType node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitVoidType(ir.VoidType node) =>
+      const EvaluationComplexity.constant();
 
   @override
-  InitializerComplexity visitInterfaceType(ir.InterfaceType node) {
+  EvaluationComplexity visitInterfaceType(ir.InterfaceType node) {
     return visitNodes(node.typeArguments);
   }
 
   @override
-  InitializerComplexity visitFutureOrType(ir.FutureOrType node) {
+  EvaluationComplexity visitFutureOrType(ir.FutureOrType node) {
     return visitNode(node.typeArgument);
   }
 
   @override
-  InitializerComplexity visitFunctionType(ir.FunctionType node) {
-    InitializerComplexity complexity = visitNode(node.returnType);
+  EvaluationComplexity visitFunctionType(ir.FunctionType node) {
+    EvaluationComplexity complexity = visitNode(node.returnType);
     complexity = complexity.combine(visitNodes(node.positionalParameters));
     complexity = complexity.combine(visitNodes(node.namedParameters));
     return complexity.combine(visitNodes(node.typeParameters));
   }
 
   @override
-  InitializerComplexity visitNamedType(ir.NamedType node) {
+  EvaluationComplexity visitNamedType(ir.NamedType node) {
     return visitNode(node.type);
   }
 
   @override
-  InitializerComplexity visitTypeParameterType(ir.TypeParameterType node) {
+  EvaluationComplexity visitTypeParameterType(ir.TypeParameterType node) {
     _analyzeTypeVariable(node, _currentTypeUsage);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
-  InitializerComplexity visitInContext(ir.Node node, VariableUse use) {
+  EvaluationComplexity visitInContext(ir.Node node, VariableUse use) {
     VariableUse oldCurrentTypeUsage = _currentTypeUsage;
     _currentTypeUsage = use;
-    InitializerComplexity complexity = visitNode(node);
+    EvaluationComplexity complexity = visitNode(node);
     _currentTypeUsage = oldCurrentTypeUsage;
     return complexity;
   }
 
-  InitializerComplexity visitNodesInContext(
+  EvaluationComplexity visitNodesInContext(
       List<ir.Node> nodes, VariableUse use) {
     VariableUse oldCurrentTypeUsage = _currentTypeUsage;
     _currentTypeUsage = use;
-    InitializerComplexity complexity = visitNodes(nodes);
+    EvaluationComplexity complexity = visitNodes(nodes);
     _currentTypeUsage = oldCurrentTypeUsage;
     return complexity;
   }
 
   @override
-  InitializerComplexity visitTypeLiteral(ir.TypeLiteral node) {
-    return visitInContext(node.type, VariableUse.explicit);
-  }
-
-  @override
-  InitializerComplexity visitIsExpression(ir.IsExpression node) {
-    visitNode(node.operand);
+  EvaluationComplexity visitTypeLiteral(ir.TypeLiteral node) {
     visitInContext(node.type, VariableUse.explicit);
-    return const InitializerComplexity.lazy();
+    return _evaluateImplicitConstant(node);
   }
 
   @override
-  InitializerComplexity visitAsExpression(ir.AsExpression node) {
-    visitNode(node.operand);
+  EvaluationComplexity visitIsExpression(ir.IsExpression node) {
+    node.operand = _handleExpression(node.operand);
+    EvaluationComplexity complexity = _lastExpressionComplexity;
+    visitInContext(node.type, VariableUse.explicit);
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return const EvaluationComplexity.lazy();
+  }
+
+  @override
+  EvaluationComplexity visitAsExpression(ir.AsExpression node) {
+    node.operand = _handleExpression(node.operand);
+    EvaluationComplexity complexity = _lastExpressionComplexity;
     visitInContext(node.type,
         node.isTypeError ? VariableUse.implicitCast : VariableUse.explicit);
-    return const InitializerComplexity.lazy();
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitNullCheck(ir.NullCheck node) {
-    visitNode(node.operand);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitNullCheck(ir.NullCheck node) {
+    node.operand = _handleExpression(node.operand);
+    EvaluationComplexity complexity = _lastExpressionComplexity;
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitAwaitExpression(ir.AwaitExpression node) {
-    visitNode(node.operand);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitAwaitExpression(ir.AwaitExpression node) {
+    node.operand = _handleExpression(node.operand);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitYieldStatement(ir.YieldStatement node) {
-    visitNode(node.expression);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitYieldStatement(ir.YieldStatement node) {
+    node.expression = _handleExpression(node.expression);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitLoadLibrary(ir.LoadLibrary node) {
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitLoadLibrary(ir.LoadLibrary node) {
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitCheckLibraryIsLoaded(
-      ir.CheckLibraryIsLoaded node) {
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitCheckLibraryIsLoaded(ir.CheckLibraryIsLoaded node) {
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitFunctionNode(ir.FunctionNode node) {
+  EvaluationComplexity visitFunctionNode(ir.FunctionNode node) {
     VariableUse parameterUsage = node.parent is ir.Member
         ? new VariableUse.memberParameter(node.parent)
         : new VariableUse.localParameter(node.parent);
@@ -744,106 +832,116 @@
         node.parent is ir.Member
             ? new VariableUse.memberReturnType(node.parent)
             : new VariableUse.localReturnType(node.parent));
-    visitNode(node.body);
-    return const InitializerComplexity.lazy();
+    if (node.body != null) {
+      visitNode(node.body);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitListLiteral(ir.ListLiteral node) {
-    InitializerComplexity complexity =
+  EvaluationComplexity visitListLiteral(ir.ListLiteral node) {
+    EvaluationComplexity complexity =
         visitInContext(node.typeArgument, VariableUse.listLiteral);
-    complexity = complexity.combine(visitNodes(node.expressions));
+    complexity = complexity.combine(visitExpressions(node.expressions));
     if (node.isConst) {
-      return const InitializerComplexity.constant();
+      return const EvaluationComplexity.constant();
     } else {
       return complexity.makeEager();
     }
   }
 
   @override
-  InitializerComplexity visitSetLiteral(ir.SetLiteral node) {
-    InitializerComplexity complexity =
+  EvaluationComplexity visitSetLiteral(ir.SetLiteral node) {
+    EvaluationComplexity complexity =
         visitInContext(node.typeArgument, VariableUse.setLiteral);
-    complexity = complexity.combine(visitNodes(node.expressions));
+    complexity = complexity.combine(visitExpressions(node.expressions));
     if (node.isConst) {
-      return const InitializerComplexity.constant();
+      return const EvaluationComplexity.constant();
     } else {
       return complexity.makeEager();
     }
   }
 
   @override
-  InitializerComplexity visitMapLiteral(ir.MapLiteral node) {
-    InitializerComplexity complexity =
+  EvaluationComplexity visitMapLiteral(ir.MapLiteral node) {
+    EvaluationComplexity complexity =
         visitInContext(node.keyType, VariableUse.mapLiteral);
     complexity = complexity
         .combine(visitInContext(node.valueType, VariableUse.mapLiteral));
     complexity = complexity.combine(visitNodes(node.entries));
     if (node.isConst) {
-      return const InitializerComplexity.constant();
+      return const EvaluationComplexity.constant();
     } else {
       return complexity.makeEager();
     }
   }
 
   @override
-  InitializerComplexity visitMapEntry(ir.MapEntry node) {
-    InitializerComplexity complexity = visitNode(node.key);
-    return complexity.combine(visitNode(node.value));
+  EvaluationComplexity visitMapEntry(ir.MapEntry node) {
+    node.key = _handleExpression(node.key);
+    EvaluationComplexity keyComplexity = _lastExpressionComplexity;
+
+    node.value = _handleExpression(node.value);
+    EvaluationComplexity valueComplexity = _lastExpressionComplexity;
+
+    return keyComplexity.combine(valueComplexity);
   }
 
   @override
-  InitializerComplexity visitNullLiteral(ir.NullLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitNullLiteral(ir.NullLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitStringLiteral(ir.StringLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitStringLiteral(ir.StringLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitIntLiteral(ir.IntLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitIntLiteral(ir.IntLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitDoubleLiteral(ir.DoubleLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitDoubleLiteral(ir.DoubleLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitSymbolLiteral(ir.SymbolLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitSymbolLiteral(ir.SymbolLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitBoolLiteral(ir.BoolLiteral node) =>
-      const InitializerComplexity.constant();
+  EvaluationComplexity visitBoolLiteral(ir.BoolLiteral node) =>
+      _evaluateImplicitConstant(node);
 
   @override
-  InitializerComplexity visitStringConcatenation(ir.StringConcatenation node) {
-    visitNodes(node.expressions);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitStringConcatenation(ir.StringConcatenation node) {
+    EvaluationComplexity complexity = visitExpressions(node.expressions);
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return complexity;
   }
 
   @override
-  InitializerComplexity visitStaticGet(ir.StaticGet node) {
+  EvaluationComplexity visitStaticGet(ir.StaticGet node) {
     ir.Member target = node.target;
     if (target is ir.Field) {
       return target.isConst
-          ? const InitializerComplexity.constant()
-          : new InitializerComplexity.eager(fields: <ir.Field>{target});
+          ? const EvaluationComplexity.constant()
+          : new EvaluationComplexity.eager(fields: <ir.Field>{target});
     } else if (target is ir.Procedure &&
         target.kind == ir.ProcedureKind.Method) {
-      return const InitializerComplexity.constant();
+      return _evaluateImplicitConstant(node);
     }
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitStaticSet(ir.StaticSet node) {
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitStaticSet(ir.StaticSet node) {
+    node.value = _handleExpression(node.value);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitStaticInvocation(ir.StaticInvocation node) {
+  EvaluationComplexity visitStaticInvocation(ir.StaticInvocation node) {
     if (node.arguments.types.isNotEmpty) {
       VariableUse usage;
       if (node.target.kind == ir.ProcedureKind.Factory) {
@@ -854,40 +952,68 @@
 
       visitNodesInContext(node.arguments.types, usage);
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
+
+    EvaluationComplexity complexity = visitArguments(node.arguments);
+    if (complexity.isConstant &&
+        node.target ==
+            _staticTypeContext.typeEnvironment.coreTypes.identicalProcedure) {
+      return _evaluateImplicitConstant(node);
+    }
     return node.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+        ? const EvaluationComplexity.constant()
+        : const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitConstructorInvocation(
+  EvaluationComplexity visitArguments(ir.Arguments node) {
+    EvaluationComplexity combinedComplexity = visitExpressions(node.positional);
+    for (int i = 0; i < node.named.length; i++) {
+      node.named[i].value = _handleExpression(node.named[i].value);
+      combinedComplexity =
+          combinedComplexity.combine(_lastExpressionComplexity);
+    }
+    return combinedComplexity;
+  }
+
+  @override
+  EvaluationComplexity visitConstructorInvocation(
       ir.ConstructorInvocation node) {
     if (node.arguments.types.isNotEmpty) {
       visitNodesInContext(node.arguments.types,
           new VariableUse.constructorTypeArgument(node.target));
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
+    visitArguments(node.arguments);
     return node.isConst
-        ? const InitializerComplexity.constant()
-        : const InitializerComplexity.lazy();
+        ? const EvaluationComplexity.constant()
+        : const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitConditionalExpression(
+  EvaluationComplexity visitConditionalExpression(
       ir.ConditionalExpression node) {
-    InitializerComplexity complexity = visitNode(node.condition);
-    complexity = complexity.combine(visitNode(node.then));
-    return complexity.combine(visitNode(node.otherwise));
+    node.condition = _handleExpression(node.condition);
+    EvaluationComplexity conditionComplexity = _lastExpressionComplexity;
+
+    node.then = _handleExpression(node.then);
+    EvaluationComplexity thenComplexity = _lastExpressionComplexity;
+
+    node.otherwise = _handleExpression(node.otherwise);
+    EvaluationComplexity elseComplexity = _lastExpressionComplexity;
+
+    EvaluationComplexity complexity =
+        conditionComplexity.combine(thenComplexity).combine(elseComplexity);
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
     // Don't visit `node.staticType`.
+    return complexity;
   }
 
   @override
-  InitializerComplexity visitMethodInvocation(ir.MethodInvocation node) {
+  EvaluationComplexity visitMethodInvocation(ir.MethodInvocation node) {
+    node.receiver = _handleExpression(node.receiver);
+    EvaluationComplexity receiverComplexity = _lastExpressionComplexity;
     ir.TreeNode receiver = node.receiver;
-    visitNode(receiver);
     if (node.arguments.types.isNotEmpty) {
       VariableUse usage;
       if (receiver is ir.VariableGet &&
@@ -899,211 +1025,237 @@
       }
       visitNodesInContext(node.arguments.types, usage);
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    // TODO(johnniwinther): Recognize constant operations.
-    return const InitializerComplexity.lazy();
+    EvaluationComplexity complexity = visitArguments(node.arguments);
+    ir.Member interfaceTarget = node.interfaceTarget;
+    if (receiverComplexity.combine(complexity).isConstant &&
+        interfaceTarget is ir.Procedure &&
+        interfaceTarget.kind == ir.ProcedureKind.Operator) {
+      return _evaluateImplicitConstant(node);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitPropertyGet(ir.PropertyGet node) {
-    visitNode(node.receiver);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitPropertyGet(ir.PropertyGet node) {
+    node.receiver = _handleExpression(node.receiver);
+    EvaluationComplexity complexity = _lastExpressionComplexity;
+    if (complexity.isConstant && node.name.name == 'length') {
+      return _evaluateImplicitConstant(node);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitPropertySet(ir.PropertySet node) {
-    visitNode(node.receiver);
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitPropertySet(ir.PropertySet node) {
+    node.receiver = _handleExpression(node.receiver);
+    node.value = _handleExpression(node.value);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    visitNode(node.receiver);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitNot(ir.Not node) {
+    node.operand = _handleExpression(node.operand);
+    EvaluationComplexity complexity = _lastExpressionComplexity;
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return complexity;
   }
 
   @override
-  InitializerComplexity visitDirectPropertySet(ir.DirectPropertySet node) {
-    visitNode(node.receiver);
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitLogicalExpression(ir.LogicalExpression node) {
+    node.left = _handleExpression(node.left);
+    EvaluationComplexity leftComplexity = _lastExpressionComplexity;
+
+    node.right = _handleExpression(node.right);
+    EvaluationComplexity rightComplexity = _lastExpressionComplexity;
+
+    EvaluationComplexity complexity = leftComplexity.combine(rightComplexity);
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return complexity;
   }
 
   @override
-  InitializerComplexity visitNot(ir.Not node) {
-    return visitNode(node.operand);
-  }
-
-  @override
-  InitializerComplexity visitLogicalExpression(ir.LogicalExpression node) {
-    InitializerComplexity complexity = visitNode(node.left);
-    return complexity.combine(visitNode(node.right));
-  }
-
-  @override
-  InitializerComplexity visitLet(ir.Let node) {
+  EvaluationComplexity visitLet(ir.Let node) {
     visitNode(node.variable);
-    visitNode(node.body);
-    return const InitializerComplexity.lazy();
+    node.body = _handleExpression(node.body);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitBlockExpression(ir.BlockExpression node) {
+  EvaluationComplexity visitBlockExpression(ir.BlockExpression node) {
     visitNode(node.body);
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+    node.value = _handleExpression(node.value);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitCatch(ir.Catch node) {
+  EvaluationComplexity visitCatch(ir.Catch node) {
     visitInContext(node.guard, VariableUse.explicit);
-    visitNode(node.exception);
-    visitNode(node.stackTrace);
+    if (node.exception != null) {
+      visitNode(node.exception);
+    }
+    if (node.stackTrace != null) {
+      visitNode(node.stackTrace);
+    }
     visitInVariableScope(node, () {
       visitNode(node.body);
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitInstantiation(ir.Instantiation node) {
-    InitializerComplexity complexity = visitNodesInContext(
+  EvaluationComplexity visitInstantiation(ir.Instantiation node) {
+    EvaluationComplexity typeArgumentsComplexity = visitNodesInContext(
         node.typeArguments, new VariableUse.instantiationTypeArgument(node));
-    return complexity.combine(visitNode(node.expression));
+    node.expression = _handleExpression(node.expression);
+    EvaluationComplexity expressionComplexity = _lastExpressionComplexity;
+
+    EvaluationComplexity complexity =
+        typeArgumentsComplexity.combine(expressionComplexity);
+    if (complexity.isConstant) {
+      return _evaluateImplicitConstant(node);
+    }
+    return complexity;
   }
 
   @override
-  InitializerComplexity visitThrow(ir.Throw node) {
-    visitNode(node.expression);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitThrow(ir.Throw node) {
+    node.expression = _handleExpression(node.expression);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitRethrow(ir.Rethrow node) =>
-      const InitializerComplexity.lazy();
+  EvaluationComplexity visitRethrow(ir.Rethrow node) =>
+      const EvaluationComplexity.lazy();
 
   @override
-  InitializerComplexity visitBlock(ir.Block node) {
+  EvaluationComplexity visitBlock(ir.Block node) {
     visitNodes(node.statements);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitAssertStatement(ir.AssertStatement node) {
+  EvaluationComplexity visitAssertStatement(ir.AssertStatement node) {
     visitInVariableScope(node, () {
-      visitNode(node.condition);
-      visitNode(node.message);
+      node.condition = _handleExpression(node.condition);
+      if (node.message != null) {
+        node.message = _handleExpression(node.message);
+      }
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitReturnStatement(ir.ReturnStatement node) {
-    visitNode(node.expression);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitReturnStatement(ir.ReturnStatement node) {
+    if (node.expression != null) {
+      node.expression = _handleExpression(node.expression);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitEmptyStatement(ir.EmptyStatement node) {
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitEmptyStatement(ir.EmptyStatement node) {
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitExpressionStatement(ir.ExpressionStatement node) {
-    visitNode(node.expression);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitExpressionStatement(ir.ExpressionStatement node) {
+    node.expression = _handleExpression(node.expression);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSwitchStatement(ir.SwitchStatement node) {
-    visitNode(node.expression);
+  EvaluationComplexity visitSwitchStatement(ir.SwitchStatement node) {
+    node.expression = _handleExpression(node.expression);
     visitInVariableScope(node, () {
       visitNodes(node.cases);
     });
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSwitchCase(ir.SwitchCase node) {
+  EvaluationComplexity visitSwitchCase(ir.SwitchCase node) {
     visitNode(node.body);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitContinueSwitchStatement(
+  EvaluationComplexity visitContinueSwitchStatement(
       ir.ContinueSwitchStatement node) {
     registerContinueSwitch();
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitBreakStatement(ir.BreakStatement node) {
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitBreakStatement(ir.BreakStatement node) {
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitLabeledStatement(ir.LabeledStatement node) {
+  EvaluationComplexity visitLabeledStatement(ir.LabeledStatement node) {
     visitNode(node.body);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitFieldInitializer(ir.FieldInitializer node) {
-    visitNode(node.value);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitFieldInitializer(ir.FieldInitializer node) {
+    node.value = _handleExpression(node.value);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitLocalInitializer(ir.LocalInitializer node) {
-    visitNode(node.variable.initializer);
-    return const InitializerComplexity.lazy();
+  EvaluationComplexity visitLocalInitializer(ir.LocalInitializer node) {
+    node.variable.initializer = _handleExpression(node.variable.initializer);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitSuperInitializer(ir.SuperInitializer node) {
+  EvaluationComplexity visitSuperInitializer(ir.SuperInitializer node) {
     if (node.arguments.types.isNotEmpty) {
       visitNodesInContext(node.arguments.types,
           new VariableUse.constructorTypeArgument(node.target));
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return const InitializerComplexity.lazy();
+    visitArguments(node.arguments);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitRedirectingInitializer(
+  EvaluationComplexity visitRedirectingInitializer(
       ir.RedirectingInitializer node) {
     if (node.arguments.types.isNotEmpty) {
       visitNodesInContext(node.arguments.types,
           new VariableUse.constructorTypeArgument(node.target));
     }
-    visitNodes(node.arguments.positional);
-    visitNodes(node.arguments.named);
-    return const InitializerComplexity.lazy();
+    visitArguments(node.arguments);
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitAssertInitializer(ir.AssertInitializer node) {
+  EvaluationComplexity visitAssertInitializer(ir.AssertInitializer node) {
     visitNode(node.statement);
-    return const InitializerComplexity.lazy();
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitIfStatement(ir.IfStatement node) {
-    visitNode(node.condition);
+  EvaluationComplexity visitIfStatement(ir.IfStatement node) {
+    EvaluationComplexity conditionComplexity = visitNode(node.condition);
+    if (conditionComplexity.isFreshConstant) {}
     visitNode(node.then);
-    visitNode(node.otherwise);
-    return const InitializerComplexity.lazy();
+    if (node.otherwise != null) {
+      visitNode(node.otherwise);
+    }
+    return const EvaluationComplexity.lazy();
   }
 
   @override
-  InitializerComplexity visitConstantExpression(ir.ConstantExpression node) {
+  EvaluationComplexity visitConstantExpression(ir.ConstantExpression node) {
     if (node.constant is ir.UnevaluatedConstant) {
       node.constant = _constantEvaluator.evaluate(_staticTypeContext, node);
     }
-    return const InitializerComplexity.constant();
+    return const EvaluationComplexity.constant();
   }
 
   /// Returns true if the node is a field, or a constructor (factory or
@@ -1156,30 +1308,31 @@
   definitelyLazy,
 }
 
-class InitializerComplexity {
+class EvaluationComplexity {
   final ComplexityLevel level;
   final Set<ir.Field> fields;
+  final ir.Constant constant;
 
-  // TODO(johnniwinther): This should hold the constant literal from CFE when
-  // provided.
-  const InitializerComplexity.constant()
+  const EvaluationComplexity.constant([this.constant])
       : level = ComplexityLevel.constant,
         fields = null;
 
   // TODO(johnniwinther): Use this to collect data on the size of the
   //  initializer.
-  InitializerComplexity.eager({this.fields})
-      : level = ComplexityLevel.potentiallyEager;
+  EvaluationComplexity.eager({this.fields})
+      : level = ComplexityLevel.potentiallyEager,
+        constant = null;
 
-  const InitializerComplexity.lazy()
+  const EvaluationComplexity.lazy()
       : level = ComplexityLevel.definitelyLazy,
-        fields = null;
+        fields = null,
+        constant = null;
 
-  InitializerComplexity combine(InitializerComplexity other) {
+  EvaluationComplexity combine(EvaluationComplexity other) {
     if (identical(this, other)) {
       return this;
     } else if (isLazy || other.isLazy) {
-      return const InitializerComplexity.lazy();
+      return const EvaluationComplexity.lazy();
     } else if (isEager || other.isEager) {
       if (fields != null && other.fields != null) {
         fields.addAll(other.fields);
@@ -1190,9 +1343,7 @@
         return other;
       }
     } else if (isConstant && other.isConstant) {
-      // TODO(johnniwinther): This is case doesn't work if InitializerComplexity
-      // objects of constant complexity hold the constant literal.
-      return this;
+      return const EvaluationComplexity.constant();
     } else if (isEager) {
       assert(other.isConstant);
       return this;
@@ -1203,16 +1354,18 @@
     }
   }
 
-  InitializerComplexity makeEager() {
+  EvaluationComplexity makeEager() {
     if (isLazy || isEager) {
       return this;
     } else {
-      return new InitializerComplexity.eager();
+      return new EvaluationComplexity.eager();
     }
   }
 
   bool get isConstant => level == ComplexityLevel.constant;
 
+  bool get isFreshConstant => isConstant && constant != null;
+
   bool get isEager => level == ComplexityLevel.potentiallyEager;
 
   bool get isLazy => level == ComplexityLevel.definitelyLazy;
@@ -1228,7 +1381,7 @@
         sb.write('eager');
         if (fields != null) {
           sb.write('&fields=[');
-          List<String> names = fields.map((f) => f.name.name).toList()..sort();
+          List<String> names = fields.map((f) => f.name.text).toList()..sort();
           sb.write(names.join(','));
           sb.write(']');
         }
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 33079f9..4472ff8 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -13,6 +13,7 @@
 import 'scope.dart';
 import 'static_type_base.dart';
 import 'static_type_cache.dart';
+import 'util.dart';
 
 /// Enum values for how the target of a static type should be interpreted.
 enum ClassRelation {
@@ -233,7 +234,7 @@
           .substituteType(interfaceTarget.getterType);
     }
     // Treat the properties of Object specially.
-    String nameString = node.name.name;
+    String nameString = node.name.text;
     if (nameString == 'hashCode') {
       return typeEnvironment.coreTypes.intNonNullableRawType;
     } else if (nameString == 'runtimeType') {
@@ -255,7 +256,7 @@
         _computePropertyGetType(node, receiverType);
     receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
     handlePropertyGet(node, receiverType, resultType);
-    if (node.name.name == Identifiers.runtimeType_) {
+    if (node.name.text == Identifiers.runtimeType_) {
       RuntimeTypeUseData data =
           computeRuntimeTypeUse(_pendingRuntimeTypeUseData, node);
       if (data.leftRuntimeTypeExpression == node) {
@@ -324,61 +325,6 @@
     return valueType;
   }
 
-  void handleDirectPropertyGet(ir.DirectPropertyGet node,
-      ir.DartType receiverType, ir.DartType resultType) {}
-
-  @override
-  ir.DartType visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.Class superclass = node.target.enclosingClass;
-    receiverType = getTypeAsInstanceOf(receiverType, superclass);
-    ir.DartType resultType = ir.Substitution.fromInterfaceType(receiverType)
-        .substituteType(node.target.getterType);
-    _expressionTypeCache[node] = resultType;
-    handleDirectPropertyGet(node, receiverType, resultType);
-    return resultType;
-  }
-
-  void handleDirectMethodInvocation(
-      ir.DirectMethodInvocation node,
-      ir.DartType receiverType,
-      ArgumentTypes argumentTypes,
-      ir.DartType returnType) {}
-
-  @override
-  ir.DartType visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ArgumentTypes argumentTypes = _visitArguments(node.arguments);
-    ir.DartType returnType;
-    if (typeEnvironment.isSpecialCasedBinaryOperator(node.target)) {
-      ir.DartType argumentType = argumentTypes.positional[0];
-      returnType = typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
-          receiverType, argumentType);
-    } else {
-      ir.Class superclass = node.target.enclosingClass;
-      receiverType = getTypeAsInstanceOf(receiverType, superclass);
-      ir.DartType returnType = ir.Substitution.fromInterfaceType(receiverType)
-          .substituteType(node.target.function.returnType);
-      returnType = ir.Substitution.fromPairs(
-              node.target.function.typeParameters, node.arguments.types)
-          .substituteType(returnType);
-    }
-    _expressionTypeCache[node] = returnType;
-    handleDirectMethodInvocation(node, receiverType, argumentTypes, returnType);
-    return returnType;
-  }
-
-  void handleDirectPropertySet(ir.DirectPropertySet node,
-      ir.DartType receiverType, ir.DartType valueType) {}
-
-  @override
-  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
-    ir.DartType receiverType = visitNode(node.receiver);
-    ir.DartType valueType = super.visitDirectPropertySet(node);
-    handleDirectPropertySet(node, receiverType, valueType);
-    return valueType;
-  }
-
   /// Returns `true` if [interfaceTarget] is an arithmetic operator whose result
   /// type is computed using both the receiver type and the argument type.
   ///
@@ -391,7 +337,7 @@
 
   ir.Member _getMember(ir.Class cls, String name) {
     for (ir.Member member in cls.members) {
-      if (member.name.name == name) return member;
+      if (member.name.text == name) return member;
     }
     throw fail("Member '$name' not found in $cls");
   }
@@ -599,7 +545,7 @@
     // TODO(34602): Remove when `interfaceTarget` is set on synthetic calls to
     // ==.
     if (interfaceTarget == null &&
-        node.name.name == '==' &&
+        node.name.text == '==' &&
         node.arguments.types.isEmpty &&
         node.arguments.positional.length == 1 &&
         node.arguments.named.isEmpty) {
@@ -647,7 +593,7 @@
         return const ir.DynamicType();
       }
     }
-    if (node.name.name == 'call') {
+    if (node.name.text == 'call') {
       if (receiverType is ir.FunctionType) {
         if (receiverType.typeParameters.length != node.arguments.types.length) {
           return const DoesNotCompleteType();
@@ -657,7 +603,7 @@
             .substituteType(receiverType.returnType);
       }
     }
-    if (node.name.name == '==') {
+    if (node.name.text == '==') {
       // We use this special case to simplify generation of '==' checks.
       return typeEnvironment.coreTypes.boolNonNullableRawType;
     }
@@ -701,12 +647,12 @@
     ir.DartType returnType =
         _computeMethodInvocationType(node, receiverType, argumentTypes);
     receiverType = _narrowInstanceReceiver(node.interfaceTarget, receiverType);
-    if (node.name.name == '==') {
+    if (node.name.text == '==') {
       ir.Expression left = node.receiver;
       ir.Expression right = node.arguments.positional[0];
       TypeMap afterInvocation = typeMap;
       if (left is ir.VariableGet &&
-          right is ir.NullLiteral &&
+          isNullLiteral(right) &&
           !_invalidatedVariables.contains(left.variable)) {
         // If `left == null` is true, we promote the type of the variable to
         // `Null` by registering that is known _not_ to be of its declared type.
@@ -716,7 +662,7 @@
             .promote(left.variable, left.variable.type, isTrue: true);
       }
       if (right is ir.VariableGet &&
-          left is ir.NullLiteral &&
+          isNullLiteral(left) &&
           !_invalidatedVariables.contains(right.variable)) {
         // If `null == right` is true, we promote the type of the variable to
         // `Null` by registering that is known _not_ to be of its declared type.
@@ -878,7 +824,7 @@
 
   @override
   ir.DartType visitLogicalExpression(ir.LogicalExpression node) {
-    if (node.operator == '&&') {
+    if (node.operatorEnum == ir.LogicalExpressionOperator.AND) {
       visitNode(node.left);
       TypeMap afterLeftWhenTrue = typeMapWhenTrue;
       TypeMap afterLeftWhenFalse = typeMapWhenFalse;
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index b62c4c9..a19523e 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -164,11 +164,6 @@
   }
 
   @override
-  ir.DartType visitDirectPropertySet(ir.DirectPropertySet node) {
-    return visitNode(node.value);
-  }
-
-  @override
   ThisInterfaceType visitThisExpression(ir.ThisExpression node) => thisType;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/types.dart b/pkg/compiler/lib/src/ir/types.dart
index a43e4fe..2d2d603 100644
--- a/pkg/compiler/lib/src/ir/types.dart
+++ b/pkg/compiler/lib/src/ir/types.dart
@@ -17,8 +17,6 @@
   KernelDartTypes(this.elementMap, this._options);
 
   @override
-  bool get useNullSafety => _options.useNullSafety;
-  @override
   bool get useLegacySubtyping => _options.useLegacySubtyping;
 
   @override
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index 7132491..15d7550 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -83,6 +83,12 @@
   }
 }
 
+/// Returns `true` if [node] is a null literal or a null constant.
+bool isNullLiteral(ir.Expression node) {
+  return node is ir.NullLiteral ||
+      (node is ir.ConstantExpression && node.constant is ir.NullConstant);
+}
+
 /// Kernel encodes a null-aware expression `a?.b` as
 ///
 ///     let final #1 = a in #1 == null ? null : #1.b
@@ -117,13 +123,13 @@
         node.variable.isFinal &&
         body is ir.ConditionalExpression &&
         body.condition is ir.MethodInvocation &&
-        body.then is ir.NullLiteral) {
+        isNullLiteral(body.then)) {
       ir.MethodInvocation invocation = body.condition;
       ir.Expression receiver = invocation.receiver;
-      if (invocation.name.name == '==' &&
+      if (invocation.name.text == '==' &&
           receiver is ir.VariableGet &&
           receiver.variable == node.variable &&
-          invocation.arguments.positional.single is ir.NullLiteral) {
+          isNullLiteral(invocation.arguments.positional.single)) {
         // We have
         //   let #t1 = e0 in #t1 == null ? null : e1
         return new NullAwareExpression(node.variable, body.otherwise);
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index bd1929e..e4a2425 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -13,7 +13,6 @@
 import '../elements/entities.dart';
 import '../elements/types.dart';
 import '../ir/element_map.dart';
-import '../options.dart';
 
 /// Visitor that converts string literals and concatenations of string literals
 /// into the string value.
@@ -44,18 +43,16 @@
 
 /// Visitor that converts kernel dart types into [DartType].
 class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
-  final CompilerOptions _options;
   final IrToElementMap elementMap;
   final Map<ir.TypeParameter, DartType> currentFunctionTypeParameters =
       <ir.TypeParameter, DartType>{};
   bool topLevel = true;
 
-  DartTypeConverter(this._options, this.elementMap);
+  DartTypeConverter(this.elementMap);
 
   DartTypes get _dartTypes => elementMap.commonElements.dartTypes;
 
   DartType _convertNullability(DartType baseType, ir.Nullability nullability) {
-    if (!_options.useNullSafety) return baseType;
     switch (nullability) {
       case ir.Nullability.nullable:
         return _dartTypes.nullableType(baseType);
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index cbb0bdd..5f63cfb 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -402,8 +402,10 @@
   BackendImpact _lazyField;
 
   BackendImpact get lazyField {
-    return _lazyField ??=
-        new BackendImpact(staticUses: [_commonElements.cyclicThrowHelper]);
+    return _lazyField ??= new BackendImpact(staticUses: [
+      _commonElements.cyclicThrowHelper,
+      _commonElements.throwLateInitializationError
+    ]);
   }
 
   BackendImpact _typeLiteral;
@@ -766,11 +768,9 @@
         _commonElements.installSpecializedIsTest,
         _commonElements.generalIsTestImplementation,
         _commonElements.generalAsCheckImplementation,
-        if (_options.useNullSafety) ...[
-          _commonElements.installSpecializedAsCheck,
-          _commonElements.generalNullableIsTestImplementation,
-          _commonElements.generalNullableAsCheckImplementation,
-        ],
+        _commonElements.installSpecializedAsCheck,
+        _commonElements.generalNullableIsTestImplementation,
+        _commonElements.generalNullableAsCheckImplementation,
         // Specialized checks.
         _commonElements.specializedIsBool,
         _commonElements.specializedAsBool,
diff --git a/pkg/compiler/lib/src/js_backend/field_analysis.dart b/pkg/compiler/lib/src/js_backend/field_analysis.dart
index a40b882..ac07284 100644
--- a/pkg/compiler/lib/src/js_backend/field_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/field_analysis.dart
@@ -124,7 +124,7 @@
     _classData[class_] = new ClassData(constructors, fieldData);
   }
 
-  void registerStaticField(KField field, InitializerComplexity complexity) {
+  void registerStaticField(KField field, EvaluationComplexity complexity) {
     ir.Field node = _elementMap.getMemberNode(field);
     ir.Expression expression = node.initializer;
     ConstantValue value = _elementMap.getConstantValue(
@@ -156,7 +156,7 @@
 
 class StaticFieldData {
   final ConstantValue initialValue;
-  final InitializerComplexity complexity;
+  final EvaluationComplexity complexity;
 
   StaticFieldData(this.initialValue, this.complexity);
 
@@ -468,7 +468,7 @@
           if (!isEager) {
             // The field might be eager depending on the initializer complexity
             // and its dependencies.
-            InitializerComplexity complexity = staticFieldData.complexity;
+            EvaluationComplexity complexity = staticFieldData.complexity;
             isEager = complexity?.isEager ?? false;
             if (isEager && complexity.fields != null) {
               for (ir.Field node in complexity.fields) {
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index ed37f59..474f127 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -18,6 +18,7 @@
 import '../js_emitter/native_emitter.dart';
 import '../native/enqueue.dart';
 import '../native/behavior.dart';
+import '../universe/call_structure.dart';
 import '../universe/feature.dart';
 import '../universe/selector.dart';
 import '../universe/use.dart';
@@ -411,6 +412,14 @@
 
     for (ConstantUse constantUse in impact.constantUses) {
       switch (constantUse.value.kind) {
+        case ConstantValueKind.SET:
+        case ConstantValueKind.MAP:
+        case ConstantValueKind.CONSTRUCTED:
+        case ConstantValueKind.INSTANTIATION:
+        case ConstantValueKind.LIST:
+          transformed.registerStaticUse(StaticUse.staticInvoke(
+              _closedWorld.commonElements.findType, CallStructure.ONE_ARG));
+          break;
         case ConstantValueKind.DEFERRED_GLOBAL:
           _closedWorld.outputUnitData
               .registerConstantDeferredUse(constantUse.value);
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
index 1ab31fc..bac69a0 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/collector.dart
@@ -9,7 +9,6 @@
 ///
 /// The code for the containing (used) methods must exist in the `universe`.
 class Collector {
-  final CompilerOptions _options;
   final JCommonElements _commonElements;
   final JElementEnvironment _elementEnvironment;
   final OutputUnitData _outputUnitData;
@@ -43,7 +42,6 @@
   final List<ClassEntity> nativeClassesAndSubclasses = [];
 
   Collector(
-      this._options,
       this._commonElements,
       this._elementEnvironment,
       this._outputUnitData,
@@ -105,7 +103,7 @@
   // Return the classes that are just helpers for the backend's type system.
   static Iterable<ClassEntity> getBackendTypeHelpers(
       JCommonElements commonElements) {
-    return <ClassEntity>[
+    return [
       commonElements.jsMutableArrayClass,
       commonElements.jsFixedArrayClass,
       commonElements.jsExtendableArrayClass,
@@ -137,14 +135,6 @@
     }
   }
 
-  Map<OutputUnit, List<ClassEntity>> get _outputListsForClassType {
-    if (_options.deferClassTypes) {
-      return outputClassTypeLists;
-    } else {
-      return outputClassLists;
-    }
-  }
-
   /// Compute all the classes and typedefs that must be emitted.
   void computeNeededDeclarations() {
     Set<ClassEntity> backendTypeHelpers =
@@ -157,7 +147,6 @@
       return !backendTypeHelpers.contains(cls) &&
           _rtiNeededClasses.contains(cls) &&
           !classesOnlyNeededForRti.contains(cls) &&
-          _options.deferClassTypes &&
           _outputUnitData.outputUnitForClass(cls) !=
               _outputUnitData.outputUnitForClassType(cls);
     }
@@ -240,7 +229,7 @@
     // 7. Sort classes needed for type checking and then add them to their
     // respective OutputUnits.
     for (ClassEntity cls in _sorter.sortClasses(neededClassTypes)) {
-      _outputListsForClassType
+      outputClassTypeLists
           .putIfAbsent(_outputUnitData.outputUnitForClassType(cls), () => [])
           .add(cls);
     }
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 5351885..0d0b438 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -135,7 +135,6 @@
       this._rtiNeededClasses,
       this._mainFunction)
       : this.collector = new Collector(
-            _options,
             _commonElements,
             _elementEnvironment,
             _outputUnitData,
@@ -653,16 +652,11 @@
   Class _buildClass(ClassEntity cls) {
     bool onlyForConstructor =
         collector.classesOnlyNeededForConstructor.contains(cls);
-    bool onlyForRti = _options.deferClassTypes
-        ? false
-        : collector.classesOnlyNeededForRti.contains(cls);
+    // TODO(joshualitt): Can we just emit JSInteropClasses as types?
+    // TODO(jacobr): check whether the class has any active static fields
+    // if it does not we can suppress it completely.
+    bool onlyForRti = _nativeData.isJsInteropClass(cls);
     bool hasRtiField = _rtiNeed.classNeedsTypeArguments(cls);
-    if (_nativeData.isJsInteropClass(cls)) {
-      // TODO(joshualitt): Can we just emit JSInteropClasses as types?
-      // TODO(jacobr): check whether the class has any active static fields
-      // if it does not we can suppress it completely.
-      onlyForRti = true;
-    }
     bool onlyForConstructorOrRti = onlyForConstructor || onlyForRti;
     bool isClosureBaseClass = cls == _commonElements.closureClass;
 
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 4ec53ba..597f756 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -168,6 +168,27 @@
   };
 }
 
+// Creates a lazy final field that uses non-nullable initialization semantics.
+//
+// A lazy field has a storage entry, [name], which holds the value, and a
+// getter ([getterName]) to access the field. If the field wasn't set before
+// the first access, it is initialized with the [initializer].
+function lazyFinal(holder, name, getterName, initializer) {
+  var uninitializedSentinel = holder;
+  holder[name] = uninitializedSentinel;
+  holder[getterName] = function() {
+    if (holder[name] === uninitializedSentinel) {
+      var value = initializer();
+      if (holder[name] !== uninitializedSentinel) {
+        #throwLateInitializationError(name);
+      }
+      holder[name] = value;
+    }
+    holder[getterName] = function() { return this[name]; };
+    return holder[name];
+  };
+}
+
 // Given a list, marks it as constant.
 //
 // The runtime ensures that const-lists cannot be modified.
@@ -369,6 +390,7 @@
 
     makeConstList: makeConstList,
     lazy: lazy,
+    lazyFinal: lazyFinal,
     lazyOld: lazyOld,
     updateHolder: updateHolder,
     convertToFastObject: convertToFastObject,
@@ -686,6 +708,8 @@
       'directAccessTestExpression': js.js(_directAccessTestExpression),
       'cyclicThrow': _emitter
           .staticFunctionAccess(_closedWorld.commonElements.cyclicThrowHelper),
+      'throwLateInitializationError': _emitter.staticFunctionAccess(
+          _closedWorld.commonElements.throwLateInitializationError),
       'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
       'tearOffCode': new js.Block(buildTearOffCode(
           _options, _emitter, _namer, _closedWorld.commonElements)),
@@ -1755,14 +1779,17 @@
     LocalAliases locals = LocalAliases();
     for (StaticField field in fields) {
       assert(field.holder.isStaticStateHolder);
+      String helper = field.usesNonNullableInitialization
+          ? field.isFinal
+              ? locals.find('_lazyFinal', 'hunkHelpers.lazyFinal')
+              : locals.find('_lazy', 'hunkHelpers.lazy')
+          : locals.find('_lazyOld', 'hunkHelpers.lazyOld');
       js.Statement statement = js.js.statement("#(#, #, #, #);", [
-        field.usesNonNullableInitialization
-            ? locals.find('_lazy', 'hunkHelpers.lazy')
-            : locals.find('_lazyOld', 'hunkHelpers.lazyOld'),
+        helper,
         field.holder.name,
         js.quoteName(field.name),
         js.quoteName(field.getterName),
-        field.code
+        field.code,
       ]);
 
       registerEntityAst(field.element, statement,
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 8ea2061..e0dd7a2 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -239,6 +239,11 @@
             }
             break;
           case VariableUseKind.localReturnType:
+            if (usage.localFunction.function.asyncMarker !=
+                ir.AsyncMarker.Sync) {
+              // The Future/Iterator/Stream implementation requires the type.
+              return true;
+            }
             if (rtiNeed.localFunctionNeedsSignature(usage.localFunction)) {
               return true;
             }
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index 10bb603..b26e902 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -174,9 +174,6 @@
   /// Returns the inferred receiver type of the dynamic [read].
   AbstractValue receiverTypeOfGet(ir.PropertyGet read);
 
-  /// Returns the inferred receiver type of the direct [read].
-  AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet read);
-
   /// Returns the inferred receiver type of the dynamic [write].
   AbstractValue receiverTypeOfSet(
       ir.PropertySet write, AbstractValueDomain abstractValueDomain);
@@ -520,7 +517,7 @@
   ir.Field node = definition.node;
   if (node.isInstanceMember &&
       !node.isFinal &&
-      node.initializer is ir.NullLiteral) {
+      isNullLiteral(node.initializer)) {
     return null;
   }
   return node.initializer;
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 20f91bd..4c5e0a1 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -136,7 +136,7 @@
       AnnotationsData annotations)
       : this.options = _elementMap.options {
     _elementEnvironment = new JsElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
@@ -296,7 +296,7 @@
   JsKernelToElementMap.readFromDataSource(this.options, this.reporter,
       this._environment, ir.Component component, DataSource source) {
     _elementEnvironment = new JsElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
@@ -820,7 +820,7 @@
     while (superclass != null) {
       JClassEnv env = classes.getEnv(superclass);
       MemberEntity superMember =
-          env.lookupMember(this, name.name, setter: setter);
+          env.lookupMember(this, name.text, setter: setter);
       if (superMember != null) {
         if (!superMember.isInstanceMember) return null;
         if (!superMember.isAbstract) {
@@ -1243,7 +1243,7 @@
   @override
   Name getName(ir.Name name) {
     return new Name(
-        name.name, name.isPrivate ? getLibrary(name.library) : null);
+        name.text, name.isPrivate ? getLibrary(name.library) : null);
   }
 
   @override
@@ -1262,9 +1262,6 @@
     if (node is ir.PropertyGet) {
       return getGetterSelector(node.name);
     }
-    if (node is ir.DirectPropertyGet) {
-      return getGetterSelector(node.target.name);
-    }
     if (node is ir.SuperPropertyGet) {
       return getGetterSelector(node.name);
     }
@@ -1302,13 +1299,13 @@
 
   Selector getGetterSelector(ir.Name irName) {
     Name name = new Name(
-        irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+        irName.text, irName.isPrivate ? getLibrary(irName.library) : null);
     return new Selector.getter(name);
   }
 
   Selector getSetterSelector(ir.Name irName) {
     Name name = new Name(
-        irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+        irName.text, irName.isPrivate ? getLibrary(irName.library) : null);
     return new Selector.setter(name);
   }
 
@@ -2140,7 +2137,7 @@
         if (node.kind == ir.ProcedureKind.Factory) {
           parts.add(utils.reconstructConstructorName(getMember(node)));
         } else {
-          parts.add(utils.operatorNameToIdentifier(node.name.name));
+          parts.add(utils.operatorNameToIdentifier(node.name.text));
         }
       } else if (node is ir.Constructor) {
         parts.add(utils.reconstructConstructorName(getMember(node)));
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index b8614dd..42ced5b 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -533,11 +533,6 @@
   }
 
   @override
-  AbstractValue receiverTypeOfDirectGet(ir.DirectPropertyGet node) {
-    return _targetResults.typeOfReceiver(node);
-  }
-
-  @override
   AbstractValue receiverTypeOfSet(
       ir.PropertySet node, AbstractValueDomain abstractValueDomain) {
     return _targetResults.typeOfReceiver(node);
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index f56563a..c93e774 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -69,6 +69,9 @@
   bool get supportsLateFields => false;
 
   @override
+  bool get supportsLateLoweringSentinel => false;
+
+  @override
   bool get useStaticFieldLowering => false;
 
   // TODO(johnniwinther,sigmund): Remove this when js-interop handles getter
diff --git a/pkg/compiler/lib/src/kernel/deferred_load.dart b/pkg/compiler/lib/src/kernel/deferred_load.dart
deleted file mode 100644
index 9ca9bcf..0000000
--- a/pkg/compiler/lib/src/kernel/deferred_load.dart
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library kernel.deferred_load_data;
-
-import 'package:kernel/ast.dart' as ir;
-import 'package:kernel/type_environment.dart' as ir;
-
-import '../common_elements.dart';
-import '../compiler.dart' show Compiler;
-import '../constants/values.dart';
-import '../deferred_load.dart';
-import '../elements/entities.dart';
-import '../ir/util.dart';
-import 'element_map.dart';
-
-class KernelDeferredLoadTask extends DeferredLoadTask {
-  KernelToElementMap _elementMap;
-  Map<ir.Library, Set<ir.NamedNode>> _additionalExportsSets =
-      <ir.Library, Set<ir.NamedNode>>{};
-
-  KernelDeferredLoadTask(Compiler compiler, this._elementMap) : super(compiler);
-
-  Iterable<ImportEntity> _findImportsTo(ir.NamedNode node, String nodeName,
-      ir.Library enclosingLibrary, LibraryEntity library) {
-    return measureSubtask('find-imports', () {
-      List<ImportEntity> imports = [];
-      ir.Library source = _elementMap.getLibraryNode(library);
-      if (!source.dependencies.any((d) => d.isDeferred)) return const [];
-      for (ir.LibraryDependency dependency in source.dependencies) {
-        if (dependency.isExport) continue;
-        if (!_isVisible(dependency.combinators, nodeName)) continue;
-        if (enclosingLibrary == dependency.targetLibrary ||
-            additionalExports(dependency.targetLibrary).contains(node)) {
-          imports.add(_elementMap.getImport(dependency));
-        }
-      }
-      return imports;
-    });
-  }
-
-  @override
-  Iterable<ImportEntity> classImportsTo(
-      ClassEntity element, LibraryEntity library) {
-    ir.Class node = _elementMap.getClassNode(element);
-    return _findImportsTo(node, node.name, node.enclosingLibrary, library);
-  }
-
-  @override
-  Iterable<ImportEntity> memberImportsTo(
-      Entity element, LibraryEntity library) {
-    ir.Member node = _elementMap.getMemberNode(element);
-    return _findImportsTo(
-        node is ir.Constructor ? node.enclosingClass : node,
-        node is ir.Constructor ? node.enclosingClass.name : node.name.name,
-        node.enclosingLibrary,
-        library);
-  }
-
-  @override
-  void checkForDeferredErrorCases(LibraryEntity library) {
-    // Nothing to do. The FE checks for error cases upfront.
-  }
-
-  @override
-  void collectConstantsFromMetadata(
-      Entity element, Set<ConstantValue> constants) {
-    // Nothing to do. Kernel-pipeline doesn't support mirrors, so we don't need
-    // to track any constants from meta-data.
-  }
-
-  @override
-  void collectConstantsInBody(MemberEntity element, Dependencies dependencies) {
-    ir.Member node = _elementMap.getMemberNode(element);
-
-    // Fetch the internal node in order to skip annotations on the member.
-    // TODO(sigmund): replace this pattern when the kernel-ast provides a better
-    // way to skip annotations (issue 31565).
-    var visitor = new ConstantCollector(
-        _elementMap, _elementMap.getStaticTypeContext(element), dependencies);
-    if (node is ir.Field) {
-      node.initializer?.accept(visitor);
-      return;
-    }
-
-    if (node is ir.Constructor) {
-      node.initializers.forEach((i) => i.accept(visitor));
-    }
-    node.function?.accept(visitor);
-  }
-
-  Set<ir.NamedNode> additionalExports(ir.Library library) {
-    return _additionalExportsSets[library] ??= new Set<ir.NamedNode>.from(
-        library.additionalExports.map((ir.Reference ref) => ref.node));
-  }
-
-  @override
-  void cleanup() {
-    _additionalExportsSets = null;
-  }
-}
-
-/// Returns whether [name] would be visible according to the given list of
-/// show/hide [combinators].
-bool _isVisible(List<ir.Combinator> combinators, String name) {
-  for (var c in combinators) {
-    if (c.isShow && !c.names.contains(name)) return false;
-    if (c.isHide && c.names.contains(name)) return false;
-  }
-  return true;
-}
-
-class ConstantCollector extends ir.RecursiveVisitor {
-  final KernelToElementMap elementMap;
-  final Dependencies dependencies;
-  final ir.StaticTypeContext staticTypeContext;
-
-  ConstantCollector(this.elementMap, this.staticTypeContext, this.dependencies);
-
-  CommonElements get commonElements => elementMap.commonElements;
-
-  void add(ir.Expression node, {bool required: true}) {
-    ConstantValue constant = elementMap
-        .getConstantValue(staticTypeContext, node, requireConstant: required);
-    if (constant != null) {
-      dependencies.addConstant(
-          constant, elementMap.getImport(getDeferredImport(node)));
-    }
-  }
-
-  @override
-  void visitIntLiteral(ir.IntLiteral literal) {}
-
-  @override
-  void visitDoubleLiteral(ir.DoubleLiteral literal) {}
-
-  @override
-  void visitBoolLiteral(ir.BoolLiteral literal) {}
-
-  @override
-  void visitStringLiteral(ir.StringLiteral literal) {}
-
-  @override
-  void visitSymbolLiteral(ir.SymbolLiteral literal) => add(literal);
-
-  @override
-  void visitNullLiteral(ir.NullLiteral literal) {}
-
-  @override
-  void visitListLiteral(ir.ListLiteral literal) {
-    if (literal.isConst) {
-      add(literal);
-    } else {
-      super.visitListLiteral(literal);
-    }
-  }
-
-  @override
-  void visitSetLiteral(ir.SetLiteral literal) {
-    if (literal.isConst) {
-      add(literal);
-    } else {
-      super.visitSetLiteral(literal);
-    }
-  }
-
-  @override
-  void visitMapLiteral(ir.MapLiteral literal) {
-    if (literal.isConst) {
-      add(literal);
-    } else {
-      super.visitMapLiteral(literal);
-    }
-  }
-
-  @override
-  void visitConstructorInvocation(ir.ConstructorInvocation node) {
-    if (node.isConst) {
-      add(node);
-    } else {
-      super.visitConstructorInvocation(node);
-    }
-  }
-
-  @override
-  void visitTypeParameter(ir.TypeParameter node) {
-    // We avoid visiting metadata on the type parameter declaration. The bound
-    // cannot hold constants so we skip that as well.
-  }
-
-  @override
-  void visitVariableDeclaration(ir.VariableDeclaration node) {
-    // We avoid visiting metadata on the parameter declaration by only visiting
-    // the initializer. The type cannot hold constants so can kan skip that
-    // as well.
-    node.initializer?.accept(this);
-  }
-
-  @override
-  void visitTypeLiteral(ir.TypeLiteral node) {
-    if (node.type is! ir.TypeParameterType) add(node);
-  }
-
-  @override
-  void visitInstantiation(ir.Instantiation node) {
-    // TODO(johnniwinther): The CFE should mark constant instantiations as
-    // constant.
-    add(node, required: false);
-    super.visitInstantiation(node);
-  }
-
-  @override
-  void visitConstantExpression(ir.ConstantExpression node) {
-    add(node);
-  }
-}
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 76e5139..d4fba7c 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -117,7 +117,7 @@
   KernelToElementMapImpl(
       this.reporter, this._environment, this._frontendStrategy, this.options) {
     _elementEnvironment = new KernelElementEnvironment(this);
-    _typeConverter = new DartTypeConverter(options, this);
+    _typeConverter = new DartTypeConverter(this);
     _types = new KernelDartTypes(this, options);
     _commonElements = new CommonElementsImpl(_types, _elementEnvironment);
     _constantValuefier = new ConstantValuefier(this);
@@ -439,7 +439,7 @@
     while (superclass != null) {
       KClassEnv env = classes.getEnv(superclass);
       MemberEntity superMember =
-          env.lookupMember(this, name.name, setter: setter);
+          env.lookupMember(this, name.text, setter: setter);
       if (superMember != null) {
         if (!superMember.isInstanceMember) return null;
         if (!superMember.isAbstract) {
@@ -826,7 +826,7 @@
   @override
   Name getName(ir.Name name) {
     return new Name(
-        name.name, name.isPrivate ? getLibrary(name.library) : null);
+        name.text, name.isPrivate ? getLibrary(name.library) : null);
   }
 
   @override
@@ -887,13 +887,13 @@
 
   Selector getGetterSelector(ir.Name irName) {
     Name name = new Name(
-        irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+        irName.text, irName.isPrivate ? getLibrary(irName.library) : null);
     return new Selector.getter(name);
   }
 
   Selector getSetterSelector(ir.Name irName) {
     Name name = new Name(
-        irName.name, irName.isPrivate ? getLibrary(irName.library) : null);
+        irName.text, irName.isPrivate ? getLibrary(irName.library) : null);
     return new Selector.setter(name);
   }
 
@@ -1534,7 +1534,7 @@
   @override
   ForeignKind getForeignKind(ir.StaticInvocation node) {
     if (commonElements.isForeignHelper(getMember(node.target))) {
-      switch (node.target.name.name) {
+      switch (node.target.name.text) {
         case Identifiers.JS:
           return ForeignKind.JS;
         case Identifiers.JS_BUILTIN:
@@ -1558,6 +1558,12 @@
     ir.Node argument = node.arguments.positional.first;
     if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
       return getInterfaceType(argument.type);
+    } else if (argument is ir.ConstantExpression &&
+        argument.constant is ir.TypeLiteralConstant) {
+      ir.TypeLiteralConstant constant = argument.constant;
+      if (constant.type is ir.InterfaceType) {
+        return getInterfaceType(constant.type);
+      }
     }
     return null;
   }
@@ -1939,10 +1945,6 @@
 
   KernelBehaviorBuilder(this.elementEnvironment, this.commonElements,
       this.nativeBasicData, this.reporter, this.options);
-
-  @override
-  bool get trustJSInteropTypeAnnotations =>
-      options.trustJSInteropTypeAnnotations;
 }
 
 class KernelNativeMemberResolver implements NativeMemberResolver {
@@ -2037,7 +2039,7 @@
   /// defaulting to the Dart name.
   void _setNativeName(ir.Member node, IrAnnotationData annotationData) {
     String name = _findJsNameFromAnnotation(node, annotationData);
-    name ??= node.name.name;
+    name ??= node.name.text;
     _nativeDataBuilder.setNativeMemberName(_elementMap.getMember(node), name);
   }
 
@@ -2052,7 +2054,7 @@
   void _setNativeNameForStaticMethod(
       ir.Member node, IrAnnotationData annotationData) {
     String name = _findJsNameFromAnnotation(node, annotationData);
-    name ??= node.name.name;
+    name ??= node.name.text;
     if (_isIdentifier(name)) {
       ClassEntity cls = _elementMap.getClass(node.enclosingClass);
       List<String> nativeNames = _nativeBasicData.getNativeTagsOfClass(cls);
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index 23a170d..36f4dad 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -125,14 +125,14 @@
         }
         if (member is ir.Procedure) {
           if (member.kind == ir.ProcedureKind.Setter) {
-            _setterMap[member.name.name] = member;
+            _setterMap[member.name.text] = member;
           } else {
-            _memberMap[member.name.name] = member;
+            _memberMap[member.name.text] = member;
           }
         } else if (member is ir.Field) {
-          _memberMap[member.name.name] = member;
+          _memberMap[member.name.text] = member;
           if (member.isMutable) {
-            _setterMap[member.name.name] = member;
+            _setterMap[member.name.text] = member;
           }
         } else {
           failedAt(
@@ -379,7 +379,7 @@
     void addField(ir.Field member, {bool includeStatic}) {
       if (!includeStatic && member.isStatic) return;
       if (isRedirectingFactoryField(member)) return;
-      var name = member.name.name;
+      var name = member.name.text;
       _memberMap[name] = member;
       if (member.isMutable) {
         _setterMap[name] = member;
@@ -399,7 +399,7 @@
           return;
         }
       }
-      var name = member.name.name;
+      var name = member.name.text;
       if (member.kind == ir.ProcedureKind.Factory) {
         if (isRedirectingFactory(member)) {
           // Don't include redirecting factories.
@@ -420,7 +420,7 @@
 
     void addConstructors(ir.Class c) {
       for (ir.Constructor member in c.constructors) {
-        var name = member.name.name;
+        var name = member.name.text;
         _constructorMap[name] = member;
       }
     }
@@ -487,7 +487,7 @@
         var forwardingConstructor = _buildForwardingConstructor(
             superclassCloner, superclassConstructor);
         cls.addMember(forwardingConstructor);
-        _constructorMap[forwardingConstructor.name.name] =
+        _constructorMap[forwardingConstructor.name.text] =
             forwardingConstructor;
       }
     }
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index 478c2bc..b8959e9 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -45,7 +45,6 @@
 import '../universe/world_builder.dart';
 import '../universe/world_impact.dart';
 import '../util/enumset.dart';
-import 'deferred_load.dart';
 import 'element_map.dart';
 import 'element_map_impl.dart';
 import 'loader.dart';
@@ -54,7 +53,7 @@
 /// model from kernel IR nodes.
 class KernelFrontendStrategy extends FrontendStrategy {
   final NativeBasicDataBuilderImpl nativeBasicDataBuilder =
-      new NativeBasicDataBuilderImpl();
+      NativeBasicDataBuilderImpl();
   NativeBasicData _nativeBasicData;
   CompilerOptions _options;
   CompilerTask _compilerTask;
@@ -87,12 +86,11 @@
   KernelFrontendStrategy(this._compilerTask, this._options,
       DiagnosticReporter reporter, env.Environment environment) {
     assert(_compilerTask != null);
-    _elementMap =
-        new KernelToElementMapImpl(reporter, environment, this, _options);
-    _modularStrategy = new KernelModularStrategy(_compilerTask, _elementMap);
-    _backendUsageBuilder = new BackendUsageBuilderImpl(this);
-    noSuchMethodRegistry = new NoSuchMethodRegistryImpl(
-        commonElements, new KernelNoSuchMethodResolver(_elementMap));
+    _elementMap = KernelToElementMapImpl(reporter, environment, this, _options);
+    _modularStrategy = KernelModularStrategy(_compilerTask, _elementMap);
+    _backendUsageBuilder = BackendUsageBuilderImpl(this);
+    noSuchMethodRegistry = NoSuchMethodRegistryImpl(
+        commonElements, KernelNoSuchMethodResolver(_elementMap));
   }
 
   NativeResolutionEnqueuer get nativeResolutionEnqueuerForTesting =>
@@ -139,32 +137,30 @@
   ResolutionEnqueuer createResolutionEnqueuer(
       CompilerTask task, Compiler compiler) {
     RuntimeTypesNeedBuilder rtiNeedBuilder = _createRuntimeTypesNeedBuilder();
-    BackendImpacts impacts =
-        new BackendImpacts(commonElements, compiler.options);
-    _nativeResolutionEnqueuer = new NativeResolutionEnqueuer(
+    BackendImpacts impacts = BackendImpacts(commonElements, compiler.options);
+    _nativeResolutionEnqueuer = NativeResolutionEnqueuer(
         compiler.options,
         elementEnvironment,
         commonElements,
         _elementMap.types,
-        new BaseNativeClassFinder(elementEnvironment, nativeBasicData));
-    _nativeDataBuilder = new NativeDataBuilderImpl(nativeBasicData);
-    _customElementsResolutionAnalysis = new CustomElementsResolutionAnalysis(
+        BaseNativeClassFinder(elementEnvironment, nativeBasicData));
+    _nativeDataBuilder = NativeDataBuilderImpl(nativeBasicData);
+    _customElementsResolutionAnalysis = CustomElementsResolutionAnalysis(
         elementEnvironment,
         commonElements,
         nativeBasicData,
         _backendUsageBuilder);
-    _fieldAnalysis = new KFieldAnalysis(this);
-    ClassQueries classQueries = new KernelClassQueries(elementMap);
+    _fieldAnalysis = KFieldAnalysis(this);
+    ClassQueries classQueries = KernelClassQueries(elementMap);
     ClassHierarchyBuilder classHierarchyBuilder =
-        new ClassHierarchyBuilder(commonElements, classQueries);
-    AnnotationsDataBuilder annotationsDataBuilder =
-        new AnnotationsDataBuilder();
+        ClassHierarchyBuilder(commonElements, classQueries);
+    AnnotationsDataBuilder annotationsDataBuilder = AnnotationsDataBuilder();
     // TODO(johnniwinther): This is a hack. The annotation data is built while
     // using it. With CFE constants the annotations data can be built fully
     // before creating the resolution enqueuer.
-    AnnotationsData annotationsData = new AnnotationsDataImpl(
+    AnnotationsData annotationsData = AnnotationsDataImpl(
         compiler.options, annotationsDataBuilder.pragmaAnnotations);
-    ImpactTransformer impactTransformer = new JavaScriptImpactTransformer(
+    ImpactTransformer impactTransformer = JavaScriptImpactTransformer(
         elementEnvironment,
         commonElements,
         impacts,
@@ -175,13 +171,12 @@
         rtiNeedBuilder,
         classHierarchyBuilder,
         annotationsData);
-    InterceptorDataBuilder interceptorDataBuilder =
-        new InterceptorDataBuilderImpl(
-            nativeBasicData, elementEnvironment, commonElements);
-    return new ResolutionEnqueuer(
+    InterceptorDataBuilder interceptorDataBuilder = InterceptorDataBuilderImpl(
+        nativeBasicData, elementEnvironment, commonElements);
+    return ResolutionEnqueuer(
         task,
         compiler.reporter,
-        new ResolutionEnqueuerListener(
+        ResolutionEnqueuerListener(
             compiler.options,
             elementEnvironment,
             commonElements,
@@ -194,7 +189,7 @@
             _nativeResolutionEnqueuer,
             _fieldAnalysis,
             compiler.deferredLoadTask),
-        new ResolutionWorldBuilderImpl(
+        ResolutionWorldBuilderImpl(
             _options,
             elementMap,
             elementEnvironment,
@@ -212,7 +207,7 @@
             const StrongModeWorldStrategy(),
             classHierarchyBuilder,
             classQueries),
-        new KernelWorkItemBuilder(
+        KernelWorkItemBuilder(
             _compilerTask,
             elementMap,
             nativeBasicData,
@@ -251,8 +246,8 @@
   void registerLoadedLibraries(KernelResult kernelResult) {
     _elementMap.addComponent(kernelResult.component);
     _irAnnotationData = processAnnotations(
-        new ModularCore(kernelResult.component, _elementMap.constantEvaluator));
-    _annotationProcessor = new KernelAnnotationProcessor(
+        ModularCore(kernelResult.component, _elementMap.constantEvaluator));
+    _annotationProcessor = KernelAnnotationProcessor(
         elementMap, nativeBasicDataBuilder, _irAnnotationData);
     for (Uri uri in kernelResult.libraries) {
       LibraryEntity library = elementEnvironment.lookupLibrary(uri);
@@ -280,7 +275,7 @@
 
   @override
   DeferredLoadTask createDeferredLoadTask(Compiler compiler) =>
-      new KernelDeferredLoadTask(compiler, _elementMap);
+      DeferredLoadTask(compiler, _elementMap);
 
   @override
   FunctionEntity computeMain(WorldImpactBuilder impactBuilder) {
@@ -290,7 +285,7 @@
   RuntimeTypesNeedBuilder _createRuntimeTypesNeedBuilder() {
     return _runtimeTypesNeedBuilder ??= _options.disableRtiOptimization
         ? const TrivialRuntimeTypesNeedBuilder()
-        : new RuntimeTypesNeedBuilderImpl(elementEnvironment);
+        : RuntimeTypesNeedBuilderImpl(elementEnvironment);
   }
 
   RuntimeTypesNeedBuilder get runtimeTypesNeedBuilderForTesting =>
@@ -326,12 +321,12 @@
       this._fieldAnalysis,
       this._modularStrategy,
       this._irAnnotationData)
-      : _nativeMemberResolver = new KernelNativeMemberResolver(
+      : _nativeMemberResolver = KernelNativeMemberResolver(
             _elementMap, nativeBasicData, nativeDataBuilder);
 
   @override
   WorkItem createWorkItem(MemberEntity entity) {
-    return new KernelWorkItem(
+    return KernelWorkItem(
         _compilerTask,
         _elementMap,
         _impactTransformer,
@@ -404,7 +399,7 @@
         ResolutionImpact impact = _elementMap.computeWorldImpact(
             element,
             scopeModel.variableScopeModel,
-            new Set<PragmaAnnotation>.from(
+            Set<PragmaAnnotation>.from(
                 annotations.iterable(PragmaAnnotation.values)),
             impactBuilderData: impactBuilderData);
         WorldImpact worldImpact =
@@ -440,8 +435,8 @@
   @override
   ModularMemberData getModularMemberData(
       ir.Member node, EnumSet<PragmaAnnotation> annotations) {
-    ScopeModel scopeModel = _compilerTask.measureSubtask('closures',
-        () => new ScopeModel.from(node, _elementMap.constantEvaluator));
+    ScopeModel scopeModel = _compilerTask.measureSubtask(
+        'closures', () => ScopeModel.from(node, _elementMap.constantEvaluator));
     ImpactBuilderData impactBuilderData;
     if (useImpactDataForTesting) {
       // TODO(johnniwinther): Always create and use the [ImpactBuilderData].
@@ -449,8 +444,8 @@
       // depend on metadata, so these parts of the impact data need to be
       // computed during conversion to [ResolutionImpact].
       impactBuilderData = _compilerTask.measureSubtask('worldImpact', () {
-        ImpactBuilder builder = new ImpactBuilder(
-            new ir.StaticTypeContext(node, _elementMap.typeEnvironment),
+        ImpactBuilder builder = ImpactBuilder(
+            ir.StaticTypeContext(node, _elementMap.typeEnvironment),
             _elementMap.classHierarchy,
             scopeModel.variableScopeModel,
             useAsserts: _elementMap.options.enableUserAssertions,
@@ -459,6 +454,6 @@
         return builder.computeImpact(node);
       });
     }
-    return new ModularMemberData(scopeModel, impactBuilderData);
+    return ModularMemberData(scopeModel, impactBuilderData);
   }
 }
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index fee3632..496d69b 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -74,17 +74,8 @@
       ir.Component component;
       var isDill = resolvedUri.path.endsWith('.dill');
 
-      // TODO(sigmund): remove after we unfork the sdk, and force null-safety to
-      // always be considered to be true.
-      void inferNullSafety() {
-        if (component.libraries.any((lib) =>
-            lib.isNonNullableByDefault && lib.importUri.scheme == 'dart')) {
-          _options.useNullSafety = true;
-        }
-      }
-
       void inferNullSafetyMode(bool isSound) {
-        if (isSound) assert(_options.useNullSafety == true);
+        if (isSound) assert(_options.enableNonNullable);
         if (_options.nullSafetyMode == NullSafetyMode.unspecified) {
           _options.nullSafetyMode =
               isSound ? NullSafetyMode.sound : NullSafetyMode.unsound;
@@ -94,7 +85,7 @@
       void validateNullSafety() {
         assert(_options.nullSafetyMode != NullSafetyMode.unspecified);
         if (_options.nullSafetyMode == NullSafetyMode.sound) {
-          assert(_options.useNullSafety);
+          assert(_options.enableNonNullable);
         }
       }
 
@@ -119,7 +110,6 @@
           throw ArgumentError("$resolvedUri was compiled with $dillMode null "
               "safety and is incompatible with the '$option' option");
         }
-        inferNullSafety();
         inferNullSafetyMode(isStrongDill);
         validateNullSafety();
 
@@ -160,7 +150,7 @@
           ..onDiagnostic = onDiagnostic;
         bool isLegacy =
             await fe.uriUsesLegacyLanguageVersion(resolvedUri, options);
-        inferNullSafetyMode(_options.useNullSafety && !isLegacy);
+        inferNullSafetyMode(_options.enableNonNullable && !isLegacy);
 
         List<Uri> dependencies = [];
         if (_options.platformBinaries != null) {
@@ -170,6 +160,7 @@
         if (_options.dillDependencies != null) {
           dependencies.addAll(_options.dillDependencies);
         }
+
         initializedCompilerState = fe.initializeCompiler(
             initializedCompilerState,
             target,
@@ -183,7 +174,6 @@
         component = await fe.compile(initializedCompilerState, verbose,
             fileSystem, onDiagnostic, resolvedUri);
         if (component == null) return null;
-        inferNullSafety();
         validateNullSafety();
       }
 
diff --git a/pkg/compiler/lib/src/kernel/native_basic_data.dart b/pkg/compiler/lib/src/kernel/native_basic_data.dart
index 9ebb17d..54e0f83 100644
--- a/pkg/compiler/lib/src/kernel/native_basic_data.dart
+++ b/pkg/compiler/lib/src/kernel/native_basic_data.dart
@@ -125,15 +125,6 @@
               _nativeBasicDataBuilder.markAsJsInteropMember(
                   function, memberName);
             }
-
-            if (!function.isExternal &&
-                !function.isAbstract &&
-                !function.isStatic) {
-              reporter.reportErrorMessage(
-                  function,
-                  MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
-                  {'cls': cls.name, 'member': member.name});
-            }
           }
         });
         elementEnvironment.forEachConstructor(cls,
diff --git a/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart b/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
index 32f6721..2e347e0 100644
--- a/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
+++ b/pkg/compiler/lib/src/kernel/no_such_method_resolver.dart
@@ -32,7 +32,7 @@
       expr = asExpression.operand;
     }
     if (expr is ir.SuperMethodInvocation &&
-        expr.name.name == Identifiers.noSuchMethod_) {
+        expr.name.text == Identifiers.noSuchMethod_) {
       ir.Arguments arguments = expr.arguments;
       if (arguments.positional.length == 1 &&
           arguments.named.isEmpty &&
diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
index 049814a..0457090 100644
--- a/pkg/compiler/lib/src/native/behavior.dart
+++ b/pkg/compiler/lib/src/native/behavior.dart
@@ -736,7 +736,6 @@
   CommonElements get commonElements;
   DiagnosticReporter get reporter;
   NativeBasicData get nativeBasicData;
-  bool get trustJSInteropTypeAnnotations;
   ElementEnvironment get elementEnvironment;
   CompilerOptions get options;
   DartTypes get dartTypes => commonElements.dartTypes;
@@ -817,21 +816,13 @@
           _behavior.typesInstantiated.add(type);
         }
 
-        if (!trustJSInteropTypeAnnotations || dartTypes.isTopType(type)) {
-          // By saying that only JS-interop types can be created, we prevent
-          // pulling in every other native type (e.g. all of dart:html) when a
-          // JS interop API returns dynamic or when we don't trust the type
-          // annotations. This means that to some degree we still use the return
-          // type to decide whether to include native types, even if we don't
-          // trust the type annotation.
-          ClassEntity cls = commonElements.jsJavaScriptObjectClass;
-          _behavior.typesInstantiated.add(elementEnvironment.getThisType(cls));
-        } else {
-          // Otherwise, when the declared type is a Dart type, we do not
-          // register an allocation because we assume it cannot be instantiated
-          // from within the JS-interop code. It must have escaped from another
-          // API.
-        }
+        // By saying that only JS-interop types can be created, we prevent
+        // pulling in every other native type (e.g. all of dart:html) when a
+        // JS interop API returns dynamic.  This means that to some degree we
+        // still use the return type to decide whether to include native types,
+        // even though we don't trust the type annotation.
+        ClassEntity cls = commonElements.jsJavaScriptObjectClass;
+        _behavior.typesInstantiated.add(elementEnvironment.getThisType(cls));
       }
     }
   }
@@ -855,8 +846,7 @@
     // compatibility or conditional support by context.
     if (type is NullableType ||
         type is LegacyType ||
-        ((!options.useNullSafety || options.useLegacySubtyping) &&
-            type is! VoidType)) {
+        (options.useLegacySubtyping && type is! VoidType)) {
       _behavior.typesReturned.add(commonElements.nullType);
     }
   }
@@ -869,9 +859,7 @@
       {bool isJsInterop}) {
     _behavior = new NativeBehavior();
     // TODO(sigmund,sra): consider doing something better for numeric types.
-    _addReturnType(!isJsInterop || trustJSInteropTypeAnnotations
-        ? type
-        : commonElements.dynamicType);
+    _addReturnType(!isJsInterop ? type : commonElements.dynamicType);
     _capture(type, isJsInterop);
     _overrideWithAnnotations(
         createsAnnotations, returnsAnnotations, lookupType);
@@ -899,15 +887,12 @@
     // Note: For dart:html and other internal libraries we maintain, we can
     // trust the return type and use it to limit what we enqueue. We have to
     // be more conservative about JS interop types and assume they can return
-    // anything (unless the user provides the experimental flag to trust the
-    // type of js-interop APIs). We do restrict the allocation effects and say
-    // that interop calls create only interop types (which may be unsound if
-    // an interop call returns a DOM type and declares a dynamic return type,
-    // but otherwise we would include a lot of code by default).
+    // anything. We do restrict the allocation effects and say that interop
+    // calls create only interop types (which may be unsound if an interop call
+    // returns a DOM type and declares a dynamic return type, but otherwise we
+    // would include a lot of code by default).
     // TODO(sigmund,sra): consider doing something better for numeric types.
-    _addReturnType(!isJsInterop || trustJSInteropTypeAnnotations
-        ? returnType
-        : commonElements.dynamicType);
+    _addReturnType(!isJsInterop ? returnType : commonElements.dynamicType);
     _capture(type, isJsInterop);
 
     for (DartType type in type.optionalParameterTypes) {
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 1d6bad2..6d336a5 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -110,6 +110,10 @@
   /// `true` if variance is enabled.
   bool get enableVariance => languageExperiments[fe.ExperimentalFlag.variance];
 
+  /// Whether `--enable-experiment=non-nullable` is provided.
+  bool get enableNonNullable =>
+      languageExperiments[fe.ExperimentalFlag.nonNullable];
+
   /// A possibly null state object for kernel compilation.
   fe.InitializedCompilerState kernelInitializedCompilerState;
 
@@ -138,32 +142,6 @@
   /// libraries are subdivided.
   Uri deferredMapUri;
 
-  /// Whether to apply the new deferred split fixes. The fixes improve on
-  /// performance and fix a soundness issue with inferred types. The latter will
-  /// move more code to the main output unit, because of that we are not
-  /// enabling the feature by default right away.
-  ///
-  /// When [reportInvalidInferredDeferredTypes] shows no errors, we expect this
-  /// flag to produce the same or better results than the current unsound
-  /// implementation.
-  bool newDeferredSplit = true; // default value.
-  bool _newDeferredSplit = false;
-  bool _noNewDeferredSplit = false;
-
-  /// Show errors when a deferred type is inferred as a return type of a closure
-  /// or in a type parameter. Those cases cause the compiler today to behave
-  /// unsoundly by putting the code in a deferred output unit. In the future
-  /// when [newDeferredSplit] is on by default, those cases will be treated
-  /// soundly and will cause more code to be moved to the main output unit.
-  ///
-  /// This flag is presented to help developers find and fix the affected code.
-  bool reportInvalidInferredDeferredTypes = false;
-
-  /// Whether to defer load class types.
-  bool deferClassTypes = true; // default value.
-  bool _deferClassTypes = false;
-  bool _noDeferClassTypes = false;
-
   /// Whether to disable inlining during the backend optimizations.
   // TODO(sigmund): negate, so all flags are positive
   bool disableInlining = false;
@@ -253,8 +231,8 @@
   bool enableNullAssertions = false;
 
   /// Whether to generate code asserting that non-nullable return values of
-  /// `@Native` methods are checked for being non-null.
-  bool enableNativeReturnNullAssertions = false;
+  /// `@Native` methods or `JS()` invocations are checked for being non-null.
+  bool enableNativeNullAssertions = false;
 
   /// Whether to generate a source-map file together with the output program.
   bool generateSourceMap = true;
@@ -277,9 +255,6 @@
   /// The compiler is run from the build bot.
   bool testMode = false;
 
-  /// Whether to trust JS-interop annotations. (experimental)
-  bool trustJSInteropTypeAnnotations = false;
-
   /// Whether to trust primitive types during inference and optimizations.
   bool trustPrimitives = false;
 
@@ -365,19 +340,16 @@
   /// Experimental reliance on JavaScript ToBoolean conversions.
   bool experimentToBoolean = false;
 
+  // Experiment to make methods that are inferred as unreachable throw an
+  // exception rather than generate suspect code.
+  bool experimentUnreachableMethodsThrow = false;
+
   /// Experimental instrumentation to investigate code bloat.
   ///
   /// If [true], the compiler will emit code that logs whenever a method is
   /// called.
   bool experimentCallInstrumentation = false;
 
-  /// Whether null-safety (non-nullable types) are enabled in the sdk.
-  ///
-  /// This may be true either when `--enable-experiment=non-nullable` is
-  /// provided on the command-line, or when the provided .dill file for the sdk
-  /// was built with null-safety enabled.
-  bool useNullSafety = false;
-
   /// When null-safety is enabled, whether the compiler should emit code with
   /// unsound or sound semantics.
   ///
@@ -396,7 +368,7 @@
   bool get useLegacySubtyping {
     assert(nullSafetyMode != NullSafetyMode.unspecified,
         "Null safety mode unspecified");
-    return !useNullSafety || (nullSafetyMode == NullSafetyMode.unsound);
+    return !enableNonNullable || (nullSafetyMode == NullSafetyMode.unsound);
   }
 
   /// The path to the file that contains the profiled allocations.
@@ -445,12 +417,6 @@
           _extractStringOption(options, '--build-id=', _UNDETERMINED_BUILD_ID)
       ..compileForServer = _hasOption(options, Flags.serverMode)
       ..deferredMapUri = _extractUriOption(options, '--deferred-map=')
-      .._newDeferredSplit = _hasOption(options, Flags.newDeferredSplit)
-      .._noNewDeferredSplit = _hasOption(options, Flags.noNewDeferredSplit)
-      ..reportInvalidInferredDeferredTypes =
-          _hasOption(options, Flags.reportInvalidInferredDeferredTypes)
-      .._deferClassTypes = _hasOption(options, Flags.deferClassTypes)
-      .._noDeferClassTypes = _hasOption(options, Flags.noDeferClassTypes)
       ..fatalWarnings = _hasOption(options, Flags.fatalWarnings)
       ..terseDiagnostics = _hasOption(options, Flags.terse)
       ..suppressWarnings = _hasOption(options, Flags.suppressWarnings)
@@ -480,6 +446,8 @@
           _hasOption(options, Flags.enableAsserts)
       ..enableNullAssertions = _hasOption(options, Flags.enableCheckedMode) ||
           _hasOption(options, Flags.enableNullAssertions)
+      ..enableNativeNullAssertions =
+          _hasOption(options, Flags.enableNativeNullAssertions)
       ..experimentalTrackAllocations =
           _hasOption(options, Flags.experimentalTrackAllocations)
       ..experimentalAllocationsPath = _extractStringOption(
@@ -487,6 +455,8 @@
       ..experimentStartupFunctions =
           _hasOption(options, Flags.experimentStartupFunctions)
       ..experimentToBoolean = _hasOption(options, Flags.experimentToBoolean)
+      ..experimentUnreachableMethodsThrow =
+          _hasOption(options, Flags.experimentUnreachableMethodsThrow)
       ..experimentCallInstrumentation =
           _hasOption(options, Flags.experimentCallInstrumentation)
       ..generateSourceMap = !_hasOption(options, Flags.noSourceMaps)
@@ -501,8 +471,6 @@
       .._legacyJavaScript = _hasOption(options, Flags.legacyJavaScript)
       .._noLegacyJavaScript = _hasOption(options, Flags.noLegacyJavaScript)
       ..testMode = _hasOption(options, Flags.testMode)
-      ..trustJSInteropTypeAnnotations =
-          _hasOption(options, Flags.trustJSInteropTypeAnnotations)
       ..trustPrimitives = _hasOption(options, Flags.trustPrimitives)
       ..useContentSecurityPolicy =
           _hasOption(options, Flags.useContentSecurityPolicy)
@@ -551,18 +519,10 @@
       throw ArgumentError("'${Flags.soundNullSafety}' incompatible with "
           "'${Flags.noSoundNullSafety}'");
     }
-    if (!useNullSafety && _soundNullSafety) {
+    if (!enableNonNullable && _soundNullSafety) {
       throw ArgumentError("'${Flags.soundNullSafety}' requires the "
           "'non-nullable' experiment to be enabled");
     }
-    if (_deferClassTypes && _noDeferClassTypes) {
-      throw ArgumentError("'${Flags.deferClassTypes}' incompatible with "
-          "'${Flags.noDeferClassTypes}'");
-    }
-    if (_newDeferredSplit && _noNewDeferredSplit) {
-      throw ArgumentError("'${Flags.newDeferredSplit}' incompatible with "
-          "'${Flags.noNewDeferredSplit}'");
-    }
   }
 
   void deriveOptions() {
@@ -579,10 +539,6 @@
     if (_noLegacyJavaScript) legacyJavaScript = false;
     if (_legacyJavaScript) legacyJavaScript = true;
 
-    if (languageExperiments[fe.ExperimentalFlag.nonNullable]) {
-      useNullSafety = true;
-    }
-
     if (_soundNullSafety) nullSafetyMode = NullSafetyMode.sound;
     if (_noSoundNullSafety) nullSafetyMode = NullSafetyMode.unsound;
 
@@ -624,17 +580,6 @@
     if (_disableMinification) {
       enableMinification = false;
     }
-
-    if (_deferClassTypes) deferClassTypes = true;
-    if (_noDeferClassTypes) deferClassTypes = false;
-
-    if (enableNullAssertions) {
-      // TODO(sra): Add a command-line flag to control this independently.
-      enableNativeReturnNullAssertions = true;
-    }
-
-    if (_newDeferredSplit) newDeferredSplit = true;
-    if (_noNewDeferredSplit) newDeferredSplit = false;
   }
 
   /// Returns `true` if warnings and hints are shown for all packages.
diff --git a/pkg/compiler/lib/src/serialization/member_data.dart b/pkg/compiler/lib/src/serialization/member_data.dart
index a014c58..72b2148 100644
--- a/pkg/compiler/lib/src/serialization/member_data.dart
+++ b/pkg/compiler/lib/src/serialization/member_data.dart
@@ -36,7 +36,7 @@
     // other libraries.
     return null;
   }
-  String name = member.name.name;
+  String name = member.name.text;
   if (member is ir.Constructor) {
     name = '.$name';
   } else if (member is ir.Procedure) {
diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart
index c65a05c..3718e25 100644
--- a/pkg/compiler/lib/src/serialization/mixins.dart
+++ b/pkg/compiler/lib/src/serialization/mixins.dart
@@ -763,7 +763,7 @@
 
   @override
   void writeName(ir.Name value) {
-    writeString(value.name);
+    writeString(value.text);
     writeValueOrNull(value.library, writeLibraryNode);
   }
 
diff --git a/pkg/compiler/lib/src/serialization/node_indexer.dart b/pkg/compiler/lib/src/serialization/node_indexer.dart
index e20df93..edc81ae 100644
--- a/pkg/compiler/lib/src/serialization/node_indexer.dart
+++ b/pkg/compiler/lib/src/serialization/node_indexer.dart
@@ -123,24 +123,6 @@
   }
 
   @override
-  void visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    registerNode(node);
-    super.visitDirectPropertyGet(node);
-  }
-
-  @override
-  void visitDirectPropertySet(ir.DirectPropertySet node) {
-    registerNode(node);
-    super.visitDirectPropertySet(node);
-  }
-
-  @override
-  void visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
-    registerNode(node);
-    super.visitDirectMethodInvocation(node);
-  }
-
-  @override
   void visitStaticInvocation(ir.StaticInvocation node) {
     registerNode(node);
     super.visitStaticInvocation(node);
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 06de6f8..8a081d7 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -112,14 +112,9 @@
           "null safety and is incompatible with the '$option' option");
     }
 
-    if (component.libraries.any((lib) =>
-        lib.isNonNullableByDefault && lib.importUri.scheme == 'dart')) {
-      _options.useNullSafety = true;
-    }
-
     if (component.mode == ir.NonNullableByDefaultCompiledMode.Strong) {
+      assert(_options.enableNonNullable);
       _options.nullSafetyMode = NullSafetyMode.sound;
-      assert(_options.useNullSafety);
     } else {
       _options.nullSafetyMode = NullSafetyMode.unsound;
     }
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index dfc216c..842d6e6 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -364,8 +364,6 @@
         return options.useContentSecurityPolicy;
       case 'VARIANCE':
         return options.enableVariance;
-      case 'NNBD':
-        return options.useNullSafety;
       case 'LEGACY':
         return options.useLegacySubtyping;
       case 'LEGACY_JAVASCRIPT':
@@ -461,6 +459,9 @@
               registry.registerStaticUse(new StaticUse.staticInvoke(
                   closedWorld.commonElements.cyclicThrowHelper,
                   CallStructure.ONE_ARG));
+              registry.registerStaticUse(new StaticUse.staticInvoke(
+                  closedWorld.commonElements.throwLateInitializationError,
+                  CallStructure.ONE_ARG));
             }
             if (targetElement.isInstanceMember) {
               if (fieldData.isEffectivelyFinal ||
@@ -1239,9 +1240,11 @@
         parameterStructure: function.parameterStructure,
         checks: _checksForFunction(function));
 
-    if (const bool.fromEnvironment('unreachable-throw')) {
-      var emptyParameters = parameters.values.where((p) =>
-          _abstractValueDomain.isEmpty(p.instructionType).isDefinitelyTrue);
+    if (options.experimentUnreachableMethodsThrow) {
+      var emptyParameters = parameters.values.where((parameter) =>
+          _abstractValueDomain
+              .isEmpty(parameter.instructionType)
+              .isDefinitelyTrue);
       if (emptyParameters.length > 0) {
         _addComment('${emptyParameters} inferred as [empty]');
         add(new HInvokeStatic(
@@ -1542,7 +1545,7 @@
           sourceInformation: null));
       HInstruction value = pop();
       // TODO(johnniwinther): Provide source information.
-      if (options.enableNativeReturnNullAssertions) {
+      if (options.enableNativeNullAssertions) {
         if (_isNonNullableByDefault(functionNode)) {
           DartType type = _getDartTypeIfValid(functionNode.returnType);
           if (dartTypes.isNonNullableIfSound(type)) {
@@ -3007,12 +3010,8 @@
   @override
   void visitLogicalExpression(ir.LogicalExpression node) {
     SsaBranchBuilder brancher = new SsaBranchBuilder(this);
-    String operator = node.operator;
-    // ir.LogicalExpression claims to allow '??' as an operator but currently
-    // that is expanded into a let-tree.
-    assert(operator == '&&' || operator == '||');
     _handleLogicalExpression(node.left, () => node.right.accept(this), brancher,
-        operator, _sourceInformationBuilder.buildBinary(node));
+        node.operatorEnum, _sourceInformationBuilder.buildBinary(node));
   }
 
   /// Optimizes logical binary expression where the left has the same logical
@@ -3028,22 +3027,22 @@
       ir.Expression left,
       void visitRight(),
       SsaBranchBuilder brancher,
-      String operator,
+      ir.LogicalExpressionOperator operatorEnum,
       SourceInformation sourceInformation) {
-    if (left is ir.LogicalExpression && left.operator == operator) {
+    if (left is ir.LogicalExpression && left.operatorEnum == operatorEnum) {
       ir.Expression innerLeft = left.left;
       ir.Expression middle = left.right;
       _handleLogicalExpression(
           innerLeft,
-          () => _handleLogicalExpression(middle, visitRight, brancher, operator,
-              _sourceInformationBuilder.buildBinary(middle)),
+          () => _handleLogicalExpression(middle, visitRight, brancher,
+              operatorEnum, _sourceInformationBuilder.buildBinary(middle)),
           brancher,
-          operator,
+          operatorEnum,
           sourceInformation);
     } else {
       brancher.handleLogicalBinary(
           () => left.accept(this), visitRight, sourceInformation,
-          isAnd: operator == '&&');
+          isAnd: operatorEnum == ir.LogicalExpressionOperator.AND);
     }
   }
 
@@ -3461,33 +3460,6 @@
   }
 
   @override
-  void visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    node.receiver.accept(this);
-    HInstruction receiver = pop();
-
-    // Fake direct call with a dynamic call.
-    // TODO(sra): Implement direct invocations properly.
-    _pushDynamicInvocation(
-        node,
-        _getStaticType(node.receiver),
-        _typeInferenceMap.receiverTypeOfDirectGet(node),
-        new Selector.getter(_elementMap.getMember(node.target).memberName),
-        <HInstruction>[receiver],
-        const <DartType>[],
-        _sourceInformationBuilder.buildGet(node));
-  }
-
-  @override
-  void visitDirectPropertySet(ir.DirectPropertySet node) {
-    throw new UnimplementedError('ir.DirectPropertySet');
-  }
-
-  @override
-  void visitDirectMethodInvocation(ir.DirectMethodInvocation node) {
-    throw new UnimplementedError('ir.DirectMethodInvocation');
-  }
-
-  @override
   void visitSuperPropertySet(ir.SuperPropertySet node) {
     SourceInformation sourceInformation =
         _sourceInformationBuilder.buildAssignment(node);
@@ -3933,9 +3905,8 @@
     } else if (isJSArrayTypedConstructor) {
       // TODO(sra): Instead of calling the identity-like factory constructor,
       // simply select the single argument.
+
       // Factory constructors take type parameters.
-      if (closedWorld.rtiNeed
-          .classNeedsTypeArguments(function.enclosingClass)) {}
       List<DartType> typeArguments =
           _getConstructorTypeArguments(function, invocation.arguments);
       // TODO(johnniwinther): Remove this when type arguments are passed to
@@ -3960,6 +3931,9 @@
       _addImplicitInstantiation(instanceType);
       _pushStaticInvocation(function, arguments, typeMask, typeArguments,
           sourceInformation: sourceInformation, instanceType: instanceType);
+
+      // TODO(sra): Special handling of List.filled, List.generate, List.of and
+      // other list constructors where 'growable' is false.
     }
 
     HInstruction newInstance = stack.last;
@@ -4103,10 +4077,44 @@
     }
   }
 
-  void _handleCreateInvocationMirror(ir.StaticInvocation invocation) {
-    ir.StringLiteral nameLiteral = invocation.arguments.positional[0];
-    String name = nameLiteral.value;
+  String _readStringLiteral(ir.Expression node) {
+    if (node is ir.StringLiteral) {
+      return node.value;
+    } else if (node is ir.ConstantExpression &&
+        node.constant is ir.StringConstant) {
+      ir.StringConstant constant = node.constant;
+      return constant.value;
+    } else {
+      return reporter.internalError(
+          _elementMap.getSpannable(targetElement, node),
+          "Unexpected string literal: "
+          "${node is ir.ConstantExpression ? node.constant : node}");
+    }
+  }
 
+  int _readIntLiteral(ir.Expression node) {
+    if (node is ir.IntLiteral) {
+      return node.value;
+    } else if (node is ir.ConstantExpression &&
+        node.constant is ir.IntConstant) {
+      ir.IntConstant constant = node.constant;
+      return constant.value;
+    } else if (node is ir.ConstantExpression &&
+        node.constant is ir.DoubleConstant) {
+      ir.DoubleConstant constant = node.constant;
+      assert(constant.value.floor() == constant.value,
+          "Unexpected int literal value ${constant.value}.");
+      return constant.value.toInt();
+    } else {
+      return reporter.internalError(
+          _elementMap.getSpannable(targetElement, node),
+          "Unexpected int literal: "
+          "${node is ir.ConstantExpression ? node.constant : node}");
+    }
+  }
+
+  void _handleCreateInvocationMirror(ir.StaticInvocation invocation) {
+    String name = _readStringLiteral(invocation.arguments.positional[0]);
     ir.ListLiteral typeArgumentsLiteral = invocation.arguments.positional[1];
     List<DartType> typeArguments =
         typeArgumentsLiteral.expressions.map((ir.Expression expression) {
@@ -4118,11 +4126,11 @@
         invocation.arguments.positional[2];
     ir.Expression namedArgumentsLiteral = invocation.arguments.positional[3];
     Map<String, ir.Expression> namedArguments = {};
-    ir.IntLiteral kindLiteral = invocation.arguments.positional[4];
+    int kind = _readIntLiteral(invocation.arguments.positional[4]);
 
     Name memberName = new Name(name, _currentFrame.member.library);
     Selector selector;
-    switch (kindLiteral.value) {
+    switch (kind) {
       case invocationMirrorGetterKind:
         selector = new Selector.getter(memberName);
         break;
@@ -4137,8 +4145,8 @@
         } else {
           if (namedArgumentsLiteral is ir.MapLiteral) {
             namedArgumentsLiteral.entries.forEach((ir.MapEntry entry) {
-              ir.StringLiteral key = entry.key;
-              namedArguments[key.value] = entry.value;
+              String key = _readStringLiteral(entry.key);
+              namedArguments[key] = entry.value;
             });
           } else if (namedArgumentsLiteral is ir.ConstantExpression &&
               namedArgumentsLiteral.constant is ir.MapConstant) {
@@ -4237,7 +4245,7 @@
       return '$count ${adjective}arguments';
     }
 
-    String name() => invocation.target.name.name;
+    String name() => invocation.target.name.text;
 
     ir.Arguments arguments = invocation.arguments;
     bool bad = false;
@@ -4648,11 +4656,7 @@
 
   bool _equivalentToMissingRti(InterfaceType type) {
     assert(type.element == _commonElements.jsArrayClass);
-    if (dartTypes.useNullSafety) {
-      return dartTypes.isStrongTopType(type.typeArguments.single);
-    } else {
-      return dartTypes.treatAsRawType(type);
-    }
+    return dartTypes.isStrongTopType(type.typeArguments.single);
   }
 
   void _handleForeignJs(ir.StaticInvocation invocation) {
@@ -4721,6 +4725,41 @@
       // It is acceptable for the type parameter to be broader than the
       // specified type.
     }
+
+    _maybeAddNullCheckOnJS(invocation);
+  }
+
+  /// If [invocation] is a `JS()` invocation in a web library and the static
+  /// type is non-nullable, add a check to make sure it isn't null.
+  void _maybeAddNullCheckOnJS(ir.StaticInvocation invocation) {
+    if (options.enableNativeNullAssertions &&
+        _isInWebLibrary(invocation) &&
+        closedWorld.dartTypes
+            .isNonNullableIfSound(_getStaticType(invocation).type)) {
+      HInstruction code = pop();
+      push(new HNullCheck(
+          code, _abstractValueDomain.excludeNull(code.instructionType),
+          sticky: true));
+    }
+  }
+
+  /// Returns true if [node] belongs to dart:html and related libraries.
+  bool _isInWebLibrary(ir.TreeNode node) {
+    if (node == null) return false;
+    bool isWebLibrary(Uri importUri) =>
+        importUri.scheme == 'dart' &&
+            (importUri.path == 'html' ||
+                importUri.path == 'svg' ||
+                importUri.path == 'indexed_db' ||
+                importUri.path == 'web_audio' ||
+                importUri.path == 'web_gl' ||
+                importUri.path == 'web_sql' ||
+                importUri.path == 'html_common') ||
+        // Mock web library path for testing.
+        importUri.path
+            .contains('native_null_assertions/js_invocations_in_web_library');
+    if (node is ir.Library) return isWebLibrary(node.importUri);
+    return _isInWebLibrary(node.parent);
   }
 
   void _handleJsStringConcat(ir.StaticInvocation invocation) {
@@ -4931,11 +4970,6 @@
           new js.Template(null, js.objectLiteral(parameterNameMap));
 
       var nativeBehavior = new NativeBehavior()..codeTemplate = codeTemplate;
-      if (options.trustJSInteropTypeAnnotations) {
-        InterfaceType thisType =
-            _elementEnvironment.getThisType(constructor.enclosingClass);
-        nativeBehavior.typesReturned.add(thisType);
-      }
       registry.registerNativeMethod(element);
       // TODO(efortuna): Source information.
       return new HForeignCode(
@@ -4955,10 +4989,9 @@
         ? _elementEnvironment.getThisType(element.enclosingClass)
         : _elementEnvironment.getFunctionType(element).returnType;
     // Native behavior effects here are similar to native/behavior.dart.
-    // The return type is dynamic if we don't trust js-interop type
+    // The return type is dynamic because we don't trust js-interop type
     // declarations.
-    nativeBehavior.typesReturned.add(
-        options.trustJSInteropTypeAnnotations ? type : dartTypes.dynamicType());
+    nativeBehavior.typesReturned.add(dartTypes.dynamicType());
 
     // The allocation effects include the declared type if it is native (which
     // includes js interop types).
@@ -4967,14 +5000,13 @@
       nativeBehavior.typesInstantiated.add(type);
     }
 
-    // It also includes any other JS interop type if we don't trust the
-    // annotation or if is declared too broad.
-    if (!options.trustJSInteropTypeAnnotations ||
-        type == _commonElements.objectType ||
-        type is DynamicType) {
-      nativeBehavior.typesInstantiated.add(_elementEnvironment
-          .getThisType(_commonElements.jsJavaScriptObjectClass));
-    }
+    // It also includes any other JS interop type. Technically, a JS interop API
+    // could return anything, so the sound thing to do would be to assume that
+    // anything that may come from JS as instantiated. In order to prevent the
+    // resulting code bloat (e.g. from `dart:html`), we unsoundly assume that
+    // only JS interop types are returned.
+    nativeBehavior.typesInstantiated.add(_elementEnvironment
+        .getThisType(_commonElements.jsJavaScriptObjectClass));
 
     AbstractValue instructionType =
         _typeInferenceMap.typeFromNativeBehavior(nativeBehavior, closedWorld);
@@ -6318,13 +6350,11 @@
 
     AbstractValue unwrappedType = kernelBuilder._typeInferenceMap
         .getReturnTypeOf(kernelBuilder._commonElements.exceptionUnwrapper);
-    if (kernelBuilder.options.useNullSafety) {
-      // Global type analysis does not currently understand that strong mode
-      // `Object` is not nullable, so is imprecise in the return type of the
-      // unwrapper, which leads to unnecessary checks for 'on Object'.
-      unwrappedType =
-          kernelBuilder._abstractValueDomain.excludeNull(unwrappedType);
-    }
+    // Global type analysis does not currently understand that strong mode
+    // `Object` is not nullable, so is imprecise in the return type of the
+    // unwrapper, which leads to unnecessary checks for 'on Object'.
+    unwrappedType =
+        kernelBuilder._abstractValueDomain.excludeNull(unwrappedType);
     kernelBuilder._pushStaticInvocation(
         kernelBuilder._commonElements.exceptionUnwrapper,
         [exception],
@@ -6844,6 +6874,11 @@
   visitConstantExpression(ir.ConstantExpression node) {
     registerRegularNode();
     registerReductiveNode();
+    ir.Constant constant = node.constant;
+    // Avoid copying long strings into call site.
+    if (constant is ir.StringConstant && isLongString(constant.value)) {
+      data.hasLongString = true;
+    }
   }
 
   @override
@@ -6987,12 +7022,16 @@
     node.visitChildren(this);
   }
 
+  /// Returns `true` if [value] is considered a long string for which copying
+  /// should be avoided.
+  bool isLongString(String value) => value.length > 14;
+
   @override
   visitStringLiteral(ir.StringLiteral node) {
     registerRegularNode();
     registerReductiveNode();
     // Avoid copying long strings into call site.
-    if (node.value.length > 14) {
+    if (isLongString(node.value)) {
       data.hasLongString = true;
     }
   }
@@ -7007,14 +7046,6 @@
   }
 
   @override
-  visitDirectPropertyGet(ir.DirectPropertyGet node) {
-    registerCall();
-    registerRegularNode();
-    registerReductiveNode();
-    visit(node.receiver);
-  }
-
-  @override
   visitPropertySet(ir.PropertySet node) {
     registerCall();
     registerRegularNode();
@@ -7025,15 +7056,6 @@
   }
 
   @override
-  visitDirectPropertySet(ir.DirectPropertySet node) {
-    registerCall();
-    registerRegularNode();
-    registerReductiveNode();
-    visit(node.receiver);
-    visit(node.value);
-  }
-
-  @override
   visitVariableGet(ir.VariableGet node) {
     if (discountParameters && node.variable.parent is ir.FunctionNode) return;
     registerRegularNode();
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index 811409f..6a551f89 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -4143,26 +4143,20 @@
   AbstractValue supersetType = checkedAbstractValue.abstractValue;
   AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);
 
-  if (!isCast && options.useNullSafety) {
+  bool _nullIs(DartType type) =>
+      dartTypes.isStrongTopType(type) ||
+      type is LegacyType &&
+          (type.baseType.isObject || type.baseType is NeverType) ||
+      type is NullableType ||
+      type is FutureOrType && _nullIs(type.typeArgument) ||
+      type.isNull;
+
+  if (!isCast) {
     if (expressionIsNull.isDefinitelyTrue) {
-      if (dartType.isObject) return AbstractBool.False;
-      if (dartTypes.isTopType(dartType) ||
-          dartType is NullableType ||
-          dartType.isNull) {
-        return AbstractBool.True;
-      }
-      if (dartType is TypeVariableType || dartType is FunctionTypeVariable) {
-        return AbstractBool.Maybe;
-      }
-      if (dartType is LegacyType) {
-        DartType baseType = dartType.baseType;
-        if (baseType is NeverType) return AbstractBool.True;
-        if (baseType is TypeVariableType || baseType is FunctionTypeVariable) {
-          return AbstractBool.Maybe;
-        }
-      }
-      return AbstractBool.False;
-    } else if (expressionIsNull.isPotentiallyTrue) {
+      if (dartType.containsFreeTypeVariables) return AbstractBool.Maybe;
+      return AbstractBool.trueOrFalse(_nullIs(dartType));
+    }
+    if (expressionIsNull.isPotentiallyTrue) {
       if (dartType.isObject) return AbstractBool.Maybe;
     }
   }
@@ -4231,8 +4225,7 @@
   AbstractBool isNullAsCheck = !options.useLegacySubtyping && isCast
       ? expressionIsNull
       : AbstractBool.False;
-  AbstractBool isNullIsTest =
-      options.useNullSafety && !isCast ? expressionIsNull : AbstractBool.False;
+  AbstractBool isNullIsTest = !isCast ? expressionIsNull : AbstractBool.False;
 
   AbstractBool unwrapAndCheck(DartType type) {
     if (dartTypes.isTopType(dartType)) return AbstractBool.True;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 5b4fb49..3718f17d 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -925,7 +925,7 @@
 
   HInstruction maybeAddNativeReturnNullCheck(
       HInstruction node, HInstruction replacement, FunctionEntity method) {
-    if (_options.enableNativeReturnNullAssertions) {
+    if (_options.enableNativeNullAssertions) {
       if (method.library.isNonNullableByDefault) {
         FunctionType type =
             _closedWorld.elementEnvironment.getFunctionType(method);
@@ -1308,37 +1308,61 @@
   @override
   HInstruction visitGetLength(HGetLength node) {
     HInstruction receiver = node.receiver;
-    if (_graph.allocatedFixedLists.contains(receiver)) {
-      // TODO(ngeoffray): checking if the second input is an integer
-      // should not be necessary but it currently makes it easier for
-      // other optimizations to reason about a fixed length constructor
-      // that we know takes an int.
-      if (receiver.inputs[0].isInteger(_abstractValueDomain).isDefinitelyTrue) {
-        return receiver.inputs[0];
-      }
-    } else if (receiver.isConstantList()) {
+
+    if (receiver.isConstantList()) {
       HConstant constantReceiver = receiver;
       ListConstantValue constant = constantReceiver.constant;
       return _graph.addConstantInt(constant.length, _closedWorld);
-    } else if (receiver.isConstantString()) {
+    }
+
+    if (receiver.isConstantString()) {
       HConstant constantReceiver = receiver;
       StringConstantValue constant = constantReceiver.constant;
       return _graph.addConstantInt(constant.length, _closedWorld);
-    } else {
-      AbstractValue type = receiver.instructionType;
-      if (_abstractValueDomain.isContainer(type) &&
-          _abstractValueDomain.getContainerLength(type) != null) {
-        HInstruction constant = _graph.addConstantInt(
-            _abstractValueDomain.getContainerLength(type), _closedWorld);
-        if (_abstractValueDomain.isNull(type).isPotentiallyTrue) {
+    }
+
+    AbstractValue receiverType = receiver.instructionType;
+    if (_abstractValueDomain.isContainer(receiverType)) {
+      int /*?*/ length = _abstractValueDomain.getContainerLength(receiverType);
+      if (length != null) {
+        HInstruction constant = _graph.addConstantInt(length, _closedWorld);
+        if (_abstractValueDomain.isNull(receiverType).isPotentiallyTrue) {
           // If the container can be null, we update all uses of the length
           // access to use the constant instead, but keep the length access in
           // the graph, to ensure we still have a null check.
           node.block.rewrite(node, constant);
           return node;
-        } else {
-          return constant;
         }
+        return constant;
+      }
+    }
+
+    // Can we find the length as an input to an allocation?
+    HInstruction potentialAllocation = receiver;
+    if (receiver is HInvokeStatic &&
+        receiver.element == commonElements.setRuntimeTypeInfo) {
+      // Look through `setRuntimeTypeInfo(new Array(), ...)`
+      potentialAllocation = receiver.inputs.first;
+    }
+    if (_graph.allocatedFixedLists.contains(potentialAllocation)) {
+      // TODO(sra): How do we keep this working if we lower/inline the receiver
+      // in an optimization?
+
+      HInstruction lengthInput = potentialAllocation.inputs.first;
+
+      // We don't expect a non-integer first input to the fixed-size allocation,
+      // but checking the input is an integer ensures we do not replace a
+      // HGetlength with a reference to something with a type that will confuse
+      // bounds check eliminiation.
+      if (lengthInput.isInteger(_abstractValueDomain).isDefinitelyTrue) {
+        // TODO(sra). HGetLength may have a better type than [lengthInput] as
+        // the allocation may throw on an out-of-range input. Typically the
+        // input is an unconstrained `int` and the length is non-negative. We
+        // may have done some optimizations with the better type that we won't
+        // be able to do with the broader type of [lengthInput].  We should
+        // insert a HTypeKnown witnessed by the allocation to narrow the
+        // lengthInput.
+        return lengthInput;
       }
     }
 
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index e12559c..39140be 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -111,7 +111,7 @@
     /// however dart2js moves the null check to the callee for performance
     /// reasons. As a result the body cannot trust or check that the type is not
     /// nullable.
-    if (builder.options.useNullSafety && memberContext.name == '==') {
+    if (memberContext.name == '==') {
       type = _closedWorld.dartTypes.nullableType(type);
     }
     HInstruction trusted = _trustType(original, type);
diff --git a/pkg/compiler/test/analyses/analysis_helper.dart b/pkg/compiler/test/analyses/analysis_helper.dart
index 90a11a2..eee894d 100644
--- a/pkg/compiler/test/analyses/analysis_helper.dart
+++ b/pkg/compiler/test/analyses/analysis_helper.dart
@@ -14,10 +14,10 @@
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/diagnostics/messages.dart';
 import 'package:compiler/src/diagnostics/source_span.dart';
+import 'package:compiler/src/ir/constants.dart';
 import 'package:compiler/src/ir/scope.dart';
 import 'package:compiler/src/ir/static_type.dart';
 import 'package:compiler/src/ir/util.dart';
-import 'package:compiler/src/kernel/dart2js_target.dart';
 import 'package:compiler/src/kernel/loader.dart';
 import 'package:expect/expect.dart';
 import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
@@ -75,21 +75,21 @@
   @override
   VariableScopeModel variableScopeModel;
 
-  ir.ConstantEvaluator _constantEvaluator;
+  Dart2jsConstantEvaluator _constantEvaluator;
 
   @override
   ir.StaticTypeContext staticTypeContext;
 
   StaticTypeVisitorBase(
-      ir.Component component, ir.ClassHierarchy classHierarchy)
-      : super(
+      ir.Component component, ir.ClassHierarchy classHierarchy,
+      {ir.EvaluationMode evaluationMode})
+      : assert(evaluationMode != null),
+        super(
             new ir.TypeEnvironment(new ir.CoreTypes(component), classHierarchy),
             classHierarchy) {
-    _constantEvaluator = new ir.ConstantEvaluator(
-        const Dart2jsConstantsBackend(supportsUnevaluatedConstants: true),
-        const {},
-        typeEnvironment,
-        const ir.SimpleErrorReporter());
+    _constantEvaluator = new Dart2jsConstantEvaluator(
+        typeEnvironment, const ir.SimpleErrorReporter().report,
+        evaluationMode: evaluationMode);
   }
 
   @override
@@ -149,7 +149,8 @@
   DynamicVisitor(this.reporter, this.component, this._allowedListPath,
       this.analyzedUrisFilter)
       : super(component,
-            new ir.ClassHierarchy(component, new ir.CoreTypes(component)));
+            new ir.ClassHierarchy(component, new ir.CoreTypes(component)),
+            evaluationMode: ir.EvaluationMode.weak);
 
   void run({bool verbose = false, bool generate = false}) {
     if (!generate && _allowedListPath != null) {
diff --git a/pkg/compiler/test/analyses/api_allowed.json b/pkg/compiler/test/analyses/api_allowed.json
index e303a89..241f168 100644
--- a/pkg/compiler/test/analyses/api_allowed.json
+++ b/pkg/compiler/test/analyses/api_allowed.json
@@ -109,16 +109,7 @@
     "Dynamic access of 'dart.io::_path'.": 1,
     "Dynamic access of 'pid'.": 1,
     "Dynamic access of 'dart.io::_arguments'.": 1,
-    "Dynamic access of 'dart.io::_workingDirectory'.": 2,
-    "Dynamic access of 'isListening'.": 3,
-    "Dynamic access of 'address'.": 4,
-    "Dynamic access of 'host'.": 5,
-    "Dynamic access of 'port'.": 3,
-    "Dynamic access of 'remoteAddress'.": 2,
-    "Dynamic access of 'remotePort'.": 2,
-    "Dynamic access of 'isTcp'.": 1,
-    "Dynamic access of 'type'.": 1,
-    "Dynamic access of 'name'.": 1
+    "Dynamic access of 'dart.io::_workingDirectory'.": 2
   },
   "org-dartlang-sdk:///lib/io/link.dart": {
     "Dynamic invocation of '[]'.": 3
diff --git a/pkg/compiler/test/analyses/static_type_visitor_test.dart b/pkg/compiler/test/analyses/static_type_visitor_test.dart
index 9fb7a2b..72b7143 100644
--- a/pkg/compiler/test/analyses/static_type_visitor_test.dart
+++ b/pkg/compiler/test/analyses/static_type_visitor_test.dart
@@ -12,6 +12,7 @@
 import 'package:kernel/class_hierarchy.dart' as ir;
 import 'package:kernel/core_types.dart' as ir;
 import 'package:kernel/type_environment.dart' as ir;
+import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
 
 import '../helpers/memory_compiler.dart';
 import 'analysis_helper.dart';
@@ -35,7 +36,8 @@
 class Visitor extends StaticTypeVisitorBase {
   Visitor(ir.Component component)
       : super(component,
-            new ir.ClassHierarchy(component, new ir.CoreTypes(component)));
+            new ir.ClassHierarchy(component, new ir.CoreTypes(component)),
+            evaluationMode: ir.EvaluationMode.weak);
 
   ir.DartType getStaticType(ir.Expression node) {
     if (typeEnvironment == null) {
diff --git a/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart b/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
index 284a1f5..a7fca88 100644
--- a/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
+++ b/pkg/compiler/test/deferred/dont_inline_deferred_constants_test.dart
@@ -18,10 +18,7 @@
       'DeferredGlobalConstant(StringConstant("string1"))': {'lib1'},
       'DeferredGlobalConstant(StringConstant("string2"))': {'lib1'},
       // "string4" is shared between lib1 and lib2, but it can be inlined.
-      'DeferredGlobalConstant(StringConstant("string4"))':
-          // TODO(johnniwinther): Should we inline CFE constants within deferred
-          // library boundaries?
-          {'lib12'},
+      'DeferredGlobalConstant(StringConstant("string4"))': {},
       // C(1) is shared between main, lib1 and lib2. Test that lib1 and lib2
       // each has a reference to it. It is defined in the main output file.
       'ConstructedConstant(C(p=IntConstant(1)))': {'main'},
diff --git a/pkg/compiler/test/deferred/not_in_main_test.dart b/pkg/compiler/test/deferred/not_in_main_test.dart
index 9550547..11e92a3 100644
--- a/pkg/compiler/test/deferred/not_in_main_test.dart
+++ b/pkg/compiler/test/deferred/not_in_main_test.dart
@@ -156,7 +156,7 @@
 typedef void F(x);
 
 main() {
-  print(foo is F);
+  print(getFoo() is F);
   def.loadLibrary().then((_) {
     def.toto();
   });
@@ -171,6 +171,7 @@
 class A {}
 class B extends A {}
 foo(B b) => null;
+getFoo() => foo;
 """,
 };
 
@@ -207,7 +208,8 @@
 import 'shared.dart';
 
 main() {
-  print(5 is A);
+  var v = 5;
+  print(v is A);
   def.loadLibrary().then((_) {
     def.toto();
   });
diff --git a/pkg/compiler/test/deferred_loading/data/basic_deferred/lib.dart b/pkg/compiler/test/deferred_loading/data/basic_deferred/lib.dart
index 3120bea..88ba170 100644
--- a/pkg/compiler/test/deferred_loading/data/basic_deferred/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/basic_deferred/lib.dart
@@ -4,12 +4,12 @@
 
 // @dart = 2.7
 
-/*member: defaultArg:OutputUnit(1, {lib})*/
+/*member: defaultArg:member_unit=1{lib}*/
 defaultArg() => "";
 
 /*member: funky:
- OutputUnit(1, {lib}),
- constants=[FunctionConstant(defaultArg)=OutputUnit(1, {lib})]
+ constants=[FunctionConstant(defaultArg)=1{lib}],
+ member_unit=1{lib}
 */
 funky([x = defaultArg]) => x();
 
diff --git a/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart b/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
index 11d445d..ca84a9f 100644
--- a/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/basic_deferred/main.dart
@@ -7,9 +7,9 @@
 import 'lib.dart' deferred as lib;
 
 /*member: main:
- OutputUnit(main, {}),
- constants=[FunctionConstant(funky)=OutputUnit(1, {lib})]
+ constants=[FunctionConstant(funky)=1{lib}],
+ member_unit=main{}
 */
-main() => lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+main() => lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
       (lib.funky)();
     });
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
index faac240..f41bc37 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_class/lib.dart
@@ -8,12 +8,15 @@
 
 library deferred_class_library;
 
-/*class: MyClass:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: MyClass:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class MyClass {
-  /*member: MyClass.:OutputUnit(1, {lib})*/
+  /*member: MyClass.:member_unit=1{lib}*/
   const MyClass();
 
-  /*member: MyClass.foo:OutputUnit(1, {lib})*/
+  /*member: MyClass.foo:member_unit=1{lib}*/
   foo(x) {
     print('MyClass.foo($x)');
     return (x - 3) ~/ 2;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
index 90fd81f..bb45d8c 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_class/main.dart
@@ -6,9 +6,9 @@
 
 import 'lib.dart' deferred as lib;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     return new lib.MyClass().foo(87);
   });
 }
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
index 5d63ed2..8351313 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant1/lib3.dart
@@ -6,9 +6,12 @@
 
 library deferred_constants1_lib3;
 
-/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
+/*class: C:
+ class_unit=main{},
+ type_unit=main{}
+*/
 class C {
-  /*member: C.value:OutputUnit(main, {})*/
+  /*member: C.value:member_unit=main{}*/
   final value;
 
   const C(this.value);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
index 0f40d1c..5a1c77d 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant1/main.dart
@@ -8,18 +8,18 @@
 import 'lib2.dart' deferred as lib2;
 
 /*member: main:
- OutputUnit(main, {}),
  constants=[
-  ConstructedConstant(C(value=ConstructedConstant(C(value=IntConstant(7)))))=OutputUnit(1, {lib2}),
-  ConstructedConstant(C(value=IntConstant(1)))=OutputUnit(main, {}),
-  ConstructedConstant(C(value=IntConstant(2)))=OutputUnit(1, {lib2}),
-  ConstructedConstant(C(value=IntConstant(4)))=OutputUnit(main, {}),
-  ConstructedConstant(C(value=IntConstant(5)))=OutputUnit(main, {})]
+  ConstructedConstant(C(value=ConstructedConstant(C(value=IntConstant(7)))))=1{lib2},
+  ConstructedConstant(C(value=IntConstant(1)))=main{},
+  ConstructedConstant(C(value=IntConstant(2)))=1{lib2},
+  ConstructedConstant(C(value=IntConstant(4)))=main{},
+  ConstructedConstant(C(value=IntConstant(5)))=main{}],
+ member_unit=main{}
 */
 main() async {
   C1.value;
   print(const C(4));
-  /*OutputUnit(main, {})*/ () => print(const C(5));
+  /*closure_unit=main{}*/ () => print(const C(5));
   await lib2.loadLibrary();
   print(lib2.C2.value);
   print(lib2.C3.value);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
index 9d06cea..da8377c 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant2/lib.dart
@@ -6,18 +6,21 @@
 
 library deferred_constants2_lib;
 
-/*class: Constant:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: Constant:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class Constant {
-  /*member: Constant.value:OutputUnit(1, {lib})*/
+  /*member: Constant.value:member_unit=1{lib}*/
   final value;
 
   const Constant(this.value);
 
-  /*member: Constant.==:OutputUnit(1, {lib})*/
+  /*member: Constant.==:member_unit=1{lib}*/
   @override
   operator ==(other) => other is Constant && value == other.value;
 
-  /*member: Constant.hashCode:OutputUnit(1, {lib})*/
+  /*member: Constant.hashCode:member_unit=1{lib}*/
   @override
   get hashCode => 0;
 }
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
index a35addc..71a715b 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant2/main.dart
@@ -9,12 +9,11 @@
 import 'lib.dart' deferred as lib;
 
 /*member: main:
- OutputUnit(main, {}),
- constants=[
-  ConstructedConstant(Constant(value=IntConstant(499)))=OutputUnit(1, {lib})]
+ constants=[ConstructedConstant(Constant(value=IntConstant(499)))=1{lib}],
+ member_unit=main{}
 */
 main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     Expect.equals(499, lib.C1.value);
   });
 }
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib1.dart
index 061d9d1..54f922e 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib1.dart
@@ -12,12 +12,12 @@
 const c3 = const C(3);
 
 /*member: m1:
- OutputUnit(1, {l1}),
  constants=[
-  ConstructedConstant(C(x=IntConstant(1)))=OutputUnit(main, {}),
-  ConstructedConstant(C(x=IntConstant(2)))=OutputUnit(1, {l1}),
-  ConstructedConstant(C(x=IntConstant(3)))=OutputUnit(1, {l1}),
-  ConstructedConstant(C(x=IntConstant(4)))=OutputUnit(2, {l2})]
+  ConstructedConstant(C(x=IntConstant(1)))=main{},
+  ConstructedConstant(C(x=IntConstant(2)))=1{l1},
+  ConstructedConstant(C(x=IntConstant(3)))=1{l1},
+  ConstructedConstant(C(x=IntConstant(4)))=2{l2}],
+ member_unit=1{l1}
 */
 m1() async {
   print(c2);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib2.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib2.dart
index 71db665..51392c1 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/lib2.dart
@@ -13,11 +13,11 @@
 const c5 = const C(5);
 
 /*member: m2:
- OutputUnit(2, {l2}),
  constants=[
-  ConstructedConstant(C(x=IntConstant(1)))=OutputUnit(main, {}),
-  ConstructedConstant(C(x=IntConstant(4)))=OutputUnit(2, {l2}),
-  ConstructedConstant(C(x=IntConstant(5)))=OutputUnit(2, {l2})]
+  ConstructedConstant(C(x=IntConstant(1)))=main{},
+  ConstructedConstant(C(x=IntConstant(4)))=2{l2},
+  ConstructedConstant(C(x=IntConstant(5)))=2{l2}],
+ member_unit=2{l2}
 */
 m2() async {
   print(c3);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
index da731a5..5bc723e 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/main.dart
@@ -10,10 +10,10 @@
 const c1 = const C(1);
 
 /*member: main:
- OutputUnit(main, {}),
  constants=[
-  ConstructedConstant(C(x=IntConstant(1)))=OutputUnit(main, {}),
-  ConstructedConstant(C(x=IntConstant(2)))=OutputUnit(1, {l1})]
+  ConstructedConstant(C(x=IntConstant(1)))=main{},
+  ConstructedConstant(C(x=IntConstant(2)))=1{l1}],
+ member_unit=main{}
 */
 main() async {
   print(c1.x);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart b/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
index 57c860b..60a3657 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_constant3/shared.dart
@@ -4,10 +4,13 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
+/*class: C:
+ class_unit=main{},
+ type_unit=main{}
+*/
 class C {
   const C(this.x);
 
-  /*member: C.x:OutputUnit(main, {})*/
+  /*member: C.x:member_unit=main{}*/
   final x;
 }
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/lib.dart
index 8cab462..c26bea6 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/lib.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*member: foo:OutputUnit(1, {lib})*/
+/*member: foo:member_unit=1{lib}*/
 foo() {
   return "loaded";
 }
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
index 67201ca..167b145 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_fail_and_retry/main.dart
@@ -11,7 +11,7 @@
 import "package:async_helper/async_helper.dart";
 import "dart:js" as js;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
   // We patch document.body.appendChild to change the script src on first
   // invocation.
@@ -36,14 +36,14 @@
   ]);
 
   asyncStart();
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     Expect.fail("Library should not have loaded");
-  }, onError: /*OutputUnit(main, {})*/ (error) {
-    lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  }, onError: /*closure_unit=main{}*/ (error) {
+    lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
       Expect.equals("loaded", lib.foo());
-    }, onError: /*OutputUnit(main, {})*/ (error) {
+    }, onError: /*closure_unit=main{}*/ (error) {
       Expect.fail("Library should have loaded this time");
-    }).whenComplete(/*OutputUnit(main, {})*/ () {
+    }).whenComplete(/*closure_unit=main{}*/ () {
       asyncEnd();
     });
   });
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_function/lib.dart b/pkg/compiler/test/deferred_loading/data/deferred_function/lib.dart
index 8406ca6..efaf766 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_function/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_function/lib.dart
@@ -8,7 +8,7 @@
 
 library deferred_function_library;
 
-/*member: foo:OutputUnit(1, {lib})*/
+/*member: foo:member_unit=1{lib}*/
 foo(x) {
   print('foo($x)');
   return 42;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
index cf774ed..3c99316 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_function/main.dart
@@ -10,16 +10,16 @@
 import 'lib.dart' deferred as lib;
 
 /*member: readFoo:
- OutputUnit(main, {}),
- constants=[FunctionConstant(foo)=OutputUnit(1, {lib})]
+ constants=[FunctionConstant(foo)=1{lib}],
+ member_unit=main{}
 */
 readFoo() {
   return lib.foo;
 }
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     lib.foo('b');
     readFoo();
   });
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
index a4170a9..55ced68 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/deferred_overlapping_lib3.dart
@@ -4,6 +4,9 @@
 
 // @dart = 2.7
 
-/*class: C3:OutputUnit(1, {lib1, lib2}), type=OutputUnit(1, {lib1, lib2})*/
-/*member: C3.:OutputUnit(1, {lib1, lib2})*/
+/*class: C3:
+ class_unit=1{lib1, lib2},
+ type_unit=1{lib1, lib2}
+*/
+/*member: C3.:member_unit=1{lib1, lib2}*/
 class C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
index 1f1586c..ca698b0 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib1.dart
@@ -6,6 +6,9 @@
 
 import "deferred_overlapping_lib3.dart";
 
-/*class: C1:OutputUnit(2, {lib1}), type=OutputUnit(2, {lib1})*/
-/*member: C1.:OutputUnit(2, {lib1})*/
+/*class: C1:
+ class_unit=2{lib1},
+ type_unit=2{lib1}
+*/
+/*member: C1.:member_unit=2{lib1}*/
 class C1 extends C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
index 748d2cd..449b2c4 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/lib2.dart
@@ -6,6 +6,9 @@
 
 import "deferred_overlapping_lib3.dart";
 
-/*class: C2:OutputUnit(3, {lib2}), type=OutputUnit(3, {lib2})*/
-/*member: C2.:OutputUnit(3, {lib2})*/
+/*class: C2:
+ class_unit=3{lib2},
+ type_unit=3{lib2}
+*/
+/*member: C2.:member_unit=3{lib2}*/
 class C2 extends C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
index b766437..782e177 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_overlapping/main.dart
@@ -8,11 +8,11 @@
 import 'lib2.dart' deferred as lib2;
 
 // lib1.C1 and lib2.C2 has a shared base class. It will go in its own hunk.
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 void main() {
-  lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib1.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     new lib1.C1();
-    lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+    lib2.loadLibrary().then(/*closure_unit=main{}*/ (_) {
       new lib2.C2();
     });
   });
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
index 0c7ae5a..d59813b 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/lib1.dart
@@ -4,15 +4,18 @@
 
 // @dart = 2.7
 
-/*class: M:none, type=OutputUnit(1, {lib})*/
+/*class: M:
+ class_unit=none,
+ type_unit=1{lib}
+*/
 class M {}
 
 typedef dynamic FF({M b});
 
 const table = const <int, FF>{1: f1, 2: f2};
 
-/*member: f1:OutputUnit(1, {lib})*/
+/*member: f1:member_unit=1{lib}*/
 dynamic f1({M b}) => null;
 
-/*member: f2:OutputUnit(1, {lib})*/
+/*member: f2:member_unit=1{lib}*/
 dynamic f2({M b}) => null;
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
index 9150c50..20bb44c 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typed_map/main.dart
@@ -6,7 +6,10 @@
 
 import 'lib1.dart' deferred as lib;
 
-/*member: main:OutputUnit(main, {}),constants=[MapConstant(<int*, dynamic Function({M* b})*>{IntConstant(1): FunctionConstant(f1), IntConstant(2): FunctionConstant(f2)})=OutputUnit(1, {lib})]*/
+/*member: main:
+ constants=[MapConstant(<int*, dynamic Function({M* b})*>{IntConstant(1): FunctionConstant(f1), IntConstant(2): FunctionConstant(f2)})=1{lib}],
+ member_unit=main{}
+*/
 main() async {
   await lib.loadLibrary();
   print(lib.table[1]);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart b/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
index e1a6bb8..b3181b4 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typedef/lib1.dart
@@ -6,12 +6,15 @@
 
 library deferred_typedef_lib1;
 
-/*class: C:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C {
-  /*member: C.a:OutputUnit(1, {lib1})*/
+  /*member: C.a:member_unit=1{lib1}*/
   final a;
 
-  /*member: C.b:OutputUnit(1, {lib1})*/
+  /*member: C.b:member_unit=1{lib1}*/
   final b;
 
   const C(this.a, this.b);
@@ -21,7 +24,7 @@
 
 typedef void MyF2();
 
-/*member: topLevelMethod:OutputUnit(1, {lib1})*/
+/*member: topLevelMethod:member_unit=1{lib1}*/
 topLevelMethod() {}
 
 const cA = const C(MyF1, topLevelMethod);
diff --git a/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart b/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
index a5bccc8..9c56b84 100644
--- a/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/deferred_typedef/main.dart
@@ -6,7 +6,12 @@
 
 import 'lib1.dart' deferred as lib1;
 
-/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(C(a=TypeConstant(void Function()),b=FunctionConstant(topLevelMethod)))=OutputUnit(1, {lib1}),TypeConstant(void Function())=OutputUnit(1, {lib1})]*/
+/*member: main:
+ constants=[
+  ConstructedConstant(C(a=TypeConstant(void Function()),b=FunctionConstant(topLevelMethod)))=1{lib1},
+  TypeConstant(void Function())=1{lib1}],
+ member_unit=main{}
+*/
 main() async {
   await lib1.loadLibrary();
   print(lib1.cA);
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
index 2fcc514..f22f054 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/exported_main.dart
@@ -9,29 +9,32 @@
 
 const c = "string3";
 
-/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
+/*class: C:
+ class_unit=main{},
+ type_unit=main{}
+*/
 class C {
-  /*member: C.p:OutputUnit(main, {})*/
+  /*member: C.p:member_unit=main{}*/
   final p;
 
   const C(this.p);
 }
 
-/*member: foo:OutputUnit(2, {lib1, lib2})*/
+/*member: foo:member_unit=2{lib1, lib2}*/
 foo() => print("main");
 
 /*member: main:
- OutputUnit(main, {}),
  constants=[
-  ConstructedConstant(C(p=IntConstant(1)))=OutputUnit(main, {}),
-  ConstructedConstant(C(p=IntConstant(1010)))=OutputUnit(1, {lib1}),
-  ConstructedConstant(C(p=IntConstant(2)))=OutputUnit(2, {lib1, lib2}),
-  ConstructedConstant(C(p=StringConstant("string1")))=OutputUnit(1, {lib1}),
-  ConstructedConstant(C(p=StringConstant("string2")))=OutputUnit(1, {lib1})]
+  ConstructedConstant(C(p=IntConstant(1)))=main{},
+  ConstructedConstant(C(p=IntConstant(1010)))=1{lib1},
+  ConstructedConstant(C(p=IntConstant(2)))=2{lib1, lib2},
+  ConstructedConstant(C(p=StringConstant("string1")))=1{lib1},
+  ConstructedConstant(C(p=StringConstant("string2")))=1{lib1}],
+ member_unit=main{}
 */
 void main() {
-  lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
-    lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib1.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+    lib2.loadLibrary().then(/*closure_unit=main{}*/ (_) {
       lib1.foo();
       lib2.foo();
       print(lib1.C1);
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
index c017966..a147c36 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib1.dart
@@ -15,7 +15,10 @@
 
 const C2b = const C(1010);
 
-/*class: D:none, type=none*/
+/*class: D:
+ class_unit=none,
+ type_unit=none
+*/
 class D {
   static const C3 = "string2";
 
@@ -28,7 +31,7 @@
 
 const C6 = const C(2);
 
-/*member: foo:OutputUnit(1, {lib1})*/
+/*member: foo:member_unit=1{lib1}*/
 foo() {
   print("lib1");
   main.foo();
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib2.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib2.dart
index cacae15..d421b89 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_constants/lib2.dart
@@ -13,7 +13,7 @@
 
 const C6 = const C(2);
 
-/*member: foo:OutputUnit(3, {lib2})*/
+/*member: foo:member_unit=3{lib2}*/
 foo() {
   print("lib2");
   main.foo();
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/lib.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/lib.dart
index 18fced0..ec89e79 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/lib.dart
@@ -4,8 +4,8 @@
 
 // @dart = 2.7
 
-/*member: finalVar:OutputUnit(1, {lib})*/
+/*member: finalVar:member_unit=1{lib}*/
 final finalVar = "string1";
 
-/*member: globalVar:OutputUnit(1, {lib})*/
+/*member: globalVar:member_unit=1{lib}*/
 var globalVar = "string2";
diff --git a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
index 22cbcb4..3a45b3e 100644
--- a/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/dont_inline_deferred_global/main.dart
@@ -6,9 +6,9 @@
 
 import 'lib.dart' deferred as lib;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 void main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     print(lib.finalVar);
     print(lib.globalVar);
     lib.globalVar = "foobar";
diff --git a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
index f305b51..ab4dc02 100644
--- a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/lib.dart
@@ -4,93 +4,135 @@
 
 // @dart = 2.7
 
-/*member: a:OutputUnit(1, {lib})*/
+/*member: a:member_unit=1{lib}*/
 a() => print("123");
 
-/*member: b:OutputUnit(1, {lib})*/
+/*member: b:member_unit=1{lib}*/
 b() => print("123");
 
-/*member: c:OutputUnit(1, {lib})*/
+/*member: c:member_unit=1{lib}*/
 c() => print("123");
 
-/*member: d:OutputUnit(1, {lib})*/
+/*member: d:member_unit=1{lib}*/
 d() => print("123");
 
-/*class: B:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: B:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class B {
-  /*member: B.:OutputUnit(1, {lib})*/
+  /*member: B.:member_unit=1{lib}*/
   B() {
     b();
   }
 }
 
-/*class: B2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: B2.:OutputUnit(1, {lib})*/
+/*class: B2:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: B2.:member_unit=1{lib}*/
 class B2 extends B {
   // No constructor creates a synthetic constructor that has an implicit
   // super-call.
 }
 
-/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: A:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class A {
-  /*member: A.:OutputUnit(1, {lib})*/
+  /*member: A.:member_unit=1{lib}*/
   A() {
     a();
   }
 }
 
-/*class: A2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: A2:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class A2 extends A {
   // Implicit super call.
-  /*member: A2.:OutputUnit(1, {lib})*/
+  /*member: A2.:member_unit=1{lib}*/
   A2();
 }
 
-/*class: C1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: C1:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class C1 {}
 
-/*class: C2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: C2:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class C2 {
-  /*member: C2.:OutputUnit(1, {lib})*/
+  /*member: C2.:member_unit=1{lib}*/
   C2() {
     c();
   }
 }
 
-/*class: C2p:none, type=none*/
+/*class: C2p:
+ class_unit=none,
+ type_unit=none
+*/
 class C2p {
   C2() {
     c();
   }
 }
 
-/*class: C3:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: C3.:OutputUnit(1, {lib})*/
+/*class: C3:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: C3.:member_unit=1{lib}*/
 class C3 extends C2 with C1 {
   // Implicit redirecting "super" call via mixin.
 }
 
-/*class: E:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: E:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class E {}
 
-/*class: F:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: F:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class F {}
 
-/*class: G:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: G.:OutputUnit(1, {lib})*/
+/*class: G:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: G.:member_unit=1{lib}*/
 class G extends C3 with C1, E, F {}
 
-/*class: D1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: D1:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class D1 {}
 
-/*class: D2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: D2:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class D2 {
-  /*member: D2.:OutputUnit(1, {lib})*/
+  /*member: D2.:member_unit=1{lib}*/
   D2(x) {
     d();
   }
 }
 
 // Implicit redirecting "super" call with a parameter via mixin.
-/*class: D3:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
+/*class: D3:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
 class D3 = D2 with D1;
diff --git a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
index fe41fa5..74cd88d 100644
--- a/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/follow_implicit_super_regression_test/main.dart
@@ -6,9 +6,9 @@
 
 import "lib.dart" deferred as lib;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 void main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     new lib.A2();
     new lib.B2();
     new lib.C3();
diff --git a/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart b/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
index d222767..aad0cf2 100644
--- a/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/future_or/lib2.dart
@@ -4,10 +4,13 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(1, {lib1}), type=OutputUnit(main, {})*/
+/*class: A:
+ class_unit=1{lib1},
+ type_unit=main{}
+*/
 class A {
   const A();
 
-  /*member: A.method:OutputUnit(1, {lib1})*/
+  /*member: A.method:member_unit=1{lib1}*/
   method() {}
 }
diff --git a/pkg/compiler/test/deferred_loading/data/future_or/main.dart b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
index ed02ff6..de44d54 100644
--- a/pkg/compiler/test/deferred_loading/data/future_or/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/future_or/main.dart
@@ -8,7 +8,10 @@
 import 'lib1.dart' deferred as lib1;
 import 'lib2.dart' as lib2;
 
-/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(A())=OutputUnit(1, {lib1})]*/
+/*member: main:
+ constants=[ConstructedConstant(A())=1{lib1}],
+ member_unit=main{}
+*/
 main() async {
   await lib1.loadLibrary();
   lib1.field is FutureOr<lib2.A>;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
index 433780c..59fba08 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation0/lib1.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(1, {b})*/
+/*member: getFoo:member_unit=1{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
-/*member: m:OutputUnit(1, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=1{b}],
+ member_unit=1{b}
+*/
 m(int x, {G<int> f: getFoo}) {
   print(f(x));
 }
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
index 0b94d3a..5da17d9 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation0/main.dart
@@ -6,12 +6,12 @@
 
 // Test instantiation used only in a deferred library.
 
-/*class: global#Instantiation:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
-/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation:class_unit=1{b},type_unit=1{b}*/
+/*class: global#Instantiation1:class_unit=1{b},type_unit=1{b}*/
 
 import 'lib1.dart' deferred as b;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   print(b.m(3));
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
index 433780c..59fba08 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/lib1.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(1, {b})*/
+/*member: getFoo:member_unit=1{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
-/*member: m:OutputUnit(1, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(1, {b})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=1{b}],
+ member_unit=1{b}
+*/
 m(int x, {G<int> f: getFoo}) {
   print(f(x));
 }
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
index 9c63363..faddc09 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/lib2.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(3, {c})*/
+/*member: getFoo:member_unit=3{c}*/
 T getFoo<T, S>(T v, S w) => v;
 
 typedef dynamic G<T, S>(T v, S w);
 
-/*member: m:OutputUnit(3, {c}),constants=[InstantiationConstant([int*, int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*, int*],FunctionConstant(getFoo))=3{c}],
+ member_unit=3{c}
+*/
 m(int x, int y, {G<int, int> f: getFoo}) {
   print(f(x, y));
 }
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
index 2e0e4ef..ae2c5a7 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation1/main.dart
@@ -7,14 +7,14 @@
 // Test instantiations with different type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(2, {b, c}), type=OutputUnit(2, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
-/*class: global#Instantiation2:OutputUnit(3, {c}), type=OutputUnit(3, {c})*/
+/*class: global#Instantiation:class_unit=2{b, c},type_unit=2{b, c}*/
+/*class: global#Instantiation1:class_unit=1{b},type_unit=1{b}*/
+/*class: global#Instantiation2:class_unit=3{c},type_unit=3{c}*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   await c.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
index 0f2e5f7..50dde94 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/lib1.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(2, {b})*/
+/*member: getFoo:member_unit=2{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
-/*member: m:OutputUnit(2, {b}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(2, {b})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=2{b}],
+ member_unit=2{b}
+*/
 m(int x, {G<int> f: getFoo}) {
   print(f(x));
 }
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
index 1d845e3..c7537c6 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/lib2.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(3, {c})*/
+/*member: getFoo:member_unit=3{c}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
-/*member: m:OutputUnit(3, {c}),constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=OutputUnit(3, {c})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=3{c}],
+ member_unit=3{c}
+*/
 m(int x, {G<int> f: getFoo}) {
   print(f(x));
 }
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
index 70dc5f6..3ff8f46 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation2/main.dart
@@ -7,13 +7,13 @@
 // Test instantiations with the same type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
+/*class: global#Instantiation:class_unit=1{b, c},type_unit=1{b, c}*/
+/*class: global#Instantiation1:class_unit=1{b, c},type_unit=1{b, c}*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   await c.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
index 7f641b8..a211ccb 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation3/lib1.dart
@@ -4,14 +4,14 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(1, {b})*/
+/*member: getFoo:member_unit=1{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
 /*member: m:
- OutputUnit(1, {b}),
- constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=1{b}],
+ member_unit=1{b}
 */
 m(int x, {G<int> f}) {
   f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
index 3cb4f5a..b0d3a8f 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation3/main.dart
@@ -6,14 +6,14 @@
 
 // Test instantiation used only in a deferred library.
 
-/*class: global#Instantiation:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
-/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
+/*class: global#Instantiation:class_unit=1{b},type_unit=1{b}*/
+/*class: global#Instantiation1:class_unit=1{b},type_unit=1{b}*/
 
-/*member: global#instantiate1:OutputUnit(1, {b})*/
+/*member: global#instantiate1:member_unit=1{b}*/
 
 import 'lib1.dart' deferred as b;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   print(b.m(3));
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
index 4359611..a211ccb 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/lib1.dart
@@ -4,12 +4,15 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(1, {b})*/
+/*member: getFoo:member_unit=1{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
-/*member: m:OutputUnit(1, {b}),constants=[FunctionConstant(getFoo)=OutputUnit(1, {b})]*/
+/*member: m:
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=1{b}],
+ member_unit=1{b}
+*/
 m(int x, {G<int> f}) {
   f ??= getFoo;
   print(f(x));
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
index b346bb4..ea8657c 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/lib2.dart
@@ -4,14 +4,14 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(3, {c})*/
+/*member: getFoo:member_unit=3{c}*/
 T getFoo<T, S>(T v, S w) => v;
 
 typedef dynamic G<T, S>(T v, S w);
 
 /*member: m:
- OutputUnit(3, {c}),
- constants=[FunctionConstant(getFoo)=OutputUnit(3, {c})]
+ constants=[InstantiationConstant([int*, int*],FunctionConstant(getFoo))=3{c}],
+ member_unit=3{c}
 */
 m(int x, int y, {G<int, int> f}) {
   f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
index 361d35a..34bf22a 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation4/main.dart
@@ -7,17 +7,17 @@
 // Test instantiations with different type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(2, {b, c}), type=OutputUnit(2, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b}), type=OutputUnit(1, {b})*/
-/*class: global#Instantiation2:OutputUnit(3, {c}), type=OutputUnit(3, {c})*/
+/*class: global#Instantiation:class_unit=2{b, c},type_unit=2{b, c}*/
+/*class: global#Instantiation1:class_unit=1{b},type_unit=1{b}*/
+/*class: global#Instantiation2:class_unit=3{c},type_unit=3{c}*/
 
-/*member: global#instantiate1:OutputUnit(1, {b})*/
-/*member: global#instantiate2:OutputUnit(3, {c})*/
+/*member: global#instantiate1:member_unit=1{b}*/
+/*member: global#instantiate2:member_unit=3{c}*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   await c.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
index 76cebb1..506a6b3 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/lib1.dart
@@ -4,14 +4,14 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(2, {b})*/
+/*member: getFoo:member_unit=2{b}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
 /*member: m:
- OutputUnit(2, {b}),
- constants=[FunctionConstant(getFoo)=OutputUnit(2, {b})]
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=2{b}],
+ member_unit=2{b}
 */
 m(int x, {G<int> f}) {
   f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
index ee8d5ab..8a5d498 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/lib2.dart
@@ -4,14 +4,14 @@
 
 // @dart = 2.7
 
-/*member: getFoo:OutputUnit(3, {c})*/
+/*member: getFoo:member_unit=3{c}*/
 T getFoo<T>(T v) => v;
 
 typedef dynamic G<T>(T v);
 
 /*member: m:
- OutputUnit(3, {c}),
- constants=[FunctionConstant(getFoo)=OutputUnit(3, {c})]
+ constants=[InstantiationConstant([int*],FunctionConstant(getFoo))=3{c}],
+ member_unit=3{c}
 */
 m(int x, {G<int> f}) {
   f ??= getFoo;
diff --git a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
index 9f270b1..5612525 100644
--- a/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/instantiation5/main.dart
@@ -7,15 +7,15 @@
 // Test instantiations with the same type argument count used only in two
 // deferred libraries.
 
-/*class: global#Instantiation:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
-/*class: global#Instantiation1:OutputUnit(1, {b, c}), type=OutputUnit(1, {b, c})*/
+/*class: global#Instantiation:class_unit=1{b, c},type_unit=1{b, c}*/
+/*class: global#Instantiation1:class_unit=1{b, c},type_unit=1{b, c}*/
 
-/*member: global#instantiate1:OutputUnit(1, {b, c})*/
+/*member: global#instantiate1:member_unit=1{b, c}*/
 
 import 'lib1.dart' deferred as b;
 import 'lib2.dart' deferred as c;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await b.loadLibrary();
   await c.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
index 95c9a26..d20e094 100644
--- a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/lib.dart
@@ -4,38 +4,62 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: A.:OutputUnit(1, {lib})*/
+/*class: A:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: A.:member_unit=1{lib}*/
 class A {}
 
-/*class: I:none, type=OutputUnit(1, {lib})*/
+/*class: I:
+ class_unit=none,
+ type_unit=1{lib}
+*/
 class I<T> {}
 
-/*class: J:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: J.:OutputUnit(1, {lib})*/
+/*class: J:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: J.:member_unit=1{lib}*/
 class J<T> {}
 
 // C needs to include "N", otherwise checking for `is I<A>` will likely cause
 // problems
-/*class: C:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: C.:OutputUnit(1, {lib})*/
+/*class: C:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: C.:member_unit=1{lib}*/
 class C extends A implements I<N> {}
 
-/*class: C1:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: C1.:OutputUnit(1, {lib})*/
+/*class: C1:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: C1.:member_unit=1{lib}*/
 class C1 extends J<M> implements A {}
 
-/*class: C2:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: C2.:OutputUnit(1, {lib})*/
+/*class: C2:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: C2.:member_unit=1{lib}*/
 class C2 extends J<M> implements I<N> {}
 
-/*class: N:none, type=OutputUnit(1, {lib})*/
+/*class: N:
+ class_unit=none,
+ type_unit=1{lib}
+*/
 class N extends A {}
 
-/*class: M:none, type=OutputUnit(1, {lib})*/
+/*class: M:
+ class_unit=none,
+ type_unit=1{lib}
+*/
 class M extends A {}
 
-/*member: doCheck1:OutputUnit(1, {lib})*/
+/*member: doCheck1:member_unit=1{lib}*/
 doCheck1(x) => x is I<A>;
-/*member: doCheck2:OutputUnit(1, {lib})*/
+/*member: doCheck2:member_unit=1{lib}*/
 doCheck2(x) => x is J<A>;
diff --git a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
index d9075e9..d4b10fb 100644
--- a/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/inteface_type_variable/main.dart
@@ -11,9 +11,9 @@
 ///
 /// If not, we may include it in the main unit and may not see that the base
 /// class is not added to the main unit.
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     lib.doCheck1(dontInline(new lib.C()));
     lib.doCheck1(dontInline(new lib.C1()));
     lib.doCheck1(dontInline(new lib.C2()));
@@ -24,5 +24,5 @@
 }
 
 @pragma('dart2js:noInline')
-/*member: dontInline:OutputUnit(main, {})*/
+/*member: dontInline:member_unit=main{}*/
 dontInline(x) => x;
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
index 3e9dbdf..4cd9f15 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/lib.dart
@@ -4,24 +4,27 @@
 
 // @dart = 2.7
 
-/*class: Foo:OutputUnit(1, {libB}), type=OutputUnit(3, {libA, libB, libC})*/
+/*class: Foo:
+ class_unit=1{libB},
+ type_unit=3{libA, libB, libC}
+*/
 class Foo {
-  /*member: Foo.x:OutputUnit(1, {libB})*/
+  /*member: Foo.x:member_unit=1{libB}*/
   int x;
-  /*member: Foo.:OutputUnit(1, {libB})*/
+  /*member: Foo.:member_unit=1{libB}*/
   Foo() {
     x = DateTime.now().millisecond;
   }
-  /*member: Foo.method:OutputUnit(1, {libB})*/
+  /*member: Foo.method:member_unit=1{libB}*/
   int method() => x;
 }
 
-/*member: isFoo:OutputUnit(3, {libA, libB, libC})*/
+/*member: isFoo:member_unit=3{libA, libB, libC}*/
 bool isFoo(o) {
   return o is Foo;
 }
 
-/*member: callFooMethod:OutputUnit(1, {libB})*/
+/*member: callFooMethod:member_unit=1{libB}*/
 int callFooMethod() {
   return Foo().method();
 }
@@ -29,58 +32,94 @@
 typedef int FunFoo(Foo a);
 typedef int FunFunFoo(FunFoo b, int c);
 
-/*member: isFunFunFoo:OutputUnit(3, {libA, libB, libC})*/
+/*member: isFunFunFoo:member_unit=3{libA, libB, libC}*/
 bool isFunFunFoo(o) {
   return o is FunFunFoo;
 }
 
-/*class: Aoo:none, type=OutputUnit(2, {libC})*/
+/*class: Aoo:
+ class_unit=none,
+ type_unit=2{libC}
+*/
 class Aoo<T> {}
 
-/*class: Boo:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*class: Boo:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
 class Boo<T> implements Aoo<T> {}
 
-/*class: Coo:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
-/*member: Coo.:OutputUnit(2, {libC})*/
+/*class: Coo:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
+/*member: Coo.:member_unit=2{libC}*/
 class Coo<T> {}
 
-/*class: Doo:OutputUnit(2, {libC}), type=OutputUnit(5, {libB, libC})*/
-/*member: Doo.:OutputUnit(2, {libC})*/
+/*class: Doo:
+ class_unit=2{libC},
+ type_unit=5{libB, libC}
+*/
+/*member: Doo.:member_unit=2{libC}*/
 class Doo<T> extends Coo<T> with Boo<T> {}
 
-/*member: createDooFunFunFoo:OutputUnit(2, {libC})*/
+/*member: createDooFunFunFoo:member_unit=2{libC}*/
 createDooFunFunFoo() => Doo<FunFunFoo>();
 
-/*class: B:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
-/*member: B.:OutputUnit(2, {libC})*/
+/*class: B:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
+/*member: B.:member_unit=2{libC}*/
 class B {}
 
-/*class: B2:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
-/*member: B2.:OutputUnit(2, {libC})*/
+/*class: B2:
+ class_unit=2{libC},
+ type_unit=4{libA, libC}
+*/
+/*member: B2.:member_unit=2{libC}*/
 class B2 extends B {}
 
-/*class: C1:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*class: C1:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
 class C1 {}
 
-/*class: C2:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
-/*member: C2.:OutputUnit(2, {libC})*/
+/*class: C2:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
+/*member: C2.:member_unit=2{libC}*/
 class C2 {}
 
-/*class: C3:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
-/*member: C3.:OutputUnit(2, {libC})*/
+/*class: C3:
+ class_unit=2{libC},
+ type_unit=4{libA, libC}
+*/
+/*member: C3.:member_unit=2{libC}*/
 class C3 extends C2 with C1 {}
 
-/*class: D1:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
+/*class: D1:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
 class D1 {}
 
-/*class: D2:OutputUnit(2, {libC}), type=OutputUnit(2, {libC})*/
-/*member: D2.:OutputUnit(2, {libC})*/
+/*class: D2:
+ class_unit=2{libC},
+ type_unit=2{libC}
+*/
+/*member: D2.:member_unit=2{libC}*/
 class D2 {}
 
-/*class: D3:OutputUnit(2, {libC}), type=OutputUnit(4, {libA, libC})*/
+/*class: D3:
+ class_unit=2{libC},
+ type_unit=4{libA, libC}
+*/
 class D3 = D2 with D1;
 
-/*member: isMega:OutputUnit(6, {libA})*/
+/*member: isMega:member_unit=6{libA}*/
 bool isMega(o) {
   return o is B2 || o is C3 || o is D3;
 }
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
index 5601618..447ec58 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/liba.dart
@@ -6,11 +6,11 @@
 
 import 'lib.dart' as lib;
 
-/*member: isFoo:OutputUnit(6, {libA})*/
+/*member: isFoo:member_unit=6{libA}*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(6, {libA})*/
+/*member: isFunFunFoo:member_unit=6{libA}*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: isMega:OutputUnit(6, {libA})*/
+/*member: isMega:member_unit=6{libA}*/
 bool isMega(o) => lib.isMega(o);
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
index 2b28333..20c2423 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/libb.dart
@@ -6,14 +6,14 @@
 
 import 'lib.dart' as lib;
 
-/*member: callFooMethod:OutputUnit(1, {libB})*/
+/*member: callFooMethod:member_unit=1{libB}*/
 int callFooMethod() => lib.callFooMethod();
 
-/*member: isFoo:OutputUnit(1, {libB})*/
+/*member: isFoo:member_unit=1{libB}*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(1, {libB})*/
+/*member: isFunFunFoo:member_unit=1{libB}*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: isDooFunFunFoo:OutputUnit(1, {libB})*/
+/*member: isDooFunFunFoo:member_unit=1{libB}*/
 bool isDooFunFunFoo(o) => o is lib.Doo<lib.FunFunFoo>;
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
index 8e9708b..ddc592e 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/libc.dart
@@ -6,20 +6,20 @@
 
 import 'lib.dart' as lib;
 
-/*member: isFoo:OutputUnit(2, {libC})*/
+/*member: isFoo:member_unit=2{libC}*/
 bool isFoo(o) => lib.isFoo(o);
 
-/*member: isFunFunFoo:OutputUnit(2, {libC})*/
+/*member: isFunFunFoo:member_unit=2{libC}*/
 bool isFunFunFoo(o) => lib.isFunFunFoo(o);
 
-/*member: createB2:OutputUnit(2, {libC})*/
+/*member: createB2:member_unit=2{libC}*/
 createB2() => new lib.B2();
 
-/*member: createC3:OutputUnit(2, {libC})*/
+/*member: createC3:member_unit=2{libC}*/
 createC3() => new lib.C3();
 
-/*member: createD3:OutputUnit(2, {libC})*/
+/*member: createD3:member_unit=2{libC}*/
 createD3() => new lib.D3();
 
-/*member: createDooFunFunFoo:OutputUnit(2, {libC})*/
+/*member: createDooFunFunFoo:member_unit=2{libC}*/
 createDooFunFunFoo() => lib.createDooFunFunFoo();
diff --git a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
index 541070c..ca9bb68 100644
--- a/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/lazy_types/main.dart
@@ -8,7 +8,23 @@
 import 'libb.dart' deferred as libB;
 import 'libc.dart' deferred as libC;
 
-/*member: foo:OutputUnit(main, {}),constants=[FunctionConstant(callFooMethod)=OutputUnit(1, {libB}),FunctionConstant(createB2)=OutputUnit(2, {libC}),FunctionConstant(createC3)=OutputUnit(2, {libC}),FunctionConstant(createD3)=OutputUnit(2, {libC}),FunctionConstant(createDooFunFunFoo)=OutputUnit(2, {libC}),FunctionConstant(isDooFunFunFoo)=OutputUnit(1, {libB}),FunctionConstant(isFoo)=OutputUnit(1, {libB}),FunctionConstant(isFoo)=OutputUnit(2, {libC}),FunctionConstant(isFoo)=OutputUnit(6, {libA}),FunctionConstant(isFunFunFoo)=OutputUnit(1, {libB}),FunctionConstant(isFunFunFoo)=OutputUnit(2, {libC}),FunctionConstant(isFunFunFoo)=OutputUnit(6, {libA}),FunctionConstant(isMega)=OutputUnit(6, {libA})]*/
+/*member: foo:
+ constants=[
+  FunctionConstant(callFooMethod)=1{libB},
+  FunctionConstant(createB2)=2{libC},
+  FunctionConstant(createC3)=2{libC},
+  FunctionConstant(createD3)=2{libC},
+  FunctionConstant(createDooFunFunFoo)=2{libC},
+  FunctionConstant(isDooFunFunFoo)=1{libB},
+  FunctionConstant(isFoo)=1{libB},
+  FunctionConstant(isFoo)=2{libC},
+  FunctionConstant(isFoo)=6{libA},
+  FunctionConstant(isFunFunFoo)=1{libB},
+  FunctionConstant(isFunFunFoo)=2{libC},
+  FunctionConstant(isFunFunFoo)=6{libA},
+  FunctionConstant(isMega)=6{libA}],
+ member_unit=main{}
+*/
 void foo() async {
   await libA.loadLibrary();
   await libB.loadLibrary();
@@ -31,7 +47,7 @@
   print((libC.createDooFunFunFoo)());
 }
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
   foo();
 }
diff --git a/pkg/compiler/test/deferred_loading/data/regress_35311/lib.dart b/pkg/compiler/test/deferred_loading/data/regress_35311/lib.dart
index ee3d8b3..b7ecf26 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_35311/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_35311/lib.dart
@@ -2,12 +2,15 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*class: B:OutputUnit(1, {lib}), type=OutputUnit(main, {})*/
-/*member: B.:OutputUnit(1, {lib})*/
+/*class: B:
+ class_unit=1{lib},
+ type_unit=main{}
+*/
+/*member: B.:member_unit=1{lib}*/
 class B {
-  /*member: B.value:OutputUnit(1, {lib})*/
+  /*member: B.value:member_unit=1{lib}*/
   B value = null;
 }
 
-/*member: list:OutputUnit(1, {lib})*/
+/*member: list:member_unit=1{lib}*/
 List<B> list = [];
diff --git a/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart b/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
index 7b8802a..9489c7f 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_35311/main.dart
@@ -4,19 +4,19 @@
 
 import 'lib.dart' deferred as lib;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await lib.loadLibrary();
 
   // inferred return-type in closures:
   // lib.B f1() => lib.B(); // Compile time error(see tests/dart2js)
-  var f2 = /*OutputUnit(main, {})*/ () =>
+  var f2 = /*closure_unit=main{}*/ () =>
       lib.B(); // no compile error, but f1 has inferred type: () -> d.B
 
   // inferred type-arguments
   // lib.list = <lib.B>[]; // Compile time error(see tests/dart2js)
   lib.list = []; // no error, but type parameter was injected here
   lib.list = lib.list
-      .map(/*OutputUnit(main, {})*/ (x) => x.value)
+      .map(/*closure_unit=main{}*/ (x) => x.value)
       .toList(); // no Compile error, type parameter inferred on closure and map<T>.
 }
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
index b72819b..c88e3f0 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/libb.dart
@@ -6,6 +6,9 @@
 
 import 'libc.dart';
 
-/*class: C1:OutputUnit(1, {libb}), type=OutputUnit(main, {})*/
-/*member: C1.:OutputUnit(1, {libb})*/
+/*class: C1:
+ class_unit=1{libb},
+ type_unit=main{}
+*/
+/*member: C1.:member_unit=1{libb}*/
 class C1 extends C2 implements C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
index a1300e3..70f5c4b 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/libc.dart
@@ -4,9 +4,15 @@
 
 // @dart = 2.7
 
-/*class: C2:OutputUnit(1, {libb}), type=OutputUnit(main, {})*/
-/*member: C2.:OutputUnit(1, {libb})*/
+/*class: C2:
+ class_unit=1{libb},
+ type_unit=main{}
+*/
+/*member: C2.:member_unit=1{libb}*/
 class C2 {}
 
-/*class: C3:none, type=OutputUnit(main, {})*/
+/*class: C3:
+ class_unit=none,
+ type_unit=main{}
+*/
 class C3 {}
diff --git a/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart b/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
index f916de5..dfbc3c4 100644
--- a/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/regress_43055/main.dart
@@ -6,9 +6,9 @@
 import 'libb.dart' deferred as libb;
 import 'libc.dart';
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
-  var f = /*OutputUnit(main, {})*/ () => libb.C1();
+  var f = /*closure_unit=main{}*/ () => libb.C1();
   print(f is C2 Function());
   print(f is C3 Function());
   await libb.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_a.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_a.dart
index 174c5a5..f4c32dc 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_a.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_a.dart
@@ -7,8 +7,8 @@
 import 'shared.dart' deferred as s1;
 
 /*member: doA:
- OutputUnit(main, {}),
- constants=[ConstructedConstant(C())=OutputUnit(1, {s1, s2})]
+ constants=[ConstructedConstant(C())=1{s1, s2}],
+ member_unit=main{}
 */
 doA() async {
   await s1.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_b.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_b.dart
index 814bff6..5e0922c 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_b.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_b.dart
@@ -7,8 +7,8 @@
 import 'shared.dart' deferred as s2;
 
 /*member: doB:
- OutputUnit(main, {}),
- constants=[ConstructedConstant(C())=OutputUnit(1, {s1, s2})]
+ constants=[ConstructedConstant(C())=1{s1, s2}],
+ member_unit=main{}
 */
 doB() async {
   await s2.loadLibrary();
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
index 71f2233..3a8da8a 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/lib_c.dart
@@ -4,10 +4,13 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(1, {s1, s2}), type=OutputUnit(1, {s1, s2})*/
+/*class: C:
+ class_unit=1{s1, s2},
+ type_unit=1{s1, s2}
+*/
 class C {
   const C();
 
-  /*member: C.method:OutputUnit(1, {s1, s2})*/
+  /*member: C.method:member_unit=1{s1, s2}*/
   method() => print("1");
 }
diff --git a/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart b/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
index 00dffbc..8337bc0 100644
--- a/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/shared_constant/main.dart
@@ -13,7 +13,7 @@
 import 'lib_a.dart';
 import 'lib_b.dart';
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   (await doA()).method();
   await doB();
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart b/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
index ebec04b..18c2288 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/lib1.dart
@@ -6,102 +6,123 @@
 
 library lib1;
 
-/*class: ConstClass:OutputUnit(2, {lib1, lib2}), type=OutputUnit(2, {lib1, lib2})*/
+/*class: ConstClass:
+ class_unit=2{lib1, lib2},
+ type_unit=2{lib1, lib2}
+*/
 class ConstClass {
-  /*member: ConstClass.x:OutputUnit(2, {lib1, lib2})*/
+  /*member: ConstClass.x:member_unit=2{lib1, lib2}*/
   final x;
 
   const ConstClass(this.x);
 }
 
 /*member: x:
- OutputUnit(2, {lib1, lib2}),
- constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=OutputUnit(2, {lib1, lib2})]
+ constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=2{lib1, lib2}],
+ member_unit=2{lib1, lib2}
 */
 var x = const ConstClass(const ConstClass(1));
 
-/*class: C:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C {
-  /*member: C.foo:OutputUnit(3, {lib2})*/
+  /*member: C.foo:member_unit=3{lib2}*/
   static foo() {
-    /*OutputUnit(3, {lib2})*/ () {}(); // Hack to avoid inlining.
+    /*closure_unit=3{lib2}*/ () {}(); // Hack to avoid inlining.
     return 1;
   }
 
-  /*member: C.:OutputUnit(1, {lib1})*/
+  /*member: C.:member_unit=1{lib1}*/
   C();
 
-  /*member: C.bar:OutputUnit(1, {lib1})*/
+  /*member: C.bar:member_unit=1{lib1}*/
   bar() {
-    /*OutputUnit(1, {lib1})*/ () {}(); // Hack to avoid inlining.
+    /*closure_unit=1{lib1}*/ () {}(); // Hack to avoid inlining.
     return 1;
   }
 }
 
-/*class: C1:none, type=none*/
+/*class: C1:
+ class_unit=none,
+ type_unit=none
+*/
 class C1 {
   /*member: C1.foo:
-   OutputUnit(3, {lib2}),
-   constants=[MapConstant({})=OutputUnit(3, {lib2})]
+   constants=[MapConstant({})=3{lib2}],
+   member_unit=3{lib2}
   */
   static var foo = const {};
   var bar = const {};
 }
 
-/*class: C2:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C2:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C2 {
-  /*member: C2.foo:OutputUnit(3, {lib2})*/
+  /*member: C2.foo:member_unit=3{lib2}*/
   static var foo = new Map<int, int>.from({1: 2});
 
-  /*member: C2.bar:OutputUnit(1, {lib1})*/
+  /*member: C2.bar:member_unit=1{lib1}*/
   var bar = new Map<int, int>.from({1: 2});
 
-  /*member: C2.:OutputUnit(1, {lib1})*/
+  /*member: C2.:member_unit=1{lib1}*/
   C2();
 }
 
-/*class: C3:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C3:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C3 {
   /*member: C3.foo:
-   OutputUnit(3, {lib2}),
-   constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=OutputUnit(2, {lib1, lib2})]
+   constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=2{lib1, lib2}],
+   member_unit=3{lib2}
   */
   static final foo = const ConstClass(const ConstClass(1));
 
   /*member: C3.bar:
-   OutputUnit(1, {lib1}),
-   constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=OutputUnit(2, {lib1, lib2})]
+   constants=[ConstructedConstant(ConstClass(x=ConstructedConstant(ConstClass(x=IntConstant(1)))))=2{lib1, lib2}],
+   member_unit=1{lib1}
   */
   final bar = const ConstClass(const ConstClass(1));
 
-  /*member: C3.:OutputUnit(1, {lib1})*/
+  /*member: C3.:member_unit=1{lib1}*/
   C3();
 }
 
-/*class: C4:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C4:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C4 {
-  /*member: C4.foo:OutputUnit(3, {lib2})*/
+  /*member: C4.foo:member_unit=3{lib2}*/
   static final foo = new Map<ConstClass, ConstClass>.from({x: x});
 
-  /*member: C4.bar:OutputUnit(1, {lib1})*/
+  /*member: C4.bar:member_unit=1{lib1}*/
   final bar = new Map<ConstClass, ConstClass>.from({x: x});
 
-  /*member: C4.:OutputUnit(1, {lib1})*/
+  /*member: C4.:member_unit=1{lib1}*/
   C4();
 }
 
-/*class: C5:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: C5:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class C5 {
   static const foo = const [
     const {1: 3}
   ];
 
-  /*member: C5.:OutputUnit(1, {lib1})*/
+  /*member: C5.:member_unit=1{lib1}*/
   C5();
 
-  /*member: C5.bar:OutputUnit(1, {lib1})*/
+  /*member: C5.bar:member_unit=1{lib1}*/
   bar() {
-    /*OutputUnit(1, {lib1})*/ () {}(); // Hack to avoid inlining.
+    /*closure_unit=1{lib1}*/ () {}(); // Hack to avoid inlining.
     return 1;
   }
 }
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart b/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
index 52b4764..79c236c 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/lib2.dart
@@ -9,7 +9,12 @@
 import "package:expect/expect.dart";
 import "lib1.dart";
 
-/*member: foo:OutputUnit(3, {lib2}),constants=[ListConstant(<Map<int*,int*>*>[MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})])=OutputUnit(3, {lib2}),MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})=OutputUnit(3, {lib2})]*/
+/*member: foo:
+ constants=[
+  ListConstant(<Map<int*,int*>*>[MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})])=3{lib2},
+  MapConstant(<int*, int*>{IntConstant(1): IntConstant(3)})=3{lib2}],
+ member_unit=3{lib2}
+*/
 foo() {
   Expect.equals(1, C.foo());
   Expect.mapEquals({}, C1.foo);
diff --git a/pkg/compiler/test/deferred_loading/data/static_separate/main.dart b/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
index eb82cbf..78918bf 100644
--- a/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/static_separate/main.dart
@@ -14,14 +14,14 @@
 import 'lib1.dart' deferred as lib1;
 import 'lib2.dart' deferred as lib2;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 void main() {
   asyncStart();
-  Expect.throws(/*OutputUnit(main, {})*/ () {
+  Expect.throws(/*closure_unit=main{}*/ () {
     new lib1.C();
   });
-  lib1.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
-    lib2.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib1.loadLibrary().then(/*closure_unit=main{}*/ (_) {
+    lib2.loadLibrary().then(/*closure_unit=main{}*/ (_) {
       print("HERE");
       Expect.equals(1, new lib1.C().bar());
       var x = new lib1.C2();
diff --git a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib1.dart b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib1.dart
index 4ef7683..de7cb74 100644
--- a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib1.dart
@@ -6,5 +6,5 @@
 
 import 'lib2.dart';
 
-/*member: doCast:OutputUnit(main, {})*/
-doCast(List<dynamic> l) => l.cast<B>().map(/*OutputUnit(main, {})*/ (x) => 1);
+/*member: doCast:member_unit=main{}*/
+doCast(List<dynamic> l) => l.cast<B>().map(/*closure_unit=main{}*/ (x) => 1);
diff --git a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
index d6a1146..1a0b2fe 100644
--- a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/lib2.dart
@@ -4,14 +4,20 @@
 
 // @dart = 2.7
 
-/*class: A:OutputUnit(1, {c}), type=OutputUnit(1, {c})*/
+/*class: A:
+ class_unit=1{c},
+ type_unit=1{c}
+*/
 class A {
-  /*member: A.:OutputUnit(1, {c})*/
+  /*member: A.:member_unit=1{c}*/
   A();
 }
 
-/*class: B:none, type=OutputUnit(main, {})*/
+/*class: B:
+ class_unit=none,
+ type_unit=main{}
+*/
 class B extends A {}
 
-/*member: createA:OutputUnit(1, {c})*/
+/*member: createA:member_unit=1{c}*/
 createA() => new A();
diff --git a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
index 70024a3..c279b65 100644
--- a/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_argument_dependency/main.dart
@@ -7,7 +7,7 @@
 import 'lib1.dart';
 import 'lib2.dart' deferred as c;
 
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() async {
   await c.loadLibrary();
   c.createA();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
index 1886af2..0d00710 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib1.dart
@@ -6,12 +6,18 @@
 
 import 'lib3.dart';
 
-/*class: A:OutputUnit(1, {lib1}), type=OutputUnit(1, {lib1})*/
+/*class: A:
+ class_unit=1{lib1},
+ type_unit=1{lib1}
+*/
 class A<T> {
   const A();
 }
 
-/*class: B:none, type=OutputUnit(1, {lib1})*/
+/*class: B:
+ class_unit=none,
+ type_unit=1{lib1}
+*/
 class B {}
 
 const dynamic field1 = const A<B>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
index 3f18084..2e07747 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib2.dart
@@ -4,12 +4,18 @@
 
 // @dart = 2.7
 
-/*class: C:OutputUnit(main, {}), type=OutputUnit(main, {})*/
+/*class: C:
+ class_unit=main{},
+ type_unit=main{}
+*/
 class C<T> {
   const C();
 }
 
-/*class: D:none, type=OutputUnit(main, {})*/
+/*class: D:
+ class_unit=none,
+ type_unit=main{}
+*/
 class D {}
 
 const dynamic field = const C<D>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
index 8e2f533..9b56057 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/lib3.dart
@@ -4,12 +4,18 @@
 
 // @dart = 2.7
 
-/*class: E:OutputUnit(2, {lib3}), type=OutputUnit(2, {lib3})*/
+/*class: E:
+ class_unit=2{lib3},
+ type_unit=2{lib3}
+*/
 class E<T> {
   const E();
 }
 
-/*class: F:none, type=OutputUnit(3, {lib1, lib3})*/
+/*class: F:
+ class_unit=none,
+ type_unit=3{lib1, lib3}
+*/
 class F {}
 
 const dynamic field = const E<F>();
diff --git a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
index 2e5f732..dd5873b 100644
--- a/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/type_arguments/main.dart
@@ -8,7 +8,14 @@
 import 'lib2.dart' as lib2;
 import 'lib3.dart' deferred as lib3;
 
-/*member: main:OutputUnit(main, {}),constants=[ConstructedConstant(A<B*>())=OutputUnit(1, {lib1}),ConstructedConstant(A<F*>())=OutputUnit(1, {lib1}),ConstructedConstant(C<D*>())=OutputUnit(main, {}),ConstructedConstant(E<F*>())=OutputUnit(2, {lib3})]*/
+/*member: main:
+ constants=[
+  ConstructedConstant(A<B*>())=1{lib1},
+  ConstructedConstant(A<F*>())=1{lib1},
+  ConstructedConstant(C<D*>())=main{},
+  ConstructedConstant(E<F*>())=2{lib3}],
+ member_unit=main{}
+*/
 main() async {
   await lib1.loadLibrary();
   lib1.field1;
diff --git a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
index 51880ac..62e44b1 100644
--- a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
+++ b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/lib.dart
@@ -7,26 +7,38 @@
 // All of these types are considered instantiated because we create an instance
 // of [C].
 
-/*class: A:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: A.:OutputUnit(1, {lib})*/
+/*class: A:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: A.:member_unit=1{lib}*/
 class A {}
 
-/*class: Box:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: Box.:OutputUnit(1, {lib})*/
+/*class: Box:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: Box.:member_unit=1{lib}*/
 class Box<T> {
-  /*member: Box.value:OutputUnit(1, {lib})*/
+  /*member: Box.value:member_unit=1{lib}*/
   int value;
 }
 
-/*class: B:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: B.:OutputUnit(1, {lib})*/
+/*class: B:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: B.:member_unit=1{lib}*/
 class B<T> extends A {
-  /*member: B.box:OutputUnit(1, {lib})*/
+  /*member: B.box:member_unit=1{lib}*/
   final box = new Box<T>();
 }
 
-/*class: C:OutputUnit(1, {lib}), type=OutputUnit(1, {lib})*/
-/*member: C.:OutputUnit(1, {lib})*/
+/*class: C:
+ class_unit=1{lib},
+ type_unit=1{lib}
+*/
+/*member: C.:member_unit=1{lib}*/
 class C extends B<N> {}
 
 // N is not instantiated, but used as a type argument in C and indirectly in a
@@ -35,5 +47,8 @@
 // to the main output unit. However, A is in the output unit of C so we fail
 // when trying to finalize the declaration of N while loading the main output
 // unit.
-/*class: N:none, type=OutputUnit(1, {lib})*/
+/*class: N:
+ class_unit=none,
+ type_unit=1{lib}
+*/
 class N extends A {}
diff --git a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
index 0f072de..8b8ad89 100644
--- a/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
+++ b/pkg/compiler/test/deferred_loading/data/uninstantiated_type_variable/main.dart
@@ -11,13 +11,13 @@
 ///
 /// If not, we may include it in the main unit and may not see that the base
 /// class is not added to the main unit.
-/*member: main:OutputUnit(main, {})*/
+/*member: main:member_unit=main{}*/
 main() {
-  lib.loadLibrary().then(/*OutputUnit(main, {})*/ (_) {
+  lib.loadLibrary().then(/*closure_unit=main{}*/ (_) {
     dontInline(new lib.C()).box.value;
   });
 }
 
 @pragma('dart2js:noInline')
-/*member: dontInline:OutputUnit(main, {})*/
+/*member: dontInline:member_unit=main{}*/
 dontInline(x) => x;
diff --git a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
index e2ad132..43f6ffa 100644
--- a/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
+++ b/pkg/compiler/test/deferred_loading/deferred_loading_test.dart
@@ -5,6 +5,7 @@
 // @dart = 2.7
 
 import 'dart:io' hide Link;
+import 'package:_fe_analyzer_shared/src/testing/features.dart';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/closure.dart';
 import 'package:compiler/src/common.dart';
@@ -23,7 +24,7 @@
 
 ///  Add in options to pass to the compiler like
 /// `Flags.disableTypeInference` or `Flags.disableInlining`
-const List<String> compilerOptions = const <String>[];
+const List<String> compilerOptions = const [];
 
 /// Compute the [OutputUnit]s for all source files involved in the test, and
 /// ensure that the compiler is correctly calculating what is used and what is
@@ -32,7 +33,7 @@
 /// same name as the original file in `data`.
 main(List<String> args) {
   asyncTest(() async {
-    Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
+    Directory dataDir = Directory.fromUri(Platform.script.resolve('data'));
     await checkTests(dataDir, const OutputUnitDataComputer(),
         options: compilerOptions, args: args, setUpFunction: () {
       importPrefixes.clear();
@@ -44,13 +45,13 @@
 // artificial constraint of requiring every deferred import use a different
 // named prefix per test. We enforce this constraint here by checking that no
 // prefix name responds to two different libraries.
-Map<String, Uri> importPrefixes = <String, Uri>{};
+Map<String, Uri> importPrefixes = {};
 
 /// Create a consistent string representation of [OutputUnit]s for both
 /// KImportEntities and ImportElements.
 String outputUnitString(OutputUnit unit) {
   if (unit == null) return 'none';
-  StringBuffer sb = new StringBuffer();
+  StringBuffer sb = StringBuffer();
   bool first = true;
   for (ImportEntity import in unit.importsForTesting) {
     if (!first) sb.write(', ');
@@ -72,10 +73,18 @@
     }
     importPrefixes[import.name] = import.enclosingLibraryUri;
   }
-  return 'OutputUnit(${unit.name}, {$sb})';
+  return '${unit.name}{$sb}';
 }
 
-class OutputUnitDataComputer extends DataComputer<String> {
+class Tags {
+  static const String cls = 'class_unit';
+  static const String member = 'member_unit';
+  static const String closure = 'closure_unit';
+  static const String constants = 'constants';
+  static const String type = 'type_unit';
+}
+
+class OutputUnitDataComputer extends DataComputer<Features> {
   const OutputUnitDataComputer();
 
   /// OutputData for [member] as a kernel based element.
@@ -86,33 +95,34 @@
   /// is.
   @override
   void computeMemberData(Compiler compiler, MemberEntity member,
-      Map<Id, ActualData<String>> actualMap,
+      Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     JsToElementMap elementMap = closedWorld.elementMap;
     MemberDefinition definition = elementMap.getMemberDefinition(member);
-    new OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
             closedWorld.outputUnitData, closedWorld.closureDataLookup)
         .run(definition.node);
   }
 
   @override
-  void computeClassData(
-      Compiler compiler, ClassEntity cls, Map<Id, ActualData<String>> actualMap,
+  void computeClassData(Compiler compiler, ClassEntity cls,
+      Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     JsToElementMap elementMap = closedWorld.elementMap;
     ClassDefinition definition = elementMap.getClassDefinition(cls);
-    new OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
+    OutputUnitIrComputer(compiler.reporter, actualMap, elementMap,
             closedWorld.outputUnitData, closedWorld.closureDataLookup)
         .computeForClass(definition.node);
   }
 
   @override
-  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+  DataInterpreter<Features> get dataValidator =>
+      const FeaturesDataInterpreter();
 }
 
-class OutputUnitIrComputer extends IrDataExtractor<String> {
+class OutputUnitIrComputer extends IrDataExtractor<Features> {
   final JsToElementMap _elementMap;
   final OutputUnitData _data;
   final ClosureData _closureDataLookup;
@@ -121,34 +131,36 @@
 
   OutputUnitIrComputer(
       DiagnosticReporter reporter,
-      Map<Id, ActualData<String>> actualMap,
+      Map<Id, ActualData<Features>> actualMap,
       this._elementMap,
       this._data,
       this._closureDataLookup)
       : super(reporter, actualMap);
 
-  String getMemberValue(MemberEntity member, Set<String> constants) {
-    StringBuffer sb = new StringBuffer();
-    sb.write(outputUnitString(_data.outputUnitForMemberForTesting(member)));
-    if (constants.isNotEmpty) {
-      List<String> text = constants.toList()..sort();
-      sb.write(',constants=[${text.join(',')}]');
+  Features getMemberValue(
+      String tag, MemberEntity member, Set<String> constants) {
+    Features features = Features();
+    features.add(tag,
+        value: outputUnitString(_data.outputUnitForMemberForTesting(member)));
+    for (var constant in constants) {
+      features.addElement(Tags.constants, constant);
     }
-    return sb.toString();
+    return features;
   }
 
   @override
-  String computeClassValue(Id id, ir.Class node) {
+  Features computeClassValue(Id id, ir.Class node) {
     var cls = _elementMap.getClass(node);
-    StringBuffer sb = new StringBuffer();
-    sb.write(outputUnitString(_data.outputUnitForClassForTesting(cls)));
-    sb.write(', type=');
-    sb.write(outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
-    return sb.toString();
+    Features features = Features();
+    features.add(Tags.cls,
+        value: outputUnitString(_data.outputUnitForClassForTesting(cls)));
+    features.add(Tags.type,
+        value: outputUnitString(_data.outputUnitForClassTypeForTesting(cls)));
+    return features;
   }
 
   @override
-  String computeMemberValue(Id id, ir.Member node) {
+  Features computeMemberValue(Id id, ir.Member node) {
     if (node is ir.Field && node.isConst) {
       ir.Expression initializer = node.initializer;
       ConstantValue constant = _elementMap.getConstantValue(node, initializer);
@@ -160,11 +172,14 @@
           // front of the constructor. The "-6" is an approximation assuming that
           // there is just a single space after "const" and no prefix.
           // TODO(sigmund): offsets should be fixed in the FE instead.
-          span = new SourceSpan(span.uri, span.begin - 6, span.end - 6);
+          span = SourceSpan(span.uri, span.begin - 6, span.end - 6);
         }
         _registerValue(
-            new NodeId(span.begin, IdKind.node),
-            outputUnitString(_data.outputUnitForConstantForTesting(constant)),
+            NodeId(span.begin, IdKind.node),
+            Features.fromMap({
+              Tags.member: outputUnitString(
+                  _data.outputUnitForConstantForTesting(constant))
+            }),
             node,
             span,
             actualMap,
@@ -172,9 +187,10 @@
       }
     }
 
-    String value = getMemberValue(_elementMap.getMember(node), _constants);
+    Features features =
+        getMemberValue(Tags.member, _elementMap.getMember(node), _constants);
     _constants = {};
-    return value;
+    return features;
   }
 
   @override
@@ -188,10 +204,10 @@
   }
 
   @override
-  String computeNodeValue(Id id, ir.TreeNode node) {
+  Features computeNodeValue(Id id, ir.TreeNode node) {
     if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
       ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
-      return getMemberValue(info.callMethod, const {});
+      return getMemberValue(Tags.closure, info.callMethod, const {});
     }
     return null;
   }
@@ -215,6 +231,6 @@
   }
   if (value != null) {
     actualMap[id] =
-        new ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
+        ActualData<T>(id, value, sourceSpan.uri, sourceSpan.begin, object);
   }
 }
diff --git a/pkg/compiler/test/field_analysis/jdata/static_initializers.dart b/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
index 1b4fdf6..16ba995 100644
--- a/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
+++ b/pkg/compiler/test/field_analysis/jdata/static_initializers.dart
@@ -126,8 +126,7 @@
 /*member: field3g:final,lazy*/
 var field3g = [method()];
 
-// TODO(johnniwinther): Recognize this as of eager complexity.
-/*member: field3h:final,lazy*/
+/*member: field3h:final,eager*/
 var field3h = [1 + 3];
 
 /*member: field4a:constant=IntConstant(5)*/
diff --git a/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart b/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
index 929cb4c..0ca8e51 100644
--- a/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
+++ b/pkg/compiler/test/field_analysis/kdata/simple_initializers.dart
@@ -10,6 +10,7 @@
 }
 
 const bool const1 = true;
+const dynamic const2 = 42;
 
 class Class1 {
   /*member: Class1.field0:initial=NullConstant*/
@@ -56,6 +57,27 @@
 
   /*member: Class1.field14:initial=BoolConstant(false)*/
   var field14 = const1 is int;
+
+  /*member: Class1.field15:initial=IntConstant(42)*/
+  var field15 = const2 as int;
+
+  /*member: Class1.field16:initial=IntConstant(5)*/
+  var field16 = 2 + 3;
+
+  /*member: Class1.field17:initial=BoolConstant(false)*/
+  var field17 = identical(2, 3);
+
+  /*member: Class1.field18:initial=IntConstant(3)*/
+  var field18 = 'foo'.length;
+
+  /*member: Class1.field19:initial=StringConstant("23")*/
+  var field19 = '${2}${3}';
+
+  /*member: Class1.field20:initial=IntConstant(2)*/
+  var field20 = '${2}${3}'.length;
+
+  /*member: Class1.field21:initial=TypeConstant(Object)*/
+  var field21 = Object;
 }
 
 class Class2 {
@@ -101,6 +123,27 @@
   /*member: Class2.field14:Class2.=BoolConstant(false),initial=NullConstant*/
   var field14;
 
+  /*member: Class2.field15:Class2.=IntConstant(42),initial=NullConstant*/
+  var field15;
+
+  /*member: Class2.field16:Class2.=IntConstant(5),initial=NullConstant*/
+  var field16;
+
+  /*member: Class2.field17:Class2.=BoolConstant(false),initial=NullConstant*/
+  var field17;
+
+  /*member: Class2.field18:Class2.=IntConstant(3),initial=NullConstant*/
+  var field18;
+
+  /*member: Class2.field19:Class2.=StringConstant("23"),initial=NullConstant*/
+  var field19;
+
+  /*member: Class2.field20:Class2.=IntConstant(2),initial=NullConstant*/
+  var field20;
+
+  /*member: Class2.field21:Class2.=TypeConstant(Object),initial=NullConstant*/
+  var field21;
+
   Class2()
       : field1 = null,
         field2 = true,
@@ -115,5 +158,12 @@
         field11 = #foo,
         field12 = 2 + 3,
         field13 = const1,
-        field14 = const1 is int;
+        field14 = const1 is int,
+        field15 = const2 as int,
+        field16 = 2 + 3,
+        field17 = identical(2, 3),
+        field18 = 'foo'.length,
+        field19 = '${2}${3}',
+        field20 = '${2}${3}'.length,
+        field21 = Object;
 }
diff --git a/pkg/compiler/test/field_analysis/kdata/static_initializers.dart b/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
index c8f2471..e573c34 100644
--- a/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
+++ b/pkg/compiler/test/field_analysis/kdata/static_initializers.dart
@@ -114,15 +114,13 @@
 /*member: field3g:complexity=lazy*/
 var field3g = [method()];
 
-// TODO(johnniwinther): Recognize this as of eager complexity.
-/*member: field3h:complexity=lazy*/
+/*member: field3h:complexity=eager*/
 var field3h = [1 + 3];
 
-// TODO(johnniwinther): Recognize `field4*` as of constant complexity.
-/*member: field4a:complexity=lazy,initial=IntConstant(5)*/
+/*member: field4a:complexity=constant,initial=IntConstant(5)*/
 final field4a = 2 + 3;
 
-/*member: field4b:complexity=lazy,initial=IntConstant(5)*/
+/*member: field4b:complexity=constant,initial=IntConstant(5)*/
 var field4b = 2 + 3;
 
 const field4c = 2 + 3;
diff --git a/pkg/compiler/test/helpers/compiler_helper.dart b/pkg/compiler/test/helpers/compiler_helper.dart
index 3dd4594..eb7046a 100644
--- a/pkg/compiler/test/helpers/compiler_helper.dart
+++ b/pkg/compiler/test/helpers/compiler_helper.dart
@@ -37,12 +37,12 @@
     bool enableTypeAssertions: false,
     bool minify: false,
     bool disableInlining: true,
-    bool trustJSInteropTypeAnnotations: false,
     bool disableTypeInference: true,
     bool omitImplicitChecks: true,
     bool enableVariance: false,
     void check(String generatedEntry),
-    bool returnAll: false}) async {
+    bool returnAll: false,
+    bool soundNullSafety: false}) async {
   OutputCollector outputCollector = returnAll ? new OutputCollector() : null;
   List<String> options = <String>[];
   if (disableTypeInference) {
@@ -57,15 +57,17 @@
   if (minify) {
     options.add(Flags.minify);
   }
-  if (trustJSInteropTypeAnnotations) {
-    options.add(Flags.trustJSInteropTypeAnnotations);
-  }
   if (disableInlining) {
     options.add(Flags.disableInlining);
   }
   if (enableVariance) {
     options.add('${Flags.enableLanguageExperiments}=variance');
   }
+  if (soundNullSafety) {
+    options.add(Flags.soundNullSafety);
+  } else {
+    options.add(Flags.noSoundNullSafety);
+  }
 
   // Pretend this is a dart2js_native test to allow use of 'native' keyword
   // and import of private libraries.
@@ -103,6 +105,7 @@
 Future<String> compileAll(String code,
     {bool disableInlining: true,
     bool minify: false,
+    bool soundNullSafety: false,
     int expectedErrors,
     int expectedWarnings}) async {
   OutputCollector outputCollector = new OutputCollector();
@@ -114,6 +117,11 @@
   if (minify) {
     options.add(Flags.minify);
   }
+  if (soundNullSafety) {
+    options.add(Flags.soundNullSafety);
+  } else {
+    options.add(Flags.noSoundNullSafety);
+  }
 
   // Pretend this is a dart2js_native test to allow use of 'native' keyword
   // and import of private libraries.
diff --git a/pkg/compiler/test/impact/data/expressions.dart b/pkg/compiler/test/impact/data/expressions.dart
index 7e6cdb0..5161a7a 100644
--- a/pkg/compiler/test/impact/data/expressions.dart
+++ b/pkg/compiler/test/impact/data/expressions.dart
@@ -73,13 +73,16 @@
 /*member: testNot:type=[inst:JSBool]*/
 testNot() => !false;
 
-/*member: testUnaryMinus:
- dynamic=[int.unary-],
- type=[inst:JSDouble,inst:JSInt,inst:JSNumber,inst:JSPositiveInt,inst:JSUInt31,inst:JSUInt32]
-*/
+/*member: testUnaryMinus:type=[
+  inst:JSDouble,
+  inst:JSInt,
+  inst:JSNumber,
+  inst:JSPositiveInt,
+  inst:JSUInt31,
+  inst:JSUInt32]*/
 testUnaryMinus() => -1;
 
-/*member: testConditional:type=[inst:JSBool,inst:JSNull,inst:JSString]*/
+/*member: testConditional:type=[inst:JSNull]*/
 // ignore: DEAD_CODE
 testConditional() => true ? null : '';
 
@@ -107,634 +110,45 @@
 */
 testPreDec(o) => --o;
 
-/*member: testIs:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:Class*]
-*/
+/*member: testIs:type=[inst:JSBool]*/
 testIs() => null is Class;
 
-/*member: testIsGeneric:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:GenericClass<int*,String*>*]
-*/
+/*member: testIsGeneric:type=[inst:JSBool]*/
 testIsGeneric() => null is GenericClass<int, String>;
 
-/*member: testIsGenericRaw:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsGenericRaw:type=[inst:JSBool]*/
 testIsGenericRaw() => null is GenericClass;
 
-/*member: testIsGenericDynamic:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsGenericDynamic:type=[inst:JSBool]*/
 testIsGenericDynamic() => null is GenericClass<dynamic, dynamic>;
 
-/*member: testIsNot:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:Class*]
-*/
+/*member: testIsNot:type=[inst:JSBool]*/
 testIsNot() => null is! Class;
 
-/*member: testIsNotGeneric:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:GenericClass<int*,String*>*]
-*/
+/*member: testIsNotGeneric:type=[inst:JSBool]*/
 testIsNotGeneric() => null is! GenericClass<int, String>;
 
-/*member: testIsNotGenericRaw:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsNotGenericRaw:type=[inst:JSBool]*/
 testIsNotGenericRaw() => null is! GenericClass;
 
-/*member: testIsNotGenericDynamic:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1)],
- type=[
-  inst:Closure,
-  inst:JSBool,
-  inst:JSNull,
-  is:GenericClass<dynamic,dynamic>*]
-*/
+/*member: testIsNotGenericDynamic:type=[inst:JSBool]*/
 testIsNotGenericDynamic() => null is! GenericClass<dynamic, dynamic>;
 
-/*member: testIsTypedef:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:dynamic Function()*]
-*/
+/*member: testIsTypedef:type=[inst:JSBool]*/
 testIsTypedef() => null is Typedef;
 
-/*member: testIsTypedefGeneric:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:int* Function(String*)*]
-*/
+/*member: testIsTypedefGeneric:type=[inst:JSBool]*/
 testIsTypedefGeneric() => null is GenericTypedef<int, String>;
 
-/*member: testIsTypedefGenericRaw:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:dynamic Function(dynamic)*]
-*/
+/*member: testIsTypedefGenericRaw:type=[inst:JSBool]*/
 testIsTypedefGenericRaw() => null is GenericTypedef;
 
-/*member: testIsTypedefGenericDynamic:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:dynamic Function(dynamic)*]
-*/
+/*member: testIsTypedefGenericDynamic:type=[inst:JSBool]*/
 testIsTypedefGenericDynamic() => null is GenericTypedef<dynamic, dynamic>;
 
-/*member: testIsTypedefDeep:
- static=[
-  Rti._bind(1),
-  Rti._eval(1),
-  _arrayInstanceType(1),
-  _asBool(1),
-  _asBoolQ(1),
-  _asBoolS(1),
-  _asDouble(1),
-  _asDoubleQ(1),
-  _asDoubleS(1),
-  _asInt(1),
-  _asIntQ(1),
-  _asIntS(1),
-  _asNum(1),
-  _asNumQ(1),
-  _asNumS(1),
-  _asObject(1),
-  _asString(1),
-  _asStringQ(1),
-  _asStringS(1),
-  _asTop(1),
-  _generalAsCheckImplementation(1),
-  _generalIsTestImplementation(1),
-  _generalNullableAsCheckImplementation(1),
-  _generalNullableIsTestImplementation(1),
-  _installSpecializedAsCheck(1),
-  _installSpecializedIsTest(1),
-  _instanceType(1),
-  _isBool(1),
-  _isInt(1),
-  _isNum(1),
-  _isObject(1),
-  _isString(1),
-  _isTop(1),
-  findType(1),
-  instanceType(1),
-  setRuntimeTypeInfo(2)],
- type=[
-  inst:Closure,
-  inst:JSArray<dynamic>,
-  inst:JSBool,
-  inst:JSExtendableArray<dynamic>,
-  inst:JSFixedArray<dynamic>,
-  inst:JSMutableArray<dynamic>,
-  inst:JSNull,
-  inst:JSUnmodifiableArray<dynamic>,
-  is:List<int* Function(dynamic Function(dynamic)*)*>*]
-*/
+/*member: testIsTypedefDeep:type=[inst:JSBool]*/
 testIsTypedefDeep() => null is List<GenericTypedef<int, GenericTypedef>>;
 
-// ignore: UNNECESSARY_CAST
 /*member: testAs:
  static=[
   Rti._bind(1),
@@ -777,9 +191,9 @@
   inst:Closure,
   inst:JSBool]
 */
+// ignore: UNNECESSARY_CAST
 testAs(dynamic o) => o as Class;
 
-// ignore: UNNECESSARY_CAST
 /*member: testAsGeneric:
  static=[
   Rti._bind(1),
@@ -828,9 +242,9 @@
   inst:JSMutableArray<dynamic>,
   inst:JSUnmodifiableArray<dynamic>]
 */
+// ignore: UNNECESSARY_CAST
 testAsGeneric(dynamic o) => o as GenericClass<int, String>;
 
-// ignore: UNNECESSARY_CAST
 /*member: testAsGenericRaw:
  static=[
   Rti._bind(1),
@@ -873,9 +287,9 @@
   inst:Closure,
   inst:JSBool]
 */
+// ignore: UNNECESSARY_CAST
 testAsGenericRaw(dynamic o) => o as GenericClass;
 
-// ignore: UNNECESSARY_CAST
 /*member: testAsGenericDynamic:
  static=[
   Rti._bind(1),
@@ -918,6 +332,7 @@
   inst:Closure,
   inst:JSBool]
 */
+// ignore: UNNECESSARY_CAST
 testAsGenericDynamic(dynamic o) => o as GenericClass<dynamic, dynamic>;
 
 /*member: testThrow:
diff --git a/pkg/compiler/test/impact/data/future_or.dart b/pkg/compiler/test/impact/data/future_or.dart
index 42e77c8..1a13b89 100644
--- a/pkg/compiler/test/impact/data/future_or.dart
+++ b/pkg/compiler/test/impact/data/future_or.dart
@@ -6,7 +6,6 @@
 
 import "dart:async";
 
-@pragma('dart2js:disableFinal')
 /*member: main:
  dynamic=[runtimeType],
  runtimeType=[unknown:FutureOr<int*>*],
@@ -22,6 +21,7 @@
   inst:JSUInt31,
   inst:JSUInt32]
 */
+@pragma('dart2js:disableFinal')
 void main() {
   FutureOr<int> i = new Future<int>.value(0);
   print(i.runtimeType);
diff --git a/pkg/compiler/test/impact/data/invokes.dart b/pkg/compiler/test/impact/data/invokes.dart
index 634025b..cb1acfc 100644
--- a/pkg/compiler/test/impact/data/invokes.dart
+++ b/pkg/compiler/test/impact/data/invokes.dart
@@ -588,7 +588,13 @@
 /*member: testTopLevelField:static=[topLevelField]*/
 testTopLevelField() => topLevelField;
 
-/*member: topLevelFieldLazy:static=[throwCyclicInit(1),topLevelFunction1(1)],type=[inst:JSNull]*/
+/*member: topLevelFieldLazy:
+ static=[
+  throwCyclicInit(1),
+  throwLateInitializationError(1),
+  topLevelFunction1(1)],
+ type=[inst:JSNull]
+*/
 var topLevelFieldLazy = topLevelFunction1(null);
 
 /*member: testTopLevelFieldLazy:static=[topLevelFieldLazy]*/
@@ -599,7 +605,13 @@
 /*member: testTopLevelFieldConst:type=[inst:JSNull]*/
 testTopLevelFieldConst() => topLevelFieldConst;
 
-/*member: topLevelFieldFinal:static=[throwCyclicInit(1),topLevelFunction1(1)],type=[inst:JSNull]*/
+/*member: topLevelFieldFinal:
+ static=[
+  throwCyclicInit(1),
+  throwLateInitializationError(1),
+  topLevelFunction1(1)],
+ type=[inst:JSNull]
+*/
 final topLevelFieldFinal = topLevelFunction1(null);
 
 /*member: testTopLevelFieldFinal:static=[topLevelFieldFinal]*/
@@ -981,40 +993,48 @@
   def:localFunction,
   localFunction(0),
   setRuntimeTypeInfo(2)],
-  type=[inst:Function,
+ type=[
+  inst:Function,
   inst:JSArray<dynamic>,
   inst:JSExtendableArray<dynamic>,
   inst:JSFixedArray<dynamic>,
   inst:JSMutableArray<dynamic>,
-  inst:JSUnmodifiableArray<dynamic>]*/
+  inst:JSUnmodifiableArray<dynamic>]
+*/
 testLocalFunctionInvoke() {
   localFunction() {}
   localFunction();
 }
 
-/*member: testLocalFunctionGet:static=[
+/*member: testLocalFunctionGet:
+ static=[
   def:localFunction,
   setRuntimeTypeInfo(2)],
-  type=[inst:Function,
+ type=[
+  inst:Function,
   inst:JSArray<dynamic>,
   inst:JSExtendableArray<dynamic>,
   inst:JSFixedArray<dynamic>,
   inst:JSMutableArray<dynamic>,
-  inst:JSUnmodifiableArray<dynamic>]*/
+  inst:JSUnmodifiableArray<dynamic>]
+*/
 testLocalFunctionGet() {
   localFunction() {}
   localFunction;
 }
 
-/*member: testClosure:static=[
+/*member: testClosure:
+ static=[
   def:<anonymous>,
   setRuntimeTypeInfo(2)],
-  type=[inst:Function,
+ type=[
+  inst:Function,
   inst:JSArray<dynamic>,
   inst:JSExtendableArray<dynamic>,
   inst:JSFixedArray<dynamic>,
   inst:JSMutableArray<dynamic>,
-  inst:JSUnmodifiableArray<dynamic>]*/
+  inst:JSUnmodifiableArray<dynamic>]
+*/
 testClosure() {
   () {};
 }
@@ -1024,7 +1044,8 @@
  static=[
   def:<anonymous>,
   setRuntimeTypeInfo(2)],
-  type=[inst:Function,
+ type=[
+  inst:Function,
   inst:JSArray<dynamic>,
   inst:JSExtendableArray<dynamic>,
   inst:JSFixedArray<dynamic>,
diff --git a/pkg/compiler/test/impact/data/jsinterop_setter1.dart b/pkg/compiler/test/impact/data/jsinterop_setter1.dart
index af09127..4042ca9 100644
--- a/pkg/compiler/test/impact/data/jsinterop_setter1.dart
+++ b/pkg/compiler/test/impact/data/jsinterop_setter1.dart
@@ -11,7 +11,6 @@
 
 import 'package:js/js.dart';
 
-@JS()
 /*member: foo=:
  static=[
   Rti._bind(1),
@@ -65,6 +64,7 @@
   native:SqlError,
   param:Function*]
 */
+@JS()
 external set foo(Function f);
 
 /*member: _doStuff:
diff --git a/pkg/compiler/test/impact/data/jsinterop_setter2.dart b/pkg/compiler/test/impact/data/jsinterop_setter2.dart
index 5a9c987..d62e98f 100644
--- a/pkg/compiler/test/impact/data/jsinterop_setter2.dart
+++ b/pkg/compiler/test/impact/data/jsinterop_setter2.dart
@@ -11,7 +11,6 @@
 
 import 'package:js/js.dart';
 
-@JS()
 /*member: foo=:
  static=[
   Rti._bind(1),
@@ -72,6 +71,7 @@
   native:SqlError,
   param:void Function(String*,File*)*]
 */
+@JS()
 external set foo(void Function(String, File) f);
 
 /*member: _doStuff:
diff --git a/pkg/compiler/test/impact/data/literals.dart b/pkg/compiler/test/impact/data/literals.dart
index 95bbf0a..4956865 100644
--- a/pkg/compiler/test/impact/data/literals.dart
+++ b/pkg/compiler/test/impact/data/literals.dart
@@ -82,10 +82,7 @@
 /*member: testString:type=[inst:JSString]*/
 testString() => 'foo';
 
-/*member: testStringInterpolation:
- dynamic=[toString(0)],
- static=[S(1)],type=[inst:JSBool,inst:JSString]
-*/
+/*member: testStringInterpolation:type=[inst:JSString]*/
 testStringInterpolation() => '${true}';
 
 /*member: testStringInterpolationConst:type=[inst:JSString]*/
@@ -94,11 +91,7 @@
   return b;
 }
 
-/*member: testStringJuxtaposition:
- dynamic=[toString(0)],
- static=[S(1)],
- type=[inst:JSString]
-*/
+/*member: testStringJuxtaposition:type=[inst:JSString]*/
 testStringJuxtaposition() => 'a' 'b';
 
 /*member: testSymbol:static=[Symbol.(1)],type=[inst:Symbol]*/
diff --git a/pkg/compiler/test/impact/data/native.dart b/pkg/compiler/test/impact/data/native.dart
index 9b26aae..b4d4c7f 100644
--- a/pkg/compiler/test/impact/data/native.dart
+++ b/pkg/compiler/test/impact/data/native.dart
@@ -58,7 +58,6 @@
 
 @Native("NativeClass")
 class NativeClass {
-  @annotation_Creates_SerializedScriptValue
   /*member: NativeClass.field:
    static=[
     Rti._bind(1),
@@ -108,6 +107,7 @@
     native:int,
     param:Object*]
   */
+  @annotation_Creates_SerializedScriptValue
   final Object field;
 
   factory NativeClass._() {
diff --git a/pkg/compiler/test/inference/data/as.dart b/pkg/compiler/test/inference/data/as.dart
index 319f83f..203687c 100644
--- a/pkg/compiler/test/inference/data/as.dart
+++ b/pkg/compiler/test/inference/data/as.dart
@@ -36,7 +36,7 @@
 /*member: asIntWithNegative:[null]*/
 asIntWithNegative() {
   _asIntWithNegative(0);
-  _asIntWithNegative(/*invoke: [exact=JSUInt31]*/ -1);
+  _asIntWithNegative(-1);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -60,7 +60,7 @@
 
 /*member: asIntOfMinusOne:[null]*/
 asIntOfMinusOne() {
-  _asIntOfMinusOne(/*invoke: [exact=JSUInt31]*/ -1);
+  _asIntOfMinusOne(-1);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/data/closure.dart b/pkg/compiler/test/inference/data/closure.dart
index 2e14eff..863cd64 100644
--- a/pkg/compiler/test/inference/data/closure.dart
+++ b/pkg/compiler/test/inference/data/closure.dart
@@ -69,7 +69,7 @@
 
   int lines = 0;
   local(/*[null]*/ () {
-    lines = /*invoke: [exact=JSUInt31]*/ -42;
+    lines = -42;
   });
   return lines;
 }
@@ -80,10 +80,10 @@
 
   int lines = 0;
   local(/*[null]*/ () {
-    lines = /*invoke: [exact=JSUInt31]*/ -42;
+    lines = -42;
   });
   local(/*[null]*/ () {
-    lines = /*invoke: [exact=JSUInt31]*/ -87;
+    lines = -87;
   });
   return lines;
 }
diff --git a/pkg/compiler/test/inference/data/list.dart b/pkg/compiler/test/inference/data/list.dart
index aa419a3..e05562f 100644
--- a/pkg/compiler/test/inference/data/list.dart
+++ b/pkg/compiler/test/inference/data/list.dart
@@ -126,9 +126,8 @@
 // Create a Uint8ClampedList using a constant multiplication as length.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: newUint8ClampedList:Container([exact=NativeUint8ClampedList], element: [exact=JSUInt31], length: null)*/
-newUint8ClampedList() =>
-    new Uint8ClampedList(2 /*invoke: [exact=JSUInt31]*/ * 7);
+/*member: newUint8ClampedList:Container([exact=NativeUint8ClampedList], element: [exact=JSUInt31], length: 14)*/
+newUint8ClampedList() => new Uint8ClampedList(2 * 7);
 
 ////////////////////////////////////////////////////////////////////////////////
 // Create a Uint8List using a const static field as length.
diff --git a/pkg/compiler/test/inference/data/list2.dart b/pkg/compiler/test/inference/data/list2.dart
new file mode 100644
index 0000000..40ab257
--- /dev/null
+++ b/pkg/compiler/test/inference/data/list2.dart
@@ -0,0 +1,124 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+/*member: main:[null]*/
+main() {
+  boolFlag = !boolFlag;
+  data. /*invoke: Container([exact=JSExtendableArray], element: [subclass=JSInt], length: null)*/ add(
+      100);
+
+  var lists = [
+    listEmptyDefault,
+    listEmptyGrowable,
+    listEmptyFixed,
+    listEmptyEither,
+    listFilledDefault,
+    listFilledGrowable,
+    listFilledFixed,
+    listFilledEither,
+    listGenerateDefault,
+    listGenerateGrowable,
+    listGenerateFixed,
+    listGenerateEither,
+    listOfDefault,
+    listOfGrowable,
+    listOfFixed,
+    listOfEither,
+    listFromDefault,
+    listFromGrowable,
+    listFromFixed,
+    listFromEither,
+    listUnmodifiable,
+  ];
+}
+
+/*member: boolFlag:[exact=JSBool]*/
+bool boolFlag = true;
+
+/*member: data:Container([exact=JSExtendableArray], element: [subclass=JSInt], length: null)*/
+List<int> data = [-1, 1];
+
+// -------- List.empty --------
+
+/*member: listEmptyDefault:Container([exact=JSFixedArray], element: [empty], length: 0)*/
+get listEmptyDefault => List<int>.empty();
+
+/*member: listEmptyGrowable:Container([exact=JSExtendableArray], element: [empty], length: 0)*/
+get listEmptyGrowable => List<int>.empty(growable: true);
+
+/*member: listEmptyFixed:Container([exact=JSFixedArray], element: [empty], length: 0)*/
+get listEmptyFixed => List<int>.empty(growable: false);
+
+/*member: listEmptyEither:Container([subclass=JSMutableArray], element: [empty], length: 0)*/
+get listEmptyEither => List<int>.empty(growable: boolFlag);
+
+// -------- List.filled --------
+
+/*member: listFilledDefault:Container([exact=JSFixedArray], element: Value([exact=JSString], value: "x"), length: 5)*/
+get listFilledDefault => List.filled(5, 'x');
+
+/*member: listFilledGrowable:Container([exact=JSExtendableArray], element: Value([exact=JSString], value: "g"), length: 5)*/
+get listFilledGrowable => List.filled(5, 'g', growable: true);
+
+/*member: listFilledFixed:Container([exact=JSFixedArray], element: Value([exact=JSString], value: "f"), length: 5)*/
+get listFilledFixed => List.filled(5, 'f', growable: false);
+
+/*member: listFilledEither:Container([subclass=JSMutableArray], element: Value([exact=JSString], value: "e"), length: 5)*/
+get listFilledEither => List.filled(5, 'e', growable: boolFlag);
+
+// -------- List.generate --------
+
+/*member: listGenerateDefault:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: 8)*/
+get listGenerateDefault => List.generate(
+    8, /*[exact=JSString]*/ (/*[subclass=JSPositiveInt]*/ i) => 'x$i');
+
+/*member: listGenerateGrowable:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: 8)*/
+get listGenerateGrowable => List.generate(
+    8, /*[exact=JSString]*/ (/*[subclass=JSPositiveInt]*/ i) => 'g$i',
+    growable: true);
+
+/*member: listGenerateFixed:Container([exact=JSFixedArray], element: [null|subclass=Object], length: 8)*/
+get listGenerateFixed => List.generate(
+    8, /*[exact=JSString]*/ (/*[subclass=JSPositiveInt]*/ i) => 'f$i',
+    growable: false);
+
+/*member: listGenerateEither:Container([subclass=JSMutableArray], element: [null|subclass=Object], length: 8)*/
+get listGenerateEither => List.generate(
+    8, /*[exact=JSString]*/ (/*[subclass=JSPositiveInt]*/ i) => 'e$i',
+    growable: boolFlag);
+
+// -------- List.of --------
+
+/*member: listOfDefault:[exact=JSExtendableArray]*/
+get listOfDefault => List.of(data);
+
+/*member: listOfGrowable:[exact=JSExtendableArray]*/
+get listOfGrowable => List.of(data, growable: true);
+
+/*member: listOfFixed:[exact=JSFixedArray]*/
+get listOfFixed => List.of(data, growable: false);
+
+/*member: listOfEither:[subclass=JSMutableArray]*/
+get listOfEither => List.of(data, growable: boolFlag);
+
+// -------- List.from --------
+
+/*member: listFromDefault:[exact=JSExtendableArray]*/
+get listFromDefault => List.from(data);
+
+/*member: listFromGrowable:[exact=JSExtendableArray]*/
+get listFromGrowable => List.from(data, growable: true);
+
+/*member: listFromFixed:[exact=JSFixedArray]*/
+get listFromFixed => List.from(data, growable: false);
+
+/*member: listFromEither:[subclass=JSMutableArray]*/
+get listFromEither => List.from(data, growable: boolFlag);
+
+// -------- List.unmodifiable --------
+
+/*member: listUnmodifiable:[exact=JSUnmodifiableArray]*/
+get listUnmodifiable => List.unmodifiable(data);
diff --git a/pkg/compiler/test/inference/data/logical.dart b/pkg/compiler/test/inference/data/logical.dart
index 6f0c127..9f16905 100644
--- a/pkg/compiler/test/inference/data/logical.dart
+++ b/pkg/compiler/test/inference/data/logical.dart
@@ -72,14 +72,14 @@
 /// Return negation of `false`.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: returnNotFalse:[exact=JSBool]*/
+/*member: returnNotFalse:Value([exact=JSBool], value: true)*/
 returnNotFalse() => !false;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return negation of `true`.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: returnNotTrue:[exact=JSBool]*/
+/*member: returnNotTrue:Value([exact=JSBool], value: false)*/
 returnNotTrue() => !true;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -104,13 +104,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 /// Return value of an is `int` test known to be true.
 ////////////////////////////////////////////////////////////////////////////////
-/*member: returnIsOneInt:[exact=JSBool]*/
+/*member: returnIsOneInt:Value([exact=JSBool], value: true)*/
 returnIsOneInt() => 1 is int;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return value of an is `int` test known to be false.
 ////////////////////////////////////////////////////////////////////////////////
-/*member: returnIsNullInt:[exact=JSBool]*/
+/*member: returnIsNullInt:Value([exact=JSBool], value: false)*/
 returnIsNullInt() => null is int;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -128,13 +128,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 /// Return value of a negated is `int` test known to be false.
 ////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotIsOneInt:[exact=JSBool]*/
+/*member: returnNotIsOneInt:Value([exact=JSBool], value: false)*/
 returnNotIsOneInt() => 1 is! int;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return value of a negated is `int` test known to be true.
 ////////////////////////////////////////////////////////////////////////////////
-/*member: returnNotIsNullInt:[exact=JSBool]*/
+/*member: returnNotIsNullInt:Value([exact=JSBool], value: true)*/
 returnNotIsNullInt() => null is! int;
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/data/mixin_constructor_default_parameter_values/lib.dart b/pkg/compiler/test/inference/data/mixin_constructor_default_parameter_values/lib.dart
index 3fc8ed9..caf5f21 100644
--- a/pkg/compiler/test/inference/data/mixin_constructor_default_parameter_values/lib.dart
+++ b/pkg/compiler/test/inference/data/mixin_constructor_default_parameter_values/lib.dart
@@ -15,13 +15,12 @@
   /*member: C.x:[exact=JSUInt31]*/
   final int x;
 
-  /*member: C.y:Union(null, [exact=JSString], [exact=_SECRET])*/
+  /*member: C.y:Union([exact=JSString], [exact=_SECRET])*/
   final y;
 
   /*member: C.a:[exact=C]*/
   C.a(int /*[exact=JSUInt31]*/ x,
-      [var /*Value([null|exact=JSString], value: "overt")*/ b =
-          const _SECRET()])
+      [var /*Union([exact=JSString], [exact=_SECRET])*/ b = const _SECRET()])
       : this.x = x,
         this.y = b;
 
diff --git a/pkg/compiler/test/inference/data/simple.dart b/pkg/compiler/test/inference/data/simple.dart
index 0fc4b6f..7709e28 100644
--- a/pkg/compiler/test/inference/data/simple.dart
+++ b/pkg/compiler/test/inference/data/simple.dart
@@ -80,14 +80,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 /*member: minusOne:[subclass=JSInt]*/
-minusOne() => /*invoke: [exact=JSUInt31]*/ -1;
+minusOne() => -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return a negative double literal.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: minusHalf:[subclass=JSNumber]*/
-minusHalf() => /*invoke: [exact=JSDouble]*/ -0.5;
+/*member: minusHalf:[exact=JSDouble]*/
+minusHalf() => -0.5;
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return an empty string.
@@ -107,14 +107,14 @@
 /// Return a string juxtaposition.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: stringJuxtaposition:[exact=JSString]*/
+/*member: stringJuxtaposition:Value([exact=JSString], value: "foobar")*/
 stringJuxtaposition() => 'foo' 'bar';
 
 ////////////////////////////////////////////////////////////////////////////////
 /// Return a string constant interpolation.
 ////////////////////////////////////////////////////////////////////////////////
 
-/*member: stringConstantInterpolation:[exact=JSString]*/
+/*member: stringConstantInterpolation:Value([exact=JSString], value: "foobar")*/
 stringConstantInterpolation() => 'foo${'bar'}';
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/data/static.dart b/pkg/compiler/test/inference/data/static.dart
index f641d1a..d34d4fc 100644
--- a/pkg/compiler/test/inference/data/static.dart
+++ b/pkg/compiler/test/inference/data/static.dart
@@ -181,7 +181,7 @@
 /*member: _field1:[null]*/
 dynamic _field1;
 
-/*member: invokeStaticFieldUninitialized:[null|subclass=Object]*/
+/*member: invokeStaticFieldUninitialized:[empty]*/
 invokeStaticFieldUninitialized() => _field1();
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/pkg/compiler/test/inference/side_effects/string_interpolation.dart b/pkg/compiler/test/inference/side_effects/string_interpolation.dart
index 444f3f1..4176998 100644
--- a/pkg/compiler/test/inference/side_effects/string_interpolation.dart
+++ b/pkg/compiler/test/inference/side_effects/string_interpolation.dart
@@ -5,9 +5,9 @@
 // @dart = 2.7
 
 /*member: stringInterpolation:SideEffects(reads nothing; writes anything)*/
-stringInterpolation() => '${null}';
+stringInterpolation(o) => '${o}';
 
 /*member: main:SideEffects(reads nothing; writes anything)*/
 main() {
-  stringInterpolation();
+  stringInterpolation(null);
 }
diff --git a/pkg/compiler/test/jsinterop/declaration_test.dart b/pkg/compiler/test/jsinterop/declaration_test.dart
index 0c3a2ce..5561004 100644
--- a/pkg/compiler/test/jsinterop/declaration_test.dart
+++ b/pkg/compiler/test/jsinterop/declaration_test.dart
@@ -94,19 +94,6 @@
 
 main() => new A();
 '''),
-  const Test('Js-interop class with instance method.', '''
-@JS()
-library test;
-
-import 'package:js/js.dart';
-
-@JS()
-class A {
-  method() {}
-}
-
-main() => new A();
-''', errors: const [MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER]),
   const Test(
       'Js-interop class with abstract getter.',
       '''
diff --git a/pkg/compiler/test/jsinterop/interop_anonymous_unreachable_test.dart b/pkg/compiler/test/jsinterop/interop_anonymous_unreachable_test.dart
index ded9c90..2e4e586 100644
--- a/pkg/compiler/test/jsinterop/interop_anonymous_unreachable_test.dart
+++ b/pkg/compiler/test/jsinterop/interop_anonymous_unreachable_test.dart
@@ -80,16 +80,6 @@
   Expect.isTrue(generated1.contains("UniqueLongNameForTesting_B"));
   Expect.isTrue(generated1.contains("UniqueLongNameForTesting_C"));
   Expect.isTrue(generated1.contains("UniqueLongNameForTesting_E"));
-
-  print(' - tree-shake when using flag -');
-  String generated2 = await compile(program,
-      trustJSInteropTypeAnnotations: true, returnAll: true);
-  Expect.isTrue(generated2.contains("UniqueLongNameForTesting_A"));
-  Expect.isTrue(generated2.contains("UniqueLongNameForTesting_D"));
-
-  Expect.isFalse(generated2.contains("UniqueLongNameForTesting_B"));
-  Expect.isFalse(generated2.contains("UniqueLongNameForTesting_C"));
-  Expect.isFalse(generated2.contains("UniqueLongNameForTesting_E"));
 }
 
 testTreeShakingNativeTypes() async {
@@ -122,14 +112,6 @@
   // but we exclude other native types like HTMLAudioElement
   Expect.isFalse(generated1.contains("HTMLAudioElement"));
 
-  print(' - allocation effect of dynamic excludes native types [flag] -');
-  // Trusting types doesn't make a difference.
-  String generated2 = await compile(program,
-      trustJSInteropTypeAnnotations: true, returnAll: true);
-  Expect.isTrue(generated2.contains("UniqueLongNameForTesting_A"));
-  Expect.isTrue(generated2.contains("UniqueLongNameForTesting_B"));
-  Expect.isFalse(generated2.contains("HTMLAudioElement"));
-
   print(' - declared native types are included in allocation effect -');
   String program2 = """
         import 'dart:html';
diff --git a/pkg/compiler/test/model/cfe_annotations_test.dart b/pkg/compiler/test/model/cfe_annotations_test.dart
index 20e0c2b..e84ee78 100644
--- a/pkg/compiler/test/model/cfe_annotations_test.dart
+++ b/pkg/compiler/test/model/cfe_annotations_test.dart
@@ -206,7 +206,7 @@
         void testMember(String idPrefix, ir.Member member,
             {bool implicitJsInteropMember, bool implicitNativeMember}) {
           if (memberIsIgnorable(member)) return;
-          String memberId = '$idPrefix::${member.name.name}';
+          String memberId = '$idPrefix::${member.name.text}';
           MemberEntity memberEntity = elementMap.getMember(member);
 
           String expectedJsInteropMemberName =
diff --git a/pkg/compiler/test/rti/data/runtime_type_equals3.dart b/pkg/compiler/test/rti/data/runtime_type_equals3.dart
index 3b3ab44..ca06e3e 100644
--- a/pkg/compiler/test/rti/data/runtime_type_equals3.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_equals3.dart
@@ -8,8 +8,10 @@
 
 /*class: Class1a:needsArgs*/
 class Class1a<T> {
+  /*member: Class1a.:*/
   Class1a();
 
+  /*member: Class1a.==:*/
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return runtimeType == other?.runtimeType;
@@ -18,6 +20,7 @@
 
 /*class: Class1b:needsArgs*/
 class Class1b<T> extends Class1a<T> {
+  /*member: Class1b.:*/
   Class1b();
 }
 
@@ -25,13 +28,17 @@
 // this class.
 /*class: Class1c:needsArgs*/
 class Class1c<T> implements Class1a<T> {
+  /*member: Class1c.:*/
   Class1c();
 }
 
+/*class: Class2:*/
 class Class2<T> {
+  /*member: Class2.:*/
   Class2();
 }
 
+/*member: main:*/
 main() {
   Class1a<int> cls1a = new Class1a<int>();
   Class1a<int> cls1b1 = new Class1b<int>();
diff --git a/pkg/compiler/test/rti/data/runtime_type_equals4.dart b/pkg/compiler/test/rti/data/runtime_type_equals4.dart
index a975295..220d033 100644
--- a/pkg/compiler/test/rti/data/runtime_type_equals4.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_equals4.dart
@@ -8,8 +8,10 @@
 
 /*class: Class1a:needsArgs*/
 class Class1a<T> {
+  /*member: Class1a.:*/
   Class1a();
 
+  /*member: Class1a.==:*/
   bool operator ==(other) {
     if (identical(this, other)) return true;
     return other?.runtimeType == runtimeType;
@@ -18,6 +20,7 @@
 
 /*class: Class1b:needsArgs*/
 class Class1b<T> extends Class1a<T> {
+  /*member: Class1b.:*/
   Class1b();
 }
 
@@ -25,13 +28,17 @@
 // this class.
 /*class: Class1c:needsArgs*/
 class Class1c<T> implements Class1a<T> {
+  /*member: Class1c.:*/
   Class1c();
 }
 
+/*class: Class2:*/
 class Class2<T> {
+  /*member: Class2.:*/
   Class2();
 }
 
+/*member: main:*/
 main() {
   Class1a<int> cls1a = new Class1a<int>();
   Class1a<int> cls1b1 = new Class1b<int>();
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 757bdf3..191de63 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dart_internal
-version: 0.1.11-nullsafety
+version: 0.1.12-nullsafety
 author: "Dart Team <misc@dartlang.org>"
 homepage: http://www.dartlang.org
 repository: https://github.com/dart-lang/sdk/tree/master/pkg/dart_internal
@@ -18,4 +18,4 @@
 environment:
   # Restrict the upper bound so that we can remove support for this in a later
   # version of the SDK without it being a breaking change.
-  sdk: ">=2.10.0-0.0 <2.10.0"
+  sdk: ">=2.10.0-0 <2.11.0"
diff --git a/pkg/dartdev/analysis_options.yaml b/pkg/dartdev/analysis_options.yaml
index 4416a89..5168988 100644
--- a/pkg/dartdev/analysis_options.yaml
+++ b/pkg/dartdev/analysis_options.yaml
@@ -12,53 +12,11 @@
 
 linter:
   rules:
-    - avoid_function_literals_in_foreach_calls
-    - avoid_private_typedef_functions
-    - avoid_redundant_argument_values
-    - avoid_renaming_method_parameters
-    - avoid_returning_null_for_void
-    - avoid_void_async
-    - await_only_futures
-    - camel_case_types
-    - constant_identifier_names
+    - always_declare_return_types
     - directives_ordering
-    - empty_statements
-    - file_names
-    - iterable_contains_unrelated_type
-    - lines_longer_than_80_chars
-    - list_remove_unrelated_type
-    - missing_whitespace_between_adjacent_strings
-    - no_runtimeType_toString
-    - non_constant_identifier_names
-    - only_throw_errors
     - overridden_fields
-    - package_names
-    - package_prefixed_library_names
-    - prefer_asserts_in_initializer_lists
-    - prefer_const_constructors
-    - prefer_const_declarations
-    - prefer_function_declarations_over_variables
-    - prefer_initializing_formals
-    - prefer_inlined_adds
-    - prefer_interpolation_to_compose_strings
-    - prefer_is_not_operator
-    - prefer_final_fields
-    - prefer_null_aware_operators
-    - prefer_relative_imports
-    - prefer_typing_uninitialized_variables
-    - prefer_void_to_null
-    - provide_deprecation_message
+    - prefer_single_quotes
     - sort_pub_dependencies
-    - test_types_in_equals
-    - throw_in_finally
-    - type_annotate_public_apis
     - unnecessary_brace_in_string_interps
-    - unnecessary_lambdas
-    - unnecessary_null_aware_assignments
     - unnecessary_overrides
     - unnecessary_parenthesis
-    - unnecessary_statements
-    - unnecessary_string_interpolations
-    - use_is_even_rather_than_modulo
-    - use_string_buffers
-    - void_checks
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index 41f0901..a6ec4bf 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -36,15 +36,15 @@
   final stopwatch = Stopwatch();
   int result;
 
-  // The exit code for the dartdev process, null indicates that it has not yet
-  // been set yet. The value is set in the catch and finally blocks below.
+  // The exit code for the dartdev process; null indicates that it has not been
+  // set yet. The value is set in the catch and finally blocks below.
   int exitCode;
 
-  // Any caught non-UsageExceptions when running the sub command
+  // Any caught non-UsageExceptions when running the sub command.
   Object exception;
   StackTrace stackTrace;
 
-  // The Analytics instance used to report information back to Google Analytics,
+  // The Analytics instance used to report information back to Google Analytics;
   // see lib/src/analytics.dart.
   Analytics analytics =
       createAnalyticsInstance(args.contains('--disable-dartdev-analytics'));
@@ -67,52 +67,31 @@
     // enableAnalytics), in which we favor the disabling of analytics.
     analytics.enabled = false;
 
-    // Alert the user that analytics have been disabled:
+    // Alert the user that analytics has been disabled.
     print(analyticsDisabledNoticeMessage);
     io.exit(0);
   } else if (args.contains('--enable-analytics')) {
     analytics.enabled = true;
 
-    // Alert the user again that anonymous data will be collected:
+    // Alert the user again that anonymous data will be collected.
     print(analyticsNoticeOnFirstRunMessage);
     io.exit(0);
   }
 
-  // --launch-dds is provided by the VM if the VM service is to be enabled. In
-  // that case, we need to launch DDS as well.
-  final launchDdsArg = args.singleWhere(
-    (element) => element.startsWith('--launch-dds'),
-    orElse: () => null,
-  );
-  if (launchDdsArg != null) {
-    // TODO(bkonyi): uncomment after 2.10 branch.
-    // RunCommand.launchDds = true;
-    // final ddsUrl = (launchDdsArg.split('=')[1]).split(':');
-    // RunCommand.ddsHost = ddsUrl[0];
-    // RunCommand.ddsPort = ddsUrl[1];
-  }
-
   String commandName;
 
   try {
     stopwatch.start();
     final runner = DartdevRunner(args);
 
-    // Run can't be called with the '--disable-dartdev-analytics' flag, remove
+    // Run can't be called with the '--disable-dartdev-analytics' flag; remove
     // it if it is contained in args.
     if (args.contains('--disable-dartdev-analytics')) {
       args = List.from(args)..remove('--disable-dartdev-analytics');
     }
 
-    // Run also can't be called with '--launch-dds', remove it if it's
-    // contained in args.
-    if (launchDdsArg != null) {
-      args = List.from(args)..remove(launchDdsArg);
-    }
-
-    // These flags have a format that can't be handled by package:args, so
-    // while they are valid flags we'll assume the VM has verified them by this
-    // point.
+    // These flags have a format that can't be handled by package:args, so while
+    // they are valid flags we'll assume the VM has verified them by this point.
     args = args
         .where(
           (element) => !(element.contains('--observe') ||
@@ -121,17 +100,16 @@
         .toList();
 
     // If ... help pub ... is in the args list, remove 'help', and add '--help'
-    // to the end of the list.  This will make it possible to use the help
-    // command to access subcommands of pub such as `dart help pub publish`, see
-    // https://github.com/dart-lang/sdk/issues/42965
+    // to the end of the list. This will make it possible to use the help
+    // command to access subcommands of pub such as `dart help pub publish`; see
+    // https://github.com/dart-lang/sdk/issues/42965.
     if (PubUtils.shouldModifyArgs(args, runner.commands.keys.toList())) {
       args = PubUtils.modifyArgs(args);
     }
 
     // For the commands format and migrate, dartdev itself sends the
-    // sendScreenView notification to analytics, for all other
-    // dartdev commands (instances of DartdevCommand) the commands send this
-    // to analytics.
+    // sendScreenView notification to analytics; for all other dartdev commands
+    // (instances of DartdevCommand) the commands send it to analytics.
     commandName = ArgParserUtils.getCommandStr(args);
     if (analytics.enabled &&
         (commandName == formatCmdName || commandName == migrateCmdName)) {
@@ -139,7 +117,7 @@
       analytics.sendScreenView(commandName);
     }
 
-    // Finally, call the runner to execute the command, see DartdevRunner.
+    // Finally, call the runner to execute the command; see DartdevRunner.
     result = await runner.run(args);
   } catch (e, st) {
     if (e is UsageException) {
@@ -194,8 +172,8 @@
     }
 
     // Set the enabled flag in the analytics object to true. Note: this will not
-    // enable the analytics unless the disclosure was shown (terminal
-    // detected), and the machine is not detected to be a bot.
+    // enable the analytics unless the disclosure was shown (terminal detected),
+    // and the machine is not detected to be a bot.
     if (analytics.firstRun) {
       analytics.enabled = true;
     }
@@ -239,11 +217,6 @@
       hide: true,
     );
 
-    // Another hidden flag used by the VM to indicate that DDS should be
-    // launched. Should be removed for all commands other than `run`.
-    argParser.addFlag('launch-dds',
-        negatable: false, hide: true, help: 'Launch DDS.');
-
     addCommand(AnalyzeCommand());
     addCommand(CreateCommand(verbose: verbose));
     addCommand(CompileCommand());
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
new file mode 100644
index 0000000..907b5104
--- /dev/null
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -0,0 +1,339 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server_client/protocol.dart'
+    show EditBulkFixesResult, ResponseDecoder;
+import 'package:path/path.dart' as path;
+
+import 'core.dart';
+import 'sdk.dart';
+import 'utils.dart';
+
+/// A class to provide an API wrapper around an analysis server process.
+class AnalysisServer {
+  AnalysisServer(this.sdkPath, this.directory);
+
+  final Directory sdkPath;
+  final Directory directory;
+
+  Process _process;
+
+  Completer<bool> _analysisFinished = Completer();
+
+  int _id = 0;
+
+  Stream<bool> get onAnalyzing {
+    // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
+    return _streamController('server.status')
+        .stream
+        .where((event) => event['analysis'] != null)
+        .map((event) => event['analysis']['isAnalyzing'] as bool);
+  }
+
+  /// This future completes when we next receive an analysis finished event
+  /// (unless there's no current analysis and we've already received a complete
+  /// event, in which case this future completes immediately).
+  Future<bool> get analysisFinished => _analysisFinished.future;
+
+  Stream<FileAnalysisErrors> get onErrors {
+    // {"event":"analysis.errors","params":{"file":"/Users/.../lib/main.dart","errors":[]}}
+    return _streamController('analysis.errors').stream.map((event) {
+      final file = event['file'] as String;
+      final errorsList = event['errors'] as List<dynamic>;
+      final errors = errorsList
+          .map<Map<String, dynamic>>(castStringKeyedMap)
+          .map<AnalysisError>(
+              (Map<String, dynamic> json) => AnalysisError(json))
+          .toList();
+      return FileAnalysisErrors(file, errors);
+    });
+  }
+
+  Future<int> get onExit => _process.exitCode;
+
+  final Map<String, StreamController<Map<String, dynamic>>> _streamControllers =
+      {};
+
+  final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};
+
+  Future<void> start() async {
+    final List<String> command = <String>[
+      sdk.analysisServerSnapshot,
+      '--disable-server-feature-completion',
+      '--disable-server-feature-search',
+      '--sdk',
+      sdkPath.path,
+    ];
+
+    _process = await startDartProcess(sdk, command);
+    // This callback hookup can't throw.
+    // ignore: unawaited_futures
+    _process.exitCode.whenComplete(() => _process = null);
+
+    final Stream<String> errorStream = _process.stderr
+        .transform<String>(utf8.decoder)
+        .transform<String>(const LineSplitter());
+    errorStream.listen(log.stderr);
+
+    final Stream<String> inStream = _process.stdout
+        .transform<String>(utf8.decoder)
+        .transform<String>(const LineSplitter());
+    inStream.listen(_handleServerResponse);
+
+    _streamController('server.error').stream.listen(_handleServerError);
+
+    // ignore: unawaited_futures
+    _sendCommand('server.setSubscriptions', params: <String, dynamic>{
+      'subscriptions': <String>['STATUS'],
+    });
+
+    // Reference and trim off any trailing slash, the Dart Analysis Server
+    // protocol throws an error (INVALID_FILE_PATH_FORMAT) if there is a
+    // trailing slash.
+    //
+    // The call to absolute.resolveSymbolicLinksSync() canonicalizes the path to
+    // be passed to the analysis server.
+    var dirPath = trimEnd(
+      directory.absolute.resolveSymbolicLinksSync(),
+      path.context.separator,
+    );
+
+    onAnalyzing.listen((bool isAnalyzing) {
+      if (isAnalyzing && _analysisFinished.isCompleted) {
+        // Start a new completer, to be completed when we receive the
+        // corresponding analysis complete event.
+        _analysisFinished = Completer();
+      } else if (!isAnalyzing && !_analysisFinished.isCompleted) {
+        _analysisFinished.complete(true);
+      }
+    });
+
+    // ignore: unawaited_futures
+    _sendCommand('analysis.setAnalysisRoots', params: <String, dynamic>{
+      'included': [dirPath],
+      'excluded': <String>[]
+    });
+  }
+
+  Future<String> getVersion() {
+    return _sendCommand('server.getVersion')
+        .then((response) => response['version']);
+  }
+
+  Future<EditBulkFixesResult> requestBulkFixes(String filePath) {
+    return _sendCommand('edit.bulkFixes', params: <String, dynamic>{
+      'included': [path.canonicalize(filePath)],
+    }).then((result) {
+      return EditBulkFixesResult.fromJson(
+          ResponseDecoder(null), 'result', result);
+    });
+  }
+
+  Future<void> shutdown({Duration timeout = const Duration(seconds: 5)}) async {
+    // Request shutdown.
+    await _sendCommand('server.shutdown').then((value) {
+      return null;
+    }).timeout(timeout, onTimeout: () async {
+      await dispose();
+    }).then((value) async {
+      await dispose();
+    });
+  }
+
+  Future<Map<String, dynamic>> _sendCommand(String method,
+      {Map<String, dynamic> params}) {
+    final String id = (++_id).toString();
+    final String message = json.encode(<String, dynamic>{
+      'id': id,
+      'method': method,
+      'params': params,
+    });
+
+    _requestCompleters[id] = Completer();
+    _process.stdin.writeln(message);
+
+    log.trace('==> $message');
+
+    return _requestCompleters[id].future;
+  }
+
+  void _handleServerResponse(String line) {
+    log.trace('<== $line');
+
+    final dynamic response = json.decode(line);
+
+    if (response is Map<String, dynamic>) {
+      if (response['event'] != null) {
+        final event = response['event'] as String;
+        final dynamic params = response['params'];
+
+        if (params is Map<String, dynamic>) {
+          _streamController(event).add(castStringKeyedMap(params));
+        }
+      } else if (response['id'] != null) {
+        final id = response['id'];
+
+        if (response['error'] != null) {
+          final error = castStringKeyedMap(response['error']);
+          _requestCompleters
+              .remove(id)
+              ?.completeError(RequestError.parse(error));
+        } else {
+          _requestCompleters.remove(id)?.complete(response['result']);
+        }
+      }
+    }
+  }
+
+  void _handleServerError(Map<String, dynamic> error) {
+    // Fields are 'isFatal', 'message', and 'stackTrace'.
+    log.stderr('Error from the analysis server: ${error['message']}');
+    if (error['stackTrace'] != null) {
+      log.stderr(error['stackTrace'] as String);
+    }
+  }
+
+  StreamController<Map<String, dynamic>> _streamController(String streamId) {
+    return _streamControllers.putIfAbsent(
+        streamId, () => StreamController<Map<String, dynamic>>.broadcast());
+  }
+
+  Future<bool> dispose() async {
+    return _process?.kill();
+  }
+}
+
+enum _AnalysisSeverity {
+  error,
+  warning,
+  info,
+  none,
+}
+
+class AnalysisError implements Comparable<AnalysisError> {
+  AnalysisError(this.json);
+
+  static final Map<String, _AnalysisSeverity> _severityMap =
+      <String, _AnalysisSeverity>{
+    'INFO': _AnalysisSeverity.info,
+    'WARNING': _AnalysisSeverity.warning,
+    'ERROR': _AnalysisSeverity.error,
+  };
+
+  // "severity":"INFO","type":"TODO","location":{
+  //   "file":"/Users/.../lib/test.dart","offset":362,"length":72,"startLine":15,"startColumn":4
+  // },"message":"...","hasFix":false}
+  Map<String, dynamic> json;
+
+  String get severity => json['severity'] as String;
+
+  _AnalysisSeverity get _severityLevel =>
+      _severityMap[severity] ?? _AnalysisSeverity.none;
+
+  bool get isInfo => _severityLevel == _AnalysisSeverity.info;
+
+  bool get isWarning => _severityLevel == _AnalysisSeverity.warning;
+
+  bool get isError => _severityLevel == _AnalysisSeverity.error;
+
+  String get type => json['type'] as String;
+
+  String get message => json['message'] as String;
+
+  String get code => json['code'] as String;
+
+  String get correction => json['correction'] as String;
+
+  String get file => json['location']['file'] as String;
+
+  int get startLine => json['location']['startLine'] as int;
+
+  int get startColumn => json['location']['startColumn'] as int;
+
+  int get offset => json['location']['offset'] as int;
+
+  String get messageSentenceFragment => trimEnd(message, '.');
+
+  String get url => json['url'] as String;
+
+  List<DiagnosticMessage> get contextMessages {
+    var messages = json['contextMessages'] as List<dynamic>;
+    if (messages == null) {
+      // The field is optional, so we return an empty list as a default value.
+      return [];
+    }
+    return messages.map((message) => DiagnosticMessage(message)).toList();
+  }
+
+  // TODO(jwren) add some tests to verify that the results are what we are
+  // expecting, 'other' is not always on the RHS of the subtraction in the
+  // implementation.
+  @override
+  int compareTo(AnalysisError other) {
+    // Sort in order of file path, error location, severity, and message.
+    if (file != other.file) {
+      return file.compareTo(other.file);
+    }
+
+    if (offset != other.offset) {
+      return offset - other.offset;
+    }
+
+    final int diff = other._severityLevel.index - _severityLevel.index;
+    if (diff != 0) {
+      return diff;
+    }
+
+    return message.compareTo(other.message);
+  }
+
+  @override
+  String toString() => '${severity.toLowerCase()} • '
+      '$messageSentenceFragment at $file:$startLine:$startColumn • '
+      '($code)';
+}
+
+class DiagnosticMessage {
+  final Map<String, dynamic> json;
+
+  DiagnosticMessage(this.json);
+
+  int get column => json['location']['startColumn'] as int;
+
+  String get filePath => json['location']['file'] as String;
+
+  int get line => json['location']['startLine'] as int;
+
+  String get message => json['message'] as String;
+}
+
+class FileAnalysisErrors {
+  final String file;
+  final List<AnalysisError> errors;
+
+  FileAnalysisErrors(this.file, this.errors);
+}
+
+class RequestError {
+  static RequestError parse(dynamic error) {
+    return RequestError(
+      error['code'],
+      error['message'],
+      stackTrace: error['stackTrace'],
+    );
+  }
+
+  final String code;
+  final String message;
+  final String stackTrace;
+
+  RequestError(this.code, this.message, {this.stackTrace});
+
+  @override
+  String toString() => '[RequestError code: $code, message: $message]';
+}
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 08d8590..80ef119 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -3,16 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
+import 'dart:io' as io;
 
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
+import '../analysis_server.dart';
 import '../core.dart';
 import '../events.dart';
 import '../sdk.dart';
 import '../utils.dart';
-import 'analyze_impl.dart';
 
 class AnalyzeCommand extends DartdevCommand<int> {
   static const String cmdName = 'analyze';
@@ -43,29 +43,21 @@
 
     // find directory from argResults.rest
     var dir = argResults.rest.isEmpty
-        ? Directory.current
-        : Directory(argResults.rest.single);
+        ? io.Directory.current
+        : io.Directory(argResults.rest.single);
     if (!dir.existsSync()) {
       usageException("Directory doesn't exist: ${dir.path}");
     }
 
-    final Completer<void> analysisCompleter = Completer<void>();
     final List<AnalysisError> errors = <AnalysisError>[];
 
     var progress = log.progress('Analyzing ${path.basename(dir.path)}');
 
     final AnalysisServer server = AnalysisServer(
-      Directory(sdk.sdkPath),
-      [dir],
+      io.Directory(sdk.sdkPath),
+      dir,
     );
 
-    StreamSubscription<bool> subscription;
-    subscription = server.onAnalyzing.listen((bool isAnalyzing) {
-      if (!isAnalyzing) {
-        analysisCompleter.complete();
-        subscription.cancel();
-      }
-    });
     server.onErrors.listen((FileAnalysisErrors fileErrors) {
       // Record the issues found (but filter out to do comments).
       errors.addAll(fileErrors.errors
@@ -73,89 +65,94 @@
     });
 
     await server.start();
-    // Completing the future in the callback can't fail.
-    //ignore: unawaited_futures
+
+    bool analysisFinished = false;
+
+    // ignore: unawaited_futures
     server.onExit.then((int exitCode) {
-      if (!analysisCompleter.isCompleted) {
-        analysisCompleter.completeError('analysis server exited: $exitCode');
+      if (!analysisFinished) {
+        io.exitCode = exitCode;
       }
     });
 
-    await analysisCompleter.future;
-    await server.dispose();
+    await server.analysisFinished;
+    analysisFinished = true;
+
+    await server.shutdown(timeout: Duration(milliseconds: 100));
+
     progress.finish(showTiming: true);
 
     errors.sort();
 
-    if (errors.isNotEmpty) {
-      final bullet = log.ansi.bullet;
-
-      log.stdout('');
-
-      bool hasErrors = false;
-      bool hasWarnings = false;
-      bool hasInfos = false;
-
-      for (final AnalysisError error in errors) {
-        // error • Message ... at path.dart:line:col • (code)
-
-        var filePath = path.relative(error.file, from: dir.path);
-        var severity = error.severity.toLowerCase().padLeft(_severityWidth);
-        if (error.isError) {
-          severity = log.ansi.error(severity);
-        }
-
-        log.stdout(
-          '$severity $bullet '
-          '${log.ansi.emphasized(error.messageSentenceFragment)} '
-          'at $filePath:${error.startLine}:${error.startColumn} $bullet '
-          '(${error.code})',
-        );
-
-        if (verbose) {
-          var padding = ' ' * _bodyIndentWidth;
-          for (var message in error.contextMessages) {
-            log.stdout('$padding${message.message} '
-                'at ${message.filePath}:${message.line}:${message.column}');
-          }
-          if (error.correction != null) {
-            log.stdout('$padding${error.correction}');
-          }
-          if (error.url != null) {
-            log.stdout('$padding${error.url}');
-          }
-        }
-
-        hasErrors |= error.isError;
-        hasWarnings |= error.isWarning;
-        hasInfos |= error.isInfo;
-      }
-
-      log.stdout('');
-
-      final errorCount = errors.length;
-      log.stdout('$errorCount ${pluralize('issue', errorCount)} found.');
-
-      // Return an error code in the range [0-3] dependent on the severity of
-      // the issue(s) found.
-      if (hasErrors) {
-        return 3;
-      }
-
-      bool fatalWarnings = argResults['fatal-warnings'];
-      bool fatalInfos = argResults['fatal-infos'];
-
-      if (fatalWarnings && hasWarnings) {
-        return 2;
-      } else if (fatalInfos && hasInfos) {
-        return 1;
-      } else {
-        return 0;
-      }
-    } else {
+    if (errors.isEmpty) {
       log.stdout('No issues found!');
       return 0;
     }
+
+    final bullet = log.ansi.bullet;
+
+    log.stdout('');
+
+    bool hasErrors = false;
+    bool hasWarnings = false;
+    bool hasInfos = false;
+
+    for (final AnalysisError error in errors) {
+      // error • Message ... at path.dart:line:col • (code)
+
+      var filePath = path.relative(error.file, from: dir.path);
+      var severity = error.severity.toLowerCase().padLeft(_severityWidth);
+      if (error.isError) {
+        severity = log.ansi.error(severity);
+      }
+
+      log.stdout(
+        '$severity $bullet '
+        '${log.ansi.emphasized(error.messageSentenceFragment)} '
+        'at $filePath:${error.startLine}:${error.startColumn} $bullet '
+        '(${error.code})',
+      );
+
+      if (verbose) {
+        var padding = ' ' * _bodyIndentWidth;
+        for (var message in error.contextMessages) {
+          log.stdout('$padding${message.message} '
+              'at ${message.filePath}:${message.line}:${message.column}');
+        }
+        if (error.correction != null) {
+          log.stdout('$padding${error.correction}');
+        }
+        if (error.url != null) {
+          log.stdout('$padding${error.url}');
+        }
+      }
+
+      hasErrors |= error.isError;
+      hasWarnings |= error.isWarning;
+      hasInfos |= error.isInfo;
+    }
+
+    log.stdout('');
+
+    final errorCount = errors.length;
+    log.stdout('$errorCount ${pluralize('issue', errorCount)} found.');
+
+    // Return an error code in the range [0-3] dependent on the severity of
+    // the issue(s) found.
+    if (hasErrors) {
+      return 3;
+    }
+
+    bool fatalWarnings = argResults['fatal-warnings'];
+    bool fatalInfos = argResults['fatal-infos'];
+
+    if (fatalWarnings && hasWarnings) {
+      return 2;
+    } else if (fatalInfos && hasInfos) {
+      return 1;
+    } else {
+      return 0;
+    }
   }
 
   @override
diff --git a/pkg/dartdev/lib/src/commands/analyze_impl.dart b/pkg/dartdev/lib/src/commands/analyze_impl.dart
deleted file mode 100644
index 714753d..0000000
--- a/pkg/dartdev/lib/src/commands/analyze_impl.dart
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:analysis_server_client/protocol.dart'
-    show EditBulkFixesResult, ResponseDecoder;
-import 'package:path/path.dart' as path;
-
-import '../core.dart';
-import '../sdk.dart';
-import '../utils.dart';
-
-/// A class to provide an API wrapper around an analysis server process.
-class AnalysisServer {
-  AnalysisServer(this.sdkPath, this.directories);
-
-  final Directory sdkPath;
-  final List<Directory> directories;
-
-  Process _process;
-  final StreamController<bool> _analyzingController =
-      StreamController<bool>.broadcast();
-  final StreamController<EditBulkFixesResult> _bulkFixesController =
-      StreamController<EditBulkFixesResult>.broadcast();
-  final StreamController<FileAnalysisErrors> _errorsController =
-      StreamController<FileAnalysisErrors>.broadcast();
-  bool _didServerErrorOccur = false;
-
-  int _id = 0;
-
-  String _fixRequestId;
-
-  bool get didServerErrorOccur => _didServerErrorOccur;
-
-  Stream<bool> get onAnalyzing => _analyzingController.stream;
-
-  Stream<FileAnalysisErrors> get onErrors => _errorsController.stream;
-
-  Stream<EditBulkFixesResult> get onBulkFixes => _bulkFixesController.stream;
-
-  Future<int> get onExit => _process.exitCode;
-
-  Future<void> start() async {
-    final List<String> command = <String>[
-      sdk.analysisServerSnapshot,
-      '--disable-server-feature-completion',
-      '--disable-server-feature-search',
-      '--sdk',
-      sdkPath.path,
-    ];
-
-    _process = await startDartProcess(sdk, command);
-    // This callback hookup can't throw.
-    //ignore: unawaited_futures
-    _process.exitCode.whenComplete(() => _process = null);
-
-    final Stream<String> errorStream = _process.stderr
-        .transform<String>(utf8.decoder)
-        .transform<String>(const LineSplitter());
-    errorStream.listen(log.stderr);
-
-    final Stream<String> inStream = _process.stdout
-        .transform<String>(utf8.decoder)
-        .transform<String>(const LineSplitter());
-    inStream.listen(_handleServerResponse);
-
-    _sendCommand('server.setSubscriptions', <String, dynamic>{
-      'subscriptions': <String>['STATUS'],
-    });
-
-    // Reference and trim off any trailing slash, the Dart Analysis Server
-    // protocol throws an error (INVALID_FILE_PATH_FORMAT) if there is a
-    // trailing slash.
-    //
-    // The call to absolute.resolveSymbolicLinksSync() canonicalizes the path
-    // to be passed to the analysis server.
-    var dirPath = trimEnd(
-      directories.single.absolute.resolveSymbolicLinksSync(),
-      path.context.separator,
-    );
-
-    _sendCommand('analysis.setAnalysisRoots', <String, dynamic>{
-      'included': [dirPath],
-      'excluded': <String>[]
-    });
-  }
-
-  void requestBulkFixes(String filePath) {
-    _sendCommand('edit.bulkFixes', <String, dynamic>{
-      'included': [path.canonicalize(filePath)],
-    });
-    _fixRequestId = _id.toString();
-  }
-
-  void _sendCommand(String method, Map<String, dynamic> params) {
-    final String message = json.encode(<String, dynamic>{
-      'id': (++_id).toString(),
-      'method': method,
-      'params': params,
-    });
-    _process.stdin.writeln(message);
-    log.trace('==> $message');
-  }
-
-  void _handleServerResponse(String line) {
-    log.trace('<== $line');
-
-    final dynamic response = json.decode(line);
-
-    if (response is Map<String, dynamic>) {
-      if (response['event'] != null) {
-        final String event = response['event'] as String;
-        final dynamic params = response['params'];
-
-        if (params is Map<String, dynamic>) {
-          if (event == 'server.status') {
-            _handleStatus(castStringKeyedMap(response['params']));
-          } else if (event == 'analysis.errors') {
-            _handleAnalysisIssues(castStringKeyedMap(response['params']));
-          } else if (event == 'server.error') {
-            _handleServerError(castStringKeyedMap(response['params']));
-          }
-        }
-      } else if (response['error'] != null) {
-        // Fields are 'code', 'message', and 'stackTrace'.
-        final Map<String, dynamic> error =
-            castStringKeyedMap(response['error']);
-        log.stderr(
-          'Error response from the server: '
-          '${error['code']} ${error['message']}',
-        );
-        if (error['stackTrace'] != null) {
-          log.stderr(error['stackTrace'] as String);
-        }
-        // Dispose of the process at this point so the process doesn't hang.
-        dispose();
-      } else if (response['id'] == _fixRequestId) {
-        var decoder = ResponseDecoder(null);
-        var result =
-            EditBulkFixesResult.fromJson(decoder, 'result', response['result']);
-        _bulkFixesController.add(result);
-      }
-    }
-  }
-
-  void _handleStatus(Map<String, dynamic> statusInfo) {
-    // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
-    if (statusInfo['analysis'] != null && !_analyzingController.isClosed) {
-      final bool isAnalyzing = statusInfo['analysis']['isAnalyzing'] as bool;
-      _analyzingController.add(isAnalyzing);
-    }
-  }
-
-  void _handleServerError(Map<String, dynamic> error) {
-    // Fields are 'isFatal', 'message', and 'stackTrace'.
-    log.stderr('Error from the analysis server: ${error['message']}');
-    if (error['stackTrace'] != null) {
-      log.stderr(error['stackTrace'] as String);
-    }
-    _didServerErrorOccur = true;
-  }
-
-  void _handleAnalysisIssues(Map<String, dynamic> issueInfo) {
-    // {"event":"analysis.errors","params":{"file":"/Users/.../lib/main.dart","errors":[]}}
-    final String file = issueInfo['file'] as String;
-    final List<dynamic> errorsList = issueInfo['errors'] as List<dynamic>;
-    final List<AnalysisError> errors = errorsList
-        .map<Map<String, dynamic>>(castStringKeyedMap)
-        .map<AnalysisError>((Map<String, dynamic> json) => AnalysisError(json))
-        .toList();
-    if (!_errorsController.isClosed) {
-      _errorsController.add(FileAnalysisErrors(file, errors));
-    }
-  }
-
-  Future<bool> dispose() async {
-    await _analyzingController.close();
-    await _errorsController.close();
-    return _process?.kill();
-  }
-}
-
-enum _AnalysisSeverity {
-  error,
-  warning,
-  info,
-  none,
-}
-
-class AnalysisError implements Comparable<AnalysisError> {
-  AnalysisError(this.json);
-
-  static final Map<String, _AnalysisSeverity> _severityMap =
-      <String, _AnalysisSeverity>{
-    'INFO': _AnalysisSeverity.info,
-    'WARNING': _AnalysisSeverity.warning,
-    'ERROR': _AnalysisSeverity.error,
-  };
-
-  // "severity":"INFO","type":"TODO","location":{
-  //   "file":"/Users/.../lib/test.dart","offset":362,"length":72,"startLine":15,"startColumn":4
-  // },"message":"...","hasFix":false}
-  Map<String, dynamic> json;
-
-  String get severity => json['severity'] as String;
-
-  _AnalysisSeverity get _severityLevel =>
-      _severityMap[severity] ?? _AnalysisSeverity.none;
-
-  bool get isInfo => _severityLevel == _AnalysisSeverity.info;
-
-  bool get isWarning => _severityLevel == _AnalysisSeverity.warning;
-
-  bool get isError => _severityLevel == _AnalysisSeverity.error;
-
-  String get type => json['type'] as String;
-
-  String get message => json['message'] as String;
-
-  String get code => json['code'] as String;
-
-  String get correction => json['correction'] as String;
-
-  String get file => json['location']['file'] as String;
-
-  int get startLine => json['location']['startLine'] as int;
-
-  int get startColumn => json['location']['startColumn'] as int;
-
-  int get offset => json['location']['offset'] as int;
-
-  String get messageSentenceFragment => trimEnd(message, '.');
-
-  String get url => json['url'] as String;
-
-  List<DiagnosticMessage> get contextMessages {
-    var messages = json['contextMessages'] as List<dynamic>;
-    if (messages == null) {
-      // The field is optional, so we return an empty list as a default value.
-      return [];
-    }
-    return messages.map((message) => DiagnosticMessage(message)).toList();
-  }
-
-  // TODO(jwren) add some tests to verify that the results are what we are
-  //  expecting, 'other' is not always on the RHS of the subtraction in the
-  //  implementation.
-  @override
-  int compareTo(AnalysisError other) {
-    // Sort in order of file path, error location, severity, and message.
-    if (file != other.file) {
-      return file.compareTo(other.file);
-    }
-
-    if (offset != other.offset) {
-      return offset - other.offset;
-    }
-
-    final int diff = other._severityLevel.index - _severityLevel.index;
-    if (diff != 0) {
-      return diff;
-    }
-
-    return message.compareTo(other.message);
-  }
-
-  @override
-  String toString() => '${severity.toLowerCase()} • '
-      '$messageSentenceFragment at $file:$startLine:$startColumn • '
-      '($code)';
-}
-
-class DiagnosticMessage {
-  final Map<String, dynamic> json;
-
-  DiagnosticMessage(this.json);
-
-  int get column => json['location']['startColumn'] as int;
-
-  String get filePath => json['location']['file'] as String;
-
-  int get line => json['location']['startLine'] as int;
-
-  String get message => json['message'] as String;
-}
-
-class FileAnalysisErrors {
-  final String file;
-  final List<AnalysisError> errors;
-
-  FileAnalysisErrors(this.file, this.errors);
-}
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index 338158e..990da09 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -3,17 +3,16 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
+import 'dart:io' as io;
 
 import 'package:analysis_server_client/protocol.dart' hide AnalysisError;
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as path;
 
+import '../analysis_server.dart';
 import '../core.dart';
 import '../events.dart';
 import '../sdk.dart';
-import '../utils.dart';
-import 'analyze_impl.dart';
 
 class FixCommand extends DartdevCommand<int> {
   static const String cmdName = 'fix';
@@ -22,6 +21,13 @@
   FixCommand() : super(cmdName, 'Fix Dart source code.', hidden: true);
 
   @override
+  UsageEvent createUsageEvent(int exitCode) => FixUsageEvent(
+        usagePath,
+        exitCode: exitCode,
+        args: argResults.arguments,
+      );
+
+  @override
   FutureOr<int> runImpl() async {
     log.stdout('\n*** The `fix` command is provisional and subject to change '
         'or removal in future releases. ***\n');
@@ -31,64 +37,64 @@
     }
 
     var dir = argResults.rest.isEmpty
-        ? Directory.current
-        : Directory(argResults.rest.single);
+        ? io.Directory.current
+        : io.Directory(argResults.rest.single);
     if (!dir.existsSync()) {
       usageException("Directory doesn't exist: ${dir.path}");
     }
 
-    var bulkFixCompleter = Completer<void>();
     var progress =
         log.progress('Computing fixes in ${path.basename(dir.path)}');
 
     var server = AnalysisServer(
-      Directory(sdk.sdkPath),
-      [dir],
+      io.Directory(sdk.sdkPath),
+      dir,
     );
 
     await server.start();
+
+    EditBulkFixesResult fixes;
     //ignore: unawaited_futures
     server.onExit.then((int exitCode) {
-      if (!bulkFixCompleter.isCompleted) {
-        bulkFixCompleter.completeError('analysis server exited: $exitCode');
+      if (fixes == null && exitCode != 0) {
+        progress?.cancel();
+        io.exitCode = exitCode;
       }
     });
 
-    List<SourceFileEdit> edits;
-    server.onBulkFixes.listen((EditBulkFixesResult fixes) {
-      edits = fixes.edits;
-      bulkFixCompleter.complete();
-    });
-    server.requestBulkFixes(dir.absolute.path);
+    fixes = await server.requestBulkFixes(dir.absolute.path);
+    final List<SourceFileEdit> edits = fixes.edits;
 
-    await bulkFixCompleter.future;
-    await server.dispose();
+    await server.shutdown();
+
     progress.finish(showTiming: true);
 
     if (edits.isEmpty) {
       log.stdout('Nothing to fix!');
     } else {
-      // todo (pq): consider a summary if more than `n` fixes are applied
-      //  (look at `dartfmt`)
-      log.stdout('Applying fixes to:');
-      for (var edit in edits) {
-        var file = File(edit.file);
-        log.stdout('  ${relativePath(file.path, dir)}');
-        var code = file.existsSync() ? file.readAsStringSync() : '';
-        code = SourceEdit.applySequence(code, edit.edits);
-        file.writeAsStringSync(code);
+      progress = log.progress('Applying fixes');
+      var fileCount = await _applyFixes(edits);
+      progress.finish(showTiming: true);
+      if (fileCount > 0) {
+        log.stdout('Fixed $fileCount files.');
       }
-      log.stdout('Done.');
     }
+
     return 0;
   }
 
-  @override
-  UsageEvent createUsageEvent(int exitCode) => FixUsageEvent(
-        usagePath,
-        exitCode: exitCode,
-        args: argResults.arguments,
-      );
+  Future<int> _applyFixes(List<SourceFileEdit> edits) async {
+    var files = <String>{};
+    for (var edit in edits) {
+      var fileName = edit.file;
+      files.add(fileName);
+      var file = io.File(fileName);
+      var code = await file.exists() ? await file.readAsString() : '';
+      code = SourceEdit.applySequence(code, edit.edits);
+      await file.writeAsString(code);
+    }
+    return files.length;
+  }
 }
 
 /// The [UsageEvent] for the fix command.
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 9fa39e6..ae2ec2a 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -21,10 +21,6 @@
 class RunCommand extends DartdevCommand<int> {
   static const String cmdName = 'run';
 
-  static bool launchDds = false;
-  static String ddsHost;
-  static String ddsPort;
-
   // kErrorExitCode, as defined in runtime/bin/error_exit.h
   static const errorExitCode = 255;
 
@@ -62,6 +58,7 @@
             'with a set of common options useful for debugging.',
         valueHelp: '[<port>[/<bind-address>]]',
       )
+      ..addOption('launch-dds', hide: true, help: 'Launch DDS.')
       ..addSeparator(
         'Options implied by --observe are currently:',
       )
@@ -160,18 +157,39 @@
   FutureOr<int> runImpl() async {
     // The command line arguments after 'run'
     var args = argResults.arguments.toList();
+    // --launch-dds is provided by the VM if the VM service is to be enabled. In
+    // that case, we need to launch DDS as well.
+    bool launchDds = false;
+    String ddsHost = '';
+    String ddsPort = '';
+
+    final launchDdsArg = args.singleWhere(
+      (element) => element.startsWith('--launch-dds'),
+      orElse: () => null,
+    );
+    if (launchDdsArg != null) {
+      launchDds = true;
+      final ddsUrl = (launchDdsArg.split('=')[1]).split(':');
+      ddsHost = ddsUrl[0];
+      ddsPort = ddsUrl[1];
+    }
 
     var argsContainFile = false;
     for (var arg in args) {
       // The arg.contains('.') matches a file name pattern, i.e. some 'foo.dart'
       if (arg.contains('.')) {
         argsContainFile = true;
-      } else if (arg == '--help' || arg == '-h' || arg == 'help') {
+      } else if (!argsContainFile &&
+          (arg == '--help' || arg == '-h' || arg == 'help')) {
+        // Only print usage if a help flag is provided before the script name.
         printUsage();
         return 0;
       }
     }
 
+    var disableServiceAuthCodes =
+        argResults['disable-service-auth-codes'] ?? false;
+
     final cwd = Directory.current;
     if (!argsContainFile && cwd.existsSync()) {
       var foundImplicitFileToRun = false;
@@ -218,7 +236,8 @@
     _DebuggingSession debugSession;
     if (launchDds) {
       debugSession = _DebuggingSession();
-      if (!await debugSession.start()) {
+      if (!await debugSession.start(
+          ddsHost, ddsPort, disableServiceAuthCodes)) {
         return errorExitCode;
       }
     }
@@ -251,7 +270,8 @@
 }
 
 class _DebuggingSession {
-  Future<bool> start() async {
+  Future<bool> start(
+      String host, String port, bool disableServiceAuthCodes) async {
     final serviceInfo = await Service.getInfo();
     final ddsSnapshot = (dirname(sdk.dart).endsWith('bin'))
         ? sdk.ddsSnapshot
@@ -267,8 +287,9 @@
           else
             absolute(dirname(sdk.dart), 'gen', 'dds.dart.snapshot'),
           serviceInfo.serverUri.toString(),
-          RunCommand.ddsHost,
-          RunCommand.ddsPort,
+          host,
+          port,
+          disableServiceAuthCodes.toString(),
         ],
         mode: ProcessStartMode.detachedWithStdio);
     final completer = Completer<void>();
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index ecc93eb..511826b 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -26,5 +26,5 @@
   usage: ^3.4.0
 
 dev_dependencies:
-  test: ^1.0.0
   pedantic: ^1.9.0
+  test: ^1.0.0
diff --git a/pkg/dartdev/test/analysis_server_test.dart b/pkg/dartdev/test/analysis_server_test.dart
new file mode 100644
index 0000000..27f5b3f
--- /dev/null
+++ b/pkg/dartdev/test/analysis_server_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' as io;
+
+import 'package:cli_util/cli_logging.dart';
+import 'package:dartdev/src/analysis_server.dart';
+import 'package:dartdev/src/core.dart';
+import 'package:dartdev/src/sdk.dart';
+import 'package:test/test.dart';
+
+import 'utils.dart';
+
+void main() {
+  group('AnalysisServer', () {
+    TestProject p;
+
+    setUp(() {
+      log = Logger.standard();
+      p = project();
+    });
+
+    tearDown(() => p?.dispose());
+
+    test('can start', () async {
+      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir);
+      await server.start();
+      await server.shutdown();
+    });
+
+    test('can send message', () async {
+      AnalysisServer server = AnalysisServer(io.Directory(sdk.sdkPath), p.dir);
+      await server.start();
+
+      final response = await server.getVersion();
+      expect(response, isNotEmpty);
+
+      await server.shutdown();
+    });
+  });
+}
diff --git a/pkg/dartdev/test/commands/analyze_test.dart b/pkg/dartdev/test/commands/analyze_test.dart
index aa4e2eb..f7791c2 100644
--- a/pkg/dartdev/test/commands/analyze_test.dart
+++ b/pkg/dartdev/test/commands/analyze_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:dartdev/src/commands/analyze_impl.dart';
+import 'package:dartdev/src/analysis_server.dart';
 import 'package:test/test.dart';
 
 import '../utils.dart';
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 5c36e71..fc444ae 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -156,10 +156,29 @@
       '--no-pause-isolates-on-unhandled-exceptions',
       p.relativeFilePath,
     ]);
+    expect(
+      result.stdout,
+      matches(
+          r'Observatory listening on http://127.0.0.1:8181/[a-zA-Z0-9]+=/\n.*'),
+    );
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+
+    // Again, with --disable-service-auth-codes.
+    result = p.runSync('run', [
+      '--observe',
+      '--pause-isolates-on-start',
+      // This should negate the above flag.
+      '--no-pause-isolates-on-start',
+      '--no-pause-isolates-on-exit',
+      '--no-pause-isolates-on-unhandled-exceptions',
+      '--disable-service-auth-codes',
+      p.relativeFilePath,
+    ]);
 
     expect(
       result.stdout,
-      contains('Observatory listening on'),
+      contains('Observatory listening on http://127.0.0.1:8181/\n'),
     );
     expect(result.stderr, isEmpty);
     expect(result.exitCode, 0);
diff --git a/pkg/dartfix/analysis_options.yaml b/pkg/dartfix/analysis_options.yaml
index bfb45bf..4be2194 100644
--- a/pkg/dartfix/analysis_options.yaml
+++ b/pkg/dartfix/analysis_options.yaml
@@ -16,6 +16,7 @@
 
 linter:
   rules:
+    - await_only_futures
     - directives_ordering
     - empty_statements
     - unnecessary_brace_in_string_interps
diff --git a/pkg/dds/CHANGELOG.md b/pkg/dds/CHANGELOG.md
index 96848ba..f959b95 100644
--- a/pkg/dds/CHANGELOG.md
+++ b/pkg/dds/CHANGELOG.md
@@ -1,3 +1,29 @@
+# 1.4.1
+- Fixed issue where `evaluate` and `evaluateInFrame` requests were not being
+  forwarded to the VM service properly when no external compilation service
+  was registered.
+
+# 1.4.0
+- Added `done` property to `DartDevelopmentService`.
+- Throw `DartDeveloperServiceException` when shutdown occurs during startup.
+- Fixed issue where `StateError` was thrown when DDS was shutdown with pending
+  requests.
+
+# 1.3.5
+
+- Fixed issue where clients subscribing to the `Service` stream were not being
+  sent `ServiceRegistered` events on connection.
+
+# 1.3.4
+
+- Fixed issue where `isolateId`s were expected to take the form `isolates/123`
+  although this is not required by the VM service specification.
+
+# 1.3.3
+
+- Fixed issue where `DartDevelopmentService.sseUri` did not return a URI with a
+  `sse` scheme.
+
 # 1.3.2
 
 - Add IPv6 hosting support.
diff --git a/pkg/dds/bin/dds.dart b/pkg/dds/bin/dds.dart
index ed683dd..3ac9a09 100644
--- a/pkg/dds/bin/dds.dart
+++ b/pkg/dds/bin/dds.dart
@@ -13,6 +13,7 @@
 ///   - VM service URI
 ///   - DDS bind address
 ///   - DDS port
+///   - Disable service authentication codes
 Future<void> main(List<String> args) async {
   if (args.isEmpty) return;
 
@@ -33,12 +34,14 @@
     host: address.address,
     port: int.parse(args[2]),
   );
+  final disableServiceAuthCodes = args[3] == 'true';
   try {
     // TODO(bkonyi): add retry logic similar to that in vmservice_server.dart
     // See https://github.com/dart-lang/sdk/issues/43192.
     await DartDevelopmentService.startDartDevelopmentService(
       remoteVmServiceUri,
       serviceUri: serviceUri,
+      enableAuthCodes: !disableServiceAuthCodes,
     );
     stderr.write('DDS started');
   } catch (e) {
diff --git a/pkg/dds/lib/dds.dart b/pkg/dds/lib/dds.dart
index f35e4d3..0f716c6 100644
--- a/pkg/dds/lib/dds.dart
+++ b/pkg/dds/lib/dds.dart
@@ -118,6 +118,9 @@
   /// authentication code to connect.
   bool get authCodesEnabled;
 
+  /// Completes when this [DartDevelopmentService] has shut down.
+  Future<void> get done;
+
   /// The HTTP [Uri] of the remote VM service instance that this service will
   /// forward requests to.
   Uri get remoteVmServiceUri;
diff --git a/pkg/dds/lib/src/dds_impl.dart b/pkg/dds/lib/src/dds_impl.dart
index 192e9ad5..06327a8 100644
--- a/pkg/dds/lib/src/dds_impl.dart
+++ b/pkg/dds/lib/src/dds_impl.dart
@@ -16,21 +16,50 @@
   }
 
   Future<void> startService() async {
+    bool started = false;
+    final completer = Completer<void>();
     // TODO(bkonyi): throw if we've already shutdown.
     // Establish the connection to the VM service.
     _vmServiceSocket = WebSocketChannel.connect(remoteVmServiceWsUri);
     _vmServiceClient = _BinaryCompatiblePeer(_vmServiceSocket, _streamManager);
     // Setup the JSON RPC client with the VM service.
-    unawaited(_vmServiceClient.listen().then((_) => shutdown()));
+    unawaited(
+      _vmServiceClient.listen().then(
+        (_) {
+          shutdown();
+          if (!started && !completer.isCompleted) {
+            completer.completeError(
+              DartDevelopmentServiceException._(
+                'Failed to start Dart Development Service',
+              ),
+            );
+          }
+        },
+        onError: (e, st) {
+          shutdown();
+          if (!completer.isCompleted) {
+            completer.completeError(e, st);
+          }
+        },
+      ),
+    );
+    try {
+      // Setup stream event handling.
+      await streamManager.listen();
 
-    // Setup stream event handling.
-    await streamManager.listen();
+      // Populate initial isolate state.
+      await _isolateManager.initialize();
 
-    // Populate initial isolate state.
-    await _isolateManager.initialize();
-
-    // Once we have a connection to the VM service, we're ready to spawn the intermediary.
-    await _startDDSServer();
+      // Once we have a connection to the VM service, we're ready to spawn the intermediary.
+      await _startDDSServer();
+      started = true;
+      completer.complete();
+    } on StateError {
+      /* Ignore json-rpc state errors */
+    } catch (e, st) {
+      completer.completeError(e, st);
+    }
+    return completer.future;
   }
 
   Future<void> _startDDSServer() async {
@@ -205,7 +234,7 @@
     }
     final pathSegments = _cleanupPathSegments(uri);
     pathSegments.add(_kSseHandlerPath);
-    return uri.replace(pathSegments: pathSegments);
+    return uri.replace(scheme: 'sse', pathSegments: pathSegments);
   }
 
   String _getNamespace(_DartDevelopmentServiceClient client) =>
diff --git a/pkg/dds/lib/src/expression_evaluator.dart b/pkg/dds/lib/src/expression_evaluator.dart
index d514d60..348d8f4 100644
--- a/pkg/dds/lib/src/expression_evaluator.dart
+++ b/pkg/dds/lib/src/expression_evaluator.dart
@@ -11,6 +11,18 @@
   _ExpressionEvaluator(this.dds);
 
   Future<Map<String, dynamic>> execute(json_rpc.Parameters parameters) async {
+    _DartDevelopmentServiceClient externalClient =
+        dds.clientManager.findFirstClientThatHandlesService(
+      'compileExpression',
+    );
+    // If no compilation service is registered, just forward to the VM service.
+    if (externalClient == null) {
+      return await dds._vmServiceClient.sendRequest(
+        parameters.method,
+        parameters.value,
+      );
+    }
+
     final isolateId = parameters['isolateId'].asString;
     final expression = parameters['expression'].asString;
     Map<String, dynamic> buildScopeResponse;
@@ -56,6 +68,11 @@
         dds.clientManager.findFirstClientThatHandlesService(
       'compileExpression',
     );
+    if (externalClient == null) {
+      throw _RpcErrorCodes.buildRpcException(
+          _RpcErrorCodes.kExpressionCompilationError,
+          data: 'compileExpression service disappeared.');
+    }
 
     final compileParams = <String, dynamic>{
       'isolateId': isolateId,
@@ -70,20 +87,11 @@
     if (klass != null) {
       compileParams['klass'] = klass;
     }
-    // TODO(bkonyi): handle service disappeared case?
     try {
-      if (externalClient != null) {
-        return (await externalClient.sendRequest(
-          'compileExpression',
-          compileParams,
-        ))['kernelBytes'];
-      } else {
-        // Fallback to compiling using the kernel service.
-        return (await dds._vmServiceClient.sendRequest(
-          '_compileExpression',
-          compileParams,
-        ))['kernelBytes'];
-      }
+      return (await externalClient.sendRequest(
+        'compileExpression',
+        compileParams,
+      ))['kernelBytes'];
     } on json_rpc.RpcException catch (e) {
       throw _RpcErrorCodes.buildRpcException(
         _RpcErrorCodes.kExpressionCompilationError,
diff --git a/pkg/dds/lib/src/isolate_manager.dart b/pkg/dds/lib/src/isolate_manager.dart
index 57711bf..c94d4cd 100644
--- a/pkg/dds/lib/src/isolate_manager.dart
+++ b/pkg/dds/lib/src/isolate_manager.dart
@@ -31,7 +31,7 @@
 }
 
 class _RunningIsolate {
-  _RunningIsolate(this.isolateManager, this.portId, this.name);
+  _RunningIsolate(this.isolateManager, this.id, this.name);
 
   // State setters.
   void pausedOnExit() => _state = _IsolateState.pauseExit;
@@ -52,7 +52,7 @@
     if (shouldResume()) {
       clearResumeApprovals();
       await isolateManager.dds._vmServiceClient.sendRequest('resume', {
-        'isolateId': 'isolates/$portId',
+        'isolateId': id,
       });
     }
   }
@@ -104,7 +104,7 @@
 
   final _IsolateManager isolateManager;
   final String name;
-  final String portId;
+  final String id;
   final Set<String> _resumeApprovalsByName = {};
   _IsolateState _state;
 }
@@ -124,7 +124,7 @@
     }
 
     final isolateData = event['isolate'];
-    final id = isolateData['number'].asString;
+    final id = isolateData['id'].asString;
     final name = isolateData['name'].asString;
     _updateIsolateState(id, name, eventKind);
   }
@@ -160,37 +160,41 @@
 
   /// Initializes the set of running isolates.
   Future<void> initialize() async {
+    if (_initialized) {
+      return;
+    }
     final vm = await dds._vmServiceClient.sendRequest('getVM');
     final List<Map> isolateRefs = vm['isolates'].cast<Map<String, dynamic>>();
     // Check the pause event for each isolate to determine whether or not the
     // isolate is already paused.
     for (final isolateRef in isolateRefs) {
+      final id = isolateRef['id'];
       final isolate = await dds._vmServiceClient.sendRequest('getIsolate', {
-        'isolateId': isolateRef['id'],
+        'isolateId': id,
       });
-      final portId = isolate['number'];
       final name = isolate['name'];
       if (isolate.containsKey('pauseEvent')) {
-        isolates[portId] = _RunningIsolate(this, portId, name);
+        isolates[id] = _RunningIsolate(this, id, name);
         final eventKind = isolate['pauseEvent']['kind'];
-        _updateIsolateState(portId, name, eventKind);
+        _updateIsolateState(id, name, eventKind);
       } else {
         // If the isolate doesn't have a pauseEvent, assume it's running.
-        isolateStarted(portId, name);
+        isolateStarted(id, name);
       }
     }
+    _initialized = true;
   }
 
   /// Initializes state for a newly started isolate.
-  void isolateStarted(String portId, String name) {
-    final isolate = _RunningIsolate(this, portId, name);
+  void isolateStarted(String id, String name) {
+    final isolate = _RunningIsolate(this, id, name);
     isolate.running();
-    isolates[portId] = isolate;
+    isolates[id] = isolate;
   }
 
   /// Cleans up state for an isolate that has exited.
-  void isolateExited(String portId) {
-    isolates.remove(portId);
+  void isolateExited(String id) {
+    isolates.remove(id);
   }
 
   /// Handles `resume` RPC requests. If the client requires that approval be
@@ -206,8 +210,7 @@
     json_rpc.Parameters parameters,
   ) async {
     final isolateId = parameters['isolateId'].asString;
-    final portId = _isolateIdToPortId(isolateId);
-    final isolate = isolates[portId];
+    final isolate = isolates[isolateId];
     if (isolate == null) {
       return _RPCResponses.collectedSentinel;
     }
@@ -233,9 +236,7 @@
     return resumeResult;
   }
 
-  static String _isolateIdToPortId(String isolateId) =>
-      isolateId.substring('isolates/'.length);
-
+  bool _initialized = false;
   final _DartDevelopmentService dds;
   final Map<String, _RunningIsolate> isolates = {};
 }
diff --git a/pkg/dds/lib/src/stream_manager.dart b/pkg/dds/lib/src/stream_manager.dart
index 5704895..abb233c 100644
--- a/pkg/dds/lib/src/stream_manager.dart
+++ b/pkg/dds/lib/src/stream_manager.dart
@@ -36,14 +36,8 @@
     }
   }
 
-  void sendServiceRegisteredEvent(
-    _DartDevelopmentServiceClient client,
-    String service,
-    String alias,
-  ) {
-    final namespace = dds._getNamespace(client);
-    streamNotify(
-      kServiceStream,
+  static Map<String, dynamic> _buildStreamRegisteredEvent(
+          String namespace, String service, String alias) =>
       {
         'streamId': kServiceStream,
         'event': {
@@ -53,8 +47,18 @@
           'service': service,
           'method': namespace + '.' + service,
           'alias': alias,
-        },
-      },
+        }
+      };
+
+  void sendServiceRegisteredEvent(
+    _DartDevelopmentServiceClient client,
+    String service,
+    String alias,
+  ) {
+    final namespace = dds._getNamespace(client);
+    streamNotify(
+      kServiceStream,
+      _buildStreamRegisteredEvent(namespace, service, alias),
       excludedClient: client,
     );
   }
@@ -135,6 +139,25 @@
       streamListeners[stream].add(client);
       if (stream == kLoggingStream) {
         dds.loggingRepository.sendHistoricalLogs(client);
+      } else if (stream == kServiceStream) {
+        // Send all previously registered service extensions when a client
+        // subscribes to the Service stream.
+        for (final c in dds.clientManager.clients) {
+          if (c == client) {
+            continue;
+          }
+          final namespace = dds._getNamespace(c);
+          for (final service in c.services.keys) {
+            client.sendNotification(
+              'streamNotify',
+              _buildStreamRegisteredEvent(
+                namespace,
+                service,
+                c.services[service],
+              ),
+            );
+          }
+        }
       }
     }
   }
diff --git a/pkg/dds/pubspec.yaml b/pkg/dds/pubspec.yaml
index 447170c..a7ae669 100644
--- a/pkg/dds/pubspec.yaml
+++ b/pkg/dds/pubspec.yaml
@@ -3,7 +3,7 @@
   A library used to spawn the Dart Developer Service, used to communicate with
   a Dart VM Service instance.
 
-version: 1.3.2
+version: 1.4.1
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/dds
 
diff --git a/pkg/dds/test/sse_smoke_test.dart b/pkg/dds/test/sse_smoke_test.dart
index 682fa18..823f816 100644
--- a/pkg/dds/test/sse_smoke_test.dart
+++ b/pkg/dds/test/sse_smoke_test.dart
@@ -66,7 +66,6 @@
             'binary': Platform.environment['CHROME_PATH'] ?? '',
           },
         });
-      print('Capabilities: $capabilities');
       webdriver = await createDriver(
         desired: capabilities,
       );
@@ -93,8 +92,10 @@
           expect(dds.isRunning, true);
           await webdriver.get('http://localhost:${server.port}');
           final testeeConnection = await handler.connections.next;
-          testeeConnection.sink.add(dds.sseUri.toString());
 
+          // Replace the sse scheme with http as sse isn't supported for CORS.
+          testeeConnection.sink
+              .add(dds.sseUri.replace(scheme: 'http').toString());
           final response = json.decode(await testeeConnection.stream.first);
           final version = service.Version.parse(response);
           expect(version.major > 0, isTrue);
diff --git a/pkg/dds/test/uri_test.dart b/pkg/dds/test/uri_test.dart
index 8afd523..8c7e64e 100644
--- a/pkg/dds/test/uri_test.dart
+++ b/pkg/dds/test/uri_test.dart
@@ -44,6 +44,7 @@
       expect(
         dds.sseUri,
         serviceUri.replace(
+          scheme: 'sse',
           pathSegments: ['\$debugHandler'],
         ),
       );
@@ -73,6 +74,7 @@
       expect(
         dds.sseUri,
         serviceUri.replace(
+          scheme: 'sse',
           pathSegments: [authCode, '\$debugHandler'],
         ),
       );
diff --git a/pkg/dev_compiler/bin/dartdevc.dart b/pkg/dev_compiler/bin/dartdevc.dart
index 68246e3..baf9c9a 100755
--- a/pkg/dev_compiler/bin/dartdevc.dart
+++ b/pkg/dev_compiler/bin/dartdevc.dart
@@ -30,17 +30,20 @@
   } else if (parsedArgs.isBatch) {
     await runBatch(parsedArgs);
   } else if (parsedArgs.isExpressionCompiler) {
-    ExpressionCompilerWorker worker;
     if (sendPort != null) {
       var receivePort = ReceivePort();
       sendPort.send(receivePort.sendPort);
-      worker = await ExpressionCompilerWorker.createFromArgs(parsedArgs.rest,
+      var worker = await ExpressionCompilerWorker.createFromArgs(
+          parsedArgs.rest,
           requestStream: receivePort.cast<Map<String, dynamic>>(),
           sendResponse: sendPort.send);
+      await worker.start();
+      receivePort.close();
     } else {
-      worker = await ExpressionCompilerWorker.createFromArgs(parsedArgs.rest);
+      var worker =
+          await ExpressionCompilerWorker.createFromArgs(parsedArgs.rest);
+      await worker.start();
     }
-    await worker.start();
   } else {
     var result = await compile(parsedArgs);
     exitCode = result.exitCode;
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 8a9fa88..153240b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -472,7 +472,7 @@
     // publicly exposed JS API for a library.
 
     var node = export.node;
-    if (node is Procedure && node.name.name == 'main') {
+    if (node is Procedure && node.name.text == 'main') {
       // Don't allow redefining names from this library.
       var name = _emitTopLevelName(export.node);
       moduleItems.add(js.statement(
@@ -560,7 +560,10 @@
 
     var body = <js_ast.Statement>[];
     _emitSuperHelperSymbols(body);
-    var deferredSupertypes = <js_ast.Statement>[];
+    // Deferred supertypes must be evaluated lazily while emitting classes to
+    // prevent evaluating a JS expression for a deferred type from influencing
+    // class declaration order (such as when calling 'emitDeferredType').
+    var deferredSupertypes = <js_ast.Statement Function()>[];
 
     // Emit the class, e.g. `core.Object = class Object { ... }`
     _defineClass(c, className, jsMethods, body, deferredSupertypes);
@@ -591,11 +594,13 @@
 
     var classDef = js_ast.Statement.from(body);
     var typeFormals = c.typeParameters;
+    var evaluatedDeferredSupertypes =
+        deferredSupertypes.map<js_ast.Statement>((f) => f()).toList();
     if (typeFormals.isNotEmpty) {
       classDef = _defineClassTypeArguments(
-          c, typeFormals, classDef, className, deferredSupertypes);
+          c, typeFormals, classDef, className, evaluatedDeferredSupertypes);
     } else {
-      afterClassDefItems.addAll(deferredSupertypes);
+      afterClassDefItems.addAll(evaluatedDeferredSupertypes);
     }
 
     body = [classDef];
@@ -745,7 +750,7 @@
       js_ast.Expression className,
       List<js_ast.Method> methods,
       List<js_ast.Statement> body,
-      List<js_ast.Statement> deferredSupertypes) {
+      List<js_ast.Statement Function()> deferredSupertypes) {
     if (c == _coreTypes.objectClass) {
       body.add(_emitClassStatement(c, className, null, methods));
       return;
@@ -820,19 +825,34 @@
       return base;
     }
 
+    /// Returns the "actual" superclass of [c].
+    ///
+    /// Walks up the superclass chain looking for the first actual class
+    /// skipping any synthetic classes inserted by the CFE.
+    Class superClassAsWritten(Class c) {
+      var superclass = c.superclass;
+      while (superclass.isAnonymousMixin) {
+        superclass = superclass.superclass;
+      }
+      return superclass;
+    }
+
     // Find the real (user declared) superclass and the list of mixins.
     // We'll use this to unroll the intermediate classes.
     //
     // TODO(jmesserly): consider using Kernel's mixin unrolling.
-    var mixinClasses = <Class>[];
-    var superclass = getSuperclassAndMixins(c, mixinClasses);
+    var superclass = superClassAsWritten(c);
     var supertype = identical(c.superclass, superclass)
         ? c.supertype.asInterfaceType
         : _hierarchy.getClassAsInstanceOf(c, superclass).asInterfaceType;
-    mixinClasses = mixinClasses.reversed.toList();
-    var mixins = mixinClasses
-        .map((m) => _hierarchy.getClassAsInstanceOf(c, m).asInterfaceType)
-        .toList();
+    // All mixins (real and anonymous) classes applied to c.
+    var mixinApplications = [
+      if (c.mixedInClass != null) c.mixedInClass,
+      for (var sc = c.superclass;
+          sc.isAnonymousMixin && sc.mixedInClass != null;
+          sc = sc.superclass)
+        sc,
+    ].reversed.toList();
 
     var hasUnnamedSuper = _hasUnnamedInheritedConstructor(superclass);
 
@@ -853,7 +873,7 @@
         _currentUri = ctor.enclosingClass.fileUri;
         var jsParams = _emitParameters(ctor.function, isForwarding: true);
         _currentUri = savedUri;
-        var name = ctor.name.name;
+        var name = ctor.name.text;
         var ctorBody = [
           if (mixinCtor != null) mixinCtor,
           if (name != '' || hasUnnamedSuper)
@@ -867,21 +887,20 @@
     var savedTopLevelClass = _classEmittingExtends;
     _classEmittingExtends = c;
 
-    // Refers to 'S' in `class C extends S`. Set this to null to avoid
-    // referencing deferred supertypes in _emitClassConstructor's JS output.
-    js_ast.Expression baseClass;
-
+    // Unroll mixins.
     if (shouldDefer(supertype)) {
-      deferredSupertypes.add(runtimeStatement('setBaseClass(#, #)', [
-        getBaseClass(isMixinAliasClass(c) ? 0 : mixins.length),
-        emitDeferredType(supertype),
-      ]));
-      // Refers to 'supertype' without any type arguments.
+      var originalSupertype = supertype;
+      deferredSupertypes.add(() => runtimeStatement('setBaseClass(#, #)', [
+            getBaseClass(isMixinAliasClass(c) ? 0 : mixinApplications.length),
+            emitDeferredType(originalSupertype),
+          ]));
+      // Refers to 'supertype' without type parameters. We remove these from
+      // the 'extends' clause for generics for cyclic dependencies and append
+      // them later with 'setBaseClass'.
       supertype =
           _coreTypes.rawType(supertype.classNode, _currentLibrary.nonNullable);
-    } else {
-      baseClass = emitClassRef(supertype);
     }
+    var baseClass = emitClassRef(supertype);
 
     if (isMixinAliasClass(c)) {
       // Given `class C = Object with M [implements I1, I2 ...];`
@@ -893,12 +912,16 @@
 
       var m = c.mixedInType.asInterfaceType;
       var deferMixin = shouldDefer(m);
-      var mixinBody = deferMixin ? deferredSupertypes : body;
       var mixinClass = deferMixin ? emitDeferredType(m) : emitClassRef(m);
       var classExpr = deferMixin ? getBaseClass(0) : className;
 
-      mixinBody
-          .add(runtimeStatement('applyMixin(#, #)', [classExpr, mixinClass]));
+      var mixinApplication =
+          runtimeStatement('applyMixin(#, #)', [classExpr, mixinClass]);
+      if (deferMixin) {
+        deferredSupertypes.add(() => mixinApplication);
+      } else {
+        body.add(mixinApplication);
+      }
 
       if (methods.isNotEmpty) {
         // However we may need to add some methods to this class that call
@@ -907,11 +930,16 @@
         // We do this with the following pattern:
         //
         //     applyMixin(C, class C$ extends M { <methods>  });
-        mixinBody.add(runtimeStatement('applyMixin(#, #)', [
+        var mixinApplicationWithMethods = runtimeStatement('applyMixin(#, #)', [
           classExpr,
           js_ast.ClassExpression(
               _emitTemporaryId(getLocalClassName(c)), mixinClass, methods)
-        ]));
+        ]);
+        if (deferMixin) {
+          deferredSupertypes.add(() => mixinApplicationWithMethods);
+        } else {
+          body.add(mixinApplicationWithMethods);
+        }
       }
 
       emitMixinConstructors(className, m);
@@ -924,29 +952,43 @@
     // classes lack required synthetic members, such as constructors.
     //
     // Also, we need to generate one extra level of nesting for alias classes.
-    for (var i = 0; i < mixins.length; i++) {
-      var m = mixins[i];
+    for (var i = 0; i < mixinApplications.length; i++) {
+      var m = mixinApplications[i];
+      var mixinClass = m.isAnonymousMixin ? m.mixedInClass : m;
+      var mixinType =
+          _hierarchy.getClassAsInstanceOf(c, mixinClass).asInterfaceType;
       var mixinName =
-          getLocalClassName(superclass) + '_' + getLocalClassName(m.classNode);
+          getLocalClassName(superclass) + '_' + getLocalClassName(mixinClass);
       var mixinId = _emitTemporaryId(mixinName + '\$');
+      // Collect all forwarding stubs from anonymous mixins classes. These will
+      // contain covariant parameter checks that need to be applied.
+      var forwardingMethodStubs = [
+        for (var procedure in m.procedures)
+          if (procedure.isForwardingStub && !procedure.isAbstract)
+            _emitMethodDeclaration(procedure)
+      ];
+
       // Bind the mixin class to a name to workaround a V8 bug with es6 classes
       // and anonymous function names.
       // TODO(leafp:) Eliminate this once the bug is fixed:
       // https://bugs.chromium.org/p/v8/issues/detail?id=7069
       body.add(js.statement('const # = #', [
         mixinId,
-        js_ast.ClassExpression(_emitTemporaryId(mixinName), baseClass, [])
+        js_ast.ClassExpression(
+            _emitTemporaryId(mixinName), baseClass, forwardingMethodStubs)
       ]));
 
-      emitMixinConstructors(mixinId, m);
-      hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(m.classNode);
+      emitMixinConstructors(mixinId, mixinType);
+      hasUnnamedSuper = hasUnnamedSuper || _hasUnnamedConstructor(mixinClass);
 
-      if (shouldDefer(m)) {
-        deferredSupertypes.add(runtimeStatement('applyMixin(#, #)',
-            [getBaseClass(mixins.length - i), emitDeferredType(m)]));
+      if (shouldDefer(mixinType)) {
+        deferredSupertypes.add(() => runtimeStatement('applyMixin(#, #)', [
+              getBaseClass(mixinApplications.length - i),
+              emitDeferredType(mixinType)
+            ]));
       } else {
-        body.add(
-            runtimeStatement('applyMixin(#, #)', [mixinId, emitClassRef(m)]));
+        body.add(runtimeStatement(
+            'applyMixin(#, #)', [mixinId, emitClassRef(mixinType)]));
       }
 
       baseClass = mixinId;
@@ -977,7 +1019,7 @@
     var fields = c.fields;
     for (var ctor in c.constructors) {
       if (ctor.isExternal) continue;
-      addConstructor(ctor.name.name, _emitConstructor(ctor, fields, className));
+      addConstructor(ctor.name.text, _emitConstructor(ctor, fields, className));
     }
 
     // If classElement has only factory constructors, and it can be mixed in,
@@ -1115,7 +1157,7 @@
       // We know enum fields can be safely emitted as const fields, as long
       // as the `values` field is emitted last.
       var classRef = _emitTopLevelName(c);
-      var valueField = fields.firstWhere((f) => f.name.name == 'values');
+      var valueField = fields.firstWhere((f) => f.name.text == 'values');
       fields.remove(valueField);
       fields.add(valueField);
       for (var f in fields) {
@@ -1123,13 +1165,13 @@
         body.add(defineValueOnClass(
                 c,
                 classRef,
-                _emitStaticMemberName(f.name.name),
+                _emitStaticMemberName(f.name.text),
                 _visitInitializer(f.initializer, f.annotations))
             .toStatement());
       }
     } else if (fields.isNotEmpty) {
       body.add(_emitLazyFields(_emitTopLevelName(c), fields,
-          (n) => _emitStaticMemberName(n.name.name)));
+          (n) => _emitStaticMemberName(n.name.text)));
     }
   }
 
@@ -1232,7 +1274,7 @@
       // nor can they be torn off.
       if (member.isStatic) continue;
 
-      var name = member.name.name;
+      var name = member.name.text;
       var reifiedType = _memberRuntimeType(member, c) as FunctionType;
 
       // Don't add redundant signatures for inherited methods whose signature
@@ -1379,7 +1421,7 @@
     // Also for const constructors we need to ensure default values are
     // available for use by top-level constant initializers.
     var fn = node.function;
-    var body = _emitArgumentInitializers(fn, node.name.name);
+    var body = _emitArgumentInitializers(fn, node.name.text);
 
     // Redirecting constructors: these are not allowed to have initializers,
     // and the redirecting ctor invocation runs before field initializers.
@@ -1427,7 +1469,7 @@
     // derived class constructor with the same name.
     return js.statement('#.#.call(this, #);', [
       className,
-      _constructorName(ctor.name.name),
+      _constructorName(ctor.name.text),
       _emitArgumentList(node.arguments, types: false)
     ]);
   }
@@ -1449,10 +1491,10 @@
     // We can skip the super call if it's empty. Most commonly this happens for
     // things that extend Object, and don't have any field initializers or their
     // own default constructor.
-    if (ctor.name.name == '' && !_hasUnnamedSuperConstructor(c)) {
+    if (ctor.name.text == '' && !_hasUnnamedSuperConstructor(c)) {
       return null;
     }
-    return _emitSuperConstructorCall(className, ctor.name.name, args);
+    return _emitSuperConstructorCall(className, ctor.name.text, args);
   }
 
   js_ast.Statement _emitSuperConstructorCall(
@@ -1626,9 +1668,9 @@
     for (var m in c.procedures) {
       if (m.isAbstract) continue;
       if (m.isGetter) {
-        getters[m.name.name] = m;
+        getters[m.name.text] = m;
       } else if (m.isSetter) {
-        setters[m.name.name] = m;
+        setters[m.name.text] = m;
       }
     }
 
@@ -1655,7 +1697,7 @@
       } else if (m.isAccessor) {
         jsMethods.add(_emitMethodDeclaration(m));
         jsMethods.add(_emitSuperAccessorWrapper(m, getters, setters));
-        if (!hasJsPeer && m.isGetter && m.name.name == 'iterator') {
+        if (!hasJsPeer && m.isGetter && m.name.text == 'iterator') {
           hasIterator = true;
           jsMethods.add(_emitIterable(c));
         }
@@ -1719,7 +1761,7 @@
       }
       fn = _emitNativeFunctionBody(member);
     } else {
-      fn = _emitFunction(member.function, member.name.name);
+      fn = _emitFunction(member.function, member.name.text);
     }
 
     return js_ast.Method(_declareMemberName(member), fn,
@@ -1730,7 +1772,7 @@
   }
 
   js_ast.Fun _emitNativeFunctionBody(Procedure node) {
-    var name = _annotationName(node, isJSAnnotation) ?? node.name.name;
+    var name = _annotationName(node, isJSAnnotation) ?? node.name.text;
     if (node.isGetter) {
       return js_ast.Fun([], js.block('{ return this.#; }', [name]));
     } else if (node.isSetter) {
@@ -1850,7 +1892,7 @@
     /// If a future Dart version allows factory constructors to take their
     /// own type parameters, this will need to be changed to call
     /// [_emitFunction] instead.
-    var name = node.name.name;
+    var name = node.name.text;
     var jsBody = _emitSyncFunctionBody(function, name);
 
     return js_ast.Method(
@@ -1909,7 +1951,7 @@
     var jsMethods = <js_ast.Method>[];
     assert(!field.isStatic);
 
-    var name = _annotationName(field, isJSName) ?? field.name.name;
+    var name = _annotationName(field, isJSName) ?? field.name.text;
     // Generate getter
     var fn = js_ast.Fun([], js.block('{ return this.#; }', [name]));
     var method = js_ast.Method(_declareMemberName(field), fn, isGetter: true);
@@ -1936,7 +1978,7 @@
       Map<String, Procedure> getters, Map<String, Procedure> setters) {
     if (member.isAbstract) return null;
 
-    var name = member.name.name;
+    var name = member.name.text;
     var memberName = _declareMemberName(member);
     if (member.isGetter) {
       if (!setters.containsKey(name) &&
@@ -2068,7 +2110,7 @@
         ..sourceInformation = _hoverComment(
             js_ast.PropertyAccess(objExpr, access),
             field.fileOffset,
-            field.name.name.length));
+            field.name.text.length));
 
       // TODO(jmesserly): currently uses a dummy setter to indicate writable.
       if (!field.isFinal && !field.isConst) {
@@ -2117,7 +2159,7 @@
   /// Unlike call sites, we always have an element available, so we can use it
   /// directly rather than computing the relevant options for [_emitMemberName].
   js_ast.Expression _declareMemberName(Member m, {bool useExtension}) {
-    return _emitMemberName(m.name.name,
+    return _emitMemberName(m.name.text,
         isStatic: m is Field ? m.isStatic : (m as Procedure).isStatic,
         useExtension:
             useExtension ?? _extensionTypes.isNativeClass(m.enclosingClass),
@@ -2348,8 +2390,8 @@
     if (m is Procedure) {
       if (m.isExternal) return true;
       if (m.isNoSuchMethodForwarder) {
-        if (renamedJsMembers.contains(m.name.name)) {
-          return _hasExternalProcedure(m.enclosingClass, m.name.name);
+        if (renamedJsMembers.contains(m.name.text)) {
+          return _hasExternalProcedure(m.enclosingClass, m.name.text);
         }
       }
     }
@@ -2373,7 +2415,7 @@
       ];
       classes.addAll(classesToCheck);
       for (var procedure in c.procedures) {
-        if (procedure.name.name == name && !procedure.isNoSuchMethodForwarder) {
+        if (procedure.name.text == name && !procedure.isNoSuchMethodForwarder) {
           return procedure.isExternal;
         }
       }
@@ -2430,9 +2472,9 @@
     _staticTypeContext.enterMember(node);
     _currentUri = node.fileUri;
 
-    var name = node.name.name;
+    var name = node.name.text;
     var result = js_ast.Method(
-        propertyName(name), _emitFunction(node.function, node.name.name),
+        propertyName(name), _emitFunction(node.function, node.name.text),
         isGetter: node.isGetter, isSetter: node.isSetter)
       ..sourceInformation = _nodeEnd(node.fileEndOffset);
 
@@ -2447,7 +2489,7 @@
     _currentUri = p.fileUri;
 
     var body = <js_ast.Statement>[];
-    var fn = _emitFunction(p.function, p.name.name)
+    var fn = _emitFunction(p.function, p.name.text)
       ..sourceInformation = _nodeEnd(p.fileEndOffset);
 
     if (_currentLibrary.importUri.scheme == 'dart' &&
@@ -2457,7 +2499,7 @@
 
     var nameExpr = _emitTopLevelName(p);
     body.add(js.statement('# = #',
-        [nameExpr, js_ast.NamedFunction(_emitTemporaryId(p.name.name), fn)]));
+        [nameExpr, js_ast.NamedFunction(_emitTemporaryId(p.name.text), fn)]));
 
     _currentUri = savedUri;
     _staticTypeContext.leaveMember(p);
@@ -2871,7 +2913,7 @@
   js_ast.Expression _emitConstructorName(InterfaceType type, Member c) {
     return _emitJSInterop(type.classNode) ??
         js_ast.PropertyAccess(
-            _emitConstructorAccess(type), _constructorName(c.name.name));
+            _emitConstructorAccess(type), _constructorName(c.name.text));
   }
 
   /// Emits an expression that lets you access statics on an [c] from code.
@@ -3014,7 +3056,7 @@
       // assign directly to [virtualField].  If the latter, copy the old
       // variable to [virtualField].
       var symbol = emitClassPrivateNameSymbol(c.enclosingLibrary,
-          getLocalClassName(c), field.name.name, virtualField);
+          getLocalClassName(c), field.name.text, virtualField);
       if (symbol != virtualField) {
         body.add(js.statement('const # = #;', [virtualField, symbol]));
       }
@@ -3400,9 +3442,9 @@
         return js.call(code, [_visitTest(node.left), _visitTest(node.right)]);
       }
 
-      var op = node.operator;
-      if (op == '&&') return shortCircuit('# && #');
-      if (op == '||') return shortCircuit('# || #');
+      var op = node.operatorEnum;
+      if (op == LogicalExpressionOperator.AND) return shortCircuit('# && #');
+      if (op == LogicalExpressionOperator.OR) return shortCircuit('# || #');
     }
 
     if (node is AsExpression && node.isTypeError) {
@@ -3794,7 +3836,7 @@
         _emitConstructorName(
             streamIterator,
             _asyncStreamIteratorClass.procedures
-                .firstWhere((p) => p.isFactory && p.name.name == '')),
+                .firstWhere((p) => p.isFactory && p.name.text == '')),
         [_visitExpression(node.iterable)]);
 
     var iter = _emitTemporaryId('iter');
@@ -4171,29 +4213,25 @@
 
   @override
   js_ast.Expression visitPropertyGet(PropertyGet node) {
-    return _emitPropertyGet(
-        node.receiver, node.interfaceTarget, node.name.name);
+    var propertyGet =
+        _emitPropertyGet(node.receiver, node.interfaceTarget, node.name.text);
+    if (_isCheckableNative(node.interfaceTarget)) {
+      // If target is a native getter with a non-nullable type, add a null check
+      // for soundness.
+      return runtimeCall('checkNativeNonNull(#)', [propertyGet]);
+    }
+    return propertyGet;
   }
 
   @override
   js_ast.Expression visitPropertySet(PropertySet node) {
     return _emitPropertySet(
-        node.receiver, node.interfaceTarget, node.value, node.name.name);
-  }
-
-  @override
-  js_ast.Expression visitDirectPropertyGet(DirectPropertyGet node) {
-    return _emitPropertyGet(node.receiver, node.target);
-  }
-
-  @override
-  js_ast.Expression visitDirectPropertySet(DirectPropertySet node) {
-    return _emitPropertySet(node.receiver, node.target, node.value);
+        node.receiver, node.interfaceTarget, node.value, node.name.text);
   }
 
   js_ast.Expression _emitPropertyGet(Expression receiver, Member member,
       [String memberName]) {
-    memberName ??= member.name.name;
+    memberName ??= member.name.text;
     // TODO(jmesserly): should tearoff of `.call` on a function type be
     // encoded as a different node, or possibly eliminated?
     // (Regardless, we'll still need to handle the callable JS interop classes.)
@@ -4235,6 +4273,16 @@
     }
   }
 
+  /// Return whether [member] returns a native object whose type needs to be
+  /// checked.
+  bool _isCheckableNative(Member member) =>
+      member != null &&
+      member.isExternal &&
+      _extensionTypes.isNativeClass(member.enclosingClass) &&
+      member is Procedure &&
+      member.function != null &&
+      member.function.returnType.isPotentiallyNonNullable;
+
   // TODO(jmesserly): can we encapsulate REPL name lookups and remove this?
   // _emitMemberName would be a nice place to handle it, but we don't have
   // access to the target expression there (needed for `dart.replNameLookup`).
@@ -4244,7 +4292,7 @@
       Expression receiver, Member member, Expression value,
       [String memberName]) {
     var jsName =
-        _emitMemberName(memberName ?? member.name.name, member: member);
+        _emitMemberName(memberName ?? member.name.text, member: member);
 
     if (member != null && isJsMember(member)) {
       value = _assertInterop(value);
@@ -4305,18 +4353,19 @@
 
   @override
   js_ast.Expression visitMethodInvocation(MethodInvocation node) {
-    return _emitMethodCall(
+    var methodCall = _emitMethodCall(
         node.receiver, node.interfaceTarget, node.arguments, node);
-  }
-
-  @override
-  js_ast.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
-    return _emitMethodCall(node.receiver, node.target, node.arguments, node);
+    if (_isCheckableNative(node.interfaceTarget)) {
+      // If target is a native method with a non-nullable type, add a null check
+      // for soundness.
+      return runtimeCall('checkNativeNonNull(#)', [methodCall]);
+    }
+    return methodCall;
   }
 
   js_ast.Expression _emitMethodCall(Expression receiver, Member target,
       Arguments arguments, InvocationExpression node) {
-    var name = node.name.name;
+    var name = node.name.text;
     if (isOperatorMethodName(name) && arguments.named.isEmpty) {
       var argLength = arguments.positional.length;
       if (argLength == 0) {
@@ -4425,7 +4474,7 @@
 
   js_ast.Expression _emitUnaryOperator(
       Expression expr, Member target, InvocationExpression node) {
-    var op = node.name.name;
+    var op = node.name.text;
     if (target != null) {
       var dispatchType = _coreTypes.legacyRawType(target.enclosingClass);
       if (_typeRep.unaryOperationIsPrimitive(dispatchType)) {
@@ -4463,7 +4512,7 @@
     // comparison, e.g.  `a & ~b == 0`.
     if (parent is InvocationExpression &&
         parent.arguments.positional.length == 1) {
-      var op = parent.name.name;
+      var op = parent.name.text;
       var left = getInvocationReceiver(parent);
       var right = parent.arguments.positional[0];
       if (left != null && op == '==') {
@@ -4482,7 +4531,7 @@
   }
 
   bool _nodeIsBitwiseOperation(InvocationExpression node) {
-    switch (node.name.name) {
+    switch (node.name.text) {
       case '&':
       case '|':
       case '^':
@@ -4516,7 +4565,7 @@
     var parent = node.parent;
     if (parent == null) return false;
     if (parent is InvocationExpression && _nodeIsBitwiseOperation(parent)) {
-      if (parent.name.name == '&' && parent.arguments.positional.length == 1) {
+      if (parent.name.text == '&' && parent.arguments.positional.length == 1) {
         var left = getInvocationReceiver(parent);
         var right = parent.arguments.positional[0];
         final MAX = (1 << width) - 1;
@@ -4546,7 +4595,7 @@
         var left = getInvocationReceiver(expr);
         var right = expr.arguments.positional[0];
         if (left != null) {
-          switch (expr.name.name) {
+          switch (expr.name.text) {
             case '&':
               return min(bitWidth(left, depth), bitWidth(right, depth));
 
@@ -4590,7 +4639,7 @@
 
   js_ast.Expression _emitBinaryOperator(Expression left, Member target,
       Expression right, InvocationExpression node) {
-    var op = node.name.name;
+    var op = node.name.text;
     if (op == '==') return _emitEqualityOperator(left, target, right);
 
     // TODO(jmesserly): using the target type here to work around:
@@ -4787,7 +4836,7 @@
   /// Emits the [js_ast.PropertyAccess] for accessors or method calls to
   /// [jsTarget].[jsName], replacing `super` if it is not allowed in scope.
   js_ast.PropertyAccess _emitSuperTarget(Member member, {bool setter = false}) {
-    var jsName = _emitMemberName(member.name.name, member: member);
+    var jsName = _emitMemberName(member.name.text, member: member);
     if (member is Field && !_virtualFields.isVirtual(member)) {
       return js_ast.PropertyAccess(js_ast.This(), jsName);
     }
@@ -4795,7 +4844,7 @@
 
     // If we can't emit `super` in this context, generate a helper that does it
     // for us, and call the helper.
-    var name = member.name.name;
+    var name = member.name.text;
     var jsMethod = _superHelpers.putIfAbsent(name, () {
       var isAccessor = member is Procedure ? member.isAccessor : true;
       if (isAccessor) {
@@ -4836,7 +4885,7 @@
 
     // Optimize some internal SDK calls.
     if (isSdkInternalRuntime(target.enclosingLibrary)) {
-      var name = target.name.name;
+      var name = target.name.text;
       if (node.arguments.positional.isEmpty) {
         if (name == 'typeRep') {
           return _emitType(node.arguments.types.single);
@@ -4903,7 +4952,7 @@
   }
 
   bool _isDebuggerCall(Procedure target) {
-    return target.name.name == 'debugger' &&
+    return target.name.text == 'debugger' &&
         target.enclosingLibrary.importUri.toString() == 'dart:developer';
   }
 
@@ -4955,12 +5004,12 @@
         var nativeName = _extensionTypes.getNativePeers(c);
         if (nativeName.isNotEmpty) {
           var memberName = _annotationName(target, isJSName) ??
-              _emitStaticMemberName(target.name.name, target);
+              _emitStaticMemberName(target.name.text, target);
           return runtimeCall('global.#.#', [nativeName[0], memberName]);
         }
       }
       return js_ast.PropertyAccess(_emitStaticClassName(c),
-          _emitStaticMemberName(target.name.name, target));
+          _emitStaticMemberName(target.name.text, target));
     }
     return _emitTopLevelName(target);
   }
@@ -5037,11 +5086,30 @@
 
     var result = js.parseForeignJS(source).instantiate(jsArgs);
 
+    // Add a check to make sure any JS() values from a native type are typed
+    // properly.
+    if (_isWebLibrary(_currentLibrary.importUri)) {
+      var type = node.getStaticType(_staticTypeContext);
+      if (type.isPotentiallyNonNullable) {
+        result = runtimeCall('checkNativeNonNull(#)', [result]);
+      }
+    }
+
     assert(result is js_ast.Expression ||
         result is js_ast.Statement && node.parent is ExpressionStatement);
-    return result;
+    return result.withSourceInformation(_nodeStart(node));
   }
 
+  bool _isWebLibrary(Uri importUri) =>
+      importUri.scheme == 'dart' &&
+      (importUri.path == 'html' ||
+          importUri.path == 'svg' ||
+          importUri.path == 'indexed_db' ||
+          importUri.path == 'web_audio' ||
+          importUri.path == 'web_gl' ||
+          importUri.path == 'web_sql' ||
+          importUri.path == 'html_common');
+
   bool _isNull(Expression expr) =>
       expr is NullLiteral ||
       expr.getStaticType(_staticTypeContext) == _coreTypes.nullType;
@@ -5140,9 +5208,9 @@
         case 'Map':
         case 'HashMap':
         case 'LinkedHashMap':
-          if (ctor.name.name == '') {
+          if (ctor.name.text == '') {
             return js.call('new #.new()', _emitMapImplType(type));
-          } else if (ctor.name.name == 'identity') {
+          } else if (ctor.name.text == 'identity') {
             return js.call(
                 'new #.new()', _emitMapImplType(type, identity: true));
           }
@@ -5150,15 +5218,15 @@
         case 'Set':
         case 'HashSet':
         case 'LinkedHashSet':
-          if (ctor.name.name == '') {
+          if (ctor.name.text == '') {
             return js.call('new #.new()', _emitSetImplType(type));
-          } else if (ctor.name.name == 'identity') {
+          } else if (ctor.name.text == 'identity') {
             return js.call(
                 'new #.new()', _emitSetImplType(type, identity: true));
           }
           break;
         case 'List':
-          if (ctor.name.name == '' && type is InterfaceType) {
+          if (ctor.name.text == '' && type is InterfaceType) {
             return _emitList(type.typeArguments[0], []);
           }
           break;
@@ -5211,14 +5279,10 @@
   @override
   js_ast.Expression visitNot(Not node) {
     var operand = node.operand;
-    if (operand is MethodInvocation && operand.name.name == '==') {
+    if (operand is MethodInvocation && operand.name.text == '==') {
       return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
           operand.arguments.positional[0],
           negated: true);
-    } else if (operand is DirectMethodInvocation && operand.name.name == '==') {
-      return _emitEqualityOperator(
-          operand.receiver, operand.target, operand.arguments.positional[0],
-          negated: true);
     } else if (operand is StaticInvocation &&
         operand.target == _coreTypes.identicalProcedure) {
       return _emitCoreIdenticalCall(operand.arguments.positional,
@@ -5796,9 +5860,9 @@
       // directly.  Otherwise, use a private symbol in case the field
       // was overridden.
       var symbol = cls.isEnum
-          ? _emitMemberName(member.name.name, member: member)
+          ? _emitMemberName(member.name.text, member: member)
           : emitClassPrivateNameSymbol(
-              cls.enclosingLibrary, getLocalClassName(cls), member.name.name);
+              cls.enclosingLibrary, getLocalClassName(cls), member.name.text);
       return js_ast.Property(symbol, constant);
     }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 69ba4a5..5400577 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -46,7 +46,7 @@
       var constant = node.constant;
       if (constant is InstanceConstant) {
         var value = constant.fieldValues.entries
-            .firstWhere((e) => e.key.asField.name.name == name,
+            .firstWhere((e) => e.key.asField.name.text == name,
                 orElse: () => null)
             ?.value;
         if (value is PrimitiveConstant) return value.value;
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
index 2b26a3f..e57a2fb 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:io';
 
 import 'package:_fe_analyzer_shared/src/messages/diagnostic_message.dart'
     show DiagnosticMessage, DiagnosticMessageHandler;
@@ -177,28 +176,28 @@
   @override
   void visitFieldReference(Field node) {
     if (node.name.isPrivate) {
-      privateFields[node.name.name] = node.name.library.importUri.toString();
+      privateFields[node.name.text] = node.name.library.importUri.toString();
     }
   }
 
   @override
   void visitField(Field node) {
     if (node.name.isPrivate) {
-      privateFields[node.name.name] = node.name.library.importUri.toString();
+      privateFields[node.name.text] = node.name.library.importUri.toString();
     }
   }
 
   @override
   void visitPropertyGet(PropertyGet node) {
     if (node.name.isPrivate) {
-      privateFields[node.name.name] = node.name.library.importUri.toString();
+      privateFields[node.name.text] = node.name.library.importUri.toString();
     }
   }
 
   @override
   void visitPropertySet(PropertySet node) {
     if (node.name.isPrivate) {
-      privateFields[node.name.name] = node.name.library.importUri.toString();
+      privateFields[node.name.text] = node.name.library.importUri.toString();
     }
   }
 }
@@ -206,24 +205,29 @@
 class ExpressionCompiler {
   static final String debugProcedureName = '\$dartEval';
 
-  final bool verbose;
+  final CompilerContext _context;
+  final CompilerOptions _options;
+  final List<String> errors;
   final IncrementalCompiler _compiler;
   final ProgramCompiler _kernel2jsCompiler;
   final Component _component;
-  final List<String> errors;
+
   DiagnosticMessageHandler onDiagnostic;
 
   void _log(String message) {
-    if (verbose) {
-      // writing to stdout breaks communication to
-      // frontend server, which is done on stdin/stdout,
-      // so we use stderr here instead
-      stderr.writeln(message);
+    if (_options.verbose) {
+      _context.options.ticker.logMs(message);
     }
   }
 
-  ExpressionCompiler(this._compiler, this._kernel2jsCompiler, this._component,
-      {this.verbose, this.onDiagnostic, this.errors});
+  ExpressionCompiler(
+    this._options,
+    this.errors,
+    this._compiler,
+    this._kernel2jsCompiler,
+    this._component,
+  )   : onDiagnostic = _options.onDiagnostic,
+        _context = _compiler.context;
 
   /// Compiles [expression] in [libraryUri] at [line]:[column] to JavaScript
   /// in [moduleName].
@@ -256,11 +260,11 @@
       String expression) async {
     // 1. find dart scope where debugger is paused
 
-    _log('ExpressionCompiler: compiling:  $expression in $moduleName');
+    _log('Compiling expression in $moduleName:\n$expression');
 
     var dartScope = await _findScopeAt(Uri.parse(libraryUri), line, column);
     if (dartScope == null) {
-      _log('ExpressionCompiler: scope not found at $libraryUri:$line:$column');
+      _log('Scope not found at $libraryUri:$line:$column');
       return null;
     }
 
@@ -280,8 +284,7 @@
     var localJsScope =
         dartScope.definitions.keys.map((variable) => jsScope[variable]);
 
-    _log('ExpressionCompiler: dart scope: $dartScope');
-    _log('ExpressionCompiler: substituted local JsScope: $localJsScope');
+    _log('Performed scope substitutions for expression');
 
     // 3. compile dart expression to JS
 
@@ -289,7 +292,7 @@
         await _compileExpression(dartScope, jsModules, moduleName, expression);
 
     if (jsExpression == null) {
-      _log('ExpressionCompiler: failed to compile $expression, $jsExpression');
+      _log('Failed to compile expression in $moduleName:\n$expression');
       return null;
     }
 
@@ -323,7 +326,8 @@
 error.name + ": " + error.message;
 }''';
 
-    _log('ExpressionCompiler: compiled $expression to $callExpression');
+    _log(
+        'Compiled expression in $moduleName:\n$expression to \n$callExpression');
     return callExpression;
   }
 
@@ -350,6 +354,7 @@
       return null;
     }
 
+    _log('Detected expression compilation scope');
     return scope;
   }
 
@@ -362,6 +367,8 @@
 
         return library.library;
       }
+
+      _log('Loaded library for expression');
       return null;
     });
   }
@@ -415,8 +422,6 @@
       Map<String, String> modules,
       String currentModule,
       String expression) async {
-    // 1. Compile expression to kernel AST
-
     var procedure = await _compiler.compileExpression(
         expression,
         scope.definitions,
@@ -426,6 +431,8 @@
         scope.cls?.name,
         scope.procedure.isStatic);
 
+    _log('Compiled expression to kernel');
+
     // TODO: make this code clear and assumptions enforceable
     // https://github.com/dart-lang/sdk/issues/43273
     //
@@ -438,14 +445,12 @@
       return null;
     }
 
-    _log('ExpressionCompiler: Kernel: ${procedure.leakingDebugToString()}');
-
-    // 2. compile kernel AST to JS ast
-
     var jsFun = _kernel2jsCompiler.emitFunctionIncremental(
         scope.library, scope.cls, procedure.function, '$debugProcedureName');
 
-    // 3. apply temporary workarounds for what ideally
+    _log('Generated JavaScript for expression');
+
+    // apply temporary workarounds for what ideally
     // needs to be done in the compiler
 
     // get private fields accessed by the evaluated expression
@@ -478,10 +483,6 @@
       }
     }
 
-    _log('ExpressionCompiler: privateFields: $privateFields');
-    _log('ExpressionCompiler: currentLibraries: $currentLibraries');
-    _log('ExpressionCompiler: currentModules: $currentModules');
-
     var body = js_ast.Block([
       // require modules used in evaluated expression
       ...currentModules.keys.map((String variable) =>
@@ -495,15 +496,15 @@
     ]);
 
     var jsFunModified = js_ast.Fun(jsFun.params, body);
-    _log('ExpressionCompiler: JS AST: $jsFunModified');
 
-    // 4. print JS ast to string for evaluation
+    // print JS ast to string for evaluation
 
     var context = js_ast.SimpleJavaScriptPrintingContext();
     var opts =
         js_ast.JavaScriptPrintingOptions(allowKeywordsInProperties: true);
 
     jsFunModified.accept(js_ast.Printer(opts, context));
+    _log('Performed JavaScript adjustments for expression');
 
     return context.getText();
   }
diff --git a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
index 9cb61dc..a1b995c 100644
--- a/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
+++ b/pkg/dev_compiler/lib/src/kernel/expression_compiler_worker.dart
@@ -103,10 +103,11 @@
   final _componentForModuleName = <String, Component>{};
   final _componentModuleNames = <Component, String>{};
   final ProcessedOptions _processedOptions;
+  final CompilerOptions _compilerOptions;
   final Component _sdkComponent;
 
-  ExpressionCompilerWorker._(this._processedOptions, this._sdkComponent,
-      this.requestStream, this.sendResponse);
+  ExpressionCompilerWorker._(this._processedOptions, this._compilerOptions,
+      this._sdkComponent, this.requestStream, this.sendResponse);
 
   static Future<ExpressionCompilerWorker> createFromArgs(
     List<String> args, {
@@ -172,7 +173,7 @@
     void Function(Map<String, dynamic>)
         sendResponse, // Defaults to write to stdout
   }) async {
-    var options = CompilerOptions()
+    var compilerOptions = CompilerOptions()
       ..compileSdk = false
       ..sdkRoot = sdkRoot
       ..sdkSummary = sdkSummary
@@ -192,15 +193,15 @@
         .cast<Map<String, dynamic>>();
     sendResponse ??= (Map<String, dynamic> response) =>
         stdout.writeln(json.encode(response));
-    var processedOpts = ProcessedOptions(options: options);
+    var processedOptions = ProcessedOptions(options: compilerOptions);
 
-    var sdkComponent = await CompilerContext(processedOpts)
+    var sdkComponent = await CompilerContext(processedOptions)
         .runInContext<Component>((CompilerContext c) async {
-      return processedOpts.loadSdkSummary(null);
+      return processedOptions.loadSdkSummary(null);
     });
 
-    return ExpressionCompilerWorker._(
-        processedOpts, sdkComponent, requestStream, sendResponse)
+    return ExpressionCompilerWorker._(processedOptions, compilerOptions,
+        sdkComponent, requestStream, sendResponse)
       .._update(sdkComponent, dartSdkModule);
   }
 
@@ -212,6 +213,7 @@
     await for (var request in requestStream) {
       try {
         var command = request['command'] as String;
+        if (command == 'Shutdown') break;
         switch (command) {
           case 'UpdateDeps':
             sendResponse(
@@ -233,11 +235,14 @@
         });
       }
     }
+    _processedOptions.ticker.logMs('Stopped expression compiler worker.');
   }
 
   /// Handles a `CompileExpression` request.
   Future<Map<String, dynamic>> _compileExpression(
       CompileExpressionRequest request) async {
+    _processedOptions.ticker.logMs('Compiling expression to JavaScript');
+
     var libraryUri = Uri.parse(request.libraryUri);
     if (libraryUri.scheme == 'dart') {
       // compiling expressions inside the SDK currently fails because
@@ -264,16 +269,18 @@
         uriToSource: originalComponent.uriToSource,
       );
     }
+    _processedOptions.ticker.logMs('Collected dependencies for expression');
 
     errors.clear();
     warnings.clear();
 
     var incrementalCompiler = IncrementalCompiler.forExpressionCompilationOnly(
-        CompilerContext(_processedOptions), component);
+        CompilerContext(_processedOptions), component, /*resetTicker*/ false);
 
     var finalComponent =
         await incrementalCompiler.computeDelta(entryPoints: [libraryUri]);
     finalComponent.computeCanonicalNames();
+    _processedOptions.ticker.logMs('Computed delta for expression');
 
     if (errors.isNotEmpty) {
       return {
@@ -294,13 +301,15 @@
       coreTypes: incrementalCompiler.getCoreTypes(),
     );
 
+    compiler.emitModule(finalComponent);
+    _processedOptions.ticker.logMs('Emitted module for expression');
+
     var expressionCompiler = ExpressionCompiler(
+      _compilerOptions,
+      errors,
       incrementalCompiler,
       compiler,
       finalComponent,
-      verbose: _processedOptions.verbose,
-      onDiagnostic: _onDiagnosticHandler(errors, warnings),
-      errors: errors,
     );
 
     var compiledProcedure = await expressionCompiler.compileExpressionToJs(
@@ -312,6 +321,8 @@
         request.moduleName,
         request.expression);
 
+    _processedOptions.ticker.logMs('Compiled expression to JavaScript');
+
     return {
       'errors': errors,
       'warnings': warnings,
@@ -347,6 +358,9 @@
 
   /// Loads in the specified dill files and invalidates any existing ones.
   Future<Map<String, dynamic>> _updateDeps(UpdateDepsRequest request) async {
+    _processedOptions.ticker
+        .logMs('Updating dependencies for expression evaluation');
+
     for (var input in request.inputs) {
       var file =
           _processedOptions.fileSystem.entityForUri(Uri.parse(input.path));
@@ -356,6 +370,9 @@
           alwaysCreateNewNamedNodes: true);
       _update(component, input.moduleName);
     }
+
+    _processedOptions.ticker
+        .logMs('Updated dependencies for expression evaluation');
     return {'succeeded': true};
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/js_interop.dart b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
index 2f929ab..9c01d89 100644
--- a/pkg/dev_compiler/lib/src/kernel/js_interop.dart
+++ b/pkg/dev_compiler/lib/src/kernel/js_interop.dart
@@ -35,7 +35,7 @@
   if (node is StaticInvocation) {
     var target = node.target;
     return _isLibrary(target.enclosingLibrary, ['dart:js']) &&
-        target.name.name == 'allowInterop';
+        target.name.text == 'allowInterop';
   }
   return false;
 }
@@ -80,7 +80,7 @@
 /// Whether [i] is a `spread` invocation (to be used on function arguments
 /// to have them compiled as `...` spread args in ES6 outputs).
 bool isJSSpreadInvocation(Procedure target) =>
-    target.name.name == 'spread' && _isJSLibrary(target.enclosingLibrary);
+    target.name.text == 'spread' && _isJSLibrary(target.enclosingLibrary);
 
 bool isJSName(Expression value) =>
     isBuiltinAnnotation(value, '_js_helper', 'JSName');
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index 81776ac..a2c50dd 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -8,7 +8,7 @@
 import 'package:kernel/kernel.dart';
 
 Constructor unnamedConstructor(Class c) =>
-    c.constructors.firstWhere((c) => c.name.name == '', orElse: () => null);
+    c.constructors.firstWhere((c) => c.name.text == '', orElse: () => null);
 
 /// Returns the enclosing library for reference [node].
 Library getLibrary(NamedNode node) {
@@ -47,10 +47,10 @@
 String getTypeParameterName(TypeParameter node) => escapeIdentifier(node.name);
 
 String getTopLevelName(NamedNode n) {
-  if (n is Procedure) return n.name.name;
+  if (n is Procedure) return n.name.text;
   if (n is Class) return n.name;
   if (n is Typedef) return n.name;
-  if (n is Field) return n.name.name;
+  if (n is Field) return n.name.text;
   return n.canonicalName?.name;
 }
 
@@ -152,7 +152,7 @@
 bool isFromEnvironmentInvocation(CoreTypes coreTypes, StaticInvocation node) {
   var target = node.target;
   return node.isConst &&
-      target.name.name == 'fromEnvironment' &&
+      target.name.text == 'fromEnvironment' &&
       target.enclosingLibrary == coreTypes.coreLibrary;
 }
 
@@ -189,15 +189,11 @@
 }
 
 Expression getInvocationReceiver(InvocationExpression node) =>
-    node is MethodInvocation
-        ? node.receiver
-        : node is DirectMethodInvocation
-            ? node.receiver
-            : null;
+    node is MethodInvocation ? node.receiver : null;
 
 bool isInlineJS(Member e) =>
     e is Procedure &&
-    e.name.name == 'JS' &&
+    e.name.text == 'JS' &&
     e.enclosingLibrary.importUri.toString() == 'dart:_foreign_helper';
 
 /// Whether the parameter [p] is covariant (either explicitly `covariant` or
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 363f13a..32c687f 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -89,13 +89,6 @@
   bool visitPropertySet(PropertySet node) => isNullable(node.value);
 
   @override
-  bool visitDirectPropertyGet(DirectPropertyGet node) =>
-      _getterIsNullable(node.target);
-
-  @override
-  bool visitDirectPropertySet(DirectPropertySet node) => isNullable(node.value);
-
-  @override
   bool visitSuperPropertyGet(SuperPropertyGet node) =>
       _getterIsNullable(node.interfaceTarget);
 
@@ -110,15 +103,11 @@
 
   @override
   bool visitMethodInvocation(MethodInvocation node) => _invocationIsNullable(
-      node.interfaceTarget, node.name.name, node.receiver);
-
-  @override
-  bool visitDirectMethodInvocation(DirectMethodInvocation node) =>
-      _invocationIsNullable(node.target, node.name.name, node.receiver);
+      node.interfaceTarget, node.name.text, node.receiver);
 
   @override
   bool visitSuperMethodInvocation(SuperMethodInvocation node) =>
-      _invocationIsNullable(node.interfaceTarget, node.name.name);
+      _invocationIsNullable(node.interfaceTarget, node.name.text);
 
   bool _invocationIsNullable(Member target, String name,
       [Expression receiver]) {
@@ -127,7 +116,7 @@
     // https://github.com/dart-lang/sdk/issues/31854
     if (name == '==') return false;
     if (target == null) return true; // dynamic call
-    if (target.name.name == 'toString' &&
+    if (target.name.text == 'toString' &&
         receiver != null &&
         receiver.getStaticType(_staticTypeContext) ==
             coreTypes.stringLegacyRawType) {
@@ -188,7 +177,7 @@
             typeString.split('|').contains('Null');
       }
     }
-    return _invocationIsNullable(target, node.name.name);
+    return _invocationIsNullable(target, node.name.text);
   }
 
   @override
@@ -274,7 +263,7 @@
     if (node is StaticGet) {
       var t = node.target;
       return t is Field &&
-          t.name.name == fieldName &&
+          t.name.text == fieldName &&
           _isInternalSdkAnnotation(t.enclosingLibrary);
     }
     return false;
diff --git a/pkg/dev_compiler/lib/src/kernel/property_model.dart b/pkg/dev_compiler/lib/src/kernel/property_model.dart
index a0d28e0..cee7fb9 100644
--- a/pkg/dev_compiler/lib/src/kernel/property_model.dart
+++ b/pkg/dev_compiler/lib/src/kernel/property_model.dart
@@ -85,7 +85,7 @@
     Map<String, Field> getInstanceFieldMap(Class c) {
       var instanceFields = c.fields.where((f) => !f.isStatic);
       return HashMap.fromIterables(
-          instanceFields.map((f) => f.name.name), instanceFields);
+          instanceFields.map((f) => f.name.text), instanceFields);
     }
 
     var allFields =
@@ -129,7 +129,7 @@
 
         // Look in all super classes to see if we're overriding a field in our
         // library, if so mark that field as overridden.
-        var name = member.name.name;
+        var name = member.name.text;
         _overriddenPrivateFields.addAll(superclasses
             .map((c) => allFields[c][name])
             .where((f) => f != null));
@@ -228,7 +228,7 @@
           continue;
         }
 
-        var name = member.name.name;
+        var name = member.name.text;
         if (member is Field) {
           inheritedGetters.add(name);
           if (!member.isFinal) inheritedSetters.add(name);
@@ -253,7 +253,7 @@
       // Also ignore abstract fields.
       if (field.isAbstract || field.isStatic) continue;
 
-      var name = field.name.name;
+      var name = field.name.text;
       if (virtualAccessorNames.contains(name) ||
           fieldModel.isVirtual(field) ||
           field.isCovariant ||
@@ -328,7 +328,7 @@
     // we've seen, and visit starting from the class, then mixins in
     // reverse order, then superclasses.
     for (var m in c.members) {
-      var name = m.name.name;
+      var name = m.name.text;
       if (m.isAbstract || m is Constructor) continue;
       if (m is Procedure) {
         if (m.isStatic) continue;
@@ -352,7 +352,7 @@
       for (var m in c.members) {
         if (!m.name.isPrivate &&
             (m is Procedure && !m.isStatic || m is Field && !m.isStatic)) {
-          members.add(m.name.name);
+          members.add(m.name.text);
         }
       }
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 8a54269..2982b8d 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -35,6 +35,9 @@
   bool get supportsLateFields => false;
 
   @override
+  bool get supportsLateLoweringSentinel => false;
+
+  @override
   bool get useStaticFieldLowering => false;
 
   // TODO(johnniwinther,sigmund): Remove this when js-interop handles getter
@@ -181,7 +184,7 @@
       var ctor = coreTypes.index
           .getClass('dart:core', '_Invocation')
           .constructors
-          .firstWhere((c) => c.name.name == name);
+          .firstWhere((c) => c.name.text == name);
       return ConstructorInvocation(ctor, Arguments(positional));
     }
 
@@ -381,32 +384,14 @@
   }
 
   @override
-  void visitDirectPropertyGet(DirectPropertyGet node) {
-    _checkTearoff(node.target);
-    super.visitDirectPropertyGet(node);
-  }
-
-  @override
   void visitPropertySet(PropertySet node) {
     _checkTarget(node.receiver, node.interfaceTarget);
     super.visitPropertySet(node);
   }
 
   @override
-  void visitDirectPropertySet(DirectPropertySet node) {
-    _checkTarget(node.receiver, node.target);
-    super.visitDirectPropertySet(node);
-  }
-
-  @override
   void visitMethodInvocation(MethodInvocation node) {
     _checkTarget(node.receiver, node.interfaceTarget);
     super.visitMethodInvocation(node);
   }
-
-  @override
-  void visitDirectMethodInvocation(DirectMethodInvocation node) {
-    _checkTarget(node.receiver, node.target);
-    super.visitDirectMethodInvocation(node);
-  }
 }
diff --git a/pkg/dev_compiler/lib/src/kernel/type_table.dart b/pkg/dev_compiler/lib/src/kernel/type_table.dart
index 8421a66..8f8a002 100644
--- a/pkg/dev_compiler/lib/src/kernel/type_table.dart
+++ b/pkg/dev_compiler/lib/src/kernel/type_table.dart
@@ -123,7 +123,7 @@
   /// Heuristically choose a good name for the cache and generator
   /// variables.
   js_ast.TemporaryId chooseTypeName(DartType type) {
-    return js_ast.TemporaryId(_typeString(type));
+    return js_ast.TemporaryId(escapeIdentifier(_typeString(type)));
   }
 }
 
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 7374f49..4e4068e 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -140,10 +140,13 @@
     kernel2jsCompiler.emitModule(component);
 
     // create expression compiler
-    var evaluator = ExpressionCompiler(compiler, kernel2jsCompiler, component,
-        verbose: setup.options.verbose,
-        onDiagnostic: setup.options.onDiagnostic,
-        errors: setup.errors);
+    var evaluator = ExpressionCompiler(
+      setup.options,
+      setup.errors,
+      compiler,
+      kernel2jsCompiler,
+      component,
+    );
 
     // collect all module names and paths
     var moduleInfo = _collectModules(component);
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index b2cd5ce..302aa18 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -54,6 +54,11 @@
             'parameters are not null.',
         defaultsTo: false,
         negatable: true)
+    ..addFlag('native-null-assertions',
+        help: 'Run with assertions on non-nullable values returned from native '
+            'APIs.',
+        defaultsTo: true,
+        negatable: true)
     ..addFlag('observe',
         help:
             'Run the compiler in the Dart VM with --observe. Implies --debug.',
@@ -109,6 +114,7 @@
   var run = mode == 'run' || mode == 'all';
   var verbose = options['verbose'] as bool;
   var nonNullAsserts = options['null-assertions'] as bool;
+  var nativeNonNullAsserts = options['null-assertions'] as bool;
 
   var soundNullSafety = options['sound-null-safety'] as bool;
   // Enable null safety either by passing the `non-nullable` experiment flag or
@@ -280,6 +286,7 @@
     if ($nnbd) {
       sdk.dart.weakNullSafetyWarnings(!$soundNullSafety);
       sdk.dart.nonNullAsserts($nonNullAsserts);
+      sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts);
     }
     sdk._debugger.registerDevtoolsFormatter();
     app.$libname.main([]);
@@ -315,6 +322,7 @@
   if ($nnbd) {
     sdk.dart.weakNullSafetyWarnings(!$soundNullSafety);
     sdk.dart.nonNullAsserts($nonNullAsserts);
+    sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts);
   }
   sdk._isolate_helper.startRootIsolate(main, []);
 } catch(e) {
@@ -347,16 +355,13 @@
 // Create a self reference for JS interop tests that set fields on self.
 dart.global.self = dart.global;
 let main = $libname.main;
-try {
-  if ($nnbd) {
-    dart.weakNullSafetyWarnings(!$soundNullSafety);
-    dart.nonNullAsserts($nonNullAsserts);
-  }
-  _isolate_helper.startRootIsolate(() => {}, []);
-  main([]);
-} catch(e) {
-  console.error(e);
+if ($nnbd) {
+  dart.weakNullSafetyWarnings(!$soundNullSafety);
+  dart.nonNullAsserts($nonNullAsserts);
+  dart.nativeNonNullAsserts($nativeNonNullAsserts);
 }
+_isolate_helper.startRootIsolate(() => {}, []);
+main([]);
 ''';
       var d8File = p.setExtension(out, '.d8.js');
       File(d8File).writeAsStringSync(runjs);
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index fcf64da..6e6b8e6 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -612,6 +612,12 @@
     Expect.throws(f, (error) => error is NoSuchMethodError, reason);
   }
 
+  static void throwsReachabilityError(void f(),
+      [String reason = "ReachabilityError"]) {
+    Expect.throws(
+        f, (error) => error.toString().startsWith('ReachabilityError'), reason);
+  }
+
   /// Checks that [f] throws an appropriate error on a null argument.
   ///
   /// In strong mode, this is expected to be a [TypeError] when casting the
diff --git a/pkg/front_end/analysis_options.yaml b/pkg/front_end/analysis_options.yaml
index 9021253..21d20ef 100644
--- a/pkg/front_end/analysis_options.yaml
+++ b/pkg/front_end/analysis_options.yaml
@@ -17,4 +17,5 @@
     - valid_regexps
     - package_api_docs
     - lines_longer_than_80_chars
+    - unrelated_type_equality_checks
     # - always_specify_types
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 7452b96..23cf4a1 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -233,6 +233,10 @@
   /// 'non-nullable' is enabled.
   NnbdMode nnbdMode = NnbdMode.Weak;
 
+  /// Whether to emit a warning when a ReachabilityError is thrown to ensure
+  /// soundness in mixed mode.
+  bool warnOnReachabilityCheck = false;
+
   /// The current sdk version string, e.g. "2.6.0-edge.sha1hash".
   /// For instance used for language versioning (specifying the maximum
   /// version).
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index ab3a7e3..c3b0dc7 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -24,17 +24,17 @@
 }
 
 const Version enableAlternativeInvalidationStrategyVersion =
-    const Version(2, 10);
-const Version enableConstantUpdate2018Version = const Version(2, 4);
-const Version enableControlFlowCollectionsVersion = const Version(2, 2);
+    const Version(2, 11);
+const Version enableConstantUpdate2018Version = const Version(2, 0);
+const Version enableControlFlowCollectionsVersion = const Version(2, 0);
 const Version enableExtensionMethodsVersion = const Version(2, 6);
-const Version enableNonNullableVersion = const Version(2, 10);
-const Version enableNonfunctionTypeAliasesVersion = const Version(2, 10);
-const Version enableSetLiteralsVersion = const Version(2, 2);
-const Version enableSpreadCollectionsVersion = const Version(2, 2);
-const Version enableTripleShiftVersion = const Version(2, 10);
-const Version enableValueClassVersion = const Version(2, 10);
-const Version enableVarianceVersion = const Version(2, 10);
+const Version enableNonNullableVersion = const Version(2, 11);
+const Version enableNonfunctionTypeAliasesVersion = const Version(2, 11);
+const Version enableSetLiteralsVersion = const Version(2, 0);
+const Version enableSpreadCollectionsVersion = const Version(2, 0);
+const Version enableTripleShiftVersion = const Version(2, 11);
+const Version enableValueClassVersion = const Version(2, 11);
+const Version enableVarianceVersion = const Version(2, 11);
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
   switch (flag) {
@@ -93,31 +93,31 @@
 };
 
 const Map<ExperimentalFlag, Version> experimentEnabledVersion = {
-  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 10),
-  ExperimentalFlag.constantUpdate2018: const Version(2, 4),
-  ExperimentalFlag.controlFlowCollections: const Version(2, 2),
+  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 11),
+  ExperimentalFlag.constantUpdate2018: const Version(2, 0),
+  ExperimentalFlag.controlFlowCollections: const Version(2, 0),
   ExperimentalFlag.extensionMethods: const Version(2, 6),
-  ExperimentalFlag.nonNullable: const Version(2, 10),
-  ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 10),
-  ExperimentalFlag.setLiterals: const Version(2, 2),
-  ExperimentalFlag.spreadCollections: const Version(2, 2),
-  ExperimentalFlag.tripleShift: const Version(2, 10),
-  ExperimentalFlag.valueClass: const Version(2, 10),
-  ExperimentalFlag.variance: const Version(2, 10),
+  ExperimentalFlag.nonNullable: const Version(2, 11),
+  ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 11),
+  ExperimentalFlag.setLiterals: const Version(2, 0),
+  ExperimentalFlag.spreadCollections: const Version(2, 0),
+  ExperimentalFlag.tripleShift: const Version(2, 11),
+  ExperimentalFlag.valueClass: const Version(2, 11),
+  ExperimentalFlag.variance: const Version(2, 11),
 };
 
 const Map<ExperimentalFlag, Version> experimentReleasedVersion = {
-  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 10),
-  ExperimentalFlag.constantUpdate2018: const Version(2, 4),
-  ExperimentalFlag.controlFlowCollections: const Version(2, 2),
+  ExperimentalFlag.alternativeInvalidationStrategy: const Version(2, 11),
+  ExperimentalFlag.constantUpdate2018: const Version(2, 0),
+  ExperimentalFlag.controlFlowCollections: const Version(2, 0),
   ExperimentalFlag.extensionMethods: const Version(2, 6),
   ExperimentalFlag.nonNullable: const Version(2, 10),
-  ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 10),
-  ExperimentalFlag.setLiterals: const Version(2, 2),
-  ExperimentalFlag.spreadCollections: const Version(2, 2),
-  ExperimentalFlag.tripleShift: const Version(2, 10),
-  ExperimentalFlag.valueClass: const Version(2, 10),
-  ExperimentalFlag.variance: const Version(2, 10),
+  ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 11),
+  ExperimentalFlag.setLiterals: const Version(2, 0),
+  ExperimentalFlag.spreadCollections: const Version(2, 0),
+  ExperimentalFlag.tripleShift: const Version(2, 11),
+  ExperimentalFlag.valueClass: const Version(2, 11),
+  ExperimentalFlag.variance: const Version(2, 11),
 };
 
 const AllowedExperimentalFlags defaultAllowedExperimentalFlags =
@@ -166,6 +166,9 @@
   "flutter": {
     ExperimentalFlag.nonNullable,
   },
+  "flutter_driver": {
+    ExperimentalFlag.nonNullable,
+  },
   "flutter_test": {
     ExperimentalFlag.nonNullable,
   },
@@ -175,15 +178,30 @@
   "flutter_goldens_client": {
     ExperimentalFlag.nonNullable,
   },
+  "http": {
+    ExperimentalFlag.nonNullable,
+  },
+  "http_parser": {
+    ExperimentalFlag.nonNullable,
+  },
+  "intl": {
+    ExperimentalFlag.nonNullable,
+  },
   "js": {
     ExperimentalFlag.nonNullable,
   },
+  "logging": {
+    ExperimentalFlag.nonNullable,
+  },
   "matcher": {
     ExperimentalFlag.nonNullable,
   },
   "meta": {
     ExperimentalFlag.nonNullable,
   },
+  "native_stack_traces": {
+    ExperimentalFlag.nonNullable,
+  },
   "path": {
     ExperimentalFlag.nonNullable,
   },
@@ -199,6 +217,9 @@
   "process": {
     ExperimentalFlag.nonNullable,
   },
+  "pub_semver": {
+    ExperimentalFlag.nonNullable,
+  },
   "sky_engine": {
     ExperimentalFlag.nonNullable,
   },
diff --git a/pkg/front_end/lib/src/api_prototype/language_version.dart b/pkg/front_end/lib/src/api_prototype/language_version.dart
index 2ce4a67..a77b716 100644
--- a/pkg/front_end/lib/src/api_prototype/language_version.dart
+++ b/pkg/front_end/lib/src/api_prototype/language_version.dart
@@ -7,7 +7,7 @@
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show LanguageVersionToken, Scanner, ScannerConfiguration, scan;
 
-import 'package:kernel/ast.dart' show Version, defaultLanguageVersion;
+import 'package:kernel/ast.dart' show Version;
 export 'package:kernel/ast.dart' show Version;
 
 import 'package:package_config/package_config.dart'
@@ -23,6 +23,8 @@
 
 import 'compiler_options.dart' show CompilerOptions;
 
+import 'experimental_flags.dart'
+    show ExperimentalFlag, experimentReleasedVersion;
 import 'file_system.dart' show FileSystem, FileSystemException;
 
 /// Gets the language version for a specific URI.
@@ -125,11 +127,13 @@
   });
 }
 
+/// Returns `true` if the language version of [uri] does not support null
+/// safety.
 Future<bool> uriUsesLegacyLanguageVersion(
     Uri uri, CompilerOptions options) async {
   // This method is here in order to use the opt out hack here for test
   // sources.
   if (SourceLibraryBuilder.isOptOutTest(uri)) return true;
   Version uriVersion = await languageVersionForUri(uri, options);
-  return (uriVersion < defaultLanguageVersion);
+  return (uriVersion < experimentReleasedVersion[ExperimentalFlag.nonNullable]);
 }
diff --git a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
index ed9062f..c208be1 100644
--- a/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
+++ b/pkg/front_end/lib/src/api_prototype/lowering_predicates.dart
@@ -28,8 +28,8 @@
 bool isLateLoweredField(Field node) {
   return node.isInternalImplementation &&
       node.name != null &&
-      node.name.name.startsWith(lateFieldPrefix) &&
-      !node.name.name.endsWith(lateIsSetSuffix);
+      node.name.text.startsWith(lateFieldPrefix) &&
+      !node.name.text.endsWith(lateIsSetSuffix);
 }
 
 /// Returns `true` if [node] is the field holding the marker for whether a
@@ -55,8 +55,8 @@
 bool isLateLoweredIsSetField(Field node) {
   return node.isInternalImplementation &&
       node.name != null &&
-      node.name.name.startsWith(lateFieldPrefix) &&
-      node.name.name.endsWith(lateIsSetSuffix);
+      node.name.text.startsWith(lateFieldPrefix) &&
+      node.name.text.endsWith(lateIsSetSuffix);
 }
 
 /// Returns `true` if [node] is the getter for reading the value of a lowered
@@ -84,11 +84,11 @@
     if (parent is Class) {
       return parent.fields.any((Field field) =>
           isLateLoweredField(field) &&
-          field.name.name.endsWith(node.name.name));
+          field.name.text.endsWith(node.name.text));
     } else if (parent is Library) {
       return parent.fields.any((Field field) =>
           isLateLoweredField(field) &&
-          field.name.name.endsWith(node.name.name));
+          field.name.text.endsWith(node.name.text));
     }
   }
   return false;
@@ -119,11 +119,11 @@
     if (parent is Class) {
       return parent.fields.any((Field field) =>
           isLateLoweredField(field) &&
-          field.name.name.endsWith(node.name.name));
+          field.name.text.endsWith(node.name.text));
     } else if (parent is Library) {
       return parent.fields.any((Field field) =>
           isLateLoweredField(field) &&
-          field.name.name.endsWith(node.name.name));
+          field.name.text.endsWith(node.name.text));
     }
   }
   return false;
diff --git a/pkg/front_end/lib/src/base/command_line_options.dart b/pkg/front_end/lib/src/base/command_line_options.dart
index f288ff5..9640a43 100644
--- a/pkg/front_end/lib/src/base/command_line_options.dart
+++ b/pkg/front_end/lib/src/base/command_line_options.dart
@@ -9,6 +9,8 @@
   static const String nnbdWeakMode = "--nnbd-weak";
 
   static const String forceLateLowering = "--force-late-lowering";
+  static const String forceLateLoweringSentinel =
+      "--force-late-lowering-sentinel";
   static const String forceStaticFieldLowering =
       "--force-static-field-lowering";
   static const String forceNoExplicitGetterCalls =
@@ -38,4 +40,5 @@
   static const String singleRootScheme = "--single-root-scheme";
   static const String verbose = "--verbose";
   static const String verify = "--verify";
+  static const String warnOnReachabilityCheck = "--warn-on-reachability-check";
 }
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 5e51442..6682c79 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -13,7 +13,12 @@
 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
 
 import 'package:kernel/kernel.dart'
-    show CanonicalName, Component, Location, Version;
+    show
+        CanonicalName,
+        Component,
+        Location,
+        NonNullableByDefaultCompiledMode,
+        Version;
 
 import 'package:kernel/target/targets.dart'
     show NoneTarget, Target, TargetFlags;
@@ -176,6 +181,8 @@
 
   NnbdMode get nnbdMode => _raw.nnbdMode;
 
+  bool get warnOnReachabilityCheck => _raw.warnOnReachabilityCheck;
+
   /// The entry-points provided to the compiler.
   final List<Uri> inputs;
 
@@ -357,6 +364,18 @@
             _raw.experimentReleasedVersionForTesting);
   }
 
+  Component _validateNullSafetyMode(Component component) {
+    if (nnbdMode == NnbdMode.Strong &&
+        !(component.mode == NonNullableByDefaultCompiledMode.Strong ||
+            component.mode == NonNullableByDefaultCompiledMode.Agnostic)) {
+      throw new FormatException(
+          'Provided .dill file for the following libraries does not '
+          'support sound null safety:\n'
+          '${component.libraries.join('\n')}');
+    }
+    return component;
+  }
+
   /// Get an outline component that summarizes the SDK, if any.
   // TODO(sigmund): move, this doesn't feel like an "option".
   Future<Component> loadSdkSummary(CanonicalName nameRoot) async {
@@ -374,6 +393,7 @@
     if (_sdkSummaryComponent != null) {
       throw new StateError("sdkSummary already loaded.");
     }
+    _validateNullSafetyMode(platform);
     _sdkSummaryComponent = platform;
   }
 
@@ -399,6 +419,7 @@
     if (_additionalDillComponents != null) {
       throw new StateError("inputAdditionalDillsComponents already loaded.");
     }
+    components.forEach(_validateNullSafetyMode);
     _additionalDillComponents = components;
   }
 
@@ -414,7 +435,7 @@
             disableLazyReading: false,
             alwaysCreateNewNamedNodes: alwaysCreateNewNamedNodes)
         .readComponent(component);
-    return component;
+    return _validateNullSafetyMode(component);
   }
 
   /// Get the [UriTranslator] which resolves "package:" and "dart:" URIs.
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index a189dc1..c43ba3b 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -14,24 +14,19 @@
         DartType,
         DynamicType,
         Expression,
-        Field,
         FunctionNode,
         FunctionType,
         FutureOrType,
         InterfaceType,
-        InvalidType,
         Member,
         MethodInvocation,
         Name,
         Nullability,
         Procedure,
-        ProcedureKind,
         ReturnStatement,
         Supertype,
         ThisExpression,
         TypeParameter,
-        TypeParameterType,
-        VariableDeclaration,
         VoidType,
         getAsTypeArguments;
 
@@ -39,8 +34,6 @@
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-import 'package:kernel/src/legacy_erasure.dart';
-
 import 'package:kernel/text/text_serialization_verifier.dart';
 
 import 'package:kernel/type_algebra.dart' show Substitution, substitute;
@@ -62,9 +55,9 @@
 
 import '../modifier.dart';
 
-import '../names.dart' show equalsName, noSuchMethodName;
+import '../names.dart' show noSuchMethodName;
 
-import '../problems.dart' show internalProblem, unhandled, unimplemented;
+import '../problems.dart' show internalProblem, unhandled;
 
 import '../scope.dart';
 
@@ -201,36 +194,9 @@
       bool isSetter,
       callback(Member declaredMember, Member interfaceMember, bool isSetter));
 
-  void checkOverride(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter),
-      {bool isInterfaceCheck = false});
-
   bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy, Class objectClass);
 
-  /// Returns whether a covariant parameter was seen and more methods thus have
-  /// to be checked.
-  bool checkMethodOverride(Types types, Procedure declaredMember,
-      Procedure interfaceMember, bool isInterfaceCheck);
-
-  void checkGetterOverride(Types types, Member declaredMember,
-      Member interfaceMember, bool isInterfaceCheck);
-
-  /// Returns whether a covariant parameter was seen and more methods thus have
-  /// to be checked.
-  bool checkSetterOverride(Types types, Member declaredMember,
-      Member interfaceMember, bool isInterfaceCheck);
-
-  // When the overriding member is inherited, report the class containing
-  // the conflict as the main error.
-  void reportInvalidOverride(bool isInterfaceCheck, Member declaredMember,
-      Message message, int fileOffset, int length,
-      {List<LocatedMessage> context});
-
   void checkMixinApplication(ClassHierarchy hierarchy, CoreTypes coreTypes);
 
   // Computes the function type of a given redirection target. Returns [null] if
@@ -285,6 +251,13 @@
   ///
   /// If [isSuper] is `true`, constructors in the superclass are searched.
   Constructor lookupConstructor(Name name, {bool isSuper: false});
+
+  /// Calls [f] for each constructor declared in this class.
+  ///
+  /// If [includeInjectedConstructors] is `true`, constructors only declared in
+  /// the patch class, if any, are included.
+  void forEachConstructor(void Function(String, MemberBuilder) f,
+      {bool includeInjectedConstructors: false});
 }
 
 abstract class ClassBuilderImpl extends DeclarationBuilderImpl
@@ -367,6 +340,24 @@
   @override
   List<ConstructorReferenceBuilder> get constructorReferences => null;
 
+  void forEachConstructor(void Function(String, MemberBuilder) f,
+      {bool includeInjectedConstructors: false}) {
+    if (isPatch) {
+      actualOrigin.forEachConstructor(f,
+          includeInjectedConstructors: includeInjectedConstructors);
+    } else {
+      constructors.forEach(f);
+      if (includeInjectedConstructors && _patchBuilder != null) {
+        _patchBuilder.constructors
+            .forEach((String name, MemberBuilder builder) {
+          if (!builder.isPatch) {
+            f(name, builder);
+          }
+        });
+      }
+    }
+  }
+
   @override
   void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
     void build(String ignore, Builder declaration) {
@@ -776,77 +767,6 @@
   }
 
   @override
-  void checkOverride(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      bool isSetter,
-      callback(Member declaredMember, Member interfaceMember, bool isSetter),
-      {bool isInterfaceCheck = false}) {
-    if (declaredMember == interfaceMember) {
-      return;
-    }
-    if (declaredMember is Constructor || interfaceMember is Constructor) {
-      unimplemented(
-          "Constructor in override check.", declaredMember.fileOffset, fileUri);
-    }
-    if (declaredMember is Procedure && interfaceMember is Procedure) {
-      if (declaredMember.kind == interfaceMember.kind) {
-        if (declaredMember.kind == ProcedureKind.Method ||
-            declaredMember.kind == ProcedureKind.Operator) {
-          bool seenCovariant = checkMethodOverride(
-              types, declaredMember, interfaceMember, isInterfaceCheck);
-          if (seenCovariant) {
-            handleSeenCovariant(
-                types, declaredMember, interfaceMember, isSetter, callback);
-          }
-        } else if (declaredMember.kind == ProcedureKind.Getter) {
-          checkGetterOverride(
-              types, declaredMember, interfaceMember, isInterfaceCheck);
-        } else if (declaredMember.kind == ProcedureKind.Setter) {
-          bool seenCovariant = checkSetterOverride(
-              types, declaredMember, interfaceMember, isInterfaceCheck);
-          if (seenCovariant) {
-            handleSeenCovariant(
-                types, declaredMember, interfaceMember, isSetter, callback);
-          }
-        } else {
-          assert(
-              false,
-              "Unexpected procedure kind in override check: "
-              "${declaredMember.kind}");
-        }
-      }
-    } else {
-      bool declaredMemberHasGetter = declaredMember is Field ||
-          declaredMember is Procedure && declaredMember.isGetter;
-      bool interfaceMemberHasGetter = interfaceMember is Field ||
-          interfaceMember is Procedure && interfaceMember.isGetter;
-      bool declaredMemberHasSetter = (declaredMember is Field &&
-              !declaredMember.isFinal &&
-              !declaredMember.isConst) ||
-          declaredMember is Procedure && declaredMember.isSetter;
-      bool interfaceMemberHasSetter = (interfaceMember is Field &&
-              !interfaceMember.isFinal &&
-              !interfaceMember.isConst) ||
-          interfaceMember is Procedure && interfaceMember.isSetter;
-      if (declaredMemberHasGetter && interfaceMemberHasGetter) {
-        checkGetterOverride(
-            types, declaredMember, interfaceMember, isInterfaceCheck);
-      }
-      if (declaredMemberHasSetter && interfaceMemberHasSetter) {
-        bool seenCovariant = checkSetterOverride(
-            types, declaredMember, interfaceMember, isInterfaceCheck);
-        if (seenCovariant) {
-          handleSeenCovariant(
-              types, declaredMember, interfaceMember, isSetter, callback);
-        }
-      }
-    }
-    // TODO(ahe): Handle other cases: accessors, operators, and fields.
-  }
-
-  @override
   bool hasUserDefinedNoSuchMethod(
       Class klass, ClassHierarchy hierarchy, Class objectClass) {
     Member noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
@@ -855,9 +775,12 @@
 
   void transformProcedureToNoSuchMethodForwarder(
       Member noSuchMethodInterface, KernelTarget target, Procedure procedure) {
-    String prefix =
-        procedure.isGetter ? 'get:' : procedure.isSetter ? 'set:' : '';
-    String invocationName = prefix + procedure.name.name;
+    String prefix = procedure.isGetter
+        ? 'get:'
+        : procedure.isSetter
+            ? 'set:'
+            : '';
+    String invocationName = prefix + procedure.name.text;
     if (procedure.isSetter) invocationName += '=';
     Expression invocation = target.backendTarget.instantiateInvocation(
         target.loader.coreTypes,
@@ -892,524 +815,6 @@
     procedure.forwardingStubSuperTarget = null;
   }
 
-  Uri _getMemberUri(Member member) {
-    if (member is Field) return member.fileUri;
-    if (member is Procedure) return member.fileUri;
-    // Other member types won't be seen because constructors don't participate
-    // in override relationships
-    return unhandled('${member.runtimeType}', '_getMemberUri', -1, null);
-  }
-
-  Substitution _computeInterfaceSubstitution(
-      Types types,
-      Member declaredMember,
-      Member interfaceMember,
-      FunctionNode declaredFunction,
-      FunctionNode interfaceFunction,
-      bool isInterfaceCheck) {
-    Substitution interfaceSubstitution = Substitution.empty;
-    if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
-      Class enclosingClass = interfaceMember.enclosingClass;
-      interfaceSubstitution = Substitution.fromPairs(
-          enclosingClass.typeParameters,
-          types.hierarchy
-              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
-    }
-
-    if (declaredFunction?.typeParameters?.length !=
-        interfaceFunction?.typeParameters?.length) {
-      reportInvalidOverride(
-          isInterfaceCheck,
-          declaredMember,
-          templateOverrideTypeVariablesMismatch.withArguments(
-              "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
-          declaredMember.fileOffset,
-          noLength,
-          context: [
-            templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.name)
-                .withLocation(_getMemberUri(interfaceMember),
-                    interfaceMember.fileOffset, noLength)
-          ]);
-    } else if (declaredFunction?.typeParameters != null) {
-      Map<TypeParameter, DartType> substitutionMap =
-          <TypeParameter, DartType>{};
-      for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
-        substitutionMap[interfaceFunction.typeParameters[i]] =
-            new TypeParameterType.forAlphaRenaming(
-                interfaceFunction.typeParameters[i],
-                declaredFunction.typeParameters[i]);
-      }
-      Substitution substitution = Substitution.fromMap(substitutionMap);
-      for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
-        TypeParameter declaredParameter = declaredFunction.typeParameters[i];
-        TypeParameter interfaceParameter = interfaceFunction.typeParameters[i];
-        if (!interfaceParameter.isGenericCovariantImpl) {
-          DartType declaredBound = declaredParameter.bound;
-          DartType interfaceBound = interfaceParameter.bound;
-          if (interfaceSubstitution != null) {
-            declaredBound = interfaceSubstitution.substituteType(declaredBound);
-            interfaceBound =
-                interfaceSubstitution.substituteType(interfaceBound);
-          }
-          DartType computedBound = substitution.substituteType(interfaceBound);
-          if (!library.isNonNullableByDefault) {
-            computedBound =
-                legacyErasure(types.hierarchy.coreTypes, computedBound);
-          }
-          if (!types
-              .performNullabilityAwareMutualSubtypesCheck(
-                  declaredBound, computedBound)
-              .isSubtypeWhenUsingNullabilities()) {
-            reportInvalidOverride(
-                isInterfaceCheck,
-                declaredMember,
-                templateOverrideTypeVariablesBoundMismatch.withArguments(
-                    declaredBound,
-                    declaredParameter.name,
-                    "${declaredMember.enclosingClass.name}."
-                        "${declaredMember.name.name}",
-                    computedBound,
-                    "${interfaceMember.enclosingClass.name}."
-                        "${interfaceMember.name.name}",
-                    library.isNonNullableByDefault),
-                declaredMember.fileOffset,
-                noLength,
-                context: [
-                  templateOverriddenMethodCause
-                      .withArguments(interfaceMember.name.name)
-                      .withLocation(_getMemberUri(interfaceMember),
-                          interfaceMember.fileOffset, noLength)
-                ]);
-          }
-        }
-      }
-      interfaceSubstitution =
-          Substitution.combine(interfaceSubstitution, substitution);
-    }
-    return interfaceSubstitution;
-  }
-
-  Substitution _computeDeclaredSubstitution(
-      Types types, Member declaredMember) {
-    Substitution declaredSubstitution = Substitution.empty;
-    if (declaredMember.enclosingClass.typeParameters.isNotEmpty) {
-      Class enclosingClass = declaredMember.enclosingClass;
-      declaredSubstitution = Substitution.fromPairs(
-          enclosingClass.typeParameters,
-          types.hierarchy
-              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
-    }
-    return declaredSubstitution;
-  }
-
-  void _checkTypes(
-      Types types,
-      Substitution interfaceSubstitution,
-      Substitution declaredSubstitution,
-      Member declaredMember,
-      Member interfaceMember,
-      DartType declaredType,
-      DartType interfaceType,
-      bool isCovariant,
-      VariableDeclaration declaredParameter,
-      bool isInterfaceCheck,
-      {bool asIfDeclaredParameter = false}) {
-    if (interfaceSubstitution != null) {
-      interfaceType = interfaceSubstitution.substituteType(interfaceType);
-    }
-    if (declaredSubstitution != null) {
-      declaredType = declaredSubstitution.substituteType(declaredType);
-    }
-
-    if (!declaredMember.isNonNullableByDefault &&
-        interfaceMember.isNonNullableByDefault) {
-      interfaceType = legacyErasure(types.hierarchy.coreTypes, interfaceType);
-    }
-
-    bool inParameter = declaredParameter != null || asIfDeclaredParameter;
-    DartType subtype = inParameter ? interfaceType : declaredType;
-    DartType supertype = inParameter ? declaredType : interfaceType;
-
-    if (types.isSubtypeOf(
-        subtype, supertype, SubtypeCheckMode.withNullabilities)) {
-      // No problem--the proper subtyping relation is satisfied.
-    } else if (isCovariant &&
-        types.isSubtypeOf(
-            supertype, subtype, SubtypeCheckMode.withNullabilities)) {
-      // No problem--the overriding parameter is marked "covariant" and has
-      // a type which is a subtype of the parameter it overrides.
-    } else if (subtype is InvalidType || supertype is InvalidType) {
-      // Don't report a problem as something else is wrong that has already
-      // been reported.
-    } else {
-      // Report an error.
-      bool isErrorInNnbdOptedOutMode = !types.isSubtypeOf(
-              subtype, supertype, SubtypeCheckMode.ignoringNullabilities) &&
-          (!isCovariant ||
-              !types.isSubtypeOf(
-                  supertype, subtype, SubtypeCheckMode.ignoringNullabilities));
-      if (isErrorInNnbdOptedOutMode || library.isNonNullableByDefault) {
-        String declaredMemberName = '${declaredMember.enclosingClass.name}'
-            '.${declaredMember.name.name}';
-        String interfaceMemberName = '${interfaceMember.enclosingClass.name}'
-            '.${interfaceMember.name.name}';
-        Message message;
-        int fileOffset;
-        if (declaredParameter == null) {
-          if (asIfDeclaredParameter) {
-            // Setter overridden by field
-            message = templateOverrideTypeMismatchSetter.withArguments(
-                declaredMemberName,
-                declaredType,
-                interfaceType,
-                interfaceMemberName,
-                library.isNonNullableByDefault);
-          } else {
-            message = templateOverrideTypeMismatchReturnType.withArguments(
-                declaredMemberName,
-                declaredType,
-                interfaceType,
-                interfaceMemberName,
-                library.isNonNullableByDefault);
-          }
-          fileOffset = declaredMember.fileOffset;
-        } else {
-          message = templateOverrideTypeMismatchParameter.withArguments(
-              declaredParameter.name,
-              declaredMemberName,
-              declaredType,
-              interfaceType,
-              interfaceMemberName,
-              library.isNonNullableByDefault);
-          fileOffset = declaredParameter.fileOffset;
-        }
-        reportInvalidOverride(
-            isInterfaceCheck, declaredMember, message, fileOffset, noLength,
-            context: [
-              templateOverriddenMethodCause
-                  .withArguments(interfaceMember.name.name)
-                  .withLocation(_getMemberUri(interfaceMember),
-                      interfaceMember.fileOffset, noLength)
-            ]);
-      }
-    }
-  }
-
-  @override
-  bool checkMethodOverride(Types types, Procedure declaredMember,
-      Procedure interfaceMember, bool isInterfaceCheck) {
-    assert(declaredMember.kind == interfaceMember.kind);
-    assert(declaredMember.kind == ProcedureKind.Method ||
-        declaredMember.kind == ProcedureKind.Operator);
-    bool seenCovariant = false;
-    FunctionNode declaredFunction = declaredMember.function;
-    FunctionNode interfaceFunction = interfaceMember.function;
-
-    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
-        types,
-        declaredMember,
-        interfaceMember,
-        declaredFunction,
-        interfaceFunction,
-        isInterfaceCheck);
-
-    Substitution declaredSubstitution =
-        _computeDeclaredSubstitution(types, declaredMember);
-
-    _checkTypes(
-        types,
-        interfaceSubstitution,
-        declaredSubstitution,
-        declaredMember,
-        interfaceMember,
-        declaredFunction.returnType,
-        interfaceFunction.returnType,
-        false,
-        null,
-        isInterfaceCheck);
-    if (declaredFunction.positionalParameters.length <
-        interfaceFunction.positionalParameters.length) {
-      reportInvalidOverride(
-          isInterfaceCheck,
-          declaredMember,
-          templateOverrideFewerPositionalArguments.withArguments(
-              "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
-          declaredMember.fileOffset,
-          noLength,
-          context: [
-            templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.name)
-                .withLocation(interfaceMember.fileUri,
-                    interfaceMember.fileOffset, noLength)
-          ]);
-    }
-    if (interfaceFunction.requiredParameterCount <
-        declaredFunction.requiredParameterCount) {
-      reportInvalidOverride(
-          isInterfaceCheck,
-          declaredMember,
-          templateOverrideMoreRequiredArguments.withArguments(
-              "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
-          declaredMember.fileOffset,
-          noLength,
-          context: [
-            templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.name)
-                .withLocation(interfaceMember.fileUri,
-                    interfaceMember.fileOffset, noLength)
-          ]);
-    }
-    for (int i = 0;
-        i < declaredFunction.positionalParameters.length &&
-            i < interfaceFunction.positionalParameters.length;
-        i++) {
-      VariableDeclaration declaredParameter =
-          declaredFunction.positionalParameters[i];
-      VariableDeclaration interfaceParameter =
-          interfaceFunction.positionalParameters[i];
-      if (i == 0 &&
-          declaredMember.name == equalsName &&
-          declaredParameter.type ==
-              types.hierarchy.coreTypes.objectNonNullableRawType &&
-          interfaceParameter.type is DynamicType) {
-        // TODO(johnniwinther): Add check for opt-in overrides of operator ==.
-        // `operator ==` methods in opt-out classes have type
-        // `bool Function(dynamic)`.
-        continue;
-      }
-
-      _checkTypes(
-          types,
-          interfaceSubstitution,
-          declaredSubstitution,
-          declaredMember,
-          interfaceMember,
-          declaredParameter.type,
-          interfaceParameter.type,
-          declaredParameter.isCovariant || interfaceParameter.isCovariant,
-          declaredParameter,
-          isInterfaceCheck);
-      if (declaredParameter.isCovariant) seenCovariant = true;
-    }
-    if (declaredFunction.namedParameters.isEmpty &&
-        interfaceFunction.namedParameters.isEmpty) {
-      return seenCovariant;
-    }
-    if (declaredFunction.namedParameters.length <
-        interfaceFunction.namedParameters.length) {
-      reportInvalidOverride(
-          isInterfaceCheck,
-          declaredMember,
-          templateOverrideFewerNamedArguments.withArguments(
-              "${declaredMember.enclosingClass.name}."
-                  "${declaredMember.name.name}",
-              "${interfaceMember.enclosingClass.name}."
-                  "${interfaceMember.name.name}"),
-          declaredMember.fileOffset,
-          noLength,
-          context: [
-            templateOverriddenMethodCause
-                .withArguments(interfaceMember.name.name)
-                .withLocation(interfaceMember.fileUri,
-                    interfaceMember.fileOffset, noLength)
-          ]);
-    }
-    int compareNamedParameters(VariableDeclaration p0, VariableDeclaration p1) {
-      return p0.name.compareTo(p1.name);
-    }
-
-    List<VariableDeclaration> sortedFromDeclared =
-        new List.from(declaredFunction.namedParameters)
-          ..sort(compareNamedParameters);
-    List<VariableDeclaration> sortedFromInterface =
-        new List.from(interfaceFunction.namedParameters)
-          ..sort(compareNamedParameters);
-    Iterator<VariableDeclaration> declaredNamedParameters =
-        sortedFromDeclared.iterator;
-    Iterator<VariableDeclaration> interfaceNamedParameters =
-        sortedFromInterface.iterator;
-    outer:
-    while (declaredNamedParameters.moveNext() &&
-        interfaceNamedParameters.moveNext()) {
-      while (declaredNamedParameters.current.name !=
-          interfaceNamedParameters.current.name) {
-        if (!declaredNamedParameters.moveNext()) {
-          reportInvalidOverride(
-              isInterfaceCheck,
-              declaredMember,
-              templateOverrideMismatchNamedParameter.withArguments(
-                  "${declaredMember.enclosingClass.name}."
-                      "${declaredMember.name.name}",
-                  interfaceNamedParameters.current.name,
-                  "${interfaceMember.enclosingClass.name}."
-                      "${interfaceMember.name.name}"),
-              declaredMember.fileOffset,
-              noLength,
-              context: [
-                templateOverriddenMethodCause
-                    .withArguments(interfaceMember.name.name)
-                    .withLocation(interfaceMember.fileUri,
-                        interfaceMember.fileOffset, noLength)
-              ]);
-          break outer;
-        }
-      }
-      VariableDeclaration declaredParameter = declaredNamedParameters.current;
-      _checkTypes(
-          types,
-          interfaceSubstitution,
-          declaredSubstitution,
-          declaredMember,
-          interfaceMember,
-          declaredParameter.type,
-          interfaceNamedParameters.current.type,
-          declaredParameter.isCovariant,
-          declaredParameter,
-          isInterfaceCheck);
-      if (declaredMember.isNonNullableByDefault &&
-          declaredParameter.isRequired &&
-          interfaceMember.isNonNullableByDefault &&
-          !interfaceNamedParameters.current.isRequired) {
-        reportInvalidOverride(
-            isInterfaceCheck,
-            declaredMember,
-            templateOverrideMismatchRequiredNamedParameter.withArguments(
-                declaredParameter.name,
-                "${declaredMember.enclosingClass.name}."
-                    "${declaredMember.name.name}",
-                "${interfaceMember.enclosingClass.name}."
-                    "${interfaceMember.name.name}"),
-            declaredParameter.fileOffset,
-            noLength,
-            context: [
-              templateOverriddenMethodCause
-                  .withArguments(interfaceMember.name.name)
-                  .withLocation(_getMemberUri(interfaceMember),
-                      interfaceMember.fileOffset, noLength)
-            ]);
-      }
-      if (declaredParameter.isCovariant) seenCovariant = true;
-    }
-    return seenCovariant;
-  }
-
-  void checkGetterOverride(Types types, Member declaredMember,
-      Member interfaceMember, bool isInterfaceCheck) {
-    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
-        types, declaredMember, interfaceMember, null, null, isInterfaceCheck);
-    Substitution declaredSubstitution =
-        _computeDeclaredSubstitution(types, declaredMember);
-    DartType declaredType = declaredMember.getterType;
-    DartType interfaceType = interfaceMember.getterType;
-    _checkTypes(
-        types,
-        interfaceSubstitution,
-        declaredSubstitution,
-        declaredMember,
-        interfaceMember,
-        declaredType,
-        interfaceType,
-        false,
-        null,
-        isInterfaceCheck);
-  }
-
-  @override
-  bool checkSetterOverride(Types types, Member declaredMember,
-      Member interfaceMember, bool isInterfaceCheck) {
-    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
-        types, declaredMember, interfaceMember, null, null, isInterfaceCheck);
-    Substitution declaredSubstitution =
-        _computeDeclaredSubstitution(types, declaredMember);
-    DartType declaredType = declaredMember.setterType;
-    DartType interfaceType = interfaceMember.setterType;
-    VariableDeclaration declaredParameter =
-        declaredMember.function?.positionalParameters?.elementAt(0);
-    bool isCovariant = declaredParameter?.isCovariant ?? false;
-    if (!isCovariant && declaredMember is Field) {
-      isCovariant = declaredMember.isCovariant;
-    }
-    if (!isCovariant && interfaceMember is Field) {
-      isCovariant = interfaceMember.isCovariant;
-    }
-    _checkTypes(
-        types,
-        interfaceSubstitution,
-        declaredSubstitution,
-        declaredMember,
-        interfaceMember,
-        declaredType,
-        interfaceType,
-        isCovariant,
-        declaredParameter,
-        isInterfaceCheck,
-        asIfDeclaredParameter: true);
-    return isCovariant;
-  }
-
-  @override
-  void reportInvalidOverride(bool isInterfaceCheck, Member declaredMember,
-      Message message, int fileOffset, int length,
-      {List<LocatedMessage> context}) {
-    if (shouldOverrideProblemBeOverlooked(this)) {
-      return;
-    }
-
-    if (declaredMember.enclosingClass == cls) {
-      // Ordinary override
-      library.addProblem(message, fileOffset, length, declaredMember.fileUri,
-          context: context);
-    } else {
-      context = [
-        message.withLocation(declaredMember.fileUri, fileOffset, length),
-        ...?context
-      ];
-      if (isInterfaceCheck) {
-        // Interface check
-        library.addProblem(
-            templateInterfaceCheck.withArguments(
-                declaredMember.name.name, cls.name),
-            cls.fileOffset,
-            cls.name.length,
-            cls.fileUri,
-            context: context);
-      } else {
-        if (cls.isAnonymousMixin) {
-          // Implicit mixin application class
-          String baseName = cls.superclass.demangledName;
-          String mixinName = cls.mixedInClass.name;
-          int classNameLength = cls.nameAsMixinApplicationSubclass.length;
-          library.addProblem(
-              templateImplicitMixinOverride.withArguments(
-                  mixinName, baseName, declaredMember.name.name),
-              cls.fileOffset,
-              classNameLength,
-              cls.fileUri,
-              context: context);
-        } else {
-          // Named mixin application class
-          library.addProblem(
-              templateNamedMixinOverride.withArguments(
-                  cls.name, declaredMember.name.name),
-              cls.fileOffset,
-              cls.name.length,
-              cls.fileUri,
-              context: context);
-        }
-      }
-    }
-  }
-
   @override
   String get fullNameForErrors {
     return isMixinApplication && !isNamedMixinApplication
diff --git a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
index 8cec3c9..ec49e0f 100644
--- a/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/constructor_builder.dart
@@ -11,6 +11,8 @@
 
 import '../constant_context.dart' show ConstantContext;
 
+import '../dill/dill_member_builder.dart';
+
 import '../kernel/body_builder.dart' show BodyBuilder;
 import '../kernel/class_hierarchy_builder.dart' show ClassMember;
 import '../kernel/expression_generator_helper.dart'
@@ -18,6 +20,7 @@
 
 import '../kernel/kernel_builder.dart'
     show isRedirectingGenerativeConstructorImplementation;
+import '../kernel/kernel_target.dart' show ClonedFunctionNode;
 
 import '../loader.dart' show Loader;
 
@@ -31,6 +34,7 @@
         messageSuperInitializerNotLast,
         noLength;
 
+import '../source/source_class_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import 'builder.dart';
@@ -431,3 +435,26 @@
     return result;
   }
 }
+
+class SyntheticConstructorBuilder extends DillMemberBuilder {
+  MemberBuilderImpl _origin;
+  ClonedFunctionNode _clonedFunctionNode;
+
+  SyntheticConstructorBuilder(
+      SourceClassBuilder parent, Constructor constructor,
+      {MemberBuilder origin, ClonedFunctionNode clonedFunctionNode})
+      : _origin = origin,
+        _clonedFunctionNode = clonedFunctionNode,
+        super(constructor, parent);
+
+  void buildOutlineExpressions(
+      LibraryBuilder libraryBuilder, CoreTypes coreTypes) {
+    if (_origin != null) {
+      // Ensure that default value expressions have been created for [_origin].
+      _origin.buildOutlineExpressions(libraryBuilder, coreTypes);
+      _clonedFunctionNode.cloneDefaultValues();
+      _clonedFunctionNode = null;
+      _origin = null;
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index da4182e..537e376 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -11,7 +11,6 @@
         Class,
         Constructor,
         ConstructorInvocation,
-        DirectPropertyGet,
         Expression,
         Field,
         FieldInitializer,
@@ -20,6 +19,7 @@
         ListLiteral,
         Procedure,
         ProcedureKind,
+        PropertyGet,
         ReturnStatement,
         StaticGet,
         StringLiteral,
@@ -386,7 +386,7 @@
     Field nameField = nameFieldBuilder.field;
     ProcedureBuilder toStringBuilder = firstMemberNamed("toString");
     toStringBuilder.body = new ReturnStatement(
-        new DirectPropertyGet(new ThisExpression(), nameField));
+        new PropertyGet(new ThisExpression(), nameField.name, nameField));
     List<Expression> values = <Expression>[];
     if (enumConstantInfos != null) {
       for (EnumConstantInfo enumConstantInfo in enumConstantInfos) {
diff --git a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
index 5dbfb12..b361811 100644
--- a/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/extension_builder.dart
@@ -119,7 +119,7 @@
   Builder lookupLocalMemberByName(Name name,
       {bool setter: false, bool required: false}) {
     Builder builder =
-        lookupLocalMember(name.name, setter: setter, required: required);
+        lookupLocalMember(name.text, setter: setter, required: required);
     if (builder != null && name.isPrivate && library.library != name.library) {
       builder = null;
     }
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 9f0a936..607bf99 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -122,6 +122,10 @@
       Procedure setterReferenceFrom)
       : super(libraryBuilder, charOffset) {
     Uri fileUri = libraryBuilder?.fileUri;
+    // If in mixed mode, late lowerings cannot use `null` as a sentinel on
+    // non-nullable fields since they can be assigned from legacy code.
+    late_lowering.IsSetStrategy isSetStrategy =
+        late_lowering.computeIsSetStrategy(libraryBuilder);
     if (isAbstract || isExternal) {
       _fieldEncoding = new AbstractOrExternalFieldEncoding(fileUri, charOffset,
           charEndOffset, getterReferenceFrom, setterReferenceFrom,
@@ -143,7 +147,8 @@
               lateIsSetReferenceFrom,
               getterReferenceFrom,
               setterReferenceFrom,
-              isCovariant);
+              isCovariant,
+              isSetStrategy);
         } else {
           _fieldEncoding = new LateFieldWithInitializerEncoding(
               name,
@@ -154,7 +159,8 @@
               lateIsSetReferenceFrom,
               getterReferenceFrom,
               setterReferenceFrom,
-              isCovariant);
+              isCovariant,
+              isSetStrategy);
         }
       } else {
         if (isFinal) {
@@ -167,7 +173,8 @@
               lateIsSetReferenceFrom,
               getterReferenceFrom,
               setterReferenceFrom,
-              isCovariant);
+              isCovariant,
+              isSetStrategy);
         } else {
           _fieldEncoding = new LateFieldWithoutInitializerEncoding(
               name,
@@ -178,7 +185,8 @@
               lateIsSetReferenceFrom,
               getterReferenceFrom,
               setterReferenceFrom,
-              isCovariant);
+              isCovariant,
+              isSetStrategy);
         }
       }
     } else if (libraryBuilder.isNonNullableByDefault &&
@@ -196,7 +204,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
       } else {
         _fieldEncoding = new LateFieldWithInitializerEncoding(
             name,
@@ -207,7 +216,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
       }
     } else {
       assert(lateIsSetReferenceFrom == null);
@@ -221,9 +231,13 @@
   bool _typeEnsured = false;
   Set<ClassMember> _overrideDependencies;
 
-  void registerOverrideDependency(ClassMember overriddenMember) {
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    assert(
+        overriddenMembers.every((overriddenMember) =>
+            overriddenMember.classBuilder != classBuilder),
+        "Unexpected override dependencies for $this: $overriddenMembers");
     _overrideDependencies ??= {};
-    _overrideDependencies.add(overriddenMember);
+    _overrideDependencies.addAll(overriddenMembers);
   }
 
   void _ensureType(ClassHierarchyBuilder hierarchy) {
@@ -685,8 +699,8 @@
   }
 
   @override
-  void registerOverrideDependency(ClassMember overriddenMember) {
-    memberBuilder.registerOverrideDependency(overriddenMember);
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    memberBuilder.registerOverrideDependency(overriddenMembers);
   }
 
   @override
@@ -703,6 +717,11 @@
 
   @override
   bool get isFunction => false;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    return other is SourceFieldMember && memberBuilder == other.memberBuilder;
+  }
 }
 
 abstract class AbstractLateFieldEncoding implements FieldEncoding {
@@ -714,11 +733,22 @@
   Procedure _lateGetter;
   Procedure _lateSetter;
 
+  // If `true`, an isSet field is used even when the type of the field is
+  // not potentially nullable.
+  //
+  // This is used to force use isSet fields in mixed mode encoding since
+  // we cannot trust non-nullable fields to be initialized with non-null values.
+  late_lowering.IsSetStrategy _isSetStrategy;
+  late_lowering.IsSetEncoding _isSetEncoding;
+
   // If `true`, the is-set field was register before the type was known to be
   // nullable or non-nullable. In this case we do not try to remove it from
   // the generated AST to avoid inconsistency between the class hierarchy used
   // during and after inference.
-  bool _forceIncludeIsSetField = false;
+  //
+  // This is also used to force use isSet fields in mixed mode encoding since
+  // we cannot trust non-nullable fields to be initialized with non-null values.
+  bool _forceIncludeIsSetField;
 
   AbstractLateFieldEncoding(
       this.name,
@@ -729,20 +759,32 @@
       Field lateIsSetReferenceFrom,
       Procedure getterReferenceFrom,
       Procedure setterReferenceFrom,
-      bool isCovariant)
-      : fileOffset = charOffset {
+      bool isCovariant,
+      late_lowering.IsSetStrategy isSetStrategy)
+      : fileOffset = charOffset,
+        _isSetStrategy = isSetStrategy,
+        _forceIncludeIsSetField =
+            isSetStrategy == late_lowering.IsSetStrategy.forceUseIsSetField {
     _field =
         new Field(null, fileUri: fileUri, reference: referenceFrom?.reference)
           ..fileOffset = charOffset
           ..fileEndOffset = charEndOffset
           ..isNonNullableByDefault = true
           ..isInternalImplementation = true;
-    _lateIsSetField = new Field(null,
-        fileUri: fileUri, reference: lateIsSetReferenceFrom?.reference)
-      ..fileOffset = charOffset
-      ..fileEndOffset = charEndOffset
-      ..isNonNullableByDefault = true
-      ..isInternalImplementation = true;
+    switch (_isSetStrategy) {
+      case late_lowering.IsSetStrategy.useSentinelOrNull:
+        // [_lateIsSetField] is never needed.
+        break;
+      case late_lowering.IsSetStrategy.forceUseIsSetField:
+      case late_lowering.IsSetStrategy.useIsSetFieldOrNull:
+        _lateIsSetField = new Field(null,
+            fileUri: fileUri, reference: lateIsSetReferenceFrom?.reference)
+          ..fileOffset = charOffset
+          ..fileEndOffset = charEndOffset
+          ..isNonNullableByDefault = true
+          ..isInternalImplementation = true;
+        break;
+    }
     _lateGetter = new Procedure(
         null, ProcedureKind.Getter, new FunctionNode(null),
         fileUri: fileUri, reference: getterReferenceFrom?.reference)
@@ -752,6 +794,12 @@
         isCovariant: isCovariant);
   }
 
+  late_lowering.IsSetEncoding get isSetEncoding {
+    assert(_type != null, "Type has not been computed for field $name.");
+    return _isSetEncoding ??=
+        late_lowering.computeIsSetEncoding(_type, _isSetStrategy);
+  }
+
   @override
   void completeSignature(CoreTypes coreTypes) {
     if (_lateIsSetField != null) {
@@ -762,7 +810,15 @@
   @override
   void createBodies(CoreTypes coreTypes, Expression initializer) {
     assert(_type != null, "Type has not been computed for field $name.");
-    _field.initializer = new NullLiteral()..parent = _field;
+    if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
+      _field.initializer = new StaticInvocation(coreTypes.createSentinelMethod,
+          new Arguments([], types: [_type])..fileOffset = fileOffset)
+        ..parent = _field;
+    } else {
+      _field.initializer = new NullLiteral()
+        ..fileOffset = fileOffset
+        ..parent = _field;
+    }
     if (_lateIsSetField != null) {
       _lateIsSetField.initializer = new BoolLiteral(false)
         ..fileOffset = fileOffset
@@ -1010,13 +1066,16 @@
   @override
   List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) {
     List<ClassMember> list = <ClassMember>[
-      new _SynthesizedFieldClassMember(fieldBuilder, field,
+      new _SynthesizedFieldClassMember(
+          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
           isInternalImplementation: true),
       new _SynthesizedFieldClassMember(fieldBuilder, _lateGetter,
+          _SynthesizedFieldMemberKind.LateGetterSetter,
           isInternalImplementation: false)
     ];
     if (_lateIsSetField != null) {
-      list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateIsSetField,
+      list.add(new _SynthesizedFieldClassMember(
+          fieldBuilder, _lateIsSetField, _SynthesizedFieldMemberKind.LateIsSet,
           isInternalImplementation: true));
     }
     return list;
@@ -1024,13 +1083,19 @@
 
   @override
   List<ClassMember> getLocalSetters(SourceFieldBuilder fieldBuilder) {
-    List<ClassMember> list = <ClassMember>[];
+    List<ClassMember> list = <ClassMember>[
+      new _SynthesizedFieldClassMember(
+          fieldBuilder, field, _SynthesizedFieldMemberKind.LateField,
+          forSetter: true, isInternalImplementation: true),
+    ];
     if (_lateIsSetField != null) {
-      list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateIsSetField,
+      list.add(new _SynthesizedFieldClassMember(
+          fieldBuilder, _lateIsSetField, _SynthesizedFieldMemberKind.LateIsSet,
           forSetter: true, isInternalImplementation: true));
     }
     if (_lateSetter != null) {
       list.add(new _SynthesizedFieldClassMember(fieldBuilder, _lateSetter,
+          _SynthesizedFieldMemberKind.LateGetterSetter,
           forSetter: true, isInternalImplementation: false));
     }
     return list;
@@ -1048,7 +1113,8 @@
         createVariableWrite: (Expression value) =>
             _createFieldSet(_field, value),
         createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField, value));
+            _createFieldSet(_lateIsSetField, value),
+        isSetEncoding: isSetEncoding);
   }
 }
 
@@ -1060,7 +1126,8 @@
     return late_lowering.createGetterBodyWithoutInitializer(
         coreTypes, fileOffset, name, type, 'Field',
         createVariableRead: _createFieldRead,
-        createIsSetRead: () => _createFieldGet(_lateIsSetField));
+        createIsSetRead: () => _createFieldGet(_lateIsSetField),
+        isSetEncoding: isSetEncoding);
   }
 }
 
@@ -1075,7 +1142,8 @@
       Field lateIsSetReferenceFrom,
       Procedure getterReferenceFrom,
       Procedure setterReferenceFrom,
-      bool isCovariant)
+      bool isCovariant,
+      late_lowering.IsSetStrategy isSetStrategy)
       : super(
             name,
             fileUri,
@@ -1085,7 +1153,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
 }
 
 class LateFieldWithInitializerEncoding extends AbstractLateFieldEncoding
@@ -1099,7 +1168,8 @@
       Field lateIsSetReferenceFrom,
       Procedure getterReferenceFrom,
       Procedure setterReferenceFrom,
-      bool isCovariant)
+      bool isCovariant,
+      late_lowering.IsSetStrategy isSetStrategy)
       : super(
             name,
             fileUri,
@@ -1109,7 +1179,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
 
   @override
   Statement _createGetterBody(
@@ -1122,7 +1193,8 @@
             _createFieldSet(_field, value),
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
         createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField, value));
+            _createFieldSet(_lateIsSetField, value),
+        isSetEncoding: isSetEncoding);
   }
 }
 
@@ -1137,7 +1209,8 @@
       Field lateIsSetReferenceFrom,
       Procedure getterReferenceFrom,
       Procedure setterReferenceFrom,
-      bool isCovariant)
+      bool isCovariant,
+      late_lowering.IsSetStrategy isSetStrategy)
       : super(
             name,
             fileUri,
@@ -1147,7 +1220,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
 
   @override
   Statement _createSetterBody(
@@ -1161,7 +1235,8 @@
             _createFieldSet(_field, value),
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
         createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField, value));
+            _createFieldSet(_lateIsSetField, value),
+        isSetEncoding: isSetEncoding);
   }
 }
 
@@ -1175,7 +1250,8 @@
       Field lateIsSetReferenceFrom,
       Procedure getterReferenceFrom,
       Procedure setterReferenceFrom,
-      bool isCovariant)
+      bool isCovariant,
+      late_lowering.IsSetStrategy isSetStrategy)
       : super(
             name,
             fileUri,
@@ -1185,7 +1261,8 @@
             lateIsSetReferenceFrom,
             getterReferenceFrom,
             setterReferenceFrom,
-            isCovariant);
+            isCovariant,
+            isSetStrategy);
   @override
   Statement _createGetterBody(
       CoreTypes coreTypes, String name, Expression initializer) {
@@ -1197,7 +1274,8 @@
             _createFieldSet(_field, value),
         createIsSetRead: () => _createFieldGet(_lateIsSetField),
         createIsSetWrite: (Expression value) =>
-            _createFieldSet(_lateIsSetField, value));
+            _createFieldSet(_lateIsSetField, value),
+        isSetEncoding: isSetEncoding);
   }
 
   @override
@@ -1214,6 +1292,7 @@
 
 class _SynthesizedFieldClassMember implements ClassMember {
   final SourceFieldBuilder fieldBuilder;
+  final _SynthesizedFieldMemberKind _kind;
 
   final Member _member;
 
@@ -1223,7 +1302,7 @@
   @override
   final bool isInternalImplementation;
 
-  _SynthesizedFieldClassMember(this.fieldBuilder, this._member,
+  _SynthesizedFieldClassMember(this.fieldBuilder, this._member, this._kind,
       {this.forSetter: false, this.isInternalImplementation})
       : assert(isInternalImplementation != null);
 
@@ -1238,8 +1317,8 @@
   }
 
   @override
-  void registerOverrideDependency(ClassMember overriddenMember) {
-    fieldBuilder.registerOverrideDependency(overriddenMember);
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    fieldBuilder.registerOverrideDependency(overriddenMembers);
   }
 
   @override
@@ -1355,8 +1434,16 @@
   }
 
   @override
-  String toString() =>
-      '_ClassMember($fieldBuilder,$_member,forSetter=${forSetter})';
+  bool isSameDeclaration(ClassMember other) {
+    if (identical(this, other)) return true;
+    return other is _SynthesizedFieldClassMember &&
+        fieldBuilder == other.fieldBuilder &&
+        _kind == other._kind;
+  }
+
+  @override
+  String toString() => '_SynthesizedFieldClassMember('
+      '$fieldBuilder,$_member,$_kind,forSetter=${forSetter})';
 }
 
 class AbstractOrExternalFieldEncoding implements FieldEncoding {
@@ -1384,8 +1471,9 @@
       ..fileEndOffset = charEndOffset
       ..isNonNullableByDefault = isNonNullableByDefault;
     if (!isFinal) {
-      VariableDeclaration parameter = new VariableDeclaration(null)
-        ..isCovariant = isCovariant;
+      VariableDeclaration parameter =
+          new VariableDeclaration("#externalFieldValue")
+            ..isCovariant = isCovariant;
       _setter = new Procedure(
           null,
           ProcedureKind.Setter,
@@ -1523,6 +1611,7 @@
   List<ClassMember> getLocalMembers(SourceFieldBuilder fieldBuilder) =>
       <ClassMember>[
         new _SynthesizedFieldClassMember(fieldBuilder, _getter,
+            _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
             forSetter: false, isInternalImplementation: false)
       ];
 
@@ -1531,7 +1620,22 @@
       _setter != null
           ? <ClassMember>[
               new _SynthesizedFieldClassMember(fieldBuilder, _setter,
+                  _SynthesizedFieldMemberKind.AbstractExternalGetterSetter,
                   forSetter: true, isInternalImplementation: false)
             ]
           : const <ClassMember>[];
 }
+
+enum _SynthesizedFieldMemberKind {
+  /// A `isSet` field used for late lowering.
+  LateIsSet,
+
+  /// A field used for the value of a late lowered field.
+  LateField,
+
+  /// A getter or setter used for late lowering.
+  LateGetterSetter,
+
+  /// A getter or setter used for abstract or external fields.
+  AbstractExternalGetterSetter,
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
index d06e553..ff976c0 100644
--- a/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/formal_parameter_builder.dart
@@ -165,41 +165,42 @@
   /// Builds the default value from this [initializerToken] if this is a
   /// formal parameter on a const constructor or instance method.
   void buildOutlineExpressions(LibraryBuilder library) {
-    // For modular compilation we need to include initializers for optional
-    // and named parameters of const constructors into the outline - to enable
-    // constant evaluation. Similarly we need to include initializers for
-    // optional and named parameters of instance methods because these might be
-    // needed to generated noSuchMethod forwarders.
-    bool isConstConstructorParameter = false;
-    if (parent is ConstructorBuilder) {
-      isConstConstructorParameter = parent.isConst;
-    } else if (parent is ProcedureBuilder) {
-      isConstConstructorParameter = parent.isFactory && parent.isConst;
-    }
-    if ((isConstConstructorParameter || parent.isClassInstanceMember) &&
-        initializerToken != null) {
-      final ClassBuilder classBuilder = parent.parent;
-      Scope scope = classBuilder.scope;
-      BodyBuilder bodyBuilder = library.loader
-          .createBodyBuilderForOutlineExpression(
-              library, classBuilder, this, scope, fileUri);
-      bodyBuilder.constantContext = ConstantContext.required;
-      assert(!initializerWasInferred);
-      Expression initializer =
-          bodyBuilder.parseFieldInitializer(initializerToken);
-      initializer = bodyBuilder.typeInferrer?.inferParameterInitializer(
-          bodyBuilder, initializer, variable.type, hasDeclaredInitializer);
-      variable.initializer = initializer..parent = variable;
-      if (library.loader is SourceLoader) {
-        SourceLoader loader = library.loader;
-        loader.transformPostInference(
-            variable,
-            bodyBuilder.transformSetLiterals,
-            bodyBuilder.transformCollections,
-            library.library);
+    if (initializerToken != null) {
+      // For modular compilation we need to include initializers for optional
+      // and named parameters of const constructors into the outline - to enable
+      // constant evaluation. Similarly we need to include initializers for
+      // optional and named parameters of instance methods because these might
+      // be needed to generated noSuchMethod forwarders.
+      bool isConstConstructorParameter = false;
+      if (parent is ConstructorBuilder) {
+        isConstConstructorParameter = parent.isConst;
+      } else if (parent is ProcedureBuilder) {
+        isConstConstructorParameter = parent.isFactory && parent.isConst;
       }
-      initializerWasInferred = true;
-      bodyBuilder.resolveRedirectingFactoryTargets();
+      if (isConstConstructorParameter || parent.isClassInstanceMember) {
+        final ClassBuilder classBuilder = parent.parent;
+        Scope scope = classBuilder.scope;
+        BodyBuilder bodyBuilder = library.loader
+            .createBodyBuilderForOutlineExpression(
+                library, classBuilder, this, scope, fileUri);
+        bodyBuilder.constantContext = ConstantContext.required;
+        assert(!initializerWasInferred);
+        Expression initializer =
+            bodyBuilder.parseFieldInitializer(initializerToken);
+        initializer = bodyBuilder.typeInferrer?.inferParameterInitializer(
+            bodyBuilder, initializer, variable.type, hasDeclaredInitializer);
+        variable.initializer = initializer..parent = variable;
+        if (library.loader is SourceLoader) {
+          SourceLoader loader = library.loader;
+          loader.transformPostInference(
+              variable,
+              bodyBuilder.transformSetLiterals,
+              bodyBuilder.transformCollections,
+              library.library);
+        }
+        initializerWasInferred = true;
+        bodyBuilder.resolveRedirectingFactoryTargets();
+      }
     }
     initializerToken = null;
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/function_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
index a7d3e2d..2fea24a 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_builder.dart
@@ -498,19 +498,24 @@
     return _extensionTypeParameters;
   }
 
+  bool _hasBuiltOutlineExpressions = false;
+
   @override
   void buildOutlineExpressions(LibraryBuilder library, CoreTypes coreTypes) {
-    MetadataBuilder.buildAnnotations(
-        member, metadata, library, isClassMember ? parent : null, this);
+    if (!_hasBuiltOutlineExpressions) {
+      MetadataBuilder.buildAnnotations(
+          member, metadata, library, isClassMember ? parent : null, this);
 
-    if (formals != null) {
-      // For const constructors we need to include default parameter values
-      // into the outline. For all other formals we need to call
-      // buildOutlineExpressions to clear initializerToken to prevent
-      // consuming too much memory.
-      for (FormalParameterBuilder formal in formals) {
-        formal.buildOutlineExpressions(library);
+      if (formals != null) {
+        // For const constructors we need to include default parameter values
+        // into the outline. For all other formals we need to call
+        // buildOutlineExpressions to clear initializerToken to prevent
+        // consuming too much memory.
+        for (FormalParameterBuilder formal in formals) {
+          formal.buildOutlineExpressions(library);
+        }
       }
+      _hasBuiltOutlineExpressions = true;
     }
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
index d91935f..f8700b1 100644
--- a/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/never_type_declaration_builder.dart
@@ -4,28 +4,47 @@
 
 library fasta.never_type_builder;
 
-import 'package:kernel/ast.dart' show DartType, Nullability;
+import 'package:kernel/ast.dart' show DartType, InterfaceType, Nullability;
 
 import 'builtin_type_declaration_builder.dart';
+import 'class_builder.dart';
 import 'library_builder.dart';
 import 'nullability_builder.dart';
 import 'type_builder.dart';
 
 class NeverTypeDeclarationBuilder extends BuiltinTypeDeclarationBuilder {
-  NeverTypeDeclarationBuilder(
-      DartType type, LibraryBuilder compilationUnit, int charOffset)
-      : super("Never", type, compilationUnit, charOffset);
+  final LibraryBuilder coreLibrary;
+  DartType _nullType;
+
+  NeverTypeDeclarationBuilder(DartType type, this.coreLibrary, int charOffset)
+      : super("Never", type, coreLibrary, charOffset) {
+    assert(coreLibrary.importUri == Uri.parse('dart:core'));
+  }
 
   String get debugName => "NeverTypeDeclarationBuilder";
 
+  DartType get nullType {
+    if (_nullType == null) {
+      ClassBuilder nullClass = coreLibrary.lookupLocalMember('Null');
+      _nullType = new InterfaceType(nullClass.cls, Nullability.nullable, []);
+    }
+    return _nullType;
+  }
+
   DartType buildType(LibraryBuilder library,
       NullabilityBuilder nullabilityBuilder, List<TypeBuilder> arguments,
       [bool notInstanceContext]) {
+    if (!library.isNonNullableByDefault) {
+      return nullType;
+    }
     return type.withDeclaredNullability(nullabilityBuilder.build(library));
   }
 
   DartType buildTypesWithBuiltArguments(LibraryBuilder library,
       Nullability nullability, List<DartType> arguments) {
+    if (!library.isNonNullableByDefault) {
+      return nullType;
+    }
     return type.withDeclaredNullability(nullability);
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
index 75c8ba1..54a738b 100644
--- a/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/procedure_builder.dart
@@ -249,9 +249,13 @@
   bool _typeEnsured = false;
   Set<ClassMember> _overrideDependencies;
 
-  void registerOverrideDependency(ClassMember overriddenMember) {
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    assert(
+        overriddenMembers.every((overriddenMember) =>
+            overriddenMember.classBuilder != classBuilder),
+        "Unexpected override dependencies for $this: $overriddenMembers");
     _overrideDependencies ??= {};
-    _overrideDependencies.add(overriddenMember);
+    _overrideDependencies.addAll(overriddenMembers);
   }
 
   void _ensureTypes(ClassHierarchyBuilder hierarchy) {
@@ -526,9 +530,7 @@
         positionalParameters: closurePositionalParameters,
         namedParameters: closureNamedParameters,
         requiredParameterCount: _procedure.function.requiredParameterCount - 1,
-        returnType: closureReturnType,
-        asyncMarker: _procedure.function.asyncMarker,
-        dartAsyncMarker: _procedure.function.dartAsyncMarker))
+        returnType: closureReturnType))
       ..fileOffset = fileOffset;
 
     _extensionTearOff
@@ -594,8 +596,8 @@
   }
 
   @override
-  void registerOverrideDependency(ClassMember overriddenMember) {
-    memberBuilder.registerOverrideDependency(overriddenMember);
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
+    memberBuilder.registerOverrideDependency(overriddenMembers);
   }
 
   @override
@@ -614,6 +616,12 @@
 
   @override
   bool get isFunction => !isProperty;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    return other is SourceProcedureMember &&
+        memberBuilder == other.memberBuilder;
+  }
 }
 
 class RedirectingFactoryBuilder extends ProcedureBuilderImpl {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 73003a2..b8afcf7 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -73,7 +73,7 @@
 
   void addMember(Member member) {
     DillMemberBuilder builder = new DillMemberBuilder(member, this);
-    String name = member.name.name;
+    String name = member.name.text;
     if (builder.isConstructor || builder.isFactory) {
       constructorScopeBuilder.addMember(name, builder);
     } else if (builder.isSetter) {
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
index 803ebd2..86aaa4d 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_extension_builder.dart
@@ -52,12 +52,12 @@
         case ExtensionMemberKind.Operator:
         case ExtensionMemberKind.Field:
           Member member = descriptor.member.asMember;
-          scopeBuilder.addMember(name.name,
+          scopeBuilder.addMember(name.text,
               new DillExtensionMemberBuilder(member, descriptor, this));
           break;
         case ExtensionMemberKind.Setter:
           Member member = descriptor.member.asMember;
-          scopeBuilder.addSetter(name.name,
+          scopeBuilder.addSetter(name.text,
               new DillExtensionMemberBuilder(member, descriptor, this));
           break;
       }
@@ -65,7 +65,7 @@
     _methods.forEach((Name name, ExtensionMemberDescriptor descriptor) {
       Member member = descriptor.member.asMember;
       scopeBuilder.addMember(
-          name.name,
+          name.text,
           new DillExtensionMemberBuilder(
               member, descriptor, this, _tearOffs[name]));
     });
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 07ed03c..e36d001 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -187,7 +187,7 @@
   }
 
   void addMember(Member member) {
-    String name = member.name.name;
+    String name = member.name.text;
     if (name == "_exports#") {
       Field field = member;
       String stringValue;
@@ -327,11 +327,11 @@
           name = node.name;
         } else if (node is Procedure) {
           libraryUri = node.enclosingLibrary.importUri;
-          name = node.name.name;
+          name = node.name.text;
           isSetter = node.isSetter;
         } else if (node is Member) {
           libraryUri = node.enclosingLibrary.importUri;
-          name = node.name.name;
+          name = node.name.text;
         } else if (node is Typedef) {
           libraryUri = node.enclosingLibrary.importUri;
           name = node.name;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
index 2426266..d31e6dd 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_member_builder.dart
@@ -33,7 +33,7 @@
 
   String get debugName => "DillMemberBuilder";
 
-  String get name => member.name.name;
+  String get name => member.name.text;
 
   bool get isConstructor => member is Constructor;
 
@@ -187,10 +187,15 @@
   }
 
   @override
-  void registerOverrideDependency(ClassMember overriddenMember) {
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
     // Do nothing; this is only for source members.
   }
 
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    return other is DillClassMember && memberBuilder == other.memberBuilder;
+  }
+
   String toString() => 'DillClassMember($memberBuilder,forSetter=${forSetter})';
 }
 
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
index 6927bdd7..3e928df 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart
@@ -353,34 +353,34 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
-        Message Function(String string, Constant _constant, DartType _type,
-            DartType _type2, bool isNonNullableByDefault)>
+        Message Function(String stringOKEmpty, Constant _constant,
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
     templateConstEvalInvalidBinaryOperandType = const Template<
-            Message Function(String string, Constant _constant, DartType _type,
-                DartType _type2, bool isNonNullableByDefault)>(
+            Message Function(String stringOKEmpty, Constant _constant,
+                DartType _type, DartType _type2, bool isNonNullableByDefault)>(
         messageTemplate:
-            r"""Binary operator '#string' on '#constant' requires operand of type '#type', but was of type '#type2'.""",
+            r"""Binary operator '#stringOKEmpty' on '#constant' requires operand of type '#type', but was of type '#type2'.""",
         withArguments: _withArgumentsConstEvalInvalidBinaryOperandType);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<
-        Message Function(String string, Constant _constant, DartType _type,
-            DartType _type2, bool isNonNullableByDefault)>
+        Message Function(String stringOKEmpty, Constant _constant,
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
     codeConstEvalInvalidBinaryOperandType = const Code<
-        Message Function(String string, Constant _constant, DartType _type,
-            DartType _type2, bool isNonNullableByDefault)>(
+        Message Function(String stringOKEmpty, Constant _constant,
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>(
   "ConstEvalInvalidBinaryOperandType",
   templateConstEvalInvalidBinaryOperandType,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidBinaryOperandType(
-    String string,
+    String stringOKEmpty,
     Constant _constant,
     DartType _type,
     DartType _type2,
     bool isNonNullableByDefault) {
-  if (string.isEmpty) throw 'No string provided';
+  if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
   List<Object> typeParts = labeler.labelType(_type);
@@ -390,10 +390,10 @@
   String type2 = type2Parts.join();
   return new Message(codeConstEvalInvalidBinaryOperandType,
       message:
-          """Binary operator '${string}' on '${constant}' requires operand of type '${type}', but was of type '${type2}'.""" +
+          """Binary operator '${stringOKEmpty}' on '${constant}' requires operand of type '${type}', but was of type '${type2}'.""" +
               labeler.originMessages,
       arguments: {
-        'string': string,
+        'stringOKEmpty': stringOKEmpty,
         'constant': _constant,
         'type': _type,
         'type2': _type2
@@ -439,21 +439,21 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
-        Message Function(
-            String string, Constant _constant, bool isNonNullableByDefault)>
+        Message Function(String stringOKEmpty, Constant _constant,
+            bool isNonNullableByDefault)>
     templateConstEvalInvalidMethodInvocation = const Template<
-            Message Function(String string, Constant _constant,
+            Message Function(String stringOKEmpty, Constant _constant,
                 bool isNonNullableByDefault)>(
         messageTemplate:
-            r"""The method '#string' can't be invoked on '#constant' in a constant expression.""",
+            r"""The method '#stringOKEmpty' can't be invoked on '#constant' in a constant expression.""",
         withArguments: _withArgumentsConstEvalInvalidMethodInvocation);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<
-        Message Function(
-            String string, Constant _constant, bool isNonNullableByDefault)>
-    codeConstEvalInvalidMethodInvocation = const Code<
-            Message Function(String string, Constant _constant,
+        Message Function(String stringOKEmpty, Constant _constant,
+            bool isNonNullableByDefault)> codeConstEvalInvalidMethodInvocation =
+    const Code<
+            Message Function(String stringOKEmpty, Constant _constant,
                 bool isNonNullableByDefault)>(
         "ConstEvalInvalidMethodInvocation",
         templateConstEvalInvalidMethodInvocation,
@@ -461,51 +461,51 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidMethodInvocation(
-    String string, Constant _constant, bool isNonNullableByDefault) {
-  if (string.isEmpty) throw 'No string provided';
+    String stringOKEmpty, Constant _constant, bool isNonNullableByDefault) {
+  if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
   String constant = constantParts.join();
   return new Message(codeConstEvalInvalidMethodInvocation,
       message:
-          """The method '${string}' can't be invoked on '${constant}' in a constant expression.""" +
+          """The method '${stringOKEmpty}' can't be invoked on '${constant}' in a constant expression.""" +
               labeler.originMessages,
-      arguments: {'string': string, 'constant': _constant});
+      arguments: {'stringOKEmpty': stringOKEmpty, 'constant': _constant});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
-        Message Function(
-            String string, Constant _constant, bool isNonNullableByDefault)>
-    templateConstEvalInvalidPropertyGet = const Template<
-            Message Function(String string, Constant _constant,
+        Message Function(String stringOKEmpty, Constant _constant,
+            bool isNonNullableByDefault)> templateConstEvalInvalidPropertyGet =
+    const Template<
+            Message Function(String stringOKEmpty, Constant _constant,
                 bool isNonNullableByDefault)>(
         messageTemplate:
-            r"""The property '#string' can't be accessed on '#constant' in a constant expression.""",
+            r"""The property '#stringOKEmpty' can't be accessed on '#constant' in a constant expression.""",
         withArguments: _withArgumentsConstEvalInvalidPropertyGet);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<
-        Message Function(
-            String string, Constant _constant, bool isNonNullableByDefault)>
-    codeConstEvalInvalidPropertyGet = const Code<
-            Message Function(String string, Constant _constant,
+        Message Function(String stringOKEmpty, Constant _constant,
+            bool isNonNullableByDefault)> codeConstEvalInvalidPropertyGet =
+    const Code<
+            Message Function(String stringOKEmpty, Constant _constant,
                 bool isNonNullableByDefault)>(
         "ConstEvalInvalidPropertyGet", templateConstEvalInvalidPropertyGet,
         analyzerCodes: <String>["CONST_EVAL_THROWS_EXCEPTION"]);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsConstEvalInvalidPropertyGet(
-    String string, Constant _constant, bool isNonNullableByDefault) {
-  if (string.isEmpty) throw 'No string provided';
+    String stringOKEmpty, Constant _constant, bool isNonNullableByDefault) {
+  if (stringOKEmpty == null || stringOKEmpty.isEmpty) stringOKEmpty = '(empty)';
   TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
   List<Object> constantParts = labeler.labelConstant(_constant);
   String constant = constantParts.join();
   return new Message(codeConstEvalInvalidPropertyGet,
       message:
-          """The property '${string}' can't be accessed on '${constant}' in a constant expression.""" +
+          """The property '${stringOKEmpty}' can't be accessed on '${constant}' in a constant expression.""" +
               labeler.originMessages,
-      arguments: {'string': string, 'constant': _constant});
+      arguments: {'stringOKEmpty': stringOKEmpty, 'constant': _constant});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2042,6 +2042,690 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterType = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the getter '#name' is not a subtype of the type '#type2' of the setter '#name2'.""",
+        withArguments: _withArgumentsInvalidGetterSetterType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+    Message Function(DartType _type, String name, DartType _type2, String name2,
+        bool isNonNullableByDefault)> codeInvalidGetterSetterType = const Code<
+    Message Function(DartType _type, String name, DartType _type2, String name2,
+        bool isNonNullableByDefault)>(
+  "InvalidGetterSetterType",
+  templateInvalidGetterSetterType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterType(DartType _type, String name,
+    DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterType,
+      message:
+          """The type '${type}' of the getter '${name}' is not a subtype of the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeBothInheritedField = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited field '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeBothInheritedField);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeBothInheritedField = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeBothInheritedField",
+  templateInvalidGetterSetterTypeBothInheritedField,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeBothInheritedField(DartType _type,
+    String name, DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeBothInheritedField,
+      message:
+          """The type '${type}' of the inherited field '${name}' is not a subtype of the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeBothInheritedFieldLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited field '#name' is not assignable to the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeBothInheritedFieldLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeBothInheritedFieldLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeBothInheritedFieldLegacy",
+  templateInvalidGetterSetterTypeBothInheritedFieldLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeBothInheritedFieldLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeBothInheritedFieldLegacy,
+      message:
+          """The type '${type}' of the inherited field '${name}' is not assignable to the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeBothInheritedGetter = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited getter '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeBothInheritedGetter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeBothInheritedGetter = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeBothInheritedGetter",
+  templateInvalidGetterSetterTypeBothInheritedGetter,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeBothInheritedGetter(DartType _type,
+    String name, DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeBothInheritedGetter,
+      message:
+          """The type '${type}' of the inherited getter '${name}' is not a subtype of the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeBothInheritedGetterLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited getter '#name' is not assignable to the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeBothInheritedGetterLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeBothInheritedGetterLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeBothInheritedGetterLegacy",
+  templateInvalidGetterSetterTypeBothInheritedGetterLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeBothInheritedGetterLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeBothInheritedGetterLegacy,
+      message:
+          """The type '${type}' of the inherited getter '${name}' is not assignable to the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeFieldInherited = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited field '#name' is not a subtype of the type '#type2' of the setter '#name2'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeFieldInherited);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeFieldInherited = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeFieldInherited",
+  templateInvalidGetterSetterTypeFieldInherited,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeFieldInherited(DartType _type,
+    String name, DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeFieldInherited,
+      message:
+          """The type '${type}' of the inherited field '${name}' is not a subtype of the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeFieldInheritedLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited field '#name' is not assignable to the type '#type2' of the setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeFieldInheritedLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeFieldInheritedLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeFieldInheritedLegacy",
+  templateInvalidGetterSetterTypeFieldInheritedLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeFieldInheritedLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeFieldInheritedLegacy,
+      message:
+          """The type '${type}' of the inherited field '${name}' is not assignable to the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeGetterInherited = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited getter '#name' is not a subtype of the type '#type2' of the setter '#name2'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeGetterInherited);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeGetterInherited = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeGetterInherited",
+  templateInvalidGetterSetterTypeGetterInherited,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeGetterInherited(DartType _type,
+    String name, DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeGetterInherited,
+      message:
+          """The type '${type}' of the inherited getter '${name}' is not a subtype of the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeGetterInheritedLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the inherited getter '#name' is not assignable to the type '#type2' of the setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeGetterInheritedLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeGetterInheritedLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeGetterInheritedLegacy",
+  templateInvalidGetterSetterTypeGetterInheritedLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeGetterInheritedLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeGetterInheritedLegacy,
+      message:
+          """The type '${type}' of the inherited getter '${name}' is not assignable to the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the getter '#name' is not assignable to the type '#type2' of the setter '#name2'.""",
+        withArguments: _withArgumentsInvalidGetterSetterTypeLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeLegacy",
+  templateInvalidGetterSetterTypeLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeLegacy(DartType _type, String name,
+    DartType _type2, String name2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeLegacy,
+      message:
+          """The type '${type}' of the getter '${name}' is not assignable to the type '${type2}' of the setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeSetterInheritedField = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the field '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeSetterInheritedField);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeSetterInheritedField = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeSetterInheritedField",
+  templateInvalidGetterSetterTypeSetterInheritedField,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeSetterInheritedField(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeSetterInheritedField,
+      message:
+          """The type '${type}' of the field '${name}' is not a subtype of the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeSetterInheritedFieldLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the field '#name' is not assignable to the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeSetterInheritedFieldLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeSetterInheritedFieldLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeSetterInheritedFieldLegacy",
+  templateInvalidGetterSetterTypeSetterInheritedFieldLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeSetterInheritedFieldLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeSetterInheritedFieldLegacy,
+      message:
+          """The type '${type}' of the field '${name}' is not assignable to the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeSetterInheritedGetter = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the getter '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeSetterInheritedGetter);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeSetterInheritedGetter = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeSetterInheritedGetter",
+  templateInvalidGetterSetterTypeSetterInheritedGetter,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeSetterInheritedGetter(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeSetterInheritedGetter,
+      message:
+          """The type '${type}' of the getter '${name}' is not a subtype of the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    templateInvalidGetterSetterTypeSetterInheritedGetterLegacy = const Template<
+            Message Function(DartType _type, String name, DartType _type2,
+                String name2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the getter '#name' is not assignable to the type '#type2' of the inherited setter '#name2'.""",
+        withArguments:
+            _withArgumentsInvalidGetterSetterTypeSetterInheritedGetterLegacy);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>
+    codeInvalidGetterSetterTypeSetterInheritedGetterLegacy = const Code<
+        Message Function(DartType _type, String name, DartType _type2,
+            String name2, bool isNonNullableByDefault)>(
+  "InvalidGetterSetterTypeSetterInheritedGetterLegacy",
+  templateInvalidGetterSetterTypeSetterInheritedGetterLegacy,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidGetterSetterTypeSetterInheritedGetterLegacy(
+    DartType _type,
+    String name,
+    DartType _type2,
+    String name2,
+    bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  if (name2.isEmpty) throw 'No name provided';
+  name2 = demangleMixinApplicationName(name2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidGetterSetterTypeSetterInheritedGetterLegacy,
+      message:
+          """The type '${type}' of the getter '${name}' is not assignable to the type '${type2}' of the inherited setter '${name2}'.""" +
+              labeler.originMessages,
+      arguments: {
+        'type': _type,
+        'name': name,
+        'type2': _type2,
+        'name2': name2
+      });
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
     Message Function(
         DartType _type,
         DartType _type2,
@@ -2120,6 +2804,80 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
+    templateMainWrongParameterType = const Template<
+            Message Function(
+                DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the first parameter of the 'main' method is not a supertype of '#type2'.""",
+        withArguments: _withArgumentsMainWrongParameterType);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
+    codeMainWrongParameterType = const Code<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+  "MainWrongParameterType",
+  templateMainWrongParameterType,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMainWrongParameterType(
+    DartType _type, DartType _type2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeMainWrongParameterType,
+      message:
+          """The type '${type}' of the first parameter of the 'main' method is not a supertype of '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
+    templateMainWrongParameterTypeExported = const Template<
+            Message Function(
+                DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+        messageTemplate:
+            r"""The type '#type' of the first parameter of the exported 'main' method is not a supertype of '#type2'.""",
+        withArguments: _withArgumentsMainWrongParameterTypeExported);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>
+    codeMainWrongParameterTypeExported = const Code<
+        Message Function(
+            DartType _type, DartType _type2, bool isNonNullableByDefault)>(
+  "MainWrongParameterTypeExported",
+  templateMainWrongParameterTypeExported,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsMainWrongParameterTypeExported(
+    DartType _type, DartType _type2, bool isNonNullableByDefault) {
+  TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeMainWrongParameterTypeExported,
+      message:
+          """The type '${type}' of the first parameter of the exported 'main' method is not a supertype of '${type2}'.""" +
+              labeler.originMessages,
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
         Message Function(DartType _type, DartType _type2, DartType _type3,
             bool isNonNullableByDefault)>
     templateMixinApplicationIncompatibleSupertype = const Template<
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 2c22a93..2cfabbe 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -13,6 +13,7 @@
         CanonicalNameError,
         CanonicalNameSdkError,
         CompilationModeError,
+        InvalidKernelSdkVersionError,
         InvalidKernelVersionError,
         SubComponentView;
 
@@ -125,7 +126,7 @@
   final CompilerContext context;
 
   final Ticker ticker;
-
+  final bool resetTicker;
   final bool outlineOnly;
   bool trackNeededDillLibraries = false;
   Set<Library> neededDillLibraries;
@@ -160,6 +161,7 @@
       this.context, this.componentToInitializeFrom,
       [bool outlineOnly, this.incrementalSerializer])
       : ticker = context.options.ticker,
+        resetTicker = true,
         initializeFromDillUri = null,
         this.outlineOnly = outlineOnly ?? false,
         this.initializedForExpressionCompilationOnly = false {
@@ -171,6 +173,7 @@
       bool outlineOnly,
       this.incrementalSerializer])
       : ticker = context.options.ticker,
+        resetTicker = true,
         componentToInitializeFrom = null,
         this.outlineOnly = outlineOnly ?? false,
         this.initializedForExpressionCompilationOnly = false {
@@ -178,8 +181,10 @@
   }
 
   IncrementalCompiler.forExpressionCompilationOnly(
-      this.context, this.componentToInitializeFrom)
+      this.context, this.componentToInitializeFrom,
+      [bool resetTicker])
       : ticker = context.options.ticker,
+        this.resetTicker = resetTicker ?? true,
         initializeFromDillUri = null,
         this.outlineOnly = false,
         this.incrementalSerializer = null,
@@ -201,7 +206,9 @@
   @override
   Future<Component> computeDelta(
       {List<Uri> entryPoints, bool fullComponent: false}) async {
-    ticker.reset();
+    if (resetTicker) {
+      ticker.reset();
+    }
     entryPoints ??= context.options.inputs;
     return context.runInContext<Component>((CompilerContext c) async {
       if (computeDeltaRunOnce && initializedForExpressionCompilationOnly) {
@@ -1008,6 +1015,7 @@
             bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
 
             if (e is InvalidKernelVersionError ||
+                e is InvalidKernelSdkVersionError ||
                 e is PackageChangedError ||
                 e is CanonicalNameSdkError ||
                 e is CompilationModeError) {
@@ -1570,6 +1578,7 @@
     return await context.runInContext((_) async {
       LibraryBuilder libraryBuilder =
           userCode.loader.read(libraryUri, -1, accessor: userCode.loader.first);
+      ticker.logMs("Loaded library $libraryUri");
 
       Class cls;
       if (className != null) {
@@ -1597,6 +1606,7 @@
         nameOrigin: libraryBuilder.library,
       );
       debugLibrary.setLanguageVersion(libraryBuilder.library.languageVersion);
+      ticker.logMs("Created debug library");
 
       if (libraryBuilder is DillLibraryBuilder) {
         for (LibraryDependency dependency
@@ -1629,6 +1639,7 @@
         }
 
         debugLibrary.addImportsToScope();
+        ticker.logMs("Added imports");
       }
 
       HybridFileSystem hfs = userCode.fileSystem;
@@ -1662,6 +1673,7 @@
       // Make sure the library has a canonical name.
       Component c = new Component(libraries: [debugLibrary.library]);
       c.computeCanonicalNames();
+      ticker.logMs("Built debug library");
 
       userCode.runProcedureTransformations(procedure);
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index f643d50..73e6525 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -1181,7 +1181,7 @@
       Member resolvedTarget = redirectionTarget?.target;
 
       if (resolvedTarget == null) {
-        String name = constructorNameForDiagnostics(initialTarget.name.name,
+        String name = constructorNameForDiagnostics(initialTarget.name.text,
             className: initialTarget.enclosingClass.name);
         // TODO(dmitryas): Report this error earlier.
         replacementNode = buildProblem(
@@ -1470,7 +1470,7 @@
                   builder.charOffset, const <TypeParameter>[]) !=
               null) {
         String superclass = classBuilder.supertypeBuilder.fullNameForErrors;
-        int length = constructor.name.name.length;
+        int length = constructor.name.text.length;
         if (length == 0) {
           length = (constructor.parent as Class).name.length;
         }
@@ -1773,6 +1773,7 @@
     }
   }
 
+  /// Handle `a && b` and `a || b`.
   void doLogicalExpression(Token token) {
     Expression argument = popForValue();
     Expression receiver = pop();
@@ -1847,7 +1848,7 @@
             .withArguments(candidate.enclosingClass.name);
       } else {
         if (candidate is Constructor) {
-          if (candidate.name.name == '') {
+          if (candidate.name.text == '') {
             length = candidate.enclosingClass.name.length;
           } else {
             // Assume no spaces around the dot. Not perfect, but probably the
@@ -1887,10 +1888,10 @@
       bool reportWarning: true,
       List<LocatedMessage> context}) {
     Message message = isSuper
-        ? fasta.templateSuperclassHasNoGetter.withArguments(name.name)
-        : fasta.templateGetterNotFound.withArguments(name.name);
+        ? fasta.templateSuperclassHasNoGetter.withArguments(name.text)
+        : fasta.templateGetterNotFound.withArguments(name.text);
     if (reportWarning) {
-      addProblemErrorIfConst(message, charOffset, name.name.length,
+      addProblemErrorIfConst(message, charOffset, name.text.length,
           context: context);
     }
     return message;
@@ -1902,10 +1903,10 @@
       bool reportWarning: true,
       List<LocatedMessage> context}) {
     Message message = isSuper
-        ? fasta.templateSuperclassHasNoSetter.withArguments(name.name)
-        : fasta.templateSetterNotFound.withArguments(name.name);
+        ? fasta.templateSuperclassHasNoSetter.withArguments(name.text)
+        : fasta.templateSetterNotFound.withArguments(name.text);
     if (reportWarning) {
-      addProblemErrorIfConst(message, charOffset, name.name.length,
+      addProblemErrorIfConst(message, charOffset, name.text.length,
           context: context);
     }
     return message;
@@ -1916,7 +1917,7 @@
       {bool isSuper: false,
       bool reportWarning: true,
       List<LocatedMessage> context}) {
-    String plainName = name.name;
+    String plainName = name.text;
     int dotIndex = plainName.lastIndexOf(".");
     if (dotIndex != -1) {
       plainName = plainName.substring(dotIndex + 1);
@@ -1928,8 +1929,8 @@
       length = 1;
     }
     Message message = isSuper
-        ? fasta.templateSuperclassHasNoMethod.withArguments(name.name)
-        : fasta.templateMethodNotFound.withArguments(name.name);
+        ? fasta.templateSuperclassHasNoMethod.withArguments(name.text)
+        : fasta.templateMethodNotFound.withArguments(name.text);
     if (reportWarning) {
       addProblemErrorIfConst(message, charOffset, length, context: context);
     }
@@ -2394,10 +2395,31 @@
   }
 
   @override
+  void beginVariableInitializer(Token token) {
+    if ((currentLocalVariableModifiers & lateMask) != 0) {
+      // This is matched by the call to [endNode] in [endVariableInitializer].
+      typeInferrer?.assignedVariables?.beginNode();
+    }
+  }
+
+  @override
   void endVariableInitializer(Token assignmentOperator) {
     debugEvent("VariableInitializer");
     assert(assignmentOperator.stringValue == "=");
-    pushNewLocalVariable(popForValue(), equalsToken: assignmentOperator);
+    AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesInfo;
+    bool isLate = (currentLocalVariableModifiers & lateMask) != 0;
+    Expression initializer = popForValue();
+    if (isLate) {
+      assignedVariablesInfo = typeInferrer?.assignedVariables
+          ?.deferNode(isClosureOrLateVariableInitializer: true);
+    }
+    pushNewLocalVariable(initializer, equalsToken: assignmentOperator);
+    if (isLate) {
+      VariableDeclaration node = peek();
+      // This is matched by the call to [beginNode] in
+      // [beginVariableInitializer].
+      typeInferrer?.assignedVariables?.storeInfo(node, assignedVariablesInfo);
+    }
   }
 
   @override
@@ -2419,7 +2441,9 @@
                   .withArguments(token.lexeme),
               token.charOffset,
               token.length);
-        } else if (isFinal && !isLate) {
+        } else if (!libraryBuilder.isNonNullableByDefault &&
+            isFinal &&
+            !isLate) {
           initializer = buildProblem(
               fasta.templateFinalFieldWithoutInitializer
                   .withArguments(token.lexeme),
@@ -2453,7 +2477,10 @@
         isConst: isConst,
         isLate: isLate,
         isRequired: isRequired,
-        hasDeclaredInitializer: initializer != null)
+        hasDeclaredInitializer: initializer != null,
+        isStaticLate: libraryBuilder.isNonNullableByDefault &&
+            isFinal &&
+            initializer == null)
       ..fileOffset = identifier.charOffset
       ..fileEqualsOffset = offsetForToken(equalsToken);
     typeInferrer?.assignedVariables?.declare(variable);
@@ -2726,7 +2753,14 @@
   @override
   void handleForInitializerLocalVariableDeclaration(Token token, bool forIn) {
     debugEvent("ForInitializerLocalVariableDeclaration");
-    if (!forIn) {
+    if (forIn) {
+      // If the declaration is of the form `for (final x in ...)`, then we may
+      // have erroneously set the `isStaticLate` flag, so un-set it.
+      Object declaration = peek();
+      if (declaration is VariableDeclarationImpl) {
+        declaration.isStaticLate = false;
+      }
+    } else {
       // This is matched by the call to [deferNode] in [endForStatement] or
       // [endForControlFlow].
       typeInferrer?.assignedVariables?.beginNode();
@@ -2772,7 +2806,7 @@
     // [handleForInitializerExpressionStatement], and
     // [handleForInitializerLocalVariableDeclaration].
     AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
-        typeInferrer?.assignedVariables?.deferNode();
+        typeInferrer?.assignedVariables?.popNode();
 
     Object variableOrExpression = pop();
     exitLocalScope();
@@ -2780,6 +2814,7 @@
     transformCollections = true;
     List<VariableDeclaration> variables =
         _buildForLoopVariableDeclarations(variableOrExpression);
+    typeInferrer?.assignedVariables?.pushNode(assignedVariablesNodeInfo);
     Expression condition;
     if (conditionStatement is ExpressionStatement) {
       condition = conditionStatement.expression;
@@ -2789,14 +2824,12 @@
     if (entry is MapEntry) {
       ForMapEntry result = forest.createForMapEntry(
           offsetForToken(forToken), variables, condition, updates, entry);
-      typeInferrer?.assignedVariables
-          ?.storeInfo(result, assignedVariablesNodeInfo);
+      typeInferrer?.assignedVariables?.endNode(result);
       push(result);
     } else {
       ForElement result = forest.createForElement(offsetForToken(forToken),
           variables, condition, updates, toValue(entry));
-      typeInferrer?.assignedVariables
-          ?.storeInfo(result, assignedVariablesNodeInfo);
+      typeInferrer?.assignedVariables?.endNode(result);
       push(result);
     }
   }
@@ -3989,7 +4022,7 @@
         target.function, arguments, charOffset, typeParameters);
     if (argMessage != null) {
       return throwNoSuchMethodError(forest.createNullLiteral(charOffset),
-          target.name.name, arguments, charOffset,
+          target.name.text, arguments, charOffset,
           candidate: target, message: argMessage);
     }
 
@@ -4064,7 +4097,7 @@
         target.function, arguments, fileOffset, typeParameters);
     if (argMessage != null) {
       return throwNoSuchMethodError(forest.createNullLiteral(fileOffset),
-          target.name.name, arguments, fileOffset,
+          target.name.text, arguments, fileOffset,
           candidate: target, message: argMessage);
     }
 
@@ -4557,6 +4590,11 @@
 
   @override
   void handleElseControlFlow(Token elseToken) {
+    // Resolve the top of the stack so that if it's a delayed assignment it
+    // happens before we go into the else block.
+    Object node = pop();
+    if (node is! MapEntry) node = toValue(node);
+    push(node);
     typePromoter?.enterElse();
   }
 
@@ -4566,8 +4604,6 @@
     Object entry = pop();
     Object condition = pop(); // parenthesized expression
     Token ifToken = pop();
-    typePromoter?.enterElse();
-    typePromoter?.exitConditional();
 
     transformCollections = true;
     if (entry is MapEntry) {
@@ -4577,6 +4613,8 @@
       push(forest.createIfElement(
           offsetForToken(ifToken), toValue(condition), toValue(entry)));
     }
+    typePromoter?.enterElse();
+    typePromoter?.exitConditional();
   }
 
   @override
@@ -4835,8 +4873,8 @@
           ..fileOffset = formals.charOffset;
         exitLocalScope();
         // This is matched by the call to [beginNode] in [enterFunction].
-        typeInferrer?.assignedVariables
-            ?.endNode(variable.initializer, isClosure: true);
+        typeInferrer?.assignedVariables?.endNode(variable.initializer,
+            isClosureOrLateVariableInitializer: true);
         Expression expression = new NamedFunctionExpressionJudgment(variable);
         if (oldInitializer != null) {
           // This must have been a compile-time error.
@@ -4867,7 +4905,8 @@
           push(declaration);
         }
         // This is matched by the call to [beginNode] in [enterFunction].
-        typeInferrer?.assignedVariables?.endNode(declaration, isClosure: true);
+        typeInferrer?.assignedVariables
+            ?.endNode(declaration, isClosureOrLateVariableInitializer: true);
       }
     } else {
       return unhandled("${declaration.runtimeType}", "pushNamedFunction",
@@ -4916,7 +4955,8 @@
     }
     push(result);
     // This is matched by the call to [beginNode] in [enterFunction].
-    typeInferrer?.assignedVariables?.endNode(result, isClosure: true);
+    typeInferrer?.assignedVariables
+        ?.endNode(result, isClosureOrLateVariableInitializer: true);
   }
 
   @override
@@ -5005,7 +5045,7 @@
 
     // This is matched by the call to [beginNode] in [handleForInLoopParts].
     AssignedVariablesNodeInfo<VariableDeclaration> assignedVariablesNodeInfo =
-        typeInferrer?.assignedVariables?.deferNode();
+        typeInferrer?.assignedVariables?.popNode();
 
     Expression iterable = popForValue();
     Object lvalue = pop(); // lvalue
@@ -5014,6 +5054,7 @@
     transformCollections = true;
     ForInElements elements =
         _computeForInElements(forToken, inToken, lvalue, null);
+    typeInferrer?.assignedVariables?.pushNode(assignedVariablesNodeInfo);
     VariableDeclaration variable = elements.variable;
     Expression problem = elements.expressionProblem;
     if (entry is MapEntry) {
@@ -5026,8 +5067,7 @@
           entry,
           problem,
           isAsync: awaitToken != null);
-      typeInferrer?.assignedVariables
-          ?.storeInfo(result, assignedVariablesNodeInfo);
+      typeInferrer?.assignedVariables?.endNode(result);
       push(result);
     } else {
       ForInElement result = forest.createForInElement(
@@ -5039,8 +5079,7 @@
           toValue(entry),
           problem,
           isAsync: awaitToken != null);
-      typeInferrer?.assignedVariables
-          ?.storeInfo(result, assignedVariablesNodeInfo);
+      typeInferrer?.assignedVariables?.endNode(result);
       push(result);
     }
   }
@@ -5053,7 +5092,6 @@
       // reported by the parser.
       lvalue.isLate = false;
       elements.explicitVariableDeclaration = lvalue;
-      typeInferrer?.assignedVariables?.write(lvalue);
       if (lvalue.isConst) {
         elements.expressionProblem = buildProblem(
             fasta.messageForInLoopWithConstVariable,
@@ -5980,7 +6018,7 @@
       [int charOffset = -1]) {
     if (member.isConst && !constructor.isConst) {
       addProblem(fasta.messageConstConstructorWithNonConstSuper, charOffset,
-          constructor.name.name.length);
+          constructor.name.text.length);
     }
     needsImplicitSuperInitializer = false;
     return new SuperInitializer(constructor, arguments)
@@ -5993,8 +6031,8 @@
       Constructor constructor, Arguments arguments,
       [int charOffset = -1]) {
     if (classBuilder.checkConstructorCyclic(
-        member.name, constructor.name.name)) {
-      int length = constructor.name.name.length;
+        member.name, constructor.name.text)) {
+      int length = constructor.name.text.length;
       if (length == 0) length = "this".length;
       addProblem(fasta.messageConstructorCyclic, charOffset, length);
       // TODO(askesc): Produce invalid initializer.
@@ -6147,7 +6185,7 @@
           fasta.templateNotConstantExpression
               .withArguments('Method invocation'),
           offset,
-          name.name.length);
+          name.text.length);
     }
     if (isSuper) {
       // We can ignore [isNullAware] on super sends.
@@ -6161,9 +6199,9 @@
           target = null;
           addProblemErrorIfConst(
               fasta.templateSuperclassMethodArgumentMismatch
-                  .withArguments(name.name),
+                  .withArguments(name.text),
               offset,
-              name.name.length);
+              name.text.length);
         }
         return new SuperMethodInvocation(name, arguments, target)
           ..fileOffset = offset;
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 29e6bd3..7b8b992 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -43,14 +43,16 @@
         Message,
         messageDeclaredMemberConflictsWithInheritedMember,
         messageDeclaredMemberConflictsWithInheritedMemberCause,
-        messageDeclaredMemberConflictsWithInheritedMembersCause,
+        messageDeclaredMemberConflictsWithOverriddenMembersCause,
         messageInheritedMembersConflict,
         messageInheritedMembersConflictCause1,
         messageInheritedMembersConflictCause2,
         messageStaticAndInstanceConflict,
         messageStaticAndInstanceConflictCause,
         templateCantInferReturnTypeDueToInconsistentOverrides,
+        templateCantInferReturnTypeDueToNoCombinedSignature,
         templateCantInferTypeDueToInconsistentOverrides,
+        templateCantInferTypeDueToNoCombinedSignature,
         templateCombinedMemberSignatureFailed,
         templateDuplicatedDeclaration,
         templateDuplicatedDeclarationCause,
@@ -64,6 +66,7 @@
 
 import '../scope.dart' show Scope;
 
+import '../source/source_class_builder.dart';
 import '../source/source_library_builder.dart' show SourceLibraryBuilder;
 
 import '../source/source_loader.dart' show SourceLoader;
@@ -238,7 +241,10 @@
   bool operator ==(Object other);
 
   void inferType(ClassHierarchyBuilder hierarchy);
-  void registerOverrideDependency(ClassMember overriddenMember);
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers);
+
+  /// Returns `true` if this has the same underlying declaration as [other].
+  bool isSameDeclaration(ClassMember other);
 }
 
 bool hasSameSignature(FunctionNode a, FunctionNode b) {
@@ -325,9 +331,9 @@
   final List<DelayedTypeComputation> _delayedTypeComputations =
       <DelayedTypeComputation>[];
 
-  final List<DelayedOverrideCheck> _overrideChecks = <DelayedOverrideCheck>[];
+  final List<DelayedCheck> _delayedChecks = <DelayedCheck>[];
 
-  final List<ClassMember> _delayedMemberChecks = <ClassMember>[];
+  final List<ClassMember> _delayedMemberComputations = <ClassMember>[];
 
   final CoreTypes coreTypes;
 
@@ -344,9 +350,9 @@
   void clear() {
     nodes.clear();
     substitutions.clear();
-    _overrideChecks.clear();
+    _delayedChecks.clear();
     _delayedTypeComputations.clear();
-    _delayedMemberChecks.clear();
+    _delayedMemberComputations.clear();
   }
 
   void registerDelayedTypeComputation(DelayedTypeComputation computation) {
@@ -354,12 +360,18 @@
   }
 
   void registerOverrideCheck(
-      ClassBuilder classBuilder, ClassMember a, ClassMember b) {
-    _overrideChecks.add(new DelayedOverrideCheck(classBuilder, a, b));
+      SourceClassBuilder classBuilder, ClassMember a, ClassMember b) {
+    _delayedChecks.add(new DelayedOverrideCheck(classBuilder, a, b));
   }
 
-  void registerMemberCheck(ClassMember member) {
-    _delayedMemberChecks.add(member);
+  void registerGetterSetterCheck(
+      SourceClassBuilder classBuilder, ClassMember getter, ClassMember setter) {
+    _delayedChecks
+        .add(new DelayedGetterSetterCheck(classBuilder, getter, setter));
+  }
+
+  void registerMemberComputation(ClassMember member) {
+    _delayedMemberComputations.add(member);
   }
 
   List<DelayedTypeComputation> takeDelayedTypeComputations() {
@@ -368,15 +380,15 @@
     return list;
   }
 
-  List<DelayedOverrideCheck> takeDelayedOverrideChecks() {
-    List<DelayedOverrideCheck> list = _overrideChecks.toList();
-    _overrideChecks.clear();
+  List<DelayedCheck> takeDelayedChecks() {
+    List<DelayedCheck> list = _delayedChecks.toList();
+    _delayedChecks.clear();
     return list;
   }
 
-  List<ClassMember> takeDelayedMemberChecks() {
-    List<ClassMember> list = _delayedMemberChecks.toList();
-    _delayedMemberChecks.clear();
+  List<ClassMember> takeDelayedMemberComputations() {
+    List<ClassMember> list = _delayedMemberComputations.toList();
+    _delayedMemberComputations.clear();
     return list;
   }
 
@@ -580,9 +592,9 @@
     if (declaration?.isStatic ?? true) return null;
     if (declaration.isDuplicate) {
       library?.addProblem(
-          templateDuplicatedDeclarationUse.withArguments(name.name),
+          templateDuplicatedDeclarationUse.withArguments(name.text),
           charOffset,
-          name.name.length,
+          name.text.length,
           library.fileUri);
       return null;
     }
@@ -670,165 +682,163 @@
       DartType inferredReturnType;
       Map<FormalParameterBuilder, DartType> inferredParameterTypes = {};
 
-      for (ClassMember classMember
-          in toSet(declaredMember.classBuilder, overriddenMembers)) {
-        Member overriddenMember = classMember.getMember(hierarchy);
-        Substitution classSubstitution;
-        if (classBuilder.cls != overriddenMember.enclosingClass) {
-          assert(
-              substitutions.containsKey(overriddenMember.enclosingClass),
-              "No substitution found for '${classBuilder.fullNameForErrors}' "
-              "as instance of '${overriddenMember.enclosingClass.name}'. "
-              "Substitutions available for: ${substitutions.keys}");
-          classSubstitution = substitutions[overriddenMember.enclosingClass];
-          debug?.log("${classBuilder.fullNameForErrors} -> "
-              "${overriddenMember.enclosingClass.name} $classSubstitution");
-        }
-        if (overriddenMember is! Procedure) {
-          debug?.log("Giving up 1");
-          continue;
-        }
-        Procedure overriddenProcedure = overriddenMember;
-        FunctionNode overriddenFunction = overriddenProcedure.function;
-
-        List<TypeParameter> overriddenTypeParameters =
-            overriddenFunction.typeParameters;
-        int typeParameterCount = declaredTypeParameters.length;
-        if (typeParameterCount != overriddenTypeParameters.length) {
-          debug?.log("Giving up 2");
-          continue;
-        }
-        Substitution methodSubstitution;
-        if (typeParameterCount != 0) {
-          List<DartType> types = new List<DartType>(typeParameterCount);
-          for (int i = 0; i < typeParameterCount; i++) {
-            types[i] = new TypeParameterType.forAlphaRenaming(
-                overriddenTypeParameters[i], declaredTypeParameters[i]);
-          }
-          methodSubstitution =
-              Substitution.fromPairs(overriddenTypeParameters, types);
-          for (int i = 0; i < typeParameterCount; i++) {
-            DartType declaredBound = declaredTypeParameters[i].bound;
-            DartType overriddenBound = methodSubstitution
-                .substituteType(overriddenTypeParameters[i].bound);
-            if (!hierarchy.types
-                .performNullabilityAwareMutualSubtypesCheck(
-                    declaredBound, overriddenBound)
-                .isSubtypeWhenUsingNullabilities()) {
-              debug?.log("Giving up 3");
-              continue;
-            }
-          }
-        }
-
-        DartType inheritedReturnType = overriddenFunction.returnType;
-        if (classSubstitution != null) {
-          inheritedReturnType =
-              classSubstitution.substituteType(inheritedReturnType);
-        }
-        if (methodSubstitution != null) {
-          inheritedReturnType =
-              methodSubstitution.substituteType(inheritedReturnType);
-        }
-        if (declaredMember.returnType == null &&
-            inferredReturnType is! InvalidType) {
-          inferredReturnType = mergeTypeInLibrary(
-              hierarchy, classBuilder, inferredReturnType, inheritedReturnType);
-          if (inferredReturnType == null) {
-            // A different type has already been inferred.
+      Set<ClassMember> overriddenMemberSet =
+          toSet(declaredMember.classBuilder, overriddenMembers);
+      if (classBuilder.library.isNonNullableByDefault) {
+        CombinedMemberSignature combinedMemberSignature =
+            new CombinedMemberSignature(
+                hierarchy, classBuilder, overriddenMemberSet.toList(),
+                forSetter: false);
+        FunctionType combinedMemberSignatureType = combinedMemberSignature
+            .getCombinedSignatureTypeInContext(declaredTypeParameters);
+        if (declaredMember.returnType == null) {
+          if (combinedMemberSignatureType == null) {
             inferredReturnType = const InvalidType();
             reportCantInferReturnType(
                 classBuilder, declaredMember, hierarchy, overriddenMembers);
+          } else {
+            inferredReturnType = combinedMemberSignatureType.returnType;
           }
         }
-        if (declaredFunction.requiredParameterCount >
-            overriddenFunction.requiredParameterCount) {
-          debug?.log("Giving up 4");
-          continue;
-        }
-        List<VariableDeclaration> overriddenPositional =
-            overriddenFunction.positionalParameters;
-        if (declaredPositional.length < overriddenPositional.length) {
-          debug?.log("Giving up 5");
-          continue;
-        }
-
-        for (int i = 0; i < overriddenPositional.length; i++) {
-          FormalParameterBuilder declaredParameter = declaredMember.formals[i];
-          if (declaredParameter.type != null) continue;
-
-          VariableDeclaration overriddenParameter = overriddenPositional[i];
-          DartType inheritedParameterType = overriddenParameter.type;
-          if (classSubstitution != null) {
-            inheritedParameterType =
-                classSubstitution.substituteType(inheritedParameterType);
-          }
-          if (methodSubstitution != null) {
-            inheritedParameterType =
-                methodSubstitution.substituteType(inheritedParameterType);
-          }
-          if (hierarchy.coreTypes.objectClass.enclosingLibrary
-                  .isNonNullableByDefault &&
-              !declaredMember.classBuilder.library.isNonNullableByDefault &&
-              overriddenProcedure == hierarchy.coreTypes.objectEquals) {
-            // In legacy code we special case `Object.==` to infer `dynamic`
-            // instead `Object!`.
-            inheritedParameterType = const DynamicType();
-          }
-          DartType inferredParameterType =
-              inferredParameterTypes[declaredParameter];
-          inferredParameterType = mergeTypeInLibrary(hierarchy, classBuilder,
-              inferredParameterType, inheritedParameterType);
-          if (inferredParameterType == null) {
-            // A different type has already been inferred.
-            inferredParameterType = const InvalidType();
-            reportCantInferParameterType(
-                classBuilder, declaredParameter, hierarchy, overriddenMembers);
-          }
-          inferredParameterTypes[declaredParameter] = inferredParameterType;
-        }
-
-        List<VariableDeclaration> overriddenNamed =
-            overriddenFunction.namedParameters;
-        named:
-        if (declaredNamed.isNotEmpty || overriddenNamed.isNotEmpty) {
-          if (declaredPositional.length != overriddenPositional.length) {
-            debug?.log("Giving up 9");
-            break named;
-          }
-          if (declaredFunction.requiredParameterCount !=
-              overriddenFunction.requiredParameterCount) {
-            debug?.log("Giving up 10");
-            break named;
-          }
-
-          overriddenNamed = overriddenNamed.toList()
-            ..sort(compareNamedParameters);
-          int declaredIndex = 0;
-          for (int overriddenIndex = 0;
-              overriddenIndex < overriddenNamed.length;
-              overriddenIndex++) {
-            String name = overriddenNamed[overriddenIndex].name;
-            for (; declaredIndex < declaredNamed.length; declaredIndex++) {
-              if (declaredNamed[declaredIndex].name == name) break;
+        if (declaredMember.formals != null) {
+          for (int i = 0; i < declaredPositional.length; i++) {
+            FormalParameterBuilder declaredParameter =
+                declaredMember.formals[i];
+            if (declaredParameter.type != null) {
+              continue;
             }
-            if (declaredIndex == declaredNamed.length) {
-              debug?.log("Giving up 11");
-              break named;
+
+            DartType inferredParameterType;
+            if (combinedMemberSignatureType == null) {
+              inferredParameterType = const InvalidType();
+              reportCantInferParameterType(classBuilder, declaredParameter,
+                  hierarchy, overriddenMembers);
+            } else if (i <
+                combinedMemberSignatureType.positionalParameters.length) {
+              inferredParameterType =
+                  combinedMemberSignatureType.positionalParameters[i];
             }
-            FormalParameterBuilder declaredParameter;
-            for (int i = declaredPositional.length;
-                i < declaredMember.formals.length;
-                ++i) {
-              if (declaredMember.formals[i].name == name) {
-                declaredParameter = declaredMember.formals[i];
-                break;
+            inferredParameterTypes[declaredParameter] = inferredParameterType;
+          }
+
+          Map<String, DartType> namedParameterTypes;
+          for (int i = declaredPositional.length;
+              i < declaredMember.formals.length;
+              i++) {
+            FormalParameterBuilder declaredParameter =
+                declaredMember.formals[i];
+            if (declaredParameter.type != null) {
+              continue;
+            }
+
+            DartType inferredParameterType;
+            if (combinedMemberSignatureType == null) {
+              inferredParameterType = const InvalidType();
+              reportCantInferParameterType(classBuilder, declaredParameter,
+                  hierarchy, overriddenMembers);
+            } else {
+              if (namedParameterTypes == null) {
+                namedParameterTypes = {};
+                for (NamedType namedType
+                    in combinedMemberSignatureType.namedParameters) {
+                  namedParameterTypes[namedType.name] = namedType.type;
+                }
+              }
+              inferredParameterType =
+                  namedParameterTypes[declaredParameter.name];
+            }
+            inferredParameterTypes[declaredParameter] = inferredParameterType;
+          }
+        }
+      } else {
+        for (ClassMember classMember in overriddenMemberSet) {
+          Member overriddenMember = classMember.getMember(hierarchy);
+          Substitution classSubstitution;
+          if (classBuilder.cls != overriddenMember.enclosingClass) {
+            assert(
+                substitutions.containsKey(overriddenMember.enclosingClass),
+                "No substitution found for '${classBuilder.fullNameForErrors}' "
+                "as instance of '${overriddenMember.enclosingClass.name}'. "
+                "Substitutions available for: ${substitutions.keys}");
+            classSubstitution = substitutions[overriddenMember.enclosingClass];
+            debug?.log("${classBuilder.fullNameForErrors} -> "
+                "${overriddenMember.enclosingClass.name} $classSubstitution");
+          }
+          if (overriddenMember is! Procedure) {
+            debug?.log("Giving up 1");
+            continue;
+          }
+          Procedure overriddenProcedure = overriddenMember;
+          FunctionNode overriddenFunction = overriddenProcedure.function;
+
+          List<TypeParameter> overriddenTypeParameters =
+              overriddenFunction.typeParameters;
+          int typeParameterCount = declaredTypeParameters.length;
+          if (typeParameterCount != overriddenTypeParameters.length) {
+            debug?.log("Giving up 2");
+            continue;
+          }
+          Substitution methodSubstitution;
+          if (typeParameterCount != 0) {
+            List<DartType> types = new List<DartType>(typeParameterCount);
+            for (int i = 0; i < typeParameterCount; i++) {
+              types[i] = new TypeParameterType.forAlphaRenaming(
+                  overriddenTypeParameters[i], declaredTypeParameters[i]);
+            }
+            methodSubstitution =
+                Substitution.fromPairs(overriddenTypeParameters, types);
+            for (int i = 0; i < typeParameterCount; i++) {
+              DartType declaredBound = declaredTypeParameters[i].bound;
+              DartType overriddenBound = methodSubstitution
+                  .substituteType(overriddenTypeParameters[i].bound);
+              if (!hierarchy.types
+                  .performNullabilityAwareMutualSubtypesCheck(
+                      declaredBound, overriddenBound)
+                  .isSubtypeWhenUsingNullabilities()) {
+                debug?.log("Giving up 3");
+                continue;
               }
             }
-            if (declaredParameter.type != null) continue;
-            VariableDeclaration overriddenParameter =
-                overriddenNamed[overriddenIndex];
+          }
 
+          DartType inheritedReturnType = overriddenFunction.returnType;
+          if (classSubstitution != null) {
+            inheritedReturnType =
+                classSubstitution.substituteType(inheritedReturnType);
+          }
+          if (methodSubstitution != null) {
+            inheritedReturnType =
+                methodSubstitution.substituteType(inheritedReturnType);
+          }
+          if (declaredMember.returnType == null &&
+              inferredReturnType is! InvalidType) {
+            inferredReturnType = mergeTypeInLibrary(hierarchy, classBuilder,
+                inferredReturnType, inheritedReturnType);
+            if (inferredReturnType == null) {
+              // A different type has already been inferred.
+              inferredReturnType = const InvalidType();
+              reportCantInferReturnType(
+                  classBuilder, declaredMember, hierarchy, overriddenMembers);
+            }
+          }
+          if (declaredFunction.requiredParameterCount >
+              overriddenFunction.requiredParameterCount) {
+            debug?.log("Giving up 4");
+            continue;
+          }
+          List<VariableDeclaration> overriddenPositional =
+              overriddenFunction.positionalParameters;
+          if (declaredPositional.length < overriddenPositional.length) {
+            debug?.log("Giving up 5");
+            continue;
+          }
+
+          for (int i = 0; i < overriddenPositional.length; i++) {
+            FormalParameterBuilder declaredParameter =
+                declaredMember.formals[i];
+            if (declaredParameter.type != null) continue;
+
+            VariableDeclaration overriddenParameter = overriddenPositional[i];
             DartType inheritedParameterType = overriddenParameter.type;
             if (classSubstitution != null) {
               inheritedParameterType =
@@ -838,6 +848,14 @@
               inheritedParameterType =
                   methodSubstitution.substituteType(inheritedParameterType);
             }
+            if (hierarchy.coreTypes.objectClass.enclosingLibrary
+                    .isNonNullableByDefault &&
+                !declaredMember.classBuilder.library.isNonNullableByDefault &&
+                overriddenProcedure == hierarchy.coreTypes.objectEquals) {
+              // In legacy code we special case `Object.==` to infer `dynamic`
+              // instead `Object!`.
+              inheritedParameterType = const DynamicType();
+            }
             DartType inferredParameterType =
                 inferredParameterTypes[declaredParameter];
             inferredParameterType = mergeTypeInLibrary(hierarchy, classBuilder,
@@ -850,6 +868,70 @@
             }
             inferredParameterTypes[declaredParameter] = inferredParameterType;
           }
+
+          List<VariableDeclaration> overriddenNamed =
+              overriddenFunction.namedParameters;
+          named:
+          if (declaredNamed.isNotEmpty || overriddenNamed.isNotEmpty) {
+            if (declaredPositional.length != overriddenPositional.length) {
+              debug?.log("Giving up 9");
+              break named;
+            }
+            if (declaredFunction.requiredParameterCount !=
+                overriddenFunction.requiredParameterCount) {
+              debug?.log("Giving up 10");
+              break named;
+            }
+
+            overriddenNamed = overriddenNamed.toList()
+              ..sort(compareNamedParameters);
+            int declaredIndex = 0;
+            for (int overriddenIndex = 0;
+                overriddenIndex < overriddenNamed.length;
+                overriddenIndex++) {
+              String name = overriddenNamed[overriddenIndex].name;
+              for (; declaredIndex < declaredNamed.length; declaredIndex++) {
+                if (declaredNamed[declaredIndex].name == name) break;
+              }
+              if (declaredIndex == declaredNamed.length) {
+                debug?.log("Giving up 11");
+                break named;
+              }
+              FormalParameterBuilder declaredParameter;
+              for (int i = declaredPositional.length;
+                  i < declaredMember.formals.length;
+                  ++i) {
+                if (declaredMember.formals[i].name == name) {
+                  declaredParameter = declaredMember.formals[i];
+                  break;
+                }
+              }
+              if (declaredParameter.type != null) continue;
+              VariableDeclaration overriddenParameter =
+                  overriddenNamed[overriddenIndex];
+
+              DartType inheritedParameterType = overriddenParameter.type;
+              if (classSubstitution != null) {
+                inheritedParameterType =
+                    classSubstitution.substituteType(inheritedParameterType);
+              }
+              if (methodSubstitution != null) {
+                inheritedParameterType =
+                    methodSubstitution.substituteType(inheritedParameterType);
+              }
+              DartType inferredParameterType =
+                  inferredParameterTypes[declaredParameter];
+              inferredParameterType = mergeTypeInLibrary(hierarchy,
+                  classBuilder, inferredParameterType, inheritedParameterType);
+              if (inferredParameterType == null) {
+                // A different type has already been inferred.
+                inferredParameterType = const InvalidType();
+                reportCantInferParameterType(classBuilder, declaredParameter,
+                    hierarchy, overriddenMembers);
+              }
+              inferredParameterTypes[declaredParameter] = inferredParameterType;
+            }
+          }
         }
       }
       if (declaredMember.returnType == null) {
@@ -1006,69 +1088,115 @@
     if (declaredMember.classBuilder == classBuilder &&
         declaredMember.returnType == null) {
       DartType inferredType;
-
-      void inferFrom(ClassMember classMember) {
-        if (inferredType is InvalidType) return;
-
-        Member overriddenMember = classMember.getMember(hierarchy);
-        Substitution substitution;
-        if (classBuilder.cls != overriddenMember.enclosingClass) {
-          assert(
-              substitutions.containsKey(overriddenMember.enclosingClass),
-              "No substitution found for '${classBuilder.fullNameForErrors}' "
-              "as instance of '${overriddenMember.enclosingClass.name}'. "
-              "Substitutions available for: ${substitutions.keys}");
-          substitution = substitutions[overriddenMember.enclosingClass];
-        }
-        DartType inheritedType;
-        if (overriddenMember is Field) {
-          inheritedType = overriddenMember.type;
-          assert(inheritedType is! ImplicitFieldType);
-        } else if (overriddenMember is Procedure) {
-          if (overriddenMember.kind == ProcedureKind.Setter) {
-            VariableDeclaration bParameter =
-                overriddenMember.function.positionalParameters.single;
-            inheritedType = bParameter.type;
-          } else if (overriddenMember.kind == ProcedureKind.Getter) {
-            inheritedType = overriddenMember.function.returnType;
-          } else {
-            debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
-            return;
-          }
-        } else {
-          debug?.log(
-              "Giving up (not field/procedure: ${overriddenMember.runtimeType})");
-          return;
-        }
-        if (substitution != null) {
-          inheritedType = substitution.substituteType(inheritedType);
-        }
-        inferredType = mergeTypeInLibrary(
-            hierarchy, classBuilder, inferredType, inheritedType);
-
-        if (inferredType == null) {
-          // A different type has already been inferred.
-          inferredType = const InvalidType();
-          reportCantInferReturnType(
-              classBuilder, declaredMember, hierarchy, overriddenMembers);
-        }
-      }
-
       overriddenMembers = toSet(classBuilder, overriddenMembers);
-      // The getter type must be inferred from getters first.
-      for (ClassMember overriddenMember in overriddenMembers) {
-        if (!overriddenMember.forSetter) {
-          inferFrom(overriddenMember);
-        }
-      }
-      if (inferredType == null) {
-        // The getter type must be inferred from setters if no type was
-        // inferred from getters.
+      if (classBuilder.library.isNonNullableByDefault) {
+        List<ClassMember> overriddenGetters = [];
+        List<ClassMember> overriddenSetters = [];
         for (ClassMember overriddenMember in overriddenMembers) {
           if (overriddenMember.forSetter) {
+            overriddenSetters.add(overriddenMember);
+          } else {
+            overriddenGetters.add(overriddenMember);
+          }
+        }
+
+        void inferFrom(List<ClassMember> members, {bool forSetter}) {
+          assert(forSetter != null);
+          CombinedMemberSignature combinedMemberSignature =
+              new CombinedMemberSignature(hierarchy, classBuilder, members,
+                  forSetter: forSetter);
+          DartType combinedMemberSignatureType =
+              combinedMemberSignature.combinedMemberSignatureType;
+          if (combinedMemberSignatureType == null) {
+            inferredType = const InvalidType();
+            reportCantInferReturnType(
+                classBuilder, declaredMember, hierarchy, members);
+          } else {
+            inferredType = combinedMemberSignatureType;
+          }
+        }
+
+        if (overriddenGetters.isNotEmpty) {
+          // 1) The return type of a getter, parameter type of a setter or type
+          // of a field which overrides/implements only one or more getters is
+          // inferred to be the return type of the combined member signature of
+          // said getter in the direct superinterfaces.
+
+          // 2) The return type of a getter which overrides/implements both a
+          // setter and a getter is inferred to be the return type of the
+          // combined member signature of said getter in the direct
+          // superinterfaces.
+          inferFrom(overriddenGetters, forSetter: false);
+        } else {
+          // The return type of a getter, parameter type of a setter or type of
+          // a field which overrides/implements only one or more setters is
+          // inferred to be the parameter type of the combined member signature
+          // of said setter in the direct superinterfaces.
+          inferFrom(overriddenSetters, forSetter: true);
+        }
+      } else {
+        void inferFrom(ClassMember classMember) {
+          if (inferredType is InvalidType) return;
+
+          Member overriddenMember = classMember.getMember(hierarchy);
+          Substitution substitution;
+          if (classBuilder.cls != overriddenMember.enclosingClass) {
+            assert(
+                substitutions.containsKey(overriddenMember.enclosingClass),
+                "No substitution found for '${classBuilder.fullNameForErrors}' "
+                "as instance of '${overriddenMember.enclosingClass.name}'. "
+                "Substitutions available for: ${substitutions.keys}");
+            substitution = substitutions[overriddenMember.enclosingClass];
+          }
+          DartType inheritedType;
+          if (overriddenMember is Field) {
+            inheritedType = overriddenMember.type;
+            assert(inheritedType is! ImplicitFieldType);
+          } else if (overriddenMember is Procedure) {
+            if (overriddenMember.kind == ProcedureKind.Setter) {
+              VariableDeclaration bParameter =
+                  overriddenMember.function.positionalParameters.single;
+              inheritedType = bParameter.type;
+            } else if (overriddenMember.kind == ProcedureKind.Getter) {
+              inheritedType = overriddenMember.function.returnType;
+            } else {
+              debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
+              return;
+            }
+          } else {
+            debug?.log("Giving up (not field/procedure: "
+                "${overriddenMember.runtimeType})");
+            return;
+          }
+          if (substitution != null) {
+            inheritedType = substitution.substituteType(inheritedType);
+          }
+          inferredType = mergeTypeInLibrary(
+              hierarchy, classBuilder, inferredType, inheritedType);
+
+          if (inferredType == null) {
+            // A different type has already been inferred.
+            inferredType = const InvalidType();
+            reportCantInferReturnType(
+                classBuilder, declaredMember, hierarchy, overriddenMembers);
+          }
+        }
+
+        // The getter type must be inferred from getters first.
+        for (ClassMember overriddenMember in overriddenMembers) {
+          if (!overriddenMember.forSetter) {
             inferFrom(overriddenMember);
           }
         }
+        if (inferredType == null) {
+          // The getter type must be inferred from setters if no type was
+          // inferred from getters.
+          for (ClassMember overriddenMember in overriddenMembers) {
+            if (overriddenMember.forSetter) {
+              inferFrom(overriddenMember);
+            }
+          }
+        }
       }
 
       inferredType ??= const DynamicType();
@@ -1087,67 +1215,114 @@
     if (declaredMember.classBuilder == classBuilder && parameter.type == null) {
       DartType inferredType;
 
-      void inferFrom(ClassMember classMember) {
-        if (inferredType is InvalidType) return;
-
-        Member overriddenMember = classMember.getMember(hierarchy);
-        Substitution substitution;
-        if (classBuilder.cls != overriddenMember.enclosingClass) {
-          assert(
-              substitutions.containsKey(overriddenMember.enclosingClass),
-              "No substitution found for '${classBuilder.fullNameForErrors}' "
-              "as instance of '${overriddenMember.enclosingClass.name}'. "
-              "Substitutions available for: ${substitutions.keys}");
-          substitution = substitutions[overriddenMember.enclosingClass];
-        }
-        DartType inheritedType;
-        if (overriddenMember is Field) {
-          inheritedType = overriddenMember.type;
-          assert(inheritedType is! ImplicitFieldType);
-        } else if (overriddenMember is Procedure) {
-          if (classMember.isSetter) {
-            VariableDeclaration bParameter =
-                overriddenMember.function.positionalParameters.single;
-            inheritedType = bParameter.type;
-          } else if (classMember.isGetter) {
-            inheritedType = overriddenMember.function.returnType;
+      overriddenMembers = toSet(classBuilder, overriddenMembers);
+      if (classBuilder.library.isNonNullableByDefault) {
+        List<ClassMember> overriddenGetters = [];
+        List<ClassMember> overriddenSetters = [];
+        for (ClassMember overriddenMember in overriddenMembers) {
+          if (overriddenMember.forSetter) {
+            overriddenSetters.add(overriddenMember);
           } else {
-            debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
+            overriddenGetters.add(overriddenMember);
+          }
+        }
+
+        void inferFrom(List<ClassMember> members, {bool forSetter}) {
+          assert(forSetter != null);
+          CombinedMemberSignature combinedMemberSignature =
+              new CombinedMemberSignature(hierarchy, classBuilder, members,
+                  forSetter: forSetter);
+          DartType combinedMemberSignatureType =
+              combinedMemberSignature.combinedMemberSignatureType;
+          if (combinedMemberSignatureType == null) {
+            inferredType = const InvalidType();
+            reportCantInferReturnType(
+                classBuilder, declaredMember, hierarchy, members);
+          } else {
+            inferredType = combinedMemberSignatureType;
+          }
+        }
+
+        if (overriddenSetters.isNotEmpty) {
+          // 1) The return type of a getter, parameter type of a setter or type
+          // of a field which overrides/implements only one or more setters is
+          // inferred to be the parameter type of the combined member signature
+          // of said setter in the direct superinterfaces.
+          //
+          // 2) The parameter type of a setter which overrides/implements both a
+          // setter and a getter is inferred to be the parameter type of the
+          // combined member signature of said setter in the direct
+          // superinterfaces.
+          inferFrom(overriddenSetters, forSetter: true);
+        } else {
+          // The return type of a getter, parameter type of a setter or type of
+          // a field which overrides/implements only one or more getters is
+          // inferred to be the return type of the combined member signature of
+          // said getter in the direct superinterfaces.
+          inferFrom(overriddenGetters, forSetter: false);
+        }
+      } else {
+        void inferFrom(ClassMember classMember) {
+          if (inferredType is InvalidType) return;
+
+          Member overriddenMember = classMember.getMember(hierarchy);
+          Substitution substitution;
+          if (classBuilder.cls != overriddenMember.enclosingClass) {
+            assert(
+                substitutions.containsKey(overriddenMember.enclosingClass),
+                "No substitution found for '${classBuilder.fullNameForErrors}' "
+                "as instance of '${overriddenMember.enclosingClass.name}'. "
+                "Substitutions available for: ${substitutions.keys}");
+            substitution = substitutions[overriddenMember.enclosingClass];
+          }
+          DartType inheritedType;
+          if (overriddenMember is Field) {
+            inheritedType = overriddenMember.type;
+            assert(inheritedType is! ImplicitFieldType);
+          } else if (overriddenMember is Procedure) {
+            if (classMember.isSetter) {
+              VariableDeclaration bParameter =
+                  overriddenMember.function.positionalParameters.single;
+              inheritedType = bParameter.type;
+            } else if (classMember.isGetter) {
+              inheritedType = overriddenMember.function.returnType;
+            } else {
+              debug?.log("Giving up (not accessor: ${overriddenMember.kind})");
+              return;
+            }
+          } else {
+            debug?.log("Giving up (not field/procedure: "
+                "${overriddenMember.runtimeType})");
             return;
           }
-        } else {
-          debug?.log(
-              "Giving up (not field/procedure: ${overriddenMember.runtimeType})");
-          return;
+          if (substitution != null) {
+            inheritedType = substitution.substituteType(inheritedType);
+          }
+          inferredType = mergeTypeInLibrary(
+              hierarchy, classBuilder, inferredType, inheritedType);
+          if (inferredType == null) {
+            // A different type has already been inferred.
+            inferredType = const InvalidType();
+            reportCantInferParameterType(
+                classBuilder, parameter, hierarchy, overriddenMembers);
+          }
         }
-        if (substitution != null) {
-          inheritedType = substitution.substituteType(inheritedType);
-        }
-        inferredType = mergeTypeInLibrary(
-            hierarchy, classBuilder, inferredType, inheritedType);
-        if (inferredType == null) {
-          // A different type has already been inferred.
-          inferredType = const InvalidType();
-          reportCantInferParameterType(
-              classBuilder, parameter, hierarchy, overriddenMembers);
-        }
-      }
 
-      overriddenMembers = toSet(classBuilder, overriddenMembers);
-      // The setter type must be inferred from setters first.
-      for (ClassMember overriddenMember in overriddenMembers) {
-        if (overriddenMember.forSetter) {
-          inferFrom(overriddenMember);
-        }
-      }
-      if (inferredType == null) {
-        // The setter type must be inferred from getters if no type was
-        // inferred from setters.
+        // The setter type must be inferred from setters first.
         for (ClassMember overriddenMember in overriddenMembers) {
-          if (!overriddenMember.forSetter) {
+          if (overriddenMember.forSetter) {
             inferFrom(overriddenMember);
           }
         }
+        if (inferredType == null) {
+          // The setter type must be inferred from getters if no type was
+          // inferred from setters.
+          for (ClassMember overriddenMember in overriddenMembers) {
+            if (!overriddenMember.forSetter) {
+              inferFrom(overriddenMember);
+            }
+          }
+        }
       }
 
       inferredType ??= const DynamicType();
@@ -1204,72 +1379,137 @@
         fieldBuilder.type == null) {
       DartType inferredType;
 
-      void inferFrom(ClassMember classMember) {
-        if (inferredType is InvalidType) return;
-
-        Member overriddenMember = classMember.getMember(hierarchy);
-        DartType inheritedType;
-        if (overriddenMember is Procedure) {
-          if (overriddenMember.isSetter) {
-            VariableDeclaration parameter =
-                overriddenMember.function.positionalParameters.single;
-            inheritedType = parameter.type;
-          } else if (overriddenMember.isGetter) {
-            inheritedType = overriddenMember.function.returnType;
+      overriddenMembers = toSet(classBuilder, overriddenMembers);
+      if (classBuilder.library.isNonNullableByDefault) {
+        List<ClassMember> overriddenGetters = [];
+        List<ClassMember> overriddenSetters = [];
+        for (ClassMember overriddenMember in overriddenMembers) {
+          if (overriddenMember.forSetter) {
+            overriddenSetters.add(overriddenMember);
+          } else {
+            overriddenGetters.add(overriddenMember);
           }
-        } else if (overriddenMember is Field) {
-          inheritedType = overriddenMember.type;
         }
-        if (inheritedType == null) {
-          debug
-              ?.log("Giving up (inheritedType == null)\n${StackTrace.current}");
-          return;
+
+        DartType inferFrom(List<ClassMember> members, {bool forSetter}) {
+          assert(forSetter != null);
+          CombinedMemberSignature combinedMemberSignature =
+              new CombinedMemberSignature(hierarchy, classBuilder, members,
+                  forSetter: forSetter);
+          return combinedMemberSignature.combinedMemberSignatureType;
         }
-        Substitution substitution;
-        if (classBuilder.cls != overriddenMember.enclosingClass) {
-          assert(
-              substitutions.containsKey(overriddenMember.enclosingClass),
-              "${classBuilder.fullNameForErrors} "
-              "${overriddenMember.enclosingClass.name}");
-          substitution = substitutions[overriddenMember.enclosingClass];
-          debug?.log("${classBuilder.fullNameForErrors} -> "
-              "${overriddenMember.enclosingClass.name} $substitution");
+
+        DartType combinedMemberSignatureType;
+        if (fieldBuilder.isAssignable &&
+            overriddenGetters.isNotEmpty &&
+            overriddenSetters.isNotEmpty) {
+          // The type of a non-final field which overrides/implements both a
+          // setter and a getter is inferred to be the parameter type of the
+          // combined member signature of said setter in the direct
+          // superinterfaces, if this type is the same as the return type of the
+          // combined member signature of said getter in the direct
+          // superinterfaces. If the types are not the same then inference fails
+          // with an error.
+          DartType getterType = inferFrom(overriddenGetters, forSetter: false);
+          DartType setterType = inferFrom(overriddenSetters, forSetter: true);
+          if (getterType == setterType) {
+            combinedMemberSignatureType = getterType;
+          }
+        } else if (overriddenGetters.isNotEmpty) {
+          // 1) The return type of a getter, parameter type of a setter or type
+          // of a field which overrides/implements only one or more getters is
+          // inferred to be the return type of the combined member signature of
+          // said getter in the direct superinterfaces.
+          //
+          // 2) The type of a final field which overrides/implements both a
+          // setter and a getter is inferred to be the return type of the
+          // combined member signature of said getter in the direct
+          // superinterfaces.
+          combinedMemberSignatureType =
+              inferFrom(overriddenGetters, forSetter: false);
+        } else {
+          // The return type of a getter, parameter type of a setter or type of
+          // a field which overrides/implements only one or more setters is
+          // inferred to be the parameter type of the combined member signature
+          // of said setter in the direct superinterfaces.
+          combinedMemberSignatureType =
+              inferFrom(overriddenSetters, forSetter: true);
         }
-        assert(inheritedType is! ImplicitFieldType);
-        if (substitution != null) {
-          inheritedType = substitution.substituteType(inheritedType);
-        }
-        inferredType = mergeTypeInLibrary(
-            hierarchy, classBuilder, inferredType, inheritedType);
-        if (inferredType == null) {
-          // A different type has already been inferred.
+
+        if (combinedMemberSignatureType == null) {
           inferredType = const InvalidType();
           reportCantInferFieldType(
               classBuilder, fieldBuilder, overriddenMembers);
-        }
-      }
-
-      overriddenMembers = toSet(classBuilder, overriddenMembers);
-      if (fieldBuilder.isAssignable) {
-        // The field type must be inferred from both getters and setters.
-        for (ClassMember overriddenMember in overriddenMembers) {
-          inferFrom(overriddenMember);
+        } else {
+          inferredType = combinedMemberSignatureType;
         }
       } else {
-        // The field type must be inferred from getters first.
-        for (ClassMember overriddenMember in overriddenMembers) {
-          if (!overriddenMember.forSetter) {
-            inferFrom(overriddenMember);
+        void inferFrom(ClassMember classMember) {
+          if (inferredType is InvalidType) return;
+
+          Member overriddenMember = classMember.getMember(hierarchy);
+          DartType inheritedType;
+          if (overriddenMember is Procedure) {
+            if (overriddenMember.isSetter) {
+              VariableDeclaration parameter =
+                  overriddenMember.function.positionalParameters.single;
+              inheritedType = parameter.type;
+            } else if (overriddenMember.isGetter) {
+              inheritedType = overriddenMember.function.returnType;
+            }
+          } else if (overriddenMember is Field) {
+            inheritedType = overriddenMember.type;
+          }
+          if (inheritedType == null) {
+            debug?.log(
+                "Giving up (inheritedType == null)\n${StackTrace.current}");
+            return;
+          }
+          Substitution substitution;
+          if (classBuilder.cls != overriddenMember.enclosingClass) {
+            assert(
+                substitutions.containsKey(overriddenMember.enclosingClass),
+                "${classBuilder.fullNameForErrors} "
+                "${overriddenMember.enclosingClass.name}");
+            substitution = substitutions[overriddenMember.enclosingClass];
+            debug?.log("${classBuilder.fullNameForErrors} -> "
+                "${overriddenMember.enclosingClass.name} $substitution");
+          }
+          assert(inheritedType is! ImplicitFieldType);
+          if (substitution != null) {
+            inheritedType = substitution.substituteType(inheritedType);
+          }
+          inferredType = mergeTypeInLibrary(
+              hierarchy, classBuilder, inferredType, inheritedType);
+          if (inferredType == null) {
+            // A different type has already been inferred.
+            inferredType = const InvalidType();
+            reportCantInferFieldType(
+                classBuilder, fieldBuilder, overriddenMembers);
           }
         }
-        if (inferredType == null) {
-          // The field type must be inferred from setters if no type was
-          // inferred from getters.
+
+        if (fieldBuilder.isAssignable) {
+          // The field type must be inferred from both getters and setters.
           for (ClassMember overriddenMember in overriddenMembers) {
-            if (overriddenMember.forSetter) {
+            inferFrom(overriddenMember);
+          }
+        } else {
+          // The field type must be inferred from getters first.
+          for (ClassMember overriddenMember in overriddenMembers) {
+            if (!overriddenMember.forSetter) {
               inferFrom(overriddenMember);
             }
           }
+          if (inferredType == null) {
+            // The field type must be inferred from setters if no type was
+            // inferred from getters.
+            for (ClassMember overriddenMember in overriddenMembers) {
+              if (overriddenMember.forSetter) {
+                inferFrom(overriddenMember);
+              }
+            }
+          }
         }
       }
 
@@ -1700,37 +1940,40 @@
     /// [ClassHierarchyNode].
     Map<Name, ClassMember> interfaceSetterMap = {};
 
-    Map<ClassMember, Set<ClassMember>> overrideDependencies = {};
-
-    // TODO(johnniwinther): Make these non-local and ensure that each
-    // underlying declaration has only on delayed type, signature, and
-    // override computation. Currently fields get one as a getter and as a
-    // setter.
-
-    void registerOverrideDependency(
-        ClassMember member, ClassMember overriddenMember) {
-      if (classBuilder == member.classBuilder && member.isSourceDeclaration) {
-        Set<ClassMember> dependencies =
-            overrideDependencies[member] ??= <ClassMember>{};
-        dependencies.add(overriddenMember);
-        member.registerOverrideDependency(overriddenMember);
-      }
-    }
-
     void registerOverrideCheck(
         ClassMember member, ClassMember overriddenMember) {
-      if (overriddenMember.hasDeclarations &&
-          classBuilder == overriddenMember.classBuilder) {
-        for (int i = 0; i < overriddenMember.declarations.length; i++) {
+      if (classBuilder is SourceClassBuilder) {
+        if (overriddenMember.hasDeclarations &&
+            classBuilder == overriddenMember.classBuilder) {
+          for (int i = 0; i < overriddenMember.declarations.length; i++) {
+            hierarchy.registerOverrideCheck(
+                classBuilder, member, overriddenMember.declarations[i]);
+          }
+        } else {
           hierarchy.registerOverrideCheck(
-              classBuilder, member, overriddenMember.declarations[i]);
+              classBuilder, member, overriddenMember);
         }
-      } else {
-        hierarchy.registerOverrideCheck(classBuilder, member, overriddenMember);
       }
     }
 
     memberMap.forEach((Name name, Tuple tuple) {
+      Set<ClassMember> overriddenMembers = {};
+
+      void registerOverrideDependency(
+          ClassMember member, ClassMember overriddenMember) {
+        if (classBuilder == member.classBuilder && member.isSourceDeclaration) {
+          if (overriddenMember.hasDeclarations &&
+              classBuilder == overriddenMember.classBuilder) {
+            for (int i = 0; i < overriddenMember.declarations.length; i++) {
+              registerOverrideDependency(
+                  member, overriddenMember.declarations[i]);
+            }
+          } else {
+            overriddenMembers.add(overriddenMember);
+          }
+        }
+      }
+
       ClassMember computeClassMember(ClassMember declaredMember,
           ClassMember extendedMember, bool forSetter) {
         if (declaredMember != null) {
@@ -1777,7 +2020,7 @@
                     shouldModifyKernel,
                     concrete.isAbstract,
                     concrete.name);
-                hierarchy.registerMemberCheck(result);
+                hierarchy.registerMemberComputation(result);
               }
             } else if (classBuilder.isMixinApplication &&
                 declaredMember.classBuilder != classBuilder) {
@@ -1789,7 +2032,7 @@
                   shouldModifyKernel,
                   isInheritableConflict: false);
               if (result.needsComputation) {
-                hierarchy.registerMemberCheck(result);
+                hierarchy.registerMemberComputation(result);
               }
             }
 
@@ -1816,7 +2059,7 @@
           }
           if (extendedMember.isInheritableConflict) {
             extendedMember = extendedMember.withParent(classBuilder);
-            hierarchy.registerMemberCheck(extendedMember);
+            hierarchy.registerMemberComputation(extendedMember);
           }
           if (extendedMember.classBuilder.library.isNonNullableByDefault &&
               !classBuilder.library.isNonNullableByDefault) {
@@ -1830,7 +2073,7 @@
                   extendedMember.isAbstract,
                   extendedMember.name,
                   isImplicitlyAbstract: extendedMember.isAbstract);
-              hierarchy.registerMemberCheck(extendedMember);
+              hierarchy.registerMemberComputation(extendedMember);
             }
           }
           return extendedMember;
@@ -1919,7 +2162,7 @@
                       shouldModifyKernel);
                 }
                 if (result.needsComputation) {
-                  hierarchy.registerMemberCheck(result);
+                  hierarchy.registerMemberComputation(result);
                 }
               }
 
@@ -1932,7 +2175,7 @@
               }
               if (interfaceMember.isInheritableConflict) {
                 interfaceMember = interfaceMember.withParent(classBuilder);
-                hierarchy.registerMemberCheck(interfaceMember);
+                hierarchy.registerMemberComputation(interfaceMember);
               }
               if (interfaceMember.classBuilder.library.isNonNullableByDefault &&
                   !classBuilder.library.isNonNullableByDefault) {
@@ -1946,7 +2189,7 @@
                       interfaceMember.isAbstract,
                       interfaceMember.name,
                       isImplicitlyAbstract: interfaceMember.isAbstract);
-                  hierarchy.registerMemberCheck(interfaceMember);
+                  hierarchy.registerMemberComputation(interfaceMember);
                 }
               }
               return interfaceMember;
@@ -1960,6 +2203,15 @@
 
       void checkMemberVsSetter(
           ClassMember member, ClassMember overriddenMember) {
+        if (overriddenMember.classBuilder == classBuilder &&
+            overriddenMember.hasDeclarations) {
+          for (ClassMember declaration in overriddenMember.declarations) {
+            checkMemberVsSetter(member, declaration);
+          }
+          return;
+        }
+
+        if (classBuilder is! SourceClassBuilder) return;
         if (overriddenMember.isStatic) return;
         if (member == overriddenMember) return;
         if (member.isDuplicate || overriddenMember.isDuplicate) {
@@ -1973,15 +2225,9 @@
         if (member.classBuilder == classBuilder &&
             overriddenMember.classBuilder != classBuilder) {
           if (member is SourceFieldMember) {
-            if (member.isFinal && overriddenMember.isSetter) {
-              registerOverrideDependency(member, overriddenMember);
-              hierarchy.registerOverrideCheck(
-                  classBuilder, member, overriddenMember);
-            } else {
-              registerOverrideDependency(member, overriddenMember);
-              hierarchy.registerOverrideCheck(
-                  classBuilder, member, overriddenMember);
-            }
+            registerOverrideDependency(member, overriddenMember);
+            hierarchy.registerOverrideCheck(
+                classBuilder, member, overriddenMember);
           } else if (member is SourceProcedureMember) {
             registerOverrideDependency(member, overriddenMember);
             hierarchy.registerOverrideCheck(
@@ -2036,6 +2282,18 @@
           classSetter = interfaceSetter;
         }
       }
+      if (classBuilder is SourceClassBuilder) {
+        ClassMember member = interfaceMember ?? classMember;
+        ClassMember setter = interfaceSetter ?? classSetter;
+        if (member != null &&
+            setter != null &&
+            member.isProperty &&
+            setter.isProperty &&
+            member.isStatic == setter.isStatic &&
+            !member.isSameDeclaration(setter)) {
+          hierarchy.registerGetterSetterCheck(classBuilder, member, setter);
+        }
+      }
       if (classMember != null) {
         classMemberMap[name] = classMember;
       }
@@ -2048,18 +2306,21 @@
       if (interfaceSetter != null) {
         interfaceSetterMap[name] = interfaceSetter;
       }
-    });
+      if (overriddenMembers.isNotEmpty) {
+        void registerOverrideDependencies(ClassMember member) {
+          if (member != null &&
+              member.classBuilder == classBuilder &&
+              member.isSourceDeclaration) {
+            member.registerOverrideDependency(overriddenMembers);
+            DelayedTypeComputation computation =
+                new DelayedTypeComputation(this, member, overriddenMembers);
+            hierarchy.registerDelayedTypeComputation(computation);
+          }
+        }
 
-    overrideDependencies
-        .forEach((ClassMember member, Set<ClassMember> overriddenMembers) {
-      assert(
-          member == memberMap[member.name].declaredMember ||
-              member == memberMap[member.name].declaredSetter,
-          "Unexpected method type inference for ${memberMap[member.name]}: "
-          "${member} -> ${overriddenMembers}");
-      DelayedTypeComputation computation =
-          new DelayedTypeComputation(this, member, overriddenMembers);
-      hierarchy.registerDelayedTypeComputation(computation);
+        registerOverrideDependencies(tuple.declaredMember);
+        registerOverrideDependencies(tuple.declaredSetter);
+      }
     });
 
     if (!hasInterfaces) {
@@ -2571,8 +2832,12 @@
   }
 }
 
-class DelayedOverrideCheck {
-  final ClassBuilder classBuilder;
+abstract class DelayedCheck {
+  void check(ClassHierarchyBuilder hierarchy);
+}
+
+class DelayedOverrideCheck implements DelayedCheck {
+  final SourceClassBuilder classBuilder;
   final ClassMember declaredMember;
   final ClassMember overriddenMember;
 
@@ -2594,6 +2859,19 @@
   }
 }
 
+class DelayedGetterSetterCheck implements DelayedCheck {
+  final SourceClassBuilder classBuilder;
+  final ClassMember getter;
+  final ClassMember setter;
+
+  const DelayedGetterSetterCheck(this.classBuilder, this.getter, this.setter);
+
+  void check(ClassHierarchyBuilder hierarchy) {
+    classBuilder.checkGetterSetter(hierarchy.types, getter.getMember(hierarchy),
+        setter.getMember(hierarchy));
+  }
+}
+
 class DelayedTypeComputation {
   final ClassHierarchyNodeBuilder builder;
   final ClassMember declaredMember;
@@ -2714,7 +2992,7 @@
   }
 
   @override
-  void registerOverrideDependency(ClassMember overriddenMember) {
+  void registerOverrideDependency(Set<ClassMember> overriddenMembers) {
     // Do nothing; this is only for declared members.
   }
 
@@ -2802,11 +3080,13 @@
       return combinedMemberSignatureResult;
     }
     if (!classBuilder.isAbstract) {
-      for (int i = 0; i < declarations.length; i++) {
-        if (concreteMember != declarations[i]) {
-          new DelayedOverrideCheck(
-                  classBuilder, concreteMember, declarations[i])
-              .check(hierarchy);
+      if (classBuilder is SourceClassBuilder) {
+        for (int i = 0; i < declarations.length; i++) {
+          if (concreteMember != declarations[i]) {
+            new DelayedOverrideCheck(
+                    classBuilder, concreteMember, declarations[i])
+                .check(hierarchy);
+          }
         }
       }
     }
@@ -2823,6 +3103,12 @@
             [this], isProperty, isSetter, modifyKernel, isAbstract, name);
   }
 
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    // This could be more precise but it currently has no benefit.
+    return identical(this, other);
+  }
+
   static ClassMember combined(
       ClassBuilder parent,
       ClassMember concreteImplementation,
@@ -2909,46 +3195,6 @@
         isImplicitlyAbstract == other.isImplicitlyAbstract;
   }
 
-  DartType computeMemberType(
-      ClassHierarchyBuilder hierarchy, DartType thisType, Member member) {
-    DartType type;
-    if (member is Procedure) {
-      if (member.isGetter) {
-        type = member.getterType;
-      } else if (member.isSetter) {
-        type = member.setterType;
-      } else {
-        type = member.function
-            .computeFunctionType(member.enclosingLibrary.nonNullable);
-      }
-    } else if (member is Field) {
-      type = member.type;
-    } else {
-      unhandled("${member.runtimeType}", "$member", classBuilder.charOffset,
-          classBuilder.fileUri);
-    }
-    InterfaceType instance = hierarchy.getTypeAsInstanceOf(
-        thisType,
-        member.enclosingClass,
-        classBuilder.library.library,
-        hierarchy.coreTypes);
-    assert(
-        instance != null,
-        "No instance of $thisType as ${member.enclosingClass} found for "
-        "$member.");
-    return Substitution.fromInterfaceType(instance).substituteType(type);
-  }
-
-  bool isMoreSpecific(ClassHierarchyBuilder hierarchy, DartType a, DartType b) {
-    if (isSetter) {
-      return hierarchy.types
-          .isSubtypeOf(b, a, SubtypeCheckMode.withNullabilities);
-    } else {
-      return hierarchy.types
-          .isSubtypeOf(a, b, SubtypeCheckMode.withNullabilities);
-    }
-  }
-
   @override
   Member getMember(ClassHierarchyBuilder hierarchy) {
     if (combinedMemberSignatureResult != null) {
@@ -2958,81 +3204,16 @@
       return combinedMemberSignatureResult =
           declarations.first.getMember(hierarchy);
     }
-    bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;
-    DartType thisType = hierarchy.coreTypes
-        .thisInterfaceType(classBuilder.cls, classBuilder.library.nonNullable);
-    List<DartType> candidateTypes = new List<DartType>(declarations.length);
-    ClassMember bestSoFar;
-    int bestSoFarIndex;
-    DartType bestTypeSoFar;
-    Map<DartType, int> mutualSubtypes;
-    for (int candidateIndex = declarations.length - 1;
-        candidateIndex >= 0;
-        candidateIndex--) {
-      ClassMember candidate = declarations[candidateIndex];
-      Member target = candidate.getMember(hierarchy);
-      assert(target != null,
-          "No member computed for ${candidate} (${candidate.runtimeType})");
-      DartType candidateType = computeMemberType(hierarchy, thisType, target);
-      if (!isNonNullableByDefault) {
-        candidateType = legacyErasure(hierarchy.coreTypes, candidateType);
-      }
-      candidateTypes[candidateIndex] = candidateType;
-      if (bestSoFar == null) {
-        bestSoFar = candidate;
-        bestTypeSoFar = candidateType;
-        bestSoFarIndex = candidateIndex;
-      } else {
-        if (isMoreSpecific(hierarchy, candidateType, bestTypeSoFar)) {
-          debug?.log("Combined Member Signature: ${candidate.fullName} "
-              "${candidateType} <: ${bestSoFar.fullName} ${bestTypeSoFar}");
-          if (isNonNullableByDefault &&
-              isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
-            if (mutualSubtypes == null) {
-              mutualSubtypes = {
-                bestTypeSoFar: bestSoFarIndex,
-                candidateType: candidateIndex
-              };
-            } else {
-              mutualSubtypes[candidateType] = candidateIndex;
-            }
-          } else {
-            mutualSubtypes = null;
-          }
-          bestSoFarIndex = candidateIndex;
-          bestSoFar = candidate;
-          bestTypeSoFar = candidateType;
-        } else {
-          debug?.log("Combined Member Signature: "
-              "${candidate.fullName} !<: ${bestSoFar.fullName}");
-        }
-      }
-    }
-    if (bestSoFar != null) {
-      debug?.log("Combined Member Signature bestSoFar: ${bestSoFar.fullName}");
-      for (int candidateIndex = 0;
-          candidateIndex < declarations.length;
-          candidateIndex++) {
-        ClassMember candidate = declarations[candidateIndex];
-        DartType candidateType = candidateTypes[candidateIndex];
-        if (!isMoreSpecific(hierarchy, bestTypeSoFar, candidateType)) {
-          debug?.log("Combined Member Signature: "
-              "${bestSoFar.fullName} !<: ${candidate.fullName}");
 
-          if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
-            bestSoFar = null;
-            bestTypeSoFar = null;
-            mutualSubtypes = null;
-          }
-          break;
-        }
-      }
-    }
-    if (bestSoFar == null) {
+    CombinedMemberSignature combinedMemberSignature =
+        new CombinedMemberSignature(hierarchy, classBuilder, declarations,
+            forSetter: isSetter);
+
+    if (combinedMemberSignature.canonicalClassMember == null) {
       String name = classBuilder.fullNameForErrors;
       int length = classBuilder.isAnonymousMixinApplication ? 1 : name.length;
       List<LocatedMessage> context = declarations.map((ClassMember d) {
-        return messageDeclaredMemberConflictsWithInheritedMembersCause
+        return messageDeclaredMemberConflictsWithOverriddenMembersCause
             .withLocation(d.fileUri, d.charOffset, d.fullNameForErrors.length);
       }).toList();
 
@@ -3049,33 +3230,30 @@
           declarations.first.getMember(hierarchy);
     }
     debug?.log("Combined Member Signature of ${fullNameForErrors}: "
-        "${bestSoFar.fullName}");
-
-    ProcedureKind kind = ProcedureKind.Method;
-    Member bestMemberSoFar = bestSoFar.getMember(hierarchy);
-    if (bestSoFar.isProperty) {
-      kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
-    } else if (bestMemberSoFar is Procedure &&
-        bestMemberSoFar.kind == ProcedureKind.Operator) {
-      kind = ProcedureKind.Operator;
-    }
+        "${combinedMemberSignature.canonicalClassMember.fullName}");
 
     if (modifyKernel) {
+      ProcedureKind kind = ProcedureKind.Method;
+      Member bestMemberSoFar =
+          combinedMemberSignature.canonicalClassMember.getMember(hierarchy);
+      if (combinedMemberSignature.canonicalClassMember.isProperty) {
+        kind = isSetter ? ProcedureKind.Setter : ProcedureKind.Getter;
+      } else if (bestMemberSoFar is Procedure &&
+          bestMemberSoFar.kind == ProcedureKind.Operator) {
+        kind = ProcedureKind.Operator;
+      }
+
       debug?.log("Combined Member Signature of ${fullNameForErrors}: new "
-          "ForwardingNode($classBuilder, $bestSoFar, $declarations, $kind)");
-      Member stub = new ForwardingNode(
-              hierarchy,
-              classBuilder,
-              bestSoFar,
-              bestSoFarIndex,
-              declarations,
-              kind,
-              mutualSubtypes?.values?.toSet())
-          .finalize();
+          "ForwardingNode($classBuilder, "
+          "${combinedMemberSignature.canonicalClassMember}, "
+          "$declarations, $kind)");
+      Member stub =
+          new ForwardingNode(combinedMemberSignature, kind).finalize();
       if (classBuilder.cls == stub.enclosingClass) {
         classBuilder.cls.addMember(stub);
         SourceLibraryBuilder library = classBuilder.library;
-        Member bestMemberSoFar = bestSoFar.getMember(hierarchy);
+        Member bestMemberSoFar =
+            combinedMemberSignature.canonicalClassMember.getMember(hierarchy);
         if (bestMemberSoFar is Procedure) {
           library.forwardersOrigins..add(stub)..add(bestMemberSoFar);
         }
@@ -3087,7 +3265,8 @@
 
     debug?.log(
         "Combined Member Signature of ${fullNameForErrors}: picked bestSoFar");
-    return combinedMemberSignatureResult = bestSoFar.getMember(hierarchy);
+    return combinedMemberSignatureResult =
+        combinedMemberSignature.canonicalClassMember.getMember(hierarchy);
   }
 
   @override
@@ -3099,6 +3278,12 @@
             isImplicitlyAbstract: isImplicitlyAbstract);
   }
 
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    // This could be more precise but it currently has no benefit.
+    return identical(this, other);
+  }
+
   static ClassMember combined(ClassBuilder parent, ClassMember a, ClassMember b,
       bool isSetter, bool createForwarders) {
     assert(a.isProperty == b.isProperty,
@@ -3166,9 +3351,11 @@
       _isChecked = true;
       if (!classBuilder.isAbstract &&
           !hierarchy.nodes[classBuilder.cls].hasNoSuchMethod) {
-        new DelayedOverrideCheck(
-                classBuilder, concreteImplementation, abstractMember)
-            .check(hierarchy);
+        if (classBuilder is SourceClassBuilder) {
+          new DelayedOverrideCheck(
+                  classBuilder, concreteImplementation, abstractMember)
+              .check(hierarchy);
+        }
       }
 
       ProcedureKind kind = ProcedureKind.Method;
@@ -3178,8 +3365,10 @@
       if (modifyKernel) {
         // This call will add a body to the abstract method if needed for
         // isGenericCovariantImpl checks.
-        new ForwardingNode(hierarchy, classBuilder, abstractMember, 1,
-                declarations, kind, null)
+        new ForwardingNode(
+                new CombinedMemberSignature.internal(
+                    hierarchy, classBuilder, 1, declarations),
+                kind)
             .finalize();
       }
     }
@@ -3219,6 +3408,15 @@
 
   @override
   ClassMember get concrete => concreteImplementation;
+
+  @override
+  bool isSameDeclaration(ClassMember other) {
+    if (identical(this, other)) return false;
+    return other is AbstractMemberOverridingImplementation &&
+        classBuilder == other.classBuilder &&
+        abstract.isSameDeclaration(other.abstract) &&
+        concrete.isSameDeclaration(other.concrete);
+  }
 }
 
 void addDeclarationIfDifferent(
@@ -3249,7 +3447,7 @@
   String name = parameter.name;
   List<LocatedMessage> context = overriddenMembers
       .map((ClassMember overriddenMember) {
-        return messageDeclaredMemberConflictsWithInheritedMembersCause
+        return messageDeclaredMemberConflictsWithOverriddenMembersCause
             .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                 overriddenMember.fullNameForErrors.length);
       })
@@ -3258,7 +3456,9 @@
       .toSet()
       .toList();
   cls.addProblem(
-      templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
+      cls.library.isNonNullableByDefault
+          ? templateCantInferTypeDueToNoCombinedSignature.withArguments(name)
+          : templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
       parameter.charOffset,
       name.length,
       wasHandled: true,
@@ -3270,7 +3470,7 @@
   String name = member.fullNameForErrors;
   List<LocatedMessage> context = overriddenMembers
       .map((ClassMember overriddenMember) {
-        return messageDeclaredMemberConflictsWithInheritedMembersCause
+        return messageDeclaredMemberConflictsWithOverriddenMembersCause
             .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                 overriddenMember.fullNameForErrors.length);
       })
@@ -3326,7 +3526,11 @@
   //   }
   // }
   cls.addProblem(
-      templateCantInferReturnTypeDueToInconsistentOverrides.withArguments(name),
+      cls.library.isNonNullableByDefault
+          ? templateCantInferReturnTypeDueToNoCombinedSignature
+              .withArguments(name)
+          : templateCantInferReturnTypeDueToInconsistentOverrides
+              .withArguments(name),
       member.charOffset,
       name.length,
       wasHandled: true,
@@ -3337,7 +3541,7 @@
     Iterable<ClassMember> overriddenMembers) {
   List<LocatedMessage> context = overriddenMembers
       .map((ClassMember overriddenMember) {
-        return messageDeclaredMemberConflictsWithInheritedMembersCause
+        return messageDeclaredMemberConflictsWithOverriddenMembersCause
             .withLocation(overriddenMember.fileUri, overriddenMember.charOffset,
                 overriddenMember.fullNameForErrors.length);
       })
@@ -3347,7 +3551,9 @@
       .toList();
   String name = member.fullNameForErrors;
   cls.addProblem(
-      templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
+      cls.library.isNonNullableByDefault
+          ? templateCantInferTypeDueToNoCombinedSignature.withArguments(name)
+          : templateCantInferTypeDueToInconsistentOverrides.withArguments(name),
       member.charOffset,
       name.length,
       wasHandled: true,
@@ -3392,3 +3598,300 @@
     }
   }
 }
+
+/// Class used for computing and inspecting the combined member signature for
+/// a set of overridden/inherited members.
+class CombinedMemberSignature {
+  /// The class hierarchy builder used for building this class.
+  final ClassHierarchyBuilder hierarchy;
+
+  /// The target class for the combined member signature.
+  ///
+  /// The [_memberTypes] are computed in terms of each member is inherited into
+  /// [classBuilder].
+  ///
+  /// [classBuilder] is also used for determining whether the combined member
+  /// signature should be computed using nnbd or legacy semantics.
+  final SourceClassBuilder classBuilder;
+
+  /// The list of the members inherited into or overridden in [classBuilder].
+  final List<ClassMember> members;
+
+  /// The index within [members] for the member whose type is the most specific
+  /// among [members]. If `null`, the combined member signature is not defined
+  /// for [members] in [classBuilder].
+  ///
+  /// For the legacy computation, the type of this member defines the combined
+  /// member signature.
+  ///
+  /// For the nnbd computation, this is one of the members whose type define
+  /// the combined member signature, and the indices of the remaining members
+  /// are stored in [_mutualSubtypes].
+  int _canonicalMemberIndex;
+
+  /// For the nnbd computation, this maps each distinct but most specific member
+  /// type to the index of one of the [members] with that type.
+  ///
+  /// If there is only one most specific member type, this is `null`.
+  Map<DartType, int> _mutualSubtypes;
+
+  /// Cache for the types of [members] as inherited into [classBuilder].
+  List<DartType> _memberTypes;
+
+  /// Cache for the this type of [classBuilder].
+  DartType _thisType;
+
+  /// If `true` the combined member signature type has been computed.
+  ///
+  /// Note that the combined member signature type might be undefined in which
+  /// case [_combinedMemberSignatureType] is `null`.
+  bool _isCombinedMemberSignatureTypeComputed = false;
+
+  /// Cache the computed combined member signature type.
+  ///
+  /// If the combined member signature type is undefined this is set to `null`.
+  DartType _combinedMemberSignatureType;
+
+  /// Creates a [CombinedMemberSignature] whose canonical member is already
+  /// defined.
+  CombinedMemberSignature.internal(this.hierarchy, this.classBuilder,
+      this._canonicalMemberIndex, this.members);
+
+  /// Creates a [CombinedMemberSignature] for [members] inherited into
+  /// [classBuilder].
+  ///
+  /// If [forSetter] is `true`, contravariance of the setter types is used to
+  /// compute the most specific member type. Otherwise covariance of the getter
+  /// types or function types is used.
+  CombinedMemberSignature(this.hierarchy, this.classBuilder, this.members,
+      {bool forSetter}) {
+    assert(forSetter != null);
+    ClassMember bestSoFar;
+    int bestSoFarIndex;
+    if (members.length == 1) {
+      bestSoFar = members.first;
+      bestSoFarIndex = 0;
+    } else {
+      bool isNonNullableByDefault = classBuilder.library.isNonNullableByDefault;
+
+      DartType bestTypeSoFar;
+      for (int candidateIndex = members.length - 1;
+          candidateIndex >= 0;
+          candidateIndex--) {
+        ClassMember candidate = members[candidateIndex];
+        DartType candidateType = getMemberType(candidateIndex);
+        if (bestSoFar == null) {
+          bestSoFar = candidate;
+          bestTypeSoFar = candidateType;
+          bestSoFarIndex = candidateIndex;
+        } else {
+          if (_isMoreSpecific(candidateType, bestTypeSoFar, forSetter)) {
+            if (isNonNullableByDefault &&
+                _isMoreSpecific(bestTypeSoFar, candidateType, forSetter)) {
+              if (_mutualSubtypes == null) {
+                _mutualSubtypes = {
+                  bestTypeSoFar: bestSoFarIndex,
+                  candidateType: candidateIndex
+                };
+              } else {
+                _mutualSubtypes[candidateType] = candidateIndex;
+              }
+            } else {
+              _mutualSubtypes = null;
+            }
+            bestSoFarIndex = candidateIndex;
+            bestSoFar = candidate;
+            bestTypeSoFar = candidateType;
+          }
+        }
+      }
+      if (bestSoFar != null) {
+        for (int candidateIndex = 0;
+            candidateIndex < members.length;
+            candidateIndex++) {
+          DartType candidateType = getMemberType(candidateIndex);
+          if (!_isMoreSpecific(bestTypeSoFar, candidateType, forSetter)) {
+            if (!shouldOverrideProblemBeOverlooked(classBuilder)) {
+              bestSoFar = null;
+              bestSoFarIndex = null;
+              bestTypeSoFar = null;
+              _mutualSubtypes = null;
+            }
+            break;
+          }
+        }
+      }
+    }
+
+    _canonicalMemberIndex = bestSoFarIndex;
+  }
+
+  /// The member within [members] type is the most specific among [members].
+  /// If `null`, the combined member signature is not defined for [members] in
+  /// [classBuilder].
+  ///
+  /// For the legacy computation, the type of this member defines the combined
+  /// member signature.
+  ///
+  /// For the nnbd computation, this is one of the members whose type define
+  /// the combined member signature, and the indices of the all members whose
+  /// type define the combined member signature are in [mutualSubtypeIndices].
+  ClassMember get canonicalClassMember =>
+      _canonicalMemberIndex != null ? members[_canonicalMemberIndex] : null;
+
+  /// The index within [members] for the member whose type is the most specific
+  /// among [members]. If `null`, the combined member signature is not defined
+  /// for [members] in [classBuilder].
+  ///
+  /// For the legacy computation, the type of this member defines the combined
+  /// member signature.
+  ///
+  /// For the nnbd computation, this is one of the members whose type define
+  /// the combined member signature, and the indices of the all members whose
+  /// type define the combined member signature are in [mutualSubtypeIndices].
+  int get classMemberIndex => _canonicalMemberIndex;
+
+  /// For the nnbd computation, the indices of the [members] with most specific
+  /// member type.
+  ///
+  /// If there is only one most specific member type, this is `null`.
+  Set<int> get mutualSubtypeIndices => _mutualSubtypes?.values?.toSet();
+
+  /// The this type of [classBuilder].
+  DartType get thisType {
+    return _thisType ??= hierarchy.coreTypes
+        .thisInterfaceType(classBuilder.cls, classBuilder.library.nonNullable);
+  }
+
+  /// Returns type of the [index]th member in [members] as inherited in
+  /// [classBuilder].
+  DartType getMemberType(int index) {
+    _memberTypes ??= new List<DartType>(members.length);
+    DartType candidateType = _memberTypes[index];
+    if (candidateType == null) {
+      ClassMember candidate = members[index];
+      Member target = candidate.getMember(hierarchy);
+      assert(target != null,
+          "No member computed for ${candidate} (${candidate.runtimeType})");
+      candidateType = _computeMemberType(thisType, target);
+      if (!classBuilder.library.isNonNullableByDefault) {
+        candidateType = legacyErasure(hierarchy.coreTypes, candidateType);
+      }
+      _memberTypes[index] = candidateType;
+    }
+    return candidateType;
+  }
+
+  /// Returns the type of the combined member signature, if defined.
+  DartType get combinedMemberSignatureType {
+    if (!_isCombinedMemberSignatureTypeComputed) {
+      _isCombinedMemberSignatureTypeComputed = true;
+      if (_canonicalMemberIndex == null) {
+        return null;
+      }
+      if (classBuilder.library.isNonNullableByDefault) {
+        _combinedMemberSignatureType = getMemberType(_canonicalMemberIndex);
+        if (_mutualSubtypes != null) {
+          _combinedMemberSignatureType =
+              norm(hierarchy.coreTypes, _combinedMemberSignatureType);
+          for (int index in _mutualSubtypes.values) {
+            if (_canonicalMemberIndex != index) {
+              _combinedMemberSignatureType = nnbdTopMerge(
+                  hierarchy.coreTypes,
+                  _combinedMemberSignatureType,
+                  norm(hierarchy.coreTypes, getMemberType(index)));
+            }
+          }
+        }
+      } else {
+        _combinedMemberSignatureType = legacyErasure(
+            hierarchy.coreTypes, getMemberType(_canonicalMemberIndex));
+      }
+    }
+    return _combinedMemberSignatureType;
+  }
+
+  /// Returns the type of the combined member signature, if defined, with
+  /// all method type parameters substituted with [typeParameters].
+  ///
+  /// This is used for inferring types on a declared member from the type of the
+  /// combined member signature.
+  DartType getCombinedSignatureTypeInContext(
+      List<TypeParameter> typeParameters) {
+    DartType type = combinedMemberSignatureType;
+    if (type == null) {
+      return null;
+    }
+    int typeParameterCount = typeParameters.length;
+    if (type is FunctionType) {
+      List<TypeParameter> signatureTypeParameters = type.typeParameters;
+      if (typeParameterCount != signatureTypeParameters.length) {
+        return null;
+      }
+      if (typeParameterCount == 0) {
+        return type;
+      }
+      List<DartType> types = new List<DartType>(typeParameterCount);
+      for (int i = 0; i < typeParameterCount; i++) {
+        types[i] = new TypeParameterType.forAlphaRenaming(
+            signatureTypeParameters[i], typeParameters[i]);
+      }
+      Substitution substitution =
+          Substitution.fromPairs(signatureTypeParameters, types);
+      for (int i = 0; i < typeParameterCount; i++) {
+        DartType typeParameterBound = typeParameters[i].bound;
+        DartType signatureTypeParameterBound =
+            substitution.substituteType(signatureTypeParameters[i].bound);
+        if (!hierarchy.types
+            .performNullabilityAwareMutualSubtypesCheck(
+                typeParameterBound, signatureTypeParameterBound)
+            .isSubtypeWhenUsingNullabilities()) {
+          return null;
+        }
+      }
+      return substitution.substituteType(type.withoutTypeParameters);
+    } else if (typeParameterCount != 0) {
+      return null;
+    }
+    return type;
+  }
+
+  DartType _computeMemberType(DartType thisType, Member member) {
+    DartType type;
+    if (member is Procedure) {
+      if (member.isGetter) {
+        type = member.getterType;
+      } else if (member.isSetter) {
+        type = member.setterType;
+      } else {
+        type = member.function
+            .computeFunctionType(member.enclosingLibrary.nonNullable);
+      }
+    } else if (member is Field) {
+      type = member.type;
+    } else {
+      unhandled("${member.runtimeType}", "$member", classBuilder.charOffset,
+          classBuilder.fileUri);
+    }
+    InterfaceType instance = hierarchy.getTypeAsInstanceOf(
+        thisType,
+        member.enclosingClass,
+        classBuilder.library.library,
+        hierarchy.coreTypes);
+    assert(
+        instance != null,
+        "No instance of $thisType as ${member.enclosingClass} found for "
+        "$member.");
+    return Substitution.fromInterfaceType(instance).substituteType(type);
+  }
+
+  bool _isMoreSpecific(DartType a, DartType b, bool forSetter) {
+    if (forSetter) {
+      return hierarchy.types
+          .isSubtypeOf(b, a, SubtypeCheckMode.withNullabilities);
+    } else {
+      return hierarchy.types
+          .isSubtypeOf(a, b, SubtypeCheckMode.withNullabilities);
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
index 28f549f..5fd43f5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.dart
@@ -18,25 +18,34 @@
   L makeLiteral(List<Expression> elements);
 
   /// Add an element to the constant list being built by this builder.
-  void add(Expression element) {
+  ///
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant add(Expression element) {
     Constant constant = evaluator._evaluateSubexpression(element);
+    if (constant is AbortConstant) return constant;
     if (evaluator.shouldBeUnevaluated) {
       parts.add(evaluator.unevaluated(
           element, makeLiteral([evaluator.extract(constant)])));
+      return null;
     } else {
-      addConstant(constant, element);
+      return addConstant(constant, element);
     }
   }
 
-  void addSpread(Expression spreadExpression) {
-    Constant spread =
-        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant addSpread(Expression spreadExpression) {
+    Constant constant = evaluator._evaluateSubexpression(spreadExpression);
+    if (constant is AbortConstant) return constant;
+    Constant spread = evaluator.unlower(constant);
     if (evaluator.shouldBeUnevaluated) {
       // Unevaluated spread
       parts.add(spread);
     } else if (spread == evaluator.nullConstant) {
       // Null spread
-      evaluator.report(spreadExpression, messageConstEvalNullValue);
+      return evaluator.createErrorConstant(
+          spreadExpression, messageConstEvalNullValue);
     } else {
       // Fully evaluated spread
       List<Constant> entries;
@@ -46,16 +55,20 @@
         entries = spread.entries;
       } else {
         // Not list or set in spread
-        return evaluator.report(
+        return evaluator.createErrorConstant(
             spreadExpression, messageConstEvalNotListOrSetInSpread);
       }
       for (Constant entry in entries) {
-        addConstant(entry, spreadExpression);
+        AbortConstant error = addConstant(entry, spreadExpression);
+        if (error != null) return error;
       }
     }
+    return null;
   }
 
-  void addConstant(Constant constant, TreeNode context);
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant addConstant(Constant constant, TreeNode context);
 
   Constant build();
 }
@@ -70,14 +83,18 @@
       new ListLiteral(elements, isConst: true);
 
   @override
-  void addConstant(Constant constant, TreeNode context) {
+  AbortConstant addConstant(Constant constant, TreeNode context) {
     List<Constant> lastPart;
     if (parts.last is List<Constant>) {
       lastPart = parts.last;
     } else {
+      // Probably unreachable.
       parts.add(lastPart = <Constant>[]);
     }
-    lastPart.add(evaluator.ensureIsSubtype(constant, elementType, context));
+    Constant value = evaluator.ensureIsSubtype(constant, elementType, context);
+    if (value is AbortConstant) return value;
+    lastPart.add(value);
+    return null;
   }
 
   @override
@@ -115,16 +132,16 @@
       new SetLiteral(elements, isConst: true);
 
   @override
-  void addConstant(Constant constant, TreeNode context) {
+  AbortConstant addConstant(Constant constant, TreeNode context) {
     if (!evaluator.hasPrimitiveEqual(constant)) {
-      evaluator.report(
+      return evaluator.createErrorConstant(
           context,
           templateConstEvalElementImplementsEqual.withArguments(
               constant, evaluator.isNonNullableByDefault));
     }
     bool unseen = seen.add(constant);
     if (!unseen) {
-      evaluator.report(
+      return evaluator.createErrorConstant(
           context,
           templateConstEvalDuplicateElement.withArguments(
               constant, evaluator.isNonNullableByDefault));
@@ -134,7 +151,8 @@
           evaluator._weakener.visitConstant(constant) ?? constant;
       bool weakUnseen = weakSeen.add(weakConstant);
       if (unseen != weakUnseen) {
-        evaluator.report(context, messageNonAgnosticConstant);
+        return evaluator.createErrorConstant(
+            context, messageNonAgnosticConstant);
       }
     }
 
@@ -142,9 +160,13 @@
     if (parts.last is List<Constant>) {
       lastPart = parts.last;
     } else {
+      // Probably unreachable.
       parts.add(lastPart = <Constant>[]);
     }
-    lastPart.add(evaluator.ensureIsSubtype(constant, elementType, context));
+    Constant value = evaluator.ensureIsSubtype(constant, elementType, context);
+    if (value is AbortConstant) return value;
+    lastPart.add(value);
+    return null;
   }
 
   @override
@@ -206,61 +228,76 @@
       this.original, this.keyType, this.valueType, this.evaluator);
 
   /// Add a map entry to the constant map being built by this builder
-  void add(MapEntry element) {
+  ///
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant add(MapEntry element) {
     Constant key = evaluator._evaluateSubexpression(element.key);
+    if (key is AbortConstant) return key;
     Constant value = evaluator._evaluateSubexpression(element.value);
+    if (value is AbortConstant) return value;
     if (evaluator.shouldBeUnevaluated) {
       parts.add(evaluator.unevaluated(
           element.key,
           new MapLiteral(
               [new MapEntry(evaluator.extract(key), evaluator.extract(value))],
               isConst: true)));
+      return null;
     } else {
-      addConstant(key, value, element.key, element.value);
+      return addConstant(key, value, element.key, element.value);
     }
   }
 
-  void addSpread(Expression spreadExpression) {
-    Constant spread =
-        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant addSpread(Expression spreadExpression) {
+    Constant constant = evaluator._evaluateSubexpression(spreadExpression);
+    if (constant is AbortConstant) return constant;
+    Constant spread = evaluator.unlower(constant);
     if (evaluator.shouldBeUnevaluated) {
       // Unevaluated spread
       parts.add(spread);
     } else if (spread == evaluator.nullConstant) {
       // Null spread
-      evaluator.report(spreadExpression, messageConstEvalNullValue);
+      return evaluator.createErrorConstant(
+          spreadExpression, messageConstEvalNullValue);
     } else {
       // Fully evaluated spread
       if (spread is MapConstant) {
         for (ConstantMapEntry entry in spread.entries) {
-          addConstant(
+          AbortConstant error = addConstant(
               entry.key, entry.value, spreadExpression, spreadExpression);
+          if (error != null) return error;
         }
       } else {
         // Not map in spread
-        return evaluator.report(
+        return evaluator.createErrorConstant(
             spreadExpression, messageConstEvalNotMapInSpread);
       }
     }
+    return null;
   }
 
-  void addConstant(Constant key, Constant value, TreeNode keyContext,
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant addConstant(Constant key, Constant value, TreeNode keyContext,
       TreeNode valueContext) {
     List<ConstantMapEntry> lastPart;
     if (parts.last is List<ConstantMapEntry>) {
       lastPart = parts.last;
     } else {
+      // Probably unreachable.
       parts.add(lastPart = <ConstantMapEntry>[]);
     }
     if (!evaluator.hasPrimitiveEqual(key)) {
-      evaluator.report(
+      return evaluator.createErrorConstant(
           keyContext,
           templateConstEvalKeyImplementsEqual.withArguments(
               key, evaluator.isNonNullableByDefault));
     }
     bool unseenKey = seenKeys.add(key);
     if (!unseenKey) {
-      evaluator.report(
+      return evaluator.createErrorConstant(
           keyContext,
           templateConstEvalDuplicateKey.withArguments(
               key, evaluator.isNonNullableByDefault));
@@ -269,12 +306,16 @@
       Constant weakKey = evaluator._weakener.visitConstant(key) ?? key;
       bool weakUnseenKey = weakSeenKeys.add(weakKey);
       if (unseenKey != weakUnseenKey) {
-        evaluator.report(keyContext, messageNonAgnosticConstant);
+        return evaluator.createErrorConstant(
+            keyContext, messageNonAgnosticConstant);
       }
     }
-    lastPart.add(new ConstantMapEntry(
-        evaluator.ensureIsSubtype(key, keyType, keyContext),
-        evaluator.ensureIsSubtype(value, valueType, valueContext)));
+    Constant key2 = evaluator.ensureIsSubtype(key, keyType, keyContext);
+    if (key2 is AbortConstant) return key2;
+    Constant value2 = evaluator.ensureIsSubtype(value, valueType, valueContext);
+    if (value2 is AbortConstant) return value2;
+    lastPart.add(new ConstantMapEntry(key2, value2));
+    return null;
   }
 
   Constant build() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index a15f7be..d237dcf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -28,6 +28,7 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/kernel.dart';
 import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/src/printer.dart' show AstPrinter, AstTextStrategy;
 import 'package:kernel/type_algebra.dart';
 import 'package:kernel/type_environment.dart';
 import 'package:kernel/target/targets.dart';
@@ -453,6 +454,8 @@
   @override
   RedirectingFactoryConstructor visitRedirectingFactoryConstructor(
       RedirectingFactoryConstructor node) {
+    // Currently unreachable as the compiler doesn't produce
+    // RedirectingFactoryConstructor.
     StaticTypeContext oldStaticTypeContext = _staticTypeContext;
     _staticTypeContext = new StaticTypeContext(node, typeEnvironment);
     constantEvaluator.withNewEnvironment(() {
@@ -724,9 +727,8 @@
       return constantEvaluator.evaluate(_staticTypeContext, node);
     }
 
-    return constantEvaluator.runInsideContext(treeContext, () {
-      return constantEvaluator.evaluate(_staticTypeContext, node);
-    });
+    return constantEvaluator.evaluate(_staticTypeContext, node,
+        contextNode: treeContext);
   }
 
   Expression makeConstantExpression(Constant constant, Expression node) {
@@ -777,8 +779,6 @@
   final BoolConstant trueConstant = new BoolConstant(true);
   final BoolConstant falseConstant = new BoolConstant(false);
 
-  final List<TreeNode> contextChain = [];
-
   InstanceBuilder instanceBuilder;
   EvaluationEnvironment env;
   Set<Expression> replacementNodes = new Set<Expression>.identity();
@@ -879,63 +879,70 @@
   /// Returns UnevaluatedConstant if the constant could not be evaluated.
   /// If the expression in the UnevaluatedConstant is an InvalidExpression,
   /// an error occurred during constant evaluation.
-  Constant evaluate(StaticTypeContext context, Expression node) {
+  Constant evaluate(StaticTypeContext context, Expression node,
+      {TreeNode contextNode}) {
     _staticTypeContext = context;
     seenUnevaluatedChild = false;
     lazyDepth = 0;
-    try {
-      Constant result = _evaluateSubexpression(node);
-      if (result is UnevaluatedConstant) {
-        if (errorOnUnevaluatedConstant) {
-          return report(node, messageConstEvalUnevaluated);
+    Constant result = _evaluateSubexpression(node);
+    if (result is AbortConstant) {
+      if (result is _AbortDueToErrorConstant) {
+        final Uri uri = getFileUri(result.node);
+        final int fileOffset = getFileOffset(uri, result.node);
+        final LocatedMessage locatedMessageActualError =
+            result.message.withLocation(uri, fileOffset, noLength);
+
+        final List<LocatedMessage> contextMessages = <LocatedMessage>[
+          locatedMessageActualError
+        ];
+        if (result.context != null) contextMessages.addAll(result.context);
+        if (contextNode != null && contextNode != result.node) {
+          final Uri uri = getFileUri(contextNode);
+          final int fileOffset = getFileOffset(uri, contextNode);
+          contextMessages.add(
+              messageConstEvalContext.withLocation(uri, fileOffset, noLength));
+        }
+
+        {
+          final Uri uri = getFileUri(node);
+          final int fileOffset = getFileOffset(uri, node);
+          final LocatedMessage locatedMessage = messageConstEvalStartingPoint
+              .withLocation(uri, fileOffset, noLength);
+          errorReporter.report(locatedMessage, contextMessages);
         }
         return new UnevaluatedConstant(
-            removeRedundantFileUriExpressions(result.expression));
+            new InvalidExpression(result.message.message));
       }
-      return result;
-    } on _AbortDueToError catch (e) {
-      final Uri uri = getFileUri(e.node);
-      final int fileOffset = getFileOffset(uri, e.node);
-      final LocatedMessage locatedMessageActualError =
-          e.message.withLocation(uri, fileOffset, noLength);
-
-      final List<LocatedMessage> contextMessages = <LocatedMessage>[
-        locatedMessageActualError
-      ];
-      if (e.context != null) contextMessages.addAll(e.context);
-      for (final TreeNode node in contextChain) {
-        if (node == e.node) continue;
-        final Uri uri = getFileUri(node);
-        final int fileOffset = getFileOffset(uri, node);
-        contextMessages.add(
-            messageConstEvalContext.withLocation(uri, fileOffset, noLength));
+      if (result is _AbortDueToInvalidExpressionConstant) {
+        InvalidExpression invalid = new InvalidExpression(result.message)
+          ..fileOffset = node.fileOffset;
+        errorReporter.reportInvalidExpression(invalid);
+        return new UnevaluatedConstant(invalid);
       }
-
-      {
-        final Uri uri = getFileUri(node);
-        final int fileOffset = getFileOffset(uri, node);
-        final LocatedMessage locatedMessage = messageConstEvalStartingPoint
-            .withLocation(uri, fileOffset, noLength);
-        errorReporter.report(locatedMessage, contextMessages);
-      }
-      return new UnevaluatedConstant(new InvalidExpression(e.message.message));
-    } on _AbortDueToInvalidExpression catch (e) {
-      InvalidExpression invalid = new InvalidExpression(e.message)
-        ..fileOffset = node.fileOffset;
-      errorReporter.reportInvalidExpression(invalid);
-      return new UnevaluatedConstant(invalid);
+      throw "Unexpected error constant";
     }
+    if (result is UnevaluatedConstant) {
+      if (errorOnUnevaluatedConstant) {
+        return createErrorConstant(node, messageConstEvalUnevaluated);
+      }
+      return new UnevaluatedConstant(
+          removeRedundantFileUriExpressions(result.expression));
+    }
+    return result;
   }
 
-  /// Report an error that has been detected during constant evaluation.
-  Null report(TreeNode node, Message message, {List<LocatedMessage> context}) {
-    throw new _AbortDueToError(node, message, context: context);
+  /// Create an error-constant indicating that an error has been detected during
+  /// constant evaluation.
+  AbortConstant createErrorConstant(TreeNode node, Message message,
+      {List<LocatedMessage> context}) {
+    return new _AbortDueToErrorConstant(node, message, context: context);
   }
 
-  /// Report a construct that should not occur inside a potentially constant
-  /// expression. It is assumed that an error has already been reported.
-  Null reportInvalid(TreeNode node, String message) {
-    throw new _AbortDueToInvalidExpression(node, message);
+  /// Create an error-constant indicating a construct that should not occur
+  /// inside a potentially constant expression.
+  /// It is assumed that an error has already been reported.
+  AbortConstant createInvalidExpressionConstant(TreeNode node, String message) {
+    return new _AbortDueToInvalidExpressionConstant(node, message);
   }
 
   /// Produce an unevaluated constant node for an expression.
@@ -1005,9 +1012,26 @@
   }
 
   /// Evaluate [node] and possibly cache the evaluation result.
-  /// @throws _AbortDueToError or _AbortDueToInvalidExpression if expression
-  /// can't be evaluated.
+  ///
+  /// Returns [_AbortDueToErrorConstant] or
+  /// [_AbortDueToInvalidExpressionConstant] (both of which is an
+  /// [AbortConstant]) if the expression can't be evaluated.
+  /// As such the return value should be checked (e.g. `is AbortConstant`)
+  /// before further use.
   Constant _evaluateSubexpression(Expression node) {
+    if (node is ConstantExpression) {
+      if (node.constant is! UnevaluatedConstant) {
+        // ConstantExpressions just pointing to an actual constant can be
+        // short-circuited. Note that it's accepted instead of just returned to
+        // get canonicalization.
+        return node.accept(this);
+      }
+    } else if (node is BasicLiteral) {
+      // Basic literals (string literals, int literals, double literals,
+      // bool literals and null literals) can be short-circuited too.
+      return node.accept(this);
+    }
+
     bool wasUnevaluated = seenUnevaluatedChild;
     seenUnevaluatedChild = false;
     Constant result;
@@ -1015,18 +1039,43 @@
       // We only try to evaluate the same [node] *once* within an empty
       // environment.
       if (nodeCache.containsKey(node)) {
-        result = nodeCache[node] ?? report(node, messageConstEvalCircularity);
+        result = nodeCache[node];
+        if (result == null) {
+          // [null] is a sentinel value only used when still evaluating the same
+          // node.
+          return createErrorConstant(node, messageConstEvalCircularity);
+        }
       } else {
         nodeCache[node] = null;
-        try {
-          result = nodeCache[node] = node.accept(this);
-        } catch (e) {
+        result = node.accept(this);
+        if (result is AbortConstant) {
           nodeCache.remove(node);
-          rethrow;
+          return result;
+        } else {
+          nodeCache[node] = result;
         }
       }
     } else {
+      bool sentinelInserted = false;
+      if (nodeCache.containsKey(node)) {
+        if (nodeCache[node] == null) {
+          // recursive call
+          return createErrorConstant(node, messageConstEvalCircularity);
+        }
+        // else we've seen the node before and come to a result -> we won't
+        // go into an infinite loop here either.
+      } else {
+        // We haven't seen this node before. Risk of loop.
+        nodeCache[node] = null;
+        sentinelInserted = true;
+      }
       result = node.accept(this);
+      if (sentinelInserted) {
+        nodeCache.remove(node);
+      }
+      if (result is AbortConstant) {
+        return result;
+      }
     }
     seenUnevaluatedChild = wasUnevaluated || result is UnevaluatedConstant;
     return result;
@@ -1037,37 +1086,11 @@
     return _evaluateSubexpression(node);
   }
 
-  T runInsideContext<T>(TreeNode node, T fun()) {
-    try {
-      pushContext(node);
-      return fun();
-    } finally {
-      popContext(node);
-    }
-  }
-
-  T runInsideContextIfNoContext<T>(TreeNode node, T fun()) {
-    if (contextChain.isEmpty) {
-      return runInsideContext(node, fun);
-    } else {
-      return fun();
-    }
-  }
-
-  void pushContext(TreeNode contextNode) {
-    contextChain.add(contextNode);
-  }
-
-  void popContext(TreeNode contextNode) {
-    assert(contextChain.last == contextNode);
-    contextChain.length = contextChain.length - 1;
-  }
-
   @override
   Constant defaultTreeNode(Node node) {
     // Only a subset of the expression language is valid for constant
     // evaluation.
-    return reportInvalid(
+    return createInvalidExpressionConstant(
         node, 'Constant evaluation has no support for ${node.runtimeType}!');
   }
 
@@ -1103,7 +1126,14 @@
 
   @override
   Constant visitTypeLiteral(TypeLiteral node) {
-    final DartType type = evaluateDartType(node, node.type);
+    final DartType type = _evaluateDartType(node, node.type);
+    if (type == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(type != null);
     return canonicalize(new TypeLiteralConstant(type));
   }
 
@@ -1112,9 +1142,8 @@
     Constant constant = node.constant;
     Constant result = constant;
     if (constant is UnevaluatedConstant) {
-      result = runInsideContext(constant.expression, () {
-        return _evaluateSubexpression(constant.expression);
-      });
+      result = _evaluateSubexpression(constant.expression);
+      if (result is AbortConstant) return result;
     }
     // If there were already constants in the AST then we make sure we
     // re-canonicalize them.  After running the transformer we will therefore
@@ -1126,12 +1155,13 @@
   @override
   Constant visitListLiteral(ListLiteral node) {
     if (!node.isConst) {
-      return reportInvalid(node, "Non-constant list literal");
+      return createInvalidExpressionConstant(node, "Non-constant list literal");
     }
     final ListConstantBuilder builder =
         new ListConstantBuilder(node, convertType(node.typeArgument), this);
     for (Expression element in node.expressions) {
-      builder.add(element);
+      AbortConstant error = builder.add(element);
+      if (error != null) return error;
     }
     return builder.build();
   }
@@ -1141,7 +1171,8 @@
     final ListConstantBuilder builder =
         new ListConstantBuilder(node, convertType(node.typeArgument), this);
     for (Expression list in node.lists) {
-      builder.addSpread(list);
+      AbortConstant error = builder.addSpread(list);
+      if (error != null) return error;
     }
     return builder.build();
   }
@@ -1149,12 +1180,13 @@
   @override
   Constant visitSetLiteral(SetLiteral node) {
     if (!node.isConst) {
-      return reportInvalid(node, "Non-constant set literal");
+      return createInvalidExpressionConstant(node, "Non-constant set literal");
     }
     final SetConstantBuilder builder =
         new SetConstantBuilder(node, convertType(node.typeArgument), this);
     for (Expression element in node.expressions) {
-      builder.add(element);
+      AbortConstant error = builder.add(element);
+      if (error != null) return error;
     }
     return builder.build();
   }
@@ -1164,7 +1196,8 @@
     final SetConstantBuilder builder =
         new SetConstantBuilder(node, convertType(node.typeArgument), this);
     for (Expression set_ in node.sets) {
-      builder.addSpread(set_);
+      AbortConstant error = builder.addSpread(set_);
+      if (error != null) return error;
     }
     return builder.build();
   }
@@ -1172,12 +1205,13 @@
   @override
   Constant visitMapLiteral(MapLiteral node) {
     if (!node.isConst) {
-      return reportInvalid(node, "Non-constant map literal");
+      return createInvalidExpressionConstant(node, "Non-constant map literal");
     }
     final MapConstantBuilder builder = new MapConstantBuilder(
         node, convertType(node.keyType), convertType(node.valueType), this);
     for (MapEntry element in node.entries) {
-      builder.add(element);
+      AbortConstant error = builder.add(element);
+      if (error != null) return error;
     }
     return builder.build();
   }
@@ -1187,35 +1221,53 @@
     final MapConstantBuilder builder = new MapConstantBuilder(
         node, convertType(node.keyType), convertType(node.valueType), this);
     for (Expression map in node.maps) {
-      builder.addSpread(map);
+      AbortConstant error = builder.addSpread(map);
+      if (error != null) return error;
     }
     return builder.build();
   }
 
   @override
   Constant visitFunctionExpression(FunctionExpression node) {
-    return reportInvalid(node, "Function literal");
+    return createInvalidExpressionConstant(node, "Function literal");
   }
 
   @override
   Constant visitConstructorInvocation(ConstructorInvocation node) {
     if (!node.isConst) {
-      return reportInvalid(
+      return createInvalidExpressionConstant(
           node, 'Non-constant constructor invocation "$node".');
     }
 
     final Constructor constructor = node.target;
-    checkConstructorConst(node, constructor);
+    AbortConstant error = checkConstructorConst(node, constructor);
+    if (error != null) return error;
 
     final Class klass = constructor.enclosingClass;
     if (klass.isAbstract) {
-      return reportInvalid(
+      // Probably unreachable.
+      return createInvalidExpressionConstant(
           node, 'Constructor "$node" belongs to abstract class "${klass}".');
     }
 
     final List<Constant> positionals =
-        evaluatePositionalArguments(node.arguments);
-    final Map<String, Constant> named = evaluateNamedArguments(node.arguments);
+        _evaluatePositionalArguments(node.arguments);
+    if (positionals == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(positionals != null);
+
+    final Map<String, Constant> named = _evaluateNamedArguments(node.arguments);
+    if (named == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(named != null);
 
     bool isSymbol = klass == coreTypes.internalSymbolClass;
     if (isSymbol && shouldBeUnevaluated) {
@@ -1234,53 +1286,67 @@
       if (nameValue is StringConstant && isValidSymbolName(nameValue.value)) {
         return canonicalize(new SymbolConstant(nameValue.value, null));
       }
-      return report(
+      return createErrorConstant(
           node.arguments.positional.first,
           templateConstEvalInvalidSymbolName.withArguments(
               nameValue, isNonNullableByDefault));
     }
 
-    final List<DartType> typeArguments =
-        convertTypes(evaluateTypeArguments(node, node.arguments));
+    List<DartType> types = _evaluateTypeArguments(node, node.arguments);
+    if (types == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(types != null);
+
+    final List<DartType> typeArguments = convertTypes(types);
 
     // Fill in any missing type arguments with "dynamic".
     for (int i = typeArguments.length; i < klass.typeParameters.length; i++) {
+      // Probably unreachable.
       typeArguments.add(const DynamicType());
     }
 
     // Start building a new instance.
     return withNewInstanceBuilder(klass, typeArguments, () {
-      return runInsideContextIfNoContext(node, () {
-        // "Run" the constructor (and any super constructor calls), which will
-        // initialize the fields of the new instance.
-        if (shouldBeUnevaluated) {
-          enterLazy();
-          handleConstructorInvocation(
-              constructor, typeArguments, positionals, named);
-          leaveLazy();
-          return unevaluated(node, instanceBuilder.buildUnevaluatedInstance());
-        }
-        handleConstructorInvocation(
+      // "Run" the constructor (and any super constructor calls), which will
+      // initialize the fields of the new instance.
+      if (shouldBeUnevaluated) {
+        enterLazy();
+        AbortConstant error = handleConstructorInvocation(
             constructor, typeArguments, positionals, named);
-        if (shouldBeUnevaluated) {
-          return unevaluated(node, instanceBuilder.buildUnevaluatedInstance());
-        }
-        return canonicalize(instanceBuilder.buildInstance());
-      });
+        if (error != null) return error;
+        leaveLazy();
+        return unevaluated(node, instanceBuilder.buildUnevaluatedInstance());
+      }
+      AbortConstant error = handleConstructorInvocation(
+          constructor, typeArguments, positionals, named);
+      if (error != null) return error;
+      if (shouldBeUnevaluated) {
+        return unevaluated(node, instanceBuilder.buildUnevaluatedInstance());
+      }
+      return canonicalize(instanceBuilder.buildInstance());
     });
   }
 
-  void checkConstructorConst(TreeNode node, Constructor constructor) {
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant checkConstructorConst(TreeNode node, Constructor constructor) {
     if (!constructor.isConst) {
-      reportInvalid(node, 'Non-const constructor invocation.');
+      return createInvalidExpressionConstant(
+          node, 'Non-const constructor invocation.');
     }
     if (constructor.function.body != null &&
         constructor.function.body is! EmptyStatement) {
-      reportInvalid(
+      // Probably unreachable.
+      return createInvalidExpressionConstant(
           node,
           'Constructor "$node" has non-trivial body '
           '"${constructor.function.body.runtimeType}".');
     }
+    return null;
   }
 
   @override
@@ -1288,21 +1354,36 @@
     return withNewInstanceBuilder(
         node.classNode, convertTypes(node.typeArguments), () {
       for (AssertStatement statement in node.asserts) {
-        checkAssert(statement);
+        AbortConstant error = checkAssert(statement);
+        if (error != null) return error;
       }
+      AbortConstant error;
       node.fieldValues.forEach((Reference fieldRef, Expression value) {
-        instanceBuilder.setFieldValue(
-            fieldRef.asField, _evaluateSubexpression(value));
-      });
-      node.unusedArguments.forEach((Expression value) {
+        if (error != null) return;
         Constant constant = _evaluateSubexpression(value);
+        if (constant is AbortConstant) {
+          error ??= constant;
+          return;
+        }
+        instanceBuilder.setFieldValue(fieldRef.asField, constant);
+      });
+      if (error != null) return error;
+      node.unusedArguments.forEach((Expression value) {
+        if (error != null) return;
+        Constant constant = _evaluateSubexpression(value);
+        if (constant is AbortConstant) {
+          error ??= constant;
+          return;
+        }
         if (constant is UnevaluatedConstant) {
           instanceBuilder.unusedArguments.add(extract(constant));
         }
       });
+      if (error != null) return error;
       if (shouldBeUnevaluated) {
         return unevaluated(node, instanceBuilder.buildUnevaluatedInstance());
       }
+      // We can get here when re-evaluating a previously unevaluated constant.
       return canonicalize(instanceBuilder.buildInstance());
     });
   }
@@ -1432,95 +1513,159 @@
         !nonUsableKeywords.contains(name);
   }
 
-  void handleConstructorInvocation(
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant handleConstructorInvocation(
       Constructor constructor,
       List<DartType> typeArguments,
       List<Constant> positionalArguments,
       Map<String, Constant> namedArguments) {
-    return runInsideContext(constructor, () {
-      return withNewEnvironment(() {
-        final Class klass = constructor.enclosingClass;
-        final FunctionNode function = constructor.function;
+    return withNewEnvironment(() {
+      final Class klass = constructor.enclosingClass;
+      final FunctionNode function = constructor.function;
 
-        // We simulate now the constructor invocation.
+      // We simulate now the constructor invocation.
 
-        // Step 1) Map type arguments and normal arguments from caller to
-        //         callee.
-        for (int i = 0; i < klass.typeParameters.length; i++) {
-          env.addTypeParameterValue(klass.typeParameters[i], typeArguments[i]);
-        }
-        for (int i = 0; i < function.positionalParameters.length; i++) {
-          final VariableDeclaration parameter =
-              function.positionalParameters[i];
-          final Constant value = (i < positionalArguments.length)
-              ? positionalArguments[i]
-              : _evaluateNullableSubexpression(parameter.initializer);
-          env.addVariableValue(parameter, value);
-        }
-        for (final VariableDeclaration parameter in function.namedParameters) {
-          final Constant value = namedArguments[parameter.name] ??
-              _evaluateNullableSubexpression(parameter.initializer);
-          env.addVariableValue(parameter, value);
-        }
+      // Step 1) Map type arguments and normal arguments from caller to
+      //         callee.
+      for (int i = 0; i < klass.typeParameters.length; i++) {
+        env.addTypeParameterValue(klass.typeParameters[i], typeArguments[i]);
+      }
+      for (int i = 0; i < function.positionalParameters.length; i++) {
+        final VariableDeclaration parameter = function.positionalParameters[i];
+        final Constant value = (i < positionalArguments.length)
+            ? positionalArguments[i]
+            // TODO(johnniwinther): This should call [_evaluateSubexpression].
+            : _evaluateNullableSubexpression(parameter.initializer);
+        if (value is AbortConstant) return value;
+        env.addVariableValue(parameter, value);
+      }
+      for (final VariableDeclaration parameter in function.namedParameters) {
+        final Constant value = namedArguments[parameter.name] ??
+            // TODO(johnniwinther): This should call [_evaluateSubexpression].
+            _evaluateNullableSubexpression(parameter.initializer);
+        if (value is AbortConstant) return value;
+        env.addVariableValue(parameter, value);
+      }
 
-        // Step 2) Run all initializers (including super calls) with environment
-        //         setup.
-        for (final Field field in klass.fields) {
-          if (!field.isStatic) {
-            instanceBuilder.setFieldValue(
-                field, _evaluateNullableSubexpression(field.initializer));
+      // Step 2) Run all initializers (including super calls) with environment
+      //         setup.
+      for (final Field field in klass.fields) {
+        if (!field.isStatic) {
+          Constant constant = _evaluateNullableSubexpression(field.initializer);
+          if (constant is AbortConstant) return constant;
+          instanceBuilder.setFieldValue(field, constant);
+        }
+      }
+      for (final Initializer init in constructor.initializers) {
+        if (init is FieldInitializer) {
+          Constant constant = _evaluateSubexpression(init.value);
+          if (constant is AbortConstant) return constant;
+          instanceBuilder.setFieldValue(init.field, constant);
+        } else if (init is LocalInitializer) {
+          final VariableDeclaration variable = init.variable;
+          Constant constant = _evaluateSubexpression(variable.initializer);
+          if (constant is AbortConstant) return constant;
+          env.addVariableValue(variable, constant);
+        } else if (init is SuperInitializer) {
+          AbortConstant error = checkConstructorConst(init, constructor);
+          if (error != null) return error;
+          List<DartType> types = _evaluateSuperTypeArguments(
+              init, constructor.enclosingClass.supertype);
+          if (types == null && _gotError != null) {
+            AbortConstant error = _gotError;
+            _gotError = null;
+            return error;
           }
-        }
-        for (final Initializer init in constructor.initializers) {
-          if (init is FieldInitializer) {
-            instanceBuilder.setFieldValue(
-                init.field, _evaluateSubexpression(init.value));
-          } else if (init is LocalInitializer) {
-            final VariableDeclaration variable = init.variable;
-            env.addVariableValue(
-                variable, _evaluateSubexpression(variable.initializer));
-          } else if (init is SuperInitializer) {
-            checkConstructorConst(init, constructor);
-            handleConstructorInvocation(
-                init.target,
-                evaluateSuperTypeArguments(
-                    init, constructor.enclosingClass.supertype),
-                evaluatePositionalArguments(init.arguments),
-                evaluateNamedArguments(init.arguments));
-          } else if (init is RedirectingInitializer) {
-            // Since a redirecting constructor targets a constructor of the same
-            // class, we pass the same [typeArguments].
-            checkConstructorConst(init, constructor);
-            handleConstructorInvocation(
-                init.target,
-                typeArguments,
-                evaluatePositionalArguments(init.arguments),
-                evaluateNamedArguments(init.arguments));
-          } else if (init is AssertInitializer) {
-            checkAssert(init.statement);
-          } else {
-            return reportInvalid(
-                constructor,
-                'No support for handling initializer of type '
-                '"${init.runtimeType}".');
-          }
-        }
+          assert(_gotError == null);
+          assert(types != null);
 
-        for (UnevaluatedConstant constant in env.unevaluatedUnreadConstants) {
-          instanceBuilder.unusedArguments.add(extract(constant));
+          List<Constant> positionalArguments =
+              _evaluatePositionalArguments(init.arguments);
+          if (positionalArguments == null && _gotError != null) {
+            AbortConstant error = _gotError;
+            _gotError = null;
+            return error;
+          }
+          assert(_gotError == null);
+          assert(positionalArguments != null);
+          Map<String, Constant> namedArguments =
+              _evaluateNamedArguments(init.arguments);
+          if (namedArguments == null && _gotError != null) {
+            AbortConstant error = _gotError;
+            _gotError = null;
+            return error;
+          }
+          assert(_gotError == null);
+          assert(namedArguments != null);
+          error = handleConstructorInvocation(
+              init.target, types, positionalArguments, namedArguments);
+          if (error != null) return error;
+        } else if (init is RedirectingInitializer) {
+          // Since a redirecting constructor targets a constructor of the same
+          // class, we pass the same [typeArguments].
+          AbortConstant error = checkConstructorConst(init, constructor);
+          if (error != null) return error;
+          List<Constant> positionalArguments =
+              _evaluatePositionalArguments(init.arguments);
+          if (positionalArguments == null && _gotError != null) {
+            AbortConstant error = _gotError;
+            _gotError = null;
+            return error;
+          }
+          assert(_gotError == null);
+          assert(positionalArguments != null);
+
+          Map<String, Constant> namedArguments =
+              _evaluateNamedArguments(init.arguments);
+          if (namedArguments == null && _gotError != null) {
+            AbortConstant error = _gotError;
+            _gotError = null;
+            return error;
+          }
+          assert(_gotError == null);
+          assert(namedArguments != null);
+
+          error = handleConstructorInvocation(
+              init.target, typeArguments, positionalArguments, namedArguments);
+          if (error != null) return error;
+        } else if (init is AssertInitializer) {
+          AbortConstant error = checkAssert(init.statement);
+          if (error != null) return error;
+        } else {
+          // InvalidInitializer or new Initializers.
+          // Probably unreachable. InvalidInitializer is (currently) only
+          // created for classes with no constructors that doesn't have a
+          // super that takes no arguments. It thus cannot be const.
+          // Explicit constructors with incorrect super calls will get a
+          // ShadowInvalidInitializer which is actually a LocalInitializer.
+          return createInvalidExpressionConstant(
+              constructor,
+              'No support for handling initializer of type '
+              '"${init.runtimeType}".');
         }
-      });
+      }
+
+      for (UnevaluatedConstant constant in env.unevaluatedUnreadConstants) {
+        instanceBuilder.unusedArguments.add(extract(constant));
+      }
+      return null;
     });
   }
 
-  void checkAssert(AssertStatement statement) {
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant checkAssert(AssertStatement statement) {
     final Constant condition = _evaluateSubexpression(statement.condition);
+    if (condition is AbortConstant) return condition;
 
     if (shouldBeUnevaluated) {
       Expression message = null;
       if (statement.message != null) {
         enterLazy();
-        message = extract(_evaluateSubexpression(statement.message));
+        Constant constant = _evaluateSubexpression(statement.message);
+        if (constant is AbortConstant) return constant;
+        message = extract(constant);
         leaveLazy();
       }
       instanceBuilder.asserts.add(new AssertStatement(extract(condition),
@@ -1530,21 +1675,23 @@
     } else if (condition is BoolConstant) {
       if (!condition.value) {
         if (statement.message == null) {
-          report(statement.condition, messageConstEvalFailedAssertion);
+          return createErrorConstant(
+              statement.condition, messageConstEvalFailedAssertion);
         }
         final Constant message = _evaluateSubexpression(statement.message);
+        if (message is AbortConstant) return message;
         if (shouldBeUnevaluated) {
           instanceBuilder.asserts.add(new AssertStatement(extract(condition),
               message: extract(message),
               conditionStartOffset: statement.conditionStartOffset,
               conditionEndOffset: statement.conditionEndOffset));
         } else if (message is StringConstant) {
-          report(
+          return createErrorConstant(
               statement.condition,
               templateConstEvalFailedAssertionWithMessage
                   .withArguments(message.value));
         } else {
-          report(
+          return createErrorConstant(
               statement.message,
               templateConstEvalInvalidType.withArguments(
                   message,
@@ -1554,7 +1701,7 @@
         }
       }
     } else {
-      report(
+      return createErrorConstant(
           statement.condition,
           templateConstEvalInvalidType.withArguments(
               condition,
@@ -1562,21 +1709,34 @@
               condition.getType(_staticTypeContext),
               isNonNullableByDefault));
     }
+
+    return null;
   }
 
   @override
   Constant visitInvalidExpression(InvalidExpression node) {
-    return reportInvalid(node, node.message);
+    return createInvalidExpressionConstant(node, node.message);
   }
 
   @override
   Constant visitMethodInvocation(MethodInvocation node) {
     // We have no support for generic method invocation atm.
-    assert(node.arguments.named.isEmpty);
+    if (node.arguments.named.isNotEmpty) {
+      return createInvalidExpressionConstant(node, "generic method invocation");
+    }
 
     final Constant receiver = _evaluateSubexpression(node.receiver);
+    if (receiver is AbortConstant) return receiver;
     final List<Constant> arguments =
-        evaluatePositionalArguments(node.arguments);
+        _evaluatePositionalArguments(node.arguments);
+
+    if (arguments == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(arguments != null);
 
     if (shouldBeUnevaluated) {
       return unevaluated(
@@ -1585,7 +1745,7 @@
               unevaluatedArguments(arguments, {}, node.arguments.types)));
     }
 
-    final String op = node.name.name;
+    final String op = node.name.text;
 
     // Handle == and != first (it's common between all types). Since `a != b` is
     // parsed as `!(a == b)` it is handled implicitly through ==.
@@ -1603,7 +1763,7 @@
         return doubleSpecialCases(receiver, right) ??
             makeBoolConstant(receiver == right);
       } else {
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidEqualsOperandType.withArguments(receiver,
                 receiver.getType(_staticTypeContext), isNonNullableByDefault));
@@ -1620,7 +1780,7 @@
               return canonicalize(
                   new StringConstant(receiver.value + other.value));
             }
-            return report(
+            return createErrorConstant(
                 node,
                 templateConstEvalInvalidBinaryOperandType.withArguments(
                     '+',
@@ -1641,7 +1801,7 @@
         } else if (other is DoubleConstant) {
           if ((op == '|' || op == '&' || op == '^') ||
               (op == '<<' || op == '>>' || op == '>>>')) {
-            return report(
+            return createErrorConstant(
                 node,
                 templateConstEvalInvalidBinaryOperandType.withArguments(
                     op,
@@ -1654,7 +1814,7 @@
           return canonicalize(evaluateBinaryNumericOperation(
               op, receiverValue, other.value, node));
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
@@ -1666,7 +1826,7 @@
     } else if (receiver is DoubleConstant) {
       if ((op == '|' || op == '&' || op == '^') ||
           (op == '<<' || op == '>>' || op == '>>>')) {
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
@@ -1688,7 +1848,7 @@
           return canonicalize(
               evaluateBinaryNumericOperation(op, receiver.value, value, node));
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidBinaryOperandType.withArguments(
                 op,
@@ -1715,10 +1875,10 @@
         }
       }
     } else if (receiver is NullConstant) {
-      return report(node, messageConstEvalNullValue);
+      return createErrorConstant(node, messageConstEvalNullValue);
     }
 
-    return report(
+    return createErrorConstant(
         node,
         templateConstEvalInvalidMethodInvocation.withArguments(
             op, receiver, isNonNullableByDefault));
@@ -1727,73 +1887,83 @@
   @override
   Constant visitLogicalExpression(LogicalExpression node) {
     final Constant left = _evaluateSubexpression(node.left);
+    if (left is AbortConstant) return left;
     if (shouldBeUnevaluated) {
       enterLazy();
       Constant right = _evaluateSubexpression(node.right);
+      if (right is AbortConstant) return right;
       leaveLazy();
-      return unevaluated(node,
-          new LogicalExpression(extract(left), node.operator, extract(right)));
+      return unevaluated(
+          node,
+          new LogicalExpression(
+              extract(left), node.operatorEnum, extract(right)));
     }
-    switch (node.operator) {
-      case '||':
+    switch (node.operatorEnum) {
+      case LogicalExpressionOperator.OR:
         if (left is BoolConstant) {
           if (left.value) return trueConstant;
 
           final Constant right = _evaluateSubexpression(node.right);
+          if (right is AbortConstant) return right;
           if (right is BoolConstant || right is UnevaluatedConstant) {
             return right;
           }
 
-          return report(
+          return createErrorConstant(
               node,
               templateConstEvalInvalidBinaryOperandType.withArguments(
-                  node.operator,
+                  logicalExpressionOperatorToString(node.operatorEnum),
                   left,
                   typeEnvironment.coreTypes.boolLegacyRawType,
                   right.getType(_staticTypeContext),
                   isNonNullableByDefault));
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidMethodInvocation.withArguments(
-                node.operator, left, isNonNullableByDefault));
-      case '&&':
+                logicalExpressionOperatorToString(node.operatorEnum),
+                left,
+                isNonNullableByDefault));
+      case LogicalExpressionOperator.AND:
         if (left is BoolConstant) {
           if (!left.value) return falseConstant;
 
           final Constant right = _evaluateSubexpression(node.right);
+          if (right is AbortConstant) return right;
           if (right is BoolConstant || right is UnevaluatedConstant) {
             return right;
           }
 
-          return report(
+          return createErrorConstant(
               node,
               templateConstEvalInvalidBinaryOperandType.withArguments(
-                  node.operator,
+                  logicalExpressionOperatorToString(node.operatorEnum),
                   left,
                   typeEnvironment.coreTypes.boolLegacyRawType,
                   right.getType(_staticTypeContext),
                   isNonNullableByDefault));
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidMethodInvocation.withArguments(
-                node.operator, left, isNonNullableByDefault));
-      case '??':
-        return (left is! NullConstant)
-            ? left
-            : _evaluateSubexpression(node.right);
+                logicalExpressionOperatorToString(node.operatorEnum),
+                left,
+                isNonNullableByDefault));
       default:
-        return report(
+        // Probably unreachable.
+        return createErrorConstant(
             node,
             templateConstEvalInvalidMethodInvocation.withArguments(
-                node.operator, left, isNonNullableByDefault));
+                logicalExpressionOperatorToString(node.operatorEnum),
+                left,
+                isNonNullableByDefault));
     }
   }
 
   @override
   Constant visitConditionalExpression(ConditionalExpression node) {
     final Constant condition = _evaluateSubexpression(node.condition);
+    if (condition is AbortConstant) return condition;
     if (condition == trueConstant) {
       return _evaluateSubexpression(node.then);
     } else if (condition == falseConstant) {
@@ -1801,14 +1971,16 @@
     } else if (shouldBeUnevaluated) {
       enterLazy();
       Constant then = _evaluateSubexpression(node.then);
+      if (then is AbortConstant) return then;
       Constant otherwise = _evaluateSubexpression(node.otherwise);
+      if (otherwise is AbortConstant) return otherwise;
       leaveLazy();
       return unevaluated(
           node,
           new ConditionalExpression(extract(condition), extract(then),
               extract(otherwise), node.staticType));
     } else {
-      return report(
+      return createErrorConstant(
           node.condition,
           templateConstEvalInvalidType.withArguments(
               condition,
@@ -1821,38 +1993,47 @@
   @override
   Constant visitPropertyGet(PropertyGet node) {
     if (node.receiver is ThisExpression) {
+      // Probably unreachable unless trying to evaluate non-const stuff as
+      // const.
       // Access "this" during instance creation.
       if (instanceBuilder == null) {
-        return report(node, messageNotAConstantExpression);
+        return createErrorConstant(node, messageNotAConstantExpression);
       }
+
       for (final Field field in instanceBuilder.fields.keys) {
         if (field.name == node.name) {
           return instanceBuilder.fields[field];
         }
       }
-      return reportInvalid(node,
+
+      // Meant as a "stable backstop for situations where Fasta fails to
+      // rewrite various erroneous constructs into invalid expressions".
+      // Probably unreachable.
+      return createInvalidExpressionConstant(node,
           'Could not evaluate field get ${node.name} on incomplete instance');
     }
 
     final Constant receiver = _evaluateSubexpression(node.receiver);
-    if (receiver is StringConstant && node.name.name == 'length') {
+    if (receiver is AbortConstant) return receiver;
+    if (receiver is StringConstant && node.name.text == 'length') {
       return canonicalize(intFolder.makeIntConstant(receiver.value.length));
     } else if (shouldBeUnevaluated) {
       return unevaluated(node,
           new PropertyGet(extract(receiver), node.name, node.interfaceTarget));
     } else if (receiver is NullConstant) {
-      return report(node, messageConstEvalNullValue);
+      return createErrorConstant(node, messageConstEvalNullValue);
     }
-    return report(
+    return createErrorConstant(
         node,
         templateConstEvalInvalidPropertyGet.withArguments(
-            node.name.name, receiver, isNonNullableByDefault));
+            node.name.text, receiver, isNonNullableByDefault));
   }
 
   @override
   Constant visitLet(Let node) {
-    env.addVariableValue(
-        node.variable, _evaluateSubexpression(node.variable.initializer));
+    Constant value = _evaluateSubexpression(node.variable.initializer);
+    if (value is AbortConstant) return value;
+    env.addVariableValue(node.variable, value);
     return _evaluateSubexpression(node.body);
   }
 
@@ -1867,7 +2048,7 @@
     final VariableDeclaration variable = node.variable;
     if (variable.parent is Let || _isFormalParameter(variable)) {
       return env.lookupVariable(node.variable) ??
-          report(
+          createErrorConstant(
               node,
               templateConstEvalNonConstantVariableGet
                   .withArguments(variable.name));
@@ -1875,7 +2056,8 @@
     if (variable.isConst) {
       return _evaluateSubexpression(variable.initializer);
     }
-    return reportInvalid(node, 'Variable get of a non-const variable.');
+    return createInvalidExpressionConstant(
+        node, 'Variable get of a non-const variable.');
   }
 
   /// Computes the constant for [expression] defined in the context of [member].
@@ -1886,15 +2068,14 @@
   Constant _evaluateExpressionInContext(Member member, Expression expression) {
     StaticTypeContext oldStaticTypeContext = _staticTypeContext;
     _staticTypeContext = new StaticTypeContext(member, typeEnvironment);
-    Constant constant = runInsideContext(member, () {
-      Constant constant = _evaluateSubexpression(expression);
+    Constant constant = _evaluateSubexpression(expression);
+    if (constant is! AbortConstant) {
       if (_staticTypeContext.nonNullableByDefaultCompiledMode ==
               NonNullableByDefaultCompiledMode.Agnostic &&
           evaluationMode == EvaluationMode.weak) {
         constant = _weakener.visitConstant(constant) ?? constant;
       }
-      return constant;
-    });
+    }
     _staticTypeContext = oldStaticTypeContext;
     return constant;
   }
@@ -1907,22 +2088,21 @@
         if (target.isConst) {
           return _evaluateExpressionInContext(target, target.initializer);
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidStaticInvocation
-                .withArguments(target.name.name));
+                .withArguments(target.name.text));
       } else if (target is Procedure) {
         if (target.kind == ProcedureKind.Method) {
           return canonicalize(new TearOffConstant(target));
         }
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidStaticInvocation
-                .withArguments(target.name.name));
+                .withArguments(target.name.text));
       } else {
-        reportInvalid(
+        return createInvalidExpressionConstant(
             node, 'No support for ${target.runtimeType} in a static-get.');
-        return null;
       }
     });
   }
@@ -1932,6 +2112,7 @@
     final List<Object> concatenated = <Object>[new StringBuffer()];
     for (int i = 0; i < node.expressions.length; i++) {
       Constant constant = _evaluateSubexpression(node.expressions[i]);
+      if (constant is AbortConstant) return constant;
       if (constant is PrimitiveConstant<Object>) {
         String value;
         if (constant is DoubleConstant && intFolder.isInt(constant)) {
@@ -1951,7 +2132,7 @@
         // error reporting till later.
         concatenated.add(constant);
       } else {
-        return report(
+        return createErrorConstant(
             node,
             templateConstEvalInvalidStringInterpolationOperand.withArguments(
                 constant, isNonNullableByDefault));
@@ -1981,7 +2162,10 @@
         .singleWhere((v) => v.name == 'defaultValue');
     return variable.initializer != null
         ? _evaluateExpressionInContext(target, variable.initializer)
-        : nullConstant;
+        :
+        // Not reachable unless a defaultValue in fromEnvironment in dart:core
+        // becomes null.
+        nullConstant;
   }
 
   Constant _handleFromEnvironment(
@@ -2000,6 +2184,7 @@
         } else if (defaultValue is NullConstant) {
           boolConstant = nullConstant;
         } else {
+          // Probably unreachable.
           boolConstant = falseConstant;
         }
       } else {
@@ -2037,6 +2222,8 @@
       }
       return stringConstant;
     }
+    // Unreachable until fromEnvironment is added to other classes in dart:core
+    // than bool, int and String.
     throw new UnsupportedError(
         'Unexpected fromEnvironment constructor: $target');
   }
@@ -2051,8 +2238,24 @@
   Constant visitStaticInvocation(StaticInvocation node) {
     final Procedure target = node.target;
     final Arguments arguments = node.arguments;
-    final List<Constant> positionals = evaluatePositionalArguments(arguments);
-    final Map<String, Constant> named = evaluateNamedArguments(arguments);
+    final List<Constant> positionals = _evaluatePositionalArguments(arguments);
+    if (positionals == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(positionals != null);
+
+    final Map<String, Constant> named = _evaluateNamedArguments(arguments);
+    if (named == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(named != null);
+
     if (shouldBeUnevaluated) {
       return unevaluated(
           node,
@@ -2064,19 +2267,19 @@
       if (target.isConst &&
           target.enclosingLibrary == coreTypes.coreLibrary &&
           positionals.length == 1 &&
-          (target.name.name == "fromEnvironment" ||
-              target.name.name == "hasEnvironment")) {
+          (target.name.text == "fromEnvironment" ||
+              target.name.text == "hasEnvironment")) {
         if (environmentDefines != null) {
           // Evaluate environment constant.
           Constant name = positionals.single;
           if (name is StringConstant) {
-            if (target.name.name == "fromEnvironment") {
+            if (target.name.text == "fromEnvironment") {
               return _handleFromEnvironment(target, name, named);
             } else {
               return _handleHasEnvironment(name);
             }
           } else if (name is NullConstant) {
-            return report(node, messageConstEvalNullValue);
+            return createErrorConstant(node, messageConstEvalNullValue);
           }
         } else {
           // Leave environment constant unevaluated.
@@ -2087,7 +2290,7 @@
                   isConst: true));
         }
       }
-    } else if (target.name.name == 'identical') {
+    } else if (target.name.text == 'identical') {
       // Ensure the "identical()" function comes from dart:core.
       final TreeNode parent = target.parent;
       if (parent is Library && parent == coreTypes.coreLibrary) {
@@ -2105,7 +2308,7 @@
               Constant weakResult = makeBoolConstant(
                   identical(weakLeft ?? left, weakRight ?? right));
               if (!identical(result, weakResult)) {
-                report(node, messageNonAgnosticConstant);
+                return createErrorConstant(node, messageNonAgnosticConstant);
               }
             }
           }
@@ -2120,10 +2323,10 @@
         return evaluateIdentical();
       }
     } else if (target.isExtensionMember) {
-      return report(node, messageConstEvalExtension);
+      return createErrorConstant(node, messageConstEvalExtension);
     }
 
-    String name = target.name.name;
+    String name = target.name.text;
     if (target is Procedure && target.isFactory) {
       if (name.isEmpty) {
         name = target.enclosingClass.name;
@@ -2131,12 +2334,13 @@
         name = '${target.enclosingClass.name}.${name}';
       }
     }
-    return reportInvalid(node, "Invocation of $name");
+    return createInvalidExpressionConstant(node, "Invocation of $name");
   }
 
   @override
   Constant visitAsExpression(AsExpression node) {
     final Constant constant = _evaluateSubexpression(node.operand);
+    if (constant is AbortConstant) return constant;
     if (shouldBeUnevaluated) {
       return unevaluated(
           node,
@@ -2144,12 +2348,21 @@
             ..isForNonNullableByDefault =
                 _staticTypeContext.isNonNullableByDefault);
     }
-    return ensureIsSubtype(constant, evaluateDartType(node, node.type), node);
+    DartType type = _evaluateDartType(node, node.type);
+    if (type == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(type != null);
+    return ensureIsSubtype(constant, type, node);
   }
 
   @override
   Constant visitIsExpression(IsExpression node) {
-    final Constant constant = node.operand.accept(this);
+    final Constant constant = _evaluateSubexpression(node.operand);
+    if (constant is AbortConstant) return constant;
     if (shouldBeUnevaluated) {
       return unevaluated(
           node,
@@ -2158,25 +2371,18 @@
             ..flags = node.flags);
     }
 
-    DartType type = evaluateDartType(node, node.type);
+    DartType type = _evaluateDartType(node, node.type);
+    if (type == null && _gotError != null) {
+      AbortConstant error = _gotError;
+      _gotError = null;
+      return error;
+    }
+    assert(_gotError == null);
+    assert(type != null);
 
     bool performIs(Constant constant, {bool strongMode}) {
       assert(strongMode != null);
       if (strongMode) {
-        // In strong checking mode: if e evaluates to a value v and v has
-        // runtime type S, an instance check e is T occurring in a legacy
-        // library or an opted-in library is evaluated as follows:
-        //
-        //    If v is null and T is a legacy type,
-        //       return LEGACY_SUBTYPE(T, NULL) || LEGACY_SUBTYPE(Object, T)
-        //    Otherwise return NNBD_SUBTYPE(S, T)
-        if (constant is NullConstant &&
-            type.nullability == Nullability.legacy) {
-          return typeEnvironment.isSubtypeOf(type, typeEnvironment.nullType,
-                  SubtypeCheckMode.ignoringNullabilities) ||
-              typeEnvironment.isSubtypeOf(typeEnvironment.objectLegacyRawType,
-                  type, SubtypeCheckMode.ignoringNullabilities);
-        }
         return isSubtype(constant, type, SubtypeCheckMode.withNullabilities);
       } else {
         // In weak checking mode: if e evaluates to a value v and v has runtime
@@ -2213,7 +2419,7 @@
         Constant weakConstant = _weakener.visitConstant(constant) ?? constant;
         bool weakResult = performIs(weakConstant, strongMode: false);
         if (strongResult != weakResult) {
-          return report(node, messageNonAgnosticConstant);
+          return createErrorConstant(node, messageNonAgnosticConstant);
         }
         return makeBoolConstant(strongResult);
       case EvaluationMode.weak:
@@ -2225,13 +2431,14 @@
   @override
   Constant visitNot(Not node) {
     final Constant constant = _evaluateSubexpression(node.operand);
+    if (constant is AbortConstant) return constant;
     if (constant is BoolConstant) {
       return makeBoolConstant(constant != trueConstant);
     }
     if (shouldBeUnevaluated) {
       return unevaluated(node, new Not(extract(constant)));
     }
-    return report(
+    return createErrorConstant(
         node,
         templateConstEvalInvalidType.withArguments(
             constant,
@@ -2243,8 +2450,9 @@
   @override
   Constant visitNullCheck(NullCheck node) {
     final Constant constant = _evaluateSubexpression(node.operand);
+    if (constant is AbortConstant) return constant;
     if (constant is NullConstant) {
-      return report(node, messageConstEvalNonNull);
+      return createErrorConstant(node, messageConstEvalNonNull);
     }
     if (shouldBeUnevaluated) {
       return unevaluated(node, new NullCheck(extract(constant)));
@@ -2262,6 +2470,7 @@
   @override
   Constant visitInstantiation(Instantiation node) {
     final Constant constant = _evaluateSubexpression(node.expression);
+    if (constant is AbortConstant) return constant;
     if (shouldBeUnevaluated) {
       return unevaluated(
           node,
@@ -2271,25 +2480,35 @@
     if (constant is TearOffConstant) {
       if (node.typeArguments.length ==
           constant.procedure.function.typeParameters.length) {
-        final List<DartType> typeArguments =
-            convertTypes(evaluateDartTypes(node, node.typeArguments));
+        List<DartType> types = _evaluateDartTypes(node, node.typeArguments);
+        if (types == null && _gotError != null) {
+          AbortConstant error = _gotError;
+          _gotError = null;
+          return error;
+        }
+        assert(_gotError == null);
+        assert(types != null);
+
+        final List<DartType> typeArguments = convertTypes(types);
         return canonicalize(
             new PartialInstantiationConstant(constant, typeArguments));
       }
-      return reportInvalid(
+      // Probably unreachable.
+      return createInvalidExpressionConstant(
           node,
           'The number of type arguments supplied in the partial instantiation '
           'does not match the number of type arguments of the $constant.');
     }
     // The inner expression in an instantiation can never be null, since
     // instantiations are only inferred on direct references to declarations.
-    return reportInvalid(
+    // Probably unreachable.
+    return createInvalidExpressionConstant(
         node, 'Only tear-off constants can be partially instantiated.');
   }
 
   @override
   Constant visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) {
-    return report(
+    return createErrorConstant(
         node, templateConstEvalDeferredLibrary.withArguments(node.import.name));
   }
 
@@ -2325,7 +2544,7 @@
     if (cached != null) return cached;
     for (Procedure procedure in klass.procedures) {
       if (procedure.kind == ProcedureKind.Operator &&
-          procedure.name.name == '==' &&
+          procedure.name.text == '==' &&
           !procedure.isAbstract &&
           !procedure.isForwardingStub) {
         return primitiveEqualCache[klass] = false;
@@ -2341,10 +2560,14 @@
 
   bool isSubtype(Constant constant, DartType type, SubtypeCheckMode mode) {
     DartType constantType = constant.getType(_staticTypeContext);
+    if (mode == SubtypeCheckMode.ignoringNullabilities) {
+      constantType = rawLegacyErasure(coreTypes, constantType) ?? constantType;
+    }
     bool result = typeEnvironment.isSubtypeOf(constantType, type, mode);
     if (targetingJavaScript && !result) {
       if (constantType is InterfaceType &&
           constantType.classNode == typeEnvironment.coreTypes.intClass) {
+        // Probably unreachable.
         // With JS semantics, an integer is also a double.
         result = typeEnvironment.isSubtypeOf(
             new InterfaceType(typeEnvironment.coreTypes.doubleClass,
@@ -2363,6 +2586,8 @@
     return result;
   }
 
+  /// Note that this returns an error-constant on error and as such the
+  /// return value should be checked.
   Constant ensureIsSubtype(Constant constant, DartType type, TreeNode node) {
     bool result;
     switch (evaluationMode) {
@@ -2376,7 +2601,7 @@
         bool weakResult = isSubtype(
             weakConstant, type, SubtypeCheckMode.ignoringNullabilities);
         if (strongResult != weakResult) {
-          return report(node, messageNonAgnosticConstant);
+          return createErrorConstant(node, messageNonAgnosticConstant);
         }
         result = strongResult;
         break;
@@ -2386,7 +2611,7 @@
         break;
     }
     if (!result) {
-      return report(
+      return createErrorConstant(
           node,
           templateConstEvalInvalidType.withArguments(constant, type,
               constant.getType(_staticTypeContext), isNonNullableByDefault));
@@ -2394,47 +2619,93 @@
     return constant;
   }
 
-  List<DartType> evaluateTypeArguments(TreeNode node, Arguments arguments) {
-    return evaluateDartTypes(node, arguments.types);
+  /// Returns the types on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  List<DartType> _evaluateTypeArguments(TreeNode node, Arguments arguments) {
+    return _evaluateDartTypes(node, arguments.types);
   }
 
-  List<DartType> evaluateSuperTypeArguments(TreeNode node, Supertype type) {
-    return evaluateDartTypes(node, type.typeArguments);
+  /// Returns the types on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  List<DartType> _evaluateSuperTypeArguments(TreeNode node, Supertype type) {
+    return _evaluateDartTypes(node, type.typeArguments);
   }
 
-  List<DartType> evaluateDartTypes(TreeNode node, List<DartType> types) {
+  /// Upon failure in certain procedure calls (e.g. [_evaluateDartTypes]) the
+  /// "error"-constant is saved here. Normally this should be null.
+  /// Once a caller calls such a procedure and it gives an error here,
+  /// the caller should fetch it an null-out this variable.
+  AbortConstant _gotError;
+
+  /// Returns the types on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  List<DartType> _evaluateDartTypes(TreeNode node, List<DartType> types) {
     // TODO: Once the frontend guarantees that there are no free type variables
     // left over after substitution, we can enable this shortcut again:
     // if (env.isEmpty) return types;
-    return types.map((t) => evaluateDartType(node, t)).toList();
+    List<DartType> result =
+        new List<DartType>.filled(types.length, null, growable: true);
+    for (int i = 0; i < types.length; i++) {
+      DartType type = _evaluateDartType(node, types[i]);
+      if (type == null && _gotError != null) {
+        return null;
+      }
+      assert(_gotError == null);
+      assert(type != null);
+      result[i] = type;
+    }
+    return result;
   }
 
-  DartType evaluateDartType(TreeNode node, DartType type) {
+  /// Returns the type on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  DartType _evaluateDartType(TreeNode node, DartType type) {
     final DartType result = env.substituteType(type);
 
     if (!isInstantiated(result)) {
-      return report(
+      _gotError = createErrorConstant(
           node,
           templateConstEvalFreeTypeParameter.withArguments(
               type, isNonNullableByDefault));
+      return null;
     }
 
     return result;
   }
 
-  List<Constant> evaluatePositionalArguments(Arguments arguments) {
-    return arguments.positional.map((Expression node) {
-      return _evaluateSubexpression(node);
-    }).toList();
+  /// Returns the types on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  List<Constant> _evaluatePositionalArguments(Arguments arguments) {
+    List<Constant> result = new List<Constant>.filled(
+        arguments.positional.length, null,
+        growable: true);
+    for (int i = 0; i < arguments.positional.length; i++) {
+      Constant constant = _evaluateSubexpression(arguments.positional[i]);
+      if (constant is AbortConstant) {
+        _gotError = constant;
+        return null;
+      }
+      result[i] = constant;
+    }
+    return result;
   }
 
-  Map<String, Constant> evaluateNamedArguments(Arguments arguments) {
+  /// Returns the arguments on success and null on failure.
+  /// Note that on failure an errorConstant is saved in [_gotError].
+  Map<String, Constant> _evaluateNamedArguments(Arguments arguments) {
     if (arguments.named.isEmpty) return const <String, Constant>{};
 
     final Map<String, Constant> named = {};
     arguments.named.forEach((NamedExpression pair) {
-      named[pair.name] = _evaluateSubexpression(pair.value);
+      if (_gotError != null) return null;
+      Constant constant = _evaluateSubexpression(pair.value);
+      if (constant is AbortConstant) {
+        _gotError = constant;
+        return null;
+      }
+      named[pair.name] = constant;
     });
+    if (_gotError != null) return null;
     return named;
   }
 
@@ -2461,22 +2732,18 @@
   T withNewInstanceBuilder<T>(
       Class klass, List<DartType> typeArguments, T fn()) {
     InstanceBuilder old = instanceBuilder;
-    try {
-      instanceBuilder = new InstanceBuilder(this, klass, typeArguments);
-      return fn();
-    } finally {
-      instanceBuilder = old;
-    }
+    instanceBuilder = new InstanceBuilder(this, klass, typeArguments);
+    T result = fn();
+    instanceBuilder = old;
+    return result;
   }
 
   T withNewEnvironment<T>(T fn()) {
     final EvaluationEnvironment oldEnv = env;
-    try {
-      env = new EvaluationEnvironment();
-      return fn();
-    } finally {
-      env = oldEnv;
-    }
+    env = new EvaluationEnvironment();
+    T result = fn();
+    env = oldEnv;
+    return result;
   }
 
   /// Binary operation between two operands, at least one of which is a double.
@@ -2493,7 +2760,7 @@
         return new DoubleConstant(a / b);
       case '~/':
         if (b == 0) {
-          return report(
+          return createErrorConstant(
               node, templateConstEvalZeroDivisor.withArguments(op, '$a'));
         }
         return intFolder.truncatingDivide(node, a, b);
@@ -2512,7 +2779,9 @@
         return makeBoolConstant(a > b);
     }
 
-    return reportInvalid(node, "Unexpected binary numeric operation '$op'.");
+    // Probably unreachable.
+    return createInvalidExpressionConstant(
+        node, "Unexpected binary numeric operation '$op'.");
   }
 
   Library libraryOf(TreeNode node) {
@@ -2605,12 +2874,6 @@
     }
   }
 
-  DartType lookupParameterValue(TypeParameter parameter) {
-    final DartType value = _typeVariables[parameter];
-    assert(value != null);
-    return value;
-  }
-
   Constant lookupVariable(VariableDeclaration variable) {
     Constant value = _variables[variable];
     if (value is UnevaluatedConstant) {
@@ -2649,20 +2912,121 @@
   }
 }
 
-// Used as control-flow to abort the current evaluation.
-class _AbortDueToError {
+abstract class AbortConstant implements Constant {}
+
+class _AbortDueToErrorConstant extends AbortConstant {
   final TreeNode node;
   final Message message;
   final List<LocatedMessage> context;
 
-  _AbortDueToError(this.node, this.message, {this.context});
+  _AbortDueToErrorConstant(this.node, this.message, {this.context});
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  R acceptReference<R>(Visitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression asExpression() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  DartType getType(StaticTypeContext context) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String leakingDebugToString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toStringInternal() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toText(AstTextStrategy strategy) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    throw new UnimplementedError();
+  }
 }
 
-class _AbortDueToInvalidExpression {
+class _AbortDueToInvalidExpressionConstant extends AbortConstant {
   final TreeNode node;
   final String message;
 
-  _AbortDueToInvalidExpression(this.node, this.message);
+  _AbortDueToInvalidExpressionConstant(this.node, this.message);
+
+  @override
+  R accept<R>(ConstantVisitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  R acceptReference<R>(Visitor<R> v) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  Expression asExpression() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  DartType getType(StaticTypeContext context) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String leakingDebugToString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toString() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toStringInternal() {
+    throw new UnimplementedError();
+  }
+
+  @override
+  String toText(AstTextStrategy strategy) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    throw new UnimplementedError();
+  }
+
+  @override
+  void visitChildren(Visitor<dynamic> v) {
+    throw new UnimplementedError();
+  }
 }
 
 abstract class ErrorReporter {
@@ -2708,6 +3072,7 @@
 
   @override
   bool defaultDartType(DartType node) {
+    // Probably unreachable.
     throw 'A visitor method seems to be unimplemented!';
   }
 
@@ -2752,6 +3117,7 @@
 
   @override
   bool visitTypedefType(TypedefType node) {
+    // Probably unreachable.
     return node.unalias.accept(this);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
index 337d61e..0d73f92 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_int_folder.dart
@@ -41,15 +41,19 @@
 
   Constant truncatingDivide(MethodInvocation node, num left, num right);
 
-  void _checkOperands(MethodInvocation node, String op, num left, num right) {
+  /// Returns [null] on success and an error-"constant" on failure, as such the
+  /// return value should be checked.
+  AbortConstant _checkOperands(
+      MethodInvocation node, String op, num left, num right) {
     if ((op == '<<' || op == '>>' || op == '>>>') && right < 0) {
-      evaluator.report(node,
+      return evaluator.createErrorConstant(node,
           templateConstEvalNegativeShift.withArguments(op, '$left', '$right'));
     }
     if ((op == '%' || op == '~/') && right == 0) {
-      evaluator.report(
+      return evaluator.createErrorConstant(
           node, templateConstEvalZeroDivisor.withArguments(op, '$left'));
     }
+    return null;
   }
 }
 
@@ -73,7 +77,9 @@
       case '~':
         return new IntConstant(~operand.value);
       default:
-        return evaluator.reportInvalid(node, "Invalid unary operator $op");
+        // Probably unreachable.
+        return evaluator.createInvalidExpressionConstant(
+            node, "Invalid unary operator $op");
     }
   }
 
@@ -82,7 +88,8 @@
       MethodInvocation node, String op, IntConstant left, IntConstant right) {
     int a = left.value;
     int b = right.value;
-    _checkOperands(node, op, a, b);
+    AbortConstant error = _checkOperands(node, op, a, b);
+    if (error != null) return error;
     switch (op) {
       case '+':
         return new IntConstant(a + b);
@@ -107,6 +114,7 @@
       case '>>':
         return new IntConstant(a >> b);
       case '>>>':
+        // Currently unreachable as int hasn't defined '>>>'.
         int result = b >= 64 ? 0 : (a >> b) & ((1 << (64 - b)) - 1);
         return new IntConstant(result);
       case '<':
@@ -118,7 +126,9 @@
       case '>':
         return evaluator.makeBoolConstant(a > b);
       default:
-        return evaluator.reportInvalid(node, "Invalid binary operator $op");
+        // Probably unreachable.
+        return evaluator.createInvalidExpressionConstant(
+            node, "Invalid binary operator $op");
     }
   }
 
@@ -127,7 +137,7 @@
     try {
       return new IntConstant(left ~/ right);
     } catch (e) {
-      return evaluator.report(node,
+      return evaluator.createErrorConstant(node,
           templateConstEvalTruncateError.withArguments('$left', '$right'));
     }
   }
@@ -154,7 +164,7 @@
   @override
   DoubleConstant makeIntConstant(int value, {bool unsigned: false}) {
     double doubleValue = value.toDouble();
-    assert(doubleValue.toInt() == value);
+    // Invalid assert: assert(doubleValue.toInt() == value);
     if (unsigned) {
       const double twoTo64 = 18446744073709551616.0;
       if (value < 0) doubleValue += twoTo64;
@@ -172,7 +182,9 @@
         int intValue = _toUint32(operand.value);
         return new DoubleConstant(_truncate32(~intValue).toDouble());
       default:
-        return evaluator.reportInvalid(node, "Invalid unary operator $op");
+        // Probably unreachable.
+        return evaluator.createInvalidExpressionConstant(
+            node, "Invalid unary operator $op");
     }
   }
 
@@ -181,7 +193,8 @@
       DoubleConstant left, DoubleConstant right) {
     double a = left.value;
     double b = right.value;
-    _checkOperands(node, op, a, b);
+    AbortConstant error = _checkOperands(node, op, a, b);
+    if (error != null) return error;
     switch (op) {
       case '+':
         return new DoubleConstant(a + b);
@@ -212,6 +225,7 @@
         }
         return new DoubleConstant(_truncate32(ai >> b.toInt()).toDouble());
       case '>>>':
+        // Currently unreachable as int hasn't defined '>>>'.
         int ai = _toUint32(a);
         return new DoubleConstant(_truncate32(ai >> b.toInt()).toDouble());
       case '<':
@@ -223,7 +237,9 @@
       case '>':
         return evaluator.makeBoolConstant(a > b);
       default:
-        return evaluator.reportInvalid(node, "Invalid binary operator $op");
+        // Probably unreachable.
+        return evaluator.createInvalidExpressionConstant(
+            node, "Invalid binary operator $op");
     }
   }
 
@@ -231,7 +247,7 @@
   Constant truncatingDivide(MethodInvocation node, num left, num right) {
     double division = (left / right);
     if (division.isNaN || division.isInfinite) {
-      return evaluator.report(node,
+      return evaluator.createErrorConstant(node,
           templateConstEvalTruncateError.withArguments('$left', '${right}'));
     }
     double result = division.truncateToDouble();
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index ec809d6..6f9a38e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -471,7 +471,7 @@
   String get _debugName => "PropertyAccessGenerator";
 
   @override
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   @override
   Expression doInvocation(
@@ -486,7 +486,7 @@
     sink.write(", receiver: ");
     printNodeOn(receiver, sink, syntheticNames: syntheticNames);
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
   }
 
   @override
@@ -503,21 +503,8 @@
   @override
   Expression buildIfNullAssignment(Expression value, DartType type, int offset,
       {bool voidContext = false}) {
-    VariableDeclaration variable =
-        _helper.forest.createVariableDeclarationForValue(receiver);
-    PropertyGet read = _forest.createPropertyGet(
-        fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset,
-            forNullGuardedAccess: true),
-        name);
-    PropertySet write = _helper.forest.createPropertySet(
-        fileOffset,
-        _helper.createVariableGet(variable, receiver.fileOffset,
-            forNullGuardedAccess: true),
-        name,
-        value,
-        forEffect: voidContext);
-    return new IfNullPropertySet(variable, read, write, forEffect: voidContext)
+    return new IfNullPropertySet(receiver, name, value,
+        forEffect: voidContext, readOffset: fileOffset, writeOffset: fileOffset)
       ..fileOffset = offset;
   }
 
@@ -624,7 +611,7 @@
   String get _debugName => "ThisPropertyAccessGenerator";
 
   @override
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   @override
   Expression buildSimpleRead() {
@@ -715,7 +702,7 @@
   @override
   void printOn(StringSink sink) {
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
   }
 }
 
@@ -738,7 +725,7 @@
   Expression receiverAccess() => new VariableGet(receiver);
 
   @override
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   @override
   Expression buildSimpleRead() {
@@ -823,7 +810,7 @@
     sink.write(", receiverExpression: ");
     printNodeOn(receiverExpression, sink, syntheticNames: syntheticNames);
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
   }
 }
 
@@ -842,7 +829,7 @@
   String get _debugName => "SuperPropertyAccessGenerator";
 
   @override
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   @override
   Expression buildSimpleRead() {
@@ -936,7 +923,7 @@
   void printOn(StringSink sink) {
     NameSystem syntheticNames = new NameSystem();
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
     sink.write(", getter: ");
     printQualifiedNameOn(getter, sink, syntheticNames: syntheticNames);
     sink.write(", setter: ");
@@ -1458,11 +1445,11 @@
       return _helper.buildProblem(
           templateNotConstantExpression.withArguments('Method invocation'),
           offset,
-          readTarget?.name?.name?.length ?? 0);
+          readTarget?.name?.text?.length ?? 0);
     }
     if (readTarget == null || isFieldOrGetter(readTarget)) {
       return _helper.forest.createExpressionInvocation(
-          offset + (readTarget?.name?.name?.length ?? 0),
+          offset + (readTarget?.name?.text?.length ?? 0),
           buildSimpleRead(),
           arguments);
     } else {
@@ -1935,7 +1922,7 @@
   String get _debugName => "ExplicitExtensionIndexedAccessGenerator";
 
   @override
-  String get _plainNameForRead => targetName.name;
+  String get _plainNameForRead => targetName.text;
 
   List<DartType> _createExtensionTypeArguments() {
     return explicitTypeArguments ?? const <DartType>[];
@@ -2037,15 +2024,10 @@
             ..fileOffset = offset)
         ..fileOffset = fileOffset;
     } else {
-      VariableDeclaration variable =
-          _helper.forest.createVariableDeclarationForValue(receiver);
-      Expression read =
-          _createRead(_helper.createVariableGet(variable, receiver.fileOffset));
-      Expression write = _createWrite(fileOffset,
-          _helper.createVariableGet(variable, receiver.fileOffset), value,
-          forEffect: voidContext, readOnlyReceiver: true);
-      return new IfNullPropertySet(variable, read, write,
-          forEffect: voidContext)
+      return new IfNullPropertySet(receiver, targetName, value,
+          forEffect: voidContext,
+          readOffset: fileOffset,
+          writeOffset: fileOffset)
         ..fileOffset = offset;
     }
   }
@@ -3079,7 +3061,7 @@
     if (declarationBuilder is DeclarationBuilder) {
       DeclarationBuilder declaration = declarationBuilder;
       Builder member = declaration.findStaticBuilder(
-          name.name, offsetForToken(send.token), _uri, _helper.libraryBuilder);
+          name.text, offsetForToken(send.token), _uri, _helper.libraryBuilder);
 
       Generator generator;
       if (member == null) {
@@ -3092,7 +3074,7 @@
               send.token,
               send.token,
               arguments,
-              name.name,
+              name.text,
               send.typeArguments,
               token.charOffset,
               Constness.implicit,
@@ -3100,7 +3082,7 @@
         }
       } else if (member is AmbiguousBuilder) {
         return _helper.buildProblem(
-            member.message, member.charOffset, name.name.length);
+            member.message, member.charOffset, name.text.length);
       } else {
         Builder setter;
         if (member.isSetter) {
@@ -3108,13 +3090,13 @@
           member = null;
         } else if (member.isGetter) {
           setter = declaration.findStaticBuilder(
-              name.name, fileOffset, _uri, _helper.libraryBuilder,
+              name.text, fileOffset, _uri, _helper.libraryBuilder,
               isSetter: true);
         } else if (member.isField) {
           MemberBuilder fieldBuilder = member;
           if (!fieldBuilder.isAssignable) {
             setter = declaration.findStaticBuilder(
-                name.name, fileOffset, _uri, _helper.libraryBuilder,
+                name.text, fileOffset, _uri, _helper.libraryBuilder,
                 isSetter: true);
           } else {
             setter = member;
@@ -3122,7 +3104,7 @@
         }
         generator = new StaticAccessGenerator.fromBuilder(
             _helper,
-            name.name,
+            name.text,
             send.token,
             member is MemberBuilder ? member : null,
             setter is MemberBuilder ? setter : null);
@@ -3338,7 +3320,7 @@
   Name get name => unsupported("name", fileOffset, _uri);
 
   @override
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   withReceiver(Object receiver, int operatorOffset, {bool isNullAware}) => this;
 
@@ -3454,7 +3436,7 @@
 
   factory UnresolvedNameGenerator(
       ExpressionGeneratorHelper helper, Token token, Name name) {
-    if (name.name.isEmpty) {
+    if (name.text.isEmpty) {
       unhandled("empty", "name", offsetForToken(token), helper.uri);
     }
     return new UnresolvedNameGenerator.internal(helper, token, name);
@@ -3511,7 +3493,7 @@
   @override
   void printOn(StringSink sink) {
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
   }
 
   Expression _buildUnresolvedVariableAssignment(
@@ -3719,7 +3701,7 @@
   @override
   void printOn(StringSink sink) {
     sink.write(", binaryOperator: ");
-    sink.write(binaryOperator.name);
+    sink.write(binaryOperator.text);
   }
 }
 
@@ -3801,8 +3783,8 @@
   /* Expression | Generator */ buildPropertyAccess(
       IncompleteSendGenerator send, int operatorOffset, bool isNullAware) {
     if (send is IncompleteSendGenerator) {
-      assert(send.name.name == send.token.lexeme,
-          "'${send.name.name}' != ${send.token.lexeme}");
+      assert(send.name.text == send.token.lexeme,
+          "'${send.name.text}' != ${send.token.lexeme}");
       Object result = qualifiedLookup(send.token);
       if (send is SendAccessGenerator) {
         result = _helper.finishSend(
@@ -4265,7 +4247,7 @@
           constructor.function, arguments, offset, <TypeParameter>[]);
     } else {
       String fullName =
-          _helper.constructorNameForDiagnostics(name.name, isSuper: isSuper);
+          _helper.constructorNameForDiagnostics(name.text, isSuper: isSuper);
       message = (isSuper
               ? templateSuperclassHasNoConstructor
               : templateConstructorNotFound)
@@ -4276,7 +4258,7 @@
       return _helper.buildInvalidInitializer(
           _helper.throwNoSuchMethodError(
               _forest.createNullLiteral(offset),
-              _helper.constructorNameForDiagnostics(name.name,
+              _helper.constructorNameForDiagnostics(name.text,
                   isSuper: isSuper),
               arguments,
               offset,
@@ -4434,7 +4416,7 @@
     assert(arguments != null);
   }
 
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   String get _debugName => "SendAccessGenerator";
 
@@ -4494,7 +4476,7 @@
   @override
   void printOn(StringSink sink) {
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
     sink.write(", arguments: ");
     Arguments node = arguments;
     if (node is Node) {
@@ -4513,7 +4495,7 @@
       ExpressionGeneratorHelper helper, Token token, this.name)
       : super(helper, token);
 
-  String get _plainNameForRead => name.name;
+  String get _plainNameForRead => name.text;
 
   String get _debugName => "IncompletePropertyAccessGenerator";
 
@@ -4572,7 +4554,7 @@
   @override
   void printOn(StringSink sink) {
     sink.write(", name: ");
-    sink.write(name.name);
+    sink.write(name.text);
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/forest.dart b/pkg/front_end/lib/src/fasta/kernel/forest.dart
index 90787ec0..b683259 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forest.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forest.dart
@@ -424,12 +424,21 @@
   }
 
   /// Return a representation of a logical expression at the given [fileOffset]
-  /// having the [leftOperand], [rightOperand] and the [operator]
+  /// having the [leftOperand], [rightOperand] and the [operatorString]
   /// (either `&&` or `||`).
   Expression createLogicalExpression(int fileOffset, Expression leftOperand,
-      String operator, Expression rightOperand) {
+      String operatorString, Expression rightOperand) {
     assert(fileOffset != null);
-    assert(operator == '&&' || operator == '||');
+    LogicalExpressionOperator operator;
+    if (operatorString == '&&') {
+      operator = LogicalExpressionOperator.AND;
+    } else if (operatorString == '||') {
+      operator = LogicalExpressionOperator.OR;
+    } else {
+      throw new UnsupportedError(
+          "Unhandled logical operator '$operatorString'");
+    }
+
     return new LogicalExpression(leftOperand, operator, rightOperand)
       ..fileOffset = fileOffset;
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
index 5fa02e2..08a6f34 100644
--- a/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/forwarding_node.dart
@@ -11,9 +11,12 @@
         Expression,
         Field,
         FunctionNode,
+        FunctionType,
         Member,
         Name,
         NamedExpression,
+        NamedType,
+        Nullability,
         Procedure,
         ProcedureKind,
         ReturnStatement,
@@ -47,33 +50,31 @@
 import 'class_hierarchy_builder.dart';
 
 class ForwardingNode {
-  final ClassHierarchyBuilder hierarchy;
+  ClassHierarchyBuilder get hierarchy => _combinedMemberSignature.hierarchy;
 
-  final SourceClassBuilder classBuilder;
+  SourceClassBuilder get classBuilder => _combinedMemberSignature.classBuilder;
 
-  final ClassMember combinedMemberSignatureResult;
+  // TODO(johnniwinther): Use [_combinedMemberSignature] more directly in
+  // the forwarding node computation.
+  final CombinedMemberSignature _combinedMemberSignature;
+
+  ClassMember get combinedMemberSignatureResult =>
+      _combinedMemberSignature.canonicalClassMember;
 
   /// The index of [combinedMemberSignatureResult] in [_candidates].
-  final int _combinedMemberIndex;
+  int get _combinedMemberIndex => _combinedMemberSignature.classMemberIndex;
 
   final ProcedureKind kind;
 
   /// A list containing the directly implemented and directly inherited
   /// procedures of the class in question.
-  final List<ClassMember> _candidates;
+  List<ClassMember> get _candidates => _combinedMemberSignature.members;
 
   /// The indices of the [_candidates] whose types need to be merged to compute
   /// the resulting member type.
-  final Set<int> _mergeIndices;
+  Set<int> get _mergeIndices => _combinedMemberSignature.mutualSubtypeIndices;
 
-  ForwardingNode(
-      this.hierarchy,
-      this.classBuilder,
-      this.combinedMemberSignatureResult,
-      this._combinedMemberIndex,
-      this._candidates,
-      this.kind,
-      this._mergeIndices);
+  ForwardingNode(this._combinedMemberSignature, this.kind);
 
   Name get name => combinedMemberSignatureResult.name;
 
@@ -83,6 +84,203 @@
   /// forwarding stubs if necessary.
   Member finalize() => _computeCovarianceFixes();
 
+  /// Creates a getter member signature for [interfaceMember] with the given
+  /// [type].
+  Member _createGetterMemberSignature(Member interfaceMember, DartType type) {
+    Procedure referenceFrom;
+    if (classBuilder.referencesFromIndexed != null) {
+      referenceFrom = classBuilder.referencesFromIndexed
+          .lookupProcedureNotSetter(name.text);
+    }
+    return new Procedure(name, kind, new FunctionNode(null, returnType: type),
+        isAbstract: true,
+        isMemberSignature: true,
+        fileUri: enclosingClass.fileUri,
+        memberSignatureOrigin: interfaceMember,
+        reference: referenceFrom?.reference)
+      ..startFileOffset = enclosingClass.fileOffset
+      ..fileOffset = enclosingClass.fileOffset
+      ..parent = enclosingClass;
+  }
+
+  /// Creates a setter member signature for [interfaceMember] with the given
+  /// [type]. The flags of parameter is set according to [isCovariant] and
+  /// [isGenericCovariantImpl] and the [parameterName] is used, if provided.
+  Member _createSetterMemberSignature(Member interfaceMember, DartType type,
+      {bool isCovariant, bool isGenericCovariantImpl, String parameterName}) {
+    assert(isCovariant != null);
+    assert(isGenericCovariantImpl != null);
+    Procedure referenceFrom;
+    if (classBuilder.referencesFromIndexed != null) {
+      referenceFrom =
+          classBuilder.referencesFromIndexed.lookupProcedureSetter(name.text);
+    }
+    return new Procedure(
+        name,
+        kind,
+        new FunctionNode(null,
+            returnType: const VoidType(),
+            positionalParameters: [
+              new VariableDeclaration(parameterName ?? '_',
+                  type: type, isCovariant: isCovariant)
+                ..isGenericCovariantImpl = isGenericCovariantImpl
+            ]),
+        isAbstract: true,
+        isMemberSignature: true,
+        fileUri: enclosingClass.fileUri,
+        memberSignatureOrigin: interfaceMember,
+        reference: referenceFrom?.reference)
+      ..startFileOffset = enclosingClass.fileOffset
+      ..fileOffset = enclosingClass.fileOffset
+      ..parent = enclosingClass;
+  }
+
+  /// Creates a legacy member signature for the field [interfaceMember] if the
+  /// type of [interfaceMember] contains non-legacy nullabilities.
+  Member _createLegacyMemberSignatureForField(Field interfaceMember) {
+    DartType type = interfaceMember.type;
+    if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+      Substitution substitution =
+          _substitutionFor(null, interfaceMember, enclosingClass);
+      type = substitution.substituteType(type);
+    }
+    DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+    if (legacyType == null) {
+      return interfaceMember;
+    } else {
+      // We base the decision to add a member signature on whether the legacy
+      // erasure of the declared type is different from the declared type, i.e.
+      // whether the declared type contained non-legacy nullabilities.
+      //
+      // This is slightly different from checking whether the legacy erasure of
+      // the inherited type is different from the
+      if (kind == ProcedureKind.Getter) {
+        return _createGetterMemberSignature(interfaceMember, legacyType);
+      } else {
+        assert(kind == ProcedureKind.Setter);
+        return _createSetterMemberSignature(interfaceMember, legacyType,
+            isCovariant: interfaceMember.isCovariant,
+            isGenericCovariantImpl: interfaceMember.isGenericCovariantImpl);
+      }
+    }
+  }
+
+  /// Creates a legacy member signature for procedure [interfaceMember] if the
+  /// type of [interfaceMember] contains non-legacy nullabilities.
+  Member _createLegacyMemberSignatureForProcedure(Procedure interfaceMember) {
+    if (interfaceMember.kind == ProcedureKind.Getter) {
+      DartType type = interfaceMember.getterType;
+      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+        Substitution substitution =
+            _substitutionFor(null, interfaceMember, enclosingClass);
+        type = substitution.substituteType(type);
+      }
+      DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+      if (legacyType == null) {
+        return interfaceMember;
+      } else {
+        return _createGetterMemberSignature(interfaceMember, legacyType);
+      }
+    } else if (interfaceMember.kind == ProcedureKind.Setter) {
+      DartType type = interfaceMember.setterType;
+      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+        Substitution substitution =
+            _substitutionFor(null, interfaceMember, enclosingClass);
+        type = substitution.substituteType(type);
+      }
+      DartType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+      if (legacyType == null) {
+        return interfaceMember;
+      } else {
+        VariableDeclaration parameter =
+            interfaceMember.function.positionalParameters.first;
+        return _createSetterMemberSignature(interfaceMember, legacyType,
+            isCovariant: parameter.isCovariant,
+            isGenericCovariantImpl: parameter.isGenericCovariantImpl,
+            parameterName: parameter.name);
+      }
+    } else {
+      FunctionNode function = interfaceMember.function;
+      FunctionType type = function.computeFunctionType(Nullability.legacy);
+      if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+        Substitution substitution =
+            _substitutionFor(null, interfaceMember, enclosingClass);
+        type = substitution.substituteType(type);
+      }
+      FunctionType legacyType = rawLegacyErasure(hierarchy.coreTypes, type);
+      if (legacyType == null) {
+        return interfaceMember;
+      }
+      Procedure referenceFrom;
+      if (classBuilder.referencesFromIndexed != null) {
+        referenceFrom = classBuilder.referencesFromIndexed
+            .lookupProcedureNotSetter(name.text);
+      }
+      List<VariableDeclaration> positionalParameters = [];
+      for (int i = 0; i < function.positionalParameters.length; i++) {
+        VariableDeclaration parameter = function.positionalParameters[i];
+        DartType parameterType = legacyType.positionalParameters[i];
+        if (i == 0 && interfaceMember == hierarchy.coreTypes.objectEquals) {
+          // In legacy code we special case `Object.==` to infer `dynamic`
+          // instead `Object!`.
+          parameterType = const DynamicType();
+        }
+        positionalParameters.add(new VariableDeclaration(parameter.name,
+            type: parameterType, isCovariant: parameter.isCovariant)
+          ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+      }
+      List<VariableDeclaration> namedParameters = [];
+      int namedParameterCount = function.namedParameters.length;
+      if (namedParameterCount == 1) {
+        NamedType namedType = legacyType.namedParameters.first;
+        VariableDeclaration parameter = function.namedParameters.first;
+        namedParameters.add(new VariableDeclaration(parameter.name,
+            type: namedType.type, isCovariant: parameter.isCovariant)
+          ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+      } else if (namedParameterCount > 1) {
+        Map<String, DartType> namedTypes = {};
+        for (NamedType namedType in legacyType.namedParameters) {
+          namedTypes[namedType.name] = namedType.type;
+        }
+        for (int i = 0; i < namedParameterCount; i++) {
+          VariableDeclaration parameter = function.namedParameters[i];
+          DartType parameterType = namedTypes[parameter.name];
+          namedParameters.add(new VariableDeclaration(parameter.name,
+              type: parameterType, isCovariant: parameter.isCovariant)
+            ..isGenericCovariantImpl = parameter.isGenericCovariantImpl);
+        }
+      }
+      return new Procedure(
+          name,
+          kind,
+          new FunctionNode(null,
+              typeParameters: legacyType.typeParameters,
+              returnType: legacyType.returnType,
+              positionalParameters: positionalParameters,
+              namedParameters: namedParameters,
+              requiredParameterCount: function.requiredParameterCount),
+          isAbstract: true,
+          isMemberSignature: true,
+          fileUri: enclosingClass.fileUri,
+          memberSignatureOrigin: interfaceMember,
+          reference: referenceFrom?.reference)
+        ..startFileOffset = enclosingClass.fileOffset
+        ..fileOffset = enclosingClass.fileOffset
+        ..parent = enclosingClass;
+    }
+  }
+
+  /// Creates a legacy member signature for [interfaceMember] if the type of
+  /// [interfaceMember] contains non-legacy nullabilities.
+  Member _createLegacyMemberSignature(Member interfaceMember) {
+    if (interfaceMember is Field) {
+      return _createLegacyMemberSignatureForField(interfaceMember);
+    } else {
+      assert(interfaceMember is Procedure);
+      return _createLegacyMemberSignatureForProcedure(interfaceMember);
+    }
+  }
+
   /// Tag the parameters of [interfaceMember] that need type checks
   ///
   /// Parameters can need type checks for calls coming from statically typed
@@ -95,6 +293,18 @@
   /// stub is introduced as a place to put the checks.
   Member _computeCovarianceFixes() {
     Member interfaceMember = combinedMemberSignatureResult.getMember(hierarchy);
+    if (_candidates.length == 1) {
+      // Covariance can only come from [interfaceMember] so we never need a
+      // forwarding stub.
+      if (interfaceMember.isNonNullableByDefault &&
+          !classBuilder.library.isNonNullableByDefault) {
+        // Create a member signature with the legacy erasure type.
+        return _createLegacyMemberSignature(interfaceMember);
+      } else {
+        // Nothing to do.
+        return interfaceMember;
+      }
+    }
 
     List<TypeParameter> interfaceMemberTypeParameters =
         interfaceMember.function?.typeParameters ?? [];
@@ -564,10 +774,10 @@
     if (classBuilder.referencesFromIndexed != null) {
       if (kind == ProcedureKind.Setter) {
         referenceFrom =
-            classBuilder.referencesFromIndexed.lookupProcedureSetter(name.name);
+            classBuilder.referencesFromIndexed.lookupProcedureSetter(name.text);
       } else {
         referenceFrom = classBuilder.referencesFromIndexed
-            .lookupProcedureNotSetter(name.name);
+            .lookupProcedureNotSetter(name.text);
       }
     }
     return new Procedure(name, kind, function,
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 7560e5b..e5d4c71 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -107,24 +107,6 @@
   }
 
   @override
-  ExpressionInferenceResult visitDirectMethodInvocation(
-      DirectMethodInvocation node, DartType typeContext) {
-    return _unhandledExpression(node, typeContext);
-  }
-
-  @override
-  ExpressionInferenceResult visitDirectPropertyGet(
-      DirectPropertyGet node, DartType typeContext) {
-    return _unhandledExpression(node, typeContext);
-  }
-
-  @override
-  ExpressionInferenceResult visitDirectPropertySet(
-      DirectPropertySet node, DartType typeContext) {
-    return _unhandledExpression(node, typeContext);
-  }
-
-  @override
   ExpressionInferenceResult visitFileUriExpression(
       FileUriExpression node, DartType typeContext) {
     return _unhandledExpression(node, typeContext);
@@ -355,7 +337,7 @@
     for (Expression expression in node.expressions) {
       expressionResults.add(inferrer.inferExpression(
           expression, const UnknownType(), !inferrer.isTopLevel,
-          isVoidAllowed: true));
+          isVoidAllowed: true, forEffect: true));
     }
     List<Statement> body = [];
     for (int index = 0; index < expressionResults.length; index++) {
@@ -396,6 +378,7 @@
   @override
   ExpressionInferenceResult visitConditionalExpression(
       ConditionalExpression node, DartType typeContext) {
+    inferrer.flowAnalysis.conditional_conditionBegin();
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -419,7 +402,7 @@
     node.otherwise = otherwiseResult.expression..parent = node;
     inferrer.registerIfUnreachableForTesting(node.otherwise,
         isReachable: isOtherwiseReachable);
-    inferrer.flowAnalysis.conditional_end(node.condition, node.otherwise);
+    inferrer.flowAnalysis.conditional_end(node, node.otherwise);
     DartType inferredType = inferrer.typeSchemaEnvironment
         .getStandardUpperBound(thenResult.inferredType,
             otherwiseResult.inferredType, inferrer.library.library);
@@ -711,7 +694,7 @@
   StatementInferenceResult visitExpressionStatement(ExpressionStatement node) {
     ExpressionInferenceResult result = inferrer.inferExpression(
         node.expression, const UnknownType(), !inferrer.isTopLevel,
-        isVoidAllowed: true);
+        isVoidAllowed: true, forEffect: true);
     node.expression = result.expression..parent = node;
     return const StatementInferenceResult();
   }
@@ -1202,6 +1185,7 @@
 
   @override
   StatementInferenceResult visitIfStatement(IfStatement node) {
+    inferrer.flowAnalysis.ifStatement_conditionBegin();
     InterfaceType expectedType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
     ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -1382,8 +1366,7 @@
           spreadType, spreadTypeBound, element.isNullAware);
       if (typeChecksNeeded) {
         if (spreadElementType == null) {
-          if (inferrer.coreTypes
-                  .isNull(inferrer.resolveTypeParameter(spreadType)) &&
+          if (inferrer.coreTypes.isNull(spreadTypeBound) &&
               !element.isNullAware) {
             replacement = inferrer.helper.buildProblem(
                 templateNonNullAwareSpreadIsNull.withArguments(
@@ -1391,6 +1374,15 @@
                 element.expression.fileOffset,
                 1);
           } else {
+            if (inferrer.isNonNullableByDefault &&
+                spreadType.isPotentiallyNullable &&
+                spreadType is! DynamicType &&
+                spreadType != inferrer.coreTypes.nullType &&
+                !element.isNullAware) {
+              replacement = inferrer.helper.buildProblem(
+                  messageNullableSpreadError, element.expression.fileOffset, 1);
+            }
+
             replacement = inferrer.helper.buildProblem(
                 templateSpreadTypeMismatch.withArguments(
                     spreadType, inferrer.isNonNullableByDefault),
@@ -1406,7 +1398,8 @@
                     inferrer.isNonNullableByDefault),
                 element.expression.fileOffset,
                 1);
-          } else if (inferrer.isNonNullableByDefault &&
+          }
+          if (inferrer.isNonNullableByDefault &&
               spreadType.isPotentiallyNullable &&
               spreadType is! DynamicType &&
               spreadType != inferrer.coreTypes.nullType &&
@@ -1420,6 +1413,7 @@
       element.elementType = spreadElementType ?? const DynamicType();
       return new ExpressionInferenceResult(element.elementType, replacement);
     } else if (element is IfElement) {
+      inferrer.flowAnalysis.ifStatement_conditionBegin();
       DartType boolType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -1725,20 +1719,21 @@
       LogicalExpression node, DartType typeContext) {
     InterfaceType boolType =
         inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
+    inferrer.flowAnalysis.logicalBinaryOp_begin();
     ExpressionInferenceResult leftResult = inferrer.inferExpression(
         node.left, boolType, !inferrer.isTopLevel,
         isVoidAllowed: false);
     Expression left = inferrer.ensureAssignableResult(boolType, leftResult);
     node.left = left..parent = node;
-    inferrer.flowAnalysis
-        .logicalBinaryOp_rightBegin(node.left, isAnd: node.operator == '&&');
+    inferrer.flowAnalysis.logicalBinaryOp_rightBegin(node.left,
+        isAnd: node.operatorEnum == LogicalExpressionOperator.AND);
     ExpressionInferenceResult rightResult = inferrer.inferExpression(
         node.right, boolType, !inferrer.isTopLevel,
         isVoidAllowed: false);
     Expression right = inferrer.ensureAssignableResult(boolType, rightResult);
     node.right = right..parent = node;
-    inferrer.flowAnalysis
-        .logicalBinaryOp_end(node, node.right, isAnd: node.operator == '&&');
+    inferrer.flowAnalysis.logicalBinaryOp_end(node, node.right,
+        isAnd: node.operatorEnum == LogicalExpressionOperator.AND);
     return new ExpressionInferenceResult(boolType, node);
   }
 
@@ -1815,8 +1810,7 @@
       MapEntry replacement = entry;
       if (typeChecksNeeded) {
         if (actualKeyType == null) {
-          if (inferrer.coreTypes
-                  .isNull(inferrer.resolveTypeParameter(spreadType)) &&
+          if (inferrer.coreTypes.isNull(spreadTypeBound) &&
               !entry.isNullAware) {
             replacement = new MapEntry(
                 inferrer.helper.buildProblem(
@@ -1827,6 +1821,18 @@
                 new NullLiteral())
               ..fileOffset = entry.fileOffset;
           } else if (actualElementType != null) {
+            if (inferrer.isNonNullableByDefault &&
+                spreadType.isPotentiallyNullable &&
+                spreadType is! DynamicType &&
+                spreadType != inferrer.coreTypes.nullType &&
+                !entry.isNullAware) {
+              replacement = new SpreadMapEntry(
+                  inferrer.helper.buildProblem(messageNullableSpreadError,
+                      entry.expression.fileOffset, 1),
+                  false)
+                ..fileOffset = entry.fileOffset;
+            }
+
             // Don't report the error here, it might be an ambiguous Set.  The
             // error is reported in checkMapEntry if it's disambiguated as map.
             iterableSpreadType = spreadType;
@@ -1912,6 +1918,7 @@
 
       return replacement;
     } else if (entry is IfMapEntry) {
+      inferrer.flowAnalysis.ifStatement_conditionBegin();
       DartType boolType =
           inferrer.coreTypes.boolRawType(inferrer.library.nonNullable);
       ExpressionInferenceResult conditionResult = inferrer.inferExpression(
@@ -2473,13 +2480,24 @@
       NullCheck node, DartType typeContext) {
     ExpressionInferenceResult operandResult = inferrer.inferExpression(
         node.operand, inferrer.computeNullable(typeContext), true);
-    node.operand = operandResult.expression..parent = node;
+    Link<NullAwareGuard> nullAwareGuards;
+    Expression operand;
+    DartType operandType;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuards = operandResult.nullAwareGuards;
+      operand = operandResult.nullAwareAction;
+      operandType = operandResult.nullAwareActionType;
+    } else {
+      operand = operandResult.expression;
+      operandType = operandResult.inferredType;
+    }
+    node.operand = operand..parent = node;
     reportNonNullableInNullAwareWarningIfNeeded(
-        operandResult.inferredType, "!", node.operand.fileOffset);
+        operandType, "!", node.operand.fileOffset);
     inferrer.flowAnalysis.nonNullAssert_end(node.operand);
-    DartType nonNullableResultType =
-        inferrer.computeNonNullable(operandResult.inferredType);
-    return new ExpressionInferenceResult(nonNullableResultType, node);
+    DartType nonNullableResultType = inferrer.computeNonNullable(operandType);
+    return inferrer.createNullAwareExpressionInferenceResult(
+        nonNullableResultType, node, nullAwareGuards);
   }
 
   ExpressionInferenceResult visitNullAwareMethodInvocation(
@@ -2679,29 +2697,66 @@
 
   ExpressionInferenceResult visitIfNullPropertySet(
       IfNullPropertySet node, DartType typeContext) {
-    Link<NullAwareGuard> nullAwareGuards =
-        inferrer.inferSyntheticVariableNullAware(node.variable);
-    ExpressionInferenceResult readResult = inferrer.inferExpression(
-        node.read, const UnknownType(), true,
-        isVoidAllowed: true);
+    ExpressionInferenceResult receiverResult = inferrer.inferExpression(
+        node.receiver, const UnknownType(), true,
+        isVoidAllowed: false);
+
+    Link<NullAwareGuard> nullAwareGuards;
+    Expression receiver;
+    DartType receiverType;
+    if (inferrer.isNonNullableByDefault) {
+      nullAwareGuards = receiverResult.nullAwareGuards;
+      receiver = receiverResult.nullAwareAction;
+      receiverType = receiverResult.nullAwareActionType;
+    } else {
+      receiver = receiverResult.expression;
+      receiverType = receiverResult.inferredType;
+    }
+
+    VariableDeclaration receiverVariable =
+        createVariable(receiver, receiverType);
+    inferrer.instrumentation?.record(
+        inferrer.uriForInstrumentation,
+        receiverVariable.fileOffset,
+        'type',
+        new InstrumentationValueForType(receiverType));
+    Expression readReceiver = createVariableGet(receiverVariable);
+    Expression writeReceiver = createVariableGet(receiverVariable);
+
+    ExpressionInferenceResult readResult = _computePropertyGet(node.readOffset,
+        readReceiver, receiverType, node.propertyName, const UnknownType(),
+        isThisReceiver: node.receiver is ThisExpression);
+
     reportNonNullableInNullAwareWarningIfNeeded(
-        readResult.inferredType, "??=", node.read.fileOffset);
+        readResult.inferredType, "??=", node.readOffset);
     Expression read = readResult.expression;
     DartType readType = readResult.inferredType;
 
+    ObjectAccessTarget writeTarget = inferrer.findInterfaceMember(
+        receiverType, node.propertyName, receiver.fileOffset,
+        setter: true, instrumented: true, includeExtensionMethods: true);
+    DartType writeContext = inferrer.getSetterType(writeTarget, receiverType);
+
     inferrer.flowAnalysis.ifNullExpression_rightBegin(read, readType);
-    ExpressionInferenceResult writeResult = inferrer
-        .inferExpression(node.write, typeContext, true, isVoidAllowed: true);
+    ExpressionInferenceResult rhsResult = inferrer
+        .inferExpression(node.rhs, writeContext, true, isVoidAllowed: true);
     inferrer.flowAnalysis.ifNullExpression_end();
 
+    Expression rhs = inferrer.ensureAssignableResult(writeContext, rhsResult);
+
+    DartType writeType = rhsResult.inferredType;
+    Expression write = _computePropertySet(node.writeOffset, writeReceiver,
+        receiverType, node.propertyName, writeTarget, rhs,
+        forEffect: node.forEffect, valueType: writeType);
+
     Member equalsMember = inferrer
         .findInterfaceMember(readType, equalsName, node.fileOffset)
         .member;
 
     DartType nonNullableReadType = inferrer.computeNonNullable(readType);
     DartType inferredType = inferrer.typeSchemaEnvironment
-        .getStandardUpperBound(nonNullableReadType, writeResult.inferredType,
-            inferrer.library.library);
+        .getStandardUpperBound(
+            nonNullableReadType, writeType, inferrer.library.library);
 
     Expression replacement;
     if (node.forEffect) {
@@ -2711,14 +2766,11 @@
       //
       MethodInvocation equalsNull =
           createEqualsNull(node.fileOffset, read, equalsMember);
-      ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull,
-          writeResult.expression,
-          new NullLiteral()..fileOffset = node.fileOffset,
-          inferredType)
+      ConditionalExpression conditional = new ConditionalExpression(equalsNull,
+          write, new NullLiteral()..fileOffset = node.fileOffset, inferredType)
         ..fileOffset = node.fileOffset;
       replacement =
-          new Let(node.variable, conditional..fileOffset = node.fileOffset)
+          new Let(receiverVariable, conditional..fileOffset = node.fileOffset)
             ..fileOffset = node.fileOffset;
     } else {
       // Encode `o.a ??= b` as:
@@ -2734,10 +2786,11 @@
         variableGet.promotedType = nonNullableReadType;
       }
       ConditionalExpression conditional = new ConditionalExpression(
-          equalsNull, writeResult.expression, variableGet, inferredType)
+          equalsNull, write, variableGet, inferredType)
         ..fileOffset = node.fileOffset;
-      replacement = new Let(node.variable, createLet(readVariable, conditional))
-        ..fileOffset = node.fileOffset;
+      replacement =
+          new Let(receiverVariable, createLet(readVariable, conditional))
+            ..fileOffset = node.fileOffset;
     }
 
     return inferrer.createNullAwareExpressionInferenceResult(
@@ -3725,9 +3778,9 @@
           inferrer.helper.wrapInProblem(
               binary,
               templateNullableOperatorCallError.withArguments(
-                  binaryName.name, leftType, inferrer.isNonNullableByDefault),
+                  binaryName.text, leftType, inferrer.isNonNullableByDefault),
               binary.fileOffset,
-              binaryName.name.length));
+              binaryName.text.length));
     }
     return new ExpressionInferenceResult(binaryType, binary);
   }
@@ -3823,10 +3876,10 @@
           unaryType,
           inferrer.helper.wrapInProblem(
               unary,
-              templateNullableOperatorCallError.withArguments(unaryName.name,
+              templateNullableOperatorCallError.withArguments(unaryName.text,
                   expressionType, inferrer.isNonNullableByDefault),
               unary.fileOffset,
-              unaryName == unaryMinusName ? 1 : unaryName.name.length));
+              unaryName == unaryMinusName ? 1 : unaryName.text.length));
     }
     return new ExpressionInferenceResult(unaryType, unary);
   }
@@ -3909,7 +3962,7 @@
           readType,
           inferrer.helper.wrapInProblem(
               read,
-              templateNullableOperatorCallError.withArguments(indexGetName.name,
+              templateNullableOperatorCallError.withArguments(indexGetName.text,
                   receiverType, inferrer.isNonNullableByDefault),
               read.fileOffset,
               noLength));
@@ -3973,7 +4026,7 @@
       return inferrer.helper.wrapInProblem(
           write,
           templateNullableOperatorCallError.withArguments(
-              indexSetName.name, receiverType, inferrer.isNonNullableByDefault),
+              indexSetName.text, receiverType, inferrer.isNonNullableByDefault),
           write.fileOffset,
           noLength);
     }
@@ -4107,9 +4160,9 @@
       readResult = inferrer.wrapExpressionInferenceResultInProblem(
           readResult,
           templateNullablePropertyAccessError.withArguments(
-              propertyName.name, receiverType, inferrer.isNonNullableByDefault),
+              propertyName.text, receiverType, inferrer.isNonNullableByDefault),
           read.fileOffset,
-          propertyName.name.length);
+          propertyName.text.length);
     }
     return readResult;
   }
@@ -4191,9 +4244,9 @@
       return inferrer.helper.wrapInProblem(
           write,
           templateNullablePropertyAccessError.withArguments(
-              propertyName.name, receiverType, inferrer.isNonNullableByDefault),
+              propertyName.text, receiverType, inferrer.isNonNullableByDefault),
           write.fileOffset,
-          propertyName.name.length);
+          propertyName.text.length);
     }
 
     return write;
@@ -5048,7 +5101,11 @@
   @override
   ExpressionInferenceResult visitRethrow(Rethrow node, DartType typeContext) {
     inferrer.flowAnalysis.handleExit();
-    return new ExpressionInferenceResult(const BottomType(), node);
+    return new ExpressionInferenceResult(
+        inferrer.isNonNullableByDefault
+            ? const NeverType(Nullability.nonNullable)
+            : const BottomType(),
+        node);
   }
 
   @override
@@ -5332,11 +5389,15 @@
       enumFields = expressionType.classNode.fields
           .where((Field field) => field.isConst && field.type == expressionType)
           .toSet();
+      if (expressionType.isPotentiallyNullable) {
+        enumFields.add(null);
+      }
     }
 
     inferrer.flowAnalysis.switchStatement_expressionEnd(node);
 
     bool hasDefault = false;
+    bool lastCaseTerminates = true;
     for (int caseIndex = 0; caseIndex < node.cases.length; ++caseIndex) {
       SwitchCaseImpl switchCase = node.cases[caseIndex];
       hasDefault = hasDefault || switchCase.isDefault;
@@ -5350,8 +5411,12 @@
         Expression caseExpression = caseExpressionResult.expression;
         switchCase.expressions[index] = caseExpression..parent = switchCase;
         DartType caseExpressionType = caseExpressionResult.inferredType;
-        if (enumFields != null && caseExpression is StaticGet) {
-          enumFields.remove(caseExpression.target);
+        if (enumFields != null) {
+          if (caseExpression is StaticGet) {
+            enumFields.remove(caseExpression.target);
+          } else if (caseExpression is NullLiteral) {
+            enumFields.remove(null);
+          }
         }
 
         if (!inferrer.isTopLevel) {
@@ -5399,19 +5464,56 @@
         switchCase.body = bodyResult.statement..parent = switchCase;
       }
 
-      if (!inferrer.isTopLevel && inferrer.isNonNullableByDefault) {
-        // The last case block is allowed to complete normally.
-        if (caseIndex < node.cases.length - 1 &&
-            inferrer.flowAnalysis.isReachable) {
-          inferrer.library.addProblem(messageSwitchCaseFallThrough,
-              switchCase.fileOffset, noLength, inferrer.helper.uri);
+      if (inferrer.isNonNullableByDefault) {
+        lastCaseTerminates = !inferrer.flowAnalysis.isReachable;
+        if (!inferrer.isTopLevel) {
+          // The last case block is allowed to complete normally.
+          if (caseIndex < node.cases.length - 1 &&
+              inferrer.flowAnalysis.isReachable) {
+            inferrer.library.addProblem(messageSwitchCaseFallThrough,
+                switchCase.fileOffset, noLength, inferrer.helper.uri);
+          }
         }
       }
     }
     bool isExhaustive =
         hasDefault || (enumFields != null && enumFields.isEmpty);
     inferrer.flowAnalysis.switchStatement_end(isExhaustive);
-    return const StatementInferenceResult();
+    Statement replacement;
+    if (isExhaustive &&
+        !hasDefault &&
+        inferrer.shouldThrowUnsoundnessException) {
+      if (!lastCaseTerminates) {
+        LabeledStatement breakTarget;
+        if (node.parent is LabeledStatement) {
+          breakTarget = node.parent;
+        } else {
+          replacement = breakTarget = new LabeledStatement(node);
+        }
+
+        SwitchCase lastCase = node.cases.last;
+        Statement body = lastCase.body;
+        if (body is Block) {
+          body.statements.add(new BreakStatementImpl(isContinue: false)
+            ..target = breakTarget
+            ..targetStatement = node
+            ..fileOffset = node.fileOffset);
+        }
+      }
+      node.cases.add(new SwitchCase(
+          [],
+          [],
+          _createExpressionStatement(inferrer.createReachabilityError(
+              node.fileOffset,
+              messageNeverReachableSwitchDefaultError,
+              messageNeverReachableSwitchDefaultWarning)),
+          isDefault: true)
+        ..fileOffset = node.fileOffset
+        ..parent = node);
+    }
+    return replacement != null
+        ? new StatementInferenceResult.single(replacement)
+        : const StatementInferenceResult();
   }
 
   @override
@@ -5526,8 +5628,10 @@
       VariableSet node, DartType typeContext) {
     VariableDeclarationImpl variable = node.variable;
     bool isDefinitelyAssigned = false;
+    bool isDefinitelyUnassigned = false;
     if (inferrer.isNonNullableByDefault) {
       isDefinitelyAssigned = inferrer.flowAnalysis.isAssigned(variable);
+      isDefinitelyUnassigned = inferrer.flowAnalysis.isUnassigned(variable);
     }
     DartType declaredOrInferredType = variable.lateType ?? variable.type;
     DartType promotedType;
@@ -5550,6 +5654,10 @@
           callName,
           new Arguments(<Expression>[rhs])..fileOffset = node.fileOffset)
         ..fileOffset = node.fileOffset;
+      // Future calls to flow analysis will be using `resultExpression` to refer
+      // to the variable set, so instruct flow analysis to forward the
+      // expression information.
+      inferrer.flowAnalysis.forwardExpression(resultExpression, node);
     } else {
       node.value = rhs..parent = node;
       resultExpression = node;
@@ -5562,13 +5670,23 @@
           declaredOrInferredType is! InvalidType) {
         if ((variable.isLate && variable.isFinal) ||
             variable.isLateFinalWithoutInitializer) {
-          if (isDefinitelyAssigned &&
-              declaredOrInferredType.isPotentiallyNonNullable) {
+          if (isDefinitelyAssigned) {
             return new ExpressionInferenceResult(
                 resultType,
                 inferrer.helper.wrapInProblem(
                     resultExpression,
-                    templateNonNullableLateDefinitelyAssignedError
+                    templateLateDefinitelyAssignedError
+                        .withArguments(node.variable.name),
+                    node.fileOffset,
+                    node.variable.name.length));
+          }
+        } else if (variable.isStaticLate) {
+          if (!isDefinitelyUnassigned) {
+            return new ExpressionInferenceResult(
+                resultType,
+                inferrer.helper.wrapInProblem(
+                    resultExpression,
+                    templateFinalPossiblyAssignedError
                         .withArguments(node.variable.name),
                     node.fileOffset,
                     node.variable.name.length));
@@ -5586,10 +5704,17 @@
         node.isImplicitlyTyped ? const UnknownType() : node.type;
     DartType inferredType;
     ExpressionInferenceResult initializerResult;
+    inferrer.flowAnalysis.declare(node, node.initializer != null);
     if (node.initializer != null) {
+      if (node.isLate) {
+        inferrer.flowAnalysis.lateInitializer_begin(node);
+      }
       initializerResult = inferrer.inferExpression(node.initializer,
           declaredType, !inferrer.isTopLevel || node.isImplicitlyTyped,
           isVoidAllowed: true);
+      if (node.isLate) {
+        inferrer.flowAnalysis.lateInitializer_end();
+      }
       inferredType = inferrer.inferDeclarationType(
           initializerResult.inferredType,
           forSyntheticVariable: node.name == null);
@@ -5605,12 +5730,24 @@
       node.type = inferredType;
     }
     if (initializerResult != null) {
+      DartType initializerType = initializerResult.inferredType;
+      if (node.isImplicitlyTyped) {
+        if (initializerType is TypeParameterType) {
+          inferrer.flowAnalysis.promote(node, initializerType);
+        }
+      } else if (!node.isFinal) {
+        // TODO(paulberry): `initializerType` is sometimes `null` during top
+        // level inference.  Figure out how to prevent this.
+        if (initializerType != null) {
+          inferrer.flowAnalysis
+              .write(node, initializerType, viaInitializer: true);
+        }
+      }
       Expression initializer = inferrer.ensureAssignableResult(
           node.type, initializerResult,
           fileOffset: node.fileOffset, isVoidAllowed: node.type is VoidType);
       node.initializer = initializer..parent = node;
     }
-    inferrer.flowAnalysis.declare(node, node.initializer != null);
     if (!inferrer.isTopLevel) {
       SourceLibraryBuilder library = inferrer.library;
       if (node.isImplicitlyTyped) {
@@ -5626,8 +5763,11 @@
       List<Statement> result = <Statement>[];
       result.add(node);
 
+      late_lowering.IsSetEncoding isSetEncoding =
+          late_lowering.computeIsSetEncoding(
+              node.type, late_lowering.computeIsSetStrategy(inferrer.library));
       VariableDeclaration isSetVariable;
-      if (node.type.isPotentiallyNullable) {
+      if (isSetEncoding == late_lowering.IsSetEncoding.useIsSetField) {
         isSetVariable = new VariableDeclaration(
             '${late_lowering.lateLocalPrefix}'
             '${node.name}'
@@ -5669,7 +5809,8 @@
                       node.type,
                       'Local',
                       createVariableRead: createVariableRead,
-                      createIsSetRead: createIsSetRead)
+                      createIsSetRead: createIsSetRead,
+                      isSetEncoding: isSetEncoding)
                   : late_lowering.createGetterWithInitializer(
                       inferrer.coreTypes,
                       fileOffset,
@@ -5679,7 +5820,8 @@
                       createVariableRead: createVariableRead,
                       createVariableWrite: createVariableWrite,
                       createIsSetRead: createIsSetRead,
-                      createIsSetWrite: createIsSetWrite),
+                      createIsSetWrite: createIsSetWrite,
+                      isSetEncoding: isSetEncoding),
               returnType: node.type))
         ..fileOffset = fileOffset;
       getVariable.type =
@@ -5713,12 +5855,14 @@
                             createVariableRead: createVariableRead,
                             createVariableWrite: createVariableWrite,
                             createIsSetRead: createIsSetRead,
-                            createIsSetWrite: createIsSetWrite)
+                            createIsSetWrite: createIsSetWrite,
+                            isSetEncoding: isSetEncoding)
                         : late_lowering.createSetterBody(inferrer.coreTypes,
                             fileOffset, node.name, setterParameter, node.type,
                             shouldReturnValue: true,
                             createVariableWrite: createVariableWrite,
-                            createIsSetWrite: createIsSetWrite)
+                            createIsSetWrite: createIsSetWrite,
+                            isSetEncoding: isSetEncoding)
                       ..fileOffset = fileOffset,
                     positionalParameters: <VariableDeclaration>[
                       setterParameter
@@ -5733,8 +5877,15 @@
       }
       node.isLate = false;
       node.lateType = node.type;
+      if (isSetEncoding == late_lowering.IsSetEncoding.useSentinel) {
+        node.initializer = new StaticInvocation(
+            inferrer.coreTypes.createSentinelMethod,
+            new Arguments([], types: [node.type])..fileOffset = fileOffset)
+          ..parent = node;
+      } else {
+        node.initializer = null;
+      }
       node.type = inferrer.computeNullable(node.type);
-      node.initializer = null;
 
       return new StatementInferenceResult.multiple(node.fileOffset, result);
     }
@@ -5780,6 +5931,10 @@
           callName,
           new Arguments(<Expression>[])..fileOffset = node.fileOffset)
         ..fileOffset = node.fileOffset;
+      // Future calls to flow analysis will be using `resultExpression` to refer
+      // to the variable get, so instruct flow analysis to forward the
+      // expression information.
+      inferrer.flowAnalysis.forwardExpression(resultExpression, node);
     } else {
       resultExpression = node;
     }
@@ -5802,28 +5957,37 @@
             !variable.isLocalFunction &&
             declaredOrInferredType is! InvalidType) {
           if (variable.isLate || variable.lateGetter != null) {
-            if (isDefinitelyUnassigned &&
-                declaredOrInferredType.isPotentiallyNonNullable) {
+            if (isDefinitelyUnassigned) {
               return new ExpressionInferenceResult(
                   resultType,
                   inferrer.helper.wrapInProblem(
                       resultExpression,
-                      templateNonNullableLateDefinitelyUnassignedError
+                      templateLateDefinitelyUnassignedError
                           .withArguments(node.variable.name),
                       node.fileOffset,
                       node.variable.name.length));
             }
           } else {
-            if (isUnassigned &&
-                declaredOrInferredType.isPotentiallyNonNullable) {
-              return new ExpressionInferenceResult(
-                  resultType,
-                  inferrer.helper.wrapInProblem(
-                      resultExpression,
-                      templateNonNullableNotAssignedError
-                          .withArguments(node.variable.name),
-                      node.fileOffset,
-                      node.variable.name.length));
+            if (isUnassigned) {
+              if (variable.isFinal) {
+                return new ExpressionInferenceResult(
+                    resultType,
+                    inferrer.helper.wrapInProblem(
+                        resultExpression,
+                        templateFinalNotAssignedError
+                            .withArguments(node.variable.name),
+                        node.fileOffset,
+                        node.variable.name.length));
+              } else if (declaredOrInferredType.isPotentiallyNonNullable) {
+                return new ExpressionInferenceResult(
+                    resultType,
+                    inferrer.helper.wrapInProblem(
+                        resultExpression,
+                        templateNonNullableNotAssignedError
+                            .withArguments(node.variable.name),
+                        node.fileOffset,
+                        node.variable.name.length));
+              }
             }
           }
         }
@@ -6054,8 +6218,14 @@
 
   LocalForInVariable(this.variableSet);
 
-  DartType computeElementType(TypeInferrerImpl inferrer) =>
-      variableSet.variable.type;
+  DartType computeElementType(TypeInferrerImpl inferrer) {
+    VariableDeclaration variable = variableSet.variable;
+    DartType promotedType;
+    if (inferrer.isNonNullableByDefault) {
+      promotedType = inferrer.flowAnalysis.promotedType(variable);
+    }
+    return promotedType ?? variable.type;
+  }
 
   Expression inferAssignment(TypeInferrerImpl inferrer, DartType rhsType) {
     Expression rhs = inferrer.ensureAssignable(
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 68d00f9..2ed8f56 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -698,9 +698,9 @@
     }
     printer.writeClassName(target.enclosingClass.reference);
     printer.writeTypeArguments(arguments.types);
-    if (target.name.name.isNotEmpty) {
+    if (target.name.text.isNotEmpty) {
       printer.write('.');
-      printer.write(target.name.name);
+      printer.write(target.name.text);
     }
     printer.writeArguments(arguments, includeTypeArguments: false);
   }
@@ -1354,18 +1354,6 @@
   }
 
   @override
-  void setVariableMutatedAnywhere(VariableDeclaration variable) {
-    if (variable is VariableDeclarationImpl) {
-      variable.mutatedAnywhere = true;
-    } else {
-      // Hack to deal with the fact that BodyBuilder still creates raw
-      // VariableDeclaration objects sometimes.
-      // TODO(paulberry): get rid of this once the type parameter is
-      // KernelVariableDeclaration.
-    }
-  }
-
-  @override
   void setVariableMutatedInClosure(VariableDeclaration variable) {
     if (variable is VariableDeclarationImpl) {
       variable.mutatedInClosure = true;
@@ -1376,19 +1364,6 @@
       // KernelVariableDeclaration.
     }
   }
-
-  @override
-  bool wasVariableMutatedAnywhere(VariableDeclaration variable) {
-    if (variable is VariableDeclarationImpl) {
-      return variable.mutatedAnywhere;
-    } else {
-      // Hack to deal with the fact that BodyBuilder still creates raw
-      // VariableDeclaration objects sometimes.
-      // TODO(paulberry): get rid of this once the type parameter is
-      // KernelVariableDeclaration.
-      return true;
-    }
-  }
 }
 
 /// Front end specific implementation of [VariableDeclaration].
@@ -1415,9 +1390,6 @@
   // be close to zero).
   bool mutatedInClosure = false;
 
-  // TODO(ahe): Investigate if this can be removed.
-  bool mutatedAnywhere = false;
-
   /// Determines whether the given [VariableDeclarationImpl] represents a
   /// local function.
   ///
@@ -1426,6 +1398,14 @@
   // TODO(ahe): Investigate if this can be removed.
   final bool isLocalFunction;
 
+  /// Whether the variable is final with no initializer in a null safe library.
+  ///
+  /// Such variables behave similar to those declared with the `late` keyword,
+  /// except that the don't have lazy evaluation semantics, and it is statically
+  /// verified by the front end that they are always assigned before they are
+  /// used.
+  bool isStaticLate;
+
   VariableDeclarationImpl(String name, this.functionNestingLevel,
       {this.forSyntheticToken: false,
       this.hasDeclaredInitializer: false,
@@ -1437,7 +1417,8 @@
       bool isCovariant: false,
       bool isLocalFunction: false,
       bool isLate: false,
-      bool isRequired: false})
+      bool isRequired: false,
+      this.isStaticLate: false})
       : isImplicitlyTyped = type == null,
         isLocalFunction = isLocalFunction,
         super(name,
@@ -1455,6 +1436,7 @@
         functionNestingLevel = 0,
         isImplicitlyTyped = false,
         isLocalFunction = false,
+        isStaticLate = false,
         hasDeclaredInitializer = true,
         super.forValue(initializer);
 
@@ -1463,6 +1445,7 @@
         functionNestingLevel = 0,
         isImplicitlyTyped = true,
         isLocalFunction = false,
+        isStaticLate = false,
         hasDeclaredInitializer = true,
         super.forValue(initializer);
 
@@ -1492,6 +1475,12 @@
   DartType lateType;
 
   @override
+  bool get isAssignable {
+    if (isStaticLate) return true;
+    return super.isAssignable;
+  }
+
+  @override
   void toTextInternal(AstPrinter printer) {
     printer.writeVariableDeclaration(this,
         isLate: isLate || lateGetter != null, type: lateType ?? type);
@@ -1595,23 +1584,29 @@
 ///     let v1 = o in v1.a == null ? v1.a = b : null
 ///
 class IfNullPropertySet extends InternalExpression {
-  /// The synthetic variable whose initializer hold the receiver.
-  VariableDeclaration variable;
+  /// The receiver used for the read/write operations.
+  Expression receiver;
 
-  /// The expression that reads the property from [variable].
-  Expression read;
+  /// Name of the property.
+  Name propertyName;
 
-  /// The expression that writes the value to the property on [variable].
-  Expression write;
+  /// The right-hand side of the binary operation.
+  Expression rhs;
 
   /// If `true`, the expression is only need for effect and not for its value.
   final bool forEffect;
 
-  IfNullPropertySet(this.variable, this.read, this.write, {this.forEffect})
+  /// The file offset for the read operation.
+  final int readOffset;
+
+  /// The file offset for the write operation.
+  final int writeOffset;
+
+  IfNullPropertySet(this.receiver, this.propertyName, this.rhs,
+      {this.forEffect, this.readOffset, this.writeOffset})
       : assert(forEffect != null) {
-    variable?.parent = this;
-    read?.parent = this;
-    write?.parent = this;
+    receiver?.parent = this;
+    rhs?.parent = this;
   }
 
   @override
@@ -1625,24 +1620,19 @@
 
   @override
   void visitChildren(Visitor<dynamic> v) {
-    variable?.accept(v);
-    read?.accept(v);
-    write?.accept(v);
+    receiver?.accept(v);
+    rhs?.accept(v);
   }
 
   @override
   void transformChildren(Transformer v) {
-    if (variable != null) {
-      variable = variable.accept<TreeNode>(v);
-      variable?.parent = this;
+    if (receiver != null) {
+      receiver = receiver.accept<TreeNode>(v);
+      receiver?.parent = this;
     }
-    if (read != null) {
-      read = read.accept<TreeNode>(v);
-      read?.parent = this;
-    }
-    if (write != null) {
-      write = write.accept<TreeNode>(v);
-      write?.parent = this;
+    if (rhs != null) {
+      rhs = rhs.accept<TreeNode>(v);
+      rhs?.parent = this;
     }
   }
 
@@ -1653,12 +1643,11 @@
 
   @override
   void toTextInternal(AstPrinter printer) {
-    printer.write('let ');
-    printer.writeVariableDeclaration(variable);
-    printer.write(' in if-null ');
-    printer.writeExpression(read);
-    printer.write(' ?? ');
-    printer.writeExpression(write);
+    printer.writeExpression(receiver);
+    printer.write('.');
+    printer.writeName(propertyName);
+    printer.write(' ??= ');
+    printer.writeExpression(rhs);
   }
 }
 
@@ -3557,12 +3546,12 @@
   }
 
   @override
-  int get precedence => Precedence.binaryPrecedence[binaryName.name];
+  int get precedence => Precedence.binaryPrecedence[binaryName.text];
 
   @override
   void toTextInternal(AstPrinter printer) {
     printer.writeExpression(left, minimumPrecedence: precedence);
-    printer.write(' ${binaryName.name} ');
+    printer.write(' ${binaryName.text} ');
     printer.writeExpression(right, minimumPrecedence: precedence);
   }
 }
@@ -3611,7 +3600,7 @@
     if (unaryName == unaryMinusName) {
       printer.write('-');
     } else {
-      printer.write('${unaryName.name}');
+      printer.write('${unaryName.text}');
     }
     printer.writeExpression(expression, minimumPrecedence: precedence);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
index cc23b9c..c8165a2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_api.dart
@@ -47,6 +47,6 @@
       sink.write(cls.name ?? syntheticNames.nameClass(cls));
       sink.write("::");
     }
-    sink.write(member.name?.name ?? syntheticNames.nameMember(member));
+    sink.write(member.name?.text ?? syntheticNames.nameMember(member));
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index b17364e3..c0b1459 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -15,7 +15,7 @@
 import '../combinator.dart' as fasta;
 
 export 'class_hierarchy_builder.dart'
-    show ClassHierarchyBuilder, ClassMember, DelayedOverrideCheck;
+    show ClassHierarchyBuilder, ClassMember, DelayedCheck;
 
 export 'implicit_field_type.dart' show ImplicitFieldType;
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index 61f54880..cf9d6cb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -4,6 +4,7 @@
 
 library fasta.kernel_constants;
 
+import 'package:front_end/src/fasta/builder/library_builder.dart';
 import 'package:kernel/ast.dart' show InvalidExpression;
 
 import '../fasta_codes.dart' show LocatedMessage;
@@ -19,9 +20,27 @@
 
   @override
   void report(LocatedMessage message, List<LocatedMessage> context) {
-    loader.addProblem(
-        message.messageObject, message.charOffset, message.length, message.uri,
-        context: context);
+    // Try to find library.
+    LibraryBuilder builder = loader.builders[message.uri];
+    if (builder == null) {
+      for (LibraryBuilder candidate in loader.builders.values) {
+        if (candidate.fileUri == message.uri) {
+          // Found it.
+          builder = candidate;
+          break;
+        }
+      }
+    }
+    if (builder == null) {
+      // TODO(jensj): Probably a part or something.
+      loader.addProblem(message.messageObject, message.charOffset,
+          message.length, message.uri,
+          context: context);
+    } else {
+      builder.addProblem(message.messageObject, message.charOffset,
+          message.length, message.uri,
+          context: context);
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 4472d88..19f16db 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -69,6 +69,7 @@
 import '../builder/field_builder.dart';
 import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
+import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/never_type_declaration_builder.dart';
 import '../builder/nullability_builder.dart';
@@ -189,7 +190,7 @@
   final bool errorOnUnevaluatedConstant =
       CompilerContext.current.options.errorOnUnevaluatedConstant;
 
-  final List<Object> clonedFormals = <Object>[];
+  final List<ClonedFunctionNode> clonedFunctionNodes = <ClonedFunctionNode>[];
 
   KernelTarget(this.fileSystem, this.includeComments, DillTarget dillTarget,
       UriTranslator uriTranslator,
@@ -359,6 +360,7 @@
       loader.buildOutlineExpressions(loader.coreTypes);
       loader.checkTypes();
       loader.checkRedirectingFactories(myClasses);
+      loader.checkMainMethods();
       _updateDelayedParameterTypes();
       installAllComponentProblems(loader.allComponentProblems);
       loader.allComponentProblems.clear();
@@ -555,7 +557,7 @@
     /// >default constructor C() : super() {}, unless C is class Object.
     // The superinitializer is installed below in [finishConstructors].
     builder.addSyntheticConstructor(
-        makeDefaultConstructor(builder.cls, referenceFrom));
+        _makeDefaultConstructor(builder, referenceFrom));
   }
 
   void installForwardingConstructors(SourceClassBuilder builder) {
@@ -601,45 +603,51 @@
     }
 
     if (supertype is ClassBuilder) {
-      if (supertype.cls.constructors.isEmpty) {
-        builder.addSyntheticConstructor(
-            makeDefaultConstructor(builder.cls, referenceFrom));
-      } else {
-        Map<TypeParameter, DartType> substitutionMap =
-            builder.getSubstitutionMap(supertype.cls);
-        for (Constructor constructor in supertype.cls.constructors) {
-          Constructor referenceFrom =
-              indexedClass?.lookupConstructor(constructor.name.name);
+      ClassBuilder superclassBuilder = supertype;
+      bool isConstructorAdded = false;
+      Map<TypeParameter, DartType> substitutionMap;
 
-          builder.addSyntheticConstructor(makeMixinApplicationConstructor(
-              builder.cls,
+      void addSyntheticConstructor(String name, MemberBuilder memberBuilder) {
+        if (memberBuilder.member is Constructor) {
+          substitutionMap ??= builder.getSubstitutionMap(superclassBuilder.cls);
+          Constructor referenceFrom = indexedClass?.lookupConstructor(name);
+          builder.addSyntheticConstructor(_makeMixinApplicationConstructor(
+              builder,
               builder.cls.mixin,
-              constructor,
+              memberBuilder,
               substitutionMap,
               referenceFrom));
+          isConstructorAdded = true;
         }
       }
+
+      superclassBuilder.forEachConstructor(addSyntheticConstructor,
+          includeInjectedConstructors: true);
+
+      if (!isConstructorAdded) {
+        builder.addSyntheticConstructor(
+            _makeDefaultConstructor(builder, referenceFrom));
+      }
     } else if (supertype is InvalidTypeDeclarationBuilder ||
         supertype is TypeVariableBuilder ||
         supertype is DynamicTypeDeclarationBuilder ||
         supertype is VoidTypeDeclarationBuilder ||
         supertype is NeverTypeDeclarationBuilder) {
       builder.addSyntheticConstructor(
-          makeDefaultConstructor(builder.cls, referenceFrom));
+          _makeDefaultConstructor(builder, referenceFrom));
     } else {
       unhandled("${supertype.runtimeType}", "installForwardingConstructors",
           builder.charOffset, builder.fileUri);
     }
   }
 
-  Constructor makeMixinApplicationConstructor(
-      Class cls,
+  SyntheticConstructorBuilder _makeMixinApplicationConstructor(
+      SourceClassBuilder classBuilder,
       Class mixin,
-      Constructor constructor,
+      MemberBuilderImpl memberBuilder,
       Map<TypeParameter, DartType> substitutionMap,
       Constructor referenceFrom) {
     VariableDeclaration copyFormal(VariableDeclaration formal) {
-      // TODO(ahe): Handle initializers.
       VariableDeclaration copy = new VariableDeclaration(formal.name,
           isFinal: formal.isFinal, isConst: formal.isConst);
       if (formal.type != null) {
@@ -651,10 +659,14 @@
       return copy;
     }
 
+    Class cls = classBuilder.cls;
+    Constructor constructor = memberBuilder.member;
+    bool isConst = constructor.isConst && mixin.fields.isEmpty;
     List<VariableDeclaration> positionalParameters = <VariableDeclaration>[];
     List<VariableDeclaration> namedParameters = <VariableDeclaration>[];
     List<Expression> positional = <Expression>[];
     List<NamedExpression> named = <NamedExpression>[];
+
     for (VariableDeclaration formal
         in constructor.function.positionalParameters) {
       positionalParameters.add(copyFormal(formal));
@@ -662,7 +674,6 @@
     }
     for (VariableDeclaration formal in constructor.function.namedParameters) {
       VariableDeclaration clone = copyFormal(formal);
-      clonedFormals..add(formal)..add(clone)..add(substitutionMap);
       namedParameters.add(clone);
       named.add(new NamedExpression(
           formal.name, new VariableGet(namedParameters.last)));
@@ -674,46 +685,56 @@
         returnType: makeConstructorReturnType(cls));
     SuperInitializer initializer = new SuperInitializer(
         constructor, new Arguments(positional, named: named));
-    return new Constructor(function,
-        name: constructor.name,
-        initializers: <Initializer>[initializer],
-        isSynthetic: true,
-        isConst: constructor.isConst && mixin.fields.isEmpty,
-        reference: referenceFrom?.reference)
-      ..isNonNullableByDefault = cls.enclosingLibrary.isNonNullableByDefault;
+    ClonedFunctionNode clonedFunctionNode =
+        new ClonedFunctionNode(substitutionMap, constructor.function, function);
+    if (!isConst) {
+      // For constant constructors default values are computed and cloned part
+      // of the outline expression and therefore passed to the
+      // [SyntheticConstructorBuilder] below.
+      //
+      // For non-constant constructors default values are cloned as part of the
+      // full compilation using [clonedFunctionNodes].
+      clonedFunctionNodes.add(clonedFunctionNode);
+    }
+    return new SyntheticConstructorBuilder(
+        classBuilder,
+        new Constructor(function,
+            name: constructor.name,
+            initializers: <Initializer>[initializer],
+            isSynthetic: true,
+            isConst: isConst,
+            reference: referenceFrom?.reference)
+          ..isNonNullableByDefault =
+              cls.enclosingLibrary.isNonNullableByDefault,
+        // If the constructor is constant, the default values must be part of
+        // the outline expressions. We pass on the original constructor and
+        // cloned function nodes to ensure that the default values are computed
+        // and cloned for the outline.
+        origin: isConst ? memberBuilder : null,
+        clonedFunctionNode: isConst ? clonedFunctionNode : null);
   }
 
   void finishClonedParameters() {
-    for (int i = 0; i < clonedFormals.length; i += 3) {
-      // Note that [original] may itself be clone. If so, it was added to
-      // [clonedFormals] before [clone], so it's initializers are already in
-      // place.
-      VariableDeclaration original = clonedFormals[i];
-      VariableDeclaration clone = clonedFormals[i + 1];
-      if (original.initializer != null) {
-        // TODO(ahe): It is unclear if it is legal to use type variables in
-        // default values, but Fasta is currently allowing it, and the VM
-        // accepts it. If it isn't legal, the we can speed this up by using a
-        // single cloner without substitution.
-        CloneVisitorNotMembers cloner =
-            new CloneVisitorNotMembers(typeSubstitution: clonedFormals[i + 2]);
-        clone.initializer = cloner.clone(original.initializer)..parent = clone;
-      }
+    for (ClonedFunctionNode clonedFunctionNode in clonedFunctionNodes) {
+      clonedFunctionNode.cloneDefaultValues();
     }
-    clonedFormals.clear();
+    clonedFunctionNodes.clear();
     ticker.logMs("Cloned default values of formals");
   }
 
-  Constructor makeDefaultConstructor(
-      Class enclosingClass, Constructor referenceFrom) {
-    return new Constructor(
-        new FunctionNode(new EmptyStatement(),
-            returnType: makeConstructorReturnType(enclosingClass)),
-        name: new Name(""),
-        isSynthetic: true,
-        reference: referenceFrom?.reference)
-      ..isNonNullableByDefault =
-          enclosingClass.enclosingLibrary.isNonNullableByDefault;
+  SyntheticConstructorBuilder _makeDefaultConstructor(
+      SourceClassBuilder classBuilder, Constructor referenceFrom) {
+    Class enclosingClass = classBuilder.cls;
+    return new SyntheticConstructorBuilder(
+        classBuilder,
+        new Constructor(
+            new FunctionNode(new EmptyStatement(),
+                returnType: makeConstructorReturnType(enclosingClass)),
+            name: new Name(""),
+            isSynthetic: true,
+            reference: referenceFrom?.reference)
+          ..isNonNullableByDefault =
+              enclosingClass.enclosingLibrary.isNonNullableByDefault);
   }
 
   DartType makeConstructorReturnType(Class enclosingClass) {
@@ -849,7 +870,7 @@
         }
       });
       Set<String> kernelConstructorNames =
-          cls.constructors.map((c) => c.name.name).toSet().difference({""});
+          cls.constructors.map((c) => c.name.text).toSet().difference({""});
       return kernelConstructorNames.containsAll(patchConstructorNames);
     }(),
         "Constructors of class '${builder.fullNameForErrors}' "
@@ -860,7 +881,7 @@
         if (initializer is RedirectingInitializer) {
           if (constructor.isConst && !initializer.target.isConst) {
             builder.addProblem(messageConstConstructorRedirectionToNonConst,
-                initializer.fileOffset, initializer.target.name.name.length);
+                initializer.fileOffset, initializer.target.name.text.length);
           }
           isRedirecting = true;
           break;
@@ -912,13 +933,14 @@
         SourceLibraryBuilder library = builder.library;
         if (library.isNonNullableByDefault) {
           if (constructor.isConst && lateFinalFields.isNotEmpty) {
-            builder.addProblem(messageConstConstructorLateFinalFieldError,
-                constructor.fileOffset, noLength,
-                context: lateFinalFields
-                    .map((field) =>
-                        messageConstConstructorLateFinalFieldCause.withLocation(
-                            field.fileUri, field.charOffset, noLength))
-                    .toList());
+            for (FieldBuilder field in lateFinalFields) {
+              builder.addProblem(messageConstConstructorLateFinalFieldError,
+                  field.charOffset, noLength,
+                  context: [
+                    messageConstConstructorLateFinalFieldCause.withLocation(
+                        constructor.fileUri, constructor.fileOffset, noLength)
+                  ]);
+            }
             lateFinalFields.clear();
           }
         }
@@ -963,9 +985,12 @@
     for (FieldBuilder fieldBuilder in uninitializedFields) {
       if (initializedFields == null ||
           !initializedFields.contains(fieldBuilder)) {
+        bool uninitializedFinalOrNonNullableFieldIsError =
+            cls.enclosingLibrary.isNonNullableByDefault ||
+                (cls.constructors.isNotEmpty || cls.isMixinDeclaration);
         if (!fieldBuilder.isLate) {
           if (fieldBuilder.isFinal &&
-              (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
+              uninitializedFinalOrNonNullableFieldIsError) {
             String uri = '${fieldBuilder.library.importUri}';
             String file = fieldBuilder.fileUri.pathSegments.last;
             if (uri == 'dart:html' ||
@@ -984,7 +1009,7 @@
             }
           } else if (fieldBuilder.fieldType is! InvalidType &&
               fieldBuilder.fieldType.isPotentiallyNonNullable &&
-              (cls.constructors.isNotEmpty || cls.isMixinDeclaration)) {
+              uninitializedFinalOrNonNullableFieldIsError) {
             SourceLibraryBuilder library = builder.library;
             if (library.isNonNullableByDefault) {
               library.addProblem(
@@ -1035,9 +1060,15 @@
                   templateFieldNonNullableNotInitializedByConstructorError
                       .withArguments(fieldBuilder.name, fieldBuilder.field.type,
                           library.isNonNullableByDefault),
-                  fieldBuilder.charOffset,
-                  fieldBuilder.name.length,
-                  fieldBuilder.fileUri);
+                  constructorBuilder.charOffset,
+                  noLength,
+                  constructorBuilder.fileUri,
+                  context: [
+                    templateMissingImplementationCause
+                        .withArguments(fieldBuilder.name)
+                        .withLocation(fieldBuilder.fileUri,
+                            fieldBuilder.charOffset, fieldBuilder.name.length)
+                  ]);
             }
           }
         }
@@ -1072,7 +1103,7 @@
           patchFieldNames.remove(name);
         }
       });
-      Set<String> kernelFieldNames = cls.fields.map((f) => f.name.name).toSet();
+      Set<String> kernelFieldNames = cls.fields.map((f) => f.name.text).toSet();
       return kernelFieldNames.containsAll(patchFieldNames);
     }(),
         "Fields of class '${builder.fullNameForErrors}' "
@@ -1119,7 +1150,7 @@
     if (loader.target.context.options
         .isExperimentEnabledGlobally(ExperimentalFlag.valueClass)) {
       valueClass.transformComponent(
-          component, loader.coreTypes, loader.hierarchy);
+          component, loader.coreTypes, loader.hierarchy, environment);
       ticker.logMs("Lowered value classes");
     }
 
@@ -1161,6 +1192,9 @@
         logger: (String msg) => ticker.logMs(msg));
   }
 
+  constants.EvaluationMode getConstantEvaluationModeForTesting() =>
+      _getConstantEvaluationMode();
+
   constants.EvaluationMode _getConstantEvaluationMode() {
     constants.EvaluationMode evaluationMode;
     // If nnbd is not enabled we will use weak evaluation mode. This is needed
@@ -1239,7 +1273,7 @@
   Class superclass = cls.superclass;
   if (superclass != null) {
     for (Constructor constructor in superclass.constructors) {
-      if (constructor.name.name.isEmpty) {
+      if (constructor.name.text.isEmpty) {
         return constructor.function.requiredParameterCount == 0
             ? constructor
             : null;
@@ -1278,3 +1312,39 @@
     target.type = substitute(source.type, substitutionMap);
   }
 }
+
+class ClonedFunctionNode {
+  final Map<TypeParameter, DartType> _typeSubstitution;
+  final FunctionNode _original;
+  final FunctionNode _clone;
+
+  ClonedFunctionNode(this._typeSubstitution, this._original, this._clone);
+
+  void cloneDefaultValues() {
+    // TODO(ahe): It is unclear if it is legal to use type variables in
+    // default values, but Fasta is currently allowing it, and the VM
+    // accepts it. If it isn't legal, the we can speed this up by using a
+    // single cloner without substitution.
+    CloneVisitorNotMembers cloner;
+
+    void cloneInitializer(VariableDeclaration originalParameter,
+        VariableDeclaration clonedParameter) {
+      if (originalParameter.initializer != null) {
+        cloner ??=
+            new CloneVisitorNotMembers(typeSubstitution: _typeSubstitution);
+        clonedParameter.initializer = cloner
+            .clone(originalParameter.initializer)
+              ..parent = clonedParameter;
+      }
+    }
+
+    for (int i = 0; i < _original.positionalParameters.length; i++) {
+      cloneInitializer(
+          _original.positionalParameters[i], _clone.positionalParameters[i]);
+    }
+
+    for (int i = 0; i < _original.namedParameters.length; i++) {
+      cloneInitializer(_original.namedParameters[i], _clone.namedParameters[i]);
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
index 9cfb1fc..3458ee9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/late_lowering.dart
@@ -5,6 +5,8 @@
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/core_types.dart';
 
+import '../../base/nnbd_mode.dart';
+import '../source/source_library_builder.dart';
 import '../names.dart';
 
 const String lateFieldPrefix = '_#';
@@ -26,65 +28,95 @@
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
-    Expression createIsSetWrite(Expression value)}) {
-  if (type.isPotentiallyNullable) {
-    // Generate:
-    //
-    //    if (!_#isSet#field) {
-    //      _#field = <init>;
-    //      _#isSet#field = true
-    //    }
-    //    return _#field;
-    return new Block(<Statement>[
-      new IfStatement(
-          new Not(createIsSetRead()..fileOffset = fileOffset)
-            ..fileOffset = fileOffset,
-          new Block(<Statement>[
-            new ExpressionStatement(
-                createVariableWrite(initializer)..fileOffset = fileOffset)
+    Expression createIsSetWrite(Expression value),
+    IsSetEncoding isSetEncoding}) {
+  assert(isSetEncoding != null);
+  switch (isSetEncoding) {
+    case IsSetEncoding.useIsSetField:
+      // Generate:
+      //
+      //    if (!_#isSet#field) {
+      //      _#field = <init>;
+      //      _#isSet#field = true
+      //    }
+      //    return _#field;
+      return new Block(<Statement>[
+        new IfStatement(
+            new Not(createIsSetRead()..fileOffset = fileOffset)
               ..fileOffset = fileOffset,
-            new ExpressionStatement(
-                createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset)
-              ..fileOffset = fileOffset,
-          ]),
-          null)
-        ..fileOffset = fileOffset,
-      new ReturnStatement(
-          // If [type] is a type variable with undetermined nullability we need
-          // to create a read of the field that is promoted to the type variable
-          // type.
-          createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
-        ..fileOffset = fileOffset
-    ])
-      ..fileOffset = fileOffset;
-  } else {
-    // Generate:
-    //
-    //    return let # = _#field in # == null ? _#field = <init> : #;
-    VariableDeclaration variable = new VariableDeclaration.forValue(
-        createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
-        type: type.withDeclaredNullability(Nullability.nullable))
-      ..fileOffset = fileOffset;
-    return new ReturnStatement(
-        new Let(
-            variable,
-            new ConditionalExpression(
-                new MethodInvocation(
-                    new VariableGet(variable)..fileOffset = fileOffset,
-                    equalsName,
-                    new Arguments(<Expression>[
-                      new NullLiteral()..fileOffset = fileOffset
-                    ])
-                      ..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset,
-                createVariableWrite(initializer)..fileOffset = fileOffset,
-                new VariableGet(variable, type)..fileOffset = fileOffset,
-                type)
-              ..fileOffset = fileOffset)
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
+            new Block(<Statement>[
+              new ExpressionStatement(
+                  createVariableWrite(initializer)..fileOffset = fileOffset)
+                ..fileOffset = fileOffset,
+              new ExpressionStatement(
+                  createIsSetWrite(
+                      new BoolLiteral(true)..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset)
+                ..fileOffset = fileOffset,
+            ]),
+            null)
+          ..fileOffset = fileOffset,
+        new ReturnStatement(
+            // If [type] is a type variable with undetermined nullability we
+            // need to create a read of the field that is promoted to the type
+            // variable type.
+            createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
+          ..fileOffset = fileOffset
+      ])
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useSentinel:
+      // Generate:
+      //
+      //    return let # = _#field in isSentinel(#) ? _#field = <init> : #;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
+          type: type.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new StaticInvocation(
+                      coreTypes.isSentinelMethod,
+                      new Arguments(<Expression>[
+                        new VariableGet(variable)..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  createVariableWrite(initializer)..fileOffset = fileOffset,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useNull:
+      // Generate:
+      //
+      //    return let # = _#field in # == null ? _#field = <init> : #;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
+          type: type.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new MethodInvocation(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      equalsName,
+                      new Arguments(<Expression>[
+                        new NullLiteral()..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  createVariableWrite(initializer)..fileOffset = fileOffset,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
   }
+  throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
 }
 
 /// Creates the body for the synthesized getter used to encode the lowering
@@ -104,7 +136,8 @@
     {Expression createVariableRead({bool needsPromotion}),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
-    Expression createIsSetWrite(Expression value)}) {
+    Expression createIsSetWrite(Expression value),
+    IsSetEncoding isSetEncoding}) {
   Expression exception = new Throw(new ConstructorInvocation(
       coreTypes.lateInitializationErrorConstructor,
       new Arguments(<Expression>[
@@ -119,93 +152,141 @@
   VariableDeclaration temp =
       new VariableDeclaration.forValue(initializer, type: type)
         ..fileOffset = fileOffset;
-  if (type.isPotentiallyNullable) {
-    // Generate:
-    //
-    //    if (!_#isSet#field) {
-    //      var temp = <init>;
-    //      if (_#isSet#field) throw '...'
-    //      _#field = temp;
-    //      _#isSet#field = true
-    //    }
-    //    return _#field;
-    return new Block(<Statement>[
-      new IfStatement(
-          new Not(createIsSetRead()..fileOffset = fileOffset)
-            ..fileOffset = fileOffset,
-          new Block(<Statement>[
-            temp,
-            new IfStatement(
-                createIsSetRead()..fileOffset = fileOffset,
-                new ExpressionStatement(exception)..fileOffset = fileOffset,
-                null)
+  switch (isSetEncoding) {
+    case IsSetEncoding.useIsSetField:
+      // Generate:
+      //
+      //    if (!_#isSet#field) {
+      //      var temp = <init>;
+      //      if (_#isSet#field) throw '...'
+      //      _#field = temp;
+      //      _#isSet#field = true
+      //    }
+      //    return _#field;
+      return new Block(<Statement>[
+        new IfStatement(
+            new Not(createIsSetRead()..fileOffset = fileOffset)
               ..fileOffset = fileOffset,
-            new ExpressionStatement(
-                createVariableWrite(
-                    new VariableGet(temp)..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset)
-              ..fileOffset = fileOffset,
-            new ExpressionStatement(
-                createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset)
-              ..fileOffset = fileOffset,
-          ]),
-          null)
-        ..fileOffset = fileOffset,
-      new ReturnStatement(
-          // If [type] is a type variable with undetermined nullability we need
-          // to create a read of the field that is promoted to the type variable
-          // type.
-          createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
-        ..fileOffset = fileOffset
-    ])
-      ..fileOffset = fileOffset;
-  } else {
-    // Generate:
-    //
-    //    return let #1 = _#field in #1 == null
-    //        ? let #2 = <init> in _#field == null ? _#field = #2 : throw '...'
-    //        : #1;
-    VariableDeclaration variable = new VariableDeclaration.forValue(
-        createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
-        type: type.withDeclaredNullability(Nullability.nullable))
-      ..fileOffset = fileOffset;
-    return new ReturnStatement(
-        new Let(
-            variable,
-            new ConditionalExpression(
-                new MethodInvocation(
-                    new VariableGet(variable)..fileOffset = fileOffset,
-                    equalsName,
-                    new Arguments(<Expression>[
-                      new NullLiteral()..fileOffset = fileOffset
-                    ])
-                      ..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset,
-                new Let(
-                    temp,
-                    new ConditionalExpression(
-                        new MethodInvocation(
-                            createVariableRead(needsPromotion: false)
-                              ..fileOffset = fileOffset,
-                            equalsName,
-                            new Arguments(<Expression>[
-                              new NullLiteral()..fileOffset = fileOffset
-                            ])
-                              ..fileOffset = fileOffset)
-                          ..fileOffset = fileOffset,
-                        createVariableWrite(
-                            new VariableGet(temp)..fileOffset = fileOffset)
-                          ..fileOffset = fileOffset,
-                        exception,
-                        type)
-                      ..fileOffset = fileOffset),
-                new VariableGet(variable, type)..fileOffset = fileOffset,
-                type)
-              ..fileOffset = fileOffset)
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
+            new Block(<Statement>[
+              temp,
+              new IfStatement(
+                  createIsSetRead()..fileOffset = fileOffset,
+                  new ExpressionStatement(exception)..fileOffset = fileOffset,
+                  null)
+                ..fileOffset = fileOffset,
+              new ExpressionStatement(
+                  createVariableWrite(
+                      new VariableGet(temp)..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset)
+                ..fileOffset = fileOffset,
+              new ExpressionStatement(
+                  createIsSetWrite(
+                      new BoolLiteral(true)..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset)
+                ..fileOffset = fileOffset,
+            ]),
+            null)
+          ..fileOffset = fileOffset,
+        new ReturnStatement(
+            // If [type] is a type variable with undetermined nullability we
+            // need to create a read of the field that is promoted to the type
+            // variable type.
+            createVariableRead(needsPromotion: type.isPotentiallyNonNullable))
+          ..fileOffset = fileOffset
+      ])
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useSentinel:
+      // Generate:
+      //
+      //    return let #1 = _#field in isSentinel(#1)
+      //        ? let #2 = <init> in isSentinel(_#field)
+      //            ? _#field = #2 : throw '...'
+      //        : #1;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
+          type: type)
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new StaticInvocation(
+                      coreTypes.isSentinelMethod,
+                      new Arguments(<Expression>[
+                        new VariableGet(variable)..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  new Let(
+                      temp,
+                      new ConditionalExpression(
+                          new StaticInvocation(
+                              coreTypes.isSentinelMethod,
+                              new Arguments(<Expression>[
+                                createVariableRead(needsPromotion: false)
+                                  ..fileOffset = fileOffset
+                              ])
+                                ..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          createVariableWrite(
+                              new VariableGet(temp)..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          exception,
+                          type)
+                        ..fileOffset = fileOffset),
+                  new VariableGet(variable)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useNull:
+      // Generate:
+      //
+      //    return let #1 = _#field in #1 == null
+      //        ? let #2 = <init> in _#field == null
+      //            ? _#field = #2 : throw '...'
+      //        : #1;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead(needsPromotion: false)..fileOffset = fileOffset,
+          type: type.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new MethodInvocation(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      equalsName,
+                      new Arguments(<Expression>[
+                        new NullLiteral()..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  new Let(
+                      temp,
+                      new ConditionalExpression(
+                          new MethodInvocation(
+                              createVariableRead(needsPromotion: false)
+                                ..fileOffset = fileOffset,
+                              equalsName,
+                              new Arguments(<Expression>[
+                                new NullLiteral()..fileOffset = fileOffset
+                              ])
+                                ..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          createVariableWrite(
+                              new VariableGet(temp)..fileOffset = fileOffset)
+                            ..fileOffset = fileOffset,
+                          exception,
+                          type)
+                        ..fileOffset = fileOffset),
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
   }
+  throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
 }
 
 /// Creates the body for the synthesized getter used to encode the lowering
@@ -213,7 +294,9 @@
 Statement createGetterBodyWithoutInitializer(CoreTypes coreTypes,
     int fileOffset, String name, DartType type, String variableKindName,
     {Expression createVariableRead({bool needsPromotion}),
-    Expression createIsSetRead()}) {
+    Expression createIsSetRead(),
+    IsSetEncoding isSetEncoding}) {
+  assert(isSetEncoding != null);
   Expression exception = new Throw(new ConstructorInvocation(
       coreTypes.lateInitializationErrorConstructor,
       new Arguments(<Expression>[
@@ -224,46 +307,73 @@
         ..fileOffset = fileOffset)
     ..fileOffset = fileOffset)
     ..fileOffset = fileOffset;
-  if (type.isPotentiallyNullable) {
-    // Generate:
-    //
-    //    return _#isSet#field ? _#field : throw '...';
-    return new ReturnStatement(
-        new ConditionalExpression(
-            createIsSetRead()..fileOffset = fileOffset,
-            createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
-              ..fileOffset = fileOffset,
-            exception,
-            type)
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
-  } else {
-    // Generate:
-    //
-    //    return let # = _#field in # == null ? throw '...' : #;
-    VariableDeclaration variable = new VariableDeclaration.forValue(
-        createVariableRead()..fileOffset = fileOffset,
-        type: type.withDeclaredNullability(Nullability.nullable))
-      ..fileOffset = fileOffset;
-    return new ReturnStatement(
-        new Let(
-            variable,
-            new ConditionalExpression(
-                new MethodInvocation(
-                    new VariableGet(variable)..fileOffset = fileOffset,
-                    equalsName,
-                    new Arguments(<Expression>[
-                      new NullLiteral()..fileOffset = fileOffset
-                    ])
-                      ..fileOffset = fileOffset)
-                  ..fileOffset = fileOffset,
-                exception,
-                new VariableGet(variable, type)..fileOffset = fileOffset,
-                type)
-              ..fileOffset = fileOffset)
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
+  switch (isSetEncoding) {
+    case IsSetEncoding.useIsSetField:
+      // Generate:
+      //
+      //    return _#isSet#field ? _#field : throw '...';
+      return new ReturnStatement(
+          new ConditionalExpression(
+              createIsSetRead()..fileOffset = fileOffset,
+              createVariableRead(needsPromotion: type.isPotentiallyNonNullable)
+                ..fileOffset = fileOffset,
+              exception,
+              type)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useSentinel:
+      // Generate:
+      //
+      //    return let # = _#field in isSentinel(#) ? throw '...' : #;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead()..fileOffset = fileOffset,
+          type: type.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new StaticInvocation(
+                      coreTypes.isSentinelMethod,
+                      new Arguments(<Expression>[
+                        new VariableGet(variable)..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  exception,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useNull:
+      // Generate:
+      //
+      //    return let # = _#field in # == null ? throw '...' : #;
+      VariableDeclaration variable = new VariableDeclaration.forValue(
+          createVariableRead()..fileOffset = fileOffset,
+          type: type.withDeclaredNullability(Nullability.nullable))
+        ..fileOffset = fileOffset;
+      return new ReturnStatement(
+          new Let(
+              variable,
+              new ConditionalExpression(
+                  new MethodInvocation(
+                      new VariableGet(variable)..fileOffset = fileOffset,
+                      equalsName,
+                      new Arguments(<Expression>[
+                        new NullLiteral()..fileOffset = fileOffset
+                      ])
+                        ..fileOffset = fileOffset)
+                    ..fileOffset = fileOffset,
+                  exception,
+                  new VariableGet(variable, type)..fileOffset = fileOffset,
+                  type)
+                ..fileOffset = fileOffset)
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
   }
+  throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
 }
 
 /// Creates the body for the synthesized setter used to encode the lowering
@@ -272,7 +382,9 @@
     VariableDeclaration parameter, DartType type,
     {bool shouldReturnValue,
     Expression createVariableWrite(Expression value),
-    Expression createIsSetWrite(Expression value)}) {
+    Expression createIsSetWrite(Expression value),
+    IsSetEncoding isSetEncoding}) {
+  assert(isSetEncoding != null);
   Statement createReturn(Expression value) {
     if (shouldReturnValue) {
       return new ReturnStatement(value)..fileOffset = fileOffset;
@@ -285,27 +397,30 @@
       createVariableWrite(new VariableGet(parameter)..fileOffset = fileOffset)
         ..fileOffset = fileOffset);
 
-  if (type.isPotentiallyNullable) {
-    // Generate:
-    //
-    //    _#isSet#field = true;
-    //    return _#field = parameter
-    //
-    return new Block([
-      new ExpressionStatement(
-          createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
-            ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset,
-      assignment
-    ])
-      ..fileOffset = fileOffset;
-  } else {
-    // Generate:
-    //
-    //    return _#field = parameter
-    //
-    return assignment;
+  switch (isSetEncoding) {
+    case IsSetEncoding.useIsSetField:
+      // Generate:
+      //
+      //    _#isSet#field = true;
+      //    return _#field = parameter
+      //
+      return new Block([
+        new ExpressionStatement(
+            createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset,
+        assignment
+      ])
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useSentinel:
+    case IsSetEncoding.useNull:
+      // Generate:
+      //
+      //    return _#field = parameter
+      //
+      return assignment;
   }
+  throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
 }
 
 /// Creates the body for the synthesized setter used to encode the lowering
@@ -321,7 +436,9 @@
     Expression createVariableRead(),
     Expression createVariableWrite(Expression value),
     Expression createIsSetRead(),
-    Expression createIsSetWrite(Expression value)}) {
+    Expression createIsSetWrite(Expression value),
+    IsSetEncoding isSetEncoding}) {
+  assert(isSetEncoding != null);
   Expression exception = new Throw(new ConstructorInvocation(
       coreTypes.lateInitializationErrorConstructor,
       new Arguments(<Expression>[
@@ -341,49 +458,132 @@
     }
   }
 
-  if (type.isPotentiallyNullable) {
-    // Generate:
-    //
-    //    if (_#isSet#field) {
-    //      throw '...';
-    //    } else
-    //      _#isSet#field = true;
-    //      return _#field = parameter
-    //    }
-    return new IfStatement(
-        createIsSetRead()..fileOffset = fileOffset,
+  switch (isSetEncoding) {
+    case IsSetEncoding.useIsSetField:
+      // Generate:
+      //
+      //    if (_#isSet#field) {
+      //      throw '...';
+      //    } else
+      //      _#isSet#field = true;
+      //      return _#field = parameter
+      //    }
+      return new IfStatement(
+          createIsSetRead()..fileOffset = fileOffset,
+          new ExpressionStatement(exception)..fileOffset = fileOffset,
+          new Block([
+            new ExpressionStatement(
+                createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
+                  ..fileOffset = fileOffset)
+              ..fileOffset = fileOffset,
+            createReturn(createVariableWrite(
+                new VariableGet(parameter)..fileOffset = fileOffset)
+              ..fileOffset = fileOffset)
+          ])
+            ..fileOffset = fileOffset)
+        ..fileOffset = fileOffset;
+    case IsSetEncoding.useSentinel:
+      // Generate:
+      //
+      //    if (isSentinel(_#field)) {
+      //      return _#field = parameter;
+      //    } else {
+      //      throw '...';
+      //    }
+      return new IfStatement(
+        new StaticInvocation(
+            coreTypes.isSentinelMethod,
+            new Arguments(
+                <Expression>[createVariableRead()..fileOffset = fileOffset])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset,
+        createReturn(createVariableWrite(
+            new VariableGet(parameter)..fileOffset = fileOffset)
+          ..fileOffset = fileOffset),
         new ExpressionStatement(exception)..fileOffset = fileOffset,
-        new Block([
-          new ExpressionStatement(
-              createIsSetWrite(new BoolLiteral(true)..fileOffset = fileOffset)
-                ..fileOffset = fileOffset)
-            ..fileOffset = fileOffset,
-          createReturn(createVariableWrite(
-              new VariableGet(parameter)..fileOffset = fileOffset)
-            ..fileOffset = fileOffset)
-        ])
-          ..fileOffset = fileOffset)
-      ..fileOffset = fileOffset;
-  } else {
-    // Generate:
-    //
-    //    if (_#field == null) {
-    //      return _#field = parameter;
-    //    } else {
-    //      throw '...';
-    //    }
-    return new IfStatement(
-      new MethodInvocation(
-          createVariableRead()..fileOffset = fileOffset,
-          equalsName,
-          new Arguments(
-              <Expression>[new NullLiteral()..fileOffset = fileOffset])
-            ..fileOffset = fileOffset)
-        ..fileOffset = fileOffset,
-      createReturn(createVariableWrite(
-          new VariableGet(parameter)..fileOffset = fileOffset)
-        ..fileOffset = fileOffset),
-      new ExpressionStatement(exception)..fileOffset = fileOffset,
-    )..fileOffset = fileOffset;
+      )..fileOffset = fileOffset;
+    case IsSetEncoding.useNull:
+      // Generate:
+      //
+      //    if (_#field == null) {
+      //      return _#field = parameter;
+      //    } else {
+      //      throw '...';
+      //    }
+      return new IfStatement(
+        new MethodInvocation(
+            createVariableRead()..fileOffset = fileOffset,
+            equalsName,
+            new Arguments(
+                <Expression>[new NullLiteral()..fileOffset = fileOffset])
+              ..fileOffset = fileOffset)
+          ..fileOffset = fileOffset,
+        createReturn(createVariableWrite(
+            new VariableGet(parameter)..fileOffset = fileOffset)
+          ..fileOffset = fileOffset),
+        new ExpressionStatement(exception)..fileOffset = fileOffset,
+      )..fileOffset = fileOffset;
   }
+  throw new UnsupportedError("Unexpected IsSetEncoding $isSetEncoding");
+}
+
+/// Strategies for encoding whether a late field/local has been initialized.
+enum IsSetEncoding {
+  /// Use a boolean `isSet` field/local.
+  useIsSetField,
+
+  /// Use `null` as sentinel value to signal an uninitialized field/locals.
+  useNull,
+
+  /// Use `createSentinel`and `isSentinel` from `dart:_internal` to generate
+  /// and check a sentinel value to signal an uninitialized field/local.
+  useSentinel,
+}
+
+/// Strategies for encoding of late fields and locals.
+enum IsSetStrategy {
+  /// Always is use an `isSet` field/local to track whether the field/local has
+  /// been initialized.
+  forceUseIsSetField,
+
+  /// For potentially nullable fields/locals use an `isSet` field/local to track
+  /// whether the field/local has been initialized. Otherwise use `null` as
+  /// sentinel value to signal an uninitialized field/local.
+  ///
+  /// This strategy can only be used with sound null safety mode. In weak mode
+  /// non-nullable can be assigned `null` from legacy code and therefore `null`
+  /// doesn't work as a sentinel.
+  useIsSetFieldOrNull,
+
+  /// For potentially nullable fields/locals use `createSentinel`and
+  /// `isSentinel` from `dart:_internal` to generate and check a sentinel value
+  /// to signal an uninitialized field/local. Otherwise use `null` as
+  /// sentinel value to signal an uninitialized field/local.
+  useSentinelOrNull,
+}
+
+IsSetStrategy computeIsSetStrategy(SourceLibraryBuilder libraryBuilder) {
+  IsSetStrategy isSetStrategy = IsSetStrategy.useIsSetFieldOrNull;
+  if (libraryBuilder.loader.target.backendTarget.supportsLateLoweringSentinel) {
+    isSetStrategy = IsSetStrategy.useSentinelOrNull;
+  } else if (libraryBuilder.loader.nnbdMode != NnbdMode.Strong) {
+    isSetStrategy = IsSetStrategy.forceUseIsSetField;
+  }
+  return isSetStrategy;
+}
+
+IsSetEncoding computeIsSetEncoding(DartType type, IsSetStrategy isSetStrategy) {
+  switch (isSetStrategy) {
+    case IsSetStrategy.forceUseIsSetField:
+      return IsSetEncoding.useIsSetField;
+    case IsSetStrategy.useIsSetFieldOrNull:
+      return type.isPotentiallyNullable
+          ? IsSetEncoding.useIsSetField
+          : IsSetEncoding.useNull;
+    case IsSetStrategy.useSentinelOrNull:
+      return type.isPotentiallyNullable
+          ? IsSetEncoding.useSentinel
+          : IsSetEncoding.useNull;
+  }
+  throw new UnsupportedError("Unexpected IsSetStrategy $isSetStrategy");
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
index 4196292..9c26327 100644
--- a/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/load_library_builder.dart
@@ -51,7 +51,7 @@
     String prefix = expression.import.name;
     Name name = new Name('_#loadLibrary_$prefix', parent.library);
     Procedure referencesFrom =
-        parent.lookupLibraryReferenceProcedure(name.name, false);
+        parent.lookupLibraryReferenceProcedure(name.text, false);
     tearoff = new Procedure(
         name,
         ProcedureKind.Method,
diff --git a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
index 35757bd..3a12ab4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/redirecting_factory_body.dart
@@ -35,7 +35,7 @@
 bool isRedirectingFactoryField(Member member) {
   return member is Field &&
       member.isStatic &&
-      member.name.name == redirectingName;
+      member.name.text == redirectingName;
 }
 
 /// Name used for a synthesized let variable used to encode redirecting factory
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
index e7f565a..06556d5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_labeler.dart
@@ -369,7 +369,7 @@
           classNode.enclosingLibrary.fileUri));
       result.add(".");
     }
-    result.add(procedure.name.name);
+    result.add(procedure.name.text);
   }
 
   void visitPartialInstantiationConstant(PartialInstantiationConstant node) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/verifier.dart b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
index f17aaef..3f0877b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/verifier.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/verifier.dart
@@ -240,7 +240,7 @@
   @override
   void visitField(Field node) {
     enterTreeNode(node);
-    fileUri = checkLocation(node, node.name.name, node.fileUri);
+    fileUri = checkLocation(node, node.name.text, node.fileUri);
     super.visitField(node);
     exitTreeNode(node);
   }
@@ -248,7 +248,7 @@
   @override
   void visitProcedure(Procedure node) {
     enterTreeNode(node);
-    fileUri = checkLocation(node, node.name.name, node.fileUri);
+    fileUri = checkLocation(node, node.name.text, node.fileUri);
     super.visitProcedure(node);
     exitTreeNode(node);
   }
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index 53b4d1b..9dbff26 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -9,6 +9,8 @@
 import 'package:kernel/clone.dart' show CloneProcedureWithoutBody;
 import 'package:kernel/reference_from_index.dart' show IndexedClass;
 import 'package:kernel/src/bounds_checks.dart';
+import 'package:kernel/src/legacy_erasure.dart';
+import 'package:kernel/src/types.dart' show Types;
 import 'package:kernel/type_algebra.dart' show Substitution;
 import 'package:kernel/type_algebra.dart' as type_algebra
     show getSubstitutionMap;
@@ -43,9 +45,9 @@
 import '../kernel/type_algorithms.dart'
     show Variance, computeTypeVariableBuilderVariance;
 
-import '../names.dart' show noSuchMethodName;
+import '../names.dart' show equalsName, noSuchMethodName;
 
-import '../problems.dart' show unexpected, unhandled;
+import '../problems.dart' show unexpected, unhandled, unimplemented;
 
 import '../scope.dart';
 
@@ -490,61 +492,8 @@
   }
 
   void checkTypesInOutline(TypeEnvironment typeEnvironment) {
-    SourceLibraryBuilder libraryBuilder = this.library;
-    Library library = libraryBuilder.library;
-    final DartType bottomType = library.isNonNullableByDefault
-        ? const NeverType(Nullability.nonNullable)
-        : typeEnvironment.nullType;
-
-    // Check in bounds of own type variables.
-    for (TypeParameter parameter in cls.typeParameters) {
-      Set<TypeArgumentIssue> issues = {};
-      issues.addAll(findTypeArgumentIssues(
-              library,
-              parameter.bound,
-              typeEnvironment,
-              SubtypeCheckMode.ignoringNullabilities,
-              bottomType,
-              allowSuperBounded: true) ??
-          const []);
-      if (library.isNonNullableByDefault) {
-        issues.addAll(findTypeArgumentIssues(library, parameter.bound,
-                typeEnvironment, SubtypeCheckMode.withNullabilities, bottomType,
-                allowSuperBounded: true) ??
-            const []);
-      }
-      for (TypeArgumentIssue issue in issues) {
-        DartType argument = issue.argument;
-        TypeParameter typeParameter = issue.typeParameter;
-        if (libraryBuilder.inferredTypes.contains(argument)) {
-          // Inference in type expressions in the supertypes boils down to
-          // instantiate-to-bound which shouldn't produce anything that breaks
-          // the bounds after the non-simplicity checks are done.  So, any
-          // violation here is the result of non-simple bounds, and the error
-          // is reported elsewhere.
-          continue;
-        }
-
-        if (argument is FunctionType && argument.typeParameters.length > 0) {
-          libraryBuilder.reportTypeArgumentIssue(
-              messageGenericFunctionTypeUsedAsActualTypeArgument,
-              fileUri,
-              parameter.fileOffset,
-              null);
-        } else {
-          libraryBuilder.reportTypeArgumentIssue(
-              templateIncorrectTypeArgument.withArguments(
-                  argument,
-                  typeParameter.bound,
-                  typeParameter.name,
-                  getGenericTypeName(issue.enclosingType),
-                  library.isNonNullableByDefault),
-              fileUri,
-              parameter.fileOffset,
-              typeParameter);
-        }
-      }
-    }
+    library.checkBoundsInTypeParameters(
+        typeEnvironment, cls.typeParameters, fileUri);
 
     // Check in supers.
     if (cls.supertype != null) {
@@ -559,72 +508,47 @@
       }
     }
 
-    // Check in members.
-    for (Procedure procedure in cls.procedures) {
-      checkVarianceInFunction(procedure, typeEnvironment, cls.typeParameters);
-      libraryBuilder.checkBoundsInFunctionNode(
-          procedure.function, typeEnvironment, fileUri);
-    }
-    for (Constructor constructor in cls.constructors) {
-      libraryBuilder.checkBoundsInFunctionNode(
-          constructor.function, typeEnvironment, fileUri);
-    }
-    for (RedirectingFactoryConstructor redirecting
-        in cls.redirectingFactoryConstructors) {
-      libraryBuilder.checkBoundsInFunctionNodeParts(
-          typeEnvironment, fileUri, redirecting.fileOffset,
-          typeParameters: redirecting.typeParameters,
-          positionalParameters: redirecting.positionalParameters,
-          namedParameters: redirecting.namedParameters);
-    }
-
     forEach((String name, Builder builder) {
-      // Check fields.
       if (builder is SourceFieldBuilder) {
+        // Check fields.
         checkVarianceInField(builder, typeEnvironment, cls.typeParameters);
-        libraryBuilder.checkTypesInField(builder, typeEnvironment);
-      }
-
-      // Check initializers.
-      if (builder is FunctionBuilder &&
-          !(builder.isAbstract || builder.isExternal) &&
-          builder.formals != null) {
-        libraryBuilder.checkInitializersInFormals(
-            builder.formals, typeEnvironment);
+        library.checkTypesInField(builder, typeEnvironment);
+      } else if (builder is ProcedureBuilder) {
+        // Check procedures
+        checkVarianceInFunction(
+            builder.procedure, typeEnvironment, cls.typeParameters);
+        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+      } else {
+        assert(builder is DillMemberBuilder && builder.name == redirectingName,
+            "Unexpected member: $builder.");
       }
     });
 
-    constructors.local.forEach((String name, MemberBuilder builder) {
+    forEachConstructor((String name, MemberBuilder builder) {
       if (builder is ConstructorBuilder) {
-        if (!builder.isExternal && builder.formals != null) {
-          libraryBuilder.checkInitializersInFormals(
-              builder.formals, typeEnvironment);
-        }
+        library.checkTypesInConstructorBuilder(builder, typeEnvironment);
       } else if (builder is RedirectingFactoryBuilder) {
-        // Default values are not required on redirecting factory constructors.
+        library.checkTypesInRedirectingFactoryBuilder(builder, typeEnvironment);
       } else if (builder is ProcedureBuilder) {
         assert(builder.isFactory, "Unexpected constructor $builder.");
-        if (!builder.isExternal && builder.formals != null) {
-          libraryBuilder.checkInitializersInFormals(
-              builder.formals, typeEnvironment);
-        }
+        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
       } else {
         assert(
             // This is a synthesized constructor.
             builder is DillMemberBuilder && builder.member is Constructor,
-            "Unexpected constructor $builder.");
+            "Unexpected constructor: $builder.");
       }
-    });
+    }, includeInjectedConstructors: true);
   }
 
-  void addSyntheticConstructor(Constructor constructor) {
-    String name = constructor.name.name;
-    cls.constructors.add(constructor);
-    constructor.parent = cls;
-    DillMemberBuilder memberBuilder = new DillMemberBuilder(constructor, this);
-    memberBuilder.next = constructorScopeBuilder[name];
-    constructorScopeBuilder.addMember(name, memberBuilder);
-    if (constructor.isConst) {
+  void addSyntheticConstructor(SyntheticConstructorBuilder constructorBuilder) {
+    String name = constructorBuilder.name;
+    constructorBuilder.next = constructorScopeBuilder[name];
+    constructorScopeBuilder.addMember(name, constructorBuilder);
+    // Synthetic constructors are created after the component has been built
+    // so we need to add the constructor to the class.
+    cls.addMember(constructorBuilder.member);
+    if (constructorBuilder.isConst) {
       cls.hasConstConstructor = true;
     }
   }
@@ -716,10 +640,10 @@
     if (referencesFromIndexed != null) {
       if (procedure.isSetter) {
         referenceFrom =
-            referencesFromIndexed.lookupProcedureSetter(procedure.name.name);
+            referencesFromIndexed.lookupProcedureSetter(procedure.name.text);
       } else {
         referenceFrom =
-            referencesFromIndexed.lookupProcedureNotSetter(procedure.name.name);
+            referencesFromIndexed.lookupProcedureNotSetter(procedure.name.text);
       }
     }
 
@@ -746,7 +670,7 @@
     Procedure referenceFrom;
     if (referencesFromIndexed != null) {
       referenceFrom =
-          referencesFromIndexed.lookupProcedureNotSetter(field.name.name);
+          referencesFromIndexed.lookupProcedureNotSetter(field.name.text);
     }
     Procedure getter = new Procedure(
         field.name,
@@ -775,7 +699,7 @@
     Procedure referenceFrom;
     if (referencesFromIndexed != null) {
       referenceFrom =
-          referencesFromIndexed.lookupProcedureSetter(field.name.name);
+          referencesFromIndexed.lookupProcedureSetter(field.name.text);
     }
 
     Procedure setter = new Procedure(
@@ -1129,4 +1053,795 @@
     }
     return count;
   }
+
+  void checkOverride(
+      Types types,
+      Member declaredMember,
+      Member interfaceMember,
+      bool isSetter,
+      callback(Member declaredMember, Member interfaceMember, bool isSetter),
+      {bool isInterfaceCheck = false}) {
+    if (declaredMember == interfaceMember) {
+      return;
+    }
+    Member interfaceMemberOrigin =
+        interfaceMember.memberSignatureOrigin ?? interfaceMember;
+    if (declaredMember is Constructor || interfaceMember is Constructor) {
+      unimplemented(
+          "Constructor in override check.", declaredMember.fileOffset, fileUri);
+    }
+    if (declaredMember is Procedure && interfaceMember is Procedure) {
+      if (declaredMember.kind == interfaceMember.kind) {
+        if (declaredMember.kind == ProcedureKind.Method ||
+            declaredMember.kind == ProcedureKind.Operator) {
+          bool seenCovariant = checkMethodOverride(types, declaredMember,
+              interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+          if (seenCovariant) {
+            handleSeenCovariant(
+                types, declaredMember, interfaceMember, isSetter, callback);
+          }
+        } else if (declaredMember.kind == ProcedureKind.Getter) {
+          checkGetterOverride(types, declaredMember, interfaceMember,
+              interfaceMemberOrigin, isInterfaceCheck);
+        } else if (declaredMember.kind == ProcedureKind.Setter) {
+          bool seenCovariant = checkSetterOverride(types, declaredMember,
+              interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+          if (seenCovariant) {
+            handleSeenCovariant(
+                types, declaredMember, interfaceMember, isSetter, callback);
+          }
+        } else {
+          assert(
+              false,
+              "Unexpected procedure kind in override check: "
+              "${declaredMember.kind}");
+        }
+      }
+    } else {
+      bool declaredMemberHasGetter = declaredMember is Field ||
+          declaredMember is Procedure && declaredMember.isGetter;
+      bool interfaceMemberHasGetter = interfaceMember is Field ||
+          interfaceMember is Procedure && interfaceMember.isGetter;
+      bool declaredMemberHasSetter = (declaredMember is Field &&
+              !declaredMember.isFinal &&
+              !declaredMember.isConst) ||
+          declaredMember is Procedure && declaredMember.isSetter;
+      bool interfaceMemberHasSetter = (interfaceMember is Field &&
+              !interfaceMember.isFinal &&
+              !interfaceMember.isConst) ||
+          interfaceMember is Procedure && interfaceMember.isSetter;
+      if (declaredMemberHasGetter && interfaceMemberHasGetter) {
+        checkGetterOverride(types, declaredMember, interfaceMember,
+            interfaceMemberOrigin, isInterfaceCheck);
+      }
+      if (declaredMemberHasSetter && interfaceMemberHasSetter) {
+        bool seenCovariant = checkSetterOverride(types, declaredMember,
+            interfaceMember, interfaceMemberOrigin, isInterfaceCheck);
+        if (seenCovariant) {
+          handleSeenCovariant(
+              types, declaredMember, interfaceMember, isSetter, callback);
+        }
+      }
+    }
+    // TODO(ahe): Handle other cases: accessors, operators, and fields.
+  }
+
+  void checkGetterSetter(Types types, Member getter, Member setter) {
+    if (getter == setter) {
+      return;
+    }
+    if (cls != getter.enclosingClass &&
+        getter.enclosingClass == setter.enclosingClass) {
+      return;
+    }
+
+    DartType getterType = getter.getterType;
+    if (getter.enclosingClass.typeParameters.isNotEmpty) {
+      getterType = Substitution.fromPairs(
+              getter.enclosingClass.typeParameters,
+              types.hierarchy.getTypeArgumentsAsInstanceOf(
+                  thisType, getter.enclosingClass))
+          .substituteType(getterType);
+    }
+
+    DartType setterType = setter.setterType;
+    if (setter.enclosingClass.typeParameters.isNotEmpty) {
+      setterType = Substitution.fromPairs(
+              setter.enclosingClass.typeParameters,
+              types.hierarchy.getTypeArgumentsAsInstanceOf(
+                  thisType, setter.enclosingClass))
+          .substituteType(setterType);
+    }
+
+    if (getterType is InvalidType || setterType is InvalidType) {
+      // Don't report a problem as something else is wrong that has already
+      // been reported.
+    } else {
+      bool isValid = types.isSubtypeOf(
+          getterType,
+          setterType,
+          library.isNonNullableByDefault
+              ? SubtypeCheckMode.withNullabilities
+              : SubtypeCheckMode.ignoringNullabilities);
+      if (!isValid && !library.isNonNullableByDefault) {
+        // Allow assignability in legacy libraries.
+        isValid = types.isSubtypeOf(
+            setterType, getterType, SubtypeCheckMode.ignoringNullabilities);
+      }
+      if (!isValid) {
+        Member getterOrigin = getter.memberSignatureOrigin ?? getter;
+        Member setterOrigin = setter.memberSignatureOrigin ?? setter;
+        String getterMemberName = '${getterOrigin.enclosingClass.name}'
+            '.${getterOrigin.name.text}';
+        String setterMemberName = '${setterOrigin.enclosingClass.name}'
+            '.${setterOrigin.name.text}';
+        if (getterOrigin.enclosingClass == cls &&
+            setterOrigin.enclosingClass == cls) {
+          Template<Message Function(DartType, String, DartType, String, bool)>
+              template = library.isNonNullableByDefault
+                  ? templateInvalidGetterSetterType
+                  : templateInvalidGetterSetterTypeLegacy;
+          library.addProblem(
+              template.withArguments(getterType, getterMemberName, setterType,
+                  setterMemberName, library.isNonNullableByDefault),
+              getterOrigin.fileOffset,
+              getterOrigin.name.text.length,
+              getterOrigin.fileUri,
+              context: [
+                templateInvalidGetterSetterTypeSetterContext
+                    .withArguments(setterMemberName)
+                    .withLocation(setterOrigin.fileUri, setterOrigin.fileOffset,
+                        setterOrigin.name.text.length)
+              ]);
+        } else if (getterOrigin.enclosingClass == cls) {
+          Template<Message Function(DartType, String, DartType, String, bool)>
+              template = library.isNonNullableByDefault
+                  ? templateInvalidGetterSetterTypeSetterInheritedGetter
+                  : templateInvalidGetterSetterTypeSetterInheritedGetterLegacy;
+          if (getterOrigin is Field) {
+            template = library.isNonNullableByDefault
+                ? templateInvalidGetterSetterTypeSetterInheritedField
+                : templateInvalidGetterSetterTypeSetterInheritedFieldLegacy;
+          }
+          library.addProblem(
+              template.withArguments(getterType, getterMemberName, setterType,
+                  setterMemberName, library.isNonNullableByDefault),
+              getterOrigin.fileOffset,
+              getterOrigin.name.text.length,
+              getterOrigin.fileUri,
+              context: [
+                templateInvalidGetterSetterTypeSetterContext
+                    .withArguments(setterMemberName)
+                    .withLocation(setterOrigin.fileUri, setterOrigin.fileOffset,
+                        setterOrigin.name.text.length)
+              ]);
+        } else if (setterOrigin.enclosingClass == cls) {
+          Template<Message Function(DartType, String, DartType, String, bool)>
+              template = library.isNonNullableByDefault
+                  ? templateInvalidGetterSetterTypeGetterInherited
+                  : templateInvalidGetterSetterTypeGetterInheritedLegacy;
+          Template<Message Function(String)> context =
+              templateInvalidGetterSetterTypeGetterContext;
+          if (getterOrigin is Field) {
+            template = library.isNonNullableByDefault
+                ? templateInvalidGetterSetterTypeFieldInherited
+                : templateInvalidGetterSetterTypeFieldInheritedLegacy;
+            context = templateInvalidGetterSetterTypeFieldContext;
+          }
+          library.addProblem(
+              template.withArguments(getterType, getterMemberName, setterType,
+                  setterMemberName, library.isNonNullableByDefault),
+              setterOrigin.fileOffset,
+              setterOrigin.name.text.length,
+              setterOrigin.fileUri,
+              context: [
+                context.withArguments(getterMemberName).withLocation(
+                    getterOrigin.fileUri,
+                    getterOrigin.fileOffset,
+                    getterOrigin.name.text.length)
+              ]);
+        } else {
+          Template<Message Function(DartType, String, DartType, String, bool)>
+              template = library.isNonNullableByDefault
+                  ? templateInvalidGetterSetterTypeBothInheritedGetter
+                  : templateInvalidGetterSetterTypeBothInheritedGetterLegacy;
+          Template<Message Function(String)> context =
+              templateInvalidGetterSetterTypeGetterContext;
+          if (getterOrigin is Field) {
+            template = library.isNonNullableByDefault
+                ? templateInvalidGetterSetterTypeBothInheritedField
+                : templateInvalidGetterSetterTypeBothInheritedFieldLegacy;
+            context = templateInvalidGetterSetterTypeFieldContext;
+          }
+          library.addProblem(
+              template.withArguments(getterType, getterMemberName, setterType,
+                  setterMemberName, library.isNonNullableByDefault),
+              charOffset,
+              noLength,
+              fileUri,
+              context: [
+                context.withArguments(getterMemberName).withLocation(
+                    getterOrigin.fileUri,
+                    getterOrigin.fileOffset,
+                    getterOrigin.name.text.length),
+                templateInvalidGetterSetterTypeSetterContext
+                    .withArguments(setterMemberName)
+                    .withLocation(setterOrigin.fileUri, setterOrigin.fileOffset,
+                        setterOrigin.name.text.length)
+              ]);
+        }
+      }
+    }
+  }
+
+  Uri _getMemberUri(Member member) {
+    if (member is Field) return member.fileUri;
+    if (member is Procedure) return member.fileUri;
+    // Other member types won't be seen because constructors don't participate
+    // in override relationships
+    return unhandled('${member.runtimeType}', '_getMemberUri', -1, null);
+  }
+
+  Substitution _computeInterfaceSubstitution(
+      Types types,
+      Member declaredMember,
+      Member interfaceMember,
+      Member interfaceMemberOrigin,
+      FunctionNode declaredFunction,
+      FunctionNode interfaceFunction,
+      bool isInterfaceCheck) {
+    Substitution interfaceSubstitution = Substitution.empty;
+    if (interfaceMember.enclosingClass.typeParameters.isNotEmpty) {
+      Class enclosingClass = interfaceMember.enclosingClass;
+      interfaceSubstitution = Substitution.fromPairs(
+          enclosingClass.typeParameters,
+          types.hierarchy
+              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
+    }
+
+    if (declaredFunction?.typeParameters?.length !=
+        interfaceFunction?.typeParameters?.length) {
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
+          templateOverrideTypeVariablesMismatch.withArguments(
+              "${declaredMember.enclosingClass.name}."
+                  "${declaredMember.name.text}",
+              "${interfaceMemberOrigin.enclosingClass.name}."
+                  "${interfaceMemberOrigin.name.text}"),
+          declaredMember.fileOffset,
+          noLength,
+          context: [
+            templateOverriddenMethodCause
+                .withArguments(interfaceMemberOrigin.name.text)
+                .withLocation(_getMemberUri(interfaceMemberOrigin),
+                    interfaceMemberOrigin.fileOffset, noLength)
+          ]);
+    } else if (declaredFunction?.typeParameters != null) {
+      Map<TypeParameter, DartType> substitutionMap =
+          <TypeParameter, DartType>{};
+      for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
+        substitutionMap[interfaceFunction.typeParameters[i]] =
+            new TypeParameterType.forAlphaRenaming(
+                interfaceFunction.typeParameters[i],
+                declaredFunction.typeParameters[i]);
+      }
+      Substitution substitution = Substitution.fromMap(substitutionMap);
+      for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
+        TypeParameter declaredParameter = declaredFunction.typeParameters[i];
+        TypeParameter interfaceParameter = interfaceFunction.typeParameters[i];
+        if (!interfaceParameter.isGenericCovariantImpl) {
+          DartType declaredBound = declaredParameter.bound;
+          DartType interfaceBound = interfaceParameter.bound;
+          if (interfaceSubstitution != null) {
+            declaredBound = interfaceSubstitution.substituteType(declaredBound);
+            interfaceBound =
+                interfaceSubstitution.substituteType(interfaceBound);
+          }
+          DartType computedBound = substitution.substituteType(interfaceBound);
+          if (!library.isNonNullableByDefault) {
+            computedBound =
+                legacyErasure(types.hierarchy.coreTypes, computedBound);
+          }
+          if (!types
+              .performNullabilityAwareMutualSubtypesCheck(
+                  declaredBound, computedBound)
+              .isSubtypeWhenUsingNullabilities()) {
+            reportInvalidOverride(
+                isInterfaceCheck,
+                declaredMember,
+                templateOverrideTypeVariablesBoundMismatch.withArguments(
+                    declaredBound,
+                    declaredParameter.name,
+                    "${declaredMember.enclosingClass.name}."
+                        "${declaredMember.name.text}",
+                    computedBound,
+                    "${interfaceMemberOrigin.enclosingClass.name}."
+                        "${interfaceMemberOrigin.name.text}",
+                    library.isNonNullableByDefault),
+                declaredMember.fileOffset,
+                noLength,
+                context: [
+                  templateOverriddenMethodCause
+                      .withArguments(interfaceMemberOrigin.name.text)
+                      .withLocation(_getMemberUri(interfaceMemberOrigin),
+                          interfaceMemberOrigin.fileOffset, noLength)
+                ]);
+          }
+        }
+      }
+      interfaceSubstitution =
+          Substitution.combine(interfaceSubstitution, substitution);
+    }
+    return interfaceSubstitution;
+  }
+
+  Substitution _computeDeclaredSubstitution(
+      Types types, Member declaredMember) {
+    Substitution declaredSubstitution = Substitution.empty;
+    if (declaredMember.enclosingClass.typeParameters.isNotEmpty) {
+      Class enclosingClass = declaredMember.enclosingClass;
+      declaredSubstitution = Substitution.fromPairs(
+          enclosingClass.typeParameters,
+          types.hierarchy
+              .getTypeArgumentsAsInstanceOf(thisType, enclosingClass));
+    }
+    return declaredSubstitution;
+  }
+
+  void _checkTypes(
+      Types types,
+      Substitution interfaceSubstitution,
+      Substitution declaredSubstitution,
+      Member declaredMember,
+      Member interfaceMember,
+      Member interfaceMemberOrigin,
+      DartType declaredType,
+      DartType interfaceType,
+      bool isCovariant,
+      VariableDeclaration declaredParameter,
+      bool isInterfaceCheck,
+      {bool asIfDeclaredParameter = false}) {
+    if (interfaceSubstitution != null) {
+      interfaceType = interfaceSubstitution.substituteType(interfaceType);
+    }
+    if (declaredSubstitution != null) {
+      declaredType = declaredSubstitution.substituteType(declaredType);
+    }
+
+    if (!declaredMember.isNonNullableByDefault &&
+        interfaceMember.isNonNullableByDefault) {
+      interfaceType = legacyErasure(types.hierarchy.coreTypes, interfaceType);
+    }
+
+    bool inParameter = declaredParameter != null || asIfDeclaredParameter;
+    DartType subtype = inParameter ? interfaceType : declaredType;
+    DartType supertype = inParameter ? declaredType : interfaceType;
+
+    if (types.isSubtypeOf(
+        subtype, supertype, SubtypeCheckMode.withNullabilities)) {
+      // No problem--the proper subtyping relation is satisfied.
+    } else if (isCovariant &&
+        types.isSubtypeOf(
+            supertype, subtype, SubtypeCheckMode.withNullabilities)) {
+      // No problem--the overriding parameter is marked "covariant" and has
+      // a type which is a subtype of the parameter it overrides.
+    } else if (subtype is InvalidType || supertype is InvalidType) {
+      // Don't report a problem as something else is wrong that has already
+      // been reported.
+    } else {
+      // Report an error.
+      bool isErrorInNnbdOptedOutMode = !types.isSubtypeOf(
+              subtype, supertype, SubtypeCheckMode.ignoringNullabilities) &&
+          (!isCovariant ||
+              !types.isSubtypeOf(
+                  supertype, subtype, SubtypeCheckMode.ignoringNullabilities));
+      if (isErrorInNnbdOptedOutMode || library.isNonNullableByDefault) {
+        String declaredMemberName = '${declaredMember.enclosingClass.name}'
+            '.${declaredMember.name.text}';
+        String interfaceMemberName =
+            '${interfaceMemberOrigin.enclosingClass.name}'
+            '.${interfaceMemberOrigin.name.text}';
+        Message message;
+        int fileOffset;
+        if (declaredParameter == null) {
+          if (asIfDeclaredParameter) {
+            // Setter overridden by field
+            message = templateOverrideTypeMismatchSetter.withArguments(
+                declaredMemberName,
+                declaredType,
+                interfaceType,
+                interfaceMemberName,
+                library.isNonNullableByDefault);
+          } else {
+            message = templateOverrideTypeMismatchReturnType.withArguments(
+                declaredMemberName,
+                declaredType,
+                interfaceType,
+                interfaceMemberName,
+                library.isNonNullableByDefault);
+          }
+          fileOffset = declaredMember.fileOffset;
+        } else {
+          message = templateOverrideTypeMismatchParameter.withArguments(
+              declaredParameter.name,
+              declaredMemberName,
+              declaredType,
+              interfaceType,
+              interfaceMemberName,
+              library.isNonNullableByDefault);
+          fileOffset = declaredParameter.fileOffset;
+        }
+        reportInvalidOverride(
+            isInterfaceCheck, declaredMember, message, fileOffset, noLength,
+            context: [
+              templateOverriddenMethodCause
+                  .withArguments(interfaceMemberOrigin.name.text)
+                  .withLocation(_getMemberUri(interfaceMemberOrigin),
+                      interfaceMemberOrigin.fileOffset, noLength)
+            ]);
+      }
+    }
+  }
+
+  /// Checks whether [declaredMember] correctly overrides [interfaceMember].
+  ///
+  /// If an error is reporter [interfaceMemberOrigin] is used as the context
+  /// for where [interfaceMember] was declared, since [interfaceMember] might
+  /// itself be synthesized.
+  ///
+  /// Returns whether a covariant parameter was seen and more methods thus have
+  /// to be checked.
+  bool checkMethodOverride(
+      Types types,
+      Procedure declaredMember,
+      Procedure interfaceMember,
+      Member interfaceMemberOrigin,
+      bool isInterfaceCheck) {
+    assert(declaredMember.kind == interfaceMember.kind);
+    assert(declaredMember.kind == ProcedureKind.Method ||
+        declaredMember.kind == ProcedureKind.Operator);
+    bool seenCovariant = false;
+    FunctionNode declaredFunction = declaredMember.function;
+    FunctionNode interfaceFunction = interfaceMember.function;
+
+    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
+        types,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        declaredFunction,
+        interfaceFunction,
+        isInterfaceCheck);
+
+    Substitution declaredSubstitution =
+        _computeDeclaredSubstitution(types, declaredMember);
+
+    _checkTypes(
+        types,
+        interfaceSubstitution,
+        declaredSubstitution,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        declaredFunction.returnType,
+        interfaceFunction.returnType,
+        false,
+        null,
+        isInterfaceCheck);
+    if (declaredFunction.positionalParameters.length <
+        interfaceFunction.positionalParameters.length) {
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
+          templateOverrideFewerPositionalArguments.withArguments(
+              "${declaredMember.enclosingClass.name}."
+                  "${declaredMember.name.text}",
+              "${interfaceMember.enclosingClass.name}."
+                  "${interfaceMember.name.text}"),
+          declaredMember.fileOffset,
+          noLength,
+          context: [
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.text)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, noLength)
+          ]);
+    }
+    if (interfaceFunction.requiredParameterCount <
+        declaredFunction.requiredParameterCount) {
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
+          templateOverrideMoreRequiredArguments.withArguments(
+              "${declaredMember.enclosingClass.name}."
+                  "${declaredMember.name.text}",
+              "${interfaceMember.enclosingClass.name}."
+                  "${interfaceMember.name.text}"),
+          declaredMember.fileOffset,
+          noLength,
+          context: [
+            templateOverriddenMethodCause
+                .withArguments(interfaceMember.name.text)
+                .withLocation(interfaceMember.fileUri,
+                    interfaceMember.fileOffset, noLength)
+          ]);
+    }
+    for (int i = 0;
+        i < declaredFunction.positionalParameters.length &&
+            i < interfaceFunction.positionalParameters.length;
+        i++) {
+      VariableDeclaration declaredParameter =
+          declaredFunction.positionalParameters[i];
+      VariableDeclaration interfaceParameter =
+          interfaceFunction.positionalParameters[i];
+      if (i == 0 &&
+          declaredMember.name == equalsName &&
+          declaredParameter.type ==
+              types.hierarchy.coreTypes.objectNonNullableRawType &&
+          interfaceParameter.type is DynamicType) {
+        // TODO(johnniwinther): Add check for opt-in overrides of operator ==.
+        // `operator ==` methods in opt-out classes have type
+        // `bool Function(dynamic)`.
+        continue;
+      }
+
+      _checkTypes(
+          types,
+          interfaceSubstitution,
+          declaredSubstitution,
+          declaredMember,
+          interfaceMember,
+          interfaceMemberOrigin,
+          declaredParameter.type,
+          interfaceParameter.type,
+          declaredParameter.isCovariant || interfaceParameter.isCovariant,
+          declaredParameter,
+          isInterfaceCheck);
+      if (declaredParameter.isCovariant) seenCovariant = true;
+    }
+    if (declaredFunction.namedParameters.isEmpty &&
+        interfaceFunction.namedParameters.isEmpty) {
+      return seenCovariant;
+    }
+    if (declaredFunction.namedParameters.length <
+        interfaceFunction.namedParameters.length) {
+      reportInvalidOverride(
+          isInterfaceCheck,
+          declaredMember,
+          templateOverrideFewerNamedArguments.withArguments(
+              "${declaredMember.enclosingClass.name}."
+                  "${declaredMember.name.text}",
+              "${interfaceMemberOrigin.enclosingClass.name}."
+                  "${interfaceMemberOrigin.name.text}"),
+          declaredMember.fileOffset,
+          noLength,
+          context: [
+            templateOverriddenMethodCause
+                .withArguments(interfaceMemberOrigin.name.text)
+                .withLocation(interfaceMemberOrigin.fileUri,
+                    interfaceMemberOrigin.fileOffset, noLength)
+          ]);
+    }
+    int compareNamedParameters(VariableDeclaration p0, VariableDeclaration p1) {
+      return p0.name.compareTo(p1.name);
+    }
+
+    List<VariableDeclaration> sortedFromDeclared =
+        new List.from(declaredFunction.namedParameters)
+          ..sort(compareNamedParameters);
+    List<VariableDeclaration> sortedFromInterface =
+        new List.from(interfaceFunction.namedParameters)
+          ..sort(compareNamedParameters);
+    Iterator<VariableDeclaration> declaredNamedParameters =
+        sortedFromDeclared.iterator;
+    Iterator<VariableDeclaration> interfaceNamedParameters =
+        sortedFromInterface.iterator;
+    outer:
+    while (declaredNamedParameters.moveNext() &&
+        interfaceNamedParameters.moveNext()) {
+      while (declaredNamedParameters.current.name !=
+          interfaceNamedParameters.current.name) {
+        if (!declaredNamedParameters.moveNext()) {
+          reportInvalidOverride(
+              isInterfaceCheck,
+              declaredMember,
+              templateOverrideMismatchNamedParameter.withArguments(
+                  "${declaredMember.enclosingClass.name}."
+                      "${declaredMember.name.text}",
+                  interfaceNamedParameters.current.name,
+                  "${interfaceMember.enclosingClass.name}."
+                      "${interfaceMember.name.text}"),
+              declaredMember.fileOffset,
+              noLength,
+              context: [
+                templateOverriddenMethodCause
+                    .withArguments(interfaceMember.name.text)
+                    .withLocation(interfaceMember.fileUri,
+                        interfaceMember.fileOffset, noLength)
+              ]);
+          break outer;
+        }
+      }
+      VariableDeclaration declaredParameter = declaredNamedParameters.current;
+      _checkTypes(
+          types,
+          interfaceSubstitution,
+          declaredSubstitution,
+          declaredMember,
+          interfaceMember,
+          interfaceMemberOrigin,
+          declaredParameter.type,
+          interfaceNamedParameters.current.type,
+          declaredParameter.isCovariant,
+          declaredParameter,
+          isInterfaceCheck);
+      if (declaredMember.isNonNullableByDefault &&
+          declaredParameter.isRequired &&
+          interfaceMember.isNonNullableByDefault &&
+          !interfaceNamedParameters.current.isRequired) {
+        reportInvalidOverride(
+            isInterfaceCheck,
+            declaredMember,
+            templateOverrideMismatchRequiredNamedParameter.withArguments(
+                declaredParameter.name,
+                "${declaredMember.enclosingClass.name}."
+                    "${declaredMember.name.text}",
+                "${interfaceMember.enclosingClass.name}."
+                    "${interfaceMember.name.text}"),
+            declaredParameter.fileOffset,
+            noLength,
+            context: [
+              templateOverriddenMethodCause
+                  .withArguments(interfaceMemberOrigin.name.text)
+                  .withLocation(_getMemberUri(interfaceMemberOrigin),
+                      interfaceMemberOrigin.fileOffset, noLength)
+            ]);
+      }
+      if (declaredParameter.isCovariant) seenCovariant = true;
+    }
+    return seenCovariant;
+  }
+
+  /// Checks whether [declaredMember] correctly overrides [interfaceMember].
+  ///
+  /// If an error is reporter [interfaceMemberOrigin] is used as the context
+  /// for where [interfaceMember] was declared, since [interfaceMember] might
+  /// itself be synthesized.
+  void checkGetterOverride(
+      Types types,
+      Member declaredMember,
+      Member interfaceMember,
+      Member interfaceMemberOrigin,
+      bool isInterfaceCheck) {
+    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
+        types,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        /* declaredFunction = */ null,
+        /* interfaceFunction = */ null,
+        isInterfaceCheck);
+    Substitution declaredSubstitution =
+        _computeDeclaredSubstitution(types, declaredMember);
+    DartType declaredType = declaredMember.getterType;
+    DartType interfaceType = interfaceMember.getterType;
+    _checkTypes(
+        types,
+        interfaceSubstitution,
+        declaredSubstitution,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        declaredType,
+        interfaceType,
+        /* isCovariant = */ false,
+        /* declaredParameter = */ null,
+        isInterfaceCheck);
+  }
+
+  /// Checks whether [declaredMember] correctly overrides [interfaceMember].
+  ///
+  /// If an error is reporter [interfaceMemberOrigin] is used as the context
+  /// for where [interfaceMember] was declared, since [interfaceMember] might
+  /// itself be synthesized.
+  ///
+  /// Returns whether a covariant parameter was seen and more methods thus have
+  /// to be checked.
+  bool checkSetterOverride(
+      Types types,
+      Member declaredMember,
+      Member interfaceMember,
+      Member interfaceMemberOrigin,
+      bool isInterfaceCheck) {
+    Substitution interfaceSubstitution = _computeInterfaceSubstitution(
+        types,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        /* declaredFunction = */ null,
+        /* interfaceFunction = */ null,
+        isInterfaceCheck);
+    Substitution declaredSubstitution =
+        _computeDeclaredSubstitution(types, declaredMember);
+    DartType declaredType = declaredMember.setterType;
+    DartType interfaceType = interfaceMember.setterType;
+    VariableDeclaration declaredParameter =
+        declaredMember.function?.positionalParameters?.elementAt(0);
+    bool isCovariant = declaredParameter?.isCovariant ?? false;
+    if (!isCovariant && declaredMember is Field) {
+      isCovariant = declaredMember.isCovariant;
+    }
+    if (!isCovariant && interfaceMember is Field) {
+      isCovariant = interfaceMember.isCovariant;
+    }
+    _checkTypes(
+        types,
+        interfaceSubstitution,
+        declaredSubstitution,
+        declaredMember,
+        interfaceMember,
+        interfaceMemberOrigin,
+        declaredType,
+        interfaceType,
+        isCovariant,
+        declaredParameter,
+        isInterfaceCheck,
+        asIfDeclaredParameter: true);
+    return isCovariant;
+  }
+
+  // When the overriding member is inherited, report the class containing
+  // the conflict as the main error.
+  void reportInvalidOverride(bool isInterfaceCheck, Member declaredMember,
+      Message message, int fileOffset, int length,
+      {List<LocatedMessage> context}) {
+    if (shouldOverrideProblemBeOverlooked(this)) {
+      return;
+    }
+
+    if (declaredMember.enclosingClass == cls) {
+      // Ordinary override
+      library.addProblem(message, fileOffset, length, declaredMember.fileUri,
+          context: context);
+    } else {
+      context = [
+        message.withLocation(declaredMember.fileUri, fileOffset, length),
+        ...?context
+      ];
+      if (isInterfaceCheck) {
+        // Interface check
+        library.addProblem(
+            templateInterfaceCheck.withArguments(
+                declaredMember.name.text, cls.name),
+            cls.fileOffset,
+            cls.name.length,
+            cls.fileUri,
+            context: context);
+      } else {
+        if (cls.isAnonymousMixin) {
+          // Implicit mixin application class
+          String baseName = cls.superclass.demangledName;
+          String mixinName = cls.mixedInClass.name;
+          int classNameLength = cls.nameAsMixinApplicationSubclass.length;
+          library.addProblem(
+              templateImplicitMixinOverride.withArguments(
+                  mixinName, baseName, declaredMember.name.text),
+              cls.fileOffset,
+              classNameLength,
+              cls.fileUri,
+              context: context);
+        } else {
+          // Named mixin application class
+          library.addProblem(
+              templateNamedMixinOverride.withArguments(
+                  cls.name, declaredMember.name.text),
+              cls.fileOffset,
+              cls.name.length,
+              cls.fileUri,
+              context: context);
+        }
+      }
+    }
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
index 6792c0d..867fb41 100644
--- a/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_extension_builder.dart
@@ -5,15 +5,18 @@
 import 'dart:core' hide MapEntry;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/type_environment.dart';
 
 import '../../base/common.dart';
 
 import '../builder/builder.dart';
 import '../builder/class_builder.dart';
 import '../builder/extension_builder.dart';
+import '../builder/field_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/metadata_builder.dart';
+import '../builder/procedure_builder.dart';
 import '../builder/type_builder.dart';
 import '../builder/type_variable_builder.dart';
 
@@ -61,6 +64,9 @@
             typeParameters, onType);
 
   @override
+  SourceLibraryBuilder get library => super.library;
+
+  @override
   SourceExtensionBuilder get origin => _origin ?? this;
 
   Extension get extension => isPatch ? origin._extension : _extension;
@@ -231,4 +237,35 @@
     });
     return count;
   }
+
+  void checkTypesInOutline(TypeEnvironment typeEnvironment) {
+    library.checkBoundsInTypeParameters(
+        typeEnvironment, extension.typeParameters, fileUri);
+
+    // Check on clause.
+    if (_extension.onType != null) {
+      library.checkBoundsInType(_extension.onType, typeEnvironment,
+          onType.fileUri, onType.charOffset);
+    }
+
+    forEach((String name, Builder builder) {
+      if (builder is SourceFieldBuilder) {
+        // Check fields.
+        library.checkTypesInField(builder, typeEnvironment);
+      } else if (builder is ProcedureBuilder) {
+        // Check procedures
+        library.checkTypesInProcedureBuilder(builder, typeEnvironment);
+        if (builder.isGetter) {
+          Builder setterDeclaration =
+              scope.lookupLocalMember(builder.name, setter: true);
+          if (setterDeclaration != null) {
+            library.checkGetterSetterTypes(
+                builder, setterDeclaration, typeEnvironment);
+          }
+        }
+      } else {
+        assert(false, "Unexpected member: $builder.");
+      }
+    });
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 6df5e4c..0bd7da5 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -67,7 +67,7 @@
         findTypeArgumentIssuesForInvocation,
         getGenericTypeName;
 
-import 'package:kernel/type_algebra.dart' show substitute;
+import 'package:kernel/type_algebra.dart' show Substitution, substitute;
 
 import 'package:kernel/type_environment.dart'
     show SubtypeCheckMode, TypeEnvironment;
@@ -477,12 +477,6 @@
         } else {
           loader.registerStrongOptOutLibrary(this);
         }
-        _languageVersion = new InvalidLanguageVersion(
-            fileUri,
-            _languageVersion.charOffset,
-            _languageVersion.charCount,
-            _languageVersion.isExplicit,
-            loader.target.currentSdkVersion);
       }
     }
     _languageVersion.isFinal = true;
@@ -1616,6 +1610,100 @@
     return typeVariablesByName;
   }
 
+  void checkGetterSetterTypes(ProcedureBuilder getterBuilder,
+      ProcedureBuilder setterBuilder, TypeEnvironment typeEnvironment) {
+    DartType getterType;
+    List<TypeParameter> getterExtensionTypeParameters;
+    if (getterBuilder.isExtensionInstanceMember) {
+      // An extension instance getter
+      //
+      //     extension E<T> on A {
+      //       T get property => ...
+      //     }
+      //
+      // is encoded as a top level method
+      //
+      //   T# E#get#property<T#>(A #this) => ...
+      //
+      Procedure procedure = getterBuilder.procedure;
+      getterType = procedure.function.returnType;
+      getterExtensionTypeParameters = procedure.function.typeParameters;
+    } else {
+      getterType = getterBuilder.procedure.getterType;
+    }
+    DartType setterType;
+    if (setterBuilder.isExtensionInstanceMember) {
+      // An extension instance setter
+      //
+      //     extension E<T> on A {
+      //       void set property(T value) { ... }
+      //     }
+      //
+      // is encoded as a top level method
+      //
+      //   void E#set#property<T#>(A #this, T# value) { ... }
+      //
+      Procedure procedure = setterBuilder.procedure;
+      setterType = procedure.function.positionalParameters[1].type;
+      if (getterExtensionTypeParameters != null &&
+          getterExtensionTypeParameters.isNotEmpty) {
+        // We substitute the setter type parameters for the getter type
+        // parameters to check them below in a shared context.
+        List<TypeParameter> setterExtensionTypeParameters =
+            procedure.function.typeParameters;
+        assert(getterExtensionTypeParameters.length ==
+            setterExtensionTypeParameters.length);
+        setterType = Substitution.fromPairs(
+                setterExtensionTypeParameters,
+                new List<DartType>.generate(
+                    getterExtensionTypeParameters.length,
+                    (int index) => new TypeParameterType.forAlphaRenaming(
+                        setterExtensionTypeParameters[index],
+                        getterExtensionTypeParameters[index])))
+            .substituteType(setterType);
+      }
+    } else {
+      setterType = setterBuilder.procedure.setterType;
+    }
+
+    if (getterType is InvalidType || setterType is InvalidType) {
+      // Don't report a problem as something else is wrong that has already
+      // been reported.
+    } else {
+      bool isValid = typeEnvironment.isSubtypeOf(
+          getterType,
+          setterType,
+          library.isNonNullableByDefault
+              ? SubtypeCheckMode.withNullabilities
+              : SubtypeCheckMode.ignoringNullabilities);
+      if (!isValid && !library.isNonNullableByDefault) {
+        // Allow assignability in legacy libraries.
+        isValid = typeEnvironment.isSubtypeOf(
+            setterType, getterType, SubtypeCheckMode.ignoringNullabilities);
+      }
+      if (!isValid) {
+        String getterMemberName = getterBuilder.fullNameForErrors;
+        String setterMemberName = setterBuilder.fullNameForErrors;
+        Template<Message Function(DartType, String, DartType, String, bool)>
+            template = library.isNonNullableByDefault
+                ? templateInvalidGetterSetterType
+                : templateInvalidGetterSetterTypeLegacy;
+        addProblem(
+            template.withArguments(getterType, getterMemberName, setterType,
+                setterMemberName, library.isNonNullableByDefault),
+            getterBuilder.charOffset,
+            getterBuilder.name.length,
+            getterBuilder.fileUri,
+            context: [
+              templateInvalidGetterSetterTypeSetterContext
+                  .withArguments(setterMemberName)
+                  .withLocation(setterBuilder.fileUri, setterBuilder.charOffset,
+                      setterBuilder.name.length)
+            ]);
+      }
+    }
+  }
+
   void addExtensionDeclaration(
       String documentationComment,
       List<MetadataBuilder> metadata,
@@ -1903,7 +1991,9 @@
           isMixinDeclaration ? null : supertype,
           isNamedMixinApplication
               ? interfaces
-              : isMixinDeclaration ? [supertype, mixin] : null,
+              : isMixinDeclaration
+                  ? [supertype, mixin]
+                  : null,
           null, // No `on` clause types.
           new Scope(
               local: <String, MemberBuilder>{},
@@ -2172,7 +2262,7 @@
     MetadataCollector metadataCollector = loader.target.metadataCollector;
     if (returnType == null) {
       if (kind == ProcedureKind.Operator &&
-          identical(name, indexSetName.name)) {
+          identical(name, indexSetName.text)) {
         returnType = addVoidType(charOffset);
       } else if (kind == ProcedureKind.Setter) {
         returnType = addVoidType(charOffset);
@@ -2736,7 +2826,7 @@
         VariableDeclaration originNamed = originNamedMap[forwarderNamed.name];
         if (originNamed == null) {
           return unhandled(
-              "null", forwarder.name.name, origin.fileOffset, origin.fileUri);
+              "null", forwarder.name.text, origin.fileOffset, origin.fileUri);
         }
         if (originNamed.initializer == null) continue;
         forwarderNamed.initializer = cloner.clone(originNamed.initializer);
@@ -3195,6 +3285,63 @@
     }
   }
 
+  void checkBoundsInTypeParameters(TypeEnvironment typeEnvironment,
+      List<TypeParameter> typeParameters, Uri fileUri) {
+    final DartType bottomType = library.isNonNullableByDefault
+        ? const NeverType(Nullability.nonNullable)
+        : typeEnvironment.nullType;
+
+    // Check in bounds of own type variables.
+    for (TypeParameter parameter in typeParameters) {
+      Set<TypeArgumentIssue> issues = {};
+      issues.addAll(findTypeArgumentIssues(
+              library,
+              parameter.bound,
+              typeEnvironment,
+              SubtypeCheckMode.ignoringNullabilities,
+              bottomType,
+              allowSuperBounded: true) ??
+          const []);
+      if (library.isNonNullableByDefault) {
+        issues.addAll(findTypeArgumentIssues(library, parameter.bound,
+                typeEnvironment, SubtypeCheckMode.withNullabilities, bottomType,
+                allowSuperBounded: true) ??
+            const []);
+      }
+      for (TypeArgumentIssue issue in issues) {
+        DartType argument = issue.argument;
+        TypeParameter typeParameter = issue.typeParameter;
+        if (inferredTypes.contains(argument)) {
+          // Inference in type expressions in the supertypes boils down to
+          // instantiate-to-bound which shouldn't produce anything that breaks
+          // the bounds after the non-simplicity checks are done.  So, any
+          // violation here is the result of non-simple bounds, and the error
+          // is reported elsewhere.
+          continue;
+        }
+
+        if (argument is FunctionType && argument.typeParameters.length > 0) {
+          reportTypeArgumentIssue(
+              messageGenericFunctionTypeUsedAsActualTypeArgument,
+              fileUri,
+              parameter.fileOffset,
+              null);
+        } else {
+          reportTypeArgumentIssue(
+              templateIncorrectTypeArgument.withArguments(
+                  argument,
+                  typeParameter.bound,
+                  typeParameter.name,
+                  getGenericTypeName(issue.enclosingType),
+                  library.isNonNullableByDefault),
+              fileUri,
+              parameter.fileOffset,
+              typeParameter);
+        }
+      }
+    }
+  }
+
   void checkBoundsInFunctionNodeParts(
       TypeEnvironment typeEnvironment, Uri fileUri, int fileOffset,
       {List<TypeParameter> typeParameters,
@@ -3269,6 +3416,34 @@
     }
   }
 
+  void checkTypesInProcedureBuilder(
+      ProcedureBuilder procedureBuilder, TypeEnvironment typeEnvironment) {
+    checkBoundsInFunctionNode(procedureBuilder.procedure.function,
+        typeEnvironment, procedureBuilder.fileUri);
+    if (procedureBuilder.formals != null &&
+        !(procedureBuilder.isAbstract || procedureBuilder.isExternal)) {
+      checkInitializersInFormals(procedureBuilder.formals, typeEnvironment);
+    }
+  }
+
+  void checkTypesInConstructorBuilder(
+      ConstructorBuilder constructorBuilder, TypeEnvironment typeEnvironment) {
+    checkBoundsInFunctionNode(
+        constructorBuilder.constructor.function, typeEnvironment, fileUri);
+    if (!constructorBuilder.isExternal && constructorBuilder.formals != null) {
+      checkInitializersInFormals(constructorBuilder.formals, typeEnvironment);
+    }
+  }
+
+  void checkTypesInRedirectingFactoryBuilder(
+      RedirectingFactoryBuilder redirectingFactoryBuilder,
+      TypeEnvironment typeEnvironment) {
+    checkBoundsInFunctionNode(redirectingFactoryBuilder.procedure.function,
+        typeEnvironment, redirectingFactoryBuilder.fileUri);
+    // Default values are not required on redirecting factory constructors so
+    // we don't call [checkInitializersInFormals].
+  }
+
   void checkBoundsInFunctionNode(
       FunctionNode function, TypeEnvironment typeEnvironment, Uri fileUri) {
     checkBoundsInFunctionNodeParts(
@@ -3403,7 +3578,7 @@
         targetReceiver =
             new InterfaceType(klass, klass.enclosingLibrary.nonNullable);
       }
-      String targetName = node.target.name.name;
+      String targetName = node.target.name.text;
       reportTypeArgumentIssues(issues, fileUri, node.fileOffset,
           typeArgumentsInfo: typeArgumentsInfo,
           targetReceiver: targetReceiver,
@@ -3487,7 +3662,7 @@
     reportTypeArgumentIssues(issues, fileUri, offset,
         typeArgumentsInfo: getTypeArgumentsInfo(arguments),
         targetReceiver: receiverType,
-        targetName: name.name);
+        targetName: name.text);
   }
 
   void checkTypesInOutline(TypeEnvironment typeEnvironment) {
@@ -3497,13 +3672,21 @@
       if (declaration is FieldBuilder) {
         checkTypesInField(declaration, typeEnvironment);
       } else if (declaration is ProcedureBuilder) {
-        checkBoundsInFunctionNode(declaration.procedure.function,
-            typeEnvironment, declaration.fileUri);
-        if (declaration.formals != null) {
-          checkInitializersInFormals(declaration.formals, typeEnvironment);
+        checkTypesInProcedureBuilder(declaration, typeEnvironment);
+        if (declaration.isGetter) {
+          Builder setterDeclaration =
+              scope.lookupLocalMember(declaration.name, setter: true);
+          if (setterDeclaration != null) {
+            checkGetterSetterTypes(
+                declaration, setterDeclaration, typeEnvironment);
+          }
         }
       } else if (declaration is SourceClassBuilder) {
         declaration.checkTypesInOutline(typeEnvironment);
+      } else if (declaration is SourceExtensionBuilder) {
+        declaration.checkTypesInOutline(typeEnvironment);
+      } else {
+        //assert(false, "Unexpected declaration ${declaration.runtimeType}");
       }
     }
     inferredTypes.clear();
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index f5f0588..14803dd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -41,6 +41,7 @@
         Library,
         LibraryDependency,
         Nullability,
+        Procedure,
         ProcedureKind,
         Reference,
         Supertype,
@@ -54,6 +55,8 @@
 
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
 
+import 'package:kernel/type_environment.dart';
+
 import 'package:package_config/package_config.dart';
 
 import '../../api_prototype/file_system.dart';
@@ -71,6 +74,7 @@
 import '../builder/enum_builder.dart';
 import '../builder/extension_builder.dart';
 import '../builder/field_builder.dart';
+import '../builder/invalid_type_declaration_builder.dart';
 import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
@@ -81,34 +85,10 @@
 
 import '../export.dart' show Export;
 
-import '../fasta_codes.dart'
-    show
-        Message,
-        SummaryTemplate,
-        Template,
-        messageObjectExtends,
-        messageObjectImplements,
-        messageObjectMixesIn,
-        messagePartOrphan,
-        messageStrongModeNNBDButOptOut,
-        messageTypedefCause,
-        messageTypedefUnaliasedTypeCause,
-        noLength,
-        templateAmbiguousSupertypes,
-        templateCantReadFile,
-        templateCyclicClassHierarchy,
-        templateExtendingEnum,
-        templateExtendingRestricted,
-        templateIllegalMixin,
-        templateIllegalMixinDueToConstructors,
-        templateIllegalMixinDueToConstructorsCause,
-        templateInternalProblemUriMissingScheme,
-        templateSourceOutlineSummary,
-        templateStrongModeNNBDPackageOptOut,
-        templateUntranslatableUri;
+import '../fasta_codes.dart';
 
 import '../kernel/kernel_builder.dart'
-    show ClassHierarchyBuilder, ClassMember, DelayedOverrideCheck;
+    show ClassHierarchyBuilder, ClassMember, DelayedCheck;
 
 import '../kernel/kernel_target.dart' show KernelTarget;
 
@@ -154,8 +134,9 @@
   ReferenceFromIndex referenceFromIndex;
 
   /// Used when building directly to kernel.
-  ClassHierarchy hierarchy;
+  ClassHierarchy _hierarchy;
   CoreTypes _coreTypes;
+  TypeEnvironment _typeEnvironment;
 
   /// For builders created with a reference, this maps from that reference to
   /// that builder. This is used for looking up source builders when finalizing
@@ -199,6 +180,19 @@
     return _coreTypes;
   }
 
+  ClassHierarchy get hierarchy => _hierarchy;
+
+  void set hierarchy(ClassHierarchy value) {
+    if (_hierarchy != value) {
+      _hierarchy = value;
+      _typeEnvironment = null;
+    }
+  }
+
+  TypeEnvironment get typeEnvironment {
+    return _typeEnvironment ??= new TypeEnvironment(coreTypes, hierarchy);
+  }
+
   Template<SummaryTemplate> get outlineSummaryTemplate =>
       templateSourceOutlineSummary;
 
@@ -1032,8 +1026,7 @@
   }
 
   void checkOverrides(List<SourceClassBuilder> sourceClasses) {
-    List<DelayedOverrideCheck> overrideChecks =
-        builderHierarchy.takeDelayedOverrideChecks();
+    List<DelayedCheck> overrideChecks = builderHierarchy.takeDelayedChecks();
     for (int i = 0; i < overrideChecks.length; i++) {
       overrideChecks[i].check(builderHierarchy);
     }
@@ -1045,7 +1038,7 @@
 
   void checkAbstractMembers(List<SourceClassBuilder> sourceClasses) {
     List<ClassMember> delayedMemberChecks =
-        builderHierarchy.takeDelayedMemberChecks();
+        builderHierarchy.takeDelayedMemberComputations();
     Set<Class> changedClasses = new Set<Class>();
     for (int i = 0; i < delayedMemberChecks.length; i++) {
       delayedMemberChecks[i].getMember(builderHierarchy);
@@ -1232,6 +1225,134 @@
         isTopLevel: isTopLevel);
   }
 
+  void checkMainMethods() {
+    DartType listOfString;
+
+    builders.forEach((Uri uri, LibraryBuilder libraryBuilder) {
+      if (libraryBuilder.loader == this &&
+          libraryBuilder.isNonNullableByDefault) {
+        Builder mainBuilder =
+            libraryBuilder.exportScope.lookupLocalMember('main', setter: false);
+        mainBuilder ??=
+            libraryBuilder.exportScope.lookupLocalMember('main', setter: true);
+        if (mainBuilder is MemberBuilder) {
+          if (mainBuilder is InvalidTypeDeclarationBuilder) {
+            // This is an ambiguous export, skip the check.
+            return;
+          }
+          if (mainBuilder.isField ||
+              mainBuilder.isGetter ||
+              mainBuilder.isSetter) {
+            if (mainBuilder.parent != libraryBuilder) {
+              libraryBuilder.addProblem(
+                  messageMainNotFunctionDeclarationExported,
+                  libraryBuilder.charOffset,
+                  noLength,
+                  libraryBuilder.fileUri,
+                  context: [
+                    messageExportedMain.withLocation(mainBuilder.fileUri,
+                        mainBuilder.charOffset, mainBuilder.name.length)
+                  ]);
+            } else {
+              libraryBuilder.addProblem(
+                  messageMainNotFunctionDeclaration,
+                  mainBuilder.charOffset,
+                  mainBuilder.name.length,
+                  mainBuilder.fileUri);
+            }
+          } else {
+            Procedure procedure = mainBuilder.member;
+            if (procedure.function.requiredParameterCount > 2) {
+              if (mainBuilder.parent != libraryBuilder) {
+                libraryBuilder.addProblem(
+                    messageMainTooManyRequiredParametersExported,
+                    libraryBuilder.charOffset,
+                    noLength,
+                    libraryBuilder.fileUri,
+                    context: [
+                      messageExportedMain.withLocation(mainBuilder.fileUri,
+                          mainBuilder.charOffset, mainBuilder.name.length)
+                    ]);
+              } else {
+                libraryBuilder.addProblem(
+                    messageMainTooManyRequiredParameters,
+                    mainBuilder.charOffset,
+                    mainBuilder.name.length,
+                    mainBuilder.fileUri);
+              }
+            } else if (procedure.function.namedParameters
+                .any((parameter) => parameter.isRequired)) {
+              if (mainBuilder.parent != libraryBuilder) {
+                libraryBuilder.addProblem(
+                    messageMainRequiredNamedParametersExported,
+                    libraryBuilder.charOffset,
+                    noLength,
+                    libraryBuilder.fileUri,
+                    context: [
+                      messageExportedMain.withLocation(mainBuilder.fileUri,
+                          mainBuilder.charOffset, mainBuilder.name.length)
+                    ]);
+              } else {
+                libraryBuilder.addProblem(
+                    messageMainRequiredNamedParameters,
+                    mainBuilder.charOffset,
+                    mainBuilder.name.length,
+                    mainBuilder.fileUri);
+              }
+            } else if (procedure.function.positionalParameters.length > 0) {
+              DartType parameterType =
+                  procedure.function.positionalParameters.first.type;
+
+              listOfString ??= new InterfaceType(
+                  coreTypes.listClass,
+                  Nullability.nonNullable,
+                  [coreTypes.stringNonNullableRawType]);
+
+              if (!typeEnvironment.isSubtypeOf(listOfString, parameterType,
+                  SubtypeCheckMode.withNullabilities)) {
+                if (mainBuilder.parent != libraryBuilder) {
+                  libraryBuilder.addProblem(
+                      templateMainWrongParameterTypeExported.withArguments(
+                          parameterType,
+                          listOfString,
+                          libraryBuilder.isNonNullableByDefault),
+                      libraryBuilder.charOffset,
+                      noLength,
+                      libraryBuilder.fileUri,
+                      context: [
+                        messageExportedMain.withLocation(mainBuilder.fileUri,
+                            mainBuilder.charOffset, mainBuilder.name.length)
+                      ]);
+                } else {
+                  libraryBuilder.addProblem(
+                      templateMainWrongParameterType.withArguments(
+                          parameterType,
+                          listOfString,
+                          libraryBuilder.isNonNullableByDefault),
+                      mainBuilder.charOffset,
+                      mainBuilder.name.length,
+                      mainBuilder.fileUri);
+                }
+              }
+            }
+          }
+        } else if (mainBuilder != null) {
+          if (mainBuilder.parent != libraryBuilder) {
+            libraryBuilder.addProblem(messageMainNotFunctionDeclarationExported,
+                libraryBuilder.charOffset, noLength, libraryBuilder.fileUri,
+                context: [
+                  messageExportedMain.withLocation(
+                      mainBuilder.fileUri, mainBuilder.charOffset, noLength)
+                ]);
+          } else {
+            libraryBuilder.addProblem(messageMainNotFunctionDeclaration,
+                mainBuilder.charOffset, noLength, mainBuilder.fileUri);
+          }
+        }
+      }
+    });
+  }
+
   void releaseAncillaryResources() {
     hierarchy = null;
     builderHierarchy = null;
@@ -1486,6 +1607,9 @@
 }
 
 T unsafeCast<T>(Object v) {}
+class ReachabilityError {
+  ReachabilityError([message]);
+}
 """;
 
 /// A minimal implementation of dart:typed_data that is sufficient to create an
diff --git a/pkg/front_end/lib/src/fasta/source/value_kinds.dart b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
index c16e23d..e533e56 100644
--- a/pkg/front_end/lib/src/fasta/source/value_kinds.dart
+++ b/pkg/front_end/lib/src/fasta/source/value_kinds.dart
@@ -14,32 +14,11 @@
 
 import 'package:kernel/ast.dart' as type;
 
-import '../builder/builder.dart' as type;
-import '../builder/builtin_type_declaration_builder.dart' as type;
-import '../builder/class_builder.dart' as type;
-import '../builder/constructor_reference_builder.dart' as type;
-import '../builder/dynamic_type_declaration_builder.dart' as type;
-import '../builder/enum_builder.dart' as type;
-import '../builder/field_builder.dart' as type;
 import '../builder/formal_parameter_builder.dart' as type;
-import '../builder/function_builder.dart' as type;
-import '../builder/function_type_builder.dart' as type;
-import '../builder/invalid_type_declaration_builder.dart' as type;
-import '../builder/library_builder.dart' as type;
-import '../builder/member_builder.dart' as type;
 import '../builder/metadata_builder.dart' as type;
-import '../builder/mixin_application_builder.dart' as type;
-import '../builder/modifier_builder.dart' as type;
-import '../builder/name_iterator.dart' as type;
-import '../builder/named_type_builder.dart' as type;
-import '../builder/nullability_builder.dart' as type;
-import '../builder/prefix_builder.dart' as type;
-import '../builder/type_alias_builder.dart' as type;
 import '../builder/type_builder.dart' as type;
-import '../builder/type_declaration_builder.dart' as type;
 import '../builder/type_variable_builder.dart' as type;
 import '../builder/unresolved_type.dart' as type;
-import '../builder/void_type_declaration_builder.dart' as type;
 
 import '../identifiers.dart' as type;
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index ff8a429..133297c 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -8,8 +8,6 @@
 
 import 'package:kernel/type_algebra.dart';
 
-import 'package:kernel/src/replacement_visitor.dart';
-
 import 'package:kernel/type_environment.dart';
 
 import 'type_schema.dart' show UnknownType;
@@ -298,105 +296,6 @@
     return type == coreTypes.nullType;
   }
 
-  /// Computes [type] as if declared without nullability markers.
-  ///
-  /// The algorithm implemented by [_isNullabilityAwareSubtypeMatch] uses the
-  /// notion of the nullable and the legacy type constructors, that is, int? and
-  /// int* are applications of the nullable and the legacy type constructors to
-  /// type int correspondingly.  The algorithm requires the ability to peel off
-  /// the two type constructors from the underlying types, which is done by
-  /// [_computeRawType].
-  DartType _computeRawType(DartType type) {
-    if (type is TypeParameterType) {
-      if (type.promotedBound == null) {
-        // The default nullability for library is used when there are no
-        // nullability markers on the type.
-        return new TypeParameterType.withDefaultNullabilityForLibrary(
-            type.parameter, _currentLibrary);
-      } else {
-        // Intersection types can't be arguments to the nullable and the legacy
-        // type constructors, so nothing can be peeled off.
-        return type;
-      }
-    } else if (type == coreTypes.nullType) {
-      return type;
-    } else {
-      // For most types, peeling off the nullability constructors means that
-      // they become non-nullable.
-      return type.withDeclaredNullability(Nullability.nonNullable);
-    }
-  }
-
-  /// Returns true if [type] is declared without nullability markers.
-  ///
-  /// The algorithm implemented by [_isNullabilityAwareSubtypeMatch] uses the
-  /// notion of the nullable and the legacy type constructors, that is, int? and
-  /// int* are applications of the nullable and the legacy type constructors to
-  /// type int correspondingly.  The algorithm requires the ability to detect if
-  /// a type is raw, that is, if it is declared without any of the two
-  /// constructors.  Method [_isRawTypeParameterType] implements that check for
-  /// [TypeParameterType]s.  For most types, comparing their
-  /// [DartType.declaredNullability] is enough, but the case of
-  /// [TypeParameterType]s is more complex for two reasons: (1) intersection
-  /// types are encoded as [TypeParameterType]s, and they can't be arguments of
-  /// the nullability constructors, and (2) if a [TypeParameterType] is declared
-  /// raw, its semantic nullability can be anything from
-  /// [Nullability.nonNullable], [Nullability.undetermined], and
-  /// [Nullability.legacy], depending on the bound.  [_isRawTypeParameterType]
-  /// checks if [type] has the same nullability as if it was declared without
-  /// any nullability markers by the programmer.
-  bool _isRawTypeParameterType(TypeParameterType type) {
-    // The default nullability for library is used when there are no nullability
-    // markers on the type.
-    return type.promotedBound == null &&
-        type.declaredNullability ==
-            new TypeParameterType.withDefaultNullabilityForLibrary(
-                    type.parameter, _currentLibrary)
-                .declaredNullability;
-  }
-
-  /// Returns true if [type] is an application of the nullable type constructor.
-  ///
-  /// The algorithm implemented by [_isNullabilityAwareSubtypeMatch] uses the
-  /// notion of the nullable type constructor, that is, int? is an application
-  /// of the nullable type constructor to type int.  The algorithm requires the
-  /// ability to detect if a type is an application of the nullable constructor
-  /// to another type, which is done by [_isNullableTypeConstructorApplication].
-  bool _isNullableTypeConstructorApplication(DartType type) {
-    return type.declaredNullability == Nullability.nullable &&
-        type is! DynamicType &&
-        type is! VoidType &&
-        type != coreTypes.nullType;
-  }
-
-  /// Returns true if [type] is an application of the legacy type constructor.
-  ///
-  /// The algorithm implemented by [_isNullabilityAwareSubtypeMatch] uses the
-  /// notion of the legacy type constructor, that is, int* is an application of
-  /// the legacy type constructor to type int.  The algorithm requires the
-  /// ability to detect if a type is an application of the nullable constructor
-  /// to another type, which is done by [_isNullableTypeConstructorApplication].
-  bool _isLegacyTypeConstructorApplication(DartType type) {
-    if (type is TypeParameterType) {
-      if (type.promotedBound == null) {
-        // The legacy nullability is considered an application of the legacy
-        // nullability constructor if it doesn't match the default nullability
-        // of the type-parameter type for the library.
-        return type.declaredNullability == Nullability.legacy &&
-            type.declaredNullability !=
-                new TypeParameterType.withDefaultNullabilityForLibrary(
-                        type.parameter, _currentLibrary)
-                    .declaredNullability;
-      } else {
-        return false;
-      }
-    } else if (type is InvalidType) {
-      return false;
-    } else {
-      return type.declaredNullability == Nullability.legacy;
-    }
-  }
-
   /// Matches [p] against [q] as a subtype against supertype.
   ///
   /// Returns true if [p] is a subtype of [q] under some constraints, and false
@@ -475,7 +374,7 @@
     //
     // Under constraint _ <: X <: Q.
     if (p is TypeParameterType &&
-        _isRawTypeParameterType(p) &&
+        isTypeParameterTypeWithoutNullabilityMarker(p, _currentLibrary) &&
         _parametersToConstrain.contains(p.parameter)) {
       _constrainParameterUpper(p.parameter, q);
       return true;
@@ -485,7 +384,7 @@
     //
     // Under constraint P <: X <: _.
     if (q is TypeParameterType &&
-        _isRawTypeParameterType(q) &&
+        isTypeParameterTypeWithoutNullabilityMarker(q, _currentLibrary) &&
         _parametersToConstrain.contains(q.parameter)) {
       _constrainParameterLower(q.parameter, p);
       return true;
@@ -504,18 +403,41 @@
     // If P is a legacy type P0* then the match holds under constraint set C:
     //
     // Only if P0 is a subtype match for Q under constraint set C.
-    if (_isLegacyTypeConstructorApplication(p)) {
-      return _isNullabilityAwareSubtypeMatch(_computeRawType(p), q,
+    if (isLegacyTypeConstructorApplication(p, _currentLibrary)) {
+      return _isNullabilityAwareSubtypeMatch(
+          computeTypeWithoutNullabilityMarker(p, _currentLibrary,
+              nullType: coreTypes.nullType),
+          q,
           constrainSupertype: constrainSupertype);
     }
 
     // If Q is a legacy type Q0* then the match holds under constraint set C:
     //
-    // Only if P is a subtype match for Q? under constraint set C.
-    if (_isLegacyTypeConstructorApplication(q)) {
-      return _isNullabilityAwareSubtypeMatch(
-          p, q.withDeclaredNullability(Nullability.nullable),
-          constrainSupertype: constrainSupertype);
+    // If P is dynamic or void and P is a subtype match for Q0 under constraint
+    // set C.
+    // Or if P is not dynamic or void and P is a subtype match for Q0? under
+    // constraint set C.
+    if (isLegacyTypeConstructorApplication(q, _currentLibrary)) {
+      final int baseConstraintCount = _protoConstraints.length;
+
+      if ((p is DynamicType || p is VoidType) &&
+          _isNullabilityAwareSubtypeMatch(
+              p,
+              computeTypeWithoutNullabilityMarker(q, _currentLibrary,
+                  nullType: coreTypes.nullType),
+              constrainSupertype: constrainSupertype)) {
+        return true;
+      }
+      _protoConstraints.length = baseConstraintCount;
+
+      if (p is! DynamicType &&
+          p is! VoidType &&
+          _isNullabilityAwareSubtypeMatch(
+              p, q.withDeclaredNullability(Nullability.nullable),
+              constrainSupertype: constrainSupertype)) {
+        return true;
+      }
+      _protoConstraints.length = baseConstraintCount;
     }
 
     // If Q is FutureOr<Q0> the match holds under constraint set C:
@@ -560,21 +482,36 @@
     // If Q is Q0? the match holds under constraint set C:
     //
     // If P is P0? and P0 is a subtype match for Q0 under constraint set C.
+    // Or if P is dynamic or void and Object is a subtype match for Q0 under
+    // constraint set C.
     // Or if P is a subtype match for Q0 under non-empty constraint set C.
     // Or if P is a subtype match for Null under constraint set C.
     // Or if P is a subtype match for Q0 under empty constraint set C.
-    if (_isNullableTypeConstructorApplication(q)) {
+    if (isNullableTypeConstructorApplication(q, nullType: coreTypes.nullType)) {
       final int baseConstraintCount = _protoConstraints.length;
-      final DartType rawP = _computeRawType(p);
-      final DartType rawQ = _computeRawType(q);
+      final DartType rawP = computeTypeWithoutNullabilityMarker(
+          p, _currentLibrary,
+          nullType: coreTypes.nullType);
+      final DartType rawQ = computeTypeWithoutNullabilityMarker(
+          q, _currentLibrary,
+          nullType: coreTypes.nullType);
 
-      if (_isNullableTypeConstructorApplication(p) &&
+      if (isNullableTypeConstructorApplication(p,
+              nullType: coreTypes.nullType) &&
           _isNullabilityAwareSubtypeMatch(rawP, rawQ,
               constrainSupertype: constrainSupertype)) {
         return true;
       }
       _protoConstraints.length = baseConstraintCount;
 
+      if ((p is DynamicType || p is VoidType) &&
+          _isNullabilityAwareSubtypeMatch(
+              coreTypes.objectNonNullableRawType, rawQ,
+              constrainSupertype: constrainSupertype)) {
+        return true;
+      }
+      _protoConstraints.length = baseConstraintCount;
+
       bool isMatchWithRawQ = _isNullabilityAwareSubtypeMatch(p, rawQ,
           constrainSupertype: constrainSupertype);
       bool matchWithRawQAddsConstraints =
@@ -616,9 +553,12 @@
     //
     // If P0 is a subtype match for Q under constraint set C1.
     // And if Null is a subtype match for Q under constraint set C2.
-    if (_isNullableTypeConstructorApplication(p)) {
+    if (isNullableTypeConstructorApplication(p, nullType: coreTypes.nullType)) {
       final int baseConstraintCount = _protoConstraints.length;
-      if (_isNullabilityAwareSubtypeMatch(_computeRawType(p), q,
+      if (_isNullabilityAwareSubtypeMatch(
+              computeTypeWithoutNullabilityMarker(p, _currentLibrary,
+                  nullType: coreTypes.nullType),
+              q,
               constrainSupertype: constrainSupertype) &&
           _isNullabilityAwareSubtypeMatch(coreTypes.nullType, q,
               constrainSupertype: constrainSupertype)) {
@@ -850,12 +790,18 @@
           List<_ProtoConstraint> constraints =
               _protoConstraints.sublist(baseConstraintCount);
           _protoConstraints.length = baseConstraintCount;
-          _NullabilityAwareTypeVariableEliminator eliminator =
-              new _NullabilityAwareTypeVariableEliminator(
-                  freshTypeParameters.freshTypeParameters.toSet(),
-                  const NeverType(Nullability.nonNullable),
-                  coreTypes.objectNullableRawType,
-                  coreTypes.functionNonNullableRawType);
+          NullabilityAwareTypeVariableEliminator eliminator =
+              new NullabilityAwareTypeVariableEliminator(
+                  eliminationTargets:
+                      freshTypeParameters.freshTypeParameters.toSet(),
+                  bottomType: const NeverType(Nullability.nonNullable),
+                  topType: coreTypes.objectNullableRawType,
+                  topFunctionType: coreTypes.functionNonNullableRawType,
+                  unhandledTypeHandler: (DartType type, ignored) =>
+                      type is UnknownType
+                          ? false
+                          : throw new UnsupportedError(
+                              "Unsupported type '${type.runtimeType}'."));
           for (_ProtoConstraint constraint in constraints) {
             if (constraint.isUpper) {
               _constrainParameterUpper(constraint.parameter,
@@ -1150,85 +1096,3 @@
         : "$bound <: ${parameter.name}";
   }
 }
-
-/// Eliminates specified free type parameters in a type.
-///
-/// The algorithm for elimination of type variables is described in
-/// https://github.com/dart-lang/language/pull/957
-class _NullabilityAwareTypeVariableEliminator extends ReplacementVisitor {
-  final DartType bottomType;
-  final DartType topType;
-  final DartType topFunctionType;
-  final Set<TypeParameter> eliminationTargets;
-  bool isLeastClosure;
-  bool isCovariant = true;
-
-  _NullabilityAwareTypeVariableEliminator(this.eliminationTargets,
-      this.bottomType, this.topType, this.topFunctionType);
-
-  /// Returns a subtype of [type] for all values of [eliminationTargets].
-  DartType eliminateToLeast(DartType type) {
-    isCovariant = true;
-    isLeastClosure = true;
-    return type.accept(this) ?? type;
-  }
-
-  /// Returns a supertype of [type] for all values of [eliminationTargets].
-  DartType eliminateToGreatest(DartType type) {
-    isCovariant = true;
-    isLeastClosure = false;
-    return type.accept(this) ?? type;
-  }
-
-  DartType get typeParameterReplacement {
-    return isLeastClosure && isCovariant || (!isLeastClosure && !isCovariant)
-        ? bottomType
-        : topType;
-  }
-
-  DartType get functionReplacement {
-    return isLeastClosure && isCovariant || (!isLeastClosure && !isCovariant)
-        ? bottomType
-        : topFunctionType;
-  }
-
-  @override
-  void changeVariance() {
-    isCovariant = !isCovariant;
-  }
-
-  @override
-  DartType visitFunctionType(FunctionType node) {
-    // - if `S` is
-    //   `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
-    //       [Tn+1 xn+1, ..., Tm xm])`
-    //   or `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
-    //       {Tn+1 xn+1, ..., Tm xm})`
-    //   and `L` contains any free type variables from any of the `Bi`:
-    //  - The least closure of `S` with respect to `L` is `Never`
-    //  - The greatest closure of `S` with respect to `L` is `Function`
-    if (node.typeParameters.isNotEmpty) {
-      for (TypeParameter typeParameter in node.typeParameters) {
-        if (containsTypeVariable(typeParameter.bound, eliminationTargets,
-            unhandledTypeHandler: (DartType type, ignored) =>
-                type is UnknownType
-                    ? false
-                    : throw new UnsupportedError(
-                        "Unsupported type '${type.runtimeType}'."))) {
-          return functionReplacement;
-        }
-      }
-    }
-    return super.visitFunctionType(node);
-  }
-
-  @override
-  DartType visitTypeParameterType(TypeParameterType node) {
-    if (eliminationTargets.contains(node.parameter)) {
-      return typeParameterReplacement.withDeclaredNullability(
-          uniteNullabilities(
-              typeParameterReplacement.nullability, node.nullability));
-    }
-    return super.visitTypeParameterType(node);
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
index a375a55..85bbacd 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_demotion.dart
@@ -105,11 +105,11 @@
   @override
   Nullability visitNullability(DartType node) {
     if (forNonNullableByDefault) {
-      if (node.nullability == Nullability.legacy) {
+      if (node.declaredNullability == Nullability.legacy) {
         return Nullability.nonNullable;
       }
     } else {
-      if (node.nullability != Nullability.legacy) {
+      if (node.declaredNullability != Nullability.legacy) {
         return Nullability.legacy;
       }
     }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
index a75173f..7e46518 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE.md file.
 
 import 'package:_fe_analyzer_shared/src/flow_analysis/flow_analysis.dart';
+import 'package:front_end/src/fasta/kernel/internal_ast.dart';
 
 import 'package:kernel/ast.dart'
     show
@@ -37,8 +38,6 @@
 
 import '../kernel/forest.dart';
 
-import '../kernel/internal_ast.dart' show VariableDeclarationImpl;
-
 import '../kernel/kernel_builder.dart'
     show ClassHierarchyBuilder, ImplicitFieldType;
 
@@ -284,14 +283,6 @@
   }
 
   @override
-  bool isLocalVariableWithoutDeclaredType(VariableDeclaration variable) {
-    return variable is VariableDeclarationImpl &&
-        variable.parent is Statement &&
-        variable.isImplicitlyTyped &&
-        !variable.hasDeclaredInitializer;
-  }
-
-  @override
   bool isNever(DartType type) {
     return typeEnvironment.coreTypes.isBottom(type);
   }
@@ -324,7 +315,15 @@
   }
 
   @override
-  DartType variableType(VariableDeclaration variable) => variable.type;
+  DartType variableType(VariableDeclaration variable) {
+    if (variable is VariableDeclarationImpl) {
+      // When late variables get lowered, their type is changed, but the
+      // original type is stored in `VariableDeclarationImpl.lateType`, so we
+      // use that if it exists.
+      return variable.lateType ?? variable.type;
+    }
+    return variable.type;
+  }
 
   @override
   DartType tryPromoteToType(DartType to, DartType from) {
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 2d855ee8..88de58d 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -275,6 +275,33 @@
     return type.withDeclaredNullability(library.nonNullable);
   }
 
+  Expression createReachabilityError(
+      int fileOffset, Message errorMessage, Message warningMessage) {
+    if (library.loader.target.context.options.warnOnReachabilityCheck &&
+        warningMessage != null) {
+      helper?.addProblem(warningMessage, fileOffset, noLength);
+    }
+    Arguments arguments;
+    if (errorMessage != null) {
+      arguments = new Arguments(
+          [new StringLiteral(errorMessage.message)..fileOffset = fileOffset])
+        ..fileOffset = fileOffset;
+    } else {
+      arguments = new Arguments([])..fileOffset = fileOffset;
+    }
+    assert(coreTypes.reachabilityErrorConstructor != null);
+    return new Throw(
+        new ConstructorInvocation(
+            coreTypes.reachabilityErrorConstructor, arguments)
+          ..fileOffset = fileOffset)
+      ..fileOffset = fileOffset;
+  }
+
+  /// Returns `true` if exceptions should be thrown in paths reachable only due
+  /// to unsoundness in flow analysis in mixed mode.
+  bool get shouldThrowUnsoundnessException =>
+      isNonNullableByDefault && nnbdMode != NnbdMode.Strong;
+
   void registerIfUnreachableForTesting(TreeNode node, {bool isReachable}) {
     if (dataForTesting == null) return;
     isReachable ??= flowAnalysis.isReachable;
@@ -292,10 +319,10 @@
       // corresponding field type which required us to know the type of the
       // constructor.
       String name = target.enclosingClass.name;
-      if (target.name.name.isNotEmpty) {
+      if (target.name.text.isNotEmpty) {
         // TODO(ahe): Use `inferrer.helper.constructorNameForDiagnostics`
         // instead. However, `inferrer.helper` may be null.
-        name += ".${target.name.name}";
+        name += ".${target.name.text}";
       }
       constructor.library.addProblem(
           templateCantInferTypeDueToCircularity.withArguments(name),
@@ -498,7 +525,7 @@
     if (contextType is! InvalidType) {
       errorNode = helper.wrapInProblem(
           errorNode,
-          template.withArguments(callName.name),
+          template.withArguments(callName.text),
           errorNode.fileOffset,
           noLength);
     }
@@ -942,13 +969,13 @@
       Template<Message Function(String, DartType, bool)> errorTemplate) {
     assert(receiverType != null && isKnown(receiverType));
     if (!isTopLevel && target.isMissing && errorTemplate != null) {
-      int length = name.name.length;
-      if (identical(name.name, callName.name) ||
-          identical(name.name, unaryMinusName.name)) {
+      int length = name.text.length;
+      if (identical(name.text, callName.text) ||
+          identical(name.text, unaryMinusName.text)) {
         length = 1;
       }
       return helper.buildProblem(
-          errorTemplate.withArguments(name.name,
+          errorTemplate.withArguments(name.text,
               resolveTypeParameter(receiverType), isNonNullableByDefault),
           fileOffset,
           length);
@@ -1561,7 +1588,7 @@
   /// the expression type and calls the appropriate specialized "infer" method.
   ExpressionInferenceResult inferExpression(
       Expression expression, DartType typeContext, bool typeNeeded,
-      {bool isVoidAllowed: false}) {
+      {bool isVoidAllowed: false, bool forEffect: false}) {
     registerIfUnreachableForTesting(expression);
 
     // `null` should never be used as the type context.  An instance of
@@ -1597,6 +1624,19 @@
     }
     if (coreTypes.isBottom(result.inferredType)) {
       flowAnalysis.handleExit();
+      if (shouldThrowUnsoundnessException &&
+          // Don't throw on expressions that inherently return the bottom type.
+          !(result.nullAwareAction is Throw ||
+              result.nullAwareAction is Rethrow ||
+              result.nullAwareAction is InvalidExpression)) {
+        Expression replacement = createLet(
+            createVariable(result.expression, result.inferredType),
+            createReachabilityError(expression.fileOffset,
+                messageNeverValueError, messageNeverValueWarning));
+        flowAnalysis.forwardExpression(replacement, result.expression);
+        result =
+            new ExpressionInferenceResult(result.inferredType, replacement);
+      }
     }
     return result;
   }
@@ -2411,9 +2451,9 @@
           replacement = helper.wrapInProblem(
               replacement,
               templateNullableMethodCallError.withArguments(
-                  name.name, receiverType, isNonNullableByDefault),
+                  name.text, receiverType, isNonNullableByDefault),
               fileOffset,
-              name.name.length);
+              name.text.length);
         }
       }
       return createNullAwareExpressionInferenceResult(
@@ -2454,9 +2494,9 @@
         replacement = helper.wrapInProblem(
             replacement,
             templateNullableMethodCallError.withArguments(
-                callName.name, receiverType, isNonNullableByDefault),
+                callName.text, receiverType, isNonNullableByDefault),
             fileOffset,
-            callName.name.length);
+            callName.text.length);
       }
     }
     // TODO(johnniwinther): Check that type arguments against the bounds.
@@ -2562,9 +2602,9 @@
         replacement = helper.wrapInProblem(
             replacement,
             templateNullableMethodCallError.withArguments(
-                methodName.name, receiverType, isNonNullableByDefault),
+                methodName.text, receiverType, isNonNullableByDefault),
             fileOffset,
-            methodName.name.length);
+            methodName.text.length);
       }
     }
 
@@ -3021,7 +3061,7 @@
         receiverType: receiverType,
         isImplicitExtensionMember: target.isExtensionMember);
     DartType inferredType = result.inferredType;
-    if (methodName.name == '==') {
+    if (methodName.text == '==') {
       inferredType = coreTypes.boolRawType(library.nonNullable);
     }
     _checkBoundsInMethodInvocation(
@@ -3320,7 +3360,7 @@
           null, engine.forest.createArguments(fileOffset, <Expression>[index]));
     } else {
       return helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments(indexGetName.name),
+          templateSuperclassHasNoMethod.withArguments(indexGetName.text),
           fileOffset,
           noLength);
     }
@@ -3337,7 +3377,7 @@
               .createArguments(fileOffset, <Expression>[index, value]));
     } else {
       return helper.buildProblem(
-          templateSuperclassHasNoMethod.withArguments(indexSetName.name),
+          templateSuperclassHasNoMethod.withArguments(indexSetName.text),
           fileOffset,
           noLength);
     }
@@ -3365,7 +3405,7 @@
       template = ambiguousTemplate;
     }
     return helper.buildProblem(
-        template.withArguments(name.name, resolveTypeParameter(receiverType),
+        template.withArguments(name.text, resolveTypeParameter(receiverType),
             isNonNullableByDefault),
         fileOffset,
         length,
@@ -3385,13 +3425,13 @@
       assert(extensionAccessCandidates == null);
       return helper.buildProblem(
           templateInvokeNonFunction
-              .withArguments(implicitInvocationPropertyName.name),
+              .withArguments(implicitInvocationPropertyName.text),
           fileOffset,
-          implicitInvocationPropertyName.name.length);
+          implicitInvocationPropertyName.text.length);
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
-          isExpressionInvocation ? noLength : name.name.length,
+          isExpressionInvocation ? noLength : name.text.length,
           receiverType,
           name,
           extensionAccessCandidates,
@@ -3409,7 +3449,7 @@
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
-          propertyName.name.length,
+          propertyName.text.length,
           receiverType,
           propertyName,
           extensionAccessCandidates,
@@ -3430,7 +3470,7 @@
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
-          propertyName.name.length,
+          propertyName.text.length,
           receiverType,
           propertyName,
           extensionAccessCandidates,
@@ -3488,7 +3528,7 @@
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
-          binaryName.name.length,
+          binaryName.text.length,
           leftType,
           binaryName,
           extensionAccessCandidates,
@@ -3506,7 +3546,7 @@
     } else {
       return _reportMissingOrAmbiguousMember(
           fileOffset,
-          unaryName == unaryMinusName ? 1 : unaryName.name.length,
+          unaryName == unaryMinusName ? 1 : unaryName.text.length,
           expressionType,
           unaryName,
           extensionAccessCandidates,
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
index 4a8dca0..2ae32bf 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_promotion.dart
@@ -190,6 +190,11 @@
   /// created.
   int _lastFactSequenceNumber = 0;
 
+  /// Map from variables to the set of scopes in which the variable is mutated.
+  /// If a variable is missing from the map, it is not mutated anywhere.
+  Map<VariableDeclaration, Set<TypePromotionScope>> _variableMutationScopes =
+      new Map<VariableDeclaration, Set<TypePromotionScope>>.identity();
+
   TypePromoterImpl.private(TypeSchemaEnvironment typeSchemaEnvironment)
       : this._(typeSchemaEnvironment, new _NullFact());
 
@@ -207,7 +212,8 @@
   DartType computePromotedType(
       TypePromotionFact fact, TypePromotionScope scope, bool mutatedInClosure) {
     if (mutatedInClosure) return null;
-    return fact?._computePromotedType(this, scope);
+    return fact?._computePromotedType(
+        this, scope, _variableMutationScopes[fact.variable]);
   }
 
   /// For internal debugging use, optionally prints the current state followed
@@ -220,28 +226,28 @@
   @override
   void enterElse() {
     debugEvent('enterElse');
+    // Pop the scope and restore the facts to the state they were in before we
+    // entered the conditional.  No promotion happens in the "else" branch.
     _ConditionalScope scope = _currentScope;
-    // Record the current fact state so that once we exit the "else" branch, we
-    // can merge facts from the two branches.
-    scope.afterTrue = _currentFacts;
-    // While processing the "else" block, assume the condition was false.
+    _currentScope = _currentScope._enclosing;
     _currentFacts = scope.beforeElse;
   }
 
   @override
   void enterLogicalExpression(Expression lhs, String operator) {
     debugEvent('enterLogicalExpression');
-    // Figure out what the facts are based on possible LHS outcomes.
-    TypePromotionFact trueFacts = _factsWhenTrue(lhs);
-    TypePromotionFact falseFacts = _factsWhenFalse(lhs);
-    // Record the fact that we are entering a new scope, and save the
-    // appropriate facts for the case where the expression gets short-cut.
-    bool isAnd = identical(operator, '&&');
-    _currentScope =
-        new _LogicalScope(_currentScope, isAnd, isAnd ? falseFacts : trueFacts);
-    // While processing the RHS, assume the condition was false or true,
-    // depending on the type of logical expression.
-    _currentFacts = isAnd ? trueFacts : falseFacts;
+    if (!identical(operator, '&&')) {
+      // We don't promote for `||`.
+      _currentScope = new _LogicalScope(_currentScope, false, _currentFacts);
+    } else {
+      // Figure out what the facts are based on possible LHS outcomes.
+      TypePromotionFact trueFacts = _factsWhenTrue(lhs);
+      // Record the fact that we are entering a new scope, and save the
+      // appropriate facts for the case where the expression gets short-cut.
+      _currentScope = new _LogicalScope(_currentScope, true, _currentFacts);
+      // While processing the RHS, assume the condition was true.
+      _currentFacts = _addBlockingScopeToFacts(trueFacts);
+    }
   }
 
   @override
@@ -249,36 +255,29 @@
     debugEvent('enterThen');
     // Figure out what the facts are based on possible condition outcomes.
     TypePromotionFact trueFacts = _factsWhenTrue(condition);
-    TypePromotionFact falseFacts = _factsWhenFalse(condition);
-    // Record the fact that we are entering a new scope, and save the "false"
+    // Record the fact that we are entering a new scope, and save the current
     // facts for when we enter the "else" branch.
-    _currentScope = new _ConditionalScope(_currentScope, falseFacts);
+    _currentScope = new _ConditionalScope(_currentScope, _currentFacts);
     // While processing the "then" block, assume the condition was true.
-    _currentFacts = trueFacts;
+    _currentFacts = _addBlockingScopeToFacts(trueFacts);
   }
 
   @override
   void exitConditional() {
     debugEvent('exitConditional');
-    _ConditionalScope scope = _currentScope;
-    _currentScope = _currentScope._enclosing;
-    _currentFacts = _mergeFacts(scope.afterTrue, _currentFacts);
   }
 
   @override
   void exitLogicalExpression(Expression rhs, Expression logicalExpression) {
     debugEvent('exitLogicalExpression');
     _LogicalScope scope = _currentScope;
-    _currentScope = _currentScope._enclosing;
     if (scope.isAnd) {
-      _recordPromotionExpression(logicalExpression, _factsWhenTrue(rhs),
-          _mergeFacts(scope.shortcutFacts, _currentFacts));
-    } else {
+      TypePromotionFact factsWhenTrue = _factsWhenTrue(rhs);
+      _currentFacts = scope.shortcutFacts;
       _recordPromotionExpression(
-          logicalExpression,
-          _mergeFacts(scope.shortcutFacts, _currentFacts),
-          _factsWhenFalse(rhs));
+          logicalExpression, _addBlockingScopeToFacts(factsWhenTrue));
     }
+    _currentScope = _currentScope._enclosing;
   }
 
   @override
@@ -317,9 +316,9 @@
         _currentFacts,
         _computeCurrentFactMap()[variable],
         functionNestingLevel,
-        type);
+        type, []);
     if (!isInverted) {
-      _recordPromotionExpression(isExpression, isCheck, _currentFacts);
+      _recordPromotionExpression(isExpression, isCheck);
     }
   }
 
@@ -335,27 +334,55 @@
   /// mutated.
   void mutateVariable(VariableDeclaration variable, int functionNestingLevel) {
     debugEvent('mutateVariable');
-    TypePromotionFact fact = _computeCurrentFactMap()[variable];
-    TypePromotionFact._recordMutatedInScope(fact, _currentScope);
+    (_variableMutationScopes[variable] ??=
+            new Set<TypePromotionScope>.identity())
+        .add(_currentScope);
     if (getVariableFunctionNestingLevel(variable) < functionNestingLevel) {
       setVariableMutatedInClosure(variable);
     }
-    setVariableMutatedAnywhere(variable);
   }
 
   /// Determines whether [a] and [b] represent the same expression, after
   /// dropping redundant enclosing parentheses.
   bool sameExpressions(Expression a, Expression b);
 
-  /// Records that the given variable was mutated somewhere inside the method.
-  void setVariableMutatedAnywhere(VariableDeclaration variable);
-
   /// Records that the given variable was mutated inside a closure.
   void setVariableMutatedInClosure(VariableDeclaration variable);
 
-  /// Indicates whether [setVariableMutatedAnywhere] has been called for the
-  /// given [variable].
-  bool wasVariableMutatedAnywhere(VariableDeclaration variable);
+  /// Updates any facts that are present in [facts] but not in [_currentFacts]
+  /// so that they include [_currentScope] in their list of blocking scopes, and
+  /// returns the resulting new linked list of facts.
+  ///
+  /// This is used when entering the body of a conditional, or the RHS of a
+  /// logical "and", to ensure that promotions are blocked if the construct
+  /// being entered contains any modifications of the corresponding variables.
+  /// It is also used when leaving the RHS of a logical "and", to ensure that
+  /// any promotions induced by the RHS of the "and" are blocked if the RHS of
+  /// the "and" contains any modifications of the corresponding variables.
+  TypePromotionFact _addBlockingScopeToFacts(TypePromotionFact facts) {
+    List<TypePromotionFact> factsToUpdate = [];
+    while (facts != _currentFacts) {
+      factsToUpdate.add(facts);
+      facts = facts.previous;
+    }
+    Map<VariableDeclaration, TypePromotionFact> factMap =
+        _computeCurrentFactMap();
+    for (TypePromotionFact fact in factsToUpdate.reversed) {
+      _IsCheck isCheck = fact as _IsCheck;
+      VariableDeclaration variable = isCheck.variable;
+      facts = new _IsCheck(
+          ++_lastFactSequenceNumber,
+          variable,
+          facts,
+          factMap[variable],
+          isCheck.functionNestingLevel,
+          isCheck.checkedType,
+          [...isCheck._blockingScopes, _currentScope]);
+      factMap[variable] = facts;
+      _factCacheState = facts;
+    }
+    return facts;
+  }
 
   /// Returns a map from variable declaration to the most recent
   /// [TypePromotionFact] associated with the variable.
@@ -401,20 +428,6 @@
   }
 
   /// Returns the set of facts known to be true after the execution of [e]
-  /// assuming it evaluates to `false`.
-  ///
-  /// [e] must be the most recently parsed expression or statement.
-  TypePromotionFact _factsWhenFalse(Expression e) {
-    // Type promotion currently only occurs when an "is" or logical expression
-    // evaluates to `true`, so no special logic is required; we just use
-    // [_currentFacts].
-    //
-    // TODO(paulberry): experiment with supporting promotion in cases like
-    // `if (x is! T) { ... } else { ...access x... }`
-    return _currentFacts;
-  }
-
-  /// Returns the set of facts known to be true after the execution of [e]
   /// assuming it evaluates to `true`.
   ///
   /// [e] must be the most recently parsed expression or statement.
@@ -423,31 +436,6 @@
           ? _trueFactsForPromotionExpression
           : _currentFacts;
 
-  /// Returns the set of facts known to be true after two branches of execution
-  /// rejoin.
-  TypePromotionFact _mergeFacts(TypePromotionFact a, TypePromotionFact b) {
-    // Type promotion currently doesn't support any mechanism for facts to
-    // accumulate along a straight-line execution path (they can only accumulate
-    // when entering a scope), so we can simply find the common ancestor fact.
-    //
-    // TODO(paulberry): experiment with supporting promotion in cases like:
-    //     if (...) {
-    //       if (x is! T) return;
-    //     } else {
-    //       if (x is! T) return;
-    //     }
-    //     ...access x...
-    while (a.sequenceNumber != b.sequenceNumber) {
-      if (a.sequenceNumber > b.sequenceNumber) {
-        a = a.previous;
-      } else {
-        b = b.previous;
-      }
-    }
-    assert(identical(a, b));
-    return a;
-  }
-
   /// For internal debugging use, prints the current state followed by the event
   /// name.
   // ignore: unused_element
@@ -466,26 +454,19 @@
     if (_promotionExpression != null) {
       print('  _promotionExpression: $_promotionExpression');
       if (!identical(_trueFactsForPromotionExpression, _currentFacts)) {
-        print('    if true: $_trueFactsForPromotionExpression');
+        print('    if true: '
+            '${factChain(_trueFactsForPromotionExpression).join(' -> ')}');
       }
     }
     print(name);
   }
 
   /// Records that after the evaluation of [expression], the facts will be
-  /// [ifTrue] on a branch where the expression evaluated to `true`, and
-  /// [ifFalse] on a branch where the expression evaluated to `false` (or where
-  /// the truth value of the expression doesn't matter).
-  ///
-  /// TODO(paulberry): when we start handling promotion in "else" clauses, we'll
-  /// need to split [ifFalse] into two cases, one for when the expression
-  /// evaluated to `false`, and one where the truth value of the expression
-  /// doesn't matter.
-  void _recordPromotionExpression(Expression expression,
-      TypePromotionFact ifTrue, TypePromotionFact ifFalse) {
+  /// [ifTrue] on a branch where the expression evaluated to `true`.
+  void _recordPromotionExpression(
+      Expression expression, TypePromotionFact ifTrue) {
     _promotionExpression = expression;
     _trueFactsForPromotionExpression = ifTrue;
-    _currentFacts = ifFalse;
   }
 }
 
@@ -533,19 +514,9 @@
   /// The function nesting level of the expression that led to this fact.
   final int functionNestingLevel;
 
-  /// If this fact's variable was mutated within any scopes the
-  /// fact applies to, a set of the corresponding scopes.  Otherwise `null`.
-  ///
-  /// TODO(paulberry): the size of this set is probably very small most of the
-  /// time.  Would it be better to use a list?
-  Set<TypePromotionScope> _mutatedInScopes;
-
-  /// If this fact's variable was accessed inside a closure within any scopes
-  /// the fact applies to, a set of the corresponding scopes.  Otherwise `null`.
-  ///
-  /// TODO(paulberry): the size of this set is probably very small most of the
-  /// time.  Would it be better to use a list?
-  Set<TypePromotionScope> _accessedInClosureInScopes;
+  /// Indicates whether this fact's variable was accessed inside a closure
+  /// within the scope the fact applies to.
+  bool _accessedInClosureInScope = false;
 
   TypePromotionFact(this.sequenceNumber, this.variable, this.previous,
       this.previousForVariable, this.functionNestingLevel);
@@ -553,9 +524,13 @@
   /// Computes the promoted type for [variable] at a location in the code where
   /// this fact applies.
   ///
+  /// [scope] is the scope containing the read that might be promoted, and
+  /// [mutationScopes] is the set of scopes in which the variable is mutated, or
+  /// `null` if the variable isn't mutated anywhere.
+  ///
   /// Should not be called until after parsing of the entire method is complete.
-  DartType _computePromotedType(
-      TypePromoterImpl promoter, TypePromotionScope scope);
+  DartType _computePromotedType(TypePromoterImpl promoter,
+      TypePromotionScope scope, Iterable<TypePromotionScope> mutationScopes);
 
   /// Records the fact that the variable referenced by [fact] was accessed
   /// within the given scope, at the given function nesting level.
@@ -569,26 +544,17 @@
     // to testing it against getVariableFunctionNestingLevel(variable)).
     while (fact != null) {
       if (functionNestingLevel > fact.functionNestingLevel) {
-        fact._accessedInClosureInScopes ??=
-            new Set<TypePromotionScope>.identity();
-        if (!fact._accessedInClosureInScopes.add(scope)) return;
+        if (fact._accessedInClosureInScope) {
+          // The variable has already been accessed in a closure in the scope of
+          // the current promotion (and this, any enclosing promotions), so
+          // no further information needs to be updated.
+          return;
+        }
+        fact._accessedInClosureInScope = true;
       }
       fact = fact.previousForVariable;
     }
   }
-
-  /// Records the fact that the variable referenced by [fact] was mutated
-  /// within the given scope.
-  ///
-  /// If `null` is passed in for [fact], there is no effect.
-  static void _recordMutatedInScope(
-      TypePromotionFact fact, TypePromotionScope scope) {
-    while (fact != null) {
-      fact._mutatedInScopes ??= new Set<TypePromotionScope>.identity();
-      if (!fact._mutatedInScopes.add(scope)) return;
-      fact = fact.previousForVariable;
-    }
-  }
 }
 
 /// Represents a contiguous block of program text in which variables may or may
@@ -629,9 +595,6 @@
   /// The fact state in effect at the top of the "else" block.
   final TypePromotionFact beforeElse;
 
-  /// The fact state which was in effect at the bottom of the "then" block.
-  TypePromotionFact afterTrue;
-
   _ConditionalScope(TypePromotionScope enclosing, this.beforeElse)
       : super(enclosing);
 }
@@ -641,13 +604,18 @@
   /// The type appearing on the right hand side of "is".
   final DartType checkedType;
 
+  /// List of the scopes in which a mutation to the variable would block
+  /// promotion.
+  final List<TypePromotionScope> _blockingScopes;
+
   _IsCheck(
       int sequenceNumber,
       VariableDeclaration variable,
       TypePromotionFact previous,
       TypePromotionFact previousForVariable,
       int functionNestingLevel,
-      this.checkedType)
+      this.checkedType,
+      this._blockingScopes)
       : super(sequenceNumber, variable, previous, previousForVariable,
             functionNestingLevel);
 
@@ -655,30 +623,27 @@
   String toString() => 'isCheck($checkedType)';
 
   @override
-  DartType _computePromotedType(
-      TypePromoterImpl promoter, TypePromotionScope scope) {
-    DartType previousPromotedType =
-        previousForVariable?._computePromotedType(promoter, scope);
+  DartType _computePromotedType(TypePromoterImpl promoter,
+      TypePromotionScope scope, Iterable<TypePromotionScope> mutationScopes) {
+    DartType previousPromotedType = previousForVariable?._computePromotedType(
+        promoter, scope, mutationScopes);
 
-    // If the variable was mutated somewhere in the scope of the potential
-    // promotion, promotion does not occur.
-    if (_mutatedInScopes != null) {
-      for (TypePromotionScope assignmentScope in _mutatedInScopes) {
-        if (assignmentScope.containsScope(scope)) {
-          return previousPromotedType;
+    if (mutationScopes != null) {
+      // If the variable was mutated somewhere in a that blocks the promotion,
+      // promotion does not occur.
+      for (TypePromotionScope blockingScope in _blockingScopes) {
+        for (TypePromotionScope mutationScope in mutationScopes) {
+          if (blockingScope.containsScope(mutationScope)) {
+            return previousPromotedType;
+          }
         }
       }
-    }
 
-    // If the variable was mutated anywhere, and it was accessed inside a
-    // closure somewhere in the scope of the potential promotion, promotion does
-    // not occur.
-    if (promoter.wasVariableMutatedAnywhere(variable) &&
-        _accessedInClosureInScopes != null) {
-      for (TypePromotionScope accessScope in _accessedInClosureInScopes) {
-        if (accessScope.containsScope(scope)) {
-          return previousPromotedType;
-        }
+      // If the variable was mutated anywhere, and it was accessed inside a
+      // closure somewhere in the scope of the potential promotion, promotion
+      // does not occur.
+      if (_accessedInClosureInScope) {
+        return previousPromotedType;
       }
     }
 
@@ -725,8 +690,8 @@
   String toString() => 'null';
 
   @override
-  DartType _computePromotedType(
-      TypePromoter promoter, TypePromotionScope scope) {
+  DartType _computePromotedType(TypePromoter promoter, TypePromotionScope scope,
+      Iterable<TypePromotionScope> mutationScopes) {
     throw new StateError('Tried to create promoted type for no variable');
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index 1b89f55..d467fb7 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -399,7 +399,7 @@
       // TODO(paulberry): this matches what is defined in the spec.  It would be
       // nice if we could change kernel to match the spec and not have to
       // override.
-      if (member.name.name == 'remainder') return false;
+      if (member.name.text == 'remainder') return false;
       if (!(receiverType is InterfaceType &&
           identical(receiverType.classNode, coreTypes.intClass))) {
         return false;
diff --git a/pkg/front_end/lib/src/kernel_generator_impl.dart b/pkg/front_end/lib/src/kernel_generator_impl.dart
index 5cef59a..76a3697 100644
--- a/pkg/front_end/lib/src/kernel_generator_impl.dart
+++ b/pkg/front_end/lib/src/kernel_generator_impl.dart
@@ -83,28 +83,11 @@
     // sdkSummary between multiple invocations.
     CanonicalName nameRoot = sdkSummary?.root ?? new CanonicalName.root();
     if (sdkSummary != null) {
-      if (options.nnbdMode == NnbdMode.Strong &&
-          !(sdkSummary.mode == NonNullableByDefaultCompiledMode.Strong ||
-              sdkSummary.mode == NonNullableByDefaultCompiledMode.Agnostic)) {
-        throw new FormatException(
-            'Provided SDK .dill does not support sound null safety.');
-      }
       dillTarget.loader.appendLibraries(sdkSummary);
     }
 
     for (Component additionalDill
         in await options.loadAdditionalDills(nameRoot)) {
-      if (options.nnbdMode == NnbdMode.Strong &&
-          !(additionalDill.mode == NonNullableByDefaultCompiledMode.Strong ||
-              // In some VM tests the SDK dill appears as an additionalDill so
-              // allow agnostic here as well.
-              additionalDill.mode ==
-                  NonNullableByDefaultCompiledMode.Agnostic)) {
-        throw new FormatException(
-            'Provided .dill file for the following libraries does not support '
-            'sound null safety:\n'
-            '${additionalDill.libraries.join('\n')}');
-      }
       loadedComponents.add(additionalDill);
       dillTarget.loader.appendLibraries(additionalDill);
     }
diff --git a/pkg/front_end/lib/src/testing/id_extractor.dart b/pkg/front_end/lib/src/testing/id_extractor.dart
index d3e174c..d63f675 100644
--- a/pkg/front_end/lib/src/testing/id_extractor.dart
+++ b/pkg/front_end/lib/src/testing/id_extractor.dart
@@ -11,7 +11,7 @@
   if (node.enclosingClass != null) {
     className = node.enclosingClass.name;
   }
-  String memberName = node.name.name;
+  String memberName = node.name.text;
   if (node is Procedure && node.kind == ProcedureKind.Setter) {
     memberName += '=';
   }
@@ -203,14 +203,14 @@
       // This is an invocation of a named local function.
       computeForNode(node, createInvokeId(node.receiver));
       node.arguments.accept(this);
-    } else if (node.name.name == '==' &&
+    } else if (node.name.text == '==' &&
         receiver is VariableGet &&
         receiver.variable.name == null) {
       // This is a desugared `?.`.
-    } else if (node.name.name == '[]') {
+    } else if (node.name.text == '[]') {
       computeForNode(node, computeDefaultNodeId(node));
       super.visitMethodInvocation(node);
-    } else if (node.name.name == '[]=') {
+    } else if (node.name.text == '[]=') {
       computeForNode(node, createUpdateId(node));
       super.visitMethodInvocation(node);
     } else {
diff --git a/pkg/front_end/lib/src/testing/id_testing_helper.dart b/pkg/front_end/lib/src/testing/id_testing_helper.dart
index c81c0a0..92502bf 100644
--- a/pkg/front_end/lib/src/testing/id_testing_helper.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_helper.dart
@@ -375,7 +375,7 @@
       if (member.enclosingClass.isEnum) {
         if (member is Constructor ||
             member.isInstanceMember ||
-            member.name == 'values') {
+            member.name.text == 'values') {
           return;
         }
       }
diff --git a/pkg/front_end/lib/src/testing/id_testing_utils.dart b/pkg/front_end/lib/src/testing/id_testing_utils.dart
index 97eed20..2d8e634 100644
--- a/pkg/front_end/lib/src/testing/id_testing_utils.dart
+++ b/pkg/front_end/lib/src/testing/id_testing_utils.dart
@@ -20,8 +20,8 @@
 
 /// Returns a canonical simple name for [member].
 String getMemberName(Member member) {
-  if (member is Procedure && member.isSetter) return '${member.name.name}=';
-  return member.name.name;
+  if (member is Procedure && member.isSetter) return '${member.name.text}=';
+  return member.name.text;
 }
 
 /// Returns the enclosing [Member] for [node].
@@ -174,7 +174,7 @@
     {bool required: true}) {
   MemberBuilder memberBuilder;
   if (member.isExtensionMember) {
-    String memberName = member.name.name;
+    String memberName = member.name.text;
     String extensionName = memberName.substring(0, memberName.indexOf('|'));
     memberName = memberName.substring(extensionName.length + 1);
     bool isSetter = member is Procedure && member.isSetter;
@@ -191,16 +191,16 @@
         isSetter: isSetter, required: required);
   } else if (member.enclosingClass != null) {
     memberBuilder = lookupClassMemberBuilder(
-        compilerResult, member.enclosingClass, member, member.name.name,
+        compilerResult, member.enclosingClass, member, member.name.text,
         required: required);
   } else {
     TypeParameterScopeBuilder libraryBuilder = lookupLibraryDeclarationBuilder(
         compilerResult, member.enclosingLibrary,
         required: required);
     if (member is Procedure && member.isSetter) {
-      memberBuilder = libraryBuilder.setters[member.name.name];
+      memberBuilder = libraryBuilder.setters[member.name.text];
     } else {
-      memberBuilder = libraryBuilder.members[member.name.name];
+      memberBuilder = libraryBuilder.members[member.name.text];
     }
   }
   if (memberBuilder == null && required) {
@@ -659,10 +659,10 @@
       sb.write('tearoff ');
       break;
   }
-  sb.write(descriptor.name.name);
+  sb.write(descriptor.name.text);
   sb.write('=');
   Member member = descriptor.member.asMember;
-  String name = member.name.name;
+  String name = member.name.text;
   if (member is Procedure && member.isSetter) {
     sb.write('$name=');
   } else {
diff --git a/pkg/front_end/lib/widget_cache.dart b/pkg/front_end/lib/widget_cache.dart
new file mode 100644
index 0000000..158125b
--- /dev/null
+++ b/pkg/front_end/lib/widget_cache.dart
@@ -0,0 +1,191 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/kernel.dart';
+
+/// Provides support for "single widget reloads" in Flutter, by determining if
+/// a partial component contains single change to the class body of a
+/// StatelessWidget, StatefulWidget, or State subtype.
+class WidgetCache {
+  /// Create a [WidgetCache] from a [Component] containing the flutter
+  /// framework.
+  WidgetCache(Component fullComponent) {
+    Library frameworkLibrary;
+    for (Library library in fullComponent.libraries) {
+      if (library?.importUri?.path == 'flutter/src/widgets/framework.dart') {
+        frameworkLibrary = library;
+        break;
+      }
+    }
+    if (frameworkLibrary == null) {
+      return;
+    }
+    for (Class classDeclaration in frameworkLibrary.classes) {
+      if (classDeclaration.name == _statelessWidgetClassName) {
+        _statelessWidget = classDeclaration;
+      } else if (classDeclaration.name == _statefulWidgetClassName) {
+        _statefulWidget = classDeclaration;
+      } else if (classDeclaration.name == _stateClassName) {
+        _state = classDeclaration;
+      }
+    }
+    _frameworkTypesLocated =
+        _statefulWidget != null && _state != null && _statelessWidget != null;
+  }
+
+  static const String _stateClassName = 'State';
+  static const String _statefulWidgetClassName = 'StatefulWidget';
+  static const String _statelessWidgetClassName = 'StatelessWidget';
+
+  Class _statelessWidget;
+  Class _state;
+  Class _statefulWidget;
+  bool _frameworkTypesLocated = false;
+
+  /// Mark [uri] as invalidated.
+  void invalidate(Uri uri) {
+    _invalidatedLibraries.add(uri);
+  }
+
+  /// Reset the invalidated libraries.
+  void reset() {
+    _invalidatedLibraries.clear();
+  }
+
+  final List<Uri> _invalidatedLibraries = <Uri>[];
+
+  /// Determine if any changes to [partialComponent] were located entirely
+  /// within the class body of a single `StatefulWidget`, `StatelessWidget` or
+  /// `State` subtype.
+  ///
+  /// Returns the class name if located, otherwise `null`.
+  String checkSingleWidgetTypeModified(
+    Component lastGoodComponent,
+    Component partialComponent,
+    ClassHierarchy classHierarchy,
+  ) {
+    if (!_frameworkTypesLocated ||
+        lastGoodComponent == null ||
+        _invalidatedLibraries.length != 1) {
+      return null;
+    }
+    Uri importUri = _invalidatedLibraries[0];
+    Library library;
+    for (Library candidateLibrary in partialComponent.libraries) {
+      if (candidateLibrary.importUri == importUri) {
+        library = candidateLibrary;
+        break;
+      }
+    }
+    if (library == null) {
+      return null;
+    }
+    List<int> oldSource = lastGoodComponent.uriToSource[library.fileUri].source;
+    List<int> newSource = partialComponent.uriToSource[library.fileUri].source;
+    // Library was added and does not exist in the old component.
+    if (oldSource == null) {
+      return null;
+    }
+    int newStartIndex = 0;
+    int newEndIndex = newSource.length - 1;
+    int oldStartIndex = 0;
+    int oldEndIndex = oldSource.length - 1;
+
+    while (newStartIndex < newEndIndex && oldStartIndex < oldEndIndex) {
+      if (newSource[newStartIndex] != oldSource[oldStartIndex]) {
+        break;
+      }
+      newStartIndex += 1;
+      oldStartIndex += 1;
+    }
+    while (newEndIndex > newStartIndex && oldEndIndex > oldStartIndex) {
+      if (newSource[newEndIndex] != oldSource[oldEndIndex]) {
+        break;
+      }
+      newEndIndex -= 1;
+      oldEndIndex -= 1;
+    }
+
+    Class newClass =
+        _locateContainingClass(library, newStartIndex, newEndIndex);
+    if (newClass == null) {
+      return null;
+    }
+
+    Library oldLibrary =
+        lastGoodComponent.libraries.firstWhere((Library library) {
+      return library.importUri == importUri;
+    });
+
+    Class oldClass =
+        _locateContainingClass(oldLibrary, oldStartIndex, oldEndIndex);
+
+    if (oldClass == null || oldClass.name != newClass.name) {
+      return null;
+    }
+
+    if (classHierarchy.isSubclassOf(newClass, _statelessWidget) ||
+        classHierarchy.isSubclassOf(newClass, _statefulWidget)) {
+      if (_hasSubClasses(newClass, partialComponent, classHierarchy)) {
+        return null;
+      }
+      return newClass.name;
+    }
+
+    // For changes to State classes, locate the name of the corresponding
+    // StatefulWidget that is provided as a type parameter. If the bounds are
+    // StatefulWidget itself, fail as that indicates the type was not
+    // specified.
+    Supertype stateSuperType =
+        classHierarchy.getClassAsInstanceOf(newClass, _state);
+    if (stateSuperType != null) {
+      if (stateSuperType.typeArguments.length != 1) {
+        return null;
+      }
+      DartType widgetType = stateSuperType.typeArguments[0];
+      if (widgetType is InterfaceType) {
+        Class statefulWidgetType = widgetType.classNode;
+        if (statefulWidgetType.name == _statefulWidgetClassName) {
+          return null;
+        }
+        if (_hasSubClasses(
+            statefulWidgetType, partialComponent, classHierarchy)) {
+          return null;
+        }
+        return statefulWidgetType.name;
+      }
+    }
+
+    return null;
+  }
+
+  /// Checks whether the class [node] has any subclasses.
+  bool _hasSubClasses(
+      Class node, Component component, ClassHierarchy classHierarchy) {
+    for (Library library in component.libraries) {
+      for (Class otherClass in library.classes) {
+        if (identical(otherClass, node)) {
+          continue;
+        }
+        if (classHierarchy.isSubclassOf(otherClass, node)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  // Locate the that fully contains the edit range, or null.
+  Class _locateContainingClass(
+      Library library, int startOffset, int endOffset) {
+    for (Class classDeclaration in library.classes) {
+      if (classDeclaration.startFileOffset <= startOffset &&
+          classDeclaration.fileEndOffset >= endOffset) {
+        return classDeclaration;
+      }
+    }
+    return null;
+  }
+}
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 3844240..5679493 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -416,6 +416,20 @@
 InvalidCatchArguments/example: Fail
 InvalidContinueTarget/analyzerCode: Fail
 InvalidContinueTarget/example: Fail
+InvalidGetterSetterType/analyzerCode: Fail
+InvalidGetterSetterTypeBothInheritedField/analyzerCode: Fail
+InvalidGetterSetterTypeBothInheritedFieldLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeBothInheritedGetter/analyzerCode: Fail
+InvalidGetterSetterTypeBothInheritedGetterLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeFieldInherited/analyzerCode: Fail
+InvalidGetterSetterTypeFieldInheritedLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeGetterInherited/analyzerCode: Fail
+InvalidGetterSetterTypeGetterInheritedLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeSetterInheritedField/analyzerCode: Fail
+InvalidGetterSetterTypeSetterInheritedFieldLegacy/analyzerCode: Fail
+InvalidGetterSetterTypeSetterInheritedGetter/analyzerCode: Fail
+InvalidGetterSetterTypeSetterInheritedGetterLegacy/analyzerCode: Fail
 InvalidInitializer/example: Fail
 InvalidPackageUri/analyzerCode: Fail
 InvalidPackageUri/example: Fail
@@ -448,6 +462,8 @@
 JsInteropNamedParameters/example: Fail # Web compiler specific
 JsInteropNonExternalConstructor/analyzerCode: Fail # Web compiler specific
 JsInteropNonExternalConstructor/example: Fail # Web compiler specific
+JsInteropNonExternalMember/analyzerCode: Fail # Web compiler specific
+JsInteropNonExternalMember/example: Fail # Web compiler specific
 LanguageVersionInvalidInDotPackages/analyzerCode: Fail
 LanguageVersionMismatchInPart/analyzerCode: Fail
 LanguageVersionMismatchInPart/part_wrapped_script: Fail # Part in (now) part.
@@ -455,6 +471,8 @@
 LanguageVersionMismatchInPatch/example: Fail
 LanguageVersionTooHigh/analyzerCode: Fail
 LanguageVersionTooHigh/part_wrapped_script: Fail # Content comes after "part of [...]" meaning it's not actually a language version specification.
+LateDefinitelyAssignedError/analyzerCode: Fail
+LateDefinitelyUnassignedError/analyzerCode: Fail
 LibraryDirectiveNotFirst/part_wrapped_script1: Fail # Defining library name in the (now) part.
 LibraryDirectiveNotFirst/part_wrapped_script2: Fail
 LibraryDirectiveNotFirst/part_wrapped_script3: Fail
@@ -462,6 +480,18 @@
 LibraryDirectiveNotFirst/script3: Fail
 ListLiteralTooManyTypeArguments/example: Fail
 LoadLibraryTakesNoArguments/example: Fail
+MainNotFunctionDeclaration/analyzerCode: Fail
+MainNotFunctionDeclarationExported/analyzerCode: Fail
+MainNotFunctionDeclarationExported/part_wrapped_script: Fail
+MainRequiredNamedParameters/analyzerCode: Fail
+MainRequiredNamedParametersExported/analyzerCode: Fail
+MainRequiredNamedParametersExported/part_wrapped_script: Fail
+MainTooManyRequiredParameters/analyzerCode: Fail
+MainTooManyRequiredParametersExported/analyzerCode: Fail
+MainTooManyRequiredParametersExported/part_wrapped_script: Fail
+MainWrongParameterType/analyzerCode: Fail
+MainWrongParameterTypeExported/analyzerCode: Fail
+MainWrongParameterTypeExported/part_wrapped_script: Fail
 MapLiteralTypeArgumentMismatch/example: Fail
 MetadataTypeArguments/example: Fail
 MethodNotFound/example: Fail
@@ -495,6 +525,14 @@
 NamedMixinOverride/analyzerCode: Fail
 NamedMixinOverride/example: Fail
 NativeClauseShouldBeAnnotation/example: Fail
+NeverReachableSwitchDefaultError/analyzerCode: Fail
+NeverReachableSwitchDefaultError/example: Fail
+NeverReachableSwitchDefaultWarning/analyzerCode: Fail
+NeverReachableSwitchDefaultWarning/example: Fail
+NeverValueError/analyzerCode: Fail
+NeverValueError/example: Fail
+NeverValueWarning/analyzerCode: Fail
+NeverValueWarning/example: Fail
 NoFormals/example: Fail
 NonAgnosticConstant/analyzerCode: Fail
 NonAgnosticConstant/example: Fail
@@ -505,8 +543,6 @@
 NonInstanceTypeVariableUse/example: Fail
 NonNullableInNullAware/analyzerCode: Fail
 NonNullableInNullAware/example: Fail
-NonNullableLateDefinitelyAssignedError/analyzerCode: Fail
-NonNullableLateDefinitelyUnassignedError/analyzerCode: Fail
 NonNullableNotAssignedError/analyzerCode: Fail
 NonNullableNotAssignedWarning/analyzerCode: Fail
 NonNullableNotAssignedWarning/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index d568f05..df50caa 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -61,7 +61,12 @@
 # `#unicode` a Unicode short identifier (U+xxxx). We use this to represent code
 #  units or code points.
 #
-# `#name`, `#name2`, `#name3`, `#name4`: names (as strings).
+# `#name`, `#name2`, `#name3`, `#name4`: names (as strings). Note that asserts
+#    check if these are empty. If they can be empty use an available `OKEmpty`
+#    version (or add the missing needed one(s)) to avoid triggering an assert.
+#
+# `#nameOKEmpty`: name (as string). Will use an "(unnamed)" default message if
+#    the string is null or empty. Otherwise see the describtion above.
 #
 # `#names`: A list of names (strings).
 #
@@ -71,6 +76,13 @@
 #    Note: as a rule of thumb, avoid using the `#string` keys. In particular,
 #    do not use them for composing error messages, see [diagnostics.md](
 #    lib/src/fasta/diagnostics.md#avoid-composing-messages-programmatically).
+#    Note that asserts check if these are empty. If they can be empty use an
+#    available `OKEmpty` version (or add the missing needed one(s)) to avoid
+#    triggering an assert.
+#
+# `#stringOKEmpty`: string (that isn't a name). Will use an "(empty)" default
+#    message if the string is null or empty.
+#    Otherwise see the describtion above.
 #
 # `#type`, #type2`, `#type3`: Kernel types.
 #
@@ -117,7 +129,7 @@
   template: "Expected constant '#constant' to be of type '#type', but was of type '#type2'."
 
 ConstEvalInvalidBinaryOperandType:
-  template: "Binary operator '#string' on '#constant' requires operand of type '#type', but was of type '#type2'."
+  template: "Binary operator '#stringOKEmpty' on '#constant' requires operand of type '#type', but was of type '#type2'."
 
 ConstEvalInvalidEqualsOperandType:
   template: "Binary operator '==' requires receiver constant '#constant' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type '#type'."
@@ -136,11 +148,11 @@
   template: "Constant expression must be non-null."
 
 ConstEvalInvalidMethodInvocation:
-  template: "The method '#string' can't be invoked on '#constant' in a constant expression."
+  template: "The method '#stringOKEmpty' can't be invoked on '#constant' in a constant expression."
   analyzerCode: UNDEFINED_OPERATOR
 
 ConstEvalInvalidPropertyGet:
-  template: "The property '#string' can't be accessed on '#constant' in a constant expression."
+  template: "The property '#stringOKEmpty' can't be accessed on '#constant' in a constant expression."
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
 
 ConstEvalInvalidStringInterpolationOperand:
@@ -150,7 +162,7 @@
   analyzerCode: CONST_EVAL_TYPE_BOOL_NUM_STRING
 
 ConstEvalInvalidStaticInvocation:
-  template: "The invocation of '#name' is not allowed in a constant expression."
+  template: "The invocation of '#nameOKEmpty' is not allowed in a constant expression."
   analyzerCode: CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
 
 ConstEvalInvalidSymbolName:
@@ -162,16 +174,16 @@
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
 
 ConstEvalFailedAssertionWithMessage:
-  template: "This assertion failed with message: #string"
+  template: "This assertion failed with message: #stringOKEmpty"
   analyzerCode: CONST_EVAL_THROWS_EXCEPTION
 
 ConstEvalNonConstantVariableGet:
-  template: "The variable '#string' is not a constant, only constant expressions are allowed."
+  template: "The variable '#nameOKEmpty' is not a constant, only constant expressions are allowed."
   analyzerCode: NON_CONSTANT_VALUE_IN_INITIALIZER
 
 ConstEvalDeferredLibrary:
   template: >
-    '#name' can't be used in a constant expression because it's marked as
+    '#nameOKEmpty' can't be used in a constant expression because it's marked as
     'deferred' which means it isn't available until loaded.
   tip: >
     Try moving the constant from the deferred library, or removing 'deferred'
@@ -494,8 +506,16 @@
 
 ExpectedIdentifier:
   template: "Expected an identifier, but got '#lexeme'."
+  tip: "Try inserting an identifier before '#lexeme'."
   analyzerCode: MISSING_IDENTIFIER
-  script: "do() {} main() {}"
+  script: "var = 42;"
+
+ExpectedIdentifierButGotKeyword:
+  template: "'#lexeme' can't be used as an identifier because it's a keyword."
+  tip: "Try renaming this to be an identifier that isn't a keyword."
+  index: 113
+  analyzerCode: ParserErrorCode.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+  script: "var default = 42;"
 
 EqualityCannotBeEqualityOperand:
   index: 1
@@ -2119,8 +2139,8 @@
   template: "This is the inherited member."
   severity: CONTEXT
 
-DeclaredMemberConflictsWithInheritedMembersCause:
-  template: "This is one of the inherited members."
+DeclaredMemberConflictsWithOverriddenMembersCause:
+  template: "This is one of the overridden members."
   severity: CONTEXT
 
 InheritedMembersConflict:
@@ -2216,6 +2236,171 @@
       method({required int? a});
     }
 
+InvalidGetterSetterType:
+  template: "The type '#type' of the getter '#name' is not a subtype of the type '#type2' of the setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      num get property;
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeGetterInherited:
+  template: "The type '#type' of the inherited getter '#name' is not a subtype of the type '#type2' of the setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      num get property;
+    }
+    abstract class B implements A {
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeFieldInherited:
+  template: "The type '#type' of the inherited field '#name' is not a subtype of the type '#type2' of the setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      final num property;
+      A(this.property);
+    }
+    abstract class B implements A {
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeSetterInheritedGetter:
+  template: "The type '#type' of the getter '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      void set property(int i);
+    }
+    abstract class B implements A {
+      num get property;
+    }
+
+InvalidGetterSetterTypeSetterInheritedField:
+  template: "The type '#type' of the field '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      void set property(int i);
+    }
+    abstract class B implements A {
+      final num property;
+      B(this.property);
+    }
+
+InvalidGetterSetterTypeBothInheritedField:
+  template: "The type '#type' of the inherited field '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      final num property;
+      A(this.property);
+    }
+    abstract class B {
+      void set property(int i);
+    }
+    abstract class C implements A, B {}
+
+InvalidGetterSetterTypeBothInheritedGetter:
+  template: "The type '#type' of the inherited getter '#name' is not a subtype of the type '#type2' of the inherited setter '#name2'."
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      num get property;
+    }
+    abstract class B {
+      void set property(int i);
+    }
+    abstract class C implements A, B {}
+
+InvalidGetterSetterTypeLegacy:
+  template: "The type '#type' of the getter '#name' is not assignable to the type '#type2' of the setter '#name2'."
+  script: |
+    abstract class A {
+      String get property;
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeGetterInheritedLegacy:
+  template: "The type '#type' of the inherited getter '#name' is not assignable to the type '#type2' of the setter '#name2'."
+  script: |
+    abstract class A {
+      String get property;
+    }
+    abstract class B implements A {
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeFieldInheritedLegacy:
+  template: "The type '#type' of the inherited field '#name' is not assignable to the type '#type2' of the setter '#name2'."
+  script: |
+    abstract class A {
+      final String property;
+      A(this.property);
+    }
+    abstract class B implements A {
+      void set property(int i);
+    }
+
+InvalidGetterSetterTypeSetterInheritedGetterLegacy:
+  template: "The type '#type' of the getter '#name' is not assignable to the type '#type2' of the inherited setter '#name2'."
+  script: |
+    abstract class A {
+      void set property(int i);
+    }
+    abstract class B implements A {
+      String get property;
+    }
+
+InvalidGetterSetterTypeSetterInheritedFieldLegacy:
+  template: "The type '#type' of the field '#name' is not assignable to the type '#type2' of the inherited setter '#name2'."
+  script: |
+    abstract class A {
+      void set property(int i);
+    }
+    abstract class B implements A {
+      final String property;
+      B(this.property);
+    }
+
+InvalidGetterSetterTypeBothInheritedFieldLegacy:
+  template: "The type '#type' of the inherited field '#name' is not assignable to the type '#type2' of the inherited setter '#name2'."
+  script: |
+    abstract class A {
+      final String property;
+      A(this.property);
+    }
+    abstract class B {
+      void set property(int i);
+    }
+    abstract class C implements A, B {}
+
+InvalidGetterSetterTypeBothInheritedGetterLegacy:
+  template: "The type '#type' of the inherited getter '#name' is not assignable to the type '#type2' of the inherited setter '#name2'."
+  script: |
+    abstract class A {
+      String get property;
+    }
+    abstract class B {
+      void set property(int i);
+    }
+    abstract class C implements A, B {}
+
+InvalidGetterSetterTypeFieldContext:
+  template: "This is the declaration of the field '#name'."
+  severity: CONTEXT
+
+InvalidGetterSetterTypeGetterContext:
+  template: "This is the declaration of the getter '#name'."
+  severity: CONTEXT
+
+InvalidGetterSetterTypeSetterContext:
+  template: "This is the declaration of the setter '#name'."
+  severity: CONTEXT
+
 PartOfSelf:
   template: "A file can't be a part of itself."
   analyzerCode: PART_OF_NON_PART
@@ -2940,10 +3125,10 @@
   severity: CONTEXT
 
 ConstConstructorLateFinalFieldError:
-  template: "Constructor is marked 'const' so fields can't be late."
+  template: "Can't have a late final field in a class with a const constructor."
 
 ConstConstructorLateFinalFieldCause:
-  template: "Field is late, but constructor is 'const'."
+  template: "This constructor is const."
   severity: CONTEXT
 
 ConstConstructorRedirectionToNonConst:
@@ -3061,6 +3246,14 @@
   tip: "Try replacing the colon with the keyword 'in'."
   analyzerCode: ParserErrorCode.COLON_IN_PLACE_OF_IN
 
+BinaryOperatorWrittenOut:
+  index: 112
+  template: "Binary operator '#string' is written as '#string2' instead of the written out word."
+  tip: "Try replacing '#string' with '#string2'."
+  analyzerCode: ParserErrorCode.BINARY_OPERATOR_WRITTEN_OUT
+  script: >
+    int foo(int x, int y) => x xor y;
+
 ExternalFactoryRedirection:
   index: 85
   template: "A redirecting factory can't be external."
@@ -3253,14 +3446,46 @@
     #num2%12.3 bytes/ms, and
     #num3%12.3 ms/libraries.
 
+CantInferTypeDueToNoCombinedSignature:
+  template: "Can't infer a type for '#name' as the overridden members don't have a combined signature."
+  tip: "Try adding an explicit type."
+  analyzerCode: COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE
+  configuration: nnbd-strong
+  script: |
+    class A {
+      void method(int a) {}
+    }
+    class B {
+      void method(String a) {}
+    }
+    class C implements A, B {
+      void method(a) {}
+    }
+
+CantInferReturnTypeDueToNoCombinedSignature:
+  template: "Can't infer a return type for '#name' as the overridden members don't have a combined signature."
+  tip: "Try adding an explicit type."
+  analyzerCode: COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE
+  configuration: nnbd-strong
+  script: |
+    abstract class A {
+      int get getter;
+    }
+    abstract class B {
+      String get getter;
+    }
+    abstract class C implements A, B {
+      get getter;
+    }
+
 CantInferTypeDueToInconsistentOverrides:
-  template: "Can't infer a type for '#name' as some of the inherited members have different types."
+  template: "Can't infer a type for '#name' as some of the overridden members have different types."
   tip: "Try adding an explicit type."
   analyzerCode: INVALID_METHOD_OVERRIDE
   external: testcases/inference/inconsistent_overrides.dart
 
 CantInferReturnTypeDueToInconsistentOverrides:
-  template: "Can't infer a return type for '#name' as some of the inherited members have different types."
+  template: "Can't infer a return type for '#name' as some of the overridden members have different types."
   tip: "Try adding an explicit type."
   analyzerCode: INVALID_METHOD_OVERRIDE
   external: testcases/inference/inconsistent_overrides.dart
@@ -4163,6 +4388,10 @@
   template: "JS interop classes do not support non-external constructors."
   tip: "Try annotating with `external`."
 
+JsInteropNonExternalMember:
+  template: "This JS interop member must be annotated with `external`. Only factories and static methods can be non-external."
+  tip: "Try annotating the member with `external`."
+
 DefaultListConstructorError:
   template: "Can't use the default List constructor."
   tip: "Try using List.filled instead."
@@ -4179,16 +4408,29 @@
       T t; t;
     }
 
-NonNullableLateDefinitelyUnassignedError:
-  template: "Non-nullable late variable '#name' without initializer is definitely unassigned."
+FinalNotAssignedError:
+  template: "Final variable '#name' must be assigned before it can be used."
+  analyzerCode: READ_POTENTIALLY_UNASSIGNED_FINAL
+  configuration: nnbd-strong
+  script: >
+    method(bool b) {
+      final int i;
+      if (b) {
+        i = 0;
+      }
+      i;
+    }
+
+LateDefinitelyUnassignedError:
+  template: "Late variable '#name' without initializer is definitely unassigned."
   configuration: nnbd-strong
   script: |
     method<T>() {
       late T t; t;
     }
 
-NonNullableLateDefinitelyAssignedError:
-  template: "Non-nullable late final variable '#name' definitely assigned."
+LateDefinitelyAssignedError:
+  template: "Late final variable '#name' definitely assigned."
   configuration: nnbd-strong
   script: |
     method() {
@@ -4197,6 +4439,17 @@
       t = 0;
     }
 
+FinalPossiblyAssignedError:
+  template: "Final variable '#name' might already be assigned at this point."
+  analyzerCode: ASSIGNMENT_TO_FINAL_LOCAL
+  configuration: nnbd-strong
+  script: |
+    method() {
+      final int i;
+      i = 0;
+      i = 0;
+    }
+
 NonAgnosticConstant:
   template: "Constant value is not strong/weak mode agnostic."
 
@@ -4278,3 +4531,85 @@
   script:
     - int set setter(_) {}
     - dynamic set setter(_) {}
+
+NeverReachableSwitchDefaultError:
+  template: "`null` encountered as case in a switch expression with a non-nullable enum type."
+
+NeverReachableSwitchDefaultWarning:
+  template: "The default case is not reachable with sound null safety because the switch expression is non-nullable."
+  severity: WARNING
+
+NeverValueError:
+  template: "`null` encountered as the result from expression with type `Never`."
+
+NeverValueWarning:
+  template: "The expression can not result in a value with sound null safety because the expression type is `Never`."
+  severity: WARNING
+
+MainNotFunctionDeclaration:
+  template: "The 'main' declaration must be a function declaration."
+  configuration: nnbd-strong
+  script:
+    - var main;
+
+MainNotFunctionDeclarationExported:
+  template: "The exported 'main' declaration must be a function declaration."
+  configuration: nnbd-strong
+  exampleAllowMoreCodes: true
+  script:
+    main.dart:
+      export 'lib.dart';
+    lib.dart:
+      var main;
+
+MainTooManyRequiredParameters:
+  template: "The 'main' method must have at most 2 required parameters."
+  configuration: nnbd-strong
+  script:
+    - main(a, b, c) {}
+
+MainTooManyRequiredParametersExported:
+  template: "The exported 'main' method must have at most 2 required parameters."
+  configuration: nnbd-strong
+  exampleAllowMoreCodes: true
+  script:
+    main.dart:
+      export 'lib.dart';
+    lib.dart:
+      main(a, b, c) {}
+
+MainRequiredNamedParameters:
+  template: "The 'main' method cannot have required named parameters."
+  configuration: nnbd-strong
+  script:
+    - main({required a}) {}
+
+MainRequiredNamedParametersExported:
+  template: "The exported 'main' method cannot have required named parameters."
+  configuration: nnbd-strong
+  exampleAllowMoreCodes: true
+  script:
+    main.dart:
+      export 'lib.dart';
+    lib.dart:
+      main({required a}) {}
+
+MainWrongParameterType:
+  template: "The type '#type' of the first parameter of the 'main' method is not a supertype of '#type2'."
+  configuration: nnbd-strong
+  script:
+    - main(Set<String> args) {}
+
+MainWrongParameterTypeExported:
+  template: "The type '#type' of the first parameter of the exported 'main' method is not a supertype of '#type2'."
+  configuration: nnbd-strong
+  exampleAllowMoreCodes: true
+  script:
+    main.dart:
+      export 'lib.dart';
+    lib.dart:
+      main(Set<String> args) {}
+
+ExportedMain:
+  template: "This is exported 'main' declaration."
+  severity: CONTEXT
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
index 2331267..0ec0417 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.expect
@@ -41,7 +41,7 @@
       handleAsyncModifier(null, null)
       beginBlockFunctionBody({)
         handleNoTypeArguments([)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
         handleIdentifier(, expression)
         handleNoTypeArguments(])
         handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
index 51983b2..923a947 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_00.dart.intertwined.expect
@@ -113,7 +113,7 @@
                                                       parseSend((, expression)
                                                         ensureIdentifier((, expression)
                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                                           rewriter()
                                                           listener: handleIdentifier(, expression)
                                                         listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
index ce13632..7cd89f8 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.expect
@@ -199,7 +199,7 @@
                     endArguments(0, (, ))
                     handleSend(D, ,)
                     handleRecoverableError(PositionalAfterNamedArgument, ], ])
-                    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                    handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                     handleIdentifier(, expression)
                     handleNoTypeArguments(])
                     handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
index eb5a793..19fb2c9 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_01.dart.intertwined.expect
@@ -449,7 +449,7 @@
                                                                               parseSend(,, expression)
                                                                                 ensureIdentifier(,, expression)
                                                                                   reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                                                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                                                                   rewriter()
                                                                                   listener: handleIdentifier(, expression)
                                                                                 listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
index 8f34cb0..cd7549e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.expect
@@ -36,7 +36,7 @@
           handleSend(foo, ))
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
           handleExpressionStatement(;)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
index 9828c2f..29aa2f0 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_03.dart.intertwined.expect
@@ -72,7 +72,7 @@
                                   parseSend(;, expression)
                                     ensureIdentifier(;, expression)
                                       reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
index 650a4a0..1afd0ff 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.expect
@@ -44,7 +44,7 @@
               handleSend(bar, ))
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
index 37ece75..16e5973 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_04.dart.intertwined.expect
@@ -104,7 +104,7 @@
                                                                       parseSend(;, expression)
                                                                         ensureIdentifier(;, expression)
                                                                           reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
index 82e783d..9e03ffc 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.expect
@@ -27,7 +27,7 @@
             handleNoConstructorReferenceContinuationAfterTypeArguments(()
           endConstructorReference(C, null, ()
           beginArguments(()
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., null, {token: ;}], ;, ;)
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
             handleIdentifier(, expression)
             handleNoTypeArguments(;)
             handleNoArguments(;)
diff --git a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
index e005b6c..b87515d 100644
--- a/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/bracket_mismatch_06.dart.intertwined.expect
@@ -57,7 +57,7 @@
                                           parseSend((, expression)
                                             ensureIdentifier((, expression)
                                               reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
-                                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., null, {token: ;}], ;, ;)
+                                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
                                               rewriter()
                                               listener: handleIdentifier(, expression)
                                             listener: handleNoTypeArguments(;)
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
index 3c0cebd..ed0f16b 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.expect
@@ -29,16 +29,16 @@
       handleAsyncModifier(async, null)
       beginBlockFunctionBody({)
         beginForStatement(for)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
           handleSend(, ))
           handleForInitializerExpressionStatement(, true)
           handleRecoverableError(Message[ExpectedButGot, Expected 'in' before this., null, {string: in}], ), ))
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           beginForInExpression())
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
             handleIdentifier(, expression)
             handleNoTypeArguments())
             handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
index f1c1fcd..e1a476f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_await_for.dart.intertwined.expect
@@ -42,7 +42,7 @@
                           parseSend((, expression)
                             ensureIdentifier((, expression)
                               reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments())
@@ -55,7 +55,7 @@
                 parseForInRest(, await, for, ))
                   parseForInLoopPartsRest(, await, for, ))
                     reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                     listener: beginForInExpression())
                     parseExpression(in)
                       parsePrecedenceExpression(in, 1, true)
@@ -64,7 +64,7 @@
                             parseSend(in, expression)
                               ensureIdentifier(in, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
index 83797a0..3a5b7b2 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.expect
@@ -29,14 +29,14 @@
       handleAsyncModifier(null, null)
       beginBlockFunctionBody({)
         beginForStatement(for)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
           handleSend(, ))
           handleForInitializerExpressionStatement(, false)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
index c1b40e9..55ccd48 100644
--- a/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/empty_for.dart.intertwined.expect
@@ -42,7 +42,7 @@
                           parseSend((, expression)
                             ensureIdentifier((, expression)
                               reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments())
@@ -64,7 +64,7 @@
                               parseSend(;, expression)
                                 ensureIdentifier(;, expression)
                                   reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                   rewriter()
                                   listener: handleIdentifier(, expression)
                                 listener: handleNoTypeArguments())
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart
new file mode 100644
index 0000000..f65a3e9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart
@@ -0,0 +1,41 @@
+abstract class Key {
+  int get a => runtimeType.hashCode xor null.hashCode;
+  int get b => runtimeType.hashCode ^ null.hashCode;
+  int get c { return runtimeType.hashCode xor null.hashCode; }
+  int get d { return runtimeType.hashCode ^ null.hashCode; }
+
+  int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+  int get h { return 1 + runtimeType.hashCode ^ null.hashCode + 3; }
+
+  int i(int x, int y) => x xor y;
+  int j(int x, int y) => x ^ y;
+  int k(int x, int y) { return x xor y; }
+  int l(int x, int y) { return x ^ y; }
+  int m(int x, int y) { int z =  x xor y; return z; }
+  int n(int x, int y) { int z = x ^ y; return z; }
+
+  int o(int x, int y) => 1 + x xor y + 3;
+  int p(int x, int y) => 1 + x ^ y + 3;
+  int q(int x, int y) { return 1 + x xor y + 3; }
+  int r(int x, int y) { return 1 + x ^ y + 3; }
+
+  s(int x, int y) {
+    s(x xor y, x xor y);
+    s(x ^ y, x ^ y);
+  }
+
+  Key(int x, int y) : foo = x xor y, bar = x xor y {
+    print("hello ${x xor y}");
+  }
+
+  Key(int x, int y) : foo = x ^ y, bar = x ^ y {
+    print("hello ${x ^ y}");
+  }
+
+  not_currently_working(int x, int y) {
+    x xor y;
+    x ^ y;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.expect
new file mode 100644
index 0000000..9eb58d9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.expect
@@ -0,0 +1,1221 @@
+Problems reported:
+
+parser/error_recovery/issue_26810:2:37: Binary operator 'xor' is written as '^' instead of the written out word.
+  int get a => runtimeType.hashCode xor null.hashCode;
+                                    ^^^
+
+parser/error_recovery/issue_26810:4:43: Binary operator 'xor' is written as '^' instead of the written out word.
+  int get c { return runtimeType.hashCode xor null.hashCode; }
+                                          ^^^
+
+parser/error_recovery/issue_26810:7:41: Binary operator 'xor' is written as '^' instead of the written out word.
+  int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+                                        ^^^
+
+parser/error_recovery/issue_26810:9:47: Binary operator 'xor' is written as '^' instead of the written out word.
+  int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+                                              ^^^
+
+parser/error_recovery/issue_26810:12:28: Binary operator 'xor' is written as '^' instead of the written out word.
+  int i(int x, int y) => x xor y;
+                           ^^^
+
+parser/error_recovery/issue_26810:14:34: Binary operator 'xor' is written as '^' instead of the written out word.
+  int k(int x, int y) { return x xor y; }
+                                 ^^^
+
+parser/error_recovery/issue_26810:16:36: Binary operator 'xor' is written as '^' instead of the written out word.
+  int m(int x, int y) { int z =  x xor y; return z; }
+                                   ^^^
+
+parser/error_recovery/issue_26810:19:32: Binary operator 'xor' is written as '^' instead of the written out word.
+  int o(int x, int y) => 1 + x xor y + 3;
+                               ^^^
+
+parser/error_recovery/issue_26810:21:38: Binary operator 'xor' is written as '^' instead of the written out word.
+  int q(int x, int y) { return 1 + x xor y + 3; }
+                                     ^^^
+
+parser/error_recovery/issue_26810:25:9: Binary operator 'xor' is written as '^' instead of the written out word.
+    s(x xor y, x xor y);
+        ^^^
+
+parser/error_recovery/issue_26810:25:18: Binary operator 'xor' is written as '^' instead of the written out word.
+    s(x xor y, x xor y);
+                 ^^^
+
+parser/error_recovery/issue_26810:29:31: Binary operator 'xor' is written as '^' instead of the written out word.
+  Key(int x, int y) : foo = x xor y, bar = x xor y {
+                              ^^^
+
+parser/error_recovery/issue_26810:29:46: Binary operator 'xor' is written as '^' instead of the written out word.
+  Key(int x, int y) : foo = x xor y, bar = x xor y {
+                                             ^^^
+
+parser/error_recovery/issue_26810:30:22: Binary operator 'xor' is written as '^' instead of the written out word.
+    print("hello ${x xor y}");
+                     ^^^
+
+parser/error_recovery/issue_26810:38:7: Expected ';' after this.
+    x xor y;
+      ^^^
+
+beginCompilationUnit(abstract)
+  beginMetadataStar(abstract)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(abstract)
+    handleIdentifier(Key, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(abstract, abstract, Key)
+      handleNoType(Key)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(abstract, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, a)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(a, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(xor)
+            handleNoArguments(xor)
+            handleSend(hashCode, xor)
+            handleEndingBinaryExpression(.)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+            beginBinaryExpression(^)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, b)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(b, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(^)
+            handleNoArguments(^)
+            handleSend(hashCode, ^)
+            handleEndingBinaryExpression(.)
+            beginBinaryExpression(^)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, c)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(c, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(hashCode, xor)
+                handleEndingBinaryExpression(.)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, d)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(d, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(hashCode, ^)
+                handleEndingBinaryExpression(.)
+                beginBinaryExpression(^)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, e)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(e, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(xor)
+              handleNoArguments(xor)
+              handleSend(hashCode, xor)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+            beginBinaryExpression(^)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, f)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(f, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(^)
+              handleNoArguments(^)
+              handleSend(hashCode, ^)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            beginBinaryExpression(^)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, g)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(g, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(xor)
+                  handleNoArguments(xor)
+                  handleSend(hashCode, xor)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, h)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(h, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(^)
+                  handleNoArguments(^)
+                  handleSend(hashCode, ^)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                beginBinaryExpression(^)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, i)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(i)
+            handleType(int, null)
+            handleIdentifier(i, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(xor)
+            handleNoArguments(xor)
+            handleSend(x, xor)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+            beginBinaryExpression(^)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, j)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(j)
+            handleType(int, null)
+            handleIdentifier(j, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(^)
+            handleNoArguments(^)
+            handleSend(x, ^)
+            beginBinaryExpression(^)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, k)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(k)
+            handleType(int, null)
+            handleIdentifier(k, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(x, xor)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, l)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(l)
+            handleType(int, null)
+            handleIdentifier(l, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(x, ^)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, m)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(m)
+            handleType(int, null)
+            handleIdentifier(m, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(xor)
+                    handleNoArguments(xor)
+                    handleSend(x, xor)
+                    handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                    beginBinaryExpression(^)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(^)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, n)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(n)
+            handleType(int, null)
+            handleIdentifier(n, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(^)
+                    handleNoArguments(^)
+                    handleSend(x, ^)
+                    beginBinaryExpression(^)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(^)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, o)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(o)
+            handleType(int, null)
+            handleIdentifier(o, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(xor)
+              handleNoArguments(xor)
+              handleSend(x, xor)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+            beginBinaryExpression(^)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, p)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(p)
+            handleType(int, null)
+            handleIdentifier(p, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(^)
+              handleNoArguments(^)
+              handleSend(x, ^)
+            endBinaryExpression(+)
+            beginBinaryExpression(^)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(^)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, q)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(q)
+            handleType(int, null)
+            handleIdentifier(q, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(xor)
+                  handleNoArguments(xor)
+                  handleSend(x, xor)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, r)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(r)
+            handleType(int, null)
+            handleIdentifier(r, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(^)
+                  handleNoArguments(^)
+                  handleSend(x, ^)
+                endBinaryExpression(+)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(^)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(s)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, s)
+            handleNoType(})
+            handleIdentifier(s, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(x, xor)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(^)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(x, xor)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(^)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(x, ^)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(^)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(x, ^)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(^)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, s, (, null, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(x, xor)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(^)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(xor)
+                handleNoArguments(xor)
+                handleSend(x, xor)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(^)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(xor)
+                  handleNoArguments(xor)
+                  handleSend(x, xor)
+                  handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                  beginBinaryExpression(^)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(^)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(x, ^)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(^)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(^)
+                handleNoArguments(^)
+                handleSend(x, ^)
+                beginBinaryExpression(^)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(^)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(^)
+                  handleNoArguments(^)
+                  handleSend(x, ^)
+                  beginBinaryExpression(^)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(^)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(not_currently_working)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, not_currently_working)
+            handleNoType(})
+            handleIdentifier(not_currently_working, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(x)
+              endMetadataStar(0)
+              handleIdentifier(x, typeReference)
+              handleNoTypeArguments(xor)
+              handleType(x, null)
+              beginVariablesDeclaration(xor, null, null)
+                handleIdentifier(xor, localVariableDeclaration)
+                beginInitializedIdentifier(xor)
+                  handleNoVariableInitializer(xor)
+                endInitializedIdentifier(xor)
+                handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], xor, xor)
+              endVariablesDeclaration(1, ;)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(^)
+              handleNoArguments(^)
+              handleSend(x, ^)
+              beginBinaryExpression(^)
+                handleIdentifier(y, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(y, ;)
+              endBinaryExpression(^)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(3, {, })
+          endClassMethod(null, not_currently_working, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+    endClassDeclaration(abstract, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.intertwined.expect
new file mode 100644
index 0000000..b6c6fda
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.intertwined.expect
@@ -0,0 +1,2594 @@
+parseUnit(abstract)
+  skipErrorTokens(abstract)
+  listener: beginCompilationUnit(abstract)
+  syntheticPreviousToken(abstract)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(abstract)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+        parseTopLevelKeywordModifiers(abstract, class)
+      parseClassOrNamedMixinApplication(abstract, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(abstract)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Key, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(abstract, abstract, Key)
+        parseClass(Key, abstract, class, Key)
+          parseClassHeaderOpt(Key, abstract, class)
+            parseClassExtendsOpt(Key)
+              listener: handleNoType(Key)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(Key)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(Key)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(abstract, class, null)
+          parseClassOrMixinOrExtensionBody(Key, DeclarationKind.Class, Key)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Key)
+              parseMetadataStar({)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'SimpleType', get, a, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, a)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(a, methodDeclaration)
+                parseQualifiedRestOpt(a, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(a, a, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(a)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(a)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(a, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(xor)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(xor)
+                              listener: handleSend(hashCode, xor)
+                        listener: handleEndingBinaryExpression(.)
+                        rewriter()
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                        reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                        rewriter()
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, b, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, b)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(b, methodDeclaration)
+                parseQualifiedRestOpt(b, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(b, b, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(b)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(b)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(b, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(^)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(^)
+                              listener: handleSend(hashCode, ^)
+                        listener: handleEndingBinaryExpression(.)
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, c, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, c)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(c, methodDeclaration)
+                parseQualifiedRestOpt(c, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(c, c, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(c)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(c)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(c, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(xor)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(xor)
+                                  listener: handleSend(hashCode, xor)
+                            listener: handleEndingBinaryExpression(.)
+                            rewriter()
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                            reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                            rewriter()
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, d, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, d)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(d, methodDeclaration)
+                parseQualifiedRestOpt(d, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(d, d, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(d)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(d)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(d, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(^)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(^)
+                                  listener: handleSend(hashCode, ^)
+                            listener: handleEndingBinaryExpression(.)
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, e, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, e)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(e, methodDeclaration)
+                parseQualifiedRestOpt(e, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(e, e, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(e)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(e)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(e, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(xor)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(xor)
+                                listener: handleSend(hashCode, xor)
+                          listener: handleEndingBinaryExpression(.)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                        rewriter()
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, f, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, f)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(f, methodDeclaration)
+                parseQualifiedRestOpt(f, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(f, f, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(f)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(f)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(f, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(^)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(^)
+                                listener: handleSend(hashCode, ^)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseLiteralNull(^)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, g, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, g)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(g, methodDeclaration)
+                parseQualifiedRestOpt(g, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(g, g, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(g)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(g)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(g, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(xor)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(xor)
+                                    listener: handleSend(hashCode, xor)
+                              listener: handleEndingBinaryExpression(.)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                            rewriter()
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, h, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, h)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(h, methodDeclaration)
+                parseQualifiedRestOpt(h, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(h, h, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(h)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(h)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(h, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(^)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(^)
+                                    listener: handleSend(hashCode, ^)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseLiteralNull(^)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, i, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, i)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(i, methodDeclaration)
+                parseQualifiedRestOpt(i, methodDeclarationContinuation)
+                parseMethodTypeVar(i)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(i, i, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(i, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(xor)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(xor)
+                                listener: handleSend(x, xor)
+                        rewriter()
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                  parseArgumentsOpt(y)
+                        reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                        rewriter()
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, j, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, j)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(j)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(j, methodDeclaration)
+                parseQualifiedRestOpt(j, methodDeclarationContinuation)
+                parseMethodTypeVar(j)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(j, j, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(j, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(^)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(^)
+                                listener: handleSend(x, ^)
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, k, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, k)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(k)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(k, methodDeclaration)
+                parseQualifiedRestOpt(k, methodDeclarationContinuation)
+                parseMethodTypeVar(k)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(k, k, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(k, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(xor)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(xor)
+                                    listener: handleSend(x, xor)
+                            rewriter()
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                      parseArgumentsOpt(y)
+                            reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                            rewriter()
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, l, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, l)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(l)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(l, methodDeclaration)
+                parseQualifiedRestOpt(l, methodDeclarationContinuation)
+                parseMethodTypeVar(l)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(l, l, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(l, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(^)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(^)
+                                    listener: handleSend(x, ^)
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, m, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, m)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(m)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(m, methodDeclaration)
+                parseQualifiedRestOpt(m, methodDeclarationContinuation)
+                parseMethodTypeVar(m)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(m, m, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(m, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(xor)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(xor)
+                                          listener: handleSend(x, xor)
+                                  rewriter()
+                                  parsePrecedenceExpression(^, 11, true)
+                                    parseUnaryExpression(^, true)
+                                      parsePrimary(^, expression)
+                                        parseSendOrFunctionLiteral(^, expression)
+                                          parseSend(^, expression)
+                                            ensureIdentifier(^, expression)
+                                            parseArgumentsOpt(y)
+                                  reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                    listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                                  rewriter()
+                                  listener: beginBinaryExpression(^)
+                                  parsePrecedenceExpression(^, 11, true)
+                                    parseUnaryExpression(^, true)
+                                      parsePrimary(^, expression)
+                                        parseSendOrFunctionLiteral(^, expression)
+                                          parseSend(^, expression)
+                                            ensureIdentifier(^, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(^)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, n, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, n)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(n)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(n, methodDeclaration)
+                parseQualifiedRestOpt(n, methodDeclarationContinuation)
+                parseMethodTypeVar(n)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(n, n, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(n, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(^)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(^)
+                                          listener: handleSend(x, ^)
+                                  listener: beginBinaryExpression(^)
+                                  parsePrecedenceExpression(^, 11, true)
+                                    parseUnaryExpression(^, true)
+                                      parsePrimary(^, expression)
+                                        parseSendOrFunctionLiteral(^, expression)
+                                          parseSend(^, expression)
+                                            ensureIdentifier(^, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(^)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, o, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, o)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(o)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(o, methodDeclaration)
+                parseQualifiedRestOpt(o, methodDeclarationContinuation)
+                parseMethodTypeVar(o)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(o, o, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(o, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(xor)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(xor)
+                                  listener: handleSend(x, xor)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                  parseArgumentsOpt(y)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                        rewriter()
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, p, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, p)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(p)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(p, methodDeclaration)
+                parseQualifiedRestOpt(p, methodDeclarationContinuation)
+                parseMethodTypeVar(p)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(p, p, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(p, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(^)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(^)
+                                  listener: handleSend(x, ^)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(^)
+                        parsePrecedenceExpression(^, 11, true)
+                          parseUnaryExpression(^, true)
+                            parsePrimary(^, expression)
+                              parseSendOrFunctionLiteral(^, expression)
+                                parseSend(^, expression)
+                                  ensureIdentifier(^, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(^)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, q, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, q)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(q)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(q, methodDeclaration)
+                parseQualifiedRestOpt(q, methodDeclarationContinuation)
+                parseMethodTypeVar(q)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(q, q, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(q, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(xor)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(xor)
+                                      listener: handleSend(x, xor)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                      parseArgumentsOpt(y)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                            rewriter()
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, r, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, r)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(r)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(r, methodDeclaration)
+                parseQualifiedRestOpt(r, methodDeclarationContinuation)
+                parseMethodTypeVar(r)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(r, r, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(r, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(^)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(^)
+                                      listener: handleSend(x, ^)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(^)
+                            parsePrecedenceExpression(^, 11, true)
+                              parseUnaryExpression(^, true)
+                                parsePrimary(^, expression)
+                                  parseSendOrFunctionLiteral(^, expression)
+                                    parseSend(^, expression)
+                                      ensureIdentifier(^, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(^)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, s)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(s)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, s, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, s)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(s, methodDeclaration)
+                parseQualifiedRestOpt(s, methodDeclarationContinuation)
+                parseMethodTypeVar(s)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(s, s, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(s, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, s)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(xor)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(xor)
+                                                        listener: handleSend(x, xor)
+                                                rewriter()
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                                                rewriter()
+                                                listener: beginBinaryExpression(^)
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(^)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(xor)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(xor)
+                                                        listener: handleSend(x, xor)
+                                                rewriter()
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                                                rewriter()
+                                                listener: beginBinaryExpression(^)
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(^)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, s)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(^)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(^)
+                                                        listener: handleSend(x, ^)
+                                                listener: beginBinaryExpression(^)
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(^)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(^)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(^)
+                                                        listener: handleSend(x, ^)
+                                                listener: beginBinaryExpression(^)
+                                                parsePrecedenceExpression(^, 11, true)
+                                                  parseUnaryExpression(^, true)
+                                                    parsePrimary(^, expression)
+                                                      parseSendOrFunctionLiteral(^, expression)
+                                                        parseSend(^, expression)
+                                                          ensureIdentifier(^, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(^)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, s, (, null, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(xor)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(xor)
+                                      listener: handleSend(x, xor)
+                              rewriter()
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                              rewriter()
+                              listener: beginBinaryExpression(^)
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(^)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(xor)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(xor)
+                                      listener: handleSend(x, xor)
+                              rewriter()
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                              rewriter()
+                              listener: beginBinaryExpression(^)
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(^)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(xor)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(xor)
+                                                                    listener: handleSend(x, xor)
+                                                            rewriter()
+                                                            parsePrecedenceExpression(^, 11, true)
+                                                              parseUnaryExpression(^, true)
+                                                                parsePrimary(^, expression)
+                                                                  parseSendOrFunctionLiteral(^, expression)
+                                                                    parseSend(^, expression)
+                                                                      ensureIdentifier(^, expression)
+                                                                      parseArgumentsOpt(y)
+                                                            reportRecoverableError(xor, Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}])
+                                                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'xor' is written as '^' instead of the written out word., Try replacing 'xor' with '^'., {string: xor, string2: ^}], xor, xor)
+                                                            rewriter()
+                                                            listener: beginBinaryExpression(^)
+                                                            parsePrecedenceExpression(^, 11, true)
+                                                              parseUnaryExpression(^, true)
+                                                                parsePrimary(^, expression)
+                                                                  parseSendOrFunctionLiteral(^, expression)
+                                                                    parseSend(^, expression)
+                                                                      ensureIdentifier(^, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(^)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(^)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(^)
+                                      listener: handleSend(x, ^)
+                              listener: beginBinaryExpression(^)
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(^)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(^)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(^)
+                                      listener: handleSend(x, ^)
+                              listener: beginBinaryExpression(^)
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(^)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(^)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(^)
+                                                                    listener: handleSend(x, ^)
+                                                            listener: beginBinaryExpression(^)
+                                                            parsePrecedenceExpression(^, 11, true)
+                                                              parseUnaryExpression(^, true)
+                                                                parsePrimary(^, expression)
+                                                                  parseSendOrFunctionLiteral(^, expression)
+                                                                    parseSend(^, expression)
+                                                                      ensureIdentifier(^, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(^)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, not_currently_working)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(not_currently_working)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, not_currently_working, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, not_currently_working)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(not_currently_working, methodDeclaration)
+                parseQualifiedRestOpt(not_currently_working, methodDeclarationContinuation)
+                parseMethodTypeVar(not_currently_working)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(not_currently_working, not_currently_working, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(not_currently_working, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, x)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(xor)
+                        listener: beginMetadataStar(x)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(x, typeReference)
+                        listener: handleNoTypeArguments(xor)
+                        listener: handleType(x, null)
+                        listener: beginVariablesDeclaration(xor, null, null)
+                        parseVariablesDeclarationRest(x, true)
+                          parseOptionallyInitializedIdentifier(x)
+                            ensureIdentifier(x, localVariableDeclaration)
+                              listener: handleIdentifier(xor, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(xor)
+                            parseVariableInitializerOpt(xor)
+                              listener: handleNoVariableInitializer(xor)
+                            listener: endInitializedIdentifier(xor)
+                          ensureSemicolon(xor)
+                            reportRecoverableError(xor, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                              listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], xor, xor)
+                            rewriter()
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, y)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(y)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, x)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(x)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(^)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(^)
+                                      listener: handleSend(x, ^)
+                              listener: beginBinaryExpression(^)
+                              parsePrecedenceExpression(^, 11, true)
+                                parseUnaryExpression(^, true)
+                                  parsePrimary(^, expression)
+                                    parseSendOrFunctionLiteral(^, expression)
+                                      parseSend(^, expression)
+                                        ensureIdentifier(^, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(;)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(;)
+                                        listener: handleSend(y, ;)
+                              listener: endBinaryExpression(^)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(3, {, })
+                listener: endClassMethod(null, not_currently_working, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+          listener: endClassDeclaration(abstract, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(abstract)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.parser.expect
new file mode 100644
index 0000000..c51d463
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.parser.expect
@@ -0,0 +1,87 @@
+NOTICE: Stream was rewritten by parser!
+
+abstract class Key {
+int get a => runtimeType.hashCode ^ null.hashCode;
+int get b => runtimeType.hashCode ^ null.hashCode;
+int get c { return runtimeType.hashCode ^ null.hashCode; }
+int get d { return runtimeType.hashCode ^ null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode ^ null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode ^ null.hashCode + 3; }
+
+int i(int x, int y) => x ^ y;
+int j(int x, int y) => x ^ y;
+int k(int x, int y) { return x ^ y; }
+int l(int x, int y) { return x ^ y; }
+int m(int x, int y) { int z = x ^ y; return z; }
+int n(int x, int y) { int z = x ^ y; return z; }
+
+int o(int x, int y) => 1 + x ^ y + 3;
+int p(int x, int y) => 1 + x ^ y + 3;
+int q(int x, int y) { return 1 + x ^ y + 3; }
+int r(int x, int y) { return 1 + x ^ y + 3; }
+
+s(int x, int y) {
+s(x ^ y, x ^ y);
+s(x ^ y, x ^ y);
+}
+
+Key(int x, int y) : foo = x ^ y, bar = x ^ y {
+print("hello ${x ^ y}");
+}
+
+Key(int x, int y) : foo = x ^ y, bar = x ^ y {
+print("hello ${x ^ y}");
+}
+
+not_currently_working(int x, int y) {
+x xor ;y;
+x ^ y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] ^[ReplacementToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] ^[ReplacementToken] y[StringToken],[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] ^[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] ^[ReplacementToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] ^[ReplacementToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] ^[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] xor[StringToken] ;[SyntheticToken]y[StringToken];[SimpleToken]
+x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.scanner.expect
new file mode 100644
index 0000000..e6fe2c9
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810.dart.scanner.expect
@@ -0,0 +1,85 @@
+abstract class Key {
+int get a => runtimeType.hashCode xor null.hashCode;
+int get b => runtimeType.hashCode ^ null.hashCode;
+int get c { return runtimeType.hashCode xor null.hashCode; }
+int get d { return runtimeType.hashCode ^ null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode ^ null.hashCode + 3; }
+
+int i(int x, int y) => x xor y;
+int j(int x, int y) => x ^ y;
+int k(int x, int y) { return x xor y; }
+int l(int x, int y) { return x ^ y; }
+int m(int x, int y) { int z = x xor y; return z; }
+int n(int x, int y) { int z = x ^ y; return z; }
+
+int o(int x, int y) => 1 + x xor y + 3;
+int p(int x, int y) => 1 + x ^ y + 3;
+int q(int x, int y) { return 1 + x xor y + 3; }
+int r(int x, int y) { return 1 + x ^ y + 3; }
+
+s(int x, int y) {
+s(x xor y, x xor y);
+s(x ^ y, x ^ y);
+}
+
+Key(int x, int y) : foo = x xor y, bar = x xor y {
+print("hello ${x xor y}");
+}
+
+Key(int x, int y) : foo = x ^ y, bar = x ^ y {
+print("hello ${x ^ y}");
+}
+
+not_currently_working(int x, int y) {
+x xor y;
+x ^ y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] xor[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] xor[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] xor[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] xor[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] ^[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] xor[StringToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] xor[StringToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] xor[StringToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] xor[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] xor[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] xor[StringToken] y[StringToken],[SimpleToken] x[StringToken] xor[StringToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] ^[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] xor[StringToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] xor[StringToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] xor[StringToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] ^[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] ^[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] xor[StringToken] y[StringToken];[SimpleToken]
+x[StringToken] ^[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart
new file mode 100644
index 0000000..cf6ecb7
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart
@@ -0,0 +1,41 @@
+abstract class Key {
+  int get a => runtimeType.hashCode and null.hashCode;
+  int get b => runtimeType.hashCode & null.hashCode;
+  int get c { return runtimeType.hashCode and null.hashCode; }
+  int get d { return runtimeType.hashCode & null.hashCode; }
+
+  int get e => 1 + runtimeType.hashCode and null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode & null.hashCode + 3;
+  int get g { return 1 + runtimeType.hashCode and null.hashCode + 3; }
+  int get h { return 1 + runtimeType.hashCode & null.hashCode + 3; }
+
+  int i(int x, int y) => x and y;
+  int j(int x, int y) => x & y;
+  int k(int x, int y) { return x and y; }
+  int l(int x, int y) { return x & y; }
+  int m(int x, int y) { int z =  x and y; return z; }
+  int n(int x, int y) { int z = x & y; return z; }
+
+  int o(int x, int y) => 1 + x and y + 3;
+  int p(int x, int y) => 1 + x & y + 3;
+  int q(int x, int y) { return 1 + x and y + 3; }
+  int r(int x, int y) { return 1 + x & y + 3; }
+
+  s(int x, int y) {
+    s(x and y, x and y);
+    s(x & y, x & y);
+  }
+
+  Key(int x, int y) : foo = x and y, bar = x and y {
+    print("hello ${x and y}");
+  }
+
+  Key(int x, int y) : foo = x & y, bar = x & y {
+    print("hello ${x & y}");
+  }
+
+  not_currently_working(int x, int y) {
+    x and y;
+    x & y;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.expect
new file mode 100644
index 0000000..e907a22
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.expect
@@ -0,0 +1,1221 @@
+Problems reported:
+
+parser/error_recovery/issue_26810_and:2:37: Binary operator 'and' is written as '&' instead of the written out word.
+  int get a => runtimeType.hashCode and null.hashCode;
+                                    ^^^
+
+parser/error_recovery/issue_26810_and:4:43: Binary operator 'and' is written as '&' instead of the written out word.
+  int get c { return runtimeType.hashCode and null.hashCode; }
+                                          ^^^
+
+parser/error_recovery/issue_26810_and:7:41: Binary operator 'and' is written as '&' instead of the written out word.
+  int get e => 1 + runtimeType.hashCode and null.hashCode + 3;
+                                        ^^^
+
+parser/error_recovery/issue_26810_and:9:47: Binary operator 'and' is written as '&' instead of the written out word.
+  int get g { return 1 + runtimeType.hashCode and null.hashCode + 3; }
+                                              ^^^
+
+parser/error_recovery/issue_26810_and:12:28: Binary operator 'and' is written as '&' instead of the written out word.
+  int i(int x, int y) => x and y;
+                           ^^^
+
+parser/error_recovery/issue_26810_and:14:34: Binary operator 'and' is written as '&' instead of the written out word.
+  int k(int x, int y) { return x and y; }
+                                 ^^^
+
+parser/error_recovery/issue_26810_and:16:36: Binary operator 'and' is written as '&' instead of the written out word.
+  int m(int x, int y) { int z =  x and y; return z; }
+                                   ^^^
+
+parser/error_recovery/issue_26810_and:19:32: Binary operator 'and' is written as '&' instead of the written out word.
+  int o(int x, int y) => 1 + x and y + 3;
+                               ^^^
+
+parser/error_recovery/issue_26810_and:21:38: Binary operator 'and' is written as '&' instead of the written out word.
+  int q(int x, int y) { return 1 + x and y + 3; }
+                                     ^^^
+
+parser/error_recovery/issue_26810_and:25:9: Binary operator 'and' is written as '&' instead of the written out word.
+    s(x and y, x and y);
+        ^^^
+
+parser/error_recovery/issue_26810_and:25:18: Binary operator 'and' is written as '&' instead of the written out word.
+    s(x and y, x and y);
+                 ^^^
+
+parser/error_recovery/issue_26810_and:29:31: Binary operator 'and' is written as '&' instead of the written out word.
+  Key(int x, int y) : foo = x and y, bar = x and y {
+                              ^^^
+
+parser/error_recovery/issue_26810_and:29:46: Binary operator 'and' is written as '&' instead of the written out word.
+  Key(int x, int y) : foo = x and y, bar = x and y {
+                                             ^^^
+
+parser/error_recovery/issue_26810_and:30:22: Binary operator 'and' is written as '&' instead of the written out word.
+    print("hello ${x and y}");
+                     ^^^
+
+parser/error_recovery/issue_26810_and:38:7: Expected ';' after this.
+    x and y;
+      ^^^
+
+beginCompilationUnit(abstract)
+  beginMetadataStar(abstract)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(abstract)
+    handleIdentifier(Key, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(abstract, abstract, Key)
+      handleNoType(Key)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(abstract, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, a)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(a, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(and)
+            handleNoArguments(and)
+            handleSend(hashCode, and)
+            handleEndingBinaryExpression(.)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+            beginBinaryExpression(&)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, b)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(b, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(&)
+            handleNoArguments(&)
+            handleSend(hashCode, &)
+            handleEndingBinaryExpression(.)
+            beginBinaryExpression(&)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, c)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(c, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(hashCode, and)
+                handleEndingBinaryExpression(.)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, d)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(d, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(hashCode, &)
+                handleEndingBinaryExpression(.)
+                beginBinaryExpression(&)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, e)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(e, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(and)
+              handleNoArguments(and)
+              handleSend(hashCode, and)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+            beginBinaryExpression(&)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, f)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(f, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(&)
+              handleNoArguments(&)
+              handleSend(hashCode, &)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            beginBinaryExpression(&)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, g)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(g, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(and)
+                  handleNoArguments(and)
+                  handleSend(hashCode, and)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, h)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(h, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(&)
+                  handleNoArguments(&)
+                  handleSend(hashCode, &)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                beginBinaryExpression(&)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, i)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(i)
+            handleType(int, null)
+            handleIdentifier(i, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(and)
+            handleNoArguments(and)
+            handleSend(x, and)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+            beginBinaryExpression(&)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, j)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(j)
+            handleType(int, null)
+            handleIdentifier(j, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(&)
+            handleNoArguments(&)
+            handleSend(x, &)
+            beginBinaryExpression(&)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, k)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(k)
+            handleType(int, null)
+            handleIdentifier(k, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(x, and)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, l)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(l)
+            handleType(int, null)
+            handleIdentifier(l, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(x, &)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, m)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(m)
+            handleType(int, null)
+            handleIdentifier(m, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(and)
+                    handleNoArguments(and)
+                    handleSend(x, and)
+                    handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                    beginBinaryExpression(&)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(&)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, n)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(n)
+            handleType(int, null)
+            handleIdentifier(n, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(&)
+                    handleNoArguments(&)
+                    handleSend(x, &)
+                    beginBinaryExpression(&)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(&)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, o)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(o)
+            handleType(int, null)
+            handleIdentifier(o, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(and)
+              handleNoArguments(and)
+              handleSend(x, and)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+            beginBinaryExpression(&)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, p)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(p)
+            handleType(int, null)
+            handleIdentifier(p, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(&)
+              handleNoArguments(&)
+              handleSend(x, &)
+            endBinaryExpression(+)
+            beginBinaryExpression(&)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(&)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, q)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(q)
+            handleType(int, null)
+            handleIdentifier(q, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(and)
+                  handleNoArguments(and)
+                  handleSend(x, and)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, r)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(r)
+            handleType(int, null)
+            handleIdentifier(r, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(&)
+                  handleNoArguments(&)
+                  handleSend(x, &)
+                endBinaryExpression(+)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(&)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(s)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, s)
+            handleNoType(})
+            handleIdentifier(s, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(x, and)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(&)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(x, and)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(&)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(x, &)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(&)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(x, &)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(&)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, s, (, null, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(x, and)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(&)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(and)
+                handleNoArguments(and)
+                handleSend(x, and)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(&)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(and)
+                  handleNoArguments(and)
+                  handleSend(x, and)
+                  handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                  beginBinaryExpression(&)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(&)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(x, &)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(&)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(&)
+                handleNoArguments(&)
+                handleSend(x, &)
+                beginBinaryExpression(&)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(&)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(&)
+                  handleNoArguments(&)
+                  handleSend(x, &)
+                  beginBinaryExpression(&)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(&)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(not_currently_working)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, not_currently_working)
+            handleNoType(})
+            handleIdentifier(not_currently_working, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(x)
+              endMetadataStar(0)
+              handleIdentifier(x, typeReference)
+              handleNoTypeArguments(and)
+              handleType(x, null)
+              beginVariablesDeclaration(and, null, null)
+                handleIdentifier(and, localVariableDeclaration)
+                beginInitializedIdentifier(and)
+                  handleNoVariableInitializer(and)
+                endInitializedIdentifier(and)
+                handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], and, and)
+              endVariablesDeclaration(1, ;)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(&)
+              handleNoArguments(&)
+              handleSend(x, &)
+              beginBinaryExpression(&)
+                handleIdentifier(y, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(y, ;)
+              endBinaryExpression(&)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(3, {, })
+          endClassMethod(null, not_currently_working, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+    endClassDeclaration(abstract, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.intertwined.expect
new file mode 100644
index 0000000..9abec744
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.intertwined.expect
@@ -0,0 +1,2594 @@
+parseUnit(abstract)
+  skipErrorTokens(abstract)
+  listener: beginCompilationUnit(abstract)
+  syntheticPreviousToken(abstract)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(abstract)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+        parseTopLevelKeywordModifiers(abstract, class)
+      parseClassOrNamedMixinApplication(abstract, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(abstract)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Key, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(abstract, abstract, Key)
+        parseClass(Key, abstract, class, Key)
+          parseClassHeaderOpt(Key, abstract, class)
+            parseClassExtendsOpt(Key)
+              listener: handleNoType(Key)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(Key)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(Key)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(abstract, class, null)
+          parseClassOrMixinOrExtensionBody(Key, DeclarationKind.Class, Key)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Key)
+              parseMetadataStar({)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'SimpleType', get, a, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, a)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(a, methodDeclaration)
+                parseQualifiedRestOpt(a, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(a, a, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(a)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(a)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(a, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(and)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(and)
+                              listener: handleSend(hashCode, and)
+                        listener: handleEndingBinaryExpression(.)
+                        rewriter()
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                        reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                        rewriter()
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, b, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, b)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(b, methodDeclaration)
+                parseQualifiedRestOpt(b, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(b, b, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(b)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(b)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(b, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(&)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(&)
+                              listener: handleSend(hashCode, &)
+                        listener: handleEndingBinaryExpression(.)
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, c, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, c)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(c, methodDeclaration)
+                parseQualifiedRestOpt(c, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(c, c, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(c)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(c)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(c, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(and)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(and)
+                                  listener: handleSend(hashCode, and)
+                            listener: handleEndingBinaryExpression(.)
+                            rewriter()
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                            reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                            rewriter()
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, d, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, d)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(d, methodDeclaration)
+                parseQualifiedRestOpt(d, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(d, d, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(d)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(d)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(d, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(&)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(&)
+                                  listener: handleSend(hashCode, &)
+                            listener: handleEndingBinaryExpression(.)
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, e, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, e)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(e, methodDeclaration)
+                parseQualifiedRestOpt(e, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(e, e, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(e)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(e)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(e, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(and)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(and)
+                                listener: handleSend(hashCode, and)
+                          listener: handleEndingBinaryExpression(.)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                        rewriter()
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, f, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, f)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(f, methodDeclaration)
+                parseQualifiedRestOpt(f, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(f, f, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(f)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(f)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(f, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(&)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(&)
+                                listener: handleSend(hashCode, &)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseLiteralNull(&)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, g, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, g)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(g, methodDeclaration)
+                parseQualifiedRestOpt(g, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(g, g, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(g)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(g)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(g, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(and)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(and)
+                                    listener: handleSend(hashCode, and)
+                              listener: handleEndingBinaryExpression(.)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                            rewriter()
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, h, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, h)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(h, methodDeclaration)
+                parseQualifiedRestOpt(h, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(h, h, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(h)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(h)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(h, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(&)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(&)
+                                    listener: handleSend(hashCode, &)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseLiteralNull(&)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, i, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, i)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(i, methodDeclaration)
+                parseQualifiedRestOpt(i, methodDeclarationContinuation)
+                parseMethodTypeVar(i)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(i, i, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(i, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(and)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(and)
+                                listener: handleSend(x, and)
+                        rewriter()
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                  parseArgumentsOpt(y)
+                        reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                        rewriter()
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, j, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, j)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(j)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(j, methodDeclaration)
+                parseQualifiedRestOpt(j, methodDeclarationContinuation)
+                parseMethodTypeVar(j)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(j, j, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(j, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(&)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(&)
+                                listener: handleSend(x, &)
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, k, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, k)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(k)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(k, methodDeclaration)
+                parseQualifiedRestOpt(k, methodDeclarationContinuation)
+                parseMethodTypeVar(k)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(k, k, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(k, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(and)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(and)
+                                    listener: handleSend(x, and)
+                            rewriter()
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                      parseArgumentsOpt(y)
+                            reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                            rewriter()
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, l, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, l)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(l)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(l, methodDeclaration)
+                parseQualifiedRestOpt(l, methodDeclarationContinuation)
+                parseMethodTypeVar(l)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(l, l, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(l, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(&)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(&)
+                                    listener: handleSend(x, &)
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, m, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, m)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(m)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(m, methodDeclaration)
+                parseQualifiedRestOpt(m, methodDeclarationContinuation)
+                parseMethodTypeVar(m)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(m, m, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(m, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(and)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(and)
+                                          listener: handleSend(x, and)
+                                  rewriter()
+                                  parsePrecedenceExpression(&, 12, true)
+                                    parseUnaryExpression(&, true)
+                                      parsePrimary(&, expression)
+                                        parseSendOrFunctionLiteral(&, expression)
+                                          parseSend(&, expression)
+                                            ensureIdentifier(&, expression)
+                                            parseArgumentsOpt(y)
+                                  reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                    listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                                  rewriter()
+                                  listener: beginBinaryExpression(&)
+                                  parsePrecedenceExpression(&, 12, true)
+                                    parseUnaryExpression(&, true)
+                                      parsePrimary(&, expression)
+                                        parseSendOrFunctionLiteral(&, expression)
+                                          parseSend(&, expression)
+                                            ensureIdentifier(&, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(&)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, n, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, n)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(n)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(n, methodDeclaration)
+                parseQualifiedRestOpt(n, methodDeclarationContinuation)
+                parseMethodTypeVar(n)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(n, n, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(n, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(&)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(&)
+                                          listener: handleSend(x, &)
+                                  listener: beginBinaryExpression(&)
+                                  parsePrecedenceExpression(&, 12, true)
+                                    parseUnaryExpression(&, true)
+                                      parsePrimary(&, expression)
+                                        parseSendOrFunctionLiteral(&, expression)
+                                          parseSend(&, expression)
+                                            ensureIdentifier(&, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(&)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, o, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, o)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(o)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(o, methodDeclaration)
+                parseQualifiedRestOpt(o, methodDeclarationContinuation)
+                parseMethodTypeVar(o)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(o, o, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(o, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(and)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(and)
+                                  listener: handleSend(x, and)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                  parseArgumentsOpt(y)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                        rewriter()
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, p, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, p)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(p)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(p, methodDeclaration)
+                parseQualifiedRestOpt(p, methodDeclarationContinuation)
+                parseMethodTypeVar(p)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(p, p, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(p, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(&)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(&)
+                                  listener: handleSend(x, &)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(&)
+                        parsePrecedenceExpression(&, 12, true)
+                          parseUnaryExpression(&, true)
+                            parsePrimary(&, expression)
+                              parseSendOrFunctionLiteral(&, expression)
+                                parseSend(&, expression)
+                                  ensureIdentifier(&, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(&)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, q, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, q)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(q)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(q, methodDeclaration)
+                parseQualifiedRestOpt(q, methodDeclarationContinuation)
+                parseMethodTypeVar(q)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(q, q, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(q, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(and)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(and)
+                                      listener: handleSend(x, and)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                      parseArgumentsOpt(y)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                            rewriter()
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, r, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, r)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(r)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(r, methodDeclaration)
+                parseQualifiedRestOpt(r, methodDeclarationContinuation)
+                parseMethodTypeVar(r)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(r, r, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(r, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(&)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(&)
+                                      listener: handleSend(x, &)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(&)
+                            parsePrecedenceExpression(&, 12, true)
+                              parseUnaryExpression(&, true)
+                                parsePrimary(&, expression)
+                                  parseSendOrFunctionLiteral(&, expression)
+                                    parseSend(&, expression)
+                                      ensureIdentifier(&, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(&)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, s)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(s)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, s, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, s)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(s, methodDeclaration)
+                parseQualifiedRestOpt(s, methodDeclarationContinuation)
+                parseMethodTypeVar(s)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(s, s, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(s, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, s)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(and)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(and)
+                                                        listener: handleSend(x, and)
+                                                rewriter()
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                                                rewriter()
+                                                listener: beginBinaryExpression(&)
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(&)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(and)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(and)
+                                                        listener: handleSend(x, and)
+                                                rewriter()
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                                                rewriter()
+                                                listener: beginBinaryExpression(&)
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(&)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, s)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(&)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(&)
+                                                        listener: handleSend(x, &)
+                                                listener: beginBinaryExpression(&)
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(&)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(&)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(&)
+                                                        listener: handleSend(x, &)
+                                                listener: beginBinaryExpression(&)
+                                                parsePrecedenceExpression(&, 12, true)
+                                                  parseUnaryExpression(&, true)
+                                                    parsePrimary(&, expression)
+                                                      parseSendOrFunctionLiteral(&, expression)
+                                                        parseSend(&, expression)
+                                                          ensureIdentifier(&, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(&)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, s, (, null, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(and)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(and)
+                                      listener: handleSend(x, and)
+                              rewriter()
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                              rewriter()
+                              listener: beginBinaryExpression(&)
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(&)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(and)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(and)
+                                      listener: handleSend(x, and)
+                              rewriter()
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                              rewriter()
+                              listener: beginBinaryExpression(&)
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(&)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(and)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(and)
+                                                                    listener: handleSend(x, and)
+                                                            rewriter()
+                                                            parsePrecedenceExpression(&, 12, true)
+                                                              parseUnaryExpression(&, true)
+                                                                parsePrimary(&, expression)
+                                                                  parseSendOrFunctionLiteral(&, expression)
+                                                                    parseSend(&, expression)
+                                                                      ensureIdentifier(&, expression)
+                                                                      parseArgumentsOpt(y)
+                                                            reportRecoverableError(and, Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}])
+                                                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'and' is written as '&' instead of the written out word., Try replacing 'and' with '&'., {string: and, string2: &}], and, and)
+                                                            rewriter()
+                                                            listener: beginBinaryExpression(&)
+                                                            parsePrecedenceExpression(&, 12, true)
+                                                              parseUnaryExpression(&, true)
+                                                                parsePrimary(&, expression)
+                                                                  parseSendOrFunctionLiteral(&, expression)
+                                                                    parseSend(&, expression)
+                                                                      ensureIdentifier(&, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(&)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(&)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(&)
+                                      listener: handleSend(x, &)
+                              listener: beginBinaryExpression(&)
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(&)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(&)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(&)
+                                      listener: handleSend(x, &)
+                              listener: beginBinaryExpression(&)
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(&)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(&)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(&)
+                                                                    listener: handleSend(x, &)
+                                                            listener: beginBinaryExpression(&)
+                                                            parsePrecedenceExpression(&, 12, true)
+                                                              parseUnaryExpression(&, true)
+                                                                parsePrimary(&, expression)
+                                                                  parseSendOrFunctionLiteral(&, expression)
+                                                                    parseSend(&, expression)
+                                                                      ensureIdentifier(&, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(&)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, not_currently_working)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(not_currently_working)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, not_currently_working, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, not_currently_working)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(not_currently_working, methodDeclaration)
+                parseQualifiedRestOpt(not_currently_working, methodDeclarationContinuation)
+                parseMethodTypeVar(not_currently_working)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(not_currently_working, not_currently_working, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(not_currently_working, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, x)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(and)
+                        listener: beginMetadataStar(x)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(x, typeReference)
+                        listener: handleNoTypeArguments(and)
+                        listener: handleType(x, null)
+                        listener: beginVariablesDeclaration(and, null, null)
+                        parseVariablesDeclarationRest(x, true)
+                          parseOptionallyInitializedIdentifier(x)
+                            ensureIdentifier(x, localVariableDeclaration)
+                              listener: handleIdentifier(and, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(and)
+                            parseVariableInitializerOpt(and)
+                              listener: handleNoVariableInitializer(and)
+                            listener: endInitializedIdentifier(and)
+                          ensureSemicolon(and)
+                            reportRecoverableError(and, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                              listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], and, and)
+                            rewriter()
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, y)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(y)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, x)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(x)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(&)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(&)
+                                      listener: handleSend(x, &)
+                              listener: beginBinaryExpression(&)
+                              parsePrecedenceExpression(&, 12, true)
+                                parseUnaryExpression(&, true)
+                                  parsePrimary(&, expression)
+                                    parseSendOrFunctionLiteral(&, expression)
+                                      parseSend(&, expression)
+                                        ensureIdentifier(&, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(;)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(;)
+                                        listener: handleSend(y, ;)
+                              listener: endBinaryExpression(&)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(3, {, })
+                listener: endClassMethod(null, not_currently_working, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+          listener: endClassDeclaration(abstract, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(abstract)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.parser.expect
new file mode 100644
index 0000000..16ee9fd
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.parser.expect
@@ -0,0 +1,87 @@
+NOTICE: Stream was rewritten by parser!
+
+abstract class Key {
+int get a => runtimeType.hashCode & null.hashCode;
+int get b => runtimeType.hashCode & null.hashCode;
+int get c { return runtimeType.hashCode & null.hashCode; }
+int get d { return runtimeType.hashCode & null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode & null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode & null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode & null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode & null.hashCode + 3; }
+
+int i(int x, int y) => x & y;
+int j(int x, int y) => x & y;
+int k(int x, int y) { return x & y; }
+int l(int x, int y) { return x & y; }
+int m(int x, int y) { int z = x & y; return z; }
+int n(int x, int y) { int z = x & y; return z; }
+
+int o(int x, int y) => 1 + x & y + 3;
+int p(int x, int y) => 1 + x & y + 3;
+int q(int x, int y) { return 1 + x & y + 3; }
+int r(int x, int y) { return 1 + x & y + 3; }
+
+s(int x, int y) {
+s(x & y, x & y);
+s(x & y, x & y);
+}
+
+Key(int x, int y) : foo = x & y, bar = x & y {
+print("hello ${x & y}");
+}
+
+Key(int x, int y) : foo = x & y, bar = x & y {
+print("hello ${x & y}");
+}
+
+not_currently_working(int x, int y) {
+x and ;y;
+x & y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] &[ReplacementToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] &[ReplacementToken] y[StringToken],[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] &[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] &[ReplacementToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] &[ReplacementToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] &[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] and[StringToken] ;[SyntheticToken]y[StringToken];[SimpleToken]
+x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.scanner.expect
new file mode 100644
index 0000000..5b180a3
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_and.dart.scanner.expect
@@ -0,0 +1,85 @@
+abstract class Key {
+int get a => runtimeType.hashCode and null.hashCode;
+int get b => runtimeType.hashCode & null.hashCode;
+int get c { return runtimeType.hashCode and null.hashCode; }
+int get d { return runtimeType.hashCode & null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode and null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode & null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode and null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode & null.hashCode + 3; }
+
+int i(int x, int y) => x and y;
+int j(int x, int y) => x & y;
+int k(int x, int y) { return x and y; }
+int l(int x, int y) { return x & y; }
+int m(int x, int y) { int z = x and y; return z; }
+int n(int x, int y) { int z = x & y; return z; }
+
+int o(int x, int y) => 1 + x and y + 3;
+int p(int x, int y) => 1 + x & y + 3;
+int q(int x, int y) { return 1 + x and y + 3; }
+int r(int x, int y) { return 1 + x & y + 3; }
+
+s(int x, int y) {
+s(x and y, x and y);
+s(x & y, x & y);
+}
+
+Key(int x, int y) : foo = x and y, bar = x and y {
+print("hello ${x and y}");
+}
+
+Key(int x, int y) : foo = x & y, bar = x & y {
+print("hello ${x & y}");
+}
+
+not_currently_working(int x, int y) {
+x and y;
+x & y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] and[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] and[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] and[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] and[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] &[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] and[StringToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] and[StringToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] and[StringToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] and[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] and[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] and[StringToken] y[StringToken],[SimpleToken] x[StringToken] and[StringToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] &[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] and[StringToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] and[StringToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] and[StringToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] &[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] &[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] and[StringToken] y[StringToken];[SimpleToken]
+x[StringToken] &[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart
new file mode 100644
index 0000000..f5fbb1c
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart
@@ -0,0 +1,41 @@
+abstract class Key {
+  int get a => runtimeType.hashCode or null.hashCode;
+  int get b => runtimeType.hashCode | null.hashCode;
+  int get c { return runtimeType.hashCode or null.hashCode; }
+  int get d { return runtimeType.hashCode | null.hashCode; }
+
+  int get e => 1 + runtimeType.hashCode or null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode | null.hashCode + 3;
+  int get g { return 1 + runtimeType.hashCode or null.hashCode + 3; }
+  int get h { return 1 + runtimeType.hashCode | null.hashCode + 3; }
+
+  int i(int x, int y) => x or y;
+  int j(int x, int y) => x | y;
+  int k(int x, int y) { return x or y; }
+  int l(int x, int y) { return x | y; }
+  int m(int x, int y) { int z =  x or y; return z; }
+  int n(int x, int y) { int z = x | y; return z; }
+
+  int o(int x, int y) => 1 + x or y + 3;
+  int p(int x, int y) => 1 + x | y + 3;
+  int q(int x, int y) { return 1 + x or y + 3; }
+  int r(int x, int y) { return 1 + x | y + 3; }
+
+  s(int x, int y) {
+    s(x or y, x or y);
+    s(x | y, x | y);
+  }
+
+  Key(int x, int y) : foo = x or y, bar = x or y {
+    print("hello ${x or y}");
+  }
+
+  Key(int x, int y) : foo = x | y, bar = x | y {
+    print("hello ${x | y}");
+  }
+
+  not_currently_working(int x, int y) {
+    x or y;
+    x | y;
+  }
+}
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.expect
new file mode 100644
index 0000000..9080b89
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.expect
@@ -0,0 +1,1221 @@
+Problems reported:
+
+parser/error_recovery/issue_26810_or:2:37: Binary operator 'or' is written as '|' instead of the written out word.
+  int get a => runtimeType.hashCode or null.hashCode;
+                                    ^^
+
+parser/error_recovery/issue_26810_or:4:43: Binary operator 'or' is written as '|' instead of the written out word.
+  int get c { return runtimeType.hashCode or null.hashCode; }
+                                          ^^
+
+parser/error_recovery/issue_26810_or:7:41: Binary operator 'or' is written as '|' instead of the written out word.
+  int get e => 1 + runtimeType.hashCode or null.hashCode + 3;
+                                        ^^
+
+parser/error_recovery/issue_26810_or:9:47: Binary operator 'or' is written as '|' instead of the written out word.
+  int get g { return 1 + runtimeType.hashCode or null.hashCode + 3; }
+                                              ^^
+
+parser/error_recovery/issue_26810_or:12:28: Binary operator 'or' is written as '|' instead of the written out word.
+  int i(int x, int y) => x or y;
+                           ^^
+
+parser/error_recovery/issue_26810_or:14:34: Binary operator 'or' is written as '|' instead of the written out word.
+  int k(int x, int y) { return x or y; }
+                                 ^^
+
+parser/error_recovery/issue_26810_or:16:36: Binary operator 'or' is written as '|' instead of the written out word.
+  int m(int x, int y) { int z =  x or y; return z; }
+                                   ^^
+
+parser/error_recovery/issue_26810_or:19:32: Binary operator 'or' is written as '|' instead of the written out word.
+  int o(int x, int y) => 1 + x or y + 3;
+                               ^^
+
+parser/error_recovery/issue_26810_or:21:38: Binary operator 'or' is written as '|' instead of the written out word.
+  int q(int x, int y) { return 1 + x or y + 3; }
+                                     ^^
+
+parser/error_recovery/issue_26810_or:25:9: Binary operator 'or' is written as '|' instead of the written out word.
+    s(x or y, x or y);
+        ^^
+
+parser/error_recovery/issue_26810_or:25:17: Binary operator 'or' is written as '|' instead of the written out word.
+    s(x or y, x or y);
+                ^^
+
+parser/error_recovery/issue_26810_or:29:31: Binary operator 'or' is written as '|' instead of the written out word.
+  Key(int x, int y) : foo = x or y, bar = x or y {
+                              ^^
+
+parser/error_recovery/issue_26810_or:29:45: Binary operator 'or' is written as '|' instead of the written out word.
+  Key(int x, int y) : foo = x or y, bar = x or y {
+                                            ^^
+
+parser/error_recovery/issue_26810_or:30:22: Binary operator 'or' is written as '|' instead of the written out word.
+    print("hello ${x or y}");
+                     ^^
+
+parser/error_recovery/issue_26810_or:38:7: Expected ';' after this.
+    x or y;
+      ^^
+
+beginCompilationUnit(abstract)
+  beginMetadataStar(abstract)
+  endMetadataStar(0)
+  beginClassOrNamedMixinApplicationPrelude(abstract)
+    handleIdentifier(Key, classOrMixinDeclaration)
+    handleNoTypeVariables({)
+    beginClassDeclaration(abstract, abstract, Key)
+      handleNoType(Key)
+      handleClassExtends(null, 1)
+      handleClassNoWithClause()
+      handleClassOrMixinImplements(null, 0)
+      handleClassHeader(abstract, class, null)
+      beginClassOrMixinBody(DeclarationKind.Class, {)
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, a)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(a, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(or)
+            handleNoArguments(or)
+            handleSend(hashCode, or)
+            handleEndingBinaryExpression(.)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+            beginBinaryExpression(|)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, b)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(b, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(runtimeType, expression)
+            handleNoTypeArguments(.)
+            handleNoArguments(.)
+            handleSend(runtimeType, .)
+            handleIdentifier(hashCode, expressionContinuation)
+            handleNoTypeArguments(|)
+            handleNoArguments(|)
+            handleSend(hashCode, |)
+            handleEndingBinaryExpression(.)
+            beginBinaryExpression(|)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(hashCode, ;)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, c)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(c, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(hashCode, or)
+                handleEndingBinaryExpression(.)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, d)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(d, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(runtimeType, expression)
+                handleNoTypeArguments(.)
+                handleNoArguments(.)
+                handleSend(runtimeType, .)
+                handleIdentifier(hashCode, expressionContinuation)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(hashCode, |)
+                handleEndingBinaryExpression(.)
+                beginBinaryExpression(|)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(hashCode, ;)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, e)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(e, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(or)
+              handleNoArguments(or)
+              handleSend(hashCode, or)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+            beginBinaryExpression(|)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, f)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(f, methodDeclaration)
+            handleNoTypeVariables(=>)
+            handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(runtimeType, expression)
+              handleNoTypeArguments(.)
+              handleNoArguments(.)
+              handleSend(runtimeType, .)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(|)
+              handleNoArguments(|)
+              handleSend(hashCode, |)
+              handleEndingBinaryExpression(.)
+            endBinaryExpression(+)
+            beginBinaryExpression(|)
+              handleLiteralNull(null)
+              handleIdentifier(hashCode, expressionContinuation)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(hashCode, +)
+              handleEndingBinaryExpression(.)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(get, int, =>, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, g)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(g, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(or)
+                  handleNoArguments(or)
+                  handleSend(hashCode, or)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, get, h)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(get)
+            handleType(int, null)
+            handleIdentifier(h, methodDeclaration)
+            handleNoTypeVariables({)
+            handleNoFormalParameters({, MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(runtimeType, expression)
+                  handleNoTypeArguments(.)
+                  handleNoArguments(.)
+                  handleSend(runtimeType, .)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(|)
+                  handleNoArguments(|)
+                  handleSend(hashCode, |)
+                  handleEndingBinaryExpression(.)
+                endBinaryExpression(+)
+                beginBinaryExpression(|)
+                  handleLiteralNull(null)
+                  handleIdentifier(hashCode, expressionContinuation)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(hashCode, +)
+                  handleEndingBinaryExpression(.)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(get, int, {, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, i)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(i)
+            handleType(int, null)
+            handleIdentifier(i, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(or)
+            handleNoArguments(or)
+            handleSend(x, or)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+            beginBinaryExpression(|)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, j)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(j)
+            handleType(int, null)
+            handleIdentifier(j, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleIdentifier(x, expression)
+            handleNoTypeArguments(|)
+            handleNoArguments(|)
+            handleSend(x, |)
+            beginBinaryExpression(|)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, k)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(k)
+            handleType(int, null)
+            handleIdentifier(k, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(x, or)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, l)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(l)
+            handleType(int, null)
+            handleIdentifier(l, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(x, |)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(;)
+                  handleNoArguments(;)
+                  handleSend(y, ;)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, m)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(m)
+            handleType(int, null)
+            handleIdentifier(m, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(or)
+                    handleNoArguments(or)
+                    handleSend(x, or)
+                    handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                    beginBinaryExpression(|)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(|)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, n)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(n)
+            handleType(int, null)
+            handleIdentifier(n, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              handleIdentifier(int, typeReference)
+              handleNoTypeArguments(z)
+              handleType(int, null)
+              beginVariablesDeclaration(z, null, null)
+                handleIdentifier(z, localVariableDeclaration)
+                beginInitializedIdentifier(z)
+                  beginVariableInitializer(=)
+                    handleIdentifier(x, expression)
+                    handleNoTypeArguments(|)
+                    handleNoArguments(|)
+                    handleSend(x, |)
+                    beginBinaryExpression(|)
+                      handleIdentifier(y, expression)
+                      handleNoTypeArguments(;)
+                      handleNoArguments(;)
+                      handleSend(y, ;)
+                    endBinaryExpression(|)
+                  endVariableInitializer(=)
+                endInitializedIdentifier(z)
+              endVariablesDeclaration(1, ;)
+              beginReturnStatement(return)
+                handleIdentifier(z, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(z, ;)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, o)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(o)
+            handleType(int, null)
+            handleIdentifier(o, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(or)
+              handleNoArguments(or)
+              handleSend(x, or)
+            endBinaryExpression(+)
+            handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+            beginBinaryExpression(|)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, p)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(p)
+            handleType(int, null)
+            handleIdentifier(p, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            handleLiteralInt(1)
+            beginBinaryExpression(+)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(|)
+              handleNoArguments(|)
+              handleSend(x, |)
+            endBinaryExpression(+)
+            beginBinaryExpression(|)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(+)
+              handleNoArguments(+)
+              handleSend(y, +)
+              beginBinaryExpression(+)
+                handleLiteralInt(3)
+              endBinaryExpression(+)
+            endBinaryExpression(|)
+            handleExpressionFunctionBody(=>, ;)
+          endClassMethod(null, int, (, null, ;)
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, q)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(q)
+            handleType(int, null)
+            handleIdentifier(q, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(or)
+                  handleNoArguments(or)
+                  handleSend(x, or)
+                endBinaryExpression(+)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(int)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, r)
+            handleIdentifier(int, typeReference)
+            handleNoTypeArguments(r)
+            handleType(int, null)
+            handleIdentifier(r, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginReturnStatement(return)
+                handleLiteralInt(1)
+                beginBinaryExpression(+)
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(|)
+                  handleNoArguments(|)
+                  handleSend(x, |)
+                endBinaryExpression(+)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(+)
+                  handleNoArguments(+)
+                  handleSend(y, +)
+                  beginBinaryExpression(+)
+                    handleLiteralInt(3)
+                  endBinaryExpression(+)
+                endBinaryExpression(|)
+              endReturnStatement(true, return, ;)
+            endBlockFunctionBody(1, {, })
+          endClassMethod(null, int, (, null, })
+        endMember()
+        beginMetadataStar(s)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, s)
+            handleNoType(})
+            handleIdentifier(s, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(x, or)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(|)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(x, or)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(|)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(s, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(x, |)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(|)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(x, |)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments())
+                  handleNoArguments())
+                  handleSend(y, ))
+                endBinaryExpression(|)
+              endArguments(2, (, ))
+              handleSend(s, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(2, {, })
+          endClassMethod(null, s, (, null, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(x, or)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(|)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(or)
+                handleNoArguments(or)
+                handleSend(x, or)
+                handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(|)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(or)
+                  handleNoArguments(or)
+                  handleSend(x, or)
+                  handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                  beginBinaryExpression(|)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(|)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(Key)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, Key)
+            handleNoType(})
+            handleIdentifier(Key, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            beginInitializers(:)
+              beginInitializer(foo)
+                handleIdentifier(foo, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(foo, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(x, |)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments(,)
+                  handleNoArguments(,)
+                  handleSend(y, ,)
+                endBinaryExpression(|)
+                handleAssignmentExpression(=)
+              endInitializer(,)
+              beginInitializer(bar)
+                handleIdentifier(bar, expression)
+                handleNoTypeArguments(=)
+                handleNoArguments(=)
+                handleSend(bar, =)
+                handleIdentifier(x, expression)
+                handleNoTypeArguments(|)
+                handleNoArguments(|)
+                handleSend(x, |)
+                beginBinaryExpression(|)
+                  handleIdentifier(y, expression)
+                  handleNoTypeArguments({)
+                  handleNoArguments({)
+                  handleSend(y, {)
+                endBinaryExpression(|)
+                handleAssignmentExpression(=)
+              endInitializer({)
+            endInitializers(2, :, {)
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              handleIdentifier(print, expression)
+              handleNoTypeArguments(()
+              beginArguments(()
+                beginLiteralString("hello )
+                  handleIdentifier(x, expression)
+                  handleNoTypeArguments(|)
+                  handleNoArguments(|)
+                  handleSend(x, |)
+                  beginBinaryExpression(|)
+                    handleIdentifier(y, expression)
+                    handleNoTypeArguments(})
+                    handleNoArguments(})
+                    handleSend(y, })
+                  endBinaryExpression(|)
+                  handleInterpolationExpression(${, })
+                  handleStringPart(")
+                endLiteralString(1, ))
+              endArguments(1, (, ))
+              handleSend(print, ;)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(1, {, })
+          endClassConstructor(null, Key, (, :, })
+        endMember()
+        beginMetadataStar(not_currently_working)
+        endMetadataStar(0)
+        beginMember()
+          beginMethod(null, null, null, null, null, not_currently_working)
+            handleNoType(})
+            handleIdentifier(not_currently_working, methodDeclaration)
+            handleNoTypeVariables(()
+            beginFormalParameters((, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(x)
+                handleType(int, null)
+                handleIdentifier(x, formalParameterDeclaration)
+                handleFormalParameterWithoutValue(,)
+              endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+              beginMetadataStar(int)
+              endMetadataStar(0)
+              beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                handleIdentifier(int, typeReference)
+                handleNoTypeArguments(y)
+                handleType(int, null)
+                handleIdentifier(y, formalParameterDeclaration)
+                handleFormalParameterWithoutValue())
+              endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+            endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+            handleNoInitializers()
+            handleAsyncModifier(null, null)
+            beginBlockFunctionBody({)
+              beginMetadataStar(x)
+              endMetadataStar(0)
+              handleIdentifier(x, typeReference)
+              handleNoTypeArguments(or)
+              handleType(x, null)
+              beginVariablesDeclaration(or, null, null)
+                handleIdentifier(or, localVariableDeclaration)
+                beginInitializedIdentifier(or)
+                  handleNoVariableInitializer(or)
+                endInitializedIdentifier(or)
+                handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+              endVariablesDeclaration(1, ;)
+              handleIdentifier(y, expression)
+              handleNoTypeArguments(;)
+              handleNoArguments(;)
+              handleSend(y, ;)
+              handleExpressionStatement(;)
+              handleIdentifier(x, expression)
+              handleNoTypeArguments(|)
+              handleNoArguments(|)
+              handleSend(x, |)
+              beginBinaryExpression(|)
+                handleIdentifier(y, expression)
+                handleNoTypeArguments(;)
+                handleNoArguments(;)
+                handleSend(y, ;)
+              endBinaryExpression(|)
+              handleExpressionStatement(;)
+            endBlockFunctionBody(3, {, })
+          endClassMethod(null, not_currently_working, (, null, })
+        endMember()
+      endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+    endClassDeclaration(abstract, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.intertwined.expect
new file mode 100644
index 0000000..60507f0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.intertwined.expect
@@ -0,0 +1,2594 @@
+parseUnit(abstract)
+  skipErrorTokens(abstract)
+  listener: beginCompilationUnit(abstract)
+  syntheticPreviousToken(abstract)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(abstract)
+      listener: endMetadataStar(0)
+    parseTopLevelKeywordDeclaration(, class, Instance of 'DirectiveContext')
+      parseClassDeclarationModifiers(, class)
+        parseTopLevelKeywordModifiers(abstract, class)
+      parseClassOrNamedMixinApplication(abstract, class)
+        listener: beginClassOrNamedMixinApplicationPrelude(abstract)
+        ensureIdentifier(class, classOrMixinDeclaration)
+          listener: handleIdentifier(Key, classOrMixinDeclaration)
+        listener: handleNoTypeVariables({)
+        listener: beginClassDeclaration(abstract, abstract, Key)
+        parseClass(Key, abstract, class, Key)
+          parseClassHeaderOpt(Key, abstract, class)
+            parseClassExtendsOpt(Key)
+              listener: handleNoType(Key)
+              listener: handleClassExtends(null, 1)
+            parseWithClauseOpt(Key)
+              listener: handleClassNoWithClause()
+            parseClassOrMixinImplementsOpt(Key)
+              listener: handleClassOrMixinImplements(null, 0)
+            listener: handleClassHeader(abstract, class, null)
+          parseClassOrMixinOrExtensionBody(Key, DeclarationKind.Class, Key)
+            listener: beginClassOrMixinBody(DeclarationKind.Class, {)
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl({, DeclarationKind.Class, Key)
+              parseMetadataStar({)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod({, null, null, null, null, null, null, {, Instance of 'SimpleType', get, a, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, a)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(a, methodDeclaration)
+                parseQualifiedRestOpt(a, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(a, a, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(a)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(a)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(a, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(or)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(or)
+                              listener: handleSend(hashCode, or)
+                        listener: handleEndingBinaryExpression(.)
+                        rewriter()
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                        reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                        rewriter()
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, b, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, b)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(b, methodDeclaration)
+                parseQualifiedRestOpt(b, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(b, b, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(b)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(b)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(b, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(runtimeType, expression)
+                                listener: handleNoTypeArguments(.)
+                                parseArgumentsOpt(runtimeType)
+                                  listener: handleNoArguments(.)
+                                listener: handleSend(runtimeType, .)
+                        parsePrimary(., expressionContinuation)
+                          parseSendOrFunctionLiteral(., expressionContinuation)
+                            parseSend(., expressionContinuation)
+                              ensureIdentifier(., expressionContinuation)
+                                listener: handleIdentifier(hashCode, expressionContinuation)
+                              listener: handleNoTypeArguments(|)
+                              parseArgumentsOpt(hashCode)
+                                listener: handleNoArguments(|)
+                              listener: handleSend(hashCode, |)
+                        listener: handleEndingBinaryExpression(.)
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(;)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(;)
+                                listener: handleSend(hashCode, ;)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(hashCode)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, c, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, c)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(c, methodDeclaration)
+                parseQualifiedRestOpt(c, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(c, c, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(c)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(c)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(c, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(or)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(or)
+                                  listener: handleSend(hashCode, or)
+                            listener: handleEndingBinaryExpression(.)
+                            rewriter()
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                            reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                            rewriter()
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, d, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, d)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(d, methodDeclaration)
+                parseQualifiedRestOpt(d, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(d, d, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(d)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(d)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(d, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(runtimeType, expression)
+                                    listener: handleNoTypeArguments(.)
+                                    parseArgumentsOpt(runtimeType)
+                                      listener: handleNoArguments(.)
+                                    listener: handleSend(runtimeType, .)
+                            parsePrimary(., expressionContinuation)
+                              parseSendOrFunctionLiteral(., expressionContinuation)
+                                parseSend(., expressionContinuation)
+                                  ensureIdentifier(., expressionContinuation)
+                                    listener: handleIdentifier(hashCode, expressionContinuation)
+                                  listener: handleNoTypeArguments(|)
+                                  parseArgumentsOpt(hashCode)
+                                    listener: handleNoArguments(|)
+                                  listener: handleSend(hashCode, |)
+                            listener: handleEndingBinaryExpression(.)
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(hashCode, ;)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(hashCode)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, e, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, e)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(e, methodDeclaration)
+                parseQualifiedRestOpt(e, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(e, e, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(e)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(e)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(e, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(or)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(or)
+                                listener: handleSend(hashCode, or)
+                          listener: handleEndingBinaryExpression(.)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                parseArgumentsOpt(hashCode)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                        rewriter()
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, f, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, f)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(f, methodDeclaration)
+                parseQualifiedRestOpt(f, methodDeclarationContinuation)
+                listener: handleNoTypeVariables(=>)
+                parseGetterOrFormalParameters(f, f, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
+                parseInitializersOpt(f)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(f)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(f, false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(runtimeType, expression)
+                                  listener: handleNoTypeArguments(.)
+                                  parseArgumentsOpt(runtimeType)
+                                    listener: handleNoArguments(.)
+                                  listener: handleSend(runtimeType, .)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(|)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(|)
+                                listener: handleSend(hashCode, |)
+                          listener: handleEndingBinaryExpression(.)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseLiteralNull(|)
+                                listener: handleLiteralNull(null)
+                          parsePrimary(., expressionContinuation)
+                            parseSendOrFunctionLiteral(., expressionContinuation)
+                              parseSend(., expressionContinuation)
+                                ensureIdentifier(., expressionContinuation)
+                                  listener: handleIdentifier(hashCode, expressionContinuation)
+                                listener: handleNoTypeArguments(+)
+                                parseArgumentsOpt(hashCode)
+                                  listener: handleNoArguments(+)
+                                listener: handleSend(hashCode, +)
+                          listener: handleEndingBinaryExpression(.)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(get, int, =>, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', get, g, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, g)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(g, methodDeclaration)
+                parseQualifiedRestOpt(g, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(g, g, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(g)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(g)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(g, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(or)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(or)
+                                    listener: handleSend(hashCode, or)
+                              listener: handleEndingBinaryExpression(.)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                    parseArgumentsOpt(hashCode)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                            rewriter()
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', get, h, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, get, h)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(get)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(get, methodDeclaration, false)
+                  listener: handleIdentifier(h, methodDeclaration)
+                parseQualifiedRestOpt(h, methodDeclarationContinuation)
+                listener: handleNoTypeVariables({)
+                parseGetterOrFormalParameters(h, h, true, MemberKind.NonStaticMethod)
+                  listener: handleNoFormalParameters({, MemberKind.NonStaticMethod)
+                parseInitializersOpt(h)
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt(h)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                inPlainSync()
+                parseFunctionBody(h, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(runtimeType, expression)
+                                      listener: handleNoTypeArguments(.)
+                                      parseArgumentsOpt(runtimeType)
+                                        listener: handleNoArguments(.)
+                                      listener: handleSend(runtimeType, .)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(|)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(|)
+                                    listener: handleSend(hashCode, |)
+                              listener: handleEndingBinaryExpression(.)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseLiteralNull(|)
+                                    listener: handleLiteralNull(null)
+                              parsePrimary(., expressionContinuation)
+                                parseSendOrFunctionLiteral(., expressionContinuation)
+                                  parseSend(., expressionContinuation)
+                                    ensureIdentifier(., expressionContinuation)
+                                      listener: handleIdentifier(hashCode, expressionContinuation)
+                                    listener: handleNoTypeArguments(+)
+                                    parseArgumentsOpt(hashCode)
+                                      listener: handleNoArguments(+)
+                                    listener: handleSend(hashCode, +)
+                              listener: handleEndingBinaryExpression(.)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(get, int, {, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, i, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, i)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(i)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(i, methodDeclaration)
+                parseQualifiedRestOpt(i, methodDeclarationContinuation)
+                parseMethodTypeVar(i)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(i, i, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(i, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(or)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(or)
+                                listener: handleSend(x, or)
+                        rewriter()
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                  parseArgumentsOpt(y)
+                        reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                        rewriter()
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, j, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, j)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(j)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(j, methodDeclaration)
+                parseQualifiedRestOpt(j, methodDeclarationContinuation)
+                parseMethodTypeVar(j)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(j, j, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(j, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseSendOrFunctionLiteral(=>, expression)
+                              parseSend(=>, expression)
+                                ensureIdentifier(=>, expression)
+                                  listener: handleIdentifier(x, expression)
+                                listener: handleNoTypeArguments(|)
+                                parseArgumentsOpt(x)
+                                  listener: handleNoArguments(|)
+                                listener: handleSend(x, |)
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(;)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(;)
+                                  listener: handleSend(y, ;)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(y)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, k, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, k)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(k)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(k, methodDeclaration)
+                parseQualifiedRestOpt(k, methodDeclarationContinuation)
+                parseMethodTypeVar(k)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(k, k, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(k, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(or)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(or)
+                                    listener: handleSend(x, or)
+                            rewriter()
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                      parseArgumentsOpt(y)
+                            reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                            rewriter()
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, l, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, l)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(l)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(l, methodDeclaration)
+                parseQualifiedRestOpt(l, methodDeclarationContinuation)
+                parseMethodTypeVar(l)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(l, l, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(l, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(x, expression)
+                                    listener: handleNoTypeArguments(|)
+                                    parseArgumentsOpt(x)
+                                      listener: handleNoArguments(|)
+                                    listener: handleSend(x, |)
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(y)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, m, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, m)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(m)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(m, methodDeclaration)
+                parseQualifiedRestOpt(m, methodDeclarationContinuation)
+                parseMethodTypeVar(m)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(m, m, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(m, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(or)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(or)
+                                          listener: handleSend(x, or)
+                                  rewriter()
+                                  parsePrecedenceExpression(|, 10, true)
+                                    parseUnaryExpression(|, true)
+                                      parsePrimary(|, expression)
+                                        parseSendOrFunctionLiteral(|, expression)
+                                          parseSend(|, expression)
+                                            ensureIdentifier(|, expression)
+                                            parseArgumentsOpt(y)
+                                  reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                    listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                                  rewriter()
+                                  listener: beginBinaryExpression(|)
+                                  parsePrecedenceExpression(|, 10, true)
+                                    parseUnaryExpression(|, true)
+                                      parsePrimary(|, expression)
+                                        parseSendOrFunctionLiteral(|, expression)
+                                          parseSend(|, expression)
+                                            ensureIdentifier(|, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(|)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, n, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, n)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(n)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(n, methodDeclaration)
+                parseQualifiedRestOpt(n, methodDeclarationContinuation)
+                parseMethodTypeVar(n)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(n, n, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(n, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, int)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(z)
+                        listener: beginMetadataStar(int)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(z)
+                        listener: handleType(int, null)
+                        listener: beginVariablesDeclaration(z, null, null)
+                        parseVariablesDeclarationRest(int, true)
+                          parseOptionallyInitializedIdentifier(int)
+                            ensureIdentifier(int, localVariableDeclaration)
+                              listener: handleIdentifier(z, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(z)
+                            parseVariableInitializerOpt(z)
+                              listener: beginVariableInitializer(=)
+                              parseExpression(=)
+                                parsePrecedenceExpression(=, 1, true)
+                                  parseUnaryExpression(=, true)
+                                    parsePrimary(=, expression)
+                                      parseSendOrFunctionLiteral(=, expression)
+                                        parseSend(=, expression)
+                                          ensureIdentifier(=, expression)
+                                            listener: handleIdentifier(x, expression)
+                                          listener: handleNoTypeArguments(|)
+                                          parseArgumentsOpt(x)
+                                            listener: handleNoArguments(|)
+                                          listener: handleSend(x, |)
+                                  listener: beginBinaryExpression(|)
+                                  parsePrecedenceExpression(|, 10, true)
+                                    parseUnaryExpression(|, true)
+                                      parsePrimary(|, expression)
+                                        parseSendOrFunctionLiteral(|, expression)
+                                          parseSend(|, expression)
+                                            ensureIdentifier(|, expression)
+                                              listener: handleIdentifier(y, expression)
+                                            listener: handleNoTypeArguments(;)
+                                            parseArgumentsOpt(y)
+                                              listener: handleNoArguments(;)
+                                            listener: handleSend(y, ;)
+                                  listener: endBinaryExpression(|)
+                              listener: endVariableInitializer(=)
+                            listener: endInitializedIdentifier(z)
+                          ensureSemicolon(y)
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, return)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseReturnStatement(;)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseSendOrFunctionLiteral(return, expression)
+                                  parseSend(return, expression)
+                                    ensureIdentifier(return, expression)
+                                      listener: handleIdentifier(z, expression)
+                                    listener: handleNoTypeArguments(;)
+                                    parseArgumentsOpt(z)
+                                      listener: handleNoArguments(;)
+                                    listener: handleSend(z, ;)
+                        ensureSemicolon(z)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, o, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, o)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(o)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(o, methodDeclaration)
+                parseQualifiedRestOpt(o, methodDeclarationContinuation)
+                parseMethodTypeVar(o)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(o, o, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(o, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(or)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(or)
+                                  listener: handleSend(x, or)
+                          rewriter()
+                        listener: endBinaryExpression(+)
+                        rewriter()
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                  parseArgumentsOpt(y)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                        reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                          listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                        rewriter()
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, p, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, p)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(p)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(p, methodDeclaration)
+                parseQualifiedRestOpt(p, methodDeclarationContinuation)
+                parseMethodTypeVar(p)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(p, p, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(p, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  parseExpressionFunctionBody(=>, false)
+                    parseExpression(=>)
+                      parsePrecedenceExpression(=>, 1, true)
+                        parseUnaryExpression(=>, true)
+                          parsePrimary(=>, expression)
+                            parseLiteralInt(=>)
+                              listener: handleLiteralInt(1)
+                        listener: beginBinaryExpression(+)
+                        parsePrecedenceExpression(+, 14, true)
+                          parseUnaryExpression(+, true)
+                            parsePrimary(+, expression)
+                              parseSendOrFunctionLiteral(+, expression)
+                                parseSend(+, expression)
+                                  ensureIdentifier(+, expression)
+                                    listener: handleIdentifier(x, expression)
+                                  listener: handleNoTypeArguments(|)
+                                  parseArgumentsOpt(x)
+                                    listener: handleNoArguments(|)
+                                  listener: handleSend(x, |)
+                        listener: endBinaryExpression(+)
+                        listener: beginBinaryExpression(|)
+                        parsePrecedenceExpression(|, 10, true)
+                          parseUnaryExpression(|, true)
+                            parsePrimary(|, expression)
+                              parseSendOrFunctionLiteral(|, expression)
+                                parseSend(|, expression)
+                                  ensureIdentifier(|, expression)
+                                    listener: handleIdentifier(y, expression)
+                                  listener: handleNoTypeArguments(+)
+                                  parseArgumentsOpt(y)
+                                    listener: handleNoArguments(+)
+                                  listener: handleSend(y, +)
+                          listener: beginBinaryExpression(+)
+                          parsePrecedenceExpression(+, 14, true)
+                            parseUnaryExpression(+, true)
+                              parsePrimary(+, expression)
+                                parseLiteralInt(+)
+                                  listener: handleLiteralInt(3)
+                          listener: endBinaryExpression(+)
+                        listener: endBinaryExpression(|)
+                    ensureSemicolon(3)
+                    listener: handleExpressionFunctionBody(=>, ;)
+                    inGenerator()
+                listener: endClassMethod(null, int, (, null, ;)
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(;, DeclarationKind.Class, Key)
+              parseMetadataStar(;)
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(;, null, null, null, null, null, null, ;, Instance of 'SimpleType', null, q, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, q)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(q)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(q, methodDeclaration)
+                parseQualifiedRestOpt(q, methodDeclarationContinuation)
+                parseMethodTypeVar(q)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(q, q, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(q, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(or)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(or)
+                                      listener: handleSend(x, or)
+                              rewriter()
+                            listener: endBinaryExpression(+)
+                            rewriter()
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                      parseArgumentsOpt(y)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                            reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                            rewriter()
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, int)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(int)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'SimpleType', null, r, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, r)
+                listener: handleIdentifier(int, typeReference)
+                listener: handleNoTypeArguments(r)
+                listener: handleType(int, null)
+                ensureIdentifierPotentiallyRecovered(int, methodDeclaration, false)
+                  listener: handleIdentifier(r, methodDeclaration)
+                parseQualifiedRestOpt(r, methodDeclarationContinuation)
+                parseMethodTypeVar(r)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(r, r, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(r, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, return)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseReturnStatement({)
+                        listener: beginReturnStatement(return)
+                        parseExpression(return)
+                          parsePrecedenceExpression(return, 1, true)
+                            parseUnaryExpression(return, true)
+                              parsePrimary(return, expression)
+                                parseLiteralInt(return)
+                                  listener: handleLiteralInt(1)
+                            listener: beginBinaryExpression(+)
+                            parsePrecedenceExpression(+, 14, true)
+                              parseUnaryExpression(+, true)
+                                parsePrimary(+, expression)
+                                  parseSendOrFunctionLiteral(+, expression)
+                                    parseSend(+, expression)
+                                      ensureIdentifier(+, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(|)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(|)
+                                      listener: handleSend(x, |)
+                            listener: endBinaryExpression(+)
+                            listener: beginBinaryExpression(|)
+                            parsePrecedenceExpression(|, 10, true)
+                              parseUnaryExpression(|, true)
+                                parsePrimary(|, expression)
+                                  parseSendOrFunctionLiteral(|, expression)
+                                    parseSend(|, expression)
+                                      ensureIdentifier(|, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(+)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(+)
+                                      listener: handleSend(y, +)
+                              listener: beginBinaryExpression(+)
+                              parsePrecedenceExpression(+, 14, true)
+                                parseUnaryExpression(+, true)
+                                  parsePrimary(+, expression)
+                                    parseLiteralInt(+)
+                                      listener: handleLiteralInt(3)
+                              listener: endBinaryExpression(+)
+                            listener: endBinaryExpression(|)
+                        ensureSemicolon(3)
+                        listener: endReturnStatement(true, return, ;)
+                        inGenerator()
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassMethod(null, int, (, null, })
+              listener: endMember()
+            notEofOrValue(}, s)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(s)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, s, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, s)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(s, methodDeclaration)
+                parseQualifiedRestOpt(s, methodDeclarationContinuation)
+                parseMethodTypeVar(s)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(s, s, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(s, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, s)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(or)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(or)
+                                                        listener: handleSend(x, or)
+                                                rewriter()
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                                                rewriter()
+                                                listener: beginBinaryExpression(|)
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(|)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(or)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(or)
+                                                        listener: handleSend(x, or)
+                                                rewriter()
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                          parseArgumentsOpt(y)
+                                                reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                                  listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                                                rewriter()
+                                                listener: beginBinaryExpression(|)
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(|)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, s)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(s)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(s, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(s)
+                                        parseArguments(s)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseSendOrFunctionLiteral((, expression)
+                                                      parseSend((, expression)
+                                                        ensureIdentifier((, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(|)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(|)
+                                                        listener: handleSend(x, |)
+                                                listener: beginBinaryExpression(|)
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments(,)
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments(,)
+                                                          listener: handleSend(y, ,)
+                                                listener: endBinaryExpression(|)
+                                            parseExpression(,)
+                                              parsePrecedenceExpression(,, 1, true)
+                                                parseUnaryExpression(,, true)
+                                                  parsePrimary(,, expression)
+                                                    parseSendOrFunctionLiteral(,, expression)
+                                                      parseSend(,, expression)
+                                                        ensureIdentifier(,, expression)
+                                                          listener: handleIdentifier(x, expression)
+                                                        listener: handleNoTypeArguments(|)
+                                                        parseArgumentsOpt(x)
+                                                          listener: handleNoArguments(|)
+                                                        listener: handleSend(x, |)
+                                                listener: beginBinaryExpression(|)
+                                                parsePrecedenceExpression(|, 10, true)
+                                                  parseUnaryExpression(|, true)
+                                                    parsePrimary(|, expression)
+                                                      parseSendOrFunctionLiteral(|, expression)
+                                                        parseSend(|, expression)
+                                                          ensureIdentifier(|, expression)
+                                                            listener: handleIdentifier(y, expression)
+                                                          listener: handleNoTypeArguments())
+                                                          parseArgumentsOpt(y)
+                                                            listener: handleNoArguments())
+                                                          listener: handleSend(y, ))
+                                                listener: endBinaryExpression(|)
+                                            listener: endArguments(2, (, ))
+                                      listener: handleSend(s, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(2, {, })
+                listener: endClassMethod(null, s, (, null, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(or)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(or)
+                                      listener: handleSend(x, or)
+                              rewriter()
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                              rewriter()
+                              listener: beginBinaryExpression(|)
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(|)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(or)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(or)
+                                      listener: handleSend(x, or)
+                              rewriter()
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                        parseArgumentsOpt(y)
+                              reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                              rewriter()
+                              listener: beginBinaryExpression(|)
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(|)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(or)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(or)
+                                                                    listener: handleSend(x, or)
+                                                            rewriter()
+                                                            parsePrecedenceExpression(|, 10, true)
+                                                              parseUnaryExpression(|, true)
+                                                                parsePrimary(|, expression)
+                                                                  parseSendOrFunctionLiteral(|, expression)
+                                                                    parseSend(|, expression)
+                                                                      ensureIdentifier(|, expression)
+                                                                      parseArgumentsOpt(y)
+                                                            reportRecoverableError(or, Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}])
+                                                              listener: handleRecoverableError(Message[BinaryOperatorWrittenOut, Binary operator 'or' is written as '|' instead of the written out word., Try replacing 'or' with '|'., {string: or, string2: |}], or, or)
+                                                            rewriter()
+                                                            listener: beginBinaryExpression(|)
+                                                            parsePrecedenceExpression(|, 10, true)
+                                                              parseUnaryExpression(|, true)
+                                                                parsePrimary(|, expression)
+                                                                  parseSendOrFunctionLiteral(|, expression)
+                                                                    parseSend(|, expression)
+                                                                      ensureIdentifier(|, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(|)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, Key)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(Key)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, Key, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, Key)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(Key, methodDeclaration)
+                parseQualifiedRestOpt(Key, methodDeclarationContinuation)
+                parseMethodTypeVar(Key)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(Key, Key, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(Key, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  parseInitializers(:)
+                    listener: beginInitializers(:)
+                    parseInitializer(:)
+                      listener: beginInitializer(foo)
+                      parseInitializerExpressionRest(:)
+                        parseExpression(:)
+                          parsePrecedenceExpression(:, 1, true)
+                            parseUnaryExpression(:, true)
+                              parsePrimary(:, expression)
+                                parseSendOrFunctionLiteral(:, expression)
+                                  parseSend(:, expression)
+                                    ensureIdentifier(:, expression)
+                                      listener: handleIdentifier(foo, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(foo)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(foo, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(|)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(|)
+                                      listener: handleSend(x, |)
+                              listener: beginBinaryExpression(|)
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(,)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(,)
+                                        listener: handleSend(y, ,)
+                              listener: endBinaryExpression(|)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer(,)
+                    parseInitializer(,)
+                      listener: beginInitializer(bar)
+                      parseInitializerExpressionRest(,)
+                        parseExpression(,)
+                          parsePrecedenceExpression(,, 1, true)
+                            parseUnaryExpression(,, true)
+                              parsePrimary(,, expression)
+                                parseSendOrFunctionLiteral(,, expression)
+                                  parseSend(,, expression)
+                                    ensureIdentifier(,, expression)
+                                      listener: handleIdentifier(bar, expression)
+                                    listener: handleNoTypeArguments(=)
+                                    parseArgumentsOpt(bar)
+                                      listener: handleNoArguments(=)
+                                    listener: handleSend(bar, =)
+                            parsePrecedenceExpression(=, 1, true)
+                              parseUnaryExpression(=, true)
+                                parsePrimary(=, expression)
+                                  parseSendOrFunctionLiteral(=, expression)
+                                    parseSend(=, expression)
+                                      ensureIdentifier(=, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(|)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(|)
+                                      listener: handleSend(x, |)
+                              listener: beginBinaryExpression(|)
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments({)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments({)
+                                        listener: handleSend(y, {)
+                              listener: endBinaryExpression(|)
+                            listener: handleAssignmentExpression(=)
+                        listener: endInitializer({)
+                    listener: endInitializers(2, :, {)
+                parseAsyncModifierOpt(y)
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(y, false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, print)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(print)
+                        parseExpressionStatement({)
+                          parseExpression({)
+                            parsePrecedenceExpression({, 1, true)
+                              parseUnaryExpression({, true)
+                                parsePrimary({, expression)
+                                  parseSendOrFunctionLiteral({, expression)
+                                    looksLikeFunctionBody(;)
+                                    parseSend({, expression)
+                                      ensureIdentifier({, expression)
+                                        listener: handleIdentifier(print, expression)
+                                      listener: handleNoTypeArguments(()
+                                      parseArgumentsOpt(print)
+                                        parseArguments(print)
+                                          parseArgumentsRest(()
+                                            listener: beginArguments(()
+                                            parseExpression(()
+                                              parsePrecedenceExpression((, 1, true)
+                                                parseUnaryExpression((, true)
+                                                  parsePrimary((, expression)
+                                                    parseLiteralString(()
+                                                      parseSingleLiteralString(()
+                                                        listener: beginLiteralString("hello )
+                                                        parseExpression(${)
+                                                          parsePrecedenceExpression(${, 1, true)
+                                                            parseUnaryExpression(${, true)
+                                                              parsePrimary(${, expression)
+                                                                parseSendOrFunctionLiteral(${, expression)
+                                                                  parseSend(${, expression)
+                                                                    ensureIdentifier(${, expression)
+                                                                      listener: handleIdentifier(x, expression)
+                                                                    listener: handleNoTypeArguments(|)
+                                                                    parseArgumentsOpt(x)
+                                                                      listener: handleNoArguments(|)
+                                                                    listener: handleSend(x, |)
+                                                            listener: beginBinaryExpression(|)
+                                                            parsePrecedenceExpression(|, 10, true)
+                                                              parseUnaryExpression(|, true)
+                                                                parsePrimary(|, expression)
+                                                                  parseSendOrFunctionLiteral(|, expression)
+                                                                    parseSend(|, expression)
+                                                                      ensureIdentifier(|, expression)
+                                                                        listener: handleIdentifier(y, expression)
+                                                                      listener: handleNoTypeArguments(})
+                                                                      parseArgumentsOpt(y)
+                                                                        listener: handleNoArguments(})
+                                                                      listener: handleSend(y, })
+                                                            listener: endBinaryExpression(|)
+                                                        listener: handleInterpolationExpression(${, })
+                                                        parseStringPart(})
+                                                          listener: handleStringPart(")
+                                                        listener: endLiteralString(1, ))
+                                            listener: endArguments(1, (, ))
+                                      listener: handleSend(print, ;)
+                          ensureSemicolon())
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(1, {, })
+                listener: endClassConstructor(null, Key, (, :, })
+              listener: endMember()
+            notEofOrValue(}, not_currently_working)
+            parseClassOrMixinOrExtensionMemberImpl(}, DeclarationKind.Class, Key)
+              parseMetadataStar(})
+                listener: beginMetadataStar(not_currently_working)
+                listener: endMetadataStar(0)
+              listener: beginMember()
+              isReservedKeyword(()
+              parseMethod(}, null, null, null, null, null, null, }, Instance of 'NoType', null, not_currently_working, DeclarationKind.Class, Key, false)
+                listener: beginMethod(null, null, null, null, null, not_currently_working)
+                listener: handleNoType(})
+                ensureIdentifierPotentiallyRecovered(}, methodDeclaration, false)
+                  listener: handleIdentifier(not_currently_working, methodDeclaration)
+                parseQualifiedRestOpt(not_currently_working, methodDeclarationContinuation)
+                parseMethodTypeVar(not_currently_working)
+                  listener: handleNoTypeVariables(()
+                parseGetterOrFormalParameters(not_currently_working, not_currently_working, false, MemberKind.NonStaticMethod)
+                  parseFormalParameters(not_currently_working, MemberKind.NonStaticMethod)
+                    parseFormalParametersRest((, MemberKind.NonStaticMethod)
+                      listener: beginFormalParameters((, MemberKind.NonStaticMethod)
+                      parseFormalParameter((, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(()
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(x)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(x, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue(,)
+                        listener: endFormalParameter(null, null, x, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      parseFormalParameter(,, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                        parseMetadataStar(,)
+                          listener: beginMetadataStar(int)
+                          listener: endMetadataStar(0)
+                        listener: beginFormalParameter(int, MemberKind.NonStaticMethod, null, null, null)
+                        listener: handleIdentifier(int, typeReference)
+                        listener: handleNoTypeArguments(y)
+                        listener: handleType(int, null)
+                        ensureIdentifier(int, formalParameterDeclaration)
+                          listener: handleIdentifier(y, formalParameterDeclaration)
+                        listener: handleFormalParameterWithoutValue())
+                        listener: endFormalParameter(null, null, y, null, null, FormalParameterKind.mandatory, MemberKind.NonStaticMethod)
+                      listener: endFormalParameters(2, (, ), MemberKind.NonStaticMethod)
+                parseInitializersOpt())
+                  listener: handleNoInitializers()
+                parseAsyncModifierOpt())
+                  listener: handleAsyncModifier(null, null)
+                  inPlainSync()
+                inPlainSync()
+                parseFunctionBody(), false, true)
+                  listener: beginBlockFunctionBody({)
+                  notEofOrValue(}, x)
+                  parseStatement({)
+                    parseStatementX({)
+                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                        looksLikeLocalFunction(or)
+                        listener: beginMetadataStar(x)
+                        listener: endMetadataStar(0)
+                        listener: handleIdentifier(x, typeReference)
+                        listener: handleNoTypeArguments(or)
+                        listener: handleType(x, null)
+                        listener: beginVariablesDeclaration(or, null, null)
+                        parseVariablesDeclarationRest(x, true)
+                          parseOptionallyInitializedIdentifier(x)
+                            ensureIdentifier(x, localVariableDeclaration)
+                              listener: handleIdentifier(or, localVariableDeclaration)
+                            listener: beginInitializedIdentifier(or)
+                            parseVariableInitializerOpt(or)
+                              listener: handleNoVariableInitializer(or)
+                            listener: endInitializedIdentifier(or)
+                          ensureSemicolon(or)
+                            reportRecoverableError(or, Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                              listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], or, or)
+                            rewriter()
+                          listener: endVariablesDeclaration(1, ;)
+                  notEofOrValue(}, y)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(y)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(y, expression)
+                                      listener: handleNoTypeArguments(;)
+                                      parseArgumentsOpt(y)
+                                        listener: handleNoArguments(;)
+                                      listener: handleSend(y, ;)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, x)
+                  parseStatement(;)
+                    parseStatementX(;)
+                      parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                        looksLikeLocalFunction(x)
+                        parseExpressionStatement(;)
+                          parseExpression(;)
+                            parsePrecedenceExpression(;, 1, true)
+                              parseUnaryExpression(;, true)
+                                parsePrimary(;, expression)
+                                  parseSendOrFunctionLiteral(;, expression)
+                                    parseSend(;, expression)
+                                      ensureIdentifier(;, expression)
+                                        listener: handleIdentifier(x, expression)
+                                      listener: handleNoTypeArguments(|)
+                                      parseArgumentsOpt(x)
+                                        listener: handleNoArguments(|)
+                                      listener: handleSend(x, |)
+                              listener: beginBinaryExpression(|)
+                              parsePrecedenceExpression(|, 10, true)
+                                parseUnaryExpression(|, true)
+                                  parsePrimary(|, expression)
+                                    parseSendOrFunctionLiteral(|, expression)
+                                      parseSend(|, expression)
+                                        ensureIdentifier(|, expression)
+                                          listener: handleIdentifier(y, expression)
+                                        listener: handleNoTypeArguments(;)
+                                        parseArgumentsOpt(y)
+                                          listener: handleNoArguments(;)
+                                        listener: handleSend(y, ;)
+                              listener: endBinaryExpression(|)
+                          ensureSemicolon(y)
+                          listener: handleExpressionStatement(;)
+                  notEofOrValue(}, })
+                  listener: endBlockFunctionBody(3, {, })
+                listener: endClassMethod(null, not_currently_working, (, null, })
+              listener: endMember()
+            notEofOrValue(}, })
+            listener: endClassOrMixinBody(DeclarationKind.Class, 22, {, })
+          listener: endClassDeclaration(abstract, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(abstract)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.parser.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.parser.expect
new file mode 100644
index 0000000..e4a44c2
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.parser.expect
@@ -0,0 +1,87 @@
+NOTICE: Stream was rewritten by parser!
+
+abstract class Key {
+int get a => runtimeType.hashCode | null.hashCode;
+int get b => runtimeType.hashCode | null.hashCode;
+int get c { return runtimeType.hashCode | null.hashCode; }
+int get d { return runtimeType.hashCode | null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode | null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode | null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode | null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode | null.hashCode + 3; }
+
+int i(int x, int y) => x | y;
+int j(int x, int y) => x | y;
+int k(int x, int y) { return x | y; }
+int l(int x, int y) { return x | y; }
+int m(int x, int y) { int z = x | y; return z; }
+int n(int x, int y) { int z = x | y; return z; }
+
+int o(int x, int y) => 1 + x | y + 3;
+int p(int x, int y) => 1 + x | y + 3;
+int q(int x, int y) { return 1 + x | y + 3; }
+int r(int x, int y) { return 1 + x | y + 3; }
+
+s(int x, int y) {
+s(x | y, x | y);
+s(x | y, x | y);
+}
+
+Key(int x, int y) : foo = x | y, bar = x | y {
+print("hello ${x | y}");
+}
+
+Key(int x, int y) : foo = x | y, bar = x | y {
+print("hello ${x | y}");
+}
+
+not_currently_working(int x, int y) {
+x or ;y;
+x | y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[ReplacementToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] |[ReplacementToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] |[ReplacementToken] y[StringToken],[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] |[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] |[ReplacementToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] |[ReplacementToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] |[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] or[StringToken] ;[SyntheticToken]y[StringToken];[SimpleToken]
+x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.scanner.expect b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.scanner.expect
new file mode 100644
index 0000000..ac05112
--- /dev/null
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_26810_or.dart.scanner.expect
@@ -0,0 +1,85 @@
+abstract class Key {
+int get a => runtimeType.hashCode or null.hashCode;
+int get b => runtimeType.hashCode | null.hashCode;
+int get c { return runtimeType.hashCode or null.hashCode; }
+int get d { return runtimeType.hashCode | null.hashCode; }
+
+int get e => 1 + runtimeType.hashCode or null.hashCode + 3;
+int get f => 1 + runtimeType.hashCode | null.hashCode + 3;
+int get g { return 1 + runtimeType.hashCode or null.hashCode + 3; }
+int get h { return 1 + runtimeType.hashCode | null.hashCode + 3; }
+
+int i(int x, int y) => x or y;
+int j(int x, int y) => x | y;
+int k(int x, int y) { return x or y; }
+int l(int x, int y) { return x | y; }
+int m(int x, int y) { int z = x or y; return z; }
+int n(int x, int y) { int z = x | y; return z; }
+
+int o(int x, int y) => 1 + x or y + 3;
+int p(int x, int y) => 1 + x | y + 3;
+int q(int x, int y) { return 1 + x or y + 3; }
+int r(int x, int y) { return 1 + x | y + 3; }
+
+s(int x, int y) {
+s(x or y, x or y);
+s(x | y, x | y);
+}
+
+Key(int x, int y) : foo = x or y, bar = x or y {
+print("hello ${x or y}");
+}
+
+Key(int x, int y) : foo = x | y, bar = x | y {
+print("hello ${x | y}");
+}
+
+not_currently_working(int x, int y) {
+x or y;
+x | y;
+}
+}
+
+
+abstract[KeywordToken] class[KeywordToken] Key[StringToken] {[BeginToken]
+int[StringToken] get[KeywordToken] a[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] or[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] b[StringToken] =>[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] c[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] or[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] d[StringToken] {[BeginToken] return[KeywordToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] get[KeywordToken] e[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] or[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] f[StringToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] get[KeywordToken] g[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] or[StringToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] get[KeywordToken] h[StringToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] runtimeType[StringToken].[SimpleToken]hashCode[StringToken] |[SimpleToken] null[KeywordToken].[SimpleToken]hashCode[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] i[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] or[StringToken] y[StringToken];[SimpleToken]
+int[StringToken] j[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken]
+int[StringToken] k[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] or[StringToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] l[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] m[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] or[StringToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] n[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] int[StringToken] z[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken] return[KeywordToken] z[StringToken];[SimpleToken] }[SimpleToken]
+
+int[StringToken] o[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] or[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] p[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] =>[SimpleToken] 1[StringToken] +[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken]
+int[StringToken] q[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] or[StringToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+int[StringToken] r[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken] return[KeywordToken] 1[StringToken] +[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] +[SimpleToken] 3[StringToken];[SimpleToken] }[SimpleToken]
+
+s[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+s[StringToken]([BeginToken]x[StringToken] or[StringToken] y[StringToken],[SimpleToken] x[StringToken] or[StringToken] y[StringToken])[SimpleToken];[SimpleToken]
+s[StringToken]([BeginToken]x[StringToken] |[SimpleToken] y[StringToken],[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] or[StringToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] or[StringToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] or[StringToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+Key[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] :[SimpleToken] foo[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken],[SimpleToken] bar[StringToken] =[SimpleToken] x[StringToken] |[SimpleToken] y[StringToken] {[BeginToken]
+print[StringToken]([BeginToken]"hello [StringToken]${[BeginToken]x[StringToken] |[SimpleToken] y[StringToken]}[SimpleToken]"[StringToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+
+not_currently_working[StringToken]([BeginToken]int[StringToken] x[StringToken],[SimpleToken] int[StringToken] y[StringToken])[SimpleToken] {[BeginToken]
+x[StringToken] or[StringToken] y[StringToken];[SimpleToken]
+x[StringToken] |[SimpleToken] y[StringToken];[SimpleToken]
+}[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
index e4e00d9..6b57708 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.expect
@@ -37,7 +37,7 @@
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], S, S)
       endTypeArguments(1, <, >)
       handleType(n, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
       handleIdentifier(, topLevelFunctionDeclaration)
       handleNoTypeVariables()
       handleRecoverableError(MissingFunctionParameters, , )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
index 80d4990..ff3cb76 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39024.crash_dart.intertwined.expect
@@ -21,9 +21,9 @@
         listener: endTypeArguments(1, <, >)
         listener: handleType(n, null)
         ensureIdentifierPotentiallyRecovered(>, topLevelFunctionDeclaration, false)
-          insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], messageOnToken: null)
-            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+          insertSyntheticIdentifier(>, topLevelFunctionDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
             rewriter()
           listener: handleIdentifier(, topLevelFunctionDeclaration)
         parseMethodTypeVar()
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
index 93bab66..74d4738 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.expect
@@ -72,7 +72,7 @@
         handleRecoverableError(Message[ExpectedAfterButGot, Expected '>' after this., null, {string: >}], c, c)
       endTypeArguments(1, <, >)
       handleType(b, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
       handleIdentifier(, topLevelVariableDeclaration)
       handleNoFieldInitializer()
       handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], , )
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
index e188e74..ee3b3ec 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_39202.crash_dart.intertwined.expect
@@ -88,9 +88,9 @@
         listener: endTypeArguments(1, <, >)
         listener: handleType(b, null)
         ensureIdentifierPotentiallyRecovered(>, topLevelVariableDeclaration, false)
-          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], messageOnToken: null)
-            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., null, {token: }], , )
+          insertSyntheticIdentifier(>, topLevelVariableDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], messageOnToken: null)
+            reportRecoverableError(, Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ''., Try inserting an identifier before ''., {token: }], , )
             rewriter()
           listener: handleIdentifier(, topLevelVariableDeclaration)
         parseFieldInitializerOpt(, , null, null, null, null, DeclarationKind.TopLevel, null)
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
index b2c79c1..705b02f 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.expect
@@ -91,7 +91,7 @@
           handleNoArguments([])
           handleSend(foo, [])
           handleEndingBinaryExpression(..)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
           handleIdentifier(, expression)
           handleNoTypeArguments(])
           handleNoArguments(])
@@ -124,7 +124,7 @@
               handleNoArguments([])
               handleSend(foo, [])
               handleEndingBinaryExpression(..)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
               handleIdentifier(, expression)
               handleNoTypeArguments(])
               handleNoArguments(])
@@ -146,7 +146,7 @@
           handleNoArguments([)
           handleSend(foo, [)
           handleEndingBinaryExpression(..)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
           handleIdentifier(, expression)
           handleNoTypeArguments(])
           handleNoArguments(])
@@ -179,7 +179,7 @@
               handleNoArguments([)
               handleSend(foo, [)
               handleEndingBinaryExpression(..)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
               handleIdentifier(, expression)
               handleNoTypeArguments(])
               handleNoArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
index 1a76870..9b81d3a 100644
--- a/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/issue_42267.dart.intertwined.expect
@@ -203,7 +203,7 @@
                                   parseSend([, expression)
                                     ensureIdentifier([, expression)
                                       reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(])
@@ -296,7 +296,7 @@
                                                                       parseSend([, expression)
                                                                         ensureIdentifier([, expression)
                                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments(])
@@ -349,7 +349,7 @@
                                   parseSend([, expression)
                                     ensureIdentifier([, expression)
                                       reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(])
@@ -439,7 +439,7 @@
                                                                       parseSend([, expression)
                                                                         ensureIdentifier([, expression)
                                                                           reportRecoverableErrorWithToken(], Instance of 'Template<(Token) => Message>')
-                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., null, {token: ]}], ], ])
+                                                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ']'., Try inserting an identifier before ']'., {token: ]}], ], ])
                                                                           rewriter()
                                                                           listener: handleIdentifier(, expression)
                                                                         listener: handleNoTypeArguments(])
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
index d552dbc..9919798 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.expect
@@ -1,134 +1,134 @@
 Problems reported:
 
-parser/error_recovery/keyword_named_class_fields:4:7: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_class_fields:4:7: 'assert' can't be used as an identifier because it's a keyword.
   int assert = 42;
       ^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:7:7: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_class_fields:7:7: 'break' can't be used as an identifier because it's a keyword.
   int break = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:8:7: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_class_fields:8:7: 'case' can't be used as an identifier because it's a keyword.
   int case = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:9:7: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_class_fields:9:7: 'catch' can't be used as an identifier because it's a keyword.
   int catch = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:10:7: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_class_fields:10:7: 'class' can't be used as an identifier because it's a keyword.
   int class = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:11:7: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_class_fields:11:7: 'const' can't be used as an identifier because it's a keyword.
   int const = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:12:7: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_class_fields:12:7: 'continue' can't be used as an identifier because it's a keyword.
   int continue = 42;
       ^^^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:14:7: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_class_fields:14:7: 'default' can't be used as an identifier because it's a keyword.
   int default = 42;
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:16:7: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_class_fields:16:7: 'do' can't be used as an identifier because it's a keyword.
   int do = 42;
       ^^
 
-parser/error_recovery/keyword_named_class_fields:18:7: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_class_fields:18:7: 'else' can't be used as an identifier because it's a keyword.
   int else = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:19:7: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_class_fields:19:7: 'enum' can't be used as an identifier because it's a keyword.
   int enum = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:21:7: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_class_fields:21:7: 'extends' can't be used as an identifier because it's a keyword.
   int extends = 42;
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:25:7: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_class_fields:25:7: 'false' can't be used as an identifier because it's a keyword.
   int false = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:26:7: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_class_fields:26:7: 'final' can't be used as an identifier because it's a keyword.
   int final = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:27:7: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_class_fields:27:7: 'finally' can't be used as an identifier because it's a keyword.
   int finally = 42;
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:28:7: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_class_fields:28:7: 'for' can't be used as an identifier because it's a keyword.
   int for = 42;
       ^^^
 
-parser/error_recovery/keyword_named_class_fields:32:7: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_class_fields:32:7: 'if' can't be used as an identifier because it's a keyword.
   int if = 42;
       ^^
 
-parser/error_recovery/keyword_named_class_fields:35:7: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_class_fields:35:7: 'in' can't be used as an identifier because it's a keyword.
   int in = 42;
       ^^
 
-parser/error_recovery/keyword_named_class_fields:38:7: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_class_fields:38:7: 'is' can't be used as an identifier because it's a keyword.
   int is = 42;
       ^^
 
-parser/error_recovery/keyword_named_class_fields:43:7: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_class_fields:43:7: 'new' can't be used as an identifier because it's a keyword.
   int new = 42;
       ^^^
 
-parser/error_recovery/keyword_named_class_fields:44:7: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_class_fields:44:7: 'null' can't be used as an identifier because it's a keyword.
   int null = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:52:7: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_class_fields:52:7: 'rethrow' can't be used as an identifier because it's a keyword.
   int rethrow = 42;
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:53:7: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_class_fields:53:7: 'return' can't be used as an identifier because it's a keyword.
   int return = 42;
       ^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:58:7: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_class_fields:58:7: 'super' can't be used as an identifier because it's a keyword.
   int super = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:59:7: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_class_fields:59:7: 'switch' can't be used as an identifier because it's a keyword.
   int switch = 42;
       ^^^^^^
 
-parser/error_recovery/keyword_named_class_fields:61:7: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_class_fields:61:7: 'this' can't be used as an identifier because it's a keyword.
   int this = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:62:7: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_class_fields:62:7: 'throw' can't be used as an identifier because it's a keyword.
   int throw = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:63:7: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_class_fields:63:7: 'true' can't be used as an identifier because it's a keyword.
   int true = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:64:7: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_class_fields:64:7: 'try' can't be used as an identifier because it's a keyword.
   int try = 42;
       ^^^
 
-parser/error_recovery/keyword_named_class_fields:66:7: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_class_fields:66:7: 'var' can't be used as an identifier because it's a keyword.
   int var = 42;
       ^^^
 
-parser/error_recovery/keyword_named_class_fields:67:7: Expected an identifier, but got 'void'.
+parser/error_recovery/keyword_named_class_fields:67:7: 'void' can't be used as an identifier because it's a keyword.
   int void = 42;
       ^^^^
 
-parser/error_recovery/keyword_named_class_fields:68:7: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_class_fields:68:7: 'while' can't be used as an identifier because it's a keyword.
   int while = 42;
       ^^^^^
 
-parser/error_recovery/keyword_named_class_fields:69:7: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_class_fields:69:7: 'with' can't be used as an identifier because it's a keyword.
   int with = 42;
       ^^^^
 
@@ -178,7 +178,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(assert)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
             handleIdentifier(assert, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -218,7 +218,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(break)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
             handleIdentifier(break, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -232,7 +232,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(case)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
             handleIdentifier(case, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -246,7 +246,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(catch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
             handleIdentifier(catch, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -260,7 +260,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(class)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
             handleIdentifier(class, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -274,7 +274,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(const)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
             handleIdentifier(const, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -288,7 +288,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(continue)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
             handleIdentifier(continue, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -315,7 +315,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(default)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
             handleIdentifier(default, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -342,7 +342,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(do)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
             handleIdentifier(do, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -369,7 +369,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(else)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
             handleIdentifier(else, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -383,7 +383,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(enum)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
             handleIdentifier(enum, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -410,7 +410,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(extends)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
             handleIdentifier(extends, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -463,7 +463,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(false)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
             handleIdentifier(false, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -477,7 +477,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(final)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
             handleIdentifier(final, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -491,7 +491,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(finally)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
             handleIdentifier(finally, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -505,7 +505,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(for)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
             handleIdentifier(for, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -558,7 +558,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(if)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
             handleIdentifier(if, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -598,7 +598,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(in)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
             handleIdentifier(in, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -638,7 +638,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(is)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
             handleIdentifier(is, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -704,7 +704,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(new)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
             handleIdentifier(new, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -718,7 +718,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(null)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
             handleIdentifier(null, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -823,7 +823,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(rethrow)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
             handleIdentifier(rethrow, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -837,7 +837,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(return)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
             handleIdentifier(return, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -903,7 +903,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(super)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
             handleIdentifier(super, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -917,7 +917,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(switch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
             handleIdentifier(switch, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -944,7 +944,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(this)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
             handleIdentifier(this, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -958,7 +958,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(throw)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
             handleIdentifier(throw, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -972,7 +972,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(true)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
             handleIdentifier(true, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -986,7 +986,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(try)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
             handleIdentifier(try, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1013,7 +1013,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(var)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
             handleIdentifier(var, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1027,7 +1027,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(void)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
             handleIdentifier(void, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1041,7 +1041,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(while)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
             handleIdentifier(while, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
@@ -1055,7 +1055,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(42)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
index 467d656..ef8682d 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_fields.dart.intertwined.expect
@@ -89,7 +89,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
                   listener: handleIdentifier(assert, fieldDeclaration)
                 parseFieldInitializerOpt(assert, assert, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -165,7 +165,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
                   listener: handleIdentifier(break, fieldDeclaration)
                 parseFieldInitializerOpt(break, break, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -193,7 +193,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
                   listener: handleIdentifier(case, fieldDeclaration)
                 parseFieldInitializerOpt(case, case, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -221,7 +221,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
                   listener: handleIdentifier(catch, fieldDeclaration)
                 parseFieldInitializerOpt(catch, catch, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -249,7 +249,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
                   listener: handleIdentifier(class, fieldDeclaration)
                 parseFieldInitializerOpt(class, class, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -277,7 +277,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
                   listener: handleIdentifier(const, fieldDeclaration)
                 parseFieldInitializerOpt(const, const, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -305,7 +305,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
                   listener: handleIdentifier(continue, fieldDeclaration)
                 parseFieldInitializerOpt(continue, continue, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -357,7 +357,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
                   listener: handleIdentifier(default, fieldDeclaration)
                 parseFieldInitializerOpt(default, default, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -409,7 +409,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
                   listener: handleIdentifier(do, fieldDeclaration)
                 parseFieldInitializerOpt(do, do, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -461,7 +461,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
                   listener: handleIdentifier(else, fieldDeclaration)
                 parseFieldInitializerOpt(else, else, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -489,7 +489,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
                   listener: handleIdentifier(enum, fieldDeclaration)
                 parseFieldInitializerOpt(enum, enum, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -541,7 +541,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
                   listener: handleIdentifier(extends, fieldDeclaration)
                 parseFieldInitializerOpt(extends, extends, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -641,7 +641,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
                   listener: handleIdentifier(false, fieldDeclaration)
                 parseFieldInitializerOpt(false, false, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -669,7 +669,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
                   listener: handleIdentifier(final, fieldDeclaration)
                 parseFieldInitializerOpt(final, final, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -697,7 +697,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
                   listener: handleIdentifier(finally, fieldDeclaration)
                 parseFieldInitializerOpt(finally, finally, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -725,7 +725,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
                   listener: handleIdentifier(for, fieldDeclaration)
                 parseFieldInitializerOpt(for, for, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -826,7 +826,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
                   listener: handleIdentifier(if, fieldDeclaration)
                 parseFieldInitializerOpt(if, if, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -902,7 +902,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
                   listener: handleIdentifier(in, fieldDeclaration)
                 parseFieldInitializerOpt(in, in, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -978,7 +978,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
                   listener: handleIdentifier(is, fieldDeclaration)
                 parseFieldInitializerOpt(is, is, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1102,7 +1102,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
                   listener: handleIdentifier(new, fieldDeclaration)
                 parseFieldInitializerOpt(new, new, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1130,7 +1130,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
                   listener: handleIdentifier(null, fieldDeclaration)
                 parseFieldInitializerOpt(null, null, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1327,7 +1327,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
                   listener: handleIdentifier(rethrow, fieldDeclaration)
                 parseFieldInitializerOpt(rethrow, rethrow, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1355,7 +1355,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
                   listener: handleIdentifier(return, fieldDeclaration)
                 parseFieldInitializerOpt(return, return, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1480,7 +1480,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
                   listener: handleIdentifier(super, fieldDeclaration)
                 parseFieldInitializerOpt(super, super, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1508,7 +1508,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
                   listener: handleIdentifier(switch, fieldDeclaration)
                 parseFieldInitializerOpt(switch, switch, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1559,7 +1559,7 @@
                   listener: handleType(int, null)
                   ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
                     reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
                     listener: handleIdentifier(this, fieldDeclaration)
                   parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.Class, WrapperClass)
                     listener: beginFieldInitializer(=)
@@ -1587,7 +1587,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
                   listener: handleIdentifier(throw, fieldDeclaration)
                 parseFieldInitializerOpt(throw, throw, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1615,7 +1615,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
                   listener: handleIdentifier(true, fieldDeclaration)
                 parseFieldInitializerOpt(true, true, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1643,7 +1643,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
                   listener: handleIdentifier(try, fieldDeclaration)
                 parseFieldInitializerOpt(try, try, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1695,7 +1695,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
                   listener: handleIdentifier(var, fieldDeclaration)
                 parseFieldInitializerOpt(var, var, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1723,7 +1723,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
                   listener: handleIdentifier(void, fieldDeclaration)
                 parseFieldInitializerOpt(void, void, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1751,7 +1751,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
                   listener: handleIdentifier(while, fieldDeclaration)
                 parseFieldInitializerOpt(while, while, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
@@ -1779,7 +1779,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, fieldDeclaration)
                 parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.Class, WrapperClass)
                   listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
index 614bc0c..c3ffe0e 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.expect
@@ -1,6 +1,6 @@
 Problems reported:
 
-parser/error_recovery/keyword_named_class_methods:12:7: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_class_methods:12:7: 'assert' can't be used as an identifier because it's a keyword.
   int assert(int x) {
       ^^^^^^
 
@@ -8,7 +8,7 @@
     return assert(x-1) + 1;
            ^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:27:7: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_class_methods:27:7: 'break' can't be used as an identifier because it's a keyword.
   int break(int x) {
       ^^^^^
 
@@ -28,31 +28,31 @@
     return break(x-1) + 1;
            ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:32:7: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_class_methods:32:7: 'case' can't be used as an identifier because it's a keyword.
   int case(int x) {
       ^^^^
 
-parser/error_recovery/keyword_named_class_methods:34:12: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_class_methods:34:12: 'case' can't be used as an identifier because it's a keyword.
     return case(x-1) + 1;
            ^^^^
 
-parser/error_recovery/keyword_named_class_methods:37:7: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_class_methods:37:7: 'catch' can't be used as an identifier because it's a keyword.
   int catch(int x) {
       ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:39:12: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_class_methods:39:12: 'catch' can't be used as an identifier because it's a keyword.
     return catch(x-1) + 1;
            ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:42:7: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_class_methods:42:7: 'class' can't be used as an identifier because it's a keyword.
   int class(int x) {
       ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:44:12: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_class_methods:44:12: 'class' can't be used as an identifier because it's a keyword.
     return class(x-1) + 1;
            ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:47:7: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_class_methods:47:7: 'const' can't be used as an identifier because it's a keyword.
   int const(int x) {
       ^^^^^
 
@@ -60,7 +60,7 @@
     return const(x-1) + 1;
                 ^
 
-parser/error_recovery/keyword_named_class_methods:52:7: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_class_methods:52:7: 'continue' can't be used as an identifier because it's a keyword.
   int continue(int x) {
       ^^^^^^^^
 
@@ -80,15 +80,15 @@
     return continue(x-1) + 1;
            ^^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:62:7: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_class_methods:62:7: 'default' can't be used as an identifier because it's a keyword.
   int default(int x) {
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:64:12: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_class_methods:64:12: 'default' can't be used as an identifier because it's a keyword.
     return default(x-1) + 1;
            ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:72:7: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_class_methods:72:7: 'do' can't be used as an identifier because it's a keyword.
   int do(int x) {
       ^^
 
@@ -116,7 +116,7 @@
   }
   ^
 
-parser/error_recovery/keyword_named_class_methods:82:7: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_class_methods:82:7: 'else' can't be used as an identifier because it's a keyword.
   int else(int x) {
       ^^^^
 
@@ -140,27 +140,27 @@
     return else(x-1) + 1;
            ^^^^
 
-parser/error_recovery/keyword_named_class_methods:87:7: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_class_methods:87:7: 'enum' can't be used as an identifier because it's a keyword.
   int enum(int x) {
       ^^^^
 
-parser/error_recovery/keyword_named_class_methods:89:12: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_class_methods:89:12: 'enum' can't be used as an identifier because it's a keyword.
     return enum(x-1) + 1;
            ^^^^
 
-parser/error_recovery/keyword_named_class_methods:97:7: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_class_methods:97:7: 'extends' can't be used as an identifier because it's a keyword.
   int extends(int x) {
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:99:12: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_class_methods:99:12: 'extends' can't be used as an identifier because it's a keyword.
     return extends(x-1) + 1;
            ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:117:7: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_class_methods:117:7: 'false' can't be used as an identifier because it's a keyword.
   int false(int x) {
       ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:122:7: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_class_methods:122:7: 'final' can't be used as an identifier because it's a keyword.
   int final(int x) {
       ^^^^^
 
@@ -200,15 +200,15 @@
     return final(x-1) + 1;
                       ^
 
-parser/error_recovery/keyword_named_class_methods:127:7: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_class_methods:127:7: 'finally' can't be used as an identifier because it's a keyword.
   int finally(int x) {
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:129:12: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_class_methods:129:12: 'finally' can't be used as an identifier because it's a keyword.
     return finally(x-1) + 1;
            ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:132:7: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_class_methods:132:7: 'for' can't be used as an identifier because it's a keyword.
   int for(int x) {
       ^^^
 
@@ -236,7 +236,7 @@
     return for(x-1) + 1;
                     ^
 
-parser/error_recovery/keyword_named_class_methods:152:7: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_class_methods:152:7: 'if' can't be used as an identifier because it's a keyword.
   int if(int x) {
       ^^
 
@@ -252,15 +252,15 @@
     return if(x-1) + 1;
                    ^
 
-parser/error_recovery/keyword_named_class_methods:167:7: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_class_methods:167:7: 'in' can't be used as an identifier because it's a keyword.
   int in(int x) {
       ^^
 
-parser/error_recovery/keyword_named_class_methods:169:12: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_class_methods:169:12: 'in' can't be used as an identifier because it's a keyword.
     return in(x-1) + 1;
            ^^
 
-parser/error_recovery/keyword_named_class_methods:182:7: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_class_methods:182:7: 'is' can't be used as an identifier because it's a keyword.
   int is(int x) {
       ^^
 
@@ -276,7 +276,7 @@
     return is(x-1) + 1;
              ^
 
-parser/error_recovery/keyword_named_class_methods:207:7: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_class_methods:207:7: 'new' can't be used as an identifier because it's a keyword.
   int new(int x) {
       ^^^
 
@@ -284,19 +284,19 @@
     return new(x-1) + 1;
               ^
 
-parser/error_recovery/keyword_named_class_methods:212:7: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_class_methods:212:7: 'null' can't be used as an identifier because it's a keyword.
   int null(int x) {
       ^^^^
 
-parser/error_recovery/keyword_named_class_methods:252:7: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_class_methods:252:7: 'rethrow' can't be used as an identifier because it's a keyword.
   int rethrow(int x) {
       ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:254:12: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_class_methods:254:12: 'rethrow' can't be used as an identifier because it's a keyword.
     return rethrow(x-1) + 1;
            ^^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:257:7: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_class_methods:257:7: 'return' can't be used as an identifier because it's a keyword.
   int return(int x) {
       ^^^^^^
 
@@ -304,11 +304,11 @@
     return return(x-1) + 1;
            ^^^^^^
 
-parser/error_recovery/keyword_named_class_methods:282:7: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_class_methods:282:7: 'super' can't be used as an identifier because it's a keyword.
   int super(int x) {
       ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:287:7: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_class_methods:287:7: 'switch' can't be used as an identifier because it's a keyword.
   int switch(int x) {
       ^^^^^^
 
@@ -328,7 +328,7 @@
     return switch(x-1) + 1;
                        ^
 
-parser/error_recovery/keyword_named_class_methods:297:7: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_class_methods:297:7: 'this' can't be used as an identifier because it's a keyword.
   int this(int x) {
       ^^^^
 
@@ -340,15 +340,15 @@
   int this(int x) {
           ^
 
-parser/error_recovery/keyword_named_class_methods:302:7: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_class_methods:302:7: 'throw' can't be used as an identifier because it's a keyword.
   int throw(int x) {
       ^^^^^
 
-parser/error_recovery/keyword_named_class_methods:307:7: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_class_methods:307:7: 'true' can't be used as an identifier because it's a keyword.
   int true(int x) {
       ^^^^
 
-parser/error_recovery/keyword_named_class_methods:312:7: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_class_methods:312:7: 'try' can't be used as an identifier because it's a keyword.
   int try(int x) {
       ^^^
 
@@ -368,7 +368,7 @@
     return try(x-1) + 1;
            ^^^
 
-parser/error_recovery/keyword_named_class_methods:322:7: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_class_methods:322:7: 'var' can't be used as an identifier because it's a keyword.
   int var(int x) {
       ^^^
 
@@ -408,7 +408,7 @@
     return var(x-1) + 1;
                     ^
 
-parser/error_recovery/keyword_named_class_methods:327:7: Expected an identifier, but got 'void'.
+parser/error_recovery/keyword_named_class_methods:327:7: 'void' can't be used as an identifier because it's a keyword.
   int void(int x) {
       ^^^^
 
@@ -448,7 +448,7 @@
     return void(x-1) + 1;
                      ^
 
-parser/error_recovery/keyword_named_class_methods:332:7: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_class_methods:332:7: 'while' can't be used as an identifier because it's a keyword.
   int while(int x) {
       ^^^^^
 
@@ -464,11 +464,11 @@
     return while(x-1) + 1;
                       ^
 
-parser/error_recovery/keyword_named_class_methods:337:7: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_class_methods:337:7: 'with' can't be used as an identifier because it's a keyword.
   int with(int x) {
       ^^^^
 
-parser/error_recovery/keyword_named_class_methods:339:12: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_class_methods:339:12: 'with' can't be used as an identifier because it's a keyword.
     return with(x-1) + 1;
            ^^^^
 
@@ -608,7 +608,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(assert)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
             handleIdentifier(assert, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -781,7 +781,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(break)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
             handleIdentifier(break, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -814,7 +814,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(break)
                 handleNoArguments(break)
@@ -846,7 +846,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(case)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
             handleIdentifier(case, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -879,7 +879,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
                 handleIdentifier(case, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -906,7 +906,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(catch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
             handleIdentifier(catch, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -939,7 +939,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
                 handleIdentifier(catch, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -966,7 +966,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(class)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
             handleIdentifier(class, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -999,7 +999,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
                 handleIdentifier(class, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1026,7 +1026,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(const)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
             handleIdentifier(const, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1060,7 +1060,7 @@
               endIfStatement(if, null)
               beginReturnStatement(return)
                 beginConstExpression(const)
-                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                   handleIdentifier(, constructorReference)
                   beginConstructorReference()
                     handleNoTypeArguments(()
@@ -1090,7 +1090,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(continue)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
             handleIdentifier(continue, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1123,7 +1123,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(continue)
                 handleNoArguments(continue)
@@ -1213,7 +1213,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(default)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
             handleIdentifier(default, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1246,7 +1246,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
                 handleIdentifier(default, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1331,7 +1331,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(do)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
             handleIdentifier(do, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1364,7 +1364,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(do)
                 handleNoArguments(do)
@@ -1388,7 +1388,7 @@
                 endDoWhileStatementBody(;)
                 handleRecoverableError(Message[ExpectedButGot, Expected 'while' before this., null, {string: while}], }, })
                 handleRecoverableError(Message[ExpectedToken, Expected to find '('., null, {string: (}], }, })
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
                 handleIdentifier(, expression)
                 handleNoTypeArguments())
                 handleNoArguments())
@@ -1464,7 +1464,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(else)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
             handleIdentifier(else, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1497,14 +1497,14 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(else)
                 handleNoArguments(else)
                 handleSend(, else)
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
               endReturnStatement(true, return, ;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
               handleIdentifier(, expression)
               handleNoTypeArguments(else)
               handleNoArguments(else)
@@ -1534,7 +1534,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(enum)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
             handleIdentifier(enum, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1567,7 +1567,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
                 handleIdentifier(enum, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1652,7 +1652,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(extends)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
             handleIdentifier(extends, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1685,7 +1685,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
                 handleIdentifier(extends, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -1886,7 +1886,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(false)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
             handleIdentifier(false, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1945,7 +1945,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(final)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
             handleIdentifier(final, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -1978,7 +1978,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(final)
                 handleNoArguments(final)
@@ -1989,7 +1989,7 @@
               endMetadataStar(0)
               handleNoType(final)
               beginVariablesDeclaration((, null, final)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -2005,7 +2005,7 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
@@ -2032,7 +2032,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(finally)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
             handleIdentifier(finally, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2065,7 +2065,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
                 handleIdentifier(finally, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -2092,7 +2092,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(for)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
             handleIdentifier(for, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2125,7 +2125,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(for)
                 handleNoArguments(for)
@@ -2142,7 +2142,7 @@
                 endBinaryExpression(-)
                 handleForInitializerExpressionStatement(1, false)
                 handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                 handleIdentifier(, expression)
                 handleNoTypeArguments())
                 handleNoArguments())
@@ -2346,7 +2346,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(if)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
             handleIdentifier(if, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2379,7 +2379,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(if)
                 handleNoArguments(if)
@@ -2533,7 +2533,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(in)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
             handleIdentifier(in, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2566,7 +2566,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
                 handleIdentifier(in, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -2709,7 +2709,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(is)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
             handleIdentifier(is, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -2742,7 +2742,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(is)
                 handleNoArguments(is)
@@ -3010,7 +3010,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(new)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
             handleIdentifier(new, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3044,7 +3044,7 @@
               endIfStatement(if, null)
               beginReturnStatement(return)
                 beginNewExpression(new)
-                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                  handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                   handleIdentifier(, constructorReference)
                   beginConstructorReference()
                     handleNoTypeArguments(()
@@ -3074,7 +3074,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(null)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
             handleIdentifier(null, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3539,7 +3539,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(rethrow)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
             handleIdentifier(rethrow, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3572,7 +3572,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
                 handleIdentifier(rethrow, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
@@ -3599,7 +3599,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(return)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
             handleIdentifier(return, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3887,7 +3887,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(super)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
             handleIdentifier(super, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3946,7 +3946,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(switch)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
             handleIdentifier(switch, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -3979,7 +3979,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(switch)
                 handleNoArguments(switch)
@@ -4076,7 +4076,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(this)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
             handleIdentifier(this, fieldDeclaration)
             handleNoFieldInitializer(()
             handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], this, this)
@@ -4087,7 +4087,7 @@
         beginMember()
           beginMethod(null, null, null, null, null, ()
             handleNoType(;)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
             handleIdentifier(, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4146,7 +4146,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(throw)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
             handleIdentifier(throw, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4202,7 +4202,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(true)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
             handleIdentifier(true, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4261,7 +4261,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(try)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
             handleIdentifier(try, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4294,7 +4294,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(try)
                 handleNoArguments(try)
@@ -4387,7 +4387,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(var)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
             handleIdentifier(var, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4420,7 +4420,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(var)
                 handleNoArguments(var)
@@ -4431,7 +4431,7 @@
               endMetadataStar(0)
               handleNoType(var)
               beginVariablesDeclaration((, null, var)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -4447,7 +4447,7 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
@@ -4474,7 +4474,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(void)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
             handleIdentifier(void, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4507,7 +4507,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(void)
                 handleNoArguments(void)
@@ -4518,7 +4518,7 @@
               endMetadataStar(0)
               handleVoidKeyword(void)
               beginVariablesDeclaration((, null, null)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                 handleIdentifier(, localVariableDeclaration)
                 beginInitializedIdentifier()
                   handleNoVariableInitializer()
@@ -4534,7 +4534,7 @@
               endBinaryExpression(-)
               handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
               handleExpressionStatement(;)
-              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+              handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
               handleIdentifier(, expression)
               handleNoTypeArguments())
               handleNoArguments())
@@ -4561,7 +4561,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(while)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
             handleIdentifier(while, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4594,7 +4594,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
                 handleIdentifier(, expression)
                 handleNoTypeArguments(while)
                 handleNoArguments(while)
@@ -4632,7 +4632,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -4665,7 +4665,7 @@
                 endThenStatement(;)
               endIfStatement(if, null)
               beginReturnStatement(return)
-                handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                 handleIdentifier(with, expression)
                 handleNoTypeArguments(()
                 beginArguments(()
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
index 325c75e..bfd0eb21 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_class_methods.dart.intertwined.expect
@@ -323,7 +323,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
                   listener: handleIdentifier(assert, methodDeclaration)
                 parseQualifiedRestOpt(assert, methodDeclarationContinuation)
                 parseMethodTypeVar(assert)
@@ -745,7 +745,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
                   listener: handleIdentifier(break, methodDeclaration)
                 parseQualifiedRestOpt(break, methodDeclarationContinuation)
                 parseMethodTypeVar(break)
@@ -832,7 +832,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(break)
@@ -921,7 +921,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
                   listener: handleIdentifier(case, methodDeclaration)
                 parseQualifiedRestOpt(case, methodDeclarationContinuation)
                 parseMethodTypeVar(case)
@@ -1008,7 +1008,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
                                     listener: handleIdentifier(case, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(case)
@@ -1065,7 +1065,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
                   listener: handleIdentifier(catch, methodDeclaration)
                 parseQualifiedRestOpt(catch, methodDeclarationContinuation)
                 parseMethodTypeVar(catch)
@@ -1152,7 +1152,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
                                     listener: handleIdentifier(catch, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(catch)
@@ -1209,7 +1209,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
                   listener: handleIdentifier(class, methodDeclaration)
                 parseQualifiedRestOpt(class, methodDeclarationContinuation)
                 parseMethodTypeVar(class)
@@ -1296,7 +1296,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
                                     listener: handleIdentifier(class, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(class)
@@ -1353,7 +1353,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
                   listener: handleIdentifier(const, methodDeclaration)
                 parseQualifiedRestOpt(const, methodDeclarationContinuation)
                 parseMethodTypeVar(const)
@@ -1440,9 +1440,9 @@
                                   listener: beginConstExpression(const)
                                   parseConstructorReference(const, null)
                                     ensureIdentifier(const, constructorReference)
-                                      insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], messageOnToken: null)
-                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}])
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                                      insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
+                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                                         rewriter()
                                       listener: handleIdentifier(, constructorReference)
                                     listener: beginConstructorReference()
@@ -1503,7 +1503,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
                   listener: handleIdentifier(continue, methodDeclaration)
                 parseQualifiedRestOpt(continue, methodDeclarationContinuation)
                 parseMethodTypeVar(continue)
@@ -1590,7 +1590,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(continue)
@@ -1820,7 +1820,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
                   listener: handleIdentifier(default, methodDeclaration)
                 parseQualifiedRestOpt(default, methodDeclarationContinuation)
                 parseMethodTypeVar(default)
@@ -1907,7 +1907,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
                                     listener: handleIdentifier(default, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(default)
@@ -2105,7 +2105,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
                   listener: handleIdentifier(do, methodDeclaration)
                 parseQualifiedRestOpt(do, methodDeclarationContinuation)
                 parseMethodTypeVar(do)
@@ -2192,7 +2192,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(do)
@@ -2271,7 +2271,7 @@
                                     parseSend((, expression)
                                       ensureIdentifier((, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -2445,7 +2445,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
                   listener: handleIdentifier(else, methodDeclaration)
                 parseQualifiedRestOpt(else, methodDeclarationContinuation)
                 parseMethodTypeVar(else)
@@ -2532,7 +2532,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(else)
@@ -2560,7 +2560,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments(else)
@@ -2638,7 +2638,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
                   listener: handleIdentifier(enum, methodDeclaration)
                 parseQualifiedRestOpt(enum, methodDeclarationContinuation)
                 parseMethodTypeVar(enum)
@@ -2725,7 +2725,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
                                     listener: handleIdentifier(enum, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(enum)
@@ -2923,7 +2923,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
                   listener: handleIdentifier(extends, methodDeclaration)
                 parseQualifiedRestOpt(extends, methodDeclarationContinuation)
                 parseMethodTypeVar(extends)
@@ -3010,7 +3010,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
                                     listener: handleIdentifier(extends, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(extends)
@@ -3490,7 +3490,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
                   listener: handleIdentifier(false, methodDeclaration)
                 parseQualifiedRestOpt(false, methodDeclarationContinuation)
                 parseMethodTypeVar(false)
@@ -3630,7 +3630,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
                   listener: handleIdentifier(final, methodDeclaration)
                 parseQualifiedRestOpt(final, methodDeclarationContinuation)
                 parseMethodTypeVar(final)
@@ -3717,7 +3717,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(final)
@@ -3743,7 +3743,7 @@
                           parseOptionallyInitializedIdentifier(final)
                             ensureIdentifier(final, localVariableDeclaration)
                               reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                               rewriter()
                               listener: handleIdentifier(, localVariableDeclaration)
                             listener: beginInitializedIdentifier()
@@ -3799,7 +3799,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -3864,7 +3864,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
                   listener: handleIdentifier(finally, methodDeclaration)
                 parseQualifiedRestOpt(finally, methodDeclarationContinuation)
                 parseMethodTypeVar(finally)
@@ -3951,7 +3951,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
                                     listener: handleIdentifier(finally, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(finally)
@@ -4008,7 +4008,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
                   listener: handleIdentifier(for, methodDeclaration)
                 parseQualifiedRestOpt(for, methodDeclarationContinuation)
                 parseMethodTypeVar(for)
@@ -4095,7 +4095,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(for)
@@ -4151,7 +4151,7 @@
                                       parseSend(;, expression)
                                         ensureIdentifier(;, expression)
                                           reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                           rewriter()
                                           listener: handleIdentifier(, expression)
                                         listener: handleNoTypeArguments())
@@ -4641,7 +4641,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
                   listener: handleIdentifier(if, methodDeclaration)
                 parseQualifiedRestOpt(if, methodDeclarationContinuation)
                 parseMethodTypeVar(if)
@@ -4728,7 +4728,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(if)
@@ -5104,7 +5104,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
                   listener: handleIdentifier(in, methodDeclaration)
                 parseQualifiedRestOpt(in, methodDeclarationContinuation)
                 parseMethodTypeVar(in)
@@ -5191,7 +5191,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
                                     listener: handleIdentifier(in, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(in)
@@ -5530,7 +5530,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
                   listener: handleIdentifier(is, methodDeclaration)
                 parseQualifiedRestOpt(is, methodDeclarationContinuation)
                 parseMethodTypeVar(is)
@@ -5617,7 +5617,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(is)
@@ -6270,7 +6270,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
                   listener: handleIdentifier(new, methodDeclaration)
                 parseQualifiedRestOpt(new, methodDeclarationContinuation)
                 parseMethodTypeVar(new)
@@ -6357,9 +6357,9 @@
                                   listener: beginNewExpression(new)
                                   parseConstructorReference(new, null)
                                     ensureIdentifier(new, constructorReference)
-                                      insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], messageOnToken: null)
-                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}])
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                                      insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
+                                        reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                                         rewriter()
                                       listener: handleIdentifier(, constructorReference)
                                     listener: beginConstructorReference()
@@ -6420,7 +6420,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
                   listener: handleIdentifier(null, methodDeclaration)
                 parseQualifiedRestOpt(null, methodDeclarationContinuation)
                 parseMethodTypeVar(null)
@@ -7549,7 +7549,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
                   listener: handleIdentifier(rethrow, methodDeclaration)
                 parseQualifiedRestOpt(rethrow, methodDeclarationContinuation)
                 parseMethodTypeVar(rethrow)
@@ -7636,7 +7636,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
                                     listener: handleIdentifier(rethrow, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(rethrow)
@@ -7693,7 +7693,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
                   listener: handleIdentifier(return, methodDeclaration)
                 parseQualifiedRestOpt(return, methodDeclarationContinuation)
                 parseMethodTypeVar(return)
@@ -8399,7 +8399,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
                   listener: handleIdentifier(super, methodDeclaration)
                 parseQualifiedRestOpt(super, methodDeclarationContinuation)
                 parseMethodTypeVar(super)
@@ -8538,7 +8538,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
                   listener: handleIdentifier(switch, methodDeclaration)
                 parseQualifiedRestOpt(switch, methodDeclarationContinuation)
                 parseMethodTypeVar(switch)
@@ -8625,7 +8625,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(switch)
@@ -8868,7 +8868,7 @@
                   listener: handleType(int, null)
                   ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, false)
                     reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
                     listener: handleIdentifier(this, fieldDeclaration)
                   parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.Class, WrapperClass)
                     listener: handleNoFieldInitializer(()
@@ -8890,8 +8890,8 @@
                   listener: handleNoType(;)
                   ensureIdentifierPotentiallyRecovered(;, methodDeclaration, false)
                     insertSyntheticIdentifier(;, methodDeclaration, message: null, messageOnToken: null)
-                      reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}])
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                      reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                       rewriter()
                     listener: handleIdentifier(, methodDeclaration)
                   parseQualifiedRestOpt(, methodDeclarationContinuation)
@@ -9031,7 +9031,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
                   listener: handleIdentifier(throw, methodDeclaration)
                 parseQualifiedRestOpt(throw, methodDeclarationContinuation)
                 parseMethodTypeVar(throw)
@@ -9171,7 +9171,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
                   listener: handleIdentifier(true, methodDeclaration)
                 parseQualifiedRestOpt(true, methodDeclarationContinuation)
                 parseMethodTypeVar(true)
@@ -9311,7 +9311,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
                   listener: handleIdentifier(try, methodDeclaration)
                 parseQualifiedRestOpt(try, methodDeclarationContinuation)
                 parseMethodTypeVar(try)
@@ -9398,7 +9398,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(try)
@@ -9634,7 +9634,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
                   listener: handleIdentifier(var, methodDeclaration)
                 parseQualifiedRestOpt(var, methodDeclarationContinuation)
                 parseMethodTypeVar(var)
@@ -9721,7 +9721,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(var)
@@ -9747,7 +9747,7 @@
                           parseOptionallyInitializedIdentifier(var)
                             ensureIdentifier(var, localVariableDeclaration)
                               reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                               rewriter()
                               listener: handleIdentifier(, localVariableDeclaration)
                             listener: beginInitializedIdentifier()
@@ -9803,7 +9803,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -9868,7 +9868,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
                   listener: handleIdentifier(void, methodDeclaration)
                 parseQualifiedRestOpt(void, methodDeclarationContinuation)
                 parseMethodTypeVar(void)
@@ -9955,7 +9955,7 @@
                                   parseSend(return, expression)
                                     ensureIdentifier(return, expression)
                                       reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+                                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
                                       rewriter()
                                       listener: handleIdentifier(, expression)
                                     listener: handleNoTypeArguments(void)
@@ -9982,7 +9982,7 @@
                             parseOptionallyInitializedIdentifier(void)
                               ensureIdentifier(void, localVariableDeclaration)
                                 reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                                 rewriter()
                                 listener: handleIdentifier(, localVariableDeclaration)
                               listener: beginInitializedIdentifier()
@@ -10038,7 +10038,7 @@
                                     parseSend(;, expression)
                                       ensureIdentifier(;, expression)
                                         reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                         rewriter()
                                         listener: handleIdentifier(, expression)
                                       listener: handleNoTypeArguments())
@@ -10103,7 +10103,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
                   listener: handleIdentifier(while, methodDeclaration)
                 parseQualifiedRestOpt(while, methodDeclarationContinuation)
                 parseMethodTypeVar(while)
@@ -10190,7 +10190,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(while)
@@ -10284,7 +10284,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 parseMethodTypeVar(with)
@@ -10371,7 +10371,7 @@
                                 parseSend(return, expression)
                                   ensureIdentifier(return, expression)
                                     reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                                     listener: handleIdentifier(with, expression)
                                   listener: handleNoTypeArguments(()
                                   parseArgumentsOpt(with)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
index 7789ff7..c634476 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.expect
@@ -1,134 +1,134 @@
 Problems reported:
 
-parser/error_recovery/keyword_named_top_level_fields:3:5: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_top_level_fields:3:5: 'assert' can't be used as an identifier because it's a keyword.
 int assert = 42;
     ^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:6:5: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_top_level_fields:6:5: 'break' can't be used as an identifier because it's a keyword.
 int break = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:7:5: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_top_level_fields:7:5: 'case' can't be used as an identifier because it's a keyword.
 int case = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:8:5: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_top_level_fields:8:5: 'catch' can't be used as an identifier because it's a keyword.
 int catch = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:9:5: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_top_level_fields:9:5: 'class' can't be used as an identifier because it's a keyword.
 int class = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:10:5: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_top_level_fields:10:5: 'const' can't be used as an identifier because it's a keyword.
 int const = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:11:5: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_top_level_fields:11:5: 'continue' can't be used as an identifier because it's a keyword.
 int continue = 42;
     ^^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:13:5: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_top_level_fields:13:5: 'default' can't be used as an identifier because it's a keyword.
 int default = 42;
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:15:5: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_top_level_fields:15:5: 'do' can't be used as an identifier because it's a keyword.
 int do = 42;
     ^^
 
-parser/error_recovery/keyword_named_top_level_fields:17:5: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_top_level_fields:17:5: 'else' can't be used as an identifier because it's a keyword.
 int else = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:18:5: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_top_level_fields:18:5: 'enum' can't be used as an identifier because it's a keyword.
 int enum = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:20:5: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_top_level_fields:20:5: 'extends' can't be used as an identifier because it's a keyword.
 int extends = 42;
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:24:5: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_top_level_fields:24:5: 'false' can't be used as an identifier because it's a keyword.
 int false = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:25:5: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_top_level_fields:25:5: 'final' can't be used as an identifier because it's a keyword.
 int final = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:26:5: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_top_level_fields:26:5: 'finally' can't be used as an identifier because it's a keyword.
 int finally = 42;
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:27:5: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_top_level_fields:27:5: 'for' can't be used as an identifier because it's a keyword.
 int for = 42;
     ^^^
 
-parser/error_recovery/keyword_named_top_level_fields:31:5: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_top_level_fields:31:5: 'if' can't be used as an identifier because it's a keyword.
 int if = 42;
     ^^
 
-parser/error_recovery/keyword_named_top_level_fields:34:5: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_top_level_fields:34:5: 'in' can't be used as an identifier because it's a keyword.
 int in = 42;
     ^^
 
-parser/error_recovery/keyword_named_top_level_fields:37:5: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_top_level_fields:37:5: 'is' can't be used as an identifier because it's a keyword.
 int is = 42;
     ^^
 
-parser/error_recovery/keyword_named_top_level_fields:42:5: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_top_level_fields:42:5: 'new' can't be used as an identifier because it's a keyword.
 int new = 42;
     ^^^
 
-parser/error_recovery/keyword_named_top_level_fields:43:5: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_top_level_fields:43:5: 'null' can't be used as an identifier because it's a keyword.
 int null = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:51:5: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_top_level_fields:51:5: 'rethrow' can't be used as an identifier because it's a keyword.
 int rethrow = 42;
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:52:5: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_top_level_fields:52:5: 'return' can't be used as an identifier because it's a keyword.
 int return = 42;
     ^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:57:5: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_top_level_fields:57:5: 'super' can't be used as an identifier because it's a keyword.
 int super = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:58:5: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_top_level_fields:58:5: 'switch' can't be used as an identifier because it's a keyword.
 int switch = 42;
     ^^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:60:5: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_top_level_fields:60:5: 'this' can't be used as an identifier because it's a keyword.
 int this = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:61:5: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_top_level_fields:61:5: 'throw' can't be used as an identifier because it's a keyword.
 int throw = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:62:5: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_top_level_fields:62:5: 'true' can't be used as an identifier because it's a keyword.
 int true = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:63:5: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_top_level_fields:63:5: 'try' can't be used as an identifier because it's a keyword.
 int try = 42;
     ^^^
 
-parser/error_recovery/keyword_named_top_level_fields:65:5: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_top_level_fields:65:5: 'var' can't be used as an identifier because it's a keyword.
 int var = 42;
     ^^^
 
-parser/error_recovery/keyword_named_top_level_fields:66:5: Expected an identifier, but got 'void'.
+parser/error_recovery/keyword_named_top_level_fields:66:5: 'void' can't be used as an identifier because it's a keyword.
 int void = 42;
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:67:5: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_top_level_fields:67:5: 'while' can't be used as an identifier because it's a keyword.
 int while = 42;
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_fields:68:5: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_top_level_fields:68:5: 'with' can't be used as an identifier because it's a keyword.
 int with = 42;
     ^^^^
 
@@ -166,7 +166,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(assert)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
       handleIdentifier(assert, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -206,7 +206,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(break)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
       handleIdentifier(break, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -220,7 +220,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(case)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
       handleIdentifier(case, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -234,7 +234,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(catch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
       handleIdentifier(catch, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -248,7 +248,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(class)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
       handleIdentifier(class, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -262,7 +262,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(const)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
       handleIdentifier(const, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -276,7 +276,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(continue)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
       handleIdentifier(continue, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -303,7 +303,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(default)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
       handleIdentifier(default, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -330,7 +330,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(do)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
       handleIdentifier(do, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -357,7 +357,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(else)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
       handleIdentifier(else, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -371,7 +371,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(enum)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
       handleIdentifier(enum, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -398,7 +398,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(extends)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
       handleIdentifier(extends, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -451,7 +451,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(false)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
       handleIdentifier(false, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -465,7 +465,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(final)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
       handleIdentifier(final, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -479,7 +479,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(finally)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
       handleIdentifier(finally, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -493,7 +493,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(for)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
       handleIdentifier(for, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -546,7 +546,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(if)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
       handleIdentifier(if, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -586,7 +586,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(in)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
       handleIdentifier(in, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -626,7 +626,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(is)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
       handleIdentifier(is, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -692,7 +692,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(new)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
       handleIdentifier(new, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -706,7 +706,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(null)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
       handleIdentifier(null, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -811,7 +811,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(rethrow)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -825,7 +825,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(return)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
       handleIdentifier(return, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -891,7 +891,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(super)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
       handleIdentifier(super, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -905,7 +905,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(switch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
       handleIdentifier(switch, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -932,7 +932,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(this)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
       handleIdentifier(this, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -946,7 +946,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(throw)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
       handleIdentifier(throw, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -960,7 +960,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(true)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
       handleIdentifier(true, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -974,7 +974,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(try)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
       handleIdentifier(try, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1001,7 +1001,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(var)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
       handleIdentifier(var, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1015,7 +1015,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(void)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
       handleIdentifier(void, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1029,7 +1029,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(while)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
       handleIdentifier(while, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
@@ -1043,7 +1043,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(42)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
index fc69737..b6db767 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_fields.dart.intertwined.expect
@@ -65,7 +65,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
           listener: handleIdentifier(assert, topLevelVariableDeclaration)
         parseFieldInitializerOpt(assert, assert, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -141,7 +141,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
           listener: handleIdentifier(break, topLevelVariableDeclaration)
         parseFieldInitializerOpt(break, break, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -169,7 +169,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
           listener: handleIdentifier(case, topLevelVariableDeclaration)
         parseFieldInitializerOpt(case, case, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -197,7 +197,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
           listener: handleIdentifier(catch, topLevelVariableDeclaration)
         parseFieldInitializerOpt(catch, catch, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -225,7 +225,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
           listener: handleIdentifier(class, topLevelVariableDeclaration)
         parseFieldInitializerOpt(class, class, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -253,7 +253,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
           listener: handleIdentifier(const, topLevelVariableDeclaration)
         parseFieldInitializerOpt(const, const, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -281,7 +281,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
           listener: handleIdentifier(continue, topLevelVariableDeclaration)
         parseFieldInitializerOpt(continue, continue, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -333,7 +333,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
           listener: handleIdentifier(default, topLevelVariableDeclaration)
         parseFieldInitializerOpt(default, default, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -385,7 +385,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
           listener: handleIdentifier(do, topLevelVariableDeclaration)
         parseFieldInitializerOpt(do, do, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -437,7 +437,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
           listener: handleIdentifier(else, topLevelVariableDeclaration)
         parseFieldInitializerOpt(else, else, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -465,7 +465,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
           listener: handleIdentifier(enum, topLevelVariableDeclaration)
         parseFieldInitializerOpt(enum, enum, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -517,7 +517,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
           listener: handleIdentifier(extends, topLevelVariableDeclaration)
         parseFieldInitializerOpt(extends, extends, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -617,7 +617,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
           listener: handleIdentifier(false, topLevelVariableDeclaration)
         parseFieldInitializerOpt(false, false, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -645,7 +645,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
           listener: handleIdentifier(final, topLevelVariableDeclaration)
         parseFieldInitializerOpt(final, final, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -673,7 +673,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
           listener: handleIdentifier(finally, topLevelVariableDeclaration)
         parseFieldInitializerOpt(finally, finally, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -701,7 +701,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
           listener: handleIdentifier(for, topLevelVariableDeclaration)
         parseFieldInitializerOpt(for, for, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -801,7 +801,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
           listener: handleIdentifier(if, topLevelVariableDeclaration)
         parseFieldInitializerOpt(if, if, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -877,7 +877,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
           listener: handleIdentifier(in, topLevelVariableDeclaration)
         parseFieldInitializerOpt(in, in, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -953,7 +953,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
           listener: handleIdentifier(is, topLevelVariableDeclaration)
         parseFieldInitializerOpt(is, is, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1077,7 +1077,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
           listener: handleIdentifier(new, topLevelVariableDeclaration)
         parseFieldInitializerOpt(new, new, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1105,7 +1105,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
           listener: handleIdentifier(null, topLevelVariableDeclaration)
         parseFieldInitializerOpt(null, null, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1301,7 +1301,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, topLevelVariableDeclaration)
         parseFieldInitializerOpt(rethrow, rethrow, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1329,7 +1329,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
           listener: handleIdentifier(return, topLevelVariableDeclaration)
         parseFieldInitializerOpt(return, return, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1453,7 +1453,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
           listener: handleIdentifier(super, topLevelVariableDeclaration)
         parseFieldInitializerOpt(super, super, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1481,7 +1481,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
           listener: handleIdentifier(switch, topLevelVariableDeclaration)
         parseFieldInitializerOpt(switch, switch, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1531,7 +1531,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, false)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
           listener: handleIdentifier(this, topLevelVariableDeclaration)
         parseFieldInitializerOpt(this, this, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1559,7 +1559,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
           listener: handleIdentifier(throw, topLevelVariableDeclaration)
         parseFieldInitializerOpt(throw, throw, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1587,7 +1587,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
           listener: handleIdentifier(true, topLevelVariableDeclaration)
         parseFieldInitializerOpt(true, true, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1615,7 +1615,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
           listener: handleIdentifier(try, topLevelVariableDeclaration)
         parseFieldInitializerOpt(try, try, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1667,7 +1667,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
           listener: handleIdentifier(var, topLevelVariableDeclaration)
         parseFieldInitializerOpt(var, var, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1695,7 +1695,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
           listener: handleIdentifier(void, topLevelVariableDeclaration)
         parseFieldInitializerOpt(void, void, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1723,7 +1723,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
           listener: handleIdentifier(while, topLevelVariableDeclaration)
         parseFieldInitializerOpt(while, while, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
@@ -1751,7 +1751,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, topLevelVariableDeclaration)
         parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
index df30d32..ab9b7d5 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.expect
@@ -1,6 +1,6 @@
 Problems reported:
 
-parser/error_recovery/keyword_named_top_level_methods:11:5: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_top_level_methods:11:5: 'assert' can't be used as an identifier because it's a keyword.
 int assert(int x) {
     ^^^^^^
 
@@ -8,7 +8,7 @@
   return assert(x-1) + 1;
          ^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:26:5: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_top_level_methods:26:5: 'break' can't be used as an identifier because it's a keyword.
 int break(int x) {
     ^^^^^
 
@@ -28,31 +28,31 @@
   return break(x-1) + 1;
          ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:31:5: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_top_level_methods:31:5: 'case' can't be used as an identifier because it's a keyword.
 int case(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:33:10: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_top_level_methods:33:10: 'case' can't be used as an identifier because it's a keyword.
   return case(x-1) + 1;
          ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:36:5: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_top_level_methods:36:5: 'catch' can't be used as an identifier because it's a keyword.
 int catch(int x) {
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:38:10: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_top_level_methods:38:10: 'catch' can't be used as an identifier because it's a keyword.
   return catch(x-1) + 1;
          ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:41:5: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_top_level_methods:41:5: 'class' can't be used as an identifier because it's a keyword.
 int class(int x) {
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:43:10: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_top_level_methods:43:10: 'class' can't be used as an identifier because it's a keyword.
   return class(x-1) + 1;
          ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:46:5: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_top_level_methods:46:5: 'const' can't be used as an identifier because it's a keyword.
 int const(int x) {
     ^^^^^
 
@@ -60,7 +60,7 @@
   return const(x-1) + 1;
               ^
 
-parser/error_recovery/keyword_named_top_level_methods:51:5: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_top_level_methods:51:5: 'continue' can't be used as an identifier because it's a keyword.
 int continue(int x) {
     ^^^^^^^^
 
@@ -80,15 +80,15 @@
   return continue(x-1) + 1;
          ^^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:61:5: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_top_level_methods:61:5: 'default' can't be used as an identifier because it's a keyword.
 int default(int x) {
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:63:10: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_top_level_methods:63:10: 'default' can't be used as an identifier because it's a keyword.
   return default(x-1) + 1;
          ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:71:5: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_top_level_methods:71:5: 'do' can't be used as an identifier because it's a keyword.
 int do(int x) {
     ^^
 
@@ -116,7 +116,7 @@
 }
 ^
 
-parser/error_recovery/keyword_named_top_level_methods:81:5: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_top_level_methods:81:5: 'else' can't be used as an identifier because it's a keyword.
 int else(int x) {
     ^^^^
 
@@ -140,27 +140,27 @@
   return else(x-1) + 1;
          ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:86:5: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_top_level_methods:86:5: 'enum' can't be used as an identifier because it's a keyword.
 int enum(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:88:10: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_top_level_methods:88:10: 'enum' can't be used as an identifier because it's a keyword.
   return enum(x-1) + 1;
          ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:96:5: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_top_level_methods:96:5: 'extends' can't be used as an identifier because it's a keyword.
 int extends(int x) {
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:98:10: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_top_level_methods:98:10: 'extends' can't be used as an identifier because it's a keyword.
   return extends(x-1) + 1;
          ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:116:5: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_top_level_methods:116:5: 'false' can't be used as an identifier because it's a keyword.
 int false(int x) {
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:121:5: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_top_level_methods:121:5: 'final' can't be used as an identifier because it's a keyword.
 int final(int x) {
     ^^^^^
 
@@ -200,15 +200,15 @@
   return final(x-1) + 1;
                     ^
 
-parser/error_recovery/keyword_named_top_level_methods:126:5: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_top_level_methods:126:5: 'finally' can't be used as an identifier because it's a keyword.
 int finally(int x) {
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:128:10: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_top_level_methods:128:10: 'finally' can't be used as an identifier because it's a keyword.
   return finally(x-1) + 1;
          ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:131:5: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_top_level_methods:131:5: 'for' can't be used as an identifier because it's a keyword.
 int for(int x) {
     ^^^
 
@@ -236,7 +236,7 @@
   return for(x-1) + 1;
                   ^
 
-parser/error_recovery/keyword_named_top_level_methods:151:5: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_top_level_methods:151:5: 'if' can't be used as an identifier because it's a keyword.
 int if(int x) {
     ^^
 
@@ -252,15 +252,15 @@
   return if(x-1) + 1;
                  ^
 
-parser/error_recovery/keyword_named_top_level_methods:166:5: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_top_level_methods:166:5: 'in' can't be used as an identifier because it's a keyword.
 int in(int x) {
     ^^
 
-parser/error_recovery/keyword_named_top_level_methods:168:10: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_top_level_methods:168:10: 'in' can't be used as an identifier because it's a keyword.
   return in(x-1) + 1;
          ^^
 
-parser/error_recovery/keyword_named_top_level_methods:181:5: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_top_level_methods:181:5: 'is' can't be used as an identifier because it's a keyword.
 int is(int x) {
     ^^
 
@@ -276,7 +276,7 @@
   return is(x-1) + 1;
            ^
 
-parser/error_recovery/keyword_named_top_level_methods:206:5: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_top_level_methods:206:5: 'new' can't be used as an identifier because it's a keyword.
 int new(int x) {
     ^^^
 
@@ -284,19 +284,19 @@
   return new(x-1) + 1;
             ^
 
-parser/error_recovery/keyword_named_top_level_methods:211:5: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_top_level_methods:211:5: 'null' can't be used as an identifier because it's a keyword.
 int null(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:251:5: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_top_level_methods:251:5: 'rethrow' can't be used as an identifier because it's a keyword.
 int rethrow(int x) {
     ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:253:10: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_top_level_methods:253:10: 'rethrow' can't be used as an identifier because it's a keyword.
   return rethrow(x-1) + 1;
          ^^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:256:5: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_top_level_methods:256:5: 'return' can't be used as an identifier because it's a keyword.
 int return(int x) {
     ^^^^^^
 
@@ -304,11 +304,11 @@
   return return(x-1) + 1;
          ^^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:281:5: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_top_level_methods:281:5: 'super' can't be used as an identifier because it's a keyword.
 int super(int x) {
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:286:5: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_top_level_methods:286:5: 'switch' can't be used as an identifier because it's a keyword.
 int switch(int x) {
     ^^^^^^
 
@@ -328,19 +328,19 @@
   return switch(x-1) + 1;
                      ^
 
-parser/error_recovery/keyword_named_top_level_methods:296:5: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_top_level_methods:296:5: 'this' can't be used as an identifier because it's a keyword.
 int this(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:301:5: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_top_level_methods:301:5: 'throw' can't be used as an identifier because it's a keyword.
 int throw(int x) {
     ^^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:306:5: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_top_level_methods:306:5: 'true' can't be used as an identifier because it's a keyword.
 int true(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:311:5: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_top_level_methods:311:5: 'try' can't be used as an identifier because it's a keyword.
 int try(int x) {
     ^^^
 
@@ -360,7 +360,7 @@
   return try(x-1) + 1;
          ^^^
 
-parser/error_recovery/keyword_named_top_level_methods:321:5: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_top_level_methods:321:5: 'var' can't be used as an identifier because it's a keyword.
 int var(int x) {
     ^^^
 
@@ -400,7 +400,7 @@
   return var(x-1) + 1;
                   ^
 
-parser/error_recovery/keyword_named_top_level_methods:326:5: Expected an identifier, but got 'void'.
+parser/error_recovery/keyword_named_top_level_methods:326:5: 'void' can't be used as an identifier because it's a keyword.
 int void(int x) {
     ^^^^
 
@@ -440,7 +440,7 @@
   return void(x-1) + 1;
                    ^
 
-parser/error_recovery/keyword_named_top_level_methods:331:5: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_top_level_methods:331:5: 'while' can't be used as an identifier because it's a keyword.
 int while(int x) {
     ^^^^^
 
@@ -456,11 +456,11 @@
   return while(x-1) + 1;
                     ^
 
-parser/error_recovery/keyword_named_top_level_methods:336:5: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_top_level_methods:336:5: 'with' can't be used as an identifier because it's a keyword.
 int with(int x) {
     ^^^^
 
-parser/error_recovery/keyword_named_top_level_methods:338:10: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_top_level_methods:338:10: 'with' can't be used as an identifier because it's a keyword.
   return with(x-1) + 1;
          ^^^^
 
@@ -586,7 +586,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(assert)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
       handleIdentifier(assert, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -756,7 +756,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(break)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
       handleIdentifier(break, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -788,7 +788,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
           handleIdentifier(, expression)
           handleNoTypeArguments(break)
           handleNoArguments(break)
@@ -820,7 +820,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(case)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
       handleIdentifier(case, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -852,7 +852,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
           handleIdentifier(case, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -879,7 +879,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(catch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
       handleIdentifier(catch, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -911,7 +911,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
           handleIdentifier(catch, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -938,7 +938,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(class)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
       handleIdentifier(class, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -970,7 +970,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
           handleIdentifier(class, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -997,7 +997,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(const)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
       handleIdentifier(const, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1030,7 +1030,7 @@
         endIfStatement(if, null)
         beginReturnStatement(return)
           beginConstExpression(const)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
             handleIdentifier(, constructorReference)
             beginConstructorReference()
               handleNoTypeArguments(()
@@ -1060,7 +1060,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(continue)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
       handleIdentifier(continue, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1092,7 +1092,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
           handleIdentifier(, expression)
           handleNoTypeArguments(continue)
           handleNoArguments(continue)
@@ -1181,7 +1181,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(default)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
       handleIdentifier(default, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1213,7 +1213,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
           handleIdentifier(default, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1297,7 +1297,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(do)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
       handleIdentifier(do, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1329,7 +1329,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
           handleIdentifier(, expression)
           handleNoTypeArguments(do)
           handleNoArguments(do)
@@ -1353,7 +1353,7 @@
           endDoWhileStatementBody(;)
           handleRecoverableError(Message[ExpectedButGot, Expected 'while' before this., null, {string: while}], }, })
           handleRecoverableError(Message[ExpectedToken, Expected to find '('., null, {string: (}], }, })
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
@@ -1428,7 +1428,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(else)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
       handleIdentifier(else, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1460,14 +1460,14 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
           handleIdentifier(, expression)
           handleNoTypeArguments(else)
           handleNoArguments(else)
           handleSend(, else)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], else, else)
         endReturnStatement(true, return, ;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
         handleIdentifier(, expression)
         handleNoTypeArguments(else)
         handleNoArguments(else)
@@ -1497,7 +1497,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(enum)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
       handleIdentifier(enum, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1529,7 +1529,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
           handleIdentifier(enum, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1613,7 +1613,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(extends)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
       handleIdentifier(extends, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1645,7 +1645,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
           handleIdentifier(extends, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -1843,7 +1843,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(false)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
       handleIdentifier(false, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1901,7 +1901,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(final)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
       handleIdentifier(final, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -1933,7 +1933,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
           handleIdentifier(, expression)
           handleNoTypeArguments(final)
           handleNoArguments(final)
@@ -1944,7 +1944,7 @@
         endMetadataStar(0)
         handleNoType(final)
         beginVariablesDeclaration((, null, final)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -1960,7 +1960,7 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
@@ -1987,7 +1987,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(finally)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
       handleIdentifier(finally, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2019,7 +2019,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
           handleIdentifier(finally, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -2046,7 +2046,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(for)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
       handleIdentifier(for, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2078,7 +2078,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
           handleIdentifier(, expression)
           handleNoTypeArguments(for)
           handleNoArguments(for)
@@ -2095,7 +2095,7 @@
           endBinaryExpression(-)
           handleForInitializerExpressionStatement(1, false)
           handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
           handleIdentifier(, expression)
           handleNoTypeArguments())
           handleNoArguments())
@@ -2296,7 +2296,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(if)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
       handleIdentifier(if, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2328,7 +2328,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
           handleIdentifier(, expression)
           handleNoTypeArguments(if)
           handleNoArguments(if)
@@ -2480,7 +2480,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(in)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
       handleIdentifier(in, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2512,7 +2512,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
           handleIdentifier(in, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -2653,7 +2653,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(is)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
       handleIdentifier(is, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2685,7 +2685,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
           handleIdentifier(, expression)
           handleNoTypeArguments(is)
           handleNoArguments(is)
@@ -2949,7 +2949,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(new)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
       handleIdentifier(new, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -2982,7 +2982,7 @@
         endIfStatement(if, null)
         beginReturnStatement(return)
           beginNewExpression(new)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
             handleIdentifier(, constructorReference)
             beginConstructorReference()
               handleNoTypeArguments(()
@@ -3012,7 +3012,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(null)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
       handleIdentifier(null, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3469,7 +3469,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(rethrow)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3501,7 +3501,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
           handleIdentifier(rethrow, expression)
           handleNoTypeArguments(()
           beginArguments(()
@@ -3528,7 +3528,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(return)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
       handleIdentifier(return, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3811,7 +3811,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(super)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
       handleIdentifier(super, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3869,7 +3869,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(switch)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
       handleIdentifier(switch, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -3901,7 +3901,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
           handleIdentifier(, expression)
           handleNoTypeArguments(switch)
           handleNoArguments(switch)
@@ -3997,7 +3997,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(this)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
       handleIdentifier(this, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4055,7 +4055,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(throw)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
       handleIdentifier(throw, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4110,7 +4110,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(true)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
       handleIdentifier(true, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4168,7 +4168,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(try)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
       handleIdentifier(try, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4200,7 +4200,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
           handleIdentifier(, expression)
           handleNoTypeArguments(try)
           handleNoArguments(try)
@@ -4292,7 +4292,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(var)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
       handleIdentifier(var, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4324,7 +4324,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
           handleIdentifier(, expression)
           handleNoTypeArguments(var)
           handleNoArguments(var)
@@ -4335,7 +4335,7 @@
         endMetadataStar(0)
         handleNoType(var)
         beginVariablesDeclaration((, null, var)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -4351,7 +4351,7 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
@@ -4378,7 +4378,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(void)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
       handleIdentifier(void, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4410,7 +4410,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
           handleIdentifier(, expression)
           handleNoTypeArguments(void)
           handleNoArguments(void)
@@ -4421,7 +4421,7 @@
         endMetadataStar(0)
         handleVoidKeyword(void)
         beginVariablesDeclaration((, null, null)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
           handleIdentifier(, localVariableDeclaration)
           beginInitializedIdentifier()
             handleNoVariableInitializer()
@@ -4437,7 +4437,7 @@
         endBinaryExpression(-)
         handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], 1, 1)
         handleExpressionStatement(;)
-        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+        handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
         handleIdentifier(, expression)
         handleNoTypeArguments())
         handleNoArguments())
@@ -4464,7 +4464,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(while)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
       handleIdentifier(while, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4496,7 +4496,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
           handleIdentifier(, expression)
           handleNoTypeArguments(while)
           handleNoArguments(while)
@@ -4534,7 +4534,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -4566,7 +4566,7 @@
           endThenStatement(;)
         endIfStatement(if, null)
         beginReturnStatement(return)
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+          handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           handleIdentifier(with, expression)
           handleNoTypeArguments(()
           beginArguments(()
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
index f6e0e65..1ce425d 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_top_level_methods.dart.intertwined.expect
@@ -291,7 +291,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
           listener: handleIdentifier(assert, topLevelFunctionDeclaration)
         parseMethodTypeVar(assert)
           listener: handleNoTypeVariables(()
@@ -701,7 +701,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
           listener: handleIdentifier(break, topLevelFunctionDeclaration)
         parseMethodTypeVar(break)
           listener: handleNoTypeVariables(()
@@ -784,7 +784,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., Try inserting an identifier before 'break'., {token: break}], break, break)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(break)
@@ -873,7 +873,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
           listener: handleIdentifier(case, topLevelFunctionDeclaration)
         parseMethodTypeVar(case)
           listener: handleNoTypeVariables(()
@@ -956,7 +956,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
                             listener: handleIdentifier(case, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(case)
@@ -1013,7 +1013,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
           listener: handleIdentifier(catch, topLevelFunctionDeclaration)
         parseMethodTypeVar(catch)
           listener: handleNoTypeVariables(()
@@ -1096,7 +1096,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
                             listener: handleIdentifier(catch, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(catch)
@@ -1153,7 +1153,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
           listener: handleIdentifier(class, topLevelFunctionDeclaration)
         parseMethodTypeVar(class)
           listener: handleNoTypeVariables(()
@@ -1236,7 +1236,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
                             listener: handleIdentifier(class, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(class)
@@ -1293,7 +1293,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
           listener: handleIdentifier(const, topLevelFunctionDeclaration)
         parseMethodTypeVar(const)
           listener: handleNoTypeVariables(()
@@ -1376,9 +1376,9 @@
                           listener: beginConstExpression(const)
                           parseConstructorReference(const, null)
                             ensureIdentifier(const, constructorReference)
-                              insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], messageOnToken: null)
-                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}])
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                              insertSyntheticIdentifier(const, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
+                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                                 rewriter()
                               listener: handleIdentifier(, constructorReference)
                             listener: beginConstructorReference()
@@ -1439,7 +1439,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
           listener: handleIdentifier(continue, topLevelFunctionDeclaration)
         parseMethodTypeVar(continue)
           listener: handleNoTypeVariables(()
@@ -1522,7 +1522,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., Try inserting an identifier before 'continue'., {token: continue}], continue, continue)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(continue)
@@ -1748,7 +1748,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
           listener: handleIdentifier(default, topLevelFunctionDeclaration)
         parseMethodTypeVar(default)
           listener: handleNoTypeVariables(()
@@ -1831,7 +1831,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
                             listener: handleIdentifier(default, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(default)
@@ -2025,7 +2025,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
           listener: handleIdentifier(do, topLevelFunctionDeclaration)
         parseMethodTypeVar(do)
           listener: handleNoTypeVariables(()
@@ -2108,7 +2108,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., Try inserting an identifier before 'do'., {token: do}], do, do)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(do)
@@ -2187,7 +2187,7 @@
                             parseSend((, expression)
                               ensureIdentifier((, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -2357,7 +2357,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
           listener: handleIdentifier(else, topLevelFunctionDeclaration)
         parseMethodTypeVar(else)
           listener: handleNoTypeVariables(()
@@ -2440,7 +2440,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(else)
@@ -2468,7 +2468,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., Try inserting an identifier before 'else'., {token: else}], else, else)
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments(else)
@@ -2546,7 +2546,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
           listener: handleIdentifier(enum, topLevelFunctionDeclaration)
         parseMethodTypeVar(enum)
           listener: handleNoTypeVariables(()
@@ -2629,7 +2629,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
                             listener: handleIdentifier(enum, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(enum)
@@ -2823,7 +2823,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
           listener: handleIdentifier(extends, topLevelFunctionDeclaration)
         parseMethodTypeVar(extends)
           listener: handleNoTypeVariables(()
@@ -2906,7 +2906,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
                             listener: handleIdentifier(extends, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(extends)
@@ -3374,7 +3374,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
           listener: handleIdentifier(false, topLevelFunctionDeclaration)
         parseMethodTypeVar(false)
           listener: handleNoTypeVariables(()
@@ -3510,7 +3510,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
           listener: handleIdentifier(final, topLevelFunctionDeclaration)
         parseMethodTypeVar(final)
           listener: handleNoTypeVariables(()
@@ -3593,7 +3593,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., Try inserting an identifier before 'final'., {token: final}], final, final)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(final)
@@ -3619,7 +3619,7 @@
                   parseOptionallyInitializedIdentifier(final)
                     ensureIdentifier(final, localVariableDeclaration)
                       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                       rewriter()
                       listener: handleIdentifier(, localVariableDeclaration)
                     listener: beginInitializedIdentifier()
@@ -3675,7 +3675,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -3740,7 +3740,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
           listener: handleIdentifier(finally, topLevelFunctionDeclaration)
         parseMethodTypeVar(finally)
           listener: handleNoTypeVariables(()
@@ -3823,7 +3823,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
                             listener: handleIdentifier(finally, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(finally)
@@ -3880,7 +3880,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
           listener: handleIdentifier(for, topLevelFunctionDeclaration)
         parseMethodTypeVar(for)
           listener: handleNoTypeVariables(()
@@ -3963,7 +3963,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., Try inserting an identifier before 'for'., {token: for}], for, for)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(for)
@@ -4019,7 +4019,7 @@
                               parseSend(;, expression)
                                 ensureIdentifier(;, expression)
                                   reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                   rewriter()
                                   listener: handleIdentifier(, expression)
                                 listener: handleNoTypeArguments())
@@ -4496,7 +4496,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
           listener: handleIdentifier(if, topLevelFunctionDeclaration)
         parseMethodTypeVar(if)
           listener: handleNoTypeVariables(()
@@ -4579,7 +4579,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., Try inserting an identifier before 'if'., {token: if}], if, if)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(if)
@@ -4947,7 +4947,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
           listener: handleIdentifier(in, topLevelFunctionDeclaration)
         parseMethodTypeVar(in)
           listener: handleNoTypeVariables(()
@@ -5030,7 +5030,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
                             listener: handleIdentifier(in, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(in)
@@ -5361,7 +5361,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
           listener: handleIdentifier(is, topLevelFunctionDeclaration)
         parseMethodTypeVar(is)
           listener: handleNoTypeVariables(()
@@ -5444,7 +5444,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., Try inserting an identifier before 'is'., {token: is}], is, is)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(is)
@@ -6081,7 +6081,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
           listener: handleIdentifier(new, topLevelFunctionDeclaration)
         parseMethodTypeVar(new)
           listener: handleNoTypeVariables(()
@@ -6164,9 +6164,9 @@
                           listener: beginNewExpression(new)
                           parseConstructorReference(new, null)
                             ensureIdentifier(new, constructorReference)
-                              insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], messageOnToken: null)
-                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}])
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                              insertSyntheticIdentifier(new, constructorReference, message: Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], messageOnToken: null)
+                                reportRecoverableError((, Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}])
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                                 rewriter()
                               listener: handleIdentifier(, constructorReference)
                             listener: beginConstructorReference()
@@ -6227,7 +6227,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
           listener: handleIdentifier(null, topLevelFunctionDeclaration)
         parseMethodTypeVar(null)
           listener: handleNoTypeVariables(()
@@ -7322,7 +7322,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, topLevelFunctionDeclaration)
         parseMethodTypeVar(rethrow)
           listener: handleNoTypeVariables(()
@@ -7405,7 +7405,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
                             listener: handleIdentifier(rethrow, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(rethrow)
@@ -7462,7 +7462,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
           listener: handleIdentifier(return, topLevelFunctionDeclaration)
         parseMethodTypeVar(return)
           listener: handleNoTypeVariables(()
@@ -8147,7 +8147,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
           listener: handleIdentifier(super, topLevelFunctionDeclaration)
         parseMethodTypeVar(super)
           listener: handleNoTypeVariables(()
@@ -8282,7 +8282,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
           listener: handleIdentifier(switch, topLevelFunctionDeclaration)
         parseMethodTypeVar(switch)
           listener: handleNoTypeVariables(()
@@ -8365,7 +8365,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., Try inserting an identifier before 'switch'., {token: switch}], switch, switch)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(switch)
@@ -8603,7 +8603,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, false)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
           listener: handleIdentifier(this, topLevelFunctionDeclaration)
         parseMethodTypeVar(this)
           listener: handleNoTypeVariables(()
@@ -8738,7 +8738,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
           listener: handleIdentifier(throw, topLevelFunctionDeclaration)
         parseMethodTypeVar(throw)
           listener: handleNoTypeVariables(()
@@ -8874,7 +8874,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
           listener: handleIdentifier(true, topLevelFunctionDeclaration)
         parseMethodTypeVar(true)
           listener: handleNoTypeVariables(()
@@ -9010,7 +9010,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
           listener: handleIdentifier(try, topLevelFunctionDeclaration)
         parseMethodTypeVar(try)
           listener: handleNoTypeVariables(()
@@ -9093,7 +9093,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., Try inserting an identifier before 'try'., {token: try}], try, try)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(try)
@@ -9325,7 +9325,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
           listener: handleIdentifier(var, topLevelFunctionDeclaration)
         parseMethodTypeVar(var)
           listener: handleNoTypeVariables(()
@@ -9408,7 +9408,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., Try inserting an identifier before 'var'., {token: var}], var, var)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(var)
@@ -9434,7 +9434,7 @@
                   parseOptionallyInitializedIdentifier(var)
                     ensureIdentifier(var, localVariableDeclaration)
                       reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                        listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                       rewriter()
                       listener: handleIdentifier(, localVariableDeclaration)
                     listener: beginInitializedIdentifier()
@@ -9490,7 +9490,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -9555,7 +9555,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
           listener: handleIdentifier(void, topLevelFunctionDeclaration)
         parseMethodTypeVar(void)
           listener: handleNoTypeVariables(()
@@ -9638,7 +9638,7 @@
                           parseSend(return, expression)
                             ensureIdentifier(return, expression)
                               reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+                                listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., Try inserting an identifier before 'void'., {token: void}], void, void)
                               rewriter()
                               listener: handleIdentifier(, expression)
                             listener: handleNoTypeArguments(void)
@@ -9665,7 +9665,7 @@
                     parseOptionallyInitializedIdentifier(void)
                       ensureIdentifier(void, localVariableDeclaration)
                         reportRecoverableErrorWithToken((, Instance of 'Template<(Token) => Message>')
-                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., null, {token: (}], (, ()
+                          listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '('., Try inserting an identifier before '('., {token: (}], (, ()
                         rewriter()
                         listener: handleIdentifier(, localVariableDeclaration)
                       listener: beginInitializedIdentifier()
@@ -9721,7 +9721,7 @@
                             parseSend(;, expression)
                               ensureIdentifier(;, expression)
                                 reportRecoverableErrorWithToken(), Instance of 'Template<(Token) => Message>')
-                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., null, {token: )}], ), ))
+                                  listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ')'., Try inserting an identifier before ')'., {token: )}], ), ))
                                 rewriter()
                                 listener: handleIdentifier(, expression)
                               listener: handleNoTypeArguments())
@@ -9786,7 +9786,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
           listener: handleIdentifier(while, topLevelFunctionDeclaration)
         parseMethodTypeVar(while)
           listener: handleNoTypeVariables(()
@@ -9869,7 +9869,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., Try inserting an identifier before 'while'., {token: while}], while, while)
                             rewriter()
                             listener: handleIdentifier(, expression)
                           listener: handleNoTypeArguments(while)
@@ -9963,7 +9963,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, topLevelFunctionDeclaration)
         parseMethodTypeVar(with)
           listener: handleNoTypeVariables(()
@@ -10046,7 +10046,7 @@
                         parseSend(return, expression)
                           ensureIdentifier(return, expression)
                             reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                              listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                             listener: handleIdentifier(with, expression)
                           listener: handleNoTypeArguments(()
                           parseArgumentsOpt(with)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
index 22a636f..f7f2800 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.expect
@@ -1,430 +1,430 @@
 Problems reported:
 
-parser/error_recovery/keyword_named_typedefs:1:14: Expected an identifier, but got 'abstract'.
+parser/error_recovery/keyword_named_typedefs:1:14: 'abstract' can't be used as an identifier because it's a keyword.
 typedef void abstract();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:2:9: Expected an identifier, but got 'abstract'.
+parser/error_recovery/keyword_named_typedefs:2:9: 'abstract' can't be used as an identifier because it's a keyword.
 typedef abstract = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:3:14: Expected an identifier, but got 'as'.
+parser/error_recovery/keyword_named_typedefs:3:14: 'as' can't be used as an identifier because it's a keyword.
 typedef void as();
              ^^
 
-parser/error_recovery/keyword_named_typedefs:4:9: Expected an identifier, but got 'as'.
+parser/error_recovery/keyword_named_typedefs:4:9: 'as' can't be used as an identifier because it's a keyword.
 typedef as = void Function();
         ^^
 
-parser/error_recovery/keyword_named_typedefs:5:14: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_typedefs:5:14: 'assert' can't be used as an identifier because it's a keyword.
 typedef void assert();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:6:9: Expected an identifier, but got 'assert'.
+parser/error_recovery/keyword_named_typedefs:6:9: 'assert' can't be used as an identifier because it's a keyword.
 typedef assert = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:11:14: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_typedefs:11:14: 'break' can't be used as an identifier because it's a keyword.
 typedef void break();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:12:9: Expected an identifier, but got 'break'.
+parser/error_recovery/keyword_named_typedefs:12:9: 'break' can't be used as an identifier because it's a keyword.
 typedef break = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:13:14: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_typedefs:13:14: 'case' can't be used as an identifier because it's a keyword.
 typedef void case();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:14:9: Expected an identifier, but got 'case'.
+parser/error_recovery/keyword_named_typedefs:14:9: 'case' can't be used as an identifier because it's a keyword.
 typedef case = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:15:14: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_typedefs:15:14: 'catch' can't be used as an identifier because it's a keyword.
 typedef void catch();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:16:9: Expected an identifier, but got 'catch'.
+parser/error_recovery/keyword_named_typedefs:16:9: 'catch' can't be used as an identifier because it's a keyword.
 typedef catch = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:17:14: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_typedefs:17:14: 'class' can't be used as an identifier because it's a keyword.
 typedef void class();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:18:9: Expected an identifier, but got 'class'.
+parser/error_recovery/keyword_named_typedefs:18:9: 'class' can't be used as an identifier because it's a keyword.
 typedef class = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:19:14: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_typedefs:19:14: 'const' can't be used as an identifier because it's a keyword.
 typedef void const();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:20:9: Expected an identifier, but got 'const'.
+parser/error_recovery/keyword_named_typedefs:20:9: 'const' can't be used as an identifier because it's a keyword.
 typedef const = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:21:14: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_typedefs:21:14: 'continue' can't be used as an identifier because it's a keyword.
 typedef void continue();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:22:9: Expected an identifier, but got 'continue'.
+parser/error_recovery/keyword_named_typedefs:22:9: 'continue' can't be used as an identifier because it's a keyword.
 typedef continue = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:23:14: Expected an identifier, but got 'covariant'.
+parser/error_recovery/keyword_named_typedefs:23:14: 'covariant' can't be used as an identifier because it's a keyword.
 typedef void covariant();
              ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:24:9: Expected an identifier, but got 'covariant'.
+parser/error_recovery/keyword_named_typedefs:24:9: 'covariant' can't be used as an identifier because it's a keyword.
 typedef covariant = void Function();
         ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:25:14: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_typedefs:25:14: 'default' can't be used as an identifier because it's a keyword.
 typedef void default();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:26:9: Expected an identifier, but got 'default'.
+parser/error_recovery/keyword_named_typedefs:26:9: 'default' can't be used as an identifier because it's a keyword.
 typedef default = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:27:14: Expected an identifier, but got 'deferred'.
+parser/error_recovery/keyword_named_typedefs:27:14: 'deferred' can't be used as an identifier because it's a keyword.
 typedef void deferred();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:28:9: Expected an identifier, but got 'deferred'.
+parser/error_recovery/keyword_named_typedefs:28:9: 'deferred' can't be used as an identifier because it's a keyword.
 typedef deferred = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:29:14: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_typedefs:29:14: 'do' can't be used as an identifier because it's a keyword.
 typedef void do();
              ^^
 
-parser/error_recovery/keyword_named_typedefs:30:9: Expected an identifier, but got 'do'.
+parser/error_recovery/keyword_named_typedefs:30:9: 'do' can't be used as an identifier because it's a keyword.
 typedef do = void Function();
         ^^
 
-parser/error_recovery/keyword_named_typedefs:31:14: Expected an identifier, but got 'dynamic'.
+parser/error_recovery/keyword_named_typedefs:31:14: 'dynamic' can't be used as an identifier because it's a keyword.
 typedef void dynamic();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:32:9: Expected an identifier, but got 'dynamic'.
+parser/error_recovery/keyword_named_typedefs:32:9: 'dynamic' can't be used as an identifier because it's a keyword.
 typedef dynamic = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:33:14: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_typedefs:33:14: 'else' can't be used as an identifier because it's a keyword.
 typedef void else();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:34:9: Expected an identifier, but got 'else'.
+parser/error_recovery/keyword_named_typedefs:34:9: 'else' can't be used as an identifier because it's a keyword.
 typedef else = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:35:14: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_typedefs:35:14: 'enum' can't be used as an identifier because it's a keyword.
 typedef void enum();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:36:9: Expected an identifier, but got 'enum'.
+parser/error_recovery/keyword_named_typedefs:36:9: 'enum' can't be used as an identifier because it's a keyword.
 typedef enum = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:37:14: Expected an identifier, but got 'export'.
+parser/error_recovery/keyword_named_typedefs:37:14: 'export' can't be used as an identifier because it's a keyword.
 typedef void export();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:38:9: Expected an identifier, but got 'export'.
+parser/error_recovery/keyword_named_typedefs:38:9: 'export' can't be used as an identifier because it's a keyword.
 typedef export = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:39:14: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_typedefs:39:14: 'extends' can't be used as an identifier because it's a keyword.
 typedef void extends();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:40:9: Expected an identifier, but got 'extends'.
+parser/error_recovery/keyword_named_typedefs:40:9: 'extends' can't be used as an identifier because it's a keyword.
 typedef extends = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:41:14: Expected an identifier, but got 'extension'.
+parser/error_recovery/keyword_named_typedefs:41:14: 'extension' can't be used as an identifier because it's a keyword.
 typedef void extension();
              ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:42:9: Expected an identifier, but got 'extension'.
+parser/error_recovery/keyword_named_typedefs:42:9: 'extension' can't be used as an identifier because it's a keyword.
 typedef extension = void Function();
         ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:43:14: Expected an identifier, but got 'external'.
+parser/error_recovery/keyword_named_typedefs:43:14: 'external' can't be used as an identifier because it's a keyword.
 typedef void external();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:44:9: Expected an identifier, but got 'external'.
+parser/error_recovery/keyword_named_typedefs:44:9: 'external' can't be used as an identifier because it's a keyword.
 typedef external = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:45:14: Expected an identifier, but got 'factory'.
+parser/error_recovery/keyword_named_typedefs:45:14: 'factory' can't be used as an identifier because it's a keyword.
 typedef void factory();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:46:9: Expected an identifier, but got 'factory'.
+parser/error_recovery/keyword_named_typedefs:46:9: 'factory' can't be used as an identifier because it's a keyword.
 typedef factory = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:47:14: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_typedefs:47:14: 'false' can't be used as an identifier because it's a keyword.
 typedef void false();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:48:9: Expected an identifier, but got 'false'.
+parser/error_recovery/keyword_named_typedefs:48:9: 'false' can't be used as an identifier because it's a keyword.
 typedef false = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:49:14: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_typedefs:49:14: 'final' can't be used as an identifier because it's a keyword.
 typedef void final();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:50:9: Expected an identifier, but got 'final'.
+parser/error_recovery/keyword_named_typedefs:50:9: 'final' can't be used as an identifier because it's a keyword.
 typedef final = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:51:14: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_typedefs:51:14: 'finally' can't be used as an identifier because it's a keyword.
 typedef void finally();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:52:9: Expected an identifier, but got 'finally'.
+parser/error_recovery/keyword_named_typedefs:52:9: 'finally' can't be used as an identifier because it's a keyword.
 typedef finally = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:53:14: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_typedefs:53:14: 'for' can't be used as an identifier because it's a keyword.
 typedef void for();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:54:9: Expected an identifier, but got 'for'.
+parser/error_recovery/keyword_named_typedefs:54:9: 'for' can't be used as an identifier because it's a keyword.
 typedef for = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:55:14: Expected an identifier, but got 'Function'.
+parser/error_recovery/keyword_named_typedefs:55:14: 'Function' can't be used as an identifier because it's a keyword.
 typedef void Function();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:56:9: Expected an identifier, but got 'Function'.
+parser/error_recovery/keyword_named_typedefs:56:9: 'Function' can't be used as an identifier because it's a keyword.
 typedef Function = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:57:14: Expected an identifier, but got 'get'.
+parser/error_recovery/keyword_named_typedefs:57:14: 'get' can't be used as an identifier because it's a keyword.
 typedef void get();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:58:9: Expected an identifier, but got 'get'.
+parser/error_recovery/keyword_named_typedefs:58:9: 'get' can't be used as an identifier because it's a keyword.
 typedef get = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:61:14: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_typedefs:61:14: 'if' can't be used as an identifier because it's a keyword.
 typedef void if();
              ^^
 
-parser/error_recovery/keyword_named_typedefs:62:9: Expected an identifier, but got 'if'.
+parser/error_recovery/keyword_named_typedefs:62:9: 'if' can't be used as an identifier because it's a keyword.
 typedef if = void Function();
         ^^
 
-parser/error_recovery/keyword_named_typedefs:63:14: Expected an identifier, but got 'implements'.
+parser/error_recovery/keyword_named_typedefs:63:14: 'implements' can't be used as an identifier because it's a keyword.
 typedef void implements();
              ^^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:64:9: Expected an identifier, but got 'implements'.
+parser/error_recovery/keyword_named_typedefs:64:9: 'implements' can't be used as an identifier because it's a keyword.
 typedef implements = void Function();
         ^^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:65:14: Expected an identifier, but got 'import'.
+parser/error_recovery/keyword_named_typedefs:65:14: 'import' can't be used as an identifier because it's a keyword.
 typedef void import();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:66:9: Expected an identifier, but got 'import'.
+parser/error_recovery/keyword_named_typedefs:66:9: 'import' can't be used as an identifier because it's a keyword.
 typedef import = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:67:14: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_typedefs:67:14: 'in' can't be used as an identifier because it's a keyword.
 typedef void in();
              ^^
 
-parser/error_recovery/keyword_named_typedefs:68:9: Expected an identifier, but got 'in'.
+parser/error_recovery/keyword_named_typedefs:68:9: 'in' can't be used as an identifier because it's a keyword.
 typedef in = void Function();
         ^^
 
-parser/error_recovery/keyword_named_typedefs:71:14: Expected an identifier, but got 'interface'.
+parser/error_recovery/keyword_named_typedefs:71:14: 'interface' can't be used as an identifier because it's a keyword.
 typedef void interface();
              ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:72:9: Expected an identifier, but got 'interface'.
+parser/error_recovery/keyword_named_typedefs:72:9: 'interface' can't be used as an identifier because it's a keyword.
 typedef interface = void Function();
         ^^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:73:14: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_typedefs:73:14: 'is' can't be used as an identifier because it's a keyword.
 typedef void is();
              ^^
 
-parser/error_recovery/keyword_named_typedefs:74:9: Expected an identifier, but got 'is'.
+parser/error_recovery/keyword_named_typedefs:74:9: 'is' can't be used as an identifier because it's a keyword.
 typedef is = void Function();
         ^^
 
-parser/error_recovery/keyword_named_typedefs:75:14: Expected an identifier, but got 'late'.
+parser/error_recovery/keyword_named_typedefs:75:14: 'late' can't be used as an identifier because it's a keyword.
 typedef void late();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:76:9: Expected an identifier, but got 'late'.
+parser/error_recovery/keyword_named_typedefs:76:9: 'late' can't be used as an identifier because it's a keyword.
 typedef late = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:77:14: Expected an identifier, but got 'library'.
+parser/error_recovery/keyword_named_typedefs:77:14: 'library' can't be used as an identifier because it's a keyword.
 typedef void library();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:78:9: Expected an identifier, but got 'library'.
+parser/error_recovery/keyword_named_typedefs:78:9: 'library' can't be used as an identifier because it's a keyword.
 typedef library = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:79:14: Expected an identifier, but got 'mixin'.
+parser/error_recovery/keyword_named_typedefs:79:14: 'mixin' can't be used as an identifier because it's a keyword.
 typedef void mixin();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:80:9: Expected an identifier, but got 'mixin'.
+parser/error_recovery/keyword_named_typedefs:80:9: 'mixin' can't be used as an identifier because it's a keyword.
 typedef mixin = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:83:14: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_typedefs:83:14: 'new' can't be used as an identifier because it's a keyword.
 typedef void new();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:84:9: Expected an identifier, but got 'new'.
+parser/error_recovery/keyword_named_typedefs:84:9: 'new' can't be used as an identifier because it's a keyword.
 typedef new = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:85:14: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_typedefs:85:14: 'null' can't be used as an identifier because it's a keyword.
 typedef void null();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:86:9: Expected an identifier, but got 'null'.
+parser/error_recovery/keyword_named_typedefs:86:9: 'null' can't be used as an identifier because it's a keyword.
 typedef null = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:91:14: Expected an identifier, but got 'operator'.
+parser/error_recovery/keyword_named_typedefs:91:14: 'operator' can't be used as an identifier because it's a keyword.
 typedef void operator();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:92:9: Expected an identifier, but got 'operator'.
+parser/error_recovery/keyword_named_typedefs:92:9: 'operator' can't be used as an identifier because it's a keyword.
 typedef operator = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:95:14: Expected an identifier, but got 'part'.
+parser/error_recovery/keyword_named_typedefs:95:14: 'part' can't be used as an identifier because it's a keyword.
 typedef void part();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:96:9: Expected an identifier, but got 'part'.
+parser/error_recovery/keyword_named_typedefs:96:9: 'part' can't be used as an identifier because it's a keyword.
 typedef part = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:99:14: Expected an identifier, but got 'required'.
+parser/error_recovery/keyword_named_typedefs:99:14: 'required' can't be used as an identifier because it's a keyword.
 typedef void required();
              ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:100:9: Expected an identifier, but got 'required'.
+parser/error_recovery/keyword_named_typedefs:100:9: 'required' can't be used as an identifier because it's a keyword.
 typedef required = void Function();
         ^^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:101:14: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_typedefs:101:14: 'rethrow' can't be used as an identifier because it's a keyword.
 typedef void rethrow();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:102:9: Expected an identifier, but got 'rethrow'.
+parser/error_recovery/keyword_named_typedefs:102:9: 'rethrow' can't be used as an identifier because it's a keyword.
 typedef rethrow = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:103:14: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_typedefs:103:14: 'return' can't be used as an identifier because it's a keyword.
 typedef void return();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:104:9: Expected an identifier, but got 'return'.
+parser/error_recovery/keyword_named_typedefs:104:9: 'return' can't be used as an identifier because it's a keyword.
 typedef return = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:105:14: Expected an identifier, but got 'set'.
+parser/error_recovery/keyword_named_typedefs:105:14: 'set' can't be used as an identifier because it's a keyword.
 typedef void set();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:106:9: Expected an identifier, but got 'set'.
+parser/error_recovery/keyword_named_typedefs:106:9: 'set' can't be used as an identifier because it's a keyword.
 typedef set = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:111:14: Expected an identifier, but got 'static'.
+parser/error_recovery/keyword_named_typedefs:111:14: 'static' can't be used as an identifier because it's a keyword.
 typedef void static();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:112:9: Expected an identifier, but got 'static'.
+parser/error_recovery/keyword_named_typedefs:112:9: 'static' can't be used as an identifier because it's a keyword.
 typedef static = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:113:14: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_typedefs:113:14: 'super' can't be used as an identifier because it's a keyword.
 typedef void super();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:114:9: Expected an identifier, but got 'super'.
+parser/error_recovery/keyword_named_typedefs:114:9: 'super' can't be used as an identifier because it's a keyword.
 typedef super = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:115:14: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_typedefs:115:14: 'switch' can't be used as an identifier because it's a keyword.
 typedef void switch();
              ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:116:9: Expected an identifier, but got 'switch'.
+parser/error_recovery/keyword_named_typedefs:116:9: 'switch' can't be used as an identifier because it's a keyword.
 typedef switch = void Function();
         ^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:119:14: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_typedefs:119:14: 'this' can't be used as an identifier because it's a keyword.
 typedef void this();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:120:9: Expected an identifier, but got 'this'.
+parser/error_recovery/keyword_named_typedefs:120:9: 'this' can't be used as an identifier because it's a keyword.
 typedef this = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:121:14: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_typedefs:121:14: 'throw' can't be used as an identifier because it's a keyword.
 typedef void throw();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:122:9: Expected an identifier, but got 'throw'.
+parser/error_recovery/keyword_named_typedefs:122:9: 'throw' can't be used as an identifier because it's a keyword.
 typedef throw = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:123:14: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_typedefs:123:14: 'true' can't be used as an identifier because it's a keyword.
 typedef void true();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:124:9: Expected an identifier, but got 'true'.
+parser/error_recovery/keyword_named_typedefs:124:9: 'true' can't be used as an identifier because it's a keyword.
 typedef true = void Function();
         ^^^^
 
-parser/error_recovery/keyword_named_typedefs:125:14: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_typedefs:125:14: 'try' can't be used as an identifier because it's a keyword.
 typedef void try();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:126:9: Expected an identifier, but got 'try'.
+parser/error_recovery/keyword_named_typedefs:126:9: 'try' can't be used as an identifier because it's a keyword.
 typedef try = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:127:14: Expected an identifier, but got 'typedef'.
+parser/error_recovery/keyword_named_typedefs:127:14: 'typedef' can't be used as an identifier because it's a keyword.
 typedef void typedef();
              ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:128:9: Expected an identifier, but got 'typedef'.
+parser/error_recovery/keyword_named_typedefs:128:9: 'typedef' can't be used as an identifier because it's a keyword.
 typedef typedef = void Function();
         ^^^^^^^
 
-parser/error_recovery/keyword_named_typedefs:129:14: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_typedefs:129:14: 'var' can't be used as an identifier because it's a keyword.
 typedef void var();
              ^^^
 
-parser/error_recovery/keyword_named_typedefs:130:9: Expected an identifier, but got 'var'.
+parser/error_recovery/keyword_named_typedefs:130:9: 'var' can't be used as an identifier because it's a keyword.
 typedef var = void Function();
         ^^^
 
-parser/error_recovery/keyword_named_typedefs:131:14: Expected an identifier, but got 'void'.
+parser/error_recovery/keyword_named_typedefs:131:14: 'void' can't be used as an identifier because it's a keyword.
 typedef void void();
              ^^^^
 
@@ -448,19 +448,19 @@
 typedef void = void Function();
                               ^
 
-parser/error_recovery/keyword_named_typedefs:133:14: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_typedefs:133:14: 'while' can't be used as an identifier because it's a keyword.
 typedef void while();
              ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:134:9: Expected an identifier, but got 'while'.
+parser/error_recovery/keyword_named_typedefs:134:9: 'while' can't be used as an identifier because it's a keyword.
 typedef while = void Function();
         ^^^^^
 
-parser/error_recovery/keyword_named_typedefs:135:14: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_typedefs:135:14: 'with' can't be used as an identifier because it's a keyword.
 typedef void with();
              ^^^^
 
-parser/error_recovery/keyword_named_typedefs:136:9: Expected an identifier, but got 'with'.
+parser/error_recovery/keyword_named_typedefs:136:9: 'with' can't be used as an identifier because it's a keyword.
 typedef with = void Function();
         ^^^^
 
@@ -470,7 +470,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'abstract'., null, {token: abstract}], abstract, abstract)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
       handleIdentifier(abstract, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -481,7 +481,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'abstract'., null, {token: abstract}], abstract, abstract)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
       handleIdentifier(abstract, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -497,7 +497,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'as'., null, {token: as}], as, as)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
       handleIdentifier(as, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -508,7 +508,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'as'., null, {token: as}], as, as)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
       handleIdentifier(as, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -524,7 +524,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
       handleIdentifier(assert, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -535,7 +535,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
       handleIdentifier(assert, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -601,7 +601,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
       handleIdentifier(break, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -612,7 +612,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
       handleIdentifier(break, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -628,7 +628,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
       handleIdentifier(case, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -639,7 +639,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
       handleIdentifier(case, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -655,7 +655,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
       handleIdentifier(catch, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -666,7 +666,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
       handleIdentifier(catch, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -682,7 +682,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
       handleIdentifier(class, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -693,7 +693,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
       handleIdentifier(class, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -709,7 +709,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
       handleIdentifier(const, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -720,7 +720,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
       handleIdentifier(const, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -736,7 +736,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
       handleIdentifier(continue, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -747,7 +747,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
       handleIdentifier(continue, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -763,7 +763,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'covariant'., null, {token: covariant}], covariant, covariant)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
       handleIdentifier(covariant, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -774,7 +774,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'covariant'., null, {token: covariant}], covariant, covariant)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
       handleIdentifier(covariant, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -790,7 +790,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
       handleIdentifier(default, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -801,7 +801,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
       handleIdentifier(default, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -817,7 +817,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'deferred'., null, {token: deferred}], deferred, deferred)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
       handleIdentifier(deferred, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -828,7 +828,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'deferred'., null, {token: deferred}], deferred, deferred)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
       handleIdentifier(deferred, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -844,7 +844,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
       handleIdentifier(do, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -855,7 +855,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
       handleIdentifier(do, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -871,7 +871,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'dynamic'., null, {token: dynamic}], dynamic, dynamic)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
       handleIdentifier(dynamic, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -882,7 +882,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'dynamic'., null, {token: dynamic}], dynamic, dynamic)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
       handleIdentifier(dynamic, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -898,7 +898,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
       handleIdentifier(else, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -909,7 +909,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
       handleIdentifier(else, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -925,7 +925,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
       handleIdentifier(enum, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -936,7 +936,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
       handleIdentifier(enum, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -952,7 +952,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'export'., null, {token: export}], export, export)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
       handleIdentifier(export, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -963,7 +963,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'export'., null, {token: export}], export, export)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
       handleIdentifier(export, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -979,7 +979,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
       handleIdentifier(extends, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -990,7 +990,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
       handleIdentifier(extends, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1006,7 +1006,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extension'., null, {token: extension}], extension, extension)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
       handleIdentifier(extension, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1017,7 +1017,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extension'., null, {token: extension}], extension, extension)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
       handleIdentifier(extension, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1033,7 +1033,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'external'., null, {token: external}], external, external)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
       handleIdentifier(external, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1044,7 +1044,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'external'., null, {token: external}], external, external)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
       handleIdentifier(external, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1060,7 +1060,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'factory'., null, {token: factory}], factory, factory)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
       handleIdentifier(factory, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1071,7 +1071,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'factory'., null, {token: factory}], factory, factory)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
       handleIdentifier(factory, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1087,7 +1087,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
       handleIdentifier(false, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1098,7 +1098,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
       handleIdentifier(false, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1114,7 +1114,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
       handleIdentifier(final, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1125,7 +1125,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
       handleIdentifier(final, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1141,7 +1141,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
       handleIdentifier(finally, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1152,7 +1152,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
       handleIdentifier(finally, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1168,7 +1168,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
       handleIdentifier(for, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1179,7 +1179,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
       handleIdentifier(for, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1195,7 +1195,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'Function'., null, {token: Function}], Function, Function)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
       handleIdentifier(Function, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1206,7 +1206,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'Function'., null, {token: Function}], Function, Function)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
       handleIdentifier(Function, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1222,7 +1222,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'get'., null, {token: get}], get, get)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
       handleIdentifier(get, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1233,7 +1233,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'get'., null, {token: get}], get, get)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
       handleIdentifier(get, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1274,7 +1274,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
       handleIdentifier(if, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1285,7 +1285,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
       handleIdentifier(if, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1301,7 +1301,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'implements'., null, {token: implements}], implements, implements)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
       handleIdentifier(implements, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1312,7 +1312,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'implements'., null, {token: implements}], implements, implements)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
       handleIdentifier(implements, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1328,7 +1328,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'import'., null, {token: import}], import, import)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
       handleIdentifier(import, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1339,7 +1339,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'import'., null, {token: import}], import, import)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
       handleIdentifier(import, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1355,7 +1355,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
       handleIdentifier(in, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1366,7 +1366,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
       handleIdentifier(in, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1407,7 +1407,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'interface'., null, {token: interface}], interface, interface)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
       handleIdentifier(interface, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1418,7 +1418,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'interface'., null, {token: interface}], interface, interface)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
       handleIdentifier(interface, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1434,7 +1434,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
       handleIdentifier(is, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1445,7 +1445,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
       handleIdentifier(is, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1461,7 +1461,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'late'., null, {token: late}], late, late)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
       handleIdentifier(late, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1472,7 +1472,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'late'., null, {token: late}], late, late)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
       handleIdentifier(late, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1488,7 +1488,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'library'., null, {token: library}], library, library)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
       handleIdentifier(library, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1499,7 +1499,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'library'., null, {token: library}], library, library)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
       handleIdentifier(library, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1515,7 +1515,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'mixin'., null, {token: mixin}], mixin, mixin)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
       handleIdentifier(mixin, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1526,7 +1526,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'mixin'., null, {token: mixin}], mixin, mixin)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
       handleIdentifier(mixin, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1567,7 +1567,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
       handleIdentifier(new, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1578,7 +1578,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
       handleIdentifier(new, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1594,7 +1594,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
       handleIdentifier(null, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1605,7 +1605,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
       handleIdentifier(null, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1671,7 +1671,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'operator'., null, {token: operator}], operator, operator)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
       handleIdentifier(operator, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1682,7 +1682,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'operator'., null, {token: operator}], operator, operator)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
       handleIdentifier(operator, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1723,7 +1723,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'part'., null, {token: part}], part, part)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
       handleIdentifier(part, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1734,7 +1734,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'part'., null, {token: part}], part, part)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
       handleIdentifier(part, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1775,7 +1775,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'required'., null, {token: required}], required, required)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
       handleIdentifier(required, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1786,7 +1786,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'required'., null, {token: required}], required, required)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
       handleIdentifier(required, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1802,7 +1802,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1813,7 +1813,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
       handleIdentifier(rethrow, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1829,7 +1829,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
       handleIdentifier(return, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1840,7 +1840,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
       handleIdentifier(return, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1856,7 +1856,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'set'., null, {token: set}], set, set)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
       handleIdentifier(set, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1867,7 +1867,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'set'., null, {token: set}], set, set)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
       handleIdentifier(set, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1933,7 +1933,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'static'., null, {token: static}], static, static)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
       handleIdentifier(static, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1944,7 +1944,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'static'., null, {token: static}], static, static)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
       handleIdentifier(static, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1960,7 +1960,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
       handleIdentifier(super, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1971,7 +1971,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
       handleIdentifier(super, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -1987,7 +1987,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
       handleIdentifier(switch, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -1998,7 +1998,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
       handleIdentifier(switch, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2039,7 +2039,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
       handleIdentifier(this, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2050,7 +2050,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
       handleIdentifier(this, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2066,7 +2066,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
       handleIdentifier(throw, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2077,7 +2077,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
       handleIdentifier(throw, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2093,7 +2093,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
       handleIdentifier(true, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2104,7 +2104,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
       handleIdentifier(true, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2120,7 +2120,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
       handleIdentifier(try, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2131,7 +2131,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
       handleIdentifier(try, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2147,7 +2147,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'typedef'., null, {token: typedef}], typedef, typedef)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
       handleIdentifier(typedef, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2158,7 +2158,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'typedef'., null, {token: typedef}], typedef, typedef)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
       handleIdentifier(typedef, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2174,7 +2174,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
       handleIdentifier(var, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2185,7 +2185,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
       handleIdentifier(var, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2201,7 +2201,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
       handleIdentifier(void, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2213,7 +2213,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., null, {token: =}], =, =)
+      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], =, =)
       handleIdentifier(, typedefDeclaration)
       handleNoTypeVariables(=)
       handleRecoverableError(MissingTypedefParameters, =, =)
@@ -2247,7 +2247,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
       handleIdentifier(while, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2258,7 +2258,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
       handleIdentifier(while, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
@@ -2274,7 +2274,7 @@
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
       handleVoidKeyword(void)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, typedefDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.FunctionTypeAlias)
@@ -2285,7 +2285,7 @@
   endMetadataStar(0)
   beginUncategorizedTopLevelDeclaration(typedef)
     beginFunctionTypeAlias(typedef)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, typedefDeclaration)
       handleNoTypeVariables(=)
       beginFunctionType(void)
diff --git a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
index 6802b71..cc71477 100644
--- a/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/keyword_named_typedefs.dart.intertwined.expect
@@ -14,7 +14,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(abstract, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'abstract'., null, {token: abstract}], abstract, abstract)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
           listener: handleIdentifier(abstract, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(abstract, MemberKind.FunctionTypeAlias)
@@ -35,7 +35,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(abstract, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'abstract'., null, {token: abstract}], abstract, abstract)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'abstract' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: abstract}], abstract, abstract)
           listener: handleIdentifier(abstract, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -61,7 +61,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(as, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'as'., null, {token: as}], as, as)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
           listener: handleIdentifier(as, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(as, MemberKind.FunctionTypeAlias)
@@ -82,7 +82,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(as, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'as'., null, {token: as}], as, as)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'as' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: as}], as, as)
           listener: handleIdentifier(as, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -108,7 +108,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
           listener: handleIdentifier(assert, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(assert, MemberKind.FunctionTypeAlias)
@@ -129,7 +129,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(assert, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'assert'., null, {token: assert}], assert, assert)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'assert' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: assert}], assert, assert)
           listener: handleIdentifier(assert, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -241,7 +241,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
           listener: handleIdentifier(break, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(break, MemberKind.FunctionTypeAlias)
@@ -262,7 +262,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(break, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'break'., null, {token: break}], break, break)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'break' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: break}], break, break)
           listener: handleIdentifier(break, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -288,7 +288,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
           listener: handleIdentifier(case, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(case, MemberKind.FunctionTypeAlias)
@@ -309,7 +309,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(case, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'case'., null, {token: case}], case, case)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'case' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: case}], case, case)
           listener: handleIdentifier(case, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -335,7 +335,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
           listener: handleIdentifier(catch, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(catch, MemberKind.FunctionTypeAlias)
@@ -356,7 +356,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(catch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'catch'., null, {token: catch}], catch, catch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'catch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: catch}], catch, catch)
           listener: handleIdentifier(catch, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -382,7 +382,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
           listener: handleIdentifier(class, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(class, MemberKind.FunctionTypeAlias)
@@ -403,7 +403,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(class, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'class'., null, {token: class}], class, class)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'class' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: class}], class, class)
           listener: handleIdentifier(class, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -429,7 +429,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
           listener: handleIdentifier(const, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(const, MemberKind.FunctionTypeAlias)
@@ -450,7 +450,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(const, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'const'., null, {token: const}], const, const)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'const' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: const}], const, const)
           listener: handleIdentifier(const, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -476,7 +476,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
           listener: handleIdentifier(continue, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(continue, MemberKind.FunctionTypeAlias)
@@ -497,7 +497,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(continue, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'continue'., null, {token: continue}], continue, continue)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'continue' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: continue}], continue, continue)
           listener: handleIdentifier(continue, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -523,7 +523,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'covariant'., null, {token: covariant}], covariant, covariant)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
           listener: handleIdentifier(covariant, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(covariant, MemberKind.FunctionTypeAlias)
@@ -544,7 +544,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(covariant, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'covariant'., null, {token: covariant}], covariant, covariant)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'covariant' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: covariant}], covariant, covariant)
           listener: handleIdentifier(covariant, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -570,7 +570,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
           listener: handleIdentifier(default, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(default, MemberKind.FunctionTypeAlias)
@@ -591,7 +591,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(default, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'default'., null, {token: default}], default, default)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'default' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: default}], default, default)
           listener: handleIdentifier(default, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -617,7 +617,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(deferred, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'deferred'., null, {token: deferred}], deferred, deferred)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
           listener: handleIdentifier(deferred, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(deferred, MemberKind.FunctionTypeAlias)
@@ -638,7 +638,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(deferred, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'deferred'., null, {token: deferred}], deferred, deferred)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'deferred' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: deferred}], deferred, deferred)
           listener: handleIdentifier(deferred, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -664,7 +664,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
           listener: handleIdentifier(do, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(do, MemberKind.FunctionTypeAlias)
@@ -685,7 +685,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(do, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'do'., null, {token: do}], do, do)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'do' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: do}], do, do)
           listener: handleIdentifier(do, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -711,7 +711,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(dynamic, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'dynamic'., null, {token: dynamic}], dynamic, dynamic)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
           listener: handleIdentifier(dynamic, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(dynamic, MemberKind.FunctionTypeAlias)
@@ -732,7 +732,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(dynamic, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'dynamic'., null, {token: dynamic}], dynamic, dynamic)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'dynamic' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: dynamic}], dynamic, dynamic)
           listener: handleIdentifier(dynamic, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -758,7 +758,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
           listener: handleIdentifier(else, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(else, MemberKind.FunctionTypeAlias)
@@ -779,7 +779,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(else, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'else'., null, {token: else}], else, else)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'else' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: else}], else, else)
           listener: handleIdentifier(else, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -805,7 +805,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
           listener: handleIdentifier(enum, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(enum, MemberKind.FunctionTypeAlias)
@@ -826,7 +826,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(enum, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'enum'., null, {token: enum}], enum, enum)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'enum' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: enum}], enum, enum)
           listener: handleIdentifier(enum, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -852,7 +852,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(export, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'export'., null, {token: export}], export, export)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
           listener: handleIdentifier(export, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(export, MemberKind.FunctionTypeAlias)
@@ -873,7 +873,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(export, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'export'., null, {token: export}], export, export)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'export' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: export}], export, export)
           listener: handleIdentifier(export, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -899,7 +899,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
           listener: handleIdentifier(extends, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(extends, MemberKind.FunctionTypeAlias)
@@ -920,7 +920,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extends, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extends'., null, {token: extends}], extends, extends)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extends' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extends}], extends, extends)
           listener: handleIdentifier(extends, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -946,7 +946,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extension, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extension'., null, {token: extension}], extension, extension)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
           listener: handleIdentifier(extension, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(extension, MemberKind.FunctionTypeAlias)
@@ -967,7 +967,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(extension, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'extension'., null, {token: extension}], extension, extension)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'extension' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: extension}], extension, extension)
           listener: handleIdentifier(extension, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -993,7 +993,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(external, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'external'., null, {token: external}], external, external)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
           listener: handleIdentifier(external, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(external, MemberKind.FunctionTypeAlias)
@@ -1014,7 +1014,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(external, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'external'., null, {token: external}], external, external)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'external' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: external}], external, external)
           listener: handleIdentifier(external, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1040,7 +1040,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(factory, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'factory'., null, {token: factory}], factory, factory)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
           listener: handleIdentifier(factory, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(factory, MemberKind.FunctionTypeAlias)
@@ -1061,7 +1061,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(factory, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'factory'., null, {token: factory}], factory, factory)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'factory' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: factory}], factory, factory)
           listener: handleIdentifier(factory, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1087,7 +1087,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
           listener: handleIdentifier(false, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(false, MemberKind.FunctionTypeAlias)
@@ -1108,7 +1108,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(false, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'false'., null, {token: false}], false, false)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'false' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: false}], false, false)
           listener: handleIdentifier(false, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1134,7 +1134,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
           listener: handleIdentifier(final, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(final, MemberKind.FunctionTypeAlias)
@@ -1155,7 +1155,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(final, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'final'., null, {token: final}], final, final)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'final' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: final}], final, final)
           listener: handleIdentifier(final, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1181,7 +1181,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
           listener: handleIdentifier(finally, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(finally, MemberKind.FunctionTypeAlias)
@@ -1202,7 +1202,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(finally, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'finally'., null, {token: finally}], finally, finally)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'finally' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: finally}], finally, finally)
           listener: handleIdentifier(finally, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1228,7 +1228,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
           listener: handleIdentifier(for, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(for, MemberKind.FunctionTypeAlias)
@@ -1249,7 +1249,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(for, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'for'., null, {token: for}], for, for)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'for' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: for}], for, for)
           listener: handleIdentifier(for, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1275,7 +1275,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(Function, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'Function'., null, {token: Function}], Function, Function)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
           listener: handleIdentifier(Function, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(Function, MemberKind.FunctionTypeAlias)
@@ -1296,7 +1296,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(Function, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'Function'., null, {token: Function}], Function, Function)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'Function' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: Function}], Function, Function)
           listener: handleIdentifier(Function, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1322,7 +1322,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(get, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'get'., null, {token: get}], get, get)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
           listener: handleIdentifier(get, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(get, MemberKind.FunctionTypeAlias)
@@ -1343,7 +1343,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(get, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'get'., null, {token: get}], get, get)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'get' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: get}], get, get)
           listener: handleIdentifier(get, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1412,7 +1412,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
           listener: handleIdentifier(if, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(if, MemberKind.FunctionTypeAlias)
@@ -1433,7 +1433,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(if, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'if'., null, {token: if}], if, if)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'if' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: if}], if, if)
           listener: handleIdentifier(if, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1459,7 +1459,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(implements, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'implements'., null, {token: implements}], implements, implements)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
           listener: handleIdentifier(implements, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(implements, MemberKind.FunctionTypeAlias)
@@ -1480,7 +1480,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(implements, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'implements'., null, {token: implements}], implements, implements)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'implements' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: implements}], implements, implements)
           listener: handleIdentifier(implements, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1506,7 +1506,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(import, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'import'., null, {token: import}], import, import)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
           listener: handleIdentifier(import, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(import, MemberKind.FunctionTypeAlias)
@@ -1527,7 +1527,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(import, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'import'., null, {token: import}], import, import)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'import' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: import}], import, import)
           listener: handleIdentifier(import, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1553,7 +1553,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
           listener: handleIdentifier(in, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(in, MemberKind.FunctionTypeAlias)
@@ -1574,7 +1574,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(in, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'in'., null, {token: in}], in, in)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'in' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: in}], in, in)
           listener: handleIdentifier(in, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1643,7 +1643,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(interface, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'interface'., null, {token: interface}], interface, interface)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
           listener: handleIdentifier(interface, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(interface, MemberKind.FunctionTypeAlias)
@@ -1664,7 +1664,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(interface, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'interface'., null, {token: interface}], interface, interface)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'interface' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: interface}], interface, interface)
           listener: handleIdentifier(interface, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1690,7 +1690,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
           listener: handleIdentifier(is, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(is, MemberKind.FunctionTypeAlias)
@@ -1711,7 +1711,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(is, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'is'., null, {token: is}], is, is)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'is' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: is}], is, is)
           listener: handleIdentifier(is, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1737,7 +1737,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'late'., null, {token: late}], late, late)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
           listener: handleIdentifier(late, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(late, MemberKind.FunctionTypeAlias)
@@ -1758,7 +1758,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(late, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'late'., null, {token: late}], late, late)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'late' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: late}], late, late)
           listener: handleIdentifier(late, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1784,7 +1784,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(library, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'library'., null, {token: library}], library, library)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
           listener: handleIdentifier(library, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(library, MemberKind.FunctionTypeAlias)
@@ -1805,7 +1805,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(library, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'library'., null, {token: library}], library, library)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'library' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: library}], library, library)
           listener: handleIdentifier(library, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1831,7 +1831,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(mixin, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'mixin'., null, {token: mixin}], mixin, mixin)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
           listener: handleIdentifier(mixin, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(mixin, MemberKind.FunctionTypeAlias)
@@ -1852,7 +1852,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(mixin, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'mixin'., null, {token: mixin}], mixin, mixin)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'mixin' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: mixin}], mixin, mixin)
           listener: handleIdentifier(mixin, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1921,7 +1921,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
           listener: handleIdentifier(new, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(new, MemberKind.FunctionTypeAlias)
@@ -1942,7 +1942,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(new, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'new'., null, {token: new}], new, new)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'new' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: new}], new, new)
           listener: handleIdentifier(new, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -1968,7 +1968,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
           listener: handleIdentifier(null, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(null, MemberKind.FunctionTypeAlias)
@@ -1989,7 +1989,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(null, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'null'., null, {token: null}], null, null)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'null' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: null}], null, null)
           listener: handleIdentifier(null, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2101,7 +2101,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(operator, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'operator'., null, {token: operator}], operator, operator)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
           listener: handleIdentifier(operator, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(operator, MemberKind.FunctionTypeAlias)
@@ -2122,7 +2122,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(operator, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'operator'., null, {token: operator}], operator, operator)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'operator' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: operator}], operator, operator)
           listener: handleIdentifier(operator, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2191,7 +2191,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(part, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'part'., null, {token: part}], part, part)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
           listener: handleIdentifier(part, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(part, MemberKind.FunctionTypeAlias)
@@ -2212,7 +2212,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(part, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'part'., null, {token: part}], part, part)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'part' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: part}], part, part)
           listener: handleIdentifier(part, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2281,7 +2281,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'required'., null, {token: required}], required, required)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
           listener: handleIdentifier(required, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(required, MemberKind.FunctionTypeAlias)
@@ -2302,7 +2302,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(required, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'required'., null, {token: required}], required, required)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'required' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: required}], required, required)
           listener: handleIdentifier(required, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2328,7 +2328,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(rethrow, MemberKind.FunctionTypeAlias)
@@ -2349,7 +2349,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(rethrow, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'rethrow'., null, {token: rethrow}], rethrow, rethrow)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'rethrow' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: rethrow}], rethrow, rethrow)
           listener: handleIdentifier(rethrow, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2375,7 +2375,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
           listener: handleIdentifier(return, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(return, MemberKind.FunctionTypeAlias)
@@ -2396,7 +2396,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(return, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'return'., null, {token: return}], return, return)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'return' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: return}], return, return)
           listener: handleIdentifier(return, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2422,7 +2422,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(set, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'set'., null, {token: set}], set, set)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
           listener: handleIdentifier(set, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(set, MemberKind.FunctionTypeAlias)
@@ -2443,7 +2443,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(set, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'set'., null, {token: set}], set, set)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'set' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: set}], set, set)
           listener: handleIdentifier(set, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2555,7 +2555,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(static, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'static'., null, {token: static}], static, static)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
           listener: handleIdentifier(static, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(static, MemberKind.FunctionTypeAlias)
@@ -2576,7 +2576,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(static, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'static'., null, {token: static}], static, static)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'static' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: static}], static, static)
           listener: handleIdentifier(static, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2602,7 +2602,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
           listener: handleIdentifier(super, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(super, MemberKind.FunctionTypeAlias)
@@ -2623,7 +2623,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(super, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'super'., null, {token: super}], super, super)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'super' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: super}], super, super)
           listener: handleIdentifier(super, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2649,7 +2649,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
           listener: handleIdentifier(switch, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(switch, MemberKind.FunctionTypeAlias)
@@ -2670,7 +2670,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(switch, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'switch'., null, {token: switch}], switch, switch)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'switch' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: switch}], switch, switch)
           listener: handleIdentifier(switch, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2739,7 +2739,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
           listener: handleIdentifier(this, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(this, MemberKind.FunctionTypeAlias)
@@ -2760,7 +2760,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(this, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'this'., null, {token: this}], this, this)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'this' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: this}], this, this)
           listener: handleIdentifier(this, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2786,7 +2786,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
           listener: handleIdentifier(throw, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(throw, MemberKind.FunctionTypeAlias)
@@ -2807,7 +2807,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(throw, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'throw'., null, {token: throw}], throw, throw)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'throw' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: throw}], throw, throw)
           listener: handleIdentifier(throw, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2833,7 +2833,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
           listener: handleIdentifier(true, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(true, MemberKind.FunctionTypeAlias)
@@ -2854,7 +2854,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(true, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'true'., null, {token: true}], true, true)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'true' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: true}], true, true)
           listener: handleIdentifier(true, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2880,7 +2880,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
           listener: handleIdentifier(try, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(try, MemberKind.FunctionTypeAlias)
@@ -2901,7 +2901,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(try, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'try'., null, {token: try}], try, try)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'try' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: try}], try, try)
           listener: handleIdentifier(try, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2927,7 +2927,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(typedef, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'typedef'., null, {token: typedef}], typedef, typedef)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
           listener: handleIdentifier(typedef, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(typedef, MemberKind.FunctionTypeAlias)
@@ -2948,7 +2948,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(typedef, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'typedef'., null, {token: typedef}], typedef, typedef)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'typedef' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: typedef}], typedef, typedef)
           listener: handleIdentifier(typedef, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -2974,7 +2974,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
           listener: handleIdentifier(var, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(var, MemberKind.FunctionTypeAlias)
@@ -2995,7 +2995,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(var, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'var'., null, {token: var}], var, var)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'var' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: var}], var, var)
           listener: handleIdentifier(var, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -3021,7 +3021,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(void, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'void'., null, {token: void}], void, void)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'void' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: void}], void, void)
           listener: handleIdentifier(void, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(void, MemberKind.FunctionTypeAlias)
@@ -3042,9 +3042,9 @@
         listener: beginFunctionTypeAlias(typedef)
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, false)
-          insertSyntheticIdentifier(void, typedefDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got '='., null, {token: =}], messageOnToken: null)
-            reportRecoverableError(=, Message[ExpectedIdentifier, Expected an identifier, but got '='., null, {token: =}])
-              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., null, {token: =}], =, =)
+          insertSyntheticIdentifier(void, typedefDeclaration, message: Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], messageOnToken: null)
+            reportRecoverableError(=, Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}])
+              listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '='., Try inserting an identifier before '='., {token: =}], =, =)
             rewriter()
           listener: handleIdentifier(, typedefDeclaration)
         listener: handleNoTypeVariables(=)
@@ -3111,7 +3111,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
           listener: handleIdentifier(while, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(while, MemberKind.FunctionTypeAlias)
@@ -3132,7 +3132,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(while, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'while'., null, {token: while}], while, while)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'while' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: while}], while, while)
           listener: handleIdentifier(while, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
@@ -3158,7 +3158,7 @@
         listener: handleVoidKeyword(void)
         ensureIdentifierPotentiallyRecovered(void, typedefDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, typedefDeclaration)
         listener: handleNoTypeVariables(()
         parseFormalParametersRequiredOpt(with, MemberKind.FunctionTypeAlias)
@@ -3179,7 +3179,7 @@
         listener: beginFunctionTypeAlias(typedef)
         ensureIdentifierPotentiallyRecovered(typedef, typedefDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, typedefDeclaration)
         listener: handleNoTypeVariables(=)
         listener: beginFunctionType(void)
diff --git a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
index 24b5d80..a86e853 100644
--- a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.expect
@@ -1,26 +1,26 @@
 Problems reported:
 
-parser/error_recovery/method_called_with:2:7: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:2:7: 'with' can't be used as an identifier because it's a keyword.
   int with() => 7;
       ^^^^
 
-parser/error_recovery/method_called_with:3:7: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:3:7: 'with' can't be used as an identifier because it's a keyword.
   int with = 7;
       ^^^^
 
-parser/error_recovery/method_called_with:4:11: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:4:11: 'with' can't be used as an identifier because it's a keyword.
   int get with => 7;
           ^^^^
 
-parser/error_recovery/method_called_with:5:12: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:5:12: 'with' can't be used as an identifier because it's a keyword.
   void set with(int x) {}
            ^^^^
 
-parser/error_recovery/method_called_with:8:5: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:8:5: 'with' can't be used as an identifier because it's a keyword.
 int with() => 7;
     ^^^^
 
-parser/error_recovery/method_called_with:9:5: Expected an identifier, but got 'with'.
+parser/error_recovery/method_called_with:9:5: 'with' can't be used as an identifier because it's a keyword.
 int with = 7;
     ^^^^
 
@@ -44,7 +44,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -62,7 +62,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(with)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, fieldDeclaration)
             beginFieldInitializer(=)
               handleLiteralInt(7)
@@ -76,7 +76,7 @@
             handleIdentifier(int, typeReference)
             handleNoTypeArguments(get)
             handleType(int, null)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(=>)
             handleNoFormalParameters(=>, MemberKind.NonStaticMethod)
@@ -91,7 +91,7 @@
         beginMember()
           beginMethod(null, null, null, null, set, with)
             handleVoidKeyword(void)
-            handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
             handleIdentifier(with, methodDeclaration)
             handleNoTypeVariables(()
             beginFormalParameters((, MemberKind.NonStaticMethod)
@@ -121,7 +121,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, topLevelFunctionDeclaration)
       handleNoTypeVariables(()
       beginFormalParameters((, MemberKind.TopLevelMethod)
@@ -138,7 +138,7 @@
       handleIdentifier(int, typeReference)
       handleNoTypeArguments(with)
       handleType(int, null)
-      handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+      handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
       handleIdentifier(with, topLevelVariableDeclaration)
       beginFieldInitializer(=)
         handleLiteralInt(7)
diff --git a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
index 4ff4bb0..4c53a03 100644
--- a/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/error_recovery/method_called_with.dart.intertwined.expect
@@ -41,7 +41,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 parseMethodTypeVar(with)
@@ -85,7 +85,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(int, fieldDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, fieldDeclaration)
                 parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.Class, C)
                   listener: beginFieldInitializer(=)
@@ -113,7 +113,7 @@
                 listener: handleType(int, null)
                 ensureIdentifierPotentiallyRecovered(get, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 listener: handleNoTypeVariables(=>)
@@ -152,7 +152,7 @@
                 listener: handleVoidKeyword(void)
                 ensureIdentifierPotentiallyRecovered(set, methodDeclaration, true)
                   reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-                    listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+                    listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
                   listener: handleIdentifier(with, methodDeclaration)
                 parseQualifiedRestOpt(with, methodDeclarationContinuation)
                 listener: handleNoTypeVariables(()
@@ -205,7 +205,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelFunctionDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, topLevelFunctionDeclaration)
         parseMethodTypeVar(with)
           listener: handleNoTypeVariables(()
@@ -245,7 +245,7 @@
         listener: handleType(int, null)
         ensureIdentifierPotentiallyRecovered(int, topLevelVariableDeclaration, true)
           reportRecoverableErrorWithToken(with, Instance of 'Template<(Token) => Message>')
-            listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got 'with'., null, {token: with}], with, with)
+            listener: handleRecoverableError(Message[ExpectedIdentifierButGotKeyword, 'with' can't be used as an identifier because it's a keyword., Try renaming this to be an identifier that isn't a keyword., {token: with}], with, with)
           listener: handleIdentifier(with, topLevelVariableDeclaration)
         parseFieldInitializerOpt(with, with, null, null, null, null, DeclarationKind.TopLevel, null)
           listener: beginFieldInitializer(=)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
index 1990760..088c5a4 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.expect
@@ -60,7 +60,7 @@
           handleParenthesizedExpression(()
           handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], ;, ;)
           handleConditionalExpressionColon()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., null, {token: ;}], ;, ;)
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
           handleIdentifier(, expression)
           handleNoTypeArguments(;)
           handleNoArguments(;)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
index 093950e..5573577 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_no_type_arguments.dart.intertwined.expect
@@ -153,7 +153,7 @@
                                 parseSend(:, expression)
                                   ensureIdentifier(:, expression)
                                     reportRecoverableErrorWithToken(;, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., null, {token: ;}], ;, ;)
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got ';'., Try inserting an identifier before ';'., {token: ;}], ;, ;)
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(;)
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
index 0b56e4b..1357097 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.expect
@@ -95,7 +95,7 @@
           endFunctionExpression((, })
           handleRecoverableError(Message[ExpectedButGot, Expected ':' before this., null, {string: :}], }, })
           handleConditionalExpressionColon()
-          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+          handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
           handleIdentifier(, expression)
           handleNoTypeArguments(})
           handleNoArguments(})
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
index 5fdde51..ee731af 100644
--- a/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
+++ b/pkg/front_end/parser_testcases/nnbd/issue_40267_method_call_with_type_arguments.dart.intertwined.expect
@@ -177,7 +177,7 @@
                                 parseSend(:, expression)
                                   ensureIdentifier(:, expression)
                                     reportRecoverableErrorWithToken(}, Instance of 'Template<(Token) => Message>')
-                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., null, {token: }}], }, })
+                                      listener: handleRecoverableError(Message[ExpectedIdentifier, Expected an identifier, but got '}'., Try inserting an identifier before '}'., {token: }}], }, })
                                     rewriter()
                                     listener: handleIdentifier(, expression)
                                   listener: handleNoTypeArguments(})
diff --git a/pkg/front_end/test/ast_nodes_has_to_string_test.dart b/pkg/front_end/test/ast_nodes_has_to_string_test.dart
index 28a3810..13d7120 100644
--- a/pkg/front_end/test/ast_nodes_has_to_string_test.dart
+++ b/pkg/front_end/test/ast_nodes_has_to_string_test.dart
@@ -51,7 +51,7 @@
               .getInterfaceMembers(c)
               .where((Member m) =>
                   !m.isAbstract &&
-                  m.name.name == "toString" &&
+                  m.name.text == "toString" &&
                   m.enclosingLibrary.importUri.scheme != "dart")
               .toList();
           if (toStringList.length > 1) throw "What?";
@@ -153,7 +153,7 @@
             .getInterfaceMembers(c)
             .where((Member m) =>
                 !m.isAbstract &&
-                m.name.name == "toString" &&
+                m.name.text == "toString" &&
                 m.enclosingLibrary.importUri.scheme != "dart")
             .toList();
         Member toString = toStringList.single;
diff --git a/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart b/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
index 706d0a6..d9f412e 100644
--- a/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
+++ b/pkg/front_end/test/binary_md_vm_tags_and_version_test.dart
@@ -111,29 +111,29 @@
     Map<int, String> tagToName = {};
     for (Field f in compareMe.tagClass.fields) {
       // Class doesn't only contain tag stuff.
-      if (f.name.name.endsWith("Mask")) continue;
-      if (f.name.name.endsWith("HighBit")) continue;
-      if (f.name.name.endsWith("Bias")) continue;
-      if (f.name.name == "ComponentFile") continue;
+      if (f.name.text.endsWith("Mask")) continue;
+      if (f.name.text.endsWith("HighBit")) continue;
+      if (f.name.text.endsWith("Bias")) continue;
+      if (f.name.text == "ComponentFile") continue;
       ConstantExpression value = f.initializer;
       IntConstant intConstant = value.constant;
       int intValue = intConstant.value;
-      if (f.name.name == "BinaryFormatVersion") {
+      if (f.name.text == "BinaryFormatVersion") {
         tagVersion = intValue;
         continue;
       }
 
       int end = intValue + 1;
       // There are a few special cases that takes up a total of 8 tags.
-      if (uses8Tags(f.name.name)) {
+      if (uses8Tags(f.name.text)) {
         end = intValue + 8;
       }
       for (; intValue < end; intValue++) {
         if (tagToName[intValue] != null) {
           throw "Double entry for ${intValue}: "
-              "${f.name.name} and ${tagToName[intValue]}";
+              "${f.name.text} and ${tagToName[intValue]}";
         }
-        tagToName[intValue] = f.name.name;
+        tagToName[intValue] = f.name.text;
       }
     }
 
diff --git a/pkg/front_end/test/comments_on_certain_arguments_tool.dart b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
index 5920035..41045b5 100644
--- a/pkg/front_end/test/comments_on_certain_arguments_tool.dart
+++ b/pkg/front_end/test/comments_on_certain_arguments_tool.dart
@@ -4,16 +4,7 @@
 
 import 'dart:convert' show utf8;
 import 'dart:io'
-    show
-        Directory,
-        File,
-        FileSystemEntity,
-        Platform,
-        Process,
-        ProcessResult,
-        exitCode,
-        stdin,
-        stdout;
+    show Directory, File, FileSystemEntity, exitCode, stdin, stdout;
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
@@ -41,16 +32,9 @@
 import 'package:kernel/target/targets.dart' show TargetFlags;
 import "package:vm/target/vm.dart" show VmTarget;
 
-final Uri repoDir = _computeRepoDir();
+import "utils/io_utils.dart";
 
-Uri _computeRepoDir() {
-  ProcessResult result = Process.runSync(
-      'git', ['rev-parse', '--show-toplevel'],
-      runInShell: true,
-      workingDirectory: new File.fromUri(Platform.script).parent.path);
-  String dirPath = (result.stdout as String).trim();
-  return new Directory(dirPath).uri;
-}
+final Uri repoDir = computeRepoDirUri();
 
 Set<Uri> libUris = {};
 
@@ -186,11 +170,6 @@
     }
   }
 
-  void visitDirectMethodInvocation(DirectMethodInvocation node) {
-    super.visitDirectMethodInvocation(node);
-    note(node.targetReference.node, node.arguments, node);
-  }
-
   void visitSuperMethodInvocation(SuperMethodInvocation node) {
     super.visitSuperMethodInvocation(node);
     note(node.interfaceTargetReference.node, node.arguments, node);
diff --git a/pkg/front_end/test/desugar_test.dart b/pkg/front_end/test/desugar_test.dart
index 9ec4d38..b61a6a7 100644
--- a/pkg/front_end/test/desugar_test.dart
+++ b/pkg/front_end/test/desugar_test.dart
@@ -63,7 +63,7 @@
       component.libraries.firstWhere((l) => l.importUri.path.endsWith(uriPath));
   var cls = lib.classes.firstWhere((c) => c.name == className);
   ir.Procedure member =
-      cls.members.firstWhere((m) => m.name.name == constructorName);
+      cls.members.firstWhere((m) => m.name.text == constructorName);
   Expect.isTrue(
       member.kind == ir.ProcedureKind.Factory, "$member is not a factory");
   Expect.isTrue(api.isRedirectingFactory(member));
diff --git a/pkg/front_end/test/explicit_creation_test.dart b/pkg/front_end/test/explicit_creation_test.dart
index 9416765..7e8246a 100644
--- a/pkg/front_end/test/explicit_creation_test.dart
+++ b/pkg/front_end/test/explicit_creation_test.dart
@@ -39,16 +39,10 @@
 import 'package:kernel/target/targets.dart';
 import "package:vm/target/vm.dart" show VmTarget;
 
-final Uri repoDir = _computeRepoDir();
+import 'testing_utils.dart' show getGitFiles;
+import "utils/io_utils.dart";
 
-Uri _computeRepoDir() {
-  ProcessResult result = Process.runSync(
-      'git', ['rev-parse', '--show-toplevel'],
-      runInShell: true,
-      workingDirectory: new File.fromUri(Platform.script).parent.path);
-  String dirPath = (result.stdout as String).trim();
-  return new Directory(dirPath).uri;
-}
+final Uri repoDir = computeRepoDirUri();
 
 Set<Uri> libUris = {};
 
@@ -77,10 +71,13 @@
     }
   }
   for (Uri uri in libUris) {
+    Set<Uri> gitFiles = await getGitFiles(uri);
     List<FileSystemEntity> entities =
         new Directory.fromUri(uri).listSync(recursive: true);
     for (FileSystemEntity entity in entities) {
-      if (entity is File && entity.path.endsWith(".dart")) {
+      if (entity is File &&
+          entity.path.endsWith(".dart") &&
+          gitFiles.contains(entity.uri)) {
         options.inputs.add(entity.uri);
       }
     }
diff --git a/pkg/front_end/test/fasta/assert_locations_test.dart b/pkg/front_end/test/fasta/assert_locations_test.dart
index eaff73c..532b311 100644
--- a/pkg/front_end/test/fasta/assert_locations_test.dart
+++ b/pkg/front_end/test/fasta/assert_locations_test.dart
@@ -114,10 +114,10 @@
 
   @override
   visitProcedure(Procedure node) {
-    expectedSpan = test.spans[node.name.name];
+    expectedSpan = test.spans[node.name.text];
     if (expectedSpan != null) {
       super.visitProcedure(node);
-      verified.add(node.name.name);
+      verified.add(node.name.text);
       expectedSpan = null;
     }
   }
diff --git a/pkg/front_end/test/fasta/bootstrap_test.dart b/pkg/front_end/test/fasta/bootstrap_test.dart
index 39effb5..37dff17 100644
--- a/pkg/front_end/test/fasta/bootstrap_test.dart
+++ b/pkg/front_end/test/fasta/bootstrap_test.dart
@@ -59,7 +59,7 @@
       ],
       suppressOutput: false);
   if (result.exitCode != 0) {
-    throw "Compilation failed.";
+    throw "Compilation failed:\n${result.output}";
   }
 }
 
diff --git a/pkg/front_end/test/fasta/messages_suite.dart b/pkg/front_end/test/fasta/messages_suite.dart
index cb0f930..3a3dcd2 100644
--- a/pkg/front_end/test/fasta/messages_suite.dart
+++ b/pkg/front_end/test/fasta/messages_suite.dart
@@ -6,7 +6,7 @@
 
 import "dart:convert" show utf8;
 
-import "dart:io" show File;
+import 'dart:io' show File, Platform;
 
 import "dart:typed_data" show Uint8List;
 
@@ -97,8 +97,31 @@
   final BatchCompiler compiler;
 
   final bool fastOnly;
+  final bool interactive;
 
-  MessageTestSuite(this.fastOnly)
+  final Set<String> reportedWords = {};
+  final Set<String> reportedWordsDenylisted = {};
+
+  @override
+  Future<void> postRun() {
+    String dartPath = Platform.resolvedExecutable;
+    Uri suiteUri =
+        spell.repoDir.resolve("pkg/front_end/test/fasta/messages_suite.dart");
+    File suiteFile = new File.fromUri(suiteUri).absolute;
+    if (!suiteFile.existsSync()) {
+      throw "Specified suite path is invalid.";
+    }
+    String suitePath = suiteFile.path;
+    spell.spellSummarizeAndInteractiveMode(
+        reportedWords,
+        reportedWordsDenylisted,
+        [spell.Dictionaries.cfeMessages],
+        interactive,
+        '"$dartPath" "$suitePath" -DfastOnly=true -Dinteractive=true');
+    return null;
+  }
+
+  MessageTestSuite(this.fastOnly, this.interactive)
       : fileSystem = new MemoryFileSystem(Uri.parse("org-dartlang-fasta:///")),
         compiler = new BatchCompiler(null);
 
@@ -143,8 +166,8 @@
       Configuration configuration;
 
       Source source;
-      List<String> formatSpellingMistakes(
-          spell.SpellingResult spellResult, int offset, String message) {
+      List<String> formatSpellingMistakes(spell.SpellingResult spellResult,
+          int offset, String message, String messageForDenyListed) {
         if (source == null) {
           List<int> bytes = file.readAsBytesSync();
           List<int> lineStarts = new List<int>();
@@ -160,12 +183,20 @@
         for (int i = 0; i < spellResult.misspelledWords.length; i++) {
           Location location = source.getLocation(
               uri, offset + spellResult.misspelledWordsOffset[i]);
+          bool denylisted = spellResult.misspelledWordsDenylisted[i];
+          String messageToUse = message;
+          if (denylisted) {
+            messageToUse = messageForDenyListed;
+            reportedWordsDenylisted.add(spellResult.misspelledWords[i]);
+          } else {
+            reportedWords.add(spellResult.misspelledWords[i]);
+          }
           result.add(command_line_reporting.formatErrorMessage(
               source.getTextLine(location.line),
               location,
               spellResult.misspelledWords[i].length,
               relativize(uri),
-              "$message: '${spellResult.misspelledWords[i]}'."));
+              "$messageToUse: '${spellResult.misspelledWords[i]}'."));
         }
         return result;
       }
@@ -190,7 +221,10 @@
               spellingMessages.addAll(formatSpellingMistakes(
                   spellingResult,
                   node.span.start.offset,
-                  "Template likely has the following spelling mistake"));
+                  "Template has the following word that is "
+                      "not in our dictionary",
+                  "Template has the following word that is "
+                      "on our deny-list"));
             }
             break;
 
@@ -206,7 +240,10 @@
               spellingMessages.addAll(formatSpellingMistakes(
                   spellingResult,
                   node.span.start.offset,
-                  "Tip likely has the following spelling mistake"));
+                  "Tip has the following word that is "
+                      "not in our dictionary",
+                  "Tip has the following word that is "
+                      "on our deny-list"));
             }
             break;
 
@@ -745,7 +782,8 @@
 Future<MessageTestSuite> createContext(
     Chain suite, Map<String, String> environment) async {
   final bool fastOnly = environment["fastOnly"] == "true";
-  return new MessageTestSuite(fastOnly);
+  final bool interactive = environment["interactive"] == "true";
+  return new MessageTestSuite(fastOnly, interactive);
 }
 
 String relativize(Uri uri) {
diff --git a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
index a3abfd1..5445a78 100644
--- a/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
+++ b/pkg/front_end/test/fasta/parser/token_stream_rewriter_test.dart
@@ -5,16 +5,17 @@
 import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart';
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'
     show ScannerResult, scanString;
-import 'package:_fe_analyzer_shared/src/scanner/token.dart' show Token;
+import 'package:_fe_analyzer_shared/src/scanner/token.dart'
+    show ReplacementToken, Token, TokenType;
 import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(TokenStreamGhostWriterTest);
     defineReflectiveTests(TokenStreamRewriterTest_NoPrevious);
     defineReflectiveTests(TokenStreamRewriterTest_UsingPrevious);
+    defineReflectiveTests(TokenStreamRewriterTest_Undoable);
   });
 }
 
@@ -23,13 +24,20 @@
   /// Indicates whether the tests should set up [Token.previous].
   bool get setPrevious;
 
+  TokenStreamRewriter getTokenStreamRewriter();
+
+  void setupDone(Token first) {}
+  void normalTestDone(TokenStreamRewriter rewriter, Token first) {}
+
   void test_insertParens() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamRewriterImpl();
-    var openParen = rewriter.insertParens(a, false);
-    var closeParen = openParen.next;
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token eof = _link([a, b]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
+    Token openParen = rewriter.insertParens(a, false);
+    Token closeParen = openParen.next;
 
     expect(openParen.lexeme, '(');
     expect(closeParen.lexeme, ')');
@@ -42,16 +50,20 @@
     expect(b.previous, same(closeParen));
     expect(closeParen.previous, same(openParen));
     expect(openParen.previous, same(a));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_insertParensWithIdentifier() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamRewriterImpl();
-    var openParen = rewriter.insertParens(a, true);
-    var identifier = openParen.next;
-    var closeParen = identifier.next;
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token eof = _link([a, b]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
+    Token openParen = rewriter.insertParens(a, true);
+    Token identifier = openParen.next;
+    Token closeParen = identifier.next;
 
     expect(openParen.lexeme, '(');
     expect(identifier.lexeme, '');
@@ -68,14 +80,18 @@
     expect(closeParen.previous, same(identifier));
     expect(identifier.previous, same(openParen));
     expect(openParen.previous, same(a));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_insertSyntheticIdentifier() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamRewriterImpl();
-    var identifier = rewriter.insertSyntheticIdentifier(a);
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token eof = _link([a, b]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
+    Token identifier = rewriter.insertSyntheticIdentifier(a);
 
     expect(identifier.lexeme, '');
     expect(identifier.isSynthetic, isTrue);
@@ -86,39 +102,51 @@
 
     expect(b.previous, same(identifier));
     expect(identifier.previous, same(a));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_insertToken_end() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a]);
-    var rewriter = new TokenStreamRewriterImpl();
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token eof = _link([a]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
     expect(rewriter.insertToken(a, b), same(b));
     expect(a.next, same(b));
     expect(b.next, same(eof));
     expect(eof.previous, same(b));
     expect(b.previous, same(a));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_insertToken_middle() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token c = _makeToken(2, 'c');
     _link([a, c]);
-    var rewriter = new TokenStreamRewriterImpl();
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
     rewriter.insertToken(a, b);
     expect(a.next, same(b));
     expect(b.next, same(c));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_insertToken_second_insertion_earlier_in_stream() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
-    var e = _makeToken(4, 'e');
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token c = _makeToken(2, 'c');
+    Token d = _makeToken(3, 'd');
+    Token e = _makeToken(4, 'e');
     _link([a, c, e]);
-    var rewriter = new TokenStreamRewriterImpl();
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
     rewriter.insertToken(c, d);
     expect(c.next, same(d));
     expect(d.next, same(e));
@@ -127,52 +155,113 @@
     rewriter.insertToken(a, b);
     expect(a.next, same(b));
     expect(b.next, same(c));
+
+    normalTestDone(rewriter, a);
+  }
+
+  void test_replaceNextTokenWithSyntheticToken_1() {
+    Token a = _makeToken(0, 'a');
+    StringToken b = _makeToken(5, 'b');
+    b.precedingComments = new CommentToken.fromSubstring(
+        TokenType.SINGLE_LINE_COMMENT, "Test comment", 1, 9, 1,
+        canonicalize: true);
+    Token c = _makeToken(10, 'c');
+    _link([a, b, c]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
+    ReplacementToken replacement =
+        rewriter.replaceNextTokenWithSyntheticToken(a, TokenType.AMPERSAND);
+    expect(b.offset, same(replacement.offset));
+    expect(b.precedingComments, same(replacement.precedingComments));
+    expect(replacement.replacedToken, same(b));
+
+    expect(a.next, same(replacement));
+    expect(replacement.next, same(c));
+    expect(c.next.isEof, true);
+
+    normalTestDone(rewriter, a);
+  }
+
+  void test_replaceNextTokenWithSyntheticToken_2() {
+    Token a = _makeToken(0, 'a');
+    StringToken b = _makeToken(5, 'b');
+    b.precedingComments = new CommentToken.fromSubstring(
+        TokenType.SINGLE_LINE_COMMENT, "Test comment", 1, 9, 1,
+        canonicalize: true);
+    _link([a, b]);
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
+    ReplacementToken replacement =
+        rewriter.replaceNextTokenWithSyntheticToken(a, TokenType.AMPERSAND);
+    expect(b.offset, same(replacement.offset));
+    expect(b.precedingComments, same(replacement.precedingComments));
+    expect(replacement.replacedToken, same(b));
+
+    expect(a.next, same(replacement));
+    expect(replacement.next.isEof, true);
+
+    normalTestDone(rewriter, a);
   }
 
   void test_moveSynthetic() {
     ScannerResult scanResult = scanString('Foo(bar; baz=0;');
     expect(scanResult.hasErrors, isTrue);
+    Token firstToken = scanResult.tokens;
+    setupDone(firstToken);
+
     Token open = scanResult.tokens.next.next;
     expect(open.lexeme, '(');
     Token close = open.endGroup;
     expect(close.isSynthetic, isTrue);
     expect(close.next.isEof, isTrue);
-    var rewriter = new TokenStreamRewriterImpl();
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
 
     Token result = rewriter.moveSynthetic(open.next, close);
     expect(result, close);
     expect(open.endGroup, close);
     expect(open.next.next, close);
     expect(close.next.isEof, isFalse);
+
+    normalTestDone(rewriter, firstToken);
   }
 
   void test_replaceTokenFollowing_multiple() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
-    var e = _makeToken(4, 'e');
-    var f = _makeToken(5, 'f');
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token c = _makeToken(2, 'c');
+    Token d = _makeToken(3, 'd');
+    Token e = _makeToken(4, 'e');
+    Token f = _makeToken(5, 'f');
     _link([a, b, e, f]);
     _link([c, d]);
-    var rewriter = new TokenStreamRewriterImpl();
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
     rewriter.replaceTokenFollowing(b, c);
     expect(a.next, same(b));
     expect(b.next, same(c));
     expect(c.next, same(d));
     expect(d.next, same(f));
+
+    normalTestDone(rewriter, a);
   }
 
   void test_replaceTokenFollowing_single() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
+    Token a = _makeToken(0, 'a');
+    Token b = _makeToken(1, 'b');
+    Token c = _makeToken(2, 'c');
+    Token d = _makeToken(3, 'd');
     _link([a, b, d]);
-    var rewriter = new TokenStreamRewriterImpl();
+    setupDone(a);
+
+    TokenStreamRewriter rewriter = getTokenStreamRewriter();
     rewriter.replaceTokenFollowing(a, c);
     expect(a.next, same(c));
     expect(c.next, same(d));
+
+    normalTestDone(rewriter, a);
   }
 
   /// Links together the given [tokens] and adds an EOF token to the end of the
@@ -182,7 +271,7 @@
   Token _link(Iterable<Token> tokens) {
     Token head = new Token.eof(-1);
     if (!setPrevious) head.previous = null;
-    for (var token in tokens) {
+    for (Token token in tokens) {
       head.next = token;
       if (setPrevious) token.previous = head;
       head = token;
@@ -210,6 +299,8 @@
 class TokenStreamRewriterTest_NoPrevious extends TokenStreamRewriterTest {
   @override
   bool get setPrevious => false;
+
+  TokenStreamRewriter getTokenStreamRewriter() => new TokenStreamRewriterImpl();
 }
 
 /// Concrete implementation of [TokenStreamRewriterTest] in which
@@ -222,202 +313,78 @@
 class TokenStreamRewriterTest_UsingPrevious extends TokenStreamRewriterTest {
   @override
   bool get setPrevious => true;
+
+  TokenStreamRewriter getTokenStreamRewriter() => new TokenStreamRewriterImpl();
 }
 
+/// Concrete implementation of [TokenStreamRewriterTest] in which
+/// the [UndoableTokenStreamRewriter] is used.
 @reflectiveTest
-class TokenStreamGhostWriterTest extends TokenStreamRewriterTest {
+class TokenStreamRewriterTest_Undoable extends TokenStreamRewriterTest {
   @override
-  bool get setPrevious => false;
+  bool get setPrevious => true;
 
-  void test_insertParens() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamGhostWriter();
-    var openParen = rewriter.insertParens(a, false);
-    var closeParen = openParen.next;
+  TokenStreamRewriter getTokenStreamRewriter() =>
+      new UndoableTokenStreamRewriter();
 
-    expect(openParen.lexeme, '(');
-    expect(closeParen.lexeme, ')');
+  List<CachedTokenSetup> setup;
 
-    expect(a.next, same(b));
-    expect(openParen.next, same(closeParen));
-    expect(closeParen.next, same(b));
-    expect(b.next, same(eof));
-
-    expect(b.previous, isNull);
-    expect(closeParen.previous, isNull);
-    expect(openParen.previous, isNull);
+  void setupDone(Token first) {
+    setup = [];
+    Token token = first;
+    while (token != null && !token.isEof) {
+      setup.add(new CachedTokenSetup(token));
+      token = token.next;
+    }
   }
 
-  void test_insertParensWithIdentifier() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamGhostWriter();
-    var openParen = rewriter.insertParens(a, true);
-    var identifier = openParen.next;
-    var closeParen = identifier.next;
+  void normalTestDone(TokenStreamRewriter rewriter, Token first) {
+    UndoableTokenStreamRewriter undoableTokenStreamRewriter = rewriter;
+    undoableTokenStreamRewriter.undo();
+    List<CachedTokenSetup> now = [];
+    Token token = first;
+    while (token != null && !token.isEof) {
+      now.add(new CachedTokenSetup(token));
+      token = token.next;
+    }
+    if (setup.length != now.length) {
+      throw "Different length: ${setup.length} vs ${now.length}";
+    }
+    for (int i = 0; i < setup.length; i++) {
+      if (setup[i] != now[i]) {
+        throw "Different at $i: ${setup[i]} vs ${now[i]}";
+      }
+    }
+    setup = null;
+  }
+}
 
-    expect(openParen.lexeme, '(');
-    expect(identifier.lexeme, '');
-    expect(identifier.isSynthetic, isTrue);
-    expect(closeParen.lexeme, ')');
+class CachedTokenSetup {
+  final Token token;
+  final Token prev;
+  final Token next;
+  final Token precedingComments;
 
-    expect(a.next, same(b));
-    expect(openParen.next, same(identifier));
-    expect(identifier.next, same(closeParen));
-    expect(closeParen.next, same(b));
-    expect(b.next, same(eof));
+  CachedTokenSetup(this.token)
+      : prev = token.previous,
+        next = token.next,
+        precedingComments = token.precedingComments;
 
-    expect(b.previous, isNull);
-    expect(closeParen.previous, isNull);
-    expect(identifier.previous, isNull);
-    expect(openParen.previous, isNull);
+  bool operator ==(Object other) {
+    if (other is! CachedTokenSetup) return false;
+    CachedTokenSetup o = other;
+    return token == o.token &&
+        prev == o.prev &&
+        next == o.next &&
+        precedingComments == o.precedingComments;
   }
 
-  void test_insertSyntheticIdentifier() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a, b]);
-    var rewriter = new TokenStreamGhostWriter();
-    var identifier = rewriter.insertSyntheticIdentifier(a);
-
-    expect(identifier.lexeme, '');
-    expect(identifier.isSynthetic, isTrue);
-
-    expect(a.next, same(b));
-    expect(identifier.next, same(b));
-    expect(b.next, same(eof));
-
-    expect(b.previous, isNull);
-    expect(identifier.previous, isNull);
-  }
-
-  void test_insertToken_end() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var eof = _link([a]);
-    var rewriter = new TokenStreamGhostWriter();
-
-    expect(rewriter.insertToken(a, b), same(b));
-    expect(a.next, same(eof));
-    expect(b.next, same(eof));
-
-    expect(eof.previous, isNull);
-    expect(b.previous, isNull);
-  }
-
-  void test_insertToken_middle() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    _link([a, c]);
-
-    var rewriter = new TokenStreamGhostWriter();
-    rewriter.insertToken(a, b);
-    expect(a.next, same(c));
-    expect(b.next, same(c));
-
-    expect(a.previous, isNull);
-    expect(b.previous, isNull);
-    expect(c.previous, isNull);
-  }
-
-  void test_insertToken_second_insertion_earlier_in_stream() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
-    var e = _makeToken(4, 'e');
-    _link([a, c, e]);
-    var rewriter = new TokenStreamGhostWriter();
-
-    rewriter.insertToken(c, d);
-    expect(c.next, same(e));
-    expect(d.next, same(e));
-
-    // The next call to rewriter should be able to find the insertion point
-    // even though it is before the insertion point used above.
-    rewriter.insertToken(a, b);
-    expect(a.next, same(c));
-    expect(b.next, same(c));
-
-    expect(a.previous, isNull);
-    expect(b.previous, isNull);
-    expect(c.previous, isNull);
-    expect(d.previous, isNull);
-    expect(e.previous, isNull);
-  }
-
-  void test_moveSynthetic() {
-    ScannerResult scanResult = scanString('Foo(bar; baz=0;');
-    expect(scanResult.hasErrors, isTrue);
-    Token open = scanResult.tokens.next.next;
-    expect(open.lexeme, '(');
-    Token semicolon = open.next.next;
-    expect(semicolon.lexeme, ';');
-    Token close = open.endGroup;
-    expect(close.isSynthetic, isTrue);
-    expect(close.next.isEof, isTrue);
-    Token semicolon2 = close.previous;
-    expect(semicolon2.lexeme, ';');
-    var rewriter = new TokenStreamGhostWriter();
-
-    Token newClose = rewriter.moveSynthetic(open.next, close);
-    expect(newClose, isNot(same(close)));
-    expect(newClose.next, same(semicolon));
-    expect(open.endGroup, close);
-    expect(open.next.next, semicolon);
-    expect(close.next.isEof, isTrue);
-
-    expect(newClose.previous, isNull);
-    expect(close.next.previous, close);
-    expect(close.previous, semicolon2);
-  }
-
-  void test_replaceTokenFollowing_multiple() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
-    var e = _makeToken(4, 'e');
-    var f = _makeToken(5, 'f');
-    _link([a, b, e, f]);
-    _link([c, d]);
-    var rewriter = new TokenStreamGhostWriter();
-    Token result = rewriter.replaceTokenFollowing(b, c);
-
-    expect(result, same(c));
-    expect(a.next, same(b));
-    expect(b.next, same(e));
-    expect(e.next, same(f));
-    expect(c.next, same(d));
-    expect(d.next, same(f));
-
-    expect(a.previous, isNull);
-    expect(b.previous, isNull);
-    expect(c.previous, isNull);
-    expect(d.previous, isNull);
-    expect(e.previous, isNull);
-  }
-
-  void test_replaceTokenFollowing_single() {
-    var a = _makeToken(0, 'a');
-    var b = _makeToken(1, 'b');
-    var c = _makeToken(2, 'c');
-    var d = _makeToken(3, 'd');
-    _link([a, b, d]);
-    var rewriter = new TokenStreamGhostWriter();
-    Token result = rewriter.replaceTokenFollowing(a, c);
-
-    expect(result, same(c));
-    expect(a.next, same(b));
-    expect(b.next, same(d));
-    expect(c.next, same(d));
-
-    expect(a.previous, isNull);
-    expect(b.previous, isNull);
-    expect(c.previous, isNull);
+  String toString() {
+    return "CachedTokenSetup["
+        "token = $token, "
+        "prev = $prev, "
+        "next = $next, "
+        "precedingComments = $precedingComments"
+        "]";
   }
 }
diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart
index 2905b1b..ed80870 100644
--- a/pkg/front_end/test/fasta/testing/suite.dart
+++ b/pkg/front_end/test/fasta/testing/suite.dart
@@ -22,6 +22,9 @@
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions, DiagnosticMessage;
 
+import 'package:front_end/src/api_prototype/constant_evaluator.dart'
+    show ConstantEvaluator, ErrorReporter, EvaluationMode;
+
 import 'package:front_end/src/api_prototype/experimental_flags.dart'
     show
         AllowedExperimentalFlags,
@@ -59,18 +62,39 @@
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
 
+import 'package:front_end/src/fasta/messages.dart' show LocatedMessage;
+
 import 'package:front_end/src/fasta/ticker.dart' show Ticker;
 
 import 'package:front_end/src/fasta/uri_translator.dart' show UriTranslator;
 
+import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
+
 import 'package:kernel/ast.dart'
-    show AwaitExpression, Component, Library, Node, Version, Visitor;
+    show
+        AwaitExpression,
+        BasicLiteral,
+        Component,
+        Constant,
+        ConstantExpression,
+        Expression,
+        FileUriExpression,
+        FileUriNode,
+        InvalidExpression,
+        Library,
+        Member,
+        Node,
+        TreeNode,
+        UnevaluatedConstant,
+        Version,
+        Visitor;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
-import 'package:kernel/kernel.dart' show loadComponentFromBytes;
+import 'package:kernel/kernel.dart'
+    show RecursiveVisitor, loadComponentFromBytes;
 
 import 'package:kernel/reference_from_index.dart' show ReferenceFromIndex;
 
@@ -78,7 +102,26 @@
     show ChangedStructureNotifier;
 
 import 'package:kernel/target/targets.dart'
-    show NoneTarget, Target, TargetFlags, DiagnosticReporter;
+    show
+        ConstantsBackend,
+        DiagnosticReporter,
+        NoneConstantsBackend,
+        NoneTarget,
+        Target,
+        TargetFlags;
+
+import 'package:kernel/target/targets.dart'
+    show
+        ConstantsBackend,
+        DiagnosticReporter,
+        NoneConstantsBackend,
+        NoneTarget,
+        NumberSemantics,
+        Target,
+        TargetFlags;
+
+import 'package:kernel/type_environment.dart'
+    show StaticTypeContext, TypeEnvironment;
 
 import 'package:testing/testing.dart'
     show
@@ -101,7 +144,6 @@
         MatchExpectation,
         Print,
         TypeCheck,
-        Verify,
         WriteDill;
 
 import '../../utils/validating_instrumentation.dart'
@@ -111,6 +153,9 @@
 
 const String ENABLE_FULL_COMPILE = " full compile ";
 
+const String UPDATE_EXPECTATIONS = "updateExpectations";
+const String UPDATE_COMMENTS = "updateComments";
+
 const String EXPECTATIONS = '''
 [
   {
@@ -154,6 +199,7 @@
 
 const String experimentalFlagOptions = '--enable-experiment=';
 const String overwriteCurrentSdkVersion = '--overwrite-current-sdk-version=';
+const String noVerifyCmd = '--no-verify';
 
 /// Options used for all tests within a given folder.
 ///
@@ -162,24 +208,36 @@
 class FolderOptions {
   final Map<ExperimentalFlag, bool> _experimentalFlags;
   final bool forceLateLowering;
+  final bool forceLateLoweringSentinel;
   final bool forceStaticFieldLowering;
   final bool forceNoExplicitGetterCalls;
   final bool nnbdAgnosticMode;
+  final Map<String, String> defines;
+  final bool noVerify;
   final String target;
   final String overwriteCurrentSdkVersion;
 
   FolderOptions(this._experimentalFlags,
       {this.forceLateLowering: false,
+      this.forceLateLoweringSentinel: false,
       this.forceStaticFieldLowering: false,
       this.forceNoExplicitGetterCalls: false,
       this.nnbdAgnosticMode: false,
+      this.defines: const {},
+      this.noVerify: false,
       this.target: "vm",
       // can be null
       this.overwriteCurrentSdkVersion})
       : assert(forceLateLowering != null),
+        assert(forceLateLoweringSentinel != null),
         assert(forceStaticFieldLowering != null),
         assert(forceNoExplicitGetterCalls != null),
         assert(nnbdAgnosticMode != null),
+        assert(
+            // no this doesn't make any sense but left to underline
+            // that this is allowed to be null!
+            defines != null || defines == null),
+        assert(noVerify != null),
         assert(target != null);
 
   Map<ExperimentalFlag, bool> computeExperimentalFlags(
@@ -235,6 +293,9 @@
   final bool updateExpectations;
 
   @override
+  String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
+
+  @override
   final ExpectationSet expectationSet =
       new ExpectationSet.fromJsonList(jsonDecode(EXPECTATIONS));
 
@@ -270,6 +331,14 @@
       fullPrefix = '.strong';
       outlinePrefix = '.outline';
     }
+
+    if (!fullCompile) {
+      // If not doing a full compile this is the only expect file so we run the
+      // extra constant evaluation now. If we do a full compilation, we'll do
+      // if after the transformation. That also ensures we don't get the same
+      // 'extra constant evaluation' output twice (in .transformed and not).
+      steps.add(const StressConstantEvaluatorStep());
+    }
     if (!ignoreExpectations) {
       steps.add(new MatchExpectation(
           fullCompile ? "$fullPrefix.expect" : "$outlinePrefix.expect",
@@ -289,20 +358,13 @@
     }
     if (fullCompile) {
       steps.add(const Transform());
+      steps.add(const StressConstantEvaluatorStep());
       if (!ignoreExpectations) {
-        steps.add(new MatchExpectation(
-            fullCompile
-                ? "$fullPrefix.transformed.expect"
-                : "$outlinePrefix.transformed.expect",
-            serializeFirst: false,
-            isLastMatchStep: updateExpectations));
+        steps.add(new MatchExpectation("$fullPrefix.transformed.expect",
+            serializeFirst: false, isLastMatchStep: updateExpectations));
         if (!updateExpectations) {
-          steps.add(new MatchExpectation(
-              fullCompile
-                  ? "$fullPrefix.transformed.expect"
-                  : "$outlinePrefix.transformed.expect",
-              serializeFirst: true,
-              isLastMatchStep: true));
+          steps.add(new MatchExpectation("$fullPrefix.transformed.expect",
+              serializeFirst: true, isLastMatchStep: true));
         }
       }
       steps.add(const EnsureNoErrors());
@@ -317,16 +379,22 @@
     FolderOptions folderOptions = _folderOptions[directory.uri];
     if (folderOptions == null) {
       bool forceLateLowering = false;
+      bool forceLateLoweringSentinel = false;
       bool forceStaticFieldLowering = false;
       bool forceNoExplicitGetterCalls = false;
       bool nnbdAgnosticMode = false;
+      bool noVerify = false;
+      Map<String, String> defines = {};
       String target = "vm";
       if (directory.uri == baseUri) {
         folderOptions = new FolderOptions({},
             forceLateLowering: forceLateLowering,
+            forceLateLoweringSentinel: forceLateLoweringSentinel,
             forceStaticFieldLowering: forceStaticFieldLowering,
             forceNoExplicitGetterCalls: forceNoExplicitGetterCalls,
             nnbdAgnosticMode: nnbdAgnosticMode,
+            defines: defines,
+            noVerify: noVerify,
             target: target);
       } else {
         File optionsFile =
@@ -342,6 +410,8 @@
             } else if (line.startsWith(overwriteCurrentSdkVersion)) {
               overwriteCurrentSdkVersionArgument =
                   line.substring(overwriteCurrentSdkVersion.length);
+            } else if (line.startsWith(Flags.forceLateLoweringSentinel)) {
+              forceLateLoweringSentinel = true;
             } else if (line.startsWith(Flags.forceLateLowering)) {
               forceLateLowering = true;
             } else if (line.startsWith(Flags.forceStaticFieldLowering)) {
@@ -352,6 +422,38 @@
               forceNoExplicitGetterCalls = true;
             } else if (line.startsWith(Flags.nnbdAgnosticMode)) {
               nnbdAgnosticMode = true;
+            } else if (line.startsWith(Flags.noDefines)) {
+              if (defines == null) {
+                throw "Specifying ${Flags.noDefines} several times "
+                    "is unsupported.";
+              }
+              if (defines.isNotEmpty) {
+                throw "Can't have no defines and specific defines "
+                    "at the same time.";
+              }
+              defines = null;
+            } else if (line.startsWith("-D")) {
+              if (defines == null) {
+                throw "Can't have no defines and specific defines "
+                    "at the same time.";
+              }
+              String define = line.substring(2); // removes "-D".
+              int index = define.indexOf('=');
+              String name;
+              String expression;
+              if (index != -1) {
+                name = define.substring(0, index);
+                expression = define.substring(index + 1);
+              } else {
+                name = define;
+                expression = define;
+              }
+              if (defines.containsKey(name)) {
+                throw "Defining '$name' several times is unsupported.";
+              }
+              defines[name] = expression;
+            } else if (line.startsWith(noVerifyCmd)) {
+              noVerify = true;
             } else if (line.startsWith(Flags.target) &&
                 line.indexOf('=') == Flags.target.length) {
               target = line.substring(Flags.target.length + 1);
@@ -367,9 +469,12 @@
                   onWarning: (String message) =>
                       throw new ArgumentError(message)),
               forceLateLowering: forceLateLowering,
+              forceLateLoweringSentinel: forceLateLoweringSentinel,
               forceStaticFieldLowering: forceStaticFieldLowering,
               forceNoExplicitGetterCalls: forceNoExplicitGetterCalls,
               nnbdAgnosticMode: nnbdAgnosticMode,
+              defines: defines,
+              noVerify: noVerify,
               target: target,
               overwriteCurrentSdkVersion: overwriteCurrentSdkVersionArgument);
         } else {
@@ -404,7 +509,7 @@
         }
         ..sdkRoot = sdk
         ..packagesFileUri = uriConfiguration.packageConfigUri ?? packages
-        ..environmentDefines = {}
+        ..environmentDefines = folderOptions.defines
         ..experimentalFlags =
             folderOptions.computeExperimentalFlags(experimentalFlags)
         ..nnbdMode = weak
@@ -588,8 +693,8 @@
     bool weak = environment["weak"] == "true";
     bool onlyCrashes = environment["onlyCrashes"] == "true";
     bool ignoreExpectations = environment["ignoreExpectations"] == "true";
-    bool updateExpectations = environment["updateExpectations"] == "true";
-    bool updateComments = environment["updateComments"] == "true";
+    bool updateExpectations = environment[UPDATE_EXPECTATIONS] == "true";
+    bool updateComments = environment[UPDATE_COMMENTS] == "true";
     bool skipVm = environment["skipVm"] == "true";
     bool verify = environment["verify"] != "false";
     bool kernelTextSerialization =
@@ -654,6 +759,7 @@
         }
         return process.toResult();
       case "none":
+      case "noneWithJs":
         return pass(0);
       default:
         throw new ArgumentError(
@@ -662,6 +768,182 @@
   }
 }
 
+class StressConstantEvaluatorStep
+    extends Step<ComponentResult, ComponentResult, FastaContext> {
+  const StressConstantEvaluatorStep();
+
+  String get name => "stress constant evaluator";
+
+  Future<Result<ComponentResult>> run(
+      ComponentResult result, FastaContext context) async {
+    KernelTarget target = result.sourceTarget;
+    ConstantsBackend constantsBackend =
+        target.backendTarget.constantsBackend(target.loader.coreTypes);
+    TypeEnvironment environment =
+        new TypeEnvironment(target.loader.coreTypes, target.loader.hierarchy);
+    StressConstantEvaluatorVisitor stressConstantEvaluatorVisitor =
+        new StressConstantEvaluatorVisitor(
+      constantsBackend,
+      result.options.environmentDefines,
+      target.isExperimentEnabledGlobally(ExperimentalFlag.tripleShift),
+      environment,
+      !target.backendTarget.supportsSetLiterals,
+      result.options.errorOnUnevaluatedConstant,
+      target.getConstantEvaluationModeForTesting(),
+    );
+    for (Library lib in result.component.libraries) {
+      if (!result.isUserLibrary(lib)) continue;
+      lib.accept(stressConstantEvaluatorVisitor);
+    }
+    if (stressConstantEvaluatorVisitor.success > 0) {
+      result.extraConstantStrings.addAll(stressConstantEvaluatorVisitor.output);
+      result.extraConstantStrings.add("Extra constant evaluation: "
+          "evaluated: ${stressConstantEvaluatorVisitor.tries}, "
+          "effectively constant: ${stressConstantEvaluatorVisitor.success}");
+    }
+    return pass(result);
+  }
+}
+
+class StressConstantEvaluatorVisitor extends RecursiveVisitor<Node>
+    implements ErrorReporter {
+  ConstantEvaluator constantEvaluator;
+  ConstantEvaluator constantEvaluatorWithEmptyEnvironment;
+  int tries = 0;
+  int success = 0;
+  List<String> output = [];
+
+  StressConstantEvaluatorVisitor(
+      ConstantsBackend backend,
+      Map<String, String> environmentDefines,
+      bool enableTripleShift,
+      TypeEnvironment typeEnvironment,
+      bool desugarSets,
+      bool errorOnUnevaluatedConstant,
+      EvaluationMode evaluationMode) {
+    constantEvaluator = new ConstantEvaluator(
+        backend, environmentDefines, typeEnvironment, this,
+        desugarSets: desugarSets,
+        enableTripleShift: enableTripleShift,
+        errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
+        evaluationMode: evaluationMode);
+    constantEvaluatorWithEmptyEnvironment = new ConstantEvaluator(
+        backend, {}, typeEnvironment, this,
+        desugarSets: desugarSets,
+        enableTripleShift: enableTripleShift,
+        errorOnUnevaluatedConstant: errorOnUnevaluatedConstant,
+        evaluationMode: evaluationMode);
+  }
+
+  Library currentLibrary;
+  Library visitLibrary(Library node) {
+    currentLibrary = node;
+    node.visitChildren(this);
+    currentLibrary = null;
+    return node;
+  }
+
+  Member currentMember;
+
+  Node defaultMember(Member node) {
+    Member prevCurrentMember = currentMember;
+    currentMember = node;
+    node.visitChildren(this);
+    currentMember = prevCurrentMember;
+    return node;
+  }
+
+  Node defaultExpression(Expression node) {
+    if (node is BasicLiteral) return node;
+    if (node is InvalidExpression) return node;
+    if (node is ConstantExpression) {
+      bool evaluate = false;
+      if (node.constant is UnevaluatedConstant) {
+        UnevaluatedConstant unevaluatedConstant = node.constant;
+        if (unevaluatedConstant.expression is! InvalidExpression) {
+          evaluate = true;
+        }
+      }
+      if (!evaluate) return node;
+      if (constantEvaluator.environmentDefines != null) {
+        throw "Unexpected UnevaluatedConstant "
+            "when the environment is not null.";
+      }
+    }
+
+    // Try to evaluate it as a constant.
+    tries++;
+    StaticTypeContext staticTypeContext;
+    if (currentMember == null) {
+      staticTypeContext = new StaticTypeContext.forAnnotations(
+          currentLibrary, constantEvaluator.typeEnvironment);
+    } else {
+      staticTypeContext = new StaticTypeContext(
+          currentMember, constantEvaluator.typeEnvironment);
+    }
+    Constant x = constantEvaluator.evaluate(staticTypeContext, node);
+    bool evaluatedWithEmptyEnvironment = false;
+    if (x is UnevaluatedConstant && x.expression is! InvalidExpression) {
+      // try with an environment
+      if (constantEvaluator.environmentDefines != null) {
+        throw "Unexpected UnevaluatedConstant (with an InvalidExpression in "
+            "it) when the environment is not null.";
+      }
+      x = constantEvaluatorWithEmptyEnvironment.evaluate(
+          new StaticTypeContext(
+              currentMember, constantEvaluator.typeEnvironment),
+          new ConstantExpression(x));
+      evaluatedWithEmptyEnvironment = true;
+    }
+    if (x is UnevaluatedConstant) {
+      if (x.expression is! InvalidExpression &&
+          x.expression is! FileUriExpression) {
+        throw "Unexpected ${x.runtimeType} with "
+            "${x.expression.runtimeType} inside.";
+      }
+      node.visitChildren(this);
+    } else {
+      success++;
+      if (!evaluatedWithEmptyEnvironment) {
+        output
+            .add("Evaluated: ${node.runtimeType} @ ${getLocation(node)} -> $x");
+        // Don't recurse into children - theoretically we could replace this
+        // node with a constant expression.
+      } else {
+        output.add("Evaluated with empty environment: "
+            "${node.runtimeType} @ ${getLocation(node)} -> $x");
+        // Here we (for now) recurse into children.
+        node.visitChildren(this);
+      }
+    }
+    return node;
+  }
+
+  String getLocation(TreeNode node) {
+    try {
+      return node.location.toString();
+    } catch (e) {
+      TreeNode n = node;
+      while (n != null && n is! FileUriNode) {
+        n = n.parent;
+      }
+      if (n == null) return "(unknown location)";
+      FileUriNode fileUriNode = n;
+      return ("(unknown position in ${fileUriNode.fileUri})");
+    }
+  }
+
+  @override
+  void report(LocatedMessage message, List<LocatedMessage> context) {
+    // ignored.
+  }
+
+  @override
+  void reportInvalidExpression(InvalidExpression node) {
+    // ignored.
+  }
+}
+
 class Outline extends Step<TestDescription, ComponentResult, FastaContext> {
   final bool fullCompile;
 
@@ -703,7 +985,7 @@
         ..onDiagnostic = (DiagnosticMessage message) {
           errors.add(message.plainTextFormatted);
         }
-        ..environmentDefines = {}
+        ..environmentDefines = folderOptions.defines
         ..experimentalFlags = experimentalFlags
         ..nnbdMode = nnbdMode
         ..librariesSpecificationUri = librariesSpecificationUri
@@ -746,7 +1028,8 @@
         }
         Component p = await sourceTarget.buildOutlines();
         if (fullCompile) {
-          p = await sourceTarget.buildComponent(verify: context.verify);
+          p = await sourceTarget.buildComponent(
+              verify: folderOptions.noVerify ? false : context.verify);
         }
 
         // To avoid possible crash in mixin transformation in the transformation
@@ -809,21 +1092,25 @@
       userLibraries.addAll(uriTranslator.dartLibraries.allLibraries
           .map((LibraryInfo info) => info.importUri));
       if (fullCompile) {
-        p = await sourceTarget.buildComponent(verify: context.verify);
+        p = await sourceTarget.buildComponent(
+            verify: folderOptions.noVerify ? false : context.verify);
         instrumentation.finish();
         if (instrumentation.hasProblems) {
           if (updateComments) {
             await instrumentation.fixSource(description.uri, false);
           } else {
             return new Result<ComponentResult>(
-                new ComponentResult(description, p, userLibraries),
+                new ComponentResult(
+                    description, p, userLibraries, options, sourceTarget),
                 context.expectationSet["InstrumentationMismatch"],
                 instrumentation.problemsAsString,
-                null);
+                null,
+                autoFixCommand: '${UPDATE_COMMENTS}=true');
           }
         }
       }
-      return pass(new ComponentResult(description, p, userLibraries));
+      return pass(new ComponentResult(
+          description, p, userLibraries, options, sourceTarget));
     });
   }
 
@@ -839,6 +1126,8 @@
         await context.computeUriTranslator(description);
     TargetFlags targetFlags = new TargetFlags(
       forceLateLoweringForTesting: testOptions.forceLateLowering,
+      forceLateLoweringSentinelForTesting:
+          testOptions.forceLateLoweringSentinel,
       forceStaticFieldLoweringForTesting: testOptions.forceStaticFieldLowering,
       forceNoExplicitGetterCallsForTesting:
           testOptions.forceNoExplicitGetterCalls,
@@ -852,6 +1141,9 @@
       case "none":
         target = new NoneTarget(targetFlags);
         break;
+      case "noneWithJs":
+        target = new NoneWithJsTarget(targetFlags);
+        break;
       default:
         throw new ArgumentError(
             "Unsupported test target '${testOptions.target}'.");
@@ -909,6 +1201,48 @@
   }
 }
 
+class Verify extends Step<ComponentResult, ComponentResult, FastaContext> {
+  final bool fullCompile;
+
+  const Verify(this.fullCompile);
+
+  String get name => "verify";
+
+  Future<Result<ComponentResult>> run(
+      ComponentResult result, FastaContext context) async {
+    FolderOptions folderOptions =
+        context.computeFolderOptions(result.description);
+
+    if (folderOptions.noVerify) {
+      return pass(result);
+    }
+
+    Component component = result.component;
+    StringBuffer messages = new StringBuffer();
+    ProcessedOptions options = new ProcessedOptions(
+        options: new CompilerOptions()
+          ..onDiagnostic = (DiagnosticMessage message) {
+            if (messages.isNotEmpty) {
+              messages.write("\n");
+            }
+            messages.writeAll(message.plainTextFormatted, "\n");
+          });
+    return await CompilerContext.runWithOptions(options,
+        (compilerContext) async {
+      compilerContext.uriToSource.addAll(component.uriToSource);
+      List<LocatedMessage> verificationErrors = verifyComponent(component,
+          isOutline: !fullCompile, skipPlatform: true);
+      assert(verificationErrors.isEmpty || messages.isNotEmpty);
+      if (messages.isEmpty) {
+        return pass(result);
+      } else {
+        return new Result<ComponentResult>(null,
+            context.expectationSet["VerificationError"], "$messages", null);
+      }
+    }, errorOnMissingInput: false);
+  }
+}
+
 /// Visitor that checks that the component has been transformed properly.
 // TODO(johnniwinther): Add checks for all nodes that are unsupported after
 // transformation.
@@ -1023,3 +1357,19 @@
         packageConfigUri == other.packageConfigUri;
   }
 }
+
+class NoneWithJsTarget extends NoneTarget {
+  NoneWithJsTarget(TargetFlags flags) : super(flags);
+
+  @override
+  ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
+      const NoneConstantsBackendWithJs(supportsUnevaluatedConstants: true);
+}
+
+class NoneConstantsBackendWithJs extends NoneConstantsBackend {
+  const NoneConstantsBackendWithJs({bool supportsUnevaluatedConstants})
+      : super(supportsUnevaluatedConstants: supportsUnevaluatedConstants);
+
+  @override
+  NumberSemantics get numberSemantics => NumberSemantics.js;
+}
diff --git a/pkg/front_end/test/fasta/textual_outline_suite.dart b/pkg/front_end/test/fasta/textual_outline_suite.dart
index db5dda5..aeb3343 100644
--- a/pkg/front_end/test/fasta/textual_outline_suite.dart
+++ b/pkg/front_end/test/fasta/textual_outline_suite.dart
@@ -22,6 +22,7 @@
         runMe;
 
 import '../utils/kernel_chain.dart' show MatchContext;
+import 'testing/suite.dart' show UPDATE_EXPECTATIONS;
 
 const List<Map<String, String>> EXPECTATIONS = [
   {
@@ -52,6 +53,10 @@
 
 class Context extends ChainContext with MatchContext {
   final bool updateExpectations;
+
+  @override
+  String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
+
   Context(this.updateExpectations);
 
   final List<Step> steps = const <Step>[
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
index 0d4d9c9..5217ca9 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
@@ -661,7 +661,7 @@
           null,
           inferredTypes,
           testLib);
-      expect(inferredTypes[0], coreTypes.numNonNullableRawType);
+      expect(inferredTypes[0], coreTypes.numLegacyRawType);
     }
   }
 
@@ -1066,13 +1066,13 @@
 
     // TODO(dmitryas): Test for various nullabilities.
     testUpper("T", "T", "T", typeParameters: "T extends Object");
-    testUpper("T", "List<Never>", "List<Object>",
+    testUpper("T", "List<Never>", "List<Object?>",
         typeParameters: "T extends List<T>");
-    testUpper("List<Never>", "T", "List<Object>",
+    testUpper("List<Never>", "T", "List<Object?>",
         typeParameters: "T extends List<T>");
-    testUpper("T", "U", "List<Object>",
+    testUpper("T", "U", "List<Object?>",
         typeParameters: "T extends List<T>, U extends List<Never>");
-    testUpper("U", "T", "List<Object>",
+    testUpper("U", "T", "List<Object?>",
         typeParameters: "T extends List<T>, U extends List<Never>");
   }
 
diff --git a/pkg/front_end/test/fasta/types/shared_type_tests.dart b/pkg/front_end/test/fasta/types/shared_type_tests.dart
index 37a43e8..fa1d750 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -696,7 +696,7 @@
     // Tests for bottom and top types.
     isSubtype('Null', 'Null');
     isNotSubtype('Null', 'bottom');
-    isNotSubtype('Null', 'Never');
+    isObliviousSubtype('Null', 'Never');
     isSubtype('bottom', 'Null');
     isSubtype('bottom', 'bottom');
     isSubtype('bottom', 'Never');
@@ -889,7 +889,7 @@
     isSubtype('Never', 'Id<Object>');
     isSubtype('Never', 'Id<Never>');
     isSubtype('Id<Never>', 'Never');
-    isNotSubtype('Null', 'Id<Never>');
+    isObliviousSubtype('Null', 'Id<Never>');
     isSubtype('Id<Never>', 'Null');
     isNotSubtype('Id<Object>', 'Never');
     isSubtype('Id<int>', 'num');
diff --git a/pkg/front_end/test/id_tests/inheritance_test.dart b/pkg/front_end/test/id_tests/inheritance_test.dart
index a042a8a..39f382a 100644
--- a/pkg/front_end/test/id_tests/inheritance_test.dart
+++ b/pkg/front_end/test/id_tests/inheritance_test.dart
@@ -151,7 +151,7 @@
         return;
       }
 
-      String memberName = name.name;
+      String memberName = name.text;
       if (isSetter) {
         memberName += '=';
       }
diff --git a/pkg/front_end/test/incremental_compiler_leak_test.dart b/pkg/front_end/test/incremental_compiler_leak_test.dart
index 326c2e2..e526d98 100644
--- a/pkg/front_end/test/incremental_compiler_leak_test.dart
+++ b/pkg/front_end/test/incremental_compiler_leak_test.dart
@@ -1,11 +1,8 @@
 import 'dart:async';
 import 'dart:io';
 
-import "package:vm_service/vm_service.dart" as vmService;
-import "package:vm_service/vm_service_io.dart" as vmService;
-
-import "vm_service_heap_helper.dart" as helper;
 import "simple_stats.dart";
+import "vm_service_helper.dart" as vmService;
 
 const int limit = 10;
 
@@ -22,7 +19,7 @@
   ]);
 }
 
-class LeakFinder extends helper.LaunchingVMServiceHeapHelper {
+class LeakFinder extends vmService.LaunchingVMServiceHelper {
   @override
   Future<void> run() async {
     vmService.VM vm = await serviceClient.getVM();
@@ -39,15 +36,22 @@
         new Map<vmService.ClassRef, vmService.Class>();
 
     Completer<String> cTimeout = new Completer();
-    Timer timer = new Timer(new Duration(minutes: 4), () {
+    Timer timer = new Timer(new Duration(minutes: 6), () {
       cTimeout.complete("Timeout");
       killProcess();
     });
 
     Completer<String> cRunDone = new Completer();
     // ignore: unawaited_futures
-    runInternal(isolateRef, classInfo, instanceCounts,
-        () => cTimeout.isCompleted || cProcessExited.isCompleted).then((value) {
+    runInternal(
+        isolateRef,
+        classInfo,
+        instanceCounts,
+        (int iteration) =>
+            // Subtract 2 as it's logically one ahead and asks _before_ the run.
+            (iteration - 2) > limit ||
+            cTimeout.isCompleted ||
+            cProcessExited.isCompleted).then((value) {
       cRunDone.complete("Done");
     });
 
@@ -57,6 +61,9 @@
     print("\n\n======================\n\n");
 
     findPossibleLeaks(instanceCounts, classInfo);
+
+    // Make sure the process doesn't hang.
+    killProcess();
   }
 
   void findPossibleLeaks(Map<vmService.ClassRef, List<int>> instanceCounts,
@@ -118,11 +125,11 @@
       vmService.IsolateRef isolateRef,
       Map<vmService.ClassRef, vmService.Class> classInfo,
       Map<vmService.ClassRef, List<int>> instanceCounts,
-      bool Function() shouldBail) async {
+      bool Function(int iteration) shouldBail) async {
     int iterationNumber = 1;
     try {
       while (true) {
-        if (shouldBail()) break;
+        if (shouldBail(iterationNumber)) break;
         if (!await waitUntilPaused(isolateRef.id)) break;
         print("\n\n====================\n\nIteration #$iterationNumber");
         iterationNumber++;
diff --git a/pkg/front_end/test/incremental_load_from_dill_suite.dart b/pkg/front_end/test/incremental_load_from_dill_suite.dart
index 51255c1..768e1ba 100644
--- a/pkg/front_end/test/incremental_load_from_dill_suite.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_suite.dart
@@ -1013,7 +1013,7 @@
       if (info.lazyDeclaredGettersAndCalls != null) {
         sb.writeln("    - lazyDeclaredGettersAndCalls:");
         for (Member member in info.lazyDeclaredGettersAndCalls) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
 
         // Expect these to be the same as in the class.
@@ -1022,7 +1022,7 @@
           if (f.isStatic) continue;
           if (!f.hasImplicitGetter) continue;
           if (!members.remove(f)) {
-            throw "Didn't find ${f.name.name} in lazyDeclaredGettersAndCalls "
+            throw "Didn't find ${f.name.text} in lazyDeclaredGettersAndCalls "
                 "for ${c.name} in ${library.importUri}";
           }
         }
@@ -1030,19 +1030,19 @@
           if (p.isStatic) continue;
           if (p.isSetter) continue;
           if (!members.remove(p)) {
-            throw "Didn't find ${p.name.name} in lazyDeclaredGettersAndCalls "
+            throw "Didn't find ${p.name.text} in lazyDeclaredGettersAndCalls "
                 "for ${c.name} in ${library.importUri}";
           }
         }
         if (members.isNotEmpty) {
-          throw "Still have ${members.map((m) => m.name.name)} left "
+          throw "Still have ${members.map((m) => m.name.text)} left "
               "for ${c.name} in ${library.importUri}";
         }
       }
       if (info.lazyDeclaredSetters != null) {
         sb.writeln("    - lazyDeclaredSetters:");
         for (Member member in info.lazyDeclaredSetters) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
 
         // Expect these to be the same as in the class.
@@ -1062,32 +1062,32 @@
           }
         }
         if (members.isNotEmpty) {
-          throw "Still have ${members.map((m) => m.name.name)} left "
+          throw "Still have ${members.map((m) => m.name.text)} left "
               "for ${c.name} in ${library.importUri}";
         }
       }
       if (info.lazyImplementedGettersAndCalls != null) {
         sb.writeln("    - lazyImplementedGettersAndCalls:");
         for (Member member in info.lazyImplementedGettersAndCalls) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
       }
       if (info.lazyImplementedSetters != null) {
         sb.writeln("    - lazyImplementedSetters:");
         for (Member member in info.lazyImplementedSetters) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
       }
       if (info.lazyInterfaceGettersAndCalls != null) {
         sb.writeln("    - lazyInterfaceGettersAndCalls:");
         for (Member member in info.lazyInterfaceGettersAndCalls) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
       }
       if (info.lazyInterfaceSetters != null) {
         sb.writeln("    - lazyInterfaceSetters:");
         for (Member member in info.lazyInterfaceSetters) {
-          sb.writeln("      - ${member.name.name}");
+          sb.writeln("      - ${member.name.text}");
         }
       }
     }
@@ -1292,10 +1292,10 @@
       libContent.add("Class ${c.name}");
     }
     for (Procedure p in lib.procedures) {
-      libContent.add("Procedure ${p.name.name}");
+      libContent.add("Procedure ${p.name.text}");
     }
     for (Field f in lib.fields) {
-      libContent.add("Field ${f.name.name}");
+      libContent.add("Field ${f.name.text}");
     }
   }
   return actualContent;
@@ -1657,7 +1657,7 @@
 void doSimulateTransformer(Component c) {
   for (Library lib in c.libraries) {
     if (lib.fields
-        .where((f) => f.name.name == "unique_SimulateTransformer")
+        .where((f) => f.name.text == "unique_SimulateTransformer")
         .toList()
         .isNotEmpty) continue;
     Name fieldName = new Name("unique_SimulateTransformer");
@@ -1669,7 +1669,7 @@
     lib.addMember(field);
     for (Class c in lib.classes) {
       if (c.fields
-          .where((f) => f.name.name == "unique_SimulateTransformer")
+          .where((f) => f.name.text == "unique_SimulateTransformer")
           .toList()
           .isNotEmpty) continue;
       fieldName = new Name("unique_SimulateTransformer");
diff --git a/pkg/front_end/test/kernel_generator_test.dart b/pkg/front_end/test/kernel_generator_test.dart
index 27fe114..20e3b57 100644
--- a/pkg/front_end/test/kernel_generator_test.dart
+++ b/pkg/front_end/test/kernel_generator_test.dart
@@ -74,7 +74,7 @@
           (await compileScript('main() => print("hi");', options: options))
               ?.component;
       var core = component.libraries.firstWhere(isDartCoreLibrary);
-      var printMember = core.members.firstWhere((m) => m.name.name == 'print');
+      var printMember = core.members.firstWhere((m) => m.name.text == 'print');
 
       // Note: summaries created by the SDK today contain empty statements as
       // method bodies.
diff --git a/pkg/front_end/test/lint_suite.dart b/pkg/front_end/test/lint_suite.dart
index d047ab7..2831434 100644
--- a/pkg/front_end/test/lint_suite.dart
+++ b/pkg/front_end/test/lint_suite.dart
@@ -30,12 +30,18 @@
 import 'package:testing/testing.dart'
     show Chain, ChainContext, Result, Step, TestDescription, runMe;
 
+import 'testing_utils.dart' show checkEnvironment, getGitFiles;
+
 main([List<String> arguments = const []]) =>
     runMe(arguments, createContext, configurationPath: "../testing.json");
 
 Future<Context> createContext(
     Chain suite, Map<String, String> environment) async {
-  return new Context();
+  const Set<String> knownEnvironmentKeys = {"onlyInGit"};
+  checkEnvironment(environment, knownEnvironmentKeys);
+
+  bool onlyInGit = environment["onlyInGit"] != "false";
+  return new Context(onlyInGit: onlyInGit);
 }
 
 class LintTestDescription extends TestDescription {
@@ -70,6 +76,9 @@
 }
 
 class Context extends ChainContext {
+  final bool onlyInGit;
+  Context({this.onlyInGit});
+
   final List<Step> steps = const <Step>[
     const LintStep(),
   ];
@@ -82,6 +91,11 @@
   }
 
   Stream<LintTestDescription> list(Chain suite) async* {
+    Set<Uri> gitFiles;
+    if (onlyInGit) {
+      gitFiles = await getGitFiles(suite.uri);
+    }
+
     Directory testRoot = new Directory.fromUri(suite.uri);
     if (await testRoot.exists()) {
       Stream<FileSystemEntity> files =
@@ -91,6 +105,7 @@
         String path = entity.uri.path;
         if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
         if (suite.pattern.any((RegExp r) => path.contains(r))) {
+          if (onlyInGit && !gitFiles.contains(entity.uri)) continue;
           Uri root = suite.uri;
           String baseName = "${entity.uri}".substring("$root".length);
           baseName = baseName.substring(0, baseName.length - ".dart".length);
diff --git a/pkg/front_end/test/old_dill_suite.dart b/pkg/front_end/test/old_dill_suite.dart
deleted file mode 100644
index c48c30b..0000000
--- a/pkg/front_end/test/old_dill_suite.dart
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async' show Future;
-
-import 'dart:io';
-
-import 'package:kernel/binary/tag.dart' show Tag;
-
-import 'package:front_end/src/base/command_line_options.dart';
-
-import 'package:testing/testing.dart'
-    show ChainContext, Result, Step, TestDescription, Chain, runMe;
-
-Future<Null> main([List<String> arguments = const []]) async {
-  if (arguments.length == 1 && arguments[0] == "--generate") {
-    print("Should now generate a dill of dart2js.");
-    await generateDill();
-    return null;
-  } else if (arguments.length == 1 && arguments[0] == "--checkDill") {
-    await checkDill();
-    return null;
-  }
-  await runMe(arguments, createContext, configurationPath: "../testing.json");
-  await checkDill();
-}
-
-String get dartVm => Platform.resolvedExecutable;
-
-Uri generateOutputUri(int binaryVersion, int compileNumber) {
-  return Uri.base.resolve("pkg/front_end/testcases/old_dills/dills/"
-      "dart2js"
-      ".version.$binaryVersion"
-      ".compile.$compileNumber"
-      ".dill");
-}
-
-verifyNotUsingCheckedInDart() {
-  String vm = dartVm.replaceAll(r"\", "/");
-  if (vm.contains("tools/sdks/dart-sdk/bin/dart")) {
-    throw "Running with checked-in VM which is not supported";
-  }
-}
-
-Future<Null> checkDill() async {
-  Uri uri = generateOutputUri(Tag.BinaryFormatVersion, 1);
-  if (!new File.fromUri(uri).existsSync()) {
-    print("File $uri doesn't exist. Generate running script");
-    print("${Platform.script.toFilePath()} --generate");
-    exit(1);
-  }
-}
-
-Future<Null> generateDill() async {
-  Uri fastaCompile = Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart");
-  if (!new File.fromUri(fastaCompile).existsSync()) {
-    throw "compile.dart from fasta tools couldn't be found";
-  }
-
-  Uri dart2js = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
-  if (!new File.fromUri(dart2js).existsSync()) {
-    throw "dart2js couldn't be found";
-  }
-
-  int compileNumber = 0;
-  Uri output;
-  do {
-    compileNumber++;
-    output = generateOutputUri(Tag.BinaryFormatVersion, compileNumber);
-  } while (new File.fromUri(output).existsSync());
-
-  ProcessResult result = await Process.run(
-      dartVm,
-      [
-        fastaCompile.toFilePath(),
-        "sdkroot:/pkg/compiler/bin/dart2js.dart",
-        "${Flags.output}",
-        output.toFilePath(),
-        "${Flags.target}=vm",
-        "${Flags.singleRootBase}=${Uri.base.toFilePath()}",
-        "${Flags.singleRootScheme}=sdkroot",
-      ],
-      workingDirectory: Uri.base.toFilePath());
-  if (result.exitCode != 0) {
-    print("stdout: ${result.stdout}");
-    print("stderr: ${result.stderr}");
-    print("Exit code: ${result.exitCode}");
-    throw "Got exit code ${result.exitCode}";
-  } else {
-    print("File generated.");
-    print("");
-    print("You should now upload via CIPD:");
-    print("");
-    print("cipd create -name dart/cfe/dart2js_dills "
-        "-in pkg/front_end/testcases/old_dills/dills/ "
-        "-install-mode copy "
-        "-tag \"binary_version:${Tag.BinaryFormatVersion}\"");
-    print("");
-    print("And update the DEPS file to say "
-        "binary_version:${Tag.BinaryFormatVersion} "
-        "under /pkg/front_end/testcases/old_dills/dills");
-  }
-}
-
-Future<Context> createContext(
-    Chain suite, Map<String, String> environment) async {
-  return new Context();
-}
-
-class Context extends ChainContext {
-  final List<Step> steps = const <Step>[
-    const RunDill(),
-  ];
-}
-
-class RunDill extends Step<TestDescription, TestDescription, Context> {
-  const RunDill();
-
-  String get name => "RunDill";
-
-  Future<Result<TestDescription>> run(
-      TestDescription description, Context context) async {
-    verifyNotUsingCheckedInDart();
-    ProcessResult result = await Process.run(
-        dartVm,
-        [
-          "--compile_all",
-          description.uri.toFilePath(),
-          "-h",
-        ],
-        workingDirectory: Uri.base.toFilePath());
-    print("stdout: ${result.stdout}");
-    print("stderr: ${result.stderr}");
-    print("Exit code: ${result.exitCode}");
-    if (result.exitCode != 0) {
-      return fail(description, "Got exit code ${result.exitCode}");
-    }
-    return pass(description);
-  }
-}
diff --git a/pkg/front_end/test/parser_suite.dart b/pkg/front_end/test/parser_suite.dart
index 5e65244..79145fb 100644
--- a/pkg/front_end/test/parser_suite.dart
+++ b/pkg/front_end/test/parser_suite.dart
@@ -46,6 +46,7 @@
         TestDescription,
         runMe;
 
+import 'fasta/testing/suite.dart' show UPDATE_EXPECTATIONS;
 import 'utils/kernel_chain.dart' show MatchContext;
 
 import 'parser_test_listener.dart' show ParserTestListener;
@@ -86,6 +87,10 @@
 
 class Context extends ChainContext with MatchContext {
   final bool updateExpectations;
+
+  @override
+  String get updateExpectationsOption => '${UPDATE_EXPECTATIONS}=true';
+
   final bool addTrace;
   final bool annotateLines;
   final String suiteName;
@@ -406,14 +411,18 @@
 
   void doPrint(String s) {
     super.doPrint(s);
-    if (s.startsWith("beginCompilationUnit(") ||
-        s.startsWith("endCompilationUnit(")) {
-      if (indent != 0) {
-        throw "Incorrect indents: '$s' (indent = $indent).\n\n${sb.toString()}";
-      }
-    } else {
-      if (indent <= 0) {
-        throw "Incorrect indents: '$s' (indent = $indent).\n\n${sb.toString()}";
+    if (!annotateLines) {
+      if (s.startsWith("beginCompilationUnit(") ||
+          s.startsWith("endCompilationUnit(")) {
+        if (indent != 0) {
+          throw "Incorrect indents: '$s' (indent = $indent).\n\n"
+              "${sb.toString()}";
+        }
+      } else {
+        if (indent <= 0) {
+          throw "Incorrect indents: '$s' (indent = $indent).\n\n"
+              "${sb.toString()}";
+        }
       }
     }
   }
diff --git a/pkg/front_end/test/patching/patching_test.dart b/pkg/front_end/test/patching/patching_test.dart
index 4cce8c0..81210eb 100644
--- a/pkg/front_end/test/patching/patching_test.dart
+++ b/pkg/front_end/test/patching/patching_test.dart
@@ -149,7 +149,7 @@
         // Don't include member signatures.
         continue;
       }
-      String name = m.name.name;
+      String name = m.name.text;
       if (m is Constructor) {
         name = '${m.enclosingClass.name}.${name}';
       }
diff --git a/pkg/front_end/test/predicates/data/late.dart b/pkg/front_end/test/predicates/data/late.dart
index 0d28456..3218974 100644
--- a/pkg/front_end/test/predicates/data/late.dart
+++ b/pkg/front_end/test/predicates/data/late.dart
@@ -5,10 +5,12 @@
 /*member: _#topLevelNonNullableWithoutInitializer:lateField*/
 /*member: topLevelNonNullableWithoutInitializer:lateFieldGetter*/
 /*member: topLevelNonNullableWithoutInitializer=:lateFieldSetter*/
+/*member: _#topLevelNonNullableWithoutInitializer#isSet:lateIsSetField*/
 late int topLevelNonNullableWithoutInitializer;
 /*member: _#finalTopLevelNonNullableWithoutInitializer:lateField*/
 /*member: finalTopLevelNonNullableWithoutInitializer:lateFieldGetter*/
 /*member: finalTopLevelNonNullableWithoutInitializer=:lateFieldSetter*/
+/*member: _#finalTopLevelNonNullableWithoutInitializer#isSet:lateIsSetField*/
 late final int finalTopLevelNonNullableWithoutInitializer;
 /*member: _#topLevelNullableWithoutInitializer:lateField*/
 /*member: _#topLevelNullableWithoutInitializer#isSet:lateIsSetField*/
@@ -23,9 +25,11 @@
 /*member: _#topLevelNonNullableWithInitializer:lateField*/
 /*member: topLevelNonNullableWithInitializer:lateFieldGetter*/
 /*member: topLevelNonNullableWithInitializer=:lateFieldSetter*/
+/*member: _#topLevelNonNullableWithInitializer#isSet:lateIsSetField*/
 late int topLevelNonNullableWithInitializer = 0;
 /*member: _#finalTopLevelNonNullableWithInitializer:lateField*/
 /*member: finalTopLevelNonNullableWithInitializer:lateFieldGetter*/
+/*member: _#finalTopLevelNonNullableWithInitializer#isSet:lateIsSetField*/
 late final int finalTopLevelNonNullableWithInitializer = 0;
 /*member: _#topLevelNullableWithInitializer:lateField*/
 /*member: _#topLevelNullableWithInitializer#isSet:lateIsSetField*/
@@ -38,10 +42,12 @@
 late final int? finalTopLevelNullableWithInitializer = 0;
 
 class Class {
+  /*member: Class._#Class#instanceNonNullableWithoutInitializer#isSet:lateIsSetField*/
   /*member: Class._#Class#instanceNonNullableWithoutInitializer:lateField*/
   /*member: Class.instanceNonNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.instanceNonNullableWithoutInitializer=:lateFieldSetter*/
   late int instanceNonNullableWithoutInitializer;
+  /*member: Class._#Class#finalInstanceNonNullableWithoutInitializer#isSet:lateIsSetField*/
   /*member: Class._#Class#finalInstanceNonNullableWithoutInitializer:lateField*/
   /*member: Class.finalInstanceNonNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.finalInstanceNonNullableWithoutInitializer=:lateFieldSetter*/
@@ -56,10 +62,12 @@
   /*member: Class.finalInstanceNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.finalInstanceNullableWithoutInitializer=:lateFieldSetter*/
   late final int? finalInstanceNullableWithoutInitializer;
+  /*member: Class._#Class#instanceNonNullableWithInitializer#isSet:lateIsSetField*/
   /*member: Class._#Class#instanceNonNullableWithInitializer:lateField*/
   /*member: Class.instanceNonNullableWithInitializer:lateFieldGetter*/
   /*member: Class.instanceNonNullableWithInitializer=:lateFieldSetter*/
   late int instanceNonNullableWithInitializer = 0;
+  /*member: Class._#Class#finalInstanceNonNullableWithInitializer#isSet:lateIsSetField*/
   /*member: Class._#Class#finalInstanceNonNullableWithInitializer:lateField*/
   /*member: Class.finalInstanceNonNullableWithInitializer:lateFieldGetter*/
   late final int finalInstanceNonNullableWithInitializer = 0;
@@ -73,10 +81,12 @@
   /*member: Class.finalInstanceNullableWithInitializer:lateFieldGetter*/
   late final int? finalInstanceNullableWithInitializer = 0;
 
+  /*member: Class._#staticNonNullableWithoutInitializer#isSet:lateIsSetField*/
   /*member: Class._#staticNonNullableWithoutInitializer:lateField*/
   /*member: Class.staticNonNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.staticNonNullableWithoutInitializer=:lateFieldSetter*/
   static late int staticNonNullableWithoutInitializer;
+  /*member: Class._#finalStaticNonNullableWithoutInitializer#isSet:lateIsSetField*/
   /*member: Class._#finalStaticNonNullableWithoutInitializer:lateField*/
   /*member: Class.finalStaticNonNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.finalStaticNonNullableWithoutInitializer=:lateFieldSetter*/
@@ -91,10 +101,12 @@
   /*member: Class.finalStaticNullableWithoutInitializer:lateFieldGetter*/
   /*member: Class.finalStaticNullableWithoutInitializer=:lateFieldSetter*/
   static late final int? finalStaticNullableWithoutInitializer;
+  /*member: Class._#staticNonNullableWithInitializer#isSet:lateIsSetField*/
   /*member: Class._#staticNonNullableWithInitializer:lateField*/
   /*member: Class.staticNonNullableWithInitializer:lateFieldGetter*/
   /*member: Class.staticNonNullableWithInitializer=:lateFieldSetter*/
   static late int staticNonNullableWithInitializer = 0;
+  /*member: Class._#finalStaticNonNullableWithInitializer#isSet:lateIsSetField*/
   /*member: Class._#finalStaticNonNullableWithInitializer:lateField*/
   /*member: Class.finalStaticNonNullableWithInitializer:lateFieldGetter*/
   static late final int finalStaticNonNullableWithInitializer = 0;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index a0e7fca..18581dd4 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -73,6 +73,7 @@
 b0i
 b0m
 b0n
+b1a
 b1i
 b1m
 b1n
@@ -81,6 +82,7 @@
 b2m
 b2n
 backping
+backstop
 badly
 bang
 bar
@@ -163,6 +165,7 @@
 checkpoint
 chunks
 ci
+circuited
 ck
 cl
 claim
@@ -526,6 +529,7 @@
 initializer's
 insertion
 inspect
+inspecting
 inspection
 inspector
 inspired
@@ -552,6 +556,7 @@
 iterating
 iterations
 iterators
+ith
 j
 jacobr
 jakemac
@@ -564,12 +569,15 @@
 jumps
 juxtaposition
 juxtapositions
+jvm
 k
 kallentu
 kernel's
 kernel2kernel
 klass
 kmillikin
+kotlin
+kotlinlang
 kustermann
 kv
 k’s
@@ -752,6 +760,7 @@
 overloader
 overlooked
 overshadowed
+oversight
 overwrite
 overwriting
 ownership
@@ -845,6 +854,7 @@
 r'\u
 r'\v
 r0i
+r0j
 r1i
 r2i
 ra
@@ -859,6 +869,8 @@
 rc
 re
 reach
+reachabilities
+reachability
 react
 realign
 realise
@@ -884,12 +896,14 @@
 redefine
 redirectee
 redirector
+redo
 reexports
 ref
 reflect
 reflective
 reg
 regis
+registering
 rehash
 reindexed
 reissued
@@ -971,7 +985,9 @@
 shas
 shelf
 shifts
+shl
 showing
+shr
 shrinking
 shru
 si
@@ -1026,9 +1042,12 @@
 stderr
 stdin
 stdio
+stdlib
 stdout
+sticky
 stmt
 str
+strategies
 streak
 streaming
 strict
@@ -1194,8 +1213,11 @@
 unseen
 unshadowed
 unsortable
+unsound
+unsoundness
 unwrapper
 unwraps
+unwritten
 unzip
 upcast
 update2018
@@ -1215,6 +1237,7 @@
 variances
 variant
 variants
+variation
 vary
 vb
 vector
@@ -1238,6 +1261,7 @@
 wc
 weakened
 weakener
+weed
 weird
 weren't
 werror
@@ -1291,6 +1315,7 @@
 xdfff
 xef
 xi
+xj
 xk
 xm
 xn
@@ -1310,6 +1335,7 @@
 yaml
 yb
 yet
+yi
 yielding
 yields
 yn
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 5882a79..f3a1c47 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -273,6 +273,7 @@
 behaved
 behaves
 behavior
+behavioral
 behaviors
 behind
 being
@@ -300,6 +301,7 @@
 bitwise
 black
 block
+blocked
 blocks
 blogs
 blue
@@ -430,6 +432,7 @@
 checked
 checker
 checking
+checkpoints
 checks
 child
 children
@@ -578,6 +581,7 @@
 conformed
 confuse
 confused
+conjunction
 connect
 connected
 connection
@@ -797,6 +801,7 @@
 derivation
 derive
 derived
+descendant
 descendants
 describe
 described
@@ -840,6 +845,7 @@
 diet
 differ
 difference
+differences
 different
 differently
 dig
@@ -910,6 +916,7 @@
 drop
 dropped
 dropping
+drops
 due
 dump
 dumped
@@ -1016,7 +1023,9 @@
 equivalence
 equivalent
 equivalents
+erasure
 erroneous
+erroneously
 error
 errors
 escape
@@ -1065,6 +1074,7 @@
 executes
 executing
 execution
+exempt
 exercise
 exhaustive
 exist
@@ -1375,6 +1385,7 @@
 holds
 hood
 hooks
+horns
 horribly
 host
 hostnames
@@ -1483,6 +1494,7 @@
 information
 informational
 informs
+inherently
 inherit
 inheritable
 inheritance
@@ -1525,6 +1537,7 @@
 instantiation
 instantiations
 instead
+instruct
 instruction
 instructions
 instrumentation
@@ -1766,6 +1779,7 @@
 main
 mainly
 maintain
+maintains
 major
 make
 makes
@@ -1809,6 +1823,7 @@
 meant
 measurably
 measure
+measurements
 mechanism
 medium
 meet
@@ -1836,6 +1851,7 @@
 might
 millisecond
 milliseconds
+mimics
 minimal
 minimum
 minor
@@ -1857,6 +1873,7 @@
 mock
 mode
 model
+modeling
 models
 modes
 modifiable
@@ -1965,6 +1982,7 @@
 noticed
 notifies
 now
+nowhere
 null
 nullability
 nullable
@@ -2122,6 +2140,7 @@
 peel
 peeled
 peeling
+peels
 pending
 percent
 percolate
@@ -2282,6 +2301,7 @@
 promoted
 promoter
 promotes
+promoting
 promotion
 promotions
 propagate
@@ -2353,6 +2373,7 @@
 real
 realigned
 realized
+realizing
 really
 reason
 reasonable
@@ -2765,6 +2786,7 @@
 speed
 speedup
 split
+splits
 splitter
 spread
 spreadable
@@ -2788,6 +2810,7 @@
 startup
 state
 stateful
+stateless
 statement
 statement's
 statements
@@ -2864,6 +2887,7 @@
 sufficiently
 suffix
 suffixes
+sugar
 suggested
 suitable
 suites
@@ -2991,6 +3015,7 @@
 thrown
 throws
 thumb
+thunk
 thus
 time
 timeline
@@ -3156,6 +3181,7 @@
 unsized
 unskip
 unsorted
+unsoundness
 unspecified
 unsplit
 unstable
diff --git a/pkg/front_end/test/spell_checking_list_messages.txt b/pkg/front_end/test/spell_checking_list_messages.txt
index 963e938..a0c8cae 100644
--- a/pkg/front_end/test/spell_checking_list_messages.txt
+++ b/pkg/front_end/test/spell_checking_list_messages.txt
@@ -36,6 +36,7 @@
 loadlibrary
 name.#name
 name.stack
+nameokempty
 native('native
 nativetype
 nnbd
@@ -51,6 +52,7 @@
 re
 sdksummary
 stacktrace
+stringokempty
 struct<#name
 structs
 super.namedconstructor
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index f858baf..164bb07 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -55,6 +55,7 @@
 beta
 bigger
 bkonyi
+bla
 blah
 blindly
 blocked
@@ -70,9 +71,16 @@
 brand
 brave
 brown
+bt
+bt3a
+bt3b
+bt4a
+bt4b
+btw
 builddir
 bulk2
 bulkcompile
+bye
 c's
 c59cdee365b94ce066344840f9e3412d642019b
 ca
@@ -101,6 +109,7 @@
 class5c
 class5d
 cloneable
+cmd
 cmp
 cnn
 coded
@@ -129,8 +138,14 @@
 corners
 costly
 cov
+coverage
+coverages
 cp
 csi
+ct3a
+ct3b
+ct4a
+ct4b
 ctrl
 cumulative
 cursor
@@ -182,10 +197,12 @@
 dispatcher
 dispose
 dist
+div
 divergent
 doctype
 doesnt
 dog
+donly
 doo
 downstream
 draw
@@ -208,6 +225,7 @@
 eoo
 epoch
 erase
+erased
 err
 esc
 everytime
@@ -230,6 +248,15 @@
 favors
 fi
 fibonacci
+field1c
+field2a
+field2b
+field2c
+field3a
+field3b
+field3c
+field4a
+field4b
 filesystem
 filler
 fisk
@@ -259,6 +286,7 @@
 forces
 foreground
 forrest
+forty
 foundation
 fox
 fulfill
@@ -269,6 +297,10 @@
 gamma
 gave
 gc
+gcd
+getter1c
+getter1d
+getter1e
 goo
 google
 graphic
@@ -282,6 +314,7 @@
 heuristics
 hi
 hints
+hits
 home
 hoo
 hosted
@@ -298,13 +331,17 @@
 image
 images
 implementor
+in1
+in2
 inclosure
 increased
 incrementally
 increments
 indents
 initializer2
+instance2
 insufficient
+intdiv
 interactive
 internet
 interpolate
@@ -347,6 +384,7 @@
 ko
 koo
 la
+launch
 launching
 le
 legs
@@ -358,6 +396,7 @@
 lints
 linux
 listening
+literal2
 ln
 local1a
 local1b
@@ -393,6 +432,7 @@
 matters
 mds
 measured
+method1d
 metric
 metrics
 mf
@@ -403,6 +443,7 @@
 mismatched
 misnamed
 miss
+misses
 misspelled
 mistake
 mistakes
@@ -422,16 +463,23 @@
 nonexisting
 noo
 numerator
+ob
+obool
 observable
 oh
 okay
+ol
+onull
 ooo
 operate
 ops
 optimal
 oracle
+out1
+out2
 outbound
 overlay
+ox
 pack
 paging
 paint
@@ -460,6 +508,14 @@
 profile
 profiler
 propagated
+property2a
+property2b
+property4a
+property4b
+property5a
+property5b
+property8a
+property8b
 protected
 proved
 provider
@@ -473,6 +529,7 @@
 quit
 quot
 quux
+quuz
 qux
 r"
 r"\s
@@ -500,14 +557,17 @@
 response
 result1
 result2
+resuming
 retaining
 retainingpath
 retains
 rev
 risky
+rk
 row
 rows
 runtimes
+rv
 scans
 scheduler
 screen
@@ -519,6 +579,11 @@
 selection
 sensitive
 services
+setter1a
+setter1b
+setter1c
+setter1d
+setter1e
 setups
 severe
 sheets
@@ -530,6 +595,7 @@
 sigwinch
 slight
 smoke
+snull
 somehow
 spans
 spawn
@@ -550,6 +616,8 @@
 stats
 stay
 std
+stress
+string2
 strip
 strongest
 stub's
@@ -563,6 +631,7 @@
 subtyping1b
 subtyping2a
 subtyping2b
+successes
 suite
 summarization
 summarized
@@ -570,6 +639,10 @@
 supplement
 suspension
 symbolic
+t3a
+t3b
+t4a
+t4b
 t\b\f\u
 t\u0008\f\u
 tails
@@ -577,6 +650,7 @@
 templates
 test3a
 test3b
+theoretically
 thereof
 timed
 timeout
@@ -607,6 +681,7 @@
 unconverted
 underline
 unpacked
+unpatched
 unpaused
 unregistered
 untransformed
@@ -648,3 +723,4 @@
 y's
 year
 yxxx
+yy
diff --git a/pkg/front_end/test/spell_checking_utils.dart b/pkg/front_end/test/spell_checking_utils.dart
index e29b233..948ea88 100644
--- a/pkg/front_end/test/spell_checking_utils.dart
+++ b/pkg/front_end/test/spell_checking_utils.dart
@@ -2,7 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io';
+import 'dart:io' show File, stdin, stdout;
+
+import "utils/io_utils.dart";
+
+final Uri repoDir = computeRepoDirUri();
 
 enum Dictionaries {
   common,
@@ -162,19 +166,18 @@
 Uri dictionaryToUri(Dictionaries dictionaryType) {
   switch (dictionaryType) {
     case Dictionaries.common:
-      return Uri.base
+      return repoDir
           .resolve("pkg/front_end/test/spell_checking_list_common.txt");
     case Dictionaries.cfeMessages:
-      return Uri.base
+      return repoDir
           .resolve("pkg/front_end/test/spell_checking_list_messages.txt");
     case Dictionaries.cfeCode:
-      return Uri.base
-          .resolve("pkg/front_end/test/spell_checking_list_code.txt");
+      return repoDir.resolve("pkg/front_end/test/spell_checking_list_code.txt");
     case Dictionaries.cfeTests:
-      return Uri.base
+      return repoDir
           .resolve("pkg/front_end/test/spell_checking_list_tests.txt");
     case Dictionaries.denylist:
-      return Uri.base
+      return repoDir
           .resolve("pkg/front_end/test/spell_checking_list_denylist.txt");
   }
   throw "Unknown Dictionary";
@@ -342,3 +345,121 @@
   }
   return result;
 }
+
+void spellSummarizeAndInteractiveMode(
+    Set<String> reportedWords,
+    Set<String> reportedWordsDenylisted,
+    List<Dictionaries> dictionaries,
+    bool interactive,
+    String interactiveLaunchExample) {
+  if (reportedWordsDenylisted.isNotEmpty) {
+    print("\n\n\n");
+    print("================");
+    print("The following words was reported as used and denylisted:");
+    print("----------------");
+    for (String s in reportedWordsDenylisted) {
+      print("$s");
+    }
+    print("================");
+  }
+  if (reportedWords.isNotEmpty) {
+    print("\n\n\n");
+    print("================");
+    print("The following word(s) were reported as unknown:");
+    print("----------------");
+
+    Dictionaries dictionaryToUse;
+    if (dictionaries.contains(Dictionaries.cfeTests)) {
+      dictionaryToUse = Dictionaries.cfeTests;
+    } else if (dictionaries.contains(Dictionaries.cfeMessages)) {
+      dictionaryToUse = Dictionaries.cfeMessages;
+    } else if (dictionaries.contains(Dictionaries.cfeCode)) {
+      dictionaryToUse = Dictionaries.cfeCode;
+    } else {
+      for (Dictionaries dictionary in dictionaries) {
+        if (dictionaryToUse == null ||
+            dictionary.index < dictionaryToUse.index) {
+          dictionaryToUse = dictionary;
+        }
+      }
+    }
+
+    if (interactive && dictionaryToUse != null) {
+      List<String> addedWords = new List<String>();
+      for (String s in reportedWords) {
+        print("- $s");
+        String answer;
+        bool add;
+        while (true) {
+          stdout.write("Do you want to add the word to the dictionary "
+              "$dictionaryToUse (y/n)? ");
+          answer = stdin.readLineSync().trim().toLowerCase();
+          switch (answer) {
+            case "y":
+            case "yes":
+            case "true":
+              add = true;
+              break;
+            case "n":
+            case "no":
+            case "false":
+              add = false;
+              break;
+            default:
+              add = null;
+              print("'$answer' is not a valid answer. Please try again.");
+              break;
+          }
+          if (add != null) break;
+        }
+        if (add) {
+          addedWords.add(s);
+        }
+      }
+      if (addedWords.isNotEmpty) {
+        File dictionaryFile =
+            new File.fromUri(dictionaryToUri(dictionaryToUse));
+        List<String> lines = dictionaryFile.readAsLinesSync();
+        List<String> header = new List<String>();
+        List<String> sortThis = new List<String>();
+        for (String line in lines) {
+          if (line.startsWith("#")) {
+            header.add(line);
+          } else if (line.trim().isEmpty && sortThis.isEmpty) {
+            header.add(line);
+          } else if (line.trim().isNotEmpty) {
+            sortThis.add(line);
+          }
+        }
+        sortThis.addAll(addedWords);
+        sortThis.sort();
+        lines = new List<String>();
+        lines.addAll(header);
+        if (header.isEmpty || header.last.isNotEmpty) {
+          lines.add("");
+        }
+        lines.addAll(sortThis);
+        lines.add("");
+        dictionaryFile.writeAsStringSync(lines.join("\n"));
+      }
+    } else {
+      for (String s in reportedWords) {
+        print("$s");
+      }
+      if (dictionaries.isNotEmpty) {
+        print("----------------");
+        print("If the word(s) are correctly spelled please add it to one of "
+            "these files:");
+        for (Dictionaries dictionary in dictionaries) {
+          print(" - ${dictionaryToUri(dictionary)}");
+        }
+
+        print("");
+        print("To add words easily, try to run this script in interactive "
+            "mode via the command");
+        print(interactiveLaunchExample);
+      }
+    }
+    print("================");
+  }
+}
diff --git a/pkg/front_end/test/spelling_test_base.dart b/pkg/front_end/test/spelling_test_base.dart
index 056d0e7..9bafa38 100644
--- a/pkg/front_end/test/spelling_test_base.dart
+++ b/pkg/front_end/test/spelling_test_base.dart
@@ -4,7 +4,7 @@
 
 import 'dart:async' show Future;
 
-import 'dart:io' show File, Platform, stdin, stdout;
+import 'dart:io' show File, Platform;
 
 import 'dart:typed_data' show Uint8List;
 
@@ -24,18 +24,21 @@
 import 'package:kernel/kernel.dart';
 
 import 'package:testing/testing.dart'
-    show ChainContext, Result, Step, TestDescription;
+    show Chain, ChainContext, Result, Step, TestDescription;
 
 import 'spell_checking_utils.dart' as spell;
 
+import 'testing_utils.dart' show filterList;
+
 abstract class SpellContext extends ChainContext {
   final List<Step> steps = const <Step>[
     const SpellTest(),
   ];
 
   final bool interactive;
+  final bool onlyInGit;
 
-  SpellContext({this.interactive});
+  SpellContext({this.interactive, this.onlyInGit});
 
   // Override special handling of negative tests.
   @override
@@ -48,115 +51,31 @@
 
   bool get onlyDenylisted;
 
+  String get repoRelativeSuitePath;
+
   Set<String> reportedWords = {};
   Set<String> reportedWordsDenylisted = {};
 
   @override
+  Stream<TestDescription> list(Chain suite) {
+    return filterList(suite, onlyInGit, super.list(suite));
+  }
+
+  @override
   Future<void> postRun() {
-    if (reportedWordsDenylisted.isNotEmpty) {
-      print("\n\n\n");
-      print("================");
-      print("The following words was reported as used and denylisted:");
-      print("----------------");
-      for (String s in reportedWordsDenylisted) {
-        print("$s");
-      }
-      print("================");
+    String dartPath = Platform.resolvedExecutable;
+    Uri suiteUri = spell.repoDir.resolve(repoRelativeSuitePath);
+    File suiteFile = new File.fromUri(suiteUri).absolute;
+    if (!suiteFile.existsSync()) {
+      throw "Specified suite path is invalid.";
     }
-    if (reportedWords.isNotEmpty) {
-      print("\n\n\n");
-      print("================");
-      print("The following word(s) were reported as unknown:");
-      print("----------------");
-
-      spell.Dictionaries dictionaryToUse;
-      if (dictionaries.contains(spell.Dictionaries.cfeTests)) {
-        dictionaryToUse = spell.Dictionaries.cfeTests;
-      } else if (dictionaries.contains(spell.Dictionaries.cfeMessages)) {
-        dictionaryToUse = spell.Dictionaries.cfeMessages;
-      } else if (dictionaries.contains(spell.Dictionaries.cfeCode)) {
-        dictionaryToUse = spell.Dictionaries.cfeCode;
-      } else {
-        for (spell.Dictionaries dictionary in dictionaries) {
-          if (dictionaryToUse == null ||
-              dictionary.index < dictionaryToUse.index) {
-            dictionaryToUse = dictionary;
-          }
-        }
-      }
-
-      if (interactive && dictionaryToUse != null) {
-        List<String> addedWords = new List<String>();
-        for (String s in reportedWords) {
-          print("- $s");
-          stdout.write("Do you want to add the word to the dictionary "
-              "$dictionaryToUse (y/n)? ");
-          String answer = stdin.readLineSync().trim().toLowerCase();
-          bool add;
-          switch (answer) {
-            case "y":
-            case "yes":
-            case "true":
-              add = true;
-              break;
-            case "n":
-            case "no":
-            case "false":
-              add = false;
-              break;
-            default:
-              throw "Didn't understand '$answer'";
-          }
-          if (add) {
-            addedWords.add(s);
-          }
-        }
-        if (addedWords.isNotEmpty) {
-          File dictionaryFile =
-              new File.fromUri(spell.dictionaryToUri(dictionaryToUse));
-          List<String> lines = dictionaryFile.readAsLinesSync();
-          List<String> header = new List<String>();
-          List<String> sortThis = new List<String>();
-          for (String line in lines) {
-            if (line.startsWith("#")) {
-              header.add(line);
-            } else if (line.trim().isEmpty && sortThis.isEmpty) {
-              header.add(line);
-            } else if (line.trim().isNotEmpty) {
-              sortThis.add(line);
-            }
-          }
-          sortThis.addAll(addedWords);
-          sortThis.sort();
-          lines = new List<String>();
-          lines.addAll(header);
-          if (header.isEmpty || header.last.isNotEmpty) {
-            lines.add("");
-          }
-          lines.addAll(sortThis);
-          lines.add("");
-          dictionaryFile.writeAsStringSync(lines.join("\n"));
-        }
-      } else {
-        for (String s in reportedWords) {
-          print("$s");
-        }
-        if (dictionaries.isNotEmpty) {
-          print("----------------");
-          print("If the word(s) are correctly spelled please add it to one of "
-              "these files:");
-          for (spell.Dictionaries dictionary in dictionaries) {
-            print(" - ${spell.dictionaryToUri(dictionary)}");
-          }
-
-          print("");
-          print("To add words easily, try to run this script in interactive "
-              "mode via the command");
-          print("dart ${Platform.script.toFilePath()} -Dinteractive=true");
-        }
-      }
-      print("================");
-    }
+    String suitePath = suiteFile.path;
+    spell.spellSummarizeAndInteractiveMode(
+        reportedWords,
+        reportedWordsDenylisted,
+        dictionaries,
+        interactive,
+        '"$dartPath" "$suitePath" -DonlyInGit=$onlyInGit -Dinteractive=true');
     return null;
   }
 }
diff --git a/pkg/front_end/test/spelling_test_external_targets.dart b/pkg/front_end/test/spelling_test_external_targets.dart
index 98faa82..0330b22 100644
--- a/pkg/front_end/test/spelling_test_external_targets.dart
+++ b/pkg/front_end/test/spelling_test_external_targets.dart
@@ -13,17 +13,25 @@
 
 import 'spell_checking_utils.dart' as spell;
 
+import 'testing_utils.dart' show checkEnvironment;
+
 main([List<String> arguments = const []]) =>
     runMe(arguments, createContext, configurationPath: "../testing.json");
 
 Future<SpellContext> createContext(
     Chain suite, Map<String, String> environment) async {
+  const Set<String> knownEnvironmentKeys = {"interactive", "onlyInGit"};
+  checkEnvironment(environment, knownEnvironmentKeys);
+
   bool interactive = environment["interactive"] == "true";
-  return new SpellContextExternal(interactive: interactive);
+  bool onlyInGit = environment["onlyInGit"] != "false";
+  return new SpellContextExternal(
+      interactive: interactive, onlyInGit: onlyInGit);
 }
 
 class SpellContextExternal extends SpellContext {
-  SpellContextExternal({bool interactive}) : super(interactive: interactive);
+  SpellContextExternal({bool interactive, bool onlyInGit})
+      : super(interactive: interactive, onlyInGit: onlyInGit);
 
   @override
   List<spell.Dictionaries> get dictionaries => const <spell.Dictionaries>[];
@@ -31,6 +39,10 @@
   @override
   bool get onlyDenylisted => true;
 
+  @override
+  String get repoRelativeSuitePath =>
+      "pkg/front_end/test/spelling_test_external_targets.dart";
+
   Stream<TestDescription> list(Chain suite) async* {
     for (String subdir in const ["pkg/", "sdk/"]) {
       Directory testRoot = new Directory.fromUri(suite.uri.resolve(subdir));
diff --git a/pkg/front_end/test/spelling_test_not_src_suite.dart b/pkg/front_end/test/spelling_test_not_src_suite.dart
index 32627a6..3259c88 100644
--- a/pkg/front_end/test/spelling_test_not_src_suite.dart
+++ b/pkg/front_end/test/spelling_test_not_src_suite.dart
@@ -10,17 +10,24 @@
 
 import 'spell_checking_utils.dart' as spell;
 
+import 'testing_utils.dart' show checkEnvironment;
+
 main([List<String> arguments = const []]) =>
     runMe(arguments, createContext, configurationPath: "../testing.json");
 
 Future<SpellContext> createContext(
     Chain suite, Map<String, String> environment) async {
+  const Set<String> knownEnvironmentKeys = {"interactive", "onlyInGit"};
+  checkEnvironment(environment, knownEnvironmentKeys);
+
   bool interactive = environment["interactive"] == "true";
-  return new SpellContextTest(interactive: interactive);
+  bool onlyInGit = environment["onlyInGit"] != "false";
+  return new SpellContextTest(interactive: interactive, onlyInGit: onlyInGit);
 }
 
 class SpellContextTest extends SpellContext {
-  SpellContextTest({bool interactive}) : super(interactive: interactive);
+  SpellContextTest({bool interactive, bool onlyInGit})
+      : super(interactive: interactive, onlyInGit: onlyInGit);
 
   @override
   List<spell.Dictionaries> get dictionaries => const <spell.Dictionaries>[
@@ -31,4 +38,8 @@
 
   @override
   bool get onlyDenylisted => false;
+
+  @override
+  String get repoRelativeSuitePath =>
+      "pkg/front_end/test/spelling_test_not_src_suite.dart";
 }
diff --git a/pkg/front_end/test/spelling_test_src_suite.dart b/pkg/front_end/test/spelling_test_src_suite.dart
index 3e4f1f5..afea1e0 100644
--- a/pkg/front_end/test/spelling_test_src_suite.dart
+++ b/pkg/front_end/test/spelling_test_src_suite.dart
@@ -10,17 +10,24 @@
 
 import 'spell_checking_utils.dart' as spell;
 
+import 'testing_utils.dart' show checkEnvironment;
+
 main([List<String> arguments = const []]) =>
     runMe(arguments, createContext, configurationPath: "../testing.json");
 
 Future<SpellContext> createContext(
     Chain suite, Map<String, String> environment) async {
+  const Set<String> knownEnvironmentKeys = {"interactive", "onlyInGit"};
+  checkEnvironment(environment, knownEnvironmentKeys);
+
   bool interactive = environment["interactive"] == "true";
-  return new SpellContextSource(interactive: interactive);
+  bool onlyInGit = environment["onlyInGit"] != "false";
+  return new SpellContextSource(interactive: interactive, onlyInGit: onlyInGit);
 }
 
 class SpellContextSource extends SpellContext {
-  SpellContextSource({bool interactive}) : super(interactive: interactive);
+  SpellContextSource({bool interactive, bool onlyInGit})
+      : super(interactive: interactive, onlyInGit: onlyInGit);
 
   @override
   List<spell.Dictionaries> get dictionaries => const <spell.Dictionaries>[
@@ -30,4 +37,8 @@
 
   @override
   bool get onlyDenylisted => false;
+
+  @override
+  String get repoRelativeSuitePath =>
+      "pkg/front_end/test/spelling_test_src_suite.dart";
 }
diff --git a/pkg/front_end/test/static_types/static_type_test.dart b/pkg/front_end/test/static_types/static_type_test.dart
index d67f465..0bed0cc 100644
--- a/pkg/front_end/test/static_types/static_type_test.dart
+++ b/pkg/front_end/test/static_types/static_type_test.dart
@@ -103,6 +103,9 @@
 
   @override
   String computeNodeValue(Id id, TreeNode node) {
+    if (isSkippedExpression(node)) {
+      return null;
+    }
     if (node is Expression) {
       DartType type = node.getStaticType(_staticTypeContext);
       return typeToText(type);
@@ -120,6 +123,37 @@
     return null;
   }
 
+  bool isNewReachabilityError(object) {
+    if (object is ConstructorInvocation) {
+      Class cls = object.target.enclosingClass;
+      return cls.name == 'ReachabilityError' &&
+          cls.enclosingLibrary.importUri.scheme == 'dart' &&
+          cls.enclosingLibrary.importUri.path == '_internal';
+    }
+    return false;
+  }
+
+  bool isNewReachabilityErrorArgument(object) {
+    return object is StringLiteral &&
+        isNewReachabilityError(object.parent.parent);
+  }
+
+  bool isThrowReachabilityError(object) {
+    return object is Throw && isNewReachabilityError(object.expression);
+  }
+
+  bool isReachabilityErrorLet(object) {
+    return object is Let &&
+        (isThrowReachabilityError(object.variable.initializer) ||
+            isThrowReachabilityError(object.body));
+  }
+
+  bool isSkippedExpression(object) =>
+      isReachabilityErrorLet(object) ||
+      isThrowReachabilityError(object) ||
+      isNewReachabilityErrorArgument(object) ||
+      isNewReachabilityError(object);
+
   ActualData<String> mergeData(
       ActualData<String> value1, ActualData<String> value2) {
     if (value1.object is NullLiteral && value2.object is! NullLiteral) {
@@ -129,6 +163,7 @@
       // Skip `null` literals from null-aware operations.
       return value1;
     }
+
     return new ActualData<String>(value1.id, '${value1.value}|${value2.value}',
         value1.uri, value1.offset, value1.object);
   }
diff --git a/pkg/front_end/test/summary_generator_test.dart b/pkg/front_end/test/summary_generator_test.dart
index 486295d..d641234 100644
--- a/pkg/front_end/test/summary_generator_test.dart
+++ b/pkg/front_end/test/summary_generator_test.dart
@@ -30,7 +30,7 @@
     var classA = aLib.classes.first;
     expect(classA.name, 'A');
     var fooMethod = classA.procedures.first;
-    expect(fooMethod.name.name, 'foo');
+    expect(fooMethod.name.text, 'foo');
     expect(fooMethod.function.body is EmptyStatement, isTrue);
   });
 
diff --git a/pkg/front_end/test/testing_utils.dart b/pkg/front_end/test/testing_utils.dart
new file mode 100644
index 0000000..b966e74
--- /dev/null
+++ b/pkg/front_end/test/testing_utils.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io' show Directory, Process, ProcessResult;
+
+import 'package:testing/testing.dart' show Chain, TestDescription;
+
+Stream<TestDescription> filterList(
+    Chain suite, bool onlyInGit, Stream<TestDescription> base) async* {
+  Set<Uri> gitFiles;
+  if (onlyInGit) {
+    gitFiles = await getGitFiles(suite.uri);
+  }
+  await for (TestDescription description in base) {
+    if (onlyInGit && !gitFiles.contains(description.uri)) {
+      continue;
+    }
+    yield description;
+  }
+}
+
+Future<Set<Uri>> getGitFiles(Uri uri) async {
+  ProcessResult result = await Process.run("git", ["ls-files", "."],
+      workingDirectory: new Directory.fromUri(uri).absolute.path,
+      runInShell: true);
+  String stdout = result.stdout;
+  return stdout
+      .split(new RegExp('^', multiLine: true))
+      .map((line) => uri.resolve(line.trimRight()))
+      .toSet();
+}
+
+void checkEnvironment(
+    Map<String, String> environment, Set<String> knownEnvironmentKeys) {
+  Set<String> environmentKeys = environment.keys.toSet();
+  environmentKeys.removeAll(knownEnvironmentKeys);
+  if (environmentKeys.isNotEmpty) {
+    throw "Unknown environment(s) given: ${environmentKeys.toList()}.\n"
+        "Knows about ${knownEnvironmentKeys.toList()}";
+  }
+}
diff --git a/pkg/front_end/test/text_representation/data/constants.dart b/pkg/front_end/test/text_representation/data/constants.dart
index cb45a66..9aecf7f 100644
--- a/pkg/front_end/test/text_representation/data/constants.dart
+++ b/pkg/front_end/test/text_representation/data/constants.dart
@@ -58,7 +58,7 @@
 const falseConstant = /*false*/ false;
 const intConstant = /*42*/ 42;
 const doubleConstant = /*3.14*/ 3.14;
-const stringConstant = /*foo*/ "foo";
+const stringConstant = /*"foo"*/ "foo";
 const symbolConstant = /*#name*/ #name;
 const privateSymbolConstant =
     /*normal|limited.#_privateName*/
@@ -95,12 +95,12 @@
     /*verbose.const <dart.core::int, dart.core::String>{}*/
     {};
 const mapConstant3 = <int, String>
-    /*normal|limited.const <int, String>{0: foo}*/
-    /*verbose.const <dart.core::int, dart.core::String>{0: foo}*/
+    /*normal|limited.const <int, String>{0: "foo"}*/
+    /*verbose.const <dart.core::int, dart.core::String>{0: "foo"}*/
     {0: "foo"};
 const mapConstant4 = <int, String?>
-    /*normal|limited.const <int, String?>{0: foo, 1: bar}*/
-    /*verbose.const <dart.core::int, dart.core::String?>{0: foo, 1: bar}*/
+    /*normal|limited.const <int, String?>{0: "foo", 1: "bar"}*/
+    /*verbose.const <dart.core::int, dart.core::String?>{0: "foo", 1: "bar"}*/
     {0: "foo", 1: "bar"};
 const tearOffConstant =
     /*normal|limited.id*/
@@ -111,20 +111,20 @@
     /*verbose.library org-dartlang-test:///a/b/c/main.dart::id<dart.core::int>*/
     id;
 const boolHasEnvironmentConstant = const
-    /*normal|limited.unevaluated{bool.hasEnvironment(foo)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.hasEnvironment(foo)}*/
+    /*normal|limited.unevaluated{bool.hasEnvironment("foo")}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.hasEnvironment("foo")}*/
     bool.hasEnvironment("foo");
 const boolFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{bool.fromEnvironment(foo, defaultValue: true)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.fromEnvironment(foo, defaultValue: true)}*/
+    /*normal|limited.unevaluated{bool.fromEnvironment("foo", defaultValue: true)}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.fromEnvironment("foo", defaultValue: true)}*/
     bool.fromEnvironment("foo", defaultValue: true);
 const intFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{int.fromEnvironment(foo, defaultValue: 87)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::int.fromEnvironment(foo, defaultValue: 87)}*/
+    /*normal|limited.unevaluated{int.fromEnvironment("foo", defaultValue: 87)}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::int.fromEnvironment("foo", defaultValue: 87)}*/
     int.fromEnvironment("foo", defaultValue: 87);
 const stringFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{String.fromEnvironment(foo, defaultValue: bar)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::String.fromEnvironment(foo, defaultValue: bar)}*/
+    /*normal|limited.unevaluated{String.fromEnvironment("foo", defaultValue: "bar")}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::String.fromEnvironment("foo", defaultValue: "bar")}*/
     String.fromEnvironment("foo", defaultValue: "bar");
 const instanceConstant1 = const
     /*normal|limited.const Class1<dynamic>{}*/
@@ -147,10 +147,10 @@
     /*verbose.const library org-dartlang-test:///a/b/c/main.dart::Class2<dart.core::num>{library org-dartlang-test:///a/b/c/main.dart::Class2.field1: 42}*/
     Class2<num>(42);
 const instanceConstant6 = const
-    /*normal|limited.const Class3<int, String>{Class3.field2: foo, Class2.field1: 42}*/
-    /*verbose.const library org-dartlang-test:///a/b/c/main.dart::Class3<dart.core::int, dart.core::String>{library org-dartlang-test:///a/b/c/main.dart::Class3.field2: foo, library org-dartlang-test:///a/b/c/main.dart::Class2.field1: 42}*/
+    /*normal|limited.const Class3<int, String>{Class3.field2: "foo", Class2.field1: 42}*/
+    /*verbose.const library org-dartlang-test:///a/b/c/main.dart::Class3<dart.core::int, dart.core::String>{library org-dartlang-test:///a/b/c/main.dart::Class3.field2: "foo", library org-dartlang-test:///a/b/c/main.dart::Class2.field1: 42}*/
     Class3<int, String>(42, "foo");
 const instanceConstant7 = const
-    /*normal|limited.const Class4<int, String?>{Class4.field2: baz, Class3.field2: foo, Class2.field1: 42}*/
-    /*verbose.const library org-dartlang-test:///a/b/c/main.dart::Class4<dart.core::int, dart.core::String?>{library org-dartlang-test:///a/b/c/main.dart::Class4.field2: baz, library org-dartlang-test:///a/b/c/main.dart::Class3.field2: foo, library org-dartlang-test:///a/b/c/main.dart::Class2.field1: 42}*/
+    /*normal|limited.const Class4<int, String?>{Class4.field2: "baz", Class3.field2: "foo", Class2.field1: 42}*/
+    /*verbose.const library org-dartlang-test:///a/b/c/main.dart::Class4<dart.core::int, dart.core::String?>{library org-dartlang-test:///a/b/c/main.dart::Class4.field2: "baz", library org-dartlang-test:///a/b/c/main.dart::Class3.field2: "foo", library org-dartlang-test:///a/b/c/main.dart::Class2.field1: 42}*/
     Class4<int, String?>(42, "foo", "baz");
diff --git a/pkg/front_end/test/text_representation/data/constants_opt_out.dart b/pkg/front_end/test/text_representation/data/constants_opt_out.dart
index a5d4519..1c9f0cd 100644
--- a/pkg/front_end/test/text_representation/data/constants_opt_out.dart
+++ b/pkg/front_end/test/text_representation/data/constants_opt_out.dart
@@ -44,7 +44,7 @@
 const falseConstant = /*false*/ false;
 const intConstant = /*42*/ 42;
 const doubleConstant = /*3.14*/ 3.14;
-const stringConstant = /*foo*/ "foo";
+const stringConstant = /*"foo"*/ "foo";
 const symbolConstant = /*#name*/ #name;
 const privateSymbolConstant =
 /*normal|limited.#_privateName*/
@@ -79,12 +79,12 @@
     /*verbose.const <dart.core::int*, dart.core::String*>{}*/
     {};
 const mapConstant3 = <int, String>
-    /*normal|limited.const <int*, String*>{0: foo}*/
-    /*verbose.const <dart.core::int*, dart.core::String*>{0: foo}*/
+    /*normal|limited.const <int*, String*>{0: "foo"}*/
+    /*verbose.const <dart.core::int*, dart.core::String*>{0: "foo"}*/
     {0: "foo"};
 const mapConstant4 = <int, String>
-    /*normal|limited.const <int*, String*>{0: foo, 1: bar}*/
-    /*verbose.const <dart.core::int*, dart.core::String*>{0: foo, 1: bar}*/
+    /*normal|limited.const <int*, String*>{0: "foo", 1: "bar"}*/
+    /*verbose.const <dart.core::int*, dart.core::String*>{0: "foo", 1: "bar"}*/
     {0: "foo", 1: "bar"};
 const tearOffConstant = /*normal|limited.id*/ /*verbose.test::id*/ id;
 const int Function(int) partialInitializationConstant =
@@ -92,20 +92,20 @@
     /*verbose.test::id<dart.core::int*>*/
     id;
 const boolHasEnvironmentConstant = const
-    /*normal|limited.unevaluated{bool.hasEnvironment(foo)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.hasEnvironment(foo)}*/
+    /*normal|limited.unevaluated{bool.hasEnvironment("foo")}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.hasEnvironment("foo")}*/
     bool.hasEnvironment("foo");
 const boolFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{bool.fromEnvironment(foo, defaultValue: true)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.fromEnvironment(foo, defaultValue: true)}*/
+    /*normal|limited.unevaluated{bool.fromEnvironment("foo", defaultValue: true)}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::bool.fromEnvironment("foo", defaultValue: true)}*/
     bool.fromEnvironment("foo", defaultValue: true);
 const intFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{int.fromEnvironment(foo, defaultValue: 87)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::int.fromEnvironment(foo, defaultValue: 87)}*/
+    /*normal|limited.unevaluated{int.fromEnvironment("foo", defaultValue: 87)}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::int.fromEnvironment("foo", defaultValue: 87)}*/
     int.fromEnvironment("foo", defaultValue: 87);
 const stringFromEnvironmentConstant = const
-    /*normal|limited.unevaluated{String.fromEnvironment(foo, defaultValue: bar)}*/
-    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::String.fromEnvironment(foo, defaultValue: bar)}*/
+    /*normal|limited.unevaluated{String.fromEnvironment("foo", defaultValue: "bar")}*/
+    /*verbose.unevaluated{{org-dartlang-test:///a/b/c/main.dart}dart.core::String.fromEnvironment("foo", defaultValue: "bar")}*/
     String.fromEnvironment("foo", defaultValue: "bar");
 const instanceConstant1 = const
     /*normal|limited.const Class1<dynamic>{}*/
@@ -128,10 +128,10 @@
     /*verbose.const test::Class2<dart.core::num*>{test::Class2.field1: 42}*/
     Class2<num>(42);
 const instanceConstant6 = const
-    /*normal|limited.const Class3<int*, String*>{Class3.field2: foo, Class2.field1: 42}*/
-    /*verbose.const test::Class3<dart.core::int*, dart.core::String*>{test::Class3.field2: foo, test::Class2.field1: 42}*/
+    /*normal|limited.const Class3<int*, String*>{Class3.field2: "foo", Class2.field1: 42}*/
+    /*verbose.const test::Class3<dart.core::int*, dart.core::String*>{test::Class3.field2: "foo", test::Class2.field1: 42}*/
     Class3<int, String>(42, "foo");
 const instanceConstant7 = const
-    /*normal|limited.const Class4<int*, String*>{Class4.field2: baz, Class3.field2: foo, Class2.field1: 42}*/
-    /*verbose.const test::Class4<dart.core::int*, dart.core::String*>{test::Class4.field2: baz, test::Class3.field2: foo, test::Class2.field1: 42}*/
+    /*normal|limited.const Class4<int*, String*>{Class4.field2: "baz", Class3.field2: "foo", Class2.field1: 42}*/
+    /*verbose.const test::Class4<dart.core::int*, dart.core::String*>{test::Class4.field2: "baz", test::Class3.field2: "foo", test::Class2.field1: 42}*/
     Class4<int, String>(42, "foo", "baz");
diff --git a/pkg/front_end/test/text_representation/data/types_opt_out.dart b/pkg/front_end/test/text_representation/data/types_opt_out.dart
index 5db349b..b302015 100644
--- a/pkg/front_end/test/text_representation/data/types_opt_out.dart
+++ b/pkg/front_end/test/text_representation/data/types_opt_out.dart
@@ -24,7 +24,7 @@
     String /*normal|limited.String**/ /*verbose.dart.core::String**/ o) {}
 voidType(void /*void*/ o) {}
 dynamicType(dynamic /*dynamic*/ o) {}
-neverType(Never /*Never**/ o) {}
+neverType(Never /*normal|limited.Null?*/ /*verbose.dart.core::Null?*/ o) {}
 objectType(
     Object /*normal|limited.Object**/ /*verbose.dart.core::Object**/ o) {}
 genericType1(
diff --git a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
index d449d21..c577233 100644
--- a/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/internal_ast_text_representation_test.dart
@@ -549,27 +549,17 @@
 }
 
 void _testIfNullPropertySet() {
-  VariableDeclaration variable =
-      new VariableDeclarationImpl.forValue(new IntLiteral(0));
   testExpression(
       new IfNullPropertySet(
-          variable,
-          new PropertyGet(new VariableGet(variable), new Name('foo')),
-          new PropertySet(
-              new VariableGet(variable), new Name('foo'), new IntLiteral(1)),
+          new IntLiteral(0), new Name('foo'), new IntLiteral(1),
           forEffect: false),
-      '''
-let final dynamic #0 = 0 in if-null #0.foo ?? #0.foo = 1''');
+      '0.foo ??= 1');
 
   testExpression(
       new IfNullPropertySet(
-          variable,
-          new PropertyGet(new VariableGet(variable), new Name('foo')),
-          new PropertySet(
-              new VariableGet(variable), new Name('foo'), new IntLiteral(1)),
+          new IntLiteral(0), new Name('foo'), new IntLiteral(1),
           forEffect: true),
-      '''
-let final dynamic #0 = 0 in if-null #0.foo ?? #0.foo = 1''');
+      '0.foo ??= 1');
 }
 
 void _testIfNullSet() {
diff --git a/pkg/front_end/test/text_representation/text_representation_test.dart b/pkg/front_end/test/text_representation/text_representation_test.dart
index ef127c6..daff068 100644
--- a/pkg/front_end/test/text_representation/text_representation_test.dart
+++ b/pkg/front_end/test/text_representation/text_representation_test.dart
@@ -134,8 +134,8 @@
 
   @override
   visitProcedure(Procedure node) {
-    if (!node.name.name.startsWith(expressionMarker) &&
-        !node.name.name.startsWith(statementMarker)) {
+    if (!node.name.text.startsWith(expressionMarker) &&
+        !node.name.text.startsWith(statementMarker)) {
       node.function.accept(this);
     }
     computeForMember(node);
@@ -143,8 +143,8 @@
 
   @override
   visitField(Field node) {
-    if (!node.name.name.startsWith(expressionMarker) &&
-        !node.name.name.startsWith(statementMarker)) {
+    if (!node.name.text.startsWith(expressionMarker) &&
+        !node.name.text.startsWith(statementMarker)) {
       node.initializer?.accept(this);
     }
     computeForMember(node);
@@ -152,10 +152,10 @@
 
   @override
   String computeMemberValue(Id id, Member node) {
-    if (node.name.name == 'stmtVariableDeclarationMulti') {
+    if (node.name.text == 'stmtVariableDeclarationMulti') {
       print(node);
     }
-    if (node.name.name.startsWith(expressionMarker)) {
+    if (node.name.text.startsWith(expressionMarker)) {
       if (node is Procedure) {
         Statement body = node.function.body;
         if (body is ReturnStatement) {
@@ -164,7 +164,7 @@
       } else if (node is Field && node.initializer != null) {
         return node.initializer.toText(strategy);
       }
-    } else if (node.name.name.startsWith(statementMarker)) {
+    } else if (node.name.text.startsWith(statementMarker)) {
       if (node is Procedure) {
         Statement body = node.function.body;
         if (body is Block && body.statements.length == 1) {
diff --git a/pkg/front_end/test/unit_test_suites.dart b/pkg/front_end/test/unit_test_suites.dart
index 1f42047..a0d190f 100644
--- a/pkg/front_end/test/unit_test_suites.dart
+++ b/pkg/front_end/test/unit_test_suites.dart
@@ -30,7 +30,6 @@
 import 'incremental_load_from_dill_suite.dart' as incremental_load
     show createContext;
 import 'lint_suite.dart' as lint show createContext;
-import 'old_dill_suite.dart' as old_dill show createContext;
 import 'parser_suite.dart' as parser show createContext;
 import 'parser_all_suite.dart' as parserAll show createContext;
 import 'spelling_test_not_src_suite.dart' as spelling_not_src
@@ -45,9 +44,10 @@
   final bool printFailureLog;
   final Uri outputDirectory;
   final String testFilter;
+  final List<String> environmentOptions;
 
   Options(this.configurationName, this.verbose, this.printFailureLog,
-      this.outputDirectory, this.testFilter);
+      this.outputDirectory, this.testFilter, this.environmentOptions);
 
   static Options parse(List<String> args) {
     var parser = new ArgParser()
@@ -59,7 +59,9 @@
       ..addFlag("verbose",
           abbr: "v", help: "print additional information", defaultsTo: false)
       ..addFlag("print",
-          abbr: "p", help: "print failure logs", defaultsTo: false);
+          abbr: "p", help: "print failure logs", defaultsTo: false)
+      ..addMultiOption('environment',
+          abbr: 'D', help: "environment options for the test suite");
     var parsedArguments = parser.parse(args);
     String outputPath = parsedArguments["output-directory"] ?? ".";
     Uri outputDirectory = Uri.base.resolveUri(Uri.directory(outputPath));
@@ -75,7 +77,8 @@
         parsedArguments["verbose"],
         parsedArguments["print"],
         outputDirectory,
-        filter);
+        filter,
+        parsedArguments['environment']);
   }
 }
 
@@ -142,8 +145,17 @@
       if (result.trace != null) {
         failureLog = "$failureLog\n\n${result.trace}";
       }
-      failureLog = "$failureLog\n\nRe-run this test: dart "
-          "pkg/front_end/test/unit_test_suites.dart -p $testName";
+      if (result.autoFixCommand != null) {
+        failureLog = "$failureLog\n\n"
+            "To re-run this test, run:\n\n"
+            "   dart pkg/front_end/test/unit_test_suites.dart -p $testName\n\n"
+            "To automatically update the test expectations, run:\n\n"
+            "   dart pkg/front_end/test/unit_test_suites.dart -p $testName "
+            "-D${result.autoFixCommand}\n";
+      } else {
+        failureLog = "$failureLog\n\nRe-run this test: dart "
+            "pkg/front_end/test/unit_test_suites.dart -p $testName";
+      }
       String outcome = "${result.outcome}";
       logsPort.send(jsonEncode({
         "name": testName,
@@ -265,7 +277,6 @@
   const Suite("incremental_load_from_dill", incremental_load.createContext,
       "../testing.json"),
   const Suite("lint", lint.createContext, "../testing.json"),
-  const Suite("old_dill", old_dill.createContext, "../testing.json"),
   const Suite("parser", parser.createContext, "../testing.json"),
   const Suite("parser_all", parserAll.createContext, "../testing.json"),
   const Suite("spelling_test_not_src", spelling_not_src.createContext,
@@ -287,6 +298,8 @@
   final bool printFailureLog;
   final String configurationName;
   final String testFilter;
+  final List<String> environmentOptions;
+
   const SuiteConfiguration(
       this.name,
       this.resultsPort,
@@ -294,7 +307,8 @@
       this.verbose,
       this.printFailureLog,
       this.configurationName,
-      this.testFilter);
+      this.testFilter,
+      this.environmentOptions);
 }
 
 void runSuite(SuiteConfiguration configuration) {
@@ -312,9 +326,11 @@
       configuration.verbose,
       configuration.printFailureLog,
       configuration.configurationName);
-  runMe(
-      <String>[if (configuration.testFilter != null) configuration.testFilter],
-      suite.createContext,
+  runMe(<String>[
+    if (configuration.testFilter != null) configuration.testFilter,
+    if (configuration.environmentOptions != null)
+      for (String option in configuration.environmentOptions) '-D${option}',
+  ], suite.createContext,
       me: suiteUri,
       configurationPath: suite.testingRootPath,
       logger: logger,
@@ -359,7 +375,8 @@
         options.verbose,
         options.printFailureLog,
         options.configurationName,
-        filter);
+        filter,
+        options.environmentOptions);
     Future future = Future<bool>(() async {
       Stopwatch stopwatch = Stopwatch()..start();
       print("Running suite $name");
diff --git a/pkg/front_end/test/utils/kernel_chain.dart b/pkg/front_end/test/utils/kernel_chain.dart
index 9e0988a..804af3c 100644
--- a/pkg/front_end/test/utils/kernel_chain.dart
+++ b/pkg/front_end/test/utils/kernel_chain.dart
@@ -26,9 +26,10 @@
 
 import 'package:front_end/src/fasta/fasta_codes.dart' show templateUnspecified;
 
-import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
+import 'package:front_end/src/fasta/kernel/kernel_target.dart'
+    show KernelTarget;
 
-import 'package:front_end/src/fasta/kernel/verifier.dart' show verifyComponent;
+import 'package:front_end/src/fasta/kernel/utils.dart' show ByteSink;
 
 import 'package:front_end/src/fasta/messages.dart'
     show DiagnosticMessageFromJson, LocatedMessage;
@@ -65,6 +66,8 @@
 abstract class MatchContext implements ChainContext {
   bool get updateExpectations;
 
+  String get updateExpectationsOption;
+
   ExpectationSet get expectationSet;
 
   Expectation get expectationFileMismatch =>
@@ -92,7 +95,10 @@
         String diff = await runDiff(expectedFile.uri, actual);
         onMismatch ??= expectationFileMismatch;
         return new Result<O>(output, onMismatch,
-            "$uri doesn't match ${expectedFile.uri}\n$diff", null);
+            "$uri doesn't match ${expectedFile.uri}\n$diff", null,
+            autoFixCommand: onMismatch == expectationFileMismatch
+                ? updateExpectationsOption
+                : null);
       } else {
         return new Result<O>.pass(output);
       }
@@ -107,7 +113,8 @@
           """
 Please create file ${expectedFile.path} with this content:
 $actual""",
-          null);
+          null,
+          autoFixCommand: updateExpectationsOption);
     }
   }
 
@@ -152,41 +159,6 @@
   }
 }
 
-class Verify extends Step<ComponentResult, ComponentResult, ChainContext> {
-  final bool fullCompile;
-
-  const Verify(this.fullCompile);
-
-  String get name => "verify";
-
-  Future<Result<ComponentResult>> run(
-      ComponentResult result, ChainContext context) async {
-    Component component = result.component;
-    StringBuffer messages = new StringBuffer();
-    ProcessedOptions options = new ProcessedOptions(
-        options: new CompilerOptions()
-          ..onDiagnostic = (DiagnosticMessage message) {
-            if (messages.isNotEmpty) {
-              messages.write("\n");
-            }
-            messages.writeAll(message.plainTextFormatted, "\n");
-          });
-    return await CompilerContext.runWithOptions(options,
-        (compilerContext) async {
-      compilerContext.uriToSource.addAll(component.uriToSource);
-      List<LocatedMessage> verificationErrors = verifyComponent(component,
-          isOutline: !fullCompile, skipPlatform: true);
-      assert(verificationErrors.isEmpty || messages.isNotEmpty);
-      if (messages.isEmpty) {
-        return pass(result);
-      } else {
-        return new Result<ComponentResult>(null,
-            context.expectationSet["VerificationError"], "$messages", null);
-      }
-    }, errorOnMissingInput: false);
-  }
-}
-
 class TypeCheck extends Step<ComponentResult, ComponentResult, ChainContext> {
   const TypeCheck();
 
@@ -316,6 +288,15 @@
       printer.endLine();
     });
     printer.writeConstantTable(componentToText);
+
+    if (result.extraConstantStrings.isNotEmpty) {
+      buffer.writeln("");
+      buffer.writeln("Extra constant evaluation status:");
+      for (String extraConstantString in result.extraConstantStrings) {
+        buffer.writeln(extraConstantString);
+      }
+    }
+
     String actual = "$buffer";
     String binariesPath =
         relativizeUri(Uri.base, platformBinariesLocation, isWindows);
@@ -418,8 +399,8 @@
     Uri uri = tmp.uri.resolve("generated.dill");
     File generated = new File.fromUri(uri);
     IOSink sink = generated.openWrite();
-    result = new ComponentResult(
-        result.description, result.component, result.userLibraries, uri);
+    result = new ComponentResult(result.description, result.component,
+        result.userLibraries, result.options, result.sourceTarget, uri);
     try {
       new BinaryPrinter(sink).writeComponentFile(component);
     } catch (e, s) {
@@ -515,8 +496,12 @@
   final Component component;
   final Set<Uri> userLibraries;
   final Uri outputUri;
+  final ProcessedOptions options;
+  final KernelTarget sourceTarget;
+  final List<String> extraConstantStrings = [];
 
   ComponentResult(this.description, this.component, this.userLibraries,
+      this.options, this.sourceTarget,
       [this.outputUri]);
 
   bool isUserLibrary(Library library) {
diff --git a/pkg/front_end/test/vm_service_coverage.dart b/pkg/front_end/test/vm_service_coverage.dart
new file mode 100644
index 0000000..b144e3d
--- /dev/null
+++ b/pkg/front_end/test/vm_service_coverage.dart
@@ -0,0 +1,142 @@
+import 'dart:async';
+
+import 'vm_service_helper.dart' as vmService;
+
+main(List<String> args) async {
+  CoverageHelper coverageHelper = new CoverageHelper();
+
+  List<String> allArgs = new List<String>();
+  allArgs.addAll([
+    "--disable-dart-dev",
+    "--enable-asserts",
+    "--pause_isolates_on_exit",
+  ]);
+  allArgs.addAll(args);
+
+  coverageHelper.start(allArgs);
+}
+
+class CoverageHelper extends vmService.LaunchingVMServiceHelper {
+  final bool forceCompilation;
+  final bool printHits;
+
+  CoverageHelper({this.forceCompilation: false, this.printHits: true});
+
+  @override
+  Future<void> run() async {
+    vmService.VM vm = await serviceClient.getVM();
+    if (vm.isolates.length != 1) {
+      throw "Expected 1 isolate, got ${vm.isolates.length}";
+    }
+    vmService.IsolateRef isolateRef = vm.isolates.single;
+    await waitUntilIsolateIsRunnable(isolateRef.id);
+    await serviceClient.resume(isolateRef.id);
+    Completer<String> cTimeout = new Completer();
+    Timer timer = new Timer(new Duration(minutes: 20), () {
+      cTimeout.complete("Timeout");
+      killProcess();
+    });
+
+    Completer<String> cRunDone = new Completer();
+    // ignore: unawaited_futures
+    waitUntilPaused(isolateRef.id).then((value) => cRunDone.complete("Done"));
+
+    await Future.any([cRunDone.future, cTimeout.future, cProcessExited.future]);
+
+    timer.cancel();
+
+    if (!await isPausedAtExit(isolateRef.id)) {
+      killProcess();
+      throw "Expected to be paused at exit, but is just paused!";
+    }
+
+    // Get and process coverage information.
+    Stopwatch stopwatch = new Stopwatch()..start();
+    vmService.SourceReport sourceReport = await serviceClient.getSourceReport(
+        isolateRef.id, [vmService.SourceReportKind.kCoverage],
+        forceCompile: forceCompilation);
+    print("Got source report from VM in ${stopwatch.elapsedMilliseconds} ms");
+    stopwatch.reset();
+    Map<Uri, Coverage> coverages = {};
+    for (vmService.SourceReportRange range in sourceReport.ranges) {
+      vmService.ScriptRef script = sourceReport.scripts[range.scriptIndex];
+      Uri scriptUri = Uri.parse(script.uri);
+      if (!includeCoverageFor(scriptUri)) continue;
+      Coverage coverage = coverages[scriptUri] ??= new Coverage();
+
+      vmService.SourceReportCoverage sourceReportCoverage = range.coverage;
+      if (sourceReportCoverage == null) {
+        // Range not compiled. Record the range if provided.
+        assert(!range.compiled);
+        if (range.startPos >= 0 || range.endPos >= 0) {
+          coverage.notCompiled
+              .add(new StartEndPair(range.startPos, range.endPos));
+        }
+        continue;
+      }
+      coverage.hits.addAll(sourceReportCoverage.hits);
+      coverage.misses.addAll(sourceReportCoverage.misses);
+    }
+    print("Processed source report from VM in "
+        "${stopwatch.elapsedMilliseconds} ms");
+    stopwatch.reset();
+
+    // It's paused at exit, so resuming should allow us to exit.
+    await serviceClient.resume(isolateRef.id);
+
+    for (MapEntry<Uri, Coverage> entry in coverages.entries) {
+      assert(entry.value.hits.intersection(entry.value.misses).isEmpty);
+      if (entry.value.hits.isEmpty &&
+          entry.value.misses.isEmpty &&
+          entry.value.notCompiled.isEmpty) {
+        continue;
+      }
+      print(entry.key);
+      if (printHits) {
+        print("Hits: ${entry.value.hits.toList()..sort()}");
+      }
+      print("Misses: ${entry.value.misses.toList()..sort()}");
+      print("Not compiled: ${entry.value.notCompiled.toList()..sort()}");
+      print("");
+    }
+  }
+
+  Completer<String> cProcessExited = new Completer();
+  void processExited(int exitCode) {
+    cProcessExited.complete("Exit");
+  }
+
+  bool includeCoverageFor(Uri uri) {
+    if (uri.scheme == "dart") {
+      return false;
+    }
+    if (uri.scheme == "package") {
+      return uri.pathSegments.first == "front_end" ||
+          uri.pathSegments.first == "_fe_analyzer_shared" ||
+          uri.pathSegments.first == "kernel";
+    }
+    return true;
+  }
+}
+
+class Coverage {
+  final Set<int> hits = {};
+  final Set<int> misses = {};
+  final Set<StartEndPair> notCompiled = {};
+}
+
+class StartEndPair implements Comparable {
+  final int startPos;
+  final int endPos;
+
+  StartEndPair(this.startPos, this.endPos);
+
+  String toString() => "[$startPos - $endPos]";
+
+  @override
+  int compareTo(Object other) {
+    if (other is! StartEndPair) return -1;
+    StartEndPair o = other;
+    return startPos - o.startPos;
+  }
+}
diff --git a/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart b/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart
new file mode 100644
index 0000000..4cab31b
--- /dev/null
+++ b/pkg/front_end/test/vm_service_coverage_constant_evaluator.dart
@@ -0,0 +1,27 @@
+import 'vm_service_coverage.dart' as helper;
+
+main(List<String> args) async {
+  CoverageHelper coverageHelper = new CoverageHelper();
+
+  List<String> allArgs = new List<String>();
+  allArgs.addAll([
+    "--disable-dart-dev",
+    "--enable-asserts",
+    "--pause_isolates_on_exit",
+  ]);
+  allArgs.addAll(args);
+
+  coverageHelper.start(allArgs);
+}
+
+class CoverageHelper extends helper.CoverageHelper {
+  CoverageHelper() : super(printHits: false);
+
+  bool includeCoverageFor(Uri uri) {
+    if (uri.scheme != "package") return false;
+    if (uri.path.startsWith("front_end/src/fasta/kernel/constant_")) {
+      return true;
+    }
+    return false;
+  }
+}
diff --git a/pkg/front_end/test/vm_service_heap_finder.dart b/pkg/front_end/test/vm_service_heap_finder.dart
index ea3bcea..2e85184 100644
--- a/pkg/front_end/test/vm_service_heap_finder.dart
+++ b/pkg/front_end/test/vm_service_heap_finder.dart
@@ -3,7 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import "dart:io";
-import "vm_service_heap_helper.dart";
+
+import "vm_service_helper.dart" as vmService;
 
 class Foo {
   final String x;
@@ -31,7 +32,7 @@
   foos.add(new Foo("!", 44));
 
   if (connectTo == null) connectTo = ask("Connect to");
-  VMServiceHeapHelperBase vm = VMServiceHeapHelperBase();
+  VMServiceHeapHelperPrinter vm = VMServiceHeapHelperPrinter();
   await vm.connect(Uri.parse(connectTo.trim()));
   String isolateId = await vm.getIsolateId();
   if (classToFind == null) classToFind = ask("Find what class");
@@ -61,3 +62,97 @@
   stdout.write("$question: ");
   return stdin.readLineSync();
 }
+
+class VMServiceHeapHelperPrinter extends vmService.VMServiceHelper {
+  Future<void> printAllocationProfile(String isolateId, {String filter}) async {
+    await waitUntilIsolateIsRunnable(isolateId);
+    vmService.AllocationProfile allocationProfile =
+        await serviceClient.getAllocationProfile(isolateId);
+    for (vmService.ClassHeapStats member in allocationProfile.members) {
+      if (filter != null) {
+        if (member.classRef.name != filter) continue;
+      } else {
+        if (member.classRef.name == "") continue;
+        if (member.instancesCurrent == 0) continue;
+      }
+      vmService.Class c =
+          await serviceClient.getObject(isolateId, member.classRef.id);
+      if (c.location?.script?.uri == null) continue;
+      print("${member.classRef.name}: ${member.instancesCurrent}");
+    }
+  }
+
+  Future<void> filterAndPrintInstances(String isolateId, String filter,
+      String fieldName, Set<String> fieldValues) async {
+    await waitUntilIsolateIsRunnable(isolateId);
+    vmService.AllocationProfile allocationProfile =
+        await serviceClient.getAllocationProfile(isolateId);
+    for (vmService.ClassHeapStats member in allocationProfile.members) {
+      if (member.classRef.name != filter) continue;
+      vmService.Class c =
+          await serviceClient.getObject(isolateId, member.classRef.id);
+      if (c.location?.script?.uri == null) continue;
+      print("${member.classRef.name}: ${member.instancesCurrent}");
+      print(c.location.script.uri);
+
+      vmService.InstanceSet instances = await serviceClient.getInstances(
+          isolateId, member.classRef.id, 10000);
+      int instanceNum = 0;
+      for (vmService.ObjRef instance in instances.instances) {
+        instanceNum++;
+        vmService.Obj receivedObject =
+            await serviceClient.getObject(isolateId, instance.id);
+        if (receivedObject is! vmService.Instance) continue;
+        vmService.Instance object = receivedObject;
+        for (vmService.BoundField field in object.fields) {
+          if (field.decl.name == fieldName) {
+            if (field.value is vmService.Sentinel) continue;
+            vmService.Obj receivedValue =
+                await serviceClient.getObject(isolateId, field.value.id);
+            if (receivedValue is! vmService.Instance) continue;
+            String value = (receivedValue as vmService.Instance).valueAsString;
+            if (!fieldValues.contains(value)) continue;
+            print("${instanceNum}: ${field.decl.name}: "
+                "${value} --- ${instance.id}");
+          }
+        }
+      }
+    }
+    print("Done!");
+  }
+
+  Future<void> printRetainingPaths(String isolateId, String filter) async {
+    await waitUntilIsolateIsRunnable(isolateId);
+    vmService.AllocationProfile allocationProfile =
+        await serviceClient.getAllocationProfile(isolateId);
+    for (vmService.ClassHeapStats member in allocationProfile.members) {
+      if (member.classRef.name != filter) continue;
+      vmService.Class c =
+          await serviceClient.getObject(isolateId, member.classRef.id);
+      print("Found ${c.name} (location: ${c.location})");
+      print("${member.classRef.name}: "
+          "(instancesCurrent: ${member.instancesCurrent})");
+      print("");
+
+      vmService.InstanceSet instances = await serviceClient.getInstances(
+          isolateId, member.classRef.id, 10000);
+      print(" => Got ${instances.instances.length} instances");
+      print("");
+
+      for (vmService.ObjRef instance in instances.instances) {
+        vmService.Obj receivedObject =
+            await serviceClient.getObject(isolateId, instance.id);
+        print("Instance: $receivedObject");
+        vmService.RetainingPath retainingPath =
+            await serviceClient.getRetainingPath(isolateId, instance.id, 1000);
+        print("Retaining path: (length ${retainingPath.length}");
+        for (int i = 0; i < retainingPath.elements.length; i++) {
+          print("  [$i] = ${retainingPath.elements[i]}");
+        }
+
+        print("");
+      }
+    }
+    print("Done!");
+  }
+}
diff --git a/pkg/front_end/test/vm_service_heap_helper.dart b/pkg/front_end/test/vm_service_heap_helper.dart
index d801f3d..497c0b3 100644
--- a/pkg/front_end/test/vm_service_heap_helper.dart
+++ b/pkg/front_end/test/vm_service_heap_helper.dart
@@ -2,288 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:convert";
-import "dart:io";
-
-import "package:vm_service/vm_service.dart" as vmService;
-import "package:vm_service/vm_service_io.dart" as vmService;
-
 import "dijkstras_sssp_algorithm.dart";
-
-class VMServiceHeapHelperBase {
-  vmService.VmService _serviceClient;
-  vmService.VmService get serviceClient => _serviceClient;
-
-  VMServiceHeapHelperBase();
-
-  Future connect(Uri observatoryUri) async {
-    String path = observatoryUri.path;
-    if (!path.endsWith("/")) path += "/";
-    String wsUriString = 'ws://${observatoryUri.authority}${path}ws';
-    _serviceClient = await vmService.vmServiceConnectUri(wsUriString,
-        log: const StdOutLog());
-  }
-
-  Future disconnect() async {
-    await _serviceClient.dispose();
-  }
-
-  Future<bool> waitUntilPaused(String isolateId) async {
-    int nulls = 0;
-    while (true) {
-      bool result = await _isPaused(isolateId);
-      if (result == null) {
-        nulls++;
-        if (nulls > 5) {
-          // We've now asked for the isolate 5 times and in all cases gotten
-          // `Sentinel`. Most likely things aren't working for whatever reason.
-          return false;
-        }
-      } else if (result) {
-        return true;
-      } else {
-        await Future.delayed(const Duration(milliseconds: 100));
-      }
-    }
-  }
-
-  Future<bool> _isPaused(String isolateId) async {
-    dynamic tmp = await _serviceClient.getIsolate(isolateId);
-    if (tmp is vmService.Isolate) {
-      vmService.Isolate isolate = tmp;
-      if (isolate.pauseEvent.kind != "Resume") return true;
-      return false;
-    }
-    return null;
-  }
-
-  Future<bool> _isPausedAtStart(String isolateId) async {
-    dynamic tmp = await _serviceClient.getIsolate(isolateId);
-    if (tmp is vmService.Isolate) {
-      vmService.Isolate isolate = tmp;
-      return isolate.pauseEvent.kind == "PauseStart";
-    }
-    return false;
-  }
-
-  Future<vmService.AllocationProfile> forceGC(String isolateId) async {
-    await waitUntilIsolateIsRunnable(isolateId);
-    int expectGcAfter = new DateTime.now().millisecondsSinceEpoch;
-    while (true) {
-      vmService.AllocationProfile allocationProfile;
-      try {
-        allocationProfile =
-            await _serviceClient.getAllocationProfile(isolateId, gc: true);
-      } catch (e) {
-        print(e.runtimeType);
-        rethrow;
-      }
-      if (allocationProfile.dateLastServiceGC != null &&
-          allocationProfile.dateLastServiceGC >= expectGcAfter) {
-        return allocationProfile;
-      }
-    }
-  }
-
-  Future<bool> isIsolateRunnable(String isolateId) async {
-    dynamic tmp = await _serviceClient.getIsolate(isolateId);
-    if (tmp is vmService.Isolate) {
-      vmService.Isolate isolate = tmp;
-      return isolate.runnable;
-    }
-    return null;
-  }
-
-  Future<void> waitUntilIsolateIsRunnable(String isolateId) async {
-    int nulls = 0;
-    while (true) {
-      bool result = await isIsolateRunnable(isolateId);
-      if (result == null) {
-        nulls++;
-        if (nulls > 5) {
-          // We've now asked for the isolate 5 times and in all cases gotten
-          // `Sentinel`. Most likely things aren't working for whatever reason.
-          return;
-        }
-      } else if (result) {
-        return;
-      } else {
-        await Future.delayed(const Duration(milliseconds: 100));
-      }
-    }
-  }
-
-  Future<void> printAllocationProfile(String isolateId, {String filter}) async {
-    await waitUntilIsolateIsRunnable(isolateId);
-    vmService.AllocationProfile allocationProfile =
-        await _serviceClient.getAllocationProfile(isolateId);
-    for (vmService.ClassHeapStats member in allocationProfile.members) {
-      if (filter != null) {
-        if (member.classRef.name != filter) continue;
-      } else {
-        if (member.classRef.name == "") continue;
-        if (member.instancesCurrent == 0) continue;
-      }
-      vmService.Class c =
-          await _serviceClient.getObject(isolateId, member.classRef.id);
-      if (c.location?.script?.uri == null) continue;
-      print("${member.classRef.name}: ${member.instancesCurrent}");
-    }
-  }
-
-  Future<void> filterAndPrintInstances(String isolateId, String filter,
-      String fieldName, Set<String> fieldValues) async {
-    await waitUntilIsolateIsRunnable(isolateId);
-    vmService.AllocationProfile allocationProfile =
-        await _serviceClient.getAllocationProfile(isolateId);
-    for (vmService.ClassHeapStats member in allocationProfile.members) {
-      if (member.classRef.name != filter) continue;
-      vmService.Class c =
-          await _serviceClient.getObject(isolateId, member.classRef.id);
-      if (c.location?.script?.uri == null) continue;
-      print("${member.classRef.name}: ${member.instancesCurrent}");
-      print(c.location.script.uri);
-
-      vmService.InstanceSet instances = await _serviceClient.getInstances(
-          isolateId, member.classRef.id, 10000);
-      int instanceNum = 0;
-      for (vmService.ObjRef instance in instances.instances) {
-        instanceNum++;
-        var receivedObject =
-            await _serviceClient.getObject(isolateId, instance.id);
-        if (receivedObject is! vmService.Instance) continue;
-        vmService.Instance object = receivedObject;
-        for (vmService.BoundField field in object.fields) {
-          if (field.decl.name == fieldName) {
-            if (field.value is vmService.Sentinel) continue;
-            var receivedValue =
-                await _serviceClient.getObject(isolateId, field.value.id);
-            if (receivedValue is! vmService.Instance) continue;
-            String value = (receivedValue as vmService.Instance).valueAsString;
-            if (!fieldValues.contains(value)) continue;
-            print("${instanceNum}: ${field.decl.name}: "
-                "${value} --- ${instance.id}");
-          }
-        }
-      }
-    }
-    print("Done!");
-  }
-
-  Future<void> printRetainingPaths(String isolateId, String filter) async {
-    await waitUntilIsolateIsRunnable(isolateId);
-    vmService.AllocationProfile allocationProfile =
-        await _serviceClient.getAllocationProfile(isolateId);
-    for (vmService.ClassHeapStats member in allocationProfile.members) {
-      if (member.classRef.name != filter) continue;
-      vmService.Class c =
-          await _serviceClient.getObject(isolateId, member.classRef.id);
-      print("Found ${c.name} (location: ${c.location})");
-      print("${member.classRef.name}: "
-          "(instancesCurrent: ${member.instancesCurrent})");
-      print("");
-
-      vmService.InstanceSet instances = await _serviceClient.getInstances(
-          isolateId, member.classRef.id, 10000);
-      print(" => Got ${instances.instances.length} instances");
-      print("");
-
-      for (vmService.ObjRef instance in instances.instances) {
-        var receivedObject =
-            await _serviceClient.getObject(isolateId, instance.id);
-        print("Instance: $receivedObject");
-        vmService.RetainingPath retainingPath =
-            await _serviceClient.getRetainingPath(isolateId, instance.id, 1000);
-        print("Retaining path: (length ${retainingPath.length}");
-        for (int i = 0; i < retainingPath.elements.length; i++) {
-          print("  [$i] = ${retainingPath.elements[i]}");
-        }
-
-        print("");
-      }
-    }
-    print("Done!");
-  }
-
-  Future<String> getIsolateId() async {
-    vmService.VM vm = await _serviceClient.getVM();
-    if (vm.isolates.length != 1) {
-      throw "Expected 1 isolate, got ${vm.isolates.length}";
-    }
-    vmService.IsolateRef isolateRef = vm.isolates.single;
-    return isolateRef.id;
-  }
-}
-
-abstract class LaunchingVMServiceHeapHelper extends VMServiceHeapHelperBase {
-  Process _process;
-  Process get process => _process;
-
-  bool _started = false;
-
-  void start(List<String> scriptAndArgs,
-      {void stdinReceiver(String line),
-      void stderrReceiver(String line)}) async {
-    if (_started) throw "Already started";
-    _started = true;
-    _process = await Process.start(
-        Platform.resolvedExecutable,
-        ["--pause_isolates_on_start", "--enable-vm-service=0"]
-          ..addAll(scriptAndArgs));
-    _process.stdout
-        .transform(utf8.decoder)
-        .transform(new LineSplitter())
-        .listen((line) {
-      const kObservatoryListening = 'Observatory listening on ';
-      if (line.startsWith(kObservatoryListening)) {
-        Uri observatoryUri =
-            Uri.parse(line.substring(kObservatoryListening.length));
-        _setupAndRun(observatoryUri).catchError((e, st) {
-          // Manually kill the process or it will leak,
-          // see http://dartbug.com/42918
-          killProcess();
-          // This seems to rethrow.
-          throw e;
-        });
-      }
-      if (stdinReceiver != null) {
-        stdinReceiver(line);
-      } else {
-        stdout.writeln("> $line");
-      }
-    });
-    _process.stderr
-        .transform(utf8.decoder)
-        .transform(new LineSplitter())
-        .listen((line) {
-      if (stderrReceiver != null) {
-        stderrReceiver(line);
-      } else {
-        stderr.writeln("> $line");
-      }
-    });
-    // ignore: unawaited_futures
-    _process.exitCode.then((value) {
-      processExited(value);
-    });
-  }
-
-  void processExited(int exitCode) {}
-
-  void killProcess() {
-    _process.kill();
-  }
-
-  Future _setupAndRun(Uri observatoryUri) async {
-    await connect(observatoryUri);
-    await run();
-  }
-
-  Future<void> run();
-}
+import "vm_service_helper.dart" as vmService;
 
 class VMServiceHeapHelperSpecificExactLeakFinder
-    extends LaunchingVMServiceHeapHelper {
+    extends vmService.LaunchingVMServiceHelper {
   final Map<Uri, Map<String, List<String>>> _interests =
       new Map<Uri, Map<String, List<String>>>();
   final Map<Uri, Map<String, List<String>>> _prettyPrints =
@@ -326,7 +49,7 @@
   }
 
   void pause() async {
-    await _serviceClient.pause(_isolateRef.id);
+    await serviceClient.pause(_isolateRef.id);
   }
 
   vmService.VM _vm;
@@ -336,7 +59,7 @@
 
   /// Best effort check if the isolate is idle.
   Future<bool> isIdle() async {
-    dynamic tmp = await _serviceClient.getIsolate(_isolateRef.id);
+    dynamic tmp = await serviceClient.getIsolate(_isolateRef.id);
     if (tmp is vmService.Isolate) {
       vmService.Isolate isolate = tmp;
       return isolate.pauseEvent.topFrame == null;
@@ -346,15 +69,15 @@
 
   @override
   Future<void> run() async {
-    _vm = await _serviceClient.getVM();
+    _vm = await serviceClient.getVM();
     if (_vm.isolates.length != 1) {
       throw "Expected 1 isolate, got ${_vm.isolates.length}";
     }
     _isolateRef = _vm.isolates.single;
     await forceGC(_isolateRef.id);
 
-    assert(await _isPausedAtStart(_isolateRef.id));
-    await _serviceClient.resume(_isolateRef.id);
+    assert(await isPausedAtStart(_isolateRef.id));
+    await serviceClient.resume(_isolateRef.id);
 
     _iterationNumber = 1;
     while (true) {
@@ -364,7 +87,7 @@
 
       vmService.HeapSnapshotGraph heapSnapshotGraph =
           await vmService.HeapSnapshotGraph.getSnapshot(
-              _serviceClient, _isolateRef);
+              serviceClient, _isolateRef);
 
       Set<String> duplicatePrints = {};
       Map<String, List<vmService.HeapSnapshotObject>> groupedByToString = {};
@@ -396,7 +119,7 @@
         }
       }
 
-      await _serviceClient.resume(_isolateRef.id);
+      await serviceClient.resume(_isolateRef.id);
       _iterationNumber++;
     }
   }
@@ -695,20 +418,6 @@
   Interest(this.uri, this.className, this.fieldNames);
 }
 
-class StdOutLog implements vmService.Log {
-  const StdOutLog();
-
-  @override
-  void severe(String message) {
-    print("> SEVERE: $message");
-  }
-
-  @override
-  void warning(String message) {
-    print("> WARNING: $message");
-  }
-}
-
 HeapGraph convertHeapGraph(vmService.HeapSnapshotGraph graph) {
   HeapGraphClassSentinel classSentinel = new HeapGraphClassSentinel();
   List<HeapGraphClassActual> classes =
diff --git a/pkg/front_end/test/vm_service_helper.dart b/pkg/front_end/test/vm_service_helper.dart
new file mode 100644
index 0000000..a80eb5a
--- /dev/null
+++ b/pkg/front_end/test/vm_service_helper.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:convert";
+import "dart:io";
+
+import "package:vm_service/vm_service.dart" as vmService;
+import "package:vm_service/vm_service_io.dart" as vmService;
+
+export "package:vm_service/vm_service.dart";
+export "package:vm_service/vm_service_io.dart";
+
+class VMServiceHelper {
+  vmService.VmService _serviceClient;
+  vmService.VmService get serviceClient => _serviceClient;
+
+  VMServiceHelper();
+
+  Future connect(Uri observatoryUri) async {
+    String path = observatoryUri.path;
+    if (!path.endsWith("/")) path += "/";
+    String wsUriString = 'ws://${observatoryUri.authority}${path}ws';
+    _serviceClient = await vmService.vmServiceConnectUri(wsUriString,
+        log: const StdOutLog());
+  }
+
+  Future disconnect() async {
+    await _serviceClient.dispose();
+  }
+
+  Future<bool> waitUntilPaused(String isolateId) async {
+    int nulls = 0;
+    while (true) {
+      bool result = await isPaused(isolateId);
+      if (result == null) {
+        nulls++;
+        if (nulls > 5) {
+          // We've now asked for the isolate 5 times and in all cases gotten
+          // `Sentinel`. Most likely things aren't working for whatever reason.
+          return false;
+        }
+      } else if (result) {
+        return true;
+      } else {
+        await Future.delayed(const Duration(milliseconds: 100));
+      }
+    }
+  }
+
+  Future<bool> isPaused(String isolateId) async {
+    dynamic tmp = await _serviceClient.getIsolate(isolateId);
+    if (tmp is vmService.Isolate) {
+      vmService.Isolate isolate = tmp;
+      if (isolate.pauseEvent.kind != "Resume") return true;
+      return false;
+    }
+    return null;
+  }
+
+  Future<bool> isPausedAtStart(String isolateId) async {
+    dynamic tmp = await _serviceClient.getIsolate(isolateId);
+    if (tmp is vmService.Isolate) {
+      vmService.Isolate isolate = tmp;
+      return isolate.pauseEvent.kind == "PauseStart";
+    }
+    return false;
+  }
+
+  Future<bool> isPausedAtExit(String isolateId) async {
+    dynamic tmp = await _serviceClient.getIsolate(isolateId);
+    if (tmp is vmService.Isolate) {
+      vmService.Isolate isolate = tmp;
+      return isolate.pauseEvent.kind == "PauseExit";
+    }
+    return false;
+  }
+
+  Future<vmService.AllocationProfile> forceGC(String isolateId) async {
+    await waitUntilIsolateIsRunnable(isolateId);
+    int expectGcAfter = new DateTime.now().millisecondsSinceEpoch;
+    while (true) {
+      vmService.AllocationProfile allocationProfile;
+      try {
+        allocationProfile =
+            await _serviceClient.getAllocationProfile(isolateId, gc: true);
+      } catch (e) {
+        print(e.runtimeType);
+        rethrow;
+      }
+      if (allocationProfile.dateLastServiceGC != null &&
+          allocationProfile.dateLastServiceGC >= expectGcAfter) {
+        return allocationProfile;
+      }
+    }
+  }
+
+  Future<bool> isIsolateRunnable(String isolateId) async {
+    dynamic tmp = await _serviceClient.getIsolate(isolateId);
+    if (tmp is vmService.Isolate) {
+      vmService.Isolate isolate = tmp;
+      return isolate.runnable;
+    }
+    return null;
+  }
+
+  Future<void> waitUntilIsolateIsRunnable(String isolateId) async {
+    int nulls = 0;
+    while (true) {
+      bool result = await isIsolateRunnable(isolateId);
+      if (result == null) {
+        nulls++;
+        if (nulls > 5) {
+          // We've now asked for the isolate 5 times and in all cases gotten
+          // `Sentinel`. Most likely things aren't working for whatever reason.
+          return;
+        }
+      } else if (result) {
+        return;
+      } else {
+        await Future.delayed(const Duration(milliseconds: 100));
+      }
+    }
+  }
+
+  Future<String> getIsolateId() async {
+    vmService.VM vm = await _serviceClient.getVM();
+    if (vm.isolates.length != 1) {
+      throw "Expected 1 isolate, got ${vm.isolates.length}";
+    }
+    vmService.IsolateRef isolateRef = vm.isolates.single;
+    return isolateRef.id;
+  }
+}
+
+class StdOutLog implements vmService.Log {
+  const StdOutLog();
+
+  @override
+  void severe(String message) {
+    print("> SEVERE: $message");
+  }
+
+  @override
+  void warning(String message) {
+    print("> WARNING: $message");
+  }
+}
+
+abstract class LaunchingVMServiceHelper extends VMServiceHelper {
+  Process _process;
+  Process get process => _process;
+
+  bool _started = false;
+
+  void start(List<String> scriptAndArgs,
+      {void stdinReceiver(String line),
+      void stderrReceiver(String line)}) async {
+    if (_started) throw "Already started";
+    _started = true;
+    _process = await Process.start(
+        Platform.resolvedExecutable,
+        ["--pause_isolates_on_start", "--enable-vm-service=0"]
+          ..addAll(scriptAndArgs));
+    _process.stdout
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((line) {
+      const kObservatoryListening = 'Observatory listening on ';
+      if (line.startsWith(kObservatoryListening)) {
+        Uri observatoryUri =
+            Uri.parse(line.substring(kObservatoryListening.length));
+        _setupAndRun(observatoryUri).catchError((e, st) {
+          // Manually kill the process or it will leak,
+          // see http://dartbug.com/42918
+          killProcess();
+          // This seems to rethrow.
+          throw e;
+        });
+      }
+      if (stdinReceiver != null) {
+        stdinReceiver(line);
+      } else {
+        stdout.writeln("> $line");
+      }
+    });
+    _process.stderr
+        .transform(utf8.decoder)
+        .transform(new LineSplitter())
+        .listen((line) {
+      if (stderrReceiver != null) {
+        stderrReceiver(line);
+      } else {
+        stderr.writeln("> $line");
+      }
+    });
+    // ignore: unawaited_futures
+    _process.exitCode.then((value) {
+      processExited(value);
+    });
+  }
+
+  void processExited(int exitCode) {}
+
+  void killProcess() {
+    _process.kill();
+  }
+
+  Future _setupAndRun(Uri observatoryUri) async {
+    await connect(observatoryUri);
+    await run();
+  }
+
+  Future<void> run();
+}
diff --git a/pkg/front_end/testcases/agnostic/as.dart.outline.expect b/pkg/front_end/testcases/agnostic/as.dart.outline.expect
index 46f9ad3..b6d34a3 100644
--- a/pkg/front_end/testcases/agnostic/as.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/as.dart.outline.expect
@@ -6,3 +6,9 @@
 static const field core::List<core::int> b = const <core::int?>[] as{ForNonNullableByDefault} core::List<core::int>;
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///as.dart:5:17 -> ListConstant(const <Null?>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///as.dart:6:17 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 4, effectively constant: 2
diff --git a/pkg/front_end/testcases/agnostic/as.dart.strong.expect b/pkg/front_end/testcases/agnostic/as.dart.strong.expect
index a8f9bcc..2afa361 100644
--- a/pkg/front_end/testcases/agnostic/as.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/as.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/as.dart:5:20: Error: Constant evaluation error:
 // const a = <Null>[] as List<int>;
@@ -21,7 +22,6 @@
 // const b = <int?>[] as List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/as.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/as.dart.strong.transformed.expect
index a8f9bcc..2afa361 100644
--- a/pkg/front_end/testcases/agnostic/as.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/as.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/as.dart:5:20: Error: Constant evaluation error:
 // const a = <Null>[] as List<int>;
@@ -21,7 +22,6 @@
 // const b = <int?>[] as List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.outline.expect b/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
index 3163945..a3ec3dc 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.outline.expect
@@ -7,3 +7,11 @@
 static const field core::bool c = core::identical(self::a, self::b);
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///identical.dart:5:16 -> ListConstant(const <int>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///identical.dart:6:17 -> ListConstant(const <int?>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///identical.dart:7:21 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///identical.dart:7:24 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 5, effectively constant: 4
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.strong.expect b/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
index c195846..fd8a51e 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/identical.dart:7:11: Error: Constant evaluation error:
 // const c = identical(a, b);
@@ -11,7 +12,6 @@
 // const c = identical(a, b);
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
index c195846..fd8a51e 100644
--- a/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/identical.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/identical.dart:7:11: Error: Constant evaluation error:
 // const c = identical(a, b);
@@ -11,7 +12,6 @@
 // const c = identical(a, b);
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/is.dart.outline.expect b/pkg/front_end/testcases/agnostic/is.dart.outline.expect
index d8d8870..0046b04 100644
--- a/pkg/front_end/testcases/agnostic/is.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/is.dart.outline.expect
@@ -6,3 +6,9 @@
 static const field core::bool b = const <core::int?>[] is{ForNonNullableByDefault} core::List<core::int>;
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///is.dart:5:17 -> ListConstant(const <Null?>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///is.dart:6:17 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 4, effectively constant: 2
diff --git a/pkg/front_end/testcases/agnostic/is.dart.strong.expect b/pkg/front_end/testcases/agnostic/is.dart.strong.expect
index 4686996..82dac4a 100644
--- a/pkg/front_end/testcases/agnostic/is.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/is.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/is.dart:5:20: Error: Constant evaluation error:
 // const a = <Null>[] is List<int>;
@@ -21,7 +22,6 @@
 // const b = <int?>[] is List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/is.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/is.dart.strong.transformed.expect
index 4686996..82dac4a 100644
--- a/pkg/front_end/testcases/agnostic/is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/is.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/is.dart:5:20: Error: Constant evaluation error:
 // const a = <Null>[] is List<int>;
@@ -21,7 +22,6 @@
 // const b = <int?>[] is List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/map.dart.outline.expect b/pkg/front_end/testcases/agnostic/map.dart.outline.expect
index 958bfdc..e1ceefa 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.outline.expect
@@ -7,3 +7,11 @@
 static const field core::Map<core::List<core::int?>, core::int> c = const <core::List<core::int?>, core::int>{self::a: 0, self::b: 1};
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:5:16 -> ListConstant(const <int>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///map.dart:6:17 -> ListConstant(const <int?>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///map.dart:7:12 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///map.dart:7:18 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 5, effectively constant: 4
diff --git a/pkg/front_end/testcases/agnostic/map.dart.strong.expect b/pkg/front_end/testcases/agnostic/map.dart.strong.expect
index e976e83..021aca0 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
 // const c = {a: 0, b: 1};
@@ -11,7 +12,6 @@
 // const c = {a: 0, b: 1};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
index e976e83..021aca0 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
 // const c = {a: 0, b: 1};
@@ -11,7 +12,6 @@
 // const c = {a: 0, b: 1};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/map.dart.weak.expect b/pkg/front_end/testcases/agnostic/map.dart.weak.expect
index 8b33ddc..1d3e649 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.weak.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
 // const c = {a: 0, b: 1};
@@ -11,7 +12,6 @@
 // const c = {a: 0, b: 1};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
index 8b33ddc..1d3e649 100644
--- a/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/map.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/map.dart:7:11: Error: Constant evaluation error:
 // const c = {a: 0, b: 1};
@@ -11,7 +12,6 @@
 // const c = {a: 0, b: 1};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/set.dart.outline.expect b/pkg/front_end/testcases/agnostic/set.dart.outline.expect
index da68e96..53dca31 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.outline.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.outline.expect
@@ -7,3 +7,11 @@
 static const field core::Set<core::List<core::int?>> c = const <core::List<core::int?>>{self::a, self::b};
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:5:16 -> ListConstant(const <int>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///set.dart:6:17 -> ListConstant(const <int?>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///set.dart:7:12 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///set.dart:7:15 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 5, effectively constant: 4
diff --git a/pkg/front_end/testcases/agnostic/set.dart.strong.expect b/pkg/front_end/testcases/agnostic/set.dart.strong.expect
index b92b78e..ad0fc3d 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.strong.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
 // const c = {a, b};
@@ -11,7 +12,6 @@
 // const c = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect b/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
index b92b78e..ad0fc3d 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
 // const c = {a, b};
@@ -11,7 +12,6 @@
 // const c = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/set.dart.weak.expect b/pkg/front_end/testcases/agnostic/set.dart.weak.expect
index 9864f71..f33d0a9 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.weak.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.weak.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
 // const c = {a, b};
@@ -11,7 +12,6 @@
 // const c = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect b/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
index 9864f71..f33d0a9 100644
--- a/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/agnostic/set.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/agnostic/set.dart:7:11: Error: Constant evaluation error:
 // const c = {a, b};
@@ -11,7 +12,6 @@
 // const c = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/expression/invalid.expression.yaml.expect b/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
index 0bf9a2f..7fc40b9 100644
--- a/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
+++ b/pkg/front_end/testcases/expression/invalid.expression.yaml.expect
@@ -3,6 +3,7 @@
   *foo(3,
       ^
   org-dartlang-debug:synthetic_debug_expression:1:1: Error: Expected an identifier, but got '*'.
+  Try inserting an identifier before '*'.
   *foo(3,
   ^
   org-dartlang-debug:synthetic_debug_expression:1:2: Error: Method not found: 'foo'.
diff --git a/pkg/front_end/testcases/expression/main.dart b/pkg/front_end/testcases/expression/main.dart
index e38cbea..91ad8d9 100644
--- a/pkg/front_end/testcases/expression/main.dart
+++ b/pkg/front_end/testcases/expression/main.dart
@@ -42,7 +42,7 @@
     return "";
   }
 
-  void set z(int _) {}
+  void set z(_) {}
   void _privMethod() {}
 }
 
diff --git a/pkg/front_end/testcases/extensions/annotations.dart.outline.expect b/pkg/front_end/testcases/extensions/annotations.dart.outline.expect
index 5d1e201..ff75d1b 100644
--- a/pkg/front_end/testcases/extensions/annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/annotations.dart.outline.expect
@@ -40,3 +40,12 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:6:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:9:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:14:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:17:4 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotations.dart:21:2 -> InstanceConstant(const pragma{pragma.name: "dart2js:noInline", pragma.options: null})
+Extra constant evaluation: evaluated: 8, effectively constant: 5
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart b/pkg/front_end/testcases/extensions/async_extensions.dart
new file mode 100644
index 0000000..a958690
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension Extension on int {
+  syncStarMethod() sync* {}
+  asyncMethod() async {}
+  asyncStarMethod() async* {}
+}
+
+main() {
+  0.syncStarMethod();
+  0.syncStarMethod;
+  0.asyncMethod();
+  0.asyncMethod;
+  0.asyncStarMethod();
+  0.asyncStarMethod;
+}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.outline.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.outline.expect
new file mode 100644
index 0000000..18fc103
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.outline.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  method syncStarMethod = self::Extension|syncStarMethod;
+  tearoff syncStarMethod = self::Extension|get#syncStarMethod;
+  method asyncMethod = self::Extension|asyncMethod;
+  tearoff asyncMethod = self::Extension|get#asyncMethod;
+  method asyncStarMethod = self::Extension|asyncStarMethod;
+  tearoff asyncStarMethod = self::Extension|get#asyncStarMethod;
+}
+static method Extension|syncStarMethod(final core::int* #this) → dynamic sync* 
+  ;
+static method Extension|get#syncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|syncStarMethod(#this);
+static method Extension|asyncMethod(final core::int* #this) → dynamic async 
+  ;
+static method Extension|get#asyncMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncMethod(#this);
+static method Extension|asyncStarMethod(final core::int* #this) → dynamic async* 
+  ;
+static method Extension|get#asyncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncStarMethod(#this);
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.strong.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.strong.expect
new file mode 100644
index 0000000..fd5e869
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.strong.expect
@@ -0,0 +1,29 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+extension Extension on core::int* {
+  method syncStarMethod = self::Extension|syncStarMethod;
+  tearoff syncStarMethod = self::Extension|get#syncStarMethod;
+  method asyncMethod = self::Extension|asyncMethod;
+  tearoff asyncMethod = self::Extension|get#asyncMethod;
+  method asyncStarMethod = self::Extension|asyncStarMethod;
+  tearoff asyncStarMethod = self::Extension|get#asyncStarMethod;
+}
+static method Extension|syncStarMethod(final core::int* #this) → dynamic sync* {}
+static method Extension|get#syncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|syncStarMethod(#this);
+static method Extension|asyncMethod(final core::int* #this) → dynamic async {}
+static method Extension|get#asyncMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncMethod(#this);
+static method Extension|asyncStarMethod(final core::int* #this) → dynamic async* {}
+static method Extension|get#asyncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncStarMethod(#this);
+static method main() → dynamic {
+  self::Extension|syncStarMethod(0);
+  self::Extension|get#syncStarMethod(0);
+  self::Extension|asyncMethod(0);
+  self::Extension|get#asyncMethod(0);
+  self::Extension|asyncStarMethod(0);
+  self::Extension|get#asyncStarMethod(0);
+}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.strong.transformed.expect
new file mode 100644
index 0000000..1ef6cf1
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.strong.transformed.expect
@@ -0,0 +1,90 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+extension Extension on core::int* {
+  method syncStarMethod = self::Extension|syncStarMethod;
+  tearoff syncStarMethod = self::Extension|get#syncStarMethod;
+  method asyncMethod = self::Extension|asyncMethod;
+  tearoff asyncMethod = self::Extension|get#asyncMethod;
+  method asyncStarMethod = self::Extension|asyncStarMethod;
+  tearoff asyncStarMethod = self::Extension|get#asyncStarMethod;
+}
+static method Extension|syncStarMethod(final core::int* #this) → dynamic /* originally sync* */ {
+  function :sync_op_gen() → (core::_SyncIterator<dynamic>*) →* core::bool* {
+    core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    return (core::_SyncIterator<dynamic>* :iterator) → core::bool* yielding {
+      {}
+      return false;
+    };
+  }
+  return new core::_SyncIterable::•<dynamic>(:sync_op_gen);
+}
+static method Extension|get#syncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|syncStarMethod(#this);
+static method Extension|asyncMethod(final core::int* #this) → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {}
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method Extension|get#asyncMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncMethod(#this);
+static method Extension|asyncStarMethod(final core::int* #this) → dynamic /* originally async* */ {
+  asy::_AsyncStarStreamController<dynamic>* :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L2:
+        {}
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<dynamic>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method Extension|get#asyncStarMethod(final core::int* #this) → () →* dynamic
+  return () → dynamic => self::Extension|asyncStarMethod(#this);
+static method main() → dynamic {
+  self::Extension|syncStarMethod(0);
+  self::Extension|get#syncStarMethod(0);
+  self::Extension|asyncMethod(0);
+  self::Extension|get#asyncMethod(0);
+  self::Extension|asyncStarMethod(0);
+  self::Extension|get#asyncStarMethod(0);
+}
diff --git a/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
new file mode 100644
index 0000000..49c2279
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/async_extensions.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+extension Extension ;
+on int (){}
+main() {}
diff --git a/pkg/front_end/testcases/extensions/conflict_with_object.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/conflict_with_object.dart.strong.transformed.expect
index 891feb9..55715f8 100644
--- a/pkg/front_end/testcases/extensions/conflict_with_object.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/conflict_with_object.dart.strong.transformed.expect
@@ -89,3 +89,8 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///conflict_with_object.dart:21:19 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 37, effectively constant: 1
diff --git a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
index 641de72..c510c9c 100644
--- a/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/deferred_explicit_access.dart.strong.transformed.expect
@@ -94,3 +94,10 @@
 }
 static method topLevelMethod() → dynamic
   return def::Extension|staticField;
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///deferred_explicit_access.dart:12:31 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///deferred_explicit_access.dart:12:45 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///deferred_explicit_access.dart:12:45 -> IntConstant(42)
+Extra constant evaluation: evaluated: 95, effectively constant: 3
diff --git a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
index 1de117d..47097a2 100644
--- a/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_extension_access.dart.strong.transformed.expect
@@ -91,3 +91,11 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_extension_access.dart:48:36 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_extension_access.dart:48:36 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_extension_access.dart:49:36 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_extension_access.dart:49:36 -> IntConstant(67)
+Extra constant evaluation: evaluated: 121, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
index adc49e4..7239cba 100644
--- a/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/explicit_generic_extension_access.dart.strong.transformed.expect
@@ -132,3 +132,13 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:91:41 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:91:41 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:93:41 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:93:41 -> IntConstant(23)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:95:41 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///explicit_generic_extension_access.dart:95:41 -> IntConstant(67)
+Extra constant evaluation: evaluated: 217, effectively constant: 6
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart b/pkg/front_end/testcases/extensions/extension_member_conflict.dart
new file mode 100644
index 0000000..ef4e4de
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension Extension<T> on int {
+  int get duplicateInstanceGetter => 0;
+  int get duplicateInstanceGetter => 0;
+
+  void set duplicateInstanceSetter(int value) {}
+  void set duplicateInstanceSetter(int value) {}
+
+  void duplicateInstanceMethod() {}
+  void duplicateInstanceMethod() {}
+
+  static int duplicateStaticField = 0;
+  static int duplicateStaticField = 0;
+
+  static int get duplicateStaticGetter => 0;
+  static int get duplicateStaticGetter => 0;
+
+  static void set duplicateStaticSetter(int value) {}
+  static void set duplicateStaticSetter(int value) {}
+
+  static void duplicateStaticMethod() {}
+  static void duplicateStaticMethod() {}
+
+  int get duplicateInstanceGetterPlusSetter => 0;
+  int get duplicateInstanceGetterPlusSetter => 0;
+  void set duplicateInstanceGetterPlusSetter(int value) {}
+
+  int get duplicateInstanceSetterPlusGetter => 0;
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+  void set duplicateInstanceSetterPlusGetter(int value) {}
+
+  int get duplicateInstanceGetterAndSetter => 0;
+  int get duplicateInstanceGetterAndSetter => 0;
+  void set duplicateInstanceGetterAndSetter(int value) {}
+  void set duplicateInstanceGetterAndSetter(int value) {}
+
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static int get duplicateStaticGetterPlusSetter => 0;
+  static void set duplicateStaticGetterPlusSetter(int value) {}
+
+  static int get duplicateStaticSetterPlusGetter => 0;
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+  static void set duplicateStaticSetterPlusGetter(int value) {}
+
+  static int get duplicateStaticGetterAndSetter => 0;
+  static int get duplicateStaticGetterAndSetter => 0;
+  static void set duplicateStaticGetterAndSetter(int value) {}
+  static void set duplicateStaticGetterAndSetter(int value) {}
+
+  int get instanceGetterAndStaticSetter => 0;
+  static void set instanceGetterAndStaticSetter(int value) {}
+
+  static int get instanceSetterAndStaticGetter => 0;
+  void set instanceSetterAndStaticGetter(int value) {}
+
+  int get instanceGetterAndStaticField => 0;
+  static int instanceGetterAndStaticField = 0;
+
+  void set instanceSetterAndStaticField(int value) {}
+  static final int instanceGetterAndStaticField = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.outline.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.outline.expect
new file mode 100644
index 0000000..78e8afc
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.outline.expect
@@ -0,0 +1,223 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:7:11: Error: 'duplicateInstanceGetter' is already declared in this scope.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:6:11: Context: Previous declaration of 'duplicateInstanceGetter'.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:10:12: Error: 'duplicateInstanceSetter' is already declared in this scope.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:9:12: Context: Previous declaration of 'duplicateInstanceSetter'.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:13:8: Error: 'duplicateInstanceMethod' is already declared in this scope.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:12:8: Context: Previous declaration of 'duplicateInstanceMethod'.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:16:14: Error: 'duplicateStaticField' is already declared in this scope.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:15:14: Context: Previous declaration of 'duplicateStaticField'.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:19:18: Error: 'duplicateStaticGetter' is already declared in this scope.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:18:18: Context: Previous declaration of 'duplicateStaticGetter'.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:22:19: Error: 'duplicateStaticSetter' is already declared in this scope.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:21:19: Context: Previous declaration of 'duplicateStaticSetter'.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:25:15: Error: 'duplicateStaticMethod' is already declared in this scope.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:24:15: Context: Previous declaration of 'duplicateStaticMethod'.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:28:11: Error: 'duplicateInstanceGetterPlusSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:27:11: Context: Previous declaration of 'duplicateInstanceGetterPlusSetter'.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:33:12: Error: 'duplicateInstanceSetterPlusGetter' is already declared in this scope.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:32:12: Context: Previous declaration of 'duplicateInstanceSetterPlusGetter'.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:36:11: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:35:11: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:38:12: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:37:12: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:41:18: Error: 'duplicateStaticGetterPlusSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:40:18: Context: Previous declaration of 'duplicateStaticGetterPlusSetter'.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:46:19: Error: 'duplicateStaticSetterPlusGetter' is already declared in this scope.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:45:19: Context: Previous declaration of 'duplicateStaticSetterPlusGetter'.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:49:18: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:48:18: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:51:19: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:50:19: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:59:11: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   int get instanceGetterAndStaticField => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:63:20: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static final int instanceGetterAndStaticField = 0;
+//                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:54:19: Error: Conflicts with member 'instanceGetterAndStaticSetter'.
+//   static void set instanceGetterAndStaticSetter(int value) {}
+//                   ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:53:11: Error: Conflicts with setter 'instanceGetterAndStaticSetter'.
+//   int get instanceGetterAndStaticSetter => 0;
+//           ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:57:12: Error: Conflicts with member 'instanceSetterAndStaticGetter'.
+//   void set instanceSetterAndStaticGetter(int value) {}
+//            ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:56:18: Error: Conflicts with setter 'instanceSetterAndStaticGetter'.
+//   static int get instanceSetterAndStaticGetter => 0;
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension Extension<T extends core::Object* = dynamic> on core::int* {
+  get duplicateInstanceGetter = self::Extension|get#duplicateInstanceGetter;
+  method duplicateInstanceMethod = self::Extension|duplicateInstanceMethod;
+  tearoff duplicateInstanceMethod = self::Extension|get#duplicateInstanceMethod;
+  static field duplicateStaticField = self::Extension|duplicateStaticField;
+  static get duplicateStaticGetter = get self::Extension|duplicateStaticGetter;
+  static method duplicateStaticMethod = self::Extension|duplicateStaticMethod;
+  get duplicateInstanceGetterPlusSetter = self::Extension|get#duplicateInstanceGetterPlusSetter;
+  get duplicateInstanceSetterPlusGetter = self::Extension|get#duplicateInstanceSetterPlusGetter;
+  get duplicateInstanceGetterAndSetter = self::Extension|get#duplicateInstanceGetterAndSetter;
+  static get duplicateStaticGetterPlusSetter = get self::Extension|duplicateStaticGetterPlusSetter;
+  static get duplicateStaticSetterPlusGetter = get self::Extension|duplicateStaticSetterPlusGetter;
+  static get duplicateStaticGetterAndSetter = get self::Extension|duplicateStaticGetterAndSetter;
+  get instanceGetterAndStaticSetter = self::Extension|get#instanceGetterAndStaticSetter;
+  static get instanceSetterAndStaticGetter = get self::Extension|instanceSetterAndStaticGetter;
+  get instanceGetterAndStaticField = self::Extension|get#instanceGetterAndStaticField;
+  set duplicateInstanceSetter = self::Extension|set#duplicateInstanceSetter;
+  static set duplicateStaticSetter = set self::Extension|duplicateStaticSetter;
+  set duplicateInstanceGetterPlusSetter = self::Extension|set#duplicateInstanceGetterPlusSetter;
+  set duplicateInstanceSetterPlusGetter = self::Extension|set#duplicateInstanceSetterPlusGetter;
+  set duplicateInstanceGetterAndSetter = self::Extension|set#duplicateInstanceGetterAndSetter;
+  static set duplicateStaticGetterPlusSetter = set self::Extension|duplicateStaticGetterPlusSetter;
+  static set duplicateStaticSetterPlusGetter = set self::Extension|duplicateStaticSetterPlusGetter;
+  static set duplicateStaticGetterAndSetter = set self::Extension|duplicateStaticGetterAndSetter;
+  static set instanceGetterAndStaticSetter = set self::Extension|instanceGetterAndStaticSetter;
+  set instanceSetterAndStaticGetter = self::Extension|set#instanceSetterAndStaticGetter;
+  set instanceSetterAndStaticField = self::Extension|set#instanceSetterAndStaticField;
+}
+static field core::int* Extension|duplicateStaticField;
+static method Extension|get#duplicateInstanceGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#duplicateInstanceSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → void
+  ;
+static method Extension|get#duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → () →* void
+  return () → void => self::Extension|duplicateInstanceMethod<self::Extension|get#duplicateInstanceMethod::T*>(#this);
+static get Extension|duplicateStaticGetter() → core::int*
+  ;
+static set Extension|duplicateStaticSetter(core::int* value) → void
+  ;
+static method Extension|duplicateStaticMethod() → void
+  ;
+static method Extension|get#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|get#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|get#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static get Extension|duplicateStaticGetterPlusSetter() → core::int*
+  ;
+static set Extension|duplicateStaticGetterPlusSetter(core::int* value) → void
+  ;
+static get Extension|duplicateStaticSetterPlusGetter() → core::int*
+  ;
+static set Extension|duplicateStaticSetterPlusGetter(core::int* value) → void
+  ;
+static get Extension|duplicateStaticGetterAndSetter() → core::int*
+  ;
+static set Extension|duplicateStaticGetterAndSetter(core::int* value) → void
+  ;
+static method Extension|get#instanceGetterAndStaticSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static set Extension|instanceGetterAndStaticSetter(core::int* value) → void
+  ;
+static get Extension|instanceSetterAndStaticGetter() → core::int*
+  ;
+static method Extension|set#instanceSetterAndStaticGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static method Extension|get#instanceGetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#instanceSetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.expect
new file mode 100644
index 0000000..52aa6f4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.expect
@@ -0,0 +1,209 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:7:11: Error: 'duplicateInstanceGetter' is already declared in this scope.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:6:11: Context: Previous declaration of 'duplicateInstanceGetter'.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:10:12: Error: 'duplicateInstanceSetter' is already declared in this scope.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:9:12: Context: Previous declaration of 'duplicateInstanceSetter'.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:13:8: Error: 'duplicateInstanceMethod' is already declared in this scope.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:12:8: Context: Previous declaration of 'duplicateInstanceMethod'.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:16:14: Error: 'duplicateStaticField' is already declared in this scope.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:15:14: Context: Previous declaration of 'duplicateStaticField'.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:19:18: Error: 'duplicateStaticGetter' is already declared in this scope.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:18:18: Context: Previous declaration of 'duplicateStaticGetter'.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:22:19: Error: 'duplicateStaticSetter' is already declared in this scope.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:21:19: Context: Previous declaration of 'duplicateStaticSetter'.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:25:15: Error: 'duplicateStaticMethod' is already declared in this scope.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:24:15: Context: Previous declaration of 'duplicateStaticMethod'.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:28:11: Error: 'duplicateInstanceGetterPlusSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:27:11: Context: Previous declaration of 'duplicateInstanceGetterPlusSetter'.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:33:12: Error: 'duplicateInstanceSetterPlusGetter' is already declared in this scope.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:32:12: Context: Previous declaration of 'duplicateInstanceSetterPlusGetter'.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:36:11: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:35:11: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:38:12: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:37:12: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:41:18: Error: 'duplicateStaticGetterPlusSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:40:18: Context: Previous declaration of 'duplicateStaticGetterPlusSetter'.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:46:19: Error: 'duplicateStaticSetterPlusGetter' is already declared in this scope.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:45:19: Context: Previous declaration of 'duplicateStaticSetterPlusGetter'.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:49:18: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:48:18: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:51:19: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:50:19: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:59:11: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   int get instanceGetterAndStaticField => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:63:20: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static final int instanceGetterAndStaticField = 0;
+//                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:54:19: Error: Conflicts with member 'instanceGetterAndStaticSetter'.
+//   static void set instanceGetterAndStaticSetter(int value) {}
+//                   ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:53:11: Error: Conflicts with setter 'instanceGetterAndStaticSetter'.
+//   int get instanceGetterAndStaticSetter => 0;
+//           ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:57:12: Error: Conflicts with member 'instanceSetterAndStaticGetter'.
+//   void set instanceSetterAndStaticGetter(int value) {}
+//            ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:56:18: Error: Conflicts with setter 'instanceSetterAndStaticGetter'.
+//   static int get instanceSetterAndStaticGetter => 0;
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension Extension<T extends core::Object* = dynamic> on core::int* {
+  get duplicateInstanceGetter = self::Extension|get#duplicateInstanceGetter;
+  method duplicateInstanceMethod = self::Extension|duplicateInstanceMethod;
+  tearoff duplicateInstanceMethod = self::Extension|get#duplicateInstanceMethod;
+  static field duplicateStaticField = self::Extension|duplicateStaticField;
+  static get duplicateStaticGetter = get self::Extension|duplicateStaticGetter;
+  static method duplicateStaticMethod = self::Extension|duplicateStaticMethod;
+  get duplicateInstanceGetterPlusSetter = self::Extension|get#duplicateInstanceGetterPlusSetter;
+  get duplicateInstanceSetterPlusGetter = self::Extension|get#duplicateInstanceSetterPlusGetter;
+  get duplicateInstanceGetterAndSetter = self::Extension|get#duplicateInstanceGetterAndSetter;
+  static get duplicateStaticGetterPlusSetter = get self::Extension|duplicateStaticGetterPlusSetter;
+  static get duplicateStaticSetterPlusGetter = get self::Extension|duplicateStaticSetterPlusGetter;
+  static get duplicateStaticGetterAndSetter = get self::Extension|duplicateStaticGetterAndSetter;
+  get instanceGetterAndStaticSetter = self::Extension|get#instanceGetterAndStaticSetter;
+  static get instanceSetterAndStaticGetter = get self::Extension|instanceSetterAndStaticGetter;
+  get instanceGetterAndStaticField = self::Extension|get#instanceGetterAndStaticField;
+  set duplicateInstanceSetter = self::Extension|set#duplicateInstanceSetter;
+  static set duplicateStaticSetter = set self::Extension|duplicateStaticSetter;
+  set duplicateInstanceGetterPlusSetter = self::Extension|set#duplicateInstanceGetterPlusSetter;
+  set duplicateInstanceSetterPlusGetter = self::Extension|set#duplicateInstanceSetterPlusGetter;
+  set duplicateInstanceGetterAndSetter = self::Extension|set#duplicateInstanceGetterAndSetter;
+  static set duplicateStaticGetterPlusSetter = set self::Extension|duplicateStaticGetterPlusSetter;
+  static set duplicateStaticSetterPlusGetter = set self::Extension|duplicateStaticSetterPlusGetter;
+  static set duplicateStaticGetterAndSetter = set self::Extension|duplicateStaticGetterAndSetter;
+  static set instanceGetterAndStaticSetter = set self::Extension|instanceGetterAndStaticSetter;
+  set instanceSetterAndStaticGetter = self::Extension|set#instanceSetterAndStaticGetter;
+  set instanceSetterAndStaticField = self::Extension|set#instanceSetterAndStaticField;
+}
+static field core::int* Extension|duplicateStaticField;
+static method Extension|get#duplicateInstanceGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → void {}
+static method Extension|get#duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → () →* void
+  return () → void => self::Extension|duplicateInstanceMethod<self::Extension|get#duplicateInstanceMethod::T*>(#this);
+static get Extension|duplicateStaticGetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticSetter(core::int* value) → void {}
+static method Extension|duplicateStaticMethod() → void {}
+static method Extension|get#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static get Extension|duplicateStaticGetterPlusSetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticGetterPlusSetter(core::int* value) → void {}
+static get Extension|duplicateStaticSetterPlusGetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticSetterPlusGetter(core::int* value) → void {}
+static get Extension|duplicateStaticGetterAndSetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticGetterAndSetter(core::int* value) → void {}
+static method Extension|get#instanceGetterAndStaticSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static set Extension|instanceGetterAndStaticSetter(core::int* value) → void {}
+static get Extension|instanceSetterAndStaticGetter() → core::int*
+  return 0;
+static method Extension|set#instanceSetterAndStaticGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#instanceGetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#instanceSetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.transformed.expect
new file mode 100644
index 0000000..52aa6f4
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.strong.transformed.expect
@@ -0,0 +1,209 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:7:11: Error: 'duplicateInstanceGetter' is already declared in this scope.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:6:11: Context: Previous declaration of 'duplicateInstanceGetter'.
+//   int get duplicateInstanceGetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:10:12: Error: 'duplicateInstanceSetter' is already declared in this scope.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:9:12: Context: Previous declaration of 'duplicateInstanceSetter'.
+//   void set duplicateInstanceSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:13:8: Error: 'duplicateInstanceMethod' is already declared in this scope.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:12:8: Context: Previous declaration of 'duplicateInstanceMethod'.
+//   void duplicateInstanceMethod() {}
+//        ^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:16:14: Error: 'duplicateStaticField' is already declared in this scope.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:15:14: Context: Previous declaration of 'duplicateStaticField'.
+//   static int duplicateStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:19:18: Error: 'duplicateStaticGetter' is already declared in this scope.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:18:18: Context: Previous declaration of 'duplicateStaticGetter'.
+//   static int get duplicateStaticGetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:22:19: Error: 'duplicateStaticSetter' is already declared in this scope.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:21:19: Context: Previous declaration of 'duplicateStaticSetter'.
+//   static void set duplicateStaticSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:25:15: Error: 'duplicateStaticMethod' is already declared in this scope.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:24:15: Context: Previous declaration of 'duplicateStaticMethod'.
+//   static void duplicateStaticMethod() {}
+//               ^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:28:11: Error: 'duplicateInstanceGetterPlusSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:27:11: Context: Previous declaration of 'duplicateInstanceGetterPlusSetter'.
+//   int get duplicateInstanceGetterPlusSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:33:12: Error: 'duplicateInstanceSetterPlusGetter' is already declared in this scope.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:32:12: Context: Previous declaration of 'duplicateInstanceSetterPlusGetter'.
+//   void set duplicateInstanceSetterPlusGetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:36:11: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:35:11: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   int get duplicateInstanceGetterAndSetter => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:38:12: Error: 'duplicateInstanceGetterAndSetter' is already declared in this scope.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:37:12: Context: Previous declaration of 'duplicateInstanceGetterAndSetter'.
+//   void set duplicateInstanceGetterAndSetter(int value) {}
+//            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:41:18: Error: 'duplicateStaticGetterPlusSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:40:18: Context: Previous declaration of 'duplicateStaticGetterPlusSetter'.
+//   static int get duplicateStaticGetterPlusSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:46:19: Error: 'duplicateStaticSetterPlusGetter' is already declared in this scope.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:45:19: Context: Previous declaration of 'duplicateStaticSetterPlusGetter'.
+//   static void set duplicateStaticSetterPlusGetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:49:18: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:48:18: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static int get duplicateStaticGetterAndSetter => 0;
+//                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:51:19: Error: 'duplicateStaticGetterAndSetter' is already declared in this scope.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:50:19: Context: Previous declaration of 'duplicateStaticGetterAndSetter'.
+//   static void set duplicateStaticGetterAndSetter(int value) {}
+//                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:59:11: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   int get instanceGetterAndStaticField => 0;
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:63:20: Error: 'instanceGetterAndStaticField' is already declared in this scope.
+//   static final int instanceGetterAndStaticField = 0;
+//                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:60:14: Context: Previous declaration of 'instanceGetterAndStaticField'.
+//   static int instanceGetterAndStaticField = 0;
+//              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:54:19: Error: Conflicts with member 'instanceGetterAndStaticSetter'.
+//   static void set instanceGetterAndStaticSetter(int value) {}
+//                   ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:53:11: Error: Conflicts with setter 'instanceGetterAndStaticSetter'.
+//   int get instanceGetterAndStaticSetter => 0;
+//           ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:57:12: Error: Conflicts with member 'instanceSetterAndStaticGetter'.
+//   void set instanceSetterAndStaticGetter(int value) {}
+//            ^
+//
+// pkg/front_end/testcases/extensions/extension_member_conflict.dart:56:18: Error: Conflicts with setter 'instanceSetterAndStaticGetter'.
+//   static int get instanceSetterAndStaticGetter => 0;
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+extension Extension<T extends core::Object* = dynamic> on core::int* {
+  get duplicateInstanceGetter = self::Extension|get#duplicateInstanceGetter;
+  method duplicateInstanceMethod = self::Extension|duplicateInstanceMethod;
+  tearoff duplicateInstanceMethod = self::Extension|get#duplicateInstanceMethod;
+  static field duplicateStaticField = self::Extension|duplicateStaticField;
+  static get duplicateStaticGetter = get self::Extension|duplicateStaticGetter;
+  static method duplicateStaticMethod = self::Extension|duplicateStaticMethod;
+  get duplicateInstanceGetterPlusSetter = self::Extension|get#duplicateInstanceGetterPlusSetter;
+  get duplicateInstanceSetterPlusGetter = self::Extension|get#duplicateInstanceSetterPlusGetter;
+  get duplicateInstanceGetterAndSetter = self::Extension|get#duplicateInstanceGetterAndSetter;
+  static get duplicateStaticGetterPlusSetter = get self::Extension|duplicateStaticGetterPlusSetter;
+  static get duplicateStaticSetterPlusGetter = get self::Extension|duplicateStaticSetterPlusGetter;
+  static get duplicateStaticGetterAndSetter = get self::Extension|duplicateStaticGetterAndSetter;
+  get instanceGetterAndStaticSetter = self::Extension|get#instanceGetterAndStaticSetter;
+  static get instanceSetterAndStaticGetter = get self::Extension|instanceSetterAndStaticGetter;
+  get instanceGetterAndStaticField = self::Extension|get#instanceGetterAndStaticField;
+  set duplicateInstanceSetter = self::Extension|set#duplicateInstanceSetter;
+  static set duplicateStaticSetter = set self::Extension|duplicateStaticSetter;
+  set duplicateInstanceGetterPlusSetter = self::Extension|set#duplicateInstanceGetterPlusSetter;
+  set duplicateInstanceSetterPlusGetter = self::Extension|set#duplicateInstanceSetterPlusGetter;
+  set duplicateInstanceGetterAndSetter = self::Extension|set#duplicateInstanceGetterAndSetter;
+  static set duplicateStaticGetterPlusSetter = set self::Extension|duplicateStaticGetterPlusSetter;
+  static set duplicateStaticSetterPlusGetter = set self::Extension|duplicateStaticSetterPlusGetter;
+  static set duplicateStaticGetterAndSetter = set self::Extension|duplicateStaticGetterAndSetter;
+  static set instanceGetterAndStaticSetter = set self::Extension|instanceGetterAndStaticSetter;
+  set instanceSetterAndStaticGetter = self::Extension|set#instanceSetterAndStaticGetter;
+  set instanceSetterAndStaticField = self::Extension|set#instanceSetterAndStaticField;
+}
+static field core::int* Extension|duplicateStaticField;
+static method Extension|get#duplicateInstanceGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → void {}
+static method Extension|get#duplicateInstanceMethod<T extends core::Object* = dynamic>(final core::int* #this) → () →* void
+  return () → void => self::Extension|duplicateInstanceMethod<self::Extension|get#duplicateInstanceMethod::T*>(#this);
+static get Extension|duplicateStaticGetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticSetter(core::int* value) → void {}
+static method Extension|duplicateStaticMethod() → void {}
+static method Extension|get#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceGetterPlusSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceSetterPlusGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#duplicateInstanceGetterAndSetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static get Extension|duplicateStaticGetterPlusSetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticGetterPlusSetter(core::int* value) → void {}
+static get Extension|duplicateStaticSetterPlusGetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticSetterPlusGetter(core::int* value) → void {}
+static get Extension|duplicateStaticGetterAndSetter() → core::int*
+  return 0;
+static set Extension|duplicateStaticGetterAndSetter(core::int* value) → void {}
+static method Extension|get#instanceGetterAndStaticSetter<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static set Extension|instanceGetterAndStaticSetter(core::int* value) → void {}
+static get Extension|instanceSetterAndStaticGetter() → core::int*
+  return 0;
+static method Extension|set#instanceSetterAndStaticGetter<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method Extension|get#instanceGetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#instanceSetterAndStaticField<T extends core::Object* = dynamic>(final core::int* #this, core::int* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
new file mode 100644
index 0000000..6d262f3
--- /dev/null
+++ b/pkg/front_end/testcases/extensions/extension_member_conflict.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+extension Extension<T> (){}
+on int (){}
+main() {}
diff --git a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
index 98f08d2..245ead1 100644
--- a/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/extension_setter.dart.strong.transformed.expect
@@ -221,3 +221,107 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:47:30 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:47:30 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:51:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:51:32 -> IntConstant(2)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:56:24 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:58:34 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:58:34 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:60:12 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:60:35 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:60:35 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:60:35 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:65:25 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:67:35 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:67:35 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:69:12 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:69:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:69:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:69:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:86:30 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:86:30 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:89:41 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:89:41 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:93:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:93:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:97:43 -> IntConstant(6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:97:43 -> IntConstant(6)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:102:24 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:104:34 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:104:34 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:106:10 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:106:35 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:106:35 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:106:35 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:110:35 -> IntConstant(-6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:112:45 -> IntConstant(7)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:112:45 -> IntConstant(7)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:114:10 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:114:46 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:114:46 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:114:46 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:119:25 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:121:35 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:121:35 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:123:10 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:123:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:123:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:123:36 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:127:36 -> IntConstant(-6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:129:46 -> IntConstant(7)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:129:46 -> IntConstant(7)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:131:10 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:131:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:131:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:131:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:136:31 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:136:31 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:139:41 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:139:41 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:143:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:143:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:147:43 -> IntConstant(6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:147:43 -> IntConstant(6)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:152:25 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:154:35 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:154:35 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:156:10 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:156:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:156:36 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:156:36 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:160:35 -> IntConstant(-6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:162:45 -> IntConstant(7)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:162:45 -> IntConstant(7)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:164:10 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:164:46 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:164:46 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:164:46 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:169:26 -> IntConstant(-2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:171:36 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:171:36 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:173:10 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:173:37 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:173:37 -> IntConstant(-4)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:173:37 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:177:36 -> IntConstant(-6)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:179:46 -> IntConstant(7)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:179:46 -> IntConstant(7)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:181:10 -> IntConstant(-8)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///extension_setter.dart:181:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:181:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:181:47 -> IntConstant(-8)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:187:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:187:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:189:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:189:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:194:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:194:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:196:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:196:33 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:201:53 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///extension_setter.dart:201:53 -> IntConstant(1)
+Extra constant evaluation: evaluated: 836, effectively constant: 100
diff --git a/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect
index 4a04ad0..cd0b1b3 100644
--- a/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/if_null.dart.strong.transformed.expect
@@ -47,3 +47,13 @@
   let final core::int* #t21 = self::Extension|get#property(c) in #t21.{core::num::==}(null) ?{core::int*} 0 : #t21;
   let final core::int* #t22 = self::Extension|get#property(c) in #t22.{core::num::==}(null) ?{core::int*} 0 : #t22;
 }
+
+
+Extra constant evaluation status:
+Evaluated: Let @ org-dartlang-testcase:///if_null.dart:21:20 -> IntConstant(42)
+Evaluated: Let @ org-dartlang-testcase:///if_null.dart:22:31 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///if_null.dart:23:18 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///if_null.dart:23:18 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///if_null.dart:24:29 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///if_null.dart:24:29 -> IntConstant(42)
+Extra constant evaluation: evaluated: 122, effectively constant: 6
diff --git a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
index 67d8909..f406204 100644
--- a/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/index.dart.strong.transformed.expect
@@ -121,3 +121,85 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:31:20 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:31:25 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:31:25 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:33:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:33:8 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:35:20 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:35:20 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:35:27 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:35:27 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:37:8 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:37:8 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:39:20 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:39:20 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:39:27 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:39:27 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:43:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:43:23 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:43:23 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:44:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:44:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:45:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:45:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:46:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:46:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:48:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:44 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:60:49 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:62:32 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:62:32 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:64:44 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:64:44 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:64:51 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:64:51 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:66:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:66:32 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:44 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:44 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:68:51 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:72:44 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:73:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:73:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:74:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:74:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:75:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:75:39 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:77:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:31 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:89:36 -> StringConstant("2")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:91:19 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:91:19 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:93:31 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:93:31 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:93:38 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:93:38 -> StringConstant("4")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:95:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:95:19 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:31 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:31 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:97:38 -> StringConstant("3")
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:101:34 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:102:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:102:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:103:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:103:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:104:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:104:29 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///index.dart:106:31 -> IntConstant(0)
+Extra constant evaluation: evaluated: 579, effectively constant: 78
diff --git a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
index ca462d0..b117363 100644
--- a/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_access.dart.strong.transformed.expect
@@ -145,3 +145,23 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:79:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:79:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:81:28 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:81:28 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:82:42 -> IntConstant(27)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:82:42 -> IntConstant(27)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:83:42 -> IntConstant(37)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:83:42 -> IntConstant(37)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:84:56 -> IntConstant(77)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:84:56 -> IntConstant(77)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:85:56 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:85:56 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:100:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:100:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:103:28 -> IntConstant(43)
+Evaluated: VariableGet @ org-dartlang-testcase:///instance_access.dart:103:28 -> IntConstant(43)
+Extra constant evaluation: evaluated: 325, effectively constant: 16
diff --git a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
index 9508bad..aabacb2 100644
--- a/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/instance_tearoff.dart.strong.transformed.expect
@@ -117,3 +117,11 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///instance_tearoff.dart:54:19 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///instance_tearoff.dart:58:19 -> IntConstant(-7)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///instance_tearoff.dart:73:19 -> IntConstant(-4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///instance_tearoff.dart:77:19 -> IntConstant(-7)
+Extra constant evaluation: evaluated: 144, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
index dadb2db..d9024f1 100644
--- a/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/internal_resolution.dart.strong.transformed.expect
@@ -48,3 +48,11 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///internal_resolution.dart:23:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///internal_resolution.dart:23:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///internal_resolution.dart:25:28 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///internal_resolution.dart:25:28 -> IntConstant(87)
+Extra constant evaluation: evaluated: 49, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/issue38600.dart.outline.expect b/pkg/front_end/testcases/extensions/issue38600.dart.outline.expect
index ac62e8d..ed495ec 100644
--- a/pkg/front_end/testcases/extensions/issue38600.dart.outline.expect
+++ b/pkg/front_end/testcases/extensions/issue38600.dart.outline.expect
@@ -15,7 +15,8 @@
 // extension try<T> on Class<T> {}
 //           ^^^
 //
-// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: Expected an identifier, but got 'try'.
+// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: 'try' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // extension try<T> on Class<T> {}
 //           ^^^
 //
diff --git a/pkg/front_end/testcases/extensions/issue38600.dart.strong.expect b/pkg/front_end/testcases/extensions/issue38600.dart.strong.expect
index 7deee30..373bda2 100644
--- a/pkg/front_end/testcases/extensions/issue38600.dart.strong.expect
+++ b/pkg/front_end/testcases/extensions/issue38600.dart.strong.expect
@@ -15,7 +15,8 @@
 // extension try<T> on Class<T> {}
 //           ^^^
 //
-// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: Expected an identifier, but got 'try'.
+// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: 'try' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // extension try<T> on Class<T> {}
 //           ^^^
 //
diff --git a/pkg/front_end/testcases/extensions/issue38600.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue38600.dart.strong.transformed.expect
index 7deee30..373bda2 100644
--- a/pkg/front_end/testcases/extensions/issue38600.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/issue38600.dart.strong.transformed.expect
@@ -15,7 +15,8 @@
 // extension try<T> on Class<T> {}
 //           ^^^
 //
-// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: Expected an identifier, but got 'try'.
+// pkg/front_end/testcases/extensions/issue38600.dart:7:11: Error: 'try' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // extension try<T> on Class<T> {}
 //           ^^^
 //
diff --git a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
index 32a70a4..a4adb78 100644
--- a/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/issue39527.dart.strong.transformed.expect
@@ -37,3 +37,11 @@
   let final self::C* #t8 = c in let final core::int* #t9 = 42 in self::Extension1|[]=(#t8, #t9, self::Extension1|-(self::Extension1|[](#t8, #t9), 1));
   self::Extension1|[]=(c, 42, self::Extension1|-(self::Extension1|[](c, 42), 1));
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:19:19 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:19:19 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue39527.dart:22:17 -> IntConstant(42)
+Extra constant evaluation: evaluated: 56, effectively constant: 4
diff --git a/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
index 6609124..fd2532c 100644
--- a/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/null_aware.dart.strong.transformed.expect
@@ -85,3 +85,31 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:18:29 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:18:29 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:19:29 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:19:29 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:28:30 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:28:30 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:29:43 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:29:43 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:36:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:36:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:39:30 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:39:30 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:40:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:40:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:44:29 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:44:29 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:45:29 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:45:29 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:47:30 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:47:30 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:55:40 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:55:40 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:56:40 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_aware.dart:56:40 -> IntConstant(87)
+Extra constant evaluation: evaluated: 368, effectively constant: 24
diff --git a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
index aa753cc..6d78eba 100644
--- a/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/extensions/unnamed_extensions.dart.strong.transformed.expect
@@ -145,3 +145,23 @@
     throw "Mismatch: expected=${expected}, actual=${actual}";
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:79:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:79:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:81:28 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:81:28 -> IntConstant(87)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:82:42 -> IntConstant(27)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:82:42 -> IntConstant(27)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:83:42 -> IntConstant(37)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:83:42 -> IntConstant(37)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:84:56 -> IntConstant(77)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:84:56 -> IntConstant(77)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:85:56 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:85:56 -> IntConstant(67)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:100:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:100:28 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:103:28 -> IntConstant(43)
+Evaluated: VariableGet @ org-dartlang-testcase:///unnamed_extensions.dart:103:28 -> IntConstant(43)
+Extra constant evaluation: evaluated: 325, effectively constant: 16
diff --git a/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect b/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
index aa76a9c..61148bb 100644
--- a/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
+++ b/pkg/front_end/testcases/general/DeltaBlue.dart.outline.expect
@@ -262,3 +262,14 @@
   ;
 static method change(self::Variable* v, core::int* newValue) → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:88:24 -> InstanceConstant(const Strength{Strength.value: 0, Strength.name: "required"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:89:32 -> InstanceConstant(const Strength{Strength.value: 1, Strength.name: "strongPreferred"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:90:25 -> InstanceConstant(const Strength{Strength.value: 2, Strength.name: "preferred"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:91:30 -> InstanceConstant(const Strength{Strength.value: 3, Strength.name: "strongDefault"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:92:22 -> InstanceConstant(const Strength{Strength.value: 4, Strength.name: "normal"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:93:28 -> InstanceConstant(const Strength{Strength.value: 5, Strength.name: "weakDefault"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///DeltaBlue.dart:94:23 -> InstanceConstant(const Strength{Strength.value: 6, Strength.name: "weakest"})
+Extra constant evaluation: evaluated: 10, effectively constant: 7
diff --git a/pkg/front_end/testcases/general/abstract_members.dart.outline.expect b/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
index eeda548..c556119 100644
--- a/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
+++ b/pkg/front_end/testcases/general/abstract_members.dart.outline.expect
@@ -372,3 +372,35 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:10:8 -> SymbolConstant(#interfaceMethod2)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:10:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:10:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:10:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:21:3 -> SymbolConstant(#abstractMethod)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:21:3 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:21:3 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:21:3 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:6:8 -> SymbolConstant(#interfaceMethod1)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:6:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:6:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:6:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:16:8 -> SymbolConstant(#interfaceMethod3)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:16:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:16:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:16:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:24:12 -> SymbolConstant(#property3=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:24:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:24:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:12:7 -> SymbolConstant(#interfaceMethod1=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:12:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:12:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:22:12 -> SymbolConstant(#property1=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:22:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:22:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_members.dart:23:12 -> SymbolConstant(#property2=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_members.dart:23:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_members.dart:23:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 73, effectively constant: 28
diff --git a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
index fa0fc05..54ce84a 100644
--- a/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
+++ b/pkg/front_end/testcases/general/abstract_overrides_concrete_with_no_such_method.dart.outline.expect
@@ -46,3 +46,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_overrides_concrete_with_no_such_method.dart:10:5 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_overrides_concrete_with_no_such_method.dart:10:5 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_overrides_concrete_with_no_such_method.dart:10:5 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_overrides_concrete_with_no_such_method.dart:10:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
index aaea247..f8b77c2 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.outline.expect
@@ -31,7 +31,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -45,3 +45,13 @@
 static const field core::int* hest = 42;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///annotation_on_enum_values.dart:15:6 -> ListConstant(const <Foo*>[const Foo{Foo.index: 0, Foo._name: "Foo.bar"}, const Foo{Foo.index: 1, Foo._name: "Foo.baz"}, const Foo{Foo.index: 2, Foo._name: "Foo.cafebabe"}])
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_on_enum_values.dart:16:4 -> IntConstant(42)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_on_enum_values.dart:17:3 -> InstanceConstant(const Foo{Foo.index: 0, Foo._name: "Foo.bar"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_on_enum_values.dart:18:4 -> InstanceConstant(const Fisk<int*>{Fisk.x: 42})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_on_enum_values.dart:19:3 -> InstanceConstant(const Foo{Foo.index: 1, Foo._name: "Foo.baz"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_on_enum_values.dart:20:3 -> InstanceConstant(const Foo{Foo.index: 2, Foo._name: "Foo.cafebabe"})
+Extra constant evaluation: evaluated: 11, effectively constant: 6
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
index 60d3c9e..742c6ea 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.expect
@@ -31,7 +31,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
index 60d3c9e..742c6ea 100644
--- a/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/annotation_on_enum_values.dart.strong.transformed.expect
@@ -31,7 +31,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general/annotation_top.dart.outline.expect b/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
index b213fc1..a3676d1 100644
--- a/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/general/annotation_top.dart.outline.expect
@@ -48,3 +48,18 @@
 @self::A::•(4)
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_top.dart:5:2 -> InstanceConstant(const Object{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:6:2 -> InstanceConstant(const A{})
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_top.dart:15:2 -> InstanceConstant(const Object{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:16:2 -> InstanceConstant(const A{})
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_top.dart:31:2 -> InstanceConstant(const Object{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:32:2 -> InstanceConstant(const A{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:9:24 -> InstanceConstant(const Object{})
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_top.dart:27:2 -> InstanceConstant(const Object{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:28:2 -> InstanceConstant(const A{})
+Evaluated: StaticGet @ org-dartlang-testcase:///annotation_top.dart:27:2 -> InstanceConstant(const Object{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///annotation_top.dart:28:2 -> InstanceConstant(const A{})
+Extra constant evaluation: evaluated: 11, effectively constant: 11
diff --git a/pkg/front_end/testcases/general/bug33099.dart.outline.expect b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
index fb764b2..22c739f 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.outline.expect
@@ -63,3 +63,9 @@
   ;
 static method _hasAnnotationInstance(mir::DeclarationMirror* declaration, dynamic instance) → core::bool*
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///bug33099.dart:14:4 -> InstanceConstant(const _FailingTest{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///bug33099.dart:7:40 -> InstanceConstant(const _FailingTest{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
index e7f6876..2f10dab 100644
--- a/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/bug33099.dart.strong.transformed.expect
@@ -84,3 +84,7 @@
   #C1 = self::_FailingTest {}
   #C2 = #foo
 }
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///bug33099.dart:21:42 -> TypeLiteralConstant(MyTest2*)
+Extra constant evaluation: evaluated: 33, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/casts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/casts.dart.strong.transformed.expect
index 4ea32aa..59f300e 100644
--- a/pkg/front_end/testcases/general/casts.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/casts.dart.strong.transformed.expect
@@ -16,3 +16,16 @@
   core::print(1.0 is core::int*);
   core::print(1.0 is core::double*);
 }
+
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:10:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:11:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:12:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:14:11 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:15:11 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:16:11 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:18:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:19:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:20:13 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 21, effectively constant: 9
diff --git a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
index 992e106..fdd58da 100644
--- a/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/check_deferred_read_type.dart.strong.transformed.expect
@@ -35,3 +35,8 @@
 static field core::int* x = 0;
 static method m(dynamic x) → dynamic
   return null;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///check_deferred_read_type.dart:9:13 -> TypeLiteralConstant(C*)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
index 9fd7126..def0418 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.outline.expect
@@ -3,26 +3,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm1<Z> = Object with Am1<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm2<Z> = Object with Am2<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // typedef TdF = Function({int});
 //                            ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Ef1<X extends Function({int})> {
 //                                  ^
 //
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
index 9b9542f..a8b62fb 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.expect
@@ -3,26 +3,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm1<Z> = Object with Am1<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm2<Z> = Object with Am2<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // typedef TdF = Function({int});
 //                            ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Ef1<X extends Function({int})> {
 //                                  ^
 //
diff --git a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
index 67d2466..7935b39 100644
--- a/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/clone_function_type.dart.strong.transformed.expect
@@ -3,26 +3,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:22:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:46:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm1<Z> = Object with Am1<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:77:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:105:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm2<Z> = Object with Am2<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:134:28: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // typedef TdF = Function({int});
 //                            ^
 //
 // pkg/front_end/testcases/general/clone_function_type.dart:190:34: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Ef1<X extends Function({int})> {
 //                                  ^
 //
diff --git a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect
index c425212..2c3a4c0 100644
--- a/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/compound_binary_implicit_as.dart.strong.transformed.expect
@@ -38,3 +38,9 @@
   on dynamic catch(final dynamic _) {
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///compound_binary_implicit_as.dart:16:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///compound_binary_implicit_as.dart:16:9 -> IntConstant(0)
+Extra constant evaluation: evaluated: 16, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect b/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect
index 579ea4a..0dde286 100644
--- a/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.outline.expect
@@ -46,3 +46,53 @@
   ;
 static method throws(() →* core::num* f) → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:7:12 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:8:19 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:9:19 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:10:19 -> DoubleConstant(-Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:14:12 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:15:19 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:16:19 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:17:19 -> DoubleConstant(-Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:19:17 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:20:19 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:21:12 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:21:20 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:22:19 -> DoubleConstant(NaN)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:22:26 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:23:19 -> DoubleConstant(Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:23:31 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:24:19 -> DoubleConstant(-Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:24:39 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:26:24 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:27:26 -> DoubleConstant(NaN)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:28:12 -> DoubleConstant(-0.0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:28:27 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:29:19 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:29:33 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:30:19 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:30:38 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:31:19 -> DoubleConstant(-Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:31:46 -> DoubleConstant(NaN)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:33:14 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:34:16 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:35:17 -> IntConstant(0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:36:19 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:36:33 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:37:19 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:37:38 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:38:19 -> DoubleConstant(-Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:38:46 -> DoubleConstant(Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:40:14 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:41:16 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:42:17 -> IntConstant(0)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:43:19 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:43:33 -> DoubleConstant(-Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:44:19 -> DoubleConstant(Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:44:38 -> DoubleConstant(-Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:45:19 -> DoubleConstant(-Infinity)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_truncate.dart:45:46 -> DoubleConstant(-Infinity)
+Extra constant evaluation: evaluated: 76, effectively constant: 46
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect b/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect
index 5e6673e..c07b061 100644
--- a/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.strong.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general/constant_truncate.dart:5:14: Error: Constant evaluation error:
 // const a0 = 0 ~/ 0; // error
@@ -301,7 +302,6 @@
 // const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
 //       ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/constant_truncate.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constant_truncate.dart.strong.transformed.expect
index 5e6673e..dc0d52e 100644
--- a/pkg/front_end/testcases/general/constant_truncate.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/constant_truncate.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general/constant_truncate.dart:5:14: Error: Constant evaluation error:
 // const a0 = 0 ~/ 0; // error
@@ -301,7 +302,6 @@
 // const f5 = double.negativeInfinity ~/ double.negativeInfinity; // error
 //       ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 
@@ -413,3 +413,18 @@
   #C3 = Infinity
   #C4 = -Infinity
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:50:8 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:57:8 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:62:11 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:63:13 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:64:8 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:64:14 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:65:20 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:66:25 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:67:33 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:71:8 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:78:8 -> DoubleConstant(-0.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///constant_truncate.dart:85:8 -> DoubleConstant(-0.0)
+Extra constant evaluation: evaluated: 115, effectively constant: 12
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart b/pkg/front_end/testcases/general/constants/circularity.dart
new file mode 100644
index 0000000..4406335
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const int a = b;
+const int b = a;
+const int c = d;
+const int d = e + 1;
+const int e = d - 1;
+
+class Class1 {
+  const Class1({Class1 c = const Class1(c: null)});
+}
+
+const Class1 c1_0 = const Class1();
+const Class1 c1_1 = const Class1(c: null);
+const Class1 c1_2 = const Class1();
+
+class Class2 {
+  final Class2 field;
+  const Class2(int value) : field = value == 0 ? null : const Class2(0);
+}
+
+const Class2 c2_0 = const Class2(1);
+const Class2 c2_1 = const Class2(0);
+const Class2 c2_2 = const Class2(1);
+
+class Class3 {
+  const Class3([Class3 c = c3_1]);
+}
+
+const Class3 c3_0 = const Class3();
+const Class3 c3_1 = const Class3(c3_2);
+const Class3 c3_2 = const Class3(null);
+
+class Class4 {
+  const Class4({Class4 c = const Class4()});
+}
+
+const Class4 c4_0 = const Class4();
+const Class4 c4_1 = const Class4(c: null);
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.outline.expect b/pkg/front_end/testcases/general/constants/circularity.dart.outline.expect
new file mode 100644
index 0000000..d30b1c7
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.outline.expect
@@ -0,0 +1,98 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class1* c = const self::Class1::•(c: null)}) → self::Class1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class2 extends core::Object /*hasConstConstructor*/  {
+  final field self::Class2* field;
+  const constructor •(core::int* value) → self::Class2*
+    : self::Class2::field = value.{core::num::==}(0) ?{self::Class2*} null : const self::Class2::•(0), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class3 extends core::Object /*hasConstConstructor*/  {
+  const constructor •([self::Class3* c = self::c3_1]) → self::Class3*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class4* c = const self::Class4::•()}) → self::Class4*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* a = self::b;
+static const field core::int* b = self::a;
+static const field core::int* c = self::d;
+static const field core::int* d = self::e.{core::num::+}(1);
+static const field core::int* e = self::d.{core::num::-}(1);
+static const field self::Class1* c1_0 = const self::Class1::•();
+static const field self::Class1* c1_1 = const self::Class1::•(c: null);
+static const field self::Class1* c1_2 = const self::Class1::•();
+static const field self::Class2* c2_0 = const self::Class2::•(1);
+static const field self::Class2* c2_1 = const self::Class2::•(0);
+static const field self::Class2* c2_2 = const self::Class2::•(1);
+static const field self::Class3* c3_0 = const self::Class3::•();
+static const field self::Class3* c3_1 = const self::Class3::•(self::c3_2);
+static const field self::Class3* c3_2 = const self::Class3::•(null);
+static const field self::Class4* c4_0 = const self::Class4::•();
+static const field self::Class4* c4_1 = const self::Class4::•(c: null);
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:12:34 -> InstanceConstant(const Class1{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:21:63 -> InstanceConstant(const Class2{Class2.field: null})
+Evaluated: StaticGet @ org-dartlang-testcase:///circularity.dart:29:28 -> InstanceConstant(const Class3{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:15:27 -> InstanceConstant(const Class1{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:16:27 -> InstanceConstant(const Class1{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:17:27 -> InstanceConstant(const Class1{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:25:27 -> InstanceConstant(const Class2{Class2.field: null})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:32:27 -> InstanceConstant(const Class3{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:33:27 -> InstanceConstant(const Class3{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:34:27 -> InstanceConstant(const Class3{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///circularity.dart:41:27 -> InstanceConstant(const Class4{})
+Extra constant evaluation: evaluated: 25, effectively constant: 11
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect b/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect
new file mode 100644
index 0000000..ad07bf9
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.strong.expect
@@ -0,0 +1,134 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:37:34: Error: Constant evaluation error:
+//   const Class4({Class4 c = const Class4()});
+//                                  ^
+// pkg/front_end/testcases/general/constants/circularity.dart:37:34: Context: Constant expression depends on itself.
+//   const Class4({Class4 c = const Class4()});
+//                                  ^
+// pkg/front_end/testcases/general/constants/circularity.dart:37:24: Context: While analyzing:
+//   const Class4({Class4 c = const Class4()});
+//                        ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:5:15: Error: Constant evaluation error:
+// const int a = b;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:5:15: Context: Constant expression depends on itself.
+// const int a = b;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:5:11: Context: While analyzing:
+// const int a = b;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:7:15: Error: Constant evaluation error:
+// const int c = d;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Context: Constant expression depends on itself.
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:7:11: Context: While analyzing:
+// const int c = d;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Error: Constant evaluation error:
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Context: Constant expression depends on itself.
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:11: Context: While analyzing:
+// const int d = e + 1;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class1* c = #C1}) → self::Class1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class2 extends core::Object /*hasConstConstructor*/  {
+  final field self::Class2* field;
+  const constructor •(core::int* value) → self::Class2*
+    : self::Class2::field = value.{core::num::==}(0) ?{self::Class2*} null : #C3, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class3 extends core::Object /*hasConstConstructor*/  {
+  const constructor •([self::Class3* c = #C4]) → self::Class3*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class4* c = invalid-expression "Constant expression depends on itself."}) → self::Class4*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* a = invalid-expression "Constant expression depends on itself.";
+static const field core::int* b = invalid-expression "Constant expression depends on itself.";
+static const field core::int* c = invalid-expression "Constant expression depends on itself.";
+static const field core::int* d = invalid-expression "Constant expression depends on itself.";
+static const field core::int* e = invalid-expression "Constant expression depends on itself.";
+static const field self::Class1* c1_0 = #C1;
+static const field self::Class1* c1_1 = #C1;
+static const field self::Class1* c1_2 = #C1;
+static const field self::Class2* c2_0 = #C5;
+static const field self::Class2* c2_1 = #C3;
+static const field self::Class2* c2_2 = #C5;
+static const field self::Class3* c3_0 = #C4;
+static const field self::Class3* c3_1 = #C4;
+static const field self::Class3* c3_2 = #C4;
+static const field self::Class4* c4_0 = invalid-expression "Constant expression depends on itself.";
+static const field self::Class4* c4_1 = #C6;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::Class1 {}
+  #C2 = null
+  #C3 = self::Class2 {field:#C2}
+  #C4 = self::Class3 {}
+  #C5 = self::Class2 {field:#C3}
+  #C6 = self::Class4 {}
+}
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect
new file mode 100644
index 0000000..ad07bf9
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.strong.transformed.expect
@@ -0,0 +1,134 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:37:34: Error: Constant evaluation error:
+//   const Class4({Class4 c = const Class4()});
+//                                  ^
+// pkg/front_end/testcases/general/constants/circularity.dart:37:34: Context: Constant expression depends on itself.
+//   const Class4({Class4 c = const Class4()});
+//                                  ^
+// pkg/front_end/testcases/general/constants/circularity.dart:37:24: Context: While analyzing:
+//   const Class4({Class4 c = const Class4()});
+//                        ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:5:15: Error: Constant evaluation error:
+// const int a = b;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:5:15: Context: Constant expression depends on itself.
+// const int a = b;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:5:11: Context: While analyzing:
+// const int a = b;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:7:15: Error: Constant evaluation error:
+// const int c = d;
+//               ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Context: Constant expression depends on itself.
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:7:11: Context: While analyzing:
+// const int c = d;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Error: Constant evaluation error:
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:17: Context: Constant expression depends on itself.
+// const int d = e + 1;
+//                 ^
+// pkg/front_end/testcases/general/constants/circularity.dart:8:11: Context: While analyzing:
+// const int d = e + 1;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Class1 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class1* c = #C1}) → self::Class1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class2 extends core::Object /*hasConstConstructor*/  {
+  final field self::Class2* field;
+  const constructor •(core::int* value) → self::Class2*
+    : self::Class2::field = value.{core::num::==}(0) ?{self::Class2*} null : #C3, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class3 extends core::Object /*hasConstConstructor*/  {
+  const constructor •([self::Class3* c = #C4]) → self::Class3*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Class4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({self::Class4* c = invalid-expression "Constant expression depends on itself."}) → self::Class4*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* a = invalid-expression "Constant expression depends on itself.";
+static const field core::int* b = invalid-expression "Constant expression depends on itself.";
+static const field core::int* c = invalid-expression "Constant expression depends on itself.";
+static const field core::int* d = invalid-expression "Constant expression depends on itself.";
+static const field core::int* e = invalid-expression "Constant expression depends on itself.";
+static const field self::Class1* c1_0 = #C1;
+static const field self::Class1* c1_1 = #C1;
+static const field self::Class1* c1_2 = #C1;
+static const field self::Class2* c2_0 = #C5;
+static const field self::Class2* c2_1 = #C3;
+static const field self::Class2* c2_2 = #C5;
+static const field self::Class3* c3_0 = #C4;
+static const field self::Class3* c3_1 = #C4;
+static const field self::Class3* c3_2 = #C4;
+static const field self::Class4* c4_0 = invalid-expression "Constant expression depends on itself.";
+static const field self::Class4* c4_1 = #C6;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = self::Class1 {}
+  #C2 = null
+  #C3 = self::Class2 {field:#C2}
+  #C4 = self::Class3 {}
+  #C5 = self::Class2 {field:#C3}
+  #C6 = self::Class4 {}
+}
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline.expect
new file mode 100644
index 0000000..4c1285d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline.expect
@@ -0,0 +1,38 @@
+const int a = b;
+const int b = a;
+const int c = d;
+const int d = e + 1;
+const int e = d - 1;
+
+class Class1 {
+  const Class1({Class1 c = const Class1(c: null)});
+}
+
+const Class1 c1_0 = const Class1();
+const Class1 c1_1 = const Class1(c: null);
+const Class1 c1_2 = const Class1();
+
+class Class2 {
+  final Class2 field;
+  const Class2(int value) : field = value == 0 ? null : const Class2(0);
+}
+
+const Class2 c2_0 = const Class2(1);
+const Class2 c2_1 = const Class2(0);
+const Class2 c2_2 = const Class2(1);
+
+class Class3 {
+  const Class3([Class3 c = c3_1]);
+}
+
+const Class3 c3_0 = const Class3();
+const Class3 c3_1 = const Class3(c3_2);
+const Class3 c3_2 = const Class3(null);
+
+class Class4 {
+  const Class4({Class4 c = const Class4()});
+}
+
+const Class4 c4_0 = const Class4();
+const Class4 c4_1 = const Class4(c: null);
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fec5c97
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/circularity.dart.textual_outline_modelled.expect
@@ -0,0 +1,34 @@
+class Class1 {
+  const Class1({Class1 c = const Class1(c: null)});
+}
+
+class Class2 {
+  const Class2(int value) : field = value == 0 ? null : const Class2(0);
+  final Class2 field;
+}
+
+class Class3 {
+  const Class3([Class3 c = c3_1]);
+}
+
+class Class4 {
+  const Class4({Class4 c = const Class4()});
+}
+
+const Class1 c1_0 = const Class1();
+const Class1 c1_1 = const Class1(c: null);
+const Class1 c1_2 = const Class1();
+const Class2 c2_0 = const Class2(1);
+const Class2 c2_1 = const Class2(0);
+const Class2 c2_2 = const Class2(1);
+const Class3 c3_0 = const Class3();
+const Class3 c3_1 = const Class3(c3_2);
+const Class3 c3_2 = const Class3(null);
+const Class4 c4_0 = const Class4();
+const Class4 c4_1 = const Class4(c: null);
+const int a = b;
+const int b = a;
+const int c = d;
+const int d = e + 1;
+const int e = d - 1;
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart b/pkg/front_end/testcases/general/constants/const_asserts.dart
new file mode 100644
index 0000000..ddb02c6
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  final int x;
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(x > 0, ""),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+  const Foo.withNullConditionFromEnv1(this.x)
+      : assert(bool.fromEnvironment("foo", defaultValue: null));
+  const Foo.withNullConditionFromEnv2(this.x)
+      : assert(const bool.fromEnvironment("foo", defaultValue: null));
+}
+
+class Bar {
+  final int x;
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+  const Bar.withEmptyMessage(this.x) : assert(x < 0);
+}
+
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+const Bar bar5 = const Bar.withEmptyMessage(1);
+const Bar bar6 = const Bar.withEmptyMessage(0);
+
+main() {
+  print(foo1);
+}
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.outline.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.outline.expect
new file mode 100644
index 0000000..2eaf487
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.outline.expect
@@ -0,0 +1,97 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:19:21: Error: Constant expression expected.
+// Try inserting 'const'.
+//       : assert(bool.fromEnvironment("foo", defaultValue: null));
+//                     ^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert(x.{core::num::>}(0), ""), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false), "foo was ${const core::bool::fromEnvironment("foo")}"), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${const core::bool::fromEnvironment("foo")}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError} core::bool*), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv1(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(const core::bool::fromEnvironment("foo", defaultValue: null)), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv2(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(const core::bool::fromEnvironment("foo", defaultValue: null)), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor withMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  const constructor withEmptyMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field self::Foo* foo1 = const self::Foo::•(1);
+static const field self::Foo* foo2 = const self::Foo::•(0);
+static const field self::Foo* foo3 = const self::Foo::withMessage(42);
+static const field self::Foo* foo4 = const self::Foo::withInvalidMessage(42);
+static const field self::Foo* foo5 = const self::Foo::withInvalidCondition(42);
+static const field self::Foo* foo6 = const self::Foo::withNullConditionFromEnv1(42);
+static const field self::Foo* foo7 = const self::Foo::withNullConditionFromEnv2(42);
+static const field self::Bar* bar1 = const self::Bar::withMessage(1);
+static const field self::Bar* bar2 = const self::Bar::withMessage(0);
+static const field self::Bar* bar3 = const self::Bar::withoutMessage(1);
+static const field self::Bar* bar4 = const self::Bar::withoutMessage(0);
+static const field self::Bar* bar5 = const self::Bar::withEmptyMessage(1);
+static const field self::Bar* bar6 = const self::Bar::withEmptyMessage(0);
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:11:50 -> BoolConstant(true)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:12:59 -> StringConstant("foo was false")
+Evaluated: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:13:50 -> BoolConstant(true)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:15:73 -> StringConstant("btw foo was false")
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:19:21 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:21:22 -> NullConstant(null)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_asserts.dart:31:24 -> InstanceConstant(const Foo{Foo.x: 1})
+Extra constant evaluation: evaluated: 48, effectively constant: 7
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect
new file mode 100644
index 0000000..2f17318
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.expect
@@ -0,0 +1,206 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:19:21: Error: Constant expression expected.
+// Try inserting 'const'.
+//       : assert(bool.fromEnvironment("foo", defaultValue: null));
+//                     ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:32:24: Error: Constant evaluation error:
+// const Foo foo2 = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:8:18: Context: This assertion failed with message: x is not positive
+//       : assert(x > 0, "x is not positive"),
+//                  ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:32:11: Context: While analyzing:
+// const Foo foo2 = const Foo(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:33:24: Error: Constant evaluation error:
+// const Foo foo3 = const Foo.withMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:15:18: Context: This assertion failed with message: btw foo was false
+//       : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+//                  ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:33:11: Context: While analyzing:
+// const Foo foo3 = const Foo.withMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:34:24: Error: Constant evaluation error:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+//   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+//                                                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:34:11: Context: While analyzing:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:36:24: Error: Constant evaluation error:
+// const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:19:21: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+//       : assert(bool.fromEnvironment("foo", defaultValue: null));
+//                     ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:36:11: Context: While analyzing:
+// const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:37:24: Error: Constant evaluation error:
+// const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:21:22: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+//       : assert(const bool.fromEnvironment("foo", defaultValue: null));
+//                      ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:37:11: Context: While analyzing:
+// const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:38:24: Error: Constant evaluation error:
+// const Bar bar1 = const Bar.withMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:26:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:38:11: Context: While analyzing:
+// const Bar bar1 = const Bar.withMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:39:24: Error: Constant evaluation error:
+// const Bar bar2 = const Bar.withMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:26:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:39:11: Context: While analyzing:
+// const Bar bar2 = const Bar.withMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:40:24: Error: Constant evaluation error:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:27:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:40:11: Context: While analyzing:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:41:24: Error: Constant evaluation error:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:27:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:41:11: Context: While analyzing:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:42:24: Error: Constant evaluation error:
+// const Bar bar5 = const Bar.withEmptyMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:28:49: Context: This assertion failed.
+//   const Bar.withEmptyMessage(this.x) : assert(x < 0);
+//                                                 ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:42:11: Context: While analyzing:
+// const Bar bar5 = const Bar.withEmptyMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:43:24: Error: Constant evaluation error:
+// const Bar bar6 = const Bar.withEmptyMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:28:49: Context: This assertion failed.
+//   const Bar.withEmptyMessage(this.x) : assert(x < 0);
+//                                                 ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:43:11: Context: While analyzing:
+// const Bar bar6 = const Bar.withEmptyMessage(0);
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert(x.{core::num::>}(0), ""), assert((#C1).{core::Object::==}(false), "foo was ${#C1}"), assert((#C1).{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C1}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError} core::bool*), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv1(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(#C2), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv2(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(#C2), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor withMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  const constructor withEmptyMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field self::Foo* foo1 = #C4;
+static const field self::Foo* foo2 = invalid-expression "This assertion failed with message: x is not positive";
+static const field self::Foo* foo3 = invalid-expression "This assertion failed with message: btw foo was false";
+static const field self::Foo* foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo* foo5 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^";
+static const field self::Foo* foo6 = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field self::Foo* foo7 = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field self::Bar* bar1 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar* bar2 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar* bar3 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar4 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar5 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar6 = invalid-expression "This assertion failed.";
+static method main() → dynamic {
+  core::print(#C4);
+}
+
+constants  {
+  #C1 = false
+  #C2 = null
+  #C3 = 1
+  #C4 = self::Foo {x:#C3}
+}
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect
new file mode 100644
index 0000000..5302b40
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.strong.transformed.expect
@@ -0,0 +1,213 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:19:21: Error: Constant expression expected.
+// Try inserting 'const'.
+//       : assert(bool.fromEnvironment("foo", defaultValue: null));
+//                     ^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:32:24: Error: Constant evaluation error:
+// const Foo foo2 = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:8:18: Context: This assertion failed with message: x is not positive
+//       : assert(x > 0, "x is not positive"),
+//                  ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:32:11: Context: While analyzing:
+// const Foo foo2 = const Foo(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:33:24: Error: Constant evaluation error:
+// const Foo foo3 = const Foo.withMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:15:18: Context: This assertion failed with message: btw foo was false
+//       : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+//                  ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:33:11: Context: While analyzing:
+// const Foo foo3 = const Foo.withMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:34:24: Error: Constant evaluation error:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:16:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+//   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+//                                                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:34:11: Context: While analyzing:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:36:24: Error: Constant evaluation error:
+// const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:19:21: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+//       : assert(bool.fromEnvironment("foo", defaultValue: null));
+//                     ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:36:11: Context: While analyzing:
+// const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:37:24: Error: Constant evaluation error:
+// const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:21:22: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+//       : assert(const bool.fromEnvironment("foo", defaultValue: null));
+//                      ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:37:11: Context: While analyzing:
+// const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:38:24: Error: Constant evaluation error:
+// const Bar bar1 = const Bar.withMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:26:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:38:11: Context: While analyzing:
+// const Bar bar1 = const Bar.withMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:39:24: Error: Constant evaluation error:
+// const Bar bar2 = const Bar.withMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:26:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:39:11: Context: While analyzing:
+// const Bar bar2 = const Bar.withMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:40:24: Error: Constant evaluation error:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:27:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:40:11: Context: While analyzing:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:41:24: Error: Constant evaluation error:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:27:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:41:11: Context: While analyzing:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:42:24: Error: Constant evaluation error:
+// const Bar bar5 = const Bar.withEmptyMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:28:49: Context: This assertion failed.
+//   const Bar.withEmptyMessage(this.x) : assert(x < 0);
+//                                                 ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:42:11: Context: While analyzing:
+// const Bar bar5 = const Bar.withEmptyMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/const_asserts.dart:43:24: Error: Constant evaluation error:
+// const Bar bar6 = const Bar.withEmptyMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:28:49: Context: This assertion failed.
+//   const Bar.withEmptyMessage(this.x) : assert(x < 0);
+//                                                 ^
+// pkg/front_end/testcases/general/constants/const_asserts.dart:43:11: Context: While analyzing:
+// const Bar bar6 = const Bar.withEmptyMessage(0);
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert(x.{core::num::>}(0), ""), assert((#C1).{core::Object::==}(false), "foo was ${#C1}"), assert((#C1).{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C1}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError} core::bool*), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv1(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(#C2), super core::Object::•()
+    ;
+  const constructor withNullConditionFromEnv2(core::int* x) → self::Foo*
+    : self::Foo::x = x, assert(#C2), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  const constructor withMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  const constructor withEmptyMessage(core::int* x) → self::Bar*
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field self::Foo* foo1 = #C4;
+static const field self::Foo* foo2 = invalid-expression "This assertion failed with message: x is not positive";
+static const field self::Foo* foo3 = invalid-expression "This assertion failed with message: btw foo was false";
+static const field self::Foo* foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo* foo5 = invalid-expression "pkg/front_end/testcases/general/constants/const_asserts.dart:17:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^";
+static const field self::Foo* foo6 = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field self::Foo* foo7 = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field self::Bar* bar1 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar* bar2 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar* bar3 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar4 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar5 = invalid-expression "This assertion failed.";
+static const field self::Bar* bar6 = invalid-expression "This assertion failed.";
+static method main() → dynamic {
+  core::print(#C4);
+}
+
+constants  {
+  #C1 = false
+  #C2 = null
+  #C3 = 1
+  #C4 = self::Foo {x:#C3}
+}
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:11:50 -> BoolConstant(true)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:12:59 -> StringConstant("foo was false")
+Evaluated: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:13:50 -> BoolConstant(true)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:15:73 -> StringConstant("btw foo was false")
+Extra constant evaluation: evaluated: 34, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline.expect
new file mode 100644
index 0000000..35c0fd4
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline.expect
@@ -0,0 +1,40 @@
+class Foo {
+  final int x;
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(x > 0, ""),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+  const Foo.withNullConditionFromEnv1(this.x)
+      : assert(bool.fromEnvironment("foo", defaultValue: null));
+  const Foo.withNullConditionFromEnv2(this.x)
+      : assert(const bool.fromEnvironment("foo", defaultValue: null));
+}
+
+class Bar {
+  final int x;
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+  const Bar.withEmptyMessage(this.x) : assert(x < 0);
+}
+
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+const Bar bar5 = const Bar.withEmptyMessage(1);
+const Bar bar6 = const Bar.withEmptyMessage(0);
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..951c20d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_asserts.dart.textual_outline_modelled.expect
@@ -0,0 +1,40 @@
+class Bar {
+  const Bar.withEmptyMessage(this.x) : assert(x < 0);
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+  final int x;
+}
+
+class Foo {
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(x > 0, ""),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  const Foo.withNullConditionFromEnv1(this.x)
+      : assert(bool.fromEnvironment("foo", defaultValue: null));
+  const Foo.withNullConditionFromEnv2(this.x)
+      : assert(const bool.fromEnvironment("foo", defaultValue: null));
+  final int x;
+}
+
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+const Bar bar5 = const Bar.withEmptyMessage(1);
+const Bar bar6 = const Bar.withEmptyMessage(0);
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+const Foo foo6 = const Foo.withNullConditionFromEnv1(42);
+const Foo foo7 = const Foo.withNullConditionFromEnv2(42);
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart b/pkg/front_end/testcases/general/constants/const_collections.dart
new file mode 100644
index 0000000..90a8445
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart
@@ -0,0 +1,161 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+class ConstIterable extends IterableBase<int> {
+  const ConstIterable();
+
+  Iterator<int> get iterator => <int>[].iterator;
+}
+
+const int fortyTwo = 42;
+const dynamic fortyTwoAsDynamic = ((fortyTwo as dynamic) * 2) ~/ 2;
+
+const List<String> nullList = null;
+const List<String> foo = ["hello", "world"];
+List<String> get fooAsGetter => const ["hello", "world"];
+const List<String> bar = [...foo, "!"];
+var barAsVar = [...foo, "!"];
+List<String> get barAsGetter => const [...foo, "!"];
+const List<String> barWithNullSpread = [...foo, ...nullList];
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+const List<String> barWithMapSpread = [...foo, ...quux];
+const List<String> barWithCustomIterableSpread1 = [
+  ...bar,
+  ...const CustomIterable()
+];
+const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+const customIterable = const CustomIterable();
+const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+const List<String> listConcat = ["Hello"] + ["World"];
+
+const Set<String> nullSet = null;
+const Set<String> baz = {"hello", "world"};
+Set<String> get bazAsGetter => const {"hello", "world"};
+const Set<String> qux = {...baz, "!"};
+Set<String> get quxAsGetter => const {...baz, "!"};
+const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+const Set<String> quxWithCustomIterableSpread1 = {
+  ...baz,
+  ...const CustomIterable()
+};
+const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+const Set<dynamic> setWithDuplicates = {42, 42};
+
+const Map<String, String> nullMap = null;
+const Map<String, String> quux = {"hello": "world"};
+Map<String, String> get quuxAsGetter => const {"hello": "world"};
+const Map<String, String> quuz = {...quux, "!": "bye!"};
+Map<String, String> get quuzAsGetter => const {...quux, "!": "bye!"};
+const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+const Map<String, String> mapWithSetSpread = {...baz};
+const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+const Map<String, String> customMap = const CustomMap();
+const Map<String, String> mapWithCustomMap3 = {...customMap};
+const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+  const WithEquals(42): 42
+};
+const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+
+class WithEquals {
+  final int i;
+  const WithEquals(this.i);
+  operator ==(Object o) {
+    return o is WithEquals && (o as WithEquals).i == i;
+  }
+}
+
+class CustomIterable extends IterableBase<String> {
+  const CustomIterable();
+  Iterator<String> get iterator => <String>[].iterator;
+}
+
+class CustomMap implements Map<String, String> {
+  const CustomMap();
+
+  @override
+  Iterable<MapEntry<String, String>> get entries => [];
+
+  @override
+  String operator [](Object key) => throw new UnimplementedError();
+
+  @override
+  void operator []=(String key, String value) => throw new UnimplementedError();
+
+  @override
+  Map<RK, RV> cast<RK, RV>() => throw new UnimplementedError();
+
+  @override
+  void clear() => throw new UnimplementedError();
+
+  @override
+  bool containsKey(Object key) => throw new UnimplementedError();
+
+  @override
+  bool containsValue(Object value) => throw new UnimplementedError();
+
+  @override
+  bool get isEmpty => throw new UnimplementedError();
+
+  @override
+  bool get isNotEmpty => throw new UnimplementedError();
+
+  @override
+  Iterable<String> get keys => throw new UnimplementedError();
+
+  @override
+  int get length => throw new UnimplementedError();
+
+  @override
+  String remove(Object key) => throw new UnimplementedError();
+
+  @override
+  Iterable<String> get values => throw new UnimplementedError();
+
+  @override
+  void addAll(Map<String, String> other) => throw new UnimplementedError();
+
+  @override
+  void addEntries(Iterable<MapEntry<String, String>> newEntries) =>
+      throw new UnimplementedError();
+
+  @override
+  void forEach(void f(String key, String value)) =>
+      throw new UnimplementedError();
+
+  @override
+  String putIfAbsent(String key, String ifAbsent()) =>
+      throw new UnimplementedError();
+
+  @override
+  void updateAll(String update(String key, String value)) =>
+      throw new UnimplementedError();
+
+  @override
+  void removeWhere(bool predicate(String key, String value)) =>
+      throw new UnimplementedError();
+
+  String update(String key, String update(String value), {String ifAbsent()}) =>
+      throw new UnimplementedError();
+
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(String key, String value)) =>
+      throw new UnimplementedError();
+}
+
+main() {
+  print(bar);
+  print(qux);
+  print(quuz);
+  print({"hello"});
+  print(const {"hello"});
+}
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.outline.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.outline.expect
new file mode 100644
index 0000000..04597c0
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.outline.expect
@@ -0,0 +1,361 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+// const List<String> barWithMapSpread = [...foo, ...quux];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Set<String> quxWithMapSpread = {...baz, ...quux};
+//                                      ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+//  - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+// const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+//                                                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+//                                                            ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+//                                               ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> mapWithSetSpread = {...baz};
+//                                              ^
+//
+import self as self;
+import "dart:collection" as col;
+import "dart:core" as core;
+
+import "dart:collection";
+
+class ConstIterable extends col::IterableBase<core::int*> /*hasConstConstructor*/  {
+  const constructor •() → self::ConstIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::int*>*
+    ;
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::int*>* other) → core::Iterable<core::int*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::int*) →* self::ConstIterable::map::T* f) → core::Iterable<self::ConstIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::int*) →* core::Iterable<self::ConstIterable::expand::T*>* f) → core::Iterable<self::ConstIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::int*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::int*, core::int*) →* core::int* combine) → core::int*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::ConstIterable::fold::T* initialValue, (self::ConstIterable::fold::T*, core::int*) →* self::ConstIterable::fold::T* combine) → self::ConstIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable}) → core::List<core::int*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::int*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse}) → core::int*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse}) → core::int*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse}) → core::int*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::int*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class WithEquals extends core::Object /*hasConstConstructor*/  {
+  final field core::int* i;
+  const constructor •(core::int* i) → self::WithEquals*
+    : self::WithEquals::i = i, super core::Object::•()
+    ;
+  operator ==(core::Object* o) → core::bool*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomIterable extends col::IterableBase<core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::String*>*
+    ;
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::String*>* other) → core::Iterable<core::String*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::String*) →* self::CustomIterable::map::T* f) → core::Iterable<self::CustomIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::String*) →* core::Iterable<self::CustomIterable::expand::T*>* f) → core::Iterable<self::CustomIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::String*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::String*, core::String*) →* core::String* combine) → core::String*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::CustomIterable::fold::T* initialValue, (self::CustomIterable::fold::T*, core::String*) →* self::CustomIterable::fold::T* combine) → self::CustomIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable}) → core::List<core::String*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::String*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse}) → core::String*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse}) → core::String*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse}) → core::String*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::String*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomMap extends core::Object implements core::Map<core::String*, core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomMap*
+    : super core::Object::•()
+    ;
+  @core::override
+  get entries() → core::Iterable<core::MapEntry<core::String*, core::String*>*>*
+    ;
+  @core::override
+  operator [](core::Object* key) → core::String*
+    ;
+  @core::override
+  operator []=(generic-covariant-impl core::String* key, generic-covariant-impl core::String* value) → void
+    ;
+  @core::override
+  method cast<RK extends core::Object* = dynamic, RV extends core::Object* = dynamic>() → core::Map<self::CustomMap::cast::RK*, self::CustomMap::cast::RV*>*
+    ;
+  @core::override
+  method clear() → void
+    ;
+  @core::override
+  method containsKey(core::Object* key) → core::bool*
+    ;
+  @core::override
+  method containsValue(core::Object* value) → core::bool*
+    ;
+  @core::override
+  get isEmpty() → core::bool*
+    ;
+  @core::override
+  get isNotEmpty() → core::bool*
+    ;
+  @core::override
+  get keys() → core::Iterable<core::String*>*
+    ;
+  @core::override
+  get length() → core::int*
+    ;
+  @core::override
+  method remove(core::Object* key) → core::String*
+    ;
+  @core::override
+  get values() → core::Iterable<core::String*>*
+    ;
+  @core::override
+  method addAll(generic-covariant-impl core::Map<core::String*, core::String*>* other) → void
+    ;
+  @core::override
+  method addEntries(generic-covariant-impl core::Iterable<core::MapEntry<core::String*, core::String*>*>* newEntries) → void
+    ;
+  @core::override
+  method forEach((core::String*, core::String*) →* void f) → void
+    ;
+  @core::override
+  method putIfAbsent(generic-covariant-impl core::String* key, generic-covariant-impl () →* core::String* ifAbsent) → core::String*
+    ;
+  @core::override
+  method updateAll(generic-covariant-impl (core::String*, core::String*) →* core::String* update) → void
+    ;
+  @core::override
+  method removeWhere((core::String*, core::String*) →* core::bool* predicate) → void
+    ;
+  method update(generic-covariant-impl core::String* key, generic-covariant-impl (core::String*) →* core::String* update, {generic-covariant-impl () →* core::String* ifAbsent}) → core::String*
+    ;
+  method map<K2 extends core::Object* = dynamic, V2 extends core::Object* = dynamic>((core::String*, core::String*) →* core::MapEntry<self::CustomMap::map::K2*, self::CustomMap::map::V2*>* f) → core::Map<self::CustomMap::map::K2*, self::CustomMap::map::V2*>*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* fortyTwo = 42;
+static const field dynamic fortyTwoAsDynamic = (self::fortyTwo as dynamic).*(2).~/(2);
+static const field core::List<core::String*>* nullList = null;
+static const field core::List<core::String*>* foo = const <core::String*>["hello", "world"];
+static const field core::List<core::String*>* bar = self::foo + const <core::String*>["!"];
+static field core::List<core::String*>* barAsVar;
+static const field core::List<core::String*>* barWithNullSpread = self::foo + self::nullList;
+static const field core::List<core::String*>* barWithIntSpread = self::foo + const <core::String*>[invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+                                                  ^"];
+static const field core::List<core::String*>* barWithIntDynamicSpread = self::foo + self::fortyTwoAsDynamic as{TypeError,ForDynamic} core::Iterable<dynamic>*;
+static const field core::List<core::String*>* barWithMapSpread = self::foo + const <core::String*>[invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+const List<String> barWithMapSpread = [...foo, ...quux];
+                                                  ^"];
+static const field core::List<core::String*>* barWithCustomIterableSpread1 = self::bar + const self::CustomIterable::•();
+static const field core::List<core::String*>* barWithCustomIterableSpread2 = self::bar + const self::CustomIterable::•();
+static const field self::CustomIterable* customIterable = const self::CustomIterable::•();
+static const field core::List<core::String*>* barWithCustomIterableSpread3 = self::bar + self::customIterable;
+static const field core::List<core::String*>* listConcat = const <core::String*>["Hello"].{core::List::+}(const <core::String*>["World"]);
+static const field core::Set<core::String*>* nullSet = null;
+static const field core::Set<core::String*>* baz = const <core::String*>{"hello", "world"};
+static const field core::Set<core::String*>* qux = self::baz + const <core::String*>{"!"};
+static const field core::Set<core::String*>* quxWithNullSpread = self::baz + self::nullSet;
+static const field core::Set<core::String*>* quxWithIntSpread = self::baz + const <core::String*>{invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+                                                 ^"};
+static const field core::Set<core::String*>* quxWithMapSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+                                     ^";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread1 = self::baz + const self::CustomIterable::•();
+static const field core::Set<core::String*>* quxWithCustomIterableSpread2 = self::baz + const self::CustomIterable::•();
+static const field core::Set<core::String*>* quxWithCustomIterableSpread3 = self::baz + const <core::String*>{let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+ - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+                                                          ^" in self::customIterable as{TypeError} core::String*};
+static const field core::Set<dynamic>* setWithNonPrimitiveEquals = const <dynamic>{const self::WithEquals::•(42)};
+static const field core::Set<dynamic>* setWithDuplicates = const <dynamic>{42, 42};
+static const field core::Map<core::String*, core::String*>* nullMap = null;
+static const field core::Map<core::String*, core::String*>* quux = const <core::String*, core::String*>{"hello": "world"};
+static const field core::Map<core::String*, core::String*>* quuz = self::quux + const <core::String*, core::String*>{"!": "bye!"};
+static const field core::Map<core::String*, core::String*>* quuzWithNullSpread = self::quux + self::nullMap;
+static const field core::Map<core::String*, core::String*>* quuzWithIntSpread = self::quux + const <core::String*, core::String*>{invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+                                                           ^": null};
+static const field core::Map<core::String*, core::String*>* quuzWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+                                              ^";
+static const field core::Map<core::String*, core::String*>* mapWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> mapWithSetSpread = {...baz};
+                                             ^";
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap1 = const self::CustomMap::•();
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap2 = const self::CustomMap::•();
+static const field core::Map<core::String*, core::String*>* customMap = const self::CustomMap::•();
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap3 = self::customMap;
+static const field core::Map<dynamic, core::int*>* mapWithNonPrimitiveEqualsKey = const <dynamic, core::int*>{const self::WithEquals::•(42): 42};
+static const field core::Map<core::int*, core::int*>* mapWithDuplicates = const <core::int*, core::int*>{42: 42, 42: 42};
+static get fooAsGetter() → core::List<core::String*>*
+  ;
+static get barAsGetter() → core::List<core::String*>*
+  ;
+static get bazAsGetter() → core::Set<core::String*>*
+  ;
+static get quxAsGetter() → core::Set<core::String*>*
+  ;
+static get quuxAsGetter() → core::Map<core::String*, core::String*>*
+  ;
+static get quuzAsGetter() → core::Map<core::String*, core::String*>*
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:86:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:89:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:92:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:95:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:98:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:101:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:104:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:107:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:110:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:113:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:116:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:119:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:122:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:125:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:128:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:132:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:136:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:140:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:144:4 -> InstanceConstant(const _Override{})
+Evaluated: MethodInvocation @ org-dartlang-testcase:///const_collections.dart:14:63 -> IntConstant(42)
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:17:26 -> ListConstant(const <String*>["hello", "world"])
+Evaluated: ListConcatenation @ org-dartlang-testcase:///const_collections.dart:19:26 -> ListConstant(const <String*>["hello", "world", "!"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:22:44 -> ListConstant(const <String*>["hello", "world"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:22:52 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:23:43 -> ListConstant(const <String*>["hello", "world"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:24:50 -> ListConstant(const <String*>["hello", "world"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:24:58 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:25:43 -> ListConstant(const <String*>["hello", "world"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:27:6 -> ListConstant(const <String*>["hello", "world", "!"])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:28:12 -> InstanceConstant(const CustomIterable{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:30:55 -> ListConstant(const <String*>["hello", "world", "!"])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:30:63 -> InstanceConstant(const CustomIterable{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:31:30 -> InstanceConstant(const CustomIterable{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:32:55 -> ListConstant(const <String*>["hello", "world", "!"])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:32:63 -> InstanceConstant(const CustomIterable{})
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:33:33 -> ListConstant(const <String*>["Hello"])
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:33:45 -> ListConstant(const <String*>["World"])
+Evaluated: SetLiteral @ org-dartlang-testcase:///const_collections.dart:36:25 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: SetConcatenation @ org-dartlang-testcase:///const_collections.dart:38:25 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null, "!", null]}})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:40:43 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:40:51 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:41:42 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:44:6 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:45:12 -> InstanceConstant(const CustomIterable{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:47:54 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:47:62 -> InstanceConstant(const CustomIterable{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:48:54 -> InstanceConstant(const _UnmodifiableSet<String*>{_UnmodifiableSet._map: const _ImmutableMap<String*, Null?>{_ImmutableMap._kvPairs: const <dynamic>["hello", null, "world", null]}})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:48:59 -> InstanceConstant(const CustomIterable{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:49:55 -> InstanceConstant(const WithEquals{WithEquals.i: 42})
+Evaluated: MapLiteral @ org-dartlang-testcase:///const_collections.dart:53:34 -> InstanceConstant(const _ImmutableMap<String*, String*>{_ImmutableMap._kvPairs: const <dynamic>["hello", "world"]})
+Evaluated: MapConcatenation @ org-dartlang-testcase:///const_collections.dart:55:27 -> InstanceConstant(const _ImmutableMap<String*, String*>{_ImmutableMap._kvPairs: const <dynamic>["hello", "world", "!", "bye!"]})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:57:52 -> InstanceConstant(const _ImmutableMap<String*, String*>{_ImmutableMap._kvPairs: const <dynamic>["hello", "world"]})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:57:61 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:58:51 -> InstanceConstant(const _ImmutableMap<String*, String*>{_ImmutableMap._kvPairs: const <dynamic>["hello", "world"]})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:61:57 -> InstanceConstant(const CustomMap{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:62:51 -> InstanceConstant(const CustomMap{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:63:45 -> InstanceConstant(const CustomMap{})
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:64:51 -> InstanceConstant(const CustomMap{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///const_collections.dart:66:9 -> InstanceConstant(const WithEquals{WithEquals.i: 42})
+Extra constant evaluation: evaluated: 90, effectively constant: 59
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect
new file mode 100644
index 0000000..e193519
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.expect
@@ -0,0 +1,514 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+// const List<String> barWithMapSpread = [...foo, ...quux];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Set<String> quxWithMapSpread = {...baz, ...quux};
+//                                      ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+//  - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+// const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+//                                                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+//                                                            ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+//                                               ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> mapWithSetSpread = {...baz};
+//                                              ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:40: Error: Constant evaluation error:
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:52: Context: Null value during constant evaluation.
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                                                    ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:20: Context: While analyzing:
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:46: Error: Constant evaluation error:
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                                              ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:58: Context: Expected constant '42' to be of type 'Iterable<dynamic>', but was of type 'int'.
+//  - 'Iterable' is from 'dart:core'.
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                                                          ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:20: Context: While analyzing:
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:26:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread1 = [
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:28:12: Context: Only lists and sets can be used in spreads in constant lists and sets.
+//   ...const CustomIterable()
+//            ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:26:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread1 = [
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:63: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                                                               ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:63: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                                                               ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:43: Error: Constant evaluation error:
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:43: Context: The method '+' can't be invoked on '<String>["Hello"]' in a constant expression.
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:20: Context: While analyzing:
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:39: Error: Constant evaluation error:
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                                       ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:51: Context: Null value during constant evaluation.
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:19: Context: While analyzing:
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:43:50: Error: Constant evaluation error:
+// const Set<String> quxWithCustomIterableSpread1 = {
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:45:12: Context: Only lists and sets can be used in spreads in constant lists and sets.
+//   ...const CustomIterable()
+//            ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:43:19: Context: While analyzing:
+// const Set<String> quxWithCustomIterableSpread1 = {
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:50: Error: Constant evaluation error:
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:62: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                                                              ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:19: Context: While analyzing:
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:48: Error: Constant evaluation error:
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                                                ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:55: Context: The element 'WithEquals {i: 42}' does not have a primitive operator '=='.
+//  - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                                                       ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:20: Context: While analyzing:
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:40: Error: Constant evaluation error:
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:45: Context: The element '42' conflicts with another existing element in the set.
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                                             ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:20: Context: While analyzing:
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:27: Error: Constant evaluation error:
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:61: Context: Null value during constant evaluation.
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                                                             ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:27: Context: While analyzing:
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:57: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                                                         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:51: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:51: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:65:56: Error: Constant evaluation error:
+// const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+//                                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:66:9: Context: The key 'WithEquals {i: 42}' does not have a primitive operator '=='.
+//  - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+//   const WithEquals(42): 42
+//         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:65:25: Context: While analyzing:
+// const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+//                         ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:41: Error: Constant evaluation error:
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                                         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:50: Context: The key '42' conflicts with another existing key in the map.
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:21: Context: While analyzing:
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                     ^
+//
+import self as self;
+import "dart:collection" as col;
+import "dart:core" as core;
+
+import "dart:collection";
+
+class ConstIterable extends col::IterableBase<core::int*> /*hasConstConstructor*/  {
+  const constructor •() → self::ConstIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::int*>*
+    return <core::int*>[].{core::Iterable::iterator};
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::int*>* other) → core::Iterable<core::int*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::int*) →* self::ConstIterable::map::T* f) → core::Iterable<self::ConstIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::int*) →* core::Iterable<self::ConstIterable::expand::T*>* f) → core::Iterable<self::ConstIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::int*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::int*, core::int*) →* core::int* combine) → core::int*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::ConstIterable::fold::T* initialValue, (self::ConstIterable::fold::T*, core::int*) →* self::ConstIterable::fold::T* combine) → self::ConstIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator = #C1]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable = #C2}) → core::List<core::int*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::int*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::int*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class WithEquals extends core::Object /*hasConstConstructor*/  {
+  final field core::int* i;
+  const constructor •(core::int* i) → self::WithEquals*
+    : self::WithEquals::i = i, super core::Object::•()
+    ;
+  operator ==(core::Object* o) → core::bool* {
+    return o is self::WithEquals* && (o{self::WithEquals*} as self::WithEquals*).{self::WithEquals::i}.{core::num::==}(this.{self::WithEquals::i});
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomIterable extends col::IterableBase<core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::String*>*
+    return <core::String*>[].{core::Iterable::iterator};
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::String*>* other) → core::Iterable<core::String*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::String*) →* self::CustomIterable::map::T* f) → core::Iterable<self::CustomIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::String*) →* core::Iterable<self::CustomIterable::expand::T*>* f) → core::Iterable<self::CustomIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::String*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::String*, core::String*) →* core::String* combine) → core::String*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::CustomIterable::fold::T* initialValue, (self::CustomIterable::fold::T*, core::String*) →* self::CustomIterable::fold::T* combine) → self::CustomIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator = #C1]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable = #C2}) → core::List<core::String*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::String*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::String*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomMap extends core::Object implements core::Map<core::String*, core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomMap*
+    : super core::Object::•()
+    ;
+  @#C4
+  get entries() → core::Iterable<core::MapEntry<core::String*, core::String*>*>*
+    return <core::MapEntry<core::String*, core::String*>*>[];
+  @#C4
+  operator [](core::Object* key) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  operator []=(generic-covariant-impl core::String* key, generic-covariant-impl core::String* value) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method cast<RK extends core::Object* = dynamic, RV extends core::Object* = dynamic>() → core::Map<self::CustomMap::cast::RK*, self::CustomMap::cast::RV*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method clear() → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method containsKey(core::Object* key) → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method containsValue(core::Object* value) → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get isEmpty() → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get isNotEmpty() → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get keys() → core::Iterable<core::String*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get length() → core::int*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method remove(core::Object* key) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get values() → core::Iterable<core::String*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method addAll(generic-covariant-impl core::Map<core::String*, core::String*>* other) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method addEntries(generic-covariant-impl core::Iterable<core::MapEntry<core::String*, core::String*>*>* newEntries) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method forEach((core::String*, core::String*) →* void f) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method putIfAbsent(generic-covariant-impl core::String* key, generic-covariant-impl () →* core::String* ifAbsent) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method updateAll(generic-covariant-impl (core::String*, core::String*) →* core::String* update) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method removeWhere((core::String*, core::String*) →* core::bool* predicate) → void
+    return throw new core::UnimplementedError::•();
+  method update(generic-covariant-impl core::String* key, generic-covariant-impl (core::String*) →* core::String* update, {generic-covariant-impl () →* core::String* ifAbsent = #C3}) → core::String*
+    return throw new core::UnimplementedError::•();
+  method map<K2 extends core::Object* = dynamic, V2 extends core::Object* = dynamic>((core::String*, core::String*) →* core::MapEntry<self::CustomMap::map::K2*, self::CustomMap::map::V2*>* f) → core::Map<self::CustomMap::map::K2*, self::CustomMap::map::V2*>*
+    return throw new core::UnimplementedError::•();
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* fortyTwo = #C5;
+static const field dynamic fortyTwoAsDynamic = #C5;
+static const field core::List<core::String*>* nullList = #C3;
+static const field core::List<core::String*>* foo = #C8;
+static const field core::List<core::String*>* bar = #C10;
+static field core::List<core::String*>* barAsVar = block {
+  final core::List<core::String*>* #t1 = <core::String*>[];
+  for (final core::String* #t2 in #C8)
+    #t1.{core::List::add}(#t2);
+  #t1.{core::List::add}("!");
+} =>#t1;
+static const field core::List<core::String*>* barWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::List<core::String*>* barWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+                                                  ^";
+static const field core::List<core::String*>* barWithIntDynamicSpread = invalid-expression "Expected constant '42' to be of type 'Iterable<dynamic>', but was of type 'int'.
+ - 'Iterable' is from 'dart:core'.";
+static const field core::List<core::String*>* barWithMapSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+const List<String> barWithMapSpread = [...foo, ...quux];
+                                                  ^";
+static const field core::List<core::String*>* barWithCustomIterableSpread1 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::List<core::String*>* barWithCustomIterableSpread2 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field self::CustomIterable* customIterable = #C11;
+static const field core::List<core::String*>* barWithCustomIterableSpread3 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::List<core::String*>* listConcat = invalid-expression "The method '+' can't be invoked on '<String>[\"Hello\"]' in a constant expression.";
+static const field core::Set<core::String*>* nullSet = #C3;
+static const field core::Set<core::String*>* baz = #C14;
+static const field core::Set<core::String*>* qux = #C17;
+static const field core::Set<core::String*>* quxWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::Set<core::String*>* quxWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+                                                 ^";
+static const field core::Set<core::String*>* quxWithMapSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+                                     ^";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread1 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread2 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread3 = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+ - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+                                                          ^";
+static const field core::Set<dynamic>* setWithNonPrimitiveEquals = invalid-expression "The element 'WithEquals {i: 42}' does not have a primitive operator '=='.
+ - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.";
+static const field core::Set<dynamic>* setWithDuplicates = invalid-expression "The element '42' conflicts with another existing element in the set.";
+static const field core::Map<core::String*, core::String*>* nullMap = #C3;
+static const field core::Map<core::String*, core::String*>* quux = #C19;
+static const field core::Map<core::String*, core::String*>* quuz = #C22;
+static const field core::Map<core::String*, core::String*>* quuzWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::Map<core::String*, core::String*>* quuzWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+                                                           ^";
+static const field core::Map<core::String*, core::String*>* quuzWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+                                              ^";
+static const field core::Map<core::String*, core::String*>* mapWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> mapWithSetSpread = {...baz};
+                                             ^";
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap1 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap2 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<core::String*, core::String*>* customMap = #C23;
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap3 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<dynamic, core::int*>* mapWithNonPrimitiveEqualsKey = invalid-expression "The key 'WithEquals {i: 42}' does not have a primitive operator '=='.
+ - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.";
+static const field core::Map<core::int*, core::int*>* mapWithDuplicates = invalid-expression "The key '42' conflicts with another existing key in the map.";
+static get fooAsGetter() → core::List<core::String*>*
+  return #C8;
+static get barAsGetter() → core::List<core::String*>*
+  return #C10;
+static get bazAsGetter() → core::Set<core::String*>*
+  return #C14;
+static get quxAsGetter() → core::Set<core::String*>*
+  return #C17;
+static get quuxAsGetter() → core::Map<core::String*, core::String*>*
+  return #C19;
+static get quuzAsGetter() → core::Map<core::String*, core::String*>*
+  return #C22;
+static method main() → dynamic {
+  core::print(#C10);
+  core::print(#C17);
+  core::print(#C22);
+  core::print(let final core::Set<core::String*>* #t3 = col::LinkedHashSet::•<core::String*>() in let final dynamic #t4 = #t3.{core::Set::add}("hello") in #t3);
+  core::print(#C26);
+}
+
+constants  {
+  #C1 = ""
+  #C2 = true
+  #C3 = null
+  #C4 = core::_Override {}
+  #C5 = 42
+  #C6 = "hello"
+  #C7 = "world"
+  #C8 = <core::String*>[#C6, #C7]
+  #C9 = "!"
+  #C10 = <core::String*>[#C6, #C7, #C9]
+  #C11 = self::CustomIterable {}
+  #C12 = <dynamic>[#C6, #C3, #C7, #C3]
+  #C13 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C12}
+  #C14 = col::_UnmodifiableSet<core::String*> {_map:#C13}
+  #C15 = <dynamic>[#C6, #C3, #C7, #C3, #C9, #C3]
+  #C16 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C15}
+  #C17 = col::_UnmodifiableSet<core::String*> {_map:#C16}
+  #C18 = <dynamic>[#C6, #C7]
+  #C19 = core::_ImmutableMap<core::String*, core::String*> {_kvPairs:#C18}
+  #C20 = "bye!"
+  #C21 = <dynamic>[#C6, #C7, #C9, #C20]
+  #C22 = core::_ImmutableMap<core::String*, core::String*> {_kvPairs:#C21}
+  #C23 = self::CustomMap {}
+  #C24 = <dynamic>[#C6, #C3]
+  #C25 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C24}
+  #C26 = col::_UnmodifiableSet<core::String*> {_map:#C25}
+}
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect
new file mode 100644
index 0000000..23d8ad3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.strong.transformed.expect
@@ -0,0 +1,519 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+// const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+// const List<String> barWithMapSpread = [...foo, ...quux];
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+// const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+//                                                  ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Set<String> quxWithMapSpread = {...baz, ...quux};
+//                                      ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+//  - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+// const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+//                                                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+// const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+//                                                            ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+//                                               ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+// const Map<String, String> mapWithSetSpread = {...baz};
+//                                              ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:40: Error: Constant evaluation error:
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:52: Context: Null value during constant evaluation.
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                                                    ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:22:20: Context: While analyzing:
+// const List<String> barWithNullSpread = [...foo, ...nullList];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:46: Error: Constant evaluation error:
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                                              ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:58: Context: Expected constant '42' to be of type 'Iterable<dynamic>', but was of type 'int'.
+//  - 'Iterable' is from 'dart:core'.
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                                                          ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:24:20: Context: While analyzing:
+// const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:26:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread1 = [
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:28:12: Context: Only lists and sets can be used in spreads in constant lists and sets.
+//   ...const CustomIterable()
+//            ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:26:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread1 = [
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:63: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                                                               ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:30:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:51: Error: Constant evaluation error:
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:63: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                                                               ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:32:20: Context: While analyzing:
+// const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:43: Error: Constant evaluation error:
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:43: Context: The method '+' can't be invoked on '<String>["Hello"]' in a constant expression.
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:33:20: Context: While analyzing:
+// const List<String> listConcat = ["Hello"] + ["World"];
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:39: Error: Constant evaluation error:
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                                       ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:51: Context: Null value during constant evaluation.
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:40:19: Context: While analyzing:
+// const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:43:50: Error: Constant evaluation error:
+// const Set<String> quxWithCustomIterableSpread1 = {
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:45:12: Context: Only lists and sets can be used in spreads in constant lists and sets.
+//   ...const CustomIterable()
+//            ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:43:19: Context: While analyzing:
+// const Set<String> quxWithCustomIterableSpread1 = {
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:50: Error: Constant evaluation error:
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:62: Context: Only lists and sets can be used in spreads in constant lists and sets.
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                                                              ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:47:19: Context: While analyzing:
+// const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+//                   ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:48: Error: Constant evaluation error:
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                                                ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:55: Context: The element 'WithEquals {i: 42}' does not have a primitive operator '=='.
+//  - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                                                       ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:49:20: Context: While analyzing:
+// const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:40: Error: Constant evaluation error:
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:45: Context: The element '42' conflicts with another existing element in the set.
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                                             ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:50:20: Context: While analyzing:
+// const Set<dynamic> setWithDuplicates = {42, 42};
+//                    ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:27: Error: Constant evaluation error:
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:61: Context: Null value during constant evaluation.
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                                                             ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:57:27: Context: While analyzing:
+// const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:57: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                                                         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:61:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:51: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:62:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:27: Error: Constant evaluation error:
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                           ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:51: Context: Only maps can be used in spreads in constant maps.
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                                                   ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:64:27: Context: While analyzing:
+// const Map<String, String> mapWithCustomMap3 = {...customMap};
+//                           ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:65:56: Error: Constant evaluation error:
+// const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+//                                                        ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:66:9: Context: The key 'WithEquals {i: 42}' does not have a primitive operator '=='.
+//  - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+//   const WithEquals(42): 42
+//         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:65:25: Context: While analyzing:
+// const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+//                         ^
+//
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:41: Error: Constant evaluation error:
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                                         ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:50: Context: The key '42' conflicts with another existing key in the map.
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                                                  ^
+// pkg/front_end/testcases/general/constants/const_collections.dart:68:21: Context: While analyzing:
+// const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+//                     ^
+//
+import self as self;
+import "dart:collection" as col;
+import "dart:core" as core;
+
+import "dart:collection";
+
+class ConstIterable extends col::IterableBase<core::int*> /*hasConstConstructor*/  {
+  const constructor •() → self::ConstIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::int*>*
+    return <core::int*>[].{core::Iterable::iterator};
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::int*>* other) → core::Iterable<core::int*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::int*) →* self::ConstIterable::map::T* f) → core::Iterable<self::ConstIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::ConstIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::int*) →* core::Iterable<self::ConstIterable::expand::T*>* f) → core::Iterable<self::ConstIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::int*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::int*, core::int*) →* core::int* combine) → core::int*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::ConstIterable::fold::T* initialValue, (self::ConstIterable::fold::T*, core::int*) →* self::ConstIterable::fold::T* combine) → self::ConstIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator = #C1]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::int*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable = #C2}) → core::List<core::int*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::int*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::int*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::int*) →* core::bool* test) → core::Iterable<core::int*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::int*) →* core::bool* test, {generic-covariant-impl () →* core::int* orElse = #C3}) → core::int*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::int*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class WithEquals extends core::Object /*hasConstConstructor*/  {
+  final field core::int* i;
+  const constructor •(core::int* i) → self::WithEquals*
+    : self::WithEquals::i = i, super core::Object::•()
+    ;
+  operator ==(core::Object* o) → core::bool* {
+    return o is self::WithEquals* && o{self::WithEquals*}.{self::WithEquals::i}.{core::num::==}(this.{self::WithEquals::i});
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomIterable extends col::IterableBase<core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomIterable*
+    : super col::IterableBase::•()
+    ;
+  get iterator() → core::Iterator<core::String*>*
+    return <core::String*>[].{core::Iterable::iterator};
+  abstract member-signature method cast<R extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::cast::R*>*; -> core::Iterable::cast
+  abstract member-signature method followedBy(generic-covariant-impl core::Iterable<core::String*>* other) → core::Iterable<core::String*>*; -> core::Iterable::followedBy
+  abstract member-signature method map<T extends core::Object* = dynamic>((core::String*) →* self::CustomIterable::map::T* f) → core::Iterable<self::CustomIterable::map::T*>*; -> core::Iterable::map
+  abstract member-signature method where((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::where
+  abstract member-signature method whereType<T extends core::Object* = dynamic>() → core::Iterable<self::CustomIterable::whereType::T*>*; -> core::Iterable::whereType
+  abstract member-signature method expand<T extends core::Object* = dynamic>((core::String*) →* core::Iterable<self::CustomIterable::expand::T*>* f) → core::Iterable<self::CustomIterable::expand::T*>*; -> core::Iterable::expand
+  abstract member-signature method contains(core::Object* element) → core::bool*; -> core::Iterable::contains
+  abstract member-signature method forEach((core::String*) →* void f) → void; -> core::Iterable::forEach
+  abstract member-signature method reduce(generic-covariant-impl (core::String*, core::String*) →* core::String* combine) → core::String*; -> core::Iterable::reduce
+  abstract member-signature method fold<T extends core::Object* = dynamic>(self::CustomIterable::fold::T* initialValue, (self::CustomIterable::fold::T*, core::String*) →* self::CustomIterable::fold::T* combine) → self::CustomIterable::fold::T*; -> core::Iterable::fold
+  abstract member-signature method every((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::every
+  abstract member-signature method join([core::String* separator = #C1]) → core::String*; -> core::Iterable::join
+  abstract member-signature method any((core::String*) →* core::bool* test) → core::bool*; -> core::Iterable::any
+  abstract member-signature method toList({core::bool* growable = #C2}) → core::List<core::String*>*; -> core::Iterable::toList
+  abstract member-signature method toSet() → core::Set<core::String*>*; -> core::Iterable::toSet
+  abstract member-signature get length() → core::int*; -> core::Iterable::length
+  abstract member-signature get isEmpty() → core::bool*; -> core::Iterable::isEmpty
+  abstract member-signature get isNotEmpty() → core::bool*; -> core::Iterable::isNotEmpty
+  abstract member-signature method take(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::take
+  abstract member-signature method takeWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::takeWhile
+  abstract member-signature method skip(core::int* count) → core::Iterable<core::String*>*; -> core::Iterable::skip
+  abstract member-signature method skipWhile((core::String*) →* core::bool* test) → core::Iterable<core::String*>*; -> core::Iterable::skipWhile
+  abstract member-signature method firstWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::firstWhere
+  abstract member-signature method lastWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::lastWhere
+  abstract member-signature method singleWhere((core::String*) →* core::bool* test, {generic-covariant-impl () →* core::String* orElse = #C3}) → core::String*; -> core::Iterable::singleWhere
+  abstract member-signature method elementAt(core::int* index) → core::String*; -> core::Iterable::elementAt
+  abstract member-signature method toString() → core::String*; -> core::Iterable::toString
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class CustomMap extends core::Object implements core::Map<core::String*, core::String*> /*hasConstConstructor*/  {
+  const constructor •() → self::CustomMap*
+    : super core::Object::•()
+    ;
+  @#C4
+  get entries() → core::Iterable<core::MapEntry<core::String*, core::String*>*>*
+    return <core::MapEntry<core::String*, core::String*>*>[];
+  @#C4
+  operator [](core::Object* key) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  operator []=(generic-covariant-impl core::String* key, generic-covariant-impl core::String* value) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method cast<RK extends core::Object* = dynamic, RV extends core::Object* = dynamic>() → core::Map<self::CustomMap::cast::RK*, self::CustomMap::cast::RV*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method clear() → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method containsKey(core::Object* key) → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method containsValue(core::Object* value) → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get isEmpty() → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get isNotEmpty() → core::bool*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get keys() → core::Iterable<core::String*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get length() → core::int*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method remove(core::Object* key) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  get values() → core::Iterable<core::String*>*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method addAll(generic-covariant-impl core::Map<core::String*, core::String*>* other) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method addEntries(generic-covariant-impl core::Iterable<core::MapEntry<core::String*, core::String*>*>* newEntries) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method forEach((core::String*, core::String*) →* void f) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method putIfAbsent(generic-covariant-impl core::String* key, generic-covariant-impl () →* core::String* ifAbsent) → core::String*
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method updateAll(generic-covariant-impl (core::String*, core::String*) →* core::String* update) → void
+    return throw new core::UnimplementedError::•();
+  @#C4
+  method removeWhere((core::String*, core::String*) →* core::bool* predicate) → void
+    return throw new core::UnimplementedError::•();
+  method update(generic-covariant-impl core::String* key, generic-covariant-impl (core::String*) →* core::String* update, {generic-covariant-impl () →* core::String* ifAbsent = #C3}) → core::String*
+    return throw new core::UnimplementedError::•();
+  method map<K2 extends core::Object* = dynamic, V2 extends core::Object* = dynamic>((core::String*, core::String*) →* core::MapEntry<self::CustomMap::map::K2*, self::CustomMap::map::V2*>* f) → core::Map<self::CustomMap::map::K2*, self::CustomMap::map::V2*>*
+    return throw new core::UnimplementedError::•();
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::int* fortyTwo = #C5;
+static const field dynamic fortyTwoAsDynamic = #C5;
+static const field core::List<core::String*>* nullList = #C3;
+static const field core::List<core::String*>* foo = #C8;
+static const field core::List<core::String*>* bar = #C10;
+static field core::List<core::String*>* barAsVar = block {
+  final core::List<core::String*>* #t1 = <core::String*>[];
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = (#C8).{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final core::String* #t2 = :sync-for-iterator.{core::Iterator::current};
+      #t1.{core::List::add}(#t2);
+    }
+  }
+  #t1.{core::List::add}("!");
+} =>#t1;
+static const field core::List<core::String*>* barWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::List<core::String*>* barWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:23:51: Error: Unexpected type 'int' of a spread.  Expected 'dynamic' or an Iterable.
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+                                                  ^";
+static const field core::List<core::String*>* barWithIntDynamicSpread = invalid-expression "Expected constant '42' to be of type 'Iterable<dynamic>', but was of type 'int'.
+ - 'Iterable' is from 'dart:core'.";
+static const field core::List<core::String*>* barWithMapSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:25:51: Error: Unexpected type 'Map<String, String>' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+const List<String> barWithMapSpread = [...foo, ...quux];
+                                                  ^";
+static const field core::List<core::String*>* barWithCustomIterableSpread1 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::List<core::String*>* barWithCustomIterableSpread2 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field self::CustomIterable* customIterable = #C11;
+static const field core::List<core::String*>* barWithCustomIterableSpread3 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::List<core::String*>* listConcat = invalid-expression "The method '+' can't be invoked on '<String>[\"Hello\"]' in a constant expression.";
+static const field core::Set<core::String*>* nullSet = #C3;
+static const field core::Set<core::String*>* baz = #C14;
+static const field core::Set<core::String*>* qux = #C17;
+static const field core::Set<core::String*>* quxWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::Set<core::String*>* quxWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:41:50: Error: Expected ',' before this.
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+                                                 ^";
+static const field core::Set<core::String*>* quxWithMapSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:42:38: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+                                     ^";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread1 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread2 = invalid-expression "Only lists and sets can be used in spreads in constant lists and sets.";
+static const field core::Set<core::String*>* quxWithCustomIterableSpread3 = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:48:59: Error: A value of type 'CustomIterable' can't be assigned to a variable of type 'String'.
+ - 'CustomIterable' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+                                                          ^";
+static const field core::Set<dynamic>* setWithNonPrimitiveEquals = invalid-expression "The element 'WithEquals {i: 42}' does not have a primitive operator '=='.
+ - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.";
+static const field core::Set<dynamic>* setWithDuplicates = invalid-expression "The element '42' conflicts with another existing element in the set.";
+static const field core::Map<core::String*, core::String*>* nullMap = #C3;
+static const field core::Map<core::String*, core::String*>* quux = #C19;
+static const field core::Map<core::String*, core::String*>* quuz = #C22;
+static const field core::Map<core::String*, core::String*>* quuzWithNullSpread = invalid-expression "Null value during constant evaluation.";
+static const field core::Map<core::String*, core::String*>* quuzWithIntSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:58:60: Error: Unexpected type 'int' of a map spread entry.  Expected 'dynamic' or a Map.
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+                                                           ^";
+static const field core::Map<core::String*, core::String*>* quuzWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:59:47: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+                                              ^";
+static const field core::Map<core::String*, core::String*>* mapWithSetSpread = invalid-expression "pkg/front_end/testcases/general/constants/const_collections.dart:60:46: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
+const Map<String, String> mapWithSetSpread = {...baz};
+                                             ^";
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap1 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap2 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<core::String*, core::String*>* customMap = #C23;
+static const field core::Map<core::String*, core::String*>* mapWithCustomMap3 = invalid-expression "Only maps can be used in spreads in constant maps.";
+static const field core::Map<dynamic, core::int*>* mapWithNonPrimitiveEqualsKey = invalid-expression "The key 'WithEquals {i: 42}' does not have a primitive operator '=='.
+ - 'WithEquals' is from 'pkg/front_end/testcases/general/constants/const_collections.dart'.";
+static const field core::Map<core::int*, core::int*>* mapWithDuplicates = invalid-expression "The key '42' conflicts with another existing key in the map.";
+static get fooAsGetter() → core::List<core::String*>*
+  return #C8;
+static get barAsGetter() → core::List<core::String*>*
+  return #C10;
+static get bazAsGetter() → core::Set<core::String*>*
+  return #C14;
+static get quxAsGetter() → core::Set<core::String*>*
+  return #C17;
+static get quuxAsGetter() → core::Map<core::String*, core::String*>*
+  return #C19;
+static get quuzAsGetter() → core::Map<core::String*, core::String*>*
+  return #C22;
+static method main() → dynamic {
+  core::print(#C10);
+  core::print(#C17);
+  core::print(#C22);
+  core::print(let final core::Set<core::String*>* #t3 = new col::_CompactLinkedHashSet::•<core::String*>() in let final core::bool #t4 = #t3.{core::Set::add}("hello") in #t3);
+  core::print(#C26);
+}
+
+constants  {
+  #C1 = ""
+  #C2 = true
+  #C3 = null
+  #C4 = core::_Override {}
+  #C5 = 42
+  #C6 = "hello"
+  #C7 = "world"
+  #C8 = <core::String*>[#C6, #C7]
+  #C9 = "!"
+  #C10 = <core::String*>[#C6, #C7, #C9]
+  #C11 = self::CustomIterable {}
+  #C12 = <dynamic>[#C6, #C3, #C7, #C3]
+  #C13 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C12}
+  #C14 = col::_UnmodifiableSet<core::String*> {_map:#C13}
+  #C15 = <dynamic>[#C6, #C3, #C7, #C3, #C9, #C3]
+  #C16 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C15}
+  #C17 = col::_UnmodifiableSet<core::String*> {_map:#C16}
+  #C18 = <dynamic>[#C6, #C7]
+  #C19 = core::_ImmutableMap<core::String*, core::String*> {_kvPairs:#C18}
+  #C20 = "bye!"
+  #C21 = <dynamic>[#C6, #C7, #C9, #C20]
+  #C22 = core::_ImmutableMap<core::String*, core::String*> {_kvPairs:#C21}
+  #C23 = self::CustomMap {}
+  #C24 = <dynamic>[#C6, #C3]
+  #C25 = core::_ImmutableMap<core::String*, core::Null?> {_kvPairs:#C24}
+  #C26 = col::_UnmodifiableSet<core::String*> {_map:#C25}
+}
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline.expect
new file mode 100644
index 0000000..1b2ee83
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline.expect
@@ -0,0 +1,124 @@
+import 'dart:collection';
+
+class ConstIterable extends IterableBase<int> {
+  const ConstIterable();
+  Iterator<int> get iterator => <int>[].iterator;
+}
+
+const int fortyTwo = 42;
+const dynamic fortyTwoAsDynamic = ((fortyTwo as dynamic) * 2) ~/ 2;
+const List<String> nullList = null;
+const List<String> foo = ["hello", "world"];
+List<String> get fooAsGetter => const ["hello", "world"];
+const List<String> bar = [...foo, "!"];
+var barAsVar = [...foo, "!"];
+List<String> get barAsGetter => const [...foo, "!"];
+const List<String> barWithNullSpread = [...foo, ...nullList];
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+const List<String> barWithMapSpread = [...foo, ...quux];
+const List<String> barWithCustomIterableSpread1 = [
+  ...bar,
+  ...const CustomIterable()
+];
+const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+const customIterable = const CustomIterable();
+const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+const List<String> listConcat = ["Hello"] + ["World"];
+const Set<String> nullSet = null;
+const Set<String> baz = {"hello", "world"};
+Set<String> get bazAsGetter => const {"hello", "world"};
+const Set<String> qux = {...baz, "!"};
+Set<String> get quxAsGetter => const {...baz, "!"};
+const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+const Set<String> quxWithCustomIterableSpread1 = {
+  ...baz,
+  ...const CustomIterable()
+};
+const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+const Set<dynamic> setWithDuplicates = {42, 42};
+const Map<String, String> nullMap = null;
+const Map<String, String> quux = {"hello": "world"};
+Map<String, String> get quuxAsGetter => const {"hello": "world"};
+const Map<String, String> quuz = {...quux, "!": "bye!"};
+Map<String, String> get quuzAsGetter => const {...quux, "!": "bye!"};
+const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+const Map<String, String> mapWithSetSpread = {...baz};
+const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+const Map<String, String> customMap = const CustomMap();
+const Map<String, String> mapWithCustomMap3 = {...customMap};
+const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+  const WithEquals(42): 42
+};
+const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+
+class WithEquals {
+  final int i;
+  const WithEquals(this.i);
+  operator ==(Object o) {}
+}
+
+class CustomIterable extends IterableBase<String> {
+  const CustomIterable();
+  Iterator<String> get iterator => <String>[].iterator;
+}
+
+class CustomMap implements Map<String, String> {
+  const CustomMap();
+  @override
+  Iterable<MapEntry<String, String>> get entries => [];
+  @override
+  String operator [](Object key) => throw new UnimplementedError();
+  @override
+  void operator []=(String key, String value) => throw new UnimplementedError();
+  @override
+  Map<RK, RV> cast<RK, RV>() => throw new UnimplementedError();
+  @override
+  void clear() => throw new UnimplementedError();
+  @override
+  bool containsKey(Object key) => throw new UnimplementedError();
+  @override
+  bool containsValue(Object value) => throw new UnimplementedError();
+  @override
+  bool get isEmpty => throw new UnimplementedError();
+  @override
+  bool get isNotEmpty => throw new UnimplementedError();
+  @override
+  Iterable<String> get keys => throw new UnimplementedError();
+  @override
+  int get length => throw new UnimplementedError();
+  @override
+  String remove(Object key) => throw new UnimplementedError();
+  @override
+  Iterable<String> get values => throw new UnimplementedError();
+  @override
+  void addAll(Map<String, String> other) => throw new UnimplementedError();
+  @override
+  void addEntries(Iterable<MapEntry<String, String>> newEntries) =>
+      throw new UnimplementedError();
+  @override
+  void forEach(void f(String key, String value)) =>
+      throw new UnimplementedError();
+  @override
+  String putIfAbsent(String key, String ifAbsent()) =>
+      throw new UnimplementedError();
+  @override
+  void updateAll(String update(String key, String value)) =>
+      throw new UnimplementedError();
+  @override
+  void removeWhere(bool predicate(String key, String value)) =>
+      throw new UnimplementedError();
+  String update(String key, String update(String value), {String ifAbsent()}) =>
+      throw new UnimplementedError();
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(String key, String value)) =>
+      throw new UnimplementedError();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..97ae580
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/const_collections.dart.textual_outline_modelled.expect
@@ -0,0 +1,124 @@
+import 'dart:collection';
+
+List<String> get barAsGetter => const [...foo, "!"];
+List<String> get fooAsGetter => const ["hello", "world"];
+Map<String, String> get quuxAsGetter => const {"hello": "world"};
+Map<String, String> get quuzAsGetter => const {...quux, "!": "bye!"};
+Set<String> get bazAsGetter => const {"hello", "world"};
+Set<String> get quxAsGetter => const {...baz, "!"};
+
+class ConstIterable extends IterableBase<int> {
+  Iterator<int> get iterator => <int>[].iterator;
+  const ConstIterable();
+}
+
+class CustomIterable extends IterableBase<String> {
+  Iterator<String> get iterator => <String>[].iterator;
+  const CustomIterable();
+}
+
+class CustomMap implements Map<String, String> {
+  @override
+  Iterable<MapEntry<String, String>> get entries => [];
+  @override
+  Iterable<String> get keys => throw new UnimplementedError();
+  @override
+  Iterable<String> get values => throw new UnimplementedError();
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> f(String key, String value)) =>
+      throw new UnimplementedError();
+  @override
+  Map<RK, RV> cast<RK, RV>() => throw new UnimplementedError();
+  @override
+  String operator [](Object key) => throw new UnimplementedError();
+  @override
+  String putIfAbsent(String key, String ifAbsent()) =>
+      throw new UnimplementedError();
+  @override
+  String remove(Object key) => throw new UnimplementedError();
+  String update(String key, String update(String value), {String ifAbsent()}) =>
+      throw new UnimplementedError();
+  @override
+  bool containsKey(Object key) => throw new UnimplementedError();
+  @override
+  bool containsValue(Object value) => throw new UnimplementedError();
+  @override
+  bool get isEmpty => throw new UnimplementedError();
+  @override
+  bool get isNotEmpty => throw new UnimplementedError();
+  const CustomMap();
+  @override
+  int get length => throw new UnimplementedError();
+  @override
+  void addAll(Map<String, String> other) => throw new UnimplementedError();
+  @override
+  void addEntries(Iterable<MapEntry<String, String>> newEntries) =>
+      throw new UnimplementedError();
+  @override
+  void clear() => throw new UnimplementedError();
+  @override
+  void forEach(void f(String key, String value)) =>
+      throw new UnimplementedError();
+  @override
+  void operator []=(String key, String value) => throw new UnimplementedError();
+  @override
+  void removeWhere(bool predicate(String key, String value)) =>
+      throw new UnimplementedError();
+  @override
+  void updateAll(String update(String key, String value)) =>
+      throw new UnimplementedError();
+}
+
+class WithEquals {
+  const WithEquals(this.i);
+  final int i;
+  operator ==(Object o) {}
+}
+
+const List<String> bar = [...foo, "!"];
+const List<String> barWithCustomIterableSpread1 = [
+  ...bar,
+  ...const CustomIterable()
+];
+const List<String> barWithCustomIterableSpread2 = [...bar, ...CustomIterable()];
+const List<String> barWithCustomIterableSpread3 = [...bar, ...customIterable];
+const List<String> barWithIntDynamicSpread = [...foo, ...fortyTwoAsDynamic];
+const List<String> barWithIntSpread = [...foo, ...fortyTwo];
+const List<String> barWithMapSpread = [...foo, ...quux];
+const List<String> barWithNullSpread = [...foo, ...nullList];
+const List<String> foo = ["hello", "world"];
+const List<String> listConcat = ["Hello"] + ["World"];
+const List<String> nullList = null;
+const Map<String, String> customMap = const CustomMap();
+const Map<String, String> mapWithCustomMap1 = {...const CustomMap()};
+const Map<String, String> mapWithCustomMap2 = {...CustomMap()};
+const Map<String, String> mapWithCustomMap3 = {...customMap};
+const Map<String, String> mapWithSetSpread = {...baz};
+const Map<String, String> nullMap = null;
+const Map<String, String> quux = {"hello": "world"};
+const Map<String, String> quuz = {...quux, "!": "bye!"};
+const Map<String, String> quuzWithIntSpread = {...quux, ...fortyTwo};
+const Map<String, String> quuzWithNullSpread = {...quux, ...nullMap};
+const Map<String, String> quuzWithSetSpread = {...quux, ...baz};
+const Map<dynamic, int> mapWithNonPrimitiveEqualsKey = {
+  const WithEquals(42): 42
+};
+const Map<int, int> mapWithDuplicates = {42: 42, 42: 42};
+const Set<String> baz = {"hello", "world"};
+const Set<String> nullSet = null;
+const Set<String> qux = {...baz, "!"};
+const Set<String> quxWithCustomIterableSpread1 = {
+  ...baz,
+  ...const CustomIterable()
+};
+const Set<String> quxWithCustomIterableSpread2 = {...baz, ...CustomIterable()};
+const Set<String> quxWithCustomIterableSpread3 = {...baz, customIterable};
+const Set<String> quxWithIntSpread = {...baz, ...fortyTwo};
+const Set<String> quxWithMapSpread = {...baz, ...quux};
+const Set<String> quxWithNullSpread = {...baz, ...nullSet};
+const Set<dynamic> setWithDuplicates = {42, 42};
+const Set<dynamic> setWithNonPrimitiveEquals = {const WithEquals(42)};
+const customIterable = const CustomIterable();
+const dynamic fortyTwoAsDynamic = ((fortyTwo as dynamic) * 2) ~/ 2;
+const int fortyTwo = 42;
+main() {}
+var barAsVar = [...foo, "!"];
diff --git a/pkg/front_end/testcases/general/constants/folder.options b/pkg/front_end/testcases/general/constants/folder.options
new file mode 100644
index 0000000..0cbe954
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/folder.options
@@ -0,0 +1,4 @@
+--enable-experiment=triple-shift
+-Dbaz=42
+-DbazTrue=true
+-DbazFalse=false
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart b/pkg/front_end/testcases/general/constants/issue_43431.dart
new file mode 100644
index 0000000..c333e70
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  const Foo({bool x: true});
+  const x = Foo();
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.outline.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.outline.expect
new file mode 100644
index 0000000..1854d2a
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.outline.expect
@@ -0,0 +1,30 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const x = Foo();
+//   ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  field self::Foo* x;
+  const constructor •({core::bool* x = true}) → self::Foo*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect
new file mode 100644
index 0000000..1c887af
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const x = Foo();
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Error: Constant expression expected.
+// Try inserting 'const'.
+//   const x = Foo();
+//             ^^^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:6:9: Error: Constructor is marked 'const' so all fields must be final.
+//   const Foo({bool x: true});
+//         ^
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:9: Context: Field isn't final, but constructor is 'const'.
+//   const x = Foo();
+//         ^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Error: Constant evaluation error:
+//   const x = Foo();
+//             ^
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Context: Constant expression depends on itself.
+//   const x = Foo();
+//             ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  field self::Foo* x = invalid-expression "Constant expression depends on itself.";
+  const constructor •({core::bool* x = #C1}) → self::Foo*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = true
+}
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect
new file mode 100644
index 0000000..1c887af
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.strong.transformed.expect
@@ -0,0 +1,52 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const x = Foo();
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Error: Constant expression expected.
+// Try inserting 'const'.
+//   const x = Foo();
+//             ^^^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:6:9: Error: Constructor is marked 'const' so all fields must be final.
+//   const Foo({bool x: true});
+//         ^
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:9: Context: Field isn't final, but constructor is 'const'.
+//   const x = Foo();
+//         ^
+//
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Error: Constant evaluation error:
+//   const x = Foo();
+//             ^
+// pkg/front_end/testcases/general/constants/issue_43431.dart:7:13: Context: Constant expression depends on itself.
+//   const x = Foo();
+//             ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  field self::Foo* x = invalid-expression "Constant expression depends on itself.";
+  const constructor •({core::bool* x = #C1}) → self::Foo*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = true
+}
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline.expect
new file mode 100644
index 0000000..3051321
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+class Foo {
+  const Foo({bool x: true});
+  const x = Foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3051321
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/issue_43431.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+class Foo {
+  const Foo({bool x: true});
+  const x = Foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/folder.options b/pkg/front_end/testcases/general/constants/js_semantics/folder.options
new file mode 100644
index 0000000..674c362
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/folder.options
@@ -0,0 +1,2 @@
+--enable-experiment=triple-shift
+--target=noneWithJs
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart
new file mode 100644
index 0000000..618b0a5
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const int shiftNegative1 = 2 << -1;
+const int shiftNegative2 = 2 >>> -1;
+const int shiftNegative3 = 2 >> -1;
+const int modZero = 2 % 0;
+const int divZero = 2 / 0;
+const int intdivZero = 2 ~/ 0;
+const int unaryMinus = -2;
+const int unaryTilde = ~2;
+const int unaryPlus = +2;
+
+const int binaryPlus = 40 + 2;
+const int binaryMinus = 44 - 2;
+const int binaryTimes = 21 * 2;
+const double binaryDiv = 84 / 2;
+const int binaryTildeDiv = 84~/ 2;
+const int binaryMod = 85 % 43;
+const int binaryOr = 32 | 10;
+const int binaryAnd = 63 & 106;
+const int binaryXor = 63 ^ 21;
+const int binaryShift1 = 21 << 1;
+
+// These aren't currently defined on int :(.
+const int binaryShift2 = 84 >>> 1;
+const int binaryShift3 = 21 >>> 64;
+
+const int binaryShift4 = 84 >> 1;
+const int binaryShift5 = -1 >> 1;
+const bool binaryLess = 42 < 42;
+const bool binaryLessEqual = 42 <= 42;
+const bool binaryGreaterEqual = 42 >= 42;
+const bool binaryGreater = 42 > 42;
+
+const int doubleTruncateDiv = 84.2 ~/ 2;
+const int doubleTruncateDivZero = 84.2 ~/ 0;
+const int doubleTruncateDivNull = 84.2 ~/ null;
+const double doubleNan = 0/0;
+const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+
+const int bigNumber = 0x8000000000000000;
+
+main() {
+
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect
new file mode 100644
index 0000000..2f0bfb0
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.outline.expect
@@ -0,0 +1,107 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = 2.{core::int::<<}(1.{core::int::unary-}());
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* shiftNegative3 = 2.{core::int::>>}(1.{core::int::unary-}());
+static const field core::int* modZero = 2.{core::num::%}(0);
+static const field core::int* divZero = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^" in 2.{core::num::/}(0) as{TypeError} core::int*;
+static const field core::int* intdivZero = 2.{core::num::~/}(0);
+static const field core::int* unaryMinus = 2.{core::int::unary-}();
+static const field core::int* unaryTilde = 2.{core::int::~}();
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^".+(2) as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryPlus = 40.{core::num::+}(2);
+static const field core::int* binaryMinus = 44.{core::num::-}(2);
+static const field core::int* binaryTimes = 21.{core::num::*}(2);
+static const field core::double* binaryDiv = 84.{core::num::/}(2);
+static const field core::int* binaryTildeDiv = 84.{core::num::~/}(2);
+static const field core::int* binaryMod = 85.{core::num::%}(43);
+static const field core::int* binaryOr = 32.{core::int::|}(10);
+static const field core::int* binaryAnd = 63.{core::int::&}(106);
+static const field core::int* binaryXor = 63.{core::int::^}(21);
+static const field core::int* binaryShift1 = 21.{core::int::<<}(1);
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryShift4 = 84.{core::int::>>}(1);
+static const field core::int* binaryShift5 = 1.{core::int::unary-}().{core::int::>>}(1);
+static const field core::bool* binaryLess = 42.{core::num::<}(42);
+static const field core::bool* binaryLessEqual = 42.{core::num::<=}(42);
+static const field core::bool* binaryGreaterEqual = 42.{core::num::>=}(42);
+static const field core::bool* binaryGreater = 42.{core::num::>}(42);
+static const field core::int* doubleTruncateDiv = 84.2.{core::double::~/}(2);
+static const field core::int* doubleTruncateDivZero = 84.2.{core::double::~/}(0);
+static const field core::int* doubleTruncateDivNull = 84.2.{core::double::~/}(null);
+static const field core::double* doubleNan = 0.{core::num::/}(0);
+static const field core::int* doubleTruncateDivNaN = 84.2.{core::double::~/}(self::doubleNan);
+static const field core::int* bigNumber = -9223372036854775808;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:5:33 -> DoubleConstant(-1.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:7:33 -> DoubleConstant(-1.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:9:23 -> DoubleConstant(Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:11:24 -> DoubleConstant(-2.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:12:24 -> DoubleConstant(4294967293.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:15:27 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:16:28 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:17:28 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:18:29 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:19:30 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:20:26 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:21:25 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:22:26 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:23:26 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:24:29 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:30:29 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:31:29 -> DoubleConstant(4294967295.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:32:28 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:33:33 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:34:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:35:31 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:37:36 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:40:27 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///number_folds.dart:41:42 -> DoubleConstant(NaN)
+Extra constant evaluation: evaluated: 38, effectively constant: 24
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.expect b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.expect
new file mode 100644
index 0000000..a425f18
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.expect
@@ -0,0 +1,159 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:30: Error: Constant evaluation error:
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:30: Context: Binary operator '<<' on '2.0' requires non-negative operand, but was '-1.0'.
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:11: Context: While analyzing:
+// const int shiftNegative1 = 2 << -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:30: Error: Constant evaluation error:
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:30: Context: Binary operator '>>' on '2.0' requires non-negative operand, but was '-1.0'.
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:11: Context: While analyzing:
+// const int shiftNegative3 = 2 >> -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:23: Error: Constant evaluation error:
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:23: Context: Binary operator '%' on '2.0' requires non-zero divisor, but divisor was '0'.
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:11: Context: While analyzing:
+// const int modZero = 2 % 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:26: Error: Constant evaluation error:
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:26: Context: Binary operator '~/' on '2.0' requires non-zero divisor, but divisor was '0'.
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:11: Context: While analyzing:
+// const int intdivZero = 2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:40: Error: Constant evaluation error:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:40: Context: Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:11: Context: While analyzing:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:40: Error: Constant evaluation error:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:40: Context: Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:11: Context: While analyzing:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:39: Error: Constant evaluation error:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:39: Context: Binary operator '84.2 ~/ NaN' results is Infinity or NaN.
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:11: Context: While analyzing:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = invalid-expression "Binary operator '<<' on '2.0' requires non-negative operand, but was '-1.0'.";
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^";
+static const field core::int* shiftNegative3 = invalid-expression "Binary operator '>>' on '2.0' requires non-negative operand, but was '-1.0'.";
+static const field core::int* modZero = invalid-expression "Binary operator '%' on '2.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* divZero = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^";
+static const field core::int* intdivZero = invalid-expression "Binary operator '~/' on '2.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* unaryMinus = #C1;
+static const field core::int* unaryTilde = #C2;
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^";
+static const field core::int* binaryPlus = #C3;
+static const field core::int* binaryMinus = #C3;
+static const field core::int* binaryTimes = #C3;
+static const field core::double* binaryDiv = #C3;
+static const field core::int* binaryTildeDiv = #C3;
+static const field core::int* binaryMod = #C3;
+static const field core::int* binaryOr = #C3;
+static const field core::int* binaryAnd = #C3;
+static const field core::int* binaryXor = #C3;
+static const field core::int* binaryShift1 = #C3;
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^";
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^";
+static const field core::int* binaryShift4 = #C3;
+static const field core::int* binaryShift5 = #C4;
+static const field core::bool* binaryLess = #C5;
+static const field core::bool* binaryLessEqual = #C6;
+static const field core::bool* binaryGreaterEqual = #C6;
+static const field core::bool* binaryGreater = #C5;
+static const field core::int* doubleTruncateDiv = #C3;
+static const field core::int* doubleTruncateDivZero = invalid-expression "Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* doubleTruncateDivNull = invalid-expression "Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.";
+static const field core::double* doubleNan = #C7;
+static const field core::int* doubleTruncateDivNaN = invalid-expression "Binary operator '84.2 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* bigNumber = #C8;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = -2.0
+  #C2 = 4294967293.0
+  #C3 = 42.0
+  #C4 = 4294967295.0
+  #C5 = false
+  #C6 = true
+  #C7 = NaN
+  #C8 = 9223372036854776000.0
+}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.transformed.expect
new file mode 100644
index 0000000..a425f18
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.strong.transformed.expect
@@ -0,0 +1,159 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:30: Error: Constant evaluation error:
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:30: Context: Binary operator '<<' on '2.0' requires non-negative operand, but was '-1.0'.
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:5:11: Context: While analyzing:
+// const int shiftNegative1 = 2 << -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:30: Error: Constant evaluation error:
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:30: Context: Binary operator '>>' on '2.0' requires non-negative operand, but was '-1.0'.
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:7:11: Context: While analyzing:
+// const int shiftNegative3 = 2 >> -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:23: Error: Constant evaluation error:
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:23: Context: Binary operator '%' on '2.0' requires non-zero divisor, but divisor was '0'.
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:8:11: Context: While analyzing:
+// const int modZero = 2 % 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:26: Error: Constant evaluation error:
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:26: Context: Binary operator '~/' on '2.0' requires non-zero divisor, but divisor was '0'.
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:10:11: Context: While analyzing:
+// const int intdivZero = 2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:40: Error: Constant evaluation error:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:40: Context: Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:38:11: Context: While analyzing:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:40: Error: Constant evaluation error:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:40: Context: Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:39:11: Context: While analyzing:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:39: Error: Constant evaluation error:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:39: Context: Binary operator '84.2 ~/ NaN' results is Infinity or NaN.
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:41:11: Context: While analyzing:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = invalid-expression "Binary operator '<<' on '2.0' requires non-negative operand, but was '-1.0'.";
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^";
+static const field core::int* shiftNegative3 = invalid-expression "Binary operator '>>' on '2.0' requires non-negative operand, but was '-1.0'.";
+static const field core::int* modZero = invalid-expression "Binary operator '%' on '2.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* divZero = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^";
+static const field core::int* intdivZero = invalid-expression "Binary operator '~/' on '2.0' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* unaryMinus = #C1;
+static const field core::int* unaryTilde = #C2;
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^";
+static const field core::int* binaryPlus = #C3;
+static const field core::int* binaryMinus = #C3;
+static const field core::int* binaryTimes = #C3;
+static const field core::double* binaryDiv = #C3;
+static const field core::int* binaryTildeDiv = #C3;
+static const field core::int* binaryMod = #C3;
+static const field core::int* binaryOr = #C3;
+static const field core::int* binaryAnd = #C3;
+static const field core::int* binaryXor = #C3;
+static const field core::int* binaryShift1 = #C3;
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^";
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^";
+static const field core::int* binaryShift4 = #C3;
+static const field core::int* binaryShift5 = #C4;
+static const field core::bool* binaryLess = #C5;
+static const field core::bool* binaryLessEqual = #C6;
+static const field core::bool* binaryGreaterEqual = #C6;
+static const field core::bool* binaryGreater = #C5;
+static const field core::int* doubleTruncateDiv = #C3;
+static const field core::int* doubleTruncateDivZero = invalid-expression "Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* doubleTruncateDivNull = invalid-expression "Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.";
+static const field core::double* doubleNan = #C7;
+static const field core::int* doubleTruncateDivNaN = invalid-expression "Binary operator '84.2 ~/ NaN' results is Infinity or NaN.";
+static const field core::int* bigNumber = #C8;
+static method main() → dynamic {}
+
+constants  {
+  #C1 = -2.0
+  #C2 = 4294967293.0
+  #C3 = 42.0
+  #C4 = 4294967295.0
+  #C5 = false
+  #C6 = true
+  #C7 = NaN
+  #C8 = 9223372036854776000.0
+}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.textual_outline.expect
new file mode 100644
index 0000000..cb5607d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/number_folds.dart.textual_outline.expect
@@ -0,0 +1,34 @@
+const int shiftNegative1 = 2 << -1;
+const int shiftNegative2 = 2 >>> -1;
+const int shiftNegative3 = 2 >> -1;
+const int modZero = 2 % 0;
+const int divZero = 2 / 0;
+const int intdivZero = 2 ~/ 0;
+const int unaryMinus = -2;
+const int unaryTilde = ~2;
+const int unaryPlus = +2;
+const int binaryPlus = 40 + 2;
+const int binaryMinus = 44 - 2;
+const int binaryTimes = 21 * 2;
+const double binaryDiv = 84 / 2;
+const int binaryTildeDiv = 84~/ 2;
+const int binaryMod = 85 % 43;
+const int binaryOr = 32 | 10;
+const int binaryAnd = 63 & 106;
+const int binaryXor = 63 ^ 21;
+const int binaryShift1 = 21 << 1;
+const int binaryShift2 = 84 >>> 1;
+const int binaryShift3 = 21 >>> 64;
+const int binaryShift4 = 84 >> 1;
+const int binaryShift5 = -1 >> 1;
+const bool binaryLess = 42 < 42;
+const bool binaryLessEqual = 42 <= 42;
+const bool binaryGreaterEqual = 42 >= 42;
+const bool binaryGreater = 42 > 42;
+const int doubleTruncateDiv = 84.2 ~/ 2;
+const int doubleTruncateDivZero = 84.2 ~/ 0;
+const int doubleTruncateDivNull = 84.2 ~/ null;
+const double doubleNan = 0/0;
+const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+const int bigNumber = 0x8000000000000000;
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart b/pkg/front_end/testcases/general/constants/js_semantics/various.dart
new file mode 100644
index 0000000..f2270ff
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const bool y = false;
+const bool z = !(y);
+
+const maybeInt = z ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const bool isItDouble = maybeInt is double ? true : false;
+
+const int actualInt = 42;
+const bool isItInt2 = actualInt is int ? true : false;
+const bool isItDouble2 = actualInt is double ? true : false;
+
+const maybeDouble = z ? 42.0 : true;
+const bool isItInt3 = maybeDouble is int ? true : false;
+const bool isItDouble3 = maybeDouble is double ? true : false;
+
+const double actualDouble = 42.0;
+const bool isItInt4 = actualDouble is int ? true : false;
+const bool isItDouble4 = actualDouble is double ? true : false;
+
+const maybeDouble2 = z ? 42.42 : true;
+const bool isItInt5 = maybeDouble2 is int ? true : false;
+const bool isItDouble5 = maybeDouble2 is double ? true : false;
+
+const double actualDouble2 = 42.42;
+const bool isItInt6 = actualDouble2 is int ? true : false;
+const bool isItDouble7 = actualDouble2 is double ? true : false;
+
+const zeroPointZeroIdentical = identical(0.0, 0.0);
+const zeroPointZeroIdenticalToZero = identical(0.0, 0);
+const zeroIdenticalToZeroPointZero = identical(0, 0.0);
+const nanIdentical = identical(0 / 0, 0 / 0);
+const stringIdentical = identical("hello", "hello");
+const string2Identical = identical("hello", "world");
+
+const zeroPointZeroEqual = 0.0 == 0.0;
+const zeroPointZeroEqualToZero = 0.0 == 0;
+const zeroEqualToZeroPointZero = 0 == 0.0;
+const nanEqual = 0 / 0 == 0 / 0;
+const stringEqual = "hello" == "hello";
+const string2Equal = "hello" == "world";
+
+const int intFortyTwo = 42;
+const String intStringConcat = "hello" "${intFortyTwo * intFortyTwo}";
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect
new file mode 100644
index 0000000..41ed046
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.outline.expect
@@ -0,0 +1,71 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::bool* y = false;
+static const field core::bool* z = !self::y;
+static const field core::Object* maybeInt = self::z ?{core::Object*} 42 : true;
+static const field core::bool* isItInt = self::maybeInt is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble = self::maybeInt is core::double* ?{core::bool*} true : false;
+static const field core::int* actualInt = 42;
+static const field core::bool* isItInt2 = self::actualInt is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble2 = self::actualInt is core::double* ?{core::bool*} true : false;
+static const field core::Object* maybeDouble = self::z ?{core::Object*} 42.0 : true;
+static const field core::bool* isItInt3 = self::maybeDouble is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble3 = self::maybeDouble is core::double* ?{core::bool*} true : false;
+static const field core::double* actualDouble = 42.0;
+static const field core::bool* isItInt4 = self::actualDouble is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble4 = self::actualDouble is core::double* ?{core::bool*} true : false;
+static const field core::Object* maybeDouble2 = self::z ?{core::Object*} 42.42 : true;
+static const field core::bool* isItInt5 = self::maybeDouble2 is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble5 = self::maybeDouble2 is core::double* ?{core::bool*} true : false;
+static const field core::double* actualDouble2 = 42.42;
+static const field core::bool* isItInt6 = self::actualDouble2 is core::int* ?{core::bool*} true : false;
+static const field core::bool* isItDouble7 = self::actualDouble2 is core::double* ?{core::bool*} true : false;
+static const field core::bool* zeroPointZeroIdentical = core::identical(0.0, 0.0);
+static const field core::bool* zeroPointZeroIdenticalToZero = core::identical(0.0, 0);
+static const field core::bool* zeroIdenticalToZeroPointZero = core::identical(0, 0.0);
+static const field core::bool* nanIdentical = core::identical(0.{core::num::/}(0), 0.{core::num::/}(0));
+static const field core::bool* stringIdentical = core::identical("hello", "hello");
+static const field core::bool* string2Identical = core::identical("hello", "world");
+static const field core::bool* zeroPointZeroEqual = 0.0.{core::num::==}(0.0);
+static const field core::bool* zeroPointZeroEqualToZero = 0.0.{core::num::==}(0);
+static const field core::bool* zeroEqualToZeroPointZero = 0.{core::num::==}(0.0);
+static const field core::bool* nanEqual = 0.{core::num::/}(0).{core::num::==}(0.{core::num::/}(0));
+static const field core::bool* stringEqual = "hello".{core::String::==}("hello");
+static const field core::bool* string2Equal = "hello".{core::String::==}("world");
+static const field core::int* intFortyTwo = 42;
+static const field core::String* intStringConcat = "hello${self::intFortyTwo.{core::num::*}(self::intFortyTwo)}";
+
+
+Extra constant evaluation status:
+Evaluated: Not @ org-dartlang-testcase:///various.dart:6:16 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:8:20 -> DoubleConstant(42.0)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:9:38 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:10:44 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:13:40 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:14:46 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:16:23 -> DoubleConstant(42.0)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:17:42 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:18:48 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:21:43 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:22:49 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:24:24 -> DoubleConstant(42.42)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:25:43 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:26:49 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:29:44 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:30:50 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:32:32 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:33:38 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:34:38 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:35:22 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:36:25 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:37:26 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:39:32 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:40:38 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:41:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:42:24 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:43:29 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:44:30 -> BoolConstant(false)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///various.dart:47:30 -> StringConstant("hello1764")
+Extra constant evaluation: evaluated: 29, effectively constant: 29
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.expect
new file mode 100644
index 0000000..0570489
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::bool* y = #C1;
+static const field core::bool* z = #C2;
+static const field core::Object* maybeInt = #C3;
+static const field core::bool* isItInt = #C2;
+static const field core::bool* isItDouble = #C2;
+static const field core::int* actualInt = #C3;
+static const field core::bool* isItInt2 = #C2;
+static const field core::bool* isItDouble2 = #C2;
+static const field core::Object* maybeDouble = #C3;
+static const field core::bool* isItInt3 = #C2;
+static const field core::bool* isItDouble3 = #C2;
+static const field core::double* actualDouble = #C3;
+static const field core::bool* isItInt4 = #C2;
+static const field core::bool* isItDouble4 = #C2;
+static const field core::Object* maybeDouble2 = #C4;
+static const field core::bool* isItInt5 = #C1;
+static const field core::bool* isItDouble5 = #C2;
+static const field core::double* actualDouble2 = #C4;
+static const field core::bool* isItInt6 = #C1;
+static const field core::bool* isItDouble7 = #C2;
+static const field core::bool* zeroPointZeroIdentical = #C2;
+static const field core::bool* zeroPointZeroIdenticalToZero = #C2;
+static const field core::bool* zeroIdenticalToZeroPointZero = #C2;
+static const field core::bool* nanIdentical = #C1;
+static const field core::bool* stringIdentical = #C2;
+static const field core::bool* string2Identical = #C1;
+static const field core::bool* zeroPointZeroEqual = #C2;
+static const field core::bool* zeroPointZeroEqualToZero = #C2;
+static const field core::bool* zeroEqualToZeroPointZero = #C2;
+static const field core::bool* nanEqual = #C1;
+static const field core::bool* stringEqual = #C2;
+static const field core::bool* string2Equal = #C1;
+static const field core::int* intFortyTwo = #C3;
+static const field core::String* intStringConcat = #C5;
+
+constants  {
+  #C1 = false
+  #C2 = true
+  #C3 = 42.0
+  #C4 = 42.42
+  #C5 = "hello1764"
+}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.transformed.expect
new file mode 100644
index 0000000..0570489
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::bool* y = #C1;
+static const field core::bool* z = #C2;
+static const field core::Object* maybeInt = #C3;
+static const field core::bool* isItInt = #C2;
+static const field core::bool* isItDouble = #C2;
+static const field core::int* actualInt = #C3;
+static const field core::bool* isItInt2 = #C2;
+static const field core::bool* isItDouble2 = #C2;
+static const field core::Object* maybeDouble = #C3;
+static const field core::bool* isItInt3 = #C2;
+static const field core::bool* isItDouble3 = #C2;
+static const field core::double* actualDouble = #C3;
+static const field core::bool* isItInt4 = #C2;
+static const field core::bool* isItDouble4 = #C2;
+static const field core::Object* maybeDouble2 = #C4;
+static const field core::bool* isItInt5 = #C1;
+static const field core::bool* isItDouble5 = #C2;
+static const field core::double* actualDouble2 = #C4;
+static const field core::bool* isItInt6 = #C1;
+static const field core::bool* isItDouble7 = #C2;
+static const field core::bool* zeroPointZeroIdentical = #C2;
+static const field core::bool* zeroPointZeroIdenticalToZero = #C2;
+static const field core::bool* zeroIdenticalToZeroPointZero = #C2;
+static const field core::bool* nanIdentical = #C1;
+static const field core::bool* stringIdentical = #C2;
+static const field core::bool* string2Identical = #C1;
+static const field core::bool* zeroPointZeroEqual = #C2;
+static const field core::bool* zeroPointZeroEqualToZero = #C2;
+static const field core::bool* zeroEqualToZeroPointZero = #C2;
+static const field core::bool* nanEqual = #C1;
+static const field core::bool* stringEqual = #C2;
+static const field core::bool* string2Equal = #C1;
+static const field core::int* intFortyTwo = #C3;
+static const field core::String* intStringConcat = #C5;
+
+constants  {
+  #C1 = false
+  #C2 = true
+  #C3 = 42.0
+  #C4 = 42.42
+  #C5 = "hello1764"
+}
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline.expect
new file mode 100644
index 0000000..4ca812c
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline.expect
@@ -0,0 +1,34 @@
+const bool y = false;
+const bool z = !(y);
+const maybeInt = z ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const bool isItDouble = maybeInt is double ? true : false;
+const int actualInt = 42;
+const bool isItInt2 = actualInt is int ? true : false;
+const bool isItDouble2 = actualInt is double ? true : false;
+const maybeDouble = z ? 42.0 : true;
+const bool isItInt3 = maybeDouble is int ? true : false;
+const bool isItDouble3 = maybeDouble is double ? true : false;
+const double actualDouble = 42.0;
+const bool isItInt4 = actualDouble is int ? true : false;
+const bool isItDouble4 = actualDouble is double ? true : false;
+const maybeDouble2 = z ? 42.42 : true;
+const bool isItInt5 = maybeDouble2 is int ? true : false;
+const bool isItDouble5 = maybeDouble2 is double ? true : false;
+const double actualDouble2 = 42.42;
+const bool isItInt6 = actualDouble2 is int ? true : false;
+const bool isItDouble7 = actualDouble2 is double ? true : false;
+const zeroPointZeroIdentical = identical(0.0, 0.0);
+const zeroPointZeroIdenticalToZero = identical(0.0, 0);
+const zeroIdenticalToZeroPointZero = identical(0, 0.0);
+const nanIdentical = identical(0 / 0, 0 / 0);
+const stringIdentical = identical("hello", "hello");
+const string2Identical = identical("hello", "world");
+const zeroPointZeroEqual = 0.0 == 0.0;
+const zeroPointZeroEqualToZero = 0.0 == 0;
+const zeroEqualToZeroPointZero = 0 == 0.0;
+const nanEqual = 0 / 0 == 0 / 0;
+const stringEqual = "hello" == "hello";
+const string2Equal = "hello" == "world";
+const int intFortyTwo = 42;
+const String intStringConcat = "hello" "${intFortyTwo * intFortyTwo}";
diff --git a/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..70b112b
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/js_semantics/various.dart.textual_outline_modelled.expect
@@ -0,0 +1,34 @@
+const String intStringConcat = "hello" "${intFortyTwo * intFortyTwo}";
+const bool isItDouble = maybeInt is double ? true : false;
+const bool isItDouble2 = actualInt is double ? true : false;
+const bool isItDouble3 = maybeDouble is double ? true : false;
+const bool isItDouble4 = actualDouble is double ? true : false;
+const bool isItDouble5 = maybeDouble2 is double ? true : false;
+const bool isItDouble7 = actualDouble2 is double ? true : false;
+const bool isItInt = maybeInt is int ? true : false;
+const bool isItInt2 = actualInt is int ? true : false;
+const bool isItInt3 = maybeDouble is int ? true : false;
+const bool isItInt4 = actualDouble is int ? true : false;
+const bool isItInt5 = maybeDouble2 is int ? true : false;
+const bool isItInt6 = actualDouble2 is int ? true : false;
+const bool y = false;
+const bool z = !(y);
+const double actualDouble = 42.0;
+const double actualDouble2 = 42.42;
+const int actualInt = 42;
+const int intFortyTwo = 42;
+const maybeDouble = z ? 42.0 : true;
+const maybeDouble2 = z ? 42.42 : true;
+const maybeInt = z ? 42 : true;
+const nanEqual = 0 / 0 == 0 / 0;
+const nanIdentical = identical(0 / 0, 0 / 0);
+const string2Equal = "hello" == "world";
+const string2Identical = identical("hello", "world");
+const stringEqual = "hello" == "hello";
+const stringIdentical = identical("hello", "hello");
+const zeroEqualToZeroPointZero = 0 == 0.0;
+const zeroIdenticalToZeroPointZero = identical(0, 0.0);
+const zeroPointZeroEqual = 0.0 == 0.0;
+const zeroPointZeroEqualToZero = 0.0 == 0;
+const zeroPointZeroIdentical = identical(0.0, 0.0);
+const zeroPointZeroIdenticalToZero = identical(0.0, 0);
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/folder.options b/pkg/front_end/testcases/general/constants/no_experiments/folder.options
new file mode 100644
index 0000000..db4ac03
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/folder.options
@@ -0,0 +1,3 @@
+-Dbaz=42
+-DbazTrue=true
+-DbazFalse=false
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart b/pkg/front_end/testcases/general/constants/no_experiments/various.dart
new file mode 100644
index 0000000..df79a2d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const Symbol tripleShiftSymbol = const Symbol(">>>");
+
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.outline.expect
new file mode 100644
index 0000000..e41cc76
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.outline.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static const field core::Symbol* tripleShiftSymbol = const _in::Symbol::•(">>>");
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.expect
new file mode 100644
index 0000000..d856926
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:40: Error: Constant evaluation error:
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//                                        ^
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:47: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '">>>"'.
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//                                               ^
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:14: Context: While analyzing:
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::Symbol* tripleShiftSymbol = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\">>>\"'.";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.transformed.expect
new file mode 100644
index 0000000..d856926
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.strong.transformed.expect
@@ -0,0 +1,19 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:40: Error: Constant evaluation error:
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//                                        ^
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:47: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '">>>"'.
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//                                               ^
+// pkg/front_end/testcases/general/constants/no_experiments/various.dart:5:14: Context: While analyzing:
+// const Symbol tripleShiftSymbol = const Symbol(">>>");
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::Symbol* tripleShiftSymbol = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\">>>\"'.";
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline.expect
new file mode 100644
index 0000000..3cb83df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+const Symbol tripleShiftSymbol = const Symbol(">>>");
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3cb83df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/no_experiments/various.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+const Symbol tripleShiftSymbol = const Symbol(">>>");
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/number_folds.dart b/pkg/front_end/testcases/general/constants/number_folds.dart
new file mode 100644
index 0000000..2069e49
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/number_folds.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const int shiftNegative1 = 2 << -1;
+const int shiftNegative2 = 2 >>> -1;
+const int shiftNegative3 = 2 >> -1;
+const int modZero = 2 % 0;
+const int divZero = 2 / 0;
+const int intdivZero = 2 ~/ 0;
+const int unaryMinus = -2;
+const int unaryTilde = ~2;
+const int unaryPlus = +2;
+
+const int binaryPlus = 40 + 2;
+const int binaryMinus = 44 - 2;
+const int binaryTimes = 21 * 2;
+const double binaryDiv = 84 / 2;
+const int binaryTildeDiv = 84~/ 2;
+const int binaryMod = 85 % 43;
+const int binaryOr = 32 | 10;
+const int binaryAnd = 63 & 106;
+const int binaryXor = 63 ^ 21;
+const int binaryShift1 = 21 << 1;
+
+// These aren't currently defined on int :(.
+const int binaryShift2 = 84 >>> 1;
+const int binaryShift3 = 21 >>> 64;
+
+const int binaryShift4 = 84 >> 1;
+const bool binaryLess = 42 < 42;
+const bool binaryLessEqual = 42 <= 42;
+const bool binaryGreaterEqual = 42 >= 42;
+const bool binaryGreater = 42 > 42;
+
+const int doubleTruncateDiv = 84.2 ~/ 2;
+const int doubleTruncateDivZero = 84.2 ~/ 0;
+const int doubleTruncateDivNull = 84.2 ~/ null;
+const double doubleNan = 0/0;
+const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+
+main() {
+
+}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/number_folds.dart.outline.expect b/pkg/front_end/testcases/general/constants/number_folds.dart.outline.expect
new file mode 100644
index 0000000..0c36235
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/number_folds.dart.outline.expect
@@ -0,0 +1,104 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = 2.{core::int::<<}(1.{core::int::unary-}());
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* shiftNegative3 = 2.{core::int::>>}(1.{core::int::unary-}());
+static const field core::int* modZero = 2.{core::num::%}(0);
+static const field core::int* divZero = let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^" in 2.{core::num::/}(0) as{TypeError} core::int*;
+static const field core::int* intdivZero = 2.{core::num::~/}(0);
+static const field core::int* unaryMinus = 2.{core::int::unary-}();
+static const field core::int* unaryTilde = 2.{core::int::~}();
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^".+(2) as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryPlus = 40.{core::num::+}(2);
+static const field core::int* binaryMinus = 44.{core::num::-}(2);
+static const field core::int* binaryTimes = 21.{core::num::*}(2);
+static const field core::double* binaryDiv = 84.{core::num::/}(2);
+static const field core::int* binaryTildeDiv = 84.{core::num::~/}(2);
+static const field core::int* binaryMod = 85.{core::num::%}(43);
+static const field core::int* binaryOr = 32.{core::int::|}(10);
+static const field core::int* binaryAnd = 63.{core::int::&}(106);
+static const field core::int* binaryXor = 63.{core::int::^}(21);
+static const field core::int* binaryShift1 = 21.{core::int::<<}(1);
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^" as{TypeError,ForDynamic} core::int*;
+static const field core::int* binaryShift4 = 84.{core::int::>>}(1);
+static const field core::bool* binaryLess = 42.{core::num::<}(42);
+static const field core::bool* binaryLessEqual = 42.{core::num::<=}(42);
+static const field core::bool* binaryGreaterEqual = 42.{core::num::>=}(42);
+static const field core::bool* binaryGreater = 42.{core::num::>}(42);
+static const field core::int* doubleTruncateDiv = 84.2.{core::double::~/}(2);
+static const field core::int* doubleTruncateDivZero = 84.2.{core::double::~/}(0);
+static const field core::int* doubleTruncateDivNull = 84.2.{core::double::~/}(null);
+static const field core::double* doubleNan = 0.{core::num::/}(0);
+static const field core::int* doubleTruncateDivNaN = 84.2.{core::double::~/}(self::doubleNan);
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:5:33 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:7:33 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:9:23 -> DoubleConstant(Infinity)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:11:24 -> IntConstant(-2)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:12:24 -> IntConstant(-3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:15:27 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:16:28 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:17:28 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:18:29 -> DoubleConstant(42.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:19:30 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:20:26 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:21:25 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:22:26 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:23:26 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:24:29 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:30:29 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:31:28 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:32:33 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:33:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:34:31 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:36:36 -> IntConstant(42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///number_folds.dart:39:27 -> DoubleConstant(NaN)
+Evaluated: StaticGet @ org-dartlang-testcase:///number_folds.dart:40:42 -> DoubleConstant(NaN)
+Extra constant evaluation: evaluated: 37, effectively constant: 23
diff --git a/pkg/front_end/testcases/general/constants/number_folds.dart.strong.expect b/pkg/front_end/testcases/general/constants/number_folds.dart.strong.expect
new file mode 100644
index 0000000..f20a0df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/number_folds.dart.strong.expect
@@ -0,0 +1,156 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:30: Error: Constant evaluation error:
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:30: Context: Binary operator '<<' on '2' requires non-negative operand, but was '-1'.
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:11: Context: While analyzing:
+// const int shiftNegative1 = 2 << -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:30: Error: Constant evaluation error:
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:30: Context: Binary operator '>>' on '2' requires non-negative operand, but was '-1'.
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:11: Context: While analyzing:
+// const int shiftNegative3 = 2 >> -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:23: Error: Constant evaluation error:
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:23: Context: Binary operator '%' on '2' requires non-zero divisor, but divisor was '0'.
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:11: Context: While analyzing:
+// const int modZero = 2 % 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:26: Error: Constant evaluation error:
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:26: Context: Binary operator '~/' on '2' requires non-zero divisor, but divisor was '0'.
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:11: Context: While analyzing:
+// const int intdivZero = 2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:40: Error: Constant evaluation error:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:40: Context: Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:11: Context: While analyzing:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:40: Error: Constant evaluation error:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:40: Context: Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:11: Context: While analyzing:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:39: Error: Constant evaluation error:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:39: Context: Binary operator '84.2 ~/ NaN' results is Infinity or NaN.
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:11: Context: While analyzing:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = invalid-expression "Binary operator '<<' on '2' requires non-negative operand, but was '-1'.";
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^";
+static const field core::int* shiftNegative3 = invalid-expression "Binary operator '>>' on '2' requires non-negative operand, but was '-1'.";
+static const field core::int* modZero = invalid-expression "Binary operator '%' on '2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* divZero = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^";
+static const field core::int* intdivZero = invalid-expression "Binary operator '~/' on '2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* unaryMinus = #C1;
+static const field core::int* unaryTilde = #C2;
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^";
+static const field core::int* binaryPlus = #C3;
+static const field core::int* binaryMinus = #C3;
+static const field core::int* binaryTimes = #C3;
+static const field core::double* binaryDiv = #C4;
+static const field core::int* binaryTildeDiv = #C3;
+static const field core::int* binaryMod = #C3;
+static const field core::int* binaryOr = #C3;
+static const field core::int* binaryAnd = #C3;
+static const field core::int* binaryXor = #C3;
+static const field core::int* binaryShift1 = #C3;
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^";
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^";
+static const field core::int* binaryShift4 = #C3;
+static const field core::bool* binaryLess = #C5;
+static const field core::bool* binaryLessEqual = #C6;
+static const field core::bool* binaryGreaterEqual = #C6;
+static const field core::bool* binaryGreater = #C5;
+static const field core::int* doubleTruncateDiv = #C3;
+static const field core::int* doubleTruncateDivZero = invalid-expression "Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* doubleTruncateDivNull = invalid-expression "Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.";
+static const field core::double* doubleNan = #C7;
+static const field core::int* doubleTruncateDivNaN = invalid-expression "Binary operator '84.2 ~/ NaN' results is Infinity or NaN.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = -2
+  #C2 = -3
+  #C3 = 42
+  #C4 = 42.0
+  #C5 = false
+  #C6 = true
+  #C7 = NaN
+}
diff --git a/pkg/front_end/testcases/general/constants/number_folds.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/number_folds.dart.strong.transformed.expect
new file mode 100644
index 0000000..f20a0df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/number_folds.dart.strong.transformed.expect
@@ -0,0 +1,156 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: '+' is not a prefix operator.
+// Try removing '+'.
+// const int unaryPlus = +2;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int shiftNegative2 = 2 >>> -1;
+//                              ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+// const int divZero = 2 / 0;
+//                       ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift2 = 84 >>> 1;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+// Try correcting the operator to an existing operator, or defining a '>>>' operator.
+// const int binaryShift3 = 21 >>> 64;
+//                             ^^^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:30: Error: Constant evaluation error:
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:30: Context: Binary operator '<<' on '2' requires non-negative operand, but was '-1'.
+// const int shiftNegative1 = 2 << -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:5:11: Context: While analyzing:
+// const int shiftNegative1 = 2 << -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:30: Error: Constant evaluation error:
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:30: Context: Binary operator '>>' on '2' requires non-negative operand, but was '-1'.
+// const int shiftNegative3 = 2 >> -1;
+//                              ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:7:11: Context: While analyzing:
+// const int shiftNegative3 = 2 >> -1;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:23: Error: Constant evaluation error:
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:23: Context: Binary operator '%' on '2' requires non-zero divisor, but divisor was '0'.
+// const int modZero = 2 % 0;
+//                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:8:11: Context: While analyzing:
+// const int modZero = 2 % 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:26: Error: Constant evaluation error:
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:26: Context: Binary operator '~/' on '2' requires non-zero divisor, but divisor was '0'.
+// const int intdivZero = 2 ~/ 0;
+//                          ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:10:11: Context: While analyzing:
+// const int intdivZero = 2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:40: Error: Constant evaluation error:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:40: Context: Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:37:11: Context: While analyzing:
+// const int doubleTruncateDivZero = 84.2 ~/ 0;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:40: Error: Constant evaluation error:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:40: Context: Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//                                        ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:38:11: Context: While analyzing:
+// const int doubleTruncateDivNull = 84.2 ~/ null;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:39: Error: Constant evaluation error:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:39: Context: Binary operator '84.2 ~/ NaN' results is Infinity or NaN.
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//                                       ^
+// pkg/front_end/testcases/general/constants/number_folds.dart:40:11: Context: While analyzing:
+// const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* shiftNegative1 = invalid-expression "Binary operator '<<' on '2' requires non-negative operand, but was '-1'.";
+static const field core::int* shiftNegative2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:6:30: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int shiftNegative2 = 2 >>> -1;
+                             ^^^";
+static const field core::int* shiftNegative3 = invalid-expression "Binary operator '>>' on '2' requires non-negative operand, but was '-1'.";
+static const field core::int* modZero = invalid-expression "Binary operator '%' on '2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* divZero = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:9:23: Error: A value of type 'double' can't be assigned to a variable of type 'int'.
+const int divZero = 2 / 0;
+                      ^";
+static const field core::int* intdivZero = invalid-expression "Binary operator '~/' on '2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* unaryMinus = #C1;
+static const field core::int* unaryTilde = #C2;
+static const field core::int* unaryPlus = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:13:23: Error: This couldn't be parsed.
+const int unaryPlus = +2;
+                      ^";
+static const field core::int* binaryPlus = #C3;
+static const field core::int* binaryMinus = #C3;
+static const field core::int* binaryTimes = #C3;
+static const field core::double* binaryDiv = #C4;
+static const field core::int* binaryTildeDiv = #C3;
+static const field core::int* binaryMod = #C3;
+static const field core::int* binaryOr = #C3;
+static const field core::int* binaryAnd = #C3;
+static const field core::int* binaryXor = #C3;
+static const field core::int* binaryShift1 = #C3;
+static const field core::int* binaryShift2 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:27:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift2 = 84 >>> 1;
+                            ^^^";
+static const field core::int* binaryShift3 = invalid-expression "pkg/front_end/testcases/general/constants/number_folds.dart:28:29: Error: The operator '>>>' isn't defined for the class 'int'.
+Try correcting the operator to an existing operator, or defining a '>>>' operator.
+const int binaryShift3 = 21 >>> 64;
+                            ^^^";
+static const field core::int* binaryShift4 = #C3;
+static const field core::bool* binaryLess = #C5;
+static const field core::bool* binaryLessEqual = #C6;
+static const field core::bool* binaryGreaterEqual = #C6;
+static const field core::bool* binaryGreater = #C5;
+static const field core::int* doubleTruncateDiv = #C3;
+static const field core::int* doubleTruncateDivZero = invalid-expression "Binary operator '~/' on '84.2' requires non-zero divisor, but divisor was '0'.";
+static const field core::int* doubleTruncateDivNull = invalid-expression "Binary operator '~/' on '84.2' requires operand of type 'num', but was of type 'Null'.";
+static const field core::double* doubleNan = #C7;
+static const field core::int* doubleTruncateDivNaN = invalid-expression "Binary operator '84.2 ~/ NaN' results is Infinity or NaN.";
+static method main() → dynamic {}
+
+constants  {
+  #C1 = -2
+  #C2 = -3
+  #C3 = 42
+  #C4 = 42.0
+  #C5 = false
+  #C6 = true
+  #C7 = NaN
+}
diff --git a/pkg/front_end/testcases/general/constants/number_folds.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/number_folds.dart.textual_outline.expect
new file mode 100644
index 0000000..20ada74
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/number_folds.dart.textual_outline.expect
@@ -0,0 +1,32 @@
+const int shiftNegative1 = 2 << -1;
+const int shiftNegative2 = 2 >>> -1;
+const int shiftNegative3 = 2 >> -1;
+const int modZero = 2 % 0;
+const int divZero = 2 / 0;
+const int intdivZero = 2 ~/ 0;
+const int unaryMinus = -2;
+const int unaryTilde = ~2;
+const int unaryPlus = +2;
+const int binaryPlus = 40 + 2;
+const int binaryMinus = 44 - 2;
+const int binaryTimes = 21 * 2;
+const double binaryDiv = 84 / 2;
+const int binaryTildeDiv = 84~/ 2;
+const int binaryMod = 85 % 43;
+const int binaryOr = 32 | 10;
+const int binaryAnd = 63 & 106;
+const int binaryXor = 63 ^ 21;
+const int binaryShift1 = 21 << 1;
+const int binaryShift2 = 84 >>> 1;
+const int binaryShift3 = 21 >>> 64;
+const int binaryShift4 = 84 >> 1;
+const bool binaryLess = 42 < 42;
+const bool binaryLessEqual = 42 <= 42;
+const bool binaryGreaterEqual = 42 >= 42;
+const bool binaryGreater = 42 > 42;
+const int doubleTruncateDiv = 84.2 ~/ 2;
+const int doubleTruncateDivZero = 84.2 ~/ 0;
+const int doubleTruncateDivNull = 84.2 ~/ null;
+const double doubleNan = 0/0;
+const int doubleTruncateDivNaN = 84.2 ~/ doubleNan;
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart
new file mode 100644
index 0000000..9eb86b4
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const int foo = 42 * 42;
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const String bar2 = "hello2" " 2" + bar;
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const blaSymbol = #_x;
+
+main() {
+  _x();
+  const bool.fromEnvironment("foo");
+  print(bar);
+}
+
+void _x() {
+  print(foo);
+  print(bar);
+}
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.outline.expect b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.outline.expect
new file mode 100644
index 0000000..f61a38d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* foo = 42.{core::num::*}(42);
+static const field core::String* bar = "hello ${const core::String::fromEnvironment("baz", defaultValue: "world")}!";
+static const field core::String* bar2 = "hello2 2".{core::String::+}(self::bar);
+static const field core::bool* baz = true && true && (false || true) && 42.{core::num::==}(21.{core::num::*}(4).{core::num::/}(2));
+static const field core::Symbol* blaSymbol = #_x;
+static method main() → dynamic
+  ;
+static method _x() → void
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///rudimentary_test_01.dart:5:20 -> IntConstant(1764)
+Evaluated: StringConcatenation @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello 42!")
+Evaluated: MethodInvocation @ org-dartlang-testcase:///rudimentary_test_01.dart:8:35 -> StringConstant("hello2 2hello 42!")
+Evaluated: LogicalExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:9:50 -> BoolConstant(true)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///rudimentary_test_01.dart:10:19 -> SymbolConstant(#_x)
+Extra constant evaluation: evaluated: 5, effectively constant: 5
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.expect b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.expect
new file mode 100644
index 0000000..f3b74df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* foo = #C1;
+static const field core::String* bar = #C2;
+static const field core::String* bar2 = #C3;
+static const field core::bool* baz = #C4;
+static const field core::Symbol* blaSymbol = #C5;
+static method main() → dynamic {
+  self::_x();
+  #C6;
+  core::print(#C2);
+}
+static method _x() → void {
+  core::print(#C1);
+  core::print(#C2);
+}
+
+constants  {
+  #C1 = 1764
+  #C2 = "hello 42!"
+  #C3 = "hello2 2hello 42!"
+  #C4 = true
+  #C5 = #org-dartlang-testcase:///rudimentary_test_01.dart::_x
+  #C6 = false
+}
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.transformed.expect
new file mode 100644
index 0000000..f3b74df
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int* foo = #C1;
+static const field core::String* bar = #C2;
+static const field core::String* bar2 = #C3;
+static const field core::bool* baz = #C4;
+static const field core::Symbol* blaSymbol = #C5;
+static method main() → dynamic {
+  self::_x();
+  #C6;
+  core::print(#C2);
+}
+static method _x() → void {
+  core::print(#C1);
+  core::print(#C2);
+}
+
+constants  {
+  #C1 = 1764
+  #C2 = "hello 42!"
+  #C3 = "hello2 2hello 42!"
+  #C4 = true
+  #C5 = #org-dartlang-testcase:///rudimentary_test_01.dart::_x
+  #C6 = false
+}
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline.expect
new file mode 100644
index 0000000..c369a44
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+const int foo = 42 * 42;
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const String bar2 = "hello2" " 2" + bar;
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const blaSymbol = #_x;
+main() {}
+void _x() {}
diff --git a/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fc42499
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/rudimentary_test_01.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const String bar2 = "hello2" " 2" + bar;
+const blaSymbol = #_x;
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const int foo = 42 * 42;
+main() {}
+void _x() {}
diff --git a/pkg/front_end/testcases/general/constants/various.dart b/pkg/front_end/testcases/general/constants/various.dart
new file mode 100644
index 0000000..a4ebf42
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Environment does not contain "bar".
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const bool barFromEnvOrNull =
+    const bool.fromEnvironment("bar", defaultValue: null);
+const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+const bool nullAwareOnNullTrue = barFromEnvOrNull ?? true;
+const bool nullAwareOnNullFalse = barFromEnvOrNull ?? false;
+const bool andOnFalse = nullAwareOnNullFalse && nullAwareOnNullTrue;
+const bool andOnFalse2 = nullAwareOnNullTrue && nullAwareOnNullFalse;
+const bool andOnNull = barFromEnvOrNull && true;
+const bool andOnNull2 = true && barFromEnvOrNull;
+const bool orOnNull = barFromEnvOrNull || true;
+const bool orOnNull2 = barFromEnvOrNull || false;
+const bool orOnNull3 = true || barFromEnvOrNull;
+const bool orOnNull4 = false || barFromEnvOrNull;
+
+const String barFromEnvString = const String.fromEnvironment("bar");
+const String barFromEnvOrNullString =
+    const String.fromEnvironment("bar", defaultValue: null);
+const String barFromEnvOrActualString =
+    const String.fromEnvironment("bar", defaultValue: "hello");
+const String nullFromEnvString =
+    const String.fromEnvironment(barFromEnvOrNullString);
+
+const bool barFromEnvBool = const bool.fromEnvironment("bar");
+const bool barFromEnvOrNullBool =
+    const bool.fromEnvironment("bar", defaultValue: null);
+const bool barFromEnvOrActualBool =
+    const bool.fromEnvironment("bar", defaultValue: true);
+const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+
+const int barFromEnvInt = const int.fromEnvironment("bar");
+const int barFromEnvOrNullInt =
+    const int.fromEnvironment("bar", defaultValue: null);
+const int barFromEnvOrActualInt =
+    const int.fromEnvironment("bar", defaultValue: 42);
+const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+
+// Environment does contain "baz" (value '42', i.e. neither true nor false).
+const bool bazFromEnv = const bool.fromEnvironment("baz");
+const bool hasBazEnv = const bool.hasEnvironment("baz");
+const int bazFromEnvAsInt = const int.fromEnvironment("baz");
+const String bazFromEnvAsString = const String.fromEnvironment("baz");
+
+// Environment does contain "bazTrue" (value 'true') and
+// "bazFalse" (value 'false').
+const bool bazTrueFromEnv = const bool.fromEnvironment("bazTrue");
+const bool bazFalseFromEnv = const bool.fromEnvironment("bazFalse");
+
+const bool trueBool = true;
+const bool falseBool = false;
+const bool binaryOnBoolCaret = trueBool ^ falseBool;
+const bool binaryOnBoolAmpersand = trueBool & falseBool;
+const bool binaryOnBoolBar = trueBool | falseBool;
+const bool binaryOnBoolBar2 = falseBool | trueBool;
+
+const dynamic willBeDouble = const bool.fromEnvironment("foo") ? 42 : 42.42;
+const binaryOnDouble = willBeDouble << 2;
+const dynamic willBeInt = const bool.fromEnvironment("foo") ? 42.42 : 42;
+const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+const binaryOnIntWithDoubleOK = willBeInt + willBeDouble;
+const binaryOnIntWithString = willBeInt << "hello";
+const dynamic willBeString =
+    const bool.fromEnvironment("foo") ? 42.42 : "hello";
+const binaryOnStringWithStringOK = willBeString + " world";
+const binaryOnStringWithInt = willBeString + willBeInt;
+const binaryOnStringWithStringBad = willBeString - " world";
+
+var x = 1;
+const x1 = --x;
+const x2 = ++x;
+const x3 = x--;
+const x4 = x++;
+
+const y = 1;
+const y1 = --y;
+const y2 = ++y;
+const y3 = y--;
+const y4 = y++;
+
+abstract class AbstractClass {}
+
+abstract class AbstractClassWithConstructor {
+  const AbstractClassWithConstructor();
+
+  int foo();
+}
+
+AbstractClassWithConstructor abstractClassWithConstructor =
+    const AbstractClassWithConstructor();
+
+class NotAbstractClass {
+  @AbstractClass()
+  Object foo;
+
+  @AbstractClassWithConstructor()
+  Object bar;
+}
+
+class Foo {
+  final int x;
+  final int y;
+  const Foo(int x)
+      : this.x = x,
+        this.y = "hello".length;
+}
+
+class ExtendsFoo1 extends Foo {
+  // No constructor.
+}
+
+const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+
+class ExtendsFoo2 extends Foo {
+  const ExtendsFoo2();
+}
+
+const ExtendsFoo2 extendsFoo2 = const ExtendsFoo2();
+
+const Foo foo1 = const Foo(42);
+const Foo foo2 = const Foo(42);
+const bool foosIdentical = identical(foo1, foo2);
+const bool foosEqual = foo1 == foo2;
+const Symbol barFoo = const Symbol("Foo");
+const Symbol barFooEqual = const Symbol("Foo=");
+const Symbol tripleShiftSymbol = const Symbol(">>>");
+const Symbol symbolWithDots = const Symbol("I.Have.Dots");
+
+const int circularity1 = circularity2;
+const int circularity2 = circularity3;
+const int circularity3 = circularity4;
+const int circularity4 = circularity1;
+
+const function_const = () {};
+var function_var = () {};
+
+class ConstClassWithFailingAssertWithEmptyMessage {
+  const ConstClassWithFailingAssertWithEmptyMessage() : assert(false, "");
+}
+
+ConstClassWithFailingAssertWithEmptyMessage failedAssertEmptyMessage =
+    const ConstClassWithFailingAssertWithEmptyMessage();
+
+class ClassWithTypeArguments<E, F, G> {
+  const ClassWithTypeArguments(E e, F f, G g);
+}
+
+const ClassWithTypeArguments classWithTypeArguments1 =
+    const ClassWithTypeArguments<int, int, int>(42, 42, 42);
+const ClassWithTypeArguments classWithTypeArguments2 =
+    const ClassWithTypeArguments(42, 42, 42);
+const bool classWithTypeArgumentsIdentical =
+    identical(classWithTypeArguments1, classWithTypeArguments2);
+
+class ClassWithNonEmptyConstConstructor {
+  const ClassWithNonEmptyConstConstructor() {
+    print("hello");
+  }
+}
+
+ClassWithNonEmptyConstConstructor classWithNonEmptyConstConstructor =
+    const ClassWithNonEmptyConstConstructor();
+
+class ConstClassWithFinalFields1 {
+  const ConstClassWithFinalFields1();
+
+  final x = 1;
+}
+
+class ConstClassWithFinalFields2 {
+  const ConstClassWithFinalFields2();
+
+  final y = 1;
+  final z1 = y;
+  final z2 = x;
+}
+
+ConstClassWithFinalFields2 constClassWithFinalFields =
+    const ConstClassWithFinalFields2();
+
+const zeroPointZeroIdentical = identical(0.0, 0.0);
+const zeroPointZeroIdenticalToZero = identical(0.0, 0);
+const zeroIdenticalToZeroPointZero = identical(0, 0.0);
+const nanIdentical = identical(0 / 0, 0 / 0);
+
+const zeroPointZeroEqual = 0.0 == 0.0;
+const zeroPointZeroEqualToZero = 0.0 == 0;
+const zeroEqualToZeroPointZero = 0 == 0.0;
+const nanEqual = 0 / 0 == 0 / 0;
+
+T id1<T>(T t) => t;
+T id2<T>(T t) => t;
+
+const dynamic willBecomeNull = const bool.fromEnvironment("foo") ? id1 : null;
+
+const int Function(int) willBecomeNullToo =
+    const bool.fromEnvironment("foo") ? id1 : willBecomeNull;
+const int Function(int) partialInstantiation =
+    const bool.fromEnvironment("foo") ? willBecomeNull : id1;
+
+const bool yBool = true;
+const bool zBool = !yBool;
+
+const maybeInt = bool.fromEnvironment("foo") ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const maybeInt2 = zBool ? 42 : true;
+const bool isItInt2 = maybeInt2 is int ? true : false;
+const maybeInt3 = zBool ? 42 : null;
+const bool isItInt3 = maybeInt3 is int ? true : false;
+
+main() {
+  print(barFromEnv);
+  print(hasBarEnv);
+}
diff --git a/pkg/front_end/testcases/general/constants/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/various.dart.outline.expect
new file mode 100644
index 0000000..055199f
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart.outline.expect
@@ -0,0 +1,456 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/various.dart:162:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const ClassWithNonEmptyConstConstructor() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:76:14: Error: Not a constant expression.
+// const x1 = --x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:77:14: Error: Not a constant expression.
+// const x2 = ++x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:78:12: Error: Not a constant expression.
+// const x3 = x--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:79:12: Error: Not a constant expression.
+// const x4 = x++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+// const y1 = --y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+// const y2 = ++y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+// const y3 = y--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+// const y4 = y++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+// const function_const = () {};
+//                        ^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Can't access 'this' in a field initializer to read 'y'.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: The class 'AbstractClass' is abstract and can't be instantiated.
+//   @AbstractClass()
+//    ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClass()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: The class 'AbstractClassWithConstructor' is abstract and can't be instantiated.
+//   @AbstractClassWithConstructor()
+//    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClassWithConstructor()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+// const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+//                                       ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+//   const ExtendsFoo2();
+//         ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Not a constant expression.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:181:14: Error: Not a constant expression.
+//   final z2 = x;
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class AbstractClass extends core::Object {
+  synthetic constructor •() → self::AbstractClass*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class AbstractClassWithConstructor extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::AbstractClassWithConstructor*
+    : super core::Object::•()
+    ;
+  abstract method foo() → core::int*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class NotAbstractClass extends core::Object {
+  @throw invalid-expression "pkg/front_end/testcases/general/constants/various.dart:99:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  @AbstractClass()
+   ^"
+  field core::Object* foo;
+  @throw invalid-expression "pkg/front_end/testcases/general/constants/various.dart:102:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  @AbstractClassWithConstructor()
+   ^"
+  field core::Object* bar;
+  synthetic constructor •() → self::NotAbstractClass*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  final field core::int* y;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, self::Foo::y = "hello".{core::String::length}, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ExtendsFoo1 extends self::Foo {
+  synthetic constructor •() → self::ExtendsFoo1*
+    ;
+}
+class ExtendsFoo2 extends self::Foo /*hasConstConstructor*/  {
+  const constructor •() → self::ExtendsFoo2*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+  const ExtendsFoo2();
+        ^^^^^^^^^^^"
+    ;
+}
+class ConstClassWithFailingAssertWithEmptyMessage extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::ConstClassWithFailingAssertWithEmptyMessage*
+    : assert(false, ""), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithTypeArguments<E extends core::Object* = dynamic, F extends core::Object* = dynamic, G extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::ClassWithTypeArguments::E* e, self::ClassWithTypeArguments::F* f, self::ClassWithTypeArguments::G* g) → self::ClassWithTypeArguments<self::ClassWithTypeArguments::E*, self::ClassWithTypeArguments::F*, self::ClassWithTypeArguments::G*>*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithNonEmptyConstConstructor extends core::Object {
+  constructor •() → self::ClassWithNonEmptyConstConstructor*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields1 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x = 1;
+  const constructor •() → self::ConstClassWithFinalFields1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields2 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* y = 1;
+  final field dynamic z1 = this.{self::ConstClassWithFinalFields2::y};
+  final field core::int* z2 = self::x;
+  const constructor •() → self::ConstClassWithFinalFields2*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::bool* barFromEnv = const core::bool::fromEnvironment("bar");
+static const field core::bool* hasBarEnv = const core::bool::hasEnvironment("bar");
+static const field core::bool* barFromEnvOrNull = const core::bool::fromEnvironment("bar", defaultValue: null);
+static const field core::bool* notBarFromEnvOrNull = !self::barFromEnvOrNull;
+static const field core::bool* conditionalOnNull = self::barFromEnvOrNull ?{core::bool*} true : false;
+static const field core::bool* nullAwareOnNullTrue = let final core::bool* #t2 = self::barFromEnvOrNull in #t2.{core::Object::==}(null) ?{core::bool*} true : #t2;
+static const field core::bool* nullAwareOnNullFalse = let final core::bool* #t3 = self::barFromEnvOrNull in #t3.{core::Object::==}(null) ?{core::bool*} false : #t3;
+static const field core::bool* andOnFalse = self::nullAwareOnNullFalse && self::nullAwareOnNullTrue;
+static const field core::bool* andOnFalse2 = self::nullAwareOnNullTrue && self::nullAwareOnNullFalse;
+static const field core::bool* andOnNull = self::barFromEnvOrNull && true;
+static const field core::bool* andOnNull2 = true && self::barFromEnvOrNull;
+static const field core::bool* orOnNull = self::barFromEnvOrNull || true;
+static const field core::bool* orOnNull2 = self::barFromEnvOrNull || false;
+static const field core::bool* orOnNull3 = true || self::barFromEnvOrNull;
+static const field core::bool* orOnNull4 = false || self::barFromEnvOrNull;
+static const field core::String* barFromEnvString = const core::String::fromEnvironment("bar");
+static const field core::String* barFromEnvOrNullString = const core::String::fromEnvironment("bar", defaultValue: null);
+static const field core::String* barFromEnvOrActualString = const core::String::fromEnvironment("bar", defaultValue: "hello");
+static const field core::String* nullFromEnvString = const core::String::fromEnvironment(self::barFromEnvOrNullString);
+static const field core::bool* barFromEnvBool = const core::bool::fromEnvironment("bar");
+static const field core::bool* barFromEnvOrNullBool = const core::bool::fromEnvironment("bar", defaultValue: null);
+static const field core::bool* barFromEnvOrActualBool = const core::bool::fromEnvironment("bar", defaultValue: true);
+static const field core::bool* nullFromEnvBool = const core::bool::fromEnvironment(self::barFromEnvOrNullString);
+static const field core::int* barFromEnvInt = const core::int::fromEnvironment("bar");
+static const field core::int* barFromEnvOrNullInt = const core::int::fromEnvironment("bar", defaultValue: null);
+static const field core::int* barFromEnvOrActualInt = const core::int::fromEnvironment("bar", defaultValue: 42);
+static const field core::int* nullFromEnvInt = const core::int::fromEnvironment(self::barFromEnvOrNullString);
+static const field core::bool* bazFromEnv = const core::bool::fromEnvironment("baz");
+static const field core::bool* hasBazEnv = const core::bool::hasEnvironment("baz");
+static const field core::int* bazFromEnvAsInt = const core::int::fromEnvironment("baz");
+static const field core::String* bazFromEnvAsString = const core::String::fromEnvironment("baz");
+static const field core::bool* bazTrueFromEnv = const core::bool::fromEnvironment("bazTrue");
+static const field core::bool* bazFalseFromEnv = const core::bool::fromEnvironment("bazFalse");
+static const field core::bool* trueBool = true;
+static const field core::bool* falseBool = false;
+static const field core::bool* binaryOnBoolCaret = self::trueBool.{core::bool::^}(self::falseBool);
+static const field core::bool* binaryOnBoolAmpersand = self::trueBool.{core::bool::&}(self::falseBool);
+static const field core::bool* binaryOnBoolBar = self::trueBool.{core::bool::|}(self::falseBool);
+static const field core::bool* binaryOnBoolBar2 = self::falseBool.{core::bool::|}(self::trueBool);
+static const field dynamic willBeDouble = const core::bool::fromEnvironment("foo") ?{core::num*} 42 : 42.42;
+static const field dynamic binaryOnDouble = self::willBeDouble.<<(2);
+static const field dynamic willBeInt = const core::bool::fromEnvironment("foo") ?{core::num*} 42.42 : 42;
+static const field dynamic binaryOnIntWithDoubleBad = self::willBeInt.<<(self::willBeDouble);
+static const field dynamic binaryOnIntWithDoubleOK = self::willBeInt.+(self::willBeDouble);
+static const field dynamic binaryOnIntWithString = self::willBeInt.<<("hello");
+static const field dynamic willBeString = const core::bool::fromEnvironment("foo") ?{core::Object*} 42.42 : "hello";
+static const field dynamic binaryOnStringWithStringOK = self::willBeString.+(" world");
+static const field dynamic binaryOnStringWithInt = self::willBeString.+(self::willBeInt);
+static const field dynamic binaryOnStringWithStringBad = self::willBeString.-(" world");
+static field core::int* x;
+static const field core::int* x1 = self::x = self::x.{core::num::-}(1);
+static const field core::int* x2 = self::x = self::x.{core::num::+}(1);
+static const field core::int* x3 = let final core::int* #t4 = self::x in let final core::int* #t5 = self::x = #t4.{core::num::-}(1) in #t4;
+static const field core::int* x4 = let final core::int* #t6 = self::x in let final core::int* #t7 = self::x = #t6.{core::num::+}(1) in #t6;
+static const field core::int* y = 1;
+static const field dynamic y1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+const y1 = --y;
+             ^";
+static const field dynamic y2 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+const y2 = ++y;
+             ^";
+static const field core::int* y3 = let final core::int* #t8 = self::y in let final dynamic #t9 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+const y3 = y--;
+           ^" in #t8;
+static const field core::int* y4 = let final core::int* #t10 = self::y in let final dynamic #t11 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+const y4 = y++;
+           ^" in #t10;
+static field self::AbstractClassWithConstructor* abstractClassWithConstructor;
+static const field self::ExtendsFoo1* extendsFoo1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+                                      ^^^^^^^^^^^" as{TypeError,ForDynamic} self::ExtendsFoo1*;
+static const field self::ExtendsFoo2* extendsFoo2 = const self::ExtendsFoo2::•();
+static const field self::Foo* foo1 = const self::Foo::•(42);
+static const field self::Foo* foo2 = const self::Foo::•(42);
+static const field core::bool* foosIdentical = core::identical(self::foo1, self::foo2);
+static const field core::bool* foosEqual = self::foo1.{self::Foo::==}(self::foo2);
+static const field core::Symbol* barFoo = const _in::Symbol::•("Foo");
+static const field core::Symbol* barFooEqual = const _in::Symbol::•("Foo=");
+static const field core::Symbol* tripleShiftSymbol = const _in::Symbol::•(">>>");
+static const field core::Symbol* symbolWithDots = const _in::Symbol::•("I.Have.Dots");
+static const field core::int* circularity1 = self::circularity2;
+static const field core::int* circularity2 = self::circularity3;
+static const field core::int* circularity3 = self::circularity4;
+static const field core::int* circularity4 = self::circularity1;
+static const field dynamic function_const = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+const function_const = () {};
+                       ^^";
+static field () →* core::Null? function_var;
+static field self::ConstClassWithFailingAssertWithEmptyMessage* failedAssertEmptyMessage;
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments1 = const self::ClassWithTypeArguments::•<core::int*, core::int*, core::int*>(42, 42, 42);
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments2 = const self::ClassWithTypeArguments::•<dynamic, dynamic, dynamic>(42, 42, 42);
+static const field core::bool* classWithTypeArgumentsIdentical = core::identical(self::classWithTypeArguments1, self::classWithTypeArguments2);
+static field self::ClassWithNonEmptyConstConstructor* classWithNonEmptyConstConstructor;
+static field self::ConstClassWithFinalFields2* constClassWithFinalFields;
+static const field core::bool* zeroPointZeroIdentical = core::identical(0.0, 0.0);
+static const field core::bool* zeroPointZeroIdenticalToZero = core::identical(0.0, 0);
+static const field core::bool* zeroIdenticalToZeroPointZero = core::identical(0, 0.0);
+static const field core::bool* nanIdentical = core::identical(0.{core::num::/}(0), 0.{core::num::/}(0));
+static const field core::bool* zeroPointZeroEqual = 0.0.{core::num::==}(0.0);
+static const field core::bool* zeroPointZeroEqualToZero = 0.0.{core::num::==}(0);
+static const field core::bool* zeroEqualToZeroPointZero = 0.{core::num::==}(0.0);
+static const field core::bool* nanEqual = 0.{core::num::/}(0).{core::num::==}(0.{core::num::/}(0));
+static const field dynamic willBecomeNull = const core::bool::fromEnvironment("foo") ?{<T extends core::Object* = dynamic>(T*) →* T*} self::id1 : null;
+static const field (core::int*) →* core::int* willBecomeNullToo = (const core::bool::fromEnvironment("foo") ?{dynamic} self::id1<core::int*> : self::willBecomeNull) as{TypeError,ForDynamic} (core::int*) →* core::int*;
+static const field (core::int*) →* core::int* partialInstantiation = (const core::bool::fromEnvironment("foo") ?{dynamic} self::willBecomeNull : self::id1<core::int*>) as{TypeError,ForDynamic} (core::int*) →* core::int*;
+static const field core::bool* yBool = true;
+static const field core::bool* zBool = !self::yBool;
+static const field core::Object* maybeInt = const core::bool::fromEnvironment("foo") ?{core::Object*} 42 : true;
+static const field core::bool* isItInt = self::maybeInt is core::int* ?{core::bool*} true : false;
+static const field core::Object* maybeInt2 = self::zBool ?{core::Object*} 42 : true;
+static const field core::bool* isItInt2 = self::maybeInt2 is core::int* ?{core::bool*} true : false;
+static const field core::int* maybeInt3 = self::zBool ?{core::int*} 42 : null;
+static const field core::bool* isItInt3 = self::maybeInt3 is core::int* ?{core::bool*} true : false;
+static method id1<T extends core::Object* = dynamic>(self::id1::T* t) → self::id1::T*
+  ;
+static method id2<T extends core::Object* = dynamic>(self::id2::T* t) → self::id2::T*
+  ;
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: PropertyGet @ org-dartlang-testcase:///various.dart:111:26 -> IntConstant(5)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:6:31 -> BoolConstant(false)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:7:30 -> BoolConstant(false)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:9:11 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:10:35 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:11:32 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///various.dart:12:51 -> BoolConstant(true)
+Evaluated: Let @ org-dartlang-testcase:///various.dart:13:52 -> BoolConstant(false)
+Evaluated: LogicalExpression @ org-dartlang-testcase:///various.dart:14:46 -> BoolConstant(false)
+Evaluated: LogicalExpression @ org-dartlang-testcase:///various.dart:15:46 -> BoolConstant(false)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:16:24 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:17:33 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:18:23 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:19:24 -> NullConstant(null)
+Evaluated: LogicalExpression @ org-dartlang-testcase:///various.dart:20:29 -> BoolConstant(true)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:21:33 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:23:39 -> StringConstant("")
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:25:11 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:27:11 -> StringConstant("hello")
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:29:34 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:31:35 -> BoolConstant(false)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:33:11 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:35:11 -> BoolConstant(true)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:36:57 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:38:33 -> IntConstant(0)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:40:11 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:42:11 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:43:54 -> NullConstant(null)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:46:31 -> BoolConstant(false)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:47:30 -> BoolConstant(true)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:48:35 -> IntConstant(42)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:49:41 -> StringConstant("42")
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:53:35 -> BoolConstant(true)
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:54:36 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:58:41 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:59:45 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:60:39 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:61:41 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:63:64 -> DoubleConstant(42.42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:64:24 -> DoubleConstant(42.42)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:65:61 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:66:34 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:66:47 -> DoubleConstant(42.42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:67:43 -> DoubleConstant(84.42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:68:31 -> IntConstant(42)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:70:39 -> StringConstant("hello")
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:71:49 -> StringConstant("hello world")
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:72:31 -> StringConstant("hello")
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:72:46 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:73:37 -> StringConstant("hello")
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:84:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///various.dart:84:12 -> IntConstant(1)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:85:12 -> IntConstant(1)
+Evaluated: VariableGet @ org-dartlang-testcase:///various.dart:85:12 -> IntConstant(1)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:126:24 -> InstanceConstant(const Foo{Foo.x: 42, Foo.y: 5})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:127:24 -> InstanceConstant(const Foo{Foo.x: 42, Foo.y: 5})
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:128:28 -> BoolConstant(true)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:129:24 -> InstanceConstant(const Foo{Foo.x: 42, Foo.y: 5})
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:129:32 -> InstanceConstant(const Foo{Foo.x: 42, Foo.y: 5})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:130:29 -> SymbolConstant(#Foo)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:131:34 -> SymbolConstant(#Foo=)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:132:40 -> SymbolConstant(#>>>)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:133:37 -> SymbolConstant(#I.Have.Dots)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:155:11 -> InstanceConstant(const ClassWithTypeArguments<int*, int*, int*>{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:157:11 -> InstanceConstant(const ClassWithTypeArguments<dynamic, dynamic, dynamic>{})
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:159:5 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:187:32 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:188:38 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:189:38 -> BoolConstant(false)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various.dart:190:22 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:192:32 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:193:38 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:194:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///various.dart:195:24 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:200:66 -> NullConstant(null)
+Evaluated: AsExpression @ org-dartlang-testcase:///various.dart:203:39 -> NullConstant(null)
+Evaluated: AsExpression @ org-dartlang-testcase:///various.dart:205:39 -> PartialInstantiationConstant(id1<int*>)
+Evaluated: Not @ org-dartlang-testcase:///various.dart:208:20 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:210:46 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:211:38 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:212:25 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:213:40 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:214:25 -> NullConstant(null)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:215:40 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 136, effectively constant: 84
diff --git a/pkg/front_end/testcases/general/constants/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/various.dart.strong.expect
new file mode 100644
index 0000000..a6df3e4
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart.strong.expect
@@ -0,0 +1,626 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/various.dart:162:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const ClassWithNonEmptyConstConstructor() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:76:14: Error: Not a constant expression.
+// const x1 = --x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:77:14: Error: Not a constant expression.
+// const x2 = ++x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:78:12: Error: Not a constant expression.
+// const x3 = x--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:79:12: Error: Not a constant expression.
+// const x4 = x++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+// const y1 = --y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+// const y2 = ++y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+// const y3 = y--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+// const y4 = y++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+// const function_const = () {};
+//                        ^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Can't access 'this' in a field initializer to read 'y'.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: The class 'AbstractClass' is abstract and can't be instantiated.
+//   @AbstractClass()
+//    ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClass()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: The class 'AbstractClassWithConstructor' is abstract and can't be instantiated.
+//   @AbstractClassWithConstructor()
+//    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClassWithConstructor()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+// const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+//                                       ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+//   const ExtendsFoo2();
+//         ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Not a constant expression.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:181:14: Error: Not a constant expression.
+//   final z2 = x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:96:11: Error: The class 'AbstractClassWithConstructor' is abstract and can't be instantiated.
+//     const AbstractClassWithConstructor();
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:96:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//     const AbstractClassWithConstructor();
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:168:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//     const ClassWithNonEmptyConstConstructor();
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:114:7: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+// class ExtendsFoo1 extends Foo {
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:10:34: Error: Constant evaluation error:
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:10:34: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:10:12: Context: While analyzing:
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:11:49: Error: Constant evaluation error:
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//                                                 ^
+// pkg/front_end/testcases/general/constants/various.dart:11:32: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//                                ^
+// pkg/front_end/testcases/general/constants/various.dart:11:12: Context: While analyzing:
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:16:41: Error: Constant evaluation error:
+// const bool andOnNull = barFromEnvOrNull && true;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:16:41: Context: The method '&&' can't be invoked on 'null' in a constant expression.
+// const bool andOnNull = barFromEnvOrNull && true;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:16:12: Context: While analyzing:
+// const bool andOnNull = barFromEnvOrNull && true;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:17:30: Error: Constant evaluation error:
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:17:30: Context: Binary operator '&&' on 'true' requires operand of type 'bool', but was of type 'Null'.
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:17:12: Context: While analyzing:
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:18:40: Error: Constant evaluation error:
+// const bool orOnNull = barFromEnvOrNull || true;
+//                                        ^
+// pkg/front_end/testcases/general/constants/various.dart:18:40: Context: The method '||' can't be invoked on 'null' in a constant expression.
+// const bool orOnNull = barFromEnvOrNull || true;
+//                                        ^
+// pkg/front_end/testcases/general/constants/various.dart:18:12: Context: While analyzing:
+// const bool orOnNull = barFromEnvOrNull || true;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:19:41: Error: Constant evaluation error:
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:19:41: Context: The method '||' can't be invoked on 'null' in a constant expression.
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:19:12: Context: While analyzing:
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:21:30: Error: Constant evaluation error:
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:21:30: Context: Binary operator '||' on 'false' requires operand of type 'bool', but was of type 'Null'.
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:21:12: Context: While analyzing:
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:29:11: Error: Constant evaluation error:
+//     const String.fromEnvironment(barFromEnvOrNullString);
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:29:11: Context: Null value during constant evaluation.
+//     const String.fromEnvironment(barFromEnvOrNullString);
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:28:14: Context: While analyzing:
+// const String nullFromEnvString =
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:36:36: Error: Constant evaluation error:
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//                                    ^
+// pkg/front_end/testcases/general/constants/various.dart:36:36: Context: Null value during constant evaluation.
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//                                    ^
+// pkg/front_end/testcases/general/constants/various.dart:36:12: Context: While analyzing:
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:43:34: Error: Constant evaluation error:
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:43:34: Context: Null value during constant evaluation.
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:43:11: Context: While analyzing:
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:64:37: Error: Constant evaluation error:
+// const binaryOnDouble = willBeDouble << 2;
+//                                     ^
+// pkg/front_end/testcases/general/constants/various.dart:64:37: Context: Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.
+// const binaryOnDouble = willBeDouble << 2;
+//                                     ^
+// pkg/front_end/testcases/general/constants/various.dart:64:7: Context: While analyzing:
+// const binaryOnDouble = willBeDouble << 2;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:66:44: Error: Constant evaluation error:
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:66:44: Context: Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:66:7: Context: While analyzing:
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:68:41: Error: Constant evaluation error:
+// const binaryOnIntWithString = willBeInt << "hello";
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:68:41: Context: Binary operator '<<' on '42' requires operand of type 'num', but was of type 'String'.
+// const binaryOnIntWithString = willBeInt << "hello";
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:68:7: Context: While analyzing:
+// const binaryOnIntWithString = willBeInt << "hello";
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:72:44: Error: Constant evaluation error:
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:72:44: Context: Binary operator '+' on '"hello"' requires operand of type 'String', but was of type 'int'.
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:72:7: Context: While analyzing:
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:73:50: Error: Constant evaluation error:
+// const binaryOnStringWithStringBad = willBeString - " world";
+//                                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:73:50: Context: The method '-' can't be invoked on '"hello"' in a constant expression.
+// const binaryOnStringWithStringBad = willBeString - " world";
+//                                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:73:7: Context: While analyzing:
+// const binaryOnStringWithStringBad = willBeString - " world";
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:78:13: Error: Constant evaluation error:
+// const x3 = x--;
+//             ^
+// pkg/front_end/testcases/general/constants/various.dart:78:12: Context: The invocation of 'x' is not allowed in a constant expression.
+// const x3 = x--;
+//            ^
+// pkg/front_end/testcases/general/constants/various.dart:78:7: Context: While analyzing:
+// const x3 = x--;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:79:13: Error: Constant evaluation error:
+// const x4 = x++;
+//             ^
+// pkg/front_end/testcases/general/constants/various.dart:79:12: Context: The invocation of 'x' is not allowed in a constant expression.
+// const x4 = x++;
+//            ^
+// pkg/front_end/testcases/general/constants/various.dart:79:7: Context: While analyzing:
+// const x4 = x++;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:129:29: Error: Constant evaluation error:
+// const bool foosEqual = foo1 == foo2;
+//                             ^
+// pkg/front_end/testcases/general/constants/various.dart:129:29: Context: Binary operator '==' requires receiver constant 'Foo {x: 42, y: 5}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type 'Foo'.
+//  - 'Foo' is from 'pkg/front_end/testcases/general/constants/various.dart'.
+// const bool foosEqual = foo1 == foo2;
+//                             ^
+// pkg/front_end/testcases/general/constants/various.dart:129:12: Context: While analyzing:
+// const bool foosEqual = foo1 == foo2;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:135:26: Error: Constant evaluation error:
+// const int circularity1 = circularity2;
+//                          ^
+// pkg/front_end/testcases/general/constants/various.dart:135:26: Context: Constant expression depends on itself.
+// const int circularity1 = circularity2;
+//                          ^
+// pkg/front_end/testcases/general/constants/various.dart:135:11: Context: While analyzing:
+// const int circularity1 = circularity2;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:148:11: Error: Constant evaluation error:
+//     const ConstClassWithFailingAssertWithEmptyMessage();
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:144:64: Context: This assertion failed with message: (empty)
+//   const ConstClassWithFailingAssertWithEmptyMessage() : assert(false, "");
+//                                                                ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:185:11: Error: Constant evaluation error:
+//     const ConstClassWithFinalFields2();
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:181:14: Context: The invocation of 'x' is not allowed in a constant expression.
+//   final z2 = x;
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class AbstractClass extends core::Object {
+  synthetic constructor •() → self::AbstractClass*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class AbstractClassWithConstructor extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::AbstractClassWithConstructor*
+    : super core::Object::•()
+    ;
+  abstract method foo() → core::int*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class NotAbstractClass extends core::Object {
+  @invalid-expression "Constant evaluation has no support for Throw!"
+  field core::Object* foo = null;
+  @invalid-expression "Constant evaluation has no support for Throw!"
+  field core::Object* bar = null;
+  synthetic constructor •() → self::NotAbstractClass*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  final field core::int* y;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, self::Foo::y = "hello".{core::String::length}, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ExtendsFoo1 extends self::Foo {
+  synthetic constructor •() → self::ExtendsFoo1*
+    : invalid-initializer
+    ;
+}
+class ExtendsFoo2 extends self::Foo /*hasConstConstructor*/  {
+  const constructor •() → self::ExtendsFoo2*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+  const ExtendsFoo2();
+        ^^^^^^^^^^^"
+    ;
+}
+class ConstClassWithFailingAssertWithEmptyMessage extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::ConstClassWithFailingAssertWithEmptyMessage*
+    : assert(false, ""), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithTypeArguments<E extends core::Object* = dynamic, F extends core::Object* = dynamic, G extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::ClassWithTypeArguments::E* e, self::ClassWithTypeArguments::F* f, self::ClassWithTypeArguments::G* g) → self::ClassWithTypeArguments<self::ClassWithTypeArguments::E*, self::ClassWithTypeArguments::F*, self::ClassWithTypeArguments::G*>*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithNonEmptyConstConstructor extends core::Object {
+  constructor •() → self::ClassWithNonEmptyConstConstructor*
+    : super core::Object::•() {
+    core::print("hello");
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields1 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x = 1;
+  const constructor •() → self::ConstClassWithFinalFields1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields2 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* y = 1;
+  final field dynamic z1 = this.{self::ConstClassWithFinalFields2::y};
+  final field core::int* z2 = self::x;
+  const constructor •() → self::ConstClassWithFinalFields2*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::bool* barFromEnv = #C1;
+static const field core::bool* hasBarEnv = #C1;
+static const field core::bool* barFromEnvOrNull = #C2;
+static const field core::bool* notBarFromEnvOrNull = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field core::bool* conditionalOnNull = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field core::bool* nullAwareOnNullTrue = #C3;
+static const field core::bool* nullAwareOnNullFalse = #C1;
+static const field core::bool* andOnFalse = #C1;
+static const field core::bool* andOnFalse2 = #C1;
+static const field core::bool* andOnNull = invalid-expression "The method '&&' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* andOnNull2 = invalid-expression "Binary operator '&&' on 'true' requires operand of type 'bool', but was of type 'Null'.";
+static const field core::bool* orOnNull = invalid-expression "The method '||' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* orOnNull2 = invalid-expression "The method '||' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* orOnNull3 = #C3;
+static const field core::bool* orOnNull4 = invalid-expression "Binary operator '||' on 'false' requires operand of type 'bool', but was of type 'Null'.";
+static const field core::String* barFromEnvString = #C4;
+static const field core::String* barFromEnvOrNullString = #C2;
+static const field core::String* barFromEnvOrActualString = #C5;
+static const field core::String* nullFromEnvString = invalid-expression "Null value during constant evaluation.";
+static const field core::bool* barFromEnvBool = #C1;
+static const field core::bool* barFromEnvOrNullBool = #C2;
+static const field core::bool* barFromEnvOrActualBool = #C3;
+static const field core::bool* nullFromEnvBool = invalid-expression "Null value during constant evaluation.";
+static const field core::int* barFromEnvInt = #C6;
+static const field core::int* barFromEnvOrNullInt = #C2;
+static const field core::int* barFromEnvOrActualInt = #C7;
+static const field core::int* nullFromEnvInt = invalid-expression "Null value during constant evaluation.";
+static const field core::bool* bazFromEnv = #C1;
+static const field core::bool* hasBazEnv = #C3;
+static const field core::int* bazFromEnvAsInt = #C7;
+static const field core::String* bazFromEnvAsString = #C8;
+static const field core::bool* bazTrueFromEnv = #C3;
+static const field core::bool* bazFalseFromEnv = #C1;
+static const field core::bool* trueBool = #C3;
+static const field core::bool* falseBool = #C1;
+static const field core::bool* binaryOnBoolCaret = #C3;
+static const field core::bool* binaryOnBoolAmpersand = #C1;
+static const field core::bool* binaryOnBoolBar = #C3;
+static const field core::bool* binaryOnBoolBar2 = #C3;
+static const field dynamic willBeDouble = #C9;
+static const field dynamic binaryOnDouble = invalid-expression "Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic willBeInt = #C7;
+static const field dynamic binaryOnIntWithDoubleBad = invalid-expression "Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic binaryOnIntWithDoubleOK = #C10;
+static const field dynamic binaryOnIntWithString = invalid-expression "Binary operator '<<' on '42' requires operand of type 'num', but was of type 'String'.";
+static const field dynamic willBeString = #C5;
+static const field dynamic binaryOnStringWithStringOK = #C11;
+static const field dynamic binaryOnStringWithInt = invalid-expression "Binary operator '+' on '\"hello\"' requires operand of type 'String', but was of type 'int'.";
+static const field dynamic binaryOnStringWithStringBad = invalid-expression "The method '-' can't be invoked on '\"hello\"' in a constant expression.";
+static field core::int* x = 1;
+static const field core::int* x1 = invalid-expression "Constant evaluation has no support for StaticSet!";
+static const field core::int* x2 = invalid-expression "Constant evaluation has no support for StaticSet!";
+static const field core::int* x3 = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::int* x4 = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::int* y = #C12;
+static const field dynamic y1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+const y1 = --y;
+             ^";
+static const field dynamic y2 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+const y2 = ++y;
+             ^";
+static const field core::int* y3 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+const y3 = y--;
+           ^";
+static const field core::int* y4 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+const y4 = y++;
+           ^";
+static field self::AbstractClassWithConstructor* abstractClassWithConstructor = throw invalid-expression "pkg/front_end/testcases/general/constants/various.dart:96:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+    const AbstractClassWithConstructor();
+          ^";
+static const field self::ExtendsFoo1* extendsFoo1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+                                      ^^^^^^^^^^^";
+static const field self::ExtendsFoo2* extendsFoo2 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+  const ExtendsFoo2();
+        ^^^^^^^^^^^";
+static const field self::Foo* foo1 = #C14;
+static const field self::Foo* foo2 = #C14;
+static const field core::bool* foosIdentical = #C3;
+static const field core::bool* foosEqual = invalid-expression "Binary operator '==' requires receiver constant 'Foo {x: 42, y: 5}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type 'Foo'.
+ - 'Foo' is from 'pkg/front_end/testcases/general/constants/various.dart'.";
+static const field core::Symbol* barFoo = #C15;
+static const field core::Symbol* barFooEqual = #C16;
+static const field core::Symbol* tripleShiftSymbol = #C17;
+static const field core::Symbol* symbolWithDots = #C18;
+static const field core::int* circularity1 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity2 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity3 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity4 = invalid-expression "Constant expression depends on itself.";
+static const field dynamic function_const = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+const function_const = () {};
+                       ^^";
+static field () →* core::Null? function_var = () → core::Null? {};
+static field self::ConstClassWithFailingAssertWithEmptyMessage* failedAssertEmptyMessage = invalid-expression "This assertion failed with message: (empty)";
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments1 = #C19;
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments2 = #C20;
+static const field core::bool* classWithTypeArgumentsIdentical = #C1;
+static field self::ClassWithNonEmptyConstConstructor* classWithNonEmptyConstConstructor = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:168:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+    const ClassWithNonEmptyConstConstructor();
+          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic} self::ClassWithNonEmptyConstConstructor*;
+static field self::ConstClassWithFinalFields2* constClassWithFinalFields = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::bool* zeroPointZeroIdentical = #C3;
+static const field core::bool* zeroPointZeroIdenticalToZero = #C1;
+static const field core::bool* zeroIdenticalToZeroPointZero = #C1;
+static const field core::bool* nanIdentical = #C3;
+static const field core::bool* zeroPointZeroEqual = #C3;
+static const field core::bool* zeroPointZeroEqualToZero = #C3;
+static const field core::bool* zeroEqualToZeroPointZero = #C3;
+static const field core::bool* nanEqual = #C1;
+static const field dynamic willBecomeNull = #C2;
+static const field (core::int*) →* core::int* willBecomeNullToo = #C2;
+static const field (core::int*) →* core::int* partialInstantiation = #C22;
+static const field core::bool* yBool = #C3;
+static const field core::bool* zBool = #C1;
+static const field core::Object* maybeInt = #C3;
+static const field core::bool* isItInt = #C1;
+static const field core::Object* maybeInt2 = #C3;
+static const field core::bool* isItInt2 = #C1;
+static const field core::int* maybeInt3 = #C2;
+static const field core::bool* isItInt3 = #C1;
+static method id1<T extends core::Object* = dynamic>(self::id1::T* t) → self::id1::T*
+  return t;
+static method id2<T extends core::Object* = dynamic>(self::id2::T* t) → self::id2::T*
+  return t;
+static method main() → dynamic {
+  core::print(#C1);
+  core::print(#C1);
+}
+
+constants  {
+  #C1 = false
+  #C2 = null
+  #C3 = true
+  #C4 = ""
+  #C5 = "hello"
+  #C6 = 0
+  #C7 = 42
+  #C8 = "42"
+  #C9 = 42.42
+  #C10 = 84.42
+  #C11 = "hello world"
+  #C12 = 1
+  #C13 = 5
+  #C14 = self::Foo {x:#C7, y:#C13}
+  #C15 = #Foo
+  #C16 = #Foo=
+  #C17 = #>>>
+  #C18 = #I.Have.Dots
+  #C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
+  #C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
+  #C21 = tearoff self::id1
+  #C22 = partial-instantiation self::id1 <core::int*>
+}
diff --git a/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect
new file mode 100644
index 0000000..c27c932
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart.strong.transformed.expect
@@ -0,0 +1,630 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/various.dart:162:3: Error: A const constructor can't have a body.
+// Try removing either the 'const' keyword or the body.
+//   const ClassWithNonEmptyConstConstructor() {
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:76:14: Error: Not a constant expression.
+// const x1 = --x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:77:14: Error: Not a constant expression.
+// const x2 = ++x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:78:12: Error: Not a constant expression.
+// const x3 = x--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:79:12: Error: Not a constant expression.
+// const x4 = x++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+// const y1 = --y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+// const y2 = ++y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+// const y3 = y--;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+// const y4 = y++;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+// const function_const = () {};
+//                        ^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Can't access 'this' in a field initializer to read 'y'.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: The class 'AbstractClass' is abstract and can't be instantiated.
+//   @AbstractClass()
+//    ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:99:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClass()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: The class 'AbstractClassWithConstructor' is abstract and can't be instantiated.
+//   @AbstractClassWithConstructor()
+//    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:102:4: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   @AbstractClassWithConstructor()
+//    ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+// const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+//                                       ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+//   const ExtendsFoo2();
+//         ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:180:14: Error: Not a constant expression.
+//   final z1 = y;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:181:14: Error: Not a constant expression.
+//   final z2 = x;
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:96:11: Error: The class 'AbstractClassWithConstructor' is abstract and can't be instantiated.
+//     const AbstractClassWithConstructor();
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:96:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//     const AbstractClassWithConstructor();
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:168:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//     const ClassWithNonEmptyConstConstructor();
+//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/constants/various.dart:114:7: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+// class ExtendsFoo1 extends Foo {
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:10:34: Error: Constant evaluation error:
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:10:34: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:10:12: Context: While analyzing:
+// const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:11:49: Error: Constant evaluation error:
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//                                                 ^
+// pkg/front_end/testcases/general/constants/various.dart:11:32: Context: Expected constant 'null' to be of type 'bool', but was of type 'Null'.
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//                                ^
+// pkg/front_end/testcases/general/constants/various.dart:11:12: Context: While analyzing:
+// const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:16:41: Error: Constant evaluation error:
+// const bool andOnNull = barFromEnvOrNull && true;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:16:41: Context: The method '&&' can't be invoked on 'null' in a constant expression.
+// const bool andOnNull = barFromEnvOrNull && true;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:16:12: Context: While analyzing:
+// const bool andOnNull = barFromEnvOrNull && true;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:17:30: Error: Constant evaluation error:
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:17:30: Context: Binary operator '&&' on 'true' requires operand of type 'bool', but was of type 'Null'.
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:17:12: Context: While analyzing:
+// const bool andOnNull2 = true && barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:18:40: Error: Constant evaluation error:
+// const bool orOnNull = barFromEnvOrNull || true;
+//                                        ^
+// pkg/front_end/testcases/general/constants/various.dart:18:40: Context: The method '||' can't be invoked on 'null' in a constant expression.
+// const bool orOnNull = barFromEnvOrNull || true;
+//                                        ^
+// pkg/front_end/testcases/general/constants/various.dart:18:12: Context: While analyzing:
+// const bool orOnNull = barFromEnvOrNull || true;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:19:41: Error: Constant evaluation error:
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:19:41: Context: The method '||' can't be invoked on 'null' in a constant expression.
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:19:12: Context: While analyzing:
+// const bool orOnNull2 = barFromEnvOrNull || false;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:21:30: Error: Constant evaluation error:
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:21:30: Context: Binary operator '||' on 'false' requires operand of type 'bool', but was of type 'Null'.
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//                              ^
+// pkg/front_end/testcases/general/constants/various.dart:21:12: Context: While analyzing:
+// const bool orOnNull4 = false || barFromEnvOrNull;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:29:11: Error: Constant evaluation error:
+//     const String.fromEnvironment(barFromEnvOrNullString);
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:29:11: Context: Null value during constant evaluation.
+//     const String.fromEnvironment(barFromEnvOrNullString);
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:28:14: Context: While analyzing:
+// const String nullFromEnvString =
+//              ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:36:36: Error: Constant evaluation error:
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//                                    ^
+// pkg/front_end/testcases/general/constants/various.dart:36:36: Context: Null value during constant evaluation.
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//                                    ^
+// pkg/front_end/testcases/general/constants/various.dart:36:12: Context: While analyzing:
+// const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:43:34: Error: Constant evaluation error:
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:43:34: Context: Null value during constant evaluation.
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:43:11: Context: While analyzing:
+// const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:64:37: Error: Constant evaluation error:
+// const binaryOnDouble = willBeDouble << 2;
+//                                     ^
+// pkg/front_end/testcases/general/constants/various.dart:64:37: Context: Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.
+// const binaryOnDouble = willBeDouble << 2;
+//                                     ^
+// pkg/front_end/testcases/general/constants/various.dart:64:7: Context: While analyzing:
+// const binaryOnDouble = willBeDouble << 2;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:66:44: Error: Constant evaluation error:
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:66:44: Context: Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:66:7: Context: While analyzing:
+// const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:68:41: Error: Constant evaluation error:
+// const binaryOnIntWithString = willBeInt << "hello";
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:68:41: Context: Binary operator '<<' on '42' requires operand of type 'num', but was of type 'String'.
+// const binaryOnIntWithString = willBeInt << "hello";
+//                                         ^
+// pkg/front_end/testcases/general/constants/various.dart:68:7: Context: While analyzing:
+// const binaryOnIntWithString = willBeInt << "hello";
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:72:44: Error: Constant evaluation error:
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:72:44: Context: Binary operator '+' on '"hello"' requires operand of type 'String', but was of type 'int'.
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//                                            ^
+// pkg/front_end/testcases/general/constants/various.dart:72:7: Context: While analyzing:
+// const binaryOnStringWithInt = willBeString + willBeInt;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:73:50: Error: Constant evaluation error:
+// const binaryOnStringWithStringBad = willBeString - " world";
+//                                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:73:50: Context: The method '-' can't be invoked on '"hello"' in a constant expression.
+// const binaryOnStringWithStringBad = willBeString - " world";
+//                                                  ^
+// pkg/front_end/testcases/general/constants/various.dart:73:7: Context: While analyzing:
+// const binaryOnStringWithStringBad = willBeString - " world";
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:78:13: Error: Constant evaluation error:
+// const x3 = x--;
+//             ^
+// pkg/front_end/testcases/general/constants/various.dart:78:12: Context: The invocation of 'x' is not allowed in a constant expression.
+// const x3 = x--;
+//            ^
+// pkg/front_end/testcases/general/constants/various.dart:78:7: Context: While analyzing:
+// const x3 = x--;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:79:13: Error: Constant evaluation error:
+// const x4 = x++;
+//             ^
+// pkg/front_end/testcases/general/constants/various.dart:79:12: Context: The invocation of 'x' is not allowed in a constant expression.
+// const x4 = x++;
+//            ^
+// pkg/front_end/testcases/general/constants/various.dart:79:7: Context: While analyzing:
+// const x4 = x++;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:129:29: Error: Constant evaluation error:
+// const bool foosEqual = foo1 == foo2;
+//                             ^
+// pkg/front_end/testcases/general/constants/various.dart:129:29: Context: Binary operator '==' requires receiver constant 'Foo {x: 42, y: 5}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type 'Foo'.
+//  - 'Foo' is from 'pkg/front_end/testcases/general/constants/various.dart'.
+// const bool foosEqual = foo1 == foo2;
+//                             ^
+// pkg/front_end/testcases/general/constants/various.dart:129:12: Context: While analyzing:
+// const bool foosEqual = foo1 == foo2;
+//            ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:135:26: Error: Constant evaluation error:
+// const int circularity1 = circularity2;
+//                          ^
+// pkg/front_end/testcases/general/constants/various.dart:135:26: Context: Constant expression depends on itself.
+// const int circularity1 = circularity2;
+//                          ^
+// pkg/front_end/testcases/general/constants/various.dart:135:11: Context: While analyzing:
+// const int circularity1 = circularity2;
+//           ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:148:11: Error: Constant evaluation error:
+//     const ConstClassWithFailingAssertWithEmptyMessage();
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:144:64: Context: This assertion failed with message: (empty)
+//   const ConstClassWithFailingAssertWithEmptyMessage() : assert(false, "");
+//                                                                ^
+//
+// pkg/front_end/testcases/general/constants/various.dart:185:11: Error: Constant evaluation error:
+//     const ConstClassWithFinalFields2();
+//           ^
+// pkg/front_end/testcases/general/constants/various.dart:181:14: Context: The invocation of 'x' is not allowed in a constant expression.
+//   final z2 = x;
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class AbstractClass extends core::Object {
+  synthetic constructor •() → self::AbstractClass*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class AbstractClassWithConstructor extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::AbstractClassWithConstructor*
+    : super core::Object::•()
+    ;
+  abstract method foo() → core::int*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class NotAbstractClass extends core::Object {
+  @invalid-expression "Constant evaluation has no support for Throw!"
+  field core::Object* foo = null;
+  @invalid-expression "Constant evaluation has no support for Throw!"
+  field core::Object* bar = null;
+  synthetic constructor •() → self::NotAbstractClass*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x;
+  final field core::int* y;
+  const constructor •(core::int* x) → self::Foo*
+    : self::Foo::x = x, self::Foo::y = "hello".{core::String::length}, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ExtendsFoo1 extends self::Foo {
+  synthetic constructor •() → self::ExtendsFoo1*
+    : invalid-initializer
+    ;
+}
+class ExtendsFoo2 extends self::Foo /*hasConstConstructor*/  {
+  const constructor •() → self::ExtendsFoo2*
+    : final dynamic #t1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+  const ExtendsFoo2();
+        ^^^^^^^^^^^"
+    ;
+}
+class ConstClassWithFailingAssertWithEmptyMessage extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::ConstClassWithFailingAssertWithEmptyMessage*
+    : assert(false, ""), super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithTypeArguments<E extends core::Object* = dynamic, F extends core::Object* = dynamic, G extends core::Object* = dynamic> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::ClassWithTypeArguments::E* e, self::ClassWithTypeArguments::F* f, self::ClassWithTypeArguments::G* g) → self::ClassWithTypeArguments<self::ClassWithTypeArguments::E*, self::ClassWithTypeArguments::F*, self::ClassWithTypeArguments::G*>*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ClassWithNonEmptyConstConstructor extends core::Object {
+  constructor •() → self::ClassWithNonEmptyConstConstructor*
+    : super core::Object::•() {
+    core::print("hello");
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields1 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* x = 1;
+  const constructor •() → self::ConstClassWithFinalFields1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class ConstClassWithFinalFields2 extends core::Object /*hasConstConstructor*/  {
+  final field core::int* y = 1;
+  final field dynamic z1 = this.{self::ConstClassWithFinalFields2::y};
+  final field core::int* z2 = self::x;
+  const constructor •() → self::ConstClassWithFinalFields2*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static const field core::bool* barFromEnv = #C1;
+static const field core::bool* hasBarEnv = #C1;
+static const field core::bool* barFromEnvOrNull = #C2;
+static const field core::bool* notBarFromEnvOrNull = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field core::bool* conditionalOnNull = invalid-expression "Expected constant 'null' to be of type 'bool', but was of type 'Null'.";
+static const field core::bool* nullAwareOnNullTrue = #C3;
+static const field core::bool* nullAwareOnNullFalse = #C1;
+static const field core::bool* andOnFalse = #C1;
+static const field core::bool* andOnFalse2 = #C1;
+static const field core::bool* andOnNull = invalid-expression "The method '&&' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* andOnNull2 = invalid-expression "Binary operator '&&' on 'true' requires operand of type 'bool', but was of type 'Null'.";
+static const field core::bool* orOnNull = invalid-expression "The method '||' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* orOnNull2 = invalid-expression "The method '||' can't be invoked on 'null' in a constant expression.";
+static const field core::bool* orOnNull3 = #C3;
+static const field core::bool* orOnNull4 = invalid-expression "Binary operator '||' on 'false' requires operand of type 'bool', but was of type 'Null'.";
+static const field core::String* barFromEnvString = #C4;
+static const field core::String* barFromEnvOrNullString = #C2;
+static const field core::String* barFromEnvOrActualString = #C5;
+static const field core::String* nullFromEnvString = invalid-expression "Null value during constant evaluation.";
+static const field core::bool* barFromEnvBool = #C1;
+static const field core::bool* barFromEnvOrNullBool = #C2;
+static const field core::bool* barFromEnvOrActualBool = #C3;
+static const field core::bool* nullFromEnvBool = invalid-expression "Null value during constant evaluation.";
+static const field core::int* barFromEnvInt = #C6;
+static const field core::int* barFromEnvOrNullInt = #C2;
+static const field core::int* barFromEnvOrActualInt = #C7;
+static const field core::int* nullFromEnvInt = invalid-expression "Null value during constant evaluation.";
+static const field core::bool* bazFromEnv = #C1;
+static const field core::bool* hasBazEnv = #C3;
+static const field core::int* bazFromEnvAsInt = #C7;
+static const field core::String* bazFromEnvAsString = #C8;
+static const field core::bool* bazTrueFromEnv = #C3;
+static const field core::bool* bazFalseFromEnv = #C1;
+static const field core::bool* trueBool = #C3;
+static const field core::bool* falseBool = #C1;
+static const field core::bool* binaryOnBoolCaret = #C3;
+static const field core::bool* binaryOnBoolAmpersand = #C1;
+static const field core::bool* binaryOnBoolBar = #C3;
+static const field core::bool* binaryOnBoolBar2 = #C3;
+static const field dynamic willBeDouble = #C9;
+static const field dynamic binaryOnDouble = invalid-expression "Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic willBeInt = #C7;
+static const field dynamic binaryOnIntWithDoubleBad = invalid-expression "Binary operator '<<' on '42.42' requires operand of type 'int', but was of type 'double'.";
+static const field dynamic binaryOnIntWithDoubleOK = #C10;
+static const field dynamic binaryOnIntWithString = invalid-expression "Binary operator '<<' on '42' requires operand of type 'num', but was of type 'String'.";
+static const field dynamic willBeString = #C5;
+static const field dynamic binaryOnStringWithStringOK = #C11;
+static const field dynamic binaryOnStringWithInt = invalid-expression "Binary operator '+' on '\"hello\"' requires operand of type 'String', but was of type 'int'.";
+static const field dynamic binaryOnStringWithStringBad = invalid-expression "The method '-' can't be invoked on '\"hello\"' in a constant expression.";
+static field core::int* x = 1;
+static const field core::int* x1 = invalid-expression "Constant evaluation has no support for StaticSet!";
+static const field core::int* x2 = invalid-expression "Constant evaluation has no support for StaticSet!";
+static const field core::int* x3 = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::int* x4 = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::int* y = #C12;
+static const field dynamic y1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:82:14: Error: Setter not found: 'y'.
+const y1 = --y;
+             ^";
+static const field dynamic y2 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:83:14: Error: Setter not found: 'y'.
+const y2 = ++y;
+             ^";
+static const field core::int* y3 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:84:12: Error: Setter not found: 'y'.
+const y3 = y--;
+           ^";
+static const field core::int* y4 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:85:12: Error: Setter not found: 'y'.
+const y4 = y++;
+           ^";
+static field self::AbstractClassWithConstructor* abstractClassWithConstructor = throw invalid-expression "pkg/front_end/testcases/general/constants/various.dart:96:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+    const AbstractClassWithConstructor();
+          ^";
+static const field self::ExtendsFoo1* extendsFoo1 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:118:39: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+                                      ^^^^^^^^^^^";
+static const field self::ExtendsFoo2* extendsFoo2 = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:121:9: Error: The superclass, 'Foo', has no unnamed constructor that takes no arguments.
+  const ExtendsFoo2();
+        ^^^^^^^^^^^";
+static const field self::Foo* foo1 = #C14;
+static const field self::Foo* foo2 = #C14;
+static const field core::bool* foosIdentical = #C3;
+static const field core::bool* foosEqual = invalid-expression "Binary operator '==' requires receiver constant 'Foo {x: 42, y: 5}' of type 'Null', 'bool', 'int', 'double', or 'String', but was of type 'Foo'.
+ - 'Foo' is from 'pkg/front_end/testcases/general/constants/various.dart'.";
+static const field core::Symbol* barFoo = #C15;
+static const field core::Symbol* barFooEqual = #C16;
+static const field core::Symbol* tripleShiftSymbol = #C17;
+static const field core::Symbol* symbolWithDots = #C18;
+static const field core::int* circularity1 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity2 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity3 = invalid-expression "Constant expression depends on itself.";
+static const field core::int* circularity4 = invalid-expression "Constant expression depends on itself.";
+static const field dynamic function_const = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:140:24: Error: Not a constant expression.
+const function_const = () {};
+                       ^^";
+static field () →* core::Null? function_var = () → core::Null? {};
+static field self::ConstClassWithFailingAssertWithEmptyMessage* failedAssertEmptyMessage = invalid-expression "This assertion failed with message: (empty)";
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments1 = #C19;
+static const field self::ClassWithTypeArguments<dynamic, dynamic, dynamic>* classWithTypeArguments2 = #C20;
+static const field core::bool* classWithTypeArgumentsIdentical = #C1;
+static field self::ClassWithNonEmptyConstConstructor* classWithNonEmptyConstConstructor = invalid-expression "pkg/front_end/testcases/general/constants/various.dart:168:11: Error: Cannot invoke a non-'const' constructor where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+    const ClassWithNonEmptyConstConstructor();
+          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^";
+static field self::ConstClassWithFinalFields2* constClassWithFinalFields = invalid-expression "The invocation of 'x' is not allowed in a constant expression.";
+static const field core::bool* zeroPointZeroIdentical = #C3;
+static const field core::bool* zeroPointZeroIdenticalToZero = #C1;
+static const field core::bool* zeroIdenticalToZeroPointZero = #C1;
+static const field core::bool* nanIdentical = #C3;
+static const field core::bool* zeroPointZeroEqual = #C3;
+static const field core::bool* zeroPointZeroEqualToZero = #C3;
+static const field core::bool* zeroEqualToZeroPointZero = #C3;
+static const field core::bool* nanEqual = #C1;
+static const field dynamic willBecomeNull = #C2;
+static const field (core::int*) →* core::int* willBecomeNullToo = #C2;
+static const field (core::int*) →* core::int* partialInstantiation = #C22;
+static const field core::bool* yBool = #C3;
+static const field core::bool* zBool = #C1;
+static const field core::Object* maybeInt = #C3;
+static const field core::bool* isItInt = #C1;
+static const field core::Object* maybeInt2 = #C3;
+static const field core::bool* isItInt2 = #C1;
+static const field core::int* maybeInt3 = #C2;
+static const field core::bool* isItInt3 = #C1;
+static method id1<T extends core::Object* = dynamic>(self::id1::T* t) → self::id1::T*
+  return t;
+static method id2<T extends core::Object* = dynamic>(self::id2::T* t) → self::id2::T*
+  return t;
+static method main() → dynamic {
+  core::print(#C1);
+  core::print(#C1);
+}
+
+constants  {
+  #C1 = false
+  #C2 = null
+  #C3 = true
+  #C4 = ""
+  #C5 = "hello"
+  #C6 = 0
+  #C7 = 42
+  #C8 = "42"
+  #C9 = 42.42
+  #C10 = 84.42
+  #C11 = "hello world"
+  #C12 = 1
+  #C13 = 5
+  #C14 = self::Foo {x:#C7, y:#C13}
+  #C15 = #Foo
+  #C16 = #Foo=
+  #C17 = #>>>
+  #C18 = #I.Have.Dots
+  #C19 = self::ClassWithTypeArguments<core::int*, core::int*, core::int*> {}
+  #C20 = self::ClassWithTypeArguments<dynamic, dynamic, dynamic> {}
+  #C21 = tearoff self::id1
+  #C22 = partial-instantiation self::id1 <core::int*>
+}
+
+Extra constant evaluation status:
+Evaluated: PropertyGet @ org-dartlang-testcase:///various.dart:111:26 -> IntConstant(5)
+Extra constant evaluation: evaluated: 12, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/constants/various.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/various.dart.textual_outline.expect
new file mode 100644
index 0000000..f696546
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart.textual_outline.expect
@@ -0,0 +1,143 @@
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const bool barFromEnvOrNull = const bool.fromEnvironment("bar", defaultValue: null);
+const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+const bool nullAwareOnNullTrue = barFromEnvOrNull ?? true;
+const bool nullAwareOnNullFalse = barFromEnvOrNull ?? false;
+const bool andOnFalse = nullAwareOnNullFalse && nullAwareOnNullTrue;
+const bool andOnFalse2 = nullAwareOnNullTrue && nullAwareOnNullFalse;
+const bool andOnNull = barFromEnvOrNull && true;
+const bool andOnNull2 = true && barFromEnvOrNull;
+const bool orOnNull = barFromEnvOrNull || true;
+const bool orOnNull2 = barFromEnvOrNull || false;
+const bool orOnNull3 = true || barFromEnvOrNull;
+const bool orOnNull4 = false || barFromEnvOrNull;
+const String barFromEnvString = const String.fromEnvironment("bar");
+const String barFromEnvOrNullString = const String.fromEnvironment("bar", defaultValue: null);
+const String barFromEnvOrActualString = const String.fromEnvironment("bar", defaultValue: "hello");
+const String nullFromEnvString = const String.fromEnvironment(barFromEnvOrNullString);
+const bool barFromEnvBool = const bool.fromEnvironment("bar");
+const bool barFromEnvOrNullBool = const bool.fromEnvironment("bar", defaultValue: null);
+const bool barFromEnvOrActualBool = const bool.fromEnvironment("bar", defaultValue: true);
+const bool nullFromEnvBool = const bool.fromEnvironment(barFromEnvOrNullString);
+const int barFromEnvInt = const int.fromEnvironment("bar");
+const int barFromEnvOrNullInt = const int.fromEnvironment("bar", defaultValue: null);
+const int barFromEnvOrActualInt = const int.fromEnvironment("bar", defaultValue: 42);
+const int nullFromEnvInt = const int.fromEnvironment(barFromEnvOrNullString);
+const bool bazFromEnv = const bool.fromEnvironment("baz");
+const bool hasBazEnv = const bool.hasEnvironment("baz");
+const int bazFromEnvAsInt = const int.fromEnvironment("baz");
+const String bazFromEnvAsString = const String.fromEnvironment("baz");
+const bool bazTrueFromEnv = const bool.fromEnvironment("bazTrue");
+const bool bazFalseFromEnv = const bool.fromEnvironment("bazFalse");
+const bool trueBool = true;
+const bool falseBool = false;
+const bool binaryOnBoolCaret = trueBool ^ falseBool;
+const bool binaryOnBoolAmpersand = trueBool & falseBool;
+const bool binaryOnBoolBar = trueBool | falseBool;
+const bool binaryOnBoolBar2 = falseBool | trueBool;
+const dynamic willBeDouble = const bool.fromEnvironment("foo") ? 42 : 42.42;
+const binaryOnDouble = willBeDouble << 2;
+const dynamic willBeInt = const bool.fromEnvironment("foo") ? 42.42 : 42;
+const binaryOnIntWithDoubleBad = willBeInt << willBeDouble;
+const binaryOnIntWithDoubleOK = willBeInt + willBeDouble;
+const binaryOnIntWithString = willBeInt << "hello";
+const dynamic willBeString = const bool.fromEnvironment("foo") ? 42.42 : "hello";
+const binaryOnStringWithStringOK = willBeString + " world";
+const binaryOnStringWithInt = willBeString + willBeInt;
+const binaryOnStringWithStringBad = willBeString - " world";
+var x = 1;
+const x1 = --x;
+const x2 = ++x;
+const x3 = x--;
+const x4 = x++;
+const y = 1;
+const y1 = --y;
+const y2 = ++y;
+const y3 = y--;
+const y4 = y++;
+abstract class AbstractClass {}
+abstract class AbstractClassWithConstructor {
+  const AbstractClassWithConstructor();
+  int foo();
+}
+AbstractClassWithConstructor abstractClassWithConstructor = const AbstractClassWithConstructor();
+class NotAbstractClass {
+  @AbstractClass()
+  Object foo;
+  @AbstractClassWithConstructor()
+  Object bar;
+}
+class Foo {
+  final int x;
+  final int y;
+  const Foo(int x) : this.x = x, this.y = "hello".length;
+}
+class ExtendsFoo1 extends Foo {}
+const ExtendsFoo1 extendsFoo1 = const ExtendsFoo1();
+class ExtendsFoo2 extends Foo {
+  const ExtendsFoo2();
+}
+const ExtendsFoo2 extendsFoo2 = const ExtendsFoo2();
+const Foo foo1 = const Foo(42);
+const Foo foo2 = const Foo(42);
+const bool foosIdentical = identical(foo1, foo2);
+const bool foosEqual = foo1 == foo2;
+const Symbol barFoo = const Symbol("Foo");
+const Symbol barFooEqual = const Symbol("Foo=");
+const Symbol tripleShiftSymbol = const Symbol(">>>");
+const Symbol symbolWithDots = const Symbol("I.Have.Dots");
+const int circularity1 = circularity2;
+const int circularity2 = circularity3;
+const int circularity3 = circularity4;
+const int circularity4 = circularity1;
+const function_const = () {};
+var function_var = () {};
+class ConstClassWithFailingAssertWithEmptyMessage {
+  const ConstClassWithFailingAssertWithEmptyMessage() : assert(false, "");
+}
+ConstClassWithFailingAssertWithEmptyMessage failedAssertEmptyMessage = const ConstClassWithFailingAssertWithEmptyMessage();
+class ClassWithTypeArguments<E, F, G> {
+  const ClassWithTypeArguments(E e, F f, G g);
+}
+const ClassWithTypeArguments classWithTypeArguments1 = const ClassWithTypeArguments<int, int, int>(42, 42, 42);
+const ClassWithTypeArguments classWithTypeArguments2 = const ClassWithTypeArguments(42, 42, 42);
+const bool classWithTypeArgumentsIdentical = identical(classWithTypeArguments1, classWithTypeArguments2);
+class ClassWithNonEmptyConstConstructor {
+  const ClassWithNonEmptyConstConstructor() {}
+}
+ClassWithNonEmptyConstConstructor classWithNonEmptyConstConstructor = const ClassWithNonEmptyConstConstructor();
+class ConstClassWithFinalFields1 {
+  const ConstClassWithFinalFields1();
+  final x = 1;
+}
+class ConstClassWithFinalFields2 {
+  const ConstClassWithFinalFields2();
+  final y = 1;
+  final z1 = y;
+  final z2 = x;
+}
+ConstClassWithFinalFields2 constClassWithFinalFields = const ConstClassWithFinalFields2();
+const zeroPointZeroIdentical = identical(0.0, 0.0);
+const zeroPointZeroIdenticalToZero = identical(0.0, 0);
+const zeroIdenticalToZeroPointZero = identical(0, 0.0);
+const nanIdentical = identical(0 / 0, 0 / 0);
+const zeroPointZeroEqual = 0.0 == 0.0;
+const zeroPointZeroEqualToZero = 0.0 == 0;
+const zeroEqualToZeroPointZero = 0 == 0.0;
+const nanEqual = 0 / 0 == 0 / 0;
+T id1<T>(T t) => t;
+T id2<T>(T t) => t;
+const dynamic willBecomeNull = const bool.fromEnvironment("foo") ? id1 : null;
+const int Function(int) willBecomeNullToo = const bool.fromEnvironment("foo") ? id1 : willBecomeNull;
+const int Function(int) partialInstantiation = const bool.fromEnvironment("foo") ? willBecomeNull : id1;
+const bool yBool = true;
+const bool zBool = !yBool;
+const maybeInt = bool.fromEnvironment("foo") ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const maybeInt2 = zBool ? 42 : true;
+const bool isItInt2 = maybeInt2 is int ? true : false;
+const maybeInt3 = zBool ? 42 : null;
+const bool isItInt3 = maybeInt3 is int ? true : false;
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/various.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/various.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..068970b
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/various.dart.textual_outline_modelled.expect
@@ -0,0 +1,39 @@
+ConstClassWithFailingAssertWithEmptyMessage failedAssertEmptyMessage =
+    const ConstClassWithFailingAssertWithEmptyMessage();
+
+abstract class AbstractClass {}
+
+class ConstClassWithFailingAssertWithEmptyMessage {
+  const ConstClassWithFailingAssertWithEmptyMessage() : assert(false, "");
+}
+
+class Foo {
+  const Foo(int x)
+      : this.x = x,
+        this.y = "hello".length;
+  final int x;
+  final int y;
+}
+
+class NotAbstractClass {
+  @AbstractClass()
+  Object foo;
+}
+
+const Foo foo = const Foo(42);
+const Symbol barFoo = const Symbol("Foo");
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const function_const = () {};
+const x1 = --x;
+const x2 = ++x;
+const x3 = x--;
+const x4 = x++;
+const y = 1;
+const y1 = --y;
+const y2 = ++y;
+const y3 = y--;
+const y4 = y++;
+main() {}
+var function_var = () {};
+var x = 1;
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart
new file mode 100644
index 0000000..473c73d
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  final int x;
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+}
+
+class Bar {
+  final int x;
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+}
+
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+
+main() {
+  print(foo1);
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect
new file mode 100644
index 0000000..9745070
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.outline.expect
@@ -0,0 +1,61 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor •(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false), "foo was ${const core::bool::fromEnvironment("foo")}"), assert(const core::bool::fromEnvironment("foo").{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${const core::bool::fromEnvironment("foo")}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int x) → self::Foo
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError,ForNonNullableByDefault} core::bool), super core::Object::•()
+    ;
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor withMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+}
+static const field self::Foo foo1 = const self::Foo::•(1);
+static const field self::Foo foo2 = const self::Foo::•(0);
+static const field self::Foo foo3 = const self::Foo::withMessage(42);
+static const field self::Foo foo4 = const self::Foo::withInvalidMessage(42);
+static const field self::Foo foo5 = const self::Foo::withInvalidCondition(42);
+static const field self::Bar bar1 = const self::Bar::withMessage(1);
+static const field self::Bar bar2 = const self::Bar::withMessage(0);
+static const field self::Bar bar3 = const self::Bar::withoutMessage(1);
+static const field self::Bar bar4 = const self::Bar::withoutMessage(0);
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:10:22 -> BoolConstant(false)
+Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:11:59 -> StringConstant("foo was false")
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:11:30 -> BoolConstant(false)
+Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:12:22 -> BoolConstant(false)
+Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:14:73 -> StringConstant("btw foo was false")
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_asserts.dart:14:44 -> BoolConstant(false)
+Evaluated with empty environment: ConstructorInvocation @ org-dartlang-testcase:///const_asserts.dart:25:24 -> InstanceConstant(const Foo{Foo.x: 1})
+Extra constant evaluation: evaluated: 39, effectively constant: 9
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect
new file mode 100644
index 0000000..aa75ba9
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.expect
@@ -0,0 +1,127 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:26:24: Error: Constant evaluation error:
+// const Foo foo2 = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:8:18: Context: This assertion failed with message: x is not positive
+//       : assert(x > 0, "x is not positive"),
+//                  ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:26:11: Context: While analyzing:
+// const Foo foo2 = const Foo(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:24: Error: Constant evaluation error:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+//   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+//                                                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:11: Context: While analyzing:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:30:24: Error: Constant evaluation error:
+// const Bar bar1 = const Bar.withMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:21:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:30:11: Context: While analyzing:
+// const Bar bar1 = const Bar.withMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:31:24: Error: Constant evaluation error:
+// const Bar bar2 = const Bar.withMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:21:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:31:11: Context: While analyzing:
+// const Bar bar2 = const Bar.withMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:32:24: Error: Constant evaluation error:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:22:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:32:11: Context: While analyzing:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:33:24: Error: Constant evaluation error:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:22:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:33:11: Context: While analyzing:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor •(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert((#C2).{core::Object::==}(false), "foo was ${#C3}"), assert((#C4).{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C5}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int x) → self::Foo
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError,ForNonNullableByDefault} core::bool), super core::Object::•()
+    ;
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor withMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+}
+static const field self::Foo foo1 = #C9;
+static const field self::Foo foo2 = invalid-expression "This assertion failed with message: x is not positive";
+static const field self::Foo foo3 = #C12;
+static const field self::Foo foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo foo5 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^";
+static const field self::Bar bar1 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar bar2 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar bar3 = invalid-expression "This assertion failed.";
+static const field self::Bar bar4 = invalid-expression "This assertion failed.";
+static method main() → dynamic {
+  core::print(#C13);
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = eval const core::bool::fromEnvironment(#C1)
+  #C3 = eval const core::bool::fromEnvironment(#C1)
+  #C4 = eval const core::bool::fromEnvironment(#C1)
+  #C5 = eval const core::bool::fromEnvironment(#C1)
+  #C6 = 1
+  #C7 = false
+  #C8 = "foo was "
+  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+  #C10 = 42
+  #C11 = "btw foo was "
+  #C12 = eval self::Foo{x:#C10, assert(#C7, "${#C11}${const core::bool::fromEnvironment(#C1)}")}
+  #C13 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect
new file mode 100644
index 0000000..84a0f93
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.strong.transformed.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+//   const Foo.withInvalidCondition(this.x) : assert(x);
+//                                                   ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:26:24: Error: Constant evaluation error:
+// const Foo foo2 = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:8:18: Context: This assertion failed with message: x is not positive
+//       : assert(x > 0, "x is not positive"),
+//                  ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:26:11: Context: While analyzing:
+// const Foo foo2 = const Foo(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:24: Error: Constant evaluation error:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:15:56: Context: Expected constant '42' to be of type 'String', but was of type 'int'.
+//   const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+//                                                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:28:11: Context: While analyzing:
+// const Foo foo4 = const Foo.withInvalidMessage(42);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:30:24: Error: Constant evaluation error:
+// const Bar bar1 = const Bar.withMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:21:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:30:11: Context: While analyzing:
+// const Bar bar1 = const Bar.withMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:31:24: Error: Constant evaluation error:
+// const Bar bar2 = const Bar.withMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:21:44: Context: This assertion failed with message: x is not negative
+//   const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:31:11: Context: While analyzing:
+// const Bar bar2 = const Bar.withMessage(0);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:32:24: Error: Constant evaluation error:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:22:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:32:11: Context: While analyzing:
+// const Bar bar3 = const Bar.withoutMessage(1);
+//           ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:33:24: Error: Constant evaluation error:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//                        ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:22:47: Context: This assertion failed.
+//   const Bar.withoutMessage(this.x) : assert(x < 0);
+//                                               ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:33:11: Context: While analyzing:
+// const Bar bar4 = const Bar.withoutMessage(0);
+//           ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Foo extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor •(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::>}(0), "x is not positive"), assert(x.{core::num::>}(0)), assert((#C2).{core::Object::==}(false), "foo was ${#C3}"), assert((#C4).{core::Object::==}(false)), super core::Object::•()
+    ;
+  const constructor withMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), "btw foo was ${#C5}"), super core::Object::•()
+    ;
+  const constructor withInvalidMessage(core::int x) → self::Foo
+    : self::Foo::x = x, assert(x.{core::num::<}(0), x), super core::Object::•()
+    ;
+  const constructor withInvalidCondition(core::int x) → self::Foo
+    : self::Foo::x = x, assert(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^" in x as{TypeError,ForNonNullableByDefault} core::bool), super core::Object::•()
+    ;
+}
+class Bar extends core::Object /*hasConstConstructor*/  {
+  final field core::int x;
+  const constructor withMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0), "x is not negative"), super core::Object::•()
+    ;
+  const constructor withoutMessage(core::int x) → self::Bar
+    : self::Bar::x = x, assert(x.{core::num::<}(0)), super core::Object::•()
+    ;
+}
+static const field self::Foo foo1 = #C9;
+static const field self::Foo foo2 = invalid-expression "This assertion failed with message: x is not positive";
+static const field self::Foo foo3 = #C12;
+static const field self::Foo foo4 = invalid-expression "Expected constant '42' to be of type 'String', but was of type 'int'.";
+static const field self::Foo foo5 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart:16:51: Error: A value of type 'int' can't be assigned to a variable of type 'bool'.
+  const Foo.withInvalidCondition(this.x) : assert(x);
+                                                  ^";
+static const field self::Bar bar1 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar bar2 = invalid-expression "This assertion failed with message: x is not negative";
+static const field self::Bar bar3 = invalid-expression "This assertion failed.";
+static const field self::Bar bar4 = invalid-expression "This assertion failed.";
+static method main() → dynamic {
+  core::print(#C13);
+}
+
+constants  {
+  #C1 = "foo"
+  #C2 = eval const core::bool::fromEnvironment(#C1)
+  #C3 = eval const core::bool::fromEnvironment(#C1)
+  #C4 = eval const core::bool::fromEnvironment(#C1)
+  #C5 = eval const core::bool::fromEnvironment(#C1)
+  #C6 = 1
+  #C7 = false
+  #C8 = "foo was "
+  #C9 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+  #C10 = 42
+  #C11 = "btw foo was "
+  #C12 = eval self::Foo{x:#C10, assert(#C7, "${#C11}${const core::bool::fromEnvironment(#C1)}")}
+  #C13 = eval self::Foo{x:#C6, assert(const core::bool::fromEnvironment(#C1).==(#C7), "${#C8}${const core::bool::fromEnvironment(#C1)}"), assert(const core::bool::fromEnvironment(#C1).==(#C7))}
+}
+
+Extra constant evaluation status:
+Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:10:50 -> BoolConstant(true)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:10:22 -> BoolConstant(false)
+Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:11:59 -> StringConstant("foo was false")
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:11:30 -> BoolConstant(false)
+Evaluated with empty environment: MethodInvocation @ org-dartlang-testcase:///const_asserts.dart:12:50 -> BoolConstant(true)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:12:22 -> BoolConstant(false)
+Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///const_asserts.dart:14:73 -> StringConstant("btw foo was false")
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:14:44 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:25:24 -> InstanceConstant(const Foo{Foo.x: 1})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_asserts.dart:25:24 -> InstanceConstant(const Foo{Foo.x: 1})
+Extra constant evaluation: evaluated: 34, effectively constant: 10
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline.expect
new file mode 100644
index 0000000..13faa29
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline.expect
@@ -0,0 +1,30 @@
+class Foo {
+  final int x;
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+}
+
+class Bar {
+  final int x;
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+}
+
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0bde6d8
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_asserts.dart.textual_outline_modelled.expect
@@ -0,0 +1,30 @@
+class Bar {
+  const Bar.withMessage(this.x) : assert(x < 0, "x is not negative");
+  const Bar.withoutMessage(this.x) : assert(x < 0);
+  final int x;
+}
+
+class Foo {
+  const Foo(this.x)
+      : assert(x > 0, "x is not positive"),
+        assert(x > 0),
+        assert(const bool.fromEnvironment("foo") == false,
+            "foo was ${const bool.fromEnvironment("foo")}"),
+        assert(const bool.fromEnvironment("foo") == false);
+  const Foo.withInvalidCondition(this.x) : assert(x);
+  const Foo.withInvalidMessage(this.x) : assert(x < 0, x);
+  const Foo.withMessage(this.x)
+      : assert(x < 0, "btw foo was ${const bool.fromEnvironment("foo")}");
+  final int x;
+}
+
+const Bar bar1 = const Bar.withMessage(1);
+const Bar bar2 = const Bar.withMessage(0);
+const Bar bar3 = const Bar.withoutMessage(1);
+const Bar bar4 = const Bar.withoutMessage(0);
+const Foo foo1 = const Foo(1);
+const Foo foo2 = const Foo(0);
+const Foo foo3 = const Foo.withMessage(42);
+const Foo foo4 = const Foo.withInvalidMessage(42);
+const Foo foo5 = const Foo.withInvalidCondition(42);
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart
new file mode 100644
index 0000000..d96e7e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const List<bool> listWithUnevaluated = [
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+];
+const List<bool> listWithUnevaluatedSpread = [
+  true,
+  ...listWithUnevaluated,
+  false
+];
+
+const Set<bool> setWithUnevaluated = {
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+};
+const Set<bool> setWithUnevaluatedSpread = {true, ...setWithUnevaluated, false};
+
+const a = <int>[];
+const b = <int?>[];
+const setNotAgnosticOK = {a, b};
+
+const Map<bool> MapWithUnevaluated = {
+  bool.fromEnvironment("foo"): bool.fromEnvironment("bar"),
+};
+
+const mapNotAgnosticOK = {a: 0, b: 1};
+
+main() {
+  print(listWithUnevaluated);
+  print(listWithUnevaluatedSpread);
+  print(setWithUnevaluated);
+  print(setWithUnevaluatedSpread);
+  print({"hello"});
+  print(const {"hello"});
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect
new file mode 100644
index 0000000..8dfa191
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.outline.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:27:7: Error: Expected 2 type arguments.
+// const Map<bool> MapWithUnevaluated = {
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::List<core::bool> listWithUnevaluated = const <core::bool>[const core::bool::fromEnvironment("foo"), const core::bool::fromEnvironment("bar"), true];
+static const field core::List<core::bool> listWithUnevaluatedSpread = const <core::bool>[true] + self::listWithUnevaluated + const <core::bool>[false];
+static const field core::Set<core::bool> setWithUnevaluated = const <core::bool>{const core::bool::fromEnvironment("foo"), const core::bool::fromEnvironment("bar"), true};
+static const field core::Set<core::bool> setWithUnevaluatedSpread = const <core::bool>{true} + self::setWithUnevaluated + const <core::bool>{false};
+static const field core::List<core::int> a = const <core::int>[];
+static const field core::List<core::int?> b = const <core::int?>[];
+static const field core::Set<core::List<core::int?>> setNotAgnosticOK = const <core::List<core::int?>>{self::a, self::b};
+static const field invalid-type MapWithUnevaluated = const <core::bool, core::bool>{const core::bool::fromEnvironment("foo"): const core::bool::fromEnvironment("bar")};
+static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = const <core::List<core::int?>, core::int>{self::a: 0, self::b: 1};
+static method main() → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated with empty environment: ListLiteral @ org-dartlang-testcase:///const_collections.dart:5:40 -> ListConstant(const <bool>[false, false, true])
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:6:8 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:7:8 -> BoolConstant(false)
+Evaluated with empty environment: ListConcatenation @ org-dartlang-testcase:///const_collections.dart:10:46 -> ListConstant(const <bool>[true, false, false, true, false])
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:10:46 -> ListConstant(const <bool>[true])
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///const_collections.dart:12:6 -> ListConstant(const <bool>[false, false, true])
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:10:46 -> ListConstant(const <bool>[false])
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:17:8 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:18:8 -> BoolConstant(false)
+Evaluated: SetLiteral @ org-dartlang-testcase:///const_collections.dart:21:44 -> SetConstant(const <bool>{true})
+Evaluated: SetLiteral @ org-dartlang-testcase:///const_collections.dart:21:44 -> SetConstant(const <bool>{false})
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:23:16 -> ListConstant(const <int>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///const_collections.dart:24:17 -> ListConstant(const <int?>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:25:27 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:25:30 -> ListConstant(const <int?>[])
+Evaluated with empty environment: MapLiteral @ org-dartlang-testcase:///const_collections.dart:27:38 -> MapConstant(const <bool, bool>{false: false})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:28:8 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///const_collections.dart:28:37 -> BoolConstant(false)
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:31:27 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///const_collections.dart:31:33 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 25, effectively constant: 20
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect
new file mode 100644
index 0000000..eadc725
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.expect
@@ -0,0 +1,79 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:27:7: Error: Expected 2 type arguments.
+// const Map<bool> MapWithUnevaluated = {
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:26: Error: Constant evaluation error:
+// const setNotAgnosticOK = {a, b};
+//                          ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:30: Context: Constant value is not strong/weak mode agnostic.
+// const setNotAgnosticOK = {a, b};
+//                              ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:7: Context: While analyzing:
+// const setNotAgnosticOK = {a, b};
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:26: Error: Constant evaluation error:
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//                          ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:33: Context: Constant value is not strong/weak mode agnostic.
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//                                 ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:7: Context: While analyzing:
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::List<core::bool> listWithUnevaluated = #C7;
+static const field core::List<core::bool> listWithUnevaluatedSpread = #C11;
+static const field core::Set<core::bool> setWithUnevaluated = #C15;
+static const field core::Set<core::bool> setWithUnevaluatedSpread = #C18;
+static const field core::List<core::int> a = #C19;
+static const field core::List<core::int?> b = #C20;
+static const field core::Set<core::List<core::int?>> setNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field invalid-type MapWithUnevaluated = #C22;
+static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static method main() → dynamic {
+  core::print(#C23);
+  core::print(#C24);
+  core::print(#C25);
+  core::print(#C26);
+  core::print(<core::String>{"hello"});
+  core::print(#C28);
+}
+
+constants  {
+  #C1 = <core::bool>[]
+  #C2 = <dynamic>[]
+  #C3 = "foo"
+  #C4 = "bar"
+  #C5 = true
+  #C6 = <dynamic>[#C5]
+  #C7 = eval #C1 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6
+  #C8 = <core::bool>[#C5]
+  #C9 = false
+  #C10 = <core::bool>[#C9]
+  #C11 = eval #C8 + #C1 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6 + #C10
+  #C12 = <core::bool>{}
+  #C13 = <dynamic>{}
+  #C14 = <dynamic>{#C5}
+  #C15 = eval #C12 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14
+  #C16 = <core::bool>{#C5}
+  #C17 = <core::bool>{#C9}
+  #C18 = eval #C16 + #C12 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14 + #C17
+  #C19 = <core::int>[]
+  #C20 = <core::int?>[]
+  #C21 = <core::bool, core::bool>{)
+  #C22 = eval #C21 + const <dynamic, dynamic>{const core::bool::fromEnvironment(#C3): const core::bool::fromEnvironment(#C4)}
+  #C23 = eval #C1 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6
+  #C24 = eval #C8 + #C1 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6 + #C10
+  #C25 = eval #C12 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14
+  #C26 = eval #C16 + #C12 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14 + #C17
+  #C27 = "hello"
+  #C28 = <core::String>{#C27}
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect
new file mode 100644
index 0000000..461ccb6
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.strong.transformed.expect
@@ -0,0 +1,88 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:27:7: Error: Expected 2 type arguments.
+// const Map<bool> MapWithUnevaluated = {
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:26: Error: Constant evaluation error:
+// const setNotAgnosticOK = {a, b};
+//                          ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:30: Context: Constant value is not strong/weak mode agnostic.
+// const setNotAgnosticOK = {a, b};
+//                              ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:25:7: Context: While analyzing:
+// const setNotAgnosticOK = {a, b};
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:26: Error: Constant evaluation error:
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//                          ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:33: Context: Constant value is not strong/weak mode agnostic.
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//                                 ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart:31:7: Context: While analyzing:
+// const mapNotAgnosticOK = {a: 0, b: 1};
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+static const field core::List<core::bool> listWithUnevaluated = #C7;
+static const field core::List<core::bool> listWithUnevaluatedSpread = #C11;
+static const field core::Set<core::bool> setWithUnevaluated = #C15;
+static const field core::Set<core::bool> setWithUnevaluatedSpread = #C18;
+static const field core::List<core::int> a = #C19;
+static const field core::List<core::int?> b = #C20;
+static const field core::Set<core::List<core::int?>> setNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static const field invalid-type MapWithUnevaluated = #C23;
+static const field core::Map<core::List<core::int?>, core::int> mapNotAgnosticOK = invalid-expression "Constant value is not strong/weak mode agnostic.";
+static method main() → dynamic {
+  core::print(#C24);
+  core::print(#C25);
+  core::print(#C26);
+  core::print(#C27);
+  core::print(<core::String>{"hello"});
+  core::print(#C29);
+}
+
+constants  {
+  #C1 = <core::bool>[]
+  #C2 = <dynamic>[]
+  #C3 = "foo"
+  #C4 = "bar"
+  #C5 = true
+  #C6 = <dynamic>[#C5]
+  #C7 = eval #C1 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6
+  #C8 = <core::bool>[#C5]
+  #C9 = false
+  #C10 = <core::bool>[#C9]
+  #C11 = eval #C8 + #C1 + #C2 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6 + #C10
+  #C12 = <core::bool>{}
+  #C13 = <dynamic>{}
+  #C14 = <dynamic>{#C5}
+  #C15 = eval #C12 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14
+  #C16 = <core::bool>{#C5}
+  #C17 = <core::bool>{#C9}
+  #C18 = eval #C16 + #C12 + #C13 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14 + #C17
+  #C19 = <core::int>[]
+  #C20 = <core::int?>[]
+  #C21 = <core::bool, core::bool>{)
+  #C22 = <dynamic, dynamic>{)
+  #C23 = eval #C21 + #C22 + const <dynamic, dynamic>{const core::bool::fromEnvironment(#C3): const core::bool::fromEnvironment(#C4)}
+  #C24 = eval #C1 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6
+  #C25 = eval #C8 + #C1 + #C2 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C3)] + #C2 + #C2 + #C2 + const <dynamic>[const core::bool::fromEnvironment(#C4)] + #C6 + #C10
+  #C26 = eval #C12 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14
+  #C27 = eval #C16 + #C12 + #C13 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C3)} + #C13 + #C13 + #C13 + const <dynamic>{const core::bool::fromEnvironment(#C4)} + #C14 + #C17
+  #C28 = "hello"
+  #C29 = <core::String>{#C28}
+}
+
+Extra constant evaluation status:
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_collections.dart:5:40 -> ListConstant(const <bool>[false, false, true])
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_collections.dart:10:46 -> ListConstant(const <bool>[true, false, false, true, false])
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_collections.dart:5:40 -> ListConstant(const <bool>[false, false, true])
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_collections.dart:10:46 -> ListConstant(const <bool>[true, false, false, true, false])
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///const_collections.dart:27:38 -> MapConstant(const <bool, bool>{false: false})
+Extra constant evaluation: evaluated: 16, effectively constant: 5
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline.expect
new file mode 100644
index 0000000..320e5f4
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline.expect
@@ -0,0 +1,24 @@
+const List<bool> listWithUnevaluated = [
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+];
+const List<bool> listWithUnevaluatedSpread = [
+  true,
+  ...listWithUnevaluated,
+  false
+];
+const Set<bool> setWithUnevaluated = {
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+};
+const Set<bool> setWithUnevaluatedSpread = {true, ...setWithUnevaluated, false};
+const a = <int>[];
+const b = <int?>[];
+const setNotAgnosticOK = {a, b};
+const Map<bool> MapWithUnevaluated = {
+  bool.fromEnvironment("foo"): bool.fromEnvironment("bar"),
+};
+const mapNotAgnosticOK = {a: 0, b: 1};
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..c3b5d78
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/const_collections.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+const List<bool> listWithUnevaluated = [
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+];
+const List<bool> listWithUnevaluatedSpread = [
+  true,
+  ...listWithUnevaluated,
+  false
+];
+const Map<bool> MapWithUnevaluated = {
+  bool.fromEnvironment("foo"): bool.fromEnvironment("bar"),
+};
+const Set<bool> setWithUnevaluated = {
+  bool.fromEnvironment("foo"),
+  bool.fromEnvironment("bar"),
+  true,
+};
+const Set<bool> setWithUnevaluatedSpread = {true, ...setWithUnevaluated, false};
+const a = <int>[];
+const b = <int?>[];
+const mapNotAgnosticOK = {a: 0, b: 1};
+const setNotAgnosticOK = {a, b};
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/folder.options b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/folder.options
new file mode 100644
index 0000000..41f34dd
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/folder.options
@@ -0,0 +1,5 @@
+--no-defines
+--target=none
+--no-verify
+--nnbd-agnostic
+--enable-experiment=non-nullable,triple-shift
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart
new file mode 100644
index 0000000..f790c4e
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const int foo = 42 * 42;
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const blaSymbol = #_x;
+
+main() {
+  _x();
+  const bool.fromEnvironment("foo");
+  print(bar);
+}
+
+void _x() {
+  print(foo);
+  print(bar);
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect
new file mode 100644
index 0000000..55d4864
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.outline.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int foo = 42.{core::num::*}(42);
+static const field core::String bar = "hello ${const core::String::fromEnvironment("baz", defaultValue: "world")}!";
+static const field core::bool baz = true && true && (false || true) && 42.{core::num::==}(21.{core::num::*}(4).{core::num::/}(2));
+static const field core::Symbol blaSymbol = #_x;
+static method main() → dynamic
+  ;
+static method _x() → void
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///rudimentary_test_01.dart:5:20 -> IntConstant(1764)
+Evaluated with empty environment: StringConcatenation @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello world!")
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///rudimentary_test_01.dart:7:27 -> StringConstant("world")
+Evaluated: LogicalExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:8:50 -> BoolConstant(true)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///rudimentary_test_01.dart:9:19 -> SymbolConstant(#_x)
+Extra constant evaluation: evaluated: 5, effectively constant: 5
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.expect
new file mode 100644
index 0000000..113d7a2
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int foo = #C1;
+static const field core::String bar = #C6;
+static const field core::bool baz = #C7;
+static const field core::Symbol blaSymbol = #C8;
+static method main() → dynamic {
+  self::_x();
+  #C10;
+  core::print(#C11);
+}
+static method _x() → void {
+  core::print(#C1);
+  core::print(#C12);
+}
+
+constants  {
+  #C1 = 1764
+  #C2 = "hello "
+  #C3 = "baz"
+  #C4 = "world"
+  #C5 = "!"
+  #C6 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+  #C7 = true
+  #C8 = #org-dartlang-testcase:///rudimentary_test_01.dart::_x
+  #C9 = "foo"
+  #C10 = eval const core::bool::fromEnvironment(#C9)
+  #C11 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+  #C12 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.transformed.expect
new file mode 100644
index 0000000..6957744
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.strong.transformed.expect
@@ -0,0 +1,39 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static const field core::int foo = #C1;
+static const field core::String bar = #C6;
+static const field core::bool baz = #C7;
+static const field core::Symbol blaSymbol = #C8;
+static method main() → dynamic {
+  self::_x();
+  #C10;
+  core::print(#C11);
+}
+static method _x() → void {
+  core::print(#C1);
+  core::print(#C12);
+}
+
+constants  {
+  #C1 = 1764
+  #C2 = "hello "
+  #C3 = "baz"
+  #C4 = "world"
+  #C5 = "!"
+  #C6 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+  #C7 = true
+  #C8 = #org-dartlang-testcase:///rudimentary_test_01.dart::_x
+  #C9 = "foo"
+  #C10 = eval const core::bool::fromEnvironment(#C9)
+  #C11 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+  #C12 = eval "${#C2}${const core::String::fromEnvironment(#C3, defaultValue: #C4)}${#C5}"
+}
+
+Extra constant evaluation status:
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:13:9 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello world!")
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello world!")
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///rudimentary_test_01.dart:6:18 -> StringConstant("hello world!")
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline.expect
new file mode 100644
index 0000000..e88a140
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline.expect
@@ -0,0 +1,7 @@
+const int foo = 42 * 42;
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const blaSymbol = #_x;
+main() {}
+void _x() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8e6f0e5
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/rudimentary_test_01.dart.textual_outline_modelled.expect
@@ -0,0 +1,7 @@
+const String bar =
+    "hello" " " "${String.fromEnvironment("baz", defaultValue: "world")}" "!";
+const blaSymbol = #_x;
+const bool baz = true && true && (false || true) && (42 == 21 * 4 / 2);
+const int foo = 42 * 42;
+main() {}
+void _x() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart
new file mode 100644
index 0000000..43e4383
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart
@@ -0,0 +1,144 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "various_lib.dart" deferred as lib;
+
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const bool? barFromEnvOrNull0 = const bool.fromEnvironment("bar") ? true : null;
+const bool barFromEnvOrNull =
+    const bool.fromEnvironment("bar", defaultValue: barFromEnvOrNull0!);
+const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+const bool andOnNull = barFromEnvOrNull && true;
+const bool andOnNull2 = true && barFromEnvOrNull;
+const bool orOnNull = barFromEnvOrNull || true;
+const bool orOnNull2 = barFromEnvOrNull || false;
+const bool orOnNull3 = true || barFromEnvOrNull;
+const bool orOnNull4 = false || barFromEnvOrNull;
+
+const fromDeferredLib = lib.x;
+
+class Foo<E> {
+  final bool saved;
+  final bool saved2;
+  const bool initialized =
+      const bool.fromEnvironment("foo", defaultValue: barFromEnv);
+  final E value;
+
+  const Foo(this.value,
+      {this.saved2: const bool.fromEnvironment("foo", defaultValue: barFromEnv),
+      bool x: const bool.fromEnvironment("foo", defaultValue: barFromEnv)})
+      : saved = x;
+}
+
+const x = const Foo<int>(42);
+
+const bool? y = true;
+const bool z = !(y!);
+
+const maybeInt = bool.fromEnvironment("foo") ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const maybeInt2 = z ? 42 : true;
+const bool isItInt2 = maybeInt2 is int ? true : false;
+const maybeInt3 = z ? 42 : null;
+const bool isItInt3 = maybeInt3 is int ? true : false;
+
+const dynamic listOfNull = [null];
+const bool isListOfNull = listOfNull is List<Null>;
+const dynamic listOfInt = [42];
+const bool isListOfInt = listOfInt is List<int>;
+const bool isList = listOfInt is List;
+const dynamic setOfInt = {42};
+const bool isSetOfInt = setOfInt is Set<int>;
+const dynamic mapOfInt = {42: 42};
+const bool isMapOfInt = mapOfInt is Map<int, int>;
+const dynamic listOfListOfInt = [
+  [42]
+];
+const bool isListOfListOfInt = listOfListOfInt is List<List<int>>;
+const dynamic setOfSetOfInt = {
+  {42}
+};
+const bool isSetOfSetOfInt = setOfSetOfInt is Set<Set<int>>;
+const dynamic mapOfMapOfInt1 = {
+  {42: 42}: 42
+};
+const dynamic mapOfMapOfInt2 = {
+  42: {42: 42}
+};
+const bool isMapOfMapOfInt1 = mapOfMapOfInt1 is Map<Map<int, int>, int>;
+const bool isMapOfMapOfInt2 = mapOfMapOfInt2 is Map<int, Map<int, int>>;
+
+const Symbol symbolWithUnevaluatedParameter =
+    const Symbol(String.fromEnvironment("foo"));
+const Symbol symbolWithInvalidName = const Symbol("42");
+
+class A {
+  const A();
+
+  A operator -() => this;
+}
+
+class B implements A {
+  const B();
+
+  B operator -() => this;
+}
+
+class C implements A {
+  const C();
+
+  C operator -() => this;
+}
+
+class Class<T extends A> {
+  const Class(T t);
+  const Class.redirect(dynamic t) : this(t);
+  const Class.method(T t) : this(-t);
+}
+
+class Subclass<T extends A> extends Class<T> {
+  const Subclass(dynamic t) : super(t);
+}
+
+const c0 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(C());
+const c1 = bool.fromEnvironment("x") ? null : const Class<A>.method(A());
+const c2 = bool.fromEnvironment("x") ? null : const Subclass<B>(C());
+const c3 = bool.fromEnvironment("x") ? null : const Class<A>(A());
+const c4 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(B());
+const c5 = bool.fromEnvironment("x") ? null : const Subclass<A>(A());
+const c6 = bool.fromEnvironment("x") ? null : const Subclass<B>(B());
+
+typedef F = int Function(int, {int named});
+const f = F;
+
+class ConstClassWithF {
+  final F foo;
+  const ConstClassWithF(this.foo);
+}
+
+int procedure(int i, {int named}) => i;
+ConstClassWithF constClassWithF1 = const ConstClassWithF(procedure);
+const ConstClassWithF constClassWithF2 = const ConstClassWithF(procedure);
+
+const bool unevaluatedBool = bool.fromEnvironment("foo");
+const bool notUnevaluatedBool = !unevaluatedBool;
+const bool? unevaluatedBoolOrNull =
+    bool.fromEnvironment("bar") ? unevaluatedBool : null;
+const bool unevaluatedBoolNotNull = unevaluatedBoolOrNull!;
+
+main() {
+  print(c0);
+  print(c1);
+  print(c2);
+  print(c3);
+  print(c4);
+  print(c5);
+  print(c6);
+  print(x);
+  print(x.saved);
+  print(x.value);
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect
new file mode 100644
index 0000000..4106544
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.outline.expect
@@ -0,0 +1,229 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:27:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const bool initialized =
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:25: Error: 'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+// Try moving the constant from the deferred library, or removing 'deferred' from the import.
+//
+// const fromDeferredLib = lib.x;
+//                         ^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:14:30: Warning: Operand of null-aware operation '??' has type 'bool' which excludes null.
+// const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+//                              ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+//  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+//   const Class.method(T t) : this(-t);
+//                                  ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:123:27: Error: Optional parameter 'named' should have a default value because its type 'int' doesn't allow null.
+// int procedure(int i, {int named}) => i;
+//                           ^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "various_lib.dart" as var;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///various_lib.dart" deferred as lib;
+
+typedef F = (core::int, {named: core::int}) → core::int;
+class Foo<E extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool saved;
+  final field core::bool saved2;
+  field core::bool initialized;
+  final field self::Foo::E% value;
+  const constructor •(self::Foo::E% value, {core::bool saved2 = const core::bool::fromEnvironment("foo", defaultValue: self::barFromEnv), core::bool x = const core::bool::fromEnvironment("foo", defaultValue: self::barFromEnv)}) → self::Foo<self::Foo::E%>
+    : self::Foo::value = value, self::Foo::saved2 = saved2, self::Foo::saved = x, super core::Object::•()
+    ;
+}
+class A extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator unary-() → self::A
+    ;
+}
+class B extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+  operator unary-() → self::B
+    ;
+}
+class C extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator unary-() → self::C
+    ;
+}
+class Class<T extends self::A = self::A> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::Class::T t) → self::Class<self::Class::T>
+    : super core::Object::•()
+    ;
+  const constructor redirect(dynamic t) → self::Class<self::Class::T>
+    : this self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Class::T)
+    ;
+  const constructor method(self::Class::T t) → self::Class<self::Class::T>
+    : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+    ;
+}
+class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
+  const constructor •(dynamic t) → self::Subclass<self::Subclass::T>
+    : super self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Subclass::T)
+    ;
+}
+class ConstClassWithF extends core::Object /*hasConstConstructor*/  {
+  final field (core::int, {named: core::int}) → core::int foo;
+  const constructor •((core::int, {named: core::int}) → core::int foo) → self::ConstClassWithF
+    : self::ConstClassWithF::foo = foo, super core::Object::•()
+    ;
+}
+static const field core::bool barFromEnv = const core::bool::fromEnvironment("bar");
+static const field core::bool hasBarEnv = const core::bool::hasEnvironment("bar");
+static const field core::bool? barFromEnvOrNull0 = const core::bool::fromEnvironment("bar") ?{core::bool?} true : null;
+static const field core::bool barFromEnvOrNull = const core::bool::fromEnvironment("bar", defaultValue: self::barFromEnvOrNull0!);
+static const field core::bool notBarFromEnvOrNull = !self::barFromEnvOrNull;
+static const field core::bool conditionalOnNull = self::barFromEnvOrNull ?{core::bool} true : false;
+static const field core::bool nullAwareOnNull = let final core::bool #t2 = self::barFromEnvOrNull in #t2.{core::Object::==}(null) ?{core::bool} true : #t2;
+static const field core::bool andOnNull = self::barFromEnvOrNull && true;
+static const field core::bool andOnNull2 = true && self::barFromEnvOrNull;
+static const field core::bool orOnNull = self::barFromEnvOrNull || true;
+static const field core::bool orOnNull2 = self::barFromEnvOrNull || false;
+static const field core::bool orOnNull3 = true || self::barFromEnvOrNull;
+static const field core::bool orOnNull4 = false || self::barFromEnvOrNull;
+static const field core::int fromDeferredLib = let final dynamic #t3 = CheckLibraryIsLoaded(lib) in var::x;
+static const field self::Foo<core::int> x = const self::Foo::•<core::int>(42);
+static const field core::bool? y = true;
+static const field core::bool z = !self::y!;
+static const field core::Object maybeInt = const core::bool::fromEnvironment("foo") ?{core::Object} 42 : true;
+static const field core::bool isItInt = self::maybeInt is{ForNonNullableByDefault} core::int ?{core::bool} true : false;
+static const field core::Object maybeInt2 = self::z ?{core::Object} 42 : true;
+static const field core::bool isItInt2 = self::maybeInt2 is{ForNonNullableByDefault} core::int ?{core::bool} true : false;
+static const field core::int? maybeInt3 = self::z ?{core::int?} 42 : null;
+static const field core::bool isItInt3 = self::maybeInt3 is{ForNonNullableByDefault} core::int ?{core::bool} true : false;
+static const field dynamic listOfNull = const <core::Null?>[null];
+static const field core::bool isListOfNull = self::listOfNull is{ForNonNullableByDefault} core::List<core::Null?>;
+static const field dynamic listOfInt = const <core::int>[42];
+static const field core::bool isListOfInt = self::listOfInt is{ForNonNullableByDefault} core::List<core::int>;
+static const field core::bool isList = self::listOfInt is{ForNonNullableByDefault} core::List<dynamic>;
+static const field dynamic setOfInt = const <core::int>{42};
+static const field core::bool isSetOfInt = self::setOfInt is{ForNonNullableByDefault} core::Set<core::int>;
+static const field dynamic mapOfInt = const <core::int, core::int>{42: 42};
+static const field core::bool isMapOfInt = self::mapOfInt is{ForNonNullableByDefault} core::Map<core::int, core::int>;
+static const field dynamic listOfListOfInt = const <core::List<core::int>>[const <core::int>[42]];
+static const field core::bool isListOfListOfInt = self::listOfListOfInt is{ForNonNullableByDefault} core::List<core::List<core::int>>;
+static const field dynamic setOfSetOfInt = const <core::Set<core::int>>{const <core::int>{42}};
+static const field core::bool isSetOfSetOfInt = self::setOfSetOfInt is{ForNonNullableByDefault} core::Set<core::Set<core::int>>;
+static const field dynamic mapOfMapOfInt1 = const <core::Map<core::int, core::int>, core::int>{const <core::int, core::int>{42: 42}: 42};
+static const field dynamic mapOfMapOfInt2 = const <core::int, core::Map<core::int, core::int>>{42: const <core::int, core::int>{42: 42}};
+static const field core::bool isMapOfMapOfInt1 = self::mapOfMapOfInt1 is{ForNonNullableByDefault} core::Map<core::Map<core::int, core::int>, core::int>;
+static const field core::bool isMapOfMapOfInt2 = self::mapOfMapOfInt2 is{ForNonNullableByDefault} core::Map<core::int, core::Map<core::int, core::int>>;
+static const field core::Symbol symbolWithUnevaluatedParameter = const _in::Symbol::•(const core::String::fromEnvironment("foo"));
+static const field core::Symbol symbolWithInvalidName = const _in::Symbol::•("42");
+static const field self::Class<self::B>? c0 = const core::bool::fromEnvironment("x") ?{self::Class<self::B>?} null : const self::Class::redirect<self::B>(const self::C::•());
+static const field self::Class<self::A>? c1 = const core::bool::fromEnvironment("x") ?{self::Class<self::A>?} null : const self::Class::method<self::A>(const self::A::•());
+static const field self::Subclass<self::B>? c2 = const core::bool::fromEnvironment("x") ?{self::Subclass<self::B>?} null : const self::Subclass::•<self::B>(const self::C::•());
+static const field self::Class<self::A>? c3 = const core::bool::fromEnvironment("x") ?{self::Class<self::A>?} null : const self::Class::•<self::A>(const self::A::•());
+static const field self::Class<self::B>? c4 = const core::bool::fromEnvironment("x") ?{self::Class<self::B>?} null : const self::Class::redirect<self::B>(const self::B::•());
+static const field self::Subclass<self::A>? c5 = const core::bool::fromEnvironment("x") ?{self::Subclass<self::A>?} null : const self::Subclass::•<self::A>(const self::A::•());
+static const field self::Subclass<self::B>? c6 = const core::bool::fromEnvironment("x") ?{self::Subclass<self::B>?} null : const self::Subclass::•<self::B>(const self::B::•());
+static const field core::Type f = (core::int, {named: core::int}) → core::int;
+static field self::ConstClassWithF constClassWithF1;
+static const field self::ConstClassWithF constClassWithF2 = const self::ConstClassWithF::•(self::procedure);
+static const field core::bool unevaluatedBool = const core::bool::fromEnvironment("foo");
+static const field core::bool notUnevaluatedBool = !self::unevaluatedBool;
+static const field core::bool? unevaluatedBoolOrNull = const core::bool::fromEnvironment("bar") ?{core::bool?} self::unevaluatedBool : null;
+static const field core::bool unevaluatedBoolNotNull = self::unevaluatedBoolOrNull!;
+static method procedure(core::int i, {core::int named}) → core::int
+  ;
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as var;
+import "dart:core" as core;
+
+static const field core::int x = 42;
+
+
+Extra constant evaluation status:
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:32:27 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:32:69 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:33:21 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:33:63 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:7:31 -> BoolConstant(false)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:8:30 -> BoolConstant(false)
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:9:67 -> NullConstant(null)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:9:39 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:11:53 -> NullConstant(null)
+Evaluated: LogicalExpression @ org-dartlang-testcase:///various.dart:19:29 -> BoolConstant(true)
+Evaluated: StaticGet @ org-dartlang-testcase:///various.dart:22:29 -> IntConstant(42)
+Evaluated with empty environment: ConstructorInvocation @ org-dartlang-testcase:///various.dart:37:17 -> InstanceConstant(const Foo<int>{Foo.saved: false, Foo.saved2: false, Foo.initialized: null, Foo.value: 42})
+Evaluated: Not @ org-dartlang-testcase:///various.dart:40:16 -> BoolConstant(false)
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:42:46 -> BoolConstant(true)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:42:23 -> BoolConstant(false)
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:43:38 -> BoolConstant(false)
+Evaluated with empty environment: IsExpression @ org-dartlang-testcase:///various.dart:43:31 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:43:22 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:44:21 -> BoolConstant(true)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:45:40 -> BoolConstant(false)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:46:21 -> NullConstant(null)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///various.dart:47:40 -> BoolConstant(false)
+Evaluated: ListLiteral @ org-dartlang-testcase:///various.dart:49:28 -> ListConstant(const <Null?>[null])
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:50:38 -> BoolConstant(true)
+Evaluated: ListLiteral @ org-dartlang-testcase:///various.dart:51:27 -> ListConstant(const <int>[42])
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:52:36 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:53:31 -> BoolConstant(true)
+Evaluated: SetLiteral @ org-dartlang-testcase:///various.dart:54:26 -> SetConstant(const <int>{42})
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:55:34 -> BoolConstant(true)
+Evaluated: MapLiteral @ org-dartlang-testcase:///various.dart:56:26 -> MapConstant(const <int, int>{42: 42})
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:57:34 -> BoolConstant(true)
+Evaluated: ListLiteral @ org-dartlang-testcase:///various.dart:58:33 -> ListConstant(const <List<int>>[const <int>[42]])
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:61:48 -> BoolConstant(true)
+Evaluated: SetLiteral @ org-dartlang-testcase:///various.dart:62:31 -> SetConstant(const <Set<int>>{const <int>{42}})
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:65:44 -> BoolConstant(true)
+Evaluated: MapLiteral @ org-dartlang-testcase:///various.dart:66:32 -> MapConstant(const <Map<int, int>, int>{const <int, int>{42: 42}: 42})
+Evaluated: MapLiteral @ org-dartlang-testcase:///various.dart:69:32 -> MapConstant(const <int, Map<int, int>>{42: const <int, int>{42: 42}})
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:72:46 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///various.dart:73:46 -> BoolConstant(true)
+Evaluated with empty environment: ConstructorInvocation @ org-dartlang-testcase:///various.dart:76:11 -> SymbolConstant(#)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:76:25 -> StringConstant("")
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:107:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:107:71 -> InstanceConstant(const C{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:108:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:108:69 -> InstanceConstant(const A{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:109:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:109:65 -> InstanceConstant(const C{})
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:110:38 -> InstanceConstant(const Class<A>{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:110:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:110:53 -> InstanceConstant(const Class<A>{})
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:111:38 -> InstanceConstant(const Class<B>{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:111:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:111:53 -> InstanceConstant(const Class<B>{})
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:112:38 -> InstanceConstant(const Subclass<A>{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:112:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:112:53 -> InstanceConstant(const Subclass<A>{})
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:113:38 -> InstanceConstant(const Subclass<B>{})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:113:17 -> BoolConstant(false)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:113:53 -> InstanceConstant(const Subclass<B>{})
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various.dart:116:11 -> TypeLiteralConstant(int Function(int, {named: int}))
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various.dart:125:48 -> InstanceConstant(const ConstClassWithF{ConstClassWithF.foo: procedure})
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:127:35 -> BoolConstant(false)
+Evaluated with empty environment: Not @ org-dartlang-testcase:///various.dart:128:33 -> BoolConstant(true)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:128:34 -> BoolConstant(false)
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various.dart:130:33 -> NullConstant(null)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various.dart:130:10 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:130:35 -> BoolConstant(false)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various.dart:131:37 -> NullConstant(null)
+Extra constant evaluation: evaluated: 112, effectively constant: 68
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect
new file mode 100644
index 0000000..3950e82
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.expect
@@ -0,0 +1,260 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:27:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const bool initialized =
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:25: Error: 'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+// Try moving the constant from the deferred library, or removing 'deferred' from the import.
+//
+// const fromDeferredLib = lib.x;
+//                         ^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:14:30: Warning: Operand of null-aware operation '??' has type 'bool' which excludes null.
+// const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+//                              ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+//  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+//   const Class.method(T t) : this(-t);
+//                                  ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:123:27: Error: Optional parameter 'named' should have a default value because its type 'int' doesn't allow null.
+// int procedure(int i, {int named}) => i;
+//                           ^^^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:31:9: Error: Constructor is marked 'const' so all fields must be final.
+//   const Foo(this.value,
+//         ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:27:14: Context: Field isn't final, but constructor is 'const'.
+//   const bool initialized =
+//              ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:29: Error: Constant evaluation error:
+// const fromDeferredLib = lib.x;
+//                             ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:29: Context: 'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+// Try moving the constant from the deferred library, or removing 'deferred' from the import.
+//
+// const fromDeferredLib = lib.x;
+//                             ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:7: Context: While analyzing:
+// const fromDeferredLib = lib.x;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:44: Error: Constant evaluation error:
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:51: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '"42"'.
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//                                                   ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:14: Context: While analyzing:
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///various_lib.dart" deferred as lib;
+
+typedef F = (core::int, {named: core::int}) → core::int;
+class Foo<E extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool saved;
+  final field core::bool saved2;
+  field core::bool initialized = #C3;
+  final field self::Foo::E% value;
+  const constructor •(self::Foo::E% value, {core::bool saved2 = #C4, core::bool x = #C5}) → self::Foo<self::Foo::E%>
+    : self::Foo::value = value, self::Foo::saved2 = saved2, self::Foo::saved = x, super core::Object::•()
+    ;
+}
+class A extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator unary-() → self::A
+    return this;
+}
+class B extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+  operator unary-() → self::B
+    return this;
+}
+class C extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator unary-() → self::C
+    return this;
+}
+class Class<T extends self::A = self::A> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::Class::T t) → self::Class<self::Class::T>
+    : super core::Object::•()
+    ;
+  const constructor redirect(dynamic t) → self::Class<self::Class::T>
+    : this self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Class::T)
+    ;
+  const constructor method(self::Class::T t) → self::Class<self::Class::T>
+    : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+    ;
+}
+class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
+  const constructor •(dynamic t) → self::Subclass<self::Subclass::T>
+    : super self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Subclass::T)
+    ;
+}
+class ConstClassWithF extends core::Object /*hasConstConstructor*/  {
+  final field (core::int, {named: core::int}) → core::int foo;
+  const constructor •((core::int, {named: core::int}) → core::int foo) → self::ConstClassWithF
+    : self::ConstClassWithF::foo = foo, super core::Object::•()
+    ;
+}
+static const field core::bool barFromEnv = #C6;
+static const field core::bool hasBarEnv = #C7;
+static const field core::bool? barFromEnvOrNull0 = #C10;
+static const field core::bool barFromEnvOrNull = #C11;
+static const field core::bool notBarFromEnvOrNull = #C12;
+static const field core::bool conditionalOnNull = #C14;
+static const field core::bool nullAwareOnNull = #C15;
+static const field core::bool andOnNull = #C16;
+static const field core::bool andOnNull2 = #C17;
+static const field core::bool orOnNull = #C18;
+static const field core::bool orOnNull2 = #C19;
+static const field core::bool orOnNull3 = #C8;
+static const field core::bool orOnNull4 = #C20;
+static const field core::int fromDeferredLib = invalid-expression "'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.";
+static const field self::Foo<core::int> x = #C22;
+static const field core::bool? y = #C8;
+static const field core::bool z = #C13;
+static const field core::Object maybeInt = #C23;
+static const field core::bool isItInt = #C24;
+static const field core::Object maybeInt2 = #C8;
+static const field core::bool isItInt2 = #C13;
+static const field core::int? maybeInt3 = #C9;
+static const field core::bool isItInt3 = #C13;
+static const field dynamic listOfNull = #C25;
+static const field core::bool isListOfNull = #C8;
+static const field dynamic listOfInt = #C26;
+static const field core::bool isListOfInt = #C8;
+static const field core::bool isList = #C8;
+static const field dynamic setOfInt = #C27;
+static const field core::bool isSetOfInt = #C8;
+static const field dynamic mapOfInt = #C28;
+static const field core::bool isMapOfInt = #C8;
+static const field dynamic listOfListOfInt = #C29;
+static const field core::bool isListOfListOfInt = #C8;
+static const field dynamic setOfSetOfInt = #C30;
+static const field core::bool isSetOfSetOfInt = #C8;
+static const field dynamic mapOfMapOfInt1 = #C31;
+static const field dynamic mapOfMapOfInt2 = #C32;
+static const field core::bool isMapOfMapOfInt1 = #C8;
+static const field core::bool isMapOfMapOfInt2 = #C8;
+static const field core::Symbol symbolWithUnevaluatedParameter = #C33;
+static const field core::Symbol symbolWithInvalidName = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\"42\"'.";
+static const field self::Class<self::B>? c0 = #C35;
+static const field self::Class<self::A>? c1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^";
+static const field self::Subclass<self::B>? c2 = #C36;
+static const field self::Class<self::A>? c3 = #C37;
+static const field self::Class<self::B>? c4 = #C38;
+static const field self::Subclass<self::A>? c5 = #C39;
+static const field self::Subclass<self::B>? c6 = #C40;
+static const field core::Type f = #C41;
+static field self::ConstClassWithF constClassWithF1 = #C43;
+static const field self::ConstClassWithF constClassWithF2 = #C43;
+static const field core::bool unevaluatedBool = #C44;
+static const field core::bool notUnevaluatedBool = #C45;
+static const field core::bool? unevaluatedBoolOrNull = #C46;
+static const field core::bool unevaluatedBoolNotNull = #C47;
+static method procedure(core::int i, {core::int named = #C9}) → core::int
+  return i;
+static method main() → dynamic {
+  core::print(#C48);
+  core::print(invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^");
+  core::print(#C49);
+  core::print(#C50);
+  core::print(#C51);
+  core::print(#C52);
+  core::print(#C53);
+  core::print(#C54);
+  core::print((#C55).{self::Foo::saved});
+  core::print((#C56).{self::Foo::value});
+}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+static const field core::int x = #C21;
+
+constants  {
+  #C1 = "foo"
+  #C2 = "bar"
+  #C3 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C4 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C5 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C6 = eval const core::bool::fromEnvironment(#C2)
+  #C7 = eval const core::bool::hasEnvironment(#C2)
+  #C8 = true
+  #C9 = null
+  #C10 = eval const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9
+  #C11 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C12 = eval !const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C13 = false
+  #C14 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) ?{core::bool} #C8 : #C13
+  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!).==(#C9) ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C16 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) && (#C8)
+  #C17 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C18 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C8)
+  #C19 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C13)
+  #C20 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C21 = 42
+  #C22 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C23 = eval const core::bool::fromEnvironment(#C1) ?{core::Object} #C21 : #C8
+  #C24 = eval (const core::bool::fromEnvironment(#C1) ?{core::Object} #C21 : #C8) is{ForNonNullableByDefault} core::int ?{core::bool} #C8 : #C13
+  #C25 = <core::Null?>[#C9]
+  #C26 = <core::int>[#C21]
+  #C27 = <core::int>{#C21}
+  #C28 = <core::int, core::int>{#C21:#C21)
+  #C29 = <core::List<core::int>>[#C26]
+  #C30 = <core::Set<core::int>>{#C27}
+  #C31 = <core::Map<core::int, core::int>, core::int>{#C28:#C21)
+  #C32 = <core::int, core::Map<core::int, core::int>>{#C21:#C28)
+  #C33 = eval const _in::Symbol::•(const core::String::fromEnvironment(#C1))
+  #C34 = "x"
+  #C35 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C36 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C37 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::A>?} #C9 : self::Class<self::A>{self::A{}}
+  #C38 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C39 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A>{(self::A{}) as{ForNonNullableByDefault} self::A}
+  #C40 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C41 = TypeLiteralConstant((core::int, {named: core::int}) → core::int)
+  #C42 = tearoff self::procedure
+  #C43 = self::ConstClassWithF {foo:#C42}
+  #C44 = eval const core::bool::fromEnvironment(#C1)
+  #C45 = eval !const core::bool::fromEnvironment(#C1)
+  #C46 = eval const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9
+  #C47 = eval (const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9)!
+  #C48 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C49 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C50 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::A>?} #C9 : self::Class<self::A>{self::A{}}
+  #C51 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C52 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A>{(self::A{}) as{ForNonNullableByDefault} self::A}
+  #C53 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C54 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C55 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C56 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect
new file mode 100644
index 0000000..0d34728
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.strong.transformed.expect
@@ -0,0 +1,287 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:27:3: Error: Only static fields can be declared as const.
+// Try using 'final' instead of 'const', or adding the keyword 'static'.
+//   const bool initialized =
+//   ^^^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:25: Error: 'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+// Try moving the constant from the deferred library, or removing 'deferred' from the import.
+//
+// const fromDeferredLib = lib.x;
+//                         ^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:14:30: Warning: Operand of null-aware operation '??' has type 'bool' which excludes null.
+// const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+//                              ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+//  - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+//   const Class.method(T t) : this(-t);
+//                                  ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:123:27: Error: Optional parameter 'named' should have a default value because its type 'int' doesn't allow null.
+// int procedure(int i, {int named}) => i;
+//                           ^^^^^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:31:9: Error: Constructor is marked 'const' so all fields must be final.
+//   const Foo(this.value,
+//         ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:27:14: Context: Field isn't final, but constructor is 'const'.
+//   const bool initialized =
+//              ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:29: Error: Constant evaluation error:
+// const fromDeferredLib = lib.x;
+//                             ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:29: Context: 'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.
+// Try moving the constant from the deferred library, or removing 'deferred' from the import.
+//
+// const fromDeferredLib = lib.x;
+//                             ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:22:7: Context: While analyzing:
+// const fromDeferredLib = lib.x;
+//       ^
+//
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:44: Error: Constant evaluation error:
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//                                            ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:51: Context: The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '"42"'.
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//                                                   ^
+// pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:77:14: Context: While analyzing:
+// const Symbol symbolWithInvalidName = const Symbol("42");
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///various_lib.dart" deferred as lib;
+
+typedef F = (core::int, {named: core::int}) → core::int;
+class Foo<E extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field core::bool saved;
+  final field core::bool saved2;
+  field core::bool initialized = #C3;
+  final field self::Foo::E% value;
+  const constructor •(self::Foo::E% value, {core::bool saved2 = #C4, core::bool x = #C5}) → self::Foo<self::Foo::E%>
+    : self::Foo::value = value, self::Foo::saved2 = saved2, self::Foo::saved = x, super core::Object::•()
+    ;
+}
+class A extends core::Object /*hasConstConstructor*/  {
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator unary-() → self::A
+    return this;
+}
+class B extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+  operator unary-() → self::B
+    return this;
+}
+class C extends core::Object implements self::A /*hasConstConstructor*/  {
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  operator unary-() → self::C
+    return this;
+}
+class Class<T extends self::A = self::A> extends core::Object /*hasConstConstructor*/  {
+  const constructor •(self::Class::T t) → self::Class<self::Class::T>
+    : super core::Object::•()
+    ;
+  const constructor redirect(dynamic t) → self::Class<self::Class::T>
+    : this self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Class::T)
+    ;
+  const constructor method(self::Class::T t) → self::Class<self::Class::T>
+    : this self::Class::•(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^" in t.{self::A::unary-}() as{TypeError,ForNonNullableByDefault} <BottomType>)
+    ;
+}
+class Subclass<T extends self::A = self::A> extends self::Class<self::Subclass::T> /*hasConstConstructor*/  {
+  const constructor •(dynamic t) → self::Subclass<self::Subclass::T>
+    : super self::Class::•(t as{TypeError,ForDynamic,ForNonNullableByDefault} self::Subclass::T)
+    ;
+}
+class ConstClassWithF extends core::Object /*hasConstConstructor*/  {
+  final field (core::int, {named: core::int}) → core::int foo;
+  const constructor •((core::int, {named: core::int}) → core::int foo) → self::ConstClassWithF
+    : self::ConstClassWithF::foo = foo, super core::Object::•()
+    ;
+}
+static const field core::bool barFromEnv = #C6;
+static const field core::bool hasBarEnv = #C7;
+static const field core::bool? barFromEnvOrNull0 = #C10;
+static const field core::bool barFromEnvOrNull = #C11;
+static const field core::bool notBarFromEnvOrNull = #C12;
+static const field core::bool conditionalOnNull = #C14;
+static const field core::bool nullAwareOnNull = #C15;
+static const field core::bool andOnNull = #C16;
+static const field core::bool andOnNull2 = #C17;
+static const field core::bool orOnNull = #C18;
+static const field core::bool orOnNull2 = #C19;
+static const field core::bool orOnNull3 = #C8;
+static const field core::bool orOnNull4 = #C20;
+static const field core::int fromDeferredLib = invalid-expression "'lib' can't be used in a constant expression because it's marked as 'deferred' which means it isn't available until loaded.";
+static const field self::Foo<core::int> x = #C22;
+static const field core::bool? y = #C8;
+static const field core::bool z = #C13;
+static const field core::Object maybeInt = #C23;
+static const field core::bool isItInt = #C24;
+static const field core::Object maybeInt2 = #C8;
+static const field core::bool isItInt2 = #C13;
+static const field core::int? maybeInt3 = #C9;
+static const field core::bool isItInt3 = #C13;
+static const field dynamic listOfNull = #C25;
+static const field core::bool isListOfNull = #C8;
+static const field dynamic listOfInt = #C26;
+static const field core::bool isListOfInt = #C8;
+static const field core::bool isList = #C8;
+static const field dynamic setOfInt = #C27;
+static const field core::bool isSetOfInt = #C8;
+static const field dynamic mapOfInt = #C28;
+static const field core::bool isMapOfInt = #C8;
+static const field dynamic listOfListOfInt = #C29;
+static const field core::bool isListOfListOfInt = #C8;
+static const field dynamic setOfSetOfInt = #C30;
+static const field core::bool isSetOfSetOfInt = #C8;
+static const field dynamic mapOfMapOfInt1 = #C31;
+static const field dynamic mapOfMapOfInt2 = #C32;
+static const field core::bool isMapOfMapOfInt1 = #C8;
+static const field core::bool isMapOfMapOfInt2 = #C8;
+static const field core::Symbol symbolWithUnevaluatedParameter = #C33;
+static const field core::Symbol symbolWithInvalidName = invalid-expression "The symbol name must be a valid public Dart member name, public constructor name, or library name, optionally qualified, but was '\"42\"'.";
+static const field self::Class<self::B>? c0 = #C35;
+static const field self::Class<self::A>? c1 = invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^";
+static const field self::Subclass<self::B>? c2 = #C36;
+static const field self::Class<self::A>? c3 = #C37;
+static const field self::Class<self::B>? c4 = #C38;
+static const field self::Subclass<self::A>? c5 = #C39;
+static const field self::Subclass<self::B>? c6 = #C40;
+static const field core::Type f = #C41;
+static field self::ConstClassWithF constClassWithF1 = #C43;
+static const field self::ConstClassWithF constClassWithF2 = #C43;
+static const field core::bool unevaluatedBool = #C44;
+static const field core::bool notUnevaluatedBool = #C45;
+static const field core::bool? unevaluatedBoolOrNull = #C46;
+static const field core::bool unevaluatedBoolNotNull = #C47;
+static method procedure(core::int i, {core::int named = #C9}) → core::int
+  return i;
+static method main() → dynamic {
+  core::print(#C48);
+  core::print(invalid-expression "pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart:100:34: Error: The argument type 'A' can't be assigned to the parameter type 'T'.
+ - 'A' is from 'pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart'.
+  const Class.method(T t) : this(-t);
+                                 ^");
+  core::print(#C49);
+  core::print(#C50);
+  core::print(#C51);
+  core::print(#C52);
+  core::print(#C53);
+  core::print(#C54);
+  core::print((#C55).{self::Foo::saved});
+  core::print((#C56).{self::Foo::value});
+}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+static const field core::int x = #C21;
+
+constants  {
+  #C1 = "foo"
+  #C2 = "bar"
+  #C3 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C4 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C5 = eval const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2))
+  #C6 = eval const core::bool::fromEnvironment(#C2)
+  #C7 = eval const core::bool::hasEnvironment(#C2)
+  #C8 = true
+  #C9 = null
+  #C10 = eval const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9
+  #C11 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C12 = eval !const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C13 = false
+  #C14 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) ?{core::bool} #C8 : #C13
+  #C15 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!).==(#C9) ?{core::bool} #C8 : const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C16 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) && (#C8)
+  #C17 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C18 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C8)
+  #C19 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!) || (#C13)
+  #C20 = eval const core::bool::fromEnvironment(#C2, defaultValue: (const core::bool::fromEnvironment(#C2) ?{core::bool?} #C8 : #C9)!)
+  #C21 = 42
+  #C22 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C23 = eval const core::bool::fromEnvironment(#C1) ?{core::Object} #C21 : #C8
+  #C24 = eval (const core::bool::fromEnvironment(#C1) ?{core::Object} #C21 : #C8) is{ForNonNullableByDefault} core::int ?{core::bool} #C8 : #C13
+  #C25 = <core::Null?>[#C9]
+  #C26 = <core::int>[#C21]
+  #C27 = <core::int>{#C21}
+  #C28 = <core::int, core::int>{#C21:#C21)
+  #C29 = <core::List<core::int>>[#C26]
+  #C30 = <core::Set<core::int>>{#C27}
+  #C31 = <core::Map<core::int, core::int>, core::int>{#C28:#C21)
+  #C32 = <core::int, core::Map<core::int, core::int>>{#C21:#C28)
+  #C33 = eval const _in::Symbol::•(const core::String::fromEnvironment(#C1))
+  #C34 = "x"
+  #C35 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C36 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C37 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::A>?} #C9 : self::Class<self::A>{self::A{}}
+  #C38 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C39 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A>{(self::A{}) as{ForNonNullableByDefault} self::A}
+  #C40 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C41 = TypeLiteralConstant((core::int, {named: core::int}) → core::int)
+  #C42 = tearoff self::procedure
+  #C43 = self::ConstClassWithF {foo:#C42}
+  #C44 = eval const core::bool::fromEnvironment(#C1)
+  #C45 = eval !const core::bool::fromEnvironment(#C1)
+  #C46 = eval const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9
+  #C47 = eval (const core::bool::fromEnvironment(#C2) ?{core::bool?} const core::bool::fromEnvironment(#C1) : #C9)!
+  #C48 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C49 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::C{}) as{ForNonNullableByDefault} self::B}
+  #C50 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::A>?} #C9 : self::Class<self::A>{self::A{}}
+  #C51 = eval const core::bool::fromEnvironment(#C34) ?{self::Class<self::B>?} #C9 : self::Class<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C52 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::A>?} #C9 : self::Subclass<self::A>{(self::A{}) as{ForNonNullableByDefault} self::A}
+  #C53 = eval const core::bool::fromEnvironment(#C34) ?{self::Subclass<self::B>?} #C9 : self::Subclass<self::B>{(self::B{}) as{ForNonNullableByDefault} self::B}
+  #C54 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C55 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+  #C56 = eval self::Foo<core::int>{saved:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), saved2:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), initialized:const core::bool::fromEnvironment(#C1, defaultValue: const core::bool::fromEnvironment(#C2)), value:#C21}
+}
+
+Extra constant evaluation status:
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:32:27 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:33:21 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:28:13 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:110:38 -> InstanceConstant(const Class<A>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:111:38 -> InstanceConstant(const Class<B>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:112:38 -> InstanceConstant(const Subclass<A>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:113:38 -> InstanceConstant(const Subclass<B>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:37:17 -> InstanceConstant(const Foo<int>{Foo.saved: false, Foo.saved2: false, Foo.initialized: false, Foo.value: 42})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:37:17 -> InstanceConstant(const Foo<int>{Foo.saved: false, Foo.saved2: false, Foo.initialized: false, Foo.value: 42})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:37:17 -> InstanceConstant(const Foo<int>{Foo.saved: false, Foo.saved2: false, Foo.initialized: false, Foo.value: 42})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:7:31 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:8:30 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:9:67 -> NullConstant(null)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:37:17 -> InstanceConstant(const Foo<int>{Foo.saved: false, Foo.saved2: false, Foo.initialized: false, Foo.value: 42})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:42:46 -> BoolConstant(true)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:43:38 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:76:11 -> SymbolConstant(#)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:110:38 -> InstanceConstant(const Class<A>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:111:38 -> InstanceConstant(const Class<B>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:112:38 -> InstanceConstant(const Subclass<A>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:113:38 -> InstanceConstant(const Subclass<B>{})
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:127:35 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:128:33 -> BoolConstant(true)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various.dart:130:33 -> NullConstant(null)
+Extra constant evaluation: evaluated: 66, effectively constant: 24
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline.expect
new file mode 100644
index 0000000..602836a
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline.expect
@@ -0,0 +1,117 @@
+import "various_lib.dart" deferred as lib;
+
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const bool? barFromEnvOrNull0 = const bool.fromEnvironment("bar") ? true : null;
+const bool barFromEnvOrNull =
+    const bool.fromEnvironment("bar", defaultValue: barFromEnvOrNull0!);
+const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+const bool andOnNull = barFromEnvOrNull && true;
+const bool andOnNull2 = true && barFromEnvOrNull;
+const bool orOnNull = barFromEnvOrNull || true;
+const bool orOnNull2 = barFromEnvOrNull || false;
+const bool orOnNull3 = true || barFromEnvOrNull;
+const bool orOnNull4 = false || barFromEnvOrNull;
+const fromDeferredLib = lib.x;
+
+class Foo<E> {
+  final bool saved;
+  final bool saved2;
+  const bool initialized =
+      const bool.fromEnvironment("foo", defaultValue: barFromEnv);
+  final E value;
+  const Foo(this.value,
+      {this.saved2: const bool.fromEnvironment("foo", defaultValue: barFromEnv),
+      bool x: const bool.fromEnvironment("foo", defaultValue: barFromEnv)})
+      : saved = x;
+}
+
+const x = const Foo<int>(42);
+const bool? y = true;
+const bool z = !(y!);
+const maybeInt = bool.fromEnvironment("foo") ? 42 : true;
+const bool isItInt = maybeInt is int ? true : false;
+const maybeInt2 = z ? 42 : true;
+const bool isItInt2 = maybeInt2 is int ? true : false;
+const maybeInt3 = z ? 42 : null;
+const bool isItInt3 = maybeInt3 is int ? true : false;
+const dynamic listOfNull = [null];
+const bool isListOfNull = listOfNull is List<Null>;
+const dynamic listOfInt = [42];
+const bool isListOfInt = listOfInt is List<int>;
+const bool isList = listOfInt is List;
+const dynamic setOfInt = {42};
+const bool isSetOfInt = setOfInt is Set<int>;
+const dynamic mapOfInt = {42: 42};
+const bool isMapOfInt = mapOfInt is Map<int, int>;
+const dynamic listOfListOfInt = [
+  [42]
+];
+const bool isListOfListOfInt = listOfListOfInt is List<List<int>>;
+const dynamic setOfSetOfInt = {
+  {42}
+};
+const bool isSetOfSetOfInt = setOfSetOfInt is Set<Set<int>>;
+const dynamic mapOfMapOfInt1 = {
+  {42: 42}: 42
+};
+const dynamic mapOfMapOfInt2 = {
+  42: {42: 42}
+};
+const bool isMapOfMapOfInt1 = mapOfMapOfInt1 is Map<Map<int, int>, int>;
+const bool isMapOfMapOfInt2 = mapOfMapOfInt2 is Map<int, Map<int, int>>;
+const Symbol symbolWithUnevaluatedParameter =
+    const Symbol(String.fromEnvironment("foo"));
+const Symbol symbolWithInvalidName = const Symbol("42");
+
+class A {
+  const A();
+  A operator -() => this;
+}
+
+class B implements A {
+  const B();
+  B operator -() => this;
+}
+
+class C implements A {
+  const C();
+  C operator -() => this;
+}
+
+class Class<T extends A> {
+  const Class(T t);
+  const Class.redirect(dynamic t) : this(t);
+  const Class.method(T t) : this(-t);
+}
+
+class Subclass<T extends A> extends Class<T> {
+  const Subclass(dynamic t) : super(t);
+}
+
+const c0 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(C());
+const c1 = bool.fromEnvironment("x") ? null : const Class<A>.method(A());
+const c2 = bool.fromEnvironment("x") ? null : const Subclass<B>(C());
+const c3 = bool.fromEnvironment("x") ? null : const Class<A>(A());
+const c4 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(B());
+const c5 = bool.fromEnvironment("x") ? null : const Subclass<A>(A());
+const c6 = bool.fromEnvironment("x") ? null : const Subclass<B>(B());
+typedef F = int Function(int, {int named});
+const f = F;
+
+class ConstClassWithF {
+  final F foo;
+  const ConstClassWithF(this.foo);
+}
+
+int procedure(int i, {int named}) => i;
+ConstClassWithF constClassWithF1 = const ConstClassWithF(procedure);
+const ConstClassWithF constClassWithF2 = const ConstClassWithF(procedure);
+const bool unevaluatedBool = bool.fromEnvironment("foo");
+const bool notUnevaluatedBool = !unevaluatedBool;
+const bool? unevaluatedBoolOrNull =
+    bool.fromEnvironment("bar") ? unevaluatedBool : null;
+const bool unevaluatedBoolNotNull = unevaluatedBoolOrNull!;
+main() {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..80ce452
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various.dart.textual_outline_modelled.expect
@@ -0,0 +1,115 @@
+import "various_lib.dart" deferred as lib;
+
+ConstClassWithF constClassWithF1 = const ConstClassWithF(procedure);
+
+class A {
+  A operator -() => this;
+  const A();
+}
+
+class B implements A {
+  B operator -() => this;
+  const B();
+}
+
+class C implements A {
+  C operator -() => this;
+  const C();
+}
+
+class Class<T extends A> {
+  const Class(T t);
+  const Class.method(T t) : this(-t);
+  const Class.redirect(dynamic t) : this(t);
+}
+
+class ConstClassWithF {
+  const ConstClassWithF(this.foo);
+  final F foo;
+}
+
+class Foo<E> {
+  const Foo(this.value,
+      {this.saved2: const bool.fromEnvironment("foo", defaultValue: barFromEnv),
+      bool x: const bool.fromEnvironment("foo", defaultValue: barFromEnv)})
+      : saved = x;
+  const bool initialized =
+      const bool.fromEnvironment("foo", defaultValue: barFromEnv);
+  final E value;
+  final bool saved;
+  final bool saved2;
+}
+
+class Subclass<T extends A> extends Class<T> {
+  const Subclass(dynamic t) : super(t);
+}
+
+const ConstClassWithF constClassWithF2 = const ConstClassWithF(procedure);
+const Symbol symbolWithInvalidName = const Symbol("42");
+const Symbol symbolWithUnevaluatedParameter =
+    const Symbol(String.fromEnvironment("foo"));
+const bool? barFromEnvOrNull0 = const bool.fromEnvironment("bar") ? true : null;
+const bool? unevaluatedBoolOrNull =
+    bool.fromEnvironment("bar") ? unevaluatedBool : null;
+const bool? y = true;
+const bool andOnNull = barFromEnvOrNull && true;
+const bool andOnNull2 = true && barFromEnvOrNull;
+const bool barFromEnv = const bool.fromEnvironment("bar");
+const bool barFromEnvOrNull =
+    const bool.fromEnvironment("bar", defaultValue: barFromEnvOrNull0!);
+const bool conditionalOnNull = barFromEnvOrNull ? true : false;
+const bool hasBarEnv = const bool.hasEnvironment("bar");
+const bool isItInt = maybeInt is int ? true : false;
+const bool isItInt2 = maybeInt2 is int ? true : false;
+const bool isItInt3 = maybeInt3 is int ? true : false;
+const bool isList = listOfInt is List;
+const bool isListOfInt = listOfInt is List<int>;
+const bool isListOfListOfInt = listOfListOfInt is List<List<int>>;
+const bool isListOfNull = listOfNull is List<Null>;
+const bool isMapOfInt = mapOfInt is Map<int, int>;
+const bool isMapOfMapOfInt1 = mapOfMapOfInt1 is Map<Map<int, int>, int>;
+const bool isMapOfMapOfInt2 = mapOfMapOfInt2 is Map<int, Map<int, int>>;
+const bool isSetOfInt = setOfInt is Set<int>;
+const bool isSetOfSetOfInt = setOfSetOfInt is Set<Set<int>>;
+const bool notBarFromEnvOrNull = !barFromEnvOrNull;
+const bool notUnevaluatedBool = !unevaluatedBool;
+const bool nullAwareOnNull = barFromEnvOrNull ?? true;
+const bool orOnNull = barFromEnvOrNull || true;
+const bool orOnNull2 = barFromEnvOrNull || false;
+const bool orOnNull3 = true || barFromEnvOrNull;
+const bool orOnNull4 = false || barFromEnvOrNull;
+const bool unevaluatedBool = bool.fromEnvironment("foo");
+const bool unevaluatedBoolNotNull = unevaluatedBoolOrNull!;
+const bool z = !(y!);
+const c0 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(C());
+const c1 = bool.fromEnvironment("x") ? null : const Class<A>.method(A());
+const c2 = bool.fromEnvironment("x") ? null : const Subclass<B>(C());
+const c3 = bool.fromEnvironment("x") ? null : const Class<A>(A());
+const c4 = bool.fromEnvironment("x") ? null : const Class<B>.redirect(B());
+const c5 = bool.fromEnvironment("x") ? null : const Subclass<A>(A());
+const c6 = bool.fromEnvironment("x") ? null : const Subclass<B>(B());
+const dynamic listOfInt = [42];
+const dynamic listOfListOfInt = [
+  [42]
+];
+const dynamic listOfNull = [null];
+const dynamic mapOfInt = {42: 42};
+const dynamic mapOfMapOfInt1 = {
+  {42: 42}: 42
+};
+const dynamic mapOfMapOfInt2 = {
+  42: {42: 42}
+};
+const dynamic setOfInt = {42};
+const dynamic setOfSetOfInt = {
+  {42}
+};
+const f = F;
+const fromDeferredLib = lib.x;
+const maybeInt = bool.fromEnvironment("foo") ? 42 : true;
+const maybeInt2 = z ? 42 : true;
+const maybeInt3 = z ? 42 : null;
+const x = const Foo<int>(42);
+int procedure(int i, {int named}) => i;
+main() {}
+typedef F = int Function(int, {int named});
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart
new file mode 100644
index 0000000..f8da5a4
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'various_2_lib.dart' as lib;
+
+typedef F1<T> = T Function(T);
+typedef F2 = T Function<T>(T);
+
+const objectTypeLiteral = Object;
+const int Function(int) partialInstantiation = lib.id1;
+const instance = const lib.Class<int>(0);
+const instance2 = const lib.Class<dynamic>([42]);
+
+const functionTypeLiteral = F1;
+const genericFunctionTypeLiteral = F2;
+const listLiteral = <int>[0];
+const listLiteral2 = <dynamic>[
+  <int>[42]
+];
+const setLiteral = <int>{0};
+const setLiteral2 = <dynamic>{
+  <int>[42]
+};
+const mapLiteral = <int, String>{0: 'foo'};
+const mapLiteral2 = <dynamic, dynamic>{
+  <int>[42]: 'foo',
+  null: <int>[42]
+};
+const listConcatenation = <int>[...listLiteral];
+const setConcatenation = <int>{...setLiteral};
+const mapConcatenation = <int, String>{...mapLiteral};
+
+const objectTypeLiteralIdentical =
+    identical(objectTypeLiteral, lib.objectTypeLiteral);
+const partialInstantiationIdentical =
+    identical(partialInstantiation, lib.partialInstantiation);
+const instanceIdentical = identical(instance, lib.instance);
+const instance2Identical = identical(instance2, lib.instance2);
+const functionTypeLiteralIdentical =
+    identical(functionTypeLiteral, lib.functionTypeLiteral);
+const genericFunctionTypeLiteralIdentical =
+    identical(genericFunctionTypeLiteral, lib.genericFunctionTypeLiteral);
+const listLiteralIdentical = identical(listLiteral, lib.listLiteral);
+const listLiteral2Identical = identical(listLiteral2, lib.listLiteral2);
+const setLiteralIdentical = identical(setLiteral, lib.setLiteral);
+const setLiteral2Identical = identical(setLiteral2, lib.setLiteral2);
+const mapLiteralIdentical = identical(mapLiteral, lib.mapLiteral);
+const mapLiteral2Identical = identical(mapLiteral2, lib.mapLiteral2);
+const listConcatenationIdentical =
+    identical(listConcatenation, lib.listConcatenation);
+const setConcatenationIdentical =
+    identical(setConcatenation, lib.setConcatenation);
+const mapConcatenationIdentical =
+    identical(mapConcatenation, lib.mapConcatenation);
+
+main() {
+  test(objectTypeLiteral, lib.objectTypeLiteral);
+  test(partialInstantiation, lib.partialInstantiation);
+  test(instance, lib.instance);
+  test(functionTypeLiteral, lib.functionTypeLiteral);
+  test(genericFunctionTypeLiteral, lib.genericFunctionTypeLiteral);
+  test(listLiteral, lib.listLiteral);
+  test(setLiteral, lib.setLiteral);
+  test(mapLiteral, lib.mapLiteral);
+  test(listConcatenation, lib.listConcatenation);
+  test(setConcatenation, lib.setConcatenation);
+  test(mapConcatenation, lib.mapConcatenation);
+
+  test(true, objectTypeLiteralIdentical);
+  test(true, partialInstantiationIdentical);
+  test(true, instanceIdentical);
+  test(true, functionTypeLiteralIdentical);
+  test(true, genericFunctionTypeLiteralIdentical);
+  test(true, listLiteralIdentical);
+  test(true, setLiteralIdentical);
+  test(true, mapLiteralIdentical);
+  test(true, listConcatenationIdentical);
+  test(true, setConcatenationIdentical);
+  test(true, mapConcatenationIdentical);
+}
+
+test(expected, actual) {
+  print('test($expected, $actual)');
+  if (!identical(expected, actual)) {
+    throw 'Expected $expected, actual $actual';
+  }
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect
new file mode 100644
index 0000000..4b3859b
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.outline.expect
@@ -0,0 +1,133 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "various_2_lib.dart" as var;
+
+import "org-dartlang-testcase:///various_2_lib.dart" as lib;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+static const field core::Type objectTypeLiteral = core::Object;
+static const field (core::int) → core::int partialInstantiation = var::id1<core::int>;
+static const field var::Class<core::int> instance = const var::Class::•<core::int>(0);
+static const field var::Class<dynamic> instance2 = const var::Class::•<dynamic>(const <core::int>[42]);
+static const field core::Type functionTypeLiteral = (dynamic) → dynamic;
+static const field core::Type genericFunctionTypeLiteral = <T extends core::Object? = dynamic>(T%) → T%;
+static const field core::List<core::int> listLiteral = const <core::int>[0];
+static const field core::List<dynamic> listLiteral2 = const <dynamic>[const <core::int>[42]];
+static const field core::Set<core::int> setLiteral = const <core::int>{0};
+static const field core::Set<dynamic> setLiteral2 = const <dynamic>{const <core::int>[42]};
+static const field core::Map<core::int, core::String> mapLiteral = const <core::int, core::String>{0: "foo"};
+static const field core::Map<dynamic, dynamic> mapLiteral2 = const <dynamic, dynamic>{const <core::int>[42]: "foo", null: const <core::int>[42]};
+static const field core::List<core::int> listConcatenation = self::listLiteral;
+static const field core::Set<core::int> setConcatenation = self::setLiteral;
+static const field core::Map<core::int, core::String> mapConcatenation = self::mapLiteral;
+static const field core::bool objectTypeLiteralIdentical = core::identical(self::objectTypeLiteral, var::objectTypeLiteral);
+static const field core::bool partialInstantiationIdentical = core::identical(self::partialInstantiation, var::partialInstantiation);
+static const field core::bool instanceIdentical = core::identical(self::instance, var::instance);
+static const field core::bool instance2Identical = core::identical(self::instance2, var::instance2);
+static const field core::bool functionTypeLiteralIdentical = core::identical(self::functionTypeLiteral, var::functionTypeLiteral);
+static const field core::bool genericFunctionTypeLiteralIdentical = core::identical(self::genericFunctionTypeLiteral, var::genericFunctionTypeLiteral);
+static const field core::bool listLiteralIdentical = core::identical(self::listLiteral, var::listLiteral);
+static const field core::bool listLiteral2Identical = core::identical(self::listLiteral2, var::listLiteral2);
+static const field core::bool setLiteralIdentical = core::identical(self::setLiteral, var::setLiteral);
+static const field core::bool setLiteral2Identical = core::identical(self::setLiteral2, var::setLiteral2);
+static const field core::bool mapLiteralIdentical = core::identical(self::mapLiteral, var::mapLiteral);
+static const field core::bool mapLiteral2Identical = core::identical(self::mapLiteral2, var::mapLiteral2);
+static const field core::bool listConcatenationIdentical = core::identical(self::listConcatenation, var::listConcatenation);
+static const field core::bool setConcatenationIdentical = core::identical(self::setConcatenation, var::setConcatenation);
+static const field core::bool mapConcatenationIdentical = core::identical(self::mapConcatenation, var::mapConcatenation);
+static method main() → dynamic
+  ;
+static method test(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as var;
+import "dart:core" as core;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field var::Class::T% field;
+  const constructor •(var::Class::T% field) → var::Class<var::Class::T%>
+    : var::Class::field = field, super core::Object::•()
+    ;
+}
+static const field core::Type objectTypeLiteral = core::Object;
+static const field (core::Object?, core::Object?) → core::bool c2 = core::identical;
+static const field (core::int) → core::int partialInstantiation = const core::bool::fromEnvironment("foo") ?{(core::int) → core::int} var::id1<core::int> : var::id2<core::int>;
+static const field var::Class<core::int> instance = const var::Class::•<core::int>(0);
+static const field var::Class<dynamic> instance2 = const var::Class::•<dynamic>(const <core::int>[42]);
+static const field core::Type functionTypeLiteral = (dynamic) → dynamic;
+static const field core::Type genericFunctionTypeLiteral = <T extends core::Object? = dynamic>(T%) → T%;
+static const field core::List<core::int> listLiteral = const <core::int>[0];
+static const field core::List<dynamic> listLiteral2 = const <dynamic>[const <core::int>[42]];
+static const field core::Set<core::int> setLiteral = const <core::int>{0};
+static const field core::Set<dynamic> setLiteral2 = const <dynamic>{const <core::int>[42]};
+static const field core::Map<core::int, core::String> mapLiteral = const <core::int, core::String>{0: "foo"};
+static const field core::Map<dynamic, dynamic> mapLiteral2 = const <dynamic, dynamic>{const <core::int>[42]: "foo", null: const <core::int>[42]};
+static const field core::List<core::int> listConcatenation = var::listLiteral;
+static const field core::Set<core::int> setConcatenation = var::setLiteral;
+static const field core::Map<core::int, core::String> mapConcatenation = var::mapLiteral;
+static method id1<T extends core::Object? = dynamic>(var::id1::T% t) → var::id1::T%
+  ;
+static method id2<T extends core::Object? = dynamic>(var::id2::T% t) → var::id2::T%
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2.dart:10:27 -> TypeLiteralConstant(Object)
+Evaluated: Instantiation @ org-dartlang-testcase:///various_2.dart:11:52 -> PartialInstantiationConstant(id1<int>)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2.dart:12:24 -> InstanceConstant(const Class<int>{Class.field: 0})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2.dart:13:25 -> InstanceConstant(const Class<dynamic>{Class.field: const <int>[42]})
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2.dart:15:29 -> TypeLiteralConstant(dynamic Function(dynamic))
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2.dart:16:36 -> TypeLiteralConstant(T% Function<T>(T%))
+Evaluated: ListLiteral @ org-dartlang-testcase:///various_2.dart:17:26 -> ListConstant(const <int>[0])
+Evaluated: ListLiteral @ org-dartlang-testcase:///various_2.dart:18:31 -> ListConstant(const <dynamic>[const <int>[42]])
+Evaluated: SetLiteral @ org-dartlang-testcase:///various_2.dart:21:25 -> SetConstant(const <int>{0})
+Evaluated: SetLiteral @ org-dartlang-testcase:///various_2.dart:22:30 -> SetConstant(const <dynamic>{const <int>[42]})
+Evaluated: MapLiteral @ org-dartlang-testcase:///various_2.dart:25:33 -> MapConstant(const <int, String>{0: "foo"})
+Evaluated: MapLiteral @ org-dartlang-testcase:///various_2.dart:26:39 -> MapConstant(const <dynamic, dynamic>{const <int>[42]: "foo", null: const <int>[42]})
+Evaluated: ListConcatenation @ org-dartlang-testcase:///various_2.dart:30:32 -> ListConstant(const <int>[0])
+Evaluated: SetConcatenation @ org-dartlang-testcase:///various_2.dart:31:31 -> SetConstant(const <int>{0})
+Evaluated: MapConcatenation @ org-dartlang-testcase:///various_2.dart:32:7 -> MapConstant(const <int, String>{0: "foo"})
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:35:5 -> BoolConstant(true)
+Evaluated with empty environment: StaticInvocation @ org-dartlang-testcase:///various_2.dart:37:5 -> BoolConstant(false)
+Evaluated: StaticGet @ org-dartlang-testcase:///various_2.dart:37:15 -> PartialInstantiationConstant(id1<int>)
+Evaluated with empty environment: StaticGet @ org-dartlang-testcase:///various_2.dart:37:41 -> PartialInstantiationConstant(id2<int>)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:38:27 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:39:28 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:41:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:43:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:44:30 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:45:31 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:46:29 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:47:30 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:48:29 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:49:30 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:51:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:53:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///various_2.dart:55:5 -> BoolConstant(true)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2_lib.dart:17:27 -> TypeLiteralConstant(Object)
+Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:18:12 -> TearOffConstant(identical)
+Evaluated with empty environment: ConditionalExpression @ org-dartlang-testcase:///various_2_lib.dart:20:39 -> PartialInstantiationConstant(id2<int>)
+Evaluated with empty environment: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///various_2_lib.dart:20:11 -> BoolConstant(false)
+Evaluated with empty environment: Instantiation @ org-dartlang-testcase:///various_2_lib.dart:20:41 -> PartialInstantiationConstant(id1<int>)
+Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:20:41 -> TearOffConstant(id1)
+Evaluated with empty environment: Instantiation @ org-dartlang-testcase:///various_2_lib.dart:20:47 -> PartialInstantiationConstant(id2<int>)
+Evaluated: StaticGet @ org-dartlang-testcase:///various_2_lib.dart:20:47 -> TearOffConstant(id2)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2_lib.dart:21:24 -> InstanceConstant(const Class<int>{Class.field: 0})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///various_2_lib.dart:22:25 -> InstanceConstant(const Class<dynamic>{Class.field: const <int>[42]})
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2_lib.dart:23:29 -> TypeLiteralConstant(dynamic Function(dynamic))
+Evaluated: TypeLiteral @ org-dartlang-testcase:///various_2_lib.dart:24:36 -> TypeLiteralConstant(T% Function<T>(T%))
+Evaluated: ListLiteral @ org-dartlang-testcase:///various_2_lib.dart:25:26 -> ListConstant(const <int>[0])
+Evaluated: ListLiteral @ org-dartlang-testcase:///various_2_lib.dart:26:31 -> ListConstant(const <dynamic>[const <int>[42]])
+Evaluated: SetLiteral @ org-dartlang-testcase:///various_2_lib.dart:29:25 -> SetConstant(const <int>{0})
+Evaluated: SetLiteral @ org-dartlang-testcase:///various_2_lib.dart:30:30 -> SetConstant(const <dynamic>{const <int>[42]})
+Evaluated: MapLiteral @ org-dartlang-testcase:///various_2_lib.dart:33:33 -> MapConstant(const <int, String>{0: "foo"})
+Evaluated: MapLiteral @ org-dartlang-testcase:///various_2_lib.dart:34:39 -> MapConstant(const <dynamic, dynamic>{const <int>[42]: "foo", null: const <int>[42]})
+Evaluated: ListConcatenation @ org-dartlang-testcase:///various_2_lib.dart:38:32 -> ListConstant(const <int>[0])
+Evaluated: SetConcatenation @ org-dartlang-testcase:///various_2_lib.dart:39:31 -> SetConstant(const <int>{0})
+Evaluated: MapConcatenation @ org-dartlang-testcase:///various_2_lib.dart:40:7 -> MapConstant(const <int, String>{0: "foo"})
+Extra constant evaluation: evaluated: 54, effectively constant: 53
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
new file mode 100644
index 0000000..95db2f1
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.expect
@@ -0,0 +1,130 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "various_2_lib.dart" as var;
+
+import "org-dartlang-testcase:///various_2_lib.dart" as lib;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+static const field core::Type objectTypeLiteral = #C1;
+static const field (core::int) → core::int partialInstantiation = #C3;
+static const field var::Class<core::int> instance = #C5;
+static const field var::Class<dynamic> instance2 = #C8;
+static const field core::Type functionTypeLiteral = #C9;
+static const field core::Type genericFunctionTypeLiteral = #C10;
+static const field core::List<core::int> listLiteral = #C11;
+static const field core::List<dynamic> listLiteral2 = #C12;
+static const field core::Set<core::int> setLiteral = #C13;
+static const field core::Set<dynamic> setLiteral2 = #C14;
+static const field core::Map<core::int, core::String> mapLiteral = #C16;
+static const field core::Map<dynamic, dynamic> mapLiteral2 = #C18;
+static const field core::List<core::int> listConcatenation = #C11;
+static const field core::Set<core::int> setConcatenation = #C13;
+static const field core::Map<core::int, core::String> mapConcatenation = #C16;
+static const field core::bool objectTypeLiteralIdentical = #C19;
+static const field core::bool partialInstantiationIdentical = #C21;
+static const field core::bool instanceIdentical = #C19;
+static const field core::bool instance2Identical = #C19;
+static const field core::bool functionTypeLiteralIdentical = #C19;
+static const field core::bool genericFunctionTypeLiteralIdentical = #C19;
+static const field core::bool listLiteralIdentical = #C19;
+static const field core::bool listLiteral2Identical = #C19;
+static const field core::bool setLiteralIdentical = #C19;
+static const field core::bool setLiteral2Identical = #C19;
+static const field core::bool mapLiteralIdentical = #C19;
+static const field core::bool mapLiteral2Identical = #C19;
+static const field core::bool listConcatenationIdentical = #C19;
+static const field core::bool setConcatenationIdentical = #C19;
+static const field core::bool mapConcatenationIdentical = #C19;
+static method main() → dynamic {
+  self::test(#C1, #C1);
+  self::test(#C3, #C22);
+  self::test(#C5, #C5);
+  self::test(#C9, #C9);
+  self::test(#C10, #C10);
+  self::test(#C11, #C11);
+  self::test(#C13, #C13);
+  self::test(#C16, #C16);
+  self::test(#C11, #C11);
+  self::test(#C13, #C13);
+  self::test(#C16, #C16);
+  self::test(true, #C19);
+  self::test(true, #C23);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+}
+static method test(dynamic expected, dynamic actual) → dynamic {
+  core::print("test(${expected}, ${actual})");
+  if(!core::identical(expected, actual)) {
+    throw "Expected ${expected}, actual ${actual}";
+  }
+}
+
+library /*isNonNullableByDefault*/;
+import self as var;
+import "dart:core" as core;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field var::Class::T% field;
+  const constructor •(var::Class::T% field) → var::Class<var::Class::T%>
+    : var::Class::field = field, super core::Object::•()
+    ;
+}
+static const field core::Type objectTypeLiteral = #C1;
+static const field (core::Object?, core::Object?) → core::bool c2 = #C24;
+static const field (core::int) → core::int partialInstantiation = #C25;
+static const field var::Class<core::int> instance = #C5;
+static const field var::Class<dynamic> instance2 = #C8;
+static const field core::Type functionTypeLiteral = #C9;
+static const field core::Type genericFunctionTypeLiteral = #C10;
+static const field core::List<core::int> listLiteral = #C11;
+static const field core::List<dynamic> listLiteral2 = #C12;
+static const field core::Set<core::int> setLiteral = #C13;
+static const field core::Set<dynamic> setLiteral2 = #C14;
+static const field core::Map<core::int, core::String> mapLiteral = #C16;
+static const field core::Map<dynamic, dynamic> mapLiteral2 = #C18;
+static const field core::List<core::int> listConcatenation = #C11;
+static const field core::Set<core::int> setConcatenation = #C13;
+static const field core::Map<core::int, core::String> mapConcatenation = #C16;
+static method id1<T extends core::Object? = dynamic>(var::id1::T% t) → var::id1::T%
+  return t;
+static method id2<T extends core::Object? = dynamic>(var::id2::T% t) → var::id2::T%
+  return t;
+
+constants  {
+  #C1 = TypeLiteralConstant(core::Object)
+  #C2 = tearoff var::id1
+  #C3 = partial-instantiation var::id1 <core::int>
+  #C4 = 0
+  #C5 = var::Class<core::int> {field:#C4}
+  #C6 = 42
+  #C7 = <core::int>[#C6]
+  #C8 = var::Class<dynamic> {field:#C7}
+  #C9 = TypeLiteralConstant((dynamic) → dynamic)
+  #C10 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T%) → T%)
+  #C11 = <core::int>[#C4]
+  #C12 = <dynamic>[#C7]
+  #C13 = <core::int>{#C4}
+  #C14 = <dynamic>{#C7}
+  #C15 = "foo"
+  #C16 = <core::int, core::String>{#C4:#C15)
+  #C17 = null
+  #C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
+  #C19 = true
+  #C20 = tearoff var::id2
+  #C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
+  #C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
+  #C23 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
+  #C24 = tearoff core::identical
+  #C25 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
+}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..6932698
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.strong.transformed.expect
@@ -0,0 +1,137 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "various_2_lib.dart" as var;
+
+import "org-dartlang-testcase:///various_2_lib.dart" as lib;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+static const field core::Type objectTypeLiteral = #C1;
+static const field (core::int) → core::int partialInstantiation = #C3;
+static const field var::Class<core::int> instance = #C5;
+static const field var::Class<dynamic> instance2 = #C8;
+static const field core::Type functionTypeLiteral = #C9;
+static const field core::Type genericFunctionTypeLiteral = #C10;
+static const field core::List<core::int> listLiteral = #C11;
+static const field core::List<dynamic> listLiteral2 = #C12;
+static const field core::Set<core::int> setLiteral = #C13;
+static const field core::Set<dynamic> setLiteral2 = #C14;
+static const field core::Map<core::int, core::String> mapLiteral = #C16;
+static const field core::Map<dynamic, dynamic> mapLiteral2 = #C18;
+static const field core::List<core::int> listConcatenation = #C11;
+static const field core::Set<core::int> setConcatenation = #C13;
+static const field core::Map<core::int, core::String> mapConcatenation = #C16;
+static const field core::bool objectTypeLiteralIdentical = #C19;
+static const field core::bool partialInstantiationIdentical = #C21;
+static const field core::bool instanceIdentical = #C19;
+static const field core::bool instance2Identical = #C19;
+static const field core::bool functionTypeLiteralIdentical = #C19;
+static const field core::bool genericFunctionTypeLiteralIdentical = #C19;
+static const field core::bool listLiteralIdentical = #C19;
+static const field core::bool listLiteral2Identical = #C19;
+static const field core::bool setLiteralIdentical = #C19;
+static const field core::bool setLiteral2Identical = #C19;
+static const field core::bool mapLiteralIdentical = #C19;
+static const field core::bool mapLiteral2Identical = #C19;
+static const field core::bool listConcatenationIdentical = #C19;
+static const field core::bool setConcatenationIdentical = #C19;
+static const field core::bool mapConcatenationIdentical = #C19;
+static method main() → dynamic {
+  self::test(#C1, #C1);
+  self::test(#C3, #C22);
+  self::test(#C5, #C5);
+  self::test(#C9, #C9);
+  self::test(#C10, #C10);
+  self::test(#C11, #C11);
+  self::test(#C13, #C13);
+  self::test(#C16, #C16);
+  self::test(#C11, #C11);
+  self::test(#C13, #C13);
+  self::test(#C16, #C16);
+  self::test(true, #C19);
+  self::test(true, #C23);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+  self::test(true, #C19);
+}
+static method test(dynamic expected, dynamic actual) → dynamic {
+  core::print("test(${expected}, ${actual})");
+  if(!core::identical(expected, actual)) {
+    throw "Expected ${expected}, actual ${actual}";
+  }
+}
+
+library /*isNonNullableByDefault*/;
+import self as var;
+import "dart:core" as core;
+
+typedef F1<invariant T extends core::Object? = dynamic> = (T%) → T%;
+typedef F2 = <T extends core::Object? = dynamic>(T%) → T%;
+class Class<T extends core::Object? = dynamic> extends core::Object /*hasConstConstructor*/  {
+  final field var::Class::T% field;
+  const constructor •(var::Class::T% field) → var::Class<var::Class::T%>
+    : var::Class::field = field, super core::Object::•()
+    ;
+}
+static const field core::Type objectTypeLiteral = #C1;
+static const field (core::Object?, core::Object?) → core::bool c2 = #C24;
+static const field (core::int) → core::int partialInstantiation = #C25;
+static const field var::Class<core::int> instance = #C5;
+static const field var::Class<dynamic> instance2 = #C8;
+static const field core::Type functionTypeLiteral = #C9;
+static const field core::Type genericFunctionTypeLiteral = #C10;
+static const field core::List<core::int> listLiteral = #C11;
+static const field core::List<dynamic> listLiteral2 = #C12;
+static const field core::Set<core::int> setLiteral = #C13;
+static const field core::Set<dynamic> setLiteral2 = #C14;
+static const field core::Map<core::int, core::String> mapLiteral = #C16;
+static const field core::Map<dynamic, dynamic> mapLiteral2 = #C18;
+static const field core::List<core::int> listConcatenation = #C11;
+static const field core::Set<core::int> setConcatenation = #C13;
+static const field core::Map<core::int, core::String> mapConcatenation = #C16;
+static method id1<T extends core::Object? = dynamic>(var::id1::T% t) → var::id1::T%
+  return t;
+static method id2<T extends core::Object? = dynamic>(var::id2::T% t) → var::id2::T%
+  return t;
+
+constants  {
+  #C1 = TypeLiteralConstant(core::Object)
+  #C2 = tearoff var::id1
+  #C3 = partial-instantiation var::id1 <core::int>
+  #C4 = 0
+  #C5 = var::Class<core::int> {field:#C4}
+  #C6 = 42
+  #C7 = <core::int>[#C6]
+  #C8 = var::Class<dynamic> {field:#C7}
+  #C9 = TypeLiteralConstant((dynamic) → dynamic)
+  #C10 = TypeLiteralConstant(<T extends core::Object? = dynamic>(T%) → T%)
+  #C11 = <core::int>[#C4]
+  #C12 = <dynamic>[#C7]
+  #C13 = <core::int>{#C4}
+  #C14 = <dynamic>{#C7}
+  #C15 = "foo"
+  #C16 = <core::int, core::String>{#C4:#C15)
+  #C17 = null
+  #C18 = <dynamic, dynamic>{#C7:#C15, #C17:#C7)
+  #C19 = true
+  #C20 = tearoff var::id2
+  #C21 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
+  #C22 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
+  #C23 = eval const core::identical(#C3, const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>)
+  #C24 = tearoff core::identical
+  #C25 = eval const core::bool::fromEnvironment(#C15) ?{(core::int) → core::int} #C2<core::int> : #C20<core::int>
+}
+
+Extra constant evaluation status:
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2.dart:15:28 -> PartialInstantiationConstant(id2<int>)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2.dart:37:5 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2.dart:37:5 -> BoolConstant(false)
+Evaluated with empty environment: ConstantExpression @ org-dartlang-testcase:///various_2_lib.dart:20:39 -> PartialInstantiationConstant(id2<int>)
+Extra constant evaluation: evaluated: 41, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline.expect
new file mode 100644
index 0000000..ba7ed46
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline.expect
@@ -0,0 +1,50 @@
+import 'various_2_lib.dart' as lib;
+
+typedef F1<T> = T Function(T);
+typedef F2 = T Function<T>(T);
+const objectTypeLiteral = Object;
+const int Function(int) partialInstantiation = lib.id1;
+const instance = const lib.Class<int>(0);
+const instance2 = const lib.Class<dynamic>([42]);
+const functionTypeLiteral = F1;
+const genericFunctionTypeLiteral = F2;
+const listLiteral = <int>[0];
+const listLiteral2 = <dynamic>[
+  <int>[42]
+];
+const setLiteral = <int>{0};
+const setLiteral2 = <dynamic>{
+  <int>[42]
+};
+const mapLiteral = <int, String>{0: 'foo'};
+const mapLiteral2 = <dynamic, dynamic>{
+  <int>[42]: 'foo',
+  null: <int>[42]
+};
+const listConcatenation = <int>[...listLiteral];
+const setConcatenation = <int>{...setLiteral};
+const mapConcatenation = <int, String>{...mapLiteral};
+const objectTypeLiteralIdentical =
+    identical(objectTypeLiteral, lib.objectTypeLiteral);
+const partialInstantiationIdentical =
+    identical(partialInstantiation, lib.partialInstantiation);
+const instanceIdentical = identical(instance, lib.instance);
+const instance2Identical = identical(instance2, lib.instance2);
+const functionTypeLiteralIdentical =
+    identical(functionTypeLiteral, lib.functionTypeLiteral);
+const genericFunctionTypeLiteralIdentical =
+    identical(genericFunctionTypeLiteral, lib.genericFunctionTypeLiteral);
+const listLiteralIdentical = identical(listLiteral, lib.listLiteral);
+const listLiteral2Identical = identical(listLiteral2, lib.listLiteral2);
+const setLiteralIdentical = identical(setLiteral, lib.setLiteral);
+const setLiteral2Identical = identical(setLiteral2, lib.setLiteral2);
+const mapLiteralIdentical = identical(mapLiteral, lib.mapLiteral);
+const mapLiteral2Identical = identical(mapLiteral2, lib.mapLiteral2);
+const listConcatenationIdentical =
+    identical(listConcatenation, lib.listConcatenation);
+const setConcatenationIdentical =
+    identical(setConcatenation, lib.setConcatenation);
+const mapConcatenationIdentical =
+    identical(mapConcatenation, lib.mapConcatenation);
+main() {}
+test(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a390688
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,50 @@
+import 'various_2_lib.dart' as lib;
+
+const functionTypeLiteral = F1;
+const functionTypeLiteralIdentical =
+    identical(functionTypeLiteral, lib.functionTypeLiteral);
+const genericFunctionTypeLiteral = F2;
+const genericFunctionTypeLiteralIdentical =
+    identical(genericFunctionTypeLiteral, lib.genericFunctionTypeLiteral);
+const instance = const lib.Class<int>(0);
+const instance2 = const lib.Class<dynamic>([42]);
+const instance2Identical = identical(instance2, lib.instance2);
+const instanceIdentical = identical(instance, lib.instance);
+const int Function(int) partialInstantiation = lib.id1;
+const listConcatenation = <int>[...listLiteral];
+const listConcatenationIdentical =
+    identical(listConcatenation, lib.listConcatenation);
+const listLiteral = <int>[0];
+const listLiteral2 = <dynamic>[
+  <int>[42]
+];
+const listLiteral2Identical = identical(listLiteral2, lib.listLiteral2);
+const listLiteralIdentical = identical(listLiteral, lib.listLiteral);
+const mapConcatenation = <int, String>{...mapLiteral};
+const mapConcatenationIdentical =
+    identical(mapConcatenation, lib.mapConcatenation);
+const mapLiteral = <int, String>{0: 'foo'};
+const mapLiteral2 = <dynamic, dynamic>{
+  <int>[42]: 'foo',
+  null: <int>[42]
+};
+const mapLiteral2Identical = identical(mapLiteral2, lib.mapLiteral2);
+const mapLiteralIdentical = identical(mapLiteral, lib.mapLiteral);
+const objectTypeLiteral = Object;
+const objectTypeLiteralIdentical =
+    identical(objectTypeLiteral, lib.objectTypeLiteral);
+const partialInstantiationIdentical =
+    identical(partialInstantiation, lib.partialInstantiation);
+const setConcatenation = <int>{...setLiteral};
+const setConcatenationIdentical =
+    identical(setConcatenation, lib.setConcatenation);
+const setLiteral = <int>{0};
+const setLiteral2 = <dynamic>{
+  <int>[42]
+};
+const setLiteral2Identical = identical(setLiteral2, lib.setLiteral2);
+const setLiteralIdentical = identical(setLiteral, lib.setLiteral);
+main() {}
+test(expected, actual) {}
+typedef F1<T> = T Function(T);
+typedef F2 = T Function<T>(T);
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2_lib.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2_lib.dart
new file mode 100644
index 0000000..7a06e11
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_2_lib.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class<T> {
+  final T field;
+
+  const Class(this.field);
+}
+
+T id1<T>(T t) => t;
+T id2<T>(T t) => t;
+
+typedef F1<T> = T Function(T);
+typedef F2 = T Function<T>(T);
+
+const objectTypeLiteral = Object;
+const c2 = identical;
+const int Function(int) partialInstantiation =
+    const bool.fromEnvironment("foo") ? id1 : id2;
+const instance = const Class<int>(0);
+const instance2 = const Class<dynamic>([42]);
+const functionTypeLiteral = F1;
+const genericFunctionTypeLiteral = F2;
+const listLiteral = <int>[0];
+const listLiteral2 = <dynamic>[
+  <int>[42]
+];
+const setLiteral = <int>{0};
+const setLiteral2 = <dynamic>{
+  <int>[42]
+};
+const mapLiteral = <int, String>{0: 'foo'};
+const mapLiteral2 = <dynamic, dynamic>{
+  <int>[42]: 'foo',
+  null: <int>[42]
+};
+const listConcatenation = <int>[...listLiteral];
+const setConcatenation = <int>{...setLiteral};
+const mapConcatenation = <int, String>{...mapLiteral};
diff --git a/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_lib.dart b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_lib.dart
new file mode 100644
index 0000000..06d2cb3
--- /dev/null
+++ b/pkg/front_end/testcases/general/constants/with_unevaluated_agnostic/various_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+const x = 42;
diff --git a/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect b/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
index a4cb425..6077536 100644
--- a/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/control_flow_collection.dart.strong.transformed.expect
@@ -100,3 +100,11 @@
 }
 static method oracle() → dynamic
   return true;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:9:26 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:18:26 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:27:29 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:27:33 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 160, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect b/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
index 7c34544..3d30d4a 100644
--- a/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/covariant_generic.dart.strong.transformed.expect
@@ -47,3 +47,9 @@
   let final self::Foo<core::num*>* #t3 = fooNum in let final core::double* #t4 = 2.5 in (#t3.{self::Foo::mutableCallbackField} as{TypeError,CovarianceCheck} (core::num*) →* void).call(#t4);
   fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null? {};
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///covariant_generic.dart:42:31 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///covariant_generic.dart:43:31 -> DoubleConstant(2.5)
+Extra constant evaluation: evaluated: 58, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
index 1e544ed..32a46a1 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.outline.expect
@@ -428,7 +428,7 @@
     : self::Enum#4::index = index, self::Enum#4::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#4::_name};
+    return this.{self::Enum#4::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -450,7 +450,7 @@
     : self::Enum#3::index = index, self::Enum#3::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#3::_name};
+    return this.{self::Enum#3::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -472,7 +472,7 @@
     : self::Enum#2::index = index, self::Enum#2::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#2::_name};
+    return this.{self::Enum#2::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -494,7 +494,7 @@
     : self::Enum#1::index = index, self::Enum#1::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#1::_name};
+    return this.{self::Enum#1::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -516,7 +516,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -538,7 +538,7 @@
     : self::AnotherEnum::index = index, self::AnotherEnum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::AnotherEnum::_name};
+    return this.{self::AnotherEnum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -559,3 +559,30 @@
 
 library;
 import self as self2;
+
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations_part.dart:86:6 -> ListConstant(const <Enum#4*>[const Enum#4{Enum#4.index: 0, Enum#4._name: "Enum.a"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:87:3 -> InstanceConstant(const Enum#4{Enum#4.index: 0, Enum#4._name: "Enum.a"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations_part.dart:80:6 -> ListConstant(const <Enum#3*>[const Enum#3{Enum#3.index: 0, Enum#3._name: "Enum.a"}, const Enum#3{Enum#3.index: 1, Enum#3._name: "Enum.b"}, const Enum#3{Enum#3.index: 2, Enum#3._name: "Enum.c"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:81:3 -> InstanceConstant(const Enum#3{Enum#3.index: 0, Enum#3._name: "Enum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:82:3 -> InstanceConstant(const Enum#3{Enum#3.index: 1, Enum#3._name: "Enum.b"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:83:3 -> InstanceConstant(const Enum#3{Enum#3.index: 2, Enum#3._name: "Enum.c"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations_part.dart:73:6 -> ListConstant(const <Enum#2*>[const Enum#2{Enum#2.index: 0, Enum#2._name: "Enum.Enum"}, const Enum#2{Enum#2.index: 1, Enum#2._name: "Enum.a"}, const Enum#2{Enum#2.index: 2, Enum#2._name: "Enum.b"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:74:3 -> InstanceConstant(const Enum#2{Enum#2.index: 0, Enum#2._name: "Enum.Enum"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:75:3 -> InstanceConstant(const Enum#2{Enum#2.index: 1, Enum#2._name: "Enum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations_part.dart:77:3 -> InstanceConstant(const Enum#2{Enum#2.index: 2, Enum#2._name: "Enum.b"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations.dart:81:6 -> ListConstant(const <Enum#1*>[const Enum#1{Enum#1.index: 0, Enum#1._name: "Enum.a"}, const Enum#1{Enum#1.index: 1, Enum#1._name: "Enum.b"}, const Enum#1{Enum#1.index: 2, Enum#1._name: "Enum.c"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:82:3 -> InstanceConstant(const Enum#1{Enum#1.index: 0, Enum#1._name: "Enum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:83:3 -> InstanceConstant(const Enum#1{Enum#1.index: 1, Enum#1._name: "Enum.b"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:84:3 -> InstanceConstant(const Enum#1{Enum#1.index: 2, Enum#1._name: "Enum.c"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations.dart:74:6 -> ListConstant(const <Enum*>[const Enum{Enum.index: 0, Enum._name: "Enum.Enum"}, const Enum{Enum.index: 1, Enum._name: "Enum.a"}, const Enum{Enum.index: 2, Enum._name: "Enum.b"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:75:3 -> InstanceConstant(const Enum{Enum.index: 0, Enum._name: "Enum.Enum"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:76:3 -> InstanceConstant(const Enum{Enum.index: 1, Enum._name: "Enum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:78:3 -> InstanceConstant(const Enum{Enum.index: 2, Enum._name: "Enum.b"})
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_declarations.dart:87:6 -> ListConstant(const <AnotherEnum*>[const AnotherEnum{AnotherEnum.index: 0, AnotherEnum._name: "AnotherEnum.a"}, const AnotherEnum{AnotherEnum.index: 1, AnotherEnum._name: "AnotherEnum.b"}, const AnotherEnum{AnotherEnum.index: 2, AnotherEnum._name: "AnotherEnum.c"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:88:3 -> InstanceConstant(const AnotherEnum{AnotherEnum.index: 0, AnotherEnum._name: "AnotherEnum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:89:3 -> InstanceConstant(const AnotherEnum{AnotherEnum.index: 1, AnotherEnum._name: "AnotherEnum.b"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///duplicated_declarations.dart:90:3 -> InstanceConstant(const AnotherEnum{AnotherEnum.index: 2, AnotherEnum._name: "AnotherEnum.c"})
+Extra constant evaluation: evaluated: 46, effectively constant: 22
diff --git a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
index 3ee4ed6..608fb62 100644
--- a/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
+++ b/pkg/front_end/testcases/general/duplicated_declarations.dart.strong.expect
@@ -490,7 +490,7 @@
     : self::Enum#4::index = index, self::Enum#4::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#4::_name};
+    return this.{self::Enum#4::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -512,7 +512,7 @@
     : self::Enum#3::index = index, self::Enum#3::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#3::_name};
+    return this.{self::Enum#3::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -534,7 +534,7 @@
     : self::Enum#2::index = index, self::Enum#2::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#2::_name};
+    return this.{self::Enum#2::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -556,7 +556,7 @@
     : self::Enum#1::index = index, self::Enum#1::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#1::_name};
+    return this.{self::Enum#1::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -578,7 +578,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -600,7 +600,7 @@
     : self::AnotherEnum::index = index, self::AnotherEnum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::AnotherEnum::_name};
+    return this.{self::AnotherEnum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
index 8159055..7b42d92 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_01_lib2.dart:8:9: Error: Constant evaluation error:
-//   const Foo(0);
-//         ^
-// pkg/front_end/testcases/general/error_locations/error_location_01_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_01_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_01_lib2.dart:8:9: Error: Constant evaluation error:
+//   const Foo(0);
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_01_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 
 import "org-dartlang-testcase:///error_location_01_lib1.dart";
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
index 8159055..7b42d92 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_01.dart.strong.transformed.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_01_lib2.dart:8:9: Error: Constant evaluation error:
-//   const Foo(0);
-//         ^
-// pkg/front_end/testcases/general/error_locations/error_location_01_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_01_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_01_lib2.dart:8:9: Error: Constant evaluation error:
+//   const Foo(0);
+//         ^
+// pkg/front_end/testcases/general/error_locations/error_location_01_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 
 import "org-dartlang-testcase:///error_location_01_lib1.dart";
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
index e1d2f71..1aae9ef 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:19: Error: Constant evaluation error:
-// const fooField2 = fooField;
-//                   ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:7: Context: While analyzing:
-// const fooField2 = fooField;
-//       ^
-//
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_02_lib1.dart" as err;
@@ -59,6 +36,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_02_lib1.dart" as err;
 
@@ -67,6 +57,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:19: Error: Constant evaluation error:
+// const fooField2 = fooField;
+//                   ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:7: Context: While analyzing:
+// const fooField2 = fooField;
+//       ^
+//
 import self as self3;
 import "error_location_02_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
index e1d2f71..1aae9ef 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_02.dart.strong.transformed.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:19: Error: Constant evaluation error:
-// const fooField2 = fooField;
-//                   ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:7: Context: While analyzing:
-// const fooField2 = fooField;
-//       ^
-//
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_02_lib1.dart" as err;
@@ -59,6 +36,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib2.dart:7:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_02_lib1.dart" as err;
 
@@ -67,6 +57,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:19: Error: Constant evaluation error:
+// const fooField2 = fooField;
+//                   ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_02_lib3.dart:7:7: Context: While analyzing:
+// const fooField2 = fooField;
+//       ^
+//
 import self as self3;
 import "error_location_02_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
index c8f681b..18b8f4f 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:25: Error: Constant evaluation error:
-// const fooField2 = const Foo(0);
-//                         ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:7: Context: While analyzing:
-// const fooField2 = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_03_lib1.dart" as err;
@@ -60,6 +37,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_03_lib1.dart" as err;
 
@@ -68,6 +58,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 import self as self3;
 import "error_location_03_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
index c8f681b..18b8f4f 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_03.dart.strong.transformed.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:25: Error: Constant evaluation error:
-// const fooField2 = const Foo(0);
-//                         ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:7: Context: While analyzing:
-// const fooField2 = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_03_lib1.dart" as err;
@@ -60,6 +37,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib2.dart:7:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_03_lib1.dart" as err;
 
@@ -68,6 +58,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general/error_locations/error_location_03_lib3.dart:7:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 import self as self3;
 import "error_location_03_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
index 1170883..972534b 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_04_lib2.dart:9:27: Error: Constant evaluation error:
-//   const Bar() : x = const Foo(0);
-//                           ^
-// pkg/front_end/testcases/general/error_locations/error_location_04_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_04_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_04_lib2.dart:9:27: Error: Constant evaluation error:
+//   const Bar() : x = const Foo(0);
+//                           ^
+// pkg/front_end/testcases/general/error_locations/error_location_04_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 import "dart:core" as core;
 import "error_location_04_lib1.dart" as err;
diff --git a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
index 1170883..972534b 100644
--- a/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_locations/error_location_04.dart.strong.transformed.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general/error_locations/error_location_04_lib2.dart:9:27: Error: Constant evaluation error:
-//   const Bar() : x = const Foo(0);
-//                           ^
-// pkg/front_end/testcases/general/error_locations/error_location_04_lib1.dart:6:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_04_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_locations/error_location_04_lib2.dart:9:27: Error: Constant evaluation error:
+//   const Bar() : x = const Foo(0);
+//                           ^
+// pkg/front_end/testcases/general/error_locations/error_location_04_lib1.dart:6:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 import "dart:core" as core;
 import "error_location_04_lib1.dart" as err;
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.expect
index e8becc5..77d5da5 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   await for () {}
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.transformed.expect
index c1b245b..b35db37 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_await_for.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/error_recovery/empty_await_for.dart:2:14: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   await for () {}
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.expect
index 3bb7f2e..fa8d15f 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   for () {}
 //        ^
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.transformed.expect
index c360df17..9344b10 100644
--- a/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/empty_for.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/error_recovery/empty_for.dart:2:8: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   for () {}
 //        ^
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart
new file mode 100644
index 0000000..ed07e7e
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class Key {
+  int get a => runtimeType.hashCode xor null.hashCode;
+  int get b => runtimeType.hashCode ^ null.hashCode;
+  int get c { return runtimeType.hashCode xor null.hashCode; }
+  int get d { return runtimeType.hashCode ^ null.hashCode; }
+
+  int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+  int get h { return 1 + runtimeType.hashCode ^ null.hashCode + 3; }
+
+  int i(int x, int y) => x xor y;
+  int j(int x, int y) => x ^ y;
+  int k(int x, int y) { return x xor y; }
+  int l(int x, int y) { return x ^ y; }
+  int m(int x, int y) { int z =  x xor y; return z; }
+  int n(int x, int y) { int z = x ^ y; return z; }
+
+  int o(int x, int y) => 1 + x xor y + 3;
+  int p(int x, int y) => 1 + x ^ y + 3;
+  int q(int x, int y) { return 1 + x xor y + 3; }
+  int r(int x, int y) { return 1 + x ^ y + 3; }
+
+  s(int x, int y) {
+    s(x xor y, x xor y);
+    s(x ^ y, x ^ y);
+  }
+
+  int foo;
+  int bar;
+
+  Key(int x, int y) : foo = x xor y, bar = x xor y {
+    print("hello ${x xor y}");
+  }
+
+  Key.NotDuplicate(int x, int y) : foo = x ^ y, bar = x ^ y {
+    print("hello ${x ^ y}");
+  }
+}
+
+main() {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.outline.expect
new file mode 100644
index 0000000..3e4746b
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.outline.expect
@@ -0,0 +1,95 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:6:37: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get a => runtimeType.hashCode xor null.hashCode;
+//                                     ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:11:41: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+//                                         ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:16:28: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int i(int x, int y) => x xor y;
+//                            ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:23:32: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int o(int x, int y) => 1 + x xor y + 3;
+//                                ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:31: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:46: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                                              ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Key extends core::Object {
+  field core::int* foo;
+  field core::int* bar;
+  constructor •(core::int* x, core::int* y) → self::Key*
+    ;
+  constructor NotDuplicate(core::int* x, core::int* y) → self::Key*
+    ;
+  get a() → core::int*
+    ;
+  get b() → core::int*
+    ;
+  get c() → core::int*
+    ;
+  get d() → core::int*
+    ;
+  get e() → core::int*
+    ;
+  get f() → core::int*
+    ;
+  get g() → core::int*
+    ;
+  get h() → core::int*
+    ;
+  method i(core::int* x, core::int* y) → core::int*
+    ;
+  method j(core::int* x, core::int* y) → core::int*
+    ;
+  method k(core::int* x, core::int* y) → core::int*
+    ;
+  method l(core::int* x, core::int* y) → core::int*
+    ;
+  method m(core::int* x, core::int* y) → core::int*
+    ;
+  method n(core::int* x, core::int* y) → core::int*
+    ;
+  method o(core::int* x, core::int* y) → core::int*
+    ;
+  method p(core::int* x, core::int* y) → core::int*
+    ;
+  method q(core::int* x, core::int* y) → core::int*
+    ;
+  method r(core::int* x, core::int* y) → core::int*
+    ;
+  method s(core::int* x, core::int* y) → dynamic
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.expect
new file mode 100644
index 0000000..13cf674
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.expect
@@ -0,0 +1,152 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:6:37: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get a => runtimeType.hashCode xor null.hashCode;
+//                                     ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:11:41: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+//                                         ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:16:28: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int i(int x, int y) => x xor y;
+//                            ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:23:32: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int o(int x, int y) => 1 + x xor y + 3;
+//                                ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:31: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:46: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                                              ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:8:43: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get c { return runtimeType.hashCode xor null.hashCode; }
+//                                           ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:13:47: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+//                                               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:18:34: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int k(int x, int y) { return x xor y; }
+//                                  ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:20:36: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int m(int x, int y) { int z =  x xor y; return z; }
+//                                    ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:25:38: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int q(int x, int y) { return 1 + x xor y + 3; }
+//                                      ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:29:9: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     s(x xor y, x xor y);
+//         ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:29:18: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     s(x xor y, x xor y);
+//                  ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:37:22: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     print("hello ${x xor y}");
+//                      ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Key extends core::Object {
+  field core::int* foo;
+  field core::int* bar;
+  constructor •(core::int* x, core::int* y) → self::Key*
+    : self::Key::foo = x.{core::int::^}(y), self::Key::bar = x.{core::int::^}(y), super core::Object::•() {
+    core::print("hello ${x.{core::int::^}(y)}");
+  }
+  constructor NotDuplicate(core::int* x, core::int* y) → self::Key*
+    : self::Key::foo = x.{core::int::^}(y), self::Key::bar = x.{core::int::^}(y), super core::Object::•() {
+    core::print("hello ${x.{core::int::^}(y)}");
+  }
+  get a() → core::int*
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  get b() → core::int*
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  get c() → core::int* {
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  }
+  get d() → core::int* {
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  }
+  get e() → core::int*
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  get f() → core::int*
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  get g() → core::int* {
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  }
+  get h() → core::int* {
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  }
+  method i(core::int* x, core::int* y) → core::int*
+    return x.{core::int::^}(y);
+  method j(core::int* x, core::int* y) → core::int*
+    return x.{core::int::^}(y);
+  method k(core::int* x, core::int* y) → core::int* {
+    return x.{core::int::^}(y);
+  }
+  method l(core::int* x, core::int* y) → core::int* {
+    return x.{core::int::^}(y);
+  }
+  method m(core::int* x, core::int* y) → core::int* {
+    core::int* z = x.{core::int::^}(y);
+    return z;
+  }
+  method n(core::int* x, core::int* y) → core::int* {
+    core::int* z = x.{core::int::^}(y);
+    return z;
+  }
+  method o(core::int* x, core::int* y) → core::int*
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  method p(core::int* x, core::int* y) → core::int*
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  method q(core::int* x, core::int* y) → core::int* {
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  }
+  method r(core::int* x, core::int* y) → core::int* {
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  }
+  method s(core::int* x, core::int* y) → dynamic {
+    this.{self::Key::s}(x.{core::int::^}(y), x.{core::int::^}(y));
+    this.{self::Key::s}(x.{core::int::^}(y), x.{core::int::^}(y));
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.transformed.expect
new file mode 100644
index 0000000..13cf674
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.strong.transformed.expect
@@ -0,0 +1,152 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:6:37: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get a => runtimeType.hashCode xor null.hashCode;
+//                                     ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:11:41: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get e => 1 + runtimeType.hashCode xor null.hashCode + 3;
+//                                         ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:16:28: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int i(int x, int y) => x xor y;
+//                            ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:23:32: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int o(int x, int y) => 1 + x xor y + 3;
+//                                ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:31: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:36:46: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   Key(int x, int y) : foo = x xor y, bar = x xor y {
+//                                              ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:8:43: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get c { return runtimeType.hashCode xor null.hashCode; }
+//                                           ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:13:47: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int get g { return 1 + runtimeType.hashCode xor null.hashCode + 3; }
+//                                               ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:18:34: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int k(int x, int y) { return x xor y; }
+//                                  ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:20:36: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int m(int x, int y) { int z =  x xor y; return z; }
+//                                    ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:25:38: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//   int q(int x, int y) { return 1 + x xor y + 3; }
+//                                      ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:29:9: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     s(x xor y, x xor y);
+//         ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:29:18: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     s(x xor y, x xor y);
+//                  ^^^
+//
+// pkg/front_end/testcases/general/error_recovery/issue_26810.dart:37:22: Error: Binary operator 'xor' is written as '^' instead of the written out word.
+// Try replacing 'xor' with '^'.
+//     print("hello ${x xor y}");
+//                      ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class Key extends core::Object {
+  field core::int* foo;
+  field core::int* bar;
+  constructor •(core::int* x, core::int* y) → self::Key*
+    : self::Key::foo = x.{core::int::^}(y), self::Key::bar = x.{core::int::^}(y), super core::Object::•() {
+    core::print("hello ${x.{core::int::^}(y)}");
+  }
+  constructor NotDuplicate(core::int* x, core::int* y) → self::Key*
+    : self::Key::foo = x.{core::int::^}(y), self::Key::bar = x.{core::int::^}(y), super core::Object::•() {
+    core::print("hello ${x.{core::int::^}(y)}");
+  }
+  get a() → core::int*
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  get b() → core::int*
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  get c() → core::int* {
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  }
+  get d() → core::int* {
+    return this.{self::Key::runtimeType}.{core::Object::hashCode}.{core::int::^}(null.{core::Null::hashCode});
+  }
+  get e() → core::int*
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  get f() → core::int*
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  get g() → core::int* {
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  }
+  get h() → core::int* {
+    return 1.{core::num::+}(this.{self::Key::runtimeType}.{core::Object::hashCode}).{core::int::^}(null.{core::Null::hashCode}.{core::num::+}(3));
+  }
+  method i(core::int* x, core::int* y) → core::int*
+    return x.{core::int::^}(y);
+  method j(core::int* x, core::int* y) → core::int*
+    return x.{core::int::^}(y);
+  method k(core::int* x, core::int* y) → core::int* {
+    return x.{core::int::^}(y);
+  }
+  method l(core::int* x, core::int* y) → core::int* {
+    return x.{core::int::^}(y);
+  }
+  method m(core::int* x, core::int* y) → core::int* {
+    core::int* z = x.{core::int::^}(y);
+    return z;
+  }
+  method n(core::int* x, core::int* y) → core::int* {
+    core::int* z = x.{core::int::^}(y);
+    return z;
+  }
+  method o(core::int* x, core::int* y) → core::int*
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  method p(core::int* x, core::int* y) → core::int*
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  method q(core::int* x, core::int* y) → core::int* {
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  }
+  method r(core::int* x, core::int* y) → core::int* {
+    return 1.{core::num::+}(x).{core::int::^}(y.{core::num::+}(3));
+  }
+  method s(core::int* x, core::int* y) → dynamic {
+    this.{self::Key::s}(x.{core::int::^}(y), x.{core::int::^}(y));
+    this.{self::Key::s}(x.{core::int::^}(y), x.{core::int::^}(y));
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline.expect
new file mode 100644
index 0000000..7cc788c
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline.expect
@@ -0,0 +1,31 @@
+abstract class Key {
+  int get a => runtimeType.hashCode ^ null.hashCode;
+  int get b => runtimeType.hashCode ^ null.hashCode;
+  int get c {}
+  int get d {}
+  int get e => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get g {}
+  int get h {}
+  int i(int x, int y) => x ^ y;
+  int j(int x, int y) => x ^ y;
+  int k(int x, int y) {}
+  int l(int x, int y) {}
+  int m(int x, int y) {}
+  int n(int x, int y) {}
+  int o(int x, int y) => 1 + x ^ y + 3;
+  int p(int x, int y) => 1 + x ^ y + 3;
+  int q(int x, int y) {}
+  int r(int x, int y) {}
+  s(int x, int y) {}
+  int foo;
+  int bar;
+  Key(int x, int y)
+      : foo = x ^ y,
+        bar = x ^ y {}
+  Key.NotDuplicate(int x, int y)
+      : foo = x ^ y,
+        bar = x ^ y {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..25de27c7
--- /dev/null
+++ b/pkg/front_end/testcases/general/error_recovery/issue_26810.dart.textual_outline_modelled.expect
@@ -0,0 +1,31 @@
+abstract class Key {
+  Key(int x, int y)
+      : foo = x ^ y,
+        bar = x ^ y {}
+  Key.NotDuplicate(int x, int y)
+      : foo = x ^ y,
+        bar = x ^ y {}
+  int bar;
+  int foo;
+  int get a => runtimeType.hashCode ^ null.hashCode;
+  int get b => runtimeType.hashCode ^ null.hashCode;
+  int get c {}
+  int get d {}
+  int get e => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get f => 1 + runtimeType.hashCode ^ null.hashCode + 3;
+  int get g {}
+  int get h {}
+  int i(int x, int y) => x ^ y;
+  int j(int x, int y) => x ^ y;
+  int k(int x, int y) {}
+  int l(int x, int y) {}
+  int m(int x, int y) {}
+  int n(int x, int y) {}
+  int o(int x, int y) => 1 + x ^ y + 3;
+  int p(int x, int y) => 1 + x ^ y + 3;
+  int q(int x, int y) {}
+  int r(int x, int y) {}
+  s(int x, int y) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.outline.expect
index 74ed3a8..6fb6069 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.outline.expect
@@ -15,6 +15,7 @@
 //   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // n<S e(
 //       ^...
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.expect
index 74ed3a8..6fb6069 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.expect
@@ -15,6 +15,7 @@
 //   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // n<S e(
 //       ^...
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.transformed.expect
index 74ed3a8..6fb6069 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart.strong.transformed.expect
@@ -15,6 +15,7 @@
 //   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39024.crash_dart:1:7: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // n<S e(
 //       ^...
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.outline.expect b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.outline.expect
index 961d9a1..5264a5a 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.outline.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.outline.expect
@@ -20,6 +20,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // () async => a b < c $? >
 //                         ^...
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.expect b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.expect
index 4ad3dc2..a61de5e 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.expect
@@ -20,6 +20,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // () async => a b < c $? >
 //                         ^...
 //
diff --git a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.transformed.expect
index 4ad3dc2..a61de5e 100644
--- a/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart.strong.transformed.expect
@@ -20,6 +20,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/general/error_recovery/issue_39202.crash_dart:1:25: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // () async => a b < c $? >
 //                         ^...
 //
diff --git a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
index 8dbe328..0676de4 100644
--- a/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/export_test.dart.strong.transformed.expect
@@ -10,3 +10,8 @@
 static method main() → dynamic {
   core::print(dev::UserTag*);
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///export_test.dart:14:9 -> TypeLiteralConstant(UserTag*)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
index ff7bf3c..04c23db 100644
--- a/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/expressions.dart.strong.transformed.expect
@@ -93,3 +93,12 @@
   #C1 = null
   #C2 = core::Object {}
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///expressions.dart:21:8 -> StringConstant("foobar")
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:70:10 -> TypeLiteralConstant(int*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:71:9 -> TypeLiteralConstant(int*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
+Evaluated: VariableGetImpl @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
+Evaluated: VariableGet @ org-dartlang-testcase:///expressions.dart:72:9 -> TypeLiteralConstant(int*)
+Extra constant evaluation: evaluated: 138, effectively constant: 6
diff --git a/pkg/front_end/testcases/general/external_import.dart.outline.expect b/pkg/front_end/testcases/general/external_import.dart.outline.expect
index b0af5d4..c82b9e6 100644
--- a/pkg/front_end/testcases/general/external_import.dart.outline.expect
+++ b/pkg/front_end/testcases/general/external_import.dart.outline.expect
@@ -7,3 +7,10 @@
 
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ null -> InstanceConstant(const ExternalName{ExternalName.name: "dart-ext:here"})
+Evaluated: ConstructorInvocation @ null -> InstanceConstant(const ExternalName{ExternalName.name: "dart-ext:foo/../there"})
+Evaluated: ConstructorInvocation @ null -> InstanceConstant(const ExternalName{ExternalName.name: "dart-ext:/usr/local/somewhere"})
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect b/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
index 30a39ac..2a3bf26 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.outline.expect
@@ -28,3 +28,9 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:13:4 -> InstanceConstant(const Double{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///ffi_sample.dart:16:4 -> InstanceConstant(const Double{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
index 97266d3..c402dca 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.strong.transformed.expect
@@ -44,7 +44,7 @@
   get next() → ffi::Pointer<self::Coordinate*>*
     return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi())));
   set next(ffi::Pointer<self::Coordinate*>* #v) → void
-    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi()), #v.{=ffi::Pointer::address});
+    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address});
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
index 6b161b4..b1f7867 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:32:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.superInstanceField in []) {}
 //          ^^^^^
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:33:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.untypedSuperInstanceField in []) {}
 //          ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
index 9e5e7ac..ea2e504 100644
--- a/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/for_in_without_declaration.dart.strong.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:32:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.superInstanceField in []) {}
 //          ^^^^^
 //
 // pkg/front_end/testcases/general/for_in_without_declaration.dart:33:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.untypedSuperInstanceField in []) {}
 //          ^^^^^
 //
diff --git a/pkg/front_end/testcases/general/function_type_default_value.dart.outline.expect b/pkg/front_end/testcases/general/function_type_default_value.dart.outline.expect
index 9d451cd..a4845bb 100644
--- a/pkg/front_end/testcases/general/function_type_default_value.dart.outline.expect
+++ b/pkg/front_end/testcases/general/function_type_default_value.dart.outline.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/function_type_default_value.dart:5:19: Error: Expected an identifier, but got ':'.
+// Try inserting an identifier before ':'.
 // void Function({obj: Object}) x;
 //                   ^
 //
diff --git a/pkg/front_end/testcases/general/function_type_default_value.dart.strong.expect b/pkg/front_end/testcases/general/function_type_default_value.dart.strong.expect
index 4e7f6a6..37aef15 100644
--- a/pkg/front_end/testcases/general/function_type_default_value.dart.strong.expect
+++ b/pkg/front_end/testcases/general/function_type_default_value.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/function_type_default_value.dart:5:19: Error: Expected an identifier, but got ':'.
+// Try inserting an identifier before ':'.
 // void Function({obj: Object}) x;
 //                   ^
 //
diff --git a/pkg/front_end/testcases/general/function_type_default_value.dart.strong.transformed.expect b/pkg/front_end/testcases/general/function_type_default_value.dart.strong.transformed.expect
index 4e7f6a6..37aef15 100644
--- a/pkg/front_end/testcases/general/function_type_default_value.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/function_type_default_value.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/function_type_default_value.dart:5:19: Error: Expected an identifier, but got ':'.
+// Try inserting an identifier before ':'.
 // void Function({obj: Object}) x;
 //                   ^
 //
diff --git a/pkg/front_end/testcases/general/getter_call.dart.strong.transformed.expect b/pkg/front_end/testcases/general/getter_call.dart.strong.transformed.expect
index 256e84e..7d5a3ba 100644
--- a/pkg/front_end/testcases/general/getter_call.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/getter_call.dart.strong.transformed.expect
@@ -185,3 +185,23 @@
   #C7 = tearoff self::method7
   #C8 = 0
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:7:45 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:130:10 -> IntConstant(-42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:131:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:133:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:136:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:138:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:141:10 -> IntConstant(-23)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:142:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:143:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:149:10 -> IntConstant(-42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:150:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:152:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:155:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:157:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:160:10 -> IntConstant(-23)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:161:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:162:10 -> IntConstant(-11)
+Extra constant evaluation: evaluated: 354, effectively constant: 17
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart b/pkg/front_end/testcases/general/getter_vs_setter_type.dart
new file mode 100644
index 0000000..4be746d
--- /dev/null
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart
@@ -0,0 +1,158 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  int get property1; // ok
+  void set property1(int i);
+
+  num get property2a; // ok
+  void set property2a(int i);
+
+  int get property2b; // ok
+  void set property2b(num i);
+
+  String get property3; // error
+  void set property3(int i);
+
+  int property4; // ok
+
+  int property5; // ok
+
+  covariant String property6; // ok
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8a => 0; // ok
+  static void set property8a(num value) {}
+
+  static num get property8b => 0; // ok
+  static void set property8b(int value) {}
+
+  static num get property9 => 0; // error
+  static void set property9(String value) {}
+}
+
+abstract class B1 {
+  int get property1;
+
+  int get property2;
+
+  String get property3;
+
+  final int property4;
+
+  final int property5;
+
+  final String property6;
+
+  B1(this.property4, this.property5, this.property6);
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i); // ok
+
+  void set property2(String i); // error
+
+  void set property3(int i); // error
+
+  void set property4(int i); // ok
+
+  void set property5(String i); // error
+
+  void set property6(int i); // error
+}
+
+abstract class C1 {
+  void set property1(int i);
+
+  void set property2(String i);
+
+  void set property3(int i);
+
+  int property4;
+
+  String property5;
+
+  int property6;
+}
+
+abstract class C2 implements C1 {
+  int get property1; // ok
+
+  int get property2; // error
+
+  String get property3; // error
+
+  int get property4; // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  int get property5; // error
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  String get property6; // error
+}
+
+abstract class D1 {
+  int get property1;
+
+  int get property2;
+
+  String get property3;
+}
+
+abstract class D2 {
+  void set property1(int i);
+
+  void set property2(String i);
+
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
+
+abstract class D4
+    implements D3 /* no need for error on property2 and property3 */ {}
+
+extension Extension<T extends num, S extends T> on int {
+  int get property1 => 0; // ok
+  void set property1(int i) {}
+
+  num get property2a => 0; // ok
+  void set property2a(int i) {}
+
+  int get property2b => 0; // ok
+  void set property2b(num i) {}
+
+  String get property3 => ''; // error
+  void set property3(int i) {}
+
+  S get property4 => 0; // ok
+  void set property4(S i) {}
+
+  S get property5a => 0; // ok
+  void set property5a(T i) {}
+
+  T get property5b => 0; // ok
+  void set property5b(S i) {}
+
+  String get property6 => ''; // error
+  void set property6(S i) {}
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8a => 0; // ok
+  static void set property8a(num value) {}
+
+  static num get property8b => 0; // ok
+  static void set property8b(int value) {}
+
+  static num get property9 => 0; // error
+  static void set property9(String value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect
new file mode 100644
index 0000000..f255528
--- /dev/null
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.outline.expect
@@ -0,0 +1,413 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:15:14: Error: The type 'String' of the getter 'A.property3' is not assignable to the type 'int' of the setter 'A.property3'.
+//   String get property3; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:16:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:33:18: Error: The type 'num' of the getter 'A.property9' is not assignable to the type 'String' of the setter 'A.property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:34:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(String value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:56:12: Error: The type 'int' of the inherited getter 'B1.property2' is not assignable to the type 'String' of the setter 'B2.property2'.
+//   void set property2(String i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:40:11: Context: This is the declaration of the getter 'B1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:58:12: Error: The type 'String' of the inherited getter 'B1.property3' is not assignable to the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:42:14: Context: This is the declaration of the getter 'B1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:62:12: Error: The type 'int' of the inherited field 'B1.property5' is not assignable to the type 'String' of the setter 'B2.property5'.
+//   void set property5(String i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:46:13: Context: This is the declaration of the field 'B1.property5'.
+//   final int property5;
+//             ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:64:12: Error: The type 'String' of the inherited field 'B1.property6' is not assignable to the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:48:16: Context: This is the declaration of the field 'B1.property6'.
+//   final String property6;
+//                ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:84:11: Error: The type 'int' of the getter 'C2.property2' is not assignable to the type 'String' of the inherited setter 'C1.property2'.
+//   int get property2; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:70:12: Context: This is the declaration of the setter 'C1.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:86:14: Error: The type 'String' of the getter 'C2.property3' is not assignable to the type 'int' of the inherited setter 'C1.property3'.
+//   String get property3; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:72:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The return type of the method 'C2.property5' is 'int', which does not match the return type, 'String', of the overridden method, 'C1.property5'.
+// Change to a subtype of 'String'.
+//   int get property5; // error
+//           ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the overridden method ('property5').
+//   String property5;
+//          ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
+//   int get property5; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
+//   String property5;
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The return type of the method 'C2.property6' is 'String', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   String get property6; // error
+//              ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
+//   String get property6; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
+// abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:102:11: Context: This is the declaration of the getter 'D1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:110:12: Context: This is the declaration of the setter 'D2.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'String' of the inherited getter 'D1.property3' is not assignable to the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:104:14: Context: This is the declaration of the getter 'D1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:112:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:117:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
+// abstract class D4
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:102:11: Context: This is the declaration of the getter 'D1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:110:12: Context: This is the declaration of the setter 'D2.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:117:16: Error: The type 'String' of the inherited getter 'D1.property3' is not assignable to the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:104:14: Context: This is the declaration of the getter 'D1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:112:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:130:14: Error: The type 'String' of the getter 'property3' is not assignable to the type 'int' of the setter 'property3'.
+//   String get property3 => ''; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:131:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:142:14: Error: The type 'String' of the getter 'property6' is not assignable to the type 'S' of the setter 'property6'.
+//   String get property6 => ''; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:143:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(S i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:154:18: Error: The type 'num' of the getter 'property9' is not assignable to the type 'String' of the setter 'property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:155:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(String value) {}
+//                   ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int* property4;
+  field core::int* property5;
+  covariant field core::String* property6;
+  synthetic constructor •() → self::A*
+    ;
+  abstract get property1() → core::int*;
+  abstract set property1(core::int* i) → void;
+  abstract get property2a() → core::num*;
+  abstract set property2a(core::int* i) → void;
+  abstract get property2b() → core::int*;
+  abstract set property2b(core::num* i) → void;
+  abstract get property3() → core::String*;
+  abstract set property3(core::int* i) → void;
+  static get property7() → core::int*
+    ;
+  static set property7(core::int* value) → void
+    ;
+  static get property8a() → core::int*
+    ;
+  static set property8a(core::num* value) → void
+    ;
+  static get property8b() → core::num*
+    ;
+  static set property8b(core::int* value) → void
+    ;
+  static get property9() → core::num*
+    ;
+  static set property9(core::String* value) → void
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class B1 extends core::Object {
+  final field core::int* property4;
+  final field core::int* property5;
+  final field core::String* property6;
+  constructor •(core::int* property4, core::int* property5, core::String* property6) → self::B1*
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2*
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract set property4(core::int* i) → void;
+  abstract set property5(core::String* i) → void;
+  abstract set property6(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class C1 extends core::Object {
+  field core::int* property4;
+  field core::String* property5;
+  field core::int* property6;
+  synthetic constructor •() → self::C1*
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2*
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract get property4() → core::int*;
+  abstract get property5() → core::int*;
+  abstract get property6() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1*
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2*
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension Extension<T extends core::num* = core::num*, S extends T* = core::num*> on core::int* {
+  get property1 = self::Extension|get#property1;
+  get property2a = self::Extension|get#property2a;
+  get property2b = self::Extension|get#property2b;
+  get property3 = self::Extension|get#property3;
+  get property4 = self::Extension|get#property4;
+  get property5a = self::Extension|get#property5a;
+  get property5b = self::Extension|get#property5b;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8a = get self::Extension|property8a;
+  static get property8b = get self::Extension|property8b;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2a = self::Extension|set#property2a;
+  set property2b = self::Extension|set#property2b;
+  set property3 = self::Extension|set#property3;
+  set property4 = self::Extension|set#property4;
+  set property5a = self::Extension|set#property5a;
+  set property5b = self::Extension|set#property5b;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8a = set self::Extension|property8a;
+  static set property8b = set self::Extension|property8b;
+  static set property9 = set self::Extension|property9;
+}
+static method Extension|get#property1<T extends core::num* = core::num*, S extends self::Extension|get#property1::T* = core::num*>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#property1<T extends core::num* = core::num*, S extends self::Extension|set#property1::T* = core::num*>(final core::int* #this, core::int* i) → void
+  ;
+static method Extension|get#property2a<T extends core::num* = core::num*, S extends self::Extension|get#property2a::T* = core::num*>(final core::int* #this) → core::num*
+  ;
+static method Extension|set#property2a<T extends core::num* = core::num*, S extends self::Extension|set#property2a::T* = core::num*>(final core::int* #this, core::int* i) → void
+  ;
+static method Extension|get#property2b<T extends core::num* = core::num*, S extends self::Extension|get#property2b::T* = core::num*>(final core::int* #this) → core::int*
+  ;
+static method Extension|set#property2b<T extends core::num* = core::num*, S extends self::Extension|set#property2b::T* = core::num*>(final core::int* #this, core::num* i) → void
+  ;
+static method Extension|get#property3<T extends core::num* = core::num*, S extends self::Extension|get#property3::T* = core::num*>(final core::int* #this) → core::String*
+  ;
+static method Extension|set#property3<T extends core::num* = core::num*, S extends self::Extension|set#property3::T* = core::num*>(final core::int* #this, core::int* i) → void
+  ;
+static method Extension|get#property4<T extends core::num* = core::num*, S extends self::Extension|get#property4::T* = core::num*>(final core::int* #this) → self::Extension|get#property4::S*
+  ;
+static method Extension|set#property4<T extends core::num* = core::num*, S extends self::Extension|set#property4::T* = core::num*>(final core::int* #this, self::Extension|set#property4::S* i) → void
+  ;
+static method Extension|get#property5a<T extends core::num* = core::num*, S extends self::Extension|get#property5a::T* = core::num*>(final core::int* #this) → self::Extension|get#property5a::S*
+  ;
+static method Extension|set#property5a<T extends core::num* = core::num*, S extends self::Extension|set#property5a::T* = core::num*>(final core::int* #this, self::Extension|set#property5a::T* i) → void
+  ;
+static method Extension|get#property5b<T extends core::num* = core::num*, S extends self::Extension|get#property5b::T* = core::num*>(final core::int* #this) → self::Extension|get#property5b::T*
+  ;
+static method Extension|set#property5b<T extends core::num* = core::num*, S extends self::Extension|set#property5b::T* = core::num*>(final core::int* #this, self::Extension|set#property5b::S* i) → void
+  ;
+static method Extension|get#property6<T extends core::num* = core::num*, S extends self::Extension|get#property6::T* = core::num*>(final core::int* #this) → core::String*
+  ;
+static method Extension|set#property6<T extends core::num* = core::num*, S extends self::Extension|set#property6::T* = core::num*>(final core::int* #this, self::Extension|set#property6::S* i) → void
+  ;
+static get Extension|property7() → core::int*
+  ;
+static set Extension|property7(core::int* value) → void
+  ;
+static get Extension|property8a() → core::int*
+  ;
+static set Extension|property8a(core::num* value) → void
+  ;
+static get Extension|property8b() → core::num*
+  ;
+static set Extension|property8b(core::int* value) → void
+  ;
+static get Extension|property9() → core::num*
+  ;
+static set Extension|property9(core::String* value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect
new file mode 100644
index 0000000..0ab82ac
--- /dev/null
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.strong.expect
@@ -0,0 +1,423 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:15:14: Error: The type 'String' of the getter 'A.property3' is not assignable to the type 'int' of the setter 'A.property3'.
+//   String get property3; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:16:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:33:18: Error: The type 'num' of the getter 'A.property9' is not assignable to the type 'String' of the setter 'A.property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:34:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(String value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:56:12: Error: The type 'int' of the inherited getter 'B1.property2' is not assignable to the type 'String' of the setter 'B2.property2'.
+//   void set property2(String i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:40:11: Context: This is the declaration of the getter 'B1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:58:12: Error: The type 'String' of the inherited getter 'B1.property3' is not assignable to the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:42:14: Context: This is the declaration of the getter 'B1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:62:12: Error: The type 'int' of the inherited field 'B1.property5' is not assignable to the type 'String' of the setter 'B2.property5'.
+//   void set property5(String i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:46:13: Context: This is the declaration of the field 'B1.property5'.
+//   final int property5;
+//             ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:64:12: Error: The type 'String' of the inherited field 'B1.property6' is not assignable to the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:48:16: Context: This is the declaration of the field 'B1.property6'.
+//   final String property6;
+//                ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:84:11: Error: The type 'int' of the getter 'C2.property2' is not assignable to the type 'String' of the inherited setter 'C1.property2'.
+//   int get property2; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:70:12: Context: This is the declaration of the setter 'C1.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:86:14: Error: The type 'String' of the getter 'C2.property3' is not assignable to the type 'int' of the inherited setter 'C1.property3'.
+//   String get property3; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:72:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The return type of the method 'C2.property5' is 'int', which does not match the return type, 'String', of the overridden method, 'C1.property5'.
+// Change to a subtype of 'String'.
+//   int get property5; // error
+//           ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the overridden method ('property5').
+//   String property5;
+//          ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:92:11: Error: The type 'int' of the getter 'C2.property5' is not assignable to the type 'String' of the inherited setter 'C1.property5'.
+//   int get property5; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:76:10: Context: This is the declaration of the setter 'C1.property5'.
+//   String property5;
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The return type of the method 'C2.property6' is 'String', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   String get property6; // error
+//              ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:96:14: Error: The type 'String' of the getter 'C2.property6' is not assignable to the type 'int' of the inherited setter 'C1.property6'.
+//   String get property6; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:78:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
+// abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:102:11: Context: This is the declaration of the getter 'D1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:110:12: Context: This is the declaration of the setter 'D2.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:115:16: Error: The type 'String' of the inherited getter 'D1.property3' is not assignable to the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property2 and property3 */ {}
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:104:14: Context: This is the declaration of the getter 'D1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:112:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:117:16: Error: The type 'int' of the inherited getter 'D1.property2' is not assignable to the type 'String' of the inherited setter 'D2.property2'.
+// abstract class D4
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:102:11: Context: This is the declaration of the getter 'D1.property2'.
+//   int get property2;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:110:12: Context: This is the declaration of the setter 'D2.property2'.
+//   void set property2(String i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:117:16: Error: The type 'String' of the inherited getter 'D1.property3' is not assignable to the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4
+//                ^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:104:14: Context: This is the declaration of the getter 'D1.property3'.
+//   String get property3;
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:112:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:130:14: Error: The type 'String' of the getter 'property3' is not assignable to the type 'int' of the setter 'property3'.
+//   String get property3 => ''; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:131:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:142:14: Error: The type 'String' of the getter 'property6' is not assignable to the type 'S' of the setter 'property6'.
+//   String get property6 => ''; // error
+//              ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:143:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(S i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:154:18: Error: The type 'num' of the getter 'property9' is not assignable to the type 'String' of the setter 'property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:155:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(String value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be assigned to a variable of type 'S'.
+//   S get property4 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:136:23: Error: A value of type 'int' can't be assigned to a variable of type 'S'.
+//   S get property5a => 0; // ok
+//                       ^
+//
+// pkg/front_end/testcases/general/getter_vs_setter_type.dart:139:23: Error: A value of type 'int' can't be assigned to a variable of type 'T'.
+//   T get property5b => 0; // ok
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int* property4 = null;
+  field core::int* property5 = null;
+  covariant field core::String* property6 = null;
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int*;
+  abstract set property1(core::int* i) → void;
+  abstract get property2a() → core::num*;
+  abstract set property2a(core::int* i) → void;
+  abstract get property2b() → core::int*;
+  abstract set property2b(core::num* i) → void;
+  abstract get property3() → core::String*;
+  abstract set property3(core::int* i) → void;
+  static get property7() → core::int*
+    return 0;
+  static set property7(core::int* value) → void {}
+  static get property8a() → core::int*
+    return 0;
+  static set property8a(core::num* value) → void {}
+  static get property8b() → core::num*
+    return 0;
+  static set property8b(core::int* value) → void {}
+  static get property9() → core::num*
+    return 0;
+  static set property9(core::String* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class B1 extends core::Object {
+  final field core::int* property4;
+  final field core::int* property5;
+  final field core::String* property6;
+  constructor •(core::int* property4, core::int* property5, core::String* property6) → self::B1*
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2*
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract set property4(core::int* i) → void;
+  abstract set property5(core::String* i) → void;
+  abstract set property6(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class C1 extends core::Object {
+  field core::int* property4 = null;
+  field core::String* property5 = null;
+  field core::int* property6 = null;
+  synthetic constructor •() → self::C1*
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2*
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract get property4() → core::int*;
+  abstract get property5() → core::int*;
+  abstract get property6() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1*
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int*;
+  abstract get property2() → core::int*;
+  abstract get property3() → core::String*;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2*
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int* i) → void;
+  abstract set property2(core::String* i) → void;
+  abstract set property3(core::int* i) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension Extension<T extends core::num* = core::num*, S extends T* = core::num*> on core::int* {
+  get property1 = self::Extension|get#property1;
+  get property2a = self::Extension|get#property2a;
+  get property2b = self::Extension|get#property2b;
+  get property3 = self::Extension|get#property3;
+  get property4 = self::Extension|get#property4;
+  get property5a = self::Extension|get#property5a;
+  get property5b = self::Extension|get#property5b;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8a = get self::Extension|property8a;
+  static get property8b = get self::Extension|property8b;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2a = self::Extension|set#property2a;
+  set property2b = self::Extension|set#property2b;
+  set property3 = self::Extension|set#property3;
+  set property4 = self::Extension|set#property4;
+  set property5a = self::Extension|set#property5a;
+  set property5b = self::Extension|set#property5b;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8a = set self::Extension|property8a;
+  static set property8b = set self::Extension|property8b;
+  static set property9 = set self::Extension|property9;
+}
+static method Extension|get#property1<T extends core::num* = core::num*, S extends self::Extension|get#property1::T* = core::num*>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#property1<T extends core::num* = core::num*, S extends self::Extension|set#property1::T* = core::num*>(final core::int* #this, core::int* i) → void {}
+static method Extension|get#property2a<T extends core::num* = core::num*, S extends self::Extension|get#property2a::T* = core::num*>(final core::int* #this) → core::num*
+  return 0;
+static method Extension|set#property2a<T extends core::num* = core::num*, S extends self::Extension|set#property2a::T* = core::num*>(final core::int* #this, core::int* i) → void {}
+static method Extension|get#property2b<T extends core::num* = core::num*, S extends self::Extension|get#property2b::T* = core::num*>(final core::int* #this) → core::int*
+  return 0;
+static method Extension|set#property2b<T extends core::num* = core::num*, S extends self::Extension|set#property2b::T* = core::num*>(final core::int* #this, core::num* i) → void {}
+static method Extension|get#property3<T extends core::num* = core::num*, S extends self::Extension|get#property3::T* = core::num*>(final core::int* #this) → core::String*
+  return "";
+static method Extension|set#property3<T extends core::num* = core::num*, S extends self::Extension|set#property3::T* = core::num*>(final core::int* #this, core::int* i) → void {}
+static method Extension|get#property4<T extends core::num* = core::num*, S extends self::Extension|get#property4::T* = core::num*>(final core::int* #this) → self::Extension|get#property4::S*
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be assigned to a variable of type 'S'.
+  S get property4 => 0; // ok
+                     ^" in 0 as{TypeError} <BottomType>;
+static method Extension|set#property4<T extends core::num* = core::num*, S extends self::Extension|set#property4::T* = core::num*>(final core::int* #this, self::Extension|set#property4::S* i) → void {}
+static method Extension|get#property5a<T extends core::num* = core::num*, S extends self::Extension|get#property5a::T* = core::num*>(final core::int* #this) → self::Extension|get#property5a::S*
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/general/getter_vs_setter_type.dart:136:23: Error: A value of type 'int' can't be assigned to a variable of type 'S'.
+  S get property5a => 0; // ok
+                      ^" in 0 as{TypeError} <BottomType>;
+static method Extension|set#property5a<T extends core::num* = core::num*, S extends self::Extension|set#property5a::T* = core::num*>(final core::int* #this, self::Extension|set#property5a::T* i) → void {}
+static method Extension|get#property5b<T extends core::num* = core::num*, S extends self::Extension|get#property5b::T* = core::num*>(final core::int* #this) → self::Extension|get#property5b::T*
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/general/getter_vs_setter_type.dart:139:23: Error: A value of type 'int' can't be assigned to a variable of type 'T'.
+  T get property5b => 0; // ok
+                      ^" in 0 as{TypeError} <BottomType>;
+static method Extension|set#property5b<T extends core::num* = core::num*, S extends self::Extension|set#property5b::T* = core::num*>(final core::int* #this, self::Extension|set#property5b::S* i) → void {}
+static method Extension|get#property6<T extends core::num* = core::num*, S extends self::Extension|get#property6::T* = core::num*>(final core::int* #this) → core::String*
+  return "";
+static method Extension|set#property6<T extends core::num* = core::num*, S extends self::Extension|set#property6::T* = core::num*>(final core::int* #this, self::Extension|set#property6::S* i) → void {}
+static get Extension|property7() → core::int*
+  return 0;
+static set Extension|property7(core::int* value) → void {}
+static get Extension|property8a() → core::int*
+  return 0;
+static set Extension|property8a(core::num* value) → void {}
+static get Extension|property8b() → core::num*
+  return 0;
+static set Extension|property8b(core::int* value) → void {}
+static get Extension|property9() → core::num*
+  return 0;
+static set Extension|property9(core::String* value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
new file mode 100644
index 0000000..47e2d86
--- /dev/null
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline.expect
@@ -0,0 +1,69 @@
+abstract class A {
+  int get property1;
+  void set property1(int i);
+  num get property2a;
+  void set property2a(int i);
+  int get property2b;
+  void set property2b(num i);
+  String get property3;
+  void set property3(int i);
+  int property4;
+  int property5;
+  covariant String property6;
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8a => 0;
+  static void set property8a(num value) {}
+  static num get property8b => 0;
+  static void set property8b(int value) {}
+  static num get property9 => 0;
+  static void set property9(String value) {}
+}
+abstract class B1 {
+  int get property1;
+  int get property2;
+  String get property3;
+  final int property4;
+  final int property5;
+  final String property6;
+  B1(this.property4, this.property5, this.property6);
+}
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(String i);
+  void set property6(int i);
+}
+abstract class C1 {
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+  int property4;
+  String property5;
+  int property6;
+}
+abstract class C2 implements C1 {
+  int get property1;
+  int get property2;
+  String get property3;
+  int get property4;
+  int get property5;
+  String get property6;
+}
+abstract class D1 {
+  int get property1;
+  int get property2;
+  String get property3;
+}
+abstract class D2 {
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+}
+abstract class D3 implements D1, D2 {}
+abstract class D4 implements D3 {}
+extension Extension<T extends num, S extends T> (){}
+on int (){}
+main() {}
diff --git a/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e2ee020
--- /dev/null
+++ b/pkg/front_end/testcases/general/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,76 @@
+abstract class A {
+  String get property3;
+  covariant String property6;
+  int get property1;
+  int get property2b;
+  int property4;
+  int property5;
+  num get property2a;
+  static int get property7 => 0;
+  static int get property8a => 0;
+  static num get property8b => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8a(num value) {}
+  static void set property8b(int value) {}
+  static void set property9(String value) {}
+  void set property1(int i);
+  void set property2a(int i);
+  void set property2b(num i);
+  void set property3(int i);
+}
+
+abstract class B1 {
+  B1(this.property4, this.property5, this.property6);
+  String get property3;
+  final String property6;
+  final int property4;
+  final int property5;
+  int get property1;
+  int get property2;
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(String i);
+  void set property6(int i);
+}
+
+abstract class C1 {
+  String property5;
+  int property4;
+  int property6;
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+}
+
+abstract class C2 implements C1 {
+  String get property3;
+  String get property6;
+  int get property1;
+  int get property2;
+  int get property4;
+  int get property5;
+}
+
+abstract class D1 {
+  String get property3;
+  int get property1;
+  int get property2;
+}
+
+abstract class D2 {
+  void set property1(int i);
+  void set property2(String i);
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 {}
+
+abstract class D4 implements D3 {}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/implicit_scope_test.dart.strong.transformed.expect b/pkg/front_end/testcases/general/implicit_scope_test.dart.strong.transformed.expect
index f041292..19d91ae 100644
--- a/pkg/front_end/testcases/general/implicit_scope_test.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/implicit_scope_test.dart.strong.transformed.expect
@@ -57,3 +57,9 @@
 static method main() → dynamic {
   self::ImplicitScopeTest::testMain();
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_scope_test.dart:11:18 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_scope_test.dart:32:49 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 28, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.outline.expect b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.outline.expect
index d2bc9fe..39fdd1f 100644
--- a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.outline.expect
+++ b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.outline.expect
@@ -7,10 +7,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.a(this);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.b(this.);
 //            ^
 //
@@ -19,10 +21,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.c(this, p);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.d(this., p);
 //            ^
 //
diff --git a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.expect b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.expect
index b147c01..ec23930 100644
--- a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.expect
+++ b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.expect
@@ -7,10 +7,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.a(this);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.b(this.);
 //            ^
 //
@@ -19,10 +21,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.c(this, p);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.d(this., p);
 //            ^
 //
diff --git a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.transformed.expect b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.transformed.expect
index b147c01..ec23930 100644
--- a/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart.strong.transformed.expect
@@ -7,10 +7,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:6:11: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.a(this);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:7:12: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.b(this.);
 //            ^
 //
@@ -19,10 +21,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.c(this, p);
 //           ^
 //
 // pkg/front_end/testcases/general/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.d(this., p);
 //            ^
 //
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
index 2bbb7e2..8c879e7 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.outline.expect
@@ -2,146 +2,146 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the overridden members.
 //   var field2 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the overridden members.
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the overridden members.
 //   var field4 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the overridden members.
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the overridden members.
 //   int field6;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the overridden members.
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the overridden members.
 //   int field8;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the overridden members.
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field11; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:16:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:16:5: Context: This is one of the overridden members.
 //   T field11;
 //     ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:37:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:37:5: Context: This is one of the overridden members.
 //   S field11;
 //     ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the overridden members.
 //   var field17 = 0;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the overridden members.
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the overridden members.
 //   int field18;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the overridden members.
 //   var field18 = '';
 //       ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the overridden members.
 //   var field2 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the overridden members.
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the overridden members.
 //   var field4 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the overridden members.
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the overridden members.
 //   int field6;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the overridden members.
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the overridden members.
 //   int field8;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the overridden members.
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the overridden members.
 //   var field17 = 0;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the overridden members.
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the overridden members.
 //   int field18;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the overridden members.
 //   var field18 = '';
 //       ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
index 73fdb87..0400159 100644
--- a/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/general/infer_field_from_multiple.dart.strong.expect
@@ -2,146 +2,146 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:49:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the overridden members.
 //   var field2 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the overridden members.
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:51:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the overridden members.
 //   var field4 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the overridden members.
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:53:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the overridden members.
 //   int field6;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the overridden members.
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:55:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the overridden members.
 //   int field8;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the overridden members.
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:58:7: Error: Can't infer a type for 'field11' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field11; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:16:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:16:5: Context: This is one of the overridden members.
 //   T field11;
 //     ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:37:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:37:5: Context: This is one of the overridden members.
 //   S field11;
 //     ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:64:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the overridden members.
 //   var field17 = 0;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the overridden members.
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:65:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the overridden members.
 //   int field18;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the overridden members.
 //   var field18 = '';
 //       ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:90:7: Error: Can't infer a type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field2; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:7:7: Context: This is one of the overridden members.
 //   var field2 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:28:7: Context: This is one of the overridden members.
 //   var field2 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:92:7: Error: Can't infer a type for 'field4' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field4 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:9:7: Context: This is one of the overridden members.
 //   var field4 = 0;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:30:7: Context: This is one of the overridden members.
 //   var field4 = '';
 //       ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:94:7: Error: Can't infer a type for 'field6' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field6; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:11:7: Context: This is one of the overridden members.
 //   int field6;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:32:10: Context: This is one of the overridden members.
 //   String field6;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:96:7: Error: Can't infer a type for 'field8' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field8 = 0; // error
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:13:7: Context: This is one of the overridden members.
 //   int field8;
 //       ^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:34:10: Context: This is one of the overridden members.
 //   String field8;
 //          ^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:105:7: Error: Can't infer a type for 'field17' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field17; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:22:7: Context: This is one of the overridden members.
 //   var field17 = 0;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:43:10: Context: This is one of the overridden members.
 //   String field17;
 //          ^^^^^^^
 //
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:106:7: Error: Can't infer a type for 'field18' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var field18; // error
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:23:7: Context: This is one of the overridden members.
 //   int field18;
 //       ^^^^^^^
-// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/infer_field_from_multiple.dart:44:7: Context: This is one of the overridden members.
 //   var field18 = '';
 //       ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/general/interface_conflict.dart.outline.expect b/pkg/front_end/testcases/general/interface_conflict.dart.outline.expect
index 9b896a7..ec8f574 100644
--- a/pkg/front_end/testcases/general/interface_conflict.dart.outline.expect
+++ b/pkg/front_end/testcases/general/interface_conflict.dart.outline.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'C'.
 // abstract class C implements A, B {}
 //                ^
-// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/interface_conflict.dart.strong.expect b/pkg/front_end/testcases/general/interface_conflict.dart.strong.expect
index 98445c0..35d40fb 100644
--- a/pkg/front_end/testcases/general/interface_conflict.dart.strong.expect
+++ b/pkg/front_end/testcases/general/interface_conflict.dart.strong.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'C'.
 // abstract class C implements A, B {}
 //                ^
-// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/interface_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/general/interface_conflict.dart.strong.transformed.expect
index 98445c0..35d40fb 100644
--- a/pkg/front_end/testcases/general/interface_conflict.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/interface_conflict.dart.strong.transformed.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'C'.
 // abstract class C implements A, B {}
 //                ^
-// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/invalid_type.dart.strong.transformed.expect b/pkg/front_end/testcases/general/invalid_type.dart.strong.transformed.expect
index eee2023..26b45d2 100644
--- a/pkg/front_end/testcases/general/invalid_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/invalid_type.dart.strong.transformed.expect
@@ -46,3 +46,8 @@
        ^^^";
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: AsExpression @ org-dartlang-testcase:///invalid_type.dart:12:9 -> NullConstant(null)
+Extra constant evaluation: evaluated: 3, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
index b39c1af..5fe56f9 100644
--- a/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue40662.dart.strong.transformed.expect
@@ -83,3 +83,9 @@
   if(!expected.{core::Object::==}(actual))
     throw "Expected ${expected}, actual ${actual}";
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///issue40662.dart:8:10 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///issue40662.dart:9:10 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 99, effectively constant: 2
diff --git a/pkg/front_end/testcases/general/issue40744.dart.outline.expect b/pkg/front_end/testcases/general/issue40744.dart.outline.expect
index 373527d..3b367f6 100644
--- a/pkg/front_end/testcases/general/issue40744.dart.outline.expect
+++ b/pkg/front_end/testcases/general/issue40744.dart.outline.expect
@@ -7,3 +7,8 @@
   ;
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: MapLiteral @ org-dartlang-testcase:///issue40744.dart:5:53 -> InstanceConstant(const _ImmutableMap<String*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>["a", 1]})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue42610.dart.strong.expect b/pkg/front_end/testcases/general/issue42610.dart.strong.expect
index 77e5fc9..40fc5da 100644
--- a/pkg/front_end/testcases/general/issue42610.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue42610.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/issue42610.dart:6:4: Error: Expected an identifier, but got 'final'.
+// Try inserting an identifier before 'final'.
 //   #final;
 //    ^^^^^
 //
@@ -11,6 +12,7 @@
 //    ^^^^^
 //
 // pkg/front_end/testcases/general/issue42610.dart:6:9: Error: Expected an identifier, but got ';'.
+// Try inserting an identifier before ';'.
 //   #final;
 //         ^
 //
diff --git a/pkg/front_end/testcases/general/issue42610.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue42610.dart.strong.transformed.expect
index 77e5fc9..40fc5da 100644
--- a/pkg/front_end/testcases/general/issue42610.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue42610.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general/issue42610.dart:6:4: Error: Expected an identifier, but got 'final'.
+// Try inserting an identifier before 'final'.
 //   #final;
 //    ^^^^^
 //
@@ -11,6 +12,7 @@
 //    ^^^^^
 //
 // pkg/front_end/testcases/general/issue42610.dart:6:9: Error: Expected an identifier, but got ';'.
+// Try inserting an identifier before ';'.
 //   #final;
 //         ^
 //
diff --git a/pkg/front_end/testcases/general/issue42694.dart b/pkg/front_end/testcases/general/issue42694.dart
new file mode 100644
index 0000000..95e5875
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  void set setter(int value);
+}
+
+class B implements A {
+  get setter => throw '';
+  void set setter(value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue42694.dart.outline.expect b/pkg/front_end/testcases/general/issue42694.dart.outline.expect
new file mode 100644
index 0000000..1b716ec
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart.outline.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  abstract set setter(core::int* value) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object implements self::A {
+  synthetic constructor •() → self::B*
+    ;
+  get setter() → core::int*
+    ;
+  set setter(core::int* value) → void
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue42694.dart.strong.expect b/pkg/front_end/testcases/general/issue42694.dart.strong.expect
new file mode 100644
index 0000000..f8b3fdc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart.strong.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract set setter(core::int* value) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object implements self::A {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  get setter() → core::int*
+    return throw "";
+  set setter(core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue42694.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue42694.dart.strong.transformed.expect
new file mode 100644
index 0000000..f8b3fdc
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart.strong.transformed.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  abstract set setter(core::int* value) → void;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object implements self::A {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  get setter() → core::int*
+    return throw "";
+  set setter(core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue42694.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue42694.dart.textual_outline.expect
new file mode 100644
index 0000000..6d5d6ad
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+abstract class A {
+  void set setter(int value);
+}
+
+class B implements A {
+  get setter => throw '';
+  void set setter(value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue42694.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue42694.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6d5d6ad
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue42694.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+abstract class A {
+  void set setter(int value);
+}
+
+class B implements A {
+  get setter => throw '';
+  void set setter(value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue42997.dart.strong.expect b/pkg/front_end/testcases/general/issue42997.dart.strong.expect
index 2c07d53..40813a7 100644
--- a/pkg/front_end/testcases/general/issue42997.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue42997.dart.strong.expect
@@ -23,6 +23,7 @@
 //                        ^^^^^^
 //
 // pkg/front_end/testcases/general/issue42997.dart:12:30: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //     for (PropertyState<Object, Object>> state in _states) ;
 //                              ^
 //
diff --git a/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
index 3706504..b501d6e 100644
--- a/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue42997.dart.strong.transformed.expect
@@ -23,6 +23,7 @@
 //                        ^^^^^^
 //
 // pkg/front_end/testcases/general/issue42997.dart:12:30: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //     for (PropertyState<Object, Object>> state in _states) ;
 //                              ^
 //
@@ -80,3 +81,8 @@
 }
 static method main() → dynamic {}
 static abstract method PropertyState() → dynamic;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///issue42997.dart:12:24 -> TypeLiteralConstant(Object*)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/issue43290.dart.strong.expect b/pkg/front_end/testcases/general/issue43290.dart.strong.expect
index 9edb793..053b66cc 100644
--- a/pkg/front_end/testcases/general/issue43290.dart.strong.expect
+++ b/pkg/front_end/testcases/general/issue43290.dart.strong.expect
@@ -1,5 +1,14 @@
+library;
 //
-// Problems in component:
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue43290.dart:11:25: Error: Not a constant expression.
+//     const Class(length: length);
+//                         ^^^^^^
+//
+// pkg/front_end/testcases/general/issue43290.dart:19:15: Error: Not a constant expression.
+//     const a = length;
+//               ^^^^^^
 //
 // pkg/front_end/testcases/general/issue43290.dart:7:11: Error: Constant evaluation error:
 //     const Class(length: this.length);
@@ -35,18 +44,6 @@
 //     const a = length;
 //           ^
 //
-library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/issue43290.dart:11:25: Error: Not a constant expression.
-//     const Class(length: length);
-//                         ^^^^^^
-//
-// pkg/front_end/testcases/general/issue43290.dart:19:15: Error: Not a constant expression.
-//     const a = length;
-//               ^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/issue43290.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue43290.dart.strong.transformed.expect
index 9edb793..053b66cc 100644
--- a/pkg/front_end/testcases/general/issue43290.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/issue43290.dart.strong.transformed.expect
@@ -1,5 +1,14 @@
+library;
 //
-// Problems in component:
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue43290.dart:11:25: Error: Not a constant expression.
+//     const Class(length: length);
+//                         ^^^^^^
+//
+// pkg/front_end/testcases/general/issue43290.dart:19:15: Error: Not a constant expression.
+//     const a = length;
+//               ^^^^^^
 //
 // pkg/front_end/testcases/general/issue43290.dart:7:11: Error: Constant evaluation error:
 //     const Class(length: this.length);
@@ -35,18 +44,6 @@
 //     const a = length;
 //           ^
 //
-library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/issue43290.dart:11:25: Error: Not a constant expression.
-//     const Class(length: length);
-//                         ^^^^^^
-//
-// pkg/front_end/testcases/general/issue43290.dart:19:15: Error: Not a constant expression.
-//     const a = length;
-//               ^^^^^^
-//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/issue43721.dart b/pkg/front_end/testcases/general/issue43721.dart
new file mode 100644
index 0000000..2e034fd
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart
@@ -0,0 +1,15 @@
+import 'dart:async';
+
+ok<T extends FutureOr<num>>(T t) {}
+error<T extends FutureOr<int>>(T t) {}
+
+bar(bool condition) {
+  FutureOr<int> x = null;
+  num n = 1;
+  var z = condition ? x : n;
+
+  ok(z); // Ok.
+  error(z); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/general/issue43721.dart.outline.expect b/pkg/front_end/testcases/general/issue43721.dart.outline.expect
new file mode 100644
index 0000000..84a6f86
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method ok<T extends FutureOr<core::num*>* = FutureOr<core::num*>*>(self::ok::T* t) → dynamic
+  ;
+static method error<T extends FutureOr<core::int*>* = FutureOr<core::int*>*>(self::error::T* t) → dynamic
+  ;
+static method bar(core::bool* condition) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/issue43721.dart.strong.expect b/pkg/front_end/testcases/general/issue43721.dart.strong.expect
new file mode 100644
index 0000000..4874055
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue43721.dart:12:3: Error: Inferred type argument 'FutureOr<num>' doesn't conform to the bound 'FutureOr<int>' of the type variable 'T' on 'error'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   error(z); // Error.
+//   ^
+// pkg/front_end/testcases/general/issue43721.dart:4:7: Context: This is the type variable whose bound isn't conformed to.
+// error<T extends FutureOr<int>>(T t) {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method ok<T extends FutureOr<core::num*>* = FutureOr<core::num*>*>(self::ok::T* t) → dynamic {}
+static method error<T extends FutureOr<core::int*>* = FutureOr<core::int*>*>(self::error::T* t) → dynamic {}
+static method bar(core::bool* condition) → dynamic {
+  FutureOr<core::int*>* x = null;
+  core::num* n = 1;
+  FutureOr<core::num*>* z = condition ?{FutureOr<core::num*>*} x : n;
+  self::ok<FutureOr<core::num*>*>(z);
+  self::error<FutureOr<core::num*>*>(z);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue43721.dart.strong.transformed.expect b/pkg/front_end/testcases/general/issue43721.dart.strong.transformed.expect
new file mode 100644
index 0000000..4874055
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/issue43721.dart:12:3: Error: Inferred type argument 'FutureOr<num>' doesn't conform to the bound 'FutureOr<int>' of the type variable 'T' on 'error'.
+// Try specifying type arguments explicitly so that they conform to the bounds.
+//   error(z); // Error.
+//   ^
+// pkg/front_end/testcases/general/issue43721.dart:4:7: Context: This is the type variable whose bound isn't conformed to.
+// error<T extends FutureOr<int>>(T t) {}
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method ok<T extends FutureOr<core::num*>* = FutureOr<core::num*>*>(self::ok::T* t) → dynamic {}
+static method error<T extends FutureOr<core::int*>* = FutureOr<core::int*>*>(self::error::T* t) → dynamic {}
+static method bar(core::bool* condition) → dynamic {
+  FutureOr<core::int*>* x = null;
+  core::num* n = 1;
+  FutureOr<core::num*>* z = condition ?{FutureOr<core::num*>*} x : n;
+  self::ok<FutureOr<core::num*>*>(z);
+  self::error<FutureOr<core::num*>*>(z);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/general/issue43721.dart.textual_outline.expect b/pkg/front_end/testcases/general/issue43721.dart.textual_outline.expect
new file mode 100644
index 0000000..8cb94b0
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+import 'dart:async';
+
+ok<T extends FutureOr<num>>(T t) {}
+error<T extends FutureOr<int>>(T t) {}
+bar(bool condition) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/issue43721.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/issue43721.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f3e0e4c
--- /dev/null
+++ b/pkg/front_end/testcases/general/issue43721.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+import 'dart:async';
+
+bar(bool condition) {}
+error<T extends FutureOr<int>>(T t) {}
+main() {}
+ok<T extends FutureOr<num>>(T t) {}
diff --git a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
index 28519d4..d40ba2b8 100644
--- a/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/magic_const.dart.strong.transformed.expect
@@ -69,3 +69,7 @@
 constants  {
   #C1 = self::Constant {}
 }
+
+Extra constant evaluation status:
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///magic_const.dart:21:8 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/main_declaration.dart b/pkg/front_end/testcases/general/main_declaration.dart
new file mode 100644
index 0000000..e4df1b0
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/main_declaration.dart.outline.expect b/pkg/front_end/testcases/general/main_declaration.dart.outline.expect
new file mode 100644
index 0000000..600a236
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart.outline.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_lib.dart";
+
+static method main() → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+static method main(core::String* args) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/main_declaration.dart.strong.expect b/pkg/front_end/testcases/general/main_declaration.dart.strong.expect
new file mode 100644
index 0000000..58118e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_lib.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+static method main(core::String* args) → dynamic {}
diff --git a/pkg/front_end/testcases/general/main_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/general/main_declaration.dart.strong.transformed.expect
new file mode 100644
index 0000000..58118e1
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_lib.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+static method main(core::String* args) → dynamic {}
diff --git a/pkg/front_end/testcases/general/main_declaration.dart.textual_outline.expect b/pkg/front_end/testcases/general/main_declaration.dart.textual_outline.expect
new file mode 100644
index 0000000..5ab8783
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/main_declaration.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/main_declaration.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5ab8783
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/main_declaration_lib.dart b/pkg/front_end/testcases/general/main_declaration_lib.dart
new file mode 100644
index 0000000..f0d8fb7
--- /dev/null
+++ b/pkg/front_end/testcases/general/main_declaration_lib.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This would be an invalid main declaration in a null safe library.
+main(String args) {}
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
index 0c6825b..908f423 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.outline.expect
@@ -14,7 +14,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -28,3 +28,12 @@
 static const field dynamic a = null;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///metadata_enum.dart:7:2 -> NullConstant(null)
+Evaluated: ListLiteral @ org-dartlang-testcase:///metadata_enum.dart:8:6 -> ListConstant(const <E*>[const E{E.index: 0, E._name: "E.E1"}, const E{E.index: 1, E._name: "E.E2"}, const E{E.index: 2, E._name: "E.E3"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///metadata_enum.dart:8:10 -> InstanceConstant(const E{E.index: 0, E._name: "E.E1"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///metadata_enum.dart:8:14 -> InstanceConstant(const E{E.index: 1, E._name: "E.E2"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///metadata_enum.dart:8:18 -> InstanceConstant(const E{E.index: 2, E._name: "E.E3"})
+Extra constant evaluation: evaluated: 9, effectively constant: 5
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
index 0c71aa0..b5f94c3 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.expect
@@ -14,7 +14,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
index 0c71aa0..b5f94c3 100644
--- a/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/metadata_enum.dart.strong.transformed.expect
@@ -14,7 +14,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.outline.expect b/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.outline.expect
index eaf663b..537845c 100644
--- a/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/general/metadata_named_mixin_application.dart.outline.expect
@@ -39,3 +39,8 @@
 static const field dynamic a = null;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///metadata_named_mixin_application.dart:7:2 -> NullConstant(null)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/minimum_int.dart.strong.transformed.expect b/pkg/front_end/testcases/general/minimum_int.dart.strong.transformed.expect
index 17fdfdc..493f69a 100644
--- a/pkg/front_end/testcases/general/minimum_int.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/minimum_int.dart.strong.transformed.expect
@@ -4,3 +4,8 @@
 
 static method main() → dynamic
   return core::print(-9223372036854775808.{core::int::unary-}());
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///minimum_int.dart:1:17 -> IntConstant(-9223372036854775808)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect
index 7bd99d8..20fffed 100644
--- a/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/missing_toplevel.dart.strong.transformed.expect
@@ -129,3 +129,12 @@
 var missingPropertySet = emptyClass.property = 42;
                                     ^^^^^^^^";
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:28:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:28:48 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:28:48 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:29:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:29:48 -> IntConstant(2)
+Extra constant evaluation: evaluated: 37, effectively constant: 5
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
index 0c0d538..daa1e5a 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart:9:15: Error: Constant evaluation error:
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
@@ -11,7 +12,6 @@
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
 //            ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
diff --git a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
index 0cc126e..fe40abd 100644
--- a/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general/mixin_constructors_with_default_values.dart:9:15: Error: Constant evaluation error:
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
@@ -11,7 +12,6 @@
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
 //            ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/libraries.json b/pkg/front_end/testcases/general/mixin_from_patch/libraries.json
new file mode 100644
index 0000000..154c73c
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/libraries.json
@@ -0,0 +1,12 @@
+{
+  "none": {
+    "libraries": {
+      "test": {
+        "patches": [
+          "patch_lib.dart"
+        ],
+        "uri": "origin_lib.dart"
+      }
+    }
+  }
+}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart b/pkg/front_end/testcases/general/mixin_from_patch/main.dart
new file mode 100644
index 0000000..9a64949
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:test';
+
+main() {
+  new Class.patched();
+  new Class.unpatched();
+  new SubClass.patched();
+  new SubClass.unpatched();
+}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.outline.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.outline.expect
new file mode 100644
index 0000000..76e0c7e
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.outline.expect
@@ -0,0 +1,56 @@
+library;
+import self as self;
+
+import "dart:test";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@_in::patch
+class Class extends core::Object {
+  constructor _internal({core::bool value}) → self2::Class
+    ;
+  @_in::patch
+  external constructor patched() → self2::Class
+    ;
+  constructor unpatched() → self2::Class
+    ;
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _SubClass&Class&Mixin = self2::Class with self2::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor patched() → self2::_SubClass&Class&Mixin
+    : super self2::Class::patched()
+    ;
+  synthetic constructor unpatched() → self2::_SubClass&Class&Mixin
+    : super self2::Class::unpatched()
+    ;
+  synthetic constructor _internal({core::bool value}) → self2::_SubClass&Class&Mixin
+    : super self2::Class::_internal(value: value)
+    ;
+}
+@_in::patch
+class SubClass extends self2::_SubClass&Class&Mixin {
+  constructor _internal() → self2::SubClass
+    ;
+  @_in::patch
+  external constructor patched() → self2::SubClass
+    ;
+  constructor unpatched() → self2::SubClass
+    ;
+}
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:20 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:14:3 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:16:19 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 5, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.expect
new file mode 100644
index 0000000..4c4257a
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.expect
@@ -0,0 +1,71 @@
+library;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  new test::Class::patched();
+  new test::Class::unpatched();
+  new test::SubClass::patched();
+  new test::SubClass::unpatched();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/mixin_from_patch/origin_lib.dart:14:12: Error: The superclass, 'Class with Mixin', has no unnamed constructor that takes no arguments.
+//   external SubClass.patched();
+//            ^^^^^^^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  constructor _internal({core::bool value = #C2}) → test::Class
+    : super core::Object::•()
+    ;
+  @#C1
+  constructor patched() → test::Class
+    : this test::Class::_internal()
+    ;
+  constructor unpatched() → test::Class
+    : super core::Object::•()
+    ;
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _SubClass&Class&Mixin = test::Class with test::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor patched() → test::_SubClass&Class&Mixin
+    : super test::Class::patched()
+    ;
+  synthetic constructor unpatched() → test::_SubClass&Class&Mixin
+    : super test::Class::unpatched()
+    ;
+  synthetic constructor _internal({core::bool value = #C2}) → test::_SubClass&Class&Mixin
+    : super test::Class::_internal(value: value)
+    ;
+}
+@#C1
+class SubClass extends test::_SubClass&Class&Mixin {
+  constructor _internal() → test::SubClass
+    : super test::_SubClass&Class&Mixin::_internal(value: true)
+    ;
+  @#C1
+  constructor patched() → test::SubClass
+    : this test::SubClass::_internal()
+    ;
+  constructor unpatched() → test::SubClass
+    : super test::_SubClass&Class&Mixin::unpatched()
+    ;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..bacc201
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.strong.transformed.expect
@@ -0,0 +1,71 @@
+library;
+import self as self;
+import "dart:test" as test;
+
+import "dart:test";
+
+static method main() → dynamic {
+  new test::Class::patched();
+  new test::Class::unpatched();
+  new test::SubClass::patched();
+  new test::SubClass::unpatched();
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/mixin_from_patch/origin_lib.dart:14:12: Error: The superclass, 'Class with Mixin', has no unnamed constructor that takes no arguments.
+//   external SubClass.patched();
+//            ^^^^^^^
+//
+import self as test;
+import "dart:_internal" as _in;
+import "dart:core" as core;
+
+import "dart:_internal";
+
+@#C1
+class Class extends core::Object {
+  constructor _internal({core::bool value = #C2}) → test::Class
+    : super core::Object::•()
+    ;
+  @#C1
+  constructor patched() → test::Class
+    : this test::Class::_internal()
+    ;
+  constructor unpatched() → test::Class
+    : super core::Object::•()
+    ;
+}
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class _SubClass&Class&Mixin extends test::Class implements test::Mixin /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor patched() → test::_SubClass&Class&Mixin
+    : super test::Class::patched()
+    ;
+  synthetic constructor unpatched() → test::_SubClass&Class&Mixin
+    : super test::Class::unpatched()
+    ;
+  synthetic constructor _internal({core::bool value = #C2}) → test::_SubClass&Class&Mixin
+    : super test::Class::_internal(value: value)
+    ;
+}
+@#C1
+class SubClass extends test::_SubClass&Class&Mixin {
+  constructor _internal() → test::SubClass
+    : super test::_SubClass&Class&Mixin::_internal(value: true)
+    ;
+  @#C1
+  constructor patched() → test::SubClass
+    : this test::SubClass::_internal()
+    ;
+  constructor unpatched() → test::SubClass
+    : super test::_SubClass&Class&Mixin::unpatched()
+    ;
+}
+
+constants  {
+  #C1 = _in::_Patch {}
+  #C2 = false
+}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3c9c90e
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'dart:test';
+
+main() {}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/origin_lib.dart b/pkg/front_end/testcases/general/mixin_from_patch/origin_lib.dart
new file mode 100644
index 0000000..3a9ea31
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/origin_lib.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  external Class.patched();
+
+  Class.unpatched();
+}
+
+mixin Mixin {}
+
+class SubClass extends Class with Mixin {
+  external SubClass.patched();
+
+  SubClass.unpatched() : super.unpatched();
+}
diff --git a/pkg/front_end/testcases/general/mixin_from_patch/patch_lib.dart b/pkg/front_end/testcases/general/mixin_from_patch/patch_lib.dart
new file mode 100644
index 0000000..5eb5e41
--- /dev/null
+++ b/pkg/front_end/testcases/general/mixin_from_patch/patch_lib.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library
+import 'dart:_internal';
+
+@patch
+class Class {
+  Class._internal({bool value = false});
+
+  @patch
+  Class.patched() : this._internal();
+}
+
+@patch
+class SubClass {
+  SubClass._internal() : super._internal(value: true);
+
+  @patch
+  SubClass.patched() : this._internal();
+}
diff --git a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.outline.expect b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.outline.expect
index b7df28f..e77f24e 100644
--- a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.outline.expect
+++ b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.outline.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'B with C'.
 // mixin M on B, C {}
 //       ^^^^^^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.expect b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.expect
index 66fe78e..194538f 100644
--- a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.expect
+++ b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'B with C'.
 // mixin M on B, C {}
 //       ^^^^^^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.transformed.expect b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.transformed.expect
index 66fe78e..194538f 100644
--- a/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/mixin_interface_conflict.dart.strong.transformed.expect
@@ -6,10 +6,10 @@
 // Try adding a declaration of 'n' to 'B with C'.
 // mixin M on B, C {}
 //       ^^^^^^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:6:11: Context: This is one of the overridden members.
 //   int get n => 1;
 //           ^
-// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/mixin_interface_conflict.dart:10:14: Context: This is one of the overridden members.
 //   double get n => 2.0;
 //              ^
 //
diff --git a/pkg/front_end/testcases/general/native_as_name.dart.outline.expect b/pkg/front_end/testcases/general/native_as_name.dart.outline.expect
index 03096a5..27aedb4 100644
--- a/pkg/front_end/testcases/general/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/general/native_as_name.dart.outline.expect
@@ -74,3 +74,8 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///native_as_name.dart:26:4 -> InstanceConstant(const _Override{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
index f0a7f09..ab987d2 100644
--- a/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
+++ b/pkg/front_end/testcases/general/nested_implicit_const_with_env_var.dart.outline.expect
@@ -53,3 +53,8 @@
 static const field core::int* foo = const core::int::fromEnvironment("fisk");
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///nested_implicit_const_with_env_var.dart:5:23 -> IntConstant(0)
+Extra constant evaluation: evaluated: 3, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.outline.expect b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.outline.expect
index 3968a64..ac5db6a 100644
--- a/pkg/front_end/testcases/general/no_such_method_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/general/no_such_method_forwarder.dart.outline.expect
@@ -41,3 +41,15 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:6:8 -> SymbolConstant(#_foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:6:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:6:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:6:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:11:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:11:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:11:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_such_method_forwarder.dart:11:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 16, effectively constant: 8
diff --git a/pkg/front_end/testcases/general/no_such_method_private_setter.dart.outline.expect b/pkg/front_end/testcases/general/no_such_method_private_setter.dart.outline.expect
index 28f8656..14a8225 100644
--- a/pkg/front_end/testcases/general/no_such_method_private_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/general/no_such_method_private_setter.dart.outline.expect
@@ -47,3 +47,14 @@
 }
 static method baz(no_::Bar* bar) → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> SymbolConstant(#_x)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> SymbolConstant(#_x=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_such_method_private_setter_lib.dart:8:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
index 6c57b54..0f69d4e 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.expect
@@ -15,18 +15,22 @@
 //             ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   print(>foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:38:9: Error: Expected an identifier, but got '<='.
+// Try inserting an identifier before '<='.
 //   print(<=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:39:9: Error: Expected an identifier, but got '>='.
+// Try inserting an identifier before '>='.
 //   print(>=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:40:9: Error: Expected an identifier, but got '=='.
+// Try inserting an identifier before '=='.
 //   print(==foo);
 //         ^^
 //
@@ -36,38 +40,47 @@
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:42:9: Error: Expected an identifier, but got '/'.
+// Try inserting an identifier before '/'.
 //   print(/foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:43:9: Error: Expected an identifier, but got '~/'.
+// Try inserting an identifier before '~/'.
 //   print(~/foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:44:9: Error: Expected an identifier, but got '*'.
+// Try inserting an identifier before '*'.
 //   print(*foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:45:9: Error: Expected an identifier, but got '%'.
+// Try inserting an identifier before '%'.
 //   print(%foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:46:9: Error: Expected an identifier, but got '|'.
+// Try inserting an identifier before '|'.
 //   print(|foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:47:9: Error: Expected an identifier, but got '^'.
+// Try inserting an identifier before '^'.
 //   print(^foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:48:9: Error: Expected an identifier, but got '&'.
+// Try inserting an identifier before '&'.
 //   print(&foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:49:9: Error: Expected an identifier, but got '<<'.
+// Try inserting an identifier before '<<'.
 //   print(<<foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:50:9: Error: Expected an identifier, but got '>>'.
+// Try inserting an identifier before '>>'.
 //   print(>>foo);
 //         ^^
 //
diff --git a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
index 6c57b54..efc4e77 100644
--- a/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/operator_method_not_found.dart.strong.transformed.expect
@@ -15,18 +15,22 @@
 //             ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:37:9: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   print(>foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:38:9: Error: Expected an identifier, but got '<='.
+// Try inserting an identifier before '<='.
 //   print(<=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:39:9: Error: Expected an identifier, but got '>='.
+// Try inserting an identifier before '>='.
 //   print(>=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:40:9: Error: Expected an identifier, but got '=='.
+// Try inserting an identifier before '=='.
 //   print(==foo);
 //         ^^
 //
@@ -36,38 +40,47 @@
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:42:9: Error: Expected an identifier, but got '/'.
+// Try inserting an identifier before '/'.
 //   print(/foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:43:9: Error: Expected an identifier, but got '~/'.
+// Try inserting an identifier before '~/'.
 //   print(~/foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:44:9: Error: Expected an identifier, but got '*'.
+// Try inserting an identifier before '*'.
 //   print(*foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:45:9: Error: Expected an identifier, but got '%'.
+// Try inserting an identifier before '%'.
 //   print(%foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:46:9: Error: Expected an identifier, but got '|'.
+// Try inserting an identifier before '|'.
 //   print(|foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:47:9: Error: Expected an identifier, but got '^'.
+// Try inserting an identifier before '^'.
 //   print(^foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:48:9: Error: Expected an identifier, but got '&'.
+// Try inserting an identifier before '&'.
 //   print(&foo);
 //         ^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:49:9: Error: Expected an identifier, but got '<<'.
+// Try inserting an identifier before '<<'.
 //   print(<<foo);
 //         ^^
 //
 // pkg/front_end/testcases/general/operator_method_not_found.dart:50:9: Error: Expected an identifier, but got '>>'.
+// Try inserting an identifier before '>>'.
 //   print(>>foo);
 //         ^^
 //
@@ -352,3 +365,8 @@
   print(foo ~ 2);
             ^");
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///operator_method_not_found.dart:29:18 -> IntConstant(2)
+Extra constant evaluation: evaluated: 74, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/override_check_generic_method_f_bounded.dart.outline.expect b/pkg/front_end/testcases/general/override_check_generic_method_f_bounded.dart.outline.expect
index 896d6f1d..0242ff5 100644
--- a/pkg/front_end/testcases/general/override_check_generic_method_f_bounded.dart.outline.expect
+++ b/pkg/front_end/testcases/general/override_check_generic_method_f_bounded.dart.outline.expect
@@ -50,3 +50,8 @@
 }
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///override_check_generic_method_f_bounded.dart:15:4 -> InstanceConstant(const _Override{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart
index a943e3a..8035f1d 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart
@@ -51,10 +51,8 @@
 
   set setterFromSetter(value);
 
-  // TODO(johnniwinther): This should be an error.
   get getterFromSetter;
 
-  // TODO(johnniwinther): This should be an error.
   set setterFromGetter(value);
 
   get getterFromGetterWithSetterConflict;
@@ -81,10 +79,8 @@
 
   set setterFromSetter(value);
 
-  // TODO(johnniwinther): This should be an error.
   get getterFromSetter;
 
-  // TODO(johnniwinther): This should be an error.
   set setterFromGetter(value);
 
   get getterFromGetterWithSetterConflict;
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
index 8bdc4d8..c4a5102 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.outline.expect
@@ -2,50 +2,94 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -106,8 +150,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → core::num*;
-  abstract set setterFromGetter(core::num* value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
@@ -138,8 +182,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → dynamic;
-  abstract set setterFromGetter(dynamic value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
index 2e2d511..81942f2 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.expect
@@ -2,50 +2,94 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -110,8 +154,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → core::num*;
-  abstract set setterFromGetter(core::num* value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
@@ -144,8 +188,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → dynamic;
-  abstract set setterFromGetter(dynamic value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
diff --git a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
index 2e2d511..81942f2 100644
--- a/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart.strong.transformed.expect
@@ -2,50 +2,94 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:50:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:54:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:52:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:7: Error: Can't infer a return type for 'getterFromGetter' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:56:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:78:7: Error: Can't infer a return type for 'getterFromGetter' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get getterFromGetter;
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:6:11: Context: This is one of the overridden members.
 //   num get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:22:11: Context: This is one of the overridden members.
 //   int get getterFromGetter;
 //           ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:24: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:82:7: Error: Can't infer a return type for 'getterFromSetter' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   get getterFromSetter;
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:10:7: Context: This is one of the overridden members.
+//   set getterFromSetter(num value);
+//       ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:32:7: Context: This is one of the overridden members.
+//   set getterFromSetter(int value);
+//       ^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:80:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set setterFromSetter(value);
 //                        ^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:8:7: Context: This is one of the overridden members.
 //   set setterFromSetter(num value);
 //       ^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:24:7: Context: This is one of the overridden members.
 //   set setterFromSetter(int value);
 //       ^^^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:84:24: Error: Can't infer a type for 'value' as some of the overridden members have different types.
+// Try adding an explicit type.
+//   set setterFromGetter(value);
+//                        ^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:12:11: Context: This is one of the overridden members.
+//   num get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/general/override_inference_for_getters_and_setters.dart:26:11: Context: This is one of the overridden members.
+//   int get setterFromGetter;
+//           ^^^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -110,8 +154,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → core::num*;
-  abstract set setterFromGetter(core::num* value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
@@ -144,8 +188,8 @@
     ;
   abstract get getterFromGetter() → invalid-type;
   abstract set setterFromSetter(invalid-type value) → void;
-  abstract get getterFromSetter() → dynamic;
-  abstract set setterFromGetter(dynamic value) → void;
+  abstract get getterFromSetter() → invalid-type;
+  abstract set setterFromGetter(invalid-type value) → void;
   abstract get getterFromGetterWithSetterConflict() → core::num*;
   abstract set setterFromSetterWithGetterConflict(dynamic value) → void;
   abstract forwarding-stub get setterFromGetter() → core::int*;
diff --git a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
index 5565e30..a493720 100644
--- a/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
+++ b/pkg/front_end/testcases/general/platform_invalid_uris/main.dart.outline.expect
@@ -60,3 +60,9 @@
 
 library;
 import self as self6;
+
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/private_method_tearoff.dart.outline.expect b/pkg/front_end/testcases/general/private_method_tearoff.dart.outline.expect
index a58a056..095531c 100644
--- a/pkg/front_end/testcases/general/private_method_tearoff.dart.outline.expect
+++ b/pkg/front_end/testcases/general/private_method_tearoff.dart.outline.expect
@@ -50,3 +50,11 @@
 }
 static method baz(pri::Bar* bar) → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///private_method_tearoff_lib.dart:8:8 -> SymbolConstant(#_f)
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_method_tearoff_lib.dart:8:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_method_tearoff_lib.dart:8:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///private_method_tearoff_lib.dart:8:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
index 87f83fc..55876a5 100644
--- a/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/general/redirecting_factory_metadata.dart.outline.expect
@@ -25,3 +25,8 @@
 static const field core::int* anotherForParameter = 3;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///redirecting_factory_metadata.dart:13:4 -> IntConstant(2)
+Extra constant evaluation: evaluated: 5, effectively constant: 1
diff --git a/tests/kernel/unsorted/regression_flutter51828_test.dart b/pkg/front_end/testcases/general/regression_flutter51828.dart
similarity index 100%
rename from tests/kernel/unsorted/regression_flutter51828_test.dart
rename to pkg/front_end/testcases/general/regression_flutter51828.dart
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.outline.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.outline.expect
new file mode 100644
index 0000000..22ce718
--- /dev/null
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.outline.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    ;
+  method foo(dynamic x) → asy::Future<void>* async 
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    ;
+  method bar(dynamic x) → asy::Future<void>* async 
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic async 
+  ;
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.expect
new file mode 100644
index 0000000..f3a4286
--- /dev/null
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.expect
@@ -0,0 +1,39 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method foo(dynamic x) → asy::Future<void>* async {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  method bar(dynamic x) → asy::Future<void>* async {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic async 
+  return <asy::Future<void>*>[new self::A::•().{self::A::foo}(await null), new self::B::•().{self::B::bar}(await null)];
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect
new file mode 100644
index 0000000..c0ef0a7
--- /dev/null
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.strong.transformed.expect
@@ -0,0 +1,119 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+  method foo(dynamic x) → asy::Future<void>* /* originally async */ {
+    final asy::_AsyncAwaitCompleter<void>* :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
+    FutureOr<void>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+    core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L1:
+        {}
+        asy::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{asy::Completer::future};
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+  method bar(dynamic x) → asy::Future<void>* /* originally async */ {
+    final asy::_AsyncAwaitCompleter<void>* :async_completer = new asy::_AsyncAwaitCompleter::•<void>();
+    FutureOr<void>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+    core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L2:
+        {}
+        asy::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{asy::Completer::future};
+  }
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :async_temporary_0;
+  dynamic :async_temporary_1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        :async_temporary_1 = new self::A::•();
+        [yield] let dynamic #t1 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+        :async_temporary_1 = _in::unsafeCast<self::A*>(:async_temporary_1).{self::A::foo}(_in::unsafeCast<core::Null?>(:result));
+        :async_temporary_0 = new self::B::•();
+        [yield] let dynamic #t2 = asy::_awaitHelper(null, :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = <asy::Future<void>*>[_in::unsafeCast<asy::Future<void>*>(:async_temporary_1), _in::unsafeCast<self::B*>(:async_temporary_0).{self::B::bar}(_in::unsafeCast<core::Null?>(:result))];
+        break #L3;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline.expect
new file mode 100644
index 0000000..10f8088
--- /dev/null
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+class A {
+  Future<void> foo(x) async {}
+}
+
+class B {
+  Future<void> bar(x) async {}
+}
+
+main() async => [A().foo(await null), B().bar(await null)];
diff --git a/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..10f8088
--- /dev/null
+++ b/pkg/front_end/testcases/general/regression_flutter51828.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+class A {
+  Future<void> foo(x) async {}
+}
+
+class B {
+  Future<void> bar(x) async {}
+}
+
+main() async => [A().foo(await null), B().bar(await null)];
diff --git a/pkg/front_end/testcases/general/statements.dart b/pkg/front_end/testcases/general/statements.dart
index e5f79de..e12e2fc 100644
--- a/pkg/front_end/testcases/general/statements.dart
+++ b/pkg/front_end/testcases/general/statements.dart
@@ -10,8 +10,8 @@
   }
 }
 
-bar() async {
-  await for (var x in []) {
+bar(d) async* {
+  await for (var x in d) {
     yield x;
     yield* x;
   }
diff --git a/pkg/front_end/testcases/general/statements.dart.outline.expect b/pkg/front_end/testcases/general/statements.dart.outline.expect
index 1b94614..d66ca8e 100644
--- a/pkg/front_end/testcases/general/statements.dart.outline.expect
+++ b/pkg/front_end/testcases/general/statements.dart.outline.expect
@@ -3,7 +3,7 @@
 
 static method foo() → dynamic
   ;
-static method bar() → dynamic async 
+static method bar(dynamic d) → dynamic async* 
   ;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/general/statements.dart.strong.expect b/pkg/front_end/testcases/general/statements.dart.strong.expect
index e15d2a6..7e7194b 100644
--- a/pkg/front_end/testcases/general/statements.dart.strong.expect
+++ b/pkg/front_end/testcases/general/statements.dart.strong.expect
@@ -1,21 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general/statements.dart:15:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
-//     yield x;
-//     ^^^^^
-//
-// pkg/front_end/testcases/general/statements.dart:16:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
-//     yield* x;
-//     ^^^^^
-//
-// pkg/front_end/testcases/general/statements.dart:14:23: Error: The type 'List<dynamic>' used in the 'for' loop must implement 'Stream<dynamic>'.
-//  - 'List' is from 'dart:core'.
-//  - 'Stream' is from 'dart:async'.
-//   await for (var x in []) {
-//                       ^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
@@ -28,14 +11,10 @@
     core::print("Hello from finally block!");
   }
 }
-static method bar() → dynamic async {
-  await for (dynamic x in let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/statements.dart:14:23: Error: The type 'List<dynamic>' used in the 'for' loop must implement 'Stream<dynamic>'.
- - 'List' is from 'dart:core'.
- - 'Stream' is from 'dart:async'.
-  await for (var x in []) {
-                      ^" in <dynamic>[] as{TypeError} asy::Stream<dynamic>*) {
+static method bar(dynamic d) → dynamic async* {
+  await for (dynamic x in d as{TypeError,ForDynamic} asy::Stream<dynamic>*) {
     yield x;
-    yield* x;
+    yield* x as{TypeError,ForDynamic} asy::Stream<dynamic>*;
   }
 }
 static method main() → dynamic {
@@ -53,12 +32,12 @@
   for (core::String* s in <core::String*>["Hello from for-in without block!"])
     core::print(s);
   dynamic s;
-  for (final dynamic #t2 in <dynamic>["Hello from for-in without decl!"]) {
-    s = #t2;
+  for (final dynamic #t1 in <dynamic>["Hello from for-in without decl!"]) {
+    s = #t1;
     core::print(s);
   }
-  for (final dynamic #t3 in <dynamic>["Hello from for-in without decl and block!"]) {
-    s = #t3;
+  for (final dynamic #t2 in <dynamic>["Hello from for-in without decl and block!"]) {
+    s = #t2;
     core::print(s);
   }
   core::print("Hello from labeled statement!");
diff --git a/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect b/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect
new file mode 100644
index 0000000..7200685b
--- /dev/null
+++ b/pkg/front_end/testcases/general/statements.dart.strong.transformed.expect
@@ -0,0 +1,242 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+static method foo() → dynamic {
+  try {
+    return;
+  }
+  finally {
+    core::print("Hello from finally block!");
+  }
+}
+static method bar(dynamic d) → dynamic /* originally async* */ {
+  asy::_AsyncStarStreamController<dynamic>* :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :saved_try_context_var2;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L1:
+        {
+          {
+            asy::Stream<dynamic>* :stream = d as{TypeError,ForDynamic} asy::Stream<dynamic>*;
+            asy::_asyncStarListenHelper(:stream, :async_op);
+            asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
+            try
+              #L2:
+              while (true) {
+                dynamic #t1 = asy::_asyncStarMoveNextHelper(:stream);
+                [yield] let dynamic #t2 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
+                if(_in::unsafeCast<core::bool>(:result)) {
+                  dynamic x = :for-iterator.{asy::_StreamIterator::current};
+                  {
+                    if(:controller.{asy::_AsyncStarStreamController::add}(x))
+                      return null;
+                    else
+                      [yield] null;
+                    if(:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic} asy::Stream<dynamic>*))
+                      return null;
+                    else
+                      [yield] null;
+                  }
+                }
+                else
+                  break #L2;
+              }
+            finally
+              if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+                [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+                :result;
+              }
+          }
+        }
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<dynamic>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method main() → dynamic {
+  do {
+    core::print("Hello from do-while!");
+  }
+  while (false)
+  do {
+    void x = core::print("Hello from do-while!");
+  }
+  while (false)
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::String* s = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::print(s);
+      }
+    }
+  }
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in without block!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::String* s = :sync-for-iterator.{core::Iterator::current};
+      core::print(s);
+    }
+  }
+  dynamic s;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
+      {
+        s = #t4;
+        core::print(s);
+      }
+    }
+  }
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl and block!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
+      {
+        s = #t5;
+        core::print(s);
+      }
+    }
+  }
+  core::print("Hello from labeled statement!");
+  try {
+    try {
+      throw "Hello from rethrow!";
+    }
+    on dynamic catch(final dynamic e) {
+      rethrow;
+    }
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  self::foo();
+  core::bool* done = false;
+  while (!done) {
+    done = true;
+    core::print("Hello from while!");
+  }
+  ;
+  assert(true);
+  assert(true, "Hello from assert!");
+  try {
+    assert(false, "Hello from assert!");
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  #L3:
+  switch(1) {
+    #L4:
+    case #C1:
+    case #C2:
+      {
+        core::print("Hello from switch case!");
+        break #L3;
+      }
+    #L5:
+    default:
+      {
+        break #L3;
+      }
+  }
+  #L6:
+  switch(4) {
+    #L7:
+    case #C2:
+      {
+        core::print("Hello from case 2!");
+        break #L6;
+      }
+    #L8:
+    case #C1:
+      {
+        core::print("Hello from case 1!");
+        continue #L7;
+      }
+    #L9:
+    case #C3:
+      {
+        core::print("Hello from case 0!");
+        continue #L8;
+      }
+    #L10:
+    case #C4:
+      {
+        core::print("Hello from case 4!");
+        continue #L11;
+      }
+    #L11:
+    default:
+      {
+        continue #L9;
+      }
+  }
+  #L12:
+  switch(4) {
+    #L13:
+    case #C1:
+      {
+        core::print("Hello from next case 1");
+        break #L12;
+      }
+    #L14:
+    default:
+      {
+        continue #L13;
+      }
+  }
+  core::int* i = 0;
+  #L15:
+  do
+    #L16:
+    {
+      core::print("Hello from do-while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L16;
+      break #L15;
+    }
+  while (true)
+  i = 0;
+  #L17:
+  while (true)
+    #L18:
+    {
+      core::print("Hello from while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L18;
+      break #L17;
+    }
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+  #C4 = 4
+}
diff --git a/pkg/front_end/testcases/general/statements.dart.textual_outline.expect b/pkg/front_end/testcases/general/statements.dart.textual_outline.expect
index cec9847..2431514 100644
--- a/pkg/front_end/testcases/general/statements.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general/statements.dart.textual_outline.expect
@@ -1,3 +1,3 @@
 foo() {}
-bar() async {}
+bar(d) async* {}
 main() {}
diff --git a/pkg/front_end/testcases/general/statements.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/statements.dart.textual_outline_modelled.expect
index 6c4d710..3453492 100644
--- a/pkg/front_end/testcases/general/statements.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general/statements.dart.textual_outline_modelled.expect
@@ -1,3 +1,3 @@
-bar() async {}
+bar(d) async* {}
 foo() {}
 main() {}
diff --git a/pkg/front_end/testcases/general/super_nsm.dart.outline.expect b/pkg/front_end/testcases/general/super_nsm.dart.outline.expect
index a0a61fb..1e84833 100644
--- a/pkg/front_end/testcases/general/super_nsm.dart.outline.expect
+++ b/pkg/front_end/testcases/general/super_nsm.dart.outline.expect
@@ -44,3 +44,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///super_nsm.dart:6:3 -> SymbolConstant(#interfaceMethod)
+Evaluated: ListLiteral @ org-dartlang-testcase:///super_nsm.dart:6:3 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///super_nsm.dart:6:3 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///super_nsm.dart:6:3 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
index da86440..2add531 100644
--- a/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_literal_as_metadata.dart.outline.expect
@@ -43,3 +43,8 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literal_as_metadata.dart:9:2 -> TypeLiteralConstant(A*)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
index 1222789..020bf8e 100644
--- a/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_variable_uses.dart.strong.transformed.expect
@@ -112,3 +112,7 @@
   #C5 = <core::Object*>[#C4]
   #C6 = <core::Object*>[#C1]
 }
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_variable_uses.dart:8:11 -> TypeLiteralConstant(<invalid>)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/general/typedef.dart.strong.transformed.expect
index 979f6c8..c1747f2 100644
--- a/pkg/front_end/testcases/general/typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/typedef.dart.strong.transformed.expect
@@ -14,3 +14,9 @@
 constants  {
   #C1 = tearoff self::main
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:10:14 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:11:14 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:12:14 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 6, effectively constant: 3
diff --git a/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect b/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
index 6af752e..e79e5a8 100644
--- a/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/void_methods.dart.strong.transformed.expect
@@ -29,3 +29,8 @@
   new self::Foo::•().{self::Foo::[]=}(3, 4);
   new self::Foo::•().{self::Foo::clear}();
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///void_methods.dart:7:24 -> IntConstant(0)
+Extra constant evaluation: evaluated: 36, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
index 85c8784..bc603fc 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.outline.expect
@@ -18,6 +18,46 @@
 // class A<X extends int> {}
 //         ^
 //
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:12:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// extension E<X extends A<num>> // Error.
+//             ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:14:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   static A<num> fieldOfE; // Error.
+//                 ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:15:16: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num> fooOfE() => null; // Error.
+//                ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:16:22: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void barOfE(A<num> a) {} // Error.
+//                      ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:17:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void bazOfE<Y extends A<num>>() {} // Error.
+//               ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
index 87bc7b9..fa633e1b 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.expect
@@ -18,6 +18,46 @@
 // class A<X extends int> {}
 //         ^
 //
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:12:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// extension E<X extends A<num>> // Error.
+//             ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:14:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   static A<num> fieldOfE; // Error.
+//                 ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:15:16: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num> fooOfE() => null; // Error.
+//                ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:16:22: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void barOfE(A<num> a) {} // Error.
+//                      ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:17:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void bazOfE<Y extends A<num>>() {} // Error.
+//               ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
index 87bc7b9..fa633e1b 100644
--- a/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart.strong.transformed.expect
@@ -18,6 +18,46 @@
 // class A<X extends int> {}
 //         ^
 //
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:12:13: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+// extension E<X extends A<num>> // Error.
+//             ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:14:17: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   static A<num> fieldOfE; // Error.
+//                 ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:15:16: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A' in the return type.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num> fooOfE() => null; // Error.
+//                ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:16:22: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void barOfE(A<num> a) {} // Error.
+//                      ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:17:15: Error: Type argument 'num' doesn't conform to the bound 'int' of the type variable 'X' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   void bazOfE<Y extends A<num>>() {} // Error.
+//               ^
+// pkg/front_end/testcases/general/well_boundness_checks_in_outline.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends int> {}
+//         ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/const_lib.dart b/pkg/front_end/testcases/general/with_dependencies/issue43538/const_lib.dart
new file mode 100644
index 0000000..f1dbca9
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/const_lib.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  const A({
+    this.d = 3.14,
+    this.s = 'default',
+  });
+
+  final double d;
+  final String s;
+}
+
+class B extends A with M {
+  const B({double d = 2.71}) : super(d: d);
+}
+
+mixin M on A {
+  m1() {}
+}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart
new file mode 100644
index 0000000..a73de4b
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'const_lib.dart';
+
+const crossModule = B();
+
+main() {
+  expect(2.71, crossModule.d);
+  expect('default', crossModule.s);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.outline.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.outline.expect
new file mode 100644
index 0000000..a6664b4
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.outline.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "const_lib.dart" as con;
+
+import "org-dartlang-testcase:///const_lib.dart";
+
+static const field con::B* crossModule = const con::B::•();
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+library;
+import self as con;
+import "dart:core" as core;
+
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  final field core::double* d;
+  final field core::String* s;
+  const constructor •({core::double* d = #C1, core::String* s = #C2}) → con::A*
+    : con::A::d = d, con::A::s = s, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _B&A&M extends con::A implements con::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •({core::double* d = #C1, core::String* s = #C2}) → con::_B&A&M*
+    : super con::A::•(d: d, s: s)
+    ;
+  method m1() → dynamic
+    ;
+}
+class B extends con::_B&A&M /*hasConstConstructor*/  {
+  const constructor •({core::double* d = #C3}) → con::B*
+    : super con::_B&A&M::•(d: d)
+    ;
+}
+abstract class M extends con::A /*isMixinDeclaration*/  {
+  method m1() → dynamic
+    ;
+}
+
+constants  {
+  #C1 = 3.14
+  #C2 = "default"
+  #C3 = 2.71
+}
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///main.dart:7:21 -> InstanceConstant(const B{A.d: 2.71, A.s: "default"})
+Extra constant evaluation: evaluated: 6, effectively constant: 1
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect
new file mode 100644
index 0000000..6100074
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "const_lib.dart" as con;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///const_lib.dart";
+
+static const field con::B* crossModule = #C3;
+static method main() → dynamic {
+  self::expect(2.71, (#C3).{con::A::d});
+  self::expect("default", (#C3).{con::A::s});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as con;
+import "dart:core" as core;
+
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  final field core::double* d;
+  final field core::String* s;
+  const constructor •({core::double* d = #C4, core::String* s = #C2}) → con::A*
+    : con::A::d = d, con::A::s = s, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _B&A&M extends con::A implements con::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •({core::double* d = #C4, core::String* s = #C2}) → con::_B&A&M*
+    : super con::A::•(d: d, s: s)
+    ;
+  method m1() → dynamic {}
+}
+class B extends con::_B&A&M /*hasConstConstructor*/  {
+  const constructor •({core::double* d = #C1}) → con::B*
+    : super con::_B&A&M::•(d: d)
+    ;
+}
+abstract class M extends con::A /*isMixinDeclaration*/  {
+  method m1() → dynamic {}
+}
+
+constants  {
+  #C1 = 2.71
+  #C2 = "default"
+  #C3 = con::B {d:#C1, s:#C2}
+  #C4 = 3.14
+}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect
new file mode 100644
index 0000000..6100074
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.strong.transformed.expect
@@ -0,0 +1,59 @@
+library;
+import self as self;
+import "const_lib.dart" as con;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///const_lib.dart";
+
+static const field con::B* crossModule = #C3;
+static method main() → dynamic {
+  self::expect(2.71, (#C3).{con::A::d});
+  self::expect("default", (#C3).{con::A::s});
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library;
+import self as con;
+import "dart:core" as core;
+
+abstract class A extends core::Object /*hasConstConstructor*/  {
+  final field core::double* d;
+  final field core::String* s;
+  const constructor •({core::double* d = #C4, core::String* s = #C2}) → con::A*
+    : con::A::d = d, con::A::s = s, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+abstract class _B&A&M extends con::A implements con::M /*isAnonymousMixin,isEliminatedMixin,hasConstConstructor*/  {
+  const synthetic constructor •({core::double* d = #C4, core::String* s = #C2}) → con::_B&A&M*
+    : super con::A::•(d: d, s: s)
+    ;
+  method m1() → dynamic {}
+}
+class B extends con::_B&A&M /*hasConstConstructor*/  {
+  const constructor •({core::double* d = #C1}) → con::B*
+    : super con::_B&A&M::•(d: d)
+    ;
+}
+abstract class M extends con::A /*isMixinDeclaration*/  {
+  method m1() → dynamic {}
+}
+
+constants  {
+  #C1 = 2.71
+  #C2 = "default"
+  #C3 = con::B {d:#C1, s:#C2}
+  #C4 = 3.14
+}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline.expect
new file mode 100644
index 0000000..d57e7dc
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+import 'const_lib.dart';
+
+const crossModule = B();
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..63f830f
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+import 'const_lib.dart';
+
+const crossModule = B();
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/general/with_dependencies/issue43538/test.options b/pkg/front_end/testcases/general/with_dependencies/issue43538/test.options
new file mode 100644
index 0000000..6c5423c
--- /dev/null
+++ b/pkg/front_end/testcases/general/with_dependencies/issue43538/test.options
@@ -0,0 +1 @@
+const_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
index 663835f..749e9d0 100644
--- a/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/with_dependencies/variance_from_dill/variance_from_dill.dart.strong.transformed.expect
@@ -14,3 +14,8 @@
 import "dart:core" as core;
 
 typedef F<unrelated T extends core::Object* = dynamic> = () →* dynamic;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///variance_from_dill.dart:5:9 -> TypeLiteralConstant(dynamic Function(dynamic Function()*)*)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
index 60d3c9e..742c6ea 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.expect
@@ -31,7 +31,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
index 60d3c9e..742c6ea 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/annotation_on_enum_values.dart.weak.transformed.expect
@@ -31,7 +31,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
index e7f6876..5d13162 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/bug33099.dart.weak.transformed.expect
@@ -84,3 +84,7 @@
   #C1 = self::_FailingTest {}
   #C2 = #foo
 }
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///bug33099.dart:23:42 -> TypeLiteralConstant(MyTest2*)
+Extra constant evaluation: evaluated: 33, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/casts.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/casts.dart.weak.transformed.expect
index 4ea32aa..28908ee 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/casts.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/casts.dart.weak.transformed.expect
@@ -16,3 +16,16 @@
   core::print(1.0 is core::int*);
   core::print(1.0 is core::double*);
 }
+
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:12:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:13:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:14:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:16:11 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:17:11 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:18:11 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:20:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:21:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///casts.dart:22:13 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 21, effectively constant: 9
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
index 992e106..156d0a6 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/check_deferred_read_type.dart.weak.transformed.expect
@@ -35,3 +35,8 @@
 static field core::int* x = 0;
 static method m(dynamic x) → dynamic
   return null;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///check_deferred_read_type.dart:11:13 -> TypeLiteralConstant(C*)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
index 8b4a395..e189517 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.expect
@@ -3,26 +3,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:24:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:48:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm1<Z> = Object with Am1<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:79:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:107:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm2<Z> = Object with Am2<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:136:28: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // typedef TdF = Function({int});
 //                            ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:192:34: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Ef1<X extends Function({int})> {
 //                                  ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
index 511e518..02dce8f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart.weak.transformed.expect
@@ -3,26 +3,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:24:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm1<Z> extends Object with Am1<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:48:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm1<Z> = Object with Am1<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:79:51: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Fm2<Z> extends Object with Am2<Function({int}), Z> {}
 //                                                   ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:107:45: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Qm2<Z> = Object with Am2<Function({int}), Z>;
 //                                             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:136:28: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // typedef TdF = Function({int});
 //                            ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/clone_function_type.dart:192:34: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class Ef1<X extends Function({int})> {
 //                                  ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/compound_binary_implicit_as.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/compound_binary_implicit_as.dart.weak.transformed.expect
index c425212..ded690f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/compound_binary_implicit_as.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/compound_binary_implicit_as.dart.weak.transformed.expect
@@ -38,3 +38,9 @@
   on dynamic catch(final dynamic _) {
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///compound_binary_implicit_as.dart:18:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///compound_binary_implicit_as.dart:18:9 -> IntConstant(0)
+Extra constant evaluation: evaluated: 16, effectively constant: 2
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
index a4cb425..fa89fde 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/control_flow_collection.dart.weak.transformed.expect
@@ -100,3 +100,11 @@
 }
 static method oracle() → dynamic
   return true;
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:11:26 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:20:26 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:29:29 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///control_flow_collection.dart:29:33 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 160, effectively constant: 4
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_generic.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_generic.dart.weak.transformed.expect
index 7c34544..5707da5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/covariant_generic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/covariant_generic.dart.weak.transformed.expect
@@ -47,3 +47,9 @@
   let final self::Foo<core::num*>* #t3 = fooNum in let final core::double* #t4 = 2.5 in (#t3.{self::Foo::mutableCallbackField} as{TypeError,CovarianceCheck} (core::num*) →* void).call(#t4);
   fooNum.{self::Foo::mutableCallbackField} = (core::num* x) → core::Null? {};
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///covariant_generic.dart:45:31 -> IntConstant(3)
+Evaluated: VariableGet @ org-dartlang-testcase:///covariant_generic.dart:46:31 -> DoubleConstant(2.5)
+Extra constant evaluation: evaluated: 58, effectively constant: 2
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
index 877eeef..d6ea288 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/duplicated_declarations.dart.weak.expect
@@ -490,7 +490,7 @@
     : self::Enum#4::index = index, self::Enum#4::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#4::_name};
+    return this.{self::Enum#4::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -512,7 +512,7 @@
     : self::Enum#3::index = index, self::Enum#3::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#3::_name};
+    return this.{self::Enum#3::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -534,7 +534,7 @@
     : self::Enum#2::index = index, self::Enum#2::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#2::_name};
+    return this.{self::Enum#2::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -556,7 +556,7 @@
     : self::Enum#1::index = index, self::Enum#1::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum#1::_name};
+    return this.{self::Enum#1::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -578,7 +578,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -600,7 +600,7 @@
     : self::AnotherEnum::index = index, self::AnotherEnum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::AnotherEnum::_name};
+    return this.{self::AnotherEnum::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
index dcb5fa0..01eb26d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib2.dart:10:9: Error: Constant evaluation error:
-//   const Foo(0);
-//         ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_01_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib2.dart:10:9: Error: Constant evaluation error:
+//   const Foo(0);
+//         ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 
 import "org-dartlang-testcase:///error_location_01_lib1.dart";
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
index dcb5fa0..01eb26d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01.dart.weak.transformed.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib2.dart:10:9: Error: Constant evaluation error:
-//   const Foo(0);
-//         ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_01_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib2.dart:10:9: Error: Constant evaluation error:
+//   const Foo(0);
+//         ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_01_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 
 import "org-dartlang-testcase:///error_location_01_lib1.dart";
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
index e9d28b1..323bb1d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:19: Error: Constant evaluation error:
-// const fooField2 = fooField;
-//                   ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:7: Context: While analyzing:
-// const fooField2 = fooField;
-//       ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_02_lib1.dart" as err;
@@ -59,6 +36,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_02_lib1.dart" as err;
 
@@ -67,6 +57,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:19: Error: Constant evaluation error:
+// const fooField2 = fooField;
+//                   ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:7: Context: While analyzing:
+// const fooField2 = fooField;
+//       ^
+//
 import self as self3;
 import "error_location_02_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
index e9d28b1..323bb1d 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02.dart.weak.transformed.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:19: Error: Constant evaluation error:
-// const fooField2 = fooField;
-//                   ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:7: Context: While analyzing:
-// const fooField2 = fooField;
-//       ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_02_lib1.dart" as err;
@@ -59,6 +36,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib2.dart:9:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_02_lib1.dart" as err;
 
@@ -67,6 +57,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:19: Error: Constant evaluation error:
+// const fooField2 = fooField;
+//                   ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_02_lib3.dart:9:7: Context: While analyzing:
+// const fooField2 = fooField;
+//       ^
+//
 import self as self3;
 import "error_location_02_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
index f9e1e20..e0eca30 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:25: Error: Constant evaluation error:
-// const fooField2 = const Foo(0);
-//                         ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:7: Context: While analyzing:
-// const fooField2 = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_03_lib1.dart" as err;
@@ -60,6 +37,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_03_lib1.dart" as err;
 
@@ -68,6 +58,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 import self as self3;
 import "error_location_03_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
index f9e1e20..e0eca30 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03.dart.weak.transformed.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:24: Error: Constant evaluation error:
-// const fooField = const Foo(0);
-//                        ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:7: Context: While analyzing:
-// const fooField = const Foo(0);
-//       ^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:25: Error: Constant evaluation error:
-// const fooField2 = const Foo(0);
-//                         ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:7: Context: While analyzing:
-// const fooField2 = const Foo(0);
-//       ^
-//
 library;
 import self as self;
 import "error_location_03_lib1.dart" as err;
@@ -60,6 +37,19 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib2.dart:9:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 import self as self2;
 import "error_location_03_lib1.dart" as err;
 
@@ -68,6 +58,19 @@
 static const field err::Foo* fooField = invalid-expression "This assertion failed.";
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_03_lib3.dart:9:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 import self as self3;
 import "error_location_03_lib1.dart" as err;
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
index 558b630..eaf451a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib2.dart:11:27: Error: Constant evaluation error:
-//   const Bar() : x = const Foo(0);
-//                           ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_04_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib2.dart:11:27: Error: Constant evaluation error:
+//   const Bar() : x = const Foo(0);
+//                           ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 import "dart:core" as core;
 import "error_location_04_lib1.dart" as err;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
index 558b630..eaf451a 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04.dart.weak.transformed.expect
@@ -1,13 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib2.dart:11:27: Error: Constant evaluation error:
-//   const Bar() : x = const Foo(0);
-//                           ^
-// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib1.dart:8:31: Context: This assertion failed.
-//   const Foo(int i) : assert(i > 0);
-//                               ^
-//
 library;
 import self as self;
 import "error_location_04_lib1.dart" as err;
@@ -45,6 +35,16 @@
 }
 
 library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib2.dart:11:27: Error: Constant evaluation error:
+//   const Bar() : x = const Foo(0);
+//                           ^
+// pkg/front_end/testcases/general_nnbd_opt_out/error_locations/error_location_04_lib1.dart:8:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 import self as err2;
 import "dart:core" as core;
 import "error_location_04_lib1.dart" as err;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
index 8dbe328..405fb55 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/export_test.dart.weak.transformed.expect
@@ -10,3 +10,8 @@
 static method main() → dynamic {
   core::print(dev::UserTag*);
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///export_test.dart:16:9 -> TypeLiteralConstant(UserTag*)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
index 7e9b65e..4796426 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/expressions.dart.weak.transformed.expect
@@ -93,3 +93,12 @@
   #C1 = null
   #C2 = core::Object {}
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///expressions.dart:23:8 -> StringConstant("foobar")
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:72:10 -> TypeLiteralConstant(int*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:73:9 -> TypeLiteralConstant(int*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
+Evaluated: VariableGetImpl @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
+Evaluated: VariableGet @ org-dartlang-testcase:///expressions.dart:74:9 -> TypeLiteralConstant(int*)
+Extra constant evaluation: evaluated: 138, effectively constant: 6
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
index 97266d3..c402dca 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/ffi_sample.dart.weak.transformed.expect
@@ -44,7 +44,7 @@
   get next() → ffi::Pointer<self::Coordinate*>*
     return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi())));
   set next(ffi::Pointer<self::Coordinate*>* #v) → void
-    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi()), #v.{=ffi::Pointer::address});
+    return ffi::_storeIntPtr(this.{ffi::Struct::_addressOf}, (#C12).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address});
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.expect
index 6320f0f..158f177 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart:34:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.superInstanceField in []) {}
 //          ^^^^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart:35:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.untypedSuperInstanceField in []) {}
 //          ^^^^^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
index ac8efc4..7eb73d5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart.weak.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart:34:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.superInstanceField in []) {}
 //          ^^^^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/for_in_without_declaration.dart:35:10: Error: Expected an identifier, but got 'super'.
+// Try inserting an identifier before 'super'.
 //     for (super.untypedSuperInstanceField in []) {}
 //          ^^^^^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.expect
index c6f2e39..67a7869 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart:7:19: Error: Expected an identifier, but got ':'.
+// Try inserting an identifier before ':'.
 // void Function({obj: Object}) x;
 //                   ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.transformed.expect
index c6f2e39..67a7869 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart.weak.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/function_type_default_value.dart:7:19: Error: Expected an identifier, but got ':'.
+// Try inserting an identifier before ':'.
 // void Function({obj: Object}) x;
 //                   ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.weak.transformed.expect
index f041292..b63a7e4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/implicit_scope_test.dart.weak.transformed.expect
@@ -57,3 +57,9 @@
 static method main() → dynamic {
   self::ImplicitScopeTest::testMain();
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_scope_test.dart:14:18 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///implicit_scope_test.dart:35:49 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 28, effectively constant: 2
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.expect
index 120c7e3..4f7c820 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.expect
@@ -7,10 +7,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.a(this);
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.b(this.);
 //            ^
 //
@@ -19,10 +21,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:10:11: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.c(this, p);
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:11:12: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.d(this., p);
 //            ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.transformed.expect
index 120c7e3..4f7c820 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart.weak.transformed.expect
@@ -7,10 +7,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:8:11: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.a(this);
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:9:12: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   C.b(this.);
 //            ^
 //
@@ -19,10 +21,12 @@
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:10:11: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.c(this, p);
 //           ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/incomplete_field_formal_parameter.dart:11:12: Error: Expected an identifier, but got ','.
+// Try inserting an identifier before ','.
 //   C.d(this., p);
 //            ^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_type.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_type.dart.weak.transformed.expect
index 383580e..a287469 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/invalid_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/invalid_type.dart.weak.transformed.expect
@@ -46,3 +46,8 @@
        ^^^";
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: AsExpression @ org-dartlang-testcase:///invalid_type.dart:14:9 -> NullConstant(null)
+Extra constant evaluation: evaluated: 3, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
index ce8e878..ab4a00c 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/magic_const.dart.weak.transformed.expect
@@ -69,3 +69,7 @@
 constants  {
   #C1 = self::Constant {}
 }
+
+Extra constant evaluation status:
+Evaluated: FactoryConstructorInvocationJudgment @ org-dartlang-testcase:///magic_const.dart:23:8 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
index 0c71aa0..b5f94c3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.expect
@@ -14,7 +14,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
index 0c71aa0..b5f94c3 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/metadata_enum.dart.weak.transformed.expect
@@ -14,7 +14,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
index d2f6483..88f46a2 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/minimum_int.dart.weak.transformed.expect
@@ -4,3 +4,8 @@
 
 static method main() → dynamic
   return core::print(-9223372036854775808.{core::int::unary-}());
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///minimum_int.dart:1:17 -> IntConstant(-9223372036854775808)
+Extra constant evaluation: evaluated: 2, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/missing_toplevel.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/missing_toplevel.dart.weak.transformed.expect
index 725a362..20f40c5 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/missing_toplevel.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/missing_toplevel.dart.weak.transformed.expect
@@ -129,3 +129,12 @@
 var missingPropertySet = emptyClass.property = 42;
                                     ^^^^^^^^";
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:30:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:30:48 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:30:48 -> IntConstant(2)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:31:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///missing_toplevel.dart:31:48 -> IntConstant(2)
+Extra constant evaluation: evaluated: 37, effectively constant: 5
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
index 1edf01c..b2d2a0f 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart:11:15: Error: Constant evaluation error:
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
@@ -11,7 +12,6 @@
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
 //            ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
index 363663f..d0d4423 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/mixin_constructors_with_default_values.dart:11:15: Error: Constant evaluation error:
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
@@ -11,7 +12,6 @@
 //   C({a: 0, b: T}) : trace = "a: $a, b: $b";
 //            ^
 //
-library;
 import self as self;
 import "dart:core" as core;
 import "package:expect/expect.dart" as exp;
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.expect
index 9099bb0..6717947 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.expect
@@ -15,18 +15,22 @@
 //             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:39:9: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   print(>foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:40:9: Error: Expected an identifier, but got '<='.
+// Try inserting an identifier before '<='.
 //   print(<=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:41:9: Error: Expected an identifier, but got '>='.
+// Try inserting an identifier before '>='.
 //   print(>=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:42:9: Error: Expected an identifier, but got '=='.
+// Try inserting an identifier before '=='.
 //   print(==foo);
 //         ^^
 //
@@ -36,38 +40,47 @@
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:44:9: Error: Expected an identifier, but got '/'.
+// Try inserting an identifier before '/'.
 //   print(/foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:45:9: Error: Expected an identifier, but got '~/'.
+// Try inserting an identifier before '~/'.
 //   print(~/foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:46:9: Error: Expected an identifier, but got '*'.
+// Try inserting an identifier before '*'.
 //   print(*foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:47:9: Error: Expected an identifier, but got '%'.
+// Try inserting an identifier before '%'.
 //   print(%foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:48:9: Error: Expected an identifier, but got '|'.
+// Try inserting an identifier before '|'.
 //   print(|foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:49:9: Error: Expected an identifier, but got '^'.
+// Try inserting an identifier before '^'.
 //   print(^foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:50:9: Error: Expected an identifier, but got '&'.
+// Try inserting an identifier before '&'.
 //   print(&foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:51:9: Error: Expected an identifier, but got '<<'.
+// Try inserting an identifier before '<<'.
 //   print(<<foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:52:9: Error: Expected an identifier, but got '>>'.
+// Try inserting an identifier before '>>'.
 //   print(>>foo);
 //         ^^
 //
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
index 9099bb0..715890e 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart.weak.transformed.expect
@@ -15,18 +15,22 @@
 //             ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:39:9: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   print(>foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:40:9: Error: Expected an identifier, but got '<='.
+// Try inserting an identifier before '<='.
 //   print(<=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:41:9: Error: Expected an identifier, but got '>='.
+// Try inserting an identifier before '>='.
 //   print(>=foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:42:9: Error: Expected an identifier, but got '=='.
+// Try inserting an identifier before '=='.
 //   print(==foo);
 //         ^^
 //
@@ -36,38 +40,47 @@
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:44:9: Error: Expected an identifier, but got '/'.
+// Try inserting an identifier before '/'.
 //   print(/foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:45:9: Error: Expected an identifier, but got '~/'.
+// Try inserting an identifier before '~/'.
 //   print(~/foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:46:9: Error: Expected an identifier, but got '*'.
+// Try inserting an identifier before '*'.
 //   print(*foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:47:9: Error: Expected an identifier, but got '%'.
+// Try inserting an identifier before '%'.
 //   print(%foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:48:9: Error: Expected an identifier, but got '|'.
+// Try inserting an identifier before '|'.
 //   print(|foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:49:9: Error: Expected an identifier, but got '^'.
+// Try inserting an identifier before '^'.
 //   print(^foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:50:9: Error: Expected an identifier, but got '&'.
+// Try inserting an identifier before '&'.
 //   print(&foo);
 //         ^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:51:9: Error: Expected an identifier, but got '<<'.
+// Try inserting an identifier before '<<'.
 //   print(<<foo);
 //         ^^
 //
 // pkg/front_end/testcases/general_nnbd_opt_out/operator_method_not_found.dart:52:9: Error: Expected an identifier, but got '>>'.
+// Try inserting an identifier before '>>'.
 //   print(>>foo);
 //         ^^
 //
@@ -352,3 +365,8 @@
   print(foo ~ 2);
             ^");
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///operator_method_not_found.dart:31:18 -> IntConstant(2)
+Extra constant evaluation: evaluated: 74, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart
index 57afbf8..a0ce9703 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart
@@ -12,8 +12,8 @@
   }
 }
 
-bar() async {
-  await for (var x in []) {
+bar(d) async* {
+  await for (var x in d) {
     yield x;
     yield* x;
   }
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline.expect b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline.expect
index 43f51e0..2d96fe8 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline.expect
@@ -1,4 +1,4 @@
 // @dart = 2.6
 foo() {}
-bar() async {}
+bar(d) async* {}
 main() {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline_modelled.expect
index 8532037..04d19df 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.textual_outline_modelled.expect
@@ -1,4 +1,4 @@
 // @dart = 2.6
-bar() async {}
+bar(d) async* {}
 foo() {}
 main() {}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.expect b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.expect
index 4059d89..7e7194b 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.expect
@@ -1,21 +1,4 @@
 library;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/statements.dart:17:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
-//     yield x;
-//     ^^^^^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/statements.dart:18:5: Error: 'yield' can only be used in 'sync*' or 'async*' methods.
-//     yield* x;
-//     ^^^^^
-//
-// pkg/front_end/testcases/general_nnbd_opt_out/statements.dart:16:23: Error: The type 'List<dynamic>' used in the 'for' loop must implement 'Stream<dynamic>'.
-//  - 'List' is from 'dart:core'.
-//  - 'Stream' is from 'dart:async'.
-//   await for (var x in []) {
-//                       ^
-//
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
@@ -28,14 +11,10 @@
     core::print("Hello from finally block!");
   }
 }
-static method bar() → dynamic async {
-  await for (dynamic x in let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general_nnbd_opt_out/statements.dart:16:23: Error: The type 'List<dynamic>' used in the 'for' loop must implement 'Stream<dynamic>'.
- - 'List' is from 'dart:core'.
- - 'Stream' is from 'dart:async'.
-  await for (var x in []) {
-                      ^" in <dynamic>[] as{TypeError} asy::Stream<dynamic>*) {
+static method bar(dynamic d) → dynamic async* {
+  await for (dynamic x in d as{TypeError,ForDynamic} asy::Stream<dynamic>*) {
     yield x;
-    yield* x;
+    yield* x as{TypeError,ForDynamic} asy::Stream<dynamic>*;
   }
 }
 static method main() → dynamic {
@@ -53,12 +32,12 @@
   for (core::String* s in <core::String*>["Hello from for-in without block!"])
     core::print(s);
   dynamic s;
-  for (final dynamic #t2 in <dynamic>["Hello from for-in without decl!"]) {
-    s = #t2;
+  for (final dynamic #t1 in <dynamic>["Hello from for-in without decl!"]) {
+    s = #t1;
     core::print(s);
   }
-  for (final dynamic #t3 in <dynamic>["Hello from for-in without decl and block!"]) {
-    s = #t3;
+  for (final dynamic #t2 in <dynamic>["Hello from for-in without decl and block!"]) {
+    s = #t2;
     core::print(s);
   }
   core::print("Hello from labeled statement!");
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect
new file mode 100644
index 0000000..7200685b
--- /dev/null
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/statements.dart.weak.transformed.expect
@@ -0,0 +1,242 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+static method foo() → dynamic {
+  try {
+    return;
+  }
+  finally {
+    core::print("Hello from finally block!");
+  }
+}
+static method bar(dynamic d) → dynamic /* originally async* */ {
+  asy::_AsyncStarStreamController<dynamic>* :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :saved_try_context_var2;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L1:
+        {
+          {
+            asy::Stream<dynamic>* :stream = d as{TypeError,ForDynamic} asy::Stream<dynamic>*;
+            asy::_asyncStarListenHelper(:stream, :async_op);
+            asy::_StreamIterator<dynamic>* :for-iterator = new asy::_StreamIterator::•<dynamic>(:stream);
+            try
+              #L2:
+              while (true) {
+                dynamic #t1 = asy::_asyncStarMoveNextHelper(:stream);
+                [yield] let dynamic #t2 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
+                if(_in::unsafeCast<core::bool>(:result)) {
+                  dynamic x = :for-iterator.{asy::_StreamIterator::current};
+                  {
+                    if(:controller.{asy::_AsyncStarStreamController::add}(x))
+                      return null;
+                    else
+                      [yield] null;
+                    if(:controller.{asy::_AsyncStarStreamController::addStream}(x as{TypeError,ForDynamic} asy::Stream<dynamic>*))
+                      return null;
+                    else
+                      [yield] null;
+                  }
+                }
+                else
+                  break #L2;
+              }
+            finally
+              if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+                [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+                :result;
+              }
+          }
+        }
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<dynamic>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method main() → dynamic {
+  do {
+    core::print("Hello from do-while!");
+  }
+  while (false)
+  do {
+    void x = core::print("Hello from do-while!");
+  }
+  while (false)
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::String* s = :sync-for-iterator.{core::Iterator::current};
+      {
+        core::print(s);
+      }
+    }
+  }
+  {
+    core::Iterator<core::String*>* :sync-for-iterator = <core::String*>["Hello from for-in without block!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      core::String* s = :sync-for-iterator.{core::Iterator::current};
+      core::print(s);
+    }
+  }
+  dynamic s;
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t4 = :sync-for-iterator.{core::Iterator::current};
+      {
+        s = #t4;
+        core::print(s);
+      }
+    }
+  }
+  {
+    core::Iterator<dynamic>* :sync-for-iterator = <dynamic>["Hello from for-in without decl and block!"].{core::Iterable::iterator};
+    for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      final dynamic #t5 = :sync-for-iterator.{core::Iterator::current};
+      {
+        s = #t5;
+        core::print(s);
+      }
+    }
+  }
+  core::print("Hello from labeled statement!");
+  try {
+    try {
+      throw "Hello from rethrow!";
+    }
+    on dynamic catch(final dynamic e) {
+      rethrow;
+    }
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  self::foo();
+  core::bool* done = false;
+  while (!done) {
+    done = true;
+    core::print("Hello from while!");
+  }
+  ;
+  assert(true);
+  assert(true, "Hello from assert!");
+  try {
+    assert(false, "Hello from assert!");
+  }
+  on dynamic catch(final dynamic e) {
+    core::print(e);
+  }
+  #L3:
+  switch(1) {
+    #L4:
+    case #C1:
+    case #C2:
+      {
+        core::print("Hello from switch case!");
+        break #L3;
+      }
+    #L5:
+    default:
+      {
+        break #L3;
+      }
+  }
+  #L6:
+  switch(4) {
+    #L7:
+    case #C2:
+      {
+        core::print("Hello from case 2!");
+        break #L6;
+      }
+    #L8:
+    case #C1:
+      {
+        core::print("Hello from case 1!");
+        continue #L7;
+      }
+    #L9:
+    case #C3:
+      {
+        core::print("Hello from case 0!");
+        continue #L8;
+      }
+    #L10:
+    case #C4:
+      {
+        core::print("Hello from case 4!");
+        continue #L11;
+      }
+    #L11:
+    default:
+      {
+        continue #L9;
+      }
+  }
+  #L12:
+  switch(4) {
+    #L13:
+    case #C1:
+      {
+        core::print("Hello from next case 1");
+        break #L12;
+      }
+    #L14:
+    default:
+      {
+        continue #L13;
+      }
+  }
+  core::int* i = 0;
+  #L15:
+  do
+    #L16:
+    {
+      core::print("Hello from do-while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L16;
+      break #L15;
+    }
+  while (true)
+  i = 0;
+  #L17:
+  while (true)
+    #L18:
+    {
+      core::print("Hello from while!");
+      if((i = i.{core::num::+}(1)).{core::num::<}(3))
+        break #L18;
+      break #L17;
+    }
+}
+
+constants  {
+  #C1 = 1
+  #C2 = 2
+  #C3 = 0
+  #C4 = 4
+}
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
index 3f3a1f0..8deddad 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/type_variable_uses.dart.weak.transformed.expect
@@ -112,3 +112,7 @@
   #C5 = <core::Object*>[#C4]
   #C6 = <core::Object*>[#C1]
 }
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_variable_uses.dart:10:11 -> TypeLiteralConstant(<invalid>)
+Extra constant evaluation: evaluated: 4, effectively constant: 1
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/typedef.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/typedef.dart.weak.transformed.expect
index 979f6c8..6176ac4 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/typedef.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/typedef.dart.weak.transformed.expect
@@ -14,3 +14,9 @@
 constants  {
   #C1 = tearoff self::main
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:12:14 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:13:14 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///typedef.dart:14:14 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 6, effectively constant: 3
diff --git a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
index 6af752e..9358d88 100644
--- a/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general_nnbd_opt_out/void_methods.dart.weak.transformed.expect
@@ -29,3 +29,8 @@
   new self::Foo::•().{self::Foo::[]=}(3, 4);
   new self::Foo::•().{self::Foo::clear}();
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///void_methods.dart:9:24 -> IntConstant(0)
+Extra constant evaluation: evaluated: 36, effectively constant: 1
diff --git a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
index 4321535..e9cba62 100644
--- a/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/implicit_getter_calls/getter_call.dart.strong.transformed.expect
@@ -185,3 +185,23 @@
   #C7 = tearoff self::method7
   #C8 = 0
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:7:45 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:130:10 -> IntConstant(-42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:131:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:133:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:136:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:138:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:141:10 -> IntConstant(-23)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:142:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:143:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:149:10 -> IntConstant(-42)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:150:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:152:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:155:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:157:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:160:10 -> IntConstant(-23)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:161:10 -> IntConstant(-11)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///getter_call.dart:162:10 -> IntConstant(-11)
+Extra constant evaluation: evaluated: 322, effectively constant: 17
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
index 9af8d7f..7b083ef 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/experiments_enabled_1.yaml
@@ -14,8 +14,8 @@
         main() {
           dynamic x;
           print(x >>> 2);
-          Class? c = new Class();
+          Class? c = new Class() as Class?;
           print(c!);
         }
         class Class {}
-    expectedLibraryCount: 1
\ No newline at end of file
+    expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
index deaa189..07b6c80 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.1.expect
@@ -36,7 +36,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
index 142aced..c592dbf 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_01.yaml.world.2.expect
@@ -36,7 +36,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
index 69a75ed..fae41df 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/ffi_02.yaml.world.1.expect
@@ -36,7 +36,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.1.expect
index e58a6a6..40e76bf 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.1.expect
@@ -13,7 +13,7 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation {
     final field wid::_Location* _location /* from null */;
-    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4}) → fra::Widget*
+    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget*
       : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
@@ -53,7 +53,7 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget {
-    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4}) → main::Foo*
+    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → main::Foo*
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.2.expect
index e58a6a6..40e76bf 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform.yaml.world.2.expect
@@ -13,7 +13,7 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation {
     final field wid::_Location* _location /* from null */;
-    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4}) → fra::Widget*
+    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget*
       : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
@@ -53,7 +53,7 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget {
-    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4}) → main::Foo*
+    synthetic constructor •({wid::_Location* $creationLocationd_0dea112b090073317d4 = #C1}) → main::Foo*
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
index b4fad46..a789fc9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.1.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -38,35 +38,35 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isNullableByDefault*/;
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isNullableByDefault*/;
-    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       return #C10;
-    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       let dynamic #redirecting_factory = foo::Baz::__ in invalid-expression;
   }
   class Boz extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz {
+    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz {
       if(createNew) {
         return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
       }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
index b6f2a14..489ea3e 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.2.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -38,35 +38,35 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isNullableByDefault*/;
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isNullableByDefault*/;
-    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       return #C10;
-    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       let dynamic #redirecting_factory = foo::Baz::__ in invalid-expression;
   }
   class Boz extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz {
+    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz {
       if(createNew) {
         return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
       }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
index b4fad46..a789fc9 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_const.yaml.world.3.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -38,35 +38,35 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       return #C7;
   }
   class Bar extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Bar::•]/*isNullableByDefault*/;
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Bar
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Bar
       let dynamic #redirecting_factory = foo::Bar::_ in invalid-expression;
   }
   class Baz extends fra::Widget /*hasConstConstructor*/  {
     static field dynamic _redirecting# = <dynamic>[foo::Baz::_]/*isNullableByDefault*/;
-    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    const constructor __({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       return #C10;
-    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Baz
+    static factory _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Baz
       let dynamic #redirecting_factory = foo::Baz::__ in invalid-expression;
   }
   class Boz extends fra::Widget /*hasConstConstructor*/  {
-    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz
+    const constructor _({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
-    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Boz {
+    static factory •({required dart.core::bool createNew = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Boz {
       if(createNew) {
         return new foo::Boz::_($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4);
       }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.1.expect
index cf1b295..aeb8651 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.1.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -38,7 +38,7 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget /*hasConstConstructor*/  {
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.2.expect
index c2ce924..871b5ac 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transform_nnbd.yaml.world.2.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -38,7 +38,7 @@
   import "package:flutter/src/widgets/widget_inspector.dart";
 
   class Foo extends fra::Widget /*hasConstConstructor*/  {
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml
new file mode 100644
index 0000000..0813f0a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml
@@ -0,0 +1,82 @@
+# Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+type: newworld
+target: DDC
+trackWidgetCreation: true
+worlds:
+  - entry: main.dart
+    experiments: non-nullable
+    sources:
+      main.dart: |
+        // @dart=2.8
+        import 'foo.dart';
+      foo.dart: |
+        // @dart=2.8
+        import 'package:flutter/src/widgets/framework.dart';
+        import 'package:flutter/src/widgets/widget_inspector.dart';
+
+        class Foo extends StatelessWidget {
+          const Foo([Object key]) : super(key: key);
+        }
+      flutter/lib/src/widgets/framework.dart: |
+        abstract class Bar {
+          const Bar();
+        }
+        abstract class Widget extends Bar {
+          final Object? key;
+
+          const Widget({this.key});
+        }
+        abstract class StatelessWidget extends Widget {
+          const StatelessWidget({Object? key}) : super(key: key);
+        }
+      flutter/lib/src/widgets/widget_inspector.dart: |
+        abstract class _HasCreationLocation {
+          _Location get _location;
+        }
+        /// A tuple with file, line, and column number, for displaying human-readable
+        /// file locations.
+        class _Location {
+          const _Location({
+            required this.file,
+            required this.line,
+            required this.column,
+            required this.name,
+            required this.parameterLocations,
+          });
+          /// File path of the location.
+          final String file;
+          /// 1-based line number.
+          final int line;
+          /// 1-based column number.
+          final int column;
+          /// Optional name of the parameter or function at this location.
+          final String name;
+          /// Optional locations of the parameters of the member at this location.
+          final List<_Location> parameterLocations;
+        }
+      .dart_tool/package_config.json: |
+        {
+          "configVersion": 2,
+          "packages": [
+            {
+              "name": "flutter",
+              "rootUri": "../flutter",
+              "packageUri": "lib/"
+            }
+          ]
+        }
+    expectedLibraryCount: 4
+  - entry: main.dart
+    worldType: updated
+    invalidate:
+      - main.dart
+    expectInitializeFromDill: false
+    sources:
+      main.dart: |
+        // @dart=2.8
+        import 'foo.dart';
+        Foo foo = const Foo();
+    expectedLibraryCount: 4
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.1.expect
new file mode 100644
index 0000000..fc776ae
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.1.expect
@@ -0,0 +1,65 @@
+main = <No Member>;
+library from "package:flutter/src/widgets/framework.dart" as fra {
+
+  abstract class Bar extends dart.core::Object /*hasConstConstructor*/  {
+    const constructor •() → fra::Bar
+      : super dart.core::Object::•()
+      ;
+  }
+  abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
+    final field dart.core::Object? key;
+    final field wid::_Location? _location /*isNullableByDefault, from null */;
+    const constructor •({dart.core::Object? key = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : fra::Widget::key = key, super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
+      ;
+  }
+  abstract class StatelessWidget extends fra::Widget /*hasConstConstructor*/  {
+    const constructor •({dart.core::Object? key = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::StatelessWidget
+      : super fra::Widget::•(key: key, $creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
+      ;
+  }
+}
+library from "package:flutter/src/widgets/widget_inspector.dart" as wid {
+
+  abstract class _HasCreationLocation extends dart.core::Object {
+    synthetic constructor •() → wid::_HasCreationLocation
+      : super dart.core::Object::•()
+      ;
+    abstract get _location() → wid::_Location;
+  }
+  class _Location extends dart.core::Object /*hasConstConstructor*/  {
+    final field dart.core::String file;
+    final field dart.core::int line;
+    final field dart.core::int column;
+    final field dart.core::String name;
+    final field dart.core::List<wid::_Location> parameterLocations;
+    const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+      : wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///foo.dart" as foo {
+
+  import "package:flutter/src/widgets/framework.dart";
+  import "package:flutter/src/widgets/widget_inspector.dart";
+
+  class Foo extends fra::StatelessWidget /*hasConstConstructor*/  {
+    const constructor •([dart.core::Object* key = #C1]) → foo::Foo*
+      : super fra::StatelessWidget::•(key: key)
+      ;
+    abstract member-signature get key() → dart.core::Object*; -> fra::Widget::key
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///foo.dart";
+
+}
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.2.expect
new file mode 100644
index 0000000..6a2fb38
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_43371.yaml.world.2.expect
@@ -0,0 +1,67 @@
+main = <No Member>;
+library from "package:flutter/src/widgets/framework.dart" as fra {
+
+  abstract class Bar extends dart.core::Object /*hasConstConstructor*/  {
+    const constructor •() → fra::Bar
+      : super dart.core::Object::•()
+      ;
+  }
+  abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
+    final field dart.core::Object? key;
+    final field wid::_Location? _location /*isNullableByDefault, from null */;
+    const constructor •({dart.core::Object? key = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : fra::Widget::key = key, super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
+      ;
+  }
+  abstract class StatelessWidget extends fra::Widget /*hasConstConstructor*/  {
+    const constructor •({dart.core::Object? key = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::StatelessWidget
+      : super fra::Widget::•(key: key, $creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
+      ;
+  }
+}
+library from "package:flutter/src/widgets/widget_inspector.dart" as wid {
+
+  abstract class _HasCreationLocation extends dart.core::Object {
+    synthetic constructor •() → wid::_HasCreationLocation
+      : super dart.core::Object::•()
+      ;
+    abstract get _location() → wid::_Location;
+  }
+  class _Location extends dart.core::Object /*hasConstConstructor*/  {
+    final field dart.core::String file;
+    final field dart.core::int line;
+    final field dart.core::int column;
+    final field dart.core::String name;
+    final field dart.core::List<wid::_Location> parameterLocations;
+    const constructor •({required dart.core::String file = #C1, required dart.core::int line = #C1, required dart.core::int column = #C1, required dart.core::String name = #C1, required dart.core::List<wid::_Location> parameterLocations = #C1}) → wid::_Location
+      : wid::_Location::file = file, wid::_Location::line = line, wid::_Location::column = column, wid::_Location::name = name, wid::_Location::parameterLocations = parameterLocations, super dart.core::Object::•()
+      ;
+  }
+}
+library from "org-dartlang-test:///foo.dart" as foo {
+
+  import "package:flutter/src/widgets/framework.dart";
+  import "package:flutter/src/widgets/widget_inspector.dart";
+
+  class Foo extends fra::StatelessWidget /*hasConstConstructor*/  {
+    const constructor •([dart.core::Object* key = #C1]) → foo::Foo*
+      : super fra::StatelessWidget::•(key: key)
+      ;
+    abstract member-signature get key() → dart.core::Object*; -> fra::Widget::key
+    abstract member-signature operator ==(dynamic other) → dart.core::bool*; -> dart.core::Object::==
+    abstract member-signature get hashCode() → dart.core::int*; -> dart.core::Object::hashCode
+    abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
+    abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
+    abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "org-dartlang-test:///foo.dart";
+
+  static field foo::Foo* foo = #C2;
+}
+constants  {
+  #C1 = null
+  #C2 = foo::Foo {key:#C1, _location:#C1}
+}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.1.expect
index ad57ba5..89e94d3 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.1.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -39,7 +39,7 @@
 
   class Foo extends fra::Widget {
     final field dart.core::String name;
-    constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : foo::Foo::name = name, super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.2.expect
index 1990ba5..a33902f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/flutter_widget_transformer_non_const.yaml.world.2.expect
@@ -8,8 +8,8 @@
   }
   abstract class Widget extends fra::Bar implements wid::_HasCreationLocation /*hasConstConstructor*/  {
     final field wid::_Location? _location /*isNullableByDefault, from null */;
-    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4}) → fra::Widget
-      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4!
+    const constructor •({wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → fra::Widget
+      : super fra::Bar::•(), fra::Widget::_location = $creationLocationd_0dea112b090073317d4
       ;
   }
 }
@@ -39,7 +39,7 @@
 
   class Foo extends fra::Widget {
     final field dart.core::String name;
-    constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4}) → foo::Foo
+    constructor •({required dart.core::String name = #C1, wid::_Location? $creationLocationd_0dea112b090073317d4 = #C1}) → foo::Foo
       : foo::Foo::name = name, super fra::Widget::•($creationLocationd_0dea112b090073317d4: $creationLocationd_0dea112b090073317d4)
       ;
   }
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
index b87a5be..36d467b 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.1.expect
@@ -42,7 +42,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
index d1e9386..cb6ad9d 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_2.yaml.world.2.expect
@@ -42,7 +42,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
index deaa189..07b6c80 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.1.expect
@@ -36,7 +36,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
index 53a7be9..879c497 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.2.expect
@@ -36,7 +36,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
index d5c77ed..c31f270 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_35.yaml.world.3.expect
@@ -37,7 +37,7 @@
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
       return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{=dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::Struct::_addressOf}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
index 12034d0..6ef80fe 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.1.expect
@@ -49,7 +49,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
index f060e27..edb6241 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.2.expect
@@ -49,7 +49,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
index c39751c..13a7716 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_6.yaml.world.3.expect
@@ -42,7 +42,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
index 162d7af..4ef6430 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.1.expect
@@ -58,7 +58,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
index 162d7af..4ef6430 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/no_outline_change_7.yaml.world.2.expect
@@ -58,7 +58,7 @@
       : main::CompilationStrategy::index = index, main::CompilationStrategy::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=main::CompilationStrategy::_name};
+      return this.{main::CompilationStrategy::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
index b92a1ea..d5f5815 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.2.expect
@@ -21,12 +21,38 @@
   }
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib2.dart:2:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib2.dart:2:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
   static const field lib::Foo* fooField = invalid-expression "This assertion failed.";
 }
 library from "org-dartlang-test:///lib3.dart" as lib3 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib3.dart:2:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib3.dart:2:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
index a37c20f..b78ad6f 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.3.expect
@@ -27,6 +27,19 @@
   static const field lib::Foo* fooField = #C1;
 }
 library from "org-dartlang-test:///lib3.dart" as lib3 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib3.dart:2:25: Error: Constant evaluation error:
+// const fooField2 = const Foo(0);
+//                         ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib3.dart:2:7: Context: While analyzing:
+// const fooField2 = const Foo(0);
+//       ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
index 7ebf557..b991c2c 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_10.yaml.world.4.expect
@@ -21,6 +21,19 @@
   }
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib2.dart:2:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib2.dart:2:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
index da804b5..0749995 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_11.yaml.world.2.expect
@@ -21,6 +21,16 @@
   }
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib2.dart:4:27: Error: Constant evaluation error:
+//   const Bar() : x = const Foo(0);
+//                           ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
index ff534c4..a3c1c19 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_8.yaml.world.2.expect
@@ -21,6 +21,16 @@
   }
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib2.dart:3:9: Error: Constant evaluation error:
+//   const Foo(0);
+//         ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
index 503ce20..20b5e7e 100644
--- a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_9.yaml.world.2.expect
@@ -21,12 +21,38 @@
   }
 }
 library from "org-dartlang-test:///lib2.dart" as lib2 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib2.dart:2:24: Error: Constant evaluation error:
+// const fooField = const Foo(0);
+//                        ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib2.dart:2:7: Context: While analyzing:
+// const fooField = const Foo(0);
+//       ^
+//
 
   import "org-dartlang-test:///lib.dart";
 
   static const field lib::Foo* fooField = invalid-expression "This assertion failed.";
 }
 library from "org-dartlang-test:///lib3.dart" as lib3 {
+//
+// Problems in library:
+//
+// org-dartlang-test:///lib3.dart:2:19: Error: Constant evaluation error:
+// const fooField2 = fooField;
+//                   ^
+// org-dartlang-test:///lib.dart:2:31: Context: This assertion failed.
+//   const Foo(int i) : assert(i > 0);
+//                               ^
+// org-dartlang-test:///lib3.dart:2:7: Context: While analyzing:
+// const fooField2 = fooField;
+//       ^
+//
 
   import "org-dartlang-test:///lib2.dart";
 
diff --git a/pkg/front_end/testcases/inference/async_await.dart.outline.expect b/pkg/front_end/testcases/inference/async_await.dart.outline.expect
index 5c7c774..f148d78 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.outline.expect
@@ -22,7 +22,7 @@
   abstract member-signature method catchError(core::Function* onError, {(core::Object*) →* core::bool* test}) → asy::Future<core::int*>*; -> asy::Future::catchError
   abstract member-signature method whenComplete(() →* FutureOr<void>* action) → asy::Future<core::int*>*; -> asy::Future::whenComplete
   abstract member-signature method asStream() → asy::Stream<core::int*>*; -> asy::Future::asStream
-  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>onTimeout}) → asy::Future<core::int*>*; -> asy::Future::timeout
+  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>* onTimeout}) → asy::Future<core::int*>*; -> asy::Future::timeout
 }
 static method test() → void async 
   ;
diff --git a/pkg/front_end/testcases/inference/async_await.dart.strong.expect b/pkg/front_end/testcases/inference/async_await.dart.strong.expect
index b99c76b..3505342 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.strong.expect
@@ -23,7 +23,7 @@
   abstract member-signature method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<core::int*>*; -> asy::Future::catchError
   abstract member-signature method whenComplete(() →* FutureOr<void>* action) → asy::Future<core::int*>*; -> asy::Future::whenComplete
   abstract member-signature method asStream() → asy::Stream<core::int*>*; -> asy::Future::asStream
-  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>onTimeout = #C1}) → asy::Future<core::int*>*; -> asy::Future::timeout
+  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>* onTimeout = #C1}) → asy::Future<core::int*>*; -> asy::Future::timeout
 }
 static method test() → void async {
   core::int* x0;
diff --git a/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
index d764e00..0903294 100644
--- a/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/async_await.dart.strong.transformed.expect
@@ -24,7 +24,7 @@
   abstract member-signature method catchError(core::Function* onError, {(core::Object*) →* core::bool* test = #C1}) → asy::Future<core::int*>*; -> asy::Future::catchError
   abstract member-signature method whenComplete(() →* FutureOr<void>* action) → asy::Future<core::int*>*; -> asy::Future::whenComplete
   abstract member-signature method asStream() → asy::Stream<core::int*>*; -> asy::Future::asStream
-  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>onTimeout = #C1}) → asy::Future<core::int*>*; -> asy::Future::timeout
+  abstract member-signature method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<core::int*>* onTimeout = #C1}) → asy::Future<core::int*>*; -> asy::Future::timeout
 }
 static method test() → void /* originally async */ {
   final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
diff --git a/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
index a0d1c29..e985e99 100644
--- a/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/bug30624.dart.strong.transformed.expect
@@ -46,3 +46,7 @@
   #C1 = null
   #C2 = tearoff self::C::_default
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///bug30624.dart:40:35 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 47, effectively constant: 1
diff --git a/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
index 7008291..ff145dc 100644
--- a/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/complex_predecrement.dart.strong.transformed.expect
@@ -6,3 +6,9 @@
   core::List<core::int*>* foo = <core::int*>[1, 2, 3];
   core::print(let final core::List<core::int*>* #t1 = foo in let final core::int* #t2 = 0 in let final core::int* #t3 = #t1.{core::List::[]}(#t2).{core::num::-}(1) in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3);
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///complex_predecrement.dart:10:75 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///complex_predecrement.dart:10:75 -> IntConstant(0)
+Extra constant evaluation: evaluated: 16, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
index 2f1de22..39b351a 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.outline.expect
@@ -2,47 +2,47 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field1 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field2 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
index 2d16975..537432c 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.expect
@@ -2,47 +2,47 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field1 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field2 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
diff --git a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
index 2d16975..537432c 100644
--- a/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicting_fields.dart.strong.transformed.expect
@@ -2,47 +2,47 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:18:7: Error: Can't infer a return type for 'field1' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field1 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:20:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field1(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:8:11: Context: This is one of the overridden members.
 //   dynamic field1;
 //           ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:13:7: Context: This is one of the overridden members.
 //   int field1;
 //       ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:19:7: Error: Can't infer a return type for 'field2' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get field2 => null;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
-// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:21:14: Error: Can't infer a type for 'value' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   set field2(value) {}
 //              ^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:9:7: Context: This is one of the overridden members.
 //   int field2;
 //       ^^^^^^
-// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicting_fields.dart:14:11: Context: This is one of the overridden members.
 //   dynamic field2;
 //           ^^^^^^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
index e5c3a99..9a21f6c 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.outline.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
index f3a5049..28c663f 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
index f3a5049..28c663f 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen.dart.strong.transformed.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:25:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:30:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:21:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen.dart:17:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
index ddd90c3..43ee8e9 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.outline.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
index 3214028..d3047a9 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
index 3214028..d3047a9 100644
--- a/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/conflicts_can_happen2.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:34:7: Error: Can't infer a return type for 'a' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   get a => null;
 //       ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:22:12: Context: This is one of the overridden members.
 //   final I1 a = null;
 //            ^
-// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/conflicts_can_happen2.dart:26:12: Context: This is one of the overridden members.
 //   final I2 a = null;
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index bd2330c..1cea698 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -52,3 +52,9 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///downwards_inference_annotations.dart:13:2 -> InstanceConstant(const Foo{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///downwards_inference_annotations.dart:16:2 -> InstanceConstant(const Foo{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index c11d438..f6d0c76 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -38,3 +38,10 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:13:4 -> InstanceConstant(const Foo{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:19:4 -> InstanceConstant(const Foo{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///downwards_inference_annotations_class_members.dart:16:4 -> InstanceConstant(const Foo{})
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/inference/future_then.dart.outline.expect b/pkg/front_end/testcases/inference/future_then.dart.outline.expect
index c766d86..903b67e 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.expect
index a9e40184..2d476b4 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
index 99e6514..15b315a 100644
--- a/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect
index c766d86..590e815 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_2.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
index 7fb39f6..9755c88 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
index 1be1c3f..e5e7002 100644
--- a/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_2.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect
index c766d86..127f049 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_3.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
index b39606f..79fbdd6 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
index e7a676e..9e2db60 100644
--- a/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_3.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect
index c766d86..c3a7845 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_4.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
index eb2b35f..090effe 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
index ce704e2..c37addd 100644
--- a/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_4.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect
index c766d86..9bddbcd 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_5.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
index c141fb2..9988e76 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
index 50fec58..27c8361 100644
--- a/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_5.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect
index c766d86..908df9c 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_6.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
index baec351..7df4804 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
index 6091b44..25b8d87 100644
--- a/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_6.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect
index c766d86..f0c10fb 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
index f94dd6a..7bbdb21 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
index 10ecbed..9be32a1 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect
index c766d86..6d7ac2e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_2.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
index 771b278..ac6c2b0 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
index f4bb5a9..4067e3e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect
index c766d86..5942aa9 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_3.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
index c23a047..cf29dae 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
index eef7092..63fe450 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect
index c766d86..e3979f7 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_4.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
index 36ad941..a3755b3 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
index e8aa435..a51edd8 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
index e44607b..413f5b1 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
@@ -20,17 +20,17 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new MyFuture<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@returnType=FutureOr<int*>*/ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x
         ? 2
         : new MyFuture<int>.value(3);
   });
   Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
       /*info:INFERRED_TYPE_CLOSURE,error:INVALID_CAST_FUNCTION_EXPR*/
-      /*@ returnType=FutureOr<int*> */ (/*@ type=bool* */ x) =>
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) =>
           x ? 2 : new MyFuture<int>.value(3));
   Future<int> t6 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@ returnType=FutureOr<int*> */ (/*@ type=bool* */ x) {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) {
     return /*info:DOWN_CAST_COMPOSITE*/ x ? 2 : new MyFuture<int>.value(3);
   });
 }
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect
index c766d86..a52e25c 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_5.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
index 61c1617..52b58db 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
@@ -29,18 +29,18 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await new self::MyFuture::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> async {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
-  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
-  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> {
-    return (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>;
+  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
+  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* {
+    return (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
index 7972bbb..584f94a 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
@@ -100,9 +100,9 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
-  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> {
-    return (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>;
+  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
+  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* {
+    return (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
index 4a0cc0e..d502d9b 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
@@ -20,15 +20,15 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new Future<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@returnType=FutureOr<int*>*/ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x ? 2 : new Future<int>.value(3);
   });
   Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
       /*info:INFERRED_TYPE_CLOSURE,error:INVALID_CAST_FUNCTION_EXPR*/
-      /*@ returnType=FutureOr<int*> */ (/*@ type=bool* */ x) =>
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) =>
           x ? 2 : new Future<int>.value(3));
   Future<int> t6 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@ returnType=FutureOr<int*> */ (/*@ type=bool* */ x) {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) {
     return /*info:DOWN_CAST_COMPOSITE*/ x ? 2 : new Future<int>.value(3);
   });
 }
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect
index c766d86..7b0d48e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_conditional_6.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
index db5bebc..3603d46 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
@@ -29,18 +29,18 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
   asy::Future<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await asy::Future::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> async {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
-  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
-  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> {
-    return (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>;
+  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
+  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* {
+    return (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
index ef8cb30..e7d7fe7 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
@@ -100,9 +100,9 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
-  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> {
-    return (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>;
+  asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
+  asy::Future<core::int*>* t6 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* {
+    return (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart b/pkg/front_end/testcases/inference/future_then_explicit_future.dart
index c1d7db6..c14e152 100644
--- a/pkg/front_end/testcases/inference/future_then_explicit_future.dart
+++ b/pkg/front_end/testcases/inference/future_then_explicit_future.dart
@@ -12,7 +12,7 @@
   var /*@type=Future<Future<List<int*>*>*>**/ x = f. /*@target=Future.then*/ then<
           Future<List<int>>>(
       /*error:ARGUMENT_TYPE_NOT_ASSIGNABLE*/
-      /*@returnType=FutureOr<Future<List<int*>*>*>*/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
+      /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
   Future<List<int>> y = x;
 }
 
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.expect
index 8cb973a..cf41d05 100644
--- a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:98: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
+// pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:99: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
 //  - 'List' is from 'dart:core'.
 //  - 'Future' is from 'dart:async'.
-//       /*@returnType=FutureOr<Future<List<int*>*>*>*/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
-//                                                                                                  ^
+//       /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
+//                                                                                                   ^
 //
 // pkg/front_end/testcases/inference/future_then_explicit_future.dart:16:25: Error: A value of type 'Future<Future<List<int>>>' can't be assigned to a variable of type 'Future<List<int>>'.
 //  - 'Future' is from 'dart:async'.
@@ -22,11 +22,11 @@
 
 static method m1() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<asy::Future<core::List<core::int*>*>*>* x = f.{asy::Future::then}<asy::Future<core::List<core::int*>*>*>((core::int* x) → FutureOr<asy::Future<core::List<core::int*>*>*> => let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:98: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
+  asy::Future<asy::Future<core::List<core::int*>*>*>* x = f.{asy::Future::then}<asy::Future<core::List<core::int*>*>*>((core::int* x) → FutureOr<asy::Future<core::List<core::int*>*>*>* => let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:99: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
  - 'List' is from 'dart:core'.
  - 'Future' is from 'dart:async'.
-      /*@returnType=FutureOr<Future<List<int*>*>*>*/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
-                                                                                                 ^" in <dynamic>[] as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>);
+      /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
+                                                                                                  ^" in <dynamic>[] as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>*);
   asy::Future<core::List<core::int*>*>* y = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:16:25: Error: A value of type 'Future<Future<List<int>>>' can't be assigned to a variable of type 'Future<List<int>>'.
  - 'Future' is from 'dart:async'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
index 8cb973a..cf41d05 100644
--- a/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_explicit_future.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:98: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
+// pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:99: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
 //  - 'List' is from 'dart:core'.
 //  - 'Future' is from 'dart:async'.
-//       /*@returnType=FutureOr<Future<List<int*>*>*>*/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
-//                                                                                                  ^
+//       /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
+//                                                                                                   ^
 //
 // pkg/front_end/testcases/inference/future_then_explicit_future.dart:16:25: Error: A value of type 'Future<Future<List<int>>>' can't be assigned to a variable of type 'Future<List<int>>'.
 //  - 'Future' is from 'dart:async'.
@@ -22,11 +22,11 @@
 
 static method m1() → dynamic {
   asy::Future<core::int*>* f;
-  asy::Future<asy::Future<core::List<core::int*>*>*>* x = f.{asy::Future::then}<asy::Future<core::List<core::int*>*>*>((core::int* x) → FutureOr<asy::Future<core::List<core::int*>*>*> => let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:98: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
+  asy::Future<asy::Future<core::List<core::int*>*>*>* x = f.{asy::Future::then}<asy::Future<core::List<core::int*>*>*>((core::int* x) → FutureOr<asy::Future<core::List<core::int*>*>*>* => let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:15:99: Error: A value of type 'List<dynamic>' can't be assigned to a variable of type 'FutureOr<Future<List<int>>>'.
  - 'List' is from 'dart:core'.
  - 'Future' is from 'dart:async'.
-      /*@returnType=FutureOr<Future<List<int*>*>*>*/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
-                                                                                                 ^" in <dynamic>[] as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>);
+      /*@returnType=FutureOr<Future<List<int*>*>*>**/ (/*@type=int**/ x) => /*@typeArgs=dynamic*/ []);
+                                                                                                  ^" in <dynamic>[] as{TypeError} FutureOr<asy::Future<core::List<core::int*>*>*>*);
   asy::Future<core::List<core::int*>*>* y = let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/inference/future_then_explicit_future.dart:16:25: Error: A value of type 'Future<Future<List<int>>>' can't be assigned to a variable of type 'Future<List<int>>'.
  - 'Future' is from 'dart:async'.
  - 'List' is from 'dart:core'.
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
index c766d86..e4600c3 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_ifNull.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
index 1d3a7b5..4771d6d 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index f4e1ed0..debc669 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -30,7 +30,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect
index 20a111b..5309f49 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void
   ;
 static method foo() → self::MyFuture<dynamic>*
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
index 3cc4af5..ee70fad 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.expect
@@ -38,7 +38,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
index c2a6d0c..31e558a 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards.dart.strong.transformed.expect
@@ -38,7 +38,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect
index 20a111b..6b301eb 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.outline.expect
@@ -29,10 +29,27 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void
   ;
 static method foo() → self::MyFuture<dynamic>*
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_2.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
index 51e731e..48b7a9a 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.expect
@@ -37,7 +37,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
index 2cc8750..d6e485a 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_2.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method main() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect
index 4d4f3b9..0085139 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void
@@ -38,3 +38,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_then_upwards_3.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
index 716490e..b19ec32 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.expect
@@ -37,7 +37,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
index d80dc98..c213ce8 100644
--- a/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_upwards_3.dart.strong.transformed.expect
@@ -37,7 +37,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method test() → void {
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect
index 53919a4..739558d 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* async 
@@ -40,3 +40,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
index a996264..ea9473b 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* async {
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
index 6f4a91b..19d7f5e 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect
index 53919a4..04c973a 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* async 
@@ -40,3 +40,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_async_conditional_2.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
index 101a065..6ee66d9 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* async {
diff --git a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
index ea54343..fac7441 100644
--- a/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_async_conditional_2.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static method g1(core::bool* x) → asy::Future<core::int*>* /* originally async */ {
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect
index 9ce2e52..ef0889f 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
@@ -41,3 +41,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
index dc7ead1..5113eaf 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.expect
@@ -36,7 +36,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
index a876f1e..b3b21ee 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards.dart.strong.transformed.expect
@@ -36,7 +36,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect
index 9ce2e52..8471c54 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
@@ -41,3 +41,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_2.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
index f6db118..bf4fd10 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
index 1d4203f..08408e4 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_2.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field self::MyFuture<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect
index a366aa3..d14c4a7 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
@@ -41,3 +41,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_3.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
index 1f9668b..b52cf7b 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.expect
@@ -36,7 +36,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
index 61d0c65c..1a3f92b 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_3.dart.strong.transformed.expect
@@ -36,7 +36,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect
index a366aa3..3853e42 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.outline.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#whenComplete, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#asStream, 0, const <core::Type*>[], const <dynamic>[], core::Map::unmodifiable<core::Symbol*, dynamic>(const <core::Symbol*, dynamic>{}))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#timeout, 0, const <core::Type*>[], core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#onTimeout: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
@@ -41,3 +41,20 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///future_union_downwards_4.dart:10:7 -> SymbolConstant(#onTimeout)
+Extra constant evaluation: evaluated: 46, effectively constant: 13
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
index a94b936..8ce0d07 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
index 5c71651..578bc3b 100644
--- a/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_union_downwards_4.dart.strong.transformed.expect
@@ -29,7 +29,7 @@
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
   no-such-method-forwarder method asStream() → asy::Stream<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 0, #C3, #C6, core::Map::unmodifiable<core::Symbol*, dynamic>(#C7))) as{TypeError,ForDynamic} asy::Stream<self::MyFuture::T*>*;
-  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
+  no-such-method-forwarder method timeout(core::Duration* timeLimit, {generic-covariant-impl () →* FutureOr<self::MyFuture::T*>* onTimeout = #C1}) → asy::Future<self::MyFuture::T*>*
     return this.{self::MyFuture::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C3, core::List::unmodifiable<dynamic>(<dynamic>[timeLimit]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C10: onTimeout}))) as{TypeError,ForDynamic} asy::Future<self::MyFuture::T*>*;
 }
 static field asy::Future<dynamic>* f;
diff --git a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.strong.transformed.expect
index 258cc6e..0034901 100644
--- a/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_infer_generic_instantiation.dart.strong.transformed.expect
@@ -125,3 +125,34 @@
   #C1 = tearoff math::max
   #C2 = tearoff math::min
 }
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:16:16 -> PartialInstantiationConstant(max<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:17:16 -> PartialInstantiationConstant(max<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:18:16 -> PartialInstantiationConstant(max<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:19:16 -> PartialInstantiationConstant(max<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:20:16 -> PartialInstantiationConstant(max<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:21:16 -> PartialInstantiationConstant(max<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:22:16 -> PartialInstantiationConstant(max<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:23:16 -> PartialInstantiationConstant(max<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:24:16 -> PartialInstantiationConstant(max<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:26:70 -> PartialInstantiationConstant(max<Object*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:28:73 -> PartialInstantiationConstant(max<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:30:73 -> PartialInstantiationConstant(max<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:31:70 -> PartialInstantiationConstant(max<Object*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:32:70 -> PartialInstantiationConstant(max<Object*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:35:11 -> PartialInstantiationConstant(min<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:36:11 -> PartialInstantiationConstant(min<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:37:11 -> PartialInstantiationConstant(min<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:38:11 -> PartialInstantiationConstant(min<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:39:11 -> PartialInstantiationConstant(min<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:40:11 -> PartialInstantiationConstant(min<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:41:11 -> PartialInstantiationConstant(min<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:42:11 -> PartialInstantiationConstant(min<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:43:11 -> PartialInstantiationConstant(min<double*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:45:65 -> PartialInstantiationConstant(min<Object*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:46:72 -> PartialInstantiationConstant(min<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:47:72 -> PartialInstantiationConstant(min<num*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:48:65 -> PartialInstantiationConstant(min<Object*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_infer_generic_instantiation.dart:49:65 -> PartialInstantiationConstant(min<Object*>)
+Extra constant evaluation: evaluated: 133, effectively constant: 28
diff --git a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
index 76dfdff..854ab35 100644
--- a/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/generic_methods_nested_generic_instantiation.dart.strong.transformed.expect
@@ -46,3 +46,8 @@
 constants  {
   #C1 = tearoff math::max
 }
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_nested_generic_instantiation.dart:28:71 -> PartialInstantiationConstant(max<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///generic_methods_nested_generic_instantiation.dart:29:67 -> PartialInstantiationConstant(max<int*>)
+Extra constant evaluation: evaluated: 16, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
index 14cea21..b735a9b 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.outline.expect
@@ -2,69 +2,69 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //   ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   h(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the overridden members.
 //   A h(A x, {I y}) {}
 //     ^
 //
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
index 3a01350..dedc39b 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.expect
@@ -2,69 +2,69 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //   ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   h(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the overridden members.
 //   A h(A x, {I y}) {}
 //     ^
 //
diff --git a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
index 3a01350..dedc39b 100644
--- a/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inconsistent_overrides.dart.strong.transformed.expect
@@ -2,69 +2,69 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:3: Error: Can't infer a return type for 'f' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //   ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:16:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   f(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:10:5: Context: This is one of the overridden members.
 //   A f(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:22:5: Context: This is one of the overridden members.
 //   I f(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:5: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:17:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   g(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:11:5: Context: This is one of the overridden members.
 //   A g(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:23:5: Context: This is one of the overridden members.
 //   A g(I x, {I y}) {}
 //     ^
 //
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:18:9: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   h(x, {y}) {}
 //         ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:12:5: Context: This is one of the overridden members.
 //   A h(A x, {A y}) {}
 //     ^
-// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/inconsistent_overrides.dart:24:5: Context: This is one of the overridden members.
 //   A h(A x, {I y}) {}
 //     ^
 //
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
index 06d6032..39b30e6 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_full.dart
@@ -23,7 +23,7 @@
 
   static void test(Test t) {
     t. /*@target=Test.member*/ member = /*@ typeArgs=B* */ f();
-    /*@ type=Test* */ t. /*@target=Test.member*/ /*@target=Test.member*/ member
+    /*@ type=Test* */ /*@target=Test.member*/ t. /*@target=Test.member*/ member
         /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
     /*@ type=Test* */ t. /*@target=Test.member*/ /*@target=Test.member*/ member
         /*@target=B.+*/ += /*@ typeArgs=C* */ f();
@@ -38,8 +38,8 @@
     var /*@ type=B* */ v1 =
         t. /*@target=Test.member*/ member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
-        /*@ type=Test* */ t
-                . /*@target=Test.member*/ /*@target=Test.member*/ member
+        /*@ type=Test* */ /*@target=Test.member*/ t
+                . /*@target=Test.member*/ member
             /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
     var /*@ type=A* */ v3 =
         /*@ type=Test* */ t
diff --git a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
index 46fbc47..4422d57 100644
--- a/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
+++ b/pkg/front_end/testcases/inference/infer_assign_to_property_upwards.dart
@@ -14,8 +14,8 @@
 
   static void test(Test1 t) {
     var /*@ type=int* */ v1 = t. /*@target=Test1.prop*/ prop = getInt();
-    var /*@ type=int* */ v4 = /*@ type=Test1* */ t
-            . /*@target=Test1.prop*/ /*@target=Test1.prop*/ prop
+    var /*@ type=int* */ v4 = /*@ type=Test1* */ /*@target=Test1.prop*/ t
+            . /*@target=Test1.prop*/ prop
         /*@target=num.==*/ ??= getInt();
     var /*@ type=int* */ v7 =
         /*@ type=Test1* */ t. /*@target=Test1.prop*/ /*@target=Test1.prop*/ prop
@@ -35,14 +35,14 @@
     var /*@ type=int* */ v1 = t. /*@target=Test2.prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test2.prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test2.prop*/ prop = getDouble();
-    var /*@ type=num* */ v4 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v4 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getInt();
-    var /*@ type=num* */ v5 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v5 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getNum();
-    var /*@ type=num* */ v6 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v6 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getDouble();
     var /*@ type=num* */ v7 =
         /*@ type=Test2* */ t. /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
@@ -67,7 +67,7 @@
   static void test3(Test3 t) {
     var /*@ type=double* */ v3 = t. /*@target=Test3.prop*/ prop = getDouble();
     var /*@ type=double* */ v6 =
-        /*@ type=Test3* */ t. /*@target=Test3.prop*/ /*@target=Test3.prop*/
+        /*@ type=Test3* */ /*@target=Test3.prop*/ t. /*@target=Test3.prop*/
             prop /*@target=num.==*/ ??= getDouble();
     var /*@ type=double* */ v7 =
         /*@ type=Test3* */ t. /*@target=Test3.prop*/ /*@target=Test3.prop*/ prop
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_double.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_double_double.dart.strong.transformed.expect
index ce38bb7..944c9ba 100644
--- a/pkg/front_end/testcases/inference/infer_binary_double_double.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_binary_double_double.dart.strong.transformed.expect
@@ -28,3 +28,19 @@
   self::a_lessEqual;
   self::a_modulo;
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:8:38 -> BoolConstant(false)
+Evaluated: Not @ org-dartlang-testcase:///infer_binary_double_double.dart:9:41 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:10:38 -> DoubleConstant(3.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:11:43 -> DoubleConstant(-1.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:12:43 -> DoubleConstant(2.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:13:42 -> DoubleConstant(0.5)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:14:48 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:15:39 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:16:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:17:45 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:18:42 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_double.dart:19:41 -> DoubleConstant(1.0)
+Extra constant evaluation: evaluated: 24, effectively constant: 12
diff --git a/pkg/front_end/testcases/inference/infer_binary_double_int.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_double_int.dart.strong.transformed.expect
index 4fb5e69..c3d3a34 100644
--- a/pkg/front_end/testcases/inference/infer_binary_double_int.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_binary_double_int.dart.strong.transformed.expect
@@ -28,3 +28,19 @@
   self::a_lessEqual;
   self::a_modulo;
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:8:38 -> BoolConstant(false)
+Evaluated: Not @ org-dartlang-testcase:///infer_binary_double_int.dart:9:41 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:10:38 -> DoubleConstant(3.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:11:43 -> DoubleConstant(-1.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:12:43 -> DoubleConstant(2.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:13:42 -> DoubleConstant(0.5)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:14:48 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:15:39 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:16:36 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:17:45 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:18:42 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_double_int.dart:19:41 -> DoubleConstant(1.0)
+Extra constant evaluation: evaluated: 24, effectively constant: 12
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_double.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_int_double.dart.strong.transformed.expect
index 29ba83c..c9a0c95 100644
--- a/pkg/front_end/testcases/inference/infer_binary_int_double.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_binary_int_double.dart.strong.transformed.expect
@@ -28,3 +28,19 @@
   self::a_lessEqual;
   self::a_modulo;
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:8:36 -> BoolConstant(false)
+Evaluated: Not @ org-dartlang-testcase:///infer_binary_int_double.dart:9:39 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:10:33 -> DoubleConstant(3.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:11:38 -> DoubleConstant(-1.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:12:38 -> DoubleConstant(2.0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:13:37 -> DoubleConstant(0.5)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:14:43 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:15:37 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:16:34 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:17:43 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:18:40 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_double.dart:19:36 -> DoubleConstant(1.0)
+Extra constant evaluation: evaluated: 24, effectively constant: 12
diff --git a/pkg/front_end/testcases/inference/infer_binary_int_int.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_binary_int_int.dart.strong.transformed.expect
index bee4a3d..e0f1ccf 100644
--- a/pkg/front_end/testcases/inference/infer_binary_int_int.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_binary_int_int.dart.strong.transformed.expect
@@ -38,3 +38,24 @@
   self::a_lessEqual;
   self::a_modulo;
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:8:36 -> BoolConstant(false)
+Evaluated: Not @ org-dartlang-testcase:///infer_binary_int_int.dart:9:39 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:10:36 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:11:36 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:12:35 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:13:44 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:14:43 -> IntConstant(4)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:15:33 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:16:38 -> IntConstant(-1)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:17:38 -> IntConstant(2)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:18:37 -> DoubleConstant(0.5)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:19:43 -> IntConstant(0)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:20:37 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:21:34 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:22:43 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:23:40 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_binary_int_int.dart:24:36 -> IntConstant(1)
+Extra constant evaluation: evaluated: 34, effectively constant: 17
diff --git a/pkg/front_end/testcases/inference/infer_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_conditional.dart.strong.transformed.expect
index d539e95..c348897 100644
--- a/pkg/front_end/testcases/inference/infer_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_conditional.dart.strong.transformed.expect
@@ -8,3 +8,9 @@
   self::a;
   self::b;
 }
+
+
+Extra constant evaluation status:
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///infer_conditional.dart:8:35 -> DoubleConstant(2.0)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///infer_conditional.dart:9:35 -> IntConstant(2)
+Extra constant evaluation: evaluated: 4, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.outline.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.outline.expect
index d58d84f..f89bc38 100644
--- a/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_consts_transitively_2.dart.outline.expect
@@ -33,3 +33,11 @@
 static const field core::int* b1 = 2;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2.dart:10:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2.dart:11:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2_a.dart:10:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2_a.dart:11:12 -> IntConstant(2)
+Extra constant evaluation: evaluated: 4, effectively constant: 4
diff --git a/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.outline.expect b/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.outline.expect
index cb88599..1b5944d 100644
--- a/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_consts_transitively_2_a.dart.outline.expect
@@ -33,3 +33,11 @@
 static const field core::int* b1 = 2;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2_a.dart:10:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2_a.dart:11:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2.dart:10:12 -> IntConstant(2)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_consts_transitively_2.dart:11:12 -> IntConstant(2)
+Extra constant evaluation: evaluated: 4, effectively constant: 4
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
index f6d6dda..28cd597 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.outline.expect
@@ -2,36 +2,36 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
index 5b91cfd..044f2fd 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.expect
@@ -2,36 +2,36 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
diff --git a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
index 5b91cfd..044f2fd 100644
--- a/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_field_override_multiple.dart.strong.transformed.expect
@@ -2,36 +2,36 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:32:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:36:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:40:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:17:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference/infer_field_override_multiple.dart:21:14: Context: This is one of the overridden members.
 //   double get x;
 //              ^
 //
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
index e645d8d..b9c9e68 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.outline.expect
@@ -1,4 +1,21 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:14:9: Error: The type 'int' of the field 'B.x' is not assignable to the type 'double' of the inherited setter 'A.x'.
+//   final x;
+//         ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
index 5cb9148..3eab43e 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.expect
@@ -1,4 +1,21 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:14:9: Error: The type 'int' of the field 'B.x' is not assignable to the type 'double' of the inherited setter 'A.x'.
+//   final x;
+//         ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
index 5cb9148..3eab43e 100644
--- a/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart.strong.transformed.expect
@@ -1,4 +1,21 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:14:9: Error: The type 'int' of the field 'B.x' is not assignable to the type 'double' of the inherited setter 'A.x'.
+//   final x;
+//         ^
+// pkg/front_end/testcases/inference/infer_final_field_getter_and_setter.dart:10:12: Context: This is the declaration of the setter 'A.x'.
+//   void set x(double value) {}
+//            ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
index 6d4396b..544c4cb 100644
--- a/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_from_complex_expressions_if_outer_most_value_is_precise.dart.strong.transformed.expect
@@ -185,3 +185,8 @@
 constants  {
   #C1 = <dynamic>[]
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_from_complex_expressions_if_outer_most_value_is_precise.dart:27:25 -> IntConstant(5)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_from_complex_expressions_if_outer_most_value_is_precise.dart:30:32 -> IntConstant(-3)
+Extra constant evaluation: evaluated: 74, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/infer_prefix_expression.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/infer_prefix_expression.dart.strong.transformed.expect
index 4d5f369..d0e0ac7 100644
--- a/pkg/front_end/testcases/inference/infer_prefix_expression.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/infer_prefix_expression.dart.strong.transformed.expect
@@ -10,3 +10,10 @@
   self::a_complement;
   self::a_negate;
 }
+
+
+Extra constant evaluation status:
+Evaluated: Not @ org-dartlang-testcase:///infer_prefix_expression.dart:8:13 -> BoolConstant(false)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_prefix_expression.dart:9:38 -> IntConstant(-2)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///infer_prefix_expression.dart:10:39 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 6, effectively constant: 3
diff --git a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.outline.expect b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.outline.expect
index af46292..f02cb50 100644
--- a/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/infer_statics_transitively3.dart.outline.expect
@@ -40,3 +40,12 @@
 static const field core::int* a2 = 4;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_statics_transitively3.dart:12:12 -> IntConstant(1)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_statics_transitively3.dart:13:12 -> IntConstant(3)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_statics_transitively3.dart:14:14 -> IntConstant(4)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_statics_transitively3.dart:15:14 -> NullConstant(null)
+Evaluated: StaticGet @ org-dartlang-testcase:///infer_statics_transitively3.dart:16:16 -> NullConstant(null)
+Extra constant evaluation: evaluated: 5, effectively constant: 5
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
index 7ca1ec1..a5b5992 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.outline.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -25,3 +25,9 @@
 static final field self::E* x;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///inferred_type_is_enum.dart:8:6 -> ListConstant(const <E*>[const E{E.index: 0, E._name: "E.v1"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inferred_type_is_enum.dart:8:10 -> InstanceConstant(const E{E.index: 0, E._name: "E.v1"})
+Extra constant evaluation: evaluated: 6, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
index 39e563c..d291d40 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
index 39e563c..d291d40 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
index 48cce61..8aa2841 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.outline.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -25,3 +25,9 @@
 static final field core::List<self::E*>* x;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///inferred_type_is_enum_values.dart:8:6 -> ListConstant(const <E*>[const E{E.index: 0, E._name: "E.v1"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///inferred_type_is_enum_values.dart:8:10 -> InstanceConstant(const E{E.index: 0, E._name: "E.v1"})
+Extra constant evaluation: evaluated: 6, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
index 90399f0..3eb7ad4 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
index 90399f0..3eb7ad4 100644
--- a/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/inferred_type_is_enum_values.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
     : self::E::index = index, self::E::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::E::_name};
+    return this.{self::E::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.strong.transformed.expect
index d6804b7..392e7e7 100644
--- a/pkg/front_end/testcases/inference/instantiate_tearoff.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/instantiate_tearoff.dart.strong.transformed.expect
@@ -47,3 +47,8 @@
   #C1 = tearoff self::f
   #C2 = tearoff self::C::g
 }
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///instantiate_tearoff.dart:25:10 -> PartialInstantiationConstant(f<int*>)
+Evaluated: Instantiation @ org-dartlang-testcase:///instantiate_tearoff.dart:27:12 -> PartialInstantiationConstant(C.g<int*>)
+Extra constant evaluation: evaluated: 18, effectively constant: 2
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
index 0ab95b6..f4c4777 100644
--- a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
@@ -28,3 +28,8 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///override_equals.dart:9:4 -> InstanceConstant(const _Override{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
index e08b136..1892d0c 100644
--- a/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/reference_to_typedef.dart.strong.transformed.expect
@@ -5,3 +5,8 @@
 typedef F = () →* void;
 static final field core::Type* x = () →* void;
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///reference_to_typedef.dart:9:11 -> TypeLiteralConstant(void Function()*)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/inference/static_method_tear_off.dart.outline.expect b/pkg/front_end/testcases/inference/static_method_tear_off.dart.outline.expect
index 0327fcf..37761d3 100644
--- a/pkg/front_end/testcases/inference/static_method_tear_off.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/static_method_tear_off.dart.outline.expect
@@ -21,3 +21,8 @@
 static const field (core::String*) →* core::int* v = self::C::f;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///static_method_tear_off.dart:8:13 -> TearOffConstant(C.f)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.outline.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.outline.expect
index fc2eda8..91c3ff0 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.outline.expect
@@ -8,6 +8,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart:9:20: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<dynamic>)(/*@returnType=int**/() {
 //                    ^
 //
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.expect
index a9f015e..2e3ca1e6 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.expect
@@ -8,6 +8,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart:9:20: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<dynamic>)(/*@returnType=int**/() {
 //                    ^
 //
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
index a9f015e..2e3ca1e6 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart.strong.transformed.expect
@@ -8,6 +8,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1.dart:9:20: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<dynamic>)(/*@returnType=int**/() {
 //                    ^
 //
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.outline.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.outline.expect
index 767988c..ac5f82d 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.outline.expect
@@ -8,6 +8,7 @@
 //               ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart:9:16: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<int>)(/*@returnType=int**/() {
 //                ^
 //
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.expect
index e7e43df..938f89a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.expect
@@ -8,6 +8,7 @@
 //               ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart:9:16: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<int>)(/*@returnType=int**/() {
 //                ^
 //
diff --git a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
index e7e43df..938f89a 100644
--- a/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart.strong.transformed.expect
@@ -8,6 +8,7 @@
 //               ^
 //
 // pkg/front_end/testcases/inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1.dart:9:16: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 // var v = (f<int>)(/*@returnType=int**/() {
 //                ^
 //
diff --git a/pkg/front_end/testcases/inference_new/const_invocation.dart b/pkg/front_end/testcases/inference_new/const_invocation.dart
index 8525174..4e58d44 100644
--- a/pkg/front_end/testcases/inference_new/const_invocation.dart
+++ b/pkg/front_end/testcases/inference_new/const_invocation.dart
@@ -8,7 +8,7 @@
 typedef V F<U, V>(U u);
 
 class Foo<T> {
-  Bar<T> get v1 => const /*@ typeArgs=Null? */ Bar();
+  Bar<T> get v1 => const /*@typeArgs=Null?*/ Bar();
   Bar<List<T>> get v2 => const /*@ typeArgs=List<Null?>* */ Bar();
   Bar<F<T, T>> get v3 => const /*@ typeArgs=(Object*) ->* Null? */ Bar();
   Bar<F<F<T, T>, T>> get v4 =>
diff --git a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
index 9bd9561..2c14e98 100644
--- a/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/indexed_assign_combiner.dart.strong.transformed.expect
@@ -123,3 +123,19 @@
   self::A* x = let final self::G* #t17 = g in let final core::int* #t18 = 0 in let final self::A* #t19 = #t17.{self::G::[]}(#t18) in let final void #t20 = #t17.{self::G::[]=}(#t18, #t19.{self::A::+}(1)) in #t19;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:36:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:36:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:37:64 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:37:64 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:43:59 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:43:59 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:45:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:45:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:49:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:49:41 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:51:45 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///indexed_assign_combiner.dart:51:45 -> IntConstant(0)
+Extra constant evaluation: evaluated: 78, effectively constant: 12
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
index 7d38c0b..d239253 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_index.dart.strong.transformed.expect
@@ -5,3 +5,10 @@
 static field core::List<core::double*>* a = <core::double*>[];
 static field core::double* b = let final core::List<core::double*>* #t1 = self::a in let final core::int* #t2 = 0 in let final core::double* #t3 = 1.0 in let final void #t4 = #t1.{core::List::[]=}(#t2, #t3) in #t3;
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_assign_to_index.dart:9:34 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_assign_to_index.dart:9:39 -> DoubleConstant(1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_assign_to_index.dart:9:39 -> DoubleConstant(1.0)
+Extra constant evaluation: evaluated: 11, effectively constant: 3
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
index 06d6032..39b30e6 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_full.dart
@@ -23,7 +23,7 @@
 
   static void test(Test t) {
     t. /*@target=Test.member*/ member = /*@ typeArgs=B* */ f();
-    /*@ type=Test* */ t. /*@target=Test.member*/ /*@target=Test.member*/ member
+    /*@ type=Test* */ /*@target=Test.member*/ t. /*@target=Test.member*/ member
         /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
     /*@ type=Test* */ t. /*@target=Test.member*/ /*@target=Test.member*/ member
         /*@target=B.+*/ += /*@ typeArgs=C* */ f();
@@ -38,8 +38,8 @@
     var /*@ type=B* */ v1 =
         t. /*@target=Test.member*/ member = /*@ typeArgs=B* */ f();
     var /*@ type=B* */ v2 =
-        /*@ type=Test* */ t
-                . /*@target=Test.member*/ /*@target=Test.member*/ member
+        /*@ type=Test* */ /*@target=Test.member*/ t
+                . /*@target=Test.member*/ member
             /*@target=A.==*/ ??= /*@ typeArgs=B* */ f();
     var /*@ type=A* */ v3 =
         /*@ type=Test* */ t
diff --git a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
index e8cd979..15bfd3c 100644
--- a/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
+++ b/pkg/front_end/testcases/inference_new/infer_assign_to_property_upwards.dart
@@ -15,11 +15,11 @@
   static void test(Test1 t) {
     var /*@ type=int* */ v1 = t. /*@target=Test1.prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test1.prop*/ prop = getNum();
-    var /*@ type=int* */ v4 = /*@ type=Test1* */ t
-            . /*@target=Test1.prop*/ /*@target=Test1.prop*/ prop
+    var /*@ type=int* */ v4 = /*@ type=Test1* */ /*@target=Test1.prop*/ t
+            . /*@target=Test1.prop*/ prop
         /*@target=num.==*/ ??= getInt();
-    var /*@ type=num* */ v5 = /*@ type=Test1* */ t
-            . /*@target=Test1.prop*/ /*@target=Test1.prop*/ prop
+    var /*@ type=num* */ v5 = /*@ type=Test1* */ /*@target=Test1.prop*/ t
+            . /*@target=Test1.prop*/ prop
         /*@target=num.==*/ ??= getNum();
     var /*@ type=int* */ v7 = /*@ type=Test1* */ t
             . /*@target=Test1.prop*/ /*@target=Test1.prop*/ prop
@@ -43,14 +43,14 @@
     var /*@ type=int* */ v1 = t. /*@target=Test2.prop*/ prop = getInt();
     var /*@ type=num* */ v2 = t. /*@target=Test2.prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test2.prop*/ prop = getDouble();
-    var /*@ type=num* */ v4 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v4 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getInt();
-    var /*@ type=num* */ v5 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v5 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getNum();
-    var /*@ type=num* */ v6 = /*@ type=Test2* */ t
-            . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
+    var /*@ type=num* */ v6 = /*@ type=Test2* */ /*@target=Test2.prop*/ t
+            . /*@target=Test2.prop*/ prop
         /*@target=num.==*/ ??= getDouble();
     var /*@ type=num* */ v7 = /*@ type=Test2* */ t
             . /*@target=Test2.prop*/ /*@target=Test2.prop*/ prop
@@ -76,11 +76,11 @@
   static void test3(Test3 t) {
     var /*@ type=num* */ v2 = t. /*@target=Test3.prop*/ prop = getNum();
     var /*@ type=double* */ v3 = t. /*@target=Test3.prop*/ prop = getDouble();
-    var /*@ type=num* */ v5 = /*@ type=Test3* */ t
-            . /*@target=Test3.prop*/ /*@target=Test3.prop*/ prop
+    var /*@ type=num* */ v5 = /*@ type=Test3* */ /*@target=Test3.prop*/ t
+            . /*@target=Test3.prop*/ prop
         /*@target=num.==*/ ??= getNum();
-    var /*@ type=double* */ v6 = /*@ type=Test3* */ t
-            . /*@target=Test3.prop*/ /*@target=Test3.prop*/ prop
+    var /*@ type=double* */ v6 = /*@ type=Test3* */ /*@target=Test3.prop*/ t
+            . /*@target=Test3.prop*/ prop
         /*@target=num.==*/ ??= getDouble();
     var /*@ type=double* */ v7 = /*@ type=Test3* */ t
             . /*@target=Test3.prop*/ /*@target=Test3.prop*/ prop
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
index 0672d55..0ebb072 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.outline.expect
@@ -2,14 +2,21 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the overridden members.
+//   void set x(double value);
+//            ^
+//
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is the declaration of the setter 'A.x'.
 //   void set x(double value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
index 60eda17..8ae0ce1 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.expect
@@ -2,14 +2,21 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the overridden members.
+//   void set x(double value);
+//            ^
+//
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is the declaration of the setter 'A.x'.
 //   void set x(double value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
index 60eda17..8ae0ce1 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart.strong.transformed.expect
@@ -2,14 +2,21 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is one of the overridden members.
+//   void set x(double value);
+//            ^
+//
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:9:11: Error: The type 'int' of the getter 'A.x' is not assignable to the type 'double' of the setter 'A.x'.
+//   int get x;
+//           ^
+// pkg/front_end/testcases/inference_new/infer_field_getter_setter_mismatch.dart:10:12: Context: This is the declaration of the setter 'A.x'.
 //   void set x(double value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
index bd38552..d9e8e4e 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.outline.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the overridden members.
 //   A get x;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the overridden members.
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var y;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the overridden members.
 //   B get y;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the overridden members.
 //   void set y(A value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
index 8fae470..3bfa8c0 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the overridden members.
 //   A get x;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the overridden members.
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var y;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the overridden members.
 //   B get y;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the overridden members.
 //   void set y(A value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
index 8fae470..3bfa8c0 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart.strong.transformed.expect
@@ -2,25 +2,25 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:16:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:6:9: Context: This is one of the overridden members.
 //   A get x;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:7:12: Context: This is one of the overridden members.
 //   void set x(B value);
 //            ^
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:17:7: Error: Can't infer a type for 'y' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var y;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:9:9: Context: This is one of the overridden members.
 //   B get y;
 //         ^
-// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_accessors.dart:10:12: Context: This is one of the overridden members.
 //   void set y(A value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
index e02792c..c38c16a 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.outline.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the overridden members.
 //   void set x(num value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
index c89eeb0..37df60c 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the overridden members.
 //   void set x(num value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
index c89eeb0..37df60c 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:13:11: Context: This is one of the overridden members.
 //   int get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_getter_overrides_setter.dart:9:12: Context: This is one of the overridden members.
 //   void set x(num value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
index 25b44a1..0d41588 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.outline.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the overridden members.
 //   void set x(int value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
index bd65763..ae57d36 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the overridden members.
 //   void set x(int value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
index bd65763..ae57d36 100644
--- a/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart.strong.transformed.expect
@@ -2,14 +2,14 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the inherited members have different types.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:19:7: Error: Can't infer a type for 'x' as some of the overridden members have different types.
 // Try adding an explicit type.
 //   var x;
 //       ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:9:11: Context: This is one of the overridden members.
 //   num get x;
 //           ^
-// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the inherited members.
+// pkg/front_end/testcases/inference_new/infer_field_override_setter_overrides_getter.dart:13:12: Context: This is one of the overridden members.
 //   void set x(int value);
 //            ^
 //
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
index 1d35c08..60d0690 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
+++ b/pkg/front_end/testcases/inference_new/infer_instance_accessor_ref.dart
@@ -20,7 +20,7 @@
 
 var a = new A();
 var x = a. /*@target=A.b*/ b. /*@target=B.c*/ c;
-var y = a. /*@ type=B* */ /*@target=A.b*/ b. /*@target=B.c*/ /*@target=B.c*/ c
+var y = a. /*@ type=B* */ /*@target=A.b*/ /*@target=B.c*/ b. /*@target=B.c*/ c
     /*@target=C.==*/ ??= new D();
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
index 2dad28c..c05b4e9 100644
--- a/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
+++ b/pkg/front_end/testcases/inference_new/infer_instance_field_ref.dart
@@ -19,7 +19,7 @@
 
 var a = new A();
 var x = a. /*@target=A.b*/ b. /*@target=B.c*/ c;
-var y = a. /*@ type=B* */ /*@target=A.b*/ b
-    . /*@target=B.c*/ /*@target=B.c*/ c /*@target=C.==*/ ??= new D();
+var y = a. /*@ type=B* */ /*@target=A.b*/ /*@target=B.c*/ b
+    . /*@target=B.c*/ c /*@target=C.==*/ ??= new D();
 
 main() {}
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.outline.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.outline.expect
index d0171ae..1dedb62 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.outline.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:29:9: Error: The type 'A' of the getter 'G.target' is not assignable to the type 'B' of the setter 'G.target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//   A get target => null;
+//         ^^^^^^
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:31:12: Context: This is the declaration of the setter 'G.target'.
+//   void set target(B value) {}
+//            ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
index 165d38e..b551bed 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:29:9: Error: The type 'A' of the getter 'G.target' is not assignable to the type 'B' of the setter 'G.target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//   A get target => null;
+//         ^^^^^^
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:31:12: Context: This is the declaration of the setter 'G.target'.
+//   void set target(B value) {}
+//            ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
index 165d38e..b551bed 100644
--- a/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/property_assign_combiner.dart.strong.transformed.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:29:9: Error: The type 'A' of the getter 'G.target' is not assignable to the type 'B' of the setter 'G.target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/property_assign_combiner.dart'.
+//   A get target => null;
+//         ^^^^^^
+// pkg/front_end/testcases/inference_new/property_assign_combiner.dart:31:12: Context: This is the declaration of the setter 'G.target'.
+//   void set target(B value) {}
+//            ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.outline.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.outline.expect
index 2bd2465..bd2765e 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.outline.expect
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.outline.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:28:7: Error: The type 'A' of the getter 'target' is not assignable to the type 'B' of the setter 'target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+// A get target => null;
+//       ^^^^^^
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:30:10: Context: This is the declaration of the setter 'target'.
+// void set target(B value) {}
+//          ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
index c956d22..a2976ca 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:28:7: Error: The type 'A' of the getter 'target' is not assignable to the type 'B' of the setter 'target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+// A get target => null;
+//       ^^^^^^
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:30:10: Context: This is the declaration of the setter 'target'.
+// void set target(B value) {}
+//          ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
index c956d22..a2976ca 100644
--- a/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference_new/static_assign_combiner.dart.strong.transformed.expect
@@ -1,4 +1,16 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:28:7: Error: The type 'A' of the getter 'target' is not assignable to the type 'B' of the setter 'target'.
+//  - 'A' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+//  - 'B' is from 'pkg/front_end/testcases/inference_new/static_assign_combiner.dart'.
+// A get target => null;
+//       ^^^^^^
+// pkg/front_end/testcases/inference_new/static_assign_combiner.dart:30:10: Context: This is the declaration of the setter 'target'.
+// void set target(B value) {}
+//          ^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect b/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
index c4340c5..5940e75 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.strong.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
 //   local += 0;
 //   ^^^^^
 //
@@ -38,7 +38,7 @@
       return local = #t6;
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local' has already been initialized.");
-  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
   ^^^^^" in #local#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
index c4340c5..5940e75 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.strong.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
 //   local += 0;
 //   ^^^^^
 //
@@ -38,7 +38,7 @@
       return local = #t6;
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local' has already been initialized.");
-  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
   ^^^^^" in #local#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect b/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
index c4340c5..b568136 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.weak.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
 //   local += 0;
 //   ^^^^^
 //
@@ -12,33 +12,47 @@
 
 static method main() → dynamic {
   core::int? local1;
+  core::bool #local1#isSet = false;
   function #local1#get() → core::int
-    return let final core::int? #t1 = local1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.") : #t1{core::int};
-  function #local1#set(core::int #t2) → dynamic
-    return local1 = #t2;
+    return #local1#isSet ?{core::int} local1{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+  function #local1#set(core::int #t1) → dynamic {
+    #local1#isSet = true;
+    return local1 = #t1;
+  }
   #local1#set.call(0);
   self::expect(0, #local1#get.call());
   #local1#set.call(#local1#get.call().{core::num::+}(2));
   self::expect(2, #local1#get.call());
   core::int? local2;
-  function #local2#get() → core::int
-    return let final core::int? #t3 = local2 in #t3.==(null) ?{core::int} local2 = 1 : #t3{core::int};
-  function #local2#set(core::int #t4) → dynamic
-    return local2 = #t4;
+  core::bool #local2#isSet = false;
+  function #local2#get() → core::int {
+    if(!#local2#isSet) {
+      local2 = 1;
+      #local2#isSet = true;
+    }
+    return local2{core::int};
+  }
+  function #local2#set(core::int #t2) → dynamic {
+    #local2#isSet = true;
+    return local2 = #t2;
+  }
   self::expect(1, #local2#get.call());
   #local2#set.call(#local2#get.call().{core::num::+}(2));
   self::expect(3, #local2#get.call());
 }
 static method error() → dynamic {
   final core::int? local;
+  core::bool #local#isSet = false;
   function #local#get() → core::int
-    return let final core::int? #t5 = local in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t5{core::int};
-  function #local#set(core::int #t6) → dynamic
-    if(local.==(null))
-      return local = #t6;
-    else
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t3) → dynamic
+    if(#local#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local' has already been initialized.");
-  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+    else {
+      #local#isSet = true;
+      return local = #t3;
+    }
+  #local#set.call((let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
   ^^^^^" in #local#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
index c4340c5..b568136 100644
--- a/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/compound.dart.weak.transformed.expect
@@ -2,7 +2,7 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
 //   local += 0;
 //   ^^^^^
 //
@@ -12,33 +12,47 @@
 
 static method main() → dynamic {
   core::int? local1;
+  core::bool #local1#isSet = false;
   function #local1#get() → core::int
-    return let final core::int? #t1 = local1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.") : #t1{core::int};
-  function #local1#set(core::int #t2) → dynamic
-    return local1 = #t2;
+    return #local1#isSet ?{core::int} local1{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local1' has not been initialized.");
+  function #local1#set(core::int #t1) → dynamic {
+    #local1#isSet = true;
+    return local1 = #t1;
+  }
   #local1#set.call(0);
   self::expect(0, #local1#get.call());
   #local1#set.call(#local1#get.call().{core::num::+}(2));
   self::expect(2, #local1#get.call());
   core::int? local2;
-  function #local2#get() → core::int
-    return let final core::int? #t3 = local2 in #t3.==(null) ?{core::int} local2 = 1 : #t3{core::int};
-  function #local2#set(core::int #t4) → dynamic
-    return local2 = #t4;
+  core::bool #local2#isSet = false;
+  function #local2#get() → core::int {
+    if(!#local2#isSet) {
+      local2 = 1;
+      #local2#isSet = true;
+    }
+    return local2{core::int};
+  }
+  function #local2#set(core::int #t2) → dynamic {
+    #local2#isSet = true;
+    return local2 = #t2;
+  }
   self::expect(1, #local2#get.call());
   #local2#set.call(#local2#get.call().{core::num::+}(2));
   self::expect(3, #local2#get.call());
 }
 static method error() → dynamic {
   final core::int? local;
+  core::bool #local#isSet = false;
   function #local#get() → core::int
-    return let final core::int? #t5 = local in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t5{core::int};
-  function #local#set(core::int #t6) → dynamic
-    if(local.==(null))
-      return local = #t6;
-    else
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t3) → dynamic
+    if(#local#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local' has already been initialized.");
-  #local#set.call((let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Non-nullable late variable 'local' without initializer is definitely unassigned.
+    else {
+      #local#isSet = true;
+      return local = #t3;
+    }
+  #local#set.call((let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/late_lowering/compound.dart:20:3: Error: Late variable 'local' without initializer is definitely unassigned.
   local += 0;
   ^^^^^" in #local#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
index 0d317bf..6bf2ce0 100644
--- a/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/covariant_late_field.dart.weak.expect
@@ -16,18 +16,24 @@
 
 class A extends core::Object {
   field core::num? _#A#invariantField = null;
+  field core::bool _#A#invariantField#isSet = false;
   field core::num? _#A#covariantField = null;
+  field core::bool _#A#covariantField#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get invariantField() → core::num
-    return let final core::num? #t1 = this.{self::A::_#A#invariantField} in #t1.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'invariantField' has not been initialized.") : #t1{core::num};
-  set invariantField(core::num #t2) → void
+    return this.{self::A::_#A#invariantField#isSet} ?{core::num} let final core::num? #t1 = this.{self::A::_#A#invariantField} in #t1{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'invariantField' has not been initialized.");
+  set invariantField(core::num #t2) → void {
+    this.{self::A::_#A#invariantField#isSet} = true;
     this.{self::A::_#A#invariantField} = #t2;
+  }
   get covariantField() → core::num
-    return let final core::num? #t3 = this.{self::A::_#A#covariantField} in #t3.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'covariantField' has not been initialized.") : #t3{core::num};
-  set covariantField(covariant core::num #t4) → void
+    return this.{self::A::_#A#covariantField#isSet} ?{core::num} let final core::num? #t3 = this.{self::A::_#A#covariantField} in #t3{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'covariantField' has not been initialized.");
+  set covariantField(covariant core::num #t4) → void {
+    this.{self::A::_#A#covariantField#isSet} = true;
     this.{self::A::_#A#covariantField} = #t4;
+  }
 }
 abstract class B extends core::Object implements self::A {
   synthetic constructor •() → self::B
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
index b69e0ea..7c2c33b 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -95,13 +95,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -141,13 +141,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -161,7 +161,7 @@
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
   #local4#set.call(0);
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 };
@@ -196,13 +196,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -242,13 +242,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -262,7 +262,7 @@
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
   #local4#set.call(0);
-  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
index b69e0ea..7c2c33b 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.strong.transformed.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -95,13 +95,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -141,13 +141,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -161,7 +161,7 @@
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
   #local4#set.call(0);
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 };
@@ -196,13 +196,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -242,13 +242,13 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -262,7 +262,7 @@
     else
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
   #local4#set.call(0);
-  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
index b69e0ea..fcbfeb4 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -77,31 +77,37 @@
       return local2 = #t1;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t2 = local4 in #t2.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    if(local4.==(null))
-      return local4 = #t3;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t2) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t2;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = local6 in #t4.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    if(local6.==(null))
-      return local6 = #t5;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t3) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t3;
+    }
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -110,29 +116,35 @@
   core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} local2{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(T% #t9) → dynamic
+  function #local2#set(T% #t7) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t9;
+      return local2 = #t7;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t10 = local4 in #t10.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t10{core::int};
-  function #local4#set(core::int #t11) → dynamic
-    if(local4.==(null))
-      return local4 = #t11;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t8) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t8;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t12 = local6 in #t12.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t12{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t13) → dynamic
-    if(local6.==(null))
-      return local6 = #t13;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t9) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t9;
+    }
   if(b) {
     #local2#set.call(value);
     #local4#set.call(0);
@@ -141,27 +153,30 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t17 = local4 in #t17.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t17{core::int};
-  function #local4#set(core::int #t18) → dynamic
-    if(local4.==(null))
-      return local4 = #t18;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t13) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t13;
+    }
   #local4#set.call(0);
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 };
@@ -170,39 +185,45 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} local2{self::methodDirect::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodDirect::T% #t20) → dynamic
+  function #local2#set(self::methodDirect::T% #t15) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t20;
+      return local2 = #t15;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t21 = local4 in #t21.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t21{core::int};
-  function #local4#set(core::int #t22) → dynamic
-    if(local4.==(null))
-      return local4 = #t22;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t16) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t16;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t23 = local6 in #t23.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t23{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t24) → dynamic
-    if(local6.==(null))
-      return local6 = #t24;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t17) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t17;
+    }
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -211,29 +232,35 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} local2{self::methodConditional::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodConditional::T% #t28) → dynamic
+  function #local2#set(self::methodConditional::T% #t21) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t28;
+      return local2 = #t21;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t29 = local4 in #t29.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t29{core::int};
-  function #local4#set(core::int #t30) → dynamic
-    if(local4.==(null))
-      return local4 = #t30;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t22) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t22;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t31 = local6 in #t31.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t31{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t32) → dynamic
-    if(local6.==(null))
-      return local6 = #t32;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t23) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t23;
+    }
   if(b) {
     #local2#set.call(value);
     #local4#set.call(0);
@@ -242,27 +269,30 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
 static method methodCompound() → dynamic {
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t36 = local4 in #t36.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t36{core::int};
-  function #local4#set(core::int #t37) → dynamic
-    if(local4.==(null))
-      return local4 = #t37;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t27) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t27;
+    }
   #local4#set.call(0);
-  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
index b69e0ea..fcbfeb4 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_assigned.dart.weak.transformed.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -77,31 +77,37 @@
       return local2 = #t1;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t2 = local4 in #t2.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    if(local4.==(null))
-      return local4 = #t3;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t2) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t2;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = local6 in #t4.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    if(local6.==(null))
-      return local6 = #t5;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t3) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t3;
+    }
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
@@ -110,29 +116,35 @@
   core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} local2{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(T% #t9) → dynamic
+  function #local2#set(T% #t7) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t9;
+      return local2 = #t7;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t10 = local4 in #t10.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t10{core::int};
-  function #local4#set(core::int #t11) → dynamic
-    if(local4.==(null))
-      return local4 = #t11;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t8) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t8;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t12 = local6 in #t12.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t12{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t13) → dynamic
-    if(local6.==(null))
-      return local6 = #t13;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t9) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t9;
+    }
   if(b) {
     #local2#set.call(value);
     #local4#set.call(0);
@@ -141,27 +153,30 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t17 = local4 in #t17.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t17{core::int};
-  function #local4#set(core::int #t18) → dynamic
-    if(local4.==(null))
-      return local4 = #t18;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t13) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t13;
+    }
   #local4#set.call(0);
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 };
@@ -170,39 +185,45 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} local2{self::methodDirect::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodDirect::T% #t20) → dynamic
+  function #local2#set(self::methodDirect::T% #t15) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t20;
+      return local2 = #t15;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t21 = local4 in #t21.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t21{core::int};
-  function #local4#set(core::int #t22) → dynamic
-    if(local4.==(null))
-      return local4 = #t22;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t16) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t16;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t23 = local6 in #t23.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t23{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t24) → dynamic
-    if(local6.==(null))
-      return local6 = #t24;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t17) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t17;
+    }
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
@@ -211,29 +232,35 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} local2{self::methodConditional::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodConditional::T% #t28) → dynamic
+  function #local2#set(self::methodConditional::T% #t21) → dynamic
     if(#local2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local2' has already been initialized.");
     else {
       #local2#isSet = true;
-      return local2 = #t28;
+      return local2 = #t21;
     }
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t29 = local4 in #t29.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t29{core::int};
-  function #local4#set(core::int #t30) → dynamic
-    if(local4.==(null))
-      return local4 = #t30;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t22) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t22;
+    }
   final FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t31 = local6 in #t31.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t31{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t32) → dynamic
-    if(local6.==(null))
-      return local6 = #t32;
-    else
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t23) → dynamic
+    if(#local6#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local6' has already been initialized.");
+    else {
+      #local6#isSet = true;
+      return local6 = #t23;
+    }
   if(b) {
     #local2#set.call(value);
     #local4#set.call(0);
@@ -242,27 +269,30 @@
   #local2#set.call(value);
   #local4#set.call(0);
   #local6#set.call(0);
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in #local2#set.call(value);
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in #local4#set.call(0);
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in #local6#set.call(0);
 }
 static method methodCompound() → dynamic {
   final core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t36 = local4 in #t36.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t36{core::int};
-  function #local4#set(core::int #t37) → dynamic
-    if(local4.==(null))
-      return local4 = #t37;
-    else
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t27) → dynamic
+    if(#local4#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'local4' has already been initialized.");
+    else {
+      #local4#isSet = true;
+      return local4 = #t27;
+    }
   #local4#set.call(0);
-  let final<BottomType> #t38 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in #local4#set.call(#local4#get.call().{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
index 94edad5..2ebcbaf 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -134,19 +134,19 @@
   let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
   let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
   let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -219,7 +219,7 @@
   local3 = (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 };
@@ -261,19 +261,19 @@
   let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
   let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
   let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -346,7 +346,7 @@
   local3 = (let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
index 94edad5..2ebcbaf 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -134,19 +134,19 @@
   let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
   let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
   let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -219,7 +219,7 @@
   local3 = (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 };
@@ -261,19 +261,19 @@
   let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
   let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
   let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -346,7 +346,7 @@
   local3 = (let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
index 94edad5..bc917d2 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -108,16 +108,22 @@
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t2 = local4 in #t2.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    return local4 = #t3;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t2) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t2;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = local6 in #t4.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    return local6 = #t5;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t3) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t3;
+  }
   T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -127,26 +133,26 @@
     }
     return local7{T%};
   }
-  function #local7#set(T% #t6) → dynamic {
+  function #local7#set(T% #t4) → dynamic {
     #local7#isSet = true;
-    return local7 = #t6;
+    return local7 = #t4;
   }
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -157,22 +163,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} local2{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(T% #t13) → dynamic {
+  function #local2#set(T% #t11) → dynamic {
     #local2#isSet = true;
-    return local2 = #t13;
+    return local2 = #t11;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t14 = local4 in #t14.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t14{core::int};
-  function #local4#set(core::int #t15) → dynamic
-    return local4 = #t15;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t12) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t12;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t16 = local6 in #t16.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t16{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t17) → dynamic
-    return local6 = #t17;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t13) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t13;
+  }
   T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -182,9 +194,9 @@
     }
     return local7{T%};
   }
-  function #local7#set(T% #t18) → dynamic {
+  function #local7#set(T% #t14) → dynamic {
     #local7#isSet = true;
-    return local7 = #t18;
+    return local7 = #t14;
   }
   if(b) {
     local1 = value;
@@ -195,15 +207,15 @@
     #local6#set.call(0);
     #local7#get.call();
   }
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:90:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:90:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
   #local2#get.call();
-  let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:92:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:92:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
   #local4#get.call();
-  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:94:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:94:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
   #local6#get.call();
@@ -212,14 +224,17 @@
 static field () → core::Null? fieldCompound = () → core::Null? {
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t22 = local4 in #t22.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t22{core::int};
-  function #local4#set(core::int #t23) → dynamic
-    return local4 = #t23;
-  local3 = (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t18) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t18;
+  }
+  local3 = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 };
@@ -229,22 +244,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} local2{self::methodDirect::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodDirect::T% #t26) → dynamic {
+  function #local2#set(self::methodDirect::T% #t21) → dynamic {
     #local2#isSet = true;
-    return local2 = #t26;
+    return local2 = #t21;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t27 = local4 in #t27.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t27{core::int};
-  function #local4#set(core::int #t28) → dynamic
-    return local4 = #t28;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t22) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t22;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t29 = local6 in #t29.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t29{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t30) → dynamic
-    return local6 = #t30;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t23) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t23;
+  }
   self::methodDirect::T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → self::methodDirect::T% {
@@ -254,26 +275,26 @@
     }
     return local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t31) → dynamic {
+  function #local7#set(self::methodDirect::T% #t24) → dynamic {
     #local7#isSet = true;
-    return local7 = #t31;
+    return local7 = #t24;
   }
-  let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
-  let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -284,22 +305,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} local2{self::methodConditional::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodConditional::T% #t38) → dynamic {
+  function #local2#set(self::methodConditional::T% #t31) → dynamic {
     #local2#isSet = true;
-    return local2 = #t38;
+    return local2 = #t31;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t39 = local4 in #t39.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t39{core::int};
-  function #local4#set(core::int #t40) → dynamic
-    return local4 = #t40;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t32) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t32;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t41 = local6 in #t41.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t41{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t42) → dynamic
-    return local6 = #t42;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t33) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t33;
+  }
   self::methodConditional::T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → self::methodConditional::T% {
@@ -309,9 +336,9 @@
     }
     return local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t43) → dynamic {
+  function #local7#set(self::methodConditional::T% #t34) → dynamic {
     #local7#isSet = true;
-    return local7 = #t43;
+    return local7 = #t34;
   }
   if(b) {
     local1 = value;
@@ -322,15 +349,15 @@
     #local6#set.call(0);
     #local7#set.call(value);
   }
-  let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:62:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:62:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
   #local2#get.call();
-  let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:64:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:64:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
   #local4#get.call();
-  let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:66:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:66:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
   #local6#get.call();
@@ -339,14 +366,17 @@
 static method methodCompound() → dynamic {
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t47 = local4 in #t47.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t47{core::int};
-  function #local4#set(core::int #t48) → dynamic
-    return local4 = #t48;
-  local3 = (let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t38) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t38;
+  }
+  local3 = (let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
index 94edad5..bc917d2 100644
--- a/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/definitely_unassigned.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -108,16 +108,22 @@
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t2 = local4 in #t2.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t2{core::int};
-  function #local4#set(core::int #t3) → dynamic
-    return local4 = #t3;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t2) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t2;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t4 = local6 in #t4.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t4{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t5) → dynamic
-    return local6 = #t5;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t3) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t3;
+  }
   T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -127,26 +133,26 @@
     }
     return local7{T%};
   }
-  function #local7#set(T% #t6) → dynamic {
+  function #local7#set(T% #t4) → dynamic {
     #local7#isSet = true;
-    return local7 = #t6;
+    return local7 = #t4;
   }
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -157,22 +163,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → T%
     return #local2#isSet ?{T%} local2{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(T% #t13) → dynamic {
+  function #local2#set(T% #t11) → dynamic {
     #local2#isSet = true;
-    return local2 = #t13;
+    return local2 = #t11;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t14 = local4 in #t14.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t14{core::int};
-  function #local4#set(core::int #t15) → dynamic
-    return local4 = #t15;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t12) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t12;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t16 = local6 in #t16.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t16{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t17) → dynamic
-    return local6 = #t17;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t13) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t13;
+  }
   T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → T% {
@@ -182,9 +194,9 @@
     }
     return local7{T%};
   }
-  function #local7#set(T% #t18) → dynamic {
+  function #local7#set(T% #t14) → dynamic {
     #local7#isSet = true;
-    return local7 = #t18;
+    return local7 = #t14;
   }
   if(b) {
     local1 = value;
@@ -195,15 +207,15 @@
     #local6#set.call(0);
     #local7#get.call();
   }
-  let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:90:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:90:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
   #local2#get.call();
-  let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:92:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:92:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
   #local4#get.call();
-  let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:94:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:94:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
   #local6#get.call();
@@ -212,14 +224,17 @@
 static field () → core::Null? fieldCompound = () → core::Null? {
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t22 = local4 in #t22.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t22{core::int};
-  function #local4#set(core::int #t23) → dynamic
-    return local4 = #t23;
-  local3 = (let final<BottomType> #t24 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t18) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t18;
+  }
+  local3 = (let final<BottomType> #t19 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 };
@@ -229,22 +244,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodDirect::T%
     return #local2#isSet ?{self::methodDirect::T%} local2{self::methodDirect::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodDirect::T% #t26) → dynamic {
+  function #local2#set(self::methodDirect::T% #t21) → dynamic {
     #local2#isSet = true;
-    return local2 = #t26;
+    return local2 = #t21;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t27 = local4 in #t27.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t27{core::int};
-  function #local4#set(core::int #t28) → dynamic
-    return local4 = #t28;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t22) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t22;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t29 = local6 in #t29.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t29{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t30) → dynamic
-    return local6 = #t30;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t23) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t23;
+  }
   self::methodDirect::T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → self::methodDirect::T% {
@@ -254,26 +275,26 @@
     }
     return local7{self::methodDirect::T%};
   }
-  function #local7#set(self::methodDirect::T% #t31) → dynamic {
+  function #local7#set(self::methodDirect::T% #t24) → dynamic {
     #local7#isSet = true;
-    return local7 = #t31;
+    return local7 = #t24;
   }
-  let final<BottomType> #t32 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t33 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t26 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in #local2#get.call();
-  let final<BottomType> #t34 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t27 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t28 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in #local4#get.call();
-  let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t29 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t30 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in #local6#get.call();
   #local7#get.call();
@@ -284,22 +305,28 @@
   core::bool #local2#isSet = false;
   function #local2#get() → self::methodConditional::T%
     return #local2#isSet ?{self::methodConditional::T%} local2{self::methodConditional::T%} : throw new _in::LateInitializationErrorImpl::•("Local 'local2' has not been initialized.");
-  function #local2#set(self::methodConditional::T% #t38) → dynamic {
+  function #local2#set(self::methodConditional::T% #t31) → dynamic {
     #local2#isSet = true;
-    return local2 = #t38;
+    return local2 = #t31;
   }
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t39 = local4 in #t39.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t39{core::int};
-  function #local4#set(core::int #t40) → dynamic
-    return local4 = #t40;
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t32) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t32;
+  }
   FutureOr<core::int>local5;
   FutureOr<core::int>? local6;
+  core::bool #local6#isSet = false;
   function #local6#get() → FutureOr<core::int>
-    return let final FutureOr<core::int>? #t41 = local6 in #t41.==(null) ?{FutureOr<core::int>} throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.") : #t41{FutureOr<core::int>};
-  function #local6#set(FutureOr<core::int>#t42) → dynamic
-    return local6 = #t42;
+    return #local6#isSet ?{FutureOr<core::int>} local6{FutureOr<core::int>} : throw new _in::LateInitializationErrorImpl::•("Local 'local6' has not been initialized.");
+  function #local6#set(FutureOr<core::int>#t33) → dynamic {
+    #local6#isSet = true;
+    return local6 = #t33;
+  }
   self::methodConditional::T? local7;
   core::bool #local7#isSet = false;
   function #local7#get() → self::methodConditional::T% {
@@ -309,9 +336,9 @@
     }
     return local7{self::methodConditional::T%};
   }
-  function #local7#set(self::methodConditional::T% #t43) → dynamic {
+  function #local7#set(self::methodConditional::T% #t34) → dynamic {
     #local7#isSet = true;
-    return local7 = #t43;
+    return local7 = #t34;
   }
   if(b) {
     local1 = value;
@@ -322,15 +349,15 @@
     #local6#set.call(0);
     #local7#set.call(value);
   }
-  let final<BottomType> #t44 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:62:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
+  let final<BottomType> #t35 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:62:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
   #local2#get.call();
-  let final<BottomType> #t45 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:64:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+  let final<BottomType> #t36 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:64:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
   #local4#get.call();
-  let final<BottomType> #t46 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:66:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
+  let final<BottomType> #t37 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:66:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
   #local6#get.call();
@@ -339,14 +366,17 @@
 static method methodCompound() → dynamic {
   core::int local3;
   core::int? local4;
+  core::bool #local4#isSet = false;
   function #local4#get() → core::int
-    return let final core::int? #t47 = local4 in #t47.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.") : #t47{core::int};
-  function #local4#set(core::int #t48) → dynamic
-    return local4 = #t48;
-  local3 = (let final<BottomType> #t49 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
+    return #local4#isSet ?{core::int} local4{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local4' has not been initialized.");
+  function #local4#set(core::int #t38) → dynamic {
+    #local4#isSet = true;
+    return local4 = #t38;
+  }
+  local3 = (let final<BottomType> #t39 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  #local4#set.call((let final<BottomType> #t50 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  #local4#set.call((let final<BottomType> #t40 = invalid-expression "pkg/front_end/testcases/late_lowering/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in #local4#get.call()).{core::num::+}(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart
new file mode 100644
index 0000000..90ac015
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  late int property4; // ok
+
+  late int? property5; // ok
+
+  covariant late int property6; // ok
+
+  A(this.property4, this.property5, this.property6);
+}
+
+abstract class B1 {
+  late final int property4;
+
+  late final int property5;
+
+  late final int? property6;
+
+  B1(this.property4, this.property5, this.property6);
+}
+
+abstract class B2 implements B1 {
+  void set property4(int i); // ok
+
+  void set property5(int? i); // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  void set property6(int i); // error
+}
+
+abstract class C1 {
+  late int property4;
+
+  late int property5;
+
+  late int property6;
+
+  C1(this.property4, this.property5, this.property6);
+}
+
+abstract class C2 implements C1 {
+  int get property4; // ok
+
+  int get property5; // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  int? get property6; // error
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect
new file mode 100644
index 0000000..7c87b5f
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.outline.expect
@@ -0,0 +1,94 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
+// Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
+//   void set property6(int i); // error
+//                          ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the overridden method ('property6').
+//   late final int? property6;
+//                   ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int? _#A#property4;
+  field core::int? _#A#property5;
+  field core::bool _#A#property5#isSet;
+  field core::int? _#A#property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    ;
+  get property4() → core::int;
+  set property4(core::int #t1) → void;
+  get property5() → core::int?;
+  set property5(core::int? #t2) → void;
+  get property6() → core::int;
+  set property6(covariant core::int #t3) → void;
+}
+abstract class B1 extends core::Object {
+  field core::int? _#B1#property4;
+  field core::int? _#B1#property5;
+  field core::int? _#B1#property6;
+  field core::bool _#B1#property6#isSet;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    ;
+  get property4() → core::int;
+  set property4(core::int #t4) → void;
+  get property5() → core::int;
+  set property5(core::int #t5) → void;
+  get property6() → core::int?;
+  set property6(core::int? #t6) → void;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int? _#C1#property4;
+  field core::int? _#C1#property5;
+  field core::int? _#C1#property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    ;
+  get property4() → core::int;
+  set property4(core::int #t7) → void;
+  get property5() → core::int;
+  set property5(core::int #t8) → void;
+  get property6() → core::int;
+  set property6(core::int #t9) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
new file mode 100644
index 0000000..9248820
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.expect
@@ -0,0 +1,130 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
+// Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
+//   void set property6(int i); // error
+//                          ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the overridden method ('property6').
+//   late final int? property6;
+//                   ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#property4 = null;
+  field core::int? _#A#property5 = null;
+  field core::bool _#A#property5#isSet = false;
+  field core::int? _#A#property6 = null;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::_#A#property4 = property4, self::A::_#A#property5#isSet = true, self::A::_#A#property5 = property5, self::A::_#A#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t1 = this.{self::A::_#A#property4} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t1{core::int};
+  set property4(core::int #t2) → void
+    this.{self::A::_#A#property4} = #t2;
+  get property5() → core::int?
+    return this.{self::A::_#A#property5#isSet} ?{core::int?} this.{self::A::_#A#property5} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int? #t3) → void {
+    this.{self::A::_#A#property5#isSet} = true;
+    this.{self::A::_#A#property5} = #t3;
+  }
+  get property6() → core::int
+    return let final core::int? #t4 = this.{self::A::_#A#property6} in #t4.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.") : #t4{core::int};
+  set property6(covariant core::int #t5) → void
+    this.{self::A::_#A#property6} = #t5;
+}
+abstract class B1 extends core::Object {
+  field core::int? _#B1#property4 = null;
+  field core::int? _#B1#property5 = null;
+  field core::int? _#B1#property6 = null;
+  field core::bool _#B1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::_#B1#property4 = property4, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t6 = this.{self::B1::_#B1#property4} in #t6.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t6{core::int};
+  set property4(core::int #t7) → void
+    if(this.{self::B1::_#B1#property4}.==(null))
+      this.{self::B1::_#B1#property4} = #t7;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'property4' has already been initialized.");
+  get property5() → core::int
+    return let final core::int? #t8 = this.{self::B1::_#B1#property5} in #t8.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.") : #t8{core::int};
+  set property5(core::int #t9) → void
+    if(this.{self::B1::_#B1#property5}.==(null))
+      this.{self::B1::_#B1#property5} = #t9;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'property5' has already been initialized.");
+  get property6() → core::int?
+    return this.{self::B1::_#B1#property6#isSet} ?{core::int?} this.{self::B1::_#B1#property6} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int? #t10) → void
+    if(this.{self::B1::_#B1#property6#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property6' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property6#isSet} = true;
+      this.{self::B1::_#B1#property6} = #t10;
+    }
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int? _#C1#property4 = null;
+  field core::int? _#C1#property5 = null;
+  field core::int? _#C1#property6 = null;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::_#C1#property4 = property4, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t11 = this.{self::C1::_#C1#property4} in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t11{core::int};
+  set property4(core::int #t12) → void
+    this.{self::C1::_#C1#property4} = #t12;
+  get property5() → core::int
+    return let final core::int? #t13 = this.{self::C1::_#C1#property5} in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.") : #t13{core::int};
+  set property5(core::int #t14) → void
+    this.{self::C1::_#C1#property5} = #t14;
+  get property6() → core::int
+    return let final core::int? #t15 = this.{self::C1::_#C1#property6} in #t15.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.") : #t15{core::int};
+  set property6(core::int #t16) → void
+    this.{self::C1::_#C1#property6} = #t16;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..9248820
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.strong.transformed.expect
@@ -0,0 +1,130 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
+// Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
+//   void set property6(int i); // error
+//                          ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the overridden method ('property6').
+//   late final int? property6;
+//                   ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#property4 = null;
+  field core::int? _#A#property5 = null;
+  field core::bool _#A#property5#isSet = false;
+  field core::int? _#A#property6 = null;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::_#A#property4 = property4, self::A::_#A#property5#isSet = true, self::A::_#A#property5 = property5, self::A::_#A#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t1 = this.{self::A::_#A#property4} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t1{core::int};
+  set property4(core::int #t2) → void
+    this.{self::A::_#A#property4} = #t2;
+  get property5() → core::int?
+    return this.{self::A::_#A#property5#isSet} ?{core::int?} this.{self::A::_#A#property5} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int? #t3) → void {
+    this.{self::A::_#A#property5#isSet} = true;
+    this.{self::A::_#A#property5} = #t3;
+  }
+  get property6() → core::int
+    return let final core::int? #t4 = this.{self::A::_#A#property6} in #t4.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.") : #t4{core::int};
+  set property6(covariant core::int #t5) → void
+    this.{self::A::_#A#property6} = #t5;
+}
+abstract class B1 extends core::Object {
+  field core::int? _#B1#property4 = null;
+  field core::int? _#B1#property5 = null;
+  field core::int? _#B1#property6 = null;
+  field core::bool _#B1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::_#B1#property4 = property4, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t6 = this.{self::B1::_#B1#property4} in #t6.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t6{core::int};
+  set property4(core::int #t7) → void
+    if(this.{self::B1::_#B1#property4}.==(null))
+      this.{self::B1::_#B1#property4} = #t7;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'property4' has already been initialized.");
+  get property5() → core::int
+    return let final core::int? #t8 = this.{self::B1::_#B1#property5} in #t8.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.") : #t8{core::int};
+  set property5(core::int #t9) → void
+    if(this.{self::B1::_#B1#property5}.==(null))
+      this.{self::B1::_#B1#property5} = #t9;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'property5' has already been initialized.");
+  get property6() → core::int?
+    return this.{self::B1::_#B1#property6#isSet} ?{core::int?} this.{self::B1::_#B1#property6} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int? #t10) → void
+    if(this.{self::B1::_#B1#property6#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property6' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property6#isSet} = true;
+      this.{self::B1::_#B1#property6} = #t10;
+    }
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int? _#C1#property4 = null;
+  field core::int? _#C1#property5 = null;
+  field core::int? _#C1#property6 = null;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::_#C1#property4 = property4, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return let final core::int? #t11 = this.{self::C1::_#C1#property4} in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.") : #t11{core::int};
+  set property4(core::int #t12) → void
+    this.{self::C1::_#C1#property4} = #t12;
+  get property5() → core::int
+    return let final core::int? #t13 = this.{self::C1::_#C1#property5} in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.") : #t13{core::int};
+  set property5(core::int #t14) → void
+    this.{self::C1::_#C1#property5} = #t14;
+  get property6() → core::int
+    return let final core::int? #t15 = this.{self::C1::_#C1#property6} in #t15.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.") : #t15{core::int};
+  set property6(core::int #t16) → void
+    this.{self::C1::_#C1#property6} = #t16;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect
new file mode 100644
index 0000000..2045647
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.textual_outline.expect
@@ -0,0 +1,39 @@
+abstract class A {
+  late int ;
+  property4;
+  late int;
+  operator? (){}
+  property5;
+  covariant late int ;
+  property6;
+  A(this.property4, this.property5, this.property6);
+}
+abstract class B1 {
+  late ;
+  final int property4;
+  late ;
+  final int property5;
+  late ;
+  final int? property6;
+  B1(this.property4, this.property5, this.property6);
+}
+abstract class B2 implements B1 {
+  void set property4(int i);
+  void set property5(int? i);
+  void set property6(int i);
+}
+abstract class C1 {
+  late int ;
+  property4;
+  late int ;
+  property5;
+  late int ;
+  property6;
+  C1(this.property4, this.property5, this.property6);
+}
+abstract class C2 implements C1 {
+  int get property4;
+  int get property5;
+  int? get property6;
+}
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
new file mode 100644
index 0000000..7dd79a4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.expect
@@ -0,0 +1,151 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
+// Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
+//   void set property6(int i); // error
+//                          ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the overridden method ('property6').
+//   late final int? property6;
+//                   ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#property4 = null;
+  field core::bool _#A#property4#isSet = false;
+  field core::int? _#A#property5 = null;
+  field core::bool _#A#property5#isSet = false;
+  field core::int? _#A#property6 = null;
+  field core::bool _#A#property6#isSet = false;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::_#A#property4#isSet = true, self::A::_#A#property4 = property4, self::A::_#A#property5#isSet = true, self::A::_#A#property5 = property5, self::A::_#A#property6#isSet = true, self::A::_#A#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::A::_#A#property4#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#property4} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t2) → void {
+    this.{self::A::_#A#property4#isSet} = true;
+    this.{self::A::_#A#property4} = #t2;
+  }
+  get property5() → core::int?
+    return this.{self::A::_#A#property5#isSet} ?{core::int?} this.{self::A::_#A#property5} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int? #t3) → void {
+    this.{self::A::_#A#property5#isSet} = true;
+    this.{self::A::_#A#property5} = #t3;
+  }
+  get property6() → core::int
+    return this.{self::A::_#A#property6#isSet} ?{core::int} let final core::int? #t4 = this.{self::A::_#A#property6} in #t4{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(covariant core::int #t5) → void {
+    this.{self::A::_#A#property6#isSet} = true;
+    this.{self::A::_#A#property6} = #t5;
+  }
+}
+abstract class B1 extends core::Object {
+  field core::int? _#B1#property4 = null;
+  field core::bool _#B1#property4#isSet = false;
+  field core::int? _#B1#property5 = null;
+  field core::bool _#B1#property5#isSet = false;
+  field core::int? _#B1#property6 = null;
+  field core::bool _#B1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::_#B1#property4#isSet = true, self::B1::_#B1#property4 = property4, self::B1::_#B1#property5#isSet = true, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::B1::_#B1#property4#isSet} ?{core::int} let final core::int? #t6 = this.{self::B1::_#B1#property4} in #t6{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t7) → void
+    if(this.{self::B1::_#B1#property4#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property4' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property4#isSet} = true;
+      this.{self::B1::_#B1#property4} = #t7;
+    }
+  get property5() → core::int
+    return this.{self::B1::_#B1#property5#isSet} ?{core::int} let final core::int? #t8 = this.{self::B1::_#B1#property5} in #t8{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int #t9) → void
+    if(this.{self::B1::_#B1#property5#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property5' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property5#isSet} = true;
+      this.{self::B1::_#B1#property5} = #t9;
+    }
+  get property6() → core::int?
+    return this.{self::B1::_#B1#property6#isSet} ?{core::int?} this.{self::B1::_#B1#property6} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int? #t10) → void
+    if(this.{self::B1::_#B1#property6#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property6' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property6#isSet} = true;
+      this.{self::B1::_#B1#property6} = #t10;
+    }
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int? _#C1#property4 = null;
+  field core::bool _#C1#property4#isSet = false;
+  field core::int? _#C1#property5 = null;
+  field core::bool _#C1#property5#isSet = false;
+  field core::int? _#C1#property6 = null;
+  field core::bool _#C1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::_#C1#property4#isSet = true, self::C1::_#C1#property4 = property4, self::C1::_#C1#property5#isSet = true, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6#isSet = true, self::C1::_#C1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::C1::_#C1#property4#isSet} ?{core::int} let final core::int? #t11 = this.{self::C1::_#C1#property4} in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t12) → void {
+    this.{self::C1::_#C1#property4#isSet} = true;
+    this.{self::C1::_#C1#property4} = #t12;
+  }
+  get property5() → core::int
+    return this.{self::C1::_#C1#property5#isSet} ?{core::int} let final core::int? #t13 = this.{self::C1::_#C1#property5} in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int #t14) → void {
+    this.{self::C1::_#C1#property5#isSet} = true;
+    this.{self::C1::_#C1#property5} = #t14;
+  }
+  get property6() → core::int
+    return this.{self::C1::_#C1#property6#isSet} ?{core::int} let final core::int? #t15 = this.{self::C1::_#C1#property6} in #t15{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int #t16) → void {
+    this.{self::C1::_#C1#property6#isSet} = true;
+    this.{self::C1::_#C1#property6} = #t16;
+  }
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..7dd79a4
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart.weak.transformed.expect
@@ -0,0 +1,151 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:26: Error: The parameter 'i' of the method 'B2.property6' has type 'int', which does not match the corresponding type, 'int?', in the overridden method, 'B1.property6'.
+// Change to a supertype of 'int?', or, for a covariant parameter, a subtype.
+//   void set property6(int i); // error
+//                          ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the overridden method ('property6').
+//   late final int? property6;
+//                   ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:32:12: Error: The type 'int?' of the inherited getter 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:20:19: Context: This is the declaration of the getter 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:52:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/late_lowering/getter_vs_setter_type.dart:40:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+abstract class A extends core::Object {
+  field core::int? _#A#property4 = null;
+  field core::bool _#A#property4#isSet = false;
+  field core::int? _#A#property5 = null;
+  field core::bool _#A#property5#isSet = false;
+  field core::int? _#A#property6 = null;
+  field core::bool _#A#property6#isSet = false;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::_#A#property4#isSet = true, self::A::_#A#property4 = property4, self::A::_#A#property5#isSet = true, self::A::_#A#property5 = property5, self::A::_#A#property6#isSet = true, self::A::_#A#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::A::_#A#property4#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#property4} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t2) → void {
+    this.{self::A::_#A#property4#isSet} = true;
+    this.{self::A::_#A#property4} = #t2;
+  }
+  get property5() → core::int?
+    return this.{self::A::_#A#property5#isSet} ?{core::int?} this.{self::A::_#A#property5} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int? #t3) → void {
+    this.{self::A::_#A#property5#isSet} = true;
+    this.{self::A::_#A#property5} = #t3;
+  }
+  get property6() → core::int
+    return this.{self::A::_#A#property6#isSet} ?{core::int} let final core::int? #t4 = this.{self::A::_#A#property6} in #t4{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(covariant core::int #t5) → void {
+    this.{self::A::_#A#property6#isSet} = true;
+    this.{self::A::_#A#property6} = #t5;
+  }
+}
+abstract class B1 extends core::Object {
+  field core::int? _#B1#property4 = null;
+  field core::bool _#B1#property4#isSet = false;
+  field core::int? _#B1#property5 = null;
+  field core::bool _#B1#property5#isSet = false;
+  field core::int? _#B1#property6 = null;
+  field core::bool _#B1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::_#B1#property4#isSet = true, self::B1::_#B1#property4 = property4, self::B1::_#B1#property5#isSet = true, self::B1::_#B1#property5 = property5, self::B1::_#B1#property6#isSet = true, self::B1::_#B1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::B1::_#B1#property4#isSet} ?{core::int} let final core::int? #t6 = this.{self::B1::_#B1#property4} in #t6{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t7) → void
+    if(this.{self::B1::_#B1#property4#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property4' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property4#isSet} = true;
+      this.{self::B1::_#B1#property4} = #t7;
+    }
+  get property5() → core::int
+    return this.{self::B1::_#B1#property5#isSet} ?{core::int} let final core::int? #t8 = this.{self::B1::_#B1#property5} in #t8{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int #t9) → void
+    if(this.{self::B1::_#B1#property5#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property5' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property5#isSet} = true;
+      this.{self::B1::_#B1#property5} = #t9;
+    }
+  get property6() → core::int?
+    return this.{self::B1::_#B1#property6#isSet} ?{core::int?} this.{self::B1::_#B1#property6} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int? #t10) → void
+    if(this.{self::B1::_#B1#property6#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'property6' has already been initialized.");
+    else {
+      this.{self::B1::_#B1#property6#isSet} = true;
+      this.{self::B1::_#B1#property6} = #t10;
+    }
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int? _#C1#property4 = null;
+  field core::bool _#C1#property4#isSet = false;
+  field core::int? _#C1#property5 = null;
+  field core::bool _#C1#property5#isSet = false;
+  field core::int? _#C1#property6 = null;
+  field core::bool _#C1#property6#isSet = false;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::_#C1#property4#isSet = true, self::C1::_#C1#property4 = property4, self::C1::_#C1#property5#isSet = true, self::C1::_#C1#property5 = property5, self::C1::_#C1#property6#isSet = true, self::C1::_#C1#property6 = property6, super core::Object::•()
+    ;
+  get property4() → core::int
+    return this.{self::C1::_#C1#property4#isSet} ?{core::int} let final core::int? #t11 = this.{self::C1::_#C1#property4} in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property4' has not been initialized.");
+  set property4(core::int #t12) → void {
+    this.{self::C1::_#C1#property4#isSet} = true;
+    this.{self::C1::_#C1#property4} = #t12;
+  }
+  get property5() → core::int
+    return this.{self::C1::_#C1#property5#isSet} ?{core::int} let final core::int? #t13 = this.{self::C1::_#C1#property5} in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property5' has not been initialized.");
+  set property5(core::int #t14) → void {
+    this.{self::C1::_#C1#property5#isSet} = true;
+    this.{self::C1::_#C1#property5} = #t14;
+  }
+  get property6() → core::int
+    return this.{self::C1::_#C1#property6#isSet} ?{core::int} let final core::int? #t15 = this.{self::C1::_#C1#property6} in #t15{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'property6' has not been initialized.");
+  set property6(core::int #t16) → void {
+    this.{self::C1::_#C1#property6#isSet} = true;
+    this.{self::C1::_#C1#property6} = #t16;
+  }
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
index 4c0d317..6dffe96 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.expect
@@ -7,9 +7,12 @@
   return t;
 static method main() → dynamic {
   core::int? local;
+  core::bool #local#isSet = false;
   function #local#get() → core::int
-    return let final core::int? #t1 = local in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t1{core::int};
-  function #local#set(core::int #t2) → dynamic
-    return local = #t2;
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t1) → dynamic {
+    #local#isSet = true;
+    return local = #t1;
+  }
   #local#set.call(self::f<core::int>(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
index 4c0d317..6dffe96 100644
--- a/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/infer_from_late_variable.dart.weak.transformed.expect
@@ -7,9 +7,12 @@
   return t;
 static method main() → dynamic {
   core::int? local;
+  core::bool #local#isSet = false;
   function #local#get() → core::int
-    return let final core::int? #t1 = local in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t1{core::int};
-  function #local#set(core::int #t2) → dynamic
-    return local = #t2;
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t1) → dynamic {
+    #local#isSet = true;
+    return local = #t1;
+  }
   #local#set.call(self::f<core::int>(0));
 }
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
index 1edfa3c..8784442 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.expect
@@ -6,19 +6,29 @@
 class Class extends core::Object {
   static field core::int nonNullableStaticFieldReads = 0;
   static field core::int? _#nonNullableStaticField = null;
+  static field core::bool _#nonNullableStaticField#isSet = false;
   static field core::int nullableStaticFieldReads = 0;
   static field core::int? _#nullableStaticField = null;
   static field core::bool _#nullableStaticField#isSet = false;
   field core::int nonNullableInstanceFieldReads = 0;
   field core::int? _#Class#nonNullableInstanceField = null;
+  field core::bool _#Class#nonNullableInstanceField#isSet = false;
   field core::int nullableInstanceFieldReads = 0;
   field core::int? _#Class#nullableInstanceField = null;
   field core::bool _#Class#nullableInstanceField#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-  static get nonNullableStaticField() → core::int
-    return let final core::int? #t1 = self::Class::_#nonNullableStaticField in #t1.==(null) ?{core::int} let final core::int #t2 = (let final core::int #t3 = self::Class::nonNullableStaticFieldReads in let final core::int #t4 = self::Class::nonNullableStaticFieldReads = #t3.{core::num::+}(1) in #t3).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticField.{core::num::+}(1) : 0 in self::Class::_#nonNullableStaticField.==(null) ?{core::int} self::Class::_#nonNullableStaticField = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.") : #t1{core::int};
+  static get nonNullableStaticField() → core::int {
+    if(!self::Class::_#nonNullableStaticField#isSet) {
+      final core::int #t1 = (let final core::int #t2 = self::Class::nonNullableStaticFieldReads in let final core::int #t3 = self::Class::nonNullableStaticFieldReads = #t2.{core::num::+}(1) in #t2).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticField.{core::num::+}(1) : 0;
+      if(self::Class::_#nonNullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticField = #t1;
+      self::Class::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticField in #t4{core::int};
+  }
   static get nullableStaticField() → core::int? {
     if(!self::Class::_#nullableStaticField#isSet) {
       final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int} self::Class::nullableStaticField.{core::Object::hashCode} : 0;
@@ -29,8 +39,16 @@
     }
     return self::Class::_#nullableStaticField;
   }
-  get nonNullableInstanceField() → core::int
-    return let final core::int? #t8 = this.{self::Class::_#Class#nonNullableInstanceField} in #t8.==(null) ?{core::int} let final core::int #t9 = (let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t11 = this.{self::Class::nonNullableInstanceFieldReads} = #t10.{core::num::+}(1) in #t10).{core::num::==}(0) ?{core::int} this.{self::Class::nonNullableInstanceField}.{core::num::+}(1) : 0 in this.{self::Class::_#Class#nonNullableInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#nonNullableInstanceField} = #t9 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.") : #t8{core::int};
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#nonNullableInstanceField#isSet}) {
+      final core::int #t8 = (let final core::int #t9 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} = #t9.{core::num::+}(1) in #t9).{core::num::==}(0) ?{core::int} this.{self::Class::nonNullableInstanceField}.{core::num::+}(1) : 0;
+      if(this.{self::Class::_#Class#nonNullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nonNullableInstanceField} = #t8;
+      this.{self::Class::_#Class#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::Class::_#Class#nonNullableInstanceField} in #t11{core::int};
+  }
   get nullableInstanceField() → core::int? {
     if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
       final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int} this.{self::Class::nullableInstanceField}.{core::Object::hashCode} : 0;
@@ -44,11 +62,20 @@
 }
 static field core::int nonNullableTopLevelFieldReads = 0;
 static field core::int? _#nonNullableTopLevelField = null;
+static field core::bool _#nonNullableTopLevelField#isSet = false;
 static field core::int nullableTopLevelFieldReads = 0;
 static field core::int? _#nullableTopLevelField = null;
 static field core::bool _#nullableTopLevelField#isSet = false;
-static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t15 = self::_#nonNullableTopLevelField in #t15.==(null) ?{core::int} let final core::int #t16 = (let final core::int #t17 = self::nonNullableTopLevelFieldReads in let final core::int #t18 = self::nonNullableTopLevelFieldReads = #t17.{core::num::+}(1) in #t17).{core::num::==}(0) ?{core::int} self::nonNullableTopLevelField.{core::num::+}(1) : 0 in self::_#nonNullableTopLevelField.==(null) ?{core::int} self::_#nonNullableTopLevelField = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.") : #t15{core::int};
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    final core::int #t15 = (let final core::int #t16 = self::nonNullableTopLevelFieldReads in let final core::int #t17 = self::nonNullableTopLevelFieldReads = #t16.{core::num::+}(1) in #t16).{core::num::==}(0) ?{core::int} self::nonNullableTopLevelField.{core::num::+}(1) : 0;
+    if(self::_#nonNullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.");
+    self::_#nonNullableTopLevelField = #t15;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t18 = self::_#nonNullableTopLevelField in #t18{core::int};
+}
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int} self::nullableTopLevelField.{core::Object::hashCode} : 0;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
index 1edfa3c..8784442 100644
--- a/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite.dart.weak.transformed.expect
@@ -6,19 +6,29 @@
 class Class extends core::Object {
   static field core::int nonNullableStaticFieldReads = 0;
   static field core::int? _#nonNullableStaticField = null;
+  static field core::bool _#nonNullableStaticField#isSet = false;
   static field core::int nullableStaticFieldReads = 0;
   static field core::int? _#nullableStaticField = null;
   static field core::bool _#nullableStaticField#isSet = false;
   field core::int nonNullableInstanceFieldReads = 0;
   field core::int? _#Class#nonNullableInstanceField = null;
+  field core::bool _#Class#nonNullableInstanceField#isSet = false;
   field core::int nullableInstanceFieldReads = 0;
   field core::int? _#Class#nullableInstanceField = null;
   field core::bool _#Class#nullableInstanceField#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-  static get nonNullableStaticField() → core::int
-    return let final core::int? #t1 = self::Class::_#nonNullableStaticField in #t1.==(null) ?{core::int} let final core::int #t2 = (let final core::int #t3 = self::Class::nonNullableStaticFieldReads in let final core::int #t4 = self::Class::nonNullableStaticFieldReads = #t3.{core::num::+}(1) in #t3).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticField.{core::num::+}(1) : 0 in self::Class::_#nonNullableStaticField.==(null) ?{core::int} self::Class::_#nonNullableStaticField = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.") : #t1{core::int};
+  static get nonNullableStaticField() → core::int {
+    if(!self::Class::_#nonNullableStaticField#isSet) {
+      final core::int #t1 = (let final core::int #t2 = self::Class::nonNullableStaticFieldReads in let final core::int #t3 = self::Class::nonNullableStaticFieldReads = #t2.{core::num::+}(1) in #t2).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticField.{core::num::+}(1) : 0;
+      if(self::Class::_#nonNullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticField = #t1;
+      self::Class::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticField in #t4{core::int};
+  }
   static get nullableStaticField() → core::int? {
     if(!self::Class::_#nullableStaticField#isSet) {
       final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int} self::Class::nullableStaticField.{core::Object::hashCode} : 0;
@@ -29,8 +39,16 @@
     }
     return self::Class::_#nullableStaticField;
   }
-  get nonNullableInstanceField() → core::int
-    return let final core::int? #t8 = this.{self::Class::_#Class#nonNullableInstanceField} in #t8.==(null) ?{core::int} let final core::int #t9 = (let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t11 = this.{self::Class::nonNullableInstanceFieldReads} = #t10.{core::num::+}(1) in #t10).{core::num::==}(0) ?{core::int} this.{self::Class::nonNullableInstanceField}.{core::num::+}(1) : 0 in this.{self::Class::_#Class#nonNullableInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#nonNullableInstanceField} = #t9 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.") : #t8{core::int};
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#nonNullableInstanceField#isSet}) {
+      final core::int #t8 = (let final core::int #t9 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} = #t9.{core::num::+}(1) in #t9).{core::num::==}(0) ?{core::int} this.{self::Class::nonNullableInstanceField}.{core::num::+}(1) : 0;
+      if(this.{self::Class::_#Class#nonNullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nonNullableInstanceField} = #t8;
+      this.{self::Class::_#Class#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::Class::_#Class#nonNullableInstanceField} in #t11{core::int};
+  }
   get nullableInstanceField() → core::int? {
     if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
       final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int} this.{self::Class::nullableInstanceField}.{core::Object::hashCode} : 0;
@@ -44,11 +62,20 @@
 }
 static field core::int nonNullableTopLevelFieldReads = 0;
 static field core::int? _#nonNullableTopLevelField = null;
+static field core::bool _#nonNullableTopLevelField#isSet = false;
 static field core::int nullableTopLevelFieldReads = 0;
 static field core::int? _#nullableTopLevelField = null;
 static field core::bool _#nullableTopLevelField#isSet = false;
-static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t15 = self::_#nonNullableTopLevelField in #t15.==(null) ?{core::int} let final core::int #t16 = (let final core::int #t17 = self::nonNullableTopLevelFieldReads in let final core::int #t18 = self::nonNullableTopLevelFieldReads = #t17.{core::num::+}(1) in #t17).{core::num::==}(0) ?{core::int} self::nonNullableTopLevelField.{core::num::+}(1) : 0 in self::_#nonNullableTopLevelField.==(null) ?{core::int} self::_#nonNullableTopLevelField = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.") : #t15{core::int};
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    final core::int #t15 = (let final core::int #t16 = self::nonNullableTopLevelFieldReads in let final core::int #t17 = self::nonNullableTopLevelFieldReads = #t16.{core::num::+}(1) in #t16).{core::num::==}(0) ?{core::int} self::nonNullableTopLevelField.{core::num::+}(1) : 0;
+    if(self::_#nonNullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.");
+    self::_#nonNullableTopLevelField = #t15;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t18 = self::_#nonNullableTopLevelField in #t18{core::int};
+}
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int} self::nullableTopLevelField.{core::Object::hashCode} : 0;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart
new file mode 100644
index 0000000..2f01985
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'initializer_rewrite_from_opt_out_lib.dart';
+
+int nonNullableTopLevelFieldReads = 0;
+
+late final int nonNullableTopLevelField = nonNullableTopLevelFieldReads++ == 0
+    ? nonNullableTopLevelField
+    : computeInitialValue();
+
+int nullableTopLevelFieldReads = 0;
+
+late final int? nullableTopLevelField = nullableTopLevelFieldReads++ == 0
+    ? nullableTopLevelField
+    : computeInitialValue();
+
+class Class {
+  static int nonNullableStaticFieldReads = 0;
+
+  static late final int nonNullableStaticField =
+      nonNullableStaticFieldReads++ == 0
+          ? nonNullableStaticField
+          : computeInitialValue();
+
+  static int nullableStaticFieldReads = 0;
+
+  static late final int? nullableStaticField = nullableStaticFieldReads++ == 0
+      ? nullableStaticField
+      : computeInitialValue();
+
+  int nonNullableInstanceFieldReads = 0;
+
+  late final int nonNullableInstanceField = nonNullableInstanceFieldReads++ == 0
+      ? nonNullableInstanceField
+      : computeInitialValue();
+
+  int nullableInstanceFieldReads = 0;
+
+  late final int? nullableInstanceField = nullableInstanceFieldReads++ == 0
+      ? nullableInstanceField
+      : computeInitialValue();
+}
+
+void main() {
+  throws(() => nonNullableTopLevelField, "Read nonNullableTopLevelField");
+  throws(() => nullableTopLevelField, "Read nullableTopLevelField");
+  throws(() => Class.nonNullableStaticField, "Read nonNullableStaticField");
+  throws(() => Class.nullableStaticField, "Read nullableStaticField");
+  throws(() => new Class().nonNullableInstanceField,
+      "Read nonNullableInstanceField");
+  throws(() => new Class().nullableInstanceField, "Read nullableInstanceField");
+}
+
+throws(f(), String message) {
+  dynamic value;
+  try {
+    value = f();
+  } on LateInitializationError catch (e) {
+    print(e);
+    return;
+  }
+  throw '$message: $value';
+}
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..db00c38
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.outline.expect
@@ -0,0 +1,49 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///initializer_rewrite_from_opt_out_lib.dart";
+
+class Class extends core::Object {
+  static field core::int nonNullableStaticFieldReads;
+  static field core::int? _#nonNullableStaticField;
+  static field core::int nullableStaticFieldReads;
+  static field core::int? _#nullableStaticField;
+  static field core::bool _#nullableStaticField#isSet;
+  field core::int nonNullableInstanceFieldReads;
+  field core::int? _#Class#nonNullableInstanceField;
+  field core::int nullableInstanceFieldReads;
+  field core::int? _#Class#nullableInstanceField;
+  field core::bool _#Class#nullableInstanceField#isSet;
+  synthetic constructor •() → self::Class
+    ;
+  static get nonNullableStaticField() → core::int;
+  static get nullableStaticField() → core::int?;
+  get nonNullableInstanceField() → core::int;
+  get nullableInstanceField() → core::int?;
+}
+static field core::int nonNullableTopLevelFieldReads;
+static field core::int? _#nonNullableTopLevelField;
+static field core::int nullableTopLevelFieldReads;
+static field core::int? _#nullableTopLevelField;
+static field core::bool _#nullableTopLevelField#isSet;
+static get nonNullableTopLevelField() → core::int;
+static get nullableTopLevelField() → core::int?;
+static method main() → void
+  ;
+static method throws(() → dynamic f, core::String message) → dynamic
+  ;
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as self2;
+import "dart:core" as core;
+
+static method computeInitialValue() → core::int*
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..cc020ed
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.expect
@@ -0,0 +1,97 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "initializer_rewrite_from_opt_out_lib.dart" as ini;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///initializer_rewrite_from_opt_out_lib.dart";
+
+class Class extends core::Object {
+  static field core::int nonNullableStaticFieldReads = 0;
+  static field core::int? _#nonNullableStaticField = null;
+  static field core::int nullableStaticFieldReads = 0;
+  static field core::int? _#nullableStaticField = null;
+  static field core::bool _#nullableStaticField#isSet = false;
+  field core::int nonNullableInstanceFieldReads = 0;
+  field core::int? _#Class#nonNullableInstanceField = null;
+  field core::int nullableInstanceFieldReads = 0;
+  field core::int? _#Class#nullableInstanceField = null;
+  field core::bool _#Class#nullableInstanceField#isSet = false;
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static get nonNullableStaticField() → core::int
+    return let final core::int? #t1 = self::Class::_#nonNullableStaticField in #t1.==(null) ?{core::int} let final core::int #t2 = (let final core::int #t3 = self::Class::nonNullableStaticFieldReads in let final core::int #t4 = self::Class::nonNullableStaticFieldReads = #t3.{core::num::+}(1) in #t3).{core::num::==}(0) ?{core::int*} self::Class::nonNullableStaticField : ini::computeInitialValue() in self::Class::_#nonNullableStaticField.==(null) ?{core::int} self::Class::_#nonNullableStaticField = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.") : #t1{core::int};
+  static get nullableStaticField() → core::int? {
+    if(!self::Class::_#nullableStaticField#isSet) {
+      final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int?} self::Class::nullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
+      self::Class::_#nullableStaticField = #t5;
+      self::Class::_#nullableStaticField#isSet = true;
+    }
+    return self::Class::_#nullableStaticField;
+  }
+  get nonNullableInstanceField() → core::int
+    return let final core::int? #t8 = this.{self::Class::_#Class#nonNullableInstanceField} in #t8.==(null) ?{core::int} let final core::int #t9 = (let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t11 = this.{self::Class::nonNullableInstanceFieldReads} = #t10.{core::num::+}(1) in #t10).{core::num::==}(0) ?{core::int*} this.{self::Class::nonNullableInstanceField} : ini::computeInitialValue() in this.{self::Class::_#Class#nonNullableInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#nonNullableInstanceField} = #t9 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.") : #t8{core::int};
+  get nullableInstanceField() → core::int? {
+    if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
+      final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int?} this.{self::Class::nullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nullableInstanceField} = #t12;
+      this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
+    }
+    return this.{self::Class::_#Class#nullableInstanceField};
+  }
+}
+static field core::int nonNullableTopLevelFieldReads = 0;
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int nullableTopLevelFieldReads = 0;
+static field core::int? _#nullableTopLevelField = null;
+static field core::bool _#nullableTopLevelField#isSet = false;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t15 = self::_#nonNullableTopLevelField in #t15.==(null) ?{core::int} let final core::int #t16 = (let final core::int #t17 = self::nonNullableTopLevelFieldReads in let final core::int #t18 = self::nonNullableTopLevelFieldReads = #t17.{core::num::+}(1) in #t17).{core::num::==}(0) ?{core::int*} self::nonNullableTopLevelField : ini::computeInitialValue() in self::_#nonNullableTopLevelField.==(null) ?{core::int} self::_#nonNullableTopLevelField = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.") : #t15{core::int};
+static get nullableTopLevelField() → core::int? {
+  if(!self::_#nullableTopLevelField#isSet) {
+    final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int?} self::nullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
+    self::_#nullableTopLevelField = #t19;
+    self::_#nullableTopLevelField#isSet = true;
+  }
+  return self::_#nullableTopLevelField;
+}
+static method main() → void {
+  self::throws(() → core::int => self::nonNullableTopLevelField, "Read nonNullableTopLevelField");
+  self::throws(() → core::int? => self::nullableTopLevelField, "Read nullableTopLevelField");
+  self::throws(() → core::int => self::Class::nonNullableStaticField, "Read nonNullableStaticField");
+  self::throws(() → core::int? => self::Class::nullableStaticField, "Read nullableStaticField");
+  self::throws(() → core::int => new self::Class::•().{self::Class::nonNullableInstanceField}, "Read nonNullableInstanceField");
+  self::throws(() → core::int? => new self::Class::•().{self::Class::nullableInstanceField}, "Read nullableInstanceField");
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as ini;
+import "dart:core" as core;
+
+static method computeInitialValue() → core::int*
+  return null;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc020ed
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,97 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "initializer_rewrite_from_opt_out_lib.dart" as ini;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///initializer_rewrite_from_opt_out_lib.dart";
+
+class Class extends core::Object {
+  static field core::int nonNullableStaticFieldReads = 0;
+  static field core::int? _#nonNullableStaticField = null;
+  static field core::int nullableStaticFieldReads = 0;
+  static field core::int? _#nullableStaticField = null;
+  static field core::bool _#nullableStaticField#isSet = false;
+  field core::int nonNullableInstanceFieldReads = 0;
+  field core::int? _#Class#nonNullableInstanceField = null;
+  field core::int nullableInstanceFieldReads = 0;
+  field core::int? _#Class#nullableInstanceField = null;
+  field core::bool _#Class#nullableInstanceField#isSet = false;
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static get nonNullableStaticField() → core::int
+    return let final core::int? #t1 = self::Class::_#nonNullableStaticField in #t1.==(null) ?{core::int} let final core::int #t2 = (let final core::int #t3 = self::Class::nonNullableStaticFieldReads in let final core::int #t4 = self::Class::nonNullableStaticFieldReads = #t3.{core::num::+}(1) in #t3).{core::num::==}(0) ?{core::int*} self::Class::nonNullableStaticField : ini::computeInitialValue() in self::Class::_#nonNullableStaticField.==(null) ?{core::int} self::Class::_#nonNullableStaticField = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.") : #t1{core::int};
+  static get nullableStaticField() → core::int? {
+    if(!self::Class::_#nullableStaticField#isSet) {
+      final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int?} self::Class::nullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
+      self::Class::_#nullableStaticField = #t5;
+      self::Class::_#nullableStaticField#isSet = true;
+    }
+    return self::Class::_#nullableStaticField;
+  }
+  get nonNullableInstanceField() → core::int
+    return let final core::int? #t8 = this.{self::Class::_#Class#nonNullableInstanceField} in #t8.==(null) ?{core::int} let final core::int #t9 = (let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t11 = this.{self::Class::nonNullableInstanceFieldReads} = #t10.{core::num::+}(1) in #t10).{core::num::==}(0) ?{core::int*} this.{self::Class::nonNullableInstanceField} : ini::computeInitialValue() in this.{self::Class::_#Class#nonNullableInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#nonNullableInstanceField} = #t9 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.") : #t8{core::int};
+  get nullableInstanceField() → core::int? {
+    if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
+      final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int?} this.{self::Class::nullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nullableInstanceField} = #t12;
+      this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
+    }
+    return this.{self::Class::_#Class#nullableInstanceField};
+  }
+}
+static field core::int nonNullableTopLevelFieldReads = 0;
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int nullableTopLevelFieldReads = 0;
+static field core::int? _#nullableTopLevelField = null;
+static field core::bool _#nullableTopLevelField#isSet = false;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t15 = self::_#nonNullableTopLevelField in #t15.==(null) ?{core::int} let final core::int #t16 = (let final core::int #t17 = self::nonNullableTopLevelFieldReads in let final core::int #t18 = self::nonNullableTopLevelFieldReads = #t17.{core::num::+}(1) in #t17).{core::num::==}(0) ?{core::int*} self::nonNullableTopLevelField : ini::computeInitialValue() in self::_#nonNullableTopLevelField.==(null) ?{core::int} self::_#nonNullableTopLevelField = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.") : #t15{core::int};
+static get nullableTopLevelField() → core::int? {
+  if(!self::_#nullableTopLevelField#isSet) {
+    final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int?} self::nullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
+    self::_#nullableTopLevelField = #t19;
+    self::_#nullableTopLevelField#isSet = true;
+  }
+  return self::_#nullableTopLevelField;
+}
+static method main() → void {
+  self::throws(() → core::int => self::nonNullableTopLevelField, "Read nonNullableTopLevelField");
+  self::throws(() → core::int? => self::nullableTopLevelField, "Read nullableTopLevelField");
+  self::throws(() → core::int => self::Class::nonNullableStaticField, "Read nonNullableStaticField");
+  self::throws(() → core::int? => self::Class::nullableStaticField, "Read nullableStaticField");
+  self::throws(() → core::int => new self::Class::•().{self::Class::nonNullableInstanceField}, "Read nonNullableInstanceField");
+  self::throws(() → core::int? => new self::Class::•().{self::Class::nullableInstanceField}, "Read nullableInstanceField");
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
+
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as ini;
+import "dart:core" as core;
+
+static method computeInitialValue() → core::int*
+  return null;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect
new file mode 100644
index 0000000..181da77
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.textual_outline.expect
@@ -0,0 +1,23 @@
+import 'initializer_rewrite_from_opt_out_lib.dart';
+int nonNullableTopLevelFieldReads = 0;
+late ;
+final int nonNullableTopLevelField = nonNullableTopLevelFieldReads++ == 0 ? nonNullableTopLevelField : computeInitialValue();
+int nullableTopLevelFieldReads = 0;
+late ;
+final int? nullableTopLevelField = nullableTopLevelFieldReads++ == 0 ? nullableTopLevelField : computeInitialValue();
+class Class {
+  static int nonNullableStaticFieldReads = 0;
+  static late ;
+  final int nonNullableStaticField = nonNullableStaticFieldReads++ == 0 ? nonNullableStaticField : computeInitialValue();
+  static int nullableStaticFieldReads = 0;
+  static late ;
+  final int? nullableStaticField = nullableStaticFieldReads++ == 0 ? nullableStaticField : computeInitialValue();
+  int nonNullableInstanceFieldReads = 0;
+  late ;
+  final int nonNullableInstanceField = nonNullableInstanceFieldReads++ == 0 ? nonNullableInstanceField : computeInitialValue();
+  int nullableInstanceFieldReads = 0;
+  late ;
+  final int? nullableInstanceField = nullableInstanceFieldReads++ == 0 ? nullableInstanceField : computeInitialValue();
+}
+void main() {}
+throws(f(), String message) {}
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect
new file mode 100644
index 0000000..d58daaa
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.expect
@@ -0,0 +1,117 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "initializer_rewrite_from_opt_out_lib.dart" as ini;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///initializer_rewrite_from_opt_out_lib.dart";
+
+class Class extends core::Object {
+  static field core::int nonNullableStaticFieldReads = 0;
+  static field core::int? _#nonNullableStaticField = null;
+  static field core::bool _#nonNullableStaticField#isSet = false;
+  static field core::int nullableStaticFieldReads = 0;
+  static field core::int? _#nullableStaticField = null;
+  static field core::bool _#nullableStaticField#isSet = false;
+  field core::int nonNullableInstanceFieldReads = 0;
+  field core::int? _#Class#nonNullableInstanceField = null;
+  field core::bool _#Class#nonNullableInstanceField#isSet = false;
+  field core::int nullableInstanceFieldReads = 0;
+  field core::int? _#Class#nullableInstanceField = null;
+  field core::bool _#Class#nullableInstanceField#isSet = false;
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static get nonNullableStaticField() → core::int {
+    if(!self::Class::_#nonNullableStaticField#isSet) {
+      final core::int #t1 = (let final core::int #t2 = self::Class::nonNullableStaticFieldReads in let final core::int #t3 = self::Class::nonNullableStaticFieldReads = #t2.{core::num::+}(1) in #t2).{core::num::==}(0) ?{core::int*} self::Class::nonNullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nonNullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticField = #t1;
+      self::Class::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticField in #t4{core::int};
+  }
+  static get nullableStaticField() → core::int? {
+    if(!self::Class::_#nullableStaticField#isSet) {
+      final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int?} self::Class::nullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
+      self::Class::_#nullableStaticField = #t5;
+      self::Class::_#nullableStaticField#isSet = true;
+    }
+    return self::Class::_#nullableStaticField;
+  }
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#nonNullableInstanceField#isSet}) {
+      final core::int #t8 = (let final core::int #t9 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} = #t9.{core::num::+}(1) in #t9).{core::num::==}(0) ?{core::int*} this.{self::Class::nonNullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nonNullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nonNullableInstanceField} = #t8;
+      this.{self::Class::_#Class#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::Class::_#Class#nonNullableInstanceField} in #t11{core::int};
+  }
+  get nullableInstanceField() → core::int? {
+    if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
+      final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int?} this.{self::Class::nullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nullableInstanceField} = #t12;
+      this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
+    }
+    return this.{self::Class::_#Class#nullableInstanceField};
+  }
+}
+static field core::int nonNullableTopLevelFieldReads = 0;
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::bool _#nonNullableTopLevelField#isSet = false;
+static field core::int nullableTopLevelFieldReads = 0;
+static field core::int? _#nullableTopLevelField = null;
+static field core::bool _#nullableTopLevelField#isSet = false;
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    final core::int #t15 = (let final core::int #t16 = self::nonNullableTopLevelFieldReads in let final core::int #t17 = self::nonNullableTopLevelFieldReads = #t16.{core::num::+}(1) in #t16).{core::num::==}(0) ?{core::int*} self::nonNullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nonNullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.");
+    self::_#nonNullableTopLevelField = #t15;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t18 = self::_#nonNullableTopLevelField in #t18{core::int};
+}
+static get nullableTopLevelField() → core::int? {
+  if(!self::_#nullableTopLevelField#isSet) {
+    final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int?} self::nullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
+    self::_#nullableTopLevelField = #t19;
+    self::_#nullableTopLevelField#isSet = true;
+  }
+  return self::_#nullableTopLevelField;
+}
+static method main() → void {
+  self::throws(() → core::int => self::nonNullableTopLevelField, "Read nonNullableTopLevelField");
+  self::throws(() → core::int? => self::nullableTopLevelField, "Read nullableTopLevelField");
+  self::throws(() → core::int => self::Class::nonNullableStaticField, "Read nonNullableStaticField");
+  self::throws(() → core::int? => self::Class::nullableStaticField, "Read nullableStaticField");
+  self::throws(() → core::int => new self::Class::•().{self::Class::nonNullableInstanceField}, "Read nonNullableInstanceField");
+  self::throws(() → core::int? => new self::Class::•().{self::Class::nullableInstanceField}, "Read nullableInstanceField");
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
+
+library;
+import self as ini;
+import "dart:core" as core;
+
+static method computeInitialValue() → core::int*
+  return null;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..d58daaa
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,117 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "initializer_rewrite_from_opt_out_lib.dart" as ini;
+import "dart:_internal" as _in;
+
+import "org-dartlang-testcase:///initializer_rewrite_from_opt_out_lib.dart";
+
+class Class extends core::Object {
+  static field core::int nonNullableStaticFieldReads = 0;
+  static field core::int? _#nonNullableStaticField = null;
+  static field core::bool _#nonNullableStaticField#isSet = false;
+  static field core::int nullableStaticFieldReads = 0;
+  static field core::int? _#nullableStaticField = null;
+  static field core::bool _#nullableStaticField#isSet = false;
+  field core::int nonNullableInstanceFieldReads = 0;
+  field core::int? _#Class#nonNullableInstanceField = null;
+  field core::bool _#Class#nonNullableInstanceField#isSet = false;
+  field core::int nullableInstanceFieldReads = 0;
+  field core::int? _#Class#nullableInstanceField = null;
+  field core::bool _#Class#nullableInstanceField#isSet = false;
+  synthetic constructor •() → self::Class
+    : super core::Object::•()
+    ;
+  static get nonNullableStaticField() → core::int {
+    if(!self::Class::_#nonNullableStaticField#isSet) {
+      final core::int #t1 = (let final core::int #t2 = self::Class::nonNullableStaticFieldReads in let final core::int #t3 = self::Class::nonNullableStaticFieldReads = #t2.{core::num::+}(1) in #t2).{core::num::==}(0) ?{core::int*} self::Class::nonNullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nonNullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticField' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticField = #t1;
+      self::Class::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticField in #t4{core::int};
+  }
+  static get nullableStaticField() → core::int? {
+    if(!self::Class::_#nullableStaticField#isSet) {
+      final core::int? #t5 = (let final core::int #t6 = self::Class::nullableStaticFieldReads in let final core::int #t7 = self::Class::nullableStaticFieldReads = #t6.{core::num::+}(1) in #t6).{core::num::==}(0) ?{core::int?} self::Class::nullableStaticField : ini::computeInitialValue();
+      if(self::Class::_#nullableStaticField#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableStaticField' has been assigned during initialization.");
+      self::Class::_#nullableStaticField = #t5;
+      self::Class::_#nullableStaticField#isSet = true;
+    }
+    return self::Class::_#nullableStaticField;
+  }
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#nonNullableInstanceField#isSet}) {
+      final core::int #t8 = (let final core::int #t9 = this.{self::Class::nonNullableInstanceFieldReads} in let final core::int #t10 = this.{self::Class::nonNullableInstanceFieldReads} = #t9.{core::num::+}(1) in #t9).{core::num::==}(0) ?{core::int*} this.{self::Class::nonNullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nonNullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nonNullableInstanceField} = #t8;
+      this.{self::Class::_#Class#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::Class::_#Class#nonNullableInstanceField} in #t11{core::int};
+  }
+  get nullableInstanceField() → core::int? {
+    if(!this.{self::Class::_#Class#nullableInstanceField#isSet}) {
+      final core::int? #t12 = (let final core::int #t13 = this.{self::Class::nullableInstanceFieldReads} in let final core::int #t14 = this.{self::Class::nullableInstanceFieldReads} = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int?} this.{self::Class::nullableInstanceField} : ini::computeInitialValue();
+      if(this.{self::Class::_#Class#nullableInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'nullableInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#nullableInstanceField} = #t12;
+      this.{self::Class::_#Class#nullableInstanceField#isSet} = true;
+    }
+    return this.{self::Class::_#Class#nullableInstanceField};
+  }
+}
+static field core::int nonNullableTopLevelFieldReads = 0;
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::bool _#nonNullableTopLevelField#isSet = false;
+static field core::int nullableTopLevelFieldReads = 0;
+static field core::int? _#nullableTopLevelField = null;
+static field core::bool _#nullableTopLevelField#isSet = false;
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    final core::int #t15 = (let final core::int #t16 = self::nonNullableTopLevelFieldReads in let final core::int #t17 = self::nonNullableTopLevelFieldReads = #t16.{core::num::+}(1) in #t16).{core::num::==}(0) ?{core::int*} self::nonNullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nonNullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has been assigned during initialization.");
+    self::_#nonNullableTopLevelField = #t15;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t18 = self::_#nonNullableTopLevelField in #t18{core::int};
+}
+static get nullableTopLevelField() → core::int? {
+  if(!self::_#nullableTopLevelField#isSet) {
+    final core::int? #t19 = (let final core::int #t20 = self::nullableTopLevelFieldReads in let final core::int #t21 = self::nullableTopLevelFieldReads = #t20.{core::num::+}(1) in #t20).{core::num::==}(0) ?{core::int?} self::nullableTopLevelField : ini::computeInitialValue();
+    if(self::_#nullableTopLevelField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has been assigned during initialization.");
+    self::_#nullableTopLevelField = #t19;
+    self::_#nullableTopLevelField#isSet = true;
+  }
+  return self::_#nullableTopLevelField;
+}
+static method main() → void {
+  self::throws(() → core::int => self::nonNullableTopLevelField, "Read nonNullableTopLevelField");
+  self::throws(() → core::int? => self::nullableTopLevelField, "Read nullableTopLevelField");
+  self::throws(() → core::int => self::Class::nonNullableStaticField, "Read nonNullableStaticField");
+  self::throws(() → core::int? => self::Class::nullableStaticField, "Read nullableStaticField");
+  self::throws(() → core::int => new self::Class::•().{self::Class::nonNullableInstanceField}, "Read nonNullableInstanceField");
+  self::throws(() → core::int? => new self::Class::•().{self::Class::nullableInstanceField}, "Read nullableInstanceField");
+}
+static method throws(() → dynamic f, core::String message) → dynamic {
+  dynamic value;
+  try {
+    value = f.call();
+  }
+  on core::LateInitializationError catch(final core::LateInitializationError e) {
+    core::print(e);
+    return;
+  }
+  throw "${message}: ${value}";
+}
+
+library;
+import self as ini;
+import "dart:core" as core;
+
+static method computeInitialValue() → core::int*
+  return null;
diff --git a/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart
new file mode 100644
index 0000000..7a87630
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/initializer_rewrite_from_opt_out_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+int computeInitialValue() => null;
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.outline.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.outline.expect
index 2996b94..fc7694c 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.outline.expect
@@ -23,3 +23,8 @@
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int;
   set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t1) → void;
 }
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
index ea024bb..e2b0019 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.expect
@@ -15,16 +15,19 @@
 @#C1
 class Class extends core::Object {
   field core::int? _#Class#foo = null /* from org-dartlang-testcase:///patch_lib.dart */;
+  field core::bool _#Class#foo#isSet = false /* from org-dartlang-testcase:///patch_lib.dart */;
   constructor bar() → self2::Class
     : super core::Object::•()
     ;
   constructor baz(core::int foo) → self2::Class
-    : self2::Class::_#Class#foo = foo, super core::Object::•()
+    : self2::Class::_#Class#foo#isSet = true, self2::Class::_#Class#foo = foo, super core::Object::•()
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
-    return let final core::int? #t1 = this.{self2::Class::_#Class#foo} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'foo' has not been initialized.") : #t1{core::int};
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void
+    return this.{self2::Class::_#Class#foo#isSet} ?{core::int} let final core::int? #t1 = this.{self2::Class::_#Class#foo} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'foo' has not been initialized.");
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void {
+    this.{self2::Class::_#Class#foo#isSet} = true;
     this.{self2::Class::_#Class#foo} = #t2;
+  }
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
index ea024bb..e2b0019 100644
--- a/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/injected_late_field_checks/main.dart.weak.transformed.expect
@@ -15,16 +15,19 @@
 @#C1
 class Class extends core::Object {
   field core::int? _#Class#foo = null /* from org-dartlang-testcase:///patch_lib.dart */;
+  field core::bool _#Class#foo#isSet = false /* from org-dartlang-testcase:///patch_lib.dart */;
   constructor bar() → self2::Class
     : super core::Object::•()
     ;
   constructor baz(core::int foo) → self2::Class
-    : self2::Class::_#Class#foo = foo, super core::Object::•()
+    : self2::Class::_#Class#foo#isSet = true, self2::Class::_#Class#foo = foo, super core::Object::•()
     ;
   get /* from org-dartlang-testcase:///patch_lib.dart */ foo() → core::int
-    return let final core::int? #t1 = this.{self2::Class::_#Class#foo} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'foo' has not been initialized.") : #t1{core::int};
-  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void
+    return this.{self2::Class::_#Class#foo#isSet} ?{core::int} let final core::int? #t1 = this.{self2::Class::_#Class#foo} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'foo' has not been initialized.");
+  set /* from org-dartlang-testcase:///patch_lib.dart */ foo(core::int #t2) → void {
+    this.{self2::Class::_#Class#foo#isSet} = true;
     this.{self2::Class::_#Class#foo} = #t2;
+  }
 }
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
index 0cfc574..9dc836f 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.expect
@@ -4,22 +4,30 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
-  get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} this.{self::Class::_#Class#field} = 10 : #t1{core::int};
-  set field(core::int #t2) → void
+  get field() → core::int {
+    if(!this.{self::Class::_#Class#field#isSet}) {
+      this.{self::Class::_#Class#field} = 10;
+      this.{self::Class::_#Class#field#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int};
+  }
+  set field(core::int #t2) → void {
+    this.{self::Class::_#Class#field#isSet} = true;
     this.{self::Class::_#Class#field} = #t2;
+  }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
index 0cfc574..9dc836f 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_with_initializer.dart.weak.transformed.expect
@@ -4,22 +4,30 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
-  get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} this.{self::Class::_#Class#field} = 10 : #t1{core::int};
-  set field(core::int #t2) → void
+  get field() → core::int {
+    if(!this.{self::Class::_#Class#field#isSet}) {
+      this.{self::Class::_#Class#field} = 10;
+      this.{self::Class::_#Class#field#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int};
+  }
+  set field(core::int #t2) → void {
+    this.{self::Class::_#Class#field#isSet} = true;
     this.{self::Class::_#Class#field} = #t2;
+  }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
index 2a32553..1fa0843 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.expect
@@ -5,22 +5,25 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.") : #t1{core::int};
-  set field(core::int #t2) → void
+    return this.{self::Class::_#Class#field#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int #t2) → void {
+    this.{self::Class::_#Class#field#isSet} = true;
     this.{self::Class::_#Class#field} = #t2;
+  }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
index 2a32553..1fa0843 100644
--- a/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_field_without_initializer.dart.weak.transformed.expect
@@ -5,22 +5,25 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.") : #t1{core::int};
-  set field(core::int #t2) → void
+    return this.{self::Class::_#Class#field#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
+  set field(core::int #t2) → void {
+    this.{self::Class::_#Class#field#isSet} = true;
     this.{self::Class::_#Class#field} = #t2;
+  }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
index cdd56ea..180d337 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.expect
@@ -5,25 +5,28 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.") : #t1{core::int};
+    return this.{self::Class::_#Class#field#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
   set field(core::int #t2) → void
-    if(this.{self::Class::_#Class#field}.==(null))
-      this.{self::Class::_#Class#field} = #t2;
-    else
+    if(this.{self::Class::_#Class#field#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field#isSet} = true;
+      this.{self::Class::_#Class#field} = #t2;
+    }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
index cdd56ea..180d337 100644
--- a/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/instance_final_field_without_initializer.dart.weak.transformed.expect
@@ -5,25 +5,28 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field = null;
+  field core::bool _#Class#field#isSet = false;
   constructor constructor1() → self::Class
     : super core::Object::•()
     ;
   constructor constructor2(core::int field) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   constructor constructor3(core::int value) → self::Class
-    : self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = value.{core::num::+}(1), super core::Object::•()
     ;
   constructor constructor4([core::int field = #C1]) → self::Class
-    : self::Class::_#Class#field = field, super core::Object::•()
+    : self::Class::_#Class#field#isSet = true, self::Class::_#Class#field = field, super core::Object::•()
     ;
   get field() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.") : #t1{core::int};
+    return this.{self::Class::_#Class#field#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field' has not been initialized.");
   set field(core::int #t2) → void
-    if(this.{self::Class::_#Class#field}.==(null))
-      this.{self::Class::_#Class#field} = #t2;
-    else
+    if(this.{self::Class::_#Class#field#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field#isSet} = true;
+      this.{self::Class::_#Class#field} = #t2;
+    }
 }
 class Subclass extends self::Class {
   constructor constructor1() → self::Subclass
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
index ecf82f3..3fc2e39 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.expect
@@ -6,17 +6,33 @@
 class C extends core::Object {
   field core::num pi = 3.14;
   field core::num? _#C#p1 = null;
+  field core::bool _#C#p1#isSet = false;
   field core::num? _#C#p2 = null;
   field core::bool _#C#p2#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-  get p1() → core::num
-    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
-  set p1(core::num #t2) → void
+  get p1() → core::num {
+    if(!this.{self::C::_#C#p1#isSet}) {
+      this.{self::C::_#C#p1} = this.{self::C::pi};
+      this.{self::C::_#C#p1#isSet} = true;
+    }
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1{core::num};
+  }
+  set p1(core::num #t2) → void {
+    this.{self::C::_#C#p1#isSet} = true;
     this.{self::C::_#C#p1} = #t2;
-  get p2() → core::num
-    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+  }
+  get p2() → core::num {
+    if(!this.{self::C::_#C#p2#isSet}) {
+      final core::num #t3 = this.{self::C::pi};
+      if(this.{self::C::_#C#p2#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.");
+      this.{self::C::_#C#p2} = #t3;
+      this.{self::C::_#C#p2#isSet} = true;
+    }
+    return let final core::num? #t4 = this.{self::C::_#C#p2} in #t4{core::num};
+  }
 }
 static method main() → dynamic {
   self::expect(3.14, new self::C::•().{self::C::p1});
diff --git a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
index ecf82f3..3fc2e39 100644
--- a/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40373.dart.weak.transformed.expect
@@ -6,17 +6,33 @@
 class C extends core::Object {
   field core::num pi = 3.14;
   field core::num? _#C#p1 = null;
+  field core::bool _#C#p1#isSet = false;
   field core::num? _#C#p2 = null;
   field core::bool _#C#p2#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
-  get p1() → core::num
-    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1.==(null) ?{core::num} this.{self::C::_#C#p1} = this.{self::C::pi} : #t1{core::num};
-  set p1(core::num #t2) → void
+  get p1() → core::num {
+    if(!this.{self::C::_#C#p1#isSet}) {
+      this.{self::C::_#C#p1} = this.{self::C::pi};
+      this.{self::C::_#C#p1#isSet} = true;
+    }
+    return let final core::num? #t1 = this.{self::C::_#C#p1} in #t1{core::num};
+  }
+  set p1(core::num #t2) → void {
+    this.{self::C::_#C#p1#isSet} = true;
     this.{self::C::_#C#p1} = #t2;
-  get p2() → core::num
-    return let final core::num? #t3 = this.{self::C::_#C#p2} in #t3.==(null) ?{core::num} let final core::num #t4 = this.{self::C::pi} in this.{self::C::_#C#p2}.==(null) ?{core::num} this.{self::C::_#C#p2} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.") : #t3{core::num};
+  }
+  get p2() → core::num {
+    if(!this.{self::C::_#C#p2#isSet}) {
+      final core::num #t3 = this.{self::C::pi};
+      if(this.{self::C::_#C#p2#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'p2' has been assigned during initialization.");
+      this.{self::C::_#C#p2} = #t3;
+      this.{self::C::_#C#p2#isSet} = true;
+    }
+    return let final core::num? #t4 = this.{self::C::_#C#p2} in #t4{core::num};
+  }
 }
 static method main() → dynamic {
   self::expect(3.14, new self::C::•().{self::C::p1});
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
index 2f75d09..aead618 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.expect
@@ -5,16 +5,19 @@
 
 class C extends core::Object {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+    return this.{self::C::_#C#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::C::_#C#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(covariant core::int #t2) → void
-    if(this.{self::C::_#C#x}.==(null))
-      this.{self::C::_#C#x} = #t2;
-    else
+    if(this.{self::C::_#C#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::C::_#C#x#isSet} = true;
+      this.{self::C::_#C#x} = #t2;
+    }
 }
 class D extends self::C {
   synthetic constructor •() → self::D
diff --git a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
index 2f75d09..aead618 100644
--- a/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue40805.dart.weak.transformed.expect
@@ -5,16 +5,19 @@
 
 class C extends core::Object {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::C::_#C#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+    return this.{self::C::_#C#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::C::_#C#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(covariant core::int #t2) → void
-    if(this.{self::C::_#C#x}.==(null))
-      this.{self::C::_#C#x} = #t2;
-    else
+    if(this.{self::C::_#C#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::C::_#C#x#isSet} = true;
+      this.{self::C::_#C#x} = #t2;
+    }
 }
 class D extends self::C {
   synthetic constructor •() → self::D
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
index 139a488..3872041 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.expect
@@ -15,13 +15,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → test::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{test::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{test::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{test::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{test::A::_#A#x#isSet} = true;
     this.{test::A::_#A#x} = #t2;
+  }
 }
 class _B extends core::Object implements test::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
index 139a488..3872041 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436/issue41436.dart.weak.transformed.expect
@@ -15,13 +15,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → test::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{test::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{test::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{test::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{test::A::_#A#x#isSet} = true;
     this.{test::A::_#A#x} = #t2;
+  }
 }
 class _B extends core::Object implements test::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
index 61c5d86..34bca462 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.expect
@@ -5,13 +5,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
     this.{self::A::_#A#x} = #t2;
+  }
 }
 class _B extends core::Object implements self::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
index 61c5d86..34bca462 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436b.dart.weak.transformed.expect
@@ -5,13 +5,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
     this.{self::A::_#A#x} = #t2;
+  }
 }
 class _B extends core::Object implements self::A {
   field core::int x = 3;
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.outline.expect
index de879f1..b7a7d1d 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.outline.expect
@@ -32,3 +32,14 @@
   synthetic constructor •() → iss::B
     ;
 }
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> SymbolConstant(#_#A#x)
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> SymbolConstant(#_#A#x=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///issue41436c_lib.dart:6:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
index 05bf5e3..432f8c1 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.expect
@@ -9,10 +9,14 @@
   synthetic constructor •() → self::C
     : super iss::B::•()
     ;
+  no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x#isSet() → core::bool
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x() → core::int?
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
+  no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x#isSet(core::bool value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x(core::int? value) → void
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   new self::C::•();
@@ -25,13 +29,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → iss::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{iss::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{iss::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{iss::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{iss::A::_#A#x#isSet} = true;
     this.{iss::A::_#A#x} = #t2;
+  }
 }
 class B extends core::Object implements iss::A {
   field core::int x = 3;
@@ -41,9 +48,11 @@
 }
 
 constants  {
-  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x#isSet
   #C2 = <core::Type*>[]
   #C3 = <dynamic>[]
   #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
-  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C6 = #org-dartlang-testcase:///issue41436c.dart::_#A#x#isSet=
+  #C7 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
 }
diff --git a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
index 05bf5e3..432f8c1 100644
--- a/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/issue41436c/issue41436c.dart.weak.transformed.expect
@@ -9,10 +9,14 @@
   synthetic constructor •() → self::C
     : super iss::B::•()
     ;
+  no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x#isSet() → core::bool
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::bool;
   no-such-method-forwarder get /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x() → core::int?
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic,ForNonNullableByDefault} core::int?;
+  no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x#isSet(core::bool value) → void
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder set /* from org-dartlang-testcase:///issue41436c_lib.dart */ _#A#x(core::int? value) → void
-    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{core::Object::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {
   new self::C::•();
@@ -25,13 +29,16 @@
 
 abstract class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   synthetic constructor •() → iss::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{iss::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{iss::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{iss::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{iss::A::_#A#x#isSet} = true;
     this.{iss::A::_#A#x} = #t2;
+  }
 }
 class B extends core::Object implements iss::A {
   field core::int x = 3;
@@ -41,9 +48,11 @@
 }
 
 constants  {
-  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C1 = #org-dartlang-testcase:///issue41436c.dart::_#A#x#isSet
   #C2 = <core::Type*>[]
   #C3 = <dynamic>[]
   #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
-  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
+  #C5 = #org-dartlang-testcase:///issue41436c.dart::_#A#x
+  #C6 = #org-dartlang-testcase:///issue41436c.dart::_#A#x#isSet=
+  #C7 = #org-dartlang-testcase:///issue41436c.dart::_#A#x=
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.outline.expect
index 4b649e0..bcd034d 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.outline.expect
@@ -113,3 +113,41 @@
 static get Extension|finalExtensionStaticFieldWithInitializer() → core::int;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:19:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:19:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:22:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:22:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:25:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:28:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:28:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:31:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:31:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:34:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:34:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:37:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:42:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:42:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:45:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:45:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:48:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:51:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:51:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:54:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:54:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:57:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:57:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:60:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:9:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:9:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:12:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:12:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:15:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:65:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:65:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:68:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:68:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///late_annotations.dart:71:4 -> InstanceConstant(const Annotation{})
+Extra constant evaluation: evaluated: 34, effectively constant: 34
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
index 44d325d..4555905 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.strong.transformed.expect
@@ -170,3 +170,12 @@
 constants  {
   #C1 = self::Annotation {}
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:26:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:38:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:49:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:61:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:16:16 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_annotations.dart:72:25 -> IntConstant(0)
+Extra constant evaluation: evaluated: 268, effectively constant: 6
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
index 44d325d..89e5a3a 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.expect
@@ -10,161 +10,260 @@
 }
 class A extends core::Object {
   field core::int? _#A#instanceField = null;
+  field core::bool _#A#instanceField#isSet = false;
   field core::int? _#A#finalInstanceField = null;
+  field core::bool _#A#finalInstanceField#isSet = false;
   field core::int? _#A#finalInstanceFieldWithInitializer = null;
+  field core::bool _#A#finalInstanceFieldWithInitializer#isSet = false;
   field core::num? _#A#covariantInstanceField = null;
+  field core::bool _#A#covariantInstanceField#isSet = false;
   static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
   static field core::int? _#finalStaticField = null;
+  static field core::bool _#finalStaticField#isSet = false;
   static field core::int? _#finalStaticFieldWithInitializer = null;
+  static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#instanceField} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t1{core::int};
+    return this.{self::A::_#A#instanceField#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#instanceField} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
   @#C1
-  set instanceField(core::int #t2) → void
+  set instanceField(core::int #t2) → void {
+    this.{self::A::_#A#instanceField#isSet} = true;
     this.{self::A::_#A#instanceField} = #t2;
+  }
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceField} in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.") : #t3{core::int};
+    return this.{self::A::_#A#finalInstanceField#isSet} ?{core::int} let final core::int? #t3 = this.{self::A::_#A#finalInstanceField} in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
   @#C1
   set finalInstanceField(core::int #t4) → void
-    if(this.{self::A::_#A#finalInstanceField}.==(null))
-      this.{self::A::_#A#finalInstanceField} = #t4;
-    else
+    if(this.{self::A::_#A#finalInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{self::A::_#A#finalInstanceField#isSet} = true;
+      this.{self::A::_#A#finalInstanceField} = #t4;
+    }
   @#C1
-  get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t5 = this.{self::A::_#A#finalInstanceFieldWithInitializer} in #t5.==(null) ?{core::int} let final core::int #t6 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}.==(null) ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.") : #t5{core::int};
+  get finalInstanceFieldWithInitializer() → core::int {
+    if(!this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}) {
+      final core::int #t5 = 0;
+      if(this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.");
+      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t5;
+      this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet} = true;
+    }
+    return let final core::int? #t6 = this.{self::A::_#A#finalInstanceFieldWithInitializer} in #t6{core::int};
+  }
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField} in #t7.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.") : #t7{core::num};
+    return this.{self::A::_#A#covariantInstanceField#isSet} ?{core::num} let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField} in #t7{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.");
   @#C1
-  set covariantInstanceField(covariant core::num #t8) → void
+  set covariantInstanceField(covariant core::num #t8) → void {
+    this.{self::A::_#A#covariantInstanceField#isSet} = true;
     this.{self::A::_#A#covariantInstanceField} = #t8;
+  }
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t9 = self::A::_#staticField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t9{core::int};
+    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t9 = self::A::_#staticField in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
   @#C1
-  static set staticField(core::int #t10) → void
+  static set staticField(core::int #t10) → void {
+    self::A::_#staticField#isSet = true;
     self::A::_#staticField = #t10;
+  }
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t11 = self::A::_#finalStaticField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.") : #t11{core::int};
+    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t11 = self::A::_#finalStaticField in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.");
   @#C1
   static set finalStaticField(core::int #t12) → void
-    if(self::A::_#finalStaticField.==(null))
-      self::A::_#finalStaticField = #t12;
-    else
+    if(self::A::_#finalStaticField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has already been initialized.");
+    else {
+      self::A::_#finalStaticField#isSet = true;
+      self::A::_#finalStaticField = #t12;
+    }
   @#C1
-  static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t13 = self::A::_#finalStaticFieldWithInitializer in #t13.==(null) ?{core::int} let final core::int #t14 = 0 in self::A::_#finalStaticFieldWithInitializer.==(null) ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.") : #t13{core::int};
+  static get finalStaticFieldWithInitializer() → core::int {
+    if(!self::A::_#finalStaticFieldWithInitializer#isSet) {
+      final core::int #t13 = 0;
+      if(self::A::_#finalStaticFieldWithInitializer#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.");
+      self::A::_#finalStaticFieldWithInitializer = #t13;
+      self::A::_#finalStaticFieldWithInitializer#isSet = true;
+    }
+    return let final core::int? #t14 = self::A::_#finalStaticFieldWithInitializer in #t14{core::int};
+  }
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   field core::int? _#B#instanceField = null;
+  field core::bool _#B#instanceField#isSet = false;
   field core::int? _#B#finalInstanceField = null;
+  field core::bool _#B#finalInstanceField#isSet = false;
   field core::int? _#B#finalInstanceFieldWithInitializer = null;
+  field core::bool _#B#finalInstanceFieldWithInitializer#isSet = false;
   field core::num? _#B#covariantInstanceField = null;
+  field core::bool _#B#covariantInstanceField#isSet = false;
   static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
   static field core::int? _#finalStaticField = null;
+  static field core::bool _#finalStaticField#isSet = false;
   static field core::int? _#finalStaticFieldWithInitializer = null;
+  static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t15 = this.{self::B::_#B#instanceField} in #t15.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t15{core::int};
+    return this.{self::B::_#B#instanceField#isSet} ?{core::int} let final core::int? #t15 = this.{self::B::_#B#instanceField} in #t15{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
   @#C1
-  set instanceField(core::int #t16) → void
+  set instanceField(core::int #t16) → void {
+    this.{self::B::_#B#instanceField#isSet} = true;
     this.{self::B::_#B#instanceField} = #t16;
+  }
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t17 = this.{self::B::_#B#finalInstanceField} in #t17.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.") : #t17{core::int};
+    return this.{self::B::_#B#finalInstanceField#isSet} ?{core::int} let final core::int? #t17 = this.{self::B::_#B#finalInstanceField} in #t17{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
   @#C1
   set finalInstanceField(core::int #t18) → void
-    if(this.{self::B::_#B#finalInstanceField}.==(null))
-      this.{self::B::_#B#finalInstanceField} = #t18;
-    else
+    if(this.{self::B::_#B#finalInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{self::B::_#B#finalInstanceField#isSet} = true;
+      this.{self::B::_#B#finalInstanceField} = #t18;
+    }
   @#C1
-  get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t19 = this.{self::B::_#B#finalInstanceFieldWithInitializer} in #t19.==(null) ?{core::int} let final core::int #t20 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}.==(null) ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t20 : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.") : #t19{core::int};
+  get finalInstanceFieldWithInitializer() → core::int {
+    if(!this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}) {
+      final core::int #t19 = 0;
+      if(this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.");
+      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t19;
+      this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet} = true;
+    }
+    return let final core::int? #t20 = this.{self::B::_#B#finalInstanceFieldWithInitializer} in #t20{core::int};
+  }
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField} in #t21.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.") : #t21{core::num};
+    return this.{self::B::_#B#covariantInstanceField#isSet} ?{core::num} let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField} in #t21{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.");
   @#C1
-  set covariantInstanceField(covariant core::num #t22) → void
+  set covariantInstanceField(covariant core::num #t22) → void {
+    this.{self::B::_#B#covariantInstanceField#isSet} = true;
     this.{self::B::_#B#covariantInstanceField} = #t22;
+  }
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t23 = self::B::_#staticField in #t23.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t23{core::int};
+    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t23 = self::B::_#staticField in #t23{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
   @#C1
-  static set staticField(core::int #t24) → void
+  static set staticField(core::int #t24) → void {
+    self::B::_#staticField#isSet = true;
     self::B::_#staticField = #t24;
+  }
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t25 = self::B::_#finalStaticField in #t25.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.") : #t25{core::int};
+    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t25 = self::B::_#finalStaticField in #t25{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.");
   @#C1
   static set finalStaticField(core::int #t26) → void
-    if(self::B::_#finalStaticField.==(null))
-      self::B::_#finalStaticField = #t26;
-    else
+    if(self::B::_#finalStaticField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has already been initialized.");
+    else {
+      self::B::_#finalStaticField#isSet = true;
+      self::B::_#finalStaticField = #t26;
+    }
   @#C1
-  static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t27 = self::B::_#finalStaticFieldWithInitializer in #t27.==(null) ?{core::int} let final core::int #t28 = 0 in self::B::_#finalStaticFieldWithInitializer.==(null) ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t28 : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.") : #t27{core::int};
+  static get finalStaticFieldWithInitializer() → core::int {
+    if(!self::B::_#finalStaticFieldWithInitializer#isSet) {
+      final core::int #t27 = 0;
+      if(self::B::_#finalStaticFieldWithInitializer#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.");
+      self::B::_#finalStaticFieldWithInitializer = #t27;
+      self::B::_#finalStaticFieldWithInitializer#isSet = true;
+    }
+    return let final core::int? #t28 = self::B::_#finalStaticFieldWithInitializer in #t28{core::int};
+  }
 }
 extension Extension on self::A {
   static field extensionStaticField = self::_#Extension|extensionStaticField;
+  static field extensionStaticField = self::_#Extension|extensionStaticField#isSet;
   static get extensionStaticField = get self::Extension|extensionStaticField;
   static set extensionStaticField = set self::Extension|extensionStaticField;
   static field finalExtensionStaticField = self::_#Extension|finalExtensionStaticField;
+  static field finalExtensionStaticField = self::_#Extension|finalExtensionStaticField#isSet;
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
   static set finalExtensionStaticField = set self::Extension|finalExtensionStaticField;
   static field finalExtensionStaticFieldWithInitializer = self::_#Extension|finalExtensionStaticFieldWithInitializer;
+  static field finalExtensionStaticFieldWithInitializer = self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet;
   static get finalExtensionStaticFieldWithInitializer = get self::Extension|finalExtensionStaticFieldWithInitializer;
 }
 static field core::int? _#topLevelField = null;
+static field core::bool _#topLevelField#isSet = false;
 static field core::int? _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
 static field core::int? _#finalTopLevelFieldWithInitializer = null;
+static field core::bool _#finalTopLevelFieldWithInitializer#isSet = false;
 static field core::int? _#Extension|extensionStaticField = null;
+static field core::bool _#Extension|extensionStaticField#isSet = false;
 static field core::int? _#Extension|finalExtensionStaticField = null;
+static field core::bool _#Extension|finalExtensionStaticField#isSet = false;
 static field core::int? _#Extension|finalExtensionStaticFieldWithInitializer = null;
+static field core::bool _#Extension|finalExtensionStaticFieldWithInitializer#isSet = false;
 @#C1
 static get topLevelField() → core::int
-  return let final core::int? #t29 = self::_#topLevelField in #t29.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.") : #t29{core::int};
+  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t29 = self::_#topLevelField in #t29{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.");
 @#C1
-static set topLevelField(core::int #t30) → void
+static set topLevelField(core::int #t30) → void {
+  self::_#topLevelField#isSet = true;
   self::_#topLevelField = #t30;
+}
 @#C1
 static get finalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#finalTopLevelField in #t31.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.") : #t31{core::int};
+  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t31 = self::_#finalTopLevelField in #t31{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
 @#C1
 static set finalTopLevelField(core::int #t32) → void
-  if(self::_#finalTopLevelField.==(null))
-    self::_#finalTopLevelField = #t32;
-  else
+  if(self::_#finalTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    self::_#finalTopLevelField#isSet = true;
+    self::_#finalTopLevelField = #t32;
+  }
 @#C1
-static get finalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t33 = self::_#finalTopLevelFieldWithInitializer in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#finalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t34 : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t33{core::int};
+static get finalTopLevelFieldWithInitializer() → core::int {
+  if(!self::_#finalTopLevelFieldWithInitializer#isSet) {
+    final core::int #t33 = 0;
+    if(self::_#finalTopLevelFieldWithInitializer#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelFieldWithInitializer' has been assigned during initialization.");
+    self::_#finalTopLevelFieldWithInitializer = #t33;
+    self::_#finalTopLevelFieldWithInitializer#isSet = true;
+  }
+  return let final core::int? #t34 = self::_#finalTopLevelFieldWithInitializer in #t34{core::int};
+}
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'extensionStaticField' has not been initialized.") : #t35{core::int};
+  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'extensionStaticField' has not been initialized.");
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void
+static set Extension|extensionStaticField(core::int #t36) → void {
+  self::_#Extension|extensionStaticField#isSet = true;
   self::_#Extension|extensionStaticField = #t36;
+}
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has not been initialized.") : #t37{core::int};
+  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has not been initialized.");
 @#C1
 static set Extension|finalExtensionStaticField(core::int #t38) → void
-  if(self::_#Extension|finalExtensionStaticField.==(null))
-    self::_#Extension|finalExtensionStaticField = #t38;
-  else
+  if(self::_#Extension|finalExtensionStaticField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has already been initialized.");
+  else {
+    self::_#Extension|finalExtensionStaticField#isSet = true;
+    self::_#Extension|finalExtensionStaticField = #t38;
+  }
 @#C1
-static get Extension|finalExtensionStaticFieldWithInitializer() → core::int
-  return let final core::int? #t39 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t39.==(null) ?{core::int} let final core::int #t40 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer.==(null) ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t40 : throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticFieldWithInitializer' has been assigned during initialization.") : #t39{core::int};
+static get Extension|finalExtensionStaticFieldWithInitializer() → core::int {
+  if(!self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet) {
+    final core::int #t39 = 0;
+    if(self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticFieldWithInitializer' has been assigned during initialization.");
+    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t39;
+    self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet = true;
+  }
+  return let final core::int? #t40 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t40{core::int};
+}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
index 44d325d..89e5a3a 100644
--- a/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_annotations.dart.weak.transformed.expect
@@ -10,161 +10,260 @@
 }
 class A extends core::Object {
   field core::int? _#A#instanceField = null;
+  field core::bool _#A#instanceField#isSet = false;
   field core::int? _#A#finalInstanceField = null;
+  field core::bool _#A#finalInstanceField#isSet = false;
   field core::int? _#A#finalInstanceFieldWithInitializer = null;
+  field core::bool _#A#finalInstanceFieldWithInitializer#isSet = false;
   field core::num? _#A#covariantInstanceField = null;
+  field core::bool _#A#covariantInstanceField#isSet = false;
   static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
   static field core::int? _#finalStaticField = null;
+  static field core::bool _#finalStaticField#isSet = false;
   static field core::int? _#finalStaticFieldWithInitializer = null;
+  static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#instanceField} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t1{core::int};
+    return this.{self::A::_#A#instanceField#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#instanceField} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
   @#C1
-  set instanceField(core::int #t2) → void
+  set instanceField(core::int #t2) → void {
+    this.{self::A::_#A#instanceField#isSet} = true;
     this.{self::A::_#A#instanceField} = #t2;
+  }
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t3 = this.{self::A::_#A#finalInstanceField} in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.") : #t3{core::int};
+    return this.{self::A::_#A#finalInstanceField#isSet} ?{core::int} let final core::int? #t3 = this.{self::A::_#A#finalInstanceField} in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
   @#C1
   set finalInstanceField(core::int #t4) → void
-    if(this.{self::A::_#A#finalInstanceField}.==(null))
-      this.{self::A::_#A#finalInstanceField} = #t4;
-    else
+    if(this.{self::A::_#A#finalInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{self::A::_#A#finalInstanceField#isSet} = true;
+      this.{self::A::_#A#finalInstanceField} = #t4;
+    }
   @#C1
-  get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t5 = this.{self::A::_#A#finalInstanceFieldWithInitializer} in #t5.==(null) ?{core::int} let final core::int #t6 = 0 in this.{self::A::_#A#finalInstanceFieldWithInitializer}.==(null) ?{core::int} this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.") : #t5{core::int};
+  get finalInstanceFieldWithInitializer() → core::int {
+    if(!this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet}) {
+      final core::int #t5 = 0;
+      if(this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.");
+      this.{self::A::_#A#finalInstanceFieldWithInitializer} = #t5;
+      this.{self::A::_#A#finalInstanceFieldWithInitializer#isSet} = true;
+    }
+    return let final core::int? #t6 = this.{self::A::_#A#finalInstanceFieldWithInitializer} in #t6{core::int};
+  }
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField} in #t7.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.") : #t7{core::num};
+    return this.{self::A::_#A#covariantInstanceField#isSet} ?{core::num} let final core::num? #t7 = this.{self::A::_#A#covariantInstanceField} in #t7{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.");
   @#C1
-  set covariantInstanceField(covariant core::num #t8) → void
+  set covariantInstanceField(covariant core::num #t8) → void {
+    this.{self::A::_#A#covariantInstanceField#isSet} = true;
     this.{self::A::_#A#covariantInstanceField} = #t8;
+  }
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t9 = self::A::_#staticField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t9{core::int};
+    return self::A::_#staticField#isSet ?{core::int} let final core::int? #t9 = self::A::_#staticField in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
   @#C1
-  static set staticField(core::int #t10) → void
+  static set staticField(core::int #t10) → void {
+    self::A::_#staticField#isSet = true;
     self::A::_#staticField = #t10;
+  }
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t11 = self::A::_#finalStaticField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.") : #t11{core::int};
+    return self::A::_#finalStaticField#isSet ?{core::int} let final core::int? #t11 = self::A::_#finalStaticField in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.");
   @#C1
   static set finalStaticField(core::int #t12) → void
-    if(self::A::_#finalStaticField.==(null))
-      self::A::_#finalStaticField = #t12;
-    else
+    if(self::A::_#finalStaticField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has already been initialized.");
+    else {
+      self::A::_#finalStaticField#isSet = true;
+      self::A::_#finalStaticField = #t12;
+    }
   @#C1
-  static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t13 = self::A::_#finalStaticFieldWithInitializer in #t13.==(null) ?{core::int} let final core::int #t14 = 0 in self::A::_#finalStaticFieldWithInitializer.==(null) ?{core::int} self::A::_#finalStaticFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.") : #t13{core::int};
+  static get finalStaticFieldWithInitializer() → core::int {
+    if(!self::A::_#finalStaticFieldWithInitializer#isSet) {
+      final core::int #t13 = 0;
+      if(self::A::_#finalStaticFieldWithInitializer#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.");
+      self::A::_#finalStaticFieldWithInitializer = #t13;
+      self::A::_#finalStaticFieldWithInitializer#isSet = true;
+    }
+    return let final core::int? #t14 = self::A::_#finalStaticFieldWithInitializer in #t14{core::int};
+  }
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   field core::int? _#B#instanceField = null;
+  field core::bool _#B#instanceField#isSet = false;
   field core::int? _#B#finalInstanceField = null;
+  field core::bool _#B#finalInstanceField#isSet = false;
   field core::int? _#B#finalInstanceFieldWithInitializer = null;
+  field core::bool _#B#finalInstanceFieldWithInitializer#isSet = false;
   field core::num? _#B#covariantInstanceField = null;
+  field core::bool _#B#covariantInstanceField#isSet = false;
   static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
   static field core::int? _#finalStaticField = null;
+  static field core::bool _#finalStaticField#isSet = false;
   static field core::int? _#finalStaticFieldWithInitializer = null;
+  static field core::bool _#finalStaticFieldWithInitializer#isSet = false;
   @#C1
   get instanceField() → core::int
-    return let final core::int? #t15 = this.{self::B::_#B#instanceField} in #t15.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t15{core::int};
+    return this.{self::B::_#B#instanceField#isSet} ?{core::int} let final core::int? #t15 = this.{self::B::_#B#instanceField} in #t15{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
   @#C1
-  set instanceField(core::int #t16) → void
+  set instanceField(core::int #t16) → void {
+    this.{self::B::_#B#instanceField#isSet} = true;
     this.{self::B::_#B#instanceField} = #t16;
+  }
   @#C1
   get finalInstanceField() → core::int
-    return let final core::int? #t17 = this.{self::B::_#B#finalInstanceField} in #t17.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.") : #t17{core::int};
+    return this.{self::B::_#B#finalInstanceField#isSet} ?{core::int} let final core::int? #t17 = this.{self::B::_#B#finalInstanceField} in #t17{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
   @#C1
   set finalInstanceField(core::int #t18) → void
-    if(this.{self::B::_#B#finalInstanceField}.==(null))
-      this.{self::B::_#B#finalInstanceField} = #t18;
-    else
+    if(this.{self::B::_#B#finalInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{self::B::_#B#finalInstanceField#isSet} = true;
+      this.{self::B::_#B#finalInstanceField} = #t18;
+    }
   @#C1
-  get finalInstanceFieldWithInitializer() → core::int
-    return let final core::int? #t19 = this.{self::B::_#B#finalInstanceFieldWithInitializer} in #t19.==(null) ?{core::int} let final core::int #t20 = 0 in this.{self::B::_#B#finalInstanceFieldWithInitializer}.==(null) ?{core::int} this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t20 : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.") : #t19{core::int};
+  get finalInstanceFieldWithInitializer() → core::int {
+    if(!this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet}) {
+      final core::int #t19 = 0;
+      if(this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceFieldWithInitializer' has been assigned during initialization.");
+      this.{self::B::_#B#finalInstanceFieldWithInitializer} = #t19;
+      this.{self::B::_#B#finalInstanceFieldWithInitializer#isSet} = true;
+    }
+    return let final core::int? #t20 = this.{self::B::_#B#finalInstanceFieldWithInitializer} in #t20{core::int};
+  }
   @#C1
   get covariantInstanceField() → core::num
-    return let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField} in #t21.==(null) ?{core::num} throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.") : #t21{core::num};
+    return this.{self::B::_#B#covariantInstanceField#isSet} ?{core::num} let final core::num? #t21 = this.{self::B::_#B#covariantInstanceField} in #t21{core::num} : throw new _in::LateInitializationErrorImpl::•("Field 'covariantInstanceField' has not been initialized.");
   @#C1
-  set covariantInstanceField(covariant core::num #t22) → void
+  set covariantInstanceField(covariant core::num #t22) → void {
+    this.{self::B::_#B#covariantInstanceField#isSet} = true;
     this.{self::B::_#B#covariantInstanceField} = #t22;
+  }
   @#C1
   static get staticField() → core::int
-    return let final core::int? #t23 = self::B::_#staticField in #t23.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t23{core::int};
+    return self::B::_#staticField#isSet ?{core::int} let final core::int? #t23 = self::B::_#staticField in #t23{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
   @#C1
-  static set staticField(core::int #t24) → void
+  static set staticField(core::int #t24) → void {
+    self::B::_#staticField#isSet = true;
     self::B::_#staticField = #t24;
+  }
   @#C1
   static get finalStaticField() → core::int
-    return let final core::int? #t25 = self::B::_#finalStaticField in #t25.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.") : #t25{core::int};
+    return self::B::_#finalStaticField#isSet ?{core::int} let final core::int? #t25 = self::B::_#finalStaticField in #t25{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has not been initialized.");
   @#C1
   static set finalStaticField(core::int #t26) → void
-    if(self::B::_#finalStaticField.==(null))
-      self::B::_#finalStaticField = #t26;
-    else
+    if(self::B::_#finalStaticField#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticField' has already been initialized.");
+    else {
+      self::B::_#finalStaticField#isSet = true;
+      self::B::_#finalStaticField = #t26;
+    }
   @#C1
-  static get finalStaticFieldWithInitializer() → core::int
-    return let final core::int? #t27 = self::B::_#finalStaticFieldWithInitializer in #t27.==(null) ?{core::int} let final core::int #t28 = 0 in self::B::_#finalStaticFieldWithInitializer.==(null) ?{core::int} self::B::_#finalStaticFieldWithInitializer = #t28 : throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.") : #t27{core::int};
+  static get finalStaticFieldWithInitializer() → core::int {
+    if(!self::B::_#finalStaticFieldWithInitializer#isSet) {
+      final core::int #t27 = 0;
+      if(self::B::_#finalStaticFieldWithInitializer#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'finalStaticFieldWithInitializer' has been assigned during initialization.");
+      self::B::_#finalStaticFieldWithInitializer = #t27;
+      self::B::_#finalStaticFieldWithInitializer#isSet = true;
+    }
+    return let final core::int? #t28 = self::B::_#finalStaticFieldWithInitializer in #t28{core::int};
+  }
 }
 extension Extension on self::A {
   static field extensionStaticField = self::_#Extension|extensionStaticField;
+  static field extensionStaticField = self::_#Extension|extensionStaticField#isSet;
   static get extensionStaticField = get self::Extension|extensionStaticField;
   static set extensionStaticField = set self::Extension|extensionStaticField;
   static field finalExtensionStaticField = self::_#Extension|finalExtensionStaticField;
+  static field finalExtensionStaticField = self::_#Extension|finalExtensionStaticField#isSet;
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
   static set finalExtensionStaticField = set self::Extension|finalExtensionStaticField;
   static field finalExtensionStaticFieldWithInitializer = self::_#Extension|finalExtensionStaticFieldWithInitializer;
+  static field finalExtensionStaticFieldWithInitializer = self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet;
   static get finalExtensionStaticFieldWithInitializer = get self::Extension|finalExtensionStaticFieldWithInitializer;
 }
 static field core::int? _#topLevelField = null;
+static field core::bool _#topLevelField#isSet = false;
 static field core::int? _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
 static field core::int? _#finalTopLevelFieldWithInitializer = null;
+static field core::bool _#finalTopLevelFieldWithInitializer#isSet = false;
 static field core::int? _#Extension|extensionStaticField = null;
+static field core::bool _#Extension|extensionStaticField#isSet = false;
 static field core::int? _#Extension|finalExtensionStaticField = null;
+static field core::bool _#Extension|finalExtensionStaticField#isSet = false;
 static field core::int? _#Extension|finalExtensionStaticFieldWithInitializer = null;
+static field core::bool _#Extension|finalExtensionStaticFieldWithInitializer#isSet = false;
 @#C1
 static get topLevelField() → core::int
-  return let final core::int? #t29 = self::_#topLevelField in #t29.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.") : #t29{core::int};
+  return self::_#topLevelField#isSet ?{core::int} let final core::int? #t29 = self::_#topLevelField in #t29{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.");
 @#C1
-static set topLevelField(core::int #t30) → void
+static set topLevelField(core::int #t30) → void {
+  self::_#topLevelField#isSet = true;
   self::_#topLevelField = #t30;
+}
 @#C1
 static get finalTopLevelField() → core::int
-  return let final core::int? #t31 = self::_#finalTopLevelField in #t31.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.") : #t31{core::int};
+  return self::_#finalTopLevelField#isSet ?{core::int} let final core::int? #t31 = self::_#finalTopLevelField in #t31{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
 @#C1
 static set finalTopLevelField(core::int #t32) → void
-  if(self::_#finalTopLevelField.==(null))
-    self::_#finalTopLevelField = #t32;
-  else
+  if(self::_#finalTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    self::_#finalTopLevelField#isSet = true;
+    self::_#finalTopLevelField = #t32;
+  }
 @#C1
-static get finalTopLevelFieldWithInitializer() → core::int
-  return let final core::int? #t33 = self::_#finalTopLevelFieldWithInitializer in #t33.==(null) ?{core::int} let final core::int #t34 = 0 in self::_#finalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#finalTopLevelFieldWithInitializer = #t34 : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t33{core::int};
+static get finalTopLevelFieldWithInitializer() → core::int {
+  if(!self::_#finalTopLevelFieldWithInitializer#isSet) {
+    final core::int #t33 = 0;
+    if(self::_#finalTopLevelFieldWithInitializer#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelFieldWithInitializer' has been assigned during initialization.");
+    self::_#finalTopLevelFieldWithInitializer = #t33;
+    self::_#finalTopLevelFieldWithInitializer#isSet = true;
+  }
+  return let final core::int? #t34 = self::_#finalTopLevelFieldWithInitializer in #t34{core::int};
+}
 @#C1
 static get Extension|extensionStaticField() → core::int
-  return let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'extensionStaticField' has not been initialized.") : #t35{core::int};
+  return self::_#Extension|extensionStaticField#isSet ?{core::int} let final core::int? #t35 = self::_#Extension|extensionStaticField in #t35{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'extensionStaticField' has not been initialized.");
 @#C1
-static set Extension|extensionStaticField(core::int #t36) → void
+static set Extension|extensionStaticField(core::int #t36) → void {
+  self::_#Extension|extensionStaticField#isSet = true;
   self::_#Extension|extensionStaticField = #t36;
+}
 @#C1
 static get Extension|finalExtensionStaticField() → core::int
-  return let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has not been initialized.") : #t37{core::int};
+  return self::_#Extension|finalExtensionStaticField#isSet ?{core::int} let final core::int? #t37 = self::_#Extension|finalExtensionStaticField in #t37{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has not been initialized.");
 @#C1
 static set Extension|finalExtensionStaticField(core::int #t38) → void
-  if(self::_#Extension|finalExtensionStaticField.==(null))
-    self::_#Extension|finalExtensionStaticField = #t38;
-  else
+  if(self::_#Extension|finalExtensionStaticField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticField' has already been initialized.");
+  else {
+    self::_#Extension|finalExtensionStaticField#isSet = true;
+    self::_#Extension|finalExtensionStaticField = #t38;
+  }
 @#C1
-static get Extension|finalExtensionStaticFieldWithInitializer() → core::int
-  return let final core::int? #t39 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t39.==(null) ?{core::int} let final core::int #t40 = 0 in self::_#Extension|finalExtensionStaticFieldWithInitializer.==(null) ?{core::int} self::_#Extension|finalExtensionStaticFieldWithInitializer = #t40 : throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticFieldWithInitializer' has been assigned during initialization.") : #t39{core::int};
+static get Extension|finalExtensionStaticFieldWithInitializer() → core::int {
+  if(!self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet) {
+    final core::int #t39 = 0;
+    if(self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalExtensionStaticFieldWithInitializer' has been assigned during initialization.");
+    self::_#Extension|finalExtensionStaticFieldWithInitializer = #t39;
+    self::_#Extension|finalExtensionStaticFieldWithInitializer#isSet = true;
+  }
+  return let final core::int? #t40 = self::_#Extension|finalExtensionStaticFieldWithInitializer in #t40{core::int};
+}
 static method main() → dynamic {}
 
 constants  {
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
index d9bfacd..ce355da 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.expect
@@ -14,10 +14,17 @@
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-  get nonNullableInstanceField() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField} in #t1.==(null) ?{core::int} this.{self::A::_#A#nonNullableInstanceField} = 0 : #t1{core::int};
-  set nonNullableInstanceField(core::int #t2) → void
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::A::_#A#nonNullableInstanceField#isSet}) {
+      this.{self::A::_#A#nonNullableInstanceField} = 0;
+      this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField} in #t1{core::int};
+  }
+  set nonNullableInstanceField(core::int #t2) → void {
+    this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
     this.{self::A::_#A#nonNullableInstanceField} = #t2;
+  }
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}) {
       this.{self::A::_#A#nullableInstanceField} = self::method();
@@ -29,10 +36,17 @@
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
     this.{self::A::_#A#nullableInstanceField} = #t3;
   }
-  static get nonNullableStaticField() → core::int
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4.==(null) ?{core::int} self::A::_#nonNullableStaticField = 0 : #t4{core::int};
-  static set nonNullableStaticField(core::int #t5) → void
+  static get nonNullableStaticField() → core::int {
+    if(!self::A::_#nonNullableStaticField#isSet) {
+      self::A::_#nonNullableStaticField = 0;
+      self::A::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4{core::int};
+  }
+  static set nonNullableStaticField(core::int #t5) → void {
+    self::A::_#nonNullableStaticField#isSet = true;
     self::A::_#nonNullableStaticField = #t5;
+  }
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
       self::A::_#nullableStaticField = self::method();
@@ -62,10 +76,17 @@
 static field core::bool _#nullableTopLevelField#isSet = false;
 static method method() → core::int?
   return null;
-static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelField = 0 : #t7{core::int};
-static set nonNullableTopLevelField(core::int #t8) → void
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    self::_#nonNullableTopLevelField = 0;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7{core::int};
+}
+static set nonNullableTopLevelField(core::int #t8) → void {
+  self::_#nonNullableTopLevelField#isSet = true;
   self::_#nonNullableTopLevelField = #t8;
+}
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     self::_#nullableTopLevelField = self::method();
diff --git a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
index d9bfacd..ce355da 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_inference.dart.weak.transformed.expect
@@ -14,10 +14,17 @@
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-  get nonNullableInstanceField() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField} in #t1.==(null) ?{core::int} this.{self::A::_#A#nonNullableInstanceField} = 0 : #t1{core::int};
-  set nonNullableInstanceField(core::int #t2) → void
+  get nonNullableInstanceField() → core::int {
+    if(!this.{self::A::_#A#nonNullableInstanceField#isSet}) {
+      this.{self::A::_#A#nonNullableInstanceField} = 0;
+      this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::A::_#A#nonNullableInstanceField} in #t1{core::int};
+  }
+  set nonNullableInstanceField(core::int #t2) → void {
+    this.{self::A::_#A#nonNullableInstanceField#isSet} = true;
     this.{self::A::_#A#nonNullableInstanceField} = #t2;
+  }
   get nullableInstanceField() → core::int? {
     if(!this.{self::A::_#A#nullableInstanceField#isSet}) {
       this.{self::A::_#A#nullableInstanceField} = self::method();
@@ -29,10 +36,17 @@
     this.{self::A::_#A#nullableInstanceField#isSet} = true;
     this.{self::A::_#A#nullableInstanceField} = #t3;
   }
-  static get nonNullableStaticField() → core::int
-    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4.==(null) ?{core::int} self::A::_#nonNullableStaticField = 0 : #t4{core::int};
-  static set nonNullableStaticField(core::int #t5) → void
+  static get nonNullableStaticField() → core::int {
+    if(!self::A::_#nonNullableStaticField#isSet) {
+      self::A::_#nonNullableStaticField = 0;
+      self::A::_#nonNullableStaticField#isSet = true;
+    }
+    return let final core::int? #t4 = self::A::_#nonNullableStaticField in #t4{core::int};
+  }
+  static set nonNullableStaticField(core::int #t5) → void {
+    self::A::_#nonNullableStaticField#isSet = true;
     self::A::_#nonNullableStaticField = #t5;
+  }
   static get nullableStaticField() → core::int? {
     if(!self::A::_#nullableStaticField#isSet) {
       self::A::_#nullableStaticField = self::method();
@@ -62,10 +76,17 @@
 static field core::bool _#nullableTopLevelField#isSet = false;
 static method method() → core::int?
   return null;
-static get nonNullableTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelField = 0 : #t7{core::int};
-static set nonNullableTopLevelField(core::int #t8) → void
+static get nonNullableTopLevelField() → core::int {
+  if(!self::_#nonNullableTopLevelField#isSet) {
+    self::_#nonNullableTopLevelField = 0;
+    self::_#nonNullableTopLevelField#isSet = true;
+  }
+  return let final core::int? #t7 = self::_#nonNullableTopLevelField in #t7{core::int};
+}
+static set nonNullableTopLevelField(core::int #t8) → void {
+  self::_#nonNullableTopLevelField#isSet = true;
   self::_#nonNullableTopLevelField = #t8;
+}
 static get nullableTopLevelField() → core::int? {
   if(!self::_#nullableTopLevelField#isSet) {
     self::_#nullableTopLevelField = self::method();
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
index 4030034..f6025fa 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
@@ -4,8 +4,11 @@
 
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   final field self::Class::T% field;
   generic-covariant-impl field self::Class::T? _#Class#lateGenericField1 = null;
   field core::bool _#Class#lateGenericField1#isSet = false;
@@ -14,23 +17,44 @@
   constructor •(self::Class::T% field) → self::Class<self::Class::T%>
     : self::Class::field = field, super core::Object::•()
     ;
-  static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+  static get lateStaticField1() → core::int {
+    if(!self::Class::_#lateStaticField1#isSet) {
+      self::Class::_#lateStaticField1 = 87;
+      self::Class::_#lateStaticField1#isSet = true;
+    }
+    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int};
+  }
+  static set lateStaticField1(core::int #t2) → void {
+    self::Class::_#lateStaticField1#isSet = true;
     self::Class::_#lateStaticField1 = #t2;
-  static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+  }
+  static get lateStaticField2() → core::int {
+    if(!self::Class::_#lateStaticField2#isSet) {
+      self::Class::_#lateStaticField2 = 42;
+      self::Class::_#lateStaticField2#isSet = true;
+    }
+    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int};
+  }
+  static set lateStaticField2(core::int #t4) → void {
+    self::Class::_#lateStaticField2#isSet = true;
     self::Class::_#lateStaticField2 = #t4;
+  }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
     self::Class::lateStaticField2 = 43;
     self::expect(43, self::Class::lateStaticField2);
   }
-  get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+  get lateInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#lateInstanceField#isSet}) {
+      this.{self::Class::_#Class#lateInstanceField} = 16;
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+    }
+    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int};
+  }
+  set lateInstanceField(core::int #t6) → void {
+    this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateInstanceField} = #t6;
+  }
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field};
@@ -66,28 +90,54 @@
 }
 extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField1 = null;
+static field core::bool _#lateTopLevelField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
-static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
-static set lateTopLevelField1(core::int #t12) → void
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
+static get lateTopLevelField1() → core::int {
+  if(!self::_#lateTopLevelField1#isSet) {
+    self::_#lateTopLevelField1 = 123;
+    self::_#lateTopLevelField1#isSet = true;
+  }
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11{core::int};
+}
+static set lateTopLevelField1(core::int #t12) → void {
+  self::_#lateTopLevelField1#isSet = true;
   self::_#lateTopLevelField1 = #t12;
-static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
-static set Extension|lateExtensionField1(core::int #t14) → void
+}
+static get Extension|lateExtensionField1() → core::int {
+  if(!self::_#Extension|lateExtensionField1#isSet) {
+    self::_#Extension|lateExtensionField1 = 87;
+    self::_#Extension|lateExtensionField1#isSet = true;
+  }
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13{core::int};
+}
+static set Extension|lateExtensionField1(core::int #t14) → void {
+  self::_#Extension|lateExtensionField1#isSet = true;
   self::_#Extension|lateExtensionField1 = #t14;
-static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
-static set Extension|lateExtensionField2(core::int #t16) → void
+}
+static get Extension|lateExtensionField2() → core::int {
+  if(!self::_#Extension|lateExtensionField2#isSet) {
+    self::_#Extension|lateExtensionField2 = 42;
+    self::_#Extension|lateExtensionField2#isSet = true;
+  }
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15{core::int};
+}
+static set Extension|lateExtensionField2(core::int #t16) → void {
+  self::_#Extension|lateExtensionField2#isSet = true;
   self::_#Extension|lateExtensionField2 = #t16;
+}
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
index 4030034..f6025fa 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
@@ -4,8 +4,11 @@
 
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   final field self::Class::T% field;
   generic-covariant-impl field self::Class::T? _#Class#lateGenericField1 = null;
   field core::bool _#Class#lateGenericField1#isSet = false;
@@ -14,23 +17,44 @@
   constructor •(self::Class::T% field) → self::Class<self::Class::T%>
     : self::Class::field = field, super core::Object::•()
     ;
-  static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} self::Class::_#lateStaticField1 = 87 : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+  static get lateStaticField1() → core::int {
+    if(!self::Class::_#lateStaticField1#isSet) {
+      self::Class::_#lateStaticField1 = 87;
+      self::Class::_#lateStaticField1#isSet = true;
+    }
+    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int};
+  }
+  static set lateStaticField1(core::int #t2) → void {
+    self::Class::_#lateStaticField1#isSet = true;
     self::Class::_#lateStaticField1 = #t2;
-  static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} self::Class::_#lateStaticField2 = 42 : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+  }
+  static get lateStaticField2() → core::int {
+    if(!self::Class::_#lateStaticField2#isSet) {
+      self::Class::_#lateStaticField2 = 42;
+      self::Class::_#lateStaticField2#isSet = true;
+    }
+    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int};
+  }
+  static set lateStaticField2(core::int #t4) → void {
+    self::Class::_#lateStaticField2#isSet = true;
     self::Class::_#lateStaticField2 = #t4;
+  }
   static method staticMethod() → dynamic {
     self::expect(42, self::Class::lateStaticField2);
     self::Class::lateStaticField2 = 43;
     self::expect(43, self::Class::lateStaticField2);
   }
-  get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = 16 : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+  get lateInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#lateInstanceField#isSet}) {
+      this.{self::Class::_#Class#lateInstanceField} = 16;
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+    }
+    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int};
+  }
+  set lateInstanceField(core::int #t6) → void {
+    this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateInstanceField} = #t6;
+  }
   get lateGenericField1() → self::Class::T% {
     if(!this.{self::Class::_#Class#lateGenericField1#isSet}) {
       this.{self::Class::_#Class#lateGenericField1} = this.{self::Class::field};
@@ -66,28 +90,54 @@
 }
 extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField1 = null;
+static field core::bool _#lateTopLevelField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
-static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} self::_#lateTopLevelField1 = 123 : #t11{core::int};
-static set lateTopLevelField1(core::int #t12) → void
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
+static get lateTopLevelField1() → core::int {
+  if(!self::_#lateTopLevelField1#isSet) {
+    self::_#lateTopLevelField1 = 123;
+    self::_#lateTopLevelField1#isSet = true;
+  }
+  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11{core::int};
+}
+static set lateTopLevelField1(core::int #t12) → void {
+  self::_#lateTopLevelField1#isSet = true;
   self::_#lateTopLevelField1 = #t12;
-static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = 87 : #t13{core::int};
-static set Extension|lateExtensionField1(core::int #t14) → void
+}
+static get Extension|lateExtensionField1() → core::int {
+  if(!self::_#Extension|lateExtensionField1#isSet) {
+    self::_#Extension|lateExtensionField1 = 87;
+    self::_#Extension|lateExtensionField1#isSet = true;
+  }
+  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13{core::int};
+}
+static set Extension|lateExtensionField1(core::int #t14) → void {
+  self::_#Extension|lateExtensionField1#isSet = true;
   self::_#Extension|lateExtensionField1 = #t14;
-static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = 42 : #t15{core::int};
-static set Extension|lateExtensionField2(core::int #t16) → void
+}
+static get Extension|lateExtensionField2() → core::int {
+  if(!self::_#Extension|lateExtensionField2#isSet) {
+    self::_#Extension|lateExtensionField2 = 42;
+    self::_#Extension|lateExtensionField2#isSet = true;
+  }
+  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15{core::int};
+}
+static set Extension|lateExtensionField2(core::int #t16) → void {
+  self::_#Extension|lateExtensionField2#isSet = true;
   self::_#Extension|lateExtensionField2 = #t16;
+}
 static method Extension|staticMethod() → dynamic {
   self::expect(42, self::Extension|lateExtensionField2);
   self::Extension|lateExtensionField2 = 43;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index 28513d18..4d4ab11 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -5,30 +5,39 @@
 
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   generic-covariant-impl field self::Class::T? _#Class#lateGenericInstanceField = null;
   field core::bool _#Class#lateGenericInstanceField#isSet = false;
   synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+    return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.");
+  static set lateStaticField1(core::int #t2) → void {
+    self::Class::_#lateStaticField1#isSet = true;
     self::Class::_#lateStaticField1 = #t2;
+  }
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.");
+  static set lateStaticField2(core::int #t4) → void {
+    self::Class::_#lateStaticField2#isSet = true;
     self::Class::_#lateStaticField2 = #t4;
+  }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+    return this.{self::Class::_#Class#lateInstanceField#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.");
+  set lateInstanceField(core::int #t6) → void {
+    this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateInstanceField} = #t6;
+  }
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
   set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
@@ -46,28 +55,39 @@
 }
 extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField = null;
+static field core::bool _#lateTopLevelField#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
-static set lateTopLevelField(core::int #t10) → void
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t9 = self::_#lateTopLevelField in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
+static set lateTopLevelField(core::int #t10) → void {
+  self::_#lateTopLevelField#isSet = true;
   self::_#lateTopLevelField = #t10;
+}
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField1(core::int #t12) → void
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
+static set Extension|lateExtensionField1(core::int #t12) → void {
+  self::_#Extension|lateExtensionField1#isSet = true;
   self::_#Extension|lateExtensionField1 = #t12;
+}
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
-static set Extension|lateExtensionField2(core::int #t14) → void
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
+static set Extension|lateExtensionField2(core::int #t14) → void {
+  self::_#Extension|lateExtensionField2#isSet = true;
   self::_#Extension|lateExtensionField2 = #t14;
+}
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index 28513d18..4d4ab11 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -5,30 +5,39 @@
 
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   generic-covariant-impl field self::Class::T? _#Class#lateGenericInstanceField = null;
   field core::bool _#Class#lateGenericInstanceField#isSet = false;
   synthetic constructor •() → self::Class<self::Class::T%>
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.") : #t1{core::int};
-  static set lateStaticField1(core::int #t2) → void
+    return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.");
+  static set lateStaticField1(core::int #t2) → void {
+    self::Class::_#lateStaticField1#isSet = true;
     self::Class::_#lateStaticField1 = #t2;
+  }
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.") : #t3{core::int};
-  static set lateStaticField2(core::int #t4) → void
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.");
+  static set lateStaticField2(core::int #t4) → void {
+    self::Class::_#lateStaticField2#isSet = true;
     self::Class::_#lateStaticField2 = #t4;
+  }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
     self::expect(42, self::Class::lateStaticField2);
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
-  set lateInstanceField(core::int #t6) → void
+    return this.{self::Class::_#Class#lateInstanceField#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.");
+  set lateInstanceField(core::int #t6) → void {
+    this.{self::Class::_#Class#lateInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateInstanceField} = #t6;
+  }
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
   set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
@@ -46,28 +55,39 @@
 }
 extension Extension<T extends core::Object? = dynamic> on self::Class<T%> {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField = null;
+static field core::bool _#lateTopLevelField#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t9 = self::_#lateTopLevelField in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t9{core::int};
-static set lateTopLevelField(core::int #t10) → void
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t9 = self::_#lateTopLevelField in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
+static set lateTopLevelField(core::int #t10) → void {
+  self::_#lateTopLevelField#isSet = true;
   self::_#lateTopLevelField = #t10;
+}
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t11{core::int};
-static set Extension|lateExtensionField1(core::int #t12) → void
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField1 in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
+static set Extension|lateExtensionField1(core::int #t12) → void {
+  self::_#Extension|lateExtensionField1#isSet = true;
   self::_#Extension|lateExtensionField1 = #t12;
+}
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t13{core::int};
-static set Extension|lateExtensionField2(core::int #t14) → void
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t13 = self::_#Extension|lateExtensionField2 in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
+static set Extension|lateExtensionField2(core::int #t14) → void {
+  self::_#Extension|lateExtensionField2#isSet = true;
   self::_#Extension|lateExtensionField2 = #t14;
+}
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
index e1e5f51..af7e11a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.expect
@@ -15,18 +15,29 @@
   constructor •(core::int x) → self::C
     : super self::B::•(x)
     ;
-  get y() → core::int
-    return let final core::int? #t1 = this.{self::C::_#C#y} in #t1.==(null) ?{core::int} let final core::int #t2 = this.{self::B::x}.{core::num::+}(1) in this.{self::C::_#C#y}.==(null) ?{core::int} this.{self::C::_#C#y} = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'y' has been assigned during initialization.") : #t1{core::int};
+  get y() → core::int {
+    if(!this.{self::C::_#C#y#isSet}) {
+      final core::int #t1 = this.{self::B::x}.{core::num::+}(1);
+      if(this.{self::C::_#C#y#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'y' has been assigned during initialization.");
+      this.{self::C::_#C#y} = #t1;
+      this.{self::C::_#C#y#isSet} = true;
+    }
+    return let final core::int? #t2 = this.{self::C::_#C#y} in #t2{core::int};
+  }
   method method() → dynamic
     return this.{self::B::x};
 }
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
   final field self::Class::T% field;
   field self::Class::T? _#Class#lateGenericField = null;
@@ -37,13 +48,29 @@
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
   }
-  static get lateStaticField1() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField1 in #t3.==(null) ?{core::int} let final core::int #t4 = self::Class::initLateStaticField1(87) in self::Class::_#lateStaticField1.==(null) ?{core::int} self::Class::_#lateStaticField1 = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.") : #t3{core::int};
+  static get lateStaticField1() → core::int {
+    if(!self::Class::_#lateStaticField1#isSet) {
+      final core::int #t3 = self::Class::initLateStaticField1(87);
+      if(self::Class::_#lateStaticField1#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.");
+      self::Class::_#lateStaticField1 = #t3;
+      self::Class::_#lateStaticField1#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#lateStaticField1 in #t4{core::int};
+  }
   static method initLateStaticField2(core::int value) → core::int {
     return self::Class::lateStaticField2Init = value;
   }
-  static get lateStaticField2() → core::int
-    return let final core::int? #t5 = self::Class::_#lateStaticField2 in #t5.==(null) ?{core::int} let final core::int #t6 = self::Class::initLateStaticField2(42) in self::Class::_#lateStaticField2.==(null) ?{core::int} self::Class::_#lateStaticField2 = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.") : #t5{core::int};
+  static get lateStaticField2() → core::int {
+    if(!self::Class::_#lateStaticField2#isSet) {
+      final core::int #t5 = self::Class::initLateStaticField2(42);
+      if(self::Class::_#lateStaticField2#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.");
+      self::Class::_#lateStaticField2 = #t5;
+      self::Class::_#lateStaticField2#isSet = true;
+    }
+    return let final core::int? #t6 = self::Class::_#lateStaticField2 in #t6{core::int};
+  }
   static method staticMethod() → dynamic {
     self::expect(null, self::Class::lateStaticField2Init);
     self::expect(42, self::Class::lateStaticField2);
@@ -52,8 +79,16 @@
   method initLateInstanceField(core::int value) → core::int {
     return this.{self::Class::lateInstanceFieldInit} = value;
   }
-  get lateInstanceField() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#lateInstanceField} in #t7.==(null) ?{core::int} let final core::int #t8 = this.{self::Class::initLateInstanceField}(16) in this.{self::Class::_#Class#lateInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = #t8 : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.") : #t7{core::int};
+  get lateInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#lateInstanceField#isSet}) {
+      final core::int #t7 = this.{self::Class::initLateInstanceField}(16);
+      if(this.{self::Class::_#Class#lateInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#lateInstanceField} = #t7;
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+    }
+    return let final core::int? #t8 = this.{self::Class::_#Class#lateInstanceField} in #t8{core::int};
+  }
   method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
     return this.{self::Class::lateGenericFieldInit} = value;
   }
@@ -80,34 +115,63 @@
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static field lateExtensionField2Init = self::Extension|lateExtensionField2Init;
   static method initLateExtensionField2 = self::Extension|initLateExtensionField2;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? lateTopLevelField1Init;
 static field core::int? _#lateTopLevelField1 = null;
+static field core::bool _#lateTopLevelField1#isSet = false;
 static field core::int? Extension|lateExtensionField1Init;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? Extension|lateExtensionField2Init;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static method initLateTopLevelField1(core::int value) → core::int {
   return self::lateTopLevelField1Init = value;
 }
-static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} let final core::int #t12 = self::initLateTopLevelField1(123) in self::_#lateTopLevelField1.==(null) ?{core::int} self::_#lateTopLevelField1 = #t12 : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.") : #t11{core::int};
+static get lateTopLevelField1() → core::int {
+  if(!self::_#lateTopLevelField1#isSet) {
+    final core::int #t11 = self::initLateTopLevelField1(123);
+    if(self::_#lateTopLevelField1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.");
+    self::_#lateTopLevelField1 = #t11;
+    self::_#lateTopLevelField1#isSet = true;
+  }
+  return let final core::int? #t12 = self::_#lateTopLevelField1 in #t12{core::int};
+}
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
-static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} let final core::int #t14 = self::Extension|initLateExtensionField1(87) in self::_#Extension|lateExtensionField1.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.") : #t13{core::int};
+static get Extension|lateExtensionField1() → core::int {
+  if(!self::_#Extension|lateExtensionField1#isSet) {
+    final core::int #t13 = self::Extension|initLateExtensionField1(87);
+    if(self::_#Extension|lateExtensionField1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.");
+    self::_#Extension|lateExtensionField1 = #t13;
+    self::_#Extension|lateExtensionField1#isSet = true;
+  }
+  return let final core::int? #t14 = self::_#Extension|lateExtensionField1 in #t14{core::int};
+}
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
-static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} let final core::int #t16 = self::Extension|initLateExtensionField2(42) in self::_#Extension|lateExtensionField2.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.") : #t15{core::int};
+static get Extension|lateExtensionField2() → core::int {
+  if(!self::_#Extension|lateExtensionField2#isSet) {
+    final core::int #t15 = self::Extension|initLateExtensionField2(42);
+    if(self::_#Extension|lateExtensionField2#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.");
+    self::_#Extension|lateExtensionField2 = #t15;
+    self::_#Extension|lateExtensionField2#isSet = true;
+  }
+  return let final core::int? #t16 = self::_#Extension|lateExtensionField2 in #t16{core::int};
+}
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
index e1e5f51..af7e11a 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_with_initializer.dart.weak.transformed.expect
@@ -15,18 +15,29 @@
   constructor •(core::int x) → self::C
     : super self::B::•(x)
     ;
-  get y() → core::int
-    return let final core::int? #t1 = this.{self::C::_#C#y} in #t1.==(null) ?{core::int} let final core::int #t2 = this.{self::B::x}.{core::num::+}(1) in this.{self::C::_#C#y}.==(null) ?{core::int} this.{self::C::_#C#y} = #t2 : throw new _in::LateInitializationErrorImpl::•("Field 'y' has been assigned during initialization.") : #t1{core::int};
+  get y() → core::int {
+    if(!this.{self::C::_#C#y#isSet}) {
+      final core::int #t1 = this.{self::B::x}.{core::num::+}(1);
+      if(this.{self::C::_#C#y#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'y' has been assigned during initialization.");
+      this.{self::C::_#C#y} = #t1;
+      this.{self::C::_#C#y#isSet} = true;
+    }
+    return let final core::int? #t2 = this.{self::C::_#C#y} in #t2{core::int};
+  }
   method method() → dynamic
     return this.{self::B::x};
 }
 class Class<T extends core::Object? = dynamic> extends core::Object {
   static field core::int? lateStaticField1Init = null;
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? lateStaticField2Init = null;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? lateInstanceFieldInit = null;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   generic-covariant-impl field self::Class::T? lateGenericFieldInit = null;
   final field self::Class::T% field;
   field self::Class::T? _#Class#lateGenericField = null;
@@ -37,13 +48,29 @@
   static method initLateStaticField1(core::int value) → core::int {
     return self::Class::lateStaticField1Init = value;
   }
-  static get lateStaticField1() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField1 in #t3.==(null) ?{core::int} let final core::int #t4 = self::Class::initLateStaticField1(87) in self::Class::_#lateStaticField1.==(null) ?{core::int} self::Class::_#lateStaticField1 = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.") : #t3{core::int};
+  static get lateStaticField1() → core::int {
+    if(!self::Class::_#lateStaticField1#isSet) {
+      final core::int #t3 = self::Class::initLateStaticField1(87);
+      if(self::Class::_#lateStaticField1#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has been assigned during initialization.");
+      self::Class::_#lateStaticField1 = #t3;
+      self::Class::_#lateStaticField1#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#lateStaticField1 in #t4{core::int};
+  }
   static method initLateStaticField2(core::int value) → core::int {
     return self::Class::lateStaticField2Init = value;
   }
-  static get lateStaticField2() → core::int
-    return let final core::int? #t5 = self::Class::_#lateStaticField2 in #t5.==(null) ?{core::int} let final core::int #t6 = self::Class::initLateStaticField2(42) in self::Class::_#lateStaticField2.==(null) ?{core::int} self::Class::_#lateStaticField2 = #t6 : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.") : #t5{core::int};
+  static get lateStaticField2() → core::int {
+    if(!self::Class::_#lateStaticField2#isSet) {
+      final core::int #t5 = self::Class::initLateStaticField2(42);
+      if(self::Class::_#lateStaticField2#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has been assigned during initialization.");
+      self::Class::_#lateStaticField2 = #t5;
+      self::Class::_#lateStaticField2#isSet = true;
+    }
+    return let final core::int? #t6 = self::Class::_#lateStaticField2 in #t6{core::int};
+  }
   static method staticMethod() → dynamic {
     self::expect(null, self::Class::lateStaticField2Init);
     self::expect(42, self::Class::lateStaticField2);
@@ -52,8 +79,16 @@
   method initLateInstanceField(core::int value) → core::int {
     return this.{self::Class::lateInstanceFieldInit} = value;
   }
-  get lateInstanceField() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#lateInstanceField} in #t7.==(null) ?{core::int} let final core::int #t8 = this.{self::Class::initLateInstanceField}(16) in this.{self::Class::_#Class#lateInstanceField}.==(null) ?{core::int} this.{self::Class::_#Class#lateInstanceField} = #t8 : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.") : #t7{core::int};
+  get lateInstanceField() → core::int {
+    if(!this.{self::Class::_#Class#lateInstanceField#isSet}) {
+      final core::int #t7 = this.{self::Class::initLateInstanceField}(16);
+      if(this.{self::Class::_#Class#lateInstanceField#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has been assigned during initialization.");
+      this.{self::Class::_#Class#lateInstanceField} = #t7;
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+    }
+    return let final core::int? #t8 = this.{self::Class::_#Class#lateInstanceField} in #t8{core::int};
+  }
   method initLateGenericField(generic-covariant-impl self::Class::T% value) → self::Class::T% {
     return this.{self::Class::lateGenericFieldInit} = value;
   }
@@ -80,34 +115,63 @@
   static field lateExtensionField1Init = self::Extension|lateExtensionField1Init;
   static method initLateExtensionField1 = self::Extension|initLateExtensionField1;
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static field lateExtensionField2Init = self::Extension|lateExtensionField2Init;
   static method initLateExtensionField2 = self::Extension|initLateExtensionField2;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? lateTopLevelField1Init;
 static field core::int? _#lateTopLevelField1 = null;
+static field core::bool _#lateTopLevelField1#isSet = false;
 static field core::int? Extension|lateExtensionField1Init;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? Extension|lateExtensionField2Init;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static method initLateTopLevelField1(core::int value) → core::int {
   return self::lateTopLevelField1Init = value;
 }
-static get lateTopLevelField1() → core::int
-  return let final core::int? #t11 = self::_#lateTopLevelField1 in #t11.==(null) ?{core::int} let final core::int #t12 = self::initLateTopLevelField1(123) in self::_#lateTopLevelField1.==(null) ?{core::int} self::_#lateTopLevelField1 = #t12 : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.") : #t11{core::int};
+static get lateTopLevelField1() → core::int {
+  if(!self::_#lateTopLevelField1#isSet) {
+    final core::int #t11 = self::initLateTopLevelField1(123);
+    if(self::_#lateTopLevelField1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField1' has been assigned during initialization.");
+    self::_#lateTopLevelField1 = #t11;
+    self::_#lateTopLevelField1#isSet = true;
+  }
+  return let final core::int? #t12 = self::_#lateTopLevelField1 in #t12{core::int};
+}
 static method Extension|initLateExtensionField1(core::int value) → core::int {
   return self::Extension|lateExtensionField1Init = value;
 }
-static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t13 = self::_#Extension|lateExtensionField1 in #t13.==(null) ?{core::int} let final core::int #t14 = self::Extension|initLateExtensionField1(87) in self::_#Extension|lateExtensionField1.==(null) ?{core::int} self::_#Extension|lateExtensionField1 = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.") : #t13{core::int};
+static get Extension|lateExtensionField1() → core::int {
+  if(!self::_#Extension|lateExtensionField1#isSet) {
+    final core::int #t13 = self::Extension|initLateExtensionField1(87);
+    if(self::_#Extension|lateExtensionField1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has been assigned during initialization.");
+    self::_#Extension|lateExtensionField1 = #t13;
+    self::_#Extension|lateExtensionField1#isSet = true;
+  }
+  return let final core::int? #t14 = self::_#Extension|lateExtensionField1 in #t14{core::int};
+}
 static method Extension|initLateExtensionField2(core::int value) → core::int {
   return self::Extension|lateExtensionField2Init = value;
 }
-static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t15 = self::_#Extension|lateExtensionField2 in #t15.==(null) ?{core::int} let final core::int #t16 = self::Extension|initLateExtensionField2(42) in self::_#Extension|lateExtensionField2.==(null) ?{core::int} self::_#Extension|lateExtensionField2 = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.") : #t15{core::int};
+static get Extension|lateExtensionField2() → core::int {
+  if(!self::_#Extension|lateExtensionField2#isSet) {
+    final core::int #t15 = self::Extension|initLateExtensionField2(42);
+    if(self::_#Extension|lateExtensionField2#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has been assigned during initialization.");
+    self::_#Extension|lateExtensionField2 = #t15;
+    self::_#Extension|lateExtensionField2#isSet = true;
+  }
+  return let final core::int? #t16 = self::_#Extension|lateExtensionField2 in #t16{core::int};
+}
 static method Extension|staticMethod() → dynamic {
   self::expect(null, self::Extension|lateExtensionField2Init);
   self::expect(42, self::Extension|lateExtensionField2);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
index 6c0bb20..381a0ba 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.expect
@@ -5,25 +5,32 @@
 
 class Class extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.") : #t1{core::int};
+    return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.");
   static set lateStaticField1(core::int #t2) → void
-    if(self::Class::_#lateStaticField1.==(null))
-      self::Class::_#lateStaticField1 = #t2;
-    else
+    if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has already been initialized.");
+    else {
+      self::Class::_#lateStaticField1#isSet = true;
+      self::Class::_#lateStaticField1 = #t2;
+    }
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.") : #t3{core::int};
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.");
   static set lateStaticField2(core::int #t4) → void
-    if(self::Class::_#lateStaticField2.==(null))
-      self::Class::_#lateStaticField2 = #t4;
-    else
+    if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has already been initialized.");
+    else {
+      self::Class::_#lateStaticField2#isSet = true;
+      self::Class::_#lateStaticField2 = #t4;
+    }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
@@ -31,12 +38,14 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
+    return this.{self::Class::_#Class#lateInstanceField#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.");
   set lateInstanceField(core::int #t6) → void
-    if(this.{self::Class::_#Class#lateInstanceField}.==(null))
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
-    else
+    if(this.{self::Class::_#Class#lateInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+      this.{self::Class::_#Class#lateInstanceField} = #t6;
+    }
   method instanceMethod() → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
@@ -46,37 +55,48 @@
 }
 extension Extension on self::Class {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField = null;
+static field core::bool _#lateTopLevelField#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t7 = self::_#lateTopLevelField in #t7{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
 static set lateTopLevelField(core::int #t8) → void
-  if(self::_#lateTopLevelField.==(null))
-    self::_#lateTopLevelField = #t8;
-  else
+  if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
+  else {
+    self::_#lateTopLevelField#isSet = true;
+    self::_#lateTopLevelField = #t8;
+  }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
 static set Extension|lateExtensionField1(core::int #t10) → void
-  if(self::_#Extension|lateExtensionField1.==(null))
-    self::_#Extension|lateExtensionField1 = #t10;
-  else
+  if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
+  else {
+    self::_#Extension|lateExtensionField1#isSet = true;
+    self::_#Extension|lateExtensionField1 = #t10;
+  }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
 static set Extension|lateExtensionField2(core::int #t12) → void
-  if(self::_#Extension|lateExtensionField2.==(null))
-    self::_#Extension|lateExtensionField2 = #t12;
-  else
+  if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
+  else {
+    self::_#Extension|lateExtensionField2#isSet = true;
+    self::_#Extension|lateExtensionField2 = #t12;
+  }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
index 6c0bb20..381a0ba 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_field_without_initializer.dart.weak.transformed.expect
@@ -5,25 +5,32 @@
 
 class Class extends core::Object {
   static field core::int? _#lateStaticField1 = null;
+  static field core::bool _#lateStaticField1#isSet = false;
   static field core::int? _#lateStaticField2 = null;
+  static field core::bool _#lateStaticField2#isSet = false;
   field core::int? _#Class#lateInstanceField = null;
+  field core::bool _#Class#lateInstanceField#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
   static get lateStaticField1() → core::int
-    return let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.") : #t1{core::int};
+    return self::Class::_#lateStaticField1#isSet ?{core::int} let final core::int? #t1 = self::Class::_#lateStaticField1 in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has not been initialized.");
   static set lateStaticField1(core::int #t2) → void
-    if(self::Class::_#lateStaticField1.==(null))
-      self::Class::_#lateStaticField1 = #t2;
-    else
+    if(self::Class::_#lateStaticField1#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField1' has already been initialized.");
+    else {
+      self::Class::_#lateStaticField1#isSet = true;
+      self::Class::_#lateStaticField1 = #t2;
+    }
   static get lateStaticField2() → core::int
-    return let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.") : #t3{core::int};
+    return self::Class::_#lateStaticField2#isSet ?{core::int} let final core::int? #t3 = self::Class::_#lateStaticField2 in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has not been initialized.");
   static set lateStaticField2(core::int #t4) → void
-    if(self::Class::_#lateStaticField2.==(null))
-      self::Class::_#lateStaticField2 = #t4;
-    else
+    if(self::Class::_#lateStaticField2#isSet)
       throw new _in::LateInitializationErrorImpl::•("Field 'lateStaticField2' has already been initialized.");
+    else {
+      self::Class::_#lateStaticField2#isSet = true;
+      self::Class::_#lateStaticField2 = #t4;
+    }
   static method staticMethod() → dynamic {
     self::throws(() → core::int => self::Class::lateStaticField2, "Read value from uninitialized Class.lateStaticField2");
     self::Class::lateStaticField2 = 42;
@@ -31,12 +38,14 @@
     self::throws(() → core::int => self::Class::lateStaticField2 = 43, "Write value to initialized Class.lateStaticField2");
   }
   get lateInstanceField() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.") : #t5{core::int};
+    return this.{self::Class::_#Class#lateInstanceField#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#lateInstanceField} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has not been initialized.");
   set lateInstanceField(core::int #t6) → void
-    if(this.{self::Class::_#Class#lateInstanceField}.==(null))
-      this.{self::Class::_#Class#lateInstanceField} = #t6;
-    else
+    if(this.{self::Class::_#Class#lateInstanceField#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'lateInstanceField' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#lateInstanceField#isSet} = true;
+      this.{self::Class::_#Class#lateInstanceField} = #t6;
+    }
   method instanceMethod() → dynamic {
     self::throws(() → core::int => this.{self::Class::lateInstanceField}, "Read value from uninitialized Class.lateInstanceField");
     this.{self::Class::lateInstanceField} = 16;
@@ -46,37 +55,48 @@
 }
 extension Extension on self::Class {
   static field lateExtensionField1 = self::_#Extension|lateExtensionField1;
+  static field lateExtensionField1 = self::_#Extension|lateExtensionField1#isSet;
   static get lateExtensionField1 = get self::Extension|lateExtensionField1;
   static set lateExtensionField1 = set self::Extension|lateExtensionField1;
   static field lateExtensionField2 = self::_#Extension|lateExtensionField2;
+  static field lateExtensionField2 = self::_#Extension|lateExtensionField2#isSet;
   static get lateExtensionField2 = get self::Extension|lateExtensionField2;
   static set lateExtensionField2 = set self::Extension|lateExtensionField2;
   static method staticMethod = self::Extension|staticMethod;
 }
 static field core::int? _#lateTopLevelField = null;
+static field core::bool _#lateTopLevelField#isSet = false;
 static field core::int? _#Extension|lateExtensionField1 = null;
+static field core::bool _#Extension|lateExtensionField1#isSet = false;
 static field core::int? _#Extension|lateExtensionField2 = null;
+static field core::bool _#Extension|lateExtensionField2#isSet = false;
 static get lateTopLevelField() → core::int
-  return let final core::int? #t7 = self::_#lateTopLevelField in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.") : #t7{core::int};
+  return self::_#lateTopLevelField#isSet ?{core::int} let final core::int? #t7 = self::_#lateTopLevelField in #t7{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has not been initialized.");
 static set lateTopLevelField(core::int #t8) → void
-  if(self::_#lateTopLevelField.==(null))
-    self::_#lateTopLevelField = #t8;
-  else
+  if(self::_#lateTopLevelField#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateTopLevelField' has already been initialized.");
+  else {
+    self::_#lateTopLevelField#isSet = true;
+    self::_#lateTopLevelField = #t8;
+  }
 static get Extension|lateExtensionField1() → core::int
-  return let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.") : #t9{core::int};
+  return self::_#Extension|lateExtensionField1#isSet ?{core::int} let final core::int? #t9 = self::_#Extension|lateExtensionField1 in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has not been initialized.");
 static set Extension|lateExtensionField1(core::int #t10) → void
-  if(self::_#Extension|lateExtensionField1.==(null))
-    self::_#Extension|lateExtensionField1 = #t10;
-  else
+  if(self::_#Extension|lateExtensionField1#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField1' has already been initialized.");
+  else {
+    self::_#Extension|lateExtensionField1#isSet = true;
+    self::_#Extension|lateExtensionField1 = #t10;
+  }
 static get Extension|lateExtensionField2() → core::int
-  return let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.") : #t11{core::int};
+  return self::_#Extension|lateExtensionField2#isSet ?{core::int} let final core::int? #t11 = self::_#Extension|lateExtensionField2 in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has not been initialized.");
 static set Extension|lateExtensionField2(core::int #t12) → void
-  if(self::_#Extension|lateExtensionField2.==(null))
-    self::_#Extension|lateExtensionField2 = #t12;
-  else
+  if(self::_#Extension|lateExtensionField2#isSet)
     throw new _in::LateInitializationErrorImpl::•("Field 'lateExtensionField2' has already been initialized.");
+  else {
+    self::_#Extension|lateExtensionField2#isSet = true;
+    self::_#Extension|lateExtensionField2 = #t12;
+  }
 static method Extension|staticMethod() → dynamic {
   self::throws(() → core::int => self::Extension|lateExtensionField2, "Read value from uninitialized Class.lateExtensionField2");
   self::Extension|lateExtensionField2 = 42;
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
index 2f84c91..bfa3459 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.expect
@@ -8,8 +8,14 @@
     return lateLocalInit = value;
   }
   final core::int? lateLocal;
-  function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+  core::bool #lateLocal#isSet = false;
+  function #lateLocal#get() → core::int {
+    if(!#lateLocal#isSet) {
+      lateLocal = initLateLocal.call(123);
+      #lateLocal#isSet = true;
+    }
+    return lateLocal{core::int};
+  }
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
index 2f84c91..bfa3459 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_with_initializer.dart.weak.transformed.expect
@@ -8,8 +8,14 @@
     return lateLocalInit = value;
   }
   final core::int? lateLocal;
-  function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = initLateLocal.call(123) : #t1{core::int};
+  core::bool #lateLocal#isSet = false;
+  function #lateLocal#get() → core::int {
+    if(!#lateLocal#isSet) {
+      lateLocal = initLateLocal.call(123);
+      #lateLocal#isSet = true;
+    }
+    return lateLocal{core::int};
+  }
   self::expect(null, lateLocalInit);
   self::expect(123, #lateLocal#get.call());
   self::expect(123, lateLocalInit);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
index 3476c20..7a343a9 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.expect
@@ -6,13 +6,16 @@
 static method main() → dynamic {
   core::bool b = false;
   final core::int? lateLocal;
+  core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    if(lateLocal.==(null))
-      return lateLocal = #t2;
-    else
+    return #lateLocal#isSet ?{core::int} lateLocal{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.");
+  function #lateLocal#set(core::int #t1) → dynamic
+    if(#lateLocal#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has already been initialized.");
+    else {
+      #lateLocal#isSet = true;
+      return lateLocal = #t1;
+    }
   if(b) {
     #lateLocal#set.call(123);
   }
@@ -27,12 +30,12 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
-    function #lateGenericLocal#set(T% #t3) → dynamic
+    function #lateGenericLocal#set(T% #t2) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
       else {
         #lateGenericLocal#isSet = true;
-        return lateGenericLocal = #t3;
+        return lateGenericLocal = #t2;
       }
     if(b) {
       #lateGenericLocal#set.call(value);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
index 3476c20..7a343a9 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_local_without_initializer.dart.weak.transformed.expect
@@ -6,13 +6,16 @@
 static method main() → dynamic {
   core::bool b = false;
   final core::int? lateLocal;
+  core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    if(lateLocal.==(null))
-      return lateLocal = #t2;
-    else
+    return #lateLocal#isSet ?{core::int} lateLocal{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.");
+  function #lateLocal#set(core::int #t1) → dynamic
+    if(#lateLocal#isSet)
       throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has already been initialized.");
+    else {
+      #lateLocal#isSet = true;
+      return lateLocal = #t1;
+    }
   if(b) {
     #lateLocal#set.call(123);
   }
@@ -27,12 +30,12 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
-    function #lateGenericLocal#set(T% #t3) → dynamic
+    function #lateGenericLocal#set(T% #t2) → dynamic
       if(#lateGenericLocal#isSet)
         throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has already been initialized.");
       else {
         #lateGenericLocal#isSet = true;
-        return lateGenericLocal = #t3;
+        return lateGenericLocal = #t2;
       }
     if(b) {
       #lateGenericLocal#set.call(value);
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
index 559ee5e..494d850 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart
@@ -6,7 +6,12 @@
   late final int? lateLocal;
 
   throws(() => lateLocal, 'Read value from uninitialized lateLocal');
-  expect(123, lateLocal = 123);
+  // This `if` test prevents flow analysis from realizing that we
+  // unconditionally write to `lateLocal`, so that we can write to it again
+  // later without a static error.
+  if (1 == 1) {
+    expect(123, lateLocal = 123);
+  }
   expect(123, lateLocal);
   throws(() => lateLocal = 124, 'Write value to initialized lateLocal');
 
@@ -15,7 +20,12 @@
 
     throws(() => lateGenericLocal,
         'Read value from uninitialized lateGenericLocal');
-    expect(value, lateGenericLocal = value);
+    // This `if` test prevents flow analysis from realizing that we
+    // unconditionally write to `lateLocal`, so that we can write to it again
+    // later without a static error.
+    if (1 == 1) {
+      expect(value, lateGenericLocal = value);
+    }
     expect(value, lateGenericLocal);
     throws(() => lateGenericLocal = value,
         'Write value to initialized lateGenericLocal');
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
index 3d8ddf1..b04eb47 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.expect
@@ -16,7 +16,9 @@
       return lateLocal = #t1;
     }
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
-  self::expect(123, #lateLocal#set.call(123));
+  if(1.{core::num::==}(1)) {
+    self::expect(123, #lateLocal#set.call(123));
+  }
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
   function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
@@ -32,7 +34,9 @@
         return lateGenericLocal = #t2;
       }
     self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
-    self::expect(value, #lateGenericLocal#set.call(value));
+    if(1.{core::num::==}(1)) {
+      self::expect(value, #lateGenericLocal#set.call(value));
+    }
     self::expect(value, #lateGenericLocal#get.call());
     self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
index 3d8ddf1..6fe95bd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.strong.transformed.expect
@@ -16,7 +16,9 @@
       return lateLocal = #t1;
     }
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
-  self::expect(123, #lateLocal#set.call(123));
+  if(1.{core::num::==}(1)) {
+    self::expect(123, #lateLocal#set.call(123));
+  }
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
   function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
@@ -32,7 +34,9 @@
         return lateGenericLocal = #t2;
       }
     self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
-    self::expect(value, #lateGenericLocal#set.call(value));
+    if(1.{core::num::==}(1)) {
+      self::expect(value, #lateGenericLocal#set.call(value));
+    }
     self::expect(value, #lateGenericLocal#get.call());
     self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
   }
@@ -56,3 +60,9 @@
   }
   throw "${message}: ${value}";
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///late_final_nullable_local_without_initializer.dart:12:9 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///late_final_nullable_local_without_initializer.dart:26:11 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 81, effectively constant: 2
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
index 3d8ddf1..b04eb47 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.expect
@@ -16,7 +16,9 @@
       return lateLocal = #t1;
     }
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
-  self::expect(123, #lateLocal#set.call(123));
+  if(1.{core::num::==}(1)) {
+    self::expect(123, #lateLocal#set.call(123));
+  }
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
   function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
@@ -32,7 +34,9 @@
         return lateGenericLocal = #t2;
       }
     self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
-    self::expect(value, #lateGenericLocal#set.call(value));
+    if(1.{core::num::==}(1)) {
+      self::expect(value, #lateGenericLocal#set.call(value));
+    }
     self::expect(value, #lateGenericLocal#get.call());
     self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
index 3d8ddf1..6fe95bd 100644
--- a/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_final_nullable_local_without_initializer.dart.weak.transformed.expect
@@ -16,7 +16,9 @@
       return lateLocal = #t1;
     }
   self::throws(() → core::int? => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
-  self::expect(123, #lateLocal#set.call(123));
+  if(1.{core::num::==}(1)) {
+    self::expect(123, #lateLocal#set.call(123));
+  }
   self::expect(123, #lateLocal#get.call());
   self::throws(() → core::int => #lateLocal#set.call(124), "Write value to initialized lateLocal");
   function local<T extends core::Object? = dynamic>(T? value) → core::Null? {
@@ -32,7 +34,9 @@
         return lateGenericLocal = #t2;
       }
     self::throws(() → T? => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
-    self::expect(value, #lateGenericLocal#set.call(value));
+    if(1.{core::num::==}(1)) {
+      self::expect(value, #lateGenericLocal#set.call(value));
+    }
     self::expect(value, #lateGenericLocal#get.call());
     self::throws(() → T? => #lateGenericLocal#set.call(value), "Write value to initialized lateGenericLocal");
   }
@@ -56,3 +60,9 @@
   }
   throw "${message}: ${value}";
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///late_final_nullable_local_without_initializer.dart:12:9 -> BoolConstant(true)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///late_final_nullable_local_without_initializer.dart:26:11 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 81, effectively constant: 2
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
index 6a5587c..ad35343 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
@@ -149,10 +149,17 @@
   self::_#field3#isSet = true;
   self::_#field3 = #t14;
 }
-static get field4() → FutureOr<core::int>
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t15{FutureOr<core::int>};
-static set field4(FutureOr<core::int>#t16) → void
+static get field4() → FutureOr<core::int> {
+  if(!self::_#field4#isSet) {
+    self::_#field4 = self::method4();
+    self::_#field4#isSet = true;
+  }
+  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15{FutureOr<core::int>};
+}
+static set field4(FutureOr<core::int>#t16) → void {
+  self::_#field4#isSet = true;
   self::_#field4 = #t16;
+}
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
     self::_#field5 = self::method5();
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
index 6a5587c..ad35343 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
@@ -149,10 +149,17 @@
   self::_#field3#isSet = true;
   self::_#field3 = #t14;
 }
-static get field4() → FutureOr<core::int>
-  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15.==(null) ?{FutureOr<core::int>} self::_#field4 = self::method4() : #t15{FutureOr<core::int>};
-static set field4(FutureOr<core::int>#t16) → void
+static get field4() → FutureOr<core::int> {
+  if(!self::_#field4#isSet) {
+    self::_#field4 = self::method4();
+    self::_#field4#isSet = true;
+  }
+  return let final FutureOr<core::int>? #t15 = self::_#field4 in #t15{FutureOr<core::int>};
+}
+static set field4(FutureOr<core::int>#t16) → void {
+  self::_#field4#isSet = true;
   self::_#field4 = #t16;
+}
 static get field5() → FutureOr<core::int?> {
   if(!self::_#field5#isSet) {
     self::_#field5 = self::method5();
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
index 9fbaf26..81e2022 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.expect
@@ -4,10 +4,18 @@
 
 static method main() → dynamic {
   core::int? lateLocal;
-  function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = 123 : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return lateLocal = #t2;
+  core::bool #lateLocal#isSet = false;
+  function #lateLocal#get() → core::int {
+    if(!#lateLocal#isSet) {
+      lateLocal = 123;
+      #lateLocal#isSet = true;
+    }
+    return lateLocal{core::int};
+  }
+  function #lateLocal#set(core::int #t1) → dynamic {
+    #lateLocal#isSet = true;
+    return lateLocal = #t1;
+  }
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
@@ -21,9 +29,9 @@
       }
       return lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% #t2) → dynamic {
       #lateGenericLocal#isSet = true;
-      return lateGenericLocal = #t3;
+      return lateGenericLocal = #t2;
     }
     self::expect(value1, #lateGenericLocal#get.call());
     self::expect(value2, #lateGenericLocal#set.call(value2));
diff --git a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
index 9fbaf26..81e2022 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_with_initializer.dart.weak.transformed.expect
@@ -4,10 +4,18 @@
 
 static method main() → dynamic {
   core::int? lateLocal;
-  function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} lateLocal = 123 : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return lateLocal = #t2;
+  core::bool #lateLocal#isSet = false;
+  function #lateLocal#get() → core::int {
+    if(!#lateLocal#isSet) {
+      lateLocal = 123;
+      #lateLocal#isSet = true;
+    }
+    return lateLocal{core::int};
+  }
+  function #lateLocal#set(core::int #t1) → dynamic {
+    #lateLocal#isSet = true;
+    return lateLocal = #t1;
+  }
   self::expect(123, #lateLocal#get.call());
   self::expect(124, #lateLocal#set.call(124));
   self::expect(124, #lateLocal#get.call());
@@ -21,9 +29,9 @@
       }
       return lateGenericLocal{T%};
     }
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% #t2) → dynamic {
       #lateGenericLocal#isSet = true;
-      return lateGenericLocal = #t3;
+      return lateGenericLocal = #t2;
     }
     self::expect(value1, #lateGenericLocal#get.call());
     self::expect(value2, #lateGenericLocal#set.call(value2));
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
index eaf2671..9c46d6e 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.expect
@@ -5,10 +5,13 @@
 
 static method main() → dynamic {
   core::int? lateLocal;
+  core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return lateLocal = #t2;
+    return #lateLocal#isSet ?{core::int} lateLocal{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.");
+  function #lateLocal#set(core::int #t1) → dynamic {
+    #lateLocal#isSet = true;
+    return lateLocal = #t1;
+  }
   self::throws(() → core::int => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
@@ -17,9 +20,9 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% #t2) → dynamic {
       #lateGenericLocal#isSet = true;
-      return lateGenericLocal = #t3;
+      return lateGenericLocal = #t2;
     }
     self::throws(() → T% => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set.call(value));
diff --git a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
index eaf2671..9c46d6e 100644
--- a/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_local_without_initializer.dart.weak.transformed.expect
@@ -5,10 +5,13 @@
 
 static method main() → dynamic {
   core::int? lateLocal;
+  core::bool #lateLocal#isSet = false;
   function #lateLocal#get() → core::int
-    return let final core::int? #t1 = lateLocal in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.") : #t1{core::int};
-  function #lateLocal#set(core::int #t2) → dynamic
-    return lateLocal = #t2;
+    return #lateLocal#isSet ?{core::int} lateLocal{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'lateLocal' has not been initialized.");
+  function #lateLocal#set(core::int #t1) → dynamic {
+    #lateLocal#isSet = true;
+    return lateLocal = #t1;
+  }
   self::throws(() → core::int => #lateLocal#get.call(), "Read value from uninitialized lateLocal");
   self::expect(123, #lateLocal#set.call(123));
   self::expect(123, #lateLocal#get.call());
@@ -17,9 +20,9 @@
     core::bool #lateGenericLocal#isSet = false;
     function #lateGenericLocal#get() → T%
       return #lateGenericLocal#isSet ?{T%} lateGenericLocal{T%} : throw new _in::LateInitializationErrorImpl::•("Local 'lateGenericLocal' has not been initialized.");
-    function #lateGenericLocal#set(T% #t3) → dynamic {
+    function #lateGenericLocal#set(T% #t2) → dynamic {
       #lateGenericLocal#isSet = true;
-      return lateGenericLocal = #t3;
+      return lateGenericLocal = #t2;
     }
     self::throws(() → T% => #lateGenericLocal#get.call(), "Read value from uninitialized lateGenericLocal");
     self::expect(value, #lateGenericLocal#set.call(value));
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.outline.expect b/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
index a6cb6f6..8288606 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.outline.expect
@@ -53,3 +53,8 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///later.dart:46:18 -> IntConstant(42)
+Extra constant evaluation: evaluated: 17, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
index 4646abe..cdcf986 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}'; // Error.
 //                              ^^^^^
 //
-// pkg/front_end/testcases/late_lowering/later.dart:48:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B(); // Error: B has late final fields.
-//         ^
-// pkg/front_end/testcases/late_lowering/later.dart:46:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/late_lowering/later.dart:46:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/late_lowering/later.dart:48:9: Context: This constructor is const.
+//   const B(); // Error: B has late final fields.
+//         ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
index 1129833..7afe2ac 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.strong.transformed.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}'; // Error.
 //                              ^^^^^
 //
-// pkg/front_end/testcases/late_lowering/later.dart:48:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B(); // Error: B has late final fields.
-//         ^
-// pkg/front_end/testcases/late_lowering/later.dart:46:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/late_lowering/later.dart:46:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/late_lowering/later.dart:48:9: Context: This constructor is const.
+//   const B(); // Error: B has late final fields.
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -268,3 +268,7 @@
 constants  {
   #C1 = tearoff self::fisk
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///later.dart:46:18 -> IntConstant(42)
+Extra constant evaluation: evaluated: 216, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
index 4646abe..1144c13 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}'; // Error.
 //                              ^^^^^
 //
-// pkg/front_end/testcases/late_lowering/later.dart:48:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B(); // Error: B has late final fields.
-//         ^
-// pkg/front_end/testcases/late_lowering/later.dart:46:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/late_lowering/later.dart:46:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/late_lowering/later.dart:48:9: Context: This constructor is const.
+//   const B(); // Error: B has late final fields.
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -70,35 +70,55 @@
 class A extends core::Object {
   field core::int a = 42;
   field core::int? _#A#b = null;
+  field core::bool _#A#b#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-  get b() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#b} in #t1.==(null) ?{core::int} this.{self::A::_#A#b} = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1) : #t1{core::int};
-  set b(core::int #t2) → void
+  get b() → core::int {
+    if(!this.{self::A::_#A#b#isSet}) {
+      this.{self::A::_#A#b} = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+      this.{self::A::_#A#b#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::A::_#A#b} in #t1{core::int};
+  }
+  set b(core::int #t2) → void {
+    this.{self::A::_#A#b#isSet} = true;
     this.{self::A::_#A#b} = #t2;
+  }
   method foo(core::int x) → dynamic {}
 }
 class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
+  field core::bool _#B#x#isSet = false;
   const constructor •() → self::B
     : super core::Object::•()
     ;
-  get x() → core::int
-    return let final core::int? #t3 = this.{self::B::_#B#x} in #t3.==(null) ?{core::int} let final core::int #t4 = 42 in this.{self::B::_#B#x}.==(null) ?{core::int} this.{self::B::_#B#x} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.") : #t3{core::int};
+  get x() → core::int {
+    if(!this.{self::B::_#B#x#isSet}) {
+      final core::int #t3 = 42;
+      if(this.{self::B::_#B#x#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.");
+      this.{self::B::_#B#x} = #t3;
+      this.{self::B::_#B#x#isSet} = true;
+    }
+    return let final core::int? #t4 = this.{self::B::_#B#x} in #t4{core::int};
+  }
 }
 class C extends core::Object {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t5 = this.{self::C::_#C#x} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t5{core::int};
+    return this.{self::C::_#C#x#isSet} ?{core::int} let final core::int? #t5 = this.{self::C::_#C#x} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(core::int #t6) → void
-    if(this.{self::C::_#C#x}.==(null))
-      this.{self::C::_#C#x} = #t6;
-    else
+    if(this.{self::C::_#C#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::C::_#C#x#isSet} = true;
+      this.{self::C::_#C#x} = #t6;
+    }
   method initVars() → dynamic {
     this.{self::C::x} = 42;
   }
@@ -138,24 +158,48 @@
 }
 static method fisk() → dynamic async {
   core::String? s1;
-  function #s1#get() → core::String
-    return let final core::String? #t8 = s1 in #t8.==(null) ?{core::String} s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+  core::bool #s1#isSet = false;
+  function #s1#get() → core::String {
+    if(!#s1#isSet) {
+      s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String : #t8{core::String};
-  function #s1#set(core::String #t9) → dynamic
-    return s1 = #t9;
+                   ^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} core::String;
+      #s1#isSet = true;
+    }
+    return s1{core::String};
+  }
+  function #s1#set(core::String #t8) → dynamic {
+    #s1#isSet = true;
+    return s1 = #t8;
+  }
   core::String? s2;
-  function #s2#get() → core::String
-    return let final core::String? #t10 = s2 in #t10.==(null) ?{core::String} s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+  core::bool #s2#isSet = false;
+  function #s2#get() → core::String {
+    if(!#s2#isSet) {
+      s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t10{core::String};
-  function #s2#set(core::String #t11) → dynamic
-    return s2 = #t11;
+                             ^^^^^"}${#C1}";
+      #s2#isSet = true;
+    }
+    return s2{core::String};
+  }
+  function #s2#set(core::String #t9) → dynamic {
+    #s2#isSet = true;
+    return s2 = #t9;
+  }
   core::Function? f;
-  function #f#get() → core::Function
-    return let final core::Function? #t12 = f in #t12.==(null) ?{core::Function} f = () → asy::Future<dynamic> async => await self::hest() : #t12{core::Function};
-  function #f#set(core::Function #t13) → dynamic
-    return f = #t13;
+  core::bool #f#isSet = false;
+  function #f#get() → core::Function {
+    if(!#f#isSet) {
+      f = () → asy::Future<dynamic> async => await self::hest();
+      #f#isSet = true;
+    }
+    return f{core::Function};
+  }
+  function #f#set(core::Function #t10) → dynamic {
+    #f#isSet = true;
+    return f = #t10;
+  }
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
index 1129833..4dac8b1 100644
--- a/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/later.dart.weak.transformed.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}'; // Error.
 //                              ^^^^^
 //
-// pkg/front_end/testcases/late_lowering/later.dart:48:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B(); // Error: B has late final fields.
-//         ^
-// pkg/front_end/testcases/late_lowering/later.dart:46:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/late_lowering/later.dart:46:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/late_lowering/later.dart:48:9: Context: This constructor is const.
+//   const B(); // Error: B has late final fields.
+//         ^
 //
 import self as self;
 import "dart:core" as core;
@@ -70,35 +70,55 @@
 class A extends core::Object {
   field core::int a = 42;
   field core::int? _#A#b = null;
+  field core::bool _#A#b#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
-  get b() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#b} in #t1.==(null) ?{core::int} this.{self::A::_#A#b} = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1) : #t1{core::int};
-  set b(core::int #t2) → void
+  get b() → core::int {
+    if(!this.{self::A::_#A#b#isSet}) {
+      this.{self::A::_#A#b} = this.{self::A::a}.{core::num::*}(2).{core::int::>>}(1);
+      this.{self::A::_#A#b#isSet} = true;
+    }
+    return let final core::int? #t1 = this.{self::A::_#A#b} in #t1{core::int};
+  }
+  set b(core::int #t2) → void {
+    this.{self::A::_#A#b#isSet} = true;
     this.{self::A::_#A#b} = #t2;
+  }
   method foo(core::int x) → dynamic {}
 }
 class B extends core::Object /*hasConstConstructor*/  {
   field core::int? _#B#x = null;
+  field core::bool _#B#x#isSet = false;
   const constructor •() → self::B
     : super core::Object::•()
     ;
-  get x() → core::int
-    return let final core::int? #t3 = this.{self::B::_#B#x} in #t3.==(null) ?{core::int} let final core::int #t4 = 42 in this.{self::B::_#B#x}.==(null) ?{core::int} this.{self::B::_#B#x} = #t4 : throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.") : #t3{core::int};
+  get x() → core::int {
+    if(!this.{self::B::_#B#x#isSet}) {
+      final core::int #t3 = 42;
+      if(this.{self::B::_#B#x#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.");
+      this.{self::B::_#B#x} = #t3;
+      this.{self::B::_#B#x#isSet} = true;
+    }
+    return let final core::int? #t4 = this.{self::B::_#B#x} in #t4{core::int};
+  }
 }
 class C extends core::Object {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   synthetic constructor •() → self::C
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t5 = this.{self::C::_#C#x} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t5{core::int};
+    return this.{self::C::_#C#x#isSet} ?{core::int} let final core::int? #t5 = this.{self::C::_#C#x} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(core::int #t6) → void
-    if(this.{self::C::_#C#x}.==(null))
-      this.{self::C::_#C#x} = #t6;
-    else
+    if(this.{self::C::_#C#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::C::_#C#x#isSet} = true;
+      this.{self::C::_#C#x} = #t6;
+    }
   method initVars() → dynamic {
     this.{self::C::x} = 42;
   }
@@ -204,52 +224,76 @@
       #L3:
       {
         core::String? s1;
-        function #s1#get() → core::String
-          return let final core::String? #t11 = s1 in #t11.==(null) ?{core::String} s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
+        core::bool #s1#isSet = false;
+        function #s1#get() → core::String {
+          if(!#s1#isSet) {
+            s1 = invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:40:20: Error: `await` expressions are not supported in late local initializers.
   late String s1 = await hest(); // Error.
-                   ^^^^^" : #t11{core::String};
-        function #s1#set(core::String #t12) → dynamic
-          return s1 = #t12;
+                   ^^^^^";
+            #s1#isSet = true;
+          }
+          return s1{core::String};
+        }
+        function #s1#set(core::String #t11) → dynamic {
+          #s1#isSet = true;
+          return s1 = #t11;
+        }
         core::String? s2;
-        function #s2#get() → core::String
-          return let final core::String? #t13 = s2 in #t13.==(null) ?{core::String} s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
+        core::bool #s2#isSet = false;
+        function #s2#get() → core::String {
+          if(!#s2#isSet) {
+            s2 = "${#C1}${invalid-expression "pkg/front_end/testcases/late_lowering/later.dart:41:30: Error: `await` expressions are not supported in late local initializers.
   late String s2 = '\${fisk}\${await hest()}\${fisk}'; // Error.
-                             ^^^^^"}${#C1}" : #t13{core::String};
-        function #s2#set(core::String #t14) → dynamic
-          return s2 = #t14;
+                             ^^^^^"}${#C1}";
+            #s2#isSet = true;
+          }
+          return s2{core::String};
+        }
+        function #s2#set(core::String #t12) → dynamic {
+          #s2#isSet = true;
+          return s2 = #t12;
+        }
         core::Function? f;
-        function #f#get() → core::Function
-          return let final core::Function? #t15 = f in #t15.==(null) ?{core::Function} f = () → asy::Future<dynamic> /* originally async */ {
-            final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
-            FutureOr<dynamic>? :return_value;
-            dynamic :async_stack_trace;
-            (dynamic) → dynamic :async_op_then;
-            (core::Object, core::StackTrace) → dynamic :async_op_error;
-            core::int :await_jump_var = 0;
-            dynamic :await_ctx_var;
-            dynamic :saved_try_context_var0;
-            function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
-              try {
-                #L4:
-                {
-                  [yield] let dynamic #t16 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
-                  :return_value = :result;
-                  break #L4;
+        core::bool #f#isSet = false;
+        function #f#get() → core::Function {
+          if(!#f#isSet) {
+            f = () → asy::Future<dynamic> /* originally async */ {
+              final asy::_AsyncAwaitCompleter<dynamic> :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+              FutureOr<dynamic>? :return_value;
+              dynamic :async_stack_trace;
+              (dynamic) → dynamic :async_op_then;
+              (core::Object, core::StackTrace) → dynamic :async_op_error;
+              core::int :await_jump_var = 0;
+              dynamic :await_ctx_var;
+              dynamic :saved_try_context_var0;
+              function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+                try {
+                  #L4:
+                  {
+                    [yield] let dynamic #t13 = asy::_awaitHelper(self::hest(), :async_op_then, :async_op_error, :async_op) in null;
+                    :return_value = :result;
+                    break #L4;
+                  }
+                  asy::_completeOnAsyncReturn(:async_completer, :return_value);
+                  return;
                 }
-                asy::_completeOnAsyncReturn(:async_completer, :return_value);
-                return;
-              }
-              on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
-                :async_completer.{asy::Completer::completeError}(exception, stack_trace);
-              }
-            :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
-            :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
-            :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
-            :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
-            return :async_completer.{asy::Completer::future};
-          } : #t15{core::Function};
-        function #f#set(core::Function #t17) → dynamic
-          return f = #t17;
+                on dynamic catch(dynamic exception, core::StackTrace stack_trace) {
+                  :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+                }
+              :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+              :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+              :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+              :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+              return :async_completer.{asy::Completer::future};
+            };
+            #f#isSet = true;
+          }
+          return f{core::Function};
+        }
+        function #f#set(core::Function #t14) → dynamic {
+          #f#isSet = true;
+          return f = #t14;
+        }
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
       return;
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart
new file mode 100644
index 0000000..4881832
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+import 'non_nullable_from_opt_out_lib.dart';
+
+main() {
+  topLevelField = null;
+  finalTopLevelField = null;
+
+  var c = new Class<int>();
+  c.instanceField = null;
+  c.finalInstanceField = null;
+  c.instanceTypeVariable = null;
+  c.finalInstanceTypeVariable = null;
+
+  Class.staticField = null;
+  Class.staticFinalField = null;
+
+  expect(null, topLevelField);
+  expect(null, finalTopLevelField);
+  expect(null, c.instanceField);
+  expect(null, c.finalInstanceField);
+  expect(null, c.instanceTypeVariable);
+  expect(null, c.finalInstanceTypeVariable);
+  expect(null, Class.staticField);
+  expect(null, Class.staticFinalField);
+
+  throws(() => finalTopLevelField = null);
+  throws(() => c.finalInstanceField = null);
+  throws(() => c.finalInstanceTypeVariable = null);
+  throws(() => Class.staticFinalField = null);
+
+  method(true, null, null);
+}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.outline.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.outline.expect
new file mode 100644
index 0000000..8fc95bd
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.outline.expect
@@ -0,0 +1,56 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as self;
+
+import "org-dartlang-testcase:///non_nullable_from_opt_out_lib.dart";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+class Class<T extends core::Object = core::Object> extends core::Object {
+  field core::int? _#Class#instanceField;
+  field dynamic _#Class#finalInstanceField;
+  field core::bool _#Class#finalInstanceField#isSet;
+  generic-covariant-impl field self2::Class::T? _#Class#instanceTypeVariable;
+  field self2::Class::T? _#Class#finalInstanceTypeVariable;
+  static field core::int? _#staticField;
+  static field dynamic _#staticFinalField;
+  static field core::bool _#staticFinalField#isSet;
+  synthetic constructor •() → self2::Class<self2::Class::T>
+    ;
+  get instanceField() → core::int;
+  set instanceField(core::int #t1) → void;
+  get finalInstanceField() → dynamic;
+  set finalInstanceField(dynamic #t2) → void;
+  get instanceTypeVariable() → self2::Class::T;
+  set instanceTypeVariable(generic-covariant-impl self2::Class::T #t3) → void;
+  get finalInstanceTypeVariable() → self2::Class::T;
+  set finalInstanceTypeVariable(self2::Class::T #t4) → void;
+  static get staticField() → core::int;
+  static set staticField(core::int #t5) → void;
+  static get staticFinalField() → dynamic;
+  static set staticFinalField(dynamic #t6) → void;
+}
+static field core::int? _#topLevelField;
+static field dynamic _#finalTopLevelField;
+static field core::bool _#finalTopLevelField#isSet;
+static get topLevelField() → core::int;
+static set topLevelField(core::int #t7) → void;
+static get finalTopLevelField() → dynamic;
+static set finalTopLevelField(dynamic #t8) → void;
+static method method<T extends core::Object = core::Object>(core::bool b, core::int i, self2::method::T t) → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → void f) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect
new file mode 100644
index 0000000..6ffbd4b
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.expect
@@ -0,0 +1,166 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as self;
+import "non_nullable_from_opt_out_lib.dart" as non;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///non_nullable_from_opt_out_lib.dart";
+
+static method main() → dynamic {
+  non::topLevelField = null;
+  non::finalTopLevelField = null;
+  non::Class<core::int*>* c = new non::Class::•<core::int*>();
+  c.{non::Class::instanceField} = null;
+  c.{non::Class::finalInstanceField} = null;
+  c.{non::Class::instanceTypeVariable} = null;
+  c.{non::Class::finalInstanceTypeVariable} = null;
+  non::Class::staticField = null;
+  non::Class::staticFinalField = null;
+  non::expect(null, non::topLevelField);
+  non::expect(null, non::finalTopLevelField);
+  non::expect(null, c.{non::Class::instanceField});
+  non::expect(null, c.{non::Class::finalInstanceField});
+  non::expect(null, c.{non::Class::instanceTypeVariable});
+  non::expect(null, c.{non::Class::finalInstanceTypeVariable});
+  non::expect(null, non::Class::staticField);
+  non::expect(null, non::Class::staticFinalField);
+  non::throws(() → core::Null? => non::finalTopLevelField = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceField} = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceTypeVariable} = null);
+  non::throws(() → core::Null? => non::Class::staticFinalField = null);
+  non::method<core::Null?>(true, null, null);
+}
+
+library /*isNonNullableByDefault*/;
+import self as non;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object = core::Object> extends core::Object {
+  field core::int? _#Class#instanceField = null;
+  field dynamic _#Class#finalInstanceField = null;
+  field core::bool _#Class#finalInstanceField#isSet = false;
+  generic-covariant-impl field non::Class::T? _#Class#instanceTypeVariable = null;
+  field non::Class::T? _#Class#finalInstanceTypeVariable = null;
+  static field core::int? _#staticField = null;
+  static field dynamic _#staticFinalField = null;
+  static field core::bool _#staticFinalField#isSet = false;
+  synthetic constructor •() → non::Class<non::Class::T>
+    : super core::Object::•()
+    ;
+  get instanceField() → core::int
+    return let final core::int? #t1 = this.{non::Class::_#Class#instanceField} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t1{core::int};
+  set instanceField(core::int #t2) → void
+    this.{non::Class::_#Class#instanceField} = #t2;
+  get finalInstanceField() → dynamic
+    return this.{non::Class::_#Class#finalInstanceField#isSet} ?{dynamic} this.{non::Class::_#Class#finalInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
+  set finalInstanceField(dynamic #t3) → void
+    if(this.{non::Class::_#Class#finalInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceField#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceField} = #t3;
+    }
+  get instanceTypeVariable() → non::Class::T
+    return let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable} in #t4.==(null) ?{non::Class::T} throw new _in::LateInitializationErrorImpl::•("Field 'instanceTypeVariable' has not been initialized.") : #t4{non::Class::T};
+  set instanceTypeVariable(generic-covariant-impl non::Class::T #t5) → void
+    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+  get finalInstanceTypeVariable() → non::Class::T
+    return let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable} in #t6.==(null) ?{non::Class::T} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has not been initialized.") : #t6{non::Class::T};
+  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    if(this.{non::Class::_#Class#finalInstanceTypeVariable}.==(null))
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has already been initialized.");
+  static get staticField() → core::int
+    return let final core::int? #t8 = non::Class::_#staticField in #t8.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t8{core::int};
+  static set staticField(core::int #t9) → void
+    non::Class::_#staticField = #t9;
+  static get staticFinalField() → dynamic
+    return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has not been initialized.");
+  static set staticFinalField(dynamic #t10) → void
+    if(non::Class::_#staticFinalField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has already been initialized.");
+    else {
+      non::Class::_#staticFinalField#isSet = true;
+      non::Class::_#staticFinalField = #t10;
+    }
+}
+static field core::int? _#topLevelField = null;
+static field dynamic _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
+static get topLevelField() → core::int
+  return let final core::int? #t11 = non::_#topLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.") : #t11{core::int};
+static set topLevelField(core::int #t12) → void
+  non::_#topLevelField = #t12;
+static get finalTopLevelField() → dynamic
+  return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
+static set finalTopLevelField(dynamic #t13) → void
+  if(non::_#finalTopLevelField#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    non::_#finalTopLevelField#isSet = true;
+    non::_#finalTopLevelField = #t13;
+  }
+static method method<T extends core::Object = core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
+  core::int? local;
+  function #local#get() → core::int
+    return let final core::int? #t14 = local in #t14.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t14{core::int};
+  function #local#set(core::int #t15) → dynamic
+    return local = #t15;
+  final dynamic finalLocal;
+  core::bool #finalLocal#isSet = false;
+  function #finalLocal#get() → dynamic
+    return #finalLocal#isSet ?{dynamic} finalLocal : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has not been initialized.");
+  function #finalLocal#set(dynamic #t16) → dynamic
+    if(#finalLocal#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has already been initialized.");
+    else {
+      #finalLocal#isSet = true;
+      return finalLocal = #t16;
+    }
+  non::method::T? localTypeVariable;
+  function #localTypeVariable#get() → non::method::T
+    return let final non::method::T? #t17 = localTypeVariable in #t17.==(null) ?{non::method::T} throw new _in::LateInitializationErrorImpl::•("Local 'localTypeVariable' has not been initialized.") : #t17{non::method::T};
+  function #localTypeVariable#set(non::method::T #t18) → dynamic
+    return localTypeVariable = #t18;
+  final non::method::T? finalLocalTypeVariable;
+  function #finalLocalTypeVariable#get() → non::method::T
+    return let final non::method::T? #t19 = finalLocalTypeVariable in #t19.==(null) ?{non::method::T} throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has not been initialized.") : #t19{non::method::T};
+  function #finalLocalTypeVariable#set(non::method::T #t20) → dynamic
+    if(finalLocalTypeVariable.==(null))
+      return finalLocalTypeVariable = #t20;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has already been initialized.");
+  if(b) {
+    #local#set.call(i);
+    #finalLocal#set.call(i);
+    #localTypeVariable#set.call(t);
+    #finalLocalTypeVariable#set.call(t);
+    non::expect(i, #local#get.call());
+    non::expect(i, #finalLocal#get.call());
+    non::expect(t, #localTypeVariable#get.call());
+    non::expect(t, #finalLocalTypeVariable#get.call());
+  }
+  non::throws(() → core::int => #finalLocal#set.call(i));
+  non::throws(() → non::method::T => #finalLocalTypeVariable#set.call(t));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect
new file mode 100644
index 0000000..6ffbd4b
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.strong.transformed.expect
@@ -0,0 +1,166 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart:5:1: Error: A library can't opt out of null safety by default, when using sound null safety.
+// // @dart=2.8
+// ^^^^^^^^^^^^
+//
+import self as self;
+import "non_nullable_from_opt_out_lib.dart" as non;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///non_nullable_from_opt_out_lib.dart";
+
+static method main() → dynamic {
+  non::topLevelField = null;
+  non::finalTopLevelField = null;
+  non::Class<core::int*>* c = new non::Class::•<core::int*>();
+  c.{non::Class::instanceField} = null;
+  c.{non::Class::finalInstanceField} = null;
+  c.{non::Class::instanceTypeVariable} = null;
+  c.{non::Class::finalInstanceTypeVariable} = null;
+  non::Class::staticField = null;
+  non::Class::staticFinalField = null;
+  non::expect(null, non::topLevelField);
+  non::expect(null, non::finalTopLevelField);
+  non::expect(null, c.{non::Class::instanceField});
+  non::expect(null, c.{non::Class::finalInstanceField});
+  non::expect(null, c.{non::Class::instanceTypeVariable});
+  non::expect(null, c.{non::Class::finalInstanceTypeVariable});
+  non::expect(null, non::Class::staticField);
+  non::expect(null, non::Class::staticFinalField);
+  non::throws(() → core::Null? => non::finalTopLevelField = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceField} = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceTypeVariable} = null);
+  non::throws(() → core::Null? => non::Class::staticFinalField = null);
+  non::method<core::Null?>(true, null, null);
+}
+
+library /*isNonNullableByDefault*/;
+import self as non;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object = core::Object> extends core::Object {
+  field core::int? _#Class#instanceField = null;
+  field dynamic _#Class#finalInstanceField = null;
+  field core::bool _#Class#finalInstanceField#isSet = false;
+  generic-covariant-impl field non::Class::T? _#Class#instanceTypeVariable = null;
+  field non::Class::T? _#Class#finalInstanceTypeVariable = null;
+  static field core::int? _#staticField = null;
+  static field dynamic _#staticFinalField = null;
+  static field core::bool _#staticFinalField#isSet = false;
+  synthetic constructor •() → non::Class<non::Class::T>
+    : super core::Object::•()
+    ;
+  get instanceField() → core::int
+    return let final core::int? #t1 = this.{non::Class::_#Class#instanceField} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.") : #t1{core::int};
+  set instanceField(core::int #t2) → void
+    this.{non::Class::_#Class#instanceField} = #t2;
+  get finalInstanceField() → dynamic
+    return this.{non::Class::_#Class#finalInstanceField#isSet} ?{dynamic} this.{non::Class::_#Class#finalInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
+  set finalInstanceField(dynamic #t3) → void
+    if(this.{non::Class::_#Class#finalInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceField#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceField} = #t3;
+    }
+  get instanceTypeVariable() → non::Class::T
+    return let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable} in #t4.==(null) ?{non::Class::T} throw new _in::LateInitializationErrorImpl::•("Field 'instanceTypeVariable' has not been initialized.") : #t4{non::Class::T};
+  set instanceTypeVariable(generic-covariant-impl non::Class::T #t5) → void
+    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+  get finalInstanceTypeVariable() → non::Class::T
+    return let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable} in #t6.==(null) ?{non::Class::T} throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has not been initialized.") : #t6{non::Class::T};
+  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    if(this.{non::Class::_#Class#finalInstanceTypeVariable}.==(null))
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has already been initialized.");
+  static get staticField() → core::int
+    return let final core::int? #t8 = non::Class::_#staticField in #t8.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.") : #t8{core::int};
+  static set staticField(core::int #t9) → void
+    non::Class::_#staticField = #t9;
+  static get staticFinalField() → dynamic
+    return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has not been initialized.");
+  static set staticFinalField(dynamic #t10) → void
+    if(non::Class::_#staticFinalField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has already been initialized.");
+    else {
+      non::Class::_#staticFinalField#isSet = true;
+      non::Class::_#staticFinalField = #t10;
+    }
+}
+static field core::int? _#topLevelField = null;
+static field dynamic _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
+static get topLevelField() → core::int
+  return let final core::int? #t11 = non::_#topLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.") : #t11{core::int};
+static set topLevelField(core::int #t12) → void
+  non::_#topLevelField = #t12;
+static get finalTopLevelField() → dynamic
+  return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
+static set finalTopLevelField(dynamic #t13) → void
+  if(non::_#finalTopLevelField#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    non::_#finalTopLevelField#isSet = true;
+    non::_#finalTopLevelField = #t13;
+  }
+static method method<T extends core::Object = core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
+  core::int? local;
+  function #local#get() → core::int
+    return let final core::int? #t14 = local in #t14.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.") : #t14{core::int};
+  function #local#set(core::int #t15) → dynamic
+    return local = #t15;
+  final dynamic finalLocal;
+  core::bool #finalLocal#isSet = false;
+  function #finalLocal#get() → dynamic
+    return #finalLocal#isSet ?{dynamic} finalLocal : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has not been initialized.");
+  function #finalLocal#set(dynamic #t16) → dynamic
+    if(#finalLocal#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has already been initialized.");
+    else {
+      #finalLocal#isSet = true;
+      return finalLocal = #t16;
+    }
+  non::method::T? localTypeVariable;
+  function #localTypeVariable#get() → non::method::T
+    return let final non::method::T? #t17 = localTypeVariable in #t17.==(null) ?{non::method::T} throw new _in::LateInitializationErrorImpl::•("Local 'localTypeVariable' has not been initialized.") : #t17{non::method::T};
+  function #localTypeVariable#set(non::method::T #t18) → dynamic
+    return localTypeVariable = #t18;
+  final non::method::T? finalLocalTypeVariable;
+  function #finalLocalTypeVariable#get() → non::method::T
+    return let final non::method::T? #t19 = finalLocalTypeVariable in #t19.==(null) ?{non::method::T} throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has not been initialized.") : #t19{non::method::T};
+  function #finalLocalTypeVariable#set(non::method::T #t20) → dynamic
+    if(finalLocalTypeVariable.==(null))
+      return finalLocalTypeVariable = #t20;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has already been initialized.");
+  if(b) {
+    #local#set.call(i);
+    #finalLocal#set.call(i);
+    #localTypeVariable#set.call(t);
+    #finalLocalTypeVariable#set.call(t);
+    non::expect(i, #local#get.call());
+    non::expect(i, #finalLocal#get.call());
+    non::expect(t, #localTypeVariable#get.call());
+    non::expect(t, #finalLocalTypeVariable#get.call());
+  }
+  non::throws(() → core::int => #finalLocal#set.call(i));
+  non::throws(() → non::method::T => #finalLocalTypeVariable#set.call(t));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline.expect
new file mode 100644
index 0000000..3bd3cd1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'non_nullable_from_opt_out_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..3bd3cd1
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'non_nullable_from_opt_out_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect
new file mode 100644
index 0000000..454958d
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.expect
@@ -0,0 +1,183 @@
+library;
+import self as self;
+import "non_nullable_from_opt_out_lib.dart" as non;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///non_nullable_from_opt_out_lib.dart";
+
+static method main() → dynamic {
+  non::topLevelField = null;
+  non::finalTopLevelField = null;
+  non::Class<core::int*>* c = new non::Class::•<core::int*>();
+  c.{non::Class::instanceField} = null;
+  c.{non::Class::finalInstanceField} = null;
+  c.{non::Class::instanceTypeVariable} = null;
+  c.{non::Class::finalInstanceTypeVariable} = null;
+  non::Class::staticField = null;
+  non::Class::staticFinalField = null;
+  non::expect(null, non::topLevelField);
+  non::expect(null, non::finalTopLevelField);
+  non::expect(null, c.{non::Class::instanceField});
+  non::expect(null, c.{non::Class::finalInstanceField});
+  non::expect(null, c.{non::Class::instanceTypeVariable});
+  non::expect(null, c.{non::Class::finalInstanceTypeVariable});
+  non::expect(null, non::Class::staticField);
+  non::expect(null, non::Class::staticFinalField);
+  non::throws(() → core::Null? => non::finalTopLevelField = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceField} = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceTypeVariable} = null);
+  non::throws(() → core::Null? => non::Class::staticFinalField = null);
+  non::method<core::Null?>(true, null, null);
+}
+
+library /*isNonNullableByDefault*/;
+import self as non;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object = core::Object> extends core::Object {
+  field core::int? _#Class#instanceField = null;
+  field core::bool _#Class#instanceField#isSet = false;
+  field dynamic _#Class#finalInstanceField = null;
+  field core::bool _#Class#finalInstanceField#isSet = false;
+  generic-covariant-impl field non::Class::T? _#Class#instanceTypeVariable = null;
+  field core::bool _#Class#instanceTypeVariable#isSet = false;
+  field non::Class::T? _#Class#finalInstanceTypeVariable = null;
+  field core::bool _#Class#finalInstanceTypeVariable#isSet = false;
+  static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
+  static field dynamic _#staticFinalField = null;
+  static field core::bool _#staticFinalField#isSet = false;
+  synthetic constructor •() → non::Class<non::Class::T>
+    : super core::Object::•()
+    ;
+  get instanceField() → core::int
+    return this.{non::Class::_#Class#instanceField#isSet} ?{core::int} let final core::int? #t1 = this.{non::Class::_#Class#instanceField} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
+  set instanceField(core::int #t2) → void {
+    this.{non::Class::_#Class#instanceField#isSet} = true;
+    this.{non::Class::_#Class#instanceField} = #t2;
+  }
+  get finalInstanceField() → dynamic
+    return this.{non::Class::_#Class#finalInstanceField#isSet} ?{dynamic} this.{non::Class::_#Class#finalInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
+  set finalInstanceField(dynamic #t3) → void
+    if(this.{non::Class::_#Class#finalInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceField#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceField} = #t3;
+    }
+  get instanceTypeVariable() → non::Class::T
+    return this.{non::Class::_#Class#instanceTypeVariable#isSet} ?{non::Class::T} let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable} in #t4{non::Class::T} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceTypeVariable' has not been initialized.");
+  set instanceTypeVariable(generic-covariant-impl non::Class::T #t5) → void {
+    this.{non::Class::_#Class#instanceTypeVariable#isSet} = true;
+    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+  }
+  get finalInstanceTypeVariable() → non::Class::T
+    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} ?{non::Class::T} let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable} in #t6{non::Class::T} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has not been initialized.");
+  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    if(this.{non::Class::_#Class#finalInstanceTypeVariable#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+    }
+  static get staticField() → core::int
+    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t8 = non::Class::_#staticField in #t8{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
+  static set staticField(core::int #t9) → void {
+    non::Class::_#staticField#isSet = true;
+    non::Class::_#staticField = #t9;
+  }
+  static get staticFinalField() → dynamic
+    return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has not been initialized.");
+  static set staticFinalField(dynamic #t10) → void
+    if(non::Class::_#staticFinalField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has already been initialized.");
+    else {
+      non::Class::_#staticFinalField#isSet = true;
+      non::Class::_#staticFinalField = #t10;
+    }
+}
+static field core::int? _#topLevelField = null;
+static field core::bool _#topLevelField#isSet = false;
+static field dynamic _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
+static get topLevelField() → core::int
+  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t11 = non::_#topLevelField in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.");
+static set topLevelField(core::int #t12) → void {
+  non::_#topLevelField#isSet = true;
+  non::_#topLevelField = #t12;
+}
+static get finalTopLevelField() → dynamic
+  return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
+static set finalTopLevelField(dynamic #t13) → void
+  if(non::_#finalTopLevelField#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    non::_#finalTopLevelField#isSet = true;
+    non::_#finalTopLevelField = #t13;
+  }
+static method method<T extends core::Object = core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
+  core::int? local;
+  core::bool #local#isSet = false;
+  function #local#get() → core::int
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t14) → dynamic {
+    #local#isSet = true;
+    return local = #t14;
+  }
+  final dynamic finalLocal;
+  core::bool #finalLocal#isSet = false;
+  function #finalLocal#get() → dynamic
+    return #finalLocal#isSet ?{dynamic} finalLocal : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has not been initialized.");
+  function #finalLocal#set(dynamic #t15) → dynamic
+    if(#finalLocal#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has already been initialized.");
+    else {
+      #finalLocal#isSet = true;
+      return finalLocal = #t15;
+    }
+  non::method::T? localTypeVariable;
+  core::bool #localTypeVariable#isSet = false;
+  function #localTypeVariable#get() → non::method::T
+    return #localTypeVariable#isSet ?{non::method::T} localTypeVariable{non::method::T} : throw new _in::LateInitializationErrorImpl::•("Local 'localTypeVariable' has not been initialized.");
+  function #localTypeVariable#set(non::method::T #t16) → dynamic {
+    #localTypeVariable#isSet = true;
+    return localTypeVariable = #t16;
+  }
+  final non::method::T? finalLocalTypeVariable;
+  core::bool #finalLocalTypeVariable#isSet = false;
+  function #finalLocalTypeVariable#get() → non::method::T
+    return #finalLocalTypeVariable#isSet ?{non::method::T} finalLocalTypeVariable{non::method::T} : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has not been initialized.");
+  function #finalLocalTypeVariable#set(non::method::T #t17) → dynamic
+    if(#finalLocalTypeVariable#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has already been initialized.");
+    else {
+      #finalLocalTypeVariable#isSet = true;
+      return finalLocalTypeVariable = #t17;
+    }
+  if(b) {
+    #local#set.call(i);
+    #finalLocal#set.call(i);
+    #localTypeVariable#set.call(t);
+    #finalLocalTypeVariable#set.call(t);
+    non::expect(i, #local#get.call());
+    non::expect(i, #finalLocal#get.call());
+    non::expect(t, #localTypeVariable#get.call());
+    non::expect(t, #finalLocalTypeVariable#get.call());
+  }
+  non::throws(() → core::int => #finalLocal#set.call(i));
+  non::throws(() → non::method::T => #finalLocalTypeVariable#set.call(t));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect
new file mode 100644
index 0000000..454958d
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out.dart.weak.transformed.expect
@@ -0,0 +1,183 @@
+library;
+import self as self;
+import "non_nullable_from_opt_out_lib.dart" as non;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///non_nullable_from_opt_out_lib.dart";
+
+static method main() → dynamic {
+  non::topLevelField = null;
+  non::finalTopLevelField = null;
+  non::Class<core::int*>* c = new non::Class::•<core::int*>();
+  c.{non::Class::instanceField} = null;
+  c.{non::Class::finalInstanceField} = null;
+  c.{non::Class::instanceTypeVariable} = null;
+  c.{non::Class::finalInstanceTypeVariable} = null;
+  non::Class::staticField = null;
+  non::Class::staticFinalField = null;
+  non::expect(null, non::topLevelField);
+  non::expect(null, non::finalTopLevelField);
+  non::expect(null, c.{non::Class::instanceField});
+  non::expect(null, c.{non::Class::finalInstanceField});
+  non::expect(null, c.{non::Class::instanceTypeVariable});
+  non::expect(null, c.{non::Class::finalInstanceTypeVariable});
+  non::expect(null, non::Class::staticField);
+  non::expect(null, non::Class::staticFinalField);
+  non::throws(() → core::Null? => non::finalTopLevelField = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceField} = null);
+  non::throws(() → core::Null? => c.{non::Class::finalInstanceTypeVariable} = null);
+  non::throws(() → core::Null? => non::Class::staticFinalField = null);
+  non::method<core::Null?>(true, null, null);
+}
+
+library /*isNonNullableByDefault*/;
+import self as non;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Class<T extends core::Object = core::Object> extends core::Object {
+  field core::int? _#Class#instanceField = null;
+  field core::bool _#Class#instanceField#isSet = false;
+  field dynamic _#Class#finalInstanceField = null;
+  field core::bool _#Class#finalInstanceField#isSet = false;
+  generic-covariant-impl field non::Class::T? _#Class#instanceTypeVariable = null;
+  field core::bool _#Class#instanceTypeVariable#isSet = false;
+  field non::Class::T? _#Class#finalInstanceTypeVariable = null;
+  field core::bool _#Class#finalInstanceTypeVariable#isSet = false;
+  static field core::int? _#staticField = null;
+  static field core::bool _#staticField#isSet = false;
+  static field dynamic _#staticFinalField = null;
+  static field core::bool _#staticFinalField#isSet = false;
+  synthetic constructor •() → non::Class<non::Class::T>
+    : super core::Object::•()
+    ;
+  get instanceField() → core::int
+    return this.{non::Class::_#Class#instanceField#isSet} ?{core::int} let final core::int? #t1 = this.{non::Class::_#Class#instanceField} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceField' has not been initialized.");
+  set instanceField(core::int #t2) → void {
+    this.{non::Class::_#Class#instanceField#isSet} = true;
+    this.{non::Class::_#Class#instanceField} = #t2;
+  }
+  get finalInstanceField() → dynamic
+    return this.{non::Class::_#Class#finalInstanceField#isSet} ?{dynamic} this.{non::Class::_#Class#finalInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has not been initialized.");
+  set finalInstanceField(dynamic #t3) → void
+    if(this.{non::Class::_#Class#finalInstanceField#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceField' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceField#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceField} = #t3;
+    }
+  get instanceTypeVariable() → non::Class::T
+    return this.{non::Class::_#Class#instanceTypeVariable#isSet} ?{non::Class::T} let final non::Class::T? #t4 = this.{non::Class::_#Class#instanceTypeVariable} in #t4{non::Class::T} : throw new _in::LateInitializationErrorImpl::•("Field 'instanceTypeVariable' has not been initialized.");
+  set instanceTypeVariable(generic-covariant-impl non::Class::T #t5) → void {
+    this.{non::Class::_#Class#instanceTypeVariable#isSet} = true;
+    this.{non::Class::_#Class#instanceTypeVariable} = #t5;
+  }
+  get finalInstanceTypeVariable() → non::Class::T
+    return this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} ?{non::Class::T} let final non::Class::T? #t6 = this.{non::Class::_#Class#finalInstanceTypeVariable} in #t6{non::Class::T} : throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has not been initialized.");
+  set finalInstanceTypeVariable(non::Class::T #t7) → void
+    if(this.{non::Class::_#Class#finalInstanceTypeVariable#isSet})
+      throw new _in::LateInitializationErrorImpl::•("Field 'finalInstanceTypeVariable' has already been initialized.");
+    else {
+      this.{non::Class::_#Class#finalInstanceTypeVariable#isSet} = true;
+      this.{non::Class::_#Class#finalInstanceTypeVariable} = #t7;
+    }
+  static get staticField() → core::int
+    return non::Class::_#staticField#isSet ?{core::int} let final core::int? #t8 = non::Class::_#staticField in #t8{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'staticField' has not been initialized.");
+  static set staticField(core::int #t9) → void {
+    non::Class::_#staticField#isSet = true;
+    non::Class::_#staticField = #t9;
+  }
+  static get staticFinalField() → dynamic
+    return non::Class::_#staticFinalField#isSet ?{dynamic} non::Class::_#staticFinalField : throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has not been initialized.");
+  static set staticFinalField(dynamic #t10) → void
+    if(non::Class::_#staticFinalField#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'staticFinalField' has already been initialized.");
+    else {
+      non::Class::_#staticFinalField#isSet = true;
+      non::Class::_#staticFinalField = #t10;
+    }
+}
+static field core::int? _#topLevelField = null;
+static field core::bool _#topLevelField#isSet = false;
+static field dynamic _#finalTopLevelField = null;
+static field core::bool _#finalTopLevelField#isSet = false;
+static get topLevelField() → core::int
+  return non::_#topLevelField#isSet ?{core::int} let final core::int? #t11 = non::_#topLevelField in #t11{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'topLevelField' has not been initialized.");
+static set topLevelField(core::int #t12) → void {
+  non::_#topLevelField#isSet = true;
+  non::_#topLevelField = #t12;
+}
+static get finalTopLevelField() → dynamic
+  return non::_#finalTopLevelField#isSet ?{dynamic} non::_#finalTopLevelField : throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has not been initialized.");
+static set finalTopLevelField(dynamic #t13) → void
+  if(non::_#finalTopLevelField#isSet)
+    throw new _in::LateInitializationErrorImpl::•("Field 'finalTopLevelField' has already been initialized.");
+  else {
+    non::_#finalTopLevelField#isSet = true;
+    non::_#finalTopLevelField = #t13;
+  }
+static method method<T extends core::Object = core::Object>(core::bool b, core::int i, non::method::T t) → dynamic {
+  core::int? local;
+  core::bool #local#isSet = false;
+  function #local#get() → core::int
+    return #local#isSet ?{core::int} local{core::int} : throw new _in::LateInitializationErrorImpl::•("Local 'local' has not been initialized.");
+  function #local#set(core::int #t14) → dynamic {
+    #local#isSet = true;
+    return local = #t14;
+  }
+  final dynamic finalLocal;
+  core::bool #finalLocal#isSet = false;
+  function #finalLocal#get() → dynamic
+    return #finalLocal#isSet ?{dynamic} finalLocal : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has not been initialized.");
+  function #finalLocal#set(dynamic #t15) → dynamic
+    if(#finalLocal#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocal' has already been initialized.");
+    else {
+      #finalLocal#isSet = true;
+      return finalLocal = #t15;
+    }
+  non::method::T? localTypeVariable;
+  core::bool #localTypeVariable#isSet = false;
+  function #localTypeVariable#get() → non::method::T
+    return #localTypeVariable#isSet ?{non::method::T} localTypeVariable{non::method::T} : throw new _in::LateInitializationErrorImpl::•("Local 'localTypeVariable' has not been initialized.");
+  function #localTypeVariable#set(non::method::T #t16) → dynamic {
+    #localTypeVariable#isSet = true;
+    return localTypeVariable = #t16;
+  }
+  final non::method::T? finalLocalTypeVariable;
+  core::bool #finalLocalTypeVariable#isSet = false;
+  function #finalLocalTypeVariable#get() → non::method::T
+    return #finalLocalTypeVariable#isSet ?{non::method::T} finalLocalTypeVariable{non::method::T} : throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has not been initialized.");
+  function #finalLocalTypeVariable#set(non::method::T #t17) → dynamic
+    if(#finalLocalTypeVariable#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Local 'finalLocalTypeVariable' has already been initialized.");
+    else {
+      #finalLocalTypeVariable#isSet = true;
+      return finalLocalTypeVariable = #t17;
+    }
+  if(b) {
+    #local#set.call(i);
+    #finalLocal#set.call(i);
+    #localTypeVariable#set.call(t);
+    #finalLocalTypeVariable#set.call(t);
+    non::expect(i, #local#get.call());
+    non::expect(i, #finalLocal#get.call());
+    non::expect(t, #localTypeVariable#get.call());
+    non::expect(t, #finalLocalTypeVariable#get.call());
+  }
+  non::throws(() → core::int => #finalLocal#set.call(i));
+  non::throws(() → non::method::T => #finalLocalTypeVariable#set.call(t));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out_lib.dart b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out_lib.dart
new file mode 100644
index 0000000..96ed716
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/non_nullable_from_opt_out_lib.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+late int topLevelField;
+late final finalTopLevelField;
+
+class Class<T extends Object> {
+  late int instanceField;
+  late final finalInstanceField;
+  late T instanceTypeVariable;
+  late final T finalInstanceTypeVariable;
+
+  static late int staticField;
+  static late final staticFinalField;
+}
+
+method<T extends Object>(bool b, int i, T t) {
+  late int local;
+  late final finalLocal;
+  late T localTypeVariable;
+  late final T finalLocalTypeVariable;
+
+  if (b) {
+    // Ensure assignments below are not definitely assigned.
+    local = i;
+    finalLocal = i;
+    localTypeVariable = t;
+    finalLocalTypeVariable = t;
+
+    expect(i, local);
+    expect(i, finalLocal);
+    expect(t, localTypeVariable);
+    expect(t, finalLocalTypeVariable);
+  }
+
+  throws(() => finalLocal = i);
+  throws(() => finalLocalTypeVariable = t);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Missing exception';
+}
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
index 8e2fcee..f94376c 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.strong.transformed.expect
@@ -119,3 +119,8 @@
   }
   throw "${message}: ${value}";
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///override.dart:16:18 -> IntConstant(0)
+Extra constant evaluation: evaluated: 232, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
index 8e2fcee..961d813 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.expect
@@ -5,60 +5,95 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field1 = null;
+  field core::bool _#Class#field1#isSet = false;
   field core::int? _#Class#field2 = null;
+  field core::bool _#Class#field2#isSet = false;
   field core::int? _#Class#field3 = null;
+  field core::bool _#Class#field3#isSet = false;
   field core::int? _#Class#field4 = null;
+  field core::bool _#Class#field4#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
   get field1() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field1} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.") : #t1{core::int};
-  set field1(core::int #t2) → void
+    return this.{self::Class::_#Class#field1#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field1} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(core::int #t2) → void {
+    this.{self::Class::_#Class#field1#isSet} = true;
     this.{self::Class::_#Class#field1} = #t2;
+  }
   get field2() → core::int
-    return let final core::int? #t3 = this.{self::Class::_#Class#field2} in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.") : #t3{core::int};
-  set field2(core::int #t4) → void
+    return this.{self::Class::_#Class#field2#isSet} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field2} in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(core::int #t4) → void {
+    this.{self::Class::_#Class#field2#isSet} = true;
     this.{self::Class::_#Class#field2} = #t4;
+  }
   get field3() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#field3} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.") : #t5{core::int};
+    return this.{self::Class::_#Class#field3#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#field3} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
   set field3(core::int #t6) → void
-    if(this.{self::Class::_#Class#field3}.==(null))
-      this.{self::Class::_#Class#field3} = #t6;
-    else
+    if(this.{self::Class::_#Class#field3#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field3' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field3#isSet} = true;
+      this.{self::Class::_#Class#field3} = #t6;
+    }
   get field4() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#field4} in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.") : #t7{core::int};
+    return this.{self::Class::_#Class#field4#isSet} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#field4} in #t7{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
   set field4(core::int #t8) → void
-    if(this.{self::Class::_#Class#field4}.==(null))
-      this.{self::Class::_#Class#field4} = #t8;
-    else
+    if(this.{self::Class::_#Class#field4#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field4' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field4#isSet} = true;
+      this.{self::Class::_#Class#field4} = #t8;
+    }
 }
 class SubClass extends self::Class {
   field core::int? _#SubClass#field1 = null;
+  field core::bool _#SubClass#field1#isSet = false;
   field core::int? _#SubClass#field2 = null;
+  field core::bool _#SubClass#field2#isSet = false;
   field core::int? _#SubClass#field3 = null;
+  field core::bool _#SubClass#field3#isSet = false;
   field core::int? _#SubClass#field4 = null;
+  field core::bool _#SubClass#field4#isSet = false;
   synthetic constructor •() → self::SubClass
     : super self::Class::•()
     ;
   get field1() → core::int
-    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1} in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.") : #t9{core::int};
-  set field1(core::int #t10) → void
+    return this.{self::SubClass::_#SubClass#field1#isSet} ?{core::int} let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1} in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(core::int #t10) → void {
+    this.{self::SubClass::_#SubClass#field1#isSet} = true;
     this.{self::SubClass::_#SubClass#field1} = #t10;
-  get field2() → core::int
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2} in #t11.==(null) ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t11{core::int};
-  set field2(core::int #t12) → void
+  }
+  get field2() → core::int {
+    if(!this.{self::SubClass::_#SubClass#field2#isSet}) {
+      this.{self::SubClass::_#SubClass#field2} = 0;
+      this.{self::SubClass::_#SubClass#field2#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2} in #t11{core::int};
+  }
+  set field2(core::int #t12) → void {
+    this.{self::SubClass::_#SubClass#field2#isSet} = true;
     this.{self::SubClass::_#SubClass#field2} = #t12;
+  }
   get field3() → core::int
-    return let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3} in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.") : #t13{core::int};
+    return this.{self::SubClass::_#SubClass#field3#isSet} ?{core::int} let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3} in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
   set field3(core::int #t14) → void
-    if(this.{self::SubClass::_#SubClass#field3}.==(null))
-      this.{self::SubClass::_#SubClass#field3} = #t14;
-    else
+    if(this.{self::SubClass::_#SubClass#field3#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field3' has already been initialized.");
-  get field4() → core::int
-    return let final core::int? #t15 = this.{self::SubClass::_#SubClass#field4} in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in this.{self::SubClass::_#SubClass#field4}.==(null) ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has been assigned during initialization.") : #t15{core::int};
+    else {
+      this.{self::SubClass::_#SubClass#field3#isSet} = true;
+      this.{self::SubClass::_#SubClass#field3} = #t14;
+    }
+  get field4() → core::int {
+    if(!this.{self::SubClass::_#SubClass#field4#isSet}) {
+      final core::int #t15 = 0;
+      if(this.{self::SubClass::_#SubClass#field4#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'field4' has been assigned during initialization.");
+      this.{self::SubClass::_#SubClass#field4} = #t15;
+      this.{self::SubClass::_#SubClass#field4#isSet} = true;
+    }
+    return let final core::int? #t16 = this.{self::SubClass::_#SubClass#field4} in #t16{core::int};
+  }
   get directField1() → core::int
     return super.{self::Class::field1};
   set directField1(core::int value) → void {
diff --git a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
index 8e2fcee..961d813 100644
--- a/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override.dart.weak.transformed.expect
@@ -5,60 +5,95 @@
 
 class Class extends core::Object {
   field core::int? _#Class#field1 = null;
+  field core::bool _#Class#field1#isSet = false;
   field core::int? _#Class#field2 = null;
+  field core::bool _#Class#field2#isSet = false;
   field core::int? _#Class#field3 = null;
+  field core::bool _#Class#field3#isSet = false;
   field core::int? _#Class#field4 = null;
+  field core::bool _#Class#field4#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
   get field1() → core::int
-    return let final core::int? #t1 = this.{self::Class::_#Class#field1} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.") : #t1{core::int};
-  set field1(core::int #t2) → void
+    return this.{self::Class::_#Class#field1#isSet} ?{core::int} let final core::int? #t1 = this.{self::Class::_#Class#field1} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(core::int #t2) → void {
+    this.{self::Class::_#Class#field1#isSet} = true;
     this.{self::Class::_#Class#field1} = #t2;
+  }
   get field2() → core::int
-    return let final core::int? #t3 = this.{self::Class::_#Class#field2} in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.") : #t3{core::int};
-  set field2(core::int #t4) → void
+    return this.{self::Class::_#Class#field2#isSet} ?{core::int} let final core::int? #t3 = this.{self::Class::_#Class#field2} in #t3{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field2' has not been initialized.");
+  set field2(core::int #t4) → void {
+    this.{self::Class::_#Class#field2#isSet} = true;
     this.{self::Class::_#Class#field2} = #t4;
+  }
   get field3() → core::int
-    return let final core::int? #t5 = this.{self::Class::_#Class#field3} in #t5.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.") : #t5{core::int};
+    return this.{self::Class::_#Class#field3#isSet} ?{core::int} let final core::int? #t5 = this.{self::Class::_#Class#field3} in #t5{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
   set field3(core::int #t6) → void
-    if(this.{self::Class::_#Class#field3}.==(null))
-      this.{self::Class::_#Class#field3} = #t6;
-    else
+    if(this.{self::Class::_#Class#field3#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field3' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field3#isSet} = true;
+      this.{self::Class::_#Class#field3} = #t6;
+    }
   get field4() → core::int
-    return let final core::int? #t7 = this.{self::Class::_#Class#field4} in #t7.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.") : #t7{core::int};
+    return this.{self::Class::_#Class#field4#isSet} ?{core::int} let final core::int? #t7 = this.{self::Class::_#Class#field4} in #t7{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
   set field4(core::int #t8) → void
-    if(this.{self::Class::_#Class#field4}.==(null))
-      this.{self::Class::_#Class#field4} = #t8;
-    else
+    if(this.{self::Class::_#Class#field4#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field4' has already been initialized.");
+    else {
+      this.{self::Class::_#Class#field4#isSet} = true;
+      this.{self::Class::_#Class#field4} = #t8;
+    }
 }
 class SubClass extends self::Class {
   field core::int? _#SubClass#field1 = null;
+  field core::bool _#SubClass#field1#isSet = false;
   field core::int? _#SubClass#field2 = null;
+  field core::bool _#SubClass#field2#isSet = false;
   field core::int? _#SubClass#field3 = null;
+  field core::bool _#SubClass#field3#isSet = false;
   field core::int? _#SubClass#field4 = null;
+  field core::bool _#SubClass#field4#isSet = false;
   synthetic constructor •() → self::SubClass
     : super self::Class::•()
     ;
   get field1() → core::int
-    return let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1} in #t9.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.") : #t9{core::int};
-  set field1(core::int #t10) → void
+    return this.{self::SubClass::_#SubClass#field1#isSet} ?{core::int} let final core::int? #t9 = this.{self::SubClass::_#SubClass#field1} in #t9{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field1' has not been initialized.");
+  set field1(core::int #t10) → void {
+    this.{self::SubClass::_#SubClass#field1#isSet} = true;
     this.{self::SubClass::_#SubClass#field1} = #t10;
-  get field2() → core::int
-    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2} in #t11.==(null) ?{core::int} this.{self::SubClass::_#SubClass#field2} = 0 : #t11{core::int};
-  set field2(core::int #t12) → void
+  }
+  get field2() → core::int {
+    if(!this.{self::SubClass::_#SubClass#field2#isSet}) {
+      this.{self::SubClass::_#SubClass#field2} = 0;
+      this.{self::SubClass::_#SubClass#field2#isSet} = true;
+    }
+    return let final core::int? #t11 = this.{self::SubClass::_#SubClass#field2} in #t11{core::int};
+  }
+  set field2(core::int #t12) → void {
+    this.{self::SubClass::_#SubClass#field2#isSet} = true;
     this.{self::SubClass::_#SubClass#field2} = #t12;
+  }
   get field3() → core::int
-    return let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3} in #t13.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.") : #t13{core::int};
+    return this.{self::SubClass::_#SubClass#field3#isSet} ?{core::int} let final core::int? #t13 = this.{self::SubClass::_#SubClass#field3} in #t13{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
   set field3(core::int #t14) → void
-    if(this.{self::SubClass::_#SubClass#field3}.==(null))
-      this.{self::SubClass::_#SubClass#field3} = #t14;
-    else
+    if(this.{self::SubClass::_#SubClass#field3#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'field3' has already been initialized.");
-  get field4() → core::int
-    return let final core::int? #t15 = this.{self::SubClass::_#SubClass#field4} in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in this.{self::SubClass::_#SubClass#field4}.==(null) ?{core::int} this.{self::SubClass::_#SubClass#field4} = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has been assigned during initialization.") : #t15{core::int};
+    else {
+      this.{self::SubClass::_#SubClass#field3#isSet} = true;
+      this.{self::SubClass::_#SubClass#field3} = #t14;
+    }
+  get field4() → core::int {
+    if(!this.{self::SubClass::_#SubClass#field4#isSet}) {
+      final core::int #t15 = 0;
+      if(this.{self::SubClass::_#SubClass#field4#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'field4' has been assigned during initialization.");
+      this.{self::SubClass::_#SubClass#field4} = #t15;
+      this.{self::SubClass::_#SubClass#field4#isSet} = true;
+    }
+    return let final core::int? #t16 = this.{self::SubClass::_#SubClass#field4} in #t16{core::int};
+  }
   get directField1() → core::int
     return super.{self::Class::field1};
   set directField1(core::int value) → void {
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
index 6e5f0ef..6466db6 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.strong.transformed.expect
@@ -87,3 +87,8 @@
   }
   throw "${message}: ${value}";
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///override_getter_setter.dart:18:18 -> IntConstant(2)
+Extra constant evaluation: evaluated: 119, effectively constant: 1
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
index 6e5f0ef..e51321c 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.expect
@@ -5,18 +5,21 @@
 
 class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   field core::int? _#A#y = null;
   field core::bool _#A#y#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(core::int #t2) → void
-    if(this.{self::A::_#A#x}.==(null))
-      this.{self::A::_#A#x} = #t2;
-    else
+    if(this.{self::A::_#A#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::A::_#A#x#isSet} = true;
+      this.{self::A::_#A#x} = #t2;
+    }
   get y() → core::int?
     return this.{self::A::_#A#y#isSet} ?{core::int?} this.{self::A::_#A#y} : throw new _in::LateInitializationErrorImpl::•("Field 'y' has not been initialized.");
   set y(core::int? #t3) → void
@@ -38,13 +41,22 @@
 }
 class C extends self::A {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   field core::int? _#C#y = null;
   field core::bool _#C#y#isSet = false;
   synthetic constructor •() → self::C
     : super self::A::•()
     ;
-  get x() → core::int
-    return let final core::int? #t4 = this.{self::C::_#C#x} in #t4.==(null) ?{core::int} let final core::int #t5 = 2 in this.{self::C::_#C#x}.==(null) ?{core::int} this.{self::C::_#C#x} = #t5 : throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.") : #t4{core::int};
+  get x() → core::int {
+    if(!this.{self::C::_#C#x#isSet}) {
+      final core::int #t4 = 2;
+      if(this.{self::C::_#C#x#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.");
+      this.{self::C::_#C#x} = #t4;
+      this.{self::C::_#C#x#isSet} = true;
+    }
+    return let final core::int? #t5 = this.{self::C::_#C#x} in #t5{core::int};
+  }
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}) {
       final core::int? #t6 = 2;
diff --git a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
index 6e5f0ef..e51321c 100644
--- a/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/override_getter_setter.dart.weak.transformed.expect
@@ -5,18 +5,21 @@
 
 class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   field core::int? _#A#y = null;
   field core::bool _#A#y#isSet = false;
   synthetic constructor •() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
   set x(core::int #t2) → void
-    if(this.{self::A::_#A#x}.==(null))
-      this.{self::A::_#A#x} = #t2;
-    else
+    if(this.{self::A::_#A#x#isSet})
       throw new _in::LateInitializationErrorImpl::•("Field 'x' has already been initialized.");
+    else {
+      this.{self::A::_#A#x#isSet} = true;
+      this.{self::A::_#A#x} = #t2;
+    }
   get y() → core::int?
     return this.{self::A::_#A#y#isSet} ?{core::int?} this.{self::A::_#A#y} : throw new _in::LateInitializationErrorImpl::•("Field 'y' has not been initialized.");
   set y(core::int? #t3) → void
@@ -38,13 +41,22 @@
 }
 class C extends self::A {
   field core::int? _#C#x = null;
+  field core::bool _#C#x#isSet = false;
   field core::int? _#C#y = null;
   field core::bool _#C#y#isSet = false;
   synthetic constructor •() → self::C
     : super self::A::•()
     ;
-  get x() → core::int
-    return let final core::int? #t4 = this.{self::C::_#C#x} in #t4.==(null) ?{core::int} let final core::int #t5 = 2 in this.{self::C::_#C#x}.==(null) ?{core::int} this.{self::C::_#C#x} = #t5 : throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.") : #t4{core::int};
+  get x() → core::int {
+    if(!this.{self::C::_#C#x#isSet}) {
+      final core::int #t4 = 2;
+      if(this.{self::C::_#C#x#isSet})
+        throw new _in::LateInitializationErrorImpl::•("Field 'x' has been assigned during initialization.");
+      this.{self::C::_#C#x} = #t4;
+      this.{self::C::_#C#x#isSet} = true;
+    }
+    return let final core::int? #t5 = this.{self::C::_#C#x} in #t5{core::int};
+  }
   get y() → core::int? {
     if(!this.{self::C::_#C#y#isSet}) {
       final core::int? #t6 = 2;
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
index 1cc4a59..9db48a4 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.expect
@@ -26,10 +26,18 @@
 }
 static method returnNonNullable(core::int value) → core::int {
   core::int? result;
-  function #result#get() → core::int
-    return let final core::int? #t2 = result in #t2.==(null) ?{core::int} result = value : #t2{core::int};
-  function #result#set(core::int #t3) → dynamic
-    return result = #t3;
+  core::bool #result#isSet = false;
+  function #result#get() → core::int {
+    if(!#result#isSet) {
+      result = value;
+      #result#isSet = true;
+    }
+    return result{core::int};
+  }
+  function #result#set(core::int #t2) → dynamic {
+    #result#isSet = true;
+    return result = #t2;
+  }
   return #result#get.call();
 }
 static method returnNullable(core::int? value) → core::int? {
@@ -42,9 +50,9 @@
     }
     return result;
   }
-  function #result#set(core::int? #t4) → dynamic {
+  function #result#set(core::int? #t3) → dynamic {
     #result#isSet = true;
-    return result = #t4;
+    return result = #t3;
   }
   return #result#get.call();
 }
diff --git a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
index 1cc4a59..9db48a4 100644
--- a/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/return_late.dart.weak.transformed.expect
@@ -26,10 +26,18 @@
 }
 static method returnNonNullable(core::int value) → core::int {
   core::int? result;
-  function #result#get() → core::int
-    return let final core::int? #t2 = result in #t2.==(null) ?{core::int} result = value : #t2{core::int};
-  function #result#set(core::int #t3) → dynamic
-    return result = #t3;
+  core::bool #result#isSet = false;
+  function #result#get() → core::int {
+    if(!#result#isSet) {
+      result = value;
+      #result#isSet = true;
+    }
+    return result{core::int};
+  }
+  function #result#set(core::int #t2) → dynamic {
+    #result#isSet = true;
+    return result = #t2;
+  }
   return #result#get.call();
 }
 static method returnNullable(core::int? value) → core::int? {
@@ -42,9 +50,9 @@
     }
     return result;
   }
-  function #result#set(core::int? #t4) → dynamic {
+  function #result#set(core::int? #t3) → dynamic {
     #result#isSet = true;
-    return result = #t4;
+    return result = #t3;
   }
   return #result#get.call();
 }
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
index 2829fae..327729a 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.expect
@@ -5,15 +5,18 @@
 
 class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   constructor foo(core::int x) → self::A
-    : self::A::_#A#x = x, super core::Object::•()
+    : self::A::_#A#x#isSet = true, self::A::_#A#x = x, super core::Object::•()
     ;
   constructor bar() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
     this.{self::A::_#A#x} = #t2;
+  }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
index 2829fae..327729a 100644
--- a/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/uninitialized_non_nullable_late_fields.dart.weak.transformed.expect
@@ -5,15 +5,18 @@
 
 class A extends core::Object {
   field core::int? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
   constructor foo(core::int x) → self::A
-    : self::A::_#A#x = x, super core::Object::•()
+    : self::A::_#A#x#isSet = true, self::A::_#A#x = x, super core::Object::•()
     ;
   constructor bar() → self::A
     : super core::Object::•()
     ;
   get x() → core::int
-    return let final core::int? #t1 = this.{self::A::_#A#x} in #t1.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.") : #t1{core::int};
-  set x(core::int #t2) → void
+    return this.{self::A::_#A#x#isSet} ?{core::int} let final core::int? #t1 = this.{self::A::_#A#x} in #t1{core::int} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(core::int #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
     this.{self::A::_#A#x} = #t2;
+  }
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/folder.options b/pkg/front_end/testcases/late_lowering_sentinel/folder.options
new file mode 100644
index 0000000..8d48ec9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/folder.options
@@ -0,0 +1,3 @@
+--enable-experiment=non-nullable
+--force-late-lowering
+--force-late-lowering-sentinel
\ No newline at end of file
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart
new file mode 100644
index 0000000..3434c11
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+late int? nullableTopLevelField;
+late int nonNullableTopLevelField;
+late int? nullableTopLevelFieldWithInitializer = null;
+late int nonNullableTopLevelFieldWithInitializer = 0;
+late final int? nullableFinalTopLevelField;
+late final int nonNullableFinalTopLevelField;
+late final int? nullableFinalTopLevelFieldWithInitializer = null;
+late final int nonNullableFinalTopLevelFieldWithInitializer = 0;
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.outline.expect
new file mode 100644
index 0000000..98525c7
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.outline.expect
@@ -0,0 +1,28 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static field core::int? _#nullableTopLevelField;
+static field core::int? _#nonNullableTopLevelField;
+static field core::int? _#nullableTopLevelFieldWithInitializer;
+static field core::int? _#nonNullableTopLevelFieldWithInitializer;
+static field core::int? _#nullableFinalTopLevelField;
+static field core::int? _#nonNullableFinalTopLevelField;
+static field core::int? _#nullableFinalTopLevelFieldWithInitializer;
+static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer;
+static get nullableTopLevelField() → core::int?;
+static set nullableTopLevelField(core::int? #t1) → void;
+static get nonNullableTopLevelField() → core::int;
+static set nonNullableTopLevelField(core::int #t2) → void;
+static get nullableTopLevelFieldWithInitializer() → core::int?;
+static set nullableTopLevelFieldWithInitializer(core::int? #t3) → void;
+static get nonNullableTopLevelFieldWithInitializer() → core::int;
+static set nonNullableTopLevelFieldWithInitializer(core::int #t4) → void;
+static get nullableFinalTopLevelField() → core::int?;
+static set nullableFinalTopLevelField(core::int? #t5) → void;
+static get nonNullableFinalTopLevelField() → core::int;
+static set nonNullableFinalTopLevelField(core::int #t6) → void;
+static get nullableFinalTopLevelFieldWithInitializer() → core::int?;
+static get nonNullableFinalTopLevelFieldWithInitializer() → core::int;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect
new file mode 100644
index 0000000..2bd9072
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static field core::int? _#nullableTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int? _#nullableTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelFieldWithInitializer = null;
+static field core::int? _#nullableFinalTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelField = null;
+static field core::int? _#nullableFinalTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer = null;
+static get nullableTopLevelField() → core::int?
+  return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has not been initialized.") : #t1{core::int?};
+static set nullableTopLevelField(core::int? #t2) → void
+  self::_#nullableTopLevelField = #t2;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has not been initialized.") : #t3{core::int};
+static set nonNullableTopLevelField(core::int #t4) → void
+  self::_#nonNullableTopLevelField = #t4;
+static get nullableTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
+  self::_#nullableTopLevelFieldWithInitializer = #t6;
+static get nonNullableTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+static get nullableFinalTopLevelField() → core::int?
+  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has not been initialized.") : #t9{core::int?};
+static set nullableFinalTopLevelField(core::int? #t10) → void
+  if(_in::isSentinel(self::_#nullableFinalTopLevelField))
+    self::_#nullableFinalTopLevelField = #t10;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has already been initialized.");
+static get nonNullableFinalTopLevelField() → core::int
+  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has not been initialized.") : #t11{core::int};
+static set nonNullableFinalTopLevelField(core::int #t12) → void
+  if(self::_#nonNullableFinalTopLevelField.==(null))
+    self::_#nonNullableFinalTopLevelField = #t12;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has already been initialized.");
+static get nullableFinalTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t13;
+static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t15{core::int};
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect
new file mode 100644
index 0000000..6d153d9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.strong.transformed.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static field core::int? _#nullableTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int? _#nullableTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelFieldWithInitializer = null;
+static field core::int? _#nullableFinalTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelField = null;
+static field core::int? _#nullableFinalTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer = null;
+static get nullableTopLevelField() → core::int?
+  return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has not been initialized.") : #t1{core::int?};
+static set nullableTopLevelField(core::int? #t2) → void
+  self::_#nullableTopLevelField = #t2;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has not been initialized.") : #t3{core::int};
+static set nonNullableTopLevelField(core::int #t4) → void
+  self::_#nonNullableTopLevelField = #t4;
+static get nullableTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
+  self::_#nullableTopLevelFieldWithInitializer = #t6;
+static get nonNullableTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+static get nullableFinalTopLevelField() → core::int?
+  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has not been initialized.") : #t9{core::int?};
+static set nullableFinalTopLevelField(core::int? #t10) → void
+  if(_in::isSentinel(self::_#nullableFinalTopLevelField))
+    self::_#nullableFinalTopLevelField = #t10;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has already been initialized.");
+static get nonNullableFinalTopLevelField() → core::int
+  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has not been initialized.") : #t11{core::int};
+static set nonNullableFinalTopLevelField(core::int #t12) → void
+  if(self::_#nonNullableFinalTopLevelField.==(null))
+    self::_#nonNullableFinalTopLevelField = #t12;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has already been initialized.");
+static get nullableFinalTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t13;
+static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t15{core::int};
+static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:11:17 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:12:16 -> IntConstant(0)
+Extra constant evaluation: evaluated: 98, effectively constant: 2
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect
new file mode 100644
index 0000000..34e9a83
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.textual_outline.expect
@@ -0,0 +1,19 @@
+late int;
+?
+nullableTopLevelField;
+late int ;
+nonNullableTopLevelField;
+late int;
+?
+nullableTopLevelFieldWithInitializer = null;
+late int ;
+nonNullableTopLevelFieldWithInitializer = 0;
+late ;
+final int? nullableFinalTopLevelField;
+late ;
+final int nonNullableFinalTopLevelField;
+late ;
+final int? nullableFinalTopLevelFieldWithInitializer = null;
+late ;
+final int nonNullableFinalTopLevelFieldWithInitializer = 0;
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect
new file mode 100644
index 0000000..2bd9072
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.expect
@@ -0,0 +1,48 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static field core::int? _#nullableTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int? _#nullableTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelFieldWithInitializer = null;
+static field core::int? _#nullableFinalTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelField = null;
+static field core::int? _#nullableFinalTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer = null;
+static get nullableTopLevelField() → core::int?
+  return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has not been initialized.") : #t1{core::int?};
+static set nullableTopLevelField(core::int? #t2) → void
+  self::_#nullableTopLevelField = #t2;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has not been initialized.") : #t3{core::int};
+static set nonNullableTopLevelField(core::int #t4) → void
+  self::_#nonNullableTopLevelField = #t4;
+static get nullableTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
+  self::_#nullableTopLevelFieldWithInitializer = #t6;
+static get nonNullableTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+static get nullableFinalTopLevelField() → core::int?
+  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has not been initialized.") : #t9{core::int?};
+static set nullableFinalTopLevelField(core::int? #t10) → void
+  if(_in::isSentinel(self::_#nullableFinalTopLevelField))
+    self::_#nullableFinalTopLevelField = #t10;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has already been initialized.");
+static get nonNullableFinalTopLevelField() → core::int
+  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has not been initialized.") : #t11{core::int};
+static set nonNullableFinalTopLevelField(core::int #t12) → void
+  if(self::_#nonNullableFinalTopLevelField.==(null))
+    self::_#nonNullableFinalTopLevelField = #t12;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has already been initialized.");
+static get nullableFinalTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t13;
+static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t15{core::int};
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect
new file mode 100644
index 0000000..6d153d9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_fields.dart.weak.transformed.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static field core::int? _#nullableTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelField = null;
+static field core::int? _#nullableTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableTopLevelFieldWithInitializer = null;
+static field core::int? _#nullableFinalTopLevelField = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelField = null;
+static field core::int? _#nullableFinalTopLevelFieldWithInitializer = _in::createSentinel<core::int?>();
+static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer = null;
+static get nullableTopLevelField() → core::int?
+  return let final core::int? #t1 = self::_#nullableTopLevelField in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableTopLevelField' has not been initialized.") : #t1{core::int?};
+static set nullableTopLevelField(core::int? #t2) → void
+  self::_#nullableTopLevelField = #t2;
+static get nonNullableTopLevelField() → core::int
+  return let final core::int? #t3 = self::_#nonNullableTopLevelField in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableTopLevelField' has not been initialized.") : #t3{core::int};
+static set nonNullableTopLevelField(core::int #t4) → void
+  self::_#nonNullableTopLevelField = #t4;
+static get nullableTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t5 = self::_#nullableTopLevelFieldWithInitializer in _in::isSentinel(#t5) ?{core::int?} self::_#nullableTopLevelFieldWithInitializer = null : #t5{core::int?};
+static set nullableTopLevelFieldWithInitializer(core::int? #t6) → void
+  self::_#nullableTopLevelFieldWithInitializer = #t6;
+static get nonNullableTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t7 = self::_#nonNullableTopLevelFieldWithInitializer in #t7.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer = 0 : #t7{core::int};
+static set nonNullableTopLevelFieldWithInitializer(core::int #t8) → void
+  self::_#nonNullableTopLevelFieldWithInitializer = #t8;
+static get nullableFinalTopLevelField() → core::int?
+  return let final core::int? #t9 = self::_#nullableFinalTopLevelField in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has not been initialized.") : #t9{core::int?};
+static set nullableFinalTopLevelField(core::int? #t10) → void
+  if(_in::isSentinel(self::_#nullableFinalTopLevelField))
+    self::_#nullableFinalTopLevelField = #t10;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelField' has already been initialized.");
+static get nonNullableFinalTopLevelField() → core::int
+  return let final core::int? #t11 = self::_#nonNullableFinalTopLevelField in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has not been initialized.") : #t11{core::int};
+static set nonNullableFinalTopLevelField(core::int #t12) → void
+  if(self::_#nonNullableFinalTopLevelField.==(null))
+    self::_#nonNullableFinalTopLevelField = #t12;
+  else
+    throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelField' has already been initialized.");
+static get nullableFinalTopLevelFieldWithInitializer() → core::int?
+  return let final core::int? #t13 = self::_#nullableFinalTopLevelFieldWithInitializer in _in::isSentinel(#t13) ?{core::int?} let final core::int? #t14 = null in _in::isSentinel(self::_#nullableFinalTopLevelFieldWithInitializer) ?{core::int?} self::_#nullableFinalTopLevelFieldWithInitializer = #t14 : throw new _in::LateInitializationErrorImpl::•("Field 'nullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t13;
+static get nonNullableFinalTopLevelFieldWithInitializer() → core::int
+  return let final core::int? #t15 = self::_#nonNullableFinalTopLevelFieldWithInitializer in #t15.==(null) ?{core::int} let final core::int #t16 = 0 in self::_#nonNullableFinalTopLevelFieldWithInitializer.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer = #t16 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer' has been assigned during initialization.") : #t15{core::int};
+static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:11:17 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:12:16 -> IntConstant(0)
+Extra constant evaluation: evaluated: 98, effectively constant: 2
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart
new file mode 100644
index 0000000..b0799a6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+test() {
+  late int? nullableTopLevelLocal;
+  late int nonNullableTopLevelLocal;
+  late int? nullableTopLevelLocalWithInitializer = null;
+  late int nonNullableTopLevelLocalWithInitializer = 0;
+  late final int? nullableFinalTopLevelLocal;
+  late final int nonNullableFinalTopLevelLocal;
+  late final int? nullableFinalTopLevelLocalWithInitializer = null;
+  late final int nonNullableFinalTopLevelLocalWithInitializer = 0;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.outline.expect
new file mode 100644
index 0000000..64923de
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
new file mode 100644
index 0000000..aace5e6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method test() → dynamic {
+  core::int? nullableTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocal#get() → core::int?
+    return let final core::int? #t1 = nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableTopLevelLocal' has not been initialized.") : #t1{core::int?};
+  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
+    return nullableTopLevelLocal = #t2;
+  core::int? nonNullableTopLevelLocal;
+  function #nonNullableTopLevelLocal#get() → core::int
+    return let final core::int? #t3 = nonNullableTopLevelLocal in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableTopLevelLocal' has not been initialized.") : #t3{core::int};
+  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
+    return nonNullableTopLevelLocal = #t4;
+  core::int? nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t5 = nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
+    return nullableTopLevelLocalWithInitializer = #t6;
+  core::int? nonNullableTopLevelLocalWithInitializer;
+  function #nonNullableTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t7 = nonNullableTopLevelLocalWithInitializer in #t7.==(null) ?{core::int} nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
+    return nonNullableTopLevelLocalWithInitializer = #t8;
+  final core::int? nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocal#get() → core::int?
+    return let final core::int? #t9 = nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has not been initialized.") : #t9{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    if(_in::isSentinel(nullableFinalTopLevelLocal))
+      return nullableFinalTopLevelLocal = #t10;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nonNullableFinalTopLevelLocal;
+  function #nonNullableFinalTopLevelLocal#get() → core::int
+    return let final core::int? #t11 = nonNullableFinalTopLevelLocal in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has not been initialized.") : #t11{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    if(nonNullableFinalTopLevelLocal.==(null))
+      return nonNullableFinalTopLevelLocal = #t12;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+  final core::int? nonNullableFinalTopLevelLocalWithInitializer;
+  function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
new file mode 100644
index 0000000..aace5e6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.strong.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method test() → dynamic {
+  core::int? nullableTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocal#get() → core::int?
+    return let final core::int? #t1 = nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableTopLevelLocal' has not been initialized.") : #t1{core::int?};
+  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
+    return nullableTopLevelLocal = #t2;
+  core::int? nonNullableTopLevelLocal;
+  function #nonNullableTopLevelLocal#get() → core::int
+    return let final core::int? #t3 = nonNullableTopLevelLocal in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableTopLevelLocal' has not been initialized.") : #t3{core::int};
+  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
+    return nonNullableTopLevelLocal = #t4;
+  core::int? nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t5 = nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
+    return nullableTopLevelLocalWithInitializer = #t6;
+  core::int? nonNullableTopLevelLocalWithInitializer;
+  function #nonNullableTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t7 = nonNullableTopLevelLocalWithInitializer in #t7.==(null) ?{core::int} nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
+    return nonNullableTopLevelLocalWithInitializer = #t8;
+  final core::int? nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocal#get() → core::int?
+    return let final core::int? #t9 = nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has not been initialized.") : #t9{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    if(_in::isSentinel(nullableFinalTopLevelLocal))
+      return nullableFinalTopLevelLocal = #t10;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nonNullableFinalTopLevelLocal;
+  function #nonNullableFinalTopLevelLocal#get() → core::int
+    return let final core::int? #t11 = nonNullableFinalTopLevelLocal in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has not been initialized.") : #t11{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    if(nonNullableFinalTopLevelLocal.==(null))
+      return nonNullableFinalTopLevelLocal = #t12;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+  final core::int? nonNullableFinalTopLevelLocalWithInitializer;
+  function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline.expect
new file mode 100644
index 0000000..ec6b9e0
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..f67dbb0
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
new file mode 100644
index 0000000..aace5e6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method test() → dynamic {
+  core::int? nullableTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocal#get() → core::int?
+    return let final core::int? #t1 = nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableTopLevelLocal' has not been initialized.") : #t1{core::int?};
+  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
+    return nullableTopLevelLocal = #t2;
+  core::int? nonNullableTopLevelLocal;
+  function #nonNullableTopLevelLocal#get() → core::int
+    return let final core::int? #t3 = nonNullableTopLevelLocal in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableTopLevelLocal' has not been initialized.") : #t3{core::int};
+  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
+    return nonNullableTopLevelLocal = #t4;
+  core::int? nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t5 = nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
+    return nullableTopLevelLocalWithInitializer = #t6;
+  core::int? nonNullableTopLevelLocalWithInitializer;
+  function #nonNullableTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t7 = nonNullableTopLevelLocalWithInitializer in #t7.==(null) ?{core::int} nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
+    return nonNullableTopLevelLocalWithInitializer = #t8;
+  final core::int? nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocal#get() → core::int?
+    return let final core::int? #t9 = nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has not been initialized.") : #t9{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    if(_in::isSentinel(nullableFinalTopLevelLocal))
+      return nullableFinalTopLevelLocal = #t10;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nonNullableFinalTopLevelLocal;
+  function #nonNullableFinalTopLevelLocal#get() → core::int
+    return let final core::int? #t11 = nonNullableFinalTopLevelLocal in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has not been initialized.") : #t11{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    if(nonNullableFinalTopLevelLocal.==(null))
+      return nonNullableFinalTopLevelLocal = #t12;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+  final core::int? nonNullableFinalTopLevelLocalWithInitializer;
+  function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
new file mode 100644
index 0000000..aace5e6
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering_sentinel/late_locals.dart.weak.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method test() → dynamic {
+  core::int? nullableTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocal#get() → core::int?
+    return let final core::int? #t1 = nullableTopLevelLocal in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableTopLevelLocal' has not been initialized.") : #t1{core::int?};
+  function #nullableTopLevelLocal#set(core::int? #t2) → dynamic
+    return nullableTopLevelLocal = #t2;
+  core::int? nonNullableTopLevelLocal;
+  function #nonNullableTopLevelLocal#get() → core::int
+    return let final core::int? #t3 = nonNullableTopLevelLocal in #t3.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableTopLevelLocal' has not been initialized.") : #t3{core::int};
+  function #nonNullableTopLevelLocal#set(core::int #t4) → dynamic
+    return nonNullableTopLevelLocal = #t4;
+  core::int? nullableTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t5 = nullableTopLevelLocalWithInitializer in _in::isSentinel(#t5) ?{core::int?} nullableTopLevelLocalWithInitializer = null : #t5{core::int?};
+  function #nullableTopLevelLocalWithInitializer#set(core::int? #t6) → dynamic
+    return nullableTopLevelLocalWithInitializer = #t6;
+  core::int? nonNullableTopLevelLocalWithInitializer;
+  function #nonNullableTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t7 = nonNullableTopLevelLocalWithInitializer in #t7.==(null) ?{core::int} nonNullableTopLevelLocalWithInitializer = 0 : #t7{core::int};
+  function #nonNullableTopLevelLocalWithInitializer#set(core::int #t8) → dynamic
+    return nonNullableTopLevelLocalWithInitializer = #t8;
+  final core::int? nullableFinalTopLevelLocal = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocal#get() → core::int?
+    return let final core::int? #t9 = nullableFinalTopLevelLocal in _in::isSentinel(#t9) ?{core::int?} throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has not been initialized.") : #t9{core::int?};
+  function #nullableFinalTopLevelLocal#set(core::int? #t10) → dynamic
+    if(_in::isSentinel(nullableFinalTopLevelLocal))
+      return nullableFinalTopLevelLocal = #t10;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nonNullableFinalTopLevelLocal;
+  function #nonNullableFinalTopLevelLocal#get() → core::int
+    return let final core::int? #t11 = nonNullableFinalTopLevelLocal in #t11.==(null) ?{core::int} throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has not been initialized.") : #t11{core::int};
+  function #nonNullableFinalTopLevelLocal#set(core::int #t12) → dynamic
+    if(nonNullableFinalTopLevelLocal.==(null))
+      return nonNullableFinalTopLevelLocal = #t12;
+    else
+      throw new _in::LateInitializationErrorImpl::•("Local 'nonNullableFinalTopLevelLocal' has already been initialized.");
+  final core::int? nullableFinalTopLevelLocalWithInitializer = _in::createSentinel<core::int?>();
+  function #nullableFinalTopLevelLocalWithInitializer#get() → core::int?
+    return let final core::int? #t13 = nullableFinalTopLevelLocalWithInitializer in _in::isSentinel(#t13) ?{core::int?} nullableFinalTopLevelLocalWithInitializer = null : #t13{core::int?};
+  final core::int? nonNullableFinalTopLevelLocalWithInitializer;
+  function #nonNullableFinalTopLevelLocalWithInitializer#get() → core::int
+    return let final core::int? #t14 = nonNullableFinalTopLevelLocalWithInitializer in #t14.==(null) ?{core::int} nonNullableFinalTopLevelLocalWithInitializer = 0 : #t14{core::int};
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
index dd6eff2..b2d7e74 100644
--- a/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/new_const_insertion/simple.dart.strong.transformed.expect
@@ -25,3 +25,8 @@
   new self::A::•(foo);
   new self::A::•(5.{core::num::+}(foo));
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///simple.dart:15:7 -> IntConstant(10)
+Extra constant evaluation: evaluated: 9, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart
index 3fd4ae8..b7305d8 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart
@@ -23,17 +23,17 @@
 
   abstract late int lateInstanceField;
 
-  external abstract int externalInstanceField;
+  external abstract int externalInstanceField1;
 
-  external abstract final int externalFinalInstanceField;
+  external abstract final int externalFinalInstanceField1;
 
-  external abstract covariant num externalCovariantInstanceField;
+  external abstract covariant num externalCovariantInstanceField1;
 
-  abstract external int externalInstanceField;
+  abstract external int externalInstanceField2;
 
-  abstract external final int externalFinalInstanceField;
+  abstract external final int externalFinalInstanceField2;
 
-  abstract external covariant num externalCovariantInstanceField;
+  abstract external covariant num externalCovariantInstanceField2;
 
   external abstract late int externalLateInstanceField;
 }
@@ -54,8 +54,8 @@
 extension Extension on A {
   abstract int extensionInstanceField;
   abstract final int finalExtensionInstanceField;
-  abstract static int extensionStaticField;
-  abstract static final int finalExtensionStaticField;
+  abstract static int extensionStaticField = 0;
+  abstract static final int finalExtensionStaticField = 0;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.outline.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.outline.expect
index 4ac62a9..799f3a0 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.outline.expect
@@ -34,55 +34,34 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract int externalInstanceField;
+//   external abstract int externalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract final int externalFinalInstanceField;
+//   external abstract final int externalFinalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract covariant num externalCovariantInstanceField;
+//   external abstract covariant num externalCovariantInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external int externalInstanceField;
+//   abstract external int externalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:25: Error: 'externalInstanceField' is already declared in this scope.
-//   abstract external int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:25: Context: Previous declaration of 'externalInstanceField'.
-//   external abstract int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external final int externalFinalInstanceField;
+//   abstract external final int externalFinalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:31: Error: 'externalFinalInstanceField' is already declared in this scope.
-//   abstract external final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:31: Context: Previous declaration of 'externalFinalInstanceField'.
-//   external abstract final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external covariant num externalCovariantInstanceField;
+//   abstract external covariant num externalCovariantInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:35: Error: 'externalCovariantInstanceField' is already declared in this scope.
-//   abstract external covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:35: Context: Previous declaration of 'externalCovariantInstanceField'.
-//   external abstract covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:38:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
 //   external abstract late int externalLateInstanceField;
@@ -140,22 +119,22 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:23: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //                       ^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:29: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //                             ^^^^^^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:5:14: Error: Field 'topLevelField' should be initialized because its type 'int' doesn't allow null.
@@ -188,27 +167,32 @@
   constructor •(core::int initializedField1) → self::A
     ;
   abstract get fieldWithInitializer() → core::int;
-  abstract set fieldWithInitializer(core::int #t1) → void;
+  abstract set fieldWithInitializer(core::int #externalFieldValue) → void;
   abstract get initializedField1() → core::int;
-  abstract set initializedField1(core::int #t2) → void;
+  abstract set initializedField1(core::int #externalFieldValue) → void;
   abstract get initializedField2() → core::int;
-  abstract set initializedField2(core::int #t3) → void;
-  external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t4) → void;
-  external get externalFinalInstanceField() → core::int;
-  external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t5) → void;
+  abstract set initializedField2(core::int #externalFieldValue) → void;
+  external get externalInstanceField1() → core::int;
+  external set externalInstanceField1(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField1() → core::int;
+  external get externalCovariantInstanceField1() → core::num;
+  external set externalCovariantInstanceField1(covariant core::num #externalFieldValue) → void;
+  external get externalInstanceField2() → core::int;
+  external set externalInstanceField2(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField2() → core::int;
+  external get externalCovariantInstanceField2() → core::num;
+  external set externalCovariantInstanceField2(covariant core::num #externalFieldValue) → void;
   external get externalLateInstanceField() → core::int;
-  external set externalLateInstanceField(core::int #t6) → void;
+  external set externalLateInstanceField(core::int #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticField;
   static final field core::int finalStaticField;
   external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t7) → void;
+  external set externalInstanceField(core::int #externalFieldValue) → void;
   external get externalFinalInstanceField() → core::int;
   external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t8) → void;
+  external set externalCovariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -223,7 +207,7 @@
 static field core::int Extension|extensionStaticField;
 static final field core::int Extension|finalExtensionStaticField;
 static abstract get Extension|extensionInstanceField() → core::int;
-static abstract set Extension|extensionInstanceField(core::int #t9) → void;
+static abstract set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 static abstract get Extension|finalExtensionInstanceField() → core::int;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.expect
index 8181af4..a4118b8 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.expect
@@ -34,55 +34,34 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract int externalInstanceField;
+//   external abstract int externalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract final int externalFinalInstanceField;
+//   external abstract final int externalFinalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract covariant num externalCovariantInstanceField;
+//   external abstract covariant num externalCovariantInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external int externalInstanceField;
+//   abstract external int externalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:25: Error: 'externalInstanceField' is already declared in this scope.
-//   abstract external int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:25: Context: Previous declaration of 'externalInstanceField'.
-//   external abstract int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external final int externalFinalInstanceField;
+//   abstract external final int externalFinalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:31: Error: 'externalFinalInstanceField' is already declared in this scope.
-//   abstract external final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:31: Context: Previous declaration of 'externalFinalInstanceField'.
-//   external abstract final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external covariant num externalCovariantInstanceField;
+//   abstract external covariant num externalCovariantInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:35: Error: 'externalCovariantInstanceField' is already declared in this scope.
-//   abstract external covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:35: Context: Previous declaration of 'externalCovariantInstanceField'.
-//   external abstract covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:38:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
 //   external abstract late int externalLateInstanceField;
@@ -140,22 +119,22 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:23: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //                       ^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:29: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //                             ^^^^^^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:5:14: Error: Field 'topLevelField' should be initialized because its type 'int' doesn't allow null.
@@ -220,27 +199,32 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   abstract get fieldWithInitializer() → core::int;
-  abstract set fieldWithInitializer(core::int #t3) → void;
+  abstract set fieldWithInitializer(core::int #externalFieldValue) → void;
   abstract get initializedField1() → core::int;
-  abstract set initializedField1(core::int #t4) → void;
+  abstract set initializedField1(core::int #externalFieldValue) → void;
   abstract get initializedField2() → core::int;
-  abstract set initializedField2(core::int #t5) → void;
-  external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t6) → void;
-  external get externalFinalInstanceField() → core::int;
-  external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t7) → void;
+  abstract set initializedField2(core::int #externalFieldValue) → void;
+  external get externalInstanceField1() → core::int;
+  external set externalInstanceField1(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField1() → core::int;
+  external get externalCovariantInstanceField1() → core::num;
+  external set externalCovariantInstanceField1(covariant core::num #externalFieldValue) → void;
+  external get externalInstanceField2() → core::int;
+  external set externalInstanceField2(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField2() → core::int;
+  external get externalCovariantInstanceField2() → core::num;
+  external set externalCovariantInstanceField2(covariant core::num #externalFieldValue) → void;
   external get externalLateInstanceField() → core::int;
-  external set externalLateInstanceField(core::int #t8) → void;
+  external set externalLateInstanceField(core::int #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticField = null;
   static final field core::int finalStaticField = null;
   external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t9) → void;
+  external set externalInstanceField(core::int #externalFieldValue) → void;
   external get externalFinalInstanceField() → core::int;
   external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t10) → void;
+  external set externalCovariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -252,10 +236,10 @@
 static field core::int topLevelField;
 static final field core::int finalTopLevelField = 0;
 static const field core::int constField = #C1;
-static field core::int Extension|extensionStaticField;
-static final field core::int Extension|finalExtensionStaticField;
+static field core::int Extension|extensionStaticField = 0;
+static final field core::int Extension|finalExtensionStaticField = 0;
 static abstract get Extension|extensionInstanceField() → core::int;
-static abstract set Extension|extensionInstanceField(core::int #t11) → void;
+static abstract set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 static abstract get Extension|finalExtensionInstanceField() → core::int;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.transformed.expect
index 8181af4..a4118b8 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.strong.transformed.expect
@@ -34,55 +34,34 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract int externalInstanceField;
+//   external abstract int externalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract final int externalFinalInstanceField;
+//   external abstract final int externalFinalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract covariant num externalCovariantInstanceField;
+//   external abstract covariant num externalCovariantInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external int externalInstanceField;
+//   abstract external int externalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:25: Error: 'externalInstanceField' is already declared in this scope.
-//   abstract external int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:25: Context: Previous declaration of 'externalInstanceField'.
-//   external abstract int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external final int externalFinalInstanceField;
+//   abstract external final int externalFinalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:31: Error: 'externalFinalInstanceField' is already declared in this scope.
-//   abstract external final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:31: Context: Previous declaration of 'externalFinalInstanceField'.
-//   external abstract final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external covariant num externalCovariantInstanceField;
+//   abstract external covariant num externalCovariantInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:35: Error: 'externalCovariantInstanceField' is already declared in this scope.
-//   abstract external covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:35: Context: Previous declaration of 'externalCovariantInstanceField'.
-//   external abstract covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:38:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
 //   external abstract late int externalLateInstanceField;
@@ -140,22 +119,22 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:23: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //                       ^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:29: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //                             ^^^^^^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:5:14: Error: Field 'topLevelField' should be initialized because its type 'int' doesn't allow null.
@@ -220,27 +199,32 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   abstract get fieldWithInitializer() → core::int;
-  abstract set fieldWithInitializer(core::int #t3) → void;
+  abstract set fieldWithInitializer(core::int #externalFieldValue) → void;
   abstract get initializedField1() → core::int;
-  abstract set initializedField1(core::int #t4) → void;
+  abstract set initializedField1(core::int #externalFieldValue) → void;
   abstract get initializedField2() → core::int;
-  abstract set initializedField2(core::int #t5) → void;
-  external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t6) → void;
-  external get externalFinalInstanceField() → core::int;
-  external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t7) → void;
+  abstract set initializedField2(core::int #externalFieldValue) → void;
+  external get externalInstanceField1() → core::int;
+  external set externalInstanceField1(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField1() → core::int;
+  external get externalCovariantInstanceField1() → core::num;
+  external set externalCovariantInstanceField1(covariant core::num #externalFieldValue) → void;
+  external get externalInstanceField2() → core::int;
+  external set externalInstanceField2(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField2() → core::int;
+  external get externalCovariantInstanceField2() → core::num;
+  external set externalCovariantInstanceField2(covariant core::num #externalFieldValue) → void;
   external get externalLateInstanceField() → core::int;
-  external set externalLateInstanceField(core::int #t8) → void;
+  external set externalLateInstanceField(core::int #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticField = null;
   static final field core::int finalStaticField = null;
   external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t9) → void;
+  external set externalInstanceField(core::int #externalFieldValue) → void;
   external get externalFinalInstanceField() → core::int;
   external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t10) → void;
+  external set externalCovariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -252,10 +236,10 @@
 static field core::int topLevelField;
 static final field core::int finalTopLevelField = 0;
 static const field core::int constField = #C1;
-static field core::int Extension|extensionStaticField;
-static final field core::int Extension|finalExtensionStaticField;
+static field core::int Extension|extensionStaticField = 0;
+static final field core::int Extension|finalExtensionStaticField = 0;
 static abstract get Extension|extensionInstanceField() → core::int;
-static abstract set Extension|extensionInstanceField(core::int #t11) → void;
+static abstract set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 static abstract get Extension|finalExtensionInstanceField() → core::int;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
index 8ad6f00..69a99ab 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.textual_outline.expect
@@ -10,12 +10,12 @@
   abstract static final int finalStaticField;
   abstract late int ;
   lateInstanceField;
-  external abstract int externalInstanceField;
-  external abstract final int externalFinalInstanceField;
-  external abstract covariant num externalCovariantInstanceField;
-  abstract external int externalInstanceField;
-  abstract external final int externalFinalInstanceField;
-  abstract external covariant num externalCovariantInstanceField;
+  external abstract int externalInstanceField1;
+  external abstract final int externalFinalInstanceField1;
+  external abstract covariant num externalCovariantInstanceField1;
+  abstract external int externalInstanceField2;
+  abstract external final int externalFinalInstanceField2;
+  abstract external covariant num externalCovariantInstanceField2;
   external abstract late int ;
   externalLateInstanceField;
 }
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.expect
index 8181af4..a4118b8 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.expect
@@ -34,55 +34,34 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract int externalInstanceField;
+//   external abstract int externalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract final int externalFinalInstanceField;
+//   external abstract final int externalFinalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract covariant num externalCovariantInstanceField;
+//   external abstract covariant num externalCovariantInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external int externalInstanceField;
+//   abstract external int externalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:25: Error: 'externalInstanceField' is already declared in this scope.
-//   abstract external int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:25: Context: Previous declaration of 'externalInstanceField'.
-//   external abstract int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external final int externalFinalInstanceField;
+//   abstract external final int externalFinalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:31: Error: 'externalFinalInstanceField' is already declared in this scope.
-//   abstract external final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:31: Context: Previous declaration of 'externalFinalInstanceField'.
-//   external abstract final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external covariant num externalCovariantInstanceField;
+//   abstract external covariant num externalCovariantInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:35: Error: 'externalCovariantInstanceField' is already declared in this scope.
-//   abstract external covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:35: Context: Previous declaration of 'externalCovariantInstanceField'.
-//   external abstract covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:38:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
 //   external abstract late int externalLateInstanceField;
@@ -140,22 +119,22 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:23: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //                       ^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:29: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //                             ^^^^^^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:5:14: Error: Field 'topLevelField' should be initialized because its type 'int' doesn't allow null.
@@ -220,27 +199,32 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   abstract get fieldWithInitializer() → core::int;
-  abstract set fieldWithInitializer(core::int #t3) → void;
+  abstract set fieldWithInitializer(core::int #externalFieldValue) → void;
   abstract get initializedField1() → core::int;
-  abstract set initializedField1(core::int #t4) → void;
+  abstract set initializedField1(core::int #externalFieldValue) → void;
   abstract get initializedField2() → core::int;
-  abstract set initializedField2(core::int #t5) → void;
-  external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t6) → void;
-  external get externalFinalInstanceField() → core::int;
-  external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t7) → void;
+  abstract set initializedField2(core::int #externalFieldValue) → void;
+  external get externalInstanceField1() → core::int;
+  external set externalInstanceField1(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField1() → core::int;
+  external get externalCovariantInstanceField1() → core::num;
+  external set externalCovariantInstanceField1(covariant core::num #externalFieldValue) → void;
+  external get externalInstanceField2() → core::int;
+  external set externalInstanceField2(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField2() → core::int;
+  external get externalCovariantInstanceField2() → core::num;
+  external set externalCovariantInstanceField2(covariant core::num #externalFieldValue) → void;
   external get externalLateInstanceField() → core::int;
-  external set externalLateInstanceField(core::int #t8) → void;
+  external set externalLateInstanceField(core::int #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticField = null;
   static final field core::int finalStaticField = null;
   external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t9) → void;
+  external set externalInstanceField(core::int #externalFieldValue) → void;
   external get externalFinalInstanceField() → core::int;
   external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t10) → void;
+  external set externalCovariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -252,10 +236,10 @@
 static field core::int topLevelField;
 static final field core::int finalTopLevelField = 0;
 static const field core::int constField = #C1;
-static field core::int Extension|extensionStaticField;
-static final field core::int Extension|finalExtensionStaticField;
+static field core::int Extension|extensionStaticField = 0;
+static final field core::int Extension|finalExtensionStaticField = 0;
 static abstract get Extension|extensionInstanceField() → core::int;
-static abstract set Extension|extensionInstanceField(core::int #t11) → void;
+static abstract set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 static abstract get Extension|finalExtensionInstanceField() → core::int;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.transformed.expect
index 8181af4..a4118b8 100644
--- a/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_field_errors.dart.weak.transformed.expect
@@ -34,55 +34,34 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract int externalInstanceField;
+//   external abstract int externalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract final int externalFinalInstanceField;
+//   external abstract final int externalFinalInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   external abstract covariant num externalCovariantInstanceField;
+//   external abstract covariant num externalCovariantInstanceField1;
 //            ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external int externalInstanceField;
+//   abstract external int externalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:32:25: Error: 'externalInstanceField' is already declared in this scope.
-//   abstract external int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:26:25: Context: Previous declaration of 'externalInstanceField'.
-//   external abstract int externalInstanceField;
-//                         ^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external final int externalFinalInstanceField;
+//   abstract external final int externalFinalInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:34:31: Error: 'externalFinalInstanceField' is already declared in this scope.
-//   abstract external final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:28:31: Context: Previous declaration of 'externalFinalInstanceField'.
-//   external abstract final int externalFinalInstanceField;
-//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:3: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
-//   abstract external covariant num externalCovariantInstanceField;
+//   abstract external covariant num externalCovariantInstanceField2;
 //   ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:36:35: Error: 'externalCovariantInstanceField' is already declared in this scope.
-//   abstract external covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-// pkg/front_end/testcases/nnbd/abstract_field_errors.dart:30:35: Context: Previous declaration of 'externalCovariantInstanceField'.
-//   external abstract covariant num externalCovariantInstanceField;
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-//
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:38:12: Error: Fields can't be declared both 'abstract' and 'external'.
 // Try removing the 'abstract' or 'external' keyword.
 //   external abstract late int externalLateInstanceField;
@@ -140,22 +119,22 @@
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:23: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //                       ^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:57:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static int extensionStaticField;
+//   abstract static int extensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:29: Error: Extension fields can't be declared 'abstract'.
 // Try removing the 'abstract' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //                             ^^^^^^^^^^^^^^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:58:3: Error: Static fields can't be declared 'abstract'.
 // Try removing the 'abstract' or 'static' keyword.
-//   abstract static final int finalExtensionStaticField;
+//   abstract static final int finalExtensionStaticField = 0;
 //   ^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd/abstract_field_errors.dart:5:14: Error: Field 'topLevelField' should be initialized because its type 'int' doesn't allow null.
@@ -220,27 +199,32 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   abstract get fieldWithInitializer() → core::int;
-  abstract set fieldWithInitializer(core::int #t3) → void;
+  abstract set fieldWithInitializer(core::int #externalFieldValue) → void;
   abstract get initializedField1() → core::int;
-  abstract set initializedField1(core::int #t4) → void;
+  abstract set initializedField1(core::int #externalFieldValue) → void;
   abstract get initializedField2() → core::int;
-  abstract set initializedField2(core::int #t5) → void;
-  external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t6) → void;
-  external get externalFinalInstanceField() → core::int;
-  external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t7) → void;
+  abstract set initializedField2(core::int #externalFieldValue) → void;
+  external get externalInstanceField1() → core::int;
+  external set externalInstanceField1(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField1() → core::int;
+  external get externalCovariantInstanceField1() → core::num;
+  external set externalCovariantInstanceField1(covariant core::num #externalFieldValue) → void;
+  external get externalInstanceField2() → core::int;
+  external set externalInstanceField2(core::int #externalFieldValue) → void;
+  external get externalFinalInstanceField2() → core::int;
+  external get externalCovariantInstanceField2() → core::num;
+  external set externalCovariantInstanceField2(covariant core::num #externalFieldValue) → void;
   external get externalLateInstanceField() → core::int;
-  external set externalLateInstanceField(core::int #t8) → void;
+  external set externalLateInstanceField(core::int #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   static field core::int staticField = null;
   static final field core::int finalStaticField = null;
   external get externalInstanceField() → core::int;
-  external set externalInstanceField(core::int #t9) → void;
+  external set externalInstanceField(core::int #externalFieldValue) → void;
   external get externalFinalInstanceField() → core::int;
   external get externalCovariantInstanceField() → core::num;
-  external set externalCovariantInstanceField(covariant core::num #t10) → void;
+  external set externalCovariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -252,10 +236,10 @@
 static field core::int topLevelField;
 static final field core::int finalTopLevelField = 0;
 static const field core::int constField = #C1;
-static field core::int Extension|extensionStaticField;
-static final field core::int Extension|finalExtensionStaticField;
+static field core::int Extension|extensionStaticField = 0;
+static final field core::int Extension|finalExtensionStaticField = 0;
 static abstract get Extension|extensionInstanceField() → core::int;
-static abstract set Extension|extensionInstanceField(core::int #t11) → void;
+static abstract set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 static abstract get Extension|finalExtensionInstanceField() → core::int;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields.dart.outline.expect b/pkg/front_end/testcases/nnbd/abstract_fields.dart.outline.expect
index e13a36a..ff6c1e2 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields.dart.outline.expect
@@ -6,17 +6,17 @@
   synthetic constructor •() → self::A
     ;
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t1) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t2) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t3) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t4) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.expect b/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.expect
index d5823fb..3e5529f 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t1) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t2) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t3) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t4) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.transformed.expect
index d5823fb..3e5529f 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields.dart.strong.transformed.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t1) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t2) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t3) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t4) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.expect b/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.expect
index d5823fb..3e5529f 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t1) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t2) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t3) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t4) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.transformed.expect
index d5823fb..3e5529f 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields.dart.weak.transformed.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t1) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t2) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   abstract get instanceField() → core::int;
-  abstract set instanceField(core::int #t3) → void;
+  abstract set instanceField(core::int #externalFieldValue) → void;
   abstract get finalInstanceField() → core::int;
   abstract get covariantInstanceField() → core::num;
-  abstract set covariantInstanceField(covariant core::num #t4) → void;
+  abstract set covariantInstanceField(covariant core::num #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.outline.expect b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.outline.expect
index 492b9a7..21e1617 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.outline.expect
@@ -6,17 +6,17 @@
   synthetic constructor •() → self::A
     ;
   abstract get i1() → core::int;
-  abstract set i1(core::int #t1) → void;
+  abstract set i1(core::int #externalFieldValue) → void;
   abstract get i2() → core::int;
-  abstract set i2(core::int #t2) → void;
+  abstract set i2(core::int #externalFieldValue) → void;
   abstract get x() → dynamic;
-  abstract set x(dynamic #t3) → void;
+  abstract set x(dynamic #externalFieldValue) → void;
   abstract get fi() → core::int;
   abstract get fx() → dynamic;
   abstract get cn() → core::num;
-  abstract set cn(covariant core::num #t4) → void;
+  abstract set cn(covariant core::num #externalFieldValue) → void;
   abstract get cx() → dynamic;
-  abstract set cx(covariant dynamic #t5) → void;
+  abstract set cx(covariant dynamic #externalFieldValue) → void;
 }
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.expect b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.expect
index 345a7f1..c91e11c 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get i1() → core::int;
-  abstract set i1(core::int #t1) → void;
+  abstract set i1(core::int #externalFieldValue) → void;
   abstract get i2() → core::int;
-  abstract set i2(core::int #t2) → void;
+  abstract set i2(core::int #externalFieldValue) → void;
   abstract get x() → dynamic;
-  abstract set x(dynamic #t3) → void;
+  abstract set x(dynamic #externalFieldValue) → void;
   abstract get fi() → core::int;
   abstract get fx() → dynamic;
   abstract get cn() → core::num;
-  abstract set cn(covariant core::num #t4) → void;
+  abstract set cn(covariant core::num #externalFieldValue) → void;
   abstract get cx() → dynamic;
-  abstract set cx(covariant dynamic #t5) → void;
+  abstract set cx(covariant dynamic #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.transformed.expect
index 345a7f1..c91e11c 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.strong.transformed.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get i1() → core::int;
-  abstract set i1(core::int #t1) → void;
+  abstract set i1(core::int #externalFieldValue) → void;
   abstract get i2() → core::int;
-  abstract set i2(core::int #t2) → void;
+  abstract set i2(core::int #externalFieldValue) → void;
   abstract get x() → dynamic;
-  abstract set x(dynamic #t3) → void;
+  abstract set x(dynamic #externalFieldValue) → void;
   abstract get fi() → core::int;
   abstract get fx() → dynamic;
   abstract get cn() → core::num;
-  abstract set cn(covariant core::num #t4) → void;
+  abstract set cn(covariant core::num #externalFieldValue) → void;
   abstract get cx() → dynamic;
-  abstract set cx(covariant dynamic #t5) → void;
+  abstract set cx(covariant dynamic #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.expect b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.expect
index 345a7f1..c91e11c 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get i1() → core::int;
-  abstract set i1(core::int #t1) → void;
+  abstract set i1(core::int #externalFieldValue) → void;
   abstract get i2() → core::int;
-  abstract set i2(core::int #t2) → void;
+  abstract set i2(core::int #externalFieldValue) → void;
   abstract get x() → dynamic;
-  abstract set x(dynamic #t3) → void;
+  abstract set x(dynamic #externalFieldValue) → void;
   abstract get fi() → core::int;
   abstract get fx() → dynamic;
   abstract get cn() → core::num;
-  abstract set cn(covariant core::num #t4) → void;
+  abstract set cn(covariant core::num #externalFieldValue) → void;
   abstract get cx() → dynamic;
-  abstract set cx(covariant dynamic #t5) → void;
+  abstract set cx(covariant dynamic #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.transformed.expect
index 345a7f1..c91e11c 100644
--- a/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/abstract_fields_spec.dart.weak.transformed.expect
@@ -7,16 +7,16 @@
     : super core::Object::•()
     ;
   abstract get i1() → core::int;
-  abstract set i1(core::int #t1) → void;
+  abstract set i1(core::int #externalFieldValue) → void;
   abstract get i2() → core::int;
-  abstract set i2(core::int #t2) → void;
+  abstract set i2(core::int #externalFieldValue) → void;
   abstract get x() → dynamic;
-  abstract set x(dynamic #t3) → void;
+  abstract set x(dynamic #externalFieldValue) → void;
   abstract get fi() → core::int;
   abstract get fx() → dynamic;
   abstract get cn() → core::num;
-  abstract set cn(covariant core::num #t4) → void;
+  abstract set cn(covariant core::num #externalFieldValue) → void;
   abstract get cx() → dynamic;
-  abstract set cx(covariant dynamic #t5) → void;
+  abstract set cx(covariant dynamic #externalFieldValue) → void;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart
new file mode 100644
index 0000000..6a834f6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'ambiguous_main_export_lib0.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.outline.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.outline.expect
new file mode 100644
index 0000000..bed220f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.outline.expect
@@ -0,0 +1,34 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///ambiguous_main_export_lib0.dart";
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart:6:1: Error: 'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.
+// export 'ambiguous_main_export_lib2.dart';
+// ^
+//
+import self as self2;
+
+export "org-dartlang-testcase:///ambiguous_main_export_lib1.dart";
+export "org-dartlang-testcase:///ambiguous_main_export_lib2.dart";
+
+static const field dynamic _exports# = "{\"main\":\"'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.\"}" /*isNullableByDefault, from null */;
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.expect
new file mode 100644
index 0000000..8a5ab57
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///ambiguous_main_export_lib0.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart:6:1: Error: 'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.
+// export 'ambiguous_main_export_lib2.dart';
+// ^
+//
+import self as self2;
+import "dart:core" as core;
+
+export "org-dartlang-testcase:///ambiguous_main_export_lib1.dart";
+export "org-dartlang-testcase:///ambiguous_main_export_lib2.dart";
+
+static const field dynamic _exports# = #C1 /*isNullableByDefault, from null */;
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(42);
+}
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(87);
+}
+
+constants  {
+  #C1 = "{\"main\":\"'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.\"}"
+}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.transformed.expect
new file mode 100644
index 0000000..8a5ab57
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///ambiguous_main_export_lib0.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart:6:1: Error: 'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.
+// export 'ambiguous_main_export_lib2.dart';
+// ^
+//
+import self as self2;
+import "dart:core" as core;
+
+export "org-dartlang-testcase:///ambiguous_main_export_lib1.dart";
+export "org-dartlang-testcase:///ambiguous_main_export_lib2.dart";
+
+static const field dynamic _exports# = #C1 /*isNullableByDefault, from null */;
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(42);
+}
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(87);
+}
+
+constants  {
+  #C1 = "{\"main\":\"'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.\"}"
+}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline.expect
new file mode 100644
index 0000000..1e66c5b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline.expect
@@ -0,0 +1,3 @@
+import 'ambiguous_main_export_lib0.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..1e66c5b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.textual_outline_modelled.expect
@@ -0,0 +1,3 @@
+import 'ambiguous_main_export_lib0.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.expect
new file mode 100644
index 0000000..8a5ab57
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///ambiguous_main_export_lib0.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart:6:1: Error: 'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.
+// export 'ambiguous_main_export_lib2.dart';
+// ^
+//
+import self as self2;
+import "dart:core" as core;
+
+export "org-dartlang-testcase:///ambiguous_main_export_lib1.dart";
+export "org-dartlang-testcase:///ambiguous_main_export_lib2.dart";
+
+static const field dynamic _exports# = #C1 /*isNullableByDefault, from null */;
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(42);
+}
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(87);
+}
+
+constants  {
+  #C1 = "{\"main\":\"'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.\"}"
+}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.transformed.expect
new file mode 100644
index 0000000..8a5ab57
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export.dart.weak.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///ambiguous_main_export_lib0.dart";
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart:6:1: Error: 'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.
+// export 'ambiguous_main_export_lib2.dart';
+// ^
+//
+import self as self2;
+import "dart:core" as core;
+
+export "org-dartlang-testcase:///ambiguous_main_export_lib1.dart";
+export "org-dartlang-testcase:///ambiguous_main_export_lib2.dart";
+
+static const field dynamic _exports# = #C1 /*isNullableByDefault, from null */;
+
+library /*isNonNullableByDefault*/;
+import self as self3;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(42);
+}
+
+library /*isNonNullableByDefault*/;
+import self as self4;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print(87);
+}
+
+constants  {
+  #C1 = "{\"main\":\"'main' is exported from both 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart' and 'pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart'.\"}"
+}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart
new file mode 100644
index 0000000..f52c596
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib0.dart
@@ -0,0 +1,6 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'ambiguous_main_export_lib1.dart';
+export 'ambiguous_main_export_lib2.dart';
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart
new file mode 100644
index 0000000..50dfbde
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  print(42);
+}
diff --git a/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart
new file mode 100644
index 0000000..2c38c67
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/ambiguous_main_export_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  print(87);
+}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart b/pkg/front_end/testcases/nnbd/const_is.dart
new file mode 100644
index 0000000..ccafc28
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart
@@ -0,0 +1,181 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests derived from co19/Language/Types/Function_Types/subtype_named_args_t04
+// and language/nnbd/subtyping/function_type_required_params_test
+
+bool inStrongMode = <int?>[] is! List<int>;
+
+int f({required int i}) {
+  return i + 1;
+}
+
+int g({int i = 1}) {
+  return i + 1;
+}
+
+typedef int fType({required int i});
+typedef int gType({int i});
+typedef int bigType(
+    {required int i1,
+    required int i2,
+    required int i3,
+    required int i4,
+    required int i5,
+    required int i6,
+    required int i7,
+    required int i8,
+    required int i9,
+    required int i10,
+    required int i11,
+    required int i12,
+    required int i13,
+    required int i14,
+    required int i15,
+    required int i16,
+    required int i17,
+    required int i18,
+    required int i19,
+    required int i20,
+    required int i21,
+    required int i22,
+    required int i23,
+    required int i24,
+    required int i25,
+    required int i26,
+    required int i27,
+    required int i28,
+    required int i29,
+    required int i30,
+    required int i31,
+    required int i32,
+    required int i33,
+    required int i34,
+    required int i35,
+    required int i36,
+    required int i37,
+    required int i38,
+    required int i39,
+    required int i40,
+    required int i41,
+    required int i42,
+    required int i43,
+    required int i44,
+    required int i45,
+    required int i46,
+    required int i47,
+    required int i48,
+    required int i49,
+    required int i50,
+    required int i51,
+    required int i52,
+    required int i53,
+    required int i54,
+    required int i55,
+    required int i56,
+    required int i57,
+    required int i58,
+    required int i59,
+    required int i60,
+    required int i61,
+    required int i62,
+    required int i63,
+    required int i64,
+    required int i65,
+    required int i66,
+    required int i67,
+    required int i68,
+    required int i69,
+    required int i70});
+
+class A {}
+
+class A1 {}
+
+class A2 {}
+
+class B implements A, A1, A2 {}
+
+class C implements B {}
+
+class D implements C {}
+
+typedef B func(Object o);
+typedef B t1(int i, B b, Map<int, num> m, var x,
+    {required var ox,
+    required B ob,
+    required List<num> ol,
+    required bool obool});
+
+B f1(int i, B b, Map<int, num> m, var x,
+        {required extraParam,
+        required bool obool,
+        required var ox,
+        required D ob,
+        required List<num>? ol}) =>
+    new B();
+D f2(int i, D b, Map<int, int> m, func x,
+        {required func ox,
+        required D ob,
+        required List<int> ol,
+        required bool obool}) =>
+    new D();
+C f3(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required extraParam,
+        required A2 ob,
+        required List ol,
+        required Object obool}) =>
+    new C();
+C f4(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required A2 ob,
+        required List ol,
+        required bool obool,
+        required A xx,
+        required B yy}) =>
+    new C();
+C f5(int i, A b, Map<Object, Object> m, var x,
+        {required ox, required B ob, required List ol, required obool}) =>
+    new C();
+
+const f_is_fType = f is fType;
+const f_is_gType = f is gType;
+const g_is_fType = g is fType;
+const g_is_gType = g is gType;
+const f_is_bigType = f is bigType;
+
+const f1_is_t1 = f1 is t1;
+const f2_is_t1 = f2 is t1;
+const f3_is_t1 = f3 is t1;
+const f4_is_t1 = f4 is t1;
+const f5_is_t1 = f5 is t1;
+
+main() {
+  expect(true, f_is_fType);
+  expect(f is fType, f_is_fType);
+  expect(!inStrongMode, f_is_gType);
+  expect(f is gType, f_is_gType);
+  expect(true, g_is_fType);
+  expect(g is fType, g_is_fType);
+  expect(true, g_is_gType);
+  expect(g is gType, g_is_gType);
+  expect(false, f_is_bigType);
+  expect(f is bigType, f_is_bigType);
+
+  expect(false, f1_is_t1);
+  expect(f1 is t1, f1_is_t1);
+  expect(false, f2_is_t1);
+  expect(f2 is t1, f2_is_t1);
+  expect(!inStrongMode, f3_is_t1);
+  expect(f3 is t1, f3_is_t1);
+  expect(!inStrongMode, f4_is_t1);
+  expect(f4 is t1, f4_is_t1);
+  expect(true, f5_is_t1);
+  expect(f5 is t1, f5_is_t1);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw "Expected $expected, actual $actual";
+}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.outline.expect b/pkg/front_end/testcases/nnbd/const_is.dart.outline.expect
new file mode 100644
index 0000000..46bacdc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.outline.expect
@@ -0,0 +1,76 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef fType = ({required i: core::int}) → core::int;
+typedef gType = ({i: core::int}) → core::int;
+typedef bigType = ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+typedef func = (core::Object) → self::B;
+typedef t1 = (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    ;
+}
+class A2 extends core::Object {
+  synthetic constructor •() → self::A2
+    ;
+}
+class B extends core::Object implements self::A, self::A1, self::A2 {
+  synthetic constructor •() → self::B
+    ;
+}
+class C extends core::Object implements self::B {
+  synthetic constructor •() → self::C
+    ;
+}
+class D extends core::Object implements self::C {
+  synthetic constructor •() → self::D
+    ;
+}
+static field core::bool inStrongMode;
+static const field core::bool f_is_fType = self::f is{ForNonNullableByDefault} ({required i: core::int}) → core::int;
+static const field core::bool f_is_gType = self::f is{ForNonNullableByDefault} ({i: core::int}) → core::int;
+static const field core::bool g_is_fType = self::g is{ForNonNullableByDefault} ({required i: core::int}) → core::int;
+static const field core::bool g_is_gType = self::g is{ForNonNullableByDefault} ({i: core::int}) → core::int;
+static const field core::bool f_is_bigType = self::f is{ForNonNullableByDefault} ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+static const field core::bool f1_is_t1 = self::f1 is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+static const field core::bool f2_is_t1 = self::f2 is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+static const field core::bool f3_is_t1 = self::f3 is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+static const field core::bool f4_is_t1 = self::f4 is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+static const field core::bool f5_is_t1 = self::f5 is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+static method f({required core::int i}) → core::int
+  ;
+static method g({core::int i}) → core::int
+  ;
+static method f1(core::int i, self::B b, core::Map<core::int, core::num> m, dynamic x, {required dynamic extraParam, required core::bool obool, required dynamic ox, required self::D ob, required core::List<core::num>? ol}) → self::B
+  ;
+static method f2(core::int i, self::D b, core::Map<core::int, core::int> m, (core::Object) → self::B x, {required (core::Object) → self::B ox, required self::D ob, required core::List<core::int> ol, required core::bool obool}) → self::D
+  ;
+static method f3(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox, required dynamic extraParam, required self::A2 ob, required core::List<dynamic> ol, required core::Object obool}) → self::C
+  ;
+static method f4(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox, required self::A2 ob, required core::List<dynamic> ol, required core::bool obool, required self::A xx, required self::B yy}) → self::C
+  ;
+static method f5(core::int i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox, required self::B ob, required core::List<dynamic> ol, required dynamic obool}) → self::C
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:143:22 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:144:22 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:145:22 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:146:22 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:147:24 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:149:21 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:150:21 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:151:21 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:152:21 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:153:21 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 10, effectively constant: 10
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
new file mode 100644
index 0000000..ecdde5d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef fType = ({required i: core::int}) → core::int;
+typedef gType = ({i: core::int}) → core::int;
+typedef bigType = ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+typedef func = (core::Object) → self::B;
+typedef t1 = (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+}
+class A2 extends core::Object {
+  synthetic constructor •() → self::A2
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A, self::A1, self::A2 {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::B {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object implements self::C {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field core::bool f_is_fType = #C1;
+static const field core::bool f_is_gType = #C2;
+static const field core::bool g_is_fType = #C1;
+static const field core::bool g_is_gType = #C1;
+static const field core::bool f_is_bigType = #C2;
+static const field core::bool f1_is_t1 = #C2;
+static const field core::bool f2_is_t1 = #C2;
+static const field core::bool f3_is_t1 = #C2;
+static const field core::bool f4_is_t1 = #C2;
+static const field core::bool f5_is_t1 = #C1;
+static method f({required core::int i = #C3}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method g({core::int i = #C4}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method f1(core::int i, self::B b, core::Map<core::int, core::num> m, dynamic x, {required dynamic extraParam = #C3, required core::bool obool = #C3, required dynamic ox = #C3, required self::D ob = #C3, required core::List<core::num>? ol = #C3}) → self::B
+  return new self::B::•();
+static method f2(core::int i, self::D b, core::Map<core::int, core::int> m, (core::Object) → self::B x, {required (core::Object) → self::B ox = #C3, required self::D ob = #C3, required core::List<core::int> ol = #C3, required core::bool obool = #C3}) → self::D
+  return new self::D::•();
+static method f3(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required dynamic extraParam = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::Object obool = #C3}) → self::C
+  return new self::C::•();
+static method f4(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::bool obool = #C3, required self::A xx = #C3, required self::B yy = #C3}) → self::C
+  return new self::C::•();
+static method f5(core::int i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::B ob = #C3, required core::List<dynamic> ol = #C3, required dynamic obool = #C3}) → self::C
+  return new self::C::•();
+static method main() → dynamic {
+  self::expect(true, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C2);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(false, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int, #C2);
+  self::expect(false, #C2);
+  self::expect((#C7) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(false, #C2);
+  self::expect((#C8) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C9) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C10) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(true, #C1);
+  self::expect((#C11) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+  #C3 = null
+  #C4 = 1
+  #C5 = tearoff self::f
+  #C6 = tearoff self::g
+  #C7 = tearoff self::f1
+  #C8 = tearoff self::f2
+  #C9 = tearoff self::f3
+  #C10 = tearoff self::f4
+  #C11 = tearoff self::f5
+}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
new file mode 100644
index 0000000..1ba909d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.strong.transformed.expect
@@ -0,0 +1,119 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef fType = ({required i: core::int}) → core::int;
+typedef gType = ({i: core::int}) → core::int;
+typedef bigType = ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+typedef func = (core::Object) → self::B;
+typedef t1 = (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+}
+class A2 extends core::Object {
+  synthetic constructor •() → self::A2
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A, self::A1, self::A2 {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::B {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object implements self::C {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field core::bool f_is_fType = #C1;
+static const field core::bool f_is_gType = #C2;
+static const field core::bool g_is_fType = #C1;
+static const field core::bool g_is_gType = #C1;
+static const field core::bool f_is_bigType = #C2;
+static const field core::bool f1_is_t1 = #C2;
+static const field core::bool f2_is_t1 = #C2;
+static const field core::bool f3_is_t1 = #C2;
+static const field core::bool f4_is_t1 = #C2;
+static const field core::bool f5_is_t1 = #C1;
+static method f({required core::int i = #C3}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method g({core::int i = #C4}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method f1(core::int i, self::B b, core::Map<core::int, core::num> m, dynamic x, {required dynamic extraParam = #C3, required core::bool obool = #C3, required dynamic ox = #C3, required self::D ob = #C3, required core::List<core::num>? ol = #C3}) → self::B
+  return new self::B::•();
+static method f2(core::int i, self::D b, core::Map<core::int, core::int> m, (core::Object) → self::B x, {required (core::Object) → self::B ox = #C3, required self::D ob = #C3, required core::List<core::int> ol = #C3, required core::bool obool = #C3}) → self::D
+  return new self::D::•();
+static method f3(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required dynamic extraParam = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::Object obool = #C3}) → self::C
+  return new self::C::•();
+static method f4(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::bool obool = #C3, required self::A xx = #C3, required self::B yy = #C3}) → self::C
+  return new self::C::•();
+static method f5(core::int i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::B ob = #C3, required core::List<dynamic> ol = #C3, required dynamic obool = #C3}) → self::C
+  return new self::C::•();
+static method main() → dynamic {
+  self::expect(true, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C2);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(false, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int, #C2);
+  self::expect(false, #C2);
+  self::expect((#C7) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(false, #C2);
+  self::expect((#C8) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C9) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C2);
+  self::expect((#C10) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(true, #C1);
+  self::expect((#C11) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+  #C3 = null
+  #C4 = 1
+  #C5 = tearoff self::f
+  #C6 = tearoff self::g
+  #C7 = tearoff self::f1
+  #C8 = tearoff self::f2
+  #C9 = tearoff self::f3
+  #C10 = tearoff self::f4
+  #C11 = tearoff self::f5
+}
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:157:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:159:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:161:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:163:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:165:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:168:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:170:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:172:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:174:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:176:13 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 56, effectively constant: 10
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline.expect
new file mode 100644
index 0000000..48d1d0a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline.expect
@@ -0,0 +1,138 @@
+bool inStrongMode = <int?>[] is! List<int>;
+int f({required int i}) {}
+int g({int i = 1}) {}
+typedef int fType({required int i});
+typedef int gType({int i});
+typedef int bigType(
+    {required int i1,
+    required int i2,
+    required int i3,
+    required int i4,
+    required int i5,
+    required int i6,
+    required int i7,
+    required int i8,
+    required int i9,
+    required int i10,
+    required int i11,
+    required int i12,
+    required int i13,
+    required int i14,
+    required int i15,
+    required int i16,
+    required int i17,
+    required int i18,
+    required int i19,
+    required int i20,
+    required int i21,
+    required int i22,
+    required int i23,
+    required int i24,
+    required int i25,
+    required int i26,
+    required int i27,
+    required int i28,
+    required int i29,
+    required int i30,
+    required int i31,
+    required int i32,
+    required int i33,
+    required int i34,
+    required int i35,
+    required int i36,
+    required int i37,
+    required int i38,
+    required int i39,
+    required int i40,
+    required int i41,
+    required int i42,
+    required int i43,
+    required int i44,
+    required int i45,
+    required int i46,
+    required int i47,
+    required int i48,
+    required int i49,
+    required int i50,
+    required int i51,
+    required int i52,
+    required int i53,
+    required int i54,
+    required int i55,
+    required int i56,
+    required int i57,
+    required int i58,
+    required int i59,
+    required int i60,
+    required int i61,
+    required int i62,
+    required int i63,
+    required int i64,
+    required int i65,
+    required int i66,
+    required int i67,
+    required int i68,
+    required int i69,
+    required int i70});
+
+class A {}
+
+class A1 {}
+
+class A2 {}
+
+class B implements A, A1, A2 {}
+
+class C implements B {}
+
+class D implements C {}
+
+typedef B func(Object o);
+typedef B t1(int i, B b, Map<int, num> m, var x,
+    {required var ox,
+    required B ob,
+    required List<num> ol,
+    required bool obool});
+B f1(int i, B b, Map<int, num> m, var x,
+        {required extraParam,
+        required bool obool,
+        required var ox,
+        required D ob,
+        required List<num>? ol}) =>
+    new B();
+D f2(int i, D b, Map<int, int> m, func x,
+        {required func ox,
+        required D ob,
+        required List<int> ol,
+        required bool obool}) =>
+    new D();
+C f3(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required extraParam,
+        required A2 ob,
+        required List ol,
+        required Object obool}) =>
+    new C();
+C f4(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required A2 ob,
+        required List ol,
+        required bool obool,
+        required A xx,
+        required B yy}) =>
+    new C();
+C f5(int i, A b, Map<Object, Object> m, var x,
+        {required ox, required B ob, required List ol, required obool}) =>
+    new C();
+const f_is_fType = f is fType;
+const f_is_gType = f is gType;
+const g_is_fType = g is fType;
+const g_is_gType = g is gType;
+const f_is_bigType = f is bigType;
+const f1_is_t1 = f1 is t1;
+const f2_is_t1 = f2 is t1;
+const f3_is_t1 = f3 is t1;
+const f4_is_t1 = f4 is t1;
+const f5_is_t1 = f5 is t1;
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5e166ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.textual_outline_modelled.expect
@@ -0,0 +1,138 @@
+B f1(int i, B b, Map<int, num> m, var x,
+        {required extraParam,
+        required bool obool,
+        required var ox,
+        required D ob,
+        required List<num>? ol}) =>
+    new B();
+C f3(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required extraParam,
+        required A2 ob,
+        required List ol,
+        required Object obool}) =>
+    new C();
+C f4(num i, A b, Map<Object, Object> m, var x,
+        {required var ox,
+        required A2 ob,
+        required List ol,
+        required bool obool,
+        required A xx,
+        required B yy}) =>
+    new C();
+C f5(int i, A b, Map<Object, Object> m, var x,
+        {required ox, required B ob, required List ol, required obool}) =>
+    new C();
+D f2(int i, D b, Map<int, int> m, func x,
+        {required func ox,
+        required D ob,
+        required List<int> ol,
+        required bool obool}) =>
+    new D();
+bool inStrongMode = <int?>[] is! List<int>;
+
+class A {}
+
+class A1 {}
+
+class A2 {}
+
+class B implements A, A1, A2 {}
+
+class C implements B {}
+
+class D implements C {}
+
+const f1_is_t1 = f1 is t1;
+const f2_is_t1 = f2 is t1;
+const f3_is_t1 = f3 is t1;
+const f4_is_t1 = f4 is t1;
+const f5_is_t1 = f5 is t1;
+const f_is_bigType = f is bigType;
+const f_is_fType = f is fType;
+const f_is_gType = f is gType;
+const g_is_fType = g is fType;
+const g_is_gType = g is gType;
+expect(expected, actual) {}
+int f({required int i}) {}
+int g({int i = 1}) {}
+main() {}
+typedef B func(Object o);
+typedef B t1(int i, B b, Map<int, num> m, var x,
+    {required var ox,
+    required B ob,
+    required List<num> ol,
+    required bool obool});
+typedef int bigType(
+    {required int i1,
+    required int i2,
+    required int i3,
+    required int i4,
+    required int i5,
+    required int i6,
+    required int i7,
+    required int i8,
+    required int i9,
+    required int i10,
+    required int i11,
+    required int i12,
+    required int i13,
+    required int i14,
+    required int i15,
+    required int i16,
+    required int i17,
+    required int i18,
+    required int i19,
+    required int i20,
+    required int i21,
+    required int i22,
+    required int i23,
+    required int i24,
+    required int i25,
+    required int i26,
+    required int i27,
+    required int i28,
+    required int i29,
+    required int i30,
+    required int i31,
+    required int i32,
+    required int i33,
+    required int i34,
+    required int i35,
+    required int i36,
+    required int i37,
+    required int i38,
+    required int i39,
+    required int i40,
+    required int i41,
+    required int i42,
+    required int i43,
+    required int i44,
+    required int i45,
+    required int i46,
+    required int i47,
+    required int i48,
+    required int i49,
+    required int i50,
+    required int i51,
+    required int i52,
+    required int i53,
+    required int i54,
+    required int i55,
+    required int i56,
+    required int i57,
+    required int i58,
+    required int i59,
+    required int i60,
+    required int i61,
+    required int i62,
+    required int i63,
+    required int i64,
+    required int i65,
+    required int i66,
+    required int i67,
+    required int i68,
+    required int i69,
+    required int i70});
+typedef int fType({required int i});
+typedef int gType({int i});
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
new file mode 100644
index 0000000..f6c3bba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.expect
@@ -0,0 +1,106 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef fType = ({required i: core::int}) → core::int;
+typedef gType = ({i: core::int}) → core::int;
+typedef bigType = ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+typedef func = (core::Object) → self::B;
+typedef t1 = (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+}
+class A2 extends core::Object {
+  synthetic constructor •() → self::A2
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A, self::A1, self::A2 {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::B {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object implements self::C {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field core::bool f_is_fType = #C1;
+static const field core::bool f_is_gType = #C1;
+static const field core::bool g_is_fType = #C1;
+static const field core::bool g_is_gType = #C1;
+static const field core::bool f_is_bigType = #C2;
+static const field core::bool f1_is_t1 = #C2;
+static const field core::bool f2_is_t1 = #C2;
+static const field core::bool f3_is_t1 = #C1;
+static const field core::bool f4_is_t1 = #C1;
+static const field core::bool f5_is_t1 = #C1;
+static method f({required core::int i = #C3}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method g({core::int i = #C4}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method f1(core::int i, self::B b, core::Map<core::int, core::num> m, dynamic x, {required dynamic extraParam = #C3, required core::bool obool = #C3, required dynamic ox = #C3, required self::D ob = #C3, required core::List<core::num>? ol = #C3}) → self::B
+  return new self::B::•();
+static method f2(core::int i, self::D b, core::Map<core::int, core::int> m, (core::Object) → self::B x, {required (core::Object) → self::B ox = #C3, required self::D ob = #C3, required core::List<core::int> ol = #C3, required core::bool obool = #C3}) → self::D
+  return new self::D::•();
+static method f3(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required dynamic extraParam = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::Object obool = #C3}) → self::C
+  return new self::C::•();
+static method f4(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::bool obool = #C3, required self::A xx = #C3, required self::B yy = #C3}) → self::C
+  return new self::C::•();
+static method f5(core::int i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::B ob = #C3, required core::List<dynamic> ol = #C3, required dynamic obool = #C3}) → self::C
+  return new self::C::•();
+static method main() → dynamic {
+  self::expect(true, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(false, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int, #C2);
+  self::expect(false, #C2);
+  self::expect((#C7) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(false, #C2);
+  self::expect((#C8) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C9) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C10) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+  self::expect(true, #C1);
+  self::expect((#C11) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+  #C3 = null
+  #C4 = 1
+  #C5 = tearoff self::f
+  #C6 = tearoff self::g
+  #C7 = tearoff self::f1
+  #C8 = tearoff self::f2
+  #C9 = tearoff self::f3
+  #C10 = tearoff self::f4
+  #C11 = tearoff self::f5
+}
diff --git a/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
new file mode 100644
index 0000000..5d2b393
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/const_is.dart.weak.transformed.expect
@@ -0,0 +1,119 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef fType = ({required i: core::int}) → core::int;
+typedef gType = ({i: core::int}) → core::int;
+typedef bigType = ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int;
+typedef func = (core::Object) → self::B;
+typedef t1 = (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B;
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class A1 extends core::Object {
+  synthetic constructor •() → self::A1
+    : super core::Object::•()
+    ;
+}
+class A2 extends core::Object {
+  synthetic constructor •() → self::A2
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object implements self::A, self::A1, self::A2 {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object implements self::B {
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object implements self::C {
+  synthetic constructor •() → self::D
+    : super core::Object::•()
+    ;
+}
+static field core::bool inStrongMode = !(<core::int?>[] is{ForNonNullableByDefault} core::List<core::int>);
+static const field core::bool f_is_fType = #C1;
+static const field core::bool f_is_gType = #C1;
+static const field core::bool g_is_fType = #C1;
+static const field core::bool g_is_gType = #C1;
+static const field core::bool f_is_bigType = #C2;
+static const field core::bool f1_is_t1 = #C2;
+static const field core::bool f2_is_t1 = #C2;
+static const field core::bool f3_is_t1 = #C1;
+static const field core::bool f4_is_t1 = #C1;
+static const field core::bool f5_is_t1 = #C1;
+static method f({required core::int i = #C3}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method g({core::int i = #C4}) → core::int {
+  return i.{core::num::+}(1);
+}
+static method f1(core::int i, self::B b, core::Map<core::int, core::num> m, dynamic x, {required dynamic extraParam = #C3, required core::bool obool = #C3, required dynamic ox = #C3, required self::D ob = #C3, required core::List<core::num>? ol = #C3}) → self::B
+  return new self::B::•();
+static method f2(core::int i, self::D b, core::Map<core::int, core::int> m, (core::Object) → self::B x, {required (core::Object) → self::B ox = #C3, required self::D ob = #C3, required core::List<core::int> ol = #C3, required core::bool obool = #C3}) → self::D
+  return new self::D::•();
+static method f3(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required dynamic extraParam = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::Object obool = #C3}) → self::C
+  return new self::C::•();
+static method f4(core::num i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::A2 ob = #C3, required core::List<dynamic> ol = #C3, required core::bool obool = #C3, required self::A xx = #C3, required self::B yy = #C3}) → self::C
+  return new self::C::•();
+static method f5(core::int i, self::A b, core::Map<core::Object, core::Object> m, dynamic x, {required dynamic ox = #C3, required self::B ob = #C3, required core::List<dynamic> ol = #C3, required dynamic obool = #C3}) → self::C
+  return new self::C::•();
+static method main() → dynamic {
+  self::expect(true, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C5) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({required i: core::int}) → core::int, #C1);
+  self::expect(true, #C1);
+  self::expect((#C6) is{ForNonNullableByDefault} ({i: core::int}) → core::int, #C1);
+  self::expect(false, #C2);
+  self::expect((#C5) is{ForNonNullableByDefault} ({required i1: core::int, required i10: core::int, required i11: core::int, required i12: core::int, required i13: core::int, required i14: core::int, required i15: core::int, required i16: core::int, required i17: core::int, required i18: core::int, required i19: core::int, required i2: core::int, required i20: core::int, required i21: core::int, required i22: core::int, required i23: core::int, required i24: core::int, required i25: core::int, required i26: core::int, required i27: core::int, required i28: core::int, required i29: core::int, required i3: core::int, required i30: core::int, required i31: core::int, required i32: core::int, required i33: core::int, required i34: core::int, required i35: core::int, required i36: core::int, required i37: core::int, required i38: core::int, required i39: core::int, required i4: core::int, required i40: core::int, required i41: core::int, required i42: core::int, required i43: core::int, required i44: core::int, required i45: core::int, required i46: core::int, required i47: core::int, required i48: core::int, required i49: core::int, required i5: core::int, required i50: core::int, required i51: core::int, required i52: core::int, required i53: core::int, required i54: core::int, required i55: core::int, required i56: core::int, required i57: core::int, required i58: core::int, required i59: core::int, required i6: core::int, required i60: core::int, required i61: core::int, required i62: core::int, required i63: core::int, required i64: core::int, required i65: core::int, required i66: core::int, required i67: core::int, required i68: core::int, required i69: core::int, required i7: core::int, required i70: core::int, required i8: core::int, required i9: core::int}) → core::int, #C2);
+  self::expect(false, #C2);
+  self::expect((#C7) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(false, #C2);
+  self::expect((#C8) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C2);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C9) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+  self::expect(!self::inStrongMode, #C1);
+  self::expect((#C10) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+  self::expect(true, #C1);
+  self::expect((#C11) is{ForNonNullableByDefault} (core::int, self::B, core::Map<core::int, core::num>, dynamic, {required ob: self::B, required obool: core::bool, required ol: core::List<core::num>, required ox: dynamic}) → self::B, #C1);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+constants  {
+  #C1 = true
+  #C2 = false
+  #C3 = null
+  #C4 = 1
+  #C5 = tearoff self::f
+  #C6 = tearoff self::g
+  #C7 = tearoff self::f1
+  #C8 = tearoff self::f2
+  #C9 = tearoff self::f3
+  #C10 = tearoff self::f4
+  #C11 = tearoff self::f5
+}
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:157:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:159:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:161:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:163:12 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:165:12 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:168:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:170:13 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:172:13 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:174:13 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:176:13 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 56, effectively constant: 10
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.outline.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.outline.expect
index dc7afba..3e7a02e 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.outline.expect
@@ -18,3 +18,11 @@
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: NullCheck @ org-dartlang-testcase:///constant_null_check.dart:6:16 -> IntConstant(42)
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_null_check.dart:9:16 -> NullConstant(null)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_check.dart:16:23 -> InstanceConstant(const Class{Class.y: 42})
+Evaluated: StaticGet @ org-dartlang-testcase:///constant_null_check.dart:17:29 -> NullConstant(null)
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
index ca8683f..a0b9eae 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/constant_null_check.dart:9:17: Error: Constant evaluation error:
 // const int? d = c!;
@@ -21,7 +22,6 @@
 // const Class f = const Class(c);
 //             ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
index ca8683f..a0b9eae 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/constant_null_check.dart:9:17: Error: Constant evaluation error:
 // const int? d = c!;
@@ -21,7 +22,6 @@
 // const Class f = const Class(c);
 //             ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
index ca8683f..a0b9eae 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/constant_null_check.dart:9:17: Error: Constant evaluation error:
 // const int? d = c!;
@@ -21,7 +22,6 @@
 // const Class f = const Class(c);
 //             ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
index ca8683f..a0b9eae 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_check.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/constant_null_check.dart:9:17: Error: Constant evaluation error:
 // const int? d = c!;
@@ -21,7 +22,6 @@
 // const Class f = const Class(c);
 //             ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
index e959da7..04a6535 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.outline.expect
@@ -49,3 +49,32 @@
   ;
 static method expect(dynamic expected, dynamic actual, core::String message) → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:9:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:10:17 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:11:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:12:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:13:17 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:14:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:15:17 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:16:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:17:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:18:17 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:19:18 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:20:18 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:21:18 -> BoolConstant(true)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:22:18 -> InstanceConstant(const Class<int>{Class.field: false})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:23:18 -> InstanceConstant(const Class<int?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:24:18 -> InstanceConstant(const Class<Null?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:25:18 -> InstanceConstant(const Class<int>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:26:18 -> InstanceConstant(const Class<int?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:27:18 -> InstanceConstant(const Class<Null?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:28:18 -> InstanceConstant(const Class<int>{Class.field: false})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:29:18 -> InstanceConstant(const Class<int?>{Class.field: false})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:30:18 -> InstanceConstant(const Class<Null?>{Class.field: false})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:31:19 -> InstanceConstant(const Class<int>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:32:19 -> InstanceConstant(const Class<int?>{Class.field: true})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constant_null_is.dart:33:19 -> InstanceConstant(const Class<Null?>{Class.field: true})
+Extra constant evaluation: evaluated: 33, effectively constant: 25
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
index 38d97af..72bc1d1 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.strong.transformed.expect
@@ -91,3 +91,20 @@
   #C8 = self::Class<core::int?> {field:#C3}
   #C9 = self::Class<core::Null?> {field:#C3}
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:45:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:46:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:47:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:48:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:49:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:50:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:51:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:52:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:53:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:54:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:55:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:56:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:57:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:7:40 -> BoolConstant(false)
+Extra constant evaluation: evaluated: 102, effectively constant: 14
diff --git a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
index 1c2af1f..4bd5117 100644
--- a/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/constant_null_is.dart.weak.transformed.expect
@@ -89,3 +89,20 @@
   #C6 = self::Class<core::int*> {field:#C2}
   #C7 = self::Class<core::Null?> {field:#C3}
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:45:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:46:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:47:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:48:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:49:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:50:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:51:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:52:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:53:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:54:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:55:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:56:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:57:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:7:40 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 102, effectively constant: 14
diff --git a/pkg/front_end/testcases/nnbd/constants.dart.outline.expect b/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
index ec25785..4de21ca 100644
--- a/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/constants.dart.outline.expect
@@ -60,3 +60,41 @@
 static const field core::Map<core::int, core::String> mapConcatenation = con::mapLiteral;
 static method id<T extends core::Object? = dynamic>(con::id::T% t) → con::id::T%
   ;
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants.dart:10:27 -> TypeLiteralConstant(Object)
+Evaluated: Instantiation @ org-dartlang-testcase:///constants.dart:11:52 -> PartialInstantiationConstant(id<int>)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constants.dart:12:24 -> InstanceConstant(const Class<int>{Class.field: 0})
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants.dart:13:29 -> TypeLiteralConstant(dynamic Function(dynamic))
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants.dart:14:36 -> TypeLiteralConstant(T% Function<T>(T%))
+Evaluated: ListLiteral @ org-dartlang-testcase:///constants.dart:15:26 -> ListConstant(const <int>[0])
+Evaluated: SetLiteral @ org-dartlang-testcase:///constants.dart:16:25 -> InstanceConstant(const _UnmodifiableSet<int>{_UnmodifiableSet._map: const _ImmutableMap<int, Null?>{_ImmutableMap._kvPairs: const <dynamic>[0, null]}})
+Evaluated: MapLiteral @ org-dartlang-testcase:///constants.dart:17:33 -> InstanceConstant(const _ImmutableMap<int, String>{_ImmutableMap._kvPairs: const <dynamic>[0, "foo"]})
+Evaluated: ListConcatenation @ org-dartlang-testcase:///constants.dart:18:32 -> ListConstant(const <int>[0])
+Evaluated: SetConcatenation @ org-dartlang-testcase:///constants.dart:19:31 -> InstanceConstant(const _UnmodifiableSet<int>{_UnmodifiableSet._map: const _ImmutableMap<int, Null?>{_ImmutableMap._kvPairs: const <dynamic>[0, null]}})
+Evaluated: MapConcatenation @ org-dartlang-testcase:///constants.dart:20:7 -> InstanceConstant(const _ImmutableMap<int, String>{_ImmutableMap._kvPairs: const <dynamic>[0, "foo"]})
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:23:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:25:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:26:27 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:28:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:30:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:31:30 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:32:29 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:33:29 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:35:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:37:5 -> BoolConstant(true)
+Evaluated: StaticInvocation @ org-dartlang-testcase:///constants.dart:39:5 -> BoolConstant(true)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants_lib.dart:16:27 -> TypeLiteralConstant(Object)
+Evaluated: StaticGet @ org-dartlang-testcase:///constants_lib.dart:17:12 -> TearOffConstant(identical)
+Evaluated: Instantiation @ org-dartlang-testcase:///constants_lib.dart:18:48 -> PartialInstantiationConstant(id<int>)
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///constants_lib.dart:19:24 -> InstanceConstant(const Class<int>{Class.field: 0})
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants_lib.dart:20:29 -> TypeLiteralConstant(dynamic Function(dynamic))
+Evaluated: TypeLiteral @ org-dartlang-testcase:///constants_lib.dart:21:36 -> TypeLiteralConstant(T% Function<T>(T%))
+Evaluated: ListLiteral @ org-dartlang-testcase:///constants_lib.dart:22:26 -> ListConstant(const <int>[0])
+Evaluated: SetLiteral @ org-dartlang-testcase:///constants_lib.dart:23:25 -> InstanceConstant(const _UnmodifiableSet<int>{_UnmodifiableSet._map: const _ImmutableMap<int, Null?>{_ImmutableMap._kvPairs: const <dynamic>[0, null]}})
+Evaluated: MapLiteral @ org-dartlang-testcase:///constants_lib.dart:24:33 -> InstanceConstant(const _ImmutableMap<int, String>{_ImmutableMap._kvPairs: const <dynamic>[0, "foo"]})
+Evaluated: ListConcatenation @ org-dartlang-testcase:///constants_lib.dart:25:32 -> ListConstant(const <int>[0])
+Evaluated: SetConcatenation @ org-dartlang-testcase:///constants_lib.dart:26:31 -> InstanceConstant(const _UnmodifiableSet<int>{_UnmodifiableSet._map: const _ImmutableMap<int, Null?>{_ImmutableMap._kvPairs: const <dynamic>[0, null]}})
+Evaluated: MapConcatenation @ org-dartlang-testcase:///constants_lib.dart:27:7 -> InstanceConstant(const _ImmutableMap<int, String>{_ImmutableMap._kvPairs: const <dynamic>[0, "foo"]})
+Extra constant evaluation: evaluated: 35, effectively constant: 34
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.expect
index fefe271f..31532b7 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -70,13 +70,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
@@ -92,20 +92,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 };
@@ -116,13 +116,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
@@ -138,20 +138,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
 static method methodCompound() → dynamic {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.transformed.expect
index fefe271f..31532b7 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.strong.transformed.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -70,13 +70,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
@@ -92,20 +92,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 };
@@ -116,13 +116,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
@@ -138,20 +138,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
 static method methodCompound() → dynamic {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.expect
index fefe271f..31532b7 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -70,13 +70,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
@@ -92,20 +92,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 };
@@ -116,13 +116,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
@@ -138,20 +138,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
 static method methodCompound() → dynamic {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.transformed.expect
index fefe271f..31532b7 100644
--- a/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_assigned.dart.weak.transformed.expect
@@ -2,59 +2,59 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
 //   local2 = value; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
 //   local6 = 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+// pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -70,13 +70,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:30:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:31:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:32:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
@@ -92,20 +92,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:70:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:71:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:72:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 };
 static field () → core::Null? fieldCompound = () → core::Null? {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:88:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 };
@@ -116,13 +116,13 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:16:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t9 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:17:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:18:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
@@ -138,20 +138,20 @@
   local2 = value;
   local4 = 0;
   local6 = 0;
-  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Non-nullable late final variable 'local2' definitely assigned.
+  let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:50:3: Error: Late final variable 'local2' definitely assigned.
   local2 = value; // error
   ^^^^^^" in local2 = value;
-  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:51:3: Error: Late final variable 'local4' definitely assigned.
   local4 = 0; // error
   ^^^^^^" in local4 = 0;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Non-nullable late final variable 'local6' definitely assigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:52:3: Error: Late final variable 'local6' definitely assigned.
   local6 = 0; // error
   ^^^^^^" in local6 = 0;
 }
 static method methodCompound() → dynamic {
   late final core::int local4;
   local4 = 0;
-  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Non-nullable late final variable 'local4' definitely assigned.
+  let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_assigned.dart:80:3: Error: Late final variable 'local4' definitely assigned.
   local4 += 0; // error
   ^^^^^^" in local4 = local4.{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.expect
index 8d264c0..d23513e 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -106,19 +106,19 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -160,7 +160,7 @@
   local3 = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 };
@@ -175,19 +175,19 @@
   let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -229,7 +229,7 @@
   local3 = (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.transformed.expect
index 47c5912..b7c2c1c 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.strong.transformed.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -108,19 +108,19 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -164,7 +164,7 @@
   local3 = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 };
@@ -181,19 +181,19 @@
   let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -237,7 +237,7 @@
   local3 = (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.expect
index 8d264c0..d23513e 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -106,19 +106,19 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -160,7 +160,7 @@
   local3 = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 };
@@ -175,19 +175,19 @@
   let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -229,7 +229,7 @@
   local3 = (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.transformed.expect
index 47c5912..b7c2c1c 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned.dart.weak.transformed.expect
@@ -6,7 +6,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -14,7 +14,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -22,7 +22,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -30,7 +30,7 @@
 //   local1; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
 //   local2; // error
 //   ^^^^^^
 //
@@ -38,7 +38,7 @@
 //   local3; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4; // error
 //   ^^^^^^
 //
@@ -46,7 +46,7 @@
 //   local5; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
 //   local6; // error
 //   ^^^^^^
 //
@@ -78,7 +78,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -86,7 +86,7 @@
 //   local3 += 0; // error
 //   ^^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
 //   local4 += 0; // error
 //   ^^^^^^
 //
@@ -108,19 +108,19 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:34:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:35:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:36:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:37:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:38:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:39:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -164,7 +164,7 @@
   local3 = (let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:111:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:112:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 };
@@ -181,19 +181,19 @@
   let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:16:3: Error: Non-nullable variable 'local1' must be assigned before it can be used.
   local1; // error
   ^^^^^^" in local1;
-  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Non-nullable late variable 'local2' without initializer is definitely unassigned.
+  let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:17:3: Error: Late variable 'local2' without initializer is definitely unassigned.
   local2; // error
   ^^^^^^" in local2;
   let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:18:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3; // error
   ^^^^^^" in local3;
-  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:19:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4; // error
   ^^^^^^" in local4;
   let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:20:3: Error: Non-nullable variable 'local5' must be assigned before it can be used.
   local5; // error
   ^^^^^^" in local5;
-  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Non-nullable late variable 'local6' without initializer is definitely unassigned.
+  let final<BottomType> #t17 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:21:3: Error: Late variable 'local6' without initializer is definitely unassigned.
   local6; // error
   ^^^^^^" in local6;
   local7;
@@ -237,7 +237,7 @@
   local3 = (let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:103:3: Error: Non-nullable variable 'local3' must be assigned before it can be used.
   local3 += 0; // error
   ^^^^^^" in local3).{core::num::+}(0);
-  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Non-nullable late variable 'local4' without initializer is definitely unassigned.
+  local4 = (let final<BottomType> #t22 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned.dart:104:3: Error: Late variable 'local4' without initializer is definitely unassigned.
   local4 += 0; // error
   ^^^^^^" in local4).{core::num::+}(0);
 }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.expect
index 3b6af6d..117106a 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
 //     bar(value); // Error.
 //         ^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
 //     barInt(intValue); // Error.
 //            ^^^^^^^^
 //
@@ -22,10 +22,10 @@
   method foo() → dynamic {
     late self::A::T% value;
     late core::int intValue;
-    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
     bar(value); // Error.
         ^^^^^" in value);
-    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
     barInt(intValue); // Error.
            ^^^^^^^^" in intValue);
   }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.transformed.expect
index 3b6af6d..117106a 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.strong.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
 //     bar(value); // Error.
 //         ^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
 //     barInt(intValue); // Error.
 //            ^^^^^^^^
 //
@@ -22,10 +22,10 @@
   method foo() → dynamic {
     late self::A::T% value;
     late core::int intValue;
-    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
     bar(value); // Error.
         ^^^^^" in value);
-    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
     barInt(intValue); // Error.
            ^^^^^^^^" in intValue);
   }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.expect
index 3b6af6d..117106a 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
 //     bar(value); // Error.
 //         ^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
 //     barInt(intValue); // Error.
 //            ^^^^^^^^
 //
@@ -22,10 +22,10 @@
   method foo() → dynamic {
     late self::A::T% value;
     late core::int intValue;
-    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
     bar(value); // Error.
         ^^^^^" in value);
-    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
     barInt(intValue); // Error.
            ^^^^^^^^" in intValue);
   }
diff --git a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.transformed.expect
index 3b6af6d..117106a 100644
--- a/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart.weak.transformed.expect
@@ -2,11 +2,11 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
 //     bar(value); // Error.
 //         ^^^^^
 //
-// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+// pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
 //     barInt(intValue); // Error.
 //            ^^^^^^^^
 //
@@ -22,10 +22,10 @@
   method foo() → dynamic {
     late self::A::T% value;
     late core::int intValue;
-    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Non-nullable late variable 'value' without initializer is definitely unassigned.
+    this.{self::A::bar}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:15:9: Error: Late variable 'value' without initializer is definitely unassigned.
     bar(value); // Error.
         ^^^^^" in value);
-    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Non-nullable late variable 'intValue' without initializer is definitely unassigned.
+    this.{self::A::barInt}(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/definitely_unassigned_late_local_variables.dart:16:12: Error: Late variable 'intValue' without initializer is definitely unassigned.
     barInt(intValue); // Error.
            ^^^^^^^^" in intValue);
   }
diff --git a/pkg/front_end/testcases/nnbd/dynamic_object_call.dart.outline.expect b/pkg/front_end/testcases/nnbd/dynamic_object_call.dart.outline.expect
index 85c4e95..723338b0 100644
--- a/pkg/front_end/testcases/nnbd/dynamic_object_call.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/dynamic_object_call.dart.outline.expect
@@ -16,3 +16,9 @@
   ;
 static method test() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///dynamic_object_call.dart:6:4 -> InstanceConstant(const _Override{})
+Evaluated: StaticGet @ org-dartlang-testcase:///dynamic_object_call.dart:9:4 -> InstanceConstant(const _Override{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart b/pkg/front_end/testcases/nnbd/export_main_declaration.dart
new file mode 100644
index 0000000..20e61e6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'export_main_declaration_class_lib.dart' as class_lib;
+import 'export_main_declaration_extension_lib.dart' as extension_lib;
+import 'export_main_declaration_field_lib.dart' as field_lib;
+import 'export_main_declaration_getter_lib.dart' as getter_lib;
+import 'export_main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'export_main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'export_main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'export_main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'export_main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'export_main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'export_main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'export_main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'export_main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'export_main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'export_main_declaration_setter_lib.dart' as setter_lib;
+import 'export_main_declaration_typedef_lib.dart' as typedef_lib;
+
+export 'main_declaration.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.outline.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.outline.expect
new file mode 100644
index 0000000..4212a8e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.outline.expect
@@ -0,0 +1,421 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_declaration.dart" as mai;
+additionalExports = (mai::main)
+
+import "org-dartlang-testcase:///export_main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///export_main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///export_main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///export_main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///export_main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///export_main_declaration_typedef_lib.dart" as typedef_lib;
+export "org-dartlang-testcase:///main_declaration.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Context: This is exported 'main' declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "main_declaration_class_lib.dart" as mai2;
+additionalExports = (mai2::main)
+
+export "org-dartlang-testcase:///main_declaration_class_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Context: This is exported 'main' declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "main_declaration_extension_lib.dart" as mai3;
+additionalExports = (mai3::main)
+
+export "org-dartlang-testcase:///main_declaration_extension_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Context: This is exported 'main' declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "main_declaration_field_lib.dart" as mai4;
+additionalExports = (mai4::main)
+
+export "org-dartlang-testcase:///main_declaration_field_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Context: This is exported 'main' declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "main_declaration_getter_lib.dart" as mai5;
+additionalExports = (mai5::main)
+
+export "org-dartlang-testcase:///main_declaration_getter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "main_declaration_method_extra_optional_parameters_lib.dart" as mai6;
+additionalExports = (mai6::main)
+
+export "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "main_declaration_method_named_parameters_lib.dart" as mai7;
+additionalExports = (mai7::main)
+
+export "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "main_declaration_method_one_optional_parameter_lib.dart" as mai8;
+additionalExports = (mai8::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "main_declaration_method_one_parameter_lib.dart" as mai9;
+additionalExports = (mai9::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "main_declaration_method_one_required_optional_lib.dart" as mai10;
+additionalExports = (mai10::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart: Error: The exported 'main' method cannot have required named parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "main_declaration_method_required_named_parameters_lib.dart" as mai11;
+additionalExports = (mai11::main)
+
+export "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart: Error: The exported 'main' method must have at most 2 required parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "main_declaration_method_too_many_parameters_lib.dart" as mai12;
+additionalExports = (mai12::main)
+
+export "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "main_declaration_method_two_optional_parameters_lib.dart" as mai13;
+additionalExports = (mai13::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "main_declaration_method_two_parameters_lib.dart" as mai14;
+additionalExports = (mai14::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart: Error: The type 'Set<String>' of the first parameter of the exported 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "main_declaration_method_wrong_parameter_type_lib.dart" as mai15;
+additionalExports = (mai15::main)
+
+export "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Context: This is exported 'main' declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+import "main_declaration_setter_lib.dart" as mai16;
+additionalExports = (mai16::main)
+
+export "org-dartlang-testcase:///main_declaration_setter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Context: This is exported 'main' declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+import "main_declaration_typedef_lib.dart" as mai17;
+additionalExports = (mai17::main)
+
+export "org-dartlang-testcase:///main_declaration_typedef_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as mai2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → mai2::main
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as mai3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as mai4;
+
+static field () → void main;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as mai5;
+
+static get main() → () → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args}) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as mai11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args}) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as mai12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args, dynamic other]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as mai14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as mai15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as mai16;
+
+static set main(() → void f) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as mai17;
+
+typedef main = () → void;
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.expect
new file mode 100644
index 0000000..87148a1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.expect
@@ -0,0 +1,417 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_declaration.dart" as mai;
+additionalExports = (mai::main)
+
+import "org-dartlang-testcase:///export_main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///export_main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///export_main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///export_main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///export_main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///export_main_declaration_typedef_lib.dart" as typedef_lib;
+export "org-dartlang-testcase:///main_declaration.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Context: This is exported 'main' declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "main_declaration_class_lib.dart" as mai2;
+additionalExports = (mai2::main)
+
+export "org-dartlang-testcase:///main_declaration_class_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Context: This is exported 'main' declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "main_declaration_extension_lib.dart" as mai3;
+additionalExports = (mai3::main)
+
+export "org-dartlang-testcase:///main_declaration_extension_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Context: This is exported 'main' declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "main_declaration_field_lib.dart" as mai4;
+additionalExports = (mai4::main)
+
+export "org-dartlang-testcase:///main_declaration_field_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Context: This is exported 'main' declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "main_declaration_getter_lib.dart" as mai5;
+additionalExports = (mai5::main)
+
+export "org-dartlang-testcase:///main_declaration_getter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "main_declaration_method_extra_optional_parameters_lib.dart" as mai6;
+additionalExports = (mai6::main)
+
+export "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "main_declaration_method_named_parameters_lib.dart" as mai7;
+additionalExports = (mai7::main)
+
+export "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "main_declaration_method_one_optional_parameter_lib.dart" as mai8;
+additionalExports = (mai8::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "main_declaration_method_one_parameter_lib.dart" as mai9;
+additionalExports = (mai9::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "main_declaration_method_one_required_optional_lib.dart" as mai10;
+additionalExports = (mai10::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart: Error: The exported 'main' method cannot have required named parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "main_declaration_method_required_named_parameters_lib.dart" as mai11;
+additionalExports = (mai11::main)
+
+export "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart: Error: The exported 'main' method must have at most 2 required parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "main_declaration_method_too_many_parameters_lib.dart" as mai12;
+additionalExports = (mai12::main)
+
+export "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "main_declaration_method_two_optional_parameters_lib.dart" as mai13;
+additionalExports = (mai13::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "main_declaration_method_two_parameters_lib.dart" as mai14;
+additionalExports = (mai14::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart: Error: The type 'Set<String>' of the first parameter of the exported 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "main_declaration_method_wrong_parameter_type_lib.dart" as mai15;
+additionalExports = (mai15::main)
+
+export "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Context: This is exported 'main' declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+import "main_declaration_setter_lib.dart" as mai16;
+additionalExports = (mai16::main)
+
+export "org-dartlang-testcase:///main_declaration_setter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Context: This is exported 'main' declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+import "main_declaration_typedef_lib.dart" as mai17;
+additionalExports = (mai17::main)
+
+export "org-dartlang-testcase:///main_declaration_typedef_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as mai2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → mai2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as mai3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as mai4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as mai5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as mai6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as mai11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as mai12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as mai15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as mai16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as mai17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.transformed.expect
new file mode 100644
index 0000000..87148a1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.strong.transformed.expect
@@ -0,0 +1,417 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_declaration.dart" as mai;
+additionalExports = (mai::main)
+
+import "org-dartlang-testcase:///export_main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///export_main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///export_main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///export_main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///export_main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///export_main_declaration_typedef_lib.dart" as typedef_lib;
+export "org-dartlang-testcase:///main_declaration.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Context: This is exported 'main' declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "main_declaration_class_lib.dart" as mai2;
+additionalExports = (mai2::main)
+
+export "org-dartlang-testcase:///main_declaration_class_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Context: This is exported 'main' declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "main_declaration_extension_lib.dart" as mai3;
+additionalExports = (mai3::main)
+
+export "org-dartlang-testcase:///main_declaration_extension_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Context: This is exported 'main' declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "main_declaration_field_lib.dart" as mai4;
+additionalExports = (mai4::main)
+
+export "org-dartlang-testcase:///main_declaration_field_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Context: This is exported 'main' declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "main_declaration_getter_lib.dart" as mai5;
+additionalExports = (mai5::main)
+
+export "org-dartlang-testcase:///main_declaration_getter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "main_declaration_method_extra_optional_parameters_lib.dart" as mai6;
+additionalExports = (mai6::main)
+
+export "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "main_declaration_method_named_parameters_lib.dart" as mai7;
+additionalExports = (mai7::main)
+
+export "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "main_declaration_method_one_optional_parameter_lib.dart" as mai8;
+additionalExports = (mai8::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "main_declaration_method_one_parameter_lib.dart" as mai9;
+additionalExports = (mai9::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "main_declaration_method_one_required_optional_lib.dart" as mai10;
+additionalExports = (mai10::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart: Error: The exported 'main' method cannot have required named parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "main_declaration_method_required_named_parameters_lib.dart" as mai11;
+additionalExports = (mai11::main)
+
+export "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart: Error: The exported 'main' method must have at most 2 required parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "main_declaration_method_too_many_parameters_lib.dart" as mai12;
+additionalExports = (mai12::main)
+
+export "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "main_declaration_method_two_optional_parameters_lib.dart" as mai13;
+additionalExports = (mai13::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "main_declaration_method_two_parameters_lib.dart" as mai14;
+additionalExports = (mai14::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart: Error: The type 'Set<String>' of the first parameter of the exported 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "main_declaration_method_wrong_parameter_type_lib.dart" as mai15;
+additionalExports = (mai15::main)
+
+export "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Context: This is exported 'main' declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+import "main_declaration_setter_lib.dart" as mai16;
+additionalExports = (mai16::main)
+
+export "org-dartlang-testcase:///main_declaration_setter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Context: This is exported 'main' declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+import "main_declaration_typedef_lib.dart" as mai17;
+additionalExports = (mai17::main)
+
+export "org-dartlang-testcase:///main_declaration_typedef_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as mai2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → mai2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as mai3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as mai4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as mai5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as mai6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as mai11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as mai12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as mai15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as mai16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as mai17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline.expect
new file mode 100644
index 0000000..fa882bb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+import 'export_main_declaration_class_lib.dart' as class_lib;
+import 'export_main_declaration_extension_lib.dart' as extension_lib;
+import 'export_main_declaration_field_lib.dart' as field_lib;
+import 'export_main_declaration_getter_lib.dart' as getter_lib;
+import 'export_main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'export_main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'export_main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'export_main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'export_main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'export_main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'export_main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'export_main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'export_main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'export_main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'export_main_declaration_setter_lib.dart' as setter_lib;
+import 'export_main_declaration_typedef_lib.dart' as typedef_lib;
+export 'main_declaration.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a182a3e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.textual_outline_modelled.expect
@@ -0,0 +1,27 @@
+export 'main_declaration.dart';
+import 'export_main_declaration_class_lib.dart' as class_lib;
+import 'export_main_declaration_extension_lib.dart' as extension_lib;
+import 'export_main_declaration_field_lib.dart' as field_lib;
+import 'export_main_declaration_getter_lib.dart' as getter_lib;
+import 'export_main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'export_main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'export_main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'export_main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'export_main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'export_main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'export_main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'export_main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'export_main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'export_main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'export_main_declaration_setter_lib.dart' as setter_lib;
+import 'export_main_declaration_typedef_lib.dart' as typedef_lib;
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.expect
new file mode 100644
index 0000000..00c2307
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.expect
@@ -0,0 +1,417 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_declaration.dart" as mai;
+additionalExports = (mai::main)
+
+import "org-dartlang-testcase:///export_main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///export_main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///export_main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///export_main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///export_main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///export_main_declaration_typedef_lib.dart" as typedef_lib;
+export "org-dartlang-testcase:///main_declaration.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Context: This is exported 'main' declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "main_declaration_class_lib.dart" as mai2;
+additionalExports = (mai2::main)
+
+export "org-dartlang-testcase:///main_declaration_class_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Context: This is exported 'main' declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "main_declaration_extension_lib.dart" as mai3;
+additionalExports = (mai3::main)
+
+export "org-dartlang-testcase:///main_declaration_extension_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Context: This is exported 'main' declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "main_declaration_field_lib.dart" as mai4;
+additionalExports = (mai4::main)
+
+export "org-dartlang-testcase:///main_declaration_field_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Context: This is exported 'main' declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "main_declaration_getter_lib.dart" as mai5;
+additionalExports = (mai5::main)
+
+export "org-dartlang-testcase:///main_declaration_getter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "main_declaration_method_extra_optional_parameters_lib.dart" as mai6;
+additionalExports = (mai6::main)
+
+export "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "main_declaration_method_named_parameters_lib.dart" as mai7;
+additionalExports = (mai7::main)
+
+export "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "main_declaration_method_one_optional_parameter_lib.dart" as mai8;
+additionalExports = (mai8::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "main_declaration_method_one_parameter_lib.dart" as mai9;
+additionalExports = (mai9::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "main_declaration_method_one_required_optional_lib.dart" as mai10;
+additionalExports = (mai10::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart: Error: The exported 'main' method cannot have required named parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "main_declaration_method_required_named_parameters_lib.dart" as mai11;
+additionalExports = (mai11::main)
+
+export "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart: Error: The exported 'main' method must have at most 2 required parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "main_declaration_method_too_many_parameters_lib.dart" as mai12;
+additionalExports = (mai12::main)
+
+export "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "main_declaration_method_two_optional_parameters_lib.dart" as mai13;
+additionalExports = (mai13::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "main_declaration_method_two_parameters_lib.dart" as mai14;
+additionalExports = (mai14::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart: Error: The type 'Set<String>' of the first parameter of the exported 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "main_declaration_method_wrong_parameter_type_lib.dart" as mai15;
+additionalExports = (mai15::main)
+
+export "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Context: This is exported 'main' declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+import "main_declaration_setter_lib.dart" as mai16;
+additionalExports = (mai16::main)
+
+export "org-dartlang-testcase:///main_declaration_setter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Context: This is exported 'main' declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+import "main_declaration_typedef_lib.dart" as mai17;
+additionalExports = (mai17::main)
+
+export "org-dartlang-testcase:///main_declaration_typedef_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as mai2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → mai2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as mai3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as mai4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as mai5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as mai6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as mai11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as mai12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as mai15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as mai16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as mai17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.transformed.expect
new file mode 100644
index 0000000..00c2307
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration.dart.weak.transformed.expect
@@ -0,0 +1,417 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "main_declaration.dart" as mai;
+additionalExports = (mai::main)
+
+import "org-dartlang-testcase:///export_main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///export_main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///export_main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///export_main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///export_main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///export_main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///export_main_declaration_typedef_lib.dart" as typedef_lib;
+export "org-dartlang-testcase:///main_declaration.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Context: This is exported 'main' declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "main_declaration_class_lib.dart" as mai2;
+additionalExports = (mai2::main)
+
+export "org-dartlang-testcase:///main_declaration_class_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Context: This is exported 'main' declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "main_declaration_extension_lib.dart" as mai3;
+additionalExports = (mai3::main)
+
+export "org-dartlang-testcase:///main_declaration_extension_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Context: This is exported 'main' declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "main_declaration_field_lib.dart" as mai4;
+additionalExports = (mai4::main)
+
+export "org-dartlang-testcase:///main_declaration_field_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Context: This is exported 'main' declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "main_declaration_getter_lib.dart" as mai5;
+additionalExports = (mai5::main)
+
+export "org-dartlang-testcase:///main_declaration_getter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "main_declaration_method_extra_optional_parameters_lib.dart" as mai6;
+additionalExports = (mai6::main)
+
+export "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "main_declaration_method_named_parameters_lib.dart" as mai7;
+additionalExports = (mai7::main)
+
+export "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "main_declaration_method_one_optional_parameter_lib.dart" as mai8;
+additionalExports = (mai8::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "main_declaration_method_one_parameter_lib.dart" as mai9;
+additionalExports = (mai9::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "main_declaration_method_one_required_optional_lib.dart" as mai10;
+additionalExports = (mai10::main)
+
+export "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart: Error: The exported 'main' method cannot have required named parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "main_declaration_method_required_named_parameters_lib.dart" as mai11;
+additionalExports = (mai11::main)
+
+export "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart: Error: The exported 'main' method must have at most 2 required parameters.
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "main_declaration_method_too_many_parameters_lib.dart" as mai12;
+additionalExports = (mai12::main)
+
+export "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "main_declaration_method_two_optional_parameters_lib.dart" as mai13;
+additionalExports = (mai13::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "main_declaration_method_two_parameters_lib.dart" as mai14;
+additionalExports = (mai14::main)
+
+export "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart: Error: The type 'Set<String>' of the first parameter of the exported 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Context: This is exported 'main' declaration.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "main_declaration_method_wrong_parameter_type_lib.dart" as mai15;
+additionalExports = (mai15::main)
+
+export "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Context: This is exported 'main' declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+import "main_declaration_setter_lib.dart" as mai16;
+additionalExports = (mai16::main)
+
+export "org-dartlang-testcase:///main_declaration_setter_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart: Error: The exported 'main' declaration must be a function declaration.
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Context: This is exported 'main' declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+import "main_declaration_typedef_lib.dart" as mai17;
+additionalExports = (mai17::main)
+
+export "org-dartlang-testcase:///main_declaration_typedef_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as mai;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as mai2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → mai2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as mai3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as mai4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as mai5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as mai6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as mai11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as mai12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as mai14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as mai15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as mai16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as mai17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart
new file mode 100644
index 0000000..6e90759e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_class_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_class_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart
new file mode 100644
index 0000000..23551a6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_extension_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_extension_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart
new file mode 100644
index 0000000..748d5f6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_field_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_field_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart
new file mode 100644
index 0000000..f9664ca
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_getter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_getter_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_extra_optional_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_extra_optional_parameters_lib.dart
new file mode 100644
index 0000000..9baf657
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_extra_optional_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_extra_optional_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_named_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_named_parameters_lib.dart
new file mode 100644
index 0000000..8463a27
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_named_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_named_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_optional_parameter_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_optional_parameter_lib.dart
new file mode 100644
index 0000000..b085630
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_optional_parameter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_one_optional_parameter_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_parameter_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_parameter_lib.dart
new file mode 100644
index 0000000..0763ad4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_parameter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_one_parameter_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_required_optional_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_required_optional_lib.dart
new file mode 100644
index 0000000..dc1d7da
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_one_required_optional_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_one_required_optional_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart
new file mode 100644
index 0000000..0496be2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_required_named_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_required_named_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart
new file mode 100644
index 0000000..3158bed
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_too_many_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_too_many_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_optional_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_optional_parameters_lib.dart
new file mode 100644
index 0000000..1fd396a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_optional_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_two_optional_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_parameters_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_parameters_lib.dart
new file mode 100644
index 0000000..a59df30
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_two_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_two_parameters_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart
new file mode 100644
index 0000000..ecb7126
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_method_wrong_parameter_type_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_method_wrong_parameter_type_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart
new file mode 100644
index 0000000..2f994d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_setter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_setter_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart b/pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart
new file mode 100644
index 0000000..79c9645
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/export_main_declaration_typedef_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+export 'main_declaration_typedef_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.weak.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.weak.expect
index 5c20141..5c94642 100644
--- a/pkg/front_end/testcases/nnbd/extension_never.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.weak.expect
@@ -1,5 +1,6 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 
 extension Extension on Never {
   method extensionMethod = self::Extension|extensionMethod;
@@ -9,10 +10,10 @@
 static method Extension|get#extensionMethod(final Never #this) → () → dynamic
   return () → dynamic => self::Extension|extensionMethod(#this);
 static method implicitAccess(Never never) → dynamic {
-  never.extensionMethod();
-  never.missingMethod();
+  let final Never #t1 = (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).extensionMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t3 = (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).missingMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method explicitAccess(Never never) → dynamic {
-  self::Extension|extensionMethod(never);
+  self::Extension|extensionMethod(let final Never #t5 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/extension_never.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/extension_never.dart.weak.transformed.expect
index 5c20141..5c94642 100644
--- a/pkg/front_end/testcases/nnbd/extension_never.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/extension_never.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 
 extension Extension on Never {
   method extensionMethod = self::Extension|extensionMethod;
@@ -9,10 +10,10 @@
 static method Extension|get#extensionMethod(final Never #this) → () → dynamic
   return () → dynamic => self::Extension|extensionMethod(#this);
 static method implicitAccess(Never never) → dynamic {
-  never.extensionMethod();
-  never.missingMethod();
+  let final Never #t1 = (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).extensionMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t3 = (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).missingMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method explicitAccess(Never never) → dynamic {
-  self::Extension|extensionMethod(never);
+  self::Extension|extensionMethod(let final Never #t5 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.outline.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.outline.expect
index 197f942..d92b2fe 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.outline.expect
@@ -6,18 +6,18 @@
   constructor •(core::int initializedField1) → self::A
     ;
   external get fieldWithInitializer() → core::int;
-  external set fieldWithInitializer(core::int #t1) → void;
+  external set fieldWithInitializer(core::int #externalFieldValue) → void;
   external get initializedField1() → core::int;
-  external set initializedField1(core::int #t2) → void;
+  external set initializedField1(core::int #externalFieldValue) → void;
   external get initializedField2() → core::int;
-  external set initializedField2(core::int #t3) → void;
+  external set initializedField2(core::int #externalFieldValue) → void;
   external static get staticField() → core::int;
-  external static set staticField(core::int #t4) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   external static get staticField() → core::int;
-  external static set staticField(core::int #t5) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 extension Extension on self::A {
@@ -29,15 +29,15 @@
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
 }
 external static get topLevelField() → core::int;
-external static set topLevelField(core::int #t6) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 external static get finalTopLevelField() → core::int;
 external static get constField() → core::int;
-external static set constField(core::int #t7) → void;
+external static set constField(core::int #externalFieldValue) → void;
 external static get Extension|extensionInstanceField() → core::int;
-external static set Extension|extensionInstanceField(core::int #t8) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionInstanceField() → core::int;
 external static get Extension|extensionStaticField() → core::int;
-external static set Extension|extensionStaticField(core::int #t9) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionStaticField() → core::int;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.expect
index 895696f..5d4f518 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.expect
@@ -86,18 +86,18 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   external get fieldWithInitializer() → core::int;
-  external set fieldWithInitializer(core::int #t3) → void;
+  external set fieldWithInitializer(core::int #externalFieldValue) → void;
   external get initializedField1() → core::int;
-  external set initializedField1(core::int #t4) → void;
+  external set initializedField1(core::int #externalFieldValue) → void;
   external get initializedField2() → core::int;
-  external set initializedField2(core::int #t5) → void;
+  external set initializedField2(core::int #externalFieldValue) → void;
   external static get staticField() → core::int;
-  external static set staticField(core::int #t6) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   external static get staticField() → core::int;
-  external static set staticField(core::int #t7) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 extension Extension on self::A {
@@ -109,14 +109,14 @@
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
 }
 external static get topLevelField() → core::int;
-external static set topLevelField(core::int #t8) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 external static get finalTopLevelField() → core::int;
 external static get constField() → core::int;
-external static set constField(core::int #t9) → void;
+external static set constField(core::int #externalFieldValue) → void;
 external static get Extension|extensionInstanceField() → core::int;
-external static set Extension|extensionInstanceField(core::int #t10) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionInstanceField() → core::int;
 external static get Extension|extensionStaticField() → core::int;
-external static set Extension|extensionStaticField(core::int #t11) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionStaticField() → core::int;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.transformed.expect
index 895696f..5d4f518 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.strong.transformed.expect
@@ -86,18 +86,18 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   external get fieldWithInitializer() → core::int;
-  external set fieldWithInitializer(core::int #t3) → void;
+  external set fieldWithInitializer(core::int #externalFieldValue) → void;
   external get initializedField1() → core::int;
-  external set initializedField1(core::int #t4) → void;
+  external set initializedField1(core::int #externalFieldValue) → void;
   external get initializedField2() → core::int;
-  external set initializedField2(core::int #t5) → void;
+  external set initializedField2(core::int #externalFieldValue) → void;
   external static get staticField() → core::int;
-  external static set staticField(core::int #t6) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   external static get staticField() → core::int;
-  external static set staticField(core::int #t7) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 extension Extension on self::A {
@@ -109,14 +109,14 @@
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
 }
 external static get topLevelField() → core::int;
-external static set topLevelField(core::int #t8) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 external static get finalTopLevelField() → core::int;
 external static get constField() → core::int;
-external static set constField(core::int #t9) → void;
+external static set constField(core::int #externalFieldValue) → void;
 external static get Extension|extensionInstanceField() → core::int;
-external static set Extension|extensionInstanceField(core::int #t10) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionInstanceField() → core::int;
 external static get Extension|extensionStaticField() → core::int;
-external static set Extension|extensionStaticField(core::int #t11) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionStaticField() → core::int;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.expect
index 895696f..5d4f518 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.expect
@@ -86,18 +86,18 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   external get fieldWithInitializer() → core::int;
-  external set fieldWithInitializer(core::int #t3) → void;
+  external set fieldWithInitializer(core::int #externalFieldValue) → void;
   external get initializedField1() → core::int;
-  external set initializedField1(core::int #t4) → void;
+  external set initializedField1(core::int #externalFieldValue) → void;
   external get initializedField2() → core::int;
-  external set initializedField2(core::int #t5) → void;
+  external set initializedField2(core::int #externalFieldValue) → void;
   external static get staticField() → core::int;
-  external static set staticField(core::int #t6) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   external static get staticField() → core::int;
-  external static set staticField(core::int #t7) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 extension Extension on self::A {
@@ -109,14 +109,14 @@
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
 }
 external static get topLevelField() → core::int;
-external static set topLevelField(core::int #t8) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 external static get finalTopLevelField() → core::int;
 external static get constField() → core::int;
-external static set constField(core::int #t9) → void;
+external static set constField(core::int #externalFieldValue) → void;
 external static get Extension|extensionInstanceField() → core::int;
-external static set Extension|extensionInstanceField(core::int #t10) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionInstanceField() → core::int;
 external static get Extension|extensionStaticField() → core::int;
-external static set Extension|extensionStaticField(core::int #t11) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionStaticField() → core::int;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.transformed.expect
index 895696f..5d4f518 100644
--- a/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_field_errors.dart.weak.transformed.expect
@@ -86,18 +86,18 @@
                                    ^^^^^^^^^^^^^^^^^"
     ;
   external get fieldWithInitializer() → core::int;
-  external set fieldWithInitializer(core::int #t3) → void;
+  external set fieldWithInitializer(core::int #externalFieldValue) → void;
   external get initializedField1() → core::int;
-  external set initializedField1(core::int #t4) → void;
+  external set initializedField1(core::int #externalFieldValue) → void;
   external get initializedField2() → core::int;
-  external set initializedField2(core::int #t5) → void;
+  external set initializedField2(core::int #externalFieldValue) → void;
   external static get staticField() → core::int;
-  external static set staticField(core::int #t6) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   external static get staticField() → core::int;
-  external static set staticField(core::int #t7) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   external static get finalStaticField() → core::int;
 }
 extension Extension on self::A {
@@ -109,14 +109,14 @@
   static get finalExtensionStaticField = get self::Extension|finalExtensionStaticField;
 }
 external static get topLevelField() → core::int;
-external static set topLevelField(core::int #t8) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 external static get finalTopLevelField() → core::int;
 external static get constField() → core::int;
-external static set constField(core::int #t9) → void;
+external static set constField(core::int #externalFieldValue) → void;
 external static get Extension|extensionInstanceField() → core::int;
-external static set Extension|extensionInstanceField(core::int #t10) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionInstanceField() → core::int;
 external static get Extension|extensionStaticField() → core::int;
-external static set Extension|extensionStaticField(core::int #t11) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 external static get Extension|finalExtensionStaticField() → core::int;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.outline.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.outline.expect
index b475be4..99614fc 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.outline.expect
@@ -13,67 +13,67 @@
   @self::Annotation::•()
   external get instanceField() → core::int;
   @self::Annotation::•()
-  external set instanceField(core::int #t1) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @self::Annotation::•()
   external get finalInstanceField() → core::int;
   @self::Annotation::•()
   external get covariantInstanceField() → core::num;
   @self::Annotation::•()
-  external set covariantInstanceField(covariant core::num #t2) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @self::Annotation::•()
   external static get staticField() → core::int;
   @self::Annotation::•()
-  external static set staticField(core::int #t3) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @self::Annotation::•()
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t4) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t5) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t6) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   @self::Annotation::•()
   external get instanceField() → core::int;
   @self::Annotation::•()
-  external set instanceField(core::int #t7) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @self::Annotation::•()
   external get finalInstanceField() → core::int;
   @self::Annotation::•()
   external get covariantInstanceField() → core::num;
   @self::Annotation::•()
-  external set covariantInstanceField(covariant core::num #t8) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @self::Annotation::•()
   external static get staticField() → core::int;
   @self::Annotation::•()
-  external static set staticField(core::int #t9) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @self::Annotation::•()
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t10) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t11) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t12) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 class C extends core::Object implements self::A {
   synthetic constructor •() → self::C
     ;
   external get instanceField() → core::int;
-  external set instanceField(core::int #t13) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   external get finalInstanceField() → core::int;
   external get covariantInstanceField() → core::num;
-  external set covariantInstanceField(covariant core::num #t14) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t15) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t16) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -92,29 +92,58 @@
 @self::Annotation::•()
 external static get topLevelField() → core::int;
 @self::Annotation::•()
-external static set topLevelField(core::int #t17) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 @self::Annotation::•()
 external static get finalTopLevelField() → core::int;
 external static get untypedTopLevelField() → dynamic;
-external static set untypedTopLevelField(dynamic #t18) → void;
+external static set untypedTopLevelField(dynamic #externalFieldValue) → void;
 external static get untypedFinalTopLevelField() → dynamic;
 @self::Annotation::•()
 external static get Extension|extensionInstanceField() → core::int;
 @self::Annotation::•()
-external static set Extension|extensionInstanceField(core::int #t19) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 @self::Annotation::•()
 external static get Extension|finalExtensionInstanceField() → core::int;
 @self::Annotation::•()
 external static get Extension|extensionStaticField() → core::int;
 @self::Annotation::•()
-external static set Extension|extensionStaticField(core::int #t20) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 @self::Annotation::•()
 external static get Extension|finalExtensionStaticField() → core::int;
 external static get Extension|untypedExtensionInstanceField() → dynamic;
-external static set Extension|untypedExtensionInstanceField(dynamic #t21) → void;
+external static set Extension|untypedExtensionInstanceField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionInstanceField() → dynamic;
 external static get Extension|untypedExtensionStaticField() → dynamic;
-external static set Extension|untypedExtensionStaticField(dynamic #t22) → void;
+external static set Extension|untypedExtensionStaticField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionStaticField() → dynamic;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:21:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:21:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:24:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:27:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:27:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:30:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:30:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:33:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:48:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:48:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:51:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:54:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:54:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:57:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:57:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:60:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:10:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:10:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:13:2 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:75:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:75:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:78:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:81:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:81:4 -> InstanceConstant(const Annotation{})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///external_fields.dart:84:4 -> InstanceConstant(const Annotation{})
+Extra constant evaluation: evaluated: 25, effectively constant: 25
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
index 8f52a91..cbc138b 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.expect
@@ -14,52 +14,52 @@
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t1) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t2) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t3) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t4) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t5) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t6) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t7) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t8) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t9) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t10) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t11) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t12) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 class C extends core::Object implements self::A {
@@ -67,15 +67,15 @@
     : super core::Object::•()
     ;
   external get instanceField() → core::int;
-  external set instanceField(core::int #t13) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   external get finalInstanceField() → core::int;
   external get covariantInstanceField() → core::num;
-  external set covariantInstanceField(covariant core::num #t14) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t15) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t16) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -94,29 +94,29 @@
 @#C1
 external static get topLevelField() → core::int;
 @#C1
-external static set topLevelField(core::int #t17) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 @#C1
 external static get finalTopLevelField() → core::int;
 external static get untypedTopLevelField() → dynamic;
-external static set untypedTopLevelField(dynamic #t18) → void;
+external static set untypedTopLevelField(dynamic #externalFieldValue) → void;
 external static get untypedFinalTopLevelField() → dynamic;
 @#C1
 external static get Extension|extensionInstanceField() → core::int;
 @#C1
-external static set Extension|extensionInstanceField(core::int #t19) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionInstanceField() → core::int;
 @#C1
 external static get Extension|extensionStaticField() → core::int;
 @#C1
-external static set Extension|extensionStaticField(core::int #t20) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionStaticField() → core::int;
 external static get Extension|untypedExtensionInstanceField() → dynamic;
-external static set Extension|untypedExtensionInstanceField(dynamic #t21) → void;
+external static set Extension|untypedExtensionInstanceField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionInstanceField() → dynamic;
 external static get Extension|untypedExtensionStaticField() → dynamic;
-external static set Extension|untypedExtensionStaticField(dynamic #t22) → void;
+external static set Extension|untypedExtensionStaticField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionStaticField() → dynamic;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
index 8f52a91..cbc138b 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.strong.transformed.expect
@@ -14,52 +14,52 @@
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t1) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t2) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t3) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t4) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t5) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t6) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t7) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t8) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t9) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t10) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t11) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t12) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 class C extends core::Object implements self::A {
@@ -67,15 +67,15 @@
     : super core::Object::•()
     ;
   external get instanceField() → core::int;
-  external set instanceField(core::int #t13) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   external get finalInstanceField() → core::int;
   external get covariantInstanceField() → core::num;
-  external set covariantInstanceField(covariant core::num #t14) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t15) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t16) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -94,29 +94,29 @@
 @#C1
 external static get topLevelField() → core::int;
 @#C1
-external static set topLevelField(core::int #t17) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 @#C1
 external static get finalTopLevelField() → core::int;
 external static get untypedTopLevelField() → dynamic;
-external static set untypedTopLevelField(dynamic #t18) → void;
+external static set untypedTopLevelField(dynamic #externalFieldValue) → void;
 external static get untypedFinalTopLevelField() → dynamic;
 @#C1
 external static get Extension|extensionInstanceField() → core::int;
 @#C1
-external static set Extension|extensionInstanceField(core::int #t19) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionInstanceField() → core::int;
 @#C1
 external static get Extension|extensionStaticField() → core::int;
 @#C1
-external static set Extension|extensionStaticField(core::int #t20) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionStaticField() → core::int;
 external static get Extension|untypedExtensionInstanceField() → dynamic;
-external static set Extension|untypedExtensionInstanceField(dynamic #t21) → void;
+external static set Extension|untypedExtensionInstanceField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionInstanceField() → dynamic;
 external static get Extension|untypedExtensionStaticField() → dynamic;
-external static set Extension|untypedExtensionStaticField(dynamic #t22) → void;
+external static set Extension|untypedExtensionStaticField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionStaticField() → dynamic;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
index 8f52a91..cbc138b 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.expect
@@ -14,52 +14,52 @@
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t1) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t2) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t3) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t4) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t5) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t6) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t7) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t8) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t9) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t10) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t11) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t12) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 class C extends core::Object implements self::A {
@@ -67,15 +67,15 @@
     : super core::Object::•()
     ;
   external get instanceField() → core::int;
-  external set instanceField(core::int #t13) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   external get finalInstanceField() → core::int;
   external get covariantInstanceField() → core::num;
-  external set covariantInstanceField(covariant core::num #t14) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t15) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t16) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -94,29 +94,29 @@
 @#C1
 external static get topLevelField() → core::int;
 @#C1
-external static set topLevelField(core::int #t17) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 @#C1
 external static get finalTopLevelField() → core::int;
 external static get untypedTopLevelField() → dynamic;
-external static set untypedTopLevelField(dynamic #t18) → void;
+external static set untypedTopLevelField(dynamic #externalFieldValue) → void;
 external static get untypedFinalTopLevelField() → dynamic;
 @#C1
 external static get Extension|extensionInstanceField() → core::int;
 @#C1
-external static set Extension|extensionInstanceField(core::int #t19) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionInstanceField() → core::int;
 @#C1
 external static get Extension|extensionStaticField() → core::int;
 @#C1
-external static set Extension|extensionStaticField(core::int #t20) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionStaticField() → core::int;
 external static get Extension|untypedExtensionInstanceField() → dynamic;
-external static set Extension|untypedExtensionInstanceField(dynamic #t21) → void;
+external static set Extension|untypedExtensionInstanceField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionInstanceField() → dynamic;
 external static get Extension|untypedExtensionStaticField() → dynamic;
-external static set Extension|untypedExtensionStaticField(dynamic #t22) → void;
+external static set Extension|untypedExtensionStaticField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionStaticField() → dynamic;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
index 8f52a91..cbc138b 100644
--- a/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields.dart.weak.transformed.expect
@@ -14,52 +14,52 @@
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t1) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t2) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t3) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t4) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t5) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t6) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 abstract class B extends core::Object /*isMixinDeclaration*/  {
   @#C1
   external get instanceField() → core::int;
   @#C1
-  external set instanceField(core::int #t7) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   @#C1
   external get finalInstanceField() → core::int;
   @#C1
   external get covariantInstanceField() → core::num;
   @#C1
-  external set covariantInstanceField(covariant core::num #t8) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   @#C1
   external static get staticField() → core::int;
   @#C1
-  external static set staticField(core::int #t9) → void;
+  external static set staticField(core::int #externalFieldValue) → void;
   @#C1
   external static get finalStaticField() → core::int;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t10) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t11) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
   external static get untypedStaticField() → dynamic;
-  external static set untypedStaticField(dynamic #t12) → void;
+  external static set untypedStaticField(dynamic #externalFieldValue) → void;
   external static get untypedFinalStaticField() → dynamic;
 }
 class C extends core::Object implements self::A {
@@ -67,15 +67,15 @@
     : super core::Object::•()
     ;
   external get instanceField() → core::int;
-  external set instanceField(core::int #t13) → void;
+  external set instanceField(core::int #externalFieldValue) → void;
   external get finalInstanceField() → core::int;
   external get covariantInstanceField() → core::num;
-  external set covariantInstanceField(covariant core::num #t14) → void;
+  external set covariantInstanceField(covariant core::num #externalFieldValue) → void;
   external get untypedInstanceField() → dynamic;
-  external set untypedInstanceField(dynamic #t15) → void;
+  external set untypedInstanceField(dynamic #externalFieldValue) → void;
   external get untypedFinalInstanceField() → dynamic;
   external get untypedCovariantInstanceField() → dynamic;
-  external set untypedCovariantInstanceField(covariant dynamic #t16) → void;
+  external set untypedCovariantInstanceField(covariant dynamic #externalFieldValue) → void;
 }
 extension Extension on self::A {
   get extensionInstanceField = get self::Extension|extensionInstanceField;
@@ -94,29 +94,29 @@
 @#C1
 external static get topLevelField() → core::int;
 @#C1
-external static set topLevelField(core::int #t17) → void;
+external static set topLevelField(core::int #externalFieldValue) → void;
 @#C1
 external static get finalTopLevelField() → core::int;
 external static get untypedTopLevelField() → dynamic;
-external static set untypedTopLevelField(dynamic #t18) → void;
+external static set untypedTopLevelField(dynamic #externalFieldValue) → void;
 external static get untypedFinalTopLevelField() → dynamic;
 @#C1
 external static get Extension|extensionInstanceField() → core::int;
 @#C1
-external static set Extension|extensionInstanceField(core::int #t19) → void;
+external static set Extension|extensionInstanceField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionInstanceField() → core::int;
 @#C1
 external static get Extension|extensionStaticField() → core::int;
 @#C1
-external static set Extension|extensionStaticField(core::int #t20) → void;
+external static set Extension|extensionStaticField(core::int #externalFieldValue) → void;
 @#C1
 external static get Extension|finalExtensionStaticField() → core::int;
 external static get Extension|untypedExtensionInstanceField() → dynamic;
-external static set Extension|untypedExtensionInstanceField(dynamic #t21) → void;
+external static set Extension|untypedExtensionInstanceField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionInstanceField() → dynamic;
 external static get Extension|untypedExtensionStaticField() → dynamic;
-external static set Extension|untypedExtensionStaticField(dynamic #t22) → void;
+external static set Extension|untypedExtensionStaticField(dynamic #externalFieldValue) → void;
 external static get Extension|untypedFinalExtensionStaticField() → dynamic;
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.outline.expect b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.outline.expect
index 832b31d..bdaf36f 100644
--- a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.outline.expect
@@ -6,15 +6,15 @@
   synthetic constructor •() → self::A
     ;
   external get i1() → core::int;
-  external set i1(core::int #t1) → void;
+  external set i1(core::int #externalFieldValue) → void;
   external get cx() → dynamic;
-  external set cx(covariant dynamic #t2) → void;
+  external set cx(covariant dynamic #externalFieldValue) → void;
   external static get s1() → core::int;
-  external static set s1(core::int #t3) → void;
+  external static set s1(core::int #externalFieldValue) → void;
   external static get fx() → dynamic;
 }
 external static get s1() → core::int;
-external static set s1(core::int #t4) → void;
+external static set s1(core::int #externalFieldValue) → void;
 external static get fx() → dynamic;
 static method main() → dynamic
   ;
diff --git a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.expect b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.expect
index 57dc59d..f39a6bb 100644
--- a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.expect
@@ -7,14 +7,14 @@
     : super core::Object::•()
     ;
   external get i1() → core::int;
-  external set i1(core::int #t1) → void;
+  external set i1(core::int #externalFieldValue) → void;
   external get cx() → dynamic;
-  external set cx(covariant dynamic #t2) → void;
+  external set cx(covariant dynamic #externalFieldValue) → void;
   external static get s1() → core::int;
-  external static set s1(core::int #t3) → void;
+  external static set s1(core::int #externalFieldValue) → void;
   external static get fx() → dynamic;
 }
 external static get s1() → core::int;
-external static set s1(core::int #t4) → void;
+external static set s1(core::int #externalFieldValue) → void;
 external static get fx() → dynamic;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.transformed.expect
index 57dc59d..f39a6bb 100644
--- a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.strong.transformed.expect
@@ -7,14 +7,14 @@
     : super core::Object::•()
     ;
   external get i1() → core::int;
-  external set i1(core::int #t1) → void;
+  external set i1(core::int #externalFieldValue) → void;
   external get cx() → dynamic;
-  external set cx(covariant dynamic #t2) → void;
+  external set cx(covariant dynamic #externalFieldValue) → void;
   external static get s1() → core::int;
-  external static set s1(core::int #t3) → void;
+  external static set s1(core::int #externalFieldValue) → void;
   external static get fx() → dynamic;
 }
 external static get s1() → core::int;
-external static set s1(core::int #t4) → void;
+external static set s1(core::int #externalFieldValue) → void;
 external static get fx() → dynamic;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.expect b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.expect
index 57dc59d..f39a6bb 100644
--- a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.expect
@@ -7,14 +7,14 @@
     : super core::Object::•()
     ;
   external get i1() → core::int;
-  external set i1(core::int #t1) → void;
+  external set i1(core::int #externalFieldValue) → void;
   external get cx() → dynamic;
-  external set cx(covariant dynamic #t2) → void;
+  external set cx(covariant dynamic #externalFieldValue) → void;
   external static get s1() → core::int;
-  external static set s1(core::int #t3) → void;
+  external static set s1(core::int #externalFieldValue) → void;
   external static get fx() → dynamic;
 }
 external static get s1() → core::int;
-external static set s1(core::int #t4) → void;
+external static set s1(core::int #externalFieldValue) → void;
 external static get fx() → dynamic;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.transformed.expect
index 57dc59d..f39a6bb 100644
--- a/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/external_fields_spec.dart.weak.transformed.expect
@@ -7,14 +7,14 @@
     : super core::Object::•()
     ;
   external get i1() → core::int;
-  external set i1(core::int #t1) → void;
+  external set i1(core::int #externalFieldValue) → void;
   external get cx() → dynamic;
-  external set cx(covariant dynamic #t2) → void;
+  external set cx(covariant dynamic #externalFieldValue) → void;
   external static get s1() → core::int;
-  external static set s1(core::int #t3) → void;
+  external static set s1(core::int #externalFieldValue) → void;
   external static get fx() → dynamic;
 }
 external static get s1() → core::int;
-external static set s1(core::int #t4) → void;
+external static set s1(core::int #externalFieldValue) → void;
 external static get fx() → dynamic;
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.outline.expect b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.outline.expect
index decf707..c79998e 100644
--- a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.outline.expect
@@ -24,3 +24,11 @@
   #C1 = <core::int>[]
   #C2 = <core::int?>[]
 }
+
+Extra constant evaluation status:
+Evaluated: StaticInvocation @ org-dartlang-testcase:///from_agnostic.dart:7:12 -> BoolConstant(false)
+Evaluated: MapLiteral @ org-dartlang-testcase:///from_agnostic.dart:8:12 -> InstanceConstant(const _ImmutableMap<List<int?>, int>{_ImmutableMap._kvPairs: const <dynamic>[const <int>[], 0, const <int?>[], 1]})
+Evaluated: SetLiteral @ org-dartlang-testcase:///from_agnostic.dart:9:12 -> InstanceConstant(const _UnmodifiableSet<List<int?>>{_UnmodifiableSet._map: const _ImmutableMap<List<int?>, Null?>{_ImmutableMap._kvPairs: const <dynamic>[const <int>[], null, const <int?>[], null]}})
+Evaluated: StaticGet @ org-dartlang-testcase:///from_agnostic.dart:10:12 -> ListConstant(const <int>[])
+Evaluated: StaticGet @ org-dartlang-testcase:///from_agnostic.dart:11:12 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 5, effectively constant: 5
diff --git a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
index 7ede780..f936ed5 100644
--- a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:12: Error: Constant evaluation error:
 // const c2 = {a: 0, b: 1};
@@ -21,7 +22,6 @@
 // const c3 = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
index 7ede780..f936ed5 100644
--- a/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/from_agnostic/from_agnostic.dart:8:12: Error: Constant evaluation error:
 // const c2 = {a: 0, b: 1};
@@ -21,7 +22,6 @@
 // const c3 = {a, b};
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart
new file mode 100644
index 0000000..1aaaf23
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+int get property1 => 0; // ok
+void set property1(int value) {}
+
+int get property2 => 0; // ok
+void set property2(num value) {}
+
+num get property3 => 0; // error
+void set property3(int value) {}
+
+abstract class A {
+  int get property1; // ok
+  void set property1(int i);
+
+  int get property2; // ok
+  void set property2(int i);
+
+  num get property3; // error
+  void set property3(int i);
+
+  int property4 = 0; // ok
+
+  int property5 = 0; // ok
+
+  covariant num property6 = 0; // ok
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8 => 0; // ok
+  static void set property8(num value) {}
+
+  static num get property9 => 0; // error
+  static void set property9(int value) {}
+}
+
+abstract class B1 {
+  int get property1;
+
+  int get property2;
+
+  num get property3;
+
+  final int property4;
+
+  final int property5;
+
+  final num property6;
+
+  B1(this.property4, this.property5, this.property6);
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i); // ok
+
+  void set property2(num i); // ok
+
+  void set property3(int i); // error
+
+  void set property4(int i); // ok
+
+  void set property5(num i); // ok
+
+  void set property6(int i); // error
+}
+
+abstract class C1 {
+  void set property1(int i);
+
+  void set property2(num i);
+
+  void set property3(int i);
+
+  int property4 = 0;
+
+  num property5 = 0;
+
+  int property6 = 0;
+}
+
+abstract class C2 implements C1 {
+  int get property1; // ok
+
+  int get property2; // ok
+
+  num get property3; // error
+
+  int get property4; // ok
+
+  int get property5; // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  num get property6; // error
+}
+
+abstract class D1 {
+  int get property1;
+
+  int get property2;
+
+  num get property3;
+}
+
+abstract class D2 {
+  void set property1(int i);
+
+  void set property2(num i);
+
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 /* error on property3 */ {}
+
+abstract class D4 implements D3 /* no need for error on property3 */ {}
+
+extension Extension<T, S extends T> on int {
+  int get property1 => 0; // ok
+  void set property1(int i) {}
+
+  int get property2 => 0; // ok
+  void set property2(num i) {}
+
+  num get property3 => 0; // error
+  void set property3(int i) {}
+
+  S get property4 => 0; // ok
+  void set property4(S i) {}
+
+  S get property5 => 0; // ok
+  void set property5(T i) {}
+
+  T get property6 => 0; // error
+  void set property6(S i) {}
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8 => 0; // ok
+  static void set property8(num value) {}
+
+  static num get property9 => 0; // error
+  static void set property9(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect
new file mode 100644
index 0000000..fb834d9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.outline.expect
@@ -0,0 +1,262 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:21:11: Error: The type 'num' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:36:18: Error: The type 'num' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:37:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:61:12: Error: The type 'num' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:45:11: Context: This is the declaration of the getter 'B1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:67:12: Error: The type 'num' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:51:13: Context: This is the declaration of the field 'B1.property6'.
+//   final num property6;
+//             ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:89:11: Error: The type 'num' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:75:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   num get property6; // error
+//           ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the overridden method ('property6').
+//   int property6 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:118:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:11:9: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// num get property3 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:127:11: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   num get property3 => 0; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:128:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:9: Error: The type 'T' of the getter 'property6' is not a subtype of the type 'S' of the setter 'property6'.
+//   T get property6 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:137:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(S i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:145:18: Error: The type 'num' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:146:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int property5;
+  covariant field core::num property6;
+  synthetic constructor •() → self::A
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int i) → void;
+  abstract get property3() → core::num;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    ;
+  static set property7(core::int value) → void
+    ;
+  static get property8() → core::int
+    ;
+  static set property8(core::num value) → void
+    ;
+  static get property9() → core::num
+    ;
+  static set property9(core::int value) → void
+    ;
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::num property6;
+  constructor •(core::int property4, core::int property5, core::num property6) → self::B1
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::num i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::num property5;
+  field core::int property6;
+  synthetic constructor •() → self::C1
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::num;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    ;
+}
+extension Extension<T extends core::Object? = dynamic, S extends T% = dynamic> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4 = self::Extension|get#property4;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4 = self::Extension|set#property4;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  ;
+static set property1(core::int value) → void
+  ;
+static get property2() → core::int
+  ;
+static set property2(core::num value) → void
+  ;
+static get property3() → core::num
+  ;
+static set property3(core::int value) → void
+  ;
+static method Extension|get#property1<T extends core::Object? = dynamic, S extends self::Extension|get#property1::T% = dynamic>(final core::int #this) → core::int
+  ;
+static method Extension|set#property1<T extends core::Object? = dynamic, S extends self::Extension|set#property1::T% = dynamic>(final core::int #this, core::int i) → void
+  ;
+static method Extension|get#property2<T extends core::Object? = dynamic, S extends self::Extension|get#property2::T% = dynamic>(final core::int #this) → core::int
+  ;
+static method Extension|set#property2<T extends core::Object? = dynamic, S extends self::Extension|set#property2::T% = dynamic>(final core::int #this, core::num i) → void
+  ;
+static method Extension|get#property3<T extends core::Object? = dynamic, S extends self::Extension|get#property3::T% = dynamic>(final core::int #this) → core::num
+  ;
+static method Extension|set#property3<T extends core::Object? = dynamic, S extends self::Extension|set#property3::T% = dynamic>(final core::int #this, core::int i) → void
+  ;
+static method Extension|get#property4<T extends core::Object? = dynamic, S extends self::Extension|get#property4::T% = dynamic>(final core::int #this) → self::Extension|get#property4::S%
+  ;
+static method Extension|set#property4<T extends core::Object? = dynamic, S extends self::Extension|set#property4::T% = dynamic>(final core::int #this, self::Extension|set#property4::S% i) → void
+  ;
+static method Extension|get#property5<T extends core::Object? = dynamic, S extends self::Extension|get#property5::T% = dynamic>(final core::int #this) → self::Extension|get#property5::S%
+  ;
+static method Extension|set#property5<T extends core::Object? = dynamic, S extends self::Extension|set#property5::T% = dynamic>(final core::int #this, self::Extension|set#property5::T% i) → void
+  ;
+static method Extension|get#property6<T extends core::Object? = dynamic, S extends self::Extension|get#property6::T% = dynamic>(final core::int #this) → self::Extension|get#property6::T%
+  ;
+static method Extension|set#property6<T extends core::Object? = dynamic, S extends self::Extension|set#property6::T% = dynamic>(final core::int #this, self::Extension|set#property6::S% i) → void
+  ;
+static get Extension|property7() → core::int
+  ;
+static set Extension|property7(core::int value) → void
+  ;
+static get Extension|property8() → core::int
+  ;
+static set Extension|property8(core::num value) → void
+  ;
+static get Extension|property9() → core::num
+  ;
+static set Extension|property9(core::int value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect
new file mode 100644
index 0000000..f346415
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.expect
@@ -0,0 +1,273 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:21:11: Error: The type 'num' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:36:18: Error: The type 'num' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:37:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:61:12: Error: The type 'num' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:45:11: Context: This is the declaration of the getter 'B1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:67:12: Error: The type 'num' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:51:13: Context: This is the declaration of the field 'B1.property6'.
+//   final num property6;
+//             ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:89:11: Error: The type 'num' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:75:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   num get property6; // error
+//           ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the overridden method ('property6').
+//   int property6 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:118:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:11:9: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// num get property3 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:127:11: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   num get property3 => 0; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:128:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:9: Error: The type 'T' of the getter 'property6' is not a subtype of the type 'S' of the setter 'property6'.
+//   T get property6 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:137:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(S i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:145:18: Error: The type 'num' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:146:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:130:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+//   S get property4 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+//   S get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property6 => 0; // error
+//                      ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4 = 0;
+  field core::int property5 = 0;
+  covariant field core::num property6 = 0;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int i) → void;
+  abstract get property3() → core::num;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::num value) → void {}
+  static get property9() → core::num
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::num property6;
+  constructor •(core::int property4, core::int property5, core::num property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::num i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4 = 0;
+  field core::num property5 = 0;
+  field core::int property6 = 0;
+  synthetic constructor •() → self::C1
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::num;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::Object? = dynamic, S extends T% = dynamic> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4 = self::Extension|get#property4;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4 = self::Extension|set#property4;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::num value) → void {}
+static get property3() → core::num
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::Object? = dynamic, S extends self::Extension|get#property1::T% = dynamic>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::Object? = dynamic, S extends self::Extension|set#property1::T% = dynamic>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::Object? = dynamic, S extends self::Extension|get#property2::T% = dynamic>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::Object? = dynamic, S extends self::Extension|set#property2::T% = dynamic>(final core::int #this, core::num i) → void {}
+static method Extension|get#property3<T extends core::Object? = dynamic, S extends self::Extension|get#property3::T% = dynamic>(final core::int #this) → core::num
+  return 0;
+static method Extension|set#property3<T extends core::Object? = dynamic, S extends self::Extension|set#property3::T% = dynamic>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4<T extends core::Object? = dynamic, S extends self::Extension|get#property4::T% = dynamic>(final core::int #this) → self::Extension|get#property4::S%
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:130:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+  S get property4 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4<T extends core::Object? = dynamic, S extends self::Extension|set#property4::T% = dynamic>(final core::int #this, self::Extension|set#property4::S% i) → void {}
+static method Extension|get#property5<T extends core::Object? = dynamic, S extends self::Extension|get#property5::T% = dynamic>(final core::int #this) → self::Extension|get#property5::S%
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+  S get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::Object? = dynamic, S extends self::Extension|set#property5::T% = dynamic>(final core::int #this, self::Extension|set#property5::T% i) → void {}
+static method Extension|get#property6<T extends core::Object? = dynamic, S extends self::Extension|get#property6::T% = dynamic>(final core::int #this) → self::Extension|get#property6::T%
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property6 => 0; // error
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::Object? = dynamic, S extends self::Extension|set#property6::T% = dynamic>(final core::int #this, self::Extension|set#property6::S% i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::num value) → void {}
+static get Extension|property9() → core::num
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.transformed.expect
new file mode 100644
index 0000000..4e6abc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.strong.transformed.expect
@@ -0,0 +1,155 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:14:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:16:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:48:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:32:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:54:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:38:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:78:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:62:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:86:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:68:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:86:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:68:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:94:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:102:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:107:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:94:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:102:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
new file mode 100644
index 0000000..806128e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline.expect
@@ -0,0 +1,71 @@
+int get property1 => 0;
+void set property1(int value) {}
+int get property2 => 0;
+void set property2(num value) {}
+num get property3 => 0;
+void set property3(int value) {}
+abstract class A {
+  int get property1;
+  void set property1(int i);
+  int get property2;
+  void set property2(int i);
+  num get property3;
+  void set property3(int i);
+  int property4 = 0;
+  int property5 = 0;
+  covariant num property6 = 0;
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(num value) {}
+  static num get property9 => 0;
+  static void set property9(int value) {}
+}
+abstract class B1 {
+  int get property1;
+  int get property2;
+  num get property3;
+  final int property4;
+  final int property5;
+  final num property6;
+  B1(this.property4, this.property5, this.property6);
+}
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(num i);
+  void set property6(int i);
+}
+abstract class C1 {
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+  int property4 = 0;
+  num property5 = 0;
+  int property6 = 0;
+}
+abstract class C2 implements C1 {
+  int get property1;
+  int get property2;
+  num get property3;
+  int get property4;
+  int get property5;
+  num get property6;
+}
+abstract class D1 {
+  int get property1;
+  int get property2;
+  num get property3;
+}
+abstract class D2 {
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+}
+abstract class D3 implements D1, D2 {}
+abstract class D4 implements D3 {}
+extension Extension<T, S extends T> (){}
+on int (){}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..feb0a3a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.textual_outline_modelled.expect
@@ -0,0 +1,78 @@
+abstract class A {
+  covariant num property6 = 0;
+  int get property1;
+  int get property2;
+  int property4 = 0;
+  int property5 = 0;
+  num get property3;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static num get property9 => 0;
+  static void set property7(int value) {}
+  static void set property8(num value) {}
+  static void set property9(int value) {}
+  void set property1(int i);
+  void set property2(int i);
+  void set property3(int i);
+}
+
+abstract class B1 {
+  B1(this.property4, this.property5, this.property6);
+  final int property4;
+  final int property5;
+  final num property6;
+  int get property1;
+  int get property2;
+  num get property3;
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(num i);
+  void set property6(int i);
+}
+
+abstract class C1 {
+  int property4 = 0;
+  int property6 = 0;
+  num property5 = 0;
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+}
+
+abstract class C2 implements C1 {
+  int get property1;
+  int get property2;
+  int get property4;
+  int get property5;
+  num get property3;
+  num get property6;
+}
+
+abstract class D1 {
+  int get property1;
+  int get property2;
+  num get property3;
+}
+
+abstract class D2 {
+  void set property1(int i);
+  void set property2(num i);
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 {}
+
+abstract class D4 implements D3 {}
+
+int get property1 => 0;
+int get property2 => 0;
+main() {}
+num get property3 => 0;
+void set property1(int value) {}
+void set property2(num value) {}
+void set property3(int value) {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect
new file mode 100644
index 0000000..f346415
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.expect
@@ -0,0 +1,273 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:21:11: Error: The type 'num' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:36:18: Error: The type 'num' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:37:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:61:12: Error: The type 'num' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:45:11: Context: This is the declaration of the getter 'B1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:67:12: Error: The type 'num' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:51:13: Context: This is the declaration of the field 'B1.property6'.
+//   final num property6;
+//             ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:89:11: Error: The type 'num' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   num get property3; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:75:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The return type of the method 'C2.property6' is 'num', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   num get property6; // error
+//           ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the overridden method ('property6').
+//   int property6 = 0;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:97:11: Error: The type 'num' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   num get property6; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:81:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6 = 0;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:116:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:118:16: Error: The type 'num' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:11: Context: This is the declaration of the getter 'D1.property3'.
+//   num get property3;
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:113:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:11:9: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// num get property3 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:127:11: Error: The type 'num' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   num get property3 => 0; // error
+//           ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:128:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:9: Error: The type 'T' of the getter 'property6' is not a subtype of the type 'S' of the setter 'property6'.
+//   T get property6 => 0; // error
+//         ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:137:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(S i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:145:18: Error: The type 'num' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static num get property9 => 0; // error
+//                  ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:146:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:130:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+//   S get property4 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+//   S get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property6 => 0; // error
+//                      ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4 = 0;
+  field core::int property5 = 0;
+  covariant field core::num property6 = 0;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int i) → void;
+  abstract get property3() → core::num;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::num value) → void {}
+  static get property9() → core::num
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::num property6;
+  constructor •(core::int property4, core::int property5, core::num property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::num i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4 = 0;
+  field core::num property5 = 0;
+  field core::int property6 = 0;
+  synthetic constructor •() → self::C1
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::num;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::num;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::num i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::Object? = dynamic, S extends T% = dynamic> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4 = self::Extension|get#property4;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4 = self::Extension|set#property4;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::num value) → void {}
+static get property3() → core::num
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::Object? = dynamic, S extends self::Extension|get#property1::T% = dynamic>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::Object? = dynamic, S extends self::Extension|set#property1::T% = dynamic>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::Object? = dynamic, S extends self::Extension|get#property2::T% = dynamic>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::Object? = dynamic, S extends self::Extension|set#property2::T% = dynamic>(final core::int #this, core::num i) → void {}
+static method Extension|get#property3<T extends core::Object? = dynamic, S extends self::Extension|get#property3::T% = dynamic>(final core::int #this) → core::num
+  return 0;
+static method Extension|set#property3<T extends core::Object? = dynamic, S extends self::Extension|set#property3::T% = dynamic>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4<T extends core::Object? = dynamic, S extends self::Extension|get#property4::T% = dynamic>(final core::int #this) → self::Extension|get#property4::S%
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:130:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+  S get property4 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4<T extends core::Object? = dynamic, S extends self::Extension|set#property4::T% = dynamic>(final core::int #this, self::Extension|set#property4::S% i) → void {}
+static method Extension|get#property5<T extends core::Object? = dynamic, S extends self::Extension|get#property5::T% = dynamic>(final core::int #this) → self::Extension|get#property5::S%
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:133:22: Error: A value of type 'int' can't be returned from a function with return type 'S'.
+  S get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::Object? = dynamic, S extends self::Extension|set#property5::T% = dynamic>(final core::int #this, self::Extension|set#property5::T% i) → void {}
+static method Extension|get#property6<T extends core::Object? = dynamic, S extends self::Extension|get#property6::T% = dynamic>(final core::int #this) → self::Extension|get#property6::T%
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:136:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property6 => 0; // error
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::Object? = dynamic, S extends self::Extension|set#property6::T% = dynamic>(final core::int #this, self::Extension|set#property6::S% i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::num value) → void {}
+static get Extension|property9() → core::num
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.transformed.expect
new file mode 100644
index 0000000..4e6abc1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart.weak.transformed.expect
@@ -0,0 +1,155 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:14:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:16:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:48:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:32:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:54:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:38:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:78:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:62:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:86:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:68:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:86:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:68:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:105:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:94:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:102:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:107:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:94:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type.dart:102:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart
new file mode 100644
index 0000000..ca3246a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  late int property4; // ok
+
+  late int? property5; // ok
+
+  covariant late int property6; // ok
+
+  A(this.property4, this.property5, this.property6);
+}
+
+abstract class B1 {
+  late final int property4;
+
+  late final int property5;
+
+  late final int? property6;
+
+  B1(this.property4, this.property5, this.property6);
+}
+
+abstract class B2 implements B1 {
+  void set property4(int i); // ok
+
+  void set property5(int? i); // ok
+
+  void set property6(int i); // error
+}
+
+abstract class C1 {
+  late int property4;
+
+  late int property5;
+
+  late int property6;
+
+  C1(this.property4, this.property5, this.property6);
+}
+
+abstract class C2 implements C1 {
+  int get property4; // ok
+
+  int get property5; // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  int? get property6; // error
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect
new file mode 100644
index 0000000..36042d2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.outline.expect
@@ -0,0 +1,66 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:30:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:20:19: Context: This is the declaration of the field 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  late field core::int property4;
+  late field core::int? property5;
+  late covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    ;
+}
+abstract class B1 extends core::Object {
+  late final [setter] field core::int property4;
+  late final [setter] field core::int property5;
+  late final [setter] field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    ;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  late field core::int property4;
+  late field core::int property5;
+  late field core::int property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    ;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect
new file mode 100644
index 0000000..e53ccba4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:30:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:20:19: Context: This is the declaration of the field 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  late field core::int property4;
+  late field core::int? property5;
+  late covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  late final [setter] field core::int property4;
+  late final [setter] field core::int property5;
+  late final [setter] field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  late field core::int property4;
+  late field core::int property5;
+  late field core::int property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect
new file mode 100644
index 0000000..e53ccba4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.strong.transformed.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:30:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:20:19: Context: This is the declaration of the field 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  late field core::int property4;
+  late field core::int? property5;
+  late covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  late final [setter] field core::int property4;
+  late final [setter] field core::int property5;
+  late final [setter] field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  late field core::int property4;
+  late field core::int property5;
+  late field core::int property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect
new file mode 100644
index 0000000..2045647
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.textual_outline.expect
@@ -0,0 +1,39 @@
+abstract class A {
+  late int ;
+  property4;
+  late int;
+  operator? (){}
+  property5;
+  covariant late int ;
+  property6;
+  A(this.property4, this.property5, this.property6);
+}
+abstract class B1 {
+  late ;
+  final int property4;
+  late ;
+  final int property5;
+  late ;
+  final int? property6;
+  B1(this.property4, this.property5, this.property6);
+}
+abstract class B2 implements B1 {
+  void set property4(int i);
+  void set property5(int? i);
+  void set property6(int i);
+}
+abstract class C1 {
+  late int ;
+  property4;
+  late int ;
+  property5;
+  late int ;
+  property6;
+  C1(this.property4, this.property5, this.property6);
+}
+abstract class C2 implements C1 {
+  int get property4;
+  int get property5;
+  int? get property6;
+}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect
new file mode 100644
index 0000000..e53ccba4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:30:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:20:19: Context: This is the declaration of the field 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  late field core::int property4;
+  late field core::int? property5;
+  late covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  late final [setter] field core::int property4;
+  late final [setter] field core::int property5;
+  late final [setter] field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  late field core::int property4;
+  late field core::int property5;
+  late field core::int property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect
new file mode 100644
index 0000000..e53ccba4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart.weak.transformed.expect
@@ -0,0 +1,70 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:30:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:20:19: Context: This is the declaration of the field 'B1.property6'.
+//   late final int? property6;
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the overridden method ('property6').
+//   late int property6;
+//            ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:50:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_late.dart:38:12: Context: This is the declaration of the setter 'C1.property6'.
+//   late int property6;
+//            ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  late field core::int property4;
+  late field core::int? property5;
+  late covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B1 extends core::Object {
+  late final [setter] field core::int property4;
+  late final [setter] field core::int property5;
+  late final [setter] field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  late field core::int property4;
+  late field core::int property5;
+  late field core::int property6;
+  constructor •(core::int property4, core::int property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart
new file mode 100644
index 0000000..2156307
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+int get property1 => 0; // ok
+void set property1(int value) {}
+
+int get property2 => 0; // ok
+void set property2(int? value) {}
+
+int? get property3 => 0; // error
+void set property3(int value) {}
+
+abstract class A {
+  int get property1; // ok
+  void set property1(int i);
+
+  int get property2; // ok
+  void set property2(int? i);
+
+  int? get property3; // error
+  void set property3(int i);
+
+  int property4; // ok
+
+  int? property5; // ok
+
+  covariant int property6; // ok
+
+  A(this.property4, this.property5, this.property6);
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8 => 0; // ok
+  static void set property8(int? value) {}
+
+  static int? get property9 => 0; // error
+  static void set property9(int value) {}
+}
+
+abstract class B1 {
+  int get property1;
+
+  int get property2;
+
+  int? get property3;
+
+  final int property4;
+
+  final int property5;
+
+  final int? property6;
+
+  B1(this.property4, this.property5, this.property6);
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i); // ok
+
+  void set property2(int? i); // ok
+
+  void set property3(int i); // error
+
+  void set property4(int i); // ok
+
+  void set property5(int? i); // ok
+
+  void set property6(int i); // error
+}
+
+abstract class C1 {
+  void set property1(int i);
+
+  void set property2(int? i);
+
+  void set property3(int i);
+
+  int property4;
+
+  int? property5;
+
+  int property6;
+
+  C1(this.property4, this.property5, this.property6);
+}
+
+abstract class C2 implements C1 {
+  int get property1; // ok
+
+  int get property2; // ok
+
+  int? get property3; // error
+
+  int get property4; // ok
+
+  int get property5; // ok
+
+  // This results in two errors; one for the getter/setter type mismatch and one
+  // for the getter override.
+  int? get property6; // error
+}
+
+abstract class D1 {
+  int get property1;
+
+  int get property2;
+
+  int? get property3;
+}
+
+abstract class D2 {
+  void set property1(int i);
+
+  void set property2(int? i);
+
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 /* error on property3 */ {}
+
+abstract class D4 implements D3 /* no need for error on property3 */ {}
+
+extension Extension<T extends num> on int {
+  int get property1 => 0; // ok
+  void set property1(int i) {}
+
+  int get property2 => 0; // ok
+  void set property2(int? i) {}
+
+  int? get property3 => 0; // error
+  void set property3(int i) {}
+
+  T get property4a => 0; // ok
+  void set property4a(T i) {}
+
+  T? get property4b => 0; // ok
+  void set property4b(T? i) {}
+
+  T get property5 => 0; // ok
+  void set property5(T? i) {}
+
+  T? get property6 => 0; // error
+  void set property6(T i) {}
+
+  static int get property7 => 0; // ok
+  static void set property7(int value) {}
+
+  static int get property8 => 0; // ok
+  static void set property8(int? value) {}
+
+  static int? get property9 => 0; // error
+  static void set property9(int value) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect
new file mode 100644
index 0000000..763d5e7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.outline.expect
@@ -0,0 +1,268 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:21:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:38:19: Error: The type 'int?' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:39:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:63:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:47:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:69:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:53:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:93:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:77:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:122:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:11:10: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// int? get property3 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:131:12: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   int? get property3 => 0; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:132:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:10: Error: The type 'T?' of the getter 'property6' is not a subtype of the type 'T' of the setter 'property6'.
+//   T? get property6 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:144:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(T i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:152:19: Error: The type 'int?' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:153:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    ;
+  static set property7(core::int value) → void
+    ;
+  static get property8() → core::int
+    ;
+  static set property8(core::int? value) → void
+    ;
+  static get property9() → core::int?
+    ;
+  static set property9(core::int value) → void
+    ;
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    ;
+}
+extension Extension<T extends core::num = core::num> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4a = self::Extension|get#property4a;
+  get property4b = self::Extension|get#property4b;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4a = self::Extension|set#property4a;
+  set property4b = self::Extension|set#property4b;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  ;
+static set property1(core::int value) → void
+  ;
+static get property2() → core::int
+  ;
+static set property2(core::int? value) → void
+  ;
+static get property3() → core::int?
+  ;
+static set property3(core::int value) → void
+  ;
+static method Extension|get#property1<T extends core::num = core::num>(final core::int #this) → core::int
+  ;
+static method Extension|set#property1<T extends core::num = core::num>(final core::int #this, core::int i) → void
+  ;
+static method Extension|get#property2<T extends core::num = core::num>(final core::int #this) → core::int
+  ;
+static method Extension|set#property2<T extends core::num = core::num>(final core::int #this, core::int? i) → void
+  ;
+static method Extension|get#property3<T extends core::num = core::num>(final core::int #this) → core::int?
+  ;
+static method Extension|set#property3<T extends core::num = core::num>(final core::int #this, core::int i) → void
+  ;
+static method Extension|get#property4a<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4a::T
+  ;
+static method Extension|set#property4a<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4a::T i) → void
+  ;
+static method Extension|get#property4b<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4b::T?
+  ;
+static method Extension|set#property4b<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4b::T? i) → void
+  ;
+static method Extension|get#property5<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property5::T
+  ;
+static method Extension|set#property5<T extends core::num = core::num>(final core::int #this, self::Extension|set#property5::T? i) → void
+  ;
+static method Extension|get#property6<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property6::T?
+  ;
+static method Extension|set#property6<T extends core::num = core::num>(final core::int #this, self::Extension|set#property6::T i) → void
+  ;
+static get Extension|property7() → core::int
+  ;
+static set Extension|property7(core::int value) → void
+  ;
+static get Extension|property8() → core::int
+  ;
+static set Extension|property8(core::int? value) → void
+  ;
+static get Extension|property9() → core::int?
+  ;
+static set Extension|property9(core::int value) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect
new file mode 100644
index 0000000..40207f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.expect
@@ -0,0 +1,284 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:21:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:38:19: Error: The type 'int?' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:39:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:63:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:47:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:69:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:53:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:93:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:77:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:122:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:11:10: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// int? get property3 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:131:12: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   int? get property3 => 0; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:132:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:10: Error: The type 'T?' of the getter 'property6' is not a subtype of the type 'T' of the setter 'property6'.
+//   T? get property6 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:144:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(T i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:152:19: Error: The type 'int?' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:153:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property4a => 0; // ok
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property4b => 0; // ok
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property6 => 0; // error
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::int? value) → void {}
+  static get property9() → core::int?
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::num = core::num> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4a = self::Extension|get#property4a;
+  get property4b = self::Extension|get#property4b;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4a = self::Extension|set#property4a;
+  set property4b = self::Extension|set#property4b;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::int? value) → void {}
+static get property3() → core::int?
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::num = core::num>(final core::int #this, core::int? i) → void {}
+static method Extension|get#property3<T extends core::num = core::num>(final core::int #this) → core::int?
+  return 0;
+static method Extension|set#property3<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4a<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4a::T
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property4a => 0; // ok
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4a<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4a::T i) → void {}
+static method Extension|get#property4b<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4b::T?
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property4b => 0; // ok
+                       ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4b<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4b::T? i) → void {}
+static method Extension|get#property5<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property5::T
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::num = core::num>(final core::int #this, self::Extension|set#property5::T? i) → void {}
+static method Extension|get#property6<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property6::T?
+  return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property6 => 0; // error
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::num = core::num>(final core::int #this, self::Extension|set#property6::T i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::int? value) → void {}
+static get Extension|property9() → core::int?
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect
new file mode 100644
index 0000000..40207f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.strong.transformed.expect
@@ -0,0 +1,284 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:21:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:38:19: Error: The type 'int?' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:39:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:63:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:47:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:69:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:53:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:93:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:77:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:122:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:11:10: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// int? get property3 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:131:12: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   int? get property3 => 0; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:132:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:10: Error: The type 'T?' of the getter 'property6' is not a subtype of the type 'T' of the setter 'property6'.
+//   T? get property6 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:144:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(T i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:152:19: Error: The type 'int?' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:153:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property4a => 0; // ok
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property4b => 0; // ok
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property6 => 0; // error
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::int? value) → void {}
+  static get property9() → core::int?
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::num = core::num> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4a = self::Extension|get#property4a;
+  get property4b = self::Extension|get#property4b;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4a = self::Extension|set#property4a;
+  set property4b = self::Extension|set#property4b;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::int? value) → void {}
+static get property3() → core::int?
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::num = core::num>(final core::int #this, core::int? i) → void {}
+static method Extension|get#property3<T extends core::num = core::num>(final core::int #this) → core::int?
+  return 0;
+static method Extension|set#property3<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4a<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4a::T
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property4a => 0; // ok
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4a<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4a::T i) → void {}
+static method Extension|get#property4b<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4b::T?
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property4b => 0; // ok
+                       ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4b<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4b::T? i) → void {}
+static method Extension|get#property5<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property5::T
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::num = core::num>(final core::int #this, self::Extension|set#property5::T? i) → void {}
+static method Extension|get#property6<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property6::T?
+  return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property6 => 0; // error
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::num = core::num>(final core::int #this, self::Extension|set#property6::T i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::int? value) → void {}
+static get Extension|property9() → core::int?
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
new file mode 100644
index 0000000..1bfebe7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline.expect
@@ -0,0 +1,73 @@
+int get property1 => 0;
+void set property1(int value) {}
+int get property2 => 0;
+void set property2(int? value) {}
+int? get property3 => 0;
+void set property3(int value) {}
+abstract class A {
+  int get property1;
+  void set property1(int i);
+  int get property2;
+  void set property2(int? i);
+  int? get property3;
+  void set property3(int i);
+  int property4;
+  int? property5;
+  covariant int property6;
+  A(this.property4, this.property5, this.property6);
+  static int get property7 => 0;
+  static void set property7(int value) {}
+  static int get property8 => 0;
+  static void set property8(int? value) {}
+  static int? get property9 => 0;
+  static void set property9(int value) {}
+}
+abstract class B1 {
+  int get property1;
+  int get property2;
+  int? get property3;
+  final int property4;
+  final int property5;
+  final int? property6;
+  B1(this.property4, this.property5, this.property6);
+}
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(int? i);
+  void set property6(int i);
+}
+abstract class C1 {
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+  int property4;
+  int? property5;
+  int property6;
+  C1(this.property4, this.property5, this.property6);
+}
+abstract class C2 implements C1 {
+  int get property1;
+  int get property2;
+  int? get property3;
+  int get property4;
+  int get property5;
+  int? get property6;
+}
+abstract class D1 {
+  int get property1;
+  int get property2;
+  int? get property3;
+}
+abstract class D2 {
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+}
+abstract class D3 implements D1, D2 {}
+abstract class D4 implements D3 {}
+extension Extension<T extends num> (){}
+on int (){}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..30cbfa9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.textual_outline_modelled.expect
@@ -0,0 +1,80 @@
+abstract class A {
+  A(this.property4, this.property5, this.property6);
+  covariant int property6;
+  int? get property3;
+  int? property5;
+  int get property1;
+  int get property2;
+  int property4;
+  static int? get property9 => 0;
+  static int get property7 => 0;
+  static int get property8 => 0;
+  static void set property7(int value) {}
+  static void set property8(int? value) {}
+  static void set property9(int value) {}
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+}
+
+abstract class B1 {
+  B1(this.property4, this.property5, this.property6);
+  final int? property6;
+  final int property4;
+  final int property5;
+  int? get property3;
+  int get property1;
+  int get property2;
+}
+
+abstract class B2 implements B1 {
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+  void set property4(int i);
+  void set property5(int? i);
+  void set property6(int i);
+}
+
+abstract class C1 {
+  C1(this.property4, this.property5, this.property6);
+  int? property5;
+  int property4;
+  int property6;
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+}
+
+abstract class C2 implements C1 {
+  int? get property3;
+  int? get property6;
+  int get property1;
+  int get property2;
+  int get property4;
+  int get property5;
+}
+
+abstract class D1 {
+  int? get property3;
+  int get property1;
+  int get property2;
+}
+
+abstract class D2 {
+  void set property1(int i);
+  void set property2(int? i);
+  void set property3(int i);
+}
+
+abstract class D3 implements D1, D2 {}
+
+abstract class D4 implements D3 {}
+
+int? get property3 => 0;
+int get property1 => 0;
+int get property2 => 0;
+main() {}
+void set property1(int value) {}
+void set property2(int? value) {}
+void set property3(int value) {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect
new file mode 100644
index 0000000..40207f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.expect
@@ -0,0 +1,284 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:21:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:38:19: Error: The type 'int?' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:39:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:63:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:47:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:69:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:53:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:93:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:77:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:122:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:11:10: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// int? get property3 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:131:12: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   int? get property3 => 0; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:132:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:10: Error: The type 'T?' of the getter 'property6' is not a subtype of the type 'T' of the setter 'property6'.
+//   T? get property6 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:144:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(T i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:152:19: Error: The type 'int?' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:153:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property4a => 0; // ok
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property4b => 0; // ok
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property6 => 0; // error
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::int? value) → void {}
+  static get property9() → core::int?
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::num = core::num> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4a = self::Extension|get#property4a;
+  get property4b = self::Extension|get#property4b;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4a = self::Extension|set#property4a;
+  set property4b = self::Extension|set#property4b;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::int? value) → void {}
+static get property3() → core::int?
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::num = core::num>(final core::int #this, core::int? i) → void {}
+static method Extension|get#property3<T extends core::num = core::num>(final core::int #this) → core::int?
+  return 0;
+static method Extension|set#property3<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4a<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4a::T
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property4a => 0; // ok
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4a<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4a::T i) → void {}
+static method Extension|get#property4b<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4b::T?
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property4b => 0; // ok
+                       ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4b<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4b::T? i) → void {}
+static method Extension|get#property5<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property5::T
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::num = core::num>(final core::int #this, self::Extension|set#property5::T? i) → void {}
+static method Extension|get#property6<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property6::T?
+  return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property6 => 0; // error
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::num = core::num>(final core::int #this, self::Extension|set#property6::T i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::int? value) → void {}
+static get Extension|property9() → core::int?
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect
new file mode 100644
index 0000000..40207f8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart.weak.transformed.expect
@@ -0,0 +1,284 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:21:12: Error: The type 'int?' of the getter 'A.property3' is not a subtype of the type 'int' of the setter 'A.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:22:12: Context: This is the declaration of the setter 'A.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:38:19: Error: The type 'int?' of the getter 'A.property9' is not a subtype of the type 'int' of the setter 'A.property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:39:19: Context: This is the declaration of the setter 'A.property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:63:12: Error: The type 'int?' of the inherited getter 'B1.property3' is not a subtype of the type 'int' of the setter 'B2.property3'.
+//   void set property3(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:47:12: Context: This is the declaration of the getter 'B1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:69:12: Error: The type 'int?' of the inherited field 'B1.property6' is not a subtype of the type 'int' of the setter 'B2.property6'.
+//   void set property6(int i); // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:53:14: Context: This is the declaration of the field 'B1.property6'.
+//   final int? property6;
+//              ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:93:12: Error: The type 'int?' of the getter 'C2.property3' is not a subtype of the type 'int' of the inherited setter 'C1.property3'.
+//   int? get property3; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:77:12: Context: This is the declaration of the setter 'C1.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The return type of the method 'C2.property6' is 'int?', which does not match the return type, 'int', of the overridden method, 'C1.property6'.
+// Change to a subtype of 'int'.
+//   int? get property6; // error
+//            ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the overridden method ('property6').
+//   int property6;
+//       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:101:12: Error: The type 'int?' of the getter 'C2.property6' is not a subtype of the type 'int' of the inherited setter 'C1.property6'.
+//   int? get property6; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:83:7: Context: This is the declaration of the setter 'C1.property6'.
+//   int property6;
+//       ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:120:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D3 implements D1, D2 /* error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:122:16: Error: The type 'int?' of the inherited getter 'D1.property3' is not a subtype of the type 'int' of the inherited setter 'D2.property3'.
+// abstract class D4 implements D3 /* no need for error on property3 */ {}
+//                ^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:109:12: Context: This is the declaration of the getter 'D1.property3'.
+//   int? get property3;
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:117:12: Context: This is the declaration of the setter 'D2.property3'.
+//   void set property3(int i);
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:11:10: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+// int? get property3 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:12:10: Context: This is the declaration of the setter 'property3'.
+// void set property3(int value) {}
+//          ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:131:12: Error: The type 'int?' of the getter 'property3' is not a subtype of the type 'int' of the setter 'property3'.
+//   int? get property3 => 0; // error
+//            ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:132:12: Context: This is the declaration of the setter 'property3'.
+//   void set property3(int i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:10: Error: The type 'T?' of the getter 'property6' is not a subtype of the type 'T' of the setter 'property6'.
+//   T? get property6 => 0; // error
+//          ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:144:12: Context: This is the declaration of the setter 'property6'.
+//   void set property6(T i) {}
+//            ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:152:19: Error: The type 'int?' of the getter 'property9' is not a subtype of the type 'int' of the setter 'property9'.
+//   static int? get property9 => 0; // error
+//                   ^^^^^^^^^
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:153:19: Context: This is the declaration of the setter 'property9'.
+//   static void set property9(int value) {}
+//                   ^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property4a => 0; // ok
+//                       ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property4b => 0; // ok
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+//   T get property5 => 0; // ok
+//                      ^
+//
+// pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+//   T? get property6 => 0; // error
+//                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+abstract class A extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  covariant field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::A
+    : self::A::property4 = property4, self::A::property5 = property5, self::A::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract set property1(core::int i) → void;
+  abstract get property2() → core::int;
+  abstract set property2(core::int? i) → void;
+  abstract get property3() → core::int?;
+  abstract set property3(core::int i) → void;
+  static get property7() → core::int
+    return 0;
+  static set property7(core::int value) → void {}
+  static get property8() → core::int
+    return 0;
+  static set property8(core::int? value) → void {}
+  static get property9() → core::int?
+    return 0;
+  static set property9(core::int value) → void {}
+}
+abstract class B1 extends core::Object {
+  final field core::int property4;
+  final field core::int property5;
+  final field core::int? property6;
+  constructor •(core::int property4, core::int property5, core::int? property6) → self::B1
+    : self::B1::property4 = property4, self::B1::property5 = property5, self::B1::property6 = property6, super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class B2 extends core::Object implements self::B1 {
+  synthetic constructor •() → self::B2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+  abstract set property4(core::int i) → void;
+  abstract set property5(core::int? i) → void;
+  abstract set property6(core::int i) → void;
+}
+abstract class C1 extends core::Object {
+  field core::int property4;
+  field core::int? property5;
+  field core::int property6;
+  constructor •(core::int property4, core::int? property5, core::int property6) → self::C1
+    : self::C1::property4 = property4, self::C1::property5 = property5, self::C1::property6 = property6, super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class C2 extends core::Object implements self::C1 {
+  synthetic constructor •() → self::C2
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+  abstract get property4() → core::int;
+  abstract get property5() → core::int;
+  abstract get property6() → core::int?;
+}
+abstract class D1 extends core::Object {
+  synthetic constructor •() → self::D1
+    : super core::Object::•()
+    ;
+  abstract get property1() → core::int;
+  abstract get property2() → core::int;
+  abstract get property3() → core::int?;
+}
+abstract class D2 extends core::Object {
+  synthetic constructor •() → self::D2
+    : super core::Object::•()
+    ;
+  abstract set property1(core::int i) → void;
+  abstract set property2(core::int? i) → void;
+  abstract set property3(core::int i) → void;
+}
+abstract class D3 extends core::Object implements self::D1, self::D2 {
+  synthetic constructor •() → self::D3
+    : super core::Object::•()
+    ;
+}
+abstract class D4 extends core::Object implements self::D3 {
+  synthetic constructor •() → self::D4
+    : super core::Object::•()
+    ;
+}
+extension Extension<T extends core::num = core::num> on core::int {
+  get property1 = self::Extension|get#property1;
+  get property2 = self::Extension|get#property2;
+  get property3 = self::Extension|get#property3;
+  get property4a = self::Extension|get#property4a;
+  get property4b = self::Extension|get#property4b;
+  get property5 = self::Extension|get#property5;
+  get property6 = self::Extension|get#property6;
+  static get property7 = get self::Extension|property7;
+  static get property8 = get self::Extension|property8;
+  static get property9 = get self::Extension|property9;
+  set property1 = self::Extension|set#property1;
+  set property2 = self::Extension|set#property2;
+  set property3 = self::Extension|set#property3;
+  set property4a = self::Extension|set#property4a;
+  set property4b = self::Extension|set#property4b;
+  set property5 = self::Extension|set#property5;
+  set property6 = self::Extension|set#property6;
+  static set property7 = set self::Extension|property7;
+  static set property8 = set self::Extension|property8;
+  static set property9 = set self::Extension|property9;
+}
+static get property1() → core::int
+  return 0;
+static set property1(core::int value) → void {}
+static get property2() → core::int
+  return 0;
+static set property2(core::int? value) → void {}
+static get property3() → core::int?
+  return 0;
+static set property3(core::int value) → void {}
+static method Extension|get#property1<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property1<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property2<T extends core::num = core::num>(final core::int #this) → core::int
+  return 0;
+static method Extension|set#property2<T extends core::num = core::num>(final core::int #this, core::int? i) → void {}
+static method Extension|get#property3<T extends core::num = core::num>(final core::int #this) → core::int?
+  return 0;
+static method Extension|set#property3<T extends core::num = core::num>(final core::int #this, core::int i) → void {}
+static method Extension|get#property4a<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4a::T
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:134:23: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property4a => 0; // ok
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4a<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4a::T i) → void {}
+static method Extension|get#property4b<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property4b::T?
+  return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:137:24: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property4b => 0; // ok
+                       ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property4b<T extends core::num = core::num>(final core::int #this, self::Extension|set#property4b::T? i) → void {}
+static method Extension|get#property5<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property5::T
+  return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:140:22: Error: A value of type 'int' can't be returned from a function with return type 'T'.
+  T get property5 => 0; // ok
+                     ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property5<T extends core::num = core::num>(final core::int #this, self::Extension|set#property5::T? i) → void {}
+static method Extension|get#property6<T extends core::num = core::num>(final core::int #this) → self::Extension|get#property6::T?
+  return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/getter_vs_setter_type_nnbd.dart:143:23: Error: A value of type 'int' can't be returned from a function with return type 'T?'.
+  T? get property6 => 0; // error
+                      ^" in 0 as{TypeError,ForNonNullableByDefault} <BottomType>;
+static method Extension|set#property6<T extends core::num = core::num>(final core::int #this, self::Extension|set#property6::T i) → void {}
+static get Extension|property7() → core::int
+  return 0;
+static set Extension|property7(core::int value) → void {}
+static get Extension|property8() → core::int
+  return 0;
+static set Extension|property8(core::int? value) → void {}
+static get Extension|property9() → core::int?
+  return 0;
+static set Extension|property9(core::int value) → void {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
index ac0794c..571f848 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.strong.transformed.expect
@@ -67,3 +67,21 @@
   core::String? s2 = let final self::A7? #t22 = a in #t22.{core::Object::==}(null) ?{core::String?} null : let final core::String? #t23 = #t22.{self::A7::bar} in #t23.{core::String::==}(null) ?{core::String} #t22.{self::A7::bar} = "bar" : #t23{core::String};
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:27 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:27 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:17 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:17 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:24 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:24 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:15 -> DoubleConstant(3.14)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:21 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:15 -> DoubleConstant(3.14)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:21 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:28 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:28 -> StringConstant("bar")
+Extra constant evaluation: evaluated: 112, effectively constant: 14
diff --git a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
index ac0794c..571f848 100644
--- a/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/infer_if_null.dart.weak.transformed.expect
@@ -67,3 +67,21 @@
   core::String? s2 = let final self::A7? #t22 = a in #t22.{core::Object::==}(null) ?{core::String?} null : let final core::String? #t23 = #t22.{self::A7::bar} in #t23.{core::String::==}(null) ?{core::String} #t22.{self::A7::bar} = "bar" : #t23{core::String};
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:27 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:49:27 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:17 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:17 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:24 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:38:24 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:15 -> DoubleConstant(3.14)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:21 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:15 -> DoubleConstant(3.14)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:21 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:28 -> StringConstant("bar")
+Evaluated: VariableGet @ org-dartlang-testcase:///infer_if_null.dart:60:28 -> StringConstant("bar")
+Extra constant evaluation: evaluated: 112, effectively constant: 14
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart
new file mode 100644
index 0000000..71068db
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+T f<T>(T t) => t;
+
+T g<T>(T? t) => t!;
+
+T h<T extends Object>(T? t) => t!;
+
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {
+  f(d);
+  f(v);
+  f(onull);
+  f(o);
+  f(snull);
+  f(s);
+
+  g(d);
+  g(v);
+  g(onull);
+  g(o);
+  g(snull);
+  g(s);
+
+  h(d);
+  h(v);
+  h(onull);
+  h(o);
+  h(snull);
+  h(s);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.outline.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.outline.expect
new file mode 100644
index 0000000..4238908
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.outline.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method f<T extends core::Object? = dynamic>(self::f::T% t) → self::f::T%
+  ;
+static method g<T extends core::Object? = dynamic>(self::g::T? t) → self::g::T%
+  ;
+static method h<T extends core::Object = core::Object>(self::h::T? t) → self::h::T
+  ;
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.expect
new file mode 100644
index 0000000..046b42e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+//   g(v);
+//     ^
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+//   h(v);
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method f<T extends core::Object? = dynamic>(self::f::T% t) → self::f::T%
+  return t;
+static method g<T extends core::Object? = dynamic>(self::g::T? t) → self::g::T%
+  return t!;
+static method h<T extends core::Object = core::Object>(self::h::T? t) → self::h::T
+  return t!;
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  self::f<dynamic>(d);
+  self::f<void>(v);
+  self::f<core::Object?>(onull);
+  self::f<core::Object>(o);
+  self::f<core::String?>(snull);
+  self::f<core::String>(s);
+  self::g<core::Object>(d);
+  self::g<core::Object>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+  g(v);
+    ^" in v);
+  self::g<core::Object>(onull);
+  self::g<core::Object>(o);
+  self::g<core::String>(snull);
+  self::g<core::String>(s);
+  self::h<core::Object>(d);
+  self::h<core::Object>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+  h(v);
+    ^" in v);
+  self::h<core::Object>(onull);
+  self::h<core::Object>(o);
+  self::h<core::String>(snull);
+  self::h<core::String>(s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.transformed.expect
new file mode 100644
index 0000000..046b42e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+//   g(v);
+//     ^
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+//   h(v);
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method f<T extends core::Object? = dynamic>(self::f::T% t) → self::f::T%
+  return t;
+static method g<T extends core::Object? = dynamic>(self::g::T? t) → self::g::T%
+  return t!;
+static method h<T extends core::Object = core::Object>(self::h::T? t) → self::h::T
+  return t!;
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  self::f<dynamic>(d);
+  self::f<void>(v);
+  self::f<core::Object?>(onull);
+  self::f<core::Object>(o);
+  self::f<core::String?>(snull);
+  self::f<core::String>(s);
+  self::g<core::Object>(d);
+  self::g<core::Object>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+  g(v);
+    ^" in v);
+  self::g<core::Object>(onull);
+  self::g<core::Object>(o);
+  self::g<core::String>(snull);
+  self::g<core::String>(s);
+  self::h<core::Object>(d);
+  self::h<core::Object>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+  h(v);
+    ^" in v);
+  self::h<core::Object>(onull);
+  self::h<core::Object>(o);
+  self::h<core::String>(snull);
+  self::h<core::String>(s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline.expect
new file mode 100644
index 0000000..51fed79
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+T f<T>(T t) => t;
+T g<T>(T? t) => t!;
+T h<T extends Object>(T? t) => t!;
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..51fed79
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+T f<T>(T t) => t;
+T g<T>(T? t) => t!;
+T h<T extends Object>(T? t) => t!;
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.expect
new file mode 100644
index 0000000..046b42e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+//   g(v);
+//     ^
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+//   h(v);
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method f<T extends core::Object? = dynamic>(self::f::T% t) → self::f::T%
+  return t;
+static method g<T extends core::Object? = dynamic>(self::g::T? t) → self::g::T%
+  return t!;
+static method h<T extends core::Object = core::Object>(self::h::T? t) → self::h::T
+  return t!;
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  self::f<dynamic>(d);
+  self::f<void>(v);
+  self::f<core::Object?>(onull);
+  self::f<core::Object>(o);
+  self::f<core::String?>(snull);
+  self::f<core::String>(s);
+  self::g<core::Object>(d);
+  self::g<core::Object>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+  g(v);
+    ^" in v);
+  self::g<core::Object>(onull);
+  self::g<core::Object>(o);
+  self::g<core::String>(snull);
+  self::g<core::String>(s);
+  self::h<core::Object>(d);
+  self::h<core::Object>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+  h(v);
+    ^" in v);
+  self::h<core::Object>(onull);
+  self::h<core::Object>(o);
+  self::h<core::String>(snull);
+  self::h<core::String>(s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.transformed.expect
new file mode 100644
index 0000000..046b42e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart.weak.transformed.expect
@@ -0,0 +1,46 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+//   g(v);
+//     ^
+//
+// pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+//   h(v);
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+static method f<T extends core::Object? = dynamic>(self::f::T% t) → self::f::T%
+  return t;
+static method g<T extends core::Object? = dynamic>(self::g::T? t) → self::g::T%
+  return t!;
+static method h<T extends core::Object = core::Object>(self::h::T? t) → self::h::T
+  return t!;
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  self::f<dynamic>(d);
+  self::f<void>(v);
+  self::f<core::Object?>(onull);
+  self::f<core::Object>(o);
+  self::f<core::String?>(snull);
+  self::f<core::String>(s);
+  self::g<core::Object>(d);
+  self::g<core::Object>(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:20:5: Error: This expression has type 'void' and can't be used.
+  g(v);
+    ^" in v);
+  self::g<core::Object>(onull);
+  self::g<core::Object>(o);
+  self::g<core::String>(snull);
+  self::g<core::String>(s);
+  self::h<core::Object>(d);
+  self::h<core::Object>(let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/infer_object_from_dynamic.dart:27:5: Error: This expression has type 'void' and can't be used.
+  h(v);
+    ^" in v);
+  self::h<core::Object>(onull);
+  self::h<core::Object>(o);
+  self::h<core::String>(snull);
+  self::h<core::String>(s);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/injected_late_field_checks/main.dart.outline.expect b/pkg/front_end/testcases/nnbd/injected_late_field_checks/main.dart.outline.expect
index ca304c6..2726966 100644
--- a/pkg/front_end/testcases/nnbd/injected_late_field_checks/main.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/injected_late_field_checks/main.dart.outline.expect
@@ -21,3 +21,8 @@
   constructor baz(core::int foo) → self2::Class
     ;
 }
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
index 14a6598..4304389 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.expect
@@ -1,9 +1,10 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method foo(core::Null? x) → dynamic {
-  self::bar(x!);
+  self::bar(let final Never #t1 = x! in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
 }
 static method bar(core::int y) → dynamic {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
index 14a6598..4304389 100644
--- a/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue39822.dart.weak.transformed.expect
@@ -1,9 +1,10 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method foo(core::Null? x) → dynamic {
-  self::bar(x!);
+  self::bar(let final Never #t1 = x! in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
 }
 static method bar(core::int y) → dynamic {}
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart b/pkg/front_end/testcases/nnbd/issue40951.dart
new file mode 100644
index 0000000..0f168e8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  num field1;
+  num field2;
+
+  A() {}
+  A.foo() {}
+  A.bar(this.field1) {}
+  A.baz(this.field1, this.field2) {}
+}
+
+abstract class B {
+  num field1;
+  num field2;
+
+  B() {}
+  B.foo() {}
+  B.bar(this.field1) {}
+  B.baz(this.field1, this.field2) {}
+}
+
+class C {
+  final num? field1;
+  final num? field2;
+
+  C() {}
+  C.foo() {}
+  C.bar(this.field1) {}
+  C.baz(this.field1, this.field2) {}
+}
+
+abstract class D {
+  final num? field1;
+  final num? field2;
+
+  D() {}
+  D.foo() {}
+  D.bar(this.field1) {}
+  D.baz(this.field1, this.field2) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.outline.expect
new file mode 100644
index 0000000..e850cd8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.outline.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::A
+    ;
+  constructor foo() → self::A
+    ;
+  constructor bar(core::num field1) → self::A
+    ;
+  constructor baz(core::num field1, core::num field2) → self::A
+    ;
+}
+abstract class B extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::B
+    ;
+  constructor foo() → self::B
+    ;
+  constructor bar(core::num field1) → self::B
+    ;
+  constructor baz(core::num field1, core::num field2) → self::B
+    ;
+}
+class C extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::C
+    ;
+  constructor foo() → self::C
+    ;
+  constructor bar(core::num? field1) → self::C
+    ;
+  constructor baz(core::num? field1, core::num? field2) → self::C
+    ;
+}
+abstract class D extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::D
+    ;
+  constructor foo() → self::D
+    ;
+  constructor bar(core::num? field1) → self::D
+    ;
+  constructor baz(core::num? field1, core::num? field2) → self::D
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.strong.expect
new file mode 100644
index 0000000..42868d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.strong.expect
@@ -0,0 +1,206 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:11:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:21:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:31:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:41:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor foo() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::A
+    : self::A::field2 = null, self::A::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::A
+    : self::A::field1 = field1, self::A::field2 = field2, super core::Object::•() {}
+}
+abstract class B extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor foo() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::B
+    : self::B::field2 = null, self::B::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::B
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•() {}
+}
+class C extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor foo() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::C
+    : self::C::field2 = null, self::C::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::C
+    : self::C::field1 = field1, self::C::field2 = field2, super core::Object::•() {}
+}
+abstract class D extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor foo() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::D
+    : self::D::field2 = null, self::D::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::D
+    : self::D::field1 = field1, self::D::field2 = field2, super core::Object::•() {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.strong.transformed.expect
new file mode 100644
index 0000000..42868d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.strong.transformed.expect
@@ -0,0 +1,206 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:11:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:21:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:31:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:41:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor foo() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::A
+    : self::A::field2 = null, self::A::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::A
+    : self::A::field1 = field1, self::A::field2 = field2, super core::Object::•() {}
+}
+abstract class B extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor foo() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::B
+    : self::B::field2 = null, self::B::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::B
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•() {}
+}
+class C extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor foo() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::C
+    : self::C::field2 = null, self::C::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::C
+    : self::C::field1 = field1, self::C::field2 = field2, super core::Object::•() {}
+}
+abstract class D extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor foo() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::D
+    : self::D::field2 = null, self::D::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::D
+    : self::D::field1 = field1, self::D::field2 = field2, super core::Object::•() {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline.expect
new file mode 100644
index 0000000..611b634
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline.expect
@@ -0,0 +1,37 @@
+class A {
+  num field1;
+  num field2;
+  A() {}
+  A.foo() {}
+  A.bar(this.field1) {}
+  A.baz(this.field1, this.field2) {}
+}
+
+abstract class B {
+  num field1;
+  num field2;
+  B() {}
+  B.foo() {}
+  B.bar(this.field1) {}
+  B.baz(this.field1, this.field2) {}
+}
+
+class C {
+  final num? field1;
+  final num? field2;
+  C() {}
+  C.foo() {}
+  C.bar(this.field1) {}
+  C.baz(this.field1, this.field2) {}
+}
+
+abstract class D {
+  final num? field1;
+  final num? field2;
+  D() {}
+  D.foo() {}
+  D.bar(this.field1) {}
+  D.baz(this.field1, this.field2) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a12b8be
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.textual_outline_modelled.expect
@@ -0,0 +1,37 @@
+abstract class B {
+  B() {}
+  B.bar(this.field1) {}
+  B.baz(this.field1, this.field2) {}
+  B.foo() {}
+  num field1;
+  num field2;
+}
+
+abstract class D {
+  D() {}
+  D.bar(this.field1) {}
+  D.baz(this.field1, this.field2) {}
+  D.foo() {}
+  final num? field1;
+  final num? field2;
+}
+
+class A {
+  A() {}
+  A.bar(this.field1) {}
+  A.baz(this.field1, this.field2) {}
+  A.foo() {}
+  num field1;
+  num field2;
+}
+
+class C {
+  C() {}
+  C.bar(this.field1) {}
+  C.baz(this.field1, this.field2) {}
+  C.foo() {}
+  final num? field1;
+  final num? field2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.weak.expect
new file mode 100644
index 0000000..42868d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.weak.expect
@@ -0,0 +1,206 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:11:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:21:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:31:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:41:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor foo() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::A
+    : self::A::field2 = null, self::A::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::A
+    : self::A::field1 = field1, self::A::field2 = field2, super core::Object::•() {}
+}
+abstract class B extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor foo() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::B
+    : self::B::field2 = null, self::B::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::B
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•() {}
+}
+class C extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor foo() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::C
+    : self::C::field2 = null, self::C::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::C
+    : self::C::field1 = field1, self::C::field2 = field2, super core::Object::•() {}
+}
+abstract class D extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor foo() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::D
+    : self::D::field2 = null, self::D::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::D
+    : self::D::field1 = field1, self::D::field2 = field2, super core::Object::•() {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue40951.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue40951.dart.weak.transformed.expect
new file mode 100644
index 0000000..42868d7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue40951.dart.weak.transformed.expect
@@ -0,0 +1,206 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:9:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:6:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:10:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:11:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   A.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:7:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:19:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field1' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:16:7: Context: 'field1' is defined here.
+//   num field1;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:20:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.foo() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:21:3: Error: This constructor should initialize field 'field2' because its type 'num' doesn't allow null.
+//   B.bar(this.field1) {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:17:7: Context: 'field2' is defined here.
+//   num field2;
+//       ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:29:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:26:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:30:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:31:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   C.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:27:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:39:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D() {}
+//   ^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field1' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:36:14: Context: 'field1' is defined here.
+//   final num? field1;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:40:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.foo() {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue40951.dart:41:3: Error: Final field 'field2' is not initialized by this constructor.
+// Try to initialize the field using an initializing formal or a field initializer.
+//   D.bar(this.field1) {}
+//   ^^^
+// pkg/front_end/testcases/nnbd/issue40951.dart:37:14: Context: 'field2' is defined here.
+//   final num? field2;
+//              ^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor foo() → self::A
+    : self::A::field2 = null, self::A::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::A
+    : self::A::field2 = null, self::A::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::A
+    : self::A::field1 = field1, self::A::field2 = field2, super core::Object::•() {}
+}
+abstract class B extends core::Object {
+  field core::num field1;
+  field core::num field2;
+  constructor •() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor foo() → self::B
+    : self::B::field2 = null, self::B::field1 = null, super core::Object::•() {}
+  constructor bar(core::num field1) → self::B
+    : self::B::field2 = null, self::B::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num field1, core::num field2) → self::B
+    : self::B::field1 = field1, self::B::field2 = field2, super core::Object::•() {}
+}
+class C extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor foo() → self::C
+    : self::C::field2 = null, self::C::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::C
+    : self::C::field2 = null, self::C::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::C
+    : self::C::field1 = field1, self::C::field2 = field2, super core::Object::•() {}
+}
+abstract class D extends core::Object {
+  final field core::num? field1;
+  final field core::num? field2;
+  constructor •() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor foo() → self::D
+    : self::D::field2 = null, self::D::field1 = null, super core::Object::•() {}
+  constructor bar(core::num? field1) → self::D
+    : self::D::field2 = null, self::D::field1 = field1, super core::Object::•() {}
+  constructor baz(core::num? field1, core::num? field2) → self::D
+    : self::D::field1 = field1, self::D::field2 = field2, super core::Object::•() {}
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
index d6311c9..4d1285a 100644
--- a/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41102.dart.strong.transformed.expect
@@ -130,3 +130,9 @@
   #C2 = 1
   #C3 = ""
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:15 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:20 -> IntConstant(0)
+Extra constant evaluation: evaluated: 55, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
index d6311c9..4d1285a 100644
--- a/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41102.dart.weak.transformed.expect
@@ -130,3 +130,9 @@
   #C2 = 1
   #C3 = ""
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:15 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41102.dart:37:20 -> IntConstant(0)
+Extra constant evaluation: evaluated: 55, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart b/pkg/front_end/testcases/nnbd/issue41114.dart
index 7db889f..3929126 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 main() async {
-  List<String>? a = <String>[];
+  List<String>? a = <String>[] as List<String>?;
   Iterable<String>? b = a?.map((e) => e);
   Iterable<String>? i = b ?? a;
   print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.strong.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic async {
-  core::List<core::String>? a = <core::String>[];
+  core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
   core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
   core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
   core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
index 4b2167b..6fb76f5 100644
--- a/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41114.dart.weak.expect
@@ -3,7 +3,7 @@
 import "dart:core" as core;
 
 static method main() → dynamic async {
-  core::List<core::String>? a = <core::String>[];
+  core::List<core::String>? a = <core::String>[] as{ForNonNullableByDefault} core::List<core::String>?;
   core::Iterable<core::String>? b = let final core::List<core::String>? #t1 = a in #t1.{core::List::==}(null) ?{core::Iterable<core::String>?} null : #t1{core::List<core::String>}.{core::Iterable::map}<core::String>((core::String e) → core::String => e);
   core::Iterable<core::String>? i = let final core::Iterable<core::String>? #t2 = b in #t2.{core::Object::==}(null) ?{core::Iterable<core::String>?} a : #t2{core::Iterable<core::String>};
   core::print(i);
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
index 11217a1..3ced126 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.expect
@@ -36,6 +36,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 import "dart:async" as asy;
 
 static method throwing() → Never
@@ -48,12 +49,12 @@
   (core::int) → core::String x3 = (core::int v) → Never {
     return throw v;
   };
-  (core::int) → core::String x4 = (core::int v) → Never => self::throwing();
+  (core::int) → core::String x4 = (core::int v) → Never => let final Never #t1 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   (core::int) → core::String x5 = (core::int v) → Never {
-    self::throwing();
+    let final Never #t2 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → core::String x6 = (core::int v) → Never {
-    return self::throwing();
+    return let final Never #t3 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> async => throw v;
   (core::int) → asy::Future<core::String> y2 = (core::int v) → asy::Future<Never> async {
@@ -62,12 +63,12 @@
   (core::int) → asy::Future<core::String> y3 = (core::int v) → asy::Future<Never> async {
     return throw v;
   };
-  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => self::throwing();
+  (core::int) → asy::Future<core::String> y4 = (core::int v) → asy::Future<Never> async => let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<Never> async {
-    self::throwing();
+    let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<Never> async {
-    return self::throwing();
+    return let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
 }
 static method errors() → void async {
@@ -77,7 +78,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
   };
@@ -87,27 +88,27 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x5 = (core::int v) → core::String {
     try {
-      self::throwing();
+      let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
   };
   (core::int) → core::String x6 = (core::int v) → core::String {
     try {
-      return self::throwing();
+      return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
   };
@@ -117,7 +118,7 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
   };
@@ -127,27 +128,27 @@
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y5 = (core::int v) → asy::Future<core::String> async {
     try {
-      self::throwing();
+      let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
   };
   (core::int) → asy::Future<core::String> y6 = (core::int v) → asy::Future<core::String> async {
     try {
-      return self::throwing();
+      return let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
     }
     on core::Object catch(final core::Object _) {
     }
-    return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+    return let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
   };
diff --git a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
index 07174dc..73ca4fa 100644
--- a/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41156.dart.weak.transformed.expect
@@ -36,6 +36,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 import "dart:async" as asy;
 
 static method throwing() → Never
@@ -48,12 +49,12 @@
   (core::int) → core::String x3 = (core::int v) → Never {
     return throw v;
   };
-  (core::int) → core::String x4 = (core::int v) → Never => self::throwing();
+  (core::int) → core::String x4 = (core::int v) → Never => let final Never #t1 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   (core::int) → core::String x5 = (core::int v) → Never {
-    self::throwing();
+    let final Never #t2 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → core::String x6 = (core::int v) → Never {
-    return self::throwing();
+    return let final Never #t3 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   };
   (core::int) → asy::Future<core::String> y1 = (core::int v) → asy::Future<Never> /* originally async */ {
     final asy::_AsyncAwaitCompleter<Never> :async_completer = new asy::_AsyncAwaitCompleter::•<Never>();
@@ -147,7 +148,7 @@
       try {
         #L4:
         {
-          :return_value = self::throwing();
+          :return_value = let final Never #t4 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           break #L4;
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -174,7 +175,7 @@
       try {
         #L5:
         {
-          self::throwing();
+          let final Never #t5 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -200,7 +201,7 @@
       try {
         #L6:
         {
-          :return_value = self::throwing();
+          :return_value = let final Never #t6 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           break #L6;
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -234,7 +235,7 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:39:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x2 = (int v) /* error */ {
                             ^" in null;
         };
@@ -244,27 +245,27 @@
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:44:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x3 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x5 = (core::int v) → core::String {
           try {
-            self::throwing();
+            let final Never #t9 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:49:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x5 = (int v) /* error */ {
                             ^" in null;
         };
         (core::int) → core::String x6 = (core::int v) → core::String {
           try {
-            return self::throwing();
+            return let final Never #t11 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
           }
           on core::Object catch(final core::Object _) {
           }
-          return let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+          return let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:54:29: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   String Function(int) x6 = (int v) /* error */ {
                             ^" in null;
         };
@@ -285,7 +286,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:59:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y2 = (int v) async /* error */ {
                                     ^" in null;
                 break #L8;
@@ -320,7 +321,7 @@
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:64:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y3 = (int v) async /* error */ {
                                     ^" in null;
                 break #L9;
@@ -350,11 +351,11 @@
               #L10:
               {
                 try {
-                  self::throwing();
+                  let final Never #t15 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t7 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t16 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:69:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y5 = (int v) async /* error */ {
                                     ^" in null;
                 break #L10;
@@ -384,12 +385,12 @@
               #L11:
               {
                 try {
-                  :return_value = self::throwing();
+                  :return_value = let final Never #t17 = self::throwing() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
                   break #L11;
                 }
                 on core::Object catch(final core::Object _) {
                 }
-                :return_value = let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
+                :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/nnbd/issue41156.dart:74:37: Error: A non-null value must be returned since the return type 'String' doesn't allow null.
   Future<String> Function(int) y6 = (int v) async /* error */ {
                                     ^" in null;
                 break #L11;
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
index eff260bc..368f224 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.strong.transformed.expect
@@ -29,3 +29,8 @@
 static method main() → dynamic {
   self::test(null);
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///issue41273.dart:16:21 -> TypeLiteralConstant(Object)
+Extra constant evaluation: evaluated: 49, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
index eff260bc..8c49c0f 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.expect
@@ -1,29 +1,30 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method test(dynamic x) → void {
   if(x is{ForNonNullableByDefault} Never) {
-    Never n1 = x{Never}.toString();
-    Never n2 = x{Never}.runtimeType;
-    Never n3 = x{Never}.someGetter;
-    Never n4 = x{Never}.someMethod();
-    Never n5 = x{Never}.+(x{Never});
-    Never n6 = x{Never}.[](x{Never});
-    Never n7 = x{Never}.call();
-    Never n8 = x{Never}.runtimeType();
-    Never n9 = x{Never}.toString;
-    x{Never}.runtimeType = core::Object;
-    x{Never}.toString = () → core::String => "";
-    Never v1 = x{Never}.toString();
-    Never v2 = x{Never}.runtimeType;
-    Never v3 = x{Never}.someGetter;
-    Never v4 = x{Never}.someMethod();
-    Never v5 = x{Never}.+(x{Never});
-    Never v6 = x{Never}.[](x{Never});
-    Never v7 = x{Never}.call();
-    Never v8 = x{Never}.runtimeType();
-    Never v9 = x{Never}.toString;
+    Never n1 = let final Never #t1 = (let final Never #t2 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n2 = let final Never #t3 = (let final Never #t4 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n3 = let final Never #t5 = (let final Never #t6 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someGetter in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n4 = let final Never #t7 = (let final Never #t8 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n5 = let final Never #t9 = (let final Never #t10 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t11 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n6 = let final Never #t12 = (let final Never #t13 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t14 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n7 = let final Never #t15 = (let final Never #t16 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n8 = let final Never #t17 = (let final Never #t18 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n9 = let final Never #t19 = (let final Never #t20 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = core::Object;
+    (let final Never #t22 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString = () → core::String => "";
+    Never v1 = let final Never #t23 = (let final Never #t24 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v2 = let final Never #t25 = (let final Never #t26 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v3 = let final Never #t27 = (let final Never #t28 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someGetter in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v4 = let final Never #t29 = (let final Never #t30 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v5 = let final Never #t31 = (let final Never #t32 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t33 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v6 = let final Never #t34 = (let final Never #t35 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t36 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v7 = let final Never #t37 = (let final Never #t38 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v8 = let final Never #t39 = (let final Never #t40 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v9 = let final Never #t41 = (let final Never #t42 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   }
 }
 static method main() → dynamic {
diff --git a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
index eff260bc..e7749a6 100644
--- a/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41273.dart.weak.transformed.expect
@@ -1,31 +1,37 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method test(dynamic x) → void {
   if(x is{ForNonNullableByDefault} Never) {
-    Never n1 = x{Never}.toString();
-    Never n2 = x{Never}.runtimeType;
-    Never n3 = x{Never}.someGetter;
-    Never n4 = x{Never}.someMethod();
-    Never n5 = x{Never}.+(x{Never});
-    Never n6 = x{Never}.[](x{Never});
-    Never n7 = x{Never}.call();
-    Never n8 = x{Never}.runtimeType();
-    Never n9 = x{Never}.toString;
-    x{Never}.runtimeType = core::Object;
-    x{Never}.toString = () → core::String => "";
-    Never v1 = x{Never}.toString();
-    Never v2 = x{Never}.runtimeType;
-    Never v3 = x{Never}.someGetter;
-    Never v4 = x{Never}.someMethod();
-    Never v5 = x{Never}.+(x{Never});
-    Never v6 = x{Never}.[](x{Never});
-    Never v7 = x{Never}.call();
-    Never v8 = x{Never}.runtimeType();
-    Never v9 = x{Never}.toString;
+    Never n1 = let final Never #t1 = (let final Never #t2 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n2 = let final Never #t3 = (let final Never #t4 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n3 = let final Never #t5 = (let final Never #t6 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someGetter in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n4 = let final Never #t7 = (let final Never #t8 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n5 = let final Never #t9 = (let final Never #t10 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t11 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n6 = let final Never #t12 = (let final Never #t13 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t14 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n7 = let final Never #t15 = (let final Never #t16 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n8 = let final Never #t17 = (let final Never #t18 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never n9 = let final Never #t19 = (let final Never #t20 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    (let final Never #t21 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType = core::Object;
+    (let final Never #t22 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString = () → core::String => "";
+    Never v1 = let final Never #t23 = (let final Never #t24 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v2 = let final Never #t25 = (let final Never #t26 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v3 = let final Never #t27 = (let final Never #t28 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someGetter in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v4 = let final Never #t29 = (let final Never #t30 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).someMethod() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v5 = let final Never #t31 = (let final Never #t32 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t33 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v6 = let final Never #t34 = (let final Never #t35 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t36 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v7 = let final Never #t37 = (let final Never #t38 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v8 = let final Never #t39 = (let final Never #t40 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    Never v9 = let final Never #t41 = (let final Never #t42 = x{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   }
 }
 static method main() → dynamic {
   self::test(null);
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///issue41273.dart:16:21 -> TypeLiteralConstant(Object)
+Extra constant evaluation: evaluated: 175, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart b/pkg/front_end/testcases/nnbd/issue41495.dart
index ceaf89a..cca6995 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart
@@ -10,7 +10,7 @@
 main() {}
 
 errors() {
-  A? a1 = new A();
+  A? a1 = new A() as A?;
   a1.c1;
   a1.test;
 }
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.strong.expect
@@ -27,7 +27,7 @@
 }
 static method main() → dynamic {}
 static method errors() → dynamic {
-  self::A? a1 = new self::A::•();
+  self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
 Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
index ecc36781..4df1b52 100644
--- a/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue41495.dart.weak.expect
@@ -27,7 +27,7 @@
 }
 static method main() → dynamic {}
 static method errors() → dynamic {
-  self::A? a1 = new self::A::•();
+  self::A? a1 = new self::A::•() as{ForNonNullableByDefault} self::A?;
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue41495.dart:14:6: Error: Property 'c1' cannot be accessed on 'A?' because it is potentially null.
  - 'A' is from 'pkg/front_end/testcases/nnbd/issue41495.dart'.
 Try accessing using ?. instead.
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.outline.expect
index a9091d4..a9d3a40 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.outline.expect
@@ -12,3 +12,11 @@
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///issue41657.dart:6:38 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///issue41657.dart:8:38 -> BoolConstant(false)
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue41657.dart:10:38 -> ListConstant(const <Null?>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue41657.dart:12:38 -> ListConstant(const <int?>[])
+Extra constant evaluation: evaluated: 6, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.expect
index f69417a..0e06724 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/issue41657.dart:10:41: Error: Constant evaluation error:
 // const assertLegacySubtyping1 = <Null>[] as List<int>;
@@ -23,7 +24,6 @@
 // const assertLegacySubtyping2 = <int?>[] as List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
index f69417a..0e06724 100644
--- a/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41657.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/issue41657.dart:10:41: Error: Constant evaluation error:
 // const assertLegacySubtyping1 = <Null>[] as List<int>;
@@ -23,7 +24,6 @@
 // const assertLegacySubtyping2 = <int?>[] as List<int>;
 //       ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/issue41700b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue41700b.dart.strong.transformed.expect
index 93245c26..46f2af9 100644
--- a/pkg/front_end/testcases/nnbd/issue41700b.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue41700b.dart.strong.transformed.expect
@@ -47,3 +47,10 @@
     ^^^";
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///issue41700b.dart:8:12 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41700b.dart:8:12 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue41700b.dart:8:12 -> NullConstant(null)
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart b/pkg/front_end/testcases/nnbd/issue42429.dart
new file mode 100644
index 0000000..5023f9a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T extends num> {}
+
+typedef FArgument<X extends num> = Function(X);
+typedef FReturn<X extends num> = X Function();
+typedef FBoth<X extends num> = X Function(X);
+typedef FNowhere<X extends num> = Function();
+
+foo() {
+  A<Object> aObject; // Error.
+  A<num?> aNumNullable; // Error.
+  A<int?> aIntNullable; // Error.
+  A<Null> aNull; // Error.
+  FArgument<Object> fArgumentObject; // Error.
+  FArgument<num?> fArgumentNumNullable; // Error.
+  FArgument<int?> fArgumentIntNullable; // Error.
+  FArgument<Null> fArgumentNull; // Error.
+  FReturn<Object> fReturnObject; // Error.
+  FReturn<num?> fReturnNumNullable; // Error.
+  FReturn<int?> fReturnIntNullable; // Error.
+  FReturn<Null> fReturnNull; // Error.
+  FBoth<Object> fBothObject; // Error.
+  FBoth<num?> fBothNumNullable; // Error.
+  FBoth<int?> fBothIntNullable; // Error.
+  FBoth<Null> fBothNull; // Error.
+  FNowhere<Object> fNowhereObject; // Error.
+  FNowhere<num?> fNowhereNumNullable; // Error.
+  FNowhere<int?> fNowhereIntNullable; // Error.
+  FNowhere<Null> fNowhereNull; // Error.
+
+  A<Object?> aObjectNullable; // Ok.
+  A<dynamic> aDynamic; // Ok.
+  A<void> aVoid; // Ok.
+  A<num> aNum; // Ok.
+  A<int> aInt; // Ok.
+  A<Never> aNever; // Ok.
+  FArgument<Object?> fArgumentObjectNullable; // Ok.
+  FArgument<dynamic> fArgumentDynamic; // Ok.
+  FArgument<void> fArgumentVoid; // Ok.
+  FArgument<num> fArgumentNum; // Ok.
+  FArgument<int> fArgumentInt; // Ok.
+  FArgument<Never> fArgumentNever; // Ok.
+  FReturn<Object?> fReturnObjectNullable; // Ok.
+  FReturn<dynamic> fReturnDynamic; // Ok.
+  FReturn<void> fReturnVoid; // Ok.
+  FReturn<num> fReturnNum; // Ok.
+  FReturn<int> fReturnInt; // Ok.
+  FReturn<Never> fReturnNever; // Ok.
+  FBoth<Object?> fBothObjectNullable; // Ok.
+  FBoth<dynamic> fBothDynamic; // Ok.
+  FBoth<void> fBothVoid; // Ok.
+  FBoth<num> fBothNum; // Ok.
+  FBoth<int> fBothInt; // Ok.
+  FBoth<Never> fBothNever; // Ok.
+  FNowhere<Object?> fNowhereObjectNullable; // Ok.
+  FNowhere<dynamic> fNowhereDynamic; // Ok.
+  FNowhere<void> fNowhereVoid; // Ok.
+  FNowhere<num> fNowhereNum; // Ok.
+  FNowhere<int> fNowhereInt; // Ok.
+  FNowhere<Never> fNowhereNever; // Ok.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.outline.expect
new file mode 100644
index 0000000..2034770
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+typedef FArgument<contravariant X extends core::num = core::num> = (X) → dynamic;
+typedef FReturn<X extends core::num = core::num> = () → X;
+typedef FBoth<invariant X extends core::num = core::num> = (X) → X;
+typedef FNowhere<unrelated X extends core::num = core::num> = () → dynamic;
+class A<T extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    ;
+}
+static method foo() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect
new file mode 100644
index 0000000..30ddc8d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.expect
@@ -0,0 +1,234 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:13:13: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Object> aObject; // Error.
+//             ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:14:11: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num?> aNumNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:15:11: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<int?> aIntNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:16:11: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Null> aNull; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:17:21: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object> fArgumentObject; // Error.
+//                     ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:18:19: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<num?> fArgumentNumNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:19:19: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<int?> fArgumentIntNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:20:19: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Null> fArgumentNull; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:21:19: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Object> fReturnObject; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:22:17: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<num?> fReturnNumNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:23:17: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<int?> fReturnIntNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:24:17: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Null> fReturnNull; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:25:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Object> fBothObject; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:26:15: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<num?> fBothNumNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:27:15: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<int?> fBothIntNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:28:15: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Null> fBothNull; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:29:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Object> fNowhereObject; // Error.
+//                    ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:30:18: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<num?> fNowhereNumNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:31:18: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<int?> fNowhereIntNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:32:18: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Null> fNowhereNull; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef FArgument<contravariant X extends core::num = core::num> = (X) → dynamic;
+typedef FReturn<X extends core::num = core::num> = () → X;
+typedef FBoth<invariant X extends core::num = core::num> = (X) → X;
+typedef FNowhere<unrelated X extends core::num = core::num> = () → dynamic;
+class A<T extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  self::A<core::Object> aObject;
+  self::A<core::num?> aNumNullable;
+  self::A<core::int?> aIntNullable;
+  self::A<core::Null?> aNull;
+  (core::Object) → dynamic fArgumentObject;
+  (core::num?) → dynamic fArgumentNumNullable;
+  (core::int?) → dynamic fArgumentIntNullable;
+  (core::Null?) → dynamic fArgumentNull;
+  () → core::Object fReturnObject;
+  () → core::num? fReturnNumNullable;
+  () → core::int? fReturnIntNullable;
+  () → core::Null? fReturnNull;
+  (core::Object) → core::Object fBothObject;
+  (core::num?) → core::num? fBothNumNullable;
+  (core::int?) → core::int? fBothIntNullable;
+  (core::Null?) → core::Null? fBothNull;
+  () → dynamic fNowhereObject;
+  () → dynamic fNowhereNumNullable;
+  () → dynamic fNowhereIntNullable;
+  () → dynamic fNowhereNull;
+  self::A<core::Object?> aObjectNullable;
+  self::A<dynamic> aDynamic;
+  self::A<void> aVoid;
+  self::A<core::num> aNum;
+  self::A<core::int> aInt;
+  self::A<Never> aNever;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
+  (core::num) → dynamic fArgumentNum;
+  (core::int) → dynamic fArgumentInt;
+  (Never) → dynamic fArgumentNever;
+  () → core::Object? fReturnObjectNullable;
+  () → dynamic fReturnDynamic;
+  () → void fReturnVoid;
+  () → core::num fReturnNum;
+  () → core::int fReturnInt;
+  () → Never fReturnNever;
+  (core::Object?) → core::Object? fBothObjectNullable;
+  (dynamic) → dynamic fBothDynamic;
+  (void) → void fBothVoid;
+  (core::num) → core::num fBothNum;
+  (core::int) → core::int fBothInt;
+  (Never) → Never fBothNever;
+  () → dynamic fNowhereObjectNullable;
+  () → dynamic fNowhereDynamic;
+  () → dynamic fNowhereVoid;
+  () → dynamic fNowhereNum;
+  () → dynamic fNowhereInt;
+  () → dynamic fNowhereNever;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect
new file mode 100644
index 0000000..30ddc8d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.strong.transformed.expect
@@ -0,0 +1,234 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:13:13: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Object> aObject; // Error.
+//             ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:14:11: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num?> aNumNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:15:11: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<int?> aIntNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:16:11: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Null> aNull; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:17:21: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object> fArgumentObject; // Error.
+//                     ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:18:19: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<num?> fArgumentNumNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:19:19: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<int?> fArgumentIntNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:20:19: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Null> fArgumentNull; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:21:19: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Object> fReturnObject; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:22:17: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<num?> fReturnNumNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:23:17: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<int?> fReturnIntNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:24:17: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Null> fReturnNull; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:25:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Object> fBothObject; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:26:15: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<num?> fBothNumNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:27:15: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<int?> fBothIntNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:28:15: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Null> fBothNull; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:29:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Object> fNowhereObject; // Error.
+//                    ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:30:18: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<num?> fNowhereNumNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:31:18: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<int?> fNowhereIntNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:32:18: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Null> fNowhereNull; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef FArgument<contravariant X extends core::num = core::num> = (X) → dynamic;
+typedef FReturn<X extends core::num = core::num> = () → X;
+typedef FBoth<invariant X extends core::num = core::num> = (X) → X;
+typedef FNowhere<unrelated X extends core::num = core::num> = () → dynamic;
+class A<T extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  self::A<core::Object> aObject;
+  self::A<core::num?> aNumNullable;
+  self::A<core::int?> aIntNullable;
+  self::A<core::Null?> aNull;
+  (core::Object) → dynamic fArgumentObject;
+  (core::num?) → dynamic fArgumentNumNullable;
+  (core::int?) → dynamic fArgumentIntNullable;
+  (core::Null?) → dynamic fArgumentNull;
+  () → core::Object fReturnObject;
+  () → core::num? fReturnNumNullable;
+  () → core::int? fReturnIntNullable;
+  () → core::Null? fReturnNull;
+  (core::Object) → core::Object fBothObject;
+  (core::num?) → core::num? fBothNumNullable;
+  (core::int?) → core::int? fBothIntNullable;
+  (core::Null?) → core::Null? fBothNull;
+  () → dynamic fNowhereObject;
+  () → dynamic fNowhereNumNullable;
+  () → dynamic fNowhereIntNullable;
+  () → dynamic fNowhereNull;
+  self::A<core::Object?> aObjectNullable;
+  self::A<dynamic> aDynamic;
+  self::A<void> aVoid;
+  self::A<core::num> aNum;
+  self::A<core::int> aInt;
+  self::A<Never> aNever;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
+  (core::num) → dynamic fArgumentNum;
+  (core::int) → dynamic fArgumentInt;
+  (Never) → dynamic fArgumentNever;
+  () → core::Object? fReturnObjectNullable;
+  () → dynamic fReturnDynamic;
+  () → void fReturnVoid;
+  () → core::num fReturnNum;
+  () → core::int fReturnInt;
+  () → Never fReturnNever;
+  (core::Object?) → core::Object? fBothObjectNullable;
+  (dynamic) → dynamic fBothDynamic;
+  (void) → void fBothVoid;
+  (core::num) → core::num fBothNum;
+  (core::int) → core::int fBothInt;
+  (Never) → Never fBothNever;
+  () → dynamic fNowhereObjectNullable;
+  () → dynamic fNowhereDynamic;
+  () → dynamic fNowhereVoid;
+  () → dynamic fNowhereNum;
+  () → dynamic fNowhereInt;
+  () → dynamic fNowhereNever;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline.expect
new file mode 100644
index 0000000..f4e93b5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+class A<T extends num> {}
+
+typedef FArgument<X extends num> = Function(X);
+typedef FReturn<X extends num> = X Function();
+typedef FBoth<X extends num> = X Function(X);
+typedef FNowhere<X extends num> = Function();
+foo() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b830697
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+class A<T extends num> {}
+
+foo() {}
+main() {}
+typedef FArgument<X extends num> = Function(X);
+typedef FBoth<X extends num> = X Function(X);
+typedef FNowhere<X extends num> = Function();
+typedef FReturn<X extends num> = X Function();
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect
new file mode 100644
index 0000000..30ddc8d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.expect
@@ -0,0 +1,234 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:13:13: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Object> aObject; // Error.
+//             ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:14:11: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num?> aNumNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:15:11: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<int?> aIntNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:16:11: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Null> aNull; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:17:21: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object> fArgumentObject; // Error.
+//                     ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:18:19: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<num?> fArgumentNumNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:19:19: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<int?> fArgumentIntNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:20:19: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Null> fArgumentNull; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:21:19: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Object> fReturnObject; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:22:17: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<num?> fReturnNumNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:23:17: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<int?> fReturnIntNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:24:17: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Null> fReturnNull; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:25:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Object> fBothObject; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:26:15: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<num?> fBothNumNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:27:15: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<int?> fBothIntNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:28:15: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Null> fBothNull; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:29:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Object> fNowhereObject; // Error.
+//                    ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:30:18: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<num?> fNowhereNumNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:31:18: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<int?> fNowhereIntNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:32:18: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Null> fNowhereNull; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef FArgument<contravariant X extends core::num = core::num> = (X) → dynamic;
+typedef FReturn<X extends core::num = core::num> = () → X;
+typedef FBoth<invariant X extends core::num = core::num> = (X) → X;
+typedef FNowhere<unrelated X extends core::num = core::num> = () → dynamic;
+class A<T extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  self::A<core::Object> aObject;
+  self::A<core::num?> aNumNullable;
+  self::A<core::int?> aIntNullable;
+  self::A<core::Null?> aNull;
+  (core::Object) → dynamic fArgumentObject;
+  (core::num?) → dynamic fArgumentNumNullable;
+  (core::int?) → dynamic fArgumentIntNullable;
+  (core::Null?) → dynamic fArgumentNull;
+  () → core::Object fReturnObject;
+  () → core::num? fReturnNumNullable;
+  () → core::int? fReturnIntNullable;
+  () → core::Null? fReturnNull;
+  (core::Object) → core::Object fBothObject;
+  (core::num?) → core::num? fBothNumNullable;
+  (core::int?) → core::int? fBothIntNullable;
+  (core::Null?) → core::Null? fBothNull;
+  () → dynamic fNowhereObject;
+  () → dynamic fNowhereNumNullable;
+  () → dynamic fNowhereIntNullable;
+  () → dynamic fNowhereNull;
+  self::A<core::Object?> aObjectNullable;
+  self::A<dynamic> aDynamic;
+  self::A<void> aVoid;
+  self::A<core::num> aNum;
+  self::A<core::int> aInt;
+  self::A<Never> aNever;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
+  (core::num) → dynamic fArgumentNum;
+  (core::int) → dynamic fArgumentInt;
+  (Never) → dynamic fArgumentNever;
+  () → core::Object? fReturnObjectNullable;
+  () → dynamic fReturnDynamic;
+  () → void fReturnVoid;
+  () → core::num fReturnNum;
+  () → core::int fReturnInt;
+  () → Never fReturnNever;
+  (core::Object?) → core::Object? fBothObjectNullable;
+  (dynamic) → dynamic fBothDynamic;
+  (void) → void fBothVoid;
+  (core::num) → core::num fBothNum;
+  (core::int) → core::int fBothInt;
+  (Never) → Never fBothNever;
+  () → dynamic fNowhereObjectNullable;
+  () → dynamic fNowhereDynamic;
+  () → dynamic fNowhereVoid;
+  () → dynamic fNowhereNum;
+  () → dynamic fNowhereInt;
+  () → dynamic fNowhereNever;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect
new file mode 100644
index 0000000..30ddc8d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42429.dart.weak.transformed.expect
@@ -0,0 +1,234 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:13:13: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Object> aObject; // Error.
+//             ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:14:11: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<num?> aNumNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:15:11: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<int?> aIntNullable; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:16:11: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+// Try changing type arguments so that they conform to the bounds.
+//   A<Null> aNull; // Error.
+//           ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<T extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:17:21: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Object> fArgumentObject; // Error.
+//                     ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:18:19: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<num?> fArgumentNumNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:19:19: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<int?> fArgumentIntNullable; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:20:19: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FArgument'.
+// Try changing type arguments so that they conform to the bounds.
+//   FArgument<Null> fArgumentNull; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:7:19: Context: This is the type variable whose bound isn't conformed to.
+// typedef FArgument<X extends num> = Function(X);
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:21:19: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Object> fReturnObject; // Error.
+//                   ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:22:17: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<num?> fReturnNumNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:23:17: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<int?> fReturnIntNullable; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:24:17: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FReturn'.
+// Try changing type arguments so that they conform to the bounds.
+//   FReturn<Null> fReturnNull; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:8:17: Context: This is the type variable whose bound isn't conformed to.
+// typedef FReturn<X extends num> = X Function();
+//                 ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:25:17: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Object> fBothObject; // Error.
+//                 ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:26:15: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<num?> fBothNumNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:27:15: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<int?> fBothIntNullable; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:28:15: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FBoth'.
+// Try changing type arguments so that they conform to the bounds.
+//   FBoth<Null> fBothNull; // Error.
+//               ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:9:15: Context: This is the type variable whose bound isn't conformed to.
+// typedef FBoth<X extends num> = X Function(X);
+//               ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:29:20: Error: Type argument 'Object' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+//  - 'Object' is from 'dart:core'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Object> fNowhereObject; // Error.
+//                    ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:30:18: Error: Type argument 'num?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<num?> fNowhereNumNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:31:18: Error: Type argument 'int?' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<int?> fNowhereIntNullable; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+// pkg/front_end/testcases/nnbd/issue42429.dart:32:18: Error: Type argument 'Null' doesn't conform to the bound 'num' of the type variable 'X' on 'FNowhere'.
+// Try changing type arguments so that they conform to the bounds.
+//   FNowhere<Null> fNowhereNull; // Error.
+//                  ^
+// pkg/front_end/testcases/nnbd/issue42429.dart:10:18: Context: This is the type variable whose bound isn't conformed to.
+// typedef FNowhere<X extends num> = Function();
+//                  ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef FArgument<contravariant X extends core::num = core::num> = (X) → dynamic;
+typedef FReturn<X extends core::num = core::num> = () → X;
+typedef FBoth<invariant X extends core::num = core::num> = (X) → X;
+typedef FNowhere<unrelated X extends core::num = core::num> = () → dynamic;
+class A<T extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::A<self::A::T>
+    : super core::Object::•()
+    ;
+}
+static method foo() → dynamic {
+  self::A<core::Object> aObject;
+  self::A<core::num?> aNumNullable;
+  self::A<core::int?> aIntNullable;
+  self::A<core::Null?> aNull;
+  (core::Object) → dynamic fArgumentObject;
+  (core::num?) → dynamic fArgumentNumNullable;
+  (core::int?) → dynamic fArgumentIntNullable;
+  (core::Null?) → dynamic fArgumentNull;
+  () → core::Object fReturnObject;
+  () → core::num? fReturnNumNullable;
+  () → core::int? fReturnIntNullable;
+  () → core::Null? fReturnNull;
+  (core::Object) → core::Object fBothObject;
+  (core::num?) → core::num? fBothNumNullable;
+  (core::int?) → core::int? fBothIntNullable;
+  (core::Null?) → core::Null? fBothNull;
+  () → dynamic fNowhereObject;
+  () → dynamic fNowhereNumNullable;
+  () → dynamic fNowhereIntNullable;
+  () → dynamic fNowhereNull;
+  self::A<core::Object?> aObjectNullable;
+  self::A<dynamic> aDynamic;
+  self::A<void> aVoid;
+  self::A<core::num> aNum;
+  self::A<core::int> aInt;
+  self::A<Never> aNever;
+  (core::Object?) → dynamic fArgumentObjectNullable;
+  (dynamic) → dynamic fArgumentDynamic;
+  (void) → dynamic fArgumentVoid;
+  (core::num) → dynamic fArgumentNum;
+  (core::int) → dynamic fArgumentInt;
+  (Never) → dynamic fArgumentNever;
+  () → core::Object? fReturnObjectNullable;
+  () → dynamic fReturnDynamic;
+  () → void fReturnVoid;
+  () → core::num fReturnNum;
+  () → core::int fReturnInt;
+  () → Never fReturnNever;
+  (core::Object?) → core::Object? fBothObjectNullable;
+  (dynamic) → dynamic fBothDynamic;
+  (void) → void fBothVoid;
+  (core::num) → core::num fBothNum;
+  (core::int) → core::int fBothInt;
+  (Never) → Never fBothNever;
+  () → dynamic fNowhereObjectNullable;
+  () → dynamic fNowhereDynamic;
+  () → dynamic fNowhereVoid;
+  () → dynamic fNowhereNum;
+  () → dynamic fNowhereInt;
+  () → dynamic fNowhereNever;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
index db8fd3e..87a95fd 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.strong.transformed.expect
@@ -16,3 +16,7 @@
 constants  {
   #C1 = tearoff self::checkme
 }
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///issue42433.dart:11:16 -> PartialInstantiationConstant(checkme<X>)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
index db8fd3e..7c42561 100644
--- a/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42433.dart.weak.transformed.expect
@@ -16,3 +16,7 @@
 constants  {
   #C1 = tearoff self::checkme
 }
+
+Extra constant evaluation status:
+Evaluated: Instantiation @ org-dartlang-testcase:///issue42433.dart:11:16 -> PartialInstantiationConstant(checkme<X*>)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
index 0f8217b..baab324 100644
--- a/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42546.dart.outline.expect
@@ -29,3 +29,21 @@
 constants  {
   #C1 = null
 }
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#catchError)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:661:13 -> SymbolConstant(#test)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> SymbolConstant(#whenComplete)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:698:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#timeout)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:725:13 -> SymbolConstant(#onTimeout)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#then)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:622:13 -> SymbolConstant(#onError)
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> SymbolConstant(#asStream)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/async/future.dart:709:13 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 61, effectively constant: 15
diff --git a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.expect
index 6e4b63d..ffb6307 100644
--- a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.expect
@@ -76,218 +76,219 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method test1(Never n1, Never? n2, core::Null? n3) → dynamic {
   core::List<Never> l1 = block {
     final core::List<Never> #t1 = <Never>[];
-    for (final Never #t2 in n1)
+    for (final Never #t2 in let final Never #t3 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
       #t1.{core::List::add}(#t2);
   } =>#t1;
   core::List<Never> l2 = block {
-    final core::List<Never> #t3 = <Never>[];
-    final core::Iterable<Never>? #t4 = n1;
-    if(!#t4.{core::Object::==}(null))
-      for (final Never #t5 in #t4{core::Iterable<Never>})
-        #t3.{core::List::add}(#t5);
-  } =>#t3;
+    final core::List<Never> #t4 = <Never>[];
+    final core::Iterable<Never>? #t5 = let final Never #t6 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t5.{core::Object::==}(null))
+      for (final Never #t7 in #t5{core::Iterable<Never>})
+        #t4.{core::List::add}(#t7);
+  } =>#t4;
   core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
   var l3 = [...n2];
                ^"];
   core::List<Never> l4 = block {
-    final core::List<Never> #t6 = <Never>[];
-    final core::Iterable<Never>? #t7 = n2;
-    if(!#t7.{core::Object::==}(null))
-      for (final Never #t8 in #t7{core::Iterable<Never>})
-        #t6.{core::List::add}(#t8);
-  } =>#t6;
+    final core::List<Never> #t8 = <Never>[];
+    final core::Iterable<Never>? #t9 = n2;
+    if(!#t9.{core::Object::==}(null))
+      for (final Never #t10 in #t9{core::Iterable<Never>})
+        #t8.{core::List::add}(#t10);
+  } =>#t8;
   core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
   var l5 = [...n3];
                ^"];
   core::List<Never> l6 = block {
-    final core::List<Never> #t9 = <Never>[];
-    final core::Iterable<Never>? #t10 = n3;
-    if(!#t10.{core::Object::==}(null))
-      for (final Never #t11 in #t10{core::Iterable<Never>})
-        #t9.{core::List::add}(#t11);
-  } =>#t9;
+    final core::List<Never> #t11 = <Never>[];
+    final core::Iterable<Never>? #t12 = n3;
+    if(!#t12.{core::Object::==}(null))
+      for (final Never #t13 in #t12{core::Iterable<Never>})
+        #t11.{core::List::add}(#t13);
+  } =>#t11;
   core::Set<Never> s1 = block {
-    final core::Set<Never> #t12 = col::LinkedHashSet::•<Never>();
-    for (final Never #t13 in n1)
-      #t12.{core::Set::add}(#t13);
-    #t12.{core::Set::add}(n1);
-  } =>#t12;
-  core::Set<Never> s2 = block {
     final core::Set<Never> #t14 = col::LinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t15 = n1;
-    if(!#t15.{core::Object::==}(null))
-      for (final Never #t16 in #t15{core::Iterable<Never>})
-        #t14.{core::Set::add}(#t16);
-    #t14.{core::Set::add}(n1);
+    for (final Never #t15 in let final Never #t16 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t14.{core::Set::add}(#t15);
+    #t14.{core::Set::add}(let final Never #t17 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
   } =>#t14;
-  core::Set<dynamic> s3 = let final core::Set<dynamic> #t17 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t18 = #t17.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:14:16: Error: Can't spread a value with static type 'Never?'.
+  core::Set<Never> s2 = block {
+    final core::Set<Never> #t18 = col::LinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t19 = let final Never #t20 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t19.{core::Object::==}(null))
+      for (final Never #t21 in #t19{core::Iterable<Never>})
+        #t18.{core::Set::add}(#t21);
+    #t18.{core::Set::add}(let final Never #t22 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t18;
+  core::Set<dynamic> s3 = let final core::Set<dynamic> #t23 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t24 = #t23.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:14:16: Error: Can't spread a value with static type 'Never?'.
   var s3 = {...n2, n1};
-               ^") in let final dynamic #t19 = #t17.{core::Set::add}(n1) in #t17;
+               ^") in let final dynamic #t25 = #t23.{core::Set::add}(let final Never #t26 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t23;
   core::Set<Never> s4 = block {
-    final core::Set<Never> #t20 = col::LinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t21 = n2;
-    if(!#t21.{core::Object::==}(null))
-      for (final Never #t22 in #t21{core::Iterable<Never>})
-        #t20.{core::Set::add}(#t22);
-    #t20.{core::Set::add}(n1);
-  } =>#t20;
-  core::Set<dynamic> s5 = let final core::Set<dynamic> #t23 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t24 = #t23.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:16:16: Error: Can't spread a value with static type 'Null'.
+    final core::Set<Never> #t27 = col::LinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t28 = n2;
+    if(!#t28.{core::Object::==}(null))
+      for (final Never #t29 in #t28{core::Iterable<Never>})
+        #t27.{core::Set::add}(#t29);
+    #t27.{core::Set::add}(let final Never #t30 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t27;
+  core::Set<dynamic> s5 = let final core::Set<dynamic> #t31 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:16:16: Error: Can't spread a value with static type 'Null'.
   var s5 = {...n3, n1};
-               ^") in let final dynamic #t25 = #t23.{core::Set::add}(n1) in #t23;
+               ^") in let final dynamic #t33 = #t31.{core::Set::add}(let final Never #t34 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t31;
   core::Set<Never> s6 = block {
-    final core::Set<Never> #t26 = col::LinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t27 = n3;
-    if(!#t27.{core::Object::==}(null))
-      for (final Never #t28 in #t27{core::Iterable<Never>})
-        #t26.{core::Set::add}(#t28);
-    #t26.{core::Set::add}(n1);
-  } =>#t26;
+    final core::Set<Never> #t35 = col::LinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t36 = n3;
+    if(!#t36.{core::Object::==}(null))
+      for (final Never #t37 in #t36{core::Iterable<Never>})
+        #t35.{core::Set::add}(#t37);
+    #t35.{core::Set::add}(let final Never #t38 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t35;
   core::Map<Never, Never> m1 = block {
-    final core::Map<Never, Never> #t29 = <Never, Never>{};
-    for (final core::MapEntry<Never, Never> #t30 in n1.{core::Map::entries})
-      #t29.{core::Map::[]=}(#t30.{core::MapEntry::key}, #t30.{core::MapEntry::value});
-    #t29.{core::Map::[]=}(n1, n1);
-  } =>#t29;
+    final core::Map<Never, Never> #t39 = <Never, Never>{};
+    for (final core::MapEntry<Never, Never> #t40 in (let final Never #t41 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).{core::Map::entries})
+      #t39.{core::Map::[]=}(#t40.{core::MapEntry::key}, #t40.{core::MapEntry::value});
+    #t39.{core::Map::[]=}(let final Never #t42 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t43 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t39;
   core::Map<Never, Never> m2 = block {
-    final core::Map<Never, Never> #t31 = <Never, Never>{};
-    final core::Map<Never, Never>? #t32 = n1;
-    if(!#t32.{core::Object::==}(null))
-      for (final core::MapEntry<Never, Never> #t33 in #t32{core::Map<Never, Never>}.{core::Map::entries})
-        #t31.{core::Map::[]=}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
-    #t31.{core::Map::[]=}(n1, n1);
-  } =>#t31;
+    final core::Map<Never, Never> #t44 = <Never, Never>{};
+    final core::Map<Never, Never>? #t45 = let final Never #t46 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t45.{core::Object::==}(null))
+      for (final core::MapEntry<Never, Never> #t47 in #t45{core::Map<Never, Never>}.{core::Map::entries})
+        #t44.{core::Map::[]=}(#t47.{core::MapEntry::key}, #t47.{core::MapEntry::value});
+    #t44.{core::Map::[]=}(let final Never #t48 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t49 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t44;
   core::Map<dynamic, dynamic> m3 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:20:16: Error: Can't spread a value with static type 'Never?'.
   var m3 = {...n2, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final Never #t50 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final Never #t51 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<Never, Never> m4 = block {
-    final core::Map<Never, Never> #t34 = <Never, Never>{};
-    final core::Map<Never, Never>? #t35 = n2;
-    if(!#t35.{core::Object::==}(null))
-      for (final core::MapEntry<Never, Never> #t36 in #t35{core::Map<Never, Never>}.{core::Map::entries})
-        #t34.{core::Map::[]=}(#t36.{core::MapEntry::key}, #t36.{core::MapEntry::value});
-    #t34.{core::Map::[]=}(n1, n1);
-  } =>#t34;
+    final core::Map<Never, Never> #t52 = <Never, Never>{};
+    final core::Map<Never, Never>? #t53 = n2;
+    if(!#t53.{core::Object::==}(null))
+      for (final core::MapEntry<Never, Never> #t54 in #t53{core::Map<Never, Never>}.{core::Map::entries})
+        #t52.{core::Map::[]=}(#t54.{core::MapEntry::key}, #t54.{core::MapEntry::value});
+    #t52.{core::Map::[]=}(let final Never #t55 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t56 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t52;
   core::Map<dynamic, dynamic> m5 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:22:16: Error: Can't spread a value with static type 'Null'.
   var m5 = {...n3, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final Never #t57 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final Never #t58 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<Never, Never> m6 = block {
-    final core::Map<Never, Never> #t37 = <Never, Never>{};
-    final core::Map<Never, Never>? #t38 = n3;
-    if(!#t38.{core::Object::==}(null))
-      for (final core::MapEntry<Never, Never> #t39 in #t38{core::Map<Never, Never>}.{core::Map::entries})
-        #t37.{core::Map::[]=}(#t39.{core::MapEntry::key}, #t39.{core::MapEntry::value});
-    #t37.{core::Map::[]=}(n1, n1);
-  } =>#t37;
+    final core::Map<Never, Never> #t59 = <Never, Never>{};
+    final core::Map<Never, Never>? #t60 = n3;
+    if(!#t60.{core::Object::==}(null))
+      for (final core::MapEntry<Never, Never> #t61 in #t60{core::Map<Never, Never>}.{core::Map::entries})
+        #t59.{core::Map::[]=}(#t61.{core::MapEntry::key}, #t61.{core::MapEntry::value});
+    #t59.{core::Map::[]=}(let final Never #t62 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t63 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t59;
 }
 static method test2<N1 extends Never = Never, N2 extends Never? = Never?, N3 extends core::Null? = core::Null?>(self::test2::N1 n1, self::test2::N2% n2, self::test2::N3% n3) → dynamic {
   core::List<Never> l1 = block {
-    final core::List<Never> #t40 = <Never>[];
-    for (final Never #t41 in n1)
-      #t40.{core::List::add}(#t41);
-  } =>#t40;
+    final core::List<Never> #t64 = <Never>[];
+    for (final Never #t65 in let final self::test2::N1 #t66 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t64.{core::List::add}(#t65);
+  } =>#t64;
   core::List<Never> l2 = block {
-    final core::List<Never> #t42 = <Never>[];
-    final core::Iterable<Never>? #t43 = n1;
-    if(!#t43.{core::Object::==}(null))
-      for (final Never #t44 in #t43{core::Iterable<Never>})
-        #t42.{core::List::add}(#t44);
-  } =>#t42;
+    final core::List<Never> #t67 = <Never>[];
+    final core::Iterable<Never>? #t68 = let final self::test2::N1 #t69 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t68.{core::Object::==}(null))
+      for (final Never #t70 in #t68{core::Iterable<Never>})
+        #t67.{core::List::add}(#t70);
+  } =>#t67;
   core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
   var l3 = [...n2];
                ^"];
   core::List<Never> l4 = block {
-    final core::List<Never> #t45 = <Never>[];
-    final core::Iterable<Never>? #t46 = n2;
-    if(!#t46.{core::Object::==}(null))
-      for (final Never #t47 in #t46{core::Iterable<Never>})
-        #t45.{core::List::add}(#t47);
-  } =>#t45;
+    final core::List<Never> #t71 = <Never>[];
+    final core::Iterable<Never>? #t72 = n2;
+    if(!#t72.{core::Object::==}(null))
+      for (final Never #t73 in #t72{core::Iterable<Never>})
+        #t71.{core::List::add}(#t73);
+  } =>#t71;
   core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
   var l5 = [...n3];
                ^"];
   core::List<Never> l6 = block {
-    final core::List<Never> #t48 = <Never>[];
-    final core::Iterable<Never>? #t49 = n3;
-    if(!#t49.{core::Object::==}(null))
-      for (final Never #t50 in #t49{core::Iterable<Never>})
-        #t48.{core::List::add}(#t50);
-  } =>#t48;
+    final core::List<Never> #t74 = <Never>[];
+    final core::Iterable<Never>? #t75 = n3;
+    if(!#t75.{core::Object::==}(null))
+      for (final Never #t76 in #t75{core::Iterable<Never>})
+        #t74.{core::List::add}(#t76);
+  } =>#t74;
   core::Set<self::test2::N1> s1 = block {
-    final core::Set<self::test2::N1> #t51 = col::LinkedHashSet::•<self::test2::N1>();
-    for (final self::test2::N1 #t52 in n1)
-      #t51.{core::Set::add}(#t52);
-    #t51.{core::Set::add}(n1);
-  } =>#t51;
+    final core::Set<self::test2::N1> #t77 = col::LinkedHashSet::•<self::test2::N1>();
+    for (final self::test2::N1 #t78 in let final self::test2::N1 #t79 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t77.{core::Set::add}(#t78);
+    #t77.{core::Set::add}(let final self::test2::N1 #t80 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t77;
   core::Set<self::test2::N1> s2 = block {
-    final core::Set<self::test2::N1> #t53 = col::LinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t54 = n1;
-    if(!#t54.{core::Object::==}(null))
-      for (final self::test2::N1 #t55 in #t54{core::Iterable<self::test2::N1>})
-        #t53.{core::Set::add}(#t55);
-    #t53.{core::Set::add}(n1);
-  } =>#t53;
-  core::Set<dynamic> s3 = let final core::Set<dynamic> #t56 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:36:16: Error: Can't spread a value with static type 'N2'.
+    final core::Set<self::test2::N1> #t81 = col::LinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t82 = let final self::test2::N1 #t83 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t82.{core::Object::==}(null))
+      for (final self::test2::N1 #t84 in #t82{core::Iterable<self::test2::N1>})
+        #t81.{core::Set::add}(#t84);
+    #t81.{core::Set::add}(let final self::test2::N1 #t85 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t81;
+  core::Set<dynamic> s3 = let final core::Set<dynamic> #t86 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t87 = #t86.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:36:16: Error: Can't spread a value with static type 'N2'.
   var s3 = {...n2, n1};
-               ^") in let final dynamic #t58 = #t56.{core::Set::add}(n1) in #t56;
+               ^") in let final dynamic #t88 = #t86.{core::Set::add}(let final self::test2::N1 #t89 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t86;
   core::Set<self::test2::N1> s4 = block {
-    final core::Set<self::test2::N1> #t59 = col::LinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t60 = n2;
-    if(!#t60.{core::Object::==}(null))
-      for (final self::test2::N1 #t61 in #t60{core::Iterable<self::test2::N1>})
-        #t59.{core::Set::add}(#t61);
-    #t59.{core::Set::add}(n1);
-  } =>#t59;
-  core::Set<dynamic> s5 = let final core::Set<dynamic> #t62 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:38:16: Error: Can't spread a value with static type 'N3'.
+    final core::Set<self::test2::N1> #t90 = col::LinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t91 = n2;
+    if(!#t91.{core::Object::==}(null))
+      for (final self::test2::N1 #t92 in #t91{core::Iterable<self::test2::N1>})
+        #t90.{core::Set::add}(#t92);
+    #t90.{core::Set::add}(let final self::test2::N1 #t93 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t90;
+  core::Set<dynamic> s5 = let final core::Set<dynamic> #t94 = col::LinkedHashSet::•<dynamic>() in let final dynamic #t95 = #t94.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:38:16: Error: Can't spread a value with static type 'N3'.
   var s5 = {...n3, n1};
-               ^") in let final dynamic #t64 = #t62.{core::Set::add}(n1) in #t62;
+               ^") in let final dynamic #t96 = #t94.{core::Set::add}(let final self::test2::N1 #t97 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t94;
   core::Set<self::test2::N1> s6 = block {
-    final core::Set<self::test2::N1> #t65 = col::LinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t66 = n3;
-    if(!#t66.{core::Object::==}(null))
-      for (final self::test2::N1 #t67 in #t66{core::Iterable<self::test2::N1>})
-        #t65.{core::Set::add}(#t67);
-    #t65.{core::Set::add}(n1);
-  } =>#t65;
+    final core::Set<self::test2::N1> #t98 = col::LinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t99 = n3;
+    if(!#t99.{core::Object::==}(null))
+      for (final self::test2::N1 #t100 in #t99{core::Iterable<self::test2::N1>})
+        #t98.{core::Set::add}(#t100);
+    #t98.{core::Set::add}(let final self::test2::N1 #t101 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t98;
   core::Map<self::test2::N1, self::test2::N1> m1 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t68 = <self::test2::N1, self::test2::N1>{};
-    for (final core::MapEntry<self::test2::N1, self::test2::N1> #t69 in n1.{core::Map::entries})
-      #t68.{core::Map::[]=}(#t69.{core::MapEntry::key}, #t69.{core::MapEntry::value});
-    #t68.{core::Map::[]=}(n1, n1);
-  } =>#t68;
+    final core::Map<self::test2::N1, self::test2::N1> #t102 = <self::test2::N1, self::test2::N1>{};
+    for (final core::MapEntry<self::test2::N1, self::test2::N1> #t103 in (let final self::test2::N1 #t104 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).{core::Map::entries})
+      #t102.{core::Map::[]=}(#t103.{core::MapEntry::key}, #t103.{core::MapEntry::value});
+    #t102.{core::Map::[]=}(let final self::test2::N1 #t105 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t106 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t102;
   core::Map<self::test2::N1, self::test2::N1> m2 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t70 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t71 = n1;
-    if(!#t71.{core::Object::==}(null))
-      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t72 in #t71{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
-        #t70.{core::Map::[]=}(#t72.{core::MapEntry::key}, #t72.{core::MapEntry::value});
-    #t70.{core::Map::[]=}(n1, n1);
-  } =>#t70;
+    final core::Map<self::test2::N1, self::test2::N1> #t107 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t108 = let final self::test2::N1 #t109 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t108.{core::Object::==}(null))
+      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t110 in #t108{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
+        #t107.{core::Map::[]=}(#t110.{core::MapEntry::key}, #t110.{core::MapEntry::value});
+    #t107.{core::Map::[]=}(let final self::test2::N1 #t111 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t112 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t107;
   core::Map<dynamic, dynamic> m3 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:42:16: Error: Can't spread a value with static type 'N2'.
   var m3 = {...n2, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final self::test2::N1 #t113 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final self::test2::N1 #t114 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<self::test2::N1, self::test2::N1> m4 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t73 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t74 = n2;
-    if(!#t74.{core::Object::==}(null))
-      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t75 in #t74{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
-        #t73.{core::Map::[]=}(#t75.{core::MapEntry::key}, #t75.{core::MapEntry::value});
-    #t73.{core::Map::[]=}(n1, n1);
-  } =>#t73;
+    final core::Map<self::test2::N1, self::test2::N1> #t115 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t116 = n2;
+    if(!#t116.{core::Object::==}(null))
+      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t117 in #t116{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
+        #t115.{core::Map::[]=}(#t117.{core::MapEntry::key}, #t117.{core::MapEntry::value});
+    #t115.{core::Map::[]=}(let final self::test2::N1 #t118 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t119 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t115;
   core::Map<dynamic, dynamic> m5 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:44:16: Error: Can't spread a value with static type 'N3'.
   var m5 = {...n3, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final self::test2::N1 #t120 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final self::test2::N1 #t121 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<self::test2::N1, self::test2::N1> m6 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t76 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t77 = n3;
-    if(!#t77.{core::Object::==}(null))
-      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t78 in #t77{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
-        #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
-    #t76.{core::Map::[]=}(n1, n1);
-  } =>#t76;
+    final core::Map<self::test2::N1, self::test2::N1> #t122 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t123 = n3;
+    if(!#t123.{core::Object::==}(null))
+      for (final core::MapEntry<self::test2::N1, self::test2::N1> #t124 in #t123{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries})
+        #t122.{core::Map::[]=}(#t124.{core::MapEntry::key}, #t124.{core::MapEntry::value});
+    #t122.{core::Map::[]=}(let final self::test2::N1 #t125 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t126 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t122;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
index 97d6ebf..1e59eae 100644
--- a/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue42758.dart.weak.transformed.expect
@@ -76,300 +76,301 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 import "dart:collection" as col;
 
 static method test1(Never n1, Never? n2, core::Null? n3) → dynamic {
   core::List<Never> l1 = block {
     final core::List<Never> #t1 = <Never>[];
-    for (final Never #t2 in n1)
+    for (final Never #t2 in let final Never #t3 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
       #t1.{core::List::add}(#t2);
   } =>#t1;
   core::List<Never> l2 = block {
-    final core::List<Never> #t3 = <Never>[];
-    final core::Iterable<Never>? #t4 = n1;
-    if(!#t4.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t4{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t4 = <Never>[];
+    final core::Iterable<Never>? #t5 = let final Never #t6 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t5.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t5{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t5 = :sync-for-iterator.{core::Iterator::current};
-        #t3.{core::List::add}(#t5);
+        final Never #t7 = :sync-for-iterator.{core::Iterator::current};
+        #t4.{core::List::add}(#t7);
       }
     }
-  } =>#t3;
+  } =>#t4;
   core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:8:16: Error: Can't spread a value with static type 'Never?'.
   var l3 = [...n2];
                ^"];
   core::List<Never> l4 = block {
-    final core::List<Never> #t6 = <Never>[];
-    final core::Iterable<Never>? #t7 = n2;
-    if(!#t7.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t7{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t8 = <Never>[];
+    final core::Iterable<Never>? #t9 = n2;
+    if(!#t9.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t9{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t8 = :sync-for-iterator.{core::Iterator::current};
-        #t6.{core::List::add}(#t8);
+        final Never #t10 = :sync-for-iterator.{core::Iterator::current};
+        #t8.{core::List::add}(#t10);
       }
     }
-  } =>#t6;
+  } =>#t8;
   core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:10:16: Error: Can't spread a value with static type 'Null'.
   var l5 = [...n3];
                ^"];
   core::List<Never> l6 = block {
-    final core::List<Never> #t9 = <Never>[];
-    final core::Iterable<Never>? #t10 = n3;
-    if(!#t10.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t10{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t11 = <Never>[];
+    final core::Iterable<Never>? #t12 = n3;
+    if(!#t12.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t12{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t11 = :sync-for-iterator.{core::Iterator::current};
-        #t9.{core::List::add}(#t11);
+        final Never #t13 = :sync-for-iterator.{core::Iterator::current};
+        #t11.{core::List::add}(#t13);
       }
     }
-  } =>#t9;
+  } =>#t11;
   core::Set<Never> s1 = block {
-    final core::Set<Never> #t12 = new col::_CompactLinkedHashSet::•<Never>();
-    for (final Never #t13 in n1)
-      #t12.{core::Set::add}(#t13);
-    #t12.{core::Set::add}(n1);
-  } =>#t12;
-  core::Set<Never> s2 = block {
     final core::Set<Never> #t14 = new col::_CompactLinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t15 = n1;
-    if(!#t15.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t15{core::Iterable<Never>}.{core::Iterable::iterator};
-      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t16 = :sync-for-iterator.{core::Iterator::current};
-        #t14.{core::Set::add}(#t16);
-      }
-    }
-    #t14.{core::Set::add}(n1);
+    for (final Never #t15 in let final Never #t16 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t14.{core::Set::add}(#t15);
+    #t14.{core::Set::add}(let final Never #t17 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
   } =>#t14;
-  core::Set<dynamic> s3 = let final core::Set<dynamic> #t17 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t18 = #t17.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:14:16: Error: Can't spread a value with static type 'Never?'.
+  core::Set<Never> s2 = block {
+    final core::Set<Never> #t18 = new col::_CompactLinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t19 = let final Never #t20 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t19.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t19{core::Iterable<Never>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final Never #t21 = :sync-for-iterator.{core::Iterator::current};
+        #t18.{core::Set::add}(#t21);
+      }
+    }
+    #t18.{core::Set::add}(let final Never #t22 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t18;
+  core::Set<dynamic> s3 = let final core::Set<dynamic> #t23 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t24 = #t23.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:14:16: Error: Can't spread a value with static type 'Never?'.
   var s3 = {...n2, n1};
-               ^") in let final core::bool #t19 = #t17.{core::Set::add}(n1) in #t17;
+               ^") in let final core::bool #t25 = #t23.{core::Set::add}(let final Never #t26 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t23;
   core::Set<Never> s4 = block {
-    final core::Set<Never> #t20 = new col::_CompactLinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t21 = n2;
-    if(!#t21.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t21{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::Set<Never> #t27 = new col::_CompactLinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t28 = n2;
+    if(!#t28.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t28{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t22 = :sync-for-iterator.{core::Iterator::current};
-        #t20.{core::Set::add}(#t22);
+        final Never #t29 = :sync-for-iterator.{core::Iterator::current};
+        #t27.{core::Set::add}(#t29);
       }
     }
-    #t20.{core::Set::add}(n1);
-  } =>#t20;
-  core::Set<dynamic> s5 = let final core::Set<dynamic> #t23 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t24 = #t23.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:16:16: Error: Can't spread a value with static type 'Null'.
+    #t27.{core::Set::add}(let final Never #t30 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t27;
+  core::Set<dynamic> s5 = let final core::Set<dynamic> #t31 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t32 = #t31.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:16:16: Error: Can't spread a value with static type 'Null'.
   var s5 = {...n3, n1};
-               ^") in let final core::bool #t25 = #t23.{core::Set::add}(n1) in #t23;
+               ^") in let final core::bool #t33 = #t31.{core::Set::add}(let final Never #t34 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t31;
   core::Set<Never> s6 = block {
-    final core::Set<Never> #t26 = new col::_CompactLinkedHashSet::•<Never>();
-    final core::Iterable<Never>? #t27 = n3;
-    if(!#t27.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t27{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::Set<Never> #t35 = new col::_CompactLinkedHashSet::•<Never>();
+    final core::Iterable<Never>? #t36 = n3;
+    if(!#t36.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t36{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t28 = :sync-for-iterator.{core::Iterator::current};
-        #t26.{core::Set::add}(#t28);
+        final Never #t37 = :sync-for-iterator.{core::Iterator::current};
+        #t35.{core::Set::add}(#t37);
       }
     }
-    #t26.{core::Set::add}(n1);
-  } =>#t26;
+    #t35.{core::Set::add}(let final Never #t38 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t35;
   core::Map<Never, Never> m1 = block {
-    final core::Map<Never, Never> #t29 = <Never, Never>{};
+    final core::Map<Never, Never> #t39 = <Never, Never>{};
     {
-      core::Iterator<core::MapEntry<<BottomType>, <BottomType>>> :sync-for-iterator = n1.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<<BottomType>, <BottomType>>> :sync-for-iterator = (let final Never #t40 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<Never, Never> #t30 = :sync-for-iterator.{core::Iterator::current};
-        #t29.{core::Map::[]=}(#t30.{core::MapEntry::key}, #t30.{core::MapEntry::value});
+        final core::MapEntry<Never, Never> #t41 = :sync-for-iterator.{core::Iterator::current};
+        #t39.{core::Map::[]=}(#t41.{core::MapEntry::key}, #t41.{core::MapEntry::value});
       }
     }
-    #t29.{core::Map::[]=}(n1, n1);
-  } =>#t29;
+    #t39.{core::Map::[]=}(let final Never #t42 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t43 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t39;
   core::Map<Never, Never> m2 = block {
-    final core::Map<Never, Never> #t31 = <Never, Never>{};
-    final core::Map<Never, Never>? #t32 = n1;
-    if(!#t32.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t32{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<Never, Never> #t44 = <Never, Never>{};
+    final core::Map<Never, Never>? #t45 = let final Never #t46 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t45.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t45{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<Never, Never> #t33 = :sync-for-iterator.{core::Iterator::current};
-        #t31.{core::Map::[]=}(#t33.{core::MapEntry::key}, #t33.{core::MapEntry::value});
+        final core::MapEntry<Never, Never> #t47 = :sync-for-iterator.{core::Iterator::current};
+        #t44.{core::Map::[]=}(#t47.{core::MapEntry::key}, #t47.{core::MapEntry::value});
       }
     }
-    #t31.{core::Map::[]=}(n1, n1);
-  } =>#t31;
+    #t44.{core::Map::[]=}(let final Never #t48 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t49 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t44;
   core::Map<dynamic, dynamic> m3 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:20:16: Error: Can't spread a value with static type 'Never?'.
   var m3 = {...n2, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final Never #t50 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final Never #t51 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<Never, Never> m4 = block {
-    final core::Map<Never, Never> #t34 = <Never, Never>{};
-    final core::Map<Never, Never>? #t35 = n2;
-    if(!#t35.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t35{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<Never, Never> #t52 = <Never, Never>{};
+    final core::Map<Never, Never>? #t53 = n2;
+    if(!#t53.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t53{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<Never, Never> #t36 = :sync-for-iterator.{core::Iterator::current};
-        #t34.{core::Map::[]=}(#t36.{core::MapEntry::key}, #t36.{core::MapEntry::value});
+        final core::MapEntry<Never, Never> #t54 = :sync-for-iterator.{core::Iterator::current};
+        #t52.{core::Map::[]=}(#t54.{core::MapEntry::key}, #t54.{core::MapEntry::value});
       }
     }
-    #t34.{core::Map::[]=}(n1, n1);
-  } =>#t34;
+    #t52.{core::Map::[]=}(let final Never #t55 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t56 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t52;
   core::Map<dynamic, dynamic> m5 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:22:16: Error: Can't spread a value with static type 'Null'.
   var m5 = {...n3, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final Never #t57 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final Never #t58 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<Never, Never> m6 = block {
-    final core::Map<Never, Never> #t37 = <Never, Never>{};
-    final core::Map<Never, Never>? #t38 = n3;
-    if(!#t38.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t38{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<Never, Never> #t59 = <Never, Never>{};
+    final core::Map<Never, Never>? #t60 = n3;
+    if(!#t60.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<Never, Never>> :sync-for-iterator = #t60{core::Map<Never, Never>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<Never, Never> #t39 = :sync-for-iterator.{core::Iterator::current};
-        #t37.{core::Map::[]=}(#t39.{core::MapEntry::key}, #t39.{core::MapEntry::value});
+        final core::MapEntry<Never, Never> #t61 = :sync-for-iterator.{core::Iterator::current};
+        #t59.{core::Map::[]=}(#t61.{core::MapEntry::key}, #t61.{core::MapEntry::value});
       }
     }
-    #t37.{core::Map::[]=}(n1, n1);
-  } =>#t37;
+    #t59.{core::Map::[]=}(let final Never #t62 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final Never #t63 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t59;
 }
 static method test2<N1 extends Never = Never, N2 extends Never? = Never?, N3 extends core::Null? = core::Null?>(self::test2::N1 n1, self::test2::N2% n2, self::test2::N3% n3) → dynamic {
   core::List<Never> l1 = block {
-    final core::List<Never> #t40 = <Never>[];
-    for (final Never #t41 in n1)
-      #t40.{core::List::add}(#t41);
-  } =>#t40;
+    final core::List<Never> #t64 = <Never>[];
+    for (final Never #t65 in let final self::test2::N1 #t66 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t64.{core::List::add}(#t65);
+  } =>#t64;
   core::List<Never> l2 = block {
-    final core::List<Never> #t42 = <Never>[];
-    final core::Iterable<Never>? #t43 = n1;
-    if(!#t43.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t43{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t67 = <Never>[];
+    final core::Iterable<Never>? #t68 = let final self::test2::N1 #t69 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t68.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t68{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t44 = :sync-for-iterator.{core::Iterator::current};
-        #t42.{core::List::add}(#t44);
+        final Never #t70 = :sync-for-iterator.{core::Iterator::current};
+        #t67.{core::List::add}(#t70);
       }
     }
-  } =>#t42;
+  } =>#t67;
   core::List<dynamic> l3 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:30:16: Error: Can't spread a value with static type 'N2'.
   var l3 = [...n2];
                ^"];
   core::List<Never> l4 = block {
-    final core::List<Never> #t45 = <Never>[];
-    final core::Iterable<Never>? #t46 = n2;
-    if(!#t46.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t46{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t71 = <Never>[];
+    final core::Iterable<Never>? #t72 = n2;
+    if(!#t72.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t72{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t47 = :sync-for-iterator.{core::Iterator::current};
-        #t45.{core::List::add}(#t47);
+        final Never #t73 = :sync-for-iterator.{core::Iterator::current};
+        #t71.{core::List::add}(#t73);
       }
     }
-  } =>#t45;
+  } =>#t71;
   core::List<dynamic> l5 = <dynamic>[invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:32:16: Error: Can't spread a value with static type 'N3'.
   var l5 = [...n3];
                ^"];
   core::List<Never> l6 = block {
-    final core::List<Never> #t48 = <Never>[];
-    final core::Iterable<Never>? #t49 = n3;
-    if(!#t49.{core::Object::==}(null)) {
-      core::Iterator<Never> :sync-for-iterator = #t49{core::Iterable<Never>}.{core::Iterable::iterator};
+    final core::List<Never> #t74 = <Never>[];
+    final core::Iterable<Never>? #t75 = n3;
+    if(!#t75.{core::Object::==}(null)) {
+      core::Iterator<Never> :sync-for-iterator = #t75{core::Iterable<Never>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final Never #t50 = :sync-for-iterator.{core::Iterator::current};
-        #t48.{core::List::add}(#t50);
+        final Never #t76 = :sync-for-iterator.{core::Iterator::current};
+        #t74.{core::List::add}(#t76);
       }
     }
-  } =>#t48;
+  } =>#t74;
   core::Set<self::test2::N1> s1 = block {
-    final core::Set<self::test2::N1> #t51 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
-    for (final self::test2::N1 #t52 in n1)
-      #t51.{core::Set::add}(#t52);
-    #t51.{core::Set::add}(n1);
-  } =>#t51;
+    final core::Set<self::test2::N1> #t77 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
+    for (final self::test2::N1 #t78 in let final self::test2::N1 #t79 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."))
+      #t77.{core::Set::add}(#t78);
+    #t77.{core::Set::add}(let final self::test2::N1 #t80 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t77;
   core::Set<self::test2::N1> s2 = block {
-    final core::Set<self::test2::N1> #t53 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t54 = n1;
-    if(!#t54.{core::Object::==}(null)) {
-      core::Iterator<self::test2::N1> :sync-for-iterator = #t54{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
+    final core::Set<self::test2::N1> #t81 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t82 = let final self::test2::N1 #t83 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t82.{core::Object::==}(null)) {
+      core::Iterator<self::test2::N1> :sync-for-iterator = #t82{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final self::test2::N1 #t55 = :sync-for-iterator.{core::Iterator::current};
-        #t53.{core::Set::add}(#t55);
+        final self::test2::N1 #t84 = :sync-for-iterator.{core::Iterator::current};
+        #t81.{core::Set::add}(#t84);
       }
     }
-    #t53.{core::Set::add}(n1);
-  } =>#t53;
-  core::Set<dynamic> s3 = let final core::Set<dynamic> #t56 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t57 = #t56.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:36:16: Error: Can't spread a value with static type 'N2'.
+    #t81.{core::Set::add}(let final self::test2::N1 #t85 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t81;
+  core::Set<dynamic> s3 = let final core::Set<dynamic> #t86 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t87 = #t86.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:36:16: Error: Can't spread a value with static type 'N2'.
   var s3 = {...n2, n1};
-               ^") in let final core::bool #t58 = #t56.{core::Set::add}(n1) in #t56;
+               ^") in let final core::bool #t88 = #t86.{core::Set::add}(let final self::test2::N1 #t89 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t86;
   core::Set<self::test2::N1> s4 = block {
-    final core::Set<self::test2::N1> #t59 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t60 = n2;
-    if(!#t60.{core::Object::==}(null)) {
-      core::Iterator<self::test2::N1> :sync-for-iterator = #t60{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
+    final core::Set<self::test2::N1> #t90 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t91 = n2;
+    if(!#t91.{core::Object::==}(null)) {
+      core::Iterator<self::test2::N1> :sync-for-iterator = #t91{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final self::test2::N1 #t61 = :sync-for-iterator.{core::Iterator::current};
-        #t59.{core::Set::add}(#t61);
+        final self::test2::N1 #t92 = :sync-for-iterator.{core::Iterator::current};
+        #t90.{core::Set::add}(#t92);
       }
     }
-    #t59.{core::Set::add}(n1);
-  } =>#t59;
-  core::Set<dynamic> s5 = let final core::Set<dynamic> #t62 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t63 = #t62.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:38:16: Error: Can't spread a value with static type 'N3'.
+    #t90.{core::Set::add}(let final self::test2::N1 #t93 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t90;
+  core::Set<dynamic> s5 = let final core::Set<dynamic> #t94 = new col::_CompactLinkedHashSet::•<dynamic>() in let final core::bool #t95 = #t94.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:38:16: Error: Can't spread a value with static type 'N3'.
   var s5 = {...n3, n1};
-               ^") in let final core::bool #t64 = #t62.{core::Set::add}(n1) in #t62;
+               ^") in let final core::bool #t96 = #t94.{core::Set::add}(let final self::test2::N1 #t97 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in #t94;
   core::Set<self::test2::N1> s6 = block {
-    final core::Set<self::test2::N1> #t65 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
-    final core::Iterable<self::test2::N1>? #t66 = n3;
-    if(!#t66.{core::Object::==}(null)) {
-      core::Iterator<self::test2::N1> :sync-for-iterator = #t66{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
+    final core::Set<self::test2::N1> #t98 = new col::_CompactLinkedHashSet::•<self::test2::N1>();
+    final core::Iterable<self::test2::N1>? #t99 = n3;
+    if(!#t99.{core::Object::==}(null)) {
+      core::Iterator<self::test2::N1> :sync-for-iterator = #t99{core::Iterable<self::test2::N1>}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final self::test2::N1 #t67 = :sync-for-iterator.{core::Iterator::current};
-        #t65.{core::Set::add}(#t67);
+        final self::test2::N1 #t100 = :sync-for-iterator.{core::Iterator::current};
+        #t98.{core::Set::add}(#t100);
       }
     }
-    #t65.{core::Set::add}(n1);
-  } =>#t65;
+    #t98.{core::Set::add}(let final self::test2::N1 #t101 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t98;
   core::Map<self::test2::N1, self::test2::N1> m1 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t68 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1> #t102 = <self::test2::N1, self::test2::N1>{};
     {
-      core::Iterator<core::MapEntry<<BottomType>, <BottomType>>> :sync-for-iterator = n1.{core::Map::entries}.{core::Iterable::iterator};
+      core::Iterator<core::MapEntry<<BottomType>, <BottomType>>> :sync-for-iterator = (let final self::test2::N1 #t103 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<self::test2::N1, self::test2::N1> #t69 = :sync-for-iterator.{core::Iterator::current};
-        #t68.{core::Map::[]=}(#t69.{core::MapEntry::key}, #t69.{core::MapEntry::value});
+        final core::MapEntry<self::test2::N1, self::test2::N1> #t104 = :sync-for-iterator.{core::Iterator::current};
+        #t102.{core::Map::[]=}(#t104.{core::MapEntry::key}, #t104.{core::MapEntry::value});
       }
     }
-    #t68.{core::Map::[]=}(n1, n1);
-  } =>#t68;
+    #t102.{core::Map::[]=}(let final self::test2::N1 #t105 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t106 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t102;
   core::Map<self::test2::N1, self::test2::N1> m2 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t70 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t71 = n1;
-    if(!#t71.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t71{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<self::test2::N1, self::test2::N1> #t107 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t108 = let final self::test2::N1 #t109 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+    if(!#t108.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t108{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<self::test2::N1, self::test2::N1> #t72 = :sync-for-iterator.{core::Iterator::current};
-        #t70.{core::Map::[]=}(#t72.{core::MapEntry::key}, #t72.{core::MapEntry::value});
+        final core::MapEntry<self::test2::N1, self::test2::N1> #t110 = :sync-for-iterator.{core::Iterator::current};
+        #t107.{core::Map::[]=}(#t110.{core::MapEntry::key}, #t110.{core::MapEntry::value});
       }
     }
-    #t70.{core::Map::[]=}(n1, n1);
-  } =>#t70;
+    #t107.{core::Map::[]=}(let final self::test2::N1 #t111 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t112 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t107;
   core::Map<dynamic, dynamic> m3 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:42:16: Error: Can't spread a value with static type 'N2'.
   var m3 = {...n2, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final self::test2::N1 #t113 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final self::test2::N1 #t114 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<self::test2::N1, self::test2::N1> m4 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t73 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t74 = n2;
-    if(!#t74.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t74{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<self::test2::N1, self::test2::N1> #t115 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t116 = n2;
+    if(!#t116.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t116{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<self::test2::N1, self::test2::N1> #t75 = :sync-for-iterator.{core::Iterator::current};
-        #t73.{core::Map::[]=}(#t75.{core::MapEntry::key}, #t75.{core::MapEntry::value});
+        final core::MapEntry<self::test2::N1, self::test2::N1> #t117 = :sync-for-iterator.{core::Iterator::current};
+        #t115.{core::Map::[]=}(#t117.{core::MapEntry::key}, #t117.{core::MapEntry::value});
       }
     }
-    #t73.{core::Map::[]=}(n1, n1);
-  } =>#t73;
+    #t115.{core::Map::[]=}(let final self::test2::N1 #t118 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t119 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t115;
   core::Map<dynamic, dynamic> m5 = <dynamic, dynamic>{invalid-expression "pkg/front_end/testcases/nnbd/issue42758.dart:44:16: Error: Can't spread a value with static type 'N3'.
   var m5 = {...n3, n1: n1};
-               ^": null, n1: n1};
+               ^": null, let final self::test2::N1 #t120 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."): let final self::test2::N1 #t121 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")};
   core::Map<self::test2::N1, self::test2::N1> m6 = block {
-    final core::Map<self::test2::N1, self::test2::N1> #t76 = <self::test2::N1, self::test2::N1>{};
-    final core::Map<self::test2::N1, self::test2::N1>? #t77 = n3;
-    if(!#t77.{core::Object::==}(null)) {
-      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t77{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
+    final core::Map<self::test2::N1, self::test2::N1> #t122 = <self::test2::N1, self::test2::N1>{};
+    final core::Map<self::test2::N1, self::test2::N1>? #t123 = n3;
+    if(!#t123.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<self::test2::N1, self::test2::N1>> :sync-for-iterator = #t123{core::Map<self::test2::N1, self::test2::N1>}.{core::Map::entries}.{core::Iterable::iterator};
       for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
-        final core::MapEntry<self::test2::N1, self::test2::N1> #t78 = :sync-for-iterator.{core::Iterator::current};
-        #t76.{core::Map::[]=}(#t78.{core::MapEntry::key}, #t78.{core::MapEntry::value});
+        final core::MapEntry<self::test2::N1, self::test2::N1> #t124 = :sync-for-iterator.{core::Iterator::current};
+        #t122.{core::Map::[]=}(#t124.{core::MapEntry::key}, #t124.{core::MapEntry::value});
       }
     }
-    #t76.{core::Map::[]=}(n1, n1);
-  } =>#t76;
+    #t122.{core::Map::[]=}(let final self::test2::N1 #t125 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."), let final self::test2::N1 #t126 = n1 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`."));
+  } =>#t122;
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart b/pkg/front_end/testcases/nnbd/issue42844_1.dart
new file mode 100644
index 0000000..6f9e7d2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  Never n; // Error.
+
+  factory C(Never n) = D;
+}
+
+class D implements C {
+  Never n;
+
+  D(this.n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect
new file mode 100644
index 0000000..a52904f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.outline.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field Never n;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(Never n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  field Never n;
+  constructor •(Never n) → self::D
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect
new file mode 100644
index 0000000..9f1d04c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_1.dart:6:9: Error: Field 'n' should be initialized because its type 'Never' doesn't allow null.
+//   Never n; // Error.
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field Never n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(Never n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  field Never n;
+  constructor •(Never n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect
new file mode 100644
index 0000000..7a9d7ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.strong.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_1.dart:6:9: Error: Field 'n' should be initialized because its type 'Never' doesn't allow null.
+//   Never n; // Error.
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field Never n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(Never n) → self::C
+    let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  field Never n;
+  constructor •(Never n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline.expect
new file mode 100644
index 0000000..5449b69
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+class C {
+  Never n;
+  factory C(Never n) = D;
+}
+
+class D implements C {
+  Never n;
+  D(this.n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..df335e7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class C {
+  Never n;
+  factory C(Never n) = D;
+}
+
+class D implements C {
+  D(this.n);
+  Never n;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect
new file mode 100644
index 0000000..9f1d04c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_1.dart:6:9: Error: Field 'n' should be initialized because its type 'Never' doesn't allow null.
+//   Never n; // Error.
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field Never n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(Never n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  field Never n;
+  constructor •(Never n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect
new file mode 100644
index 0000000..7a9d7ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_1.dart.weak.transformed.expect
@@ -0,0 +1,24 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_1.dart:6:9: Error: Field 'n' should be initialized because its type 'Never' doesn't allow null.
+//   Never n; // Error.
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  field Never n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(Never n) → self::C
+    let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  field Never n;
+  constructor •(Never n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart b/pkg/front_end/testcases/nnbd/issue42844_2.dart
new file mode 100644
index 0000000..544e1aa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  final dynamic n; // Error.
+
+  factory C(dynamic n) = D;
+}
+
+class D implements C {
+  final dynamic n;
+
+  D(this.n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect
new file mode 100644
index 0000000..40df7c4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.outline.expect
@@ -0,0 +1,17 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field dynamic n;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(dynamic n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  final field dynamic n;
+  constructor •(dynamic n) → self::D
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect
new file mode 100644
index 0000000..afaa082
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_2.dart:6:17: Error: Final field 'n' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic n; // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field dynamic n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(dynamic n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  final field dynamic n;
+  constructor •(dynamic n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect
new file mode 100644
index 0000000..4e1efe4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_2.dart:6:17: Error: Final field 'n' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic n; // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field dynamic n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(dynamic n) → self::C
+    let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  final field dynamic n;
+  constructor •(dynamic n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline.expect
new file mode 100644
index 0000000..dc93ebc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+class C {
+  final dynamic n;
+  factory C(dynamic n) = D;
+}
+
+class D implements C {
+  final dynamic n;
+  D(this.n);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8402c4d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.textual_outline_modelled.expect
@@ -0,0 +1,11 @@
+class C {
+  factory C(dynamic n) = D;
+  final dynamic n;
+}
+
+class D implements C {
+  D(this.n);
+  final dynamic n;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect
new file mode 100644
index 0000000..afaa082
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_2.dart:6:17: Error: Final field 'n' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic n; // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field dynamic n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(dynamic n) → self::C
+    let dynamic #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  final field dynamic n;
+  constructor •(dynamic n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect
new file mode 100644
index 0000000..4e1efe4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42844_2.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42844_2.dart:6:17: Error: Final field 'n' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic n; // Error.
+//                 ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+  final field dynamic n = null;
+  static field dynamic _redirecting# = <dynamic>[self::C::•]/*isNullableByDefault*/;
+  static factory •(dynamic n) → self::C
+    let<BottomType> #redirecting_factory = self::D::• in invalid-expression;
+}
+class D extends core::Object implements self::C {
+  final field dynamic n;
+  constructor •(dynamic n) → self::D
+    : self::D::n = n, super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart b/pkg/front_end/testcases/nnbd/issue42967.dart
new file mode 100644
index 0000000..e2e39a7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Class A has no constructors.
+class A {
+  num fieldNonNullableOfA; // Error.
+  late num fieldLateNonNullableOfA; // Ok.
+
+  final dynamic fieldFinalDynamicOfA; // Error.
+  late final dynamic fieldLateFinalDynamicOfA; // Ok.
+}
+
+// Class AbstractA has no constructors.
+abstract class AbstractA {
+  external num fieldExternalNonNullableOfAbstractA; // Ok.
+  abstract num fieldAbstractNonNullableOfAbstractA; // Ok.
+
+  external final dynamic fieldExternalFinalDynamicOfAbstractA; // Ok.
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractA; // Ok.
+}
+
+
+// Class B has only factory constructors.
+class B {
+  num fieldNonNullableOfB; // Error.
+  late num fieldLateNonNullableOfB; // Ok.
+
+  final dynamic fieldFinalDynamicOfB; // Error.
+  late final dynamic fieldLateFinalDynamicOfB; // Ok.
+
+  factory B() => throw 42;
+}
+
+// Class AbstractB has only factory constructors.
+abstract class AbstractB {
+  external num fieldExternalNonNullableOfAbstractB; // Ok.
+  abstract num fieldAbstractNonNullableOfAbstractB; // Ok.
+
+  external final dynamic fieldExternalFinalDynamicOfAbstractB; // Ok.
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractB; // Ok.
+}
+
+mixin M {
+  num fieldNonNullableOfM; // Error.
+  late num fieldLateNonNullableOfM; // Ok.
+  external num fieldExternalNonNullableOfM; // Ok.
+  abstract num fieldAbstractNonNullableOfM; // Ok.
+
+  final dynamic fieldFinalDynamicOfM; // Error.
+  late final dynamic fieldLateFinalDynamicOfM; // Ok.
+  external final dynamic fieldExternalFinalDynamicOfM; // Ok.
+  abstract final dynamic fieldAbstractFinalDynamicOfM; // Ok.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.outline.expect
new file mode 100644
index 0000000..12ac249
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.outline.expect
@@ -0,0 +1,54 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num fieldNonNullableOfA;
+  late field core::num fieldLateNonNullableOfA;
+  final field dynamic fieldFinalDynamicOfA;
+  late final [setter] field dynamic fieldLateFinalDynamicOfA;
+  synthetic constructor •() → self::A
+    ;
+}
+abstract class AbstractA extends core::Object {
+  synthetic constructor •() → self::AbstractA
+    ;
+  external get fieldExternalNonNullableOfAbstractA() → core::num;
+  external set fieldExternalNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractA() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractA() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractA() → dynamic;
+}
+class B extends core::Object {
+  field core::num fieldNonNullableOfB;
+  late field core::num fieldLateNonNullableOfB;
+  final field dynamic fieldFinalDynamicOfB;
+  late final [setter] field dynamic fieldLateFinalDynamicOfB;
+  static factory •() → self::B
+    ;
+}
+abstract class AbstractB extends core::Object {
+  synthetic constructor •() → self::AbstractB
+    ;
+  external get fieldExternalNonNullableOfAbstractB() → core::num;
+  external set fieldExternalNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractB() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractB() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractB() → dynamic;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  field core::num fieldNonNullableOfM;
+  late field core::num fieldLateNonNullableOfM;
+  final field dynamic fieldFinalDynamicOfM;
+  late final [setter] field dynamic fieldLateFinalDynamicOfM;
+  external get fieldExternalNonNullableOfM() → core::num;
+  external set fieldExternalNonNullableOfM(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfM() → core::num;
+  abstract set fieldAbstractNonNullableOfM(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfM() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfM() → dynamic;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.strong.expect
new file mode 100644
index 0000000..3995dbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.strong.expect
@@ -0,0 +1,86 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:7:7: Error: Field 'fieldNonNullableOfA' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfA; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:10:17: Error: Final field 'fieldFinalDynamicOfA' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfA; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:26:7: Error: Field 'fieldNonNullableOfB' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfB; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:29:17: Error: Final field 'fieldFinalDynamicOfB' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfB; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:45:7: Error: Field 'fieldNonNullableOfM' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfM; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:50:17: Error: Final field 'fieldFinalDynamicOfM' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfM; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num fieldNonNullableOfA = null;
+  late field core::num fieldLateNonNullableOfA;
+  final field dynamic fieldFinalDynamicOfA = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfA;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractA extends core::Object {
+  synthetic constructor •() → self::AbstractA
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractA() → core::num;
+  external set fieldExternalNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractA() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractA() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractA() → dynamic;
+}
+class B extends core::Object {
+  field core::num fieldNonNullableOfB = null;
+  late field core::num fieldLateNonNullableOfB;
+  final field dynamic fieldFinalDynamicOfB = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfB;
+  static factory •() → self::B
+    return throw 42;
+}
+abstract class AbstractB extends core::Object {
+  synthetic constructor •() → self::AbstractB
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractB() → core::num;
+  external set fieldExternalNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractB() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractB() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractB() → dynamic;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  field core::num fieldNonNullableOfM = null;
+  late field core::num fieldLateNonNullableOfM;
+  final field dynamic fieldFinalDynamicOfM = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfM;
+  external get fieldExternalNonNullableOfM() → core::num;
+  external set fieldExternalNonNullableOfM(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfM() → core::num;
+  abstract set fieldAbstractNonNullableOfM(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfM() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfM() → dynamic;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.strong.transformed.expect
new file mode 100644
index 0000000..3995dbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.strong.transformed.expect
@@ -0,0 +1,86 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:7:7: Error: Field 'fieldNonNullableOfA' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfA; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:10:17: Error: Final field 'fieldFinalDynamicOfA' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfA; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:26:7: Error: Field 'fieldNonNullableOfB' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfB; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:29:17: Error: Final field 'fieldFinalDynamicOfB' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfB; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:45:7: Error: Field 'fieldNonNullableOfM' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfM; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:50:17: Error: Final field 'fieldFinalDynamicOfM' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfM; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num fieldNonNullableOfA = null;
+  late field core::num fieldLateNonNullableOfA;
+  final field dynamic fieldFinalDynamicOfA = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfA;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractA extends core::Object {
+  synthetic constructor •() → self::AbstractA
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractA() → core::num;
+  external set fieldExternalNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractA() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractA() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractA() → dynamic;
+}
+class B extends core::Object {
+  field core::num fieldNonNullableOfB = null;
+  late field core::num fieldLateNonNullableOfB;
+  final field dynamic fieldFinalDynamicOfB = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfB;
+  static factory •() → self::B
+    return throw 42;
+}
+abstract class AbstractB extends core::Object {
+  synthetic constructor •() → self::AbstractB
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractB() → core::num;
+  external set fieldExternalNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractB() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractB() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractB() → dynamic;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  field core::num fieldNonNullableOfM = null;
+  late field core::num fieldLateNonNullableOfM;
+  final field dynamic fieldFinalDynamicOfM = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfM;
+  external get fieldExternalNonNullableOfM() → core::num;
+  external set fieldExternalNonNullableOfM(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfM() → core::num;
+  abstract set fieldAbstractNonNullableOfM(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfM() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfM() → dynamic;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect
new file mode 100644
index 0000000..003e9d3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.textual_outline.expect
@@ -0,0 +1,42 @@
+class A {
+  num fieldNonNullableOfA;
+  late num ;
+  fieldLateNonNullableOfA;
+  final dynamic fieldFinalDynamicOfA;
+  late ;
+  final dynamic fieldLateFinalDynamicOfA;
+}
+abstract class AbstractA {
+  external num fieldExternalNonNullableOfAbstractA;
+  abstract num fieldAbstractNonNullableOfAbstractA;
+  external final dynamic fieldExternalFinalDynamicOfAbstractA;
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractA;
+}
+class B {
+  num fieldNonNullableOfB;
+  late num ;
+  fieldLateNonNullableOfB;
+  final dynamic fieldFinalDynamicOfB;
+  late ;
+  final dynamic fieldLateFinalDynamicOfB;
+  factory B() => throw 42;
+}
+abstract class AbstractB {
+  external num fieldExternalNonNullableOfAbstractB;
+  abstract num fieldAbstractNonNullableOfAbstractB;
+  external final dynamic fieldExternalFinalDynamicOfAbstractB;
+  abstract final dynamic fieldAbstractFinalDynamicOfAbstractB;
+}
+mixin M {
+  num fieldNonNullableOfM;
+  late num ;
+  fieldLateNonNullableOfM;
+  external num fieldExternalNonNullableOfM;
+  abstract num fieldAbstractNonNullableOfM;
+  final dynamic fieldFinalDynamicOfM;
+  late ;
+  final dynamic fieldLateFinalDynamicOfM;
+  external final dynamic fieldExternalFinalDynamicOfM;
+  abstract final dynamic fieldAbstractFinalDynamicOfM;
+}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.weak.expect
new file mode 100644
index 0000000..3995dbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.weak.expect
@@ -0,0 +1,86 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:7:7: Error: Field 'fieldNonNullableOfA' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfA; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:10:17: Error: Final field 'fieldFinalDynamicOfA' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfA; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:26:7: Error: Field 'fieldNonNullableOfB' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfB; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:29:17: Error: Final field 'fieldFinalDynamicOfB' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfB; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:45:7: Error: Field 'fieldNonNullableOfM' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfM; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:50:17: Error: Final field 'fieldFinalDynamicOfM' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfM; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num fieldNonNullableOfA = null;
+  late field core::num fieldLateNonNullableOfA;
+  final field dynamic fieldFinalDynamicOfA = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfA;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractA extends core::Object {
+  synthetic constructor •() → self::AbstractA
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractA() → core::num;
+  external set fieldExternalNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractA() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractA() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractA() → dynamic;
+}
+class B extends core::Object {
+  field core::num fieldNonNullableOfB = null;
+  late field core::num fieldLateNonNullableOfB;
+  final field dynamic fieldFinalDynamicOfB = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfB;
+  static factory •() → self::B
+    return throw 42;
+}
+abstract class AbstractB extends core::Object {
+  synthetic constructor •() → self::AbstractB
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractB() → core::num;
+  external set fieldExternalNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractB() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractB() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractB() → dynamic;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  field core::num fieldNonNullableOfM = null;
+  late field core::num fieldLateNonNullableOfM;
+  final field dynamic fieldFinalDynamicOfM = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfM;
+  external get fieldExternalNonNullableOfM() → core::num;
+  external set fieldExternalNonNullableOfM(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfM() → core::num;
+  abstract set fieldAbstractNonNullableOfM(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfM() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfM() → dynamic;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue42967.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue42967.dart.weak.transformed.expect
new file mode 100644
index 0000000..3995dbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue42967.dart.weak.transformed.expect
@@ -0,0 +1,86 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:7:7: Error: Field 'fieldNonNullableOfA' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfA; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:10:17: Error: Final field 'fieldFinalDynamicOfA' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfA; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:26:7: Error: Field 'fieldNonNullableOfB' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfB; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:29:17: Error: Final field 'fieldFinalDynamicOfB' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfB; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:45:7: Error: Field 'fieldNonNullableOfM' should be initialized because its type 'num' doesn't allow null.
+//   num fieldNonNullableOfM; // Error.
+//       ^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue42967.dart:50:17: Error: Final field 'fieldFinalDynamicOfM' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final dynamic fieldFinalDynamicOfM; // Error.
+//                 ^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::num fieldNonNullableOfA = null;
+  late field core::num fieldLateNonNullableOfA;
+  final field dynamic fieldFinalDynamicOfA = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfA;
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+abstract class AbstractA extends core::Object {
+  synthetic constructor •() → self::AbstractA
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractA() → core::num;
+  external set fieldExternalNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractA() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractA(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractA() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractA() → dynamic;
+}
+class B extends core::Object {
+  field core::num fieldNonNullableOfB = null;
+  late field core::num fieldLateNonNullableOfB;
+  final field dynamic fieldFinalDynamicOfB = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfB;
+  static factory •() → self::B
+    return throw 42;
+}
+abstract class AbstractB extends core::Object {
+  synthetic constructor •() → self::AbstractB
+    : super core::Object::•()
+    ;
+  external get fieldExternalNonNullableOfAbstractB() → core::num;
+  external set fieldExternalNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfAbstractB() → core::num;
+  abstract set fieldAbstractNonNullableOfAbstractB(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfAbstractB() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfAbstractB() → dynamic;
+}
+abstract class M extends core::Object /*isMixinDeclaration*/  {
+  field core::num fieldNonNullableOfM = null;
+  late field core::num fieldLateNonNullableOfM;
+  final field dynamic fieldFinalDynamicOfM = null;
+  late final [setter] field dynamic fieldLateFinalDynamicOfM;
+  external get fieldExternalNonNullableOfM() → core::num;
+  external set fieldExternalNonNullableOfM(core::num #externalFieldValue) → void;
+  abstract get fieldAbstractNonNullableOfM() → core::num;
+  abstract set fieldAbstractNonNullableOfM(core::num #externalFieldValue) → void;
+  external get fieldExternalFinalDynamicOfM() → dynamic;
+  abstract get fieldAbstractFinalDynamicOfM() → dynamic;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart b/pkg/front_end/testcases/nnbd/issue43211.dart
new file mode 100644
index 0000000..f04a817
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<X extends A<X>?> {}
+
+class D<X extends num> {}
+
+extension Extension1<X extends A<X>?> on A<X> {
+  void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+    A<Y>? c;
+    A<A<Null>>? d;
+  }
+
+  void method2<Y extends String>(D<Y> a, D<String>? b) {
+    D<Y>? c;
+    D<String>? d;
+  }
+}
+
+extension ext2<X extends A<Null>?> on A<X> {}
+
+class B<X extends A<Null>?> implements A<X> {
+  void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+    A<Y>? c;
+    A<A<Null>>? d;
+  }
+
+  void method2<Y extends String>(D<Y> a, D<String>? b) {
+    D<Y>? c;
+    D<String>? d;
+  }
+}
+
+class C {
+  factory C.redirect(A<A<Null>>? a) = C.internal;
+
+  factory C.fact(A<A<Null>>? a) {
+    A<A<Null>>? b;
+    D<String>? c;
+    return new C.internal(a);
+  }
+
+  C.internal(_) {
+    A<A<Null>>? a;
+    D<String>? b;
+  }
+}
+
+test() {
+  var a = new A<Null>();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect
new file mode 100644
index 0000000..f9ad8e5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.outline.expect
@@ -0,0 +1,151 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:10:53: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:21:39: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// extension ext2<X extends A<Null>?> on A<X> {}
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:23:7: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A' in the supertype 'A' of class 'B'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class B<X extends A<Null>?> implements A<X> {
+//       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:41: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                         ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:56: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                                        ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:36:34: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.redirect(A<A<Null>>? a) = C.internal;
+//                                  ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:38:30: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.fact(A<A<Null>>? a) {
+//                              ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends self::A<self::A::X%>? = self::A<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    ;
+}
+class D<X extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    ;
+}
+class B<X extends self::A<core::Null?>? = self::A<core::Null?>?> extends core::Object implements self::A<self::B::X%> {
+  synthetic constructor •() → self::B<self::B::X%>
+    ;
+  method method1<Y extends self::A<core::Null?>? = self::A<core::Null?>?>(self::A<self::B::method1::Y%> a, self::A<self::A<core::Null?>>? b) → void
+    ;
+  method method2<Y extends core::String = core::String>(self::D<self::B::method2::Y> a, self::D<core::String>? b) → void
+    ;
+}
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isNullableByDefault*/;
+  constructor internal(dynamic _) → self::C
+    ;
+  static factory redirect(self::A<self::A<core::Null?>>? a) → self::C
+    let dynamic #redirecting_factory = self::C::internal in invalid-expression;
+  static factory fact(self::A<self::A<core::Null?>>? a) → self::C
+    ;
+}
+extension Extension1<X extends self::A<X%>? = self::A<dynamic>?> on self::A<X%> {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+}
+extension ext2<X extends self::A<core::Null?>? = self::A<core::Null?>?> on self::A<X%> {
+}
+static method Extension1|method1<X extends self::A<self::Extension1|method1::X%>? = self::A<dynamic>?, Y extends self::A<self::Extension1|method1::Y%>? = self::A<dynamic>?>(final self::A<self::Extension1|method1::X%> #this, self::A<self::Extension1|method1::Y%> a, self::A<self::A<core::Null?>>? b) → void
+  ;
+static method Extension1|get#method1<X extends self::A<self::Extension1|get#method1::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method1::X%> #this) → <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%>, self::A<self::A<core::Null?>>?) → void
+  return <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%> a, self::A<self::A<core::Null?>>? b) → void => self::Extension1|method1<self::Extension1|get#method1::X%, Y%>(#this, a, b);
+static method Extension1|method2<X extends self::A<self::Extension1|method2::X%>? = self::A<dynamic>?, Y extends core::String = core::String>(final self::A<self::Extension1|method2::X%> #this, self::D<self::Extension1|method2::Y> a, self::D<core::String>? b) → void
+  ;
+static method Extension1|get#method2<X extends self::A<self::Extension1|get#method2::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method2::X%> #this) → <Y extends core::String = core::String>(self::D<Y>, self::D<core::String>?) → void
+  return <Y extends core::String = core::String>(self::D<Y> a, self::D<core::String>? b) → void => self::Extension1|method2<self::Extension1|get#method2::X%, Y>(#this, a, b);
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect
new file mode 100644
index 0000000..127779c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.expect
@@ -0,0 +1,261 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:10:53: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:21:39: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// extension ext2<X extends A<Null>?> on A<X> {}
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:23:7: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A' in the supertype 'A' of class 'B'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class B<X extends A<Null>?> implements A<X> {
+//       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:41: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                         ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:56: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                                        ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:36:34: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.redirect(A<A<Null>>? a) = C.internal;
+//                                  ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:38:30: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.fact(A<A<Null>>? a) {
+//                              ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:12:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:16:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:17:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:25:11: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:26:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:30:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:31:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:39:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? b;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:40:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? c;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:45:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? a;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:46:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? b;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends self::A<self::A::X%>? = self::A<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class D<X extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends self::A<core::Null?>? = self::A<core::Null?>?> extends core::Object implements self::A<self::B::X%> {
+  synthetic constructor •() → self::B<self::B::X%>
+    : super core::Object::•()
+    ;
+  method method1<Y extends self::A<core::Null?>? = self::A<core::Null?>?>(self::A<self::B::method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+    self::A<self::B::method1::Y%>? c;
+    self::A<self::A<core::Null?>>? d;
+  }
+  method method2<Y extends core::String = core::String>(self::D<self::B::method2::Y> a, self::D<core::String>? b) → void {
+    self::D<self::B::method2::Y>? c;
+    self::D<core::String>? d;
+  }
+}
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isNullableByDefault*/;
+  constructor internal(dynamic _) → self::C
+    : super core::Object::•() {
+    self::A<self::A<core::Null?>>? a;
+    self::D<core::String>? b;
+  }
+  static factory redirect(self::A<self::A<core::Null?>>? a) → self::C
+    let dynamic #redirecting_factory = self::C::internal in invalid-expression;
+  static factory fact(self::A<self::A<core::Null?>>? a) → self::C {
+    self::A<self::A<core::Null?>>? b;
+    self::D<core::String>? c;
+    return new self::C::internal(a);
+  }
+}
+extension Extension1<X extends self::A<X%>? = self::A<dynamic>?> on self::A<X%> {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+}
+extension ext2<X extends self::A<core::Null?>? = self::A<core::Null?>?> on self::A<X%> {
+}
+static method Extension1|method1<X extends self::A<self::Extension1|method1::X%>? = self::A<dynamic>?, Y extends self::A<self::Extension1|method1::Y%>? = self::A<dynamic>?>(final self::A<self::Extension1|method1::X%> #this, self::A<self::Extension1|method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+  self::A<self::Extension1|method1::Y%>? c;
+  self::A<self::A<core::Null?>>? d;
+}
+static method Extension1|get#method1<X extends self::A<self::Extension1|get#method1::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method1::X%> #this) → <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%>, self::A<self::A<core::Null?>>?) → void
+  return <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%> a, self::A<self::A<core::Null?>>? b) → void => self::Extension1|method1<self::Extension1|get#method1::X%, Y%>(#this, a, b);
+static method Extension1|method2<X extends self::A<self::Extension1|method2::X%>? = self::A<dynamic>?, Y extends core::String = core::String>(final self::A<self::Extension1|method2::X%> #this, self::D<self::Extension1|method2::Y> a, self::D<core::String>? b) → void {
+  self::D<self::Extension1|method2::Y>? c;
+  self::D<core::String>? d;
+}
+static method Extension1|get#method2<X extends self::A<self::Extension1|get#method2::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method2::X%> #this) → <Y extends core::String = core::String>(self::D<Y>, self::D<core::String>?) → void
+  return <Y extends core::String = core::String>(self::D<Y> a, self::D<core::String>? b) → void => self::Extension1|method2<self::Extension1|get#method2::X%, Y>(#this, a, b);
+static method test() → dynamic {
+  self::A<core::Null?> a = new self::A::•<core::Null?>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect
new file mode 100644
index 0000000..10f7711
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.strong.transformed.expect
@@ -0,0 +1,261 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:10:53: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:21:39: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// extension ext2<X extends A<Null>?> on A<X> {}
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:23:7: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A' in the supertype 'A' of class 'B'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class B<X extends A<Null>?> implements A<X> {
+//       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:41: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                         ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:56: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                                        ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:36:34: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.redirect(A<A<Null>>? a) = C.internal;
+//                                  ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:38:30: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.fact(A<A<Null>>? a) {
+//                              ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:12:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:16:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:17:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:25:11: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:26:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:30:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:31:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:39:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? b;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:40:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? c;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:45:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? a;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:46:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? b;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends self::A<self::A::X%>? = self::A<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class D<X extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends self::A<core::Null?>? = self::A<core::Null?>?> extends core::Object implements self::A<self::B::X%> {
+  synthetic constructor •() → self::B<self::B::X%>
+    : super core::Object::•()
+    ;
+  method method1<Y extends self::A<core::Null?>? = self::A<core::Null?>?>(self::A<self::B::method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+    self::A<self::B::method1::Y%>? c;
+    self::A<self::A<core::Null?>>? d;
+  }
+  method method2<Y extends core::String = core::String>(self::D<self::B::method2::Y> a, self::D<core::String>? b) → void {
+    self::D<self::B::method2::Y>? c;
+    self::D<core::String>? d;
+  }
+}
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isNullableByDefault*/;
+  constructor internal(dynamic _) → self::C
+    : super core::Object::•() {
+    self::A<self::A<core::Null?>>? a;
+    self::D<core::String>? b;
+  }
+  static factory redirect(self::A<self::A<core::Null?>>? a) → self::C
+    let<BottomType> #redirecting_factory = self::C::internal in invalid-expression;
+  static factory fact(self::A<self::A<core::Null?>>? a) → self::C {
+    self::A<self::A<core::Null?>>? b;
+    self::D<core::String>? c;
+    return new self::C::internal(a);
+  }
+}
+extension Extension1<X extends self::A<X%>? = self::A<dynamic>?> on self::A<X%> {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+}
+extension ext2<X extends self::A<core::Null?>? = self::A<core::Null?>?> on self::A<X%> {
+}
+static method Extension1|method1<X extends self::A<self::Extension1|method1::X%>? = self::A<dynamic>?, Y extends self::A<self::Extension1|method1::Y%>? = self::A<dynamic>?>(final self::A<self::Extension1|method1::X%> #this, self::A<self::Extension1|method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+  self::A<self::Extension1|method1::Y%>? c;
+  self::A<self::A<core::Null?>>? d;
+}
+static method Extension1|get#method1<X extends self::A<self::Extension1|get#method1::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method1::X%> #this) → <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%>, self::A<self::A<core::Null?>>?) → void
+  return <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%> a, self::A<self::A<core::Null?>>? b) → void => self::Extension1|method1<self::Extension1|get#method1::X%, Y%>(#this, a, b);
+static method Extension1|method2<X extends self::A<self::Extension1|method2::X%>? = self::A<dynamic>?, Y extends core::String = core::String>(final self::A<self::Extension1|method2::X%> #this, self::D<self::Extension1|method2::Y> a, self::D<core::String>? b) → void {
+  self::D<self::Extension1|method2::Y>? c;
+  self::D<core::String>? d;
+}
+static method Extension1|get#method2<X extends self::A<self::Extension1|get#method2::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method2::X%> #this) → <Y extends core::String = core::String>(self::D<Y>, self::D<core::String>?) → void
+  return <Y extends core::String = core::String>(self::D<Y> a, self::D<core::String>? b) → void => self::Extension1|method2<self::Extension1|get#method2::X%, Y>(#this, a, b);
+static method test() → dynamic {
+  self::A<core::Null?> a = new self::A::•<core::Null?>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
new file mode 100644
index 0000000..f38556f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.textual_outline.expect
@@ -0,0 +1,17 @@
+class A<X extends A<X>?> {}
+class D<X extends num> {}
+extension Extension1<X extends A<X>?> (){}
+on A<X> (){}
+extension ext2<X extends A<Null>?> (){}
+on A<X> (){}
+class B<X extends A<Null>?> implements A<X> {
+  void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {}
+  void method2<Y extends String>(D<Y> a, D<String>? b) {}
+}
+class C {
+  factory C.redirect(A<A<Null>>? a) = C.internal;
+  factory C.fact(A<A<Null>>? a) {}
+  C.internal(_) {}
+}
+test() {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect
new file mode 100644
index 0000000..127779c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.expect
@@ -0,0 +1,261 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:10:53: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:21:39: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// extension ext2<X extends A<Null>?> on A<X> {}
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:23:7: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A' in the supertype 'A' of class 'B'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class B<X extends A<Null>?> implements A<X> {
+//       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:41: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                         ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:56: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                                        ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:36:34: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.redirect(A<A<Null>>? a) = C.internal;
+//                                  ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:38:30: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.fact(A<A<Null>>? a) {
+//                              ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:12:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:16:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:17:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:25:11: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:26:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:30:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:31:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:39:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? b;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:40:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? c;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:45:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? a;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:46:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? b;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends self::A<self::A::X%>? = self::A<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class D<X extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends self::A<core::Null?>? = self::A<core::Null?>?> extends core::Object implements self::A<self::B::X%> {
+  synthetic constructor •() → self::B<self::B::X%>
+    : super core::Object::•()
+    ;
+  method method1<Y extends self::A<core::Null?>? = self::A<core::Null?>?>(self::A<self::B::method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+    self::A<self::B::method1::Y%>? c;
+    self::A<self::A<core::Null?>>? d;
+  }
+  method method2<Y extends core::String = core::String>(self::D<self::B::method2::Y> a, self::D<core::String>? b) → void {
+    self::D<self::B::method2::Y>? c;
+    self::D<core::String>? d;
+  }
+}
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isNullableByDefault*/;
+  constructor internal(dynamic _) → self::C
+    : super core::Object::•() {
+    self::A<self::A<core::Null?>>? a;
+    self::D<core::String>? b;
+  }
+  static factory redirect(self::A<self::A<core::Null?>>? a) → self::C
+    let dynamic #redirecting_factory = self::C::internal in invalid-expression;
+  static factory fact(self::A<self::A<core::Null?>>? a) → self::C {
+    self::A<self::A<core::Null?>>? b;
+    self::D<core::String>? c;
+    return new self::C::internal(a);
+  }
+}
+extension Extension1<X extends self::A<X%>? = self::A<dynamic>?> on self::A<X%> {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+}
+extension ext2<X extends self::A<core::Null?>? = self::A<core::Null?>?> on self::A<X%> {
+}
+static method Extension1|method1<X extends self::A<self::Extension1|method1::X%>? = self::A<dynamic>?, Y extends self::A<self::Extension1|method1::Y%>? = self::A<dynamic>?>(final self::A<self::Extension1|method1::X%> #this, self::A<self::Extension1|method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+  self::A<self::Extension1|method1::Y%>? c;
+  self::A<self::A<core::Null?>>? d;
+}
+static method Extension1|get#method1<X extends self::A<self::Extension1|get#method1::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method1::X%> #this) → <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%>, self::A<self::A<core::Null?>>?) → void
+  return <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%> a, self::A<self::A<core::Null?>>? b) → void => self::Extension1|method1<self::Extension1|get#method1::X%, Y%>(#this, a, b);
+static method Extension1|method2<X extends self::A<self::Extension1|method2::X%>? = self::A<dynamic>?, Y extends core::String = core::String>(final self::A<self::Extension1|method2::X%> #this, self::D<self::Extension1|method2::Y> a, self::D<core::String>? b) → void {
+  self::D<self::Extension1|method2::Y>? c;
+  self::D<core::String>? d;
+}
+static method Extension1|get#method2<X extends self::A<self::Extension1|get#method2::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method2::X%> #this) → <Y extends core::String = core::String>(self::D<Y>, self::D<core::String>?) → void
+  return <Y extends core::String = core::String>(self::D<Y> a, self::D<core::String>? b) → void => self::Extension1|method2<self::Extension1|get#method2::X%, Y>(#this, a, b);
+static method test() → dynamic {
+  self::A<core::Null?> a = new self::A::•<core::Null?>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect
new file mode 100644
index 0000000..10f7711
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43211.dart.weak.transformed.expect
@@ -0,0 +1,261 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:10:53: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Y>?>(A<Y> a, A<A<Null>>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:15:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:21:39: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// extension ext2<X extends A<Null>?> on A<X> {}
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:23:7: Error: Type argument 'X/*1*/' doesn't conform to the bound 'A<X/*2*/>?' of the type variable 'X' on 'A' in the supertype 'A' of class 'B'.
+//  - 'X/*1*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+//  - 'X/*2*/' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+// class B<X extends A<Null>?> implements A<X> {
+//       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:41: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                         ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:24:56: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method1<Y extends A<Null>?>(A<Y> a, A<A<Null>>? b) {
+//                                                        ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:39: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                       ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:29:53: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//   void method2<Y extends String>(D<Y> a, D<String>? b) {
+//                                                     ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:36:34: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.redirect(A<A<Null>>? a) = C.internal;
+//                                  ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:38:30: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//   factory C.fact(A<A<Null>>? a) {
+//                              ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:12:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:16:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:17:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:25:11: Error: Type argument 'Y' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:26:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? d;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:30:11: Error: Type argument 'Y' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<Y>? c;
+//           ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:31:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? d;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:39:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? b;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:40:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? c;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:45:17: Error: Type argument 'A<Null>' doesn't conform to the bound 'A<X>?' of the type variable 'X' on 'A'.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43211.dart'.
+// Try changing type arguments so that they conform to the bounds.
+//     A<A<Null>>? a;
+//                 ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:5:9: Context: This is the type variable whose bound isn't conformed to.
+// class A<X extends A<X>?> {}
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43211.dart:46:16: Error: Type argument 'String' doesn't conform to the bound 'num' of the type variable 'X' on 'D'.
+// Try changing type arguments so that they conform to the bounds.
+//     D<String>? b;
+//                ^
+// pkg/front_end/testcases/nnbd/issue43211.dart:7:9: Context: This is the type variable whose bound isn't conformed to.
+// class D<X extends num> {}
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A<X extends self::A<self::A::X%>? = self::A<dynamic>?> extends core::Object {
+  synthetic constructor •() → self::A<self::A::X%>
+    : super core::Object::•()
+    ;
+}
+class D<X extends core::num = core::num> extends core::Object {
+  synthetic constructor •() → self::D<self::D::X>
+    : super core::Object::•()
+    ;
+}
+class B<X extends self::A<core::Null?>? = self::A<core::Null?>?> extends core::Object implements self::A<self::B::X%> {
+  synthetic constructor •() → self::B<self::B::X%>
+    : super core::Object::•()
+    ;
+  method method1<Y extends self::A<core::Null?>? = self::A<core::Null?>?>(self::A<self::B::method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+    self::A<self::B::method1::Y%>? c;
+    self::A<self::A<core::Null?>>? d;
+  }
+  method method2<Y extends core::String = core::String>(self::D<self::B::method2::Y> a, self::D<core::String>? b) → void {
+    self::D<self::B::method2::Y>? c;
+    self::D<core::String>? d;
+  }
+}
+class C extends core::Object {
+  static field dynamic _redirecting# = <dynamic>[self::C::redirect]/*isNullableByDefault*/;
+  constructor internal(dynamic _) → self::C
+    : super core::Object::•() {
+    self::A<self::A<core::Null?>>? a;
+    self::D<core::String>? b;
+  }
+  static factory redirect(self::A<self::A<core::Null?>>? a) → self::C
+    let<BottomType> #redirecting_factory = self::C::internal in invalid-expression;
+  static factory fact(self::A<self::A<core::Null?>>? a) → self::C {
+    self::A<self::A<core::Null?>>? b;
+    self::D<core::String>? c;
+    return new self::C::internal(a);
+  }
+}
+extension Extension1<X extends self::A<X%>? = self::A<dynamic>?> on self::A<X%> {
+  method method1 = self::Extension1|method1;
+  tearoff method1 = self::Extension1|get#method1;
+  method method2 = self::Extension1|method2;
+  tearoff method2 = self::Extension1|get#method2;
+}
+extension ext2<X extends self::A<core::Null?>? = self::A<core::Null?>?> on self::A<X%> {
+}
+static method Extension1|method1<X extends self::A<self::Extension1|method1::X%>? = self::A<dynamic>?, Y extends self::A<self::Extension1|method1::Y%>? = self::A<dynamic>?>(final self::A<self::Extension1|method1::X%> #this, self::A<self::Extension1|method1::Y%> a, self::A<self::A<core::Null?>>? b) → void {
+  self::A<self::Extension1|method1::Y%>? c;
+  self::A<self::A<core::Null?>>? d;
+}
+static method Extension1|get#method1<X extends self::A<self::Extension1|get#method1::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method1::X%> #this) → <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%>, self::A<self::A<core::Null?>>?) → void
+  return <Y extends self::A<Y%>? = self::A<dynamic>?>(self::A<Y%> a, self::A<self::A<core::Null?>>? b) → void => self::Extension1|method1<self::Extension1|get#method1::X%, Y%>(#this, a, b);
+static method Extension1|method2<X extends self::A<self::Extension1|method2::X%>? = self::A<dynamic>?, Y extends core::String = core::String>(final self::A<self::Extension1|method2::X%> #this, self::D<self::Extension1|method2::Y> a, self::D<core::String>? b) → void {
+  self::D<self::Extension1|method2::Y>? c;
+  self::D<core::String>? d;
+}
+static method Extension1|get#method2<X extends self::A<self::Extension1|get#method2::X%>? = self::A<dynamic>?>(final self::A<self::Extension1|get#method2::X%> #this) → <Y extends core::String = core::String>(self::D<Y>, self::D<core::String>?) → void
+  return <Y extends core::String = core::String>(self::D<Y> a, self::D<core::String>? b) → void => self::Extension1|method2<self::Extension1|get#method2::X%, Y>(#this, a, b);
+static method test() → dynamic {
+  self::A<core::Null?> a = new self::A::•<core::Null?>();
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.expect
index 0d7d725..c66b4918 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.expect
@@ -22,6 +22,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
@@ -30,6 +34,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
index ef9e80c..32a8e8e 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.strong.transformed.expect
@@ -22,6 +22,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
@@ -30,6 +34,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.expect
index 0d7d725..c66b4918 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.expect
@@ -22,6 +22,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
@@ -30,6 +34,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
diff --git a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
index ef9e80c..32a8e8e 100644
--- a/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/issue43256.dart.weak.transformed.expect
@@ -22,6 +22,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:48:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
@@ -30,6 +34,10 @@
 //     if (i > 0) ...y, // error
 //                   ^
 //
+// pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     if (i > 0) ...x, // error
+//                   ^
+//
 // pkg/front_end/testcases/nnbd/issue43256.dart:53:19: Error: Unexpected type 'X' of a spread.  Expected 'dynamic' or an Iterable.
 //     if (i > 0) ...x, // error
 //                   ^
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart b/pkg/front_end/testcases/nnbd/issue43278.dart
new file mode 100644
index 0000000..6bc9bbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int? foo;
+  A bar;
+
+  A(this.bar);
+}
+
+test<T extends A?>(A? a, T t, dynamic d, int x) {
+  a.foo ??= x; // Error.
+  t.foo ??= x; // Error.
+  d.foo ??= x; // Ok.
+  a?.bar.foo ??= x; // Ok.
+}
+
+class B {}
+
+extension Extension on B {
+  int? get fooExtension => null;
+  void set fooExtension(int? value) {}
+  B get barExtension => new B();
+}
+
+testExtension<T extends B?>(B? b, T t, int x) {
+  b.fooExtension ??= x; // Error.
+  t.fooExtension ??= x; // Error.
+  b?.barExtension.fooExtension ??= x; // Ok.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.outline.expect
new file mode 100644
index 0000000..1ca6277
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.outline.expect
@@ -0,0 +1,31 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? foo;
+  field self::A bar;
+  constructor •(self::A bar) → self::A
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    ;
+}
+extension Extension on self::B {
+  get fooExtension = self::Extension|get#fooExtension;
+  get barExtension = self::Extension|get#barExtension;
+  set fooExtension = self::Extension|set#fooExtension;
+}
+static method test<T extends self::A? = self::A?>(self::A? a, self::test::T% t, dynamic d, core::int x) → dynamic
+  ;
+static method Extension|get#fooExtension(final self::B #this) → core::int?
+  ;
+static method Extension|set#fooExtension(final self::B #this, core::int? value) → void
+  ;
+static method Extension|get#barExtension(final self::B #this) → self::B
+  ;
+static method testExtension<T extends self::B? = self::B?>(self::B? b, self::testExtension::T% t, core::int x) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect
new file mode 100644
index 0000000..7ca309b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.expect
@@ -0,0 +1,91 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   a.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   b.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? foo = null;
+  field self::A bar;
+  constructor •(self::A bar) → self::A
+    : self::A::bar = bar, super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::B {
+  get fooExtension = self::Extension|get#fooExtension;
+  get barExtension = self::Extension|get#barExtension;
+  set fooExtension = self::Extension|set#fooExtension;
+}
+static method test<T extends self::A? = self::A?>(self::A? a, self::test::T% t, dynamic d, core::int x) → dynamic {
+  let final self::A? #t1 = a in (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo} = x : null;
+  let final self::test::T% #t4 = t in (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo} = x : null;
+  let final dynamic #t7 = d in #t7.foo.{core::Object::==}(null) ?{dynamic} #t7.foo = x : null;
+  let final self::A? #t8 = a in #t8.{core::Object::==}(null) ?{core::int?} null : let final self::A #t9 = #t8{self::A}.{self::A::bar} in #t9.{self::A::foo}.{core::num::==}(null) ?{core::int} #t9.{self::A::foo} = x : null;
+}
+static method Extension|get#fooExtension(final self::B #this) → core::int?
+  return null;
+static method Extension|set#fooExtension(final self::B #this, core::int? value) → void {}
+static method Extension|get#barExtension(final self::B #this) → self::B
+  return new self::B::•();
+static method testExtension<T extends self::B? = self::B?>(self::B? b, self::testExtension::T% t, core::int x) → dynamic {
+  let final self::B? #t10 = b in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
+  let final self::testExtension::T% #t13 = t in (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+  let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect
new file mode 100644
index 0000000..7ca309b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.strong.transformed.expect
@@ -0,0 +1,91 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   a.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   b.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? foo = null;
+  field self::A bar;
+  constructor •(self::A bar) → self::A
+    : self::A::bar = bar, super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::B {
+  get fooExtension = self::Extension|get#fooExtension;
+  get barExtension = self::Extension|get#barExtension;
+  set fooExtension = self::Extension|set#fooExtension;
+}
+static method test<T extends self::A? = self::A?>(self::A? a, self::test::T% t, dynamic d, core::int x) → dynamic {
+  let final self::A? #t1 = a in (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo} = x : null;
+  let final self::test::T% #t4 = t in (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo} = x : null;
+  let final dynamic #t7 = d in #t7.foo.{core::Object::==}(null) ?{dynamic} #t7.foo = x : null;
+  let final self::A? #t8 = a in #t8.{core::Object::==}(null) ?{core::int?} null : let final self::A #t9 = #t8{self::A}.{self::A::bar} in #t9.{self::A::foo}.{core::num::==}(null) ?{core::int} #t9.{self::A::foo} = x : null;
+}
+static method Extension|get#fooExtension(final self::B #this) → core::int?
+  return null;
+static method Extension|set#fooExtension(final self::B #this, core::int? value) → void {}
+static method Extension|get#barExtension(final self::B #this) → self::B
+  return new self::B::•();
+static method testExtension<T extends self::B? = self::B?>(self::B? b, self::testExtension::T% t, core::int x) → dynamic {
+  let final self::B? #t10 = b in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
+  let final self::testExtension::T% #t13 = t in (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+  let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
new file mode 100644
index 0000000..989f770
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+class A {
+  int? foo;
+  A bar;
+  A(this.bar);
+}
+test<T extends A?>(A? a, T t, dynamic d, int x) {}
+class B {}
+extension Extension ;
+on B (){}
+testExtension<T extends B?>(B? b, T t, int x) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ffcd116
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+bar<T extends A?>(A? a, T t, dynamic d, int x) {}
+
+class A {
+  A(this.bar);
+  A bar;
+  int? foo;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect
new file mode 100644
index 0000000..7ca309b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.expect
@@ -0,0 +1,91 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   a.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   b.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? foo = null;
+  field self::A bar;
+  constructor •(self::A bar) → self::A
+    : self::A::bar = bar, super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::B {
+  get fooExtension = self::Extension|get#fooExtension;
+  get barExtension = self::Extension|get#barExtension;
+  set fooExtension = self::Extension|set#fooExtension;
+}
+static method test<T extends self::A? = self::A?>(self::A? a, self::test::T% t, dynamic d, core::int x) → dynamic {
+  let final self::A? #t1 = a in (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo} = x : null;
+  let final self::test::T% #t4 = t in (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo} = x : null;
+  let final dynamic #t7 = d in #t7.foo.{core::Object::==}(null) ?{dynamic} #t7.foo = x : null;
+  let final self::A? #t8 = a in #t8.{core::Object::==}(null) ?{core::int?} null : let final self::A #t9 = #t8{self::A}.{self::A::bar} in #t9.{self::A::foo}.{core::num::==}(null) ?{core::int} #t9.{self::A::foo} = x : null;
+}
+static method Extension|get#fooExtension(final self::B #this) → core::int?
+  return null;
+static method Extension|set#fooExtension(final self::B #this, core::int? value) → void {}
+static method Extension|get#barExtension(final self::B #this) → self::B
+  return new self::B::•();
+static method testExtension<T extends self::B? = self::B?>(self::B? b, self::testExtension::T% t, core::int x) → dynamic {
+  let final self::B? #t10 = b in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
+  let final self::testExtension::T% #t13 = t in (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+  let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect
new file mode 100644
index 0000000..7ca309b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43278.dart.weak.transformed.expect
@@ -0,0 +1,91 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+//  - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   a.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.foo ??= x; // Error.
+//     ^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+//  - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+// Try accessing using ?. instead.
+//   b.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+// Try accessing using ?. instead.
+//   t.fooExtension ??= x; // Error.
+//     ^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int? foo = null;
+  field self::A bar;
+  constructor •(self::A bar) → self::A
+    : self::A::bar = bar, super core::Object::•()
+    ;
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+extension Extension on self::B {
+  get fooExtension = self::Extension|get#fooExtension;
+  get barExtension = self::Extension|get#barExtension;
+  set fooExtension = self::Extension|set#fooExtension;
+}
+static method test<T extends self::A? = self::A?>(self::A? a, self::test::T% t, dynamic d, core::int x) → dynamic {
+  let final self::A? #t1 = a in (let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:13:5: Error: Property 'foo' cannot be accessed on 'A?' because it is potentially null.
+ - 'A' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  a.foo ??= x; // Error.
+    ^^^" in #t1.{self::A::foo} = x : null;
+  let final self::test::T% #t4 = t in (let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo}).{core::num::==}(null) ?{core::int} let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:14:5: Error: Property 'foo' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.foo ??= x; // Error.
+    ^^^" in #t4.{self::A::foo} = x : null;
+  let final dynamic #t7 = d in #t7.foo.{core::Object::==}(null) ?{dynamic} #t7.foo = x : null;
+  let final self::A? #t8 = a in #t8.{core::Object::==}(null) ?{core::int?} null : let final self::A #t9 = #t8{self::A}.{self::A::bar} in #t9.{self::A::foo}.{core::num::==}(null) ?{core::int} #t9.{self::A::foo} = x : null;
+}
+static method Extension|get#fooExtension(final self::B #this) → core::int?
+  return null;
+static method Extension|set#fooExtension(final self::B #this, core::int? value) → void {}
+static method Extension|get#barExtension(final self::B #this) → self::B
+  return new self::B::•();
+static method testExtension<T extends self::B? = self::B?>(self::B? b, self::testExtension::T% t, core::int x) → dynamic {
+  let final self::B? #t10 = b in (let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t10)).{core::num::==}(null) ?{core::int} let final<BottomType> #t12 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:28:5: Error: Property 'fooExtension' cannot be accessed on 'B?' because it is potentially null.
+ - 'B' is from 'pkg/front_end/testcases/nnbd/issue43278.dart'.
+Try accessing using ?. instead.
+  b.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t10, x) : null;
+  let final self::testExtension::T% #t13 = t in (let final<BottomType> #t14 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|get#fooExtension(#t13)).{core::num::==}(null) ?{core::int} let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/nnbd/issue43278.dart:29:5: Error: Property 'fooExtension' cannot be accessed on 'T' because it is potentially null.
+Try accessing using ?. instead.
+  t.fooExtension ??= x; // Error.
+    ^^^^^^^^^^^^" in self::Extension|set#fooExtension(#t13, x) : null;
+  let final self::B? #t16 = b in #t16.{core::Object::==}(null) ?{core::int?} null : let final self::B #t17 = self::Extension|get#barExtension(#t16{self::B}) in self::Extension|get#fooExtension(#t17).{core::num::==}(null) ?{core::int} self::Extension|set#fooExtension(#t17, x) : null;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart b/pkg/front_end/testcases/nnbd/issue43354.dart
new file mode 100644
index 0000000..0fe7700
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// The error should be reported on the field, not the constructor.
+
+class A {
+  late final int foo = 42;
+  const A();
+}
+
+class B {
+  late final int foo = 42;
+  late final String bar = "foobar";
+  const B();
+}
+
+class C {
+  late final int foo = 42;
+  const C();
+  const C.another();
+}
+
+class D {
+  late final int foo = 42;
+  late final String bar = "foobar";
+  const D();
+  const D.another();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.outline.expect
new file mode 100644
index 0000000..af871a2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.outline.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  const constructor another() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::D
+    : super core::Object::•()
+    ;
+  const constructor another() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.strong.expect
new file mode 100644
index 0000000..b068885
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.strong.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:8:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:9:9: Context: This constructor is const.
+//   const A();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:13:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:14:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:19:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:20:9: Context: This constructor is const.
+//   const C();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:25:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:26:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  const constructor another() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::D
+    : super core::Object::•()
+    ;
+  const constructor another() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.strong.transformed.expect
new file mode 100644
index 0000000..b068885
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.strong.transformed.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:8:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:9:9: Context: This constructor is const.
+//   const A();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:13:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:14:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:19:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:20:9: Context: This constructor is const.
+//   const C();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:25:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:26:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  const constructor another() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::D
+    : super core::Object::•()
+    ;
+  const constructor another() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect
new file mode 100644
index 0000000..d4f44a6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.textual_outline.expect
@@ -0,0 +1,27 @@
+class A {
+  late ;
+  final int foo = 42;
+  const A();
+}
+class B {
+  late ;
+  final int foo = 42;
+  late ;
+  final String bar = "foobar";
+  const B();
+}
+class C {
+  late ;
+  final int foo = 42;
+  const C();
+  const C.another();
+}
+class D {
+  late ;
+  final int foo = 42;
+  late ;
+  final String bar = "foobar";
+  const D();
+  const D.another();
+}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.weak.expect
new file mode 100644
index 0000000..b068885
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.weak.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:8:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:9:9: Context: This constructor is const.
+//   const A();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:13:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:14:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:19:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:20:9: Context: This constructor is const.
+//   const C();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:25:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:26:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  const constructor another() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::D
+    : super core::Object::•()
+    ;
+  const constructor another() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43354.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43354.dart.weak.transformed.expect
new file mode 100644
index 0000000..b068885
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43354.dart.weak.transformed.expect
@@ -0,0 +1,82 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:8:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:9:9: Context: This constructor is const.
+//   const A();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:13:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:14:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:15:9: Context: This constructor is const.
+//   const B();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:19:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:20:9: Context: This constructor is const.
+//   const C();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:25:18: Error: Can't have a late final field in a class with a const constructor.
+//   late final int foo = 42;
+//                  ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43354.dart:26:21: Error: Can't have a late final field in a class with a const constructor.
+//   late final String bar = "foobar";
+//                     ^
+// pkg/front_end/testcases/nnbd/issue43354.dart:27:9: Context: This constructor is const.
+//   const D();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::A
+    : super core::Object::•()
+    ;
+}
+class B extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::B
+    : super core::Object::•()
+    ;
+}
+class C extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  const constructor •() → self::C
+    : super core::Object::•()
+    ;
+  const constructor another() → self::C
+    : super core::Object::•()
+    ;
+}
+class D extends core::Object /*hasConstConstructor*/  {
+  late final field core::int foo = 42;
+  late final field core::String bar = "foobar";
+  const constructor •() → self::D
+    : super core::Object::•()
+    ;
+  const constructor another() → self::D
+    : super core::Object::•()
+    ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart b/pkg/front_end/testcases/nnbd/issue43455.dart
new file mode 100644
index 0000000..8501673
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+assertRightSubtype(dynamic x) {
+  x as Set<Object?>;
+}
+
+assertLeftSubtype<X>(X x) {
+  new Set<Object?>() as X;
+}
+
+class C<X extends Object?, Y extends Object> {
+  test(X x, Y? y) {
+    var v = {x, 42}; // Checking UP(X, int).
+    var w = {42, x}; // Checking UP(int, X).
+    var p = {y, 42}; // Checking UP(Y?, int).
+    var q = {42, y}; // Checking UP(int, Y?).
+
+    // Check that variable types are both subtype and supertype of Set<Object?>.
+    assertRightSubtype(v);
+    assertLeftSubtype(v);
+    assertRightSubtype(w);
+    assertLeftSubtype(w);
+    assertRightSubtype(p);
+    assertLeftSubtype(p);
+    assertRightSubtype(q);
+    assertLeftSubtype(q);
+
+    // Check the same for intersection types.
+    if (x is Object?) {
+      var v = {x, 42}; // Checking UP(X & Object?, int).
+      var w = {42, x}; // Checking UP(int, X & Object?).
+
+      assertRightSubtype(v);
+      assertLeftSubtype(v);
+      assertRightSubtype(w);
+      assertLeftSubtype(w);
+    }
+  }
+}
+
+main() {
+  new C<int?, int>().test(42, null);
+  new C<int?, int>().test(null, null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.outline.expect
new file mode 100644
index 0000000..d9fa31c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y>
+    ;
+  method test(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y? y) → dynamic
+    ;
+}
+static method assertRightSubtype(dynamic x) → dynamic
+  ;
+static method assertLeftSubtype<X extends core::Object? = dynamic>(self::assertLeftSubtype::X% x) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.strong.expect
new file mode 100644
index 0000000..0acee2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.strong.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y>
+    : super core::Object::•()
+    ;
+  method test(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y? y) → dynamic {
+    core::Set<core::Object?> v = let final core::Set<core::Object?> #t1 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t2 = #t1.{core::Set::add}(x) in let final dynamic #t3 = #t1.{core::Set::add}(42) in #t1;
+    core::Set<core::Object?> w = let final core::Set<core::Object?> #t4 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t5 = #t4.{core::Set::add}(42) in let final dynamic #t6 = #t4.{core::Set::add}(x) in #t4;
+    core::Set<core::Object?> p = let final core::Set<core::Object?> #t7 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t8 = #t7.{core::Set::add}(y) in let final dynamic #t9 = #t7.{core::Set::add}(42) in #t7;
+    core::Set<core::Object?> q = let final core::Set<core::Object?> #t10 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t11 = #t10.{core::Set::add}(42) in let final dynamic #t12 = #t10.{core::Set::add}(y) in #t10;
+    self::assertRightSubtype(v);
+    self::assertLeftSubtype<core::Set<core::Object?>>(v);
+    self::assertRightSubtype(w);
+    self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    self::assertRightSubtype(p);
+    self::assertLeftSubtype<core::Set<core::Object?>>(p);
+    self::assertRightSubtype(q);
+    self::assertLeftSubtype<core::Set<core::Object?>>(q);
+    if(x is{ForNonNullableByDefault} core::Object?) {
+      core::Set<core::Object?> v = let final core::Set<core::Object?> #t13 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t14 = #t13.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in let final dynamic #t15 = #t13.{core::Set::add}(42) in #t13;
+      core::Set<core::Object?> w = let final core::Set<core::Object?> #t16 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t17 = #t16.{core::Set::add}(42) in let final dynamic #t18 = #t16.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in #t16;
+      self::assertRightSubtype(v);
+      self::assertLeftSubtype<core::Set<core::Object?>>(v);
+      self::assertRightSubtype(w);
+      self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    }
+  }
+}
+static method assertRightSubtype(dynamic x) → dynamic {
+  x as{ForNonNullableByDefault} core::Set<core::Object?>;
+}
+static method assertLeftSubtype<X extends core::Object? = dynamic>(self::assertLeftSubtype::X% x) → dynamic {
+  col::LinkedHashSet::•<core::Object?>() as{ForNonNullableByDefault} self::assertLeftSubtype::X%;
+}
+static method main() → dynamic {
+  new self::C::•<core::int?, core::int>().{self::C::test}(42, null);
+  new self::C::•<core::int?, core::int>().{self::C::test}(null, null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.strong.transformed.expect
new file mode 100644
index 0000000..49327f3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.strong.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y>
+    : super core::Object::•()
+    ;
+  method test(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y? y) → dynamic {
+    core::Set<core::Object?> v = let final core::Set<core::Object?> #t1 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t2 = #t1.{core::Set::add}(x) in let final core::bool #t3 = #t1.{core::Set::add}(42) in #t1;
+    core::Set<core::Object?> w = let final core::Set<core::Object?> #t4 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t5 = #t4.{core::Set::add}(42) in let final core::bool #t6 = #t4.{core::Set::add}(x) in #t4;
+    core::Set<core::Object?> p = let final core::Set<core::Object?> #t7 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t8 = #t7.{core::Set::add}(y) in let final core::bool #t9 = #t7.{core::Set::add}(42) in #t7;
+    core::Set<core::Object?> q = let final core::Set<core::Object?> #t10 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t11 = #t10.{core::Set::add}(42) in let final core::bool #t12 = #t10.{core::Set::add}(y) in #t10;
+    self::assertRightSubtype(v);
+    self::assertLeftSubtype<core::Set<core::Object?>>(v);
+    self::assertRightSubtype(w);
+    self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    self::assertRightSubtype(p);
+    self::assertLeftSubtype<core::Set<core::Object?>>(p);
+    self::assertRightSubtype(q);
+    self::assertLeftSubtype<core::Set<core::Object?>>(q);
+    if(x is{ForNonNullableByDefault} core::Object?) {
+      core::Set<core::Object?> v = let final core::Set<core::Object?> #t13 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t14 = #t13.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in let final core::bool #t15 = #t13.{core::Set::add}(42) in #t13;
+      core::Set<core::Object?> w = let final core::Set<core::Object?> #t16 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t17 = #t16.{core::Set::add}(42) in let final core::bool #t18 = #t16.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in #t16;
+      self::assertRightSubtype(v);
+      self::assertLeftSubtype<core::Set<core::Object?>>(v);
+      self::assertRightSubtype(w);
+      self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    }
+  }
+}
+static method assertRightSubtype(dynamic x) → dynamic {
+  x as{ForNonNullableByDefault} core::Set<core::Object?>;
+}
+static method assertLeftSubtype<X extends core::Object? = dynamic>(self::assertLeftSubtype::X% x) → dynamic {
+  new col::_CompactLinkedHashSet::•<core::Object?>() as{ForNonNullableByDefault} self::assertLeftSubtype::X%;
+}
+static method main() → dynamic {
+  new self::C::•<core::int?, core::int>().{self::C::test}(42, null);
+  new self::C::•<core::int?, core::int>().{self::C::test}(null, null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline.expect
new file mode 100644
index 0000000..4ec51c7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+assertRightSubtype(dynamic x) {}
+assertLeftSubtype<X>(X x) {}
+
+class C<X extends Object?, Y extends Object> {
+  test(X x, Y? y) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..287d84a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+assertLeftSubtype<X>(X x) {}
+assertRightSubtype(dynamic x) {}
+
+class C<X extends Object?, Y extends Object> {
+  test(X x, Y? y) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.weak.expect
new file mode 100644
index 0000000..0acee2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.weak.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y>
+    : super core::Object::•()
+    ;
+  method test(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y? y) → dynamic {
+    core::Set<core::Object?> v = let final core::Set<core::Object?> #t1 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t2 = #t1.{core::Set::add}(x) in let final dynamic #t3 = #t1.{core::Set::add}(42) in #t1;
+    core::Set<core::Object?> w = let final core::Set<core::Object?> #t4 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t5 = #t4.{core::Set::add}(42) in let final dynamic #t6 = #t4.{core::Set::add}(x) in #t4;
+    core::Set<core::Object?> p = let final core::Set<core::Object?> #t7 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t8 = #t7.{core::Set::add}(y) in let final dynamic #t9 = #t7.{core::Set::add}(42) in #t7;
+    core::Set<core::Object?> q = let final core::Set<core::Object?> #t10 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t11 = #t10.{core::Set::add}(42) in let final dynamic #t12 = #t10.{core::Set::add}(y) in #t10;
+    self::assertRightSubtype(v);
+    self::assertLeftSubtype<core::Set<core::Object?>>(v);
+    self::assertRightSubtype(w);
+    self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    self::assertRightSubtype(p);
+    self::assertLeftSubtype<core::Set<core::Object?>>(p);
+    self::assertRightSubtype(q);
+    self::assertLeftSubtype<core::Set<core::Object?>>(q);
+    if(x is{ForNonNullableByDefault} core::Object?) {
+      core::Set<core::Object?> v = let final core::Set<core::Object?> #t13 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t14 = #t13.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in let final dynamic #t15 = #t13.{core::Set::add}(42) in #t13;
+      core::Set<core::Object?> w = let final core::Set<core::Object?> #t16 = col::LinkedHashSet::•<core::Object?>() in let final dynamic #t17 = #t16.{core::Set::add}(42) in let final dynamic #t18 = #t16.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in #t16;
+      self::assertRightSubtype(v);
+      self::assertLeftSubtype<core::Set<core::Object?>>(v);
+      self::assertRightSubtype(w);
+      self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    }
+  }
+}
+static method assertRightSubtype(dynamic x) → dynamic {
+  x as{ForNonNullableByDefault} core::Set<core::Object?>;
+}
+static method assertLeftSubtype<X extends core::Object? = dynamic>(self::assertLeftSubtype::X% x) → dynamic {
+  col::LinkedHashSet::•<core::Object?>() as{ForNonNullableByDefault} self::assertLeftSubtype::X%;
+}
+static method main() → dynamic {
+  new self::C::•<core::int?, core::int>().{self::C::test}(42, null);
+  new self::C::•<core::int?, core::int>().{self::C::test}(null, null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43455.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43455.dart.weak.transformed.expect
new file mode 100644
index 0000000..49327f3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43455.dart.weak.transformed.expect
@@ -0,0 +1,42 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C<X extends core::Object? = core::Object?, Y extends core::Object = core::Object> extends core::Object {
+  synthetic constructor •() → self::C<self::C::X%, self::C::Y>
+    : super core::Object::•()
+    ;
+  method test(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y? y) → dynamic {
+    core::Set<core::Object?> v = let final core::Set<core::Object?> #t1 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t2 = #t1.{core::Set::add}(x) in let final core::bool #t3 = #t1.{core::Set::add}(42) in #t1;
+    core::Set<core::Object?> w = let final core::Set<core::Object?> #t4 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t5 = #t4.{core::Set::add}(42) in let final core::bool #t6 = #t4.{core::Set::add}(x) in #t4;
+    core::Set<core::Object?> p = let final core::Set<core::Object?> #t7 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t8 = #t7.{core::Set::add}(y) in let final core::bool #t9 = #t7.{core::Set::add}(42) in #t7;
+    core::Set<core::Object?> q = let final core::Set<core::Object?> #t10 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t11 = #t10.{core::Set::add}(42) in let final core::bool #t12 = #t10.{core::Set::add}(y) in #t10;
+    self::assertRightSubtype(v);
+    self::assertLeftSubtype<core::Set<core::Object?>>(v);
+    self::assertRightSubtype(w);
+    self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    self::assertRightSubtype(p);
+    self::assertLeftSubtype<core::Set<core::Object?>>(p);
+    self::assertRightSubtype(q);
+    self::assertLeftSubtype<core::Set<core::Object?>>(q);
+    if(x is{ForNonNullableByDefault} core::Object?) {
+      core::Set<core::Object?> v = let final core::Set<core::Object?> #t13 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t14 = #t13.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in let final core::bool #t15 = #t13.{core::Set::add}(42) in #t13;
+      core::Set<core::Object?> w = let final core::Set<core::Object?> #t16 = new col::_CompactLinkedHashSet::•<core::Object?>() in let final core::bool #t17 = #t16.{core::Set::add}(42) in let final core::bool #t18 = #t16.{core::Set::add}(x{self::C::X% & core::Object? /* '%' & '?' = '%' */}) in #t16;
+      self::assertRightSubtype(v);
+      self::assertLeftSubtype<core::Set<core::Object?>>(v);
+      self::assertRightSubtype(w);
+      self::assertLeftSubtype<core::Set<core::Object?>>(w);
+    }
+  }
+}
+static method assertRightSubtype(dynamic x) → dynamic {
+  x as{ForNonNullableByDefault} core::Set<core::Object?>;
+}
+static method assertLeftSubtype<X extends core::Object? = dynamic>(self::assertLeftSubtype::X% x) → dynamic {
+  new col::_CompactLinkedHashSet::•<core::Object?>() as{ForNonNullableByDefault} self::assertLeftSubtype::X%;
+}
+static method main() → dynamic {
+  new self::C::•<core::int?, core::int>().{self::C::test}(42, null);
+  new self::C::•<core::int?, core::int>().{self::C::test}(null, null);
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart b/pkg/front_end/testcases/nnbd/issue43495.dart
new file mode 100644
index 0000000..993306d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+foo(bool condition, Iterable<dynamic> iterable, List<int>? a, Set<int>? b,
+    Iterable<int>? c, Map<int, int>? d) {
+  return [
+    {...a}, // Error.
+    {...b}, // Error.
+    {...c}, // Error.
+    {...d}, // Error.
+    <int, int>{...a}, // Error.
+    <int>{...d}, // Error.
+    {if (condition) ...a}, // Error.
+    {if (condition) ...b}, // Error.
+    {if (condition) ...c}, // Error.
+    {if (condition) ...d}, // Error.
+    {for (dynamic e in iterable) ...a}, // Error.
+    {for (dynamic e in iterable) ...b}, // Error.
+    {for (dynamic e in iterable) ...c}, // Error.
+    {for (dynamic e in iterable) ...d}, // Error.
+    {for (int i = 0; i < 42; ++i) ...a}, // Error.
+    {for (int i = 0; i < 42; ++i) ...b}, // Error.
+    {for (int i = 0; i < 42; ++i) ...c}, // Error.
+    {for (int i = 0; i < 42; ++i) ...d}, // Error.
+
+    {...?a}, // Ok.
+    {...?b}, // Ok.
+    {...?c}, // Ok.
+    {...?d}, // Ok.
+    {if (condition) ...?a}, // Ok.
+    {if (condition) ...?b}, // Ok.
+    {if (condition) ...?c}, // Ok.
+    {if (condition) ...?d}, // Ok.
+    {for (dynamic e in iterable) ...?a}, // Ok.
+    {for (dynamic e in iterable) ...?b}, // Ok.
+    {for (dynamic e in iterable) ...?c}, // Ok.
+    {for (dynamic e in iterable) ...?d}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?a}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?b}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?c}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?d}, // Ok.
+  ];
+}
+
+bar<X extends List<int>?, Y extends Set<int>?, Z extends Iterable<int>?,
+        W extends Map<int, int>?>(
+    bool condition, Iterable<dynamic> iterable, X x, Y y, Z z, W w) {
+  return [
+    {...x}, // Error.
+    {...y}, // Error.
+    {...z}, // Error.
+    {...w}, // Error.
+    <int, int>{...x}, // Error.
+    <int>{...w}, // Error.
+    {if (condition) ...x}, // Error.
+    {if (condition) ...y}, // Error.
+    {if (condition) ...z}, // Error.
+    {if (condition) ...w}, // Error.
+    {for (dynamic e in iterable) ...x}, // Error.
+    {for (dynamic e in iterable) ...y}, // Error.
+    {for (dynamic e in iterable) ...z}, // Error.
+    {for (dynamic e in iterable) ...w}, // Error.
+    {for (int i = 0; i < 42; ++i) ...x}, // Error.
+    {for (int i = 0; i < 42; ++i) ...y}, // Error.
+    {for (int i = 0; i < 42; ++i) ...z}, // Error.
+    {for (int i = 0; i < 42; ++i) ...w}, // Error.
+
+    {...?x}, // Ok.
+    {...?y}, // Ok.
+    {...?z}, // Ok.
+    {...?w}, // Ok.
+    {if (condition) ...?x}, // Ok.
+    {if (condition) ...?y}, // Ok.
+    {if (condition) ...?z}, // Ok.
+    {if (condition) ...?w}, // Ok.
+    {for (dynamic e in iterable) ...?x}, // Ok.
+    {for (dynamic e in iterable) ...?y}, // Ok.
+    {for (dynamic e in iterable) ...?z}, // Ok.
+    {for (dynamic e in iterable) ...?w}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?x}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?y}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?z}, // Ok.
+    {for (int i = 0; i < 42; ++i) ...?w}, // Ok.
+  ];
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.outline.expect
new file mode 100644
index 0000000..89dfdbb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.outline.expect
@@ -0,0 +1,10 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+static method foo(core::bool condition, core::Iterable<dynamic> iterable, core::List<core::int>? a, core::Set<core::int>? b, core::Iterable<core::int>? c, core::Map<core::int, core::int>? d) → dynamic
+  ;
+static method bar<X extends core::List<core::int>? = core::List<core::int>?, Y extends core::Set<core::int>? = core::Set<core::int>?, Z extends core::Iterable<core::int>? = core::Iterable<core::int>?, W extends core::Map<core::int, core::int>? = core::Map<core::int, core::int>?>(core::bool condition, core::Iterable<dynamic> iterable, self::bar::X% x, self::bar::Y% y, self::bar::Z% z, self::bar::W% w) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.strong.expect
new file mode 100644
index 0000000..e89957c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.strong.expect
@@ -0,0 +1,725 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...a}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...b}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...c}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...d}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+//  - 'List' is from 'dart:core'.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...a}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...b}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...c}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...d}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...a}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...b}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...c}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...d}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...a}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...b}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...c}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...d}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...x}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...y}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...z}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...w}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...x}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...y}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...z}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...w}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...x}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...y}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...z}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...w}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...x}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...y}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...z}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...w}, // Error.
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method foo(core::bool condition, core::Iterable<dynamic> iterable, core::List<core::int>? a, core::Set<core::int>? b, core::Iterable<core::int>? c, core::Map<core::int, core::int>? d) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t2 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...a}, // Error.
+        ^") {
+      final core::int #t3 = #t2 as{TypeError,ForNonNullableByDefault} core::int;
+      #t1.{core::Set::add}(#t3);
+    }
+  } =>#t1, block {
+    final core::Set<core::int> #t4 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t5 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...b}, // Error.
+        ^") {
+      final core::int #t6 = #t5 as{TypeError,ForNonNullableByDefault} core::int;
+      #t4.{core::Set::add}(#t6);
+    }
+  } =>#t4, block {
+    final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t8 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...c}, // Error.
+        ^") {
+      final core::int #t9 = #t8 as{TypeError,ForNonNullableByDefault} core::int;
+      #t7.{core::Set::add}(#t9);
+    }
+  } =>#t7, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...d}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+ - 'List' is from 'dart:core'.
+    <int, int>{...a}, // Error.
+                  ^": null}, let final core::Set<core::int> #t10 = col::LinkedHashSet::•<core::int>() in let final dynamic #t11 = #t10.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+    <int>{...d}, // Error.
+             ^") in #t10, block {
+    final core::Set<core::int> #t12 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t13 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...a}, // Error.
+                       ^") {
+        final core::int #t14 = #t13 as{TypeError,ForNonNullableByDefault} core::int;
+        #t12.{core::Set::add}(#t14);
+      }
+  } =>#t12, block {
+    final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t16 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...b}, // Error.
+                       ^") {
+        final core::int #t17 = #t16 as{TypeError,ForNonNullableByDefault} core::int;
+        #t15.{core::Set::add}(#t17);
+      }
+  } =>#t15, block {
+    final core::Set<core::int> #t18 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t19 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...c}, // Error.
+                       ^") {
+        final core::int #t20 = #t19 as{TypeError,ForNonNullableByDefault} core::int;
+        #t18.{core::Set::add}(#t20);
+      }
+  } =>#t18, block {
+    final core::Map<core::int, core::int> #t21 = <core::int, core::int>{};
+    if(condition)
+      #t21.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...d}, // Error.
+                       ^", null);
+  } =>#t21, block {
+    final core::Set<core::int> #t22 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t23 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...a}, // Error.
+                                    ^") {
+        final core::int #t24 = #t23 as{TypeError,ForNonNullableByDefault} core::int;
+        #t22.{core::Set::add}(#t24);
+      }
+  } =>#t22, block {
+    final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t26 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...b}, // Error.
+                                    ^") {
+        final core::int #t27 = #t26 as{TypeError,ForNonNullableByDefault} core::int;
+        #t25.{core::Set::add}(#t27);
+      }
+  } =>#t25, block {
+    final core::Set<core::int> #t28 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t29 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...c}, // Error.
+                                    ^") {
+        final core::int #t30 = #t29 as{TypeError,ForNonNullableByDefault} core::int;
+        #t28.{core::Set::add}(#t30);
+      }
+  } =>#t28, block {
+    final core::Map<core::int, core::int> #t31 = <core::int, core::int>{};
+    for (dynamic e in iterable)
+      #t31.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...d}, // Error.
+                                    ^", null);
+  } =>#t31, block {
+    final core::Set<core::int> #t32 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t33 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...a}, // Error.
+                                     ^") {
+        final core::int #t34 = #t33 as{TypeError,ForNonNullableByDefault} core::int;
+        #t32.{core::Set::add}(#t34);
+      }
+  } =>#t32, block {
+    final core::Set<core::int> #t35 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t36 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...b}, // Error.
+                                     ^") {
+        final core::int #t37 = #t36 as{TypeError,ForNonNullableByDefault} core::int;
+        #t35.{core::Set::add}(#t37);
+      }
+  } =>#t35, block {
+    final core::Set<core::int> #t38 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t39 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...c}, // Error.
+                                     ^") {
+        final core::int #t40 = #t39 as{TypeError,ForNonNullableByDefault} core::int;
+        #t38.{core::Set::add}(#t40);
+      }
+  } =>#t38, block {
+    final core::Map<core::int, core::int> #t41 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t41.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...d}, // Error.
+                                     ^", null);
+  } =>#t41, block {
+    final core::Set<core::int> #t42 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t43 = a;
+    if(!#t43.{core::Object::==}(null))
+      for (final dynamic #t44 in #t43{core::Iterable<dynamic>}) {
+        final core::int #t45 = #t44 as{TypeError,ForNonNullableByDefault} core::int;
+        #t42.{core::Set::add}(#t45);
+      }
+  } =>#t42, block {
+    final core::Set<core::int> #t46 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t47 = b;
+    if(!#t47.{core::Object::==}(null))
+      for (final dynamic #t48 in #t47{core::Iterable<dynamic>}) {
+        final core::int #t49 = #t48 as{TypeError,ForNonNullableByDefault} core::int;
+        #t46.{core::Set::add}(#t49);
+      }
+  } =>#t46, block {
+    final core::Set<core::int> #t50 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t51 = c;
+    if(!#t51.{core::Object::==}(null))
+      for (final dynamic #t52 in #t51{core::Iterable<dynamic>}) {
+        final core::int #t53 = #t52 as{TypeError,ForNonNullableByDefault} core::int;
+        #t50.{core::Set::add}(#t53);
+      }
+  } =>#t50, block {
+    final core::Map<core::int, core::int> #t54 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t55 = d;
+    if(!#t55.{core::Object::==}(null))
+      for (final core::MapEntry<core::int, core::int> #t56 in #t55{core::Map<core::int, core::int>}.{core::Map::entries})
+        #t54.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
+  } =>#t54, block {
+    final core::Set<core::int> #t57 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t58 = a;
+      if(!#t58.{core::Object::==}(null))
+        for (final dynamic #t59 in #t58{core::Iterable<dynamic>}) {
+          final core::int #t60 = #t59 as{TypeError,ForNonNullableByDefault} core::int;
+          #t57.{core::Set::add}(#t60);
+        }
+    }
+  } =>#t57, block {
+    final core::Set<core::int> #t61 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t62 = b;
+      if(!#t62.{core::Object::==}(null))
+        for (final dynamic #t63 in #t62{core::Iterable<dynamic>}) {
+          final core::int #t64 = #t63 as{TypeError,ForNonNullableByDefault} core::int;
+          #t61.{core::Set::add}(#t64);
+        }
+    }
+  } =>#t61, block {
+    final core::Set<core::int> #t65 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t66 = c;
+      if(!#t66.{core::Object::==}(null))
+        for (final dynamic #t67 in #t66{core::Iterable<dynamic>}) {
+          final core::int #t68 = #t67 as{TypeError,ForNonNullableByDefault} core::int;
+          #t65.{core::Set::add}(#t68);
+        }
+    }
+  } =>#t65, block {
+    final core::Map<core::int, core::int> #t69 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t70 = d;
+      if(!#t70.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t71 in #t70{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t69.{core::Map::[]=}(#t71.{core::MapEntry::key}, #t71.{core::MapEntry::value});
+    }
+  } =>#t69, block {
+    final core::Set<core::int> #t72 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t73 = a;
+      if(!#t73.{core::Object::==}(null))
+        for (final dynamic #t74 in #t73{core::Iterable<dynamic>}) {
+          final core::int #t75 = #t74 as{TypeError,ForNonNullableByDefault} core::int;
+          #t72.{core::Set::add}(#t75);
+        }
+    }
+  } =>#t72, block {
+    final core::Set<core::int> #t76 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t77 = b;
+      if(!#t77.{core::Object::==}(null))
+        for (final dynamic #t78 in #t77{core::Iterable<dynamic>}) {
+          final core::int #t79 = #t78 as{TypeError,ForNonNullableByDefault} core::int;
+          #t76.{core::Set::add}(#t79);
+        }
+    }
+  } =>#t76, block {
+    final core::Set<core::int> #t80 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t81 = c;
+      if(!#t81.{core::Object::==}(null))
+        for (final dynamic #t82 in #t81{core::Iterable<dynamic>}) {
+          final core::int #t83 = #t82 as{TypeError,ForNonNullableByDefault} core::int;
+          #t80.{core::Set::add}(#t83);
+        }
+    }
+  } =>#t80, block {
+    final core::Map<core::int, core::int> #t84 = <core::int, core::int>{};
+    for (dynamic e in iterable) {
+      final core::Map<core::int, core::int>? #t85 = d;
+      if(!#t85.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t86 in #t85{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t84.{core::Map::[]=}(#t86.{core::MapEntry::key}, #t86.{core::MapEntry::value});
+    }
+  } =>#t84, block {
+    final core::Set<core::int> #t87 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t88 = a;
+      if(!#t88.{core::Object::==}(null))
+        for (final dynamic #t89 in #t88{core::Iterable<dynamic>}) {
+          final core::int #t90 = #t89 as{TypeError,ForNonNullableByDefault} core::int;
+          #t87.{core::Set::add}(#t90);
+        }
+    }
+  } =>#t87, block {
+    final core::Set<core::int> #t91 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t92 = b;
+      if(!#t92.{core::Object::==}(null))
+        for (final dynamic #t93 in #t92{core::Iterable<dynamic>}) {
+          final core::int #t94 = #t93 as{TypeError,ForNonNullableByDefault} core::int;
+          #t91.{core::Set::add}(#t94);
+        }
+    }
+  } =>#t91, block {
+    final core::Set<core::int> #t95 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t96 = c;
+      if(!#t96.{core::Object::==}(null))
+        for (final dynamic #t97 in #t96{core::Iterable<dynamic>}) {
+          final core::int #t98 = #t97 as{TypeError,ForNonNullableByDefault} core::int;
+          #t95.{core::Set::add}(#t98);
+        }
+    }
+  } =>#t95, block {
+    final core::Map<core::int, core::int> #t99 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t100 = d;
+      if(!#t100.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t101 in #t100{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t99.{core::Map::[]=}(#t101.{core::MapEntry::key}, #t101.{core::MapEntry::value});
+    }
+  } =>#t99];
+}
+static method bar<X extends core::List<core::int>? = core::List<core::int>?, Y extends core::Set<core::int>? = core::Set<core::int>?, Z extends core::Iterable<core::int>? = core::Iterable<core::int>?, W extends core::Map<core::int, core::int>? = core::Map<core::int, core::int>?>(core::bool condition, core::Iterable<dynamic> iterable, self::bar::X% x, self::bar::Y% y, self::bar::Z% z, self::bar::W% w) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t102 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t103 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...x}, // Error.
+        ^") {
+      final core::int #t104 = #t103 as{TypeError,ForNonNullableByDefault} core::int;
+      #t102.{core::Set::add}(#t104);
+    }
+  } =>#t102, block {
+    final core::Set<core::int> #t105 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t106 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...y}, // Error.
+        ^") {
+      final core::int #t107 = #t106 as{TypeError,ForNonNullableByDefault} core::int;
+      #t105.{core::Set::add}(#t107);
+    }
+  } =>#t105, block {
+    final core::Set<core::int> #t108 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t109 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...z}, // Error.
+        ^") {
+      final core::int #t110 = #t109 as{TypeError,ForNonNullableByDefault} core::int;
+      #t108.{core::Set::add}(#t110);
+    }
+  } =>#t108, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...w}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+    <int, int>{...x}, // Error.
+                  ^": null}, let final core::Set<core::int> #t111 = col::LinkedHashSet::•<core::int>() in let final dynamic #t112 = #t111.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+    <int>{...w}, // Error.
+             ^") in #t111, block {
+    final core::Set<core::int> #t113 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t114 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...x}, // Error.
+                       ^") {
+        final core::int #t115 = #t114 as{TypeError,ForNonNullableByDefault} core::int;
+        #t113.{core::Set::add}(#t115);
+      }
+  } =>#t113, block {
+    final core::Set<core::int> #t116 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t117 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...y}, // Error.
+                       ^") {
+        final core::int #t118 = #t117 as{TypeError,ForNonNullableByDefault} core::int;
+        #t116.{core::Set::add}(#t118);
+      }
+  } =>#t116, block {
+    final core::Set<core::int> #t119 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t120 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...z}, // Error.
+                       ^") {
+        final core::int #t121 = #t120 as{TypeError,ForNonNullableByDefault} core::int;
+        #t119.{core::Set::add}(#t121);
+      }
+  } =>#t119, block {
+    final core::Map<core::int, core::int> #t122 = <core::int, core::int>{};
+    if(condition)
+      #t122.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...w}, // Error.
+                       ^", null);
+  } =>#t122, block {
+    final core::Set<core::int> #t123 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t124 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...x}, // Error.
+                                    ^") {
+        final core::int #t125 = #t124 as{TypeError,ForNonNullableByDefault} core::int;
+        #t123.{core::Set::add}(#t125);
+      }
+  } =>#t123, block {
+    final core::Set<core::int> #t126 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t127 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...y}, // Error.
+                                    ^") {
+        final core::int #t128 = #t127 as{TypeError,ForNonNullableByDefault} core::int;
+        #t126.{core::Set::add}(#t128);
+      }
+  } =>#t126, block {
+    final core::Set<core::int> #t129 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t130 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...z}, // Error.
+                                    ^") {
+        final core::int #t131 = #t130 as{TypeError,ForNonNullableByDefault} core::int;
+        #t129.{core::Set::add}(#t131);
+      }
+  } =>#t129, block {
+    final core::Map<core::int, core::int> #t132 = <core::int, core::int>{};
+    for (dynamic e in iterable)
+      #t132.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...w}, // Error.
+                                    ^", null);
+  } =>#t132, block {
+    final core::Set<core::int> #t133 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t134 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...x}, // Error.
+                                     ^") {
+        final core::int #t135 = #t134 as{TypeError,ForNonNullableByDefault} core::int;
+        #t133.{core::Set::add}(#t135);
+      }
+  } =>#t133, block {
+    final core::Set<core::int> #t136 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t137 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...y}, // Error.
+                                     ^") {
+        final core::int #t138 = #t137 as{TypeError,ForNonNullableByDefault} core::int;
+        #t136.{core::Set::add}(#t138);
+      }
+  } =>#t136, block {
+    final core::Set<core::int> #t139 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t140 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...z}, // Error.
+                                     ^") {
+        final core::int #t141 = #t140 as{TypeError,ForNonNullableByDefault} core::int;
+        #t139.{core::Set::add}(#t141);
+      }
+  } =>#t139, block {
+    final core::Map<core::int, core::int> #t142 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t142.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...w}, // Error.
+                                     ^", null);
+  } =>#t142, block {
+    final core::Set<core::int> #t143 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t144 = x;
+    if(!#t144.{core::Object::==}(null))
+      for (final dynamic #t145 in #t144{core::Iterable<dynamic>}) {
+        final core::int #t146 = #t145 as{TypeError,ForNonNullableByDefault} core::int;
+        #t143.{core::Set::add}(#t146);
+      }
+  } =>#t143, block {
+    final core::Set<core::int> #t147 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t148 = y;
+    if(!#t148.{core::Object::==}(null))
+      for (final dynamic #t149 in #t148{core::Iterable<dynamic>}) {
+        final core::int #t150 = #t149 as{TypeError,ForNonNullableByDefault} core::int;
+        #t147.{core::Set::add}(#t150);
+      }
+  } =>#t147, block {
+    final core::Set<core::int> #t151 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t152 = z;
+    if(!#t152.{core::Object::==}(null))
+      for (final dynamic #t153 in #t152{core::Iterable<dynamic>}) {
+        final core::int #t154 = #t153 as{TypeError,ForNonNullableByDefault} core::int;
+        #t151.{core::Set::add}(#t154);
+      }
+  } =>#t151, block {
+    final core::Map<core::int, core::int> #t155 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t156 = w;
+    if(!#t156.{core::Object::==}(null))
+      for (final core::MapEntry<core::int, core::int> #t157 in #t156{core::Map<core::int, core::int>}.{core::Map::entries})
+        #t155.{core::Map::[]=}(#t157.{core::MapEntry::key}, #t157.{core::MapEntry::value});
+  } =>#t155, block {
+    final core::Set<core::int> #t158 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t159 = x;
+      if(!#t159.{core::Object::==}(null))
+        for (final dynamic #t160 in #t159{core::Iterable<dynamic>}) {
+          final core::int #t161 = #t160 as{TypeError,ForNonNullableByDefault} core::int;
+          #t158.{core::Set::add}(#t161);
+        }
+    }
+  } =>#t158, block {
+    final core::Set<core::int> #t162 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t163 = y;
+      if(!#t163.{core::Object::==}(null))
+        for (final dynamic #t164 in #t163{core::Iterable<dynamic>}) {
+          final core::int #t165 = #t164 as{TypeError,ForNonNullableByDefault} core::int;
+          #t162.{core::Set::add}(#t165);
+        }
+    }
+  } =>#t162, block {
+    final core::Set<core::int> #t166 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t167 = z;
+      if(!#t167.{core::Object::==}(null))
+        for (final dynamic #t168 in #t167{core::Iterable<dynamic>}) {
+          final core::int #t169 = #t168 as{TypeError,ForNonNullableByDefault} core::int;
+          #t166.{core::Set::add}(#t169);
+        }
+    }
+  } =>#t166, block {
+    final core::Map<core::int, core::int> #t170 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t171 = w;
+      if(!#t171.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t172 in #t171{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t170.{core::Map::[]=}(#t172.{core::MapEntry::key}, #t172.{core::MapEntry::value});
+    }
+  } =>#t170, block {
+    final core::Set<core::int> #t173 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t174 = x;
+      if(!#t174.{core::Object::==}(null))
+        for (final dynamic #t175 in #t174{core::Iterable<dynamic>}) {
+          final core::int #t176 = #t175 as{TypeError,ForNonNullableByDefault} core::int;
+          #t173.{core::Set::add}(#t176);
+        }
+    }
+  } =>#t173, block {
+    final core::Set<core::int> #t177 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t178 = y;
+      if(!#t178.{core::Object::==}(null))
+        for (final dynamic #t179 in #t178{core::Iterable<dynamic>}) {
+          final core::int #t180 = #t179 as{TypeError,ForNonNullableByDefault} core::int;
+          #t177.{core::Set::add}(#t180);
+        }
+    }
+  } =>#t177, block {
+    final core::Set<core::int> #t181 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t182 = z;
+      if(!#t182.{core::Object::==}(null))
+        for (final dynamic #t183 in #t182{core::Iterable<dynamic>}) {
+          final core::int #t184 = #t183 as{TypeError,ForNonNullableByDefault} core::int;
+          #t181.{core::Set::add}(#t184);
+        }
+    }
+  } =>#t181, block {
+    final core::Map<core::int, core::int> #t185 = <core::int, core::int>{};
+    for (dynamic e in iterable) {
+      final core::Map<core::int, core::int>? #t186 = w;
+      if(!#t186.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t187 in #t186{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t185.{core::Map::[]=}(#t187.{core::MapEntry::key}, #t187.{core::MapEntry::value});
+    }
+  } =>#t185, block {
+    final core::Set<core::int> #t188 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t189 = x;
+      if(!#t189.{core::Object::==}(null))
+        for (final dynamic #t190 in #t189{core::Iterable<dynamic>}) {
+          final core::int #t191 = #t190 as{TypeError,ForNonNullableByDefault} core::int;
+          #t188.{core::Set::add}(#t191);
+        }
+    }
+  } =>#t188, block {
+    final core::Set<core::int> #t192 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t193 = y;
+      if(!#t193.{core::Object::==}(null))
+        for (final dynamic #t194 in #t193{core::Iterable<dynamic>}) {
+          final core::int #t195 = #t194 as{TypeError,ForNonNullableByDefault} core::int;
+          #t192.{core::Set::add}(#t195);
+        }
+    }
+  } =>#t192, block {
+    final core::Set<core::int> #t196 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t197 = z;
+      if(!#t197.{core::Object::==}(null))
+        for (final dynamic #t198 in #t197{core::Iterable<dynamic>}) {
+          final core::int #t199 = #t198 as{TypeError,ForNonNullableByDefault} core::int;
+          #t196.{core::Set::add}(#t199);
+        }
+    }
+  } =>#t196, block {
+    final core::Map<core::int, core::int> #t200 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t201 = w;
+      if(!#t201.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t202 in #t201{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t200.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
+    }
+  } =>#t200];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.strong.transformed.expect
new file mode 100644
index 0000000..84cd03a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.strong.transformed.expect
@@ -0,0 +1,965 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...a}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...b}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...c}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...d}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+//  - 'List' is from 'dart:core'.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...a}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...b}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...c}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...d}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...a}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...b}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...c}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...d}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...a}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...b}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...c}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...d}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...x}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...y}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...z}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...w}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...x}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...y}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...z}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...w}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...x}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...y}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...z}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...w}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...x}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...y}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...z}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...w}, // Error.
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method foo(core::bool condition, core::Iterable<dynamic> iterable, core::List<core::int>? a, core::Set<core::int>? b, core::Iterable<core::int>? c, core::Map<core::int, core::int>? d) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t1 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t2 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...a}, // Error.
+        ^") {
+      final core::int #t3 = #t2 as{TypeError,ForNonNullableByDefault} core::int;
+      #t1.{core::Set::add}(#t3);
+    }
+  } =>#t1, block {
+    final core::Set<core::int> #t4 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t5 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...b}, // Error.
+        ^") {
+      final core::int #t6 = #t5 as{TypeError,ForNonNullableByDefault} core::int;
+      #t4.{core::Set::add}(#t6);
+    }
+  } =>#t4, block {
+    final core::Set<core::int> #t7 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t8 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...c}, // Error.
+        ^") {
+      final core::int #t9 = #t8 as{TypeError,ForNonNullableByDefault} core::int;
+      #t7.{core::Set::add}(#t9);
+    }
+  } =>#t7, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...d}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+ - 'List' is from 'dart:core'.
+    <int, int>{...a}, // Error.
+                  ^": null}, let final core::Set<core::int> #t10 = new col::_CompactLinkedHashSet::•<core::int>() in let final core::bool #t11 = #t10.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+    <int>{...d}, // Error.
+             ^") in #t10, block {
+    final core::Set<core::int> #t12 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t13 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...a}, // Error.
+                       ^") {
+        final core::int #t14 = #t13 as{TypeError,ForNonNullableByDefault} core::int;
+        #t12.{core::Set::add}(#t14);
+      }
+  } =>#t12, block {
+    final core::Set<core::int> #t15 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t16 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...b}, // Error.
+                       ^") {
+        final core::int #t17 = #t16 as{TypeError,ForNonNullableByDefault} core::int;
+        #t15.{core::Set::add}(#t17);
+      }
+  } =>#t15, block {
+    final core::Set<core::int> #t18 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t19 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...c}, // Error.
+                       ^") {
+        final core::int #t20 = #t19 as{TypeError,ForNonNullableByDefault} core::int;
+        #t18.{core::Set::add}(#t20);
+      }
+  } =>#t18, block {
+    final core::Map<core::int, core::int> #t21 = <core::int, core::int>{};
+    if(condition)
+      #t21.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...d}, // Error.
+                       ^", null);
+  } =>#t21, block {
+    final core::Set<core::int> #t22 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t23 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...a}, // Error.
+                                    ^") {
+          final core::int #t24 = #t23 as{TypeError,ForNonNullableByDefault} core::int;
+          #t22.{core::Set::add}(#t24);
+        }
+      }
+    }
+  } =>#t22, block {
+    final core::Set<core::int> #t25 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t26 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...b}, // Error.
+                                    ^") {
+          final core::int #t27 = #t26 as{TypeError,ForNonNullableByDefault} core::int;
+          #t25.{core::Set::add}(#t27);
+        }
+      }
+    }
+  } =>#t25, block {
+    final core::Set<core::int> #t28 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t29 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...c}, // Error.
+                                    ^") {
+          final core::int #t30 = #t29 as{TypeError,ForNonNullableByDefault} core::int;
+          #t28.{core::Set::add}(#t30);
+        }
+      }
+    }
+  } =>#t28, block {
+    final core::Map<core::int, core::int> #t31 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        #t31.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...d}, // Error.
+                                    ^", null);
+      }
+    }
+  } =>#t31, block {
+    final core::Set<core::int> #t32 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t33 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...a}, // Error.
+                                     ^") {
+        final core::int #t34 = #t33 as{TypeError,ForNonNullableByDefault} core::int;
+        #t32.{core::Set::add}(#t34);
+      }
+  } =>#t32, block {
+    final core::Set<core::int> #t35 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t36 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...b}, // Error.
+                                     ^") {
+        final core::int #t37 = #t36 as{TypeError,ForNonNullableByDefault} core::int;
+        #t35.{core::Set::add}(#t37);
+      }
+  } =>#t35, block {
+    final core::Set<core::int> #t38 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t39 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...c}, // Error.
+                                     ^") {
+        final core::int #t40 = #t39 as{TypeError,ForNonNullableByDefault} core::int;
+        #t38.{core::Set::add}(#t40);
+      }
+  } =>#t38, block {
+    final core::Map<core::int, core::int> #t41 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t41.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...d}, // Error.
+                                     ^", null);
+  } =>#t41, block {
+    final core::Set<core::int> #t42 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t43 = a;
+    if(!#t43.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t43{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t44 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t45 = #t44 as{TypeError,ForNonNullableByDefault} core::int;
+          #t42.{core::Set::add}(#t45);
+        }
+      }
+    }
+  } =>#t42, block {
+    final core::Set<core::int> #t46 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t47 = b;
+    if(!#t47.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t47{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t48 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t49 = #t48 as{TypeError,ForNonNullableByDefault} core::int;
+          #t46.{core::Set::add}(#t49);
+        }
+      }
+    }
+  } =>#t46, block {
+    final core::Set<core::int> #t50 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t51 = c;
+    if(!#t51.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t51{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t52 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t53 = #t52 as{TypeError,ForNonNullableByDefault} core::int;
+          #t50.{core::Set::add}(#t53);
+        }
+      }
+    }
+  } =>#t50, block {
+    final core::Map<core::int, core::int> #t54 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t55 = d;
+    if(!#t55.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t55{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::MapEntry<core::int, core::int> #t56 = :sync-for-iterator.{core::Iterator::current};
+        #t54.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
+      }
+    }
+  } =>#t54, block {
+    final core::Set<core::int> #t57 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t58 = a;
+      if(!#t58.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t58{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t59 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t60 = #t59 as{TypeError,ForNonNullableByDefault} core::int;
+            #t57.{core::Set::add}(#t60);
+          }
+        }
+      }
+    }
+  } =>#t57, block {
+    final core::Set<core::int> #t61 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t62 = b;
+      if(!#t62.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t62{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t63 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t64 = #t63 as{TypeError,ForNonNullableByDefault} core::int;
+            #t61.{core::Set::add}(#t64);
+          }
+        }
+      }
+    }
+  } =>#t61, block {
+    final core::Set<core::int> #t65 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t66 = c;
+      if(!#t66.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t66{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t67 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t68 = #t67 as{TypeError,ForNonNullableByDefault} core::int;
+            #t65.{core::Set::add}(#t68);
+          }
+        }
+      }
+    }
+  } =>#t65, block {
+    final core::Map<core::int, core::int> #t69 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t70 = d;
+      if(!#t70.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t70{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t71 = :sync-for-iterator.{core::Iterator::current};
+          #t69.{core::Map::[]=}(#t71.{core::MapEntry::key}, #t71.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t69, block {
+    final core::Set<core::int> #t72 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t73 = a;
+          if(!#t73.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t73{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t74 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t75 = #t74 as{TypeError,ForNonNullableByDefault} core::int;
+                #t72.{core::Set::add}(#t75);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t72, block {
+    final core::Set<core::int> #t76 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t77 = b;
+          if(!#t77.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t77{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t78 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t79 = #t78 as{TypeError,ForNonNullableByDefault} core::int;
+                #t76.{core::Set::add}(#t79);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t76, block {
+    final core::Set<core::int> #t80 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t81 = c;
+          if(!#t81.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t81{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t82 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t83 = #t82 as{TypeError,ForNonNullableByDefault} core::int;
+                #t80.{core::Set::add}(#t83);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t80, block {
+    final core::Map<core::int, core::int> #t84 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Map<core::int, core::int>? #t85 = d;
+          if(!#t85.{core::Object::==}(null)) {
+            core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t85{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final core::MapEntry<core::int, core::int> #t86 = :sync-for-iterator.{core::Iterator::current};
+              #t84.{core::Map::[]=}(#t86.{core::MapEntry::key}, #t86.{core::MapEntry::value});
+            }
+          }
+        }
+      }
+    }
+  } =>#t84, block {
+    final core::Set<core::int> #t87 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t88 = a;
+      if(!#t88.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t88{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t89 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t90 = #t89 as{TypeError,ForNonNullableByDefault} core::int;
+            #t87.{core::Set::add}(#t90);
+          }
+        }
+      }
+    }
+  } =>#t87, block {
+    final core::Set<core::int> #t91 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t92 = b;
+      if(!#t92.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t92{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t93 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t94 = #t93 as{TypeError,ForNonNullableByDefault} core::int;
+            #t91.{core::Set::add}(#t94);
+          }
+        }
+      }
+    }
+  } =>#t91, block {
+    final core::Set<core::int> #t95 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t96 = c;
+      if(!#t96.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t96{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t97 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t98 = #t97 as{TypeError,ForNonNullableByDefault} core::int;
+            #t95.{core::Set::add}(#t98);
+          }
+        }
+      }
+    }
+  } =>#t95, block {
+    final core::Map<core::int, core::int> #t99 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t100 = d;
+      if(!#t100.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t100{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t101 = :sync-for-iterator.{core::Iterator::current};
+          #t99.{core::Map::[]=}(#t101.{core::MapEntry::key}, #t101.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t99];
+}
+static method bar<X extends core::List<core::int>? = core::List<core::int>?, Y extends core::Set<core::int>? = core::Set<core::int>?, Z extends core::Iterable<core::int>? = core::Iterable<core::int>?, W extends core::Map<core::int, core::int>? = core::Map<core::int, core::int>?>(core::bool condition, core::Iterable<dynamic> iterable, self::bar::X% x, self::bar::Y% y, self::bar::Z% z, self::bar::W% w) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t102 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t103 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...x}, // Error.
+        ^") {
+      final core::int #t104 = #t103 as{TypeError,ForNonNullableByDefault} core::int;
+      #t102.{core::Set::add}(#t104);
+    }
+  } =>#t102, block {
+    final core::Set<core::int> #t105 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t106 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...y}, // Error.
+        ^") {
+      final core::int #t107 = #t106 as{TypeError,ForNonNullableByDefault} core::int;
+      #t105.{core::Set::add}(#t107);
+    }
+  } =>#t105, block {
+    final core::Set<core::int> #t108 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t109 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...z}, // Error.
+        ^") {
+      final core::int #t110 = #t109 as{TypeError,ForNonNullableByDefault} core::int;
+      #t108.{core::Set::add}(#t110);
+    }
+  } =>#t108, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...w}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+    <int, int>{...x}, // Error.
+                  ^": null}, let final core::Set<core::int> #t111 = new col::_CompactLinkedHashSet::•<core::int>() in let final core::bool #t112 = #t111.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+    <int>{...w}, // Error.
+             ^") in #t111, block {
+    final core::Set<core::int> #t113 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t114 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...x}, // Error.
+                       ^") {
+        final core::int #t115 = #t114 as{TypeError,ForNonNullableByDefault} core::int;
+        #t113.{core::Set::add}(#t115);
+      }
+  } =>#t113, block {
+    final core::Set<core::int> #t116 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t117 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...y}, // Error.
+                       ^") {
+        final core::int #t118 = #t117 as{TypeError,ForNonNullableByDefault} core::int;
+        #t116.{core::Set::add}(#t118);
+      }
+  } =>#t116, block {
+    final core::Set<core::int> #t119 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t120 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...z}, // Error.
+                       ^") {
+        final core::int #t121 = #t120 as{TypeError,ForNonNullableByDefault} core::int;
+        #t119.{core::Set::add}(#t121);
+      }
+  } =>#t119, block {
+    final core::Map<core::int, core::int> #t122 = <core::int, core::int>{};
+    if(condition)
+      #t122.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...w}, // Error.
+                       ^", null);
+  } =>#t122, block {
+    final core::Set<core::int> #t123 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t124 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...x}, // Error.
+                                    ^") {
+          final core::int #t125 = #t124 as{TypeError,ForNonNullableByDefault} core::int;
+          #t123.{core::Set::add}(#t125);
+        }
+      }
+    }
+  } =>#t123, block {
+    final core::Set<core::int> #t126 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t127 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...y}, // Error.
+                                    ^") {
+          final core::int #t128 = #t127 as{TypeError,ForNonNullableByDefault} core::int;
+          #t126.{core::Set::add}(#t128);
+        }
+      }
+    }
+  } =>#t126, block {
+    final core::Set<core::int> #t129 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t130 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...z}, // Error.
+                                    ^") {
+          final core::int #t131 = #t130 as{TypeError,ForNonNullableByDefault} core::int;
+          #t129.{core::Set::add}(#t131);
+        }
+      }
+    }
+  } =>#t129, block {
+    final core::Map<core::int, core::int> #t132 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        #t132.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...w}, // Error.
+                                    ^", null);
+      }
+    }
+  } =>#t132, block {
+    final core::Set<core::int> #t133 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t134 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...x}, // Error.
+                                     ^") {
+        final core::int #t135 = #t134 as{TypeError,ForNonNullableByDefault} core::int;
+        #t133.{core::Set::add}(#t135);
+      }
+  } =>#t133, block {
+    final core::Set<core::int> #t136 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t137 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...y}, // Error.
+                                     ^") {
+        final core::int #t138 = #t137 as{TypeError,ForNonNullableByDefault} core::int;
+        #t136.{core::Set::add}(#t138);
+      }
+  } =>#t136, block {
+    final core::Set<core::int> #t139 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t140 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...z}, // Error.
+                                     ^") {
+        final core::int #t141 = #t140 as{TypeError,ForNonNullableByDefault} core::int;
+        #t139.{core::Set::add}(#t141);
+      }
+  } =>#t139, block {
+    final core::Map<core::int, core::int> #t142 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t142.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...w}, // Error.
+                                     ^", null);
+  } =>#t142, block {
+    final core::Set<core::int> #t143 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t144 = x;
+    if(!#t144.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t144{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t145 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t146 = #t145 as{TypeError,ForNonNullableByDefault} core::int;
+          #t143.{core::Set::add}(#t146);
+        }
+      }
+    }
+  } =>#t143, block {
+    final core::Set<core::int> #t147 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t148 = y;
+    if(!#t148.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t148{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t149 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t150 = #t149 as{TypeError,ForNonNullableByDefault} core::int;
+          #t147.{core::Set::add}(#t150);
+        }
+      }
+    }
+  } =>#t147, block {
+    final core::Set<core::int> #t151 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t152 = z;
+    if(!#t152.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t152{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t153 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t154 = #t153 as{TypeError,ForNonNullableByDefault} core::int;
+          #t151.{core::Set::add}(#t154);
+        }
+      }
+    }
+  } =>#t151, block {
+    final core::Map<core::int, core::int> #t155 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t156 = w;
+    if(!#t156.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t156{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::MapEntry<core::int, core::int> #t157 = :sync-for-iterator.{core::Iterator::current};
+        #t155.{core::Map::[]=}(#t157.{core::MapEntry::key}, #t157.{core::MapEntry::value});
+      }
+    }
+  } =>#t155, block {
+    final core::Set<core::int> #t158 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t159 = x;
+      if(!#t159.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t159{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t160 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t161 = #t160 as{TypeError,ForNonNullableByDefault} core::int;
+            #t158.{core::Set::add}(#t161);
+          }
+        }
+      }
+    }
+  } =>#t158, block {
+    final core::Set<core::int> #t162 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t163 = y;
+      if(!#t163.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t163{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t164 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t165 = #t164 as{TypeError,ForNonNullableByDefault} core::int;
+            #t162.{core::Set::add}(#t165);
+          }
+        }
+      }
+    }
+  } =>#t162, block {
+    final core::Set<core::int> #t166 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t167 = z;
+      if(!#t167.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t167{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t168 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t169 = #t168 as{TypeError,ForNonNullableByDefault} core::int;
+            #t166.{core::Set::add}(#t169);
+          }
+        }
+      }
+    }
+  } =>#t166, block {
+    final core::Map<core::int, core::int> #t170 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t171 = w;
+      if(!#t171.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t171{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t172 = :sync-for-iterator.{core::Iterator::current};
+          #t170.{core::Map::[]=}(#t172.{core::MapEntry::key}, #t172.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t170, block {
+    final core::Set<core::int> #t173 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t174 = x;
+          if(!#t174.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t174{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t175 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t176 = #t175 as{TypeError,ForNonNullableByDefault} core::int;
+                #t173.{core::Set::add}(#t176);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t173, block {
+    final core::Set<core::int> #t177 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t178 = y;
+          if(!#t178.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t178{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t179 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t180 = #t179 as{TypeError,ForNonNullableByDefault} core::int;
+                #t177.{core::Set::add}(#t180);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t177, block {
+    final core::Set<core::int> #t181 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t182 = z;
+          if(!#t182.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t182{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t183 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t184 = #t183 as{TypeError,ForNonNullableByDefault} core::int;
+                #t181.{core::Set::add}(#t184);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t181, block {
+    final core::Map<core::int, core::int> #t185 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Map<core::int, core::int>? #t186 = w;
+          if(!#t186.{core::Object::==}(null)) {
+            core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t186{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final core::MapEntry<core::int, core::int> #t187 = :sync-for-iterator.{core::Iterator::current};
+              #t185.{core::Map::[]=}(#t187.{core::MapEntry::key}, #t187.{core::MapEntry::value});
+            }
+          }
+        }
+      }
+    }
+  } =>#t185, block {
+    final core::Set<core::int> #t188 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t189 = x;
+      if(!#t189.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t189{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t190 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t191 = #t190 as{TypeError,ForNonNullableByDefault} core::int;
+            #t188.{core::Set::add}(#t191);
+          }
+        }
+      }
+    }
+  } =>#t188, block {
+    final core::Set<core::int> #t192 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t193 = y;
+      if(!#t193.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t193{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t194 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t195 = #t194 as{TypeError,ForNonNullableByDefault} core::int;
+            #t192.{core::Set::add}(#t195);
+          }
+        }
+      }
+    }
+  } =>#t192, block {
+    final core::Set<core::int> #t196 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t197 = z;
+      if(!#t197.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t197{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t198 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t199 = #t198 as{TypeError,ForNonNullableByDefault} core::int;
+            #t196.{core::Set::add}(#t199);
+          }
+        }
+      }
+    }
+  } =>#t196, block {
+    final core::Map<core::int, core::int> #t200 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t201 = w;
+      if(!#t201.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t201{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t202 = :sync-for-iterator.{core::Iterator::current};
+          #t200.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t200];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline.expect
new file mode 100644
index 0000000..92ee2bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+foo(bool condition, Iterable<dynamic> iterable, List<int>? a, Set<int>? b,
+    Iterable<int>? c, Map<int, int>? d) {}
+bar<X extends List<int>?, Y extends Set<int>?, Z extends Iterable<int>?,
+        W extends Map<int, int>?>(
+    bool condition, Iterable<dynamic> iterable, X x, Y y, Z z, W w) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..b5153b9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+bar<X extends List<int>?, Y extends Set<int>?, Z extends Iterable<int>?,
+        W extends Map<int, int>?>(
+    bool condition, Iterable<dynamic> iterable, X x, Y y, Z z, W w) {}
+foo(bool condition, Iterable<dynamic> iterable, List<int>? a, Set<int>? b,
+    Iterable<int>? c, Map<int, int>? d) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.weak.expect
new file mode 100644
index 0000000..e89957c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.weak.expect
@@ -0,0 +1,725 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...a}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...b}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...c}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...d}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+//  - 'List' is from 'dart:core'.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...a}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...b}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...c}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...d}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...a}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...b}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...c}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...d}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...a}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...b}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...c}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...d}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...x}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...y}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...z}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...w}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...x}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...y}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...z}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...w}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...x}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...y}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...z}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...w}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...x}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...y}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...z}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...w}, // Error.
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method foo(core::bool condition, core::Iterable<dynamic> iterable, core::List<core::int>? a, core::Set<core::int>? b, core::Iterable<core::int>? c, core::Map<core::int, core::int>? d) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t2 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...a}, // Error.
+        ^") {
+      final core::int #t3 = #t2 as{TypeError,ForNonNullableByDefault} core::int;
+      #t1.{core::Set::add}(#t3);
+    }
+  } =>#t1, block {
+    final core::Set<core::int> #t4 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t5 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...b}, // Error.
+        ^") {
+      final core::int #t6 = #t5 as{TypeError,ForNonNullableByDefault} core::int;
+      #t4.{core::Set::add}(#t6);
+    }
+  } =>#t4, block {
+    final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t8 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...c}, // Error.
+        ^") {
+      final core::int #t9 = #t8 as{TypeError,ForNonNullableByDefault} core::int;
+      #t7.{core::Set::add}(#t9);
+    }
+  } =>#t7, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...d}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+ - 'List' is from 'dart:core'.
+    <int, int>{...a}, // Error.
+                  ^": null}, let final core::Set<core::int> #t10 = col::LinkedHashSet::•<core::int>() in let final dynamic #t11 = #t10.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+    <int>{...d}, // Error.
+             ^") in #t10, block {
+    final core::Set<core::int> #t12 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t13 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...a}, // Error.
+                       ^") {
+        final core::int #t14 = #t13 as{TypeError,ForNonNullableByDefault} core::int;
+        #t12.{core::Set::add}(#t14);
+      }
+  } =>#t12, block {
+    final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t16 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...b}, // Error.
+                       ^") {
+        final core::int #t17 = #t16 as{TypeError,ForNonNullableByDefault} core::int;
+        #t15.{core::Set::add}(#t17);
+      }
+  } =>#t15, block {
+    final core::Set<core::int> #t18 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t19 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...c}, // Error.
+                       ^") {
+        final core::int #t20 = #t19 as{TypeError,ForNonNullableByDefault} core::int;
+        #t18.{core::Set::add}(#t20);
+      }
+  } =>#t18, block {
+    final core::Map<core::int, core::int> #t21 = <core::int, core::int>{};
+    if(condition)
+      #t21.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...d}, // Error.
+                       ^", null);
+  } =>#t21, block {
+    final core::Set<core::int> #t22 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t23 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...a}, // Error.
+                                    ^") {
+        final core::int #t24 = #t23 as{TypeError,ForNonNullableByDefault} core::int;
+        #t22.{core::Set::add}(#t24);
+      }
+  } =>#t22, block {
+    final core::Set<core::int> #t25 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t26 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...b}, // Error.
+                                    ^") {
+        final core::int #t27 = #t26 as{TypeError,ForNonNullableByDefault} core::int;
+        #t25.{core::Set::add}(#t27);
+      }
+  } =>#t25, block {
+    final core::Set<core::int> #t28 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t29 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...c}, // Error.
+                                    ^") {
+        final core::int #t30 = #t29 as{TypeError,ForNonNullableByDefault} core::int;
+        #t28.{core::Set::add}(#t30);
+      }
+  } =>#t28, block {
+    final core::Map<core::int, core::int> #t31 = <core::int, core::int>{};
+    for (dynamic e in iterable)
+      #t31.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...d}, // Error.
+                                    ^", null);
+  } =>#t31, block {
+    final core::Set<core::int> #t32 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t33 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...a}, // Error.
+                                     ^") {
+        final core::int #t34 = #t33 as{TypeError,ForNonNullableByDefault} core::int;
+        #t32.{core::Set::add}(#t34);
+      }
+  } =>#t32, block {
+    final core::Set<core::int> #t35 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t36 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...b}, // Error.
+                                     ^") {
+        final core::int #t37 = #t36 as{TypeError,ForNonNullableByDefault} core::int;
+        #t35.{core::Set::add}(#t37);
+      }
+  } =>#t35, block {
+    final core::Set<core::int> #t38 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t39 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...c}, // Error.
+                                     ^") {
+        final core::int #t40 = #t39 as{TypeError,ForNonNullableByDefault} core::int;
+        #t38.{core::Set::add}(#t40);
+      }
+  } =>#t38, block {
+    final core::Map<core::int, core::int> #t41 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t41.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...d}, // Error.
+                                     ^", null);
+  } =>#t41, block {
+    final core::Set<core::int> #t42 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t43 = a;
+    if(!#t43.{core::Object::==}(null))
+      for (final dynamic #t44 in #t43{core::Iterable<dynamic>}) {
+        final core::int #t45 = #t44 as{TypeError,ForNonNullableByDefault} core::int;
+        #t42.{core::Set::add}(#t45);
+      }
+  } =>#t42, block {
+    final core::Set<core::int> #t46 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t47 = b;
+    if(!#t47.{core::Object::==}(null))
+      for (final dynamic #t48 in #t47{core::Iterable<dynamic>}) {
+        final core::int #t49 = #t48 as{TypeError,ForNonNullableByDefault} core::int;
+        #t46.{core::Set::add}(#t49);
+      }
+  } =>#t46, block {
+    final core::Set<core::int> #t50 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t51 = c;
+    if(!#t51.{core::Object::==}(null))
+      for (final dynamic #t52 in #t51{core::Iterable<dynamic>}) {
+        final core::int #t53 = #t52 as{TypeError,ForNonNullableByDefault} core::int;
+        #t50.{core::Set::add}(#t53);
+      }
+  } =>#t50, block {
+    final core::Map<core::int, core::int> #t54 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t55 = d;
+    if(!#t55.{core::Object::==}(null))
+      for (final core::MapEntry<core::int, core::int> #t56 in #t55{core::Map<core::int, core::int>}.{core::Map::entries})
+        #t54.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
+  } =>#t54, block {
+    final core::Set<core::int> #t57 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t58 = a;
+      if(!#t58.{core::Object::==}(null))
+        for (final dynamic #t59 in #t58{core::Iterable<dynamic>}) {
+          final core::int #t60 = #t59 as{TypeError,ForNonNullableByDefault} core::int;
+          #t57.{core::Set::add}(#t60);
+        }
+    }
+  } =>#t57, block {
+    final core::Set<core::int> #t61 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t62 = b;
+      if(!#t62.{core::Object::==}(null))
+        for (final dynamic #t63 in #t62{core::Iterable<dynamic>}) {
+          final core::int #t64 = #t63 as{TypeError,ForNonNullableByDefault} core::int;
+          #t61.{core::Set::add}(#t64);
+        }
+    }
+  } =>#t61, block {
+    final core::Set<core::int> #t65 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t66 = c;
+      if(!#t66.{core::Object::==}(null))
+        for (final dynamic #t67 in #t66{core::Iterable<dynamic>}) {
+          final core::int #t68 = #t67 as{TypeError,ForNonNullableByDefault} core::int;
+          #t65.{core::Set::add}(#t68);
+        }
+    }
+  } =>#t65, block {
+    final core::Map<core::int, core::int> #t69 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t70 = d;
+      if(!#t70.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t71 in #t70{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t69.{core::Map::[]=}(#t71.{core::MapEntry::key}, #t71.{core::MapEntry::value});
+    }
+  } =>#t69, block {
+    final core::Set<core::int> #t72 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t73 = a;
+      if(!#t73.{core::Object::==}(null))
+        for (final dynamic #t74 in #t73{core::Iterable<dynamic>}) {
+          final core::int #t75 = #t74 as{TypeError,ForNonNullableByDefault} core::int;
+          #t72.{core::Set::add}(#t75);
+        }
+    }
+  } =>#t72, block {
+    final core::Set<core::int> #t76 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t77 = b;
+      if(!#t77.{core::Object::==}(null))
+        for (final dynamic #t78 in #t77{core::Iterable<dynamic>}) {
+          final core::int #t79 = #t78 as{TypeError,ForNonNullableByDefault} core::int;
+          #t76.{core::Set::add}(#t79);
+        }
+    }
+  } =>#t76, block {
+    final core::Set<core::int> #t80 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t81 = c;
+      if(!#t81.{core::Object::==}(null))
+        for (final dynamic #t82 in #t81{core::Iterable<dynamic>}) {
+          final core::int #t83 = #t82 as{TypeError,ForNonNullableByDefault} core::int;
+          #t80.{core::Set::add}(#t83);
+        }
+    }
+  } =>#t80, block {
+    final core::Map<core::int, core::int> #t84 = <core::int, core::int>{};
+    for (dynamic e in iterable) {
+      final core::Map<core::int, core::int>? #t85 = d;
+      if(!#t85.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t86 in #t85{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t84.{core::Map::[]=}(#t86.{core::MapEntry::key}, #t86.{core::MapEntry::value});
+    }
+  } =>#t84, block {
+    final core::Set<core::int> #t87 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t88 = a;
+      if(!#t88.{core::Object::==}(null))
+        for (final dynamic #t89 in #t88{core::Iterable<dynamic>}) {
+          final core::int #t90 = #t89 as{TypeError,ForNonNullableByDefault} core::int;
+          #t87.{core::Set::add}(#t90);
+        }
+    }
+  } =>#t87, block {
+    final core::Set<core::int> #t91 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t92 = b;
+      if(!#t92.{core::Object::==}(null))
+        for (final dynamic #t93 in #t92{core::Iterable<dynamic>}) {
+          final core::int #t94 = #t93 as{TypeError,ForNonNullableByDefault} core::int;
+          #t91.{core::Set::add}(#t94);
+        }
+    }
+  } =>#t91, block {
+    final core::Set<core::int> #t95 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t96 = c;
+      if(!#t96.{core::Object::==}(null))
+        for (final dynamic #t97 in #t96{core::Iterable<dynamic>}) {
+          final core::int #t98 = #t97 as{TypeError,ForNonNullableByDefault} core::int;
+          #t95.{core::Set::add}(#t98);
+        }
+    }
+  } =>#t95, block {
+    final core::Map<core::int, core::int> #t99 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t100 = d;
+      if(!#t100.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t101 in #t100{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t99.{core::Map::[]=}(#t101.{core::MapEntry::key}, #t101.{core::MapEntry::value});
+    }
+  } =>#t99];
+}
+static method bar<X extends core::List<core::int>? = core::List<core::int>?, Y extends core::Set<core::int>? = core::Set<core::int>?, Z extends core::Iterable<core::int>? = core::Iterable<core::int>?, W extends core::Map<core::int, core::int>? = core::Map<core::int, core::int>?>(core::bool condition, core::Iterable<dynamic> iterable, self::bar::X% x, self::bar::Y% y, self::bar::Z% z, self::bar::W% w) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t102 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t103 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...x}, // Error.
+        ^") {
+      final core::int #t104 = #t103 as{TypeError,ForNonNullableByDefault} core::int;
+      #t102.{core::Set::add}(#t104);
+    }
+  } =>#t102, block {
+    final core::Set<core::int> #t105 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t106 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...y}, // Error.
+        ^") {
+      final core::int #t107 = #t106 as{TypeError,ForNonNullableByDefault} core::int;
+      #t105.{core::Set::add}(#t107);
+    }
+  } =>#t105, block {
+    final core::Set<core::int> #t108 = col::LinkedHashSet::•<core::int>();
+    for (final dynamic #t109 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...z}, // Error.
+        ^") {
+      final core::int #t110 = #t109 as{TypeError,ForNonNullableByDefault} core::int;
+      #t108.{core::Set::add}(#t110);
+    }
+  } =>#t108, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...w}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+    <int, int>{...x}, // Error.
+                  ^": null}, let final core::Set<core::int> #t111 = col::LinkedHashSet::•<core::int>() in let final dynamic #t112 = #t111.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+    <int>{...w}, // Error.
+             ^") in #t111, block {
+    final core::Set<core::int> #t113 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t114 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...x}, // Error.
+                       ^") {
+        final core::int #t115 = #t114 as{TypeError,ForNonNullableByDefault} core::int;
+        #t113.{core::Set::add}(#t115);
+      }
+  } =>#t113, block {
+    final core::Set<core::int> #t116 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t117 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...y}, // Error.
+                       ^") {
+        final core::int #t118 = #t117 as{TypeError,ForNonNullableByDefault} core::int;
+        #t116.{core::Set::add}(#t118);
+      }
+  } =>#t116, block {
+    final core::Set<core::int> #t119 = col::LinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t120 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...z}, // Error.
+                       ^") {
+        final core::int #t121 = #t120 as{TypeError,ForNonNullableByDefault} core::int;
+        #t119.{core::Set::add}(#t121);
+      }
+  } =>#t119, block {
+    final core::Map<core::int, core::int> #t122 = <core::int, core::int>{};
+    if(condition)
+      #t122.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...w}, // Error.
+                       ^", null);
+  } =>#t122, block {
+    final core::Set<core::int> #t123 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t124 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...x}, // Error.
+                                    ^") {
+        final core::int #t125 = #t124 as{TypeError,ForNonNullableByDefault} core::int;
+        #t123.{core::Set::add}(#t125);
+      }
+  } =>#t123, block {
+    final core::Set<core::int> #t126 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t127 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...y}, // Error.
+                                    ^") {
+        final core::int #t128 = #t127 as{TypeError,ForNonNullableByDefault} core::int;
+        #t126.{core::Set::add}(#t128);
+      }
+  } =>#t126, block {
+    final core::Set<core::int> #t129 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable)
+      for (final dynamic #t130 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...z}, // Error.
+                                    ^") {
+        final core::int #t131 = #t130 as{TypeError,ForNonNullableByDefault} core::int;
+        #t129.{core::Set::add}(#t131);
+      }
+  } =>#t129, block {
+    final core::Map<core::int, core::int> #t132 = <core::int, core::int>{};
+    for (dynamic e in iterable)
+      #t132.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...w}, // Error.
+                                    ^", null);
+  } =>#t132, block {
+    final core::Set<core::int> #t133 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t134 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...x}, // Error.
+                                     ^") {
+        final core::int #t135 = #t134 as{TypeError,ForNonNullableByDefault} core::int;
+        #t133.{core::Set::add}(#t135);
+      }
+  } =>#t133, block {
+    final core::Set<core::int> #t136 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t137 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...y}, // Error.
+                                     ^") {
+        final core::int #t138 = #t137 as{TypeError,ForNonNullableByDefault} core::int;
+        #t136.{core::Set::add}(#t138);
+      }
+  } =>#t136, block {
+    final core::Set<core::int> #t139 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t140 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...z}, // Error.
+                                     ^") {
+        final core::int #t141 = #t140 as{TypeError,ForNonNullableByDefault} core::int;
+        #t139.{core::Set::add}(#t141);
+      }
+  } =>#t139, block {
+    final core::Map<core::int, core::int> #t142 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t142.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...w}, // Error.
+                                     ^", null);
+  } =>#t142, block {
+    final core::Set<core::int> #t143 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t144 = x;
+    if(!#t144.{core::Object::==}(null))
+      for (final dynamic #t145 in #t144{core::Iterable<dynamic>}) {
+        final core::int #t146 = #t145 as{TypeError,ForNonNullableByDefault} core::int;
+        #t143.{core::Set::add}(#t146);
+      }
+  } =>#t143, block {
+    final core::Set<core::int> #t147 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t148 = y;
+    if(!#t148.{core::Object::==}(null))
+      for (final dynamic #t149 in #t148{core::Iterable<dynamic>}) {
+        final core::int #t150 = #t149 as{TypeError,ForNonNullableByDefault} core::int;
+        #t147.{core::Set::add}(#t150);
+      }
+  } =>#t147, block {
+    final core::Set<core::int> #t151 = col::LinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t152 = z;
+    if(!#t152.{core::Object::==}(null))
+      for (final dynamic #t153 in #t152{core::Iterable<dynamic>}) {
+        final core::int #t154 = #t153 as{TypeError,ForNonNullableByDefault} core::int;
+        #t151.{core::Set::add}(#t154);
+      }
+  } =>#t151, block {
+    final core::Map<core::int, core::int> #t155 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t156 = w;
+    if(!#t156.{core::Object::==}(null))
+      for (final core::MapEntry<core::int, core::int> #t157 in #t156{core::Map<core::int, core::int>}.{core::Map::entries})
+        #t155.{core::Map::[]=}(#t157.{core::MapEntry::key}, #t157.{core::MapEntry::value});
+  } =>#t155, block {
+    final core::Set<core::int> #t158 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t159 = x;
+      if(!#t159.{core::Object::==}(null))
+        for (final dynamic #t160 in #t159{core::Iterable<dynamic>}) {
+          final core::int #t161 = #t160 as{TypeError,ForNonNullableByDefault} core::int;
+          #t158.{core::Set::add}(#t161);
+        }
+    }
+  } =>#t158, block {
+    final core::Set<core::int> #t162 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t163 = y;
+      if(!#t163.{core::Object::==}(null))
+        for (final dynamic #t164 in #t163{core::Iterable<dynamic>}) {
+          final core::int #t165 = #t164 as{TypeError,ForNonNullableByDefault} core::int;
+          #t162.{core::Set::add}(#t165);
+        }
+    }
+  } =>#t162, block {
+    final core::Set<core::int> #t166 = col::LinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t167 = z;
+      if(!#t167.{core::Object::==}(null))
+        for (final dynamic #t168 in #t167{core::Iterable<dynamic>}) {
+          final core::int #t169 = #t168 as{TypeError,ForNonNullableByDefault} core::int;
+          #t166.{core::Set::add}(#t169);
+        }
+    }
+  } =>#t166, block {
+    final core::Map<core::int, core::int> #t170 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t171 = w;
+      if(!#t171.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t172 in #t171{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t170.{core::Map::[]=}(#t172.{core::MapEntry::key}, #t172.{core::MapEntry::value});
+    }
+  } =>#t170, block {
+    final core::Set<core::int> #t173 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t174 = x;
+      if(!#t174.{core::Object::==}(null))
+        for (final dynamic #t175 in #t174{core::Iterable<dynamic>}) {
+          final core::int #t176 = #t175 as{TypeError,ForNonNullableByDefault} core::int;
+          #t173.{core::Set::add}(#t176);
+        }
+    }
+  } =>#t173, block {
+    final core::Set<core::int> #t177 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t178 = y;
+      if(!#t178.{core::Object::==}(null))
+        for (final dynamic #t179 in #t178{core::Iterable<dynamic>}) {
+          final core::int #t180 = #t179 as{TypeError,ForNonNullableByDefault} core::int;
+          #t177.{core::Set::add}(#t180);
+        }
+    }
+  } =>#t177, block {
+    final core::Set<core::int> #t181 = col::LinkedHashSet::•<core::int>();
+    for (dynamic e in iterable) {
+      final core::Iterable<dynamic>? #t182 = z;
+      if(!#t182.{core::Object::==}(null))
+        for (final dynamic #t183 in #t182{core::Iterable<dynamic>}) {
+          final core::int #t184 = #t183 as{TypeError,ForNonNullableByDefault} core::int;
+          #t181.{core::Set::add}(#t184);
+        }
+    }
+  } =>#t181, block {
+    final core::Map<core::int, core::int> #t185 = <core::int, core::int>{};
+    for (dynamic e in iterable) {
+      final core::Map<core::int, core::int>? #t186 = w;
+      if(!#t186.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t187 in #t186{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t185.{core::Map::[]=}(#t187.{core::MapEntry::key}, #t187.{core::MapEntry::value});
+    }
+  } =>#t185, block {
+    final core::Set<core::int> #t188 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t189 = x;
+      if(!#t189.{core::Object::==}(null))
+        for (final dynamic #t190 in #t189{core::Iterable<dynamic>}) {
+          final core::int #t191 = #t190 as{TypeError,ForNonNullableByDefault} core::int;
+          #t188.{core::Set::add}(#t191);
+        }
+    }
+  } =>#t188, block {
+    final core::Set<core::int> #t192 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t193 = y;
+      if(!#t193.{core::Object::==}(null))
+        for (final dynamic #t194 in #t193{core::Iterable<dynamic>}) {
+          final core::int #t195 = #t194 as{TypeError,ForNonNullableByDefault} core::int;
+          #t192.{core::Set::add}(#t195);
+        }
+    }
+  } =>#t192, block {
+    final core::Set<core::int> #t196 = col::LinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t197 = z;
+      if(!#t197.{core::Object::==}(null))
+        for (final dynamic #t198 in #t197{core::Iterable<dynamic>}) {
+          final core::int #t199 = #t198 as{TypeError,ForNonNullableByDefault} core::int;
+          #t196.{core::Set::add}(#t199);
+        }
+    }
+  } =>#t196, block {
+    final core::Map<core::int, core::int> #t200 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t201 = w;
+      if(!#t201.{core::Object::==}(null))
+        for (final core::MapEntry<core::int, core::int> #t202 in #t201{core::Map<core::int, core::int>}.{core::Map::entries})
+          #t200.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
+    }
+  } =>#t200];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43495.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43495.dart.weak.transformed.expect
new file mode 100644
index 0000000..84cd03a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43495.dart.weak.transformed.expect
@@ -0,0 +1,965 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...a}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...b}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...c}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...d}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+//  - 'List' is from 'dart:core'.
+//     <int, int>{...a}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+//  - 'Map' is from 'dart:core'.
+//     <int>{...d}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...a}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...b}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...c}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...d}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...a}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...b}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...c}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...d}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...a}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...b}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...c}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...d}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...x}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...y}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...z}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {...w}, // Error.
+//         ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+//     <int, int>{...x}, // Error.
+//                   ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+//     <int>{...w}, // Error.
+//              ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...x}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...y}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...z}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {if (condition) ...w}, // Error.
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...x}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...y}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...z}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (dynamic e in iterable) ...w}, // Error.
+//                                     ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...x}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...y}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...z}, // Error.
+//                                      ^
+//
+// pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+//     {for (int i = 0; i < 42; ++i) ...w}, // Error.
+//                                      ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+static method foo(core::bool condition, core::Iterable<dynamic> iterable, core::List<core::int>? a, core::Set<core::int>? b, core::Iterable<core::int>? c, core::Map<core::int, core::int>? d) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t1 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t2 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:8:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...a}, // Error.
+        ^") {
+      final core::int #t3 = #t2 as{TypeError,ForNonNullableByDefault} core::int;
+      #t1.{core::Set::add}(#t3);
+    }
+  } =>#t1, block {
+    final core::Set<core::int> #t4 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t5 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:9:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...b}, // Error.
+        ^") {
+      final core::int #t6 = #t5 as{TypeError,ForNonNullableByDefault} core::int;
+      #t4.{core::Set::add}(#t6);
+    }
+  } =>#t4, block {
+    final core::Set<core::int> #t7 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t8 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:10:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...c}, // Error.
+        ^") {
+      final core::int #t9 = #t8 as{TypeError,ForNonNullableByDefault} core::int;
+      #t7.{core::Set::add}(#t9);
+    }
+  } =>#t7, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:11:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...d}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:12:19: Error: Unexpected type 'List<int>?' of a map spread entry.  Expected 'dynamic' or a Map.
+ - 'List' is from 'dart:core'.
+    <int, int>{...a}, // Error.
+                  ^": null}, let final core::Set<core::int> #t10 = new col::_CompactLinkedHashSet::•<core::int>() in let final core::bool #t11 = #t10.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:13:14: Error: Unexpected type 'Map<int, int>?' of a spread.  Expected 'dynamic' or an Iterable.
+ - 'Map' is from 'dart:core'.
+    <int>{...d}, // Error.
+             ^") in #t10, block {
+    final core::Set<core::int> #t12 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t13 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:14:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...a}, // Error.
+                       ^") {
+        final core::int #t14 = #t13 as{TypeError,ForNonNullableByDefault} core::int;
+        #t12.{core::Set::add}(#t14);
+      }
+  } =>#t12, block {
+    final core::Set<core::int> #t15 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t16 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:15:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...b}, // Error.
+                       ^") {
+        final core::int #t17 = #t16 as{TypeError,ForNonNullableByDefault} core::int;
+        #t15.{core::Set::add}(#t17);
+      }
+  } =>#t15, block {
+    final core::Set<core::int> #t18 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t19 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:16:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...c}, // Error.
+                       ^") {
+        final core::int #t20 = #t19 as{TypeError,ForNonNullableByDefault} core::int;
+        #t18.{core::Set::add}(#t20);
+      }
+  } =>#t18, block {
+    final core::Map<core::int, core::int> #t21 = <core::int, core::int>{};
+    if(condition)
+      #t21.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:17:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...d}, // Error.
+                       ^", null);
+  } =>#t21, block {
+    final core::Set<core::int> #t22 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t23 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:18:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...a}, // Error.
+                                    ^") {
+          final core::int #t24 = #t23 as{TypeError,ForNonNullableByDefault} core::int;
+          #t22.{core::Set::add}(#t24);
+        }
+      }
+    }
+  } =>#t22, block {
+    final core::Set<core::int> #t25 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t26 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:19:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...b}, // Error.
+                                    ^") {
+          final core::int #t27 = #t26 as{TypeError,ForNonNullableByDefault} core::int;
+          #t25.{core::Set::add}(#t27);
+        }
+      }
+    }
+  } =>#t25, block {
+    final core::Set<core::int> #t28 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t29 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:20:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...c}, // Error.
+                                    ^") {
+          final core::int #t30 = #t29 as{TypeError,ForNonNullableByDefault} core::int;
+          #t28.{core::Set::add}(#t30);
+        }
+      }
+    }
+  } =>#t28, block {
+    final core::Map<core::int, core::int> #t31 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        #t31.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:21:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...d}, // Error.
+                                    ^", null);
+      }
+    }
+  } =>#t31, block {
+    final core::Set<core::int> #t32 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t33 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:22:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...a}, // Error.
+                                     ^") {
+        final core::int #t34 = #t33 as{TypeError,ForNonNullableByDefault} core::int;
+        #t32.{core::Set::add}(#t34);
+      }
+  } =>#t32, block {
+    final core::Set<core::int> #t35 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t36 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:23:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...b}, // Error.
+                                     ^") {
+        final core::int #t37 = #t36 as{TypeError,ForNonNullableByDefault} core::int;
+        #t35.{core::Set::add}(#t37);
+      }
+  } =>#t35, block {
+    final core::Set<core::int> #t38 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t39 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:24:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...c}, // Error.
+                                     ^") {
+        final core::int #t40 = #t39 as{TypeError,ForNonNullableByDefault} core::int;
+        #t38.{core::Set::add}(#t40);
+      }
+  } =>#t38, block {
+    final core::Map<core::int, core::int> #t41 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t41.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:25:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...d}, // Error.
+                                     ^", null);
+  } =>#t41, block {
+    final core::Set<core::int> #t42 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t43 = a;
+    if(!#t43.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t43{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t44 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t45 = #t44 as{TypeError,ForNonNullableByDefault} core::int;
+          #t42.{core::Set::add}(#t45);
+        }
+      }
+    }
+  } =>#t42, block {
+    final core::Set<core::int> #t46 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t47 = b;
+    if(!#t47.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t47{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t48 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t49 = #t48 as{TypeError,ForNonNullableByDefault} core::int;
+          #t46.{core::Set::add}(#t49);
+        }
+      }
+    }
+  } =>#t46, block {
+    final core::Set<core::int> #t50 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t51 = c;
+    if(!#t51.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t51{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t52 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t53 = #t52 as{TypeError,ForNonNullableByDefault} core::int;
+          #t50.{core::Set::add}(#t53);
+        }
+      }
+    }
+  } =>#t50, block {
+    final core::Map<core::int, core::int> #t54 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t55 = d;
+    if(!#t55.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t55{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::MapEntry<core::int, core::int> #t56 = :sync-for-iterator.{core::Iterator::current};
+        #t54.{core::Map::[]=}(#t56.{core::MapEntry::key}, #t56.{core::MapEntry::value});
+      }
+    }
+  } =>#t54, block {
+    final core::Set<core::int> #t57 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t58 = a;
+      if(!#t58.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t58{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t59 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t60 = #t59 as{TypeError,ForNonNullableByDefault} core::int;
+            #t57.{core::Set::add}(#t60);
+          }
+        }
+      }
+    }
+  } =>#t57, block {
+    final core::Set<core::int> #t61 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t62 = b;
+      if(!#t62.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t62{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t63 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t64 = #t63 as{TypeError,ForNonNullableByDefault} core::int;
+            #t61.{core::Set::add}(#t64);
+          }
+        }
+      }
+    }
+  } =>#t61, block {
+    final core::Set<core::int> #t65 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t66 = c;
+      if(!#t66.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t66{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t67 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t68 = #t67 as{TypeError,ForNonNullableByDefault} core::int;
+            #t65.{core::Set::add}(#t68);
+          }
+        }
+      }
+    }
+  } =>#t65, block {
+    final core::Map<core::int, core::int> #t69 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t70 = d;
+      if(!#t70.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t70{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t71 = :sync-for-iterator.{core::Iterator::current};
+          #t69.{core::Map::[]=}(#t71.{core::MapEntry::key}, #t71.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t69, block {
+    final core::Set<core::int> #t72 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t73 = a;
+          if(!#t73.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t73{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t74 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t75 = #t74 as{TypeError,ForNonNullableByDefault} core::int;
+                #t72.{core::Set::add}(#t75);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t72, block {
+    final core::Set<core::int> #t76 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t77 = b;
+          if(!#t77.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t77{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t78 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t79 = #t78 as{TypeError,ForNonNullableByDefault} core::int;
+                #t76.{core::Set::add}(#t79);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t76, block {
+    final core::Set<core::int> #t80 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t81 = c;
+          if(!#t81.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t81{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t82 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t83 = #t82 as{TypeError,ForNonNullableByDefault} core::int;
+                #t80.{core::Set::add}(#t83);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t80, block {
+    final core::Map<core::int, core::int> #t84 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Map<core::int, core::int>? #t85 = d;
+          if(!#t85.{core::Object::==}(null)) {
+            core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t85{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final core::MapEntry<core::int, core::int> #t86 = :sync-for-iterator.{core::Iterator::current};
+              #t84.{core::Map::[]=}(#t86.{core::MapEntry::key}, #t86.{core::MapEntry::value});
+            }
+          }
+        }
+      }
+    }
+  } =>#t84, block {
+    final core::Set<core::int> #t87 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t88 = a;
+      if(!#t88.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t88{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t89 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t90 = #t89 as{TypeError,ForNonNullableByDefault} core::int;
+            #t87.{core::Set::add}(#t90);
+          }
+        }
+      }
+    }
+  } =>#t87, block {
+    final core::Set<core::int> #t91 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t92 = b;
+      if(!#t92.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t92{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t93 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t94 = #t93 as{TypeError,ForNonNullableByDefault} core::int;
+            #t91.{core::Set::add}(#t94);
+          }
+        }
+      }
+    }
+  } =>#t91, block {
+    final core::Set<core::int> #t95 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t96 = c;
+      if(!#t96.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t96{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t97 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t98 = #t97 as{TypeError,ForNonNullableByDefault} core::int;
+            #t95.{core::Set::add}(#t98);
+          }
+        }
+      }
+    }
+  } =>#t95, block {
+    final core::Map<core::int, core::int> #t99 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t100 = d;
+      if(!#t100.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t100{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t101 = :sync-for-iterator.{core::Iterator::current};
+          #t99.{core::Map::[]=}(#t101.{core::MapEntry::key}, #t101.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t99];
+}
+static method bar<X extends core::List<core::int>? = core::List<core::int>?, Y extends core::Set<core::int>? = core::Set<core::int>?, Z extends core::Iterable<core::int>? = core::Iterable<core::int>?, W extends core::Map<core::int, core::int>? = core::Map<core::int, core::int>?>(core::bool condition, core::Iterable<dynamic> iterable, self::bar::X% x, self::bar::Y% y, self::bar::Z% z, self::bar::W% w) → dynamic {
+  return <core::Object>[ block {
+    final core::Set<core::int> #t102 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t103 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:50:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...x}, // Error.
+        ^") {
+      final core::int #t104 = #t103 as{TypeError,ForNonNullableByDefault} core::int;
+      #t102.{core::Set::add}(#t104);
+    }
+  } =>#t102, block {
+    final core::Set<core::int> #t105 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t106 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:51:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...y}, // Error.
+        ^") {
+      final core::int #t107 = #t106 as{TypeError,ForNonNullableByDefault} core::int;
+      #t105.{core::Set::add}(#t107);
+    }
+  } =>#t105, block {
+    final core::Set<core::int> #t108 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (final dynamic #t109 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:52:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...z}, // Error.
+        ^") {
+      final core::int #t110 = #t109 as{TypeError,ForNonNullableByDefault} core::int;
+      #t108.{core::Set::add}(#t110);
+    }
+  } =>#t108, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:53:9: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {...w}, // Error.
+        ^": null}, <core::int, core::int>{invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:54:19: Error: Unexpected type 'X' of a map spread entry.  Expected 'dynamic' or a Map.
+    <int, int>{...x}, // Error.
+                  ^": null}, let final core::Set<core::int> #t111 = new col::_CompactLinkedHashSet::•<core::int>() in let final core::bool #t112 = #t111.{core::Set::add}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:55:14: Error: Unexpected type 'W' of a spread.  Expected 'dynamic' or an Iterable.
+    <int>{...w}, // Error.
+             ^") in #t111, block {
+    final core::Set<core::int> #t113 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t114 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:56:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...x}, // Error.
+                       ^") {
+        final core::int #t115 = #t114 as{TypeError,ForNonNullableByDefault} core::int;
+        #t113.{core::Set::add}(#t115);
+      }
+  } =>#t113, block {
+    final core::Set<core::int> #t116 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t117 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:57:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...y}, // Error.
+                       ^") {
+        final core::int #t118 = #t117 as{TypeError,ForNonNullableByDefault} core::int;
+        #t116.{core::Set::add}(#t118);
+      }
+  } =>#t116, block {
+    final core::Set<core::int> #t119 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition)
+      for (final dynamic #t120 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:58:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...z}, // Error.
+                       ^") {
+        final core::int #t121 = #t120 as{TypeError,ForNonNullableByDefault} core::int;
+        #t119.{core::Set::add}(#t121);
+      }
+  } =>#t119, block {
+    final core::Map<core::int, core::int> #t122 = <core::int, core::int>{};
+    if(condition)
+      #t122.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:59:24: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {if (condition) ...w}, // Error.
+                       ^", null);
+  } =>#t122, block {
+    final core::Set<core::int> #t123 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t124 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:60:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...x}, // Error.
+                                    ^") {
+          final core::int #t125 = #t124 as{TypeError,ForNonNullableByDefault} core::int;
+          #t123.{core::Set::add}(#t125);
+        }
+      }
+    }
+  } =>#t123, block {
+    final core::Set<core::int> #t126 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t127 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:61:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...y}, // Error.
+                                    ^") {
+          final core::int #t128 = #t127 as{TypeError,ForNonNullableByDefault} core::int;
+          #t126.{core::Set::add}(#t128);
+        }
+      }
+    }
+  } =>#t126, block {
+    final core::Set<core::int> #t129 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        for (final dynamic #t130 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:62:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...z}, // Error.
+                                    ^") {
+          final core::int #t131 = #t130 as{TypeError,ForNonNullableByDefault} core::int;
+          #t129.{core::Set::add}(#t131);
+        }
+      }
+    }
+  } =>#t129, block {
+    final core::Map<core::int, core::int> #t132 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        #t132.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:63:37: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (dynamic e in iterable) ...w}, // Error.
+                                    ^", null);
+      }
+    }
+  } =>#t132, block {
+    final core::Set<core::int> #t133 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t134 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:64:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...x}, // Error.
+                                     ^") {
+        final core::int #t135 = #t134 as{TypeError,ForNonNullableByDefault} core::int;
+        #t133.{core::Set::add}(#t135);
+      }
+  } =>#t133, block {
+    final core::Set<core::int> #t136 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t137 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:65:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...y}, // Error.
+                                     ^") {
+        final core::int #t138 = #t137 as{TypeError,ForNonNullableByDefault} core::int;
+        #t136.{core::Set::add}(#t138);
+      }
+  } =>#t136, block {
+    final core::Set<core::int> #t139 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      for (final dynamic #t140 in invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:66:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...z}, // Error.
+                                     ^") {
+        final core::int #t141 = #t140 as{TypeError,ForNonNullableByDefault} core::int;
+        #t139.{core::Set::add}(#t141);
+      }
+  } =>#t139, block {
+    final core::Map<core::int, core::int> #t142 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1))
+      #t142.{core::Map::[]=}(invalid-expression "pkg/front_end/testcases/nnbd/issue43495.dart:67:38: Error: An expression whose value can be 'null' must be null-checked before it can be dereferenced.
+    {for (int i = 0; i < 42; ++i) ...w}, // Error.
+                                     ^", null);
+  } =>#t142, block {
+    final core::Set<core::int> #t143 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t144 = x;
+    if(!#t144.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t144{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t145 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t146 = #t145 as{TypeError,ForNonNullableByDefault} core::int;
+          #t143.{core::Set::add}(#t146);
+        }
+      }
+    }
+  } =>#t143, block {
+    final core::Set<core::int> #t147 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t148 = y;
+    if(!#t148.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t148{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t149 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t150 = #t149 as{TypeError,ForNonNullableByDefault} core::int;
+          #t147.{core::Set::add}(#t150);
+        }
+      }
+    }
+  } =>#t147, block {
+    final core::Set<core::int> #t151 = new col::_CompactLinkedHashSet::•<core::int>();
+    final core::Iterable<dynamic>? #t152 = z;
+    if(!#t152.{core::Object::==}(null)) {
+      core::Iterator<dynamic> :sync-for-iterator = #t152{core::Iterable<dynamic>}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final dynamic #t153 = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::int #t154 = #t153 as{TypeError,ForNonNullableByDefault} core::int;
+          #t151.{core::Set::add}(#t154);
+        }
+      }
+    }
+  } =>#t151, block {
+    final core::Map<core::int, core::int> #t155 = <core::int, core::int>{};
+    final core::Map<core::int, core::int>? #t156 = w;
+    if(!#t156.{core::Object::==}(null)) {
+      core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t156{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        final core::MapEntry<core::int, core::int> #t157 = :sync-for-iterator.{core::Iterator::current};
+        #t155.{core::Map::[]=}(#t157.{core::MapEntry::key}, #t157.{core::MapEntry::value});
+      }
+    }
+  } =>#t155, block {
+    final core::Set<core::int> #t158 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t159 = x;
+      if(!#t159.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t159{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t160 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t161 = #t160 as{TypeError,ForNonNullableByDefault} core::int;
+            #t158.{core::Set::add}(#t161);
+          }
+        }
+      }
+    }
+  } =>#t158, block {
+    final core::Set<core::int> #t162 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t163 = y;
+      if(!#t163.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t163{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t164 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t165 = #t164 as{TypeError,ForNonNullableByDefault} core::int;
+            #t162.{core::Set::add}(#t165);
+          }
+        }
+      }
+    }
+  } =>#t162, block {
+    final core::Set<core::int> #t166 = new col::_CompactLinkedHashSet::•<core::int>();
+    if(condition) {
+      final core::Iterable<dynamic>? #t167 = z;
+      if(!#t167.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t167{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t168 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t169 = #t168 as{TypeError,ForNonNullableByDefault} core::int;
+            #t166.{core::Set::add}(#t169);
+          }
+        }
+      }
+    }
+  } =>#t166, block {
+    final core::Map<core::int, core::int> #t170 = <core::int, core::int>{};
+    if(condition) {
+      final core::Map<core::int, core::int>? #t171 = w;
+      if(!#t171.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t171{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t172 = :sync-for-iterator.{core::Iterator::current};
+          #t170.{core::Map::[]=}(#t172.{core::MapEntry::key}, #t172.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t170, block {
+    final core::Set<core::int> #t173 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t174 = x;
+          if(!#t174.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t174{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t175 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t176 = #t175 as{TypeError,ForNonNullableByDefault} core::int;
+                #t173.{core::Set::add}(#t176);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t173, block {
+    final core::Set<core::int> #t177 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t178 = y;
+          if(!#t178.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t178{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t179 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t180 = #t179 as{TypeError,ForNonNullableByDefault} core::int;
+                #t177.{core::Set::add}(#t180);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t177, block {
+    final core::Set<core::int> #t181 = new col::_CompactLinkedHashSet::•<core::int>();
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Iterable<dynamic>? #t182 = z;
+          if(!#t182.{core::Object::==}(null)) {
+            core::Iterator<dynamic> :sync-for-iterator = #t182{core::Iterable<dynamic>}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final dynamic #t183 = :sync-for-iterator.{core::Iterator::current};
+              {
+                final core::int #t184 = #t183 as{TypeError,ForNonNullableByDefault} core::int;
+                #t181.{core::Set::add}(#t184);
+              }
+            }
+          }
+        }
+      }
+    }
+  } =>#t181, block {
+    final core::Map<core::int, core::int> #t185 = <core::int, core::int>{};
+    {
+      core::Iterator<dynamic> :sync-for-iterator = iterable.{core::Iterable::iterator};
+      for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+        dynamic e = :sync-for-iterator.{core::Iterator::current};
+        {
+          final core::Map<core::int, core::int>? #t186 = w;
+          if(!#t186.{core::Object::==}(null)) {
+            core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t186{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+            for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+              final core::MapEntry<core::int, core::int> #t187 = :sync-for-iterator.{core::Iterator::current};
+              #t185.{core::Map::[]=}(#t187.{core::MapEntry::key}, #t187.{core::MapEntry::value});
+            }
+          }
+        }
+      }
+    }
+  } =>#t185, block {
+    final core::Set<core::int> #t188 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t189 = x;
+      if(!#t189.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t189{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t190 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t191 = #t190 as{TypeError,ForNonNullableByDefault} core::int;
+            #t188.{core::Set::add}(#t191);
+          }
+        }
+      }
+    }
+  } =>#t188, block {
+    final core::Set<core::int> #t192 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t193 = y;
+      if(!#t193.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t193{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t194 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t195 = #t194 as{TypeError,ForNonNullableByDefault} core::int;
+            #t192.{core::Set::add}(#t195);
+          }
+        }
+      }
+    }
+  } =>#t192, block {
+    final core::Set<core::int> #t196 = new col::_CompactLinkedHashSet::•<core::int>();
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Iterable<dynamic>? #t197 = z;
+      if(!#t197.{core::Object::==}(null)) {
+        core::Iterator<dynamic> :sync-for-iterator = #t197{core::Iterable<dynamic>}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final dynamic #t198 = :sync-for-iterator.{core::Iterator::current};
+          {
+            final core::int #t199 = #t198 as{TypeError,ForNonNullableByDefault} core::int;
+            #t196.{core::Set::add}(#t199);
+          }
+        }
+      }
+    }
+  } =>#t196, block {
+    final core::Map<core::int, core::int> #t200 = <core::int, core::int>{};
+    for (core::int i = 0; i.{core::num::<}(42); i = i.{core::num::+}(1)) {
+      final core::Map<core::int, core::int>? #t201 = w;
+      if(!#t201.{core::Object::==}(null)) {
+        core::Iterator<core::MapEntry<core::int, core::int>> :sync-for-iterator = #t201{core::Map<core::int, core::int>}.{core::Map::entries}.{core::Iterable::iterator};
+        for (; :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+          final core::MapEntry<core::int, core::int> #t202 = :sync-for-iterator.{core::Iterator::current};
+          #t200.{core::Map::[]=}(#t202.{core::MapEntry::key}, #t202.{core::MapEntry::value});
+        }
+      }
+    }
+  } =>#t200];
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart b/pkg/front_end/testcases/nnbd/issue43536.dart
new file mode 100644
index 0000000..ac26684
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C<T> {
+  foo<E extends T>(List<E> list) {
+    List<E> variable = method(list);
+  }
+
+  List<F> method<F extends T>(List<F> list) => list;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.outline.expect
new file mode 100644
index 0000000..15e7e74
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.outline.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    ;
+  method foo<generic-covariant-impl E extends self::C::T% = self::C::T%>(core::List<self::C::foo::E%> list) → dynamic
+    ;
+  method method<generic-covariant-impl F extends self::C::T% = self::C::T%>(core::List<self::C::method::F%> list) → core::List<self::C::method::F%>
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.strong.expect
new file mode 100644
index 0000000..e22d4b0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.strong.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  method foo<generic-covariant-impl E extends self::C::T% = self::C::T%>(core::List<self::C::foo::E%> list) → dynamic {
+    core::List<self::C::foo::E%> variable = this.{self::C::method}<self::C::foo::E%>(list);
+  }
+  method method<generic-covariant-impl F extends self::C::T% = self::C::T%>(core::List<self::C::method::F%> list) → core::List<self::C::method::F%>
+    return list;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.strong.transformed.expect
new file mode 100644
index 0000000..e22d4b0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.strong.transformed.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  method foo<generic-covariant-impl E extends self::C::T% = self::C::T%>(core::List<self::C::foo::E%> list) → dynamic {
+    core::List<self::C::foo::E%> variable = this.{self::C::method}<self::C::foo::E%>(list);
+  }
+  method method<generic-covariant-impl F extends self::C::T% = self::C::T%>(core::List<self::C::method::F%> list) → core::List<self::C::method::F%>
+    return list;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline.expect
new file mode 100644
index 0000000..89b6571
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline.expect
@@ -0,0 +1,6 @@
+class C<T> {
+  foo<E extends T>(List<E> list) {}
+  List<F> method<F extends T>(List<F> list) => list;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2ba6b44
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.textual_outline_modelled.expect
@@ -0,0 +1,6 @@
+class C<T> {
+  List<F> method<F extends T>(List<F> list) => list;
+  foo<E extends T>(List<E> list) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.weak.expect
new file mode 100644
index 0000000..e22d4b0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.weak.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  method foo<generic-covariant-impl E extends self::C::T% = self::C::T%>(core::List<self::C::foo::E%> list) → dynamic {
+    core::List<self::C::foo::E%> variable = this.{self::C::method}<self::C::foo::E%>(list);
+  }
+  method method<generic-covariant-impl F extends self::C::T% = self::C::T%>(core::List<self::C::method::F%> list) → core::List<self::C::method::F%>
+    return list;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43536.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43536.dart.weak.transformed.expect
new file mode 100644
index 0000000..e22d4b0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43536.dart.weak.transformed.expect
@@ -0,0 +1,15 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<T extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::C<self::C::T%>
+    : super core::Object::•()
+    ;
+  method foo<generic-covariant-impl E extends self::C::T% = self::C::T%>(core::List<self::C::foo::E%> list) → dynamic {
+    core::List<self::C::foo::E%> variable = this.{self::C::method}<self::C::foo::E%>(list);
+  }
+  method method<generic-covariant-impl F extends self::C::T% = self::C::T%>(core::List<self::C::method::F%> list) → core::List<self::C::method::F%>
+    return list;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart b/pkg/front_end/testcases/nnbd/issue43716a.dart
new file mode 100644
index 0000000..fac58ad
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+bool b = true;
+
+class C<X extends C<X, X>?, Y extends C<Y, Y>?> {
+  X x;
+  C(this.x);
+  Object m(X x, Y y) {
+    // UP(X extends C<X, X>?, Y extends C<Y, Y>?) ==
+    // C<Object, Object>?.
+    var z = b ? x : y;
+    if (z == null) throw 0;
+    return z.x; // Error.
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.outline.expect
new file mode 100644
index 0000000..be98ef0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.outline.expect
@@ -0,0 +1,14 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<X extends self::C<self::C::X%, self::C::X%>? = self::C<dynamic, dynamic>?, Y extends self::C<self::C::Y%, self::C::Y%>? = self::C<dynamic, dynamic>?> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%, self::C::Y%>
+    ;
+  method m(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → core::Object
+    ;
+}
+static field core::bool b;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.expect
new file mode 100644
index 0000000..f415c03
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//     return z.x; // Error.
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends self::C<self::C::X%, self::C::X%>? = self::C<dynamic, dynamic>?, Y extends self::C<self::C::Y%, self::C::Y%>? = self::C<dynamic, dynamic>?> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%, self::C::Y%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → core::Object {
+    self::C<core::Object?, core::Object?>? z = self::b ?{self::C<core::Object?, core::Object?>?} x : y;
+    if(z.{core::Object::==}(null))
+      throw 0;
+    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+ - 'Object' is from 'dart:core'.
+    return z.x; // Error.
+             ^" in z{self::C<core::Object?, core::Object?>}.{self::C::x} as{TypeError,ForNonNullableByDefault} core::Object;
+  }
+}
+static field core::bool b = true;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.transformed.expect
new file mode 100644
index 0000000..06894de
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.strong.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//     return z.x; // Error.
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends self::C<self::C::X%, self::C::X%>? = self::C<dynamic, dynamic>?, Y extends self::C<self::C::Y%, self::C::Y%>? = self::C<dynamic, dynamic>?> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%, self::C::Y%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → core::Object {
+    self::C<core::Object?, core::Object?>? z = self::b ?{self::C<core::Object?, core::Object?>?} x : y;
+    if(z.{core::Object::==}(null))
+      throw 0;
+    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+ - 'Object' is from 'dart:core'.
+    return z.x; // Error.
+             ^" in let core::Object? #t2 = z{self::C<core::Object?, core::Object?>}.{self::C::x} in #t2.==(null) ?{core::Object} #t2 as{TypeError,ForNonNullableByDefault} core::Object : #t2{core::Object};
+  }
+}
+static field core::bool b = true;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline.expect
new file mode 100644
index 0000000..52093da
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+bool b = true;
+
+class C<X extends C<X, X>?, Y extends C<Y, Y>?> {
+  X x;
+  C(this.x);
+  Object m(X x, Y y) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..5d771921
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+bool b = true;
+
+class C<X extends C<X, X>?, Y extends C<Y, Y>?> {
+  C(this.x);
+  Object m(X x, Y y) {}
+  X x;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.expect
new file mode 100644
index 0000000..f415c03
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//     return z.x; // Error.
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends self::C<self::C::X%, self::C::X%>? = self::C<dynamic, dynamic>?, Y extends self::C<self::C::Y%, self::C::Y%>? = self::C<dynamic, dynamic>?> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%, self::C::Y%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → core::Object {
+    self::C<core::Object?, core::Object?>? z = self::b ?{self::C<core::Object?, core::Object?>?} x : y;
+    if(z.{core::Object::==}(null))
+      throw 0;
+    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+ - 'Object' is from 'dart:core'.
+    return z.x; // Error.
+             ^" in z{self::C<core::Object?, core::Object?>}.{self::C::x} as{TypeError,ForNonNullableByDefault} core::Object;
+  }
+}
+static field core::bool b = true;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.transformed.expect
new file mode 100644
index 0000000..2b40d28
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716a.dart.weak.transformed.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//     return z.x; // Error.
+//              ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends self::C<self::C::X%, self::C::X%>? = self::C<dynamic, dynamic>?, Y extends self::C<self::C::Y%, self::C::Y%>? = self::C<dynamic, dynamic>?> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%, self::C::Y%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m(generic-covariant-impl self::C::X% x, generic-covariant-impl self::C::Y% y) → core::Object {
+    self::C<core::Object?, core::Object?>? z = self::b ?{self::C<core::Object?, core::Object?>?} x : y;
+    if(z.{core::Object::==}(null))
+      throw 0;
+    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716a.dart:15:14: Error: A value of type 'Object?' can't be returned from a function with return type 'Object'.
+ - 'Object' is from 'dart:core'.
+    return z.x; // Error.
+             ^" in z{self::C<core::Object?, core::Object?>}.{self::C::x};
+  }
+}
+static field core::bool b = true;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart b/pkg/front_end/testcases/nnbd/issue43716b.dart
new file mode 100644
index 0000000..629055b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+bool b = true;
+
+void f(Object o) {}
+
+class C<X extends void Function(X)?> {
+  X x;
+  C(this.x);
+  void m() {
+    // UP(X extends void Function(X)?, void Function(Object)) ==
+    // void Function(Object)?.
+    var z = b ? x : f;
+    if (z == null) return;
+    z(42); // Error.
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.outline.expect
new file mode 100644
index 0000000..3b44433
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.outline.expect
@@ -0,0 +1,16 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C<X extends (self::C::X%) →? void = (Never) →? void> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%>
+    ;
+  method m() → void
+    ;
+}
+static field core::bool b;
+static method f(core::Object o) → void
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
new file mode 100644
index 0000000..e9ab0b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+//     z(42); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends (self::C::X%) →? void = (Never) →? void> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m() → void {
+    (Never) →? void z = self::b ?{(Never) →? void} this.{self::C::x} : #C1;
+    if(z.{core::Object::==}(null))
+      return;
+    z{(Never) → void}.call(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+    z(42); // Error.
+      ^" in 42 as{TypeError,ForNonNullableByDefault} Never);
+  }
+}
+static field core::bool b = true;
+static method f(core::Object o) → void {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::f
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
new file mode 100644
index 0000000..e9ab0b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+//     z(42); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends (self::C::X%) →? void = (Never) →? void> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m() → void {
+    (Never) →? void z = self::b ?{(Never) →? void} this.{self::C::x} : #C1;
+    if(z.{core::Object::==}(null))
+      return;
+    z{(Never) → void}.call(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+    z(42); // Error.
+      ^" in 42 as{TypeError,ForNonNullableByDefault} Never);
+  }
+}
+static field core::bool b = true;
+static method f(core::Object o) → void {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::f
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline.expect
new file mode 100644
index 0000000..f44dbcd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+bool b = true;
+void f(Object o) {}
+
+class C<X extends void Function(X)?> {
+  X x;
+  C(this.x);
+  void m() {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..8a353f3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+bool b = true;
+
+class C<X extends void Function(X)?> {
+  C(this.x);
+  X x;
+  void m() {}
+}
+
+main() {}
+void f(Object o) {}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
new file mode 100644
index 0000000..e9ab0b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+//     z(42); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends (self::C::X%) →? void = (Never) →? void> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m() → void {
+    (Never) →? void z = self::b ?{(Never) →? void} this.{self::C::x} : #C1;
+    if(z.{core::Object::==}(null))
+      return;
+    z{(Never) → void}.call(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+    z(42); // Error.
+      ^" in 42 as{TypeError,ForNonNullableByDefault} Never);
+  }
+}
+static field core::bool b = true;
+static method f(core::Object o) → void {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::f
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
new file mode 100644
index 0000000..e9ab0b4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43716b.dart.weak.transformed.expect
@@ -0,0 +1,32 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+//     z(42); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class C<X extends (self::C::X%) →? void = (Never) →? void> extends core::Object {
+  generic-covariant-impl field self::C::X% x;
+  constructor •(self::C::X% x) → self::C<self::C::X%>
+    : self::C::x = x, super core::Object::•()
+    ;
+  method m() → void {
+    (Never) →? void z = self::b ?{(Never) →? void} this.{self::C::x} : #C1;
+    if(z.{core::Object::==}(null))
+      return;
+    z{(Never) → void}.call(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43716b.dart:17:7: Error: The argument type 'int' can't be assigned to the parameter type 'Never'.
+    z(42); // Error.
+      ^" in 42 as{TypeError,ForNonNullableByDefault} Never);
+  }
+}
+static field core::bool b = true;
+static method f(core::Object o) → void {}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = tearoff self::f
+}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart b/pkg/front_end/testcases/nnbd/issue43721.dart
new file mode 100644
index 0000000..a5f8c2c
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+foo(Object x) {}
+
+bar(bool condition) {
+  FutureOr<int?> x = null;
+  num n = 1;
+  var z = condition ? x : n;
+  foo(z); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.outline.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.outline.expect
new file mode 100644
index 0000000..fb5deaf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.outline.expect
@@ -0,0 +1,12 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo(core::Object x) → dynamic
+  ;
+static method bar(core::bool condition) → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.strong.expect
new file mode 100644
index 0000000..a293187
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.strong.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//   foo(z); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo(core::Object x) → dynamic {}
+static method bar(core::bool condition) → dynamic {
+  FutureOr<core::int?>x = null;
+  core::num n = 1;
+  FutureOr<core::num?>z = condition ?{FutureOr<core::num?>} x : n;
+  self::foo(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+ - 'Object' is from 'dart:core'.
+  foo(z); // Error.
+      ^" in z as{TypeError,ForNonNullableByDefault} core::Object);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.strong.transformed.expect
new file mode 100644
index 0000000..7d5061d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//   foo(z); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo(core::Object x) → dynamic {}
+static method bar(core::bool condition) → dynamic {
+  FutureOr<core::int?>x = null;
+  core::num n = 1;
+  FutureOr<core::num?>z = condition ?{FutureOr<core::num?>} x : n;
+  self::foo(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+ - 'Object' is from 'dart:core'.
+  foo(z); // Error.
+      ^" in let FutureOr<core::num?>#t2 = z in #t2.==(null) ?{core::Object} #t2 as{TypeError,ForNonNullableByDefault} core::Object : #t2{core::Object});
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline.expect
new file mode 100644
index 0000000..6cc3511
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline.expect
@@ -0,0 +1,5 @@
+import 'dart:async';
+
+foo(Object x) {}
+bar(bool condition) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..78950e4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.textual_outline_modelled.expect
@@ -0,0 +1,5 @@
+import 'dart:async';
+
+bar(bool condition) {}
+foo(Object x) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.weak.expect
new file mode 100644
index 0000000..a293187
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.weak.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//   foo(z); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo(core::Object x) → dynamic {}
+static method bar(core::bool condition) → dynamic {
+  FutureOr<core::int?>x = null;
+  core::num n = 1;
+  FutureOr<core::num?>z = condition ?{FutureOr<core::num?>} x : n;
+  self::foo(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+ - 'Object' is from 'dart:core'.
+  foo(z); // Error.
+      ^" in z as{TypeError,ForNonNullableByDefault} core::Object);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/issue43721.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue43721.dart.weak.transformed.expect
new file mode 100644
index 0000000..7619193
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue43721.dart.weak.transformed.expect
@@ -0,0 +1,25 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+//  - 'Object' is from 'dart:core'.
+//   foo(z); // Error.
+//       ^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+static method foo(core::Object x) → dynamic {}
+static method bar(core::bool condition) → dynamic {
+  FutureOr<core::int?>x = null;
+  core::num n = 1;
+  FutureOr<core::num?>z = condition ?{FutureOr<core::num?>} x : n;
+  self::foo(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/issue43721.dart:13:7: Error: The argument type 'FutureOr<num?>' can't be assigned to the parameter type 'Object'.
+ - 'Object' is from 'dart:core'.
+  foo(z); // Error.
+      ^" in z);
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
index 4ea3cb9..992c773 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}';
 //                              ^^^^^
 //
-// pkg/front_end/testcases/nnbd/later.dart:46:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B();
-//         ^
-// pkg/front_end/testcases/nnbd/later.dart:44:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/nnbd/later.dart:44:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/nnbd/later.dart:46:9: Context: This constructor is const.
+//   const B();
+//         ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
index 37d882a..f36cfd3 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.strong.transformed.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}';
 //                              ^^^^^
 //
-// pkg/front_end/testcases/nnbd/later.dart:46:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B();
-//         ^
-// pkg/front_end/testcases/nnbd/later.dart:44:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/nnbd/later.dart:44:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/nnbd/later.dart:46:9: Context: This constructor is const.
+//   const B();
+//         ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
index 4ea3cb9..992c773 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}';
 //                              ^^^^^
 //
-// pkg/front_end/testcases/nnbd/later.dart:46:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B();
-//         ^
-// pkg/front_end/testcases/nnbd/later.dart:44:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/nnbd/later.dart:44:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/nnbd/later.dart:46:9: Context: This constructor is const.
+//   const B();
+//         ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
index 37d882a..f36cfd3 100644
--- a/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/later.dart.weak.transformed.expect
@@ -55,12 +55,12 @@
 //   late String s2 = '${fisk}${await hest()}${fisk}';
 //                              ^^^^^
 //
-// pkg/front_end/testcases/nnbd/later.dart:46:9: Error: Constructor is marked 'const' so fields can't be late.
-//   const B();
-//         ^
-// pkg/front_end/testcases/nnbd/later.dart:44:18: Context: Field is late, but constructor is 'const'.
+// pkg/front_end/testcases/nnbd/later.dart:44:18: Error: Can't have a late final field in a class with a const constructor.
 //   late final int x = 42;
 //                  ^
+// pkg/front_end/testcases/nnbd/later.dart:46:9: Context: This constructor is const.
+//   const B();
+//         ^
 //
 import self as self;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart b/pkg/front_end/testcases/nnbd/main_declaration.dart
new file mode 100644
index 0000000..102df45
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'main_declaration_class_lib.dart' as class_lib;
+import 'main_declaration_extension_lib.dart' as extension_lib;
+import 'main_declaration_field_lib.dart' as field_lib;
+import 'main_declaration_getter_lib.dart' as getter_lib;
+import 'main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'main_declaration_setter_lib.dart' as setter_lib;
+import 'main_declaration_typedef_lib.dart' as typedef_lib;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.outline.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.outline.expect
new file mode 100644
index 0000000..60101d4
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.outline.expect
@@ -0,0 +1,195 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → self2::main
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+
+static field () → void main;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+
+static get main() → () → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args}) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args}) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args, dynamic other]) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+
+static set main(() → void f) → void
+  ;
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+
+typedef main = () → void;
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.expect
new file mode 100644
index 0000000..bef2df6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.expect
@@ -0,0 +1,191 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → self2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.transformed.expect
new file mode 100644
index 0000000..bef2df6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.strong.transformed.expect
@@ -0,0 +1,191 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → self2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline.expect
new file mode 100644
index 0000000..13c6b88
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline.expect
@@ -0,0 +1,28 @@
+import 'main_declaration_class_lib.dart' as class_lib;
+import 'main_declaration_extension_lib.dart' as extension_lib;
+import 'main_declaration_field_lib.dart' as field_lib;
+import 'main_declaration_getter_lib.dart' as getter_lib;
+import 'main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'main_declaration_setter_lib.dart' as setter_lib;
+import 'main_declaration_typedef_lib.dart' as typedef_lib;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..13c6b88
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.textual_outline_modelled.expect
@@ -0,0 +1,28 @@
+import 'main_declaration_class_lib.dart' as class_lib;
+import 'main_declaration_extension_lib.dart' as extension_lib;
+import 'main_declaration_field_lib.dart' as field_lib;
+import 'main_declaration_getter_lib.dart' as getter_lib;
+import 'main_declaration_method_extra_optional_parameters_lib.dart'
+    as method_extra_optional_parameters_lib;
+import 'main_declaration_method_named_parameters_lib.dart'
+    as method_named_parameters_lib;
+import 'main_declaration_method_one_optional_parameter_lib.dart'
+    as method_one_optional_parameter_lib;
+import 'main_declaration_method_one_parameter_lib.dart'
+    as method_one_parameter_lib;
+import 'main_declaration_method_one_required_optional_lib.dart'
+    as method_one_required_optional_lib;
+import 'main_declaration_method_required_named_parameters_lib.dart'
+    as method_required_named_parameters_lib;
+import 'main_declaration_method_too_many_parameters_lib.dart'
+    as method_too_many_parameters_lib;
+import 'main_declaration_method_two_optional_parameters_lib.dart'
+    as method_two_optional_parameters_lib;
+import 'main_declaration_method_two_parameters_lib.dart'
+    as method_two_parameters_lib;
+import 'main_declaration_method_wrong_parameter_type_lib.dart'
+    as method_wrong_parameter_type_lib;
+import 'main_declaration_setter_lib.dart' as setter_lib;
+import 'main_declaration_typedef_lib.dart' as typedef_lib;
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.expect
new file mode 100644
index 0000000..c850a85
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.expect
@@ -0,0 +1,191 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → self2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.transformed.expect
new file mode 100644
index 0000000..c850a85
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration.dart.weak.transformed.expect
@@ -0,0 +1,191 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_class_lib.dart" as class_lib;
+import "org-dartlang-testcase:///main_declaration_extension_lib.dart" as extension_lib;
+import "org-dartlang-testcase:///main_declaration_field_lib.dart" as field_lib;
+import "org-dartlang-testcase:///main_declaration_getter_lib.dart" as getter_lib;
+import "org-dartlang-testcase:///main_declaration_method_extra_optional_parameters_lib.dart" as method_extra_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_named_parameters_lib.dart" as method_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_optional_parameter_lib.dart" as method_one_optional_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_parameter_lib.dart" as method_one_parameter_lib;
+import "org-dartlang-testcase:///main_declaration_method_one_required_optional_lib.dart" as method_one_required_optional_lib;
+import "org-dartlang-testcase:///main_declaration_method_required_named_parameters_lib.dart" as method_required_named_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_too_many_parameters_lib.dart" as method_too_many_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_optional_parameters_lib.dart" as method_two_optional_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_two_parameters_lib.dart" as method_two_parameters_lib;
+import "org-dartlang-testcase:///main_declaration_method_wrong_parameter_type_lib.dart" as method_wrong_parameter_type_lib;
+import "org-dartlang-testcase:///main_declaration_setter_lib.dart" as setter_lib;
+import "org-dartlang-testcase:///main_declaration_typedef_lib.dart" as typedef_lib;
+
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart:5:7: Error: The 'main' declaration must be a function declaration.
+// class main /* error */ {}
+//       ^
+//
+import self as self2;
+import "dart:core" as core;
+
+class main extends core::Object {
+  synthetic constructor •() → self2::main
+    : super core::Object::•()
+    ;
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart:5:11: Error: The 'main' declaration must be a function declaration.
+// extension main /* error */ on Object {}
+//           ^
+//
+import self as self3;
+import "dart:core" as core;
+
+extension main on core::Object {
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart:5:17: Error: The 'main' declaration must be a function declaration.
+// void Function() main /* error */ = () {};
+//                 ^^^^
+//
+import self as self4;
+import "dart:core" as core;
+
+static field () → void main = () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart:5:21: Error: The 'main' declaration must be a function declaration.
+// void Function() get main /* error */ => () {};
+//                     ^^^^
+//
+import self as self5;
+import "dart:core" as core;
+
+static get main() → () → void
+  return () → core::Null? {};
+
+library /*isNonNullableByDefault*/;
+import self as self6;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other, [dynamic extra = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self7;
+import "dart:core" as core;
+
+static method main({core::List<core::String> args = #C2}) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self8;
+import "dart:core" as core;
+
+static method main([core::List<core::String>? args = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self9;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self10;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, [dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart:5:6: Error: The 'main' method cannot have required named parameters.
+// void main({required List<String> args}) /* error */ {}
+//      ^^^^
+//
+import self as self11;
+import "dart:core" as core;
+
+static method main({required core::List<core::String> args = #C1}) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart:5:6: Error: The 'main' method must have at most 2 required parameters.
+// void main(List<String> args, a, b) /* error */ {}
+//      ^^^^
+//
+import self as self12;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic a, dynamic b) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self13;
+import "dart:core" as core;
+
+static method main([core::List<core::String> args = #C2, dynamic other = #C1]) → void {}
+
+library /*isNonNullableByDefault*/;
+import self as self14;
+import "dart:core" as core;
+
+static method main(core::List<core::String> args, dynamic other) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart:5:6: Error: The type 'Set<String>' of the first parameter of the 'main' method is not a supertype of 'List<String>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'List' is from 'dart:core'.
+// void main(Set<String> args) /* error */ {}
+//      ^^^^
+//
+import self as self15;
+import "dart:core" as core;
+
+static method main(core::Set<core::String> args) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart:5:10: Error: The 'main' declaration must be a function declaration.
+// void set main(void Function() f) /* error */ {}
+//          ^^^^
+//
+import self as self16;
+
+static set main(() → void f) → void {}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart:5:9: Error: The 'main' declaration must be a function declaration.
+// typedef main /* error */ = void Function();
+//         ^
+//
+import self as self17;
+
+typedef main = () → void;
+
+constants  {
+  #C1 = null
+  #C2 = <core::String*>[]
+}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart
new file mode 100644
index 0000000..3adbd2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_class_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class main /* error */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart
new file mode 100644
index 0000000..5ac4335
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_extension_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+extension main /* error */ on Object {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart
new file mode 100644
index 0000000..a90670e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_field_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void Function() main /* error */ = () {};
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart
new file mode 100644
index 0000000..fb93e96
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_getter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void Function() get main /* error */ => () {};
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_extra_optional_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_extra_optional_parameters_lib.dart
new file mode 100644
index 0000000..1d64aba
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_extra_optional_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(List<String> args, other, [extra]) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_named_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_named_parameters_lib.dart
new file mode 100644
index 0000000..22ff181
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_named_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main({List<String> args = const []}) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_one_optional_parameter_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_one_optional_parameter_lib.dart
new file mode 100644
index 0000000..bcdd265
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_one_optional_parameter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main([List<String>? args]) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_one_parameter_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_one_parameter_lib.dart
new file mode 100644
index 0000000..1c04bbf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_one_parameter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(List<String> args) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_one_required_optional_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_one_required_optional_lib.dart
new file mode 100644
index 0000000..1a18bcb
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_one_required_optional_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(List<String> args, [other]) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart
new file mode 100644
index 0000000..705bf05
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_required_named_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main({required List<String> args}) /* error */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart
new file mode 100644
index 0000000..9fc54c9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_too_many_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(List<String> args, a, b) /* error */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_two_optional_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_two_optional_parameters_lib.dart
new file mode 100644
index 0000000..5659662
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_two_optional_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main([List<String> args = const [], other]) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_two_parameters_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_two_parameters_lib.dart
new file mode 100644
index 0000000..d737d25
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_two_parameters_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(List<String> args, other) /* ok */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart
new file mode 100644
index 0000000..c0a8f34
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_method_wrong_parameter_type_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main(Set<String> args) /* error */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart
new file mode 100644
index 0000000..d9fd5bc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_setter_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void set main(void Function() f) /* error */ {}
diff --git a/pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart b/pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart
new file mode 100644
index 0000000..d0ea0fa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/main_declaration_typedef_lib.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+typedef main /* error */ = void Function();
diff --git a/pkg/front_end/testcases/nnbd/never_calls.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_calls.dart.weak.expect
index 33ac05b..242bb80 100644
--- a/pkg/front_end/testcases/nnbd/never_calls.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_calls.dart.weak.expect
@@ -1,34 +1,35 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method propertyGet(Never never) → dynamic {
-  Never v1 = never.foo;
-  Never v2 = never.hashCode;
-  Never v3 = never.runtimeType;
-  Never v4 = never.toString;
-  Never v5 = never.noSuchMethod;
+  Never v1 = let final Never #t1 = (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t3 = (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).hashCode in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t5 = (let final Never #t6 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t7 = (let final Never #t8 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v5 = let final Never #t9 = (let final Never #t10 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method propertySet(Never never) → dynamic {
-  core::int v1 = never.foo = 42;
+  core::int v1 = (let final Never #t11 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo = 42;
 }
 static method methodInvocation(Never never, core::Invocation invocation) → dynamic {
-  Never v1 = never.foo();
-  Never v2 = never.hashCode();
-  Never v3 = never.runtimeType();
-  Never v4 = never.toString();
-  Never v5 = never.toString(foo: 42);
-  Never v6 = never.noSuchMethod(invocation);
-  Never v7 = never.noSuchMethod(42);
+  Never v1 = let final Never #t12 = (let final Never #t13 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t14 = (let final Never #t15 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).hashCode() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t16 = (let final Never #t17 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t18 = (let final Never #t19 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v5 = let final Never #t20 = (let final Never #t21 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString(foo: 42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v6 = let final Never #t22 = (let final Never #t23 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod(invocation) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v7 = let final Never #t24 = (let final Never #t25 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod(42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method equals(Never never) → dynamic {
-  Never v1 = never.==(null);
-  Never v2 = never.==(never);
+  Never v1 = let final Never #t26 = (let final Never #t27 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(null) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t28 = (let final Never #t29 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(let final Never #t30 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method operator(Never never) → dynamic {
-  Never v1 = never.+(never);
-  Never v2 = never.unary-();
-  Never v3 = never.[](never);
-  Never v4 = let final Never #t1 = never in let final Never #t2 = never in let final Never #t3 = never in let final void #t4 = #t1.[]=(#t2, #t3) in #t3;
+  Never v1 = let final Never #t31 = (let final Never #t32 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t33 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t34 = (let final Never #t35 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).unary-() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t36 = (let final Never #t37 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t38 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t39 = let final Never #t40 = let final Never #t41 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final Never #t42 = let final Never #t43 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final Never #t44 = let final Never #t45 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final void #t46 = #t40.[]=(#t42, #t44) in #t44 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/never_calls.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_calls.dart.weak.transformed.expect
index 33ac05b..242bb80 100644
--- a/pkg/front_end/testcases/nnbd/never_calls.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_calls.dart.weak.transformed.expect
@@ -1,34 +1,35 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method propertyGet(Never never) → dynamic {
-  Never v1 = never.foo;
-  Never v2 = never.hashCode;
-  Never v3 = never.runtimeType;
-  Never v4 = never.toString;
-  Never v5 = never.noSuchMethod;
+  Never v1 = let final Never #t1 = (let final Never #t2 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t3 = (let final Never #t4 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).hashCode in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t5 = (let final Never #t6 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t7 = (let final Never #t8 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v5 = let final Never #t9 = (let final Never #t10 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method propertySet(Never never) → dynamic {
-  core::int v1 = never.foo = 42;
+  core::int v1 = (let final Never #t11 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo = 42;
 }
 static method methodInvocation(Never never, core::Invocation invocation) → dynamic {
-  Never v1 = never.foo();
-  Never v2 = never.hashCode();
-  Never v3 = never.runtimeType();
-  Never v4 = never.toString();
-  Never v5 = never.toString(foo: 42);
-  Never v6 = never.noSuchMethod(invocation);
-  Never v7 = never.noSuchMethod(42);
+  Never v1 = let final Never #t12 = (let final Never #t13 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t14 = (let final Never #t15 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).hashCode() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t16 = (let final Never #t17 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).runtimeType() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t18 = (let final Never #t19 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v5 = let final Never #t20 = (let final Never #t21 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).toString(foo: 42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v6 = let final Never #t22 = (let final Never #t23 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod(invocation) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v7 = let final Never #t24 = (let final Never #t25 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).noSuchMethod(42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method equals(Never never) → dynamic {
-  Never v1 = never.==(null);
-  Never v2 = never.==(never);
+  Never v1 = let final Never #t26 = (let final Never #t27 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(null) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t28 = (let final Never #t29 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(let final Never #t30 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method operator(Never never) → dynamic {
-  Never v1 = never.+(never);
-  Never v2 = never.unary-();
-  Never v3 = never.[](never);
-  Never v4 = let final Never #t1 = never in let final Never #t2 = never in let final Never #t3 = never in let final void #t4 = #t1.[]=(#t2, #t3) in #t3;
+  Never v1 = let final Never #t31 = (let final Never #t32 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(let final Never #t33 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v2 = let final Never #t34 = (let final Never #t35 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).unary-() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v3 = let final Never #t36 = (let final Never #t37 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](let final Never #t38 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  Never v4 = let final Never #t39 = let final Never #t40 = let final Never #t41 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final Never #t42 = let final Never #t43 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final Never #t44 = let final Never #t45 = never in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in let final void #t46 = #t40.[]=(#t42, #t44) in #t44 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/never_equals.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_equals.dart.weak.expect
index eafd607..52cfdac 100644
--- a/pkg/front_end/testcases/nnbd/never_equals.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_equals.dart.weak.expect
@@ -1,9 +1,10 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method test(Never nonNullableNever, Never? nullableNever) → dynamic {
-  Never v1 = nonNullableNever.==(nonNullableNever);
+  Never v1 = let final Never #t1 = (let final Never #t2 = nonNullableNever in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(let final Never #t3 = nonNullableNever in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   core::bool v2 = nullableNever.{core::Object::==}(nullableNever);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/never_equals.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_equals.dart.weak.transformed.expect
index eafd607..52cfdac 100644
--- a/pkg/front_end/testcases/nnbd/never_equals.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_equals.dart.weak.transformed.expect
@@ -1,9 +1,10 @@
 library /*isNonNullableByDefault*/;
 import self as self;
+import "dart:_internal" as _in;
 import "dart:core" as core;
 
 static method test(Never nonNullableNever, Never? nullableNever) → dynamic {
-  Never v1 = nonNullableNever.==(nonNullableNever);
+  Never v1 = let final Never #t1 = (let final Never #t2 = nonNullableNever in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).==(let final Never #t3 = nonNullableNever in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   core::bool v2 = nullableNever.{core::Object::==}(nullableNever);
 }
 static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
index 8a67b5a..ea4279d 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.expect
@@ -64,29 +64,30 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
-  x.foo();
-  x.bar;
-  x.baz = 42;
-  x.call();
-  x.[](42);
-  x.[]=(42, 42);
-  x = x.+(1);
-  x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{core::Null?} null : #t1{Never}.foo();
-  let final Never? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let final Never? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let final Never? #t4 = y in #t4.{core::Object::==}(null) ?{core::Null?} null : #t4{Never}.call();
-  let final Never? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let final Never? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
-  let final Never #t7 = x in #t7.{core::Object::==}(null) ?{core::Null?} null : #t7.foo();
-  let final Never #t8 = x in #t8.{core::Object::==}(null) ?{core::Null?} null : #t8.bar;
-  let final Never #t9 = x in #t9.{core::Object::==}(null) ?{core::int?} null : #t9.baz = 42;
-  let final Never #t10 = x in #t10.{core::Object::==}(null) ?{core::Null?} null : #t10.[](42);
-  let final Never #t11 = x in #t11.{core::Object::==}(null) ?{core::int?} null : #t11.[]=(42, 42);
+  let final Never #t1 = (let final Never #t2 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t3 = (let final Never #t4 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (let final Never #t5 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never #t6 = (let final Never #t7 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t8 = (let final Never #t9 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (let final Never #t10 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
+  let final Never #t11 = x = let final Never #t12 = (let final Never #t13 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(1) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t14 = x = let final Never #t15 = (let final Never #t16 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(1) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t17 = y in #t17.{core::Object::==}(null) ?{core::Null?} null : let final Never #t18 = (let final Never #t19 = #t17{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t20 = y in #t20.{core::Object::==}(null) ?{core::Null?} null : let final Never #t21 = (let final Never #t22 = #t20{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t23 = y in #t23.{core::Object::==}(null) ?{core::int?} null : (let final Never #t24 = #t23{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never? #t25 = y in #t25.{core::Object::==}(null) ?{core::Null?} null : let final Never #t26 = (let final Never #t27 = #t25{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t28 = y in #t28.{core::Object::==}(null) ?{core::Null?} null : let final Never #t29 = (let final Never #t30 = #t28{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t31 = y in #t31.{core::Object::==}(null) ?{core::int?} null : (let final Never #t32 = #t31{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
+  let final Never #t33 = let final Never #t34 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t33.{core::Object::==}(null) ?{core::Null?} null : let final Never #t35 = (let final Never #t36 = #t33 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t37 = let final Never #t38 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t37.{core::Object::==}(null) ?{core::Null?} null : let final Never #t39 = (let final Never #t40 = #t37 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t41 = let final Never #t42 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t41.{core::Object::==}(null) ?{core::int?} null : (let final Never #t43 = #t41 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never #t44 = let final Never #t45 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t44.{core::Object::==}(null) ?{core::Null?} null : let final Never #t46 = (let final Never #t47 = #t44 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t48 = let final Never #t49 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t48.{core::Object::==}(null) ?{core::int?} null : (let final Never #t50 = #t48 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
   invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:5: Error: The method 'foo' isn't defined for the class 'Never?'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
index aa42b16..d677ad0 100644
--- a/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/never_receiver.dart.weak.transformed.expect
@@ -64,29 +64,30 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 static method foo(Never x, Never? y) → dynamic {
   core::String local0 = y.{core::Object::toString}();
   core::int local1 = y.{core::Object::hashCode};
-  x.foo();
-  x.bar;
-  x.baz = 42;
-  x.call();
-  x.[](42);
-  x.[]=(42, 42);
-  x = x.+(1);
-  x = x.+(1);
-  let final Never? #t1 = y in #t1.{core::Object::==}(null) ?{core::Null?} null : #t1{Never}.foo();
-  let final Never? #t2 = y in #t2.{core::Object::==}(null) ?{core::Null?} null : #t2{Never}.bar;
-  let final Never? #t3 = y in #t3.{core::Object::==}(null) ?{core::int?} null : #t3{Never}.baz = 42;
-  let final Never? #t4 = y in #t4.{core::Object::==}(null) ?{core::Null?} null : #t4{Never}.call();
-  let final Never? #t5 = y in #t5.{core::Object::==}(null) ?{core::Null?} null : #t5{Never}.[](42);
-  let final Never? #t6 = y in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{Never}.[]=(42, 42);
-  let final Never #t7 = x in #t7.{core::Object::==}(null) ?{core::Null?} null : #t7.foo();
-  let final Never #t8 = x in #t8.{core::Object::==}(null) ?{core::Null?} null : #t8.bar;
-  let final Never #t9 = x in #t9.{core::Object::==}(null) ?{core::int?} null : #t9.baz = 42;
-  let final Never #t10 = x in #t10.{core::Object::==}(null) ?{core::Null?} null : #t10.[](42);
-  let final Never #t11 = x in #t11.{core::Object::==}(null) ?{core::int?} null : #t11.[]=(42, 42);
+  let final Never #t1 = (let final Never #t2 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t3 = (let final Never #t4 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (let final Never #t5 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never #t6 = (let final Never #t7 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t8 = (let final Never #t9 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  (let final Never #t10 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
+  let final Never #t11 = x = let final Never #t12 = (let final Never #t13 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(1) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t14 = x = let final Never #t15 = (let final Never #t16 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).+(1) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t17 = y in #t17.{core::Object::==}(null) ?{core::Null?} null : let final Never #t18 = (let final Never #t19 = #t17{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t20 = y in #t20.{core::Object::==}(null) ?{core::Null?} null : let final Never #t21 = (let final Never #t22 = #t20{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t23 = y in #t23.{core::Object::==}(null) ?{core::int?} null : (let final Never #t24 = #t23{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never? #t25 = y in #t25.{core::Object::==}(null) ?{core::Null?} null : let final Never #t26 = (let final Never #t27 = #t25{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t28 = y in #t28.{core::Object::==}(null) ?{core::Null?} null : let final Never #t29 = (let final Never #t30 = #t28{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never? #t31 = y in #t31.{core::Object::==}(null) ?{core::int?} null : (let final Never #t32 = #t31{Never} in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
+  let final Never #t33 = let final Never #t34 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t33.{core::Object::==}(null) ?{core::Null?} null : let final Never #t35 = (let final Never #t36 = #t33 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).foo() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t37 = let final Never #t38 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t37.{core::Object::==}(null) ?{core::Null?} null : let final Never #t39 = (let final Never #t40 = #t37 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).bar in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t41 = let final Never #t42 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t41.{core::Object::==}(null) ?{core::int?} null : (let final Never #t43 = #t41 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).baz = 42;
+  let final Never #t44 = let final Never #t45 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t44.{core::Object::==}(null) ?{core::Null?} null : let final Never #t46 = (let final Never #t47 = #t44 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[](42) in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  let final Never #t48 = let final Never #t49 = x in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.") in #t48.{core::Object::==}(null) ?{core::int?} null : (let final Never #t50 = #t48 in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.")).[]=(42, 42);
   invalid-expression "pkg/front_end/testcases/nnbd/never_receiver.dart:30:5: Error: The method 'foo' isn't defined for the class 'Never?'.
 Try correcting the name to the name of an existing method, or defining a method named 'foo'.
   y.foo(); // Error.
diff --git a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.expect b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.expect
index 82f387d..af326bf 100644
--- a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42] = 42;
 //      ^
 //
@@ -15,6 +17,7 @@
 //           ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]++;
 //      ^
 //
@@ -23,6 +26,7 @@
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42];
 //        ^
 //
@@ -31,18 +35,22 @@
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //            ^
 //
@@ -51,10 +59,12 @@
 //                ^^^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //            ^
 //
@@ -63,10 +73,12 @@
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //              ^
 //
@@ -79,6 +91,7 @@
 static method main() → dynamic {
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42];
      ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:11: Error: Can't assign to this.
@@ -87,14 +100,17 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Can't assign to this.
   c?.[42]++;
      ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]++;
      ^";
   let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Can't assign to this.
   ++c?.[42];
        ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42];
        ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0];
            ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:16: Error: Can't assign to this.
@@ -103,11 +119,13 @@
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Can't assign to this.
   c?.[42]?.[0]++;
            ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0]++;
            ^";
   let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Can't assign to this.
   ++c?.[42]?.[0];
              ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42]?.[0];
              ^";
 }
diff --git a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.transformed.expect
index 82f387d..af326bf 100644
--- a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.strong.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42] = 42;
 //      ^
 //
@@ -15,6 +17,7 @@
 //           ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]++;
 //      ^
 //
@@ -23,6 +26,7 @@
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42];
 //        ^
 //
@@ -31,18 +35,22 @@
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //            ^
 //
@@ -51,10 +59,12 @@
 //                ^^^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //            ^
 //
@@ -63,10 +73,12 @@
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //              ^
 //
@@ -79,6 +91,7 @@
 static method main() → dynamic {
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42];
      ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:11: Error: Can't assign to this.
@@ -87,14 +100,17 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Can't assign to this.
   c?.[42]++;
      ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]++;
      ^";
   let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Can't assign to this.
   ++c?.[42];
        ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42];
        ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0];
            ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:16: Error: Can't assign to this.
@@ -103,11 +119,13 @@
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Can't assign to this.
   c?.[42]?.[0]++;
            ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0]++;
            ^";
   let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Can't assign to this.
   ++c?.[42]?.[0];
              ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42]?.[0];
              ^";
 }
diff --git a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.expect b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.expect
index 82f387d..af326bf 100644
--- a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42] = 42;
 //      ^
 //
@@ -15,6 +17,7 @@
 //           ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]++;
 //      ^
 //
@@ -23,6 +26,7 @@
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42];
 //        ^
 //
@@ -31,18 +35,22 @@
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //            ^
 //
@@ -51,10 +59,12 @@
 //                ^^^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //            ^
 //
@@ -63,10 +73,12 @@
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //              ^
 //
@@ -79,6 +91,7 @@
 static method main() → dynamic {
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42];
      ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:11: Error: Can't assign to this.
@@ -87,14 +100,17 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Can't assign to this.
   c?.[42]++;
      ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]++;
      ^";
   let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Can't assign to this.
   ++c?.[42];
        ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42];
        ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0];
            ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:16: Error: Can't assign to this.
@@ -103,11 +119,13 @@
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Can't assign to this.
   c?.[42]?.[0]++;
            ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0]++;
            ^";
   let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Can't assign to this.
   ++c?.[42]?.[0];
              ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42]?.[0];
              ^";
 }
diff --git a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.transformed.expect
index 82f387d..af326bf 100644
--- a/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart.weak.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42] = 42;
 //      ^
 //
@@ -15,6 +17,7 @@
 //           ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]++;
 //      ^
 //
@@ -23,6 +26,7 @@
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42];
 //        ^
 //
@@ -31,18 +35,22 @@
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0];
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0] ??= 42;
 //            ^
 //
@@ -51,10 +59,12 @@
 //                ^^^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:6: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //      ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   c?.[42]?.[0]++;
 //            ^
 //
@@ -63,10 +73,12 @@
 //            ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:8: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //        ^
 //
 // pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+// Try inserting an identifier before '['.
 //   ++c?.[42]?.[0];
 //              ^
 //
@@ -79,6 +91,7 @@
 static method main() → dynamic {
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:7:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42];
      ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:8:11: Error: Can't assign to this.
@@ -87,14 +100,17 @@
   let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Can't assign to this.
   c?.[42]++;
      ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:9:6: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]++;
      ^";
   let final<BottomType> #t2 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Can't assign to this.
   ++c?.[42];
        ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:10:8: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42];
        ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:11:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0];
            ^";
   invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:12:16: Error: Can't assign to this.
@@ -103,11 +119,13 @@
   let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Can't assign to this.
   c?.[42]?.[0]++;
            ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:13:12: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   c?.[42]?.[0]++;
            ^";
   let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Can't assign to this.
   ++c?.[42]?.[0];
              ^" in invalid-expression "pkg/front_end/testcases/nnbd/no_support_for_old_null_aware_index_access_syntax.dart:14:14: Error: Expected an identifier, but got '['.
+Try inserting an identifier before '['.
   ++c?.[42]?.[0];
              ^";
 }
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
index 057a76f..296454f 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.outline.expect
@@ -14,6 +14,10 @@
 //   static int staticFieldOfM; // Error.
 //              ^^^^^^^^^^^^^^
 //
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:34:14: Error: Field 'staticFieldOfE' should be initialized because its type 'int' doesn't allow null.
+//   static int staticFieldOfE; // Error.
+//              ^^^^^^^^^^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
index bd5dcc7..344ba8c 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.expect
@@ -14,15 +14,28 @@
 //   static int staticFieldOfM; // Error.
 //              ^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:34:14: Error: Field 'staticFieldOfE' should be initialized because its type 'int' doesn't allow null.
+//   static int staticFieldOfE; // Error.
+//              ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:12:3: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+//   A.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Context: 'fieldOfA' is defined here.
 //   int fieldOfA; // Error.
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Context: 'fieldOfB' is defined here.
 //   X fieldOfB; // Error.
 //     ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Context: 'fieldOfB2' is defined here.
 //   Y fieldOfB2; // Error.
 //     ^^^^^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
index bd5dcc7..344ba8c 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.strong.transformed.expect
@@ -14,15 +14,28 @@
 //   static int staticFieldOfM; // Error.
 //              ^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:34:14: Error: Field 'staticFieldOfE' should be initialized because its type 'int' doesn't allow null.
+//   static int staticFieldOfE; // Error.
+//              ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:12:3: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+//   A.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Context: 'fieldOfA' is defined here.
 //   int fieldOfA; // Error.
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Context: 'fieldOfB' is defined here.
 //   X fieldOfB; // Error.
 //     ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Context: 'fieldOfB2' is defined here.
 //   Y fieldOfB2; // Error.
 //     ^^^^^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
index bd5dcc7..344ba8c 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.expect
@@ -14,15 +14,28 @@
 //   static int staticFieldOfM; // Error.
 //              ^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:34:14: Error: Field 'staticFieldOfE' should be initialized because its type 'int' doesn't allow null.
+//   static int staticFieldOfE; // Error.
+//              ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:12:3: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+//   A.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Context: 'fieldOfA' is defined here.
 //   int fieldOfA; // Error.
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Context: 'fieldOfB' is defined here.
 //   X fieldOfB; // Error.
 //     ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Context: 'fieldOfB2' is defined here.
 //   Y fieldOfB2; // Error.
 //     ^^^^^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
index bd5dcc7..344ba8c 100644
--- a/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart.weak.transformed.expect
@@ -14,15 +14,28 @@
 //   static int staticFieldOfM; // Error.
 //              ^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:34:14: Error: Field 'staticFieldOfE' should be initialized because its type 'int' doesn't allow null.
+//   static int staticFieldOfE; // Error.
+//              ^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:12:3: Error: This constructor should initialize field 'fieldOfA' because its type 'int' doesn't allow null.
+//   A.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:11:7: Context: 'fieldOfA' is defined here.
 //   int fieldOfA; // Error.
 //       ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB' because its type 'X' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:17:5: Context: 'fieldOfB' is defined here.
 //   X fieldOfB; // Error.
 //     ^^^^^^^^
 //
-// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:19:3: Error: This constructor should initialize field 'fieldOfB2' because its type 'Y' doesn't allow null.
+//   B.foo();
+//   ^
+// pkg/front_end/testcases/nnbd/non_nullable_field_initialization.dart:18:5: Context: 'fieldOfB2' is defined here.
 //   Y fieldOfB2; // Error.
 //     ^^^^^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
index 6c5d89f..edab243 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.strong.expect
@@ -191,8 +191,8 @@
                                ^" in #t34.{self::Class::nullableField}.{core::num::+}(2)) as{TypeError,ForNonNullableByDefault} core::int?;
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : #t37.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t37.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t38 = nullableClass in #t38.{core::Object::==}(null) ?{core::int?} null : #t38.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t38.{self::Class::nullableField} = 0 : null;
-  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nonNullableField} = 0 : null;
-  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42{self::Class}.{self::Class::nullableField} = 0 : null;
+  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40.{self::Class::nonNullableField} = 0 : null;
+  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42.{self::Class::nullableField} = 0 : null;
   let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
index 980d82f..599069e 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.strong.transformed.expect
@@ -191,8 +191,8 @@
                                ^" in #t34.{self::Class::nullableField}.{core::num::+}(2);
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : #t37.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t37.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t38 = nullableClass in #t38.{core::Object::==}(null) ?{core::int?} null : #t38.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t38.{self::Class::nullableField} = 0 : null;
-  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nonNullableField} = 0 : null;
-  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42{self::Class}.{self::Class::nullableField} = 0 : null;
+  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40.{self::Class::nonNullableField} = 0 : null;
+  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42.{self::Class::nullableField} = 0 : null;
   let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
index 6c5d89f..edab243 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.weak.expect
@@ -191,8 +191,8 @@
                                ^" in #t34.{self::Class::nullableField}.{core::num::+}(2)) as{TypeError,ForNonNullableByDefault} core::int?;
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : #t37.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t37.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t38 = nullableClass in #t38.{core::Object::==}(null) ?{core::int?} null : #t38.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t38.{self::Class::nullableField} = 0 : null;
-  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nonNullableField} = 0 : null;
-  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42{self::Class}.{self::Class::nullableField} = 0 : null;
+  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40.{self::Class::nonNullableField} = 0 : null;
+  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42.{self::Class::nullableField} = 0 : null;
   let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
diff --git a/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
index 980d82f..599069e 100644
--- a/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_access.dart.weak.transformed.expect
@@ -191,8 +191,8 @@
                                ^" in #t34.{self::Class::nullableField}.{core::num::+}(2);
   let final self::Class? #t37 = nullableClass in #t37.{core::Object::==}(null) ?{core::int?} null : #t37.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t37.{self::Class::nonNullableField} = 0 : null;
   let final self::Class? #t38 = nullableClass in #t38.{core::Object::==}(null) ?{core::int?} null : #t38.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t38.{self::Class::nullableField} = 0 : null;
-  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40{self::Class}.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40{self::Class}.{self::Class::nonNullableField} = 0 : null;
-  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class? #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42{self::Class}.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42{self::Class}.{self::Class::nullableField} = 0 : null;
+  let final self::Class? #t39 = nullableClass in #t39.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t40 = #t39{self::Class}.{self::Class::nonNullableClass} in #t40.{self::Class::nonNullableField}.{core::num::==}(null) ?{core::int} #t40.{self::Class::nonNullableField} = 0 : null;
+  let final self::Class? #t41 = nullableClass in #t41.{core::Object::==}(null) ?{core::int?} null : let final self::Class #t42 = #t41{self::Class}.{self::Class::nonNullableClass} in #t42.{self::Class::nullableField}.{core::num::==}(null) ?{core::int} #t42.{self::Class::nullableField} = 0 : null;
   let final<BottomType> #t43 = invalid-expression "pkg/front_end/testcases/nnbd/null_access.dart:57:16: Error: Can't use an expression of type 'Class?' as a function because it's potentially null.
  - 'Class' is from 'pkg/front_end/testcases/nnbd/null_access.dart'.
 Try calling using ?.call instead.
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
index a53cacf..ff589af 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart
@@ -11,6 +11,6 @@
 }
 
 main() {
-  Class? c = new Class();
+  Class? c = new Class() as Class?;
   c?.getter1.getter2?.getter1.getter2?.field = c;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.strong.expect
@@ -13,7 +13,7 @@
     return this.{self::Class::field};
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
 }
 
diff --git a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
index 267161a..4c16033 100644
--- a/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_aware_chain.dart.weak.expect
@@ -13,7 +13,7 @@
     return this.{self::Class::field};
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   let final self::Class? #t1 = c in #t1.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t2 = #t1{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t2.{core::Object::==}(null) ?{self::Class?} null : let final self::Class? #t3 = #t2{self::Class}.{self::Class::getter1}.{self::Class::getter2} in #t3.{core::Object::==}(null) ?{self::Class?} null : #t3{self::Class}.{self::Class::field} = c{self::Class};
 }
 
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart b/pkg/front_end/testcases/nnbd/null_check.dart
index 110d74f..4cef88b 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart
+++ b/pkg/front_end/testcases/nnbd/null_check.dart
@@ -9,7 +9,7 @@
 }
 
 main() {
-  Class? c = new Class();
+  Class? c = new Class() as Class?;
   c!;
   c!.field;
   c!.field = 42;
@@ -22,7 +22,7 @@
   c + c!;
   (c + c)!;
 
-  bool? o = true;
+  bool? o = true as bool?;
   !o! ? !o! : !!o!!;
   !(o!) ? (!o)! : (!(!o)!)!;
-}
\ No newline at end of file
+}
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.strong.expect
@@ -99,7 +99,7 @@
     return new self::Class::•();
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   c!;
   c{self::Class}!.{self::Class::field};
   c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
   c{self::Class}!.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class})!;
-  core::bool? o = true;
+  core::bool? o = true as{ForNonNullableByDefault} core::bool?;
   !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
   !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
index 26ca627..a1827fa 100644
--- a/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_check.dart.weak.expect
@@ -99,7 +99,7 @@
     return new self::Class::•();
 }
 static method main() → dynamic {
-  self::Class? c = new self::Class::•();
+  self::Class? c = new self::Class::•() as{ForNonNullableByDefault} self::Class?;
   c!;
   c{self::Class}!.{self::Class::field};
   c{self::Class}!.{self::Class::field} = 42;
@@ -111,7 +111,7 @@
   c{self::Class}!.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class}!);
   c{self::Class}.{self::Class::+}(c{self::Class})!;
-  core::bool? o = true;
+  core::bool? o = true as{ForNonNullableByDefault} core::bool?;
   !o! ?{core::bool} !o{core::bool}! : !!o{core::bool}!!;
   !o{core::bool}! ?{core::bool} (!o{core::bool})! : (!(!o{core::bool})!)!;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
index 8f95eca..d0bb828 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.expect
@@ -253,8 +253,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t263 = n1 in #t263.{core::Object::==}(null) ?{self::Class1?} null : #t263.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t263.{self::Class1::nullable1} = n1{self::Class1} : null;
   n1 = let final self::Class1? #t264 = n1 in #t264.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t265 = #t264.{self::Class1::nullable1} in #t265.{core::Object::==}(null) ?{self::Class1} #t264.{self::Class1::nullable1} = n1{self::Class1} : #t265{self::Class1};
-  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267{self::Class1}.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : null;
-  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269{self::Class1}.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
+  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267.{self::Class1::nullable1} = n1{self::Class1} : null;
+  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
   let final self::Class1? #t271 = n1 in #t271.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t272 = #t271{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t273 = n1{self::Class1} in #t272.{self::Class1::[]}(#t273).{core::Object::==}(null) ?{self::Class1} #t272.{self::Class1::[]=}(#t273, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t274 = n1 in #t274.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t275 = #t274{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t276 = n1{self::Class1} in let final self::Class1? #t277 = #t275.{self::Class1::[]}(#t276) in #t277.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t278 = n1{self::Class1} in let final void #t279 = #t275.{self::Class1::[]=}(#t276, #t278) in #t278 : #t277{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
index 8f95eca..d0bb828 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.strong.transformed.expect
@@ -253,8 +253,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t263 = n1 in #t263.{core::Object::==}(null) ?{self::Class1?} null : #t263.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t263.{self::Class1::nullable1} = n1{self::Class1} : null;
   n1 = let final self::Class1? #t264 = n1 in #t264.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t265 = #t264.{self::Class1::nullable1} in #t265.{core::Object::==}(null) ?{self::Class1} #t264.{self::Class1::nullable1} = n1{self::Class1} : #t265{self::Class1};
-  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267{self::Class1}.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : null;
-  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269{self::Class1}.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
+  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267.{self::Class1::nullable1} = n1{self::Class1} : null;
+  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
   let final self::Class1? #t271 = n1 in #t271.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t272 = #t271{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t273 = n1{self::Class1} in #t272.{self::Class1::[]}(#t273).{core::Object::==}(null) ?{self::Class1} #t272.{self::Class1::[]=}(#t273, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t274 = n1 in #t274.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t275 = #t274{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t276 = n1{self::Class1} in let final self::Class1? #t277 = #t275.{self::Class1::[]}(#t276) in #t277.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t278 = n1{self::Class1} in let final void #t279 = #t275.{self::Class1::[]=}(#t276, #t278) in #t278 : #t277{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
index 8f95eca..d0bb828 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.expect
@@ -253,8 +253,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t263 = n1 in #t263.{core::Object::==}(null) ?{self::Class1?} null : #t263.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t263.{self::Class1::nullable1} = n1{self::Class1} : null;
   n1 = let final self::Class1? #t264 = n1 in #t264.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t265 = #t264.{self::Class1::nullable1} in #t265.{core::Object::==}(null) ?{self::Class1} #t264.{self::Class1::nullable1} = n1{self::Class1} : #t265{self::Class1};
-  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267{self::Class1}.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : null;
-  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269{self::Class1}.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
+  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267.{self::Class1::nullable1} = n1{self::Class1} : null;
+  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
   let final self::Class1? #t271 = n1 in #t271.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t272 = #t271{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t273 = n1{self::Class1} in #t272.{self::Class1::[]}(#t273).{core::Object::==}(null) ?{self::Class1} #t272.{self::Class1::[]=}(#t273, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t274 = n1 in #t274.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t275 = #t274{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t276 = n1{self::Class1} in let final self::Class1? #t277 = #t275.{self::Class1::[]}(#t276) in #t277.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t278 = n1{self::Class1} in let final void #t279 = #t275.{self::Class1::[]=}(#t276, #t278) in #t278 : #t277{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
index 8f95eca..d0bb828 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting.dart.weak.transformed.expect
@@ -253,8 +253,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t263 = n1 in #t263.{core::Object::==}(null) ?{self::Class1?} null : #t263.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t263.{self::Class1::nullable1} = n1{self::Class1} : null;
   n1 = let final self::Class1? #t264 = n1 in #t264.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t265 = #t264.{self::Class1::nullable1} in #t265.{core::Object::==}(null) ?{self::Class1} #t264.{self::Class1::nullable1} = n1{self::Class1} : #t265{self::Class1};
-  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267{self::Class1}.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : null;
-  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269{self::Class1}.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269{self::Class1}.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
+  let final self::Class1? #t266 = n1 in #t266.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t267 = #t266{self::Class1}.{self::Class1::nonNullable1} in #t267.{self::Class1::nullable1}.{core::Object::==}(null) ?{self::Class1} #t267.{self::Class1::nullable1} = n1{self::Class1} : null;
+  n1 = let final self::Class1? #t268 = n1 in #t268.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t269 = #t268{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1? #t270 = #t269.{self::Class1::nullable1} in #t270.{core::Object::==}(null) ?{self::Class1} #t269.{self::Class1::nullable1} = n1{self::Class1} : #t270{self::Class1};
   let final self::Class1? #t271 = n1 in #t271.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t272 = #t271{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t273 = n1{self::Class1} in #t272.{self::Class1::[]}(#t273).{core::Object::==}(null) ?{self::Class1} #t272.{self::Class1::[]=}(#t273, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t274 = n1 in #t274.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t275 = #t274{self::Class1}.{self::Class1::nonNullable1} in let final self::Class1 #t276 = n1{self::Class1} in let final self::Class1? #t277 = #t275.{self::Class1::[]}(#t276) in #t277.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t278 = n1{self::Class1} in let final void #t279 = #t275.{self::Class1::[]=}(#t276, #t278) in #t278 : #t277{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
index 7dffc16..5a4a4e5 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t353 = n1 in #t353.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t353).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t353, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t354 = n1 in #t354.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t355 = self::Extension1|get#nullable1(#t354) in #t355.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t356 = n1{self::Class1} in let final void #t357 = self::Extension1|set#nullable1(#t354, #t356) in #t356 : #t355{self::Class1};
-  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361{self::Class1}) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361{self::Class1}, #t363) in #t363 : #t362{self::Class1};
+  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361, #t363) in #t363 : #t362{self::Class1};
   let final self::Class1? #t365 = n1 in #t365.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t366 = self::Extension1|get#nonNullable1(#t365{self::Class1}) in let final self::Class1 #t367 = n1{self::Class1} in self::Extension1|[](#t366, #t367).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t366, #t367, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t368 = n1 in #t368.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t369 = self::Extension1|get#nonNullable1(#t368{self::Class1}) in let final self::Class1 #t370 = n1{self::Class1} in let final self::Class1? #t371 = self::Extension1|[](#t369, #t370) in #t371.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t372 = n1{self::Class1} in let final void #t373 = self::Extension1|[]=(#t369, #t370, #t372) in #t372 : #t371{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
index 7dffc16..5a4a4e5 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.strong.transformed.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t353 = n1 in #t353.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t353).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t353, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t354 = n1 in #t354.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t355 = self::Extension1|get#nullable1(#t354) in #t355.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t356 = n1{self::Class1} in let final void #t357 = self::Extension1|set#nullable1(#t354, #t356) in #t356 : #t355{self::Class1};
-  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361{self::Class1}) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361{self::Class1}, #t363) in #t363 : #t362{self::Class1};
+  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361, #t363) in #t363 : #t362{self::Class1};
   let final self::Class1? #t365 = n1 in #t365.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t366 = self::Extension1|get#nonNullable1(#t365{self::Class1}) in let final self::Class1 #t367 = n1{self::Class1} in self::Extension1|[](#t366, #t367).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t366, #t367, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t368 = n1 in #t368.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t369 = self::Extension1|get#nonNullable1(#t368{self::Class1}) in let final self::Class1 #t370 = n1{self::Class1} in let final self::Class1? #t371 = self::Extension1|[](#t369, #t370) in #t371.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t372 = n1{self::Class1} in let final void #t373 = self::Extension1|[]=(#t369, #t370, #t372) in #t372 : #t371{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
index 7dffc16..5a4a4e5 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t353 = n1 in #t353.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t353).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t353, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t354 = n1 in #t354.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t355 = self::Extension1|get#nullable1(#t354) in #t355.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t356 = n1{self::Class1} in let final void #t357 = self::Extension1|set#nullable1(#t354, #t356) in #t356 : #t355{self::Class1};
-  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361{self::Class1}) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361{self::Class1}, #t363) in #t363 : #t362{self::Class1};
+  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361, #t363) in #t363 : #t362{self::Class1};
   let final self::Class1? #t365 = n1 in #t365.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t366 = self::Extension1|get#nonNullable1(#t365{self::Class1}) in let final self::Class1 #t367 = n1{self::Class1} in self::Extension1|[](#t366, #t367).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t366, #t367, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t368 = n1 in #t368.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t369 = self::Extension1|get#nonNullable1(#t368{self::Class1}) in let final self::Class1 #t370 = n1{self::Class1} in let final self::Class1? #t371 = self::Extension1|[](#t369, #t370) in #t371.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t372 = n1{self::Class1} in let final void #t373 = self::Extension1|[]=(#t369, #t370, #t372) in #t372 : #t371{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
index 7dffc16..5a4a4e5 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_explicit_extension.dart.weak.transformed.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t353 = n1 in #t353.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t353).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t353, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t354 = n1 in #t354.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t355 = self::Extension1|get#nullable1(#t354) in #t355.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t356 = n1{self::Class1} in let final void #t357 = self::Extension1|set#nullable1(#t354, #t356) in #t356 : #t355{self::Class1};
-  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361{self::Class1}) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361{self::Class1}, #t363) in #t363 : #t362{self::Class1};
+  let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in self::Extension1|get#nullable1(#t359).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t359, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t360 = n1 in #t360.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t361 = self::Extension1|get#nonNullable1(#t360{self::Class1}) in let final self::Class1? #t362 = self::Extension1|get#nullable1(#t361) in #t362.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t363 = n1{self::Class1} in let final void #t364 = self::Extension1|set#nullable1(#t361, #t363) in #t363 : #t362{self::Class1};
   let final self::Class1? #t365 = n1 in #t365.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t366 = self::Extension1|get#nonNullable1(#t365{self::Class1}) in let final self::Class1 #t367 = n1{self::Class1} in self::Extension1|[](#t366, #t367).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t366, #t367, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t368 = n1 in #t368.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t369 = self::Extension1|get#nonNullable1(#t368{self::Class1}) in let final self::Class1 #t370 = n1{self::Class1} in let final self::Class1? #t371 = self::Extension1|[](#t369, #t370) in #t371.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t372 = n1{self::Class1} in let final void #t373 = self::Extension1|[]=(#t369, #t370, #t372) in #t372 : #t371{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
index f93ce59..45fd2888 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t351 = n1 in #t351.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t351).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t351, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t352 = n1 in #t352.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t353 = self::Extension1|get#nullable1(#t352) in #t353.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t354 = n1{self::Class1} in let final void #t355 = self::Extension1|set#nullable1(#t352, #t354) in #t354 : #t353{self::Class1};
-  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359{self::Class1}) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359{self::Class1}, #t361) in #t361 : #t360{self::Class1};
+  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359, #t361) in #t361 : #t360{self::Class1};
   let final self::Class1? #t363 = n1 in #t363.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t364 = self::Extension1|get#nonNullable1(#t363{self::Class1}) in let final self::Class1 #t365 = n1{self::Class1} in self::Extension1|[](#t364, #t365).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t364, #t365, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t366 = n1 in #t366.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t367 = self::Extension1|get#nonNullable1(#t366{self::Class1}) in let final self::Class1 #t368 = n1{self::Class1} in let final self::Class1? #t369 = self::Extension1|[](#t367, #t368) in #t369.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t370 = n1{self::Class1} in let final void #t371 = self::Extension1|[]=(#t367, #t368, #t370) in #t370 : #t369{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
index f93ce59..45fd2888 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.strong.transformed.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t351 = n1 in #t351.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t351).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t351, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t352 = n1 in #t352.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t353 = self::Extension1|get#nullable1(#t352) in #t353.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t354 = n1{self::Class1} in let final void #t355 = self::Extension1|set#nullable1(#t352, #t354) in #t354 : #t353{self::Class1};
-  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359{self::Class1}) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359{self::Class1}, #t361) in #t361 : #t360{self::Class1};
+  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359, #t361) in #t361 : #t360{self::Class1};
   let final self::Class1? #t363 = n1 in #t363.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t364 = self::Extension1|get#nonNullable1(#t363{self::Class1}) in let final self::Class1 #t365 = n1{self::Class1} in self::Extension1|[](#t364, #t365).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t364, #t365, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t366 = n1 in #t366.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t367 = self::Extension1|get#nonNullable1(#t366{self::Class1}) in let final self::Class1 #t368 = n1{self::Class1} in let final self::Class1? #t369 = self::Extension1|[](#t367, #t368) in #t369.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t370 = n1{self::Class1} in let final void #t371 = self::Extension1|[]=(#t367, #t368, #t370) in #t370 : #t369{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
index f93ce59..45fd2888 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t351 = n1 in #t351.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t351).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t351, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t352 = n1 in #t352.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t353 = self::Extension1|get#nullable1(#t352) in #t353.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t354 = n1{self::Class1} in let final void #t355 = self::Extension1|set#nullable1(#t352, #t354) in #t354 : #t353{self::Class1};
-  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359{self::Class1}) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359{self::Class1}, #t361) in #t361 : #t360{self::Class1};
+  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359, #t361) in #t361 : #t360{self::Class1};
   let final self::Class1? #t363 = n1 in #t363.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t364 = self::Extension1|get#nonNullable1(#t363{self::Class1}) in let final self::Class1 #t365 = n1{self::Class1} in self::Extension1|[](#t364, #t365).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t364, #t365, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t366 = n1 in #t366.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t367 = self::Extension1|get#nonNullable1(#t366{self::Class1}) in let final self::Class1 #t368 = n1{self::Class1} in let final self::Class1? #t369 = self::Extension1|[](#t367, #t368) in #t369.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t370 = n1{self::Class1} in let final void #t371 = self::Extension1|[]=(#t367, #t368, #t370) in #t370 : #t369{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
index f93ce59..45fd2888 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_extension.dart.weak.transformed.expect
@@ -282,8 +282,8 @@
   self::Class1? nullable1 = n1;
   let final self::Class1? #t351 = n1 in #t351.{core::Object::==}(null) ?{self::Class1?} null : self::Extension1|get#nullable1(#t351).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t351, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t352 = n1 in #t352.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t353 = self::Extension1|get#nullable1(#t352) in #t353.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t354 = n1{self::Class1} in let final void #t355 = self::Extension1|set#nullable1(#t352, #t354) in #t354 : #t353{self::Class1};
-  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357{self::Class1}).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357{self::Class1}, n1{self::Class1}) : null;
-  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1? #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359{self::Class1}) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359{self::Class1}, #t361) in #t361 : #t360{self::Class1};
+  let final self::Class1? #t356 = n1 in #t356.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t357 = self::Extension1|get#nonNullable1(#t356{self::Class1}) in self::Extension1|get#nullable1(#t357).{core::Object::==}(null) ?{self::Class1} self::Extension1|set#nullable1(#t357, n1{self::Class1}) : null;
+  n1 = let final self::Class1? #t358 = n1 in #t358.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t359 = self::Extension1|get#nonNullable1(#t358{self::Class1}) in let final self::Class1? #t360 = self::Extension1|get#nullable1(#t359) in #t360.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t361 = n1{self::Class1} in let final void #t362 = self::Extension1|set#nullable1(#t359, #t361) in #t361 : #t360{self::Class1};
   let final self::Class1? #t363 = n1 in #t363.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t364 = self::Extension1|get#nonNullable1(#t363{self::Class1}) in let final self::Class1 #t365 = n1{self::Class1} in self::Extension1|[](#t364, #t365).{core::Object::==}(null) ?{self::Class1} self::Extension1|[]=(#t364, #t365, n1{self::Class1}) : null;
   n1 = let final self::Class1? #t366 = n1 in #t366.{core::Object::==}(null) ?{self::Class1?} null : let final self::Class1 #t367 = self::Extension1|get#nonNullable1(#t366{self::Class1}) in let final self::Class1 #t368 = n1{self::Class1} in let final self::Class1? #t369 = self::Extension1|[](#t367, #t368) in #t369.{core::Object::==}(null) ?{self::Class1} let final self::Class1 #t370 = n1{self::Class1} in let final void #t371 = self::Extension1|[]=(#t367, #t368, #t370) in #t370 : #t369{self::Class1};
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
index ce82366..70f3567 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart
@@ -26,8 +26,6 @@
   c1?[0] = 1 + c1[0];
   c1?[0] += 1;
   c1?[0] += 1 + c1[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c1?[0];
   c1?[0]++;
   c1?[0] ??= 1;
@@ -39,8 +37,6 @@
   c2?[0] = 1 + c2[0];
   c2?[0] += 1;
   c2?[0] += 1 + c2[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c2?[0];
   c2?[0]++;
   c2?[0] ??= 1;
@@ -51,8 +47,6 @@
   Extension(c2)?[0] = 1 + Extension(c2)[0];
   Extension(c2)?[0] += 1;
   Extension(c2)?[0] += 1 + Extension(c2)[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++Extension(c2)?[0];
   Extension(c2)?[0]++;
   Extension(c2)?[0] ??= 1;
@@ -63,8 +57,6 @@
   c1?.field?[0] = 1 + c1[0];
   c1?.field?[0] += 1;
   c1?.field?[0] += 1 + c1[0];
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
   ++c1?.field?[0];
   c1?.field?[0]++;
   c1?.field?[0] ??= 1;
@@ -72,13 +64,11 @@
 
   Extension(c1?.field)?[0];
   Extension(c1?.field)?[0] = 1;
-  Extension(c1?.field)?[0] = 1 + Extension(c2)?[0]!;
+  Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
   Extension(c1?.field)?[0] += 1;
-  Extension(c1?.field)?[0] += 1 + Extension(c2)?[0]!;
-  // TODO(johnniwinther): ++ should probably not be null-shorted, awaiting spec
-  //  update.
+  Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
   ++Extension(c1?.field)?[0];
   Extension(c1?.field)?[0]++;
   Extension(c1?.field)?[0] ??= 1;
-  Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+  Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
index e1edbab..e391c8f 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!) as{ForNonNullableByDefault} core::int)) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
index e1edbab..9838019 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.strong.transformed.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,75 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
-  let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
-  let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
-  let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
-  let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}(let core::int? #t84 = let final self::Class2? #t85 = c2 in #t85.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t85{self::Class2}, 0)! in #t84.==(null) ?{core::int} #t84 as{ForNonNullableByDefault} core::int : #t84{core::int}));
+  let final self::Class1? #t86 = c1 in #t86.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t87 = #t86{self::Class1}.{self::Class1::field} in #t87.{core::Object::==}(null) ?{core::int?} null : let final core::int #t88 = 0 in self::Extension|[]=(#t87{self::Class2}, #t88, self::Extension|[](#t87{self::Class2}, #t88).{core::num::+}(1));
+  let final self::Class1? #t89 = c1 in #t89.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t90 = #t89{self::Class1}.{self::Class1::field} in #t90.{core::Object::==}(null) ?{core::int?} null : let final core::int #t91 = 0 in self::Extension|[]=(#t90{self::Class2}, #t91, self::Extension|[](#t90{self::Class2}, #t91).{core::num::+}(1.{core::num::+}(let core::int? #t92 = let final self::Class2? #t93 = c2 in #t93.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t93{self::Class2}, 0)! in #t92.==(null) ?{core::int} #t92 as{ForNonNullableByDefault} core::int : #t92{core::int})));
+  let final self::Class1? #t94 = c1 in #t94.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t95 = #t94{self::Class1}.{self::Class1::field} in #t95.{core::Object::==}(null) ?{core::int?} null : let final core::int #t96 = 0 in let final core::int #t97 = self::Extension|[](#t95{self::Class2}, #t96).{core::num::+}(1) in let final void #t98 = self::Extension|[]=(#t95{self::Class2}, #t96, #t97) in #t97;
+  let final self::Class1? #t99 = c1 in #t99.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t100 = #t99{self::Class1}.{self::Class1::field} in #t100.{core::Object::==}(null) ?{core::int?} null : let final core::int #t101 = 0 in self::Extension|[]=(#t100{self::Class2}, #t101, self::Extension|[](#t100{self::Class2}, #t101).{core::num::+}(1));
+  let final self::Class1? #t102 = c1 in #t102.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t103 = #t102{self::Class1}.{self::Class1::field} in #t103.{core::Object::==}(null) ?{core::int?} null : let final core::int #t104 = 0 in self::Extension|[](#t103{self::Class2}, #t104).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t103{self::Class2}, #t104, 1) : null;
+  let final self::Class1? #t105 = c1 in #t105.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t106 = #t105{self::Class1}.{self::Class1::field} in #t106.{core::Object::==}(null) ?{core::int?} null : let final core::int #t107 = 0 in self::Extension|[](#t106{self::Class2}, #t107).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t106{self::Class2}, #t107, 1.{core::num::+}(let core::int? #t108 = let final self::Class2? #t109 = c2 in #t109.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t109{self::Class2}, 1)! in #t108.==(null) ?{core::int} #t108 as{ForNonNullableByDefault} core::int : #t108{core::int})) : null;
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:27:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:27:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:28:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:28:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:29:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:29:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:30:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:30:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:31:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:31:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:32:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:32:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:38:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:38:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:39:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:39:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:40:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:40:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:41:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:41:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:42:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:42:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:43:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:43:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:48:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:48:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:49:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:49:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:50:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:50:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:51:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:51:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:52:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:52:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:53:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:53:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:58:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:58:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:59:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:59:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:60:16 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:60:16 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:61:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:61:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:62:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:62:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:63:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:63:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:68:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:68:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:69:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:69:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:70:27 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:70:27 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:71:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:71:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:72:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:72:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:73:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:73:25 -> IntConstant(0)
+Extra constant evaluation: evaluated: 723, effectively constant: 60
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
index e1edbab..e391c8f 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,11 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!) as{ForNonNullableByDefault} core::int)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!) as{ForNonNullableByDefault} core::int)) : null;
 }
diff --git a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
index e1edbab..7e7ea06 100644
--- a/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/null_shorting_index.dart.weak.transformed.expect
@@ -2,46 +2,58 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:33:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:31:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:34:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:32:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?[0] ??= 1 + c1[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:46:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:42:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1;
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:47:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:43:6: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c2?[0] ??= 1 + c2[1];
 //      ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:58:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:52:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1;
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:59:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:53:17: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c2)?[0] ??= 1 + Extension(c2)[1];
 //                 ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:70:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:62:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1;
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:71:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:63:13: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   c1?.field?[0] ??= 1 + c1[1];
 //             ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:82:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:67:49: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] = 1 + (Extension(c2)?[0]! as int);
+//                                                 ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:69:50: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] += 1 + (Extension(c2)?[0]! as int);
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:72:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
 //   Extension(c1?.field)?[0] ??= 1;
 //                        ^
 //
-// pkg/front_end/testcases/nnbd/null_shorting_index.dart:83:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
-//   Extension(c1?.field)?[0] ??= 1 + Extension(c2)?[1]!;
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:24: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
 //                        ^
 //
+// pkg/front_end/testcases/nnbd/null_shorting_index.dart:73:51: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+//   Extension(c1?.field)?[0] ??= 1 + (Extension(c2)?[1]! as int);
+//                                                   ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -111,11 +123,75 @@
   let final self::Class1? #t75 = c1 in #t75.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t76 = #t75{self::Class1}.{self::Class1::field} in #t76.{core::Object::==}(null) ?{core::int?} null : let final core::int #t77 = 0 in self::Extension|[](#t76{self::Class2}, #t77).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t76{self::Class2}, #t77, 1.{core::num::+}(c1{self::Class1}.{self::Class1::[]}(1))) : null;
   let final self::Class1? #t78 = c1 in #t78.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t79 = #t78{self::Class1}.{self::Class1::field} in #t79.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t79{self::Class2}, 0);
   let final self::Class1? #t80 = c1 in #t80.{core::Object::==}(null) ?{void} null : let final self::Class2? #t81 = #t80{self::Class1}.{self::Class1::field} in #t81.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t81{self::Class2}, 0, 1);
-  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}((let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0))!));
+  let final self::Class1? #t82 = c1 in #t82.{core::Object::==}(null) ?{void} null : let final self::Class2? #t83 = #t82{self::Class1}.{self::Class1::field} in #t83.{core::Object::==}(null) ?{void} null : self::Extension|[]=(#t83{self::Class2}, 0, 1.{core::num::+}(let final self::Class2? #t84 = c2 in #t84.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t84{self::Class2}, 0)!));
   let final self::Class1? #t85 = c1 in #t85.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t86 = #t85{self::Class1}.{self::Class1::field} in #t86.{core::Object::==}(null) ?{core::int?} null : let final core::int #t87 = 0 in self::Extension|[]=(#t86{self::Class2}, #t87, self::Extension|[](#t86{self::Class2}, #t87).{core::num::+}(1));
-  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}((let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0))!)));
+  let final self::Class1? #t88 = c1 in #t88.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t89 = #t88{self::Class1}.{self::Class1::field} in #t89.{core::Object::==}(null) ?{core::int?} null : let final core::int #t90 = 0 in self::Extension|[]=(#t89{self::Class2}, #t90, self::Extension|[](#t89{self::Class2}, #t90).{core::num::+}(1.{core::num::+}(let final self::Class2? #t91 = c2 in #t91.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t91{self::Class2}, 0)!)));
   let final self::Class1? #t92 = c1 in #t92.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t93 = #t92{self::Class1}.{self::Class1::field} in #t93.{core::Object::==}(null) ?{core::int?} null : let final core::int #t94 = 0 in let final core::int #t95 = self::Extension|[](#t93{self::Class2}, #t94).{core::num::+}(1) in let final void #t96 = self::Extension|[]=(#t93{self::Class2}, #t94, #t95) in #t95;
   let final self::Class1? #t97 = c1 in #t97.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t98 = #t97{self::Class1}.{self::Class1::field} in #t98.{core::Object::==}(null) ?{core::int?} null : let final core::int #t99 = 0 in self::Extension|[]=(#t98{self::Class2}, #t99, self::Extension|[](#t98{self::Class2}, #t99).{core::num::+}(1));
   let final self::Class1? #t100 = c1 in #t100.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t101 = #t100{self::Class1}.{self::Class1::field} in #t101.{core::Object::==}(null) ?{core::int?} null : let final core::int #t102 = 0 in self::Extension|[](#t101{self::Class2}, #t102).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t101{self::Class2}, #t102, 1) : null;
-  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}((let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1))!)) : null;
+  let final self::Class1? #t103 = c1 in #t103.{core::Object::==}(null) ?{core::int?} null : let final self::Class2? #t104 = #t103{self::Class1}.{self::Class1::field} in #t104.{core::Object::==}(null) ?{core::int?} null : let final core::int #t105 = 0 in self::Extension|[](#t104{self::Class2}, #t105).{core::num::==}(null) ?{core::int} self::Extension|[]=(#t104{self::Class2}, #t105, 1.{core::num::+}(let final self::Class2? #t106 = c2 in #t106.{core::Object::==}(null) ?{core::int?} null : self::Extension|[](#t106{self::Class2}, 1)!)) : null;
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:27:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:27:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:28:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:28:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:29:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:29:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:30:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:30:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:31:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:31:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:32:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:32:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:38:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:38:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:39:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:39:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:40:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:40:9 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:41:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:41:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:42:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:42:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:43:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:43:7 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:48:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:48:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:49:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:49:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:50:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:50:20 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:51:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:51:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:52:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:52:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:53:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:53:18 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:58:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:58:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:59:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:59:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:60:16 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:60:16 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:61:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:61:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:62:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:62:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:63:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:63:14 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:68:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:68:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:69:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:69:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:70:27 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:70:27 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:71:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:71:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:72:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:72:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:73:25 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///null_shorting_index.dart:73:25 -> IntConstant(0)
+Extra constant evaluation: evaluated: 702, effectively constant: 60
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
index 701d5d6..49de6f1 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.strong.transformed.expect
@@ -22,3 +22,7 @@
 constants  {
   #C1 = null
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///nullable_param.dart:19:23 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 20, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
index 701d5d6..49de6f1 100644
--- a/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_param.dart.weak.transformed.expect
@@ -22,3 +22,7 @@
 constants  {
   #C1 = null
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///nullable_param.dart:19:23 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 20, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart b/pkg/front_end/testcases/nnbd/nullable_setter.dart
index 8e9d230..f644300 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart
@@ -19,7 +19,7 @@
 }
 
 main() {
-  C? c = new C();
+  C? c = new C() as C?;
   expect("", c?.m);
   c.setter = "42";
   expect("42", c?.m);
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.strong.expect
@@ -21,7 +21,7 @@
   let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
 }
 static method main() → dynamic {
-  self::C? c = new self::C::•();
+  self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
   self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
   self::_extension#0|set#setter(c, "42");
   self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
index d367854..ac016f2 100644
--- a/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/nullable_setter.dart.weak.expect
@@ -21,7 +21,7 @@
   let final self::C? #t2 = #this in #t2.{core::Object::==}(null) ?{core::String?} null : #t2{self::C}.{self::C::m} = "${index}${value}";
 }
 static method main() → dynamic {
-  self::C? c = new self::C::•();
+  self::C? c = new self::C::•() as{ForNonNullableByDefault} self::C?;
   self::expect("", let final self::C? #t3 = c in #t3.{core::Object::==}(null) ?{core::String?} null : #t3{self::C}.{self::C::m});
   self::_extension#0|set#setter(c, "42");
   self::expect("42", let final self::C? #t4 = c in #t4.{core::Object::==}(null) ?{core::String?} null : #t4{self::C}.{self::C::m});
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart b/pkg/front_end/testcases/nnbd/override_inference.dart
new file mode 100644
index 0000000..c62bd15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+abstract class A<AT> {
+  String method1a(Object x);
+  Object method1b(String x);
+  void method1c(int x);
+  String method1d();
+  void method2a(Object? x);
+  void method2b(dynamic x);
+  void method3a<AT3a>(AT3a x);
+  void method3b<AT3b>(AT3b x);
+  void method4a<AT4a>(AT4a x, AT y);
+  void method4b<AT4b>(AT4b x, AT y);
+  void method5a(int x, num y);
+  void method5b(int x, num y);
+  void method6a({int x, num y});
+  void method6b({num y, int x});
+  Object? method7a(Object? o, {Object? named}) {}
+
+  Object get getter1a;
+  String get getter1b;
+  String get getter1c;
+  set getter1d(String x);
+  int get getter1e;
+  set getter1e(int x);
+
+  void set setter1a(Object x);
+  void set setter1b(String x);
+  void set setter1c(String x);
+  String get setter1d;
+  int get setter1e;
+  set setter1e(int x);
+
+  int? get field1a;
+  num? get field1b;
+  int? get field1c;
+
+  void set field2a(int? value);
+  void set field2b(num? value);
+  void set field2c(int? value);
+
+  int? get field3a;
+  num? get field3b;
+  int? get field3c;
+
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+
+  num? get field4a;
+  num? get field4b;
+  void set field4b(Object? value);
+}
+
+abstract class B<BT> {
+  Object method1a(String x);
+  String method1b(Object x);
+  void method1c(String x);
+  int method1d();
+  void method2a(dynamic x);
+  void method2b(Object? x);
+  void method3a<BT3a>(BT3a x);
+  void method3b<BT3b>(BT3b x);
+  void method4a<BT4a>(BT4a x, BT y);
+  void method4b<BT4b>(BT4b x, BT y);
+  void method5a(num x, int y);
+  void method5b(num x, int y);
+  void method6a({Object x, num y});
+  void method6b({int x, Object y});
+  FutureOr method7a(FutureOr o, {FutureOr named});
+
+  String get getter1a;
+  Object get getter1b;
+  int get getter1c;
+  set getter1d(Object x);
+  num get getter1e;
+  set getter1e(Object x);
+
+  void set setter1a(String x);
+  void set setter1b(Object x);
+  void set setter1c(int x);
+  Object get setter1d;
+  num get setter1e;
+  set setter1e(Object x);
+
+  num? get field1a;
+  int? get field1b;
+  double? get field1c;
+
+  void set field2a(num? value);
+  void set field2b(int? value);
+  void set field2c(double? value);
+
+  num? get field3a;
+  int? get field3b;
+  double? get field3c;
+
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+
+  void set field4a(num? value);
+  num? get field4b;
+  void set field4b(Object? value);
+}
+
+abstract class C implements A<int>, B<num> {
+  method1a(x);
+  method1b(x);
+  void method1c(x); // error
+  method1d(); // error
+  void method2a(x);
+  void method2b(x);
+  void method3a<CT3a>(x);
+  void method3b<CT3b>(x, [y]);
+  void method4a<CT4a>(x, y);
+  void method4b<CT4b>(x, y, [z]);
+  void method5a(x, y); // error
+  void method5b(num x, num y, [z]); // error
+  void method6a({x, y});
+  void method6b({x, y, z});
+  method7a(o, {named});
+
+  get getter1a;
+  get getter1b;
+  get getter1c; // error
+  get getter1d;
+  get getter1e;
+
+  void set setter1a(x);
+  void set setter1b(x);
+  void set setter1c(x); // error
+  void set setter1d(x);
+  void set setter1e(x);
+
+  final field1a = null;
+  final field1b = null;
+  final field1c = null; // error
+
+  final field2a = null;
+  final field2b = null;
+  final field2c = null; // error
+
+  final field3a = null;
+  final field3b = null;
+  final field3c = null; // error
+
+  var field4a = null;
+  var field4b = null; // error
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect
new file mode 100644
index 0000000..5e9a2cc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.outline.expect
@@ -0,0 +1,291 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:114:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method1c(x); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:10:8: Context: This is one of the overridden members.
+//   void method1c(int x);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:62:8: Context: This is one of the overridden members.
+//   void method1c(String x);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:115:3: Error: Can't infer a return type for 'method1d' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   method1d(); // error
+//   ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:11:10: Context: This is one of the overridden members.
+//   String method1d();
+//          ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:63:7: Context: This is one of the overridden members.
+//   int method1d();
+//       ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                    ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:123:32: Error: Can't infer a type for 'z' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5b(num x, num y, [z]); // error
+//                                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:19:8: Context: This is one of the overridden members.
+//   void method5b(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:71:8: Context: This is one of the overridden members.
+//   void method5b(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:130:7: Error: Can't infer a return type for 'getter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   get getter1c; // error
+//       ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:26:14: Context: This is one of the overridden members.
+//   String get getter1c;
+//              ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:78:11: Context: This is one of the overridden members.
+//   int get getter1c;
+//           ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:142:9: Error: Can't infer a type for 'field1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field1c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:40:12: Context: This is one of the overridden members.
+//   int? get field1c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:92:15: Context: This is one of the overridden members.
+//   double? get field1c;
+//               ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:146:9: Error: Can't infer a type for 'field2c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field2c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:150:9: Error: Can't infer a type for 'field3c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field3c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:48:12: Context: This is one of the overridden members.
+//   int? get field3c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:100:15: Context: This is one of the overridden members.
+//   double? get field3c;
+//               ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:52:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:104:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:153:7: Error: Can't infer a type for 'field4b' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   var field4b = null; // error
+//       ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:55:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:107:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:56:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:108:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:136:12: Error: Can't infer a return type for 'setter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void set setter1c(x); // error
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:33:12: Context: This is one of the overridden members.
+//   void set setter1c(String x);
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:85:12: Context: This is one of the overridden members.
+//   void set setter1c(int x);
+//            ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:111:16: Error: Class 'C' inherits multiple members named 'field2c' with incompatible signatures.
+// Try adding a declaration of 'field2c' to 'C'.
+// abstract class C implements A<int>, B<num> {
+//                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+abstract class A<AT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::AT%>
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::String x) → core::Object;
+  abstract method method1c(core::int x) → void;
+  abstract method method1d() → core::String;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(dynamic x) → void;
+  abstract method method3a<AT3a extends core::Object? = dynamic>(self::A::method3a::AT3a% x) → void;
+  abstract method method3b<AT3b extends core::Object? = dynamic>(self::A::method3b::AT3b% x) → void;
+  abstract method method4a<AT4a extends core::Object? = dynamic>(self::A::method4a::AT4a% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method4b<AT4b extends core::Object? = dynamic>(self::A::method4b::AT4b% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method5a(core::int x, core::num y) → void;
+  abstract method method5b(core::int x, core::num y) → void;
+  abstract method method6a({core::int x, core::num y}) → void;
+  abstract method method6b({core::num y, core::int x}) → void;
+  method method7a(core::Object? o, {core::Object? named}) → core::Object?
+    ;
+  abstract get getter1a() → core::Object;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → core::String;
+  abstract set getter1d(core::String x) → void;
+  abstract get getter1e() → core::int;
+  abstract set getter1e(core::int x) → void;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::String x) → void;
+  abstract set setter1c(core::String x) → void;
+  abstract get setter1d() → core::String;
+  abstract get setter1e() → core::int;
+  abstract set setter1e(core::int x) → void;
+  abstract get field1a() → core::int?;
+  abstract get field1b() → core::num?;
+  abstract get field1c() → core::int?;
+  abstract set field2a(core::int? value) → void;
+  abstract set field2b(core::num? value) → void;
+  abstract set field2c(core::int? value) → void;
+  abstract get field3a() → core::int?;
+  abstract get field3b() → core::num?;
+  abstract get field3c() → core::int?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract get field4a() → core::num?;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class B<BT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::BT%>
+    ;
+  abstract method method1a(core::String x) → core::Object;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(core::String x) → void;
+  abstract method method1d() → core::int;
+  abstract method method2a(dynamic x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<BT3a extends core::Object? = dynamic>(self::B::method3a::BT3a% x) → void;
+  abstract method method3b<BT3b extends core::Object? = dynamic>(self::B::method3b::BT3b% x) → void;
+  abstract method method4a<BT4a extends core::Object? = dynamic>(self::B::method4a::BT4a% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method4b<BT4b extends core::Object? = dynamic>(self::B::method4b::BT4b% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method5a(core::num x, core::int y) → void;
+  abstract method method5b(core::num x, core::int y) → void;
+  abstract method method6a({core::Object x, core::num y}) → void;
+  abstract method method6b({core::int x, core::Object y}) → void;
+  abstract method method7a(FutureOr<dynamic>o, {FutureOr<dynamic>named}) → FutureOr<dynamic>;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::Object;
+  abstract get getter1c() → core::int;
+  abstract set getter1d(core::Object x) → void;
+  abstract get getter1e() → core::num;
+  abstract set getter1e(core::Object x) → void;
+  abstract set setter1a(core::String x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(core::int x) → void;
+  abstract get setter1d() → core::Object;
+  abstract get setter1e() → core::num;
+  abstract set setter1e(core::Object x) → void;
+  abstract get field1a() → core::num?;
+  abstract get field1b() → core::int?;
+  abstract get field1c() → core::double?;
+  abstract set field2a(core::num? value) → void;
+  abstract set field2b(core::int? value) → void;
+  abstract set field2c(core::double? value) → void;
+  abstract get field3a() → core::num?;
+  abstract get field3b() → core::int?;
+  abstract get field3c() → core::double?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract set field4a(core::num? value) → void;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class C extends core::Object implements self::A<core::int>, self::B<core::num> {
+  final field core::int? field1a;
+  final field core::int? field1b;
+  final field invalid-type field1c;
+  final field core::num? field2a;
+  final field core::num? field2b;
+  final field invalid-type field2c;
+  final field core::int? field3a;
+  final field core::int? field3b;
+  final field invalid-type field3c;
+  field core::num? field4a;
+  field invalid-type field4b;
+  synthetic constructor •() → self::C
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(invalid-type x) → void;
+  abstract method method1d() → invalid-type;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<CT3a extends core::Object? = dynamic>(self::C::method3a::CT3a% x) → void;
+  abstract method method3b<CT3b extends core::Object? = dynamic>(self::C::method3b::CT3b% x, [dynamic y]) → void;
+  abstract method method4a<CT4a extends core::Object? = dynamic>(self::C::method4a::CT4a% x, generic-covariant-impl core::num y) → void;
+  abstract method method4b<CT4b extends core::Object? = dynamic>(self::C::method4b::CT4b% x, generic-covariant-impl core::num y, [dynamic z]) → void;
+  abstract method method5a(invalid-type x, invalid-type y) → void;
+  abstract method method5b(core::num x, core::num y, [invalid-type z]) → void;
+  abstract method method6a({core::Object x, core::num y}) → void;
+  abstract method method6b({core::int x, core::Object y, dynamic z}) → void;
+  abstract method method7a(core::Object? o, {core::Object? named}) → core::Object?;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → invalid-type;
+  abstract get getter1d() → core::Object;
+  abstract get getter1e() → core::int;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(invalid-type x) → void;
+  abstract set setter1d(core::String x) → void;
+  abstract set setter1e(core::Object x) → void;
+  abstract forwarding-stub set getter1d(core::Object x) → void;
+  abstract forwarding-stub set getter1e(core::Object x) → void;
+  abstract forwarding-stub set field2a(core::num? value) → void;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect
new file mode 100644
index 0000000..71e2237
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:114:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method1c(x); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:10:8: Context: This is one of the overridden members.
+//   void method1c(int x);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:62:8: Context: This is one of the overridden members.
+//   void method1c(String x);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:115:3: Error: Can't infer a return type for 'method1d' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   method1d(); // error
+//   ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:11:10: Context: This is one of the overridden members.
+//   String method1d();
+//          ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:63:7: Context: This is one of the overridden members.
+//   int method1d();
+//       ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                    ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:123:32: Error: Can't infer a type for 'z' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5b(num x, num y, [z]); // error
+//                                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:19:8: Context: This is one of the overridden members.
+//   void method5b(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:71:8: Context: This is one of the overridden members.
+//   void method5b(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:130:7: Error: Can't infer a return type for 'getter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   get getter1c; // error
+//       ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:26:14: Context: This is one of the overridden members.
+//   String get getter1c;
+//              ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:78:11: Context: This is one of the overridden members.
+//   int get getter1c;
+//           ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:142:9: Error: Can't infer a type for 'field1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field1c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:40:12: Context: This is one of the overridden members.
+//   int? get field1c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:92:15: Context: This is one of the overridden members.
+//   double? get field1c;
+//               ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:146:9: Error: Can't infer a type for 'field2c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field2c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:150:9: Error: Can't infer a type for 'field3c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field3c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:48:12: Context: This is one of the overridden members.
+//   int? get field3c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:100:15: Context: This is one of the overridden members.
+//   double? get field3c;
+//               ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:52:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:104:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:153:7: Error: Can't infer a type for 'field4b' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   var field4b = null; // error
+//       ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:55:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:107:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:56:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:108:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:136:12: Error: Can't infer a return type for 'setter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void set setter1c(x); // error
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:33:12: Context: This is one of the overridden members.
+//   void set setter1c(String x);
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:85:12: Context: This is one of the overridden members.
+//   void set setter1c(int x);
+//            ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:111:16: Error: Class 'C' inherits multiple members named 'field2c' with incompatible signatures.
+// Try adding a declaration of 'field2c' to 'C'.
+// abstract class C implements A<int>, B<num> {
+//                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+abstract class A<AT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::AT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::String x) → core::Object;
+  abstract method method1c(core::int x) → void;
+  abstract method method1d() → core::String;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(dynamic x) → void;
+  abstract method method3a<AT3a extends core::Object? = dynamic>(self::A::method3a::AT3a% x) → void;
+  abstract method method3b<AT3b extends core::Object? = dynamic>(self::A::method3b::AT3b% x) → void;
+  abstract method method4a<AT4a extends core::Object? = dynamic>(self::A::method4a::AT4a% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method4b<AT4b extends core::Object? = dynamic>(self::A::method4b::AT4b% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method5a(core::int x, core::num y) → void;
+  abstract method method5b(core::int x, core::num y) → void;
+  abstract method method6a({core::int x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::num y = #C1, core::int x = #C1}) → void;
+  method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object? {}
+  abstract get getter1a() → core::Object;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → core::String;
+  abstract set getter1d(core::String x) → void;
+  abstract get getter1e() → core::int;
+  abstract set getter1e(core::int x) → void;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::String x) → void;
+  abstract set setter1c(core::String x) → void;
+  abstract get setter1d() → core::String;
+  abstract get setter1e() → core::int;
+  abstract set setter1e(core::int x) → void;
+  abstract get field1a() → core::int?;
+  abstract get field1b() → core::num?;
+  abstract get field1c() → core::int?;
+  abstract set field2a(core::int? value) → void;
+  abstract set field2b(core::num? value) → void;
+  abstract set field2c(core::int? value) → void;
+  abstract get field3a() → core::int?;
+  abstract get field3b() → core::num?;
+  abstract get field3c() → core::int?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract get field4a() → core::num?;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class B<BT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::BT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::String x) → core::Object;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(core::String x) → void;
+  abstract method method1d() → core::int;
+  abstract method method2a(dynamic x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<BT3a extends core::Object? = dynamic>(self::B::method3a::BT3a% x) → void;
+  abstract method method3b<BT3b extends core::Object? = dynamic>(self::B::method3b::BT3b% x) → void;
+  abstract method method4a<BT4a extends core::Object? = dynamic>(self::B::method4a::BT4a% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method4b<BT4b extends core::Object? = dynamic>(self::B::method4b::BT4b% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method5a(core::num x, core::int y) → void;
+  abstract method method5b(core::num x, core::int y) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1}) → void;
+  abstract method method7a(FutureOr<dynamic>o, {FutureOr<dynamic>named = #C1}) → FutureOr<dynamic>;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::Object;
+  abstract get getter1c() → core::int;
+  abstract set getter1d(core::Object x) → void;
+  abstract get getter1e() → core::num;
+  abstract set getter1e(core::Object x) → void;
+  abstract set setter1a(core::String x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(core::int x) → void;
+  abstract get setter1d() → core::Object;
+  abstract get setter1e() → core::num;
+  abstract set setter1e(core::Object x) → void;
+  abstract get field1a() → core::num?;
+  abstract get field1b() → core::int?;
+  abstract get field1c() → core::double?;
+  abstract set field2a(core::num? value) → void;
+  abstract set field2b(core::int? value) → void;
+  abstract set field2c(core::double? value) → void;
+  abstract get field3a() → core::num?;
+  abstract get field3b() → core::int?;
+  abstract get field3c() → core::double?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract set field4a(core::num? value) → void;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class C extends core::Object implements self::A<core::int>, self::B<core::num> {
+  final field core::int? field1a = null;
+  final field core::int? field1b = null;
+  final field invalid-type field1c = null;
+  final field core::num? field2a = null;
+  final field core::num? field2b = null;
+  final field invalid-type field2c = null;
+  final field core::int? field3a = null;
+  final field core::int? field3b = null;
+  final field invalid-type field3c = null;
+  field core::num? field4a = null;
+  field invalid-type field4b = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(invalid-type x) → void;
+  abstract method method1d() → invalid-type;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<CT3a extends core::Object? = dynamic>(self::C::method3a::CT3a% x) → void;
+  abstract method method3b<CT3b extends core::Object? = dynamic>(self::C::method3b::CT3b% x, [dynamic y = #C1]) → void;
+  abstract method method4a<CT4a extends core::Object? = dynamic>(self::C::method4a::CT4a% x, generic-covariant-impl core::num y) → void;
+  abstract method method4b<CT4b extends core::Object? = dynamic>(self::C::method4b::CT4b% x, generic-covariant-impl core::num y, [dynamic z = #C1]) → void;
+  abstract method method5a(invalid-type x, invalid-type y) → void;
+  abstract method method5b(core::num x, core::num y, [invalid-type z = #C1]) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1, dynamic z = #C1}) → void;
+  abstract method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object?;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → invalid-type;
+  abstract get getter1d() → core::Object;
+  abstract get getter1e() → core::int;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(invalid-type x) → void;
+  abstract set setter1d(core::String x) → void;
+  abstract set setter1e(core::Object x) → void;
+  abstract forwarding-stub set getter1d(core::Object x) → void;
+  abstract forwarding-stub set getter1e(core::Object x) → void;
+  abstract forwarding-stub set field2a(core::num? value) → void;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect
new file mode 100644
index 0000000..71e2237
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.strong.transformed.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:114:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method1c(x); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:10:8: Context: This is one of the overridden members.
+//   void method1c(int x);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:62:8: Context: This is one of the overridden members.
+//   void method1c(String x);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:115:3: Error: Can't infer a return type for 'method1d' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   method1d(); // error
+//   ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:11:10: Context: This is one of the overridden members.
+//   String method1d();
+//          ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:63:7: Context: This is one of the overridden members.
+//   int method1d();
+//       ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                    ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:123:32: Error: Can't infer a type for 'z' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5b(num x, num y, [z]); // error
+//                                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:19:8: Context: This is one of the overridden members.
+//   void method5b(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:71:8: Context: This is one of the overridden members.
+//   void method5b(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:130:7: Error: Can't infer a return type for 'getter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   get getter1c; // error
+//       ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:26:14: Context: This is one of the overridden members.
+//   String get getter1c;
+//              ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:78:11: Context: This is one of the overridden members.
+//   int get getter1c;
+//           ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:142:9: Error: Can't infer a type for 'field1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field1c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:40:12: Context: This is one of the overridden members.
+//   int? get field1c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:92:15: Context: This is one of the overridden members.
+//   double? get field1c;
+//               ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:146:9: Error: Can't infer a type for 'field2c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field2c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:150:9: Error: Can't infer a type for 'field3c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field3c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:48:12: Context: This is one of the overridden members.
+//   int? get field3c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:100:15: Context: This is one of the overridden members.
+//   double? get field3c;
+//               ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:52:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:104:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:153:7: Error: Can't infer a type for 'field4b' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   var field4b = null; // error
+//       ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:55:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:107:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:56:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:108:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:136:12: Error: Can't infer a return type for 'setter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void set setter1c(x); // error
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:33:12: Context: This is one of the overridden members.
+//   void set setter1c(String x);
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:85:12: Context: This is one of the overridden members.
+//   void set setter1c(int x);
+//            ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:111:16: Error: Class 'C' inherits multiple members named 'field2c' with incompatible signatures.
+// Try adding a declaration of 'field2c' to 'C'.
+// abstract class C implements A<int>, B<num> {
+//                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+abstract class A<AT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::AT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::String x) → core::Object;
+  abstract method method1c(core::int x) → void;
+  abstract method method1d() → core::String;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(dynamic x) → void;
+  abstract method method3a<AT3a extends core::Object? = dynamic>(self::A::method3a::AT3a% x) → void;
+  abstract method method3b<AT3b extends core::Object? = dynamic>(self::A::method3b::AT3b% x) → void;
+  abstract method method4a<AT4a extends core::Object? = dynamic>(self::A::method4a::AT4a% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method4b<AT4b extends core::Object? = dynamic>(self::A::method4b::AT4b% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method5a(core::int x, core::num y) → void;
+  abstract method method5b(core::int x, core::num y) → void;
+  abstract method method6a({core::int x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::num y = #C1, core::int x = #C1}) → void;
+  method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object? {}
+  abstract get getter1a() → core::Object;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → core::String;
+  abstract set getter1d(core::String x) → void;
+  abstract get getter1e() → core::int;
+  abstract set getter1e(core::int x) → void;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::String x) → void;
+  abstract set setter1c(core::String x) → void;
+  abstract get setter1d() → core::String;
+  abstract get setter1e() → core::int;
+  abstract set setter1e(core::int x) → void;
+  abstract get field1a() → core::int?;
+  abstract get field1b() → core::num?;
+  abstract get field1c() → core::int?;
+  abstract set field2a(core::int? value) → void;
+  abstract set field2b(core::num? value) → void;
+  abstract set field2c(core::int? value) → void;
+  abstract get field3a() → core::int?;
+  abstract get field3b() → core::num?;
+  abstract get field3c() → core::int?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract get field4a() → core::num?;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class B<BT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::BT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::String x) → core::Object;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(core::String x) → void;
+  abstract method method1d() → core::int;
+  abstract method method2a(dynamic x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<BT3a extends core::Object? = dynamic>(self::B::method3a::BT3a% x) → void;
+  abstract method method3b<BT3b extends core::Object? = dynamic>(self::B::method3b::BT3b% x) → void;
+  abstract method method4a<BT4a extends core::Object? = dynamic>(self::B::method4a::BT4a% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method4b<BT4b extends core::Object? = dynamic>(self::B::method4b::BT4b% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method5a(core::num x, core::int y) → void;
+  abstract method method5b(core::num x, core::int y) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1}) → void;
+  abstract method method7a(FutureOr<dynamic>o, {FutureOr<dynamic>named = #C1}) → FutureOr<dynamic>;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::Object;
+  abstract get getter1c() → core::int;
+  abstract set getter1d(core::Object x) → void;
+  abstract get getter1e() → core::num;
+  abstract set getter1e(core::Object x) → void;
+  abstract set setter1a(core::String x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(core::int x) → void;
+  abstract get setter1d() → core::Object;
+  abstract get setter1e() → core::num;
+  abstract set setter1e(core::Object x) → void;
+  abstract get field1a() → core::num?;
+  abstract get field1b() → core::int?;
+  abstract get field1c() → core::double?;
+  abstract set field2a(core::num? value) → void;
+  abstract set field2b(core::int? value) → void;
+  abstract set field2c(core::double? value) → void;
+  abstract get field3a() → core::num?;
+  abstract get field3b() → core::int?;
+  abstract get field3c() → core::double?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract set field4a(core::num? value) → void;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class C extends core::Object implements self::A<core::int>, self::B<core::num> {
+  final field core::int? field1a = null;
+  final field core::int? field1b = null;
+  final field invalid-type field1c = null;
+  final field core::num? field2a = null;
+  final field core::num? field2b = null;
+  final field invalid-type field2c = null;
+  final field core::int? field3a = null;
+  final field core::int? field3b = null;
+  final field invalid-type field3c = null;
+  field core::num? field4a = null;
+  field invalid-type field4b = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(invalid-type x) → void;
+  abstract method method1d() → invalid-type;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<CT3a extends core::Object? = dynamic>(self::C::method3a::CT3a% x) → void;
+  abstract method method3b<CT3b extends core::Object? = dynamic>(self::C::method3b::CT3b% x, [dynamic y = #C1]) → void;
+  abstract method method4a<CT4a extends core::Object? = dynamic>(self::C::method4a::CT4a% x, generic-covariant-impl core::num y) → void;
+  abstract method method4b<CT4b extends core::Object? = dynamic>(self::C::method4b::CT4b% x, generic-covariant-impl core::num y, [dynamic z = #C1]) → void;
+  abstract method method5a(invalid-type x, invalid-type y) → void;
+  abstract method method5b(core::num x, core::num y, [invalid-type z = #C1]) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1, dynamic z = #C1}) → void;
+  abstract method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object?;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → invalid-type;
+  abstract get getter1d() → core::Object;
+  abstract get getter1e() → core::int;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(invalid-type x) → void;
+  abstract set setter1d(core::String x) → void;
+  abstract set setter1e(core::Object x) → void;
+  abstract forwarding-stub set getter1d(core::Object x) → void;
+  abstract forwarding-stub set getter1e(core::Object x) → void;
+  abstract forwarding-stub set field2a(core::num? value) → void;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline.expect
new file mode 100644
index 0000000..2a10caa
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline.expect
@@ -0,0 +1,132 @@
+import 'dart:async';
+
+abstract class A<AT> {
+  String method1a(Object x);
+  Object method1b(String x);
+  void method1c(int x);
+  String method1d();
+  void method2a(Object? x);
+  void method2b(dynamic x);
+  void method3a<AT3a>(AT3a x);
+  void method3b<AT3b>(AT3b x);
+  void method4a<AT4a>(AT4a x, AT y);
+  void method4b<AT4b>(AT4b x, AT y);
+  void method5a(int x, num y);
+  void method5b(int x, num y);
+  void method6a({int x, num y});
+  void method6b({num y, int x});
+  Object? method7a(Object? o, {Object? named}) {}
+  Object get getter1a;
+  String get getter1b;
+  String get getter1c;
+  set getter1d(String x);
+  int get getter1e;
+  set getter1e(int x);
+  void set setter1a(Object x);
+  void set setter1b(String x);
+  void set setter1c(String x);
+  String get setter1d;
+  int get setter1e;
+  set setter1e(int x);
+  int? get field1a;
+  num? get field1b;
+  int? get field1c;
+  void set field2a(int? value);
+  void set field2b(num? value);
+  void set field2c(int? value);
+  int? get field3a;
+  num? get field3b;
+  int? get field3c;
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+  num? get field4a;
+  num? get field4b;
+  void set field4b(Object? value);
+}
+
+abstract class B<BT> {
+  Object method1a(String x);
+  String method1b(Object x);
+  void method1c(String x);
+  int method1d();
+  void method2a(dynamic x);
+  void method2b(Object? x);
+  void method3a<BT3a>(BT3a x);
+  void method3b<BT3b>(BT3b x);
+  void method4a<BT4a>(BT4a x, BT y);
+  void method4b<BT4b>(BT4b x, BT y);
+  void method5a(num x, int y);
+  void method5b(num x, int y);
+  void method6a({Object x, num y});
+  void method6b({int x, Object y});
+  FutureOr method7a(FutureOr o, {FutureOr named});
+  String get getter1a;
+  Object get getter1b;
+  int get getter1c;
+  set getter1d(Object x);
+  num get getter1e;
+  set getter1e(Object x);
+  void set setter1a(String x);
+  void set setter1b(Object x);
+  void set setter1c(int x);
+  Object get setter1d;
+  num get setter1e;
+  set setter1e(Object x);
+  num? get field1a;
+  int? get field1b;
+  double? get field1c;
+  void set field2a(num? value);
+  void set field2b(int? value);
+  void set field2c(double? value);
+  num? get field3a;
+  int? get field3b;
+  double? get field3c;
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+  void set field4a(num? value);
+  num? get field4b;
+  void set field4b(Object? value);
+}
+
+abstract class C implements A<int>, B<num> {
+  method1a(x);
+  method1b(x);
+  void method1c(x);
+  method1d();
+  void method2a(x);
+  void method2b(x);
+  void method3a<CT3a>(x);
+  void method3b<CT3b>(x, [y]);
+  void method4a<CT4a>(x, y);
+  void method4b<CT4b>(x, y, [z]);
+  void method5a(x, y);
+  void method5b(num x, num y, [z]);
+  void method6a({x, y});
+  void method6b({x, y, z});
+  method7a(o, {named});
+  get getter1a;
+  get getter1b;
+  get getter1c;
+  get getter1d;
+  get getter1e;
+  void set setter1a(x);
+  void set setter1b(x);
+  void set setter1c(x);
+  void set setter1d(x);
+  void set setter1e(x);
+  final field1a = null;
+  final field1b = null;
+  final field1c = null;
+  final field2a = null;
+  final field2b = null;
+  final field2c = null;
+  final field3a = null;
+  final field3b = null;
+  final field3c = null;
+  var field4a = null;
+  var field4b = null;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..ef0f7cf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.textual_outline_modelled.expect
@@ -0,0 +1,132 @@
+import 'dart:async';
+
+abstract class A<AT> {
+  Object? method7a(Object? o, {Object? named}) {}
+  Object get getter1a;
+  Object method1b(String x);
+  String get getter1b;
+  String get getter1c;
+  String get setter1d;
+  String method1a(Object x);
+  String method1d();
+  int? get field1a;
+  int? get field1c;
+  int? get field3a;
+  int? get field3c;
+  int get getter1e;
+  int get setter1e;
+  num? get field1b;
+  num? get field3b;
+  num? get field4a;
+  num? get field4b;
+  set getter1d(String x);
+  set getter1e(int x);
+  set setter1e(int x);
+  void method1c(int x);
+  void method2a(Object? x);
+  void method2b(dynamic x);
+  void method3a<AT3a>(AT3a x);
+  void method3b<AT3b>(AT3b x);
+  void method4a<AT4a>(AT4a x, AT y);
+  void method4b<AT4b>(AT4b x, AT y);
+  void method5a(int x, num y);
+  void method5b(int x, num y);
+  void method6a({int x, num y});
+  void method6b({num y, int x});
+  void set field2a(int? value);
+  void set field2b(num? value);
+  void set field2c(int? value);
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+  void set field4b(Object? value);
+  void set setter1a(Object x);
+  void set setter1b(String x);
+  void set setter1c(String x);
+}
+
+abstract class B<BT> {
+  FutureOr method7a(FutureOr o, {FutureOr named});
+  Object get getter1b;
+  Object get setter1d;
+  Object method1a(String x);
+  String get getter1a;
+  String method1b(Object x);
+  double? get field1c;
+  double? get field3c;
+  int? get field1b;
+  int? get field3b;
+  int get getter1c;
+  int method1d();
+  num? get field1a;
+  num? get field3a;
+  num? get field4b;
+  num get getter1e;
+  num get setter1e;
+  set getter1d(Object x);
+  set getter1e(Object x);
+  set setter1e(Object x);
+  void method1c(String x);
+  void method2a(dynamic x);
+  void method2b(Object? x);
+  void method3a<BT3a>(BT3a x);
+  void method3b<BT3b>(BT3b x);
+  void method4a<BT4a>(BT4a x, BT y);
+  void method4b<BT4b>(BT4b x, BT y);
+  void method5a(num x, int y);
+  void method5b(num x, int y);
+  void method6a({Object x, num y});
+  void method6b({int x, Object y});
+  void set field2a(num? value);
+  void set field2b(int? value);
+  void set field2c(double? value);
+  void set field3a(Object? value);
+  void set field3b(Object? value);
+  void set field3c(Object? value);
+  void set field4a(num? value);
+  void set field4b(Object? value);
+  void set setter1a(String x);
+  void set setter1b(Object x);
+  void set setter1c(int x);
+}
+
+abstract class C implements A<int>, B<num> {
+  final field1a = null;
+  final field1b = null;
+  final field1c = null;
+  final field2a = null;
+  final field2b = null;
+  final field2c = null;
+  final field3a = null;
+  final field3b = null;
+  final field3c = null;
+  get getter1a;
+  get getter1b;
+  get getter1c;
+  get getter1d;
+  get getter1e;
+  method1a(x);
+  method1b(x);
+  method1d();
+  method7a(o, {named});
+  var field4a = null;
+  var field4b = null;
+  void method1c(x);
+  void method2a(x);
+  void method2b(x);
+  void method3a<CT3a>(x);
+  void method3b<CT3b>(x, [y]);
+  void method4a<CT4a>(x, y);
+  void method4b<CT4b>(x, y, [z]);
+  void method5a(x, y);
+  void method5b(num x, num y, [z]);
+  void method6a({x, y});
+  void method6b({x, y, z});
+  void set setter1a(x);
+  void set setter1b(x);
+  void set setter1c(x);
+  void set setter1d(x);
+  void set setter1e(x);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect
new file mode 100644
index 0000000..71e2237
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:114:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method1c(x); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:10:8: Context: This is one of the overridden members.
+//   void method1c(int x);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:62:8: Context: This is one of the overridden members.
+//   void method1c(String x);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:115:3: Error: Can't infer a return type for 'method1d' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   method1d(); // error
+//   ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:11:10: Context: This is one of the overridden members.
+//   String method1d();
+//          ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:63:7: Context: This is one of the overridden members.
+//   int method1d();
+//       ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                    ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:123:32: Error: Can't infer a type for 'z' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5b(num x, num y, [z]); // error
+//                                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:19:8: Context: This is one of the overridden members.
+//   void method5b(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:71:8: Context: This is one of the overridden members.
+//   void method5b(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:130:7: Error: Can't infer a return type for 'getter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   get getter1c; // error
+//       ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:26:14: Context: This is one of the overridden members.
+//   String get getter1c;
+//              ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:78:11: Context: This is one of the overridden members.
+//   int get getter1c;
+//           ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:142:9: Error: Can't infer a type for 'field1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field1c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:40:12: Context: This is one of the overridden members.
+//   int? get field1c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:92:15: Context: This is one of the overridden members.
+//   double? get field1c;
+//               ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:146:9: Error: Can't infer a type for 'field2c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field2c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:150:9: Error: Can't infer a type for 'field3c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field3c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:48:12: Context: This is one of the overridden members.
+//   int? get field3c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:100:15: Context: This is one of the overridden members.
+//   double? get field3c;
+//               ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:52:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:104:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:153:7: Error: Can't infer a type for 'field4b' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   var field4b = null; // error
+//       ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:55:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:107:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:56:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:108:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:136:12: Error: Can't infer a return type for 'setter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void set setter1c(x); // error
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:33:12: Context: This is one of the overridden members.
+//   void set setter1c(String x);
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:85:12: Context: This is one of the overridden members.
+//   void set setter1c(int x);
+//            ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:111:16: Error: Class 'C' inherits multiple members named 'field2c' with incompatible signatures.
+// Try adding a declaration of 'field2c' to 'C'.
+// abstract class C implements A<int>, B<num> {
+//                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+abstract class A<AT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::AT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::String x) → core::Object;
+  abstract method method1c(core::int x) → void;
+  abstract method method1d() → core::String;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(dynamic x) → void;
+  abstract method method3a<AT3a extends core::Object? = dynamic>(self::A::method3a::AT3a% x) → void;
+  abstract method method3b<AT3b extends core::Object? = dynamic>(self::A::method3b::AT3b% x) → void;
+  abstract method method4a<AT4a extends core::Object? = dynamic>(self::A::method4a::AT4a% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method4b<AT4b extends core::Object? = dynamic>(self::A::method4b::AT4b% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method5a(core::int x, core::num y) → void;
+  abstract method method5b(core::int x, core::num y) → void;
+  abstract method method6a({core::int x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::num y = #C1, core::int x = #C1}) → void;
+  method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object? {}
+  abstract get getter1a() → core::Object;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → core::String;
+  abstract set getter1d(core::String x) → void;
+  abstract get getter1e() → core::int;
+  abstract set getter1e(core::int x) → void;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::String x) → void;
+  abstract set setter1c(core::String x) → void;
+  abstract get setter1d() → core::String;
+  abstract get setter1e() → core::int;
+  abstract set setter1e(core::int x) → void;
+  abstract get field1a() → core::int?;
+  abstract get field1b() → core::num?;
+  abstract get field1c() → core::int?;
+  abstract set field2a(core::int? value) → void;
+  abstract set field2b(core::num? value) → void;
+  abstract set field2c(core::int? value) → void;
+  abstract get field3a() → core::int?;
+  abstract get field3b() → core::num?;
+  abstract get field3c() → core::int?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract get field4a() → core::num?;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class B<BT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::BT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::String x) → core::Object;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(core::String x) → void;
+  abstract method method1d() → core::int;
+  abstract method method2a(dynamic x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<BT3a extends core::Object? = dynamic>(self::B::method3a::BT3a% x) → void;
+  abstract method method3b<BT3b extends core::Object? = dynamic>(self::B::method3b::BT3b% x) → void;
+  abstract method method4a<BT4a extends core::Object? = dynamic>(self::B::method4a::BT4a% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method4b<BT4b extends core::Object? = dynamic>(self::B::method4b::BT4b% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method5a(core::num x, core::int y) → void;
+  abstract method method5b(core::num x, core::int y) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1}) → void;
+  abstract method method7a(FutureOr<dynamic>o, {FutureOr<dynamic>named = #C1}) → FutureOr<dynamic>;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::Object;
+  abstract get getter1c() → core::int;
+  abstract set getter1d(core::Object x) → void;
+  abstract get getter1e() → core::num;
+  abstract set getter1e(core::Object x) → void;
+  abstract set setter1a(core::String x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(core::int x) → void;
+  abstract get setter1d() → core::Object;
+  abstract get setter1e() → core::num;
+  abstract set setter1e(core::Object x) → void;
+  abstract get field1a() → core::num?;
+  abstract get field1b() → core::int?;
+  abstract get field1c() → core::double?;
+  abstract set field2a(core::num? value) → void;
+  abstract set field2b(core::int? value) → void;
+  abstract set field2c(core::double? value) → void;
+  abstract get field3a() → core::num?;
+  abstract get field3b() → core::int?;
+  abstract get field3c() → core::double?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract set field4a(core::num? value) → void;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class C extends core::Object implements self::A<core::int>, self::B<core::num> {
+  final field core::int? field1a = null;
+  final field core::int? field1b = null;
+  final field invalid-type field1c = null;
+  final field core::num? field2a = null;
+  final field core::num? field2b = null;
+  final field invalid-type field2c = null;
+  final field core::int? field3a = null;
+  final field core::int? field3b = null;
+  final field invalid-type field3c = null;
+  field core::num? field4a = null;
+  field invalid-type field4b = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(invalid-type x) → void;
+  abstract method method1d() → invalid-type;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<CT3a extends core::Object? = dynamic>(self::C::method3a::CT3a% x) → void;
+  abstract method method3b<CT3b extends core::Object? = dynamic>(self::C::method3b::CT3b% x, [dynamic y = #C1]) → void;
+  abstract method method4a<CT4a extends core::Object? = dynamic>(self::C::method4a::CT4a% x, generic-covariant-impl core::num y) → void;
+  abstract method method4b<CT4b extends core::Object? = dynamic>(self::C::method4b::CT4b% x, generic-covariant-impl core::num y, [dynamic z = #C1]) → void;
+  abstract method method5a(invalid-type x, invalid-type y) → void;
+  abstract method method5b(core::num x, core::num y, [invalid-type z = #C1]) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1, dynamic z = #C1}) → void;
+  abstract method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object?;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → invalid-type;
+  abstract get getter1d() → core::Object;
+  abstract get getter1e() → core::int;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(invalid-type x) → void;
+  abstract set setter1d(core::String x) → void;
+  abstract set setter1e(core::Object x) → void;
+  abstract forwarding-stub set getter1d(core::Object x) → void;
+  abstract forwarding-stub set getter1e(core::Object x) → void;
+  abstract forwarding-stub set field2a(core::num? value) → void;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect
new file mode 100644
index 0000000..71e2237
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/override_inference.dart.weak.transformed.expect
@@ -0,0 +1,296 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:114:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method1c(x); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:10:8: Context: This is one of the overridden members.
+//   void method1c(int x);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:62:8: Context: This is one of the overridden members.
+//   void method1c(String x);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:115:3: Error: Can't infer a return type for 'method1d' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   method1d(); // error
+//   ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:11:10: Context: This is one of the overridden members.
+//   String method1d();
+//          ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:63:7: Context: This is one of the overridden members.
+//   int method1d();
+//       ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:17: Error: Can't infer a type for 'x' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                 ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:122:20: Error: Can't infer a type for 'y' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5a(x, y); // error
+//                    ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:18:8: Context: This is one of the overridden members.
+//   void method5a(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:70:8: Context: This is one of the overridden members.
+//   void method5a(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:123:32: Error: Can't infer a type for 'z' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void method5b(num x, num y, [z]); // error
+//                                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:19:8: Context: This is one of the overridden members.
+//   void method5b(int x, num y);
+//        ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:71:8: Context: This is one of the overridden members.
+//   void method5b(num x, int y);
+//        ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:130:7: Error: Can't infer a return type for 'getter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   get getter1c; // error
+//       ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:26:14: Context: This is one of the overridden members.
+//   String get getter1c;
+//              ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:78:11: Context: This is one of the overridden members.
+//   int get getter1c;
+//           ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:142:9: Error: Can't infer a type for 'field1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field1c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:40:12: Context: This is one of the overridden members.
+//   int? get field1c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:92:15: Context: This is one of the overridden members.
+//   double? get field1c;
+//               ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:146:9: Error: Can't infer a type for 'field2c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field2c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:150:9: Error: Can't infer a type for 'field3c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   final field3c = null; // error
+//         ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:48:12: Context: This is one of the overridden members.
+//   int? get field3c;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:100:15: Context: This is one of the overridden members.
+//   double? get field3c;
+//               ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:52:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:104:12: Context: This is one of the overridden members.
+//   void set field3c(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:153:7: Error: Can't infer a type for 'field4b' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   var field4b = null; // error
+//       ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:55:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:107:12: Context: This is one of the overridden members.
+//   num? get field4b;
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:56:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:108:12: Context: This is one of the overridden members.
+//   void set field4b(Object? value);
+//            ^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:136:12: Error: Can't infer a return type for 'setter1c' as the overridden members don't have a combined signature.
+// Try adding an explicit type.
+//   void set setter1c(x); // error
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:33:12: Context: This is one of the overridden members.
+//   void set setter1c(String x);
+//            ^^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:85:12: Context: This is one of the overridden members.
+//   void set setter1c(int x);
+//            ^^^^^^^^
+//
+// pkg/front_end/testcases/nnbd/override_inference.dart:111:16: Error: Class 'C' inherits multiple members named 'field2c' with incompatible signatures.
+// Try adding a declaration of 'field2c' to 'C'.
+// abstract class C implements A<int>, B<num> {
+//                ^
+// pkg/front_end/testcases/nnbd/override_inference.dart:44:12: Context: This is one of the overridden members.
+//   void set field2c(int? value);
+//            ^^^^^^^
+// pkg/front_end/testcases/nnbd/override_inference.dart:96:12: Context: This is one of the overridden members.
+//   void set field2c(double? value);
+//            ^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+abstract class A<AT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::A<self::A::AT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::String x) → core::Object;
+  abstract method method1c(core::int x) → void;
+  abstract method method1d() → core::String;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(dynamic x) → void;
+  abstract method method3a<AT3a extends core::Object? = dynamic>(self::A::method3a::AT3a% x) → void;
+  abstract method method3b<AT3b extends core::Object? = dynamic>(self::A::method3b::AT3b% x) → void;
+  abstract method method4a<AT4a extends core::Object? = dynamic>(self::A::method4a::AT4a% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method4b<AT4b extends core::Object? = dynamic>(self::A::method4b::AT4b% x, generic-covariant-impl self::A::AT% y) → void;
+  abstract method method5a(core::int x, core::num y) → void;
+  abstract method method5b(core::int x, core::num y) → void;
+  abstract method method6a({core::int x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::num y = #C1, core::int x = #C1}) → void;
+  method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object? {}
+  abstract get getter1a() → core::Object;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → core::String;
+  abstract set getter1d(core::String x) → void;
+  abstract get getter1e() → core::int;
+  abstract set getter1e(core::int x) → void;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::String x) → void;
+  abstract set setter1c(core::String x) → void;
+  abstract get setter1d() → core::String;
+  abstract get setter1e() → core::int;
+  abstract set setter1e(core::int x) → void;
+  abstract get field1a() → core::int?;
+  abstract get field1b() → core::num?;
+  abstract get field1c() → core::int?;
+  abstract set field2a(core::int? value) → void;
+  abstract set field2b(core::num? value) → void;
+  abstract set field2c(core::int? value) → void;
+  abstract get field3a() → core::int?;
+  abstract get field3b() → core::num?;
+  abstract get field3c() → core::int?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract get field4a() → core::num?;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class B<BT extends core::Object? = dynamic> extends core::Object {
+  synthetic constructor •() → self::B<self::B::BT%>
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::String x) → core::Object;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(core::String x) → void;
+  abstract method method1d() → core::int;
+  abstract method method2a(dynamic x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<BT3a extends core::Object? = dynamic>(self::B::method3a::BT3a% x) → void;
+  abstract method method3b<BT3b extends core::Object? = dynamic>(self::B::method3b::BT3b% x) → void;
+  abstract method method4a<BT4a extends core::Object? = dynamic>(self::B::method4a::BT4a% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method4b<BT4b extends core::Object? = dynamic>(self::B::method4b::BT4b% x, generic-covariant-impl self::B::BT% y) → void;
+  abstract method method5a(core::num x, core::int y) → void;
+  abstract method method5b(core::num x, core::int y) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1}) → void;
+  abstract method method7a(FutureOr<dynamic>o, {FutureOr<dynamic>named = #C1}) → FutureOr<dynamic>;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::Object;
+  abstract get getter1c() → core::int;
+  abstract set getter1d(core::Object x) → void;
+  abstract get getter1e() → core::num;
+  abstract set getter1e(core::Object x) → void;
+  abstract set setter1a(core::String x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(core::int x) → void;
+  abstract get setter1d() → core::Object;
+  abstract get setter1e() → core::num;
+  abstract set setter1e(core::Object x) → void;
+  abstract get field1a() → core::num?;
+  abstract get field1b() → core::int?;
+  abstract get field1c() → core::double?;
+  abstract set field2a(core::num? value) → void;
+  abstract set field2b(core::int? value) → void;
+  abstract set field2c(core::double? value) → void;
+  abstract get field3a() → core::num?;
+  abstract get field3b() → core::int?;
+  abstract get field3c() → core::double?;
+  abstract set field3a(core::Object? value) → void;
+  abstract set field3b(core::Object? value) → void;
+  abstract set field3c(core::Object? value) → void;
+  abstract set field4a(core::num? value) → void;
+  abstract get field4b() → core::num?;
+  abstract set field4b(core::Object? value) → void;
+}
+abstract class C extends core::Object implements self::A<core::int>, self::B<core::num> {
+  final field core::int? field1a = null;
+  final field core::int? field1b = null;
+  final field invalid-type field1c = null;
+  final field core::num? field2a = null;
+  final field core::num? field2b = null;
+  final field invalid-type field2c = null;
+  final field core::int? field3a = null;
+  final field core::int? field3b = null;
+  final field invalid-type field3c = null;
+  field core::num? field4a = null;
+  field invalid-type field4b = null;
+  synthetic constructor •() → self::C
+    : super core::Object::•()
+    ;
+  abstract method method1a(core::Object x) → core::String;
+  abstract method method1b(core::Object x) → core::String;
+  abstract method method1c(invalid-type x) → void;
+  abstract method method1d() → invalid-type;
+  abstract method method2a(core::Object? x) → void;
+  abstract method method2b(core::Object? x) → void;
+  abstract method method3a<CT3a extends core::Object? = dynamic>(self::C::method3a::CT3a% x) → void;
+  abstract method method3b<CT3b extends core::Object? = dynamic>(self::C::method3b::CT3b% x, [dynamic y = #C1]) → void;
+  abstract method method4a<CT4a extends core::Object? = dynamic>(self::C::method4a::CT4a% x, generic-covariant-impl core::num y) → void;
+  abstract method method4b<CT4b extends core::Object? = dynamic>(self::C::method4b::CT4b% x, generic-covariant-impl core::num y, [dynamic z = #C1]) → void;
+  abstract method method5a(invalid-type x, invalid-type y) → void;
+  abstract method method5b(core::num x, core::num y, [invalid-type z = #C1]) → void;
+  abstract method method6a({core::Object x = #C1, core::num y = #C1}) → void;
+  abstract method method6b({core::int x = #C1, core::Object y = #C1, dynamic z = #C1}) → void;
+  abstract method method7a(core::Object? o, {core::Object? named = #C1}) → core::Object?;
+  abstract get getter1a() → core::String;
+  abstract get getter1b() → core::String;
+  abstract get getter1c() → invalid-type;
+  abstract get getter1d() → core::Object;
+  abstract get getter1e() → core::int;
+  abstract set setter1a(core::Object x) → void;
+  abstract set setter1b(core::Object x) → void;
+  abstract set setter1c(invalid-type x) → void;
+  abstract set setter1d(core::String x) → void;
+  abstract set setter1e(core::Object x) → void;
+  abstract forwarding-stub set getter1d(core::Object x) → void;
+  abstract forwarding-stub set getter1e(core::Object x) → void;
+  abstract forwarding-stub set field2a(core::num? value) → void;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/platform_definite_assignment/main.dart.outline.expect b/pkg/front_end/testcases/nnbd/platform_definite_assignment/main.dart.outline.expect
index 1d570f5..f5a5f71 100644
--- a/pkg/front_end/testcases/nnbd/platform_definite_assignment/main.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/platform_definite_assignment/main.dart.outline.expect
@@ -38,3 +38,11 @@
 external static method patchedMethod(core::int a) → void;
 static method /* from org-dartlang-testcase:///patch_lib.dart */ _injectedMethod(core::int i) → core::int
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:9:5 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:9:43 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:15:19 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:28:17 -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 6, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.outline.expect b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.outline.expect
index 461cb26..96c486e9 100644
--- a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.outline.expect
@@ -35,3 +35,9 @@
   constructor constructor1() → self2::Class2
     ;
 }
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.expect b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.expect
index 873a553..8aa11f6 100644
--- a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.expect
@@ -21,7 +21,10 @@
 //   int field;
 //       ^^^^^
 //
-// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/origin_lib.dart:8:3: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+//   Class2.constructor1();
+//   ^
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Context: 'field' is defined here.
 //   int field;
 //       ^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.transformed.expect
index 873a553..8aa11f6 100644
--- a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.strong.transformed.expect
@@ -21,7 +21,10 @@
 //   int field;
 //       ^^^^^
 //
-// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/origin_lib.dart:8:3: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+//   Class2.constructor1();
+//   ^
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Context: 'field' is defined here.
 //   int field;
 //       ^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.expect b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.expect
index 873a553..8aa11f6 100644
--- a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.expect
@@ -21,7 +21,10 @@
 //   int field;
 //       ^^^^^
 //
-// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/origin_lib.dart:8:3: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+//   Class2.constructor1();
+//   ^
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Context: 'field' is defined here.
 //   int field;
 //       ^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.transformed.expect
index 873a553..8aa11f6 100644
--- a/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_nonnullable_fields/main.dart.weak.transformed.expect
@@ -21,7 +21,10 @@
 //   int field;
 //       ^^^^^
 //
-// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/origin_lib.dart:8:3: Error: This constructor should initialize field 'field' because its type 'int' doesn't allow null.
+//   Class2.constructor1();
+//   ^
+// pkg/front_end/testcases/nnbd/platform_nonnullable_fields/patch_lib2.dart:37:7: Context: 'field' is defined here.
 //   int field;
 //       ^^^^^
 //
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
index 85646dd..6a9e27e 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.outline.expect
@@ -34,10 +34,6 @@
 // void method([int i]) {}
 //                  ^
 //
-// pkg/front_end/testcases/nnbd/platform_optional_parameters/origin_lib.dart:13:34: Error: Optional parameter 'i' should have a default value because its type 'int' doesn't allow null.
-// external void patchedMethod([int i]);
-//                                  ^
-//
 import self as self2;
 import "dart:_internal" as _in;
 import "dart:core" as core;
@@ -61,3 +57,10 @@
 external static method patchedMethod([core::int i]) → void;
 static method /* from org-dartlang-testcase:///patch_lib.dart */ _injectedMethod([core::int i]) → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:8:22 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ org-dartlang-testcase:///origin_lib.dart:11:2 -> InstanceConstant(const _Patch{})
+Evaluated: StaticGet @ (unknown position in org-dartlang-testcase:///origin_lib.dart) -> InstanceConstant(const _Patch{})
+Extra constant evaluation: evaluated: 3, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
index 0c2e596..9762f48 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.expect
@@ -36,10 +36,6 @@
 // void method([int i]) {}
 //                  ^
 //
-// pkg/front_end/testcases/nnbd/platform_optional_parameters/origin_lib.dart:13:34: Error: Optional parameter 'i' should have a default value because its type 'int' doesn't allow null.
-// external void patchedMethod([int i]);
-//                                  ^
-//
 import self as test;
 import "dart:_internal" as _in;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
index 0c2e596..9762f48 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.strong.transformed.expect
@@ -36,10 +36,6 @@
 // void method([int i]) {}
 //                  ^
 //
-// pkg/front_end/testcases/nnbd/platform_optional_parameters/origin_lib.dart:13:34: Error: Optional parameter 'i' should have a default value because its type 'int' doesn't allow null.
-// external void patchedMethod([int i]);
-//                                  ^
-//
 import self as test;
 import "dart:_internal" as _in;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
index 0c2e596..9762f48 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.expect
@@ -36,10 +36,6 @@
 // void method([int i]) {}
 //                  ^
 //
-// pkg/front_end/testcases/nnbd/platform_optional_parameters/origin_lib.dart:13:34: Error: Optional parameter 'i' should have a default value because its type 'int' doesn't allow null.
-// external void patchedMethod([int i]);
-//                                  ^
-//
 import self as test;
 import "dart:_internal" as _in;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
index 0c2e596..9762f48 100644
--- a/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/platform_optional_parameters/main.dart.weak.transformed.expect
@@ -36,10 +36,6 @@
 // void method([int i]) {}
 //                  ^
 //
-// pkg/front_end/testcases/nnbd/platform_optional_parameters/origin_lib.dart:13:34: Error: Optional parameter 'i' should have a default value because its type 'int' doesn't allow null.
-// external void patchedMethod([int i]);
-//                                  ^
-//
 import self as test;
 import "dart:_internal" as _in;
 import "dart:core" as core;
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.outline.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.outline.expect
index fa3b2cf..55b2345 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.outline.expect
@@ -45,3 +45,9 @@
   ;
 static method errors() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///potentially_constant_type_as.dart:22:36 -> IntConstant(3)
+Evaluated: Instantiation @ org-dartlang-testcase:///potentially_constant_type_as.dart:11:43 -> PartialInstantiationConstant(idFunction<int>)
+Extra constant evaluation: evaluated: 11, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
index 6ec69f6..f6d9603 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:61:9: Error: Constant evaluation error:
 //   const ClassWithFunction<Object>(objectFunction); // ok in weak mode
@@ -133,7 +134,6 @@
 //   const ClassWithFunction(dynamic value) : field = value as T Function(T);
 //                                                          ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
index 6ec69f6..f6d9603 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.strong.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:61:9: Error: Constant evaluation error:
 //   const ClassWithFunction<Object>(objectFunction); // ok in weak mode
@@ -133,7 +134,6 @@
 //   const ClassWithFunction(dynamic value) : field = value as T Function(T);
 //                                                          ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
index 37e43f1..03c1430 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
 //   const Class<num>(''); // error
@@ -125,7 +126,6 @@
 //   const ClassWithFunction(dynamic value) : field = value as T Function(T);
 //                                                          ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
index 37e43f1..03c1430 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart.weak.transformed.expect
@@ -1,5 +1,6 @@
+library /*isNonNullableByDefault*/;
 //
-// Problems in component:
+// Problems in library:
 //
 // pkg/front_end/testcases/nnbd/potentially_constant_type_as.dart:65:9: Error: Constant evaluation error:
 //   const Class<num>(''); // error
@@ -125,7 +126,6 @@
 //   const ClassWithFunction(dynamic value) : field = value as T Function(T);
 //                                                          ^
 //
-library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.outline.expect b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.outline.expect
index 59b2a45..b2e2658 100644
--- a/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/potentially_constant_type_is.dart.outline.expect
@@ -41,3 +41,9 @@
   ;
 static method main() → void
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///potentially_constant_type_is.dart:22:36 -> IntConstant(3)
+Evaluated: Instantiation @ org-dartlang-testcase:///potentially_constant_type_is.dart:11:43 -> PartialInstantiationConstant(idFunction<int>)
+Extra constant evaluation: evaluated: 11, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.outline.expect b/pkg/front_end/testcases/nnbd/return_null.dart.outline.expect
index 3fc7c86..d70d113 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.outline.expect
@@ -15,7 +15,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
 }
 static method returnImplicit() → core::String
   ;
@@ -49,3 +49,10 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///return_null.dart:43:6 -> ListConstant(const <Enum>[const Enum{Enum.index: 0, Enum._name: "Enum.a"}, const Enum{Enum.index: 1, Enum._name: "Enum.b"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///return_null.dart:43:13 -> InstanceConstant(const Enum{Enum.index: 0, Enum._name: "Enum.a"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///return_null.dart:43:16 -> InstanceConstant(const Enum{Enum.index: 1, Enum._name: "Enum.b"})
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
index 022f00c..99136f1 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.expect
@@ -68,7 +68,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
 }
 static method returnImplicit() → core::String {
   core::print("foo");
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
index 6f1bd4c..3d6ecf6 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.strong.transformed.expect
@@ -68,7 +68,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
 }
 static method returnImplicit() → core::String {
   core::print("foo");
@@ -630,3 +630,18 @@
   #C6 = self::Enum {index:#C4, _name:#C5}
   #C7 = <self::Enum>[#C3, #C6]
 }
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:13:10 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:13:10 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:13:10 -> NullConstant(null)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:19:12 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:19:12 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:19:12 -> NullConstant(null)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:69:12 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:69:12 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:69:12 -> NullConstant(null)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///return_null.dart:75:14 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///return_null.dart:75:14 -> NullConstant(null)
+Extra constant evaluation: evaluated: 428, effectively constant: 12
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
index 4c9329b..75221ed 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.expect
@@ -55,6 +55,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -68,7 +69,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
 }
 static method returnImplicit() → core::String {
   core::print("foo");
@@ -120,16 +121,19 @@
       {
         return e;
       }
+    #L3:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
   }
 }
 static method caseReturn2(self::Enum e) → self::Enum {
   switch(e) {
-    #L3:
+    #L4:
     case #C3:
       {
         return e;
       }
-    #L4:
+    #L5:
     default:
       {}
   }
@@ -179,26 +183,29 @@
   function yieldAsync() → asy::Stream<dynamic> async* {}
   function caseReturn1(self::Enum e) → self::Enum {
     switch(e) {
-      #L5:
+      #L6:
       case #C3:
         {
           return e;
         }
-      #L6:
+      #L7:
       case #C6:
         {
           return e;
         }
+      #L8:
+      default:
+        throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
     }
   }
   function caseReturn2(self::Enum e) → self::Enum {
     switch(e) {
-      #L7:
+      #L9:
       case #C3:
         {
           return e;
         }
-      #L8:
+      #L10:
       default:
         {}
     }
diff --git a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
index b3b3e5b..91bc7b3 100644
--- a/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/return_null.dart.weak.transformed.expect
@@ -55,6 +55,7 @@
 import self as self;
 import "dart:core" as core;
 import "dart:async" as asy;
+import "dart:_internal" as _in;
 
 import "dart:async";
 
@@ -68,7 +69,7 @@
     : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::Enum::_name};
+    return this.{self::Enum::_name};
 }
 static method returnImplicit() → core::String {
   core::print("foo");
@@ -320,16 +321,19 @@
       {
         return e;
       }
+    #L11:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
   }
 }
 static method caseReturn2(self::Enum e) → self::Enum {
   switch(e) {
-    #L11:
+    #L12:
     case #C3:
       {
         return e;
       }
-    #L12:
+    #L13:
     default:
       {}
   }
@@ -372,7 +376,7 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L13:
+        #L14:
         {}
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -396,7 +400,7 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L14:
+        #L15:
         {}
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -420,12 +424,12 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L15:
+        #L16:
         {
           :return_value = let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/nnbd/return_null.dart:83:3: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
   FutureOr<int> returnAsync3() async {} // error
   ^" in null;
-          break #L15;
+          break #L16;
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -449,7 +453,7 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L16:
+        #L17:
         {}
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -473,7 +477,7 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L17:
+        #L18:
         {}
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -497,10 +501,10 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L18:
+        #L19:
         {
           :return_value = null;
-          break #L18;
+          break #L19;
         }
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -524,7 +528,7 @@
     dynamic :await_ctx_var;
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try {
-        #L19:
+        #L20:
         {}
         asy::_completeOnAsyncReturn(:async_completer, :return_value);
         return;
@@ -560,7 +564,7 @@
     function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
       try
         try {
-          #L20:
+          #L21:
           {}
           return;
         }
@@ -579,26 +583,29 @@
   }
   function caseReturn1(self::Enum e) → self::Enum {
     switch(e) {
-      #L21:
+      #L22:
       case #C3:
         {
           return e;
         }
-      #L22:
+      #L23:
       case #C6:
         {
           return e;
         }
+      #L24:
+      default:
+        throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
     }
   }
   function caseReturn2(self::Enum e) → self::Enum {
     switch(e) {
-      #L23:
+      #L25:
       case #C3:
         {
           return e;
         }
-      #L24:
+      #L26:
       default:
         {}
     }
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart b/pkg/front_end/testcases/nnbd/shorting_null_check.dart
new file mode 100644
index 0000000..1b45f04
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int zero;
+  int? zeroOrNull;
+
+  A(this.zero, [this.zeroOrNull]);
+}
+
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+
+  Foo(this.bar);
+
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+}
+
+class Bar {
+  int baz;
+
+  Bar(this.baz);
+
+  int operator [](int index) => index;
+
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+}
+
+Bar? test5(Foo? foo) => foo?.bar!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+
+main() {
+  expect(0, test1(new A(0)));
+  expect(null, test1(null));
+
+  expect(0, test2(new A(0, 0)));
+  expect(null, test2(null));
+  throws(() => test2(new A(0, null)));
+
+  expect(true, test3(new A(0)));
+  expect(null, test3(null));
+
+  expect(true, test4(new A(0, 0)));
+  expect(null, test4(null));
+  throws(() => test4(new A(0, null)));
+
+  expect(new Bar(0), test5(new Foo(new Bar(0))));
+  expect(null, test5(null));
+  throws(() => test5(new Foo(null)));
+
+  expect(0, test6(new Foo(new Bar(0))));
+  expect(null, test6(null));
+  throws(() => test6(new Foo(null)));
+
+  expect(42, test7(new Foo(new Bar(0)), 42));
+  expect(null, test7(null, 42));
+  throws(() => test7(new Foo(null), 42));
+
+  expect(new Bar(42), test8(new Foo(new Bar(0)), 42));
+  expect(null, test8(null, 42));
+  throws(() => test8(new Foo(new Bar(0)), null));
+
+  expect(42, test9(new Foo(new Bar(0)), 42));
+  expect(null, test9(null, 42));
+  throws(() => test9(new Foo(new Bar(0)), null));
+
+  expect(87, test10(new Foo(new Bar(0)), 42, 87));
+  expect(null, test10(null, 42, 87));
+  throws(() => test10(new Foo(new Bar(0)), null, 87));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw 'Missing exception';
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect
new file mode 100644
index 0000000..02e531b
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.outline.expect
@@ -0,0 +1,52 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull]) → self::A
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    ;
+  operator [](core::int? index) → self::Bar?
+    ;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    ;
+  operator [](core::int index) → core::int
+    ;
+  operator ==(core::Object other) → core::bool
+    ;
+}
+static method test1(self::A? a) → core::int?
+  ;
+static method test2(self::A? a) → core::int?
+  ;
+static method test3(self::A? a) → core::bool?
+  ;
+static method test4(self::A? a) → core::bool?
+  ;
+static method test5(self::Foo? foo) → self::Bar?
+  ;
+static method test6(self::Foo? foo) → core::int?
+  ;
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  ;
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  ;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  ;
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → void f) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.strong.transformed.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect
new file mode 100644
index 0000000..13961a5
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline.expect
@@ -0,0 +1,33 @@
+class A {
+  int zero;
+  int? zeroOrNull;
+  A(this.zero, [this.zeroOrNull]);
+}
+
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class Foo {
+  Bar? bar;
+  Foo(this.bar);
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+}
+
+class Bar {
+  int baz;
+  Bar(this.baz);
+  int operator [](int index) => index;
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+}
+
+Bar? test5(Foo? foo) => foo?.bar!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+main() {}
+expect(expected, actual) {}
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..58770bf
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.textual_outline_modelled.expect
@@ -0,0 +1,33 @@
+Bar? test5(Foo? foo) => foo?.bar!;
+Bar? test8(Foo? foo, int? bar) => foo?[bar]!;
+bool? test3(A? a) => a?.zero!.isEven;
+bool? test4(A? a) => a?.zeroOrNull!.isEven;
+
+class A {
+  A(this.zero, [this.zeroOrNull]);
+  int? zeroOrNull;
+  int zero;
+}
+
+class Bar {
+  Bar(this.baz);
+  bool operator ==(Object other) => other is Bar && baz == other.baz;
+  int baz;
+  int operator [](int index) => index;
+}
+
+class Foo {
+  Bar? bar;
+  Bar? operator [](int? index) => index != null ? new Bar(index) : null;
+  Foo(this.bar);
+}
+
+expect(expected, actual) {}
+int? test1(A? a) => a?.zero!;
+int? test2(A? a) => a?.zeroOrNull!;
+int? test6(Foo? foo) => foo?.bar!.baz;
+int? test7(Foo? foo, int baz) => foo?.bar![baz];
+int? test9(Foo? foo, int? bar) => foo?[bar]!.baz;
+main() {}
+test10(Foo? foo, int? bar, int baz) => foo?[bar]![baz];
+throws(void Function() f) {}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect
new file mode 100644
index 0000000..2897025
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/shorting_null_check.dart.weak.transformed.expect
@@ -0,0 +1,107 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:12:24: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// int? test1(A? a) => a?.zero!;
+//                        ^
+//
+// pkg/front_end/testcases/nnbd/shorting_null_check.dart:14:25: Warning: Operand of null-aware operation '!' has type 'int' which excludes null.
+// bool? test3(A? a) => a?.zero!.isEven;
+//                         ^
+//
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int zero;
+  field core::int? zeroOrNull;
+  constructor •(core::int zero, [core::int? zeroOrNull = #C1]) → self::A
+    : self::A::zero = zero, self::A::zeroOrNull = zeroOrNull, super core::Object::•()
+    ;
+}
+class Foo extends core::Object {
+  field self::Bar? bar;
+  constructor •(self::Bar? bar) → self::Foo
+    : self::Foo::bar = bar, super core::Object::•()
+    ;
+  operator [](core::int? index) → self::Bar?
+    return !index.{core::num::==}(null) ?{self::Bar?} new self::Bar::•(index{core::int}) : null;
+}
+class Bar extends core::Object {
+  field core::int baz;
+  constructor •(core::int baz) → self::Bar
+    : self::Bar::baz = baz, super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator ==(core::Object other) → core::bool
+    return other is{ForNonNullableByDefault} self::Bar && this.{self::Bar::baz}.{core::num::==}(other{self::Bar}.{self::Bar::baz});
+}
+static method test1(self::A? a) → core::int?
+  return let final self::A? #t1 = a in #t1.{core::Object::==}(null) ?{core::int?} null : #t1{self::A}.{self::A::zero}!;
+static method test2(self::A? a) → core::int?
+  return let final self::A? #t2 = a in #t2.{core::Object::==}(null) ?{core::int?} null : #t2{self::A}.{self::A::zeroOrNull}!;
+static method test3(self::A? a) → core::bool?
+  return let final self::A? #t3 = a in #t3.{core::Object::==}(null) ?{core::bool?} null : #t3{self::A}.{self::A::zero}!.{core::int::isEven};
+static method test4(self::A? a) → core::bool?
+  return let final self::A? #t4 = a in #t4.{core::Object::==}(null) ?{core::bool?} null : #t4{self::A}.{self::A::zeroOrNull}!.{core::int::isEven};
+static method test5(self::Foo? foo) → self::Bar?
+  return let final self::Foo? #t5 = foo in #t5.{core::Object::==}(null) ?{self::Bar?} null : #t5{self::Foo}.{self::Foo::bar}!;
+static method test6(self::Foo? foo) → core::int?
+  return let final self::Foo? #t6 = foo in #t6.{core::Object::==}(null) ?{core::int?} null : #t6{self::Foo}.{self::Foo::bar}!.{self::Bar::baz};
+static method test7(self::Foo? foo, core::int baz) → core::int?
+  return let final self::Foo? #t7 = foo in #t7.{core::Object::==}(null) ?{core::int?} null : #t7{self::Foo}.{self::Foo::bar}!.{self::Bar::[]}(baz);
+static method test8(self::Foo? foo, core::int? bar) → self::Bar?
+  return let final self::Foo? #t8 = foo in #t8.{core::Object::==}(null) ?{self::Bar?} null : #t8{self::Foo}.{self::Foo::[]}(bar)!;
+static method test9(self::Foo? foo, core::int? bar) → core::int?
+  return let final self::Foo? #t9 = foo in #t9.{core::Object::==}(null) ?{core::int?} null : #t9{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::baz};
+static method test10(self::Foo? foo, core::int? bar, core::int baz) → dynamic
+  return let final self::Foo? #t10 = foo in #t10.{core::Object::==}(null) ?{core::int?} null : #t10{self::Foo}.{self::Foo::[]}(bar)!.{self::Bar::[]}(baz);
+static method main() → dynamic {
+  self::expect(0, self::test1(new self::A::•(0)));
+  self::expect(null, self::test1(null));
+  self::expect(0, self::test2(new self::A::•(0, 0)));
+  self::expect(null, self::test2(null));
+  self::throws(() → core::int? => self::test2(new self::A::•(0, null)));
+  self::expect(true, self::test3(new self::A::•(0)));
+  self::expect(null, self::test3(null));
+  self::expect(true, self::test4(new self::A::•(0, 0)));
+  self::expect(null, self::test4(null));
+  self::throws(() → core::bool? => self::test4(new self::A::•(0, null)));
+  self::expect(new self::Bar::•(0), self::test5(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test5(null));
+  self::throws(() → self::Bar? => self::test5(new self::Foo::•(null)));
+  self::expect(0, self::test6(new self::Foo::•(new self::Bar::•(0))));
+  self::expect(null, self::test6(null));
+  self::throws(() → core::int? => self::test6(new self::Foo::•(null)));
+  self::expect(42, self::test7(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test7(null, 42));
+  self::throws(() → core::int? => self::test7(new self::Foo::•(null), 42));
+  self::expect(new self::Bar::•(42), self::test8(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test8(null, 42));
+  self::throws(() → self::Bar? => self::test8(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(42, self::test9(new self::Foo::•(new self::Bar::•(0)), 42));
+  self::expect(null, self::test9(null, 42));
+  self::throws(() → core::int? => self::test9(new self::Foo::•(new self::Bar::•(0)), null));
+  self::expect(87, self::test10(new self::Foo::•(new self::Bar::•(0)), 42, 87));
+  self::expect(null, self::test10(null, 42, 87));
+  self::throws(() → dynamic => self::test10(new self::Foo::•(new self::Bar::•(0)), null, 87));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Missing exception";
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
index 609cde0..2c4e1da 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.strong.transformed.expect
@@ -111,3 +111,11 @@
     f.call();
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:26:13 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:26:13 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:27:11 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:27:11 -> IntConstant(0)
+Extra constant evaluation: evaluated: 165, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
index 609cde0..2c4e1da 100644
--- a/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/shorting_stop.dart.weak.transformed.expect
@@ -111,3 +111,11 @@
     f.call();
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:26:13 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:26:13 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:27:11 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///shorting_stop.dart:27:11 -> IntConstant(0)
+Extra constant evaluation: evaluated: 165, effectively constant: 4
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
index 3d73f1d..87930a9 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.strong.transformed.expect
@@ -212,3 +212,13 @@
   } =>#t32;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:22:11 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:22:11 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:42:8 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:42:8 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:43:5 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:43:5 -> IntConstant(42)
+Extra constant evaluation: evaluated: 221, effectively constant: 6
diff --git a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
index 3d73f1d..87930a9 100644
--- a/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strictly_non_nullable_warnings.dart.weak.transformed.expect
@@ -212,3 +212,13 @@
   } =>#t32;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:22:11 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:22:11 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:42:8 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:42:8 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:43:5 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///strictly_non_nullable_warnings.dart:43:5 -> IntConstant(42)
+Extra constant evaluation: evaluated: 221, effectively constant: 6
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.outline.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.outline.expect
index acb4c8d..953b07d 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.outline.expect
@@ -13,6 +13,8 @@
 
 library;
 import self as self2;
+import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void
   ;
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.expect
index b5f4dc2..6501ffc 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.expect
@@ -17,6 +17,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.transformed.expect
index b5f4dc2..6501ffc 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.strong.transformed.expect
@@ -17,6 +17,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.expect
index dfa3681..c9d352f 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.expect
@@ -12,6 +12,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.transformed.expect
index dfa3681..c9d352f 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong.dart.weak.transformed.expect
@@ -12,6 +12,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong_lib.dart b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong_lib.dart
index 930d387..ed07dd6 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong_lib.dart
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_dill/strong_lib.dart
@@ -1,5 +1,7 @@
 // @dart = 2.7
 
+int x;
+
 void foo() {
   print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.outline.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.outline.expect
index 7a170f8..f0ae2dc 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.outline.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.outline.expect
@@ -6,7 +6,7 @@
 static method main() → dynamic
   ;
 
-library /*isNonNullableByDefault*/;
+library;
 //
 // Problems in library:
 //
@@ -15,6 +15,8 @@
 // ^^^^^^^^^^^^^^
 //
 import self as self2;
+import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void
   ;
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.expect
index 701927d..fecb1f5 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.expect
@@ -8,7 +8,7 @@
   str::foo();
 }
 
-library /*isNonNullableByDefault*/;
+library;
 //
 // Problems in library:
 //
@@ -19,6 +19,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.transformed.expect
index 701927d..fecb1f5 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.strong.transformed.expect
@@ -8,7 +8,7 @@
   str::foo();
 }
 
-library /*isNonNullableByDefault*/;
+library;
 //
 // Problems in library:
 //
@@ -19,6 +19,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.expect
index dfa3681..c9d352f 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.expect
@@ -12,6 +12,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.transformed.expect
index dfa3681..c9d352f 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong.dart.weak.transformed.expect
@@ -12,6 +12,7 @@
 import self as str;
 import "dart:core" as core;
 
+static field core::int* x;
 static method foo() → void {
   core::print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong_lib.dart b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong_lib.dart
index 930d387..ed07dd6 100644
--- a/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong_lib.dart
+++ b/pkg/front_end/testcases/nnbd/strong_lib_not_ok_from_source/strong_lib.dart
@@ -1,5 +1,7 @@
 // @dart = 2.7
 
+int x;
+
 void foo() {
   print("hello");
 }
diff --git a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib1.dart b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib1.dart
index a08c72e..a3a3556 100644
--- a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib1.dart
+++ b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib1.dart
@@ -1,3 +1,5 @@
 // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
+int x;
diff --git a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib2.dart b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib2.dart
index a08c72e..0ba8a05 100644
--- a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib2.dart
+++ b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_dill/opt_out_package/lib/regular_lib2.dart
@@ -1,3 +1,5 @@
 // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
+int y;
diff --git a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib1.dart b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib1.dart
index a08c72e..a3a3556 100644
--- a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib1.dart
+++ b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib1.dart
@@ -1,3 +1,5 @@
 // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
+int x;
diff --git a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib2.dart b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib2.dart
index a08c72e..0ba8a05 100644
--- a/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib2.dart
+++ b/pkg/front_end/testcases/nnbd/strong_package_not_ok_from_source/opt_out_package/lib/regular_lib2.dart
@@ -1,3 +1,5 @@
 // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+
+int y;
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart
new file mode 100644
index 0000000..0275ec6
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+enum Enum { e1, e2 }
+
+int method1(Enum? e) {
+  switch (e) {
+    case Enum.e1:
+    case Enum.e2:
+      return 0;
+  }
+}
+
+int method2(Enum? e) {
+  switch (e) {
+    case Enum.e1:
+    case Enum.e2:
+      return 0;
+    case null:
+      return 1;
+  }
+}
+
+int method3(Enum? e) {
+  switch (e) {
+    case Enum.e1:
+    case Enum.e2:
+      return 0;
+    default:
+      return 1;
+  }
+}
+
+int method4(Enum? e) {
+  switch (e) {
+    case Enum.e1:
+    case Enum.e2:
+      return 0;
+    case null:
+    default:
+      return 1;
+  }
+}
+
+test() {
+  method1(Enum.e1);
+}
+
+main() {
+  expect(0, method2(Enum.e1));
+  expect(0, method2(Enum.e2));
+  expect(1, method2(null));
+
+  expect(0, method3(Enum.e1));
+  expect(0, method3(Enum.e2));
+  expect(1, method3(null));
+
+  expect(0, method4(Enum.e1));
+  expect(0, method4(Enum.e2));
+  expect(1, method4(null));
+}
+
+expect(expected, actual) {
+  if (expected != actual) {
+    throw 'Expected $expected, actual $actual.';
+  }
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.outline.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.outline.expect
new file mode 100644
index 0000000..0c1c54e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.outline.expect
@@ -0,0 +1,37 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Enum extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<self::Enum> values = const <self::Enum>[self::Enum::e1, self::Enum::e2];
+  static const field self::Enum e1 = const self::Enum::•(0, "Enum.e1");
+  static const field self::Enum e2 = const self::Enum::•(1, "Enum.e2");
+  const constructor •(core::int index, core::String _name) → self::Enum
+    : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{self::Enum::_name};
+}
+static method method1(self::Enum? e) → core::int
+  ;
+static method method2(self::Enum? e) → core::int
+  ;
+static method method3(self::Enum? e) → core::int
+  ;
+static method method4(self::Enum? e) → core::int
+  ;
+static method test() → dynamic
+  ;
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///switch_nullable_enum.dart:5:6 -> ListConstant(const <Enum>[const Enum{Enum.index: 0, Enum._name: "Enum.e1"}, const Enum{Enum.index: 1, Enum._name: "Enum.e2"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///switch_nullable_enum.dart:5:13 -> InstanceConstant(const Enum{Enum.index: 0, Enum._name: "Enum.e1"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///switch_nullable_enum.dart:5:17 -> InstanceConstant(const Enum{Enum.index: 1, Enum._name: "Enum.e2"})
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
new file mode 100644
index 0000000..daebafc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int method1(Enum? e) {
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Enum extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<self::Enum> values = #C7;
+  static const field self::Enum e1 = #C3;
+  static const field self::Enum e2 = #C6;
+  const constructor •(core::int index, core::String _name) → self::Enum
+    : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{self::Enum::_name};
+}
+static method method1(self::Enum? e) → core::int {
+  switch(e) {
+    #L1:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+  }
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+int method1(Enum? e) {
+    ^" in null;
+}
+static method method2(self::Enum? e) → core::int {
+  switch(e) {
+    #L2:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L3:
+    case #C8:
+      {
+        return 1;
+      }
+  }
+}
+static method method3(self::Enum? e) → core::int {
+  switch(e) {
+    #L4:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L5:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method method4(self::Enum? e) → core::int {
+  switch(e) {
+    #L6:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L7:
+    case #C8:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method test() → dynamic {
+  self::method1(#C3);
+}
+static method main() → dynamic {
+  self::expect(0, self::method2(#C3));
+  self::expect(0, self::method2(#C6));
+  self::expect(1, self::method2(null));
+  self::expect(0, self::method3(#C3));
+  self::expect(0, self::method3(#C6));
+  self::expect(1, self::method3(null));
+  self::expect(0, self::method4(#C3));
+  self::expect(0, self::method4(#C6));
+  self::expect(1, self::method4(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}.";
+  }
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "Enum.e1"
+  #C3 = self::Enum {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "Enum.e2"
+  #C6 = self::Enum {index:#C4, _name:#C5}
+  #C7 = <self::Enum>[#C3, #C6]
+  #C8 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
new file mode 100644
index 0000000..daebafc
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.strong.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int method1(Enum? e) {
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Enum extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<self::Enum> values = #C7;
+  static const field self::Enum e1 = #C3;
+  static const field self::Enum e2 = #C6;
+  const constructor •(core::int index, core::String _name) → self::Enum
+    : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{self::Enum::_name};
+}
+static method method1(self::Enum? e) → core::int {
+  switch(e) {
+    #L1:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+  }
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+int method1(Enum? e) {
+    ^" in null;
+}
+static method method2(self::Enum? e) → core::int {
+  switch(e) {
+    #L2:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L3:
+    case #C8:
+      {
+        return 1;
+      }
+  }
+}
+static method method3(self::Enum? e) → core::int {
+  switch(e) {
+    #L4:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L5:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method method4(self::Enum? e) → core::int {
+  switch(e) {
+    #L6:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L7:
+    case #C8:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method test() → dynamic {
+  self::method1(#C3);
+}
+static method main() → dynamic {
+  self::expect(0, self::method2(#C3));
+  self::expect(0, self::method2(#C6));
+  self::expect(1, self::method2(null));
+  self::expect(0, self::method3(#C3));
+  self::expect(0, self::method3(#C6));
+  self::expect(1, self::method3(null));
+  self::expect(0, self::method4(#C3));
+  self::expect(0, self::method4(#C6));
+  self::expect(1, self::method4(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}.";
+  }
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "Enum.e1"
+  #C3 = self::Enum {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "Enum.e2"
+  #C6 = self::Enum {index:#C4, _name:#C5}
+  #C7 = <self::Enum>[#C3, #C6]
+  #C8 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline.expect
new file mode 100644
index 0000000..acc9973
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline.expect
@@ -0,0 +1,8 @@
+enum Enum { e1, e2 }
+int method1(Enum? e) {}
+int method2(Enum? e) {}
+int method3(Enum? e) {}
+int method4(Enum? e) {}
+test() {}
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..a18d6e9
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.textual_outline_modelled.expect
@@ -0,0 +1,8 @@
+enum Enum { e1, e2 }
+expect(expected, actual) {}
+int method1(Enum? e) {}
+int method2(Enum? e) {}
+int method3(Enum? e) {}
+int method4(Enum? e) {}
+main() {}
+test() {}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
new file mode 100644
index 0000000..28d2d15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.expect
@@ -0,0 +1,116 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int method1(Enum? e) {
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Enum extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<self::Enum> values = #C7;
+  static const field self::Enum e1 = #C3;
+  static const field self::Enum e2 = #C6;
+  const constructor •(core::int index, core::String _name) → self::Enum
+    : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{self::Enum::_name};
+}
+static method method1(self::Enum? e) → core::int {
+  switch(e) {
+    #L1:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+  }
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+int method1(Enum? e) {
+    ^" in null;
+}
+static method method2(self::Enum? e) → core::int {
+  switch(e) {
+    #L2:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L3:
+    case #C8:
+      {
+        return 1;
+      }
+    #L4:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method method3(self::Enum? e) → core::int {
+  switch(e) {
+    #L5:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L6:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method method4(self::Enum? e) → core::int {
+  switch(e) {
+    #L7:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L8:
+    case #C8:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method test() → dynamic {
+  self::method1(#C3);
+}
+static method main() → dynamic {
+  self::expect(0, self::method2(#C3));
+  self::expect(0, self::method2(#C6));
+  self::expect(1, self::method2(null));
+  self::expect(0, self::method3(#C3));
+  self::expect(0, self::method3(#C6));
+  self::expect(1, self::method3(null));
+  self::expect(0, self::method4(#C3));
+  self::expect(0, self::method4(#C6));
+  self::expect(1, self::method4(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}.";
+  }
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "Enum.e1"
+  #C3 = self::Enum {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "Enum.e2"
+  #C6 = self::Enum {index:#C4, _name:#C5}
+  #C7 = <self::Enum*>[#C3, #C6]
+  #C8 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
new file mode 100644
index 0000000..28d2d15
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/switch_nullable_enum.dart.weak.transformed.expect
@@ -0,0 +1,116 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+// int method1(Enum? e) {
+//     ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Enum extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<self::Enum> values = #C7;
+  static const field self::Enum e1 = #C3;
+  static const field self::Enum e2 = #C6;
+  const constructor •(core::int index, core::String _name) → self::Enum
+    : self::Enum::index = index, self::Enum::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{self::Enum::_name};
+}
+static method method1(self::Enum? e) → core::int {
+  switch(e) {
+    #L1:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+  }
+  return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd/switch_nullable_enum.dart:7:5: Error: A non-null value must be returned since the return type 'int' doesn't allow null.
+int method1(Enum? e) {
+    ^" in null;
+}
+static method method2(self::Enum? e) → core::int {
+  switch(e) {
+    #L2:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L3:
+    case #C8:
+      {
+        return 1;
+      }
+    #L4:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method method3(self::Enum? e) → core::int {
+  switch(e) {
+    #L5:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L6:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method method4(self::Enum? e) → core::int {
+  switch(e) {
+    #L7:
+    case #C3:
+    case #C6:
+      {
+        return 0;
+      }
+    #L8:
+    case #C8:
+    default:
+      {
+        return 1;
+      }
+  }
+}
+static method test() → dynamic {
+  self::method1(#C3);
+}
+static method main() → dynamic {
+  self::expect(0, self::method2(#C3));
+  self::expect(0, self::method2(#C6));
+  self::expect(1, self::method2(null));
+  self::expect(0, self::method3(#C3));
+  self::expect(0, self::method3(#C6));
+  self::expect(1, self::method3(null));
+  self::expect(0, self::method4(#C3));
+  self::expect(0, self::method4(#C6));
+  self::expect(1, self::method4(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual)) {
+    throw "Expected ${expected}, actual ${actual}.";
+  }
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "Enum.e1"
+  #C3 = self::Enum {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "Enum.e2"
+  #C6 = self::Enum {index:#C4, _name:#C5}
+  #C7 = <self::Enum*>[#C3, #C6]
+  #C8 = null
+}
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.expect
index d0e258c..d5183ef 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
   synthetic constructor •() → self::A
@@ -18,7 +19,7 @@
       #L1:
       case #C1:
         {
-          this.{self::A::neverReturn}();
+          let final Never #t1 = this.{self::A::neverReturn}() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
       #L2:
       default:
@@ -35,7 +36,7 @@
     #L3:
     case #C1:
       {
-        b ?{Never} throw "hest" : throw "fisk";
+        let final Never #t2 = b ?{Never} throw "hest" : throw "fisk" in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
       }
     #L4:
     case #C2:
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.transformed.expect
index d0e258c..d5183ef 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_fall_over.dart.weak.transformed.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 abstract class A extends core::Object {
   synthetic constructor •() → self::A
@@ -18,7 +19,7 @@
       #L1:
       case #C1:
         {
-          this.{self::A::neverReturn}();
+          let final Never #t1 = this.{self::A::neverReturn}() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
         }
       #L2:
       default:
@@ -35,7 +36,7 @@
     #L3:
     case #C1:
       {
-        b ?{Never} throw "hest" : throw "fisk";
+        let final Never #t2 = b ?{Never} throw "hest" : throw "fisk" in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
       }
     #L4:
     case #C2:
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
index bd7eee5..c678c28 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case const D(42): // Error: D has custom operator ==.
-//                ^
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case x: // Error: D has custom operator ==.
-//          ^
-//
 library /*isNonNullableByDefault*/;
 //
 // Problems in library:
@@ -32,6 +19,16 @@
 //   switch (b) {
 //           ^
 //
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case const D(42): // Error: D has custom operator ==.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case x: // Error: D has custom operator ==.
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
index bd7eee5..c678c28 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.strong.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case const D(42): // Error: D has custom operator ==.
-//                ^
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case x: // Error: D has custom operator ==.
-//          ^
-//
 library /*isNonNullableByDefault*/;
 //
 // Problems in library:
@@ -32,6 +19,16 @@
 //   switch (b) {
 //           ^
 //
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case const D(42): // Error: D has custom operator ==.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case x: // Error: D has custom operator ==.
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
index bd7eee5..c678c28 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case const D(42): // Error: D has custom operator ==.
-//                ^
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case x: // Error: D has custom operator ==.
-//          ^
-//
 library /*isNonNullableByDefault*/;
 //
 // Problems in library:
@@ -32,6 +19,16 @@
 //   switch (b) {
 //           ^
 //
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case const D(42): // Error: D has custom operator ==.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case x: // Error: D has custom operator ==.
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
index bd7eee5..c678c28 100644
--- a/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/switch_redesign_types.dart.weak.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case const D(42): // Error: D has custom operator ==.
-//                ^
-//
-// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
-//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
-//     case x: // Error: D has custom operator ==.
-//          ^
-//
 library /*isNonNullableByDefault*/;
 //
 // Problems in library:
@@ -32,6 +19,16 @@
 //   switch (b) {
 //           ^
 //
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:37:16: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case const D(42): // Error: D has custom operator ==.
+//                ^
+//
+// pkg/front_end/testcases/nnbd/switch_redesign_types.dart:39:10: Error: Case expression 'D {}' does not have a primitive operator '=='.
+//  - 'D' is from 'pkg/front_end/testcases/nnbd/switch_redesign_types.dart'.
+//     case x: // Error: D has custom operator ==.
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
index 32d138d..c7475f1 100644
--- a/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/tearoff_from_nullable_receiver.dart.strong.transformed.expect
@@ -91,3 +91,10 @@
                           ^" in t as{TypeError,ForNonNullableByDefault} () →? core::int);
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///tearoff_from_nullable_receiver.dart:14:24 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///tearoff_from_nullable_receiver.dart:14:24 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///tearoff_from_nullable_receiver.dart:14:24 -> NullConstant(null)
+Extra constant evaluation: evaluated: 58, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/type_constraint_solving_closures_in_upper_and_lower_bounds.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/type_constraint_solving_closures_in_upper_and_lower_bounds.dart.strong.transformed.expect
index f25f680..0104bef 100644
--- a/pkg/front_end/testcases/nnbd/type_constraint_solving_closures_in_upper_and_lower_bounds.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/type_constraint_solving_closures_in_upper_and_lower_bounds.dart.strong.transformed.expect
@@ -24,3 +24,10 @@
              ^" in x as{TypeError,ForNonNullableByDefault} core::String;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///type_constraint_solving_closures_in_upper_and_lower_bounds.dart:10:3 -> BoolConstant(true)
+Evaluated: VariableGet @ org-dartlang-testcase:///type_constraint_solving_closures_in_upper_and_lower_bounds.dart:10:15 -> NullConstant(null)
+Evaluated: VariableGet @ org-dartlang-testcase:///type_constraint_solving_closures_in_upper_and_lower_bounds.dart:10:3 -> NullConstant(null)
+Extra constant evaluation: evaluated: 12, effectively constant: 3
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
index 4db6f6e..8762f10 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.expect
@@ -1,17 +1,18 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
   synthetic constructor •() → self::A<self::A::X, self::A::Y%>
     : super core::Object::•()
     ;
   method foo() → self::A::X
-    return self::never();
+    return let final Never #t1 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   method bar() → self::A::X?
     return null;
   method baz() → self::A::Y%
-    return self::never();
+    return let final Never #t2 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
   synthetic constructor •() → self::B<self::B::X, self::B::Y%>
@@ -35,21 +36,21 @@
   return throw "Never";
 static method main() → dynamic {
   function fun1<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → X
-    return self::never();
+    return let final Never #t3 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun2<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → Y%
-    return self::never();
+    return let final Never #t4 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun3<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → X
-    return self::never();
+    return let final Never #t5 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun4<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → Y%
-    return self::never();
+    return let final Never #t6 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun5<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → X%
-    return self::never();
+    return let final Never #t7 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun6<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → Y%
-    return self::never();
+    return let final Never #t8 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun7<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → X%
-    return self::never();
+    return let final Never #t9 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun8<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Y%
-    return self::never();
+    return let final Never #t10 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun9<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Z%
-    return self::never();
+    return let final Never #t11 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
diff --git a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
index 4db6f6e..8762f10 100644
--- a/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/type_parameter_types.dart.weak.transformed.expect
@@ -1,17 +1,18 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "dart:_internal" as _in;
 
 class A<X extends core::Object = core::Object, Y extends core::Object? = core::Object?> extends core::Object {
   synthetic constructor •() → self::A<self::A::X, self::A::Y%>
     : super core::Object::•()
     ;
   method foo() → self::A::X
-    return self::never();
+    return let final Never #t1 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   method bar() → self::A::X?
     return null;
   method baz() → self::A::Y%
-    return self::never();
+    return let final Never #t2 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
 class B<X extends core::List<self::B::Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?> extends core::Object {
   synthetic constructor •() → self::B<self::B::X, self::B::Y%>
@@ -35,21 +36,21 @@
   return throw "Never";
 static method main() → dynamic {
   function fun1<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → X
-    return self::never();
+    return let final Never #t3 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun2<X extends core::Object = core::Object, Y extends core::Object? = core::Object?>() → Y%
-    return self::never();
+    return let final Never #t4 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun3<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → X
-    return self::never();
+    return let final Never #t5 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun4<X extends core::List<Y%> = core::List<core::Object?>, Y extends core::Object? = core::Object?>() → Y%
-    return self::never();
+    return let final Never #t6 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun5<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → X%
-    return self::never();
+    return let final Never #t7 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun6<X extends core::List<Y%>? = core::List<dynamic>?, Y extends core::List<X%>? = core::List<dynamic>?>() → Y%
-    return self::never();
+    return let final Never #t8 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun7<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → X%
-    return self::never();
+    return let final Never #t9 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun8<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Y%
-    return self::never();
+    return let final Never #t10 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   function fun9<X extends Y% = dynamic, Y extends Z% = dynamic, Z extends core::Object? = dynamic>() → Z%
-    return self::never();
+    return let final Never #t11 = self::never() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
 }
diff --git a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.expect b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.expect
index 78aceb3..15fcd35 100644
--- a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.expect
@@ -11,7 +11,7 @@
   method qux() → dynamic {
     final self::Foo::T? v = this.{self::Foo::bar} as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo::T?;
     if(v is{ForNonNullableByDefault} core::num) {
-      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object?} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
+      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.transformed.expect
index 78aceb3..15fcd35 100644
--- a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.strong.transformed.expect
@@ -11,7 +11,7 @@
   method qux() → dynamic {
     final self::Foo::T? v = this.{self::Foo::bar} as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo::T?;
     if(v is{ForNonNullableByDefault} core::num) {
-      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object?} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
+      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.expect b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.expect
index 78aceb3..15fcd35 100644
--- a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.expect
@@ -11,7 +11,7 @@
   method qux() → dynamic {
     final self::Foo::T? v = this.{self::Foo::bar} as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo::T?;
     if(v is{ForNonNullableByDefault} core::num) {
-      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object?} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
+      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.transformed.expect
index 78aceb3..15fcd35 100644
--- a/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd/upper_bound_on_promoted_type.dart.weak.transformed.expect
@@ -11,7 +11,7 @@
   method qux() → dynamic {
     final self::Foo::T? v = this.{self::Foo::bar} as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo::T?;
     if(v is{ForNonNullableByDefault} core::num) {
-      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object?} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
+      this.{self::Foo::baz}.[]=("value", v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::isFinite} ?{core::Object} v{self::Foo::T? & core::num /* '?' & '!' = '!' */} : v{self::Foo::T? & core::num /* '?' & '!' = '!' */}.{core::num::toString}());
     }
   }
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart b/pkg/front_end/testcases/nnbd_mixed/const_is.dart
new file mode 100644
index 0000000..9649a2d
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test derived from language/nnbd/subtyping/function_type_bounds_weak_test
+
+import 'const_is_lib.dart';
+
+main() {
+  // void fn<T extends Object>() is void Function<T extends Object?>()
+  // Should pass with weak checking because when the nullability information on
+  // Object and Object? are erased the type bounds are equivalent.
+  expect(true, fnWithNonNullObjectBound is fnTypeWithNullableObjectBound);
+  const test1 = fnWithNonNullObjectBound is fnTypeWithNullableObjectBound;
+  expect(true, test1);
+
+  // void fn<T extends Null>() is void Function<T extends Never>()
+  // Should pass with weak checking because because Null becomes equivalent to
+  // the bottom type.
+  expect(true, fnWithNullBound is fnTypeWithNeverBound);
+  const test2 = fnWithNullBound is fnTypeWithNeverBound;
+  expect(true, test2);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw "Expected $expected, actual $actual";
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline.expect
new file mode 100644
index 0000000..2b71bf0
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+import 'const_is_lib.dart';
+
+main() {}
+expect(expected, actual) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0d90c13
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+import 'const_is_lib.dart';
+
+expect(expected, actual) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
new file mode 100644
index 0000000..a139d60
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.expect
@@ -0,0 +1,33 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///const_is_lib.dart";
+
+static method main() → dynamic {
+  self::expect(true, (#C1) is{ForNonNullableByDefault} <T extends core::Object? = core::Object?>() → void);
+  self::expect(true, #C2);
+  self::expect(true, (#C3) is{ForNonNullableByDefault} <T extends Never = dynamic>() → void);
+  self::expect(true, #C2);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+typedef fnTypeWithNullableObjectBound = <T extends core::Object? = core::Object?>() → void;
+typedef fnTypeWithNeverBound = <T extends Never = dynamic>() → void;
+static method fnWithNonNullObjectBound<T extends core::Object = core::Object>() → void
+  return null;
+static method fnWithNullBound<T extends core::Null? = core::Null?>() → void
+  return null;
+
+constants  {
+  #C1 = tearoff self2::fnWithNonNullObjectBound
+  #C2 = true
+  #C3 = tearoff self2::fnWithNullBound
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
new file mode 100644
index 0000000..9c0d806
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is.dart.weak.transformed.expect
@@ -0,0 +1,38 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///const_is_lib.dart";
+
+static method main() → dynamic {
+  self::expect(true, (#C1) is{ForNonNullableByDefault} <T extends core::Object? = core::Object?>() → void);
+  self::expect(true, #C2);
+  self::expect(true, (#C3) is{ForNonNullableByDefault} <T extends Never = dynamic>() → void);
+  self::expect(true, #C2);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:core" as core;
+
+typedef fnTypeWithNullableObjectBound = <T extends core::Object? = core::Object?>() → void;
+typedef fnTypeWithNeverBound = <T extends Never = dynamic>() → void;
+static method fnWithNonNullObjectBound<T extends core::Object = core::Object>() → void
+  return null;
+static method fnWithNullBound<T extends core::Null? = core::Null?>() → void
+  return null;
+
+constants  {
+  #C1 = tearoff self2::fnWithNonNullObjectBound
+  #C2 = true
+  #C3 = tearoff self2::fnWithNullBound
+}
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:13:41 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///const_is.dart:20:32 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 14, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd_mixed/const_is_lib.dart b/pkg/front_end/testcases/nnbd_mixed/const_is_lib.dart
new file mode 100644
index 0000000..e3d0d48
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/const_is_lib.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A null safe library of helper methods to construct types and values
+/// containing non-nullable and nullable (question ?) types.
+
+typedef fnTypeWithNullableObjectBound = void Function<T extends Object?>();
+typedef fnTypeWithNeverBound = void Function<T extends Never>();
+
+void fnWithNonNullObjectBound<T extends Object>() => null;
+void fnWithNullBound<T extends Null>() => null;
diff --git a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
index 2a5dc83..439da59 100644
--- a/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/constant_null_is.dart.weak.transformed.expect
@@ -123,3 +123,22 @@
   #C6 = self::Class<core::int*> {field:#C2}
   #C7 = self::Class<core::Null?> {field:#C3}
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:46:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:47:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:48:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:49:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:50:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:51:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:52:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:53:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:54:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:55:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:56:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:57:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:58:15 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is.dart:8:40 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is_lib.dart:24:15 -> BoolConstant(false)
+Evaluated: IsExpression @ org-dartlang-testcase:///constant_null_is_lib.dart:25:15 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 139, effectively constant: 16
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart
new file mode 100644
index 0000000..a167112
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+  void covariant(SubClass cls) {} // ok
+  void invariant(SubClass cls) {} // error
+  void contravariant(Object cls) {} // ok
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect
new file mode 100644
index 0000000..4a8f587
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline.expect
@@ -0,0 +1,10 @@
+// @dart = 2.8
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+  void covariant(SubClass cls) {}
+  void invariant(SubClass cls) {}
+  void contravariant(Object cls) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0c09e22
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.textual_outline_modelled.expect
@@ -0,0 +1,10 @@
+// @dart = 2.8
+import 'covariant_from_opt_in_lib.dart';
+
+class SubClass extends Class with Mixin {
+  void contravariant(Object cls) {}
+  void covariant(SubClass cls) {}
+  void invariant(SubClass cls) {}
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect
new file mode 100644
index 0000000..433878f
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart.weak.expect
@@ -0,0 +1,62 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart:11:27: Error: The parameter 'cls' of the method 'SubClass.invariant' has type 'SubClass', which does not match the corresponding type, 'Class', in the overridden method, 'Class.invariant'.
+//  - 'SubClass' is from 'pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in.dart'.
+//  - 'Class' is from 'pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart'.
+// Change to a supertype of 'Class', or, for a covariant parameter, a subtype.
+//   void invariant(SubClass cls) {} // error
+//                           ^
+// pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart:9:8: Context: This is the overridden method ('invariant').
+//   void invariant(Class cls);
+//        ^
+//
+import self as self;
+import "covariant_from_opt_in_lib.dart" as cov;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///covariant_from_opt_in_lib.dart";
+
+abstract class _SubClass&Class&Mixin = cov::Class with cov::Mixin /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_SubClass&Class&Mixin*
+    : super cov::Class::•()
+    ;
+  abstract member-signature method covariant(covariant cov::Class* cls) → void; -> cov::Class::covariant
+  abstract member-signature method invariant(cov::Class* cls) → void; -> cov::Class::invariant
+  abstract member-signature method contravariant(cov::Class* cls) → void; -> cov::Class::contravariant
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class SubClass extends self::_SubClass&Class&Mixin {
+  synthetic constructor •() → self::SubClass*
+    : super self::_SubClass&Class&Mixin::•()
+    ;
+  method covariant(covariant self::SubClass* cls) → void {}
+  method invariant(self::SubClass* cls) → void {}
+  method contravariant(core::Object* cls) → void {}
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as cov;
+import "dart:core" as core;
+
+abstract class Mixin extends core::Object /*isMixinDeclaration*/  {
+}
+abstract class Class extends core::Object {
+  synthetic constructor •() → cov::Class
+    : super core::Object::•()
+    ;
+  abstract method covariant(covariant cov::Class cls) → void;
+  abstract method invariant(cov::Class cls) → void;
+  abstract method contravariant(cov::Class cls) → void;
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart
new file mode 100644
index 0000000..a10e376
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/covariant_from_opt_in_lib.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+mixin Mixin {}
+
+abstract class Class {
+  void covariant(covariant Class cls);
+  void invariant(Class cls);
+  void contravariant(Class cls);
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart
new file mode 100644
index 0000000..0e43b03
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import './opt_out_lib.dart';
+
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {
+  f(d);
+  f(v);
+  f(onull);
+  f(o);
+  f(snull);
+  f(s);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline.expect
new file mode 100644
index 0000000..7188a11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+import './opt_out_lib.dart';
+
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..7188a11
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+import './opt_out_lib.dart';
+
+foo(dynamic d, void v, Object? onull, Object o, String? snull, String s) {}
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.expect
new file mode 100644
index 0000000..216a6b7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.expect
@@ -0,0 +1,23 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///opt_out_lib.dart";
+
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  opt::f<dynamic>(d);
+  opt::f<void>(v);
+  opt::f<core::Object?>(onull);
+  opt::f<core::Object>(o);
+  opt::f<core::String?>(snull);
+  opt::f<core::String>(s);
+}
+static method main() → dynamic {}
+
+library;
+import self as opt;
+import "dart:core" as core;
+
+static method f<T extends core::Object* = dynamic>(opt::f::T* a) → opt::f::T*
+  return a;
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.transformed.expect
new file mode 100644
index 0000000..216a6b7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/main.dart.weak.transformed.expect
@@ -0,0 +1,23 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "opt_out_lib.dart" as opt;
+
+import "org-dartlang-testcase:///opt_out_lib.dart";
+
+static method foo(dynamic d, void v, core::Object? onull, core::Object o, core::String? snull, core::String s) → dynamic {
+  opt::f<dynamic>(d);
+  opt::f<void>(v);
+  opt::f<core::Object?>(onull);
+  opt::f<core::Object>(o);
+  opt::f<core::String?>(snull);
+  opt::f<core::String>(s);
+}
+static method main() → dynamic {}
+
+library;
+import self as opt;
+import "dart:core" as core;
+
+static method f<T extends core::Object* = dynamic>(opt::f::T* a) → opt::f::T*
+  return a;
diff --git a/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/opt_out_lib.dart b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/opt_out_lib.dart
new file mode 100644
index 0000000..1b2aaa8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/infer_object_from_dynamic/opt_out_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+T f<T>(T a) => a;
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
index 4fa35c5..c941a64 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.expect
@@ -7,12 +7,12 @@
 
 static method main() → void {
   core::Null? nil;
-  iss::x = null as{TypeError} Never;
-  iss::x = nil as{TypeError} Never;
-  iss::takesNever(null as{TypeError} Never);
-  iss::takesNever(nil as{TypeError} Never);
+  iss::x = null;
+  iss::x = nil;
+  iss::takesNever(null);
+  iss::takesNever(nil);
   iss::takesTakesNull(#C1);
-  iss::f = (Never* x) → core::Null? {};
+  iss::f = (core::Null? x) → core::Null? {};
 }
 
 library /*isNonNullableByDefault*/;
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
index 4fa35c5..c941a64 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41435.dart.weak.transformed.expect
@@ -7,12 +7,12 @@
 
 static method main() → void {
   core::Null? nil;
-  iss::x = null as{TypeError} Never;
-  iss::x = nil as{TypeError} Never;
-  iss::takesNever(null as{TypeError} Never);
-  iss::takesNever(nil as{TypeError} Never);
+  iss::x = null;
+  iss::x = nil;
+  iss::takesNever(null);
+  iss::takesNever(nil);
   iss::takesTakesNull(#C1);
-  iss::f = (Never* x) → core::Null? {};
+  iss::f = (core::Null? x) → core::Null? {};
 }
 
 library /*isNonNullableByDefault*/;
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.expect
index d17df18..af178d3 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.expect
@@ -73,26 +73,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   !c?..f;
 //       ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   !c?..f;
 //       ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f!;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f!;
 //      ^
 //
@@ -109,12 +115,15 @@
 
 static method errors(dynamic c) → dynamic {
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f;
      ^".f;
   !(invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   !c?..f;
       ^".f as{TypeError,ForDynamic} core::bool*);
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f!;
      ^".f!;
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.transformed.expect
index d14676f..d3c36df 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41597.dart.weak.transformed.expect
@@ -73,26 +73,32 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   !c?..f;
 //       ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   !c?..f;
 //       ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f!;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f!;
 //      ^
 //
@@ -109,12 +115,15 @@
 
 static method errors(dynamic c) → dynamic {
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:8:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f;
      ^".f;
   !(invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:9:7: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   !c?..f;
       ^".f as{TypeError,ForDynamic} core::bool*);
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/issue41597_lib.dart:10:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f!;
      ^".f!;
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
index d562933..a19de51 100644
--- a/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/issue41657.dart.weak.transformed.expect
@@ -26,3 +26,8 @@
   #C2 = true
   #C3 = <core::int*>[]
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///issue41657.dart:5:44 -> BoolConstant(true)
+Evaluated: IsExpression @ org-dartlang-testcase:///issue41657.dart:7:44 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 18, effectively constant: 2
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart
new file mode 100644
index 0000000..a219889
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline.expect
new file mode 100644
index 0000000..34a9e3a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..34a9e3a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.textual_outline_modelled.expect
@@ -0,0 +1,4 @@
+// @dart = 2.8
+import 'main_declaration_lib.dart';
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.expect
new file mode 100644
index 0000000..58118e1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_lib.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+static method main(core::String* args) → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.transformed.expect
new file mode 100644
index 0000000..58118e1
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration.dart.weak.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///main_declaration_lib.dart";
+
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+static method main(core::String* args) → dynamic {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/main_declaration_lib.dart b/pkg/front_end/testcases/nnbd_mixed/main_declaration_lib.dart
new file mode 100644
index 0000000..9fb74f3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/main_declaration_lib.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+// This would be an invalid main declaration in a null safe library.
+main(String args) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.expect
index c2781bb..44dc597 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.expect
@@ -43,17 +43,6 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature method method1() → core::int*; -> mem::Class::method1
-  abstract member-signature method method2() → core::int*; -> mem::Class::method2
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*; -> mem::Class::method5a
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*; -> mem::Class::method5b
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*; -> mem::Class::method5c
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method7a
-  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*; -> mem::Class::method7b
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method9a
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*; -> mem::Class::method9b
-  abstract member-signature get getter1() → core::int*; -> mem::Class::getter1
-  abstract member-signature get getter2() → core::int*; -> mem::Class::getter2
   abstract member-signature get field1() → core::int*; -> mem::Class::field1
   abstract member-signature set field1(core::int* _) → void; -> mem::Class::field1
   abstract member-signature get field2() → core::int*; -> mem::Class::field2
@@ -66,6 +55,17 @@
   abstract member-signature set property5(core::int* _) → void; -> mem::Class::property5
   abstract member-signature get property6() → core::int*; -> mem::Class::property6
   abstract member-signature set property6(core::int* _) → void; -> mem::Class::property6
+  abstract member-signature method method1() → core::int*; -> mem::Class::method1
+  abstract member-signature method method2() → core::int*; -> mem::Class::method2
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*; -> mem::Class::method5a
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*; -> mem::Class::method5b
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*; -> mem::Class::method5c
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method7a
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*; -> mem::Class::method7b
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method9a
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*; -> mem::Class::method9b
+  abstract member-signature get getter1() → core::int*; -> mem::Class::getter1
+  abstract member-signature get getter2() → core::int*; -> mem::Class::getter2
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.transformed.expect
index c2781bb..44dc597 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_in.dart.weak.transformed.expect
@@ -43,17 +43,6 @@
   get property4() → core::int*
     return 0;
   set property4(core::int* value) → void {}
-  abstract member-signature method method1() → core::int*; -> mem::Class::method1
-  abstract member-signature method method2() → core::int*; -> mem::Class::method2
-  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*; -> mem::Class::method5a
-  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*; -> mem::Class::method5b
-  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*; -> mem::Class::method5c
-  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method7a
-  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*; -> mem::Class::method7b
-  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method9a
-  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*; -> mem::Class::method9b
-  abstract member-signature get getter1() → core::int*; -> mem::Class::getter1
-  abstract member-signature get getter2() → core::int*; -> mem::Class::getter2
   abstract member-signature get field1() → core::int*; -> mem::Class::field1
   abstract member-signature set field1(core::int* _) → void; -> mem::Class::field1
   abstract member-signature get field2() → core::int*; -> mem::Class::field2
@@ -66,6 +55,17 @@
   abstract member-signature set property5(core::int* _) → void; -> mem::Class::property5
   abstract member-signature get property6() → core::int*; -> mem::Class::property6
   abstract member-signature set property6(core::int* _) → void; -> mem::Class::property6
+  abstract member-signature method method1() → core::int*; -> mem::Class::method1
+  abstract member-signature method method2() → core::int*; -> mem::Class::method2
+  abstract member-signature method method5a(core::int* a, core::int* b) → core::int*; -> mem::Class::method5a
+  abstract member-signature method method5b(core::int* a, [core::int* b = #C1]) → core::int*; -> mem::Class::method5b
+  abstract member-signature method method5c([core::int* a = #C2, core::int* b = #C1]) → core::int*; -> mem::Class::method5c
+  abstract member-signature method method7a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method7a
+  abstract member-signature method method7b({core::int* a = #C2, core::int* b = #C1}) → core::int*; -> mem::Class::method7b
+  abstract member-signature method method9a(core::int* a, {core::int* b = #C1}) → core::int*; -> mem::Class::method9a
+  abstract member-signature method method9b({core::int* a = #C1, core::int* b = #C1}) → core::int*; -> mem::Class::method9b
+  abstract member-signature get getter1() → core::int*; -> mem::Class::getter1
+  abstract member-signature get getter2() → core::int*; -> mem::Class::getter2
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
index 3f07aa4..973cfd4 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
@@ -49,22 +49,6 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method1() → core::int; -> opt::LegacyClass::method1
-  abstract member-signature method method2() → core::int?; -> opt::LegacyClass::method2
-  abstract member-signature method method3a(core::int a, core::int b) → core::int; -> opt::LegacyClass::method3a
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int; -> opt::LegacyClass::method3b
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int; -> opt::LegacyClass::method3c
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?; -> opt::LegacyClass::method4a
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4b
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4c
-  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int; -> opt::LegacyClass::method5a
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5b
-  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5c
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6a
-  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6b
-  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6c
-  abstract member-signature get getter1() → core::int; -> opt::LegacyClass::getter1
-  abstract member-signature get getter2() → core::int?; -> opt::LegacyClass::getter2
   abstract member-signature get field1() → core::int; -> opt::LegacyClass::field1
   abstract member-signature set field1(core::int _) → void; -> opt::LegacyClass::field1
   abstract member-signature get field2() → core::int?; -> opt::LegacyClass::field2
@@ -81,6 +65,20 @@
   abstract member-signature set property3(core::int value) → void; -> opt::LegacyClass::property3
   abstract member-signature get property4() → core::int?; -> opt::LegacyClass::property4
   abstract member-signature set property4(core::int? value) → void; -> opt::LegacyClass::property4
+  abstract member-signature method method1() → core::int; -> opt::LegacyClass::method1
+  abstract member-signature method method2() → core::int?; -> opt::LegacyClass::method2
+  abstract member-signature method method3a(core::int a, core::int b) → core::int; -> opt::LegacyClass::method3a
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int; -> opt::LegacyClass::method3b
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int; -> opt::LegacyClass::method3c
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?; -> opt::LegacyClass::method4a
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4b
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4c
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int; -> opt::LegacyClass::method5a
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5b
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6a
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6b
+  abstract member-signature get getter1() → core::int; -> opt::LegacyClass::getter1
+  abstract member-signature get getter2() → core::int?; -> opt::LegacyClass::getter2
   abstract member-signature get _identityHashCode() → core::int; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
index 3f07aa4..973cfd4 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
@@ -49,22 +49,6 @@
   synthetic constructor •() → self::Class2a
     : super opt::LegacyClass::•()
     ;
-  abstract member-signature method method1() → core::int; -> opt::LegacyClass::method1
-  abstract member-signature method method2() → core::int?; -> opt::LegacyClass::method2
-  abstract member-signature method method3a(core::int a, core::int b) → core::int; -> opt::LegacyClass::method3a
-  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int; -> opt::LegacyClass::method3b
-  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int; -> opt::LegacyClass::method3c
-  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?; -> opt::LegacyClass::method4a
-  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4b
-  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4c
-  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int; -> opt::LegacyClass::method5a
-  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5b
-  abstract member-signature method method5c({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5c
-  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6a
-  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6b
-  abstract member-signature method method6c({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6c
-  abstract member-signature get getter1() → core::int; -> opt::LegacyClass::getter1
-  abstract member-signature get getter2() → core::int?; -> opt::LegacyClass::getter2
   abstract member-signature get field1() → core::int; -> opt::LegacyClass::field1
   abstract member-signature set field1(core::int _) → void; -> opt::LegacyClass::field1
   abstract member-signature get field2() → core::int?; -> opt::LegacyClass::field2
@@ -81,6 +65,20 @@
   abstract member-signature set property3(core::int value) → void; -> opt::LegacyClass::property3
   abstract member-signature get property4() → core::int?; -> opt::LegacyClass::property4
   abstract member-signature set property4(core::int? value) → void; -> opt::LegacyClass::property4
+  abstract member-signature method method1() → core::int; -> opt::LegacyClass::method1
+  abstract member-signature method method2() → core::int?; -> opt::LegacyClass::method2
+  abstract member-signature method method3a(core::int a, core::int b) → core::int; -> opt::LegacyClass::method3a
+  abstract member-signature method method3b(core::int a, [core::int b = #C1]) → core::int; -> opt::LegacyClass::method3b
+  abstract member-signature method method3c([core::int a = #C1, core::int b = #C1]) → core::int; -> opt::LegacyClass::method3c
+  abstract member-signature method method4a(core::int? a, core::int? b) → core::int?; -> opt::LegacyClass::method4a
+  abstract member-signature method method4b(core::int? a, [core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4b
+  abstract member-signature method method4c([core::int? a = #C1, core::int? b = #C1]) → core::int?; -> opt::LegacyClass::method4c
+  abstract member-signature method method5a(core::int a, {core::int b = #C1}) → core::int; -> opt::LegacyClass::method5a
+  abstract member-signature method method5b({core::int a = #C1, core::int b = #C1}) → core::int; -> opt::LegacyClass::method5b
+  abstract member-signature method method6a(core::int? a, {core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6a
+  abstract member-signature method method6b({core::int? a = #C1, core::int? b = #C1}) → core::int?; -> opt::LegacyClass::method6b
+  abstract member-signature get getter1() → core::int; -> opt::LegacyClass::getter1
+  abstract member-signature get getter2() → core::int?; -> opt::LegacyClass::getter2
   abstract member-signature get _identityHashCode() → core::int; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.expect
index 831000c..225ab3c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.expect
@@ -25,94 +25,94 @@
   synthetic constructor •() → self::MockHttpHeaders*
     : super self::Mock::•()
     ;
-  no-such-method-forwarder operator [](core::String* name) → core::List<core::String*>*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
-  no-such-method-forwarder method value(core::String* name) → core::String*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
-  no-such-method-forwarder method add(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C6}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: preserveHeaderCase})));
-  no-such-method-forwarder method set(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C6}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: preserveHeaderCase})));
-  no-such-method-forwarder method remove(core::String* name, core::Object* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method removeAll(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method forEach((core::String*, core::List<core::String*>*) →* void action) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method noFolding(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get date() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set date(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get expires() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set expires(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get ifModifiedSince() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C18, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set ifModifiedSince(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get host() → core::String*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C20, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
   no-such-method-forwarder set host(core::String* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get port() → core::int*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set port(core::int* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentType() → _ht::ContentType*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C24, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} _ht::ContentType*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} _ht::ContentType*;
   no-such-method-forwarder set contentType(_ht::ContentType* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentLength() → core::int*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C26, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set contentLength(core::int* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get persistentConnection() → core::bool*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C18, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set persistentConnection(core::bool* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get chunkedTransferEncoding() → core::bool*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C20, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set chunkedTransferEncoding(core::bool* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder operator [](core::String* name) → core::List<core::String*>*
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
+  no-such-method-forwarder method value(core::String* name) → core::String*
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
+  no-such-method-forwarder method add(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+  no-such-method-forwarder method set(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+  no-such-method-forwarder method remove(core::String* name, core::Object* value) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method removeAll(core::String* name) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method forEach((core::String*, core::List<core::String*>*) →* void action) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method noFolding(core::String* name) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/_http/http.dart */ clear() → void
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C32, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
 constants  {
-  #C1 = #[]
+  #C1 = #date
   #C2 = <core::Type*>[]
   #C3 = <dynamic>[]
   #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
-  #C5 = #value
-  #C6 = false
-  #C7 = #add
-  #C8 = #preserveHeaderCase
-  #C9 = #set
-  #C10 = #remove
-  #C11 = #removeAll
-  #C12 = #forEach
-  #C13 = #noFolding
-  #C14 = #date
-  #C15 = #date=
-  #C16 = #expires
-  #C17 = #expires=
-  #C18 = #ifModifiedSince
-  #C19 = #ifModifiedSince=
-  #C20 = #host
-  #C21 = #host=
-  #C22 = #port
-  #C23 = #port=
-  #C24 = #contentType
-  #C25 = #contentType=
-  #C26 = #contentLength
-  #C27 = #contentLength=
-  #C28 = #persistentConnection
-  #C29 = #persistentConnection=
-  #C30 = #chunkedTransferEncoding
-  #C31 = #chunkedTransferEncoding=
+  #C5 = #date=
+  #C6 = #expires
+  #C7 = #expires=
+  #C8 = #ifModifiedSince
+  #C9 = #ifModifiedSince=
+  #C10 = #host
+  #C11 = #host=
+  #C12 = #port
+  #C13 = #port=
+  #C14 = #contentType
+  #C15 = #contentType=
+  #C16 = #contentLength
+  #C17 = #contentLength=
+  #C18 = #persistentConnection
+  #C19 = #persistentConnection=
+  #C20 = #chunkedTransferEncoding
+  #C21 = #chunkedTransferEncoding=
+  #C22 = #[]
+  #C23 = #value
+  #C24 = false
+  #C25 = #add
+  #C26 = #preserveHeaderCase
+  #C27 = #set
+  #C28 = #remove
+  #C29 = #removeAll
+  #C30 = #forEach
+  #C31 = #noFolding
   #C32 = #clear
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
index 831000c..225ab3c 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.transformed.expect
@@ -25,94 +25,94 @@
   synthetic constructor •() → self::MockHttpHeaders*
     : super self::Mock::•()
     ;
-  no-such-method-forwarder operator [](core::String* name) → core::List<core::String*>*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
-  no-such-method-forwarder method value(core::String* name) → core::String*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
-  no-such-method-forwarder method add(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C6}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: preserveHeaderCase})));
-  no-such-method-forwarder method set(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C6}) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C8: preserveHeaderCase})));
-  no-such-method-forwarder method remove(core::String* name, core::Object* value) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method removeAll(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method forEach((core::String*, core::List<core::String*>*) →* void action) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
-  no-such-method-forwarder method noFolding(core::String* name) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get date() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C1, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set date(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C5, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get expires() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C6, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set expires(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C7, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get ifModifiedSince() → core::DateTime*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C18, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C8, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::DateTime*;
   no-such-method-forwarder set ifModifiedSince(core::DateTime* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C9, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get host() → core::String*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C20, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C10, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
   no-such-method-forwarder set host(core::String* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C11, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get port() → core::int*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C12, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set port(core::int* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C13, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentType() → _ht::ContentType*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C24, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} _ht::ContentType*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C14, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} _ht::ContentType*;
   no-such-method-forwarder set contentType(_ht::ContentType* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C15, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get contentLength() → core::int*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C26, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C16, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::int*;
   no-such-method-forwarder set contentLength(core::int* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C17, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get persistentConnection() → core::bool*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C18, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set persistentConnection(core::bool* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C19, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder get chunkedTransferEncoding() → core::bool*
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C20, 1, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::bool*;
   no-such-method-forwarder set chunkedTransferEncoding(core::bool* _) → void
-    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C21, 2, #C2, core::List::unmodifiable<dynamic>(<dynamic>[_]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder operator [](core::String* name) → core::List<core::String*>*
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C22, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::List<core::String*>*;
+  no-such-method-forwarder method value(core::String* name) → core::String*
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C23, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4))) as{TypeError,ForDynamic} core::String*;
+  no-such-method-forwarder method add(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C25, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+  no-such-method-forwarder method set(core::String* name, core::Object* value, {core::bool* preserveHeaderCase = #C24}) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C27, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(<core::Symbol*, dynamic>{#C26: preserveHeaderCase})));
+  no-such-method-forwarder method remove(core::String* name, core::Object* value) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C28, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name, value]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method removeAll(core::String* name) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C29, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method forEach((core::String*, core::List<core::String*>*) →* void action) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C30, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[action]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
+  no-such-method-forwarder method noFolding(core::String* name) → void
+    return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C31, 0, #C2, core::List::unmodifiable<dynamic>(<dynamic>[name]), core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
   no-such-method-forwarder method /*isNonNullableByDefault, from org-dartlang-sdk:///sdk/lib/_http/http.dart */ clear() → void
     return this.{self::Mock::noSuchMethod}(new core::_InvocationMirror::_withType(#C32, 0, #C2, #C3, core::Map::unmodifiable<core::Symbol*, dynamic>(#C4)));
 }
 static method main() → dynamic {}
 
 constants  {
-  #C1 = #[]
+  #C1 = #date
   #C2 = <core::Type*>[]
   #C3 = <dynamic>[]
   #C4 = core::_ImmutableMap<core::Symbol*, dynamic> {_kvPairs:#C3}
-  #C5 = #value
-  #C6 = false
-  #C7 = #add
-  #C8 = #preserveHeaderCase
-  #C9 = #set
-  #C10 = #remove
-  #C11 = #removeAll
-  #C12 = #forEach
-  #C13 = #noFolding
-  #C14 = #date
-  #C15 = #date=
-  #C16 = #expires
-  #C17 = #expires=
-  #C18 = #ifModifiedSince
-  #C19 = #ifModifiedSince=
-  #C20 = #host
-  #C21 = #host=
-  #C22 = #port
-  #C23 = #port=
-  #C24 = #contentType
-  #C25 = #contentType=
-  #C26 = #contentLength
-  #C27 = #contentLength=
-  #C28 = #persistentConnection
-  #C29 = #persistentConnection=
-  #C30 = #chunkedTransferEncoding
-  #C31 = #chunkedTransferEncoding=
+  #C5 = #date=
+  #C6 = #expires
+  #C7 = #expires=
+  #C8 = #ifModifiedSince
+  #C9 = #ifModifiedSince=
+  #C10 = #host
+  #C11 = #host=
+  #C12 = #port
+  #C13 = #port=
+  #C14 = #contentType
+  #C15 = #contentType=
+  #C16 = #contentLength
+  #C17 = #contentLength=
+  #C18 = #persistentConnection
+  #C19 = #persistentConnection=
+  #C20 = #chunkedTransferEncoding
+  #C21 = #chunkedTransferEncoding=
+  #C22 = #[]
+  #C23 = #value
+  #C24 = false
+  #C25 = #add
+  #C26 = #preserveHeaderCase
+  #C27 = #set
+  #C28 = #remove
+  #C29 = #removeAll
+  #C30 = #forEach
+  #C31 = #noFolding
   #C32 = #clear
 }
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart
index 1d9981b..4f30ec5 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart
@@ -9,7 +9,17 @@
 Never optOutNever;
 var inferredOptOutNever = optInNever;
 
+genericMethod<T>() {}
+
+class GenericClass<T> {}
+
 main() {
+  optInNever = optOutNever;
+
+  Type typeNever = Never;
+  genericMethod<Never>();
+  new GenericClass<Never>();
+
   Never localNever = null;
   Null localNull = null;
   var inferredLocalNever = optInNever;
@@ -62,6 +72,15 @@
   throws(() => optInNever = throwing());
   throws(() => inferredOptOutNever = throwing());
   throws(() => inferredLocalNever = throwing());
+
+  var boundedGenericClass = new BoundedGenericClass();
+  throws(() {
+    var boundedGenericMethodResult1 = boundedGenericMethod1();
+  });
+  var boundedGenericMethodResult2 = boundedGenericMethod2();
+
+  dynamic dyn = null;
+  optInNever = dyn;
 }
 
 class B extends A {
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline.expect
index 0630e92..fc4c4c0 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline.expect
@@ -3,6 +3,10 @@
 
 Never optOutNever;
 var inferredOptOutNever = optInNever;
+genericMethod<T>() {}
+
+class GenericClass<T> {}
+
 main() {}
 
 class B extends A {
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline_modelled.expect
index 26f5017..c9f7109 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.textual_outline_modelled.expect
@@ -25,6 +25,9 @@
   void set nullProperty(Never value) {}
 }
 
+class GenericClass<T> {}
+
+genericMethod<T>() {}
 main() {}
 throws(void Function() f) {}
 var inferredOptOutNever = optInNever;
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
index 974155d..4852b17 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.expect
@@ -1,10 +1,25 @@
 library;
 import self as self;
-import "never_opt_out_lib.dart" as nev;
 import "dart:core" as core;
+import "never_opt_out_lib.dart" as nev;
 
 import "org-dartlang-testcase:///never_opt_out_lib.dart";
 
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
 class B extends nev::A {
   field core::Null? neverField = null;
   field core::Null? nullField = null;
@@ -33,21 +48,21 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 class C extends nev::A {
-  field Never* neverField = null;
-  field Never* nullField = null;
+  field core::Null? neverField = null;
+  field core::Null? nullField = null;
   synthetic constructor •() → self::C*
     : super nev::A::•()
     ;
-  method neverMethod(Never* value) → Never*
+  method neverMethod(core::Null? value) → core::Null?
     return value;
-  get neverProperty() → Never*
+  get neverProperty() → core::Null?
     return null;
-  set neverProperty(Never* value) → void {}
-  method nullMethod(Never* value) → Never*
+  set neverProperty(core::Null? value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
     return value;
-  get nullProperty() → Never*
+  get nullProperty() → core::Null?
     return null;
-  set nullProperty(Never* value) → void {}
+  set nullProperty(core::Null? value) → void {}
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -59,10 +74,15 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
-static field Never* optOutNever;
+static field core::Null? optOutNever;
 static field dynamic inferredOptOutNever = nev::optInNever;
+static method genericMethod<T extends core::Object* = dynamic>() → dynamic {}
 static method main() → dynamic {
-  Never* localNever = null;
+  nev::optInNever = self::optOutNever;
+  core::Type* typeNever = core::Null?;
+  self::genericMethod<core::Null?>();
+  new self::GenericClass::•<core::Null?>();
+  core::Null? localNever = null;
   core::Null? localNull = null;
   dynamic inferredLocalNever = nev::optInNever;
   localNever = localNever;
@@ -73,30 +93,30 @@
   inferredLocalNever = localNever;
   localNever = self::optOutNever;
   self::optOutNever = self::optOutNever;
-  nev::optInNever = self::optOutNever as{TypeError} Never;
+  nev::optInNever = self::optOutNever;
   localNull = self::optOutNever;
   self::inferredOptOutNever = self::optOutNever;
   inferredLocalNever = self::optOutNever;
   localNever = nev::optInNever;
   self::optOutNever = nev::optInNever;
-  nev::optInNever = nev::optInNever as{TypeError} Never;
+  nev::optInNever = nev::optInNever;
   localNull = nev::optInNever;
   self::inferredOptOutNever = nev::optInNever;
   inferredLocalNever = nev::optInNever;
   localNever = localNull;
   self::optOutNever = localNull;
-  nev::optInNever = localNull as{TypeError} Never;
+  nev::optInNever = localNull;
   localNull = localNull;
   self::inferredOptOutNever = localNull;
   inferredLocalNever = localNull;
-  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
-  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never*;
+  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
+  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
   nev::optInNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never;
   localNull = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
   self::inferredOptOutNever = self::inferredOptOutNever;
   inferredLocalNever = self::inferredOptOutNever;
-  localNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
-  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} Never*;
+  localNever = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
+  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
   nev::optInNever = inferredLocalNever as{TypeError,ForDynamic} Never;
   localNull = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
   self::inferredOptOutNever = inferredLocalNever;
@@ -104,9 +124,16 @@
   self::throws(() → core::Null? => self::optOutNever = nev::throwing());
   self::throws(() → core::Null? => localNever = nev::throwing());
   self::throws(() → core::Null? => self::optOutNever = nev::throwing());
-  self::throws(() → core::Null? => nev::optInNever = nev::throwing() as{TypeError} Never);
+  self::throws(() → core::Null? => nev::optInNever = nev::throwing());
   self::throws(() → core::Null? => self::inferredOptOutNever = nev::throwing());
   self::throws(() → core::Null? => inferredLocalNever = nev::throwing());
+  nev::BoundedGenericClass<core::Null?>* boundedGenericClass = new nev::BoundedGenericClass::•<core::Null?>();
+  self::throws(() → core::Null? {
+    dynamic boundedGenericMethodResult1 = nev::boundedGenericMethod1<core::Null?>();
+  });
+  core::List<core::Null?>* boundedGenericMethodResult2 = nev::boundedGenericMethod2<core::Null?>();
+  dynamic dyn = null;
+  nev::optInNever = dyn as{TypeError,ForDynamic} Never;
 }
 static method throws(() →* void f) → dynamic {
   try {
@@ -119,17 +146,9 @@
 }
 
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be returned from a function with return type 'Null'.
-//  - 'Type' is from 'dart:core'.
-//   Null get nullProperty => Null;
-//                            ^
-//
 import self as nev;
 import "dart:core" as core;
-import "never_opt_out.dart" as self;
+import "dart:_internal" as _in;
 
 import "org-dartlang-testcase:///never_opt_out.dart";
 
@@ -140,19 +159,25 @@
     : super core::Object::•()
     ;
   method neverMethod(Never value) → Never
-    return value;
+    return let final Never #t1 = value in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
   get neverProperty() → Never
     return throw "Should not reach here";
   set neverProperty(Never value) → void {}
   method nullMethod(core::Null? value) → core::Null?
     return value;
   get nullProperty() → core::Null?
-    return let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart:19:28: Error: A value of type 'Type' can't be returned from a function with return type 'Null'.
- - 'Type' is from 'dart:core'.
-  Null get nullProperty => Null;
-                           ^" in core::Null? as{TypeError,ForNonNullableByDefault} core::Null?;
+    return null;
   set nullProperty(core::Null? value) → void {}
 }
-static field Never optInNever = self::optOutNever;
+class BoundedGenericClass<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → nev::BoundedGenericClass<nev::BoundedGenericClass::T>
+    : super core::Object::•()
+    ;
+}
+late static field Never optInNever;
 static method throwing() → Never
   return throw "Never!";
+static method boundedGenericMethod1<T extends Never = Never>() → nev::boundedGenericMethod1::T
+  return throw "Should never return";
+static method boundedGenericMethod2<T extends Never = Never>() → core::List<nev::boundedGenericMethod2::T>
+  return <nev::boundedGenericMethod2::T>[];
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
index bf726fb..9428bc8 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out.dart.weak.transformed.expect
@@ -5,12 +5,86 @@
 
 import "org-dartlang-testcase:///never_opt_out_lib.dart";
 
-static field Never* optOutNever;
-static field core::Null? inferredOptOutNever = nev::optInNever;
+class GenericClass<T extends core::Object* = dynamic> extends core::Object {
+  synthetic constructor •() → self::GenericClass<self::GenericClass::T*>*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class B extends nev::A {
+  field core::Null? neverField = null;
+  field core::Null? nullField = null;
+  synthetic constructor •() → self::B*
+    : super nev::A::•()
+    ;
+  method neverMethod(core::Null? value) → core::Null?
+    return value;
+  get neverProperty() → core::Null?
+    return null;
+  set neverProperty(core::Null? value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return null;
+  set nullProperty(core::Null? value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class C extends nev::A {
+  field core::Null? neverField = null;
+  field core::Null? nullField = null;
+  synthetic constructor •() → self::C*
+    : super nev::A::•()
+    ;
+  method neverMethod(core::Null? value) → core::Null?
+    return value;
+  get neverProperty() → core::Null?
+    return null;
+  set neverProperty(core::Null? value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return null;
+  set nullProperty(core::Null? value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+static field core::Null? optOutNever;
+static field dynamic inferredOptOutNever = nev::optInNever;
+static method genericMethod<T extends core::Object* = dynamic>() → dynamic {}
 static method main() → dynamic {
-  Never* localNever = null;
+  nev::optInNever = self::optOutNever;
+  core::Type* typeNever = core::Null?;
+  self::genericMethod<core::Null?>();
+  new self::GenericClass::•<core::Null?>();
+  core::Null? localNever = null;
   core::Null? localNull = null;
-  Never inferredLocalNever = nev::optInNever;
+  dynamic inferredLocalNever = nev::optInNever;
   localNever = localNever;
   self::optOutNever = localNever;
   nev::optInNever = localNever;
@@ -31,28 +105,35 @@
   inferredLocalNever = nev::optInNever;
   localNever = localNull;
   self::optOutNever = localNull;
-  nev::optInNever = localNull as{TypeError} Never;
+  nev::optInNever = localNull;
   localNull = localNull;
   self::inferredOptOutNever = localNull;
-  inferredLocalNever = localNull as{TypeError} Never;
-  localNever = self::inferredOptOutNever;
-  self::optOutNever = self::inferredOptOutNever;
-  nev::optInNever = self::inferredOptOutNever as{TypeError} Never;
-  localNull = self::inferredOptOutNever;
+  inferredLocalNever = localNull;
+  localNever = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
+  self::optOutNever = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
+  nev::optInNever = self::inferredOptOutNever as{TypeError,ForDynamic} Never;
+  localNull = self::inferredOptOutNever as{TypeError,ForDynamic} core::Null?;
   self::inferredOptOutNever = self::inferredOptOutNever;
-  inferredLocalNever = self::inferredOptOutNever as{TypeError} Never;
-  localNever = inferredLocalNever;
-  self::optOutNever = inferredLocalNever;
-  nev::optInNever = inferredLocalNever;
-  localNull = inferredLocalNever;
+  inferredLocalNever = self::inferredOptOutNever;
+  localNever = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
+  self::optOutNever = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
+  nev::optInNever = inferredLocalNever as{TypeError,ForDynamic} Never;
+  localNull = inferredLocalNever as{TypeError,ForDynamic} core::Null?;
   self::inferredOptOutNever = inferredLocalNever;
   inferredLocalNever = inferredLocalNever;
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => localNever = nev::throwing());
-  self::throws(() → Never => self::optOutNever = nev::throwing());
-  self::throws(() → Never => nev::optInNever = nev::throwing());
-  self::throws(() → Never => self::inferredOptOutNever = nev::throwing());
-  self::throws(() → Never => inferredLocalNever = nev::throwing());
+  self::throws(() → core::Null? => self::optOutNever = nev::throwing());
+  self::throws(() → core::Null? => localNever = nev::throwing());
+  self::throws(() → core::Null? => self::optOutNever = nev::throwing());
+  self::throws(() → core::Null? => nev::optInNever = nev::throwing());
+  self::throws(() → core::Null? => self::inferredOptOutNever = nev::throwing());
+  self::throws(() → core::Null? => inferredLocalNever = nev::throwing());
+  nev::BoundedGenericClass<core::Null?>* boundedGenericClass = new nev::BoundedGenericClass::•<core::Null?>();
+  self::throws(() → core::Null? {
+    dynamic boundedGenericMethodResult1 = nev::boundedGenericMethod1<core::Null?>();
+  });
+  core::List<core::Null?>* boundedGenericMethodResult2 = nev::boundedGenericMethod2<core::Null?>();
+  dynamic dyn = null;
+  nev::optInNever = dyn as{TypeError,ForDynamic} Never;
 }
 static method throws(() →* void f) → dynamic {
   try {
@@ -66,10 +147,42 @@
 
 library /*isNonNullableByDefault*/;
 import self as nev;
-import "never_opt_out.dart" as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
 
 import "org-dartlang-testcase:///never_opt_out.dart";
 
-static field Never optInNever = self::optOutNever;
+class A extends core::Object {
+  field Never neverField = throw "Should not reach here";
+  field core::Null? nullField = null;
+  synthetic constructor •() → nev::A
+    : super core::Object::•()
+    ;
+  method neverMethod(Never value) → Never
+    return let final Never #t1 = value in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+  get neverProperty() → Never
+    return throw "Should not reach here";
+  set neverProperty(Never value) → void {}
+  method nullMethod(core::Null? value) → core::Null?
+    return value;
+  get nullProperty() → core::Null?
+    return null;
+  set nullProperty(core::Null? value) → void {}
+}
+class BoundedGenericClass<T extends Never = Never> extends core::Object {
+  synthetic constructor •() → nev::BoundedGenericClass<nev::BoundedGenericClass::T>
+    : super core::Object::•()
+    ;
+}
+late static field Never optInNever;
 static method throwing() → Never
   return throw "Never!";
+static method boundedGenericMethod1<T extends Never = Never>() → nev::boundedGenericMethod1::T
+  return throw "Should never return";
+static method boundedGenericMethod2<T extends Never = Never>() → core::List<nev::boundedGenericMethod2::T>
+  return <nev::boundedGenericMethod2::T>[];
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///never_opt_out.dart:19:20 -> TypeLiteralConstant(Null?)
+Extra constant evaluation: evaluated: 136, effectively constant: 1
diff --git a/pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart b/pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart
index 06c5c16..b2f225b 100644
--- a/pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart
+++ b/pkg/front_end/testcases/nnbd_mixed/never_opt_out_lib.dart
@@ -6,7 +6,7 @@
 
 Never throwing() => throw 'Never!';
 
-Never optInNever = optOutNever;
+late Never optInNever;
 
 class A {
   Never neverField = throw "Should not reach here";
@@ -16,6 +16,12 @@
 
   Null nullField = null;
   Null nullMethod(Null value) => value;
-  Null get nullProperty => Null;
+  Null get nullProperty => null;
   void set nullProperty(Null value) {}
 }
+
+class BoundedGenericClass<T extends Never> {}
+
+T boundedGenericMethod1<T extends Never>() => throw "Should never return";
+
+List<T> boundedGenericMethod2<T extends Never>() => <T>[];
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
index 2c1fe98..3869af1 100644
--- a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.expect
@@ -116,10 +116,12 @@
 // ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f;
 //      ^
 //
@@ -168,6 +170,7 @@
   core::String* t = s!;
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f;
      ^".f;
   let final dynamic #t3 = c in #t3.{core::Object::==}(null) ?{dynamic} null : #t3.[](0);
diff --git a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
index 2c1fe98..3869af1 100644
--- a/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/opt_out.dart.weak.transformed.expect
@@ -116,10 +116,12 @@
 // ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got '.'.
+// Try inserting an identifier before '.'.
 //   c?..f;
 //      ^
 //
 // pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   c?..f;
 //      ^
 //
@@ -168,6 +170,7 @@
   core::String* t = s!;
   dynamic c;
   invalid-expression "pkg/front_end/testcases/nnbd_mixed/opt_out_lib.dart:36:6: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   c?..f;
      ^".f;
   let final dynamic #t3 = c in #t3.{core::Object::==}(null) ?{dynamic} null : #t3.[](0);
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart
new file mode 100644
index 0000000..3939918
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart
@@ -0,0 +1,286 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+import 'unsound_checks_lib.dart';
+
+isNullOptOut1(int i) => i == null;
+
+isNotNullOptOut1(int i) => i != null;
+
+isNullOptOut2(int i) => null == i;
+
+isNotNullOptOut2(int i) => null != i;
+
+ifNullOptOut(int i) => i ?? 42;
+
+class OptOutClass1 {}
+
+extension OptOutExtension on OptOutClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
+
+extensionIfNullOptOut1ForEffect(int i) {
+  OptOutExtension(new OptOutClass1())[i] ??= 42;
+}
+
+extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
+
+extensionIfNullOptOut2ForEffect(int i) {
+  new OptOutClass1()[i] ??= 42;
+}
+
+class OptOutClass2 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
+
+ifNullIndexSetOptOutForEffect(int i) {
+  new OptOutClass2()[i] ??= 42;
+}
+
+class OptOutClass3 {
+  int field;
+
+  OptOutClass3(this.field);
+}
+
+ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
+
+ifNullPropertySetOptOutForEffect(int i) {
+  new OptOutClass3(i).field ??= 42;
+}
+
+ifNullSetOptOut(int i) => i ??= 42;
+
+ifNullSetOptOutForEffect(int i) {
+  i ??= 42;
+}
+
+class OptOutSuperClass4 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class OptOutClass4 extends OptOutSuperClass4 {
+  method(int i) => super[i] ??= 42;
+  methodForEffect(int i) {
+    super[i] ??= 42;
+  }
+}
+
+ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
+
+ifNullSuperIndexSetOptOutForEffect(int i) {
+  new OptOutClass4().methodForEffect(i);
+}
+
+class OptOutClass5 {
+  int field;
+
+  OptOutClass5(this.field);
+}
+
+nullAwareIfNullSetOptOut(int i) {
+  OptOutClass5 o = new OptOutClass5(i);
+  return o?.field ??= 42;
+}
+
+nullAwareIfNullSetOptOutForEffect(int i) {
+  OptOutClass5 o = new OptOutClass5(i);
+  o?.field ??= 42;
+}
+
+isTestOptOut(int i) => i is int;
+
+isNotTestOptOut(int i) => i is! int;
+
+main() {
+  expect(false, isNullOptIn1(0));
+  expect(false, isNullOptOut1(0));
+
+  expect(true, isNullOptIn1(null));
+  expect(true, isNullOptOut1(null));
+
+  expect(true, isNotNullOptIn1(0));
+  expect(true, isNotNullOptOut1(0));
+
+  expect(false, isNotNullOptIn1(null));
+  expect(false, isNotNullOptOut1(null));
+
+  expect(false, isNullOptIn2(0));
+  expect(false, isNullOptOut2(0));
+
+  expect(true, isNullOptIn2(null));
+  expect(true, isNullOptOut2(null));
+
+  expect(true, isNotNullOptIn2(0));
+  expect(true, isNotNullOptOut2(0));
+
+  expect(false, isNotNullOptIn2(null));
+  expect(false, isNotNullOptOut2(null));
+
+  expect(0, ifNullOptIn(0));
+  expect(0, ifNullOptOut(0));
+
+  expect(42, ifNullOptIn(null));
+  expect(42, ifNullOptOut(null));
+
+  expect(0, extensionIfNullOptIn1(0));
+  expect(0, extensionIfNullOptOut1(0));
+
+  expect(42, extensionIfNullOptIn1(null));
+  expect(42, extensionIfNullOptOut1(null));
+
+  extensionIfNullOptIn1ForEffect(0);
+  extensionIfNullOptOut1ForEffect(0);
+
+  extensionIfNullOptIn1ForEffect(null);
+  extensionIfNullOptOut1ForEffect(null);
+
+  expect(0, extensionIfNullOptIn2(0));
+  expect(0, extensionIfNullOptOut2(0));
+
+  expect(42, extensionIfNullOptIn2(null));
+  expect(42, extensionIfNullOptOut2(null));
+
+  extensionIfNullOptIn2ForEffect(0);
+  extensionIfNullOptOut2ForEffect(0);
+
+  extensionIfNullOptIn2ForEffect(null);
+  extensionIfNullOptOut2ForEffect(null);
+
+  expect(0, ifNullIndexSetOptIn(0));
+  expect(0, ifNullIndexSetOptOut(0));
+
+  expect(42, ifNullIndexSetOptIn(null));
+  expect(42, ifNullIndexSetOptOut(null));
+
+  ifNullIndexSetOptInForEffect(0);
+  ifNullIndexSetOptOutForEffect(0);
+
+  ifNullIndexSetOptInForEffect(null);
+  ifNullIndexSetOptOutForEffect(null);
+
+  expect(0, ifNullPropertySetOptIn(0));
+  expect(0, ifNullPropertySetOptOut(0));
+
+  expect(42, ifNullPropertySetOptIn(null));
+  expect(42, ifNullPropertySetOptOut(null));
+
+  ifNullPropertySetOptInForEffect(0);
+  ifNullPropertySetOptOutForEffect(0);
+
+  ifNullPropertySetOptInForEffect(null);
+  ifNullPropertySetOptOutForEffect(null);
+
+  expect(0, ifNullSetOptIn(0));
+  expect(0, ifNullSetOptOut(0));
+
+  expect(42, ifNullSetOptIn(null));
+  expect(42, ifNullSetOptOut(null));
+
+  ifNullSetOptInForEffect(0);
+  ifNullSetOptOutForEffect(0);
+
+  ifNullSetOptInForEffect(null);
+  ifNullSetOptOutForEffect(null);
+
+  expect(0, ifNullSuperIndexSetOptIn(0));
+  expect(0, ifNullSuperIndexSetOptOut(0));
+
+  expect(42, ifNullSuperIndexSetOptIn(null));
+  expect(42, ifNullSuperIndexSetOptOut(null));
+
+  ifNullSuperIndexSetOptInForEffect(0);
+  ifNullSuperIndexSetOptOutForEffect(0);
+
+  ifNullSuperIndexSetOptInForEffect(null);
+  ifNullSuperIndexSetOptOutForEffect(null);
+
+  expect(0, nullAwareIfNullSetOptIn(0));
+  expect(0, nullAwareIfNullSetOptOut(0));
+
+  expect(42, nullAwareIfNullSetOptIn(null));
+  expect(42, nullAwareIfNullSetOptOut(null));
+
+  nullAwareIfNullSetOptInForEffect(0);
+  nullAwareIfNullSetOptOutForEffect(0);
+
+  nullAwareIfNullSetOptInForEffect(null);
+  nullAwareIfNullSetOptOutForEffect(null);
+
+  expect(true, isTestOptIn(0));
+  expect(true, isTestOptOut(0));
+
+  expect(false, isTestOptIn(null));
+  expect(false, isTestOptOut(null));
+
+  expect(false, isNotTestOptIn(0));
+  expect(false, isNotTestOptOut(0));
+
+  expect(true, isNotTestOptIn(null));
+  expect(true, isNotTestOptOut(null));
+
+  expect(true, nullAwareAccess1(0));
+  expect(null, nullAwareAccess1(null));
+
+  promotionToNever(0);
+  promotionToNever(null);
+
+  unnecessaryNullCheck(() => 0);
+  unnecessaryNullCheck(() => null);
+
+  expect(0, unnecessaryIfNull(() => 0, () => 42));
+  expect(42, unnecessaryIfNull(() => null, () => 42));
+
+  unnecessaryIfNullAssign(<int>[0], () => 42);
+  unnecessaryIfNullAssign(<int>[null], () => 42);
+
+  unnecessaryNullAwareAccess(() => 0);
+  unnecessaryNullAwareAccess(() => null);
+
+  throws(() => callReturningNever(() => throw 'foo'), (e) => e == 'foo');
+  var f = () => null;
+  throws(() => callReturningNever(f));
+
+  switchOnEnum(E.e1);
+  switchOnEnum(E.e2);
+  throws(() => switchOnEnum(null));
+
+  switchOnEnumWithBreak(E.e1);
+  switchOnEnumWithBreak(E.e2);
+  throws(() => switchOnEnumWithBreak(null));
+
+  switchOnEnumWithFallThrough1(E.e1);
+  switchOnEnumWithFallThrough1(E.e2);
+  throws(() => switchOnEnumWithFallThrough1(null));
+
+  switchOnEnumWithFallThrough2(E.e1);
+  switchOnEnumWithFallThrough2(E.e2);
+  throws(() => switchOnEnumWithFallThrough2(null));
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw 'Expected $expected, actual $actual';
+}
+
+throws(void f(), [bool Function(Object) testException]) {
+  try {
+    f();
+  } catch (e) {
+    if (testException != null && !testException(e)) {
+      throw 'Unexpected exception: $e';
+    }
+    print(e);
+    return;
+  }
+  throw 'Missing exception.';
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
new file mode 100644
index 0000000..50ce9f2
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.textual_outline.expect
@@ -0,0 +1,49 @@
+// @dart = 2.8
+import 'unsound_checks_lib.dart';
+isNullOptOut1(int i) => i == null;
+isNotNullOptOut1(int i) => i != null;
+isNullOptOut2(int i) => null == i;
+isNotNullOptOut2(int i) => null != i;
+ifNullOptOut(int i) => i ?? 42;
+class OptOutClass1 {}
+extension OptOutExtension ;
+on OptOutClass1 (){}
+extensionIfNullOptOut1(int i) => OptOutExtension(new OptOutClass1())[i] ??= 42;
+extensionIfNullOptOut1ForEffect(int i) {}
+extensionIfNullOptOut2(int i) => new OptOutClass1()[i] ??= 42;
+extensionIfNullOptOut2ForEffect(int i) {}
+class OptOutClass2 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+ifNullIndexSetOptOut(int i) => new OptOutClass2()[i] ??= 42;
+ifNullIndexSetOptOutForEffect(int i) {}
+class OptOutClass3 {
+  int field;
+  OptOutClass3(this.field);
+}
+ifNullPropertySetOptOut(int i) => new OptOutClass3(i).field ??= 42;
+ifNullPropertySetOptOutForEffect(int i) {}
+ifNullSetOptOut(int i) => i ??= 42;
+ifNullSetOptOutForEffect(int i) {}
+class OptOutSuperClass4 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+class OptOutClass4 extends OptOutSuperClass4 {
+  method(int i) => super[i] ??= 42;
+  methodForEffect(int i) {}
+}
+ifNullSuperIndexSetOptOut(int i) => new OptOutClass4().method(i);
+ifNullSuperIndexSetOptOutForEffect(int i) {}
+class OptOutClass5 {
+  int field;
+  OptOutClass5(this.field);
+}
+nullAwareIfNullSetOptOut(int i) {}
+nullAwareIfNullSetOptOutForEffect(int i) {}
+isTestOptOut(int i) => i is int;
+isNotTestOptOut(int i) => i is! int;
+main() {}
+expect(expected, actual) {}
+throws(void f(), [bool Function(Object) testException]) {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
new file mode 100644
index 0000000..06a5216
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.expect
@@ -0,0 +1,621 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "unsound_checks_lib.dart" as uns;
+
+import "org-dartlang-testcase:///unsound_checks_lib.dart";
+
+class OptOutClass1 extends core::Object {
+  synthetic constructor •() → self::OptOutClass1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass2 extends core::Object {
+  synthetic constructor •() → self::OptOutClass2*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return index;
+  operator []=(core::int* index, core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass3 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::OptOutClass3*
+    : self::OptOutClass3::field = field, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutSuperClass4 extends core::Object {
+  synthetic constructor •() → self::OptOutSuperClass4*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return index;
+  operator []=(core::int* index, core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass4 extends self::OptOutSuperClass4 {
+  synthetic constructor •() → self::OptOutClass4*
+    : super self::OptOutSuperClass4::•()
+    ;
+  method method(core::int* i) → dynamic
+    return let final core::int* #t1 = i in let final core::int* #t2 = super.{self::OptOutSuperClass4::[]}(#t1) in #t2.{core::num::==}(null) ?{core::int*} let final core::int* #t3 = 42 in let final void #t4 = super.{self::OptOutSuperClass4::[]=}(#t1, #t3) in #t3 : #t2;
+  method methodForEffect(core::int* i) → dynamic {
+    let final core::int* #t5 = i in super.{self::OptOutSuperClass4::[]}(#t5).{core::num::==}(null) ?{core::int*} super.{self::OptOutSuperClass4::[]=}(#t5, 42) : null;
+  }
+}
+class OptOutClass5 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::OptOutClass5*
+    : self::OptOutClass5::field = field, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension OptOutExtension on self::OptOutClass1* {
+  operator [] = self::OptOutExtension|[];
+  operator []= = self::OptOutExtension|[]=;
+}
+static method isNullOptOut1(core::int* i) → dynamic
+  return i.{core::num::==}(null);
+static method isNotNullOptOut1(core::int* i) → dynamic
+  return !i.{core::num::==}(null);
+static method isNullOptOut2(core::int* i) → dynamic
+  return null.{core::Object::==}(i);
+static method isNotNullOptOut2(core::int* i) → dynamic
+  return !null.{core::Object::==}(i);
+static method ifNullOptOut(core::int* i) → dynamic
+  return let final core::int* #t6 = i in #t6.{core::num::==}(null) ?{core::int*} 42 : #t6;
+static method OptOutExtension|[](final self::OptOutClass1* #this, core::int* index) → core::int*
+  return index;
+static method OptOutExtension|[]=(final self::OptOutClass1* #this, core::int* index, core::int* value) → void {}
+static method extensionIfNullOptOut1(core::int* i) → dynamic
+  return let final self::OptOutClass1* #t7 = new self::OptOutClass1::•() in let final core::int* #t8 = i in let final core::int* #t9 = self::OptOutExtension|[](#t7, #t8) in #t9.{core::num::==}(null) ?{core::int*} let final core::int* #t10 = 42 in let final void #t11 = self::OptOutExtension|[]=(#t7, #t8, #t10) in #t10 : #t9;
+static method extensionIfNullOptOut1ForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass1* #t12 = new self::OptOutClass1::•() in let final core::int* #t13 = i in self::OptOutExtension|[](#t12, #t13).{core::num::==}(null) ?{core::int*} self::OptOutExtension|[]=(#t12, #t13, 42) : null;
+}
+static method extensionIfNullOptOut2(core::int* i) → dynamic
+  return let final self::OptOutClass1* #t14 = new self::OptOutClass1::•() in let final core::int* #t15 = i in let final core::int* #t16 = self::OptOutExtension|[](#t14, #t15) in #t16.{core::num::==}(null) ?{core::int*} let final core::int* #t17 = 42 in let final void #t18 = self::OptOutExtension|[]=(#t14, #t15, #t17) in #t17 : #t16;
+static method extensionIfNullOptOut2ForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass1* #t19 = new self::OptOutClass1::•() in let final core::int* #t20 = i in self::OptOutExtension|[](#t19, #t20).{core::num::==}(null) ?{core::int*} self::OptOutExtension|[]=(#t19, #t20, 42) : null;
+}
+static method ifNullIndexSetOptOut(core::int* i) → dynamic
+  return let final self::OptOutClass2* #t21 = new self::OptOutClass2::•() in let final core::int* #t22 = i in let final core::int* #t23 = #t21.{self::OptOutClass2::[]}(#t22) in #t23.{core::num::==}(null) ?{core::int*} let final core::int* #t24 = 42 in let final void #t25 = #t21.{self::OptOutClass2::[]=}(#t22, #t24) in #t24 : #t23;
+static method ifNullIndexSetOptOutForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass2* #t26 = new self::OptOutClass2::•() in let final core::int* #t27 = i in #t26.{self::OptOutClass2::[]}(#t27).{core::num::==}(null) ?{core::int*} #t26.{self::OptOutClass2::[]=}(#t27, 42) : null;
+}
+static method ifNullPropertySetOptOut(core::int* i) → dynamic
+  return let final self::OptOutClass3* #t28 = new self::OptOutClass3::•(i) in let final core::int* #t29 = #t28.{self::OptOutClass3::field} in #t29.{core::num::==}(null) ?{core::int*} #t28.{self::OptOutClass3::field} = 42 : #t29;
+static method ifNullPropertySetOptOutForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass3* #t30 = new self::OptOutClass3::•(i) in #t30.{self::OptOutClass3::field}.{core::num::==}(null) ?{core::int*} #t30.{self::OptOutClass3::field} = 42 : null;
+}
+static method ifNullSetOptOut(core::int* i) → dynamic
+  return let final core::int* #t31 = i in #t31.{core::num::==}(null) ?{core::int*} i = 42 : #t31;
+static method ifNullSetOptOutForEffect(core::int* i) → dynamic {
+  i.{core::num::==}(null) ?{core::int*} i = 42 : null;
+}
+static method ifNullSuperIndexSetOptOut(core::int* i) → dynamic
+  return new self::OptOutClass4::•().{self::OptOutClass4::method}(i);
+static method ifNullSuperIndexSetOptOutForEffect(core::int* i) → dynamic {
+  new self::OptOutClass4::•().{self::OptOutClass4::methodForEffect}(i);
+}
+static method nullAwareIfNullSetOptOut(core::int* i) → dynamic {
+  self::OptOutClass5* o = new self::OptOutClass5::•(i);
+  return let final self::OptOutClass5* #t32 = o in #t32.{self::OptOutClass5::==}(null) ?{core::int*} null : let final core::int* #t33 = #t32.{self::OptOutClass5::field} in #t33.{core::num::==}(null) ?{core::int*} #t32.{self::OptOutClass5::field} = 42 : #t33;
+}
+static method nullAwareIfNullSetOptOutForEffect(core::int* i) → dynamic {
+  self::OptOutClass5* o = new self::OptOutClass5::•(i);
+  let final self::OptOutClass5* #t34 = o in #t34.{self::OptOutClass5::==}(null) ?{core::int*} null : #t34.{self::OptOutClass5::field}.{core::num::==}(null) ?{core::int*} #t34.{self::OptOutClass5::field} = 42 : null;
+}
+static method isTestOptOut(core::int* i) → dynamic
+  return i is core::int*;
+static method isNotTestOptOut(core::int* i) → dynamic
+  return !(i is core::int*);
+static method main() → dynamic {
+  self::expect(false, uns::isNullOptIn1(0));
+  self::expect(false, self::isNullOptOut1(0));
+  self::expect(true, uns::isNullOptIn1(null));
+  self::expect(true, self::isNullOptOut1(null));
+  self::expect(true, uns::isNotNullOptIn1(0));
+  self::expect(true, self::isNotNullOptOut1(0));
+  self::expect(false, uns::isNotNullOptIn1(null));
+  self::expect(false, self::isNotNullOptOut1(null));
+  self::expect(false, uns::isNullOptIn2(0));
+  self::expect(false, self::isNullOptOut2(0));
+  self::expect(true, uns::isNullOptIn2(null));
+  self::expect(true, self::isNullOptOut2(null));
+  self::expect(true, uns::isNotNullOptIn2(0));
+  self::expect(true, self::isNotNullOptOut2(0));
+  self::expect(false, uns::isNotNullOptIn2(null));
+  self::expect(false, self::isNotNullOptOut2(null));
+  self::expect(0, uns::ifNullOptIn(0));
+  self::expect(0, self::ifNullOptOut(0));
+  self::expect(42, uns::ifNullOptIn(null));
+  self::expect(42, self::ifNullOptOut(null));
+  self::expect(0, uns::extensionIfNullOptIn1(0));
+  self::expect(0, self::extensionIfNullOptOut1(0));
+  self::expect(42, uns::extensionIfNullOptIn1(null));
+  self::expect(42, self::extensionIfNullOptOut1(null));
+  uns::extensionIfNullOptIn1ForEffect(0);
+  self::extensionIfNullOptOut1ForEffect(0);
+  uns::extensionIfNullOptIn1ForEffect(null);
+  self::extensionIfNullOptOut1ForEffect(null);
+  self::expect(0, uns::extensionIfNullOptIn2(0));
+  self::expect(0, self::extensionIfNullOptOut2(0));
+  self::expect(42, uns::extensionIfNullOptIn2(null));
+  self::expect(42, self::extensionIfNullOptOut2(null));
+  uns::extensionIfNullOptIn2ForEffect(0);
+  self::extensionIfNullOptOut2ForEffect(0);
+  uns::extensionIfNullOptIn2ForEffect(null);
+  self::extensionIfNullOptOut2ForEffect(null);
+  self::expect(0, uns::ifNullIndexSetOptIn(0));
+  self::expect(0, self::ifNullIndexSetOptOut(0));
+  self::expect(42, uns::ifNullIndexSetOptIn(null));
+  self::expect(42, self::ifNullIndexSetOptOut(null));
+  uns::ifNullIndexSetOptInForEffect(0);
+  self::ifNullIndexSetOptOutForEffect(0);
+  uns::ifNullIndexSetOptInForEffect(null);
+  self::ifNullIndexSetOptOutForEffect(null);
+  self::expect(0, uns::ifNullPropertySetOptIn(0));
+  self::expect(0, self::ifNullPropertySetOptOut(0));
+  self::expect(42, uns::ifNullPropertySetOptIn(null));
+  self::expect(42, self::ifNullPropertySetOptOut(null));
+  uns::ifNullPropertySetOptInForEffect(0);
+  self::ifNullPropertySetOptOutForEffect(0);
+  uns::ifNullPropertySetOptInForEffect(null);
+  self::ifNullPropertySetOptOutForEffect(null);
+  self::expect(0, uns::ifNullSetOptIn(0));
+  self::expect(0, self::ifNullSetOptOut(0));
+  self::expect(42, uns::ifNullSetOptIn(null));
+  self::expect(42, self::ifNullSetOptOut(null));
+  uns::ifNullSetOptInForEffect(0);
+  self::ifNullSetOptOutForEffect(0);
+  uns::ifNullSetOptInForEffect(null);
+  self::ifNullSetOptOutForEffect(null);
+  self::expect(0, uns::ifNullSuperIndexSetOptIn(0));
+  self::expect(0, self::ifNullSuperIndexSetOptOut(0));
+  self::expect(42, uns::ifNullSuperIndexSetOptIn(null));
+  self::expect(42, self::ifNullSuperIndexSetOptOut(null));
+  uns::ifNullSuperIndexSetOptInForEffect(0);
+  self::ifNullSuperIndexSetOptOutForEffect(0);
+  uns::ifNullSuperIndexSetOptInForEffect(null);
+  self::ifNullSuperIndexSetOptOutForEffect(null);
+  self::expect(0, uns::nullAwareIfNullSetOptIn(0));
+  self::expect(0, self::nullAwareIfNullSetOptOut(0));
+  self::expect(42, uns::nullAwareIfNullSetOptIn(null));
+  self::expect(42, self::nullAwareIfNullSetOptOut(null));
+  uns::nullAwareIfNullSetOptInForEffect(0);
+  self::nullAwareIfNullSetOptOutForEffect(0);
+  uns::nullAwareIfNullSetOptInForEffect(null);
+  self::nullAwareIfNullSetOptOutForEffect(null);
+  self::expect(true, uns::isTestOptIn(0));
+  self::expect(true, self::isTestOptOut(0));
+  self::expect(false, uns::isTestOptIn(null));
+  self::expect(false, self::isTestOptOut(null));
+  self::expect(false, uns::isNotTestOptIn(0));
+  self::expect(false, self::isNotTestOptOut(0));
+  self::expect(true, uns::isNotTestOptIn(null));
+  self::expect(true, self::isNotTestOptOut(null));
+  self::expect(true, uns::nullAwareAccess1(0));
+  self::expect(null, uns::nullAwareAccess1(null));
+  uns::promotionToNever(0);
+  uns::promotionToNever(null);
+  uns::unnecessaryNullCheck(() → core::int* => 0);
+  uns::unnecessaryNullCheck(() → core::Null? => null);
+  self::expect(0, uns::unnecessaryIfNull(() → core::int* => 0, () → core::int* => 42));
+  self::expect(42, uns::unnecessaryIfNull(() → core::Null? => null, () → core::int* => 42));
+  uns::unnecessaryIfNullAssign(<core::int*>[0], () → core::int* => 42);
+  uns::unnecessaryIfNullAssign(<core::int*>[null], () → core::int* => 42);
+  uns::unnecessaryNullAwareAccess(() → core::int* => 0);
+  uns::unnecessaryNullAwareAccess(() → core::Null? => null);
+  self::throws(() → dynamic => uns::callReturningNever(() → <BottomType>=> throw "foo"), (core::Object* e) → core::bool* => e.{core::Object::==}("foo"));
+  () →* core::Null? f = () → core::Null? => null;
+  self::throws(() → dynamic => uns::callReturningNever(f));
+  uns::switchOnEnum(#C3);
+  uns::switchOnEnum(#C6);
+  self::throws(() → dynamic => uns::switchOnEnum(null));
+  uns::switchOnEnumWithBreak(#C3);
+  uns::switchOnEnumWithBreak(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithBreak(null));
+  uns::switchOnEnumWithFallThrough1(#C3);
+  uns::switchOnEnumWithFallThrough1(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithFallThrough1(null));
+  uns::switchOnEnumWithFallThrough2(#C3);
+  uns::switchOnEnumWithFallThrough2(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithFallThrough2(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() →* void f, [(core::Object*) →* core::bool* testException = #C7]) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic e) {
+    if(!testException.{core::Object::==}(null) && !testException.call(e)) {
+      throw "Unexpected exception: ${e}";
+    }
+    core::print(e);
+    return;
+  }
+  throw "Missing exception.";
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:13:23: Warning: Operand of null-aware operation '??' has type 'int' which excludes null.
+// ifNullOptIn(int i) => i ?? 42;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:22:66: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// extensionIfNullOptIn1(int i) => OptInExtension(new OptInClass1())[i] ??= 42;
+//                                                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:25:36: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   OptInExtension(new OptInClass1())[i] ??= 42;
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:28:50: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// extensionIfNullOptIn2(int i) => new OptInClass1()[i] ??= 42;
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:31:20: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass1()[i] ??= 42;
+//                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:39:48: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullIndexSetOptIn(int i) => new OptInClass2()[i] ??= 42;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:42:20: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass2()[i] ??= 42;
+//                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:51:53: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullPropertySetOptIn(int i) => new OptInClass3(i).field ??= 42;
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:54:22: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass3(i).field ??= 42;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:57:26: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullSetOptIn(int i) => i ??= 42;
+//                          ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:60:3: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   i ??= 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:69:25: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   method(int i) => super[i] ??= 42;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:71:10: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//     super[i] ??= 42;
+//          ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:113:28: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+// nullAwareAccess1(int i) => i?.isEven;
+//                            ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:116:3: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+//   i?.isEven;
+//   ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:128:11: Warning: Operand of null-aware operation '??' has type 'int' which excludes null.
+//   return f() ??
+//           ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:134:4: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   x[0] ??= f();
+//    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:138:4: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+//   f()?.gcd(0); // Should not throw if `f` returns null
+//    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:195:10: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   return {...d}; // Should not throw ReachabilityError.
+//          ^
+//
+import self as uns;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class OptInClass1 extends core::Object {
+  synthetic constructor •() → uns::OptInClass1
+    : super core::Object::•()
+    ;
+}
+class OptInClass2 extends core::Object {
+  synthetic constructor •() → uns::OptInClass2
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator []=(core::int index, core::int value) → void {}
+}
+class OptInClass3 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → uns::OptInClass3
+    : uns::OptInClass3::field = field, super core::Object::•()
+    ;
+}
+class OptInSuperClass4 extends core::Object {
+  synthetic constructor •() → uns::OptInSuperClass4
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator []=(core::int index, core::int value) → void {}
+}
+class OptInClass4 extends uns::OptInSuperClass4 {
+  synthetic constructor •() → uns::OptInClass4
+    : super uns::OptInSuperClass4::•()
+    ;
+  method method(core::int i) → dynamic
+    return let final core::int #t35 = i in let final core::int #t36 = super.{uns::OptInSuperClass4::[]}(#t35) in #t36.{core::num::==}(null) ?{core::int} let final core::int #t37 = 42 in let final void #t38 = super.{uns::OptInSuperClass4::[]=}(#t35, #t37) in #t37 : #t36;
+  method methodForEffect(core::int i) → dynamic {
+    let final core::int #t39 = i in super.{uns::OptInSuperClass4::[]}(#t39).{core::num::==}(null) ?{core::int} super.{uns::OptInSuperClass4::[]=}(#t39, 42) : null;
+  }
+}
+class OptInClass5 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → uns::OptInClass5
+    : uns::OptInClass5::field = field, super core::Object::•()
+    ;
+}
+class OptInClass6a extends core::Object {
+  final field uns::OptInClass6b cls;
+  constructor •(uns::OptInClass6b cls) → uns::OptInClass6a
+    : uns::OptInClass6a::cls = cls, super core::Object::•()
+    ;
+}
+class OptInClass6b extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → uns::OptInClass6b
+    : uns::OptInClass6b::field = field, super core::Object::•()
+    ;
+}
+class E extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<uns::E> values = #C8;
+  static const field uns::E e1 = #C3;
+  static const field uns::E e2 = #C6;
+  const constructor •(core::int index, core::String _name) → uns::E
+    : uns::E::index = index, uns::E::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{uns::E::_name};
+}
+extension OptInExtension on uns::OptInClass1 {
+  operator [] = uns::OptInExtension|[];
+  operator []= = uns::OptInExtension|[]=;
+}
+static method isNullOptIn1(core::int i) → dynamic
+  return i.{core::num::==}(null);
+static method isNotNullOptIn1(core::int i) → dynamic
+  return !i.{core::num::==}(null);
+static method isNullOptIn2(core::int i) → dynamic
+  return null.{core::Object::==}(i);
+static method isNotNullOptIn2(core::int i) → dynamic
+  return !null.{core::Object::==}(i);
+static method ifNullOptIn(core::int i) → dynamic
+  return let final core::int #t40 = i in #t40.{core::num::==}(null) ?{core::int} 42 : #t40;
+static method OptInExtension|[](final uns::OptInClass1 #this, core::int index) → core::int
+  return index;
+static method OptInExtension|[]=(final uns::OptInClass1 #this, core::int index, core::int value) → void {}
+static method extensionIfNullOptIn1(core::int i) → dynamic
+  return let final uns::OptInClass1 #t41 = new uns::OptInClass1::•() in let final core::int #t42 = i in let final core::int #t43 = uns::OptInExtension|[](#t41, #t42) in #t43.{core::num::==}(null) ?{core::int} let final core::int #t44 = 42 in let final void #t45 = uns::OptInExtension|[]=(#t41, #t42, #t44) in #t44 : #t43;
+static method extensionIfNullOptIn1ForEffect(core::int i) → dynamic {
+  let final uns::OptInClass1 #t46 = new uns::OptInClass1::•() in let final core::int #t47 = i in uns::OptInExtension|[](#t46, #t47).{core::num::==}(null) ?{core::int} uns::OptInExtension|[]=(#t46, #t47, 42) : null;
+}
+static method extensionIfNullOptIn2(core::int i) → dynamic
+  return let final uns::OptInClass1 #t48 = new uns::OptInClass1::•() in let final core::int #t49 = i in let final core::int #t50 = uns::OptInExtension|[](#t48, #t49) in #t50.{core::num::==}(null) ?{core::int} let final core::int #t51 = 42 in let final void #t52 = uns::OptInExtension|[]=(#t48, #t49, #t51) in #t51 : #t50;
+static method extensionIfNullOptIn2ForEffect(core::int i) → dynamic {
+  let final uns::OptInClass1 #t53 = new uns::OptInClass1::•() in let final core::int #t54 = i in uns::OptInExtension|[](#t53, #t54).{core::num::==}(null) ?{core::int} uns::OptInExtension|[]=(#t53, #t54, 42) : null;
+}
+static method ifNullIndexSetOptIn(core::int i) → dynamic
+  return let final uns::OptInClass2 #t55 = new uns::OptInClass2::•() in let final core::int #t56 = i in let final core::int #t57 = #t55.{uns::OptInClass2::[]}(#t56) in #t57.{core::num::==}(null) ?{core::int} let final core::int #t58 = 42 in let final void #t59 = #t55.{uns::OptInClass2::[]=}(#t56, #t58) in #t58 : #t57;
+static method ifNullIndexSetOptInForEffect(core::int i) → dynamic {
+  let final uns::OptInClass2 #t60 = new uns::OptInClass2::•() in let final core::int #t61 = i in #t60.{uns::OptInClass2::[]}(#t61).{core::num::==}(null) ?{core::int} #t60.{uns::OptInClass2::[]=}(#t61, 42) : null;
+}
+static method ifNullPropertySetOptIn(core::int i) → dynamic
+  return let final uns::OptInClass3 #t62 = new uns::OptInClass3::•(i) in let final core::int #t63 = #t62.{uns::OptInClass3::field} in #t63.{core::num::==}(null) ?{core::int} #t62.{uns::OptInClass3::field} = 42 : #t63;
+static method ifNullPropertySetOptInForEffect(core::int i) → dynamic {
+  let final uns::OptInClass3 #t64 = new uns::OptInClass3::•(i) in #t64.{uns::OptInClass3::field}.{core::num::==}(null) ?{core::int} #t64.{uns::OptInClass3::field} = 42 : null;
+}
+static method ifNullSetOptIn(core::int i) → dynamic
+  return let final core::int #t65 = i in #t65.{core::num::==}(null) ?{core::int} i = 42 : #t65;
+static method ifNullSetOptInForEffect(core::int i) → dynamic {
+  i.{core::num::==}(null) ?{core::int} i = 42 : null;
+}
+static method ifNullSuperIndexSetOptIn(core::int i) → dynamic
+  return new uns::OptInClass4::•().{uns::OptInClass4::method}(i);
+static method ifNullSuperIndexSetOptInForEffect(core::int i) → dynamic {
+  new uns::OptInClass4::•().{uns::OptInClass4::methodForEffect}(i);
+}
+static method nullAwareIfNullSetOptIn(core::int i) → dynamic {
+  uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
+  return let final uns::OptInClass5? #t66 = o in #t66.{core::Object::==}(null) ?{core::int?} null : let final core::int #t67 = #t66.{uns::OptInClass5::field} in #t67.{core::num::==}(null) ?{core::int} #t66.{uns::OptInClass5::field} = 42 : #t67;
+}
+static method nullAwareIfNullSetOptInForEffect(core::int i) → dynamic {
+  uns::OptInClass5? o = new uns::OptInClass5::•(i) as{ForNonNullableByDefault} uns::OptInClass5?;
+  let final uns::OptInClass5? #t68 = o in #t68.{core::Object::==}(null) ?{core::int?} null : #t68.{uns::OptInClass5::field}.{core::num::==}(null) ?{core::int} #t68.{uns::OptInClass5::field} = 42 : null;
+}
+static method isTestOptIn(core::int i) → dynamic
+  return i is{ForNonNullableByDefault} core::int;
+static method isNotTestOptIn(core::int i) → dynamic
+  return !(i is{ForNonNullableByDefault} core::int);
+static method nullAwareAccess1(core::int i) → dynamic
+  return let final core::int #t69 = i in #t69.{core::num::==}(null) ?{core::bool?} null : #t69.{core::int::isEven};
+static method nullAwareAccessForEffect1(core::int i) → dynamic {
+  let final core::int #t70 = i in #t70.{core::num::==}(null) ?{core::bool?} null : #t70.{core::int::isEven};
+}
+static method promotionToNever(core::int i) → dynamic {
+  if(i is{ForNonNullableByDefault} core::int)
+    return;
+}
+static method unnecessaryNullCheck(() → core::int f) → dynamic {
+  if(!f.call().{core::num::==}(null))
+    return;
+}
+static method unnecessaryIfNull(() → core::int f, () → core::int g) → dynamic {
+  return let final core::int #t71 = f.call() in #t71.{core::num::==}(null) ?{core::int} g.call() : #t71;
+}
+static method unnecessaryIfNullAssign(core::List<core::int> x, () → core::int f) → dynamic {
+  let final core::List<core::int> #t72 = x in let final core::int #t73 = 0 in #t72.{core::List::[]}(#t73).{core::num::==}(null) ?{core::int} #t72.{core::List::[]=}(#t73, f.call()) : null;
+}
+static method unnecessaryNullAwareAccess(() → core::int f) → dynamic {
+  let final core::int #t74 = f.call() in #t74.{core::num::==}(null) ?{core::int?} null : #t74.{core::int::gcd}(0);
+}
+static method callReturningNever(() → Never f) → dynamic {
+  let final Never #t75 = f.call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+}
+static method switchOnEnum(uns::E e) → dynamic {
+  switch(e) {
+    #L1:
+    case #C3:
+      {
+        return;
+      }
+    #L2:
+    case #C6:
+      {
+        return;
+      }
+    #L3:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithBreak(uns::E e) → dynamic {
+  #L4:
+  switch(e) {
+    #L5:
+    case #C3:
+      {
+        break #L4;
+      }
+    #L6:
+    case #C6:
+      {
+        break #L4;
+      }
+    #L7:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithFallThrough1(uns::E e) → dynamic {
+  #L8:
+  switch(e) {
+    #L9:
+    case #C3:
+      {
+        break #L8;
+      }
+    #L10:
+    case #C6:
+      {
+        break #L8;
+      }
+    #L11:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithFallThrough2(uns::E e) → dynamic {
+  #L12:
+  switch(e) {
+    #L13:
+    case #C3:
+    case #C6:
+      {
+        break #L12;
+      }
+    #L14:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method handleThrow() → dynamic {
+  throw "";
+}
+static method handleRethrow() → dynamic {
+  try {
+    uns::handleThrow();
+  }
+  on core::Object catch(final core::Object _) {
+    rethrow;
+  }
+}
+static method handleInvalid(dynamic d) → dynamic {
+  return invalid-expression "pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:195:10: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  return {...d}; // Should not throw ReachabilityError.
+         ^";
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "E.e1"
+  #C3 = uns::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "E.e2"
+  #C6 = uns::E {index:#C4, _name:#C5}
+  #C7 = null
+  #C8 = <uns::E*>[#C3, #C6]
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
new file mode 100644
index 0000000..908eb54
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks.dart.weak.transformed.expect
@@ -0,0 +1,642 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "unsound_checks_lib.dart" as uns;
+
+import "org-dartlang-testcase:///unsound_checks_lib.dart";
+
+class OptOutClass1 extends core::Object {
+  synthetic constructor •() → self::OptOutClass1*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass2 extends core::Object {
+  synthetic constructor •() → self::OptOutClass2*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return index;
+  operator []=(core::int* index, core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass3 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::OptOutClass3*
+    : self::OptOutClass3::field = field, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutSuperClass4 extends core::Object {
+  synthetic constructor •() → self::OptOutSuperClass4*
+    : super core::Object::•()
+    ;
+  operator [](core::int* index) → core::int*
+    return index;
+  operator []=(core::int* index, core::int* value) → void {}
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+class OptOutClass4 extends self::OptOutSuperClass4 {
+  synthetic constructor •() → self::OptOutClass4*
+    : super self::OptOutSuperClass4::•()
+    ;
+  method method(core::int* i) → dynamic
+    return let final core::int* #t1 = i in let final core::int* #t2 = super.{self::OptOutSuperClass4::[]}(#t1) in #t2.{core::num::==}(null) ?{core::int*} let final core::int* #t3 = 42 in let final void #t4 = super.{self::OptOutSuperClass4::[]=}(#t1, #t3) in #t3 : #t2;
+  method methodForEffect(core::int* i) → dynamic {
+    let final core::int* #t5 = i in super.{self::OptOutSuperClass4::[]}(#t5).{core::num::==}(null) ?{core::int*} super.{self::OptOutSuperClass4::[]=}(#t5, 42) : null;
+  }
+}
+class OptOutClass5 extends core::Object {
+  field core::int* field;
+  constructor •(core::int* field) → self::OptOutClass5*
+    : self::OptOutClass5::field = field, super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
+  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
+  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
+  abstract member-signature method toString() → core::String*; -> core::Object::toString
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
+  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+}
+extension OptOutExtension on self::OptOutClass1* {
+  operator [] = self::OptOutExtension|[];
+  operator []= = self::OptOutExtension|[]=;
+}
+static method isNullOptOut1(core::int* i) → dynamic
+  return i.{core::num::==}(null);
+static method isNotNullOptOut1(core::int* i) → dynamic
+  return !i.{core::num::==}(null);
+static method isNullOptOut2(core::int* i) → dynamic
+  return null.{core::Object::==}(i);
+static method isNotNullOptOut2(core::int* i) → dynamic
+  return !null.{core::Object::==}(i);
+static method ifNullOptOut(core::int* i) → dynamic
+  return let final core::int* #t6 = i in #t6.{core::num::==}(null) ?{core::int*} 42 : #t6;
+static method OptOutExtension|[](final self::OptOutClass1* #this, core::int* index) → core::int*
+  return index;
+static method OptOutExtension|[]=(final self::OptOutClass1* #this, core::int* index, core::int* value) → void {}
+static method extensionIfNullOptOut1(core::int* i) → dynamic
+  return let final self::OptOutClass1* #t7 = new self::OptOutClass1::•() in let final core::int* #t8 = i in let final core::int* #t9 = self::OptOutExtension|[](#t7, #t8) in #t9.{core::num::==}(null) ?{core::int*} let final core::int* #t10 = 42 in let final void #t11 = self::OptOutExtension|[]=(#t7, #t8, #t10) in #t10 : #t9;
+static method extensionIfNullOptOut1ForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass1* #t12 = new self::OptOutClass1::•() in let final core::int* #t13 = i in self::OptOutExtension|[](#t12, #t13).{core::num::==}(null) ?{core::int*} self::OptOutExtension|[]=(#t12, #t13, 42) : null;
+}
+static method extensionIfNullOptOut2(core::int* i) → dynamic
+  return let final self::OptOutClass1* #t14 = new self::OptOutClass1::•() in let final core::int* #t15 = i in let final core::int* #t16 = self::OptOutExtension|[](#t14, #t15) in #t16.{core::num::==}(null) ?{core::int*} let final core::int* #t17 = 42 in let final void #t18 = self::OptOutExtension|[]=(#t14, #t15, #t17) in #t17 : #t16;
+static method extensionIfNullOptOut2ForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass1* #t19 = new self::OptOutClass1::•() in let final core::int* #t20 = i in self::OptOutExtension|[](#t19, #t20).{core::num::==}(null) ?{core::int*} self::OptOutExtension|[]=(#t19, #t20, 42) : null;
+}
+static method ifNullIndexSetOptOut(core::int* i) → dynamic
+  return let final self::OptOutClass2* #t21 = new self::OptOutClass2::•() in let final core::int* #t22 = i in let final core::int* #t23 = #t21.{self::OptOutClass2::[]}(#t22) in #t23.{core::num::==}(null) ?{core::int*} let final core::int* #t24 = 42 in let final void #t25 = #t21.{self::OptOutClass2::[]=}(#t22, #t24) in #t24 : #t23;
+static method ifNullIndexSetOptOutForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass2* #t26 = new self::OptOutClass2::•() in let final core::int* #t27 = i in #t26.{self::OptOutClass2::[]}(#t27).{core::num::==}(null) ?{core::int*} #t26.{self::OptOutClass2::[]=}(#t27, 42) : null;
+}
+static method ifNullPropertySetOptOut(core::int* i) → dynamic
+  return let final self::OptOutClass3* #t28 = new self::OptOutClass3::•(i) in let final core::int* #t29 = #t28.{self::OptOutClass3::field} in #t29.{core::num::==}(null) ?{core::int*} #t28.{self::OptOutClass3::field} = 42 : #t29;
+static method ifNullPropertySetOptOutForEffect(core::int* i) → dynamic {
+  let final self::OptOutClass3* #t30 = new self::OptOutClass3::•(i) in #t30.{self::OptOutClass3::field}.{core::num::==}(null) ?{core::int*} #t30.{self::OptOutClass3::field} = 42 : null;
+}
+static method ifNullSetOptOut(core::int* i) → dynamic
+  return let final core::int* #t31 = i in #t31.{core::num::==}(null) ?{core::int*} i = 42 : #t31;
+static method ifNullSetOptOutForEffect(core::int* i) → dynamic {
+  i.{core::num::==}(null) ?{core::int*} i = 42 : null;
+}
+static method ifNullSuperIndexSetOptOut(core::int* i) → dynamic
+  return new self::OptOutClass4::•().{self::OptOutClass4::method}(i);
+static method ifNullSuperIndexSetOptOutForEffect(core::int* i) → dynamic {
+  new self::OptOutClass4::•().{self::OptOutClass4::methodForEffect}(i);
+}
+static method nullAwareIfNullSetOptOut(core::int* i) → dynamic {
+  self::OptOutClass5* o = new self::OptOutClass5::•(i);
+  return let final self::OptOutClass5* #t32 = o in #t32.{self::OptOutClass5::==}(null) ?{core::int*} null : let final core::int* #t33 = #t32.{self::OptOutClass5::field} in #t33.{core::num::==}(null) ?{core::int*} #t32.{self::OptOutClass5::field} = 42 : #t33;
+}
+static method nullAwareIfNullSetOptOutForEffect(core::int* i) → dynamic {
+  self::OptOutClass5* o = new self::OptOutClass5::•(i);
+  let final self::OptOutClass5* #t34 = o in #t34.{self::OptOutClass5::==}(null) ?{core::int*} null : #t34.{self::OptOutClass5::field}.{core::num::==}(null) ?{core::int*} #t34.{self::OptOutClass5::field} = 42 : null;
+}
+static method isTestOptOut(core::int* i) → dynamic
+  return i is core::int*;
+static method isNotTestOptOut(core::int* i) → dynamic
+  return !(i is core::int*);
+static method main() → dynamic {
+  self::expect(false, uns::isNullOptIn1(0));
+  self::expect(false, self::isNullOptOut1(0));
+  self::expect(true, uns::isNullOptIn1(null));
+  self::expect(true, self::isNullOptOut1(null));
+  self::expect(true, uns::isNotNullOptIn1(0));
+  self::expect(true, self::isNotNullOptOut1(0));
+  self::expect(false, uns::isNotNullOptIn1(null));
+  self::expect(false, self::isNotNullOptOut1(null));
+  self::expect(false, uns::isNullOptIn2(0));
+  self::expect(false, self::isNullOptOut2(0));
+  self::expect(true, uns::isNullOptIn2(null));
+  self::expect(true, self::isNullOptOut2(null));
+  self::expect(true, uns::isNotNullOptIn2(0));
+  self::expect(true, self::isNotNullOptOut2(0));
+  self::expect(false, uns::isNotNullOptIn2(null));
+  self::expect(false, self::isNotNullOptOut2(null));
+  self::expect(0, uns::ifNullOptIn(0));
+  self::expect(0, self::ifNullOptOut(0));
+  self::expect(42, uns::ifNullOptIn(null));
+  self::expect(42, self::ifNullOptOut(null));
+  self::expect(0, uns::extensionIfNullOptIn1(0));
+  self::expect(0, self::extensionIfNullOptOut1(0));
+  self::expect(42, uns::extensionIfNullOptIn1(null));
+  self::expect(42, self::extensionIfNullOptOut1(null));
+  uns::extensionIfNullOptIn1ForEffect(0);
+  self::extensionIfNullOptOut1ForEffect(0);
+  uns::extensionIfNullOptIn1ForEffect(null);
+  self::extensionIfNullOptOut1ForEffect(null);
+  self::expect(0, uns::extensionIfNullOptIn2(0));
+  self::expect(0, self::extensionIfNullOptOut2(0));
+  self::expect(42, uns::extensionIfNullOptIn2(null));
+  self::expect(42, self::extensionIfNullOptOut2(null));
+  uns::extensionIfNullOptIn2ForEffect(0);
+  self::extensionIfNullOptOut2ForEffect(0);
+  uns::extensionIfNullOptIn2ForEffect(null);
+  self::extensionIfNullOptOut2ForEffect(null);
+  self::expect(0, uns::ifNullIndexSetOptIn(0));
+  self::expect(0, self::ifNullIndexSetOptOut(0));
+  self::expect(42, uns::ifNullIndexSetOptIn(null));
+  self::expect(42, self::ifNullIndexSetOptOut(null));
+  uns::ifNullIndexSetOptInForEffect(0);
+  self::ifNullIndexSetOptOutForEffect(0);
+  uns::ifNullIndexSetOptInForEffect(null);
+  self::ifNullIndexSetOptOutForEffect(null);
+  self::expect(0, uns::ifNullPropertySetOptIn(0));
+  self::expect(0, self::ifNullPropertySetOptOut(0));
+  self::expect(42, uns::ifNullPropertySetOptIn(null));
+  self::expect(42, self::ifNullPropertySetOptOut(null));
+  uns::ifNullPropertySetOptInForEffect(0);
+  self::ifNullPropertySetOptOutForEffect(0);
+  uns::ifNullPropertySetOptInForEffect(null);
+  self::ifNullPropertySetOptOutForEffect(null);
+  self::expect(0, uns::ifNullSetOptIn(0));
+  self::expect(0, self::ifNullSetOptOut(0));
+  self::expect(42, uns::ifNullSetOptIn(null));
+  self::expect(42, self::ifNullSetOptOut(null));
+  uns::ifNullSetOptInForEffect(0);
+  self::ifNullSetOptOutForEffect(0);
+  uns::ifNullSetOptInForEffect(null);
+  self::ifNullSetOptOutForEffect(null);
+  self::expect(0, uns::ifNullSuperIndexSetOptIn(0));
+  self::expect(0, self::ifNullSuperIndexSetOptOut(0));
+  self::expect(42, uns::ifNullSuperIndexSetOptIn(null));
+  self::expect(42, self::ifNullSuperIndexSetOptOut(null));
+  uns::ifNullSuperIndexSetOptInForEffect(0);
+  self::ifNullSuperIndexSetOptOutForEffect(0);
+  uns::ifNullSuperIndexSetOptInForEffect(null);
+  self::ifNullSuperIndexSetOptOutForEffect(null);
+  self::expect(0, uns::nullAwareIfNullSetOptIn(0));
+  self::expect(0, self::nullAwareIfNullSetOptOut(0));
+  self::expect(42, uns::nullAwareIfNullSetOptIn(null));
+  self::expect(42, self::nullAwareIfNullSetOptOut(null));
+  uns::nullAwareIfNullSetOptInForEffect(0);
+  self::nullAwareIfNullSetOptOutForEffect(0);
+  uns::nullAwareIfNullSetOptInForEffect(null);
+  self::nullAwareIfNullSetOptOutForEffect(null);
+  self::expect(true, uns::isTestOptIn(0));
+  self::expect(true, self::isTestOptOut(0));
+  self::expect(false, uns::isTestOptIn(null));
+  self::expect(false, self::isTestOptOut(null));
+  self::expect(false, uns::isNotTestOptIn(0));
+  self::expect(false, self::isNotTestOptOut(0));
+  self::expect(true, uns::isNotTestOptIn(null));
+  self::expect(true, self::isNotTestOptOut(null));
+  self::expect(true, uns::nullAwareAccess1(0));
+  self::expect(null, uns::nullAwareAccess1(null));
+  uns::promotionToNever(0);
+  uns::promotionToNever(null);
+  uns::unnecessaryNullCheck(() → core::int* => 0);
+  uns::unnecessaryNullCheck(() → core::Null? => null);
+  self::expect(0, uns::unnecessaryIfNull(() → core::int* => 0, () → core::int* => 42));
+  self::expect(42, uns::unnecessaryIfNull(() → core::Null? => null, () → core::int* => 42));
+  uns::unnecessaryIfNullAssign(<core::int*>[0], () → core::int* => 42);
+  uns::unnecessaryIfNullAssign(<core::int*>[null], () → core::int* => 42);
+  uns::unnecessaryNullAwareAccess(() → core::int* => 0);
+  uns::unnecessaryNullAwareAccess(() → core::Null? => null);
+  self::throws(() → dynamic => uns::callReturningNever(() → <BottomType>=> throw "foo"), (core::Object* e) → core::bool* => e.{core::Object::==}("foo"));
+  () →* core::Null? f = () → core::Null? => null;
+  self::throws(() → dynamic => uns::callReturningNever(f));
+  uns::switchOnEnum(#C3);
+  uns::switchOnEnum(#C6);
+  self::throws(() → dynamic => uns::switchOnEnum(null));
+  uns::switchOnEnumWithBreak(#C3);
+  uns::switchOnEnumWithBreak(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithBreak(null));
+  uns::switchOnEnumWithFallThrough1(#C3);
+  uns::switchOnEnumWithFallThrough1(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithFallThrough1(null));
+  uns::switchOnEnumWithFallThrough2(#C3);
+  uns::switchOnEnumWithFallThrough2(#C6);
+  self::throws(() → dynamic => uns::switchOnEnumWithFallThrough2(null));
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() →* void f, [(core::Object*) →* core::bool* testException = #C7]) → dynamic {
+  try {
+    f.call();
+  }
+  on dynamic catch(final dynamic e) {
+    if(!testException.{core::Object::==}(null) && !testException.call(e)) {
+      throw "Unexpected exception: ${e}";
+    }
+    core::print(e);
+    return;
+  }
+  throw "Missing exception.";
+}
+
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:13:23: Warning: Operand of null-aware operation '??' has type 'int' which excludes null.
+// ifNullOptIn(int i) => i ?? 42;
+//                       ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:22:66: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// extensionIfNullOptIn1(int i) => OptInExtension(new OptInClass1())[i] ??= 42;
+//                                                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:25:36: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   OptInExtension(new OptInClass1())[i] ??= 42;
+//                                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:28:50: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// extensionIfNullOptIn2(int i) => new OptInClass1()[i] ??= 42;
+//                                                  ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:31:20: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass1()[i] ??= 42;
+//                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:39:48: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullIndexSetOptIn(int i) => new OptInClass2()[i] ??= 42;
+//                                                ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:42:20: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass2()[i] ??= 42;
+//                    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:51:53: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullPropertySetOptIn(int i) => new OptInClass3(i).field ??= 42;
+//                                                     ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:54:22: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   new OptInClass3(i).field ??= 42;
+//                      ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:57:26: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+// ifNullSetOptIn(int i) => i ??= 42;
+//                          ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:60:3: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   i ??= 42;
+//   ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:69:25: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   method(int i) => super[i] ??= 42;
+//                         ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:71:10: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//     super[i] ??= 42;
+//          ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:113:28: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+// nullAwareAccess1(int i) => i?.isEven;
+//                            ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:116:3: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+//   i?.isEven;
+//   ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:128:11: Warning: Operand of null-aware operation '??' has type 'int' which excludes null.
+//   return f() ??
+//           ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:134:4: Warning: Operand of null-aware operation '??=' has type 'int' which excludes null.
+//   x[0] ??= f();
+//    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:138:4: Warning: Operand of null-aware operation '?.' has type 'int' which excludes null.
+//   f()?.gcd(0); // Should not throw if `f` returns null
+//    ^
+//
+// pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:195:10: Error: Not enough type information to disambiguate between literal set and literal map.
+// Try providing type arguments for the literal explicitly to disambiguate it.
+//   return {...d}; // Should not throw ReachabilityError.
+//          ^
+//
+import self as uns;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class OptInClass1 extends core::Object {
+  synthetic constructor •() → uns::OptInClass1
+    : super core::Object::•()
+    ;
+}
+class OptInClass2 extends core::Object {
+  synthetic constructor •() → uns::OptInClass2
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator []=(core::int index, core::int value) → void {}
+}
+class OptInClass3 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → uns::OptInClass3
+    : uns::OptInClass3::field = field, super core::Object::•()
+    ;
+}
+class OptInSuperClass4 extends core::Object {
+  synthetic constructor •() → uns::OptInSuperClass4
+    : super core::Object::•()
+    ;
+  operator [](core::int index) → core::int
+    return index;
+  operator []=(core::int index, core::int value) → void {}
+}
+class OptInClass4 extends uns::OptInSuperClass4 {
+  synthetic constructor •() → uns::OptInClass4
+    : super uns::OptInSuperClass4::•()
+    ;
+  method method(core::int i) → dynamic
+    return let final core::int #t35 = i in let final core::int #t36 = super.{uns::OptInSuperClass4::[]}(#t35) in #t36.{core::num::==}(null) ?{core::int} let final core::int #t37 = 42 in let final void #t38 = super.{uns::OptInSuperClass4::[]=}(#t35, #t37) in #t37 : #t36;
+  method methodForEffect(core::int i) → dynamic {
+    let final core::int #t39 = i in super.{uns::OptInSuperClass4::[]}(#t39).{core::num::==}(null) ?{core::int} super.{uns::OptInSuperClass4::[]=}(#t39, 42) : null;
+  }
+}
+class OptInClass5 extends core::Object {
+  field core::int field;
+  constructor •(core::int field) → uns::OptInClass5
+    : uns::OptInClass5::field = field, super core::Object::•()
+    ;
+}
+class OptInClass6a extends core::Object {
+  final field uns::OptInClass6b cls;
+  constructor •(uns::OptInClass6b cls) → uns::OptInClass6a
+    : uns::OptInClass6a::cls = cls, super core::Object::•()
+    ;
+}
+class OptInClass6b extends core::Object {
+  final field core::int field;
+  constructor •(core::int field) → uns::OptInClass6b
+    : uns::OptInClass6b::field = field, super core::Object::•()
+    ;
+}
+class E extends core::Object /*isEnum*/  {
+  final field core::int index;
+  final field core::String _name;
+  static const field core::List<uns::E> values = #C8;
+  static const field uns::E e1 = #C3;
+  static const field uns::E e2 = #C6;
+  const constructor •(core::int index, core::String _name) → uns::E
+    : uns::E::index = index, uns::E::_name = _name, super core::Object::•()
+    ;
+  method toString() → core::String
+    return this.{uns::E::_name};
+}
+extension OptInExtension on uns::OptInClass1 {
+  operator [] = uns::OptInExtension|[];
+  operator []= = uns::OptInExtension|[]=;
+}
+static method isNullOptIn1(core::int i) → dynamic
+  return i.{core::num::==}(null);
+static method isNotNullOptIn1(core::int i) → dynamic
+  return !i.{core::num::==}(null);
+static method isNullOptIn2(core::int i) → dynamic
+  return null.{core::Object::==}(i);
+static method isNotNullOptIn2(core::int i) → dynamic
+  return !null.{core::Object::==}(i);
+static method ifNullOptIn(core::int i) → dynamic
+  return let final core::int #t40 = i in #t40.{core::num::==}(null) ?{core::int} 42 : #t40;
+static method OptInExtension|[](final uns::OptInClass1 #this, core::int index) → core::int
+  return index;
+static method OptInExtension|[]=(final uns::OptInClass1 #this, core::int index, core::int value) → void {}
+static method extensionIfNullOptIn1(core::int i) → dynamic
+  return let final uns::OptInClass1 #t41 = new uns::OptInClass1::•() in let final core::int #t42 = i in let final core::int #t43 = uns::OptInExtension|[](#t41, #t42) in #t43.{core::num::==}(null) ?{core::int} let final core::int #t44 = 42 in let final void #t45 = uns::OptInExtension|[]=(#t41, #t42, #t44) in #t44 : #t43;
+static method extensionIfNullOptIn1ForEffect(core::int i) → dynamic {
+  let final uns::OptInClass1 #t46 = new uns::OptInClass1::•() in let final core::int #t47 = i in uns::OptInExtension|[](#t46, #t47).{core::num::==}(null) ?{core::int} uns::OptInExtension|[]=(#t46, #t47, 42) : null;
+}
+static method extensionIfNullOptIn2(core::int i) → dynamic
+  return let final uns::OptInClass1 #t48 = new uns::OptInClass1::•() in let final core::int #t49 = i in let final core::int #t50 = uns::OptInExtension|[](#t48, #t49) in #t50.{core::num::==}(null) ?{core::int} let final core::int #t51 = 42 in let final void #t52 = uns::OptInExtension|[]=(#t48, #t49, #t51) in #t51 : #t50;
+static method extensionIfNullOptIn2ForEffect(core::int i) → dynamic {
+  let final uns::OptInClass1 #t53 = new uns::OptInClass1::•() in let final core::int #t54 = i in uns::OptInExtension|[](#t53, #t54).{core::num::==}(null) ?{core::int} uns::OptInExtension|[]=(#t53, #t54, 42) : null;
+}
+static method ifNullIndexSetOptIn(core::int i) → dynamic
+  return let final uns::OptInClass2 #t55 = new uns::OptInClass2::•() in let final core::int #t56 = i in let final core::int #t57 = #t55.{uns::OptInClass2::[]}(#t56) in #t57.{core::num::==}(null) ?{core::int} let final core::int #t58 = 42 in let final void #t59 = #t55.{uns::OptInClass2::[]=}(#t56, #t58) in #t58 : #t57;
+static method ifNullIndexSetOptInForEffect(core::int i) → dynamic {
+  let final uns::OptInClass2 #t60 = new uns::OptInClass2::•() in let final core::int #t61 = i in #t60.{uns::OptInClass2::[]}(#t61).{core::num::==}(null) ?{core::int} #t60.{uns::OptInClass2::[]=}(#t61, 42) : null;
+}
+static method ifNullPropertySetOptIn(core::int i) → dynamic
+  return let final uns::OptInClass3 #t62 = new uns::OptInClass3::•(i) in let final core::int #t63 = #t62.{uns::OptInClass3::field} in #t63.{core::num::==}(null) ?{core::int} #t62.{uns::OptInClass3::field} = 42 : #t63;
+static method ifNullPropertySetOptInForEffect(core::int i) → dynamic {
+  let final uns::OptInClass3 #t64 = new uns::OptInClass3::•(i) in #t64.{uns::OptInClass3::field}.{core::num::==}(null) ?{core::int} #t64.{uns::OptInClass3::field} = 42 : null;
+}
+static method ifNullSetOptIn(core::int i) → dynamic
+  return let final core::int #t65 = i in #t65.{core::num::==}(null) ?{core::int} i = 42 : #t65;
+static method ifNullSetOptInForEffect(core::int i) → dynamic {
+  i.{core::num::==}(null) ?{core::int} i = 42 : null;
+}
+static method ifNullSuperIndexSetOptIn(core::int i) → dynamic
+  return new uns::OptInClass4::•().{uns::OptInClass4::method}(i);
+static method ifNullSuperIndexSetOptInForEffect(core::int i) → dynamic {
+  new uns::OptInClass4::•().{uns::OptInClass4::methodForEffect}(i);
+}
+static method nullAwareIfNullSetOptIn(core::int i) → dynamic {
+  uns::OptInClass5? o = new uns::OptInClass5::•(i);
+  return let final uns::OptInClass5? #t66 = o in #t66.{core::Object::==}(null) ?{core::int?} null : let final core::int #t67 = #t66.{uns::OptInClass5::field} in #t67.{core::num::==}(null) ?{core::int} #t66.{uns::OptInClass5::field} = 42 : #t67;
+}
+static method nullAwareIfNullSetOptInForEffect(core::int i) → dynamic {
+  uns::OptInClass5? o = new uns::OptInClass5::•(i);
+  let final uns::OptInClass5? #t68 = o in #t68.{core::Object::==}(null) ?{core::int?} null : #t68.{uns::OptInClass5::field}.{core::num::==}(null) ?{core::int} #t68.{uns::OptInClass5::field} = 42 : null;
+}
+static method isTestOptIn(core::int i) → dynamic
+  return i is{ForNonNullableByDefault} core::int;
+static method isNotTestOptIn(core::int i) → dynamic
+  return !(i is{ForNonNullableByDefault} core::int);
+static method nullAwareAccess1(core::int i) → dynamic
+  return let final core::int #t69 = i in #t69.{core::num::==}(null) ?{core::bool?} null : #t69.{core::int::isEven};
+static method nullAwareAccessForEffect1(core::int i) → dynamic {
+  let final core::int #t70 = i in #t70.{core::num::==}(null) ?{core::bool?} null : #t70.{core::int::isEven};
+}
+static method promotionToNever(core::int i) → dynamic {
+  if(i is{ForNonNullableByDefault} core::int)
+    return;
+}
+static method unnecessaryNullCheck(() → core::int f) → dynamic {
+  if(!f.call().{core::num::==}(null))
+    return;
+}
+static method unnecessaryIfNull(() → core::int f, () → core::int g) → dynamic {
+  return let final core::int #t71 = f.call() in #t71.{core::num::==}(null) ?{core::int} g.call() : #t71;
+}
+static method unnecessaryIfNullAssign(core::List<core::int> x, () → core::int f) → dynamic {
+  let final core::List<core::int> #t72 = x in let final core::int #t73 = 0 in #t72.{core::List::[]}(#t73).{core::num::==}(null) ?{core::int} #t72.{core::List::[]=}(#t73, f.call()) : null;
+}
+static method unnecessaryNullAwareAccess(() → core::int f) → dynamic {
+  let final core::int #t74 = f.call() in #t74.{core::num::==}(null) ?{core::int?} null : #t74.{core::int::gcd}(0);
+}
+static method callReturningNever(() → Never f) → dynamic {
+  let final Never #t75 = f.call() in throw new _in::ReachabilityError::•("`null` encountered as the result from expression with type `Never`.");
+}
+static method switchOnEnum(uns::E e) → dynamic {
+  switch(e) {
+    #L1:
+    case #C3:
+      {
+        return;
+      }
+    #L2:
+    case #C6:
+      {
+        return;
+      }
+    #L3:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithBreak(uns::E e) → dynamic {
+  #L4:
+  switch(e) {
+    #L5:
+    case #C3:
+      {
+        break #L4;
+      }
+    #L6:
+    case #C6:
+      {
+        break #L4;
+      }
+    #L7:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithFallThrough1(uns::E e) → dynamic {
+  #L8:
+  switch(e) {
+    #L9:
+    case #C3:
+      {
+        break #L8;
+      }
+    #L10:
+    case #C6:
+      {
+        break #L8;
+      }
+    #L11:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method switchOnEnumWithFallThrough2(uns::E e) → dynamic {
+  #L12:
+  switch(e) {
+    #L13:
+    case #C3:
+    case #C6:
+      {
+        break #L12;
+      }
+    #L14:
+    default:
+      throw new _in::ReachabilityError::•("`null` encountered as case in a switch expression with a non-nullable enum type.");
+  }
+}
+static method handleThrow() → dynamic {
+  throw "";
+}
+static method handleRethrow() → dynamic {
+  try {
+    uns::handleThrow();
+  }
+  on core::Object catch(final core::Object _) {
+    rethrow;
+  }
+}
+static method handleInvalid(dynamic d) → dynamic {
+  return invalid-expression "pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart:195:10: Error: Not enough type information to disambiguate between literal set and literal map.
+Try providing type arguments for the literal explicitly to disambiguate it.
+  return {...d}; // Should not throw ReachabilityError.
+         ^";
+}
+
+constants  {
+  #C1 = 0
+  #C2 = "E.e1"
+  #C3 = uns::E {index:#C1, _name:#C2}
+  #C4 = 1
+  #C5 = "E.e2"
+  #C6 = uns::E {index:#C4, _name:#C5}
+  #C7 = null
+  #C8 = <uns::E*>[#C3, #C6]
+}
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:73:33 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:73:33 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:26:77 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:26:77 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:32:60 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:32:60 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:43:58 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks.dart:43:58 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:69:33 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:69:33 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:22:74 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:22:74 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:28:58 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:28:58 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:39:56 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:39:56 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:134:5 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///unsound_checks_lib.dart:134:5 -> IntConstant(0)
+Extra constant evaluation: evaluated: 719, effectively constant: 18
diff --git a/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
new file mode 100644
index 0000000..738e03a
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/unsound_checks_lib.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+isNullOptIn1(int i) => i == null;
+
+isNotNullOptIn1(int i) => i != null;
+
+isNullOptIn2(int i) => null == i;
+
+isNotNullOptIn2(int i) => null != i;
+
+ifNullOptIn(int i) => i ?? 42;
+
+class OptInClass1 {}
+
+extension OptInExtension on OptInClass1 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+extensionIfNullOptIn1(int i) => OptInExtension(new OptInClass1())[i] ??= 42;
+
+extensionIfNullOptIn1ForEffect(int i) {
+  OptInExtension(new OptInClass1())[i] ??= 42;
+}
+
+extensionIfNullOptIn2(int i) => new OptInClass1()[i] ??= 42;
+
+extensionIfNullOptIn2ForEffect(int i) {
+  new OptInClass1()[i] ??= 42;
+}
+
+class OptInClass2 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+ifNullIndexSetOptIn(int i) => new OptInClass2()[i] ??= 42;
+
+ifNullIndexSetOptInForEffect(int i) {
+  new OptInClass2()[i] ??= 42;
+}
+
+class OptInClass3 {
+  int field;
+
+  OptInClass3(this.field);
+}
+
+ifNullPropertySetOptIn(int i) => new OptInClass3(i).field ??= 42;
+
+ifNullPropertySetOptInForEffect(int i) {
+  new OptInClass3(i).field ??= 42;
+}
+
+ifNullSetOptIn(int i) => i ??= 42;
+
+ifNullSetOptInForEffect(int i) {
+  i ??= 42;
+}
+
+class OptInSuperClass4 {
+  int operator [](int index) => index;
+  void operator []=(int index, int value) {}
+}
+
+class OptInClass4 extends OptInSuperClass4 {
+  method(int i) => super[i] ??= 42;
+  methodForEffect(int i) {
+    super[i] ??= 42;
+  }
+}
+
+ifNullSuperIndexSetOptIn(int i) => new OptInClass4().method(i);
+
+ifNullSuperIndexSetOptInForEffect(int i) {
+  new OptInClass4().methodForEffect(i);
+}
+
+class OptInClass5 {
+  int field;
+
+  OptInClass5(this.field);
+}
+
+nullAwareIfNullSetOptIn(int i) {
+  OptInClass5? o = new OptInClass5(i) as OptInClass5?;
+  return o?.field ??= 42;
+}
+
+nullAwareIfNullSetOptInForEffect(int i) {
+  OptInClass5? o = new OptInClass5(i) as OptInClass5?;
+  o?.field ??= 42;
+}
+
+isTestOptIn(int i) => i is int;
+
+isNotTestOptIn(int i) => i is! int;
+
+class OptInClass6a {
+  final OptInClass6b cls;
+
+  OptInClass6a(this.cls);
+}
+
+class OptInClass6b {
+  final int field;
+
+  OptInClass6b(this.field);
+}
+
+nullAwareAccess1(int i) => i?.isEven;
+
+nullAwareAccessForEffect1(int i) {
+  i?.isEven;
+}
+
+promotionToNever(int i) {
+  if (i is int) return; // Should not throw if `i` is null
+}
+
+unnecessaryNullCheck(int f()) {
+  if (f() != null) return; // Should not throw if `f` returns null
+}
+
+unnecessaryIfNull(int f(), int g()) {
+  return f() ??
+      g(); // Should not throw if `f` returns null (rather than calling `g`)
+}
+
+unnecessaryIfNullAssign(List<int> x, int f()) {
+  // Should not  throw if `x[0]` returns null (rather than calling `f`)
+  x[0] ??= f();
+}
+
+unnecessaryNullAwareAccess(int f()) {
+  f()?.gcd(0); // Should not throw if `f` returns null
+}
+
+callReturningNever(Never f()) {
+  f(); // Should throw if `f` completes normally
+}
+
+enum E { e1, e2 }
+
+switchOnEnum(E e) {
+  switch (e) {
+    case E.e1:
+      return;
+    case E.e2:
+      return;
+  } // Should throw if the implicit `default` branch is taken
+}
+
+switchOnEnumWithBreak(E e) {
+  switch (e) {
+    case E.e1:
+      break;
+    case E.e2:
+      break;
+  } // Should throw if the implicit `default` branch is taken
+}
+
+switchOnEnumWithFallThrough1(E e) {
+  switch (e) {
+    case E.e1:
+      break;
+    case E.e2:
+  } // Should throw if the implicit `default` branch is taken
+}
+
+switchOnEnumWithFallThrough2(E e) {
+  switch (e) {
+    case E.e1:
+    case E.e2:
+  } // Should throw if the implicit `default` branch is taken
+}
+
+handleThrow() {
+  throw ''; // Should not throw ReachabilityError.
+}
+
+handleRethrow() {
+  try {
+    handleThrow();
+  } catch (_) {
+    rethrow; // Should not throw ReachabilityError.
+  }
+}
+
+handleInvalid(dynamic d) {
+  // This is deliberately creating a compile-time error to verify that we
+  // don't create ReachabilityError for invalid expressions.
+  return {...d}; // Should not throw ReachabilityError.
+}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.outline.expect
index 55520c5..6a3fcc1 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field.dart.outline.expect
@@ -44,3 +44,14 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field.dart:18:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
index fb37b2b..26d73b4 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_arent_mixed_in.dart.outline.expect
@@ -61,3 +61,14 @@
 static field core::int* count;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_arent_mixed_in.dart:12:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.outline.expect
index 05b41eb..8db6c2b 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_one_defined.dart.outline.expect
@@ -67,3 +67,14 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_one_defined.dart:17:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.outline.expect
index 874eb21..8348811 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_accessors_from_field_with_substitution.dart.outline.expect
@@ -40,3 +40,14 @@
   ;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_accessors_from_field_with_substitution.dart:18:11 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
index 80872a0..29f7048 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
@@ -40,3 +40,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_interface_nsm_inherited.dart:16:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_interface_nsm_inherited.dart:16:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_interface_nsm_inherited.dart:16:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_interface_nsm_inherited.dart:16:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.outline.expect
index 18732e96..a18f420 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_abstract_different_type.dart.outline.expect
@@ -35,3 +35,19 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:8:7 -> SymbolConstant(#push=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:8:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:8:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:9:7 -> SymbolConstant(#float=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:9:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:9:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:16:7 -> SymbolConstant(#push=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:16:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:16:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:17:7 -> SymbolConstant(#float=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:17:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_override_abstract_different_type.dart:17:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 40, effectively constant: 12
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
index 6db64b7..fd257f0 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_override_with_different_signature.dart.outline.expect
@@ -69,3 +69,17 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:8:8 -> SymbolConstant(#eatFood)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:8:8 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:8:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:23:8 -> SymbolConstant(#eatFood)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:23:8 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:23:8 -> SymbolConstant(#amount)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:26:7 -> SymbolConstant(#eatFood)
+Evaluated: ListLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:26:7 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:26:7 -> SymbolConstant(#amount)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///abstract_override_with_different_signature.dart:26:7 -> SymbolConstant(#yetAnother)
+Extra constant evaluation: evaluated: 39, effectively constant: 10
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
index ebb3cd0..be653d9 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/concrete_method_over_forwarder_in_mixin_application.dart.outline.expect
@@ -61,3 +61,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///concrete_method_over_forwarder_in_mixin_application.dart:10:3 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect
index eb0cac0..27e25ce 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/default_argument_values.dart.outline.expect
@@ -29,3 +29,14 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///default_argument_values.dart:21:10 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///default_argument_values.dart:21:10 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///default_argument_values.dart:21:10 -> ListConstant(const <dynamic>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///default_argument_values.dart:21:10 -> SymbolConstant(#bar)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///default_argument_values.dart:22:7 -> SymbolConstant(#hest)
+Evaluated: ListLiteral @ org-dartlang-testcase:///default_argument_values.dart:22:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///default_argument_values.dart:22:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 22, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.outline.expect
index a0f19c9..4dfd530 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/duplicated_abstract_method.dart.outline.expect
@@ -51,3 +51,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///duplicated_abstract_method.dart:14:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_abstract_method.dart:14:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///duplicated_abstract_method.dart:14:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///duplicated_abstract_method.dart:14:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.outline.expect
index 47c4e4a..dcd9757 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarder_propagation.dart.outline.expect
@@ -100,3 +100,36 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:12:11 -> SymbolConstant(#bar)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:12:11 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:12:11 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:12:11 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:13:8 -> SymbolConstant(#baz)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:13:8 -> ListConstant(const <Type*>[])
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:13:8 -> SymbolConstant(#y)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:13:8 -> SymbolConstant(#z)
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:11:12 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:11:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation.dart:11:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:7:11 -> SymbolConstant(#_privateGetter)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:7:11 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:7:11 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:7:11 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> SymbolConstant(#_privateField)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:9:8 -> SymbolConstant(#_privateMethod)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:9:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:9:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:9:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:8:12 -> SymbolConstant(#_privateSetter=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:8:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:8:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> SymbolConstant(#_privateField=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarder_propagation_lib.dart:6:7 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 79, effectively constant: 29
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
index f5c8765..e03bb94 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/forwarders_not_assumed_from_mixin.dart.outline.expect
@@ -56,3 +56,15 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///forwarders_not_assumed_from_mixin.dart:10:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 16, effectively constant: 8
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
index 4e3645c..513d138 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
@@ -41,3 +41,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///interface_with_concrete.dart:16:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_concrete.dart:16:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_concrete.dart:16:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///interface_with_concrete.dart:16:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
index facaaaf..6e4c566 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -76,3 +76,19 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///interface_with_nsm.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 24, effectively constant: 12
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.outline.expect
index a5ebee0..8a420c1 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/multiple_abstract_setters.dart.outline.expect
@@ -77,3 +77,14 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:17:12 -> SymbolConstant(#bar)
+Evaluated: ListLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:17:12 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:17:12 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:17:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:16:12 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:16:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///multiple_abstract_setters.dart:16:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 19, effectively constant: 7
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.outline.expect
index 16b6208..c81571e 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes.dart.outline.expect
@@ -26,3 +26,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes.dart:13:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes.dart:13:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes.dart:13:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes.dart:13:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.outline.expect
index 81d064a..59a56b80 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_forwarders_for_abstract_classes_chain.dart.outline.expect
@@ -34,3 +34,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes_chain.dart:14:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes_chain.dart:14:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes_chain.dart:14:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///no_forwarders_for_abstract_classes_chain.dart:14:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
index a3ab6a8..cf93dc7 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
@@ -25,3 +25,10 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///nsm_inherited.dart:13:8 -> SymbolConstant(#call)
+Evaluated: ListLiteral @ org-dartlang-testcase:///nsm_inherited.dart:13:8 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///nsm_inherited.dart:13:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 10, effectively constant: 3
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
index 936234c..69a5847 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -39,3 +39,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///nsm_mixed_in.dart:15:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
index 67632eb..6b1da0c 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/private.dart.outline.expect
@@ -58,3 +58,15 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> SymbolConstant(#_hest)
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> SymbolConstant(#_hest)
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///private_module.dart:11:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 16, effectively constant: 8
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.outline.expect
index 247243b..40e53fb 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/private_same.dart.outline.expect
@@ -27,3 +27,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///private_same.dart:10:8 -> SymbolConstant(#_foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_same.dart:10:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///private_same.dart:10:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///private_same.dart:10:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
index c3c56f4..b321f75 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
@@ -21,3 +21,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///same.dart:14:8 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///same.dart:14:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///same.dart:14:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///same.dart:14:8 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 8, effectively constant: 4
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
index 7e60f4f..7c74a0a 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/setter_not_shadowed_by_method.dart.outline.expect
@@ -33,3 +33,10 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///setter_not_shadowed_by_method.dart:12:12 -> SymbolConstant(#foo=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///setter_not_shadowed_by_method.dart:12:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///setter_not_shadowed_by_method.dart:12:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 10, effectively constant: 3
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
index a62df4b..e523dd2 100644
--- a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -54,3 +54,11 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> SymbolConstant(#foo)
+Evaluated: ListLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///subst_on_forwarder.dart:10:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 9, effectively constant: 4
diff --git a/pkg/front_end/testcases/old_dills/.gitignore b/pkg/front_end/testcases/old_dills/.gitignore
deleted file mode 100644
index e449e17..0000000
--- a/pkg/front_end/testcases/old_dills/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-dills
diff --git a/pkg/front_end/testcases/old_dills/dills/dart2js.version.46.compile.1.dill b/pkg/front_end/testcases/old_dills/dills/dart2js.version.46.compile.1.dill
new file mode 100644
index 0000000..d766ad5
--- /dev/null
+++ b/pkg/front_end/testcases/old_dills/dills/dart2js.version.46.compile.1.dill
Binary files differ
diff --git a/pkg/front_end/testcases/old_dills/old_dills.status b/pkg/front_end/testcases/old_dills/old_dills.status
deleted file mode 100644
index e22cfe5..0000000
--- a/pkg/front_end/testcases/old_dills/old_dills.status
+++ /dev/null
@@ -1,3 +0,0 @@
-# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE.md file.
diff --git a/pkg/front_end/testcases/outline.status b/pkg/front_end/testcases/outline.status
index 3c00bd1..532869a 100644
--- a/pkg/front_end/testcases/outline.status
+++ b/pkg/front_end/testcases/outline.status
@@ -14,7 +14,9 @@
 general_nnbd_opt_out/override_setter_with_field: TypeCheckError
 general/abstract_members: TypeCheckError
 general/bug30695: TypeCheckError
+general/constants/const_collections: TypeCheckError
 general/covariant_field: TypeCheckError
+general/getter_vs_setter_type: TypeCheckError
 general/infer_field_from_multiple: TypeCheckError
 general/invalid_operator: TypeCheckError
 general/invalid_operator_override: TypeCheckError
@@ -43,6 +45,7 @@
 inference/mixin_inference_unification_2: TypeCheckError
 late_lowering/covariant_late_field: TypeCheckError
 nnbd/covariant_late_field: TypeCheckError
+nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue42603: TypeCheckError
 rasta/native_is_illegal: Pass # Issue 29763
 runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
diff --git a/pkg/front_end/testcases/rasta/enum.dart.outline.expect b/pkg/front_end/testcases/rasta/enum.dart.outline.expect
index 1d69d48..a6d72f1 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.outline.expect
@@ -12,7 +12,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
@@ -25,3 +25,10 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///enum.dart:5:6 -> ListConstant(const <Foo*>[const Foo{Foo.index: 0, Foo._name: "Foo.ec1"}, const Foo{Foo.index: 1, Foo._name: "Foo.ec2"}])
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum.dart:6:3 -> InstanceConstant(const Foo{Foo.index: 0, Foo._name: "Foo.ec1"})
+Evaluated: ConstructorInvocation @ org-dartlang-testcase:///enum.dart:7:3 -> InstanceConstant(const Foo{Foo.index: 1, Foo._name: "Foo.ec2"})
+Extra constant evaluation: evaluated: 7, effectively constant: 3
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
index 0b718d7..7ae9eb8 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.expect
@@ -12,7 +12,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
index 0b718d7..7ae9eb8 100644
--- a/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/enum.dart.strong.transformed.expect
@@ -12,7 +12,7 @@
     : self::Foo::index = index, self::Foo::_name = _name, super core::Object::•()
     ;
   method toString() → core::String*
-    return this.{=self::Foo::_name};
+    return this.{self::Foo::_name};
   abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
   abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
   abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
diff --git a/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect
index b3330742..d8064f6 100644
--- a/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000026.dart.strong.transformed.expect
@@ -42,3 +42,9 @@
   new self::C::•();
   new self::D::•();
 }
+
+
+Extra constant evaluation status:
+Evaluated: MethodInvocation @ org-dartlang-testcase:///issue_000026.dart:8:13 -> IntConstant(3)
+Evaluated: MethodInvocation @ org-dartlang-testcase:///issue_000026.dart:14:13 -> IntConstant(-1)
+Extra constant evaluation: evaluated: 4, effectively constant: 2
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
index efbb1fc..d9fcdaf 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.outline.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // }
 // ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
index 7fcff63e..9cae185 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // }
 // ^
 //
@@ -21,6 +22,7 @@
 // ^
 //
 // pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // }
 // ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
index 7fcff63e..9cae185 100644
--- a/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000032.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000032.dart:7:1: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // }
 // ^
 //
@@ -21,6 +22,7 @@
 // ^
 //
 // pkg/front_end/testcases/rasta/issue_000032.dart:11:1: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // }
 // ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.outline.expect
index 14f3ce3..9e8c916 100644
--- a/pkg/front_end/testcases/rasta/issue_000036.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000036.dart.outline.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// Try inserting an identifier before '-'.
 // main() => a. - 5;
 //              ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect
index c46dc5c..433f8d9 100644
--- a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// Try inserting an identifier before '-'.
 // main() => a. - 5;
 //              ^
 //
 // pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // main() => a. - 5;
 //              ^
 //
@@ -14,5 +16,6 @@
 
 static method main() → dynamic
   return invalid-expression "pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
 main() => a. - 5;
              ^".-(5);
diff --git a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect
index c46dc5c..433f8d9 100644
--- a/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000036.dart.strong.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got '-'.
+// Try inserting an identifier before '-'.
 // main() => a. - 5;
 //              ^
 //
 // pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 // main() => a. - 5;
 //              ^
 //
@@ -14,5 +16,6 @@
 
 static method main() → dynamic
   return invalid-expression "pkg/front_end/testcases/rasta/issue_000036.dart:5:14: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
 main() => a. - 5;
              ^".-(5);
diff --git a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect
index 293d1e6..238ce88 100644
--- a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 //   }
 //   ^
 //
 // pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   }
 //   ^
 //
@@ -26,6 +28,7 @@
   constructor •(dynamic x) → self::A*
     : super core::Object::•() {
     this.{self::A::a} = invalid-expression "pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   }
   ^";
   }
diff --git a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect
index 293d1e6..238ce88 100644
--- a/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000039.dart.strong.transformed.expect
@@ -3,10 +3,12 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 //   }
 //   ^
 //
 // pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+// Try inserting an identifier before ''.
 //   }
 //   ^
 //
@@ -26,6 +28,7 @@
   constructor •(dynamic x) → self::A*
     : super core::Object::•() {
     this.{self::A::a} = invalid-expression "pkg/front_end/testcases/rasta/issue_000039.dart:10:3: Error: Expected an identifier, but got ''.
+Try inserting an identifier before ''.
   }
   ^";
   }
diff --git a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
index 62fa768..9a23794 100644
--- a/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000043.dart.strong.transformed.expect
@@ -19,3 +19,8 @@
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///issue_000043.dart:6:14 -> TypeLiteralConstant(C*)
+Extra constant evaluation: evaluated: 3, effectively constant: 1
diff --git a/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect
index 2622c42..c9a26da 100644
--- a/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000045.dart.strong.transformed.expect
@@ -17,3 +17,9 @@
 static method main() → dynamic
   return "${1}
 \"\"\"";
+
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///issue_000045.dart:6:1 -> StringConstant("1
+\"\"\"")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.outline.expect
index 4a4defd..204c7a9 100644
--- a/pkg/front_end/testcases/rasta/issue_000046.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000046.dart.outline.expect
@@ -15,6 +15,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   C c = new Object)();
 //                    ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect
index a724b05..7cade84 100644
--- a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.expect
@@ -15,6 +15,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   C c = new Object)();
 //                    ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect
index a724b05..7cade84 100644
--- a/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000046.dart.strong.transformed.expect
@@ -15,6 +15,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/rasta/issue_000046.dart:6:20: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   C c = new Object)();
 //                    ^
 //
diff --git a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
index 8b5453f..9fbd201 100644
--- a/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000070.dart.outline.expect
@@ -50,3 +50,8 @@
 }
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: ListLiteral @ org-dartlang-testcase:///issue_000070.dart:22:33 -> ListConstant(const <Null?>[null])
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
index bf1076a..8b6d4d8 100644
--- a/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/issue_000081.dart.strong.transformed.expect
@@ -33,3 +33,9 @@
   core::List<core::Null?>* l = <core::Null?>[null];
   let final core::List<core::Null?>* #t2 = l in let final core::int* #t3 = 0 in #t2.{core::List::[]}(#t3).{core::Object::==}(null) ?{core::String*} #t2.{core::List::[]=}(#t3, "fisk" as{TypeError} core::Null?) : null;
 }
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue_000081.dart:22:5 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///issue_000081.dart:22:5 -> IntConstant(0)
+Extra constant evaluation: evaluated: 33, effectively constant: 2
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect b/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect
index 13f78fd..1b9b0f8 100644
--- a/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/parser_error.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: Expected an identifier, but got '?'.
+// Try inserting an identifier before '?'.
 //   if (?b) return b;  /// 01: compile-time error
 //       ^
 //
@@ -11,6 +12,7 @@
 //         ^
 //
 // pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   if (?b) return b;  /// 01: compile-time error
 //         ^
 //
diff --git a/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect
index 104ab44..a7bf51f 100644
--- a/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/parser_error.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/rasta/parser_error.dart:10:7: Error: Expected an identifier, but got '?'.
+// Try inserting an identifier before '?'.
 //   if (?b) return b;  /// 01: compile-time error
 //       ^
 //
@@ -11,6 +12,7 @@
 //         ^
 //
 // pkg/front_end/testcases/rasta/parser_error.dart:10:9: Error: Expected an identifier, but got ')'.
+// Try inserting an identifier before ')'.
 //   if (?b) return b;  /// 01: compile-time error
 //         ^
 //
diff --git a/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
index b43a9e5..7c94fe0 100644
--- a/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/static.dart.strong.transformed.expect
@@ -337,3 +337,12 @@
   #C1 = 42
   #C2 = tearoff self::Foo::staticFunction
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///static.dart:32:13 -> IntConstant(42)
+Evaluated: VariableGet @ org-dartlang-testcase:///static.dart:36:13 -> TearOffConstant(Foo.staticFunction)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///static.dart:75:24 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///static.dart:76:28 -> IntConstant(42)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///static.dart:79:24 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///static.dart:80:28 -> TearOffConstant(Foo.staticFunction)
+Extra constant evaluation: evaluated: 122, effectively constant: 6
diff --git a/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
index ad8084b..b50aab5 100644
--- a/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/type_literals.dart.strong.transformed.expect
@@ -530,3 +530,19 @@
 static method main() → dynamic {
   new self::C::•<dynamic>().{self::C::test}();
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:11:5 -> TypeLiteralConstant(C<dynamic>*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:12:9 -> TypeLiteralConstant(C<dynamic>*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:13:5 -> TypeLiteralConstant(dynamic)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:14:9 -> TypeLiteralConstant(dynamic)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:17:5 -> TypeLiteralConstant(void Function()*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///type_literals.dart:18:9 -> TypeLiteralConstant(void Function()*)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:74:7 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:75:11 -> TypeLiteralConstant(C<dynamic>*)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:76:13 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:77:17 -> TypeLiteralConstant(dynamic)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///type_literals.dart:80:10 -> NullConstant(null)
+Evaluated: Let @ org-dartlang-testcase:///type_literals.dart:81:14 -> TypeLiteralConstant(void Function()*)
+Extra constant evaluation: evaluated: 72, effectively constant: 12
diff --git a/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
index 36ac25e..2fda16d 100644
--- a/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/typedef.dart.strong.transformed.expect
@@ -30,3 +30,9 @@
   Foo();
   ^^^";
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///typedef.dart:8:9 -> TypeLiteralConstant(void Function()*)
+Evaluated: ConditionalExpression @ org-dartlang-testcase:///typedef.dart:10:7 -> NullConstant(null)
+Extra constant evaluation: evaluated: 3, effectively constant: 2
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
index 814c1f0..8a74c31 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.expect
@@ -19,6 +19,7 @@
 //          ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //     for (1 in x) {
 //          ^
 //
@@ -69,6 +70,7 @@
 //        ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:43:8: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //   for (1 in arguments) {
 //        ^
 //
diff --git a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
index 1e0dee4..85061fb 100644
--- a/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_for_in.dart.strong.transformed.expect
@@ -19,6 +19,7 @@
 //          ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:23:10: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //     for (1 in x) {
 //          ^
 //
@@ -69,6 +70,7 @@
 //        ^^^^^^^^^^^^
 //
 // pkg/front_end/testcases/rasta/unresolved_for_in.dart:43:8: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //   for (1 in arguments) {
 //        ^
 //
@@ -256,3 +258,11 @@
     }
   }
 }
+
+
+Extra constant evaluation status:
+Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:15:13 -> TypeLiteralConstant(Fisk*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:21:13 -> TypeLiteralConstant(void Function()*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:35:11 -> TypeLiteralConstant(Fisk*)
+Evaluated: TypeLiteral @ org-dartlang-testcase:///unresolved_for_in.dart:41:11 -> TypeLiteralConstant(void Function()*)
+Extra constant evaluation: evaluated: 85, effectively constant: 4
diff --git a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
index 6906158..85bcb06 100644
--- a/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
+++ b/pkg/front_end/testcases/rasta/unresolved_recovery.dart.strong.expect
@@ -26,7 +26,8 @@
 //   on Exception catch (e) { }
 //      ^^^^^^^^^
 //
-// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: Expected an identifier, but got 'catch'.
+// pkg/front_end/testcases/rasta/unresolved_recovery.dart:20:16: Error: 'catch' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 //   on Exception catch (e) { }
 //                ^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_29941.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29941.dart.strong.expect
index 5fc0850..82b995b 100644
--- a/pkg/front_end/testcases/regress/issue_29941.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29941.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_29941.dart:7:5: Error: Expected an identifier, but got '""'.
+// Try inserting an identifier before '""'.
 //   a."";
 //     ^^
 //
@@ -12,6 +13,7 @@
 static method bad() → dynamic {
   core::String* a = "";
   invalid-expression "pkg/front_end/testcases/regress/issue_29941.dart:7:5: Error: Expected an identifier, but got '\"\"'.
+Try inserting an identifier before '\"\"'.
   a.\"\";
     ^^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_29941.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29941.dart.strong.transformed.expect
index 5fc0850..82b995b 100644
--- a/pkg/front_end/testcases/regress/issue_29941.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29941.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_29941.dart:7:5: Error: Expected an identifier, but got '""'.
+// Try inserting an identifier before '""'.
 //   a."";
 //     ^^
 //
@@ -12,6 +13,7 @@
 static method bad() → dynamic {
   core::String* a = "";
   invalid-expression "pkg/front_end/testcases/regress/issue_29941.dart:7:5: Error: Expected an identifier, but got '\"\"'.
+Try inserting an identifier before '\"\"'.
   a.\"\";
     ^^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_29943.dart.strong.expect b/pkg/front_end/testcases/regress/issue_29943.dart.strong.expect
index 4684ec6..cc07a5e 100644
--- a/pkg/front_end/testcases/regress/issue_29943.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_29943.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_29943.dart:6:5: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   x.(null);
 //     ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   invalid-expression "pkg/front_end/testcases/regress/issue_29943.dart:6:5: Error: Expected an identifier, but got '('.
+Try inserting an identifier before '('.
   x.(null);
     ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_29943.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_29943.dart.strong.transformed.expect
index 4684ec6..cc07a5e 100644
--- a/pkg/front_end/testcases/regress/issue_29943.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_29943.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_29943.dart:6:5: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   x.(null);
 //     ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   invalid-expression "pkg/front_end/testcases/regress/issue_29943.dart:6:5: Error: Expected an identifier, but got '('.
+Try inserting an identifier before '('.
   x.(null);
     ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
index e570118..83eb83e 100644
--- a/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_30838.dart.strong.transformed.expect
@@ -34,3 +34,7 @@
 constants  {
   #C1 = tearoff self::foo
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///issue_30838.dart:15:15 -> StringConstant("hello")
+Extra constant evaluation: evaluated: 7, effectively constant: 1
diff --git a/pkg/front_end/testcases/regress/issue_31157.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31157.dart.strong.expect
index f102486..f999813 100644
--- a/pkg/front_end/testcases/regress/issue_31157.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31157.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31157.dart:6:16: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   return null?.(1);
 //                ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31157.dart:6:16: Error: Expected an identifier, but got '('.
+Try inserting an identifier before '('.
   return null?.(1);
                ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31157.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31157.dart.strong.transformed.expect
index f102486..f999813 100644
--- a/pkg/front_end/testcases/regress/issue_31157.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31157.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31157.dart:6:16: Error: Expected an identifier, but got '('.
+// Try inserting an identifier before '('.
 //   return null?.(1);
 //                ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31157.dart:6:16: Error: Expected an identifier, but got '('.
+Try inserting an identifier before '('.
   return null?.(1);
                ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31180.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31180.dart.strong.transformed.expect
index 261ed57..49cab5b 100644
--- a/pkg/front_end/testcases/regress/issue_31180.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31180.dart.strong.transformed.expect
@@ -14,3 +14,8 @@
   return let final<BottomType> #t1 = null in #t1.{core::Object::==}(null) ?{dynamic} null : #t1.[](1);
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: Let @ org-dartlang-testcase:///issue_31180.dart:6:10 -> NullConstant(null)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
index ed5c611..059fa66 100644
--- a/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.strong.expect
@@ -14,6 +14,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   for (int i = 0, i > 10; i++) {}
 //                     ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31184.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31184.dart.strong.transformed.expect
index 57aaf8d..5737a9e 100644
--- a/pkg/front_end/testcases/regress/issue_31184.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31184.dart.strong.transformed.expect
@@ -14,6 +14,7 @@
 //                   ^
 //
 // pkg/front_end/testcases/regress/issue_31184.dart:6:21: Error: Expected an identifier, but got '>'.
+// Try inserting an identifier before '>'.
 //   for (int i = 0, i > 10; i++) {}
 //                     ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_31186.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31186.dart.strong.expect
index 8f46e0f..ce4b4c6 100644
--- a/pkg/front_end/testcases/regress/issue_31186.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31186.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31186.dart:6:16: Error: Expected an identifier, but got 'true'.
+// Try inserting an identifier before 'true'.
 //   return null?.true;
 //                ^^^^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31186.dart:6:16: Error: Expected an identifier, but got 'true'.
+Try inserting an identifier before 'true'.
   return null?.true;
                ^^^^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31186.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31186.dart.strong.transformed.expect
index 8f46e0f..ce4b4c6 100644
--- a/pkg/front_end/testcases/regress/issue_31186.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31186.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31186.dart:6:16: Error: Expected an identifier, but got 'true'.
+// Try inserting an identifier before 'true'.
 //   return null?.true;
 //                ^^^^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31186.dart:6:16: Error: Expected an identifier, but got 'true'.
+Try inserting an identifier before 'true'.
   return null?.true;
                ^^^^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31187.dart.strong.expect b/pkg/front_end/testcases/regress/issue_31187.dart.strong.expect
index 6126225..77462b2 100644
--- a/pkg/front_end/testcases/regress/issue_31187.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_31187.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31187.dart:6:16: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //   return null?.1;
 //                ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31187.dart:6:16: Error: Expected an identifier, but got '1'.
+Try inserting an identifier before '1'.
   return null?.1;
                ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31187.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31187.dart.strong.transformed.expect
index 6126225..77462b2 100644
--- a/pkg/front_end/testcases/regress/issue_31187.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31187.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_31187.dart:6:16: Error: Expected an identifier, but got '1'.
+// Try inserting an identifier before '1'.
 //   return null?.1;
 //                ^
 //
@@ -10,6 +11,7 @@
 
 static method bad() → dynamic {
   return invalid-expression "pkg/front_end/testcases/regress/issue_31187.dart:6:16: Error: Expected an identifier, but got '1'.
+Try inserting an identifier before '1'.
   return null?.1;
                ^";
 }
diff --git a/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
index a9152eb..14ec668 100644
--- a/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_31846.dart.strong.transformed.expect
@@ -15,3 +15,7 @@
 constants  {
   #C1 = tearoff self::main
 }
+
+Extra constant evaluation status:
+Evaluated: IsExpression @ org-dartlang-testcase:///issue_31846.dart:6:14 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 26, effectively constant: 1
diff --git a/pkg/front_end/testcases/regress/issue_34614.dart.outline.expect b/pkg/front_end/testcases/regress/issue_34614.dart.outline.expect
index 89401ca..3132fad 100644
--- a/pkg/front_end/testcases/regress/issue_34614.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_34614.dart.outline.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_34614.dart:5:14: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class C { C. }
 //              ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_34614.dart.strong.expect b/pkg/front_end/testcases/regress/issue_34614.dart.strong.expect
index e939413..c556791 100644
--- a/pkg/front_end/testcases/regress/issue_34614.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_34614.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_34614.dart:5:14: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class C { C. }
 //              ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_34614.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_34614.dart.strong.transformed.expect
index e939413..c556791 100644
--- a/pkg/front_end/testcases/regress/issue_34614.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_34614.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_34614.dart:5:14: Error: Expected an identifier, but got '}'.
+// Try inserting an identifier before '}'.
 // class C { C. }
 //              ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_35220.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_35220.dart.strong.transformed.expect
index 321df68..2538af6 100644
--- a/pkg/front_end/testcases/regress/issue_35220.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_35220.dart.strong.transformed.expect
@@ -32,3 +32,8 @@
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: Not @ org-dartlang-testcase:///issue_35220.dart:6:25 -> BoolConstant(true)
+Extra constant evaluation: evaluated: 3, effectively constant: 1
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
index 8cd18d0..67b102e 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
@@ -32,7 +32,8 @@
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: 'extends' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
index 9c3c2e5..3ad0fc9 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
@@ -32,7 +32,8 @@
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: 'extends' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
index 9c3c2e5..3ad0fc9 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
@@ -32,7 +32,8 @@
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: Expected an identifier, but got 'extends'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:18: Error: 'extends' can't be used as an identifier because it's a keyword.
+// Try renaming this to be an identifier that isn't a keyword.
 // class xxx xx XXX extends XXX {
 //                  ^^^^^^^
 //
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
index 99368e0..8436fb3 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -17,3 +17,8 @@
 static field core::int* x;
 static method main() → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///issue_36793.dart:7:2 -> IntConstant(42)
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/regress/issue_37285.dart.outline.expect b/pkg/front_end/testcases/regress/issue_37285.dart.outline.expect
index eb023c1..ffc4431 100644
--- a/pkg/front_end/testcases/regress/issue_37285.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_37285.dart.outline.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_37285.dart:6:17: Error: Expected an identifier, but got ']'.
+// Try inserting an identifier before ']'.
 //   C() : super()[];
 //                 ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_37285.dart.strong.expect b/pkg/front_end/testcases/regress/issue_37285.dart.strong.expect
index ffef555..84ceeef 100644
--- a/pkg/front_end/testcases/regress/issue_37285.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_37285.dart.strong.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_37285.dart:6:17: Error: Expected an identifier, but got ']'.
+// Try inserting an identifier before ']'.
 //   C() : super()[];
 //                 ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_37285.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_37285.dart.strong.transformed.expect
index ffef555..84ceeef 100644
--- a/pkg/front_end/testcases/regress/issue_37285.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_37285.dart.strong.transformed.expect
@@ -3,6 +3,7 @@
 // Problems in library:
 //
 // pkg/front_end/testcases/regress/issue_37285.dart:6:17: Error: Expected an identifier, but got ']'.
+// Try inserting an identifier before ']'.
 //   C() : super()[];
 //                 ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect
index efb076e..19ddd7d 100644
--- a/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.outline.expect
@@ -11,6 +11,7 @@
 //      ^^
 //
 // pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// Try inserting an identifier before '"'.
 // M("${)=
 //   ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect
index 1a54007..255f4ae 100644
--- a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.expect
@@ -11,6 +11,7 @@
 //      ^^
 //
 // pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// Try inserting an identifier before '"'.
 // M("${)=
 //   ^
 //
diff --git a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect
index 1a54007..255f4ae 100644
--- a/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_39035.crash_dart.strong.transformed.expect
@@ -11,6 +11,7 @@
 //      ^^
 //
 // pkg/front_end/testcases/regress/issue_39035.crash_dart:5:3: Error: Expected an identifier, but got '"'.
+// Try inserting an identifier before '"'.
 // M("${)=
 //   ^
 //
diff --git a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
index a081cbc..84c4721 100644
--- a/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/contravariant_getter.dart.strong.transformed.expect
@@ -26,3 +26,8 @@
   let final self::C<core::num*>* #t2 = c in let final core::double* #t3 = 1.5 in (#t2.{self::C::y} as{TypeError,CovarianceCheck} (core::num*) →* void).call(#t3);
 }
 static method main() → void {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_getter.dart:18:49 -> DoubleConstant(1.5)
+Extra constant evaluation: evaluated: 14, effectively constant: 1
diff --git a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.strong.transformed.expect
index 89e5e57..12c20f9 100644
--- a/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks/dynamic_invocation_of_getter.dart.strong.transformed.expect
@@ -30,3 +30,7 @@
 constants  {
   #C1 = tearoff self::h
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///dynamic_invocation_of_getter.dart:14:7 -> DoubleConstant(1.5)
+Extra constant evaluation: evaluated: 10, effectively constant: 1
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
index 9b11bf0c..4656a41 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_combiner.dart.strong.transformed.expect
@@ -57,3 +57,11 @@
   self::B<core::num*, (core::num*) →* void>* x = self::C::y = self::C::y.{self::B::+}(2) as{TypeError,CovarianceCheck} self::B<core::num*, (core::num*) →* void>*;
 }
 static method main() → void {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_combiner.dart:27:5 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_combiner.dart:27:5 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_combiner.dart:28:13 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_combiner.dart:28:13 -> IntConstant(0)
+Extra constant evaluation: evaluated: 58, effectively constant: 4
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.outline.expect
index 5fd91f2..fa1259d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.outline.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.outline.expect
@@ -1,4 +1,15 @@
 library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:30:14: Error: The type 'C<num>' of the getter 'D.value' is not assignable to the type 'int Function(int)' of the setter 'D.value'.
+//  - 'C' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart'.
+//   C<num> get value => getValue;
+//              ^^^^^
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:32:12: Context: This is the declaration of the setter 'D.value'.
+//   void set value(int Function(int) value) {
+//            ^^^^^
+//
 import self as self;
 import "dart:core" as core;
 
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
index 59b4ef8..408ea27 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:30:14: Error: The type 'C<num>' of the getter 'D.value' is not assignable to the type 'int Function(int)' of the setter 'D.value'.
+//  - 'C' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart'.
+//   C<num> get value => getValue;
+//              ^^^^^
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:32:12: Context: This is the declaration of the setter 'D.value'.
+//   void set value(int Function(int) value) {
+//            ^^^^^
+//
 // pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:49:46: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'int Function(int)'.
 //   d.value /*@ checkReturn=(num*) ->* num* */ += 1;
 //                                              ^
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
index 59b4ef8..7907879 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart.strong.transformed.expect
@@ -2,6 +2,14 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:30:14: Error: The type 'C<num>' of the getter 'D.value' is not assignable to the type 'int Function(int)' of the setter 'D.value'.
+//  - 'C' is from 'pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart'.
+//   C<num> get value => getValue;
+//              ^^^^^
+// pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:32:12: Context: This is the declaration of the setter 'D.value'.
+//   void set value(int Function(int) value) {
+//            ^^^^^
+//
 // pkg/front_end/testcases/runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast.dart:49:46: Error: A value of type 'num Function(num)' can't be assigned to a variable of type 'int Function(int)'.
 //   d.value /*@ checkReturn=(num*) ->* num* */ += 1;
 //                                              ^
@@ -89,3 +97,7 @@
   #C1 = tearoff self::numToInt
   #C2 = tearoff self::numToNum
 }
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_generic_return_with_compound_assign_implicit_downcast.dart:50:21 -> IntConstant(0)
+Extra constant evaluation: evaluated: 58, effectively constant: 1
diff --git a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
index 890a09c..e094433 100644
--- a/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/contravariant_index_assign.dart.strong.transformed.expect
@@ -46,3 +46,15 @@
   self::B<(core::num*) →* void>* y = let final self::C<core::num*>* #t9 = c in let final core::int* #t10 = 0 in let final self::B<(core::num*) →* void>* #t11 = #t9.{self::C::[]}(#t10) as{TypeError,CovarianceCheck} self::B<(core::num*) →* void>* in #t11.{self::B::==}(null) ?{self::B<(core::num*) →* void>*} let final self::B<(core::num*) →* void>* #t12 = new self::B::•<(core::num*) →* void>() in let final void #t13 = #t9.{self::C::[]=}(#t10, #t12) in #t12 : #t11;
 }
 static method main() → dynamic {}
+
+
+Extra constant evaluation status:
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:21:45 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:21:45 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:22:53 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:22:53 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:23:45 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:23:45 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:24:53 -> IntConstant(0)
+Evaluated: VariableGet @ org-dartlang-testcase:///contravariant_index_assign.dart:24:53 -> IntConstant(0)
+Extra constant evaluation: evaluated: 64, effectively constant: 8
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
index 1fcfe08..aede924 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.expect
@@ -12,7 +12,7 @@
     : self::A::index = index, self::A::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::A::_name};
+    return this.{self::A::_name};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
index 1fcfe08..aede924 100644
--- a/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/enum.dart.weak.transformed.expect
@@ -12,7 +12,7 @@
     : self::A::index = index, self::A::_name = _name, super core::Object::•()
     ;
   method toString() → core::String
-    return this.{=self::A::_name};
+    return this.{self::A::_name};
 }
 static method main() → dynamic {}
 
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
index d53be31..da6a3f4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.expect
@@ -9,26 +9,39 @@
   field core::int nonNullableInstanceFieldWithInitializer = self::init<core::int>(55);
   field core::int? nullableInstanceFieldWithInitializer = self::init<core::int?>(17);
   static field core::int? _#nonNullableStaticFieldWithInitializer1 = null;
+  static field core::bool _#nonNullableStaticFieldWithInitializer1#isSet = false;
   static field core::int? _#nullableStaticFieldWithInitializer1 = null;
   static field core::bool _#nullableStaticFieldWithInitializer1#isSet = false;
   static field core::int? _#nonNullableStaticFieldWithInitializer2 = null;
+  static field core::bool _#nonNullableStaticFieldWithInitializer2#isSet = false;
   static field core::int? _#nullableStaticFieldWithInitializer2 = null;
   static field core::bool _#nullableStaticFieldWithInitializer2#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer1 = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer1#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer1 = null;
   static field core::bool _#nullableStaticFinalFieldWithInitializer1#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer2Init = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer2Init#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer2 = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer2#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer2Init = null;
+  static field core::bool _#nullableStaticFinalFieldWithInitializer2Init#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer2 = null;
   static field core::bool _#nullableStaticFinalFieldWithInitializer2#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-  static get nonNullableStaticFieldWithInitializer1() → core::int
-    return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1.==(null) ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55) : #t1{core::int};
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void
+  static get nonNullableStaticFieldWithInitializer1() → core::int {
+    if(!self::Class::_#nonNullableStaticFieldWithInitializer1#isSet) {
+      self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55);
+      self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
+    }
+    return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1{core::int};
+  }
+  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void {
+    self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
     self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+  }
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer1 = self::init<core::int?>(17);
@@ -40,10 +53,17 @@
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
     self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
   }
-  static get nonNullableStaticFieldWithInitializer2() → core::int
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4.==(null) ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t4{core::int};
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void
+  static get nonNullableStaticFieldWithInitializer2() → core::int {
+    if(!self::Class::_#nonNullableStaticFieldWithInitializer2#isSet) {
+      self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55);
+      self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4{core::int};
+  }
+  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void {
+    self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
     self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+  }
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer2 = self::init<core::int?>(17);
@@ -55,8 +75,16 @@
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
     self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
   }
-  static get nonNullableStaticFinalFieldWithInitializer1() → core::int
-    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t7.==(null) ?{core::int} let final core::int #t8 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t8 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer1' has been assigned during initialization.") : #t7{core::int};
+  static get nonNullableStaticFinalFieldWithInitializer1() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet) {
+      final core::int #t7 = self::init<core::int>(73);
+      if(self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer1' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t7;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet = true;
+    }
+    return let final core::int? #t8 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t8{core::int};
+  }
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
       final core::int? #t9 = self::init<core::int?>(19);
@@ -67,16 +95,38 @@
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
   }
-  static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t10{core::int};
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void
+  static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet) {
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
+    }
+    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10{core::int};
+  }
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void {
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
     self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
-  static get nonNullableStaticFinalFieldWithInitializer2() → core::int
-    return let final core::int? #t12 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t12.==(null) ?{core::int} let final core::int #t13 = (let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t15 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t14.{core::num::+}(1) in #t14).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1) : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t13 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer2' has been assigned during initialization.") : #t12{core::int};
-  static get nullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16.==(null) ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t16{core::int};
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void
+  }
+  static get nonNullableStaticFinalFieldWithInitializer2() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet) {
+      final core::int #t12 = (let final core::int #t13 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1) : 87;
+      if(self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer2' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t12;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet = true;
+    }
+    return let final core::int? #t15 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t15{core::int};
+  }
+  static get nullableStaticFinalFieldWithInitializer2Init() → core::int {
+    if(!self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet) {
+      self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
+    }
+    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16{core::int};
+  }
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void {
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
     self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+  }
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
       final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1) in #t19).{core::num::==}(0) ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1) : 32;
@@ -92,27 +142,40 @@
 static const field core::int constTopLevelField = #C2;
 static field core::int? topLevelFieldWithoutInitializer;
 static field core::int? _#nonNullableTopLevelFieldWithInitializer1 = null;
+static field core::bool _#nonNullableTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nullableTopLevelFieldWithInitializer = null;
 static field core::bool _#nullableTopLevelFieldWithInitializer#isSet = false;
 static field core::int? _#nonNullableTopLevelFieldWithInitializer2 = null;
+static field core::bool _#nonNullableTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nullableTopLevelFieldWithInitializer2 = null;
 static field core::bool _#nullableTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer1 = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer1 = null;
 static field core::bool _#nullableFinalTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer2Init = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer2 = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer2Init = null;
+static field core::bool _#nullableFinalTopLevelFieldWithInitializer2Init#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer2 = null;
 static field core::bool _#nullableFinalTopLevelFieldWithInitializer2#isSet = false;
 static method init<T extends core::Object? = dynamic>(self::init::T% value) → self::init::T% {
   self::lastInit = value;
   return value;
 }
-static get nonNullableTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t21{core::int};
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void
+static get nonNullableTopLevelFieldWithInitializer1() → core::int {
+  if(!self::_#nonNullableTopLevelFieldWithInitializer1#isSet) {
+    self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42);
+    self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
+  }
+  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21{core::int};
+}
+static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void {
+  self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
   self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+}
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
     self::_#nullableTopLevelFieldWithInitializer = self::init<core::int?>(123);
@@ -124,10 +187,17 @@
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
   self::_#nullableTopLevelFieldWithInitializer = #t23;
 }
-static get nonNullableTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t24{core::int};
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void
+static get nonNullableTopLevelFieldWithInitializer2() → core::int {
+  if(!self::_#nonNullableTopLevelFieldWithInitializer2#isSet) {
+    self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42);
+    self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
+  }
+  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24{core::int};
+}
+static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void {
+  self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
   self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+}
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nullableTopLevelFieldWithInitializer2 = self::init<core::int?>(123);
@@ -139,8 +209,16 @@
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
   self::_#nullableTopLevelFieldWithInitializer2 = #t26;
 }
-static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t27 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t27.==(null) ?{core::int} let final core::int #t28 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t28 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer1' has been assigned during initialization.") : #t27{core::int};
+static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet) {
+    final core::int #t27 = self::init<core::int>(87);
+    if(self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer1' has been assigned during initialization.");
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t27;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet = true;
+  }
+  return let final core::int? #t28 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t28{core::int};
+}
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
     final core::int? #t29 = self::init<core::int?>(32);
@@ -151,16 +229,38 @@
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
 }
-static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t30{core::int};
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void
+static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet) {
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
+  }
+  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30{core::int};
+}
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void {
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
-static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t32 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t32.==(null) ?{core::int} let final core::int #t33 = (let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t35 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t34.{core::num::+}(1) in #t34).{core::num::==}(0) ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1) : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t33 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer2' has been assigned during initialization.") : #t32{core::int};
-static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36.==(null) ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t36{core::int};
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void
+}
+static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet) {
+    final core::int #t32 = (let final core::int #t33 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t33.{core::num::+}(1) in #t33).{core::num::==}(0) ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1) : 87;
+    if(self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer2' has been assigned during initialization.");
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t32;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet = true;
+  }
+  return let final core::int? #t35 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t35{core::int};
+}
+static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int {
+  if(!self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet) {
+    self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0;
+    self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
+  }
+  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36{core::int};
+}
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void {
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+}
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
     final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1) in #t39).{core::num::==}(0) ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1) : 32;
diff --git a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
index d53be31..da6a3f4 100644
--- a/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/static_field_lowering/opt_in.dart.weak.transformed.expect
@@ -9,26 +9,39 @@
   field core::int nonNullableInstanceFieldWithInitializer = self::init<core::int>(55);
   field core::int? nullableInstanceFieldWithInitializer = self::init<core::int?>(17);
   static field core::int? _#nonNullableStaticFieldWithInitializer1 = null;
+  static field core::bool _#nonNullableStaticFieldWithInitializer1#isSet = false;
   static field core::int? _#nullableStaticFieldWithInitializer1 = null;
   static field core::bool _#nullableStaticFieldWithInitializer1#isSet = false;
   static field core::int? _#nonNullableStaticFieldWithInitializer2 = null;
+  static field core::bool _#nonNullableStaticFieldWithInitializer2#isSet = false;
   static field core::int? _#nullableStaticFieldWithInitializer2 = null;
   static field core::bool _#nullableStaticFieldWithInitializer2#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer1 = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer1#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer1 = null;
   static field core::bool _#nullableStaticFinalFieldWithInitializer1#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer2Init = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer2Init#isSet = false;
   static field core::int? _#nonNullableStaticFinalFieldWithInitializer2 = null;
+  static field core::bool _#nonNullableStaticFinalFieldWithInitializer2#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer2Init = null;
+  static field core::bool _#nullableStaticFinalFieldWithInitializer2Init#isSet = false;
   static field core::int? _#nullableStaticFinalFieldWithInitializer2 = null;
   static field core::bool _#nullableStaticFinalFieldWithInitializer2#isSet = false;
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-  static get nonNullableStaticFieldWithInitializer1() → core::int
-    return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1.==(null) ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55) : #t1{core::int};
-  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void
+  static get nonNullableStaticFieldWithInitializer1() → core::int {
+    if(!self::Class::_#nonNullableStaticFieldWithInitializer1#isSet) {
+      self::Class::_#nonNullableStaticFieldWithInitializer1 = self::init<core::int>(55);
+      self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
+    }
+    return let final core::int? #t1 = self::Class::_#nonNullableStaticFieldWithInitializer1 in #t1{core::int};
+  }
+  static set nonNullableStaticFieldWithInitializer1(core::int #t2) → void {
+    self::Class::_#nonNullableStaticFieldWithInitializer1#isSet = true;
     self::Class::_#nonNullableStaticFieldWithInitializer1 = #t2;
+  }
   static get nullableStaticFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer1#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer1 = self::init<core::int?>(17);
@@ -40,10 +53,17 @@
     self::Class::_#nullableStaticFieldWithInitializer1#isSet = true;
     self::Class::_#nullableStaticFieldWithInitializer1 = #t3;
   }
-  static get nonNullableStaticFieldWithInitializer2() → core::int
-    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4.==(null) ?{core::int} self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55) : #t4{core::int};
-  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void
+  static get nonNullableStaticFieldWithInitializer2() → core::int {
+    if(!self::Class::_#nonNullableStaticFieldWithInitializer2#isSet) {
+      self::Class::_#nonNullableStaticFieldWithInitializer2 = self::init<core::int>(55);
+      self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
+    }
+    return let final core::int? #t4 = self::Class::_#nonNullableStaticFieldWithInitializer2 in #t4{core::int};
+  }
+  static set nonNullableStaticFieldWithInitializer2(core::int #t5) → void {
+    self::Class::_#nonNullableStaticFieldWithInitializer2#isSet = true;
     self::Class::_#nonNullableStaticFieldWithInitializer2 = #t5;
+  }
   static get nullableStaticFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFieldWithInitializer2#isSet) {
       self::Class::_#nullableStaticFieldWithInitializer2 = self::init<core::int?>(17);
@@ -55,8 +75,16 @@
     self::Class::_#nullableStaticFieldWithInitializer2#isSet = true;
     self::Class::_#nullableStaticFieldWithInitializer2 = #t6;
   }
-  static get nonNullableStaticFinalFieldWithInitializer1() → core::int
-    return let final core::int? #t7 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t7.==(null) ?{core::int} let final core::int #t8 = self::init<core::int>(73) in self::Class::_#nonNullableStaticFinalFieldWithInitializer1.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t8 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer1' has been assigned during initialization.") : #t7{core::int};
+  static get nonNullableStaticFinalFieldWithInitializer1() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet) {
+      final core::int #t7 = self::init<core::int>(73);
+      if(self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer1' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1 = #t7;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer1#isSet = true;
+    }
+    return let final core::int? #t8 = self::Class::_#nonNullableStaticFinalFieldWithInitializer1 in #t8{core::int};
+  }
   static get nullableStaticFinalFieldWithInitializer1() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer1#isSet) {
       final core::int? #t9 = self::init<core::int?>(19);
@@ -67,16 +95,38 @@
     }
     return self::Class::_#nullableStaticFinalFieldWithInitializer1;
   }
-  static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0 : #t10{core::int};
-  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void
+  static get nonNullableStaticFinalFieldWithInitializer2Init() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet) {
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = 0;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
+    }
+    return let final core::int? #t10 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init in #t10{core::int};
+  }
+  static set nonNullableStaticFinalFieldWithInitializer2Init(core::int #t11) → void {
+    self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init#isSet = true;
     self::Class::_#nonNullableStaticFinalFieldWithInitializer2Init = #t11;
-  static get nonNullableStaticFinalFieldWithInitializer2() → core::int
-    return let final core::int? #t12 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t12.==(null) ?{core::int} let final core::int #t13 = (let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t15 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t14.{core::num::+}(1) in #t14).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1) : 87 in self::Class::_#nonNullableStaticFinalFieldWithInitializer2.==(null) ?{core::int} self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t13 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer2' has been assigned during initialization.") : #t12{core::int};
-  static get nullableStaticFinalFieldWithInitializer2Init() → core::int
-    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16.==(null) ?{core::int} self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0 : #t16{core::int};
-  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void
+  }
+  static get nonNullableStaticFinalFieldWithInitializer2() → core::int {
+    if(!self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet) {
+      final core::int #t12 = (let final core::int #t13 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init in let final core::int #t14 = self::Class::nonNullableStaticFinalFieldWithInitializer2Init = #t13.{core::num::+}(1) in #t13).{core::num::==}(0) ?{core::int} self::Class::nonNullableStaticFinalFieldWithInitializer2.{core::num::+}(1) : 87;
+      if(self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet)
+        throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableStaticFinalFieldWithInitializer2' has been assigned during initialization.");
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2 = #t12;
+      self::Class::_#nonNullableStaticFinalFieldWithInitializer2#isSet = true;
+    }
+    return let final core::int? #t15 = self::Class::_#nonNullableStaticFinalFieldWithInitializer2 in #t15{core::int};
+  }
+  static get nullableStaticFinalFieldWithInitializer2Init() → core::int {
+    if(!self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet) {
+      self::Class::_#nullableStaticFinalFieldWithInitializer2Init = 0;
+      self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
+    }
+    return let final core::int? #t16 = self::Class::_#nullableStaticFinalFieldWithInitializer2Init in #t16{core::int};
+  }
+  static set nullableStaticFinalFieldWithInitializer2Init(core::int #t17) → void {
+    self::Class::_#nullableStaticFinalFieldWithInitializer2Init#isSet = true;
     self::Class::_#nullableStaticFinalFieldWithInitializer2Init = #t17;
+  }
   static get nullableStaticFinalFieldWithInitializer2() → core::int? {
     if(!self::Class::_#nullableStaticFinalFieldWithInitializer2#isSet) {
       final core::int? #t18 = (let final core::int #t19 = self::Class::nullableStaticFinalFieldWithInitializer2Init in let final core::int #t20 = self::Class::nullableStaticFinalFieldWithInitializer2Init = #t19.{core::num::+}(1) in #t19).{core::num::==}(0) ?{core::int} self::Class::nullableStaticFinalFieldWithInitializer2!.{core::num::+}(1) : 32;
@@ -92,27 +142,40 @@
 static const field core::int constTopLevelField = #C2;
 static field core::int? topLevelFieldWithoutInitializer;
 static field core::int? _#nonNullableTopLevelFieldWithInitializer1 = null;
+static field core::bool _#nonNullableTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nullableTopLevelFieldWithInitializer = null;
 static field core::bool _#nullableTopLevelFieldWithInitializer#isSet = false;
 static field core::int? _#nonNullableTopLevelFieldWithInitializer2 = null;
+static field core::bool _#nonNullableTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nullableTopLevelFieldWithInitializer2 = null;
 static field core::bool _#nullableTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer1 = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer1 = null;
 static field core::bool _#nullableFinalTopLevelFieldWithInitializer1#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer2Init = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = false;
 static field core::int? _#nonNullableFinalTopLevelFieldWithInitializer2 = null;
+static field core::bool _#nonNullableFinalTopLevelFieldWithInitializer2#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer2Init = null;
+static field core::bool _#nullableFinalTopLevelFieldWithInitializer2Init#isSet = false;
 static field core::int? _#nullableFinalTopLevelFieldWithInitializer2 = null;
 static field core::bool _#nullableFinalTopLevelFieldWithInitializer2#isSet = false;
 static method init<T extends core::Object? = dynamic>(self::init::T% value) → self::init::T% {
   self::lastInit = value;
   return value;
 }
-static get nonNullableTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42) : #t21{core::int};
-static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void
+static get nonNullableTopLevelFieldWithInitializer1() → core::int {
+  if(!self::_#nonNullableTopLevelFieldWithInitializer1#isSet) {
+    self::_#nonNullableTopLevelFieldWithInitializer1 = self::init<core::int>(42);
+    self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
+  }
+  return let final core::int? #t21 = self::_#nonNullableTopLevelFieldWithInitializer1 in #t21{core::int};
+}
+static set nonNullableTopLevelFieldWithInitializer1(core::int #t22) → void {
+  self::_#nonNullableTopLevelFieldWithInitializer1#isSet = true;
   self::_#nonNullableTopLevelFieldWithInitializer1 = #t22;
+}
 static get nullableTopLevelFieldWithInitializer() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer#isSet) {
     self::_#nullableTopLevelFieldWithInitializer = self::init<core::int?>(123);
@@ -124,10 +187,17 @@
   self::_#nullableTopLevelFieldWithInitializer#isSet = true;
   self::_#nullableTopLevelFieldWithInitializer = #t23;
 }
-static get nonNullableTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24.==(null) ?{core::int} self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42) : #t24{core::int};
-static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void
+static get nonNullableTopLevelFieldWithInitializer2() → core::int {
+  if(!self::_#nonNullableTopLevelFieldWithInitializer2#isSet) {
+    self::_#nonNullableTopLevelFieldWithInitializer2 = self::init<core::int>(42);
+    self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
+  }
+  return let final core::int? #t24 = self::_#nonNullableTopLevelFieldWithInitializer2 in #t24{core::int};
+}
+static set nonNullableTopLevelFieldWithInitializer2(core::int #t25) → void {
+  self::_#nonNullableTopLevelFieldWithInitializer2#isSet = true;
   self::_#nonNullableTopLevelFieldWithInitializer2 = #t25;
+}
 static get nullableTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableTopLevelFieldWithInitializer2#isSet) {
     self::_#nullableTopLevelFieldWithInitializer2 = self::init<core::int?>(123);
@@ -139,8 +209,16 @@
   self::_#nullableTopLevelFieldWithInitializer2#isSet = true;
   self::_#nullableTopLevelFieldWithInitializer2 = #t26;
 }
-static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int
-  return let final core::int? #t27 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t27.==(null) ?{core::int} let final core::int #t28 = self::init<core::int>(87) in self::_#nonNullableFinalTopLevelFieldWithInitializer1.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t28 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer1' has been assigned during initialization.") : #t27{core::int};
+static get nonNullableFinalTopLevelFieldWithInitializer1() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet) {
+    final core::int #t27 = self::init<core::int>(87);
+    if(self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer1' has been assigned during initialization.");
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1 = #t27;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer1#isSet = true;
+  }
+  return let final core::int? #t28 = self::_#nonNullableFinalTopLevelFieldWithInitializer1 in #t28{core::int};
+}
 static get nullableFinalTopLevelFieldWithInitializer1() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer1#isSet) {
     final core::int? #t29 = self::init<core::int?>(32);
@@ -151,16 +229,38 @@
   }
   return self::_#nullableFinalTopLevelFieldWithInitializer1;
 }
-static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0 : #t30{core::int};
-static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void
+static get nonNullableFinalTopLevelFieldWithInitializer2Init() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet) {
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = 0;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
+  }
+  return let final core::int? #t30 = self::_#nonNullableFinalTopLevelFieldWithInitializer2Init in #t30{core::int};
+}
+static set nonNullableFinalTopLevelFieldWithInitializer2Init(core::int #t31) → void {
+  self::_#nonNullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   self::_#nonNullableFinalTopLevelFieldWithInitializer2Init = #t31;
-static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int
-  return let final core::int? #t32 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t32.==(null) ?{core::int} let final core::int #t33 = (let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t35 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t34.{core::num::+}(1) in #t34).{core::num::==}(0) ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1) : 87 in self::_#nonNullableFinalTopLevelFieldWithInitializer2.==(null) ?{core::int} self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t33 : throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer2' has been assigned during initialization.") : #t32{core::int};
-static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int
-  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36.==(null) ?{core::int} self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0 : #t36{core::int};
-static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void
+}
+static get nonNullableFinalTopLevelFieldWithInitializer2() → core::int {
+  if(!self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet) {
+    final core::int #t32 = (let final core::int #t33 = self::nonNullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t34 = self::nonNullableFinalTopLevelFieldWithInitializer2Init = #t33.{core::num::+}(1) in #t33).{core::num::==}(0) ?{core::int} self::nonNullableFinalTopLevelFieldWithInitializer2.{core::num::+}(1) : 87;
+    if(self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet)
+      throw new _in::LateInitializationErrorImpl::•("Field 'nonNullableFinalTopLevelFieldWithInitializer2' has been assigned during initialization.");
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2 = #t32;
+    self::_#nonNullableFinalTopLevelFieldWithInitializer2#isSet = true;
+  }
+  return let final core::int? #t35 = self::_#nonNullableFinalTopLevelFieldWithInitializer2 in #t35{core::int};
+}
+static get nullableFinalTopLevelFieldWithInitializer2Init() → core::int {
+  if(!self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet) {
+    self::_#nullableFinalTopLevelFieldWithInitializer2Init = 0;
+    self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
+  }
+  return let final core::int? #t36 = self::_#nullableFinalTopLevelFieldWithInitializer2Init in #t36{core::int};
+}
+static set nullableFinalTopLevelFieldWithInitializer2Init(core::int #t37) → void {
+  self::_#nullableFinalTopLevelFieldWithInitializer2Init#isSet = true;
   self::_#nullableFinalTopLevelFieldWithInitializer2Init = #t37;
+}
 static get nullableFinalTopLevelFieldWithInitializer2() → core::int? {
   if(!self::_#nullableFinalTopLevelFieldWithInitializer2#isSet) {
     final core::int? #t38 = (let final core::int #t39 = self::nullableFinalTopLevelFieldWithInitializer2Init in let final core::int #t40 = self::nullableFinalTopLevelFieldWithInitializer2Init = #t39.{core::num::+}(1) in #t39).{core::num::==}(0) ?{core::int} self::nullableFinalTopLevelFieldWithInitializer2!.{core::num::+}(1) : 32;
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 524c1c577..c15549a 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -62,6 +62,7 @@
 general/error_recovery/yield_not_in_generator: RuntimeError
 general/expressions: RuntimeError
 general/external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
+general/getter_vs_setter_type: TypeCheckError
 general/incomplete_field_formal_parameter: RuntimeError
 general/infer_field_from_multiple: TypeCheckError
 general/invalid_operator: TypeCheckError
@@ -88,7 +89,6 @@
 general/override_setter_with_field: TypeCheckError
 general/reject_generic_function_types_in_bounds: RuntimeError # Expected
 general/spread_collection: RuntimeError
-general/statements: Crash
 general/type_parameter_type_named_int: RuntimeError # Expected
 general/type_variable_as_super: RuntimeError
 general/type_variable_bound_access: TypeCheckError
@@ -171,7 +171,10 @@
 instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError # Expected
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError # Expected
 late_lowering/covariant_late_field: TypeCheckError
+late_lowering/initializer_rewrite_from_opt_out: RuntimeError # Test is inherently mixed mode
+late_lowering/non_nullable_from_opt_out: RuntimeError # Test is inherently mixed mode
 nnbd/covariant_late_field: TypeCheckError
+nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError # Strong mode runtime checking fails due to mixed strong mode.
 nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
@@ -255,4 +258,5 @@
 set_literals/disambiguation_rule: RuntimeError
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
-value_class/value_implements_non_value: RuntimeError # Expected
\ No newline at end of file
+value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index b68d320..3c35730 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -24,6 +24,10 @@
 general/callable_type_variable: TypeCheckError
 general/candidate_found: TypeCheckError
 general/cascade: RuntimeError
+general/constants/with_unevaluated_agnostic/const_asserts: TextSerializationFailure
+general/constants/with_unevaluated_agnostic/const_collections: TextSerializationFailure
+general/constants/with_unevaluated_agnostic/various: TextSerializationFailure
+general/constants/with_unevaluated_agnostic/various_2: TextSerializationFailure
 general/constructor_initializer_invalid: RuntimeError
 general/covariant_field: TypeCheckError
 general/covariant_generic: RuntimeError
@@ -62,6 +66,7 @@
 general/error_recovery/yield_not_in_generator: RuntimeError
 general/expressions: RuntimeError
 general/external_import: RuntimeError
+general/getter_vs_setter_type: TypeCheckError
 general/incomplete_field_formal_parameter: RuntimeError
 general/infer_field_from_multiple: TypeCheckError
 general/invalid_operator: TypeCheckError
@@ -87,7 +92,6 @@
 general/override_setter_with_field: TypeCheckError
 general/reject_generic_function_types_in_bounds: RuntimeError
 general/spread_collection: RuntimeError # Should be fixed as part of implementing spread collection support
-general/statements: Crash
 general/type_parameter_type_named_int: RuntimeError
 general/type_variable_as_super: RuntimeError
 general/type_variable_bound_access: TypeCheckError
@@ -169,7 +173,10 @@
 instantiate_to_bound/non_simple_class_parametrized_typedef_cycle: RuntimeError
 instantiate_to_bound/non_simple_generic_function_in_bound_regress: RuntimeError
 late_lowering/covariant_late_field: TypeCheckError
+late_lowering/initializer_rewrite_from_opt_out: RuntimeError # Test is inherently mixed mode
+late_lowering/non_nullable_from_opt_out: RuntimeError # Test is inherently mixed mode
 nnbd/covariant_late_field: TypeCheckError
+nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue41180: RuntimeError
 nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
@@ -253,3 +260,4 @@
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
 value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index 229c220..c551669 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -22,6 +22,7 @@
 
 extensions/ambiguous: FormatterCrash
 extensions/annotations: FormatterCrash
+extensions/async_extensions: FormatterCrash
 extensions/bounds: FormatterCrash
 extensions/builtin_identifiers: FormatterCrash
 extensions/call_methods: FormatterCrash
@@ -41,17 +42,18 @@
 extensions/extension_call: FormatterCrash
 extensions/extension_constructor: FormatterCrash
 extensions/extension_field_with_type_parameter_usage: FormatterCrash
+extensions/extension_member_conflict: FormatterCrash
 extensions/extension_methods: FormatterCrash
-extensions/extension_setter_error: FormatterCrash
 extensions/extension_setter: FormatterCrash
+extensions/extension_setter_error: FormatterCrash
 extensions/generic_function_in_generic_extension: FormatterCrash
 extensions/getter_setter_conflict: FormatterCrash
 extensions/if_null: FormatterCrash
 extensions/implicit_extension_inference: FormatterCrash
 extensions/implicit_this: FormatterCrash
 extensions/index: FormatterCrash
-extensions/instance_access_of_static: FormatterCrash
 extensions/instance_access: FormatterCrash
+extensions/instance_access_of_static: FormatterCrash
 extensions/instance_members: FormatterCrash
 extensions/instance_tearoff: FormatterCrash
 extensions/internal_resolution: FormatterCrash
@@ -77,26 +79,19 @@
 extensions/on_type_variable_inference: FormatterCrash
 extensions/operators: FormatterCrash
 extensions/other_kinds: FormatterCrash
-extensions/static_access_of_instance: FormatterCrash
 extensions/static_access: FormatterCrash
+extensions/static_access_of_instance: FormatterCrash
 extensions/tear_offs: FormatterCrash
 extensions/type_variables: FormatterCrash
 extensions/unnamed_extensions: FormatterCrash
 extensions/use_this: FormatterCrash
-general_nnbd_opt_out/annotation_eof: FormatterCrash
-general_nnbd_opt_out/bad_setter_abstract: FormatterCrash
-general_nnbd_opt_out/bug31124: FormatterCrash
-general_nnbd_opt_out/clone_function_type: FormatterCrash
-general_nnbd_opt_out/constructor_initializer_invalid: FormatterCrash
-general_nnbd_opt_out/duplicated_declarations: FormatterCrash
-general_nnbd_opt_out/function_type_default_value: FormatterCrash
-general_nnbd_opt_out/incomplete_field_formal_parameter: FormatterCrash
-general_nnbd_opt_out/many_errors: FormatterCrash
-general_nnbd_opt_out/var_as_type_name: FormatterCrash
 general/annotation_eof: FormatterCrash
 general/bad_setter_abstract: FormatterCrash
 general/bug31124: FormatterCrash
 general/clone_function_type: FormatterCrash
+general/constants/js_semantics/number_folds: FormatterCrash
+general/constants/number_folds: FormatterCrash
+general/constants/various: FormatterCrash
 general/constructor_initializer_invalid: FormatterCrash
 general/duplicated_declarations: FormatterCrash
 general/error_recovery/annotations: FormatterCrash
@@ -115,9 +110,10 @@
 general/error_recovery/issue_39230.crash: FormatterCrash
 general/error_recovery/issue_39958_01: FormatterCrash
 general/function_type_default_value: FormatterCrash
+general/getter_vs_setter_type: FormatterCrash
 general/incomplete_field_formal_parameter: FormatterCrash
-general/invalid_operator: FormatterCrash
 general/invalid_operator2: FormatterCrash
+general/invalid_operator: FormatterCrash
 general/issue40242: FormatterCrash
 general/issue42997: FormatterCrash
 general/many_errors: FormatterCrash
@@ -126,11 +122,23 @@
 general/type_parameters_on_void: FormatterCrash
 general/var_as_type_name: FormatterCrash
 general/well_boundness_checks_in_outline: FormatterCrash
+general_nnbd_opt_out/annotation_eof: FormatterCrash
+general_nnbd_opt_out/bad_setter_abstract: FormatterCrash
+general_nnbd_opt_out/bug31124: FormatterCrash
+general_nnbd_opt_out/clone_function_type: FormatterCrash
+general_nnbd_opt_out/constructor_initializer_invalid: FormatterCrash
+general_nnbd_opt_out/duplicated_declarations: FormatterCrash
+general_nnbd_opt_out/function_type_default_value: FormatterCrash
+general_nnbd_opt_out/incomplete_field_formal_parameter: FormatterCrash
+general_nnbd_opt_out/many_errors: FormatterCrash
+general_nnbd_opt_out/var_as_type_name: FormatterCrash
 inference/unsafe_block_closure_inference_function_call_explicit_dynamic_param_via_expr1: FormatterCrash
 inference/unsafe_block_closure_inference_function_call_explicit_type_param_via_expr1: FormatterCrash
 late_lowering/covariant_late_field: FormatterCrash
+late_lowering/getter_vs_setter_type: FormatterCrash
 late_lowering/infer_late_field_type: FormatterCrash
 late_lowering/initializer_rewrite: FormatterCrash
+late_lowering/initializer_rewrite_from_opt_out: FormatterCrash
 late_lowering/instance_field_with_initializer: FormatterCrash
 late_lowering/instance_field_without_initializer: FormatterCrash
 late_lowering/instance_final_field_without_initializer: FormatterCrash
@@ -155,16 +163,10 @@
 late_lowering/late_nullable_field_with_initializer: FormatterCrash
 late_lowering/late_nullable_field_without_initializer: FormatterCrash
 late_lowering/later: FormatterCrash
-late_lowering/override_getter_setter: FormatterCrash
 late_lowering/override: FormatterCrash
+late_lowering/override_getter_setter: FormatterCrash
 late_lowering/uninitialized_non_nullable_late_fields: FormatterCrash
-nnbd_mixed/inheritance_from_opt_in: FormatterCrash
-nnbd_mixed/issue41597: FormatterCrash
-nnbd_mixed/no_null_shorting_explicit_extension: FormatterCrash
-nnbd_mixed/no_null_shorting_extension: FormatterCrash
-nnbd_mixed/null_safety_invalid_language_version: FormatterCrash
-nnbd_mixed/nullable_extension_on_opt_out: FormatterCrash
-nnbd_mixed/opt_out: FormatterCrash
+late_lowering_sentinel/late_fields: FormatterCrash
 nnbd/abstract_field_errors: FormatterCrash
 nnbd/covariant_late_field: FormatterCrash
 nnbd/extension_bounds: FormatterCrash
@@ -172,11 +174,18 @@
 nnbd/external_field_errors: FormatterCrash
 nnbd/external_fields: FormatterCrash
 nnbd/forbidden_supers: FormatterCrash
+nnbd/getter_vs_setter_type: FormatterCrash
+nnbd/getter_vs_setter_type_late: FormatterCrash
+nnbd/getter_vs_setter_type_nnbd: FormatterCrash
 nnbd/infer_if_null: FormatterCrash
 nnbd/inheritance_from_opt_in: FormatterCrash
 nnbd/issue40805: FormatterCrash
 nnbd/issue41349: FormatterCrash
 nnbd/issue41597: FormatterCrash
+nnbd/issue42967: FormatterCrash
+nnbd/issue43211: FormatterCrash
+nnbd/issue43278: FormatterCrash
+nnbd/issue43354: FormatterCrash
 nnbd/late: FormatterCrash
 nnbd/later: FormatterCrash
 nnbd/no_null_shorting_explicit_extension: FormatterCrash
@@ -193,6 +202,14 @@
 nnbd/potentially_nullable_access: FormatterCrash
 nnbd/strictly_non_nullable_warnings: FormatterCrash
 nnbd/uninitialized_non_nullable_late_fields: FormatterCrash
+nnbd_mixed/inheritance_from_opt_in: FormatterCrash
+nnbd_mixed/issue41597: FormatterCrash
+nnbd_mixed/no_null_shorting_explicit_extension: FormatterCrash
+nnbd_mixed/no_null_shorting_extension: FormatterCrash
+nnbd_mixed/null_safety_invalid_language_version: FormatterCrash
+nnbd_mixed/nullable_extension_on_opt_out: FormatterCrash
+nnbd_mixed/opt_out: FormatterCrash
+nnbd_mixed/unsound_checks: FormatterCrash
 nonfunction_type_aliases/issue41501: FormatterCrash
 rasta/bad_redirection: FormatterCrash
 rasta/issue_000032: FormatterCrash
diff --git a/pkg/front_end/testcases/unified_collections/string_concatenation.dart.strong.transformed.expect b/pkg/front_end/testcases/unified_collections/string_concatenation.dart.strong.transformed.expect
index 930929b..b5ffe41 100644
--- a/pkg/front_end/testcases/unified_collections/string_concatenation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/unified_collections/string_concatenation.dart.strong.transformed.expect
@@ -11,3 +11,9 @@
       #t1.{core::List::add}("cd");
   } =>#t1;
 }
+
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///string_concatenation.dart:7:3 -> StringConstant("ab")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///string_concatenation.dart:7:18 -> StringConstant("cd")
+Extra constant evaluation: evaluated: 10, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart
new file mode 100644
index 0000000..a878e4a
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'value_class_support_lib.dart';
+
+class Animal {
+  final int? numberOfLegs;
+  Animal({required this.numberOfLegs});
+}
+
+@valueClass
+class Cat extends Animal {
+  final int? numberOfWhiskers;
+}
+
+class Foo {
+  int? bar, bar2;
+  Foo({this.bar, this.bar2});
+  Foo copyWith({int bar, int bar2}) {
+    return Foo(bar, bar2);
+  }
+}
+
+@valueClass
+class A {}
+
+main() {
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+ // positive case
+ Cat cat2 = (cat as dynamic).copyWith(numberOfWhiskers: 4) as Cat;
+ // nested case
+ Cat cat3 = ((((cat as dynamic).copyWith(numberOfWhiskers: 4) as Cat) as dynamic).copyWith(numberOfLegs: 3) as Cat);
+ // wrong right hand side
+ Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+ // empty arguments
+ Cat cat5 = (cat as dynamic).copyWith() as Cat;
+ // Some existing fields, extra arguments.
+ Cat cat6 = (cat as dynamic).copyWith(numberOfWhiskers: 4, numberOfHorns: 5) as Cat;
+
+ A a;
+ // No fields, extra arguments.
+ A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+
+
+ Foo foo = Foo(bar: 4, bar2: 5);
+ // wrong left hand side
+ Foo foo2 = (foo as dynamic).copyWith(bar: 4) as Foo;
+}
+
+
+
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect
new file mode 100644
index 0000000..93422d0
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.outline.expect
@@ -0,0 +1,64 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:21: Error: Optional parameter 'bar' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                     ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:30: Error: Optional parameter 'bar2' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                              ^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+  final field core::int? numberOfLegs;
+  constructor •({required core::int? numberOfLegs}) → self::Animal
+    ;
+}
+@val::valueClass
+class Cat extends self::Animal {
+  final field core::int? numberOfWhiskers;
+  synthetic constructor •() → self::Cat
+    ;
+}
+class Foo extends core::Object {
+  field core::int? bar;
+  field core::int? bar2;
+  constructor •({core::int? bar, core::int? bar2}) → self::Foo
+    ;
+  method copyWith({core::int bar, core::int bar2}) → self::Foo
+    ;
+}
+@val::valueClass
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    ;
+}
+static method main() → dynamic
+  ;
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+  synthetic constructor •() → val::JenkinsSmiHash
+    ;
+  static method combine(core::int hash, core::int value) → core::int
+    ;
+  static method finish(core::int hash) → core::int
+    ;
+}
+static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///copy_with_call_sites.dart:12:2 -> StringConstant("valueClass")
+Evaluated: StaticGet @ org-dartlang-testcase:///copy_with_call_sites.dart:25:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect
new file mode 100644
index 0000000..e404600
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:21: Error: Optional parameter 'bar' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                     ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:30: Error: Optional parameter 'bar2' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                              ^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     return Foo(bar, bar2);
+//               ^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:19:3: Context: Found this candidate, but the arguments don't match.
+//   Foo({this.bar, this.bar2});
+//   ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+//  Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+//                    ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+//       ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+//  - 'Object' is from 'dart:core'.
+// Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+//  Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+//                             ^^^^^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+//  A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+//          ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:14: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int? numberOfWhiskers;
+//              ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+  final field core::int? numberOfLegs;
+  constructor •({required core::int? numberOfLegs = #C1}) → self::Animal
+    : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+    ;
+}
+class Cat extends self::Animal {
+  final field core::int? numberOfWhiskers = null;
+  synthetic constructor •({required core::int? numberOfWhiskers, core::int? numberOfLegs}) → self::Cat
+    : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int? numberOfLegs, core::int? numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+class Foo extends core::Object {
+  field core::int? bar;
+  field core::int? bar2;
+  constructor •({core::int? bar = #C1, core::int? bar2 = #C1}) → self::Foo
+    : self::Foo::bar = bar, self::Foo::bar2 = bar2, super core::Object::•()
+    ;
+  method copyWith({core::int bar = #C1, core::int bar2 = #C1}) → self::Foo {
+    return invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    return Foo(bar, bar2);
+              ^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo;
+  }
+}
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///copy_with_call_sites.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
+}
+static method main() → dynamic {
+  self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+                   ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+  self::Cat cat2 = (let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat3 = (let final dynamic #t2 = ((cat as{ForNonNullableByDefault} dynamic).copyWith(numberOfWhiskers: 4) as{ForNonNullableByDefault} self::Cat) as{ForNonNullableByDefault} dynamic in #t2.copyWith(numberOfWhiskers: #t2.numberOfWhiskers, numberOfLegs: 3)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat4 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+ - 'Object' is from 'dart:core'.
+Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+ Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+                            ^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+  self::Cat cat5 = (let final dynamic #t3 = cat as{ForNonNullableByDefault} dynamic in #t3.copyWith(numberOfWhiskers: #t3.numberOfWhiskers, numberOfLegs: #t3.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat6 = (let final dynamic #t4 = cat as{ForNonNullableByDefault} dynamic in #t4.copyWith(numberOfWhiskers: 4, numberOfLegs: #t4.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::A a;
+  self::A a2 = (let final dynamic #t5 = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+ A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+         ^" in a) as{ForNonNullableByDefault} dynamic in #t5.copyWith()) as{ForNonNullableByDefault} self::A;
+  self::Foo foo = new self::Foo::•(bar: 4, bar2: 5);
+  self::Foo foo2 = (foo as{ForNonNullableByDefault} dynamic).copyWith(bar: 4) as{ForNonNullableByDefault} self::Foo;
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+  synthetic constructor •() → val::JenkinsSmiHash
+    : super core::Object::•()
+    ;
+  static method combine(core::int hash, core::int value) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+    return hash.{core::int::^}(hash.{core::int::>>}(6));
+  }
+  static method finish(core::int hash) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+    hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+    return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+  }
+}
+static const field core::String valueClass = #C2;
+
+constants  {
+  #C1 = null
+  #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect
new file mode 100644
index 0000000..90ed8ba
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.strong.transformed.expect
@@ -0,0 +1,144 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:21: Error: Optional parameter 'bar' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                     ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:30: Error: Optional parameter 'bar2' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                              ^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     return Foo(bar, bar2);
+//               ^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:19:3: Context: Found this candidate, but the arguments don't match.
+//   Foo({this.bar, this.bar2});
+//   ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+//  Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+//                    ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+//       ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+//  - 'Object' is from 'dart:core'.
+// Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+//  Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+//                             ^^^^^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+//  A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+//          ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:14: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int? numberOfWhiskers;
+//              ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+  final field core::int? numberOfLegs;
+  constructor •({required core::int? numberOfLegs = #C1}) → self::Animal
+    : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+    ;
+}
+class Cat extends self::Animal {
+  final field core::int? numberOfWhiskers = null;
+  synthetic constructor •({required core::int? numberOfWhiskers, core::int? numberOfLegs}) → self::Cat
+    : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int? numberOfLegs, core::int? numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+class Foo extends core::Object {
+  field core::int? bar;
+  field core::int? bar2;
+  constructor •({core::int? bar = #C1, core::int? bar2 = #C1}) → self::Foo
+    : self::Foo::bar = bar, self::Foo::bar2 = bar2, super core::Object::•()
+    ;
+  method copyWith({core::int bar = #C1, core::int bar2 = #C1}) → self::Foo {
+    return invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    return Foo(bar, bar2);
+              ^";
+  }
+}
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///copy_with_call_sites.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
+}
+static method main() → dynamic {
+  self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+                   ^^^^^^^^^^^^^^^^";
+  self::Cat cat2 = (let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat3 = (let final dynamic #t2 = ((cat as{ForNonNullableByDefault} dynamic).copyWith(numberOfWhiskers: 4) as{ForNonNullableByDefault} self::Cat) as{ForNonNullableByDefault} dynamic in #t2.copyWith(numberOfWhiskers: #t2.numberOfWhiskers, numberOfLegs: 3)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat4 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+ - 'Object' is from 'dart:core'.
+Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+ Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+                            ^^^^^^^^";
+  self::Cat cat5 = (let final dynamic #t3 = cat as{ForNonNullableByDefault} dynamic in #t3.copyWith(numberOfWhiskers: #t3.numberOfWhiskers, numberOfLegs: #t3.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat6 = (let final dynamic #t4 = cat as{ForNonNullableByDefault} dynamic in #t4.copyWith(numberOfWhiskers: 4, numberOfLegs: #t4.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::A a;
+  self::A a2 = (let final dynamic #t5 = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+ A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+         ^" in a) as{ForNonNullableByDefault} dynamic in #t5.copyWith()) as{ForNonNullableByDefault} self::A;
+  self::Foo foo = new self::Foo::•(bar: 4, bar2: 5);
+  self::Foo foo2 = (foo as{ForNonNullableByDefault} dynamic).copyWith(bar: 4) as{ForNonNullableByDefault} self::Foo;
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+  synthetic constructor •() → val::JenkinsSmiHash
+    : super core::Object::•()
+    ;
+  static method combine(core::int hash, core::int value) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+    return hash.{core::int::^}(hash.{core::int::>>}(6));
+  }
+  static method finish(core::int hash) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+    hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+    return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+  }
+}
+static const field core::String valueClass = #C2;
+
+constants  {
+  #C1 = null
+  #C2 = "valueClass"
+}
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///copy_with_call_sites.dart:26:7 -> StringConstant("A()")
+Extra constant evaluation: evaluated: 128, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect
new file mode 100644
index 0000000..55829f7
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline.expect
@@ -0,0 +1,22 @@
+import 'value_class_support_lib.dart';
+
+class Animal {
+  final int? numberOfLegs;
+  Animal({required this.numberOfLegs});
+}
+
+@valueClass
+class Cat extends Animal {
+  final int? numberOfWhiskers;
+}
+
+class Foo {
+  int? bar, bar2;
+  Foo({this.bar, this.bar2});
+  Foo copyWith({int bar, int bar2}) {}
+}
+
+@valueClass
+class A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..77c0c3c
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+import 'value_class_support_lib.dart';
+
+@valueClass
+class A {}
+
+class Animal {
+  Animal({required this.numberOfLegs});
+  final int? numberOfLegs;
+}
+
+@valueClass
+class Cat extends Animal {
+  final int? numberOfWhiskers;
+}
+
+class Foo {
+  Foo({this.bar, this.bar2});
+  Foo copyWith({int bar, int bar2}) {}
+  int? bar, bar2;
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect
new file mode 100644
index 0000000..e404600
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.expect
@@ -0,0 +1,140 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:21: Error: Optional parameter 'bar' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                     ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:30: Error: Optional parameter 'bar2' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                              ^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     return Foo(bar, bar2);
+//               ^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:19:3: Context: Found this candidate, but the arguments don't match.
+//   Foo({this.bar, this.bar2});
+//   ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+//  Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+//                    ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+//       ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+//  - 'Object' is from 'dart:core'.
+// Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+//  Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+//                             ^^^^^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+//  A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+//          ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:14: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int? numberOfWhiskers;
+//              ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+  final field core::int? numberOfLegs;
+  constructor •({required core::int? numberOfLegs = #C1}) → self::Animal
+    : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+    ;
+}
+class Cat extends self::Animal {
+  final field core::int? numberOfWhiskers = null;
+  synthetic constructor •({required core::int? numberOfWhiskers, core::int? numberOfLegs}) → self::Cat
+    : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int? numberOfLegs, core::int? numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+class Foo extends core::Object {
+  field core::int? bar;
+  field core::int? bar2;
+  constructor •({core::int? bar = #C1, core::int? bar2 = #C1}) → self::Foo
+    : self::Foo::bar = bar, self::Foo::bar2 = bar2, super core::Object::•()
+    ;
+  method copyWith({core::int bar = #C1, core::int bar2 = #C1}) → self::Foo {
+    return invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    return Foo(bar, bar2);
+              ^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Foo;
+  }
+}
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///copy_with_call_sites.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
+}
+static method main() → dynamic {
+  self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+                   ^^^^^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+  self::Cat cat2 = (let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat3 = (let final dynamic #t2 = ((cat as{ForNonNullableByDefault} dynamic).copyWith(numberOfWhiskers: 4) as{ForNonNullableByDefault} self::Cat) as{ForNonNullableByDefault} dynamic in #t2.copyWith(numberOfWhiskers: #t2.numberOfWhiskers, numberOfLegs: 3)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat4 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+ - 'Object' is from 'dart:core'.
+Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+ Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+                            ^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
+  self::Cat cat5 = (let final dynamic #t3 = cat as{ForNonNullableByDefault} dynamic in #t3.copyWith(numberOfWhiskers: #t3.numberOfWhiskers, numberOfLegs: #t3.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat6 = (let final dynamic #t4 = cat as{ForNonNullableByDefault} dynamic in #t4.copyWith(numberOfWhiskers: 4, numberOfLegs: #t4.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::A a;
+  self::A a2 = (let final dynamic #t5 = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+ A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+         ^" in a) as{ForNonNullableByDefault} dynamic in #t5.copyWith()) as{ForNonNullableByDefault} self::A;
+  self::Foo foo = new self::Foo::•(bar: 4, bar2: 5);
+  self::Foo foo2 = (foo as{ForNonNullableByDefault} dynamic).copyWith(bar: 4) as{ForNonNullableByDefault} self::Foo;
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+  synthetic constructor •() → val::JenkinsSmiHash
+    : super core::Object::•()
+    ;
+  static method combine(core::int hash, core::int value) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+    return hash.{core::int::^}(hash.{core::int::>>}(6));
+  }
+  static method finish(core::int hash) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+    hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+    return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+  }
+}
+static const field core::String valueClass = #C2;
+
+constants  {
+  #C1 = null
+  #C2 = "valueClass"
+}
diff --git a/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect
new file mode 100644
index 0000000..90ed8ba
--- /dev/null
+++ b/pkg/front_end/testcases/value_class/copy_with_call_sites.dart.weak.transformed.expect
@@ -0,0 +1,144 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:21: Error: Optional parameter 'bar' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                     ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:20:30: Error: Optional parameter 'bar2' should have a default value because its type 'int' doesn't allow null.
+//   Foo copyWith({int bar, int bar2}) {
+//                              ^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+// Try removing the extra positional arguments.
+//     return Foo(bar, bar2);
+//               ^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:19:3: Context: Found this candidate, but the arguments don't match.
+//   Foo({this.bar, this.bar2});
+//   ^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+//  Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+//                    ^^^^^^^^^^^^^^^^
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// class Cat extends Animal {
+//       ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+//  - 'Object' is from 'dart:core'.
+// Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+//  Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+//                             ^^^^^^^^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+//  A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+//          ^
+//
+// pkg/front_end/testcases/value_class/copy_with_call_sites.dart:14:14: Error: Final field 'numberOfWhiskers' is not initialized.
+// Try to initialize the field in the declaration or in every constructor.
+//   final int? numberOfWhiskers;
+//              ^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
+
+import "org-dartlang-testcase:///value_class_support_lib.dart";
+
+class Animal extends core::Object {
+  final field core::int? numberOfLegs;
+  constructor •({required core::int? numberOfLegs = #C1}) → self::Animal
+    : self::Animal::numberOfLegs = numberOfLegs, super core::Object::•()
+    ;
+}
+class Cat extends self::Animal {
+  final field core::int? numberOfWhiskers = null;
+  synthetic constructor •({required core::int? numberOfWhiskers, core::int? numberOfLegs}) → self::Cat
+    : self::Cat::numberOfWhiskers = numberOfWhiskers, super self::Animal::•(numberOfLegs)
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///copy_with_call_sites.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int? numberOfLegs, core::int? numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
+}
+class Foo extends core::Object {
+  field core::int? bar;
+  field core::int? bar2;
+  constructor •({core::int? bar = #C1, core::int? bar2 = #C1}) → self::Foo
+    : self::Foo::bar = bar, self::Foo::bar2 = bar2, super core::Object::•()
+    ;
+  method copyWith({core::int bar = #C1, core::int bar2 = #C1}) → self::Foo {
+    return invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:21:15: Error: Too many positional arguments: 0 allowed, but 2 found.
+Try removing the extra positional arguments.
+    return Foo(bar, bar2);
+              ^";
+  }
+}
+class A extends core::Object {
+  synthetic constructor •() → self::A
+    : super core::Object::•()
+    ;
+  operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
+    return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///copy_with_call_sites.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
+}
+static method main() → dynamic {
+  self::Cat cat = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:29:20: Error: No named parameter with the name 'numberOfWhiskers'.
+ Cat cat = new Cat(numberOfWhiskers: 20, numberOfLegs: 4);
+                   ^^^^^^^^^^^^^^^^";
+  self::Cat cat2 = (let final dynamic #t1 = cat as{ForNonNullableByDefault} dynamic in #t1.copyWith(numberOfWhiskers: 4, numberOfLegs: #t1.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat3 = (let final dynamic #t2 = ((cat as{ForNonNullableByDefault} dynamic).copyWith(numberOfWhiskers: 4) as{ForNonNullableByDefault} self::Cat) as{ForNonNullableByDefault} dynamic in #t2.copyWith(numberOfWhiskers: #t2.numberOfWhiskers, numberOfLegs: 3)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat4 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:35:29: Error: The method 'copyWith' isn't defined for the class 'Object'.
+ - 'Object' is from 'dart:core'.
+Try correcting the name to the name of an existing method, or defining a method named 'copyWith'.
+ Cat cat4 = (cat as Object).copyWith(numberOfWhiskers: 4);
+                            ^^^^^^^^";
+  self::Cat cat5 = (let final dynamic #t3 = cat as{ForNonNullableByDefault} dynamic in #t3.copyWith(numberOfWhiskers: #t3.numberOfWhiskers, numberOfLegs: #t3.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::Cat cat6 = (let final dynamic #t4 = cat as{ForNonNullableByDefault} dynamic in #t4.copyWith(numberOfWhiskers: 4, numberOfLegs: #t4.numberOfLegs)) as{ForNonNullableByDefault} self::Cat;
+  self::A a;
+  self::A a2 = (let final dynamic #t5 = (let final<BottomType> #t6 = invalid-expression "pkg/front_end/testcases/value_class/copy_with_call_sites.dart:43:10: Error: Non-nullable variable 'a' must be assigned before it can be used.
+ A a2 = (a as dynamic).copyWith(x: 42, y: 42) as A;
+         ^" in a) as{ForNonNullableByDefault} dynamic in #t5.copyWith()) as{ForNonNullableByDefault} self::A;
+  self::Foo foo = new self::Foo::•(bar: 4, bar2: 5);
+  self::Foo foo2 = (foo as{ForNonNullableByDefault} dynamic).copyWith(bar: 4) as{ForNonNullableByDefault} self::Foo;
+}
+
+library /*isNonNullableByDefault*/;
+import self as val;
+import "dart:core" as core;
+
+class JenkinsSmiHash extends core::Object {
+  synthetic constructor •() → val::JenkinsSmiHash
+    : super core::Object::•()
+    ;
+  static method combine(core::int hash, core::int value) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(value));
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(524287.{core::int::&}(hash).{core::int::<<}(10)));
+    return hash.{core::int::^}(hash.{core::int::>>}(6));
+  }
+  static method finish(core::int hash) → core::int {
+    hash = 536870911.{core::int::&}(hash.{core::num::+}(67108863.{core::int::&}(hash).{core::int::<<}(3)));
+    hash = hash.{core::int::^}(hash.{core::int::>>}(11));
+    return 536870911.{core::int::&}(hash.{core::num::+}(16383.{core::int::&}(hash).{core::int::<<}(15)));
+  }
+}
+static const field core::String valueClass = #C2;
+
+constants  {
+  #C1 = null
+  #C2 = "valueClass"
+}
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///copy_with_call_sites.dart:26:7 -> StringConstant("A()")
+Extra constant evaluation: evaluated: 128, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/empty.dart.outline.expect b/pkg/front_end/testcases/value_class/empty.dart.outline.expect
index 8eabbff..2f8fd42 100644
--- a/pkg/front_end/testcases/value_class/empty.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/empty.dart.outline.expect
@@ -26,3 +26,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///empty.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/empty.dart.strong.expect b/pkg/front_end/testcases/value_class/empty.dart.strong.expect
index 96207aa..ea8f20e 100644
--- a/pkg/front_end/testcases/value_class/empty.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/empty.dart.strong.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,15 +11,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::EmptyClass;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///empty.dartEmptyClass".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "EmptyClass()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::EmptyClass::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/empty.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/empty.dart.strong.transformed.expect
index 96207aa..0ce153d 100644
--- a/pkg/front_end/testcases/value_class/empty.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/empty.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,15 +11,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::EmptyClass;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///empty.dartEmptyClass".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "EmptyClass()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::EmptyClass::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -37,3 +44,7 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///empty.dart:8:7 -> StringConstant("EmptyClass()")
+Extra constant evaluation: evaluated: 40, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/empty.dart.weak.expect b/pkg/front_end/testcases/value_class/empty.dart.weak.expect
index 96207aa..ea8f20e 100644
--- a/pkg/front_end/testcases/value_class/empty.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/empty.dart.weak.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,15 +11,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::EmptyClass;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///empty.dartEmptyClass".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "EmptyClass()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::EmptyClass::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/empty.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/empty.dart.weak.transformed.expect
index 96207aa..0ce153d 100644
--- a/pkg/front_end/testcases/value_class/empty.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/empty.dart.weak.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,15 +11,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::EmptyClass;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///empty.dartEmptyClass".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "EmptyClass()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::EmptyClass::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -37,3 +44,7 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///empty.dart:8:7 -> StringConstant("EmptyClass()")
+Extra constant evaluation: evaluated: 40, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/explicit_mixin.dart.outline.expect b/pkg/front_end/testcases/value_class/explicit_mixin.dart.outline.expect
index 1186e41..da7ab09 100644
--- a/pkg/front_end/testcases/value_class/explicit_mixin.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/explicit_mixin.dart.outline.expect
@@ -50,3 +50,9 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///explicit_mixin.dart:7:2 -> StringConstant("valueClass")
+Evaluated: StaticGet @ org-dartlang-testcase:///explicit_mixin.dart:17:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.expect b/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.expect
index 9fe3384..8f5b282 100644
--- a/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -37,15 +44,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::F;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartF".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "F()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::F::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.transformed.expect
index fa46235..f6df7f8 100644
--- a/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/explicit_mixin.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -32,6 +39,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class F extends self::B implements self::C /*isEliminatedMixin*/  {
   synthetic constructor •() → self::F
@@ -39,15 +52,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::F;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartF".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "F()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::F::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -66,3 +85,9 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:18:7 -> StringConstant("F()")
+Extra constant evaluation: evaluated: 52, effectively constant: 3
diff --git a/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.expect b/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.expect
index 9fe3384..8f5b282 100644
--- a/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -37,15 +44,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::F;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartF".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "F()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::F::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.transformed.expect
index fa46235..f6df7f8 100644
--- a/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/explicit_mixin.dart.weak.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -32,6 +39,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class F extends self::B implements self::C /*isEliminatedMixin*/  {
   synthetic constructor •() → self::F
@@ -39,15 +52,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::F;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///explicit_mixin.dartF".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "F()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::F::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -66,3 +85,9 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///explicit_mixin.dart:18:7 -> StringConstant("F()")
+Extra constant evaluation: evaluated: 52, effectively constant: 3
diff --git a/pkg/front_end/testcases/value_class/non_final_field_error.dart.outline.expect b/pkg/front_end/testcases/value_class/non_final_field_error.dart.outline.expect
index c7f8eba..941c5938 100644
--- a/pkg/front_end/testcases/value_class/non_final_field_error.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/non_final_field_error.dart.outline.expect
@@ -27,3 +27,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///non_final_field_error.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.expect b/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.expect
index fa2785e..106c4ea 100644
--- a/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -18,15 +19,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_final_field_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.transformed.expect
index fa2785e..106c4ea 100644
--- a/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_final_field_error.dart.strong.transformed.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -18,15 +19,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_final_field_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.expect b/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.expect
index fa2785e..106c4ea 100644
--- a/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -18,15 +19,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_final_field_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.transformed.expect
index fa2785e..106c4ea 100644
--- a/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_final_field_error.dart.weak.transformed.expect
@@ -8,6 +8,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -18,15 +19,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_final_field_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.outline.expect b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.outline.expect
index cabfc54..3c037ce 100644
--- a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.outline.expect
@@ -31,3 +31,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///non_value_extends_value_error.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.expect b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.expect
index a5978c5..8b97d06 100644
--- a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.expect
@@ -9,6 +9,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -19,6 +20,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_extends_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends self::Animal {
   synthetic constructor •() → self::Cat
@@ -28,11 +35,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.transformed.expect
index a5978c5..8b97d06 100644
--- a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.strong.transformed.expect
@@ -9,6 +9,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -19,6 +20,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_extends_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends self::Animal {
   synthetic constructor •() → self::Cat
@@ -28,11 +35,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.expect b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.expect
index a5978c5..8b97d06 100644
--- a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.expect
@@ -9,6 +9,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -19,6 +20,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_extends_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends self::Animal {
   synthetic constructor •() → self::Cat
@@ -28,11 +35,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.transformed.expect
index a5978c5..8b97d06 100644
--- a/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_value_extends_value_error.dart.weak.transformed.expect
@@ -9,6 +9,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -19,6 +20,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_extends_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends self::Animal {
   synthetic constructor •() → self::Cat
@@ -28,11 +35,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.outline.expect b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.outline.expect
index 26f4715..a164ad8 100644
--- a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.outline.expect
@@ -32,3 +32,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///non_value_implements_value_error.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.expect b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.expect
index dc47c2a..c12b1c3 100644
--- a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.expect
@@ -14,6 +14,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -24,6 +25,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_implements_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends core::Object implements self::Animal {
   final field core::int numberOfLegs = null;
@@ -34,11 +41,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.transformed.expect
index dc47c2a..c12b1c3 100644
--- a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.strong.transformed.expect
@@ -14,6 +14,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -24,6 +25,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_implements_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends core::Object implements self::Animal {
   final field core::int numberOfLegs = null;
@@ -34,11 +41,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.expect b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.expect
index dc47c2a..c12b1c3 100644
--- a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.expect
@@ -14,6 +14,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -24,6 +25,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_implements_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends core::Object implements self::Animal {
   final field core::int numberOfLegs = null;
@@ -34,11 +41,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.transformed.expect
index dc47c2a..c12b1c3 100644
--- a/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/non_value_implements_value_error.dart.weak.transformed.expect
@@ -14,6 +14,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -24,6 +25,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///non_value_implements_value_error.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 class Cat extends core::Object implements self::Animal {
   final field core::int numberOfLegs = null;
@@ -34,11 +41,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/simple.dart.outline.expect b/pkg/front_end/testcases/value_class/simple.dart.outline.expect
index ffcabdf..fd0c916 100644
--- a/pkg/front_end/testcases/value_class/simple.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/simple.dart.outline.expect
@@ -29,3 +29,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///simple.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/simple.dart.strong.expect b/pkg/front_end/testcases/value_class/simple.dart.strong.expect
index eb9f0d0..67bbec1 100644
--- a/pkg/front_end/testcases/value_class/simple.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/simple.dart.strong.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -40,6 +41,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///simple.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {
   self::Animal firstAnimal = invalid-expression "pkg/front_end/testcases/value_class/simple.dart:13:31: Error: No named parameter with the name 'numberOfLegs'.
@@ -62,11 +69,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/simple.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/simple.dart.strong.transformed.expect
index ea02301..88adc14 100644
--- a/pkg/front_end/testcases/value_class/simple.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/simple.dart.strong.transformed.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -40,6 +41,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///simple.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {
   self::Animal firstAnimal = invalid-expression "pkg/front_end/testcases/value_class/simple.dart:13:31: Error: No named parameter with the name 'numberOfLegs'.
@@ -62,11 +69,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/simple.dart.weak.expect b/pkg/front_end/testcases/value_class/simple.dart.weak.expect
index eb9f0d0..67bbec1 100644
--- a/pkg/front_end/testcases/value_class/simple.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/simple.dart.weak.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -40,6 +41,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///simple.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {
   self::Animal firstAnimal = invalid-expression "pkg/front_end/testcases/value_class/simple.dart:13:31: Error: No named parameter with the name 'numberOfLegs'.
@@ -62,11 +69,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/simple.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/simple.dart.weak.transformed.expect
index ea02301..88adc14 100644
--- a/pkg/front_end/testcases/value_class/simple.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/simple.dart.weak.transformed.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -40,6 +41,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Animal && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Animal}.{self::Animal::numberOfLegs});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine("org-dartlang-testcase:///simple.dartAnimal".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Animal(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs}) → dynamic
+    return new self::Animal::•(numberOfLegs: numberOfLegs);
 }
 static method main() → dynamic {
   self::Animal firstAnimal = invalid-expression "pkg/front_end/testcases/value_class/simple.dart:13:31: Error: No named parameter with the name 'numberOfLegs'.
@@ -62,11 +69,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.outline.expect b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.outline.expect
index 6cdbfae..6b5a117 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.outline.expect
@@ -34,3 +34,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///value_extends_non_value.dart:12:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.expect b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.expect
index aa94e2f..8ab2483 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -46,6 +47,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_extends_non_value.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
   self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_extends_non_value.dart:18:22: Error: No named parameter with the name 'numberOfLegs'.
@@ -68,11 +75,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.transformed.expect
index 0a9d8aa..2227f34 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.strong.transformed.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -46,6 +47,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_extends_non_value.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
   self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_extends_non_value.dart:18:22: Error: No named parameter with the name 'numberOfLegs'.
@@ -68,11 +75,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.expect b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.expect
index aa94e2f..8ab2483 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -46,6 +47,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_extends_non_value.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
   self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_extends_non_value.dart:18:22: Error: No named parameter with the name 'numberOfLegs'.
@@ -68,11 +75,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.transformed.expect
index 0a9d8aa..2227f34 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value.dart.weak.transformed.expect
@@ -30,6 +30,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -46,6 +47,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Animal::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Animal::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_extends_non_value.dartCat".{core::String::hashCode}, this.{self::Animal::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Animal::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
   self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_extends_non_value.dart:18:22: Error: No named parameter with the name 'numberOfLegs'.
@@ -68,11 +75,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.outline.expect b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.outline.expect
index a6a74a9..a1dd54d 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.outline.expect
@@ -41,3 +41,9 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///value_extends_non_value_error.dart:11:2 -> StringConstant("valueClass")
+Evaluated: StaticGet @ org-dartlang-testcase:///value_extends_non_value_error.dart:18:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.expect b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.expect
index e0bd837..95e0356 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.expect
@@ -13,6 +13,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -28,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat::•();
 }
 class Animal2 extends core::Object {
   final field core::int numberOfLegs = null;
@@ -41,15 +48,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat2".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat2::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.transformed.expect
index e0bd837..b55acf5 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.strong.transformed.expect
@@ -13,6 +13,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -28,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat::•();
 }
 class Animal2 extends core::Object {
   final field core::int numberOfLegs = null;
@@ -41,15 +48,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat2".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat2::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -68,3 +81,8 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_extends_non_value_error.dart:12:7 -> StringConstant("Cat()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_extends_non_value_error.dart:19:7 -> StringConstant("Cat2()")
+Extra constant evaluation: evaluated: 46, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.expect b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.expect
index e0bd837..95e0356 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.expect
@@ -13,6 +13,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -28,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat::•();
 }
 class Animal2 extends core::Object {
   final field core::int numberOfLegs = null;
@@ -41,15 +48,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat2".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat2::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.transformed.expect
index e0bd837..b55acf5 100644
--- a/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_extends_non_value_error.dart.weak.transformed.expect
@@ -13,6 +13,7 @@
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -28,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat::•();
 }
 class Animal2 extends core::Object {
   final field core::int numberOfLegs = null;
@@ -41,15 +48,21 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_extends_non_value_error.dartCat2".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::Cat2::•();
 }
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -68,3 +81,8 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_extends_non_value_error.dart:12:7 -> StringConstant("Cat()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_extends_non_value_error.dart:19:7 -> StringConstant("Cat2()")
+Extra constant evaluation: evaluated: 46, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart b/pkg/front_end/testcases/value_class/value_implements_non_value.dart
index ccb27e8..6b6cf57 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart
@@ -2,7 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import '../nnbd_mixed/nnbd_opt_out_language_version.dart';
 import 'value_class_support_lib.dart';
 
 class Animal {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.outline.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.outline.expect
index 858458c..4896c3e 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.outline.expect
@@ -3,7 +3,6 @@
 import "dart:core" as core;
 import "value_class_support_lib.dart" as val;
 
-import "org-dartlang-testcase-sdk:///pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart";
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
 class Animal extends core::Object {
@@ -36,38 +35,6 @@
   ;
 
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:1:1: Error: A library can't opt out of null safety by default, when using sound null safety.
-// // @dart=2.4
-// ^^^^^^^^^^^^
-//
-import self as self2;
-import "dart:core" as core;
-
-class late extends core::Object {
-  synthetic constructor •() → self2::late
-    ;
-  get g() → core::int
-    ;
-}
-class required extends core::Object {
-  synthetic constructor •() → self2::required
-    ;
-  get g() → core::int
-    ;
-}
-class C extends core::Object {
-  field self2::late l;
-  field self2::required r;
-  synthetic constructor •() → self2::C
-    ;
-}
-static method main() → dynamic
-  ;
-
-library /*isNonNullableByDefault*/;
 import self as val;
 import "dart:core" as core;
 
@@ -80,3 +47,9 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///value_implements_non_value.dart:11:2 -> StringConstant("valueClass")
+Evaluated: StaticGet @ org-dartlang-testcase:///value_implements_non_value.dart:21:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 2, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.expect
index 28a8793..ea9e6be 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.expect
@@ -2,77 +2,77 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                       ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                          ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:9:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:8:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:15:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:25:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
-import "org-dartlang-testcase-sdk:///pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart";
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
 class Animal extends core::Object {
@@ -89,6 +89,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Cat::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat".{core::String::hashCode}, this.{self::Cat::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Cat::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 abstract class Animal2 extends core::Object {
   synthetic constructor •() → self::Animal2
@@ -104,28 +110,34 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2 && this.{self::Cat2::numberOfLegs}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfLegs}) && this.{self::Cat2::numberOfWhiskers}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat2".{core::String::hashCode}, this.{self::Cat2::numberOfLegs}.{core::num::hashCode}), this.{self::Cat2::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2(numberOfLegs: ${this.{self::Cat2::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat2::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat2::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
-  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                      ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
-  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                       ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
-  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
                      ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
   self::expect(true, firstCat.{core::Object::==}(secondCat));
   self::expect(false, firstCat.{core::Object::==}(thirdCat));
   self::expect(true, firstCat.{core::Object::hashCode}.{core::num::==}(secondCat.{core::Object::hashCode}));
   self::expect(false, firstCat.{core::Object::hashCode}.{core::num::==}(thirdCat.{core::Object::hashCode}));
-  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                         ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
-  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                          ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
-  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
                         ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
   self::expect(true, firstCat2.{core::Object::==}(secondCat2));
@@ -139,73 +151,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:1:1: Error: A library can't opt out of null safety by default, when using sound null safety.
-// // @dart=2.4
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:3:7: Error: Can't use 'late' as a name here.
-// class late {
-//       ^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:7:7: Error: Can't use 'required' as a name here.
-// class required {
-//       ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:12:8: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
-// Try adding the name of the type of the variable or the keyword 'var'.
-//   late l = late();
-//        ^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:13:3: Error: Can't have modifier 'required' here.
-// Try removing 'required'.
-//   required r = required();
-//   ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:13:12: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
-// Try adding the name of the type of the variable or the keyword 'var'.
-//   required r = required();
-//            ^
-//
-import self as self2;
-import "dart:core" as core;
-
-class late extends core::Object {
-  synthetic constructor •() → self2::late
-    : super core::Object::•()
-    ;
-  get g() → core::int
-    return 1;
-}
-class required extends core::Object {
-  synthetic constructor •() → self2::required
-    : super core::Object::•()
-    ;
-  get g() → core::int
-    return 2;
-}
-class C extends core::Object {
-  field self2::late l = new self2::late::•();
-  field self2::required r = new self2::required::•();
-  synthetic constructor •() → self2::C
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {
-  if(!new self2::C::•().{self2::C::l}.{self2::late::g}.{core::num::==}(1))
-    throw "Expected 1";
-  if(!new self2::C::•().{self2::C::r}.{self2::required::g}.{core::num::==}(2))
-    throw "Expected 2";
-}
-
-library /*isNonNullableByDefault*/;
-import self as self3;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self3::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.transformed.expect
index 4a66e5d..dfd6ccf 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.strong.transformed.expect
@@ -2,77 +2,77 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                       ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                          ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:9:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:8:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:15:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:25:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
-import "org-dartlang-testcase-sdk:///pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart";
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
 class Animal extends core::Object {
@@ -89,6 +89,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Cat::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat".{core::String::hashCode}, this.{self::Cat::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Cat::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 abstract class Animal2 extends core::Object {
   synthetic constructor •() → self::Animal2
@@ -104,28 +110,34 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2 && this.{self::Cat2::numberOfLegs}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfLegs}) && this.{self::Cat2::numberOfWhiskers}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat2".{core::String::hashCode}, this.{self::Cat2::numberOfLegs}.{core::num::hashCode}), this.{self::Cat2::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2(numberOfLegs: ${this.{self::Cat2::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat2::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat2::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
-  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                      ^^^^^^^^^^^^";
-  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                       ^^^^^^^^^^^^";
-  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
                      ^^^^^^^^^^^^";
   self::expect(true, firstCat.{core::Object::==}(secondCat));
   self::expect(false, firstCat.{core::Object::==}(thirdCat));
   self::expect(true, firstCat.{core::Object::hashCode}.{core::num::==}(secondCat.{core::Object::hashCode}));
   self::expect(false, firstCat.{core::Object::hashCode}.{core::num::==}(thirdCat.{core::Object::hashCode}));
-  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                         ^^^^^^^^^^^^";
-  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                          ^^^^^^^^^^^^";
-  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
                         ^^^^^^^^^^^^";
   self::expect(true, firstCat2.{core::Object::==}(secondCat2));
@@ -139,73 +151,11 @@
 }
 
 library /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:1:1: Error: A library can't opt out of null safety by default, when using sound null safety.
-// // @dart=2.4
-// ^^^^^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:3:7: Error: Can't use 'late' as a name here.
-// class late {
-//       ^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:7:7: Error: Can't use 'required' as a name here.
-// class required {
-//       ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:12:8: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
-// Try adding the name of the type of the variable or the keyword 'var'.
-//   late l = late();
-//        ^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:13:3: Error: Can't have modifier 'required' here.
-// Try removing 'required'.
-//   required r = required();
-//   ^^^^^^^^
-//
-// pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart:13:12: Error: Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
-// Try adding the name of the type of the variable or the keyword 'var'.
-//   required r = required();
-//            ^
-//
-import self as self2;
-import "dart:core" as core;
-
-class late extends core::Object {
-  synthetic constructor •() → self2::late
-    : super core::Object::•()
-    ;
-  get g() → core::int
-    return 1;
-}
-class required extends core::Object {
-  synthetic constructor •() → self2::required
-    : super core::Object::•()
-    ;
-  get g() → core::int
-    return 2;
-}
-class C extends core::Object {
-  field self2::late l = new self2::late::•();
-  field self2::required r = new self2::required::•();
-  synthetic constructor •() → self2::C
-    : super core::Object::•()
-    ;
-}
-static method main() → dynamic {
-  if(!new self2::C::•().{self2::C::l}.{self2::late::g}.{core::num::==}(1))
-    throw "Expected 1";
-  if(!new self2::C::•().{self2::C::r}.{self2::required::g}.{core::num::==}(2))
-    throw "Expected 2";
-}
-
-library /*isNonNullableByDefault*/;
-import self as self3;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self3::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline.expect
index 2d8e9d2..bf86aab 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline.expect
@@ -1,4 +1,3 @@
-import '../nnbd_mixed/nnbd_opt_out_language_version.dart';
 import 'value_class_support_lib.dart';
 
 class Animal {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline_modelled.expect
index 43b3505..0b34b85 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline_modelled.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.textual_outline_modelled.expect
@@ -1,4 +1,3 @@
-import '../nnbd_mixed/nnbd_opt_out_language_version.dart';
 import 'value_class_support_lib.dart';
 
 abstract class Animal2 {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.expect
index 21d4e29..ea9e6be 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.expect
@@ -2,77 +2,77 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                       ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                          ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:9:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:8:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:15:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:25:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
-import "org-dartlang-testcase-sdk:///pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart";
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
 class Animal extends core::Object {
@@ -89,6 +89,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Cat::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat".{core::String::hashCode}, this.{self::Cat::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Cat::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 abstract class Animal2 extends core::Object {
   synthetic constructor •() → self::Animal2
@@ -104,28 +110,34 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2 && this.{self::Cat2::numberOfLegs}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfLegs}) && this.{self::Cat2::numberOfWhiskers}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat2".{core::String::hashCode}, this.{self::Cat2::numberOfLegs}.{core::num::hashCode}), this.{self::Cat2::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2(numberOfLegs: ${this.{self::Cat2::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat2::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat2::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
-  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                      ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
-  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                       ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
-  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
                      ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat;
   self::expect(true, firstCat.{core::Object::==}(secondCat));
   self::expect(false, firstCat.{core::Object::==}(thirdCat));
   self::expect(true, firstCat.{core::Object::hashCode}.{core::num::==}(secondCat.{core::Object::hashCode}));
   self::expect(false, firstCat.{core::Object::hashCode}.{core::num::==}(thirdCat.{core::Object::hashCode}));
-  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                         ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
-  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                          ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
-  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
                         ^^^^^^^^^^^^" as{TypeError,ForDynamic,ForNonNullableByDefault} self::Cat2;
   self::expect(true, firstCat2.{core::Object::==}(secondCat2));
@@ -138,74 +150,12 @@
     throw "Expected=${expected}, actual=${actual}";
 }
 
-library;
-import self as self2;
-import "dart:core" as core;
-
-class late extends core::Object {
-  synthetic constructor •() → self2::late*
-    : super core::Object::•()
-    ;
-  get g() → core::int*
-    return 1;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-class required extends core::Object {
-  synthetic constructor •() → self2::required*
-    : super core::Object::•()
-    ;
-  get g() → core::int*
-    return 2;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-class C extends core::Object {
-  field self2::late* l = new self2::late::•();
-  field self2::required* r = new self2::required::•();
-  synthetic constructor •() → self2::C*
-    : super core::Object::•()
-    ;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-static method main() → dynamic {
-  if(!new self2::C::•().{self2::C::l}.{self2::late::g}.{core::num::==}(1))
-    throw "Expected 1";
-  if(!new self2::C::•().{self2::C::r}.{self2::required::g}.{core::num::==}(2))
-    throw "Expected 2";
-}
-
 library /*isNonNullableByDefault*/;
-import self as self3;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self3::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.transformed.expect
index 39979d6..dfd6ccf 100644
--- a/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_implements_non_value.dart.weak.transformed.expect
@@ -2,77 +2,77 @@
 //
 // Problems in library:
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
 //                       ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
 //                      ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:7: Context: The class 'Cat' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:12:7: Context: The class 'Cat' has a constructor that takes no arguments.
 // class Cat implements Animal {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
 //                          ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
 //   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
 //                         ^^^^^^^^^^^^
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:7: Context: The class 'Cat2' has a constructor that takes no arguments.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:22:7: Context: The class 'Cat2' has a constructor that takes no arguments.
 // class Cat2 implements Animal2 {
 //       ^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:9:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:8:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:13:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:15:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:14:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfLegs' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:23:13: Error: Final field 'numberOfLegs' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfLegs;
 //             ^^^^^^^^^^^^
 //
-// pkg/front_end/testcases/value_class/value_implements_non_value.dart:25:13: Error: Final field 'numberOfWhiskers' is not initialized.
+// pkg/front_end/testcases/value_class/value_implements_non_value.dart:24:13: Error: Final field 'numberOfWhiskers' is not initialized.
 // Try to initialize the field in the declaration or in every constructor.
 //   final int numberOfWhiskers;
 //             ^^^^^^^^^^^^^^^^
 //
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
-import "org-dartlang-testcase-sdk:///pkg/front_end/testcases/nnbd_mixed/nnbd_opt_out_language_version.dart";
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
 class Animal extends core::Object {
@@ -89,6 +89,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat && this.{self::Cat::numberOfLegs}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfLegs}) && this.{self::Cat::numberOfWhiskers}.{core::num::==}(other{self::Cat}.{self::Cat::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat".{core::String::hashCode}, this.{self::Cat::numberOfLegs}.{core::num::hashCode}), this.{self::Cat::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat(numberOfLegs: ${this.{self::Cat::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 abstract class Animal2 extends core::Object {
   synthetic constructor •() → self::Animal2
@@ -104,28 +110,34 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::Cat2 && this.{self::Cat2::numberOfLegs}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfLegs}) && this.{self::Cat2::numberOfWhiskers}.{core::num::==}(other{self::Cat2}.{self::Cat2::numberOfWhiskers});
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish(val::JenkinsSmiHash::combine(val::JenkinsSmiHash::combine("org-dartlang-testcase:///value_implements_non_value.dartCat2".{core::String::hashCode}, this.{self::Cat2::numberOfLegs}.{core::num::hashCode}), this.{self::Cat2::numberOfWhiskers}.{core::num::hashCode}));
+  method /*isNullableByDefault*/ toString() → core::String
+    return "Cat2(numberOfLegs: ${this.{self::Cat2::numberOfLegs}.{core::int::toString}()}, numberOfWhiskers: ${this.{self::Cat2::numberOfWhiskers}.{core::int::toString}()})";
+  method /*isNullableByDefault*/ copyWith({core::int numberOfLegs, core::int numberOfWhiskers}) → dynamic
+    return new self::Cat2::•(numberOfLegs: numberOfLegs, numberOfWhiskers: numberOfWhiskers);
 }
 static method main() → dynamic {
-  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat firstCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:29:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat firstCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                      ^^^^^^^^^^^^";
-  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:23: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat secondCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:30:23: Error: No named parameter with the name 'numberOfLegs'.
   Cat secondCat = Cat(numberOfLegs: 4, numberOfWhiskers: 10);
                       ^^^^^^^^^^^^";
-  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:32:22: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat thirdCat = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:31:22: Error: No named parameter with the name 'numberOfLegs'.
   Cat thirdCat = Cat(numberOfLegs: 4, numberOfWhiskers: 0);
                      ^^^^^^^^^^^^";
   self::expect(true, firstCat.{core::Object::==}(secondCat));
   self::expect(false, firstCat.{core::Object::==}(thirdCat));
   self::expect(true, firstCat.{core::Object::hashCode}.{core::num::==}(secondCat.{core::Object::hashCode}));
   self::expect(false, firstCat.{core::Object::hashCode}.{core::num::==}(thirdCat.{core::Object::hashCode}));
-  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 firstCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:39:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 firstCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                         ^^^^^^^^^^^^";
-  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:26: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 secondCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:40:26: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 secondCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 10);
                          ^^^^^^^^^^^^";
-  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:42:25: Error: No named parameter with the name 'numberOfLegs'.
+  self::Cat2 thirdCat2 = invalid-expression "pkg/front_end/testcases/value_class/value_implements_non_value.dart:41:25: Error: No named parameter with the name 'numberOfLegs'.
   Cat2 thirdCat2 = Cat2(numberOfLegs: 4, numberOfWhiskers: 0);
                         ^^^^^^^^^^^^";
   self::expect(true, firstCat2.{core::Object::==}(secondCat2));
@@ -138,74 +150,12 @@
     throw "Expected=${expected}, actual=${actual}";
 }
 
-library;
-import self as self2;
-import "dart:core" as core;
-
-class late extends core::Object {
-  synthetic constructor •() → self2::late*
-    : super core::Object::•()
-    ;
-  get g() → core::int*
-    return 1;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-class required extends core::Object {
-  synthetic constructor •() → self2::required*
-    : super core::Object::•()
-    ;
-  get g() → core::int*
-    return 2;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-class C extends core::Object {
-  field self2::late* l = new self2::late::•();
-  field self2::required* r = new self2::required::•();
-  synthetic constructor •() → self2::C*
-    : super core::Object::•()
-    ;
-  abstract member-signature get _identityHashCode() → core::int*; -> core::Object::_identityHashCode
-  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*; -> core::Object::_instanceOf
-  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOf
-  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfTrue
-  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*; -> core::Object::_simpleInstanceOfFalse
-  abstract member-signature operator ==(dynamic other) → core::bool*; -> core::Object::==
-  abstract member-signature get hashCode() → core::int*; -> core::Object::hashCode
-  abstract member-signature method toString() → core::String*; -> core::Object::toString
-  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
-  abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
-}
-static method main() → dynamic {
-  if(!new self2::C::•().{self2::C::l}.{self2::late::g}.{core::num::==}(1))
-    throw "Expected 1";
-  if(!new self2::C::•().{self2::C::r}.{self2::required::g}.{core::num::==}(2))
-    throw "Expected 2";
-}
-
 library /*isNonNullableByDefault*/;
-import self as self3;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self3::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_mixin_error.dart.outline.expect b/pkg/front_end/testcases/value_class/value_mixin_error.dart.outline.expect
index 3210673..cbe7b43 100644
--- a/pkg/front_end/testcases/value_class/value_mixin_error.dart.outline.expect
+++ b/pkg/front_end/testcases/value_class/value_mixin_error.dart.outline.expect
@@ -48,3 +48,8 @@
     ;
 }
 static const field core::String valueClass = "valueClass";
+
+
+Extra constant evaluation status:
+Evaluated: StaticGet @ org-dartlang-testcase:///value_mixin_error.dart:7:2 -> StringConstant("valueClass")
+Extra constant evaluation: evaluated: 1, effectively constant: 1
diff --git a/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.expect b/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.expect
index 18d691c..5b97acf 100644
--- a/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.expect
+++ b/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -39,11 +46,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.transformed.expect b/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.transformed.expect
index 338f201..5b474c0 100644
--- a/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_mixin_error.dart.strong.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -22,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class C extends self::_C&B&A {
   synthetic constructor •() → self::C
@@ -41,11 +54,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -64,3 +77,8 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_mixin_error.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_mixin_error.dart:8:7 -> StringConstant("A()")
+Extra constant evaluation: evaluated: 46, effectively constant: 2
diff --git a/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.expect b/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.expect
index 18d691c..5b97acf 100644
--- a/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.expect
+++ b/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -39,11 +46,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
diff --git a/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.transformed.expect b/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.transformed.expect
index 338f201..5b474c0 100644
--- a/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/value_class/value_mixin_error.dart.weak.transformed.expect
@@ -1,6 +1,7 @@
 library /*isNonNullableByDefault*/;
 import self as self;
 import "dart:core" as core;
+import "value_class_support_lib.dart" as val;
 
 import "org-dartlang-testcase:///value_class_support_lib.dart";
 
@@ -10,6 +11,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class B extends core::Object {
   synthetic constructor •() → self::B
@@ -22,6 +29,12 @@
     ;
   operator /*isNullableByDefault*/ ==(core::Object other) → core::bool
     return other is self::A;
+  get /*isNullableByDefault*/ hashCode() → core::int
+    return val::JenkinsSmiHash::finish("org-dartlang-testcase:///value_mixin_error.dartA".{core::String::hashCode});
+  method /*isNullableByDefault*/ toString() → core::String
+    return "A()";
+  method /*isNullableByDefault*/ copyWith() → dynamic
+    return new self::A::•();
 }
 class C extends self::_C&B&A {
   synthetic constructor •() → self::C
@@ -41,11 +54,11 @@
 static method main() → dynamic {}
 
 library /*isNonNullableByDefault*/;
-import self as self2;
+import self as val;
 import "dart:core" as core;
 
 class JenkinsSmiHash extends core::Object {
-  synthetic constructor •() → self2::JenkinsSmiHash
+  synthetic constructor •() → val::JenkinsSmiHash
     : super core::Object::•()
     ;
   static method combine(core::int hash, core::int value) → core::int {
@@ -64,3 +77,8 @@
 constants  {
   #C1 = "valueClass"
 }
+
+Extra constant evaluation status:
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_mixin_error.dart:8:7 -> StringConstant("A()")
+Evaluated: StringConcatenation @ org-dartlang-testcase:///value_mixin_error.dart:8:7 -> StringConstant("A()")
+Extra constant evaluation: evaluated: 46, effectively constant: 2
diff --git a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
index 436ada2..22cd762 100644
--- a/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
+++ b/pkg/front_end/testcases/variance/generic_covariance_sound_variance.dart.outline.expect
@@ -164,3 +164,20 @@
   ;
 static method expect(dynamic expected, dynamic actual) → dynamic
   ;
+
+
+Extra constant evaluation status:
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> SymbolConstant(#x)
+Evaluated: ListLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:23:5 -> SymbolConstant(#method)
+Evaluated: ListLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:23:5 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:23:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:24:12 -> SymbolConstant(#y=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:24:12 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:24:12 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Evaluated: SymbolLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> SymbolConstant(#x=)
+Evaluated: ListLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> ListConstant(const <Type*>[])
+Evaluated: MapLiteral @ org-dartlang-testcase:///generic_covariance_sound_variance.dart:22:5 -> InstanceConstant(const _ImmutableMap<Symbol*, dynamic>{_ImmutableMap._kvPairs: const <dynamic>[]})
+Extra constant evaluation: evaluated: 42, effectively constant: 13
diff --git a/pkg/front_end/testcases/weak.status b/pkg/front_end/testcases/weak.status
index d9272d6..bf869dd 100644
--- a/pkg/front_end/testcases/weak.status
+++ b/pkg/front_end/testcases/weak.status
@@ -52,7 +52,6 @@
 general_nnbd_opt_out/override_setter_with_field: TypeCheckError
 general_nnbd_opt_out/reject_generic_function_types_in_bounds: RuntimeError # Expected
 general_nnbd_opt_out/spread_collection: RuntimeError
-general_nnbd_opt_out/statements: Crash
 general_nnbd_opt_out/type_parameter_type_named_int: RuntimeError # Expected
 general_nnbd_opt_out/type_variable_as_super: RuntimeError
 general_nnbd_opt_out/type_variable_bound_access: TypeCheckError
@@ -60,6 +59,7 @@
 general_nnbd_opt_out/void_methods: RuntimeError
 late_lowering/covariant_late_field: TypeCheckError
 nnbd/covariant_late_field: TypeCheckError
+nnbd/getter_vs_setter_type: TypeCheckError
 nnbd/issue42546: TypeCheckError
 nnbd/issue42603: TypeCheckError
 nnbd/no_support_for_old_null_aware_index_access_syntax: RuntimeError # Expected.
@@ -67,11 +67,12 @@
 nnbd/nullable_receiver: TypeCheckError
 nnbd/potentially_nullable_access: TypeCheckError
 nnbd_mixed/bad_mixins: TypeCheckError
+nnbd_mixed/covariant_from_opt_in: TypeCheckError
 nnbd_mixed/inheritance_from_opt_in: TypeCheckError
 nnbd_mixed/issue41567: TypeCheckError
 nnbd_mixed/messages_with_types_opt_in: TypeCheckError
 nnbd_mixed/messages_with_types_opt_out: TypeCheckError
-nnbd_mixed/never_opt_out: TypeCheckError
 value_class/simple: RuntimeError # Expected
 value_class/value_extends_non_value: RuntimeError # Expected
-value_class/value_implements_non_value: RuntimeError # Expected
\ No newline at end of file
+value_class/value_implements_non_value: RuntimeError # Expected
+value_class/copy_with_call_sites: RuntimeError # Expected
\ No newline at end of file
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 418cb27..47f67ff 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -252,17 +252,6 @@
       "exclude": []
     },
     {
-      "name": "old_dill",
-      "kind": "Chain",
-      "source": "test/old_dill_suite.dart",
-      "path": "testcases/old_dills/dills/",
-      "status": "testcases/old_dills/old_dills.status",
-      "pattern": [
-        ".*\\.dill$"
-      ],
-      "exclude": []
-    },
-    {
       "name": "parser",
       "kind": "Chain",
       "source": "test/parser_suite.dart",
diff --git a/pkg/front_end/tool/_fasta/bench_maker.dart b/pkg/front_end/tool/_fasta/bench_maker.dart
index 5ab2e3e..581b5a9 100644
--- a/pkg/front_end/tool/_fasta/bench_maker.dart
+++ b/pkg/front_end/tool/_fasta/bench_maker.dart
@@ -164,7 +164,7 @@
     }
     Procedure callOperator;
     for (Procedure procedure in cls.procedures) {
-      if (procedure.name.name == "call") {
+      if (procedure.name.text == "call") {
         callOperator = procedure;
       }
     }
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index fd864cf..ca24131 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -197,6 +197,7 @@
   Flags.target: const StringValue(),
   Flags.verbose: const BoolValue(false),
   Flags.verify: const BoolValue(false),
+  Flags.warnOnReachabilityCheck: const BoolValue(false),
   Flags.linkDependencies: const UriListValue(),
   Flags.noDeps: const BoolValue(false),
   "-D": const DefineValue(),
@@ -298,6 +299,8 @@
       ? NnbdMode.Agnostic
       : (nnbdStrongMode ? NnbdMode.Strong : NnbdMode.Weak);
 
+  final bool warnOnReachabilityCheck = options[Flags.warnOnReachabilityCheck];
+
   final List<Uri> linkDependencies = options[Flags.linkDependencies] ?? [];
 
   if (nnbdStrongMode && nnbdWeakMode) {
@@ -348,7 +351,8 @@
     ..environmentDefines = noDefines ? null : parsedArguments.defines
     ..nnbdMode = nnbdMode
     ..additionalDills = linkDependencies
-    ..emitDeps = !noDeps;
+    ..emitDeps = !noDeps
+    ..warnOnReachabilityCheck = warnOnReachabilityCheck;
 
   if (programName == "compile_platform") {
     if (arguments.length != 5) {
diff --git a/pkg/front_end/tool/_fasta/generate_messages.dart b/pkg/front_end/tool/_fasta/generate_messages.dart
index 2a47606..5eeb061 100644
--- a/pkg/front_end/tool/_fasta/generate_messages.dart
+++ b/pkg/front_end/tool/_fasta/generate_messages.dart
@@ -246,6 +246,13 @@
         conversions.add("name4 = demangleMixinApplicationName(name4);");
         break;
 
+      case "nameOKEmpty":
+        parameters.add("String nameOKEmpty");
+        conversions.add("if (nameOKEmpty == null || nameOKEmpty.isEmpty) "
+            "nameOKEmpty = '(unnamed)';");
+        arguments.add("'nameOKEmpty': nameOKEmpty");
+        break;
+
       case "names":
         parameters.add("List<String> _names");
         conversions.add("if (_names.isEmpty) throw 'No names provided';");
@@ -283,6 +290,13 @@
         arguments.add("'string3': string3");
         break;
 
+      case "stringOKEmpty":
+        parameters.add("String stringOKEmpty");
+        conversions.add("if (stringOKEmpty == null || stringOKEmpty.isEmpty) "
+            "stringOKEmpty = '(empty)';");
+        arguments.add("'stringOKEmpty': stringOKEmpty");
+        break;
+
       case "type":
       case "type2":
       case "type3":
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index ecbe56d..8bffb28 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -75,16 +75,7 @@
   }
 }
 
-Uri sdkRoot = _computeRoot();
-Uri _computeRoot() {
-  // TODO(sigmund): delete this when our performance bots include runtime/lib/
-  if (new Directory('runtime/lib/').existsSync()) {
-    return Uri.base.resolve("sdk/");
-  }
-  return Uri.base
-      .resolveUri(new Uri.file(Platform.resolvedExecutable))
-      .resolve('patched_sdk/');
-}
+Uri sdkRoot = Uri.base.resolve("sdk/");
 
 /// Translates `dart:*` and `package:*` URIs to resolved URIs.
 UriTranslator uriResolver;
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index af48251..dc92143 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -20,6 +20,7 @@
 import 'package:front_end/src/api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags;
 import 'package:front_end/src/api_unstable/vm.dart';
+import 'package:front_end/widget_cache.dart';
 import 'package:kernel/ast.dart' show Library, Procedure, LibraryDependency;
 import 'package:kernel/binary/ast_to_binary.dart';
 import 'package:kernel/kernel.dart'
@@ -176,7 +177,10 @@
       defaultsTo: false)
   ..addOption('dartdevc-module-format',
       help: 'The module format to use on for the dartdevc compiler',
-      defaultsTo: 'amd');
+      defaultsTo: 'amd')
+  ..addFlag('flutter-widget-cache',
+      help: 'Enable the widget cache to track changes to Widget subtypes',
+      defaultsTo: false);
 
 String usage = '''
 Usage: server [options] [input.dart]
@@ -338,6 +342,7 @@
 
   CompilerOptions _compilerOptions;
   BytecodeOptions _bytecodeOptions;
+  ProcessedOptions _processedOptions;
   FileSystem _fileSystem;
   Uri _mainSource;
   ArgResults _options;
@@ -345,6 +350,8 @@
   IncrementalCompiler _generator;
   JavaScriptBundler _bundler;
 
+  WidgetCache _widgetCache;
+
   String _kernelBinaryFilename;
   String _kernelBinaryFilenameIncremental;
   String _kernelBinaryFilenameFull;
@@ -510,6 +517,7 @@
 
     _compilerOptions = compilerOptions;
     _bytecodeOptions = bytecodeOptions;
+    _processedOptions = ProcessedOptions(options: compilerOptions);
 
     KernelCompilationResults results;
     IncrementalSerializer incrementalSerializer;
@@ -530,6 +538,9 @@
           component.uriToSource.keys);
 
       incrementalSerializer = _generator.incrementalSerializer;
+      if (options['flutter-widget-cache']) {
+        _widgetCache = WidgetCache(component);
+      }
     } else {
       if (options['link-platform']) {
         // TODO(aam): Remove linkedDependencies once platform is directly embedded
@@ -904,6 +915,7 @@
       await writeDillFile(results, _kernelBinaryFilename,
           incrementalSerializer: _generator.incrementalSerializer);
     }
+    _updateWidgetCache(deltaProgram);
 
     _outputStream.writeln(boundaryKey);
     await _outputDependenciesDelta(results.compiledSources);
@@ -962,14 +974,21 @@
     final String boundaryKey = Uuid().generateV4();
     _outputStream.writeln('result $boundaryKey');
 
+    _processedOptions.ticker.logMs('Compiling expression to JavaScript');
+
     var kernel2jsCompiler = _bundler.compilers[moduleName];
     Component component = _generator.lastKnownGoodComponent;
     component.computeCanonicalNames();
+
+    _processedOptions.ticker.logMs('Computed component');
+
     var evaluator = new ExpressionCompiler(
-        _generator.generator, kernel2jsCompiler, component,
-        verbose: _compilerOptions.verbose,
-        onDiagnostic: _compilerOptions.onDiagnostic,
-        errors: errors);
+      _compilerOptions,
+      errors,
+      _generator.generator,
+      kernel2jsCompiler,
+      component,
+    );
 
     var procedure = await evaluator.compileExpressionToJs(libraryUri, line,
         column, jsModules, jsFrameValues, moduleName, expression);
@@ -980,6 +999,8 @@
     // rename to _outputFileName?
     await File(_kernelBinaryFilename).writeAsString(result);
 
+    _processedOptions.ticker.logMs('Compiled expression to JavaScript');
+
     _outputStream
         .writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
 
@@ -1095,6 +1116,7 @@
   @override
   void acceptLastDelta() {
     _generator.accept();
+    _widgetCache?.reset();
   }
 
   @override
@@ -1108,11 +1130,13 @@
   @override
   void invalidate(Uri uri) {
     _generator.invalidate(uri);
+    _widgetCache?.invalidate(uri);
   }
 
   @override
   void resetIncrementalCompiler() {
     _generator.resetDeltaState();
+    _widgetCache?.reset();
     _kernelBinaryFilename = _kernelBinaryFilenameFull;
   }
 
@@ -1122,6 +1146,31 @@
         incrementalSerialization: incrementalSerialization);
   }
 
+  /// If the flutter widget cache is enabled, check if a single class was modified.
+  ///
+  /// The resulting class name is written as a String to
+  /// `_kernelBinaryFilename`.widget_cache, or else the file is deleted
+  /// if it exists.
+  ///
+  /// Should not run if a full component is requested.
+  void _updateWidgetCache(Component partialComponent) {
+    if (_widgetCache == null || _generator.fullComponent) {
+      return;
+    }
+    final String singleModifiedClassName =
+        _widgetCache.checkSingleWidgetTypeModified(
+      _generator.lastKnownGoodComponent,
+      partialComponent,
+      _generator.getClassHierarchy(),
+    );
+    final File outputFile = File('$_kernelBinaryFilename.widget_cache');
+    if (singleModifiedClassName != null) {
+      outputFile.writeAsStringSync(singleModifiedClassName);
+    } else if (outputFile.existsSync()) {
+      outputFile.deleteSync();
+    }
+  }
+
   Uri _ensureFolderPath(String path) {
     String uriPath = Uri.file(path).toString();
     if (!uriPath.endsWith('/')) {
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index d4b17b7..3bbdeb0 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -68,6 +68,24 @@
       expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
       expect(capturedArgs.single['link-platform'], equals(true));
     });
+
+    test('compile from command line with widget cache', () async {
+      final List<String> args = <String>[
+        'server.dart',
+        '--sdk-root',
+        'sdkroot',
+        '--flutter-widget-cache',
+      ];
+      await starter(args, compiler: compiler);
+      final List<dynamic> capturedArgs = verify(compiler.compile(
+        argThat(equals('server.dart')),
+        captureAny,
+        generator: anyNamed('generator'),
+      )).captured;
+      expect(capturedArgs.single['sdk-root'], equals('sdkroot'));
+      expect(capturedArgs.single['link-platform'], equals(true));
+      expect(capturedArgs.single['flutter-widget-cache'], equals(true));
+    });
   });
 
   group('interactive compile with mocked compiler', () {
@@ -230,6 +248,34 @@
       inputStreamController.close();
     });
 
+    test('recompile one file with widget cache does not fail', () async {
+      // The component will not contain the flutter framework sources so
+      // this should no-op.
+      final StreamController<List<int>> inputStreamController =
+          StreamController<List<int>>();
+      final ReceivePort recompileCalled = ReceivePort();
+
+      when(compiler.recompileDelta(entryPoint: null))
+          .thenAnswer((Invocation invocation) async {
+        recompileCalled.sendPort.send(true);
+      });
+      Future<int> result = starter(
+        <String>[...args, '--flutter-widget-cache'],
+        compiler: compiler,
+        input: inputStreamController.stream,
+      );
+      inputStreamController.add('recompile abc\nfile1.dart\nabc\n'.codeUnits);
+      await recompileCalled.first;
+
+      verifyInOrder(<void>[
+        compiler.invalidate(Uri.base.resolve('file1.dart')),
+        await compiler.recompileDelta(entryPoint: null),
+      ]);
+      inputStreamController.add('quit\n'.codeUnits);
+      expect(await result, 0);
+      inputStreamController.close();
+    });
+
     test('recompile few files with new entrypoint', () async {
       final StreamController<List<int>> inputStreamController =
           StreamController<List<int>>();
@@ -836,7 +882,7 @@
 
           file.writeAsStringSync("import 'lib.dart'; main() => foo();\n");
           inputStreamController.add('recompile ${file.path} abc\n'
-                  '${file.path}\n'
+                  '${file.uri}\n'
                   'abc\n'
               .codeUnits);
 
@@ -906,7 +952,7 @@
           var file2 = File('${tempDir.path}/bar.dart')..createSync();
           file2.writeAsStringSync("main() {}\n");
           inputStreamController.add('recompile ${file2.path} abc\n'
-                  '${file2.path}\n'
+                  '${file2.uri}\n'
                   'abc\n'
               .codeUnits);
         } else {
@@ -923,6 +969,218 @@
       inputStreamController.close();
     });
 
+    test(
+        'recompile request with flutter widget cache outputs change in class name',
+        () async {
+      var frameworkDirectory = Directory('${tempDir.path}/flutter');
+      var flutterFramework =
+          File('${frameworkDirectory.path}/lib/src/widgets/framework.dart')
+            ..createSync(recursive: true);
+      flutterFramework.writeAsStringSync('''
+abstract class Widget {}
+class StatelessWidget extends Widget {}
+class StatefulWidget extends Widget {}
+class State<T extends StatefulWidget> {}
+''');
+
+      var file = File('${tempDir.path}/foo.dart')..createSync();
+      file.writeAsStringSync("""
+import "package:flutter/src/widgets/framework.dart";
+
+void main() {}
+
+class FooWidget extends StatelessWidget {}
+
+class FizzWidget extends StatefulWidget {}
+
+class BarState extends State<FizzWidget> {}
+""");
+      var config = File('${tempDir.path}/package_config.json')..createSync();
+      config.writeAsStringSync('''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "flutter",
+      "rootUri": "${frameworkDirectory.uri}",
+      "packageUri": "lib/",
+      "languageVersion": "2.2"
+    }
+  ]
+}
+''');
+
+      var dillFile = File('${tempDir.path}/app.dill');
+      expect(dillFile.existsSync(), equals(false));
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${platformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--flutter-widget-cache',
+        '--packages=${config.path}',
+      ];
+
+      final StreamController<List<int>> inputStreamController =
+          StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          StreamController<List<int>>();
+      final IOSink ioSink = IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = StreamController<Result>();
+
+      final outputParser = OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      Future<int> result =
+          starter(args, input: inputStreamController.stream, output: ioSink);
+      inputStreamController.add('compile ${file.path}\n'.codeUnits);
+      int count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        if (count == 0) {
+          // First request is to 'compile', which results in full kernel file.
+          expect(dillFile.existsSync(), equals(true));
+          compiledResult.expectNoErrors(filename: dillFile.path);
+          count += 1;
+          inputStreamController.add('accept\n'.codeUnits);
+          file.writeAsStringSync("""
+import "package:flutter/src/widgets/framework.dart";
+
+void main() {}
+
+class FooWidget extends StatelessWidget {
+  // Added.
+}
+
+class FizzWidget extends StatefulWidget {}
+
+class BarState extends State<FizzWidget> {}
+""");
+          inputStreamController.add('recompile ${file.path} abc\n'
+                  '${file.uri}\n'
+                  'abc\n'
+              .codeUnits);
+        } else if (count == 1) {
+          expect(count, 1);
+          // Second request is to 'recompile', which results in incremental
+          // kernel file and invalidation of StatelessWidget.
+          var dillIncFile = File('${dillFile.path}.incremental.dill');
+          var widgetCacheFile =
+              File('${dillFile.path}.incremental.dill.widget_cache');
+          compiledResult.expectNoErrors(filename: dillIncFile.path);
+          expect(dillIncFile.existsSync(), equals(true));
+          expect(widgetCacheFile.existsSync(), equals(true));
+          expect(widgetCacheFile.readAsStringSync(), 'FooWidget');
+          count += 1;
+          inputStreamController.add('accept\n'.codeUnits);
+
+          file.writeAsStringSync("""
+import "package:flutter/src/widgets/framework.dart";
+
+void main() {}
+
+class FooWidget extends StatelessWidget {
+  // Added.
+}
+
+class FizzWidget extends StatefulWidget {
+  // Added.
+}
+
+class BarState extends State<FizzWidget> {}
+""");
+          inputStreamController.add('recompile ${file.path} abc\n'
+                  '${file.uri}\n'
+                  'abc\n'
+              .codeUnits);
+        } else if (count == 2) {
+          // Second request is to 'recompile', which results in incremental
+          // kernel file and invalidation of StatelessWidget.
+          var dillIncFile = File('${dillFile.path}.incremental.dill');
+          var widgetCacheFile =
+              File('${dillFile.path}.incremental.dill.widget_cache');
+          compiledResult.expectNoErrors(filename: dillIncFile.path);
+          expect(dillIncFile.existsSync(), equals(true));
+          expect(widgetCacheFile.existsSync(), equals(true));
+          expect(widgetCacheFile.readAsStringSync(), 'FizzWidget');
+          count += 1;
+          inputStreamController.add('accept\n'.codeUnits);
+
+          file.writeAsStringSync("""
+import "package:flutter/src/widgets/framework.dart";
+
+void main() {}
+
+class FooWidget extends StatelessWidget {
+  // Added.
+}
+
+class FizzWidget extends StatefulWidget {
+  // Added.
+}
+
+class BarState extends State<FizzWidget> {
+  // Added.
+}
+""");
+          inputStreamController.add('recompile ${file.path} abc\n'
+                  '${file.uri}\n'
+                  'abc\n'
+              .codeUnits);
+        } else if (count == 3) {
+          // Third request is to 'recompile', which results in incremental
+          // kernel file and invalidation of State class.
+          var dillIncFile = File('${dillFile.path}.incremental.dill');
+          var widgetCacheFile =
+              File('${dillFile.path}.incremental.dill.widget_cache');
+          compiledResult.expectNoErrors(filename: dillIncFile.path);
+          expect(dillIncFile.existsSync(), equals(true));
+          expect(widgetCacheFile.existsSync(), equals(true));
+          expect(widgetCacheFile.readAsStringSync(), 'FizzWidget');
+          count += 1;
+          inputStreamController.add('accept\n'.codeUnits);
+
+          file.writeAsStringSync("""
+import "package:flutter/src/widgets/framework.dart";
+
+void main() {}
+
+// Added
+
+class FooWidget extends StatelessWidget {
+  // Added.
+}
+
+class FizzWidget extends StatefulWidget {
+  // Added.
+}
+
+class BarState extends State<FizzWidget> {
+  // Added.
+}
+""");
+          inputStreamController.add('recompile ${file.path} abc\n'
+                  '${file.uri}\n'
+                  'abc\n'
+              .codeUnits);
+        } else if (count == 4) {
+          // Fourth request is to 'recompile', which results in incremental
+          // kernel file and no widget cache
+          var dillIncFile = File('${dillFile.path}.incremental.dill');
+          var widgetCacheFile =
+              File('${dillFile.path}.incremental.dill.widget_cache');
+          compiledResult.expectNoErrors(filename: dillIncFile.path);
+          expect(dillIncFile.existsSync(), equals(true));
+          expect(widgetCacheFile.existsSync(), equals(false));
+          inputStreamController.add('quit\n'.codeUnits);
+        }
+      });
+      expect(await result, 0);
+      inputStreamController.close();
+    });
+
     test('unsafe-package-serialization', () async {
       // Package A.
       var file = File('${tempDir.path}/pkgA/a.dart')
@@ -999,7 +1257,7 @@
             inputStreamController.add('reset\n'.codeUnits);
 
             inputStreamController.add('recompile ${fileB.path} abc\n'
-                    '${fileB.path}\n'
+                    '${fileB.uri}\n'
                     'abc\n'
                 .codeUnits);
             break;
@@ -1105,7 +1363,7 @@
             inputStreamController.add('reset\n'.codeUnits);
 
             inputStreamController.add('recompile ${fileB.path} abc\n'
-                    '${fileB.path}\n'
+                    '${fileB.uri}\n'
                     'abc\n'
                 .codeUnits);
             break;
diff --git a/pkg/js/CHANGELOG.md b/pkg/js/CHANGELOG.md
index a996ef1..3728fa9 100644
--- a/pkg/js/CHANGELOG.md
+++ b/pkg/js/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.3-nullsafety.1
+
+* Allow 2.10 stable and 2.11.0 dev SDK versions.
+
 ## 0.6.3-nullsafety
 
 * Opt in to null safety.
diff --git a/pkg/js/pubspec.yaml b/pkg/js/pubspec.yaml
index 67165c3..b9d05c4 100644
--- a/pkg/js/pubspec.yaml
+++ b/pkg/js/pubspec.yaml
@@ -1,10 +1,10 @@
 name: js
-version: 0.6.3-nullsafety
+version: 0.6.3-nullsafety.1
 description: Annotations to create static Dart interfaces for JavaScript APIs.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/js
 
 environment:
-  sdk: '>=2.10.0-0 <2.10.0'
+  sdk: '>=2.10.0-0 <2.11.0'
 
 dev_dependencies:
   pedantic: ^1.9.0
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index b36cb0c..aade49b 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -143,7 +143,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 45;
+  UInt32 formatVersion = 46;
   Byte[10] shortSdkHash;
   List<String> problemsAsJson; // Described in problems.md.
   Library[] libraries;
@@ -613,23 +613,6 @@
   MemberReference interfaceTargetOrigin; // May be NullReference.
 }
 
-type DirectPropertyGet extends Expression {
-  Byte tag = 15; // Note: tag is out of order
-  FileOffset fileOffset;
-  Expression receiver;
-  MemberReference target;
-  MemberReference targetOrigin; // May be NullReference.
-}
-
-type DirectPropertySet extends Expression {
-  Byte tag = 16; // Note: tag is out of order
-  FileOffset fileOffset;
-  Expression receiver;
-  MemberReference target;
-  MemberReference targetOrigin; // May be NullReference.
-  Expression value;
-}
-
 type StaticGet extends Expression {
   Byte tag = 26;
   FileOffset fileOffset;
@@ -676,15 +659,6 @@
   MemberReference interfaceTargetOrigin; // May be NullReference.
 }
 
-type DirectMethodInvocation extends Expression {
-  Byte tag = 17; // Note: tag is out of order
-  FileOffset fileOffset;
-  Expression receiver;
-  MemberReference target;
-  MemberReference targetOrigin; // May be NullReference.
-  Arguments arguments;
-}
-
 type StaticInvocation extends Expression {
   Byte tag = 30;
   FileOffset fileOffset;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index bbde631..e9b6940 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -3252,7 +3252,7 @@
           .substituteType(interfaceTarget.getterType);
     }
     // Treat the properties of Object specially.
-    String nameString = name.name;
+    String nameString = name.text;
     if (nameString == 'hashCode') {
       return context.typeEnvironment.coreTypes.intRawType(context.nonNullable);
     } else if (nameString == 'runtimeType') {
@@ -3362,203 +3362,6 @@
   }
 }
 
-/// Directly read a field, call a getter, or tear off a method.
-class DirectPropertyGet extends Expression {
-  Expression receiver;
-  Reference targetReference;
-
-  DirectPropertyGet(Expression receiver, Member target)
-      : this.byReference(receiver, getMemberReference(target));
-
-  DirectPropertyGet.byReference(this.receiver, this.targetReference) {
-    receiver?.parent = this;
-  }
-
-  Member get target => targetReference?.asMember;
-
-  void set target(Member target) {
-    targetReference = getMemberReference(target);
-  }
-
-  Name get name => target?.name;
-
-  visitChildren(Visitor v) {
-    receiver?.accept(v);
-    target?.acceptReference(v);
-  }
-
-  transformChildren(Transformer v) {
-    if (receiver != null) {
-      receiver = receiver.accept<TreeNode>(v);
-      receiver?.parent = this;
-    }
-  }
-
-  R accept<R>(ExpressionVisitor<R> v) => v.visitDirectPropertyGet(this);
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitDirectPropertyGet(this, arg);
-
-  DartType getStaticType(StaticTypeContext context) {
-    Class superclass = target.enclosingClass;
-    var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, context);
-    return Substitution.fromInterfaceType(receiverType)
-        .substituteType(target.getterType);
-  }
-
-  @override
-  String toString() {
-    return "DirectPropertyGet(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(targetReference, name);
-  }
-}
-
-/// Directly assign a field, or call a setter.
-///
-/// Evaluates to the value of [value].
-class DirectPropertySet extends Expression {
-  Expression receiver;
-  Reference targetReference;
-  Expression value;
-
-  DirectPropertySet(Expression receiver, Member target, Expression value)
-      : this.byReference(receiver, getMemberReference(target), value);
-
-  DirectPropertySet.byReference(
-      this.receiver, this.targetReference, this.value) {
-    receiver?.parent = this;
-    value?.parent = this;
-  }
-
-  Member get target => targetReference?.asMember;
-
-  void set target(Member target) {
-    targetReference = getMemberReference(target);
-  }
-
-  Name get name => target?.name;
-
-  visitChildren(Visitor v) {
-    receiver?.accept(v);
-    target?.acceptReference(v);
-    value?.accept(v);
-  }
-
-  transformChildren(Transformer v) {
-    if (receiver != null) {
-      receiver = receiver.accept<TreeNode>(v);
-      receiver?.parent = this;
-    }
-    if (value != null) {
-      value = value.accept<TreeNode>(v);
-      value?.parent = this;
-    }
-  }
-
-  R accept<R>(ExpressionVisitor<R> v) => v.visitDirectPropertySet(this);
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitDirectPropertySet(this, arg);
-
-  DartType getStaticType(StaticTypeContext context) =>
-      value.getStaticType(context);
-
-  @override
-  String toString() {
-    return "DirectPropertySet(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(targetReference, name);
-    printer.write(' = ');
-    printer.writeExpression(value);
-  }
-}
-
-/// Directly call an instance method, bypassing ordinary dispatch.
-class DirectMethodInvocation extends InvocationExpression {
-  Expression receiver;
-  Reference targetReference;
-  Arguments arguments;
-
-  DirectMethodInvocation(
-      Expression receiver, Procedure target, Arguments arguments)
-      : this.byReference(receiver, getMemberReference(target), arguments);
-
-  DirectMethodInvocation.byReference(
-      this.receiver, this.targetReference, this.arguments) {
-    receiver?.parent = this;
-    arguments?.parent = this;
-  }
-
-  Procedure get target => targetReference?.asProcedure;
-
-  void set target(Procedure target) {
-    targetReference = getMemberReference(target);
-  }
-
-  Name get name => target?.name;
-
-  visitChildren(Visitor v) {
-    receiver?.accept(v);
-    target?.acceptReference(v);
-    arguments?.accept(v);
-  }
-
-  transformChildren(Transformer v) {
-    if (receiver != null) {
-      receiver = receiver.accept<TreeNode>(v);
-      receiver?.parent = this;
-    }
-    if (arguments != null) {
-      arguments = arguments.accept<TreeNode>(v);
-      arguments?.parent = this;
-    }
-  }
-
-  R accept<R>(ExpressionVisitor<R> v) => v.visitDirectMethodInvocation(this);
-  R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
-      v.visitDirectMethodInvocation(this, arg);
-
-  DartType getStaticType(StaticTypeContext context) {
-    if (context.typeEnvironment.isSpecialCasedBinaryOperator(target)) {
-      return context.typeEnvironment.getTypeOfSpecialCasedBinaryOperator(
-          receiver.getStaticType(context),
-          arguments.positional[0].getStaticType(context));
-    }
-    Class superclass = target.enclosingClass;
-    var receiverType = receiver.getStaticTypeAsInstanceOf(superclass, context);
-    var returnType = Substitution.fromInterfaceType(receiverType)
-        .substituteType(target.function.returnType);
-    return Substitution.fromPairs(
-            target.function.typeParameters, arguments.types)
-        .substituteType(returnType);
-  }
-
-  @override
-  String toString() {
-    return "DirectMethodInvocation(${toStringInternal()})";
-  }
-
-  @override
-  void toTextInternal(AstPrinter printer) {
-    printer.writeExpression(receiver,
-        minimumPrecedence: astToText.Precedence.PRIMARY);
-    printer.write('.');
-    printer.writeInterfaceMemberName(targetReference, name);
-    printer.writeArguments(arguments);
-  }
-}
-
 /// Expression of form `super.field`.
 ///
 /// This may invoke a getter, read a field, or tear off a method.
@@ -3790,13 +3593,16 @@
 
   factory Arguments.forwarded(FunctionNode function, Library library) {
     return new Arguments(
-        function.positionalParameters.map((p) => new VariableGet(p)).toList(),
+        function.positionalParameters
+            .map<Expression>((p) => new VariableGet(p))
+            .toList(),
         named: function.namedParameters
             .map((p) => new NamedExpression(p.name, new VariableGet(p)))
             .toList(),
         types: function.typeParameters
-            .map((p) => new TypeParameterType.withDefaultNullabilityForLibrary(
-                p, library))
+            .map<DartType>((p) =>
+                new TypeParameterType.withDefaultNullabilityForLibrary(
+                    p, library))
             .toList());
   }
 
@@ -3979,7 +3785,7 @@
       }
       return const DynamicType();
     }
-    if (name.name == 'call') {
+    if (name.text == 'call') {
       var receiverType = receiver.getStaticType(context);
       if (receiverType is FunctionType) {
         if (receiverType.typeParameters.length != arguments.types.length) {
@@ -3990,7 +3796,7 @@
             .substituteType(receiverType.returnType);
       }
     }
-    if (name.name == '==') {
+    if (name.text == '==') {
       // We use this special case to simplify generation of '==' checks.
       return context.typeEnvironment.coreTypes.boolRawType(context.nonNullable);
     }
@@ -4243,9 +4049,9 @@
     }
     printer.writeClassName(target.enclosingClass.reference);
     printer.writeTypeArguments(arguments.types);
-    if (target.name.name.isNotEmpty) {
+    if (target.name.text.isNotEmpty) {
       printer.write('.');
-      printer.write(target.name.name);
+      printer.write(target.name.text);
     }
     printer.writeArguments(arguments, includeTypeArguments: false);
   }
@@ -4336,13 +4142,25 @@
   }
 }
 
+enum LogicalExpressionOperator { AND, OR }
+
+String logicalExpressionOperatorToString(LogicalExpressionOperator operator) {
+  switch (operator) {
+    case LogicalExpressionOperator.AND:
+      return "&&";
+    case LogicalExpressionOperator.OR:
+      return "||";
+  }
+  throw "Unhandled LogicalExpressionOperator: ${operator}";
+}
+
 /// Expression of form `x && y` or `x || y`
 class LogicalExpression extends Expression {
   Expression left;
-  String operator; // && or || or ??
+  LogicalExpressionOperator operatorEnum; // AND (&&) or OR (||).
   Expression right;
 
-  LogicalExpression(this.left, this.operator, this.right) {
+  LogicalExpression(this.left, this.operatorEnum, this.right) {
     left?.parent = this;
     right?.parent = this;
   }
@@ -4379,7 +4197,7 @@
   void toTextInternal(AstPrinter printer) {
     int minimumPrecedence = precedence;
     printer.writeExpression(left, minimumPrecedence: minimumPrecedence);
-    printer.write(' $operator ');
+    printer.write(' ${logicalExpressionOperatorToString(operatorEnum)} ');
     printer.writeExpression(right, minimumPrecedence: minimumPrecedence + 1);
   }
 }
@@ -7085,29 +6903,33 @@
 /// library name for private names; uniqueness is not guaranteed.
 abstract class Name extends Node {
   final int hashCode;
-  final String name;
+  final String text;
   Reference get libraryName;
   Library get library;
   bool get isPrivate;
 
-  Name._internal(this.hashCode, this.name);
+  Name._internal(this.hashCode, this.text);
 
-  factory Name(String name, [Library library]) =>
-      new Name.byReference(name, library?.reference);
+  factory Name(String text, [Library library]) =>
+      new Name.byReference(text, library?.reference);
 
-  factory Name.byReference(String name, Reference libraryName) {
+  factory Name.byReference(String text, Reference libraryName) {
     /// Use separate subclasses for the public and private case to save memory
     /// for public names.
-    if (name.startsWith('_')) {
+    if (text.startsWith('_')) {
       assert(libraryName != null);
-      return new _PrivateName(name, libraryName);
+      return new _PrivateName(text, libraryName);
     } else {
-      return new _PublicName(name);
+      return new _PublicName(text);
     }
   }
 
+  // TODO(johnniwinther): Remove this when dependent code has been updated to
+  // use [text].
+  String get name => text;
+
   bool operator ==(other) {
-    return other is Name && name == other.name && library == other.library;
+    return other is Name && text == other.text && library == other.library;
   }
 
   R accept<R>(Visitor<R> v) => v.visitName(this);
@@ -7132,13 +6954,13 @@
   final Reference libraryName;
   bool get isPrivate => true;
 
-  _PrivateName(String name, Reference libraryName)
+  _PrivateName(String text, Reference libraryName)
       : this.libraryName = libraryName,
-        super._internal(_computeHashCode(name, libraryName), name);
+        super._internal(_computeHashCode(text, libraryName), text);
 
   String toString() => toStringInternal();
 
-  String toStringInternal() => library != null ? '$library::$name' : name;
+  String toStringInternal() => library != null ? '$library::$text' : text;
 
   Library get library => libraryName.asLibrary;
 
@@ -7155,7 +6977,7 @@
   Library get library => null;
   bool get isPrivate => false;
 
-  _PublicName(String name) : super._internal(name.hashCode, name);
+  _PublicName(String text) : super._internal(text.hashCode, text);
 
   String toString() => toStringInternal();
 }
@@ -8935,8 +8757,18 @@
   R accept<R>(ConstantVisitor<R> v) => v.visitStringConstant(this);
   R acceptReference<R>(Visitor<R> v) => v.visitStringConstantReference(this);
 
+  @override
   DartType getType(StaticTypeContext context) =>
       context.typeEnvironment.coreTypes.stringRawType(context.nonNullable);
+
+  @override
+  void toTextInternal(AstPrinter printer) {
+    printer.write('"');
+    printer.write(escapeString(value));
+    printer.write('"');
+  }
+
+  String toString() => 'StringConstant(${toStringInternal()})';
 }
 
 class SymbolConstant extends Constant {
@@ -8951,7 +8783,7 @@
   R acceptReference<R>(Visitor<R> v) => v.visitSymbolConstantReference(this);
 
   @override
-  String toString() => 'StringConstant(${toStringInternal()})';
+  String toString() => 'SymbolConstant(${toStringInternal()})';
 
   int get hashCode => _Hash.hash2(name, libraryReference);
 
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index d718a30..01e245c 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -1324,7 +1324,7 @@
     var name = readName();
     var annotations = readAnnotationList(node);
     assert(() {
-      debugPath.add(node.name?.name ?? 'field');
+      debugPath.add(node.name?.text ?? 'field');
       return true;
     }());
     var type = readDartType();
@@ -1364,7 +1364,7 @@
     var name = readName();
     var annotations = readAnnotationList(node);
     assert(() {
-      debugPath.add(node.name?.name ?? 'constructor');
+      debugPath.add(node.name?.text ?? 'constructor');
       return true;
     }());
     var function = readFunctionNode();
@@ -1408,7 +1408,7 @@
     var name = readName();
     var annotations = readAnnotationList(node);
     assert(() {
-      debugPath.add(node.name?.name ?? 'procedure');
+      debugPath.add(node.name?.text ?? 'procedure');
       return true;
     }());
     int functionNodeSize = endOffset - _byteOffset;
@@ -1469,7 +1469,7 @@
     var name = readName();
     var annotations = readAnnotationList(node);
     assert(() {
-      debugPath.add(node.name?.name ?? 'redirecting-factory-constructor');
+      debugPath.add(node.name?.text ?? 'redirecting-factory-constructor');
       return true;
     }());
     var targetReference = readMemberReference();
@@ -1638,12 +1638,12 @@
     return variableStack[index];
   }
 
-  String logicalOperatorToString(int index) {
+  LogicalExpressionOperator logicalOperatorToEnum(int index) {
     switch (index) {
       case 0:
-        return '&&';
+        return LogicalExpressionOperator.AND;
       case 1:
-        return '||';
+        return LogicalExpressionOperator.OR;
       default:
         throw fail('unexpected logical operator index: $index');
     }
@@ -1720,16 +1720,6 @@
         return new SuperPropertySet.byReference(readName(), readExpression(),
             readInstanceMemberReference(allowNull: true))
           ..fileOffset = offset;
-      case Tag.DirectPropertyGet:
-        int offset = readOffset();
-        return new DirectPropertyGet.byReference(
-            readExpression(), readInstanceMemberReference())
-          ..fileOffset = offset;
-      case Tag.DirectPropertySet:
-        int offset = readOffset();
-        return new DirectPropertySet.byReference(
-            readExpression(), readInstanceMemberReference(), readExpression())
-          ..fileOffset = offset;
       case Tag.StaticGet:
         int offset = readOffset();
         return new StaticGet.byReference(readMemberReference())
@@ -1750,11 +1740,6 @@
         return new SuperMethodInvocation.byReference(readName(),
             readArguments(), readInstanceMemberReference(allowNull: true))
           ..fileOffset = offset;
-      case Tag.DirectMethodInvocation:
-        int offset = readOffset();
-        return new DirectMethodInvocation.byReference(
-            readExpression(), readInstanceMemberReference(), readArguments())
-          ..fileOffset = offset;
       case Tag.StaticInvocation:
         int offset = readOffset();
         return new StaticInvocation.byReference(
@@ -1786,7 +1771,7 @@
         return new NullCheck(readExpression())..fileOffset = offset;
       case Tag.LogicalExpression:
         return new LogicalExpression(readExpression(),
-            logicalOperatorToString(readByte()), readExpression());
+            logicalOperatorToEnum(readByte()), readExpression());
       case Tag.ConditionalExpression:
         return new ConditionalExpression(readExpression(), readExpression(),
             readExpression(), readDartTypeOption());
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 481479e..2dbc82f 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -937,7 +937,7 @@
     if (_metadataSubsections != null) {
       _writeNodeMetadata(node);
     }
-    writeStringReference(node.name);
+    writeStringReference(node.text);
     // TODO: Consider a more compressed format for private names within the
     // enclosing library.
     if (node.isPrivate) {
@@ -1235,8 +1235,10 @@
     leaveScope(memberScope: true);
 
     _currentlyInNonimplementation = currentlyInNonimplementationSaved;
-    assert((node.forwardingStubSuperTarget != null) ||
-        !(node.isForwardingStub && node.function.body != null));
+    assert(
+        (node.forwardingStubSuperTarget != null) ||
+            !(node.isForwardingStub && node.function.body != null),
+        "Invalid forwarding stub $node.");
   }
 
   @override
@@ -1443,23 +1445,6 @@
   }
 
   @override
-  void visitDirectPropertyGet(DirectPropertyGet node) {
-    writeByte(Tag.DirectPropertyGet);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeNonNullInstanceMemberReference(node.targetReference);
-  }
-
-  @override
-  void visitDirectPropertySet(DirectPropertySet node) {
-    writeByte(Tag.DirectPropertySet);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeNonNullInstanceMemberReference(node.targetReference);
-    writeNode(node.value);
-  }
-
-  @override
   void visitStaticGet(StaticGet node) {
     writeByte(Tag.StaticGet);
     writeOffset(node.fileOffset);
@@ -1494,15 +1479,6 @@
   }
 
   @override
-  void visitDirectMethodInvocation(DirectMethodInvocation node) {
-    writeByte(Tag.DirectMethodInvocation);
-    writeOffset(node.fileOffset);
-    writeNode(node.receiver);
-    writeNonNullInstanceMemberReference(node.targetReference);
-    writeArgumentsNode(node.arguments);
-  }
-
-  @override
   void visitStaticInvocation(StaticInvocation node) {
     writeByte(node.isConst ? Tag.ConstStaticInvocation : Tag.StaticInvocation);
     writeOffset(node.fileOffset);
@@ -1547,11 +1523,11 @@
     writeNode(node.operand);
   }
 
-  int logicalOperatorIndex(String operator) {
+  int logicalOperatorIndex(LogicalExpressionOperator operator) {
     switch (operator) {
-      case '&&':
+      case LogicalExpressionOperator.AND:
         return 0;
-      case '||':
+      case LogicalExpressionOperator.OR:
         return 1;
     }
     throw new ArgumentError('Not a logical operator: $operator');
@@ -1561,7 +1537,7 @@
   void visitLogicalExpression(LogicalExpression node) {
     writeByte(Tag.LogicalExpression);
     writeNode(node.left);
-    writeByte(logicalOperatorIndex(node.operator));
+    writeByte(logicalOperatorIndex(node.operatorEnum));
     writeNode(node.right);
   }
 
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index a70bec0..2bbc968 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -29,9 +29,6 @@
   // Expressions
   static const int CheckLibraryIsLoaded = 13;
   static const int LoadLibrary = 14;
-  static const int DirectPropertyGet = 15;
-  static const int DirectPropertySet = 16;
-  static const int DirectMethodInvocation = 17;
   static const int ConstStaticInvocation = 18;
   static const int InvalidExpression = 19;
   static const int VariableGet = 20;
@@ -149,7 +146,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 45;
+  static const int BinaryFormatVersion = 46;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/canonical_name.dart b/pkg/kernel/lib/canonical_name.dart
index c7e7067..95acedd 100644
--- a/pkg/kernel/lib/canonical_name.dart
+++ b/pkg/kernel/lib/canonical_name.dart
@@ -118,8 +118,8 @@
 
   CanonicalName getChildFromQualifiedName(Name name) {
     return name.isPrivate
-        ? getChildFromUri(name.library.importUri).getChild(name.name)
-        : getChild(name.name);
+        ? getChildFromUri(name.library.importUri).getChild(name.text)
+        : getChild(name.text);
   }
 
   CanonicalName getChildFromMember(Member member) {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 446a07f..9f8500c 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -281,8 +281,8 @@
     int firstHash = firstName.hashCode;
     int secondHash = secondName.hashCode;
     if (firstHash != secondHash) return firstHash - secondHash;
-    String firstString = firstName.name;
-    String secondString = secondName.name;
+    String firstString = firstName.text;
+    String secondString = secondName.text;
     int firstLength = firstString.length;
     int secondLength = secondString.length;
     if (firstLength != secondLength) {
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 6b7bbad..507d6a1 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -138,16 +138,6 @@
         clone(node.value), node.interfaceTargetReference);
   }
 
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    return new DirectPropertyGet.byReference(
-        clone(node.receiver), node.targetReference);
-  }
-
-  visitDirectPropertySet(DirectPropertySet node) {
-    return new DirectPropertySet.byReference(
-        clone(node.receiver), node.targetReference, clone(node.value));
-  }
-
   visitSuperPropertyGet(SuperPropertyGet node) {
     return new SuperPropertyGet.byReference(
         node.name, node.interfaceTargetReference);
@@ -171,11 +161,6 @@
         clone(node.arguments), node.interfaceTargetReference);
   }
 
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    return new DirectMethodInvocation.byReference(
-        clone(node.receiver), node.targetReference, clone(node.arguments));
-  }
-
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     return new SuperMethodInvocation.byReference(
         node.name, clone(node.arguments), node.interfaceTargetReference);
@@ -203,7 +188,7 @@
 
   visitLogicalExpression(LogicalExpression node) {
     return new LogicalExpression(
-        clone(node.left), node.operator, clone(node.right));
+        clone(node.left), node.operatorEnum, clone(node.right));
   }
 
   visitConditionalExpression(ConditionalExpression node) {
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index cc60986..d67ff48 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -31,6 +31,7 @@
     ],
     'dart:_internal': [
       'LateInitializationErrorImpl',
+      'ReachabilityError',
       'Symbol',
     ],
     'dart:async': [
@@ -71,6 +72,8 @@
   Procedure _iterableGetIterator;
   Procedure _iteratorMoveNext;
   Procedure _iteratorGetCurrent;
+  Procedure _isSentinelMethod;
+  Procedure _createSentinelMethod;
 
   Class _internalSymbolClass;
 
@@ -95,6 +98,7 @@
   Procedure _awaitHelperProcedure;
   Procedure _boolFromEnvironment;
   Constructor _lateInitializationErrorConstructor;
+  Constructor _reachabilityErrorConstructor;
 
   /// The `dart:mirrors` library, or `null` if the component does not use it.
   Library _mirrorsLibrary;
@@ -497,6 +501,16 @@
         index.getMember('dart:core', 'bool', 'fromEnvironment');
   }
 
+  Procedure get createSentinelMethod {
+    return _createSentinelMethod ??=
+        index.getTopLevelMember('dart:_internal', 'createSentinel');
+  }
+
+  Procedure get isSentinelMethod {
+    return _isSentinelMethod ??=
+        index.getTopLevelMember('dart:_internal', 'isSentinel');
+  }
+
   InterfaceType get objectLegacyRawType {
     return _objectLegacyRawType ??= _legacyRawTypes[objectClass] ??=
         new InterfaceType(objectClass, Nullability.legacy, const <DartType>[]);
@@ -1223,6 +1237,11 @@
         index.getMember('dart:_internal', 'LateInitializationErrorImpl', '');
   }
 
+  Constructor get reachabilityErrorConstructor {
+    return _reachabilityErrorConstructor ??=
+        index.getMember('dart:_internal', 'ReachabilityError', '');
+  }
+
   InterfaceType bottomInterfaceType(Class klass, Nullability nullability) {
     InterfaceType result = _bottomInterfaceTypes[klass];
     if (result == null) {
diff --git a/pkg/kernel/lib/default_language_version.dart b/pkg/kernel/lib/default_language_version.dart
index 6b7b18c..eb90980 100644
--- a/pkg/kernel/lib/default_language_version.dart
+++ b/pkg/kernel/lib/default_language_version.dart
@@ -9,4 +9,4 @@
 
 import "ast.dart";
 
-Version defaultLanguageVersion = const Version(2, 10);
+Version defaultLanguageVersion = const Version(2, 11);
diff --git a/pkg/kernel/lib/error_formatter.dart b/pkg/kernel/lib/error_formatter.dart
index 56f4a9f..7bb8974 100644
--- a/pkg/kernel/lib/error_formatter.dart
+++ b/pkg/kernel/lib/error_formatter.dart
@@ -65,7 +65,7 @@
       final parent = context.parent;
       final parentName =
           parent is Class ? parent.name : (parent as Library).name;
-      name = "${parentName}::${context.name.name}";
+      name = "${parentName}::${context.name.text}";
     } else {
       final field = context as Field;
       if (where is Field) {
diff --git a/pkg/kernel/lib/kernel.dart b/pkg/kernel/lib/kernel.dart
index d93c688..8504ef3 100644
--- a/pkg/kernel/lib/kernel.dart
+++ b/pkg/kernel/lib/kernel.dart
@@ -16,7 +16,6 @@
 import 'ast.dart';
 import 'binary/ast_to_binary.dart';
 import 'binary/ast_from_binary.dart';
-import 'dart:async';
 import 'dart:io';
 import 'text/ast_to_text.dart';
 
diff --git a/pkg/kernel/lib/library_index.dart b/pkg/kernel/lib/library_index.dart
index 94db880..8dbb8ee 100644
--- a/pkg/kernel/lib/library_index.dart
+++ b/pkg/kernel/lib/library_index.dart
@@ -220,10 +220,10 @@
 
   String getDisambiguatedName(Member member) {
     if (member is Procedure) {
-      if (member.isGetter) return LibraryIndex.getterPrefix + member.name.name;
-      if (member.isSetter) return LibraryIndex.setterPrefix + member.name.name;
+      if (member.isGetter) return LibraryIndex.getterPrefix + member.name.text;
+      if (member.isSetter) return LibraryIndex.setterPrefix + member.name.text;
     }
-    return member.name.name;
+    return member.name.text;
   }
 
   void addMember(Member member) {
@@ -238,12 +238,12 @@
   String getDisambiguatedExtensionName(
       ExtensionMemberDescriptor extensionMember) {
     if (extensionMember.kind == ExtensionMemberKind.TearOff)
-      return LibraryIndex.tearoffPrefix + extensionMember.name.name;
+      return LibraryIndex.tearoffPrefix + extensionMember.name.text;
     if (extensionMember.kind == ExtensionMemberKind.Getter)
-      return LibraryIndex.getterPrefix + extensionMember.name.name;
+      return LibraryIndex.getterPrefix + extensionMember.name.text;
     if (extensionMember.kind == ExtensionMemberKind.Setter)
-      return LibraryIndex.setterPrefix + extensionMember.name.name;
-    return extensionMember.name.name;
+      return LibraryIndex.setterPrefix + extensionMember.name.text;
+    return extensionMember.name.text;
   }
 
   void addExtensionMember(ExtensionMemberDescriptor extensionMember) {
diff --git a/pkg/kernel/lib/naive_type_checker.dart b/pkg/kernel/lib/naive_type_checker.dart
index ef93768..1178a0c 100644
--- a/pkg/kernel/lib/naive_type_checker.dart
+++ b/pkg/kernel/lib/naive_type_checker.dart
@@ -272,7 +272,7 @@
     // Permit any invocation on Function type.
     if (receiver == environment.coreTypes.functionLegacyRawType &&
         where is MethodInvocation &&
-        where.name.name == 'call') {
+        where.name.text == 'call') {
       return;
     }
 
diff --git a/pkg/kernel/lib/reference_from_index.dart b/pkg/kernel/lib/reference_from_index.dart
index a2a5f77..709fbb5 100644
--- a/pkg/kernel/lib/reference_from_index.dart
+++ b/pkg/kernel/lib/reference_from_index.dart
@@ -48,14 +48,14 @@
     for (int i = 0; i < library.procedures.length; i++) {
       Procedure procedure = library.procedures[i];
       if (procedure.isSetter) {
-        _proceduresSetters[procedure.name.name] = procedure;
+        _proceduresSetters[procedure.name.text] = procedure;
       } else {
-        _proceduresNotSetters[procedure.name.name] = procedure;
+        _proceduresNotSetters[procedure.name.text] = procedure;
       }
     }
     for (int i = 0; i < library.fields.length; i++) {
       Field field = library.fields[i];
-      _fields[field.name.name] = field;
+      _fields[field.name.text] = field;
     }
   }
 
@@ -80,19 +80,19 @@
   IndexedClass._(Class c) {
     for (int i = 0; i < c.constructors.length; i++) {
       Constructor constructor = c.constructors[i];
-      _constructors[constructor.name.name] = constructor;
+      _constructors[constructor.name.text] = constructor;
     }
     for (int i = 0; i < c.procedures.length; i++) {
       Procedure procedure = c.procedures[i];
       if (procedure.isSetter) {
-        _proceduresSetters[procedure.name.name] = procedure;
+        _proceduresSetters[procedure.name.text] = procedure;
       } else {
-        _proceduresNotSetters[procedure.name.name] = procedure;
+        _proceduresNotSetters[procedure.name.text] = procedure;
       }
     }
     for (int i = 0; i < c.fields.length; i++) {
       Field field = c.fields[i];
-      _fields[field.name.name] = field;
+      _fields[field.name.text] = field;
     }
   }
 
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 2597bba..3bbef8a 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -376,7 +376,8 @@
   if (!allowSuperBounded) return result;
 
   result = null;
-  type = convertSuperBoundedToRegularBounded(typeEnvironment, type, bottomType);
+  type = convertSuperBoundedToRegularBounded(
+      library, typeEnvironment, type, bottomType);
   List<DartType> argumentsToReport = arguments.toList();
   if (type is InterfaceType) {
     variables = type.classNode.typeParameters;
@@ -483,13 +484,16 @@
 /// Replaces all covariant occurrences of `dynamic`, `Object`, and `void` with
 /// [BottomType] and all contravariant occurrences of `Null` and [BottomType]
 /// with `Object`.
-DartType convertSuperBoundedToRegularBounded(
+DartType convertSuperBoundedToRegularBounded(Library clientLibrary,
     TypeEnvironment typeEnvironment, DartType type, DartType bottomType,
     {bool isCovariant = true}) {
-  if ((type is DynamicType ||
+  bool isTop = clientLibrary.isNonNullableByDefault
+      ? typeEnvironment.coreTypes.isTop(type)
+      : type is DynamicType ||
           type is VoidType ||
-          isObject(typeEnvironment, type)) &&
-      isCovariant) {
+          type is InterfaceType &&
+              type.classNode == typeEnvironment.coreTypes.objectClass;
+  if (isTop && isCovariant) {
     return bottomType;
   } else if ((type == bottomType || type is BottomType) && !isCovariant) {
     return typeEnvironment.coreTypes.objectLegacyRawType;
@@ -498,7 +502,7 @@
         new List<DartType>(type.typeArguments.length);
     for (int i = 0; i < replacedTypeArguments.length; i++) {
       replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-          typeEnvironment, type.typeArguments[i], bottomType,
+          clientLibrary, typeEnvironment, type.typeArguments[i], bottomType,
           isCovariant: isCovariant);
     }
     return new InterfaceType(
@@ -508,20 +512,23 @@
         new List<DartType>(type.typeArguments.length);
     for (int i = 0; i < replacedTypeArguments.length; i++) {
       replacedTypeArguments[i] = convertSuperBoundedToRegularBounded(
-          typeEnvironment, type.typeArguments[i], bottomType,
+          clientLibrary, typeEnvironment, type.typeArguments[i], bottomType,
           isCovariant: isCovariant);
     }
     return new TypedefType(
         type.typedefNode, type.nullability, replacedTypeArguments);
   } else if (type is FunctionType) {
     var replacedReturnType = convertSuperBoundedToRegularBounded(
-        typeEnvironment, type.returnType, bottomType,
+        clientLibrary, typeEnvironment, type.returnType, bottomType,
         isCovariant: isCovariant);
     var replacedPositionalParameters =
         new List<DartType>(type.positionalParameters.length);
     for (int i = 0; i < replacedPositionalParameters.length; i++) {
       replacedPositionalParameters[i] = convertSuperBoundedToRegularBounded(
-          typeEnvironment, type.positionalParameters[i], bottomType,
+          clientLibrary,
+          typeEnvironment,
+          type.positionalParameters[i],
+          bottomType,
           isCovariant: !isCovariant);
     }
     var replacedNamedParameters =
@@ -529,8 +536,8 @@
     for (int i = 0; i < replacedNamedParameters.length; i++) {
       replacedNamedParameters[i] = new NamedType(
           type.namedParameters[i].name,
-          convertSuperBoundedToRegularBounded(
-              typeEnvironment, type.namedParameters[i].type, bottomType,
+          convertSuperBoundedToRegularBounded(clientLibrary, typeEnvironment,
+              type.namedParameters[i].type, bottomType,
               isCovariant: !isCovariant));
     }
     return new FunctionType(
@@ -542,17 +549,12 @@
   } else if (type is FutureOrType) {
     return new FutureOrType(
         convertSuperBoundedToRegularBounded(
-            typeEnvironment, type.typeArgument, bottomType),
+            clientLibrary, typeEnvironment, type.typeArgument, bottomType),
         type.declaredNullability);
   }
   return type;
 }
 
-bool isObject(TypeEnvironment typeEnvironment, DartType type) {
-  return type is InterfaceType &&
-      type.classNode == typeEnvironment.coreTypes.objectClass;
-}
-
 int computeVariance(TypeParameter typeParameter, DartType type,
     {Map<TypeParameter, Map<DartType, int>> computedVariances}) {
   computedVariances ??= new Map<TypeParameter, Map<DartType, int>>.identity();
diff --git a/pkg/kernel/lib/src/legacy_erasure.dart b/pkg/kernel/lib/src/legacy_erasure.dart
index b7fa3e5..44a5d3a 100644
--- a/pkg/kernel/lib/src/legacy_erasure.dart
+++ b/pkg/kernel/lib/src/legacy_erasure.dart
@@ -56,7 +56,7 @@
   _LegacyErasure(this.coreTypes);
 
   Nullability visitNullability(DartType node) {
-    if (node.nullability != Nullability.legacy) {
+    if (node.declaredNullability != Nullability.legacy) {
       return Nullability.legacy;
     }
     return null;
diff --git a/pkg/kernel/lib/src/standard_bounds.dart b/pkg/kernel/lib/src/standard_bounds.dart
index e57f264..2fb3a96 100644
--- a/pkg/kernel/lib/src/standard_bounds.dart
+++ b/pkg/kernel/lib/src/standard_bounds.dart
@@ -396,17 +396,19 @@
     // without using the nullability of the outermost type. The result uses
     // [intersectNullabilities] to compute the resulting type if the subtype
     // relation is established.
-    DartType nonNullableType1 =
-        type1.withDeclaredNullability(Nullability.nonNullable);
-    DartType nonNullableType2 =
-        type2.withDeclaredNullability(Nullability.nonNullable);
-    if (isSubtypeOf(nonNullableType1, nonNullableType2,
-        SubtypeCheckMode.withNullabilities)) {
+    DartType typeWithoutNullabilityMarker1 =
+        computeTypeWithoutNullabilityMarker(type1, clientLibrary,
+            nullType: coreTypes.nullType);
+    DartType typeWithoutNullabilityMarker2 =
+        computeTypeWithoutNullabilityMarker(type2, clientLibrary,
+            nullType: coreTypes.nullType);
+    if (isSubtypeOf(typeWithoutNullabilityMarker1,
+        typeWithoutNullabilityMarker2, SubtypeCheckMode.withNullabilities)) {
       return type1.withDeclaredNullability(intersectNullabilities(
           type1.declaredNullability, type2.declaredNullability));
     }
-    if (isSubtypeOf(nonNullableType2, nonNullableType1,
-        SubtypeCheckMode.withNullabilities)) {
+    if (isSubtypeOf(typeWithoutNullabilityMarker2,
+        typeWithoutNullabilityMarker1, SubtypeCheckMode.withNullabilities)) {
       return type2.withDeclaredNullability(intersectNullabilities(
           type1.declaredNullability, type2.declaredNullability));
     }
@@ -710,9 +712,9 @@
             type1.declaredNullability, type2.declaredNullability));
       }
 
-      // UP(T Function<...>(...), T2) = Object
-      return coreTypes.objectRawType(uniteNullabilities(
-          type1.declaredNullability, type2.declaredNullability));
+      // UP(T Function<...>(...), T2) = UP(Object, T2)
+      return _getNullabilityAwareStandardUpperBound(
+          coreTypes.objectNonNullableRawType, type2, clientLibrary);
     } else if (type2 is FunctionType) {
       if (type1 is InterfaceType &&
           type1.classNode == coreTypes.functionClass) {
@@ -721,25 +723,42 @@
             type1.declaredNullability, type2.declaredNullability));
       }
 
-      // UP(T1, T Function<...>(...)) = Object
-      return coreTypes.objectRawType(uniteNullabilities(
-          type1.declaredNullability, type2.declaredNullability));
+      // UP(T1, T Function<...>(...)) = UP(T1, Object)
+      return _getNullabilityAwareStandardUpperBound(
+          type1, coreTypes.objectNonNullableRawType, clientLibrary);
     }
 
-    if (type1 is FutureOrType || type2 is FutureOrType) {
-      if (isSubtypeOf(type1, type2, SubtypeCheckMode.withNullabilities)) {
-        return type2;
+    // UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (type1 is FutureOrType) {
+      DartType t1 = type1.typeArgument;
+      DartType t2;
+      if (type2 is InterfaceType && type2.classNode == coreTypes.futureClass) {
+        t2 = type2.typeArguments.single;
+      } else if (type2 is FutureOrType) {
+        t2 = type2.typeArgument;
+      } else {
+        t2 = type2;
       }
-      if (isSubtypeOf(type2, type1, SubtypeCheckMode.withNullabilities)) {
-        return type1;
+      return new FutureOrType(
+          getStandardUpperBound(t1, t2, clientLibrary),
+          uniteNullabilities(
+              type1.declaredNullability, type2.declaredNullability));
+    } else if (type2 is FutureOrType) {
+      DartType t2 = type2.typeArgument;
+      DartType t1;
+      if (type1 is InterfaceType && type1.classNode == coreTypes.futureClass) {
+        t1 = type1.typeArguments.single;
+      } else {
+        t1 = type1;
       }
-      if (type1 is FutureOrType && type2 is FutureOrType) {
-        return new FutureOrType(
-            getStandardUpperBound(
-                type1.typeArgument, type2.typeArgument, clientLibrary),
-            uniteNullabilities(
-                type1.declaredNullability, type2.declaredNullability));
-      }
+      return new FutureOrType(
+          getStandardUpperBound(t1, t2, clientLibrary),
+          uniteNullabilities(
+              type1.declaredNullability, type2.declaredNullability));
     }
 
     // UP(T1, T2) = T2 if T1 <: T2
@@ -753,21 +772,23 @@
     // T1 <: T2 without using the nullability of the outermost type. The result
     // uses [uniteNullabilities] to compute the resulting type if the subtype
     // relation is established.
-    InterfaceType nonNonNullableType1 =
-        type1.withDeclaredNullability(Nullability.nonNullable);
-    InterfaceType nonNonNullableType2 =
-        type2.withDeclaredNullability(Nullability.nonNullable);
+    InterfaceType typeWithoutNullabilityMarker1 =
+        computeTypeWithoutNullabilityMarker(type1, clientLibrary,
+            nullType: coreTypes.nullType);
+    InterfaceType typeWithoutNullabilityMarker2 =
+        computeTypeWithoutNullabilityMarker(type2, clientLibrary,
+            nullType: coreTypes.nullType);
 
-    if (isSubtypeOf(nonNonNullableType1, nonNonNullableType2,
-        SubtypeCheckMode.withNullabilities)) {
+    if (isSubtypeOf(typeWithoutNullabilityMarker1,
+        typeWithoutNullabilityMarker2, SubtypeCheckMode.withNullabilities)) {
       return type2.withDeclaredNullability(
           uniteNullabilities(type1.nullability, type2.nullability));
     }
 
     // UP(T1, T2) = T1 if T2 <: T1
     //   Note that both types must be class types at this point.
-    if (isSubtypeOf(nonNonNullableType2, nonNonNullableType1,
-        SubtypeCheckMode.withNullabilities)) {
+    if (isSubtypeOf(typeWithoutNullabilityMarker2,
+        typeWithoutNullabilityMarker1, SubtypeCheckMode.withNullabilities)) {
       return type1.withDeclaredNullability(uniteNullabilities(
           type1.declaredNullability, type2.declaredNullability));
     }
@@ -1148,7 +1169,9 @@
       // UP(X1 extends B1, T2) =
       //   T2 if X1 <: T2
       //   otherwise X1 if T2 <: X1
-      //   otherwise UP(B1[Object/X1], T2)
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1,
+      //     as defined in [inference.md].
       if (isSubtypeOf(type1, type2, SubtypeCheckMode.withNullabilities)) {
         return type2.withDeclaredNullability(uniteNullabilities(
             type1.declaredNullability, type2.declaredNullability));
@@ -1157,20 +1180,28 @@
         return type1.withDeclaredNullability(uniteNullabilities(
             type1.declaredNullability, type2.declaredNullability));
       }
-      Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
-        type1.parameter: coreTypes.objectNonNullableRawType
-      };
+      NullabilityAwareTypeVariableEliminator eliminator =
+          new NullabilityAwareTypeVariableEliminator(
+              eliminationTargets: <TypeParameter>{type1.parameter},
+              bottomType: const NeverType(Nullability.nonNullable),
+              topType: coreTypes.objectNullableRawType,
+              topFunctionType: coreTypes.functionNonNullableRawType,
+              unhandledTypeHandler: (type, recursor) => false);
       return _getNullabilityAwareStandardUpperBound(
-              substitute(type1.parameter.bound, substitution),
+              eliminator.eliminateToGreatest(type1.parameter.bound),
               type2,
               clientLibrary)
           .withDeclaredNullability(uniteNullabilities(
-              type1.declaredNullability, type2.declaredNullability));
+              type1.declaredNullability,
+              uniteNullabilities(type1.parameter.bound.declaredNullability,
+                  type2.declaredNullability)));
     } else {
       // UP(X1 & B1, T2) =
       //   T2 if X1 <: T2
       //   otherwise X1 if T2 <: X1
-      //   otherwise UP(B1[Object/X1], T2)
+      //   otherwise UP(B1a, T2)
+      //     where B1a is the greatest closure of B1 with respect to X1,
+      //     as defined in [inference.md].
       DartType demoted =
           new TypeParameterType(type1.parameter, type1.declaredNullability);
       if (isSubtypeOf(demoted, type2, SubtypeCheckMode.withNullabilities)) {
@@ -1181,15 +1212,20 @@
         return demoted.withDeclaredNullability(uniteNullabilities(
             type1.declaredNullability, type2.declaredNullability));
       }
-      Map<TypeParameter, DartType> substitution = <TypeParameter, DartType>{
-        type1.parameter: coreTypes.objectNonNullableRawType
-      };
+      NullabilityAwareTypeVariableEliminator eliminator =
+          new NullabilityAwareTypeVariableEliminator(
+              eliminationTargets: <TypeParameter>{type1.parameter},
+              bottomType: const NeverType(Nullability.nonNullable),
+              topType: coreTypes.objectNullableRawType,
+              topFunctionType: coreTypes.functionNonNullableRawType,
+              unhandledTypeHandler: (type, recursor) => false);
       return _getNullabilityAwareStandardUpperBound(
-              substitute(type1.promotedBound, substitution),
+              eliminator.eliminateToGreatest(type1.promotedBound),
               type2,
               clientLibrary)
           .withDeclaredNullability(uniteNullabilities(
-              type1.declaredNullability, type2.declaredNullability));
+              type1.promotedBound.declaredNullability,
+              type2.declaredNullability));
     }
   }
 
@@ -1270,20 +1306,37 @@
           type1, type2, clientLibrary);
     }
 
-    if (type1 is FutureOrType || type2 is FutureOrType) {
-      if (isSubtypeOf(type1, type2, SubtypeCheckMode.ignoringNullabilities)) {
-        return type2;
+    // UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
+    // UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
+    if (type1 is FutureOrType) {
+      DartType t1 = type1.typeArgument;
+      DartType t2;
+      if (type2 is InterfaceType && type2.classNode == coreTypes.futureClass) {
+        t2 = type2.typeArguments.single;
+      } else if (type2 is FutureOrType) {
+        t2 = type2.typeArgument;
+      } else {
+        t2 = type2;
       }
-      if (isSubtypeOf(type2, type1, SubtypeCheckMode.ignoringNullabilities)) {
-        return type1;
+      return new FutureOrType(
+          getStandardUpperBound(t1, t2, clientLibrary),
+          uniteNullabilities(
+              type1.declaredNullability, type2.declaredNullability));
+    } else if (type2 is FutureOrType) {
+      DartType t2 = type2.typeArgument;
+      DartType t1;
+      if (type1 is InterfaceType && type1.classNode == coreTypes.futureClass) {
+        t1 = type1.typeArguments.single;
+      } else {
+        t1 = type1;
       }
-      if (type1 is FutureOrType && type2 is FutureOrType) {
-        return new FutureOrType(
-            getStandardUpperBound(
-                type1.typeArgument, type2.typeArgument, clientLibrary),
-            uniteNullabilities(
-                type1.declaredNullability, type2.declaredNullability));
-      }
+      return new FutureOrType(
+          getStandardUpperBound(t1, t2, clientLibrary),
+          uniteNullabilities(
+              type1.declaredNullability, type2.declaredNullability));
     }
 
     if (type1 is InvalidType || type2 is InvalidType) {
diff --git a/pkg/kernel/lib/src/text_util.dart b/pkg/kernel/lib/src/text_util.dart
index c04deb8..9fe573f 100644
--- a/pkg/kernel/lib/src/text_util.dart
+++ b/pkg/kernel/lib/src/text_util.dart
@@ -22,9 +22,9 @@
   if (node == null) {
     return 'null';
   } else if (node.library != null && includeLibraryName) {
-    return '${libraryNameToString(node.library)}::${node.name}';
+    return '${libraryNameToString(node.library)}::${node.text}';
   } else {
-    return node.name;
+    return node.text;
   }
 }
 
@@ -205,7 +205,7 @@
 }
 
 String memberNameToString(Member node) {
-  return node.name?.name ??
+  return node.name?.text ??
       "null-named member ${node.runtimeType} ${node.hashCode}";
 }
 
diff --git a/pkg/kernel/lib/src/types.dart b/pkg/kernel/lib/src/types.dart
index 88e6940..2ab1891 100644
--- a/pkg/kernel/lib/src/types.dart
+++ b/pkg/kernel/lib/src/types.dart
@@ -482,9 +482,9 @@
         return const IsSubtypeOf.never();
       }
     }
-    List<NamedType> sNamed = s.namedParameters;
-    List<NamedType> tNamed = t.namedParameters;
-    if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
+    List<NamedType> sNamedParameters = s.namedParameters;
+    List<NamedType> tNamedParameters = t.namedParameters;
+    if (sNamedParameters.isNotEmpty || tNamedParameters.isNotEmpty) {
       // Rule 16, the number of positional parameters must be the same.
       if (sPositional.length != tPositional.length) {
         return const IsSubtypeOf.never();
@@ -497,17 +497,46 @@
       // [s]. Also, for the intersection, the type of the parameter of [t] must
       // be a subtype of the type of the parameter of [s].
       int sCount = 0;
-      for (int tCount = 0; tCount < tNamed.length; tCount++) {
-        String name = tNamed[tCount].name;
-        for (; sCount < sNamed.length; sCount++) {
-          if (sNamed[sCount].name == name) break;
+      for (int tCount = 0; tCount < tNamedParameters.length; tCount++) {
+        NamedType tNamedParameter = tNamedParameters[tCount];
+        String name = tNamedParameter.name;
+        NamedType sNamedParameter;
+        for (; sCount < sNamedParameters.length; sCount++) {
+          sNamedParameter = sNamedParameters[sCount];
+          if (sNamedParameter.name == name) {
+            break;
+          } else if (sNamedParameter.isRequired) {
+            /// From the NNBD spec: For each j such that r0j is required, then
+            /// there exists an i in n+1...q such that xj = yi, and r1i is
+            /// required
+            result =
+                result.and(const IsSubtypeOf.onlyIfIgnoringNullabilities());
+          }
         }
-        if (sCount == sNamed.length) return const IsSubtypeOf.never();
+        if (sCount == sNamedParameters.length) return const IsSubtypeOf.never();
+        // Increment [sCount] so we don't check [sNamedParameter] again in the
+        // loop above or below and assume it is an extra (unmatched) parameter.
+        sCount++;
         result = result.and(types.performNullabilityAwareSubtypeCheck(
-            tNamed[tCount].type, sNamed[sCount].type));
+            tNamedParameter.type, sNamedParameter.type));
         if (!result.isSubtypeWhenIgnoringNullabilities()) {
           return const IsSubtypeOf.never();
         }
+
+        /// From the NNBD spec: For each j such that r0j is required, then there
+        /// exists an i in n+1...q such that xj = yi, and r1i is required
+        if (sNamedParameter.isRequired && !tNamedParameter.isRequired) {
+          result = result.and(const IsSubtypeOf.onlyIfIgnoringNullabilities());
+        }
+      }
+      for (; sCount < sNamedParameters.length; sCount++) {
+        NamedType sNamedParameter = sNamedParameters[sCount];
+        if (sNamedParameter.isRequired) {
+          /// From the NNBD spec: For each j such that r0j is required, then
+          /// there exists an i in n+1...q such that xj = yi, and r1i is
+          /// required
+          result = result.and(const IsSubtypeOf.onlyIfIgnoringNullabilities());
+        }
       }
     }
     return result.and(new IsSubtypeOf.basedSolelyOnNullabilities(s, t));
@@ -899,7 +928,7 @@
         return const IsSubtypeOf.always();
       }
       if (t.nullability == Nullability.nonNullable) {
-        return const IsSubtypeOf.never();
+        return const IsSubtypeOf.onlyIfIgnoringNullabilities();
       }
       throw new StateError(
           "Unexpected nullability '$t.nullability' of type Never");
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 1aa2f44..93ea3c9 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -14,6 +14,7 @@
 class TargetFlags {
   final bool trackWidgetCreation;
   final bool forceLateLoweringForTesting;
+  final bool forceLateLoweringSentinelForTesting;
   final bool forceStaticFieldLoweringForTesting;
   final bool forceNoExplicitGetterCallsForTesting;
   final bool enableNullSafety;
@@ -21,6 +22,7 @@
   const TargetFlags(
       {this.trackWidgetCreation = false,
       this.forceLateLoweringForTesting = false,
+      this.forceLateLoweringSentinelForTesting = false,
       this.forceStaticFieldLoweringForTesting = false,
       this.forceNoExplicitGetterCallsForTesting = false,
       this.enableNullSafety = false});
@@ -30,6 +32,8 @@
     return other is TargetFlags &&
         trackWidgetCreation == other.trackWidgetCreation &&
         forceLateLoweringForTesting == other.forceLateLoweringForTesting &&
+        forceLateLoweringSentinelForTesting ==
+            other.forceLateLoweringSentinelForTesting &&
         forceStaticFieldLoweringForTesting ==
             other.forceStaticFieldLoweringForTesting &&
         forceNoExplicitGetterCallsForTesting ==
@@ -43,6 +47,8 @@
     hash = 0x3fffffff &
         (hash * 31 + (hash ^ forceLateLoweringForTesting.hashCode));
     hash = 0x3fffffff &
+        (hash * 31 + (hash ^ forceLateLoweringSentinelForTesting.hashCode));
+    hash = 0x3fffffff &
         (hash * 31 + (hash ^ forceStaticFieldLoweringForTesting.hashCode));
     hash = 0x3fffffff &
         (hash * 31 + (hash ^ forceNoExplicitGetterCallsForTesting.hashCode));
@@ -282,6 +288,13 @@
   /// details.
   bool get supportsLateFields;
 
+  /// If `true`, the backend supports creation and checking of a sentinel value
+  /// for uninitialized late fields and variables through the `createSentinel`
+  /// and `isSentinel` methods in `dart:_internal`.
+  ///
+  /// If `true` this is used when [supportsLateFields] is `false`.
+  bool get supportsLateLoweringSentinel;
+
   /// Whether static fields with initializers in nnbd libraries should be
   /// encoded using the late field lowering.
   bool get useStaticFieldLowering;
@@ -349,6 +362,10 @@
   bool get supportsLateFields => !flags.forceLateLoweringForTesting;
 
   @override
+  bool get supportsLateLoweringSentinel =>
+      flags.forceLateLoweringSentinelForTesting;
+
+  @override
   bool get useStaticFieldLowering => flags.forceStaticFieldLoweringForTesting;
 
   @override
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index 71f9fef..3e253af 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -119,7 +119,7 @@
 }
 
 String debugMemberName(Member node) {
-  return node.name?.name ?? globalDebuggingNames.nameMember(node);
+  return node.name?.text ?? globalDebuggingNames.nameMember(node);
 }
 
 String debugQualifiedMemberName(Member node) {
@@ -341,14 +341,14 @@
   static final Name emptyName = new Name(emptyNameString);
 
   Name getMemberName(Member node) {
-    if (node.name?.name == '') return emptyName;
+    if (node.name?.text == '') return emptyName;
     if (node.name != null) return node.name;
     return new Name(syntheticNames.nameMember(node));
   }
 
   String getMemberReference(Member node) {
     if (node == null) return '<No Member>';
-    String name = getMemberName(node).name;
+    String name = getMemberName(node).text;
     if (node.parent is Class) {
       String className = getClassReference(node.parent);
       return '$className::$name';
@@ -481,11 +481,11 @@
       } else if (node is Field) {
         Library nodeLibrary = node.enclosingLibrary;
         String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
-        write(prefix + '::' + node.name.name);
+        write(prefix + '::' + node.name.text);
       } else if (node is Procedure) {
         Library nodeLibrary = node.enclosingLibrary;
         String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
-        write(prefix + '::' + node.name.name);
+        write(prefix + '::' + node.name.text);
       } else if (node is Typedef) {
         Library nodeLibrary = node.enclosingLibrary;
         String prefix = syntheticNames.nameLibraryPrefix(nodeLibrary);
@@ -701,10 +701,10 @@
   }
 
   void writeName(Name name) {
-    if (name?.name == '') {
+    if (name?.text == '') {
       writeWord(emptyNameString);
     } else {
-      writeWord(name?.name ?? '<anonymous>'); // TODO: write library name
+      writeWord(name?.text ?? '<anonymous>'); // TODO: write library name
     }
   }
 
@@ -1345,14 +1345,6 @@
     writeNode(node.arguments);
   }
 
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.{=');
-    writeMemberReferenceFromReference(node.targetReference);
-    writeSymbol('}');
-    writeNode(node.arguments);
-  }
-
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     writeWord('super');
     writeSymbol('.');
@@ -1383,9 +1375,10 @@
   }
 
   visitLogicalExpression(LogicalExpression node) {
-    int precedence = Precedence.binaryPrecedence[node.operator];
+    int precedence = Precedence
+        .binaryPrecedence[logicalExpressionOperatorToString(node.operatorEnum)];
     writeExpression(node.left, precedence);
-    writeSpaced(node.operator);
+    writeSpaced(logicalExpressionOperatorToString(node.operatorEnum));
     writeExpression(node.right, precedence + 1);
   }
 
@@ -1458,7 +1451,7 @@
       if (!first) {
         writeComma();
       }
-      writeWord('${fieldRef.asField.name.name}');
+      writeWord('${fieldRef.asField.name.text}');
       writeSymbol(':');
       writeExpression(value);
       first = false;
@@ -1771,22 +1764,6 @@
     writeExpression(node.value);
   }
 
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.{=');
-    writeMemberReferenceFromReference(node.targetReference);
-    writeSymbol('}');
-  }
-
-  visitDirectPropertySet(DirectPropertySet node) {
-    writeExpression(node.receiver, Precedence.PRIMARY);
-    writeSymbol('.{=');
-    writeMemberReferenceFromReference(node.targetReference);
-    writeSymbol('}');
-    writeSpaced('=');
-    writeExpression(node.value);
-  }
-
   visitStaticGet(StaticGet node) {
     writeMemberReferenceFromReference(node.targetReference);
   }
@@ -2366,7 +2343,7 @@
     writeList(node.fieldValues.entries,
         (core.MapEntry<Reference, Constant> entry) {
       if (entry.key.node != null) {
-        writeWord('${entry.key.asField.name.name}');
+        writeWord('${entry.key.asField.name.text}');
       } else {
         writeWord('${entry.key.canonicalName.name}');
       }
@@ -2478,13 +2455,12 @@
   int visitInvalidExpression(InvalidExpression node) => CALLEE;
   int visitMethodInvocation(MethodInvocation node) => CALLEE;
   int visitSuperMethodInvocation(SuperMethodInvocation node) => CALLEE;
-  int visitDirectMethodInvocation(DirectMethodInvocation node) => CALLEE;
   int visitStaticInvocation(StaticInvocation node) => CALLEE;
   int visitConstructorInvocation(ConstructorInvocation node) => CALLEE;
   int visitNot(Not node) => PREFIX;
   int visitNullCheck(NullCheck node) => PRIMARY;
   int visitLogicalExpression(LogicalExpression node) =>
-      binaryPrecedence[node.operator];
+      binaryPrecedence[logicalExpressionOperatorToString(node.operatorEnum)];
   int visitConditionalExpression(ConditionalExpression node) => CONDITIONAL;
   int visitStringConcatenation(StringConcatenation node) => PRIMARY;
   int visitIsExpression(IsExpression node) => RELATIONAL;
@@ -2510,8 +2486,6 @@
   int visitPropertySet(PropertySet node) => EXPRESSION;
   int visitSuperPropertyGet(SuperPropertyGet node) => PRIMARY;
   int visitSuperPropertySet(SuperPropertySet node) => EXPRESSION;
-  int visitDirectPropertyGet(DirectPropertyGet node) => PRIMARY;
-  int visitDirectPropertySet(DirectPropertySet node) => EXPRESSION;
   int visitStaticGet(StaticGet node) => PRIMARY;
   int visitStaticSet(StaticSet node) => EXPRESSION;
   int visitLet(Let node) => EXPRESSION;
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 59d13a0..e633d04 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -21,10 +21,10 @@
 }
 
 TextSerializer<Name> publicName =
-    Wrapped((w) => w.name, (u) => Name(u), const DartString());
+    Wrapped((w) => w.text, (u) => Name(u), const DartString());
 
 TextSerializer<Name> privateName = Wrapped(
-    (w) => Tuple2(w.name, w.library.canonicalName),
+    (w) => Tuple2(w.text, w.library.canonicalName),
     (u) => Name.byReference(u.first, u.second.getReference()),
     Tuple2Serializer(DartString(), CanonicalNameSerializer()));
 
@@ -45,7 +45,7 @@
   String visitInvalidExpression(InvalidExpression _) => "invalid";
   String visitNot(Not _) => "not";
   String visitLogicalExpression(LogicalExpression expression) {
-    return expression.operator;
+    return logicalExpressionOperatorToString(expression.operatorEnum);
   }
 
   String visitStringConcatenation(StringConcatenation _) => "concat";
@@ -83,16 +83,10 @@
   String visitVariableSet(VariableSet _) => "set-var";
   String visitStaticGet(StaticGet _) => "get-static";
   String visitStaticSet(StaticSet _) => "set-static";
-  String visitDirectPropertyGet(DirectPropertyGet _) => "get-direct-prop";
-  String visitDirectPropertySet(DirectPropertySet _) => "set-direct-prop";
   String visitStaticInvocation(StaticInvocation expression) {
     return expression.isConst ? "invoke-const-static" : "invoke-static";
   }
 
-  String visitDirectMethodInvocation(DirectMethodInvocation _) {
-    return "invoke-direct-method";
-  }
-
   String visitConstructorInvocation(ConstructorInvocation expression) {
     return expression.isConst
         ? "invoke-const-constructor"
@@ -143,7 +137,8 @@
 }
 
 LogicalExpression wrapLogicalAnd(Tuple2<Expression, Expression> tuple) {
-  return new LogicalExpression(tuple.first, '&&', tuple.second);
+  return new LogicalExpression(
+      tuple.first, LogicalExpressionOperator.AND, tuple.second);
 }
 
 TextSerializer<LogicalExpression> logicalOrSerializer = new Wrapped(
@@ -152,7 +147,8 @@
     new Tuple2Serializer(expressionSerializer, expressionSerializer));
 
 LogicalExpression wrapLogicalOr(Tuple2<Expression, Expression> tuple) {
-  return new LogicalExpression(tuple.first, '||', tuple.second);
+  return new LogicalExpression(
+      tuple.first, LogicalExpressionOperator.OR, tuple.second);
 }
 
 TextSerializer<StringConcatenation> stringConcatenationSerializer = new Wrapped(
@@ -562,42 +558,6 @@
   return new StaticSet.byReference(tuple.first.getReference(), tuple.second);
 }
 
-TextSerializer<DirectPropertyGet> directPropertyGetSerializer = new Wrapped(
-    unwrapDirectPropertyGet,
-    wrapDirectPropertyGet,
-    new Tuple2Serializer(
-        expressionSerializer, const CanonicalNameSerializer()));
-
-Tuple2<Expression, CanonicalName> unwrapDirectPropertyGet(
-    DirectPropertyGet expression) {
-  return new Tuple2(
-      expression.receiver, expression.targetReference.canonicalName);
-}
-
-DirectPropertyGet wrapDirectPropertyGet(
-    Tuple2<Expression, CanonicalName> tuple) {
-  return new DirectPropertyGet.byReference(
-      tuple.first, tuple.second.getReference());
-}
-
-TextSerializer<DirectPropertySet> directPropertySetSerializer = new Wrapped(
-    unwrapDirectPropertySet,
-    wrapDirectPropertySet,
-    new Tuple3Serializer(expressionSerializer, const CanonicalNameSerializer(),
-        expressionSerializer));
-
-Tuple3<Expression, CanonicalName, Expression> unwrapDirectPropertySet(
-    DirectPropertySet expression) {
-  return new Tuple3(expression.receiver,
-      expression.targetReference.canonicalName, expression.value);
-}
-
-DirectPropertySet wrapDirectPropertySet(
-    Tuple3<Expression, CanonicalName, Expression> tuple) {
-  return new DirectPropertySet.byReference(
-      tuple.first, tuple.second.getReference(), tuple.third);
-}
-
 TextSerializer<StaticInvocation> staticInvocationSerializer = new Wrapped(
     unwrapStaticInvocation,
     wrapStaticInvocation,
@@ -627,25 +587,6 @@
       isConst: true);
 }
 
-TextSerializer<DirectMethodInvocation> directMethodInvocationSerializer =
-    new Wrapped(
-        unwrapDirectMethodInvocation,
-        wrapDirectMethodInvocation,
-        new Tuple3Serializer(expressionSerializer,
-            const CanonicalNameSerializer(), argumentsSerializer));
-
-Tuple3<Expression, CanonicalName, Arguments> unwrapDirectMethodInvocation(
-    DirectMethodInvocation expression) {
-  return new Tuple3(expression.receiver,
-      expression.targetReference.canonicalName, expression.arguments);
-}
-
-DirectMethodInvocation wrapDirectMethodInvocation(
-    Tuple3<Expression, CanonicalName, Arguments> tuple) {
-  return new DirectMethodInvocation.byReference(
-      tuple.first, tuple.second.getReference(), tuple.third);
-}
-
 TextSerializer<ConstructorInvocation> constructorInvocationSerializer =
     new Wrapped(
         unwrapConstructorInvocation,
@@ -2096,11 +2037,8 @@
     "set-var": variableSetSerializer,
     "get-static": staticGetSerializer,
     "set-static": staticSetSerializer,
-    "get-direct-prop": directPropertyGetSerializer,
-    "set-direct-prop": directPropertySetSerializer,
     "invoke-static": staticInvocationSerializer,
     "invoke-const-static": constStaticInvocationSerializer,
-    "invoke-direct-method": directMethodInvocationSerializer,
     "invoke-constructor": constructorInvocationSerializer,
     "invoke-const-constructor": constConstructorInvocationSerializer,
     "fun": functionExpressionSerializer,
diff --git a/pkg/kernel/lib/transformations/async.dart b/pkg/kernel/lib/transformations/async.dart
index 9d5b372..37c9ea9 100644
--- a/pkg/kernel/lib/transformations/async.dart
+++ b/pkg/kernel/lib/transformations/async.dart
@@ -213,7 +213,6 @@
 
   TreeNode visitVariableSet(VariableSet expr) => unary(expr);
   TreeNode visitPropertyGet(PropertyGet expr) => unary(expr);
-  TreeNode visitDirectPropertyGet(DirectPropertyGet expr) => unary(expr);
   TreeNode visitSuperPropertySet(SuperPropertySet expr) => unary(expr);
   TreeNode visitStaticSet(StaticSet expr) => unary(expr);
   TreeNode visitNot(Not expr) => unary(expr);
@@ -228,13 +227,6 @@
     });
   }
 
-  TreeNode visitDirectPropertySet(DirectPropertySet expr) {
-    return transform(expr, () {
-      expr.value = expr.value.accept<TreeNode>(this)..parent = expr;
-      expr.receiver = expr.receiver.accept<TreeNode>(this)..parent = expr;
-    });
-  }
-
   TreeNode visitArguments(Arguments args) {
     for (var named in args.named.reversed) {
       named.value = named.value.accept<TreeNode>(this)..parent = named;
@@ -255,13 +247,6 @@
     });
   }
 
-  TreeNode visitDirectMethodInvocation(DirectMethodInvocation expr) {
-    return transform(expr, () {
-      visitArguments(expr.arguments);
-      expr.receiver = expr.receiver.accept<TreeNode>(this)..parent = expr;
-    });
-  }
-
   TreeNode visitSuperMethodInvocation(SuperMethodInvocation expr) {
     return transform(expr, () {
       visitArguments(expr.arguments);
@@ -351,7 +336,7 @@
         new MethodInvocation(expr.right, new Name('=='),
             new Arguments(<Expression>[new BoolLiteral(true)])))));
     var then, otherwise;
-    if (expr.operator == '&&') {
+    if (expr.operatorEnum == LogicalExpressionOperator.AND) {
       then = rightBody;
       otherwise = null;
     } else {
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index 314803a..8af53bf 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -19,20 +19,14 @@
     CoreTypes coreTypes,
     ClassHierarchy hierarchy,
     List<Library> libraries,
-    ReferenceFromIndex referenceFromIndex,
-    {bool doSuperResolution: true}) {
-  new MixinFullResolution(targetInfo, coreTypes, hierarchy,
-          doSuperResolution: doSuperResolution)
+    ReferenceFromIndex referenceFromIndex) {
+  new MixinFullResolution(targetInfo, coreTypes, hierarchy)
       .transform(libraries, referenceFromIndex);
 }
 
 /// Replaces all mixin applications with regular classes, cloning all fields
 /// and procedures from the mixed-in class, cloning all constructors from the
 /// base class.
-///
-/// When [doSuperResolution] constructor parameter is [true], super calls
-/// (as well as super initializer invocations) are also resolved to their
-/// targets in this pass.
 class MixinFullResolution {
   final Target targetInfo;
   final CoreTypes coreTypes;
@@ -44,13 +38,7 @@
   /// valid anymore.
   ClassHierarchy hierarchy;
 
-  // This enables `super` resolution transformation, which is not compatible
-  // with Dart VM's requirements around incremental compilation and has been
-  // moved to Dart VM itself.
-  final bool doSuperResolution;
-
-  MixinFullResolution(this.targetInfo, this.coreTypes, this.hierarchy,
-      {this.doSuperResolution: true});
+  MixinFullResolution(this.targetInfo, this.coreTypes, this.hierarchy);
 
   /// Transform the given new [libraries].  It is expected that all other
   /// libraries have already been transformed.
@@ -73,22 +61,6 @@
     // We might need to update the class hierarchy.
     hierarchy =
         hierarchy.applyMemberChanges(transformedClasses, findDescendants: true);
-
-    if (!doSuperResolution) {
-      return;
-    }
-    // Resolve all super call expressions and super initializers.
-    for (var library in libraries) {
-      for (var class_ in library.classes) {
-        for (var procedure in class_.procedures) {
-          if (procedure.containsSuperCalls) {
-            new SuperCallResolutionTransformer(
-                    hierarchy, coreTypes, class_.superclass, targetInfo)
-                .visit(procedure);
-          }
-        }
-      }
-    }
   }
 
   transformClass(
@@ -153,7 +125,7 @@
 
     for (var field in class_.mixin.fields) {
       Field clone =
-          cloner.cloneField(field, indexedClass?.lookupField(field.name.name));
+          cloner.cloneField(field, indexedClass?.lookupField(field.name.text));
       Procedure setter = setters[field.name];
       if (setter != null) {
         setters.remove(field.name);
@@ -187,10 +159,10 @@
       Procedure referenceFrom;
       if (procedure.isSetter) {
         referenceFrom =
-            indexedClass?.lookupProcedureSetter(procedure.name.name);
+            indexedClass?.lookupProcedureSetter(procedure.name.text);
       } else {
         referenceFrom =
-            indexedClass?.lookupProcedureNotSetter(procedure.name.name);
+            indexedClass?.lookupProcedureNotSetter(procedure.name.text);
       }
 
       // Linear search for a forwarding stub with the same name.
@@ -252,160 +224,3 @@
     class_.isEliminatedMixin = true;
   }
 }
-
-class SuperCallResolutionTransformer extends Transformer {
-  final ClassHierarchy hierarchy;
-  final CoreTypes coreTypes;
-  final Class lookupClass;
-  final Target targetInfo;
-
-  SuperCallResolutionTransformer(
-      this.hierarchy, this.coreTypes, this.lookupClass, this.targetInfo);
-
-  TreeNode visit(TreeNode node) => node.accept(this);
-
-  visitSuperPropertyGet(SuperPropertyGet node) {
-    Member target = hierarchy.getDispatchTarget(lookupClass, node.name);
-    if (target != null) {
-      return new DirectPropertyGet(new ThisExpression(), target)
-        ..fileOffset = node.fileOffset;
-    } else {
-      return _callNoSuchMethod(node.name.name, new Arguments.empty(), node,
-          isGetter: true, isSuper: true);
-    }
-  }
-
-  visitSuperPropertySet(SuperPropertySet node) {
-    Member target =
-        hierarchy.getDispatchTarget(lookupClass, node.name, setter: true);
-    if (target != null) {
-      return new DirectPropertySet(
-          new ThisExpression(), target, visit(node.value))
-        ..fileOffset = node.fileOffset;
-    } else {
-      // Call has to return right-hand-side.
-      VariableDeclaration rightHandSide =
-          new VariableDeclaration.forValue(visit(node.value));
-      Expression result = _callNoSuchMethod(
-          node.name.name, new Arguments([new VariableGet(rightHandSide)]), node,
-          isSetter: true, isSuper: true);
-      VariableDeclaration call = new VariableDeclaration.forValue(result);
-      return new Let(
-          rightHandSide, new Let(call, new VariableGet(rightHandSide)));
-    }
-  }
-
-  visitSuperMethodInvocation(SuperMethodInvocation node) {
-    Member target = hierarchy.getDispatchTarget(lookupClass, node.name);
-    Arguments visitedArguments = visit(node.arguments);
-    if (target is Procedure &&
-        !target.isAccessor &&
-        _callIsLegal(target.function, visitedArguments)) {
-      return new DirectMethodInvocation(
-          new ThisExpression(), target, visitedArguments)
-        ..fileOffset = node.fileOffset;
-    } else if (target == null || (target is Procedure && !target.isAccessor)) {
-      // Target not found at all, or call was illegal.
-      return _callNoSuchMethod(node.name.name, visitedArguments, node,
-          isSuper: true);
-    } else {
-      return new MethodInvocation(
-          new DirectPropertyGet(new ThisExpression(), target),
-          new Name('call'),
-          visitedArguments)
-        ..fileOffset = node.fileOffset;
-    }
-  }
-
-  /// Create a call to no such method.
-  Expression _callNoSuchMethod(
-      String methodName, Arguments methodArguments, TreeNode node,
-      {isSuper: false, isGetter: false, isSetter: false}) {
-    Member noSuchMethod =
-        hierarchy.getDispatchTarget(lookupClass, new Name("noSuchMethod"));
-    String methodNameUsed = (isGetter)
-        ? "get:$methodName"
-        : (isSetter) ? "set:$methodName=" : methodName;
-    if (noSuchMethod != null &&
-        noSuchMethod.function.positionalParameters.length == 1 &&
-        noSuchMethod.function.namedParameters.isEmpty) {
-      // We have a correct noSuchMethod method.
-      ConstructorInvocation invocation = _createInvocation(
-          methodNameUsed, methodArguments, isSuper, new ThisExpression());
-      return new DirectMethodInvocation(
-          new ThisExpression(), noSuchMethod, new Arguments([invocation]))
-        ..fileOffset = node.fileOffset;
-    } else {
-      // Incorrect noSuchMethod method: Call noSuchMethod on Object
-      // with Invocation of noSuchMethod as the method that did not exist.
-      noSuchMethod = hierarchy.getDispatchTarget(
-          coreTypes.objectClass, new Name("noSuchMethod"));
-      ConstructorInvocation invocation = _createInvocation(
-          methodNameUsed, methodArguments, isSuper, new ThisExpression());
-      ConstructorInvocation invocationPrime = _createInvocation("noSuchMethod",
-          new Arguments([invocation]), false, new ThisExpression());
-      return new DirectMethodInvocation(
-          new ThisExpression(), noSuchMethod, new Arguments([invocationPrime]))
-        ..fileOffset = node.fileOffset;
-    }
-  }
-
-  /// Creates an "new _InvocationMirror(...)" invocation.
-  ConstructorInvocation _createInvocation(String methodName,
-      Arguments callArguments, bool isSuperInvocation, Expression receiver) {
-    return targetInfo.instantiateInvocation(
-        coreTypes, receiver, methodName, callArguments, -1, isSuperInvocation);
-  }
-
-  /// Check that a call to the targetFunction is legal given the arguments.
-  ///
-  /// I.e. check that the number of positional parameters and the names of the
-  /// given named parameters represents a valid call to the function.
-  bool _callIsLegal(FunctionNode targetFunction, Arguments arguments) {
-    if ((targetFunction.requiredParameterCount > arguments.positional.length) ||
-        (targetFunction.positionalParameters.length <
-            arguments.positional.length)) {
-      // Given too few or too many positional arguments
-      return false;
-    }
-
-    // Do we give named that we don't take?
-    Set<String> givenNamed = arguments.named.map((v) => v.name).toSet();
-    Set<String> takenNamed =
-        targetFunction.namedParameters.map((v) => v.name).toSet();
-    givenNamed.removeAll(takenNamed);
-    return givenNamed.isEmpty;
-  }
-}
-
-class SuperInitializerResolutionTransformer extends InitializerVisitor {
-  final Class lookupClass;
-
-  SuperInitializerResolutionTransformer(this.lookupClass);
-
-  transformInitializers(List<Initializer> initializers) {
-    for (var initializer in initializers) {
-      initializer.accept(this);
-    }
-  }
-
-  visitSuperInitializer(SuperInitializer node) {
-    Constructor constructor = node.target;
-    if (constructor.enclosingClass != lookupClass) {
-      // If [node] refers to a constructor target which is not directly the
-      // superclass but some indirect base class then this is because classes in
-      // the middle are mixin applications.  These mixin applications will have
-      // received a forwarding constructor which we are required to use instead.
-      for (var replacement in lookupClass.constructors) {
-        if (constructor.name == replacement.name) {
-          node.target = replacement;
-          return null;
-        }
-      }
-
-      throw new Exception(
-          'Could not find a generative constructor named "${constructor.name}" '
-          'in lookup class "${lookupClass.name}"!');
-    }
-  }
-}
diff --git a/pkg/kernel/lib/transformations/scanner.dart b/pkg/kernel/lib/transformations/scanner.dart
index 5083fa6..ce4b9fc 100644
--- a/pkg/kernel/lib/transformations/scanner.dart
+++ b/pkg/kernel/lib/transformations/scanner.dart
@@ -11,7 +11,7 @@
 }
 
 class ScanResult<X extends TreeNode, Y extends TreeNode> {
-  Map<X, ScanResult<Y, TreeNode>> targets;
+  Map<X, ScanResult<Y, TreeNode>> targets = new Map();
   Map<X, ScanError> errors;
 }
 
@@ -26,26 +26,235 @@
 
   ScanResult<Class, Y> scan(TreeNode node) {
     ScanResult<Class, Y> result = new ScanResult();
-    result.targets = new Map();
+
     if (node is Class) {
       if (predicate(node)) {
         result.targets[node] = next?.scan(node);
+        // TODO(dmitryas): set result.errors when specification is landed,
+        //  same with all other places where targets is set
       }
     } else if (node is Library) {
-      for (Class cls in node.classes) {
-        if (predicate(cls)) {
-          result.targets[cls] = next?.scan(cls);
-        }
-      }
+      _scanLibrary(node, result);
     } else if (node is Component) {
-      for (Library library in node.libraries) {
-        for (Class cls in library.classes) {
-          if (predicate(cls)) {
-            result.targets[cls] = next?.scan(cls);
-          }
-        }
+      _scanComponent(node, result);
+    }
+
+    return result;
+  }
+
+  void _scanLibrary(Library library, ScanResult<Class, Y> result) {
+    for (Class cls in library.classes) {
+      if (predicate(cls)) {
+        result.targets[cls] = next?.scan(cls);
       }
     }
+  }
+
+  void _scanComponent(Component component, ScanResult<Class, Y> result) {
+    for (Library library in component.libraries) {
+      _scanLibrary(library, result);
+    }
+  }
+}
+
+abstract class FieldScanner<Y extends TreeNode> implements Scanner<Field, Y> {
+  final Scanner<Y, TreeNode> next;
+
+  FieldScanner(this.next);
+
+  bool predicate(Field node);
+
+  ScanResult<Field, Y> scan(TreeNode node) {
+    ScanResult<Field, Y> result = new ScanResult();
+
+    if (node is Field) {
+      _scanField(node, result);
+    } else if (node is Class) {
+      _scanClass(node, result);
+    } else if (node is Library) {
+      _scanLibrary(node, result);
+    } else if (node is Component) {
+      _scanComponent(node, result);
+    }
+
     return result;
   }
+
+  void _scanField(Field field, ScanResult<Field, Y> result) {
+    if (predicate(field)) {
+      result.targets[field] = next?.scan(field);
+    }
+  }
+
+  void _scanClass(Class cls, ScanResult<Field, Y> result) {
+    for (Field field in cls.fields) {
+      _scanField(field, result);
+    }
+  }
+
+  void _scanLibrary(Library library, ScanResult<Field, Y> result) {
+    for (Class cls in library.classes) {
+      _scanClass(cls, result);
+    }
+    for (Field field in library.fields) {
+      _scanField(field, result);
+    }
+  }
+
+  void _scanComponent(Component component, ScanResult<Field, Y> result) {
+    for (Library library in component.libraries) {
+      _scanLibrary(library, result);
+    }
+  }
+}
+
+abstract class MemberScanner<Y extends TreeNode> implements Scanner<Member, Y> {
+  final Scanner<Y, TreeNode> next;
+
+  MemberScanner(this.next);
+
+  bool predicate(Member node);
+
+  ScanResult<Member, Y> scan(TreeNode node) {
+    ScanResult<Member, Y> result = new ScanResult();
+
+    if (node is Member) {
+      _scanMember(node, result);
+    } else if (node is Class) {
+      _scanClass(node, result);
+    } else if (node is Library) {
+      _scanLibrary(node, result);
+    } else if (node is Component) {
+      _scanComponent(node, result);
+    }
+
+    return result;
+  }
+
+  void _scanMember(Member member, ScanResult<Member, Y> result) {
+    if (predicate(member)) {
+      result.targets[member] = next?.scan(member);
+    }
+  }
+
+  void _scanClass(Class cls, ScanResult<Member, Y> result) {
+    for (Member member in cls.members) {
+      _scanMember(member, result);
+    }
+  }
+
+  void _scanLibrary(Library library, ScanResult<Member, Y> result) {
+    for (Class cls in library.classes) {
+      _scanClass(cls, result);
+    }
+    for (Member member in library.members) {
+      _scanMember(member, result);
+    }
+  }
+
+  void _scanComponent(Component component, ScanResult<Member, Y> result) {
+    for (Library library in component.libraries) {
+      _scanLibrary(library, result);
+    }
+  }
+}
+
+abstract class ProcedureScanner<Y extends TreeNode>
+    implements Scanner<Procedure, Y> {
+  final Scanner<Y, TreeNode> next;
+
+  ProcedureScanner(this.next);
+
+  bool predicate(Procedure node);
+
+  ScanResult<Procedure, Y> scan(TreeNode node) {
+    ScanResult<Procedure, Y> result = new ScanResult();
+
+    if (node is Procedure) {
+      _scanProcedure(node, result);
+    } else if (node is Class) {
+      _scanClass(node, result);
+    } else if (node is Library) {
+      _scanLibrary(node, result);
+    } else if (node is Component) {
+      _scanComponent(node, result);
+    }
+
+    return result;
+  }
+
+  void _scanProcedure(Procedure procedure, ScanResult<Procedure, Y> result) {
+    if (predicate(procedure)) {
+      result.targets[procedure] = next?.scan(procedure);
+    }
+  }
+
+  void _scanClass(Class cls, ScanResult<Procedure, Y> result) {
+    for (Procedure procedure in cls.procedures) {
+      _scanProcedure(procedure, result);
+    }
+  }
+
+  void _scanLibrary(Library library, ScanResult<Procedure, Y> result) {
+    for (Class cls in library.classes) {
+      _scanClass(cls, result);
+    }
+    for (Procedure procedure in library.procedures) {
+      _scanProcedure(procedure, result);
+    }
+  }
+
+  void _scanComponent(Component component, ScanResult<Procedure, Y> result) {
+    for (Library library in component.libraries) {
+      _scanLibrary(library, result);
+    }
+  }
+}
+
+abstract class ExpressionScanner<Y extends TreeNode>
+    extends RecursiveVisitor<void> implements Scanner<Expression, Y> {
+  final Scanner<Y, TreeNode> next;
+  ScanResult<Expression, Y> _result;
+
+  ExpressionScanner(this.next);
+
+  bool predicate(Expression node);
+
+  ScanResult<Expression, Y> scan(TreeNode node) {
+    ScanResult<Expression, Y> result = _result = new ScanResult();
+    node.accept(this);
+    _result = null;
+    return result;
+  }
+
+  void visitExpression(Expression node) {
+    if (predicate(node)) {
+      _result.targets[node] = next?.scan(node);
+      // TODO: Update result.errors.
+    }
+  }
+}
+
+abstract class MethodInvocationScanner<Y extends TreeNode>
+    extends RecursiveVisitor<void> implements Scanner<MethodInvocation, Y> {
+  final Scanner<Y, TreeNode> next;
+  ScanResult<MethodInvocation, Y> _result;
+
+  MethodInvocationScanner(this.next);
+
+  bool predicate(MethodInvocation node);
+
+  ScanResult<MethodInvocation, Y> scan(TreeNode node) {
+    ScanResult<MethodInvocation, Y> result = _result = new ScanResult();
+    node.accept(this);
+    _result = null;
+    return result;
+  }
+
+  void visitMethodInvocation(MethodInvocation node) {
+    if (predicate(node)) {
+      _result.targets[node] = next?.scan(node);
+      // TODO: Update result.errors.
+    }
+  }
 }
diff --git a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
index 5e18e6f..a47072d 100644
--- a/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
+++ b/pkg/kernel/lib/transformations/track_widget_constructor_locations.dart
@@ -360,7 +360,7 @@
   void _transformClassImplementingWidget(
       Class clazz, ChangedStructureNotifier changedStructureNotifier) {
     if (clazz.fields
-        .any((Field field) => field.name.name == _locationFieldName)) {
+        .any((Field field) => field.name.text == _locationFieldName)) {
       // This class has already been transformed. Skip
       return;
     }
@@ -396,10 +396,10 @@
         _creationLocationParameterName,
       ));
       final VariableDeclaration variable = new VariableDeclaration(
-        _creationLocationParameterName,
-        type:
-            new InterfaceType(_locationClass, clazz.enclosingLibrary.nullable),
-      );
+          _creationLocationParameterName,
+          type: new InterfaceType(
+              _locationClass, clazz.enclosingLibrary.nullable),
+          initializer: new NullLiteral());
       if (!_maybeAddNamedParameter(constructor.function, variable)) {
         return;
       }
@@ -424,14 +424,8 @@
         }
       }
       if (!hasRedirectingInitializer) {
-        constructor.initializers.add(new FieldInitializer(
-          locationField,
-          clazz.enclosingLibrary.isNonNullableByDefault
-              // The parameter is nullable so that it can be optional but the
-              // field is non-nullable so we check it here.
-              ? new NullCheck(new VariableGet(variable))
-              : new VariableGet(variable),
-        ));
+        constructor.initializers.add(
+            new FieldInitializer(locationField, new VariableGet(variable)));
         // TODO(jacobr): add an assert verifying the locationField is not
         // null. Currently, we cannot safely add this assert because we do not
         // handle Widget classes with optional positional arguments. There are
@@ -547,7 +541,8 @@
           procedure.function,
           new VariableDeclaration(_creationLocationParameterName,
               type: new InterfaceType(
-                  _locationClass, clazz.enclosingLibrary.nullable)),
+                  _locationClass, clazz.enclosingLibrary.nullable),
+              initializer: new NullLiteral()),
         );
       }
     }
@@ -570,7 +565,8 @@
       final VariableDeclaration variable = new VariableDeclaration(
           _creationLocationParameterName,
           type: new InterfaceType(
-              _locationClass, clazz.enclosingLibrary.nullable));
+              _locationClass, clazz.enclosingLibrary.nullable),
+          initializer: new NullLiteral());
       if (_hasNamedParameter(
           constructor.function, _creationLocationParameterName)) {
         // Constructor was already rewritten. TODO(jacobr): is this case actually hit?
diff --git a/pkg/kernel/lib/transformations/value_class.dart b/pkg/kernel/lib/transformations/value_class.dart
index 9e38786..d56989a 100644
--- a/pkg/kernel/lib/transformations/value_class.dart
+++ b/pkg/kernel/lib/transformations/value_class.dart
@@ -4,6 +4,8 @@
 
 library kernel.transformations.value_class;
 
+import 'package:kernel/type_environment.dart';
+
 import '../ast.dart';
 import '../kernel.dart';
 import '../core_types.dart' show CoreTypes;
@@ -13,44 +15,67 @@
 class ValueClassScanner extends ClassScanner<Null> {
   ValueClassScanner() : super(null);
 
+  bool predicate(Class node) => isValueClass(node);
+}
+
+class JenkinsClassScanner extends ClassScanner<Procedure> {
+  JenkinsClassScanner(Scanner<Procedure, TreeNode> next) : super(next);
+
   bool predicate(Class node) {
-    for (Expression annotation in node.annotations) {
-      if (annotation is ConstantExpression &&
-          annotation.constant is StringConstant) {
-        StringConstant constant = annotation.constant;
-        if (constant.value == 'valueClass') {
-          return true;
-        }
-      }
-    }
-    return false;
+    return node.name == "JenkinsSmiHash";
   }
 }
 
-void transformComponent(
-    Component node, CoreTypes coreTypes, ClassHierarchy hierarchy) {
+class HashCombineMethodsScanner extends ProcedureScanner<Null> {
+  HashCombineMethodsScanner() : super(null);
+
+  bool predicate(Procedure node) {
+    return node.name.text == "combine" || node.name.text == "finish";
+  }
+}
+
+class AllMemberScanner extends MemberScanner<MethodInvocation> {
+  AllMemberScanner(Scanner<MethodInvocation, TreeNode> next) : super(next);
+
+  bool predicate(Member member) => true;
+}
+
+// Scans and matches all copyWith invocations were the reciever is _ as dynamic
+// It will filter out the results that are not value classes afterwards
+class ValueClassCopyWithScanner extends MethodInvocationScanner<Null> {
+  ValueClassCopyWithScanner() : super(null);
+
+  // The matching construct followed in unit-tests is:
+  // @valueClass V {}
+  // V v;
+  // (v as dynamic).copyWith() as V
+  bool predicate(MethodInvocation node) {
+    return node.name.name == "copyWith" &&
+        _isValueClassAsConstruct(node.receiver);
+  }
+
+  bool _isValueClassAsConstruct(Expression node) {
+    return node is AsExpression && node.type is DynamicType;
+  }
+}
+
+void transformComponent(Component node, CoreTypes coreTypes,
+    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
   ValueClassScanner scanner = new ValueClassScanner();
   ScanResult<Class, Null> valueClasses = scanner.scan(node);
   for (Class valueClass in valueClasses.targets.keys) {
-    transformValueClass(valueClass, coreTypes, hierarchy);
+    transformValueClass(valueClass, coreTypes, hierarchy, typeEnvironment);
+  }
+
+  treatCopyWithCallSites(node, coreTypes, typeEnvironment, hierarchy);
+
+  for (Class valueClass in valueClasses.targets.keys) {
+    removeValueClassAnnotation(valueClass);
   }
 }
 
-void transformValueClass(
-    Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy) {
-  addConstructor(cls, coreTypes);
-  addEqualsOperator(cls, coreTypes, hierarchy);
-  // addHashCode(cls, coreTypes);
-  // addCopyWith(cls);
-}
-
-void addConstructor(Class cls, CoreTypes coreTypes) {
-  Constructor superConstructor = null;
-  for (Constructor constructor in cls.superclass.constructors) {
-    if (constructor.name.name == "") {
-      superConstructor = constructor;
-    }
-  }
+void transformValueClass(Class cls, CoreTypes coreTypes,
+    ClassHierarchy hierarchy, TypeEnvironment typeEnvironment) {
   Constructor syntheticConstructor = null;
   for (Constructor constructor in cls.constructors) {
     if (constructor.isSynthetic) {
@@ -58,20 +83,40 @@
     }
   }
 
+  List<VariableDeclaration> allVariables = queryAllInstanceVariables(cls);
+  List<VariableDeclaration> allVariablesList = allVariables.toList();
+  allVariablesList.sort((a, b) => a.name.compareTo(b.name));
+
+  addConstructor(cls, coreTypes, syntheticConstructor);
+  addEqualsOperator(cls, coreTypes, hierarchy, allVariablesList);
+  addHashCode(cls, coreTypes, hierarchy, allVariablesList);
+  addToString(cls, coreTypes, hierarchy, allVariablesList);
+  addCopyWith(cls, coreTypes, hierarchy, allVariablesList, syntheticConstructor,
+      typeEnvironment);
+}
+
+void addConstructor(
+    Class cls, CoreTypes coreTypes, Constructor syntheticConstructor) {
+  Constructor superConstructor = null;
+  for (Constructor constructor in cls.superclass.constructors) {
+    if (constructor.name.text == "") {
+      superConstructor = constructor;
+    }
+  }
   List<VariableDeclaration> superParameters = superConstructor
       .function.namedParameters
       .map<VariableDeclaration>((e) => VariableDeclaration(e.name, type: e.type)
         ..parent = syntheticConstructor.function)
       .toList();
   Map<String, VariableDeclaration> ownFields = Map.fromIterable(cls.fields,
-      key: (f) => f.name.name,
+      key: (f) => f.name.text,
       value: (f) =>
-          VariableDeclaration(f.name.name, type: f.type, isRequired: true)
+          VariableDeclaration(f.name.text, type: f.type, isRequired: true)
             ..parent = syntheticConstructor.function);
 
   List<Initializer> initializersConstructor = cls.fields
       .map<Initializer>((f) =>
-          FieldInitializer(f, VariableGet(ownFields[f.name.name]))
+          FieldInitializer(f, VariableGet(ownFields[f.name.text]))
             ..parent = syntheticConstructor)
       .toList();
 
@@ -84,52 +129,23 @@
     ..addAll(ownFields.values)
     ..addAll(superParameters);
   syntheticConstructor.initializers = initializersConstructor;
-
-  int valueClassAnnotationIndex;
-  for (int annotationIndex = 0;
-      annotationIndex < cls.annotations.length;
-      annotationIndex++) {
-    Expression annotation = cls.annotations[annotationIndex];
-    if (annotation is ConstantExpression &&
-        annotation.constant is StringConstant) {
-      StringConstant constant = annotation.constant;
-      if (constant.value == 'valueClass') {
-        valueClassAnnotationIndex = annotationIndex;
-      }
-    }
-  }
-  cls.annotations.removeAt(valueClassAnnotationIndex);
 }
 
-void addEqualsOperator(
-    Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy) {
+void addEqualsOperator(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
+    List<VariableDeclaration> allVariablesList) {
+  List<VariableDeclaration> allVariables = allVariablesList.toList();
   for (Procedure procedure in cls.procedures) {
     if (procedure.kind == ProcedureKind.Operator &&
-        procedure.name.name == "==") {
+        procedure.name.text == "==") {
       // ==operator is already implemented, spec is to do nothing
       return;
     }
   }
-  DartType returnType = cls.enclosingLibrary.isNonNullableByDefault
-      ? coreTypes.boolNonNullableRawType
-      : coreTypes.boolLegacyRawType;
+  DartType returnType = coreTypes.boolRawType(cls.enclosingLibrary.nonNullable);
   DartType myType = coreTypes.thisInterfaceType(cls, Nullability.nonNullable);
 
-  Constructor superConstructor = null;
-  for (Constructor constructor in cls.superclass.constructors) {
-    if (constructor.name.name == "") {
-      superConstructor = constructor;
-    }
-  }
   VariableDeclaration other = VariableDeclaration("other",
       type: coreTypes.objectRawType(Nullability.nonNullable));
-  List<VariableDeclaration> allVariables = superConstructor
-      .function.namedParameters
-      .map<VariableDeclaration>(
-          (f) => VariableDeclaration(f.name, type: f.type))
-      .toList()
-        ..addAll(cls.fields.map<VariableDeclaration>(
-            (f) => VariableDeclaration(f.name.name, type: f.type)));
 
   Map<VariableDeclaration, Member> targetsEquals = new Map();
   Map<VariableDeclaration, Member> targets = new Map();
@@ -161,8 +177,8 @@
                   targetsEquals[f]))
               .fold(
                   IsExpression(VariableGet(other), myType),
-                  (previousValue, element) =>
-                      LogicalExpression(previousValue, '&&', element))),
+                  (previousValue, element) => LogicalExpression(
+                      previousValue, LogicalExpressionOperator.AND, element))),
           returnType: returnType,
           positionalParameters: [other]),
       fileUri: cls.fileUri)
@@ -170,44 +186,129 @@
   cls.addMember(equalsOperator);
 }
 
-/*
-void addHashCode(Class cls, CoreTypes coreTypes) {
-  Map<String, VariableDeclaration> environment = Map.fromIterable(cls.fields,
-      key: (f) => f.name.name,
-      value: (f) => VariableDeclaration(f.name.name, type: f.type));
+void addHashCode(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
+    List<VariableDeclaration> allVariablesList) {
+  List<VariableDeclaration> allVariables = allVariablesList.toList();
+  for (Procedure procedure in cls.procedures) {
+    if (procedure.kind == ProcedureKind.Getter &&
+        procedure.name.text == "hashCode") {
+      // hashCode getter is already implemented, spec is to do nothing
+      return;
+    }
+  }
+  DartType returnType = coreTypes.intRawType(cls.enclosingLibrary.nonNullable);
 
-  VariableDeclaration other = VariableDeclaration("other");
+  Procedure hashCombine, hashFinish;
+  HashCombineMethodsScanner hashCombineMethodsScanner =
+      new HashCombineMethodsScanner();
+  JenkinsClassScanner jenkinsScanner =
+      new JenkinsClassScanner(hashCombineMethodsScanner);
+  ScanResult<Class, Procedure> hashMethodsResult =
+      jenkinsScanner.scan(cls.enclosingLibrary.enclosingComponent);
+  for (Class clazz in hashMethodsResult.targets.keys) {
+    for (Procedure procedure in hashMethodsResult.targets[clazz].targets.keys) {
+      if (procedure.name.text == "combine") hashCombine = procedure;
+      if (procedure.name.text == "finish") hashFinish = procedure;
+    }
+  }
 
-  var returnType = cls.enclosingLibrary.isNonNullableByDefault
-      ? coreTypes.boolNonNullableRawType
-      : coreTypes.boolLegacyRawType;
-
+  Map<VariableDeclaration, Member> targetsHashcode = new Map();
+  Map<VariableDeclaration, Member> targets = new Map();
+  for (VariableDeclaration variable in allVariables) {
+    Member target = coreTypes.objectEquals;
+    Member targetHashcode = coreTypes.objectEquals;
+    DartType fieldsType = variable.type;
+    if (fieldsType is InterfaceType) {
+      targetHashcode =
+          hierarchy.getInterfaceMember(fieldsType.classNode, Name("hashCode"));
+      target = hierarchy.getInterfaceMember(cls, Name(variable.name));
+    }
+    targetsHashcode[variable] = targetHashcode;
+    targets[variable] = target;
+  }
   cls.addMember(Procedure(
       Name("hashCode"),
       ProcedureKind.Getter,
-      FunctionNode(ReturnStatement(cls.fields
-          .map((f) => DirectPropertyGet(
-              VariableGet(environment[f.name.name]),
-              Procedure(Name("hashCode"), ProcedureKind.Getter,
-                  null) // TODO(jlcontreras): Add ref to the real hashCode getter, dont create a new one
-              ))
-          .toList()
-          .fold(
-              IntLiteral(0),
-              (previousValue, element) => MethodInvocation(
-                  previousValue, Name("*"), Arguments([element])))))));
+      FunctionNode(
+          ReturnStatement(StaticInvocation(
+              hashFinish,
+              Arguments([
+                allVariables
+                    .map((f) => (PropertyGet(
+                        PropertyGet(ThisExpression(), Name(f.name), targets[f]),
+                        Name("hashCode"),
+                        targetsHashcode[f])))
+                    .fold(
+                        PropertyGet(
+                            StringLiteral(
+                                cls.enclosingLibrary.importUri.toString() +
+                                    cls.name),
+                            Name("hashCode"),
+                            hierarchy.getInterfaceMember(
+                                coreTypes.stringClass, Name("hashCode"))),
+                        (previousValue, element) => StaticInvocation(
+                            hashCombine, Arguments([previousValue, element])))
+              ]))),
+          returnType: returnType),
+      fileUri: cls.fileUri)
+    ..fileOffset = cls.fileOffset);
 }
 
-void addCopyWith(Class cls) {
-  Map<String, VariableDeclaration> environment = Map.fromIterable(cls.fields,
-      key: (f) => f.name.name,
-      value: (f) => VariableDeclaration(f.name.name, type: f.type));
+void addToString(Class cls, CoreTypes coreTypes, ClassHierarchy hierarchy,
+    List<VariableDeclaration> allVariablesList) {
+  List<Expression> wording = [StringLiteral("${cls.name}(")];
 
-  Constructor syntheticConstructor = null;
-  for (Constructor constructor in cls.constructors) {
-    if (constructor.isSynthetic) {
-      syntheticConstructor = constructor;
+  for (VariableDeclaration variable in allVariablesList) {
+    wording.add(StringLiteral("${variable.name}: "));
+    wording.add(MethodInvocation(
+        PropertyGet(ThisExpression(), Name(variable.name),
+            hierarchy.getInterfaceMember(cls, Name(variable.name))),
+        Name("toString"),
+        Arguments([]),
+        (variable.type is InterfaceType)
+            ? hierarchy.getInterfaceMember(
+                (variable.type as InterfaceType).classNode, Name("toString"))
+            : null));
+    wording.add(StringLiteral(", "));
+  }
+  if (allVariablesList.length != 0) {
+    wording[wording.length - 1] = StringLiteral(")");
+  } else {
+    wording.add(StringLiteral(")"));
+  }
+  DartType returnType =
+      coreTypes.stringRawType(cls.enclosingLibrary.nonNullable);
+  cls.addMember(Procedure(
+      Name("toString"),
+      ProcedureKind.Method,
+      FunctionNode(ReturnStatement(StringConcatenation(wording)),
+          returnType: returnType),
+      fileUri: cls.fileUri)
+    ..fileOffset = cls.fileOffset);
+}
+
+void addCopyWith(
+    Class cls,
+    CoreTypes coreTypes,
+    ClassHierarchy hierarchy,
+    List<VariableDeclaration> allVariablesList,
+    Constructor syntheticConstructor,
+    TypeEnvironment typeEnvironment) {
+  List<VariableDeclaration> allVariables = allVariablesList.toList();
+
+  Map<VariableDeclaration, Member> targetsEquals = new Map();
+  Map<VariableDeclaration, Member> targets = new Map();
+  for (VariableDeclaration variable in allVariables) {
+    Member target = coreTypes.objectEquals;
+    Member targetEquals = coreTypes.objectEquals;
+    DartType fieldsType = variable.type;
+    if (fieldsType is InterfaceType) {
+      targetEquals =
+          hierarchy.getInterfaceMember(fieldsType.classNode, Name("=="));
+      target = hierarchy.getInterfaceMember(cls, Name(variable.name));
     }
+    targetsEquals[variable] = targetEquals;
+    targets[variable] = target;
   }
 
   cls.addMember(Procedure(
@@ -216,25 +317,118 @@
       FunctionNode(
           ReturnStatement(ConstructorInvocation(
               syntheticConstructor,
-              Arguments(cls.fields
-                  .map((f) => ConditionalExpression(
-                      MethodInvocation(VariableGet(environment[f.name.name]),
-                          Name('=='), Arguments([NullLiteral()])),
-                      PropertyGet(ThisExpression(), f.name, f),
-                      VariableGet(environment[f.name.name]),
-                      f.type))
-                  .toList()))),
-          namedParameters:
-              cls.fields.map((f) => environment[f.name.name]).toList())));
+              Arguments([],
+                  named: allVariables
+                      .map((f) => NamedExpression(f.name, VariableGet(f)))
+                      .toList()))),
+          namedParameters: allVariables),
+      fileUri: cls.fileUri)
+    ..fileOffset = cls.fileOffset);
 }
-*/
 
-bool isValueClass(Class cls) {
-  for (Expression annotation in cls.annotations) {
+List<VariableDeclaration> queryAllInstanceVariables(Class cls) {
+  Constructor superConstructor = null;
+  for (Constructor constructor in cls.superclass.constructors) {
+    if (constructor.name.text == "") {
+      superConstructor = constructor;
+    }
+  }
+  return superConstructor.function.namedParameters
+      .map<VariableDeclaration>(
+          (f) => VariableDeclaration(f.name, type: f.type))
+      .toList()
+        ..addAll(cls.fields.map<VariableDeclaration>(
+            (f) => VariableDeclaration(f.name.text, type: f.type)));
+}
+
+void removeValueClassAnnotation(Class cls) {
+  int valueClassAnnotationIndex;
+  for (int annotationIndex = 0;
+      annotationIndex < cls.annotations.length;
+      annotationIndex++) {
+    Expression annotation = cls.annotations[annotationIndex];
     if (annotation is ConstantExpression &&
         annotation.constant is StringConstant) {
       StringConstant constant = annotation.constant;
       if (constant.value == 'valueClass') {
+        valueClassAnnotationIndex = annotationIndex;
+      }
+    }
+  }
+  cls.annotations.removeAt(valueClassAnnotationIndex);
+}
+
+void treatCopyWithCallSites(Component component, CoreTypes coreTypes,
+    TypeEnvironment typeEnvironment, ClassHierarchy hierarchy) {
+  ValueClassCopyWithScanner valueCopyWithScanner =
+      new ValueClassCopyWithScanner();
+  AllMemberScanner copyWithScanner = AllMemberScanner(valueCopyWithScanner);
+  ScanResult<Member, MethodInvocation> copyWithCallSites =
+      copyWithScanner.scan(component);
+  for (Member memberWithCopyWith in copyWithCallSites.targets.keys) {
+    if (copyWithCallSites.targets[memberWithCopyWith].targets != null) {
+      StaticTypeContext staticTypeContext =
+          StaticTypeContext(memberWithCopyWith, typeEnvironment);
+      for (MethodInvocation copyWithCall
+          in copyWithCallSites.targets[memberWithCopyWith].targets.keys) {
+        AsExpression receiver = copyWithCall.receiver as AsExpression;
+
+        Expression valueClassInstance = receiver.operand;
+        DartType valueClassType =
+            valueClassInstance.getStaticType(staticTypeContext);
+        if (valueClassType is InterfaceType) {
+          Class valueClass = valueClassType.classNode;
+          if (isValueClass(valueClass)) {
+            treatCopyWithCallSite(
+                valueClass, copyWithCall, coreTypes, hierarchy);
+          }
+        }
+      }
+    }
+  }
+}
+
+void treatCopyWithCallSite(Class valueClass, MethodInvocation copyWithCall,
+    CoreTypes coreTypes, ClassHierarchy hierarchy) {
+  Map<String, Expression> preTransformationArguments = new Map();
+  for (NamedExpression argument in copyWithCall.arguments.named) {
+    preTransformationArguments[argument.name] = argument.value;
+  }
+  Constructor syntheticConstructor;
+  for (Constructor constructor in valueClass.constructors) {
+    if (constructor.isSynthetic) {
+      syntheticConstructor = constructor;
+    }
+  }
+  List<VariableDeclaration> allArguments =
+      syntheticConstructor.function.namedParameters;
+
+  VariableDeclaration letVariable =
+      VariableDeclaration.forValue(copyWithCall.receiver);
+  Arguments postTransformationArguments = Arguments.empty();
+  for (VariableDeclaration argument in allArguments) {
+    if (preTransformationArguments.containsKey(argument.name)) {
+      postTransformationArguments.named.add(NamedExpression(
+          argument.name, preTransformationArguments[argument.name])
+        ..parent = postTransformationArguments);
+    } else {
+      postTransformationArguments.named.add(NamedExpression(argument.name,
+          PropertyGet(VariableGet(letVariable), Name(argument.name)))
+        ..parent = postTransformationArguments);
+    }
+  }
+  copyWithCall.replaceWith(Let(
+      letVariable,
+      MethodInvocation(VariableGet(letVariable), Name("copyWith"),
+          postTransformationArguments)));
+}
+
+bool isValueClass(Class node) {
+  for (Expression annotation in node.annotations) {
+    if (annotation is ConstantExpression &&
+        annotation.constant is StringConstant) {
+      StringConstant constant = annotation.constant;
+      if (constant.value == "valueClass") {
         return true;
       }
     }
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index 4661aeb..dccad1c 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -5,6 +5,7 @@
 
 import 'ast.dart';
 import 'core_types.dart';
+import 'src/replacement_visitor.dart';
 
 /// Returns a type where all occurrences of the given type parameters have been
 /// replaced with the corresponding types.
@@ -1034,16 +1035,18 @@
 
 /// Implementation of [unwrapNullabilityConstructor] as a visitor.
 ///
-/// Implementing the function as a visitor makes the necessity of supporting a new implementation of [DartType] visible at compile time.
-// TODO(dmitryas): Remove CoreTypes as the second argument when NullType is landed.
+/// Implementing the function as a visitor makes the necessity of supporting a
+/// new implementation of [DartType] visible at compile time.
+// TODO(dmitryas): Remove CoreTypes as the second argument when NullType is
+// landed.
 class _NullabilityConstructorUnwrapper
     implements DartTypeVisitor1<DartType, CoreTypes> {
   const _NullabilityConstructorUnwrapper();
 
   @override
   DartType defaultDartType(DartType node, CoreTypes coreTypes) {
-    throw new UnsupportedError(
-        "Unsupported operation: _NullabilityConstructorUnwrapper(${node.runtimeType})");
+    throw new UnsupportedError("Unsupported operation: "
+        "_NullabilityConstructorUnwrapper(${node.runtimeType})");
   }
 
   @override
@@ -1096,3 +1099,181 @@
   @override
   DartType visitVoidType(VoidType node, CoreTypes coreTypes) => node;
 }
+
+/// Eliminates specified free type parameters in a type.
+///
+/// The algorithm for elimination of type variables is described in
+/// https://github.com/dart-lang/language/pull/957
+class NullabilityAwareTypeVariableEliminator extends ReplacementVisitor {
+  final DartType bottomType;
+  final DartType topType;
+  final DartType topFunctionType;
+  final Set<TypeParameter> eliminationTargets;
+  bool isLeastClosure;
+  bool isCovariant = true;
+  bool Function(DartType type, bool Function(DartType type) recursor)
+      unhandledTypeHandler; // Can be null.
+
+  NullabilityAwareTypeVariableEliminator(
+      {this.eliminationTargets,
+      this.bottomType,
+      this.topType,
+      this.topFunctionType,
+      this.unhandledTypeHandler})
+      : assert(eliminationTargets != null),
+        assert(bottomType != null),
+        assert(topType != null),
+        assert(topFunctionType != null);
+
+  /// Returns a subtype of [type] for all values of [eliminationTargets].
+  DartType eliminateToLeast(DartType type) {
+    isCovariant = true;
+    isLeastClosure = true;
+    return type.accept(this) ?? type;
+  }
+
+  /// Returns a supertype of [type] for all values of [eliminationTargets].
+  DartType eliminateToGreatest(DartType type) {
+    isCovariant = true;
+    isLeastClosure = false;
+    return type.accept(this) ?? type;
+  }
+
+  DartType get typeParameterReplacement {
+    return isLeastClosure && isCovariant || (!isLeastClosure && !isCovariant)
+        ? bottomType
+        : topType;
+  }
+
+  DartType get functionReplacement {
+    return isLeastClosure && isCovariant || (!isLeastClosure && !isCovariant)
+        ? bottomType
+        : topFunctionType;
+  }
+
+  @override
+  void changeVariance() {
+    isCovariant = !isCovariant;
+  }
+
+  @override
+  DartType visitFunctionType(FunctionType node) {
+    // - if `S` is
+    //   `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
+    //       [Tn+1 xn+1, ..., Tm xm])`
+    //   or `T Function<X0 extends B0, ...., Xk extends Bk>(T0 x0, ...., Tn xn,
+    //       {Tn+1 xn+1, ..., Tm xm})`
+    //   and `L` contains any free type variables from any of the `Bi`:
+    //  - The least closure of `S` with respect to `L` is `Never`
+    //  - The greatest closure of `S` with respect to `L` is `Function`
+    if (node.typeParameters.isNotEmpty) {
+      for (TypeParameter typeParameter in node.typeParameters) {
+        if (containsTypeVariable(typeParameter.bound, eliminationTargets,
+            unhandledTypeHandler: unhandledTypeHandler)) {
+          return functionReplacement;
+        }
+      }
+    }
+    return super.visitFunctionType(node);
+  }
+
+  @override
+  DartType visitTypeParameterType(TypeParameterType node) {
+    if (eliminationTargets.contains(node.parameter)) {
+      return typeParameterReplacement.withDeclaredNullability(
+          uniteNullabilities(
+              typeParameterReplacement.nullability, node.nullability));
+    }
+    return super.visitTypeParameterType(node);
+  }
+}
+
+/// Computes [type] as if declared without nullability markers.
+///
+/// For example, int? and int* are considered applications of the nullable and
+/// the legacy type constructors to type int correspondingly.
+/// [computeTypeWithoutNullabilityMarker] peels off these type constructors,
+/// returning the non-nullable version of type int.  In case of
+/// [TypeParameterType]s, the result may be either [Nullability.nonNullable] or
+/// [Nullability.undetermined], depending on the bound.
+DartType computeTypeWithoutNullabilityMarker(
+    DartType type, Library clientLibrary,
+    {DartType nullType}) {
+  assert(nullType != null);
+  if (type is TypeParameterType) {
+    if (type.promotedBound == null) {
+      // The default nullability for library is used when there are no
+      // nullability markers on the type.
+      return new TypeParameterType.withDefaultNullabilityForLibrary(
+          type.parameter, clientLibrary);
+    } else {
+      // Intersection types can't be arguments to the nullable and the legacy
+      // type constructors, so nothing can be peeled off.
+      return type;
+    }
+  } else if (type == nullType) {
+    return type;
+  } else {
+    // For most types, peeling off the nullability constructors means that
+    // they become non-nullable.
+    return type.withDeclaredNullability(Nullability.nonNullable);
+  }
+}
+
+/// Returns true if [type] is declared without nullability markers.
+///
+/// An example of the nullable type constructor application is T? where T is a
+/// type parameter.  Some examples of types declared without nullability markers
+/// are T% and S, where T and S are type parameters such that T extends Object?
+/// and S extends Object.
+bool isTypeParameterTypeWithoutNullabilityMarker(
+    TypeParameterType type, Library clientLibrary) {
+  // The default nullability for library is used when there are no nullability
+  // markers on the type.
+  return type.promotedBound == null &&
+      type.declaredNullability ==
+          new TypeParameterType.withDefaultNullabilityForLibrary(
+                  type.parameter, clientLibrary)
+              .declaredNullability;
+}
+
+/// Returns true if [type] is an application of the nullable type constructor.
+///
+/// A type is considered an application of the nullable type constructor if it
+/// was declared with the ? marker.  Some examples of such types are int?,
+/// String?, Object?, and T? where T is a type parameter.  Types dynamic, void,
+/// and Null are nullable, but aren't considered applications of the nullable
+/// type constructor.
+bool isNullableTypeConstructorApplication(DartType type, {DartType nullType}) {
+  assert(nullType != null);
+  return type.declaredNullability == Nullability.nullable &&
+      type is! DynamicType &&
+      type is! VoidType &&
+      type != nullType;
+}
+
+/// Returns true if [type] is an application of the legacy type constructor.
+///
+/// A type is considered an application of the legacy type constructor if it was
+/// declared within a legacy library and is not one of exempt types, such as
+/// dynamic or void.
+bool isLegacyTypeConstructorApplication(DartType type, Library clientLibrary) {
+  if (type is TypeParameterType) {
+    if (type.promotedBound == null) {
+      // The legacy nullability is considered an application of the legacy
+      // nullability constructor if it doesn't match the default nullability
+      // of the type-parameter type for the library.
+      return type.declaredNullability == Nullability.legacy &&
+          type.declaredNullability !=
+              new TypeParameterType.withDefaultNullabilityForLibrary(
+                      type.parameter, clientLibrary)
+                  .declaredNullability;
+    } else {
+      return false;
+    }
+  } else if (type is InvalidType) {
+    return false;
+  } else {
+    return type.declaredNullability == Nullability.legacy;
+  }
+}
diff --git a/pkg/kernel/lib/type_checker.dart b/pkg/kernel/lib/type_checker.dart
index 5db606b..ff94bf8 100644
--- a/pkg/kernel/lib/type_checker.dart
+++ b/pkg/kernel/lib/type_checker.dart
@@ -456,27 +456,6 @@
   }
 
   @override
-  DartType visitDirectMethodInvocation(DirectMethodInvocation node) {
-    return handleCall(node.arguments, node.target.getterType,
-        receiver: getReceiverType(node, node.receiver, node.target));
-  }
-
-  @override
-  DartType visitDirectPropertyGet(DirectPropertyGet node) {
-    var receiver = getReceiverType(node, node.receiver, node.target);
-    return receiver.substituteType(node.target.getterType);
-  }
-
-  @override
-  DartType visitDirectPropertySet(DirectPropertySet node) {
-    var receiver = getReceiverType(node, node.receiver, node.target);
-    var value = visitExpression(node.value);
-    checkAssignable(node, value,
-        receiver.substituteType(node.target.setterType, contravariant: true));
-    return value;
-  }
-
-  @override
   DartType visitDoubleLiteral(DoubleLiteral node) {
     return environment.coreTypes.doubleLegacyRawType;
   }
@@ -622,11 +601,11 @@
     var target = node.interfaceTarget;
     if (target == null) {
       var receiver = visitExpression(node.receiver);
-      if (node.name.name == '==') {
+      if (node.name.text == '==') {
         visitExpression(node.arguments.positional.single);
         return environment.coreTypes.boolLegacyRawType;
       }
-      if (node.name.name == 'call' && receiver is FunctionType) {
+      if (node.name.text == 'call' && receiver is FunctionType) {
         return handleFunctionCall(node, receiver, node.arguments);
       }
       checkUnresolvedInvocation(receiver, node);
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index a6f70ca..4ccf611 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -156,7 +156,7 @@
       if (class_ == coreTypes.intClass ||
           class_ == coreTypes.numClass ||
           class_ == coreTypes.doubleClass) {
-        String name = member.name.name;
+        String name = member.name.text;
         return name == '+' ||
             name == '-' ||
             name == '*' ||
@@ -166,7 +166,7 @@
     } else {
       Class class_ = member.enclosingClass;
       if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
-        String name = member.name.name;
+        String name = member.name.text;
         return name == '+' ||
             name == '-' ||
             name == '*' ||
@@ -184,7 +184,7 @@
     if (isNonNullableByDefault) {
       Class class_ = member.enclosingClass;
       if (class_ == coreTypes.intClass || class_ == coreTypes.numClass) {
-        String name = member.name.name;
+        String name = member.name.text;
         return name == 'clamp';
       }
     }
diff --git a/pkg/kernel/lib/verifier.dart b/pkg/kernel/lib/verifier.dart
index 5ad6c85..3ab077d 100644
--- a/pkg/kernel/lib/verifier.dart
+++ b/pkg/kernel/lib/verifier.dart
@@ -63,6 +63,8 @@
   /// a verification error for anything that should have been removed by it.
   final bool afterConst;
 
+  AsyncMarker currentAsyncMarker = AsyncMarker.Sync;
+
   bool inCatchBlock = false;
 
   bool inUnevaluatedConstant = false;
@@ -273,11 +275,11 @@
     var oldParent = enterParent(node);
     bool isTopLevel = node.parent == currentLibrary;
     if (isTopLevel && !node.isStatic) {
-      problem(node, "The top-level field '${node.name.name}' should be static",
+      problem(node, "The top-level field '${node.name.text}' should be static",
           context: node);
     }
     if (node.isConst && !node.isStatic) {
-      problem(node, "The const field '${node.name.name}' should be static",
+      problem(node, "The const field '${node.name.text}' should be static",
           context: node);
     }
     classTypeParametersAreInScope = !node.isStatic;
@@ -378,9 +380,12 @@
   visitFunctionNode(FunctionNode node) {
     declareTypeParameters(node.typeParameters);
     bool savedInCatchBlock = inCatchBlock;
+    AsyncMarker savedAsyncMarker = currentAsyncMarker;
+    currentAsyncMarker = node.asyncMarker;
     inCatchBlock = false;
     visitWithLocalScope(node);
     inCatchBlock = savedInCatchBlock;
+    currentAsyncMarker = savedAsyncMarker;
     undeclareTypeParameters(node.typeParameters);
   }
 
@@ -444,6 +449,40 @@
   }
 
   @override
+  void visitReturnStatement(ReturnStatement node) {
+    switch (currentAsyncMarker) {
+      case AsyncMarker.Sync:
+      case AsyncMarker.Async:
+      case AsyncMarker.SyncYielding:
+        // ok
+        break;
+      case AsyncMarker.SyncStar:
+      case AsyncMarker.AsyncStar:
+        problem(node,
+            "Return statement in function with async marker: $currentAsyncMarker");
+        break;
+    }
+    super.visitReturnStatement(node);
+  }
+
+  @override
+  void visitYieldStatement(YieldStatement node) {
+    switch (currentAsyncMarker) {
+      case AsyncMarker.Sync:
+      case AsyncMarker.Async:
+        problem(node,
+            "Yield statement in function with async marker: $currentAsyncMarker");
+        break;
+      case AsyncMarker.SyncStar:
+      case AsyncMarker.AsyncStar:
+      case AsyncMarker.SyncYielding:
+        // ok
+        break;
+    }
+    super.visitYieldStatement(node);
+  }
+
+  @override
   visitRethrow(Rethrow node) {
     if (!inCatchBlock) {
       problem(node, "Rethrow must be inside a Catch block.");
@@ -574,45 +613,6 @@
   }
 
   @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    visitChildren(node);
-    if (node.target == null) {
-      problem(node, "DirectPropertyGet without target.");
-    }
-    if (!node.target.hasGetter) {
-      problem(node, "DirectPropertyGet of '${node.target}' without getter.");
-    }
-    if (!node.target.isInstanceMember) {
-      problem(
-          node,
-          "DirectPropertyGet of '${node.target}' that isn't an"
-          " instance member.");
-    }
-  }
-
-  @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    visitChildren(node);
-    if (node.target == null) {
-      problem(node, "DirectPropertySet without target.");
-    }
-    if (!node.target.hasSetter) {
-      problem(node, "DirectPropertySet of '${node.target}' without setter.");
-    }
-    if (!node.target.isInstanceMember) {
-      problem(node, "DirectPropertySet of '${node.target}' that is static.");
-    }
-  }
-
-  @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    checkTargetedInvocation(node.target, node);
-    if (node.receiver == null) {
-      problem(node, "DirectMethodInvocation without receiver.");
-    }
-  }
-
-  @override
   visitConstructorInvocation(ConstructorInvocation node) {
     checkTargetedInvocation(node.target, node);
     if (node.target.enclosingClass.isAbstract) {
diff --git a/pkg/kernel/lib/visitor.dart b/pkg/kernel/lib/visitor.dart
index fadb45f..5cbe74c 100644
--- a/pkg/kernel/lib/visitor.dart
+++ b/pkg/kernel/lib/visitor.dart
@@ -19,15 +19,11 @@
   R visitVariableSet(VariableSet node) => defaultExpression(node);
   R visitPropertyGet(PropertyGet node) => defaultExpression(node);
   R visitPropertySet(PropertySet node) => defaultExpression(node);
-  R visitDirectPropertyGet(DirectPropertyGet node) => defaultExpression(node);
-  R visitDirectPropertySet(DirectPropertySet node) => defaultExpression(node);
   R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
   R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
   R visitStaticGet(StaticGet node) => defaultExpression(node);
   R visitStaticSet(StaticSet node) => defaultExpression(node);
   R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
-  R visitDirectMethodInvocation(DirectMethodInvocation node) =>
-      defaultExpression(node);
   R visitSuperMethodInvocation(SuperMethodInvocation node) =>
       defaultExpression(node);
   R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -148,15 +144,11 @@
   R visitVariableSet(VariableSet node) => defaultExpression(node);
   R visitPropertyGet(PropertyGet node) => defaultExpression(node);
   R visitPropertySet(PropertySet node) => defaultExpression(node);
-  R visitDirectPropertyGet(DirectPropertyGet node) => defaultExpression(node);
-  R visitDirectPropertySet(DirectPropertySet node) => defaultExpression(node);
   R visitSuperPropertyGet(SuperPropertyGet node) => defaultExpression(node);
   R visitSuperPropertySet(SuperPropertySet node) => defaultExpression(node);
   R visitStaticGet(StaticGet node) => defaultExpression(node);
   R visitStaticSet(StaticSet node) => defaultExpression(node);
   R visitMethodInvocation(MethodInvocation node) => defaultExpression(node);
-  R visitDirectMethodInvocation(DirectMethodInvocation node) =>
-      defaultExpression(node);
   R visitSuperMethodInvocation(SuperMethodInvocation node) =>
       defaultExpression(node);
   R visitStaticInvocation(StaticInvocation node) => defaultExpression(node);
@@ -667,10 +659,6 @@
   R visitVariableSet(VariableSet node, T arg) => defaultExpression(node, arg);
   R visitPropertyGet(PropertyGet node, T arg) => defaultExpression(node, arg);
   R visitPropertySet(PropertySet node, T arg) => defaultExpression(node, arg);
-  R visitDirectPropertyGet(DirectPropertyGet node, T arg) =>
-      defaultExpression(node, arg);
-  R visitDirectPropertySet(DirectPropertySet node, T arg) =>
-      defaultExpression(node, arg);
   R visitSuperPropertyGet(SuperPropertyGet node, T arg) =>
       defaultExpression(node, arg);
   R visitSuperPropertySet(SuperPropertySet node, T arg) =>
@@ -679,8 +667,6 @@
   R visitStaticSet(StaticSet node, T arg) => defaultExpression(node, arg);
   R visitMethodInvocation(MethodInvocation node, T arg) =>
       defaultExpression(node, arg);
-  R visitDirectMethodInvocation(DirectMethodInvocation node, T arg) =>
-      defaultExpression(node, arg);
   R visitSuperMethodInvocation(SuperMethodInvocation node, T arg) =>
       defaultExpression(node, arg);
   R visitStaticInvocation(StaticInvocation node, T arg) =>
diff --git a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
index bc84c87..7a55d99 100644
--- a/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
+++ b/pkg/kernel/test/text_serializer_from_kernel_nodes_test.dart
@@ -220,11 +220,10 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {dynamic field;} A x; */ x.{A::field};',
-          node: new ExpressionStatement(new DirectPropertyGet.byReference(
-              new VariableGet(x), field.reference)),
+          node: new ExpressionStatement(new PropertyGet.byReference(
+              new VariableGet(x), field.name, field.reference)),
           expectation: ''
-              '(expr (get-direct-prop (get-var "x^0" _)'
-              ' "package:foo/bar.dart::A::@fields::field"))',
+              '(expr (get-prop (get-var "x^0" _) (public "field")))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -249,11 +248,13 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {dynamic field;} A x; */ x.{A::field} = 42;',
-          node: new ExpressionStatement(new DirectPropertySet.byReference(
-              new VariableGet(x), field.reference, new IntLiteral(42))),
+          node: new ExpressionStatement(PropertySet.byReference(
+              new VariableGet(x),
+              field.name,
+              new IntLiteral(42),
+              field.reference)),
           expectation: ''
-              '(expr (set-direct-prop (get-var "x^0" _)'
-              ' "package:foo/bar.dart::A::@fields::field" (int 42)))',
+              '(expr (set-prop (get-var "x^0" _) (public "field") (int 42)))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
                 ..addBinder(x, nameClue: 'x')
@@ -280,11 +281,13 @@
           new VariableDeclaration('x', type: const DynamicType());
       return new TestCase<Statement>(
           name: '/* suppose A {foo() {...}} A x; */ x.{A::foo}();',
-          node: new ExpressionStatement(new DirectMethodInvocation.byReference(
-              new VariableGet(x), method.reference, new Arguments([]))),
+          node: new ExpressionStatement(new MethodInvocation.byReference(
+              new VariableGet(x),
+              method.name,
+              new Arguments([]),
+              method.reference)),
           expectation: ''
-              '(expr (invoke-direct-method (get-var "x^0" _)'
-              ' "package:foo/bar.dart::A::@methods::foo"'
+              '(expr (invoke-method (get-var "x^0" _) (public "foo")'
               ' () () ()))',
           makeSerializationState: () =>
               new SerializationState(new SerializationEnvironment(null)
@@ -522,7 +525,8 @@
     if (roundTripInput != testCase.expectation) {
       failures.add(''
           "* initial serialization for test '${testCase.name}'"
-          " gave output '${roundTripInput}'");
+          " gave output '${roundTripInput}'"
+          " but expected '${testCase.expectation}'");
     }
 
     TreeNode deserialized =
diff --git a/pkg/kernel/test/verify_test.dart b/pkg/kernel/test/verify_test.dart
index 905375c..0e5a207 100644
--- a/pkg/kernel/test/verify_test.dart
+++ b/pkg/kernel/test/verify_test.dart
@@ -57,7 +57,7 @@
       VariableDeclaration variable = test.makeVariable();
       test.addNode(LogicalExpression(
           new Let(variable, new VariableGet(variable)),
-          '&&',
+          LogicalExpressionOperator.AND,
           new VariableGet(variable)));
       return variable;
     },
@@ -236,7 +236,7 @@
     'Dangling field get',
     (TestHarness test) {
       Field orphan = new Field(new Name('foo'));
-      test.addNode(new DirectPropertyGet(new NullLiteral(), orphan));
+      test.addNode(new PropertyGet(new NullLiteral(), orphan.name, orphan));
       return orphan;
     },
     (Node node) => "Dangling reference to '$node', parent is: 'null'.",
diff --git a/pkg/kernel/tool/smoke_test_quick.dart b/pkg/kernel/tool/smoke_test_quick.dart
index 53cfae1..bf32ec3 100644
--- a/pkg/kernel/tool/smoke_test_quick.dart
+++ b/pkg/kernel/tool/smoke_test_quick.dart
@@ -11,7 +11,6 @@
 main(List<String> args) async {
   Stopwatch stopwatch = new Stopwatch()..start();
   List<Future> futures = new List<Future>();
-  futures.add(run("pkg/front_end/test/old_dill_suite.dart", ["--checkDill"]));
   futures.add(run("pkg/front_end/test/spelling_test_src_suite.dart",
       ["--", "spelling_test_src/kernel/..."]));
   await Future.wait(futures);
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index f79fbff..d80e12b 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 1.3.0-nullsafety.4
+
+* Introduce `@internal` to annotate elements that should not be used outside of
+  the package in which the element is declared.
+
+## 1.3.0-nullsafety.3
+
+* Allow 2.10 stable and 2.11.0 dev SDK versions.
+
 ## 1.3.0-nullsafety.2
 
 * Update for the 2.10 dev sdk.
diff --git a/pkg/meta/lib/meta.dart b/pkg/meta/lib/meta.dart
index 11652e1..c6dff3b 100644
--- a/pkg/meta/lib/meta.dart
+++ b/pkg/meta/lib/meta.dart
@@ -126,6 +126,20 @@
 ///   class that has this annotation is not immutable.
 const Immutable immutable = Immutable();
 
+/// Used to annotate a declaration which should only be used from within the
+/// package in which it is declared, and which should not be exposed from said
+/// package's public API.
+///
+/// Tools, such as the analyzer, can provide feedback if
+///
+/// * the declaration is declared in a package's public API, or is exposed from
+///   a package's public API, or
+/// * the declaration is private, an unnamed extension, a static member of a
+///   private class, mixin, or extension, a value of a private enum, or a
+///   constructor of a private class, or
+/// * the declaration is referenced outside the package in which it is declared.
+const _Internal internal = _Internal();
+
 /// Used to annotate a test framework function that runs a single test.
 ///
 /// Tools, such as IDEs, can show invocations of such function in a file
@@ -257,15 +271,15 @@
 /// * the member is referenced outside of the defining library.
 const _VisibleForOverriding visibleForOverriding = _VisibleForOverriding();
 
-/// Used to annotate a declaration was made public, so that it is more visible
-/// than otherwise necessary, to make code testable.
+/// Used to annotate a declaration that was made public, so that it is more
+/// visible than otherwise necessary, to make code testable.
 ///
 /// Tools, such as the analyzer, can provide feedback if
 ///
 /// * the annotation is associated with a declaration not in the `lib` folder
 ///   of a package, or a private declaration, or a declaration in an unnamed
 ///   static extension, or
-/// * the declaration is referenced outside of its the defining library or a
+/// * the declaration is referenced outside of its defining library or a
 ///   library which is in the `test` folder of the defining package.
 const _VisibleForTesting visibleForTesting = _VisibleForTesting();
 
@@ -326,6 +340,10 @@
   const _Factory();
 }
 
+class _Internal {
+  const _Internal();
+}
+
 class _IsTest {
   const _IsTest();
 }
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index dfad765..28a9847 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 1.3.0-nullsafety.2
+version: 1.3.0-nullsafety.4
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/meta
 description: >
  This library contains the declarations of annotations that developers can use
@@ -8,4 +8,4 @@
  to provide a better user experience.
 environment:
   # This must remain a tight constraint until nnbd is stable
-  sdk: '>=2.10.0-0 <2.10.0'
+  sdk: '>=2.10.0-0 <2.11.0'
diff --git a/pkg/native_stack_traces/analysis_options.yaml b/pkg/native_stack_traces/analysis_options.yaml
index 84a5e26..486705d 100644
--- a/pkg/native_stack_traces/analysis_options.yaml
+++ b/pkg/native_stack_traces/analysis_options.yaml
@@ -1 +1 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
+include: package:pedantic/analysis_options.1.9.0.yaml
diff --git a/pkg/native_stack_traces/bin/decode.dart b/pkg/native_stack_traces/bin/decode.dart
index 2458e16..9a7aee0 100644
--- a/pkg/native_stack_traces/bin/decode.dart
+++ b/pkg/native_stack_traces/bin/decode.dart
@@ -123,7 +123,7 @@
 Options specific to the find command:
 ${_findParser.usage}''';
 
-final _usages = <String, String>{
+final _usages = <String?, String>{
   null: _mainUsage,
   '': _mainUsage,
   'help': _helpUsage,
@@ -133,7 +133,7 @@
 
 const int _badUsageExitCode = 1;
 
-void errorWithUsage(String message, {String command}) {
+void errorWithUsage(String message, {String? command}) {
   print("Error: $message.\n");
   print(_usages[command]);
   io.exitCode = _badUsageExitCode;
@@ -156,7 +156,7 @@
   }
 }
 
-Dwarf _loadFromFile(String original, Function(String) usageError) {
+Dwarf? _loadFromFile(String? original, Function(String) usageError) {
   if (original == null) {
     usageError('must provide -d/--debug');
     return null;
@@ -178,7 +178,7 @@
   final bool forceHexadecimal = options['force_hexadecimal'];
 
   void usageError(String message) => errorWithUsage(message, command: 'find');
-  int parseIntAddress(String s) {
+  int? tryParseIntAddress(String s) {
     if (!forceHexadecimal && !s.startsWith("0x")) {
       final decimal = int.tryParse(s);
       if (decimal != null) return decimal;
@@ -186,11 +186,11 @@
     return int.tryParse(s.startsWith("0x") ? s.substring(2) : s, radix: 16);
   }
 
-  PCOffset convertAddress(StackTraceHeader header, String s) {
+  PCOffset? convertAddress(StackTraceHeader header, String s) {
     final parsedOffset = tryParseSymbolOffset(s, forceHexadecimal);
     if (parsedOffset != null) return parsedOffset;
 
-    final address = parseIntAddress(s);
+    final address = tryParseIntAddress(s);
     if (address != null) return header.offsetOf(address);
 
     return null;
@@ -209,20 +209,22 @@
 
   int vmStart = dwarf.vmStartAddress;
   if (options['vm_start'] != null) {
-    vmStart = parseIntAddress(options['vm_start']);
-    if (vmStart == null) {
+    final address = tryParseIntAddress(options['vm_start']);
+    if (address == null) {
       return usageError('could not parse VM start address '
           '${options['vm_start']}');
     }
+    vmStart = address;
   }
 
   int isolateStart = dwarf.isolateStartAddress;
   if (options['isolate_start'] != null) {
-    isolateStart = parseIntAddress(options['isolate_start']);
-    if (isolateStart == null) {
+    final address = tryParseIntAddress(options['isolate_start']);
+    if (address == null) {
       return usageError('could not parse isolate start address '
           '${options['isolate_start']}');
     }
+    isolateStart = address;
   }
 
   final header = StackTraceHeader(isolateStart, vmStart);
diff --git a/pkg/native_stack_traces/lib/src/convert.dart b/pkg/native_stack_traces/lib/src/convert.dart
index 8f81c17..b6d96b4 100644
--- a/pkg/native_stack_traces/lib/src/convert.dart
+++ b/pkg/native_stack_traces/lib/src/convert.dart
@@ -27,11 +27,11 @@
 //
 // Returns a new [StackTraceHeader] if [line] contains the needed header
 // information, otherwise returns `null`.
-StackTraceHeader _parseInstructionsLine(String line) {
+StackTraceHeader? _parseInstructionsLine(String line) {
   final match = _headerEndRE.firstMatch(line);
   if (match == null) return null;
-  final isolateAddr = int.parse(match[1], radix: 16);
-  final vmAddr = int.parse(match[2], radix: 16);
+  final isolateAddr = int.parse(match[1]!, radix: 16);
+  final vmAddr = int.parse(match[2]!, radix: 16);
   return StackTraceHeader(isolateAddr, vmAddr);
 }
 
@@ -81,12 +81,12 @@
 /// any hexdecimal digits will be parsed as decimal.
 ///
 /// Returns null if the string is not of the expected format.
-PCOffset tryParseSymbolOffset(String s, [bool forceHexadecimal = false]) {
+PCOffset? tryParseSymbolOffset(String s, [bool forceHexadecimal = false]) {
   final match = _symbolOffsetRE.firstMatch(s);
   if (match == null) return null;
-  final symbolString = match.namedGroup('symbol');
-  final offsetString = match.namedGroup('offset');
-  int offset;
+  final symbolString = match.namedGroup('symbol')!;
+  final offsetString = match.namedGroup('offset')!;
+  int? offset;
   if (!forceHexadecimal && !offsetString.startsWith("0x")) {
     offset = int.tryParse(offsetString);
   }
@@ -108,9 +108,9 @@
   return null;
 }
 
-PCOffset _retrievePCOffset(StackTraceHeader header, RegExpMatch match) {
+PCOffset? _retrievePCOffset(StackTraceHeader? header, RegExpMatch? match) {
   if (match == null) return null;
-  final restString = match.namedGroup('rest');
+  final restString = match.namedGroup('rest')!;
   // Try checking for symbol information first, since we don't need the header
   // information to translate it.
   if (restString.isNotEmpty) {
@@ -120,8 +120,8 @@
   // If we're parsing the absolute address, we can only convert it into
   // a PCOffset if we saw the instructions line of the stack trace header.
   if (header != null) {
-    final addressString = match.namedGroup('absolute');
-    final address = int.tryParse(addressString, radix: 16);
+    final addressString = match.namedGroup('absolute')!;
+    final address = int.parse(addressString, radix: 16);
     return header.offsetOf(address);
   }
   // If all other cases failed, check for a virtual address. Until this package
@@ -130,7 +130,7 @@
   // debugging information, the other methods should be tried first.
   final virtualString = match.namedGroup('virtual');
   if (virtualString != null) {
-    final address = int.tryParse(virtualString, radix: 16);
+    final address = int.parse(virtualString, radix: 16);
     return PCOffset(address, InstructionsSection.none);
   }
   return null;
@@ -138,7 +138,7 @@
 
 /// The [PCOffset]s for frames of the non-symbolic stack traces in [lines].
 Iterable<PCOffset> collectPCOffsets(Iterable<String> lines) sync* {
-  StackTraceHeader header;
+  StackTraceHeader? header;
   for (var line in lines) {
     final parsedHeader = _parseInstructionsLine(line);
     if (parsedHeader != null) {
@@ -184,7 +184,7 @@
 
   Stream<String> bind(Stream<String> stream) async* {
     int depth = 0;
-    StackTraceHeader header;
+    StackTraceHeader? header;
     await for (final line in stream) {
       final parsedHeader = _parseInstructionsLine(line);
       if (parsedHeader != null) {
@@ -207,7 +207,7 @@
       if (callInfo.isEmpty) continue;
       // Output the lines for the symbolic frame with the prefix found on the
       // original non-symbolic frame line.
-      final prefix = line.substring(0, lineMatch.start);
+      final prefix = line.substring(0, lineMatch!.start);
       for (final call in callInfo) {
         yield prefix + _stackTracePiece(call, depth++);
       }
diff --git a/pkg/native_stack_traces/lib/src/dwarf.dart b/pkg/native_stack_traces/lib/src/dwarf.dart
index fd0911b..e8d7ef1 100644
--- a/pkg/native_stack_traces/lib/src/dwarf.dart
+++ b/pkg/native_stack_traces/lib/src/dwarf.dart
@@ -122,7 +122,7 @@
 
   _Attribute._(this.name, this.form);
 
-  static _Attribute fromReader(Reader reader) {
+  static _Attribute? fromReader(Reader reader) {
     final nameInt = reader.readLEB128EncodedInteger();
     final formInt = reader.readLEB128EncodedInteger();
     if (nameInt == 0 && formInt == 0) return null;
@@ -132,7 +132,7 @@
     if (!_attributeForms.containsKey(formInt)) {
       throw FormatException("Unexpected DW_FORM value 0x${paddedHex(formInt)}");
     }
-    return _Attribute._(_attributeNames[nameInt], _attributeForms[formInt]);
+    return _Attribute._(_attributeNames[nameInt]!, _attributeForms[formInt]!);
   }
 
   Object read(Reader reader, CompilationUnitHeader header) {
@@ -148,25 +148,24 @@
       case _AttributeForm.reference4:
         return reader.readBytes(4);
     }
-    return null;
   }
 
-  String valueToString(Object value, [CompilationUnit unit]) {
+  String valueToString(Object value, [CompilationUnit? unit]) {
     switch (form) {
       case _AttributeForm.string:
         return value as String;
       case _AttributeForm.address:
-        return '0x' + paddedHex(value as int, unit?.header?.addressSize ?? 0);
+        return '0x' + paddedHex(value as int, unit?.header.addressSize ?? 0);
       case _AttributeForm.sectionOffset:
         return paddedHex(value as int, 4);
       case _AttributeForm.constant:
         return value.toString();
       case _AttributeForm.reference4:
-        final unresolvedValue = paddedHex(value as int, 4);
-        final name = unit?.nameOfOrigin(value as int) ?? "(unresolved)";
+        final intValue = value as int;
+        final unresolvedValue = paddedHex(intValue, 4);
+        final name = unit?.nameOfOrigin(intValue) ?? "<unresolved>";
         return '0x${unresolvedValue} (origin: ${name})';
     }
-    return "<unknown>";
   }
 }
 
@@ -182,14 +181,14 @@
   static const _DW_CHILDREN_no = 0x00;
   static const _DW_CHILDREN_yes = 0x01;
 
-  static _Abbreviation fromReader(Reader reader) {
+  static _Abbreviation? fromReader(Reader reader) {
     final code = reader.readLEB128EncodedInteger();
     if (code == 0) return null;
     final tagInt = reader.readLEB128EncodedInteger();
     if (!_tags.containsKey(tagInt)) {
       throw FormatException("Unexpected DW_TAG value 0x${paddedHex(tagInt)}");
     }
-    final tag = _tags[tagInt];
+    final tag = _tags[tagInt]!;
     final childrenByte = reader.readByte();
     if (childrenByte != _DW_CHILDREN_no && childrenByte != _DW_CHILDREN_yes) {
       throw FormatException("Expected DW_CHILDREN_no or DW_CHILDREN_yes: "
@@ -210,9 +209,9 @@
     for (final attribute in attributes) {
       buffer
         ..write('      ')
-        ..write(_attributeNameStrings[attribute.name])
+        ..write(_attributeNameStrings[attribute.name]!)
         ..write(': ')
-        ..writeln(_attributeFormStrings[attribute.form]);
+        ..writeln(_attributeFormStrings[attribute.form]!);
     }
   }
 
@@ -230,9 +229,9 @@
   _AbbreviationsTable._(this._abbreviations);
 
   bool containsKey(int code) => _abbreviations.containsKey(code);
-  _Abbreviation operator [](int code) => _abbreviations[code];
+  _Abbreviation? operator [](int code) => _abbreviations[code];
 
-  static _AbbreviationsTable fromReader(Reader reader) {
+  static _AbbreviationsTable? fromReader(Reader reader) {
     final abbreviations = Map.fromEntries(reader
         .readRepeated(_Abbreviation.fromReader)
         .map((abbr) => MapEntry(abbr.code, abbr)));
@@ -241,14 +240,14 @@
 
   void writeToStringBuffer(StringBuffer buffer) {
     buffer..writeln('Abbreviations table:')..writeln();
-    for (final key in _abbreviations.keys) {
+    _abbreviations.forEach((key, abbreviation) {
       buffer
         ..write('  ')
         ..write(key)
         ..writeln(':');
-      _abbreviations[key].writeToStringBuffer(buffer);
+      abbreviation.writeToStringBuffer(buffer);
       buffer..writeln();
-    }
+    });
   }
 
   @override
@@ -268,7 +267,7 @@
 
   DebugInformationEntry._(this.code, this.attributes, this.children);
 
-  static DebugInformationEntry fromReader(
+  static DebugInformationEntry? fromReader(
       Reader reader, CompilationUnitHeader header) {
     final code = reader.readLEB128EncodedInteger();
     // DIEs with an abbreviation table index of 0 are list end markers.
@@ -276,81 +275,83 @@
     if (!header.abbreviations.containsKey(code)) {
       throw FormatException("Unknown abbreviation code 0x${paddedHex(code)}");
     }
-    final abbreviation = header.abbreviations[code];
+    final abbreviation = header.abbreviations[code]!;
     final attributes = <_Attribute, Object>{};
     for (final attribute in abbreviation.attributes) {
       attributes[attribute] = attribute.read(reader, header);
     }
-    Map<int, DebugInformationEntry> children;
+    final children = <int, DebugInformationEntry>{};
     if (abbreviation.children) {
-      children = Map.fromEntries(reader.readRepeatedWithOffsets(
+      children.addEntries(reader.readRepeatedWithOffsets(
           (r) => DebugInformationEntry.fromReader(r, header),
           absolute: true));
     }
-    assert((children != null) == abbreviation.children);
     return DebugInformationEntry._(code, attributes, children);
   }
 
-  _Attribute _namedAttribute(_AttributeName name) => attributes.keys
-      .firstWhere((_Attribute k) => k.name == name, orElse: () => null);
+  _Attribute? _namedAttribute(_AttributeName name) {
+    for (final attribute in attributes.keys) {
+      if (attribute.name == name) {
+        return attribute;
+      }
+    }
+    return null;
+  }
 
   bool containsKey(_AttributeName name) => _namedAttribute(name) != null;
 
-  Object operator [](_AttributeName name) => attributes[_namedAttribute(name)];
+  Object? operator [](_AttributeName name) => attributes[_namedAttribute(name)];
 
-  int get abstractOrigin => this[_AttributeName.abstractOrigin] as int;
+  int? get sectionOffset => this[_AttributeName.statementList] as int?;
 
-  int get lowPC => this[_AttributeName.lowProgramCounter] as int;
+  int? get abstractOrigin => this[_AttributeName.abstractOrigin] as int?;
 
-  int get highPC => this[_AttributeName.highProgramCounter] as int;
+  int? get lowPC => this[_AttributeName.lowProgramCounter] as int?;
+
+  int? get highPC => this[_AttributeName.highProgramCounter] as int?;
 
   bool containsPC(int virtualAddress) =>
-      lowPC != null && lowPC <= virtualAddress && virtualAddress < highPC;
+      (lowPC ?? 0) <= virtualAddress && virtualAddress < (highPC ?? -1);
 
-  String get name => this[_AttributeName.name] as String;
+  String? get name => this[_AttributeName.name] as String?;
 
-  int get callFileIndex => this[_AttributeName.callFile] as int;
+  int? get callFileIndex => this[_AttributeName.callFile] as int?;
 
-  int get callLine => this[_AttributeName.callLine] as int;
+  int? get callLine => this[_AttributeName.callLine] as int?;
 
-  // We don't assume that call columns are present for backwards compatibility.
-  int get callColumn => containsKey(_AttributeName.callColumn)
-      ? this[_AttributeName.callColumn] as int
-      : 0;
+  int? get callColumn => this[_AttributeName.callColumn] as int?;
 
-  List<CallInfo> callInfo(
+  List<CallInfo>? callInfo(
       CompilationUnit unit, LineNumberProgram lineNumberProgram, int address) {
     String callFilename(int index) =>
-        lineNumberProgram.header.filesInfo[index].name;
+        lineNumberProgram.header.filesInfo[index]?.name ?? '<unknown file>';
     if (!containsPC(address)) return null;
 
-    final tag = unit.header.abbreviations[code].tag;
+    final tag = unit.header.abbreviations[code]!.tag;
     final inlined = tag == _Tag.inlinedSubroutine;
-    if (children != null) {
-      for (final child in children.values) {
-        final callInfo = child.callInfo(unit, lineNumberProgram, address);
-        if (callInfo == null) continue;
+    for (final child in children.values) {
+      final callInfo = child.callInfo(unit, lineNumberProgram, address);
+      if (callInfo == null) continue;
 
-        if (tag == _Tag.compileUnit) return callInfo;
+      if (tag == _Tag.compileUnit) return callInfo;
 
-        return callInfo
-          ..add(DartCallInfo(
-              function: unit.nameOfOrigin(abstractOrigin),
-              inlined: inlined,
-              filename: callFilename(child.callFileIndex),
-              line: child.callLine,
-              column: child.callColumn));
-      }
+      return callInfo
+        ..add(DartCallInfo(
+            function: unit.nameOfOrigin(abstractOrigin ?? -1),
+            inlined: inlined,
+            filename: callFilename(child.callFileIndex ?? -1),
+            line: child.callLine ?? 0,
+            column: child.callColumn ?? 0));
     }
 
     if (tag == _Tag.compileUnit) return null;
 
-    final filename = lineNumberProgram.filename(address);
-    final line = lineNumberProgram.lineNumber(address);
-    final column = lineNumberProgram.column(address);
+    final filename = lineNumberProgram.filename(address)!;
+    final line = lineNumberProgram.lineNumber(address)!;
+    final column = lineNumberProgram.column(address)!;
     return [
       DartCallInfo(
-          function: unit.nameOfOrigin(abstractOrigin),
+          function: unit.nameOfOrigin(abstractOrigin ?? -1),
           inlined: inlined,
           filename: filename,
           line: line,
@@ -359,21 +360,21 @@
   }
 
   void writeToStringBuffer(StringBuffer buffer,
-      {CompilationUnit unit, String indent = ''}) {
+      {CompilationUnit? unit, String indent = ''}) {
     buffer
       ..write(indent)
       ..write('Abbreviation code: ')
       ..write(code)
       ..writeln('):');
-    for (final attribute in attributes.keys) {
+    attributes.forEach((attribute, value) {
       buffer
         ..write(indent)
         ..write('  ')
-        ..write(_attributeNameStrings[attribute.name])
+        ..write(_attributeNameStrings[attribute.name]!)
         ..write(' => ')
-        ..writeln(attribute.valueToString(attributes[attribute], unit));
-    }
-    if (children != null) {
+        ..writeln(attribute.valueToString(value, unit));
+    });
+    if (children.isNotEmpty) {
       buffer
         ..write(indent)
         ..write('Children (')
@@ -413,7 +414,7 @@
   CompilationUnitHeader._(this.size, this.version, this.abbreviationsOffset,
       this.addressSize, this.abbreviations);
 
-  static CompilationUnitHeader fromReader(
+  static CompilationUnitHeader? fromReader(
       Reader reader, Map<int, _AbbreviationsTable> abbreviationsTables) {
     final size = _initialLengthValue(reader);
     // An empty unit is an ending marker.
@@ -423,13 +424,14 @@
       throw FormatException("Expected DWARF version 2, got $version");
     }
     final abbreviationsOffset = reader.readBytes(4);
-    if (!abbreviationsTables.containsKey(abbreviationsOffset)) {
+    final abbreviationsTable = abbreviationsTables[abbreviationsOffset];
+    if (abbreviationsTable == null) {
       throw FormatException("No abbreviation table found for offset "
           "0x${paddedHex(abbreviationsOffset, 4)}");
     }
     final addressSize = reader.readByte();
-    return CompilationUnitHeader._(size, version, abbreviationsOffset,
-        addressSize, abbreviationsTables[abbreviationsOffset]);
+    return CompilationUnitHeader._(
+        size, version, abbreviationsOffset, addressSize, abbreviationsTable);
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
@@ -461,7 +463,7 @@
 
   CompilationUnit._(this.header, this.referenceTable);
 
-  static CompilationUnit fromReader(
+  static CompilationUnit? fromReader(
       Reader reader, Map<int, _AbbreviationsTable> abbreviationsTables) {
     final header =
         CompilationUnitHeader.fromReader(reader, abbreviationsTables);
@@ -477,25 +479,21 @@
   static void _addChildEntries(Map<int, DebugInformationEntry> table) {
     final workList = Queue<MapEntry<int, DebugInformationEntry>>();
     for (final die in table.values) {
-      if (die.children != null) {
-        workList.addAll(die.children.entries);
-      }
+      workList.addAll(die.children.entries);
     }
     while (workList.isNotEmpty) {
       final kv = workList.removeFirst();
       final offset = kv.key;
       final child = kv.value;
       table[offset] = child;
-      if (child.children != null) {
-        workList.addAll(child.children.entries);
-      }
+      workList.addAll(child.children.entries);
     }
   }
 
-  Iterable<CallInfo> callInfo(LineNumberInfo lineNumberInfo, int address) {
+  Iterable<CallInfo>? callInfo(LineNumberInfo lineNumberInfo, int address) {
     for (final die in referenceTable.values) {
-      final lineNumberProgram =
-          lineNumberInfo[die[_AttributeName.statementList]];
+      final lineNumberProgram = lineNumberInfo[die.sectionOffset ?? -1];
+      if (lineNumberProgram == null) continue;
       final callInfo = die.callInfo(this, lineNumberProgram, address);
       if (callInfo != null) return callInfo;
     }
@@ -503,26 +501,24 @@
   }
 
   String nameOfOrigin(int offset) {
-    if (!referenceTable.containsKey(offset)) {
+    final origin = referenceTable[offset];
+    if (origin == null) {
       throw ArgumentError(
           "${paddedHex(offset)} is not the offset of an abbreviated unit");
     }
-    final origin = referenceTable[offset];
-    assert(origin.containsKey(_AttributeName.name));
     return origin[_AttributeName.name] as String;
   }
 
   void writeToStringBuffer(StringBuffer buffer) {
     header.writeToStringBuffer(buffer);
-    for (final offset in referenceTable.keys) {
-      final die = referenceTable[offset];
+    referenceTable.forEach((offset, die) {
       buffer
         ..write('Debug information entry at offset 0x')
         ..write(paddedHex(offset))
         ..writeln(':');
       die.writeToStringBuffer(buffer, unit: this);
       buffer.writeln();
-    }
+    });
   }
 
   @override
@@ -548,7 +544,7 @@
     return DebugInfo._(units);
   }
 
-  Iterable<CallInfo> callInfo(LineNumberInfo lineNumberInfo, int address) {
+  Iterable<CallInfo>? callInfo(LineNumberInfo lineNumberInfo, int address) {
     for (final unit in units) {
       final callInfo = unit.callInfo(lineNumberInfo, address);
       if (callInfo != null) return callInfo;
@@ -578,7 +574,7 @@
 
   FileEntry._(this.name, this.directoryIndex, this.lastModified, this.size);
 
-  static FileEntry fromReader(Reader reader) {
+  static FileEntry? fromReader(Reader reader) {
     final name = reader.readNullTerminatedString();
     // An empty null-terminated string marks the table end.
     if (name == "") return null;
@@ -611,7 +607,7 @@
   }
 
   bool containsKey(int index) => _files.containsKey(index);
-  FileEntry operator [](int index) => _files[index];
+  FileEntry? operator [](int index) => _files[index];
 
   void writeToStringBuffer(StringBuffer buffer) {
     if (_files.isEmpty) {
@@ -654,17 +650,17 @@
       ..writeln(nameHeader);
 
     for (final index in _files.keys) {
-      buffer..write(" ")..write(indexStrings[index].padRight(maxIndexLength));
+      buffer..write(" ")..write(indexStrings[index]!.padRight(maxIndexLength));
       buffer
         ..write(" ")
-        ..write(dirIndexStrings[index].padRight(maxDirIndexLength));
+        ..write(dirIndexStrings[index]!.padRight(maxDirIndexLength));
       buffer
         ..write(" ")
-        ..write(modifiedStrings[index].padRight(maxModifiedLength));
-      buffer..write(" ")..write(sizeStrings[index].padRight(maxSizeLength));
+        ..write(modifiedStrings[index]!.padRight(maxModifiedLength));
+      buffer..write(" ")..write(sizeStrings[index]!.padRight(maxSizeLength));
       buffer
         ..write(" ")
-        ..writeln(_files[index].name);
+        ..writeln(_files[index]!.name);
     }
   }
 
@@ -679,13 +675,13 @@
 class LineNumberState {
   final defaultIsStatement;
 
-  int address;
-  int fileIndex;
-  int line;
-  int column;
-  bool isStatement;
-  bool basicBlock;
-  bool endSequence;
+  late int address;
+  late int fileIndex;
+  late int line;
+  late int column;
+  late bool isStatement;
+  late bool basicBlock;
+  late bool endSequence;
 
   LineNumberState(this.defaultIsStatement) {
     reset();
@@ -749,7 +745,7 @@
       this.includeDirectories,
       this.filesInfo);
 
-  static LineNumberProgramHeader fromReader(Reader reader) {
+  static LineNumberProgramHeader? fromReader(Reader reader) {
     final size = _initialLengthValue(reader);
     if (size == 0) return null;
     final version = reader.readBytes(2);
@@ -861,7 +857,7 @@
 
   LineNumberProgram._(this.header, this.calculatedMatrix) : cachedLookups = {};
 
-  static LineNumberProgram fromReader(Reader reader) {
+  static LineNumberProgram? fromReader(Reader reader) {
     final header = LineNumberProgramHeader.fromReader(reader);
     if (header == null) return null;
     final calculatedMatrix = _readOpcodes(reader, header).toList();
@@ -955,14 +951,14 @@
         address < calculatedMatrix.last.address;
   }
 
-  LineNumberState operator [](int address) {
+  LineNumberState? operator [](int address) {
     if (cachedLookups.containsKey(address)) return cachedLookups[address];
 
     if (!containsKey(address)) return null;
 
     // Since the addresses are generated in increasing order, we can do a
     // binary search to find the right state.
-    assert(calculatedMatrix != null && calculatedMatrix.isNotEmpty);
+    assert(calculatedMatrix.isNotEmpty);
     var minIndex = 0;
     var maxIndex = calculatedMatrix.length - 1;
     while (true) {
@@ -983,12 +979,12 @@
     }
   }
 
-  String filename(int address) =>
-      header.filesInfo[this[address]?.fileIndex]?.name;
+  String? filename(int address) =>
+      header.filesInfo[this[address]?.fileIndex ?? -1]?.name;
 
-  int lineNumber(int address) => this[address]?.line;
+  int? lineNumber(int address) => this[address]?.line;
 
-  int column(int address) => this[address]?.column;
+  int? column(int address) => this[address]?.column;
 
   void writeToStringBuffer(StringBuffer buffer) {
     header.writeToStringBuffer(buffer);
@@ -1019,15 +1015,15 @@
   }
 
   bool containsKey(int address) => programs.containsKey(address);
-  LineNumberProgram operator [](int address) => programs[address];
+  LineNumberProgram? operator [](int address) => programs[address];
 
   void writeToStringBuffer(StringBuffer buffer) {
-    for (final offset in programs.keys) {
+    programs.forEach((offset, program) {
       buffer
         ..write('Line number program @ 0x')
         ..writeln(paddedHex(offset));
-      programs[offset].writeToStringBuffer(buffer);
-    }
+      program.writeToStringBuffer(buffer);
+    });
   }
 
   String toString() {
@@ -1068,10 +1064,10 @@
 
   DartCallInfo(
       {this.inlined = false,
-      this.function,
-      this.filename,
-      this.line,
-      this.column});
+      required this.function,
+      required this.filename,
+      required this.line,
+      required this.column});
 
   @override
   bool get isInternal => false;
@@ -1122,7 +1118,7 @@
   final String name;
   final int offset;
 
-  StubCallInfo({this.name, this.offset});
+  StubCallInfo({required this.name, required this.offset});
 
   @override
   int get hashCode => _hashFinish(
@@ -1156,9 +1152,11 @@
 
   /// The call information found for this [PCOffset] in [dwarf].
   ///
+  /// Returns null if the PCOffset is invalid for the given DWARF information.
+  ///
   /// If [includeInternalFrames] is false, then only information corresponding
   /// to user or library code is returned.
-  Iterable<CallInfo> callInfoFrom(Dwarf dwarf,
+  Iterable<CallInfo>? callInfoFrom(Dwarf dwarf,
           {bool includeInternalFrames = false}) =>
       dwarf.callInfoFor(dwarf.virtualAddressOf(this),
           includeInternalFrames: includeInternalFrames);
@@ -1180,7 +1178,7 @@
 /// The DWARF debugging information for a Dart snapshot.
 class Dwarf {
   final Elf _elf;
-  final Map<int, _AbbreviationsTable> _abbreviationTables;
+  final Map<int, _AbbreviationsTable> _abbreviationsTables;
   final DebugInfo _debugInfo;
   final LineNumberInfo _lineNumberInfo;
 
@@ -1192,13 +1190,13 @@
   /// DWARF information.
   final int isolateStartAddress;
 
-  Dwarf._(this._elf, this._abbreviationTables, this._debugInfo,
+  Dwarf._(this._elf, this._abbreviationsTables, this._debugInfo,
       this._lineNumberInfo, this.vmStartAddress, this.isolateStartAddress);
 
   /// Attempts to load the DWARF debugging information from the reader.
   ///
   /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
-  static Dwarf fromReader(Reader reader) {
+  static Dwarf? fromReader(Reader reader) {
     // Currently, the only DWARF-containing format we recognize is ELF.
     final elf = Elf.fromReader(reader);
     if (elf == null) return null;
@@ -1208,18 +1206,19 @@
   /// Attempts to load the DWARF debugging information from the given bytes.
   ///
   /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
-  static Dwarf fromBytes(Uint8List bytes) =>
+  static Dwarf? fromBytes(Uint8List bytes) =>
       Dwarf.fromReader(Reader.fromTypedData(bytes));
 
   /// Attempts to load the DWARF debugging information from the file at [path].
   ///
   /// Returns a [Dwarf] object if the load succeeds, otherwise returns null.
-  static Dwarf fromFile(String path) => Dwarf.fromReader(Reader.fromFile(path));
+  static Dwarf? fromFile(String path) =>
+      Dwarf.fromReader(Reader.fromFile(path));
 
   static Dwarf _loadSectionsFromElf(Reader reader, Elf elf) {
     final abbrevSection = elf.namedSections(".debug_abbrev").single;
     final abbrevReader = abbrevSection.refocusedCopy(reader);
-    final abbreviationTables = Map.fromEntries(
+    final abbreviationsTables = Map.fromEntries(
         abbrevReader.readRepeatedWithOffsets(_AbbreviationsTable.fromReader));
 
     final lineNumberSection = elf.namedSections(".debug_line").single;
@@ -1228,7 +1227,7 @@
 
     final infoSection = elf.namedSections(".debug_info").single;
     final debugInfo = DebugInfo.fromReader(
-        infoSection.refocusedCopy(reader), abbreviationTables);
+        infoSection.refocusedCopy(reader), abbreviationsTables);
 
     final vmStartSymbol = elf.dynamicSymbolFor(constants.vmSymbolName);
     if (vmStartSymbol == null) {
@@ -1245,29 +1244,33 @@
     }
     final isolateStartAddress = isolateStartSymbol.value;
 
-    return Dwarf._(elf, abbreviationTables, debugInfo, lineNumberInfo,
+    return Dwarf._(elf, abbreviationsTables, debugInfo, lineNumberInfo,
         vmStartAddress, isolateStartAddress);
   }
 
   /// The build ID for the debugging information.
   ///
   /// Returns null if there is no build ID information recorded.
-  String get buildId {
+  String? get buildId {
     final sections = _elf.namedSections(constants.buildIdSectionName);
     if (sections.isEmpty) return null;
-    final Note note = sections.single;
+    final note = sections.single as Note;
     if (note.type != constants.buildIdNoteType) return null;
     if (note.name != constants.buildIdNoteName) return null;
-    return note.description.map((i) => i.toRadixString(16)).join();
+    return note.description
+        .map((i) => i.toRadixString(16).padLeft(2, '0'))
+        .join();
   }
 
   /// The call information for the given virtual address. There may be
   /// multiple [CallInfo] objects returned for a single virtual address when
   /// code has been inlined.
   ///
+  /// Returns null if the given address is invalid for the DWARF information.
+  ///
   /// If [includeInternalFrames] is false, then only information corresponding
   /// to user or library code is returned.
-  Iterable<CallInfo> callInfoFor(int address,
+  Iterable<CallInfo>? callInfoFor(int address,
       {bool includeInternalFrames = false}) {
     var calls = _debugInfo.callInfo(_lineNumberInfo, address);
     if (calls == null) {
@@ -1304,10 +1307,10 @@
       ..writeln('         Abbreviation tables')
       ..writeln('----------------------------------------')
       ..writeln();
-    for (final offset in _abbreviationTables.keys) {
+    _abbreviationsTables.forEach((offset, table) {
       buffer..write('(Offset ')..write(paddedHex(offset, 4))..write(') ');
-      _abbreviationTables[offset].writeToStringBuffer(buffer);
-    }
+      table.writeToStringBuffer(buffer);
+    });
     buffer
       ..writeln('----------------------------------------')
       ..writeln('          Debug information')
diff --git a/pkg/native_stack_traces/lib/src/elf.dart b/pkg/native_stack_traces/lib/src/elf.dart
index b0c7c54..e92fecd 100644
--- a/pkg/native_stack_traces/lib/src/elf.dart
+++ b/pkg/native_stack_traces/lib/src/elf.dart
@@ -95,7 +95,7 @@
       this.sectionHeaderEntrySize,
       this.sectionHeaderStringsIndex);
 
-  static ElfHeader fromReader(Reader reader) {
+  static ElfHeader? fromReader(Reader reader) {
     final fileSize = reader.length;
 
     for (final sigByte in _ELFMAG.codeUnits) {
@@ -275,10 +275,11 @@
       this.paddr, this.filesz, this.memsz, this.align, this.wordSize);
 
   static ProgramHeaderEntry fromReader(Reader reader) {
-    assert(reader.wordSize == 4 || reader.wordSize == 8);
+    int wordSize = reader.wordSize;
+    assert(wordSize == 4 || wordSize == 8);
     final type = _readElfWord(reader);
-    int flags;
-    if (reader.wordSize == 8) {
+    late int flags;
+    if (wordSize == 8) {
       flags = _readElfWord(reader);
     }
     final offset = _readElfOffset(reader);
@@ -286,12 +287,12 @@
     final paddr = _readElfAddress(reader);
     final filesz = _readElfNative(reader);
     final memsz = _readElfNative(reader);
-    if (reader.wordSize == 4) {
+    if (wordSize == 4) {
       flags = _readElfWord(reader);
     }
     final align = _readElfNative(reader);
-    return ProgramHeaderEntry._(type, flags, offset, vaddr, paddr, filesz,
-        memsz, align, reader.wordSize);
+    return ProgramHeaderEntry._(
+        type, flags, offset, vaddr, paddr, filesz, memsz, align, wordSize);
   }
 
   static const _typeStrings = <int, String>{
@@ -301,12 +302,8 @@
     _PT_PHDR: "PT_PHDR",
   };
 
-  static String _typeToString(int type) {
-    if (_typeStrings.containsKey(type)) {
-      return _typeStrings[type];
-    }
-    return "unknown (${paddedHex(type, 4)})";
-  }
+  static String _typeToString(int type) =>
+      _typeStrings[type] ?? "unknown (${paddedHex(type, 4)})";
 
   void writeToStringBuffer(StringBuffer buffer) {
     buffer
@@ -384,7 +381,7 @@
   final int addrAlign;
   final int entrySize;
   final int wordSize;
-  String _cachedName;
+  late String name;
 
   SectionHeaderEntry._(
       this.nameIndex,
@@ -426,11 +423,9 @@
   static const _SHT_DYNSYM = 11;
 
   void setName(StringTable nameTable) {
-    _cachedName = nameTable[nameIndex];
+    name = nameTable[nameIndex]!;
   }
 
-  String get name => _cachedName != null ? _cachedName : '<${nameIndex}>';
-
   static const _typeStrings = <int, String>{
     _SHT_NULL: "SHT_NULL",
     _SHT_PROGBITS: "SHT_PROGBITS",
@@ -443,25 +438,17 @@
     _SHT_DYNSYM: "SHT_DYNSYM",
   };
 
-  static String _typeToString(int type) {
-    if (_typeStrings.containsKey(type)) {
-      return _typeStrings[type];
-    }
-    return "unknown (${paddedHex(type, 4)})";
-  }
+  static String _typeToString(int type) =>
+      _typeStrings[type] ?? "unknown (${paddedHex(type, 4)})";
 
   void writeToStringBuffer(StringBuffer buffer) {
     buffer.write('Name: ');
-    if (_cachedName != null) {
-      buffer
-        ..write('"')
-        ..write(name)
-        ..write('" (@ ')
-        ..write(nameIndex)
-        ..writeln(')');
-    } else {
-      buffer.writeln(name);
-    }
+    buffer
+      ..write('"')
+      ..write(name)
+      ..write('" (@ ')
+      ..write(nameIndex)
+      ..writeln(')');
     buffer
       ..write('Type: ')
       ..writeln(_typeToString(type))
@@ -629,7 +616,7 @@
 
 /// A map from table offsets to strings, used to store names of ELF objects.
 class StringTable extends Section {
-  final _entries;
+  final Map<int, String> _entries;
 
   StringTable._(entry, this._entries) : super._(entry);
 
@@ -640,7 +627,7 @@
     return StringTable._(entry, entries);
   }
 
-  String operator [](int index) => _entries[index];
+  String? operator [](int index) => _entries[index];
   bool containsKey(int index) => _entries.containsKey(index);
 
   @override
@@ -685,40 +672,40 @@
   final int sectionIndex;
   final int value;
   final int size;
-
   final int _wordSize;
-
-  String name;
+  late String name;
 
   Symbol._(this.nameIndex, this.info, this.other, this.sectionIndex, this.value,
       this.size, this._wordSize);
 
   static Symbol fromReader(Reader reader) {
+    final wordSize = reader.wordSize;
     final nameIndex = _readElfWord(reader);
-    int info;
-    int other;
-    int sectionIndex;
-    if (reader.wordSize == 8) {
+    late int info;
+    late int other;
+    late int sectionIndex;
+    if (wordSize == 8) {
       info = reader.readByte();
       other = reader.readByte();
       sectionIndex = _readElfSection(reader);
     }
     final value = _readElfAddress(reader);
     final size = _readElfNative(reader);
-    if (reader.wordSize == 4) {
+    if (wordSize == 4) {
       info = reader.readByte();
       other = reader.readByte();
       sectionIndex = _readElfSection(reader);
     }
     return Symbol._(
-        nameIndex, info, other, sectionIndex, value, size, reader.wordSize);
+        nameIndex, info, other, sectionIndex, value, size, wordSize);
   }
 
   void _cacheNameFromStringTable(StringTable table) {
-    if (!table.containsKey(nameIndex)) {
+    final nameFromTable = table[nameIndex];
+    if (nameFromTable == null) {
       throw FormatException("Index $nameIndex not found in string table");
     }
-    name = table[nameIndex];
+    name = nameFromTable;
   }
 
   SymbolBinding get bind => SymbolBinding.values[info >> 4];
@@ -726,11 +713,7 @@
   SymbolVisibility get visibility => SymbolVisibility.values[other & 0x03];
 
   void writeToStringBuffer(StringBuffer buffer) {
-    if (name != null) {
-      buffer..write('"')..write(name)..write('" =>');
-    } else {
-      buffer..write('<')..write(nameIndex)..write('> =>');
-    }
+    buffer..write('"')..write(name)..write('" =>');
     switch (bind) {
       case SymbolBinding.STB_GLOBAL:
         buffer..write(' a global');
@@ -793,8 +776,8 @@
   }
 
   Iterable<String> get keys => _nameCache.keys;
-  Iterable<Symbol> get values => _nameCache.values;
-  Symbol operator [](String name) => _nameCache[name];
+  Iterable<Symbol> get values => _entries;
+  Symbol? operator [](String name) => _nameCache[name];
   bool containsKey(String name) => _nameCache.containsKey(name);
 
   @override
@@ -825,21 +808,23 @@
   /// Creates an [Elf] from [bytes].
   ///
   /// Returns null if the file does not start with the ELF magic number.
-  static Elf fromBuffer(Uint8List bytes) =>
+  static Elf? fromBuffer(Uint8List bytes) =>
       Elf.fromReader(Reader.fromTypedData(bytes));
 
   /// Creates an [Elf] from the file at [path].
   ///
   /// Returns null if the file does not start with the ELF magic number.
-  static Elf fromFile(String path) => Elf.fromReader(Reader.fromFile(path));
+  static Elf? fromFile(String path) => Elf.fromReader(Reader.fromFile(path));
 
-  Iterable<Section> namedSections(String name) => _sectionsByName[name];
+  Iterable<Section> namedSections(String name) =>
+      _sectionsByName[name] ?? <Section>[];
 
   /// Lookup of a dynamic symbol by name.
   ///
   /// Returns -1 if there is no dynamic symbol that matches [name].
-  Symbol dynamicSymbolFor(String name) {
-    for (final SymbolTable dynsym in namedSections(".dynsym")) {
+  Symbol? dynamicSymbolFor(String name) {
+    for (final section in namedSections(".dynsym")) {
+      final dynsym = section as SymbolTable;
       if (dynsym.containsKey(name)) return dynsym[name];
     }
     return null;
@@ -847,8 +832,9 @@
 
   /// Reverse lookup of the static symbol that contains the given virtual
   /// address. Returns null if no static symbol matching the address is found.
-  Symbol staticSymbolAt(int address) {
-    for (final SymbolTable table in namedSections('.symtab')) {
+  Symbol? staticSymbolAt(int address) {
+    for (final section in namedSections('.symtab')) {
+      final table = section as SymbolTable;
       for (final symbol in table.values) {
         final start = symbol.value;
         final end = start + symbol.size;
@@ -865,7 +851,7 @@
   /// of the reader will be unchanged.
   ///
   /// Returns null if the file does not start with the ELF magic number.
-  static Elf fromReader(Reader elfReader) {
+  static Elf? fromReader(Reader elfReader) {
     // ELF files contain absolute offsets from the start of the file, so
     // make sure we have a reader that a) makes no assumptions about the
     // endianness or word size, since we'll read those in the header and b)
@@ -887,24 +873,47 @@
     }
     // Now set up the by-name section table and cache the names in the section
     // header entries.
-    final StringTable sectionHeaderStringTable =
-        sections[sectionHeader.entries[header.sectionHeaderStringsIndex]];
+    if (header.sectionHeaderStringsIndex < 0 ||
+        header.sectionHeaderStringsIndex >= sectionHeader.entries.length) {
+      throw FormatException("Section header string table index invalid");
+    }
+    final sectionHeaderStringTableEntry =
+        sectionHeader.entries[header.sectionHeaderStringsIndex];
+    final sectionHeaderStringTable =
+        sections[sectionHeaderStringTableEntry] as StringTable?;
+    if (sectionHeaderStringTable == null) {
+      throw FormatException(
+          "No section for entry ${sectionHeaderStringTableEntry}");
+    }
     final sectionsByName = <String, Set<Section>>{};
     for (final entry in sectionHeader.entries) {
+      final section = sections[entry];
+      if (section == null) {
+        throw FormatException("No section found for entry ${entry}");
+      }
       entry.setName(sectionHeaderStringTable);
-      sectionsByName.putIfAbsent(entry.name, () => {}).add(sections[entry]);
+      sectionsByName.putIfAbsent(entry.name, () => {}).add(section);
     }
     void _cacheSymbolNames(String stringTableTag, String symbolTableTag) {
-      final stringTables = Map.fromEntries(sectionsByName[stringTableTag]
-          .map((s) => MapEntry(s.headerEntry, s)));
-      for (final SymbolTable symbolTable in sectionsByName[symbolTableTag]) {
+      final stringTables = sectionsByName[stringTableTag]?.cast<StringTable>();
+      if (stringTables == null) {
+        return;
+      }
+      final stringTableMap =
+          Map.fromEntries(stringTables.map((s) => MapEntry(s.headerEntry, s)));
+      final symbolTables = sectionsByName[symbolTableTag]?.cast<SymbolTable>();
+      if (symbolTables == null) {
+        return;
+      }
+      for (final symbolTable in symbolTables) {
         final link = symbolTable.headerEntry.link;
         final entry = sectionHeader.entries[link];
-        if (!stringTables.containsKey(entry)) {
+        final stringTable = stringTableMap[entry];
+        if (stringTable == null) {
           throw FormatException(
               "String table not found at section header entry ${link}");
         }
-        symbolTable._cacheNames(stringTables[entry]);
+        symbolTable._cacheNames(stringTable);
       }
     }
 
@@ -948,7 +957,7 @@
       ..writeln('-----------------------------------------------------')
       ..writeln();
     for (final entry in _sectionHeader.entries) {
-      _sections[entry].writeToStringBuffer(buffer);
+      _sections[entry]!.writeToStringBuffer(buffer);
       buffer.writeln();
     }
   }
diff --git a/pkg/native_stack_traces/lib/src/reader.dart b/pkg/native_stack_traces/lib/src/reader.dart
index 21f6297..9eb5be6 100644
--- a/pkg/native_stack_traces/lib/src/reader.dart
+++ b/pkg/native_stack_traces/lib/src/reader.dart
@@ -14,26 +14,35 @@
   final ByteData bdata;
   // These are mutable so we can update them, in case the endianness and
   // wordSize are read using the reader (e.g., ELF files).
-  Endian endian;
-  int wordSize;
+  Endian? _endian;
+  int? _wordSize;
 
   int _offset = 0;
 
+  Endian get endian => _endian as Endian;
+  void set endian(Endian value) => _endian = value;
+  int get wordSize => _wordSize as int;
+  void set wordSize(int value) => _wordSize = value;
+
   /// Unless provided, [wordSize] and [endian] are initialized to values that
   /// ensure no reads are made that depend on their value (e.g., readBytes).
-  Reader.fromTypedData(TypedData data, {this.wordSize = -1, this.endian})
-      : bdata =
+  Reader.fromTypedData(TypedData data, {int? wordSize, Endian? endian})
+      : _wordSize = wordSize,
+        _endian = endian,
+        bdata =
             ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes);
 
-  Reader.fromFile(String path, {this.wordSize, this.endian})
-      : bdata = ByteData.sublistView(File(path).readAsBytesSync());
+  Reader.fromFile(String path, {int? wordSize, Endian? endian})
+      : _wordSize = wordSize,
+        _endian = endian,
+        bdata = ByteData.sublistView(File(path).readAsBytesSync());
 
   /// Returns a reader focused on a different portion of the underlying buffer.
   Reader refocusedCopy(int pos, int size) {
     assert(pos >= 0 && pos < bdata.buffer.lengthInBytes);
     assert(size >= 0 && (pos + size) <= bdata.buffer.lengthInBytes);
     return Reader.fromTypedData(ByteData.view(bdata.buffer, pos, size),
-        wordSize: wordSize, endian: endian);
+        wordSize: _wordSize, endian: _endian);
   }
 
   int get start => bdata.offsetInBytes;
@@ -65,7 +74,6 @@
         return signed
             ? bdata.getInt32(start, endian)
             : bdata.getUint32(start, endian);
-        break;
       case 8:
         return signed
             ? bdata.getInt64(start, endian)
@@ -116,7 +124,7 @@
   /// Stops either when the reader is empty or when a null item is returned
   /// from the callback.
   Iterable<MapEntry<int, S>> readRepeatedWithOffsets<S>(
-      S Function(Reader) callback,
+      S? Function(Reader) callback,
       {bool absolute = false}) sync* {
     final start = offset;
     while (!done) {
@@ -127,7 +135,7 @@
     }
   }
 
-  Iterable<S> readRepeated<S>(S Function(Reader) callback) =>
+  Iterable<S> readRepeated<S>(S? Function(Reader) callback) =>
       readRepeatedWithOffsets(callback).map((kv) => kv.value);
 
   void writeCurrentReaderPosition(StringBuffer buffer,
@@ -160,27 +168,27 @@
     final buffer = StringBuffer();
     buffer
       ..write("Word size: ")
-      ..write(wordSize)
+      ..write(_wordSize)
       ..writeln();
     buffer
       ..write("Endianness: ")
-      ..write(endian)
+      ..write(_endian)
       ..writeln();
     buffer
       ..write("Start:  0x")
-      ..write(paddedHex(start, wordSize ?? 0))
+      ..write(paddedHex(start, _wordSize ?? 0))
       ..write(" (")
       ..write(start)
       ..writeln(")");
     buffer
       ..write("Offset: 0x")
-      ..write(paddedHex(offset, wordSize ?? 0))
+      ..write(paddedHex(offset, _wordSize ?? 0))
       ..write(" (")
       ..write(offset)
       ..writeln(")");
     buffer
       ..write("Length: 0x")
-      ..write(paddedHex(length, wordSize ?? 0))
+      ..write(paddedHex(length, _wordSize ?? 0))
       ..write(" (")
       ..write(length)
       ..writeln(")");
diff --git a/pkg/native_stack_traces/pubspec.yaml b/pkg/native_stack_traces/pubspec.yaml
index cc0d214..f831df6 100644
--- a/pkg/native_stack_traces/pubspec.yaml
+++ b/pkg/native_stack_traces/pubspec.yaml
@@ -1,18 +1,19 @@
 name: native_stack_traces
 description: Utilities for working with non-symbolic stack traces.
-version: 0.3.8
+version: 0.4.0-nullsafety
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
 environment:
-  sdk: '>=2.8.0 <3.0.0'
+  # This must remain a tight constraint until nnbd is stable
+  sdk: '>=2.10.0-0 <2.10.0'
 
 executables:
   decode:
 
 dependencies:
-  args: ^1.5.2
-  path: ^1.6.4
+  args: ^1.6.0
+  path: ^1.8.0-nullsafety
 
 dev_dependencies:
-  pedantic: ^1.8.0
+  pedantic: ^1.9.2
diff --git a/pkg/nnbd_migration/analysis_options.yaml b/pkg/nnbd_migration/analysis_options.yaml
index 7d525d0..d38c130 100644
--- a/pkg/nnbd_migration/analysis_options.yaml
+++ b/pkg/nnbd_migration/analysis_options.yaml
@@ -1,8 +1,22 @@
+include: package:pedantic/analysis_options.1.9.0.yaml
+
 analyzer:
+  errors:
+    # There are currently 175 violations.
+    always_declare_return_types: ignore
+    # There are currently 60 violations.
+    annotate_overrides: ignore
+    # There are currently 200 violations.
+    omit_local_variable_types: ignore
+    # There are currently 20 violations.
+    unawaited_futures: ignore
+
   strong-mode:
     implicit-casts: false
+
 linter:
   rules:
+    - await_only_futures
     - empty_constructor_bodies
     - empty_statements
     - unnecessary_brace_in_string_interps
diff --git a/pkg/nnbd_migration/lib/fix_reason_target.dart b/pkg/nnbd_migration/lib/fix_reason_target.dart
index d1c0caa..9f9c91c 100644
--- a/pkg/nnbd_migration/lib/fix_reason_target.dart
+++ b/pkg/nnbd_migration/lib/fix_reason_target.dart
@@ -10,7 +10,7 @@
 /// is associated with each reason.
 abstract class FixReasonTarget {
   /// Fix reason target representing the full type, rather than a part of it.
-  static const FixReasonTarget root = const _FixReasonTarget_Root();
+  static const FixReasonTarget root = _FixReasonTarget_Root();
 
   const FixReasonTarget._();
 
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index 26821cb..d3f5fae 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -28,6 +28,7 @@
 import 'package:nnbd_migration/src/exceptions.dart';
 import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
 import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
+import 'package:nnbd_migration/src/front_end/migration_state.dart';
 import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
 import 'package:nnbd_migration/src/messages.dart';
 import 'package:nnbd_migration/src/utilities/json.dart' as json;
@@ -449,8 +450,6 @@
   /// The result of parsing command-line options.
   final CommandLineOptions options;
 
-  final Map<String, List<AnalysisError>> fileErrors = {};
-
   final Map<String, LineInfo> lineInfo = {};
 
   DartFixListener _dartFixListener;
@@ -545,7 +544,7 @@
   NonNullableFix createNonNullableFix(
       DartFixListener listener,
       ResourceProvider resourceProvider,
-      LineInfo getLineInfo(String path),
+      LineInfo Function(String path) getLineInfo,
       Object bindAddress,
       {List<String> included = const <String>[],
       int preferredPort,
@@ -577,7 +576,6 @@
 
     DriverBasedAnalysisContext context = analysisContext;
 
-    List<String> previewUrls;
     NonNullableFix nonNullableFix;
 
     logger.stdout(ansi.emphasized('Analyzing project...'));
@@ -591,11 +589,18 @@
         summaryPath: options.summary);
     nonNullableFix.rerunFunction = _rerunFunction;
     _fixCodeProcessor.registerCodeTask(nonNullableFix);
-    _fixCodeProcessor.nonNullableFixTask = nonNullableFix;
 
     try {
-      await _fixCodeProcessor.runFirstPhase(singlePhaseProgress: true);
-      _checkForErrors();
+      var analysisResult = await _fixCodeProcessor.runFirstPhase();
+
+      if (analysisResult.hasErrors) {
+        _logErrors(analysisResult);
+        if (!options.ignoreErrors) {
+          throw MigrationExit(1);
+        }
+      } else {
+        logger.stdout('No analysis issues found.');
+      }
     } on ExperimentStatusException catch (e) {
       logger.stdout(e.toString());
       final sdkPathVar = cli._environmentVariables['SDK_PATH'];
@@ -607,7 +612,7 @@
 
     logger.stdout('');
     logger.stdout(ansi.emphasized('Generating migration suggestions...'));
-    previewUrls = await _fixCodeProcessor.runLaterPhases(resetProgress: true);
+    var previewUrls = (await _fixCodeProcessor.runLaterPhases()).previewUrls;
 
     if (options.applyChanges) {
       logger.stdout(ansi.emphasized('Applying changes:'));
@@ -626,10 +631,10 @@
     }
 
     if (options.webPreview) {
-      String url = previewUrls.first;
-      assert(previewUrls.length <= 1,
+      assert(previewUrls.length == 1,
           'Got unexpected extra preview URLs from server');
 
+      var url = previewUrls.single;
       // TODO(#41809): Open a browser automatically.
       logger.stdout('''
 View the migration suggestions by visiting:
@@ -637,11 +642,9 @@
   ${ansi.emphasized(url)}
 
 Use this interactive web view to review, improve, or apply the results.
-''');
+When finished with the preview, hit ctrl-c to terminate this process.
 
-      logger.stdout('When finished with the preview, hit ctrl-c '
-          'to terminate this process.');
-      logger.stdout('');
+''');
 
       // Block until sigint (ctrl-c).
       await blockUntilSignalInterrupt();
@@ -718,43 +721,39 @@
     }
   }
 
-  void _checkForErrors() {
-    if (fileErrors.isEmpty) {
-      logger.stdout('No analysis issues found.');
+  void _logErrors(AnalysisResult analysisResult) {
+    logger.stdout('');
+
+    var issueCount = analysisResult.errors.length;
+    logger.stdout(
+        '$issueCount analysis ${_pluralize(issueCount, 'issue')} found:');
+
+    _IssueRenderer renderer =
+        _IssueRenderer(logger, options.directory, pathContext, lineInfo);
+    for (AnalysisError error in analysisResult.errors) {
+      renderer.render(error);
+    }
+
+    logger.stdout('');
+    logger.stdout('Note: analysis errors will result in erroneous migration '
+        'suggestions.');
+
+    _hasAnalysisErrors = true;
+    if (options.ignoreErrors) {
+      logger.stdout('Continuing with migration suggestions due to the use of '
+          '--${CommandLineOptions.ignoreErrorsFlag}.');
     } else {
+      // Fail with how to continue.
       logger.stdout('');
-
-      int issueCount =
-          fileErrors.values.map((list) => list.length).reduce((a, b) => a + b);
-      logger.stdout(
-          '$issueCount analysis ${_pluralize(issueCount, 'issue')} found:');
-      List<AnalysisError> allErrors = fileErrors.values
-          .fold(<AnalysisError>[], (list, element) => list..addAll(element));
-      _displayIssues(logger, options.directory, allErrors, lineInfo);
-      var importErrorCount = allErrors.where(_isUriError).length;
-
-      logger.stdout('');
-      logger.stdout(
-          'Note: analysis errors will result in erroneous migration suggestions.');
-
-      _hasAnalysisErrors = true;
-      if (options.ignoreErrors) {
-        logger.stdout('Continuing with migration suggestions due to the use of '
-            '--${CommandLineOptions.ignoreErrorsFlag}.');
-      } else {
-        // Fail with how to continue.
+      if (analysisResult.hasImportErrors) {
+        logger
+            .stdout('Unresolved URIs found.  Did you forget to run "pub get"?');
         logger.stdout('');
-        if (importErrorCount != 0) {
-          logger.stdout(
-              'Unresolved URIs found.  Did you forget to run "pub get"?');
-          logger.stdout('');
-        }
-        logger.stdout(
-            'Please fix the analysis issues (or, force generation of migration '
-            'suggestions by re-running with '
-            '--${CommandLineOptions.ignoreErrorsFlag}).');
-        throw MigrationExit(1);
       }
+      logger.stdout(
+          'Please fix the analysis issues (or, force generation of migration '
+          'suggestions by re-running with '
+          '--${CommandLineOptions.ignoreErrorsFlag}).');
     }
   }
 
@@ -794,22 +793,6 @@
     }
   }
 
-  void _displayIssues(Logger logger, String directory,
-      List<AnalysisError> issues, Map<String, LineInfo> lineInfo) {
-    issues.sort((AnalysisError one, AnalysisError two) {
-      if (one.source != two.source) {
-        return one.source.fullName.compareTo(two.source.fullName);
-      }
-      return one.offset - two.offset;
-    });
-
-    _IssueRenderer renderer =
-        _IssueRenderer(logger, directory, pathContext, lineInfo);
-    for (AnalysisError issue in issues) {
-      renderer.render(issue);
-    }
-  }
-
   void _exceptionReported(String detail) {
     if (_hasExceptions) return;
     _hasExceptions = true;
@@ -847,18 +830,24 @@
     }
   }
 
-  bool _isUriError(AnalysisError error) =>
-      error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST;
-
-  Future<void> _rerunFunction() async {
-    logger.stdout(ansi.emphasized('Recalculating migration suggestions...'));
+  Future<MigrationState> _rerunFunction() async {
+    logger.stdout(ansi.emphasized('Re-analyzing project...'));
 
     _dartFixListener.reset();
     _fixCodeProcessor.prepareToRerun();
-    await _fixCodeProcessor.runFirstPhase();
-    // TODO(paulberry): check for errors (see
-    // https://github.com/dart-lang/sdk/issues/41712)
-    await _fixCodeProcessor.runLaterPhases();
+    var analysisResult = await _fixCodeProcessor.runFirstPhase();
+    if (analysisResult.hasErrors) {
+      _logErrors(analysisResult);
+      return MigrationState(
+          _fixCodeProcessor._task.migration,
+          _fixCodeProcessor._task.includedRoot,
+          _dartFixListener,
+          _fixCodeProcessor._task.instrumentationListener,
+          analysisResult);
+    } else {
+      logger.stdout(ansi.emphasized('Re-generating migration suggestions...'));
+      return await _fixCodeProcessor.runLaterPhases();
+    }
   }
 
   List<SourceEdit> _sortEdits(SourceFileEdit sourceFileEdit) {
@@ -879,6 +868,51 @@
   }
 }
 
+/// The result of a round of static analysis; primarily a list of
+/// [AnalysisError]s.
+class AnalysisResult {
+  final List<AnalysisError> errors;
+  final Map<String, LineInfo> lineInfo;
+  final Context pathContext;
+  final String rootDirectory;
+
+  AnalysisResult(
+      this.errors, this.lineInfo, this.pathContext, this.rootDirectory) {
+    errors.sort((AnalysisError one, AnalysisError two) {
+      if (one.source != two.source) {
+        return one.source.fullName.compareTo(two.source.fullName);
+      }
+      return one.offset - two.offset;
+    });
+  }
+
+  bool get hasErrors => errors.isNotEmpty;
+
+  /// Whether the errors include any which may be the result of not yet having
+  /// run "pub get".
+  bool get hasImportErrors => errors.any(
+      (error) => error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST);
+
+  /// Converts the list of errors into JSON, for displaying in the web preview.
+  List<Map<String, dynamic>> toJson() {
+    var result = <Map<String, dynamic>>[];
+    // severity • Message ... at foo/bar.dart:6:1 • (error_code)
+    for (var error in errors) {
+      var lineInfoForThisFile = lineInfo[error.source.fullName];
+      var location = lineInfoForThisFile.getLocation(error.offset);
+      var path =
+          pathContext.relative(error.source.fullName, from: rootDirectory);
+      result.add({
+        'severity': error.severity.name,
+        'message': _removePeriod(error.message),
+        'location': '$path:${location.lineNumber}:${location.columnNumber}',
+        'code': error.errorCode.name.toLowerCase(),
+      });
+    }
+    return result;
+  }
+}
+
 /// Exception thrown by [MigrationCli] if the client should exit.
 class MigrationExit {
   /// The exit code that the client should set.
@@ -920,6 +954,7 @@
 
   final DriverBasedAnalysisContext context;
 
+  /// The task used to migrate to NNBD.
   NonNullableFix _task;
 
   Set<String> pathsToProcess;
@@ -928,14 +963,10 @@
 
   final MigrationCliRunner _migrationCli;
 
-  /// The task used to migrate to NNBD.
-  NonNullableFix nonNullableFixTask;
-
   _FixCodeProcessor(this.context, this._migrationCli)
       : pathsToProcess = _migrationCli.computePathsToProcess(context);
 
-  bool get isPreviewServerRunnning =>
-      nonNullableFixTask?.isPreviewServerRunning ?? false;
+  bool get isPreviewServerRunnning => _task?.isPreviewServerRunning ?? false;
 
   LineInfo getLineInfo(String path) =>
       context.currentSession.getFile(path).lineInfo;
@@ -988,14 +1019,15 @@
     _task = task;
   }
 
-  Future<void> runFirstPhase({bool singlePhaseProgress = false}) async {
+  Future<AnalysisResult> runFirstPhase() async {
     // All tasks should be registered; [numPhases] should be finalized.
-    _progressBar = _ProgressBar(
-        pathsToProcess.length * (singlePhaseProgress ? 1 : numPhases));
+    _progressBar = _ProgressBar(pathsToProcess.length);
 
     // Process package
     _task.processPackage(context.contextRoot.root);
 
+    var analysisErrors = <AnalysisError>[];
+
     // Process each source file.
     await processResources((ResolvedUnitResult result) async {
       _progressBar.tick();
@@ -1003,20 +1035,20 @@
           .where((error) => error.severity == Severity.error)
           .toList();
       if (errors.isNotEmpty) {
-        _migrationCli.fileErrors[result.path] = errors;
+        analysisErrors.addAll(errors);
         _migrationCli.lineInfo[result.path] = result.lineInfo;
       }
-      if (_migrationCli.options.ignoreErrors ||
-          _migrationCli.fileErrors.isEmpty) {
+      if (_migrationCli.options.ignoreErrors || analysisErrors.isEmpty) {
         await _task.prepareUnit(result);
       }
     });
+
+    return AnalysisResult(analysisErrors, _migrationCli.lineInfo,
+        _migrationCli.pathContext, _migrationCli.options.directory);
   }
 
-  Future<List<String>> runLaterPhases({bool resetProgress = false}) async {
-    if (resetProgress) {
-      _progressBar = _ProgressBar(pathsToProcess.length * (numPhases - 1));
-    }
+  Future<MigrationState> runLaterPhases() async {
+    _progressBar = _ProgressBar(pathsToProcess.length * (numPhases - 1));
 
     await processResources((ResolvedUnitResult result) async {
       _progressBar.tick();
@@ -1033,8 +1065,9 @@
       await _task.startPreviewServer(state, _migrationCli.applyHook);
     }
     _progressBar.complete();
+    state.previewUrls = _task.previewUrls;
 
-    return nonNullableFixTask.previewUrls;
+    return state;
   }
 }
 
@@ -1056,26 +1089,13 @@
     final Ansi ansi = logger.ansi;
 
     logger.stdout(
-      '  ${ansi.error(_severityToString(issue.severity))} • '
+      '  ${ansi.error(issue.severity.name)} • '
       '${ansi.emphasized(_removePeriod(issue.message))} '
       'at ${pathContext.relative(issue.source.fullName, from: rootDirectory)}'
-      ':${location.lineNumber}:'
-      '${location.columnNumber} '
+      ':${location.lineNumber}:${location.columnNumber} '
       '• (${issue.errorCode.name.toLowerCase()})',
     );
   }
-
-  String _severityToString(Severity severity) {
-    switch (severity) {
-      case Severity.error:
-        return 'error';
-      case Severity.warning:
-        return 'warning';
-      case Severity.info:
-        return 'info';
-    }
-    return '???';
-  }
 }
 
 /// A facility for drawing a progress bar in the terminal.
@@ -1149,3 +1169,18 @@
         ']');
   }
 }
+
+extension on Severity {
+  /// Returns the simple name of the Severity, as a String.
+  String get name {
+    switch (this) {
+      case Severity.error:
+        return 'error';
+      case Severity.warning:
+        return 'warning';
+      case Severity.info:
+        return 'info';
+    }
+    return '???';
+  }
+}
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index 5be23ba..787b235 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -18,29 +18,29 @@
 /// Description of fixes that might be performed by nullability migration.
 class NullabilityFixDescription {
   /// A variable declaration needs to be marked as "late".
-  static const addLate = const NullabilityFixDescription._(
+  static const addLate = NullabilityFixDescription._(
       appliedMessage: 'Added a late keyword', kind: NullabilityFixKind.addLate);
 
   /// A variable declaration needs to be marked as "late" due to the presence of
   /// a `/*late*/` hint.
-  static const addLateDueToHint = const NullabilityFixDescription._(
+  static const addLateDueToHint = NullabilityFixDescription._(
       appliedMessage: 'Added a late keyword, due to a hint',
       kind: NullabilityFixKind.addLateDueToHint);
 
   /// A variable declaration needs to be marked as "late" due to being certainly
   /// assigned in test setup.
-  static const addLateDueToTestSetup = const NullabilityFixDescription._(
+  static const addLateDueToTestSetup = NullabilityFixDescription._(
       appliedMessage: 'Added a late keyword, due to assignment in `setUp`',
       kind: NullabilityFixKind.addLateDueToTestSetup);
 
   /// An expression's value needs to be null-checked.
-  static const checkExpression = const NullabilityFixDescription._(
+  static const checkExpression = NullabilityFixDescription._(
     appliedMessage: 'Added a non-null assertion to nullable expression',
     kind: NullabilityFixKind.checkExpression,
   );
 
   /// An expression's value will be null-checked due to a hint.
-  static const checkExpressionDueToHint = const NullabilityFixDescription._(
+  static const checkExpressionDueToHint = NullabilityFixDescription._(
     appliedMessage: 'Accepted a null check hint',
     kind: NullabilityFixKind.checkExpressionDueToHint,
   );
@@ -48,47 +48,47 @@
   /// A compound assignment's combiner operator returns a type that isn't
   /// assignable to the LHS of the assignment.
   static const compoundAssignmentHasBadCombinedType =
-      const NullabilityFixDescription._(
+      NullabilityFixDescription._(
     appliedMessage: 'Compound assignment has bad combined type',
     kind: NullabilityFixKind.compoundAssignmentHasBadCombinedType,
   );
 
   /// A compound assignment's LHS has a nullable type.
   static const compoundAssignmentHasNullableSource =
-      const NullabilityFixDescription._(
+      NullabilityFixDescription._(
     appliedMessage: 'Compound assignment has nullable source',
     kind: NullabilityFixKind.compoundAssignmentHasNullableSource,
   );
 
   /// Informative message: a condition of an if-test or conditional expression
   /// will always evaluate to `false` in strong checking mode.
-  static const conditionFalseInStrongMode = const NullabilityFixDescription._(
+  static const conditionFalseInStrongMode = NullabilityFixDescription._(
       appliedMessage: 'Condition will always be false in strong checking mode',
       kind: NullabilityFixKind.conditionFalseInStrongMode);
 
   /// Informative message: a condition of an if-test or conditional expression
   /// will always evaluate to `true` in strong checking mode.
-  static const conditionTrueInStrongMode = const NullabilityFixDescription._(
+  static const conditionTrueInStrongMode = NullabilityFixDescription._(
       appliedMessage: 'Condition will always be true in strong checking mode',
       kind: NullabilityFixKind.conditionTrueInStrongMode);
 
   /// An if-test or conditional expression needs to have its condition
   /// discarded.
-  static const discardCondition = const NullabilityFixDescription._(
+  static const discardCondition = NullabilityFixDescription._(
     appliedMessage: 'Discarded a condition which is always true',
     kind: NullabilityFixKind.removeDeadCode,
   );
 
   /// An if-test or conditional expression needs to have its condition and
   /// "else" branch discarded.
-  static const discardElse = const NullabilityFixDescription._(
+  static const discardElse = NullabilityFixDescription._(
     appliedMessage: 'Discarded an unreachable conditional else branch',
     kind: NullabilityFixKind.removeDeadCode,
   );
 
   /// An if-test or conditional expression needs to have its condition and
   /// "then" branch discarded.
-  static const discardThen = const NullabilityFixDescription._(
+  static const discardThen = NullabilityFixDescription._(
     appliedMessage:
         'Discarded a condition which is always false, and the "then" branch '
         'that follows',
@@ -96,12 +96,12 @@
   );
 
   /// An if-test needs to be discarded completely.
-  static const discardIf = const NullabilityFixDescription._(
+  static const discardIf = NullabilityFixDescription._(
     appliedMessage: 'Discarded an if-test with no effect',
     kind: NullabilityFixKind.removeDeadCode,
   );
 
-  static const downcastExpression = const NullabilityFixDescription._(
+  static const downcastExpression = NullabilityFixDescription._(
     appliedMessage: 'Added a downcast to an expression',
     kind: NullabilityFixKind.downcastExpression,
   );
@@ -109,7 +109,7 @@
   /// Informative message: a null-aware access won't be necessary in strong
   /// checking mode.
   static const nullAwarenessUnnecessaryInStrongMode =
-      const NullabilityFixDescription._(
+      NullabilityFixDescription._(
           appliedMessage:
               'Null-aware access will be unnecessary in strong checking mode',
           kind: NullabilityFixKind.nullAwarenessUnnecessaryInStrongMode);
@@ -117,38 +117,38 @@
   /// Informative message: a null-aware assignment won't be necessary in strong
   /// checking mode.
   static const nullAwareAssignmentUnnecessaryInStrongMode =
-      const NullabilityFixDescription._(
+      NullabilityFixDescription._(
           appliedMessage:
               'Null-aware assignment will be unnecessary in strong checking mode',
           kind: NullabilityFixKind.nullAwareAssignmentUnnecessaryInStrongMode);
 
-  static const otherCastExpression = const NullabilityFixDescription._(
+  static const otherCastExpression = NullabilityFixDescription._(
     appliedMessage: 'Added a cast to an expression (non-downcast)',
     kind: NullabilityFixKind.otherCastExpression,
   );
 
   /// An unnecessary downcast has been discarded.
-  static const removeLanguageVersionComment = const NullabilityFixDescription._(
+  static const removeLanguageVersionComment = NullabilityFixDescription._(
     appliedMessage: 'Removed language version comment so that NNBD features '
         'will be allowed in this file',
     kind: NullabilityFixKind.removeLanguageVersionComment,
   );
 
   /// An unnecessary downcast has been discarded.
-  static const removeAs = const NullabilityFixDescription._(
+  static const removeAs = NullabilityFixDescription._(
     appliedMessage: 'Discarded a downcast that is now unnecessary',
     kind: NullabilityFixKind.removeAs,
   );
 
   /// A null-aware operator needs to be changed into its non-null-aware
   /// equivalent.
-  static const removeNullAwareness = const NullabilityFixDescription._(
+  static const removeNullAwareness = NullabilityFixDescription._(
       appliedMessage:
           'Changed a null-aware access into an ordinary access, because the target cannot be null',
       kind: NullabilityFixKind.removeDeadCode);
 
   /// A null-aware assignment was removed because its LHS is non-nullable.
-  static const removeNullAwareAssignment = const NullabilityFixDescription._(
+  static const removeNullAwareAssignment = NullabilityFixDescription._(
       appliedMessage:
           'Removed a null-aware assignment, because the target cannot be null',
       kind: NullabilityFixKind.removeDeadCode);
diff --git a/pkg/nnbd_migration/lib/src/decorated_type.dart b/pkg/nnbd_migration/lib/src/decorated_type.dart
index 4c36029..da5596f 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type.dart
@@ -158,7 +158,8 @@
       return DecoratedType(type, nullabilityNode, typeArguments: typeArguments);
     } else if (type is FunctionType) {
       if (typeArguments != null) {
-        throw "Not supported: implicit function type with explicit type arguments";
+        throw 'Not supported: implicit function type with explicit type '
+            'arguments';
       }
       return DecoratedType.forImplicitFunction(
           typeProvider, type, nullabilityNode, graph, target);
@@ -184,7 +185,7 @@
     // [_decoratedTypeParameterBounds] so the type parameter needs to have an
     // enclosing element of `null`.
     assert(parameter.enclosingElement == null,
-        "$parameter should not have parent ${parameter.enclosingElement}");
+        '$parameter should not have parent ${parameter.enclosingElement}');
   }
 
   /// If `this` represents an interface type, returns the substitution necessary
@@ -219,8 +220,8 @@
   @override
   bool operator ==(Object other) {
     if (other is DecoratedType) {
-      if (!identical(this.node, other.node)) return false;
-      var thisType = this.type;
+      if (!identical(node, other.node)) return false;
+      var thisType = type;
       var otherType = other.type;
       if (thisType is FunctionType && otherType is FunctionType) {
         if (thisType.normalParameterTypes.length !=
@@ -244,7 +245,7 @@
         return true;
       } else if (thisType is InterfaceType && otherType is InterfaceType) {
         if (thisType.element != otherType.element) return false;
-        if (!_compareLists(this.typeArguments, other.typeArguments)) {
+        if (!_compareLists(typeArguments, other.typeArguments)) {
           return false;
         }
         return true;
diff --git a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
index 13e52db..4c776c8 100644
--- a/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
+++ b/pkg/nnbd_migration/lib/src/decorated_type_operations.dart
@@ -59,13 +59,6 @@
   }
 
   @override
-  bool isLocalVariableWithoutDeclaredType(PromotableElement variable) {
-    return variable is LocalVariableElement &&
-        variable.hasImplicitType &&
-        !variable.hasInitializer;
-  }
-
-  @override
   bool isNever(DecoratedType type) {
     return false;
   }
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index b59c9c5..44f256d 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -211,7 +211,7 @@
 
   final Set<PromotableElement> _lateHintedLocals = {};
 
-  Map<Token, HintComment> _nullCheckHints = {};
+  final Map<Token, HintComment> _nullCheckHints = {};
 
   EdgeBuilder(this.typeProvider, this._typeSystem, this._variables, this._graph,
       this.source, this.listener, this._decoratedClassHierarchy,
@@ -447,6 +447,7 @@
     } else if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
         operatorType == TokenType.BAR_BAR) {
       bool isAnd = operatorType == TokenType.AMPERSAND_AMPERSAND;
+      _flowAnalysis.logicalBinaryOp_begin();
       _checkExpressionNotNull(leftOperand);
       _flowAnalysis.logicalBinaryOp_rightBegin(node.leftOperand, isAnd: isAnd);
       _postDominatedLocals.doScoped(
@@ -484,7 +485,7 @@
       } else {
         var calleeType =
             getOrComputeElementType(callee, targetType: targetType);
-        assert(calleeType.positionalParameters.length > 0); // TODO(paulberry)
+        assert(calleeType.positionalParameters.isNotEmpty); // TODO(paulberry)
         _handleAssignment(rightOperand,
             destinationType: calleeType.positionalParameters[0]);
         return _fixNumericTypes(calleeType.returnType, node.staticType);
@@ -619,6 +620,7 @@
 
   @override
   DecoratedType visitConditionalExpression(ConditionalExpression node) {
+    _flowAnalysis.conditional_conditionBegin();
     _checkExpressionNotNull(node.condition);
     NullabilityNode trueGuard;
     NullabilityNode falseGuard;
@@ -947,6 +949,7 @@
 
   @override
   DecoratedType visitIfStatement(IfStatement node) {
+    _flowAnalysis.ifStatement_conditionBegin();
     _checkExpressionNotNull(node.condition);
     NullabilityNode trueGuard;
     NullabilityNode falseGuard;
@@ -1728,7 +1731,7 @@
           var instantiatedType =
               _variables.decoratedTypeAnnotation(source, typeName);
           if (instantiatedType == null) {
-            throw new StateError('No type annotation for type name '
+            throw StateError('No type annotation for type name '
                 '${typeName.toSource()}, offset=${typeName.offset}');
           }
           var origin = InstantiateToBoundsOrigin(source, typeName);
@@ -2238,7 +2241,7 @@
           DecoratedType compoundOperatorType = getOrComputeElementType(
               compoundOperatorMethod,
               targetType: destinationType);
-          assert(compoundOperatorType.positionalParameters.length > 0);
+          assert(compoundOperatorType.positionalParameters.isNotEmpty);
           _checkAssignment(edgeOrigin, FixReasonTarget.root,
               source: sourceType,
               destination: compoundOperatorType.positionalParameters[0],
@@ -2757,7 +2760,7 @@
       }
     }
     int i = 0;
-    var suppliedNamedParameters = Set<String>();
+    var suppliedNamedParameters = <String>{};
     for (var argument in arguments) {
       String name;
       Expression expression;
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 9c75138..621a6e8a 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -90,7 +90,7 @@
   /// Optional argument [info] contains information about why the change was
   /// made.
   const AtomicEdit.insert(this.replacement,
-      {this.info, this.isInformative: false})
+      {this.info, this.isInformative = false})
       : assert(replacement.length > 0),
         assert(isInformative is bool),
         length = 0;
@@ -105,13 +105,13 @@
         isInformative = false;
 
   /// Return `true` if this edit is a deletion (no characters added).
-  bool get isDeletion => replacement.length == 0;
+  bool get isDeletion => replacement.isEmpty;
 
   /// Return `true` if this edit is an insertion (no characters removed).
   bool get isInsertion => length == 0;
 
   /// Return `true` if this edit is a replacement.
-  bool get isReplacement => length > 0 && replacement.length > 0;
+  bool get isReplacement => length > 0 && replacement.isNotEmpty;
 
   @override
   String toString() {
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index ff2d412..9e5e486 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -26,7 +26,6 @@
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/instrumentation.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
@@ -471,20 +470,18 @@
       _wrapExceptions(node, () => type, () {
         var parent = node.parent;
         if (parent is AssignmentExpression) {
-          return (_assignmentLikeExpressionHandlers[parent] ??=
-                  _AssignmentExpressionHandler(parent))
-              .modifySubexpressionType(this, node, type);
+          if (parent.leftHandSide == node) {
+            return type;
+          }
+          return _assignmentLikeExpressionHandlers[parent]
+              .modifyAssignmentRhs(this, node, type);
         } else if (parent is PrefixExpression) {
           if (_isIncrementOrDecrementOperator(parent.operator.type)) {
-            return (_assignmentLikeExpressionHandlers[parent] ??=
-                    _PrefixExpressionHandler(parent))
-                .modifySubexpressionType(this, node, type);
+            return type;
           }
         } else if (parent is PostfixExpression) {
           if (_isIncrementOrDecrementOperator(parent.operator.type)) {
-            return (_assignmentLikeExpressionHandlers[parent] ??=
-                    _PostfixExpressionHandler(parent))
-                .modifySubexpressionType(this, node, type);
+            return type;
           }
         }
         return _modifyRValueType(node, type);
@@ -503,6 +500,30 @@
   }
 
   @override
+  void setCompoundAssignmentExpressionTypes(CompoundAssignmentExpression node) {
+    assert(_assignmentLikeExpressionHandlers[node] == null);
+    if (node is AssignmentExpression) {
+      var handler = _AssignmentExpressionHandler(node);
+      _assignmentLikeExpressionHandlers[node] = handler;
+      handler.handleLValueType(this, node.readType, node.writeType);
+    } else if (node is PrefixExpression) {
+      assert(_isIncrementOrDecrementOperator(node.operator.type));
+      var handler = _PrefixExpressionHandler(node);
+      _assignmentLikeExpressionHandlers[node] = handler;
+      handler.handleLValueType(this, node.readType, node.writeType);
+      handler.handleAssignmentRhs(this, _fixBuilder.typeProvider.intType);
+    } else if (node is PostfixExpression) {
+      assert(_isIncrementOrDecrementOperator(node.operator.type));
+      var handler = _PostfixExpressionHandler(node);
+      _assignmentLikeExpressionHandlers[node] = handler;
+      handler.handleLValueType(this, node.readType, node.writeType);
+      handler.handleAssignmentRhs(this, _fixBuilder.typeProvider.intType);
+    } else {
+      throw StateError('(${node.runtimeType}) $node');
+    }
+  }
+
+  @override
   void setFlowAnalysis(
       FlowAnalysis<AstNode, Statement, Expression, PromotableElement, DartType>
           flowAnalysis) {
@@ -765,37 +786,21 @@
   /// [writeType], and [rhsContextType].  Also verifies that for compound
   /// assignments, the [readType] is non-nullable, and that for null-aware
   /// assignments, the [readType] is nullable.
-  void handleLValueType(
-      MigrationResolutionHooksImpl hooks, DartType resolvedType) {
-    assert(resolvedType.nullabilitySuffix != NullabilitySuffix.star);
-    // Provisionally store the resolved type as the type of the target, so that
-    // getReadType can fall back on it if necessary.
-    var target = this.target;
-    target.staticType = resolvedType;
-    // The type passed in by the resolver for the LHS of an assignment is the
-    // "write type".
-    var writeType = resolvedType;
-    if (target is SimpleIdentifier) {
-      var element = target.staticElement;
-      if (element is PromotableElement) {
-        // However, if the LHS is a reference to a local variable that has
-        // been promoted, the resolver passes in the promoted type.  We
-        // want to use the variable element's type, so that we consider it
-        // ok to assign a value to the variable that un-does the
-        // promotion.  See https://github.com/dart-lang/sdk/issues/41411.
-        writeType = element.type;
-      }
-    }
-    assert(writeType.nullabilitySuffix != NullabilitySuffix.star);
-    this.writeType = writeType;
+  void handleLValueType(MigrationResolutionHooksImpl hooks,
+      DartType readTypeToSet, DartType writeTypeToSet) {
+    assert(writeTypeToSet.nullabilitySuffix != NullabilitySuffix.star);
+    writeType = writeTypeToSet;
+    // TODO(scheglov) Remove this after the analyzer breaking change that
+    // will top setting types for LHS.
+    target.staticType = writeTypeToSet;
     var fixBuilder = hooks._fixBuilder;
     if (combinerType == TokenType.EQ) {
-      rhsContextType = writeType;
+      rhsContextType = writeTypeToSet;
     } else {
-      readType = getReadType(target);
+      readType = readTypeToSet;
       assert(readType.nullabilitySuffix != NullabilitySuffix.star);
       if (combinerType == TokenType.QUESTION_QUESTION_EQ) {
-        rhsContextType = writeType;
+        rhsContextType = writeTypeToSet;
         if (fixBuilder._typeSystem.isNonNullable(readType)) {
           (fixBuilder._getChange(node) as NodeChangeForAssignment)
               .isWeakNullAware = true;
@@ -810,26 +815,13 @@
     }
   }
 
-  /// Called after visiting the LHS or the RHS of the assignment.
-  DartType modifySubexpressionType(MigrationResolutionHooksImpl hooks,
+  /// Called after visiting the RHS of the assignment.
+  DartType modifyAssignmentRhs(MigrationResolutionHooksImpl hooks,
       Expression subexpression, DartType type) {
-    if (identical(subexpression, target)) {
-      handleLValueType(hooks, type);
-      if (node is! AssignmentExpression) {
-        // Must be a pre or post increment/decrement, so the "RHS" is implicitly
-        // the integer 1.
-        handleAssignmentRhs(hooks, hooks._fixBuilder.typeProvider.intType);
-      }
-      return type;
-    } else {
-      var node = this.node;
-      assert(node is AssignmentExpression &&
-          identical(subexpression, node.rightHandSide));
-      type =
-          hooks._modifyRValueType(subexpression, type, context: rhsContextType);
-      handleAssignmentRhs(hooks, type);
-      return type;
-    }
+    type =
+        hooks._modifyRValueType(subexpression, type, context: rhsContextType);
+    handleAssignmentRhs(hooks, type);
+    return type;
   }
 }
 
diff --git a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
index bf77587..c16f646 100644
--- a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
@@ -238,7 +238,7 @@
     var description = 'Non-nullability reason${target.suffix}';
     var step = node.whyNotNullable;
     if (step == null) {
-      if (node != this.info.never) {
+      if (node != info.never) {
         // 'never' indicates we're describing an edge to never, such as a `!`.
         traces.add(TraceInfo(description, [
           _nodeToTraceEntry(node,
@@ -313,6 +313,17 @@
     var content = result.content;
     unitInfo.diskContent = content;
     var regions = unitInfo.regions;
+
+    // There are certain rare conditions involving generated code in a bazel
+    // workspace that can cause a source file to get processed more than once by
+    // the migration tool (sometimes with a correct URI, sometimes with an
+    // incorrect URI that corresponds to a file path in the `bazel-out`
+    // directory).  That can cause this method to get called twice for the same
+    // unit.  To avoid this creating user-visible problems, we need to ensure
+    // that any regions left over from the previous invocation are cleared out
+    // before we re-populate the region list.
+    regions.clear();
+
     var lineInfo = result.unit.lineInfo;
     var insertions = <int, List<AtomicEdit>>{};
     var hintsSeen = <HintComment>{};
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_state.dart b/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
index adb249f..8593172 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_state.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:nnbd_migration/instrumentation.dart';
+import 'package:nnbd_migration/migration_cli.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
 import 'package:nnbd_migration/src/front_end/info_builder.dart';
@@ -38,9 +39,14 @@
   /// If there have been changes to disk so the migration needs to be rerun.
   bool needsRerun = false;
 
+  final AnalysisResult analysisResult;
+
   /// Initialize a newly created migration state with the given values.
   MigrationState(this.migration, this.includedRoot, this.listener,
-      this.instrumentationListener);
+      this.instrumentationListener,
+      [this.analysisResult]);
+
+  bool get hasErrors => analysisResult?.hasErrors ?? false;
 
   /// If the migration has been applied to disk.
   bool get hasBeenApplied => _hasBeenApplied;
@@ -63,4 +69,6 @@
         unitInfos, infoBuilder.unitMap, pathContext, includedRoot);
     pathMapper = PathMapper(provider);
   }
+
+  /*late*/ List<String> previewUrls;
 }
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index 5a651dc..9b9d955 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -78,7 +78,7 @@
   /// If this occurs, then don't update any code.
   bool _packageIsNNBD = true;
 
-  Future<void> Function() rerunFunction;
+  Future<MigrationState> Function() rerunFunction;
 
   /// A list of the URLs corresponding to the included roots.
   List<String> previewUrls;
@@ -161,9 +161,7 @@
 
   Future<MigrationState> rerun() async {
     reset();
-    await rerunFunction();
-    final state = MigrationState(
-        migration, includedRoot, listener, instrumentationListener);
+    var state = await rerunFunction();
     await state.refresh();
     return state;
   }
@@ -185,6 +183,8 @@
 
   Future<void> startPreviewServer(
       MigrationState state, void Function() applyHook) async {
+    // This method may be called multiple times, for example during a re-run.
+    // But the preview server should only be started once.
     if (_server == null) {
       _server = HttpPreviewServer(
           state, rerun, applyHook, bindAddress, preferredPort);
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/index.html b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
index 1b67ad7..c30f9ae 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/index.html
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
@@ -6,6 +6,7 @@
     <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:400,600&display=swap">
     <link rel="stylesheet" href="{{ highlightStylePath }}">
     <style>{{ dartPageStyle }}</style>
+    <link rel="shortcut icon" href="/dart_192.png">
 </head>
 <body class="{{ migrationAppliedStyle }} {{ needsRerunStyle }}">
 <div class="rerunning-pane">
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
index 0d594f0..4c121b8 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
@@ -371,8 +371,8 @@
 }
 
 .region.added-region {
-  background-color: #263952; /* $dark-selection-color */
-  color: #c0c2c5; /* $dark-editor-text */
+  background-color: #178afd;
+  color: #fff;
 }
 
 .region.removed-region {
@@ -381,12 +381,12 @@
 }
 
 .region.informative-region {
-  background-color: #178afd; /* $dark-selection-color */
+  background-color: #263952;
   color: #fff;
   display: inline-block;
-  height: 14px;
+  height: 15px;
   position: relative;
-  top: 1px;
+  top: 2px;
 }
 
 .target {
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
index 5de078e..80f9df3 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
@@ -7422,71 +7422,72 @@
 ''';
 
 String _index_html;
-// index_html md5 is '39097ee2371c204f0f1e3515a60a7203'
+// index_html md5 is 'f17972e91adf7afeeed745126e359ffb'
 String _index_html_base64 = '''
 PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
 cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
 cnRQYWdlU2NyaXB0IH19PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0
 dHBzOi8vZm9udHMuZ29vZ2xlYXBpcy5jb20vY3NzP2ZhbWlseT1PcGVuK1NhbnM6NDAwLDYwMCZkaXNw
 bGF5PXN3YXAiPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJ7eyBoaWdobGlnaHRTdHls
-ZVBhdGggfX0iPgogICAgPHN0eWxlPnt7IGRhcnRQYWdlU3R5bGUgfX08L3N0eWxlPgo8L2hlYWQ+Cjxi
-b2R5IGNsYXNzPSJ7eyBtaWdyYXRpb25BcHBsaWVkU3R5bGUgfX0ge3sgbmVlZHNSZXJ1blN0eWxlIH19
-Ij4KPGRpdiBjbGFzcz0icmVydW5uaW5nLXBhbmUiPgogIDxoMT5SZXJ1bm5pbmcuLi48L2gxPgo8L2Rp
-dj4KPGRpdiBjbGFzcz0icG9wdXAtcGFuZSI+CiAgPGRpdiBjbGFzcz0iY2xvc2UgYnV0dG9uIj5YPC9k
-aXY+CiAgPGgyPjwvaDI+PCEtLSBoZWFkZXIgcGxhY2Vob2xkZXIgZWxlbWVudCAtLT4KICA8cD48L3A+
-PCEtLSBzdWJoZWFkZXIgcGxhY2Vob2xkZXIgZWxlbWVudCAtLT4KICA8cHJlPjwvcHJlPjwhLS0gcHJl
-Zm9ybWF0ZWQgY29udGVudCBwbGFjZWhvbGRlciBlbGVtZW50IC0tPgogIDxhIGNsYXNzPSJidXR0b24g
-Ym90dG9tIiB0YXJnZXQ9Il9ibGFuayI+RmlsZSBvbiBHaXRIdWI8L2E+PCEtLSBwb3N0IHRvIGdpdGh1
-YiBwbGFjZWhvbGRlciBlbGVtZW50IC0tPgo8L2Rpdj4KPHAgY2xhc3M9InJvb3QiPnt7IHJvb3QgfX08
-L3A+CjxoZWFkZXIgY2xhc3M9ImVsZXZhdGlvbi16NCI+CiAgICA8aW1nIHNyYz0ie3sgZGFydExvZ29Q
-YXRoIH19IiBhbHQ9IkRhcnRQYWQgTG9nbyIgY2xhc3M9ImxvZ28iLz4KICAgIDxoMT5EYXJ0PC9oMT4K
-ICAgIDxoMiBjbGFzcz0iYmVmb3JlLWFwcGx5Ij5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9o
-Mj4KICAgIDxoMiBjbGFzcz0iYWZ0ZXItYXBwbHkiPiYjMTAwMDM7IE51bGwgc2FmZXR5IG1pZ3JhdGlv
-biBhcHBsaWVkPC9oMj4KICAgIDxoMyBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gzPgogICAgPGEgdGFy
-Z2V0PSJfYmxhbmsiCiAgICAgICBocmVmPSJodHRwczovL2dvby5nbGUvZGFydC1udWxsLXNhZmV0eS1t
-aWdyYXRpb24tdG9vbCI+CiAgICAgIDxidXR0b24gY2xhc3M9ImFjdGlvbi1idXR0b24iPgogICAgICAg
-IDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+bGF1bmNoPC9pPgogICAgICAgIDxzcGFuPkhlbHA8L3Nw
-YW4+CiAgICAgIDwvYnV0dG9uPgogICAgPC9hPgogICAgPGJ1dHRvbiBjbGFzcz0iYWN0aW9uLWJ1dHRv
-biBhcHBseS1taWdyYXRpb24iPgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+ZWRpdDwv
+ZVBhdGggfX0iPgogICAgPHN0eWxlPnt7IGRhcnRQYWdlU3R5bGUgfX08L3N0eWxlPgogICAgPGxpbmsg
+cmVsPSJzaG9ydGN1dCBpY29uIiBocmVmPSIvZGFydF8xOTIucG5nIj4KPC9oZWFkPgo8Ym9keSBjbGFz
+cz0ie3sgbWlncmF0aW9uQXBwbGllZFN0eWxlIH19IHt7IG5lZWRzUmVydW5TdHlsZSB9fSI+CjxkaXYg
+Y2xhc3M9InJlcnVubmluZy1wYW5lIj4KICA8aDE+UmVydW5uaW5nLi4uPC9oMT4KPC9kaXY+CjxkaXYg
+Y2xhc3M9InBvcHVwLXBhbmUiPgogIDxkaXYgY2xhc3M9ImNsb3NlIGJ1dHRvbiI+WDwvZGl2PgogIDxo
+Mj48L2gyPjwhLS0gaGVhZGVyIHBsYWNlaG9sZGVyIGVsZW1lbnQgLS0+CiAgPHA+PC9wPjwhLS0gc3Vi
+aGVhZGVyIHBsYWNlaG9sZGVyIGVsZW1lbnQgLS0+CiAgPHByZT48L3ByZT48IS0tIHByZWZvcm1hdGVk
+IGNvbnRlbnQgcGxhY2Vob2xkZXIgZWxlbWVudCAtLT4KICA8YSBjbGFzcz0iYnV0dG9uIGJvdHRvbSIg
+dGFyZ2V0PSJfYmxhbmsiPkZpbGUgb24gR2l0SHViPC9hPjwhLS0gcG9zdCB0byBnaXRodWIgcGxhY2Vo
+b2xkZXIgZWxlbWVudCAtLT4KPC9kaXY+CjxwIGNsYXNzPSJyb290Ij57eyByb290IH19PC9wPgo8aGVh
+ZGVyIGNsYXNzPSJlbGV2YXRpb24tejQiPgogICAgPGltZyBzcmM9Int7IGRhcnRMb2dvUGF0aCB9fSIg
+YWx0PSJEYXJ0UGFkIExvZ28iIGNsYXNzPSJsb2dvIi8+CiAgICA8aDE+RGFydDwvaDE+CiAgICA8aDIg
+Y2xhc3M9ImJlZm9yZS1hcHBseSI+UHJvcG9zZWQgbnVsbCBzYWZldHkgY2hhbmdlczwvaDI+CiAgICA8
+aDIgY2xhc3M9ImFmdGVyLWFwcGx5Ij4mIzEwMDAzOyBOdWxsIHNhZmV0eSBtaWdyYXRpb24gYXBwbGll
+ZDwvaDI+CiAgICA8aDMgaWQ9InVuaXQtbmFtZSI+Jm5ic3A7PC9oMz4KICAgIDxhIHRhcmdldD0iX2Js
+YW5rIgogICAgICAgaHJlZj0iaHR0cHM6Ly9nb28uZ2xlL2RhcnQtbnVsbC1zYWZldHktbWlncmF0aW9u
+LXRvb2wiPgogICAgICA8YnV0dG9uIGNsYXNzPSJhY3Rpb24tYnV0dG9uIj4KICAgICAgICA8aSBjbGFz
+cz0ibWF0ZXJpYWwtaWNvbnMiPmxhdW5jaDwvaT4KICAgICAgICA8c3Bhbj5IZWxwPC9zcGFuPgogICAg
+ICA8L2J1dHRvbj4KICAgIDwvYT4KICAgIDxidXR0b24gY2xhc3M9ImFjdGlvbi1idXR0b24gYXBwbHkt
+bWlncmF0aW9uIj4KICAgICAgICA8aSBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMiPmVkaXQ8L2k+CiAgICAg
+ICAgPHNwYW4gY2xhc3M9ImxhYmVsIj4KICAgICAgICAgIEFwcGx5IE1pZ3JhdGlvbgogICAgICAgIDwv
+c3Bhbj4KICAgIDwvYnV0dG9uPgogICAgPGJ1dHRvbiBjbGFzcz0iYWN0aW9uLWJ1dHRvbiBhcHBseS1t
+aWdyYXRpb24iIGRpc2FibGVkPgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+ZWRpdDwv
 aT4KICAgICAgICA8c3BhbiBjbGFzcz0ibGFiZWwiPgogICAgICAgICAgQXBwbHkgTWlncmF0aW9uCiAg
 ICAgICAgPC9zcGFuPgogICAgPC9idXR0b24+CiAgICA8YnV0dG9uIGNsYXNzPSJhY3Rpb24tYnV0dG9u
-IGFwcGx5LW1pZ3JhdGlvbiIgZGlzYWJsZWQ+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25z
-Ij5lZGl0PC9pPgogICAgICAgIDxzcGFuIGNsYXNzPSJsYWJlbCI+CiAgICAgICAgICBBcHBseSBNaWdy
-YXRpb24KICAgICAgICA8L3NwYW4+CiAgICA8L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9ImFjdGlv
-bi1idXR0b24gcmVydW4tbWlncmF0aW9uIGJlZm9yZS1hcHBseSI+CiAgICAgIDxzcGFuIGNsYXNzPSJv
-cHRpb25hbCI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25zIj5yZXBsYXk8L2k+CiAgICAg
-ICAgUmVydW4gRnJvbSBTb3VyY2VzCiAgICAgIDwvc3Bhbj4KICAgICAgPHNwYW4gY2xhc3M9InJlcXVp
-cmVkIj4KICAgICAgICA8aSBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMiPndhcm5pbmc8L2k+CiAgICAgICAg
-UmVydW4gV2l0aCBDaGFuZ2VzCiAgICAgIDwvc3Bhbj4KICAgIDwvYnV0dG9uPgo8L2hlYWRlcj4KPGRp
-diBjbGFzcz0icGFuZWxzIGhvcml6b250YWwiPgogICAgPGRpdiBjbGFzcz0ibmF2LXBhbmVsIj4KICAg
-ICAgICA8ZGl2IGNsYXNzPSJuYXYtaW5uZXIiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1o
-ZWFkaW5nIj5Qcm9qZWN0IEZpbGVzPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im5hdi10cmVl
-Ij48L2Rpdj4KICAgICAgICA8L2Rpdj48IS0tIC9uYXYtaW5uZXIgLS0+CiAgICA8L2Rpdj48IS0tIC9u
-YXYgLS0+CiAgICA8ZGl2IGNsYXNzPSJjb250ZW50Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJyZWdpb25z
-Ij4KICAgICAgICAgICAgPCEtLSBUaGUgcmVnaW9ucyBvdmVybGF5IGNvZGUgY29weSBvZiB0aGUgY29u
-dGVudCB0byBwcm92aWRlIC0tPgogICAgICAgICAgICA8IS0tIHRvb2x0aXBzIGZvciBtb2RpZmllZCBy
-ZWdpb25zLiAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9yZWdpb25zIC0tPgogICAgICAgIDxkaXYgY2xh
-c3M9ImNvZGUiPgogICAgICAgICAgICA8IS0tIENvbXBpbGF0aW9uIHVuaXQgY29udGVudCBpcyB3cml0
-dGVuIGhlcmUuIC0tPgogICAgICAgICAgICA8cCBjbGFzcz0id2VsY29tZSI+CiAgICAgICAgICAgICAg
-ICBTZWxlY3QgYSBzb3VyY2UgZmlsZSBvbiB0aGUgbGVmdCB0byBwcmV2aWV3IHRoZSBwcm9wb3NlZCBl
-ZGl0cy4KICAgICAgICAgICAgPC9wPgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+PCEtLSAvY29udGVu
-dCAtLT4KICAgIDxkaXYgY2xhc3M9ImluZm8tcGFuZWwiPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQt
-bGlzdCI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPlByb3Bvc2VkIEVkaXRz
-PC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPjwvZGl2PgogICAgICAg
-IDwvZGl2PjwhLS0gL2VkaXQtbGlzdCAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LXBhbmVsIj4K
-ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+RWRpdCBEZXRhaWxzPC9kaXY+CiAg
-ICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPHAgY2xh
-c3M9InBsYWNlaG9sZGVyIj5TZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuPC9wPgogICAg
-ICAgICAgICA8L2Rpdj48IS0tIC9wYW5lbC1jb250ZW50IC0tPgogICAgICAgIDwvZGl2PjwhLS0gL2Vk
-aXQtcGFuZWwgLS0+CiAgICA8L2Rpdj48IS0tIC9pbmZvLXBhbmVsIC0tPgo8L2Rpdj48IS0tIC9wYW5l
-bHMgLS0+Cjxmb290ZXI+CiAgPGJ1dHRvbiBjbGFzcz0icmVwb3J0LXByb2JsZW0iPlNlbmQgRmVlZGJh
-Y2s8L2J1dHRvbj4KICAgIDxzcGFuIGNsYXNzPSJ3aWRlIj4gPC9zcGFuPgogICAgPGRpdiBjbGFzcz0i
-c2RrLXZlcnNpb24iPkJhc2VkIG9uIDxzcGFuIGlkPSJzZGstdmVyc2lvbiI+e3sgc2RrVmVyc2lvbiB9
-fTwvc3Bhbj48L2Rpdj4KPC9mb290ZXI+CjwvYm9keT4KPC9odG1sPgo=
+IHJlcnVuLW1pZ3JhdGlvbiBiZWZvcmUtYXBwbHkiPgogICAgICA8c3BhbiBjbGFzcz0ib3B0aW9uYWwi
+PgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+cmVwbGF5PC9pPgogICAgICAgIFJlcnVu
+IEZyb20gU291cmNlcwogICAgICA8L3NwYW4+CiAgICAgIDxzcGFuIGNsYXNzPSJyZXF1aXJlZCI+CiAg
+ICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25zIj53YXJuaW5nPC9pPgogICAgICAgIFJlcnVuIFdp
+dGggQ2hhbmdlcwogICAgICA8L3NwYW4+CiAgICA8L2J1dHRvbj4KPC9oZWFkZXI+CjxkaXYgY2xhc3M9
+InBhbmVscyBob3Jpem9udGFsIj4KICAgIDxkaXYgY2xhc3M9Im5hdi1wYW5lbCI+CiAgICAgICAgPGRp
+diBjbGFzcz0ibmF2LWlubmVyIj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+
+UHJvamVjdCBGaWxlczwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJuYXYtdHJlZSI+PC9kaXY+
+CiAgICAgICAgPC9kaXY+PCEtLSAvbmF2LWlubmVyIC0tPgogICAgPC9kaXY+PCEtLSAvbmF2IC0tPgog
+ICAgPGRpdiBjbGFzcz0iY29udGVudCI+CiAgICAgICAgPGRpdiBjbGFzcz0icmVnaW9ucyI+CiAgICAg
+ICAgICAgIDwhLS0gVGhlIHJlZ2lvbnMgb3ZlcmxheSBjb2RlIGNvcHkgb2YgdGhlIGNvbnRlbnQgdG8g
+cHJvdmlkZSAtLT4KICAgICAgICAgICAgPCEtLSB0b29sdGlwcyBmb3IgbW9kaWZpZWQgcmVnaW9ucy4g
+LS0+CiAgICAgICAgPC9kaXY+PCEtLSAvcmVnaW9ucyAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJjb2Rl
+Ij4KICAgICAgICAgICAgPCEtLSBDb21waWxhdGlvbiB1bml0IGNvbnRlbnQgaXMgd3JpdHRlbiBoZXJl
+LiAtLT4KICAgICAgICAgICAgPHAgY2xhc3M9IndlbGNvbWUiPgogICAgICAgICAgICAgICAgU2VsZWN0
+IGEgc291cmNlIGZpbGUgb24gdGhlIGxlZnQgdG8gcHJldmlldyB0aGUgcHJvcG9zZWQgZWRpdHMuCiAg
+ICAgICAgICAgIDwvcD4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PjwhLS0gL2NvbnRlbnQgLS0+CiAg
+ICA8ZGl2IGNsYXNzPSJpbmZvLXBhbmVsIj4KICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LWxpc3QiPgog
+ICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1oZWFkaW5nIj5Qcm9wb3NlZCBFZGl0czwvZGl2Pgog
+ICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1jb250ZW50Ij48L2Rpdj4KICAgICAgICA8L2Rpdj48
+IS0tIC9lZGl0LWxpc3QgLS0+CiAgICAgICAgPGRpdiBjbGFzcz0iZWRpdC1wYW5lbCI+CiAgICAgICAg
+ICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPkVkaXQgRGV0YWlsczwvZGl2PgogICAgICAgICAg
+ICA8ZGl2IGNsYXNzPSJwYW5lbC1jb250ZW50Ij4KICAgICAgICAgICAgICAgIDxwIGNsYXNzPSJwbGFj
+ZWhvbGRlciI+U2VlIGRldGFpbHMgYWJvdXQgYSBwcm9wb3NlZCBlZGl0LjwvcD4KICAgICAgICAgICAg
+PC9kaXY+PCEtLSAvcGFuZWwtY29udGVudCAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9lZGl0LXBhbmVs
+IC0tPgogICAgPC9kaXY+PCEtLSAvaW5mby1wYW5lbCAtLT4KPC9kaXY+PCEtLSAvcGFuZWxzIC0tPgo8
+Zm9vdGVyPgogIDxidXR0b24gY2xhc3M9InJlcG9ydC1wcm9ibGVtIj5TZW5kIEZlZWRiYWNrPC9idXR0
+b24+CiAgICA8c3BhbiBjbGFzcz0id2lkZSI+IDwvc3Bhbj4KICAgIDxkaXYgY2xhc3M9InNkay12ZXJz
+aW9uIj5CYXNlZCBvbiA8c3BhbiBpZD0ic2RrLXZlcnNpb24iPnt7IHNka1ZlcnNpb24gfX08L3NwYW4+
+PC9kaXY+CjwvZm9vdGVyPgo8L2JvZHk+CjwvaHRtbD4K
 ''';
 
 String _migration_css;
-// migration_css md5 is 'c3045f5a8c1f62b4e8f5efd90e079029'
+// migration_css md5 is 'aa4c1eeef41fd9f06779ba7bac691ac2'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
@@ -7590,104 +7591,103 @@
 ZS1ubyB7CiAgYm9yZGVyLXJpZ2h0OiBzb2xpZCAjY2NjIDJweDsKfQoKLnJlZ2lvbiB7CiAgZGlzcGxh
 eTogaW5saW5lLWJsb2NrOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB2aXNpYmlsaXR5OiB2aXNpYmxl
 OwogIHotaW5kZXg6IDIwMDsKfQoKLnJlZ2lvbi5hZGRlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29s
-b3I6ICMyNjM5NTI7IC8qICRkYXJrLXNlbGVjdGlvbi1jb2xvciAqLwogIGNvbG9yOiAjYzBjMmM1OyAv
-KiAkZGFyay1lZGl0b3ItdGV4dCAqLwp9CgoucmVnaW9uLnJlbW92ZWQtcmVnaW9uIHsKICBiYWNrZ3Jv
-dW5kLWNvbG9yOiAjRkE1NTdkOyAvKiAkZGFyay1waW5rICovCiAgY29sb3I6ICNmZmY7Cn0KCi5yZWdp
-b24uaW5mb3JtYXRpdmUtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTc4YWZkOyAvKiAkZGFy
-ay1zZWxlY3Rpb24tY29sb3IgKi8KICBjb2xvcjogI2ZmZjsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7
-CiAgaGVpZ2h0OiAxNHB4OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB0b3A6IDFweDsKfQoKLnRhcmdl
-dCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdmlzaWJp
-bGl0eTogdmlzaWJsZTsKICBmb250LXdlaWdodDogNjAwOwp9CgouaW5mby1wYW5lbCB7CiAgZmxleDog
-MSAyMDBweDsKICBtYXJnaW46IDA7CiAgaGVpZ2h0OiAxMDAlOwogIGRpc3BsYXk6IGZsZXg7CiAgZmxl
-eC1kaXJlY3Rpb246IGNvbHVtbjsKfQoKLmluZm8tcGFuZWwgLmVkaXQtcGFuZWwgewogIGJhY2tncm91
-bmQtY29sb3I6ICMxMjIwMmY7CiAgb3ZlcmZsb3c6IGF1dG87Cn0KCi5pbmZvLXBhbmVsIC5wYW5lbC1j
-b250ZW50IHsKICBwYWRkaW5nOiA3cHg7Cn0KCi5pbmZvLXBhbmVsIC5wYW5lbC1jb250ZW50PiA6Zmly
-c3QtY2hpbGQgewogIG1hcmdpbi10b3A6IDA7Cn0KCi5pbmZvLXBhbmVsIC5ub3dyYXAgewogIHdoaXRl
-LXNwYWNlOiBub3dyYXA7Cn0KCi5pbmZvLXBhbmVsIHVsLAouaW5mby1wYW5lbCBvbCB7CiAgcGFkZGlu
-Zy1sZWZ0OiAyMHB4Owp9CgouaW5mby1wYW5lbCBsaSB7CiAgbWFyZ2luOiAwIDAgNXB4IDA7Cn0KCi5p
-bmZvLXBhbmVsIGEgewogIGNvbG9yOiAjMTM5YmI1Owp9CgouaW5mby1wYW5lbCBhOmhvdmVyIHsKICBj
-b2xvcjogIzFlYzdlNzsgLyogIzEzOWJiNSBsaWdodGVuZWQgMjAlICovCn0KCi5pbmZvLXBhbmVsIC5l
-ZGl0LWxpc3QgewogIGJhY2tncm91bmQtY29sb3I6ICMxMjIwMmY7CiAgb3ZlcmZsb3c6IGF1dG87Cn0K
-Ci5lZGl0LXBhbmVsIHsKICBtYXJnaW4tdG9wOiA2cHg7CiAgZmxleDogMSAxMDBweDsKfQoKLmVkaXQt
-bGlzdCB7CiAgZmxleDogMiAxMDBweDsKfQoKLmVkaXQtbGlzdCAuZWRpdCB7CiAgbWFyZ2luOiAzcHgg
-MDsKfQoKLmVkaXQtbGlzdCAuZWRpdC1saW5rIHsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5wb3B1cC1w
-YW5lIHsKICBkaXNwbGF5OiBub25lOwogIHBvc2l0aW9uOiBmaXhlZDsKICB0b3A6IDE1MHB4OwogIGxl
-ZnQ6IDE1MHB4OwogIHJpZ2h0OiAxNTBweDsKICBib3R0b206IDE1MHB4OwogIGJvcmRlcjogMXB4IHNv
-bGlkIGJsYWNrOwogIGJvcmRlci10b3A6IDJweCBzb2xpZCBibGFjazsKICBib3JkZXItcmFkaXVzOiA3
-cHg7CiAgYm94LXNoYWRvdzogMHB4IDBweCAyMHB4IDJweCAjYjRiZmNiMjI7CiAgei1pbmRleDogNDAw
-OwogIGJhY2tncm91bmQ6ICMyYjMwMzY7CiAgcGFkZGluZzogMjBweDsKfQoKLnBvcHVwLXBhbmUgLmNs
-b3NlIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgcmlnaHQ6IDEwcHg7CiAgdG9wOiAxMHB4OwogIGN1
-cnNvcjogcG9pbnRlcjsKICB0ZXh0LXNoYWRvdzogMXB4IDFweCAycHggIzg4ODsKICBib3gtc2hhZG93
-OiAxcHggMXB4IDJweCAjMTExOwp9CgoucG9wdXAtcGFuZSBoMiB7CiAgcGFkZGluZzogMjFweDsKICBo
-ZWlnaHQ6IDEwJTsKICBtYXJnaW46IDBweDsKICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgoucG9w
-dXAtcGFuZSBwIHsKICBoZWlnaHQ6IDEwJTsKICBib3gtc2l6aW5nOiBib3JkZXItYm94OwogIHBhZGRp
-bmc6IDBweCAyMHB4Owp9CgoucG9wdXAtcGFuZSBwcmUgewogIGJhY2tncm91bmQ6ICMxMjIwMmY7CiAg
-cGFkZGluZzogMjBweDsKICBib3R0b206IDBweDsKICBvdmVyZmxvdzogYXV0byBzY3JvbGw7CiAgaGVp
-Z2h0OiA2NSU7CiAgbWFyZ2luOiAwcHg7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKfQoKLnBvcHVw
-LXBhbmUgLmJ1dHRvbi5ib3R0b20gewogIG1hcmdpbjogMjBweCAwcHg7CiAgZGlzcGxheTogYmxvY2s7
-CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgoucmVydW5uaW5nLXBhbmUgewogIGRpc3BsYXk6IG5vbmU7
-Cn0KCmJvZHkucmVydW5uaW5nIC5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTogYmxvY2s7CiAgcG9z
-aXRpb246IGZpeGVkOwogIHRvcDogMHB4OwogIGJvdHRvbTogMHB4OwogIGxlZnQ6IDBweDsKICByaWdo
-dDogMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDBBQTsgLyogdHJhbnNsdWNlbnQgYmxhY2sg
-Ki8KICB6LWluZGV4OiA0MDA7Cn0KCi5yZXJ1bm5pbmctcGFuZSBoMSB7CiAgcG9zaXRpb246IGFic29s
-dXRlOwogIHRvcDogNTAlOwogIGxlZnQ6IDUwJTsKICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAt
-NTAlKTsKfQoKLmVkaXQtcGFuZWwgLnR5cGUtZGVzY3JpcHRpb24gewogIC8qIEZyb20gRGFydFBhZCAk
-ZGFyay1vcmFuZ2UgKi8KICBjb2xvcjogI2ZmOTE2ZTsKICBmb250LWZhbWlseTogbW9ub3NwYWNlOwp9
-Cgp1bC50cmFjZSB7CiAgZm9udC1zaXplOiAxM3B4OwogIGxpc3Qtc3R5bGUtdHlwZTogbm9uZTsKICBw
-YWRkaW5nLWxlZnQ6IDBweDsKfQoKdWwudHJhY2UgbGkgewogIGNvbG9yOiB3aGl0ZTsKfQoKdWwudHJh
-Y2UgbGkgLmZ1bmN0aW9uIHsKICAvKiBmcm9tIC5obGpzLXZhcmlhYmxlICovCiAgY29sb3I6ICMxNmFk
-Y2E7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXdlaWdodDogNjAwOwp9Cgp1bC50cmFj
-ZSBsaSBwLmRyYXdlciB7CiAgbWFyZ2luOiAzcHggMHB4OwogIHBhZGRpbmc6IDBweCAwcHggMHB4IDE0
-cHg7Cn0KCnVsLnRyYWNlIGxpIHAuZHJhd2VyIGJ1dHRvbiB7CiAgbWFyZ2luLXJpZ2h0OiAzcHg7Cn0K
-Ci5lbGV2YXRpb24tejQgewogIGJveC1zaGFkb3c6IDBweCAycHggNHB4IC0xcHggcmdiYSgwLCAwLCAw
-LCAwLjIpLAogICAgICAwcHggNHB4IDVweCAwcHggcmdiYSgwLCAwLCAwLCAwLjE0KSwKICAgICAgMHB4
-IDFweCAxMHB4IDBweCByZ2JhKDAsIDAsIDAsIC4xMik7Cn0KCmEgewogIGNvbG9yOiAjY2NjOwogIGZp
-bGw6ICNjY2M7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CgphOmhvdmVyIHsKICBjb2xvcjogI2Ri
-ZGJkYjsgLyogI2NjYyBsaWdodGVudGVkIDMwJSovCiAgZmlsbDogI2ZmZjsKfQoKLmFkZC1oaW50LWxp
-bmsgewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBtYXJnaW46IDNweDsKfQoKLmFkZC1oaW50LWxp
-bms6aG92ZXIgewogIGNvbG9yOiAjZmZmOwp9CgpoZWFkZXIgYnV0dG9uIHsKICB0ZXh0LXRyYW5zZm9y
-bTogdXBwZXJjYXNlOwp9CgpoZWFkZXIgYSB7CiAgbWFyZ2luOiAwOwp9CgovKiBDYXJlZnVsIGhlcmUu
-IGBhLmJ1dHRvbmAgaXMgcmVwZXRpdGl2ZSBidXQgcmVxdWlyZWQgdG8gZ2V0IGNvcnJlY3QKICogc3Bl
-Y2lmaWNpdHkgKi8KYnV0dG9uLCAuYnV0dG9uLCBhLmJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjog
-cmdiYSgyMiwgMTM4LCAyNTMsIDAuMTUpOwogIGJvcmRlcjogbm9uZTsKICBib3JkZXItcmFkaXVzOiAz
-cHg7CiAgcGFkZGluZzogM3B4IDEwcHg7CiAgZm9udC13ZWlnaHQ6IDUwMDsKICBmb250LWZvbnQ6IFJv
-Ym90bywgc2Fucy1zZXJpZjsKICBjb2xvcjogI2ZmZjsKfQoKYnV0dG9uOmhvdmVyLCAuYnV0dG9uOmhv
-dmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyLCAxMzgsIDI1MywgMC4yOSk7CiAgY3Vyc29y
-OiBwb2ludGVyOwp9CgpidXR0b25bZGlzYWJsZWRdIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1
-NSwyNTUsMjU1LC4xMik7CiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsLjM3KTsKICBjdXJzb3I6IG5v
-dC1hbGxvd2VkOwp9CgovKiBDaGFuZ2UgZWRpdCBwYW5lbCBidXR0b24gY29sb3JzICovCi5lZGl0LXBh
-bmVsIC5idXR0b24sIC5lZGl0LXBhbmVsIGJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg2
-MywgMTA0LCAxNDgsIDAuNik7CiAgY29sb3I6IHdoaXRlOwp9Ci5lZGl0LXBhbmVsIC5idXR0b246aG92
-ZXIsIC5lZGl0LXBhbmVsIGJ1dHRvbjpob3ZlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgxMDEs
-IDE1MywgMjA4LCAwLjYpOwogIGNvbG9yOiB3aGl0ZTsKfQoKLyoKICogQWRqdXN0bWVudHMgdG8gYWxp
-Z24gbWF0ZXJpYWwgaWNvbnMgaW4gdGhlIHRvb2xiYXIgYnV0dG9ucy4KKi8KLmFjdGlvbi1idXR0b24g
-PiBzcGFuIHsKICBwb3NpdGlvbjpyZWxhdGl2ZTsKICB0b3A6IC0zcHg7Cn0KCi5hY3Rpb24tYnV0dG9u
-IC5tYXRlcmlhbC1pY29ucyB7CiAgdG9wOiA0cHg7Cn0KCi8qIERvbid0IHNoaWZ0IHRoZSBpY29uIHdo
-ZW4gaXQncyBhIGRpcmVjdCBjaGlsZCBvZiB0aGUgYnV0dG9uICovCi5hY3Rpb24tYnV0dG9uID4gLm1h
-dGVyaWFsLWljb25zIHsKICB0b3A6IDFweDsKfQoKLyogU2hpZnQgdGhlIHRleHQgdG8gY2VudGVyIHdp
-dGggdGhlIGljb24uICovCi5hY3Rpb24tYnV0dG9uID4gc3Bhbi5sYWJlbCB7CiAgcG9zaXRpb246cmVs
-YXRpdmU7CiAgdG9wOiAtNHB4Owp9CgouYWN0aW9uLWJ1dHRvbiAubWF0ZXJpYWwtaWNvbnMgewogIGZv
-bnQtc2l6ZTogMjBweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7Cn0KCi5wbGFjZWhvbGRlciB7CiAgY29s
-b3I6ICM3Nzc7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIG1hcmdpbi10b3A6IDNlbSAhaW1wb3J0YW50
-Owp9CgovKioKICogSExKUyBPdmVycmlkZXMKICovCi5obGpzIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAj
-MTIyMDJmOyAvKiAkZGFyay1jb2RlLWJhY2tncm91bmQtY29sb3IgKi8KICBjb2xvcjogI2MwYzJjNTsg
-LyogJGRhcmstZWRpdG9yLXRleHQgKi8KICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdy14OiBhdXRv
-OwogIHBhZGRpbmc6IDAuNWVtOwogIC8qKgogICAqIFRoaXMgYWxsb3dzIHRoZSBwZXItbGluZSBoaWdo
-bGlnaHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9uZTsKfQoKLmhsanMta2V5d29yZCwK
-LmhsanMtc2VsZWN0b3ItdGFnLAouaGxqcy1kZWxldGlvbiB7CiAgY29sb3I6ICM1MWM2ODY7IC8qIGNt
-LWtleXdvcmQgKi8KfQoKLmhsanMtbnVtYmVyIHsKICBjb2xvcjogIzYyNzk3ODsgLyogY20tbnVtYmVy
-ICovCn0KCi5obGpzLWNvbW1lbnQgewogIGNvbG9yOiAjOTE5OGI0OyAvKiBjbS1jb21tZW50ICovCn0K
-Ci5obGpzLWxpdGVyYWwgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS1hdG9tICovCn0KCi5obGpzLXN0
-cmluZyB7CiAgY29sb3I6ICNlNTUwNzQ7IC8qIGNtLXN0cmluZyAqLwp9CgouaGxqcy12YXJpYWJsZSB7
-CiAgY29sb3I6ICMxNmFkY2E7IC8qIGNtLXZhcmlhYmxlICovCn0KCi5obGpzLWxpbmsgewogIGNvbG9y
-OiAjZTU1MDc0OyAvKiBjbS1zdHJpbmcgKi8KfQouaGxqcy1zZWN0aW9uLAouaGxqcy10eXBlLAouaGxq
-cy1idWlsdF9pbiwKLmhsanMtdGl0bGUgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS12YXJpYWJsZS0y
-ICovCn0KCi5obGpzLWFkZGl0aW9uIHsKICBjb2xvcjogIzI2Mzk1MjsgLyogJGRhcmstc2VsZWN0aW9u
-LWNvbG9yICovCn0KCi5obGpzLW1ldGEgewogIGNvbG9yOiAjNjI3OTc4Owp9Cg==
+b3I6ICMxNzhhZmQ7CiAgY29sb3I6ICNmZmY7Cn0KCi5yZWdpb24ucmVtb3ZlZC1yZWdpb24gewogIGJh
+Y2tncm91bmQtY29sb3I6ICNGQTU1N2Q7IC8qICRkYXJrLXBpbmsgKi8KICBjb2xvcjogI2ZmZjsKfQoK
+LnJlZ2lvbi5pbmZvcm1hdGl2ZS1yZWdpb24gewogIGJhY2tncm91bmQtY29sb3I6ICMyNjM5NTI7CiAg
+Y29sb3I6ICNmZmY7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIGhlaWdodDogMTVweDsKICBwb3Np
+dGlvbjogcmVsYXRpdmU7CiAgdG9wOiAycHg7Cn0KCi50YXJnZXQgewogIGJhY2tncm91bmQtY29sb3I6
+ICM0NDQ7CiAgcG9zaXRpb246IHJlbGF0aXZlOwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAgZm9udC13
+ZWlnaHQ6IDYwMDsKfQoKLmluZm8tcGFuZWwgewogIGZsZXg6IDEgMjAwcHg7CiAgbWFyZ2luOiAwOwog
+IGhlaWdodDogMTAwJTsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47Cn0K
+Ci5pbmZvLXBhbmVsIC5lZGl0LXBhbmVsIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTIyMDJmOwogIG92
+ZXJmbG93OiBhdXRvOwp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudCB7CiAgcGFkZGluZzogN3B4
+Owp9CgouaW5mby1wYW5lbCAucGFuZWwtY29udGVudD4gOmZpcnN0LWNoaWxkIHsKICBtYXJnaW4tdG9w
+OiAwOwp9CgouaW5mby1wYW5lbCAubm93cmFwIHsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwp9CgouaW5m
+by1wYW5lbCB1bCwKLmluZm8tcGFuZWwgb2wgewogIHBhZGRpbmctbGVmdDogMjBweDsKfQoKLmluZm8t
+cGFuZWwgbGkgewogIG1hcmdpbjogMCAwIDVweCAwOwp9CgouaW5mby1wYW5lbCBhIHsKICBjb2xvcjog
+IzEzOWJiNTsKfQoKLmluZm8tcGFuZWwgYTpob3ZlciB7CiAgY29sb3I6ICMxZWM3ZTc7IC8qICMxMzli
+YjUgbGlnaHRlbmVkIDIwJSAqLwp9CgouaW5mby1wYW5lbCAuZWRpdC1saXN0IHsKICBiYWNrZ3JvdW5k
+LWNvbG9yOiAjMTIyMDJmOwogIG92ZXJmbG93OiBhdXRvOwp9CgouZWRpdC1wYW5lbCB7CiAgbWFyZ2lu
+LXRvcDogNnB4OwogIGZsZXg6IDEgMTAwcHg7Cn0KCi5lZGl0LWxpc3QgewogIGZsZXg6IDIgMTAwcHg7
+Cn0KCi5lZGl0LWxpc3QgLmVkaXQgewogIG1hcmdpbjogM3B4IDA7Cn0KCi5lZGl0LWxpc3QgLmVkaXQt
+bGluayB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoucG9wdXAtcGFuZSB7CiAgZGlzcGxheTogbm9uZTsK
+ICBwb3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAxNTBweDsKICBsZWZ0OiAxNTBweDsKICByaWdodDogMTUw
+cHg7CiAgYm90dG9tOiAxNTBweDsKICBib3JkZXI6IDFweCBzb2xpZCBibGFjazsKICBib3JkZXItdG9w
+OiAycHggc29saWQgYmxhY2s7CiAgYm9yZGVyLXJhZGl1czogN3B4OwogIGJveC1zaGFkb3c6IDBweCAw
+cHggMjBweCAycHggI2I0YmZjYjIyOwogIHotaW5kZXg6IDQwMDsKICBiYWNrZ3JvdW5kOiAjMmIzMDM2
+OwogIHBhZGRpbmc6IDIwcHg7Cn0KCi5wb3B1cC1wYW5lIC5jbG9zZSB7CiAgcG9zaXRpb246IGFic29s
+dXRlOwogIHJpZ2h0OiAxMHB4OwogIHRvcDogMTBweDsKICBjdXJzb3I6IHBvaW50ZXI7CiAgdGV4dC1z
+aGFkb3c6IDFweCAxcHggMnB4ICM4ODg7CiAgYm94LXNoYWRvdzogMXB4IDFweCAycHggIzExMTsKfQoK
+LnBvcHVwLXBhbmUgaDIgewogIHBhZGRpbmc6IDIxcHg7CiAgaGVpZ2h0OiAxMCU7CiAgbWFyZ2luOiAw
+cHg7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKfQoKLnBvcHVwLXBhbmUgcCB7CiAgaGVpZ2h0OiAx
+MCU7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKICBwYWRkaW5nOiAwcHggMjBweDsKfQoKLnBvcHVw
+LXBhbmUgcHJlIHsKICBiYWNrZ3JvdW5kOiAjMTIyMDJmOwogIHBhZGRpbmc6IDIwcHg7CiAgYm90dG9t
+OiAwcHg7CiAgb3ZlcmZsb3c6IGF1dG8gc2Nyb2xsOwogIGhlaWdodDogNjUlOwogIG1hcmdpbjogMHB4
+OwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7Cn0KCi5wb3B1cC1wYW5lIC5idXR0b24uYm90dG9tIHsK
+ICBtYXJnaW46IDIwcHggMHB4OwogIGRpc3BsYXk6IGJsb2NrOwogIHRleHQtYWxpZ246IGNlbnRlcjsK
+fQoKLnJlcnVubmluZy1wYW5lIHsKICBkaXNwbGF5OiBub25lOwp9Cgpib2R5LnJlcnVubmluZyAucmVy
+dW5uaW5nLXBhbmUgewogIGRpc3BsYXk6IGJsb2NrOwogIHBvc2l0aW9uOiBmaXhlZDsKICB0b3A6IDBw
+eDsKICBib3R0b206IDBweDsKICBsZWZ0OiAwcHg7CiAgcmlnaHQ6IDBweDsKICBiYWNrZ3JvdW5kLWNv
+bG9yOiAjMDAwMDAwQUE7IC8qIHRyYW5zbHVjZW50IGJsYWNrICovCiAgei1pbmRleDogNDAwOwp9Cgou
+cmVydW5uaW5nLXBhbmUgaDEgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICB0b3A6IDUwJTsKICBsZWZ0
+OiA1MCU7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7Cn0KCi5lZGl0LXBhbmVsIC50
+eXBlLWRlc2NyaXB0aW9uIHsKICAvKiBGcm9tIERhcnRQYWQgJGRhcmstb3JhbmdlICovCiAgY29sb3I6
+ICNmZjkxNmU7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKfQoKdWwudHJhY2UgewogIGZvbnQtc2l6
+ZTogMTNweDsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7CiAgcGFkZGluZy1sZWZ0OiAwcHg7Cn0KCnVs
+LnRyYWNlIGxpIHsKICBjb2xvcjogd2hpdGU7Cn0KCnVsLnRyYWNlIGxpIC5mdW5jdGlvbiB7CiAgLyog
+ZnJvbSAuaGxqcy12YXJpYWJsZSAqLwogIGNvbG9yOiAjMTZhZGNhOwogIGZvbnQtZmFtaWx5OiBtb25v
+c3BhY2U7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKdWwudHJhY2UgbGkgcC5kcmF3ZXIgewogIG1hcmdp
+bjogM3B4IDBweDsKICBwYWRkaW5nOiAwcHggMHB4IDBweCAxNHB4Owp9Cgp1bC50cmFjZSBsaSBwLmRy
+YXdlciBidXR0b24gewogIG1hcmdpbi1yaWdodDogM3B4Owp9CgouZWxldmF0aW9uLXo0IHsKICBib3gt
+c2hhZG93OiAwcHggMnB4IDRweCAtMXB4IHJnYmEoMCwgMCwgMCwgMC4yKSwKICAgICAgMHB4IDRweCA1
+cHggMHB4IHJnYmEoMCwgMCwgMCwgMC4xNCksCiAgICAgIDBweCAxcHggMTBweCAwcHggcmdiYSgwLCAw
+LCAwLCAuMTIpOwp9CgphIHsKICBjb2xvcjogI2NjYzsKICBmaWxsOiAjY2NjOwogIHRleHQtZGVjb3Jh
+dGlvbjogbm9uZTsKfQoKYTpob3ZlciB7CiAgY29sb3I6ICNkYmRiZGI7IC8qICNjY2MgbGlnaHRlbnRl
+ZCAzMCUqLwogIGZpbGw6ICNmZmY7Cn0KCi5hZGQtaGludC1saW5rIHsKICBkaXNwbGF5OiBpbmxpbmUt
+YmxvY2s7CiAgbWFyZ2luOiAzcHg7Cn0KCi5hZGQtaGludC1saW5rOmhvdmVyIHsKICBjb2xvcjogI2Zm
+ZjsKfQoKaGVhZGVyIGJ1dHRvbiB7CiAgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsKfQoKaGVhZGVy
+IGEgewogIG1hcmdpbjogMDsKfQoKLyogQ2FyZWZ1bCBoZXJlLiBgYS5idXR0b25gIGlzIHJlcGV0aXRp
+dmUgYnV0IHJlcXVpcmVkIHRvIGdldCBjb3JyZWN0CiAqIHNwZWNpZmljaXR5ICovCmJ1dHRvbiwgLmJ1
+dHRvbiwgYS5idXR0b24gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMjIsIDEzOCwgMjUzLCAwLjE1
+KTsKICBib3JkZXI6IG5vbmU7CiAgYm9yZGVyLXJhZGl1czogM3B4OwogIHBhZGRpbmc6IDNweCAxMHB4
+OwogIGZvbnQtd2VpZ2h0OiA1MDA7CiAgZm9udC1mb250OiBSb2JvdG8sIHNhbnMtc2VyaWY7CiAgY29s
+b3I6ICNmZmY7Cn0KCmJ1dHRvbjpob3ZlciwgLmJ1dHRvbjpob3ZlciB7CiAgYmFja2dyb3VuZC1jb2xv
+cjogcmdiYSgyMiwgMTM4LCAyNTMsIDAuMjkpOwogIGN1cnNvcjogcG9pbnRlcjsKfQoKYnV0dG9uW2Rp
+c2FibGVkXSB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgyNTUsMjU1LDI1NSwuMTIpOwogIGNvbG9y
+OiByZ2JhKDI1NSwyNTUsMjU1LC4zNyk7CiAgY3Vyc29yOiBub3QtYWxsb3dlZDsKfQoKLyogQ2hhbmdl
+IGVkaXQgcGFuZWwgYnV0dG9uIGNvbG9ycyAqLwouZWRpdC1wYW5lbCAuYnV0dG9uLCAuZWRpdC1wYW5l
+bCBidXR0b24gewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoNjMsIDEwNCwgMTQ4LCAwLjYpOwogIGNv
+bG9yOiB3aGl0ZTsKfQouZWRpdC1wYW5lbCAuYnV0dG9uOmhvdmVyLCAuZWRpdC1wYW5lbCBidXR0b246
+aG92ZXIgewogIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMTAxLCAxNTMsIDIwOCwgMC42KTsKICBjb2xv
+cjogd2hpdGU7Cn0KCi8qCiAqIEFkanVzdG1lbnRzIHRvIGFsaWduIG1hdGVyaWFsIGljb25zIGluIHRo
+ZSB0b29sYmFyIGJ1dHRvbnMuCiovCi5hY3Rpb24tYnV0dG9uID4gc3BhbiB7CiAgcG9zaXRpb246cmVs
+YXRpdmU7CiAgdG9wOiAtM3B4Owp9CgouYWN0aW9uLWJ1dHRvbiAubWF0ZXJpYWwtaWNvbnMgewogIHRv
+cDogNHB4Owp9CgovKiBEb24ndCBzaGlmdCB0aGUgaWNvbiB3aGVuIGl0J3MgYSBkaXJlY3QgY2hpbGQg
+b2YgdGhlIGJ1dHRvbiAqLwouYWN0aW9uLWJ1dHRvbiA+IC5tYXRlcmlhbC1pY29ucyB7CiAgdG9wOiAx
+cHg7Cn0KCi8qIFNoaWZ0IHRoZSB0ZXh0IHRvIGNlbnRlciB3aXRoIHRoZSBpY29uLiAqLwouYWN0aW9u
+LWJ1dHRvbiA+IHNwYW4ubGFiZWwgewogIHBvc2l0aW9uOnJlbGF0aXZlOwogIHRvcDogLTRweDsKfQoK
+LmFjdGlvbi1idXR0b24gLm1hdGVyaWFsLWljb25zIHsKICBmb250LXNpemU6IDIwcHg7CiAgcG9zaXRp
+b246IHJlbGF0aXZlOwp9CgoucGxhY2Vob2xkZXIgewogIGNvbG9yOiAjNzc3OwogIHRleHQtYWxpZ246
+IGNlbnRlcjsKICBtYXJnaW4tdG9wOiAzZW0gIWltcG9ydGFudDsKfQoKLyoqCiAqIEhMSlMgT3ZlcnJp
+ZGVzCiAqLwouaGxqcyB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzEyMjAyZjsgLyogJGRhcmstY29kZS1i
+YWNrZ3JvdW5kLWNvbG9yICovCiAgY29sb3I6ICNjMGMyYzU7IC8qICRkYXJrLWVkaXRvci10ZXh0ICov
+CiAgZGlzcGxheTogYmxvY2s7CiAgb3ZlcmZsb3cteDogYXV0bzsKICBwYWRkaW5nOiAwLjVlbTsKICAv
+KioKICAgKiBUaGlzIGFsbG93cyB0aGUgcGVyLWxpbmUgaGlnaGxpZ2h0cyB0byBzaG93LgogICAqLwog
+IGJhY2tncm91bmQ6IG5vbmU7Cn0KCi5obGpzLWtleXdvcmQsCi5obGpzLXNlbGVjdG9yLXRhZywKLmhs
+anMtZGVsZXRpb24gewogIGNvbG9yOiAjNTFjNjg2OyAvKiBjbS1rZXl3b3JkICovCn0KCi5obGpzLW51
+bWJlciB7CiAgY29sb3I6ICM2Mjc5Nzg7IC8qIGNtLW51bWJlciAqLwp9CgouaGxqcy1jb21tZW50IHsK
+ICBjb2xvcjogIzkxOThiNDsgLyogY20tY29tbWVudCAqLwp9CgouaGxqcy1saXRlcmFsIHsKICBjb2xv
+cjogI2VlODY2NjsgLyogY20tYXRvbSAqLwp9CgouaGxqcy1zdHJpbmcgewogIGNvbG9yOiAjZTU1MDc0
+OyAvKiBjbS1zdHJpbmcgKi8KfQoKLmhsanMtdmFyaWFibGUgewogIGNvbG9yOiAjMTZhZGNhOyAvKiBj
+bS12YXJpYWJsZSAqLwp9CgouaGxqcy1saW5rIHsKICBjb2xvcjogI2U1NTA3NDsgLyogY20tc3RyaW5n
+ICovCn0KLmhsanMtc2VjdGlvbiwKLmhsanMtdHlwZSwKLmhsanMtYnVpbHRfaW4sCi5obGpzLXRpdGxl
+IHsKICBjb2xvcjogI2VlODY2NjsgLyogY20tdmFyaWFibGUtMiAqLwp9CgouaGxqcy1hZGRpdGlvbiB7
+CiAgY29sb3I6ICMyNjM5NTI7IC8qICRkYXJrLXNlbGVjdGlvbi1jb2xvciAqLwp9CgouaGxqcy1tZXRh
+IHsKICBjb2xvcjogIzYyNzk3ODsKfQo=
 ''';
 
 String _migration_js;
-// migration_dart md5 is 'd04379013212a42347eb972f1bbcde3e'
+// migration_dart md5 is '6102ec712b1621d5b1eb706530f5efd2'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgcz1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHI9MDtyPHMubGVuZ3RoO3IrKyl7dmFyIHE9c1tyXQpiW3FdPWFb
@@ -7713,3873 +7713,3985 @@
 c2Ugcj1hW2JdfWZpbmFsbHl7aWYocj09PXEpYVtiXT1udWxsCmFbY109ZnVuY3Rpb24oKXtyZXR1cm4g
 dGhpc1tiXX19cmV0dXJuIHJ9fWZ1bmN0aW9uIGxhenkoYSxiLGMsZCl7dmFyIHM9YQphW2JdPXMKYVtj
 XT1mdW5jdGlvbigpe2lmKGFbYl09PT1zKWFbYl09ZCgpCmFbY109ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
-c1tiXX0KcmV0dXJuIGFbYl19fWZ1bmN0aW9uIG1ha2VDb25zdExpc3QoYSl7YS5pbW11dGFibGUkbGlz
-dD1BcnJheQphLmZpeGVkJGxlbmd0aD1BcnJheQpyZXR1cm4gYX1mdW5jdGlvbiBjb252ZXJ0VG9GYXN0
-T2JqZWN0KGEpe2Z1bmN0aW9uIHQoKXt9dC5wcm90b3R5cGU9YQpuZXcgdCgpCnJldHVybiBhfWZ1bmN0
-aW9uIGNvbnZlcnRBbGxUb0Zhc3RPYmplY3QoYSl7Zm9yKHZhciBzPTA7czxhLmxlbmd0aDsrK3MpY29u
-dmVydFRvRmFzdE9iamVjdChhW3NdKX12YXIgeT0wCmZ1bmN0aW9uIHRlYXJPZmZHZXR0ZXIoYSxiLGMs
-ZCxlKXtyZXR1cm4gZT9uZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJy
-ZWZsZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5
-KysrIihyZWNlaXZlcikgeyIrImlmIChjID09PSBudWxsKSBjID0gIisiSC5LcSIrIigiKyJ0aGlzLCBm
-dW5jcywgYXBwbHlUcmFtcG9saW5lSW5kZXgsIHJlZmxlY3Rpb25JbmZvLCBmYWxzZSwgdHJ1ZSwgbmFt
-ZSk7IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1bmNzWzBdLCByZWNlaXZlciwgbmFtZSk7IisifSIpKGEs
-YixjLGQsSCxudWxsKTpuZXcgRnVuY3Rpb24oImZ1bmNzIiwiYXBwbHlUcmFtcG9saW5lSW5kZXgiLCJy
-ZWZsZWN0aW9uSW5mbyIsIm5hbWUiLCJIIiwiYyIsInJldHVybiBmdW5jdGlvbiB0ZWFyT2ZmXyIrZCt5
-KysrIigpIHsiKyJpZiAoYyA9PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFw
-cGx5VHJhbXBvbGluZUluZGV4LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIGZhbHNlLCBuYW1lKTsiKyJy
-ZXR1cm4gbmV3IGModGhpcywgZnVuY3NbMF0sIG51bGwsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVs
-bCl9ZnVuY3Rpb24gdGVhck9mZihhLGIsYyxkLGUsZil7dmFyIHM9bnVsbApyZXR1cm4gZD9mdW5jdGlv
-bigpe2lmKHM9PT1udWxsKXM9SC5LcSh0aGlzLGEsYixjLHRydWUsZmFsc2UsZSkucHJvdG90eXBlCnJl
-dHVybiBzfTp0ZWFyT2ZmR2V0dGVyKGEsYixjLGUsZil9dmFyIHg9MApmdW5jdGlvbiBpbnN0YWxsVGVh
-ck9mZihhLGIsYyxkLGUsZixnLGgsaSxqKXt2YXIgcz1bXQpmb3IodmFyIHI9MDtyPGgubGVuZ3RoO3Ir
-Kyl7dmFyIHE9aFtyXQppZih0eXBlb2YgcT09J3N0cmluZycpcT1hW3FdCnEuJGNhbGxOYW1lPWdbcl0K
-cy5wdXNoKHEpfXZhciBxPXNbMF0KcS4kUj1lCnEuJEQ9Zgp2YXIgcD1pCmlmKHR5cGVvZiBwPT0ibnVt
-YmVyIilwKz14CnZhciBvPWhbMF0KcS4kc3R1Yk5hbWU9bwp2YXIgbj10ZWFyT2ZmKHMsanx8MCxwLGMs
-byxkKQphW2JdPW4KaWYoYylxLiR0ZWFyT2ZmPW59ZnVuY3Rpb24gaW5zdGFsbFN0YXRpY1RlYXJPZmYo
-YSxiLGMsZCxlLGYsZyxoKXtyZXR1cm4gaW5zdGFsbFRlYXJPZmYoYSxiLHRydWUsZmFsc2UsYyxkLGUs
-ZixnLGgpfWZ1bmN0aW9uIGluc3RhbGxJbnN0YW5jZVRlYXJPZmYoYSxiLGMsZCxlLGYsZyxoLGkpe3Jl
-dHVybiBpbnN0YWxsVGVhck9mZihhLGIsZmFsc2UsYyxkLGUsZixnLGgsaSl9ZnVuY3Rpb24gc2V0T3JV
-cGRhdGVJbnRlcmNlcHRvcnNCeVRhZyhhKXt2YXIgcz12LmludGVyY2VwdG9yc0J5VGFnCmlmKCFzKXt2
-LmludGVyY2VwdG9yc0J5VGFnPWEKcmV0dXJufWNvcHlQcm9wZXJ0aWVzKGEscyl9ZnVuY3Rpb24gc2V0
-T3JVcGRhdGVMZWFmVGFncyhhKXt2YXIgcz12LmxlYWZUYWdzCmlmKCFzKXt2LmxlYWZUYWdzPWEKcmV0
-dXJufWNvcHlQcm9wZXJ0aWVzKGEscyl9ZnVuY3Rpb24gdXBkYXRlVHlwZXMoYSl7dmFyIHM9di50eXBl
-cwp2YXIgcj1zLmxlbmd0aApzLnB1c2guYXBwbHkocyxhKQpyZXR1cm4gcn1mdW5jdGlvbiB1cGRhdGVI
-b2xkZXIoYSxiKXtjb3B5UHJvcGVydGllcyhiLGEpCnJldHVybiBhfXZhciBodW5rSGVscGVycz1mdW5j
-dGlvbigpe3ZhciBzPWZ1bmN0aW9uKGEsYixjLGQsZSl7cmV0dXJuIGZ1bmN0aW9uKGYsZyxoLGkpe3Jl
-dHVybiBpbnN0YWxsSW5zdGFuY2VUZWFyT2ZmKGYsZyxhLGIsYyxkLFtoXSxpLGUpfX0scj1mdW5jdGlv
-bihhLGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24oZSxmLGcsaCl7cmV0dXJuIGluc3RhbGxTdGF0aWNUZWFy
-T2ZmKGUsZixhLGIsYyxbZ10saCxkKX19CnJldHVybntpbmhlcml0OmluaGVyaXQsaW5oZXJpdE1hbnk6
-aW5oZXJpdE1hbnksbWl4aW46bWl4aW4saW5zdGFsbFN0YXRpY1RlYXJPZmY6aW5zdGFsbFN0YXRpY1Rl
-YXJPZmYsaW5zdGFsbEluc3RhbmNlVGVhck9mZjppbnN0YWxsSW5zdGFuY2VUZWFyT2ZmLF9pbnN0YW5j
-ZV8wdTpzKDAsMCxudWxsLFsiJDAiXSwwKSxfaW5zdGFuY2VfMXU6cygwLDEsbnVsbCxbIiQxIl0sMCks
-X2luc3RhbmNlXzJ1OnMoMCwyLG51bGwsWyIkMiJdLDApLF9pbnN0YW5jZV8waTpzKDEsMCxudWxsLFsi
-JDAiXSwwKSxfaW5zdGFuY2VfMWk6cygxLDEsbnVsbCxbIiQxIl0sMCksX2luc3RhbmNlXzJpOnMoMSwy
-LG51bGwsWyIkMiJdLDApLF9zdGF0aWNfMDpyKDAsbnVsbCxbIiQwIl0sMCksX3N0YXRpY18xOnIoMSxu
-dWxsLFsiJDEiXSwwKSxfc3RhdGljXzI6cigyLG51bGwsWyIkMiJdLDApLG1ha2VDb25zdExpc3Q6bWFr
-ZUNvbnN0TGlzdCxsYXp5OmxhenksbGF6eU9sZDpsYXp5T2xkLHVwZGF0ZUhvbGRlcjp1cGRhdGVIb2xk
-ZXIsY29udmVydFRvRmFzdE9iamVjdDpjb252ZXJ0VG9GYXN0T2JqZWN0LHNldEZ1bmN0aW9uTmFtZXNJ
-Zk5lY2Vzc2FyeTpzZXRGdW5jdGlvbk5hbWVzSWZOZWNlc3NhcnksdXBkYXRlVHlwZXM6dXBkYXRlVHlw
-ZXMsc2V0T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZzpzZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFn
-LHNldE9yVXBkYXRlTGVhZlRhZ3M6c2V0T3JVcGRhdGVMZWFmVGFnc319KCkKZnVuY3Rpb24gaW5pdGlh
-bGl6ZURlZmVycmVkSHVuayhhKXt4PXYudHlwZXMubGVuZ3RoCmEoaHVua0hlbHBlcnMsdix3LCQpfWZ1
-bmN0aW9uIGdldEdsb2JhbEZyb21OYW1lKGEpe2Zvcih2YXIgcz0wO3M8dy5sZW5ndGg7cysrKXtpZih3
-W3NdPT1DKWNvbnRpbnVlCmlmKHdbc11bYV0pcmV0dXJuIHdbc11bYV19fXZhciBDPXt9LEg9e0ZLOmZ1
-bmN0aW9uIEZLKCl7fSwKeVI6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILm5kKGEpfSwKb286ZnVuY3Rp
-b24oYSl7dmFyIHMscj1hXjQ4CmlmKHI8PTkpcmV0dXJuIHIKcz1hfDMyCmlmKDk3PD1zJiZzPD0xMDIp
-cmV0dXJuIHMtODcKcmV0dXJuLTF9LApxQzpmdW5jdGlvbihhLGIsYyxkKXtQLmsxKGIsInN0YXJ0IikK
-aWYoYyE9bnVsbCl7UC5rMShjLCJlbmQiKQppZihiPmMpSC52aChQLlRFKGIsMCxjLCJzdGFydCIsbnVs
-bCkpfXJldHVybiBuZXcgSC5uSChhLGIsYyxkLkMoIm5IPDA+IikpfSwKSzE6ZnVuY3Rpb24oYSxiLGMs
-ZCl7aWYodC5ndy5iKGEpKXJldHVybiBuZXcgSC54eShhLGIsYy5DKCJAPDA+IikuS3EoZCkuQygieHk8
-MSwyPiIpKQpyZXR1cm4gbmV3IEguaTEoYSxiLGMuQygiQDwwPiIpLktxKGQpLkMoImkxPDEsMj4iKSl9
-LApXcDpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigiTm8gZWxlbWVudCIpfSwKQW06ZnVuY3Rpb24o
-KXtyZXR1cm4gbmV3IFAubGooIlRvbyBtYW55IGVsZW1lbnRzIil9LAphcjpmdW5jdGlvbigpe3JldHVy
-biBuZXcgUC5saigiVG9vIGZldyBlbGVtZW50cyIpfSwKbmQ6ZnVuY3Rpb24gbmQoYSl7dGhpcy5hPWF9
-LApxajpmdW5jdGlvbiBxaihhKXt0aGlzLmE9YX0sCmJROmZ1bmN0aW9uIGJRKCl7fSwKYUw6ZnVuY3Rp
-b24gYUwoKXt9LApuSDpmdW5jdGlvbiBuSChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
-Yz1jCl8uJHRpPWR9LAphNzpmdW5jdGlvbiBhNyhhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9MApfLmQ9bnVsbApfLiR0aT1jfSwKaTE6ZnVuY3Rpb24gaTEoYSxiLGMpe3RoaXMuYT1hCnRoaXMu
-Yj1iCnRoaXMuJHRpPWN9LAp4eTpmdW5jdGlvbiB4eShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
-cy4kdGk9Y30sCk1IOmZ1bmN0aW9uIE1IKGEsYixjKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8u
-Yz1iCl8uJHRpPWN9LApsSjpmdW5jdGlvbiBsSihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4k
-dGk9Y30sClU1OmZ1bmN0aW9uIFU1KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwK
-U086ZnVuY3Rpb24gU08oYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LAp1NjpmdW5j
-dGlvbiB1NihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApKQjpmdW5jdGlvbiBKQihhLGIpe3RoaXMu
-YT1hCnRoaXMuJHRpPWJ9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9uIFJlKCl7fSwKdzI6
-ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sCmRjOmZ1bmN0aW9uKCl7
-dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIE1hcCIpKX0sCk5ROmZ1bmN0
-aW9uKGEpe3ZhciBzLHI9SC5KZyhhKQppZihyIT1udWxsKXJldHVybiByCnM9Im1pbmlmaWVkOiIrYQpy
-ZXR1cm4gc30sCndWOmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYoYiE9bnVsbCl7cz1iLngKaWYocyE9bnVs
-bClyZXR1cm4gc31yZXR1cm4gdC5hVS5iKGEpfSwKRWo6ZnVuY3Rpb24oYSl7dmFyIHMKaWYodHlwZW9m
-IGE9PSJzdHJpbmciKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoYSE9PTApcmV0dXJu
-IiIrYX1lbHNlIGlmKCEwPT09YSlyZXR1cm4idHJ1ZSIKZWxzZSBpZighMT09PWEpcmV0dXJuImZhbHNl
-IgplbHNlIGlmKGE9PW51bGwpcmV0dXJuIm51bGwiCnM9Si5qKGEpCmlmKHR5cGVvZiBzIT0ic3RyaW5n
-Iil0aHJvdyBILmIoSC50TChhKSkKcmV0dXJuIHN9LAplUTpmdW5jdGlvbihhKXt2YXIgcz1hLiRpZGVu
-dGl0eUhhc2gKaWYocz09bnVsbCl7cz1NYXRoLnJhbmRvbSgpKjB4M2ZmZmZmZmZ8MAphLiRpZGVudGl0
-eUhhc2g9c31yZXR1cm4gc30sCkhwOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG09bnVsbApp
-Zih0eXBlb2YgYSE9InN0cmluZyIpSC52aChILnRMKGEpKQpzPS9eXHMqWystXT8oKDB4W2EtZjAtOV0r
-KXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZihzPT1udWxsKXJldHVybiBtCmlmKDM+
-PXMubGVuZ3RoKXJldHVybiBILk9IKHMsMykKcj1zWzNdCmlmKGI9PW51bGwpe2lmKHIhPW51bGwpcmV0
-dXJuIHBhcnNlSW50KGEsMTApCmlmKHNbMl0hPW51bGwpcmV0dXJuIHBhcnNlSW50KGEsMTYpCnJldHVy
-biBtfWlmKGI8Mnx8Yj4zNil0aHJvdyBILmIoUC5URShiLDIsMzYsInJhZGl4IixtKSkKaWYoYj09PTEw
-JiZyIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihiPDEwfHxyPT1udWxsKXtxPWI8PTEwPzQ3
-K2I6ODYrYgpwPXNbMV0KZm9yKG89cC5sZW5ndGgsbj0wO248bzsrK24paWYoKEMueEIuVyhwLG4pfDMy
-KT5xKXJldHVybiBtfXJldHVybiBwYXJzZUludChhLGIpfSwKTTpmdW5jdGlvbihhKXtyZXR1cm4gSC5I
-NShhKX0sCkg1OmZ1bmN0aW9uKGEpe3ZhciBzLHIscQppZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4g
-SC5kbShILnooYSksbnVsbCkKaWYoSi5pYShhKT09PUMuT2t8fHQuYWsuYihhKSl7cz1DLk80KGEpCmlm
-KEguQmUocykpcmV0dXJuIHMKcj1hLmNvbnN0cnVjdG9yCmlmKHR5cGVvZiByPT0iZnVuY3Rpb24iKXtx
-PXIubmFtZQppZih0eXBlb2YgcT09InN0cmluZyImJkguQmUocSkpcmV0dXJuIHF9fXJldHVybiBILmRt
-KEgueihhKSxudWxsKX0sCkJlOmZ1bmN0aW9uKGEpe3ZhciBzPWEhPT0iT2JqZWN0IiYmYSE9PSIiCnJl
-dHVybiBzfSwKTTA6ZnVuY3Rpb24oKXtpZighIXNlbGYubG9jYXRpb24pcmV0dXJuIHNlbGYubG9jYXRp
-b24uaHJlZgpyZXR1cm4gbnVsbH0sClZLOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG89YS5sZW5ndGgK
-aWYobzw9NTAwKXJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHM9IiIs
-cj0wO3I8bztyPXEpe3E9cis1MDAKcD1xPG8/cTpvCnMrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHko
-bnVsbCxhLnNsaWNlKHIscCkpfXJldHVybiBzfSwKQ3E6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9SC5W
-TShbXSx0LmEpCmZvcihzPWEubGVuZ3RoLHI9MDtyPGEubGVuZ3RoO2EubGVuZ3RoPT09c3x8KDAsSC5s
-aykoYSksKytyKXtxPWFbcl0KaWYoIUgub2socSkpdGhyb3cgSC5iKEgudEwocSkpCmlmKHE8PTY1NTM1
-KUMuTm0uaShwLHEpCmVsc2UgaWYocTw9MTExNDExMSl7Qy5ObS5pKHAsNTUyOTYrKEMuam4ud0cocS02
-NTUzNiwxMCkmMTAyMykpCkMuTm0uaShwLDU2MzIwKyhxJjEwMjMpKX1lbHNlIHRocm93IEguYihILnRM
-KHEpKX1yZXR1cm4gSC5WSyhwKX0sCmVUOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQpmb3Iocz1hLmxlbmd0
-aCxyPTA7cjxzOysrcil7cT1hW3JdCmlmKCFILm9rKHEpKXRocm93IEguYihILnRMKHEpKQppZihxPDAp
-dGhyb3cgSC5iKEgudEwocSkpCmlmKHE+NjU1MzUpcmV0dXJuIEguQ3EoYSl9cmV0dXJuIEguVksoYSl9
-LApmdzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAKaWYoYzw9NTAwJiZiPT09MCYmYz09PWEubGVu
-Z3RoKXJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYSkKZm9yKHM9YixyPSIiO3M8
-YztzPXEpe3E9cys1MDAKcD1xPGM/cTpjCnIrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxh
-LnN1YmFycmF5KHMscCkpfXJldHVybiByfSwKTHc6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoMDw9YSl7aWYo
-YTw9NjU1MzUpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoYSkKaWYoYTw9MTExNDExMSl7cz1hLTY1
-NTM2CnJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCg1NTI5NnxDLmpuLndHKHMsMTApKT4+PjAsNTYz
-MjB8cyYxMDIzKX19dGhyb3cgSC5iKFAuVEUoYSwwLDExMTQxMTEsbnVsbCxudWxsKSl9LApvMjpmdW5j
-dGlvbihhKXtpZihhLmRhdGU9PT12b2lkIDApYS5kYXRlPW5ldyBEYXRlKGEuYSkKcmV0dXJuIGEuZGF0
-ZX0sCnRKOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0RnVsbFllYXIoKSswCnJldHVybiBzfSwK
-TlM6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXRNb250aCgpKzEKcmV0dXJuIHN9LApqQTpmdW5j
-dGlvbihhKXt2YXIgcz1ILm8yKGEpLmdldERhdGUoKSswCnJldHVybiBzfSwKSVg6ZnVuY3Rpb24oYSl7
-dmFyIHM9SC5vMihhKS5nZXRIb3VycygpKzAKcmV0dXJuIHN9LApjaDpmdW5jdGlvbihhKXt2YXIgcz1I
-Lm8yKGEpLmdldE1pbnV0ZXMoKSswCnJldHVybiBzfSwKSmQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihh
-KS5nZXRTZWNvbmRzKCkrMApyZXR1cm4gc30sCm8xOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0
-TWlsbGlzZWNvbmRzKCkrMApyZXR1cm4gc30sCnpvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9e30K
-cS5hPTAKcz1bXQpyPVtdCnEuYT1iLmxlbmd0aApDLk5tLkZWKHMsYikKcS5iPSIiCmlmKGMhPW51bGwm
-JmMuYSE9PTApYy5LKDAsbmV3IEguQ2oocSxyLHMpKQoiIitxLmEKcmV0dXJuIEouSnkoYSxuZXcgSC5M
-SShDLlRlLDAscyxyLDApKX0sCkVrOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscAppZihiIGluc3Rh
-bmNlb2YgQXJyYXkpcz1jPT1udWxsfHxjLmE9PT0wCmVsc2Ugcz0hMQppZihzKXtyPWIKcT1yLmxlbmd0
-aAppZihxPT09MCl7aWYoISFhLiQwKXJldHVybiBhLiQwKCl9ZWxzZSBpZihxPT09MSl7aWYoISFhLiQx
-KXJldHVybiBhLiQxKHJbMF0pfWVsc2UgaWYocT09PTIpe2lmKCEhYS4kMilyZXR1cm4gYS4kMihyWzBd
-LHJbMV0pfWVsc2UgaWYocT09PTMpe2lmKCEhYS4kMylyZXR1cm4gYS4kMyhyWzBdLHJbMV0sclsyXSl9
-ZWxzZSBpZihxPT09NCl7aWYoISFhLiQ0KXJldHVybiBhLiQ0KHJbMF0sclsxXSxyWzJdLHJbM10pfWVs
-c2UgaWYocT09PTUpaWYoISFhLiQ1KXJldHVybiBhLiQ1KHJbMF0sclsxXSxyWzJdLHJbM10scls0XSkK
-cD1hWyIiKyIkIitxXQppZihwIT1udWxsKXJldHVybiBwLmFwcGx5KGEscil9cmV0dXJuIEguZTEoYSxi
-LGMpfSwKZTE6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGk9YiBpbnN0YW5j
-ZW9mIEFycmF5P2I6UC5DSChiLCEwLHQueiksaD1pLmxlbmd0aCxnPWEuJFIKaWYoaDxnKXJldHVybiBI
-LnpvKGEsaSxjKQpzPWEuJEQKcj1zPT1udWxsCnE9IXI/cygpOm51bGwKcD1KLmlhKGEpCm89cC4kQwpp
-Zih0eXBlb2Ygbz09InN0cmluZyIpbz1wW29dCmlmKHIpe2lmKGMhPW51bGwmJmMuYSE9PTApcmV0dXJu
-IEguem8oYSxpLGMpCmlmKGg9PT1nKXJldHVybiBvLmFwcGx5KGEsaSkKcmV0dXJuIEguem8oYSxpLGMp
-fWlmKHEgaW5zdGFuY2VvZiBBcnJheSl7aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC56byhhLGks
-YykKaWYoaD5nK3EubGVuZ3RoKXJldHVybiBILnpvKGEsaSxudWxsKQpDLk5tLkZWKGkscS5zbGljZSho
-LWcpKQpyZXR1cm4gby5hcHBseShhLGkpfWVsc2V7aWYoaD5nKXJldHVybiBILnpvKGEsaSxjKQpuPU9i
-amVjdC5rZXlzKHEpCmlmKGM9PW51bGwpZm9yKHI9bi5sZW5ndGgsbT0wO208bi5sZW5ndGg7bi5sZW5n
-dGg9PT1yfHwoMCxILmxrKShuKSwrK20pe2w9cVtILmgoblttXSldCmlmKEMuTnY9PT1sKXJldHVybiBI
-LnpvKGEsaSxjKQpDLk5tLmkoaSxsKX1lbHNle2ZvcihyPW4ubGVuZ3RoLGs9MCxtPTA7bTxuLmxlbmd0
-aDtuLmxlbmd0aD09PXJ8fCgwLEgubGspKG4pLCsrbSl7aj1ILmgoblttXSkKaWYoYy54NChqKSl7Kytr
-CkMuTm0uaShpLGMucSgwLGopKX1lbHNle2w9cVtqXQppZihDLk52PT09bClyZXR1cm4gSC56byhhLGks
-YykKQy5ObS5pKGksbCl9fWlmKGshPT1jLmEpcmV0dXJuIEguem8oYSxpLGMpfXJldHVybiBvLmFwcGx5
-KGEsaSl9fSwKcFk6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKEgudEwoYSkpfSwKT0g6ZnVuY3Rpb24oYSxi
-KXtpZihhPT1udWxsKUouSG0oYSkKdGhyb3cgSC5iKEguSFkoYSxiKSl9LApIWTpmdW5jdGlvbihhLGIp
-e3ZhciBzLHIscT0iaW5kZXgiCmlmKCFILm9rKGIpKXJldHVybiBuZXcgUC51KCEwLGIscSxudWxsKQpz
-PUgudVAoSi5IbShhKSkKaWYoIShiPDApKXtpZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBILnBZ
-KHMpCnI9Yj49c31lbHNlIHI9ITAKaWYocilyZXR1cm4gUC5DZihiLGEscSxudWxsLHMpCnJldHVybiBQ
-Lk83KGIscSl9LAphdTpmdW5jdGlvbihhLGIsYyl7aWYoYT5jKXJldHVybiBQLlRFKGEsMCxjLCJzdGFy
-dCIsbnVsbCkKaWYoYiE9bnVsbClpZihiPGF8fGI+YylyZXR1cm4gUC5URShiLGEsYywiZW5kIixudWxs
-KQpyZXR1cm4gbmV3IFAudSghMCxiLCJlbmQiLG51bGwpfSwKdEw6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
-dyBQLnUoITAsYSxudWxsLG51bGwpfSwKYjpmdW5jdGlvbihhKXt2YXIgcyxyCmlmKGE9PW51bGwpYT1u
-ZXcgUC5uKCkKcz1uZXcgRXJyb3IoKQpzLmRhcnRFeGNlcHRpb249YQpyPUgueAppZigiZGVmaW5lUHJv
-cGVydHkiIGluIE9iamVjdCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KHMsIm1lc3NhZ2UiLHtnZXQ6cn0p
-CnMubmFtZT0iIn1lbHNlIHMudG9TdHJpbmc9cgpyZXR1cm4gc30sCng6ZnVuY3Rpb24oKXtyZXR1cm4g
-Si5qKHRoaXMuZGFydEV4Y2VwdGlvbil9LAp2aDpmdW5jdGlvbihhKXt0aHJvdyBILmIoYSl9LApsazpm
-dW5jdGlvbihhKXt0aHJvdyBILmIoUC5hNChhKSl9LApjTTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxv
-LG4KYT1ILmVBKGEucmVwbGFjZShTdHJpbmcoe30pLCckcmVjZWl2ZXIkJykpCnM9YS5tYXRjaCgvXFxc
-JFthLXpBLVpdK1xcXCQvZykKaWYocz09bnVsbClzPUguVk0oW10sdC5zKQpyPXMuaW5kZXhPZigiXFwk
-YXJndW1lbnRzXFwkIikKcT1zLmluZGV4T2YoIlxcJGFyZ3VtZW50c0V4cHJcXCQiKQpwPXMuaW5kZXhP
-ZigiXFwkZXhwclxcJCIpCm89cy5pbmRleE9mKCJcXCRtZXRob2RcXCQiKQpuPXMuaW5kZXhPZigiXFwk
-cmVjZWl2ZXJcXCQiKQpyZXR1cm4gbmV3IEguZjkoYS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRh
-cmd1bWVudHNcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdc
-XFxcXFwkYXJndW1lbnRzRXhwclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5l
-dyBSZWdFeHAoJ1xcXFxcXCRleHByXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154XSkqKScpLnJlcGxhY2Uo
-bmV3IFJlZ0V4cCgnXFxcXFxcJG1ldGhvZFxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBs
-YWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRyZWNlaXZlclxcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKikn
-KSxyLHEscCxvLG4pfSwKUzc6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dmFyICRh
-cmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXskZXhwciQuJG1ldGhvZCQoJGFyZ3VtZW50c0V4
-cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oYSl9LApNajpmdW5jdGlvbihhKXtyZXR1cm4g
-ZnVuY3Rpb24oJGV4cHIkKXt0cnl7JGV4cHIkLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3Nh
-Z2V9fShhKX0sCklqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILlcwKGEsYj09bnVsbD9udWxsOmIu
-bWV0aG9kKX0sClQzOmZ1bmN0aW9uKGEsYil7dmFyIHM9Yj09bnVsbCxyPXM/bnVsbDpiLm1ldGhvZApy
-ZXR1cm4gbmV3IEguYXooYSxyLHM/bnVsbDpiLnJlY2VpdmVyKX0sClJ1OmZ1bmN0aW9uKGEpe2lmKGE9
-PW51bGwpcmV0dXJuIG5ldyBILnRlKGEpCmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBILnRXKGEs
-YS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlmKCJkYXJ0RXhjZXB0aW9uIiBpbiBh
-KXJldHVybiBILnRXKGEsYS5kYXJ0RXhjZXB0aW9uKQpyZXR1cm4gSC50bChhKX0sCnRXOmZ1bmN0aW9u
-KGEsYil7aWYodC5tLmIoYikpaWYoYi4kdGhyb3duSnNFcnJvcj09bnVsbCliLiR0aHJvd25Kc0Vycm9y
-PWEKcmV0dXJuIGJ9LAp0bDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxm
-LGU9bnVsbAppZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1cm4gYQpzPWEubWVzc2FnZQppZigibnVtYmVy
-IiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIiKXtyPWEubnVtYmVyCnE9ciY2NTUzNQppZigo
-Qy5qbi53RyhyLDE2KSY4MTkxKT09PTEwKXN3aXRjaChxKXtjYXNlIDQzODpyZXR1cm4gSC50VyhhLEgu
-VDMoSC5FaihzKSsiIChFcnJvciAiK3ErIikiLGUpKQpjYXNlIDQ0NTpjYXNlIDUwMDc6cmV0dXJuIEgu
-dFcoYSxILklqKEguRWoocykrIiAoRXJyb3IgIitxKyIpIixlKSl9fWlmKGEgaW5zdGFuY2VvZiBUeXBl
-RXJyb3Ipe3A9JC5TbigpCm89JC5scSgpCm49JC5OOSgpCm09JC5pSSgpCmw9JC5VTigpCms9JC5aaCgp
-Cmo9JC5yTigpCiQuYzMoKQppPSQuSEsoKQpoPSQucjEoKQpnPXAucVMocykKaWYoZyE9bnVsbClyZXR1
-cm4gSC50VyhhLEguVDMoSC5oKHMpLGcpKQplbHNle2c9by5xUyhzKQppZihnIT1udWxsKXtnLm1ldGhv
-ZD0iY2FsbCIKcmV0dXJuIEgudFcoYSxILlQzKEguaChzKSxnKSl9ZWxzZXtnPW4ucVMocykKaWYoZz09
-bnVsbCl7Zz1tLnFTKHMpCmlmKGc9PW51bGwpe2c9bC5xUyhzKQppZihnPT1udWxsKXtnPWsucVMocykK
-aWYoZz09bnVsbCl7Zz1qLnFTKHMpCmlmKGc9PW51bGwpe2c9bS5xUyhzKQppZihnPT1udWxsKXtnPWku
-cVMocykKaWYoZz09bnVsbCl7Zz1oLnFTKHMpCmY9ZyE9bnVsbH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVs
-c2UgZj0hMH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1lbHNlIGY9ITAKaWYoZilyZXR1cm4g
-SC50VyhhLEguSWooSC5oKHMpLGcpKX19cmV0dXJuIEgudFcoYSxuZXcgSC52Vih0eXBlb2Ygcz09InN0
-cmluZyI/czoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5nZUVycm9yKXtpZih0eXBlb2Ygcz09InN0cmlu
-ZyImJnMuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEpcmV0dXJuIG5ldyBQLktZKCkKcz1mdW5jdGlv
-bihiKXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChkKXt9cmV0dXJuIG51bGx9KGEpCnJldHVybiBI
-LnRXKGEsbmV3IFAudSghMSxlLGUsdHlwZW9mIHM9PSJzdHJpbmciP3MucmVwbGFjZSgvXlJhbmdlRXJy
-b3I6XHMqLywiIik6cykpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9yPT0iZnVuY3Rpb24iJiZhIGluc3Rh
-bmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2Ygcz09InN0cmluZyImJnM9PT0idG9vIG11Y2ggcmVj
-dXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRzOmZ1bmN0aW9uKGEpe3ZhciBzCmlm
-KGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVsbClyZXR1cm4gbmV3IEguWE8oYSkK
-cz1hLiRjYWNoZWRUcmFjZQppZihzIT1udWxsKXJldHVybiBzCnJldHVybiBhLiRjYWNoZWRUcmFjZT1u
-ZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHA9YS5sZW5ndGgKZm9yKHM9MDtz
-PHA7cz1xKXtyPXMrMQpxPXIrMQpiLlkoMCxhW3NdLGFbcl0pfXJldHVybiBifSwKZnQ6ZnVuY3Rpb24o
-YSxiLGMsZCxlLGYpe3QuWS5hKGEpCnN3aXRjaChILnVQKGIpKXtjYXNlIDA6cmV0dXJuIGEuJDAoKQpj
-YXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQyKGMsZCkKY2FzZSAzOnJldHVybiBh
-LiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9dGhyb3cgSC5iKG5ldyBQLkNEKCJV
-bnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFwcGVkIGNsb3N1cmUiKSl9LAp0Ujpm
-dW5jdGlvbihhLGIpe3ZhciBzCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKcz1hLiRpZGVudGl0eQppZigh
-IXMpcmV0dXJuIHMKcz1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1bmN0aW9uKGYsZyxoLGkpe3JldHVy
-biBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0eT1zCnJldHVybiBzfSwKaUE6ZnVu
-Y3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHMscixxLHAsbyxuLG0sbD1iWzBdLGs9bC4kY2FsbE5hbWUs
-aj1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpOk9iamVjdC5j
-cmVhdGUobmV3IEguclQobnVsbCxudWxsLG51bGwsIiIpLmNvbnN0cnVjdG9yLnByb3RvdHlwZSkKai4k
-aW5pdGlhbGl6ZT1qLmNvbnN0cnVjdG9yCmlmKGUpcz1mdW5jdGlvbiBzdGF0aWNfdGVhcl9vZmYoKXt0
-aGlzLiRpbml0aWFsaXplKCl9CmVsc2V7cj0kLnlqCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJu
-IHIuaCgpCiQueWo9cisxCnI9bmV3IEZ1bmN0aW9uKCJhLGIsYyxkIityLCJ0aGlzLiRpbml0aWFsaXpl
-KGEsYixjLGQiK3IrIikiKQpzPXJ9ai5jb25zdHJ1Y3Rvcj1zCnMucHJvdG90eXBlPWoKaWYoIWUpe3E9
-SC5ieChhLGwsZikKcS4kcmVmbGVjdGlvbkluZm89ZH1lbHNle2ouJHN0YXRpY19uYW1lPWcKcT1sfWou
-JFM9SC5pbShkLGUsZikKaltrXT1xCmZvcihwPXEsbz0xO288Yi5sZW5ndGg7KytvKXtuPWJbb10KbT1u
-LiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEsbixmKQpqW21dPW59aWYobz09PWMpe24u
-JHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1qLiRDPXAKai4kUj1sLiRSCmouJEQ9bC4kRApyZXR1cm4gc30s
-CmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGZ1bmN0
-aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQoZSl9fShILkJwLGEpCmlmKHR5cGVvZiBh
-PT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBjb21wdXRlIHNpZ25hdHVyZSBmb3Igc3Rh
-dGljIHRlYXJvZmYuIikKcz1jP0guUFc6SC5UbgpyZXR1cm4gZnVuY3Rpb24oZCxlKXtyZXR1cm4gZnVu
-Y3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSxzKX10aHJvdyBILmIoIkVycm9yIGluIGZ1bmN0aW9u
-VHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcz1ILkRWCnN3aXRjaChi
-Py0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4g
-Zih0aGlzKVtlXSgpfX0oYyxzKQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0
-aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyxzKQpjYXNlIDI6cmV0dXJuIGZ1bmN0aW9uKGUs
-Zil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhpcylbZV0oZyxoKX19KGMscykKY2FzZSAz
-OnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihnLGgsaSl7cmV0dXJuIGYodGhpcylb
-ZV0oZyxoLGkpfX0oYyxzKQpjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9u
-KGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGopfX0oYyxzKQpjYXNlIDU6cmV0dXJuIGZ1
-bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGosayl7cmV0dXJuIGYodGhpcylbZV0oZyxo
-LGksaixrKX19KGMscykKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24o
-KXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9fShkLHMpfX0sCmJ4OmZ1bmN0aW9uKGEs
-YixjKXt2YXIgcyxyLHEscCxvLG4sbQppZihjKXJldHVybiBILkhmKGEsYikKcz1iLiRzdHViTmFtZQpy
-PWIubGVuZ3RoCnE9YVtzXQpwPWI9PW51bGw/cT09bnVsbDpiPT09cQpvPSFwfHxyPj0yNwppZihvKXJl
-dHVybiBILnZxKHIsIXAscyxiKQppZihyPT09MCl7cD0kLnlqCmlmKHR5cGVvZiBwIT09Im51bWJlciIp
-cmV0dXJuIHAuaCgpCiQueWo9cCsxCm49InNlbGYiK3AKcmV0dXJuIG5ldyBGdW5jdGlvbigicmV0dXJu
-IGZ1bmN0aW9uKCl7dmFyICIrbisiID0gdGhpcy4iK0guRWooSC5vTigpKSsiO3JldHVybiAiK24rIi4i
-K0guRWoocykrIigpO30iKSgpfW09ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgiIiku
-c3BsaWNlKDAscikuam9pbigiLCIpCnA9JC55agppZih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVybiBw
-LmgoKQokLnlqPXArMQptKz1wCnJldHVybiBuZXcgRnVuY3Rpb24oInJldHVybiBmdW5jdGlvbigiK20r
-Iil7cmV0dXJuIHRoaXMuIitILkVqKEgub04oKSkrIi4iK0guRWoocykrIigiK20rIik7fSIpKCl9LApa
-NDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcz1ILkRWLHI9SC55Uwpzd2l0Y2goYj8tMTphKXtjYXNlIDA6
-dGhyb3cgSC5iKG5ldyBILkVxKCJJbnRlcmNlcHRlZCBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cy4i
-KSkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGYo
-dGhpcylbZV0oZyh0aGlzKSl9fShjLHMscikKY2FzZSAyOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0
-dXJuIGZ1bmN0aW9uKGgpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCl9fShjLHMscikKY2FzZSAz
-OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSl7cmV0dXJuIGYodGhpcylb
-ZV0oZyh0aGlzKSxoLGkpfX0oYyxzLHIpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVy
-biBmdW5jdGlvbihoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksail9fShjLHMscikK
-Y2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGspe3JldHVy
-biBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayl9fShjLHMscikKY2FzZSA2OnJldHVybiBmdW5jdGlv
-bihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGssbCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlz
-KSxoLGksaixrLGwpfX0oYyxzLHIpCmRlZmF1bHQ6cmV0dXJuIGZ1bmN0aW9uKGUsZixnLGgpe3JldHVy
-biBmdW5jdGlvbigpe2g9W2codGhpcyldCkFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGgsYXJndW1l
-bnRzKQpyZXR1cm4gZS5hcHBseShmKHRoaXMpLGgpfX0oZCxzLHIpfX0sCkhmOmZ1bmN0aW9uKGEsYil7
-dmFyIHMscixxLHAsbyxuLG09SC5vTigpLGw9JC5QNAppZihsPT1udWxsKWw9JC5QND1ILkUyKCJyZWNl
-aXZlciIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09
-PXEKbz0hcHx8cj49MjgKaWYobylyZXR1cm4gSC5aNChyLCFwLHMsYikKaWYocj09PTEpe3A9InJldHVy
-biBmdW5jdGlvbigpe3JldHVybiB0aGlzLiIrSC5FaihtKSsiLiIrSC5FaihzKSsiKHRoaXMuIitsKyIp
-OyIKbz0kLnlqCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8uaCgpCiQueWo9bysxCnJldHVy
-biBuZXcgRnVuY3Rpb24ocCtvKyJ9IikoKX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3Bs
-aXQoIiIpLnNwbGljZSgwLHItMSkuam9pbigiLCIpCnA9InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0
-dXJuIHRoaXMuIitILkVqKG0pKyIuIitILkVqKHMpKyIodGhpcy4iK2wrIiwgIituKyIpOyIKbz0kLnlq
-CmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8uaCgpCiQueWo9bysxCnJldHVybiBuZXcgRnVu
-Y3Rpb24ocCtvKyJ9IikoKX0sCktxOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3JldHVybiBILmlBKGEs
-YixjLGQsISFlLCEhZixnKX0sClRuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVy
-c2UsSC56KGEuYSksYil9LApQVzpmdW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNl
-LEgueihhLmMpLGIpfSwKRFY6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBhLmN9LApvTjpmdW5jdGlvbigpe3ZhciBzPSQubUoKcmV0dXJuIHM9PW51bGw/JC5tSj1ILkUy
-KCJzZWxmIik6c30sCkUyOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPW5ldyBILnJUKCJzZWxmIiwidGFy
-Z2V0IiwicmVjZWl2ZXIiLCJuYW1lIiksbz1KLkVwKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHAp
-LHQuUykKZm9yKHM9by5sZW5ndGgscj0wO3I8czsrK3Ipe3E9b1tyXQppZihwW3FdPT09YSlyZXR1cm4g
-cX10aHJvdyBILmIoUC54WSgiRmllbGQgbmFtZSAiK2ErIiBub3QgZm91bmQuIikpfSwKb1Q6ZnVuY3Rp
-b24oYSl7aWYoYT09bnVsbClILmZPKCJib29sZWFuIGV4cHJlc3Npb24gbXVzdCBub3QgYmUgbnVsbCIp
-CnJldHVybiBhfSwKZk86ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5ldyBILmtZKGEpKX0sCmFnOmZ1bmN0
-aW9uKGEpe3Rocm93IEguYihuZXcgUC5jKGEpKX0sCllnOmZ1bmN0aW9uKGEpe3JldHVybiB2LmdldElz
-b2xhdGVUYWcoYSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7
-dmFsdWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0s
-CnczOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbj1ILmgoJC5ORi4kMShhKSksbT0kLm53W25dCmlm
-KG0hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3Zh
-bHVlOm0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0
-dXJuIG0uaX1zPSQudnZbbl0KaWYocyE9bnVsbClyZXR1cm4gcwpyPXYuaW50ZXJjZXB0b3JzQnlUYWdb
-bl0KaWYocj09bnVsbCl7cT1ILmsoJC5UWC4kMihhLG4pKQppZihxIT1udWxsKXttPSQubndbcV0KaWYo
-bSE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFs
-dWU6bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1
-cm4gbS5pfXM9JC52dltxXQppZihzIT1udWxsKXJldHVybiBzCnI9di5pbnRlcmNlcHRvcnNCeVRhZ1tx
-XQpuPXF9fWlmKHI9PW51bGwpcmV0dXJuIG51bGwKcz1yLnByb3RvdHlwZQpwPW5bMF0KaWYocD09PSIh
-Iil7bT1ILlZhKHMpCiQubndbbl09bQpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJv
-cGVydHlOYW1lLHt2YWx1ZTptLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFi
-bGU6dHJ1ZX0pCnJldHVybiBtLml9aWYocD09PSJ+Iil7JC52dltuXT1zCnJldHVybiBzfWlmKHA9PT0i
-LSIpe289SC5WYShzKQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEp
-LHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0
-cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX1pZihwPT09IisiKXJldHVybiBILkxjKGEs
-cykKaWYocD09PSIqIil0aHJvdyBILmIoUC5TWShuKSkKaWYodi5sZWFmVGFnc1tuXT09PXRydWUpe289
-SC5WYShzKQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlz
-cGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNv
-bmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX1lbHNlIHJldHVybiBILkxjKGEscyl9LApMYzpmdW5j
-dGlvbihhLGIpe3ZhciBzPU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQpPYmplY3QuZGVmaW5lUHJvcGVy
-dHkocyx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpKLlF1KGIscyxudWxsLG51bGwpLGVudW1l
-cmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBifSwKVmE6
-ZnVuY3Rpb24oYSl7cmV0dXJuIEouUXUoYSwhMSxudWxsLCEhYS4kaVhqKX0sClZGOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgcz1iLnByb3RvdHlwZQppZih2LmxlYWZUYWdzW2FdPT09dHJ1ZSlyZXR1cm4gSC5WYShz
-KQplbHNlIHJldHVybiBKLlF1KHMsYyxudWxsLG51bGwpfSwKWEQ6ZnVuY3Rpb24oKXtpZighMD09PSQu
-QnYpcmV0dXJuCiQuQnY9ITAKSC5aMSgpfSwKWjE6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbSxs
-CiQubnc9T2JqZWN0LmNyZWF0ZShudWxsKQokLnZ2PU9iamVjdC5jcmVhdGUobnVsbCkKSC5rTygpCnM9
-di5pbnRlcmNlcHRvcnNCeVRhZwpyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHMpCmlmKHR5cGVv
-ZiB3aW5kb3chPSJ1bmRlZmluZWQiKXt3aW5kb3cKcT1mdW5jdGlvbigpe30KZm9yKHA9MDtwPHIubGVu
-Z3RoOysrcCl7bz1yW3BdCm49JC54Ny4kMShvKQppZihuIT1udWxsKXttPUguVkYobyxzW29dLG4pCmlm
-KG0hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShuLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3Zh
-bHVlOm0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcS5w
-cm90b3R5cGU9bn19fX1mb3IocD0wO3A8ci5sZW5ndGg7KytwKXtvPXJbcF0KaWYoL15bQS1aYS16X10v
-LnRlc3Qobykpe2w9c1tvXQpzWyIhIitvXT1sCnNbIn4iK29dPWwKc1siLSIrb109bApzWyIrIitvXT1s
-CnNbIioiK29dPWx9fX0sCmtPOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09Qy5ZcSgpCm09SC51
-ZChDLktVLEgudWQoQy5mUSxILnVkKEMuaTcsSC51ZChDLmk3LEgudWQoQy54aSxILnVkKEMuZGssSC51
-ZChDLndiKEMuTzQpLG0pKSkpKSkpCmlmKHR5cGVvZiBkYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5z
-Zm9ybWVyIT0idW5kZWZpbmVkIil7cz1kYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyCmlm
-KHR5cGVvZiBzPT0iZnVuY3Rpb24iKXM9W3NdCmlmKHMuY29uc3RydWN0b3I9PUFycmF5KWZvcihyPTA7
-cjxzLmxlbmd0aDsrK3Ipe3E9c1tyXQppZih0eXBlb2YgcT09ImZ1bmN0aW9uIiltPXEobSl8fG19fXA9
-bS5nZXRUYWcKbz1tLmdldFVua25vd25UYWcKbj1tLnByb3RvdHlwZUZvclRhZwokLk5GPW5ldyBILmRD
-KHApCiQuVFg9bmV3IEgud04obykKJC54Nz1uZXcgSC5WWChuKX0sCnVkOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIGEoYil8fGJ9LAp2NDpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHM9Yj8ibSI6IiIscj1jPyIi
-OiJpIixxPWQ/InUiOiIiLHA9ZT8icyI6IiIsbz1mPyJnIjoiIixuPWZ1bmN0aW9uKGcsaCl7dHJ5e3Jl
-dHVybiBuZXcgUmVnRXhwKGcsaCl9Y2F0Y2gobSl7cmV0dXJuIG19fShhLHMrcitxK3ArbykKaWYobiBp
-bnN0YW5jZW9mIFJlZ0V4cClyZXR1cm4gbgp0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBSZWdFeHAgcGF0
-dGVybiAoIitTdHJpbmcobikrIikiLGEsbnVsbCkpfSwKbTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlm
-KHR5cGVvZiBiPT0ic3RyaW5nIilyZXR1cm4gYS5pbmRleE9mKGIsYyk+PTAKZWxzZSBpZihiIGluc3Rh
-bmNlb2YgSC5WUil7cz1DLnhCLkcoYSxjKQpyZXR1cm4gYi5iLnRlc3Qocyl9ZWxzZXtzPUouRkwoYixD
-LnhCLkcoYSxjKSkKcmV0dXJuIXMuZ2wwKHMpfX0sCkE0OmZ1bmN0aW9uKGEpe2lmKGEuaW5kZXhPZigi
-JCIsMCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQkJCIpCnJldHVybiBhfSwKZUE6ZnVuY3Rp
-b24oYSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChhKSlyZXR1cm4gYS5yZXBsYWNlKC9bW1xd
-e30oKSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwKeXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciBz
-PUgubk0oYSxiLGMpCnJldHVybiBzfSwKbk06ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwCmlmKGI9
-PT0iIil7aWYoYT09PSIiKXJldHVybiBjCnM9YS5sZW5ndGgKZm9yKHI9YyxxPTA7cTxzOysrcSlyPXIr
-YVtxXStjCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfXA9YS5pbmRleE9mKGIsMCkKaWYocDww
-KXJldHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9mKCIkIiwwKT49MClyZXR1cm4gYS5zcGxp
-dChiKS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJlZ0V4cChILmVBKGIpLCdnJyksSC5BNChj
-KSl9LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApXVTpmdW5jdGlvbiBX
-VSgpe30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMK
-Xy4kdGk9ZH0sClhSOmZ1bmN0aW9uIFhSKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCkxJOmZ1bmN0
-aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLmY9ZX0s
-CkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmY5OmZ1bmN0
-aW9uIGY5KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1l
-Cl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmF6OmZ1bmN0aW9u
-IGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnZWOmZ1bmN0aW9uIHZWKGEpe3Ro
-aXMuYT1hfSwKdGU6ZnVuY3Rpb24gdGUoYSl7dGhpcy5hPWF9LApicTpmdW5jdGlvbiBicShhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKWE86ZnVuY3Rpb24gWE8oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LAp2
-OmZ1bmN0aW9uIHYoKXt9LApsYzpmdW5jdGlvbiBsYygpe30sCnp4OmZ1bmN0aW9uIHp4KCl7fSwKclQ6
-ZnVuY3Rpb24gclQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkVx
-OmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1hfSwKa1k6ZnVuY3Rpb24ga1koYSl7dGhpcy5hPWF9LAprcjpm
-dW5jdGlvbiBrcigpe30sCk41OmZ1bmN0aW9uIE41KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1f
-LmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApkYjpmdW5jdGlvbiBkYihhLGIpe3ZhciBfPXRo
-aXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVuY3Rpb24gaTUoYSxiKXt0aGlzLmE9YQp0
-aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5k
-PV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhhKXt0aGlzLmE9YX0sCndOOmZ1bmN0aW9u
-IHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7dGhpcy5hPWF9LApWUjpmdW5jdGlvbiBW
-UihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKRUs6ZnVuY3Rpb24gRUso
-YSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
-PWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9
-bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEKdGhpcy5jPWJ9LAp1bjpmdW5jdGlvbiB1
-bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApTZDpmdW5jdGlvbiBTZChhLGIsYyl7
-dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sClhGOmZ1bmN0aW9uKGEpe3JldHVy
-biBhfSwKb2Q6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Pj4wIT09YXx8YT49Yyl0aHJvdyBILmIoSC5IWShi
-LGEpKX0sCnJNOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZighKGE+Pj4wIT09YSkpcz1iPj4+MCE9PWJ8
-fGE+Ynx8Yj5jCmVsc2Ugcz0hMAppZihzKXRocm93IEguYihILmF1KGEsYixjKSkKcmV0dXJuIGJ9LApF
-VDpmdW5jdGlvbiBFVCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7fSwKRGc6ZnVuY3Rpb24gRGcoKXt9LApQ
-ZzpmdW5jdGlvbiBQZygpe30sCnhqOmZ1bmN0aW9uIHhqKCl7fSwKZEU6ZnVuY3Rpb24gZEUoKXt9LApa
-QTpmdW5jdGlvbiBaQSgpe30sCmRUOmZ1bmN0aW9uIGRUKCl7fSwKUHE6ZnVuY3Rpb24gUHEoKXt9LApl
-RTpmdW5jdGlvbiBlRSgpe30sClY2OmZ1bmN0aW9uIFY2KCl7fSwKUkc6ZnVuY3Rpb24gUkcoKXt9LApW
-UDpmdW5jdGlvbiBWUCgpe30sCldCOmZ1bmN0aW9uIFdCKCl7fSwKWkc6ZnVuY3Rpb24gWkcoKXt9LApj
-ejpmdW5jdGlvbihhLGIpe3ZhciBzPWIuYwpyZXR1cm4gcz09bnVsbD9iLmM9SC5CKGEsYi56LCEwKTpz
-fSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmMKcmV0dXJuIHM9PW51bGw/Yi5jPUguSihhLCJiOCIs
-W2Iuel0pOnN9LApRMTpmdW5jdGlvbihhKXt2YXIgcz1hLnkKaWYocz09PTZ8fHM9PT03fHxzPT09OCly
-ZXR1cm4gSC5RMShhLnopCnJldHVybiBzPT09MTF8fHM9PT0xMn0sCm1EOmZ1bmN0aW9uKGEpe3JldHVy
-biBhLmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJzZSxhLCExKX0sClBM
-OmZ1bmN0aW9uKGEsYixhMCxhMSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYz1i
-LnkKc3dpdGNoKGMpe2Nhc2UgNTpjYXNlIDE6Y2FzZSAyOmNhc2UgMzpjYXNlIDQ6cmV0dXJuIGIKY2Fz
-ZSA2OnM9Yi56CnI9SC5QTChhLHMsYTAsYTEpCmlmKHI9PT1zKXJldHVybiBiCnJldHVybiBILkMoYSxy
-LCEwKQpjYXNlIDc6cz1iLnoKcj1ILlBMKGEscyxhMCxhMSkKaWYocj09PXMpcmV0dXJuIGIKcmV0dXJu
-IEguQihhLHIsITApCmNhc2UgODpzPWIuegpyPUguUEwoYSxzLGEwLGExKQppZihyPT09cylyZXR1cm4g
-YgpyZXR1cm4gSC5mKGEsciwhMCkKY2FzZSA5OnE9Yi5RCnA9SC5iWihhLHEsYTAsYTEpCmlmKHA9PT1x
-KXJldHVybiBiCnJldHVybiBILkooYSxiLnoscCkKY2FzZSAxMDpvPWIuegpuPUguUEwoYSxvLGEwLGEx
-KQptPWIuUQpsPUguYlooYSxtLGEwLGExKQppZihuPT09byYmbD09PW0pcmV0dXJuIGIKcmV0dXJuIEgu
-YShhLG4sbCkKY2FzZSAxMTprPWIuegpqPUguUEwoYSxrLGEwLGExKQppPWIuUQpoPUgucVQoYSxpLGEw
-LGExKQppZihqPT09ayYmaD09PWkpcmV0dXJuIGIKcmV0dXJuIEguZChhLGosaCkKY2FzZSAxMjpnPWIu
-UQphMSs9Zy5sZW5ndGgKZj1ILmJaKGEsZyxhMCxhMSkKbz1iLnoKbj1ILlBMKGEsbyxhMCxhMSkKaWYo
-Zj09PWcmJm49PT1vKXJldHVybiBiCnJldHVybiBILkQoYSxuLGYsITApCmNhc2UgMTM6ZT1iLnoKaWYo
-ZTxhMSlyZXR1cm4gYgpkPWEwW2UtYTFdCmlmKGQ9PW51bGwpcmV0dXJuIGIKcmV0dXJuIGQKZGVmYXVs
-dDp0aHJvdyBILmIoUC5oVigiQXR0ZW1wdGVkIHRvIHN1YnN0aXR1dGUgdW5leHBlY3RlZCBSVEkga2lu
-ZCAiK2MpKX19LApiWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvPWIubGVuZ3RoLG49W10K
-Zm9yKHM9ITEscj0wO3I8bzsrK3Ipe3E9YltyXQpwPUguUEwoYSxxLGMsZCkKaWYocCE9PXEpcz0hMApu
-LnB1c2gocCl9cmV0dXJuIHM/bjpifSwKdk86ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxu
-LG09Yi5sZW5ndGgsbD1bXQpmb3Iocz0hMSxyPTA7cjxtO3IrPTMpe3E9YltyXQpwPWJbcisxXQpvPWJb
-cisyXQpuPUguUEwoYSxvLGMsZCkKaWYobiE9PW8pcz0hMApsLnB1c2gocSkKbC5wdXNoKHApCmwucHVz
-aChuKX1yZXR1cm4gcz9sOmJ9LApxVDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyPWIuYSxxPUguYloo
-YSxyLGMsZCkscD1iLmIsbz1ILmJaKGEscCxjLGQpLG49Yi5jLG09SC52TyhhLG4sYyxkKQppZihxPT09
-ciYmbz09PXAmJm09PT1uKXJldHVybiBiCnM9bmV3IEguRygpCnMuYT1xCnMuYj1vCnMuYz1tCnJldHVy
-biBzfSwKVk06ZnVuY3Rpb24oYSxiKXthW3YuYXJyYXlSdGldPWIKcmV0dXJuIGF9LApKUzpmdW5jdGlv
-bihhKXt2YXIgcz1hLiRTCmlmKHMhPW51bGwpe2lmKHR5cGVvZiBzPT0ibnVtYmVyIilyZXR1cm4gSC5C
-cChzKQpyZXR1cm4gYS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihI
-LlExKGIpKWlmKGEgaW5zdGFuY2VvZiBILnYpe3M9SC5KUyhhKQppZihzIT1udWxsKXJldHVybiBzfXJl
+c1tiXX0KcmV0dXJuIGFbYl19fWZ1bmN0aW9uIGxhenlGaW5hbChhLGIsYyxkKXt2YXIgcz1hCmFbYl09
+cwphW2NdPWZ1bmN0aW9uKCl7aWYoYVtiXT09PXMpe3ZhciByPWQoKQppZihhW2JdIT09cylILkJvKGIp
+CmFbYl09cn1hW2NdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXNbYl19CnJldHVybiBhW2JdfX1mdW5jdGlv
+biBtYWtlQ29uc3RMaXN0KGEpe2EuaW1tdXRhYmxlJGxpc3Q9QXJyYXkKYS5maXhlZCRsZW5ndGg9QXJy
+YXkKcmV0dXJuIGF9ZnVuY3Rpb24gY29udmVydFRvRmFzdE9iamVjdChhKXtmdW5jdGlvbiB0KCl7fXQu
+cHJvdG90eXBlPWEKbmV3IHQoKQpyZXR1cm4gYX1mdW5jdGlvbiBjb252ZXJ0QWxsVG9GYXN0T2JqZWN0
+KGEpe2Zvcih2YXIgcz0wO3M8YS5sZW5ndGg7KytzKWNvbnZlcnRUb0Zhc3RPYmplY3QoYVtzXSl9dmFy
+IHk9MApmdW5jdGlvbiB0ZWFyT2ZmR2V0dGVyKGEsYixjLGQsZSl7cmV0dXJuIGU/bmV3IEZ1bmN0aW9u
+KCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1lIiwiSCIs
+ImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIocmVjZWl2ZXIpIHsiKyJpZiAoYyA9
+PT0gbnVsbCkgYyA9ICIrIkguS3EiKyIoIisidGhpcywgZnVuY3MsIGFwcGx5VHJhbXBvbGluZUluZGV4
+LCByZWZsZWN0aW9uSW5mbywgZmFsc2UsIHRydWUsIG5hbWUpOyIrInJldHVybiBuZXcgYyh0aGlzLCBm
+dW5jc1swXSwgcmVjZWl2ZXIsIG5hbWUpOyIrIn0iKShhLGIsYyxkLEgsbnVsbCk6bmV3IEZ1bmN0aW9u
+KCJmdW5jcyIsImFwcGx5VHJhbXBvbGluZUluZGV4IiwicmVmbGVjdGlvbkluZm8iLCJuYW1lIiwiSCIs
+ImMiLCJyZXR1cm4gZnVuY3Rpb24gdGVhck9mZl8iK2QreSsrKyIoKSB7IisiaWYgKGMgPT09IG51bGwp
+IGMgPSAiKyJILktxIisiKCIrInRoaXMsIGZ1bmNzLCBhcHBseVRyYW1wb2xpbmVJbmRleCwgcmVmbGVj
+dGlvbkluZm8sIGZhbHNlLCBmYWxzZSwgbmFtZSk7IisicmV0dXJuIG5ldyBjKHRoaXMsIGZ1bmNzWzBd
+LCBudWxsLCBuYW1lKTsiKyJ9IikoYSxiLGMsZCxILG51bGwpfWZ1bmN0aW9uIHRlYXJPZmYoYSxiLGMs
+ZCxlLGYpe3ZhciBzPW51bGwKcmV0dXJuIGQ/ZnVuY3Rpb24oKXtpZihzPT09bnVsbClzPUguS3EodGhp
+cyxhLGIsYyx0cnVlLGZhbHNlLGUpLnByb3RvdHlwZQpyZXR1cm4gc306dGVhck9mZkdldHRlcihhLGIs
+YyxlLGYpfXZhciB4PTAKZnVuY3Rpb24gaW5zdGFsbFRlYXJPZmYoYSxiLGMsZCxlLGYsZyxoLGksail7
+dmFyIHM9W10KZm9yKHZhciByPTA7cjxoLmxlbmd0aDtyKyspe3ZhciBxPWhbcl0KaWYodHlwZW9mIHE9
+PSdzdHJpbmcnKXE9YVtxXQpxLiRjYWxsTmFtZT1nW3JdCnMucHVzaChxKX12YXIgcT1zWzBdCnEuJFI9
+ZQpxLiREPWYKdmFyIHA9aQppZih0eXBlb2YgcD09Im51bWJlciIpcCs9eAp2YXIgbz1oWzBdCnEuJHN0
+dWJOYW1lPW8KdmFyIG49dGVhck9mZihzLGp8fDAscCxjLG8sZCkKYVtiXT1uCmlmKGMpcS4kdGVhck9m
+Zj1ufWZ1bmN0aW9uIGluc3RhbGxTdGF0aWNUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCl7cmV0dXJuIGlu
+c3RhbGxUZWFyT2ZmKGEsYix0cnVlLGZhbHNlLGMsZCxlLGYsZyxoKX1mdW5jdGlvbiBpbnN0YWxsSW5z
+dGFuY2VUZWFyT2ZmKGEsYixjLGQsZSxmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbFRlYXJPZmYoYSxiLGZh
+bHNlLGMsZCxlLGYsZyxoLGkpfWZ1bmN0aW9uIHNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoYSl7
+dmFyIHM9di5pbnRlcmNlcHRvcnNCeVRhZwppZighcyl7di5pbnRlcmNlcHRvcnNCeVRhZz1hCnJldHVy
+bn1jb3B5UHJvcGVydGllcyhhLHMpfWZ1bmN0aW9uIHNldE9yVXBkYXRlTGVhZlRhZ3MoYSl7dmFyIHM9
+di5sZWFmVGFncwppZighcyl7di5sZWFmVGFncz1hCnJldHVybn1jb3B5UHJvcGVydGllcyhhLHMpfWZ1
+bmN0aW9uIHVwZGF0ZVR5cGVzKGEpe3ZhciBzPXYudHlwZXMKdmFyIHI9cy5sZW5ndGgKcy5wdXNoLmFw
+cGx5KHMsYSkKcmV0dXJuIHJ9ZnVuY3Rpb24gdXBkYXRlSG9sZGVyKGEsYil7Y29weVByb3BlcnRpZXMo
+YixhKQpyZXR1cm4gYX12YXIgaHVua0hlbHBlcnM9ZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlvbihhLGIs
+YyxkLGUpe3JldHVybiBmdW5jdGlvbihmLGcsaCxpKXtyZXR1cm4gaW5zdGFsbEluc3RhbmNlVGVhck9m
+ZihmLGcsYSxiLGMsZCxbaF0saSxlKX19LHI9ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGZ1bmN0aW9u
+KGUsZixnLGgpe3JldHVybiBpbnN0YWxsU3RhdGljVGVhck9mZihlLGYsYSxiLGMsW2ddLGgsZCl9fQpy
+ZXR1cm57aW5oZXJpdDppbmhlcml0LGluaGVyaXRNYW55OmluaGVyaXRNYW55LG1peGluOm1peGluLGlu
+c3RhbGxTdGF0aWNUZWFyT2ZmOmluc3RhbGxTdGF0aWNUZWFyT2ZmLGluc3RhbGxJbnN0YW5jZVRlYXJP
+ZmY6aW5zdGFsbEluc3RhbmNlVGVhck9mZixfaW5zdGFuY2VfMHU6cygwLDAsbnVsbCxbIiQwIl0sMCks
+X2luc3RhbmNlXzF1OnMoMCwxLG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8ydTpzKDAsMixudWxsLFsi
+JDIiXSwwKSxfaW5zdGFuY2VfMGk6cygxLDAsbnVsbCxbIiQwIl0sMCksX2luc3RhbmNlXzFpOnMoMSwx
+LG51bGwsWyIkMSJdLDApLF9pbnN0YW5jZV8yaTpzKDEsMixudWxsLFsiJDIiXSwwKSxfc3RhdGljXzA6
+cigwLG51bGwsWyIkMCJdLDApLF9zdGF0aWNfMTpyKDEsbnVsbCxbIiQxIl0sMCksX3N0YXRpY18yOnIo
+MixudWxsLFsiJDIiXSwwKSxtYWtlQ29uc3RMaXN0Om1ha2VDb25zdExpc3QsbGF6eTpsYXp5LGxhenlG
+aW5hbDpsYXp5RmluYWwsbGF6eU9sZDpsYXp5T2xkLHVwZGF0ZUhvbGRlcjp1cGRhdGVIb2xkZXIsY29u
+dmVydFRvRmFzdE9iamVjdDpjb252ZXJ0VG9GYXN0T2JqZWN0LHNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vz
+c2FyeTpzZXRGdW5jdGlvbk5hbWVzSWZOZWNlc3NhcnksdXBkYXRlVHlwZXM6dXBkYXRlVHlwZXMsc2V0
+T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZzpzZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFnLHNldE9y
+VXBkYXRlTGVhZlRhZ3M6c2V0T3JVcGRhdGVMZWFmVGFnc319KCkKZnVuY3Rpb24gaW5pdGlhbGl6ZURl
+ZmVycmVkSHVuayhhKXt4PXYudHlwZXMubGVuZ3RoCmEoaHVua0hlbHBlcnMsdix3LCQpfWZ1bmN0aW9u
+IGdldEdsb2JhbEZyb21OYW1lKGEpe2Zvcih2YXIgcz0wO3M8dy5sZW5ndGg7cysrKXtpZih3W3NdPT1D
+KWNvbnRpbnVlCmlmKHdbc11bYV0pcmV0dXJuIHdbc11bYV19fXZhciBDPXt9LEg9e0ZLOmZ1bmN0aW9u
+IEZLKCl7fSwKR0o6ZnVuY3Rpb24oYSxiLGMpe2lmKGIuQygiYlE8MD4iKS5iKGEpKXJldHVybiBuZXcg
+SC5vbChhLGIuQygiQDwwPiIpLktxKGMpLkMoIm9sPDEsMj4iKSkKcmV0dXJuIG5ldyBILlp5KGEsYi5D
+KCJAPDA+IikuS3EoYykuQygiWnk8MSwyPiIpKX0sCmM6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILm4o
+YSl9LApvbzpmdW5jdGlvbihhKXt2YXIgcyxyPWFeNDgKaWYocjw9OSlyZXR1cm4gcgpzPWF8MzIKaWYo
+OTc8PXMmJnM8PTEwMilyZXR1cm4gcy04NwpyZXR1cm4tMX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1Au
+azEoYiwic3RhcnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILnYoUC5URShiLDAs
+Yywic3RhcnQiLG51bGwpKX1yZXR1cm4gbmV3IEgubkgoYSxiLGMsZC5DKCJuSDwwPiIpKX0sCksxOmZ1
+bmN0aW9uKGEsYixjLGQpe2lmKHQuYi5iKGEpKXJldHVybiBuZXcgSC54eShhLGIsYy5DKCJAPDA+Iiku
+S3EoZCkuQygieHk8MSwyPiIpKQpyZXR1cm4gbmV3IEguaTEoYSxiLGMuQygiQDwwPiIpLktxKGQpLkMo
+ImkxPDEsMj4iKSl9LApiSzpmdW5jdGlvbihhLGIsYyl7dmFyIHM9ImNvdW50IgppZih0LmIuYihhKSl7
+UC5VSShiLHMsdC5TKQpQLmsxKGIscykKcmV0dXJuIG5ldyBILmQ1KGEsYixjLkMoImQ1PDA+IikpfVAu
+VUkoYixzLHQuUykKUC5rMShiLHMpCnJldHVybiBuZXcgSC5BTShhLGIsYy5DKCJBTTwwPiIpKX0sCldw
+OmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmxqKCJObyBlbGVtZW50Iil9LApBbTpmdW5jdGlvbigpe3Jl
+dHVybiBuZXcgUC5saigiVG9vIG1hbnkgZWxlbWVudHMiKX0sCmFyOmZ1bmN0aW9uKCl7cmV0dXJuIG5l
+dyBQLmxqKCJUb28gZmV3IGVsZW1lbnRzIil9LApCUjpmdW5jdGlvbiBCUigpe30sCkU3OmZ1bmN0aW9u
+IEU3KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sClp5OmZ1bmN0aW9uIFp5KGEsYil7dGhpcy5hPWEK
+dGhpcy4kdGk9Yn0sCm9sOmZ1bmN0aW9uIG9sKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sClVxOmZ1
+bmN0aW9uIFVxKCl7fSwKalY6ZnVuY3Rpb24galYoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKbjpm
+dW5jdGlvbiBuKGEpe3RoaXMuYT1hfSwKcWo6ZnVuY3Rpb24gcWooYSl7dGhpcy5hPWF9LApiUTpmdW5j
+dGlvbiBiUSgpe30sCmFMOmZ1bmN0aW9uIGFMKCl7fSwKbkg6ZnVuY3Rpb24gbkgoYSxiLGMsZCl7dmFy
+IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLiR0aT1kfSwKYTc6ZnVuY3Rpb24gYTcoYSxiLGMpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCmkxOmZ1bmN0aW9uIGkx
+KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKeHk6ZnVuY3Rpb24geHkoYSxiLGMp
+e3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApNSDpmdW5jdGlvbiBNSChhLGIsYyl7dmFyIF89
+dGhpcwpfLmE9bnVsbApfLmI9YQpfLmM9YgpfLiR0aT1jfSwKbEo6ZnVuY3Rpb24gbEooYSxiLGMpe3Ro
+aXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApVNTpmdW5jdGlvbiBVNShhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy4kdGk9Y30sClNPOmZ1bmN0aW9uIFNPKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9
+Ygp0aGlzLiR0aT1jfSwKQU06ZnVuY3Rpb24gQU0oYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMu
+JHRpPWN9LApkNTpmdW5jdGlvbiBkNShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30s
+ClUxOmZ1bmN0aW9uIFUxKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKTUI6ZnVu
+Y3Rpb24gTUIoYSl7dGhpcy4kdGk9YX0sCkZ1OmZ1bmN0aW9uIEZ1KGEpe3RoaXMuJHRpPWF9LAp1Njpm
+dW5jdGlvbiB1NihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApKQjpmdW5jdGlvbiBKQihhLGIpe3Ro
+aXMuYT1hCnRoaXMuJHRpPWJ9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9uIFJlKCl7fSwK
+dzI6ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sClFDOmZ1bmN0aW9u
+IFFDKCl7fSwKZGM6ZnVuY3Rpb24oKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlm
+aWFibGUgTWFwIikpfSwKTlE6ZnVuY3Rpb24oYSl7dmFyIHMscj1ILkpnKGEpCmlmKHIhPW51bGwpcmV0
+dXJuIHIKcz0ibWluaWZpZWQ6IithCnJldHVybiBzfSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihi
+IT1udWxsKXtzPWIueAppZihzIT1udWxsKXJldHVybiBzfXJldHVybiB0LmFVLmIoYSl9LApFajpmdW5j
+dGlvbihhKXt2YXIgcwppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJu
+dW1iZXIiKXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVlIgplbHNl
+IGlmKCExPT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKcz1KLmoo
+YSkKaWYodHlwZW9mIHMhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpyZXR1cm4gc30sCmVROmZ1
+bmN0aW9uKGEpe3ZhciBzPWEuJGlkZW50aXR5SGFzaAppZihzPT1udWxsKXtzPU1hdGgucmFuZG9tKCkq
+MHgzZmZmZmZmZnwwCmEuJGlkZW50aXR5SGFzaD1zfXJldHVybiBzfSwKSHA6ZnVuY3Rpb24oYSxiKXt2
+YXIgcyxyLHEscCxvLG4sbT1udWxsCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnYoSC50TChhKSkKcz0v
+XlxzKlsrLV0/KCgweFthLWYwLTldKyl8KFxkKyl8KFthLXowLTldKykpXHMqJC9pLmV4ZWMoYSkKaWYo
+cz09bnVsbClyZXR1cm4gbQppZigzPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDMpCnI9c1szXQppZihi
+PT1udWxsKXtpZihyIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZihzWzJdIT1udWxsKXJldHVy
+biBwYXJzZUludChhLDE2KQpyZXR1cm4gbX1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwyLDM2
+LCJyYWRpeCIsbSkpCmlmKGI9PT0xMCYmciE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYoYjwx
+MHx8cj09bnVsbCl7cT1iPD0xMD80NytiOjg2K2IKcD1zWzFdCmZvcihvPXAubGVuZ3RoLG49MDtuPG87
+KytuKWlmKChDLnhCLlcocCxuKXwzMik+cSlyZXR1cm4gbX1yZXR1cm4gcGFyc2VJbnQoYSxiKX0sCk06
+ZnVuY3Rpb24oYSl7cmV0dXJuIEguSDUoYSl9LApINTpmdW5jdGlvbihhKXt2YXIgcyxyLHEKaWYoYSBp
+bnN0YW5jZW9mIFAuTWgpcmV0dXJuIEguZG0oSC56KGEpLG51bGwpCmlmKEouaWEoYSk9PT1DLk9rfHx0
+LmJKLmIoYSkpe3M9Qy5PNChhKQppZihILkJlKHMpKXJldHVybiBzCnI9YS5jb25zdHJ1Y3RvcgppZih0
+eXBlb2Ygcj09ImZ1bmN0aW9uIil7cT1yLm5hbWUKaWYodHlwZW9mIHE9PSJzdHJpbmciJiZILkJlKHEp
+KXJldHVybiBxfX1yZXR1cm4gSC5kbShILnooYSksbnVsbCl9LApCZTpmdW5jdGlvbihhKXt2YXIgcz1h
+IT09Ik9iamVjdCImJmEhPT0iIgpyZXR1cm4gc30sCk0wOmZ1bmN0aW9uKCl7aWYoISFzZWxmLmxvY2F0
+aW9uKXJldHVybiBzZWxmLmxvY2F0aW9uLmhyZWYKcmV0dXJuIG51bGx9LApWSzpmdW5jdGlvbihhKXt2
+YXIgcyxyLHEscCxvPWEubGVuZ3RoCmlmKG88PTUwMClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5h
+cHBseShudWxsLGEpCmZvcihzPSIiLHI9MDtyPG87cj1xKXtxPXIrNTAwCnA9cTxvP3E6bwpzKz1TdHJp
+bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zbGljZShyLHApKX1yZXR1cm4gc30sCkNxOmZ1bmN0
+aW9uKGEpe3ZhciBzLHIscSxwPUguVk0oW10sdC5hKQpmb3Iocz1hLmxlbmd0aCxyPTA7cjxhLmxlbmd0
+aDthLmxlbmd0aD09PXN8fCgwLEgubGspKGEpLCsrcil7cT1hW3JdCmlmKCFILm9rKHEpKXRocm93IEgu
+YihILnRMKHEpKQppZihxPD02NTUzNSlDLk5tLmkocCxxKQplbHNlIGlmKHE8PTExMTQxMTEpe0MuTm0u
+aShwLDU1Mjk2KyhDLmpuLndHKHEtNjU1MzYsMTApJjEwMjMpKQpDLk5tLmkocCw1NjMyMCsocSYxMDIz
+KSl9ZWxzZSB0aHJvdyBILmIoSC50TChxKSl9cmV0dXJuIEguVksocCl9LAplVDpmdW5jdGlvbihhKXt2
+YXIgcyxyLHEKZm9yKHM9YS5sZW5ndGgscj0wO3I8czsrK3Ipe3E9YVtyXQppZighSC5vayhxKSl0aHJv
+dyBILmIoSC50TChxKSkKaWYocTwwKXRocm93IEguYihILnRMKHEpKQppZihxPjY1NTM1KXJldHVybiBI
+LkNxKGEpfXJldHVybiBILlZLKGEpfSwKZnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwCmlmKGM8
+PTUwMCYmYj09PTAmJmM9PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShu
+dWxsLGEpCmZvcihzPWIscj0iIjtzPGM7cz1xKXtxPXMrNTAwCnA9cTxjP3E6YwpyKz1TdHJpbmcuZnJv
+bUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zdWJhcnJheShzLHApKX1yZXR1cm4gcn0sCkx3OmZ1bmN0aW9u
+KGEpe3ZhciBzCmlmKDA8PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGEp
+CmlmKGE8PTExMTQxMTEpe3M9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgoNTUyOTZ8
+Qy5qbi53RyhzLDEwKSk+Pj4wLDU2MzIwfHMmMTAyMyl9fXRocm93IEguYihQLlRFKGEsMCwxMTE0MTEx
+LG51bGwsbnVsbCkpfSwKbzI6ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0ZT1uZXcg
+RGF0ZShhLmEpCnJldHVybiBhLmRhdGV9LAp0SjpmdW5jdGlvbihhKXt2YXIgcz1ILm8yKGEpLmdldEZ1
+bGxZZWFyKCkrMApyZXR1cm4gc30sCk5TOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0TW9udGgo
+KSsxCnJldHVybiBzfSwKakE6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXREYXRlKCkrMApyZXR1
+cm4gc30sCklYOmZ1bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0SG91cnMoKSswCnJldHVybiBzfSwK
+Y2g6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vMihhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gc30sCkpkOmZ1
+bmN0aW9uKGEpe3ZhciBzPUgubzIoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHN9LApvMTpmdW5jdGlv
+bihhKXt2YXIgcz1ILm8yKGEpLmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHN9LAp6bzpmdW5jdGlv
+bihhLGIsYyl7dmFyIHMscixxPXt9CnEuYT0wCnM9W10Kcj1bXQpxLmE9Yi5sZW5ndGgKQy5ObS5GVihz
+LGIpCnEuYj0iIgppZihjIT1udWxsJiZjLmEhPT0wKWMuSygwLG5ldyBILkNqKHEscixzKSkKIiIrcS5h
+CnJldHVybiBKLkp5KGEsbmV3IEguTEkoQy5UZSwwLHMsciwwKSl9LApFazpmdW5jdGlvbihhLGIsYyl7
+dmFyIHMscixxLHAKaWYoYiBpbnN0YW5jZW9mIEFycmF5KXM9Yz09bnVsbHx8Yy5hPT09MAplbHNlIHM9
+ITEKaWYocyl7cj1iCnE9ci5sZW5ndGgKaWYocT09PTApe2lmKCEhYS4kMClyZXR1cm4gYS4kMCgpfWVs
+c2UgaWYocT09PTEpe2lmKCEhYS4kMSlyZXR1cm4gYS4kMShyWzBdKX1lbHNlIGlmKHE9PT0yKXtpZigh
+IWEuJDIpcmV0dXJuIGEuJDIoclswXSxyWzFdKX1lbHNlIGlmKHE9PT0zKXtpZighIWEuJDMpcmV0dXJu
+IGEuJDMoclswXSxyWzFdLHJbMl0pfWVsc2UgaWYocT09PTQpe2lmKCEhYS4kNClyZXR1cm4gYS4kNChy
+WzBdLHJbMV0sclsyXSxyWzNdKX1lbHNlIGlmKHE9PT01KWlmKCEhYS4kNSlyZXR1cm4gYS4kNShyWzBd
+LHJbMV0sclsyXSxyWzNdLHJbNF0pCnA9YVsiIisiJCIrcV0KaWYocCE9bnVsbClyZXR1cm4gcC5hcHBs
+eShhLHIpfXJldHVybiBILmUxKGEsYixjKX0sCmUxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxv
+LG4sbSxsLGssaixpPWIgaW5zdGFuY2VvZiBBcnJheT9iOlAuQ0goYiwhMCx0LnopLGg9aS5sZW5ndGgs
+Zz1hLiRSCmlmKGg8ZylyZXR1cm4gSC56byhhLGksYykKcz1hLiRECnI9cz09bnVsbApxPSFyP3MoKTpu
+dWxsCnA9Si5pYShhKQpvPXAuJEMKaWYodHlwZW9mIG89PSJzdHJpbmciKW89cFtvXQppZihyKXtpZihj
+IT1udWxsJiZjLmEhPT0wKXJldHVybiBILnpvKGEsaSxjKQppZihoPT09ZylyZXR1cm4gby5hcHBseShh
+LGkpCnJldHVybiBILnpvKGEsaSxjKX1pZihxIGluc3RhbmNlb2YgQXJyYXkpe2lmKGMhPW51bGwmJmMu
+YSE9PTApcmV0dXJuIEguem8oYSxpLGMpCmlmKGg+ZytxLmxlbmd0aClyZXR1cm4gSC56byhhLGksbnVs
+bCkKQy5ObS5GVihpLHEuc2xpY2UoaC1nKSkKcmV0dXJuIG8uYXBwbHkoYSxpKX1lbHNle2lmKGg+Zyly
+ZXR1cm4gSC56byhhLGksYykKbj1PYmplY3Qua2V5cyhxKQppZihjPT1udWxsKWZvcihyPW4ubGVuZ3Ro
+LG09MDttPG4ubGVuZ3RoO24ubGVuZ3RoPT09cnx8KDAsSC5saykobiksKyttKXtsPXFbSC5oKG5bbV0p
+XQppZihDLk52PT09bClyZXR1cm4gSC56byhhLGksYykKQy5ObS5pKGksbCl9ZWxzZXtmb3Iocj1uLmxl
+bmd0aCxrPTAsbT0wO208bi5sZW5ndGg7bi5sZW5ndGg9PT1yfHwoMCxILmxrKShuKSwrK20pe2o9SC5o
+KG5bbV0pCmlmKGMueDQoaikpeysrawpDLk5tLmkoaSxjLnEoMCxqKSl9ZWxzZXtsPXFbal0KaWYoQy5O
+dj09PWwpcmV0dXJuIEguem8oYSxpLGMpCkMuTm0uaShpLGwpfX1pZihrIT09Yy5hKXJldHVybiBILnpv
+KGEsaSxjKX1yZXR1cm4gby5hcHBseShhLGkpfX0sCnBZOmZ1bmN0aW9uKGEpe3Rocm93IEguYihILnRM
+KGEpKX0sCk9IOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClKLkhtKGEpCnRocm93IEguYihILkhZKGEs
+YikpfSwKSFk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9ImluZGV4IgppZighSC5vayhiKSlyZXR1cm4g
+bmV3IFAudSghMCxiLHEsbnVsbCkKcz1ILnVQKEouSG0oYSkpCmlmKCEoYjwwKSl7aWYodHlwZW9mIHMh
+PT0ibnVtYmVyIilyZXR1cm4gSC5wWShzKQpyPWI+PXN9ZWxzZSByPSEwCmlmKHIpcmV0dXJuIFAuQ2Yo
+YixhLHEsbnVsbCxzKQpyZXR1cm4gUC5PNyhiLHEpfSwKYXU6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Yyly
+ZXR1cm4gUC5URShhLDAsYywic3RhcnQiLG51bGwpCmlmKGIhPW51bGwpaWYoYjxhfHxiPmMpcmV0dXJu
+IFAuVEUoYixhLGMsImVuZCIsbnVsbCkKcmV0dXJuIG5ldyBQLnUoITAsYiwiZW5kIixudWxsKX0sCnRM
+OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC51KCEwLGEsbnVsbCxudWxsKX0sCmI6ZnVuY3Rpb24oYSl7
+dmFyIHMscgppZihhPT1udWxsKWE9bmV3IFAuRigpCnM9bmV3IEVycm9yKCkKcy5kYXJ0RXhjZXB0aW9u
+PWEKcj1ILngKaWYoImRlZmluZVByb3BlcnR5IiBpbiBPYmplY3Qpe09iamVjdC5kZWZpbmVQcm9wZXJ0
+eShzLCJtZXNzYWdlIix7Z2V0OnJ9KQpzLm5hbWU9IiJ9ZWxzZSBzLnRvU3RyaW5nPXIKcmV0dXJuIHN9
+LAp4OmZ1bmN0aW9uKCl7cmV0dXJuIEouaih0aGlzLmRhcnRFeGNlcHRpb24pfSwKdjpmdW5jdGlvbihh
+KXt0aHJvdyBILmIoYSl9LApsazpmdW5jdGlvbihhKXt0aHJvdyBILmIoUC5hNChhKSl9LApjTTpmdW5j
+dGlvbihhKXt2YXIgcyxyLHEscCxvLG4KYT1ILmVBKGEucmVwbGFjZShTdHJpbmcoe30pLCckcmVjZWl2
+ZXIkJykpCnM9YS5tYXRjaCgvXFxcJFthLXpBLVpdK1xcXCQvZykKaWYocz09bnVsbClzPUguVk0oW10s
+dC5zKQpyPXMuaW5kZXhPZigiXFwkYXJndW1lbnRzXFwkIikKcT1zLmluZGV4T2YoIlxcJGFyZ3VtZW50
+c0V4cHJcXCQiKQpwPXMuaW5kZXhPZigiXFwkZXhwclxcJCIpCm89cy5pbmRleE9mKCJcXCRtZXRob2Rc
+XCQiKQpuPXMuaW5kZXhPZigiXFwkcmVjZWl2ZXJcXCQiKQpyZXR1cm4gbmV3IEguZjkoYS5yZXBsYWNl
+KG5ldyBSZWdFeHAoJ1xcXFxcXCRhcmd1bWVudHNcXFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJyku
+cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkYXJndW1lbnRzRXhwclxcXFxcXCQnLCdnJyksJygoPzp4
+fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRleHByXFxcXFxcJCcsJ2cnKSwnKCg/
+Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJG1ldGhvZFxcXFxcXCQnLCdnJyks
+JygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRyZWNlaXZlclxcXFxcXCQn
+LCdnJyksJygoPzp4fFteeF0pKiknKSxyLHEscCxvLG4pfSwKUzc6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1
+bmN0aW9uKCRleHByJCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXskZXhwciQu
+JG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChzKXtyZXR1cm4gcy5tZXNzYWdlfX0oYSl9LApN
+ajpmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rpb24oJGV4cHIkKXt0cnl7JGV4cHIkLiRtZXRob2QkfWNh
+dGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fShhKX0sCklqOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBI
+LlcwKGEsYj09bnVsbD9udWxsOmIubWV0aG9kKX0sClQzOmZ1bmN0aW9uKGEsYil7dmFyIHM9Yj09bnVs
+bCxyPXM/bnVsbDpiLm1ldGhvZApyZXR1cm4gbmV3IEguYXooYSxyLHM/bnVsbDpiLnJlY2VpdmVyKX0s
+ClJ1OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG5ldyBILnRlKGEpCmlmKGEgaW5zdGFuY2Vv
+ZiBILmJxKXJldHVybiBILnRXKGEsYS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlm
+KCJkYXJ0RXhjZXB0aW9uIiBpbiBhKXJldHVybiBILnRXKGEsYS5kYXJ0RXhjZXB0aW9uKQpyZXR1cm4g
+SC50bChhKX0sCnRXOmZ1bmN0aW9uKGEsYil7aWYodC5yLmIoYikpaWYoYi4kdGhyb3duSnNFcnJvcj09
+bnVsbCliLiR0aHJvd25Kc0Vycm9yPWEKcmV0dXJuIGJ9LAp0bDpmdW5jdGlvbihhKXt2YXIgcyxyLHEs
+cCxvLG4sbSxsLGssaixpLGgsZyxmLGU9bnVsbAppZighKCJtZXNzYWdlIiBpbiBhKSlyZXR1cm4gYQpz
+PWEubWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9PSJudW1iZXIiKXtyPWEu
+bnVtYmVyCnE9ciY2NTUzNQppZigoQy5qbi53RyhyLDE2KSY4MTkxKT09PTEwKXN3aXRjaChxKXtjYXNl
+IDQzODpyZXR1cm4gSC50VyhhLEguVDMoSC5FaihzKSsiIChFcnJvciAiK3ErIikiLGUpKQpjYXNlIDQ0
+NTpjYXNlIDUwMDc6cmV0dXJuIEgudFcoYSxILklqKEguRWoocykrIiAoRXJyb3IgIitxKyIpIixlKSl9
+fWlmKGEgaW5zdGFuY2VvZiBUeXBlRXJyb3Ipe3A9JC5TbigpCm89JC5scSgpCm49JC5OOSgpCm09JC5p
+SSgpCmw9JC5VTigpCms9JC5aaCgpCmo9JC5yTigpCiQuYzMoKQppPSQuSEsoKQpoPSQucjEoKQpnPXAu
+cVMocykKaWYoZyE9bnVsbClyZXR1cm4gSC50VyhhLEguVDMoSC5oKHMpLGcpKQplbHNle2c9by5xUyhz
+KQppZihnIT1udWxsKXtnLm1ldGhvZD0iY2FsbCIKcmV0dXJuIEgudFcoYSxILlQzKEguaChzKSxnKSl9
+ZWxzZXtnPW4ucVMocykKaWYoZz09bnVsbCl7Zz1tLnFTKHMpCmlmKGc9PW51bGwpe2c9bC5xUyhzKQpp
+ZihnPT1udWxsKXtnPWsucVMocykKaWYoZz09bnVsbCl7Zz1qLnFTKHMpCmlmKGc9PW51bGwpe2c9bS5x
+UyhzKQppZihnPT1udWxsKXtnPWkucVMocykKaWYoZz09bnVsbCl7Zz1oLnFTKHMpCmY9ZyE9bnVsbH1l
+bHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1lbHNlIGY9ITB9ZWxzZSBmPSEwfWVsc2UgZj0hMH1l
+bHNlIGY9ITAKaWYoZilyZXR1cm4gSC50VyhhLEguSWooSC5oKHMpLGcpKX19cmV0dXJuIEgudFcoYSxu
+ZXcgSC52Vih0eXBlb2Ygcz09InN0cmluZyI/czoiIikpfWlmKGEgaW5zdGFuY2VvZiBSYW5nZUVycm9y
+KXtpZih0eXBlb2Ygcz09InN0cmluZyImJnMuaW5kZXhPZigiY2FsbCBzdGFjayIpIT09LTEpcmV0dXJu
+IG5ldyBQLktZKCkKcz1mdW5jdGlvbihiKXt0cnl7cmV0dXJuIFN0cmluZyhiKX1jYXRjaChkKXt9cmV0
+dXJuIG51bGx9KGEpCnJldHVybiBILnRXKGEsbmV3IFAudSghMSxlLGUsdHlwZW9mIHM9PSJzdHJpbmci
+P3MucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6cykpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9y
+PT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2Ygcz09InN0cmlu
+ZyImJnM9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRz
+OmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVs
+bClyZXR1cm4gbmV3IEguWE8oYSkKcz1hLiRjYWNoZWRUcmFjZQppZihzIT1udWxsKXJldHVybiBzCnJl
+dHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHMscixx
+LHA9YS5sZW5ndGgKZm9yKHM9MDtzPHA7cz1xKXtyPXMrMQpxPXIrMQpiLlkoMCxhW3NdLGFbcl0pfXJl
+dHVybiBifSwKZnQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3QuWS5hKGEpCnN3aXRjaChILnVQKGIpKXtj
+YXNlIDA6cmV0dXJuIGEuJDAoKQpjYXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQy
+KGMsZCkKY2FzZSAzOnJldHVybiBhLiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9
+dGhyb3cgSC5iKG5ldyBQLkNEKCJVbnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFw
+cGVkIGNsb3N1cmUiKSl9LAp0UjpmdW5jdGlvbihhLGIpe3ZhciBzCmlmKGE9PW51bGwpcmV0dXJuIG51
+bGwKcz1hLiRpZGVudGl0eQppZighIXMpcmV0dXJuIHMKcz1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1
+bmN0aW9uKGYsZyxoLGkpe3JldHVybiBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0
+eT1zCnJldHVybiBzfSwKaUE6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHMscixxLHAsbyxuLG0s
+bD1iWzBdLGs9bC4kY2FsbE5hbWUsaj1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5jb25zdHJ1Y3Rv
+ci5wcm90b3R5cGUpOk9iamVjdC5jcmVhdGUobmV3IEguclQobnVsbCxudWxsLG51bGwsIiIpLmNvbnN0
+cnVjdG9yLnByb3RvdHlwZSkKai4kaW5pdGlhbGl6ZT1qLmNvbnN0cnVjdG9yCmlmKGUpcz1mdW5jdGlv
+biBzdGF0aWNfdGVhcl9vZmYoKXt0aGlzLiRpbml0aWFsaXplKCl9CmVsc2V7cj0kLnlqCmlmKHR5cGVv
+ZiByIT09Im51bWJlciIpcmV0dXJuIHIuaCgpCiQueWo9cisxCnI9bmV3IEZ1bmN0aW9uKCJhLGIsYyxk
+IityLCJ0aGlzLiRpbml0aWFsaXplKGEsYixjLGQiK3IrIikiKQpzPXJ9ai5jb25zdHJ1Y3Rvcj1zCnMu
+cHJvdG90eXBlPWoKaWYoIWUpe3E9SC5ieChhLGwsZikKcS4kcmVmbGVjdGlvbkluZm89ZH1lbHNle2ou
+JHN0YXRpY19uYW1lPWcKcT1sfWouJFM9SC5pbShkLGUsZikKaltrXT1xCmZvcihwPXEsbz0xO288Yi5s
+ZW5ndGg7KytvKXtuPWJbb10KbT1uLiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEsbixm
+KQpqW21dPW59aWYobz09PWMpe24uJHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1qLiRDPXAKai4kUj1sLiRS
+CmouJEQ9bC4kRApyZXR1cm4gc30sCmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwppZih0eXBlb2YgYT09
+Im51bWJlciIpcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQoZSl9
+fShILkJwLGEpCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBjb21w
+dXRlIHNpZ25hdHVyZSBmb3Igc3RhdGljIHRlYXJvZmYuIikKcz1jP0guUFc6SC5UbgpyZXR1cm4gZnVu
+Y3Rpb24oZCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSxzKX10aHJvdyBI
+LmIoIkVycm9yIGluIGZ1bmN0aW9uVHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgcz1ILkRWCnN3aXRjaChiPy0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1
+cm4gZnVuY3Rpb24oKXtyZXR1cm4gZih0aGlzKVtlXSgpfX0oYyxzKQpjYXNlIDE6cmV0dXJuIGZ1bmN0
+aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyxzKQpjYXNl
+IDI6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhpcylb
+ZV0oZyxoKX19KGMscykKY2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlvbihn
+LGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyxoLGkpfX0oYyxzKQpjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9u
+KGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGopfX0o
+YyxzKQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGosayl7
+cmV0dXJuIGYodGhpcylbZV0oZyxoLGksaixrKX19KGMscykKZGVmYXVsdDpyZXR1cm4gZnVuY3Rpb24o
+ZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9fShk
+LHMpfX0sCmJ4OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvLG4sbQppZihjKXJldHVybiBILkhm
+KGEsYikKcz1iLiRzdHViTmFtZQpyPWIubGVuZ3RoCnE9YVtzXQpwPWI9PW51bGw/cT09bnVsbDpiPT09
+cQpvPSFwfHxyPj0yNwppZihvKXJldHVybiBILnZxKHIsIXAscyxiKQppZihyPT09MCl7cD0kLnlqCmlm
+KHR5cGVvZiBwIT09Im51bWJlciIpcmV0dXJuIHAuaCgpCiQueWo9cCsxCm49InNlbGYiK3AKcmV0dXJu
+IG5ldyBGdW5jdGlvbigicmV0dXJuIGZ1bmN0aW9uKCl7dmFyICIrbisiID0gdGhpcy4iK0guRWooSC5v
+TigpKSsiO3JldHVybiAiK24rIi4iK0guRWoocykrIigpO30iKSgpfW09ImFiY2RlZmdoaWprbG1ub3Bx
+cnN0dXZ3eHl6Ii5zcGxpdCgiIikuc3BsaWNlKDAscikuam9pbigiLCIpCnA9JC55agppZih0eXBlb2Yg
+cCE9PSJudW1iZXIiKXJldHVybiBwLmgoKQokLnlqPXArMQptKz1wCnJldHVybiBuZXcgRnVuY3Rpb24o
+InJldHVybiBmdW5jdGlvbigiK20rIil7cmV0dXJuIHRoaXMuIitILkVqKEgub04oKSkrIi4iK0guRWoo
+cykrIigiK20rIik7fSIpKCl9LApaNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcz1ILkRWLHI9SC55Uwpz
+d2l0Y2goYj8tMTphKXtjYXNlIDA6dGhyb3cgSC5iKG5ldyBILkVxKCJJbnRlcmNlcHRlZCBmdW5jdGlv
+biB3aXRoIG5vIGFyZ3VtZW50cy4iKSkKY2FzZSAxOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJu
+IGZ1bmN0aW9uKCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSl9fShjLHMscikKY2FzZSAyOnJldHVy
+biBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgpe3JldHVybiBmKHRoaXMpW2VdKGcodGhp
+cyksaCl9fShjLHMscikKY2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9u
+KGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGkpfX0oYyxzLHIpCmNhc2UgNDpyZXR1cm4g
+ZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyh0
+aGlzKSxoLGksail9fShjLHMscikKY2FzZSA1OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1
+bmN0aW9uKGgsaSxqLGspe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpLGosayl9fShjLHMscikK
+Y2FzZSA2OnJldHVybiBmdW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqLGssbCl7cmV0
+dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrLGwpfX0oYyxzLHIpCmRlZmF1bHQ6cmV0dXJuIGZ1
+bmN0aW9uKGUsZixnLGgpe3JldHVybiBmdW5jdGlvbigpe2g9W2codGhpcyldCkFycmF5LnByb3RvdHlw
+ZS5wdXNoLmFwcGx5KGgsYXJndW1lbnRzKQpyZXR1cm4gZS5hcHBseShmKHRoaXMpLGgpfX0oZCxzLHIp
+fX0sCkhmOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG09SC5vTigpLGw9JC5QNAppZihsPT1u
+dWxsKWw9JC5QND1ILkUyKCJyZWNlaXZlciIpCnM9Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10K
+cD1iPT1udWxsP3E9PW51bGw6Yj09PXEKbz0hcHx8cj49MjgKaWYobylyZXR1cm4gSC5aNChyLCFwLHMs
+YikKaWYocj09PTEpe3A9InJldHVybiBmdW5jdGlvbigpe3JldHVybiB0aGlzLiIrSC5FaihtKSsiLiIr
+SC5FaihzKSsiKHRoaXMuIitsKyIpOyIKbz0kLnlqCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJu
+IG8uaCgpCiQueWo9bysxCnJldHVybiBuZXcgRnVuY3Rpb24ocCtvKyJ9IikoKX1uPSJhYmNkZWZnaGlq
+a2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIpLnNwbGljZSgwLHItMSkuam9pbigiLCIpCnA9InJldHVy
+biBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIitILkVqKG0pKyIuIitILkVqKHMpKyIodGhpcy4i
+K2wrIiwgIituKyIpOyIKbz0kLnlqCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8uaCgpCiQu
+eWo9bysxCnJldHVybiBuZXcgRnVuY3Rpb24ocCtvKyJ9IikoKX0sCktxOmZ1bmN0aW9uKGEsYixjLGQs
+ZSxmLGcpe3JldHVybiBILmlBKGEsYixjLGQsISFlLCEhZixnKX0sClRuOmZ1bmN0aW9uKGEsYil7cmV0
+dXJuIEguY0Uodi50eXBlVW5pdmVyc2UsSC56KGEuYSksYil9LApQVzpmdW5jdGlvbihhLGIpe3JldHVy
+biBILmNFKHYudHlwZVVuaXZlcnNlLEgueihhLmMpLGIpfSwKRFY6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+YX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN9LApvTjpmdW5jdGlvbigpe3ZhciBzPSQubUoKcmV0
+dXJuIHM9PW51bGw/JC5tSj1ILkUyKCJzZWxmIik6c30sCkUyOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxw
+PW5ldyBILnJUKCJzZWxmIiwidGFyZ2V0IiwicmVjZWl2ZXIiLCJuYW1lIiksbz1KLkVwKE9iamVjdC5n
+ZXRPd25Qcm9wZXJ0eU5hbWVzKHApLHQuVykKZm9yKHM9by5sZW5ndGgscj0wO3I8czsrK3Ipe3E9b1ty
+XQppZihwW3FdPT09YSlyZXR1cm4gcX10aHJvdyBILmIoUC54WSgiRmllbGQgbmFtZSAiK2ErIiBub3Qg
+Zm91bmQuIikpfSwKb1Q6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClILmZPKCJib29sZWFuIGV4cHJlc3Np
+b24gbXVzdCBub3QgYmUgbnVsbCIpCnJldHVybiBhfSwKZk86ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5l
+dyBILmtZKGEpKX0sCmFnOmZ1bmN0aW9uKGEpe3Rocm93IEguYihuZXcgUC5wKGEpKX0sCllnOmZ1bmN0
+aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApCbzpmdW5jdGlvbihhKXtyZXR1cm4gSC52
+KEguYyhhKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFs
+dWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KX0sCncz
+OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbj1ILmgoJC5ORi4kMShhKSksbT0kLm53W25dCmlmKG0h
+PW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVl
+Om0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJu
+IG0uaX1zPSQudnZbbl0KaWYocyE9bnVsbClyZXR1cm4gcwpyPXYuaW50ZXJjZXB0b3JzQnlUYWdbbl0K
+aWYocj09bnVsbCl7cT1ILmsoJC5UWC4kMihhLG4pKQppZihxIT1udWxsKXttPSQubndbcV0KaWYobSE9
+bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5kaXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6
+bSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4g
+bS5pfXM9JC52dltxXQppZihzIT1udWxsKXJldHVybiBzCnI9di5pbnRlcmNlcHRvcnNCeVRhZ1txXQpu
+PXF9fWlmKHI9PW51bGwpcmV0dXJuIG51bGwKcz1yLnByb3RvdHlwZQpwPW5bMF0KaWYocD09PSIhIil7
+bT1ILlZhKHMpCiQubndbbl09bQpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVy
+dHlOYW1lLHt2YWx1ZTptLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6
+dHJ1ZX0pCnJldHVybiBtLml9aWYocD09PSJ+Iil7JC52dltuXT1zCnJldHVybiBzfWlmKHA9PT0iLSIp
+e289SC5WYShzKQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYu
+ZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVl
+LGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX1pZihwPT09IisiKXJldHVybiBILkxjKGEscykK
+aWYocD09PSIqIil0aHJvdyBILmIoUC5TWShuKSkKaWYodi5sZWFmVGFnc1tuXT09PXRydWUpe289SC5W
+YShzKQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0
+Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZp
+Z3VyYWJsZTp0cnVlfSkKcmV0dXJuIG8uaX1lbHNlIHJldHVybiBILkxjKGEscyl9LApMYzpmdW5jdGlv
+bihhLGIpe3ZhciBzPU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQpPYmplY3QuZGVmaW5lUHJvcGVydHko
+cyx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpKLlF1KGIscyxudWxsLG51bGwpLGVudW1lcmFi
+bGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBifSwKVmE6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouUXUoYSwhMSxudWxsLCEhYS4kaVhqKX0sClZGOmZ1bmN0aW9uKGEsYixj
+KXt2YXIgcz1iLnByb3RvdHlwZQppZih2LmxlYWZUYWdzW2FdPT09dHJ1ZSlyZXR1cm4gSC5WYShzKQpl
+bHNlIHJldHVybiBKLlF1KHMsYyxudWxsLG51bGwpfSwKWEQ6ZnVuY3Rpb24oKXtpZighMD09PSQuQnYp
+cmV0dXJuCiQuQnY9ITAKSC5aMSgpfSwKWjE6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbSxsCiQu
+bnc9T2JqZWN0LmNyZWF0ZShudWxsKQokLnZ2PU9iamVjdC5jcmVhdGUobnVsbCkKSC5rTygpCnM9di5p
+bnRlcmNlcHRvcnNCeVRhZwpyPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHMpCmlmKHR5cGVvZiB3
+aW5kb3chPSJ1bmRlZmluZWQiKXt3aW5kb3cKcT1mdW5jdGlvbigpe30KZm9yKHA9MDtwPHIubGVuZ3Ro
+OysrcCl7bz1yW3BdCm49JC54Ny4kMShvKQppZihuIT1udWxsKXttPUguVkYobyxzW29dLG4pCmlmKG0h
+PW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShuLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVl
+Om0sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcS5wcm90
+b3R5cGU9bn19fX1mb3IocD0wO3A8ci5sZW5ndGg7KytwKXtvPXJbcF0KaWYoL15bQS1aYS16X10vLnRl
+c3Qobykpe2w9c1tvXQpzWyIhIitvXT1sCnNbIn4iK29dPWwKc1siLSIrb109bApzWyIrIitvXT1sCnNb
+IioiK29dPWx9fX0sCmtPOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09Qy5ZcSgpCm09SC51ZChD
+LktVLEgudWQoQy5mUSxILnVkKEMuaTcsSC51ZChDLmk3LEgudWQoQy54aSxILnVkKEMuZGssSC51ZChD
+LndiKEMuTzQpLG0pKSkpKSkpCmlmKHR5cGVvZiBkYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9y
+bWVyIT0idW5kZWZpbmVkIil7cz1kYXJ0TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyCmlmKHR5
+cGVvZiBzPT0iZnVuY3Rpb24iKXM9W3NdCmlmKHMuY29uc3RydWN0b3I9PUFycmF5KWZvcihyPTA7cjxz
+Lmxlbmd0aDsrK3Ipe3E9c1tyXQppZih0eXBlb2YgcT09ImZ1bmN0aW9uIiltPXEobSl8fG19fXA9bS5n
+ZXRUYWcKbz1tLmdldFVua25vd25UYWcKbj1tLnByb3RvdHlwZUZvclRhZwokLk5GPW5ldyBILmRDKHAp
+CiQuVFg9bmV3IEgud04obykKJC54Nz1uZXcgSC5WWChuKX0sCnVkOmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IGEoYil8fGJ9LAp2NDpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHM9Yj8ibSI6IiIscj1jPyIiOiJp
+IixxPWQ/InUiOiIiLHA9ZT8icyI6IiIsbz1mPyJnIjoiIixuPWZ1bmN0aW9uKGcsaCl7dHJ5e3JldHVy
+biBuZXcgUmVnRXhwKGcsaCl9Y2F0Y2gobSl7cmV0dXJuIG19fShhLHMrcitxK3ArbykKaWYobiBpbnN0
+YW5jZW9mIFJlZ0V4cClyZXR1cm4gbgp0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBSZWdFeHAgcGF0dGVy
+biAoIitTdHJpbmcobikrIikiLGEsbnVsbCkpfSwKbTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKHR5
+cGVvZiBiPT0ic3RyaW5nIilyZXR1cm4gYS5pbmRleE9mKGIsYyk+PTAKZWxzZSBpZihiIGluc3RhbmNl
+b2YgSC5WUil7cz1DLnhCLkcoYSxjKQpyZXR1cm4gYi5iLnRlc3Qocyl9ZWxzZXtzPUouRkwoYixDLnhC
+LkcoYSxjKSkKcmV0dXJuIXMuZ2wwKHMpfX0sCkE0OmZ1bmN0aW9uKGEpe2lmKGEuaW5kZXhPZigiJCIs
+MCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQkJCIpCnJldHVybiBhfSwKZUE6ZnVuY3Rpb24o
+YSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChhKSlyZXR1cm4gYS5yZXBsYWNlKC9bW1xde30o
+KSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwKeXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPUgu
+bk0oYSxiLGMpCnJldHVybiBzfSwKbk06ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwCmlmKGI9PT0i
+Iil7aWYoYT09PSIiKXJldHVybiBjCnM9YS5sZW5ndGgKZm9yKHI9YyxxPTA7cTxzOysrcSlyPXIrYVtx
+XStjCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfXA9YS5pbmRleE9mKGIsMCkKaWYocDwwKXJl
+dHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9mKCIkIiwwKT49MClyZXR1cm4gYS5zcGxpdChi
+KS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJlZ0V4cChILmVBKGIpLCdnJyksSC5BNChjKSl9
+LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApXVTpmdW5jdGlvbiBXVSgp
+e30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4k
+dGk9ZH0sClhSOmZ1bmN0aW9uIFhSKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCkxJOmZ1bmN0aW9u
+IExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLmY9ZX0sCkNq
+OmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCmY5OmZ1bmN0aW9u
+IGY5KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8u
+Zj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmF6OmZ1bmN0aW9uIGF6
+KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnZWOmZ1bmN0aW9uIHZWKGEpe3RoaXMu
+YT1hfSwKdGU6ZnVuY3Rpb24gdGUoYSl7dGhpcy5hPWF9LApicTpmdW5jdGlvbiBicShhLGIpe3RoaXMu
+YT1hCnRoaXMuYj1ifSwKWE86ZnVuY3Rpb24gWE8oYSl7dGhpcy5hPWEKdGhpcy5iPW51bGx9LApUcDpm
+dW5jdGlvbiBUcCgpe30sCmxjOmZ1bmN0aW9uIGxjKCl7fSwKeng6ZnVuY3Rpb24gengoKXt9LApyVDpm
+dW5jdGlvbiByVChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKRXE6
+ZnVuY3Rpb24gRXEoYSl7dGhpcy5hPWF9LAprWTpmdW5jdGlvbiBrWShhKXt0aGlzLmE9YX0sCmtyOmZ1
+bmN0aW9uIGtyKCl7fSwKTjU6ZnVuY3Rpb24gTjUoYSl7dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5lPV8u
+ZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4kdGk9YX0sCnZoOmZ1bmN0aW9uIHZoKGEsYil7dmFyIF89dGhp
+cwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LAppNTpmdW5jdGlvbiBpNShhLGIpe3RoaXMuYT1hCnRo
+aXMuJHRpPWJ9LApONjpmdW5jdGlvbiBONihhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9
+Xy5jPW51bGwKXy4kdGk9Y30sCmRDOmZ1bmN0aW9uIGRDKGEpe3RoaXMuYT1hfSwKd046ZnVuY3Rpb24g
+d04oYSl7dGhpcy5hPWF9LApWWDpmdW5jdGlvbiBWWChhKXt0aGlzLmE9YX0sClZSOmZ1bmN0aW9uIFZS
+KGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LApFSzpmdW5jdGlvbiBFSyhh
+KXt0aGlzLmI9YX0sCktXOmZ1bmN0aW9uIEtXKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
+Y30sClBiOmZ1bmN0aW9uIFBiKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1u
+dWxsfSwKdFE6ZnVuY3Rpb24gdFEoYSxiKXt0aGlzLmE9YQp0aGlzLmM9Yn0sCnVuOmZ1bmN0aW9uIHVu
+KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClNkOmZ1bmN0aW9uIFNkKGEsYixjKXt2
+YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwKWEY6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGF9LApvZDpmdW5jdGlvbihhLGIsYyl7aWYoYT4+PjAhPT1hfHxhPj1jKXRocm93IEguYihILkhZKGIs
+YSkpfSwKck06ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKCEoYT4+PjAhPT1hKSlzPWI+Pj4wIT09Ynx8
+YT5ifHxiPmMKZWxzZSBzPSEwCmlmKHMpdGhyb3cgSC5iKEguYXUoYSxiLGMpKQpyZXR1cm4gYn0sCkVU
+OmZ1bmN0aW9uIEVUKCl7fSwKWEg6ZnVuY3Rpb24gWEgoKXt9LApEZzpmdW5jdGlvbiBEZygpe30sClBn
+OmZ1bmN0aW9uIFBnKCl7fSwKeGo6ZnVuY3Rpb24geGooKXt9LApkRTpmdW5jdGlvbiBkRSgpe30sClpB
+OmZ1bmN0aW9uIFpBKCl7fSwKZFQ6ZnVuY3Rpb24gZFQoKXt9LApQcTpmdW5jdGlvbiBQcSgpe30sCmVF
+OmZ1bmN0aW9uIGVFKCl7fSwKVjY6ZnVuY3Rpb24gVjYoKXt9LApSRzpmdW5jdGlvbiBSRygpe30sClZQ
+OmZ1bmN0aW9uIFZQKCl7fSwKV0I6ZnVuY3Rpb24gV0IoKXt9LApaRzpmdW5jdGlvbiBaRygpe30sCmN6
+OmZ1bmN0aW9uKGEsYil7dmFyIHM9Yi5jCnJldHVybiBzPT1udWxsP2IuYz1ILkIoYSxiLnosITApOnN9
+LAp4WjpmdW5jdGlvbihhLGIpe3ZhciBzPWIuYwpyZXR1cm4gcz09bnVsbD9iLmM9SC5KKGEsImI4Iixb
+Yi56XSk6c30sClExOmZ1bmN0aW9uKGEpe3ZhciBzPWEueQppZihzPT09Nnx8cz09PTd8fHM9PT04KXJl
+dHVybiBILlExKGEueikKcmV0dXJuIHM9PT0xMXx8cz09PTEyfSwKbUQ6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEuY3l9LApOMDpmdW5jdGlvbihhKXtyZXR1cm4gSC5FKHYudHlwZVVuaXZlcnNlLGEsITEpfSwKUEw6
+ZnVuY3Rpb24oYSxiLGEwLGExKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjPWIu
+eQpzd2l0Y2goYyl7Y2FzZSA1OmNhc2UgMTpjYXNlIDI6Y2FzZSAzOmNhc2UgNDpyZXR1cm4gYgpjYXNl
+IDY6cz1iLnoKcj1ILlBMKGEscyxhMCxhMSkKaWYocj09PXMpcmV0dXJuIGIKcmV0dXJuIEguQyhhLHIs
+ITApCmNhc2UgNzpzPWIuegpyPUguUEwoYSxzLGEwLGExKQppZihyPT09cylyZXR1cm4gYgpyZXR1cm4g
+SC5CKGEsciwhMCkKY2FzZSA4OnM9Yi56CnI9SC5QTChhLHMsYTAsYTEpCmlmKHI9PT1zKXJldHVybiBi
+CnJldHVybiBILmYoYSxyLCEwKQpjYXNlIDk6cT1iLlEKcD1ILmJaKGEscSxhMCxhMSkKaWYocD09PXEp
+cmV0dXJuIGIKcmV0dXJuIEguSihhLGIueixwKQpjYXNlIDEwOm89Yi56Cm49SC5QTChhLG8sYTAsYTEp
+Cm09Yi5RCmw9SC5iWihhLG0sYTAsYTEpCmlmKG49PT1vJiZsPT09bSlyZXR1cm4gYgpyZXR1cm4gSC5h
+KGEsbixsKQpjYXNlIDExOms9Yi56Cmo9SC5QTChhLGssYTAsYTEpCmk9Yi5RCmg9SC5xVChhLGksYTAs
+YTEpCmlmKGo9PT1rJiZoPT09aSlyZXR1cm4gYgpyZXR1cm4gSC5kKGEsaixoKQpjYXNlIDEyOmc9Yi5R
+CmExKz1nLmxlbmd0aApmPUguYlooYSxnLGEwLGExKQpvPWIuegpuPUguUEwoYSxvLGEwLGExKQppZihm
+PT09ZyYmbj09PW8pcmV0dXJuIGIKcmV0dXJuIEguRChhLG4sZiwhMCkKY2FzZSAxMzplPWIuegppZihl
+PGExKXJldHVybiBiCmQ9YTBbZS1hMV0KaWYoZD09bnVsbClyZXR1cm4gYgpyZXR1cm4gZApkZWZhdWx0
+OnRocm93IEguYihQLmhWKCJBdHRlbXB0ZWQgdG8gc3Vic3RpdHV0ZSB1bmV4cGVjdGVkIFJUSSBraW5k
+ICIrYykpfX0sCmJaOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG89Yi5sZW5ndGgsbj1bXQpm
+b3Iocz0hMSxyPTA7cjxvOysrcil7cT1iW3JdCnA9SC5QTChhLHEsYyxkKQppZihwIT09cSlzPSEwCm4u
+cHVzaChwKX1yZXR1cm4gcz9uOmJ9LAp2TzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvLG4s
+bT1iLmxlbmd0aCxsPVtdCmZvcihzPSExLHI9MDtyPG07cis9Myl7cT1iW3JdCnA9YltyKzFdCm89Ylty
+KzJdCm49SC5QTChhLG8sYyxkKQppZihuIT09bylzPSEwCmwucHVzaChxKQpsLnB1c2gocCkKbC5wdXNo
+KG4pfXJldHVybiBzP2w6Yn0sCnFUOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHI9Yi5hLHE9SC5iWihh
+LHIsYyxkKSxwPWIuYixvPUguYlooYSxwLGMsZCksbj1iLmMsbT1ILnZPKGEsbixjLGQpCmlmKHE9PT1y
+JiZvPT09cCYmbT09PW4pcmV0dXJuIGIKcz1uZXcgSC5HKCkKcy5hPXEKcy5iPW8Kcy5jPW0KcmV0dXJu
+IHN9LApWTTpmdW5jdGlvbihhLGIpe2Fbdi5hcnJheVJ0aV09YgpyZXR1cm4gYX0sCkpTOmZ1bmN0aW9u
+KGEpe3ZhciBzPWEuJFMKaWYocyE9bnVsbCl7aWYodHlwZW9mIHM9PSJudW1iZXIiKXJldHVybiBILkJw
+KHMpCnJldHVybiBhLiRTKCl9cmV0dXJuIG51bGx9LApVZTpmdW5jdGlvbihhLGIpe3ZhciBzCmlmKEgu
+UTEoYikpaWYoYSBpbnN0YW5jZW9mIEguVHApe3M9SC5KUyhhKQppZihzIT1udWxsKXJldHVybiBzfXJl
 dHVybiBILnooYSl9LAp6OmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGEgaW5zdGFuY2VvZiBQLk1oKXtzPWEu
 JHRpCnJldHVybiBzIT1udWxsP3M6SC5WVShhKX1pZihBcnJheS5pc0FycmF5KGEpKXJldHVybiBILnQ2
 KGEpCnJldHVybiBILlZVKEouaWEoYSkpfSwKdDY6ZnVuY3Rpb24oYSl7dmFyIHM9YVt2LmFycmF5UnRp
-XSxyPXQudgppZihzPT1udWxsKXJldHVybiByCmlmKHMuY29uc3RydWN0b3IhPT1yLmNvbnN0cnVjdG9y
+XSxyPXQueAppZihzPT1udWxsKXJldHVybiByCmlmKHMuY29uc3RydWN0b3IhPT1yLmNvbnN0cnVjdG9y
 KXJldHVybiByCnJldHVybiBzfSwKTGg6ZnVuY3Rpb24oYSl7dmFyIHM9YS4kdGkKcmV0dXJuIHMhPW51
 bGw/czpILlZVKGEpfSwKVlU6ZnVuY3Rpb24oYSl7dmFyIHM9YS5jb25zdHJ1Y3RvcixyPXMuJGNjYWNo
 ZQppZihyIT1udWxsKXJldHVybiByCnJldHVybiBILnI5KGEscyl9LApyOTpmdW5jdGlvbihhLGIpe3Zh
-ciBzPWEgaW5zdGFuY2VvZiBILnY/YS5fX3Byb3RvX18uX19wcm90b19fLmNvbnN0cnVjdG9yOmIscj1I
-LmFpKHYudHlwZVVuaXZlcnNlLHMubmFtZSkKYi4kY2NhY2hlPXIKcmV0dXJuIHJ9LApCcDpmdW5jdGlv
-bihhKXt2YXIgcyxyLHEKSC51UChhKQpzPXYudHlwZXMKcj1zW2FdCmlmKHR5cGVvZiByPT0ic3RyaW5n
-Iil7cT1ILkUodi50eXBlVW5pdmVyc2UsciwhMSkKc1thXT1xCnJldHVybiBxfXJldHVybiByfSwKSko6
-ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD10LksKaWYocT09PXApcmV0dXJuIEguUkUocSxhLEgu
-a2UpCmlmKCFILkE4KHEpKWlmKCEocT09PXQuXykpcD1xPT09cAplbHNlIHA9ITAKZWxzZSBwPSEwCmlm
-KHApcmV0dXJuIEguUkUocSxhLEguSXcpCnA9cS55CnM9cD09PTY/cS56OnEKaWYocz09PXQucClyPUgu
-b2sKZWxzZSBpZihzPT09dC5nUnx8cz09PXQuZGkpcj1ILktICmVsc2UgaWYocz09PXQuTilyPUguTU0K
-ZWxzZSByPXM9PT10Lnk/SC5sOm51bGwKaWYociE9bnVsbClyZXR1cm4gSC5SRShxLGEscikKaWYocy55
-PT09OSl7cD1zLnoKaWYocy5RLmV2ZXJ5KEguY2MpKXtxLnI9IiRpIitwCnJldHVybiBILlJFKHEsYSxI
-LnQ0KX19ZWxzZSBpZihwPT09NylyZXR1cm4gSC5SRShxLGEsSC5BUSkKcmV0dXJuIEguUkUocSxhLEgu
-WU8pfSwKUkU6ZnVuY3Rpb24oYSxiLGMpe2EuYj1jCnJldHVybiBhLmIoYil9LApBdTpmdW5jdGlvbihh
-KXt2YXIgcyxyLHE9dGhpcwppZighSC5BOChxKSlpZighKHE9PT10Ll8pKXM9cT09PXQuSwplbHNlIHM9
-ITAKZWxzZSBzPSEwCmlmKHMpcj1ILmhuCmVsc2UgaWYocT09PXQuSylyPUguVGkKZWxzZSByPUgubDQK
-cS5hPXIKcmV0dXJuIHEuYShhKX0sClFqOmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS55CmlmKCFILkE4KGEp
-KWlmKCEoYT09PXQuXykpcz1hPT09dC5LCmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0dXJuIHN8fGE9PT10
-LmF3fHxyPT09N3x8YT09PXQuUHx8YT09PXQuVH0sCllPOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYo
-YT09bnVsbClyZXR1cm4gSC5RaihzKQpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEscyks
-bnVsbCxzLG51bGwpfSwKQVE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4hMApyZXR1cm4gdGhp
-cy56LmIoYSl9LAp0NDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLHI9cy5yCmlmKGEgaW5zdGFuY2VvZiBQ
-Lk1oKXJldHVybiEhYVtyXQpyZXR1cm4hIUouaWEoYSlbcl19LApPejpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzCmlmKGE9PW51bGwpcmV0dXJuIGEKZWxzZSBpZihzLmIoYSkpcmV0dXJuIGEKSC5tNChhLHMpfSwK
-bDQ6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcwppZihhPT1udWxsKXJldHVybiBhCmVsc2UgaWYocy5iKGEp
-KXJldHVybiBhCkgubTQoYSxzKX0sCm00OmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKEguWmMoSC5XSyhh
-LEguVWUoYSxiKSxILmRtKGIsbnVsbCkpKSl9LApEaDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcz1udWxs
-CmlmKEguV2Uodi50eXBlVW5pdmVyc2UsYSxzLGIscykpcmV0dXJuIGEKdGhyb3cgSC5iKEguWmMoIlRo
-ZSB0eXBlIGFyZ3VtZW50ICciK0guRWooSC5kbShhLHMpKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9mIHRo
-ZSB0eXBlIHZhcmlhYmxlIGJvdW5kICciK0guRWooSC5kbShiLHMpKSsiJyBvZiB0eXBlIHZhcmlhYmxl
-ICciK0guRWooYykrIicgaW4gJyIrSC5FaihkKSsiJy4iKSl9LApXSzpmdW5jdGlvbihhLGIsYyl7dmFy
-IHM9UC5wKGEpLHI9SC5kbShiPT1udWxsP0gueihhKTpiLG51bGwpCnJldHVybiBzKyI6IHR5cGUgJyIr
-SC5FaihyKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9mIHR5cGUgJyIrSC5FaihjKSsiJyJ9LApaYzpmdW5j
-dGlvbihhKXtyZXR1cm4gbmV3IEguaU0oIlR5cGVFcnJvcjogIithKX0sCnE6ZnVuY3Rpb24oYSxiKXty
-ZXR1cm4gbmV3IEguaU0oIlR5cGVFcnJvcjogIitILldLKGEsbnVsbCxiKSl9LAprZTpmdW5jdGlvbihh
-KXtyZXR1cm4gYSE9bnVsbH0sClRpOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKSXc6ZnVuY3Rpb24oYSl7
-cmV0dXJuITB9LApobjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmw6ZnVuY3Rpb24oYSl7cmV0dXJuITA9
-PT1hfHwhMT09PWF9LApwODpmdW5jdGlvbihhKXtpZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJl
-dHVybiExCnRocm93IEguYihILnEoYSwiYm9vbCIpKX0sCnk4OmZ1bmN0aW9uKGEpe2lmKCEwPT09YSly
-ZXR1cm4hMAppZighMT09PWEpcmV0dXJuITEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5x
-KGEsImJvb2wiKSl9LApCUjpmdW5jdGlvbihhKXtpZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJl
-dHVybiExCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJib29sPyIpKX0sCkZHOmZ1
-bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImRv
-dWJsZSIpKX0sCkdIOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihh
-PT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiZG91YmxlIikpfSwKUWs6ZnVuY3Rpb24oYSl7
-aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5i
-KEgucShhLCJkb3VibGU/IikpfSwKb2s6ZnVuY3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVy
-IiYmTWF0aC5mbG9vcihhKT09PWF9LApJWjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIm
-Jk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBhCnRocm93IEguYihILnEoYSwiaW50IikpfSwKdVA6ZnVu
-Y3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQpp
-ZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiaW50IikpfSwKVWM6ZnVuY3Rpb24oYSl7
-aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1udWxs
-KXJldHVybiBhCnRocm93IEguYihILnEoYSwiaW50PyIpKX0sCktIOmZ1bmN0aW9uKGEpe3JldHVybiB0
-eXBlb2YgYT09Im51bWJlciJ9LAp6NTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0
-dXJuIGEKdGhyb3cgSC5iKEgucShhLCJudW0iKSl9LApXMTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09
-Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bSIp
-KX0sCmNVOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxs
-KXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVtPyIpKX0sCk1NOmZ1bmN0aW9uKGEpe3JldHVybiB0
-eXBlb2YgYT09InN0cmluZyJ9LApCdDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0
-dXJuIGEKdGhyb3cgSC5iKEgucShhLCJTdHJpbmciKSl9LApoOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBh
-PT0ic3RyaW5nIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3Ry
-aW5nIikpfSwKazpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09
-bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIlN0cmluZz8iKSl9LAppbzpmdW5jdGlvbihhLGIp
-e3ZhciBzLHIscQpmb3Iocz0iIixyPSIiLHE9MDtxPGEubGVuZ3RoOysrcSxyPSIsICIpcys9Qy54Qi5o
-KHIsSC5kbShhW3FdLGIpKQpyZXR1cm4gc30sCmJJOmZ1bmN0aW9uKGE1LGE2LGE3KXt2YXIgcyxyLHEs
-cCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMyxhND0iLCAiCmlmKGE3IT1u
-dWxsKXtzPWE3Lmxlbmd0aAppZihhNj09bnVsbCl7YTY9SC5WTShbXSx0LnMpCnI9bnVsbH1lbHNlIHI9
-YTYubGVuZ3RoCnE9YTYubGVuZ3RoCmZvcihwPXM7cD4wOy0tcClDLk5tLmkoYTYsIlQiKyhxK3ApKQpm
-b3Iobz10LlMsbj10Ll8sbT10LkssbD0iPCIsaz0iIixwPTA7cDxzOysrcCxrPWE0KXtsKz1rCmo9YTYu
-bGVuZ3RoCmk9ai0xLXAKaWYoaTwwKXJldHVybiBILk9IKGE2LGkpCmw9Qy54Qi5oKGwsYTZbaV0pCmg9
-YTdbcF0KZz1oLnkKaWYoIShnPT09Mnx8Zz09PTN8fGc9PT00fHxnPT09NXx8aD09PW8pKWlmKCEoaD09
-PW4pKWo9aD09PW0KZWxzZSBqPSEwCmVsc2Ugaj0hMAppZighailsKz1DLnhCLmgoIiBleHRlbmRzICIs
-SC5kbShoLGE2KSl9bCs9Ij4ifWVsc2V7bD0iIgpyPW51bGx9bz1hNS56CmY9YTUuUQplPWYuYQpkPWUu
-bGVuZ3RoCmM9Zi5iCmI9Yy5sZW5ndGgKYT1mLmMKYTA9YS5sZW5ndGgKYTE9SC5kbShvLGE2KQpmb3Io
-YTI9IiIsYTM9IiIscD0wO3A8ZDsrK3AsYTM9YTQpYTIrPUMueEIuaChhMyxILmRtKGVbcF0sYTYpKQpp
-ZihiPjApe2EyKz1hMysiWyIKZm9yKGEzPSIiLHA9MDtwPGI7KytwLGEzPWE0KWEyKz1DLnhCLmgoYTMs
-SC5kbShjW3BdLGE2KSkKYTIrPSJdIn1pZihhMD4wKXthMis9YTMrInsiCmZvcihhMz0iIixwPTA7cDxh
-MDtwKz0zLGEzPWE0KXthMis9YTMKaWYoYVtwKzFdKWEyKz0icmVxdWlyZWQgIgphMis9Si5iYihILmRt
-KGFbcCsyXSxhNiksIiAiKSthW3BdfWEyKz0ifSJ9aWYociE9bnVsbCl7YTYudG9TdHJpbmcKYTYubGVu
-Z3RoPXJ9cmV0dXJuIGwrIigiK2EyKyIpID0+ICIrSC5FaihhMSl9LApkbTpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIscSxwLG8sbixtLGw9YS55CmlmKGw9PT01KXJldHVybiJlcmFzZWQiCmlmKGw9PT0yKXJldHVy
-biJkeW5hbWljIgppZihsPT09MylyZXR1cm4idm9pZCIKaWYobD09PTEpcmV0dXJuIk5ldmVyIgppZihs
-PT09NClyZXR1cm4iYW55IgppZihsPT09Nil7cz1ILmRtKGEueixiKQpyZXR1cm4gc31pZihsPT09Nyl7
-cj1hLnoKcz1ILmRtKHIsYikKcT1yLnkKcmV0dXJuIEouYmIocT09PTExfHxxPT09MTI/Qy54Qi5oKCIo
-IixzKSsiKSI6cywiPyIpfWlmKGw9PT04KXJldHVybiJGdXR1cmVPcjwiK0guRWooSC5kbShhLnosYikp
-KyI+IgppZihsPT09OSl7cD1ILm8zKGEueikKbz1hLlEKcmV0dXJuIG8ubGVuZ3RoIT09MD9wKygiPCIr
-SC5pbyhvLGIpKyI+Iik6cH1pZihsPT09MTEpcmV0dXJuIEguYkkoYSxiLG51bGwpCmlmKGw9PT0xMily
-ZXR1cm4gSC5iSShhLnosYixhLlEpCmlmKGw9PT0xMyl7Yi50b1N0cmluZwpuPWEuegptPWIubGVuZ3Ro
-Cm49bS0xLW4KaWYobjwwfHxuPj1tKXJldHVybiBILk9IKGIsbikKcmV0dXJuIGJbbl19cmV0dXJuIj8i
-fSwKbzM6ZnVuY3Rpb24oYSl7dmFyIHMscj1ILkpnKGEpCmlmKHIhPW51bGwpcmV0dXJuIHIKcz0ibWlu
-aWZpZWQ6IithCnJldHVybiBzfSwKUW86ZnVuY3Rpb24oYSxiKXt2YXIgcz1hLnRSW2JdCmZvcig7dHlw
-ZW9mIHM9PSJzdHJpbmciOylzPWEudFJbc10KcmV0dXJuIHN9LAphaTpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIscSxwLG8sbj1hLmVULG09bltiXQppZihtPT1udWxsKXJldHVybiBILkUoYSxiLCExKQplbHNlIGlm
-KHR5cGVvZiBtPT0ibnVtYmVyIil7cz1tCnI9SC5tKGEsNSwiIyIpCnE9W10KZm9yKHA9MDtwPHM7Kytw
-KXEucHVzaChyKQpvPUguSihhLGIscSkKbltiXT1vCnJldHVybiBvfWVsc2UgcmV0dXJuIG19LAp4Yjpm
-dW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEudFIsYil9LApGRjpmdW5jdGlvbihhLGIpe3JldHVybiBI
-Lkl4KGEuZVQsYil9LApFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWEuZUMscT1yLmdldChiKQppZihx
-IT1udWxsKXJldHVybiBxCnM9SC5pKEgubyhhLG51bGwsYixjKSkKci5zZXQoYixzKQpyZXR1cm4gc30s
-CmNFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9Yi5jaAppZihxPT1udWxsKXE9Yi5jaD1uZXcgTWFw
-KCkKcz1xLmdldChjKQppZihzIT1udWxsKXJldHVybiBzCnI9SC5pKEgubyhhLGIsYywhMCkpCnEuc2V0
-KGMscikKcmV0dXJuIHJ9LAp2NTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHA9Yi5jeAppZihwPT1u
-dWxsKXA9Yi5jeD1uZXcgTWFwKCkKcz1jLmN5CnI9cC5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgpx
-PUguYShhLGIsYy55PT09MTA/Yy5ROltjXSkKcC5zZXQocyxxKQpyZXR1cm4gcX0sCkJEOmZ1bmN0aW9u
-KGEsYil7Yi5hPUguQXUKYi5iPUguSkoKcmV0dXJuIGJ9LAptOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
-LHE9YS5lQy5nZXQoYykKaWYocSE9bnVsbClyZXR1cm4gcQpzPW5ldyBILkpjKG51bGwsbnVsbCkKcy55
-PWIKcy5jeT1jCnI9SC5CRChhLHMpCmEuZUMuc2V0KGMscikKcmV0dXJuIHJ9LApDOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgcyxyPWIuY3krIioiLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUgu
-WjcoYSxiLHIsYykKYS5lQy5zZXQocixzKQpyZXR1cm4gc30sClo3OmZ1bmN0aW9uKGEsYixjLGQpe3Zh
-ciBzLHIscQppZihkKXtzPWIueQppZighSC5BOChiKSlyPWI9PT10LlB8fGI9PT10LlR8fHM9PT03fHxz
-PT09NgplbHNlIHI9ITAKaWYocilyZXR1cm4gYn1xPW5ldyBILkpjKG51bGwsbnVsbCkKcS55PTYKcS56
-PWIKcS5jeT1jCnJldHVybiBILkJEKGEscSl9LApCOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWIuY3kr
-Ij8iLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUgubGwoYSxiLHIsYykKYS5lQy5z
-ZXQocixzKQpyZXR1cm4gc30sCmxsOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwCmlmKGQpe3M9
-Yi55CmlmKCFILkE4KGIpKWlmKCEoYj09PXQuUHx8Yj09PXQuVCkpaWYocyE9PTcpcj1zPT09OCYmSC5s
-UihiLnopCmVsc2Ugcj0hMAplbHNlIHI9ITAKZWxzZSByPSEwCmlmKHIpcmV0dXJuIGIKZWxzZSBpZihz
-PT09MXx8Yj09PXQuYXcpcmV0dXJuIHQuUAplbHNlIGlmKHM9PT02KXtxPWIuegppZihxLnk9PT04JiZI
-LmxSKHEueikpcmV0dXJuIHEKZWxzZSByZXR1cm4gSC5jeihhLGIpfX1wPW5ldyBILkpjKG51bGwsbnVs
-bCkKcC55PTcKcC56PWIKcC5jeT1jCnJldHVybiBILkJEKGEscCl9LApmOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgcyxyPWIuY3krIi8iLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUguZVYoYSxi
-LHIsYykKYS5lQy5zZXQocixzKQpyZXR1cm4gc30sCmVWOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIs
-cQppZihkKXtzPWIueQppZighSC5BOChiKSlpZighKGI9PT10Ll8pKXI9Yj09PXQuSwplbHNlIHI9ITAK
-ZWxzZSByPSEwCmlmKHJ8fGI9PT10LkspcmV0dXJuIGIKZWxzZSBpZihzPT09MSlyZXR1cm4gSC5KKGEs
-ImI4IixbYl0pCmVsc2UgaWYoYj09PXQuUHx8Yj09PXQuVClyZXR1cm4gdC5iR31xPW5ldyBILkpjKG51
-bGwsbnVsbCkKcS55PTgKcS56PWIKcS5jeT1jCnJldHVybiBILkJEKGEscSl9LApIOmZ1bmN0aW9uKGEs
-Yil7dmFyIHMscixxPSIiK2IrIl4iLHA9YS5lQy5nZXQocSkKaWYocCE9bnVsbClyZXR1cm4gcApzPW5l
-dyBILkpjKG51bGwsbnVsbCkKcy55PTEzCnMuej1iCnMuY3k9cQpyPUguQkQoYSxzKQphLmVDLnNldChx
-LHIpCnJldHVybiByfSwKVXg6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9YS5sZW5ndGgKZm9yKHM9IiIs
-cj0iIixxPTA7cTxwOysrcSxyPSIsIilzKz1yK2FbcV0uY3kKcmV0dXJuIHN9LApTNDpmdW5jdGlvbihh
-KXt2YXIgcyxyLHEscCxvLG4sbT1hLmxlbmd0aApmb3Iocz0iIixyPSIiLHE9MDtxPG07cSs9MyxyPSIs
-Iil7cD1hW3FdCm89YVtxKzFdPyIhIjoiOiIKbj1hW3ErMl0uY3kKcys9citwK28rbn1yZXR1cm4gc30s
-Cko6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwPWIKaWYoYy5sZW5ndGghPT0wKXArPSI8IitILlV4
-KGMpKyI+IgpzPWEuZUMuZ2V0KHApCmlmKHMhPW51bGwpcmV0dXJuIHMKcj1uZXcgSC5KYyhudWxsLG51
-bGwpCnIueT05CnIuej1iCnIuUT1jCmlmKGMubGVuZ3RoPjApci5jPWNbMF0Kci5jeT1wCnE9SC5CRChh
-LHIpCmEuZUMuc2V0KHAscSkKcmV0dXJuIHF9LAphOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxv
-LG4KaWYoYi55PT09MTApe3M9Yi56CnI9Yi5RLmNvbmNhdChjKX1lbHNle3I9YwpzPWJ9cT1zLmN5Kygi
-OzwiK0guVXgocikrIj4iKQpwPWEuZUMuZ2V0KHEpCmlmKHAhPW51bGwpcmV0dXJuIHAKbz1uZXcgSC5K
-YyhudWxsLG51bGwpCm8ueT0xMApvLno9cwpvLlE9cgpvLmN5PXEKbj1ILkJEKGEsbykKYS5lQy5zZXQo
-cSxuKQpyZXR1cm4gbn0sCmQ6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbj1iLmN5LG09Yy5h
-LGw9bS5sZW5ndGgsaz1jLmIsaj1rLmxlbmd0aCxpPWMuYyxoPWkubGVuZ3RoLGc9IigiK0guVXgobSkK
-aWYoaj4wKXtzPWw+MD8iLCI6IiIKcj1ILlV4KGspCmcrPXMrIlsiK3IrIl0ifWlmKGg+MCl7cz1sPjA/
-IiwiOiIiCnI9SC5TNChpKQpnKz1zKyJ7IityKyJ9In1xPW4rKGcrIikiKQpwPWEuZUMuZ2V0KHEpCmlm
-KHAhPW51bGwpcmV0dXJuIHAKbz1uZXcgSC5KYyhudWxsLG51bGwpCm8ueT0xMQpvLno9YgpvLlE9Ywpv
-LmN5PXEKcj1ILkJEKGEsbykKYS5lQy5zZXQocSxyKQpyZXR1cm4gcn0sCkQ6ZnVuY3Rpb24oYSxiLGMs
-ZCl7dmFyIHMscj1iLmN5KygiPCIrSC5VeChjKSsiPiIpLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbCly
-ZXR1cm4gcQpzPUguaHcoYSxiLGMscixkKQphLmVDLnNldChyLHMpCnJldHVybiBzfSwKaHc6ZnVuY3Rp
-b24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG4sbSxsCmlmKGUpe3M9Yy5sZW5ndGgKcj1uZXcgQXJy
-YXkocykKZm9yKHE9MCxwPTA7cDxzOysrcCl7bz1jW3BdCmlmKG8ueT09PTEpe3JbcF09bzsrK3F9fWlm
-KHE+MCl7bj1ILlBMKGEsYixyLDApCm09SC5iWihhLGMsciwwKQpyZXR1cm4gSC5EKGEsbixtLGMhPT1t
-KX19bD1uZXcgSC5KYyhudWxsLG51bGwpCmwueT0xMgpsLno9YgpsLlE9YwpsLmN5PWQKcmV0dXJuIEgu
-QkQoYSxsKX0sCm86ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJue3U6YSxlOmIscjpjLHM6W10scDowLG46
-ZH19LAppOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnPWEucixmPWEucwpm
-b3Iocz1nLmxlbmd0aCxyPTA7cjxzOyl7cT1nLmNoYXJDb2RlQXQocikKaWYocT49NDgmJnE8PTU3KXI9
-SC5BKHIrMSxxLGcsZikKZWxzZSBpZigoKChxfDMyKT4+PjApLTk3JjY1NTM1KTwyNnx8cT09PTk1fHxx
-PT09MzYpcj1ILnQoYSxyLGcsZiwhMSkKZWxzZSBpZihxPT09NDYpcj1ILnQoYSxyLGcsZiwhMCkKZWxz
-ZXsrK3IKc3dpdGNoKHEpe2Nhc2UgNDQ6YnJlYWsKY2FzZSA1ODpmLnB1c2goITEpCmJyZWFrCmNhc2Ug
-MzM6Zi5wdXNoKCEwKQpicmVhawpjYXNlIDU5OmYucHVzaChILksoYS51LGEuZSxmLnBvcCgpKSkKYnJl
-YWsKY2FzZSA5NDpmLnB1c2goSC5IKGEudSxmLnBvcCgpKSkKYnJlYWsKY2FzZSAzNTpmLnB1c2goSC5t
-KGEudSw1LCIjIikpCmJyZWFrCmNhc2UgNjQ6Zi5wdXNoKEgubShhLnUsMiwiQCIpKQpicmVhawpjYXNl
-IDEyNjpmLnB1c2goSC5tKGEudSwzLCJ+IikpCmJyZWFrCmNhc2UgNjA6Zi5wdXNoKGEucCkKYS5wPWYu
-bGVuZ3RoCmJyZWFrCmNhc2UgNjI6cD1hLnUKbz1mLnNwbGljZShhLnApCkgucihhLnUsYS5lLG8pCmEu
-cD1mLnBvcCgpCm49Zi5wb3AoKQppZih0eXBlb2Ygbj09InN0cmluZyIpZi5wdXNoKEguSihwLG4sbykp
-CmVsc2V7bT1ILksocCxhLmUsbikKc3dpdGNoKG0ueSl7Y2FzZSAxMTpmLnB1c2goSC5EKHAsbSxvLGEu
-bikpCmJyZWFrCmRlZmF1bHQ6Zi5wdXNoKEguYShwLG0sbykpCmJyZWFrfX1icmVhawpjYXNlIDM4Okgu
-SShhLGYpCmJyZWFrCmNhc2UgNDI6bD1hLnUKZi5wdXNoKEguQyhsLEguSyhsLGEuZSxmLnBvcCgpKSxh
-Lm4pKQpicmVhawpjYXNlIDYzOmw9YS51CmYucHVzaChILkIobCxILksobCxhLmUsZi5wb3AoKSksYS5u
-KSkKYnJlYWsKY2FzZSA0NzpsPWEudQpmLnB1c2goSC5mKGwsSC5LKGwsYS5lLGYucG9wKCkpLGEubikp
-CmJyZWFrCmNhc2UgNDA6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgNDE6cD1hLnUK
-az1uZXcgSC5HKCkKaj1wLnNFQQppPXAuc0VBCm49Zi5wb3AoKQppZih0eXBlb2Ygbj09Im51bWJlciIp
-c3dpdGNoKG4pe2Nhc2UtMTpqPWYucG9wKCkKYnJlYWsKY2FzZS0yOmk9Zi5wb3AoKQpicmVhawpkZWZh
-dWx0OmYucHVzaChuKQpicmVha31lbHNlIGYucHVzaChuKQpvPWYuc3BsaWNlKGEucCkKSC5yKGEudSxh
-LmUsbykKYS5wPWYucG9wKCkKay5hPW8Kay5iPWoKay5jPWkKZi5wdXNoKEguZChwLEguSyhwLGEuZSxm
-LnBvcCgpKSxrKSkKYnJlYWsKY2FzZSA5MTpmLnB1c2goYS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2Fz
-ZSA5MzpvPWYuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUsbykKYS5wPWYucG9wKCkKZi5wdXNoKG8pCmYu
-cHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2Ug
-MTI1Om89Zi5zcGxpY2UoYS5wKQpILnkoYS51LGEuZSxvKQphLnA9Zi5wb3AoKQpmLnB1c2gobykKZi5w
-dXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJhZCBjaGFyYWN0ZXIgIitxfX19aD1mLnBvcCgpCnJl
-dHVybiBILksoYS51LGEuZSxoKX0sCkE6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxPWItNDgKZm9y
-KHM9Yy5sZW5ndGg7YTxzOysrYSl7cj1jLmNoYXJDb2RlQXQoYSkKaWYoIShyPj00OCYmcjw9NTcpKWJy
-ZWFrCnE9cSoxMCsoci00OCl9ZC5wdXNoKHEpCnJldHVybiBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUp
-e3ZhciBzLHIscSxwLG8sbixtPWIrMQpmb3Iocz1jLmxlbmd0aDttPHM7KyttKXtyPWMuY2hhckNvZGVB
-dChtKQppZihyPT09NDYpe2lmKGUpYnJlYWsKZT0hMH1lbHNle2lmKCEoKCgocnwzMik+Pj4wKS05NyY2
-NTUzNSk8MjZ8fHI9PT05NXx8cj09PTM2KSlxPXI+PTQ4JiZyPD01NwplbHNlIHE9ITAKaWYoIXEpYnJl
-YWt9fXA9Yy5zdWJzdHJpbmcoYixtKQppZihlKXtzPWEudQpvPWEuZQppZihvLnk9PT0xMClvPW8uegpu
-PUguUW8ocyxvLnopW3BdCmlmKG49PW51bGwpSC52aCgnTm8gIicrcCsnIiBpbiAiJytILm1EKG8pKyci
-JykKZC5wdXNoKEguY0UocyxvLG4pKX1lbHNlIGQucHVzaChwKQpyZXR1cm4gbX0sCkk6ZnVuY3Rpb24o
-YSxiKXt2YXIgcz1iLnBvcCgpCmlmKDA9PT1zKXtiLnB1c2goSC5tKGEudSwxLCIwJiIpKQpyZXR1cm59
-aWYoMT09PXMpe2IucHVzaChILm0oYS51LDQsIjEmIikpCnJldHVybn10aHJvdyBILmIoUC5oVigiVW5l
-eHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILkVqKHMpKSl9LApLOmZ1bmN0aW9uKGEsYixjKXtp
-Zih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguSihhLGMsYS5zRUEpCmVsc2UgaWYodHlwZW9mIGM9
-PSJudW1iZXIiKXJldHVybiBILlRWKGEsYixjKQplbHNlIHJldHVybiBjfSwKcjpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0wO3M8cjsrK3MpY1tzXT1ILksoYSxiLGNbc10pfSwKeTpm
-dW5jdGlvbihhLGIsYyl7dmFyIHMscj1jLmxlbmd0aApmb3Iocz0yO3M8cjtzKz0zKWNbc109SC5LKGEs
-YixjW3NdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9Yi55CmlmKHE9PT0xMCl7aWYoYz09
-PTApcmV0dXJuIGIuegpzPWIuUQpyPXMubGVuZ3RoCmlmKGM8PXIpcmV0dXJuIHNbYy0xXQpjLT1yCmI9
-Yi56CnE9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIKaWYocSE9PTkpdGhyb3cgSC5iKFAuaFYoIklu
-ZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0eXBlIikpCnM9Yi5RCmlmKGM8PXMubGVuZ3Ro
-KXJldHVybiBzW2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJhZCBpbmRleCAiK2MrIiBmb3IgIitiLncoMCkp
-KX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGoKaWYoYj09PWQp
-cmV0dXJuITAKaWYoIUguQTgoZCkpaWYoIShkPT09dC5fKSlzPWQ9PT10LksKZWxzZSBzPSEwCmVsc2Ug
-cz0hMAppZihzKXJldHVybiEwCnI9Yi55CmlmKHI9PT00KXJldHVybiEwCmlmKEguQTgoYikpcmV0dXJu
-ITEKaWYoYi55IT09MSlzPWI9PT10LlB8fGI9PT10LlQKZWxzZSBzPSEwCmlmKHMpcmV0dXJuITAKcT1y
-PT09MTMKaWYocSlpZihILldlKGEsY1tiLnpdLGMsZCxlKSlyZXR1cm4hMApwPWQueQppZihyPT09Nily
-ZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocD09PTYpe3M9ZC56CnJldHVybiBILldlKGEsYixjLHMs
-ZSl9aWYocj09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSlyZXR1cm4hMQpyZXR1cm4gSC5XZShhLEgu
-eFooYSxiKSxjLGQsZSl9aWYocj09PTcpe3M9SC5XZShhLGIueixjLGQsZSkKcmV0dXJuIHN9aWYocD09
-PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJldHVybiBILldlKGEsYixjLEgueFooYSxk
-KSxlKX1pZihwPT09Nyl7cz1ILldlKGEsYixjLGQueixlKQpyZXR1cm4gc31pZihxKXJldHVybiExCnM9
-ciE9PTExCmlmKCghc3x8cj09PTEyKSYmZD09PXQuWSlyZXR1cm4hMAppZihwPT09MTIpe2lmKGI9PT10
-LngpcmV0dXJuITAKaWYociE9PTEyKXJldHVybiExCm89Yi5RCm49ZC5RCm09by5sZW5ndGgKaWYobSE9
-PW4ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9vOm8uY29uY2F0KGMpCmU9ZT09bnVsbD9uOm4uY29u
-Y2F0KGUpCmZvcihsPTA7bDxtOysrbCl7az1vW2xdCmo9bltsXQppZighSC5XZShhLGssYyxqLGUpfHwh
-SC5XZShhLGosZSxrLGMpKXJldHVybiExfXJldHVybiBILmJPKGEsYi56LGMsZC56LGUpfWlmKHA9PT0x
-MSl7aWYoYj09PXQueClyZXR1cm4hMAppZihzKXJldHVybiExCnJldHVybiBILmJPKGEsYixjLGQsZSl9
-aWYocj09PTkpe2lmKHAhPT05KXJldHVybiExCnJldHVybiBILnBHKGEsYixjLGQsZSl9cmV0dXJuITF9
-LApiTzpmdW5jdGlvbihhMixhMyxhNCxhNSxhNil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcs
-ZixlLGQsYyxiLGEsYTAsYTEKaWYoIUguV2UoYTIsYTMueixhNCxhNS56LGE2KSlyZXR1cm4hMQpzPWEz
-LlEKcj1hNS5RCnE9cy5hCnA9ci5hCm89cS5sZW5ndGgKbj1wLmxlbmd0aAppZihvPm4pcmV0dXJuITEK
-bT1uLW8KbD1zLmIKaz1yLmIKaj1sLmxlbmd0aAppPWsubGVuZ3RoCmlmKG8rajxuK2kpcmV0dXJuITEK
-Zm9yKGg9MDtoPG87KytoKXtnPXFbaF0KaWYoIUguV2UoYTIscFtoXSxhNixnLGE0KSlyZXR1cm4hMX1m
-b3IoaD0wO2g8bTsrK2gpe2c9bFtoXQppZighSC5XZShhMixwW28raF0sYTYsZyxhNCkpcmV0dXJuITF9
-Zm9yKGg9MDtoPGk7KytoKXtnPWxbbStoXQppZighSC5XZShhMixrW2hdLGE2LGcsYTQpKXJldHVybiEx
-fWY9cy5jCmU9ci5jCmQ9Zi5sZW5ndGgKYz1lLmxlbmd0aApmb3IoYj0wLGE9MDthPGM7YSs9Myl7YTA9
-ZVthXQpmb3IoOyEwOyl7aWYoYj49ZClyZXR1cm4hMQphMT1mW2JdCmIrPTMKaWYoYTA8YTEpcmV0dXJu
-ITEKaWYoYTE8YTApY29udGludWUKZz1mW2ItMV0KaWYoIUguV2UoYTIsZVthKzJdLGE2LGcsYTQpKXJl
-dHVybiExCmJyZWFrfX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAs
-byxuLG0sbCxrPWIueixqPWQuegppZihrPT09ail7cz1iLlEKcj1kLlEKcT1zLmxlbmd0aApmb3IocD0w
-O3A8cTsrK3Ape289c1twXQpuPXJbcF0KaWYoIUguV2UoYSxvLGMsbixlKSlyZXR1cm4hMX1yZXR1cm4h
-MH1pZihkPT09dC5LKXJldHVybiEwCm09SC5RbyhhLGspCmlmKG09PW51bGwpcmV0dXJuITEKbD1tW2pd
-CmlmKGw9PW51bGwpcmV0dXJuITEKcT1sLmxlbmd0aApyPWQuUQpmb3IocD0wO3A8cTsrK3ApaWYoIUgu
-V2UoYSxILmNFKGEsYixsW3BdKSxjLHJbcF0sZSkpcmV0dXJuITEKcmV0dXJuITB9LApsUjpmdW5jdGlv
-bihhKXt2YXIgcyxyPWEueQppZighKGE9PT10LlB8fGE9PT10LlQpKWlmKCFILkE4KGEpKWlmKHIhPT03
-KWlmKCEocj09PTYmJkgubFIoYS56KSkpcz1yPT09OCYmSC5sUihhLnopCmVsc2Ugcz0hMAplbHNlIHM9
-ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMApyZXR1cm4gc30sCmNjOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKCFI
-LkE4KGEpKWlmKCEoYT09PXQuXykpcz1hPT09dC5LCmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0dXJuIHN9
-LApBODpmdW5jdGlvbihhKXt2YXIgcz1hLnkKcmV0dXJuIHM9PT0yfHxzPT09M3x8cz09PTR8fHM9PT01
-fHxhPT09dC5TfSwKSXg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9T2JqZWN0LmtleXMoYikscD1xLmxl
-bmd0aApmb3Iocz0wO3M8cDsrK3Mpe3I9cVtzXQphW3JdPWJbcl19fSwKSmM6ZnVuY3Rpb24gSmMoYSxi
-KXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8ueD1fLnI9Xy5jPW51bGwKXy55PTAKXy5jeT1fLmN4PV8u
-Y2g9Xy5RPV8uej1udWxsfSwKRzpmdW5jdGlvbiBHKCl7dGhpcy5jPXRoaXMuYj10aGlzLmE9bnVsbH0s
-CnU5OmZ1bmN0aW9uIHU5KCl7fSwKaU06ZnVuY3Rpb24gaU0oYSl7dGhpcy5hPWF9LApSOTpmdW5jdGlv
-bihhKXtyZXR1cm4gdC53LmIoYSl8fHQuQi5iKGEpfHx0LmR6LmIoYSl8fHQuSS5iKGEpfHx0LkEuYihh
-KXx8dC5nNC5iKGEpfHx0LmcyLmIoYSl9LApKZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5tYW5nbGVkR2xv
-YmFsTmFtZXNbYV19fSxKPXsKUXU6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJue2k6YSxwOmIsZTpjLHg6
-ZH19LAprczpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0K
-aWYobz09bnVsbClpZigkLkJ2PT1udWxsKXtILlhEKCkKbz1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVd
-fWlmKG8hPW51bGwpe3M9by5wCmlmKCExPT09cylyZXR1cm4gby5pCmlmKCEwPT09cylyZXR1cm4gYQpy
-PU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQppZihzPT09cilyZXR1cm4gby5pCmlmKG8uZT09PXIpdGhy
-b3cgSC5iKFAuU1koIlJldHVybiBpbnRlcmNlcHRvciBmb3IgIitILkVqKHMoYSxvKSkpKX1xPWEuY29u
-c3RydWN0b3IKcD1xPT1udWxsP251bGw6cVtKLlJQKCldCmlmKHAhPW51bGwpcmV0dXJuIHAKcD1ILncz
-KGEpCmlmKHAhPW51bGwpcmV0dXJuIHAKaWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEMuREcK
-cz1PYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkKaWYocz09bnVsbClyZXR1cm4gQy5aUQppZihzPT09T2Jq
-ZWN0LnByb3RvdHlwZSlyZXR1cm4gQy5aUQppZih0eXBlb2YgcT09ImZ1bmN0aW9uIil7T2JqZWN0LmRl
-ZmluZVByb3BlcnR5KHEsSi5SUCgpLHt2YWx1ZTpDLnZCLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6
-dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBDLnZCfXJldHVybiBDLnZCfSwKUlA6ZnVuY3Rp
-b24oKXt2YXIgcz0kLnptCnJldHVybiBzPT1udWxsPyQuem09di5nZXRJc29sYXRlVGFnKCJfJGRhcnRf
-anMiKTpzfSwKUWk6ZnVuY3Rpb24oYSxiKXtpZihhPDB8fGE+NDI5NDk2NzI5NSl0aHJvdyBILmIoUC5U
-RShhLDAsNDI5NDk2NzI5NSwibGVuZ3RoIixudWxsKSkKcmV0dXJuIEoucHkobmV3IEFycmF5KGEpLGIp
-fSwKS2g6ZnVuY3Rpb24oYSxiKXtpZihhPDApdGhyb3cgSC5iKFAueFkoIkxlbmd0aCBtdXN0IGJlIGEg
-bm9uLW5lZ2F0aXZlIGludGVnZXI6ICIrYSkpCnJldHVybiBILlZNKG5ldyBBcnJheShhKSxiLkMoImpk
-PDA+IikpfSwKcHk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5FcChILlZNKGEsYi5DKCJqZDwwPiIpKSxi
-KX0sCkVwOmZ1bmN0aW9uKGEsYil7YS5maXhlZCRsZW5ndGg9QXJyYXkKcmV0dXJuIGF9LAp6QzpmdW5j
-dGlvbihhKXthLmZpeGVkJGxlbmd0aD1BcnJheQphLmltbXV0YWJsZSRsaXN0PUFycmF5CnJldHVybiBh
-fSwKR2E6ZnVuY3Rpb24oYSl7aWYoYTwyNTYpc3dpdGNoKGEpe2Nhc2UgOTpjYXNlIDEwOmNhc2UgMTE6
-Y2FzZSAxMjpjYXNlIDEzOmNhc2UgMzI6Y2FzZSAxMzM6Y2FzZSAxNjA6cmV0dXJuITAKZGVmYXVsdDpy
-ZXR1cm4hMX1zd2l0Y2goYSl7Y2FzZSA1NzYwOmNhc2UgODE5MjpjYXNlIDgxOTM6Y2FzZSA4MTk0OmNh
-c2UgODE5NTpjYXNlIDgxOTY6Y2FzZSA4MTk3OmNhc2UgODE5ODpjYXNlIDgxOTk6Y2FzZSA4MjAwOmNh
-c2UgODIwMTpjYXNlIDgyMDI6Y2FzZSA4MjMyOmNhc2UgODIzMzpjYXNlIDgyMzk6Y2FzZSA4Mjg3OmNh
-c2UgMTIyODg6Y2FzZSA2NTI3OTpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfX0sCm1tOmZ1bmN0aW9u
-KGEsYil7dmFyIHMscgpmb3Iocz1hLmxlbmd0aDtiPHM7KXtyPUMueEIuVyhhLGIpCmlmKHIhPT0zMiYm
-ciE9PTEzJiYhSi5HYShyKSlicmVhazsrK2J9cmV0dXJuIGJ9LApjMTpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIKZm9yKDtiPjA7Yj1zKXtzPWItMQpyPUMueEIubShhLHMpCmlmKHIhPT0zMiYmciE9PTEzJiYhSi5H
-YShyKSlicmVha31yZXR1cm4gYn0sClRKOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIily
-ZXR1cm4gSi5xSS5wcm90b3R5cGUKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3Rv
-dHlwZQppZihhPT1udWxsKXJldHVybiBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpk
-LnByb3RvdHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJl
-dHVybiBKLmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpy
-ZXR1cm4gSi5rcyhhKX0sClU2OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4g
-Si5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSly
-ZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1
-bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgp
-cmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApZRTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBh
-CmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUu
-cHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBKLmtz
-KGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRoLmZsb29yKGEp
-PT1hKXJldHVybiBKLmJVLnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYodHlwZW9mIGE9
-PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBKLndlLnByb3Rv
-dHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQppZihhLmNvbnN0
-cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtp
-Zih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBp
-bnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtpZih0
-eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEK
-aWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVybiBhfSwKdzE6
-ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1
-cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0
-aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0
-dXJuIGEKcmV0dXJuIEoua3MoYSl9LApDTTpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5ZRShhKS5k
-dShhLGIsYyxkKX0sCkVoOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5ZRShhKS5tSyhhLGIsYyl9LApG
-TDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBKLncxKGEpLkUoYSxiKX0sCkdyOmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEpLmdtVyhhKX0s
-CkhtOmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2KGEpLmdBKGEpfSwKSVQ6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEoudzEoYSkuZ2t6KGEpfSwKSnk6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5pYShhKS5lNyhhLGIpfSwK
-S1Y6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShhKS5HKGEsYil9LApMdDpmdW5jdGlvbihhKXtyZXR1
-cm4gSi5ZRShhKS53ZyhhKX0sCk0xOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi53MShhKS5FMihhLGIs
-Yyl9LApNdTpmdW5jdGlvbihhLGIpe3JldHVybiBKLllFKGEpLnNEKGEsYil9LApRejpmdW5jdGlvbihh
-LGIpe3JldHVybiBKLnJZKGEpLlcoYSxiKX0sClJNOmZ1bmN0aW9uKGEsYil7aWYoYT09bnVsbClyZXR1
-cm4gYj09bnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGIhPW51bGwmJmE9PT1iCnJldHVy
-biBKLmlhKGEpLkROKGEsYil9LApUMDpmdW5jdGlvbihhKXtyZXR1cm4gSi5yWShhKS5iUyhhKX0sCmE2
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkubShhLGIpfSwKYlQ6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEouWUUoYSkuRDQoYSl9LApiYjpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmdHlw
-ZW9mIGI9PSJudW1iZXIiKXJldHVybiBhK2IKcmV0dXJuIEouVEooYSkuaChhLGIpfSwKY0g6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEouclkoYSkuaGMoYSl9LApkUjpmdW5jdGlvbihhKXtyZXR1cm4gSi5ZRShhKS5n
-RChhKX0sCmRaOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLllFKGEpLk9uKGEsYixjLGQpfSwKZGc6
-ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouclkoYSkuaTcoYSxiLGMsZCl9LApkaDpmdW5jdGlvbihh
-KXtyZXR1cm4gSi5ZRShhKS5GRihhKX0sCmRyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouWUUoYSkuc2E0
-KGEsYil9LApoZjpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5naU8oYSl9LAppZzpmdW5jdGlvbihh
-KXtyZXR1cm4gSi5ZRShhKS5nUWcoYSl9LApqOmZ1bmN0aW9uKGEpe3JldHVybiBKLmlhKGEpLncoYSl9
-LApsNTpmdW5jdGlvbihhLGIpe3JldHVybiBKLllFKGEpLnNoZihhLGIpfSwKbGQ6ZnVuY3Rpb24oYSxi
-LGMpe3JldHVybiBKLnJZKGEpLk5qKGEsYixjKX0sCnA0OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclko
-YSkuVGMoYSxiKX0sCnEwOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5yWShhKS5RaShhLGIsYyl9LApx
-RjpmdW5jdGlvbihhKXtyZXR1cm4gSi5ZRShhKS5nVmwoYSl9LAp0SDpmdW5jdGlvbihhLGIsYyl7cmV0
-dXJuIEouWUUoYSkucGsoYSxiLGMpfSwKdVU6ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYoYSkuZ2wwKGEp
-fSwKd2Y6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zUk4oYSxiKX0sCng5OmZ1bmN0aW9uKGEs
-Yil7aWYodHlwZW9mIGI9PT0ibnVtYmVyIilpZihhLmNvbnN0cnVjdG9yPT1BcnJheXx8dHlwZW9mIGE9
-PSJzdHJpbmcifHxILndWKGEsYVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXSkpaWYoYj4+PjA9PT1iJiZi
-PGEubGVuZ3RoKXJldHVybiBhW2JdCnJldHVybiBKLlU2KGEpLnEoYSxiKX0sCnpsOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIEouVTYoYSkudGcoYSxiKX0sCnZCOmZ1bmN0aW9uIHZCKCl7fSwKeUU6ZnVuY3Rpb24g
-eUUoKXt9LAp3ZTpmdW5jdGlvbiB3ZSgpe30sCk1GOmZ1bmN0aW9uIE1GKCl7fSwKaUM6ZnVuY3Rpb24g
-aUMoKXt9LAprZDpmdW5jdGlvbiBrZCgpe30sCmM1OmZ1bmN0aW9uIGM1KCl7fSwKamQ6ZnVuY3Rpb24g
-amQoYSl7dGhpcy4kdGk9YX0sClBvOmZ1bmN0aW9uIFBvKGEpe3RoaXMuJHRpPWF9LAptMTpmdW5jdGlv
-biBtMShhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwK
-cUk6ZnVuY3Rpb24gcUkoKXt9LApiVTpmdW5jdGlvbiBiVSgpe30sClZBOmZ1bmN0aW9uIFZBKCl7fSwK
-RHI6ZnVuY3Rpb24gRHIoKXt9fSxQPXsKT2o6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9e30KaWYoc2VsZi5z
-Y2hlZHVsZUltbWVkaWF0ZSE9bnVsbClyZXR1cm4gUC5FWCgpCmlmKHNlbGYuTXV0YXRpb25PYnNlcnZl
-ciE9bnVsbCYmc2VsZi5kb2N1bWVudCE9bnVsbCl7cz1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQo
-ImRpdiIpCnI9c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzcGFuIikKcS5hPW51bGwKbmV3IHNl
-bGYuTXV0YXRpb25PYnNlcnZlcihILnRSKG5ldyBQLnRoKHEpLDEpKS5vYnNlcnZlKHMse2NoaWxkTGlz
-dDp0cnVlfSkKcmV0dXJuIG5ldyBQLmhhKHEscyxyKX1lbHNlIGlmKHNlbGYuc2V0SW1tZWRpYXRlIT1u
-dWxsKXJldHVybiBQLnl0KCkKcmV0dXJuIFAucVcoKX0sClpWOmZ1bmN0aW9uKGEpe3NlbGYuc2NoZWR1
-bGVJbW1lZGlhdGUoSC50UihuZXcgUC5Wcyh0Lk0uYShhKSksMCkpfSwKb0E6ZnVuY3Rpb24oYSl7c2Vs
-Zi5zZXRJbW1lZGlhdGUoSC50UihuZXcgUC5GdCh0Lk0uYShhKSksMCkpfSwKQno6ZnVuY3Rpb24oYSl7
-dC5NLmEoYSkKUC5RTigwLGEpfSwKUU46ZnVuY3Rpb24oYSxiKXt2YXIgcz1uZXcgUC5XMygpCnMuQ1ko
-YSxiKQpyZXR1cm4gc30sCkZYOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5paChuZXcgUC52cygkLlgz
-LGEuQygidnM8MD4iKSksYS5DKCJpaDwwPiIpKX0sCkRJOmZ1bmN0aW9uKGEsYil7YS4kMigwLG51bGwp
-CmIuYj0hMApyZXR1cm4gYi5hfSwKalE6ZnVuY3Rpb24oYSxiKXtQLkplKGEsYil9LAp5QzpmdW5jdGlv
-bihhLGIpe2IuYU0oMCxhKX0sCmYzOmZ1bmN0aW9uKGEsYil7Yi53MChILlJ1KGEpLEgudHMoYSkpfSwK
-SmU6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9bmV3IFAuV00oYikscD1uZXcgUC5TWChiKQppZihhIGlu
-c3RhbmNlb2YgUC52cylhLlFkKHEscCx0LnopCmVsc2V7cz10LnoKaWYodC5kLmIoYSkpYS5TcShxLHAs
-cykKZWxzZXtyPW5ldyBQLnZzKCQuWDMsdC5jKQpyLmE9NApyLmM9YQpyLlFkKHEscCxzKX19fSwKbHo6
-ZnVuY3Rpb24oYSl7dmFyIHM9ZnVuY3Rpb24oYixjKXtyZXR1cm4gZnVuY3Rpb24oZCxlKXt3aGlsZSh0
-cnVlKXRyeXtiKGQsZSkKYnJlYWt9Y2F0Y2gocil7ZT1yCmQ9Y319fShhLDEpCnJldHVybiAkLlgzLkxq
-KG5ldyBQLkdzKHMpLHQuSCx0LnAsdC56KX0sCkdROmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5GeShh
-LDEpfSwKVGg6ZnVuY3Rpb24oKXtyZXR1cm4gQy53UX0sClltOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcg
-UC5GeShhLDMpfSwKbDA6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAucTQoYSxiLkMoInE0PDA+Iikp
-fSwKazM6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKYi5hPTEKdHJ5e2EuU3EobmV3IFAucFYoYiksbmV3
-IFAuVTcoYiksdC5QKX1jYXRjaChxKXtzPUguUnUocSkKcj1ILnRzKHEpClAucmIobmV3IFAudnIoYixz
-LHIpKX19LApBOTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQpmb3Iocz10LmM7cj1hLmEscj09PTI7KWE9
-cy5hKGEuYykKaWYocj49NCl7cT1iLmFoKCkKYi5hPWEuYQpiLmM9YS5jClAuSFooYixxKX1lbHNle3E9
-dC5GLmEoYi5jKQpiLmE9MgpiLmM9YQphLmpRKHEpfX0sCkhaOmZ1bmN0aW9uKGEwLGExKXt2YXIgcyxy
-LHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjPW51bGwsYj17fSxhPWIuYT1hMApmb3Iocz10Lm4s
-cj10LkYscT10LmQ7ITA7KXtwPXt9Cm89YS5hPT09OAppZihhMT09bnVsbCl7aWYobyl7bj1zLmEoYS5j
-KQpQLkwyKGMsYyxhLmIsbi5hLG4uYil9cmV0dXJufXAuYT1hMQptPWExLmEKZm9yKGE9YTE7bSE9bnVs
-bDthPW0sbT1sKXthLmE9bnVsbApQLkhaKGIuYSxhKQpwLmE9bQpsPW0uYX1rPWIuYQpqPWsuYwpwLmI9
-bwpwLmM9agppPSFvCmlmKGkpe2g9YS5jCmg9KGgmMSkhPT0wfHwoaCYxNSk9PT04fWVsc2UgaD0hMApp
-ZihoKXtnPWEuYi5iCmlmKG8pe2g9ay5iPT09ZwpoPSEoaHx8aCl9ZWxzZSBoPSExCmlmKGgpe3MuYShq
-KQpQLkwyKGMsYyxrLmIsai5hLGouYikKcmV0dXJufWY9JC5YMwppZihmIT09ZykkLlgzPWcKZWxzZSBm
-PWMKYT1hLmMKaWYoKGEmMTUpPT09OCluZXcgUC5SVChwLGIsbykuJDAoKQplbHNlIGlmKGkpe2lmKChh
-JjEpIT09MCluZXcgUC5ycShwLGopLiQwKCl9ZWxzZSBpZigoYSYyKSE9PTApbmV3IFAuUlcoYixwKS4k
-MCgpCmlmKGYhPW51bGwpJC5YMz1mCmE9cC5jCmlmKHEuYihhKSl7ZT1wLmEuYgppZihhLmE+PTQpe2Q9
-ci5hKGUuYykKZS5jPW51bGwKYTE9ZS5OOChkKQplLmE9YS5hCmUuYz1hLmMKYi5hPWEKY29udGludWV9
-ZWxzZSBQLkE5KGEsZSkKcmV0dXJufX1lPXAuYS5iCmQ9ci5hKGUuYykKZS5jPW51bGwKYTE9ZS5OOChk
-KQphPXAuYgprPXAuYwppZighYSl7ZS4kdGkuYy5hKGspCmUuYT00CmUuYz1rfWVsc2V7cy5hKGspCmUu
-YT04CmUuYz1rfWIuYT1lCmE9ZX19LApWSDpmdW5jdGlvbihhLGIpe3ZhciBzCmlmKHQuYWcuYihhKSly
-ZXR1cm4gYi5MaihhLHQueix0LkssdC5sKQpzPXQuYkkKaWYocy5iKGEpKXJldHVybiBzLmEoYSkKdGhy
-b3cgSC5iKFAuTDMoYSwib25FcnJvciIsIkVycm9yIGhhbmRsZXIgbXVzdCBhY2NlcHQgb25lIE9iamVj
-dCBvciBvbmUgT2JqZWN0IGFuZCBhIFN0YWNrVHJhY2UgYXMgYXJndW1lbnRzLCBhbmQgcmV0dXJuIGEg
-YSB2YWxpZCByZXN1bHQiKSl9LApwdTpmdW5jdGlvbigpe3ZhciBzLHIKZm9yKHM9JC5TNjtzIT1udWxs
-O3M9JC5TNil7JC5tZz1udWxsCnI9cy5iCiQuUzY9cgppZihyPT1udWxsKSQuazg9bnVsbApzLmEuJDAo
-KX19LAplTjpmdW5jdGlvbigpeyQuVUQ9ITAKdHJ5e1AucHUoKX1maW5hbGx5eyQubWc9bnVsbAokLlVE
-PSExCmlmKCQuUzYhPW51bGwpJC51dCgpLiQxKFAuVjkoKSl9fSwKZVc6ZnVuY3Rpb24oYSl7dmFyIHM9
-bmV3IFAuT00oYSkscj0kLms4CmlmKHI9PW51bGwpeyQuUzY9JC5rOD1zCmlmKCEkLlVEKSQudXQoKS4k
-MShQLlY5KCkpfWVsc2UgJC5rOD1yLmI9c30sCnJSOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPSQuUzYK
-aWYocD09bnVsbCl7UC5lVyhhKQokLm1nPSQuazgKcmV0dXJufXM9bmV3IFAuT00oYSkKcj0kLm1nCmlm
-KHI9PW51bGwpe3MuYj1wCiQuUzY9JC5tZz1zfWVsc2V7cT1yLmIKcy5iPXEKJC5tZz1yLmI9cwppZihx
-PT1udWxsKSQuazg9c319LApyYjpmdW5jdGlvbihhKXt2YXIgcz1udWxsLHI9JC5YMwppZihDLk5VPT09
-cil7UC5UayhzLHMsQy5OVSxhKQpyZXR1cm59UC5UayhzLHMscix0Lk0uYShyLkdZKGEpKSl9LApRdzpm
-dW5jdGlvbihhLGIpe1AuVUkoYSwic3RyZWFtIixiLkMoInFoPDA+IikpCnJldHVybiBuZXcgUC54SShi
-LkMoInhJPDA+IikpfSwKVGw6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iPT1udWxsP1AudjAoYSk6YgpQLlVJ
-KGEsImVycm9yIix0LkspCnJldHVybiBuZXcgUC5DdyhhLHMpfSwKdjA6ZnVuY3Rpb24oYSl7dmFyIHMK
-aWYodC5tLmIoYSkpe3M9YS5nSUkoKQppZihzIT1udWxsKXJldHVybiBzfXJldHVybiBDLnBkfSwKTDI6
-ZnVuY3Rpb24oYSxiLGMsZCxlKXtQLnJSKG5ldyBQLnBLKGQsZSkpfSwKVDg6ZnVuY3Rpb24oYSxiLGMs
-ZCxlKXt2YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJuIGQuJDAoKQokLlgzPWMKcz1yCnRyeXtyPWQu
-JDAoKQpyZXR1cm4gcn1maW5hbGx5eyQuWDM9c319LAp5djpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2
-YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJuIGQuJDEoZSkKJC5YMz1jCnM9cgp0cnl7cj1kLiQxKGUp
-CnJldHVybiByfWZpbmFsbHl7JC5YMz1zfX0sClF4OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcsaCxpKXt2
-YXIgcyxyPSQuWDMKaWYocj09PWMpcmV0dXJuIGQuJDIoZSxmKQokLlgzPWMKcz1yCnRyeXtyPWQuJDIo
-ZSxmKQpyZXR1cm4gcn1maW5hbGx5eyQuWDM9c319LApUazpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcwp0
-Lk0uYShkKQpzPUMuTlUhPT1jCmlmKHMpZD0hKCFzfHwhMSk/Yy5HWShkKTpjLlJUKGQsdC5IKQpQLmVX
-KGQpfSwKdGg6ZnVuY3Rpb24gdGgoYSl7dGhpcy5hPWF9LApoYTpmdW5jdGlvbiBoYShhLGIsYyl7dGhp
-cy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWczpmdW5jdGlvbiBWcyhhKXt0aGlzLmE9YX0sCkZ0OmZ1
-bmN0aW9uIEZ0KGEpe3RoaXMuYT1hfSwKVzM6ZnVuY3Rpb24gVzMoKXt9LAp5SDpmdW5jdGlvbiB5SChh
-LGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKaWg6ZnVuY3Rpb24gaWgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-ITEKdGhpcy4kdGk9Yn0sCldNOmZ1bmN0aW9uIFdNKGEpe3RoaXMuYT1hfSwKU1g6ZnVuY3Rpb24gU1go
-YSl7dGhpcy5hPWF9LApHczpmdW5jdGlvbiBHcyhhKXt0aGlzLmE9YX0sCkZ5OmZ1bmN0aW9uIEZ5KGEs
-Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LApHVjpmdW5jdGlvbiBHVihhLGIpe3ZhciBfPXRoaXMKXy5hPWEK
-Xy5kPV8uYz1fLmI9bnVsbApfLiR0aT1ifSwKcTQ6ZnVuY3Rpb24gcTQoYSxiKXt0aGlzLmE9YQp0aGlz
-LiR0aT1ifSwKUGY6ZnVuY3Rpb24gUGYoKXt9LApaZjpmdW5jdGlvbiBaZihhLGIpe3RoaXMuYT1hCnRo
-aXMuJHRpPWJ9LApGZTpmdW5jdGlvbiBGZShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5hPW51bGwKXy5i
-PWEKXy5jPWIKXy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZzOmZ1bmN0aW9uIHZzKGEsYil7dmFyIF89dGhp
-cwpfLmE9MApfLmI9YQpfLmM9bnVsbApfLiR0aT1ifSwKZGE6ZnVuY3Rpb24gZGEoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCm9ROmZ1bmN0aW9uIG9RKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApwVjpmdW5j
-dGlvbiBwVihhKXt0aGlzLmE9YX0sClU3OmZ1bmN0aW9uIFU3KGEpe3RoaXMuYT1hfSwKdnI6ZnVuY3Rp
-b24gdnIoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcnQ6ZnVuY3Rpb24gcnQoYSxi
-KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktGOmZ1bmN0aW9uIEtGKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
-LApaTDpmdW5jdGlvbiBaTChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApSVDpmdW5j
-dGlvbiBSVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApqWjpmdW5jdGlvbiBqWihh
-KXt0aGlzLmE9YX0sCnJxOmZ1bmN0aW9uIHJxKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApSVzpmdW5j
-dGlvbiBSVyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT006ZnVuY3Rpb24gT00oYSl7dGhpcy5hPWEK
-dGhpcy5iPW51bGx9LApxaDpmdW5jdGlvbiBxaCgpe30sCkI1OmZ1bmN0aW9uIEI1KGEsYil7dGhpcy5h
-PWEKdGhpcy5iPWJ9LAp1TzpmdW5jdGlvbiB1TyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKTU86ZnVu
-Y3Rpb24gTU8oKXt9LAprVDpmdW5jdGlvbiBrVCgpe30sCnhJOmZ1bmN0aW9uIHhJKGEpe3RoaXMuJHRp
-PWF9LApDdzpmdW5jdGlvbiBDdyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKbTA6ZnVuY3Rpb24gbTAo
-KXt9LApwSzpmdW5jdGlvbiBwSyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSmk6ZnVuY3Rpb24gSmko
-KXt9LApoajpmdW5jdGlvbiBoaihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWcDpm
-dW5jdGlvbiBWcChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24gT1IoYSxiLGMpe3Ro
-aXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLkMoIkA8
-MD4iKS5LcShjKS5DKCJGbzwxLDI+IikuYShILkI3KGEsbmV3IEguTjUoYi5DKCJAPDA+IikuS3EoYyku
-QygiTjU8MSwyPiIpKSkpfSwKRmw6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguTjUoYS5DKCJAPDA+
-IikuS3EoYikuQygiTjU8MSwyPiIpKX0sCkxzOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5iNihhLkMo
-ImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24oKXt2YXIgcz1PYmplY3QuY3JlYXRlKG51bGwpCnNbIjxub24t
-aWRlbnRpZmllci1rZXk+Il09cwpkZWxldGUgc1siPG5vbi1pZGVudGlmaWVyLWtleT4iXQpyZXR1cm4g
-c30sCnJqOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1uZXcgUC5sbShhLGIsYy5DKCJsbTwwPiIpKQpzLmM9
-YS5lCnJldHVybiBzfSwKRVA6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIKaWYoUC5oQihhKSl7aWYoYj09
-PSIoIiYmYz09PSIpIilyZXR1cm4iKC4uLikiCnJldHVybiBiKyIuLi4iK2N9cz1ILlZNKFtdLHQucykK
-Qy5ObS5pKCQueGcsYSkKdHJ5e1AuVnIoYSxzKX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVy
-biBILk9IKCQueGcsLTEpCiQueGcucG9wKCl9cj1QLnZnKGIsdC5yLmEocyksIiwgIikrYwpyZXR1cm4g
-ci5jaGFyQ29kZUF0KDApPT0wP3I6cn0sCldFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyCmlmKFAuaEIo
-YSkpcmV0dXJuIGIrIi4uLiIrYwpzPW5ldyBQLlJuKGIpCkMuTm0uaSgkLnhnLGEpCnRyeXtyPXMKci5h
-PVAudmcoci5hLGEsIiwgIil9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhn
-LC0xKQokLnhnLnBvcCgpfXMuYSs9YwpyPXMuYQpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn0s
-CmhCOmZ1bmN0aW9uKGEpe3ZhciBzLHIKZm9yKHM9JC54Zy5sZW5ndGgscj0wO3I8czsrK3IpaWYoYT09
-PSQueGdbcl0pcmV0dXJuITAKcmV0dXJuITF9LApWcjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8s
-bixtLGw9YS5na3ooYSksaz0wLGo9MAp3aGlsZSghMCl7aWYoIShrPDgwfHxqPDMpKWJyZWFrCmlmKCFs
-LkYoKSlyZXR1cm4Kcz1ILkVqKGwuZ2woKSkKQy5ObS5pKGIscykKays9cy5sZW5ndGgrMjsrK2p9aWYo
-IWwuRigpKXtpZihqPD01KXJldHVybgppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpyPWIu
-cG9wKCkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcT1iLnBvcCgpfWVsc2V7cD1sLmds
-KCk7KytqCmlmKCFsLkYoKSl7aWYoajw9NCl7Qy5ObS5pKGIsSC5FaihwKSkKcmV0dXJufXI9SC5Faihw
-KQppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQpxPWIucG9wKCkKays9ci5sZW5ndGgrMn1l
-bHNle289bC5nbCgpOysragpmb3IoO2wuRigpO3A9byxvPW4pe249bC5nbCgpOysragppZihqPjEwMCl7
-d2hpbGUoITApe2lmKCEoaz43NSYmaj4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChi
-LC0xKQprLT1iLnBvcCgpLmxlbmd0aCsyOy0tan1DLk5tLmkoYiwiLi4uIikKcmV0dXJufX1xPUguRWoo
-cCkKcj1ILkVqKG8pCmsrPXIubGVuZ3RoK3EubGVuZ3RoKzR9fWlmKGo+Yi5sZW5ndGgrMil7ays9NQpt
-PSIuLi4ifWVsc2UgbT1udWxsCndoaWxlKCEwKXtpZighKGs+ODAmJmIubGVuZ3RoPjMpKWJyZWFrCmlm
-KDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEpCmstPWIucG9wKCkubGVuZ3RoKzIKaWYobT09bnVs
-bCl7ays9NQptPSIuLi4ifX1pZihtIT1udWxsKUMuTm0uaShiLG0pCkMuTm0uaShiLHEpCkMuTm0uaShi
-LHIpfSwKdE06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9UC5McyhiKQpmb3Iocz1hLmxlbmd0aCxyPTA7
-cjxhLmxlbmd0aDthLmxlbmd0aD09PXN8fCgwLEgubGspKGEpLCsrcilxLmkoMCxiLmEoYVtyXSkpCnJl
-dHVybiBxfSwKbk86ZnVuY3Rpb24oYSl7dmFyIHMscj17fQppZihQLmhCKGEpKXJldHVybiJ7Li4ufSIK
-cz1uZXcgUC5SbigiIikKdHJ5e0MuTm0uaSgkLnhnLGEpCnMuYSs9InsiCnIuYT0hMAphLksoMCxuZXcg
-UC5yYShyLHMpKQpzLmErPSJ9In1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILk9IKCQu
-eGcsLTEpCiQueGcucG9wKCl9cj1zLmEKcmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9LApiNjpm
-dW5jdGlvbiBiNihhKXt2YXIgXz10aGlzCl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9
-MApfLiR0aT1hfSwKYm46ZnVuY3Rpb24gYm4oYSl7dGhpcy5hPWEKdGhpcy5jPXRoaXMuYj1udWxsfSwK
-bG06ZnVuY3Rpb24gbG0oYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8u
-JHRpPWN9LAptVzpmdW5jdGlvbiBtVygpe30sCnV5OmZ1bmN0aW9uIHV5KCl7fSwKbEQ6ZnVuY3Rpb24g
-bEQoKXt9LAppbDpmdW5jdGlvbiBpbCgpe30sCnJhOmZ1bmN0aW9uIHJhKGEsYil7dGhpcy5hPWEKdGhp
-cy5iPWJ9LApZazpmdW5jdGlvbiBZaygpe30sCnlROmZ1bmN0aW9uIHlRKGEpe3RoaXMuYT1hfSwKS1A6
-ZnVuY3Rpb24gS1AoKXt9LApQbjpmdW5jdGlvbiBQbigpe30sCkdqOmZ1bmN0aW9uIEdqKGEsYil7dGhp
-cy5hPWEKdGhpcy4kdGk9Yn0sCk1hOmZ1bmN0aW9uIE1hKCl7fSwKVmo6ZnVuY3Rpb24gVmooKXt9LApY
-djpmdW5jdGlvbiBYdigpe30sCm5ZOmZ1bmN0aW9uIG5ZKCl7fSwKV1k6ZnVuY3Rpb24gV1koKXt9LApS
-VTpmdW5jdGlvbiBSVSgpe30sCkJTOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAKaWYodHlwZW9mIGEh
-PSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpzPW51bGwKdHJ5e3M9SlNPTi5wYXJzZShhKX1jYXRj
-aChxKXtyPUguUnUocSkKcD1QLnJyKFN0cmluZyhyKSxudWxsLG51bGwpCnRocm93IEguYihwKX1wPVAu
-UWUocykKcmV0dXJuIHB9LApRZTpmdW5jdGlvbihhKXt2YXIgcwppZihhPT1udWxsKXJldHVybiBudWxs
-CmlmKHR5cGVvZiBhIT0ib2JqZWN0IilyZXR1cm4gYQppZihPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSkh
-PT1BcnJheS5wcm90b3R5cGUpcmV0dXJuIG5ldyBQLnV3KGEsT2JqZWN0LmNyZWF0ZShudWxsKSkKZm9y
-KHM9MDtzPGEubGVuZ3RoOysrcylhW3NdPVAuUWUoYVtzXSkKcmV0dXJuIGF9LApreTpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgcyxyCmlmKGIgaW5zdGFuY2VvZiBVaW50OEFycmF5KXtzPWIKZD1zLmxlbmd0aApp
-ZihkLWM8MTUpcmV0dXJuIG51bGwKcj1QLkNHKGEscyxjLGQpCmlmKHIhPW51bGwmJmEpaWYoci5pbmRl
-eE9mKCJcdWZmZmQiKT49MClyZXR1cm4gbnVsbApyZXR1cm4gcn1yZXR1cm4gbnVsbH0sCkNHOmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciBzPWE/JC5IRygpOiQucmYoKQppZihzPT1udWxsKXJldHVybiBudWxsCmlm
-KDA9PT1jJiZkPT09Yi5sZW5ndGgpcmV0dXJuIFAuUmIocyxiKQpyZXR1cm4gUC5SYihzLGIuc3ViYXJy
-YXkoYyxQLmpCKGMsZCxiLmxlbmd0aCkpKX0sClJiOmZ1bmN0aW9uKGEsYil7dmFyIHMscgp0cnl7cz1h
-LmRlY29kZShiKQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIpfXJldHVybiBudWxsfSwKeE06ZnVuY3Rp
-b24oYSxiLGMsZCxlLGYpe2lmKEMuam4uelkoZiw0KSE9PTApdGhyb3cgSC5iKFAucnIoIkludmFsaWQg
-YmFzZTY0IHBhZGRpbmcsIHBhZGRlZCBsZW5ndGggbXVzdCBiZSBtdWx0aXBsZSBvZiBmb3VyLCBpcyAi
-K2YsYSxjKSkKaWYoZCtlIT09Zil0aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgcGFkZGluZywg
-Jz0nIG5vdCBhdCB0aGUgZW5kIixhLGIpKQppZihlPjIpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFz
-ZTY0IHBhZGRpbmcsIG1vcmUgdGhhbiB0d28gJz0nIGNoYXJhY3RlcnMiLGEsYikpfSwKR3k6ZnVuY3Rp
-b24oYSxiLGMpe3JldHVybiBuZXcgUC5VZChhLGIpfSwKTkM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuTHQo
-KX0sClVnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLnR1KGEsW10sUC5DeSgpKX0sCnVYOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcyxyPW5ldyBQLlJuKCIiKSxxPVAuVWcocixiKQpxLmlVKGEpCnM9ci5hCnJl
-dHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKajQ6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2Ug
-NjU6cmV0dXJuIk1pc3NpbmcgZXh0ZW5zaW9uIGJ5dGUiCmNhc2UgNjc6cmV0dXJuIlVuZXhwZWN0ZWQg
-ZXh0ZW5zaW9uIGJ5dGUiCmNhc2UgNjk6cmV0dXJuIkludmFsaWQgVVRGLTggYnl0ZSIKY2FzZSA3MTpy
-ZXR1cm4iT3ZlcmxvbmcgZW5jb2RpbmciCmNhc2UgNzM6cmV0dXJuIk91dCBvZiB1bmljb2RlIHJhbmdl
-IgpjYXNlIDc1OnJldHVybiJFbmNvZGVkIHN1cnJvZ2F0ZSIKY2FzZSA3NzpyZXR1cm4iVW5maW5pc2hl
-ZCBVVEYtOCBvY3RldCBzZXF1ZW5jZSIKZGVmYXVsdDpyZXR1cm4iIn19LApqeTpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHMscixxLHAsbz1jLWIsbj1uZXcgVWludDhBcnJheShvKQpmb3Iocz1uLmxlbmd0aCxyPUou
-VTYoYSkscT0wO3E8bzsrK3Epe3A9ci5xKGEsYitxKQppZih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVy
-biBwLnpNKCkKaWYoKHAmNDI5NDk2NzA0MCk+Pj4wIT09MClwPTI1NQppZihxPj1zKXJldHVybiBILk9I
-KG4scSkKbltxXT1wfXJldHVybiBufSwKdXc6ZnVuY3Rpb24gdXcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-Ygp0aGlzLmM9bnVsbH0sCmk4OmZ1bmN0aW9uIGk4KGEpe3RoaXMuYT1hfSwKcGc6ZnVuY3Rpb24gcGco
-KXt9LApjMjpmdW5jdGlvbiBjMigpe30sCkNWOmZ1bmN0aW9uIENWKCl7fSwKVTg6ZnVuY3Rpb24gVTgo
-KXt9LApVazpmdW5jdGlvbiBVaygpe30sCndJOmZ1bmN0aW9uIHdJKCl7fSwKWmk6ZnVuY3Rpb24gWmko
-KXt9LApVZDpmdW5jdGlvbiBVZChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSzg6ZnVuY3Rpb24gSzgo
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmJ5OmZ1bmN0aW9uIGJ5KCl7fSwKb2o6ZnVuY3Rpb24gb2oo
-YSl7dGhpcy5iPWF9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0sClNoOmZ1bmN0aW9uIFNoKCl7
-fSwKdGk6ZnVuY3Rpb24gdGkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnR1OmZ1bmN0aW9uIHR1KGEs
-YixjKXt0aGlzLmM9YQp0aGlzLmE9Ygp0aGlzLmI9Y30sCnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6ZnVu
-Y3Rpb24gRTMoKXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1bmN0
-aW9uIEdZKGEpe3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24gYnooYSl7dGhpcy5hPWEKdGhpcy5iPTE2CnRo
-aXMuYz0wfSwKUUE6ZnVuY3Rpb24oYSxiKXt2YXIgcz1ILkhwKGEsYikKaWYocyE9bnVsbClyZXR1cm4g
-cwp0aHJvdyBILmIoUC5ycihhLG51bGwsbnVsbCkpfSwKRjpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNl
-b2YgSC52KXJldHVybiBhLncoMCkKcmV0dXJuIkluc3RhbmNlIG9mICciK0guRWooSC5NKGEpKSsiJyJ9
-LApPODpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyPWM/Si5LaChhLGQpOkouUWkoYSxkKQppZihhIT09
-MCYmYiE9bnVsbClmb3Iocz0wO3M8ci5sZW5ndGg7KytzKXJbc109YgpyZXR1cm4gcn0sCkNIOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcyxyPUguVk0oW10sYy5DKCJqZDwwPiIpKQpmb3Iocz1KLklUKGEpO3MuRigp
-OylDLk5tLmkocixjLmEocy5nbCgpKSkKaWYoYilyZXR1cm4gcgpyZXR1cm4gSi5FcChyLGMpfSwKZEg6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHI9Si5LaChhLGMpCmZvcihzPTA7czxhOysrcylDLk5tLlkocixz
-LGIuJDEocykpCnJldHVybiByfSwKQUY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi56QyhQLkNIKGEsITEs
-YikpfSwKSE06ZnVuY3Rpb24oYSxiLGMpe2lmKHQuYm0uYihhKSlyZXR1cm4gSC5mdyhhLGIsUC5qQihi
-LGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1cm4gSC5M
-dyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvLG49bnVsbAppZihiPDApdGhyb3cg
-SC5iKFAuVEUoYiwwLGEubGVuZ3RoLG4sbikpCnM9Yz09bnVsbAppZighcyYmYzxiKXRocm93IEguYihQ
-LlRFKGMsYixhLmxlbmd0aCxuLG4pKQpyPW5ldyBILmE3KGEsYS5sZW5ndGgsSC56KGEpLkMoImE3PGxE
-LkU+IikpCmZvcihxPTA7cTxiOysrcSlpZighci5GKCkpdGhyb3cgSC5iKFAuVEUoYiwwLHEsbixuKSkK
-cD1bXQppZihzKWZvcig7ci5GKCk7KXtvPXIuZApwLnB1c2gobyl9ZWxzZSBmb3IocT1iO3E8YzsrK3Ep
-e2lmKCFyLkYoKSl0aHJvdyBILmIoUC5URShjLGIscSxuLG4pKQpvPXIuZApwLnB1c2gobyl9cmV0dXJu
-IEguZVQocCl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEs
-ITEsITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1KLklUKGIpCmlmKCFzLkYoKSlyZXR1cm4g
-YQppZihjLmxlbmd0aD09PTApe2RvIGErPUguRWoocy5nbCgpKQp3aGlsZShzLkYoKSl9ZWxzZXthKz1I
-LkVqKHMuZ2woKSkKZm9yKDtzLkYoKTspYT1hK2MrSC5FaihzLmdsKCkpfXJldHVybiBhfSwKbHI6ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIg
-cz1ILk0wKCkKaWYocyE9bnVsbClyZXR1cm4gUC5oSyhzKQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNl
-JyBpcyBub3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxu
-LG09IjAxMjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXtzPSQuejQoKS5iCmlmKHR5cGVvZiBiIT0i
-c3RyaW5nIilILnZoKEgudEwoYikpCnM9cy50ZXN0KGIpfWVsc2Ugcz0hMQppZihzKXJldHVybiBiCkgu
-TGgoYykuQygiVWsuUyIpLmEoYikKcj1jLmdaRSgpLldKKGIpCmZvcihzPXIubGVuZ3RoLHE9MCxwPSIi
-O3E8czsrK3Epe289cltxXQppZihvPDEyOCl7bj1vPj4+NAppZihuPj04KXJldHVybiBILk9IKGEsbikK
-bj0oYVtuXSYxPDwobyYxNSkpIT09MH1lbHNlIG49ITEKaWYobilwKz1ILkx3KG8pCmVsc2UgcD1kJiZv
-PT09MzI/cCsiKyI6cCsiJSIrbVtvPj4+NCYxNV0rbVtvJjE1XX1yZXR1cm4gcC5jaGFyQ29kZUF0KDAp
-PT0wP3A6cH0sCkdxOmZ1bmN0aW9uKGEpe3ZhciBzPU1hdGguYWJzKGEpLHI9YTwwPyItIjoiIgppZihz
-Pj0xMDAwKXJldHVybiIiK2EKaWYocz49MTAwKXJldHVybiByKyIwIitzCmlmKHM+PTEwKXJldHVybiBy
-KyIwMCIrcwpyZXR1cm4gcisiMDAwIitzfSwKVng6ZnVuY3Rpb24oYSl7aWYoYT49MTAwKXJldHVybiIi
-K2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJuIjAwIithfSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49
-MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCnA6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1i
-ZXIifHxILmwoYSl8fG51bGw9PWEpcmV0dXJuIEouaihhKQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0
-dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLkYoYSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4g
-bmV3IFAuQzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudSghMSxudWxsLG51bGwsYSl9
-LApMMzpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQLnUoITAsYSxiLGMpfSwKVUk6ZnVuY3Rpb24o
-YSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKG5ldyBQLnUoITEsbnVsbCxiLCJNdXN0IG5vdCBiZSBu
-dWxsIikpCnJldHVybiBhfSwKTzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuYkoobnVsbCxudWxs
-LCEwLGEsYiwiVmFsdWUgbm90IGluIHJhbmdlIil9LApURTpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVy
-biBuZXcgUC5iSihiLGMsITAsYSxkLCJJbnZhbGlkIHZhbHVlIil9LAp3QTpmdW5jdGlvbihhLGIsYyxk
-KXtpZihhPGJ8fGE+Yyl0aHJvdyBILmIoUC5URShhLGIsYyxkLG51bGwpKQpyZXR1cm4gYX0sCmpCOmZ1
-bmN0aW9uKGEsYixjKXtpZigwPmF8fGE+Yyl0aHJvdyBILmIoUC5URShhLDAsYywic3RhcnQiLG51bGwp
-KQppZihiIT1udWxsKXtpZihhPmJ8fGI+Yyl0aHJvdyBILmIoUC5URShiLGEsYywiZW5kIixudWxsKSkK
-cmV0dXJuIGJ9cmV0dXJuIGN9LAprMTpmdW5jdGlvbihhLGIpe2lmKGE8MCl0aHJvdyBILmIoUC5URShh
-LDAsbnVsbCxiLG51bGwpKQpyZXR1cm4gYX0sCkNmOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9SC51
-UChlPT1udWxsP0ouSG0oYik6ZSkKcmV0dXJuIG5ldyBQLmVZKHMsITAsYSxjLCJJbmRleCBvdXQgb2Yg
-cmFuZ2UiKX0sCkw0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC51YihhKX0sClNZOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC5kcyhhKX0sClBWOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5saihhKX0sCmE0
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5VVihhKX0sCnJyOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4g
-bmV3IFAuYUUoYSxiLGMpfSwKaEs6ZnVuY3Rpb24oYTUpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGks
-aCxnLGYsZSxkLGMsYixhLGEwLGExLGEyLGEzPW51bGwsYTQ9YTUubGVuZ3RoCmlmKGE0Pj01KXtzPSgo
-Si5ReihhNSw0KV41OCkqM3xDLnhCLlcoYTUsMCleMTAwfEMueEIuVyhhNSwxKV45N3xDLnhCLlcoYTUs
-MileMTE2fEMueEIuVyhhNSwzKV45Nyk+Pj4wCmlmKHM9PT0wKXJldHVybiBQLktEKGE0PGE0P0MueEIu
-TmooYTUsMCxhNCk6YTUsNSxhMykuZ2xSKCkKZWxzZSBpZihzPT09MzIpcmV0dXJuIFAuS0QoQy54Qi5O
-aihhNSw1LGE0KSwwLGEzKS5nbFIoKX1yPVAuTzgoOCwwLCExLHQucCkKQy5ObS5ZKHIsMCwwKQpDLk5t
-LlkociwxLC0xKQpDLk5tLlkociwyLC0xKQpDLk5tLlkociw3LC0xKQpDLk5tLlkociwzLDApCkMuTm0u
-WShyLDQsMCkKQy5ObS5ZKHIsNSxhNCkKQy5ObS5ZKHIsNixhNCkKaWYoUC5VQihhNSwwLGE0LDAscik+
-PTE0KUMuTm0uWShyLDcsYTQpCmlmKDE+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsMSkKcT1yWzFdCmlm
-KHE+PTApaWYoUC5VQihhNSwwLHEsMjAscik9PT0yMCl7aWYoNz49ci5sZW5ndGgpcmV0dXJuIEguT0go
-ciw3KQpyWzddPXF9cD1yLmxlbmd0aAppZigyPj1wKXJldHVybiBILk9IKHIsMikKbz1yWzJdKzEKaWYo
-Mz49cClyZXR1cm4gSC5PSChyLDMpCm49clszXQppZig0Pj1wKXJldHVybiBILk9IKHIsNCkKbT1yWzRd
-CmlmKDU+PXApcmV0dXJuIEguT0gociw1KQpsPXJbNV0KaWYoNj49cClyZXR1cm4gSC5PSChyLDYpCms9
-cls2XQppZihrPGwpbD1rCmlmKG08byltPWwKZWxzZSBpZihtPD1xKW09cSsxCmlmKG48byluPW0KaWYo
-Nz49cClyZXR1cm4gSC5PSChyLDcpCmo9cls3XTwwCmlmKGopaWYobz5xKzMpe2k9YTMKaj0hMX1lbHNl
-e3A9bj4wCmlmKHAmJm4rMT09PW0pe2k9YTMKaj0hMX1lbHNle2lmKCEobDxhNCYmbD09PW0rMiYmSi5x
-MChhNSwiLi4iLG0pKSloPWw+bSsyJiZKLnEwKGE1LCIvLi4iLGwtMykKZWxzZSBoPSEwCmlmKGgpe2k9
-YTMKaj0hMX1lbHNle2lmKHE9PT00KWlmKEoucTAoYTUsImZpbGUiLDApKXtpZihvPD0wKXtpZighQy54
-Qi5RaShhNSwiLyIsbSkpe2c9ImZpbGU6Ly8vIgpzPTN9ZWxzZXtnPSJmaWxlOi8vIgpzPTJ9YTU9ZytD
-LnhCLk5qKGE1LG0sYTQpCnEtPTAKcD1zLTAKbCs9cAprKz1wCmE0PWE1Lmxlbmd0aApvPTcKbj03Cm09
-N31lbHNlIGlmKG09PT1sKXsrK2sKZj1sKzEKYTU9Qy54Qi5pNyhhNSxtLGwsIi8iKTsrK2E0Cmw9Zn1p
-PSJmaWxlIn1lbHNlIGlmKEMueEIuUWkoYTUsImh0dHAiLDApKXtpZihwJiZuKzM9PT1tJiZDLnhCLlFp
-KGE1LCI4MCIsbisxKSl7ay09MwplPW0tMwpsLT0zCmE1PUMueEIuaTcoYTUsbixtLCIiKQphNC09Mwpt
-PWV9aT0iaHR0cCJ9ZWxzZSBpPWEzCmVsc2UgaWYocT09PTUmJkoucTAoYTUsImh0dHBzIiwwKSl7aWYo
-cCYmbis0PT09bSYmSi5xMChhNSwiNDQzIixuKzEpKXtrLT00CmU9bS00CmwtPTQKYTU9Si5kZyhhNSxu
-LG0sIiIpCmE0LT0zCm09ZX1pPSJodHRwcyJ9ZWxzZSBpPWEzCmo9ITB9fX1lbHNlIGk9YTMKaWYoail7
-cD1hNS5sZW5ndGgKaWYoYTQ8cCl7YTU9Si5sZChhNSwwLGE0KQpxLT0wCm8tPTAKbi09MAptLT0wCmwt
-PTAKay09MH1yZXR1cm4gbmV3IFAuVWYoYTUscSxvLG4sbSxsLGssaSl9aWYoaT09bnVsbClpZihxPjAp
-aT1QLlBpKGE1LDAscSkKZWxzZXtpZihxPT09MClQLlIzKGE1LDAsIkludmFsaWQgZW1wdHkgc2NoZW1l
-IikKaT0iIn1pZihvPjApe2Q9cSszCmM9ZDxvP1AuelIoYTUsZCxvLTEpOiIiCmI9UC5PZShhNSxvLG4s
-ITEpCnA9bisxCmlmKHA8bSl7YT1ILkhwKEoubGQoYTUscCxtKSxhMykKYTA9UC53QihhPT1udWxsP0gu
-dmgoUC5ycigiSW52YWxpZCBwb3J0IixhNSxwKSk6YSxpKX1lbHNlIGEwPWEzfWVsc2V7YTA9YTMKYj1h
-MApjPSIifWExPVAua2EoYTUsbSxsLGEzLGksYiE9bnVsbCkKYTI9bDxrP1AubGUoYTUsbCsxLGssYTMp
-OmEzCnJldHVybiBuZXcgUC5EbihpLGMsYixhMCxhMSxhMixrPGE0P1AudEcoYTUsaysxLGE0KTphMyl9
-LApNdDpmdW5jdGlvbihhKXtILmgoYSkKcmV0dXJuIFAua3UoYSwwLGEubGVuZ3RoLEMueE0sITEpfSwK
-V1g6ZnVuY3Rpb24oYSl7dmFyIHM9dC5OCnJldHVybiBDLk5tLk4wKEguVk0oYS5zcGxpdCgiJiIpLHQu
-cyksUC5GbChzLHMpLG5ldyBQLm4xKEMueE0pLHQuSil9LApIaDpmdW5jdGlvbihhLGIsYyl7dmFyIHMs
-cixxLHAsbyxuLG0sbD0iSVB2NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4YWN0bHkgNCBwYXJ0cyIs
-az0iZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1uZXcgUC5jUyhhKSxpPW5l
-dyBVaW50OEFycmF5KDQpCmZvcihzPWkubGVuZ3RoLHI9YixxPXIscD0wO3I8YzsrK3Ipe289Qy54Qi5t
-KGEscikKaWYobyE9PTQ2KXtpZigob140OCk+OSlqLiQyKCJpbnZhbGlkIGNoYXJhY3RlciIscil9ZWxz
-ZXtpZihwPT09MylqLiQyKGwscikKbj1QLlFBKEMueEIuTmooYSxxLHIpLG51bGwpCmlmKHR5cGVvZiBu
-IT09Im51bWJlciIpcmV0dXJuIG4ub3MoKQppZihuPjI1NSlqLiQyKGsscSkKbT1wKzEKaWYocD49cyly
-ZXR1cm4gSC5PSChpLHApCmlbcF09bgpxPXIrMQpwPW19fWlmKHAhPT0zKWouJDIobCxjKQpuPVAuUUEo
-Qy54Qi5OaihhLHEsYyksbnVsbCkKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5vcygpCmlm
-KG4+MjU1KWouJDIoayxxKQppZihwPj1zKXJldHVybiBILk9IKGkscCkKaVtwXT1uCnJldHVybiBpfSwK
-ZWc6ZnVuY3Rpb24oYSxhMCxhMSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYz1u
-ZXcgUC5WQyhhKSxiPW5ldyBQLkpUKGMsYSkKaWYoYS5sZW5ndGg8MiljLiQxKCJhZGRyZXNzIGlzIHRv
-byBzaG9ydCIpCnM9SC5WTShbXSx0LmEpCmZvcihyPWEwLHE9cixwPSExLG89ITE7cjxhMTsrK3Ipe249
-Qy54Qi5tKGEscikKaWYobj09PTU4KXtpZihyPT09YTApeysrcgppZihDLnhCLm0oYSxyKSE9PTU4KWMu
-JDIoImludmFsaWQgc3RhcnQgY29sb24uIixyKQpxPXJ9aWYocj09PXEpe2lmKHApYy4kMigib25seSBv
-bmUgd2lsZGNhcmQgYDo6YCBpcyBhbGxvd2VkIixyKQpDLk5tLmkocywtMSkKcD0hMH1lbHNlIEMuTm0u
-aShzLGIuJDIocSxyKSkKcT1yKzF9ZWxzZSBpZihuPT09NDYpbz0hMH1pZihzLmxlbmd0aD09PTApYy4k
-MSgidG9vIGZldyBwYXJ0cyIpCm09cT09PWExCmw9Qy5ObS5ncloocykKaWYobSYmbCE9PS0xKWMuJDIo
-ImV4cGVjdGVkIGEgcGFydCBhZnRlciBsYXN0IGA6YCIsYTEpCmlmKCFtKWlmKCFvKUMuTm0uaShzLGIu
-JDIocSxhMSkpCmVsc2V7az1QLkhoKGEscSxhMSkKQy5ObS5pKHMsKGtbMF08PDh8a1sxXSk+Pj4wKQpD
-Lk5tLmkocywoa1syXTw8OHxrWzNdKT4+PjApfWlmKHApe2lmKHMubGVuZ3RoPjcpYy4kMSgiYW4gYWRk
-cmVzcyB3aXRoIGEgd2lsZGNhcmQgbXVzdCBoYXZlIGxlc3MgdGhhbiA3IHBhcnRzIil9ZWxzZSBpZihz
-Lmxlbmd0aCE9PTgpYy4kMSgiYW4gYWRkcmVzcyB3aXRob3V0IGEgd2lsZGNhcmQgbXVzdCBjb250YWlu
-IGV4YWN0bHkgOCBwYXJ0cyIpCmo9bmV3IFVpbnQ4QXJyYXkoMTYpCmZvcihsPXMubGVuZ3RoLGk9ai5s
-ZW5ndGgsaD05LWwscj0wLGc9MDtyPGw7KytyKXtmPXNbcl0KaWYoZj09PS0xKWZvcihlPTA7ZTxoOysr
-ZSl7aWYoZzwwfHxnPj1pKXJldHVybiBILk9IKGosZykKaltnXT0wCmQ9ZysxCmlmKGQ+PWkpcmV0dXJu
-IEguT0goaixkKQpqW2RdPTAKZys9Mn1lbHNle2Q9Qy5qbi53RyhmLDgpCmlmKGc8MHx8Zz49aSlyZXR1
-cm4gSC5PSChqLGcpCmpbZ109ZApkPWcrMQppZihkPj1pKXJldHVybiBILk9IKGosZCkKaltkXT1mJjI1
-NQpnKz0yfX1yZXR1cm4gan0sCktMOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciBzLHIscSxwLG8s
-bgpmPWY9PW51bGw/IiI6UC5QaShmLDAsZi5sZW5ndGgpCmc9UC56UihnLDAsZz09bnVsbD8wOmcubGVu
-Z3RoKQphPVAuT2UoYSwwLGE9PW51bGw/MDphLmxlbmd0aCwhMSkKcz1QLmxlKG51bGwsMCwwLGUpCnI9
-UC50RyhudWxsLDAsMCkKZD1QLndCKGQsZikKcT1mPT09ImZpbGUiCmlmKGE9PW51bGwpcD1nLmxlbmd0
-aCE9PTB8fGQhPW51bGx8fHEKZWxzZSBwPSExCmlmKHApYT0iIgpwPWE9PW51bGwKbz0hcApiPVAua2Eo
-YiwwLGI9PW51bGw/MDpiLmxlbmd0aCxjLGYsbykKbj1mLmxlbmd0aD09PTAKaWYobiYmcCYmIUMueEIu
-bihiLCIvIikpYj1QLndGKGIsIW58fG8pCmVsc2UgYj1QLnhlKGIpCnJldHVybiBuZXcgUC5EbihmLGcs
-cCYmQy54Qi5uKGIsIi8vIik/IiI6YSxkLGIscyxyKX0sCndLOmZ1bmN0aW9uKGEpe2lmKGE9PT0iaHR0
-cCIpcmV0dXJuIDgwCmlmKGE9PT0iaHR0cHMiKXJldHVybiA0NDMKcmV0dXJuIDB9LApSMzpmdW5jdGlv
-bihhLGIsYyl7dGhyb3cgSC5iKFAucnIoYyxhLGIpKX0sClhkOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBz
-LHIscSxwLG8sbixtLGwsayxqLGksaD1udWxsLGc9Yi5sZW5ndGgKaWYoZyE9PTApe3E9MAp3aGlsZSgh
-MCl7aWYoIShxPGcpKXtzPSIiCnI9MApicmVha31pZihDLnhCLlcoYixxKT09PTY0KXtzPUMueEIuTmoo
-YiwwLHEpCnI9cSsxCmJyZWFrfSsrcX1pZihyPGcmJkMueEIuVyhiLHIpPT09OTEpe2ZvcihwPXIsbz0t
-MTtwPGc7KytwKXtuPUMueEIuVyhiLHApCmlmKG49PT0zNyYmbzwwKXttPUMueEIuUWkoYiwiMjUiLHAr
-MSk/cCsyOnAKbz1wCnA9bX1lbHNlIGlmKG49PT05MylicmVha31pZihwPT09Zyl0aHJvdyBILmIoUC5y
-cigiSW52YWxpZCBJUHY2IGhvc3QgZW50cnkuIixiLHIpKQpsPW88MD9wOm8KUC5lZyhiLHIrMSxsKTsr
-K3AKaWYocCE9PWcmJkMueEIuVyhiLHApIT09NTgpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgZW5kIG9m
-IGF1dGhvcml0eSIsYixwKSl9ZWxzZSBwPXIKd2hpbGUoITApe2lmKCEocDxnKSl7az1oCmJyZWFrfWlm
-KEMueEIuVyhiLHApPT09NTgpe2o9Qy54Qi5HKGIscCsxKQprPWoubGVuZ3RoIT09MD9QLlFBKGosaCk6
-aApicmVha30rK3B9aT1DLnhCLk5qKGIscixwKX1lbHNle2s9aAppPWsKcz0iIn1yZXR1cm4gUC5LTChp
-LGgsSC5WTShjLnNwbGl0KCIvIiksdC5zKSxrLGQsYSxzKX0sCmtFOmZ1bmN0aW9uKGEsYil7dmFyIHMs
-cixxLHAsbwpmb3Iocz1hLmxlbmd0aCxyPTA7cjxzOysrcil7cT1hW3JdCnEudG9TdHJpbmcKcD1KLlU2
-KHEpCm89cC5nQShxKQppZigwPm8pSC52aChQLlRFKDAsMCxwLmdBKHEpLG51bGwsbnVsbCkpCmlmKEgu
-bTIocSwiLyIsMCkpe3M9UC5MNCgiSWxsZWdhbCBwYXRoIGNoYXJhY3RlciAiK0guRWoocSkpCnRocm93
-IEguYihzKX19fSwKSE46ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscQpmb3Iocz1ILnFDKGEsYyxudWxs
-LEgudDYoYSkuYykscz1uZXcgSC5hNyhzLHMuZ0Eocykscy4kdGkuQygiYTc8YUwuRT4iKSk7cy5GKCk7
-KXtyPXMuZApxPVAubnUoJ1siKi86PD4/XFxcXHxdJykKci50b1N0cmluZwppZihILm0yKHIscSwwKSl7
-cz1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRoOiAiK3IpCnRocm93IEguYihzKX19fSwKcmc6
-ZnVuY3Rpb24oYSxiKXt2YXIgcwppZighKDY1PD1hJiZhPD05MCkpcz05Nzw9YSYmYTw9MTIyCmVsc2Ug
-cz0hMAppZihzKXJldHVybgpzPVAuTDQoIklsbGVnYWwgZHJpdmUgbGV0dGVyICIrUC5PbyhhKSkKdGhy
-b3cgSC5iKHMpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihhIT1udWxsJiZhPT09UC53SyhiKSlyZXR1cm4g
-bnVsbApyZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbgppZihhPT1u
-dWxsKXJldHVybiBudWxsCmlmKGI9PT1jKXJldHVybiIiCmlmKEMueEIubShhLGIpPT09OTEpe3M9Yy0x
-CmlmKEMueEIubShhLHMpIT09OTMpUC5SMyhhLGIsIk1pc3NpbmcgZW5kIGBdYCB0byBtYXRjaCBgW2Ag
-aW4gaG9zdCIpCnI9YisxCnE9UC50byhhLHIscykKaWYocTxzKXtwPXErMQpvPVAuT0EoYSxDLnhCLlFp
-KGEsIjI1IixwKT9xKzM6cCxzLCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLHIscSkKcmV0dXJuIEMueEIu
-TmooYSxiLHEpLnRvTG93ZXJDYXNlKCkrbysiXSJ9Zm9yKG49YjtuPGM7KytuKWlmKEMueEIubShhLG4p
-PT09NTgpe3E9Qy54Qi5YVShhLCIlIixiKQpxPXE+PWImJnE8Yz9xOmMKaWYocTxjKXtwPXErMQpvPVAu
-T0EoYSxDLnhCLlFpKGEsIjI1IixwKT9xKzM6cCxjLCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLGIscSkK
-cmV0dXJuIlsiK0MueEIuTmooYSxiLHEpK28rIl0ifXJldHVybiBQLk9MKGEsYixjKX0sCnRvOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcz1DLnhCLlhVKGEsIiUiLGIpCnJldHVybiBzPj1iJiZzPGM/czpjfSwKT0E6
-ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaT1kIT09IiI/bmV3IFAuUm4o
-ZCk6bnVsbApmb3Iocz1iLHI9cyxxPSEwO3M8Yzspe3A9Qy54Qi5tKGEscykKaWYocD09PTM3KXtvPVAu
-cnYoYSxzLCEwKQpuPW89PW51bGwKaWYobiYmcSl7cys9Mwpjb250aW51ZX1pZihpPT1udWxsKWk9bmV3
-IFAuUm4oIiIpCm09aS5hKz1DLnhCLk5qKGEscixzKQppZihuKW89Qy54Qi5OaihhLHMscyszKQplbHNl
-IGlmKG89PT0iJSIpUC5SMyhhLHMsIlpvbmVJRCBzaG91bGQgbm90IGNvbnRhaW4gJSBhbnltb3JlIikK
-aS5hPW0rbwpzKz0zCnI9cwpxPSEwfWVsc2V7aWYocDwxMjcpe249cD4+PjQKaWYobj49OClyZXR1cm4g
-SC5PSChDLkYzLG4pCm49KEMuRjNbbl0mMTw8KHAmMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEm
-JjY1PD1wJiY5MD49cCl7aWYoaT09bnVsbClpPW5ldyBQLlJuKCIiKQppZihyPHMpe2kuYSs9Qy54Qi5O
-aihhLHIscykKcj1zfXE9ITF9KytzfWVsc2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnMrMTxjKXtsPUMu
-eEIubShhLHMrMSkKaWYoKGwmNjQ1MTIpPT09NTYzMjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGwmMTAy
-MwprPTJ9ZWxzZSBrPTF9ZWxzZSBrPTEKaj1DLnhCLk5qKGEscixzKQppZihpPT1udWxsKXtpPW5ldyBQ
-LlJuKCIiKQpuPWl9ZWxzZSBuPWkKbi5hKz1qCm4uYSs9UC56WChwKQpzKz1rCnI9c319fWlmKGk9PW51
-bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHI8YylpLmErPUMueEIuTmooYSxyLGMpCm49aS5hCnJl
-dHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKT0w6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxw
-LG8sbixtLGwsayxqLGkKZm9yKHM9YixyPXMscT1udWxsLHA9ITA7czxjOyl7bz1DLnhCLm0oYSxzKQpp
-ZihvPT09Mzcpe249UC5ydihhLHMsITApCm09bj09bnVsbAppZihtJiZwKXtzKz0zCmNvbnRpbnVlfWlm
-KHE9PW51bGwpcT1uZXcgUC5SbigiIikKbD1DLnhCLk5qKGEscixzKQprPXEuYSs9IXA/bC50b0xvd2Vy
-Q2FzZSgpOmwKaWYobSl7bj1DLnhCLk5qKGEscyxzKzMpCmo9M31lbHNlIGlmKG49PT0iJSIpe249IiUy
-NSIKaj0xfWVsc2Ugaj0zCnEuYT1rK24Kcys9agpyPXMKcD0hMH1lbHNle2lmKG88MTI3KXttPW8+Pj40
-CmlmKG0+PTgpcmV0dXJuIEguT0goQy5lYSxtKQptPShDLmVhW21dJjE8PChvJjE1KSkhPT0wfWVsc2Ug
-bT0hMQppZihtKXtpZihwJiY2NTw9byYmOTA+PW8pe2lmKHE9PW51bGwpcT1uZXcgUC5SbigiIikKaWYo
-cjxzKXtxLmErPUMueEIuTmooYSxyLHMpCnI9c31wPSExfSsrc31lbHNle2lmKG88PTkzKXttPW8+Pj40
-CmlmKG0+PTgpcmV0dXJuIEguT0goQy5hayxtKQptPShDLmFrW21dJjE8PChvJjE1KSkhPT0wfWVsc2Ug
-bT0hMQppZihtKVAuUjMoYSxzLCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYoKG8mNjQ1MTIpPT09
-NTUyOTYmJnMrMTxjKXtpPUMueEIubShhLHMrMSkKaWYoKGkmNjQ1MTIpPT09NTYzMjApe289NjU1MzZ8
-KG8mMTAyMyk8PDEwfGkmMTAyMwpqPTJ9ZWxzZSBqPTF9ZWxzZSBqPTEKbD1DLnhCLk5qKGEscixzKQpp
-ZighcClsPWwudG9Mb3dlckNhc2UoKQppZihxPT1udWxsKXtxPW5ldyBQLlJuKCIiKQptPXF9ZWxzZSBt
-PXEKbS5hKz1sCm0uYSs9UC56WChvKQpzKz1qCnI9c319fX1pZihxPT1udWxsKXJldHVybiBDLnhCLk5q
-KGEsYixjKQppZihyPGMpe2w9Qy54Qi5OaihhLHIsYykKcS5hKz0hcD9sLnRvTG93ZXJDYXNlKCk6bH1t
-PXEuYQpyZXR1cm4gbS5jaGFyQ29kZUF0KDApPT0wP206bX0sClBpOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-cyxyLHEscAppZihiPT09YylyZXR1cm4iIgppZighUC5FdChKLnJZKGEpLlcoYSxiKSkpUC5SMyhhLGIs
-IlNjaGVtZSBub3Qgc3RhcnRpbmcgd2l0aCBhbHBoYWJldGljIGNoYXJhY3RlciIpCmZvcihzPWIscj0h
-MTtzPGM7KytzKXtxPUMueEIuVyhhLHMpCmlmKHE8MTI4KXtwPXE+Pj40CmlmKHA+PTgpcmV0dXJuIEgu
-T0goQy5tSyxwKQpwPShDLm1LW3BdJjE8PChxJjE1KSkhPT0wfWVsc2UgcD0hMQppZighcClQLlIzKGEs
-cywiSWxsZWdhbCBzY2hlbWUgY2hhcmFjdGVyIikKaWYoNjU8PXEmJnE8PTkwKXI9ITB9YT1DLnhCLk5q
-KGEsYixjKQpyZXR1cm4gUC5ZYShyP2EudG9Mb3dlckNhc2UoKTphKX0sCllhOmZ1bmN0aW9uKGEpe2lm
-KGE9PT0iaHR0cCIpcmV0dXJuImh0dHAiCmlmKGE9PT0iZmlsZSIpcmV0dXJuImZpbGUiCmlmKGE9PT0i
-aHR0cHMiKXJldHVybiJodHRwcyIKaWYoYT09PSJwYWNrYWdlIilyZXR1cm4icGFja2FnZSIKcmV0dXJu
-IGF9LAp6UjpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4iIgpyZXR1cm4gUC5QSShhLGIs
-YyxDLnRvLCExKX0sCmthOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgcyxyLHE9ZT09PSJmaWxlIixw
-PXF8fGYKaWYoYT09bnVsbCl7aWYoZD09bnVsbClyZXR1cm4gcT8iLyI6IiIKcz1ILnQ2KGQpCnI9bmV3
-IEgubEooZCxzLkMoInFVKDEpIikuYShuZXcgUC5SWigpKSxzLkMoImxKPDEscVU+IikpLkgoMCwiLyIp
-fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgiQm90aCBwYXRoIGFuZCBwYXRoU2VnbWVudHMg
-c3BlY2lmaWVkIikpCmVsc2Ugcj1QLlBJKGEsYixjLEMuV2QsITApCmlmKHIubGVuZ3RoPT09MCl7aWYo
-cSlyZXR1cm4iLyJ9ZWxzZSBpZihwJiYhQy54Qi5uKHIsIi8iKSlyPSIvIityCnJldHVybiBQLkpyKHIs
-ZSxmKX0sCkpyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1iLmxlbmd0aD09PTAKaWYocyYmIWMmJiFDLnhC
-Lm4oYSwiLyIpKXJldHVybiBQLndGKGEsIXN8fGMpCnJldHVybiBQLnhlKGEpfSwKbGU6ZnVuY3Rpb24o
-YSxiLGMsZCl7dmFyIHMscj17fQppZihhIT1udWxsKXtpZihkIT1udWxsKXRocm93IEguYihQLnhZKCJC
-b3RoIHF1ZXJ5IGFuZCBxdWVyeVBhcmFtZXRlcnMgc3BlY2lmaWVkIikpCnJldHVybiBQLlBJKGEsYixj
-LEMuVkMsITApfWlmKGQ9PW51bGwpcmV0dXJuIG51bGwKcz1uZXcgUC5SbigiIikKci5hPSIiCmQuSygw
-LG5ldyBQLnk1KG5ldyBQLk1FKHIscykpKQpyPXMuYQpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6
-cn0sCnRHOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiBudWxsCnJldHVybiBQLlBJKGEs
-YixjLEMuVkMsITApfSwKcnY6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbj1iKzIKaWYobj49
-YS5sZW5ndGgpcmV0dXJuIiUiCnM9Qy54Qi5tKGEsYisxKQpyPUMueEIubShhLG4pCnE9SC5vbyhzKQpw
-PUgub28ocikKaWYocTwwfHxwPDApcmV0dXJuIiUiCm89cSoxNitwCmlmKG88MTI3KXtuPUMuam4ud0co
-byw0KQppZihuPj04KXJldHVybiBILk9IKEMuRjMsbikKbj0oQy5GM1tuXSYxPDwobyYxNSkpIT09MH1l
-bHNlIG49ITEKaWYobilyZXR1cm4gSC5MdyhjJiY2NTw9byYmOTA+PW8/KG98MzIpPj4+MDpvKQppZihz
-Pj05N3x8cj49OTcpcmV0dXJuIEMueEIuTmooYSxiLGIrMykudG9VcHBlckNhc2UoKQpyZXR1cm4gbnVs
-bH0sCnpYOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsaz0iMDEyMzQ1Njc4OUFCQ0RFRiIK
-aWYoYTwxMjgpe3M9bmV3IFVpbnQ4QXJyYXkoMykKcj1zLmxlbmd0aAppZigwPj1yKXJldHVybiBILk9I
-KHMsMCkKc1swXT0zNwpxPUMueEIuVyhrLGE+Pj40KQppZigxPj1yKXJldHVybiBILk9IKHMsMSkKc1sx
-XT1xCnE9Qy54Qi5XKGssYSYxNSkKaWYoMj49cilyZXR1cm4gSC5PSChzLDIpCnNbMl09cX1lbHNle2lm
-KGE+MjA0NylpZihhPjY1NTM1KXtwPTI0MApvPTR9ZWxzZXtwPTIyNApvPTN9ZWxzZXtwPTE5MgpvPTJ9
-cz1uZXcgVWludDhBcnJheSgzKm8pCmZvcihyPXMubGVuZ3RoLG49MDstLW8sbz49MDtwPTEyOCl7bT1D
-LmpuLmJmKGEsNipvKSY2M3xwCmlmKG4+PXIpcmV0dXJuIEguT0gocyxuKQpzW25dPTM3CnE9bisxCmw9
-Qy54Qi5XKGssbT4+PjQpCmlmKHE+PXIpcmV0dXJuIEguT0gocyxxKQpzW3FdPWwKbD1uKzIKcT1DLnhC
-LlcoayxtJjE1KQppZihsPj1yKXJldHVybiBILk9IKHMsbCkKc1tsXT1xCm4rPTN9fXJldHVybiBQLkhN
-KHMsMCxudWxsKX0sClBJOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9UC5VbChhLGIsYyxkLGUpCnJl
-dHVybiBzPT1udWxsP0MueEIuTmooYSxiLGMpOnN9LApVbDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBz
-LHIscSxwLG8sbixtLGwsayxqPW51bGwKZm9yKHM9IWUscj1iLHE9cixwPWo7cjxjOyl7bz1DLnhCLm0o
-YSxyKQppZihvPDEyNyl7bj1vPj4+NAppZihuPj04KXJldHVybiBILk9IKGQsbikKbj0oZFtuXSYxPDwo
-byYxNSkpIT09MH1lbHNlIG49ITEKaWYobikrK3IKZWxzZXtpZihvPT09Mzcpe209UC5ydihhLHIsITEp
-CmlmKG09PW51bGwpe3IrPTMKY29udGludWV9aWYoIiUiPT09bSl7bT0iJTI1IgpsPTF9ZWxzZSBsPTN9
-ZWxzZXtpZihzKWlmKG88PTkzKXtuPW8+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5hayxuKQpuPShD
-LmFrW25dJjE8PChvJjE1KSkhPT0wfWVsc2Ugbj0hMQplbHNlIG49ITEKaWYobil7UC5SMyhhLHIsIklu
-dmFsaWQgY2hhcmFjdGVyIikKbD1qCm09bH1lbHNle2lmKChvJjY0NTEyKT09PTU1Mjk2KXtuPXIrMQpp
-ZihuPGMpe2s9Qy54Qi5tKGEsbikKaWYoKGsmNjQ1MTIpPT09NTYzMjApe289NjU1MzZ8KG8mMTAyMyk8
-PDEwfGsmMTAyMwpsPTJ9ZWxzZSBsPTF9ZWxzZSBsPTF9ZWxzZSBsPTEKbT1QLnpYKG8pfX1pZihwPT1u
-dWxsKXtwPW5ldyBQLlJuKCIiKQpuPXB9ZWxzZSBuPXAKbi5hKz1DLnhCLk5qKGEscSxyKQpuLmErPUgu
-RWoobSkKaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShsKQpyKz1sCnE9cn19aWYocD09
-bnVsbClyZXR1cm4gagppZihxPGMpcC5hKz1DLnhCLk5qKGEscSxjKQpzPXAuYQpyZXR1cm4gcy5jaGFy
-Q29kZUF0KDApPT0wP3M6c30sCnlCOmZ1bmN0aW9uKGEpe2lmKEMueEIubihhLCIuIikpcmV0dXJuITAK
-cmV0dXJuIEMueEIuT1koYSwiLy4iKSE9PS0xfSwKeGU6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxu
-LG0KaWYoIVAueUIoYSkpcmV0dXJuIGEKcz1ILlZNKFtdLHQucykKZm9yKHI9YS5zcGxpdCgiLyIpLHE9
-ci5sZW5ndGgscD0hMSxvPTA7bzxxOysrbyl7bj1yW29dCmlmKEouUk0obiwiLi4iKSl7bT1zLmxlbmd0
-aAppZihtIT09MCl7aWYoMD49bSlyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCmlmKHMubGVuZ3RoPT09
-MClDLk5tLmkocywiIil9cD0hMH1lbHNlIGlmKCIuIj09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9
-ITF9fWlmKHApQy5ObS5pKHMsIiIpCnJldHVybiBDLk5tLkgocywiLyIpfSwKd0Y6ZnVuY3Rpb24oYSxi
-KXt2YXIgcyxyLHEscCxvLG4KaWYoIVAueUIoYSkpcmV0dXJuIWI/UC5DMShhKTphCnM9SC5WTShbXSx0
-LnMpCmZvcihyPWEuc3BsaXQoIi8iKSxxPXIubGVuZ3RoLHA9ITEsbz0wO288cTsrK28pe249cltvXQpp
-ZigiLi4iPT09bilpZihzLmxlbmd0aCE9PTAmJkMuTm0uZ3JaKHMpIT09Ii4uIil7aWYoMD49cy5sZW5n
-dGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpwPSEwfWVsc2V7Qy5ObS5pKHMsIi4uIikKcD0hMX1l
-bHNlIGlmKCIuIj09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9ITF9fXI9cy5sZW5ndGgKaWYociE9
-PTApaWYocj09PTEpe2lmKDA+PXIpcmV0dXJuIEguT0gocywwKQpyPXNbMF0ubGVuZ3RoPT09MH1lbHNl
-IHI9ITEKZWxzZSByPSEwCmlmKHIpcmV0dXJuIi4vIgppZihwfHxDLk5tLmdyWihzKT09PSIuLiIpQy5O
-bS5pKHMsIiIpCmlmKCFiKXtpZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDApCkMuTm0uWShzLDAs
-UC5DMShzWzBdKSl9cmV0dXJuIEMuTm0uSChzLCIvIil9LApDMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEs
-cD1hLmxlbmd0aAppZihwPj0yJiZQLkV0KEouUXooYSwwKSkpZm9yKHM9MTtzPHA7KytzKXtyPUMueEIu
-VyhhLHMpCmlmKHI9PT01OClyZXR1cm4gQy54Qi5OaihhLDAscykrIiUzQSIrQy54Qi5HKGEscysxKQpp
-ZihyPD0xMjcpe3E9cj4+PjQKaWYocT49OClyZXR1cm4gSC5PSChDLm1LLHEpCnE9KEMubUtbcV0mMTw8
-KHImMTUpKT09PTB9ZWxzZSBxPSEwCmlmKHEpYnJlYWt9cmV0dXJuIGF9LAptbjpmdW5jdGlvbihhKXt2
-YXIgcyxyLHEscD1hLmdGaigpLG89cC5sZW5ndGgKaWYobz4wJiZKLkhtKHBbMF0pPT09MiYmSi5hNihw
-WzBdLDEpPT09NTgpe2lmKDA+PW8pcmV0dXJuIEguT0gocCwwKQpQLnJnKEouYTYocFswXSwwKSwhMSkK
-UC5ITihwLCExLDEpCnM9ITB9ZWxzZXtQLkhOKHAsITEsMCkKcz0hMX1yPWEuZ3RUKCkmJiFzPyJcXCI6
-IiIKaWYoYS5nY2ooKSl7cT1hLmdKZihhKQppZihxLmxlbmd0aCE9PTApcj1yKyJcXCIrcSsiXFwifXI9
-UC52ZyhyLHAsIlxcIikKbz1zJiZvPT09MT9yKyJcXCI6cgpyZXR1cm4gby5jaGFyQ29kZUF0KDApPT0w
-P286b30sCkloOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxCmZvcihzPTAscj0wO3I8MjsrK3Ipe3E9Qy54
-Qi5XKGEsYityKQppZig0ODw9cSYmcTw9NTcpcz1zKjE2K3EtNDgKZWxzZXtxfD0zMgppZig5Nzw9cSYm
-cTw9MTAyKXM9cyoxNitxLTg3CmVsc2UgdGhyb3cgSC5iKFAueFkoIkludmFsaWQgVVJMIGVuY29kaW5n
-IikpfX1yZXR1cm4gc30sCmt1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbz1KLnJZKGEp
-LG49Ygp3aGlsZSghMCl7aWYoIShuPGMpKXtzPSEwCmJyZWFrfXI9by5XKGEsbikKaWYocjw9MTI3KWlm
-KHIhPT0zNylxPWUmJnI9PT00MwplbHNlIHE9ITAKZWxzZSBxPSEwCmlmKHEpe3M9ITEKYnJlYWt9Kytu
-fWlmKHMpe2lmKEMueE0hPT1kKXE9ITEKZWxzZSBxPSEwCmlmKHEpcmV0dXJuIG8uTmooYSxiLGMpCmVs
-c2UgcD1uZXcgSC5xaihvLk5qKGEsYixjKSl9ZWxzZXtwPUguVk0oW10sdC5hKQpmb3Iobj1iO248Yzsr
-K24pe3I9by5XKGEsbikKaWYocj4xMjcpdGhyb3cgSC5iKFAueFkoIklsbGVnYWwgcGVyY2VudCBlbmNv
-ZGluZyBpbiBVUkkiKSkKaWYocj09PTM3KXtpZihuKzM+YS5sZW5ndGgpdGhyb3cgSC5iKFAueFkoIlRy
-dW5jYXRlZCBVUkkiKSkKQy5ObS5pKHAsUC5JaChhLG4rMSkpCm4rPTJ9ZWxzZSBpZihlJiZyPT09NDMp
-Qy5ObS5pKHAsMzIpCmVsc2UgQy5ObS5pKHAscil9fXQuTC5hKHApCnJldHVybiBDLm9FLldKKHApfSwK
-RXQ6ZnVuY3Rpb24oYSl7dmFyIHM9YXwzMgpyZXR1cm4gOTc8PXMmJnM8PTEyMn0sCktEOmZ1bmN0aW9u
-KGEsYixjKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9IkludmFsaWQgTUlNRSB0eXBlIixqPUguVk0oW2It
-MV0sdC5hKQpmb3Iocz1hLmxlbmd0aCxyPWIscT0tMSxwPW51bGw7cjxzOysrcil7cD1DLnhCLlcoYSxy
-KQppZihwPT09NDR8fHA9PT01OSlicmVhawppZihwPT09NDcpe2lmKHE8MCl7cT1yCmNvbnRpbnVlfXRo
-cm93IEguYihQLnJyKGssYSxyKSl9fWlmKHE8MCYmcj5iKXRocm93IEguYihQLnJyKGssYSxyKSkKZm9y
-KDtwIT09NDQ7KXtDLk5tLmkoaixyKTsrK3IKZm9yKG89LTE7cjxzOysrcil7cD1DLnhCLlcoYSxyKQpp
-ZihwPT09NjEpe2lmKG88MClvPXJ9ZWxzZSBpZihwPT09NTl8fHA9PT00NClicmVha31pZihvPj0wKUMu
-Tm0uaShqLG8pCmVsc2V7bj1DLk5tLmdyWihqKQppZihwIT09NDR8fHIhPT1uKzd8fCFDLnhCLlFpKGEs
-ImJhc2U2NCIsbisxKSl0aHJvdyBILmIoUC5ycigiRXhwZWN0aW5nICc9JyIsYSxyKSkKYnJlYWt9fUMu
-Tm0uaShqLHIpCm09cisxCmlmKChqLmxlbmd0aCYxKT09PTEpYT1DLmg5LnlyKGEsbSxzKQplbHNle2w9
-UC5VbChhLG0scyxDLlZDLCEwKQppZihsIT1udWxsKWE9Qy54Qi5pNyhhLG0scyxsKX1yZXR1cm4gbmV3
-IFAuUEUoYSxqLGMpfSwKS046ZnVuY3Rpb24oKXt2YXIgcz0iMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1O
-T1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXotLl9+ISQmJygpKissOz0iLHI9Ii4i
-LHE9IjoiLHA9Ii8iLG89Ij8iLG49IiMiLG09UC5kSCgyMixuZXcgUC5xMygpLHQuZ2MpLGw9bmV3IFAu
-eUkobSksaz1uZXcgUC5jNigpLGo9bmV3IFAucWQoKSxpPWwuJDIoMCwyMjUpCmsuJDMoaSxzLDEpCmsu
-JDMoaSxyLDE0KQprLiQzKGkscSwzNCkKay4kMyhpLHAsMykKay4kMyhpLG8sMTcyKQprLiQzKGksbiwy
-MDUpCmk9bC4kMigxNCwyMjUpCmsuJDMoaSxzLDEpCmsuJDMoaSxyLDE1KQprLiQzKGkscSwzNCkKay4k
-MyhpLHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDE1LDIyNSkKay4kMyhp
-LHMsMSkKay4kMyhpLCIlIiwyMjUpCmsuJDMoaSxxLDM0KQprLiQzKGkscCw5KQprLiQzKGksbywxNzIp
-CmsuJDMoaSxuLDIwNSkKaT1sLiQyKDEsMjI1KQprLiQzKGkscywxKQprLiQzKGkscSwzNCkKay4kMyhp
-LHAsMTApCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoMiwyMzUpCmsuJDMoaSxzLDEz
-OSkKay4kMyhpLHAsMTMxKQprLiQzKGksciwxNDYpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQpp
-PWwuJDIoMywyMzUpCmsuJDMoaSxzLDExKQprLiQzKGkscCw2OCkKay4kMyhpLHIsMTgpCmsuJDMoaSxv
-LDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoNCwyMjkpCmsuJDMoaSxzLDUpCmouJDMoaSwiQVoiLDIy
-OSkKay4kMyhpLHEsMTAyKQprLiQzKGksIkAiLDY4KQprLiQzKGksIlsiLDIzMikKay4kMyhpLHAsMTM4
-KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDUsMjI5KQprLiQzKGkscyw1KQpqLiQz
-KGksIkFaIiwyMjkpCmsuJDMoaSxxLDEwMikKay4kMyhpLCJAIiw2OCkKay4kMyhpLHAsMTM4KQprLiQz
-KGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDYsMjMxKQpqLiQzKGksIjE5Iiw3KQprLiQzKGks
-IkAiLDY4KQprLiQzKGkscCwxMzgpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoNywy
-MzEpCmouJDMoaSwiMDkiLDcpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxwLDEzOCkKay4kMyhpLG8sMTcy
-KQprLiQzKGksbiwyMDUpCmsuJDMobC4kMig4LDgpLCJdIiw1KQppPWwuJDIoOSwyMzUpCmsuJDMoaSxz
-LDExKQprLiQzKGksciwxNikKay4kMyhpLHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkK
-aT1sLiQyKDE2LDIzNSkKay4kMyhpLHMsMTEpCmsuJDMoaSxyLDE3KQprLiQzKGkscCwyMzQpCmsuJDMo
-aSxvLDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoMTcsMjM1KQprLiQzKGkscywxMSkKay4kMyhpLHAs
-OSkKay4kMyhpLG8sMTcyKQprLiQzKGksbiwyMDUpCmk9bC4kMigxMCwyMzUpCmsuJDMoaSxzLDExKQpr
-LiQzKGksciwxOCkKay4kMyhpLHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQy
-KDE4LDIzNSkKay4kMyhpLHMsMTEpCmsuJDMoaSxyLDE5KQprLiQzKGkscCwyMzQpCmsuJDMoaSxvLDE3
-MikKay4kMyhpLG4sMjA1KQppPWwuJDIoMTksMjM1KQprLiQzKGkscywxMSkKay4kMyhpLHAsMjM0KQpr
-LiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDExLDIzNSkKay4kMyhpLHMsMTEpCmsuJDMo
-aSxwLDEwKQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDEyLDIzNikKay4kMyhpLHMs
-MTIpCmsuJDMoaSxvLDEyKQprLiQzKGksbiwyMDUpCmk9bC4kMigxMywyMzcpCmsuJDMoaSxzLDEzKQpr
-LiQzKGksbywxMykKai4kMyhsLiQyKDIwLDI0NSksImF6IiwyMSkKaT1sLiQyKDIxLDI0NSkKai4kMyhp
-LCJheiIsMjEpCmouJDMoaSwiMDkiLDIxKQprLiQzKGksIistLiIsMjEpCnJldHVybiBtfSwKVUI6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG49JC52WigpCmZvcihzPUouclkoYSkscj1iO3I8
-YzsrK3Ipe2lmKGQ8MHx8ZD49bi5sZW5ndGgpcmV0dXJuIEguT0gobixkKQpxPW5bZF0KcD1zLlcoYSxy
-KV45NgppZihwPjk1KXA9MzEKaWYocD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSxwKQpvPXFbcF0KZD1v
-JjMxCkMuTm0uWShlLG8+Pj41LHIpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCmlQOmZ1bmN0aW9uIGlQKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApYUzpmdW5j
-dGlvbiBYUygpe30sCkM2OmZ1bmN0aW9uIEM2KGEpe3RoaXMuYT1hfSwKRXo6ZnVuY3Rpb24gRXooKXt9
-LApuOmZ1bmN0aW9uIG4oKXt9LAp1OmZ1bmN0aW9uIHUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpf
-LmI9YgpfLmM9YwpfLmQ9ZH0sCmJKOmZ1bmN0aW9uIGJKKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8u
-ZT1hCl8uZj1iCl8uYT1jCl8uYj1kCl8uYz1lCl8uZD1mfSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxl
-KXt2YXIgXz10aGlzCl8uZj1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAo
-YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHVi
-KGEpe3RoaXMuYT1hfSwKZHM6ZnVuY3Rpb24gZHMoYSl7dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihh
-KXt0aGlzLmE9YX0sClVWOmZ1bmN0aW9uIFVWKGEpe3RoaXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9
-LApLWTpmdW5jdGlvbiBLWSgpe30sCmM6ZnVuY3Rpb24gYyhhKXt0aGlzLmE9YX0sCkNEOmZ1bmN0aW9u
-IENEKGEpe3RoaXMuYT1hfSwKYUU6ZnVuY3Rpb24gYUUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRo
-aXMuYz1jfSwKY1g6ZnVuY3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCk4zOmZ1bmN0aW9u
-IE4zKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKYzg6ZnVuY3Rpb24gYzgoKXt9
-LApNaDpmdW5jdGlvbiBNaCgpe30sClpkOmZ1bmN0aW9uIFpkKCl7fSwKUm46ZnVuY3Rpb24gUm4oYSl7
-dGhpcy5hPWF9LApuMTpmdW5jdGlvbiBuMShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3Ro
-aXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMoYSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbiBKVChhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVuY3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpf
-LmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVs
-bH0sClJaOmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
-Yn0sCnk1OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMu
-YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShh
-KXt0aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5j
-dGlvbiBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQK
-Xy5lPWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUs
-ZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8u
-UT1fLno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApqZzpmdW5jdGlvbiBqZyhhLGIp
-e3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
-CkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBczpmdW5jdGlvbiBBcygpe30s
-CkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24gTjcoYSxiKXt0aGlzLmE9YQp0
-aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApSNDpmdW5jdGlv
-bihhLGIsYyxkKXt2YXIgcyxyLHEKSC55OChiKQp0LmIuYShkKQppZihILm9UKGIpKXtzPVtjXQpDLk5t
-LkZWKHMsZCkKZD1zfXI9dC56CnE9UC5DSChKLk0xKGQsUC53MCgpLHIpLCEwLHIpCnQuWS5hKGEpCnJl
-dHVybiBQLndZKEguRWsoYSxxLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwp0cnl7aWYo
-T2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2Fs
-bChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNo
-KHMpe0guUnUocyl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lmKE9iamVjdC5wcm90b3R5cGUu
-aGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVybiBudWxsfSwKd1k6ZnVuY3Rp
-b24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fEgu
-bChhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0
-dXJuIGEKaWYodC5FLmIoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIEgubzIo
-YSkKaWYodC5ZLmIoYSkpcmV0dXJuIFAuaEUoYSwiJGRhcnRfanNGdW5jdGlvbiIsbmV3IFAuUEMoKSkK
-cmV0dXJuIFAuaEUoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcgUC5tdCgkLmtJKCkpKX0sCmhFOmZ1bmN0
-aW9uKGEsYixjKXt2YXIgcz1QLk9tKGEsYikKaWYocz09bnVsbCl7cz1jLiQxKGEpClAuRG0oYSxiLHMp
-fXJldHVybiBzfSwKZFU6ZnVuY3Rpb24oYSl7dmFyIHMscgppZihhPT1udWxsfHx0eXBlb2YgYT09InN0
-cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gYQplbHNl
-IGlmKGEgaW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNl
-b2YgT2JqZWN0JiZ0LkUuYihhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBEYXRlKXtzPUgu
-dVAoYS5nZXRUaW1lKCkpCmlmKE1hdGguYWJzKHMpPD04NjRlMTMpcj0hMQplbHNlIHI9ITAKaWYocilI
-LnZoKFAueFkoIkRhdGVUaW1lIGlzIG91dHNpZGUgdmFsaWQgcmFuZ2U6ICIrcykpClAuVUkoITEsImlz
-VXRjIix0LnkpCnJldHVybiBuZXcgUC5pUChzLCExKX1lbHNlIGlmKGEuY29uc3RydWN0b3I9PT0kLmtJ
-KCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVuY3Rpb24oYSl7aWYodHlwZW9m
-IGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLncoKSxuZXcgUC5OeigpKQppZihhIGluc3RhbmNl
-b2YgQXJyYXkpcmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAuUVMoKSkKcmV0dXJuIFAuaVEoYSwkLlI4
-KCksbmV3IFAubnAoKSl9LAppUTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9UC5PbShhLGIpCmlmKHM9PW51
-bGx8fCEoYSBpbnN0YW5jZW9mIE9iamVjdCkpe3M9Yy4kMShhKQpQLkRtKGEsYixzKX1yZXR1cm4gc30s
-ClBDOmZ1bmN0aW9uIFBDKCl7fSwKbXQ6ZnVuY3Rpb24gbXQoYSl7dGhpcy5hPWF9LApOejpmdW5jdGlv
-biBOeigpe30sClFTOmZ1bmN0aW9uIFFTKCl7fSwKbnA6ZnVuY3Rpb24gbnAoKXt9LApFNDpmdW5jdGlv
-biBFNChhKXt0aGlzLmE9YX0sCnI3OmZ1bmN0aW9uIHI3KGEpe3RoaXMuYT1hfSwKVHo6ZnVuY3Rpb24g
-VHooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY286ZnVuY3Rpb24gY28oKXt9LApiQjpmdW5jdGlv
-biBiQigpe30sCktlOmZ1bmN0aW9uIEtlKGEpe3RoaXMuYT1hfSwKZDU6ZnVuY3Rpb24gZDUoKXt9fSxX
-PXsKeDM6ZnVuY3Rpb24oKXtyZXR1cm4gd2luZG93fSwKWnI6ZnVuY3Rpb24oKXtyZXR1cm4gZG9jdW1l
-bnR9LApKNjpmdW5jdGlvbihhKXt2YXIgcz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJhIikKaWYoYSE9
-bnVsbClDLnhuLnNMVShzLGEpCnJldHVybiBzfSwKVTk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHI9ZG9j
-dW1lbnQuYm9keQpyLnRvU3RyaW5nCnM9Qy5SWS5yNihyLGEsYixjKQpzLnRvU3RyaW5nCnI9dC5hYwpy
-PW5ldyBILlU1KG5ldyBXLmU3KHMpLHIuQygiYTIobEQuRSkiKS5hKG5ldyBXLkN2KCkpLHIuQygiVTU8
-bEQuRT4iKSkKcmV0dXJuIHQuaC5hKHIuZ3I4KHIpKX0sCnJTOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT0i
-ZWxlbWVudCB0YWcgdW5hdmFpbGFibGUiCnRyeXtzPUouWUUoYSkKaWYodHlwZW9mIHMuZ25zKGEpPT0i
-c3RyaW5nIilxPXMuZ25zKGEpfWNhdGNoKHIpe0guUnUocil9cmV0dXJuIHF9LApDMDpmdW5jdGlvbihh
-LGIpe2E9NTM2ODcwOTExJmErYgphPTUzNjg3MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0dXJuIGFe
-YT4+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcz1XLkMwKFcuQzAoVy5DMChXLkMwKDAsYSks
-YiksYyksZCkscj01MzY4NzA5MTEmcysoKDY3MTA4ODYzJnMpPDwzKQpyXj1yPj4+MTEKcmV0dXJuIDUz
-Njg3MDkxMSZyKygoMTYzODMmcik8PDE1KX0sClROOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPWEuY2xh
-c3NMaXN0CmZvcihzPWIubGVuZ3RoLHI9MDtyPGIubGVuZ3RoO2IubGVuZ3RoPT09c3x8KDAsSC5sayko
-YiksKytyKXEuYWRkKGJbcl0pfSwKSkU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcz1XLmFGKG5ldyBX
-LnZOKGMpLHQuQikKaWYocyE9bnVsbCYmITApSi5kWihhLGIscywhMSkKcmV0dXJuIG5ldyBXLnhDKGEs
-YixzLCExLGUuQygieEM8MD4iKSl9LApUdzpmdW5jdGlvbihhKXt2YXIgcz1XLko2KG51bGwpLHI9d2lu
-ZG93LmxvY2F0aW9uCnM9bmV3IFcuSlEobmV3IFcubWsocyxyKSkKcy5DWShhKQpyZXR1cm4gc30sCnFE
-OmZ1bmN0aW9uKGEsYixjLGQpe3QuaC5hKGEpCkguaChiKQpILmgoYykKdC5jci5hKGQpCnJldHVybiEw
-fSwKUVc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxCnQuaC5hKGEpCkguaChiKQpILmgoYykKcz10
-LmNyLmEoZCkuYQpyPXMuYQpDLnhuLnNMVShyLGMpCnE9ci5ob3N0bmFtZQpzPXMuYgppZighKHE9PXMu
-aG9zdG5hbWUmJnIucG9ydD09cy5wb3J0JiZyLnByb3RvY29sPT1zLnByb3RvY29sKSlpZihxPT09IiIp
-aWYoci5wb3J0PT09IiIpe3M9ci5wcm90b2NvbApzPXM9PT0iOiJ8fHM9PT0iIn1lbHNlIHM9ITEKZWxz
-ZSBzPSExCmVsc2Ugcz0hMApyZXR1cm4gc30sCkJsOmZ1bmN0aW9uKCl7dmFyIHM9dC5OLHI9UC50TShD
-LlF4LHMpLHE9dC5kMC5hKG5ldyBXLklBKCkpLHA9SC5WTShbIlRFTVBMQVRFIl0sdC5zKQpzPW5ldyBX
-LmN0KHIsUC5McyhzKSxQLkxzKHMpLFAuTHMocyksbnVsbCkKcy5DWShudWxsLG5ldyBILmxKKEMuUXgs
-cSx0LmZqKSxwLG51bGwpCnJldHVybiBzfSwKUHY6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4g
-bnVsbApyZXR1cm4gVy5QMShhKX0sCnFjOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKGE9PW51bGwpcmV0dXJu
-IG51bGwKaWYoInBvc3RNZXNzYWdlIiBpbiBhKXtzPVcuUDEoYSkKaWYodC5hUy5iKHMpKXJldHVybiBz
-CnJldHVybiBudWxsfWVsc2UgcmV0dXJuIHQuY2guYShhKX0sClAxOmZ1bmN0aW9uKGEpe2lmKGE9PT13
-aW5kb3cpcmV0dXJuIHQuY2kuYShhKQplbHNlIHJldHVybiBuZXcgVy5kVyhhKX0sCkhIOmZ1bmN0aW9u
-KGEpe2lmKGE9PT13aW5kb3cubG9jYXRpb24pcmV0dXJuIGEKZWxzZSByZXR1cm4gbmV3IFcuRmIoKX0s
-CmFGOmZ1bmN0aW9uKGEsYil7dmFyIHM9JC5YMwppZihzPT09Qy5OVSlyZXR1cm4gYQpyZXR1cm4gcy5Q
-eShhLGIpfSwKcUU6ZnVuY3Rpb24gcUUoKXt9LApHaDpmdW5jdGlvbiBHaCgpe30sCmZZOmZ1bmN0aW9u
-IGZZKCl7fSwKbkI6ZnVuY3Rpb24gbkIoKXt9LApBejpmdW5jdGlvbiBBeigpe30sClFQOmZ1bmN0aW9u
-IFFQKCl7fSwKbng6ZnVuY3Rpb24gbngoKXt9LApvSjpmdW5jdGlvbiBvSigpe30sCmlkOmZ1bmN0aW9u
-IGlkKCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9LApOaDpmdW5jdGlvbiBOaCgpe30sCmFlOmZ1bmN0aW9u
-IGFlKCl7fSwKSUI6ZnVuY3Rpb24gSUIoKXt9LApuNzpmdW5jdGlvbiBuNygpe30sCnd6OmZ1bmN0aW9u
-IHd6KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCmN2OmZ1bmN0aW9uIGN2KCl7fSwKQ3Y6ZnVuY3Rp
-b24gQ3YoKXt9LAplYTpmdW5jdGlvbiBlYSgpe30sCkQwOmZ1bmN0aW9uIEQwKCl7fSwKaEg6ZnVuY3Rp
-b24gaEgoKXt9LApoNDpmdW5jdGlvbiBoNCgpe30sCmJyOmZ1bmN0aW9uIGJyKCl7fSwKVmI6ZnVuY3Rp
-b24gVmIoKXt9LApmSjpmdW5jdGlvbiBmSigpe30sCndhOmZ1bmN0aW9uIHdhKCl7fSwKU2c6ZnVuY3Rp
-b24gU2coKXt9LAp1ODpmdW5jdGlvbiB1OCgpe30sCkFqOmZ1bmN0aW9uIEFqKCl7fSwKZTc6ZnVuY3Rp
-b24gZTcoYSl7dGhpcy5hPWF9LAp1SDpmdW5jdGlvbiB1SCgpe30sCkJIOmZ1bmN0aW9uIEJIKCl7fSwK
-U046ZnVuY3Rpb24gU04oKXt9LApldzpmdW5jdGlvbiBldygpe30sCmxwOmZ1bmN0aW9uIGxwKCl7fSwK
-VGI6ZnVuY3Rpb24gVGIoKXt9LApJdjpmdW5jdGlvbiBJdigpe30sCldQOmZ1bmN0aW9uIFdQKCl7fSwK
-eVk6ZnVuY3Rpb24geVkoKXt9LAp3NjpmdW5jdGlvbiB3Nigpe30sCks1OmZ1bmN0aW9uIEs1KCl7fSwK
-Q206ZnVuY3Rpb24gQ20oKXt9LApDUTpmdW5jdGlvbiBDUSgpe30sCnc0OmZ1bmN0aW9uIHc0KCl7fSwK
-cmg6ZnVuY3Rpb24gcmgoKXt9LApjZjpmdW5jdGlvbiBjZigpe30sCmk3OmZ1bmN0aW9uIGk3KGEpe3Ro
-aXMuYT1hfSwKU3k6ZnVuY3Rpb24gU3koYSl7dGhpcy5hPWF9LApLUzpmdW5jdGlvbiBLUyhhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKQTM6ZnVuY3Rpb24gQTMoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkk0
-OmZ1bmN0aW9uIEk0KGEpe3RoaXMuYT1hfSwKRms6ZnVuY3Rpb24gRmsoYSxiKXt0aGlzLmE9YQp0aGlz
-LiR0aT1ifSwKUk86ZnVuY3Rpb24gUk8oYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9
-YwpfLiR0aT1kfSwKZXU6ZnVuY3Rpb24gZXUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9Ygpf
-LmM9YwpfLiR0aT1kfSwKeEM6ZnVuY3Rpb24geEMoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYj1hCl8u
-Yz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2TjpmdW5jdGlvbiB2TihhKXt0aGlzLmE9YX0sCkpROmZ1
-bmN0aW9uIEpRKGEpe3RoaXMuYT1hfSwKR206ZnVuY3Rpb24gR20oKXt9LAp2RDpmdW5jdGlvbiB2RChh
-KXt0aGlzLmE9YX0sClV2OmZ1bmN0aW9uIFV2KGEpe3RoaXMuYT1hfSwKRWc6ZnVuY3Rpb24gRWcoYSxi
-LGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKbTY6ZnVuY3Rpb24gbTYoKXt9LApFbzpmdW5j
-dGlvbiBFbygpe30sCldrOmZ1bmN0aW9uIFdrKCl7fSwKY3Q6ZnVuY3Rpb24gY3QoYSxiLGMsZCxlKXt2
-YXIgXz10aGlzCl8uZT1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKSUE6ZnVuY3Rpb24gSUEoKXt9
-LApPdzpmdW5jdGlvbiBPdygpe30sClc5OmZ1bmN0aW9uIFc5KGEsYixjKXt2YXIgXz10aGlzCl8uYT1h
-Cl8uYj1iCl8uYz0tMQpfLmQ9bnVsbApfLiR0aT1jfSwKZFc6ZnVuY3Rpb24gZFcoYSl7dGhpcy5hPWF9
-LApGYjpmdW5jdGlvbiBGYigpe30sCm1rOmZ1bmN0aW9uIG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
-LApLbzpmdW5jdGlvbiBLbyhhKXt0aGlzLmE9YQp0aGlzLmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0
-aGlzLmE9YX0sCkxlOmZ1bmN0aW9uIExlKCl7fSwKSzc6ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlv
-biByQigpe30sClhXOmZ1bmN0aW9uIFhXKCl7fSwKb2E6ZnVuY3Rpb24gb2EoKXt9fSxNPXsKT1g6ZnVu
-Y3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5BZDpyZXR1cm4iQWRkIC8qPyovIGhpbnQiCmNhc2UgQy5u
-ZTpyZXR1cm4iQWRkIC8qISovIGhpbnQiCmNhc2UgQy53VjpyZXR1cm4iUmVtb3ZlIC8qPyovIGhpbnQi
-CmNhc2UgQy5mUjpyZXR1cm4iUmVtb3ZlIC8qISovIGhpbnQiCmNhc2UgQy5teTpyZXR1cm4iQ2hhbmdl
-IHRvIC8qPyovIGhpbnQiCmNhc2UgQy5yeDpyZXR1cm4iQ2hhbmdlIHRvIC8qISovIGhpbnQifXJldHVy
-biBudWxsfSwKSDc6ZnVuY3Rpb24gSDcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllGOmZ1bmN0aW9u
-KGEsYil7dmFyIHMscixxLHAsbyxuLG0sbApmb3Iocz1iLmxlbmd0aCxyPTE7cjxzOysrcil7aWYoYlty
-XT09bnVsbHx8YltyLTFdIT1udWxsKWNvbnRpbnVlCmZvcig7cz49MTtzPXEpe3E9cy0xCmlmKGJbcV0h
-PW51bGwpYnJlYWt9cD1uZXcgUC5SbigiIikKbz1hKyIoIgpwLmE9bwpuPUgudDYoYikKbT1uLkMoIm5I
-PDE+IikKbD1uZXcgSC5uSChiLDAscyxtKQpsLkhkKGIsMCxzLG4uYykKbT1vK25ldyBILmxKKGwsbS5D
-KCJxVShhTC5FKSIpLmEobmV3IE0uTm8oKSksbS5DKCJsSjxhTC5FLHFVPiIpKS5IKDAsIiwgIikKcC5h
-PW0KcC5hPW0rKCIpOiBwYXJ0ICIrKHItMSkrIiB3YXMgbnVsbCwgYnV0IHBhcnQgIityKyIgd2FzIG5v
-dC4iKQp0aHJvdyBILmIoUC54WShwLncoMCkpKX19LApsSTpmdW5jdGlvbiBsSShhKXt0aGlzLmE9YX0s
-CnE3OmZ1bmN0aW9uIHE3KCl7fSwKTm86ZnVuY3Rpb24gTm8oKXt9fSxVPXsKbno6ZnVuY3Rpb24oYSl7
-dmFyIHM9SC51UChhLnEoMCwibm9kZUlkIikpCnJldHVybiBuZXcgVS5MTChDLk5tLkh0KEMucmssbmV3
-IFUuTUQoYSkpLHMpfSwKTEw6ZnVuY3Rpb24gTEwoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1EOmZ1
-bmN0aW9uIE1EKGEpe3RoaXMuYT1hfSwKamY6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAKaWYoYT09bnVs
-bClzPW51bGwKZWxzZXtzPUguVk0oW10sdC5kNykKZm9yKHI9Si5JVCh0LlUuYShhKSk7ci5GKCk7KXtx
-PXIuZ2woKQpwPUouVTYocSkKQy5ObS5pKHMsbmV3IFUuU2UoSC5oKHAucShxLCJkZXNjcmlwdGlvbiIp
-KSxILmgocC5xKHEsImhyZWYiKSkpKX19cmV0dXJuIHN9LApOZDpmdW5jdGlvbihhKXt2YXIgcyxyCmlm
-KGE9PW51bGwpcz1udWxsCmVsc2V7cz1ILlZNKFtdLHQuYUEpCmZvcihyPUouSVQodC5VLmEoYSkpO3Iu
-RigpOylDLk5tLmkocyxVLk5mKHIuZ2woKSkpfXJldHVybiBzfSwKTmY6ZnVuY3Rpb24oYSl7dmFyIHM9
-Si5VNihhKSxyPUguaChzLnEoYSwiZGVzY3JpcHRpb24iKSkscT1ILlZNKFtdLHQuYUopCmZvcihzPUou
-SVQodC5VLmEocy5xKGEsImVudHJpZXMiKSkpO3MuRigpOylDLk5tLmkocSxVLlJqKHMuZ2woKSkpCnJl
-dHVybiBuZXcgVS55RChyLHEpfSwKUmo6ZnVuY3Rpb24oYSl7dmFyIHMscj1KLlU2KGEpLHE9SC5oKHIu
-cShhLCJkZXNjcmlwdGlvbiIpKSxwPUguaChyLnEoYSwiZnVuY3Rpb24iKSksbz1yLnEoYSwibGluayIp
-CmlmKG89PW51bGwpbz1udWxsCmVsc2V7cz1KLlU2KG8pCm89bmV3IFUuTWwoSC5oKHMucShvLCJocmVm
-IikpLEgudVAocy5xKG8sImxpbmUiKSksSC5oKHMucShvLCJwYXRoIikpKX1yPXQuZksuYShyLnEoYSwi
-aGludEFjdGlvbnMiKSkKcj1yPT1udWxsP251bGw6Si5NMShyLG5ldyBVLmFOKCksdC5hWCkKcj1yPT1u
-dWxsP251bGw6UC5DSChyLCEwLHIuJHRpLkMoImFMLkUiKSkKcmV0dXJuIG5ldyBVLndiKHEscCxvLHI9
-PW51bGw/Qy5kbjpyKX0sCmQyOmZ1bmN0aW9uIGQyKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1h
-Cl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKU2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9
-YQp0aGlzLmI9Yn0sCk1sOmZ1bmN0aW9uIE1sKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
-Y30sCnlEOmZ1bmN0aW9uIHlEKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp3YjpmdW5jdGlvbiB3Yihh
-LGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKYU46ZnVuY3Rpb24gYU4o
-KXt9LApiMDpmdW5jdGlvbiBiMCgpe319LEI9ewp3UjpmdW5jdGlvbigpe3JldHVybiBuZXcgQi5xcCgi
-IiwiIiwiIixDLkR4KX0sCllmOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsaz1ILmgoYS5x
-KDAsInJlZ2lvbnMiKSksaj1ILmgoYS5xKDAsIm5hdmlnYXRpb25Db250ZW50IikpLGk9SC5oKGEucSgw
-LCJzb3VyY2VDb2RlIikpLGg9UC5GbCh0LlgsdC5kXykKZm9yKHM9dC50LmEoYS5xKDAsImVkaXRzIikp
-LHM9cy5nUHUocykscz1zLmdreihzKSxyPXQuVSxxPXQuaDQ7cy5GKCk7KXtwPXMuZ2woKQpvPXAuYQpu
-PUguVk0oW10scSkKZm9yKHA9Si5JVChyLmEocC5iKSk7cC5GKCk7KXttPXAuZ2woKQpsPUouVTYobSkK
-Qy5ObS5pKG4sbmV3IEIuajgoSC51UChsLnEobSwibGluZSIpKSxILmgobC5xKG0sImV4cGxhbmF0aW9u
-IikpLEgudVAobC5xKG0sIm9mZnNldCIpKSkpfWguWSgwLG8sbil9cmV0dXJuIG5ldyBCLnFwKGssaixp
-LGgpfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6
-ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmZ2
-OmZ1bmN0aW9uIGZ2KCl7fSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIShhPj02NSYmYTw9OTApKXM9
-YT49OTcmJmE8PTEyMgplbHNlIHM9ITAKcmV0dXJuIHN9LApZdTpmdW5jdGlvbihhLGIpe3ZhciBzPWEu
-bGVuZ3RoLHI9YisyCmlmKHM8cilyZXR1cm4hMQppZighQi5PUyhDLnhCLm0oYSxiKSkpcmV0dXJuITEK
-aWYoQy54Qi5tKGEsYisxKSE9PTU4KXJldHVybiExCmlmKHM9PT1yKXJldHVybiEwCnJldHVybiBDLnhC
-Lm0oYSxyKT09PTQ3fX0sVD17bVE6ZnVuY3Rpb24gbVEoKXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJa
-LkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2FkZWQiLG5ldyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9w
-c3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5jdGlvbihhKXt2YXIgcyxyPXQuZy5hKGEucGFyZW50Tm9k
-ZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4gdWwiKSxxPXIuc3R5bGUscD0iIitDLkNELnpRKHIub2Zm
-c2V0SGVpZ2h0KSoyKyJweCIKcS5tYXhIZWlnaHQ9cApxPUoucUYoYSkKcD1xLiR0aQpzPXAuQygifigx
-KT8iKS5hKG5ldyBMLld4KHIsYSkpCnQuWi5hKG51bGwpClcuSkUocS5hLHEuYixzLCExLHAuYyl9LAp5
-WDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPSJxdWVyeVNlbGVjdG9yQWxsIixsPWRvY3Vt
-ZW50LnF1ZXJ5U2VsZWN0b3IoYSksaz10LmcKbC50b1N0cmluZwpzPXQuaApILkRoKGsscywiVCIsbSkK
-cj10LlIKcT1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5uYXYtbGluayIpLHIpCnEuSyhxLG5l
-dyBMLkFPKGIpKQpILkRoKGsscywiVCIsbSkKcD1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5y
-ZWdpb24iKSxyKQppZihwLmdBKHApIT09MCl7bz1sLnF1ZXJ5U2VsZWN0b3IoInRhYmxlW2RhdGEtcGF0
-aF0iKQpvLnRvU3RyaW5nCnAuSyhwLG5ldyBMLkhvKG8uZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcu
-U3kobmV3IFcuaTcobykpLk8oInBhdGgiKSkpKX1ILkRoKGsscywiVCIsbSkKbj1uZXcgVy53eihsLnF1
-ZXJ5U2VsZWN0b3JBbGwoIi5hZGQtaGludC1saW5rIikscikKbi5LKG4sbmV3IEwuSUMoKSl9LApRNjpm
-dW5jdGlvbihhLGIsYyl7dmFyIHM9bmV3IFhNTEh0dHBSZXF1ZXN0KCkKQy5EdC5lbyhzLCJHRVQiLEwu
-UTQoYSxiKSwhMCkKcy5zZXRSZXF1ZXN0SGVhZGVyKCJDb250ZW50LVR5cGUiLCJhcHBsaWNhdGlvbi9q
-c29uOyBjaGFyc2V0PVVURi04IikKcmV0dXJuIEwuTFUocyxudWxsLGMuQygiMCoiKSl9LAp0eTpmdW5j
-dGlvbihhLGIpe3ZhciBzPW5ldyBYTUxIdHRwUmVxdWVzdCgpLHI9dC5YCkMuRHQuZW8ocywiUE9TVCIs
-TC5RNChhLFAuRmwocixyKSksITApCnMuc2V0UmVxdWVzdEhlYWRlcigiQ29udGVudC1UeXBlIiwiYXBw
-bGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCIpCnJldHVybiBMLkxVKHMsYix0LnQpfSwKTFU6ZnVu
-Y3Rpb24oYSxiLGMpe3JldHVybiBMLlRnKGEsYixjLGMuQygiMCoiKSl9LApUZzpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgcz0wLHI9UC5GWChkKSxxLHA9MixvLG49W10sbSxsLGssaixpLGgsZyxmCnZhciAkYXN5
-bmMkTFU9UC5seihmdW5jdGlvbihlLGEwKXtpZihlPT09MSl7bz1hMApzPXB9d2hpbGUodHJ1ZSlzd2l0
-Y2gocyl7Y2FzZSAwOmk9bmV3IFAuWmYobmV3IFAudnMoJC5YMyx0LmdWKSx0LmJDKQpoPXQuZWIKZz1o
-LmEobmV3IEwuZkMoaSxhKSkKdC5aLmEobnVsbCkKbD10LmVRClcuSkUoYSwibG9hZCIsZywhMSxsKQpX
-LkpFKGEsImVycm9yIixoLmEoaS5nWUooKSksITEsbCkKYS5zZW5kKGI9PW51bGw/bnVsbDpDLkN0Lk9C
-KGIsbnVsbCkpCnA9NApzPTcKcmV0dXJuIFAualEoaS5hLCRhc3luYyRMVSkKY2FzZSA3OnA9MgpzPTYK
-YnJlYWsKY2FzZSA0OnA9MwpmPW8KSC5SdShmKQptPUgudHMoZikKaD1QLlRsKCJFcnJvciByZWFjaGlu
-ZyBtaWdyYXRpb24gcHJldmlldyBzZXJ2ZXIuIixtKQp0aHJvdyBILmIoaCkKcz02CmJyZWFrCmNhc2Ug
-MzpzPTIKYnJlYWsKY2FzZSA2Omo9Qy5DdC5wVygwLGEucmVzcG9uc2VUZXh0LG51bGwpCmlmKGEuc3Rh
-dHVzPT09MjAwKXtxPWMuQygiMCoiKS5hKGopCnM9MQpicmVha31lbHNlIHRocm93IEguYihqKQpjYXNl
-IDE6cmV0dXJuIFAueUMocSxyKQpjYXNlIDI6cmV0dXJuIFAuZjMobyxyKX19KQpyZXR1cm4gUC5ESSgk
-YXN5bmMkTFUscil9LAphSzpmdW5jdGlvbihhKXt2YXIgcz1QLmhLKGEpLmdoWSgpLnEoMCwibGluZSIp
-CnJldHVybiBzPT1udWxsP251bGw6SC5IcChzLG51bGwpfSwKRzY6ZnVuY3Rpb24oYSl7dmFyIHM9UC5o
-SyhhKS5naFkoKS5xKDAsIm9mZnNldCIpCnJldHVybiBzPT1udWxsP251bGw6SC5IcChzLG51bGwpfSwK
-aTY6ZnVuY3Rpb24oYSl7cmV0dXJuIEwublcodC5PLmEoYSkpfSwKblc6ZnVuY3Rpb24oYSl7dmFyIHM9
-MCxyPVAuRlgodC56KSxxPTEscCxvPVtdLG4sbSxsLGssagp2YXIgJGFzeW5jJGk2PVAubHooZnVuY3Rp
-b24oYixjKXtpZihiPT09MSl7cD1jCnM9cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6az10Lmcu
-YShXLnFjKGEuY3VycmVudFRhcmdldCkpLmdldEF0dHJpYnV0ZSgiaHJlZiIpCmEucHJldmVudERlZmF1
-bHQoKQpxPTMKcz02CnJldHVybiBQLmpRKEwudHkoayxudWxsKSwkYXN5bmMkaTYpCmNhc2UgNjp0LmJa
-LmEoSi5HcihXLlB2KGRvY3VtZW50LmRlZmF1bHRWaWV3KSkpLnJlbG9hZCgpCnE9MQpzPTUKYnJlYWsK
-Y2FzZSAzOnE9MgpqPXAKbj1ILlJ1KGopCm09SC50cyhqKQpMLkMyKCJDb3VsZCBub3QgYWRkL3JlbW92
-ZSBoaW50IixuLG0pCnM9NQpicmVhawpjYXNlIDI6cz0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55Qyhu
-dWxsLHIpCmNhc2UgMTpyZXR1cm4gUC5mMyhwLHIpfX0pCnJldHVybiBQLkRJKCRhc3luYyRpNixyKX0s
-CkMyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD0iZXhjZXB0aW9uIixvPSJzdGFja1RyYWNlIixu
-PXQudC5iKGIpJiZKLlJNKGIucSgwLCJzdWNjZXNzIiksITEpJiZiLng0KHApJiZiLng0KG8pLG09Si5p
-YShiKQppZihuKXtzPUguaChtLnEoYixwKSkKYz1tLnEoYixvKX1lbHNlIHM9bS53KGIpCm49ZG9jdW1l
-bnQKcj1uLnF1ZXJ5U2VsZWN0b3IoIi5wb3B1cC1wYW5lIikKci5xdWVyeVNlbGVjdG9yKCJoMiIpLmlu
-bmVyVGV4dD1hCnIucXVlcnlTZWxlY3RvcigicCIpLmlubmVyVGV4dD1zCnIucXVlcnlTZWxlY3Rvcigi
-cHJlIikuaW5uZXJUZXh0PUouaihjKQptPXQuZGQuYShyLnF1ZXJ5U2VsZWN0b3IoImEuYm90dG9tIikp
-CnE9dC5YOyhtJiZDLnhuKS5zTFUobSxQLlhkKCJodHRwcyIsImdpdGh1Yi5jb20iLCJkYXJ0LWxhbmcv
-c2RrL2lzc3Vlcy9uZXciLFAuRUYoWyJ0aXRsZSIsIkN1c3RvbWVyLXJlcG9ydGVkIGlzc3VlIHdpdGgg
-Tk5CRCBtaWdyYXRpb24gdG9vbDogIithLCJsYWJlbHMiLHUuZCwiYm9keSIsYSsiXG5cbkVycm9yOiAi
-K0guRWoocykrIlxuXG5QbGVhc2UgZmlsbCBpbiB0aGUgZm9sbG93aW5nOlxuXG4qKk5hbWUgb2YgcGFj
-a2FnZSBiZWluZyBtaWdyYXRlZCAoaWYgcHVibGljKSoqOlxuKipXaGF0IEkgd2FzIGRvaW5nIHdoZW4g
-dGhpcyBpc3N1ZSBvY2N1cnJlZCoqOlxuKipJcyBpdCBwb3NzaWJsZSB0byB3b3JrIGFyb3VuZCB0aGlz
-IGlzc3VlKio6XG4qKkhhcyB0aGlzIGlzc3VlIGhhcHBlbmVkIGJlZm9yZSwgYW5kIGlmIHNvLCBob3cg
-b2Z0ZW4qKjpcbioqRGFydCBTREsgdmVyc2lvbioqOiAiK0guRWoobi5nZXRFbGVtZW50QnlJZCgic2Rr
-LXZlcnNpb24iKS50ZXh0Q29udGVudCkrIlxuKipBZGRpdGlvbmFsIGRldGFpbHMqKjpcblxuVGhhbmtz
-IGZvciBmaWxpbmchXG5cblN0YWNrdHJhY2U6IF9hdXRvIHBvcHVsYXRlZCBieSBtaWdyYXRpb24gcHJl
-dmlldyB0b29sLl9cblxuYGBgXG4iK0guRWooYykrIlxuYGBgXG4iXSxxLHEpKS5nbkQoKSkKcT1yLnN0
-eWxlCnEuZGlzcGxheT0iaW5pdGlhbCIKbj1hKyI6ICIrSC5FaihiKQp3aW5kb3cKaWYodHlwZW9mIGNv
-bnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKG4pCndpbmRvdwpuPUguRWooYykK
-aWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKG4pfSwKVXM6
-ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYoYSkudGcoYSwiPyIpP0MueEIuTmooYSwwLEMueEIuT1koYSwi
-PyIpKTphfSwKdDI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG89dC5nLmEoVy5xYyhhLmN1cnJl
-bnRUYXJnZXQpKQphLnByZXZlbnREZWZhdWx0KCkKcz1vLmdldEF0dHJpYnV0ZSgiaHJlZiIpCnI9TC5V
-cyhzKQpxPUwuRzYocykKcD1MLmFLKHMpCmlmKHEhPW51bGwpTC5hZihyLHEscCxiLG5ldyBMLm5UKHIs
-cSxwKSkKZWxzZSBMLmFmKHIsbnVsbCxudWxsLGIsbmV3IEwuTlkocikpfSwKdlU6ZnVuY3Rpb24oKXt2
-YXIgcz1kb2N1bWVudApILkRoKHQuZyx0LmgsIlQiLCJxdWVyeVNlbGVjdG9yQWxsIikKcz1uZXcgVy53
-eihzLnF1ZXJ5U2VsZWN0b3JBbGwoIi5jb2RlIiksdC5SKQpzLksocyxuZXcgTC5lWCgpKX0sCmhYOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4gTC5ZdyhhLGIsYyl9LApZdzpmdW5jdGlvbihhLGIsYyl7dmFyIHM9
-MCxyPVAuRlgodC56KSxxPTEscCxvPVtdLG4sbSxsLGssaixpLGgsZwp2YXIgJGFzeW5jJGhYPVAubHoo
-ZnVuY3Rpb24oZCxlKXtpZihkPT09MSl7cD1lCnM9cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6
-cT0zCmo9dC5YCnM9NgpyZXR1cm4gUC5qUShMLlE2KGEsUC5FRihbInJlZ2lvbiIsInJlZ2lvbiIsIm9m
-ZnNldCIsSC5FaihiKV0saixqKSx0LnQpLCRhc3luYyRoWCkKY2FzZSA2Om49ZQpqPW4KaT1KLlU2KGop
-Cm09bmV3IFUuZDIoVS5qZihpLnEoaiwiZWRpdHMiKSksSC5oKGkucShqLCJleHBsYW5hdGlvbiIpKSxI
-LnVQKGkucShqLCJsaW5lIikpLEguaChpLnEoaiwiZGlzcGxheVBhdGgiKSksSC5oKGkucShqLCJ1cmlQ
-YXRoIikpLFUuTmQoaS5xKGosInRyYWNlcyIpKSkKTC5UMShtKQpMLkZyKGEsYixjKQpMLnlYKCIuZWRp
-dC1wYW5lbCAucGFuZWwtY29udGVudCIsITEpCnE9MQpzPTUKYnJlYWsKY2FzZSAzOnE9MgpnPXAKbD1I
-LlJ1KGcpCms9SC50cyhnKQpMLkMyKCJDb3VsZCBub3QgbG9hZCBlZGl0IGRldGFpbHMiLGwsaykKcz01
-CmJyZWFrCmNhc2UgMjpzPTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscikKY2FzZSAxOnJl
-dHVybiBQLmYzKHAscil9fSkKcmV0dXJuIFAuREkoJGFzeW5jJGhYLHIpfSwKRzc6ZnVuY3Rpb24oYSxi
-LGMsZCxlKXtyZXR1cm4gTC5MNShhLGIsYyxkLGUpfSwKTDU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIg
-cz0wLHI9UC5GWCh0LnopLHEscD0yLG8sbj1bXSxtLGwsayxqLGksaCxnCnZhciAkYXN5bmMkRzc9UC5s
-eihmdW5jdGlvbihmLGEwKXtpZihmPT09MSl7bz1hMApzPXB9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2Fz
-ZSAwOmlmKCFKLnA0KGEsIi5kYXJ0Iikpe0wuQkUoYSxCLndSKCksZCkKTC5CWChhLG51bGwpCmlmKGUh
-PW51bGwpZS4kMCgpCnM9MQpicmVha31wPTQKaT10LlgKcz03CnJldHVybiBQLmpRKEwuUTYoYSxQLkVG
-KFsiaW5saW5lIiwidHJ1ZSJdLGksaSksdC50KSwkYXN5bmMkRzcpCmNhc2UgNzptPWEwCkwuQkUoYSxC
-LllmKG0pLGQpCkwuZkcoYixjKQpsPUwuVXMoYSkKTC5CWChsLGIpCmlmKGUhPW51bGwpZS4kMCgpCnA9
-MgpzPTYKYnJlYWsKY2FzZSA0OnA9MwpnPW8Kaz1ILlJ1KGcpCmo9SC50cyhnKQpMLkMyKCJDb3VsZCBu
-b3QgbG9hZCBkYXJ0IGZpbGUgIithLGssaikKcz02CmJyZWFrCmNhc2UgMzpzPTIKYnJlYWsKY2FzZSA2
-OmNhc2UgMTpyZXR1cm4gUC55QyhxLHIpCmNhc2UgMjpyZXR1cm4gUC5mMyhvLHIpfX0pCnJldHVybiBQ
-LkRJKCRhc3luYyRHNyxyKX0sCkdlOmZ1bmN0aW9uKCl7dmFyIHM9MCxyPVAuRlgodC56KSxxPTEscCxv
-PVtdLG4sbSxsLGssaixpLGgKdmFyICRhc3luYyRHZT1QLmx6KGZ1bmN0aW9uKGEsYil7aWYoYT09PTEp
-e3A9YgpzPXF9d2hpbGUodHJ1ZSlzd2l0Y2gocyl7Y2FzZSAwOmk9Ii9fcHJldmlldy9uYXZpZ2F0aW9u
-VHJlZS5qc29uIgpxPTMKcz02CnJldHVybiBQLmpRKEwuUTYoaSxDLkNNLHQuZUUpLCRhc3luYyRHZSkK
-Y2FzZSA2Om49YgptPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIpCkoubDUobSwiIikK
-TC50WChtLEwubUsobikpCnE9MQpzPTUKYnJlYWsKY2FzZSAzOnE9MgpoPXAKbD1ILlJ1KGgpCms9SC50
-cyhoKQpMLkMyKCJDb3VsZCBub3QgbG9hZCBuYXZpZ2F0aW9uIHRyZWUiLGwsaykKcz01CmJyZWFrCmNh
-c2UgMjpzPTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscikKY2FzZSAxOnJldHVybiBQLmYz
-KHAscil9fSkKcmV0dXJuIFAuREkoJGFzeW5jJEdlLHIpfSwKcU86ZnVuY3Rpb24oYSl7dmFyIHMscj1h
-LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLHE9Qy5DRC56USgkLmZpKCkub2Zmc2V0SGVpZ2h0KSxwPXdp
-bmRvdy5pbm5lckhlaWdodCxvPUMuQ0QuelEoJC5EVygpLm9mZnNldEhlaWdodCkKaWYodHlwZW9mIHAh
-PT0ibnVtYmVyIilyZXR1cm4gcC5ITigpCnM9ci5ib3R0b20Kcy50b1N0cmluZwppZihzPnAtKG8rMTQp
-KUouZGgoYSkKZWxzZXtwPXIudG9wCnAudG9TdHJpbmcKaWYocDxxKzE0KUouZGgoYSl9fSwKZkc6ZnVu
-Y3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvCmlmKGEhPW51bGwpe3M9ZG9jdW1lbnQKcj1zLmdldEVsZW1l
-bnRCeUlkKCJvIitILkVqKGEpKQpxPXMucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILkVqKGIpKQppZihy
-IT1udWxsKXtMLnFPKHIpCkouZFIocikuaSgwLCJ0YXJnZXQiKX1lbHNlIGlmKHEhPW51bGwpTC5xTyhx
-LnBhcmVudEVsZW1lbnQpCmlmKHEhPW51bGwpSi5kUih0LmcuYShxLnBhcmVudE5vZGUpKS5pKDAsImhp
-Z2hsaWdodCIpfWVsc2V7cz1kb2N1bWVudApwPXQuZwpILkRoKHAsdC5oLCJUIiwicXVlcnlTZWxlY3Rv
-ckFsbCIpCnM9cy5xdWVyeVNlbGVjdG9yQWxsKCIubGluZS1ubyIpCm89bmV3IFcud3oocyx0LlIpCmlm
-KG8uZ0Eobyk9PT0wKXJldHVybgpMLnFPKHAuYShDLnQ1Lmd0SChzKSkpfX0sCmFmOmZ1bmN0aW9uKGEs
-YixjLGQsZSl7dmFyIHMscixxPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHA9TC5hSyh3aW5kb3cu
-bG9jYXRpb24uaHJlZikKaWYocSE9bnVsbCl7cz1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIrSC5F
-aihxKSkKaWYocyE9bnVsbClKLmRSKHMpLlIoMCwidGFyZ2V0Iil9aWYocCE9bnVsbCl7cj1kb2N1bWVu
-dC5xdWVyeVNlbGVjdG9yKCIubGluZS0iK0guRWoocCkpCmlmKHIhPW51bGwpSi5kUihyLnBhcmVudEVs
-ZW1lbnQpLlIoMCwiaGlnaGxpZ2h0Iil9aWYoYT09d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lKXtMLmZH
-KGIsYykKZS4kMCgpfWVsc2UgTC5HNyhhLGIsYyxkLGUpfSwKUTQ6ZnVuY3Rpb24oYSxiKXt2YXIgcyxy
-LHE9UC5oSyhhKSxwPXQuWApwPVAuRmwocCxwKQpmb3Iocz1xLmdoWSgpLHM9cy5nUHUocykscz1zLmdr
-eihzKTtzLkYoKTspe3I9cy5nbCgpCnAuWSgwLHIuYSxyLmIpfWZvcihzPWIuZ1B1KGIpLHM9cy5na3oo
-cyk7cy5GKCk7KXtyPXMuZ2woKQpwLlkoMCxyLmEsci5iKX1wLlkoMCwiYXV0aFRva2VuIiwkLlVFKCkp
-CnJldHVybiBxLm5tKDAscCkuZ25EKCl9LApUMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxs
-LGssaj0kLmhMKCkKSi5sNShqLCIiKQppZihhPT1udWxsKXtzPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQo
-InAiKQpDLkx0LnNhNChzLCJTZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuIikKQy5MdC5z
-RChzLEguVk0oWyJwbGFjZWhvbGRlciJdLHQuaSkpCmouYXBwZW5kQ2hpbGQocykKQy5MdC5GRihzKQpy
-ZXR1cm59cj1hLmQKcT0kLm5VKCkKcD1xLnpmKHIpCm89YS5iCm49ZG9jdW1lbnQKbT1xLkhQKHIsSi5U
-MChuLnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQpKQpsPWEuYwprPW4uY3JlYXRlRWxl
-bWVudCgicCIpCmouYXBwZW5kQ2hpbGQoaykKay5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKEgu
-RWoobykrIiBhdCAiKSkKcT10LlgKcT1XLko2KEwuUTQoYS5lLFAuRUYoWyJsaW5lIixKLmoobCldLHEs
-cSkpKQpxLmFwcGVuZENoaWxkKG4uY3JlYXRlVGV4dE5vZGUoSC5FaihtKSsiOiIrSC5FaihsKSsiLiIp
-KQprLmFwcGVuZENoaWxkKHEpCkouZGgoaykKTC5DQyhhLGoscCkKTC5GeihhLGopfSwKTEg6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT0kLnlQKCkKSi5sNShlLCIi
-KQppZihiLmdBKGIpPT09MCl7cz1kb2N1bWVudApyPXMuY3JlYXRlRWxlbWVudCgicCIpCmUuYXBwZW5k
-Q2hpbGQocikKci5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKCJObyBwcm9wb3NlZCBlZGl0cyIp
-KX1lbHNlIGZvcihlPWIuZ1B1KGIpLGU9ZS5na3ooZSkscz10LlgscT10LmoscD1xLkMoIn4oMSk/Iiks
-bz10LloscT1xLmM7ZS5GKCk7KXtuPWUuZ2woKQptPWRvY3VtZW50CnI9bS5jcmVhdGVFbGVtZW50KCJw
-IikKbD0kLnlQKCkKbC5hcHBlbmRDaGlsZChyKQpyLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUo
-SC5FaihuLmEpKyI6IikpCms9bS5jcmVhdGVFbGVtZW50KCJ1bCIpCmwuYXBwZW5kQ2hpbGQoaykKZm9y
-KG49Si5JVChuLmIpO24uRigpOyl7bD1uLmdsKCkKaj1tLmNyZWF0ZUVsZW1lbnQoImxpIikKay5hcHBl
-bmRDaGlsZChqKQpKLmRSKGopLmkoMCwiZWRpdCIpCmk9bS5jcmVhdGVFbGVtZW50KCJhIikKai5hcHBl
-bmRDaGlsZChpKQppLmNsYXNzTGlzdC5hZGQoImVkaXQtbGluayIpCmg9bC5jCmc9SC5FaihoKQppLnNl
-dEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGkpKS5PKCJvZmZzZXQiKSxnKQpmPWwu
-YQpnPUguRWooZikKaS5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuTygi
-bGluZSIpLGcpCmkuYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgibGluZSAiK0guRWooZikpKQpp
-LnNldEF0dHJpYnV0ZSgiaHJlZiIsTC5RNCh3aW5kb3cubG9jYXRpb24ucGF0aG5hbWUsUC5FRihbImxp
-bmUiLEguRWooZiksIm9mZnNldCIsSC5FaihoKV0scyxzKSkpCmc9cC5hKG5ldyBMLkVFKGgsZixhKSkK
-by5hKG51bGwpClcuSkUoaSwiY2xpY2siLGcsITEscSkKai5hcHBlbmRDaGlsZChtLmNyZWF0ZVRleHRO
-b2RlKCI6ICIrSC5FaihsLmIpKSl9fWlmKGMpTC5UMShudWxsKX0sCkZyOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgcyxyLHE9d2luZG93LmxvY2F0aW9uLHA9UC5oSygocSYmQy5FeCkuZ0RyKHEpK0guRWooYSkpCnE9
-dC5YCnE9UC5GbChxLHEpCmlmKGIhPW51bGwpcS5ZKDAsIm9mZnNldCIsSC5FaihiKSkKaWYoYyE9bnVs
-bClxLlkoMCwibGluZSIsSC5FaihjKSkKcS5ZKDAsImF1dGhUb2tlbiIsJC5VRSgpKQpwPXAubm0oMCxx
-KQpxPXdpbmRvdy5oaXN0b3J5CnM9dC56CnI9cC5nbkQoKQpxLnRvU3RyaW5nCnEucHVzaFN0YXRlKG5l
-dyBQLkJmKFtdLFtdKS5QdihQLkZsKHMscykpLCIiLHIpfSwKRW46ZnVuY3Rpb24oYSl7dmFyIHM9Si5i
-Yihkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50LCIvIikKaWYoQy54Qi5u
-KGEscykpcmV0dXJuIEMueEIuRyhhLHMubGVuZ3RoKQplbHNlIHJldHVybiBhfSwKQlg6ZnVuY3Rpb24o
-YSxiKXt2YXIgcyxyPXt9CnIuYT1hCmE9TC5FbihhKQpyLmE9YQpKLmRyKCQuRDkoKSxhKQpzPWRvY3Vt
-ZW50CkguRGgodC5nLHQuaCwiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQpzPW5ldyBXLnd6KHMucXVlcnlT
-ZWxlY3RvckFsbCgiLm5hdi1wYW5lbCAubmF2LWxpbmsiKSx0LlIpCnMuSyhzLG5ldyBMLlZTKHIpKX0s
-CkJFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz0iLnJlZ2lvbnMiLHI9ZG9jdW1lbnQscT1yLnF1ZXJ5U2Vs
-ZWN0b3IocykscD1yLnF1ZXJ5U2VsZWN0b3IoIi5jb2RlIikKSi50SChxLGIuYSwkLktHKCkpCkoudEgo
-cCxiLmIsJC5LRygpKQpMLkxIKGEsYi5kLGMpCkwudlUoKQpMLnlYKCIuY29kZSIsITApCkwueVgocywh
-MCl9LAp0WDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1kb2N1
-bWVudCxkPWUuY3JlYXRlRWxlbWVudCgidWwiKQphLmFwcGVuZENoaWxkKGQpCmZvcihzPWIubGVuZ3Ro
-LHI9dC5YLHE9dC5aLHA9MDtwPGIubGVuZ3RoO2IubGVuZ3RoPT09c3x8KDAsSC5saykoYiksKytwKXtv
-PWJbcF0Kbj1lLmNyZWF0ZUVsZW1lbnQoImxpIikKZC5hcHBlbmRDaGlsZChuKQptPUouWUUobikKaWYo
-by5hPT09Qy5ZMil7bS5nRChuKS5pKDAsImRpciIpCmw9ZS5jcmVhdGVFbGVtZW50KCJzcGFuIikKbi5h
-cHBlbmRDaGlsZChsKQptPUouWUUobCkKbS5nRChsKS5pKDAsImFycm93IikKbS5zaGYobCwiJiN4MjVC
-QzsiKQprPWUuY3JlYXRlRWxlbWVudCgic3BhbiIpCm4uYXBwZW5kQ2hpbGQoaykKSi5sNShrLCc8c3Bh
-biBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMiPmZvbGRlcl9vcGVuPC9zcGFuPicpCm4uYXBwZW5kQ2hpbGQo
-ZS5jcmVhdGVUZXh0Tm9kZShvLmIpKQpMLnRYKG4sby5jKQpMLmt6KGwpfWVsc2V7bS5zaGYobiwnPHNw
-YW4gY2xhc3M9Im1hdGVyaWFsLWljb25zIj5pbnNlcnRfZHJpdmVfZmlsZTwvc3Bhbj4nKQpqPWUuY3Jl
-YXRlRWxlbWVudCgiYSIpCm4uYXBwZW5kQ2hpbGQoaikKbT1KLllFKGopCm0uZ0QoaikuaSgwLCJuYXYt
-bGluayIpCmouc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoaikpLk8oIm5hbWUi
-KSxvLmQpCmouc2V0QXR0cmlidXRlKCJocmVmIixMLlE0KG8uZSxQLkZsKHIscikpKQpqLmFwcGVuZENo
-aWxkKGUuY3JlYXRlVGV4dE5vZGUoby5iKSkKbT1tLmdWbChqKQppPW0uJHRpCmg9aS5DKCJ+KDEpPyIp
-LmEobmV3IEwuVEQoKSkKcS5hKG51bGwpClcuSkUobS5hLG0uYixoLCExLGkuYykKZz1vLmYKaWYodHlw
-ZW9mIGchPT0ibnVtYmVyIilyZXR1cm4gZy5vcygpCmlmKGc+MCl7Zj1lLmNyZWF0ZUVsZW1lbnQoInNw
-YW4iKQpuLmFwcGVuZENoaWxkKGYpCkouZFIoZikuaSgwLCJlZGl0LWNvdW50IikKbT0iIitnKyIgIgpp
-ZihnPT09MSlpPSJlZGl0IgplbHNlIGk9ImVkaXRzIgpmLnNldEF0dHJpYnV0ZSgidGl0bGUiLG0raSkK
-Zi5hcHBlbmRDaGlsZChlLmNyZWF0ZVRleHROb2RlKEMuam4udyhnKSkpfX19fSwKRno6ZnVuY3Rpb24o
-YSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGg9YS5hCmlmKGg9PW51bGwpcmV0dXJuCnM9ZG9j
-dW1lbnQKcj1zLmNyZWF0ZUVsZW1lbnQoInAiKQpxPWIuYXBwZW5kQ2hpbGQocikKcj1zLmNyZWF0ZUVs
-ZW1lbnQoInNwYW4iKQpwPXQuaQpKLk11KHIsSC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxwKSkKci5h
-cHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKCJBY3Rpb25zIikpCnEuYXBwZW5kQ2hpbGQocikKcS5h
-cHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKCI6IikpCm89cy5jcmVhdGVFbGVtZW50KCJwIikKYi5h
-cHBlbmRDaGlsZChvKQpmb3Iocj1oLmxlbmd0aCxuPXQuUSxtPTA7bTxoLmxlbmd0aDtoLmxlbmd0aD09
-PXJ8fCgwLEgubGspKGgpLCsrbSl7bD1oW21dCms9cy5jcmVhdGVFbGVtZW50KCJhIikKby5hcHBlbmRD
-aGlsZChrKQprLmFwcGVuZENoaWxkKHMuY3JlYXRlVGV4dE5vZGUobC5hKSkKay5zZXRBdHRyaWJ1dGUo
-ImhyZWYiLGwuYikKaj1uLmEoSC5WTShbImFkZC1oaW50LWxpbmsiLCJiZWZvcmUtYXBwbHkiLCJidXR0
-b24iXSxwKSkKaT1KLmRSKGspCmkuVjEoMCkKaS5GVigwLGopfX0sCkNDOmZ1bmN0aW9uKGE5LGIwLGIx
-KXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMyxhNCxh
-NSxhNixhNyxhOApmb3Iocz1hOS5mLHI9cy5sZW5ndGgscT10LmkscD10LlEsbz10Lmosbj1vLkMoIn4o
-MSk/IiksbT10Llosbz1vLmMsbD0wO2w8cy5sZW5ndGg7cy5sZW5ndGg9PT1yfHwoMCxILmxrKShzKSwr
-K2wpe2s9c1tsXQpqPWRvY3VtZW50Cmk9ai5jcmVhdGVFbGVtZW50KCJwIikKaD1wLmEoSC5WTShbInRy
-YWNlIl0scSkpCmc9Si5kUihpKQpnLlYxKDApCmcuRlYoMCxoKQpmPWIwLmFwcGVuZENoaWxkKGkpCmk9
-ai5jcmVhdGVFbGVtZW50KCJzcGFuIikKaD1wLmEoSC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxxKSkK
-Zz1KLmRSKGkpCmcuVjEoMCkKZy5GVigwLGgpCmkuYXBwZW5kQ2hpbGQoai5jcmVhdGVUZXh0Tm9kZShr
-LmEpKQpmLmFwcGVuZENoaWxkKGkpCmYuYXBwZW5kQ2hpbGQoai5jcmVhdGVUZXh0Tm9kZSgiOiIpKQpp
-PWouY3JlYXRlRWxlbWVudCgidWwiKQpoPXAuYShILlZNKFsidHJhY2UiXSxxKSkKZz1KLmRSKGkpCmcu
-VjEoMCkKZy5GVigwLGgpCmU9Zi5hcHBlbmRDaGlsZChpKQpmb3IoaT1rLmIsaD1pLmxlbmd0aCxkPTA7
-ZDxpLmxlbmd0aDtpLmxlbmd0aD09PWh8fCgwLEgubGspKGkpLCsrZCl7Yz1pW2RdCmI9ai5jcmVhdGVF
-bGVtZW50KCJsaSIpCmUuYXBwZW5kQ2hpbGQoYikKYT1qLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQphMD1w
-LmEoSC5WTShbImZ1bmN0aW9uIl0scSkpCmc9Si5kUihhKQpnLlYxKDApCmcuRlYoMCxhMCkKYTA9Yy5i
-Ckwua0QoYSxhMD09bnVsbD8idW5rbm93biI6YTApCmIuYXBwZW5kQ2hpbGQoYSkKYTE9Yy5jCmlmKGEx
-IT1udWxsKXtiLmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5vZGUoIiAoIikpCmEyPWExLmIKYTM9ai5j
-cmVhdGVFbGVtZW50KCJhIikKYTMuYXBwZW5kQ2hpbGQoai5jcmVhdGVUZXh0Tm9kZShILkVqKGExLmMp
-KyI6IitILkVqKGEyKSkpCmEzLnNldEF0dHJpYnV0ZSgiaHJlZiIsYTEuYSkKYTMuY2xhc3NMaXN0LmFk
-ZCgibmF2LWxpbmsiKQpiLmFwcGVuZENoaWxkKGEzKQpiLmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5v
-ZGUoIikiKSl9Yi5hcHBlbmRDaGlsZChqLmNyZWF0ZVRleHROb2RlKCI6ICIpKQphPWMuYQpMLmtEKGIs
-YT09bnVsbD8idW5rbm93biI6YSkKYT1jLmQKaWYoYS5sZW5ndGghPT0wKXthMD1qLmNyZWF0ZUVsZW1l
-bnQoInAiKQphND1wLmEoSC5WTShbImRyYXdlciIsImJlZm9yZS1hcHBseSJdLHEpKQpnPUouZFIoYTAp
-CmcuVjEoMCkKZy5GVigwLGE0KQphNT1iLmFwcGVuZENoaWxkKGEwKQpmb3IoYTA9YS5sZW5ndGgsYTY9
-MDthNjxhLmxlbmd0aDthLmxlbmd0aD09PWEwfHwoMCxILmxrKShhKSwrK2E2KXthNz1hW2E2XQphND1q
-LmNyZWF0ZUVsZW1lbnQoImJ1dHRvbiIpCmE4PW4uYShuZXcgTC5BUyhhNyxhMSkpCm0uYShudWxsKQpX
-LkpFKGE0LCJjbGljayIsYTgsITEsbykKYTQuYXBwZW5kQ2hpbGQoai5jcmVhdGVUZXh0Tm9kZShNLk9Y
-KGE3LmEpKSkKYTUuYXBwZW5kQ2hpbGQoYTQpfX19fX0sCmtEOmZ1bmN0aW9uKGEsYil7dmFyIHMscixx
-PUguVk0oYi5zcGxpdCgiLiIpLHQucykscD1DLk5tLmd0SChxKSxvPWRvY3VtZW50CmEuYXBwZW5kQ2hp
-bGQoby5jcmVhdGVUZXh0Tm9kZShwKSkKZm9yKHA9SC5xQyhxLDEsbnVsbCx0Lk4pLHA9bmV3IEguYTco
-cCxwLmdBKHApLHAuJHRpLkMoImE3PGFMLkU+IikpLHM9Si5ZRShhKTtwLkYoKTspe3I9cC5kCnMubnoo
-YSwiYmVmb3JlZW5kIiwiJiM4MjAzOy4iLG51bGwsbnVsbCkKYS5hcHBlbmRDaGlsZChvLmNyZWF0ZVRl
-eHROb2RlKHIpKX19LAplOmZ1bmN0aW9uIGUoKXt9LApWVzpmdW5jdGlvbiBWVyhhLGIsYyl7dGhpcy5h
-PWEKdGhpcy5iPWIKdGhpcy5jPWN9LApvWjpmdW5jdGlvbiBvWigpe30sCmpyOmZ1bmN0aW9uIGpyKCl7
-fSwKcWw6ZnVuY3Rpb24gcWwoKXt9LApIaTpmdW5jdGlvbiBIaSgpe30sCkJUOmZ1bmN0aW9uIEJUKCl7
-fSwKUFk6ZnVuY3Rpb24gUFkoKXt9LApMOmZ1bmN0aW9uIEwoKXt9LApXeDpmdW5jdGlvbiBXeChhLGIp
-e3RoaXMuYT1hCnRoaXMuYj1ifSwKQU86ZnVuY3Rpb24gQU8oYSl7dGhpcy5hPWF9LApkTjpmdW5jdGlv
-biBkTihhKXt0aGlzLmE9YX0sCkhvOmZ1bmN0aW9uIEhvKGEpe3RoaXMuYT1hfSwKeHo6ZnVuY3Rpb24g
-eHooYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCklDOmZ1bmN0aW9uIElDKCl7fSwKZkM6ZnVuY3Rpb24g
-ZkMoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm5UOmZ1bmN0aW9uIG5UKGEsYixjKXt0aGlzLmE9YQp0
-aGlzLmI9Ygp0aGlzLmM9Y30sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3RoaXMuYT1hfSwKZVg6ZnVuY3Rpb24g
-ZVgoKXt9LApFRTpmdW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApR
-TDpmdW5jdGlvbiBRTChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVuY3Rpb24gVlMoYSl7dGhp
-cy5hPWF9LApURDpmdW5jdGlvbiBURCgpe30sCkFTOmZ1bmN0aW9uIEFTKGEsYil7dGhpcy5hPWEKdGhp
-cy5iPWJ9LApYQTpmdW5jdGlvbiBYQSgpe30sCm1LOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixt
-PUguVk0oW10sdC5jUSkKZm9yKHM9Si5JVCh0LlUuYShhKSk7cy5GKCk7KXtyPXMuZ2woKQpxPUouVTYo
-cikKcD1MLnAyKEguaChxLnEociwidHlwZSIpKSkKbz1ILmgocS5xKHIsIm5hbWUiKSkKbj1xLnEociwi
-c3VidHJlZSIpCm49bj09bnVsbD9udWxsOkwubUsobikKQy5ObS5pKG0sbmV3IEwuWloocCxvLG4sSC5o
-KHEucShyLCJwYXRoIikpLEguaChxLnEociwiaHJlZiIpKSxILnVQKHEucShyLCJlZGl0Q291bnQiKSkp
-KX1yZXR1cm4gbX0sClZEOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1ILlZNKFtdLHQuRykKZm9yKHM9YS5s
-ZW5ndGgscj0wO3I8YS5sZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShhKSwrK3IpQy5ObS5pKHEs
-YVtyXS5MdCgpKQpyZXR1cm4gcX0sCnAyOmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtjYXNlImRpcmVjdG9y
-eSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpkZWZhdWx0OnRocm93IEguYihQLlBW
-KCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIitILkVqKGEpKSl9fSwKdnk6
-ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5ZMjpyZXR1cm4iZGlyZWN0b3J5IgpjYXNlIEMucmY6
-cmV0dXJuImZpbGUifXRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5v
-ZGUgdHlwZTogIithLncoMCkpKX0sClpaOmZ1bmN0aW9uIFpaKGEsYixjLGQsZSxmKXt2YXIgXz10aGlz
-Cl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKTzk6ZnVuY3Rpb24gTzkoYSl7dGhp
-cy5iPWF9LApJVjpmdW5jdGlvbiBJVihhLGIsYyxkKXt2YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1j
-Cl8ucj1kfX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuPWIueFooYSkKYi5oSyhh
-KQppZihuIT1udWxsKWE9Si5LVihhLG4ubGVuZ3RoKQpzPXQucwpyPUguVk0oW10scykKcT1ILlZNKFtd
-LHMpCnM9YS5sZW5ndGgKaWYocyE9PTAmJmIucjQoQy54Qi5XKGEsMCkpKXtpZigwPj1zKXJldHVybiBI
-Lk9IKGEsMCkKQy5ObS5pKHEsYVswXSkKcD0xfWVsc2V7Qy5ObS5pKHEsIiIpCnA9MH1mb3Iobz1wO288
-czsrK28paWYoYi5yNChDLnhCLlcoYSxvKSkpe0MuTm0uaShyLEMueEIuTmooYSxwLG8pKQpDLk5tLmko
-cSxhW29dKQpwPW8rMX1pZihwPHMpe0MuTm0uaShyLEMueEIuRyhhLHApKQpDLk5tLmkocSwiIil9cmV0
-dXJuIG5ldyBYLldEKGIsbixyLHEpfSwKV0Q6ZnVuY3Rpb24gV0QoYSxiLGMsZCl7dmFyIF89dGhpcwpf
-LmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCkk3OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgWC5kdihhKX0s
-CmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1bmN0aW9uKCl7dmFyIHMscj1udWxs
-CmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIilyZXR1cm4gJC5FYigpCnM9UC51bygpCmlmKCFDLnhCLlRj
-KHMuZ0lpKHMpLCIvIikpcmV0dXJuICQuRWIoKQppZihQLktMKHIsImEvYiIscixyLHIscixyKS50NCgp
-PT09ImFcXGIiKXJldHVybiAkLktrKCkKcmV0dXJuICQuYkQoKX0sCnpMOmZ1bmN0aW9uIHpMKCl7fX0s
-RT17T0Y6ZnVuY3Rpb24gT0YoYSxiLGMpe3RoaXMuZD1hCnRoaXMuZT1iCnRoaXMuZj1jfX0sRj17cnU6
-ZnVuY3Rpb24gcnUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9YgpfLmY9YwpfLnI9ZH19LEQ9
-ewpSWDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89bnVsbAp0cnl7bz1QLnVvKCl9Y2F0Y2gocyl7aWYo
-dC5nOC5iKEguUnUocykpKXtyPSQuRmYKaWYociE9bnVsbClyZXR1cm4gcgp0aHJvdyBzfWVsc2UgdGhy
-b3cgc31pZihKLlJNKG8sJC5JNikpe3I9JC5GZgpyLnRvU3RyaW5nCnJldHVybiByfSQuSTY9bwppZigk
-LkhrKCk9PSQuRWIoKSlyPSQuRmY9by5aSSgiLiIpLncoMCkKZWxzZXtxPW8udDQoKQpwPXEubGVuZ3Ro
-LTEKcj0kLkZmPXA9PT0wP3E6Qy54Qi5OaihxLDAscCl9cmV0dXJuIHJ9fQp2YXIgdz1bQyxILEosUCxX
-LE0sVSxCLFQsTCxYLE8sRSxGLERdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9uTmFtZXNJZk5lY2Vzc2Fy
-eSh3KQp2YXIgJD17fQpILkZLLnByb3RvdHlwZT17fQpKLnZCLnByb3RvdHlwZT17CkROOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIGE9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKdzpmdW5j
-dGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5FaihILk0oYSkpKyInIn0sCmU3OmZ1bmN0aW9u
-KGEsYil7dC5vLmEoYikKdGhyb3cgSC5iKFAubHIoYSxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfX0K
-Si55RS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LApnaU86ZnVuY3Rp
-b24oYSl7cmV0dXJuIGE/NTE5MDE4OjIxODE1OX0sCiRpYTI6MX0KSi53ZS5wcm90b3R5cGU9ewpETjpm
-dW5jdGlvbihhLGIpe3JldHVybiBudWxsPT1ifSwKdzpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9LApn
-aU86ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LAplNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNqKGEs
-dC5vLmEoYikpfSwKJGljODoxfQpKLk1GLnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4g
-MH0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdm06MX0KSi5pQy5wcm90b3R5cGU9
-e30KSi5rZC5wcm90b3R5cGU9e30KSi5jNS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPWFb
-JC53KCldCmlmKHM9PW51bGwpcmV0dXJuIHRoaXMudChhKQpyZXR1cm4iSmF2YVNjcmlwdCBmdW5jdGlv
-biBmb3IgIitILkVqKEouaihzKSl9LAokaUVIOjF9CkouamQucHJvdG90eXBlPXsKaTpmdW5jdGlvbihh
-LGIpe0gudDYoYSkuYy5hKGIpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJhZGQiKSkKYS5w
-dXNoKGIpfSwKVzQ6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5M
-NCgicmVtb3ZlQXQiKSkKcz1hLmxlbmd0aAppZihiPj1zKXRocm93IEguYihQLk83KGIsbnVsbCkpCnJl
-dHVybiBhLnNwbGljZShiLDEpWzBdfSwKVUc6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscQpILnQ2KGEp
-LkMoImNYPDE+IikuYShjKQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgiaW5zZXJ0QWxsIikp
-CnM9YS5sZW5ndGgKUC53QShiLDAscywiaW5kZXgiKQpyPWMubGVuZ3RoCmEubGVuZ3RoPXMrcgpxPWIr
-cgp0aGlzLllXKGEscSxhLmxlbmd0aCxhLGIpCnRoaXMudmcoYSxiLHEsYyl9LAptdjpmdW5jdGlvbihh
-KXtpZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgicmVtb3ZlTGFzdCIpKQppZihhLmxlbmd0aD09
-PTApdGhyb3cgSC5iKEguSFkoYSwtMSkpCnJldHVybiBhLnBvcCgpfSwKRlY6ZnVuY3Rpb24oYSxiKXt2
-YXIgcwpILnQ2KGEpLkMoImNYPDE+IikuYShiKQppZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgi
-YWRkQWxsIikpCmZvcihzPUouSVQoYik7cy5GKCk7KWEucHVzaChzLmdsKCkpfSwKRTI6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciBzPUgudDYoYSkKcmV0dXJuIG5ldyBILmxKKGEscy5LcShjKS5DKCIxKDIpIikuYShi
-KSxzLkMoIkA8MT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciBzLHI9
-UC5POChhLmxlbmd0aCwiIiwhMSx0Lk4pCmZvcihzPTA7czxhLmxlbmd0aDsrK3MpdGhpcy5ZKHIscyxI
-LkVqKGFbc10pKQpyZXR1cm4gci5qb2luKGIpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixx
-CmQuYShiKQpILnQ2KGEpLktxKGQpLkMoIjEoMSwyKSIpLmEoYykKcz1hLmxlbmd0aApmb3Iocj1iLHE9
-MDtxPHM7KytxKXtyPWMuJDIocixhW3FdKQppZihhLmxlbmd0aCE9PXMpdGhyb3cgSC5iKFAuYTQoYSkp
-fXJldHVybiByfSwKSHQ6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvCkgudDYoYSkuQygiYTIoMSki
-KS5hKGIpCnM9YS5sZW5ndGgKZm9yKHI9bnVsbCxxPSExLHA9MDtwPHM7KytwKXtvPWFbcF0KaWYoSC5v
-VChiLiQxKG8pKSl7aWYocSl0aHJvdyBILmIoSC5BbSgpKQpyPW8KcT0hMH1pZihzIT09YS5sZW5ndGgp
-dGhyb3cgSC5iKFAuYTQoYSkpfWlmKHEpcmV0dXJuIHIKdGhyb3cgSC5iKEguV3AoKSl9LApFOmZ1bmN0
-aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwK
-Z3RIOmZ1bmN0aW9uKGEpe2lmKGEubGVuZ3RoPjApcmV0dXJuIGFbMF0KdGhyb3cgSC5iKEguV3AoKSl9
-LApnclo6ZnVuY3Rpb24oYSl7dmFyIHM9YS5sZW5ndGgKaWYocz4wKXJldHVybiBhW3MtMV0KdGhyb3cg
-SC5iKEguV3AoKSl9LApZVzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzLHIscSxwCkgudDYoYSkuQygi
-Y1g8MT4iKS5hKGQpCmlmKCEhYS5pbW11dGFibGUkbGlzdClILnZoKFAuTDQoInNldFJhbmdlIikpClAu
-akIoYixjLGEubGVuZ3RoKQpzPWMtYgppZihzPT09MClyZXR1cm4KUC5rMShlLCJza2lwQ291bnQiKQpy
-PWQKcT1KLlU2KHIpCmlmKGUrcz5xLmdBKHIpKXRocm93IEguYihILmFyKCkpCmlmKGU8Yilmb3IocD1z
-LTE7cD49MDstLXApYVtiK3BdPXEucShyLGUrcCkKZWxzZSBmb3IocD0wO3A8czsrK3ApYVtiK3BdPXEu
-cShyLGUrcCl9LAp2ZzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gdGhpcy5ZVyhhLGIsYyxkLDApfSwK
-VnI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCkgudDYoYSkuQygiYTIoMSkiKS5hKGIpCnM9YS5sZW5ndGgK
-Zm9yKHI9MDtyPHM7KytyKXtpZihILm9UKGIuJDEoYVtyXSkpKXJldHVybiEwCmlmKGEubGVuZ3RoIT09
-cyl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJuITF9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciBzCmZvcihz
-PTA7czxhLmxlbmd0aDsrK3MpaWYoSi5STShhW3NdLGIpKXJldHVybiEwCnJldHVybiExfSwKZ2wwOmZ1
-bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aD09PTB9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
-Z3RoIT09MH0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX0sCmdrejpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IEoubTEoYSxhLmxlbmd0aCxILnQ2KGEpLkMoIm0xPDE+IikpfSwKZ2lPOmZ1
-bmN0aW9uKGEpe3JldHVybiBILmVRKGEpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwK
-c0E6ZnVuY3Rpb24oYSxiKXtpZighIWEuZml4ZWQkbGVuZ3RoKUgudmgoUC5MNCgic2V0IGxlbmd0aCIp
-KQphLmxlbmd0aD1ifSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKaWYoYj49YS5sZW5ndGh8fGI8MCl0
-aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0gudDYoYSku
-Yy5hKGMpCmlmKCEhYS5pbW11dGFibGUkbGlzdClILnZoKFAuTDQoImluZGV4ZWQgc2V0IikpCmlmKGI+
-PWEubGVuZ3RofHxiPDApdGhyb3cgSC5iKEguSFkoYSxiKSkKYVtiXT1jfSwKJGliUToxLAokaWNYOjEs
-CiRpek06MX0KSi5Qby5wcm90b3R5cGU9e30KSi5tMS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3Jl
-dHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9ci5hLHA9cS5sZW5ndGgKaWYo
-ci5iIT09cCl0aHJvdyBILmIoSC5sayhxKSkKcz1yLmMKaWYocz49cCl7ci5zTShudWxsKQpyZXR1cm4h
-MX1yLnNNKHFbc10pOysrci5jCnJldHVybiEwfSwKc006ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRp
-LkMoIjE/IikuYShhKX0sCiRpQW46MX0KSi5xSS5wcm90b3R5cGU9ewp6UTpmdW5jdGlvbihhKXtpZihh
-PjApe2lmKGEhPT0xLzApcmV0dXJuIE1hdGgucm91bmQoYSl9ZWxzZSBpZihhPi0xLzApcmV0dXJuIDAt
-TWF0aC5yb3VuZCgwLWEpCnRocm93IEguYihQLkw0KCIiK2ErIi5yb3VuZCgpIikpfSwKdzpmdW5jdGlv
-bihhKXtpZihhPT09MCYmMS9hPDApcmV0dXJuIi0wLjAiCmVsc2UgcmV0dXJuIiIrYX0sCmdpTzpmdW5j
-dGlvbihhKXt2YXIgcyxyLHEscCxvPWF8MAppZihhPT09bylyZXR1cm4gNTM2ODcwOTExJm8Kcz1NYXRo
-LmFicyhhKQpyPU1hdGgubG9nKHMpLzAuNjkzMTQ3MTgwNTU5OTQ1M3wwCnE9TWF0aC5wb3coMixyKQpw
-PXM8MT9zL3E6cS9zCnJldHVybiA1MzY4NzA5MTEmKChwKjkwMDcxOTkyNTQ3NDA5OTJ8MCkrKHAqMzU0
-MjI0MzE4MTE3NjUyMXwwKSkqNTk5MTk3K3IqMTI1OX0sCnpZOmZ1bmN0aW9uKGEsYil7dmFyIHM9YSVi
-CmlmKHM9PT0wKXJldHVybiAwCmlmKHM+MClyZXR1cm4gcwppZihiPDApcmV0dXJuIHMtYgplbHNlIHJl
-dHVybiBzK2J9LApCVTpmdW5jdGlvbihhLGIpe3JldHVybihhfDApPT09YT9hL2J8MDp0aGlzLkRKKGEs
-Yil9LApESjpmdW5jdGlvbihhLGIpe3ZhciBzPWEvYgppZihzPj0tMjE0NzQ4MzY0OCYmczw9MjE0NzQ4
-MzY0NylyZXR1cm4gc3wwCmlmKHM+MCl7aWYocyE9PTEvMClyZXR1cm4gTWF0aC5mbG9vcihzKX1lbHNl
-IGlmKHM+LTEvMClyZXR1cm4gTWF0aC5jZWlsKHMpCnRocm93IEguYihQLkw0KCJSZXN1bHQgb2YgdHJ1
-bmNhdGluZyBkaXZpc2lvbiBpcyAiK0guRWoocykrIjogIitILkVqKGEpKyIgfi8gIitiKSl9LAp3Rzpm
-dW5jdGlvbihhLGIpe3ZhciBzCmlmKGE+MClzPXRoaXMucDMoYSxiKQplbHNle3M9Yj4zMT8zMTpiCnM9
-YT4+cz4+PjB9cmV0dXJuIHN9LApiZjpmdW5jdGlvbihhLGIpe2lmKGI8MCl0aHJvdyBILmIoSC50TChi
-KSkKcmV0dXJuIHRoaXMucDMoYSxiKX0sCnAzOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGI+MzE/MDphPj4+
-Yn0sCiRpQ1A6MSwKJGlsZjoxfQpKLmJVLnByb3RvdHlwZT17JGlJZjoxfQpKLlZBLnByb3RvdHlwZT17
-fQpKLkRyLnByb3RvdHlwZT17Cm06ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5iKEguSFkoYSxi
-KSkKaWYoYj49YS5sZW5ndGgpSC52aChILkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApX
-OmZ1bmN0aW9uKGEsYil7aWYoYj49YS5sZW5ndGgpdGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGEu
-Y2hhckNvZGVBdChiKX0sCmRkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILnVuKGIsYSwwKX0sCmg6
-ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyIpdGhyb3cgSC5iKFAuTDMoYixudWxsLG51
-bGwpKQpyZXR1cm4gYStifSwKVGM6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmxlbmd0aCxyPWEubGVuZ3Ro
-CmlmKHM+cilyZXR1cm4hMQpyZXR1cm4gYj09PXRoaXMuRyhhLHItcyl9LAppNzpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgcz1QLmpCKGIsYyxhLmxlbmd0aCkscj1hLnN1YnN0cmluZygwLGIpLHE9YS5zdWJzdHJp
-bmcocykKcmV0dXJuIHIrZCtxfSwKUWk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKGM8MHx8Yz5hLmxl
-bmd0aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKcz1jK2IubGVuZ3RoCmlm
-KHM+YS5sZW5ndGgpcmV0dXJuITEKcmV0dXJuIGI9PT1hLnN1YnN0cmluZyhjLHMpfSwKbjpmdW5jdGlv
-bihhLGIpe3JldHVybiB0aGlzLlFpKGEsYiwwKX0sCk5qOmZ1bmN0aW9uKGEsYixjKXtpZihjPT1udWxs
-KWM9YS5sZW5ndGgKaWYoYjwwKXRocm93IEguYihQLk83KGIsbnVsbCkpCmlmKGI+Yyl0aHJvdyBILmIo
-UC5PNyhiLG51bGwpKQppZihjPmEubGVuZ3RoKXRocm93IEguYihQLk83KGMsbnVsbCkpCnJldHVybiBh
-LnN1YnN0cmluZyhiLGMpfSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLk5qKGEsYixudWxsKX0s
-CmhjOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93ZXJDYXNlKCl9LApiUzpmdW5jdGlvbihhKXt2YXIg
-cyxyLHEscD1hLnRyaW0oKSxvPXAubGVuZ3RoCmlmKG89PT0wKXJldHVybiBwCmlmKHRoaXMuVyhwLDAp
-PT09MTMzKXtzPUoubW0ocCwxKQppZihzPT09bylyZXR1cm4iIn1lbHNlIHM9MApyPW8tMQpxPXRoaXMu
-bShwLHIpPT09MTMzP0ouYzEocCxyKTpvCmlmKHM9PT0wJiZxPT09bylyZXR1cm4gcApyZXR1cm4gcC5z
-dWJzdHJpbmcocyxxKX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZigwPj1iKXJldHVybiIiCmlm
-KGI9PT0xfHxhLmxlbmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4wKXRocm93IEguYihDLkVxKQpm
-b3Iocz1hLHI9IiI7ITA7KXtpZigoYiYxKT09PTEpcj1zK3IKYj1iPj4+MQppZihiPT09MClicmVhawpz
-Kz1zfXJldHVybiByfSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKGM8MHx8Yz5hLmxlbmd0aCl0
-aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKcz1hLmluZGV4T2YoYixjKQpyZXR1
-cm4gc30sCk9ZOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxiLDApfSwKUGs6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciBzLHIKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2UgaWYoYzwwfHxjPmEubGVuZ3Ro
-KXRocm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQpzPWIubGVuZ3RoCnI9YS5sZW5n
-dGgKaWYoYytzPnIpYz1yLXMKcmV0dXJuIGEubGFzdEluZGV4T2YoYixjKX0sCmNuOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIHRoaXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPWEubGVu
-Z3RoCmlmKGM+cyl0aHJvdyBILmIoUC5URShjLDAscyxudWxsLG51bGwpKQpyZXR1cm4gSC5tMihhLGIs
-Yyl9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiwwKX0sCnc6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGF9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHMscixxCmZvcihzPWEubGVuZ3RoLHI9MCxxPTA7
-cTxzOysrcSl7cj01MzY4NzA5MTEmcithLmNoYXJDb2RlQXQocSkKcj01MzY4NzA5MTEmcisoKDUyNDI4
-NyZyKTw8MTApCnJePXI+PjZ9cj01MzY4NzA5MTEmcisoKDY3MTA4ODYzJnIpPDwzKQpyXj1yPj4xMQpy
-ZXR1cm4gNTM2ODcwOTExJnIrKCgxNjM4MyZyKTw8MTUpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-bGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKaWYoYj49YS5sZW5ndGh8fCExKXRocm93IEgu
-YihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKJGl2WDoxLAokaXFVOjF9CkgubmQucHJvdG90eXBlPXsK
-dzpmdW5jdGlvbihhKXt2YXIgcz0iTGF0ZUluaXRpYWxpemF0aW9uRXJyb3I6ICIrdGhpcy5hCnJldHVy
-biBzfX0KSC5xai5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmxlbmd0aH0s
-CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy54Qi5tKHRoaXMuYSxILnVQKGIpKX19CkguYlEucHJvdG90
-eXBlPXt9CkguYUwucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKcmV0dXJuIG5l
-dyBILmE3KHMscy5nQShzKSxILkxoKHMpLkMoImE3PGFMLkU+IikpfSwKZ2wwOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB0aGlzLmdBKHRoaXMpPT09MH0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD10aGlzLG89
-cC5nQShwKQppZihiLmxlbmd0aCE9PTApe2lmKG89PT0wKXJldHVybiIiCnM9SC5FaihwLkUoMCwwKSkK
-aWYobyE9PXAuZ0EocCkpdGhyb3cgSC5iKFAuYTQocCkpCmZvcihyPXMscT0xO3E8bzsrK3Epe3I9citi
-K0guRWoocC5FKDAscSkpCmlmKG8hPT1wLmdBKHApKXRocm93IEguYihQLmE0KHApKX1yZXR1cm4gci5j
-aGFyQ29kZUF0KDApPT0wP3I6cn1lbHNle2ZvcihxPTAscj0iIjtxPG87KytxKXtyKz1ILkVqKHAuRSgw
-LHEpKQppZihvIT09cC5nQShwKSl0aHJvdyBILmIoUC5hNChwKSl9cmV0dXJuIHIuY2hhckNvZGVBdCgw
-KT09MD9yOnJ9fSwKZXY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5HRygwLEguTGgodGhpcykuQygi
-YTIoYUwuRSkiKS5hKGIpKX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1ILkxoKHRoaXMpCnJldHVy
-biBuZXcgSC5sSih0aGlzLHMuS3EoYykuQygiMShhTC5FKSIpLmEoYikscy5DKCJAPGFMLkU+IikuS3Eo
-YykuQygibEo8MSwyPiIpKX19CkgubkgucHJvdG90eXBlPXsKSGQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
-IHMscj10aGlzLmIKUC5rMShyLCJzdGFydCIpCnM9dGhpcy5jCmlmKHMhPW51bGwpe1AuazEocywiZW5k
-IikKaWYocj5zKXRocm93IEguYihQLlRFKHIsMCxzLCJzdGFydCIsbnVsbCkpfX0sCmdVRDpmdW5jdGlv
-bigpe3ZhciBzPUouSG0odGhpcy5hKSxyPXRoaXMuYwppZihyPT1udWxsfHxyPnMpcmV0dXJuIHMKcmV0
-dXJuIHJ9LApnQXM6ZnVuY3Rpb24oKXt2YXIgcz1KLkhtKHRoaXMuYSkscj10aGlzLmIKaWYocj5zKXJl
-dHVybiBzCnJldHVybiByfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHMscj1KLkhtKHRoaXMuYSkscT10aGlz
-LmIKaWYocT49cilyZXR1cm4gMApzPXRoaXMuYwppZihzPT1udWxsfHxzPj1yKXJldHVybiByLXEKaWYo
-dHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCnJldHVybiBzLXF9LApFOmZ1bmN0aW9uKGEs
-Yil7dmFyIHM9dGhpcyxyPXMuZ0FzKCkrYgppZihiPDB8fHI+PXMuZ1VEKCkpdGhyb3cgSC5iKFAuQ2Yo
-YixzLCJpbmRleCIsbnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIpfX0KSC5hNy5wcm90b3R5cGU9
-ewpnbDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuZApyZXR1cm4gc30sCkY6ZnVuY3Rpb24oKXt2YXIgcyxy
-PXRoaXMscT1yLmEscD1KLlU2KHEpLG89cC5nQShxKQppZihyLmIhPT1vKXRocm93IEguYihQLmE0KHEp
-KQpzPXIuYwppZihzPj1vKXtyLnNJKG51bGwpCnJldHVybiExfXIuc0kocC5FKHEscykpOysrci5jCnJl
-dHVybiEwfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCiRpQW46
-MX0KSC5pMS5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHM9SC5MaCh0aGlzKQpyZXR1cm4g
-bmV3IEguTUgoSi5JVCh0aGlzLmEpLHRoaXMuYixzLkMoIkA8MT4iKS5LcShzLlFbMV0pLkMoIk1IPDEs
-Mj4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IbSh0aGlzLmEpfX0KSC54eS5wcm90b3R5cGU9
-eyRpYlE6MX0KSC5NSC5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYgppZihy
-LkYoKSl7cy5zSShzLmMuJDEoci5nbCgpKSkKcmV0dXJuITB9cy5zSShudWxsKQpyZXR1cm4hMX0sCmds
-OmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5hCnJldHVybiBzfSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5hPXRo
-aXMuJHRpLkMoIjI/IikuYShhKX19CkgubEoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJu
-IEouSG0odGhpcy5hKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5iLiQxKEouR0EodGhpcy5h
-LGIpKX19CkguVTUucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TTyhKLklU
-KHRoaXMuYSksdGhpcy5iLHRoaXMuJHRpLkMoIlNPPDE+IikpfX0KSC5TTy5wcm90b3R5cGU9ewpGOmZ1
-bmN0aW9uKCl7dmFyIHMscgpmb3Iocz10aGlzLmEscj10aGlzLmI7cy5GKCk7KWlmKEgub1Qoci4kMShz
-LmdsKCkpKSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5nbCgp
-fX0KSC51Ni5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILkpCKEouSVQodGhp
-cy5hKSx0aGlzLiR0aS5DKCJKQjwxPiIpKX19CkguSkIucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3Zh
-ciBzLHIKZm9yKHM9dGhpcy5hLHI9dGhpcy4kdGkuYztzLkYoKTspaWYoci5iKHMuZ2woKSkpcmV0dXJu
-ITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLiR0aS5jLmEodGhpcy5hLmdsKCkp
-fSwKJGlBbjoxfQpILlNVLnByb3RvdHlwZT17fQpILlJlLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxi
-LGMpe0guTGgodGhpcykuQygiUmUuRSIpLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkg
-YW4gdW5tb2RpZmlhYmxlIGxpc3QiKSl9fQpILncyLnByb3RvdHlwZT17fQpILnd2LnByb3RvdHlwZT17
-CmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLl9oYXNoQ29kZQppZihzIT1udWxsKXJldHVybiBzCnM9
-NTM2ODcwOTExJjY2NDU5NypKLmhmKHRoaXMuYSkKdGhpcy5faGFzaENvZGU9cwpyZXR1cm4gc30sCnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuJ1N5bWJvbCgiJytILkVqKHRoaXMuYSkrJyIpJ30sCkROOmZ1bmN0aW9u
-KGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9mIEgud3YmJnRoaXMuYT09
-Yi5hfSwKJGlHRDoxfQpILlBELnByb3RvdHlwZT17fQpILldVLnByb3RvdHlwZT17CmdsMDpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRo
-aXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpzLmMuYShiKQpzLlFbMV0uYShj
-KQpILmRjKCl9LApnUHU6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMucTQoYSxILkxoKHRoaXMpLkMoIk4z
-PDEsMj4iKSl9LApxNDpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKcmV0dXJuIFAubDAoZnVuY3Rpb24o
-KXt2YXIgcj1hCnZhciBxPTAscD0xLG8sbixtLGwsawpyZXR1cm4gZnVuY3Rpb24gJGFzeW5jJGdQdShj
-LGQpe2lmKGM9PT0xKXtvPWQKcT1wfXdoaWxlKHRydWUpc3dpdGNoKHEpe2Nhc2UgMDpuPXMuZ1YoKSxu
-PW4uZ2t6KG4pLG09SC5MaChzKSxtPW0uQygiQDwxPiIpLktxKG0uUVsxXSkuQygiTjM8MSwyPiIpCmNh
-c2UgMjppZighbi5GKCkpe3E9MwpicmVha31sPW4uZ2woKQprPXMucSgwLGwpCmsudG9TdHJpbmcKcT00
-CnJldHVybiBuZXcgUC5OMyhsLGssbSkKY2FzZSA0OnE9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgo
-KQpjYXNlIDE6cmV0dXJuIFAuWW0obyl9fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ0E6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCng0OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhIT0ic3Ry
-aW5nIilyZXR1cm4hMQppZigiX19wcm90b19fIj09PWEpcmV0dXJuITEKcmV0dXJuIHRoaXMuYi5oYXNP
-d25Qcm9wZXJ0eShhKX0sCnE6ZnVuY3Rpb24oYSxiKXtpZighdGhpcy54NChiKSlyZXR1cm4gbnVsbApy
-ZXR1cm4gdGhpcy5xUChiKX0sCnFQOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC5oKGEpXX0sCks6
-ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvPUguTGgodGhpcykKby5DKCJ+KDEsMikiKS5hKGIpCnM9
-dGhpcy5jCmZvcihyPXMubGVuZ3RoLG89by5RWzFdLHE9MDtxPHI7KytxKXtwPXNbcV0KYi4kMihwLG8u
-YSh0aGlzLnFQKHApKSl9fSwKZ1Y6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEguWFIodGhpcyxILkxoKHRo
-aXMpLkMoIlhSPDE+IikpfX0KSC5YUi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
-cy5hLmMKcmV0dXJuIG5ldyBKLm0xKHMscy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX0sCmdBOmZ1
-bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYy5sZW5ndGh9fQpILkxJLnByb3RvdHlwZT17CmdXYTpmdW5j
-dGlvbigpe3ZhciBzPXRoaXMuYQpyZXR1cm4gc30sCmduZDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89
-dGhpcwppZihvLmM9PT0xKXJldHVybiBDLmhVCnM9by5kCnI9cy5sZW5ndGgtby5lLmxlbmd0aC1vLmYK
-aWYocj09PTApcmV0dXJuIEMuaFUKcT1bXQpmb3IocD0wO3A8cjsrK3Ape2lmKHA+PXMubGVuZ3RoKXJl
-dHVybiBILk9IKHMscCkKcS5wdXNoKHNbcF0pfXJldHVybiBKLnpDKHEpfSwKZ1ZtOmZ1bmN0aW9uKCl7
-dmFyIHMscixxLHAsbyxuLG0sbCxrPXRoaXMKaWYoay5jIT09MClyZXR1cm4gQy5XTwpzPWsuZQpyPXMu
-bGVuZ3RoCnE9ay5kCnA9cS5sZW5ndGgtci1rLmYKaWYocj09PTApcmV0dXJuIEMuV08Kbz1uZXcgSC5O
-NSh0LmVvKQpmb3Iobj0wO248cjsrK24pe2lmKG4+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsbikKbT1z
-W25dCmw9cCtuCmlmKGw8MHx8bD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSxsKQpvLlkoMCxuZXcgSC53
-dihtKSxxW2xdKX1yZXR1cm4gbmV3IEguUEQobyx0LmdGKX0sCiRpdlE6MX0KSC5Dai5wcm90b3R5cGU9
-ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzCkguaChhKQpzPXRoaXMuYQpzLmI9cy5iKyIkIitILkVqKGEp
-CkMuTm0uaSh0aGlzLmIsYSkKQy5ObS5pKHRoaXMuYyxiKTsrK3MuYX0sCiRTOjE0fQpILmY5LnByb3Rv
-dHlwZT17CnFTOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLHA9bmV3IFJlZ0V4cChxLmEpLmV4ZWMo
-YSkKaWYocD09bnVsbClyZXR1cm4gbnVsbApzPU9iamVjdC5jcmVhdGUobnVsbCkKcj1xLmIKaWYociE9
-PS0xKXMuYXJndW1lbnRzPXBbcisxXQpyPXEuYwppZihyIT09LTEpcy5hcmd1bWVudHNFeHByPXBbcisx
-XQpyPXEuZAppZihyIT09LTEpcy5leHByPXBbcisxXQpyPXEuZQppZihyIT09LTEpcy5tZXRob2Q9cFty
-KzFdCnI9cS5mCmlmKHIhPT0tMSlzLnJlY2VpdmVyPXBbcisxXQpyZXR1cm4gc319CkguVzAucHJvdG90
-eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4iTm9TdWNoTWV0
-aG9kRXJyb3I6ICIrSC5Faih0aGlzLmEpCnJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5v
-dCBmb3VuZDogJyIrcysiJyBvbiBudWxsIn19CkguYXoucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2
-YXIgcyxyPXRoaXMscT0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciLHA9ci5i
-CmlmKHA9PW51bGwpcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guRWooci5hKQpzPXIuYwppZihz
-PT1udWxsKXJldHVybiBxK3ArIicgKCIrSC5FaihyLmEpKyIpIgpyZXR1cm4gcStwKyInIG9uICciK3Mr
-IicgKCIrSC5FaihyLmEpKyIpIn19CkgudlYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzLmEKcmV0dXJuIHMubGVuZ3RoPT09MD8iRXJyb3IiOiJFcnJvcjogIitzfX0KSC50ZS5wcm90b3R5
-cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJUaHJvdyBvZiBudWxsICgnIisodGhpcy5hPT09bnVsbD8i
-bnVsbCI6InVuZGVmaW5lZCIpKyInIGZyb20gSmF2YVNjcmlwdCkifSwKJGlSejoxfQpILmJxLnByb3Rv
-dHlwZT17fQpILlhPLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmIKaWYociE9
-bnVsbClyZXR1cm4gcgpyPXRoaXMuYQpzPXIhPT1udWxsJiZ0eXBlb2Ygcj09PSJvYmplY3QiP3Iuc3Rh
-Y2s6bnVsbApyZXR1cm4gdGhpcy5iPXM9PW51bGw/IiI6c30sCiRpR3o6MX0KSC52LnByb3RvdHlwZT17
-Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5jb25zdHJ1Y3RvcixyPXM9PW51bGw/bnVsbDpzLm5hbWUK
-cmV0dXJuIkNsb3N1cmUgJyIrSC5OUShyPT1udWxsPyJ1bmtub3duIjpyKSsiJyJ9LAokaUVIOjEsCmdL
-dTpmdW5jdGlvbigpe3JldHVybiB0aGlzfSwKJEM6IiQxIiwKJFI6MSwKJEQ6bnVsbH0KSC5sYy5wcm90
-b3R5cGU9e30KSC56eC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuJHN0YXRpY19u
-YW1lCmlmKHM9PW51bGwpcmV0dXJuIkNsb3N1cmUgb2YgdW5rbm93biBzdGF0aWMgbWV0aG9kIgpyZXR1
-cm4iQ2xvc3VyZSAnIitILk5RKHMpKyInIn19CkguclQucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxi
-KXt2YXIgcz10aGlzCmlmKGI9PW51bGwpcmV0dXJuITEKaWYocz09PWIpcmV0dXJuITAKaWYoIShiIGlu
-c3RhbmNlb2YgSC5yVCkpcmV0dXJuITEKcmV0dXJuIHMuYT09PWIuYSYmcy5iPT09Yi5iJiZzLmM9PT1i
-LmN9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmMKaWYocj09bnVsbClzPUguZVEodGhpcy5h
-KQplbHNlIHM9dHlwZW9mIHIhPT0ib2JqZWN0Ij9KLmhmKHIpOkguZVEocikKcmV0dXJuKHNeSC5lUSh0
-aGlzLmIpKT4+PjB9LAp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYwppZihzPT1udWxsKXM9dGhpcy5h
-CnJldHVybiJDbG9zdXJlICciK0guRWoodGhpcy5kKSsiJyBvZiAiKygiSW5zdGFuY2Ugb2YgJyIrSC5F
-aihILk0ocykpKyInIil9fQpILkVxLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJ1bnRp
-bWVFcnJvcjogIit0aGlzLmF9fQpILmtZLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkFz
-c2VydGlvbiBmYWlsZWQ6ICIrUC5wKHRoaXMuYSl9fQpILmtyLnByb3RvdHlwZT17fQpILk41LnByb3Rv
-dHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJu
-IHRoaXMuYT09PTB9LApnVjpmdW5jdGlvbigpe3JldHVybiBuZXcgSC5pNSh0aGlzLEguTGgodGhpcyku
-QygiaTU8MT4iKSl9LAp4NDpmdW5jdGlvbihhKXt2YXIgcyxyCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7
-cz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhpcy5YdShzLGEpfWVsc2V7cj10aGlz
-LkNYKGEpCnJldHVybiByfX0sCkNYOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZAppZihzPT1udWxsKXJl
-dHVybiExCnJldHVybiB0aGlzLkZoKHRoaXMuQnQocyxKLmhmKGEpJjB4M2ZmZmZmZiksYSk+PTB9LApx
-OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbz10aGlzLG49bnVsbAppZih0eXBlb2YgYj09InN0cmlu
-ZyIpe3M9by5iCmlmKHM9PW51bGwpcmV0dXJuIG4Kcj1vLmoyKHMsYikKcT1yPT1udWxsP246ci5iCnJl
-dHVybiBxfWVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIiJiYoYiYweDNmZmZmZmYpPT09Yil7cD1vLmMK
-aWYocD09bnVsbClyZXR1cm4gbgpyPW8uajIocCxiKQpxPXI9PW51bGw/bjpyLmIKcmV0dXJuIHF9ZWxz
-ZSByZXR1cm4gby5hYShiKX0sCmFhOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLmQKaWYocT09bnVs
-bClyZXR1cm4gbnVsbApzPXRoaXMuQnQocSxKLmhmKGEpJjB4M2ZmZmZmZikKcj10aGlzLkZoKHMsYSkK
-aWYocjwwKXJldHVybiBudWxsCnJldHVybiBzW3JdLmJ9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
-LHEscCxvLG4sbT10aGlzLGw9SC5MaChtKQpsLmMuYShiKQpsLlFbMV0uYShjKQppZih0eXBlb2YgYj09
-InN0cmluZyIpe3M9bS5iCm0uRUgocz09bnVsbD9tLmI9bS56SygpOnMsYixjKX1lbHNlIGlmKHR5cGVv
-ZiBiPT0ibnVtYmVyIiYmKGImMHgzZmZmZmZmKT09PWIpe3I9bS5jCm0uRUgocj09bnVsbD9tLmM9bS56
-SygpOnIsYixjKX1lbHNle3E9bS5kCmlmKHE9PW51bGwpcT1tLmQ9bS56SygpCnA9Si5oZihiKSYweDNm
-ZmZmZmYKbz1tLkJ0KHEscCkKaWYobz09bnVsbCltLkVJKHEscCxbbS5IbihiLGMpXSkKZWxzZXtuPW0u
-RmgobyxiKQppZihuPj0wKW9bbl0uYj1jCmVsc2Ugby5wdXNoKG0uSG4oYixjKSl9fX0sCks6ZnVuY3Rp
-b24oYSxiKXt2YXIgcyxyLHE9dGhpcwpILkxoKHEpLkMoIn4oMSwyKSIpLmEoYikKcz1xLmUKcj1xLnIK
-Zm9yKDtzIT1udWxsOyl7Yi4kMihzLmEscy5iKQppZihyIT09cS5yKXRocm93IEguYihQLmE0KHEpKQpz
-PXMuY319LApFSDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscj10aGlzLHE9SC5MaChyKQpxLmMuYShiKQpx
-LlFbMV0uYShjKQpzPXIuajIoYSxiKQppZihzPT1udWxsKXIuRUkoYSxiLHIuSG4oYixjKSkKZWxzZSBz
-LmI9Y30sCmtzOmZ1bmN0aW9uKCl7dGhpcy5yPXRoaXMucisxJjY3MTA4ODYzfSwKSG46ZnVuY3Rpb24o
-YSxiKXt2YXIgcz10aGlzLHI9SC5MaChzKSxxPW5ldyBILmRiKHIuYy5hKGEpLHIuUVsxXS5hKGIpKQpp
-ZihzLmU9PW51bGwpcy5lPXMuZj1xCmVsc2V7cj1zLmYKci50b1N0cmluZwpxLmQ9cgpzLmY9ci5jPXF9
-KytzLmEKcy5rcygpCnJldHVybiBxfSwKRmg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGE9PW51bGwp
-cmV0dXJuLTEKcz1hLmxlbmd0aApmb3Iocj0wO3I8czsrK3IpaWYoSi5STShhW3JdLmEsYikpcmV0dXJu
-IHIKcmV0dXJuLTF9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKajI6ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gYVtiXX0sCkJ0OmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19LApFSTpmdW5jdGlv
-bihhLGIsYyl7YVtiXT1jfSwKcm46ZnVuY3Rpb24oYSxiKXtkZWxldGUgYVtiXX0sClh1OmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIHRoaXMuajIoYSxiKSE9bnVsbH0sCnpLOmZ1bmN0aW9uKCl7dmFyIHM9Ijxub24t
-aWRlbnRpZmllci1rZXk+IixyPU9iamVjdC5jcmVhdGUobnVsbCkKdGhpcy5FSShyLHMscikKdGhpcy5y
-bihyLHMpCnJldHVybiByfSwKJGlGbzoxfQpILmRiLnByb3RvdHlwZT17fQpILmk1LnByb3RvdHlwZT17
-CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
-cy5hLmE9PT0wfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYSxyPW5ldyBILk42KHMscy5yLHRo
-aXMuJHRpLkMoIk42PDE+IikpCnIuYz1zLmUKcmV0dXJuIHJ9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVy
-biB0aGlzLmEueDQoYil9fQpILk42LnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMu
-ZH0sCkY6ZnVuY3Rpb24oKXt2YXIgcyxyPXRoaXMscT1yLmEKaWYoci5iIT09cS5yKXRocm93IEguYihQ
-LmE0KHEpKQpzPXIuYwppZihzPT1udWxsKXtyLnNxWShudWxsKQpyZXR1cm4hMX1lbHNle3Iuc3FZKHMu
-YSkKci5jPXMuYwpyZXR1cm4hMH19LApzcVk6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/
-IikuYShhKX0sCiRpQW46MX0KSC5kQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
-cy5hKGEpfSwKJFM6NH0KSC53Ti5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-LmEoYSxiKX0sCiRTOjM0fQpILlZYLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LmEoSC5oKGEpKX0sCiRTOjMyfQpILlZSLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJl
-Z0V4cC8iK3RoaXMuYSsiLyIrdGhpcy5iLmZsYWdzfSwKZ0hjOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxy
-PXMuYwppZihyIT1udWxsKXJldHVybiByCnI9cy5iCnJldHVybiBzLmM9SC52NChzLmEsci5tdWx0aWxp
-bmUsIXIuaWdub3JlQ2FzZSxyLnVuaWNvZGUsci5kb3RBbGwsITApfSwKZGQ6ZnVuY3Rpb24oYSxiKXty
-ZXR1cm4gbmV3IEguS1codGhpcyxiLDApfSwKVVo6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyPXRoaXMuZ0hj
-KCkKci5sYXN0SW5kZXg9YgpzPXIuZXhlYyhhKQppZihzPT1udWxsKXJldHVybiBudWxsCnJldHVybiBu
-ZXcgSC5FSyhzKX0sCiRpdlg6MSwKJGl3TDoxfQpILkVLLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxi
-KXt2YXIgcwpILnVQKGIpCnM9dGhpcy5iCmlmKGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcmV0
-dXJuIHNbYl19LAokaU9kOjEsCiRpaWI6MX0KSC5LVy5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7
-cmV0dXJuIG5ldyBILlBiKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguUGIucHJvdG90eXBlPXsKZ2w6
-ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmQKcy50b1N0cmluZwpyZXR1cm4gc30sCkY6ZnVuY3Rpb24oKXt2
-YXIgcyxyLHEscCxvLG4sbT10aGlzLGw9bS5iCmlmKGw9PW51bGwpcmV0dXJuITEKcz1tLmMKcj1sLmxl
-bmd0aAppZihzPD1yKXtxPW0uYQpwPXEuVVoobCxzKQppZihwIT1udWxsKXttLmQ9cApzPXAuYgpvPXMu
-aW5kZXgKbj1vK3NbMF0ubGVuZ3RoCmlmKG89PT1uKXtpZihxLmIudW5pY29kZSl7cz1tLmMKcT1zKzEK
-aWYocTxyKXtzPUMueEIubShsLHMpCmlmKHM+PTU1Mjk2JiZzPD01NjMxOSl7cz1DLnhCLm0obCxxKQpz
-PXM+PTU2MzIwJiZzPD01NzM0M31lbHNlIHM9ITF9ZWxzZSBzPSExfWVsc2Ugcz0hMQpuPShzP24rMTpu
-KSsxfW0uYz1uCnJldHVybiEwfX1tLmI9bS5kPW51bGwKcmV0dXJuITF9LAokaUFuOjF9CkgudFEucHJv
-dG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKaWYoYiE9PTApSC52aChQLk83KGIsbnVsbCkp
-CnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3Jl
-dHVybiBuZXcgSC5TZCh0aGlzLmEsdGhpcy5iLHRoaXMuYyl9fQpILlNkLnByb3RvdHlwZT17CkY6ZnVu
-Y3Rpb24oKXt2YXIgcyxyLHE9dGhpcyxwPXEuYyxvPXEuYixuPW8ubGVuZ3RoLG09cS5hLGw9bS5sZW5n
-dGgKaWYocCtuPmwpe3EuZD1udWxsCnJldHVybiExfXM9bS5pbmRleE9mKG8scCkKaWYoczwwKXtxLmM9
-bCsxCnEuZD1udWxsCnJldHVybiExfXI9cytuCnEuZD1uZXcgSC50UShzLG8pCnEuYz1yPT09cS5jP3Ir
-MTpyCnJldHVybiEwfSwKZ2w6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmQKcy50b1N0cmluZwpyZXR1cm4g
-c30sCiRpQW46MX0KSC5FVC5wcm90b3R5cGU9eyRpRVQ6MSwkaWVxOjF9CkguTFoucHJvdG90eXBlPXsK
-Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKJGlYajoxfQpILkRnLnByb3RvdHlwZT17CnE6
-ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX0sClk6ZnVu
-Y3Rpb24oYSxiLGMpe0guR0goYykKSC5vZChiLGEsYS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGlj
-WDoxLAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7SC51UChjKQpILm9k
-KGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUToxLAokaWNYOjEsCiRpek06MX0KSC54ai5wcm90b3R5
-cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19
-fQpILmRFLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3Ro
-KQpyZXR1cm4gYVtiXX19CkguWkEucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5v
-ZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5kVC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEs
-Yil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILlBxLnByb3RvdHlwZT17
-CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19Ckgu
-ZUUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihh
-LGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5WNi5wcm90b3R5cGU9
-ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpI
-Lm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LAokaVY2OjEsCiRpbjY6MX0KSC5SRy5wcm90b3R5
-cGU9e30KSC5WUC5wcm90b3R5cGU9e30KSC5XQi5wcm90b3R5cGU9e30KSC5aRy5wcm90b3R5cGU9e30K
-SC5KYy5wcm90b3R5cGU9ewpDOmZ1bmN0aW9uKGEpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLHRo
-aXMsYSl9LApLcTpmdW5jdGlvbihhKXtyZXR1cm4gSC52NSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0K
-SC5HLnByb3RvdHlwZT17fQpILnU5LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-YX19CkguaU0ucHJvdG90eXBlPXt9ClAudGgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHM9
-dGhpcy5hLHI9cy5hCnMuYT1udWxsCnIuJDAoKX0sCiRTOjEwfQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1
-bmN0aW9uKGEpe3ZhciBzLHIKdGhpcy5hLmE9dC5NLmEoYSkKcz10aGlzLmIKcj10aGlzLmMKcy5maXJz
-dENoaWxkP3MucmVtb3ZlQ2hpbGQocik6cy5hcHBlbmRDaGlsZChyKX0sCiRTOjUxfQpQLlZzLnByb3Rv
-dHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0
-LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzow
-fQpQLlczLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxs
-KXNlbGYuc2V0VGltZW91dChILnRSKG5ldyBQLnlIKHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIo
-UC5MNCgiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5kLiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVu
-Y3Rpb24oKXt0aGlzLmIuJDAoKX0sCiRDOiIkMCIsCiRSOjAsCiRTOjF9ClAuaWgucHJvdG90eXBlPXsK
-YU06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyPXRoaXMscT1yLiR0aQpxLkMoIjEvPyIpLmEoYikKaWYoIXIu
-YilyLmEuWGYoYikKZWxzZXtzPXIuYQppZihxLkMoImI4PDE+IikuYihiKSlzLmNVKGIpCmVsc2Ugcy5Y
-MihxLmMuYShiKSl9fSwKdzA6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihiPT1udWxsKWI9UC52MChhKQpz
-PXRoaXMuYQppZih0aGlzLmIpcy5aTChhLGIpCmVsc2Ugcy5OayhhLGIpfX0KUC5XTS5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLiQyKDAsYSl9LAokUzo0Mn0KUC5TWC5wcm90b3R5
-cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS4kMigxLG5ldyBILmJxKGEsdC5sLmEoYikpKX0sCiRD
-OiIkMiIsCiRSOjIsCiRTOjUzfQpQLkdzLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5h
-KEgudVAoYSksYil9LAokUzoyNX0KUC5GeS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJJ
-dGVyYXRpb25NYXJrZXIoIit0aGlzLmIrIiwgIitILkVqKHRoaXMuYSkrIikifX0KUC5HVi5wcm90b3R5
-cGU9ewpnbDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYwppZihzPT1udWxsKXJldHVybiB0aGlzLiR0aS5j
-LmEodGhpcy5iKQpyZXR1cm4gcy5nbCgpfSwKRjpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtPXRo
-aXMKZm9yKHM9bS4kdGkuQygiQW48MT4iKTshMDspe3I9bS5jCmlmKHIhPW51bGwpaWYoci5GKCkpcmV0
-dXJuITAKZWxzZSBtLnNYOShudWxsKQpxPWZ1bmN0aW9uKGEsYixjKXt2YXIgbCxrPWIKd2hpbGUodHJ1
-ZSl0cnl7cmV0dXJuIGEoayxsKX1jYXRjaChqKXtsPWoKaz1jfX0obS5hLDAsMSkKaWYocSBpbnN0YW5j
-ZW9mIFAuRnkpe3A9cS5iCmlmKHA9PT0yKXtvPW0uZAppZihvPT1udWxsfHxvLmxlbmd0aD09PTApe20u
-c0VDKG51bGwpCnJldHVybiExfWlmKDA+PW8ubGVuZ3RoKXJldHVybiBILk9IKG8sLTEpCm0uYT1vLnBv
-cCgpCmNvbnRpbnVlfWVsc2V7cj1xLmEKaWYocD09PTMpdGhyb3cgcgplbHNle249cy5hKEouSVQocikp
-CmlmKG4gaW5zdGFuY2VvZiBQLkdWKXtyPW0uZAppZihyPT1udWxsKXI9bS5kPVtdCkMuTm0uaShyLG0u
-YSkKbS5hPW4uYQpjb250aW51ZX1lbHNle20uc1g5KG4pCmNvbnRpbnVlfX19fWVsc2V7bS5zRUMocSkK
-cmV0dXJuITB9fXJldHVybiExfSwKc0VDOmZ1bmN0aW9uKGEpe3RoaXMuYj10aGlzLiR0aS5DKCIxPyIp
-LmEoYSl9LApzWDk6ZnVuY3Rpb24oYSl7dGhpcy5jPXRoaXMuJHRpLkMoIkFuPDE+PyIpLmEoYSl9LAok
-aUFuOjF9ClAucTQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5HVih0aGlz
-LmEoKSx0aGlzLiR0aS5DKCJHVjwxPiIpKX19ClAuUGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxi
-KXt2YXIgcwpQLlVJKGEsImVycm9yIix0LkspCnM9dGhpcy5hCmlmKHMuYSE9PTApdGhyb3cgSC5iKFAu
-UFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQppZihiPT1udWxsKWI9UC52MChhKQpzLk5rKGEs
-Yil9LApwbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9
-ewphTTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy4kdGkKci5DKCIxLz8iKS5hKGIpCnM9dGhpcy5h
-CmlmKHMuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQpzLlhm
-KHIuQygiMS8iKS5hKGIpKX19ClAuRmUucHJvdG90eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMu
-YyYxNSkhPT02KXJldHVybiEwCnJldHVybiB0aGlzLmIuYi5idih0LmFsLmEodGhpcy5kKSxhLmEsdC55
-LHQuSyl9LApLdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmUscj10LnoscT10LksscD10aGlzLiR0aS5D
-KCIyLyIpLG89dGhpcy5iLmIKaWYodC5hZy5iKHMpKXJldHVybiBwLmEoby5ycChzLGEuYSxhLmIscixx
-LHQubCkpCmVsc2UgcmV0dXJuIHAuYShvLmJ2KHQuYkkuYShzKSxhLmEscixxKSl9fQpQLnZzLnByb3Rv
-dHlwZT17ClNxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscD10aGlzLiR0aQpwLktxKGMpLkMoIjEv
-KDIpIikuYShhKQpzPSQuWDMKaWYocyE9PUMuTlUpe2MuQygiQDwwLz4iKS5LcShwLmMpLkMoIjEoMiki
-KS5hKGEpCmlmKGIhPW51bGwpYj1QLlZIKGIscyl9cj1uZXcgUC52cygkLlgzLGMuQygidnM8MD4iKSkK
-cT1iPT1udWxsPzE6Mwp0aGlzLnhmKG5ldyBQLkZlKHIscSxhLGIscC5DKCJAPDE+IikuS3EoYykuQygi
-RmU8MSwyPiIpKSkKcmV0dXJuIHJ9LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVs
-bCxiKX0sClFkOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPXRoaXMuJHRpCnIuS3EoYykuQygiMS8oMiki
-KS5hKGEpCnM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnRoaXMueGYobmV3IFAuRmUocywxOSxh
-LGIsci5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHN9LAp4ZjpmdW5jdGlvbihh
-KXt2YXIgcyxyPXRoaXMscT1yLmEKaWYocTw9MSl7YS5hPXQuRi5hKHIuYykKci5jPWF9ZWxzZXtpZihx
-PT09Mil7cz10LmMuYShyLmMpCnE9cy5hCmlmKHE8NCl7cy54ZihhKQpyZXR1cm59ci5hPXEKci5jPXMu
-Y31QLlRrKG51bGwsbnVsbCxyLmIsdC5NLmEobmV3IFAuZGEocixhKSkpfX0sCmpROmZ1bmN0aW9uKGEp
-e3ZhciBzLHIscSxwLG8sbixtPXRoaXMsbD17fQpsLmE9YQppZihhPT1udWxsKXJldHVybgpzPW0uYQpp
-ZihzPD0xKXtyPXQuRi5hKG0uYykKbS5jPWEKaWYociE9bnVsbCl7cT1hLmEKZm9yKHA9YTtxIT1udWxs
-O3A9cSxxPW8pbz1xLmEKcC5hPXJ9fWVsc2V7aWYocz09PTIpe249dC5jLmEobS5jKQpzPW4uYQppZihz
-PDQpe24ualEoYSkKcmV0dXJufW0uYT1zCm0uYz1uLmN9bC5hPW0uTjgoYSkKUC5UayhudWxsLG51bGws
-bS5iLHQuTS5hKG5ldyBQLm9RKGwsbSkpKX19LAphaDpmdW5jdGlvbigpe3ZhciBzPXQuRi5hKHRoaXMu
-YykKdGhpcy5jPW51bGwKcmV0dXJuIHRoaXMuTjgocyl9LApOODpmdW5jdGlvbihhKXt2YXIgcyxyLHEK
-Zm9yKHM9YSxyPW51bGw7cyE9bnVsbDtyPXMscz1xKXtxPXMuYQpzLmE9cn1yZXR1cm4gcn0sCkhIOmZ1
-bmN0aW9uKGEpe3ZhciBzLHI9dGhpcyxxPXIuJHRpCnEuQygiMS8iKS5hKGEpCmlmKHEuQygiYjg8MT4i
-KS5iKGEpKWlmKHEuYihhKSlQLkE5KGEscikKZWxzZSBQLmszKGEscikKZWxzZXtzPXIuYWgoKQpxLmMu
-YShhKQpyLmE9NApyLmM9YQpQLkhaKHIscyl9fSwKWDI6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzCnIu
-JHRpLmMuYShhKQpzPXIuYWgoKQpyLmE9NApyLmM9YQpQLkhaKHIscyl9LApaTDpmdW5jdGlvbihhLGIp
-e3ZhciBzLHIscT10aGlzCnQubC5hKGIpCnM9cS5haCgpCnI9UC5UbChhLGIpCnEuYT04CnEuYz1yClAu
-SFoocSxzKX0sClhmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuJHRpCnMuQygiMS8iKS5hKGEpCmlmKHMu
-QygiYjg8MT4iKS5iKGEpKXt0aGlzLmNVKGEpCnJldHVybn10aGlzLndVKHMuYy5hKGEpKX0sCndVOmZ1
-bmN0aW9uKGEpe3ZhciBzPXRoaXMKcy4kdGkuYy5hKGEpCnMuYT0xClAuVGsobnVsbCxudWxsLHMuYix0
-Lk0uYShuZXcgUC5ydChzLGEpKSl9LApjVTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLHI9cy4kdGkKci5D
-KCJiODwxPiIpLmEoYSkKaWYoci5iKGEpKXtpZihhLmE9PT04KXtzLmE9MQpQLlRrKG51bGwsbnVsbCxz
-LmIsdC5NLmEobmV3IFAuS0YocyxhKSkpfWVsc2UgUC5BOShhLHMpCnJldHVybn1QLmszKGEscyl9LApO
-azpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxsLHRoaXMuYix0Lk0uYShuZXcgUC5a
-TCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuSFoo
-dGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0
-aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
-cz10aGlzLmEKcy5hPTAKcy5ISChhKX0sCiRTOjEwfQpQLlU3LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9u
-KGEsYil7dGhpcy5hLlpMKGEsdC5sLmEoYikpfSwKJEM6IiQyIiwKJFI6MiwKJFM6Mjl9ClAudnIucHJv
-dG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLnJ0
-LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLlgyKHRoaXMuYil9LAokUzowfQpQLktGLnBy
-b3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5BOSh0aGlzLmIsdGhpcy5hKX0sCiRTOjB9ClAuWkwucHJv
-dG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLlJU
-LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09dGhpcyxsPW51bGwKdHJ5
-e3E9bS5hLmEKbD1xLmIuYi56eih0LmZPLmEocS5kKSx0LnopfWNhdGNoKHApe3M9SC5SdShwKQpyPUgu
-dHMocCkKaWYobS5jKXtxPXQubi5hKG0uYi5hLmMpLmEKbz1zCm89cT09bnVsbD9vPT1udWxsOnE9PT1v
-CnE9b31lbHNlIHE9ITEKbz1tLmEKaWYocSlvLmM9dC5uLmEobS5iLmEuYykKZWxzZSBvLmM9UC5UbChz
-LHIpCm8uYj0hMApyZXR1cm59aWYobCBpbnN0YW5jZW9mIFAudnMmJmwuYT49NCl7aWYobC5hPT09OCl7
-cT1tLmEKcS5jPXQubi5hKGwuYykKcS5iPSEwfXJldHVybn1pZih0LmQuYihsKSl7bj1tLmIuYQpxPW0u
-YQpxLmM9bC5XNyhuZXcgUC5qWihuKSx0LnopCnEuYj0hMX19LAokUzoxfQpQLmpaLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAokUzozMH0KUC5ycS5wcm90b3R5cGU9ewokMDpm
-dW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGwKdHJ5e3E9dGhpcy5hCnA9cS5hCm89cC4kdGkKbj1v
-LmMKbT1uLmEodGhpcy5iKQpxLmM9cC5iLmIuYnYoby5DKCIyLygxKSIpLmEocC5kKSxtLG8uQygiMi8i
-KSxuKX1jYXRjaChsKXtzPUguUnUobCkKcj1ILnRzKGwpCnE9dGhpcy5hCnEuYz1QLlRsKHMscikKcS5i
-PSEwfX0sCiRTOjF9ClAuUlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4s
-bSxsLGs9dGhpcwp0cnl7cz10Lm4uYShrLmEuYS5jKQpwPWsuYgppZihILm9UKHAuYS5IUihzKSkmJnAu
-YS5lIT1udWxsKXtwLmM9cC5hLkt3KHMpCnAuYj0hMX19Y2F0Y2gobyl7cj1ILlJ1KG8pCnE9SC50cyhv
-KQpwPXQubi5hKGsuYS5hLmMpCm49cC5hCm09cgpsPWsuYgppZihuPT1udWxsP209PW51bGw6bj09PW0p
-bC5jPXAKZWxzZSBsLmM9UC5UbChyLHEpCmwuYj0hMH19LAokUzoxfQpQLk9NLnByb3RvdHlwZT17fQpQ
-LnFoLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLHA9e30sbz1uZXcgUC52
-cygkLlgzLHQuZkopCnAuYT0wCnM9SC5MaChxKQpyPXMuQygifigxKT8iKS5hKG5ldyBQLkI1KHAscSkp
-CnQuWi5hKG5ldyBQLnVPKHAsbykpClcuSkUocS5hLHEuYixyLCExLHMuYykKcmV0dXJuIG99fQpQLkI1
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guTGgodGhpcy5iKS5jLmEoYSk7Kyt0aGlzLmEuYX0s
-CiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEguTGgodGhpcy5iKS5DKCJjOCgxKSIpfX0KUC51Ty5wcm90b3R5
-cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi5ISCh0aGlzLmEuYSl9LAokUzowfQpQLk1PLnByb3RvdHlw
-ZT17fQpQLmtULnByb3RvdHlwZT17fQpQLnhJLnByb3RvdHlwZT17fQpQLkN3LnByb3RvdHlwZT17Cnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIEguRWoodGhpcy5hKX0sCiRpWFM6MSwKZ0lJOmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYn19ClAubTAucHJvdG90eXBlPXskaVFtOjF9ClAucEsucHJvdG90eXBlPXsKJDA6ZnVu
-Y3Rpb24oKXt2YXIgcz1ILmIodGhpcy5hKQpzLnN0YWNrPUouaih0aGlzLmIpCnRocm93IHN9LAokUzow
-fQpQLkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPW51bGwKdC5NLmEoYSkK
-dHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJufVAuVDgocCxwLHRoaXMsYSx0LkgpfWNhdGNo
-KHEpe3M9SC5SdShxKQpyPUgudHMocSkKUC5MMihwLHAsdGhpcyxzLHQubC5hKHIpKX19LApEbDpmdW5j
-dGlvbihhLGIsYyl7dmFyIHMscixxLHA9bnVsbApjLkMoIn4oMCkiKS5hKGEpCmMuYShiKQp0cnl7aWYo
-Qy5OVT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYocCxwLHRoaXMsYSxiLHQuSCxjKX1jYXRjaChx
-KXtzPUguUnUocSkKcj1ILnRzKHEpClAuTDIocCxwLHRoaXMscyx0LmwuYShyKSl9fSwKUlQ6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMoIjAoKSIpLmEoYSksYil9LApHWTpmdW5jdGlv
-bihhKXtyZXR1cm4gbmV3IFAuVnAodGhpcyx0Lk0uYShhKSl9LApQeTpmdW5jdGlvbihhLGIpe3JldHVy
-biBuZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmEoYSksYil9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IG51bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgpIikuYShhKQppZigkLlgzPT09Qy5OVSlyZXR1
-cm4gYS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0aGlzLGEsYil9LApidjpmdW5jdGlvbihhLGIs
-YyxkKXtjLkMoIkA8MD4iKS5LcShkKS5DKCIxKDIpIikuYShhKQpkLmEoYikKaWYoJC5YMz09PUMuTlUp
-cmV0dXJuIGEuJDEoYikKcmV0dXJuIFAueXYobnVsbCxudWxsLHRoaXMsYSxiLGMsZCl9LApycDpmdW5j
-dGlvbihhLGIsYyxkLGUsZil7ZC5DKCJAPDA+IikuS3EoZSkuS3EoZikuQygiMSgyLDMpIikuYShhKQpl
-LmEoYikKZi5hKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQyKGIsYykKcmV0dXJuIFAuUXgobnVs
-bCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfSwKTGo6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGIuQygi
-QDwwPiIpLktxKGMpLktxKGQpLkMoIjEoMiwzKSIpLmEoYSl9fQpQLmhqLnByb3RvdHlwZT17CiQwOmZ1
-bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS56eih0aGlzLmIsdGhpcy5jKX0sCiRTOmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYy5DKCIwKCkiKX19ClAuVnAucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5hLmJIKHRoaXMuYil9LAokUzoxfQpQLk9SLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Zh
-ciBzPXRoaXMuYwpyZXR1cm4gdGhpcy5hLkRsKHRoaXMuYixzLmEoYSkscyl9LAokUzpmdW5jdGlvbigp
-e3JldHVybiB0aGlzLmMuQygifigwKSIpfX0KUC5iNi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7
-dmFyIHM9dGhpcyxyPW5ldyBQLmxtKHMscy5yLEguTGgocykuQygibG08MT4iKSkKci5jPXMuZQpyZXR1
-cm4gcn0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpe3M9dGhpcy5iCmlmKHM9PW51
-bGwpcmV0dXJuITEKcmV0dXJuIHQuVy5hKHNbYl0pIT1udWxsfWVsc2V7cj10aGlzLlBSKGIpCnJldHVy
-biByfX0sClBSOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZAppZihzPT1udWxsKXJldHVybiExCnJldHVy
-biB0aGlzLkRGKHNbdGhpcy5OKGEpXSxhKT49MH0sCmk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9dGhp
-cwpILkxoKHEpLmMuYShiKQppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7cz1x
-LmIKcmV0dXJuIHEuYlEocz09bnVsbD9xLmI9UC5UMigpOnMsYil9ZWxzZSBpZih0eXBlb2YgYj09Im51
-bWJlciImJihiJjEwNzM3NDE4MjMpPT09Yil7cj1xLmMKcmV0dXJuIHEuYlEocj09bnVsbD9xLmM9UC5U
-MigpOnIsYil9ZWxzZSByZXR1cm4gcS5CNyhiKX0sCkI3OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPXRo
-aXMKSC5MaChwKS5jLmEoYSkKcz1wLmQKaWYocz09bnVsbClzPXAuZD1QLlQyKCkKcj1wLk4oYSkKcT1z
-W3JdCmlmKHE9PW51bGwpc1tyXT1bcC55byhhKV0KZWxzZXtpZihwLkRGKHEsYSk+PTApcmV0dXJuITEK
-cS5wdXNoKHAueW8oYSkpfXJldHVybiEwfSwKUjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKaWYodHlw
-ZW9mIGI9PSJzdHJpbmciJiZiIT09Il9fcHJvdG9fXyIpcmV0dXJuIHMuTChzLmIsYikKZWxzZSBpZih0
-eXBlb2YgYj09Im51bWJlciImJihiJjEwNzM3NDE4MjMpPT09YilyZXR1cm4gcy5MKHMuYyxiKQplbHNl
-IHJldHVybiBzLnFnKGIpfSwKcWc6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbz10aGlzLG49by5kCmlm
-KG49PW51bGwpcmV0dXJuITEKcz1vLk4oYSkKcj1uW3NdCnE9by5ERihyLGEpCmlmKHE8MClyZXR1cm4h
-MQpwPXIuc3BsaWNlKHEsMSlbMF0KaWYoMD09PXIubGVuZ3RoKWRlbGV0ZSBuW3NdCm8uR1MocCkKcmV0
-dXJuITB9LApiUTpmdW5jdGlvbihhLGIpe0guTGgodGhpcykuYy5hKGIpCmlmKHQuVy5hKGFbYl0pIT1u
-dWxsKXJldHVybiExCmFbYl09dGhpcy55byhiKQpyZXR1cm4hMH0sCkw6ZnVuY3Rpb24oYSxiKXt2YXIg
-cwppZihhPT1udWxsKXJldHVybiExCnM9dC5XLmEoYVtiXSkKaWYocz09bnVsbClyZXR1cm4hMQp0aGlz
-LkdTKHMpCmRlbGV0ZSBhW2JdCnJldHVybiEwfSwKUzpmdW5jdGlvbigpe3RoaXMucj0xMDczNzQxODIz
-JnRoaXMucisxfSwKeW86ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLHE9bmV3IFAuYm4oSC5MaChyKS5j
-LmEoYSkpCmlmKHIuZT09bnVsbClyLmU9ci5mPXEKZWxzZXtzPXIuZgpzLnRvU3RyaW5nCnEuYz1zCnIu
-Zj1zLmI9cX0rK3IuYQpyLlMoKQpyZXR1cm4gcX0sCkdTOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMscj1h
-LmMscT1hLmIKaWYocj09bnVsbClzLmU9cQplbHNlIHIuYj1xCmlmKHE9PW51bGwpcy5mPXIKZWxzZSBx
-LmM9cjstLXMuYQpzLlMoKX0sCk46ZnVuY3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30s
-CkRGOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihhPT1udWxsKXJldHVybi0xCnM9YS5sZW5ndGgKZm9y
-KHI9MDtyPHM7KytyKWlmKEouUk0oYVtyXS5hLGIpKXJldHVybiByCnJldHVybi0xfX0KUC5ibi5wcm90
-b3R5cGU9e30KUC5sbS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1
-bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYyxxPXMuYQppZihzLmIhPT1xLnIpdGhyb3cgSC5iKFAuYTQo
-cSkpCmVsc2UgaWYocj09bnVsbCl7cy5zaihudWxsKQpyZXR1cm4hMX1lbHNle3Muc2oocy4kdGkuQygi
-MT8iKS5hKHIuYSkpCnMuYz1yLmIKcmV0dXJuITB9fSwKc2o6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMu
-JHRpLkMoIjE/IikuYShhKX0sCiRpQW46MX0KUC5tVy5wcm90b3R5cGU9e30KUC51eS5wcm90b3R5cGU9
-eyRpYlE6MSwkaWNYOjEsJGl6TToxfQpQLmxELnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1
-cm4gbmV3IEguYTcoYSx0aGlzLmdBKGEpLEgueihhKS5DKCJhNzxsRC5FPiIpKX0sCkU6ZnVuY3Rpb24o
-YSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILnooYSkuQygi
-fihsRC5FKSIpLmEoYikKcz10aGlzLmdBKGEpCmZvcihyPTA7cjxzOysrcil7Yi4kMSh0aGlzLnEoYSxy
-KSkKaWYocyE9PXRoaXMuZ0EoYSkpdGhyb3cgSC5iKFAuYTQoYSkpfX0sCmdvcjpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5nQShhKSE9PTB9LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC56KGEpCnJldHVy
-biBuZXcgSC5sSihhLHMuS3EoYykuQygiMShsRC5FKSIpLmEoYikscy5DKCJAPGxELkU+IikuS3EoYyku
-QygibEo8MSwyPiIpKX0sCmR1OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzCkgueihhKS5DKCJsRC5FPyIp
-LmEoZCkKUC5qQihiLGMsdGhpcy5nQShhKSkKZm9yKHM9YjtzPGM7KytzKXRoaXMuWShhLHMsZCl9LAp3
-OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9fQpQLmlsLnByb3RvdHlwZT17fQpQLnJh
-LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmEKaWYoIXIuYSl0aGlzLmIu
-YSs9IiwgIgpyLmE9ITEKcj10aGlzLmIKcz1yLmErPUguRWooYSkKci5hPXMrIjogIgpyLmErPUguRWoo
-Yil9LAokUzoxMn0KUC5Zay5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILkxoKHRo
-aXMpLkMoIn4oWWsuSyxZay5WKSIpLmEoYikKZm9yKHM9Si5JVCh0aGlzLmdWKCkpO3MuRigpOyl7cj1z
-LmdsKCkKYi4kMihyLHRoaXMucSgwLHIpKX19LApnUHU6ZnVuY3Rpb24oYSl7cmV0dXJuIEouTTEodGhp
-cy5nVigpLG5ldyBQLnlRKHRoaXMpLEguTGgodGhpcykuQygiTjM8WWsuSyxZay5WPiIpKX0sCng0OmZ1
-bmN0aW9uKGEpe3JldHVybiBKLnpsKHRoaXMuZ1YoKSxhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBK
-LkhtKHRoaXMuZ1YoKSl9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudVUodGhpcy5nVigpKX0sCnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIFAubk8odGhpcyl9LAokaVowOjF9ClAueVEucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLHI9SC5MaChzKQpyLkMoIllrLksiKS5hKGEpCnJldHVybiBu
-ZXcgUC5OMyhhLHMucSgwLGEpLHIuQygiQDxZay5LPiIpLktxKHIuQygiWWsuViIpKS5DKCJOMzwxLDI+
-IikpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlzLmEpLkMoIk4zPFlrLkssWWsuVj4oWWsu
-SykiKX19ClAuS1AucHJvdG90eXBlPXsKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpz
-LmMuYShiKQpzLlFbMV0uYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFi
-bGUgbWFwIikpfX0KUC5Qbi5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5x
-KDAsYil9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1ILkxoKHRoaXMpCnRoaXMuYS5ZKDAscy5jLmEo
-Yikscy5RWzFdLmEoYykpfSwKeDQ6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS54NChhKX0sCks6ZnVu
-Y3Rpb24oYSxiKXt0aGlzLmEuSygwLEguTGgodGhpcykuQygifigxLDIpIikuYShiKSl9LApnbDA6ZnVu
-Y3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmdsMChzKX0sCmdBOmZ1bmN0aW9uKGEpe3ZhciBz
-PXRoaXMuYQpyZXR1cm4gcy5nQShzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIEouaih0aGlzLmEpfSwK
-Z1B1OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQpyZXR1cm4gcy5nUHUocyl9LAokaVowOjF9ClAuR2ou
-cHJvdG90eXBlPXt9ClAuTWEucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRSh0aGlz
-LCJ7IiwifSIpfX0KUC5Wai5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjEsJGl4dToxfQpQLlh2LnByb3Rv
-dHlwZT17CkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMKZm9yKHM9Si5JVChILkxoKHRoaXMpLkMoImNYPDE+
-IikuYShiKSk7cy5GKCk7KXRoaXMuaSgwLHMuZ2woKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldF
-KHRoaXMsInsiLCJ9Iil9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHMscj1QLnJqKHRoaXMsdGhpcy5yLEgu
-TGgodGhpcykuYykKaWYoIXIuRigpKXJldHVybiIiCmlmKGI9PT0iIil7cz0iIgpkbyBzKz1ILkVqKHIu
-ZCkKd2hpbGUoci5GKCkpfWVsc2V7cz1ILkVqKHIuZCkKZm9yKDtyLkYoKTspcz1zK2IrSC5FaihyLmQp
-fXJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKJGliUToxLAokaWNYOjEsCiRpeHU6MX0KUC5u
-WS5wcm90b3R5cGU9e30KUC5XWS5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90
-b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHMscj10aGlzLmIKaWYocj09bnVsbClyZXR1cm4gdGhp
-cy5jLnEoMCxiKQplbHNlIGlmKHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3M9clti
-XQpyZXR1cm4gdHlwZW9mIHM9PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6c319LApnQTpmdW5jdGlvbihh
-KXtyZXR1cm4gdGhpcy5iPT1udWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApnbDA6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuZ0EodGhpcyk9PT0wfSwKZ1Y6ZnVuY3Rpb24oKXtpZih0aGlzLmI9PW51
-bGwpe3ZhciBzPXRoaXMuYwpyZXR1cm4gbmV3IEguaTUocyxILkxoKHMpLkMoImk1PDE+IikpfXJldHVy
-biBuZXcgUC5pOCh0aGlzKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscT10aGlzCmlmKHEuYj09
-bnVsbClxLmMuWSgwLGIsYykKZWxzZSBpZihxLng0KGIpKXtzPXEuYgpzW2JdPWMKcj1xLmEKaWYocj09
-bnVsbD9zIT1udWxsOnIhPT1zKXJbYl09bnVsbH1lbHNlIHEuWEsoKS5ZKDAsYixjKX0sCng0OmZ1bmN0
-aW9uKGEpe2lmKHRoaXMuYj09bnVsbClyZXR1cm4gdGhpcy5jLng0KGEpCnJldHVybiBPYmplY3QucHJv
-dG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodGhpcy5hLGEpfSwKSzpmdW5jdGlvbihhLGIpe3ZhciBz
-LHIscSxwLG89dGhpcwp0LmNBLmEoYikKaWYoby5iPT1udWxsKXJldHVybiBvLmMuSygwLGIpCnM9by5D
-ZigpCmZvcihyPTA7cjxzLmxlbmd0aDsrK3Ipe3E9c1tyXQpwPW8uYltxXQppZih0eXBlb2YgcD09InVu
-ZGVmaW5lZCIpe3A9UC5RZShvLmFbcV0pCm8uYltxXT1wfWIuJDIocSxwKQppZihzIT09by5jKXRocm93
-IEguYihQLmE0KG8pKX19LApDZjpmdW5jdGlvbigpe3ZhciBzPXQuYk0uYSh0aGlzLmMpCmlmKHM9PW51
-bGwpcz10aGlzLmM9SC5WTShPYmplY3Qua2V5cyh0aGlzLmEpLHQucykKcmV0dXJuIHN9LApYSzpmdW5j
-dGlvbigpe3ZhciBzLHIscSxwLG8sbj10aGlzCmlmKG4uYj09bnVsbClyZXR1cm4gbi5jCnM9UC5GbCh0
-Lk4sdC56KQpyPW4uQ2YoKQpmb3IocT0wO3A9ci5sZW5ndGgscTxwOysrcSl7bz1yW3FdCnMuWSgwLG8s
-bi5xKDAsbykpfWlmKHA9PT0wKUMuTm0uaShyLCIiKQplbHNlIEMuTm0uc0EociwwKQpuLmE9bi5iPW51
-bGwKcmV0dXJuIG4uYz1zfSwKZmI6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIU9iamVjdC5wcm90b3R5cGUu
-aGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkpcmV0dXJuIG51bGwKcz1QLlFlKHRoaXMuYVthXSkK
-cmV0dXJuIHRoaXMuYlthXT1zfX0KUC5pOC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgcz10
-aGlzLmEKcmV0dXJuIHMuZ0Eocyl9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcy5hCmlmKHMuYj09
-bnVsbClzPXMuZ1YoKS5FKDAsYikKZWxzZXtzPXMuQ2YoKQppZihiPDB8fGI+PXMubGVuZ3RoKXJldHVy
-biBILk9IKHMsYikKcz1zW2JdfXJldHVybiBzfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQpp
-ZihzLmI9PW51bGwpe3M9cy5nVigpCnM9cy5na3oocyl9ZWxzZXtzPXMuQ2YoKQpzPW5ldyBKLm0xKHMs
-cy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX1yZXR1cm4gc30sCnRnOmZ1bmN0aW9uKGEsYil7cmV0
-dXJuIHRoaXMuYS54NChiKX19ClAucGcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyCnRy
-eXtzPW5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtmYXRhbDp0cnVlfSkKcmV0dXJuIHN9Y2F0Y2gocil7
-SC5SdShyKX1yZXR1cm4gbnVsbH0sCiRTOjEzfQpQLmMyLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7
-dmFyIHMscgp0cnl7cz1uZXcgVGV4dERlY29kZXIoInV0Zi04Iix7ZmF0YWw6ZmFsc2V9KQpyZXR1cm4g
-c31jYXRjaChyKXtILlJ1KHIpfXJldHVybiBudWxsfSwKJFM6MTN9ClAuQ1YucHJvdG90eXBlPXsKeXI6
-ZnVuY3Rpb24oYTAsYTEsYTIpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixh
-PSJJbnZhbGlkIGJhc2U2NCBlbmNvZGluZyBsZW5ndGggIgphMj1QLmpCKGExLGEyLGEwLmxlbmd0aCkK
-cz0kLlY3KCkKZm9yKHI9YTEscT1yLHA9bnVsbCxvPS0xLG49LTEsbT0wO3I8YTI7cj1sKXtsPXIrMQpr
-PUMueEIuVyhhMCxyKQppZihrPT09Mzcpe2o9bCsyCmlmKGo8PWEyKXtpPUgub28oQy54Qi5XKGEwLGwp
-KQpoPUgub28oQy54Qi5XKGEwLGwrMSkpCmc9aSoxNitoLShoJjI1NikKaWYoZz09PTM3KWc9LTEKbD1q
-fWVsc2UgZz0tMX1lbHNlIGc9awppZigwPD1nJiZnPD0xMjcpe2lmKGc8MHx8Zz49cy5sZW5ndGgpcmV0
-dXJuIEguT0gocyxnKQpmPXNbZ10KaWYoZj49MCl7Zz1DLnhCLm0oIkFCQ0RFRkdISUpLTE1OT1BRUlNU
-VVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8iLGYpCmlmKGc9PT1rKWNv
-bnRpbnVlCms9Z31lbHNle2lmKGY9PT0tMSl7aWYobzwwKXtlPXA9PW51bGw/bnVsbDpwLmEubGVuZ3Ro
-CmlmKGU9PW51bGwpZT0wCm89ZSsoci1xKQpuPXJ9KyttCmlmKGs9PT02MSljb250aW51ZX1rPWd9aWYo
-ZiE9PS0yKXtpZihwPT1udWxsKXtwPW5ldyBQLlJuKCIiKQplPXB9ZWxzZSBlPXAKZS5hKz1DLnhCLk5q
-KGEwLHEscikKZS5hKz1ILkx3KGspCnE9bApjb250aW51ZX19dGhyb3cgSC5iKFAucnIoIkludmFsaWQg
-YmFzZTY0IGRhdGEiLGEwLHIpKX1pZihwIT1udWxsKXtlPXAuYSs9Qy54Qi5OaihhMCxxLGEyKQpkPWUu
-bGVuZ3RoCmlmKG8+PTApUC54TShhMCxuLGEyLG8sbSxkKQplbHNle2M9Qy5qbi56WShkLTEsNCkrMQpp
-ZihjPT09MSl0aHJvdyBILmIoUC5ycihhLGEwLGEyKSkKZm9yKDtjPDQ7KXtlKz0iPSIKcC5hPWU7Kytj
-fX1lPXAuYQpyZXR1cm4gQy54Qi5pNyhhMCxhMSxhMixlLmNoYXJDb2RlQXQoMCk9PTA/ZTplKX1iPWEy
-LWExCmlmKG8+PTApUC54TShhMCxuLGEyLG8sbSxiKQplbHNle2M9Qy5qbi56WShiLDQpCmlmKGM9PT0x
-KXRocm93IEguYihQLnJyKGEsYTAsYTIpKQppZihjPjEpYTA9Qy54Qi5pNyhhMCxhMixhMixjPT09Mj8i
-PT0iOiI9Iil9cmV0dXJuIGEwfX0KUC5VOC5wcm90b3R5cGU9e30KUC5Vay5wcm90b3R5cGU9e30KUC53
-SS5wcm90b3R5cGU9e30KUC5aaS5wcm90b3R5cGU9e30KUC5VZC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
-KGEpe3ZhciBzPVAucCh0aGlzLmEpCnJldHVybih0aGlzLmIhPW51bGw/IkNvbnZlcnRpbmcgb2JqZWN0
-IHRvIGFuIGVuY29kYWJsZSBvYmplY3QgZmFpbGVkOiI6IkNvbnZlcnRpbmcgb2JqZWN0IGRpZCBub3Qg
-cmV0dXJuIGFuIGVuY29kYWJsZSBvYmplY3Q6IikrIiAiK3N9fQpQLks4LnByb3RvdHlwZT17Cnc6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIkN5Y2xpYyBlcnJvciBpbiBKU09OIHN0cmluZ2lmeSJ9fQpQLmJ5LnByb3Rv
-dHlwZT17CnBXOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwp0LmZWLmEoYykKcz1QLkJTKGIsdGhpcy5nSGUo
-KS5hKQpyZXR1cm4gc30sCk9COmZ1bmN0aW9uKGEsYil7dmFyIHMKdC5kQS5hKGIpCnM9UC51WChhLHRo
-aXMuZ1pFKCkuYixudWxsKQpyZXR1cm4gc30sCmdaRTpmdW5jdGlvbigpe3JldHVybiBDLm5YfSwKZ0hl
-OmZ1bmN0aW9uKCl7cmV0dXJuIEMuQTN9fQpQLm9qLnByb3RvdHlwZT17fQpQLk14LnByb3RvdHlwZT17
-fQpQLlNoLnByb3RvdHlwZT17CnZwOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGw9YS5sZW5n
-dGgKZm9yKHM9Si5yWShhKSxyPXRoaXMuYyxxPTAscD0wO3A8bDsrK3Ape289cy5XKGEscCkKaWYobz45
-Mil7aWYobz49NTUyOTYpe249byY2NDUxMgppZihuPT09NTUyOTYpe209cCsxCm09IShtPGwmJihDLnhC
-LlcoYSxtKSY2NDUxMik9PT01NjMyMCl9ZWxzZSBtPSExCmlmKCFtKWlmKG49PT01NjMyMCl7bj1wLTEK
-bj0hKG4+PTAmJihDLnhCLm0oYSxuKSY2NDUxMik9PT01NTI5Nil9ZWxzZSBuPSExCmVsc2Ugbj0hMApp
-ZihuKXtpZihwPnEpci5hKz1DLnhCLk5qKGEscSxwKQpxPXArMQpyLmErPUguTHcoOTIpCnIuYSs9SC5M
-dygxMTcpCnIuYSs9SC5MdygxMDApCm49bz4+PjgmMTUKci5hKz1ILkx3KG48MTA/NDgrbjo4NytuKQpu
-PW8+Pj40JjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246ODcrbikKbj1vJjE1CnIuYSs9SC5MdyhuPDEwPzQ4
-K246ODcrbil9fWNvbnRpbnVlfWlmKG88MzIpe2lmKHA+cSlyLmErPUMueEIuTmooYSxxLHApCnE9cCsx
-CnIuYSs9SC5Mdyg5MikKc3dpdGNoKG8pe2Nhc2UgODpyLmErPUguTHcoOTgpCmJyZWFrCmNhc2UgOTpy
-LmErPUguTHcoMTE2KQpicmVhawpjYXNlIDEwOnIuYSs9SC5MdygxMTApCmJyZWFrCmNhc2UgMTI6ci5h
-Kz1ILkx3KDEwMikKYnJlYWsKY2FzZSAxMzpyLmErPUguTHcoMTE0KQpicmVhawpkZWZhdWx0OnIuYSs9
-SC5MdygxMTcpCnIuYSs9SC5Mdyg0OCkKci5hKz1ILkx3KDQ4KQpuPW8+Pj40JjE1CnIuYSs9SC5Mdyhu
-PDEwPzQ4K246ODcrbikKbj1vJjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246ODcrbikKYnJlYWt9fWVsc2Ug
-aWYobz09PTM0fHxvPT09OTIpe2lmKHA+cSlyLmErPUMueEIuTmooYSxxLHApCnE9cCsxCnIuYSs9SC5M
-dyg5MikKci5hKz1ILkx3KG8pfX1pZihxPT09MClyLmErPUguRWooYSkKZWxzZSBpZihxPGwpci5hKz1z
-Lk5qKGEscSxsKX0sCkpuOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwCmZvcihzPXRoaXMuYSxyPXMubGVu
-Z3RoLHE9MDtxPHI7KytxKXtwPXNbcV0KaWYoYT09bnVsbD9wPT1udWxsOmE9PT1wKXRocm93IEguYihu
-ZXcgUC5LOChhLG51bGwpKX1DLk5tLmkocyxhKX0sCmlVOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG89
-dGhpcwppZihvLnRNKGEpKXJldHVybgpvLkpuKGEpCnRyeXtzPW8uYi4kMShhKQppZighby50TShzKSl7
-cT1QLkd5KGEsbnVsbCxvLmdWSygpKQp0aHJvdyBILmIocSl9cT1vLmEKaWYoMD49cS5sZW5ndGgpcmV0
-dXJuIEguT0gocSwtMSkKcS5wb3AoKX1jYXRjaChwKXtyPUguUnUocCkKcT1QLkd5KGEscixvLmdWSygp
-KQp0aHJvdyBILmIocSl9fSwKdE06ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMKaWYodHlwZW9mIGE9
-PSJudW1iZXIiKXtpZighaXNGaW5pdGUoYSkpcmV0dXJuITEKcS5jLmErPUMuQ0QudyhhKQpyZXR1cm4h
-MH1lbHNlIGlmKGE9PT0hMCl7cS5jLmErPSJ0cnVlIgpyZXR1cm4hMH1lbHNlIGlmKGE9PT0hMSl7cS5j
-LmErPSJmYWxzZSIKcmV0dXJuITB9ZWxzZSBpZihhPT1udWxsKXtxLmMuYSs9Im51bGwiCnJldHVybiEw
-fWVsc2UgaWYodHlwZW9mIGE9PSJzdHJpbmciKXtzPXEuYwpzLmErPSciJwpxLnZwKGEpCnMuYSs9JyIn
-CnJldHVybiEwfWVsc2UgaWYodC5iLmIoYSkpe3EuSm4oYSkKcS5sSyhhKQpzPXEuYQppZigwPj1zLmxl
-bmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCnJldHVybiEwfWVsc2UgaWYodC5mLmIoYSkpe3Eu
-Sm4oYSkKcj1xLmp3KGEpCnM9cS5hCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9w
-KCkKcmV0dXJuIHJ9ZWxzZSByZXR1cm4hMX0sCmxLOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLmMK
-cS5hKz0iWyIKcz1KLlU2KGEpCmlmKHMuZ29yKGEpKXt0aGlzLmlVKHMucShhLDApKQpmb3Iocj0xO3I8
-cy5nQShhKTsrK3Ipe3EuYSs9IiwiCnRoaXMuaVUocy5xKGEscikpfX1xLmErPSJdIn0sCmp3OmZ1bmN0
-aW9uKGEpe3ZhciBzLHIscSxwLG8sbj10aGlzLG09e30KaWYoYS5nbDAoYSkpe24uYy5hKz0ie30iCnJl
-dHVybiEwfXM9UC5POChhLmdBKGEpKjIsbnVsbCwhMSx0LlMpCnI9bS5hPTAKbS5iPSEwCmEuSygwLG5l
-dyBQLnRpKG0scykpCmlmKCFtLmIpcmV0dXJuITEKcT1uLmMKcS5hKz0ieyIKZm9yKHA9JyInO3I8cy5s
-ZW5ndGg7cis9MixwPScsIicpe3EuYSs9cApuLnZwKEguaChzW3JdKSkKcS5hKz0nIjonCm89cisxCmlm
-KG8+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsbykKbi5pVShzW29dKX1xLmErPSJ9IgpyZXR1cm4hMH19
-ClAudGkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKHR5cGVvZiBhIT0ic3Ry
-aW5nIil0aGlzLmEuYj0hMQpzPXRoaXMuYgpyPXRoaXMuYQpDLk5tLlkocyxyLmErKyxhKQpDLk5tLlko
-cyxyLmErKyxiKX0sCiRTOjEyfQpQLnR1LnByb3RvdHlwZT17CmdWSzpmdW5jdGlvbigpe3ZhciBzPXRo
-aXMuYy5hCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfX0KUC51NS5wcm90b3R5cGU9ewpnWkU6
-ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90eXBlPXsKV0o6ZnVuY3Rpb24oYSl7dmFy
-IHMscixxPVAuakIoMCxudWxsLGEubGVuZ3RoKSxwPXEtMAppZihwPT09MClyZXR1cm4gbmV3IFVpbnQ4
-QXJyYXkoMCkKcz1uZXcgVWludDhBcnJheShwKjMpCnI9bmV3IFAuUncocykKaWYoci5HeChhLDAscSkh
-PT1xKXtKLmE2KGEscS0xKQpyLlJPKCl9cmV0dXJuIG5ldyBVaW50OEFycmF5KHMuc3ViYXJyYXkoMCxI
-LnJNKDAsci5iLHMubGVuZ3RoKSkpfX0KUC5Sdy5wcm90b3R5cGU9ewpSTzpmdW5jdGlvbigpe3ZhciBz
-PXRoaXMscj1zLmMscT1zLmIscD1zLmI9cSsxLG89ci5sZW5ndGgKaWYocT49bylyZXR1cm4gSC5PSChy
-LHEpCnJbcV09MjM5CnE9cy5iPXArMQppZihwPj1vKXJldHVybiBILk9IKHIscCkKcltwXT0xOTEKcy5i
-PXErMQppZihxPj1vKXJldHVybiBILk9IKHIscSkKcltxXT0xODl9LApPNjpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHIscSxwLG8sbj10aGlzCmlmKChiJjY0NTEyKT09PTU2MzIwKXtzPTY1NTM2KygoYSYxMDIzKTw8
-MTApfGImMTAyMwpyPW4uYwpxPW4uYgpwPW4uYj1xKzEKbz1yLmxlbmd0aAppZihxPj1vKXJldHVybiBI
-Lk9IKHIscSkKcltxXT0yNDB8cz4+PjE4CnE9bi5iPXArMQppZihwPj1vKXJldHVybiBILk9IKHIscCkK
-cltwXT0xMjh8cz4+PjEyJjYzCnA9bi5iPXErMQppZihxPj1vKXJldHVybiBILk9IKHIscSkKcltxXT0x
-Mjh8cz4+PjYmNjMKbi5iPXArMQppZihwPj1vKXJldHVybiBILk9IKHIscCkKcltwXT0xMjh8cyY2Mwpy
-ZXR1cm4hMH1lbHNle24uUk8oKQpyZXR1cm4hMX19LApHeDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixx
-LHAsbyxuLG0sbD10aGlzCmlmKGIhPT1jJiYoQy54Qi5tKGEsYy0xKSY2NDUxMik9PT01NTI5NiktLWMK
-Zm9yKHM9bC5jLHI9cy5sZW5ndGgscT1iO3E8YzsrK3Epe3A9Qy54Qi5XKGEscSkKaWYocDw9MTI3KXtv
-PWwuYgppZihvPj1yKWJyZWFrCmwuYj1vKzEKc1tvXT1wfWVsc2V7bz1wJjY0NTEyCmlmKG89PT01NTI5
-Nil7aWYobC5iKzQ+cilicmVhawpuPXErMQppZihsLk82KHAsQy54Qi5XKGEsbikpKXE9bn1lbHNlIGlm
-KG89PT01NjMyMCl7aWYobC5iKzM+cilicmVhawpsLlJPKCl9ZWxzZSBpZihwPD0yMDQ3KXtvPWwuYgpt
-PW8rMQppZihtPj1yKWJyZWFrCmwuYj1tCmlmKG8+PXIpcmV0dXJuIEguT0gocyxvKQpzW29dPTE5Mnxw
-Pj4+NgpsLmI9bSsxCnNbbV09MTI4fHAmNjN9ZWxzZXtvPWwuYgppZihvKzI+PXIpYnJlYWsKbT1sLmI9
-bysxCmlmKG8+PXIpcmV0dXJuIEguT0gocyxvKQpzW29dPTIyNHxwPj4+MTIKbz1sLmI9bSsxCmlmKG0+
-PXIpcmV0dXJuIEguT0gocyxtKQpzW21dPTEyOHxwPj4+NiY2MwpsLmI9bysxCmlmKG8+PXIpcmV0dXJu
-IEguT0gocyxvKQpzW29dPTEyOHxwJjYzfX19cmV0dXJuIHF9fQpQLkdZLnByb3RvdHlwZT17CldKOmZ1
-bmN0aW9uKGEpe3ZhciBzLHIKdC5MLmEoYSkKcz10aGlzLmEKcj1QLmt5KHMsYSwwLG51bGwpCmlmKHIh
-PW51bGwpcmV0dXJuIHIKcmV0dXJuIG5ldyBQLmJ6KHMpLk5lKGEsMCxudWxsLCEwKX19ClAuYnoucHJv
-dG90eXBlPXsKTmU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuPXRoaXMKdC5MLmEoYSkK
-cz1QLmpCKGIsYyxKLkhtKGEpKQppZihiPT09cylyZXR1cm4iIgpyPVAuankoYSxiLHMpCnE9bi5oTyhy
-LDAscy1iLCEwKQpwPW4uYgppZigocCYxKSE9PTApe289UC5qNChwKQpuLmI9MAp0aHJvdyBILmIoUC5y
-cihvLGEsYituLmMpKX1yZXR1cm4gcX0sCmhPOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscT10aGlz
-CmlmKGMtYj4xMDAwKXtzPUMuam4uQlUoYitjLDIpCnI9cS5oTyhhLGIscywhMSkKaWYoKHEuYiYxKSE9
-PTApcmV0dXJuIHIKcmV0dXJuIHIrcS5oTyhhLHMsYyxkKX1yZXR1cm4gcS5FaChhLGIsYyxkKX0sCkVo
-OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbixtLGwsaz10aGlzLGo9NjU1MzMsaT1rLmIs
-aD1rLmMsZz1uZXcgUC5SbigiIiksZj1iKzEsZT1hLmxlbmd0aAppZihiPDB8fGI+PWUpcmV0dXJuIEgu
-T0goYSxiKQpzPWFbYl0KJGxhYmVsMCQwOmZvcihyPWsuYTshMDspe2Zvcig7ITA7Zj1vKXtxPUMueEIu
-VygiQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
-QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
-QUFBQUFBQUFBQUFGRkZGRkZGRkZGRkZGRkZGR0dHR0dHR0dHR0dHR0dHR0hISEhISEhISEhISEhISEhI
-SEhISEhISEhISElISEhKRUVCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLQ0NDQ0NDQ0NDQ0ND
-RENMT05OTk1FRUVFRUVFRUVFRSIscykmMzEKaD1pPD0zMj9zJjYxNjk0Pj4+cToocyY2M3xoPDw2KT4+
-PjAKaT1DLnhCLlcoIiBceDAwMDpYRUNDQ0NDTjpsRGIgXHgwMDA6WEVDQ0NDQ052bERiIFx4MDAwOlhF
-Q0NDQ0NOOmxEYiBBQUFBQVx4MDBceDAwXHgwMFx4MDBceDAwQUFBQUEwMDAwMEFBQUFBOjo6OjpBQUFB
-QUdHMDAwQUFBQUEwMEtLS0FBQUFBRzo6OjpBQUFBQTpJSUlJQUFBQUEwMDBceDgwMEFBQUFBXHgwMFx4
-MDBceDAwXHgwMCBBQUFBQSIsaStxKQppZihpPT09MCl7Zy5hKz1ILkx3KGgpCmlmKGY9PT1jKWJyZWFr
-ICRsYWJlbDAkMApicmVha31lbHNlIGlmKChpJjEpIT09MCl7aWYocilzd2l0Y2goaSl7Y2FzZSA2OTpj
-YXNlIDY3OmcuYSs9SC5MdyhqKQpicmVhawpjYXNlIDY1OmcuYSs9SC5MdyhqKTstLWYKYnJlYWsKZGVm
-YXVsdDpwPWcuYSs9SC5MdyhqKQpnLmE9cCtILkx3KGopCmJyZWFrfWVsc2V7ay5iPWkKay5jPWYtMQpy
-ZXR1cm4iIn1pPTB9aWYoZj09PWMpYnJlYWsgJGxhYmVsMCQwCm89ZisxCmlmKGY8MHx8Zj49ZSlyZXR1
-cm4gSC5PSChhLGYpCnM9YVtmXX1vPWYrMQppZihmPDB8fGY+PWUpcmV0dXJuIEguT0goYSxmKQpzPWFb
-Zl0KaWYoczwxMjgpe3doaWxlKCEwKXtpZighKG88Yykpe249YwpicmVha31tPW8rMQppZihvPDB8fG8+
-PWUpcmV0dXJuIEguT0goYSxvKQpzPWFbb10KaWYocz49MTI4KXtuPW0tMQpvPW0KYnJlYWt9bz1tfWlm
-KG4tZjwyMClmb3IobD1mO2w8bjsrK2wpe2lmKGw+PWUpcmV0dXJuIEguT0goYSxsKQpnLmErPUguTHco
-YVtsXSl9ZWxzZSBnLmErPVAuSE0oYSxmLG4pCmlmKG49PT1jKWJyZWFrICRsYWJlbDAkMApmPW99ZWxz
-ZSBmPW99aWYoZCYmaT4zMilpZihyKWcuYSs9SC5MdyhqKQplbHNle2suYj03NwprLmM9YwpyZXR1cm4i
-In1rLmI9aQprLmM9aAplPWcuYQpyZXR1cm4gZS5jaGFyQ29kZUF0KDApPT0wP2U6ZX19ClAuV0YucHJv
-dG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKdC5mby5hKGEpCnM9dGhpcy5iCnI9dGhp
-cy5hCnMuYSs9ci5hCnE9cy5hKz1ILkVqKGEuYSkKcy5hPXErIjogIgpzLmErPVAucChiKQpyLmE9Iiwg
-In0sCiRTOjQxfQpQLmlQLnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1
-cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9mIFAuaVAmJnRoaXMuYT09PWIuYSYmITB9LApnaU86ZnVuY3Rp
-b24oYSl7dmFyIHM9dGhpcy5hCnJldHVybihzXkMuam4ud0cocywzMCkpJjEwNzM3NDE4MjN9LAp3OmZ1
-bmN0aW9uKGEpe3ZhciBzPXRoaXMscj1QLkdxKEgudEoocykpLHE9UC5oMChILk5TKHMpKSxwPVAuaDAo
-SC5qQShzKSksbz1QLmgwKEguSVgocykpLG49UC5oMChILmNoKHMpKSxtPVAuaDAoSC5KZChzKSksbD1Q
-LlZ4KEgubzEocykpLGs9cisiLSIrcSsiLSIrcCsiICIrbysiOiIrbisiOiIrbSsiLiIrbApyZXR1cm4g
-a319ClAuWFMucHJvdG90eXBlPXsKZ0lJOmZ1bmN0aW9uKCl7cmV0dXJuIEgudHModGhpcy4kdGhyb3du
-SnNFcnJvcil9fQpQLkM2LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCmlmKHMh
-PW51bGwpcmV0dXJuIkFzc2VydGlvbiBmYWlsZWQ6ICIrUC5wKHMpCnJldHVybiJBc3NlcnRpb24gZmFp
-bGVkIn19ClAuRXoucHJvdG90eXBlPXt9ClAubi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVy
-biJUaHJvdyBvZiBudWxsLiJ9fQpQLnUucHJvdG90eXBlPXsKZ1o6ZnVuY3Rpb24oKXtyZXR1cm4iSW52
-YWxpZCBhcmd1bWVudCIrKCF0aGlzLmE/IihzKSI6IiIpfSwKZ3U6ZnVuY3Rpb24oKXtyZXR1cm4iIn0s
-Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD1xLmMsbz1wPT1udWxsPyIiOiIgKCIrcCsiKSIs
-bj1xLmQsbT1uPT1udWxsPyIiOiI6ICIrSC5FaihuKSxsPXEuZ1ooKStvK20KaWYoIXEuYSlyZXR1cm4g
-bApzPXEuZ3UoKQpyPVAucChxLmIpCnJldHVybiBsK3MrIjogIityfX0KUC5iSi5wcm90b3R5cGU9ewpn
-WjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHMscj10aGlz
-LmUscT10aGlzLmYKaWYocj09bnVsbClzPXEhPW51bGw/IjogTm90IGxlc3MgdGhhbiBvciBlcXVhbCB0
-byAiK0guRWoocSk6IiIKZWxzZSBpZihxPT1udWxsKXM9IjogTm90IGdyZWF0ZXIgdGhhbiBvciBlcXVh
-bCB0byAiK0guRWoocikKZWxzZSBpZihxPnIpcz0iOiBOb3QgaW4gaW5jbHVzaXZlIHJhbmdlICIrSC5F
-aihyKSsiLi4iK0guRWoocSkKZWxzZSBzPXE8cj8iOiBWYWxpZCB2YWx1ZSByYW5nZSBpcyBlbXB0eSI6
-IjogT25seSB2YWxpZCB2YWx1ZSBpcyAiK0guRWoocikKcmV0dXJuIHN9fQpQLmVZLnByb3RvdHlwZT17
-CmdaOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3IifSwKZ3U6ZnVuY3Rpb24oKXt2YXIgcyxyPUgu
-dVAodGhpcy5iKQppZih0eXBlb2YgciE9PSJudW1iZXIiKXJldHVybiByLkooKQppZihyPDApcmV0dXJu
-IjogaW5kZXggbXVzdCBub3QgYmUgbmVnYXRpdmUiCnM9dGhpcy5mCmlmKHM9PT0wKXJldHVybiI6IG5v
-IGluZGljZXMgYXJlIHZhbGlkIgpyZXR1cm4iOiBpbmRleCBzaG91bGQgYmUgbGVzcyB0aGFuICIrSC5F
-aihzKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmZ9fQpQLm1wLnByb3RvdHlwZT17Cnc6ZnVu
-Y3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrPXRoaXMsaj17fSxpPW5ldyBQLlJuKCIiKQpqLmE9
-IiIKcz1rLmMKZm9yKHI9cy5sZW5ndGgscT0wLHA9IiIsbz0iIjtxPHI7KytxLG89IiwgIil7bj1zW3Fd
-CmkuYT1wK28KcD1pLmErPVAucChuKQpqLmE9IiwgIn1rLmQuSygwLG5ldyBQLldGKGosaSkpCm09UC5w
-KGsuYSkKbD1pLncoMCkKcj0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK0gu
-RWooay5iLmEpKyInXG5SZWNlaXZlcjogIittKyJcbkFyZ3VtZW50czogWyIrbCsiXSIKcmV0dXJuIHJ9
-fQpQLnViLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlVuc3VwcG9ydGVkIG9wZXJhdGlv
-bjogIit0aGlzLmF9fQpQLmRzLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJl
-dHVybiBzIT1udWxsPyJVbmltcGxlbWVudGVkRXJyb3I6ICIrczoiVW5pbXBsZW1lbnRlZEVycm9yIn19
-ClAubGoucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iQmFkIHN0YXRlOiAiK3RoaXMuYX19
-ClAuVVYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKaWYocz09bnVsbClyZXR1
-cm4iQ29uY3VycmVudCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbi4iCnJldHVybiJDb25jdXJy
-ZW50IG1vZGlmaWNhdGlvbiBkdXJpbmcgaXRlcmF0aW9uOiAiK1AucChzKSsiLiJ9fQpQLms1LnByb3Rv
-dHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIk91dCBvZiBNZW1vcnkifSwKZ0lJOmZ1bmN0aW9uKCl7
-cmV0dXJuIG51bGx9LAokaVhTOjF9ClAuS1kucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4i
-U3RhY2sgT3ZlcmZsb3cifSwKZ0lJOmZ1bmN0aW9uKCl7cmV0dXJuIG51bGx9LAokaVhTOjF9ClAuYy5w
-cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQpyZXR1cm4gcz09bnVsbD8iUmVhZGlu
-ZyBzdGF0aWMgdmFyaWFibGUgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlvbiI6IlJlYWRpbmcgc3RhdGlj
-IHZhcmlhYmxlICciK3MrIicgZHVyaW5nIGl0cyBpbml0aWFsaXphdGlvbiJ9fQpQLkNELnByb3RvdHlw
-ZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkV4Y2VwdGlvbjogIit0aGlzLmF9LAokaVJ6OjF9ClAuYUUu
-cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZz10aGlz
-LmEsZj1nIT1udWxsJiYiIiE9PWc/IkZvcm1hdEV4Y2VwdGlvbjogIitILkVqKGcpOiJGb3JtYXRFeGNl
-cHRpb24iLGU9dGhpcy5jLGQ9dGhpcy5iCmlmKHR5cGVvZiBkPT0ic3RyaW5nIil7aWYoZSE9bnVsbClz
-PWU8MHx8ZT5kLmxlbmd0aAplbHNlIHM9ITEKaWYocyllPW51bGwKaWYoZT09bnVsbCl7aWYoZC5sZW5n
-dGg+NzgpZD1DLnhCLk5qKGQsMCw3NSkrIi4uLiIKcmV0dXJuIGYrIlxuIitkfWZvcihyPTEscT0wLHA9
-ITEsbz0wO288ZTsrK28pe249Qy54Qi5XKGQsbykKaWYobj09PTEwKXtpZihxIT09b3x8IXApKytyCnE9
-bysxCnA9ITF9ZWxzZSBpZihuPT09MTMpeysrcgpxPW8rMQpwPSEwfX1mPXI+MT9mKygiIChhdCBsaW5l
-ICIrcisiLCBjaGFyYWN0ZXIgIisoZS1xKzEpKyIpXG4iKTpmKygiIChhdCBjaGFyYWN0ZXIgIisoZSsx
-KSsiKVxuIikKbT1kLmxlbmd0aApmb3Iobz1lO288bTsrK28pe249Qy54Qi5tKGQsbykKaWYobj09PTEw
-fHxuPT09MTMpe209bwpicmVha319aWYobS1xPjc4KWlmKGUtcTw3NSl7bD1xKzc1Cms9cQpqPSIiCmk9
-Ii4uLiJ9ZWxzZXtpZihtLWU8NzUpe2s9bS03NQpsPW0KaT0iIn1lbHNle2s9ZS0zNgpsPWUrMzYKaT0i
-Li4uIn1qPSIuLi4ifWVsc2V7bD1tCms9cQpqPSIiCmk9IiJ9aD1DLnhCLk5qKGQsayxsKQpyZXR1cm4g
-ZitqK2graSsiXG4iK0MueEIuSXgoIiAiLGUtaytqLmxlbmd0aCkrIl5cbiJ9ZWxzZSByZXR1cm4gZSE9
-bnVsbD9mKygiIChhdCBvZmZzZXQgIitILkVqKGUpKyIpIik6Zn0sCiRpUno6MX0KUC5jWC5wcm90b3R5
-cGU9ewpFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpyZXR1cm4gSC5LMSh0aGlzLHMu
-S3EoYykuQygiMShjWC5FKSIpLmEoYikscy5DKCJjWC5FIiksYyl9LApldjpmdW5jdGlvbihhLGIpe3Zh
-ciBzPUguTGgodGhpcykKcmV0dXJuIG5ldyBILlU1KHRoaXMscy5DKCJhMihjWC5FKSIpLmEoYikscy5D
-KCJVNTxjWC5FPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5na3oodGhpcykKZm9yKHM9
-MDtyLkYoKTspKytzCnJldHVybiBzfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiF0aGlzLmdreih0aGlz
-KS5GKCl9LApncjg6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmdreih0aGlzKQppZighci5GKCkpdGhy
-b3cgSC5iKEguV3AoKSkKcz1yLmdsKCkKaWYoci5GKCkpdGhyb3cgSC5iKEguQW0oKSkKcmV0dXJuIHN9
-LApFOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxClAuazEoYiwiaW5kZXgiKQpmb3Iocz10aGlzLmdreih0
-aGlzKSxyPTA7cy5GKCk7KXtxPXMuZ2woKQppZihiPT09cilyZXR1cm4gcTsrK3J9dGhyb3cgSC5iKFAu
-Q2YoYix0aGlzLCJpbmRleCIsbnVsbCxyKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLkVQKHRoaXMs
-IigiLCIpIil9fQpQLkFuLnByb3RvdHlwZT17fQpQLk4zLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7
-cmV0dXJuIk1hcEVudHJ5KCIrSC5FaihKLmoodGhpcy5hKSkrIjogIitILkVqKEouaih0aGlzLmIpKSsi
-KSJ9fQpQLmM4LnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gUC5NaC5wcm90b3R5cGUu
-Z2lPLmNhbGwoQy5qTix0aGlzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIm51bGwifX0KUC5NaC5wcm90
-b3R5cGU9e2NvbnN0cnVjdG9yOlAuTWgsJGlNaDoxLApETjpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
-PT09Yn0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUSh0aGlzKX0sCnc6ZnVuY3Rpb24oYSl7cmV0
-dXJuIkluc3RhbmNlIG9mICciK0guRWooSC5NKHRoaXMpKSsiJyJ9LAplNzpmdW5jdGlvbihhLGIpe3Qu
-by5hKGIpCnRocm93IEguYihQLmxyKHRoaXMsYi5nV2EoKSxiLmduZCgpLGIuZ1ZtKCkpKX0sCnRvU3Ry
-aW5nOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMudyh0aGlzKX19ClAuWmQucHJvdG90eXBlPXsKdzpmdW5j
-dGlvbihhKXtyZXR1cm4iIn0sCiRpR3o6MX0KUC5Sbi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzLmNo
-YXJDb2RlQXQoMCk9PTA/czpzfSwKJGlCTDoxfQpQLm4xLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
-Yil7dmFyIHMscixxLHAKdC5KLmEoYSkKSC5oKGIpCnM9Si5yWShiKS5PWShiLCI9IikKaWYocz09PS0x
-KXtpZihiIT09IiIpYS5ZKDAsUC5rdShiLDAsYi5sZW5ndGgsdGhpcy5hLCEwKSwiIil9ZWxzZSBpZihz
-IT09MCl7cj1DLnhCLk5qKGIsMCxzKQpxPUMueEIuRyhiLHMrMSkKcD10aGlzLmEKYS5ZKDAsUC5rdShy
-LDAsci5sZW5ndGgscCwhMCksUC5rdShxLDAscS5sZW5ndGgscCwhMCkpfXJldHVybiBhfSwKJFM6MjF9
-ClAuY1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBJ
-UHY0IGFkZHJlc3MsICIrYSx0aGlzLmEsYikpfSwKJFM6NDZ9ClAuVkMucHJvdG90eXBlPXsKJDI6ZnVu
-Y3Rpb24oYSxiKXt0aHJvdyBILmIoUC5ycigiSWxsZWdhbCBJUHY2IGFkZHJlc3MsICIrYSx0aGlzLmEs
-YikpfSwKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuJDIoYSxudWxsKX0sCiRTOjQ4fQpQLkpULnBy
-b3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYoYi1hPjQpdGhpcy5hLiQyKCJhbiBJUHY2
-IHBhcnQgY2FuIG9ubHkgY29udGFpbiBhIG1heGltdW0gb2YgNCBoZXggZGlnaXRzIixhKQpzPVAuUUEo
-Qy54Qi5Oaih0aGlzLmIsYSxiKSwxNikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkK
-aWYoczwwfHxzPjY1NTM1KXRoaXMuYS4kMigiZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIG9m
-IGAweDAuLjB4RkZGRmAiLGEpCnJldHVybiBzfSwKJFM6NTB9ClAuRG4ucHJvdG90eXBlPXsKZ25EOmZ1
-bmN0aW9uKCl7dmFyIHMscixxLHA9dGhpcyxvPXAueAppZihvPT1udWxsKXtvPXAuYQpzPW8ubGVuZ3Ro
-IT09MD9vKyI6IjoiIgpyPXAuYwpxPXI9PW51bGwKaWYoIXF8fG89PT0iZmlsZSIpe289cysiLy8iCnM9
-cC5iCmlmKHMubGVuZ3RoIT09MClvPW8rcysiQCIKaWYoIXEpbys9cgpzPXAuZAppZihzIT1udWxsKW89
-bysiOiIrSC5FaihzKX1lbHNlIG89cwpvKz1wLmUKcz1wLmYKaWYocyE9bnVsbClvPW8rIj8iK3MKcz1w
-LnIKaWYocyE9bnVsbClvPW8rIiMiK3MKbz1vLmNoYXJDb2RlQXQoMCk9PTA/bzpvCmlmKHAueD09bnVs
-bClwLng9bwplbHNlIG89SC52aChILnlSKCJGaWVsZCAnX3RleHQnIGhhcyBiZWVuIGFzc2lnbmVkIGR1
-cmluZyBpbml0aWFsaXphdGlvbi4iKSl9cmV0dXJuIG99LApnRmo6ZnVuY3Rpb24oKXt2YXIgcyxyPXRo
-aXMscT1yLnkKaWYocT09bnVsbCl7cz1yLmUKaWYocy5sZW5ndGghPT0wJiZDLnhCLlcocywwKT09PTQ3
-KXM9Qy54Qi5HKHMsMSkKcT1zLmxlbmd0aD09PTA/Qy54RDpQLkFGKG5ldyBILmxKKEguVk0ocy5zcGxp
-dCgiLyIpLHQucyksdC5kTy5hKFAuUEgoKSksdC5kbyksdC5OKQppZihyLnk9PW51bGwpci5zS3AocSkK
-ZWxzZSBxPUgudmgoSC55UigiRmllbGQgJ3BhdGhTZWdtZW50cycgaGFzIGJlZW4gYXNzaWduZWQgZHVy
-aW5nIGluaXRpYWxpemF0aW9uLiIpKX1yZXR1cm4gcX0sCmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlz
-LHI9cy56CmlmKHI9PW51bGwpe3I9Qy54Qi5naU8ocy5nbkQoKSkKaWYocy56PT1udWxsKXMuej1yCmVs
-c2Ugcj1ILnZoKEgueVIoIkZpZWxkICdoYXNoQ29kZScgaGFzIGJlZW4gYXNzaWduZWQgZHVyaW5nIGlu
-aXRpYWxpemF0aW9uLiIpKX1yZXR1cm4gcn0sCmdoWTpmdW5jdGlvbigpe3ZhciBzPXRoaXMscj1zLlEK
-aWYocj09bnVsbCl7cj1uZXcgUC5HaihQLldYKHMuZ3RQKCkpLHQuZHcpCmlmKHMuUT09bnVsbClzLnNO
-TShyKQplbHNlIHI9SC52aChILnlSKCJGaWVsZCAncXVlcnlQYXJhbWV0ZXJzJyBoYXMgYmVlbiBhc3Np
-Z25lZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24uIikpfXJldHVybiByfSwKZ2t1OmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYn0sCmdKZjpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmMKaWYocz09bnVsbClyZXR1cm4i
-IgppZihDLnhCLm4ocywiWyIpKXJldHVybiBDLnhCLk5qKHMsMSxzLmxlbmd0aC0xKQpyZXR1cm4gc30s
-Cmd0cDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmQKcmV0dXJuIHM9PW51bGw/UC53Syh0aGlzLmEpOnN9
-LApndFA6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmYKcmV0dXJuIHM9PW51bGw/IiI6c30sCmdLYTpmdW5j
-dGlvbigpe3ZhciBzPXRoaXMucgpyZXR1cm4gcz09bnVsbD8iIjpzfSwKbm06ZnVuY3Rpb24oYSxiKXt2
-YXIgcyxyLHEscCxvLG4sbSxsLGssaj10aGlzCnQuYzkuYShiKQpzPWouYQpyPXM9PT0iZmlsZSIKcT1q
-LmIKcD1qLmQKbz1qLmMKaWYoIShvIT1udWxsKSlvPXEubGVuZ3RoIT09MHx8cCE9bnVsbHx8cj8iIjpu
-dWxsCm49ai5lCmlmKCFyKW09byE9bnVsbCYmbi5sZW5ndGghPT0wCmVsc2UgbT0hMAppZihtJiYhQy54
-Qi5uKG4sIi8iKSluPSIvIituCmw9bgprPVAubGUobnVsbCwwLDAsYikKcmV0dXJuIG5ldyBQLkRuKHMs
-cSxvLHAsbCxrLGoucil9LApKaDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbgpmb3Iocz0wLHI9
-MDtDLnhCLlFpKGIsIi4uLyIscik7KXtyKz0zOysrc31xPUMueEIuY24oYSwiLyIpCndoaWxlKCEwKXtp
-ZighKHE+MCYmcz4wKSlicmVhawpwPUMueEIuUGsoYSwiLyIscS0xKQppZihwPDApYnJlYWsKbz1xLXAK
-bj1vIT09MgppZighbnx8bz09PTMpaWYoQy54Qi5tKGEscCsxKT09PTQ2KW49IW58fEMueEIubShhLHAr
-Mik9PT00NgplbHNlIG49ITEKZWxzZSBuPSExCmlmKG4pYnJlYWs7LS1zCnE9cH1yZXR1cm4gQy54Qi5p
-NyhhLHErMSxudWxsLEMueEIuRyhiLHItMypzKSl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5t
-UyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqPXRoaXMsaT1u
-dWxsCmlmKGEuZ0ZpKCkubGVuZ3RoIT09MCl7cz1hLmdGaSgpCmlmKGEuZ2NqKCkpe3I9YS5na3UoKQpx
-PWEuZ0pmKGEpCnA9YS5neEEoKT9hLmd0cChhKTppfWVsc2V7cD1pCnE9cApyPSIifW89UC54ZShhLmdJ
-aShhKSkKbj1hLmdRRCgpP2EuZ3RQKCk6aX1lbHNle3M9ai5hCmlmKGEuZ2NqKCkpe3I9YS5na3UoKQpx
-PWEuZ0pmKGEpCnA9UC53QihhLmd4QSgpP2EuZ3RwKGEpOmkscykKbz1QLnhlKGEuZ0lpKGEpKQpuPWEu
-Z1FEKCk/YS5ndFAoKTppfWVsc2V7cj1qLmIKcT1qLmMKcD1qLmQKaWYoYS5nSWkoYSk9PT0iIil7bz1q
-LmUKbj1hLmdRRCgpP2EuZ3RQKCk6ai5mfWVsc2V7aWYoYS5ndFQoKSlvPVAueGUoYS5nSWkoYSkpCmVs
-c2V7bT1qLmUKaWYobS5sZW5ndGg9PT0wKWlmKHE9PW51bGwpbz1zLmxlbmd0aD09PTA/YS5nSWkoYSk6
-UC54ZShhLmdJaShhKSkKZWxzZSBvPVAueGUoIi8iK2EuZ0lpKGEpKQplbHNle2w9ai5KaChtLGEuZ0lp
-KGEpKQprPXMubGVuZ3RoPT09MAppZigha3x8cSE9bnVsbHx8Qy54Qi5uKG0sIi8iKSlvPVAueGUobCkK
-ZWxzZSBvPVAud0YobCwha3x8cSE9bnVsbCl9fW49YS5nUUQoKT9hLmd0UCgpOml9fX1yZXR1cm4gbmV3
-IFAuRG4ocyxyLHEscCxvLG4sYS5nWjgoKT9hLmdLYSgpOmkpfSwKZ2NqOmZ1bmN0aW9uKCl7cmV0dXJu
-IHRoaXMuYyE9bnVsbH0sCmd4QTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmQhPW51bGx9LApnUUQ6ZnVu
-Y3Rpb24oKXtyZXR1cm4gdGhpcy5mIT1udWxsfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuciE9
-bnVsbH0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLm4odGhpcy5lLCIvIil9LAp0NDpmdW5jdGlv
-bigpe3ZhciBzLHI9dGhpcyxxPXIuYQppZihxIT09IiImJnEhPT0iZmlsZSIpdGhyb3cgSC5iKFAuTDQo
-IkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSAiK3ErIiBVUkkiKSkKaWYoci5ndFAoKSE9
-PSIiKXRocm93IEguYihQLkw0KHUuaSkpCmlmKHIuZ0thKCkhPT0iIil0aHJvdyBILmIoUC5MNCh1Lmwp
-KQpxPSQud1EoKQppZihILm9UKHEpKXE9UC5tbihyKQplbHNle2lmKHIuYyE9bnVsbCYmci5nSmYocikh
-PT0iIilILnZoKFAuTDQodS5qKSkKcz1yLmdGaigpClAua0UocywhMSkKcT1QLnZnKEMueEIubihyLmUs
-Ii8iKT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29kZUF0KDApPT0wP3E6cX1yZXR1cm4gcX0sCnc6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHRoaXMuZ25EKCl9LApETjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKaWYo
-Yj09bnVsbClyZXR1cm4hMQppZihzPT09YilyZXR1cm4hMApyZXR1cm4gdC5kRC5iKGIpJiZzLmE9PT1i
-LmdGaSgpJiZzLmMhPW51bGw9PT1iLmdjaigpJiZzLmI9PT1iLmdrdSgpJiZzLmdKZihzKT09PWIuZ0pm
-KGIpJiZzLmd0cChzKT09PWIuZ3RwKGIpJiZzLmU9PT1iLmdJaShiKSYmcy5mIT1udWxsPT09Yi5nUUQo
-KSYmcy5ndFAoKT09PWIuZ3RQKCkmJnMuciE9bnVsbD09PWIuZ1o4KCkmJnMuZ0thKCk9PT1iLmdLYSgp
-fSwKc0twOmZ1bmN0aW9uKGEpe3RoaXMueT10LmJrLmEoYSl9LApzTk06ZnVuY3Rpb24oYSl7dGhpcy5R
-PXQuY1ouYShhKX0sCiRpaUQ6MSwKZ0ZpOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYX0sCmdJaTpmdW5j
-dGlvbihhKXtyZXR1cm4gdGhpcy5lfX0KUC5SWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1
-cm4gUC5lUChDLlpKLEguaChhKSxDLnhNLCExKX0sCiRTOjV9ClAuTUUucHJvdG90eXBlPXsKJDI6ZnVu
-Y3Rpb24oYSxiKXt2YXIgcz10aGlzLmIscj10aGlzLmEKcy5hKz1yLmEKci5hPSImIgpyPXMuYSs9SC5F
-aihQLmVQKEMuRjMsYSxDLnhNLCEwKSkKaWYoYiE9bnVsbCYmYi5sZW5ndGghPT0wKXtzLmE9cisiPSIK
-cy5hKz1ILkVqKFAuZVAoQy5GMyxiLEMueE0sITApKX19LAokUzoyMn0KUC55NS5wcm90b3R5cGU9ewok
-MjpmdW5jdGlvbihhLGIpe3ZhciBzLHIKSC5oKGEpCmlmKGI9PW51bGx8fHR5cGVvZiBiPT0ic3RyaW5n
-Iil0aGlzLmEuJDIoYSxILmsoYikpCmVsc2UgZm9yKHM9Si5JVCh0LnIuYShiKSkscj10aGlzLmE7cy5G
-KCk7KXIuJDIoYSxILmgocy5nbCgpKSl9LAokUzoxNH0KUC5QRS5wcm90b3R5cGU9ewpnbFI6ZnVuY3Rp
-b24oKXt2YXIgcyxyLHEscCxvPXRoaXMsbj1udWxsLG09by5jCmlmKG09PW51bGwpe209by5iCmlmKDA+
-PW0ubGVuZ3RoKXJldHVybiBILk9IKG0sMCkKcz1vLmEKbT1tWzBdKzEKcj1DLnhCLlhVKHMsIj8iLG0p
-CnE9cy5sZW5ndGgKaWYocj49MCl7cD1QLlBJKHMscisxLHEsQy5WQywhMSkKcT1yfWVsc2UgcD1uCm09
-by5jPW5ldyBQLnFlKCJkYXRhIiwiIixuLG4sUC5QSShzLG0scSxDLldkLCExKSxwLG4pfXJldHVybiBt
-fSwKdzpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMuYgppZigwPj1yLmxlbmd0aClyZXR1cm4gSC5PSChy
-LDApCnM9dGhpcy5hCnJldHVybiByWzBdPT09LTE/ImRhdGE6IitzOnN9fQpQLnEzLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVWludDhBcnJheSg5Nil9LAokUzoyM30KUC55SS5wcm90
-b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYQppZihhPj1zLmxlbmd0aClyZXR1cm4g
-SC5PSChzLGEpCnM9c1thXQpKLkNNKHMsMCw5NixiKQpyZXR1cm4gc30sCiRTOjI0fQpQLmM2LnByb3Rv
-dHlwZT17CiQzOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscApmb3Iocz1iLmxlbmd0aCxyPWEubGVu
-Z3RoLHE9MDtxPHM7KytxKXtwPUMueEIuVyhiLHEpXjk2CmlmKHA+PXIpcmV0dXJuIEguT0goYSxwKQph
-W3BdPWN9fSwKJFM6MTV9ClAucWQucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIs
-cSxwCmZvcihzPUMueEIuVyhiLDApLHI9Qy54Qi5XKGIsMSkscT1hLmxlbmd0aDtzPD1yOysrcyl7cD0o
-c145Nik+Pj4wCmlmKHA+PXEpcmV0dXJuIEguT0goYSxwKQphW3BdPWN9fSwKJFM6MTV9ClAuVWYucHJv
-dG90eXBlPXsKZ2NqOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYz4wfSwKZ3hBOmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYz4wJiZ0aGlzLmQrMTx0aGlzLmV9LApnUUQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5m
-PHRoaXMucn0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnI8dGhpcy5hLmxlbmd0aH0sCmdOdzpm
-dW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm4odGhpcy5hLCJmaWxlIil9LApnV1o6ZnVu
-Y3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NCYmQy54Qi5uKHRoaXMuYSwiaHR0cCIpfSwKZ1JlOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuYj09PTUmJkMueEIubih0aGlzLmEsImh0dHBzIil9LApndFQ6ZnVuY3Rp
-b24oKXtyZXR1cm4gQy54Qi5RaSh0aGlzLmEsIi8iLHRoaXMuZSl9LApnRmk6ZnVuY3Rpb24oKXt2YXIg
-cz10aGlzLngKcmV0dXJuIHM9PW51bGw/dGhpcy54PXRoaXMuVTIoKTpzfSwKVTI6ZnVuY3Rpb24oKXt2
-YXIgcz10aGlzLHI9cy5iCmlmKHI8PTApcmV0dXJuIiIKaWYocy5nV1ooKSlyZXR1cm4iaHR0cCIKaWYo
-cy5nUmUoKSlyZXR1cm4iaHR0cHMiCmlmKHMuZ053KCkpcmV0dXJuImZpbGUiCmlmKHI9PT03JiZDLnhC
-Lm4ocy5hLCJwYWNrYWdlIikpcmV0dXJuInBhY2thZ2UiCnJldHVybiBDLnhCLk5qKHMuYSwwLHIpfSwK
-Z2t1OmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5jLHI9dGhpcy5iKzMKcmV0dXJuIHM+cj9DLnhCLk5qKHRo
-aXMuYSxyLHMtMSk6IiJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5jCnJldHVybiBzPjA/Qy54
-Qi5Oaih0aGlzLmEscyx0aGlzLmQpOiIifSwKZ3RwOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYocy5n
-eEEoKSlyZXR1cm4gUC5RQShDLnhCLk5qKHMuYSxzLmQrMSxzLmUpLG51bGwpCmlmKHMuZ1daKCkpcmV0
-dXJuIDgwCmlmKHMuZ1JlKCkpcmV0dXJuIDQ0MwpyZXR1cm4gMH0sCmdJaTpmdW5jdGlvbihhKXtyZXR1
-cm4gQy54Qi5Oaih0aGlzLmEsdGhpcy5lLHRoaXMuZil9LApndFA6ZnVuY3Rpb24oKXt2YXIgcz10aGlz
-LmYscj10aGlzLnIKcmV0dXJuIHM8cj9DLnhCLk5qKHRoaXMuYSxzKzEscik6IiJ9LApnS2E6ZnVuY3Rp
-b24oKXt2YXIgcz10aGlzLnIscj10aGlzLmEKcmV0dXJuIHM8ci5sZW5ndGg/Qy54Qi5HKHIscysxKToi
-In0sCmdGajpmdW5jdGlvbigpe3ZhciBzLHIscT10aGlzLmUscD10aGlzLmYsbz10aGlzLmEKaWYoQy54
-Qi5RaShvLCIvIixxKSkrK3EKaWYocT09PXApcmV0dXJuIEMueEQKcz1ILlZNKFtdLHQucykKZm9yKHI9
-cTtyPHA7KytyKWlmKEMueEIubShvLHIpPT09NDcpe0MuTm0uaShzLEMueEIuTmoobyxxLHIpKQpxPXIr
-MX1DLk5tLmkocyxDLnhCLk5qKG8scSxwKSkKcmV0dXJuIFAuQUYocyx0Lk4pfSwKZ2hZOmZ1bmN0aW9u
-KCl7aWYodGhpcy5mPj10aGlzLnIpcmV0dXJuIEMuQ00KcmV0dXJuIG5ldyBQLkdqKFAuV1godGhpcy5n
-dFAoKSksdC5kdyl9LAprWDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmQrMQpyZXR1cm4gcythLmxlbmd0
-aD09PXRoaXMuZSYmQy54Qi5RaSh0aGlzLmEsYSxzKX0sCk45OmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxy
-PXMucixxPXMuYQppZihyPj1xLmxlbmd0aClyZXR1cm4gcwpyZXR1cm4gbmV3IFAuVWYoQy54Qi5Oaihx
-LDAscikscy5iLHMuYyxzLmQscy5lLHMuZixyLHMueCl9LApubTpmdW5jdGlvbihhLGIpe3ZhciBzLHIs
-cSxwLG8sbixtLGwsayxqLGk9dGhpcyxoPW51bGwKdC5jOS5hKGIpCnM9aS5nRmkoKQpyPXM9PT0iZmls
-ZSIKcT1pLmMKcD1xPjA/Qy54Qi5OaihpLmEsaS5iKzMscSk6IiIKbz1pLmd4QSgpP2kuZ3RwKGkpOmgK
-cT1pLmMKaWYocT4wKW49Qy54Qi5OaihpLmEscSxpLmQpCmVsc2Ugbj1wLmxlbmd0aCE9PTB8fG8hPW51
-bGx8fHI/IiI6aApxPWkuYQptPUMueEIuTmoocSxpLmUsaS5mKQppZighcilsPW4hPW51bGwmJm0ubGVu
-Z3RoIT09MAplbHNlIGw9ITAKaWYobCYmIUMueEIubihtLCIvIikpbT0iLyIrbQprPVAubGUoaCwwLDAs
-YikKbD1pLnIKaj1sPHEubGVuZ3RoP0MueEIuRyhxLGwrMSk6aApyZXR1cm4gbmV3IFAuRG4ocyxwLG4s
-byxtLGssail9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0
-aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVybiB0aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRo
-aXMudnMoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxo
-LGc9Yi5iCmlmKGc+MClyZXR1cm4gYgpzPWIuYwppZihzPjApe3I9YS5iCmlmKHI8PTApcmV0dXJuIGIK
-aWYoYS5nTncoKSlxPWIuZSE9PWIuZgplbHNlIGlmKGEuZ1daKCkpcT0hYi5rWCgiODAiKQplbHNlIHE9
-IWEuZ1JlKCl8fCFiLmtYKCI0NDMiKQppZihxKXtwPXIrMQpyZXR1cm4gbmV3IFAuVWYoQy54Qi5Oaihh
-LmEsMCxwKStDLnhCLkcoYi5hLGcrMSkscixzK3AsYi5kK3AsYi5lK3AsYi5mK3AsYi5yK3AsYS54KX1l
-bHNlIHJldHVybiB0aGlzLnZzKCkubVMoYil9bz1iLmUKZz1iLmYKaWYobz09PWcpe3M9Yi5yCmlmKGc8
-cyl7cj1hLmYKcD1yLWcKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscikrQy54Qi5HKGIuYSxn
-KSxhLmIsYS5jLGEuZCxhLmUsZytwLHMrcCxhLngpfWc9Yi5hCmlmKHM8Zy5sZW5ndGgpe3I9YS5yCnJl
-dHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHIpK0MueEIuRyhnLHMpLGEuYixhLmMsYS5kLGEuZSxh
-LmYscysoci1zKSxhLngpfXJldHVybiBhLk45KCl9cz1iLmEKaWYoQy54Qi5RaShzLCIvIixvKSl7cj1h
-LmUKcD1yLW8KcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscikrQy54Qi5HKHMsbyksYS5iLGEu
-YyxhLmQscixnK3AsYi5yK3AsYS54KX1uPWEuZQptPWEuZgppZihuPT09bSYmYS5jPjApe2Zvcig7Qy54
-Qi5RaShzLCIuLi8iLG8pOylvKz0zCnA9bi1vKzEKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAs
-bikrIi8iK0MueEIuRyhzLG8pLGEuYixhLmMsYS5kLG4sZytwLGIucitwLGEueCl9bD1hLmEKZm9yKGs9
-bjtDLnhCLlFpKGwsIi4uLyIsayk7KWsrPTMKaj0wCndoaWxlKCEwKXtpPW8rMwppZighKGk8PWcmJkMu
-eEIuUWkocywiLi4vIixvKSkpYnJlYWs7KytqCm89aX1mb3IoaD0iIjttPms7KXstLW0KaWYoQy54Qi5t
-KGwsbSk9PT00Nyl7aWYoaj09PTApe2g9Ii8iCmJyZWFrfS0tagpoPSIvIn19aWYobT09PWsmJmEuYjw9
-MCYmIUMueEIuUWkobCwiLyIsbikpe28tPWoqMwpoPSIifXA9bS1vK2gubGVuZ3RoCnJldHVybiBuZXcg
-UC5VZihDLnhCLk5qKGwsMCxtKStoK0MueEIuRyhzLG8pLGEuYixhLmMsYS5kLG4sZytwLGIucitwLGEu
-eCl9LAp0NDpmdW5jdGlvbigpe3ZhciBzLHIscSxwPXRoaXMKaWYocC5iPj0wJiYhcC5nTncoKSl0aHJv
-dyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIrcC5nRmkoKSsiIFVS
-SSIpKQpzPXAuZgpyPXAuYQppZihzPHIubGVuZ3RoKXtpZihzPHAucil0aHJvdyBILmIoUC5MNCh1Lmkp
-KQp0aHJvdyBILmIoUC5MNCh1LmwpKX1xPSQud1EoKQppZihILm9UKHEpKXM9UC5tbihwKQplbHNle2lm
-KHAuYzxwLmQpSC52aChQLkw0KHUuaikpCnM9Qy54Qi5OaihyLHAuZSxzKX1yZXR1cm4gc30sCmdpTzpm
-dW5jdGlvbihhKXt2YXIgcz10aGlzLnkKcmV0dXJuIHM9PW51bGw/dGhpcy55PUMueEIuZ2lPKHRoaXMu
-YSk6c30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQppZih0aGlzPT09YilyZXR1
-cm4hMApyZXR1cm4gdC5kRC5iKGIpJiZ0aGlzLmE9PT1iLncoMCl9LAp2czpmdW5jdGlvbigpe3ZhciBz
-PXRoaXMscj1udWxsLHE9cy5nRmkoKSxwPXMuZ2t1KCksbz1zLmM+MD9zLmdKZihzKTpyLG49cy5neEEo
-KT9zLmd0cChzKTpyLG09cy5hLGw9cy5mLGs9Qy54Qi5OaihtLHMuZSxsKSxqPXMucgpsPWw8aj9zLmd0
-UCgpOnIKcmV0dXJuIG5ldyBQLkRuKHEscCxvLG4sayxsLGo8bS5sZW5ndGg/cy5nS2EoKTpyKX0sCnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5w
-cm90b3R5cGU9e30KVy5HaC5wcm90b3R5cGU9ewpzTFU6ZnVuY3Rpb24oYSxiKXthLmhyZWY9Yn0sCnc6
-ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpR2g6MX0KVy5mWS5wcm90b3R5cGU9ewp3OmZ1
-bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLm5CLnByb3RvdHlwZT17JGluQjoxfQpXLkF6LnBy
-b3RvdHlwZT17JGlBejoxfQpXLlFQLnByb3RvdHlwZT17JGlRUDoxfQpXLm54LnByb3RvdHlwZT17CmdB
-OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcub0oucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGEubGVuZ3RofX0KVy5pZC5wcm90b3R5cGU9e30KVy5RRi5wcm90b3R5cGU9e30KVy5O
-aC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLmFlLnByb3RvdHlw
-ZT17CkRjOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuY3JlYXRlSFRNTERvY3VtZW50KGIpfX0KVy5JQi5w
-cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS5sZWZ0CnIudG9TdHJpbmcKcj0iUmVjdGFu
-Z2xlICgiK0guRWoocikrIiwgIgpzPWEudG9wCnMudG9TdHJpbmcKcz1yK0guRWoocykrIikgIgpyPWEu
-d2lkdGgKci50b1N0cmluZwpyPXMrSC5FaihyKSsiIHggIgpzPWEuaGVpZ2h0CnMudG9TdHJpbmcKcmV0
-dXJuIHIrSC5FaihzKX0sCkROOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihiPT1udWxsKXJldHVybiEx
-CmlmKHQucS5iKGIpKXtzPWEubGVmdApzLnRvU3RyaW5nCnI9Yi5sZWZ0CnIudG9TdHJpbmcKaWYocz09
-PXIpe3M9YS50b3AKcy50b1N0cmluZwpyPWIudG9wCnIudG9TdHJpbmcKaWYocz09PXIpe3M9YS53aWR0
-aApzLnRvU3RyaW5nCnI9Yi53aWR0aApyLnRvU3RyaW5nCmlmKHM9PT1yKXtzPWEuaGVpZ2h0CnMudG9T
-dHJpbmcKcj1iLmhlaWdodApyLnRvU3RyaW5nCnI9cz09PXIKcz1yfWVsc2Ugcz0hMX1lbHNlIHM9ITF9
-ZWxzZSBzPSExfWVsc2Ugcz0hMQpyZXR1cm4gc30sCmdpTzpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1h
-LmxlZnQKcC50b1N0cmluZwpwPUMuQ0QuZ2lPKHApCnM9YS50b3AKcy50b1N0cmluZwpzPUMuQ0QuZ2lP
-KHMpCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9Qy5DRC5naU8ocikKcT1hLmhlaWdodApxLnRvU3RyaW5n
-CnJldHVybiBXLnJFKHAscyxyLEMuQ0QuZ2lPKHEpKX0sCiRpdG46MX0KVy5uNy5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLnd6LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9u
-KGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3ZhciBzCkgudVAoYikKcz10
-aGlzLmEKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGIpCnJldHVybiB0aGlzLiR0aS5j
-LmEoc1tiXSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0aGlzLiR0aS5jLmEoYykKdGhyb3cgSC5iKFAuTDQo
-IkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19ClcuY3YucHJvdG90eXBlPXsKZ1FnOmZ1bmN0aW9uKGEpe3Jl
-dHVybiBuZXcgVy5pNyhhKX0sCmdEOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5JNChhKX0sCnNEOmZ1
-bmN0aW9uKGEsYil7dmFyIHMKdC5RLmEoYikKcz10aGlzLmdEKGEpCnMuVjEoMCkKcy5GVigwLGIpfSwK
-dzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LApGRjpmdW5jdGlvbihhKXt2YXIgcz0hIWEu
-c2Nyb2xsSW50b1ZpZXdJZk5lZWRlZAppZihzKWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZCgpCmVsc2Ug
-YS5zY3JvbGxJbnRvVmlldygpfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyPXRoaXMucjYo
-YSxjLGQsZSkKc3dpdGNoKGIudG9Mb3dlckNhc2UoKSl7Y2FzZSJiZWZvcmViZWdpbiI6cz1hLnBhcmVu
-dE5vZGUKcy50b1N0cmluZwpKLkVoKHMscixhKQpicmVhawpjYXNlImFmdGVyYmVnaW4iOnM9YS5jaGls
-ZE5vZGVzCnRoaXMubUsoYSxyLHMubGVuZ3RoPjA/c1swXTpudWxsKQpicmVhawpjYXNlImJlZm9yZWVu
-ZCI6YS5hcHBlbmRDaGlsZChyKQpicmVhawpjYXNlImFmdGVyZW5kIjpzPWEucGFyZW50Tm9kZQpzLnRv
-U3RyaW5nCkouRWgocyxyLGEubmV4dFNpYmxpbmcpCmJyZWFrCmRlZmF1bHQ6SC52aChQLnhZKCJJbnZh
-bGlkIHBvc2l0aW9uICIrYikpfX0sCnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwCmlmKGM9
-PW51bGwpe2lmKGQ9PW51bGwpe3M9JC5sdAppZihzPT1udWxsKXtzPUguVk0oW10sdC51KQpyPW5ldyBX
-LnZEKHMpCkMuTm0uaShzLFcuVHcobnVsbCkpCkMuTm0uaShzLFcuQmwoKSkKJC5sdD1yCmQ9cn1lbHNl
-IGQ9c31zPSQuRVUKaWYocz09bnVsbCl7cz1uZXcgVy5LbyhkKQokLkVVPXMKYz1zfWVsc2V7cy5hPWQK
-Yz1zfX1lbHNlIGlmKGQhPW51bGwpdGhyb3cgSC5iKFAueFkoInZhbGlkYXRvciBjYW4gb25seSBiZSBw
-YXNzZWQgaWYgdHJlZVNhbml0aXplciBpcyBudWxsIikpCmlmKCQueG89PW51bGwpe3M9ZG9jdW1lbnQK
-cj1zLmltcGxlbWVudGF0aW9uCnIudG9TdHJpbmcKcj1DLm1ILkRjKHIsIiIpCiQueG89cgokLkJPPXIu
-Y3JlYXRlUmFuZ2UoKQpyPSQueG8uY3JlYXRlRWxlbWVudCgiYmFzZSIpCnQuY1IuYShyKQpzPXMuYmFz
-ZVVSSQpzLnRvU3RyaW5nCnIuaHJlZj1zCiQueG8uaGVhZC5hcHBlbmRDaGlsZChyKX1zPSQueG8KaWYo
-cy5ib2R5PT1udWxsKXtyPXMuY3JlYXRlRWxlbWVudCgiYm9keSIpCkMuQlouc1hHKHMsdC5rLmEocikp
-fXM9JC54bwppZih0LmsuYihhKSl7cz1zLmJvZHkKcy50b1N0cmluZwpxPXN9ZWxzZXtzLnRvU3RyaW5n
-CnE9cy5jcmVhdGVFbGVtZW50KGEudGFnTmFtZSkKJC54by5ib2R5LmFwcGVuZENoaWxkKHEpfWlmKCJj
-cmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUmJiFDLk5tLnRn
-KEMuU3EsYS50YWdOYW1lKSl7JC5CTy5zZWxlY3ROb2RlQ29udGVudHMocSkKcz0kLkJPCnMudG9TdHJp
-bmcKcD1zLmNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudChiPT1udWxsPyJudWxsIjpiKX1lbHNle0oud2Yo
-cSxiKQpwPSQueG8uY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCmZvcig7cz1xLmZpcnN0Q2hpbGQscyE9
-bnVsbDspcC5hcHBlbmRDaGlsZChzKX1pZihxIT09JC54by5ib2R5KUouTHQocSkKYy5QbihwKQpkb2N1
-bWVudC5hZG9wdE5vZGUocCkKcmV0dXJuIHB9LApBSDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMu
-cjYoYSxiLGMsbnVsbCl9LApzaGY6ZnVuY3Rpb24oYSxiKXt0aGlzLllDKGEsYil9LApwazpmdW5jdGlv
-bihhLGIsYyl7dGhpcy5zYTQoYSxudWxsKQphLmFwcGVuZENoaWxkKHRoaXMucjYoYSxiLG51bGwsYykp
-fSwKWUM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LApzUk46ZnVuY3Rpb24o
-YSxiKXthLmlubmVySFRNTD1ifSwKZ25zOmZ1bmN0aW9uKGEpe3JldHVybiBhLnRhZ05hbWV9LApnVmw6
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLmV1KGEsImNsaWNrIiwhMSx0LmopfSwKJGljdjoxfQpXLkN2
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0LmguYih0LkEuYShhKSl9LAokUzoyNn0K
-Vy5lYS5wcm90b3R5cGU9eyRpZWE6MX0KVy5EMC5wcm90b3R5cGU9ewpPbjpmdW5jdGlvbihhLGIsYyxk
-KXt0LmJ3LmEoYykKaWYoYyE9bnVsbCl0aGlzLnYoYSxiLGMsZCl9LApCOmZ1bmN0aW9uKGEsYixjKXty
-ZXR1cm4gdGhpcy5PbihhLGIsYyxudWxsKX0sCnY6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEuYWRk
-RXZlbnRMaXN0ZW5lcihiLEgudFIodC5idy5hKGMpLDEpLGQpfSwKJGlEMDoxfQpXLmhILnByb3RvdHlw
-ZT17JGloSDoxfQpXLmg0LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19
-ClcuYnIucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5WYi5wcm90
-b3R5cGU9ewpzWEc6ZnVuY3Rpb24oYSxiKXthLmJvZHk9Yn19ClcuZkoucHJvdG90eXBlPXsKZW86ZnVu
-Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIGEub3BlbihiLGMsITApfSwKJGlmSjoxfQpXLndhLnByb3RvdHlw
-ZT17fQpXLlNnLnByb3RvdHlwZT17JGlTZzoxfQpXLnU4LnByb3RvdHlwZT17CmdEcjpmdW5jdGlvbihh
-KXtpZigib3JpZ2luIiBpbiBhKXJldHVybiBhLm9yaWdpbgpyZXR1cm4gSC5FaihhLnByb3RvY29sKSsi
-Ly8iK0guRWooYS5ob3N0KX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdTg6MX0K
-Vy5Bai5wcm90b3R5cGU9eyRpQWo6MX0KVy5lNy5wcm90b3R5cGU9ewpncjg6ZnVuY3Rpb24oYSl7dmFy
-IHM9dGhpcy5hLHI9cy5jaGlsZE5vZGVzLmxlbmd0aAppZihyPT09MCl0aHJvdyBILmIoUC5QVigiTm8g
-ZWxlbWVudHMiKSkKaWYocj4xKXRocm93IEguYihQLlBWKCJNb3JlIHRoYW4gb25lIGVsZW1lbnQiKSkK
-cz1zLmZpcnN0Q2hpbGQKcy50b1N0cmluZwpyZXR1cm4gc30sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMs
-cixxLHAsbwp0LmVoLmEoYikKcz1iLmEKcj10aGlzLmEKaWYocyE9PXIpZm9yKHE9cy5jaGlsZE5vZGVz
-Lmxlbmd0aCxwPTA7cDxxOysrcCl7bz1zLmZpcnN0Q2hpbGQKby50b1N0cmluZwpyLmFwcGVuZENoaWxk
-KG8pfXJldHVybn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIKdC5BLmEoYykKcz10aGlzLmEKcj1z
-LmNoaWxkTm9kZXMKaWYoYjwwfHxiPj1yLmxlbmd0aClyZXR1cm4gSC5PSChyLGIpCnMucmVwbGFjZUNo
-aWxkKGMscltiXSl9LApna3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLmNoaWxkTm9kZXMKcmV0dXJu
-IG5ldyBXLlc5KHMscy5sZW5ndGgsSC56KHMpLkMoIlc5PEdtLkU+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuYS5jaGlsZE5vZGVzLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXt2YXIgcwpILnVQ
-KGIpCnM9dGhpcy5hLmNoaWxkTm9kZXMKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGIp
-CnJldHVybiBzW2JdfX0KVy51SC5wcm90b3R5cGU9ewp3ZzpmdW5jdGlvbihhKXt2YXIgcz1hLnBhcmVu
-dE5vZGUKaWYocyE9bnVsbClzLnJlbW92ZUNoaWxkKGEpfSwKRDQ6ZnVuY3Rpb24oYSl7dmFyIHMKZm9y
-KDtzPWEuZmlyc3RDaGlsZCxzIT1udWxsOylhLnJlbW92ZUNoaWxkKHMpfSwKdzpmdW5jdGlvbihhKXt2
-YXIgcz1hLm5vZGVWYWx1ZQpyZXR1cm4gcz09bnVsbD90aGlzLlUoYSk6c30sCnNhNDpmdW5jdGlvbihh
-LGIpe2EudGV4dENvbnRlbnQ9Yn0sCm1LOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYS5pbnNlcnRCZWZv
-cmUoYixjKX0sCiRpdUg6MX0KVy5CSC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5s
-ZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRo
-cm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihh
-LGIsYyl7dC5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11
-dGFibGUgTGlzdC4iKSl9LApndEg6ZnVuY3Rpb24oYSl7aWYoYS5sZW5ndGg+MClyZXR1cm4gYVswXQp0
-aHJvdyBILmIoUC5QVigiTm8gZWxlbWVudHMiKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1h
-Lmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6
-MSwKJGl6TToxfQpXLlNOLnByb3RvdHlwZT17fQpXLmV3LnByb3RvdHlwZT17JGlldzoxfQpXLmxwLnBy
-b3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuVGIucHJvdG90eXBlPXsK
-cjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscgppZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBp
-biB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixjLGQpCnM9Vy5VOSgiPHRh
-YmxlPiIrSC5FaihiKSsiPC90YWJsZT4iLGMsZCkKcj1kb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdt
-ZW50KCkKci50b1N0cmluZwpzLnRvU3RyaW5nCm5ldyBXLmU3KHIpLkZWKDAsbmV3IFcuZTcocykpCnJl
-dHVybiByfX0KVy5Jdi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscApp
-ZigiY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVy
-biB0aGlzLkRXKGEsYixjLGQpCnM9ZG9jdW1lbnQKcj1zLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpz
-PUMuSWUucjYocy5jcmVhdGVFbGVtZW50KCJ0YWJsZSIpLGIsYyxkKQpzLnRvU3RyaW5nCnM9bmV3IFcu
-ZTcocykKcT1zLmdyOChzKQpxLnRvU3RyaW5nCnM9bmV3IFcuZTcocSkKcD1zLmdyOChzKQpyLnRvU3Ry
-aW5nCnAudG9TdHJpbmcKbmV3IFcuZTcocikuRlYoMCxuZXcgVy5lNyhwKSkKcmV0dXJuIHJ9fQpXLldQ
-LnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQppZigiY3JlYXRlQ29udGV4
-dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlKXJldHVybiB0aGlzLkRXKGEsYixj
-LGQpCnM9ZG9jdW1lbnQKcj1zLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpzPUMuSWUucjYocy5jcmVh
-dGVFbGVtZW50KCJ0YWJsZSIpLGIsYyxkKQpzLnRvU3RyaW5nCnM9bmV3IFcuZTcocykKcT1zLmdyOChz
-KQpyLnRvU3RyaW5nCnEudG9TdHJpbmcKbmV3IFcuZTcocikuRlYoMCxuZXcgVy5lNyhxKSkKcmV0dXJu
-IHJ9fQpXLnlZLnByb3RvdHlwZT17CnBrOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyCnRoaXMuc2E0KGEs
-bnVsbCkKcz1hLmNvbnRlbnQKcy50b1N0cmluZwpKLmJUKHMpCnI9dGhpcy5yNihhLGIsbnVsbCxjKQph
-LmNvbnRlbnQuYXBwZW5kQ2hpbGQocil9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEs
-YixudWxsKX0sCiRpeVk6MX0KVy53Ni5wcm90b3R5cGU9e30KVy5LNS5wcm90b3R5cGU9ewpQbzpmdW5j
-dGlvbihhLGIsYyl7dmFyIHM9Vy5QMShhLm9wZW4oYixjKSkKcmV0dXJuIHN9LApnbVc6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGEubG9jYXRpb259LAp1czpmdW5jdGlvbihhLGIpe3JldHVybiBhLmNvbmZpcm0oYil9
-LAokaUs1OjEsCiRpdjY6MX0KVy5DbS5wcm90b3R5cGU9eyRpQ206MX0KVy5DUS5wcm90b3R5cGU9eyRp
-Q1E6MX0KVy53NC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS5sZWZ0CnIudG9TdHJp
-bmcKcj0iUmVjdGFuZ2xlICgiK0guRWoocikrIiwgIgpzPWEudG9wCnMudG9TdHJpbmcKcz1yK0guRWoo
-cykrIikgIgpyPWEud2lkdGgKci50b1N0cmluZwpyPXMrSC5FaihyKSsiIHggIgpzPWEuaGVpZ2h0CnMu
-dG9TdHJpbmcKcmV0dXJuIHIrSC5FaihzKX0sCkROOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihiPT1u
-dWxsKXJldHVybiExCmlmKHQucS5iKGIpKXtzPWEubGVmdApzLnRvU3RyaW5nCnI9Yi5sZWZ0CnIudG9T
-dHJpbmcKaWYocz09PXIpe3M9YS50b3AKcy50b1N0cmluZwpyPWIudG9wCnIudG9TdHJpbmcKaWYocz09
-PXIpe3M9YS53aWR0aApzLnRvU3RyaW5nCnI9Yi53aWR0aApyLnRvU3RyaW5nCmlmKHM9PT1yKXtzPWEu
-aGVpZ2h0CnMudG9TdHJpbmcKcj1iLmhlaWdodApyLnRvU3RyaW5nCnI9cz09PXIKcz1yfWVsc2Ugcz0h
-MX1lbHNlIHM9ITF9ZWxzZSBzPSExfWVsc2Ugcz0hMQpyZXR1cm4gc30sCmdpTzpmdW5jdGlvbihhKXt2
-YXIgcyxyLHEscD1hLmxlZnQKcC50b1N0cmluZwpwPUMuQ0QuZ2lPKHApCnM9YS50b3AKcy50b1N0cmlu
-ZwpzPUMuQ0QuZ2lPKHMpCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9Qy5DRC5naU8ocikKcT1hLmhlaWdo
-dApxLnRvU3RyaW5nCnJldHVybiBXLnJFKHAscyxyLEMuQ0QuZ2lPKHEpKX19ClcucmgucHJvdG90eXBl
-PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikK
-aWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC5DZihiLGEsbnVsbCxudWxsLG51bGwp
-KQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe3QuQS5hKGMpCnRocm93IEguYihQLkw0KCJD
-YW5ub3QgYXNzaWduIGVsZW1lbnQgb2YgaW1tdXRhYmxlIExpc3QuIikpfSwKRTpmdW5jdGlvbihhLGIp
-e2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwK
-JGlYajoxLAokaWNYOjEsCiRpek06MX0KVy5jZi5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFy
-IHMscixxLHAsbwp0LmVBLmEoYikKZm9yKHM9dGhpcy5nVigpLHI9cy5sZW5ndGgscT10aGlzLmEscD0w
-O3A8cy5sZW5ndGg7cy5sZW5ndGg9PT1yfHwoMCxILmxrKShzKSwrK3Ape289c1twXQpiLiQyKG8scS5n
-ZXRBdHRyaWJ1dGUobykpfX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09dGhpcy5hLmF0
-dHJpYnV0ZXMKbS50b1N0cmluZwpzPUguVk0oW10sdC5zKQpmb3Iocj1tLmxlbmd0aCxxPXQuaDkscD0w
-O3A8cjsrK3Ape2lmKHA+PW0ubGVuZ3RoKXJldHVybiBILk9IKG0scCkKbz1xLmEobVtwXSkKaWYoby5u
-YW1lc3BhY2VVUkk9PW51bGwpe249by5uYW1lCm4udG9TdHJpbmcKQy5ObS5pKHMsbil9fXJldHVybiBz
-fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVuZ3RoPT09MH19ClcuaTcucHJvdG90
-eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vVCh0aGlzLmEuaGFzQXR0cmlidXRlKGEpKQpyZXR1
-cm4gc30sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmdldEF0dHJpYnV0ZShILmgoYikpfSwK
-WTpmdW5jdGlvbihhLGIsYyl7dGhpcy5hLnNldEF0dHJpYnV0ZShiLGMpfSwKZ0E6ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuZ1YoKS5sZW5ndGh9fQpXLlN5LnByb3RvdHlwZT17Cng0OmZ1bmN0aW9uKGEpe3Zh
-ciBzPUgub1QodGhpcy5hLmEuaGFzQXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKGEpKSkKcmV0dXJuIHN9
-LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgiZGF0YS0iK3RoaXMu
-TyhILmgoYikpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJpYnV0ZSgiZGF0YS0i
-K3RoaXMuTyhiKSxjKX0sCks6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLG5ldyBXLktTKHRoaXMsdC5l
-QS5hKGIpKSl9LApnVjpmdW5jdGlvbigpe3ZhciBzPUguVk0oW10sdC5zKQp0aGlzLmEuSygwLG5ldyBX
-LkEzKHRoaXMscykpCnJldHVybiBzfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ1YoKS5sZW5n
-dGh9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ1YoKS5sZW5ndGg9PT0wfSwKazpmdW5jdGlv
-bihhKXt2YXIgcyxyLHE9SC5WTShhLnNwbGl0KCItIiksdC5zKQpmb3Iocz0xO3M8cS5sZW5ndGg7Kytz
-KXtyPXFbc10KaWYoci5sZW5ndGg+MClDLk5tLlkocSxzLHJbMF0udG9VcHBlckNhc2UoKStKLktWKHIs
-MSkpfXJldHVybiBDLk5tLkgocSwiIil9LApPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8KZm9yKHM9
-YS5sZW5ndGgscj0wLHE9IiI7cjxzOysrcil7cD1hW3JdCm89cC50b0xvd2VyQ2FzZSgpCnE9KHAhPT1v
-JiZyPjA/cSsiLSI6cSkrb31yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX19ClcuS1MucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZKGEpLm4oYSwiZGF0YS0iKSl0aGlzLmIuJDIodGhp
-cy5hLmsoQy54Qi5HKGEsNSkpLGIpfSwKJFM6MTZ9ClcuQTMucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24o
-YSxiKXtpZihKLnJZKGEpLm4oYSwiZGF0YS0iKSlDLk5tLmkodGhpcy5iLHRoaXMuYS5rKEMueEIuRyhh
-LDUpKSl9LAokUzoxNn0KVy5JNC5wcm90b3R5cGU9ewpQOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz1Q
-LkxzKHQuTikKZm9yKHM9dGhpcy5hLmNsYXNzTmFtZS5zcGxpdCgiICIpLHI9cy5sZW5ndGgscT0wO3E8
-cjsrK3Epe3A9Si5UMChzW3FdKQppZihwLmxlbmd0aCE9PTApby5pKDAscCl9cmV0dXJuIG99LApYOmZ1
-bmN0aW9uKGEpe3RoaXMuYS5jbGFzc05hbWU9dC5DLmEoYSkuSCgwLCIgIil9LApnQTpmdW5jdGlvbihh
-KXtyZXR1cm4gdGhpcy5hLmNsYXNzTGlzdC5sZW5ndGh9LApWMTpmdW5jdGlvbihhKXt0aGlzLmEuY2xh
-c3NOYW1lPSIifSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmEuY2xhc3NMaXN0LmNvbnRhaW5z
-KGIpCnJldHVybiBzfSwKaTpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYS5jbGFzc0xpc3Qscj1zLmNv
-bnRhaW5zKGIpCnMuYWRkKGIpCnJldHVybiFyfSwKUjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYS5j
-bGFzc0xpc3Qscj1zLmNvbnRhaW5zKGIpCnMucmVtb3ZlKGIpCnJldHVybiByfSwKRlY6ZnVuY3Rpb24o
-YSxiKXtXLlROKHRoaXMuYSx0LlEuYShiKSl9fQpXLkZrLnByb3RvdHlwZT17fQpXLlJPLnByb3RvdHlw
-ZT17fQpXLmV1LnByb3RvdHlwZT17fQpXLnhDLnByb3RvdHlwZT17fQpXLnZOLnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodC5CLmEoYSkpfSwKJFM6Mjh9ClcuSlEucHJvdG90
-eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoJC5vci5hPT09MCl7Zm9yKHM9MDtzPDI2MjsrK3Mp
-JC5vci5ZKDAsQy5jbVtzXSxXLnBTKCkpCmZvcihzPTA7czwxMjsrK3MpJC5vci5ZKDAsQy5CSVtzXSxX
-LlY0KCkpfX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiAkLkFOKCkudGcoMCxXLnJTKGEpKX0sCkViOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgcz0kLm9yLnEoMCxILkVqKFcuclMoYSkpKyI6OiIrYikKaWYocz09bnVs
-bClzPSQub3IucSgwLCIqOjoiK2IpCmlmKHM9PW51bGwpcmV0dXJuITEKcmV0dXJuIEgueTgocy4kNChh
-LGIsYyx0aGlzKSl9LAokaWtGOjF9ClcuR20ucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVy
-biBuZXcgVy5XOShhLHRoaXMuZ0EoYSksSC56KGEpLkMoIlc5PEdtLkU+IikpfX0KVy52RC5wcm90b3R5
-cGU9ewppMDpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuVXYoYSkpfSwKRWI6
-ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBDLk5tLlZyKHRoaXMuYSxuZXcgVy5FZyhhLGIsYykpfSwKJGlr
-RjoxfQpXLlV2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0LmUuYShhKS5pMCh0aGlz
-LmEpfSwKJFM6MTd9ClcuRWcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuZS5hKGEp
-LkViKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjE3fQpXLm02LnByb3RvdHlwZT17CkNZOmZ1bmN0
-aW9uKGEsYixjLGQpe3ZhciBzLHIscQp0aGlzLmEuRlYoMCxjKQpzPWIuZXYoMCxuZXcgVy5FbygpKQpy
-PWIuZXYoMCxuZXcgVy5XaygpKQp0aGlzLmIuRlYoMCxzKQpxPXRoaXMuYwpxLkZWKDAsQy54RCkKcS5G
-VigwLHIpfSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS50ZygwLFcuclMoYSkpfSwKRWI6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciBzPXRoaXMscj1XLnJTKGEpLHE9cy5jCmlmKHEudGcoMCxILkVqKHIpKyI6
-OiIrYikpcmV0dXJuIHMuZC5EdChjKQplbHNlIGlmKHEudGcoMCwiKjo6IitiKSlyZXR1cm4gcy5kLkR0
-KGMpCmVsc2V7cT1zLmIKaWYocS50ZygwLEguRWoocikrIjo6IitiKSlyZXR1cm4hMAplbHNlIGlmKHEu
-dGcoMCwiKjo6IitiKSlyZXR1cm4hMAplbHNlIGlmKHEudGcoMCxILkVqKHIpKyI6OioiKSlyZXR1cm4h
-MAplbHNlIGlmKHEudGcoMCwiKjo6KiIpKXJldHVybiEwfXJldHVybiExfSwKJGlrRjoxfQpXLkVvLnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiFDLk5tLnRnKEMuQkksSC5oKGEpKX0sCiRTOjZ9
-ClcuV2sucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0udGcoQy5CSSxILmgoYSkp
-fSwKJFM6Nn0KVy5jdC5wcm90b3R5cGU9ewpFYjpmdW5jdGlvbihhLGIsYyl7aWYodGhpcy5qRihhLGIs
-YykpcmV0dXJuITAKaWYoYj09PSJ0ZW1wbGF0ZSImJmM9PT0iIilyZXR1cm4hMAppZihhLmdldEF0dHJp
-YnV0ZSgidGVtcGxhdGUiKT09PSIiKXJldHVybiB0aGlzLmUudGcoMCxiKQpyZXR1cm4hMX19ClcuSUEu
-cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIlRFTVBMQVRFOjoiK0guRWooSC5oKGEpKX0s
-CiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHMKaWYodC5ldy5iKGEpKXJl
-dHVybiExCnM9dC5nNy5iKGEpCmlmKHMmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0dXJuITEK
-aWYocylyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09ImlzInx8Qy54
-Qi5uKGIsIm9uIikpcmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9LAokaWtGOjF9ClcuVzkucHJvdG90
-eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzPXRoaXMscj1zLmMrMSxxPXMuYgppZihyPHEpe3Muc3AoSi54
-OShzLmEscikpCnMuYz1yCnJldHVybiEwfXMuc3AobnVsbCkKcy5jPXEKcmV0dXJuITF9LApnbDpmdW5j
-dGlvbigpe3JldHVybiB0aGlzLmR9LApzcDpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuQygiMT8i
-KS5hKGEpfSwKJGlBbjoxfQpXLmRXLnByb3RvdHlwZT17CmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gVy5I
-SCh0aGlzLmEubG9jYXRpb24pfSwKJGlEMDoxLAokaXY2OjF9ClcuRmIucHJvdG90eXBlPXt9ClcubWsu
-cHJvdG90eXBlPXskaXkwOjF9ClcuS28ucHJvdG90eXBlPXsKUG46ZnVuY3Rpb24oYSl7dmFyIHM9dGhp
-cyxyPW5ldyBXLmZtKHMpCnMuYj0hMQpyLiQyKGEsbnVsbCkKZm9yKDtzLmI7KXtzLmI9ITEKci4kMihh
-LG51bGwpfX0sCkVQOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcy5iPSEwCmlmKGIhPW51bGw/YiE9PWEu
-cGFyZW50Tm9kZTpzKUouTHQoYSkKZWxzZSBiLnJlbW92ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxi
-KXt2YXIgcyxyLHEscCxvLG49ITAsbT1udWxsLGw9bnVsbAp0cnl7bT1KLmlnKGEpCmw9bS5hLmdldEF0
-dHJpYnV0ZSgiaXMiKQp0LmguYShhKQpzPWZ1bmN0aW9uKGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3Rh
-bmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4gdHJ1ZQppZihjLmlkPT0nbGFzdENoaWxkJ3x8Yy5uYW1l
-PT0nbGFzdENoaWxkJ3x8Yy5pZD09J3ByZXZpb3VzU2libGluZyd8fGMubmFtZT09J3ByZXZpb3VzU2li
-bGluZyd8fGMuaWQ9PSdjaGlsZHJlbid8fGMubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZQp2YXIg
-az1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQmJmMubGFzdENoaWxkIT09a1trLmxlbmd0aC0xXSly
-ZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEoYy5jaGlsZHJlbiBpbnN0YW5jZW9mIEhUTUxDb2xs
-ZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2YgTm9kZUxpc3QpKXJldHVybiB0cnVlCnZhciBqPTAK
-aWYoYy5jaGlsZHJlbilqPWMuY2hpbGRyZW4ubGVuZ3RoCmZvcih2YXIgaT0wO2k8ajtpKyspe3ZhciBo
-PWMuY2hpbGRyZW5baV0KaWYoaC5pZD09J2F0dHJpYnV0ZXMnfHxoLm5hbWU9PSdhdHRyaWJ1dGVzJ3x8
-aC5pZD09J2xhc3RDaGlsZCd8fGgubmFtZT09J2xhc3RDaGlsZCd8fGguaWQ9PSdwcmV2aW91c1NpYmxp
-bmcnfHxoLm5hbWU9PSdwcmV2aW91c1NpYmxpbmcnfHxoLmlkPT0nY2hpbGRyZW4nfHxoLm5hbWU9PSdj
-aGlsZHJlbicpcmV0dXJuIHRydWV9cmV0dXJuIGZhbHNlfShhKQpuPUgub1Qocyk/ITA6IShhLmF0dHJp
-YnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApfWNhdGNoKHApe0guUnUocCl9cj0iZWxlbWVudCB1
-bnByaW50YWJsZSIKdHJ5e3I9Si5qKGEpfWNhdGNoKHApe0guUnUocCl9dHJ5e3E9Vy5yUyhhKQp0aGlz
-LmtSKHQuaC5hKGEpLGIsbixyLHEsdC5mLmEobSksSC5rKGwpKX1jYXRjaChwKXtpZihILlJ1KHApIGlu
-c3RhbmNlb2YgUC51KXRocm93IHAKZWxzZXt0aGlzLkVQKGEsYikKd2luZG93Cm89IlJlbW92aW5nIGNv
-cnJ1cHRlZCBlbGVtZW50ICIrSC5FaihyKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2lu
-ZG93LmNvbnNvbGUud2FybihvKX19fSwKa1I6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHMscixx
-LHAsbyxuLG09dGhpcwppZihjKXttLkVQKGEsYikKd2luZG93CnM9IlJlbW92aW5nIGVsZW1lbnQgZHVl
-IHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9uIDwiK2QrIj4iCmlmKHR5cGVvZiBjb25zb2xlIT0idW5k
-ZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHMpCnJldHVybn1pZighbS5hLmkwKGEpKXttLkVQKGEs
-YikKd2luZG93CnM9IlJlbW92aW5nIGRpc2FsbG93ZWQgZWxlbWVudCA8IitILkVqKGUpKyI+IGZyb20g
-IitILkVqKGIpCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJu
-KHMpCnJldHVybn1pZihnIT1udWxsKWlmKCFtLmEuRWIoYSwiaXMiLGcpKXttLkVQKGEsYikKd2luZG93
-CnM9IlJlbW92aW5nIGRpc2FsbG93ZWQgdHlwZSBleHRlbnNpb24gPCIrSC5FaihlKSsnIGlzPSInK2cr
-JyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihzKQpy
-ZXR1cm59cz1mLmdWKCkKcj1ILlZNKHMuc2xpY2UoMCksSC50NihzKS5DKCJqZDwxPiIpKQpmb3IocT1m
-LmdWKCkubGVuZ3RoLTEscz1mLmE7cT49MDstLXEpe2lmKHE+PXIubGVuZ3RoKXJldHVybiBILk9IKHIs
-cSkKcD1yW3FdCm89bS5hCm49Si5jSChwKQpILmgocCkKaWYoIW8uRWIoYSxuLHMuZ2V0QXR0cmlidXRl
-KHApKSl7d2luZG93Cm89IlJlbW92aW5nIGRpc2FsbG93ZWQgYXR0cmlidXRlIDwiK0guRWooZSkrIiAi
-K3ArJz0iJytILkVqKHMuZ2V0QXR0cmlidXRlKHApKSsnIj4nCmlmKHR5cGVvZiBjb25zb2xlIT0idW5k
-ZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKG8pCnMucmVtb3ZlQXR0cmlidXRlKHApfX1pZih0LmFX
-LmIoYSkpe3M9YS5jb250ZW50CnMudG9TdHJpbmcKbS5QbihzKX19LAokaW9uOjF9ClcuZm0ucHJvdG90
-eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzLmEKc3dpdGNoKGEubm9k
-ZVR5cGUpe2Nhc2UgMTptLkk0KGEsYikKYnJlYWsKY2FzZSA4OmNhc2UgMTE6Y2FzZSAzOmNhc2UgNDpi
-cmVhawpkZWZhdWx0Om0uRVAoYSxiKX1zPWEubGFzdENoaWxkCmZvcihxPXQuQTtudWxsIT1zOyl7cj1u
-dWxsCnRyeXtyPXMucHJldmlvdXNTaWJsaW5nCmlmKHIhPW51bGwpe3A9ci5uZXh0U2libGluZwpvPXMK
-bz1wPT1udWxsP28hPW51bGw6cCE9PW8KcD1vfWVsc2UgcD0hMQppZihwKXtwPVAuUFYoIkNvcnJ1cHQg
-SFRNTCIpCnRocm93IEguYihwKX19Y2F0Y2gobil7SC5SdShuKQpwPXEuYShzKQptLmI9ITAKbz1wLnBh
-cmVudE5vZGUKbz1hPT1udWxsP28hPW51bGw6YSE9PW8KaWYobyl7bz1wLnBhcmVudE5vZGUKaWYobyE9
-bnVsbClvLnJlbW92ZUNoaWxkKHApfWVsc2UgYS5yZW1vdmVDaGlsZChwKQpzPW51bGwKcj1hLmxhc3RD
-aGlsZH1pZihzIT1udWxsKXRoaXMuJDIocyxhKQpzPXJ9fSwKJFM6MzF9ClcuTGUucHJvdG90eXBlPXt9
-ClcuSzcucHJvdG90eXBlPXt9ClcuckIucHJvdG90eXBlPXt9ClcuWFcucHJvdG90eXBlPXt9Clcub2Eu
-cHJvdG90eXBlPXt9ClAuaUoucHJvdG90eXBlPXsKVkg6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmEs
-cT1yLmxlbmd0aApmb3Iocz0wO3M8cTsrK3MpaWYocltzXT09PWEpcmV0dXJuIHMKQy5ObS5pKHIsYSkK
-Qy5ObS5pKHRoaXMuYixudWxsKQpyZXR1cm4gcX0sClB2OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPXRo
-aXMsbz17fQppZihhPT1udWxsKXJldHVybiBhCmlmKEgubChhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09
-Im51bWJlciIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGEgaW5zdGFu
-Y2VvZiBQLmlQKXJldHVybiBuZXcgRGF0ZShhLmEpCmlmKHQuZnYuYihhKSl0aHJvdyBILmIoUC5TWSgi
-c3RydWN0dXJlZCBjbG9uZSBvZiBSZWdFeHAiKSkKaWYodC5jOC5iKGEpKXJldHVybiBhCmlmKHQudy5i
-KGEpKXJldHVybiBhCmlmKHQuSS5iKGEpKXJldHVybiBhCnM9dC5kRS5iKGEpfHwhMQppZihzKXJldHVy
-biBhCmlmKHQuZi5iKGEpKXtyPXAuVkgoYSkKcz1wLmIKaWYocj49cy5sZW5ndGgpcmV0dXJuIEguT0go
-cyxyKQpxPW8uYT1zW3JdCmlmKHEhPW51bGwpcmV0dXJuIHEKcT17fQpvLmE9cQpDLk5tLlkocyxyLHEp
-CmEuSygwLG5ldyBQLmpnKG8scCkpCnJldHVybiBvLmF9aWYodC5iLmIoYSkpe3I9cC5WSChhKQpvPXAu
-YgppZihyPj1vLmxlbmd0aClyZXR1cm4gSC5PSChvLHIpCnE9b1tyXQppZihxIT1udWxsKXJldHVybiBx
-CnJldHVybiBwLmVrKGEscil9aWYodC5lSC5iKGEpKXtyPXAuVkgoYSkKcz1wLmIKaWYocj49cy5sZW5n
-dGgpcmV0dXJuIEguT0gocyxyKQpxPW8uYj1zW3JdCmlmKHEhPW51bGwpcmV0dXJuIHEKcT17fQpvLmI9
-cQpDLk5tLlkocyxyLHEpCnAuaW0oYSxuZXcgUC5UYShvLHApKQpyZXR1cm4gby5ifXRocm93IEguYihQ
-LlNZKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIG90aGVyIHR5cGUiKSl9LAplazpmdW5jdGlvbihhLGIpe3Zh
-ciBzLHI9Si5VNihhKSxxPXIuZ0EoYSkscD1uZXcgQXJyYXkocSkKQy5ObS5ZKHRoaXMuYixiLHApCmZv
-cihzPTA7czxxOysrcylDLk5tLlkocCxzLHRoaXMuUHYoci5xKGEscykpKQpyZXR1cm4gcH19ClAuamcu
-cHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuYVthXT10aGlzLmIuUHYoYil9LAokUzo3
-fQpQLlRhLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmJbYV09dGhpcy5iLlB2KGIp
-fSwKJFM6N30KUC5CZi5wcm90b3R5cGU9ewppbTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwCnQuYjgu
-YShiKQpmb3Iocz1PYmplY3Qua2V5cyhhKSxyPXMubGVuZ3RoLHE9MDtxPHI7KytxKXtwPXNbcV0KYi4k
-MihwLGFbcF0pfX19ClAuQXMucHJvdG90eXBlPXsKVDpmdW5jdGlvbihhKXt2YXIgcwpILmgoYSkKcz0k
-LmhHKCkuYgppZih0eXBlb2YgYSE9InN0cmluZyIpSC52aChILnRMKGEpKQppZihzLnRlc3QoYSkpcmV0
-dXJuIGEKdGhyb3cgSC5iKFAuTDMoYSwidmFsdWUiLCJOb3QgYSB2YWxpZCBjbGFzcyB0b2tlbiIpKX0s
-Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuUCgpLkgoMCwiICIpfSwKZ2t6OmZ1bmN0aW9uKGEpe3Zh
-ciBzPXRoaXMuUCgpCnJldHVybiBQLnJqKHMscy5yLEguTGgocykuYyl9LApnQTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5QKCkuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dGhpcy5UKGIpCnJldHVybiB0aGlzLlAo
-KS50ZygwLGIpfSwKaTpmdW5jdGlvbihhLGIpe3ZhciBzCnRoaXMuVChiKQpzPXRoaXMuT1MobmV3IFAu
-R0UoYikpCnJldHVybiBILnk4KHM9PW51bGw/ITE6cyl9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHMscgp0
-aGlzLlQoYikKcz10aGlzLlAoKQpyPXMuUigwLGIpCnRoaXMuWChzKQpyZXR1cm4gcn0sCkZWOmZ1bmN0
-aW9uKGEsYil7dGhpcy5PUyhuZXcgUC5ONyh0aGlzLHQuUS5hKGIpKSl9LApWMTpmdW5jdGlvbihhKXt0
-aGlzLk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMscgp0LmJVLmEoYSkKcz10aGlz
-LlAoKQpyPWEuJDEocykKdGhpcy5YKHMpCnJldHVybiByfX0KUC5HRS5wcm90b3R5cGU9ewokMTpmdW5j
-dGlvbihhKXtyZXR1cm4gdC5DLmEoYSkuaSgwLHRoaXMuYSl9LAokUzozM30KUC5ONy5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIscj1ILnQ2KHMpCnJldHVybiB0LkMuYShhKS5GVigw
-LG5ldyBILmxKKHMsci5DKCJxVSgxKSIpLmEodGhpcy5hLmd1TSgpKSxyLkMoImxKPDEscVU+IikpKX0s
-CiRTOjE4fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3QuQy5hKGEpCmlmKGEuYT4wKXth
-LmI9YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5TKCl9cmV0dXJuIG51bGx9LAokUzoxOH0KUC5o
-Ri5wcm90b3R5cGU9eyRpaEY6MX0KUC5QQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0
-LlkuYShhKQpzPWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gYihjLGQsdGhp
-cyxBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9fShQLlI0LGEsITEpClAuRG0o
-cywkLncoKSxhKQpyZXR1cm4gc30sCiRTOjR9ClAubXQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
-cmV0dXJuIG5ldyB0aGlzLmEoYSl9LAokUzo0fQpQLk56LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC5yNyhhKX0sCiRTOjQ0fQpQLlFTLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC5UeihhLHQuYW0pfSwKJFM6MzZ9ClAubnAucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7cmV0dXJuIG5ldyBQLkU0KGEpfSwKJFM6Mzd9ClAuRTQucHJvdG90eXBlPXsKcTpmdW5jdGlv
-bihhLGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIhPSJudW1iZXIiKXRocm93IEguYihQ
-LnhZKCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikpCnJldHVybiBQLmRVKHRoaXMuYVti
-XSl9LApZOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVt
-YmVyIil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQp0aGlz
-LmFbYl09UC53WShjKX0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4g
-YiBpbnN0YW5jZW9mIFAuRTQmJnRoaXMuYT09PWIuYX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHMscgp0cnl7
-cz1TdHJpbmcodGhpcy5hKQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIpCnM9dGhpcy54YigwKQpyZXR1
-cm4gc319LApWNzpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy5hCmlmKGI9PW51bGwpcz1udWxsCmVs
-c2V7cz1ILnQ2KGIpCnM9UC5DSChuZXcgSC5sSihiLHMuQygiQCgxKSIpLmEoUC5pRygpKSxzLkMoImxK
-PDEsQD4iKSksITAsdC56KX1yZXR1cm4gUC5kVShyW2FdLmFwcGx5KHIscykpfSwKZ2lPOmZ1bmN0aW9u
-KGEpe3JldHVybiAwfX0KUC5yNy5wcm90b3R5cGU9e30KUC5Uei5wcm90b3R5cGU9ewpjUDpmdW5jdGlv
-bihhKXt2YXIgcz10aGlzLHI9YTwwfHxhPj1zLmdBKHMpCmlmKHIpdGhyb3cgSC5iKFAuVEUoYSwwLHMu
-Z0EocyksbnVsbCxudWxsKSl9LApxOmZ1bmN0aW9uKGEsYil7aWYoSC5vayhiKSl0aGlzLmNQKGIpCnJl
-dHVybiB0aGlzLiR0aS5jLmEodGhpcy5VcigwLGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuY1Ao
-YikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEubGVuZ3RoCmlmKHR5
-cGVvZiBzPT09Im51bWJlciImJnM+Pj4wPT09cylyZXR1cm4gcwp0aHJvdyBILmIoUC5QVigiQmFkIEpz
-QXJyYXkgbGVuZ3RoIikpfSwKJGliUToxLAokaWNYOjEsCiRpek06MX0KUC5jby5wcm90b3R5cGU9e30K
-UC5iQi5wcm90b3R5cGU9eyRpYkI6MX0KUC5LZS5wcm90b3R5cGU9ewpQOmZ1bmN0aW9uKCl7dmFyIHMs
-cixxLHAsbz10aGlzLmEuZ2V0QXR0cmlidXRlKCJjbGFzcyIpLG49UC5Mcyh0Lk4pCmlmKG89PW51bGwp
-cmV0dXJuIG4KZm9yKHM9by5zcGxpdCgiICIpLHI9cy5sZW5ndGgscT0wO3E8cjsrK3Epe3A9Si5UMChz
-W3FdKQppZihwLmxlbmd0aCE9PTApbi5pKDAscCl9cmV0dXJuIG59LApYOmZ1bmN0aW9uKGEpe3RoaXMu
-YS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLkgoMCwiICIpKX19ClAuZDUucHJvdG90eXBlPXsKZ0Q6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIG5ldyBQLktlKGEpfSwKc2hmOmZ1bmN0aW9uKGEsYil7dGhpcy5ZQyhhLGIp
-fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuCmlmKGQ9PW51bGwpe3M9SC5WTShb
-XSx0LnUpCmQ9bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkKQy5ObS5pKHMsVy5CbCgpKQpD
-Lk5tLmkocyxuZXcgVy5PdygpKX1jPW5ldyBXLktvKGQpCnI9JzxzdmcgdmVyc2lvbj0iMS4xIj4nK0gu
-RWooYikrIjwvc3ZnPiIKcz1kb2N1bWVudApxPXMuYm9keQpxLnRvU3RyaW5nCnA9Qy5SWS5BSChxLHIs
-YykKbz1zLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpwLnRvU3RyaW5nCnM9bmV3IFcuZTcocCkKbj1z
-LmdyOChzKQpmb3IoO3M9bi5maXJzdENoaWxkLHMhPW51bGw7KW8uYXBwZW5kQ2hpbGQocykKcmV0dXJu
-IG99LApuejpmdW5jdGlvbihhLGIsYyxkLGUpe3Rocm93IEguYihQLkw0KCJDYW5ub3QgaW52b2tlIGlu
-c2VydEFkamFjZW50SHRtbCBvbiBTVkcuIikpfSwKZ1ZsOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5l
-dShhLCJjbGljayIsITEsdC5qKX0sCiRpZDU6MX0KTS5INy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEp
-e3JldHVybiB0aGlzLmJ9fQpVLkxMLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJuIFAuRUYo
-WyJub2RlSWQiLHRoaXMuYiwia2luZCIsdGhpcy5hLmFdLHQuWCx0Ll8pfX0KVS5NRC5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdC5mRS5hKGEpLmE9PT10aGlzLmEucSgwLCJraW5kIil9LAok
-UzozOH0KVS5kMi5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89dGhpcyxuPXQu
-WCxtPXQuXyxsPVAuRmwobixtKSxrPW8uYQppZihrIT1udWxsKXtzPUguVk0oW10sdC5HKQpmb3Iocj1r
-Lmxlbmd0aCxxPTA7cTxrLmxlbmd0aDtrLmxlbmd0aD09PXJ8fCgwLEgubGspKGspLCsrcSl7cD1rW3Fd
-CkMuTm0uaShzLFAuRUYoWyJkZXNjcmlwdGlvbiIscC5hLCJocmVmIixwLmJdLG4sbSkpfWwuWSgwLCJl
-ZGl0cyIscyl9bC5ZKDAsImV4cGxhbmF0aW9uIixvLmIpCmwuWSgwLCJsaW5lIixvLmMpCmwuWSgwLCJk
-aXNwbGF5UGF0aCIsby5kKQpsLlkoMCwidXJpUGF0aCIsby5lKQpuPW8uZgppZihuIT1udWxsKXttPUgu
-Vk0oW10sdC5HKQpmb3Ioaz1uLmxlbmd0aCxxPTA7cTxuLmxlbmd0aDtuLmxlbmd0aD09PWt8fCgwLEgu
-bGspKG4pLCsrcSlDLk5tLmkobSxuW3FdLkx0KCkpCmwuWSgwLCJ0cmFjZXMiLG0pfXJldHVybiBsfX0K
-VS5TZS5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3JldHVybiBQLkVGKFsiZGVzY3JpcHRpb24iLHRo
-aXMuYSwiaHJlZiIsdGhpcy5iXSx0LlgsdC5fKX19ClUuTWwucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24o
-KXtyZXR1cm4gUC5FRihbImhyZWYiLHRoaXMuYSwibGluZSIsdGhpcy5iLCJwYXRoIix0aGlzLmNdLHQu
-WCx0Ll8pfX0KVS55RC5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwPUguVk0oW10s
-dC5HKQpmb3Iocz10aGlzLmIscj1zLmxlbmd0aCxxPTA7cTxzLmxlbmd0aDtzLmxlbmd0aD09PXJ8fCgw
-LEgubGspKHMpLCsrcSlDLk5tLmkocCxzW3FdLkx0KCkpCnJldHVybiBQLkVGKFsiZGVzY3JpcHRpb24i
-LHRoaXMuYSwiZW50cmllcyIscF0sdC5YLHQuXyl9fQpVLndiLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9u
-KCl7dmFyIHMscixxLHA9dGhpcyxvPVAuRmwodC5YLHQuXykKby5ZKDAsImRlc2NyaXB0aW9uIixwLmEp
-CnM9cC5iCmlmKHMhPW51bGwpby5ZKDAsImZ1bmN0aW9uIixzKQpzPXAuYwppZihzIT1udWxsKW8uWSgw
-LCJsaW5rIixzLkx0KCkpCnM9cC5kCmlmKHMubGVuZ3RoIT09MCl7cj1ILnQ2KHMpCnE9ci5DKCJsSjwx
-LFowPHFVKixNaCo+Kj4iKQpvLlkoMCwiaGludEFjdGlvbnMiLFAuQ0gobmV3IEgubEoocyxyLkMoIlow
-PHFVKixNaCo+KigxKSIpLmEobmV3IFUuYjAoKSkscSksITAscS5DKCJhTC5FIikpKX1yZXR1cm4gb319
-ClUuYU4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFUubnoodC50LmEoYSkpfSwKJFM6
-Mzl9ClUuYjAucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuYVguYShhKS5MdCgpfSwK
-JFM6NDB9CkIuajgucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1cm4gUC5FRihbImxpbmUiLHRo
-aXMuYSwiZXhwbGFuYXRpb24iLHRoaXMuYiwib2Zmc2V0Iix0aGlzLmNdLHQuWCx0Ll8pfX0KQi5xcC5w
-cm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcyxrPXQuWCxqPVAu
-Rmwoayx0LmRwKQpmb3Iocz1sLmQscz1zLmdQdShzKSxzPXMuZ2t6KHMpLHI9dC5fLHE9dC5HO3MuRigp
-Oyl7cD1zLmdsKCkKbz1wLmEKbj1ILlZNKFtdLHEpCmZvcihwPUouSVQocC5iKTtwLkYoKTspe209cC5n
-bCgpCkMuTm0uaShuLFAuRUYoWyJsaW5lIixtLmEsImV4cGxhbmF0aW9uIixtLmIsIm9mZnNldCIsbS5j
-XSxrLHIpKX1qLlkoMCxvLG4pfXJldHVybiBQLkVGKFsicmVnaW9ucyIsbC5hLCJuYXZpZ2F0aW9uQ29u
-dGVudCIsbC5iLCJzb3VyY2VDb2RlIixsLmMsImVkaXRzIixqXSxrLHIpfX0KVC5tUS5wcm90b3R5cGU9
-e30KTC5lLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtCnQuYUwuYShh
-KQpzPXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpyPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnE9
-TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKTC5HZSgpCmlmKHMhPT0iLyImJnMhPT1KLlQwKGRvY3Vt
-ZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQpKUwuRzcocyxyLHEsITAsbmV3IEwu
-VlcocyxyLHEpKQpwPWRvY3VtZW50Cm89Si5xRihwLnF1ZXJ5U2VsZWN0b3IoIi5hcHBseS1taWdyYXRp
-b24iKSkKbj1vLiR0aQptPW4uQygifigxKT8iKS5hKG5ldyBMLm9aKCkpCnQuWi5hKG51bGwpClcuSkUo
-by5hLG8uYixtLCExLG4uYykKbj1KLnFGKHAucXVlcnlTZWxlY3RvcigiLnJlcnVuLW1pZ3JhdGlvbiIp
-KQptPW4uJHRpClcuSkUobi5hLG4uYixtLkMoIn4oMSk/IikuYShuZXcgTC5IaSgpKSwhMSxtLmMpCm09
-Si5xRihwLnF1ZXJ5U2VsZWN0b3IoIi5yZXBvcnQtcHJvYmxlbSIpKQpuPW0uJHRpClcuSkUobS5hLG0u
-YixuLkMoIn4oMSk/IikuYShuZXcgTC5CVCgpKSwhMSxuLmMpCnA9Si5xRihwLnF1ZXJ5U2VsZWN0b3Io
-Ii5wb3B1cC1wYW5lIC5jbG9zZSIpKQpuPXAuJHRpClcuSkUocC5hLHAuYixuLkMoIn4oMSk/IikuYShu
-ZXcgTC5QWSgpKSwhMSxuLmMpfSwKJFM6MTl9CkwuVlcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtM
-LkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjB9Ckwub1oucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHMscixxLHAKdC5PLmEoYSkKaWYoSC5vVChDLm9sLnVzKHdpbmRvdywiVGhpcyB3aWxs
-IGFwcGx5IHRoZSBjaGFuZ2VzIHlvdSd2ZSBwcmV2aWV3ZWQgdG8geW91ciB3b3JraW5nIGRpcmVjdG9y
-eS4gSXQgaXMgcmVjb21tZW5kZWQgeW91IGNvbW1pdCBhbnkgY2hhbmdlcyB5b3UgbWFkZSBiZWZvcmUg
-ZG9pbmcgdGhpcy4iKSkpe3M9TC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIsbnVsbCkuVzcobmV3IEwuanIo
-KSx0LlApCnI9bmV3IEwucWwoKQp0LmI3LmEobnVsbCkKcT1zLiR0aQpwPSQuWDMKaWYocCE9PUMuTlUp
-cj1QLlZIKHIscCkKcy54ZihuZXcgUC5GZShuZXcgUC52cyhwLHEpLDIsbnVsbCxyLHEuQygiQDwxPiIp
-LktxKHEuYykuQygiRmU8MSwyPiIpKSl9fSwKJFM6Mn0KTC5qci5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXt2YXIgcwp0LnQuYShhKQpzPWRvY3VtZW50LmJvZHkKcy5jbGFzc0xpc3QucmVtb3ZlKCJwcm9w
-b3NlZCIpCnMuY2xhc3NMaXN0LmFkZCgiYXBwbGllZCIpfSwKJFM6NDN9CkwucWwucHJvdG90eXBlPXsK
-JDI6ZnVuY3Rpb24oYSxiKXtMLkMyKCJDb3VsZCBub3QgYXBwbHkgbWlncmF0aW9uIixhLGIpfSwKJEM6
-IiQyIiwKJFI6MiwKJFM6N30KTC5IaS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
-cy54bih0Lk8uYShhKSl9LAp4bjpmdW5jdGlvbihhKXt2YXIgcz0wLHI9UC5GWCh0LlApLHE9MSxwLG89
-W10sbixtLGwsawp2YXIgJGFzeW5jJCQxPVAubHooZnVuY3Rpb24oYixjKXtpZihiPT09MSl7cD1jCnM9
-cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6cT0zCmRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFk
-ZCgicmVydW5uaW5nIikKcz02CnJldHVybiBQLmpRKEwudHkoIi9yZXJ1bi1taWdyYXRpb24iLG51bGwp
-LCRhc3luYyQkMSkKY2FzZSA2OndpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKQpvLnB1c2goNSkKcz00CmJy
-ZWFrCmNhc2UgMzpxPTIKaz1wCm49SC5SdShrKQptPUgudHMoaykKTC5DMigiRmFpbGVkIHRvIHJlcnVu
-IG1pZ3JhdGlvbiIsbixtKQpvLnB1c2goNSkKcz00CmJyZWFrCmNhc2UgMjpvPVsxXQpjYXNlIDQ6cT0x
-CmRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgicmVydW5uaW5nIikKcz1vLnBvcCgpCmJyZWFr
-CmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2UgMTpyZXR1cm4gUC5mMyhwLHIpfX0pCnJldHVy
-biBQLkRJKCRhc3luYyQkMSxyKX0sCiRTOjExfQpMLkJULnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3ZhciBzCnQuTy5hKGEpCnM9dC5YCkMub2wuUG8od2luZG93LFAuWGQoImh0dHBzIiwiZ2l0aHViLmNv
-bSIsImRhcnQtbGFuZy9zZGsvaXNzdWVzL25ldyIsUC5FRihbInRpdGxlIiwiQ3VzdG9tZXItcmVwb3J0
-ZWQgaXNzdWUgd2l0aCBOTkJEIG1pZ3JhdGlvbiB0b29sIiwibGFiZWxzIix1LmQsImJvZHkiLCIjIyMj
-IFN0ZXBzIHRvIHJlcHJvZHVjZVxuXG4jIyMjIFdoYXQgZGlkIHlvdSBleHBlY3QgdG8gaGFwcGVuP1xu
-XG4jIyMjIFdoYXQgYWN0dWFsbHkgaGFwcGVuZWQ/XG5cbl9TY3JlZW5zaG90cyBhcmUgYXBwcmVjaWF0
-ZWRfXG5cbioqRGFydCBTREsgdmVyc2lvbioqOiAiK0guRWooZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQo
-InNkay12ZXJzaW9uIikudGV4dENvbnRlbnQpKyJcblxuVGhhbmtzIGZvciBmaWxpbmchXG4iXSxzLHMp
-KS5nbkQoKSwicmVwb3J0LXByb2JsZW0iKX0sCiRTOjJ9CkwuUFkucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7dmFyIHMKdC5PLmEoYSkKcz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIucG9wdXAtcGFuZSIp
-LnN0eWxlCnMuZGlzcGxheT0ibm9uZSIKcmV0dXJuIm5vbmUifSwKJFM6NDV9CkwuTC5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEKdC5hTC5hKGEpCnM9d2luZG93LmxvY2F0aW9uLnBhdGhu
-YW1lCnI9TC5HNih3aW5kb3cubG9jYXRpb24uaHJlZikKcT1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVm
-KQppZihzLmxlbmd0aD4xKUwuRzcocyxyLHEsITEsbnVsbCkKZWxzZXtMLkJFKHMsQi53UigpLCEwKQpM
-LkJYKCImbmJzcDsiLG51bGwpfX0sCiRTOjE5fQpMLld4LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3ZhciBzLHIscSxwPSJjb2xsYXBzZWQiCnQuTy5hKGEpCnM9dGhpcy5hCnI9Si5ZRShzKQpxPXRoaXMu
-YgppZighci5nRChzKS50ZygwLHApKXtyLmdEKHMpLmkoMCxwKQpKLmRSKHEpLmkoMCxwKX1lbHNle3Iu
-Z0QocykuUigwLHApCkouZFIocSkuUigwLHApfX0sCiRTOjJ9CkwuQU8ucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7dmFyIHM9Si5xRih0LmcuYShhKSkscj1zLiR0aSxxPXIuQygifigxKT8iKS5hKG5ldyBM
-LmROKHRoaXMuYSkpCnQuWi5hKG51bGwpClcuSkUocy5hLHMuYixxLCExLHIuYyl9LAokUzozfQpMLmRO
-LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzCnQuTy5hKGEpCnM9ZG9jdW1lbnQucXVlcnlT
-ZWxlY3RvcigidGFibGVbZGF0YS1wYXRoXSIpCnMudG9TdHJpbmcKTC50MihhLHRoaXMuYSxzLmdldEF0
-dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHMpKS5PKCJwYXRoIikpKX0sCiRTOjJ9Ckwu
-SG8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxCnQuZy5hKGEpCnM9Si5xRihhKQpy
-PXMuJHRpCnE9ci5DKCJ+KDEpPyIpLmEobmV3IEwueHooYSx0aGlzLmEpKQp0LlouYShudWxsKQpXLkpF
-KHMuYSxzLmIscSwhMSxyLmMpfSwKJFM6M30KTC54ei5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
-YXIgcwp0Lk8uYShhKQpzPXRoaXMuYQpMLmhYKHRoaXMuYixQLlFBKHMuZ2V0QXR0cmlidXRlKCJkYXRh
-LSIrbmV3IFcuU3kobmV3IFcuaTcocykpLk8oIm9mZnNldCIpKSxudWxsKSxQLlFBKHMuZ2V0QXR0cmli
-dXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcocykpLk8oImxpbmUiKSksbnVsbCkpfSwKJFM6Mn0K
-TC5JQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz1KLnFGKHQuZy5hKGEpKSxyPXMuJHRp
-CnIuQygifigxKT8iKS5hKEwuaVMoKSkKdC5aLmEobnVsbCkKVy5KRShzLmEscy5iLEwuaVMoKSwhMSxy
-LmMpfSwKJFM6M30KTC5mQy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt0LmVRLmEoYSkKdGhpcy5h
-LmFNKDAsdGhpcy5iKX0sCiRTOjQ3fQpMLm5ULnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7TC5Gcih0
-aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLk5ZLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7
-TC5Gcih0aGlzLmEsbnVsbCxudWxsKX0sCiRTOjB9CkwuZVgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
-YSl7dC5nLmEoYSkKJC56QigpLnRvU3RyaW5nCnQuZEguYSgkLm93KCkucSgwLCJobGpzIikpLlY3KCJo
-aWdobGlnaHRCbG9jayIsW2FdKX0sCiRTOjN9CkwuRUUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
-dmFyIHMscgp0Lk8uYShhKS5wcmV2ZW50RGVmYXVsdCgpCnM9dGhpcy5hCnI9dGhpcy5iCkwuYWYod2lu
-ZG93LmxvY2F0aW9uLnBhdGhuYW1lLHMsciwhMCxuZXcgTC5RTChzLHIpKQpMLmhYKHRoaXMuYyxzLHIp
-fSwKJFM6Mn0KTC5RTC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9u
-LnBhdGhuYW1lLHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KTC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXt2YXIgcyxyPSJzZWxlY3RlZC1maWxlIgp0LmcuYShhKQphLnRvU3RyaW5nCnM9Si5ZRShhKQpp
-ZihhLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGEpKS5PKCJuYW1lIikpPT09
-dGhpcy5hLmEpcy5nRChhKS5pKDAscikKZWxzZSBzLmdEKGEpLlIoMCxyKX0sCiRTOjN9CkwuVEQucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEwudDIodC5PLmEoYSksITAsbnVsbCl9LAokUzoy
-MH0KTC5BUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5QTCh0Lk8uYShhKSl9
-LApQTDpmdW5jdGlvbihhKXt2YXIgcz0wLHI9UC5GWCh0LlApLHE9MSxwLG89W10sbj10aGlzLG0sbCxr
-LGosaSxoCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0xKXtwPWMKcz1xfXdo
-aWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDpxPTMKaj10LlgKcz02CnJldHVybiBQLmpRKEwudHkoTC5R
-NCgiL2FwcGx5LWhpbnQiLFAuRmwoaixqKSksbi5hLkx0KCkpLCRhc3luYyQkMSkKY2FzZSA2Omo9bi5i
-Cm09TC5VcyhqLmEpCkwuRzcobSxudWxsLGouYiwhMSxudWxsKQpkb2N1bWVudC5ib2R5LmNsYXNzTGlz
-dC5hZGQoIm5lZWRzLXJlcnVuIikKcT0xCnM9NQpicmVhawpjYXNlIDM6cT0yCmg9cApsPUguUnUoaCkK
-az1ILnRzKGgpCkwuQzIoIkNvdWxkIG5vdCBhcHBseSBoaW50IixsLGspCnM9NQpicmVhawpjYXNlIDI6
+ciBzPWEgaW5zdGFuY2VvZiBILlRwP2EuX19wcm90b19fLl9fcHJvdG9fXy5jb25zdHJ1Y3RvcjpiLHI9
+SC5haSh2LnR5cGVVbml2ZXJzZSxzLm5hbWUpCmIuJGNjYWNoZT1yCnJldHVybiByfSwKQnA6ZnVuY3Rp
+b24oYSl7dmFyIHMscixxCkgudVAoYSkKcz12LnR5cGVzCnI9c1thXQppZih0eXBlb2Ygcj09InN0cmlu
+ZyIpe3E9SC5FKHYudHlwZVVuaXZlcnNlLHIsITEpCnNbYV09cQpyZXR1cm4gcX1yZXR1cm4gcn0sCkpK
+OmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzLHA9dC5LCmlmKHE9PT1wKXJldHVybiBILlJFKHEsYSxI
+LmtlKQppZighSC5BOChxKSlpZighKHE9PT10Ll8pKXA9cT09PXAKZWxzZSBwPSEwCmVsc2UgcD0hMApp
+ZihwKXJldHVybiBILlJFKHEsYSxILkl3KQpwPXEueQpzPXA9PT02P3EuejpxCmlmKHM9PT10LlMpcj1I
+Lm9rCmVsc2UgaWYocz09PXQuZ1J8fHM9PT10LmRpKXI9SC5LSAplbHNlIGlmKHM9PT10Lk4pcj1ILk1N
+CmVsc2Ugcj1zPT09dC55P0gubDpudWxsCmlmKHIhPW51bGwpcmV0dXJuIEguUkUocSxhLHIpCmlmKHMu
+eT09PTkpe3A9cy56CmlmKHMuUS5ldmVyeShILmNjKSl7cS5yPSIkaSIrcApyZXR1cm4gSC5SRShxLGEs
+SC50NCl9fWVsc2UgaWYocD09PTcpcmV0dXJuIEguUkUocSxhLEguQVEpCnJldHVybiBILlJFKHEsYSxI
+LllPKX0sClJFOmZ1bmN0aW9uKGEsYixjKXthLmI9YwpyZXR1cm4gYS5iKGIpfSwKQXU6ZnVuY3Rpb24o
+YSl7dmFyIHMscixxPXRoaXMKaWYoIUguQTgocSkpaWYoIShxPT09dC5fKSlzPXE9PT10LksKZWxzZSBz
+PSEwCmVsc2Ugcz0hMAppZihzKXI9SC5obgplbHNlIGlmKHE9PT10Lkspcj1ILlRpCmVsc2Ugcj1ILmw0
+CnEuYT1yCnJldHVybiBxLmEoYSl9LApRajpmdW5jdGlvbihhKXt2YXIgcyxyPWEueQppZighSC5BOChh
+KSlpZighKGE9PT10Ll8pKXM9YT09PXQuSwplbHNlIHM9ITAKZWxzZSBzPSEwCnJldHVybiBzfHxhPT09
+dC5jRnx8cj09PTd8fGE9PT10LlB8fGE9PT10LlR9LApZTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzCmlm
+KGE9PW51bGwpcmV0dXJuIEguUWoocykKcmV0dXJuIEguV2Uodi50eXBlVW5pdmVyc2UsSC5VZShhLHMp
+LG51bGwscyxudWxsKX0sCkFROmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuITAKcmV0dXJuIHRo
+aXMuei5iKGEpfSwKdDQ6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzCmlmKGE9PW51bGwpcmV0dXJuIEgu
+UWoocikKcz1yLnIKaWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuISFhW3NdCnJldHVybiEhSi5pYShh
+KVtzXX0sCk96OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKaWYoYT09bnVsbClyZXR1cm4gYQplbHNlIGlm
+KHMuYihhKSlyZXR1cm4gYQpILm00KGEscyl9LApsNDpmdW5jdGlvbihhKXt2YXIgcz10aGlzCmlmKGE9
+PW51bGwpcmV0dXJuIGEKZWxzZSBpZihzLmIoYSkpcmV0dXJuIGEKSC5tNChhLHMpfSwKbTQ6ZnVuY3Rp
+b24oYSxiKXt0aHJvdyBILmIoSC5aYyhILldLKGEsSC5VZShhLGIpLEguZG0oYixudWxsKSkpKX0sCkRo
+OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzPW51bGwKaWYoSC5XZSh2LnR5cGVVbml2ZXJzZSxhLHMsYixz
+KSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYygiVGhlIHR5cGUgYXJndW1lbnQgJyIrSC5FaihILmRtKGEs
+cykpKyInIGlzIG5vdCBhIHN1YnR5cGUgb2YgdGhlIHR5cGUgdmFyaWFibGUgYm91bmQgJyIrSC5FaihI
+LmRtKGIscykpKyInIG9mIHR5cGUgdmFyaWFibGUgJyIrSC5FaihjKSsiJyBpbiAnIitILkVqKGQpKyIn
+LiIpKX0sCldLOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1QLmhsKGEpLHI9SC5kbShiPT1udWxsP0gueihh
+KTpiLG51bGwpCnJldHVybiBzKyI6IHR5cGUgJyIrSC5FaihyKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9m
+IHR5cGUgJyIrSC5FaihjKSsiJyJ9LApaYzpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguaU0oIlR5cGVF
+cnJvcjogIithKX0sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguaU0oIlR5cGVFcnJvcjogIitI
+LldLKGEsbnVsbCxiKSl9LAprZTpmdW5jdGlvbihhKXtyZXR1cm4gYSE9bnVsbH0sClRpOmZ1bmN0aW9u
+KGEpe3JldHVybiBhfSwKSXc6ZnVuY3Rpb24oYSl7cmV0dXJuITB9LApobjpmdW5jdGlvbihhKXtyZXR1
+cm4gYX0sCmw6ZnVuY3Rpb24oYSl7cmV0dXJuITA9PT1hfHwhMT09PWF9LApwODpmdW5jdGlvbihhKXtp
+ZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJldHVybiExCnRocm93IEguYihILnEoYSwiYm9vbCIp
+KX0sCnk4OmZ1bmN0aW9uKGEpe2lmKCEwPT09YSlyZXR1cm4hMAppZighMT09PWEpcmV0dXJuITEKaWYo
+YT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImJvb2wiKSl9LApkcDpmdW5jdGlvbihhKXtp
+ZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJldHVybiExCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhy
+b3cgSC5iKEgucShhLCJib29sPyIpKX0sCkZHOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVy
+IilyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImRvdWJsZSIpKX0sCkdIOmZ1bmN0aW9uKGEpe2lmKHR5
+cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEo
+YSwiZG91YmxlIikpfSwKUWs6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBh
+CmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJkb3VibGU/IikpfSwKb2s6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWF9LApJWjpmdW5j
+dGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBhCnRo
+cm93IEguYihILnEoYSwiaW50IikpfSwKdVA6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIi
+JiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihI
+LnEoYSwiaW50IikpfSwKVWM6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZs
+b29yKGEpPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiaW50
+PyIpKX0sCktIOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJlciJ9LAp6NTpmdW5jdGlv
+bihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJudW0iKSl9
+LApXMTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbCly
+ZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bSIpKX0sCmNVOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBh
+PT0ibnVtYmVyIilyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVt
+PyIpKX0sCk1NOmZ1bmN0aW9uKGEpe3JldHVybiB0eXBlb2YgYT09InN0cmluZyJ9LApCdDpmdW5jdGlv
+bihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJTdHJpbmci
+KSl9LApoOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZihhPT1udWxs
+KXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3RyaW5nIikpfSwKazpmdW5jdGlvbihhKXtpZih0eXBl
+b2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEs
+IlN0cmluZz8iKSl9LAppbzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQpmb3Iocz0iIixyPSIiLHE9MDtx
+PGEubGVuZ3RoOysrcSxyPSIsICIpcys9Qy54Qi5oKHIsSC5kbShhW3FdLGIpKQpyZXR1cm4gc30sCmJJ
+OmZ1bmN0aW9uKGE1LGE2LGE3KXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIs
+YSxhMCxhMSxhMixhMyxhND0iLCAiCmlmKGE3IT1udWxsKXtzPWE3Lmxlbmd0aAppZihhNj09bnVsbCl7
+YTY9SC5WTShbXSx0LnMpCnI9bnVsbH1lbHNlIHI9YTYubGVuZ3RoCnE9YTYubGVuZ3RoCmZvcihwPXM7
+cD4wOy0tcClDLk5tLmkoYTYsIlQiKyhxK3ApKQpmb3Iobz10Llcsbj10Ll8sbT10LkssbD0iPCIsaz0i
+IixwPTA7cDxzOysrcCxrPWE0KXtsKz1rCmo9YTYubGVuZ3RoCmk9ai0xLXAKaWYoaTwwKXJldHVybiBI
+Lk9IKGE2LGkpCmw9Qy54Qi5oKGwsYTZbaV0pCmg9YTdbcF0KZz1oLnkKaWYoIShnPT09Mnx8Zz09PTN8
+fGc9PT00fHxnPT09NXx8aD09PW8pKWlmKCEoaD09PW4pKWo9aD09PW0KZWxzZSBqPSEwCmVsc2Ugaj0h
+MAppZighailsKz1DLnhCLmgoIiBleHRlbmRzICIsSC5kbShoLGE2KSl9bCs9Ij4ifWVsc2V7bD0iIgpy
+PW51bGx9bz1hNS56CmY9YTUuUQplPWYuYQpkPWUubGVuZ3RoCmM9Zi5iCmI9Yy5sZW5ndGgKYT1mLmMK
+YTA9YS5sZW5ndGgKYTE9SC5kbShvLGE2KQpmb3IoYTI9IiIsYTM9IiIscD0wO3A8ZDsrK3AsYTM9YTQp
+YTIrPUMueEIuaChhMyxILmRtKGVbcF0sYTYpKQppZihiPjApe2EyKz1hMysiWyIKZm9yKGEzPSIiLHA9
+MDtwPGI7KytwLGEzPWE0KWEyKz1DLnhCLmgoYTMsSC5kbShjW3BdLGE2KSkKYTIrPSJdIn1pZihhMD4w
+KXthMis9YTMrInsiCmZvcihhMz0iIixwPTA7cDxhMDtwKz0zLGEzPWE0KXthMis9YTMKaWYoYVtwKzFd
+KWEyKz0icmVxdWlyZWQgIgphMis9Si5iYihILmRtKGFbcCsyXSxhNiksIiAiKSthW3BdfWEyKz0ifSJ9
+aWYociE9bnVsbCl7YTYudG9TdHJpbmcKYTYubGVuZ3RoPXJ9cmV0dXJuIGwrIigiK2EyKyIpID0+ICIr
+SC5FaihhMSl9LApkbTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtLGw9YS55CmlmKGw9PT01
+KXJldHVybiJlcmFzZWQiCmlmKGw9PT0yKXJldHVybiJkeW5hbWljIgppZihsPT09MylyZXR1cm4idm9p
+ZCIKaWYobD09PTEpcmV0dXJuIk5ldmVyIgppZihsPT09NClyZXR1cm4iYW55IgppZihsPT09Nil7cz1I
+LmRtKGEueixiKQpyZXR1cm4gc31pZihsPT09Nyl7cj1hLnoKcz1ILmRtKHIsYikKcT1yLnkKcmV0dXJu
+IEouYmIocT09PTExfHxxPT09MTI/Qy54Qi5oKCIoIixzKSsiKSI6cywiPyIpfWlmKGw9PT04KXJldHVy
+biJGdXR1cmVPcjwiK0guRWooSC5kbShhLnosYikpKyI+IgppZihsPT09OSl7cD1ILm8zKGEueikKbz1h
+LlEKcmV0dXJuIG8ubGVuZ3RoIT09MD9wKygiPCIrSC5pbyhvLGIpKyI+Iik6cH1pZihsPT09MTEpcmV0
+dXJuIEguYkkoYSxiLG51bGwpCmlmKGw9PT0xMilyZXR1cm4gSC5iSShhLnosYixhLlEpCmlmKGw9PT0x
+Myl7Yi50b1N0cmluZwpuPWEuegptPWIubGVuZ3RoCm49bS0xLW4KaWYobjwwfHxuPj1tKXJldHVybiBI
+Lk9IKGIsbikKcmV0dXJuIGJbbl19cmV0dXJuIj8ifSwKbzM6ZnVuY3Rpb24oYSl7dmFyIHMscj1ILkpn
+KGEpCmlmKHIhPW51bGwpcmV0dXJuIHIKcz0ibWluaWZpZWQ6IithCnJldHVybiBzfSwKUW86ZnVuY3Rp
+b24oYSxiKXt2YXIgcz1hLnRSW2JdCmZvcig7dHlwZW9mIHM9PSJzdHJpbmciOylzPWEudFJbc10KcmV0
+dXJuIHN9LAphaTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbj1hLmVULG09bltiXQppZihtPT1u
+dWxsKXJldHVybiBILkUoYSxiLCExKQplbHNlIGlmKHR5cGVvZiBtPT0ibnVtYmVyIil7cz1tCnI9SC5t
+KGEsNSwiIyIpCnE9W10KZm9yKHA9MDtwPHM7KytwKXEucHVzaChyKQpvPUguSihhLGIscSkKbltiXT1v
+CnJldHVybiBvfWVsc2UgcmV0dXJuIG19LAp4YjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEudFIs
+Yil9LApGRjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEuZVQsYil9LApFOmZ1bmN0aW9uKGEsYixj
+KXt2YXIgcyxyPWEuZUMscT1yLmdldChiKQppZihxIT1udWxsKXJldHVybiBxCnM9SC5pKEgubyhhLG51
+bGwsYixjKSkKci5zZXQoYixzKQpyZXR1cm4gc30sCmNFOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9
+Yi5jaAppZihxPT1udWxsKXE9Yi5jaD1uZXcgTWFwKCkKcz1xLmdldChjKQppZihzIT1udWxsKXJldHVy
+biBzCnI9SC5pKEgubyhhLGIsYywhMCkpCnEuc2V0KGMscikKcmV0dXJuIHJ9LAp2NTpmdW5jdGlvbihh
+LGIsYyl7dmFyIHMscixxLHA9Yi5jeAppZihwPT1udWxsKXA9Yi5jeD1uZXcgTWFwKCkKcz1jLmN5CnI9
+cC5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgpxPUguYShhLGIsYy55PT09MTA/Yy5ROltjXSkKcC5z
+ZXQocyxxKQpyZXR1cm4gcX0sCkJEOmZ1bmN0aW9uKGEsYil7Yi5hPUguQXUKYi5iPUguSkoKcmV0dXJu
+IGJ9LAptOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHE9YS5lQy5nZXQoYykKaWYocSE9bnVsbClyZXR1
+cm4gcQpzPW5ldyBILkpjKG51bGwsbnVsbCkKcy55PWIKcy5jeT1jCnI9SC5CRChhLHMpCmEuZUMuc2V0
+KGMscikKcmV0dXJuIHJ9LApDOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWIuY3krIioiLHE9YS5lQy5n
+ZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUguWjcoYSxiLHIsYykKYS5lQy5zZXQocixzKQpyZXR1
+cm4gc30sClo3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQppZihkKXtzPWIueQppZighSC5BOChi
+KSlyPWI9PT10LlB8fGI9PT10LlR8fHM9PT03fHxzPT09NgplbHNlIHI9ITAKaWYocilyZXR1cm4gYn1x
+PW5ldyBILkpjKG51bGwsbnVsbCkKcS55PTYKcS56PWIKcS5jeT1jCnJldHVybiBILkJEKGEscSl9LApC
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWIuY3krIj8iLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbCly
+ZXR1cm4gcQpzPUgubGwoYSxiLHIsYykKYS5lQy5zZXQocixzKQpyZXR1cm4gc30sCmxsOmZ1bmN0aW9u
+KGEsYixjLGQpe3ZhciBzLHIscSxwCmlmKGQpe3M9Yi55CmlmKCFILkE4KGIpKWlmKCEoYj09PXQuUHx8
+Yj09PXQuVCkpaWYocyE9PTcpcj1zPT09OCYmSC5sUihiLnopCmVsc2Ugcj0hMAplbHNlIHI9ITAKZWxz
+ZSByPSEwCmlmKHIpcmV0dXJuIGIKZWxzZSBpZihzPT09MXx8Yj09PXQuY0YpcmV0dXJuIHQuUAplbHNl
+IGlmKHM9PT02KXtxPWIuegppZihxLnk9PT04JiZILmxSKHEueikpcmV0dXJuIHEKZWxzZSByZXR1cm4g
+SC5jeihhLGIpfX1wPW5ldyBILkpjKG51bGwsbnVsbCkKcC55PTcKcC56PWIKcC5jeT1jCnJldHVybiBI
+LkJEKGEscCl9LApmOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWIuY3krIi8iLHE9YS5lQy5nZXQocikK
+aWYocSE9bnVsbClyZXR1cm4gcQpzPUguZVYoYSxiLHIsYykKYS5lQy5zZXQocixzKQpyZXR1cm4gc30s
+CmVWOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscQppZihkKXtzPWIueQppZighSC5BOChiKSlpZigh
+KGI9PT10Ll8pKXI9Yj09PXQuSwplbHNlIHI9ITAKZWxzZSByPSEwCmlmKHJ8fGI9PT10LkspcmV0dXJu
+IGIKZWxzZSBpZihzPT09MSlyZXR1cm4gSC5KKGEsImI4IixbYl0pCmVsc2UgaWYoYj09PXQuUHx8Yj09
+PXQuVClyZXR1cm4gdC5iR31xPW5ldyBILkpjKG51bGwsbnVsbCkKcS55PTgKcS56PWIKcS5jeT1jCnJl
+dHVybiBILkJEKGEscSl9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPSIiK2IrIl4iLHA9YS5lQy5n
+ZXQocSkKaWYocCE9bnVsbClyZXR1cm4gcApzPW5ldyBILkpjKG51bGwsbnVsbCkKcy55PTEzCnMuej1i
+CnMuY3k9cQpyPUguQkQoYSxzKQphLmVDLnNldChxLHIpCnJldHVybiByfSwKVXg6ZnVuY3Rpb24oYSl7
+dmFyIHMscixxLHA9YS5sZW5ndGgKZm9yKHM9IiIscj0iIixxPTA7cTxwOysrcSxyPSIsIilzKz1yK2Fb
+cV0uY3kKcmV0dXJuIHN9LApTNDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbT1hLmxlbmd0aApm
+b3Iocz0iIixyPSIiLHE9MDtxPG07cSs9MyxyPSIsIil7cD1hW3FdCm89YVtxKzFdPyIhIjoiOiIKbj1h
+W3ErMl0uY3kKcys9citwK28rbn1yZXR1cm4gc30sCko6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxw
+PWIKaWYoYy5sZW5ndGghPT0wKXArPSI8IitILlV4KGMpKyI+IgpzPWEuZUMuZ2V0KHApCmlmKHMhPW51
+bGwpcmV0dXJuIHMKcj1uZXcgSC5KYyhudWxsLG51bGwpCnIueT05CnIuej1iCnIuUT1jCmlmKGMubGVu
+Z3RoPjApci5jPWNbMF0Kci5jeT1wCnE9SC5CRChhLHIpCmEuZUMuc2V0KHAscSkKcmV0dXJuIHF9LAph
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvLG4KaWYoYi55PT09MTApe3M9Yi56CnI9Yi5RLmNv
+bmNhdChjKX1lbHNle3I9YwpzPWJ9cT1zLmN5KygiOzwiK0guVXgocikrIj4iKQpwPWEuZUMuZ2V0KHEp
+CmlmKHAhPW51bGwpcmV0dXJuIHAKbz1uZXcgSC5KYyhudWxsLG51bGwpCm8ueT0xMApvLno9cwpvLlE9
+cgpvLmN5PXEKbj1ILkJEKGEsbykKYS5lQy5zZXQocSxuKQpyZXR1cm4gbn0sCmQ6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciBzLHIscSxwLG8sbj1iLmN5LG09Yy5hLGw9bS5sZW5ndGgsaz1jLmIsaj1rLmxlbmd0aCxp
+PWMuYyxoPWkubGVuZ3RoLGc9IigiK0guVXgobSkKaWYoaj4wKXtzPWw+MD8iLCI6IiIKcj1ILlV4KGsp
+CmcrPXMrIlsiK3IrIl0ifWlmKGg+MCl7cz1sPjA/IiwiOiIiCnI9SC5TNChpKQpnKz1zKyJ7IityKyJ9
+In1xPW4rKGcrIikiKQpwPWEuZUMuZ2V0KHEpCmlmKHAhPW51bGwpcmV0dXJuIHAKbz1uZXcgSC5KYyhu
+dWxsLG51bGwpCm8ueT0xMQpvLno9YgpvLlE9YwpvLmN5PXEKcj1ILkJEKGEsbykKYS5lQy5zZXQocSxy
+KQpyZXR1cm4gcn0sCkQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscj1iLmN5KygiPCIrSC5VeChjKSsi
+PiIpLHE9YS5lQy5nZXQocikKaWYocSE9bnVsbClyZXR1cm4gcQpzPUguaHcoYSxiLGMscixkKQphLmVD
+LnNldChyLHMpCnJldHVybiBzfSwKaHc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG4s
+bSxsCmlmKGUpe3M9Yy5sZW5ndGgKcj1uZXcgQXJyYXkocykKZm9yKHE9MCxwPTA7cDxzOysrcCl7bz1j
+W3BdCmlmKG8ueT09PTEpe3JbcF09bzsrK3F9fWlmKHE+MCl7bj1ILlBMKGEsYixyLDApCm09SC5iWihh
+LGMsciwwKQpyZXR1cm4gSC5EKGEsbixtLGMhPT1tKX19bD1uZXcgSC5KYyhudWxsLG51bGwpCmwueT0x
+MgpsLno9YgpsLlE9YwpsLmN5PWQKcmV0dXJuIEguQkQoYSxsKX0sCm86ZnVuY3Rpb24oYSxiLGMsZCl7
+cmV0dXJue3U6YSxlOmIscjpjLHM6W10scDowLG46ZH19LAppOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxw
+LG8sbixtLGwsayxqLGksaCxnPWEucixmPWEucwpmb3Iocz1nLmxlbmd0aCxyPTA7cjxzOyl7cT1nLmNo
+YXJDb2RlQXQocikKaWYocT49NDgmJnE8PTU3KXI9SC5BKHIrMSxxLGcsZikKZWxzZSBpZigoKChxfDMy
+KT4+PjApLTk3JjY1NTM1KTwyNnx8cT09PTk1fHxxPT09MzYpcj1ILnQoYSxyLGcsZiwhMSkKZWxzZSBp
+ZihxPT09NDYpcj1ILnQoYSxyLGcsZiwhMCkKZWxzZXsrK3IKc3dpdGNoKHEpe2Nhc2UgNDQ6YnJlYWsK
+Y2FzZSA1ODpmLnB1c2goITEpCmJyZWFrCmNhc2UgMzM6Zi5wdXNoKCEwKQpicmVhawpjYXNlIDU5OmYu
+cHVzaChILksoYS51LGEuZSxmLnBvcCgpKSkKYnJlYWsKY2FzZSA5NDpmLnB1c2goSC5IKGEudSxmLnBv
+cCgpKSkKYnJlYWsKY2FzZSAzNTpmLnB1c2goSC5tKGEudSw1LCIjIikpCmJyZWFrCmNhc2UgNjQ6Zi5w
+dXNoKEgubShhLnUsMiwiQCIpKQpicmVhawpjYXNlIDEyNjpmLnB1c2goSC5tKGEudSwzLCJ+IikpCmJy
+ZWFrCmNhc2UgNjA6Zi5wdXNoKGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgNjI6cD1hLnUKbz1m
+LnNwbGljZShhLnApCkgucihhLnUsYS5lLG8pCmEucD1mLnBvcCgpCm49Zi5wb3AoKQppZih0eXBlb2Yg
+bj09InN0cmluZyIpZi5wdXNoKEguSihwLG4sbykpCmVsc2V7bT1ILksocCxhLmUsbikKc3dpdGNoKG0u
+eSl7Y2FzZSAxMTpmLnB1c2goSC5EKHAsbSxvLGEubikpCmJyZWFrCmRlZmF1bHQ6Zi5wdXNoKEguYShw
+LG0sbykpCmJyZWFrfX1icmVhawpjYXNlIDM4OkguSShhLGYpCmJyZWFrCmNhc2UgNDI6bD1hLnUKZi5w
+dXNoKEguQyhsLEguSyhsLGEuZSxmLnBvcCgpKSxhLm4pKQpicmVhawpjYXNlIDYzOmw9YS51CmYucHVz
+aChILkIobCxILksobCxhLmUsZi5wb3AoKSksYS5uKSkKYnJlYWsKY2FzZSA0NzpsPWEudQpmLnB1c2go
+SC5mKGwsSC5LKGwsYS5lLGYucG9wKCkpLGEubikpCmJyZWFrCmNhc2UgNDA6Zi5wdXNoKGEucCkKYS5w
+PWYubGVuZ3RoCmJyZWFrCmNhc2UgNDE6cD1hLnUKaz1uZXcgSC5HKCkKaj1wLnNFQQppPXAuc0VBCm49
+Zi5wb3AoKQppZih0eXBlb2Ygbj09Im51bWJlciIpc3dpdGNoKG4pe2Nhc2UtMTpqPWYucG9wKCkKYnJl
+YWsKY2FzZS0yOmk9Zi5wb3AoKQpicmVhawpkZWZhdWx0OmYucHVzaChuKQpicmVha31lbHNlIGYucHVz
+aChuKQpvPWYuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUsbykKYS5wPWYucG9wKCkKay5hPW8Kay5iPWoK
+ay5jPWkKZi5wdXNoKEguZChwLEguSyhwLGEuZSxmLnBvcCgpKSxrKSkKYnJlYWsKY2FzZSA5MTpmLnB1
+c2goYS5wKQphLnA9Zi5sZW5ndGgKYnJlYWsKY2FzZSA5MzpvPWYuc3BsaWNlKGEucCkKSC5yKGEudSxh
+LmUsbykKYS5wPWYucG9wKCkKZi5wdXNoKG8pCmYucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zi5wdXNo
+KGEucCkKYS5wPWYubGVuZ3RoCmJyZWFrCmNhc2UgMTI1Om89Zi5zcGxpY2UoYS5wKQpILnkoYS51LGEu
+ZSxvKQphLnA9Zi5wb3AoKQpmLnB1c2gobykKZi5wdXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJh
+ZCBjaGFyYWN0ZXIgIitxfX19aD1mLnBvcCgpCnJldHVybiBILksoYS51LGEuZSxoKX0sCkE6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHMscixxPWItNDgKZm9yKHM9Yy5sZW5ndGg7YTxzOysrYSl7cj1jLmNoYXJD
+b2RlQXQoYSkKaWYoIShyPj00OCYmcjw9NTcpKWJyZWFrCnE9cSoxMCsoci00OCl9ZC5wdXNoKHEpCnJl
+dHVybiBhfSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzLHIscSxwLG8sbixtPWIrMQpmb3Iocz1j
+Lmxlbmd0aDttPHM7KyttKXtyPWMuY2hhckNvZGVBdChtKQppZihyPT09NDYpe2lmKGUpYnJlYWsKZT0h
+MH1lbHNle2lmKCEoKCgocnwzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHI9PT05NXx8cj09PTM2KSlxPXI+
+PTQ4JiZyPD01NwplbHNlIHE9ITAKaWYoIXEpYnJlYWt9fXA9Yy5zdWJzdHJpbmcoYixtKQppZihlKXtz
+PWEudQpvPWEuZQppZihvLnk9PT0xMClvPW8uegpuPUguUW8ocyxvLnopW3BdCmlmKG49PW51bGwpSC52
+KCdObyAiJytwKyciIGluICInK0gubUQobykrJyInKQpkLnB1c2goSC5jRShzLG8sbikpfWVsc2UgZC5w
+dXNoKHApCnJldHVybiBtfSwKSTpmdW5jdGlvbihhLGIpe3ZhciBzPWIucG9wKCkKaWYoMD09PXMpe2Iu
+cHVzaChILm0oYS51LDEsIjAmIikpCnJldHVybn1pZigxPT09cyl7Yi5wdXNoKEgubShhLnUsNCwiMSYi
+KSkKcmV0dXJufXRocm93IEguYihQLmhWKCJVbmV4cGVjdGVkIGV4dGVuZGVkIG9wZXJhdGlvbiAiK0gu
+RWoocykpKX0sCks6ZnVuY3Rpb24oYSxiLGMpe2lmKHR5cGVvZiBjPT0ic3RyaW5nIilyZXR1cm4gSC5K
+KGEsYyxhLnNFQSkKZWxzZSBpZih0eXBlb2YgYz09Im51bWJlciIpcmV0dXJuIEguVFYoYSxiLGMpCmVs
+c2UgcmV0dXJuIGN9LApyOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWMubGVuZ3RoCmZvcihzPTA7czxy
+OysrcyljW3NdPUguSyhhLGIsY1tzXSl9LAp5OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWMubGVuZ3Ro
+CmZvcihzPTI7czxyO3MrPTMpY1tzXT1ILksoYSxiLGNbc10pfSwKVFY6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzLHIscT1iLnkKaWYocT09PTEwKXtpZihjPT09MClyZXR1cm4gYi56CnM9Yi5RCnI9cy5sZW5ndGgK
+aWYoYzw9cilyZXR1cm4gc1tjLTFdCmMtPXIKYj1iLnoKcT1iLnl9ZWxzZSBpZihjPT09MClyZXR1cm4g
+YgppZihxIT09OSl0aHJvdyBILmIoUC5oVigiSW5kZXhlZCBiYXNlIG11c3QgYmUgYW4gaW50ZXJmYWNl
+IHR5cGUiKSkKcz1iLlEKaWYoYzw9cy5sZW5ndGgpcmV0dXJuIHNbYy0xXQp0aHJvdyBILmIoUC5oVigi
+QmFkIGluZGV4ICIrYysiIGZvciAiK2IudygwKSkpfSwKV2U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIg
+cyxyLHEscCxvLG4sbSxsLGssagppZihiPT09ZClyZXR1cm4hMAppZighSC5BOChkKSlpZighKGQ9PT10
+Ll8pKXM9ZD09PXQuSwplbHNlIHM9ITAKZWxzZSBzPSEwCmlmKHMpcmV0dXJuITAKcj1iLnkKaWYocj09
+PTQpcmV0dXJuITAKaWYoSC5BOChiKSlyZXR1cm4hMQppZihiLnkhPT0xKXM9Yj09PXQuUHx8Yj09PXQu
+VAplbHNlIHM9ITAKaWYocylyZXR1cm4hMApxPXI9PT0xMwppZihxKWlmKEguV2UoYSxjW2Iuel0sYyxk
+LGUpKXJldHVybiEwCnA9ZC55CmlmKHI9PT02KXJldHVybiBILldlKGEsYi56LGMsZCxlKQppZihwPT09
+Nil7cz1kLnoKcmV0dXJuIEguV2UoYSxiLGMscyxlKX1pZihyPT09OCl7aWYoIUguV2UoYSxiLnosYyxk
+LGUpKXJldHVybiExCnJldHVybiBILldlKGEsSC54WihhLGIpLGMsZCxlKX1pZihyPT09Nyl7cz1ILldl
+KGEsYi56LGMsZCxlKQpyZXR1cm4gc31pZihwPT09OCl7aWYoSC5XZShhLGIsYyxkLnosZSkpcmV0dXJu
+ITAKcmV0dXJuIEguV2UoYSxiLGMsSC54WihhLGQpLGUpfWlmKHA9PT03KXtzPUguV2UoYSxiLGMsZC56
+LGUpCnJldHVybiBzfWlmKHEpcmV0dXJuITEKcz1yIT09MTEKaWYoKCFzfHxyPT09MTIpJiZkPT09dC5Z
+KXJldHVybiEwCmlmKHA9PT0xMil7aWYoYj09PXQuRClyZXR1cm4hMAppZihyIT09MTIpcmV0dXJuITEK
+bz1iLlEKbj1kLlEKbT1vLmxlbmd0aAppZihtIT09bi5sZW5ndGgpcmV0dXJuITEKYz1jPT1udWxsP286
+by5jb25jYXQoYykKZT1lPT1udWxsP246bi5jb25jYXQoZSkKZm9yKGw9MDtsPG07KytsKXtrPW9bbF0K
+aj1uW2xdCmlmKCFILldlKGEsayxjLGosZSl8fCFILldlKGEsaixlLGssYykpcmV0dXJuITF9cmV0dXJu
+IEguYk8oYSxiLnosYyxkLnosZSl9aWYocD09PTExKXtpZihiPT09dC5EKXJldHVybiEwCmlmKHMpcmV0
+dXJuITEKcmV0dXJuIEguYk8oYSxiLGMsZCxlKX1pZihyPT09OSl7aWYocCE9PTkpcmV0dXJuITEKcmV0
+dXJuIEgucEcoYSxiLGMsZCxlKX1yZXR1cm4hMX0sCmJPOmZ1bmN0aW9uKGEyLGEzLGE0LGE1LGE2KXt2
+YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMQppZighSC5XZShhMixh
+My56LGE0LGE1LnosYTYpKXJldHVybiExCnM9YTMuUQpyPWE1LlEKcT1zLmEKcD1yLmEKbz1xLmxlbmd0
+aApuPXAubGVuZ3RoCmlmKG8+bilyZXR1cm4hMQptPW4tbwpsPXMuYgprPXIuYgpqPWwubGVuZ3RoCmk9
+ay5sZW5ndGgKaWYobytqPG4raSlyZXR1cm4hMQpmb3IoaD0wO2g8bzsrK2gpe2c9cVtoXQppZighSC5X
+ZShhMixwW2hdLGE2LGcsYTQpKXJldHVybiExfWZvcihoPTA7aDxtOysraCl7Zz1sW2hdCmlmKCFILldl
+KGEyLHBbbytoXSxhNixnLGE0KSlyZXR1cm4hMX1mb3IoaD0wO2g8aTsrK2gpe2c9bFttK2hdCmlmKCFI
+LldlKGEyLGtbaF0sYTYsZyxhNCkpcmV0dXJuITF9Zj1zLmMKZT1yLmMKZD1mLmxlbmd0aApjPWUubGVu
+Z3RoCmZvcihiPTAsYT0wO2E8YzthKz0zKXthMD1lW2FdCmZvcig7ITA7KXtpZihiPj1kKXJldHVybiEx
+CmExPWZbYl0KYis9MwppZihhMDxhMSlyZXR1cm4hMQppZihhMTxhMCljb250aW51ZQpnPWZbYi0xXQpp
+ZighSC5XZShhMixlW2ErMl0sYTYsZyxhNCkpcmV0dXJuITEKYnJlYWt9fXJldHVybiEwfSwKcEc6ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9Yi56LGo9ZC56CmlmKGs9PT1qKXtz
+PWIuUQpyPWQuUQpxPXMubGVuZ3RoCmZvcihwPTA7cDxxOysrcCl7bz1zW3BdCm49cltwXQppZighSC5X
+ZShhLG8sYyxuLGUpKXJldHVybiExfXJldHVybiEwfWlmKGQ9PT10LkspcmV0dXJuITAKbT1ILlFvKGEs
+aykKaWYobT09bnVsbClyZXR1cm4hMQpsPW1bal0KaWYobD09bnVsbClyZXR1cm4hMQpxPWwubGVuZ3Ro
+CnI9ZC5RCmZvcihwPTA7cDxxOysrcClpZighSC5XZShhLEguY0UoYSxiLGxbcF0pLGMscltwXSxlKSly
+ZXR1cm4hMQpyZXR1cm4hMH0sCmxSOmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS55CmlmKCEoYT09PXQuUHx8
+YT09PXQuVCkpaWYoIUguQTgoYSkpaWYociE9PTcpaWYoIShyPT09NiYmSC5sUihhLnopKSlzPXI9PT04
+JiZILmxSKGEueikKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEwCnJldHVybiBz
+fSwKY2M6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIUguQTgoYSkpaWYoIShhPT09dC5fKSlzPWE9PT10LksK
+ZWxzZSBzPSEwCmVsc2Ugcz0hMApyZXR1cm4gc30sCkE4OmZ1bmN0aW9uKGEpe3ZhciBzPWEueQpyZXR1
+cm4gcz09PTJ8fHM9PT0zfHxzPT09NHx8cz09PTV8fGE9PT10Lld9LApJeDpmdW5jdGlvbihhLGIpe3Zh
+ciBzLHIscT1PYmplY3Qua2V5cyhiKSxwPXEubGVuZ3RoCmZvcihzPTA7czxwOysrcyl7cj1xW3NdCmFb
+cl09YltyXX19LApKYzpmdW5jdGlvbiBKYyhhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy54PV8u
+cj1fLmM9bnVsbApfLnk9MApfLmN5PV8uY3g9Xy5jaD1fLlE9Xy56PW51bGx9LApHOmZ1bmN0aW9uIEco
+KXt0aGlzLmM9dGhpcy5iPXRoaXMuYT1udWxsfSwKa1M6ZnVuY3Rpb24ga1MoKXt9LAppTTpmdW5jdGlv
+biBpTShhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9uKGEpe3JldHVybiB0LncuYihhKXx8dC5CLmIoYSl8
+fHQuZHouYihhKXx8dC5JLmIoYSl8fHQuQS5iKGEpfHx0Lmc0LmIoYSl8fHQuZzIuYihhKX0sCkpnOmZ1
+bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1thXX19LEo9ewpRdTpmdW5jdGlvbihh
+LGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmtzOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxw
+LG89YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihvPT1udWxsKWlmKCQuQnY9PW51bGwpe0guWEQo
+KQpvPWFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV19aWYobyE9bnVsbCl7cz1vLnAKaWYoITE9PT1zKXJl
+dHVybiBvLmkKaWYoITA9PT1zKXJldHVybiBhCnI9T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCmlmKHM9
+PT1yKXJldHVybiBvLmkKaWYoby5lPT09cil0aHJvdyBILmIoUC5TWSgiUmV0dXJuIGludGVyY2VwdG9y
+IGZvciAiK0guRWoocyhhLG8pKSkpfXE9YS5jb25zdHJ1Y3RvcgpwPXE9PW51bGw/bnVsbDpxW0ouUlAo
+KV0KaWYocCE9bnVsbClyZXR1cm4gcApwPUgudzMoYSkKaWYocCE9bnVsbClyZXR1cm4gcAppZih0eXBl
+b2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwpzPU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQppZihz
+PT1udWxsKXJldHVybiBDLlpRCmlmKHM9PT1PYmplY3QucHJvdG90eXBlKXJldHVybiBDLlpRCmlmKHR5
+cGVvZiBxPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVydHkocSxKLlJQKCkse3ZhbHVlOkMu
+dkIsZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJu
+IEMudkJ9cmV0dXJuIEMudkJ9LApSUDpmdW5jdGlvbigpe3ZhciBzPSQuem0KcmV0dXJuIHM9PW51bGw/
+JC56bT12LmdldElzb2xhdGVUYWcoIl8kZGFydF9qcyIpOnN9LApRaTpmdW5jdGlvbihhLGIpe2lmKGE8
+MHx8YT40Mjk0OTY3Mjk1KXRocm93IEguYihQLlRFKGEsMCw0Mjk0OTY3Mjk1LCJsZW5ndGgiLG51bGwp
+KQpyZXR1cm4gSi5weShuZXcgQXJyYXkoYSksYil9LApLaDpmdW5jdGlvbihhLGIpe2lmKGE8MCl0aHJv
+dyBILmIoUC54WSgiTGVuZ3RoIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlcjogIithKSkKcmV0
+dXJuIEguVk0obmV3IEFycmF5KGEpLGIuQygiamQ8MD4iKSl9LApweTpmdW5jdGlvbihhLGIpe3JldHVy
+biBKLkVwKEguVk0oYSxiLkMoImpkPDA+IikpLGIpfSwKRXA6ZnVuY3Rpb24oYSxiKXthLmZpeGVkJGxl
+bmd0aD1BcnJheQpyZXR1cm4gYX0sCnpDOmZ1bmN0aW9uKGEpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CmEu
+aW1tdXRhYmxlJGxpc3Q9QXJyYXkKcmV0dXJuIGF9LApHYTpmdW5jdGlvbihhKXtpZihhPDI1Nilzd2l0
+Y2goYSl7Y2FzZSA5OmNhc2UgMTA6Y2FzZSAxMTpjYXNlIDEyOmNhc2UgMTM6Y2FzZSAzMjpjYXNlIDEz
+MzpjYXNlIDE2MDpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfXN3aXRjaChhKXtjYXNlIDU3NjA6Y2Fz
+ZSA4MTkyOmNhc2UgODE5MzpjYXNlIDgxOTQ6Y2FzZSA4MTk1OmNhc2UgODE5NjpjYXNlIDgxOTc6Y2Fz
+ZSA4MTk4OmNhc2UgODE5OTpjYXNlIDgyMDA6Y2FzZSA4MjAxOmNhc2UgODIwMjpjYXNlIDgyMzI6Y2Fz
+ZSA4MjMzOmNhc2UgODIzOTpjYXNlIDgyODc6Y2FzZSAxMjI4ODpjYXNlIDY1Mjc5OnJldHVybiEwCmRl
+ZmF1bHQ6cmV0dXJuITF9fSwKbW06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmZvcihzPWEubGVuZ3RoO2I8
+czspe3I9Qy54Qi5XKGEsYikKaWYociE9PTMyJiZyIT09MTMmJiFKLkdhKHIpKWJyZWFrOysrYn1yZXR1
+cm4gYn0sCmMxOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpmb3IoO2I+MDtiPXMpe3M9Yi0xCnI9Qy54Qi5t
+KGEscykKaWYociE9PTMyJiZyIT09MTMmJiFKLkdhKHIpKWJyZWFrfXJldHVybiBifSwKVEo6ZnVuY3Rp
+b24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBKLnFJLnByb3RvdHlwZQppZih0eXBlb2Yg
+YT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5j
+b25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0
+Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlm
+KGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBKLmtzKGEpfSwKVTY6ZnVuY3Rpb24oYSl7
+aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVy
+biBhCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2Yg
+YSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpy
+ZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sCllFOmZ1
+bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBl
+b2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5j
+ZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LAppYTpmdW5jdGlvbihhKXtpZih0eXBlb2Yg
+YT09Im51bWJlciIpe2lmKE1hdGguZmxvb3IoYSk9PWEpcmV0dXJuIEouYlUucHJvdG90eXBlCnJldHVy
+biBKLlZBLnByb3RvdHlwZX1pZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBl
+CmlmKGE9PW51bGwpcmV0dXJuIEoud2UucHJvdG90eXBlCmlmKHR5cGVvZiBhPT0iYm9vbGVhbiIpcmV0
+dXJuIEoueUUucHJvdG90eXBlCmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpkLnByb3Rv
+dHlwZQppZih0eXBlb2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBK
+LmM1LnByb3RvdHlwZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpyZXR1cm4g
+Si5rcyhhKX0sCnJZOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5w
+cm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gYQppZighKGEgaW5zdGFuY2VvZiBQLk1oKSlyZXR1cm4g
+Si5rZC5wcm90b3R5cGUKcmV0dXJuIGF9LAp3MTpmdW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBh
+CmlmKGEuY29uc3RydWN0b3I9PUFycmF5KXJldHVybiBKLmpkLnByb3RvdHlwZQppZih0eXBlb2YgYSE9
+Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlwZQpyZXR1
+cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sCkE1OmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIEoudzEoYSkuZVIoYSxiKX0sCkNNOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVy
+biBKLllFKGEpLmR1KGEsYixjLGQpfSwKRWg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLllFKGEpLm1L
+KGEsYixjKX0sCkVsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEoudzEoYSkuZHIoYSxiKX0sCkY3OmZ1bmN0
+aW9uKGEpe3JldHVybiBKLlU2KGEpLmdvcihhKX0sCkZMOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclko
+YSkuZGQoYSxiKX0sCkdBOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEoudzEoYSkuRShhLGIpfSwKR3I6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ21XKGEpfSwKSG06ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYo
+YSkuZ0EoYSl9LApJVDpmdW5jdGlvbihhKXtyZXR1cm4gSi53MShhKS5na3ooYSl9LApKeTpmdW5jdGlv
+bihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZ
+KGEpLkcoYSxiKX0sCkx0OmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEpLndnKGEpfSwKTTE6ZnVuY3Rp
+b24oYSxiLGMpe3JldHVybiBKLncxKGEpLkUyKGEsYixjKX0sCk11OmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IEouWUUoYSkuc0QoYSxiKX0sClF6OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkuVyhhLGIpfSwK
+Uk06ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiPT1udWxsCmlmKHR5cGVvZiBhIT0ib2Jq
+ZWN0IilyZXR1cm4gYiE9bnVsbCYmYT09PWIKcmV0dXJuIEouaWEoYSkuRE4oYSxiKX0sClJYOmZ1bmN0
+aW9uKGEpe3JldHVybiBKLncxKGEpLmJyKGEpfSwKVDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEouclkoYSku
+YlMoYSl9LAphNjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZKGEpLm0oYSxiKX0sCmJUOmZ1bmN0aW9u
+KGEpe3JldHVybiBKLllFKGEpLkQ0KGEpfSwKYmI6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51
+bWJlciImJnR5cGVvZiBiPT0ibnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0s
+CmNIOmZ1bmN0aW9uKGEpe3JldHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouWUUoYSkuZ0QoYSl9LApkWjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5ZRShhKS5PbihhLGIs
+YyxkKX0sCmRnOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuRkYoYSl9LApkcjpmdW5jdGlvbihhLGIpe3JldHVybiBK
+LllFKGEpLnNhNChhLGIpfSwKaGY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouaWEoYSkuZ2lPKGEpfSwKaWc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ1FnKGEpfSwKajpmdW5jdGlvbihhKXtyZXR1cm4gSi5p
+YShhKS53KGEpfSwKbDU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zaGYoYSxiKX0sCmxkOmZ1
+bmN0aW9uKGEsYixjKXtyZXR1cm4gSi5yWShhKS5OaihhLGIsYyl9LApwNDpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBKLnJZKGEpLlRjKGEsYil9LApxMDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouclkoYSkuUWko
+YSxiLGMpfSwKcUY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ1ZsKGEpfSwKdEg6ZnVuY3Rpb24o
+YSxiLGMpe3JldHVybiBKLllFKGEpLnBrKGEsYixjKX0sCnU5OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4g
+Si53MShhKS5ZKGEsYixjKX0sCnVVOmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2KGEpLmdsMChhKX0sCndm
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouWUUoYSkuc1JOKGEsYil9LAp4OTpmdW5jdGlvbihhLGIpe2lm
+KHR5cGVvZiBiPT09Im51bWJlciIpaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXl8fHR5cGVvZiBhPT0ic3Ry
+aW5nInx8SC53VihhLGFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0pKWlmKGI+Pj4wPT09YiYmYjxhLmxl
+bmd0aClyZXR1cm4gYVtiXQpyZXR1cm4gSi5VNihhKS5xKGEsYil9LAp6bDpmdW5jdGlvbihhLGIpe3Jl
+dHVybiBKLlU2KGEpLnRnKGEsYil9LAp2QjpmdW5jdGlvbiB2Qigpe30sCnlFOmZ1bmN0aW9uIHlFKCl7
+fSwKd2U6ZnVuY3Rpb24gd2UoKXt9LApNRjpmdW5jdGlvbiBNRigpe30sCmlDOmZ1bmN0aW9uIGlDKCl7
+fSwKa2Q6ZnVuY3Rpb24ga2QoKXt9LApjNTpmdW5jdGlvbiBjNSgpe30sCmpkOmZ1bmN0aW9uIGpkKGEp
+e3RoaXMuJHRpPWF9LApQbzpmdW5jdGlvbiBQbyhhKXt0aGlzLiR0aT1hfSwKbTE6ZnVuY3Rpb24gbTEo
+YSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwKXy4kdGk9Y30sCnFJOmZ1
+bmN0aW9uIHFJKCl7fSwKYlU6ZnVuY3Rpb24gYlUoKXt9LApWQTpmdW5jdGlvbiBWQSgpe30sCkRyOmZ1
+bmN0aW9uIERyKCl7fX0sUD17Ck9qOmZ1bmN0aW9uKCl7dmFyIHMscixxPXt9CmlmKHNlbGYuc2NoZWR1
+bGVJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAuRVgoKQppZihzZWxmLk11dGF0aW9uT2JzZXJ2ZXIhPW51
+bGwmJnNlbGYuZG9jdW1lbnQhPW51bGwpe3M9c2VsZi5kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJkaXYi
+KQpyPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3BhbiIpCnEuYT1udWxsCm5ldyBzZWxmLk11
+dGF0aW9uT2JzZXJ2ZXIoSC50UihuZXcgUC50aChxKSwxKSkub2JzZXJ2ZShzLHtjaGlsZExpc3Q6dHJ1
+ZX0pCnJldHVybiBuZXcgUC5oYShxLHMscil9ZWxzZSBpZihzZWxmLnNldEltbWVkaWF0ZSE9bnVsbCly
+ZXR1cm4gUC55dCgpCnJldHVybiBQLnFXKCl9LApaVjpmdW5jdGlvbihhKXtzZWxmLnNjaGVkdWxlSW1t
+ZWRpYXRlKEgudFIobmV3IFAuVnModC5NLmEoYSkpLDApKX0sCm9BOmZ1bmN0aW9uKGEpe3NlbGYuc2V0
+SW1tZWRpYXRlKEgudFIobmV3IFAuRnQodC5NLmEoYSkpLDApKX0sCkJ6OmZ1bmN0aW9uKGEpe3QuTS5h
+KGEpClAuUU4oMCxhKX0sClFOOmZ1bmN0aW9uKGEsYil7dmFyIHM9bmV3IFAuVzMoKQpzLkNZKGEsYikK
+cmV0dXJuIHN9LApGWDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuaWgobmV3IFAudnMoJC5YMyxhLkMo
+InZzPDA+IikpLGEuQygiaWg8MD4iKSl9LApESTpmdW5jdGlvbihhLGIpe2EuJDIoMCxudWxsKQpiLmI9
+ITAKcmV0dXJuIGIuYX0sCmpROmZ1bmN0aW9uKGEsYil7UC5KZShhLGIpfSwKeUM6ZnVuY3Rpb24oYSxi
+KXtiLmFNKDAsYSl9LApmMzpmdW5jdGlvbihhLGIpe2IudzAoSC5SdShhKSxILnRzKGEpKX0sCkplOmZ1
+bmN0aW9uKGEsYil7dmFyIHMscixxPW5ldyBQLldNKGIpLHA9bmV3IFAuU1goYikKaWYoYSBpbnN0YW5j
+ZW9mIFAudnMpYS5RZChxLHAsdC56KQplbHNle3M9dC56CmlmKHQuZC5iKGEpKWEuU3EocSxwLHMpCmVs
+c2V7cj1uZXcgUC52cygkLlgzLHQuYykKci5hPTQKci5jPWEKci5RZChxLHAscyl9fX0sCmx6OmZ1bmN0
+aW9uKGEpe3ZhciBzPWZ1bmN0aW9uKGIsYyl7cmV0dXJuIGZ1bmN0aW9uKGQsZSl7d2hpbGUodHJ1ZSl0
+cnl7YihkLGUpCmJyZWFrfWNhdGNoKHIpe2U9cgpkPWN9fX0oYSwxKQpyZXR1cm4gJC5YMy5MaihuZXcg
+UC5HcyhzKSx0LkgsdC5TLHQueil9LApHUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnkoYSwxKX0s
+ClRoOmZ1bmN0aW9uKCl7cmV0dXJuIEMud1F9LApZbTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuRnko
+YSwzKX0sCmwwOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLnE0KGEsYi5DKCJxNDwwPiIpKX0sCmsz
+OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxCmIuYT0xCnRyeXthLlNxKG5ldyBQLnBWKGIpLG5ldyBQLlU3
+KGIpLHQuUCl9Y2F0Y2gocSl7cz1ILlJ1KHEpCnI9SC50cyhxKQpQLnJiKG5ldyBQLnZyKGIscyxyKSl9
+fSwKQTk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEKZm9yKHM9dC5jO3I9YS5hLHI9PT0yOylhPXMuYShh
+LmMpCmlmKHI+PTQpe3E9Yi5haCgpCmIuYT1hLmEKYi5jPWEuYwpQLkhaKGIscSl9ZWxzZXtxPXQuRi5h
+KGIuYykKYi5hPTIKYi5jPWEKYS5qUShxKX19LApIWjpmdW5jdGlvbihhMCxhMSl7dmFyIHMscixxLHAs
+byxuLG0sbCxrLGosaSxoLGcsZixlLGQsYz1udWxsLGI9e30sYT1iLmE9YTAKZm9yKHM9dC5uLHI9dC5G
+LHE9dC5kOyEwOyl7cD17fQpvPWEuYT09PTgKaWYoYTE9PW51bGwpe2lmKG8pe249cy5hKGEuYykKUC5M
+MihjLGMsYS5iLG4uYSxuLmIpfXJldHVybn1wLmE9YTEKbT1hMS5hCmZvcihhPWExO20hPW51bGw7YT1t
+LG09bCl7YS5hPW51bGwKUC5IWihiLmEsYSkKcC5hPW0KbD1tLmF9az1iLmEKaj1rLmMKcC5iPW8KcC5j
+PWoKaT0hbwppZihpKXtoPWEuYwpoPShoJjEpIT09MHx8KGgmMTUpPT09OH1lbHNlIGg9ITAKaWYoaCl7
+Zz1hLmIuYgppZihvKXtoPWsuYj09PWcKaD0hKGh8fGgpfWVsc2UgaD0hMQppZihoKXtzLmEoaikKUC5M
+MihjLGMsay5iLGouYSxqLmIpCnJldHVybn1mPSQuWDMKaWYoZiE9PWcpJC5YMz1nCmVsc2UgZj1jCmE9
+YS5jCmlmKChhJjE1KT09PTgpbmV3IFAuUlQocCxiLG8pLiQwKCkKZWxzZSBpZihpKXtpZigoYSYxKSE9
+PTApbmV3IFAucnEocCxqKS4kMCgpfWVsc2UgaWYoKGEmMikhPT0wKW5ldyBQLlJXKGIscCkuJDAoKQpp
+ZihmIT1udWxsKSQuWDM9ZgphPXAuYwppZihxLmIoYSkpe2U9cC5hLmIKaWYoYS5hPj00KXtkPXIuYShl
+LmMpCmUuYz1udWxsCmExPWUuTjgoZCkKZS5hPWEuYQplLmM9YS5jCmIuYT1hCmNvbnRpbnVlfWVsc2Ug
+UC5BOShhLGUpCnJldHVybn19ZT1wLmEuYgpkPXIuYShlLmMpCmUuYz1udWxsCmExPWUuTjgoZCkKYT1w
+LmIKaz1wLmMKaWYoIWEpe2UuJHRpLmMuYShrKQplLmE9NAplLmM9a31lbHNle3MuYShrKQplLmE9OApl
+LmM9a31iLmE9ZQphPWV9fSwKVkg6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZih0LmFnLmIoYSkpcmV0dXJu
+IGIuTGooYSx0LnosdC5LLHQubCkKcz10LmJJCmlmKHMuYihhKSlyZXR1cm4gcy5hKGEpCnRocm93IEgu
+YihQLkwzKGEsIm9uRXJyb3IiLCJFcnJvciBoYW5kbGVyIG11c3QgYWNjZXB0IG9uZSBPYmplY3Qgb3Ig
+b25lIE9iamVjdCBhbmQgYSBTdGFja1RyYWNlIGFzIGFyZ3VtZW50cywgYW5kIHJldHVybiBhIGEgdmFs
+aWQgcmVzdWx0IikpfSwKcHU6ZnVuY3Rpb24oKXt2YXIgcyxyCmZvcihzPSQuUzY7cyE9bnVsbDtzPSQu
+UzYpeyQubWc9bnVsbApyPXMuYgokLlM2PXIKaWYocj09bnVsbCkkLms4PW51bGwKcy5hLiQwKCl9fSwK
+ZU46ZnVuY3Rpb24oKXskLlVEPSEwCnRyeXtQLnB1KCl9ZmluYWxseXskLm1nPW51bGwKJC5VRD0hMQpp
+ZigkLlM2IT1udWxsKSQudXQoKS4kMShQLlY5KCkpfX0sCmVXOmZ1bmN0aW9uKGEpe3ZhciBzPW5ldyBQ
+Lk9NKGEpLHI9JC5rOAppZihyPT1udWxsKXskLlM2PSQuazg9cwppZighJC5VRCkkLnV0KCkuJDEoUC5W
+OSgpKX1lbHNlICQuazg9ci5iPXN9LApyUjpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD0kLlM2CmlmKHA9
+PW51bGwpe1AuZVcoYSkKJC5tZz0kLms4CnJldHVybn1zPW5ldyBQLk9NKGEpCnI9JC5tZwppZihyPT1u
+dWxsKXtzLmI9cAokLlM2PSQubWc9c31lbHNle3E9ci5iCnMuYj1xCiQubWc9ci5iPXMKaWYocT09bnVs
+bCkkLms4PXN9fSwKcmI6ZnVuY3Rpb24oYSl7dmFyIHM9bnVsbCxyPSQuWDMKaWYoQy5OVT09PXIpe1Au
+VGsocyxzLEMuTlUsYSkKcmV0dXJufVAuVGsocyxzLHIsdC5NLmEoci5HWShhKSkpfSwKUXc6ZnVuY3Rp
+b24oYSxiKXtQLlVJKGEsInN0cmVhbSIsYi5DKCJxaDwwPiIpKQpyZXR1cm4gbmV3IFAueEkoYi5DKCJ4
+STwwPiIpKX0sClRsOmZ1bmN0aW9uKGEsYil7dmFyIHM9Yj09bnVsbD9QLnYwKGEpOmIKUC5VSShhLCJl
+cnJvciIsdC5LKQpyZXR1cm4gbmV3IFAuQ3coYSxzKX0sCnYwOmZ1bmN0aW9uKGEpe3ZhciBzCmlmKHQu
+ci5iKGEpKXtzPWEuZ0lJKCkKaWYocyE9bnVsbClyZXR1cm4gc31yZXR1cm4gQy5wZH0sCkwyOmZ1bmN0
+aW9uKGEsYixjLGQsZSl7UC5yUihuZXcgUC5wSyhkLGUpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7
+dmFyIHMscj0kLlgzCmlmKHI9PT1jKXJldHVybiBkLiQwKCkKJC5YMz1jCnM9cgp0cnl7cj1kLiQwKCkK
+cmV0dXJuIHJ9ZmluYWxseXskLlgzPXN9fSwKeXY6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHMs
+cj0kLlgzCmlmKHI9PT1jKXJldHVybiBkLiQxKGUpCiQuWDM9YwpzPXIKdHJ5e3I9ZC4kMShlKQpyZXR1
+cm4gcn1maW5hbGx5eyQuWDM9c319LApReDpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHMs
+cj0kLlgzCmlmKHI9PT1jKXJldHVybiBkLiQyKGUsZikKJC5YMz1jCnM9cgp0cnl7cj1kLiQyKGUsZikK
+cmV0dXJuIHJ9ZmluYWxseXskLlgzPXN9fSwKVGs6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMKdC5NLmEo
+ZCkKcz1DLk5VIT09YwppZihzKWQ9ISghc3x8ITEpP2MuR1koZCk6Yy5SVChkLHQuSCkKUC5lVyhkKX0s
+CnRoOmZ1bmN0aW9uIHRoKGEpe3RoaXMuYT1hfSwKaGE6ZnVuY3Rpb24gaGEoYSxiLGMpe3RoaXMuYT1h
+CnRoaXMuYj1iCnRoaXMuYz1jfSwKVnM6ZnVuY3Rpb24gVnMoYSl7dGhpcy5hPWF9LApGdDpmdW5jdGlv
+biBGdChhKXt0aGlzLmE9YX0sClczOmZ1bmN0aW9uIFczKCl7fSwKeUg6ZnVuY3Rpb24geUgoYSxiKXt0
+aGlzLmE9YQp0aGlzLmI9Yn0sCmloOmZ1bmN0aW9uIGloKGEsYil7dGhpcy5hPWEKdGhpcy5iPSExCnRo
+aXMuJHRpPWJ9LApXTTpmdW5jdGlvbiBXTShhKXt0aGlzLmE9YX0sClNYOmZ1bmN0aW9uIFNYKGEpe3Ro
+aXMuYT1hfSwKR3M6ZnVuY3Rpb24gR3MoYSl7dGhpcy5hPWF9LApGeTpmdW5jdGlvbiBGeShhLGIpe3Ro
+aXMuYT1hCnRoaXMuYj1ifSwKR1Y6ZnVuY3Rpb24gR1YoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uZD1f
+LmM9Xy5iPW51bGwKXy4kdGk9Yn0sCnE0OmZ1bmN0aW9uIHE0KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9
+Yn0sClBmOmZ1bmN0aW9uIFBmKCl7fSwKWmY6ZnVuY3Rpb24gWmYoYSxiKXt0aGlzLmE9YQp0aGlzLiR0
+aT1ifSwKRmU6ZnVuY3Rpb24gRmUoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8u
+Yz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2czpmdW5jdGlvbiB2cyhhLGIpe3ZhciBfPXRoaXMKXy5h
+PTAKXy5iPWEKXy5jPW51bGwKXy4kdGk9Yn0sCmRhOmZ1bmN0aW9uIGRhKGEsYil7dGhpcy5hPWEKdGhp
+cy5iPWJ9LApvUTpmdW5jdGlvbiBvUShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKcFY6ZnVuY3Rpb24g
+cFYoYSl7dGhpcy5hPWF9LApVNzpmdW5jdGlvbiBVNyhhKXt0aGlzLmE9YX0sCnZyOmZ1bmN0aW9uIHZy
+KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnJ0OmZ1bmN0aW9uIHJ0KGEsYil7dGhp
+cy5hPWEKdGhpcy5iPWJ9LApLRjpmdW5jdGlvbiBLRihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWkw6
+ZnVuY3Rpb24gWkwoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKUlQ6ZnVuY3Rpb24g
+UlQoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKalo6ZnVuY3Rpb24galooYSl7dGhp
+cy5hPWF9LApycTpmdW5jdGlvbiBycShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKUlc6ZnVuY3Rpb24g
+UlcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk9NOmZ1bmN0aW9uIE9NKGEpe3RoaXMuYT1hCnRoaXMu
+Yj1udWxsfSwKcWg6ZnVuY3Rpb24gcWgoKXt9LApCNTpmdW5jdGlvbiBCNShhLGIpe3RoaXMuYT1hCnRo
+aXMuYj1ifSwKdU86ZnVuY3Rpb24gdU8oYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1POmZ1bmN0aW9u
+IE1PKCl7fSwKa1Q6ZnVuY3Rpb24ga1QoKXt9LAp4STpmdW5jdGlvbiB4SShhKXt0aGlzLiR0aT1hfSwK
+Q3c6ZnVuY3Rpb24gQ3coYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm0wOmZ1bmN0aW9uIG0wKCl7fSwK
+cEs6ZnVuY3Rpb24gcEsoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkppOmZ1bmN0aW9uIEppKCl7fSwK
+aGo6ZnVuY3Rpb24gaGooYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnA6ZnVuY3Rp
+b24gVnAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk9SOmZ1bmN0aW9uIE9SKGEsYixjKXt0aGlzLmE9
+YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCkVGOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gYi5DKCJAPDA+Iiku
+S3EoYykuQygiRm88MSwyPiIpLmEoSC5CNyhhLG5ldyBILk41KGIuQygiQDwwPiIpLktxKGMpLkMoIk41
+PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILk41KGEuQygiQDwwPiIpLktx
+KGIpLkMoIk41PDEsMj4iKSl9LApMczpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuYjYoYS5DKCJiNjww
+PiIpKX0sClQyOmZ1bmN0aW9uKCl7dmFyIHM9T2JqZWN0LmNyZWF0ZShudWxsKQpzWyI8bm9uLWlkZW50
+aWZpZXIta2V5PiJdPXMKZGVsZXRlIHNbIjxub24taWRlbnRpZmllci1rZXk+Il0KcmV0dXJuIHN9LApy
+ajpmdW5jdGlvbihhLGIsYyl7dmFyIHM9bmV3IFAubG0oYSxiLGMuQygibG08MD4iKSkKcy5jPWEuZQpy
+ZXR1cm4gc30sCkVQOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyCmlmKFAuaEIoYSkpe2lmKGI9PT0iKCIm
+JmM9PT0iKSIpcmV0dXJuIiguLi4pIgpyZXR1cm4gYisiLi4uIitjfXM9SC5WTShbXSx0LnMpCkMuTm0u
+aSgkLnhnLGEpCnRyeXtQLlZyKGEscyl9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5P
+SCgkLnhnLC0xKQokLnhnLnBvcCgpfXI9UC52ZyhiLHQudS5hKHMpLCIsICIpK2MKcmV0dXJuIHIuY2hh
+ckNvZGVBdCgwKT09MD9yOnJ9LApXRTpmdW5jdGlvbihhLGIsYyl7dmFyIHMscgppZihQLmhCKGEpKXJl
+dHVybiBiKyIuLi4iK2MKcz1uZXcgUC5SbihiKQpDLk5tLmkoJC54ZyxhKQp0cnl7cj1zCnIuYT1QLnZn
+KHIuYSxhLCIsICIpfWZpbmFsbHl7aWYoMD49JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkK
+JC54Zy5wb3AoKX1zLmErPWMKcj1zLmEKcmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9LApoQjpm
+dW5jdGlvbihhKXt2YXIgcyxyCmZvcihzPSQueGcubGVuZ3RoLHI9MDtyPHM7KytyKWlmKGE9PT0kLnhn
+W3JdKXJldHVybiEwCnJldHVybiExfSwKVnI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxs
+PWEuZ2t6KGEpLGs9MCxqPTAKd2hpbGUoITApe2lmKCEoazw4MHx8ajwzKSlicmVhawppZighbC5GKCkp
+cmV0dXJuCnM9SC5FaihsLmdsKCkpCkMuTm0uaShiLHMpCmsrPXMubGVuZ3RoKzI7KytqfWlmKCFsLkYo
+KSl7aWYoajw9NSlyZXR1cm4KaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcj1iLnBvcCgp
+CmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9IKGIsLTEpCnE9Yi5wb3AoKX1lbHNle3A9bC5nbCgpOysr
+agppZighbC5GKCkpe2lmKGo8PTQpe0MuTm0uaShiLEguRWoocCkpCnJldHVybn1yPUguRWoocCkKaWYo
+MD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcT1iLnBvcCgpCmsrPXIubGVuZ3RoKzJ9ZWxzZXtv
+PWwuZ2woKTsrK2oKZm9yKDtsLkYoKTtwPW8sbz1uKXtuPWwuZ2woKTsrK2oKaWYoaj4xMDApe3doaWxl
+KCEwKXtpZighKGs+NzUmJmo+MykpYnJlYWsKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkK
+ay09Yi5wb3AoKS5sZW5ndGgrMjstLWp9Qy5ObS5pKGIsIi4uLiIpCnJldHVybn19cT1ILkVqKHApCnI9
+SC5FaihvKQprKz1yLmxlbmd0aCtxLmxlbmd0aCs0fX1pZihqPmIubGVuZ3RoKzIpe2srPTUKbT0iLi4u
+In1lbHNlIG09bnVsbAp3aGlsZSghMCl7aWYoIShrPjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigwPj1i
+Lmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQprLT1iLnBvcCgpLmxlbmd0aCsyCmlmKG09PW51bGwpe2sr
+PTUKbT0iLi4uIn19aWYobSE9bnVsbClDLk5tLmkoYixtKQpDLk5tLmkoYixxKQpDLk5tLmkoYixyKX0s
+CnRNOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPVAuTHMoYikKZm9yKHM9YS5sZW5ndGgscj0wO3I8YS5s
+ZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShhKSwrK3IpcS5pKDAsYi5hKGFbcl0pKQpyZXR1cm4g
+cX0sCm5POmZ1bmN0aW9uKGEpe3ZhciBzLHI9e30KaWYoUC5oQihhKSlyZXR1cm4iey4uLn0iCnM9bmV3
+IFAuUm4oIiIpCnRyeXtDLk5tLmkoJC54ZyxhKQpzLmErPSJ7IgpyLmE9ITAKYS5LKDAsbmV3IFAucmEo
+cixzKSkKcy5hKz0ifSJ9ZmluYWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0x
+KQokLnhnLnBvcCgpfXI9cy5hCnJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfSwKYjY6ZnVuY3Rp
+b24gYjYoYSl7dmFyIF89dGhpcwpfLmE9MApfLmY9Xy5lPV8uZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4k
+dGk9YX0sCmJuOmZ1bmN0aW9uIGJuKGEpe3RoaXMuYT1hCnRoaXMuYz10aGlzLmI9bnVsbH0sCmxtOmZ1
+bmN0aW9uIGxtKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0aT1j
+fSwKbVc6ZnVuY3Rpb24gbVcoKXt9LAp1eTpmdW5jdGlvbiB1eSgpe30sCmxEOmZ1bmN0aW9uIGxEKCl7
+fSwKaWw6ZnVuY3Rpb24gaWwoKXt9LApyYTpmdW5jdGlvbiByYShhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKWWs6ZnVuY3Rpb24gWWsoKXt9LAp5UTpmdW5jdGlvbiB5UShhKXt0aGlzLmE9YX0sCktQOmZ1bmN0
+aW9uIEtQKCl7fSwKUG46ZnVuY3Rpb24gUG4oKXt9LApHajpmdW5jdGlvbiBHaihhLGIpe3RoaXMuYT1h
+CnRoaXMuJHRpPWJ9LApsZjpmdW5jdGlvbiBsZigpe30sClZqOmZ1bmN0aW9uIFZqKCl7fSwKWHY6ZnVu
+Y3Rpb24gWHYoKXt9LApuWTpmdW5jdGlvbiBuWSgpe30sCldZOmZ1bmN0aW9uIFdZKCl7fSwKUlU6ZnVu
+Y3Rpb24gUlUoKXt9LApCUzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwCmlmKHR5cGVvZiBhIT0ic3Ry
+aW5nIil0aHJvdyBILmIoSC50TChhKSkKcz1udWxsCnRyeXtzPUpTT04ucGFyc2UoYSl9Y2F0Y2gocSl7
+cj1ILlJ1KHEpCnA9UC5ycihTdHJpbmcociksbnVsbCxudWxsKQp0aHJvdyBILmIocCl9cD1QLlFlKHMp
+CnJldHVybiBwfSwKUWU6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZih0
+eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGEKaWYoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpIT09QXJy
+YXkucHJvdG90eXBlKXJldHVybiBuZXcgUC51dyhhLE9iamVjdC5jcmVhdGUobnVsbCkpCmZvcihzPTA7
+czxhLmxlbmd0aDsrK3MpYVtzXT1QLlFlKGFbc10pCnJldHVybiBhfSwKa3k6ZnVuY3Rpb24oYSxiLGMs
+ZCl7dmFyIHMscgppZihiIGluc3RhbmNlb2YgVWludDhBcnJheSl7cz1iCmQ9cy5sZW5ndGgKaWYoZC1j
+PDE1KXJldHVybiBudWxsCnI9UC5DRyhhLHMsYyxkKQppZihyIT1udWxsJiZhKWlmKHIuaW5kZXhPZigi
+XHVmZmZkIik+PTApcmV0dXJuIG51bGwKcmV0dXJuIHJ9cmV0dXJuIG51bGx9LApDRzpmdW5jdGlvbihh
+LGIsYyxkKXt2YXIgcz1hPyQuSEcoKTokLnJmKCkKaWYocz09bnVsbClyZXR1cm4gbnVsbAppZigwPT09
+YyYmZD09PWIubGVuZ3RoKXJldHVybiBQLlJiKHMsYikKcmV0dXJuIFAuUmIocyxiLnN1YmFycmF5KGMs
+UC5qQihjLGQsYi5sZW5ndGgpKSl9LApSYjpmdW5jdGlvbihhLGIpe3ZhciBzLHIKdHJ5e3M9YS5kZWNv
+ZGUoYikKcmV0dXJuIHN9Y2F0Y2gocil7SC5SdShyKX1yZXR1cm4gbnVsbH0sCnhNOmZ1bmN0aW9uKGEs
+YixjLGQsZSxmKXtpZihDLmpuLnpZKGYsNCkhPT0wKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2
+NCBwYWRkaW5nLCBwYWRkZWQgbGVuZ3RoIG11c3QgYmUgbXVsdGlwbGUgb2YgZm91ciwgaXMgIitmLGEs
+YykpCmlmKGQrZSE9PWYpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsICc9JyBu
+b3QgYXQgdGhlIGVuZCIsYSxiKSkKaWYoZT4yKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBw
+YWRkaW5nLCBtb3JlIHRoYW4gdHdvICc9JyBjaGFyYWN0ZXJzIixhLGIpKX0sCkd5OmZ1bmN0aW9uKGEs
+YixjKXtyZXR1cm4gbmV3IFAuVWQoYSxiKX0sCk5DOmZ1bmN0aW9uKGEpe3JldHVybiBhLkx0KCl9LApV
+ZzpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC50dShhLFtdLFAuQ3koKSl9LAp1WDpmdW5jdGlvbihh
+LGIsYyl7dmFyIHMscj1uZXcgUC5SbigiIikscT1QLlVnKHIsYikKcS5pVShhKQpzPXIuYQpyZXR1cm4g
+cy5jaGFyQ29kZUF0KDApPT0wP3M6c30sCmo0OmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtjYXNlIDY1OnJl
+dHVybiJNaXNzaW5nIGV4dGVuc2lvbiBieXRlIgpjYXNlIDY3OnJldHVybiJVbmV4cGVjdGVkIGV4dGVu
+c2lvbiBieXRlIgpjYXNlIDY5OnJldHVybiJJbnZhbGlkIFVURi04IGJ5dGUiCmNhc2UgNzE6cmV0dXJu
+Ik92ZXJsb25nIGVuY29kaW5nIgpjYXNlIDczOnJldHVybiJPdXQgb2YgdW5pY29kZSByYW5nZSIKY2Fz
+ZSA3NTpyZXR1cm4iRW5jb2RlZCBzdXJyb2dhdGUiCmNhc2UgNzc6cmV0dXJuIlVuZmluaXNoZWQgVVRG
+LTggb2N0ZXQgc2VxdWVuY2UiCmRlZmF1bHQ6cmV0dXJuIiJ9fSwKank6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzLHIscSxwLG89Yy1iLG49bmV3IFVpbnQ4QXJyYXkobykKZm9yKHM9bi5sZW5ndGgscj1KLlU2KGEp
+LHE9MDtxPG87KytxKXtwPXIucShhLGIrcSkKaWYodHlwZW9mIHAhPT0ibnVtYmVyIilyZXR1cm4gcC56
+TSgpCmlmKChwJjQyOTQ5NjcwNDApPj4+MCE9PTApcD0yNTUKaWYocT49cylyZXR1cm4gSC5PSChuLHEp
+Cm5bcV09cH1yZXR1cm4gbn0sCnV3OmZ1bmN0aW9uIHV3KGEsYil7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
+cy5jPW51bGx9LAppODpmdW5jdGlvbiBpOChhKXt0aGlzLmE9YX0sCnBnOmZ1bmN0aW9uIHBnKCl7fSwK
+YzI6ZnVuY3Rpb24gYzIoKXt9LApDVjpmdW5jdGlvbiBDVigpe30sClU4OmZ1bmN0aW9uIFU4KCl7fSwK
+VWs6ZnVuY3Rpb24gVWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0aW9uIFppKCl7fSwK
+VWQ6ZnVuY3Rpb24gVWQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCks4OmZ1bmN0aW9uIEs4KGEsYil7
+dGhpcy5hPWEKdGhpcy5iPWJ9LApieTpmdW5jdGlvbiBieSgpe30sCm9qOmZ1bmN0aW9uIG9qKGEpe3Ro
+aXMuYj1hfSwKTXg6ZnVuY3Rpb24gTXgoYSl7dGhpcy5hPWF9LApTaDpmdW5jdGlvbiBTaCgpe30sCnRp
+OmZ1bmN0aW9uIHRpKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp0dTpmdW5jdGlvbiB0dShhLGIsYyl7
+dGhpcy5jPWEKdGhpcy5hPWIKdGhpcy5iPWN9LAp1NTpmdW5jdGlvbiB1NSgpe30sCkUzOmZ1bmN0aW9u
+IEUzKCl7fSwKUnc6ZnVuY3Rpb24gUncoYSl7dGhpcy5iPTAKdGhpcy5jPWF9LApHWTpmdW5jdGlvbiBH
+WShhKXt0aGlzLmE9YX0sCmJ6OmZ1bmN0aW9uIGJ6KGEpe3RoaXMuYT1hCnRoaXMuYj0xNgp0aGlzLmM9
+MH0sClFBOmZ1bmN0aW9uKGEsYil7dmFyIHM9SC5IcChhLGIpCmlmKHMhPW51bGwpcmV0dXJuIHMKdGhy
+b3cgSC5iKFAucnIoYSxudWxsLG51bGwpKX0sCm9zOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBI
+LlRwKXJldHVybiBhLncoMCkKcmV0dXJuIkluc3RhbmNlIG9mICciK0guRWooSC5NKGEpKSsiJyJ9LApP
+ODpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyPWM/Si5LaChhLGQpOkouUWkoYSxkKQppZihhIT09MCYm
+YiE9bnVsbClmb3Iocz0wO3M8ci5sZW5ndGg7KytzKXJbc109YgpyZXR1cm4gcn0sCkNIOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgcyxyPUguVk0oW10sYy5DKCJqZDwwPiIpKQpmb3Iocz1KLklUKGEpO3MuRigpOylD
+Lk5tLmkocixjLmEocy5nbCgpKSkKaWYoYilyZXR1cm4gcgpyZXR1cm4gSi5FcChyLGMpfSwKZEg6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzLHI9Si5LaChhLGMpCmZvcihzPTA7czxhOysrcylDLk5tLlkocixzLGIu
+JDEocykpCnJldHVybiByfSwKQUY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi56QyhQLkNIKGEsITEsYikp
+fSwKSE06ZnVuY3Rpb24oYSxiLGMpe2lmKHQuYm0uYihhKSlyZXR1cm4gSC5mdyhhLGIsUC5qQihiLGMs
+YS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9LApPbzpmdW5jdGlvbihhKXtyZXR1cm4gSC5Mdyhh
+KX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscCxvLG49bnVsbAppZihiPDApdGhyb3cgSC5i
+KFAuVEUoYiwwLGEubGVuZ3RoLG4sbikpCnM9Yz09bnVsbAppZighcyYmYzxiKXRocm93IEguYihQLlRF
+KGMsYixhLmxlbmd0aCxuLG4pKQpyPW5ldyBILmE3KGEsYS5sZW5ndGgsSC56KGEpLkMoImE3PGxELkU+
+IikpCmZvcihxPTA7cTxiOysrcSlpZighci5GKCkpdGhyb3cgSC5iKFAuVEUoYiwwLHEsbixuKSkKcD1b
+XQppZihzKWZvcig7ci5GKCk7KXtvPXIuZApwLnB1c2gobyl9ZWxzZSBmb3IocT1iO3E8YzsrK3Epe2lm
+KCFyLkYoKSl0aHJvdyBILmIoUC5URShjLGIscSxuLG4pKQpvPXIuZApwLnB1c2gobyl9cmV0dXJuIEgu
+ZVQocCl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEs
+ITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1KLklUKGIpCmlmKCFzLkYoKSlyZXR1cm4gYQpp
+ZihjLmxlbmd0aD09PTApe2RvIGErPUguRWoocy5nbCgpKQp3aGlsZShzLkYoKSl9ZWxzZXthKz1ILkVq
+KHMuZ2woKSkKZm9yKDtzLkYoKTspYT1hK2MrSC5FaihzLmdsKCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rp
+b24oYSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgcz1I
+Lk0wKCkKaWYocyE9bnVsbClyZXR1cm4gUC5oSyhzKQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBp
+cyBub3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuLG09
+IjAxMjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXtzPSQuejQoKS5iCmlmKHR5cGVvZiBiIT0ic3Ry
+aW5nIilILnYoSC50TChiKSkKcz1zLnRlc3QoYil9ZWxzZSBzPSExCmlmKHMpcmV0dXJuIGIKSC5MaChj
+KS5DKCJVay5TIikuYShiKQpyPWMuZ1pFKCkuV0ooYikKZm9yKHM9ci5sZW5ndGgscT0wLHA9IiI7cTxz
+OysrcSl7bz1yW3FdCmlmKG88MTI4KXtuPW8+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goYSxuKQpuPShh
+W25dJjE8PChvJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKXArPUguTHcobykKZWxzZSBwPWQmJm89PT0z
+Mj9wKyIrIjpwKyIlIittW28+Pj40JjE1XSttW28mMTVdfXJldHVybiBwLmNoYXJDb2RlQXQoMCk9PTA/
+cDpwfSwKR3E6ZnVuY3Rpb24oYSl7dmFyIHM9TWF0aC5hYnMoYSkscj1hPDA/Ii0iOiIiCmlmKHM+PTEw
+MDApcmV0dXJuIiIrYQppZihzPj0xMDApcmV0dXJuIHIrIjAiK3MKaWYocz49MTApcmV0dXJuIHIrIjAw
+IitzCnJldHVybiByKyIwMDAiK3N9LApWeDpmdW5jdGlvbihhKXtpZihhPj0xMDApcmV0dXJuIiIrYQpp
+ZihhPj0xMClyZXR1cm4iMCIrYQpyZXR1cm4iMDAiK2F9LApoMDpmdW5jdGlvbihhKXtpZihhPj0xMCly
+ZXR1cm4iIithCnJldHVybiIwIithfSwKaGw6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIi
+fHxILmwoYSl8fG51bGw9PWEpcmV0dXJuIEouaihhKQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJu
+IEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLm9zKGEpfSwKaFY6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
+dyBQLkM2KGEpfSwKeFk6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLnUoITEsbnVsbCxudWxsLGEpfSwK
+TDM6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBuZXcgUC51KCEwLGEsYixjKX0sClVJOmZ1bmN0aW9uKGEs
+YixjKXtpZihhPT1udWxsKXRocm93IEguYihuZXcgUC51KCExLG51bGwsYiwiTXVzdCBub3QgYmUgbnVs
+bCIpKQpyZXR1cm4gYX0sCk83OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLmJKKG51bGwsbnVsbCwh
+MCxhLGIsIlZhbHVlIG5vdCBpbiByYW5nZSIpfSwKVEU6ZnVuY3Rpb24oYSxiLGMsZCxlKXtyZXR1cm4g
+bmV3IFAuYkooYixjLCEwLGEsZCwiSW52YWxpZCB2YWx1ZSIpfSwKd0E6ZnVuY3Rpb24oYSxiLGMsZCl7
+aWYoYTxifHxhPmMpdGhyb3cgSC5iKFAuVEUoYSxiLGMsZCxudWxsKSkKcmV0dXJuIGF9LApqQjpmdW5j
+dGlvbihhLGIsYyl7aWYoMD5hfHxhPmMpdGhyb3cgSC5iKFAuVEUoYSwwLGMsInN0YXJ0IixudWxsKSkK
+aWYoYiE9bnVsbCl7aWYoYT5ifHxiPmMpdGhyb3cgSC5iKFAuVEUoYixhLGMsImVuZCIsbnVsbCkpCnJl
+dHVybiBifXJldHVybiBjfSwKazE6ZnVuY3Rpb24oYSxiKXtpZihhPDApdGhyb3cgSC5iKFAuVEUoYSww
+LG51bGwsYixudWxsKSkKcmV0dXJuIGF9LApDZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzPUgudVAo
+ZT09bnVsbD9KLkhtKGIpOmUpCnJldHVybiBuZXcgUC5lWShzLCEwLGEsYywiSW5kZXggb3V0IG9mIHJh
+bmdlIil9LApMNDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAudWIoYSl9LApTWTpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAuZHMoYSl9LApQVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAubGooYSl9LAphNDpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVVYoYSl9LApycjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5l
+dyBQLmFFKGEsYixjKX0sCmhLOmZ1bmN0aW9uKGE1KXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgs
+ZyxmLGUsZCxjLGIsYSxhMCxhMSxhMixhMz1udWxsLGE0PWE1Lmxlbmd0aAppZihhND49NSl7cz0oKEou
+UXooYTUsNCleNTgpKjN8Qy54Qi5XKGE1LDApXjEwMHxDLnhCLlcoYTUsMSleOTd8Qy54Qi5XKGE1LDIp
+XjExNnxDLnhCLlcoYTUsMyleOTcpPj4+MAppZihzPT09MClyZXR1cm4gUC5LRChhNDxhND9DLnhCLk5q
+KGE1LDAsYTQpOmE1LDUsYTMpLmdsUigpCmVsc2UgaWYocz09PTMyKXJldHVybiBQLktEKEMueEIuTmoo
+YTUsNSxhNCksMCxhMykuZ2xSKCl9cj1QLk84KDgsMCwhMSx0LlMpCkMuTm0uWShyLDAsMCkKQy5ObS5Z
+KHIsMSwtMSkKQy5ObS5ZKHIsMiwtMSkKQy5ObS5ZKHIsNywtMSkKQy5ObS5ZKHIsMywwKQpDLk5tLlko
+ciw0LDApCkMuTm0uWShyLDUsYTQpCkMuTm0uWShyLDYsYTQpCmlmKFAuVUIoYTUsMCxhNCwwLHIpPj0x
+NClDLk5tLlkociw3LGE0KQppZigxPj1yLmxlbmd0aClyZXR1cm4gSC5PSChyLDEpCnE9clsxXQppZihx
+Pj0wKWlmKFAuVUIoYTUsMCxxLDIwLHIpPT09MjApe2lmKDc+PXIubGVuZ3RoKXJldHVybiBILk9IKHIs
+NykKcls3XT1xfXA9ci5sZW5ndGgKaWYoMj49cClyZXR1cm4gSC5PSChyLDIpCm89clsyXSsxCmlmKDM+
+PXApcmV0dXJuIEguT0gociwzKQpuPXJbM10KaWYoND49cClyZXR1cm4gSC5PSChyLDQpCm09cls0XQpp
+Zig1Pj1wKXJldHVybiBILk9IKHIsNSkKbD1yWzVdCmlmKDY+PXApcmV0dXJuIEguT0gociw2KQprPXJb
+Nl0KaWYoazxsKWw9awppZihtPG8pbT1sCmVsc2UgaWYobTw9cSltPXErMQppZihuPG8pbj1tCmlmKDc+
+PXApcmV0dXJuIEguT0gociw3KQpqPXJbN108MAppZihqKWlmKG8+cSszKXtpPWEzCmo9ITF9ZWxzZXtw
+PW4+MAppZihwJiZuKzE9PT1tKXtpPWEzCmo9ITF9ZWxzZXtpZighKGw8YTQmJmw9PT1tKzImJkoucTAo
+YTUsIi4uIixtKSkpaD1sPm0rMiYmSi5xMChhNSwiLy4uIixsLTMpCmVsc2UgaD0hMAppZihoKXtpPWEz
+Cmo9ITF9ZWxzZXtpZihxPT09NClpZihKLnEwKGE1LCJmaWxlIiwwKSl7aWYobzw9MCl7aWYoIUMueEIu
+UWkoYTUsIi8iLG0pKXtnPSJmaWxlOi8vLyIKcz0zfWVsc2V7Zz0iZmlsZTovLyIKcz0yfWE1PWcrQy54
+Qi5OaihhNSxtLGE0KQpxLT0wCnA9cy0wCmwrPXAKays9cAphND1hNS5sZW5ndGgKbz03Cm49NwptPTd9
+ZWxzZSBpZihtPT09bCl7KytrCmY9bCsxCmE1PUMueEIuaTcoYTUsbSxsLCIvIik7KythNApsPWZ9aT0i
+ZmlsZSJ9ZWxzZSBpZihDLnhCLlFpKGE1LCJodHRwIiwwKSl7aWYocCYmbiszPT09bSYmQy54Qi5RaShh
+NSwiODAiLG4rMSkpe2stPTMKZT1tLTMKbC09MwphNT1DLnhCLmk3KGE1LG4sbSwiIikKYTQtPTMKbT1l
+fWk9Imh0dHAifWVsc2UgaT1hMwplbHNlIGlmKHE9PT01JiZKLnEwKGE1LCJodHRwcyIsMCkpe2lmKHAm
+Jm4rND09PW0mJkoucTAoYTUsIjQ0MyIsbisxKSl7ay09NAplPW0tNApsLT00CmE1PUouZGcoYTUsbixt
+LCIiKQphNC09MwptPWV9aT0iaHR0cHMifWVsc2UgaT1hMwpqPSEwfX19ZWxzZSBpPWEzCmlmKGope3A9
+YTUubGVuZ3RoCmlmKGE0PHApe2E1PUoubGQoYTUsMCxhNCkKcS09MApvLT0wCm4tPTAKbS09MApsLT0w
+CmstPTB9cmV0dXJuIG5ldyBQLlVmKGE1LHEsbyxuLG0sbCxrLGkpfWlmKGk9PW51bGwpaWYocT4wKWk9
+UC5QaShhNSwwLHEpCmVsc2V7aWYocT09PTApUC5SMyhhNSwwLCJJbnZhbGlkIGVtcHR5IHNjaGVtZSIp
+Cmk9IiJ9aWYobz4wKXtkPXErMwpjPWQ8bz9QLnpSKGE1LGQsby0xKToiIgpiPVAuT2UoYTUsbyxuLCEx
+KQpwPW4rMQppZihwPG0pe2E9SC5IcChKLmxkKGE1LHAsbSksYTMpCmEwPVAud0IoYT09bnVsbD9ILnYo
+UC5ycigiSW52YWxpZCBwb3J0IixhNSxwKSk6YSxpKX1lbHNlIGEwPWEzfWVsc2V7YTA9YTMKYj1hMApj
+PSIifWExPVAua2EoYTUsbSxsLGEzLGksYiE9bnVsbCkKYTI9bDxrP1AubGUoYTUsbCsxLGssYTMpOmEz
+CnJldHVybiBuZXcgUC5EbihpLGMsYixhMCxhMSxhMixrPGE0P1AudEcoYTUsaysxLGE0KTphMyl9LApN
+dDpmdW5jdGlvbihhKXtILmgoYSkKcmV0dXJuIFAua3UoYSwwLGEubGVuZ3RoLEMueE0sITEpfSwKV1g6
+ZnVuY3Rpb24oYSl7dmFyIHM9dC5OCnJldHVybiBDLk5tLk4wKEguVk0oYS5zcGxpdCgiJiIpLHQucyks
+UC5GbChzLHMpLG5ldyBQLm4xKEMueE0pLHQuSil9LApIaDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixx
+LHAsbyxuLG0sbD0iSVB2NCBhZGRyZXNzIHNob3VsZCBjb250YWluIGV4YWN0bHkgNCBwYXJ0cyIsaz0i
+ZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIDAuLjI1NSIsaj1uZXcgUC5jUyhhKSxpPW5ldyBV
+aW50OEFycmF5KDQpCmZvcihzPWkubGVuZ3RoLHI9YixxPXIscD0wO3I8YzsrK3Ipe289Qy54Qi5tKGEs
+cikKaWYobyE9PTQ2KXtpZigob140OCk+OSlqLiQyKCJpbnZhbGlkIGNoYXJhY3RlciIscil9ZWxzZXtp
+ZihwPT09MylqLiQyKGwscikKbj1QLlFBKEMueEIuTmooYSxxLHIpLG51bGwpCmlmKG4+MjU1KWouJDIo
+ayxxKQptPXArMQppZihwPj1zKXJldHVybiBILk9IKGkscCkKaVtwXT1uCnE9cisxCnA9bX19aWYocCE9
+PTMpai4kMihsLGMpCm49UC5RQShDLnhCLk5qKGEscSxjKSxudWxsKQppZihuPjI1NSlqLiQyKGsscSkK
+aWYocD49cylyZXR1cm4gSC5PSChpLHApCmlbcF09bgpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYTAs
+YTEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGM9bmV3IFAuVkMoYSksYj1uZXcg
+UC5KVChjLGEpCmlmKGEubGVuZ3RoPDIpYy4kMSgiYWRkcmVzcyBpcyB0b28gc2hvcnQiKQpzPUguVk0o
+W10sdC5hKQpmb3Iocj1hMCxxPXIscD0hMSxvPSExO3I8YTE7KytyKXtuPUMueEIubShhLHIpCmlmKG49
+PT01OCl7aWYocj09PWEwKXsrK3IKaWYoQy54Qi5tKGEscikhPT01OCljLiQyKCJpbnZhbGlkIHN0YXJ0
+IGNvbG9uLiIscikKcT1yfWlmKHI9PT1xKXtpZihwKWMuJDIoIm9ubHkgb25lIHdpbGRjYXJkIGA6OmAg
+aXMgYWxsb3dlZCIscikKQy5ObS5pKHMsLTEpCnA9ITB9ZWxzZSBDLk5tLmkocyxiLiQyKHEscikpCnE9
+cisxfWVsc2UgaWYobj09PTQ2KW89ITB9aWYocy5sZW5ndGg9PT0wKWMuJDEoInRvbyBmZXcgcGFydHMi
+KQptPXE9PT1hMQpsPUMuTm0uZ3JaKHMpCmlmKG0mJmwhPT0tMSljLiQyKCJleHBlY3RlZCBhIHBhcnQg
+YWZ0ZXIgbGFzdCBgOmAiLGExKQppZighbSlpZighbylDLk5tLmkocyxiLiQyKHEsYTEpKQplbHNle2s9
+UC5IaChhLHEsYTEpCkMuTm0uaShzLChrWzBdPDw4fGtbMV0pPj4+MCkKQy5ObS5pKHMsKGtbMl08PDh8
+a1szXSk+Pj4wKX1pZihwKXtpZihzLmxlbmd0aD43KWMuJDEoImFuIGFkZHJlc3Mgd2l0aCBhIHdpbGRj
+YXJkIG11c3QgaGF2ZSBsZXNzIHRoYW4gNyBwYXJ0cyIpfWVsc2UgaWYocy5sZW5ndGghPT04KWMuJDEo
+ImFuIGFkZHJlc3Mgd2l0aG91dCBhIHdpbGRjYXJkIG11c3QgY29udGFpbiBleGFjdGx5IDggcGFydHMi
+KQpqPW5ldyBVaW50OEFycmF5KDE2KQpmb3IobD1zLmxlbmd0aCxpPWoubGVuZ3RoLGg9OS1sLHI9MCxn
+PTA7cjxsOysrcil7Zj1zW3JdCmlmKGY9PT0tMSlmb3IoZT0wO2U8aDsrK2Upe2lmKGc8MHx8Zz49aSly
+ZXR1cm4gSC5PSChqLGcpCmpbZ109MApkPWcrMQppZihkPj1pKXJldHVybiBILk9IKGosZCkKaltkXT0w
+CmcrPTJ9ZWxzZXtkPUMuam4ud0coZiw4KQppZihnPDB8fGc+PWkpcmV0dXJuIEguT0goaixnKQpqW2dd
+PWQKZD1nKzEKaWYoZD49aSlyZXR1cm4gSC5PSChqLGQpCmpbZF09ZiYyNTUKZys9Mn19cmV0dXJuIGp9
+LApLTDpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2YXIgcyxyLHEscCxvLG4KZj1mPT1udWxsPyIiOlAu
+UGkoZiwwLGYubGVuZ3RoKQpnPVAuelIoZywwLGc9PW51bGw/MDpnLmxlbmd0aCkKYT1QLk9lKGEsMCxh
+PT1udWxsPzA6YS5sZW5ndGgsITEpCnM9UC5sZShudWxsLDAsMCxlKQpyPVAudEcobnVsbCwwLDApCmQ9
+UC53QihkLGYpCnE9Zj09PSJmaWxlIgppZihhPT1udWxsKXA9Zy5sZW5ndGghPT0wfHxkIT1udWxsfHxx
+CmVsc2UgcD0hMQppZihwKWE9IiIKcD1hPT1udWxsCm89IXAKYj1QLmthKGIsMCxiPT1udWxsPzA6Yi5s
+ZW5ndGgsYyxmLG8pCm49Zi5sZW5ndGg9PT0wCmlmKG4mJnAmJiFDLnhCLm4oYiwiLyIpKWI9UC53Rihi
+LCFufHxvKQplbHNlIGI9UC54ZShiKQpyZXR1cm4gbmV3IFAuRG4oZixnLHAmJkMueEIubihiLCIvLyIp
+PyIiOmEsZCxiLHMscil9LAp3SzpmdW5jdGlvbihhKXtpZihhPT09Imh0dHAiKXJldHVybiA4MAppZihh
+PT09Imh0dHBzIilyZXR1cm4gNDQzCnJldHVybiAwfSwKUjM6ZnVuY3Rpb24oYSxiLGMpe3Rocm93IEgu
+YihQLnJyKGMsYSxiKSl9LApYZDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHEscCxvLG4sbSxsLGss
+aixpLGg9bnVsbCxnPWIubGVuZ3RoCmlmKGchPT0wKXtxPTAKd2hpbGUoITApe2lmKCEocTxnKSl7cz0i
+IgpyPTAKYnJlYWt9aWYoQy54Qi5XKGIscSk9PT02NCl7cz1DLnhCLk5qKGIsMCxxKQpyPXErMQpicmVh
+a30rK3F9aWYocjxnJiZDLnhCLlcoYixyKT09PTkxKXtmb3IocD1yLG89LTE7cDxnOysrcCl7bj1DLnhC
+LlcoYixwKQppZihuPT09MzcmJm88MCl7bT1DLnhCLlFpKGIsIjI1IixwKzEpP3ArMjpwCm89cApwPW19
+ZWxzZSBpZihuPT09OTMpYnJlYWt9aWYocD09PWcpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgSVB2NiBo
+b3N0IGVudHJ5LiIsYixyKSkKbD1vPDA/cDpvClAuZWcoYixyKzEsbCk7KytwCmlmKHAhPT1nJiZDLnhC
+LlcoYixwKSE9PTU4KXRocm93IEguYihQLnJyKCJJbnZhbGlkIGVuZCBvZiBhdXRob3JpdHkiLGIscCkp
+fWVsc2UgcD1yCndoaWxlKCEwKXtpZighKHA8Zykpe2s9aApicmVha31pZihDLnhCLlcoYixwKT09PTU4
+KXtqPUMueEIuRyhiLHArMSkKaz1qLmxlbmd0aCE9PTA/UC5RQShqLGgpOmgKYnJlYWt9KytwfWk9Qy54
+Qi5OaihiLHIscCl9ZWxzZXtrPWgKaT1rCnM9IiJ9cmV0dXJuIFAuS0woaSxoLEguVk0oYy5zcGxpdCgi
+LyIpLHQucyksayxkLGEscyl9LAprRTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8KZm9yKHM9YS5s
+ZW5ndGgscj0wO3I8czsrK3Ipe3E9YVtyXQpxLnRvU3RyaW5nCnA9Si5VNihxKQpvPXAuZ0EocSkKaWYo
+MD5vKUgudihQLlRFKDAsMCxwLmdBKHEpLG51bGwsbnVsbCkpCmlmKEgubTIocSwiLyIsMCkpe3M9UC5M
+NCgiSWxsZWdhbCBwYXRoIGNoYXJhY3RlciAiK0guRWoocSkpCnRocm93IEguYihzKX19fSwKSE46ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzLHIscQpmb3Iocz1ILnFDKGEsYyxudWxsLEgudDYoYSkuYykscz1uZXcg
+SC5hNyhzLHMuZ0Eocykscy4kdGkuQygiYTc8YUwuRT4iKSk7cy5GKCk7KXtyPXMuZApxPVAubnUoJ1si
+Ki86PD4/XFxcXHxdJykKci50b1N0cmluZwppZihILm0yKHIscSwwKSl7cz1QLkw0KCJJbGxlZ2FsIGNo
+YXJhY3RlciBpbiBwYXRoOiAiK3IpCnRocm93IEguYihzKX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIg
+cwppZighKDY1PD1hJiZhPD05MCkpcz05Nzw9YSYmYTw9MTIyCmVsc2Ugcz0hMAppZihzKXJldHVybgpz
+PVAuTDQoIklsbGVnYWwgZHJpdmUgbGV0dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5iKHMpfSwKd0I6ZnVu
+Y3Rpb24oYSxiKXtpZihhIT1udWxsJiZhPT09UC53SyhiKSlyZXR1cm4gbnVsbApyZXR1cm4gYX0sCk9l
+OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbgppZihhPT1udWxsKXJldHVybiBudWxsCmlm
+KGI9PT1jKXJldHVybiIiCmlmKEMueEIubShhLGIpPT09OTEpe3M9Yy0xCmlmKEMueEIubShhLHMpIT09
+OTMpUC5SMyhhLGIsIk1pc3NpbmcgZW5kIGBdYCB0byBtYXRjaCBgW2AgaW4gaG9zdCIpCnI9YisxCnE9
+UC50byhhLHIscykKaWYocTxzKXtwPXErMQpvPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixwKT9xKzM6cCxz
+LCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLHIscSkKcmV0dXJuIEMueEIuTmooYSxiLHEpLnRvTG93ZXJD
+YXNlKCkrbysiXSJ9Zm9yKG49YjtuPGM7KytuKWlmKEMueEIubShhLG4pPT09NTgpe3E9Qy54Qi5YVShh
+LCIlIixiKQpxPXE+PWImJnE8Yz9xOmMKaWYocTxjKXtwPXErMQpvPVAuT0EoYSxDLnhCLlFpKGEsIjI1
+IixwKT9xKzM6cCxjLCIlMjUiKX1lbHNlIG89IiIKUC5lZyhhLGIscSkKcmV0dXJuIlsiK0MueEIuTmoo
+YSxiLHEpK28rIl0ifXJldHVybiBQLk9MKGEsYixjKX0sCnRvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1D
+LnhCLlhVKGEsIiUiLGIpCnJldHVybiBzPj1iJiZzPGM/czpjfSwKT0E6ZnVuY3Rpb24oYSxiLGMsZCl7
+dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaT1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbApmb3Iocz1iLHI9
+cyxxPSEwO3M8Yzspe3A9Qy54Qi5tKGEscykKaWYocD09PTM3KXtvPVAucnYoYSxzLCEwKQpuPW89PW51
+bGwKaWYobiYmcSl7cys9Mwpjb250aW51ZX1pZihpPT1udWxsKWk9bmV3IFAuUm4oIiIpCm09aS5hKz1D
+LnhCLk5qKGEscixzKQppZihuKW89Qy54Qi5OaihhLHMscyszKQplbHNlIGlmKG89PT0iJSIpUC5SMyhh
+LHMsIlpvbmVJRCBzaG91bGQgbm90IGNvbnRhaW4gJSBhbnltb3JlIikKaS5hPW0rbwpzKz0zCnI9cwpx
+PSEwfWVsc2V7aWYocDwxMjcpe249cD4+PjQKaWYobj49OClyZXR1cm4gSC5PSChDLkYzLG4pCm49KEMu
+RjNbbl0mMTw8KHAmMTUpKSE9PTB9ZWxzZSBuPSExCmlmKG4pe2lmKHEmJjY1PD1wJiY5MD49cCl7aWYo
+aT09bnVsbClpPW5ldyBQLlJuKCIiKQppZihyPHMpe2kuYSs9Qy54Qi5OaihhLHIscykKcj1zfXE9ITF9
+KytzfWVsc2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnMrMTxjKXtsPUMueEIubShhLHMrMSkKaWYoKGwm
+NjQ1MTIpPT09NTYzMjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGwmMTAyMwprPTJ9ZWxzZSBrPTF9ZWxz
+ZSBrPTEKaj1DLnhCLk5qKGEscixzKQppZihpPT1udWxsKXtpPW5ldyBQLlJuKCIiKQpuPWl9ZWxzZSBu
+PWkKbi5hKz1qCm4uYSs9UC56WChwKQpzKz1rCnI9c319fWlmKGk9PW51bGwpcmV0dXJuIEMueEIuTmoo
+YSxiLGMpCmlmKHI8YylpLmErPUMueEIuTmooYSxyLGMpCm49aS5hCnJldHVybiBuLmNoYXJDb2RlQXQo
+MCk9PTA/bjpufSwKT0w6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGkKZm9y
+KHM9YixyPXMscT1udWxsLHA9ITA7czxjOyl7bz1DLnhCLm0oYSxzKQppZihvPT09Mzcpe249UC5ydihh
+LHMsITApCm09bj09bnVsbAppZihtJiZwKXtzKz0zCmNvbnRpbnVlfWlmKHE9PW51bGwpcT1uZXcgUC5S
+bigiIikKbD1DLnhCLk5qKGEscixzKQprPXEuYSs9IXA/bC50b0xvd2VyQ2FzZSgpOmwKaWYobSl7bj1D
+LnhCLk5qKGEscyxzKzMpCmo9M31lbHNlIGlmKG49PT0iJSIpe249IiUyNSIKaj0xfWVsc2Ugaj0zCnEu
+YT1rK24Kcys9agpyPXMKcD0hMH1lbHNle2lmKG88MTI3KXttPW8+Pj40CmlmKG0+PTgpcmV0dXJuIEgu
+T0goQy5lYSxtKQptPShDLmVhW21dJjE8PChvJjE1KSkhPT0wfWVsc2UgbT0hMQppZihtKXtpZihwJiY2
+NTw9byYmOTA+PW8pe2lmKHE9PW51bGwpcT1uZXcgUC5SbigiIikKaWYocjxzKXtxLmErPUMueEIuTmoo
+YSxyLHMpCnI9c31wPSExfSsrc31lbHNle2lmKG88PTkzKXttPW8+Pj40CmlmKG0+PTgpcmV0dXJuIEgu
+T0goQy5hayxtKQptPShDLmFrW21dJjE8PChvJjE1KSkhPT0wfWVsc2UgbT0hMQppZihtKVAuUjMoYSxz
+LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYoKG8mNjQ1MTIpPT09NTUyOTYmJnMrMTxjKXtpPUMu
+eEIubShhLHMrMSkKaWYoKGkmNjQ1MTIpPT09NTYzMjApe289NjU1MzZ8KG8mMTAyMyk8PDEwfGkmMTAy
+MwpqPTJ9ZWxzZSBqPTF9ZWxzZSBqPTEKbD1DLnhCLk5qKGEscixzKQppZighcClsPWwudG9Mb3dlckNh
+c2UoKQppZihxPT1udWxsKXtxPW5ldyBQLlJuKCIiKQptPXF9ZWxzZSBtPXEKbS5hKz1sCm0uYSs9UC56
+WChvKQpzKz1qCnI9c319fX1pZihxPT1udWxsKXJldHVybiBDLnhCLk5qKGEsYixjKQppZihyPGMpe2w9
+Qy54Qi5OaihhLHIsYykKcS5hKz0hcD9sLnRvTG93ZXJDYXNlKCk6bH1tPXEuYQpyZXR1cm4gbS5jaGFy
+Q29kZUF0KDApPT0wP206bX0sClBpOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEscAppZihiPT09Yyly
+ZXR1cm4iIgppZighUC5FdChKLnJZKGEpLlcoYSxiKSkpUC5SMyhhLGIsIlNjaGVtZSBub3Qgc3RhcnRp
+bmcgd2l0aCBhbHBoYWJldGljIGNoYXJhY3RlciIpCmZvcihzPWIscj0hMTtzPGM7KytzKXtxPUMueEIu
+VyhhLHMpCmlmKHE8MTI4KXtwPXE+Pj40CmlmKHA+PTgpcmV0dXJuIEguT0goQy5tSyxwKQpwPShDLm1L
+W3BdJjE8PChxJjE1KSkhPT0wfWVsc2UgcD0hMQppZighcClQLlIzKGEscywiSWxsZWdhbCBzY2hlbWUg
+Y2hhcmFjdGVyIikKaWYoNjU8PXEmJnE8PTkwKXI9ITB9YT1DLnhCLk5qKGEsYixjKQpyZXR1cm4gUC5Z
+YShyP2EudG9Mb3dlckNhc2UoKTphKX0sCllhOmZ1bmN0aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJu
+Imh0dHAiCmlmKGE9PT0iZmlsZSIpcmV0dXJuImZpbGUiCmlmKGE9PT0iaHR0cHMiKXJldHVybiJodHRw
+cyIKaWYoYT09PSJwYWNrYWdlIilyZXR1cm4icGFja2FnZSIKcmV0dXJuIGF9LAp6UjpmdW5jdGlvbihh
+LGIsYyl7aWYoYT09bnVsbClyZXR1cm4iIgpyZXR1cm4gUC5QSShhLGIsYyxDLnRvLCExKX0sCmthOmZ1
+bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIgcyxyLHE9ZT09PSJmaWxlIixwPXF8fGYKaWYoYT09bnVsbCl7
+aWYoZD09bnVsbClyZXR1cm4gcT8iLyI6IiIKcz1ILnQ2KGQpCnI9bmV3IEgubEooZCxzLkMoInFVKDEp
+IikuYShuZXcgUC5SWigpKSxzLkMoImxKPDEscVU+IikpLkgoMCwiLyIpfWVsc2UgaWYoZCE9bnVsbCl0
+aHJvdyBILmIoUC54WSgiQm90aCBwYXRoIGFuZCBwYXRoU2VnbWVudHMgc3BlY2lmaWVkIikpCmVsc2Ug
+cj1QLlBJKGEsYixjLEMuV2QsITApCmlmKHIubGVuZ3RoPT09MCl7aWYocSlyZXR1cm4iLyJ9ZWxzZSBp
+ZihwJiYhQy54Qi5uKHIsIi8iKSlyPSIvIityCnJldHVybiBQLkpyKHIsZSxmKX0sCkpyOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgcz1iLmxlbmd0aD09PTAKaWYocyYmIWMmJiFDLnhCLm4oYSwiLyIpKXJldHVybiBQ
+LndGKGEsIXN8fGMpCnJldHVybiBQLnhlKGEpfSwKbGU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscj17
+fQppZihhIT1udWxsKXtpZihkIT1udWxsKXRocm93IEguYihQLnhZKCJCb3RoIHF1ZXJ5IGFuZCBxdWVy
+eVBhcmFtZXRlcnMgc3BlY2lmaWVkIikpCnJldHVybiBQLlBJKGEsYixjLEMuVkMsITApfWlmKGQ9PW51
+bGwpcmV0dXJuIG51bGwKcz1uZXcgUC5SbigiIikKci5hPSIiCmQuSygwLG5ldyBQLnk1KG5ldyBQLk1F
+KHIscykpKQpyPXMuYQpyZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn0sCnRHOmZ1bmN0aW9uKGEs
+YixjKXtpZihhPT1udWxsKXJldHVybiBudWxsCnJldHVybiBQLlBJKGEsYixjLEMuVkMsITApfSwKcnY6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbj1iKzIKaWYobj49YS5sZW5ndGgpcmV0dXJuIiUi
+CnM9Qy54Qi5tKGEsYisxKQpyPUMueEIubShhLG4pCnE9SC5vbyhzKQpwPUgub28ocikKaWYocTwwfHxw
+PDApcmV0dXJuIiUiCm89cSoxNitwCmlmKG88MTI3KXtuPUMuam4ud0cobyw0KQppZihuPj04KXJldHVy
+biBILk9IKEMuRjMsbikKbj0oQy5GM1tuXSYxPDwobyYxNSkpIT09MH1lbHNlIG49ITEKaWYobilyZXR1
+cm4gSC5MdyhjJiY2NTw9byYmOTA+PW8/KG98MzIpPj4+MDpvKQppZihzPj05N3x8cj49OTcpcmV0dXJu
+IEMueEIuTmooYSxiLGIrMykudG9VcHBlckNhc2UoKQpyZXR1cm4gbnVsbH0sCnpYOmZ1bmN0aW9uKGEp
+e3ZhciBzLHIscSxwLG8sbixtLGwsaz0iMDEyMzQ1Njc4OUFCQ0RFRiIKaWYoYTwxMjgpe3M9bmV3IFVp
+bnQ4QXJyYXkoMykKcj1zLmxlbmd0aAppZigwPj1yKXJldHVybiBILk9IKHMsMCkKc1swXT0zNwpxPUMu
+eEIuVyhrLGE+Pj40KQppZigxPj1yKXJldHVybiBILk9IKHMsMSkKc1sxXT1xCnE9Qy54Qi5XKGssYSYx
+NSkKaWYoMj49cilyZXR1cm4gSC5PSChzLDIpCnNbMl09cX1lbHNle2lmKGE+MjA0NylpZihhPjY1NTM1
+KXtwPTI0MApvPTR9ZWxzZXtwPTIyNApvPTN9ZWxzZXtwPTE5MgpvPTJ9cz1uZXcgVWludDhBcnJheSgz
+Km8pCmZvcihyPXMubGVuZ3RoLG49MDstLW8sbz49MDtwPTEyOCl7bT1DLmpuLmJmKGEsNipvKSY2M3xw
+CmlmKG4+PXIpcmV0dXJuIEguT0gocyxuKQpzW25dPTM3CnE9bisxCmw9Qy54Qi5XKGssbT4+PjQpCmlm
+KHE+PXIpcmV0dXJuIEguT0gocyxxKQpzW3FdPWwKbD1uKzIKcT1DLnhCLlcoayxtJjE1KQppZihsPj1y
+KXJldHVybiBILk9IKHMsbCkKc1tsXT1xCm4rPTN9fXJldHVybiBQLkhNKHMsMCxudWxsKX0sClBJOmZ1
+bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9UC5VbChhLGIsYyxkLGUpCnJldHVybiBzPT1udWxsP0MueEIu
+TmooYSxiLGMpOnN9LApVbDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzLHIscSxwLG8sbixtLGwsayxq
+PW51bGwKZm9yKHM9IWUscj1iLHE9cixwPWo7cjxjOyl7bz1DLnhCLm0oYSxyKQppZihvPDEyNyl7bj1v
+Pj4+NAppZihuPj04KXJldHVybiBILk9IKGQsbikKbj0oZFtuXSYxPDwobyYxNSkpIT09MH1lbHNlIG49
+ITEKaWYobikrK3IKZWxzZXtpZihvPT09Mzcpe209UC5ydihhLHIsITEpCmlmKG09PW51bGwpe3IrPTMK
+Y29udGludWV9aWYoIiUiPT09bSl7bT0iJTI1IgpsPTF9ZWxzZSBsPTN9ZWxzZXtpZihzKWlmKG88PTkz
+KXtuPW8+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5hayxuKQpuPShDLmFrW25dJjE8PChvJjE1KSkh
+PT0wfWVsc2Ugbj0hMQplbHNlIG49ITEKaWYobil7UC5SMyhhLHIsIkludmFsaWQgY2hhcmFjdGVyIikK
+bD1qCm09bH1lbHNle2lmKChvJjY0NTEyKT09PTU1Mjk2KXtuPXIrMQppZihuPGMpe2s9Qy54Qi5tKGEs
+bikKaWYoKGsmNjQ1MTIpPT09NTYzMjApe289NjU1MzZ8KG8mMTAyMyk8PDEwfGsmMTAyMwpsPTJ9ZWxz
+ZSBsPTF9ZWxzZSBsPTF9ZWxzZSBsPTEKbT1QLnpYKG8pfX1pZihwPT1udWxsKXtwPW5ldyBQLlJuKCIi
+KQpuPXB9ZWxzZSBuPXAKbi5hKz1DLnhCLk5qKGEscSxyKQpuLmErPUguRWoobSkKaWYodHlwZW9mIGwh
+PT0ibnVtYmVyIilyZXR1cm4gSC5wWShsKQpyKz1sCnE9cn19aWYocD09bnVsbClyZXR1cm4gagppZihx
+PGMpcC5hKz1DLnhCLk5qKGEscSxjKQpzPXAuYQpyZXR1cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c30s
+CnlCOmZ1bmN0aW9uKGEpe2lmKEMueEIubihhLCIuIikpcmV0dXJuITAKcmV0dXJuIEMueEIuT1koYSwi
+Ly4iKSE9PS0xfSwKeGU6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0KaWYoIVAueUIoYSkpcmV0
+dXJuIGEKcz1ILlZNKFtdLHQucykKZm9yKHI9YS5zcGxpdCgiLyIpLHE9ci5sZW5ndGgscD0hMSxvPTA7
+bzxxOysrbyl7bj1yW29dCmlmKEouUk0obiwiLi4iKSl7bT1zLmxlbmd0aAppZihtIT09MCl7aWYoMD49
+bSlyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCmlmKHMubGVuZ3RoPT09MClDLk5tLmkocywiIil9cD0h
+MH1lbHNlIGlmKCIuIj09PW4pcD0hMAplbHNle0MuTm0uaShzLG4pCnA9ITF9fWlmKHApQy5ObS5pKHMs
+IiIpCnJldHVybiBDLk5tLkgocywiLyIpfSwKd0Y6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4K
+aWYoIVAueUIoYSkpcmV0dXJuIWI/UC5DMShhKTphCnM9SC5WTShbXSx0LnMpCmZvcihyPWEuc3BsaXQo
+Ii8iKSxxPXIubGVuZ3RoLHA9ITEsbz0wO288cTsrK28pe249cltvXQppZigiLi4iPT09bilpZihzLmxl
+bmd0aCE9PTAmJkMuTm0uZ3JaKHMpIT09Ii4uIil7aWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywt
+MSkKcy5wb3AoKQpwPSEwfWVsc2V7Qy5ObS5pKHMsIi4uIikKcD0hMX1lbHNlIGlmKCIuIj09PW4pcD0h
+MAplbHNle0MuTm0uaShzLG4pCnA9ITF9fXI9cy5sZW5ndGgKaWYociE9PTApaWYocj09PTEpe2lmKDA+
+PXIpcmV0dXJuIEguT0gocywwKQpyPXNbMF0ubGVuZ3RoPT09MH1lbHNlIHI9ITEKZWxzZSByPSEwCmlm
+KHIpcmV0dXJuIi4vIgppZihwfHxDLk5tLmdyWihzKT09PSIuLiIpQy5ObS5pKHMsIiIpCmlmKCFiKXtp
+ZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDApCkMuTm0uWShzLDAsUC5DMShzWzBdKSl9cmV0dXJu
+IEMuTm0uSChzLCIvIil9LApDMTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1hLmxlbmd0aAppZihwPj0y
+JiZQLkV0KEouUXooYSwwKSkpZm9yKHM9MTtzPHA7KytzKXtyPUMueEIuVyhhLHMpCmlmKHI9PT01OCly
+ZXR1cm4gQy54Qi5OaihhLDAscykrIiUzQSIrQy54Qi5HKGEscysxKQppZihyPD0xMjcpe3E9cj4+PjQK
+aWYocT49OClyZXR1cm4gSC5PSChDLm1LLHEpCnE9KEMubUtbcV0mMTw8KHImMTUpKT09PTB9ZWxzZSBx
+PSEwCmlmKHEpYnJlYWt9cmV0dXJuIGF9LAptbjpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1hLmdGaigp
+LG89cC5sZW5ndGgKaWYobz4wJiZKLkhtKHBbMF0pPT09MiYmSi5hNihwWzBdLDEpPT09NTgpe2lmKDA+
+PW8pcmV0dXJuIEguT0gocCwwKQpQLnJnKEouYTYocFswXSwwKSwhMSkKUC5ITihwLCExLDEpCnM9ITB9
+ZWxzZXtQLkhOKHAsITEsMCkKcz0hMX1yPWEuZ3RUKCkmJiFzPyJcXCI6IiIKaWYoYS5nY2ooKSl7cT1h
+LmdKZihhKQppZihxLmxlbmd0aCE9PTApcj1yKyJcXCIrcSsiXFwifXI9UC52ZyhyLHAsIlxcIikKbz1z
+JiZvPT09MT9yKyJcXCI6cgpyZXR1cm4gby5jaGFyQ29kZUF0KDApPT0wP286b30sCkloOmZ1bmN0aW9u
+KGEsYil7dmFyIHMscixxCmZvcihzPTAscj0wO3I8MjsrK3Ipe3E9Qy54Qi5XKGEsYityKQppZig0ODw9
+cSYmcTw9NTcpcz1zKjE2K3EtNDgKZWxzZXtxfD0zMgppZig5Nzw9cSYmcTw9MTAyKXM9cyoxNitxLTg3
+CmVsc2UgdGhyb3cgSC5iKFAueFkoIkludmFsaWQgVVJMIGVuY29kaW5nIikpfX1yZXR1cm4gc30sCmt1
+OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHMscixxLHAsbz1KLnJZKGEpLG49Ygp3aGlsZSghMCl7aWYo
+IShuPGMpKXtzPSEwCmJyZWFrfXI9by5XKGEsbikKaWYocjw9MTI3KWlmKHIhPT0zNylxPWUmJnI9PT00
+MwplbHNlIHE9ITAKZWxzZSBxPSEwCmlmKHEpe3M9ITEKYnJlYWt9KytufWlmKHMpe2lmKEMueE0hPT1k
+KXE9ITEKZWxzZSBxPSEwCmlmKHEpcmV0dXJuIG8uTmooYSxiLGMpCmVsc2UgcD1uZXcgSC5xaihvLk5q
+KGEsYixjKSl9ZWxzZXtwPUguVk0oW10sdC5hKQpmb3Iobj1iO248YzsrK24pe3I9by5XKGEsbikKaWYo
+cj4xMjcpdGhyb3cgSC5iKFAueFkoIklsbGVnYWwgcGVyY2VudCBlbmNvZGluZyBpbiBVUkkiKSkKaWYo
+cj09PTM3KXtpZihuKzM+YS5sZW5ndGgpdGhyb3cgSC5iKFAueFkoIlRydW5jYXRlZCBVUkkiKSkKQy5O
+bS5pKHAsUC5JaChhLG4rMSkpCm4rPTJ9ZWxzZSBpZihlJiZyPT09NDMpQy5ObS5pKHAsMzIpCmVsc2Ug
+Qy5ObS5pKHAscil9fXQuTC5hKHApCnJldHVybiBDLm9FLldKKHApfSwKRXQ6ZnVuY3Rpb24oYSl7dmFy
+IHM9YXwzMgpyZXR1cm4gOTc8PXMmJnM8PTEyMn0sCktEOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyLHEs
+cCxvLG4sbSxsLGs9IkludmFsaWQgTUlNRSB0eXBlIixqPUguVk0oW2ItMV0sdC5hKQpmb3Iocz1hLmxl
+bmd0aCxyPWIscT0tMSxwPW51bGw7cjxzOysrcil7cD1DLnhCLlcoYSxyKQppZihwPT09NDR8fHA9PT01
+OSlicmVhawppZihwPT09NDcpe2lmKHE8MCl7cT1yCmNvbnRpbnVlfXRocm93IEguYihQLnJyKGssYSxy
+KSl9fWlmKHE8MCYmcj5iKXRocm93IEguYihQLnJyKGssYSxyKSkKZm9yKDtwIT09NDQ7KXtDLk5tLmko
+aixyKTsrK3IKZm9yKG89LTE7cjxzOysrcil7cD1DLnhCLlcoYSxyKQppZihwPT09NjEpe2lmKG88MClv
+PXJ9ZWxzZSBpZihwPT09NTl8fHA9PT00NClicmVha31pZihvPj0wKUMuTm0uaShqLG8pCmVsc2V7bj1D
+Lk5tLmdyWihqKQppZihwIT09NDR8fHIhPT1uKzd8fCFDLnhCLlFpKGEsImJhc2U2NCIsbisxKSl0aHJv
+dyBILmIoUC5ycigiRXhwZWN0aW5nICc9JyIsYSxyKSkKYnJlYWt9fUMuTm0uaShqLHIpCm09cisxCmlm
+KChqLmxlbmd0aCYxKT09PTEpYT1DLmg5LnlyKGEsbSxzKQplbHNle2w9UC5VbChhLG0scyxDLlZDLCEw
+KQppZihsIT1udWxsKWE9Qy54Qi5pNyhhLG0scyxsKX1yZXR1cm4gbmV3IFAuUEUoYSxqLGMpfSwKS046
+ZnVuY3Rpb24oKXt2YXIgcz0iMDEyMzQ1Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVm
+Z2hpamtsbW5vcHFyc3R1dnd4eXotLl9+ISQmJygpKissOz0iLHI9Ii4iLHE9IjoiLHA9Ii8iLG89Ij8i
+LG49IiMiLG09UC5kSCgyMixuZXcgUC5xMygpLHQuZ2MpLGw9bmV3IFAueUkobSksaz1uZXcgUC5jNigp
+LGo9bmV3IFAucWQoKSxpPWwuJDIoMCwyMjUpCmsuJDMoaSxzLDEpCmsuJDMoaSxyLDE0KQprLiQzKGks
+cSwzNCkKay4kMyhpLHAsMykKay4kMyhpLG8sMTcyKQprLiQzKGksbiwyMDUpCmk9bC4kMigxNCwyMjUp
+CmsuJDMoaSxzLDEpCmsuJDMoaSxyLDE1KQprLiQzKGkscSwzNCkKay4kMyhpLHAsMjM0KQprLiQzKGks
+bywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDE1LDIyNSkKay4kMyhpLHMsMSkKay4kMyhpLCIlIiwy
+MjUpCmsuJDMoaSxxLDM0KQprLiQzKGkscCw5KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1s
+LiQyKDEsMjI1KQprLiQzKGkscywxKQprLiQzKGkscSwzNCkKay4kMyhpLHAsMTApCmsuJDMoaSxvLDE3
+MikKay4kMyhpLG4sMjA1KQppPWwuJDIoMiwyMzUpCmsuJDMoaSxzLDEzOSkKay4kMyhpLHAsMTMxKQpr
+LiQzKGksciwxNDYpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoMywyMzUpCmsuJDMo
+aSxzLDExKQprLiQzKGkscCw2OCkKay4kMyhpLHIsMTgpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1
+KQppPWwuJDIoNCwyMjkpCmsuJDMoaSxzLDUpCmouJDMoaSwiQVoiLDIyOSkKay4kMyhpLHEsMTAyKQpr
+LiQzKGksIkAiLDY4KQprLiQzKGksIlsiLDIzMikKay4kMyhpLHAsMTM4KQprLiQzKGksbywxNzIpCmsu
+JDMoaSxuLDIwNSkKaT1sLiQyKDUsMjI5KQprLiQzKGkscyw1KQpqLiQzKGksIkFaIiwyMjkpCmsuJDMo
+aSxxLDEwMikKay4kMyhpLCJAIiw2OCkKay4kMyhpLHAsMTM4KQprLiQzKGksbywxNzIpCmsuJDMoaSxu
+LDIwNSkKaT1sLiQyKDYsMjMxKQpqLiQzKGksIjE5Iiw3KQprLiQzKGksIkAiLDY4KQprLiQzKGkscCwx
+MzgpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQppPWwuJDIoNywyMzEpCmouJDMoaSwiMDkiLDcp
+CmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxwLDEzOCkKay4kMyhpLG8sMTcyKQprLiQzKGksbiwyMDUpCmsu
+JDMobC4kMig4LDgpLCJdIiw1KQppPWwuJDIoOSwyMzUpCmsuJDMoaSxzLDExKQprLiQzKGksciwxNikK
+ay4kMyhpLHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDE2LDIzNSkKay4k
+MyhpLHMsMTEpCmsuJDMoaSxyLDE3KQprLiQzKGkscCwyMzQpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4s
+MjA1KQppPWwuJDIoMTcsMjM1KQprLiQzKGkscywxMSkKay4kMyhpLHAsOSkKay4kMyhpLG8sMTcyKQpr
+LiQzKGksbiwyMDUpCmk9bC4kMigxMCwyMzUpCmsuJDMoaSxzLDExKQprLiQzKGksciwxOCkKay4kMyhp
+LHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDE4LDIzNSkKay4kMyhpLHMs
+MTEpCmsuJDMoaSxyLDE5KQprLiQzKGkscCwyMzQpCmsuJDMoaSxvLDE3MikKay4kMyhpLG4sMjA1KQpp
+PWwuJDIoMTksMjM1KQprLiQzKGkscywxMSkKay4kMyhpLHAsMjM0KQprLiQzKGksbywxNzIpCmsuJDMo
+aSxuLDIwNSkKaT1sLiQyKDExLDIzNSkKay4kMyhpLHMsMTEpCmsuJDMoaSxwLDEwKQprLiQzKGksbywx
+NzIpCmsuJDMoaSxuLDIwNSkKaT1sLiQyKDEyLDIzNikKay4kMyhpLHMsMTIpCmsuJDMoaSxvLDEyKQpr
+LiQzKGksbiwyMDUpCmk9bC4kMigxMywyMzcpCmsuJDMoaSxzLDEzKQprLiQzKGksbywxMykKai4kMyhs
+LiQyKDIwLDI0NSksImF6IiwyMSkKaT1sLiQyKDIxLDI0NSkKai4kMyhpLCJheiIsMjEpCmouJDMoaSwi
+MDkiLDIxKQprLiQzKGksIistLiIsMjEpCnJldHVybiBtfSwKVUI6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
+YXIgcyxyLHEscCxvLG49JC52WigpCmZvcihzPUouclkoYSkscj1iO3I8YzsrK3Ipe24ubGVuZ3RoCmlm
+KGQ8MHx8ZD49MjIpcmV0dXJuIEguT0gobixkKQpxPW5bZF0KcD1zLlcoYSxyKV45NgppZihwPjk1KXA9
+MzEKaWYocD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSxwKQpvPXFbcF0KZD1vJjMxCkMuTm0uWShlLG8+
+Pj41LHIpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmlQ
+OmZ1bmN0aW9uIGlQKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApYUzpmdW5jdGlvbiBYUygpe30sCkM2
+OmZ1bmN0aW9uIEM2KGEpe3RoaXMuYT1hfSwKRXo6ZnVuY3Rpb24gRXooKXt9LApGOmZ1bmN0aW9uIEYo
+KXt9LAp1OmZ1bmN0aW9uIHUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9
+ZH0sCmJKOmZ1bmN0aW9uIGJKKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uZT1hCl8uZj1iCl8uYT1j
+Cl8uYj1kCl8uYz1lCl8uZD1mfSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8u
+Zj1hCl8uYT1iCl8uYj1jCl8uYz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAoYSxiLGMsZCl7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHViKGEpe3RoaXMuYT1hfSwK
+ZHM6ZnVuY3Rpb24gZHMoYSl7dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihhKXt0aGlzLmE9YX0sClVW
+OmZ1bmN0aW9uIFVWKGEpe3RoaXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9LApLWTpmdW5jdGlvbiBL
+WSgpe30sCnA6ZnVuY3Rpb24gcChhKXt0aGlzLmE9YX0sCkNEOmZ1bmN0aW9uIENEKGEpe3RoaXMuYT1h
+fSwKYUU6ZnVuY3Rpb24gYUUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKY1g6ZnVu
+Y3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBBbigpe30sCk4zOmZ1bmN0aW9uIE4zKGEsYixjKXt0aGlz
+LmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKYzg6ZnVuY3Rpb24gYzgoKXt9LApNaDpmdW5jdGlvbiBN
+aCgpe30sClpkOmZ1bmN0aW9uIFpkKCl7fSwKUm46ZnVuY3Rpb24gUm4oYSl7dGhpcy5hPWF9LApuMTpm
+dW5jdGlvbiBuMShhKXt0aGlzLmE9YX0sCmNTOmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVu
+Y3Rpb24gVkMoYSl7dGhpcy5hPWF9LApKVDpmdW5jdGlvbiBKVChhLGIpe3RoaXMuYT1hCnRoaXMuYj1i
+fSwKRG46ZnVuY3Rpb24gRG4oYSxiLGMsZCxlLGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9
+YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9ZwpfLlE9Xy56PV8ueT1fLng9bnVsbH0sClJaOmZ1bmN0aW9u
+IFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9u
+IHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRo
+aXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2
+OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxk
+LGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5y
+PWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlz
+Cl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1u
+dWxsfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApqZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMu
+Yj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJm
+KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBczpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdF
+KGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24gTjcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVROmZ1
+bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24gaEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
+cyxyLHEKSC55OChiKQp0LmouYShkKQppZihILm9UKGIpKXtzPVtjXQpDLk5tLkZWKHMsZCkKZD1zfXI9
+dC56CnE9UC5DSChKLk0xKGQsUC53MCgpLHIpLCEwLHIpCnQuWS5hKGEpCnJldHVybiBQLndZKEguRWso
+YSxxLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEsYixjKXt2YXIgcwp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5z
+aWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3Qu
+ZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHMpe0guUnUocyl9cmV0
+dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHku
+Y2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVybiBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVs
+bHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fEgubChhKSlyZXR1cm4gYQpp
+ZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4gYS5hCmlmKEguUjkoYSkpcmV0dXJuIGEKaWYodC5hay5i
+KGEpKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBILm8yKGEpCmlmKHQuWS5iKGEp
+KXJldHVybiBQLmhFKGEsIiRkYXJ0X2pzRnVuY3Rpb24iLG5ldyBQLlBDKCkpCnJldHVybiBQLmhFKGEs
+Il8kZGFydF9qc09iamVjdCIsbmV3IFAubXQoJC5rSSgpKSl9LApoRTpmdW5jdGlvbihhLGIsYyl7dmFy
+IHM9UC5PbShhLGIpCmlmKHM9PW51bGwpe3M9Yy4kMShhKQpQLkRtKGEsYixzKX1yZXR1cm4gc30sCmRV
+OmZ1bmN0aW9uKGEpe3ZhciBzLHIKaWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2Yg
+YT09Im51bWJlciJ8fHR5cGVvZiBhPT0iYm9vbGVhbiIpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNl
+b2YgT2JqZWN0JiZILlI5KGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIE9iamVjdCYmdC5h
+ay5iKGEpKXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIERhdGUpe3M9SC51UChhLmdldFRpbWUo
+KSkKaWYoTWF0aC5hYnMocyk8PTg2NGUxMylyPSExCmVsc2Ugcj0hMAppZihyKUgudihQLnhZKCJEYXRl
+VGltZSBpcyBvdXRzaWRlIHZhbGlkIHJhbmdlOiAiK3MpKQpQLlVJKCExLCJpc1V0YyIsdC55KQpyZXR1
+cm4gbmV3IFAuaVAocywhMSl9ZWxzZSBpZihhLmNvbnN0cnVjdG9yPT09JC5rSSgpKXJldHVybiBhLm8K
+ZWxzZSByZXR1cm4gUC5ORChhKX0sCk5EOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24i
+KXJldHVybiBQLmlRKGEsJC53KCksbmV3IFAuTnooKSkKaWYoYSBpbnN0YW5jZW9mIEFycmF5KXJldHVy
+biBQLmlRKGEsJC5SOCgpLG5ldyBQLlFTKCkpCnJldHVybiBQLmlRKGEsJC5SOCgpLG5ldyBQLm5wKCkp
+fSwKaVE6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPVAuT20oYSxiKQppZihzPT1udWxsfHwhKGEgaW5zdGFu
+Y2VvZiBPYmplY3QpKXtzPWMuJDEoYSkKUC5EbShhLGIscyl9cmV0dXJuIHN9LApQQzpmdW5jdGlvbiBQ
+Qygpe30sCm10OmZ1bmN0aW9uIG10KGEpe3RoaXMuYT1hfSwKTno6ZnVuY3Rpb24gTnooKXt9LApRUzpm
+dW5jdGlvbiBRUygpe30sCm5wOmZ1bmN0aW9uIG5wKCl7fSwKRTQ6ZnVuY3Rpb24gRTQoYSl7dGhpcy5h
+PWF9LApyNzpmdW5jdGlvbiByNyhhKXt0aGlzLmE9YX0sClR6OmZ1bmN0aW9uIFR6KGEsYil7dGhpcy5h
+PWEKdGhpcy4kdGk9Yn0sCmNvOmZ1bmN0aW9uIGNvKCl7fSwKbmQ6ZnVuY3Rpb24gbmQoKXt9LApLZTpm
+dW5jdGlvbiBLZShhKXt0aGlzLmE9YX0sCmhpOmZ1bmN0aW9uIGhpKCl7fX0sVz17CngzOmZ1bmN0aW9u
+KCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7cmV0dXJuIGRvY3VtZW50fSwKSjY6ZnVuY3Rp
+b24oYSl7dmFyIHM9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpCmlmKGEhPW51bGwpQy54bi5zTFUo
+cyxhKQpyZXR1cm4gc30sClU5OmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxyPWRvY3VtZW50LmJvZHkKci50
+b1N0cmluZwpzPUMuUlkucjYocixhLGIsYykKcy50b1N0cmluZwpyPXQuYWMKcj1uZXcgSC5VNShuZXcg
+Vy5lNyhzKSxyLkMoImEyKGxELkUpIikuYShuZXcgVy5DdigpKSxyLkMoIlU1PGxELkU+IikpCnJldHVy
+biB0LmguYShyLmdyOChyKSl9LApyUzpmdW5jdGlvbihhKXt2YXIgcyxyLHE9ImVsZW1lbnQgdGFnIHVu
+YXZhaWxhYmxlIgp0cnl7cz1KLllFKGEpCmlmKHR5cGVvZiBzLmducyhhKT09InN0cmluZyIpcT1zLmdu
+cyhhKX1jYXRjaChyKXtILlJ1KHIpfXJldHVybiBxfSwKQzA6ZnVuY3Rpb24oYSxiKXthPTUzNjg3MDkx
+MSZhK2IKYT01MzY4NzA5MTEmYSsoKDUyNDI4NyZhKTw8MTApCnJldHVybiBhXmE+Pj42fSwKckU6ZnVu
+Y3Rpb24oYSxiLGMsZCl7dmFyIHM9Vy5DMChXLkMwKFcuQzAoVy5DMCgwLGEpLGIpLGMpLGQpLHI9NTM2
+ODcwOTExJnMrKCg2NzEwODg2MyZzKTw8MykKcl49cj4+PjExCnJldHVybiA1MzY4NzA5MTEmcisoKDE2
+MzgzJnIpPDwxNSl9LApUTjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1hLmNsYXNzTGlzdApmb3Iocz1i
+Lmxlbmd0aCxyPTA7cjxiLmxlbmd0aDtiLmxlbmd0aD09PXN8fCgwLEgubGspKGIpLCsrcilxLmFkZChi
+W3JdKX0sCkpFOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHM9Vy5hRihuZXcgVy52TihjKSx0LkIpCmlm
+KHMhPW51bGwmJiEwKUouZFooYSxiLHMsITEpCnJldHVybiBuZXcgVy54QyhhLGIscywhMSxlLkMoInhD
+PDA+IikpfSwKVHc6ZnVuY3Rpb24oYSl7dmFyIHM9Vy5KNihudWxsKSxyPXdpbmRvdy5sb2NhdGlvbgpz
+PW5ldyBXLkpRKG5ldyBXLm1rKHMscikpCnMuQ1koYSkKcmV0dXJuIHN9LApxRDpmdW5jdGlvbihhLGIs
+YyxkKXt0LmguYShhKQpILmgoYikKSC5oKGMpCnQuY3IuYShkKQpyZXR1cm4hMH0sClFXOmZ1bmN0aW9u
+KGEsYixjLGQpe3ZhciBzLHIscQp0LmguYShhKQpILmgoYikKSC5oKGMpCnM9dC5jci5hKGQpLmEKcj1z
+LmEKQy54bi5zTFUocixjKQpxPXIuaG9zdG5hbWUKcz1zLmIKaWYoIShxPT1zLmhvc3RuYW1lJiZyLnBv
+cnQ9PXMucG9ydCYmci5wcm90b2NvbD09cy5wcm90b2NvbCkpaWYocT09PSIiKWlmKHIucG9ydD09PSIi
+KXtzPXIucHJvdG9jb2wKcz1zPT09IjoifHxzPT09IiJ9ZWxzZSBzPSExCmVsc2Ugcz0hMQplbHNlIHM9
+ITAKcmV0dXJuIHN9LApCbDpmdW5jdGlvbigpe3ZhciBzPXQuTixyPVAudE0oQy5ReCxzKSxxPXQuZDAu
+YShuZXcgVy5JQSgpKSxwPUguVk0oWyJURU1QTEFURSJdLHQucykKcz1uZXcgVy5jdChyLFAuTHMocyks
+UC5McyhzKSxQLkxzKHMpLG51bGwpCnMuQ1kobnVsbCxuZXcgSC5sSihDLlF4LHEsdC5maikscCxudWxs
+KQpyZXR1cm4gc30sClB2OmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIFcu
+UDEoYSl9LApxYzpmdW5jdGlvbihhKXt2YXIgcwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKCJwb3N0
+TWVzc2FnZSIgaW4gYSl7cz1XLlAxKGEpCmlmKHQuYVMuYihzKSlyZXR1cm4gcwpyZXR1cm4gbnVsbH1l
+bHNlIHJldHVybiB0LmNoLmEoYSl9LApQMTpmdW5jdGlvbihhKXtpZihhPT09d2luZG93KXJldHVybiB0
+LmNpLmEoYSkKZWxzZSByZXR1cm4gbmV3IFcuZFcoYSl9LApISDpmdW5jdGlvbihhKXtpZihhPT09d2lu
+ZG93LmxvY2F0aW9uKXJldHVybiBhCmVsc2UgcmV0dXJuIG5ldyBXLkZiKCl9LAphRjpmdW5jdGlvbihh
+LGIpe3ZhciBzPSQuWDMKaWYocz09PUMuTlUpcmV0dXJuIGEKcmV0dXJuIHMuUHkoYSxiKX0sCnFFOmZ1
+bmN0aW9uIHFFKCl7fSwKR2g6ZnVuY3Rpb24gR2goKXt9LApmWTpmdW5jdGlvbiBmWSgpe30sCm5COmZ1
+bmN0aW9uIG5CKCl7fSwKQXo6ZnVuY3Rpb24gQXooKXt9LApRUDpmdW5jdGlvbiBRUCgpe30sCm54OmZ1
+bmN0aW9uIG54KCl7fSwKb0o6ZnVuY3Rpb24gb0ooKXt9LAppZDpmdW5jdGlvbiBpZCgpe30sClFGOmZ1
+bmN0aW9uIFFGKCl7fSwKTmg6ZnVuY3Rpb24gTmgoKXt9LAphZTpmdW5jdGlvbiBhZSgpe30sCklCOmZ1
+bmN0aW9uIElCKCl7fSwKbjc6ZnVuY3Rpb24gbjcoKXt9LAp3ejpmdW5jdGlvbiB3eihhLGIpe3RoaXMu
+YT1hCnRoaXMuJHRpPWJ9LApjdjpmdW5jdGlvbiBjdigpe30sCkN2OmZ1bmN0aW9uIEN2KCl7fSwKZWE6
+ZnVuY3Rpb24gZWEoKXt9LApEMDpmdW5jdGlvbiBEMCgpe30sCmhIOmZ1bmN0aW9uIGhIKCl7fSwKaDQ6
+ZnVuY3Rpb24gaDQoKXt9LApicjpmdW5jdGlvbiBicigpe30sClZiOmZ1bmN0aW9uIFZiKCl7fSwKZko6
+ZnVuY3Rpb24gZkooKXt9LAp3YTpmdW5jdGlvbiB3YSgpe30sClNnOmZ1bmN0aW9uIFNnKCl7fSwKdTg6
+ZnVuY3Rpb24gdTgoKXt9LApBajpmdW5jdGlvbiBBaigpe30sCmU3OmZ1bmN0aW9uIGU3KGEpe3RoaXMu
+YT1hfSwKdUg6ZnVuY3Rpb24gdUgoKXt9LApCSDpmdW5jdGlvbiBCSCgpe30sClNOOmZ1bmN0aW9uIFNO
+KCl7fSwKZXc6ZnVuY3Rpb24gZXcoKXt9LApscDpmdW5jdGlvbiBscCgpe30sClRiOmZ1bmN0aW9uIFRi
+KCl7fSwKSXY6ZnVuY3Rpb24gSXYoKXt9LApXUDpmdW5jdGlvbiBXUCgpe30sCnlZOmZ1bmN0aW9uIHlZ
+KCl7fSwKdzY6ZnVuY3Rpb24gdzYoKXt9LApLNTpmdW5jdGlvbiBLNSgpe30sCkNtOmZ1bmN0aW9uIENt
+KCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LAp3NDpmdW5jdGlvbiB3NCgpe30sCnJoOmZ1bmN0aW9uIHJo
+KCl7fSwKY2Y6ZnVuY3Rpb24gY2YoKXt9LAppNzpmdW5jdGlvbiBpNyhhKXt0aGlzLmE9YX0sClN5OmZ1
+bmN0aW9uIFN5KGEpe3RoaXMuYT1hfSwKS1M6ZnVuY3Rpb24gS1MoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCkEzOmZ1bmN0aW9uIEEzKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApJNDpmdW5jdGlvbiBJNChh
+KXt0aGlzLmE9YX0sCkZrOmZ1bmN0aW9uIEZrKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sClJPOmZ1
+bmN0aW9uIFJPKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCmV1
+OmZ1bmN0aW9uIGV1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0s
+CnhDOmZ1bmN0aW9uIHhDKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmI9YQpfLmM9YgpfLmQ9YwpfLmU9
+ZApfLiR0aT1lfSwKdk46ZnVuY3Rpb24gdk4oYSl7dGhpcy5hPWF9LApKUTpmdW5jdGlvbiBKUShhKXt0
+aGlzLmE9YX0sCkdtOmZ1bmN0aW9uIEdtKCl7fSwKdkQ6ZnVuY3Rpb24gdkQoYSl7dGhpcy5hPWF9LApV
+djpmdW5jdGlvbiBVdihhKXt0aGlzLmE9YX0sCkVnOmZ1bmN0aW9uIEVnKGEsYixjKXt0aGlzLmE9YQp0
+aGlzLmI9Ygp0aGlzLmM9Y30sCm02OmZ1bmN0aW9uIG02KCl7fSwKRW86ZnVuY3Rpb24gRW8oKXt9LApX
+azpmdW5jdGlvbiBXaygpe30sCmN0OmZ1bmN0aW9uIGN0KGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmU9
+YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCklBOmZ1bmN0aW9uIElBKCl7fSwKT3c6ZnVuY3Rpb24g
+T3coKXt9LApXOTpmdW5jdGlvbiBXOShhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9LTEK
+Xy5kPW51bGwKXy4kdGk9Y30sCmRXOmZ1bmN0aW9uIGRXKGEpe3RoaXMuYT1hfSwKRmI6ZnVuY3Rpb24g
+RmIoKXt9LAptazpmdW5jdGlvbiBtayhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKS286ZnVuY3Rpb24g
+S28oYSl7dGhpcy5hPWEKdGhpcy5iPSExfSwKZm06ZnVuY3Rpb24gZm0oYSl7dGhpcy5hPWF9LApMZTpm
+dW5jdGlvbiBMZSgpe30sCks3OmZ1bmN0aW9uIEs3KCl7fSwKckI6ZnVuY3Rpb24gckIoKXt9LApYVzpm
+dW5jdGlvbiBYVygpe30sCm9hOmZ1bmN0aW9uIG9hKCl7fX0sTT17Ck9YOmZ1bmN0aW9uKGEpe3N3aXRj
+aChhKXtjYXNlIEMuQWQ6cmV0dXJuIkFkZCAvKj8qLyBoaW50IgpjYXNlIEMubmU6cmV0dXJuIkFkZCAv
+KiEqLyBoaW50IgpjYXNlIEMud1Y6cmV0dXJuIlJlbW92ZSAvKj8qLyBoaW50IgpjYXNlIEMuZlI6cmV0
+dXJuIlJlbW92ZSAvKiEqLyBoaW50IgpjYXNlIEMubXk6cmV0dXJuIkNoYW5nZSB0byAvKj8qLyBoaW50
+IgpjYXNlIEMucng6cmV0dXJuIkNoYW5nZSB0byAvKiEqLyBoaW50In1yZXR1cm4gbnVsbH0sCkg3OmZ1
+bmN0aW9uIEg3KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApZRjpmdW5jdGlvbihhLGIpe3ZhciBzLHIs
+cSxwLG8sbixtLGwKZm9yKHM9Yi5sZW5ndGgscj0xO3I8czsrK3Ipe2lmKGJbcl09PW51bGx8fGJbci0x
+XSE9bnVsbCljb250aW51ZQpmb3IoO3M+PTE7cz1xKXtxPXMtMQppZihiW3FdIT1udWxsKWJyZWFrfXA9
+bmV3IFAuUm4oIiIpCm89YSsiKCIKcC5hPW8Kbj1ILnQ2KGIpCm09bi5DKCJuSDwxPiIpCmw9bmV3IEgu
+bkgoYiwwLHMsbSkKbC5IZChiLDAscyxuLmMpCm09bytuZXcgSC5sSihsLG0uQygicVUoYUwuRSkiKS5h
+KG5ldyBNLk5vKCkpLG0uQygibEo8YUwuRSxxVT4iKSkuSCgwLCIsICIpCnAuYT1tCnAuYT1tKygiKTog
+cGFydCAiKyhyLTEpKyIgd2FzIG51bGwsIGJ1dCBwYXJ0ICIrcisiIHdhcyBub3QuIikKdGhyb3cgSC5i
+KFAueFkocC53KDApKSl9fSwKbEk6ZnVuY3Rpb24gbEkoYSl7dGhpcy5hPWF9LApxNzpmdW5jdGlvbiBx
+Nygpe30sCk5vOmZ1bmN0aW9uIE5vKCl7fX0sVT17Cm56OmZ1bmN0aW9uKGEpe3ZhciBzPUgudVAoYS5x
+KDAsIm5vZGVJZCIpKQpyZXR1cm4gbmV3IFUuTEwoQy5ObS5IdChDLnJrLG5ldyBVLk1EKGEpKSxzKX0s
+CkxMOmZ1bmN0aW9uIExMKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApNRDpmdW5jdGlvbiBNRChhKXt0
+aGlzLmE9YX0sCmpmOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwCmlmKGE9PW51bGwpcz1udWxsCmVsc2V7
+cz1ILlZNKFtdLHQuZDcpCmZvcihyPUouSVQodC5VLmEoYSkpO3IuRigpOyl7cT1yLmdsKCkKcD1KLlU2
+KHEpCkMuTm0uaShzLG5ldyBVLlNlKEguaChwLnEocSwiZGVzY3JpcHRpb24iKSksSC5oKHAucShxLCJo
+cmVmIikpKSl9fXJldHVybiBzfSwKTmQ6ZnVuY3Rpb24oYSl7dmFyIHMscgppZihhPT1udWxsKXM9bnVs
+bAplbHNle3M9SC5WTShbXSx0LmFBKQpmb3Iocj1KLklUKHQuVS5hKGEpKTtyLkYoKTspQy5ObS5pKHMs
+VS5OZihyLmdsKCkpKX1yZXR1cm4gc30sCk5mOmZ1bmN0aW9uKGEpe3ZhciBzPUouVTYoYSkscj1ILmgo
+cy5xKGEsImRlc2NyaXB0aW9uIikpLHE9SC5WTShbXSx0LmFKKQpmb3Iocz1KLklUKHQuVS5hKHMucShh
+LCJlbnRyaWVzIikpKTtzLkYoKTspQy5ObS5pKHEsVS5SaihzLmdsKCkpKQpyZXR1cm4gbmV3IFUueUQo
+cixxKX0sClJqOmZ1bmN0aW9uKGEpe3ZhciBzLHI9Si5VNihhKSxxPUguaChyLnEoYSwiZGVzY3JpcHRp
+b24iKSkscD1ILmgoci5xKGEsImZ1bmN0aW9uIikpLG89ci5xKGEsImxpbmsiKQppZihvPT1udWxsKW89
+bnVsbAplbHNle3M9Si5VNihvKQpvPW5ldyBVLk1sKEguaChzLnEobywiaHJlZiIpKSxILnVQKHMucShv
+LCJsaW5lIikpLEguaChzLnEobywicGF0aCIpKSl9cj10LmZLLmEoci5xKGEsImhpbnRBY3Rpb25zIikp
+CnI9cj09bnVsbD9udWxsOkouTTEocixuZXcgVS5hTigpLHQuYVgpCnI9cj09bnVsbD9udWxsOnIuYnIo
+MCkKcmV0dXJuIG5ldyBVLndiKHEscCxvLHI9PW51bGw/Qy5kbjpyKX0sCmQyOmZ1bmN0aW9uIGQyKGEs
+YixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwK
+U2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1sOmZ1bmN0aW9uIE1sKGEsYixj
+KXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnlEOmZ1bmN0aW9uIHlEKGEsYil7dGhpcy5hPWEK
+dGhpcy5iPWJ9LAp3YjpmdW5jdGlvbiB3YihhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8u
+Yz1jCl8uZD1kfSwKYU46ZnVuY3Rpb24gYU4oKXt9LApiMDpmdW5jdGlvbiBiMCgpe319LEI9ewp3Ujpm
+dW5jdGlvbigpe3JldHVybiBuZXcgQi5xcCgiIiwiIiwiIixDLkR4KX0sCllmOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHIscSxwLG8sbixtLGwsaz1ILmgoYS5xKDAsInJlZ2lvbnMiKSksaj1ILmgoYS5xKDAsIm5hdmln
+YXRpb25Db250ZW50IikpLGk9SC5oKGEucSgwLCJzb3VyY2VDb2RlIikpLGg9UC5GbCh0LlgsdC5kXykK
+Zm9yKHM9dC50LmEoYS5xKDAsImVkaXRzIikpLHM9cy5nUHUocykscz1zLmdreihzKSxyPXQuVSxxPXQu
+aDQ7cy5GKCk7KXtwPXMuZ2woKQpvPXAuYQpuPUguVk0oW10scSkKZm9yKHA9Si5JVChyLmEocC5iKSk7
+cC5GKCk7KXttPXAuZ2woKQpsPUouVTYobSkKQy5ObS5pKG4sbmV3IEIuajgoSC51UChsLnEobSwibGlu
+ZSIpKSxILmgobC5xKG0sImV4cGxhbmF0aW9uIikpLEgudVAobC5xKG0sIm9mZnNldCIpKSkpfWguWSgw
+LG8sbil9cmV0dXJuIG5ldyBCLnFwKGssaixpLGgpfSwKajg6ZnVuY3Rpb24gajgoYSxiLGMpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcXA6ZnVuY3Rpb24gcXAoYSxiLGMsZCl7dmFyIF89dGhpcwpf
+LmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmZ2OmZ1bmN0aW9uIGZ2KCl7fSwKT1M6ZnVuY3Rpb24oYSl7
+dmFyIHMKaWYoIShhPj02NSYmYTw9OTApKXM9YT49OTcmJmE8PTEyMgplbHNlIHM9ITAKcmV0dXJuIHN9
+LApZdTpmdW5jdGlvbihhLGIpe3ZhciBzPWEubGVuZ3RoLHI9YisyCmlmKHM8cilyZXR1cm4hMQppZigh
+Qi5PUyhDLnhCLm0oYSxiKSkpcmV0dXJuITEKaWYoQy54Qi5tKGEsYisxKSE9PTU4KXJldHVybiExCmlm
+KHM9PT1yKXJldHVybiEwCnJldHVybiBDLnhCLm0oYSxyKT09PTQ3fX0sVD17bVE6ZnVuY3Rpb24gbVEo
+KXt9fSxMPXsKSXE6ZnVuY3Rpb24oKXtDLkJaLkIoZG9jdW1lbnQsIkRPTUNvbnRlbnRMb2FkZWQiLG5l
+dyBMLmUoKSkKQy5vbC5CKHdpbmRvdywicG9wc3RhdGUiLG5ldyBMLkwoKSl9LAprejpmdW5jdGlvbihh
+KXt2YXIgcyxyPXQuZy5hKGEucGFyZW50Tm9kZSkucXVlcnlTZWxlY3RvcigiOnNjb3BlID4gdWwiKSxx
+PXIuc3R5bGUscD0iIitDLkNELnpRKHIub2Zmc2V0SGVpZ2h0KSoyKyJweCIKcS5tYXhIZWlnaHQ9cApx
+PUoucUYoYSkKcD1xLiR0aQpzPXAuQygifigxKT8iKS5hKG5ldyBMLld4KHIsYSkpCnQuWi5hKG51bGwp
+ClcuSkUocS5hLHEuYixzLCExLHAuYyl9LAp5WDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixt
+PSJxdWVyeVNlbGVjdG9yQWxsIixsPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYSksaz10LmcKbC50b1N0
+cmluZwpzPXQuaApILkRoKGsscywiVCIsbSkKcj10LlIKcT1uZXcgVy53eihsLnF1ZXJ5U2VsZWN0b3JB
+bGwoIi5uYXYtbGluayIpLHIpCnEuSyhxLG5ldyBMLkFPKGIpKQpILkRoKGsscywiVCIsbSkKcD1uZXcg
+Vy53eihsLnF1ZXJ5U2VsZWN0b3JBbGwoIi5yZWdpb24iKSxyKQppZighcC5nbDAocCkpe289bC5xdWVy
+eVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKby50b1N0cmluZwpwLksocCxuZXcgTC5IbyhvLmdl
+dEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KG8pKS5PKCJwYXRoIikpKSl9SC5EaChr
+LHMsIlQiLG0pCm49bmV3IFcud3oobC5xdWVyeVNlbGVjdG9yQWxsKCIuYWRkLWhpbnQtbGluayIpLHIp
+Cm4uSyhuLG5ldyBMLklDKCkpfSwKUTY6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPW5ldyBYTUxIdHRwUmVx
+dWVzdCgpCkMuRHQuZW8ocywiR0VUIixMLlE0KGEsYiksITApCnMuc2V0UmVxdWVzdEhlYWRlcigiQ29u
+dGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hhcnNldD1VVEYtOCIpCnJldHVybiBMLkxVKHMs
+bnVsbCxjLkMoIjAqIikpfSwKdHk6ZnVuY3Rpb24oYSxiKXt2YXIgcz1uZXcgWE1MSHR0cFJlcXVlc3Qo
+KSxyPXQuWApDLkR0LmVvKHMsIlBPU1QiLEwuUTQoYSxQLkZsKHIscikpLCEwKQpzLnNldFJlcXVlc3RI
+ZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pzb247IGNoYXJzZXQ9VVRGLTgiKQpyZXR1
+cm4gTC5MVShzLGIsdC50KX0sCkxVOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gTC5UZyhhLGIsYyxjLkMo
+IjAqIikpfSwKVGc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHM9MCxyPVAuRlgoZCkscSxwPTIsbyxuPVtd
+LG0sbCxrLGosaSxoLGcsZgp2YXIgJGFzeW5jJExVPVAubHooZnVuY3Rpb24oZSxhMCl7aWYoZT09PTEp
+e289YTAKcz1wfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDppPW5ldyBQLlpmKG5ldyBQLnZzKCQu
+WDMsdC5nViksdC5iQykKaD10LmViCmc9aC5hKG5ldyBMLmZDKGksYSkpCnQuWi5hKG51bGwpCmw9dC5l
+UQpXLkpFKGEsImxvYWQiLGcsITEsbCkKVy5KRShhLCJlcnJvciIsaC5hKGkuZ1lKKCkpLCExLGwpCmEu
+c2VuZChiPT1udWxsP251bGw6Qy5DdC5PQihiLG51bGwpKQpwPTQKcz03CnJldHVybiBQLmpRKGkuYSwk
+YXN5bmMkTFUpCmNhc2UgNzpwPTIKcz02CmJyZWFrCmNhc2UgNDpwPTMKZj1vCkguUnUoZikKbT1ILnRz
+KGYpCmg9UC5UbCgiRXJyb3IgcmVhY2hpbmcgbWlncmF0aW9uIHByZXZpZXcgc2VydmVyLiIsbSkKdGhy
+b3cgSC5iKGgpCnM9NgpicmVhawpjYXNlIDM6cz0yCmJyZWFrCmNhc2UgNjpqPUMuQ3QucFcoMCxhLnJl
+c3BvbnNlVGV4dCxudWxsKQppZihhLnN0YXR1cz09PTIwMCl7cT1jLkMoIjAqIikuYShqKQpzPTEKYnJl
+YWt9ZWxzZSB0aHJvdyBILmIoaikKY2FzZSAxOnJldHVybiBQLnlDKHEscikKY2FzZSAyOnJldHVybiBQ
+LmYzKG8scil9fSkKcmV0dXJuIFAuREkoJGFzeW5jJExVLHIpfSwKYUs6ZnVuY3Rpb24oYSl7dmFyIHM9
+UC5oSyhhKS5naFkoKS5xKDAsImxpbmUiKQpyZXR1cm4gcz09bnVsbD9udWxsOkguSHAocyxudWxsKX0s
+Ckc2OmZ1bmN0aW9uKGEpe3ZhciBzPVAuaEsoYSkuZ2hZKCkucSgwLCJvZmZzZXQiKQpyZXR1cm4gcz09
+bnVsbD9udWxsOkguSHAocyxudWxsKX0sCmk2OmZ1bmN0aW9uKGEpe3JldHVybiBMLm5XKHQuTy5hKGEp
+KX0sCm5XOmZ1bmN0aW9uKGEpe3ZhciBzPTAscj1QLkZYKHQueikscT0xLHAsbz1bXSxuLG0sbCxrLGoK
+dmFyICRhc3luYyRpNj1QLmx6KGZ1bmN0aW9uKGIsYyl7aWYoYj09PTEpe3A9YwpzPXF9d2hpbGUodHJ1
+ZSlzd2l0Y2gocyl7Y2FzZSAwOms9dC5nLmEoVy5xYyhhLmN1cnJlbnRUYXJnZXQpKS5nZXRBdHRyaWJ1
+dGUoImhyZWYiKQphLnByZXZlbnREZWZhdWx0KCkKcT0zCnM9NgpyZXR1cm4gUC5qUShMLnR5KGssbnVs
+bCksJGFzeW5jJGk2KQpjYXNlIDY6dC5iWi5hKEouR3IoVy5Qdihkb2N1bWVudC5kZWZhdWx0Vmlldykp
+KS5yZWxvYWQoKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKaj1wCm49SC5SdShqKQptPUgudHMoaikK
+TC5DMigiQ291bGQgbm90IGFkZC9yZW1vdmUgaGludCIsbixtKQpzPTUKYnJlYWsKY2FzZSAyOnM9MQpi
+cmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxyKQpjYXNlIDE6cmV0dXJuIFAuZjMocCxyKX19KQpy
+ZXR1cm4gUC5ESSgkYXN5bmMkaTYscil9LApLMDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscD1kb2N1bWVu
+dC5xdWVyeVNlbGVjdG9yKCIucG9wdXAtcGFuZSIpCnAucXVlcnlTZWxlY3RvcigiaDIiKS5pbm5lclRl
+eHQ9IkZhaWxlZCB0byByZXJ1biBmcm9tIHNvdXJjZXMiCnAucXVlcnlTZWxlY3RvcigicCIpLmlubmVy
+VGV4dD0iU291cmNlcyBjb250YWluIHN0YXRpYyBhbmFseXNpcyBlcnJvcnM6IgpzPXAucXVlcnlTZWxl
+Y3RvcigicHJlIikKcj1KLkVsKGEsdC5hdykKcT1ILkxoKHIpCnMuaW5uZXJUZXh0PW5ldyBILmxKKHIs
+cS5DKCJxVSoobEQuRSkiKS5hKG5ldyBMLnVlKCkpLHEuQygibEo8bEQuRSxxVSo+IikpLkgoMCwiXG4i
+KQpxPXAucXVlcnlTZWxlY3RvcigiYS5ib3R0b20iKS5zdHlsZQpxLmRpc3BsYXk9Im5vbmUiCnM9cC5z
+dHlsZQpzLmRpc3BsYXk9ImluaXRpYWwifSwKQzI6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwPSJl
+eGNlcHRpb24iLG89InN0YWNrVHJhY2UiLG49dC50LmIoYikmJkouUk0oYi5xKDAsInN1Y2Nlc3MiKSwh
+MSkmJmIueDQocCkmJmIueDQobyksbT1KLmlhKGIpCmlmKG4pe3M9SC5oKG0ucShiLHApKQpjPW0ucShi
+LG8pfWVsc2Ugcz1tLncoYikKbj1kb2N1bWVudApyPW4ucXVlcnlTZWxlY3RvcigiLnBvcHVwLXBhbmUi
+KQpyLnF1ZXJ5U2VsZWN0b3IoImgyIikuaW5uZXJUZXh0PWEKci5xdWVyeVNlbGVjdG9yKCJwIikuaW5u
+ZXJUZXh0PXMKci5xdWVyeVNlbGVjdG9yKCJwcmUiKS5pbm5lclRleHQ9Si5qKGMpCnE9dC5kZC5hKHIu
+cXVlcnlTZWxlY3RvcigiYS5ib3R0b20iKSkKbT10Llg7KHEmJkMueG4pLnNMVShxLFAuWGQoImh0dHBz
+IiwiZ2l0aHViLmNvbSIsImRhcnQtbGFuZy9zZGsvaXNzdWVzL25ldyIsUC5FRihbInRpdGxlIiwiQ3Vz
+dG9tZXItcmVwb3J0ZWQgaXNzdWUgd2l0aCBOTkJEIG1pZ3JhdGlvbiB0b29sOiAiK2EsImxhYmVscyIs
+dS5kLCJib2R5IixhKyJcblxuRXJyb3I6ICIrSC5FaihzKSsiXG5cblBsZWFzZSBmaWxsIGluIHRoZSBm
+b2xsb3dpbmc6XG5cbioqTmFtZSBvZiBwYWNrYWdlIGJlaW5nIG1pZ3JhdGVkIChpZiBwdWJsaWMpKio6
+XG4qKldoYXQgSSB3YXMgZG9pbmcgd2hlbiB0aGlzIGlzc3VlIG9jY3VycmVkKio6XG4qKklzIGl0IHBv
+c3NpYmxlIHRvIHdvcmsgYXJvdW5kIHRoaXMgaXNzdWUqKjpcbioqSGFzIHRoaXMgaXNzdWUgaGFwcGVu
+ZWQgYmVmb3JlLCBhbmQgaWYgc28sIGhvdyBvZnRlbioqOlxuKipEYXJ0IFNESyB2ZXJzaW9uKio6ICIr
+SC5FaihuLmdldEVsZW1lbnRCeUlkKCJzZGstdmVyc2lvbiIpLnRleHRDb250ZW50KSsiXG4qKkFkZGl0
+aW9uYWwgZGV0YWlscyoqOlxuXG5UaGFua3MgZm9yIGZpbGluZyFcblxuU3RhY2t0cmFjZTogX2F1dG8g
+cG9wdWxhdGVkIGJ5IG1pZ3JhdGlvbiBwcmV2aWV3IHRvb2wuX1xuXG5gYGBcbiIrSC5FaihjKSsiXG5g
+YGBcbiJdLG0sbSkpLmduRCgpKQptPXEuc3R5bGUKbS5kaXNwbGF5PSJpbml0aWFsIgpuPXIuc3R5bGUK
+bi5kaXNwbGF5PSJpbml0aWFsIgpuPWErIjogIitILkVqKGIpCndpbmRvdwppZih0eXBlb2YgY29uc29s
+ZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3IobikKd2luZG93Cm49SC5FaihjKQppZih0
+eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3Iobil9LApVczpmdW5j
+dGlvbihhKXtyZXR1cm4gSi5VNihhKS50ZyhhLCI/Iik/Qy54Qi5OaihhLDAsQy54Qi5PWShhLCI/Iikp
+OmF9LAp0MjpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAsbz10LmcuYShXLnFjKGEuY3VycmVudFRh
+cmdldCkpCmEucHJldmVudERlZmF1bHQoKQpzPW8uZ2V0QXR0cmlidXRlKCJocmVmIikKcj1MLlVzKHMp
+CnE9TC5HNihzKQpwPUwuYUsocykKaWYocSE9bnVsbClMLmFmKHIscSxwLGIsbmV3IEwublQocixxLHAp
+KQplbHNlIEwuYWYocixudWxsLG51bGwsYixuZXcgTC5OWShyKSl9LAp2VTpmdW5jdGlvbigpe3ZhciBz
+PWRvY3VtZW50CkguRGgodC5nLHQuaCwiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQpzPW5ldyBXLnd6KHMu
+cXVlcnlTZWxlY3RvckFsbCgiLmNvZGUiKSx0LlIpCnMuSyhzLG5ldyBMLmVYKCkpfSwKaFg6ZnVuY3Rp
+b24oYSxiLGMpe3JldHVybiBMLll3KGEsYixjKX0sCll3OmZ1bmN0aW9uKGEsYixjKXt2YXIgcz0wLHI9
+UC5GWCh0LnopLHE9MSxwLG89W10sbixtLGwsayxqLGksaCxnCnZhciAkYXN5bmMkaFg9UC5seihmdW5j
+dGlvbihkLGUpe2lmKGQ9PT0xKXtwPWUKcz1xfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDpxPTMK
+aj10LlgKcz02CnJldHVybiBQLmpRKEwuUTYoYSxQLkVGKFsicmVnaW9uIiwicmVnaW9uIiwib2Zmc2V0
+IixILkVqKGIpXSxqLGopLHQudCksJGFzeW5jJGhYKQpjYXNlIDY6bj1lCmo9bgppPUouVTYoaikKbT1u
+ZXcgVS5kMihVLmpmKGkucShqLCJlZGl0cyIpKSxILmgoaS5xKGosImV4cGxhbmF0aW9uIikpLEgudVAo
+aS5xKGosImxpbmUiKSksSC5oKGkucShqLCJkaXNwbGF5UGF0aCIpKSxILmgoaS5xKGosInVyaVBhdGgi
+KSksVS5OZChpLnEoaiwidHJhY2VzIikpKQpMLlQxKG0pCkwuRnIoYSxiLGMpCkwueVgoIi5lZGl0LXBh
+bmVsIC5wYW5lbC1jb250ZW50IiwhMSkKcT0xCnM9NQpicmVhawpjYXNlIDM6cT0yCmc9cApsPUguUnUo
+ZykKaz1ILnRzKGcpCkwuQzIoIkNvdWxkIG5vdCBsb2FkIGVkaXQgZGV0YWlscyIsbCxrKQpzPTUKYnJl
+YWsKY2FzZSAyOnM9MQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxyKQpjYXNlIDE6cmV0dXJu
+IFAuZjMocCxyKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkaFgscil9LApHNzpmdW5jdGlvbihhLGIsYyxk
+LGUpe3JldHVybiBMLkw1KGEsYixjLGQsZSl9LApMNTpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzPTAs
+cj1QLkZYKHQueikscSxwPTIsbyxuPVtdLG0sbCxrLGosaSxoLGcKdmFyICRhc3luYyRHNz1QLmx6KGZ1
+bmN0aW9uKGYsYTApe2lmKGY9PT0xKXtvPWEwCnM9cH13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6
+aWYoIUoucDQoYSwiLmRhcnQiKSl7TC5CRShhLEIud1IoKSxkKQpMLkJYKGEsbnVsbCkKaWYoZSE9bnVs
+bCllLiQwKCkKcz0xCmJyZWFrfXA9NAppPXQuWApzPTcKcmV0dXJuIFAualEoTC5RNihhLFAuRUYoWyJp
+bmxpbmUiLCJ0cnVlIl0saSxpKSx0LnQpLCRhc3luYyRHNykKY2FzZSA3Om09YTAKTC5CRShhLEIuWWYo
+bSksZCkKTC5mRyhiLGMpCmw9TC5VcyhhKQpMLkJYKGwsYikKaWYoZSE9bnVsbCllLiQwKCkKcD0yCnM9
+NgpicmVhawpjYXNlIDQ6cD0zCmc9bwprPUguUnUoZykKaj1ILnRzKGcpCkwuQzIoIkNvdWxkIG5vdCBs
+b2FkIGRhcnQgZmlsZSAiK2EsayxqKQpzPTYKYnJlYWsKY2FzZSAzOnM9MgpicmVhawpjYXNlIDY6Y2Fz
+ZSAxOnJldHVybiBQLnlDKHEscikKY2FzZSAyOnJldHVybiBQLmYzKG8scil9fSkKcmV0dXJuIFAuREko
+JGFzeW5jJEc3LHIpfSwKR2U6ZnVuY3Rpb24oKXt2YXIgcz0wLHI9UC5GWCh0LnopLHE9MSxwLG89W10s
+bixtLGwsayxqLGksaAp2YXIgJGFzeW5jJEdlPVAubHooZnVuY3Rpb24oYSxiKXtpZihhPT09MSl7cD1i
+CnM9cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6aT0iL19wcmV2aWV3L25hdmlnYXRpb25UcmVl
+Lmpzb24iCnE9MwpzPTYKcmV0dXJuIFAualEoTC5RNihpLEMuQ00sdC5tKSwkYXN5bmMkR2UpCmNhc2Ug
+NjpuPWIKbT1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIubmF2LXRyZWUiKQpKLmw1KG0sIiIpCkwudFgo
+bSxMLm1LKG4pKQpxPTEKcz01CmJyZWFrCmNhc2UgMzpxPTIKaD1wCmw9SC5SdShoKQprPUgudHMoaCkK
+TC5DMigiQ291bGQgbm90IGxvYWQgbmF2aWdhdGlvbiB0cmVlIixsLGspCnM9NQpicmVhawpjYXNlIDI6
 cz0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHIpCmNhc2UgMTpyZXR1cm4gUC5mMyhwLHIp
-fX0pCnJldHVybiBQLkRJKCRhc3luYyQkMSxyKX0sCiRTOjExfQpMLlhBLnByb3RvdHlwZT17CkViOmZ1
-bmN0aW9uKGEsYixjKXtyZXR1cm4hMH0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKJGlrRjoxfQpM
-LlpaLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9UC5GbCh0LlgsdC5fKQpx
-LlkoMCwidHlwZSIsTC52eShyLmEpKQpxLlkoMCwibmFtZSIsci5iKQpzPXIuYwppZihzIT1udWxsKXEu
-WSgwLCJzdWJ0cmVlIixMLlZEKHMpKQpzPXIuZAppZihzIT1udWxsKXEuWSgwLCJwYXRoIixzKQpzPXIu
-ZQppZihzIT1udWxsKXEuWSgwLCJocmVmIixzKQpzPXIuZgppZihzIT1udWxsKXEuWSgwLCJlZGl0Q291
-bnQiLHMpCnJldHVybiBxfX0KTC5POS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
-LmJ9fQpNLmxJLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7dmFyIHM9RC5SWCgpCnJldHVybiBzfSwK
-V086ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9dC5kNApNLllGKCJhYnNvbHV0ZSIsSC5WTShbYixudWxs
-LG51bGwsbnVsbCxudWxsLG51bGwsbnVsbF0scSkpCnM9dGhpcy5hCnM9cy5ZcihiKT4wJiYhcy5oSyhi
-KQppZihzKXJldHVybiBiCnI9SC5WTShbdGhpcy5nbCgpLGIsbnVsbCxudWxsLG51bGwsbnVsbCxudWxs
-LG51bGxdLHEpCk0uWUYoImpvaW4iLHIpCnJldHVybiB0aGlzLklQKG5ldyBILnU2KHIsdC5lSikpfSwK
-emY6ZnVuY3Rpb24oYSl7dmFyIHMscixxPVguQ0woYSx0aGlzLmEpCnEuSVYoKQpzPXEuZApyPXMubGVu
-Z3RoCmlmKHI9PT0wKXtzPXEuYgpyZXR1cm4gcz09bnVsbD8iLiI6c31pZihyPT09MSl7cz1xLmIKcmV0
-dXJuIHM9PW51bGw/Ii4iOnN9aWYoMD49cilyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCkMuTm0ubXYo
-cS5lKQpxLklWKCkKcmV0dXJuIHEudygwKX0sCklQOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixt
-LGwsayxqCnQuUS5hKGEpCmZvcihzPWEuJHRpLHI9cy5DKCJhMihjWC5FKSIpLmEobmV3IE0ucTcoKSks
-cT1hLmdreihhKSxzPW5ldyBILlNPKHEscixzLkMoIlNPPGNYLkU+IikpLHI9dGhpcy5hLHA9ITEsbz0h
-MSxuPSIiO3MuRigpOyl7bT1xLmdsKCkKaWYoci5oSyhtKSYmbyl7bD1YLkNMKG0scikKaz1uLmNoYXJD
-b2RlQXQoMCk9PTA/bjpuCm49Qy54Qi5OaihrLDAsci5TcChrLCEwKSkKbC5iPW4KaWYoci5kcyhuKSlD
-Lk5tLlkobC5lLDAsci5nbUkoKSkKbj1sLncoMCl9ZWxzZSBpZihyLllyKG0pPjApe289IXIuaEsobSkK
-bj1ILkVqKG0pfWVsc2V7aj1tLmxlbmd0aAppZihqIT09MCl7aWYoMD49ailyZXR1cm4gSC5PSChtLDAp
-Cmo9ci5VZChtWzBdKX1lbHNlIGo9ITEKaWYoIWopaWYocCluKz1yLmdtSSgpCm4rPW19cD1yLmRzKG0p
-fXJldHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKbzU6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIXRo
-aXMueTMoYSkpcmV0dXJuIGEKcz1YLkNMKGEsdGhpcy5hKQpzLnJSKCkKcmV0dXJuIHMudygwKX0sCnkz
-OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqCmEudG9TdHJpbmcKcz10aGlzLmEKcj1z
-LllyKGEpCmlmKHIhPT0wKXtpZihzPT09JC5LaygpKWZvcihxPTA7cTxyOysrcSlpZihDLnhCLlcoYSxx
-KT09PTQ3KXJldHVybiEwCnA9cgpvPTQ3fWVsc2V7cD0wCm89bnVsbH1mb3Iobj1uZXcgSC5xaihhKS5h
-LG09bi5sZW5ndGgscT1wLGw9bnVsbDtxPG07KytxLGw9byxvPWspe2s9Qy54Qi5tKG4scSkKaWYocy5y
-NChrKSl7aWYocz09PSQuS2soKSYmaz09PTQ3KXJldHVybiEwCmlmKG8hPW51bGwmJnMucjQobykpcmV0
-dXJuITAKaWYobz09PTQ2KWo9bD09bnVsbHx8bD09PTQ2fHxzLnI0KGwpCmVsc2Ugaj0hMQppZihqKXJl
-dHVybiEwfX1pZihvPT1udWxsKXJldHVybiEwCmlmKHMucjQobykpcmV0dXJuITAKaWYobz09PTQ2KXM9
-bD09bnVsbHx8cy5yNChsKXx8bD09PTQ2CmVsc2Ugcz0hMQppZihzKXJldHVybiEwCnJldHVybiExfSwK
-SFA6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsPXRoaXMsaz0nVW5hYmxlIHRvIGZpbmQg
-YSBwYXRoIHRvICInCmI9bC5XTygwLGIpCnM9bC5hCmlmKHMuWXIoYik8PTAmJnMuWXIoYSk+MClyZXR1
-cm4gbC5vNShhKQppZihzLllyKGEpPD0wfHxzLmhLKGEpKWE9bC5XTygwLGEpCmlmKHMuWXIoYSk8PTAm
-JnMuWXIoYik+MCl0aHJvdyBILmIoWC5JNyhrK0guRWooYSkrJyIgZnJvbSAiJytILkVqKGIpKyciLicp
-KQpyPVguQ0woYixzKQpyLnJSKCkKcT1YLkNMKGEscykKcS5yUigpCnA9ci5kCm89cC5sZW5ndGgKaWYo
-byE9PTApe2lmKDA+PW8pcmV0dXJuIEguT0gocCwwKQpwPUouUk0ocFswXSwiLiIpfWVsc2UgcD0hMQpp
-ZihwKXJldHVybiBxLncoMCkKcD1yLmIKbz1xLmIKaWYocCE9bylwPXA9PW51bGx8fG89PW51bGx8fCFz
-Lk5jKHAsbykKZWxzZSBwPSExCmlmKHApcmV0dXJuIHEudygwKQp3aGlsZSghMCl7cD1yLmQKbz1wLmxl
-bmd0aAppZihvIT09MCl7bj1xLmQKbT1uLmxlbmd0aAppZihtIT09MCl7aWYoMD49bylyZXR1cm4gSC5P
-SChwLDApCnA9cFswXQppZigwPj1tKXJldHVybiBILk9IKG4sMCkKbj1zLk5jKHAsblswXSkKcD1ufWVs
-c2UgcD0hMX1lbHNlIHA9ITEKaWYoIXApYnJlYWsKQy5ObS5XNChyLmQsMCkKQy5ObS5XNChyLmUsMSkK
-Qy5ObS5XNChxLmQsMCkKQy5ObS5XNChxLmUsMSl9cD1yLmQKbz1wLmxlbmd0aAppZihvIT09MCl7aWYo
-MD49bylyZXR1cm4gSC5PSChwLDApCnA9Si5STShwWzBdLCIuLiIpfWVsc2UgcD0hMQppZihwKXRocm93
-IEguYihYLkk3KGsrSC5FaihhKSsnIiBmcm9tICInK0guRWooYikrJyIuJykpCnA9dC5OCkMuTm0uVUco
-cS5kLDAsUC5POChyLmQubGVuZ3RoLCIuLiIsITEscCkpCkMuTm0uWShxLmUsMCwiIikKQy5ObS5VRyhx
-LmUsMSxQLk84KHIuZC5sZW5ndGgscy5nbUkoKSwhMSxwKSkKcz1xLmQKcD1zLmxlbmd0aAppZihwPT09
-MClyZXR1cm4iLiIKaWYocD4xJiZKLlJNKEMuTm0uZ3JaKHMpLCIuIikpe3M9cS5kCmlmKDA+PXMubGVu
-Z3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKcz1xLmUKQy5ObS5tdihzKQpDLk5tLm12KHMpCkMu
-Tm0uaShzLCIiKX1xLmI9IiIKcS5JVigpCnJldHVybiBxLncoMCl9fQpNLnE3LnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3JldHVybiBILmgoYSkhPT0iIn0sCiRTOjZ9Ck0uTm8ucHJvdG90eXBlPXsKJDE6
-ZnVuY3Rpb24oYSl7SC5rKGEpCnJldHVybiBhPT1udWxsPyJudWxsIjonIicrYSsnIid9LAokUzo0OX0K
-Qi5mdi5wcm90b3R5cGU9ewp4WjpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMuWXIoYSkKaWYocj4wKXJl
-dHVybiBKLmxkKGEsMCxyKQppZih0aGlzLmhLKGEpKXtpZigwPj1hLmxlbmd0aClyZXR1cm4gSC5PSChh
-LDApCnM9YVswXX1lbHNlIHM9bnVsbApyZXR1cm4gc30sCk5jOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9
-PWJ9fQpYLldELnByb3RvdHlwZT17CklWOmZ1bmN0aW9uKCl7dmFyIHMscixxPXRoaXMKd2hpbGUoITAp
-e3M9cS5kCmlmKCEocy5sZW5ndGghPT0wJiZKLlJNKEMuTm0uZ3JaKHMpLCIiKSkpYnJlYWsKcz1xLmQK
-aWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpDLk5tLm12KHEuZSl9cz1xLmUK
-cj1zLmxlbmd0aAppZihyIT09MClDLk5tLlkocyxyLTEsIiIpfSwKclI6ZnVuY3Rpb24oKXt2YXIgcyxy
-LHEscCxvLG4sbT10aGlzLGw9SC5WTShbXSx0LnMpCmZvcihzPW0uZCxyPXMubGVuZ3RoLHE9MCxwPTA7
-cDxzLmxlbmd0aDtzLmxlbmd0aD09PXJ8fCgwLEgubGspKHMpLCsrcCl7bz1zW3BdCm49Si5pYShvKQpp
-ZighKG4uRE4obywiLiIpfHxuLkROKG8sIiIpKSlpZihuLkROKG8sIi4uIikpe249bC5sZW5ndGgKaWYo
-biE9PTApe2lmKDA+PW4pcmV0dXJuIEguT0gobCwtMSkKbC5wb3AoKX1lbHNlICsrcX1lbHNlIEMuTm0u
-aShsLG8pfWlmKG0uYj09bnVsbClDLk5tLlVHKGwsMCxQLk84KHEsIi4uIiwhMSx0Lk4pKQppZihsLmxl
-bmd0aD09PTAmJm0uYj09bnVsbClDLk5tLmkobCwiLiIpCm0uc25KKGwpCnM9bS5hCm0uc1BoKFAuTzgo
-bC5sZW5ndGgrMSxzLmdtSSgpLCEwLHQuTikpCnI9bS5iCmlmKHI9PW51bGx8fGwubGVuZ3RoPT09MHx8
-IXMuZHMocikpQy5ObS5ZKG0uZSwwLCIiKQpyPW0uYgppZihyIT1udWxsJiZzPT09JC5LaygpKXtyLnRv
-U3RyaW5nCm0uYj1ILnlzKHIsIi8iLCJcXCIpfW0uSVYoKX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHMscixx
-PXRoaXMscD1xLmIKcD1wIT1udWxsP3A6IiIKZm9yKHM9MDtzPHEuZC5sZW5ndGg7KytzKXtyPXEuZQpp
-ZihzPj1yLmxlbmd0aClyZXR1cm4gSC5PSChyLHMpCnI9cCtILkVqKHJbc10pCnA9cS5kCmlmKHM+PXAu
-bGVuZ3RoKXJldHVybiBILk9IKHAscykKcD1yK0guRWoocFtzXSl9cCs9SC5FaihDLk5tLmdyWihxLmUp
-KQpyZXR1cm4gcC5jaGFyQ29kZUF0KDApPT0wP3A6cH0sCnNuSjpmdW5jdGlvbihhKXt0aGlzLmQ9dC5E
-LmEoYSl9LApzUGg6ZnVuY3Rpb24oYSl7dGhpcy5lPXQuRC5hKGEpfX0KWC5kdi5wcm90b3R5cGU9ewp3
-OmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhjZXB0aW9uOiAiK3RoaXMuYX0sCiRpUno6MX0KTy56TC5w
-cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdvYyh0aGlzKX19CkUuT0YucHJvdG90
-eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3ZhciBzPWEubGVuZ3RoCnJldHVybiBzIT09MCYm
-Qy54Qi5tKGEscy0xKSE9PTQ3fSwKU3A6ZnVuY3Rpb24oYSxiKXtpZihhLmxlbmd0aCE9PTAmJkMueEIu
-VyhhLDApPT09NDcpcmV0dXJuIDEKcmV0dXJuIDB9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5T
-cChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiExfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInBv
-c2l4In0sCmdtSTpmdW5jdGlvbigpe3JldHVybiIvIn19CkYucnUucHJvdG90eXBlPXsKVWQ6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30s
-CmRzOmZ1bmN0aW9uKGEpe3ZhciBzPWEubGVuZ3RoCmlmKHM9PT0wKXJldHVybiExCmlmKEMueEIubShh
-LHMtMSkhPT00NylyZXR1cm4hMApyZXR1cm4gQy54Qi5UYyhhLCI6Ly8iKSYmdGhpcy5ZcihhKT09PXN9
-LApTcDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG89YS5sZW5ndGgKaWYobz09PTApcmV0dXJuIDAK
-aWYoQy54Qi5XKGEsMCk9PT00NylyZXR1cm4gMQpmb3Iocz0wO3M8bzsrK3Mpe3I9Qy54Qi5XKGEscykK
-aWYocj09PTQ3KXJldHVybiAwCmlmKHI9PT01OCl7aWYocz09PTApcmV0dXJuIDAKcT1DLnhCLlhVKGEs
-Ii8iLEMueEIuUWkoYSwiLy8iLHMrMSk/cyszOnMpCmlmKHE8PTApcmV0dXJuIG8KaWYoIWJ8fG88cSsz
-KXJldHVybiBxCmlmKCFDLnhCLm4oYSwiZmlsZTovLyIpKXJldHVybiBxCmlmKCFCLll1KGEscSsxKSly
-ZXR1cm4gcQpwPXErMwpyZXR1cm4gbz09PXA/cDpxKzR9fXJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGghPT0wJiZD
-LnhCLlcoYSwwKT09PTQ3fSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInVybCJ9LApnbUk6ZnVuY3Rpb24o
-KXtyZXR1cm4iLyJ9fQpMLklWLnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRn
-KGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBhPT09NDd8fGE9PT05Mn0sCmRzOmZ1bmN0aW9u
-KGEpe3ZhciBzPWEubGVuZ3RoCmlmKHM9PT0wKXJldHVybiExCnM9Qy54Qi5tKGEscy0xKQpyZXR1cm4h
-KHM9PT00N3x8cz09PTkyKX0sClNwOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPWEubGVuZ3RoCmlmKHE9
-PT0wKXJldHVybiAwCnM9Qy54Qi5XKGEsMCkKaWYocz09PTQ3KXJldHVybiAxCmlmKHM9PT05Mil7aWYo
-cTwyfHxDLnhCLlcoYSwxKSE9PTkyKXJldHVybiAxCnI9Qy54Qi5YVShhLCJcXCIsMikKaWYocj4wKXty
-PUMueEIuWFUoYSwiXFwiLHIrMSkKaWYocj4wKXJldHVybiByfXJldHVybiBxfWlmKHE8MylyZXR1cm4g
-MAppZighQi5PUyhzKSlyZXR1cm4gMAppZihDLnhCLlcoYSwxKSE9PTU4KXJldHVybiAwCnE9Qy54Qi5X
-KGEsMikKaWYoIShxPT09NDd8fHE9PT05MikpcmV0dXJuIDAKcmV0dXJuIDN9LApZcjpmdW5jdGlvbihh
-KXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLllyKGEpPT09
-MX0sCk90OmZ1bmN0aW9uKGEsYil7dmFyIHMKaWYoYT09PWIpcmV0dXJuITAKaWYoYT09PTQ3KXJldHVy
-biBiPT09OTIKaWYoYT09PTkyKXJldHVybiBiPT09NDcKaWYoKGFeYikhPT0zMilyZXR1cm4hMQpzPWF8
-MzIKcmV0dXJuIHM+PTk3JiZzPD0xMjJ9LApOYzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQppZihhPT1i
-KXJldHVybiEwCnM9YS5sZW5ndGgKaWYocyE9PWIubGVuZ3RoKXJldHVybiExCmZvcihyPUouclkoYiks
-cT0wO3E8czsrK3EpaWYoIXRoaXMuT3QoQy54Qi5XKGEscSksci5XKGIscSkpKXJldHVybiExCnJldHVy
-biEwfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuIndpbmRvd3MifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJu
-IlxcIn19OyhmdW5jdGlvbiBhbGlhc2VzKCl7dmFyIHM9Si52Qi5wcm90b3R5cGUKcy5VPXMudwpzLlNq
-PXMuZTcKcz1KLk1GLnByb3RvdHlwZQpzLnQ9cy53CnM9UC5jWC5wcm90b3R5cGUKcy5HRz1zLmV2CnM9
-UC5NaC5wcm90b3R5cGUKcy54Yj1zLncKcz1XLmN2LnByb3RvdHlwZQpzLkRXPXMucjYKcz1XLm02LnBy
-b3RvdHlwZQpzLmpGPXMuRWIKcz1QLkU0LnByb3RvdHlwZQpzLlVyPXMucQpzLmU0PXMuWX0pKCk7KGZ1
-bmN0aW9uIGluc3RhbGxUZWFyT2Zmcygpe3ZhciBzPWh1bmtIZWxwZXJzLl9zdGF0aWNfMSxyPWh1bmtI
-ZWxwZXJzLl9zdGF0aWNfMCxxPWh1bmtIZWxwZXJzLmluc3RhbGxJbnN0YW5jZVRlYXJPZmYscD1odW5r
-SGVscGVycy5pbnN0YWxsU3RhdGljVGVhck9mZixvPWh1bmtIZWxwZXJzLl9pbnN0YW5jZV8xdQpzKFAs
-IkVYIiwiWlYiLDgpCnMoUCwieXQiLCJvQSIsOCkKcyhQLCJxVyIsIkJ6Iiw4KQpyKFAsIlY5IiwiZU4i
-LDEpCnEoUC5QZi5wcm90b3R5cGUsImdZSiIsMCwxLG51bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0s
-MjcsMCkKcyhQLCJDeSIsIk5DIiw0KQpzKFAsIlBIIiwiTXQiLDUpCnAoVywicFMiLDQsbnVsbCxbIiQ0
-Il0sWyJxRCJdLDksMCkKcChXLCJWNCIsNCxudWxsLFsiJDQiXSxbIlFXIl0sOSwwKQpvKFAuQXMucHJv
-dG90eXBlLCJndU0iLCJUIiw1KQpzKFAsImlHIiwid1kiLDUyKQpzKFAsIncwIiwiZFUiLDM1KQpzKEws
-ImlTIiwiaTYiLDIwKX0pKCk7KGZ1bmN0aW9uIGluaGVyaXRhbmNlKCl7dmFyIHM9aHVua0hlbHBlcnMu
-bWl4aW4scj1odW5rSGVscGVycy5pbmhlcml0LHE9aHVua0hlbHBlcnMuaW5oZXJpdE1hbnkKcihQLk1o
-LG51bGwpCnEoUC5NaCxbSC5GSyxKLnZCLEoubTEsUC5YUyxQLm5ZLFAuY1gsSC5hNyxQLkFuLEguSkIs
-SC5TVSxILlJlLEgud3YsUC5QbixILldVLEguTEksSC52LEguZjksSC50ZSxILmJxLEguWE8sSC5rcixQ
-LllrLEguZGIsSC5ONixILlZSLEguRUssSC5QYixILnRRLEguU2QsSC5KYyxILkcsUC5XMyxQLmloLFAu
-RnksUC5HVixQLlBmLFAuRmUsUC52cyxQLk9NLFAucWgsUC5NTyxQLmtULFAueEksUC5DdyxQLm0wLFAu
-WHYsUC5ibixQLmxtLFAubEQsUC5LUCxQLk1hLFAuV1ksUC5VayxQLlNoLFAuUncsUC5ieixQLmlQLFAu
-azUsUC5LWSxQLkNELFAuYUUsUC5OMyxQLmM4LFAuWmQsUC5SbixQLkRuLFAuUEUsUC5VZixXLmlkLFcu
-RmssVy5KUSxXLkdtLFcudkQsVy5tNixXLk93LFcuVzksVy5kVyxXLkZiLFcubWssVy5LbyxQLmlKLFAu
-RTQsTS5INyxVLkxMLFUuZDIsVS5TZSxVLk1sLFUueUQsVS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwu
-WlosTC5POSxNLmxJLE8uekwsWC5XRCxYLmR2XSkKcShKLnZCLFtKLnlFLEoud2UsSi5NRixKLmpkLEou
-cUksSi5EcixILkVULFcuRDAsVy5BeixXLkxlLFcuTmgsVy5hZSxXLklCLFcubjcsVy5lYSxXLmJyLFcu
-U2csVy51OCxXLks3LFcuWFcsUC5oRl0pCnEoSi5NRixbSi5pQyxKLmtkLEouYzVdKQpyKEouUG8sSi5q
-ZCkKcShKLnFJLFtKLmJVLEouVkFdKQpxKFAuWFMsW0gubmQsUC5FeixILmF6LEgudlYsSC5FcSxQLkM2
-LEgudTksUC5VZCxQLm4sUC51LFAubXAsUC51YixQLmRzLFAubGosUC5VVixQLmNdKQpyKFAudXksUC5u
-WSkKcShQLnV5LFtILncyLFcud3osVy5lN10pCnIoSC5xaixILncyKQpxKFAuY1gsW0guYlEsSC5pMSxI
-LlU1LEgudTYsSC5YUixQLm1XLEgudW5dKQpxKEguYlEsW0guYUwsSC5pNV0pCnEoSC5hTCxbSC5uSCxI
-LmxKLFAuaThdKQpyKEgueHksSC5pMSkKcShQLkFuLFtILk1ILEguU09dKQpyKFAuUlUsUC5QbikKcihQ
-LkdqLFAuUlUpCnIoSC5QRCxQLkdqKQpyKEguTFAsSC5XVSkKcShILnYsW0guQ2osSC5sYyxILmRDLEgu
-d04sSC5WWCxQLnRoLFAuaGEsUC5WcyxQLkZ0LFAueUgsUC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9RLFAu
-cFYsUC5VNyxQLnZyLFAucnQsUC5LRixQLlpMLFAuUlQsUC5qWixQLnJxLFAuUlcsUC5CNSxQLnVPLFAu
-cEssUC5oaixQLlZwLFAuT1IsUC5yYSxQLnlRLFAucGcsUC5jMixQLnRpLFAuV0YsUC5uMSxQLmNTLFAu
-VkMsUC5KVCxQLlJaLFAuTUUsUC55NSxQLnEzLFAueUksUC5jNixQLnFkLFcuQ3YsVy5LUyxXLkEzLFcu
-dk4sVy5VdixXLkVnLFcuRW8sVy5XayxXLklBLFcuZm0sUC5qZyxQLlRhLFAuR0UsUC5ONyxQLnVRLFAu
-UEMsUC5tdCxQLk56LFAuUVMsUC5ucCxVLk1ELFUuYU4sVS5iMCxMLmUsTC5WVyxMLm9aLEwuanIsTC5x
-bCxMLkhpLEwuQlQsTC5QWSxMLkwsTC5XeCxMLkFPLEwuZE4sTC5IbyxMLnh6LEwuSUMsTC5mQyxMLm5U
-LEwuTlksTC5lWCxMLkVFLEwuUUwsTC5WUyxMLlRELEwuQVMsTS5xNyxNLk5vXSkKcihILlcwLFAuRXop
-CnEoSC5sYyxbSC56eCxILnJUXSkKcihILmtZLFAuQzYpCnIoUC5pbCxQLllrKQpxKFAuaWwsW0guTjUs
-UC51dyxXLmNmLFcuU3ldKQpxKFAubVcsW0guS1csUC5xNF0pCnIoSC5MWixILkVUKQpxKEguTFosW0gu
-UkcsSC5XQl0pCnIoSC5WUCxILlJHKQpyKEguRGcsSC5WUCkKcihILlpHLEguV0IpCnIoSC5QZyxILlpH
-KQpxKEguUGcsW0gueGosSC5kRSxILlpBLEguZFQsSC5QcSxILmVFLEguVjZdKQpyKEguaU0sSC51OSkK
-cihQLlpmLFAuUGYpCnIoUC5KaSxQLm0wKQpyKFAuYjYsUC5YdikKcihQLlZqLFAuV1kpCnEoUC5Vayxb
-UC5DVixQLlppLFAuYnldKQpyKFAud0ksUC5rVCkKcShQLndJLFtQLlU4LFAub2osUC5NeCxQLkUzLFAu
-R1ldKQpyKFAuSzgsUC5VZCkKcihQLnR1LFAuU2gpCnIoUC51NSxQLlppKQpxKFAudSxbUC5iSixQLmVZ
-XSkKcihQLnFlLFAuRG4pCnEoVy5EMCxbVy51SCxXLndhLFcuSzUsVy5DbV0pCnEoVy51SCxbVy5jdixX
-Lm54LFcuUUYsVy5DUV0pCnEoVy5jdixbVy5xRSxQLmQ1XSkKcShXLnFFLFtXLkdoLFcuZlksVy5uQixX
-LlFQLFcuaDQsVy5TTixXLmxwLFcuVGIsVy5JdixXLldQLFcueVldKQpyKFcub0osVy5MZSkKcihXLmhI
-LFcuQXopCnIoVy5WYixXLlFGKQpyKFcuZkosVy53YSkKcShXLmVhLFtXLnc2LFcuZXddKQpyKFcuQWos
-Vy53NikKcihXLnJCLFcuSzcpCnIoVy5CSCxXLnJCKQpyKFcudzQsVy5JQikKcihXLm9hLFcuWFcpCnIo
-Vy5yaCxXLm9hKQpyKFcuaTcsVy5jZikKcihQLkFzLFAuVmopCnEoUC5BcyxbVy5JNCxQLktlXSkKcihX
-LlJPLFAucWgpCnIoVy5ldSxXLlJPKQpyKFcueEMsUC5NTykKcihXLmN0LFcubTYpCnIoUC5CZixQLmlK
-KQpxKFAuRTQsW1AucjcsUC5jb10pCnIoUC5UeixQLmNvKQpyKFAuYkIsUC5kNSkKcihCLmZ2LE8uekwp
-CnEoQi5mdixbRS5PRixGLnJ1LEwuSVZdKQpzKEgudzIsSC5SZSkKcyhILlJHLFAubEQpCnMoSC5WUCxI
-LlNVKQpzKEguV0IsUC5sRCkKcyhILlpHLEguU1UpCnMoUC5uWSxQLmxEKQpzKFAuV1ksUC5NYSkKcyhQ
-LlJVLFAuS1ApCnMoVy5MZSxXLmlkKQpzKFcuSzcsUC5sRCkKcyhXLnJCLFcuR20pCnMoVy5YVyxQLmxE
-KQpzKFcub2EsVy5HbSkKcyhQLmNvLFAubEQpfSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcg
-TWFwKCksdFI6e30sZVQ6e30sdFBWOnt9LHNFQTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntJZjoiaW50
-IixDUDoiZG91YmxlIixsZjoibnVtIixxVToiU3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJM
-aXN0In0sbWFuZ2xlZE5hbWVzOnt9LGdldFR5cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRh
-ZGF0YTpbXSx0eXBlczpbImM4KCkiLCJ+KCkiLCJjOChBaiopIiwiYzgoY3YqKSIsIkAoQCkiLCJxVShx
-VSkiLCJhMihxVSkiLCJjOChALEApIiwifih+KCkpIiwiYTIoY3YscVUscVUsSlEpIiwiYzgoQCkiLCJi
-ODxjOD4qKEFqKikiLCJjOChNaD8sTWg/KSIsIkAoKSIsImM4KHFVLEApIiwifihuNixxVSxJZikiLCJj
-OChxVSxxVSkiLCJhMihrRikiLCJ+KHh1PHFVPikiLCJjOChlYSopIiwifihBaiopIiwiWjA8cVUscVU+
-KFowPHFVLHFVPixxVSkiLCJ+KHFVLHFVPykiLCJuNihJZikiLCJuNihALEApIiwiYzgoSWYsQCkiLCJh
-Mih1SCkiLCJ+KE1oW0d6P10pIiwiQChlYSkiLCJjOChNaCxHeikiLCJ2czxAPihAKSIsIn4odUgsdUg/
-KSIsIkAocVUpIiwiYTIoeHU8cVU+KSIsIkAoQCxxVSkiLCJNaD8oQCkiLCJUejxAPihAKSIsIkU0KEAp
-IiwiYTIqKEg3KikiLCJMTCooQCkiLCJaMDxxVSosTWgqPiooTEwqKSIsImM4KEdELEApIiwifihAKSIs
-ImM4KFowPHFVKixNaCo+KikiLCJyNyhAKSIsInFVKihBaiopIiwifihxVSxJZikiLCJjOChldyopIiwi
-fihxVVtAXSkiLCJxVShxVT8pIiwiSWYoSWYsSWYpIiwiYzgofigpKSIsIk1oPyhNaD8pIiwiYzgoQCxH
-eikiXSxpbnRlcmNlcHRvcnNCeVRhZzpudWxsLGxlYWZUYWdzOm51bGwsYXJyYXlSdGk6dHlwZW9mIFN5
-bWJvbD09ImZ1bmN0aW9uIiYmdHlwZW9mIFN5bWJvbCgpPT0ic3ltYm9sIj9TeW1ib2woIiR0aSIpOiIk
-dGkifQpILnhiKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3siYzUiOiJNRiIsImlDIjoiTUYiLCJr
-ZCI6Ik1GIiwicngiOiJlYSIsImU1IjoiZWEiLCJZMCI6ImQ1IiwidHAiOiJkNSIsIkc4IjoiZXciLCJN
-ciI6InFFIiwiZUwiOiJxRSIsIkkwIjoidUgiLCJocyI6InVIIiwiWGciOiJRRiIsIm5yIjoiQWoiLCJ5
-NCI6Inc2IiwiYVAiOiJDbSIsInhjIjoibngiLCJrSiI6Im54IiwielUiOiJEZyIsImRmIjoiRVQiLCJ5
-RSI6eyJhMiI6W119LCJ3ZSI6eyJjOCI6W119LCJNRiI6eyJ2bSI6W10sIkVIIjpbXX0sImpkIjp7InpN
-IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJQbyI6eyJqZCI6WyIxIl0sInpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJjWCI6WyIxIl19LCJtMSI6eyJBbiI6WyIxIl19LCJxSSI6eyJDUCI6W10sImxmIjpb
-XX0sImJVIjp7IkNQIjpbXSwiSWYiOltdLCJsZiI6W119LCJWQSI6eyJDUCI6W10sImxmIjpbXX0sIkRy
-Ijp7InFVIjpbXSwidlgiOltdfSwibmQiOnsiWFMiOltdfSwicWoiOnsibEQiOlsiSWYiXSwiUmUiOlsi
-SWYiXSwiek0iOlsiSWYiXSwiYlEiOlsiSWYiXSwiY1giOlsiSWYiXSwibEQuRSI6IklmIiwiUmUuRSI6
-IklmIn0sImJRIjp7ImNYIjpbIjEiXX0sImFMIjp7ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwibkgiOnsi
-YUwiOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXSwiYUwuRSI6IjEiLCJjWC5FIjoiMSJ9LCJhNyI6
-eyJBbiI6WyIxIl19LCJpMSI6eyJjWCI6WyIyIl0sImNYLkUiOiIyIn0sInh5Ijp7ImkxIjpbIjEiLCIy
-Il0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJjWC5FIjoiMiJ9LCJNSCI6eyJBbiI6WyIyIl19LCJsSiI6
-eyJhTCI6WyIyIl0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJhTC5FIjoiMiIsImNYLkUiOiIyIn0sIlU1
-Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiU08iOnsiQW4iOlsiMSJdfSwidTYiOnsiY1giOlsiMSJd
-LCJjWC5FIjoiMSJ9LCJKQiI6eyJBbiI6WyIxIl19LCJ3MiI6eyJsRCI6WyIxIl0sIlJlIjpbIjEiXSwi
-ek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sInd2Ijp7IkdEIjpbXX0sIlBEIjp7IkdqIjpb
-IjEiLCIyIl0sIlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpb
-IjEiLCIyIl19LCJXVSI6eyJaMCI6WyIxIiwiMiJdfSwiTFAiOnsiV1UiOlsiMSIsIjIiXSwiWjAiOlsi
-MSIsIjIiXX0sIlhSIjp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiTEkiOnsidlEiOltdfSwiVzAiOnsi
-WFMiOltdfSwiYXoiOnsiWFMiOltdfSwidlYiOnsiWFMiOltdfSwidGUiOnsiUnoiOltdfSwiWE8iOnsi
-R3oiOltdfSwidiI6eyJFSCI6W119LCJsYyI6eyJFSCI6W119LCJ6eCI6eyJFSCI6W119LCJyVCI6eyJF
-SCI6W119LCJFcSI6eyJYUyI6W119LCJrWSI6eyJYUyI6W119LCJONSI6eyJZayI6WyIxIiwiMiJdLCJG
-byI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdLCJZay5LIjoiMSIsIllrLlYiOiIyIn0sImk1Ijp7ImJR
-IjpbIjEiXSwiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJONiI6eyJBbiI6WyIxIl19LCJWUiI6eyJ3TCI6
-W10sInZYIjpbXX0sIkVLIjp7ImliIjpbXSwiT2QiOltdfSwiS1ciOnsiY1giOlsiaWIiXSwiY1guRSI6
-ImliIn0sIlBiIjp7IkFuIjpbImliIl19LCJ0USI6eyJPZCI6W119LCJ1biI6eyJjWCI6WyJPZCJdLCJj
-WC5FIjoiT2QifSwiU2QiOnsiQW4iOlsiT2QiXX0sIkVUIjp7ImVxIjpbXX0sIkxaIjp7IlhqIjpbIjEi
-XSwiRVQiOltdLCJlcSI6W119LCJEZyI6eyJsRCI6WyJDUCJdLCJYaiI6WyJDUCJdLCJ6TSI6WyJDUCJd
-LCJFVCI6W10sImJRIjpbIkNQIl0sImVxIjpbXSwiY1giOlsiQ1AiXSwiU1UiOlsiQ1AiXSwibEQuRSI6
-IkNQIn0sIlBnIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEi
-OlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdfSwieGoiOnsibEQiOlsiSWYiXSwi
-WGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklm
-Il0sIlNVIjpbIklmIl0sImxELkUiOiJJZiJ9LCJkRSI6eyJsRCI6WyJJZiJdLCJYaiI6WyJJZiJdLCJ6
-TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsiSWYi
-XSwibEQuRSI6IklmIn0sIlpBIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0sIkVU
-IjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5FIjoiSWYi
-fSwiZFQiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJ
-ZiJdLCJlcSI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0sImxELkUiOiJJZiJ9LCJQcSI6eyJsRCI6
-WyJJZiJdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwi
-Y1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0sImVFIjp7ImxEIjpbIklmIl0sIlhqIjpb
-IklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJT
-VSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiVjYiOnsibEQiOlsiSWYiXSwibjYiOltdLCJYaiI6WyJJZiJd
-LCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsi
-SWYiXSwibEQuRSI6IklmIn0sInU5Ijp7IlhTIjpbXX0sImlNIjp7IlhTIjpbXX0sIkdWIjp7IkFuIjpb
-IjEiXX0sInE0Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiWmYiOnsiUGYiOlsiMSJdfSwidnMiOnsi
-YjgiOlsiMSJdfSwiQ3ciOnsiWFMiOltdfSwibTAiOnsiUW0iOltdfSwiSmkiOnsibTAiOltdLCJRbSI6
-W119LCJiNiI6eyJYdiI6WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJsbSI6
-eyJBbiI6WyIxIl19LCJtVyI6eyJjWCI6WyIxIl19LCJ1eSI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpbCI6eyJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwi
-WWsiOnsiWjAiOlsiMSIsIjIiXX0sIlBuIjp7IlowIjpbIjEiLCIyIl19LCJHaiI6eyJSVSI6WyIxIiwi
-MiJdLCJQbiI6WyIxIiwiMiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiVmoiOnsiTWEi
-OlsiMSJdLCJ4dSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiWHYiOnsieHUiOlsiMSJdLCJi
-USI6WyIxIl0sImNYIjpbIjEiXX0sInV3Ijp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwi
-WWsuSyI6InFVIiwiWWsuViI6IkAifSwiaTgiOnsiYUwiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsi
-cVUiXSwiYUwuRSI6InFVIiwiY1guRSI6InFVIn0sIkNWIjp7IlVrIjpbInpNPElmPiIsInFVIl0sIlVr
-LlMiOiJ6TTxJZj4ifSwiVTgiOnsid0kiOlsiek08SWY+IiwicVUiXX0sIlppIjp7IlVrIjpbInFVIiwi
-ek08SWY+Il19LCJVZCI6eyJYUyI6W119LCJLOCI6eyJYUyI6W119LCJieSI6eyJVayI6WyJNaD8iLCJx
-VSJdLCJVay5TIjoiTWg/In0sIm9qIjp7IndJIjpbIk1oPyIsInFVIl19LCJNeCI6eyJ3SSI6WyJxVSIs
-Ik1oPyJdfSwidTUiOnsiVWsiOlsicVUiLCJ6TTxJZj4iXSwiVWsuUyI6InFVIn0sIkUzIjp7IndJIjpb
-InFVIiwiek08SWY+Il19LCJHWSI6eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwiQ1AiOnsibGYiOltdfSwi
-SWYiOnsibGYiOltdfSwiek0iOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4
-dSI6eyJiUSI6WyIxIl0sImNYIjpbIjEiXX0sInFVIjp7InZYIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIkV6
-Ijp7IlhTIjpbXX0sIm4iOnsiWFMiOltdfSwidSI6eyJYUyI6W119LCJiSiI6eyJYUyI6W119LCJlWSI6
-eyJYUyI6W119LCJtcCI6eyJYUyI6W119LCJ1YiI6eyJYUyI6W119LCJkcyI6eyJYUyI6W119LCJsaiI6
-eyJYUyI6W119LCJVViI6eyJYUyI6W119LCJrNSI6eyJYUyI6W119LCJLWSI6eyJYUyI6W119LCJjIjp7
-IlhTIjpbXX0sIkNEIjp7IlJ6IjpbXX0sImFFIjp7IlJ6IjpbXX0sIlpkIjp7Ikd6IjpbXX0sIlJuIjp7
-IkJMIjpbXX0sIkRuIjp7ImlEIjpbXX0sIlVmIjp7ImlEIjpbXX0sInFlIjp7ImlEIjpbXX0sInFFIjp7
-ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHaCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZlki
-OnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm5CIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJR
-UCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibngiOnsidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1
-SCI6W10sIkQwIjpbXX0sIklCIjp7InRuIjpbImxmIl19LCJ3eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEi
-XSwiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImxELkUiOiIxIn0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwi
-aEgiOnsiQXoiOltdfSwiaDQiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlZiIjp7InVIIjpbXSwi
-RDAiOltdfSwiZkoiOnsiRDAiOltdfSwid2EiOnsiRDAiOltdfSwiQWoiOnsiZWEiOltdfSwiZTciOnsi
-bEQiOlsidUgiXSwiek0iOlsidUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwibEQuRSI6InVIIn0s
-InVIIjp7IkQwIjpbXX0sIkJIIjp7ImxEIjpbInVIIl0sIkdtIjpbInVIIl0sInpNIjpbInVIIl0sIlhq
-IjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJT
-TiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZXciOnsiZWEiOltdfSwibHAiOnsiY3YiOltdLCJ1
-SCI6W10sIkQwIjpbXX0sIlRiIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJJdiI6eyJjdiI6W10s
-InVIIjpbXSwiRDAiOltdfSwiV1AiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sInlZIjp7ImN2Ijpb
-XSwidUgiOltdLCJEMCI6W119LCJ3NiI6eyJlYSI6W119LCJLNSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNt
-Ijp7IkQwIjpbXX0sIkNRIjp7InVIIjpbXSwiRDAiOltdfSwidzQiOnsidG4iOlsibGYiXX0sInJoIjp7
-ImxEIjpbInVIIl0sIkdtIjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpbInVIIl0s
-ImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJjZiI6eyJZayI6WyJxVSIsInFVIl0s
-IlowIjpbInFVIiwicVUiXX0sImk3Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZ
-ay5LIjoicVUiLCJZay5WIjoicVUifSwiU3kiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFV
-Il0sIllrLksiOiJxVSIsIllrLlYiOiJxVSJ9LCJJNCI6eyJNYSI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJi
-USI6WyJxVSJdLCJjWCI6WyJxVSJdfSwiUk8iOnsicWgiOlsiMSJdfSwiZXUiOnsiUk8iOlsiMSJdLCJx
-aCI6WyIxIl19LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6eyJrRiI6W119LCJ2RCI6eyJrRiI6W119LCJt
-NiI6eyJrRiI6W119LCJjdCI6eyJrRiI6W119LCJPdyI6eyJrRiI6W119LCJXOSI6eyJBbiI6WyIxIl19
-LCJkVyI6eyJ2NiI6W10sIkQwIjpbXX0sIm1rIjp7InkwIjpbXX0sIktvIjp7Im9uIjpbXX0sIkFzIjp7
-Ik1hIjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6
-W119LCJUeiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJFNCI6W10sImNYIjpbIjEi
-XSwibEQuRSI6IjEifSwiYkIiOnsiZDUiOltdLCJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiS2UiOnsi
-TWEiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsicVUiXX0sImQ1Ijp7ImN2Ijpb
-XSwidUgiOltdLCJEMCI6W119LCJYQSI6eyJrRiI6W119LCJkdiI6eyJSeiI6W119LCJPRiI6eyJmdiI6
-W119LCJydSI6eyJmdiI6W119LCJJViI6eyJmdiI6W119LCJuNiI6eyJ6TSI6WyJJZiJdLCJiUSI6WyJJ
-ZiJdLCJjWCI6WyJJZiJdLCJlcSI6W119fScpKQpILkZGKHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2Uo
-J3siYlEiOjEsIncyIjoxLCJMWiI6MSwia1QiOjIsIm1XIjoxLCJ1eSI6MSwiaWwiOjIsIlZqIjoxLCJu
-WSI6MSwiV1kiOjEsImNvIjoxfScpKQp2YXIgdT17bDoiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGgg
-ZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IixpOiJDYW5ub3QgZXh0cmFjdCBhIGZp
-bGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiLGo6IkNhbm5vdCBleHRyYWN0
-IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIs
-ZDoiYXJlYS1hbmFseXplcixhbmFseXplci1ubmJkLW1pZ3JhdGlvbix0eXBlLWJ1ZyJ9CnZhciB0PShm
-dW5jdGlvbiBydGlpKCl7dmFyIHM9SC5OMApyZXR1cm57bjpzKCJDdyIpLGNSOnMoIm5CIiksdzpzKCJB
-eiIpLGs6cygiUVAiKSxnRjpzKCJQRDxHRCxAPiIpLGd3OnMoImJRPEA+IiksaDpzKCJjdiIpLG06cygi
-WFMiKSxCOnMoImVhIiksYVM6cygiRDAiKSxnODpzKCJSeiIpLGM4OnMoImhIIiksWTpzKCJFSCIpLGQ6
-cygiYjg8QD4iKSxJOnMoIlNnIiksbzpzKCJ2USIpLGVoOnMoImNYPHVIPiIpLFE6cygiY1g8cVU+Iiks
-cjpzKCJjWDxAPiIpLHU6cygiamQ8a0Y+IiksczpzKCJqZDxxVT4iKSx2OnMoImpkPEA+IiksYTpzKCJq
-ZDxJZj4iKSxkNzpzKCJqZDxTZSo+IiksaDQ6cygiamQ8ajgqPiIpLEc6cygiamQ8WjA8cVUqLE1oKj4q
-PiIpLGNROnMoImpkPFpaKj4iKSxpOnMoImpkPHFVKj4iKSxhQTpzKCJqZDx5RCo+IiksYUo6cygiamQ8
-d2IqPiIpLFY6cygiamQ8SWYqPiIpLGQ0OnMoImpkPHFVPz4iKSxUOnMoIndlIiksZUg6cygidm0iKSx4
-OnMoImM1IiksYVU6cygiWGo8QD4iKSxhbTpzKCJUejxAPiIpLGVvOnMoIk41PEdELEA+IiksZHo6cygi
-aEYiKSxEOnMoInpNPHFVPiIpLGI6cygiek08QD4iKSxMOnMoInpNPElmPiIpLEo6cygiWjA8cVUscVU+
-IiksZjpzKCJaMDxALEA+IiksZG86cygibEo8cVUsQD4iKSxmajpzKCJsSjxxVSoscVU+IiksZEU6cygi
-RVQiKSxibTpzKCJWNiIpLEE6cygidUgiKSxlOnMoImtGIiksUDpzKCJjOCIpLEs6cygiTWgiKSxxOnMo
-InRuPGxmPiIpLGZ2OnMoIndMIiksZXc6cygiYkIiKSxDOnMoInh1PHFVPiIpLGw6cygiR3oiKSxOOnMo
-InFVIiksZDA6cygicVUocVUqKSIpLGc3OnMoImQ1IiksZm86cygiR0QiKSxhVzpzKCJ5WSIpLEU6cygi
-ZXEiKSxnYzpzKCJuNiIpLGFrOnMoImtkIiksZHc6cygiR2o8cVUscVU+IiksZEQ6cygiaUQiKSxlSjpz
-KCJ1NjxxVT4iKSxnNDpzKCJLNSIpLGNpOnMoInY2IiksZzI6cygiQ20iKSxiQzpzKCJaZjxmSio+Iiks
-aDk6cygiQ1EiKSxhYzpzKCJlNyIpLGo6cygiZXU8QWoqPiIpLFI6cygid3o8Y3YqPiIpLGM6cygidnM8
-QD4iKSxmSjpzKCJ2czxJZj4iKSxnVjpzKCJ2czxmSio+IiksY3I6cygiSlEiKSx5OnMoImEyIiksYWw6
-cygiYTIoTWgpIiksZ1I6cygiQ1AiKSx6OnMoIkAiKSxmTzpzKCJAKCkiKSxiSTpzKCJAKE1oKSIpLGFn
-OnMoIkAoTWgsR3opIiksYlU6cygiQCh4dTxxVT4pIiksZE86cygiQChxVSkiKSxiODpzKCJAKEAsQCki
-KSxwOnMoIklmIiksZGQ6cygiR2gqIiksZzpzKCJjdioiKSxhTDpzKCJlYSoiKSxhWDpzKCJMTCoiKSxm
-RTpzKCJINyoiKSxVOnMoImNYPEA+KiIpLGRIOnMoIkU0KiIpLGZLOnMoInpNPEA+KiIpLGRfOnMoInpN
-PGo4Kj4qIiksZHA6cygiek08WjA8cVUqLE1oKj4qPioiKSxlRTpzKCJ6TTxNaCo+KiIpLGJaOnMoInU4
-KiIpLHQ6cygiWjA8cVUqLE1oKj4qIiksTzpzKCJBaioiKSxhdzpzKCIwJioiKSxfOnMoIk1oKiIpLGVR
-OnMoImV3KiIpLFg6cygicVUqIiksY2g6cygiRDA/IiksYkc6cygiYjg8Yzg+PyIpLGJrOnMoInpNPHFV
-Pj8iKSxiTTpzKCJ6TTxAPj8iKSxjWjpzKCJaMDxxVSxxVT4/IiksYzk6cygiWjA8cVUsQD4/IiksUzpz
-KCJNaD8iKSxGOnMoIkZlPEAsQD4/IiksVzpzKCJibj8iKSxiNzpzKCJhMihNaCk/IiksYnc6cygiQChl
-YSk/IiksZlY6cygiTWg/KE1oPyxNaD8pPyIpLGRBOnMoIk1oPyhAKT8iKSxaOnMoIn4oKT8iKSxlYjpz
-KCJ+KGV3Kik/IiksZGk6cygibGYiKSxIOnMoIn4iKSxNOnMoIn4oKSIpLGVBOnMoIn4ocVUscVUpIiks
-Y0E6cygifihxVSxAKSIpfX0pKCk7KGZ1bmN0aW9uIGNvbnN0YW50cygpe3ZhciBzPWh1bmtIZWxwZXJz
-Lm1ha2VDb25zdExpc3QKQy54bj1XLkdoLnByb3RvdHlwZQpDLlJZPVcuUVAucHJvdG90eXBlCkMubUg9
-Vy5hZS5wcm90b3R5cGUKQy5CWj1XLlZiLnByb3RvdHlwZQpDLkR0PVcuZkoucHJvdG90eXBlCkMuT2s9
-Si52Qi5wcm90b3R5cGUKQy5ObT1KLmpkLnByb3RvdHlwZQpDLmpuPUouYlUucHJvdG90eXBlCkMuak49
-Si53ZS5wcm90b3R5cGUKQy5DRD1KLnFJLnByb3RvdHlwZQpDLnhCPUouRHIucHJvdG90eXBlCkMuREc9
-Si5jNS5wcm90b3R5cGUKQy5FeD1XLnU4LnByb3RvdHlwZQpDLnQ1PVcuQkgucHJvdG90eXBlCkMuTHQ9
-Vy5TTi5wcm90b3R5cGUKQy5aUT1KLmlDLnByb3RvdHlwZQpDLkllPVcuVGIucHJvdG90eXBlCkMudkI9
-Si5rZC5wcm90b3R5cGUKQy5vbD1XLks1LnByb3RvdHlwZQpDLnk4PW5ldyBQLlU4KCkKQy5oOT1uZXcg
-UC5DVigpCkMuTzQ9ZnVuY3Rpb24gZ2V0VGFnRmFsbGJhY2sobykgewogIHZhciBzID0gT2JqZWN0LnBy
-b3RvdHlwZS50b1N0cmluZy5jYWxsKG8pOwogIHJldHVybiBzLnN1YnN0cmluZyg4LCBzLmxlbmd0aCAt
-IDEpOwp9CkMuWXE9ZnVuY3Rpb24oKSB7CiAgdmFyIHRvU3RyaW5nRnVuY3Rpb24gPSBPYmplY3QucHJv
-dG90eXBlLnRvU3RyaW5nOwogIGZ1bmN0aW9uIGdldFRhZyhvKSB7CiAgICB2YXIgcyA9IHRvU3RyaW5n
-RnVuY3Rpb24uY2FsbChvKTsKICAgIHJldHVybiBzLnN1YnN0cmluZyg4LCBzLmxlbmd0aCAtIDEpOwog
-IH0KICBmdW5jdGlvbiBnZXRVbmtub3duVGFnKG9iamVjdCwgdGFnKSB7CiAgICBpZiAoL15IVE1MW0Et
-Wl0uKkVsZW1lbnQkLy50ZXN0KHRhZykpIHsKICAgICAgdmFyIG5hbWUgPSB0b1N0cmluZ0Z1bmN0aW9u
-LmNhbGwob2JqZWN0KTsKICAgICAgaWYgKG5hbWUgPT0gIltvYmplY3QgT2JqZWN0XSIpIHJldHVybiBu
-dWxsOwogICAgICByZXR1cm4gIkhUTUxFbGVtZW50IjsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2V0VW5r
-bm93blRhZ0dlbmVyaWNCcm93c2VyKG9iamVjdCwgdGFnKSB7CiAgICBpZiAoc2VsZi5IVE1MRWxlbWVu
-dCAmJiBvYmplY3QgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCkgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAg
-ICByZXR1cm4gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZyk7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlw
-ZUZvclRhZyh0YWcpIHsKICAgIGlmICh0eXBlb2Ygd2luZG93ID09ICJ1bmRlZmluZWQiKSByZXR1cm4g
-bnVsbDsKICAgIGlmICh0eXBlb2Ygd2luZG93W3RhZ10gPT0gInVuZGVmaW5lZCIpIHJldHVybiBudWxs
-OwogICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107CiAgICBpZiAodHlwZW9mIGNvbnN0cnVj
-dG9yICE9ICJmdW5jdGlvbiIpIHJldHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3Rv
-dHlwZTsKICB9CiAgZnVuY3Rpb24gZGlzY3JpbWluYXRvcih0YWcpIHsgcmV0dXJuIG51bGw7IH0KICB2
-YXIgaXNCcm93c2VyID0gdHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IjsKICByZXR1cm4gewogICAg
-Z2V0VGFnOiBnZXRUYWcsCiAgICBnZXRVbmtub3duVGFnOiBpc0Jyb3dzZXIgPyBnZXRVbmtub3duVGFn
-R2VuZXJpY0Jyb3dzZXIgOiBnZXRVbmtub3duVGFnLAogICAgcHJvdG90eXBlRm9yVGFnOiBwcm90b3R5
-cGVGb3JUYWcsCiAgICBkaXNjcmltaW5hdG9yOiBkaXNjcmltaW5hdG9yIH07Cn0KQy53Yj1mdW5jdGlv
-bihnZXRUYWdGYWxsYmFjaykgewogIHJldHVybiBmdW5jdGlvbihob29rcykgewogICAgaWYgKHR5cGVv
-ZiBuYXZpZ2F0b3IgIT0gIm9iamVjdCIpIHJldHVybiBob29rczsKICAgIHZhciB1YSA9IG5hdmlnYXRv
-ci51c2VyQWdlbnQ7CiAgICBpZiAodWEuaW5kZXhPZigiRHVtcFJlbmRlclRyZWUiKSA+PSAwKSByZXR1
-cm4gaG9va3M7CiAgICBpZiAodWEuaW5kZXhPZigiQ2hyb21lIikgPj0gMCkgewogICAgICBmdW5jdGlv
-biBjb25maXJtKHApIHsKICAgICAgICByZXR1cm4gdHlwZW9mIHdpbmRvdyA9PSAib2JqZWN0IiAmJiB3
-aW5kb3dbcF0gJiYgd2luZG93W3BdLm5hbWUgPT0gcDsKICAgICAgfQogICAgICBpZiAoY29uZmlybSgi
-V2luZG93IikgJiYgY29uZmlybSgiSFRNTEVsZW1lbnQiKSkgcmV0dXJuIGhvb2tzOwogICAgfQogICAg
-aG9va3MuZ2V0VGFnID0gZ2V0VGFnRmFsbGJhY2s7CiAgfTsKfQpDLktVPWZ1bmN0aW9uKGhvb2tzKSB7
-CiAgaWYgKHR5cGVvZiBkYXJ0RXhwZXJpbWVudGFsRml4dXBHZXRUYWcgIT0gImZ1bmN0aW9uIikgcmV0
-dXJuIGhvb2tzOwogIGhvb2tzLmdldFRhZyA9IGRhcnRFeHBlcmltZW50YWxGaXh1cEdldFRhZyhob29r
-cy5nZXRUYWcpOwp9CkMuZlE9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgZ2V0VGFnID0gaG9va3MuZ2V0
-VGFnOwogIHZhciBwcm90b3R5cGVGb3JUYWcgPSBob29rcy5wcm90b3R5cGVGb3JUYWc7CiAgZnVuY3Rp
-b24gZ2V0VGFnRml4ZWQobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAgIGlmICh0YWcgPT0g
-IkRvY3VtZW50IikgewogICAgICBpZiAoISFvLnhtbFZlcnNpb24pIHJldHVybiAiIURvY3VtZW50IjsK
-ICAgICAgcmV0dXJuICIhSFRNTERvY3VtZW50IjsKICAgIH0KICAgIHJldHVybiB0YWc7CiAgfQogIGZ1
-bmN0aW9uIHByb3RvdHlwZUZvclRhZ0ZpeGVkKHRhZykgewogICAgaWYgKHRhZyA9PSAiRG9jdW1lbnQi
-KSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBwcm90b3R5cGVGb3JUYWcodGFnKTsKICB9CiAgaG9va3Mu
-Z2V0VGFnID0gZ2V0VGFnRml4ZWQ7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJvdG90eXBlRm9y
-VGFnRml4ZWQ7Cn0KQy5kaz1mdW5jdGlvbihob29rcykgewogIHZhciB1c2VyQWdlbnQgPSB0eXBlb2Yg
-bmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2VudCA6ICIiOwogIGlmICh1c2Vy
-QWdlbnQuaW5kZXhPZigiRmlyZWZveCIpID09IC0xKSByZXR1cm4gaG9va3M7CiAgdmFyIGdldFRhZyA9
-IGhvb2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVmb3JlVW5sb2FkRXZlbnQiOiAi
-RXZlbnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAogICAgIkdlb0dlb2xvY2F0aW9u
-IjogIkdlb2xvY2F0aW9uIiwKICAgICJMb2NhdGlvbiI6ICIhTG9jYXRpb24iLAogICAgIldvcmtlck1l
-c3NhZ2VFdmVudCI6ICJNZXNzYWdlRXZlbnQiLAogICAgIlhNTERvY3VtZW50IjogIiFEb2N1bWVudCJ9
-OwogIGZ1bmN0aW9uIGdldFRhZ0ZpcmVmb3gobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAg
-IHJldHVybiBxdWlja01hcFt0YWddIHx8IHRhZzsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRmly
-ZWZveDsKfQpDLnhpPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIHVzZXJBZ2VudCA9IHR5cGVvZiBuYXZp
+fX0pCnJldHVybiBQLkRJKCRhc3luYyRHZSxyKX0sCnFPOmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS5nZXRC
+b3VuZGluZ0NsaWVudFJlY3QoKSxxPUMuQ0QuelEoJC5maSgpLm9mZnNldEhlaWdodCkscD13aW5kb3cu
+aW5uZXJIZWlnaHQsbz1DLkNELnpRKCQuRFcoKS5vZmZzZXRIZWlnaHQpCmlmKHR5cGVvZiBwIT09Im51
+bWJlciIpcmV0dXJuIHAuSE4oKQpzPXIuYm90dG9tCnMudG9TdHJpbmcKaWYocz5wLShvKzE0KSlKLmRo
+KGEpCmVsc2V7cD1yLnRvcApwLnRvU3RyaW5nCmlmKHA8cSsxNClKLmRoKGEpfX0sCmZHOmZ1bmN0aW9u
+KGEsYil7dmFyIHMscixxLHAsbwppZihhIT1udWxsKXtzPWRvY3VtZW50CnI9cy5nZXRFbGVtZW50QnlJ
+ZCgibyIrSC5FaihhKSkKcT1zLnF1ZXJ5U2VsZWN0b3IoIi5saW5lLSIrSC5FaihiKSkKaWYociE9bnVs
+bCl7TC5xTyhyKQpKLmRSKHIpLmkoMCwidGFyZ2V0Iil9ZWxzZSBpZihxIT1udWxsKUwucU8ocS5wYXJl
+bnRFbGVtZW50KQppZihxIT1udWxsKUouZFIodC5nLmEocS5wYXJlbnROb2RlKSkuaSgwLCJoaWdobGln
+aHQiKX1lbHNle3M9ZG9jdW1lbnQKcD10LmcKSC5EaChwLHQuaCwiVCIsInF1ZXJ5U2VsZWN0b3JBbGwi
+KQpzPXMucXVlcnlTZWxlY3RvckFsbCgiLmxpbmUtbm8iKQpvPW5ldyBXLnd6KHMsdC5SKQppZihvLmdB
+KG8pPT09MClyZXR1cm4KTC5xTyhwLmEoQy50NS5ndEgocykpKX19LAphZjpmdW5jdGlvbihhLGIsYyxk
+LGUpe3ZhciBzLHIscT1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKSxwPUwuYUsod2luZG93LmxvY2F0
+aW9uLmhyZWYpCmlmKHEhPW51bGwpe3M9ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guRWoocSkp
+CmlmKHMhPW51bGwpSi5kUihzKS5SKDAsInRhcmdldCIpfWlmKHAhPW51bGwpe3I9ZG9jdW1lbnQucXVl
+cnlTZWxlY3RvcigiLmxpbmUtIitILkVqKHApKQppZihyIT1udWxsKUouZFIoci5wYXJlbnRFbGVtZW50
+KS5SKDAsImhpZ2hsaWdodCIpfWlmKGE9PXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSl7TC5mRyhiLGMp
+CmUuJDAoKX1lbHNlIEwuRzcoYSxiLGMsZCxlKX0sClE0OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPVAu
+aEsoYSkscD10LlgKcD1QLkZsKHAscCkKZm9yKHM9cS5naFkoKSxzPXMuZ1B1KHMpLHM9cy5na3oocyk7
+cy5GKCk7KXtyPXMuZ2woKQpwLlkoMCxyLmEsci5iKX1mb3Iocz1iLmdQdShiKSxzPXMuZ2t6KHMpO3Mu
+RigpOyl7cj1zLmdsKCkKcC5ZKDAsci5hLHIuYil9cC5ZKDAsImF1dGhUb2tlbiIsJC5VRSgpKQpyZXR1
+cm4gcS5ubSgwLHApLmduRCgpfSwKVDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGo9
+JC5oTCgpCkoubDUoaiwiIikKaWYoYT09bnVsbCl7cz1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJwIikK
+Qy5MdC5zYTQocywiU2VlIGRldGFpbHMgYWJvdXQgYSBwcm9wb3NlZCBlZGl0LiIpCkMuTHQuc0QocyxI
+LlZNKFsicGxhY2Vob2xkZXIiXSx0LmkpKQpqLmFwcGVuZENoaWxkKHMpCkMuTHQuRkYocykKcmV0dXJu
+fXI9YS5kCnE9JC5uVSgpCnA9cS56ZihyKQpvPWEuYgpuPWRvY3VtZW50Cm09cS5IUChyLEouVDAobi5x
+dWVyeVNlbGVjdG9yKCIucm9vdCIpLnRleHRDb250ZW50KSkKbD1hLmMKaz1uLmNyZWF0ZUVsZW1lbnQo
+InAiKQpqLmFwcGVuZENoaWxkKGspCmsuYXBwZW5kQ2hpbGQobi5jcmVhdGVUZXh0Tm9kZShILkVqKG8p
+KyIgYXQgIikpCnE9dC5YCnE9Vy5KNihMLlE0KGEuZSxQLkVGKFsibGluZSIsSi5qKGwpXSxxLHEpKSkK
+cS5hcHBlbmRDaGlsZChuLmNyZWF0ZVRleHROb2RlKEguRWoobSkrIjoiK0guRWoobCkrIi4iKSkKay5h
+cHBlbmRDaGlsZChxKQpKLmRoKGspCkwuQ0MoYSxqLHApCkwuRnooYSxqKX0sCkxIOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9JC55UCgpCkoubDUoZSwiIikKaWYo
+Yi5nQShiKT09PTApe3M9ZG9jdW1lbnQKcj1zLmNyZWF0ZUVsZW1lbnQoInAiKQplLmFwcGVuZENoaWxk
+KHIpCnIuYXBwZW5kQ2hpbGQocy5jcmVhdGVUZXh0Tm9kZSgiTm8gcHJvcG9zZWQgZWRpdHMiKSl9ZWxz
+ZSBmb3IoZT1iLmdQdShiKSxlPWUuZ2t6KGUpLHM9dC5YLHE9dC5rLHA9cS5DKCJ+KDEpPyIpLG89dC5a
+LHE9cS5jO2UuRigpOyl7bj1lLmdsKCkKbT1kb2N1bWVudApyPW0uY3JlYXRlRWxlbWVudCgicCIpCmw9
+JC55UCgpCmwuYXBwZW5kQ2hpbGQocikKci5hcHBlbmRDaGlsZChtLmNyZWF0ZVRleHROb2RlKEguRWoo
+bi5hKSsiOiIpKQprPW0uY3JlYXRlRWxlbWVudCgidWwiKQpsLmFwcGVuZENoaWxkKGspCmZvcihuPUou
+SVQobi5iKTtuLkYoKTspe2w9bi5nbCgpCmo9bS5jcmVhdGVFbGVtZW50KCJsaSIpCmsuYXBwZW5kQ2hp
+bGQoaikKSi5kUihqKS5pKDAsImVkaXQiKQppPW0uY3JlYXRlRWxlbWVudCgiYSIpCmouYXBwZW5kQ2hp
+bGQoaSkKaS5jbGFzc0xpc3QuYWRkKCJlZGl0LWxpbmsiKQpoPWwuYwpnPUguRWooaCkKaS5zZXRBdHRy
+aWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhpKSkuTygib2Zmc2V0IiksZykKZj1sLmEKZz1I
+LkVqKGYpCmkuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoaSkpLk8oImxpbmUi
+KSxnKQppLmFwcGVuZENoaWxkKG0uY3JlYXRlVGV4dE5vZGUoImxpbmUgIitILkVqKGYpKSkKaS5zZXRB
+dHRyaWJ1dGUoImhyZWYiLEwuUTQod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLFAuRUYoWyJsaW5lIixI
+LkVqKGYpLCJvZmZzZXQiLEguRWooaCldLHMscykpKQpnPXAuYShuZXcgTC5FRShoLGYsYSkpCm8uYShu
+dWxsKQpXLkpFKGksImNsaWNrIixnLCExLHEpCmouYXBwZW5kQ2hpbGQobS5jcmVhdGVUZXh0Tm9kZSgi
+OiAiK0guRWoobC5iKSkpfX1pZihjKUwuVDEobnVsbCl9LApGcjpmdW5jdGlvbihhLGIsYyl7dmFyIHMs
+cixxPXdpbmRvdy5sb2NhdGlvbixwPVAuaEsoKHEmJkMuRXgpLmdEcihxKStILkVqKGEpKQpxPXQuWApx
+PVAuRmwocSxxKQppZihiIT1udWxsKXEuWSgwLCJvZmZzZXQiLEguRWooYikpCmlmKGMhPW51bGwpcS5Z
+KDAsImxpbmUiLEguRWooYykpCnEuWSgwLCJhdXRoVG9rZW4iLCQuVUUoKSkKcD1wLm5tKDAscSkKcT13
+aW5kb3cuaGlzdG9yeQpzPXQuegpyPXAuZ25EKCkKcS50b1N0cmluZwpxLnB1c2hTdGF0ZShuZXcgUC5C
+ZihbXSxbXSkuUHYoUC5GbChzLHMpKSwiIixyKX0sCkVuOmZ1bmN0aW9uKGEpe3ZhciBzPUouYmIoZG9j
+dW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCwiLyIpCmlmKEMueEIubihhLHMp
+KXJldHVybiBDLnhCLkcoYSxzLmxlbmd0aCkKZWxzZSByZXR1cm4gYX0sCkJYOmZ1bmN0aW9uKGEsYil7
+dmFyIHMscj17fQpyLmE9YQphPUwuRW4oYSkKci5hPWEKSi5kcigkLkQ5KCksYSkKcz1kb2N1bWVudApI
+LkRoKHQuZyx0LmgsIlQiLCJxdWVyeVNlbGVjdG9yQWxsIikKcz1uZXcgVy53eihzLnF1ZXJ5U2VsZWN0
+b3JBbGwoIi5uYXYtcGFuZWwgLm5hdi1saW5rIiksdC5SKQpzLksocyxuZXcgTC5WUyhyKSl9LApCRTpm
+dW5jdGlvbihhLGIsYyl7dmFyIHM9Ii5yZWdpb25zIixyPWRvY3VtZW50LHE9ci5xdWVyeVNlbGVjdG9y
+KHMpLHA9ci5xdWVyeVNlbGVjdG9yKCIuY29kZSIpCkoudEgocSxiLmEsJC5LRygpKQpKLnRIKHAsYi5i
+LCQuS0coKSkKTC5MSChhLGIuZCxjKQpMLnZVKCkKTC55WCgiLmNvZGUiLCEwKQpMLnlYKHMsITApfSwK
+dFg6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9ZG9jdW1lbnQs
+ZD1lLmNyZWF0ZUVsZW1lbnQoInVsIikKYS5hcHBlbmRDaGlsZChkKQpmb3Iocz1iLmxlbmd0aCxyPXQu
+WCxxPXQuWixwPTA7cDxiLmxlbmd0aDtiLmxlbmd0aD09PXN8fCgwLEgubGspKGIpLCsrcCl7bz1iW3Bd
+Cm49ZS5jcmVhdGVFbGVtZW50KCJsaSIpCmQuYXBwZW5kQ2hpbGQobikKbT1KLllFKG4pCmlmKG8uYT09
+PUMuWTIpe20uZ0QobikuaSgwLCJkaXIiKQpsPWUuY3JlYXRlRWxlbWVudCgic3BhbiIpCm4uYXBwZW5k
+Q2hpbGQobCkKbT1KLllFKGwpCm0uZ0QobCkuaSgwLCJhcnJvdyIpCm0uc2hmKGwsIiYjeDI1QkM7IikK
+az1lLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpuLmFwcGVuZENoaWxkKGspCkoubDUoaywnPHNwYW4gY2xh
+c3M9Im1hdGVyaWFsLWljb25zIj5mb2xkZXJfb3Blbjwvc3Bhbj4nKQpuLmFwcGVuZENoaWxkKGUuY3Jl
+YXRlVGV4dE5vZGUoby5iKSkKTC50WChuLG8uYykKTC5reihsKX1lbHNle20uc2hmKG4sJzxzcGFuIGNs
+YXNzPSJtYXRlcmlhbC1pY29ucyI+aW5zZXJ0X2RyaXZlX2ZpbGU8L3NwYW4+JykKaj1lLmNyZWF0ZUVs
+ZW1lbnQoImEiKQpuLmFwcGVuZENoaWxkKGopCm09Si5ZRShqKQptLmdEKGopLmkoMCwibmF2LWxpbmsi
+KQpqLnNldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGopKS5PKCJuYW1lIiksby5k
+KQpqLnNldEF0dHJpYnV0ZSgiaHJlZiIsTC5RNChvLmUsUC5GbChyLHIpKSkKai5hcHBlbmRDaGlsZChl
+LmNyZWF0ZVRleHROb2RlKG8uYikpCm09bS5nVmwoaikKaT1tLiR0aQpoPWkuQygifigxKT8iKS5hKG5l
+dyBMLlREKCkpCnEuYShudWxsKQpXLkpFKG0uYSxtLmIsaCwhMSxpLmMpCmc9by5mCmlmKHR5cGVvZiBn
+IT09Im51bWJlciIpcmV0dXJuIGcub3MoKQppZihnPjApe2Y9ZS5jcmVhdGVFbGVtZW50KCJzcGFuIikK
+bi5hcHBlbmRDaGlsZChmKQpKLmRSKGYpLmkoMCwiZWRpdC1jb3VudCIpCm09IiIrZysiICIKaWYoZz09
+PTEpaT0iZWRpdCIKZWxzZSBpPSJlZGl0cyIKZi5zZXRBdHRyaWJ1dGUoInRpdGxlIixtK2kpCmYuYXBw
+ZW5kQ2hpbGQoZS5jcmVhdGVUZXh0Tm9kZShDLmpuLncoZykpKX19fX0sCkZ6OmZ1bmN0aW9uKGEsYil7
+dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoPWEuYQppZihoPT1udWxsKXJldHVybgpzPWRvY3VtZW50
+CnI9cy5jcmVhdGVFbGVtZW50KCJwIikKcT1iLmFwcGVuZENoaWxkKHIpCnI9cy5jcmVhdGVFbGVtZW50
+KCJzcGFuIikKcD10LmkKSi5NdShyLEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0scCkpCnIuYXBwZW5k
+Q2hpbGQocy5jcmVhdGVUZXh0Tm9kZSgiQWN0aW9ucyIpKQpxLmFwcGVuZENoaWxkKHIpCnEuYXBwZW5k
+Q2hpbGQocy5jcmVhdGVUZXh0Tm9kZSgiOiIpKQpvPXMuY3JlYXRlRWxlbWVudCgicCIpCmIuYXBwZW5k
+Q2hpbGQobykKZm9yKHI9aC5sZW5ndGgsbj10LlEsbT0wO208aC5sZW5ndGg7aC5sZW5ndGg9PT1yfHwo
+MCxILmxrKShoKSwrK20pe2w9aFttXQprPXMuY3JlYXRlRWxlbWVudCgiYSIpCm8uYXBwZW5kQ2hpbGQo
+aykKay5hcHBlbmRDaGlsZChzLmNyZWF0ZVRleHROb2RlKGwuYSkpCmsuc2V0QXR0cmlidXRlKCJocmVm
+IixsLmIpCmo9bi5hKEguVk0oWyJhZGQtaGludC1saW5rIiwiYmVmb3JlLWFwcGx5IiwiYnV0dG9uIl0s
+cCkpCmk9Si5kUihrKQppLlYxKDApCmkuRlYoMCxqKX19LApDQzpmdW5jdGlvbihhOSxiMCxiMSl7dmFy
+IHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEsYTIsYTMsYTQsYTUsYTYs
+YTcsYTgKZm9yKHM9YTkuZixyPXMubGVuZ3RoLHE9dC5pLHA9dC5RLG89dC5rLG49by5DKCJ+KDEpPyIp
+LG09dC5aLG89by5jLGw9MDtsPHMubGVuZ3RoO3MubGVuZ3RoPT09cnx8KDAsSC5saykocyksKytsKXtr
+PXNbbF0Kaj1kb2N1bWVudAppPWouY3JlYXRlRWxlbWVudCgicCIpCmg9cC5hKEguVk0oWyJ0cmFjZSJd
+LHEpKQpnPUouZFIoaSkKZy5WMSgwKQpnLkZWKDAsaCkKZj1iMC5hcHBlbmRDaGlsZChpKQppPWouY3Jl
+YXRlRWxlbWVudCgic3BhbiIpCmg9cC5hKEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0scSkpCmc9Si5k
+UihpKQpnLlYxKDApCmcuRlYoMCxoKQppLmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5vZGUoay5hKSkK
+Zi5hcHBlbmRDaGlsZChpKQpmLmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5vZGUoIjoiKSkKaT1qLmNy
+ZWF0ZUVsZW1lbnQoInVsIikKaD1wLmEoSC5WTShbInRyYWNlIl0scSkpCmc9Si5kUihpKQpnLlYxKDAp
+CmcuRlYoMCxoKQplPWYuYXBwZW5kQ2hpbGQoaSkKZm9yKGk9ay5iLGg9aS5sZW5ndGgsZD0wO2Q8aS5s
+ZW5ndGg7aS5sZW5ndGg9PT1ofHwoMCxILmxrKShpKSwrK2Qpe2M9aVtkXQpiPWouY3JlYXRlRWxlbWVu
+dCgibGkiKQplLmFwcGVuZENoaWxkKGIpCmE9ai5jcmVhdGVFbGVtZW50KCJzcGFuIikKYTA9cC5hKEgu
+Vk0oWyJmdW5jdGlvbiJdLHEpKQpnPUouZFIoYSkKZy5WMSgwKQpnLkZWKDAsYTApCmEwPWMuYgpMLmtE
+KGEsYTA9PW51bGw/InVua25vd24iOmEwKQpiLmFwcGVuZENoaWxkKGEpCmExPWMuYwppZihhMSE9bnVs
+bCl7Yi5hcHBlbmRDaGlsZChqLmNyZWF0ZVRleHROb2RlKCIgKCIpKQphMj1hMS5iCmEzPWouY3JlYXRl
+RWxlbWVudCgiYSIpCmEzLmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5vZGUoSC5FaihhMS5jKSsiOiIr
+SC5FaihhMikpKQphMy5zZXRBdHRyaWJ1dGUoImhyZWYiLGExLmEpCmEzLmNsYXNzTGlzdC5hZGQoIm5h
+di1saW5rIikKYi5hcHBlbmRDaGlsZChhMykKYi5hcHBlbmRDaGlsZChqLmNyZWF0ZVRleHROb2RlKCIp
+IikpfWIuYXBwZW5kQ2hpbGQoai5jcmVhdGVUZXh0Tm9kZSgiOiAiKSkKYT1jLmEKTC5rRChiLGE9PW51
+bGw/InVua25vd24iOmEpCmE9Yy5kCmlmKGEubGVuZ3RoIT09MCl7YTA9ai5jcmVhdGVFbGVtZW50KCJw
+IikKYTQ9cC5hKEguVk0oWyJkcmF3ZXIiLCJiZWZvcmUtYXBwbHkiXSxxKSkKZz1KLmRSKGEwKQpnLlYx
+KDApCmcuRlYoMCxhNCkKYTU9Yi5hcHBlbmRDaGlsZChhMCkKZm9yKGEwPWEubGVuZ3RoLGE2PTA7YTY8
+YS5sZW5ndGg7YS5sZW5ndGg9PT1hMHx8KDAsSC5saykoYSksKythNil7YTc9YVthNl0KYTQ9ai5jcmVh
+dGVFbGVtZW50KCJidXR0b24iKQphOD1uLmEobmV3IEwuQVMoYTcsYTEpKQptLmEobnVsbCkKVy5KRShh
+NCwiY2xpY2siLGE4LCExLG8pCmE0LmFwcGVuZENoaWxkKGouY3JlYXRlVGV4dE5vZGUoTS5PWChhNy5h
+KSkpCmE1LmFwcGVuZENoaWxkKGE0KX19fX19LAprRDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT1ILlZN
+KGIuc3BsaXQoIi4iKSx0LnMpLHA9Qy5ObS5ndEgocSksbz1kb2N1bWVudAphLmFwcGVuZENoaWxkKG8u
+Y3JlYXRlVGV4dE5vZGUocCkpCmZvcihwPUgucUMocSwxLG51bGwsdC5OKSxwPW5ldyBILmE3KHAscC5n
+QShwKSxwLiR0aS5DKCJhNzxhTC5FPiIpKSxzPUouWUUoYSk7cC5GKCk7KXtyPXAuZApzLm56KGEsImJl
+Zm9yZWVuZCIsIiYjODIwMzsuIixudWxsLG51bGwpCmEuYXBwZW5kQ2hpbGQoby5jcmVhdGVUZXh0Tm9k
+ZShyKSl9fSwKZTpmdW5jdGlvbiBlKCl7fSwKVlc6ZnVuY3Rpb24gVlcoYSxiLGMpe3RoaXMuYT1hCnRo
+aXMuYj1iCnRoaXMuYz1jfSwKb1o6ZnVuY3Rpb24gb1ooKXt9LApqcjpmdW5jdGlvbiBqcigpe30sCnFs
+OmZ1bmN0aW9uIHFsKCl7fSwKSGk6ZnVuY3Rpb24gSGkoKXt9LApCVDpmdW5jdGlvbiBCVCgpe30sClBZ
+OmZ1bmN0aW9uIFBZKCl7fSwKTDpmdW5jdGlvbiBMKCl7fSwKV3g6ZnVuY3Rpb24gV3goYSxiKXt0aGlz
+LmE9YQp0aGlzLmI9Yn0sCkFPOmZ1bmN0aW9uIEFPKGEpe3RoaXMuYT1hfSwKZE46ZnVuY3Rpb24gZE4o
+YSl7dGhpcy5hPWF9LApIbzpmdW5jdGlvbiBIbyhhKXt0aGlzLmE9YX0sCnh6OmZ1bmN0aW9uIHh6KGEs
+Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LApJQzpmdW5jdGlvbiBJQygpe30sCmZDOmZ1bmN0aW9uIGZDKGEs
+Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp1ZTpmdW5jdGlvbiB1ZSgpe30sCm5UOmZ1bmN0aW9uIG5UKGEs
+YixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3RoaXMuYT1h
+fSwKZVg6ZnVuY3Rpb24gZVgoKXt9LApFRTpmdW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5i
+PWIKdGhpcy5jPWN9LApRTDpmdW5jdGlvbiBRTChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVlM6ZnVu
+Y3Rpb24gVlMoYSl7dGhpcy5hPWF9LApURDpmdW5jdGlvbiBURCgpe30sCkFTOmZ1bmN0aW9uIEFTKGEs
+Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LApYQTpmdW5jdGlvbiBYQSgpe30sCm1LOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHIscSxwLG8sbixtPUguVk0oW10sdC5jUSkKZm9yKHM9Si5JVCh0LlUuYShhKSk7cy5GKCk7KXty
+PXMuZ2woKQpxPUouVTYocikKcD1MLnAyKEguaChxLnEociwidHlwZSIpKSkKbz1ILmgocS5xKHIsIm5h
+bWUiKSkKbj1xLnEociwic3VidHJlZSIpCm49bj09bnVsbD9udWxsOkwubUsobikKQy5ObS5pKG0sbmV3
+IEwuWloocCxvLG4sSC5oKHEucShyLCJwYXRoIikpLEguaChxLnEociwiaHJlZiIpKSxILnVQKHEucShy
+LCJlZGl0Q291bnQiKSkpKX1yZXR1cm4gbX0sClZEOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1ILlZNKFtd
+LHQuRykKZm9yKHM9YS5sZW5ndGgscj0wO3I8YS5sZW5ndGg7YS5sZW5ndGg9PT1zfHwoMCxILmxrKShh
+KSwrK3IpQy5ObS5pKHEsYVtyXS5MdCgpKQpyZXR1cm4gcX0sCnAyOmZ1bmN0aW9uKGEpe3N3aXRjaChh
+KXtjYXNlImRpcmVjdG9yeSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpkZWZhdWx0
+OnRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIitI
+LkVqKGEpKSl9fSwKdnk6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5ZMjpyZXR1cm4iZGlyZWN0
+b3J5IgpjYXNlIEMucmY6cmV0dXJuImZpbGUifXRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2
+aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIithLncoMCkpKX0sClpaOmZ1bmN0aW9uIFpaKGEsYixjLGQs
+ZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKTzk6ZnVu
+Y3Rpb24gTzkoYSl7dGhpcy5iPWF9LApJVjpmdW5jdGlvbiBJVihhLGIsYyxkKXt2YXIgXz10aGlzCl8u
+ZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHAsbyxu
+PWIueFooYSkKYi5oSyhhKQppZihuIT1udWxsKWE9Si5LVihhLG4ubGVuZ3RoKQpzPXQucwpyPUguVk0o
+W10scykKcT1ILlZNKFtdLHMpCnM9YS5sZW5ndGgKaWYocyE9PTAmJmIucjQoQy54Qi5XKGEsMCkpKXtp
+ZigwPj1zKXJldHVybiBILk9IKGEsMCkKQy5ObS5pKHEsYVswXSkKcD0xfWVsc2V7Qy5ObS5pKHEsIiIp
+CnA9MH1mb3Iobz1wO288czsrK28paWYoYi5yNChDLnhCLlcoYSxvKSkpe0MuTm0uaShyLEMueEIuTmoo
+YSxwLG8pKQpDLk5tLmkocSxhW29dKQpwPW8rMX1pZihwPHMpe0MuTm0uaShyLEMueEIuRyhhLHApKQpD
+Lk5tLmkocSwiIil9cmV0dXJuIG5ldyBYLldEKGIsbixyLHEpfSwKV0Q6ZnVuY3Rpb24gV0QoYSxiLGMs
+ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCkk3OmZ1bmN0aW9uKGEpe3JldHVy
+biBuZXcgWC5kdihhKX0sCmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1bmN0aW9u
+KCl7dmFyIHMscj1udWxsCmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIilyZXR1cm4gJC5FYigpCnM9UC51
+bygpCmlmKCFDLnhCLlRjKHMuZ0lpKHMpLCIvIikpcmV0dXJuICQuRWIoKQppZihQLktMKHIsImEvYiIs
+cixyLHIscixyKS50NCgpPT09ImFcXGIiKXJldHVybiAkLktrKCkKcmV0dXJuICQuYkQoKX0sCnpMOmZ1
+bmN0aW9uIHpMKCl7fX0sRT17T0Y6ZnVuY3Rpb24gT0YoYSxiLGMpe3RoaXMuZD1hCnRoaXMuZT1iCnRo
+aXMuZj1jfX0sRj17cnU6ZnVuY3Rpb24gcnUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpfLmU9Ygpf
+LmY9YwpfLnI9ZH19LEQ9ewphYjpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89bnVsbAp0cnl7bz1QLnVv
+KCl9Y2F0Y2gocyl7aWYodC5nOC5iKEguUnUocykpKXtyPSQuRmYKaWYociE9bnVsbClyZXR1cm4gcgp0
+aHJvdyBzfWVsc2UgdGhyb3cgc31pZihKLlJNKG8sJC5JNikpe3I9JC5GZgpyLnRvU3RyaW5nCnJldHVy
+biByfSQuSTY9bwppZigkLkhrKCk9PSQuRWIoKSlyPSQuRmY9by5aSSgiLiIpLncoMCkKZWxzZXtxPW8u
+dDQoKQpwPXEubGVuZ3RoLTEKcj0kLkZmPXA9PT0wP3E6Qy54Qi5OaihxLDAscCl9cmV0dXJuIHJ9fQp2
+YXIgdz1bQyxILEosUCxXLE0sVSxCLFQsTCxYLE8sRSxGLERdCmh1bmtIZWxwZXJzLnNldEZ1bmN0aW9u
+TmFtZXNJZk5lY2Vzc2FyeSh3KQp2YXIgJD17fQpILkZLLnByb3RvdHlwZT17fQpKLnZCLnByb3RvdHlw
+ZT17CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGE9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBI
+LmVRKGEpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5FaihILk0oYSkpKyIn
+In0sCmU3OmZ1bmN0aW9uKGEsYil7dC5vLmEoYikKdGhyb3cgSC5iKFAubHIoYSxiLmdXYSgpLGIuZ25k
+KCksYi5nVm0oKSkpfX0KSi55RS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmco
+YSl9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIGE/NTE5MDE4OjIxODE1OX0sCiRpYTI6MX0KSi53ZS5w
+cm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3JldHVybiBudWxsPT1ifSwKdzpmdW5jdGlvbihhKXty
+ZXR1cm4ibnVsbCJ9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LAplNzpmdW5jdGlvbihhLGIpe3Jl
+dHVybiB0aGlzLlNqKGEsdC5vLmEoYikpfSwKJGljODoxfQpKLk1GLnByb3RvdHlwZT17CmdpTzpmdW5j
+dGlvbihhKXtyZXR1cm4gMH0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdm06MX0K
+Si5pQy5wcm90b3R5cGU9e30KSi5rZC5wcm90b3R5cGU9e30KSi5jNS5wcm90b3R5cGU9ewp3OmZ1bmN0
+aW9uKGEpe3ZhciBzPWFbJC53KCldCmlmKHM9PW51bGwpcmV0dXJuIHRoaXMudChhKQpyZXR1cm4iSmF2
+YVNjcmlwdCBmdW5jdGlvbiBmb3IgIitILkVqKEouaihzKSl9LAokaUVIOjF9CkouamQucHJvdG90eXBl
+PXsKZHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEgualYoYSxILnQ2KGEpLkMoIkA8MT4iKS5LcShi
+KS5DKCJqVjwxLDI+IikpfSwKaTpmdW5jdGlvbihhLGIpe0gudDYoYSkuYy5hKGIpCmlmKCEhYS5maXhl
+ZCRsZW5ndGgpSC52KFAuTDQoImFkZCIpKQphLnB1c2goYil9LApXNDpmdW5jdGlvbihhLGIpe3ZhciBz
+CmlmKCEhYS5maXhlZCRsZW5ndGgpSC52KFAuTDQoInJlbW92ZUF0IikpCnM9YS5sZW5ndGgKaWYoYj49
+cyl0aHJvdyBILmIoUC5PNyhiLG51bGwpKQpyZXR1cm4gYS5zcGxpY2UoYiwxKVswXX0sClVHOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgcyxyCkgudDYoYSkuQygiY1g8MT4iKS5hKGMpCmlmKCEhYS5maXhlZCRsZW5n
+dGgpSC52KFAuTDQoImluc2VydEFsbCIpKQpQLndBKGIsMCxhLmxlbmd0aCwiaW5kZXgiKQppZighdC5i
+LmIoYykpYz1KLlJYKGMpCnM9Si5IbShjKQphLmxlbmd0aD1hLmxlbmd0aCtzCnI9YitzCnRoaXMuWVco
+YSxyLGEubGVuZ3RoLGEsYikKdGhpcy52ZyhhLGIscixjKX0sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMK
+SC50NihhKS5DKCJjWDwxPiIpLmEoYikKaWYoISFhLmZpeGVkJGxlbmd0aClILnYoUC5MNCgiYWRkQWxs
+IikpCmZvcihzPUouSVQoYik7cy5GKCk7KWEucHVzaChzLmdsKCkpfSwKRTI6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciBzPUgudDYoYSkKcmV0dXJuIG5ldyBILmxKKGEscy5LcShjKS5DKCIxKDIpIikuYShiKSxzLkMo
+IkA8MT4iKS5LcShjKS5DKCJsSjwxLDI+IikpfSwKSDpmdW5jdGlvbihhLGIpe3ZhciBzLHI9UC5POChh
+Lmxlbmd0aCwiIiwhMSx0Lk4pCmZvcihzPTA7czxhLmxlbmd0aDsrK3MpdGhpcy5ZKHIscyxILkVqKGFb
+c10pKQpyZXR1cm4gci5qb2luKGIpfSwKZVI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5xQyhhLGIsbnVs
+bCxILnQ2KGEpLmMpfSwKTjA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxCmQuYShiKQpILnQ2KGEp
+LktxKGQpLkMoIjEoMSwyKSIpLmEoYykKcz1hLmxlbmd0aApmb3Iocj1iLHE9MDtxPHM7KytxKXtyPWMu
+JDIocixhW3FdKQppZihhLmxlbmd0aCE9PXMpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiByfSwKSHQ6
+ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvCkgudDYoYSkuQygiYTIoMSkiKS5hKGIpCnM9YS5sZW5n
+dGgKZm9yKHI9bnVsbCxxPSExLHA9MDtwPHM7KytwKXtvPWFbcF0KaWYoSC5vVChiLiQxKG8pKSl7aWYo
+cSl0aHJvdyBILmIoSC5BbSgpKQpyPW8KcT0hMH1pZihzIT09YS5sZW5ndGgpdGhyb3cgSC5iKFAuYTQo
+YSkpfWlmKHEpcmV0dXJuIHIKdGhyb3cgSC5iKEguV3AoKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjww
+fHxiPj1hLmxlbmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKZ3RIOmZ1bmN0aW9uKGEp
+e2lmKGEubGVuZ3RoPjApcmV0dXJuIGFbMF0KdGhyb3cgSC5iKEguV3AoKSl9LApnclo6ZnVuY3Rpb24o
+YSl7dmFyIHM9YS5sZW5ndGgKaWYocz4wKXJldHVybiBhW3MtMV0KdGhyb3cgSC5iKEguV3AoKSl9LApZ
+VzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciBzLHIscSxwLG8KSC50NihhKS5DKCJjWDwxPiIpLmEoZCkK
+aWYoISFhLmltbXV0YWJsZSRsaXN0KUgudihQLkw0KCJzZXRSYW5nZSIpKQpQLmpCKGIsYyxhLmxlbmd0
+aCkKcz1jLWIKaWYocz09PTApcmV0dXJuClAuazEoZSwic2tpcENvdW50IikKaWYodC5qLmIoZCkpe3I9
+ZApxPWV9ZWxzZXtyPUouQTUoZCxlKS50dCgwLCExKQpxPTB9cD1KLlU2KHIpCmlmKHErcz5wLmdBKHIp
+KXRocm93IEguYihILmFyKCkpCmlmKHE8Yilmb3Iobz1zLTE7bz49MDstLW8pYVtiK29dPXAucShyLHEr
+bykKZWxzZSBmb3Iobz0wO288czsrK28pYVtiK29dPXAucShyLHErbyl9LAp2ZzpmdW5jdGlvbihhLGIs
+YyxkKXtyZXR1cm4gdGhpcy5ZVyhhLGIsYyxkLDApfSwKVnI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCkgu
+dDYoYSkuQygiYTIoMSkiKS5hKGIpCnM9YS5sZW5ndGgKZm9yKHI9MDtyPHM7KytyKXtpZihILm9UKGIu
+JDEoYVtyXSkpKXJldHVybiEwCmlmKGEubGVuZ3RoIT09cyl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJu
+ITF9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciBzCmZvcihzPTA7czxhLmxlbmd0aDsrK3MpaWYoSi5STShh
+W3NdLGIpKXJldHVybiEwCnJldHVybiExfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aD09
+PTB9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RoIT09MH0sCnc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIFAuV0UoYSwiWyIsIl0iKX0sCnR0OmZ1bmN0aW9uKGEsYil7dmFyIHM9SC5WTShhLnNsaWNlKDAp
+LEgudDYoYSkpCnJldHVybiBzfSwKYnI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMudHQoYSwhMCl9LApn
+a3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBKLm0xKGEsYS5sZW5ndGgsSC50NihhKS5DKCJtMTwxPiIp
+KX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gSC5lUShhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBh
+Lmxlbmd0aH0sCnNBOmZ1bmN0aW9uKGEsYil7aWYoISFhLmZpeGVkJGxlbmd0aClILnYoUC5MNCgic2V0
+IGxlbmd0aCIpKQppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLG51bGwsIm5ld0xlbmd0aCIsbnVsbCkp
+CmEubGVuZ3RoPWJ9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj1hLmxlbmd0aHx8YjwwKXRo
+cm93IEguYihILkhZKGEsYikpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7SC50NihhKS5j
+LmEoYykKaWYoISFhLmltbXV0YWJsZSRsaXN0KUgudihQLkw0KCJpbmRleGVkIHNldCIpKQppZihiPj1h
+Lmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAok
+aXpNOjF9CkouUG8ucHJvdG90eXBlPXt9CkoubTEucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPXIuYSxwPXEubGVuZ3RoCmlmKHIu
+YiE9PXApdGhyb3cgSC5iKEgubGsocSkpCnM9ci5jCmlmKHM+PXApe3Iuc00obnVsbCkKcmV0dXJuITF9
+ci5zTShxW3NdKTsrK3IuYwpyZXR1cm4hMH0sCnNNOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5D
+KCIxPyIpLmEoYSl9LAokaUFuOjF9CkoucUkucHJvdG90eXBlPXsKelE6ZnVuY3Rpb24oYSl7aWYoYT4w
+KXtpZihhIT09MS8wKXJldHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAwLU1h
+dGgucm91bmQoMC1hKQp0aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCnc6ZnVuY3Rpb24o
+YSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9LApnaU86ZnVuY3Rp
+b24oYSl7dmFyIHMscixxLHAsbz1hfDAKaWYoYT09PW8pcmV0dXJuIDUzNjg3MDkxMSZvCnM9TWF0aC5h
+YnMoYSkKcj1NYXRoLmxvZyhzKS8wLjY5MzE0NzE4MDU1OTk0NTN8MApxPU1hdGgucG93KDIscikKcD1z
+PDE/cy9xOnEvcwpyZXR1cm4gNTM2ODcwOTExJigocCo5MDA3MTk5MjU0NzQwOTkyfDApKyhwKjM1NDIy
+NDMxODExNzY1MjF8MCkpKjU5OTE5NytyKjEyNTl9LAp6WTpmdW5jdGlvbihhLGIpe3ZhciBzPWElYgpp
+ZihzPT09MClyZXR1cm4gMAppZihzPjApcmV0dXJuIHMKaWYoYjwwKXJldHVybiBzLWIKZWxzZSByZXR1
+cm4gcytifSwKQlU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4oYXwwKT09PWE/YS9ifDA6dGhpcy5ESihhLGIp
+fSwKREo6ZnVuY3Rpb24oYSxiKXt2YXIgcz1hL2IKaWYocz49LTIxNDc0ODM2NDgmJnM8PTIxNDc0ODM2
+NDcpcmV0dXJuIHN8MAppZihzPjApe2lmKHMhPT0xLzApcmV0dXJuIE1hdGguZmxvb3Iocyl9ZWxzZSBp
+ZihzPi0xLzApcmV0dXJuIE1hdGguY2VpbChzKQp0aHJvdyBILmIoUC5MNCgiUmVzdWx0IG9mIHRydW5j
+YXRpbmcgZGl2aXNpb24gaXMgIitILkVqKHMpKyI6ICIrSC5FaihhKSsiIH4vICIrYikpfSwKd0c6ZnVu
+Y3Rpb24oYSxiKXt2YXIgcwppZihhPjApcz10aGlzLnAzKGEsYikKZWxzZXtzPWI+MzE/MzE6YgpzPWE+
+PnM+Pj4wfXJldHVybiBzfSwKYmY6ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5iKEgudEwoYikp
+CnJldHVybiB0aGlzLnAzKGEsYil9LApwMzpmdW5jdGlvbihhLGIpe3JldHVybiBiPjMxPzA6YT4+PmJ9
+LAokaUNQOjEsCiRpTFo6MX0KSi5iVS5wcm90b3R5cGU9eyRpSWY6MX0KSi5WQS5wcm90b3R5cGU9e30K
+Si5Eci5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILkhZKGEsYikp
+CmlmKGI+PWEubGVuZ3RoKUgudihILkhZKGEsYikpCnJldHVybiBhLmNoYXJDb2RlQXQoYil9LApXOmZ1
+bmN0aW9uKGEsYil7aWYoYj49YS5sZW5ndGgpdGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGEuY2hh
+ckNvZGVBdChiKX0sCmRkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILnVuKGIsYSwwKX0sCmg6ZnVu
+Y3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyIpdGhyb3cgSC5iKFAuTDMoYixudWxsLG51bGwp
+KQpyZXR1cm4gYStifSwKVGM6ZnVuY3Rpb24oYSxiKXt2YXIgcz1iLmxlbmd0aCxyPWEubGVuZ3RoCmlm
+KHM+cilyZXR1cm4hMQpyZXR1cm4gYj09PXRoaXMuRyhhLHItcyl9LAppNzpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgcz1QLmpCKGIsYyxhLmxlbmd0aCkscj1hLnN1YnN0cmluZygwLGIpLHE9YS5zdWJzdHJpbmco
+cykKcmV0dXJuIHIrZCtxfSwKUWk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKGM8MHx8Yz5hLmxlbmd0
+aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKcz1jK2IubGVuZ3RoCmlmKHM+
+YS5sZW5ndGgpcmV0dXJuITEKcmV0dXJuIGI9PT1hLnN1YnN0cmluZyhjLHMpfSwKbjpmdW5jdGlvbihh
+LGIpe3JldHVybiB0aGlzLlFpKGEsYiwwKX0sCk5qOmZ1bmN0aW9uKGEsYixjKXtpZihjPT1udWxsKWM9
+YS5sZW5ndGgKaWYoYjwwKXRocm93IEguYihQLk83KGIsbnVsbCkpCmlmKGI+Yyl0aHJvdyBILmIoUC5P
+NyhiLG51bGwpKQppZihjPmEubGVuZ3RoKXRocm93IEguYihQLk83KGMsbnVsbCkpCnJldHVybiBhLnN1
+YnN0cmluZyhiLGMpfSwKRzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLk5qKGEsYixudWxsKX0sCmhj
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLnRvTG93ZXJDYXNlKCl9LApiUzpmdW5jdGlvbihhKXt2YXIgcyxy
+LHEscD1hLnRyaW0oKSxvPXAubGVuZ3RoCmlmKG89PT0wKXJldHVybiBwCmlmKHRoaXMuVyhwLDApPT09
+MTMzKXtzPUoubW0ocCwxKQppZihzPT09bylyZXR1cm4iIn1lbHNlIHM9MApyPW8tMQpxPXRoaXMubShw
+LHIpPT09MTMzP0ouYzEocCxyKTpvCmlmKHM9PT0wJiZxPT09bylyZXR1cm4gcApyZXR1cm4gcC5zdWJz
+dHJpbmcocyxxKX0sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZigwPj1iKXJldHVybiIiCmlmKGI9
+PT0xfHxhLmxlbmd0aD09PTApcmV0dXJuIGEKaWYoYiE9PWI+Pj4wKXRocm93IEguYihDLkVxKQpmb3Io
+cz1hLHI9IiI7ITA7KXtpZigoYiYxKT09PTEpcj1zK3IKYj1iPj4+MQppZihiPT09MClicmVhawpzKz1z
+fXJldHVybiByfSwKWFU6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzCmlmKGM8MHx8Yz5hLmxlbmd0aCl0aHJv
+dyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKcz1hLmluZGV4T2YoYixjKQpyZXR1cm4g
+c30sCk9ZOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuWFUoYSxiLDApfSwKUGs6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciBzLHIKaWYoYz09bnVsbCljPWEubGVuZ3RoCmVsc2UgaWYoYzwwfHxjPmEubGVuZ3RoKXRo
+cm93IEguYihQLlRFKGMsMCxhLmxlbmd0aCxudWxsLG51bGwpKQpzPWIubGVuZ3RoCnI9YS5sZW5ndGgK
+aWYoYytzPnIpYz1yLXMKcmV0dXJuIGEubGFzdEluZGV4T2YoYixjKX0sCmNuOmZ1bmN0aW9uKGEsYil7
+cmV0dXJuIHRoaXMuUGsoYSxiLG51bGwpfSwKSXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPWEubGVuZ3Ro
+CmlmKGM+cyl0aHJvdyBILmIoUC5URShjLDAscyxudWxsLG51bGwpKQpyZXR1cm4gSC5tMihhLGIsYyl9
+LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLklzKGEsYiwwKX0sCnc6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGF9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHMscixxCmZvcihzPWEubGVuZ3RoLHI9MCxxPTA7cTxz
+OysrcSl7cj01MzY4NzA5MTEmcithLmNoYXJDb2RlQXQocSkKcj01MzY4NzA5MTEmcisoKDUyNDI4NyZy
+KTw8MTApCnJePXI+PjZ9cj01MzY4NzA5MTEmcisoKDY3MTA4ODYzJnIpPDwzKQpyXj1yPj4xMQpyZXR1
+cm4gNTM2ODcwOTExJnIrKCgxNjM4MyZyKTw8MTUpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVu
+Z3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKaWYoYj49YS5sZW5ndGh8fCExKXRocm93IEguYihI
+LkhZKGEsYikpCnJldHVybiBhW2JdfSwKJGl2WDoxLAokaXFVOjF9CkguQlIucHJvdG90eXBlPXsKZ2t6
+OmZ1bmN0aW9uKGEpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIG5ldyBILkU3KEouSVQodGhpcy5nT04o
+KSkscy5DKCJAPDE+IikuS3Eocy5RWzFdKS5DKCJFNzwxLDI+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0
+dXJuIEouSG0odGhpcy5nT04oKSl9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudVUodGhpcy5nT04o
+KSl9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIEouRjcodGhpcy5nT04oKSl9LAplUjpmdW5jdGlvbihh
+LGIpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIEguR0ooSi5BNSh0aGlzLmdPTigpLGIpLHMuYyxzLlFb
+MV0pfSwKRTpmdW5jdGlvbihhLGIpe3JldHVybiBILkxoKHRoaXMpLlFbMV0uYShKLkdBKHRoaXMuZ09O
+KCksYikpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuZ09OKCkpfX0KSC5FNy5wcm90b3R5
+cGU9ewpGOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5GKCl9LApnbDpmdW5jdGlvbigpe3JldHVybiB0
+aGlzLiR0aS5RWzFdLmEodGhpcy5hLmdsKCkpfSwKJGlBbjoxfQpILlp5LnByb3RvdHlwZT17CmdPTjpm
+dW5jdGlvbigpe3JldHVybiB0aGlzLmF9fQpILm9sLnByb3RvdHlwZT17JGliUToxfQpILlVxLnByb3Rv
+dHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy4kdGkuUVsxXS5hKEoueDkodGhpcy5hLEgu
+dVAoYikpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzPXRoaXMuJHRpCkoudTkodGhpcy5hLGIscy5j
+LmEocy5RWzFdLmEoYykpKX0sCiRpYlE6MSwKJGl6TToxfQpILmpWLnByb3RvdHlwZT17CmRyOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIG5ldyBILmpWKHRoaXMuYSx0aGlzLiR0aS5DKCJAPDE+IikuS3EoYikuQygi
+alY8MSwyPiIpKX0sCmdPTjpmdW5jdGlvbigpe3JldHVybiB0aGlzLmF9fQpILm4ucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMhPW51bGw/IkxhdGVJbml0aWFsaXphdGlv
+bkVycm9yOiAiK3M6IkxhdGVJbml0aWFsaXphdGlvbkVycm9yIn19CkgucWoucHJvdG90eXBlPXsKZ0E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMu
+eEIubSh0aGlzLmEsSC51UChiKSl9fQpILmJRLnByb3RvdHlwZT17fQpILmFMLnByb3RvdHlwZT17Cmdr
+ejpmdW5jdGlvbihhKXt2YXIgcz10aGlzCnJldHVybiBuZXcgSC5hNyhzLHMuZ0EocyksSC5MaChzKS5D
+KCJhNzxhTC5FPiIpKX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApI
+OmZ1bmN0aW9uKGEsYil7dmFyIHMscixxLHA9dGhpcyxvPXAuZ0EocCkKaWYoYi5sZW5ndGghPT0wKXtp
+ZihvPT09MClyZXR1cm4iIgpzPUguRWoocC5FKDAsMCkpCmlmKG8hPT1wLmdBKHApKXRocm93IEguYihQ
+LmE0KHApKQpmb3Iocj1zLHE9MTtxPG87KytxKXtyPXIrYitILkVqKHAuRSgwLHEpKQppZihvIT09cC5n
+QShwKSl0aHJvdyBILmIoUC5hNChwKSl9cmV0dXJuIHIuY2hhckNvZGVBdCgwKT09MD9yOnJ9ZWxzZXtm
+b3IocT0wLHI9IiI7cTxvOysrcSl7cis9SC5FaihwLkUoMCxxKSkKaWYobyE9PXAuZ0EocCkpdGhyb3cg
+SC5iKFAuYTQocCkpfXJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfX0sCmV2OmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIHRoaXMuR0coMCxILkxoKHRoaXMpLkMoImEyKGFMLkUpIikuYShiKSl9LApFMjpmdW5j
+dGlvbihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEgubEoodGhpcyxzLktxKGMpLkMo
+IjEoYUwuRSkiKS5hKGIpLHMuQygiQDxhTC5FPiIpLktxKGMpLkMoImxKPDEsMj4iKSl9LAplUjpmdW5j
+dGlvbihhLGIpe3JldHVybiBILnFDKHRoaXMsYixudWxsLEguTGgodGhpcykuQygiYUwuRSIpKX0sCnR0
+OmZ1bmN0aW9uKGEsYil7cmV0dXJuIFAuQ0godGhpcywhMCxILkxoKHRoaXMpLkMoImFMLkUiKSl9LApi
+cjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy50dChhLCEwKX19CkgubkgucHJvdG90eXBlPXsKSGQ6ZnVu
+Y3Rpb24oYSxiLGMsZCl7dmFyIHMscj10aGlzLmIKUC5rMShyLCJzdGFydCIpCnM9dGhpcy5jCmlmKHMh
+PW51bGwpe1AuazEocywiZW5kIikKaWYocj5zKXRocm93IEguYihQLlRFKHIsMCxzLCJzdGFydCIsbnVs
+bCkpfX0sCmdVRDpmdW5jdGlvbigpe3ZhciBzPUouSG0odGhpcy5hKSxyPXRoaXMuYwppZihyPT1udWxs
+fHxyPnMpcmV0dXJuIHMKcmV0dXJuIHJ9LApnQXM6ZnVuY3Rpb24oKXt2YXIgcz1KLkhtKHRoaXMuYSks
+cj10aGlzLmIKaWYocj5zKXJldHVybiBzCnJldHVybiByfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHMscj1K
+LkhtKHRoaXMuYSkscT10aGlzLmIKaWYocT49cilyZXR1cm4gMApzPXRoaXMuYwppZihzPT1udWxsfHxz
+Pj1yKXJldHVybiByLXEKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCnJldHVybiBz
+LXF9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcyxyPXMuZ0FzKCkrYgppZihiPDB8fHI+PXMuZ1VE
+KCkpdGhyb3cgSC5iKFAuQ2YoYixzLCJpbmRleCIsbnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIp
+fSwKZVI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9dGhpcwpQLmsxKGIsImNvdW50IikKcz1xLmIrYgpy
+PXEuYwppZihyIT1udWxsJiZzPj1yKXJldHVybiBuZXcgSC5NQihxLiR0aS5DKCJNQjwxPiIpKQpyZXR1
+cm4gSC5xQyhxLmEscyxyLHEuJHRpLmMpfSwKdHQ6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD10aGlz
+LG89cC5iLG49cC5hLG09Si5VNihuKSxsPW0uZ0Eobiksaz1wLmMKaWYoayE9bnVsbCYmazxsKWw9awpp
+Zih0eXBlb2YgbCE9PSJudW1iZXIiKXJldHVybiBsLkhOKCkKcz1sLW8KaWYoczw9MCl7bj1KLlFpKDAs
+cC4kdGkuYykKcmV0dXJuIG59cj1QLk84KHMsbS5FKG4sbyksITEscC4kdGkuYykKZm9yKHE9MTtxPHM7
+KytxKXtDLk5tLlkocixxLG0uRShuLG8rcSkpCmlmKG0uZ0Eobik8bCl0aHJvdyBILmIoUC5hNChwKSl9
+cmV0dXJuIHJ9fQpILmE3LnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5kCnJldHVy
+biBzfSwKRjpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPXIuYSxwPUouVTYocSksbz1wLmdBKHEpCmlm
+KHIuYiE9PW8pdGhyb3cgSC5iKFAuYTQocSkpCnM9ci5jCmlmKHM+PW8pe3Iuc0kobnVsbCkKcmV0dXJu
+ITF9ci5zSShwLkUocSxzKSk7KytyLmMKcmV0dXJuITB9LApzSTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhp
+cy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpILmkxLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihh
+KXt2YXIgcz1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5NSChKLklUKHRoaXMuYSksdGhpcy5iLHMuQygi
+QDwxPiIpLktxKHMuUVsxXSkuQygiTUg8MSwyPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkht
+KHRoaXMuYSl9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEoudVUodGhpcy5hKX0sCkU6ZnVuY3Rpb24o
+YSxiKXtyZXR1cm4gdGhpcy5iLiQxKEouR0EodGhpcy5hLGIpKX19CkgueHkucHJvdG90eXBlPXskaWJR
+OjF9CkguTUgucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzPXRoaXMscj1zLmIKaWYoci5GKCkp
+e3Muc0kocy5jLiQxKHIuZ2woKSkpCnJldHVybiEwfXMuc0kobnVsbCkKcmV0dXJuITF9LApnbDpmdW5j
+dGlvbigpe3ZhciBzPXRoaXMuYQpyZXR1cm4gc30sCnNJOmZ1bmN0aW9uKGEpe3RoaXMuYT10aGlzLiR0
+aS5DKCIyPyIpLmEoYSl9fQpILmxKLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkht
+KHRoaXMuYSl9LApFOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYi4kMShKLkdBKHRoaXMuYSxiKSl9
+fQpILlU1LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguU08oSi5JVCh0aGlz
+LmEpLHRoaXMuYix0aGlzLiR0aS5DKCJTTzwxPiIpKX19CkguU08ucHJvdG90eXBlPXsKRjpmdW5jdGlv
+bigpe3ZhciBzLHIKZm9yKHM9dGhpcy5hLHI9dGhpcy5iO3MuRigpOylpZihILm9UKHIuJDEocy5nbCgp
+KSkpcmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuZ2woKX19Ckgu
+QU0ucHJvdG90eXBlPXsKZVI6ZnVuY3Rpb24oYSxiKXtQLlVJKGIsImNvdW50Iix0LlMpClAuazEoYiwi
+Y291bnQiKQpyZXR1cm4gbmV3IEguQU0odGhpcy5hLHRoaXMuYitiLEguTGgodGhpcykuQygiQU08MT4i
+KSl9LApna3o6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlUxKEouSVQodGhpcy5hKSx0aGlzLmIsSC5M
+aCh0aGlzKS5DKCJVMTwxPiIpKX19CkguZDUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7dmFyIHM9
+Si5IbSh0aGlzLmEpLXRoaXMuYgppZihzPj0wKXJldHVybiBzCnJldHVybiAwfSwKZVI6ZnVuY3Rpb24o
+YSxiKXtQLlVJKGIsImNvdW50Iix0LlMpClAuazEoYiwiY291bnQiKQpyZXR1cm4gbmV3IEguZDUodGhp
+cy5hLHRoaXMuYitiLHRoaXMuJHRpKX0sCiRpYlE6MX0KSC5VMS5wcm90b3R5cGU9ewpGOmZ1bmN0aW9u
+KCl7dmFyIHMscgpmb3Iocz10aGlzLmEscj0wO3I8dGhpcy5iOysrcilzLkYoKQp0aGlzLmI9MApyZXR1
+cm4gcy5GKCl9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuZ2woKX19CkguTUIucHJvdG90eXBl
+PXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBDLkd3fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwK
+Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LApFOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAuVEUoYiww
+LDAsImluZGV4IixudWxsKSl9LAplUjpmdW5jdGlvbihhLGIpe1AuazEoYiwiY291bnQiKQpyZXR1cm4g
+dGhpc319CkguRnUucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3JldHVybiExfSwKZ2w6ZnVuY3Rpb24o
+KXt0aHJvdyBILmIoSC5XcCgpKX0sCiRpQW46MX0KSC51Ni5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24o
+YSl7cmV0dXJuIG5ldyBILkpCKEouSVQodGhpcy5hKSx0aGlzLiR0aS5DKCJKQjwxPiIpKX19CkguSkIu
+cHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciBzLHIKZm9yKHM9dGhpcy5hLHI9dGhpcy4kdGkuYztz
+LkYoKTspaWYoci5iKHMuZ2woKSkpcmV0dXJuITAKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVy
+biB0aGlzLiR0aS5jLmEodGhpcy5hLmdsKCkpfSwKJGlBbjoxfQpILlNVLnByb3RvdHlwZT17fQpILlJl
+LnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxiLGMpe0guTGgodGhpcykuQygiUmUuRSIpLmEoYykKdGhy
+b3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgYW4gdW5tb2RpZmlhYmxlIGxpc3QiKSl9fQpILncyLnBy
+b3RvdHlwZT17fQpILnd2LnByb3RvdHlwZT17CmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLl9oYXNo
+Q29kZQppZihzIT1udWxsKXJldHVybiBzCnM9NTM2ODcwOTExJjY2NDU5NypKLmhmKHRoaXMuYSkKdGhp
+cy5faGFzaENvZGU9cwpyZXR1cm4gc30sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuJ1N5bWJvbCgiJytILkVq
+KHRoaXMuYSkrJyIpJ30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4g
+YiBpbnN0YW5jZW9mIEgud3YmJnRoaXMuYT09Yi5hfSwKJGlHRDoxfQpILlFDLnByb3RvdHlwZT17fQpI
+LlBELnByb3RvdHlwZT17fQpILldVLnByb3RvdHlwZT17CmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5nQSh0aGlzKT09PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKWTpmdW5jdGlv
+bihhLGIsYyl7dmFyIHM9SC5MaCh0aGlzKQpzLmMuYShiKQpzLlFbMV0uYShjKQpILmRjKCl9LApnUHU6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMucTQoYSxILkxoKHRoaXMpLkMoIk4zPDEsMj4iKSl9LApxNDpm
+dW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKcmV0dXJuIFAubDAoZnVuY3Rpb24oKXt2YXIgcj1hCnZhciBx
+PTAscD0xLG8sbixtLGwsawpyZXR1cm4gZnVuY3Rpb24gJGFzeW5jJGdQdShjLGQpe2lmKGM9PT0xKXtv
+PWQKcT1wfXdoaWxlKHRydWUpc3dpdGNoKHEpe2Nhc2UgMDpuPXMuZ1YoKSxuPW4uZ2t6KG4pLG09SC5M
+aChzKSxtPW0uQygiQDwxPiIpLktxKG0uUVsxXSkuQygiTjM8MSwyPiIpCmNhc2UgMjppZighbi5GKCkp
+e3E9MwpicmVha31sPW4uZ2woKQprPXMucSgwLGwpCmsudG9TdHJpbmcKcT00CnJldHVybiBuZXcgUC5O
+MyhsLGssbSkKY2FzZSA0OnE9MgpicmVhawpjYXNlIDM6cmV0dXJuIFAuVGgoKQpjYXNlIDE6cmV0dXJu
+IFAuWW0obyl9fX0sYil9LAokaVowOjF9CkguTFAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuYX0sCng0OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhIT0ic3RyaW5nIilyZXR1cm4hMQpp
+ZigiX19wcm90b19fIj09PWEpcmV0dXJuITEKcmV0dXJuIHRoaXMuYi5oYXNPd25Qcm9wZXJ0eShhKX0s
+CnE6ZnVuY3Rpb24oYSxiKXtpZighdGhpcy54NChiKSlyZXR1cm4gbnVsbApyZXR1cm4gdGhpcy5xUChi
+KX0sCnFQOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC5oKGEpXX0sCks6ZnVuY3Rpb24oYSxiKXt2
+YXIgcyxyLHEscCxvPUguTGgodGhpcykKby5DKCJ+KDEsMikiKS5hKGIpCnM9dGhpcy5jCmZvcihyPXMu
+bGVuZ3RoLG89by5RWzFdLHE9MDtxPHI7KytxKXtwPXNbcV0KYi4kMihwLG8uYSh0aGlzLnFQKHApKSl9
+fSwKZ1Y6ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEguWFIodGhpcyxILkxoKHRoaXMpLkMoIlhSPDE+Iikp
+fX0KSC5YUi5wcm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLmMKcmV0dXJuIG5l
+dyBKLm0xKHMscy5sZW5ndGgsSC50NihzKS5DKCJtMTwxPiIpKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVy
+biB0aGlzLmEuYy5sZW5ndGh9fQpILkxJLnByb3RvdHlwZT17CmdXYTpmdW5jdGlvbigpe3ZhciBzPXRo
+aXMuYQpyZXR1cm4gc30sCmduZDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG89dGhpcwppZihvLmM9PT0x
+KXJldHVybiBDLmhVCnM9by5kCnI9cy5sZW5ndGgtby5lLmxlbmd0aC1vLmYKaWYocj09PTApcmV0dXJu
+IEMuaFUKcT1bXQpmb3IocD0wO3A8cjsrK3Ape2lmKHA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscCkK
+cS5wdXNoKHNbcF0pfXJldHVybiBKLnpDKHEpfSwKZ1ZtOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxu
+LG0sbCxrPXRoaXMKaWYoay5jIT09MClyZXR1cm4gQy5XTwpzPWsuZQpyPXMubGVuZ3RoCnE9ay5kCnA9
+cS5sZW5ndGgtci1rLmYKaWYocj09PTApcmV0dXJuIEMuV08Kbz1uZXcgSC5ONSh0LmVvKQpmb3Iobj0w
+O248cjsrK24pe2lmKG4+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsbikKbT1zW25dCmw9cCtuCmlmKGw8
+MHx8bD49cS5sZW5ndGgpcmV0dXJuIEguT0gocSxsKQpvLlkoMCxuZXcgSC53dihtKSxxW2xdKX1yZXR1
+cm4gbmV3IEguUEQobyx0LmdGKX0sCiRpdlE6MX0KSC5Dai5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
+LGIpe3ZhciBzCkguaChhKQpzPXRoaXMuYQpzLmI9cy5iKyIkIitILkVqKGEpCkMuTm0uaSh0aGlzLmIs
+YSkKQy5ObS5pKHRoaXMuYyxiKTsrK3MuYX0sCiRTOjE0fQpILmY5LnByb3RvdHlwZT17CnFTOmZ1bmN0
+aW9uKGEpe3ZhciBzLHIscT10aGlzLHA9bmV3IFJlZ0V4cChxLmEpLmV4ZWMoYSkKaWYocD09bnVsbCly
+ZXR1cm4gbnVsbApzPU9iamVjdC5jcmVhdGUobnVsbCkKcj1xLmIKaWYociE9PS0xKXMuYXJndW1lbnRz
+PXBbcisxXQpyPXEuYwppZihyIT09LTEpcy5hcmd1bWVudHNFeHByPXBbcisxXQpyPXEuZAppZihyIT09
+LTEpcy5leHByPXBbcisxXQpyPXEuZQppZihyIT09LTEpcy5tZXRob2Q9cFtyKzFdCnI9cS5mCmlmKHIh
+PT0tMSlzLnJlY2VpdmVyPXBbcisxXQpyZXR1cm4gc319CkguVzAucHJvdG90eXBlPXsKdzpmdW5jdGlv
+bihhKXt2YXIgcz10aGlzLmIKaWYocz09bnVsbClyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6ICIrSC5F
+aih0aGlzLmEpCnJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9kIG5vdCBmb3VuZDogJyIrcysi
+JyBvbiBudWxsIn19CkguYXoucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMscT0i
+Tm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciLHA9ci5iCmlmKHA9PW51bGwpcmV0
+dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guRWooci5hKQpzPXIuYwppZihzPT1udWxsKXJldHVybiBx
+K3ArIicgKCIrSC5FaihyLmEpKyIpIgpyZXR1cm4gcStwKyInIG9uICciK3MrIicgKCIrSC5FaihyLmEp
+KyIpIn19CkgudlYucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMu
+bGVuZ3RoPT09MD8iRXJyb3IiOiJFcnJvcjogIitzfX0KSC50ZS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9u
+KGEpe3JldHVybiJUaHJvdyBvZiBudWxsICgnIisodGhpcy5hPT09bnVsbD8ibnVsbCI6InVuZGVmaW5l
+ZCIpKyInIGZyb20gSmF2YVNjcmlwdCkifSwKJGlSejoxfQpILmJxLnByb3RvdHlwZT17fQpILlhPLnBy
+b3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmIKaWYociE9bnVsbClyZXR1cm4gcgpy
+PXRoaXMuYQpzPXIhPT1udWxsJiZ0eXBlb2Ygcj09PSJvYmplY3QiP3Iuc3RhY2s6bnVsbApyZXR1cm4g
+dGhpcy5iPXM9PW51bGw/IiI6c30sCiRpR3o6MX0KSC5UcC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEp
+e3ZhciBzPXRoaXMuY29uc3RydWN0b3Iscj1zPT1udWxsP251bGw6cy5uYW1lCnJldHVybiJDbG9zdXJl
+ICciK0guTlEocj09bnVsbD8idW5rbm93biI6cikrIicifSwKJGlFSDoxLApnS3U6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpc30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9CkgubGMucHJvdG90eXBlPXt9Ckguengu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLiRzdGF0aWNfbmFtZQppZihzPT1udWxs
+KXJldHVybiJDbG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1ldGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIr
+SC5OUShzKSsiJyJ9fQpILnJULnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcwpp
+ZihiPT1udWxsKXJldHVybiExCmlmKHM9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguclQp
+KXJldHVybiExCnJldHVybiBzLmE9PT1iLmEmJnMuYj09PWIuYiYmcy5jPT09Yi5jfSwKZ2lPOmZ1bmN0
+aW9uKGEpe3ZhciBzLHI9dGhpcy5jCmlmKHI9PW51bGwpcz1ILmVRKHRoaXMuYSkKZWxzZSBzPXR5cGVv
+ZiByIT09Im9iamVjdCI/Si5oZihyKTpILmVRKHIpCnJldHVybihzXkguZVEodGhpcy5iKSk+Pj4wfSwK
+dzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmMKaWYocz09bnVsbClzPXRoaXMuYQpyZXR1cm4iQ2xvc3Vy
+ZSAnIitILkVqKHRoaXMuZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guRWooSC5NKHMpKSsiJyIp
+fX0KSC5FcS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJSdW50aW1lRXJyb3I6ICIrdGhp
+cy5hfX0KSC5rWS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVk
+OiAiK1AuaGwodGhpcy5hKX19Ckgua3IucHJvdG90eXBlPXt9CkguTjUucHJvdG90eXBlPXsKZ0E6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hPT09MH0s
+CmdWOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBILmk1KHRoaXMsSC5MaCh0aGlzKS5DKCJpNTwxPiIpKX0s
+Cng0OmZ1bmN0aW9uKGEpe3ZhciBzLHIKaWYodHlwZW9mIGE9PSJzdHJpbmciKXtzPXRoaXMuYgppZihz
+PT1udWxsKXJldHVybiExCnJldHVybiB0aGlzLlh1KHMsYSl9ZWxzZXtyPXRoaXMuQ1goYSkKcmV0dXJu
+IHJ9fSwKQ1g6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5kCmlmKHM9PW51bGwpcmV0dXJuITEKcmV0dXJu
+IHRoaXMuRmgodGhpcy5CdChzLEouaGYoYSkmMHgzZmZmZmZmKSxhKT49MH0sCnE6ZnVuY3Rpb24oYSxi
+KXt2YXIgcyxyLHEscCxvPXRoaXMsbj1udWxsCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7cz1vLmIKaWYo
+cz09bnVsbClyZXR1cm4gbgpyPW8uajIocyxiKQpxPXI9PW51bGw/bjpyLmIKcmV0dXJuIHF9ZWxzZSBp
+Zih0eXBlb2YgYj09Im51bWJlciImJihiJjB4M2ZmZmZmZik9PT1iKXtwPW8uYwppZihwPT1udWxsKXJl
+dHVybiBuCnI9by5qMihwLGIpCnE9cj09bnVsbD9uOnIuYgpyZXR1cm4gcX1lbHNlIHJldHVybiBvLmFh
+KGIpfSwKYWE6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMuZAppZihxPT1udWxsKXJldHVybiBudWxs
+CnM9dGhpcy5CdChxLEouaGYoYSkmMHgzZmZmZmZmKQpyPXRoaXMuRmgocyxhKQppZihyPDApcmV0dXJu
+IG51bGwKcmV0dXJuIHNbcl0uYn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtPXRo
+aXMsbD1ILkxoKG0pCmwuYy5hKGIpCmwuUVsxXS5hKGMpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIil7cz1t
+LmIKbS5FSChzPT1udWxsP20uYj1tLnpLKCk6cyxiLGMpfWVsc2UgaWYodHlwZW9mIGI9PSJudW1iZXIi
+JiYoYiYweDNmZmZmZmYpPT09Yil7cj1tLmMKbS5FSChyPT1udWxsP20uYz1tLnpLKCk6cixiLGMpfWVs
+c2V7cT1tLmQKaWYocT09bnVsbClxPW0uZD1tLnpLKCkKcD1KLmhmKGIpJjB4M2ZmZmZmZgpvPW0uQnQo
+cSxwKQppZihvPT1udWxsKW0uRUkocSxwLFttLkhuKGIsYyldKQplbHNle249bS5GaChvLGIpCmlmKG4+
+PTApb1tuXS5iPWMKZWxzZSBvLnB1c2gobS5IbihiLGMpKX19fSwKSzpmdW5jdGlvbihhLGIpe3ZhciBz
+LHIscT10aGlzCkguTGgocSkuQygifigxLDIpIikuYShiKQpzPXEuZQpyPXEucgpmb3IoO3MhPW51bGw7
+KXtiLiQyKHMuYSxzLmIpCmlmKHIhPT1xLnIpdGhyb3cgSC5iKFAuYTQocSkpCnM9cy5jfX0sCkVIOmZ1
+bmN0aW9uKGEsYixjKXt2YXIgcyxyPXRoaXMscT1ILkxoKHIpCnEuYy5hKGIpCnEuUVsxXS5hKGMpCnM9
+ci5qMihhLGIpCmlmKHM9PW51bGwpci5FSShhLGIsci5IbihiLGMpKQplbHNlIHMuYj1jfSwKa3M6ZnVu
+Y3Rpb24oKXt0aGlzLnI9dGhpcy5yKzEmNjcxMDg4NjN9LApIbjpmdW5jdGlvbihhLGIpe3ZhciBzPXRo
+aXMscj1ILkxoKHMpLHE9bmV3IEgudmgoci5jLmEoYSksci5RWzFdLmEoYikpCmlmKHMuZT09bnVsbClz
+LmU9cy5mPXEKZWxzZXtyPXMuZgpyLnRvU3RyaW5nCnEuZD1yCnMuZj1yLmM9cX0rK3MuYQpzLmtzKCkK
+cmV0dXJuIHF9LApGaDpmdW5jdGlvbihhLGIpe3ZhciBzLHIKaWYoYT09bnVsbClyZXR1cm4tMQpzPWEu
+bGVuZ3RoCmZvcihyPTA7cjxzOysrcilpZihKLlJNKGFbcl0uYSxiKSlyZXR1cm4gcgpyZXR1cm4tMX0s
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAubk8odGhpcyl9LApqMjpmdW5jdGlvbihhLGIpe3JldHVybiBh
+W2JdfSwKQnQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCkVJOmZ1bmN0aW9uKGEsYixjKXthW2Jd
+PWN9LApybjpmdW5jdGlvbihhLGIpe2RlbGV0ZSBhW2JdfSwKWHU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+dGhpcy5qMihhLGIpIT1udWxsfSwKeks6ZnVuY3Rpb24oKXt2YXIgcz0iPG5vbi1pZGVudGlmaWVyLWtl
+eT4iLHI9T2JqZWN0LmNyZWF0ZShudWxsKQp0aGlzLkVJKHIscyxyKQp0aGlzLnJuKHIscykKcmV0dXJu
+IHJ9LAokaUZvOjF9CkgudmgucHJvdG90eXBlPXt9CkguaTUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuYS5hfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYT09PTB9LApn
+a3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLHI9bmV3IEguTjYocyxzLnIsdGhpcy4kdGkuQygiTjY8
+MT4iKSkKci5jPXMuZQpyZXR1cm4gcn0sCnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS54NChi
+KX19CkguTjYucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlv
+bigpe3ZhciBzLHI9dGhpcyxxPXIuYQppZihyLmIhPT1xLnIpdGhyb3cgSC5iKFAuYTQocSkpCnM9ci5j
+CmlmKHM9PW51bGwpe3Iuc3FZKG51bGwpCnJldHVybiExfWVsc2V7ci5zcVkocy5hKQpyLmM9cy5jCnJl
+dHVybiEwfX0sCnNxWTpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlB
+bjoxfQpILmRDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzo0
+fQpILndOLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6
+NDF9CkguVlgucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILmgoYSkpfSwK
+JFM6MzR9CkguVlIucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5h
+KyIvIit0aGlzLmIuZmxhZ3N9LApnSGM6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLHI9cy5jCmlmKHIhPW51
+bGwpcmV0dXJuIHIKcj1zLmIKcmV0dXJuIHMuYz1ILnY0KHMuYSxyLm11bHRpbGluZSwhci5pZ25vcmVD
+YXNlLHIudW5pY29kZSxyLmRvdEFsbCwhMCl9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5L
+Vyh0aGlzLGIsMCl9LApVWjpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy5nSGMoKQpyLmxhc3RJbmRl
+eD1iCnM9ci5leGVjKGEpCmlmKHM9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIG5ldyBILkVLKHMpfSwK
+JGl2WDoxLAokaXdMOjF9CkguRUsucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciBzCkgudVAo
+YikKcz10aGlzLmIKaWYoYj49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxiKQpyZXR1cm4gc1tiXX0sCiRp
+T2Q6MSwKJGlpYjoxfQpILktXLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEgu
+UGIodGhpcy5hLHRoaXMuYix0aGlzLmMpfX0KSC5QYi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbyxuLG09dGhpcyxsPW0uYgppZihs
+PT1udWxsKXJldHVybiExCnM9bS5jCnI9bC5sZW5ndGgKaWYoczw9cil7cT1tLmEKcD1xLlVaKGwscykK
+aWYocCE9bnVsbCl7bS5kPXAKcz1wLmIKbz1zLmluZGV4Cm49bytzWzBdLmxlbmd0aAppZihvPT09bil7
+aWYocS5iLnVuaWNvZGUpe3M9bS5jCnE9cysxCmlmKHE8cil7cz1DLnhCLm0obCxzKQppZihzPj01NTI5
+NiYmczw9NTYzMTkpe3M9Qy54Qi5tKGwscSkKcz1zPj01NjMyMCYmczw9NTczNDN9ZWxzZSBzPSExfWVs
+c2Ugcz0hMX1lbHNlIHM9ITEKbj0ocz9uKzE6bikrMX1tLmM9bgpyZXR1cm4hMH19bS5iPW0uZD1udWxs
+CnJldHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIp
+CmlmKGIhPT0wKUgudihQLk83KGIsbnVsbCkpCnJldHVybiB0aGlzLmN9LAokaU9kOjF9CkgudW4ucHJv
+dG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TZCh0aGlzLmEsdGhpcy5iLHRoaXMu
+Yyl9fQpILlNkLnByb3RvdHlwZT17CkY6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9dGhpcyxwPXEuYyxvPXEu
+YixuPW8ubGVuZ3RoLG09cS5hLGw9bS5sZW5ndGgKaWYocCtuPmwpe3EuZD1udWxsCnJldHVybiExfXM9
+bS5pbmRleE9mKG8scCkKaWYoczwwKXtxLmM9bCsxCnEuZD1udWxsCnJldHVybiExfXI9cytuCnEuZD1u
+ZXcgSC50UShzLG8pCnEuYz1yPT09cS5jP3IrMTpyCnJldHVybiEwfSwKZ2w6ZnVuY3Rpb24oKXt2YXIg
+cz10aGlzLmQKcy50b1N0cmluZwpyZXR1cm4gc30sCiRpQW46MX0KSC5FVC5wcm90b3R5cGU9eyRpRVQ6
+MSwkaWVxOjF9CkguWEgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwK
+JGlYajoxfQpILkRnLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEu
+bGVuZ3RoKQpyZXR1cm4gYVtiXX0sClk6ZnVuY3Rpb24oYSxiLGMpe0guR0goYykKSC5vZChiLGEsYS5s
+ZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkguUGcucHJvdG90eXBlPXsKWTpm
+dW5jdGlvbihhLGIsYyl7SC51UChjKQpILm9kKGIsYSxhLmxlbmd0aCkKYVtiXT1jfSwKJGliUToxLAok
+aWNYOjEsCiRpek06MX0KSC54ai5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9k
+KGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmRFLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxi
+KXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguWkEucHJvdG90eXBlPXsK
+cTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5k
+VC5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0
+dXJuIGFbYl19fQpILlBxLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixh
+LGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguZUUucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJl
+dHVybiBhW2JdfX0KSC5WNi5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9
+LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LAok
+aVY2OjEsCiRpbjY6MX0KSC5SRy5wcm90b3R5cGU9e30KSC5WUC5wcm90b3R5cGU9e30KSC5XQi5wcm90
+b3R5cGU9e30KSC5aRy5wcm90b3R5cGU9e30KSC5KYy5wcm90b3R5cGU9ewpDOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBILmNFKHYudHlwZVVuaXZlcnNlLHRoaXMsYSl9LApLcTpmdW5jdGlvbihhKXtyZXR1cm4gSC52
+NSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfX0KSC5HLnByb3RvdHlwZT17fQpILmtTLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX19CkguaU0ucHJvdG90eXBlPXt9ClAudGgucHJvdG90
+eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hLHI9cy5hCnMuYT1udWxsCnIuJDAoKX0sCiRT
+OjEwfQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIKdGhpcy5hLmE9dC5NLmEo
+YSkKcz10aGlzLmIKcj10aGlzLmMKcy5maXJzdENoaWxkP3MucmVtb3ZlQ2hpbGQocik6cy5hcHBlbmRD
+aGlsZChyKX0sCiRTOjUyfQpQLlZzLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5hLiQwKCl9
+LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5h
+LiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLlczLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEs
+Yil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNlbGYuc2V0VGltZW91dChILnRSKG5ldyBQLnlIKHRo
+aXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5MNCgiYHNldFRpbWVvdXQoKWAgbm90IGZvdW5kLiIp
+KX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuJDAoKX0sCiRDOiIkMCIsCiRS
+OjAsCiRTOjF9ClAuaWgucHJvdG90eXBlPXsKYU06ZnVuY3Rpb24oYSxiKXt2YXIgcyxyPXRoaXMscT1y
+LiR0aQpxLkMoIjEvPyIpLmEoYikKaWYoIXIuYilyLmEuWGYoYikKZWxzZXtzPXIuYQppZihxLkMoImI4
+PDE+IikuYihiKSlzLmNVKGIpCmVsc2Ugcy5YMihxLmMuYShiKSl9fSwKdzA6ZnVuY3Rpb24oYSxiKXt2
+YXIgcwppZihiPT1udWxsKWI9UC52MChhKQpzPXRoaXMuYQppZih0aGlzLmIpcy5aTChhLGIpCmVsc2Ug
+cy5OayhhLGIpfX0KUC5XTS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLiQy
+KDAsYSl9LAokUzo0Nn0KUC5TWC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS4kMigx
+LG5ldyBILmJxKGEsdC5sLmEoYikpKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjI3fQpQLkdzLnByb3RvdHlw
+ZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hKEgudVAoYSksYil9LAokUzoyNX0KUC5GeS5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJJdGVyYXRpb25NYXJrZXIoIit0aGlzLmIrIiwgIitILkVq
+KHRoaXMuYSkrIikifX0KUC5HVi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYwpp
+ZihzPT1udWxsKXJldHVybiB0aGlzLiR0aS5jLmEodGhpcy5iKQpyZXR1cm4gcy5nbCgpfSwKRjpmdW5j
+dGlvbigpe3ZhciBzLHIscSxwLG8sbixtPXRoaXMKZm9yKHM9bS4kdGkuQygiQW48MT4iKTshMDspe3I9
+bS5jCmlmKHIhPW51bGwpaWYoci5GKCkpcmV0dXJuITAKZWxzZSBtLnNYOShudWxsKQpxPWZ1bmN0aW9u
+KGEsYixjKXt2YXIgbCxrPWIKd2hpbGUodHJ1ZSl0cnl7cmV0dXJuIGEoayxsKX1jYXRjaChqKXtsPWoK
+az1jfX0obS5hLDAsMSkKaWYocSBpbnN0YW5jZW9mIFAuRnkpe3A9cS5iCmlmKHA9PT0yKXtvPW0uZApp
+ZihvPT1udWxsfHxvLmxlbmd0aD09PTApe20uc0VDKG51bGwpCnJldHVybiExfWlmKDA+PW8ubGVuZ3Ro
+KXJldHVybiBILk9IKG8sLTEpCm0uYT1vLnBvcCgpCmNvbnRpbnVlfWVsc2V7cj1xLmEKaWYocD09PTMp
+dGhyb3cgcgplbHNle249cy5hKEouSVQocikpCmlmKG4gaW5zdGFuY2VvZiBQLkdWKXtyPW0uZAppZihy
+PT1udWxsKXI9bS5kPVtdCkMuTm0uaShyLG0uYSkKbS5hPW4uYQpjb250aW51ZX1lbHNle20uc1g5KG4p
+CmNvbnRpbnVlfX19fWVsc2V7bS5zRUMocSkKcmV0dXJuITB9fXJldHVybiExfSwKc0VDOmZ1bmN0aW9u
+KGEpe3RoaXMuYj10aGlzLiR0aS5DKCIxPyIpLmEoYSl9LApzWDk6ZnVuY3Rpb24oYSl7dGhpcy5jPXRo
+aXMuJHRpLkMoIkFuPDE+PyIpLmEoYSl9LAokaUFuOjF9ClAucTQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0
+aW9uKGEpe3JldHVybiBuZXcgUC5HVih0aGlzLmEoKSx0aGlzLiR0aS5DKCJHVjwxPiIpKX19ClAuUGYu
+cHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxiKXt2YXIgcwpQLlVJKGEsImVycm9yIix0LkspCnM9dGhp
+cy5hCmlmKHMuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQpp
+ZihiPT1udWxsKWI9UC52MChhKQpzLk5rKGEsYil9LApwbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53
+MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9ewphTTpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy4k
+dGkKci5DKCIxLz8iKS5hKGIpCnM9dGhpcy5hCmlmKHMuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVy
+ZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQpzLlhmKHIuQygiMS8iKS5hKGIpKX19ClAuRmUucHJvdG90eXBl
+PXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMuYyYxNSkhPT02KXJldHVybiEwCnJldHVybiB0aGlzLmIu
+Yi5idih0LmFsLmEodGhpcy5kKSxhLmEsdC55LHQuSyl9LApLdzpmdW5jdGlvbihhKXt2YXIgcz10aGlz
+LmUscj10LnoscT10LksscD10aGlzLiR0aS5DKCIyLyIpLG89dGhpcy5iLmIKaWYodC5hZy5iKHMpKXJl
+dHVybiBwLmEoby5ycChzLGEuYSxhLmIscixxLHQubCkpCmVsc2UgcmV0dXJuIHAuYShvLmJ2KHQuYkku
+YShzKSxhLmEscixxKSl9fQpQLnZzLnByb3RvdHlwZT17ClNxOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
+LHEscD10aGlzLiR0aQpwLktxKGMpLkMoIjEvKDIpIikuYShhKQpzPSQuWDMKaWYocyE9PUMuTlUpe2Mu
+QygiQDwwLz4iKS5LcShwLmMpLkMoIjEoMikiKS5hKGEpCmlmKGIhPW51bGwpYj1QLlZIKGIscyl9cj1u
+ZXcgUC52cygkLlgzLGMuQygidnM8MD4iKSkKcT1iPT1udWxsPzE6Mwp0aGlzLnhmKG5ldyBQLkZlKHIs
+cSxhLGIscC5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHJ9LApXNzpmdW5jdGlv
+bihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVsbCxiKX0sClFkOmZ1bmN0aW9uKGEsYixjKXt2YXIgcyxy
+PXRoaXMuJHRpCnIuS3EoYykuQygiMS8oMikiKS5hKGEpCnM9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+
+IikpCnRoaXMueGYobmV3IFAuRmUocywxOSxhLGIsci5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIp
+KSkKcmV0dXJuIHN9LAp4ZjpmdW5jdGlvbihhKXt2YXIgcyxyPXRoaXMscT1yLmEKaWYocTw9MSl7YS5h
+PXQuRi5hKHIuYykKci5jPWF9ZWxzZXtpZihxPT09Mil7cz10LmMuYShyLmMpCnE9cy5hCmlmKHE8NCl7
+cy54ZihhKQpyZXR1cm59ci5hPXEKci5jPXMuY31QLlRrKG51bGwsbnVsbCxyLmIsdC5NLmEobmV3IFAu
+ZGEocixhKSkpfX0sCmpROmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwLG8sbixtPXRoaXMsbD17fQpsLmE9
+YQppZihhPT1udWxsKXJldHVybgpzPW0uYQppZihzPD0xKXtyPXQuRi5hKG0uYykKbS5jPWEKaWYociE9
+bnVsbCl7cT1hLmEKZm9yKHA9YTtxIT1udWxsO3A9cSxxPW8pbz1xLmEKcC5hPXJ9fWVsc2V7aWYocz09
+PTIpe249dC5jLmEobS5jKQpzPW4uYQppZihzPDQpe24ualEoYSkKcmV0dXJufW0uYT1zCm0uYz1uLmN9
+bC5hPW0uTjgoYSkKUC5UayhudWxsLG51bGwsbS5iLHQuTS5hKG5ldyBQLm9RKGwsbSkpKX19LAphaDpm
+dW5jdGlvbigpe3ZhciBzPXQuRi5hKHRoaXMuYykKdGhpcy5jPW51bGwKcmV0dXJuIHRoaXMuTjgocyl9
+LApOODpmdW5jdGlvbihhKXt2YXIgcyxyLHEKZm9yKHM9YSxyPW51bGw7cyE9bnVsbDtyPXMscz1xKXtx
+PXMuYQpzLmE9cn1yZXR1cm4gcn0sCkhIOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcyxxPXIuJHRpCnEu
+QygiMS8iKS5hKGEpCmlmKHEuQygiYjg8MT4iKS5iKGEpKWlmKHEuYihhKSlQLkE5KGEscikKZWxzZSBQ
+LmszKGEscikKZWxzZXtzPXIuYWgoKQpxLmMuYShhKQpyLmE9NApyLmM9YQpQLkhaKHIscyl9fSwKWDI6
+ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzCnIuJHRpLmMuYShhKQpzPXIuYWgoKQpyLmE9NApyLmM9YQpQ
+LkhaKHIscyl9LApaTDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscT10aGlzCnQubC5hKGIpCnM9cS5haCgp
+CnI9UC5UbChhLGIpCnEuYT04CnEuYz1yClAuSFoocSxzKX0sClhmOmZ1bmN0aW9uKGEpe3ZhciBzPXRo
+aXMuJHRpCnMuQygiMS8iKS5hKGEpCmlmKHMuQygiYjg8MT4iKS5iKGEpKXt0aGlzLmNVKGEpCnJldHVy
+bn10aGlzLndVKHMuYy5hKGEpKX0sCndVOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMKcy4kdGkuYy5hKGEp
+CnMuYT0xClAuVGsobnVsbCxudWxsLHMuYix0Lk0uYShuZXcgUC5ydChzLGEpKSl9LApjVTpmdW5jdGlv
+bihhKXt2YXIgcz10aGlzLHI9cy4kdGkKci5DKCJiODwxPiIpLmEoYSkKaWYoci5iKGEpKXtpZihhLmE9
+PT04KXtzLmE9MQpQLlRrKG51bGwsbnVsbCxzLmIsdC5NLmEobmV3IFAuS0YocyxhKSkpfWVsc2UgUC5B
+OShhLHMpCnJldHVybn1QLmszKGEscyl9LApOazpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVs
+bCxudWxsLHRoaXMuYix0Lk0uYShuZXcgUC5aTCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90
+b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuSFoodGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3Rv
+dHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcy5hPTAKcy5ISChhKX0sCiRTOjEwfQpQ
+LlU3LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLlpMKGEsdC5sLmEoYikpfSwKJEM6
+IiQyIiwKJFI6MiwKJFM6MzB9ClAudnIucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwo
+dGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLnJ0LnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5h
+LlgyKHRoaXMuYil9LAokUzowfQpQLktGLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5BOSh0aGlz
+LmIsdGhpcy5hKX0sCiRTOjB9ClAuWkwucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwo
+dGhpcy5iLHRoaXMuYyl9LAokUzowfQpQLlJULnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHMs
+cixxLHAsbyxuLG09dGhpcyxsPW51bGwKdHJ5e3E9bS5hLmEKbD1xLmIuYi56eih0LmZPLmEocS5kKSx0
+LnopfWNhdGNoKHApe3M9SC5SdShwKQpyPUgudHMocCkKaWYobS5jKXtxPXQubi5hKG0uYi5hLmMpLmEK
+bz1zCm89cT09bnVsbD9vPT1udWxsOnE9PT1vCnE9b31lbHNlIHE9ITEKbz1tLmEKaWYocSlvLmM9dC5u
+LmEobS5iLmEuYykKZWxzZSBvLmM9UC5UbChzLHIpCm8uYj0hMApyZXR1cm59aWYobCBpbnN0YW5jZW9m
+IFAudnMmJmwuYT49NCl7aWYobC5hPT09OCl7cT1tLmEKcS5jPXQubi5hKGwuYykKcS5iPSEwfXJldHVy
+bn1pZih0LmQuYihsKSl7bj1tLmIuYQpxPW0uYQpxLmM9bC5XNyhuZXcgUC5qWihuKSx0LnopCnEuYj0h
+MX19LAokUzoxfQpQLmpaLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9LAok
+UzozMn0KUC5ycS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixtLGwKdHJ5
+e3E9dGhpcy5hCnA9cS5hCm89cC4kdGkKbj1vLmMKbT1uLmEodGhpcy5iKQpxLmM9cC5iLmIuYnYoby5D
+KCIyLygxKSIpLmEocC5kKSxtLG8uQygiMi8iKSxuKX1jYXRjaChsKXtzPUguUnUobCkKcj1ILnRzKGwp
+CnE9dGhpcy5hCnEuYz1QLlRsKHMscikKcS5iPSEwfX0sCiRTOjF9ClAuUlcucHJvdG90eXBlPXsKJDA6
+ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9dGhpcwp0cnl7cz10Lm4uYShrLmEuYS5jKQpw
+PWsuYgppZihILm9UKHAuYS5IUihzKSkmJnAuYS5lIT1udWxsKXtwLmM9cC5hLkt3KHMpCnAuYj0hMX19
+Y2F0Y2gobyl7cj1ILlJ1KG8pCnE9SC50cyhvKQpwPXQubi5hKGsuYS5hLmMpCm49cC5hCm09cgpsPWsu
+YgppZihuPT1udWxsP209PW51bGw6bj09PW0pbC5jPXAKZWxzZSBsLmM9UC5UbChyLHEpCmwuYj0hMH19
+LAokUzoxfQpQLk9NLnByb3RvdHlwZT17fQpQLnFoLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHIscT10aGlzLHA9e30sbz1uZXcgUC52cygkLlgzLHQuZkopCnAuYT0wCnM9SC5MaChxKQpyPXMu
+QygifigxKT8iKS5hKG5ldyBQLkI1KHAscSkpCnQuWi5hKG5ldyBQLnVPKHAsbykpClcuSkUocS5hLHEu
+YixyLCExLHMuYykKcmV0dXJuIG99fQpQLkI1LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guTGgo
+dGhpcy5iKS5jLmEoYSk7Kyt0aGlzLmEuYX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEguTGgodGhpcy5i
+KS5DKCJjOCgxKSIpfX0KUC51Ty5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYi5ISCh0aGlz
+LmEuYSl9LAokUzowfQpQLk1PLnByb3RvdHlwZT17fQpQLmtULnByb3RvdHlwZT17fQpQLnhJLnByb3Rv
+dHlwZT17fQpQLkN3LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRWoodGhpcy5hKX0s
+CiRpWFM6MSwKZ0lJOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYn19ClAubTAucHJvdG90eXBlPXskaVFt
+OjF9ClAucEsucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcz1ILmIodGhpcy5hKQpzLnN0YWNr
+PUouaih0aGlzLmIpCnRocm93IHN9LAokUzowfQpQLkppLnByb3RvdHlwZT17CmJIOmZ1bmN0aW9uKGEp
+e3ZhciBzLHIscSxwPW51bGwKdC5NLmEoYSkKdHJ5e2lmKEMuTlU9PT0kLlgzKXthLiQwKCkKcmV0dXJu
+fVAuVDgocCxwLHRoaXMsYSx0LkgpfWNhdGNoKHEpe3M9SC5SdShxKQpyPUgudHMocSkKUC5MMihwLHAs
+dGhpcyxzLHQubC5hKHIpKX19LApEbDpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHA9bnVsbApjLkMo
+In4oMCkiKS5hKGEpCmMuYShiKQp0cnl7aWYoQy5OVT09PSQuWDMpe2EuJDEoYikKcmV0dXJufVAueXYo
+cCxwLHRoaXMsYSxiLHQuSCxjKX1jYXRjaChxKXtzPUguUnUocSkKcj1ILnRzKHEpClAuTDIocCxwLHRo
+aXMscyx0LmwuYShyKSl9fSwKUlQ6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuaGoodGhpcyxiLkMo
+IjAoKSIpLmEoYSksYil9LApHWTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVnAodGhpcyx0Lk0uYShh
+KSl9LApQeTpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5PUih0aGlzLGIuQygifigwKSIpLmEoYSks
+Yil9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGx9LAp6ejpmdW5jdGlvbihhLGIpe2IuQygiMCgp
+IikuYShhKQppZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMCgpCnJldHVybiBQLlQ4KG51bGwsbnVsbCx0
+aGlzLGEsYil9LApidjpmdW5jdGlvbihhLGIsYyxkKXtjLkMoIkA8MD4iKS5LcShkKS5DKCIxKDIpIiku
+YShhKQpkLmEoYikKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDEoYikKcmV0dXJuIFAueXYobnVsbCxu
+dWxsLHRoaXMsYSxiLGMsZCl9LApycDpmdW5jdGlvbihhLGIsYyxkLGUsZil7ZC5DKCJAPDA+IikuS3Eo
+ZSkuS3EoZikuQygiMSgyLDMpIikuYShhKQplLmEoYikKZi5hKGMpCmlmKCQuWDM9PT1DLk5VKXJldHVy
+biBhLiQyKGIsYykKcmV0dXJuIFAuUXgobnVsbCxudWxsLHRoaXMsYSxiLGMsZCxlLGYpfSwKTGo6ZnVu
+Y3Rpb24oYSxiLGMsZCl7cmV0dXJuIGIuQygiQDwwPiIpLktxKGMpLktxKGQpLkMoIjEoMiwzKSIpLmEo
+YSl9fQpQLmhqLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS56eih0aGlzLmIs
+dGhpcy5jKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYy5DKCIwKCkiKX19ClAuVnAucHJvdG90
+eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hLmJIKHRoaXMuYil9LAokUzoxfQpQLk9SLnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYwpyZXR1cm4gdGhpcy5hLkRsKHRoaXMu
+YixzLmEoYSkscyl9LAokUzpmdW5jdGlvbigpe3JldHVybiB0aGlzLmMuQygifigwKSIpfX0KUC5iNi5w
+cm90b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcyxyPW5ldyBQLmxtKHMscy5yLEguTGgo
+cykuQygibG08MT4iKSkKci5jPXMuZQpyZXR1cm4gcn0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlz
+LmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYT09PTB9LApnb3I6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHRoaXMuYSE9PTB9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciBzLHIKaWYodHlwZW9mIGI9PSJzdHJp
+bmciJiZiIT09Il9fcHJvdG9fXyIpe3M9dGhpcy5iCmlmKHM9PW51bGwpcmV0dXJuITEKcmV0dXJuIHQu
+ZS5hKHNbYl0pIT1udWxsfWVsc2V7cj10aGlzLlBSKGIpCnJldHVybiByfX0sClBSOmZ1bmN0aW9uKGEp
+e3ZhciBzPXRoaXMuZAppZihzPT1udWxsKXJldHVybiExCnJldHVybiB0aGlzLkRGKHNbdGhpcy5OKGEp
+XSxhKT49MH0sCmk6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHE9dGhpcwpILkxoKHEpLmMuYShiKQppZih0
+eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7cz1xLmIKcmV0dXJuIHEuYlEocz09bnVs
+bD9xLmI9UC5UMigpOnMsYil9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihiJjEwNzM3NDE4MjMp
+PT09Yil7cj1xLmMKcmV0dXJuIHEuYlEocj09bnVsbD9xLmM9UC5UMigpOnIsYil9ZWxzZSByZXR1cm4g
+cS5CNyhiKX0sCkI3OmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPXRoaXMKSC5MaChwKS5jLmEoYSkKcz1w
+LmQKaWYocz09bnVsbClzPXAuZD1QLlQyKCkKcj1wLk4oYSkKcT1zW3JdCmlmKHE9PW51bGwpc1tyXT1b
+cC55byhhKV0KZWxzZXtpZihwLkRGKHEsYSk+PTApcmV0dXJuITEKcS5wdXNoKHAueW8oYSkpfXJldHVy
+biEwfSwKUjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMKaWYodHlwZW9mIGI9PSJzdHJpbmciJiZiIT09
+Il9fcHJvdG9fXyIpcmV0dXJuIHMuTChzLmIsYikKZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihi
+JjEwNzM3NDE4MjMpPT09YilyZXR1cm4gcy5MKHMuYyxiKQplbHNlIHJldHVybiBzLnFnKGIpfSwKcWc6
+ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbz10aGlzLG49by5kCmlmKG49PW51bGwpcmV0dXJuITEKcz1v
+Lk4oYSkKcj1uW3NdCnE9by5ERihyLGEpCmlmKHE8MClyZXR1cm4hMQpwPXIuc3BsaWNlKHEsMSlbMF0K
+aWYoMD09PXIubGVuZ3RoKWRlbGV0ZSBuW3NdCm8uR1MocCkKcmV0dXJuITB9LApiUTpmdW5jdGlvbihh
+LGIpe0guTGgodGhpcykuYy5hKGIpCmlmKHQuZS5hKGFbYl0pIT1udWxsKXJldHVybiExCmFbYl09dGhp
+cy55byhiKQpyZXR1cm4hMH0sCkw6ZnVuY3Rpb24oYSxiKXt2YXIgcwppZihhPT1udWxsKXJldHVybiEx
+CnM9dC5lLmEoYVtiXSkKaWYocz09bnVsbClyZXR1cm4hMQp0aGlzLkdTKHMpCmRlbGV0ZSBhW2JdCnJl
+dHVybiEwfSwKUzpmdW5jdGlvbigpe3RoaXMucj0xMDczNzQxODIzJnRoaXMucisxfSwKeW86ZnVuY3Rp
+b24oYSl7dmFyIHMscj10aGlzLHE9bmV3IFAuYm4oSC5MaChyKS5jLmEoYSkpCmlmKHIuZT09bnVsbCly
+LmU9ci5mPXEKZWxzZXtzPXIuZgpzLnRvU3RyaW5nCnEuYz1zCnIuZj1zLmI9cX0rK3IuYQpyLlMoKQpy
+ZXR1cm4gcX0sCkdTOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMscj1hLmMscT1hLmIKaWYocj09bnVsbClz
+LmU9cQplbHNlIHIuYj1xCmlmKHE9PW51bGwpcy5mPXIKZWxzZSBxLmM9cjstLXMuYQpzLlMoKX0sCk46
+ZnVuY3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sCkRGOmZ1bmN0aW9uKGEsYil7dmFy
+IHMscgppZihhPT1udWxsKXJldHVybi0xCnM9YS5sZW5ndGgKZm9yKHI9MDtyPHM7KytyKWlmKEouUk0o
+YVtyXS5hLGIpKXJldHVybiByCnJldHVybi0xfX0KUC5ibi5wcm90b3R5cGU9e30KUC5sbS5wcm90b3R5
+cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxy
+PXMuYyxxPXMuYQppZihzLmIhPT1xLnIpdGhyb3cgSC5iKFAuYTQocSkpCmVsc2UgaWYocj09bnVsbCl7
+cy5zaihudWxsKQpyZXR1cm4hMX1lbHNle3Muc2oocy4kdGkuQygiMT8iKS5hKHIuYSkpCnMuYz1yLmIK
+cmV0dXJuITB9fSwKc2o6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCiRp
+QW46MX0KUC5tVy5wcm90b3R5cGU9e30KUC51eS5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjEsJGl6TTox
+fQpQLmxELnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguYTcoYSx0aGlzLmdB
+KGEpLEgueihhKS5DKCJhNzxsRC5FPiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEs
+Yil9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHMscgpILnooYSkuQygifihsRC5FKSIpLmEoYikKcz10aGlz
+LmdBKGEpCmZvcihyPTA7cjxzOysrcil7Yi4kMSh0aGlzLnEoYSxyKSkKaWYocyE9PXRoaXMuZ0EoYSkp
+dGhyb3cgSC5iKFAuYTQoYSkpfX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQShhKT09PTB9
+LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIXRoaXMuZ2wwKGEpfSwKRTI6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciBzPUgueihhKQpyZXR1cm4gbmV3IEgubEooYSxzLktxKGMpLkMoIjEobEQuRSkiKS5hKGIpLHMuQygi
+QDxsRC5FPiIpLktxKGMpLkMoImxKPDEsMj4iKSl9LAplUjpmdW5jdGlvbihhLGIpe3JldHVybiBILnFD
+KGEsYixudWxsLEgueihhKS5DKCJsRC5FIikpfSwKZHI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEgu
+alYoYSxILnooYSkuQygiQDxsRC5FPiIpLktxKGIpLkMoImpWPDEsMj4iKSl9LApkdTpmdW5jdGlvbihh
+LGIsYyxkKXt2YXIgcwpILnooYSkuQygibEQuRT8iKS5hKGQpClAuakIoYixjLHRoaXMuZ0EoYSkpCmZv
+cihzPWI7czxjOysrcyl0aGlzLlkoYSxzLGQpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRShhLCJb
+IiwiXSIpfX0KUC5pbC5wcm90b3R5cGU9e30KUC5yYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
+e3ZhciBzLHI9dGhpcy5hCmlmKCFyLmEpdGhpcy5iLmErPSIsICIKci5hPSExCnI9dGhpcy5iCnM9ci5h
+Kz1ILkVqKGEpCnIuYT1zKyI6ICIKci5hKz1ILkVqKGIpfSwKJFM6MTJ9ClAuWWsucHJvdG90eXBlPXsK
+SzpmdW5jdGlvbihhLGIpe3ZhciBzLHIKSC5MaCh0aGlzKS5DKCJ+KFlrLkssWWsuVikiKS5hKGIpCmZv
+cihzPUouSVQodGhpcy5nVigpKTtzLkYoKTspe3I9cy5nbCgpCmIuJDIocix0aGlzLnEoMCxyKSl9fSwK
+Z1B1OmZ1bmN0aW9uKGEpe3JldHVybiBKLk0xKHRoaXMuZ1YoKSxuZXcgUC55USh0aGlzKSxILkxoKHRo
+aXMpLkMoIk4zPFlrLkssWWsuVj4iKSl9LAp4NDpmdW5jdGlvbihhKXtyZXR1cm4gSi56bCh0aGlzLmdW
+KCksYSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gSi5IbSh0aGlzLmdWKCkpfSwKZ2wwOmZ1bmN0aW9u
+KGEpe3JldHVybiBKLnVVKHRoaXMuZ1YoKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMp
+fSwKJGlaMDoxfQpQLnlRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYSxyPUgu
+TGgocykKci5DKCJZay5LIikuYShhKQpyZXR1cm4gbmV3IFAuTjMoYSxzLnEoMCxhKSxyLkMoIkA8WWsu
+Sz4iKS5LcShyLkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEgu
+TGgodGhpcy5hKS5DKCJOMzxZay5LLFlrLlY+KFlrLkspIil9fQpQLktQLnByb3RvdHlwZT17Clk6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzPUguTGgodGhpcykKcy5jLmEoYikKcy5RWzFdLmEoYykKdGhyb3cgSC5i
+KFAuTDQoIkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIG1hcCIpKX19ClAuUG4ucHJvdG90eXBlPXsK
+cTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEucSgwLGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFy
+IHM9SC5MaCh0aGlzKQp0aGlzLmEuWSgwLHMuYy5hKGIpLHMuUVsxXS5hKGMpKX0sCng0OmZ1bmN0aW9u
+KGEpe3JldHVybiB0aGlzLmEueDQoYSl9LApLOmZ1bmN0aW9uKGEsYil7dGhpcy5hLksoMCxILkxoKHRo
+aXMpLkMoIn4oMSwyKSIpLmEoYikpfSwKZ2wwOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQpyZXR1cm4g
+cy5nbDAocyl9LApnQTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ0Eocyl9LAp3OmZ1
+bmN0aW9uKGEpe3JldHVybiBKLmoodGhpcy5hKX0sCmdQdTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEK
+cmV0dXJuIHMuZ1B1KHMpfSwKJGlaMDoxfQpQLkdqLnByb3RvdHlwZT17fQpQLmxmLnByb3RvdHlwZT17
+CmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApnb3I6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuZ0EodGhpcykhPT0wfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5XRSh0aGlzLCJ7
+IiwifSIpfSwKZVI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5iSyh0aGlzLGIsSC5MaCh0aGlzKS5DKCJs
+Zi5FIikpfSwKRTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwPSJpbmRleCIKUC5VSShiLHAsdC5TKQpQ
+LmsxKGIscCkKZm9yKHM9dGhpcy5QKCkscz1QLnJqKHMscy5yLEguTGgocykuYykscj0wO3MuRigpOyl7
+cT1zLmQKaWYoYj09PXIpcmV0dXJuIHE7KytyfXRocm93IEguYihQLkNmKGIsdGhpcyxwLG51bGwscikp
+fX0KUC5Wai5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjEsJGl4dToxfQpQLlh2LnByb3RvdHlwZT17Cmds
+MDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hPT09MH0sCmdvcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5hIT09MH0sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHMKZm9yKHM9Si5JVChILkxoKHRoaXMpLkMoImNY
+PDE+IikuYShiKSk7cy5GKCk7KXRoaXMuaSgwLHMuZ2woKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQ
+LldFKHRoaXMsInsiLCJ9Iil9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHMscj1QLnJqKHRoaXMsdGhpcy5y
+LEguTGgodGhpcykuYykKaWYoIXIuRigpKXJldHVybiIiCmlmKGI9PT0iIil7cz0iIgpkbyBzKz1ILkVq
+KHIuZCkKd2hpbGUoci5GKCkpfWVsc2V7cz1ILkVqKHIuZCkKZm9yKDtyLkYoKTspcz1zK2IrSC5Faihy
+LmQpfXJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKZVI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+SC5iSyh0aGlzLGIsSC5MaCh0aGlzKS5jKX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscD10aGlz
+LG89ImluZGV4IgpQLlVJKGIsbyx0LlMpClAuazEoYixvKQpmb3Iocz1QLnJqKHAscC5yLEguTGgocCku
+Yykscj0wO3MuRigpOyl7cT1zLmQKaWYoYj09PXIpcmV0dXJuIHE7KytyfXRocm93IEguYihQLkNmKGIs
+cCxvLG51bGwscikpfSwKJGliUToxLAokaWNYOjEsCiRpeHU6MX0KUC5uWS5wcm90b3R5cGU9e30KUC5X
+WS5wcm90b3R5cGU9e30KUC5SVS5wcm90b3R5cGU9e30KUC51dy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9u
+KGEsYil7dmFyIHMscj10aGlzLmIKaWYocj09bnVsbClyZXR1cm4gdGhpcy5jLnEoMCxiKQplbHNlIGlm
+KHR5cGVvZiBiIT0ic3RyaW5nIilyZXR1cm4gbnVsbAplbHNle3M9cltiXQpyZXR1cm4gdHlwZW9mIHM9
+PSJ1bmRlZmluZWQiP3RoaXMuZmIoYik6c319LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5iPT1u
+dWxsP3RoaXMuYy5hOnRoaXMuQ2YoKS5sZW5ndGh9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
+Z0EodGhpcyk9PT0wfSwKZ1Y6ZnVuY3Rpb24oKXtpZih0aGlzLmI9PW51bGwpe3ZhciBzPXRoaXMuYwpy
+ZXR1cm4gbmV3IEguaTUocyxILkxoKHMpLkMoImk1PDE+IikpfXJldHVybiBuZXcgUC5pOCh0aGlzKX0s
+Clk6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscT10aGlzCmlmKHEuYj09bnVsbClxLmMuWSgwLGIsYykK
+ZWxzZSBpZihxLng0KGIpKXtzPXEuYgpzW2JdPWMKcj1xLmEKaWYocj09bnVsbD9zIT1udWxsOnIhPT1z
+KXJbYl09bnVsbH1lbHNlIHEuWEsoKS5ZKDAsYixjKX0sCng0OmZ1bmN0aW9uKGEpe2lmKHRoaXMuYj09
+bnVsbClyZXR1cm4gdGhpcy5jLng0KGEpCnJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3Bl
+cnR5LmNhbGwodGhpcy5hLGEpfSwKSzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG89dGhpcwp0LmNB
+LmEoYikKaWYoby5iPT1udWxsKXJldHVybiBvLmMuSygwLGIpCnM9by5DZigpCmZvcihyPTA7cjxzLmxl
+bmd0aDsrK3Ipe3E9c1tyXQpwPW8uYltxXQppZih0eXBlb2YgcD09InVuZGVmaW5lZCIpe3A9UC5RZShv
+LmFbcV0pCm8uYltxXT1wfWIuJDIocSxwKQppZihzIT09by5jKXRocm93IEguYihQLmE0KG8pKX19LApD
+ZjpmdW5jdGlvbigpe3ZhciBzPXQuYk0uYSh0aGlzLmMpCmlmKHM9PW51bGwpcz10aGlzLmM9SC5WTShP
+YmplY3Qua2V5cyh0aGlzLmEpLHQucykKcmV0dXJuIHN9LApYSzpmdW5jdGlvbigpe3ZhciBzLHIscSxw
+LG8sbj10aGlzCmlmKG4uYj09bnVsbClyZXR1cm4gbi5jCnM9UC5GbCh0Lk4sdC56KQpyPW4uQ2YoKQpm
+b3IocT0wO3A9ci5sZW5ndGgscTxwOysrcSl7bz1yW3FdCnMuWSgwLG8sbi5xKDAsbykpfWlmKHA9PT0w
+KUMuTm0uaShyLCIiKQplbHNlIEMuTm0uc0EociwwKQpuLmE9bi5iPW51bGwKcmV0dXJuIG4uYz1zfSwK
+ZmI6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2Fs
+bCh0aGlzLmEsYSkpcmV0dXJuIG51bGwKcz1QLlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT1z
+fX0KUC5pOC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHMuZ0Eo
+cyl9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcy5hCmlmKHMuYj09bnVsbClzPXMuZ1YoKS5FKDAs
+YikKZWxzZXtzPXMuQ2YoKQppZihiPDB8fGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcz1zW2Jd
+fXJldHVybiBzfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQppZihzLmI9PW51bGwpe3M9cy5n
+VigpCnM9cy5na3oocyl9ZWxzZXtzPXMuQ2YoKQpzPW5ldyBKLm0xKHMscy5sZW5ndGgsSC50NihzKS5D
+KCJtMTwxPiIpKX1yZXR1cm4gc30sCnRnOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS54NChiKX19
+ClAucGcucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgcyxyCnRyeXtzPW5ldyBUZXh0RGVjb2Rl
+cigidXRmLTgiLHtmYXRhbDp0cnVlfSkKcmV0dXJuIHN9Y2F0Y2gocil7SC5SdShyKX1yZXR1cm4gbnVs
+bH0sCiRTOjEzfQpQLmMyLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHMscgp0cnl7cz1uZXcg
+VGV4dERlY29kZXIoInV0Zi04Iix7ZmF0YWw6ZmFsc2V9KQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIp
+fXJldHVybiBudWxsfSwKJFM6MTN9ClAuQ1YucHJvdG90eXBlPXsKeXI6ZnVuY3Rpb24oYTAsYTEsYTIp
+e3ZhciBzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhPSJJbnZhbGlkIGJhc2U2NCBl
+bmNvZGluZyBsZW5ndGggIgphMj1QLmpCKGExLGEyLGEwLmxlbmd0aCkKcz0kLlY3KCkKZm9yKHI9YTEs
+cT1yLHA9bnVsbCxvPS0xLG49LTEsbT0wO3I8YTI7cj1sKXtsPXIrMQprPUMueEIuVyhhMCxyKQppZihr
+PT09Mzcpe2o9bCsyCmlmKGo8PWEyKXtpPUgub28oQy54Qi5XKGEwLGwpKQpoPUgub28oQy54Qi5XKGEw
+LGwrMSkpCmc9aSoxNitoLShoJjI1NikKaWYoZz09PTM3KWc9LTEKbD1qfWVsc2UgZz0tMX1lbHNlIGc9
+awppZigwPD1nJiZnPD0xMjcpe2lmKGc8MHx8Zz49cy5sZW5ndGgpcmV0dXJuIEguT0gocyxnKQpmPXNb
+Z10KaWYoZj49MCl7Zz1DLnhCLm0oIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamts
+bW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8iLGYpCmlmKGc9PT1rKWNvbnRpbnVlCms9Z31lbHNle2lm
+KGY9PT0tMSl7aWYobzwwKXtlPXA9PW51bGw/bnVsbDpwLmEubGVuZ3RoCmlmKGU9PW51bGwpZT0wCm89
+ZSsoci1xKQpuPXJ9KyttCmlmKGs9PT02MSljb250aW51ZX1rPWd9aWYoZiE9PS0yKXtpZihwPT1udWxs
+KXtwPW5ldyBQLlJuKCIiKQplPXB9ZWxzZSBlPXAKZS5hKz1DLnhCLk5qKGEwLHEscikKZS5hKz1ILkx3
+KGspCnE9bApjb250aW51ZX19dGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IGRhdGEiLGEwLHIp
+KX1pZihwIT1udWxsKXtlPXAuYSs9Qy54Qi5OaihhMCxxLGEyKQpkPWUubGVuZ3RoCmlmKG8+PTApUC54
+TShhMCxuLGEyLG8sbSxkKQplbHNle2M9Qy5qbi56WShkLTEsNCkrMQppZihjPT09MSl0aHJvdyBILmIo
+UC5ycihhLGEwLGEyKSkKZm9yKDtjPDQ7KXtlKz0iPSIKcC5hPWU7KytjfX1lPXAuYQpyZXR1cm4gQy54
+Qi5pNyhhMCxhMSxhMixlLmNoYXJDb2RlQXQoMCk9PTA/ZTplKX1iPWEyLWExCmlmKG8+PTApUC54TShh
+MCxuLGEyLG8sbSxiKQplbHNle2M9Qy5qbi56WShiLDQpCmlmKGM9PT0xKXRocm93IEguYihQLnJyKGEs
+YTAsYTIpKQppZihjPjEpYTA9Qy54Qi5pNyhhMCxhMixhMixjPT09Mj8iPT0iOiI9Iil9cmV0dXJuIGEw
+fX0KUC5VOC5wcm90b3R5cGU9e30KUC5Vay5wcm90b3R5cGU9e30KUC53SS5wcm90b3R5cGU9e30KUC5a
+aS5wcm90b3R5cGU9e30KUC5VZC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzPVAuaGwodGhp
+cy5hKQpyZXR1cm4odGhpcy5iIT1udWxsPyJDb252ZXJ0aW5nIG9iamVjdCB0byBhbiBlbmNvZGFibGUg
+b2JqZWN0IGZhaWxlZDoiOiJDb252ZXJ0aW5nIG9iamVjdCBkaWQgbm90IHJldHVybiBhbiBlbmNvZGFi
+bGUgb2JqZWN0OiIpKyIgIitzfX0KUC5LOC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJD
+eWNsaWMgZXJyb3IgaW4gSlNPTiBzdHJpbmdpZnkifX0KUC5ieS5wcm90b3R5cGU9ewpwVzpmdW5jdGlv
+bihhLGIsYyl7dmFyIHMKdC5mVi5hKGMpCnM9UC5CUyhiLHRoaXMuZ0hlKCkuYSkKcmV0dXJuIHN9LApP
+QjpmdW5jdGlvbihhLGIpe3ZhciBzCnQuZEEuYShiKQpzPVAudVgoYSx0aGlzLmdaRSgpLmIsbnVsbCkK
+cmV0dXJuIHN9LApnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5uWH0sCmdIZTpmdW5jdGlvbigpe3JldHVy
+biBDLkEzfX0KUC5vai5wcm90b3R5cGU9e30KUC5NeC5wcm90b3R5cGU9e30KUC5TaC5wcm90b3R5cGU9
+ewp2cDpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvLG4sbSxsPWEubGVuZ3RoCmZvcihzPUouclkoYSks
+cj10aGlzLmMscT0wLHA9MDtwPGw7KytwKXtvPXMuVyhhLHApCmlmKG8+OTIpe2lmKG8+PTU1Mjk2KXtu
+PW8mNjQ1MTIKaWYobj09PTU1Mjk2KXttPXArMQptPSEobTxsJiYoQy54Qi5XKGEsbSkmNjQ1MTIpPT09
+NTYzMjApfWVsc2UgbT0hMQppZighbSlpZihuPT09NTYzMjApe249cC0xCm49IShuPj0wJiYoQy54Qi5t
+KGEsbikmNjQ1MTIpPT09NTUyOTYpfWVsc2Ugbj0hMQplbHNlIG49ITAKaWYobil7aWYocD5xKXIuYSs9
+Qy54Qi5OaihhLHEscCkKcT1wKzEKci5hKz1ILkx3KDkyKQpyLmErPUguTHcoMTE3KQpyLmErPUguTHco
+MTAwKQpuPW8+Pj44JjE1CnIuYSs9SC5MdyhuPDEwPzQ4K246ODcrbikKbj1vPj4+NCYxNQpyLmErPUgu
+THcobjwxMD80OCtuOjg3K24pCm49byYxNQpyLmErPUguTHcobjwxMD80OCtuOjg3K24pfX1jb250aW51
+ZX1pZihvPDMyKXtpZihwPnEpci5hKz1DLnhCLk5qKGEscSxwKQpxPXArMQpyLmErPUguTHcoOTIpCnN3
+aXRjaChvKXtjYXNlIDg6ci5hKz1ILkx3KDk4KQpicmVhawpjYXNlIDk6ci5hKz1ILkx3KDExNikKYnJl
+YWsKY2FzZSAxMDpyLmErPUguTHcoMTEwKQpicmVhawpjYXNlIDEyOnIuYSs9SC5MdygxMDIpCmJyZWFr
+CmNhc2UgMTM6ci5hKz1ILkx3KDExNCkKYnJlYWsKZGVmYXVsdDpyLmErPUguTHcoMTE3KQpyLmErPUgu
+THcoNDgpCnIuYSs9SC5Mdyg0OCkKbj1vPj4+NCYxNQpyLmErPUguTHcobjwxMD80OCtuOjg3K24pCm49
+byYxNQpyLmErPUguTHcobjwxMD80OCtuOjg3K24pCmJyZWFrfX1lbHNlIGlmKG89PT0zNHx8bz09PTky
+KXtpZihwPnEpci5hKz1DLnhCLk5qKGEscSxwKQpxPXArMQpyLmErPUguTHcoOTIpCnIuYSs9SC5Mdyhv
+KX19aWYocT09PTApci5hKz1ILkVqKGEpCmVsc2UgaWYocTxsKXIuYSs9cy5OaihhLHEsbCl9LApKbjpm
+dW5jdGlvbihhKXt2YXIgcyxyLHEscApmb3Iocz10aGlzLmEscj1zLmxlbmd0aCxxPTA7cTxyOysrcSl7
+cD1zW3FdCmlmKGE9PW51bGw/cD09bnVsbDphPT09cCl0aHJvdyBILmIobmV3IFAuSzgoYSxudWxsKSl9
+Qy5ObS5pKHMsYSl9LAppVTpmdW5jdGlvbihhKXt2YXIgcyxyLHEscCxvPXRoaXMKaWYoby50TShhKSly
+ZXR1cm4Kby5KbihhKQp0cnl7cz1vLmIuJDEoYSkKaWYoIW8udE0ocykpe3E9UC5HeShhLG51bGwsby5n
+VksoKSkKdGhyb3cgSC5iKHEpfXE9by5hCmlmKDA+PXEubGVuZ3RoKXJldHVybiBILk9IKHEsLTEpCnEu
+cG9wKCl9Y2F0Y2gocCl7cj1ILlJ1KHApCnE9UC5HeShhLHIsby5nVksoKSkKdGhyb3cgSC5iKHEpfX0s
+CnRNOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT10aGlzCmlmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoIWlz
+RmluaXRlKGEpKXJldHVybiExCnEuYy5hKz1DLkNELncoYSkKcmV0dXJuITB9ZWxzZSBpZihhPT09ITAp
+e3EuYy5hKz0idHJ1ZSIKcmV0dXJuITB9ZWxzZSBpZihhPT09ITEpe3EuYy5hKz0iZmFsc2UiCnJldHVy
+biEwfWVsc2UgaWYoYT09bnVsbCl7cS5jLmErPSJudWxsIgpyZXR1cm4hMH1lbHNlIGlmKHR5cGVvZiBh
+PT0ic3RyaW5nIil7cz1xLmMKcy5hKz0nIicKcS52cChhKQpzLmErPSciJwpyZXR1cm4hMH1lbHNlIGlm
+KHQuai5iKGEpKXtxLkpuKGEpCnEubEsoYSkKcz1xLmEKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0go
+cywtMSkKcy5wb3AoKQpyZXR1cm4hMH1lbHNlIGlmKHQuZi5iKGEpKXtxLkpuKGEpCnI9cS5qdyhhKQpz
+PXEuYQppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCnJldHVybiByfWVsc2Ug
+cmV0dXJuITF9LApsSzpmdW5jdGlvbihhKXt2YXIgcyxyLHE9dGhpcy5jCnEuYSs9IlsiCnM9Si5VNihh
+KQppZihzLmdvcihhKSl7dGhpcy5pVShzLnEoYSwwKSkKZm9yKHI9MTtyPHMuZ0EoYSk7KytyKXtxLmEr
+PSIsIgp0aGlzLmlVKHMucShhLHIpKX19cS5hKz0iXSJ9LApqdzpmdW5jdGlvbihhKXt2YXIgcyxyLHEs
+cCxvLG49dGhpcyxtPXt9CmlmKGEuZ2wwKGEpKXtuLmMuYSs9Int9IgpyZXR1cm4hMH1zPVAuTzgoYS5n
+QShhKSoyLG51bGwsITEsdC5XKQpyPW0uYT0wCm0uYj0hMAphLksoMCxuZXcgUC50aShtLHMpKQppZigh
+bS5iKXJldHVybiExCnE9bi5jCnEuYSs9InsiCmZvcihwPSciJztyPHMubGVuZ3RoO3IrPTIscD0nLCIn
+KXtxLmErPXAKbi52cChILmgoc1tyXSkpCnEuYSs9JyI6JwpvPXIrMQppZihvPj1zLmxlbmd0aClyZXR1
+cm4gSC5PSChzLG8pCm4uaVUoc1tvXSl9cS5hKz0ifSIKcmV0dXJuITB9fQpQLnRpLnByb3RvdHlwZT17
+CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZih0eXBlb2YgYSE9InN0cmluZyIpdGhpcy5hLmI9ITEK
+cz10aGlzLmIKcj10aGlzLmEKQy5ObS5ZKHMsci5hKyssYSkKQy5ObS5ZKHMsci5hKyssYil9LAokUzox
+Mn0KUC50dS5wcm90b3R5cGU9ewpnVks6ZnVuY3Rpb24oKXt2YXIgcz10aGlzLmMuYQpyZXR1cm4gcy5j
+aGFyQ29kZUF0KDApPT0wP3M6c319ClAudTUucHJvdG90eXBlPXsKZ1pFOmZ1bmN0aW9uKCl7cmV0dXJu
+IEMuUWt9fQpQLkUzLnByb3RvdHlwZT17CldKOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1QLmpCKDAsbnVs
+bCxhLmxlbmd0aCkscD1xLTAKaWYocD09PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApCnM9bmV3IFVp
+bnQ4QXJyYXkocCozKQpyPW5ldyBQLlJ3KHMpCmlmKHIuR3goYSwwLHEpIT09cSl7Si5hNihhLHEtMSkK
+ci5STygpfXJldHVybiBuZXcgVWludDhBcnJheShzLnN1YmFycmF5KDAsSC5yTSgwLHIuYixzLmxlbmd0
+aCkpKX19ClAuUncucHJvdG90eXBlPXsKUk86ZnVuY3Rpb24oKXt2YXIgcz10aGlzLHI9cy5jLHE9cy5i
+LHA9cy5iPXErMSxvPXIubGVuZ3RoCmlmKHE+PW8pcmV0dXJuIEguT0gocixxKQpyW3FdPTIzOQpxPXMu
+Yj1wKzEKaWYocD49bylyZXR1cm4gSC5PSChyLHApCnJbcF09MTkxCnMuYj1xKzEKaWYocT49bylyZXR1
+cm4gSC5PSChyLHEpCnJbcV09MTg5fSwKTzY6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvLG49dGhp
+cwppZigoYiY2NDUxMik9PT01NjMyMCl7cz02NTUzNisoKGEmMTAyMyk8PDEwKXxiJjEwMjMKcj1uLmMK
+cT1uLmIKcD1uLmI9cSsxCm89ci5sZW5ndGgKaWYocT49bylyZXR1cm4gSC5PSChyLHEpCnJbcV09MjQw
+fHM+Pj4xOApxPW4uYj1wKzEKaWYocD49bylyZXR1cm4gSC5PSChyLHApCnJbcF09MTI4fHM+Pj4xMiY2
+MwpwPW4uYj1xKzEKaWYocT49bylyZXR1cm4gSC5PSChyLHEpCnJbcV09MTI4fHM+Pj42JjYzCm4uYj1w
+KzEKaWYocD49bylyZXR1cm4gSC5PSChyLHApCnJbcF09MTI4fHMmNjMKcmV0dXJuITB9ZWxzZXtuLlJP
+KCkKcmV0dXJuITF9fSwKR3g6ZnVuY3Rpb24oYSxiLGMpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcwpp
+ZihiIT09YyYmKEMueEIubShhLGMtMSkmNjQ1MTIpPT09NTUyOTYpLS1jCmZvcihzPWwuYyxyPXMubGVu
+Z3RoLHE9YjtxPGM7KytxKXtwPUMueEIuVyhhLHEpCmlmKHA8PTEyNyl7bz1sLmIKaWYobz49cilicmVh
+awpsLmI9bysxCnNbb109cH1lbHNle289cCY2NDUxMgppZihvPT09NTUyOTYpe2lmKGwuYis0PnIpYnJl
+YWsKbj1xKzEKaWYobC5PNihwLEMueEIuVyhhLG4pKSlxPW59ZWxzZSBpZihvPT09NTYzMjApe2lmKGwu
+YiszPnIpYnJlYWsKbC5STygpfWVsc2UgaWYocDw9MjA0Nyl7bz1sLmIKbT1vKzEKaWYobT49cilicmVh
+awpsLmI9bQppZihvPj1yKXJldHVybiBILk9IKHMsbykKc1tvXT0xOTJ8cD4+PjYKbC5iPW0rMQpzW21d
+PTEyOHxwJjYzfWVsc2V7bz1sLmIKaWYobysyPj1yKWJyZWFrCm09bC5iPW8rMQppZihvPj1yKXJldHVy
+biBILk9IKHMsbykKc1tvXT0yMjR8cD4+PjEyCm89bC5iPW0rMQppZihtPj1yKXJldHVybiBILk9IKHMs
+bSkKc1ttXT0xMjh8cD4+PjYmNjMKbC5iPW8rMQppZihvPj1yKXJldHVybiBILk9IKHMsbykKc1tvXT0x
+Mjh8cCY2M319fXJldHVybiBxfX0KUC5HWS5wcm90b3R5cGU9ewpXSjpmdW5jdGlvbihhKXt2YXIgcyxy
+CnQuTC5hKGEpCnM9dGhpcy5hCnI9UC5reShzLGEsMCxudWxsKQppZihyIT1udWxsKXJldHVybiByCnJl
+dHVybiBuZXcgUC5ieihzKS5OZShhLDAsbnVsbCwhMCl9fQpQLmJ6LnByb3RvdHlwZT17Ck5lOmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwLG8sbj10aGlzCnQuTC5hKGEpCnM9UC5qQihiLGMsSi5IbShh
+KSkKaWYoYj09PXMpcmV0dXJuIiIKcj1QLmp5KGEsYixzKQpxPW4uaE8ociwwLHMtYiwhMCkKcD1uLmIK
+aWYoKHAmMSkhPT0wKXtvPVAuajQocCkKbi5iPTAKdGhyb3cgSC5iKFAucnIobyxhLGIrbi5jKSl9cmV0
+dXJuIHF9LApoTzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyLHE9dGhpcwppZihjLWI+MTAwMCl7cz1D
+LmpuLkJVKGIrYywyKQpyPXEuaE8oYSxiLHMsITEpCmlmKChxLmImMSkhPT0wKXJldHVybiByCnJldHVy
+biByK3EuaE8oYSxzLGMsZCl9cmV0dXJuIHEuRWgoYSxiLGMsZCl9LApFaDpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgcyxyLHEscCxvLG4sbSxsLGs9dGhpcyxqPTY1NTMzLGk9ay5iLGg9ay5jLGc9bmV3IFAuUm4o
+IiIpLGY9YisxLGU9YS5sZW5ndGgKaWYoYjwwfHxiPj1lKXJldHVybiBILk9IKGEsYikKcz1hW2JdCiRs
+YWJlbDAkMDpmb3Iocj1rLmE7ITA7KXtmb3IoOyEwO2Y9byl7cT1DLnhCLlcoIkFBQUFBQUFBQUFBQUFB
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRkZGRkZG
+RkZGRkZGRkZGRkdHR0dHR0dHR0dHR0dHR0dISEhISEhISEhISEhISEhISEhISEhISEhISEhJSEhISkVF
+QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCS0NDQ0NDQ0NDQ0NDQ0RDTE9OTk5NRUVFRUVFRUVF
+RUUiLHMpJjMxCmg9aTw9MzI/cyY2MTY5ND4+PnE6KHMmNjN8aDw8Nik+Pj4wCmk9Qy54Qi5XKCIgXHgw
+MDA6WEVDQ0NDQ046bERiIFx4MDAwOlhFQ0NDQ0NOdmxEYiBceDAwMDpYRUNDQ0NDTjpsRGIgQUFBQUFc
+eDAwXHgwMFx4MDBceDAwXHgwMEFBQUFBMDAwMDBBQUFBQTo6Ojo6QUFBQUFHRzAwMEFBQUFBMDBLS0tB
+QUFBQUc6Ojo6QUFBQUE6SUlJSUFBQUFBMDAwXHg4MDBBQUFBQVx4MDBceDAwXHgwMFx4MDAgQUFBQUEi
+LGkrcSkKaWYoaT09PTApe2cuYSs9SC5MdyhoKQppZihmPT09YylicmVhayAkbGFiZWwwJDAKYnJlYWt9
+ZWxzZSBpZigoaSYxKSE9PTApe2lmKHIpc3dpdGNoKGkpe2Nhc2UgNjk6Y2FzZSA2NzpnLmErPUguTHco
+aikKYnJlYWsKY2FzZSA2NTpnLmErPUguTHcoaik7LS1mCmJyZWFrCmRlZmF1bHQ6cD1nLmErPUguTHco
+aikKZy5hPXArSC5MdyhqKQpicmVha31lbHNle2suYj1pCmsuYz1mLTEKcmV0dXJuIiJ9aT0wfWlmKGY9
+PT1jKWJyZWFrICRsYWJlbDAkMApvPWYrMQppZihmPDB8fGY+PWUpcmV0dXJuIEguT0goYSxmKQpzPWFb
+Zl19bz1mKzEKaWYoZjwwfHxmPj1lKXJldHVybiBILk9IKGEsZikKcz1hW2ZdCmlmKHM8MTI4KXt3aGls
+ZSghMCl7aWYoIShvPGMpKXtuPWMKYnJlYWt9bT1vKzEKaWYobzwwfHxvPj1lKXJldHVybiBILk9IKGEs
+bykKcz1hW29dCmlmKHM+PTEyOCl7bj1tLTEKbz1tCmJyZWFrfW89bX1pZihuLWY8MjApZm9yKGw9Zjts
+PG47KytsKXtpZihsPj1lKXJldHVybiBILk9IKGEsbCkKZy5hKz1ILkx3KGFbbF0pfWVsc2UgZy5hKz1Q
+LkhNKGEsZixuKQppZihuPT09YylicmVhayAkbGFiZWwwJDAKZj1vfWVsc2UgZj1vfWlmKGQmJmk+MzIp
+aWYocilnLmErPUguTHcoaikKZWxzZXtrLmI9NzcKay5jPWMKcmV0dXJuIiJ9ay5iPWkKay5jPWgKZT1n
+LmEKcmV0dXJuIGUuY2hhckNvZGVBdCgwKT09MD9lOmV9fQpQLldGLnByb3RvdHlwZT17CiQyOmZ1bmN0
+aW9uKGEsYil7dmFyIHMscixxCnQuZm8uYShhKQpzPXRoaXMuYgpyPXRoaXMuYQpzLmErPXIuYQpxPXMu
+YSs9SC5FaihhLmEpCnMuYT1xKyI6ICIKcy5hKz1QLmhsKGIpCnIuYT0iLCAifSwKJFM6NDJ9ClAuaVAu
+cHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtpZihiPT1udWxsKXJldHVybiExCnJldHVybiBiIGlu
+c3RhbmNlb2YgUC5pUCYmdGhpcy5hPT09Yi5hJiYhMH0sCmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlz
+LmEKcmV0dXJuKHNeQy5qbi53RyhzLDMwKSkmMTA3Mzc0MTgyM30sCnc6ZnVuY3Rpb24oYSl7dmFyIHM9
+dGhpcyxyPVAuR3EoSC50SihzKSkscT1QLmgwKEguTlMocykpLHA9UC5oMChILmpBKHMpKSxvPVAuaDAo
+SC5JWChzKSksbj1QLmgwKEguY2gocykpLG09UC5oMChILkpkKHMpKSxsPVAuVngoSC5vMShzKSksaz1y
+KyItIitxKyItIitwKyIgIitvKyI6IituKyI6IittKyIuIitsCnJldHVybiBrfX0KUC5YUy5wcm90b3R5
+cGU9ewpnSUk6ZnVuY3Rpb24oKXtyZXR1cm4gSC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKaWYocyE9bnVsbClyZXR1cm4iQXNz
+ZXJ0aW9uIGZhaWxlZDogIitQLmhsKHMpCnJldHVybiJBc3NlcnRpb24gZmFpbGVkIn19ClAuRXoucHJv
+dG90eXBlPXt9ClAuRi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJUaHJvdyBvZiBudWxs
+LiJ9fQpQLnUucHJvdG90eXBlPXsKZ1o6ZnVuY3Rpb24oKXtyZXR1cm4iSW52YWxpZCBhcmd1bWVudCIr
+KCF0aGlzLmE/IihzKSI6IiIpfSwKZ3U6ZnVuY3Rpb24oKXtyZXR1cm4iIn0sCnc6ZnVuY3Rpb24oYSl7
+dmFyIHMscixxPXRoaXMscD1xLmMsbz1wPT1udWxsPyIiOiIgKCIrcCsiKSIsbj1xLmQsbT1uPT1udWxs
+PyIiOiI6ICIrSC5FaihuKSxsPXEuZ1ooKStvK20KaWYoIXEuYSlyZXR1cm4gbApzPXEuZ3UoKQpyPVAu
+aGwocS5iKQpyZXR1cm4gbCtzKyI6ICIrcn19ClAuYkoucHJvdG90eXBlPXsKZ1o6ZnVuY3Rpb24oKXty
+ZXR1cm4iUmFuZ2VFcnJvciJ9LApndTpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcy5lLHE9dGhpcy5mCmlm
+KHI9PW51bGwpcz1xIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gIitILkVqKHEpOiIi
+CmVsc2UgaWYocT09bnVsbClzPSI6IE5vdCBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gIitILkVqKHIp
+CmVsc2UgaWYocT5yKXM9IjogTm90IGluIGluY2x1c2l2ZSByYW5nZSAiK0guRWoocikrIi4uIitILkVq
+KHEpCmVsc2Ugcz1xPHI/IjogVmFsaWQgdmFsdWUgcmFuZ2UgaXMgZW1wdHkiOiI6IE9ubHkgdmFsaWQg
+dmFsdWUgaXMgIitILkVqKHIpCnJldHVybiBzfX0KUC5lWS5wcm90b3R5cGU9ewpnWjpmdW5jdGlvbigp
+e3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHMscj1ILnVQKHRoaXMuYikKaWYo
+dHlwZW9mIHIhPT0ibnVtYmVyIilyZXR1cm4gci5KKCkKaWYocjwwKXJldHVybiI6IGluZGV4IG11c3Qg
+bm90IGJlIG5lZ2F0aXZlIgpzPXRoaXMuZgppZihzPT09MClyZXR1cm4iOiBubyBpbmRpY2VzIGFyZSB2
+YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAiK0guRWoocyl9LApnQTpmdW5j
+dGlvbihhKXtyZXR1cm4gdGhpcy5mfX0KUC5tcC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBz
+LHIscSxwLG8sbixtLGwsaz10aGlzLGo9e30saT1uZXcgUC5SbigiIikKai5hPSIiCnM9ay5jCmZvcihy
+PXMubGVuZ3RoLHE9MCxwPSIiLG89IiI7cTxyOysrcSxvPSIsICIpe249c1txXQppLmE9cCtvCnA9aS5h
+Kz1QLmhsKG4pCmouYT0iLCAifWsuZC5LKDAsbmV3IFAuV0YoaixpKSkKbT1QLmhsKGsuYSkKbD1pLnco
+MCkKcj0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK0guRWooay5iLmEpKyIn
+XG5SZWNlaXZlcjogIittKyJcbkFyZ3VtZW50czogWyIrbCsiXSIKcmV0dXJuIHJ9fQpQLnViLnByb3Rv
+dHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlVuc3VwcG9ydGVkIG9wZXJhdGlvbjogIit0aGlzLmF9
+fQpQLmRzLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5hCnJldHVybiBzIT1udWxs
+PyJVbmltcGxlbWVudGVkRXJyb3I6ICIrczoiVW5pbXBsZW1lbnRlZEVycm9yIn19ClAubGoucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iQmFkIHN0YXRlOiAiK3RoaXMuYX19ClAuVVYucHJvdG90
+eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKaWYocz09bnVsbClyZXR1cm4iQ29uY3VycmVu
+dCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbi4iCnJldHVybiJDb25jdXJyZW50IG1vZGlmaWNh
+dGlvbiBkdXJpbmcgaXRlcmF0aW9uOiAiK1AuaGwocykrIi4ifX0KUC5rNS5wcm90b3R5cGU9ewp3OmZ1
+bmN0aW9uKGEpe3JldHVybiJPdXQgb2YgTWVtb3J5In0sCmdJSTpmdW5jdGlvbigpe3JldHVybiBudWxs
+fSwKJGlYUzoxfQpQLktZLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlN0YWNrIE92ZXJm
+bG93In0sCmdJSTpmdW5jdGlvbigpe3JldHVybiBudWxsfSwKJGlYUzoxfQpQLnAucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmEKcmV0dXJuIHM9PW51bGw/IlJlYWRpbmcgc3RhdGljIHZh
+cmlhYmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSAn
+IitzKyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5wcm90b3R5cGU9ewp3OmZ1bmN0
+aW9uKGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfSwKJGlSejoxfQpQLmFFLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGc9dGhpcy5hLGY9ZyE9bnVs
+bCYmIiIhPT1nPyJGb3JtYXRFeGNlcHRpb246ICIrSC5FaihnKToiRm9ybWF0RXhjZXB0aW9uIixlPXRo
+aXMuYyxkPXRoaXMuYgppZih0eXBlb2YgZD09InN0cmluZyIpe2lmKGUhPW51bGwpcz1lPDB8fGU+ZC5s
+ZW5ndGgKZWxzZSBzPSExCmlmKHMpZT1udWxsCmlmKGU9PW51bGwpe2lmKGQubGVuZ3RoPjc4KWQ9Qy54
+Qi5OaihkLDAsNzUpKyIuLi4iCnJldHVybiBmKyJcbiIrZH1mb3Iocj0xLHE9MCxwPSExLG89MDtvPGU7
+KytvKXtuPUMueEIuVyhkLG8pCmlmKG49PT0xMCl7aWYocSE9PW98fCFwKSsrcgpxPW8rMQpwPSExfWVs
+c2UgaWYobj09PTEzKXsrK3IKcT1vKzEKcD0hMH19Zj1yPjE/ZisoIiAoYXQgbGluZSAiK3IrIiwgY2hh
+cmFjdGVyICIrKGUtcSsxKSsiKVxuIik6ZisoIiAoYXQgY2hhcmFjdGVyICIrKGUrMSkrIilcbiIpCm09
+ZC5sZW5ndGgKZm9yKG89ZTtvPG07KytvKXtuPUMueEIubShkLG8pCmlmKG49PT0xMHx8bj09PTEzKXtt
+PW8KYnJlYWt9fWlmKG0tcT43OClpZihlLXE8NzUpe2w9cSs3NQprPXEKaj0iIgppPSIuLi4ifWVsc2V7
+aWYobS1lPDc1KXtrPW0tNzUKbD1tCmk9IiJ9ZWxzZXtrPWUtMzYKbD1lKzM2Cmk9Ii4uLiJ9aj0iLi4u
+In1lbHNle2w9bQprPXEKaj0iIgppPSIifWg9Qy54Qi5OaihkLGssbCkKcmV0dXJuIGYraitoK2krIlxu
+IitDLnhCLkl4KCIgIixlLWsrai5sZW5ndGgpKyJeXG4ifWVsc2UgcmV0dXJuIGUhPW51bGw/ZisoIiAo
+YXQgb2Zmc2V0ICIrSC5FaihlKSsiKSIpOmZ9LAokaVJ6OjF9ClAuY1gucHJvdG90eXBlPXsKZHI6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gSC5HSih0aGlzLEguTGgodGhpcykuQygiY1guRSIpLGIpfSwKRTI6ZnVu
+Y3Rpb24oYSxiLGMpe3ZhciBzPUguTGgodGhpcykKcmV0dXJuIEguSzEodGhpcyxzLktxKGMpLkMoIjEo
+Y1guRSkiKS5hKGIpLHMuQygiY1guRSIpLGMpfSwKZXY6ZnVuY3Rpb24oYSxiKXt2YXIgcz1ILkxoKHRo
+aXMpCnJldHVybiBuZXcgSC5VNSh0aGlzLHMuQygiYTIoY1guRSkiKS5hKGIpLHMuQygiVTU8Y1guRT4i
+KSl9LAp0dDpmdW5jdGlvbihhLGIpe3JldHVybiBQLkNIKHRoaXMsYixILkxoKHRoaXMpLkMoImNYLkUi
+KSl9LApicjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy50dChhLCEwKX0sCmdBOmZ1bmN0aW9uKGEpe3Zh
+ciBzLHI9dGhpcy5na3oodGhpcykKZm9yKHM9MDtyLkYoKTspKytzCnJldHVybiBzfSwKZ2wwOmZ1bmN0
+aW9uKGEpe3JldHVybiF0aGlzLmdreih0aGlzKS5GKCl9LApnb3I6ZnVuY3Rpb24oYSl7cmV0dXJuIXRo
+aXMuZ2wwKHRoaXMpfSwKZVI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5iSyh0aGlzLGIsSC5MaCh0aGlz
+KS5DKCJjWC5FIikpfSwKZ3I4OmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5na3oodGhpcykKaWYoIXIu
+RigpKXRocm93IEguYihILldwKCkpCnM9ci5nbCgpCmlmKHIuRigpKXRocm93IEguYihILkFtKCkpCnJl
+dHVybiBzfSwKRTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQpQLmsxKGIsImluZGV4IikKZm9yKHM9dGhp
+cy5na3oodGhpcykscj0wO3MuRigpOyl7cT1zLmdsKCkKaWYoYj09PXIpcmV0dXJuIHE7KytyfXRocm93
+IEguYihQLkNmKGIsdGhpcywiaW5kZXgiLG51bGwscikpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5F
+UCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90b3R5cGU9e30KUC5OMy5wcm90b3R5cGU9ewp3OmZ1bmN0
+aW9uKGEpe3JldHVybiJNYXBFbnRyeSgiK0guRWooSi5qKHRoaXMuYSkpKyI6ICIrSC5FaihKLmoodGhp
+cy5iKSkrIikifX0KUC5jOC5wcm90b3R5cGU9ewpnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFAuTWgucHJv
+dG90eXBlLmdpTy5jYWxsKEMuak4sdGhpcyl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiJudWxsIn19ClAu
+TWgucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpQLk1oLCRpTWg6MSwKRE46ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gdGhpcz09PWJ9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIEguZVEodGhpcyl9LAp3OmZ1bmN0aW9u
+KGEpe3JldHVybiJJbnN0YW5jZSBvZiAnIitILkVqKEguTSh0aGlzKSkrIicifSwKZTc6ZnVuY3Rpb24o
+YSxiKXt0Lm8uYShiKQp0aHJvdyBILmIoUC5scih0aGlzLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgpKSl9
+LAp0b1N0cmluZzpmdW5jdGlvbigpe3JldHVybiB0aGlzLncodGhpcyl9fQpQLlpkLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIiJ9LAokaUd6OjF9ClAuUm4ucHJvdG90eXBlPXsKZ0E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LAp3OmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuYQpyZXR1
+cm4gcy5jaGFyQ29kZUF0KDApPT0wP3M6c30sCiRpQkw6MX0KUC5uMS5wcm90b3R5cGU9ewokMjpmdW5j
+dGlvbihhLGIpe3ZhciBzLHIscSxwCnQuSi5hKGEpCkguaChiKQpzPUouclkoYikuT1koYiwiPSIpCmlm
+KHM9PT0tMSl7aWYoYiE9PSIiKWEuWSgwLFAua3UoYiwwLGIubGVuZ3RoLHRoaXMuYSwhMCksIiIpfWVs
+c2UgaWYocyE9PTApe3I9Qy54Qi5OaihiLDAscykKcT1DLnhCLkcoYixzKzEpCnA9dGhpcy5hCmEuWSgw
+LFAua3UociwwLHIubGVuZ3RoLHAsITApLFAua3UocSwwLHEubGVuZ3RoLHAsITApKX1yZXR1cm4gYX0s
+CiRTOjQ0fQpQLmNTLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAucnIoIkls
+bGVnYWwgSVB2NCBhZGRyZXNzLCAiK2EsdGhpcy5hLGIpKX0sCiRTOjIxfQpQLlZDLnByb3RvdHlwZT17
+CiQyOmZ1bmN0aW9uKGEsYil7dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgSVB2NiBhZGRyZXNzLCAiK2Es
+dGhpcy5hLGIpKX0sCiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLiQyKGEsbnVsbCl9LAokUzo0OX0K
+UC5KVC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzCmlmKGItYT40KXRoaXMuYS4kMigi
+YW4gSVB2NiBwYXJ0IGNhbiBvbmx5IGNvbnRhaW4gYSBtYXhpbXVtIG9mIDQgaGV4IGRpZ2l0cyIsYSkK
+cz1QLlFBKEMueEIuTmoodGhpcy5iLGEsYiksMTYpCmlmKHM8MHx8cz42NTUzNSl0aGlzLmEuJDIoImVh
+Y2ggcGFydCBtdXN0IGJlIGluIHRoZSByYW5nZSBvZiBgMHgwLi4weEZGRkZgIixhKQpyZXR1cm4gc30s
+CiRTOjUxfQpQLkRuLnByb3RvdHlwZT17CmduRDpmdW5jdGlvbigpe3ZhciBzLHIscSxwPXRoaXMsbz1w
+LngKaWYobz09bnVsbCl7bz1wLmEKcz1vLmxlbmd0aCE9PTA/bysiOiI6IiIKcj1wLmMKcT1yPT1udWxs
+CmlmKCFxfHxvPT09ImZpbGUiKXtvPXMrIi8vIgpzPXAuYgppZihzLmxlbmd0aCE9PTApbz1vK3MrIkAi
+CmlmKCFxKW8rPXIKcz1wLmQKaWYocyE9bnVsbClvPW8rIjoiK0guRWoocyl9ZWxzZSBvPXMKbys9cC5l
+CnM9cC5mCmlmKHMhPW51bGwpbz1vKyI/IitzCnM9cC5yCmlmKHMhPW51bGwpbz1vKyIjIitzCm89by5j
+aGFyQ29kZUF0KDApPT0wP286bwppZihwLng9PW51bGwpcC54PW8KZWxzZSBvPUgudihILmMoIkZpZWxk
+ICdfdGV4dCcgaGFzIGJlZW4gYXNzaWduZWQgZHVyaW5nIGluaXRpYWxpemF0aW9uLiIpKX1yZXR1cm4g
+b30sCmdGajpmdW5jdGlvbigpe3ZhciBzLHI9dGhpcyxxPXIueQppZihxPT1udWxsKXtzPXIuZQppZihz
+Lmxlbmd0aCE9PTAmJkMueEIuVyhzLDApPT09NDcpcz1DLnhCLkcocywxKQpxPXMubGVuZ3RoPT09MD9D
+LnhEOlAuQUYobmV3IEgubEooSC5WTShzLnNwbGl0KCIvIiksdC5zKSx0LmRPLmEoUC5QSCgpKSx0LmRv
+KSx0Lk4pCmlmKHIueT09bnVsbClyLnNLcChxKQplbHNlIHE9SC52KEguYygiRmllbGQgJ3BhdGhTZWdt
+ZW50cycgaGFzIGJlZW4gYXNzaWduZWQgZHVyaW5nIGluaXRpYWxpemF0aW9uLiIpKX1yZXR1cm4gcX0s
+CmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLHI9cy56CmlmKHI9PW51bGwpe3I9Qy54Qi5naU8ocy5n
+bkQoKSkKaWYocy56PT1udWxsKXMuej1yCmVsc2Ugcj1ILnYoSC5jKCJGaWVsZCAnaGFzaENvZGUnIGhh
+cyBiZWVuIGFzc2lnbmVkIGR1cmluZyBpbml0aWFsaXphdGlvbi4iKSl9cmV0dXJuIHJ9LApnaFk6ZnVu
+Y3Rpb24oKXt2YXIgcz10aGlzLHI9cy5RCmlmKHI9PW51bGwpe3I9bmV3IFAuR2ooUC5XWChzLmd0UCgp
+KSx0LmR3KQppZihzLlE9PW51bGwpcy5zTk0ocikKZWxzZSByPUgudihILmMoIkZpZWxkICdxdWVyeVBh
+cmFtZXRlcnMnIGhhcyBiZWVuIGFzc2lnbmVkIGR1cmluZyBpbml0aWFsaXphdGlvbi4iKSl9cmV0dXJu
+IHJ9LApna3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5ifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciBzPXRo
+aXMuYwppZihzPT1udWxsKXJldHVybiIiCmlmKEMueEIubihzLCJbIikpcmV0dXJuIEMueEIuTmoocywx
+LHMubGVuZ3RoLTEpCnJldHVybiBzfSwKZ3RwOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMuZApyZXR1cm4g
+cz09bnVsbD9QLndLKHRoaXMuYSk6c30sCmd0UDpmdW5jdGlvbigpe3ZhciBzPXRoaXMuZgpyZXR1cm4g
+cz09bnVsbD8iIjpzfSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5yCnJldHVybiBzPT1udWxsPyIi
+OnN9LApubTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtLGwsayxqPXRoaXMKdC5jOS5hKGIp
+CnM9ai5hCnI9cz09PSJmaWxlIgpxPWouYgpwPWouZApvPWouYwppZighKG8hPW51bGwpKW89cS5sZW5n
+dGghPT0wfHxwIT1udWxsfHxyPyIiOm51bGwKbj1qLmUKaWYoIXIpbT1vIT1udWxsJiZuLmxlbmd0aCE9
+PTAKZWxzZSBtPSEwCmlmKG0mJiFDLnhCLm4obiwiLyIpKW49Ii8iK24KbD1uCms9UC5sZShudWxsLDAs
+MCxiKQpyZXR1cm4gbmV3IFAuRG4ocyxxLG8scCxsLGssai5yKX0sCkpoOmZ1bmN0aW9uKGEsYil7dmFy
+IHMscixxLHAsbyxuCmZvcihzPTAscj0wO0MueEIuUWkoYiwiLi4vIixyKTspe3IrPTM7KytzfXE9Qy54
+Qi5jbihhLCIvIikKd2hpbGUoITApe2lmKCEocT4wJiZzPjApKWJyZWFrCnA9Qy54Qi5QayhhLCIvIixx
+LTEpCmlmKHA8MClicmVhawpvPXEtcApuPW8hPT0yCmlmKCFufHxvPT09MylpZihDLnhCLm0oYSxwKzEp
+PT09NDYpbj0hbnx8Qy54Qi5tKGEscCsyKT09PTQ2CmVsc2Ugbj0hMQplbHNlIG49ITEKaWYobilicmVh
+azstLXMKcT1wfXJldHVybiBDLnhCLmk3KGEscSsxLG51bGwsQy54Qi5HKGIsci0zKnMpKX0sClpJOmZ1
+bmN0aW9uKGEpe3JldHVybiB0aGlzLm1TKFAuaEsoYSkpfSwKbVM6ZnVuY3Rpb24oYSl7dmFyIHMscixx
+LHAsbyxuLG0sbCxrLGo9dGhpcyxpPW51bGwKaWYoYS5nRmkoKS5sZW5ndGghPT0wKXtzPWEuZ0ZpKCkK
+aWYoYS5nY2ooKSl7cj1hLmdrdSgpCnE9YS5nSmYoYSkKcD1hLmd4QSgpP2EuZ3RwKGEpOml9ZWxzZXtw
+PWkKcT1wCnI9IiJ9bz1QLnhlKGEuZ0lpKGEpKQpuPWEuZ1FEKCk/YS5ndFAoKTppfWVsc2V7cz1qLmEK
+aWYoYS5nY2ooKSl7cj1hLmdrdSgpCnE9YS5nSmYoYSkKcD1QLndCKGEuZ3hBKCk/YS5ndHAoYSk6aSxz
+KQpvPVAueGUoYS5nSWkoYSkpCm49YS5nUUQoKT9hLmd0UCgpOml9ZWxzZXtyPWouYgpxPWouYwpwPWou
+ZAppZihhLmdJaShhKT09PSIiKXtvPWouZQpuPWEuZ1FEKCk/YS5ndFAoKTpqLmZ9ZWxzZXtpZihhLmd0
+VCgpKW89UC54ZShhLmdJaShhKSkKZWxzZXttPWouZQppZihtLmxlbmd0aD09PTApaWYocT09bnVsbClv
+PXMubGVuZ3RoPT09MD9hLmdJaShhKTpQLnhlKGEuZ0lpKGEpKQplbHNlIG89UC54ZSgiLyIrYS5nSWko
+YSkpCmVsc2V7bD1qLkpoKG0sYS5nSWkoYSkpCms9cy5sZW5ndGg9PT0wCmlmKCFrfHxxIT1udWxsfHxD
+LnhCLm4obSwiLyIpKW89UC54ZShsKQplbHNlIG89UC53RihsLCFrfHxxIT1udWxsKX19bj1hLmdRRCgp
+P2EuZ3RQKCk6aX19fXJldHVybiBuZXcgUC5EbihzLHIscSxwLG8sbixhLmdaOCgpP2EuZ0thKCk6aSl9
+LApnY2o6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jIT1udWxsfSwKZ3hBOmZ1bmN0aW9uKCl7cmV0dXJu
+IHRoaXMuZCE9bnVsbH0sCmdRRDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmYhPW51bGx9LApnWjg6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5yIT1udWxsfSwKZ3RUOmZ1bmN0aW9uKCl7cmV0dXJuIEMueEIubih0
+aGlzLmUsIi8iKX0sCnQ0OmZ1bmN0aW9uKCl7dmFyIHMscj10aGlzLHE9ci5hCmlmKHEhPT0iIiYmcSE9
+PSJmaWxlIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhICIr
+cSsiIFVSSSIpKQppZihyLmd0UCgpIT09IiIpdGhyb3cgSC5iKFAuTDQodS5pKSkKaWYoci5nS2EoKSE9
+PSIiKXRocm93IEguYihQLkw0KHUubCkpCnE9JC53USgpCmlmKEgub1QocSkpcT1QLm1uKHIpCmVsc2V7
+aWYoci5jIT1udWxsJiZyLmdKZihyKSE9PSIiKUgudihQLkw0KHUuaikpCnM9ci5nRmooKQpQLmtFKHMs
+ITEpCnE9UC52ZyhDLnhCLm4oci5lLCIvIik/Ii8iOiIiLHMsIi8iKQpxPXEuY2hhckNvZGVBdCgwKT09
+MD9xOnF9cmV0dXJuIHF9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmduRCgpfSwKRE46ZnVuY3Rp
+b24oYSxiKXt2YXIgcz10aGlzCmlmKGI9PW51bGwpcmV0dXJuITEKaWYocz09PWIpcmV0dXJuITAKcmV0
+dXJuIHQuZEQuYihiKSYmcy5hPT09Yi5nRmkoKSYmcy5jIT1udWxsPT09Yi5nY2ooKSYmcy5iPT09Yi5n
+a3UoKSYmcy5nSmYocyk9PT1iLmdKZihiKSYmcy5ndHAocyk9PT1iLmd0cChiKSYmcy5lPT09Yi5nSWko
+YikmJnMuZiE9bnVsbD09PWIuZ1FEKCkmJnMuZ3RQKCk9PT1iLmd0UCgpJiZzLnIhPW51bGw9PT1iLmda
+OCgpJiZzLmdLYSgpPT09Yi5nS2EoKX0sCnNLcDpmdW5jdGlvbihhKXt0aGlzLnk9dC5iay5hKGEpfSwK
+c05NOmZ1bmN0aW9uKGEpe3RoaXMuUT10LmNaLmEoYSl9LAokaWlEOjEsCmdGaTpmdW5jdGlvbigpe3Jl
+dHVybiB0aGlzLmF9LApnSWk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZX19ClAuUloucHJvdG90eXBl
+PXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuZVAoQy5aSixILmgoYSksQy54TSwhMSl9LAokUzo1fQpQ
+Lk1FLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHM9dGhpcy5iLHI9dGhpcy5hCnMuYSs9
+ci5hCnIuYT0iJiIKcj1zLmErPUguRWooUC5lUChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51bGwmJmIu
+bGVuZ3RoIT09MCl7cy5hPXIrIj0iCnMuYSs9SC5FaihQLmVQKEMuRjMsYixDLnhNLCEwKSl9fSwKJFM6
+MjJ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCkguaChhKQppZihiPT1u
+dWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhpcy5hLiQyKGEsSC5rKGIpKQplbHNlIGZvcihzPUouSVQo
+dC51LmEoYikpLHI9dGhpcy5hO3MuRigpOylyLiQyKGEsSC5oKHMuZ2woKSkpfSwKJFM6MTR9ClAuUEUu
+cHJvdG90eXBlPXsKZ2xSOmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz10aGlzLG49bnVsbCxtPW8uYwpp
+ZihtPT1udWxsKXttPW8uYgppZigwPj1tLmxlbmd0aClyZXR1cm4gSC5PSChtLDApCnM9by5hCm09bVsw
+XSsxCnI9Qy54Qi5YVShzLCI/IixtKQpxPXMubGVuZ3RoCmlmKHI+PTApe3A9UC5QSShzLHIrMSxxLEMu
+VkMsITEpCnE9cn1lbHNlIHA9bgptPW8uYz1uZXcgUC5xZSgiZGF0YSIsIiIsbixuLFAuUEkocyxtLHEs
+Qy5XZCwhMSkscCxuKX1yZXR1cm4gbX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHMscj10aGlzLmIKaWYoMD49
+ci5sZW5ndGgpcmV0dXJuIEguT0gociwwKQpzPXRoaXMuYQpyZXR1cm4gclswXT09PS0xPyJkYXRhOiIr
+czpzfX0KUC5xMy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXko
+OTYpfSwKJFM6MjN9ClAueUkucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmEK
+aWYoYT49MjIpcmV0dXJuIEguT0gocyxhKQpzPXNbYV0KSi5DTShzLDAsOTYsYikKcmV0dXJuIHN9LAok
+UzoyNH0KUC5jNi5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHMscixxLHAKZm9yKHM9
+Yi5sZW5ndGgscj1hLmxlbmd0aCxxPTA7cTxzOysrcSl7cD1DLnhCLlcoYixxKV45NgppZihwPj1yKXJl
+dHVybiBILk9IKGEscCkKYVtwXT1jfX0sCiRTOjE1fQpQLnFkLnByb3RvdHlwZT17CiQzOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgcyxyLHEscApmb3Iocz1DLnhCLlcoYiwwKSxyPUMueEIuVyhiLDEpLHE9YS5sZW5n
+dGg7czw9cjsrK3Mpe3A9KHNeOTYpPj4+MAppZihwPj1xKXJldHVybiBILk9IKGEscCkKYVtwXT1jfX0s
+CiRTOjE1fQpQLlVmLnByb3RvdHlwZT17CmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmM+MH0sCmd4
+QTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmM+MCYmdGhpcy5kKzE8dGhpcy5lfSwKZ1FEOmZ1bmN0aW9u
+KCl7cmV0dXJuIHRoaXMuZjx0aGlzLnJ9LApnWjg6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5yPHRoaXMu
+YS5sZW5ndGh9LApnTnc6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NCYmQy54Qi5uKHRoaXMuYSwi
+ZmlsZSIpfSwKZ1daOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubih0aGlzLmEsImh0
+dHAiKX0sCmdSZTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT01JiZDLnhCLm4odGhpcy5hLCJodHRw
+cyIpfSwKZ3RUOmZ1bmN0aW9uKCl7cmV0dXJuIEMueEIuUWkodGhpcy5hLCIvIix0aGlzLmUpfSwKZ0Zp
+OmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy54CnJldHVybiBzPT1udWxsP3RoaXMueD10aGlzLlUyKCk6c30s
+ClUyOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYgppZihyPD0wKXJldHVybiIiCmlmKHMuZ1daKCkp
+cmV0dXJuImh0dHAiCmlmKHMuZ1JlKCkpcmV0dXJuImh0dHBzIgppZihzLmdOdygpKXJldHVybiJmaWxl
+IgppZihyPT09NyYmQy54Qi5uKHMuYSwicGFja2FnZSIpKXJldHVybiJwYWNrYWdlIgpyZXR1cm4gQy54
+Qi5OaihzLmEsMCxyKX0sCmdrdTpmdW5jdGlvbigpe3ZhciBzPXRoaXMuYyxyPXRoaXMuYiszCnJldHVy
+biBzPnI/Qy54Qi5Oaih0aGlzLmEscixzLTEpOiIifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciBzPXRoaXMu
+YwpyZXR1cm4gcz4wP0MueEIuTmoodGhpcy5hLHMsdGhpcy5kKToiIn0sCmd0cDpmdW5jdGlvbihhKXt2
+YXIgcz10aGlzCmlmKHMuZ3hBKCkpcmV0dXJuIFAuUUEoQy54Qi5OaihzLmEscy5kKzEscy5lKSxudWxs
+KQppZihzLmdXWigpKXJldHVybiA4MAppZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJuIDB9LApnSWk6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIuTmoodGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ3RQOmZ1bmN0
+aW9uKCl7dmFyIHM9dGhpcy5mLHI9dGhpcy5yCnJldHVybiBzPHI/Qy54Qi5Oaih0aGlzLmEscysxLHIp
+OiIifSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcy5yLHI9dGhpcy5hCnJldHVybiBzPHIubGVuZ3Ro
+P0MueEIuRyhyLHMrMSk6IiJ9LApnRmo6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9dGhpcy5lLHA9dGhpcy5m
+LG89dGhpcy5hCmlmKEMueEIuUWkobywiLyIscSkpKytxCmlmKHE9PT1wKXJldHVybiBDLnhECnM9SC5W
+TShbXSx0LnMpCmZvcihyPXE7cjxwOysrcilpZihDLnhCLm0obyxyKT09PTQ3KXtDLk5tLmkocyxDLnhC
+Lk5qKG8scSxyKSkKcT1yKzF9Qy5ObS5pKHMsQy54Qi5OaihvLHEscCkpCnJldHVybiBQLkFGKHMsdC5O
+KX0sCmdoWTpmdW5jdGlvbigpe2lmKHRoaXMuZj49dGhpcy5yKXJldHVybiBDLkNNCnJldHVybiBuZXcg
+UC5HaihQLldYKHRoaXMuZ3RQKCkpLHQuZHcpfSwKa1g6ZnVuY3Rpb24oYSl7dmFyIHM9dGhpcy5kKzEK
+cmV0dXJuIHMrYS5sZW5ndGg9PT10aGlzLmUmJkMueEIuUWkodGhpcy5hLGEscyl9LApOOTpmdW5jdGlv
+bigpe3ZhciBzPXRoaXMscj1zLnIscT1zLmEKaWYocj49cS5sZW5ndGgpcmV0dXJuIHMKcmV0dXJuIG5l
+dyBQLlVmKEMueEIuTmoocSwwLHIpLHMuYixzLmMscy5kLHMuZSxzLmYscixzLngpfSwKbm06ZnVuY3Rp
+b24oYSxiKXt2YXIgcyxyLHEscCxvLG4sbSxsLGssaixpPXRoaXMsaD1udWxsCnQuYzkuYShiKQpzPWku
+Z0ZpKCkKcj1zPT09ImZpbGUiCnE9aS5jCnA9cT4wP0MueEIuTmooaS5hLGkuYiszLHEpOiIiCm89aS5n
+eEEoKT9pLmd0cChpKTpoCnE9aS5jCmlmKHE+MCluPUMueEIuTmooaS5hLHEsaS5kKQplbHNlIG49cC5s
+ZW5ndGghPT0wfHxvIT1udWxsfHxyPyIiOmgKcT1pLmEKbT1DLnhCLk5qKHEsaS5lLGkuZikKaWYoIXIp
+bD1uIT1udWxsJiZtLmxlbmd0aCE9PTAKZWxzZSBsPSEwCmlmKGwmJiFDLnhCLm4obSwiLyIpKW09Ii8i
+K20Kaz1QLmxlKGgsMCwwLGIpCmw9aS5yCmo9bDxxLmxlbmd0aD9DLnhCLkcocSxsKzEpOmgKcmV0dXJu
+IG5ldyBQLkRuKHMscCxuLG8sbSxrLGopfSwKWkk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMoUC5o
+SyhhKSl9LAptUzpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNlb2YgUC5VZilyZXR1cm4gdGhpcy51MSh0
+aGlzLGEpCnJldHVybiB0aGlzLnZzKCkubVMoYSl9LAp1MTpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxw
+LG8sbixtLGwsayxqLGksaCxnPWIuYgppZihnPjApcmV0dXJuIGIKcz1iLmMKaWYocz4wKXtyPWEuYgpp
+ZihyPD0wKXJldHVybiBiCmlmKGEuZ053KCkpcT1iLmUhPT1iLmYKZWxzZSBpZihhLmdXWigpKXE9IWIu
+a1goIjgwIikKZWxzZSBxPSFhLmdSZSgpfHwhYi5rWCgiNDQzIikKaWYocSl7cD1yKzEKcmV0dXJuIG5l
+dyBQLlVmKEMueEIuTmooYS5hLDAscCkrQy54Qi5HKGIuYSxnKzEpLHIscytwLGIuZCtwLGIuZStwLGIu
+ZitwLGIucitwLGEueCl9ZWxzZSByZXR1cm4gdGhpcy52cygpLm1TKGIpfW89Yi5lCmc9Yi5mCmlmKG89
+PT1nKXtzPWIucgppZihnPHMpe3I9YS5mCnA9ci1nCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSww
+LHIpK0MueEIuRyhiLmEsZyksYS5iLGEuYyxhLmQsYS5lLGcrcCxzK3AsYS54KX1nPWIuYQppZihzPGcu
+bGVuZ3RoKXtyPWEucgpyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihhLmEsMCxyKStDLnhCLkcoZyxzKSxh
+LmIsYS5jLGEuZCxhLmUsYS5mLHMrKHItcyksYS54KX1yZXR1cm4gYS5OOSgpfXM9Yi5hCmlmKEMueEIu
+UWkocywiLyIsbykpe3I9YS5lCnA9ci1vCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHIpK0Mu
+eEIuRyhzLG8pLGEuYixhLmMsYS5kLHIsZytwLGIucitwLGEueCl9bj1hLmUKbT1hLmYKaWYobj09PW0m
+JmEuYz4wKXtmb3IoO0MueEIuUWkocywiLi4vIixvKTspbys9MwpwPW4tbysxCnJldHVybiBuZXcgUC5V
+ZihDLnhCLk5qKGEuYSwwLG4pKyIvIitDLnhCLkcocyxvKSxhLmIsYS5jLGEuZCxuLGcrcCxiLnIrcCxh
+LngpfWw9YS5hCmZvcihrPW47Qy54Qi5RaShsLCIuLi8iLGspOylrKz0zCmo9MAp3aGlsZSghMCl7aT1v
+KzMKaWYoIShpPD1nJiZDLnhCLlFpKHMsIi4uLyIsbykpKWJyZWFrOysragpvPWl9Zm9yKGg9IiI7bT5r
+Oyl7LS1tCmlmKEMueEIubShsLG0pPT09NDcpe2lmKGo9PT0wKXtoPSIvIgpicmVha30tLWoKaD0iLyJ9
+fWlmKG09PT1rJiZhLmI8PTAmJiFDLnhCLlFpKGwsIi8iLG4pKXtvLT1qKjMKaD0iIn1wPW0tbytoLmxl
+bmd0aApyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihsLDAsbSkraCtDLnhCLkcocyxvKSxhLmIsYS5jLGEu
+ZCxuLGcrcCxiLnIrcCxhLngpfSwKdDQ6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscD10aGlzCmlmKHAuYj49
+MCYmIXAuZ053KCkpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20g
+YSAiK3AuZ0ZpKCkrIiBVUkkiKSkKcz1wLmYKcj1wLmEKaWYoczxyLmxlbmd0aCl7aWYoczxwLnIpdGhy
+b3cgSC5iKFAuTDQodS5pKSkKdGhyb3cgSC5iKFAuTDQodS5sKSl9cT0kLndRKCkKaWYoSC5vVChxKSlz
+PVAubW4ocCkKZWxzZXtpZihwLmM8cC5kKUgudihQLkw0KHUuaikpCnM9Qy54Qi5OaihyLHAuZSxzKX1y
+ZXR1cm4gc30sCmdpTzpmdW5jdGlvbihhKXt2YXIgcz10aGlzLnkKcmV0dXJuIHM9PW51bGw/dGhpcy55
+PUMueEIuZ2lPKHRoaXMuYSk6c30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpp
+Zih0aGlzPT09YilyZXR1cm4hMApyZXR1cm4gdC5kRC5iKGIpJiZ0aGlzLmE9PT1iLncoMCl9LAp2czpm
+dW5jdGlvbigpe3ZhciBzPXRoaXMscj1udWxsLHE9cy5nRmkoKSxwPXMuZ2t1KCksbz1zLmM+MD9zLmdK
+ZihzKTpyLG49cy5neEEoKT9zLmd0cChzKTpyLG09cy5hLGw9cy5mLGs9Qy54Qi5OaihtLHMuZSxsKSxq
+PXMucgpsPWw8aj9zLmd0UCgpOnIKcmV0dXJuIG5ldyBQLkRuKHEscCxvLG4sayxsLGo8bS5sZW5ndGg/
+cy5nS2EoKTpyKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90
+b3R5cGU9e30KVy5xRS5wcm90b3R5cGU9e30KVy5HaC5wcm90b3R5cGU9ewpzTFU6ZnVuY3Rpb24oYSxi
+KXthLmhyZWY9Yn0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpR2g6MX0KVy5mWS5w
+cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9fQpXLm5CLnByb3RvdHlwZT17
+JGluQjoxfQpXLkF6LnByb3RvdHlwZT17JGlBejoxfQpXLlFQLnByb3RvdHlwZT17JGlRUDoxfQpXLm54
+LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcub0oucHJvdG90eXBl
+PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5pZC5wcm90b3R5cGU9e30KVy5RRi5w
+cm90b3R5cGU9e30KVy5OaC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9
+fQpXLmFlLnByb3RvdHlwZT17CkRjOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuY3JlYXRlSFRNTERvY3Vt
+ZW50KGIpfX0KVy5JQi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciBzLHI9YS5sZWZ0CnIudG9T
+dHJpbmcKcj0iUmVjdGFuZ2xlICgiK0guRWoocikrIiwgIgpzPWEudG9wCnMudG9TdHJpbmcKcz1yK0gu
+RWoocykrIikgIgpyPWEud2lkdGgKci50b1N0cmluZwpyPXMrSC5FaihyKSsiIHggIgpzPWEuaGVpZ2h0
+CnMudG9TdHJpbmcKcmV0dXJuIHIrSC5FaihzKX0sCkROOmZ1bmN0aW9uKGEsYil7dmFyIHMscgppZihi
+PT1udWxsKXJldHVybiExCmlmKHQucS5iKGIpKXtzPWEubGVmdApzLnRvU3RyaW5nCnI9Yi5sZWZ0CnIu
+dG9TdHJpbmcKaWYocz09PXIpe3M9YS50b3AKcy50b1N0cmluZwpyPWIudG9wCnIudG9TdHJpbmcKaWYo
+cz09PXIpe3M9YS53aWR0aApzLnRvU3RyaW5nCnI9Yi53aWR0aApyLnRvU3RyaW5nCmlmKHM9PT1yKXtz
+PWEuaGVpZ2h0CnMudG9TdHJpbmcKcj1iLmhlaWdodApyLnRvU3RyaW5nCnI9cz09PXIKcz1yfWVsc2Ug
+cz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSExfWVsc2Ugcz0hMQpyZXR1cm4gc30sCmdpTzpmdW5jdGlvbihh
+KXt2YXIgcyxyLHEscD1hLmxlZnQKcC50b1N0cmluZwpwPUMuQ0QuZ2lPKHApCnM9YS50b3AKcy50b1N0
+cmluZwpzPUMuQ0QuZ2lPKHMpCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9Qy5DRC5naU8ocikKcT1hLmhl
+aWdodApxLnRvU3RyaW5nCnJldHVybiBXLnJFKHAscyxyLEMuQ0QuZ2lPKHEpKX0sCiRpdG46MX0KVy5u
+Ny5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLnd6LnByb3RvdHlw
+ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3Zh
+ciBzCkgudVAoYikKcz10aGlzLmEKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLGIpCnJl
+dHVybiB0aGlzLiR0aS5jLmEoc1tiXSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0aGlzLiR0aS5jLmEoYykK
+dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgbGlzdCIpKX19ClcuY3YucHJvdG90eXBlPXsKZ1Fn
+OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgVy5pNyhhKX0sCmdEOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcg
+Vy5JNChhKX0sCnNEOmZ1bmN0aW9uKGEsYil7dmFyIHMKdC5RLmEoYikKcz10aGlzLmdEKGEpCnMuVjEo
+MCkKcy5GVigwLGIpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhbE5hbWV9LApGRjpmdW5jdGlv
+bihhKXt2YXIgcz0hIWEuc2Nyb2xsSW50b1ZpZXdJZk5lZWRlZAppZihzKWEuc2Nyb2xsSW50b1ZpZXdJ
+Zk5lZWRlZCgpCmVsc2UgYS5zY3JvbGxJbnRvVmlldygpfSwKbno6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2
+YXIgcyxyPXRoaXMucjYoYSxjLGQsZSkKc3dpdGNoKGIudG9Mb3dlckNhc2UoKSl7Y2FzZSJiZWZvcmVi
+ZWdpbiI6cz1hLnBhcmVudE5vZGUKcy50b1N0cmluZwpKLkVoKHMscixhKQpicmVhawpjYXNlImFmdGVy
+YmVnaW4iOnM9YS5jaGlsZE5vZGVzCnRoaXMubUsoYSxyLHMubGVuZ3RoPjA/c1swXTpudWxsKQpicmVh
+awpjYXNlImJlZm9yZWVuZCI6YS5hcHBlbmRDaGlsZChyKQpicmVhawpjYXNlImFmdGVyZW5kIjpzPWEu
+cGFyZW50Tm9kZQpzLnRvU3RyaW5nCkouRWgocyxyLGEubmV4dFNpYmxpbmcpCmJyZWFrCmRlZmF1bHQ6
+SC52KFAueFkoIkludmFsaWQgcG9zaXRpb24gIitiKSl9fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHMscixxLHAKaWYoYz09bnVsbCl7aWYoZD09bnVsbCl7cz0kLmx0CmlmKHM9PW51bGwpe3M9SC5WTShb
+XSx0LnYpCnI9bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkKQy5ObS5pKHMsVy5CbCgpKQok
+Lmx0PXIKZD1yfWVsc2UgZD1zfXM9JC5FVQppZihzPT1udWxsKXtzPW5ldyBXLktvKGQpCiQuRVU9cwpj
+PXN9ZWxzZXtzLmE9ZApjPXN9fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9y
+IGNhbiBvbmx5IGJlIHBhc3NlZCBpZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVs
+bCl7cz1kb2N1bWVudApyPXMuaW1wbGVtZW50YXRpb24Kci50b1N0cmluZwpyPUMubUguRGMociwiIikK
+JC54bz1yCiQuQk89ci5jcmVhdGVSYW5nZSgpCnI9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdC5j
+Ui5hKHIpCnM9cy5iYXNlVVJJCnMudG9TdHJpbmcKci5ocmVmPXMKJC54by5oZWFkLmFwcGVuZENoaWxk
+KHIpfXM9JC54bwppZihzLmJvZHk9PW51bGwpe3I9cy5jcmVhdGVFbGVtZW50KCJib2R5IikKQy5CWi5z
+WEcocyx0LnAuYShyKSl9cz0kLnhvCmlmKHQucC5iKGEpKXtzPXMuYm9keQpzLnRvU3RyaW5nCnE9c31l
+bHNle3MudG9TdHJpbmcKcT1zLmNyZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5k
+Q2hpbGQocSl9aWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3Rv
+dHlwZSYmIUMuTm0udGcoQy5TcSxhLnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhxKQpz
+PSQuQk8Kcy50b1N0cmluZwpwPXMuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGI9PW51bGw/Im51bGwi
+OmIpfWVsc2V7Si53ZihxLGIpCnA9JC54by5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKZm9yKDtzPXEu
+Zmlyc3RDaGlsZCxzIT1udWxsOylwLmFwcGVuZENoaWxkKHMpfWlmKHEhPT0kLnhvLmJvZHkpSi5MdChx
+KQpjLlBuKHApCmRvY3VtZW50LmFkb3B0Tm9kZShwKQpyZXR1cm4gcH0sCkFIOmZ1bmN0aW9uKGEsYixj
+KXtyZXR1cm4gdGhpcy5yNihhLGIsYyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxi
+KX0sCnBrOmZ1bmN0aW9uKGEsYixjKXt0aGlzLnNhNChhLG51bGwpCmEuYXBwZW5kQ2hpbGQodGhpcy5y
+NihhLGIsbnVsbCxjKSl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0s
+CnNSTjpmdW5jdGlvbihhLGIpe2EuaW5uZXJIVE1MPWJ9LApnbnM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
+dGFnTmFtZX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuZXUoYSwiY2xpY2siLCExLHQuayl9
+LAokaWN2OjF9ClcuQ3YucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHQuaC5iKHQuQS5h
+KGEpKX0sCiRTOjI2fQpXLmVhLnByb3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17Ck9uOmZ1
+bmN0aW9uKGEsYixjLGQpe3QuYncuYShjKQppZihjIT1udWxsKXRoaXMudihhLGIsYyxkKX0sCkI6ZnVu
+Y3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLk9uKGEsYixjLG51bGwpfSwKdjpmdW5jdGlvbihhLGIsYyxk
+KXtyZXR1cm4gYS5hZGRFdmVudExpc3RlbmVyKGIsSC50Uih0LmJ3LmEoYyksMSksZCl9LAokaUQwOjF9
+ClcuaEgucHJvdG90eXBlPXskaWhIOjF9ClcuaDQucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0
+dXJuIGEubGVuZ3RofX0KVy5ici5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
+dGh9fQpXLlZiLnByb3RvdHlwZT17CnNYRzpmdW5jdGlvbihhLGIpe2EuYm9keT1ifX0KVy5mSi5wcm90
+b3R5cGU9ewplbzpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaWZKOjF9
+Clcud2EucHJvdG90eXBlPXt9ClcuU2cucHJvdG90eXBlPXskaVNnOjF9ClcudTgucHJvdG90eXBlPXsK
+Z0RyOmZ1bmN0aW9uKGEpe2lmKCJvcmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILkVq
+KGEucHJvdG9jb2wpKyIvLyIrSC5FaihhLmhvc3QpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5n
+KGEpfSwKJGl1ODoxfQpXLkFqLnByb3RvdHlwZT17JGlBajoxfQpXLmU3LnByb3RvdHlwZT17CmdyODpm
+dW5jdGlvbihhKXt2YXIgcz10aGlzLmEscj1zLmNoaWxkTm9kZXMubGVuZ3RoCmlmKHI9PT0wKXRocm93
+IEguYihQLlBWKCJObyBlbGVtZW50cyIpKQppZihyPjEpdGhyb3cgSC5iKFAuUFYoIk1vcmUgdGhhbiBv
+bmUgZWxlbWVudCIpKQpzPXMuZmlyc3RDaGlsZApzLnRvU3RyaW5nCnJldHVybiBzfSwKRlY6ZnVuY3Rp
+b24oYSxiKXt2YXIgcyxyLHEscCxvCnQuZWguYShiKQppZihiIGluc3RhbmNlb2YgVy5lNyl7cz1iLmEK
+cj10aGlzLmEKaWYocyE9PXIpZm9yKHE9cy5jaGlsZE5vZGVzLmxlbmd0aCxwPTA7cDxxOysrcCl7bz1z
+LmZpcnN0Q2hpbGQKby50b1N0cmluZwpyLmFwcGVuZENoaWxkKG8pfXJldHVybn1mb3Iocz1iLmdreihi
+KSxyPXRoaXMuYTtzLkYoKTspci5hcHBlbmRDaGlsZChzLmdsKCkpfSwKWTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHMscgp0LkEuYShjKQpzPXRoaXMuYQpyPXMuY2hpbGROb2RlcwppZihiPDB8fGI+PXIubGVuZ3Ro
+KXJldHVybiBILk9IKHIsYikKcy5yZXBsYWNlQ2hpbGQoYyxyW2JdKX0sCmdrejpmdW5jdGlvbihhKXt2
+YXIgcz10aGlzLmEuY2hpbGROb2RlcwpyZXR1cm4gbmV3IFcuVzkocyxzLmxlbmd0aCxILnoocykuQygi
+Vzk8R20uRT4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNoaWxkTm9kZXMubGVuZ3Ro
+fSwKcTpmdW5jdGlvbihhLGIpe3ZhciBzCkgudVAoYikKcz10aGlzLmEuY2hpbGROb2RlcwppZihiPDB8
+fGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKcmV0dXJuIHNbYl19fQpXLnVILnByb3RvdHlwZT17
+CndnOmZ1bmN0aW9uKGEpe3ZhciBzPWEucGFyZW50Tm9kZQppZihzIT1udWxsKXMucmVtb3ZlQ2hpbGQo
+YSl9LApENDpmdW5jdGlvbihhKXt2YXIgcwpmb3IoO3M9YS5maXJzdENoaWxkLHMhPW51bGw7KWEucmVt
+b3ZlQ2hpbGQocyl9LAp3OmZ1bmN0aW9uKGEpe3ZhciBzPWEubm9kZVZhbHVlCnJldHVybiBzPT1udWxs
+P3RoaXMuVShhKTpzfSwKc2E0OmZ1bmN0aW9uKGEsYil7YS50ZXh0Q29udGVudD1ifSwKbUs6ZnVuY3Rp
+b24oYSxiLGMpe3JldHVybiBhLmluc2VydEJlZm9yZShiLGMpfSwKJGl1SDoxfQpXLkJILnByb3RvdHlw
+ZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIp
+CmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5iKFAuQ2YoYixhLG51bGwsbnVsbCxudWxs
+KSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXt0LkEuYShjKQp0aHJvdyBILmIoUC5MNCgi
+Q2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCmd0SDpmdW5jdGlvbihh
+KXtpZihhLmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEguYihQLlBWKCJObyBlbGVtZW50cyIpKX0s
+CkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3RoKXJldHVybiBILk9IKGEsYikKcmV0dXJu
+IGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9ClcuU04ucHJvdG90eXBlPXt9Clcu
+ZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJu
+IGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgcyxyCmlm
+KCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJu
+IHRoaXMuRFcoYSxiLGMsZCkKcz1XLlU5KCI8dGFibGU+IitILkVqKGIpKyI8L3RhYmxlPiIsYyxkKQpy
+PWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpyLnRvU3RyaW5nCnMudG9TdHJpbmcKbmV3
+IFcuZTcocikuRlYoMCxuZXcgVy5lNyhzKSkKcmV0dXJuIHJ9fQpXLkl2LnByb3RvdHlwZT17CnI2OmZ1
+bmN0aW9uKGEsYixjLGQpe3ZhciBzLHIscSxwCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGlu
+IHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApy
+PXMuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxl
+IiksYixjLGQpCnMudG9TdHJpbmcKcz1uZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnEudG9TdHJpbmcKcz1u
+ZXcgVy5lNyhxKQpwPXMuZ3I4KHMpCnIudG9TdHJpbmcKcC50b1N0cmluZwpuZXcgVy5lNyhyKS5GVigw
+LG5ldyBXLmU3KHApKQpyZXR1cm4gcn19ClcuV1AucHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMs
+ZCl7dmFyIHMscixxCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5w
+cm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKcz1kb2N1bWVudApyPXMuY3JlYXRlRG9jdW1l
+bnRGcmFnbWVudCgpCnM9Qy5JZS5yNihzLmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnMudG9T
+dHJpbmcKcz1uZXcgVy5lNyhzKQpxPXMuZ3I4KHMpCnIudG9TdHJpbmcKcS50b1N0cmluZwpuZXcgVy5l
+NyhyKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gcn19ClcueVkucHJvdG90eXBlPXsKcGs6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciBzLHIKdGhpcy5zYTQoYSxudWxsKQpzPWEuY29udGVudApzLnRvU3RyaW5nCkou
+YlQocykKcj10aGlzLnI2KGEsYixudWxsLGMpCmEuY29udGVudC5hcHBlbmRDaGlsZChyKX0sCllDOmZ1
+bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwpfSwKJGl5WToxfQpXLnc2LnByb3RvdHlw
+ZT17fQpXLks1LnByb3RvdHlwZT17ClBvOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz1XLlAxKGEub3Blbihi
+LGMpKQpyZXR1cm4gc30sCmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gYS5sb2NhdGlvbn0sCnVzOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIGEuY29uZmlybShiKX0sCiRpSzU6MSwKJGl2NjoxfQpXLkNtLnByb3RvdHlw
+ZT17JGlDbToxfQpXLkNRLnByb3RvdHlwZT17JGlDUToxfQpXLnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rp
+b24oYSl7dmFyIHMscj1hLmxlZnQKci50b1N0cmluZwpyPSJSZWN0YW5nbGUgKCIrSC5FaihyKSsiLCAi
+CnM9YS50b3AKcy50b1N0cmluZwpzPXIrSC5FaihzKSsiKSAiCnI9YS53aWR0aApyLnRvU3RyaW5nCnI9
+cytILkVqKHIpKyIgeCAiCnM9YS5oZWlnaHQKcy50b1N0cmluZwpyZXR1cm4gcitILkVqKHMpfSwKRE46
+ZnVuY3Rpb24oYSxiKXt2YXIgcyxyCmlmKGI9PW51bGwpcmV0dXJuITEKaWYodC5xLmIoYikpe3M9YS5s
+ZWZ0CnMudG9TdHJpbmcKcj1iLmxlZnQKci50b1N0cmluZwppZihzPT09cil7cz1hLnRvcApzLnRvU3Ry
+aW5nCnI9Yi50b3AKci50b1N0cmluZwppZihzPT09cil7cz1hLndpZHRoCnMudG9TdHJpbmcKcj1iLndp
+ZHRoCnIudG9TdHJpbmcKaWYocz09PXIpe3M9YS5oZWlnaHQKcy50b1N0cmluZwpyPWIuaGVpZ2h0CnIu
+dG9TdHJpbmcKcj1zPT09cgpzPXJ9ZWxzZSBzPSExfWVsc2Ugcz0hMX1lbHNlIHM9ITF9ZWxzZSBzPSEx
+CnJldHVybiBzfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciBzLHIscSxwPWEubGVmdApwLnRvU3RyaW5nCnA9
+Qy5DRC5naU8ocCkKcz1hLnRvcApzLnRvU3RyaW5nCnM9Qy5DRC5naU8ocykKcj1hLndpZHRoCnIudG9T
+dHJpbmcKcj1DLkNELmdpTyhyKQpxPWEuaGVpZ2h0CnEudG9TdHJpbmcKcmV0dXJuIFcuckUocCxzLHIs
+Qy5DRC5naU8ocSkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5n
+dGh9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93
+IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIs
+Yyl7dC5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFi
+bGUgTGlzdC4iKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1cm4gSC5P
+SChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6MSwKJGl6TToxfQpXLmNmLnBy
+b3RvdHlwZT17Cks6ZnVuY3Rpb24oYSxiKXt2YXIgcyxyLHEscCxvCnQuZUEuYShiKQpmb3Iocz10aGlz
+LmdWKCkscj1zLmxlbmd0aCxxPXRoaXMuYSxwPTA7cDxzLmxlbmd0aDtzLmxlbmd0aD09PXJ8fCgwLEgu
+bGspKHMpLCsrcCl7bz1zW3BdCmIuJDIobyxxLmdldEF0dHJpYnV0ZShvKSl9fSwKZ1Y6ZnVuY3Rpb24o
+KXt2YXIgcyxyLHEscCxvLG4sbT10aGlzLmEuYXR0cmlidXRlcwptLnRvU3RyaW5nCnM9SC5WTShbXSx0
+LnMpCmZvcihyPW0ubGVuZ3RoLHE9dC5oOSxwPTA7cDxyOysrcCl7aWYocD49bS5sZW5ndGgpcmV0dXJu
+IEguT0gobSxwKQpvPXEuYShtW3BdKQppZihvLm5hbWVzcGFjZVVSST09bnVsbCl7bj1vLm5hbWUKbi50
+b1N0cmluZwpDLk5tLmkocyxuKX19cmV0dXJuIHN9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
+Z1YoKS5sZW5ndGg9PT0wfX0KVy5pNy5wcm90b3R5cGU9ewp4NDpmdW5jdGlvbihhKXt2YXIgcz1ILm9U
+KHRoaXMuYS5oYXNBdHRyaWJ1dGUoYSkpCnJldHVybiBzfSwKcTpmdW5jdGlvbihhLGIpe3JldHVybiB0
+aGlzLmEuZ2V0QXR0cmlidXRlKEguaChiKSl9LApZOmZ1bmN0aW9uKGEsYixjKXt0aGlzLmEuc2V0QXR0
+cmlidXRlKGIsYyl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aH19ClcuU3ku
+cHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHM9SC5vVCh0aGlzLmEuYS5oYXNBdHRyaWJ1dGUo
+ImRhdGEtIit0aGlzLk8oYSkpKQpyZXR1cm4gc30sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5h
+LmEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKEguaChiKSkpfSwKWTpmdW5jdGlvbihhLGIsYyl7
+dGhpcy5hLmEuc2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKGIpLGMpfSwKSzpmdW5jdGlvbihhLGIp
+e3RoaXMuYS5LKDAsbmV3IFcuS1ModGhpcyx0LmVBLmEoYikpKX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHM9
+SC5WTShbXSx0LnMpCnRoaXMuYS5LKDAsbmV3IFcuQTModGhpcyxzKSkKcmV0dXJuIHN9LApnQTpmdW5j
+dGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aH0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
+cy5nVigpLmxlbmd0aD09PTB9LAprOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1ILlZNKGEuc3BsaXQoIi0i
+KSx0LnMpCmZvcihzPTE7czxxLmxlbmd0aDsrK3Mpe3I9cVtzXQppZihyLmxlbmd0aD4wKUMuTm0uWShx
+LHMsclswXS50b1VwcGVyQ2FzZSgpK0ouS1YociwxKSl9cmV0dXJuIEMuTm0uSChxLCIiKX0sCk86ZnVu
+Y3Rpb24oYSl7dmFyIHMscixxLHAsbwpmb3Iocz1hLmxlbmd0aCxyPTAscT0iIjtyPHM7KytyKXtwPWFb
+cl0Kbz1wLnRvTG93ZXJDYXNlKCkKcT0ocCE9PW8mJnI+MD9xKyItIjpxKStvfXJldHVybiBxLmNoYXJD
+b2RlQXQoMCk9PTA/cTpxfX0KVy5LUy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclko
+YSkubihhLCJkYXRhLSIpKXRoaXMuYi4kMih0aGlzLmEuayhDLnhCLkcoYSw1KSksYil9LAokUzoxMX0K
+Vy5BMy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubihhLCJkYXRhLSIpKUMu
+Tm0uaSh0aGlzLmIsdGhpcy5hLmsoQy54Qi5HKGEsNSkpKX0sCiRTOjExfQpXLkk0LnByb3RvdHlwZT17
+ClA6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvPVAuTHModC5OKQpmb3Iocz10aGlzLmEuY2xhc3NOYW1l
+LnNwbGl0KCIgIikscj1zLmxlbmd0aCxxPTA7cTxyOysrcSl7cD1KLlQwKHNbcV0pCmlmKHAubGVuZ3Ro
+IT09MClvLmkoMCxwKX1yZXR1cm4gb30sClg6ZnVuY3Rpb24oYSl7dGhpcy5hLmNsYXNzTmFtZT10LkMu
+YShhKS5IKDAsIiAiKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0
+aH0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNsYXNzTGlzdC5sZW5ndGg9PT0wfSwKZ29y
+OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0aCE9PTB9LApWMTpmdW5jdGlv
+bihhKXt0aGlzLmEuY2xhc3NOYW1lPSIifSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmEuY2xh
+c3NMaXN0LmNvbnRhaW5zKGIpCnJldHVybiBzfSwKaTpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuYS5j
+bGFzc0xpc3Qscj1zLmNvbnRhaW5zKGIpCnMuYWRkKGIpCnJldHVybiFyfSwKUjpmdW5jdGlvbihhLGIp
+e3ZhciBzPXRoaXMuYS5jbGFzc0xpc3Qscj1zLmNvbnRhaW5zKGIpCnMucmVtb3ZlKGIpCnJldHVybiBy
+fSwKRlY6ZnVuY3Rpb24oYSxiKXtXLlROKHRoaXMuYSx0LlEuYShiKSl9fQpXLkZrLnByb3RvdHlwZT17
+fQpXLlJPLnByb3RvdHlwZT17fQpXLmV1LnByb3RvdHlwZT17fQpXLnhDLnByb3RvdHlwZT17fQpXLnZO
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuJDEodC5CLmEoYSkpfSwKJFM6
+Mjh9ClcuSlEucHJvdG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSl7dmFyIHMKaWYoJC5vci5hPT09MCl7Zm9y
+KHM9MDtzPDI2MjsrK3MpJC5vci5ZKDAsQy5jbVtzXSxXLnBTKCkpCmZvcihzPTA7czwxMjsrK3MpJC5v
+ci5ZKDAsQy5CSVtzXSxXLlY0KCkpfX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiAkLkFOKCkudGcoMCxX
+LnJTKGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgcz0kLm9yLnEoMCxILkVqKFcuclMoYSkpKyI6
+OiIrYikKaWYocz09bnVsbClzPSQub3IucSgwLCIqOjoiK2IpCmlmKHM9PW51bGwpcmV0dXJuITEKcmV0
+dXJuIEgueTgocy4kNChhLGIsYyx0aGlzKSl9LAokaWtGOjF9ClcuR20ucHJvdG90eXBlPXsKZ2t6OmZ1
+bmN0aW9uKGEpe3JldHVybiBuZXcgVy5XOShhLHRoaXMuZ0EoYSksSC56KGEpLkMoIlc5PEdtLkU+Iikp
+fX0KVy52RC5wcm90b3R5cGU9ewppMDpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3
+IFcuVXYoYSkpfSwKRWI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBDLk5tLlZyKHRoaXMuYSxuZXcgVy5F
+ZyhhLGIsYykpfSwKJGlrRjoxfQpXLlV2LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0
+LmY2LmEoYSkuaTAodGhpcy5hKX0sCiRTOjE2fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
+e3JldHVybiB0LmY2LmEoYSkuRWIodGhpcy5hLHRoaXMuYix0aGlzLmMpfSwKJFM6MTZ9ClcubTYucHJv
+dG90eXBlPXsKQ1k6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxCnRoaXMuYS5GVigwLGMpCnM9Yi5l
+digwLG5ldyBXLkVvKCkpCnI9Yi5ldigwLG5ldyBXLldrKCkpCnRoaXMuYi5GVigwLHMpCnE9dGhpcy5j
+CnEuRlYoMCxDLnhEKQpxLkZWKDAscil9LAppMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLnRnKDAs
+Vy5yUyhhKSl9LApFYjpmdW5jdGlvbihhLGIsYyl7dmFyIHM9dGhpcyxyPVcuclMoYSkscT1zLmMKaWYo
+cS50ZygwLEguRWoocikrIjo6IitiKSlyZXR1cm4gcy5kLkR0KGMpCmVsc2UgaWYocS50ZygwLCIqOjoi
+K2IpKXJldHVybiBzLmQuRHQoYykKZWxzZXtxPXMuYgppZihxLnRnKDAsSC5FaihyKSsiOjoiK2IpKXJl
+dHVybiEwCmVsc2UgaWYocS50ZygwLCIqOjoiK2IpKXJldHVybiEwCmVsc2UgaWYocS50ZygwLEguRWoo
+cikrIjo6KiIpKXJldHVybiEwCmVsc2UgaWYocS50ZygwLCIqOjoqIikpcmV0dXJuITB9cmV0dXJuITF9
+LAokaWtGOjF9ClcuRW8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIUMuTm0udGcoQy5C
+SSxILmgoYSkpfSwKJFM6Nn0KVy5Xay5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gQy5O
+bS50ZyhDLkJJLEguaChhKSl9LAokUzo2fQpXLmN0LnByb3RvdHlwZT17CkViOmZ1bmN0aW9uKGEsYixj
+KXtpZih0aGlzLmpGKGEsYixjKSlyZXR1cm4hMAppZihiPT09InRlbXBsYXRlIiYmYz09PSIiKXJldHVy
+biEwCmlmKGEuZ2V0QXR0cmlidXRlKCJ0ZW1wbGF0ZSIpPT09IiIpcmV0dXJuIHRoaXMuZS50ZygwLGIp
+CnJldHVybiExfX0KVy5JQS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4iVEVNUExBVEU6
+OiIrSC5FaihILmgoYSkpfSwKJFM6NX0KVy5Pdy5wcm90b3R5cGU9ewppMDpmdW5jdGlvbihhKXt2YXIg
+cwppZih0LmV3LmIoYSkpcmV0dXJuITEKcz10Lmc3LmIoYSkKaWYocyYmVy5yUyhhKT09PSJmb3JlaWdu
+T2JqZWN0IilyZXR1cm4hMQppZihzKXJldHVybiEwCnJldHVybiExfSwKRWI6ZnVuY3Rpb24oYSxiLGMp
+e2lmKGI9PT0iaXMifHxDLnhCLm4oYiwib24iKSlyZXR1cm4hMQpyZXR1cm4gdGhpcy5pMChhKX0sCiRp
+a0Y6MX0KVy5XOS5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHM9dGhpcyxyPXMuYysxLHE9cy5i
+CmlmKHI8cSl7cy5zcChKLng5KHMuYSxyKSkKcy5jPXIKcmV0dXJuITB9cy5zcChudWxsKQpzLmM9cQpy
+ZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCnNwOmZ1bmN0aW9uKGEpe3RoaXMu
+ZD10aGlzLiR0aS5DKCIxPyIpLmEoYSl9LAokaUFuOjF9ClcuZFcucHJvdG90eXBlPXsKZ21XOmZ1bmN0
+aW9uKGEpe3JldHVybiBXLkhIKHRoaXMuYS5sb2NhdGlvbil9LAokaUQwOjEsCiRpdjY6MX0KVy5GYi5w
+cm90b3R5cGU9e30KVy5tay5wcm90b3R5cGU9eyRpeTA6MX0KVy5Lby5wcm90b3R5cGU9ewpQbjpmdW5j
+dGlvbihhKXt2YXIgcz10aGlzLHI9bmV3IFcuZm0ocykKcy5iPSExCnIuJDIoYSxudWxsKQpmb3IoO3Mu
+Yjspe3MuYj0hMQpyLiQyKGEsbnVsbCl9fSwKRVA6ZnVuY3Rpb24oYSxiKXt2YXIgcz10aGlzLmI9ITAK
+aWYoYiE9bnVsbD9iIT09YS5wYXJlbnROb2RlOnMpSi5MdChhKQplbHNlIGIucmVtb3ZlQ2hpbGQoYSl9
+LApJNDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbj0hMCxtPW51bGwsbD1udWxsCnRyeXttPUou
+aWcoYSkKbD1tLmEuZ2V0QXR0cmlidXRlKCJpcyIpCnQuaC5hKGEpCnM9ZnVuY3Rpb24oYyl7aWYoIShj
+LmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApKXJldHVybiB0cnVlCmlmKGMuaWQ9PSds
+YXN0Q2hpbGQnfHxjLm5hbWU9PSdsYXN0Q2hpbGQnfHxjLmlkPT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5u
+YW1lPT0ncHJldmlvdXNTaWJsaW5nJ3x8Yy5pZD09J2NoaWxkcmVuJ3x8Yy5uYW1lPT0nY2hpbGRyZW4n
+KXJldHVybiB0cnVlCnZhciBrPWMuY2hpbGROb2RlcwppZihjLmxhc3RDaGlsZCYmYy5sYXN0Q2hpbGQh
+PT1rW2subGVuZ3RoLTFdKXJldHVybiB0cnVlCmlmKGMuY2hpbGRyZW4paWYoIShjLmNoaWxkcmVuIGlu
+c3RhbmNlb2YgSFRNTENvbGxlY3Rpb258fGMuY2hpbGRyZW4gaW5zdGFuY2VvZiBOb2RlTGlzdCkpcmV0
+dXJuIHRydWUKdmFyIGo9MAppZihjLmNoaWxkcmVuKWo9Yy5jaGlsZHJlbi5sZW5ndGgKZm9yKHZhciBp
+PTA7aTxqO2krKyl7dmFyIGg9Yy5jaGlsZHJlbltpXQppZihoLmlkPT0nYXR0cmlidXRlcyd8fGgubmFt
+ZT09J2F0dHJpYnV0ZXMnfHxoLmlkPT0nbGFzdENoaWxkJ3x8aC5uYW1lPT0nbGFzdENoaWxkJ3x8aC5p
+ZD09J3ByZXZpb3VzU2libGluZyd8fGgubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGguaWQ9PSdjaGls
+ZHJlbid8fGgubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZX1yZXR1cm4gZmFsc2V9KGEpCm49SC5v
+VChzKT8hMDohKGEuYXR0cmlidXRlcyBpbnN0YW5jZW9mIE5hbWVkTm9kZU1hcCl9Y2F0Y2gocCl7SC5S
+dShwKX1yPSJlbGVtZW50IHVucHJpbnRhYmxlIgp0cnl7cj1KLmooYSl9Y2F0Y2gocCl7SC5SdShwKX10
+cnl7cT1XLnJTKGEpCnRoaXMua1IodC5oLmEoYSksYixuLHIscSx0LmYuYShtKSxILmsobCkpfWNhdGNo
+KHApe2lmKEguUnUocCkgaW5zdGFuY2VvZiBQLnUpdGhyb3cgcAplbHNle3RoaXMuRVAoYSxiKQp3aW5k
+b3cKbz0iUmVtb3ZpbmcgY29ycnVwdGVkIGVsZW1lbnQgIitILkVqKHIpCmlmKHR5cGVvZiBjb25zb2xl
+IT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKG8pfX19LAprUjpmdW5jdGlvbihhLGIsYyxk
+LGUsZixnKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzCmlmKGMpe20uRVAoYSxiKQp3aW5kb3cKcz0iUmVt
+b3ZpbmcgZWxlbWVudCBkdWUgdG8gY29ycnVwdGVkIGF0dHJpYnV0ZXMgb24gPCIrZCsiPiIKaWYodHlw
+ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4ocykKcmV0dXJufWlmKCFt
+LmEuaTAoYSkpe20uRVAoYSxiKQp3aW5kb3cKcz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCBlbGVtZW50IDwi
+K0guRWooZSkrIj4gZnJvbSAiK0guRWooYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdp
+bmRvdy5jb25zb2xlLndhcm4ocykKcmV0dXJufWlmKGchPW51bGwpaWYoIW0uYS5FYihhLCJpcyIsZykp
+e20uRVAoYSxiKQp3aW5kb3cKcz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4dGVuc2lvbiA8IitI
+LkVqKGUpKycgaXM9IicrZysnIj4nCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cu
+Y29uc29sZS53YXJuKHMpCnJldHVybn1zPWYuZ1YoKQpyPUguVk0ocy5zbGljZSgwKSxILnQ2KHMpLkMo
+ImpkPDE+IikpCmZvcihxPWYuZ1YoKS5sZW5ndGgtMSxzPWYuYTtxPj0wOy0tcSl7aWYocT49ci5sZW5n
+dGgpcmV0dXJuIEguT0gocixxKQpwPXJbcV0Kbz1tLmEKbj1KLmNIKHApCkguaChwKQppZighby5FYihh
+LG4scy5nZXRBdHRyaWJ1dGUocCkpKXt3aW5kb3cKbz0iUmVtb3ZpbmcgZGlzYWxsb3dlZCBhdHRyaWJ1
+dGUgPCIrSC5FaihlKSsiICIrcCsnPSInK0guRWoocy5nZXRBdHRyaWJ1dGUocCkpKyciPicKaWYodHlw
+ZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4obykKcy5yZW1vdmVBdHRy
+aWJ1dGUocCl9fWlmKHQuYVcuYihhKSl7cz1hLmNvbnRlbnQKcy50b1N0cmluZwptLlBuKHMpfX0sCiRp
+b246MX0KVy5mbS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtPXRo
+aXMuYQpzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOm0uSTQoYSxiKQpicmVhawpjYXNlIDg6Y2FzZSAx
+MTpjYXNlIDM6Y2FzZSA0OmJyZWFrCmRlZmF1bHQ6bS5FUChhLGIpfXM9YS5sYXN0Q2hpbGQKZm9yKHE9
+dC5BO251bGwhPXM7KXtyPW51bGwKdHJ5e3I9cy5wcmV2aW91c1NpYmxpbmcKaWYociE9bnVsbCl7cD1y
+Lm5leHRTaWJsaW5nCm89cwpvPXA9PW51bGw/byE9bnVsbDpwIT09bwpwPW99ZWxzZSBwPSExCmlmKHAp
+e3A9UC5QVigiQ29ycnVwdCBIVE1MIikKdGhyb3cgSC5iKHApfX1jYXRjaChuKXtILlJ1KG4pCnA9cS5h
+KHMpCm0uYj0hMApvPXAucGFyZW50Tm9kZQpvPWE9PW51bGw/byE9bnVsbDphIT09bwppZihvKXtvPXAu
+cGFyZW50Tm9kZQppZihvIT1udWxsKW8ucmVtb3ZlQ2hpbGQocCl9ZWxzZSBhLnJlbW92ZUNoaWxkKHAp
+CnM9bnVsbApyPWEubGFzdENoaWxkfWlmKHMhPW51bGwpdGhpcy4kMihzLGEpCnM9cn19LAokUzozMX0K
+Vy5MZS5wcm90b3R5cGU9e30KVy5LNy5wcm90b3R5cGU9e30KVy5yQi5wcm90b3R5cGU9e30KVy5YVy5w
+cm90b3R5cGU9e30KVy5vYS5wcm90b3R5cGU9e30KUC5pSi5wcm90b3R5cGU9ewpWSDpmdW5jdGlvbihh
+KXt2YXIgcyxyPXRoaXMuYSxxPXIubGVuZ3RoCmZvcihzPTA7czxxOysrcylpZihyW3NdPT09YSlyZXR1
+cm4gcwpDLk5tLmkocixhKQpDLk5tLmkodGhpcy5iLG51bGwpCnJldHVybiBxfSwKUHY6ZnVuY3Rpb24o
+YSl7dmFyIHMscixxLHA9dGhpcyxvPXt9CmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoSC5sKGEpKXJldHVy
+biBhCmlmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0
+dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAuaVApcmV0dXJuIG5ldyBEYXRlKGEuYSkKaWYodC5mdi5iKGEp
+KXRocm93IEguYihQLlNZKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIFJlZ0V4cCIpKQppZih0LmM4LmIoYSkp
+cmV0dXJuIGEKaWYodC53LmIoYSkpcmV0dXJuIGEKaWYodC5JLmIoYSkpcmV0dXJuIGEKcz10LmRFLmIo
+YSl8fCExCmlmKHMpcmV0dXJuIGEKaWYodC5mLmIoYSkpe3I9cC5WSChhKQpzPXAuYgppZihyPj1zLmxl
+bmd0aClyZXR1cm4gSC5PSChzLHIpCnE9by5hPXNbcl0KaWYocSE9bnVsbClyZXR1cm4gcQpxPXt9Cm8u
+YT1xCkMuTm0uWShzLHIscSkKYS5LKDAsbmV3IFAuamcobyxwKSkKcmV0dXJuIG8uYX1pZih0LmouYihh
+KSl7cj1wLlZIKGEpCm89cC5iCmlmKHI+PW8ubGVuZ3RoKXJldHVybiBILk9IKG8scikKcT1vW3JdCmlm
+KHEhPW51bGwpcmV0dXJuIHEKcmV0dXJuIHAuZWsoYSxyKX1pZih0LmVILmIoYSkpe3I9cC5WSChhKQpz
+PXAuYgppZihyPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLHIpCnE9by5iPXNbcl0KaWYocSE9bnVsbCly
+ZXR1cm4gcQpxPXt9Cm8uYj1xCkMuTm0uWShzLHIscSkKcC5pbShhLG5ldyBQLlRhKG8scCkpCnJldHVy
+biBvLmJ9dGhyb3cgSC5iKFAuU1koInN0cnVjdHVyZWQgY2xvbmUgb2Ygb3RoZXIgdHlwZSIpKX0sCmVr
+OmZ1bmN0aW9uKGEsYil7dmFyIHMscj1KLlU2KGEpLHE9ci5nQShhKSxwPW5ldyBBcnJheShxKQpDLk5t
+LlkodGhpcy5iLGIscCkKZm9yKHM9MDtzPHE7KytzKUMuTm0uWShwLHMsdGhpcy5QdihyLnEoYSxzKSkp
+CnJldHVybiBwfX0KUC5qZy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5hW2FdPXRo
+aXMuYi5QdihiKX0sCiRTOjd9ClAuVGEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEu
+YlthXT10aGlzLmIuUHYoYil9LAokUzo3fQpQLkJmLnByb3RvdHlwZT17CmltOmZ1bmN0aW9uKGEsYil7
+dmFyIHMscixxLHAKdC5iOC5hKGIpCmZvcihzPU9iamVjdC5rZXlzKGEpLHI9cy5sZW5ndGgscT0wO3E8
+cjsrK3Epe3A9c1txXQpiLiQyKHAsYVtwXSl9fX0KUC5Bcy5wcm90b3R5cGU9ewpUOmZ1bmN0aW9uKGEp
+e3ZhciBzCkguaChhKQpzPSQuaEcoKS5iCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnYoSC50TChhKSkK
+aWYocy50ZXN0KGEpKXJldHVybiBhCnRocm93IEguYihQLkwzKGEsInZhbHVlIiwiTm90IGEgdmFsaWQg
+Y2xhc3MgdG9rZW4iKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLlAoKS5IKDAsIiAiKX0sCmdr
+ejpmdW5jdGlvbihhKXt2YXIgcz10aGlzLlAoKQpyZXR1cm4gUC5yaihzLHMucixILkxoKHMpLmMpfSwK
+Z2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLlAoKS5hPT09MH0sCmdvcjpmdW5jdGlvbihhKXtyZXR1
+cm4gdGhpcy5QKCkuYSE9PTB9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5QKCkuYX0sCnRnOmZ1
+bmN0aW9uKGEsYil7dGhpcy5UKGIpCnJldHVybiB0aGlzLlAoKS50ZygwLGIpfSwKaTpmdW5jdGlvbihh
+LGIpe3ZhciBzCnRoaXMuVChiKQpzPXRoaXMuT1MobmV3IFAuR0UoYikpCnJldHVybiBILnk4KHM9PW51
+bGw/ITE6cyl9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHMscgp0aGlzLlQoYikKcz10aGlzLlAoKQpyPXMu
+UigwLGIpCnRoaXMuWChzKQpyZXR1cm4gcn0sCkZWOmZ1bmN0aW9uKGEsYil7dGhpcy5PUyhuZXcgUC5O
+Nyh0aGlzLHQuUS5hKGIpKSl9LAplUjpmdW5jdGlvbihhLGIpe3ZhciBzPXRoaXMuUCgpCnJldHVybiBI
+LmJLKHMsYixILkxoKHMpLmMpfSwKRTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlAoKS5FKDAsYil9
+LApWMTpmdW5jdGlvbihhKXt0aGlzLk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHMs
+cgp0LmJVLmEoYSkKcz10aGlzLlAoKQpyPWEuJDEocykKdGhpcy5YKHMpCnJldHVybiByfX0KUC5HRS5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdC5DLmEoYSkuaSgwLHRoaXMuYSl9LAokUzoz
+M30KUC5ONy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz10aGlzLmIscj1ILnQ2KHMpCnJl
+dHVybiB0LkMuYShhKS5GVigwLG5ldyBILmxKKHMsci5DKCJxVSgxKSIpLmEodGhpcy5hLmd1TSgpKSxy
+LkMoImxKPDEscVU+IikpKX0sCiRTOjE3fQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Qu
+Qy5hKGEpCmlmKGEuYT4wKXthLmI9YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5TKCl9cmV0dXJu
+IG51bGx9LAokUzoxN30KUC5oRi5wcm90b3R5cGU9eyRpaEY6MX0KUC5QQy5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXt2YXIgcwp0LlkuYShhKQpzPWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24o
+KXtyZXR1cm4gYihjLGQsdGhpcyxBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9
+fShQLlI0LGEsITEpClAuRG0ocywkLncoKSxhKQpyZXR1cm4gc30sCiRTOjR9ClAubXQucHJvdG90eXBl
+PXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyB0aGlzLmEoYSl9LAokUzo0fQpQLk56LnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5yNyhhKX0sCiRTOjM1fQpQLlFTLnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5UeihhLHQuYW0pfSwKJFM6NTR9ClAubnAucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkU0KGEpfSwKJFM6Mzd9ClAuRTQucHJv
+dG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiIT0ic3RyaW5nIiYmdHlwZW9mIGIhPSJu
+dW1iZXIiKXRocm93IEguYihQLnhZKCJwcm9wZXJ0eSBpcyBub3QgYSBTdHJpbmcgb3IgbnVtIikpCnJl
+dHVybiBQLmRVKHRoaXMuYVtiXSl9LApZOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYiE9InN0cmlu
+ZyImJnR5cGVvZiBiIT0ibnVtYmVyIil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3Ry
+aW5nIG9yIG51bSIpKQp0aGlzLmFbYl09UC53WShjKX0sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVs
+bClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0YW5jZW9mIFAuRTQmJnRoaXMuYT09PWIuYX0sCnc6ZnVuY3Rp
+b24oYSl7dmFyIHMscgp0cnl7cz1TdHJpbmcodGhpcy5hKQpyZXR1cm4gc31jYXRjaChyKXtILlJ1KHIp
+CnM9dGhpcy54YigwKQpyZXR1cm4gc319LApWNzpmdW5jdGlvbihhLGIpe3ZhciBzLHI9dGhpcy5hCmlm
+KGI9PW51bGwpcz1udWxsCmVsc2V7cz1ILnQ2KGIpCnM9UC5DSChuZXcgSC5sSihiLHMuQygiQCgxKSIp
+LmEoUC5pRygpKSxzLkMoImxKPDEsQD4iKSksITAsdC56KX1yZXR1cm4gUC5kVShyW2FdLmFwcGx5KHIs
+cykpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfX0KUC5yNy5wcm90b3R5cGU9e30KUC5Uei5wcm90
+b3R5cGU9ewpjUDpmdW5jdGlvbihhKXt2YXIgcz10aGlzLHI9YTwwfHxhPj1zLmdBKHMpCmlmKHIpdGhy
+b3cgSC5iKFAuVEUoYSwwLHMuZ0EocyksbnVsbCxudWxsKSl9LApxOmZ1bmN0aW9uKGEsYil7aWYoSC5v
+ayhiKSl0aGlzLmNQKGIpCnJldHVybiB0aGlzLiR0aS5jLmEodGhpcy5VcigwLGIpKX0sClk6ZnVuY3Rp
+b24oYSxiLGMpe3RoaXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlvbihhKXt2YXIgcz10
+aGlzLmEubGVuZ3RoCmlmKHR5cGVvZiBzPT09Im51bWJlciImJnM+Pj4wPT09cylyZXR1cm4gcwp0aHJv
+dyBILmIoUC5QVigiQmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGliUToxLAokaWNYOjEsCiRpek06MX0K
+UC5jby5wcm90b3R5cGU9e30KUC5uZC5wcm90b3R5cGU9eyRpbmQ6MX0KUC5LZS5wcm90b3R5cGU9ewpQ
+OmZ1bmN0aW9uKCl7dmFyIHMscixxLHAsbz10aGlzLmEuZ2V0QXR0cmlidXRlKCJjbGFzcyIpLG49UC5M
+cyh0Lk4pCmlmKG89PW51bGwpcmV0dXJuIG4KZm9yKHM9by5zcGxpdCgiICIpLHI9cy5sZW5ndGgscT0w
+O3E8cjsrK3Epe3A9Si5UMChzW3FdKQppZihwLmxlbmd0aCE9PTApbi5pKDAscCl9cmV0dXJuIG59LApY
+OmZ1bmN0aW9uKGEpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLkgoMCwiICIpKX19ClAuaGku
+cHJvdG90eXBlPXsKZ0Q6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLktlKGEpfSwKc2hmOmZ1bmN0aW9u
+KGEsYil7dGhpcy5ZQyhhLGIpfSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHMscixxLHAsbyxuCmlm
+KGQ9PW51bGwpe3M9SC5WTShbXSx0LnYpCmQ9bmV3IFcudkQocykKQy5ObS5pKHMsVy5UdyhudWxsKSkK
+Qy5ObS5pKHMsVy5CbCgpKQpDLk5tLmkocyxuZXcgVy5PdygpKX1jPW5ldyBXLktvKGQpCnI9Jzxzdmcg
+dmVyc2lvbj0iMS4xIj4nK0guRWooYikrIjwvc3ZnPiIKcz1kb2N1bWVudApxPXMuYm9keQpxLnRvU3Ry
+aW5nCnA9Qy5SWS5BSChxLHIsYykKbz1zLmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpwLnRvU3RyaW5n
+CnM9bmV3IFcuZTcocCkKbj1zLmdyOChzKQpmb3IoO3M9bi5maXJzdENoaWxkLHMhPW51bGw7KW8uYXBw
+ZW5kQ2hpbGQocykKcmV0dXJuIG99LApuejpmdW5jdGlvbihhLGIsYyxkLGUpe3Rocm93IEguYihQLkw0
+KCJDYW5ub3QgaW52b2tlIGluc2VydEFkamFjZW50SHRtbCBvbiBTVkcuIikpfSwKZ1ZsOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgVy5ldShhLCJjbGljayIsITEsdC5rKX0sCiRpaGk6MX0KTS5INy5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpVLkxMLnByb3RvdHlwZT17Ckx0OmZ1bmN0
+aW9uKCl7cmV0dXJuIFAuRUYoWyJub2RlSWQiLHRoaXMuYiwia2luZCIsdGhpcy5hLmFdLHQuWCx0Ll8p
+fX0KVS5NRC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdC5mRS5hKGEpLmE9PT10aGlz
+LmEucSgwLCJraW5kIil9LAokUzozOH0KVS5kMi5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBz
+LHIscSxwLG89dGhpcyxuPXQuWCxtPXQuXyxsPVAuRmwobixtKSxrPW8uYQppZihrIT1udWxsKXtzPUgu
+Vk0oW10sdC5HKQpmb3Iocj1rLmxlbmd0aCxxPTA7cTxrLmxlbmd0aDtrLmxlbmd0aD09PXJ8fCgwLEgu
+bGspKGspLCsrcSl7cD1rW3FdCkMuTm0uaShzLFAuRUYoWyJkZXNjcmlwdGlvbiIscC5hLCJocmVmIixw
+LmJdLG4sbSkpfWwuWSgwLCJlZGl0cyIscyl9bC5ZKDAsImV4cGxhbmF0aW9uIixvLmIpCmwuWSgwLCJs
+aW5lIixvLmMpCmwuWSgwLCJkaXNwbGF5UGF0aCIsby5kKQpsLlkoMCwidXJpUGF0aCIsby5lKQpuPW8u
+ZgppZihuIT1udWxsKXttPUguVk0oW10sdC5HKQpmb3Ioaz1uLmxlbmd0aCxxPTA7cTxuLmxlbmd0aDtu
+Lmxlbmd0aD09PWt8fCgwLEgubGspKG4pLCsrcSlDLk5tLmkobSxuW3FdLkx0KCkpCmwuWSgwLCJ0cmFj
+ZXMiLG0pfXJldHVybiBsfX0KVS5TZS5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3JldHVybiBQLkVG
+KFsiZGVzY3JpcHRpb24iLHRoaXMuYSwiaHJlZiIsdGhpcy5iXSx0LlgsdC5fKX19ClUuTWwucHJvdG90
+eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1cm4gUC5FRihbImhyZWYiLHRoaXMuYSwibGluZSIsdGhpcy5i
+LCJwYXRoIix0aGlzLmNdLHQuWCx0Ll8pfX0KVS55RC5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3Zh
+ciBzLHIscSxwPUguVk0oW10sdC5HKQpmb3Iocz10aGlzLmIscj1zLmxlbmd0aCxxPTA7cTxzLmxlbmd0
+aDtzLmxlbmd0aD09PXJ8fCgwLEgubGspKHMpLCsrcSlDLk5tLmkocCxzW3FdLkx0KCkpCnJldHVybiBQ
+LkVGKFsiZGVzY3JpcHRpb24iLHRoaXMuYSwiZW50cmllcyIscF0sdC5YLHQuXyl9fQpVLndiLnByb3Rv
+dHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHMscixxLHA9dGhpcyxvPVAuRmwodC5YLHQuXykKby5ZKDAs
+ImRlc2NyaXB0aW9uIixwLmEpCnM9cC5iCmlmKHMhPW51bGwpby5ZKDAsImZ1bmN0aW9uIixzKQpzPXAu
+YwppZihzIT1udWxsKW8uWSgwLCJsaW5rIixzLkx0KCkpCnM9cC5kCmlmKHMubGVuZ3RoIT09MCl7cj1I
+LnQ2KHMpCnE9ci5DKCJsSjwxLFowPHFVKixNaCo+Kj4iKQpvLlkoMCwiaGludEFjdGlvbnMiLFAuQ0go
+bmV3IEgubEoocyxyLkMoIlowPHFVKixNaCo+KigxKSIpLmEobmV3IFUuYjAoKSkscSksITAscS5DKCJh
+TC5FIikpKX1yZXR1cm4gb319ClUuYU4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFUu
+bnoodC50LmEoYSkpfSwKJFM6Mzl9ClUuYjAucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJu
+IHQuYVguYShhKS5MdCgpfSwKJFM6NDB9CkIuajgucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1
+cm4gUC5FRihbImxpbmUiLHRoaXMuYSwiZXhwbGFuYXRpb24iLHRoaXMuYiwib2Zmc2V0Iix0aGlzLmNd
+LHQuWCx0Ll8pfX0KQi5xcC5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBzLHIscSxwLG8sbixt
+LGw9dGhpcyxrPXQuWCxqPVAuRmwoayx0LmRwKQpmb3Iocz1sLmQscz1zLmdQdShzKSxzPXMuZ2t6KHMp
+LHI9dC5fLHE9dC5HO3MuRigpOyl7cD1zLmdsKCkKbz1wLmEKbj1ILlZNKFtdLHEpCmZvcihwPUouSVQo
+cC5iKTtwLkYoKTspe209cC5nbCgpCkMuTm0uaShuLFAuRUYoWyJsaW5lIixtLmEsImV4cGxhbmF0aW9u
+IixtLmIsIm9mZnNldCIsbS5jXSxrLHIpKX1qLlkoMCxvLG4pfXJldHVybiBQLkVGKFsicmVnaW9ucyIs
+bC5hLCJuYXZpZ2F0aW9uQ29udGVudCIsbC5iLCJzb3VyY2VDb2RlIixsLmMsImVkaXRzIixqXSxrLHIp
+fX0KVC5tUS5wcm90b3R5cGU9e30KTC5lLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIs
+cSxwLG8sbixtCnQuYUwuYShhKQpzPXdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZQpyPUwuRzYod2luZG93
+LmxvY2F0aW9uLmhyZWYpCnE9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKTC5HZSgpCmlmKHMhPT0i
+LyImJnMhPT1KLlQwKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQpKUwu
+RzcocyxyLHEsITAsbmV3IEwuVlcocyxyLHEpKQpwPWRvY3VtZW50Cm89Si5xRihwLnF1ZXJ5U2VsZWN0
+b3IoIi5hcHBseS1taWdyYXRpb24iKSkKbj1vLiR0aQptPW4uQygifigxKT8iKS5hKG5ldyBMLm9aKCkp
+CnQuWi5hKG51bGwpClcuSkUoby5hLG8uYixtLCExLG4uYykKbj1KLnFGKHAucXVlcnlTZWxlY3Rvcigi
+LnJlcnVuLW1pZ3JhdGlvbiIpKQptPW4uJHRpClcuSkUobi5hLG4uYixtLkMoIn4oMSk/IikuYShuZXcg
+TC5IaSgpKSwhMSxtLmMpCm09Si5xRihwLnF1ZXJ5U2VsZWN0b3IoIi5yZXBvcnQtcHJvYmxlbSIpKQpu
+PW0uJHRpClcuSkUobS5hLG0uYixuLkMoIn4oMSk/IikuYShuZXcgTC5CVCgpKSwhMSxuLmMpCnA9Si5x
+RihwLnF1ZXJ5U2VsZWN0b3IoIi5wb3B1cC1wYW5lIC5jbG9zZSIpKQpuPXAuJHRpClcuSkUocC5hLHAu
+YixuLkMoIn4oMSk/IikuYShuZXcgTC5QWSgpKSwhMSxuLmMpfSwKJFM6MTh9CkwuVlcucHJvdG90eXBl
+PXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX0sCiRTOjB9Ckwub1oucHJv
+dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAKdC5PLmEoYSkKaWYoSC5vVChDLm9sLnVz
+KHdpbmRvdywiVGhpcyB3aWxsIGFwcGx5IHRoZSBjaGFuZ2VzIHlvdSd2ZSBwcmV2aWV3ZWQgdG8geW91
+ciB3b3JraW5nIGRpcmVjdG9yeS4gSXQgaXMgcmVjb21tZW5kZWQgeW91IGNvbW1pdCBhbnkgY2hhbmdl
+cyB5b3UgbWFkZSBiZWZvcmUgZG9pbmcgdGhpcy4iKSkpe3M9TC50eSgiL2FwcGx5LW1pZ3JhdGlvbiIs
+bnVsbCkuVzcobmV3IEwuanIoKSx0LlApCnI9bmV3IEwucWwoKQp0LmI3LmEobnVsbCkKcT1zLiR0aQpw
+PSQuWDMKaWYocCE9PUMuTlUpcj1QLlZIKHIscCkKcy54ZihuZXcgUC5GZShuZXcgUC52cyhwLHEpLDIs
+bnVsbCxyLHEuQygiQDwxPiIpLktxKHEuYykuQygiRmU8MSwyPiIpKSl9fSwKJFM6Mn0KTC5qci5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0LnQuYShhKQpzPWRvY3VtZW50LmJvZHkKcy5jbGFz
+c0xpc3QucmVtb3ZlKCJwcm9wb3NlZCIpCnMuY2xhc3NMaXN0LmFkZCgiYXBwbGllZCIpfSwKJFM6NDN9
+CkwucWwucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtMLkMyKCJDb3VsZCBub3QgYXBwbHkgbWln
+cmF0aW9uIixhLGIpfSwKJEM6IiQyIiwKJFI6MiwKJFM6N30KTC5IaS5wcm90b3R5cGU9ewokMTpmdW5j
+dGlvbihhKXtyZXR1cm4gdGhpcy54bih0Lk8uYShhKSl9LAp4bjpmdW5jdGlvbihhKXt2YXIgcz0wLHI9
+UC5GWCh0LlApLHE9MSxwLG89W10sbixtLGwsayxqCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlvbihi
+LGMpe2lmKGI9PT0xKXtwPWMKcz1xfXdoaWxlKHRydWUpc3dpdGNoKHMpe2Nhc2UgMDpxPTMKZG9jdW1l
+bnQuYm9keS5jbGFzc0xpc3QuYWRkKCJyZXJ1bm5pbmciKQpzPTYKcmV0dXJuIFAualEoTC50eSgiL3Jl
+cnVuLW1pZ3JhdGlvbiIsbnVsbCksJGFzeW5jJCQxKQpjYXNlIDY6bj1jCmlmKEgub1QoSC55OChKLng5
+KG4sInN1Y2Nlc3MiKSkpKXdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKQplbHNlIEwuSzAodC5tLmEoSi54
+OShuLCJlcnJvcnMiKSkpCm8ucHVzaCg1KQpzPTQKYnJlYWsKY2FzZSAzOnE9MgpqPXAKbT1ILlJ1KGop
+Cmw9SC50cyhqKQpMLkMyKCJGYWlsZWQgdG8gcmVydW4gbWlncmF0aW9uIixtLGwpCm8ucHVzaCg1KQpz
+PTQKYnJlYWsKY2FzZSAyOm89WzFdCmNhc2UgNDpxPTEKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVt
+b3ZlKCJyZXJ1bm5pbmciKQpzPW8ucG9wKCkKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscikK
+Y2FzZSAxOnJldHVybiBQLmYzKHAscil9fSkKcmV0dXJuIFAuREkoJGFzeW5jJCQxLHIpfSwKJFM6MTl9
+CkwuQlQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMKdC5PLmEoYSkKcz10LlgKQy5vbC5Q
+byh3aW5kb3csUC5YZCgiaHR0cHMiLCJnaXRodWIuY29tIiwiZGFydC1sYW5nL3Nkay9pc3N1ZXMvbmV3
+IixQLkVGKFsidGl0bGUiLCJDdXN0b21lci1yZXBvcnRlZCBpc3N1ZSB3aXRoIE5OQkQgbWlncmF0aW9u
+IHRvb2wiLCJsYWJlbHMiLHUuZCwiYm9keSIsIiMjIyMgU3RlcHMgdG8gcmVwcm9kdWNlXG5cbiMjIyMg
+V2hhdCBkaWQgeW91IGV4cGVjdCB0byBoYXBwZW4/XG5cbiMjIyMgV2hhdCBhY3R1YWxseSBoYXBwZW5l
+ZD9cblxuX1NjcmVlbnNob3RzIGFyZSBhcHByZWNpYXRlZF9cblxuKipEYXJ0IFNESyB2ZXJzaW9uKio6
+ICIrSC5Faihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2RrLXZlcnNpb24iKS50ZXh0Q29udGVudCkr
+IlxuXG5UaGFua3MgZm9yIGZpbGluZyFcbiJdLHMscykpLmduRCgpLCJyZXBvcnQtcHJvYmxlbSIpfSwK
+JFM6Mn0KTC5QWS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcwp0Lk8uYShhKQpzPWRvY3Vt
+ZW50LnF1ZXJ5U2VsZWN0b3IoIi5wb3B1cC1wYW5lIikuc3R5bGUKcy5kaXNwbGF5PSJub25lIgpyZXR1
+cm4ibm9uZSJ9LAokUzo0NX0KTC5MLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIscQp0
+LmFMLmEoYSkKcz13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKcj1MLkc2KHdpbmRvdy5sb2NhdGlvbi5o
+cmVmKQpxPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCmlmKHMubGVuZ3RoPjEpTC5HNyhzLHIscSwh
+MSxudWxsKQplbHNle0wuQkUocyxCLndSKCksITApCkwuQlgoIiZuYnNwOyIsbnVsbCl9fSwKJFM6MTh9
+CkwuV3gucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHA9ImNvbGxhcHNlZCIKdC5P
+LmEoYSkKcz10aGlzLmEKcj1KLllFKHMpCnE9dGhpcy5iCmlmKCFyLmdEKHMpLnRnKDAscCkpe3IuZ0Qo
+cykuaSgwLHApCkouZFIocSkuaSgwLHApfWVsc2V7ci5nRChzKS5SKDAscCkKSi5kUihxKS5SKDAscCl9
+fSwKJFM6Mn0KTC5BTy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgcz1KLnFGKHQuZy5hKGEp
+KSxyPXMuJHRpLHE9ci5DKCJ+KDEpPyIpLmEobmV3IEwuZE4odGhpcy5hKSkKdC5aLmEobnVsbCkKVy5K
+RShzLmEscy5iLHEsITEsci5jKX0sCiRTOjN9CkwuZE4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
+dmFyIHMKdC5PLmEoYSkKcz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikK
+cy50b1N0cmluZwpMLnQyKGEsdGhpcy5hLHMuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3
+IFcuaTcocykpLk8oInBhdGgiKSkpfSwKJFM6Mn0KTC5Iby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt2YXIgcyxyLHEKdC5nLmEoYSkKcz1KLnFGKGEpCnI9cy4kdGkKcT1yLkMoIn4oMSk/IikuYShuZXcg
+TC54eihhLHRoaXMuYSkpCnQuWi5hKG51bGwpClcuSkUocy5hLHMuYixxLCExLHIuYyl9LAokUzozfQpM
+Lnh6LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzCnQuTy5hKGEpCnM9dGhpcy5hCkwuaFgo
+dGhpcy5iLFAuUUEocy5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhzKSkuTygi
+b2Zmc2V0IikpLG51bGwpLFAuUUEocy5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5p
+NyhzKSkuTygibGluZSIpKSxudWxsKSl9LAokUzoyfQpMLklDLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9u
+KGEpe3ZhciBzPUoucUYodC5nLmEoYSkpLHI9cy4kdGkKci5DKCJ+KDEpPyIpLmEoTC5pUygpKQp0Llou
+YShudWxsKQpXLkpFKHMuYSxzLmIsTC5pUygpLCExLHIuYyl9LAokUzozfQpMLmZDLnByb3RvdHlwZT17
+CiQxOmZ1bmN0aW9uKGEpe3QuZVEuYShhKQp0aGlzLmEuYU0oMCx0aGlzLmIpfSwKJFM6NDd9CkwudWUu
+cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dC5hdy5hKGEpCnJldHVybiBILkVqKGEucSgwLCJzZXZl
+cml0eSIpKSsiIC0gIitILkVqKGEucSgwLCJtZXNzYWdlIikpKyIgYXQgIitILkVqKGEucSgwLCJsb2Nh
+dGlvbiIpKSsiIC0gKCIrSC5FaihhLnEoMCwiY29kZSIpKSsiKSJ9LAokUzo0OH0KTC5uVC5wcm90b3R5
+cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KTC5OWS5w
+cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLG51bGwsbnVsbCl9LAokUzowfQpMLmVY
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3QuZy5hKGEpCiQuekIoKS50b1N0cmluZwp0LmRILmEo
+JC5vdygpLnEoMCwiaGxqcyIpKS5WNygiaGlnaGxpZ2h0QmxvY2siLFthXSl9LAokUzozfQpMLkVFLnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciBzLHIKdC5PLmEoYSkucHJldmVudERlZmF1bHQoKQpz
+PXRoaXMuYQpyPXRoaXMuYgpMLmFmKHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSxzLHIsITAsbmV3IEwu
+UUwocyxyKSkKTC5oWCh0aGlzLmMscyxyKX0sCiRTOjJ9CkwuUUwucHJvdG90eXBlPXsKJDA6ZnVuY3Rp
+b24oKXtMLkZyKHdpbmRvdy5sb2NhdGlvbi5wYXRobmFtZSx0aGlzLmEsdGhpcy5iKX0sCiRTOjB9Ckwu
+VlMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHMscj0ic2VsZWN0ZWQtZmlsZSIKdC5nLmEo
+YSkKYS50b1N0cmluZwpzPUouWUUoYSkKaWYoYS5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShu
+ZXcgVy5pNyhhKSkuTygibmFtZSIpKT09PXRoaXMuYS5hKXMuZ0QoYSkuaSgwLHIpCmVsc2Ugcy5nRChh
+KS5SKDAscil9LAokUzozfQpMLlRELnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBMLnQy
+KHQuTy5hKGEpLCEwLG51bGwpfSwKJFM6MjB9CkwuQVMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7
+cmV0dXJuIHRoaXMuUEwodC5PLmEoYSkpfSwKUEw6ZnVuY3Rpb24oYSl7dmFyIHM9MCxyPVAuRlgodC5Q
+KSxxPTEscCxvPVtdLG49dGhpcyxtLGwsayxqLGksaAp2YXIgJGFzeW5jJCQxPVAubHooZnVuY3Rpb24o
+YixjKXtpZihiPT09MSl7cD1jCnM9cX13aGlsZSh0cnVlKXN3aXRjaChzKXtjYXNlIDA6cT0zCmo9dC5Y
+CnM9NgpyZXR1cm4gUC5qUShMLnR5KEwuUTQoIi9hcHBseS1oaW50IixQLkZsKGosaikpLG4uYS5MdCgp
+KSwkYXN5bmMkJDEpCmNhc2UgNjpqPW4uYgptPUwuVXMoai5hKQpMLkc3KG0sbnVsbCxqLmIsITEsbnVs
+bCkKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCJuZWVkcy1yZXJ1biIpCnE9MQpzPTUKYnJlYWsK
+Y2FzZSAzOnE9MgpoPXAKbD1ILlJ1KGgpCms9SC50cyhoKQpMLkMyKCJDb3VsZCBub3QgYXBwbHkgaGlu
+dCIsbCxrKQpzPTUKYnJlYWsKY2FzZSAyOnM9MQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxy
+KQpjYXNlIDE6cmV0dXJuIFAuZjMocCxyKX19KQpyZXR1cm4gUC5ESSgkYXN5bmMkJDEscil9LAokUzox
+OX0KTC5YQS5wcm90b3R5cGU9ewpFYjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuITB9LAppMDpmdW5jdGlv
+bihhKXtyZXR1cm4hMH0sCiRpa0Y6MX0KTC5aWi5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3ZhciBz
+LHI9dGhpcyxxPVAuRmwodC5YLHQuXykKcS5ZKDAsInR5cGUiLEwudnkoci5hKSkKcS5ZKDAsIm5hbWUi
+LHIuYikKcz1yLmMKaWYocyE9bnVsbClxLlkoMCwic3VidHJlZSIsTC5WRChzKSkKcz1yLmQKaWYocyE9
+bnVsbClxLlkoMCwicGF0aCIscykKcz1yLmUKaWYocyE9bnVsbClxLlkoMCwiaHJlZiIscykKcz1yLmYK
+aWYocyE9bnVsbClxLlkoMCwiZWRpdENvdW50IixzKQpyZXR1cm4gcX19CkwuTzkucHJvdG90eXBlPXsK
+dzpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ifX0KTS5sSS5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigp
+e3ZhciBzPUQuYWIoKQpyZXR1cm4gc30sCldPOmZ1bmN0aW9uKGEsYil7dmFyIHMscixxPXQuZDQKTS5Z
+RigiYWJzb2x1dGUiLEguVk0oW2IsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGxdLHEpKQpzPXRo
+aXMuYQpzPXMuWXIoYik+MCYmIXMuaEsoYikKaWYocylyZXR1cm4gYgpyPUguVk0oW3RoaXMuZ2woKSxi
+LG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSxxKQpNLllGKCJqb2luIixyKQpyZXR1cm4gdGhp
+cy5JUChuZXcgSC51NihyLHQuZUopKX0sCnpmOmZ1bmN0aW9uKGEpe3ZhciBzLHIscT1YLkNMKGEsdGhp
+cy5hKQpxLklWKCkKcz1xLmQKcj1zLmxlbmd0aAppZihyPT09MCl7cz1xLmIKcmV0dXJuIHM9PW51bGw/
+Ii4iOnN9aWYocj09PTEpe3M9cS5iCnJldHVybiBzPT1udWxsPyIuIjpzfWlmKDA+PXIpcmV0dXJuIEgu
+T0gocywtMSkKcy5wb3AoKQpzPXEuZQppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBv
+cCgpCnEuSVYoKQpyZXR1cm4gcS53KDApfSwKSVA6ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0s
+bCxrLGoKdC5RLmEoYSkKZm9yKHM9YS4kdGkscj1zLkMoImEyKGNYLkUpIikuYShuZXcgTS5xNygpKSxx
+PWEuZ2t6KGEpLHM9bmV3IEguU08ocSxyLHMuQygiU088Y1guRT4iKSkscj10aGlzLmEscD0hMSxvPSEx
+LG49IiI7cy5GKCk7KXttPXEuZ2woKQppZihyLmhLKG0pJiZvKXtsPVguQ0wobSxyKQprPW4uY2hhckNv
+ZGVBdCgwKT09MD9uOm4Kbj1DLnhCLk5qKGssMCxyLlNwKGssITApKQpsLmI9bgppZihyLmRzKG4pKUMu
+Tm0uWShsLmUsMCxyLmdtSSgpKQpuPWwudygwKX1lbHNlIGlmKHIuWXIobSk+MCl7bz0hci5oSyhtKQpu
+PUguRWoobSl9ZWxzZXtqPW0ubGVuZ3RoCmlmKGohPT0wKXtpZigwPj1qKXJldHVybiBILk9IKG0sMCkK
+aj1yLlVkKG1bMF0pfWVsc2Ugaj0hMQppZighailpZihwKW4rPXIuZ21JKCkKbis9bX1wPXIuZHMobSl9
+cmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LApvNTpmdW5jdGlvbihhKXt2YXIgcwppZighdGhp
+cy55MyhhKSlyZXR1cm4gYQpzPVguQ0woYSx0aGlzLmEpCnMuclIoKQpyZXR1cm4gcy53KDApfSwKeTM6
+ZnVuY3Rpb24oYSl7dmFyIHMscixxLHAsbyxuLG0sbCxrLGoKYS50b1N0cmluZwpzPXRoaXMuYQpyPXMu
+WXIoYSkKaWYociE9PTApe2lmKHM9PT0kLktrKCkpZm9yKHE9MDtxPHI7KytxKWlmKEMueEIuVyhhLHEp
+PT09NDcpcmV0dXJuITAKcD1yCm89NDd9ZWxzZXtwPTAKbz1udWxsfWZvcihuPW5ldyBILnFqKGEpLmEs
+bT1uLmxlbmd0aCxxPXAsbD1udWxsO3E8bTsrK3EsbD1vLG89ayl7az1DLnhCLm0obixxKQppZihzLnI0
+KGspKXtpZihzPT09JC5LaygpJiZrPT09NDcpcmV0dXJuITAKaWYobyE9bnVsbCYmcy5yNChvKSlyZXR1
+cm4hMAppZihvPT09NDYpaj1sPT1udWxsfHxsPT09NDZ8fHMucjQobCkKZWxzZSBqPSExCmlmKGopcmV0
+dXJuITB9fWlmKG89PW51bGwpcmV0dXJuITAKaWYocy5yNChvKSlyZXR1cm4hMAppZihvPT09NDYpcz1s
+PT1udWxsfHxzLnI0KGwpfHxsPT09NDYKZWxzZSBzPSExCmlmKHMpcmV0dXJuITAKcmV0dXJuITF9LApI
+UDpmdW5jdGlvbihhLGIpe3ZhciBzLHIscSxwLG8sbixtLGw9dGhpcyxrPSdVbmFibGUgdG8gZmluZCBh
+IHBhdGggdG8gIicKYj1sLldPKDAsYikKcz1sLmEKaWYocy5ZcihiKTw9MCYmcy5ZcihhKT4wKXJldHVy
+biBsLm81KGEpCmlmKHMuWXIoYSk8PTB8fHMuaEsoYSkpYT1sLldPKDAsYSkKaWYocy5ZcihhKTw9MCYm
+cy5ZcihiKT4wKXRocm93IEguYihYLkk3KGsrSC5FaihhKSsnIiBmcm9tICInK0guRWooYikrJyIuJykp
+CnI9WC5DTChiLHMpCnIuclIoKQpxPVguQ0woYSxzKQpxLnJSKCkKcD1yLmQKbz1wLmxlbmd0aAppZihv
+IT09MCl7aWYoMD49bylyZXR1cm4gSC5PSChwLDApCnA9Si5STShwWzBdLCIuIil9ZWxzZSBwPSExCmlm
+KHApcmV0dXJuIHEudygwKQpwPXIuYgpvPXEuYgppZihwIT1vKXA9cD09bnVsbHx8bz09bnVsbHx8IXMu
+TmMocCxvKQplbHNlIHA9ITEKaWYocClyZXR1cm4gcS53KDApCndoaWxlKCEwKXtwPXIuZApvPXAubGVu
+Z3RoCmlmKG8hPT0wKXtuPXEuZAptPW4ubGVuZ3RoCmlmKG0hPT0wKXtpZigwPj1vKXJldHVybiBILk9I
+KHAsMCkKcD1wWzBdCmlmKDA+PW0pcmV0dXJuIEguT0gobiwwKQpuPXMuTmMocCxuWzBdKQpwPW59ZWxz
+ZSBwPSExfWVsc2UgcD0hMQppZighcClicmVhawpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0KHIuZSwxKQpD
+Lk5tLlc0KHEuZCwwKQpDLk5tLlc0KHEuZSwxKX1wPXIuZApvPXAubGVuZ3RoCmlmKG8hPT0wKXtpZigw
+Pj1vKXJldHVybiBILk9IKHAsMCkKcD1KLlJNKHBbMF0sIi4uIil9ZWxzZSBwPSExCmlmKHApdGhyb3cg
+SC5iKFguSTcoaytILkVqKGEpKyciIGZyb20gIicrSC5FaihiKSsnIi4nKSkKcD10Lk4KQy5ObS5VRyhx
+LmQsMCxQLk84KHIuZC5sZW5ndGgsIi4uIiwhMSxwKSkKQy5ObS5ZKHEuZSwwLCIiKQpDLk5tLlVHKHEu
+ZSwxLFAuTzgoci5kLmxlbmd0aCxzLmdtSSgpLCExLHApKQpzPXEuZApwPXMubGVuZ3RoCmlmKHA9PT0w
+KXJldHVybiIuIgppZihwPjEmJkouUk0oQy5ObS5ncloocyksIi4iKSl7cz1xLmQKaWYoMD49cy5sZW5n
+dGgpcmV0dXJuIEguT0gocywtMSkKcy5wb3AoKQpzPXEuZQppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5P
+SChzLC0xKQpzLnBvcCgpCmlmKDA+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsLTEpCnMucG9wKCkKQy5O
+bS5pKHMsIiIpfXEuYj0iIgpxLklWKCkKcmV0dXJuIHEudygwKX19Ck0ucTcucHJvdG90eXBlPXsKJDE6
+ZnVuY3Rpb24oYSl7cmV0dXJuIEguaChhKSE9PSIifSwKJFM6Nn0KTS5Oby5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXtILmsoYSkKcmV0dXJuIGE9PW51bGw/Im51bGwiOiciJythKyciJ30sCiRTOjUwfQpC
+LmZ2LnByb3RvdHlwZT17CnhaOmZ1bmN0aW9uKGEpe3ZhciBzLHI9dGhpcy5ZcihhKQppZihyPjApcmV0
+dXJuIEoubGQoYSwwLHIpCmlmKHRoaXMuaEsoYSkpe2lmKDA+PWEubGVuZ3RoKXJldHVybiBILk9IKGEs
+MCkKcz1hWzBdfWVsc2Ugcz1udWxsCnJldHVybiBzfSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09
+Yn19ClguV0QucHJvdG90eXBlPXsKSVY6ZnVuY3Rpb24oKXt2YXIgcyxyLHE9dGhpcwp3aGlsZSghMCl7
+cz1xLmQKaWYoIShzLmxlbmd0aCE9PTAmJkouUk0oQy5ObS5ncloocyksIiIpKSlicmVhawpzPXEuZApp
+ZigwPj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLC0xKQpzLnBvcCgpCnM9cS5lCmlmKDA+PXMubGVuZ3Ro
+KXJldHVybiBILk9IKHMsLTEpCnMucG9wKCl9cz1xLmUKcj1zLmxlbmd0aAppZihyIT09MClDLk5tLlko
+cyxyLTEsIiIpfSwKclI6ZnVuY3Rpb24oKXt2YXIgcyxyLHEscCxvLG4sbT10aGlzLGw9SC5WTShbXSx0
+LnMpCmZvcihzPW0uZCxyPXMubGVuZ3RoLHE9MCxwPTA7cDxzLmxlbmd0aDtzLmxlbmd0aD09PXJ8fCgw
+LEgubGspKHMpLCsrcCl7bz1zW3BdCm49Si5pYShvKQppZighKG4uRE4obywiLiIpfHxuLkROKG8sIiIp
+KSlpZihuLkROKG8sIi4uIikpe249bC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJuIEguT0go
+bCwtMSkKbC5wb3AoKX1lbHNlICsrcX1lbHNlIEMuTm0uaShsLG8pfWlmKG0uYj09bnVsbClDLk5tLlVH
+KGwsMCxQLk84KHEsIi4uIiwhMSx0Lk4pKQppZihsLmxlbmd0aD09PTAmJm0uYj09bnVsbClDLk5tLmko
+bCwiLiIpCm0uc25KKGwpCnM9bS5hCm0uc1BoKFAuTzgobC5sZW5ndGgrMSxzLmdtSSgpLCEwLHQuTikp
+CnI9bS5iCmlmKHI9PW51bGx8fGwubGVuZ3RoPT09MHx8IXMuZHMocikpQy5ObS5ZKG0uZSwwLCIiKQpy
+PW0uYgppZihyIT1udWxsJiZzPT09JC5LaygpKXtyLnRvU3RyaW5nCm0uYj1ILnlzKHIsIi8iLCJcXCIp
+fW0uSVYoKX0sCnc6ZnVuY3Rpb24oYSl7dmFyIHMscixxPXRoaXMscD1xLmIKcD1wIT1udWxsP3A6IiIK
+Zm9yKHM9MDtzPHEuZC5sZW5ndGg7KytzKXtyPXEuZQppZihzPj1yLmxlbmd0aClyZXR1cm4gSC5PSChy
+LHMpCnI9cCtILkVqKHJbc10pCnA9cS5kCmlmKHM+PXAubGVuZ3RoKXJldHVybiBILk9IKHAscykKcD1y
+K0guRWoocFtzXSl9cCs9SC5FaihDLk5tLmdyWihxLmUpKQpyZXR1cm4gcC5jaGFyQ29kZUF0KDApPT0w
+P3A6cH0sCnNuSjpmdW5jdGlvbihhKXt0aGlzLmQ9dC5FLmEoYSl9LApzUGg6ZnVuY3Rpb24oYSl7dGhp
+cy5lPXQuRS5hKGEpfX0KWC5kdi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhj
+ZXB0aW9uOiAiK3RoaXMuYX0sCiRpUno6MX0KTy56TC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLmdvYyh0aGlzKX19CkUuT0YucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEMueEIudGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9u
+KGEpe3ZhciBzPWEubGVuZ3RoCnJldHVybiBzIT09MCYmQy54Qi5tKGEscy0xKSE9PTQ3fSwKU3A6ZnVu
+Y3Rpb24oYSxiKXtpZihhLmxlbmd0aCE9PTAmJkMueEIuVyhhLDApPT09NDcpcmV0dXJuIDEKcmV0dXJu
+IDB9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3Jl
+dHVybiExfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInBvc2l4In0sCmdtSTpmdW5jdGlvbigpe3JldHVy
+biIvIn19CkYucnUucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIp
+fSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3ZhciBzPWEubGVu
+Z3RoCmlmKHM9PT0wKXJldHVybiExCmlmKEMueEIubShhLHMtMSkhPT00NylyZXR1cm4hMApyZXR1cm4g
+Qy54Qi5UYyhhLCI6Ly8iKSYmdGhpcy5ZcihhKT09PXN9LApTcDpmdW5jdGlvbihhLGIpe3ZhciBzLHIs
+cSxwLG89YS5sZW5ndGgKaWYobz09PTApcmV0dXJuIDAKaWYoQy54Qi5XKGEsMCk9PT00NylyZXR1cm4g
+MQpmb3Iocz0wO3M8bzsrK3Mpe3I9Qy54Qi5XKGEscykKaWYocj09PTQ3KXJldHVybiAwCmlmKHI9PT01
+OCl7aWYocz09PTApcmV0dXJuIDAKcT1DLnhCLlhVKGEsIi8iLEMueEIuUWkoYSwiLy8iLHMrMSk/cysz
+OnMpCmlmKHE8PTApcmV0dXJuIG8KaWYoIWJ8fG88cSszKXJldHVybiBxCmlmKCFDLnhCLm4oYSwiZmls
+ZTovLyIpKXJldHVybiBxCmlmKCFCLll1KGEscSsxKSlyZXR1cm4gcQpwPXErMwpyZXR1cm4gbz09PXA/
+cDpxKzR9fXJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpm
+dW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGghPT0wJiZDLnhCLlcoYSwwKT09PTQ3fSwKZ29jOmZ1bmN0
+aW9uKCl7cmV0dXJuInVybCJ9LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpMLklWLnByb3RvdHlw
+ZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhPT09NDd8fGE9PT05Mn0sCmRzOmZ1bmN0aW9uKGEpe3ZhciBzPWEubGVuZ3RoCmlmKHM9PT0w
+KXJldHVybiExCnM9Qy54Qi5tKGEscy0xKQpyZXR1cm4hKHM9PT00N3x8cz09PTkyKX0sClNwOmZ1bmN0
+aW9uKGEsYil7dmFyIHMscixxPWEubGVuZ3RoCmlmKHE9PT0wKXJldHVybiAwCnM9Qy54Qi5XKGEsMCkK
+aWYocz09PTQ3KXJldHVybiAxCmlmKHM9PT05Mil7aWYocTwyfHxDLnhCLlcoYSwxKSE9PTkyKXJldHVy
+biAxCnI9Qy54Qi5YVShhLCJcXCIsMikKaWYocj4wKXtyPUMueEIuWFUoYSwiXFwiLHIrMSkKaWYocj4w
+KXJldHVybiByfXJldHVybiBxfWlmKHE8MylyZXR1cm4gMAppZighQi5PUyhzKSlyZXR1cm4gMAppZihD
+LnhCLlcoYSwxKSE9PTU4KXJldHVybiAwCnE9Qy54Qi5XKGEsMikKaWYoIShxPT09NDd8fHE9PT05Mikp
+cmV0dXJuIDAKcmV0dXJuIDN9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhL
+OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLllyKGEpPT09MX0sCk90OmZ1bmN0aW9uKGEsYil7dmFyIHMK
+aWYoYT09PWIpcmV0dXJuITAKaWYoYT09PTQ3KXJldHVybiBiPT09OTIKaWYoYT09PTkyKXJldHVybiBi
+PT09NDcKaWYoKGFeYikhPT0zMilyZXR1cm4hMQpzPWF8MzIKcmV0dXJuIHM+PTk3JiZzPD0xMjJ9LApO
+YzpmdW5jdGlvbihhLGIpe3ZhciBzLHIscQppZihhPT1iKXJldHVybiEwCnM9YS5sZW5ndGgKaWYocyE9
+PWIubGVuZ3RoKXJldHVybiExCmZvcihyPUouclkoYikscT0wO3E8czsrK3EpaWYoIXRoaXMuT3QoQy54
+Qi5XKGEscSksci5XKGIscSkpKXJldHVybiExCnJldHVybiEwfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJu
+IndpbmRvd3MifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIlxcIn19OyhmdW5jdGlvbiBhbGlhc2VzKCl7
+dmFyIHM9Si52Qi5wcm90b3R5cGUKcy5VPXMudwpzLlNqPXMuZTcKcz1KLk1GLnByb3RvdHlwZQpzLnQ9
+cy53CnM9UC5jWC5wcm90b3R5cGUKcy5HRz1zLmV2CnM9UC5NaC5wcm90b3R5cGUKcy54Yj1zLncKcz1X
+LmN2LnByb3RvdHlwZQpzLkRXPXMucjYKcz1XLm02LnByb3RvdHlwZQpzLmpGPXMuRWIKcz1QLkU0LnBy
+b3RvdHlwZQpzLlVyPXMucQpzLmU0PXMuWX0pKCk7KGZ1bmN0aW9uIGluc3RhbGxUZWFyT2Zmcygpe3Zh
+ciBzPWh1bmtIZWxwZXJzLl9zdGF0aWNfMSxyPWh1bmtIZWxwZXJzLl9zdGF0aWNfMCxxPWh1bmtIZWxw
+ZXJzLmluc3RhbGxJbnN0YW5jZVRlYXJPZmYscD1odW5rSGVscGVycy5pbnN0YWxsU3RhdGljVGVhck9m
+ZixvPWh1bmtIZWxwZXJzLl9pbnN0YW5jZV8xdQpzKFAsIkVYIiwiWlYiLDgpCnMoUCwieXQiLCJvQSIs
+OCkKcyhQLCJxVyIsIkJ6Iiw4KQpyKFAsIlY5IiwiZU4iLDEpCnEoUC5QZi5wcm90b3R5cGUsImdZSiIs
+MCwxLG51bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0sMjksMCkKcyhQLCJDeSIsIk5DIiw0KQpzKFAs
+IlBIIiwiTXQiLDUpCnAoVywicFMiLDQsbnVsbCxbIiQ0Il0sWyJxRCJdLDksMCkKcChXLCJWNCIsNCxu
+dWxsLFsiJDQiXSxbIlFXIl0sOSwwKQpvKFAuQXMucHJvdG90eXBlLCJndU0iLCJUIiw1KQpzKFAsImlH
+Iiwid1kiLDUzKQpzKFAsIncwIiwiZFUiLDM2KQpzKEwsImlTIiwiaTYiLDIwKX0pKCk7KGZ1bmN0aW9u
+IGluaGVyaXRhbmNlKCl7dmFyIHM9aHVua0hlbHBlcnMubWl4aW4scj1odW5rSGVscGVycy5pbmhlcml0
+LHE9aHVua0hlbHBlcnMuaW5oZXJpdE1hbnkKcihQLk1oLG51bGwpCnEoUC5NaCxbSC5GSyxKLnZCLEou
+bTEsUC5jWCxILkU3LFAuWFMsUC5uWSxILmE3LFAuQW4sSC5GdSxILkpCLEguU1UsSC5SZSxILnd2LFAu
+UG4sSC5XVSxILkxJLEguVHAsSC5mOSxILnRlLEguYnEsSC5YTyxILmtyLFAuWWssSC52aCxILk42LEgu
+VlIsSC5FSyxILlBiLEgudFEsSC5TZCxILkpjLEguRyxQLlczLFAuaWgsUC5GeSxQLkdWLFAuUGYsUC5G
+ZSxQLnZzLFAuT00sUC5xaCxQLk1PLFAua1QsUC54SSxQLkN3LFAubTAsUC5YdixQLmJuLFAubG0sUC5s
+RCxQLktQLFAubGYsUC5XWSxQLlVrLFAuU2gsUC5SdyxQLmJ6LFAuaVAsUC5rNSxQLktZLFAuQ0QsUC5h
+RSxQLk4zLFAuYzgsUC5aZCxQLlJuLFAuRG4sUC5QRSxQLlVmLFcuaWQsVy5GayxXLkpRLFcuR20sVy52
+RCxXLm02LFcuT3csVy5XOSxXLmRXLFcuRmIsVy5tayxXLktvLFAuaUosUC5FNCxNLkg3LFUuTEwsVS5k
+MixVLlNlLFUuTWwsVS55RCxVLndiLEIuajgsQi5xcCxULm1RLEwuWEEsTC5aWixMLk85LE0ubEksTy56
+TCxYLldELFguZHZdKQpxKEoudkIsW0oueUUsSi53ZSxKLk1GLEouamQsSi5xSSxKLkRyLEguRVQsVy5E
+MCxXLkF6LFcuTGUsVy5OaCxXLmFlLFcuSUIsVy5uNyxXLmVhLFcuYnIsVy5TZyxXLnU4LFcuSzcsVy5Y
+VyxQLmhGXSkKcShKLk1GLFtKLmlDLEoua2QsSi5jNV0pCnIoSi5QbyxKLmpkKQpxKEoucUksW0ouYlUs
+Si5WQV0pCnEoUC5jWCxbSC5CUixILmJRLEguaTEsSC5VNSxILkFNLEgudTYsSC5YUixQLm1XLEgudW5d
+KQpxKEguQlIsW0guWnksSC5RQ10pCnIoSC5vbCxILlp5KQpyKEguVXEsSC5RQykKcihILmpWLEguVXEp
+CnEoUC5YUyxbSC5uLFAuRXosSC5heixILnZWLEguRXEsUC5DNixILmtTLFAuVWQsUC5GLFAudSxQLm1w
+LFAudWIsUC5kcyxQLmxqLFAuVVYsUC5wXSkKcihQLnV5LFAublkpCnEoUC51eSxbSC53MixXLnd6LFcu
+ZTddKQpyKEgucWosSC53MikKcShILmJRLFtILmFMLEguTUIsSC5pNV0pCnEoSC5hTCxbSC5uSCxILmxK
+LFAuaThdKQpyKEgueHksSC5pMSkKcShQLkFuLFtILk1ILEguU08sSC5VMV0pCnIoSC5kNSxILkFNKQpy
+KFAuUlUsUC5QbikKcihQLkdqLFAuUlUpCnIoSC5QRCxQLkdqKQpyKEguTFAsSC5XVSkKcShILlRwLFtI
+LkNqLEgubGMsSC5kQyxILndOLEguVlgsUC50aCxQLmhhLFAuVnMsUC5GdCxQLnlILFAuV00sUC5TWCxQ
+LkdzLFAuZGEsUC5vUSxQLnBWLFAuVTcsUC52cixQLnJ0LFAuS0YsUC5aTCxQLlJULFAualosUC5ycSxQ
+LlJXLFAuQjUsUC51TyxQLnBLLFAuaGosUC5WcCxQLk9SLFAucmEsUC55USxQLnBnLFAuYzIsUC50aSxQ
+LldGLFAubjEsUC5jUyxQLlZDLFAuSlQsUC5SWixQLk1FLFAueTUsUC5xMyxQLnlJLFAuYzYsUC5xZCxX
+LkN2LFcuS1MsVy5BMyxXLnZOLFcuVXYsVy5FZyxXLkVvLFcuV2ssVy5JQSxXLmZtLFAuamcsUC5UYSxQ
+LkdFLFAuTjcsUC51USxQLlBDLFAubXQsUC5OeixQLlFTLFAubnAsVS5NRCxVLmFOLFUuYjAsTC5lLEwu
+VlcsTC5vWixMLmpyLEwucWwsTC5IaSxMLkJULEwuUFksTC5MLEwuV3gsTC5BTyxMLmROLEwuSG8sTC54
+eixMLklDLEwuZkMsTC51ZSxMLm5ULEwuTlksTC5lWCxMLkVFLEwuUUwsTC5WUyxMLlRELEwuQVMsTS5x
+NyxNLk5vXSkKcihILlcwLFAuRXopCnEoSC5sYyxbSC56eCxILnJUXSkKcihILmtZLFAuQzYpCnIoUC5p
+bCxQLllrKQpxKFAuaWwsW0guTjUsUC51dyxXLmNmLFcuU3ldKQpxKFAubVcsW0guS1csUC5xNF0pCnIo
+SC5YSCxILkVUKQpxKEguWEgsW0guUkcsSC5XQl0pCnIoSC5WUCxILlJHKQpyKEguRGcsSC5WUCkKcihI
+LlpHLEguV0IpCnIoSC5QZyxILlpHKQpxKEguUGcsW0gueGosSC5kRSxILlpBLEguZFQsSC5QcSxILmVF
+LEguVjZdKQpyKEguaU0sSC5rUykKcihQLlpmLFAuUGYpCnIoUC5KaSxQLm0wKQpyKFAuYjYsUC5YdikK
+cihQLlZqLFAuV1kpCnEoUC5VayxbUC5DVixQLlppLFAuYnldKQpyKFAud0ksUC5rVCkKcShQLndJLFtQ
+LlU4LFAub2osUC5NeCxQLkUzLFAuR1ldKQpyKFAuSzgsUC5VZCkKcihQLnR1LFAuU2gpCnIoUC51NSxQ
+LlppKQpxKFAudSxbUC5iSixQLmVZXSkKcihQLnFlLFAuRG4pCnEoVy5EMCxbVy51SCxXLndhLFcuSzUs
+Vy5DbV0pCnEoVy51SCxbVy5jdixXLm54LFcuUUYsVy5DUV0pCnEoVy5jdixbVy5xRSxQLmhpXSkKcShX
+LnFFLFtXLkdoLFcuZlksVy5uQixXLlFQLFcuaDQsVy5TTixXLmxwLFcuVGIsVy5JdixXLldQLFcueVld
+KQpyKFcub0osVy5MZSkKcihXLmhILFcuQXopCnIoVy5WYixXLlFGKQpyKFcuZkosVy53YSkKcShXLmVh
+LFtXLnc2LFcuZXddKQpyKFcuQWosVy53NikKcihXLnJCLFcuSzcpCnIoVy5CSCxXLnJCKQpyKFcudzQs
+Vy5JQikKcihXLm9hLFcuWFcpCnIoVy5yaCxXLm9hKQpyKFcuaTcsVy5jZikKcihQLkFzLFAuVmopCnEo
+UC5BcyxbVy5JNCxQLktlXSkKcihXLlJPLFAucWgpCnIoVy5ldSxXLlJPKQpyKFcueEMsUC5NTykKcihX
+LmN0LFcubTYpCnIoUC5CZixQLmlKKQpxKFAuRTQsW1AucjcsUC5jb10pCnIoUC5UeixQLmNvKQpyKFAu
+bmQsUC5oaSkKcihCLmZ2LE8uekwpCnEoQi5mdixbRS5PRixGLnJ1LEwuSVZdKQpzKEgudzIsSC5SZSkK
+cyhILlFDLFAubEQpCnMoSC5SRyxQLmxEKQpzKEguVlAsSC5TVSkKcyhILldCLFAubEQpCnMoSC5aRyxI
+LlNVKQpzKFAublksUC5sRCkKcyhQLldZLFAubGYpCnMoUC5SVSxQLktQKQpzKFcuTGUsVy5pZCkKcyhX
+Lks3LFAubEQpCnMoVy5yQixXLkdtKQpzKFcuWFcsUC5sRCkKcyhXLm9hLFcuR20pCnMoUC5jbyxQLmxE
+KX0pKCkKdmFyIHY9e3R5cGVVbml2ZXJzZTp7ZUM6bmV3IE1hcCgpLHRSOnt9LGVUOnt9LHRQVjp7fSxz
+RUE6W119LG1hbmdsZWRHbG9iYWxOYW1lczp7SWY6ImludCIsQ1A6ImRvdWJsZSIsTFo6Im51bSIscVU6
+IlN0cmluZyIsYTI6ImJvb2wiLGM4OiJOdWxsIix6TToiTGlzdCJ9LG1hbmdsZWROYW1lczp7fSxnZXRU
+eXBlRnJvbU5hbWU6Z2V0R2xvYmFsRnJvbU5hbWUsbWV0YWRhdGE6W10sdHlwZXM6WyJjOCgpIiwifigp
+IiwiYzgoQWoqKSIsImM4KGN2KikiLCJAKEApIiwicVUocVUpIiwiYTIocVUpIiwiYzgoQCxAKSIsIn4o
+figpKSIsImEyKGN2LHFVLHFVLEpRKSIsImM4KEApIiwiYzgocVUscVUpIiwiYzgoTWg/LE1oPykiLCJA
+KCkiLCJjOChxVSxAKSIsIn4objYscVUsSWYpIiwiYTIoa0YpIiwifih4dTxxVT4pIiwiYzgoZWEqKSIs
+ImI4PGM4PiooQWoqKSIsIn4oQWoqKSIsIn4ocVUsSWYpIiwifihxVSxxVT8pIiwibjYoSWYpIiwibjYo
+QCxAKSIsImM4KElmLEApIiwiYTIodUgpIiwiYzgoQCxHeikiLCJAKGVhKSIsIn4oTWhbR3o/XSkiLCJj
+OChNaCxHeikiLCJ+KHVILHVIPykiLCJ2czxAPihAKSIsImEyKHh1PHFVPikiLCJAKHFVKSIsInI3KEAp
+IiwiTWg/KEApIiwiRTQoQCkiLCJhMiooSDcqKSIsIkxMKihAKSIsIlowPHFVKixNaCo+KihMTCopIiwi
+QChALHFVKSIsImM4KEdELEApIiwiYzgoWjA8cVUqLE1oKj4qKSIsIlowPHFVLHFVPihaMDxxVSxxVT4s
+cVUpIiwicVUqKEFqKikiLCJ+KEApIiwiYzgoZXcqKSIsInFVKihaMDxALEA+KikiLCJ+KHFVW0BdKSIs
+InFVKHFVPykiLCJJZihJZixJZikiLCJjOCh+KCkpIiwiTWg/KE1oPykiLCJUejxAPihAKSJdLGludGVy
+Y2VwdG9yc0J5VGFnOm51bGwsbGVhZlRhZ3M6bnVsbCxhcnJheVJ0aTp0eXBlb2YgU3ltYm9sPT0iZnVu
+Y3Rpb24iJiZ0eXBlb2YgU3ltYm9sKCk9PSJzeW1ib2wiP1N5bWJvbCgiJHRpIik6IiR0aSJ9CkgueGIo
+di50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJjNSI6Ik1GIiwiaUMiOiJNRiIsImtkIjoiTUYiLCJy
+eCI6ImVhIiwiZTUiOiJlYSIsIlkwIjoiaGkiLCJ0cCI6ImhpIiwiRzgiOiJldyIsIk1yIjoicUUiLCJl
+TCI6InFFIiwiSTAiOiJ1SCIsImhzIjoidUgiLCJYZyI6IlFGIiwibnIiOiJBaiIsInk0IjoidzYiLCJh
+UCI6IkNtIiwieGMiOiJueCIsImtKIjoibngiLCJ6VSI6IkRnIiwiZGYiOiJFVCIsInlFIjp7ImEyIjpb
+XX0sIndlIjp7ImM4IjpbXX0sIk1GIjp7InZtIjpbXSwiRUgiOltdfSwiamQiOnsiek0iOlsiMSJdLCJi
+USI6WyIxIl0sImNYIjpbIjEiXX0sIlBvIjp7ImpkIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0s
+ImNYIjpbIjEiXX0sIm0xIjp7IkFuIjpbIjEiXX0sInFJIjp7IkNQIjpbXSwiTFoiOltdfSwiYlUiOnsi
+Q1AiOltdLCJJZiI6W10sIkxaIjpbXX0sIlZBIjp7IkNQIjpbXSwiTFoiOltdfSwiRHIiOnsicVUiOltd
+LCJ2WCI6W119LCJCUiI6eyJjWCI6WyIyIl19LCJFNyI6eyJBbiI6WyIyIl19LCJaeSI6eyJCUiI6WyIx
+IiwiMiJdLCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIm9sIjp7Ilp5IjpbIjEiLCIyIl0sIkJSIjpbIjEi
+LCIyIl0sImJRIjpbIjIiXSwiY1giOlsiMiJdLCJjWC5FIjoiMiJ9LCJVcSI6eyJsRCI6WyIyIl0sInpN
+IjpbIjIiXSwiQlIiOlsiMSIsIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl19LCJqViI6eyJVcSI6WyIx
+IiwiMiJdLCJsRCI6WyIyIl0sInpNIjpbIjIiXSwiQlIiOlsiMSIsIjIiXSwiYlEiOlsiMiJdLCJjWCI6
+WyIyIl0sImxELkUiOiIyIiwiY1guRSI6IjIifSwibiI6eyJYUyI6W119LCJxaiI6eyJsRCI6WyJJZiJd
+LCJSZSI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJiUSI6WyJJZiJdLCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYi
+LCJSZS5FIjoiSWYifSwiYlEiOnsiY1giOlsiMSJdfSwiYUwiOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19
+LCJuSCI6eyJhTCI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdLCJhTC5FIjoiMSIsImNYLkUiOiIx
+In0sImE3Ijp7IkFuIjpbIjEiXX0sImkxIjp7ImNYIjpbIjIiXSwiY1guRSI6IjIifSwieHkiOnsiaTEi
+OlsiMSIsIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIk1IIjp7IkFuIjpbIjIi
+XX0sImxKIjp7ImFMIjpbIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl0sImFMLkUiOiIyIiwiY1guRSI6
+IjIifSwiVTUiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJTTyI6eyJBbiI6WyIxIl19LCJBTSI6eyJj
+WCI6WyIxIl0sImNYLkUiOiIxIn0sImQ1Ijp7IkFNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl0s
+ImNYLkUiOiIxIn0sIlUxIjp7IkFuIjpbIjEiXX0sIk1CIjp7ImJRIjpbIjEiXSwiY1giOlsiMSJdLCJj
+WC5FIjoiMSJ9LCJGdSI6eyJBbiI6WyIxIl19LCJ1NiI6eyJjWCI6WyIxIl0sImNYLkUiOiIxIn0sIkpC
+Ijp7IkFuIjpbIjEiXX0sIncyIjp7ImxEIjpbIjEiXSwiUmUiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpb
+IjEiXSwiY1giOlsiMSJdfSwid3YiOnsiR0QiOltdfSwiUEQiOnsiR2oiOlsiMSIsIjIiXSwiUlUiOlsi
+MSIsIjIiXSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIldVIjp7
+IlowIjpbIjEiLCIyIl19LCJMUCI6eyJXVSI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiWFIiOnsi
+Y1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJMSSI6eyJ2USI6W119LCJXMCI6eyJYUyI6W119LCJheiI6eyJY
+UyI6W119LCJ2ViI6eyJYUyI6W119LCJ0ZSI6eyJSeiI6W119LCJYTyI6eyJHeiI6W119LCJUcCI6eyJF
+SCI6W119LCJsYyI6eyJFSCI6W119LCJ6eCI6eyJFSCI6W119LCJyVCI6eyJFSCI6W119LCJFcSI6eyJY
+UyI6W119LCJrWSI6eyJYUyI6W119LCJONSI6eyJZayI6WyIxIiwiMiJdLCJGbyI6WyIxIiwiMiJdLCJa
+MCI6WyIxIiwiMiJdLCJZay5LIjoiMSIsIllrLlYiOiIyIn0sImk1Ijp7ImJRIjpbIjEiXSwiY1giOlsi
+MSJdLCJjWC5FIjoiMSJ9LCJONiI6eyJBbiI6WyIxIl19LCJWUiI6eyJ3TCI6W10sInZYIjpbXX0sIkVL
+Ijp7ImliIjpbXSwiT2QiOltdfSwiS1ciOnsiY1giOlsiaWIiXSwiY1guRSI6ImliIn0sIlBiIjp7IkFu
+IjpbImliIl19LCJ0USI6eyJPZCI6W119LCJ1biI6eyJjWCI6WyJPZCJdLCJjWC5FIjoiT2QifSwiU2Qi
+OnsiQW4iOlsiT2QiXX0sIkVUIjp7ImVxIjpbXX0sIlhIIjp7IlhqIjpbIjEiXSwiRVQiOltdLCJlcSI6
+W119LCJEZyI6eyJsRCI6WyJDUCJdLCJYaiI6WyJDUCJdLCJ6TSI6WyJDUCJdLCJFVCI6W10sImJRIjpb
+IkNQIl0sImVxIjpbXSwiY1giOlsiQ1AiXSwiU1UiOlsiQ1AiXSwibEQuRSI6IkNQIn0sIlBnIjp7ImxE
+IjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltd
+LCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdfSwieGoiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0i
+OlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0s
+ImxELkUiOiJJZiJ9LCJkRSI6eyJsRCI6WyJJZiJdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6
+W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0s
+IlpBIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYi
+XSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiZFQiOnsibEQiOlsi
+SWYiXSwiWGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJlcSI6W10sImNY
+IjpbIklmIl0sIlNVIjpbIklmIl0sImxELkUiOiJJZiJ9LCJQcSI6eyJsRCI6WyJJZiJdLCJYaiI6WyJJ
+ZiJdLCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1Ui
+OlsiSWYiXSwibEQuRSI6IklmIn0sImVFIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklm
+Il0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5F
+IjoiSWYifSwiVjYiOnsibEQiOlsiSWYiXSwibjYiOltdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJF
+VCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6Iklm
+In0sImtTIjp7IlhTIjpbXX0sImlNIjp7IlhTIjpbXX0sIkdWIjp7IkFuIjpbIjEiXX0sInE0Ijp7ImNY
+IjpbIjEiXSwiY1guRSI6IjEifSwiWmYiOnsiUGYiOlsiMSJdfSwidnMiOnsiYjgiOlsiMSJdfSwiQ3ci
+OnsiWFMiOltdfSwibTAiOnsiUW0iOltdfSwiSmkiOnsibTAiOltdLCJRbSI6W119LCJiNiI6eyJYdiI6
+WyIxIl0sInh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJsbSI6eyJBbiI6WyIxIl19LCJt
+VyI6eyJjWCI6WyIxIl19LCJ1eSI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6
+WyIxIl19LCJpbCI6eyJZayI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiWWsiOnsiWjAiOlsiMSIs
+IjIiXX0sIlBuIjp7IlowIjpbIjEiLCIyIl19LCJHaiI6eyJSVSI6WyIxIiwiMiJdLCJQbiI6WyIxIiwi
+MiJdLCJLUCI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwiVmoiOnsibGYiOlsiMSJdLCJ4dSI6WyIx
+Il0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwiWHYiOnsieHUiOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpb
+IjEiXX0sInV3Ijp7IllrIjpbInFVIiwiQCJdLCJaMCI6WyJxVSIsIkAiXSwiWWsuSyI6InFVIiwiWWsu
+ViI6IkAifSwiaTgiOnsiYUwiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsicVUiXSwiYUwuRSI6InFV
+IiwiY1guRSI6InFVIn0sIkNWIjp7IlVrIjpbInpNPElmPiIsInFVIl0sIlVrLlMiOiJ6TTxJZj4ifSwi
+VTgiOnsid0kiOlsiek08SWY+IiwicVUiXX0sIlppIjp7IlVrIjpbInFVIiwiek08SWY+Il19LCJVZCI6
+eyJYUyI6W119LCJLOCI6eyJYUyI6W119LCJieSI6eyJVayI6WyJNaD8iLCJxVSJdLCJVay5TIjoiTWg/
+In0sIm9qIjp7IndJIjpbIk1oPyIsInFVIl19LCJNeCI6eyJ3SSI6WyJxVSIsIk1oPyJdfSwidTUiOnsi
+VWsiOlsicVUiLCJ6TTxJZj4iXSwiVWsuUyI6InFVIn0sIkUzIjp7IndJIjpbInFVIiwiek08SWY+Il19
+LCJHWSI6eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwiQ1AiOnsiTFoiOltdfSwiSWYiOnsiTFoiOltdfSwi
+ek0iOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4dSI6eyJiUSI6WyIxIl0s
+ImNYIjpbIjEiXX0sInFVIjp7InZYIjpbXX0sIkM2Ijp7IlhTIjpbXX0sIkV6Ijp7IlhTIjpbXX0sIkYi
+OnsiWFMiOltdfSwidSI6eyJYUyI6W119LCJiSiI6eyJYUyI6W119LCJlWSI6eyJYUyI6W119LCJtcCI6
+eyJYUyI6W119LCJ1YiI6eyJYUyI6W119LCJkcyI6eyJYUyI6W119LCJsaiI6eyJYUyI6W119LCJVViI6
+eyJYUyI6W119LCJrNSI6eyJYUyI6W119LCJLWSI6eyJYUyI6W119LCJwIjp7IlhTIjpbXX0sIkNEIjp7
+IlJ6IjpbXX0sImFFIjp7IlJ6IjpbXX0sIlpkIjp7Ikd6IjpbXX0sIlJuIjp7IkJMIjpbXX0sIkRuIjp7
+ImlEIjpbXX0sIlVmIjp7ImlEIjpbXX0sInFlIjp7ImlEIjpbXX0sInFFIjp7ImN2IjpbXSwidUgiOltd
+LCJEMCI6W119LCJHaCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZlkiOnsiY3YiOltdLCJ1SCI6
+W10sIkQwIjpbXX0sIm5CIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRUCI6eyJjdiI6W10sInVI
+IjpbXSwiRDAiOltdfSwibngiOnsidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0s
+IklCIjp7InRuIjpbIkxaIl19LCJ3eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJj
+WCI6WyIxIl0sImxELkUiOiIxIn0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwiaEgiOnsiQXoiOltdfSwi
+aDQiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwiZkoiOnsi
+RDAiOltdfSwid2EiOnsiRDAiOltdfSwiQWoiOnsiZWEiOltdfSwiZTciOnsibEQiOlsidUgiXSwiek0i
+OlsidUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwibEQuRSI6InVIIn0sInVIIjp7IkQwIjpbXX0s
+IkJIIjp7ImxEIjpbInVIIl0sIkdtIjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpb
+InVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJTTiI6eyJjdiI6W10sInVI
+IjpbXSwiRDAiOltdfSwiZXciOnsiZWEiOltdfSwibHAiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0s
+IlRiIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltd
+fSwiV1AiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sInlZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
+W119LCJ3NiI6eyJlYSI6W119LCJLNSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQwIjpbXX0sIkNR
+Ijp7InVIIjpbXSwiRDAiOltdfSwidzQiOnsidG4iOlsiTFoiXX0sInJoIjp7ImxEIjpbInVIIl0sIkdt
+IjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0sImxE
+LkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJjZiI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUi
+XX0sImk3Ijp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZay5W
+IjoicVUifSwiU3kiOnsiWWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIs
+IllrLlYiOiJxVSJ9LCJJNCI6eyJsZiI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6
+WyJxVSJdLCJsZi5FIjoicVUifSwiUk8iOnsicWgiOlsiMSJdfSwiZXUiOnsiUk8iOlsiMSJdLCJxaCI6
+WyIxIl19LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6eyJrRiI6W119LCJ2RCI6eyJrRiI6W119LCJtNiI6
+eyJrRiI6W119LCJjdCI6eyJrRiI6W119LCJPdyI6eyJrRiI6W119LCJXOSI6eyJBbiI6WyIxIl19LCJk
+VyI6eyJ2NiI6W10sIkQwIjpbXX0sIm1rIjp7InkwIjpbXX0sIktvIjp7Im9uIjpbXX0sIkFzIjp7Imxm
+IjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6W119
+LCJUeiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJFNCI6W10sImNYIjpbIjEiXSwi
+bEQuRSI6IjEifSwibmQiOnsiaGkiOltdLCJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiS2UiOnsibGYi
+OlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUiXSwiY1giOlsicVUiXSwibGYuRSI6InFVIn0sImhp
+Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJYQSI6eyJrRiI6W119LCJkdiI6eyJSeiI6W119LCJP
+RiI6eyJmdiI6W119LCJydSI6eyJmdiI6W119LCJJViI6eyJmdiI6W119LCJuNiI6eyJ6TSI6WyJJZiJd
+LCJiUSI6WyJJZiJdLCJjWCI6WyJJZiJdLCJlcSI6W119fScpKQpILkZGKHYudHlwZVVuaXZlcnNlLEpT
+T04ucGFyc2UoJ3sidzIiOjEsIlFDIjoyLCJYSCI6MSwia1QiOjIsIm1XIjoxLCJ1eSI6MSwiaWwiOjIs
+IlZqIjoxLCJuWSI6MSwiV1kiOjEsImNvIjoxfScpKQp2YXIgdT17bDoiQ2Fubm90IGV4dHJhY3QgYSBm
+aWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IixpOiJDYW5ub3QgZXh0
+cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBxdWVyeSBjb21wb25lbnQiLGo6IkNhbm5v
+dCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1
+dGhvcml0eSIsZDoiYXJlYS1hbmFseXplcixhbmFseXplci1ubmJkLW1pZ3JhdGlvbix0eXBlLWJ1ZyJ9
+CnZhciB0PShmdW5jdGlvbiBydGlpKCl7dmFyIHM9SC5OMApyZXR1cm57bjpzKCJDdyIpLGNSOnMoIm5C
+IiksdzpzKCJBeiIpLHA6cygiUVAiKSxnRjpzKCJQRDxHRCxAPiIpLGI6cygiYlE8QD4iKSxoOnMoImN2
+IikscjpzKCJYUyIpLEI6cygiZWEiKSxhUzpzKCJEMCIpLGc4OnMoIlJ6IiksYzg6cygiaEgiKSxZOnMo
+IkVIIiksZDpzKCJiODxAPiIpLEk6cygiU2ciKSxvOnMoInZRIiksZWg6cygiY1g8dUg+IiksUTpzKCJj
+WDxxVT4iKSx1OnMoImNYPEA+IiksdjpzKCJqZDxrRj4iKSxzOnMoImpkPHFVPiIpLHg6cygiamQ8QD4i
+KSxhOnMoImpkPElmPiIpLGQ3OnMoImpkPFNlKj4iKSxoNDpzKCJqZDxqOCo+IiksRzpzKCJqZDxaMDxx
+VSosTWgqPio+IiksY1E6cygiamQ8WloqPiIpLGk6cygiamQ8cVUqPiIpLGFBOnMoImpkPHlEKj4iKSxh
+SjpzKCJqZDx3Yio+IiksVjpzKCJqZDxJZio+IiksZDQ6cygiamQ8cVU/PiIpLFQ6cygid2UiKSxlSDpz
+KCJ2bSIpLEQ6cygiYzUiKSxhVTpzKCJYajxAPiIpLGFtOnMoIlR6PEA+IiksZW86cygiTjU8R0QsQD4i
+KSxkejpzKCJoRiIpLEU6cygiek08cVU+IiksajpzKCJ6TTxAPiIpLEw6cygiek08SWY+IiksSjpzKCJa
+MDxxVSxxVT4iKSxmOnMoIlowPEAsQD4iKSxkbzpzKCJsSjxxVSxAPiIpLGZqOnMoImxKPHFVKixxVT4i
+KSxkRTpzKCJFVCIpLGJtOnMoIlY2IiksQTpzKCJ1SCIpLGY2OnMoImtGIiksUDpzKCJjOCIpLEs6cygi
+TWgiKSxxOnMoInRuPExaPiIpLGZ2OnMoIndMIiksZXc6cygibmQiKSxDOnMoInh1PHFVPiIpLGw6cygi
+R3oiKSxOOnMoInFVIiksZDA6cygicVUocVUqKSIpLGc3OnMoImhpIiksZm86cygiR0QiKSxhVzpzKCJ5
+WSIpLGFrOnMoImVxIiksZ2M6cygibjYiKSxiSjpzKCJrZCIpLGR3OnMoIkdqPHFVLHFVPiIpLGREOnMo
+ImlEIiksZUo6cygidTY8cVU+IiksZzQ6cygiSzUiKSxjaTpzKCJ2NiIpLGcyOnMoIkNtIiksYkM6cygi
+WmY8ZkoqPiIpLGg5OnMoIkNRIiksYWM6cygiZTciKSxrOnMoImV1PEFqKj4iKSxSOnMoInd6PGN2Kj4i
+KSxjOnMoInZzPEA+IiksZko6cygidnM8SWY+IiksZ1Y6cygidnM8ZkoqPiIpLGNyOnMoIkpRIikseTpz
+KCJhMiIpLGFsOnMoImEyKE1oKSIpLGdSOnMoIkNQIiksejpzKCJAIiksZk86cygiQCgpIiksYkk6cygi
+QChNaCkiKSxhZzpzKCJAKE1oLEd6KSIpLGJVOnMoIkAoeHU8cVU+KSIpLGRPOnMoIkAocVUpIiksYjg6
+cygiQChALEApIiksUzpzKCJJZiIpLGRkOnMoIkdoKiIpLGc6cygiY3YqIiksYUw6cygiZWEqIiksYVg6
+cygiTEwqIiksZkU6cygiSDcqIiksVTpzKCJjWDxAPioiKSxkSDpzKCJFNCoiKSxmSzpzKCJ6TTxAPioi
+KSxkXzpzKCJ6TTxqOCo+KiIpLGRwOnMoInpNPFowPHFVKixNaCo+Kj4qIiksbTpzKCJ6TTxNaCo+KiIp
+LGJaOnMoInU4KiIpLGF3OnMoIlowPEAsQD4qIiksdDpzKCJaMDxxVSosTWgqPioiKSxPOnMoIkFqKiIp
+LGNGOnMoIjAmKiIpLF86cygiTWgqIiksZVE6cygiZXcqIiksWDpzKCJxVSoiKSxjaDpzKCJEMD8iKSxi
+RzpzKCJiODxjOD4/IiksYms6cygiek08cVU+PyIpLGJNOnMoInpNPEA+PyIpLGNaOnMoIlowPHFVLHFV
+Pj8iKSxjOTpzKCJaMDxxVSxAPj8iKSxXOnMoIk1oPyIpLEY6cygiRmU8QCxAPj8iKSxlOnMoImJuPyIp
+LGI3OnMoImEyKE1oKT8iKSxidzpzKCJAKGVhKT8iKSxmVjpzKCJNaD8oTWg/LE1oPyk/IiksZEE6cygi
+TWg/KEApPyIpLFo6cygifigpPyIpLGViOnMoIn4oZXcqKT8iKSxkaTpzKCJMWiIpLEg6cygifiIpLE06
+cygifigpIiksZUE6cygifihxVSxxVSkiKSxjQTpzKCJ+KHFVLEApIil9fSkoKTsoZnVuY3Rpb24gY29u
+c3RhbnRzKCl7dmFyIHM9aHVua0hlbHBlcnMubWFrZUNvbnN0TGlzdApDLnhuPVcuR2gucHJvdG90eXBl
+CkMuUlk9Vy5RUC5wcm90b3R5cGUKQy5tSD1XLmFlLnByb3RvdHlwZQpDLkJaPVcuVmIucHJvdG90eXBl
+CkMuRHQ9Vy5mSi5wcm90b3R5cGUKQy5Paz1KLnZCLnByb3RvdHlwZQpDLk5tPUouamQucHJvdG90eXBl
+CkMuam49Si5iVS5wcm90b3R5cGUKQy5qTj1KLndlLnByb3RvdHlwZQpDLkNEPUoucUkucHJvdG90eXBl
+CkMueEI9Si5Eci5wcm90b3R5cGUKQy5ERz1KLmM1LnByb3RvdHlwZQpDLkV4PVcudTgucHJvdG90eXBl
+CkMudDU9Vy5CSC5wcm90b3R5cGUKQy5MdD1XLlNOLnByb3RvdHlwZQpDLlpRPUouaUMucHJvdG90eXBl
+CkMuSWU9Vy5UYi5wcm90b3R5cGUKQy52Qj1KLmtkLnByb3RvdHlwZQpDLm9sPVcuSzUucHJvdG90eXBl
+CkMueTg9bmV3IFAuVTgoKQpDLmg5PW5ldyBQLkNWKCkKQy5Hdz1uZXcgSC5GdShILk4wKCJGdTxjOD4i
+KSkKQy5PND1mdW5jdGlvbiBnZXRUYWdGYWxsYmFjayhvKSB7CiAgdmFyIHMgPSBPYmplY3QucHJvdG90
+eXBlLnRvU3RyaW5nLmNhbGwobyk7CiAgcmV0dXJuIHMuc3Vic3RyaW5nKDgsIHMubGVuZ3RoIC0gMSk7
+Cn0KQy5ZcT1mdW5jdGlvbigpIHsKICB2YXIgdG9TdHJpbmdGdW5jdGlvbiA9IE9iamVjdC5wcm90b3R5
+cGUudG9TdHJpbmc7CiAgZnVuY3Rpb24gZ2V0VGFnKG8pIHsKICAgIHZhciBzID0gdG9TdHJpbmdGdW5j
+dGlvbi5jYWxsKG8pOwogICAgcmV0dXJuIHMuc3Vic3RyaW5nKDgsIHMubGVuZ3RoIC0gMSk7CiAgfQog
+IGZ1bmN0aW9uIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpIHsKICAgIGlmICgvXkhUTUxbQS1aXS4q
+RWxlbWVudCQvLnRlc3QodGFnKSkgewogICAgICB2YXIgbmFtZSA9IHRvU3RyaW5nRnVuY3Rpb24uY2Fs
+bChvYmplY3QpOwogICAgICBpZiAobmFtZSA9PSAiW29iamVjdCBPYmplY3RdIikgcmV0dXJuIG51bGw7
+CiAgICAgIHJldHVybiAiSFRNTEVsZW1lbnQiOwogICAgfQogIH0KICBmdW5jdGlvbiBnZXRVbmtub3du
+VGFnR2VuZXJpY0Jyb3dzZXIob2JqZWN0LCB0YWcpIHsKICAgIGlmIChzZWxmLkhUTUxFbGVtZW50ICYm
+IG9iamVjdCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSByZXR1cm4gIkhUTUxFbGVtZW50IjsKICAgIHJl
+dHVybiBnZXRVbmtub3duVGFnKG9iamVjdCwgdGFnKTsKICB9CiAgZnVuY3Rpb24gcHJvdG90eXBlRm9y
+VGFnKHRhZykgewogICAgaWYgKHR5cGVvZiB3aW5kb3cgPT0gInVuZGVmaW5lZCIpIHJldHVybiBudWxs
+OwogICAgaWYgKHR5cGVvZiB3aW5kb3dbdGFnXSA9PSAidW5kZWZpbmVkIikgcmV0dXJuIG51bGw7CiAg
+ICB2YXIgY29uc3RydWN0b3IgPSB3aW5kb3dbdGFnXTsKICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3Ig
+IT0gImZ1bmN0aW9uIikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gY29uc3RydWN0b3IucHJvdG90eXBl
+OwogIH0KICBmdW5jdGlvbiBkaXNjcmltaW5hdG9yKHRhZykgeyByZXR1cm4gbnVsbDsgfQogIHZhciBp
+c0Jyb3dzZXIgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3QiOwogIHJldHVybiB7CiAgICBnZXRU
+YWc6IGdldFRhZywKICAgIGdldFVua25vd25UYWc6IGlzQnJvd3NlciA/IGdldFVua25vd25UYWdHZW5l
+cmljQnJvd3NlciA6IGdldFVua25vd25UYWcsCiAgICBwcm90b3R5cGVGb3JUYWc6IHByb3RvdHlwZUZv
+clRhZywKICAgIGRpc2NyaW1pbmF0b3I6IGRpc2NyaW1pbmF0b3IgfTsKfQpDLndiPWZ1bmN0aW9uKGdl
+dFRhZ0ZhbGxiYWNrKSB7CiAgcmV0dXJuIGZ1bmN0aW9uKGhvb2tzKSB7CiAgICBpZiAodHlwZW9mIG5h
+dmlnYXRvciAhPSAib2JqZWN0IikgcmV0dXJuIGhvb2tzOwogICAgdmFyIHVhID0gbmF2aWdhdG9yLnVz
+ZXJBZ2VudDsKICAgIGlmICh1YS5pbmRleE9mKCJEdW1wUmVuZGVyVHJlZSIpID49IDApIHJldHVybiBo
+b29rczsKICAgIGlmICh1YS5pbmRleE9mKCJDaHJvbWUiKSA+PSAwKSB7CiAgICAgIGZ1bmN0aW9uIGNv
+bmZpcm0ocCkgewogICAgICAgIHJldHVybiB0eXBlb2Ygd2luZG93ID09ICJvYmplY3QiICYmIHdpbmRv
+d1twXSAmJiB3aW5kb3dbcF0ubmFtZSA9PSBwOwogICAgICB9CiAgICAgIGlmIChjb25maXJtKCJXaW5k
+b3ciKSAmJiBjb25maXJtKCJIVE1MRWxlbWVudCIpKSByZXR1cm4gaG9va3M7CiAgICB9CiAgICBob29r
+cy5nZXRUYWcgPSBnZXRUYWdGYWxsYmFjazsKICB9Owp9CkMuS1U9ZnVuY3Rpb24oaG9va3MpIHsKICBp
+ZiAodHlwZW9mIGRhcnRFeHBlcmltZW50YWxGaXh1cEdldFRhZyAhPSAiZnVuY3Rpb24iKSByZXR1cm4g
+aG9va3M7CiAgaG9va3MuZ2V0VGFnID0gZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0VGFnKGhvb2tzLmdl
+dFRhZyk7Cn0KQy5mUT1mdW5jdGlvbihob29rcykgewogIHZhciBnZXRUYWcgPSBob29rcy5nZXRUYWc7
+CiAgdmFyIHByb3RvdHlwZUZvclRhZyA9IGhvb2tzLnByb3RvdHlwZUZvclRhZzsKICBmdW5jdGlvbiBn
+ZXRUYWdGaXhlZChvKSB7CiAgICB2YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgaWYgKHRhZyA9PSAiRG9j
+dW1lbnQiKSB7CiAgICAgIGlmICghIW8ueG1sVmVyc2lvbikgcmV0dXJuICIhRG9jdW1lbnQiOwogICAg
+ICByZXR1cm4gIiFIVE1MRG9jdW1lbnQiOwogICAgfQogICAgcmV0dXJuIHRhZzsKICB9CiAgZnVuY3Rp
+b24gcHJvdG90eXBlRm9yVGFnRml4ZWQodGFnKSB7CiAgICBpZiAodGFnID09ICJEb2N1bWVudCIpIHJl
+dHVybiBudWxsOwogICAgcmV0dXJuIHByb3RvdHlwZUZvclRhZyh0YWcpOwogIH0KICBob29rcy5nZXRU
+YWcgPSBnZXRUYWdGaXhlZDsKICBob29rcy5wcm90b3R5cGVGb3JUYWcgPSBwcm90b3R5cGVGb3JUYWdG
+aXhlZDsKfQpDLmRrPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIHVzZXJBZ2VudCA9IHR5cGVvZiBuYXZp
 Z2F0b3IgPT0gIm9iamVjdCIgPyBuYXZpZ2F0b3IudXNlckFnZW50IDogIiI7CiAgaWYgKHVzZXJBZ2Vu
-dC5pbmRleE9mKCJUcmlkZW50LyIpID09IC0xKSByZXR1cm4gaG9va3M7CiAgdmFyIGdldFRhZyA9IGhv
-b2tzLmdldFRhZzsKICB2YXIgcXVpY2tNYXAgPSB7CiAgICAiQmVmb3JlVW5sb2FkRXZlbnQiOiAiRXZl
-bnQiLAogICAgIkRhdGFUcmFuc2ZlciI6ICJDbGlwYm9hcmQiLAogICAgIkhUTUxEREVsZW1lbnQiOiAi
-SFRNTEVsZW1lbnQiLAogICAgIkhUTUxEVEVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIkhUTUxQ
-aHJhc2VFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJQb3NpdGlvbiI6ICJHZW9wb3NpdGlvbiIK
-ICB9OwogIGZ1bmN0aW9uIGdldFRhZ0lFKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWcobyk7CiAgICB2
-YXIgbmV3VGFnID0gcXVpY2tNYXBbdGFnXTsKICAgIGlmIChuZXdUYWcpIHJldHVybiBuZXdUYWc7CiAg
-ICBpZiAodGFnID09ICJPYmplY3QiKSB7CiAgICAgIGlmICh3aW5kb3cuRGF0YVZpZXcgJiYgKG8gaW5z
-dGFuY2VvZiB3aW5kb3cuRGF0YVZpZXcpKSByZXR1cm4gIkRhdGFWaWV3IjsKICAgIH0KICAgIHJldHVy
-biB0YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZ0lFKHRhZykgewogICAgdmFyIGNvbnN0
-cnVjdG9yID0gd2luZG93W3RhZ107CiAgICBpZiAoY29uc3RydWN0b3IgPT0gbnVsbCkgcmV0dXJuIG51
-bGw7CiAgICByZXR1cm4gY29uc3RydWN0b3IucHJvdG90eXBlOwogIH0KICBob29rcy5nZXRUYWcgPSBn
-ZXRUYWdJRTsKICBob29rcy5wcm90b3R5cGVGb3JUYWcgPSBwcm90b3R5cGVGb3JUYWdJRTsKfQpDLmk3
-PWZ1bmN0aW9uKGhvb2tzKSB7IHJldHVybiBob29rczsgfQoKQy5DdD1uZXcgUC5ieSgpCkMuRXE9bmV3
-IFAuazUoKQpDLnhNPW5ldyBQLnU1KCkKQy5Raz1uZXcgUC5FMygpCkMuTnY9bmV3IEgua3IoKQpDLk5V
-PW5ldyBQLkppKCkKQy5wZD1uZXcgUC5aZCgpCkMuQWQ9bmV3IE0uSDcoMCwiSGludEFjdGlvbktpbmQu
-YWRkTnVsbGFibGVIaW50IikKQy5uZT1uZXcgTS5INygxLCJIaW50QWN0aW9uS2luZC5hZGROb25OdWxs
-YWJsZUhpbnQiKQpDLm15PW5ldyBNLkg3KDIsIkhpbnRBY3Rpb25LaW5kLmNoYW5nZVRvTnVsbGFibGVI
-aW50IikKQy5yeD1uZXcgTS5INygzLCJIaW50QWN0aW9uS2luZC5jaGFuZ2VUb05vbk51bGxhYmxlSGlu
-dCIpCkMud1Y9bmV3IE0uSDcoNCwiSGludEFjdGlvbktpbmQucmVtb3ZlTnVsbGFibGVIaW50IikKQy5m
-Uj1uZXcgTS5INyg1LCJIaW50QWN0aW9uS2luZC5yZW1vdmVOb25OdWxsYWJsZUhpbnQiKQpDLkEzPW5l
-dyBQLk14KG51bGwpCkMublg9bmV3IFAub2oobnVsbCkKQy5haz1ILlZNKHMoWzAsMCwzMjc3NiwzMzc5
-MiwxLDEwMjQwLDAsMF0pLHQuVikKQy5jbT1ILlZNKHMoWyIqOjpjbGFzcyIsIio6OmRpciIsIio6OmRy
-YWdnYWJsZSIsIio6OmhpZGRlbiIsIio6OmlkIiwiKjo6aW5lcnQiLCIqOjppdGVtcHJvcCIsIio6Oml0
-ZW1yZWYiLCIqOjppdGVtc2NvcGUiLCIqOjpsYW5nIiwiKjo6c3BlbGxjaGVjayIsIio6OnRpdGxlIiwi
-Kjo6dHJhbnNsYXRlIiwiQTo6YWNjZXNza2V5IiwiQTo6Y29vcmRzIiwiQTo6aHJlZmxhbmciLCJBOjpu
-YW1lIiwiQTo6c2hhcGUiLCJBOjp0YWJpbmRleCIsIkE6OnRhcmdldCIsIkE6OnR5cGUiLCJBUkVBOjph
-Y2Nlc3NrZXkiLCJBUkVBOjphbHQiLCJBUkVBOjpjb29yZHMiLCJBUkVBOjpub2hyZWYiLCJBUkVBOjpz
-aGFwZSIsIkFSRUE6OnRhYmluZGV4IiwiQVJFQTo6dGFyZ2V0IiwiQVVESU86OmNvbnRyb2xzIiwiQVVE
-SU86Omxvb3AiLCJBVURJTzo6bWVkaWFncm91cCIsIkFVRElPOjptdXRlZCIsIkFVRElPOjpwcmVsb2Fk
-IiwiQkRPOjpkaXIiLCJCT0RZOjphbGluayIsIkJPRFk6OmJnY29sb3IiLCJCT0RZOjpsaW5rIiwiQk9E
-WTo6dGV4dCIsIkJPRFk6OnZsaW5rIiwiQlI6OmNsZWFyIiwiQlVUVE9OOjphY2Nlc3NrZXkiLCJCVVRU
-T046OmRpc2FibGVkIiwiQlVUVE9OOjpuYW1lIiwiQlVUVE9OOjp0YWJpbmRleCIsIkJVVFRPTjo6dHlw
-ZSIsIkJVVFRPTjo6dmFsdWUiLCJDQU5WQVM6OmhlaWdodCIsIkNBTlZBUzo6d2lkdGgiLCJDQVBUSU9O
-OjphbGlnbiIsIkNPTDo6YWxpZ24iLCJDT0w6OmNoYXIiLCJDT0w6OmNoYXJvZmYiLCJDT0w6OnNwYW4i
-LCJDT0w6OnZhbGlnbiIsIkNPTDo6d2lkdGgiLCJDT0xHUk9VUDo6YWxpZ24iLCJDT0xHUk9VUDo6Y2hh
-ciIsIkNPTEdST1VQOjpjaGFyb2ZmIiwiQ09MR1JPVVA6OnNwYW4iLCJDT0xHUk9VUDo6dmFsaWduIiwi
-Q09MR1JPVVA6OndpZHRoIiwiQ09NTUFORDo6Y2hlY2tlZCIsIkNPTU1BTkQ6OmNvbW1hbmQiLCJDT01N
-QU5EOjpkaXNhYmxlZCIsIkNPTU1BTkQ6OmxhYmVsIiwiQ09NTUFORDo6cmFkaW9ncm91cCIsIkNPTU1B
-TkQ6OnR5cGUiLCJEQVRBOjp2YWx1ZSIsIkRFTDo6ZGF0ZXRpbWUiLCJERVRBSUxTOjpvcGVuIiwiRElS
-Ojpjb21wYWN0IiwiRElWOjphbGlnbiIsIkRMOjpjb21wYWN0IiwiRklFTERTRVQ6OmRpc2FibGVkIiwi
-Rk9OVDo6Y29sb3IiLCJGT05UOjpmYWNlIiwiRk9OVDo6c2l6ZSIsIkZPUk06OmFjY2VwdCIsIkZPUk06
-OmF1dG9jb21wbGV0ZSIsIkZPUk06OmVuY3R5cGUiLCJGT1JNOjptZXRob2QiLCJGT1JNOjpuYW1lIiwi
-Rk9STTo6bm92YWxpZGF0ZSIsIkZPUk06OnRhcmdldCIsIkZSQU1FOjpuYW1lIiwiSDE6OmFsaWduIiwi
-SDI6OmFsaWduIiwiSDM6OmFsaWduIiwiSDQ6OmFsaWduIiwiSDU6OmFsaWduIiwiSDY6OmFsaWduIiwi
-SFI6OmFsaWduIiwiSFI6Om5vc2hhZGUiLCJIUjo6c2l6ZSIsIkhSOjp3aWR0aCIsIkhUTUw6OnZlcnNp
-b24iLCJJRlJBTUU6OmFsaWduIiwiSUZSQU1FOjpmcmFtZWJvcmRlciIsIklGUkFNRTo6aGVpZ2h0Iiwi
-SUZSQU1FOjptYXJnaW5oZWlnaHQiLCJJRlJBTUU6Om1hcmdpbndpZHRoIiwiSUZSQU1FOjp3aWR0aCIs
-IklNRzo6YWxpZ24iLCJJTUc6OmFsdCIsIklNRzo6Ym9yZGVyIiwiSU1HOjpoZWlnaHQiLCJJTUc6Omhz
-cGFjZSIsIklNRzo6aXNtYXAiLCJJTUc6Om5hbWUiLCJJTUc6OnVzZW1hcCIsIklNRzo6dnNwYWNlIiwi
-SU1HOjp3aWR0aCIsIklOUFVUOjphY2NlcHQiLCJJTlBVVDo6YWNjZXNza2V5IiwiSU5QVVQ6OmFsaWdu
-IiwiSU5QVVQ6OmFsdCIsIklOUFVUOjphdXRvY29tcGxldGUiLCJJTlBVVDo6YXV0b2ZvY3VzIiwiSU5Q
-VVQ6OmNoZWNrZWQiLCJJTlBVVDo6ZGlzYWJsZWQiLCJJTlBVVDo6aW5wdXRtb2RlIiwiSU5QVVQ6Omlz
-bWFwIiwiSU5QVVQ6Omxpc3QiLCJJTlBVVDo6bWF4IiwiSU5QVVQ6Om1heGxlbmd0aCIsIklOUFVUOjpt
-aW4iLCJJTlBVVDo6bXVsdGlwbGUiLCJJTlBVVDo6bmFtZSIsIklOUFVUOjpwbGFjZWhvbGRlciIsIklO
-UFVUOjpyZWFkb25seSIsIklOUFVUOjpyZXF1aXJlZCIsIklOUFVUOjpzaXplIiwiSU5QVVQ6OnN0ZXAi
-LCJJTlBVVDo6dGFiaW5kZXgiLCJJTlBVVDo6dHlwZSIsIklOUFVUOjp1c2VtYXAiLCJJTlBVVDo6dmFs
-dWUiLCJJTlM6OmRhdGV0aW1lIiwiS0VZR0VOOjpkaXNhYmxlZCIsIktFWUdFTjo6a2V5dHlwZSIsIktF
-WUdFTjo6bmFtZSIsIkxBQkVMOjphY2Nlc3NrZXkiLCJMQUJFTDo6Zm9yIiwiTEVHRU5EOjphY2Nlc3Nr
-ZXkiLCJMRUdFTkQ6OmFsaWduIiwiTEk6OnR5cGUiLCJMSTo6dmFsdWUiLCJMSU5LOjpzaXplcyIsIk1B
-UDo6bmFtZSIsIk1FTlU6OmNvbXBhY3QiLCJNRU5VOjpsYWJlbCIsIk1FTlU6OnR5cGUiLCJNRVRFUjo6
-aGlnaCIsIk1FVEVSOjpsb3ciLCJNRVRFUjo6bWF4IiwiTUVURVI6Om1pbiIsIk1FVEVSOjp2YWx1ZSIs
-Ik9CSkVDVDo6dHlwZW11c3RtYXRjaCIsIk9MOjpjb21wYWN0IiwiT0w6OnJldmVyc2VkIiwiT0w6OnN0
-YXJ0IiwiT0w6OnR5cGUiLCJPUFRHUk9VUDo6ZGlzYWJsZWQiLCJPUFRHUk9VUDo6bGFiZWwiLCJPUFRJ
-T046OmRpc2FibGVkIiwiT1BUSU9OOjpsYWJlbCIsIk9QVElPTjo6c2VsZWN0ZWQiLCJPUFRJT046OnZh
-bHVlIiwiT1VUUFVUOjpmb3IiLCJPVVRQVVQ6Om5hbWUiLCJQOjphbGlnbiIsIlBSRTo6d2lkdGgiLCJQ
-Uk9HUkVTUzo6bWF4IiwiUFJPR1JFU1M6Om1pbiIsIlBST0dSRVNTOjp2YWx1ZSIsIlNFTEVDVDo6YXV0
-b2NvbXBsZXRlIiwiU0VMRUNUOjpkaXNhYmxlZCIsIlNFTEVDVDo6bXVsdGlwbGUiLCJTRUxFQ1Q6Om5h
-bWUiLCJTRUxFQ1Q6OnJlcXVpcmVkIiwiU0VMRUNUOjpzaXplIiwiU0VMRUNUOjp0YWJpbmRleCIsIlNP
-VVJDRTo6dHlwZSIsIlRBQkxFOjphbGlnbiIsIlRBQkxFOjpiZ2NvbG9yIiwiVEFCTEU6OmJvcmRlciIs
-IlRBQkxFOjpjZWxscGFkZGluZyIsIlRBQkxFOjpjZWxsc3BhY2luZyIsIlRBQkxFOjpmcmFtZSIsIlRB
-QkxFOjpydWxlcyIsIlRBQkxFOjpzdW1tYXJ5IiwiVEFCTEU6OndpZHRoIiwiVEJPRFk6OmFsaWduIiwi
-VEJPRFk6OmNoYXIiLCJUQk9EWTo6Y2hhcm9mZiIsIlRCT0RZOjp2YWxpZ24iLCJURDo6YWJiciIsIlRE
-OjphbGlnbiIsIlREOjpheGlzIiwiVEQ6OmJnY29sb3IiLCJURDo6Y2hhciIsIlREOjpjaGFyb2ZmIiwi
-VEQ6OmNvbHNwYW4iLCJURDo6aGVhZGVycyIsIlREOjpoZWlnaHQiLCJURDo6bm93cmFwIiwiVEQ6OnJv
-d3NwYW4iLCJURDo6c2NvcGUiLCJURDo6dmFsaWduIiwiVEQ6OndpZHRoIiwiVEVYVEFSRUE6OmFjY2Vz
-c2tleSIsIlRFWFRBUkVBOjphdXRvY29tcGxldGUiLCJURVhUQVJFQTo6Y29scyIsIlRFWFRBUkVBOjpk
-aXNhYmxlZCIsIlRFWFRBUkVBOjppbnB1dG1vZGUiLCJURVhUQVJFQTo6bmFtZSIsIlRFWFRBUkVBOjpw
-bGFjZWhvbGRlciIsIlRFWFRBUkVBOjpyZWFkb25seSIsIlRFWFRBUkVBOjpyZXF1aXJlZCIsIlRFWFRB
-UkVBOjpyb3dzIiwiVEVYVEFSRUE6OnRhYmluZGV4IiwiVEVYVEFSRUE6OndyYXAiLCJURk9PVDo6YWxp
-Z24iLCJURk9PVDo6Y2hhciIsIlRGT09UOjpjaGFyb2ZmIiwiVEZPT1Q6OnZhbGlnbiIsIlRIOjphYmJy
-IiwiVEg6OmFsaWduIiwiVEg6OmF4aXMiLCJUSDo6Ymdjb2xvciIsIlRIOjpjaGFyIiwiVEg6OmNoYXJv
-ZmYiLCJUSDo6Y29sc3BhbiIsIlRIOjpoZWFkZXJzIiwiVEg6OmhlaWdodCIsIlRIOjpub3dyYXAiLCJU
-SDo6cm93c3BhbiIsIlRIOjpzY29wZSIsIlRIOjp2YWxpZ24iLCJUSDo6d2lkdGgiLCJUSEVBRDo6YWxp
-Z24iLCJUSEVBRDo6Y2hhciIsIlRIRUFEOjpjaGFyb2ZmIiwiVEhFQUQ6OnZhbGlnbiIsIlRSOjphbGln
-biIsIlRSOjpiZ2NvbG9yIiwiVFI6OmNoYXIiLCJUUjo6Y2hhcm9mZiIsIlRSOjp2YWxpZ24iLCJUUkFD
-Szo6ZGVmYXVsdCIsIlRSQUNLOjpraW5kIiwiVFJBQ0s6OmxhYmVsIiwiVFJBQ0s6OnNyY2xhbmciLCJV
-TDo6Y29tcGFjdCIsIlVMOjp0eXBlIiwiVklERU86OmNvbnRyb2xzIiwiVklERU86OmhlaWdodCIsIlZJ
-REVPOjpsb29wIiwiVklERU86Om1lZGlhZ3JvdXAiLCJWSURFTzo6bXV0ZWQiLCJWSURFTzo6cHJlbG9h
-ZCIsIlZJREVPOjp3aWR0aCJdKSx0LmkpCkMuVkM9SC5WTShzKFswLDAsNjU0OTAsNDUwNTUsNjU1MzUs
-MzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMubUs9SC5WTShzKFswLDAsMjY2MjQsMTAyMyw2NTUzNCwy
-MDQ3LDY1NTM0LDIwNDddKSx0LlYpCkMuU3E9SC5WTShzKFsiSEVBRCIsIkFSRUEiLCJCQVNFIiwiQkFT
-RUZPTlQiLCJCUiIsIkNPTCIsIkNPTEdST1VQIiwiRU1CRUQiLCJGUkFNRSIsIkZSQU1FU0VUIiwiSFIi
-LCJJTUFHRSIsIklNRyIsIklOUFVUIiwiSVNJTkRFWCIsIkxJTksiLCJNRVRBIiwiUEFSQU0iLCJTT1VS
-Q0UiLCJTVFlMRSIsIlRJVExFIiwiV0JSIl0pLHQuaSkKQy5oVT1ILlZNKHMoW10pLHQudikKQy5kbj1I
-LlZNKHMoW10pLEguTjAoImpkPExMKj4iKSkKQy54RD1ILlZNKHMoW10pLHQuaSkKQy50bz1ILlZNKHMo
-WzAsMCwzMjcyMiwxMjI4Nyw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0pLHQuVikKQy5yaz1ILlZNKHMo
-W0MuQWQsQy5uZSxDLm15LEMucngsQy53VixDLmZSXSksSC5OMCgiamQ8SDcqPiIpKQpDLkYzPUguVk0o
-cyhbMCwwLDI0NTc2LDEwMjMsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMuZWE9SC5WTShz
-KFswLDAsMzI3NTQsMTEyNjMsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMuWko9SC5WTShz
-KFswLDAsMzI3MjIsMTIyODcsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMuV2Q9SC5WTShz
-KFswLDAsNjU0OTAsMTIyODcsNjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx0LlYpCkMuUXg9SC5WTShz
-KFsiYmluZCIsImlmIiwicmVmIiwicmVwZWF0Iiwic3ludGF4Il0pLHQuaSkKQy5CST1ILlZNKHMoWyJB
-OjpocmVmIiwiQVJFQTo6aHJlZiIsIkJMT0NLUVVPVEU6OmNpdGUiLCJCT0RZOjpiYWNrZ3JvdW5kIiwi
-Q09NTUFORDo6aWNvbiIsIkRFTDo6Y2l0ZSIsIkZPUk06OmFjdGlvbiIsIklNRzo6c3JjIiwiSU5QVVQ6
-OnNyYyIsIklOUzo6Y2l0ZSIsIlE6OmNpdGUiLCJWSURFTzo6cG9zdGVyIl0pLHQuaSkKQy5EeD1uZXcg
-SC5MUCgwLHt9LEMueEQsSC5OMCgiTFA8cVUqLHpNPGo4Kj4qPiIpKQpDLkNNPW5ldyBILkxQKDAse30s
-Qy54RCxILk4wKCJMUDxxVSoscVUqPiIpKQpDLmlIPUguVk0ocyhbXSksSC5OMCgiamQ8R0QqPiIpKQpD
-LldPPW5ldyBILkxQKDAse30sQy5pSCxILk4wKCJMUDxHRCosQD4iKSkKQy5ZMj1uZXcgTC5POSgiTmF2
-aWdhdGlvblRyZWVOb2RlVHlwZS5kaXJlY3RvcnkiKQpDLnJmPW5ldyBMLk85KCJOYXZpZ2F0aW9uVHJl
-ZU5vZGVUeXBlLmZpbGUiKQpDLlRlPW5ldyBILnd2KCJjYWxsIikKQy5vRT1uZXcgUC5HWSghMSkKQy53
-UT1uZXcgUC5GeShudWxsLDIpfSkoKTsoZnVuY3Rpb24gc3RhdGljRmllbGRzKCl7JC56bT1udWxsCiQu
-eWo9MAokLm1KPW51bGwKJC5QND1udWxsCiQuTkY9bnVsbAokLlRYPW51bGwKJC54Nz1udWxsCiQubnc9
-bnVsbAokLnZ2PW51bGwKJC5Cdj1udWxsCiQuUzY9bnVsbAokLms4PW51bGwKJC5tZz1udWxsCiQuVUQ9
-ITEKJC5YMz1DLk5VCiQueGc9SC5WTShbXSxILk4wKCJqZDxNaD4iKSkKJC54bz1udWxsCiQuQk89bnVs
-bAokLmx0PW51bGwKJC5FVT1udWxsCiQub3I9UC5GbCh0Lk4sdC5ZKQokLkk2PW51bGwKJC5GZj1udWxs
-fSkoKTsoZnVuY3Rpb24gbGF6eUluaXRpYWxpemVycygpe3ZhciBzPWh1bmtIZWxwZXJzLmxhenkscj1o
-dW5rSGVscGVycy5sYXp5T2xkCnMoJCwiZmEiLCJ3IixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRh
-cnRfZGFydENsb3N1cmUiKX0pCnMoJCwiVTIiLCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3
-KHsKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKcygkLCJ4cSIsImxx
-IixmdW5jdGlvbigpe3JldHVybiBILmNNKEguUzcoeyRtZXRob2QkOm51bGwsCnRvU3RyaW5nOmZ1bmN0
-aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnMoJCwiUjEiLCJOOSIsZnVuY3Rpb24oKXtyZXR1
-cm4gSC5jTShILlM3KG51bGwpKX0pCnMoJCwiZk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShm
-dW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7bnVsbC4kbWV0aG9k
-JCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHEpe3JldHVybiBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwicWki
-LCJVTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHZvaWQgMCkpfSkKcygkLCJyWiIsIlpoIixm
-dW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3Vt
-ZW50cyQnCnRyeXsodm9pZCAwKS4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHEpe3JldHVy
-biBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwia3EiLCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1q
-KG51bGwpKX0pCnMoJCwidHQiLCJjMyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3Ry
-eXtudWxsLiRtZXRob2QkfWNhdGNoKHEpe3JldHVybiBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwiZHQiLCJI
-SyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKHZvaWQgMCkpfSkKcygkLCJBNyIsInIxIixmdW5j
-dGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9uKCl7dHJ5eyh2b2lkIDApLiRtZXRob2QkfWNhdGNoKHEp
-e3JldHVybiBxLm1lc3NhZ2V9fSgpKX0pCnMoJCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5P
-aigpfSkKcygkLCJraCIsInJmIixmdW5jdGlvbigpe3JldHVybiBuZXcgUC5wZygpLiQwKCl9KQpzKCQs
-ImFYIiwiSEciLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmMyKCkuJDAoKX0pCnMoJCwiYnQiLCJWNyIs
-ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEludDhBcnJheShILlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
-LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYy
-LC0yLDYzLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAs
-MSwyLDMsNCw1LDYsNyw4LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMs
-MjQsMjUsLTIsLTIsLTIsLTIsNjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcs
-MzgsMzksNDAsNDEsNDIsNDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHQu
-YSkpKX0pCnMoJCwiTTUiLCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRl
-ZmluZWQiJiZPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHBy
-b2Nlc3NdIiYmcHJvY2Vzcy5wbGF0Zm9ybT09IndpbjMyIn0pCnMoJCwibWYiLCJ6NCIsZnVuY3Rpb24o
-KXtyZXR1cm4gUC5udSgiXltcXC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKcygkLCJPUSIsInZaIixmdW5j
-dGlvbigpe3JldHVybiBQLktOKCl9KQpzKCQsIlNDIiwiQU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0o
-WyJBIiwiQUJCUiIsIkFDUk9OWU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFV
-RElPIiwiQiIsIkJESSIsIkJETyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZB
-UyIsIkNBUFRJT04iLCJDRU5URVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFO
-RCIsIkRBVEEiLCJEQVRBTElTVCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIs
-IkRMIiwiRFQiLCJFTSIsIkZJRUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09U
-RVIiLCJGT1JNIiwiSDEiLCJIMiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwi
-SFIiLCJJIiwiSUZSQU1FIiwiSU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIs
-IkxJIiwiTUFQIiwiTUFSSyIsIk1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQ
-IiwiT1BUSU9OIiwiT1VUUFVUIiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VD
-VElPTiIsIlNFTEVDVCIsIlNNQUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNV
-QiIsIlNVTU1BUlkiLCJTVVAiLCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwi
-VEgiLCJUSEVBRCIsIlRJTUUiLCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIs
-IldCUiJdLHQuTil9KQpzKCQsIlg0IiwiaEciLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIp
-fSkKcygkLCJ3TyIsIm93IixmdW5jdGlvbigpe3JldHVybiBQLk5EKHNlbGYpfSkKcygkLCJrdCIsIlI4
-IixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydE9iamVjdCIpfSkKcygkLCJmSyIsImtJ
-IixmdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbiBEYXJ0T2JqZWN0KGEpe3RoaXMubz1hfX0pCnIoJCwi
-cXQiLCJ6QiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFQubVEoKX0pCnIoJCwiT2wiLCJVRSIsZnVuY3Rp
-b24oKXtyZXR1cm4gUC5oSyhDLm9sLmdtVyhXLngzKCkpLmhyZWYpLmdoWSgpLnEoMCwiYXV0aFRva2Vu
-Iil9KQpyKCQsImhUIiwieVAiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIu
-ZWRpdC1saXN0IC5wYW5lbC1jb250ZW50Iil9KQpyKCQsIlc2IiwiaEwiLGZ1bmN0aW9uKCl7cmV0dXJu
-IFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKcigkLCJU
-UiIsIkRXIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9KQpy
-KCQsIkVZIiwiZmkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFkZXIi
-KX0pCnIoJCwiYXYiLCJEOSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1
-bml0LW5hbWUiKX0pCnIoJCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnMo
-JCwiZW8iLCJuVSIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnMoJCwieXIiLCJi
-RCIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgi
-Xi8iKSl9KQpzKCQsIk1rIiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxc
-XF0iKSxQLm51KCJbXi9cXFxcXSQiKSxQLm51KCJeKFxcXFxcXFxcW15cXFxcXStcXFxcW15cXFxcL10r
-fFthLXpBLVpdOlsvXFxcXF0pIiksUC5udSgiXlsvXFxcXF0oPyFbL1xcXFxdKSIpKX0pCnMoJCwiYWsi
-LCJFYiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEYucnUoUC5udSgiLyIpLFAubnUoIiheW2EtekEtWl1b
-LSsuYS16QS1aXFxkXSo6Ly98W14vXSkkIiksUC5udSgiW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly9b
-Xi9dKiIpLFAubnUoIl4vIikpfSkKcygkLCJscyIsIkhrIixmdW5jdGlvbigpe3JldHVybiBPLlJoKCl9
-KX0pKCk7KGZ1bmN0aW9uIG5hdGl2ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2YXIgcz1mdW5jdGlvbihh
-KXt2YXIgbT17fQptW2FdPTEKcmV0dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxwZXJzLmNvbnZlcnRUb0Zh
-c3RPYmplY3QobSkpWzBdfQp2LmdldElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7cmV0dXJuIHMoIl9fX2Rh
-cnRfIithK3YuaXNvbGF0ZVRhZyl9CnZhciByPSJfX19kYXJ0X2lzb2xhdGVfdGFnc18iCnZhciBxPU9i
-amVjdFtyXXx8KE9iamVjdFtyXT1PYmplY3QuY3JlYXRlKG51bGwpKQp2YXIgcD0iX1p4WXhYIgpmb3Io
-dmFyIG89MDs7bysrKXt2YXIgbj1zKHArIl8iK28rIl8iKQppZighKG4gaW4gcSkpe3Fbbl09MQp2Lmlz
-b2xhdGVUYWc9bgpicmVha319di5kaXNwYXRjaFByb3BlcnR5TmFtZT12LmdldElzb2xhdGVUYWcoImRp
-c3BhdGNoX3JlY29yZCIpfSgpCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWco
-e0RPTUVycm9yOkoudkIsTWVkaWFFcnJvcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRvckNvbmN1
-cnJlbnRIYXJkd2FyZTpKLnZCLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsT3ZlcmNvbnN0cmFp
-bmVkRXJyb3I6Si52QixQb3NpdGlvbkVycm9yOkoudkIsUmFuZ2U6Si52QixTUUxFcnJvcjpKLnZCLERh
-dGFWaWV3OkguRVQsQXJyYXlCdWZmZXJWaWV3OkguRVQsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFy
-cmF5OkguRGcsSW50MTZBcnJheTpILnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50
-MTZBcnJheTpILmRULFVpbnQzMkFycmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQ
-aXhlbEFycmF5OkguZUUsVWludDhBcnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJF
-bGVtZW50OlcucUUsSFRNTEJ1dHRvbkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhU
-TUxDb250ZW50RWxlbWVudDpXLnFFLEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6
-Vy5xRSxIVE1MRGF0YUxpc3RFbGVtZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERp
-YWxvZ0VsZW1lbnQ6Vy5xRSxIVE1MRGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxI
-VE1MRmllbGRTZXRFbGVtZW50OlcucUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpX
-LnFFLEhUTUxIZWFkaW5nRWxlbWVudDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVF
-bGVtZW50OlcucUUsSFRNTEltYWdlRWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1M
-TElFbGVtZW50OlcucUUsSFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUs
-SFRNTExpbmtFbGVtZW50OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50Olcu
-cUUsSFRNTE1lbnVFbGVtZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVu
-dDpXLnFFLEhUTUxNb2RFbGVtZW50OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RF
-bGVtZW50OlcucUUsSFRNTE9wdEdyb3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUs
-SFRNTE91dHB1dEVsZW1lbnQ6Vy5xRSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVt
-ZW50OlcucUUsSFRNTFByZUVsZW1lbnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1
-b3RlRWxlbWVudDpXLnFFLEhUTUxTY3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5x
-RSxIVE1MU2xvdEVsZW1lbnQ6Vy5xRSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVu
-dDpXLnFFLEhUTUxTdHlsZUVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhU
-TUxUYWJsZUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRh
-YmxlSGVhZGVyQ2VsbEVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRB
-cmVhRWxlbWVudDpXLnFFLEhUTUxUaW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxI
-VE1MVHJhY2tFbGVtZW50OlcucUUsSFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVu
-dDpXLnFFLEhUTUxWaWRlb0VsZW1lbnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxG
-b250RWxlbWVudDpXLnFFLEhUTUxGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50Olcu
-cUUsSFRNTE1hcnF1ZWVFbGVtZW50OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVu
-dDpXLkdoLEhUTUxBcmVhRWxlbWVudDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixI
-VE1MQm9keUVsZW1lbnQ6Vy5RUCxDREFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29t
-bWVudDpXLm54LFByb2Nlc3NpbmdJbnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xh
-cmF0aW9uOlcub0osTVNTdHlsZUNTU1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhN
-TERvY3VtZW50OlcuUUYsRG9jdW1lbnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01JbXBsZW1lbnRh
-dGlvbjpXLmFlLERPTVJlY3RSZWFkT25seTpXLklCLERPTVRva2VuTGlzdDpXLm43LEVsZW1lbnQ6Vy5j
-dixBYm9ydFBheW1lbnRFdmVudDpXLmVhLEFuaW1hdGlvbkV2ZW50OlcuZWEsQW5pbWF0aW9uUGxheWJh
-Y2tFdmVudDpXLmVhLEFwcGxpY2F0aW9uQ2FjaGVFcnJvckV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNo
-Q2xpY2tFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoRmFp
-bEV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoZWRFdmVudDpXLmVhLEJlZm9yZUluc3RhbGxQcm9tcHRF
-dmVudDpXLmVhLEJlZm9yZVVubG9hZEV2ZW50OlcuZWEsQmxvYkV2ZW50OlcuZWEsQ2FuTWFrZVBheW1l
-bnRFdmVudDpXLmVhLENsaXBib2FyZEV2ZW50OlcuZWEsQ2xvc2VFdmVudDpXLmVhLEN1c3RvbUV2ZW50
-OlcuZWEsRGV2aWNlTW90aW9uRXZlbnQ6Vy5lYSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OlcuZWEsRXJy
-b3JFdmVudDpXLmVhLEV4dGVuZGFibGVFdmVudDpXLmVhLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6Vy5l
-YSxGZXRjaEV2ZW50OlcuZWEsRm9udEZhY2VTZXRMb2FkRXZlbnQ6Vy5lYSxGb3JlaWduRmV0Y2hFdmVu
-dDpXLmVhLEdhbWVwYWRFdmVudDpXLmVhLEhhc2hDaGFuZ2VFdmVudDpXLmVhLEluc3RhbGxFdmVudDpX
-LmVhLE1lZGlhRW5jcnlwdGVkRXZlbnQ6Vy5lYSxNZWRpYUtleU1lc3NhZ2VFdmVudDpXLmVhLE1lZGlh
-UXVlcnlMaXN0RXZlbnQ6Vy5lYSxNZWRpYVN0cmVhbUV2ZW50OlcuZWEsTWVkaWFTdHJlYW1UcmFja0V2
-ZW50OlcuZWEsTWVzc2FnZUV2ZW50OlcuZWEsTUlESUNvbm5lY3Rpb25FdmVudDpXLmVhLE1JRElNZXNz
-YWdlRXZlbnQ6Vy5lYSxNdXRhdGlvbkV2ZW50OlcuZWEsTm90aWZpY2F0aW9uRXZlbnQ6Vy5lYSxQYWdl
-VHJhbnNpdGlvbkV2ZW50OlcuZWEsUGF5bWVudFJlcXVlc3RFdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0
-VXBkYXRlRXZlbnQ6Vy5lYSxQb3BTdGF0ZUV2ZW50OlcuZWEsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2
-YWlsYWJsZUV2ZW50OlcuZWEsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6Vy5lYSxQcm9t
-aXNlUmVqZWN0aW9uRXZlbnQ6Vy5lYSxQdXNoRXZlbnQ6Vy5lYSxSVENEYXRhQ2hhbm5lbEV2ZW50Olcu
-ZWEsUlRDRFRNRlRvbmVDaGFuZ2VFdmVudDpXLmVhLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6Vy5l
-YSxSVENUcmFja0V2ZW50OlcuZWEsU2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDpXLmVhLFNlbnNv
-ckVycm9yRXZlbnQ6Vy5lYSxTcGVlY2hSZWNvZ25pdGlvbkVycm9yOlcuZWEsU3BlZWNoUmVjb2duaXRp
-b25FdmVudDpXLmVhLFNwZWVjaFN5bnRoZXNpc0V2ZW50OlcuZWEsU3RvcmFnZUV2ZW50OlcuZWEsU3lu
-Y0V2ZW50OlcuZWEsVHJhY2tFdmVudDpXLmVhLFRyYW5zaXRpb25FdmVudDpXLmVhLFdlYktpdFRyYW5z
-aXRpb25FdmVudDpXLmVhLFZSRGV2aWNlRXZlbnQ6Vy5lYSxWUkRpc3BsYXlFdmVudDpXLmVhLFZSU2Vz
-c2lvbkV2ZW50OlcuZWEsTW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDpXLmVhLFVTQkNvbm5lY3Rpb25F
-dmVudDpXLmVhLElEQlZlcnNpb25DaGFuZ2VFdmVudDpXLmVhLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50Olcu
-ZWEsT2ZmbGluZUF1ZGlvQ29tcGxldGlvbkV2ZW50OlcuZWEsV2ViR0xDb250ZXh0RXZlbnQ6Vy5lYSxF
-dmVudDpXLmVhLElucHV0RXZlbnQ6Vy5lYSxTdWJtaXRFdmVudDpXLmVhLEV2ZW50VGFyZ2V0OlcuRDAs
-RmlsZTpXLmhILEhUTUxGb3JtRWxlbWVudDpXLmg0LEhpc3Rvcnk6Vy5icixIVE1MRG9jdW1lbnQ6Vy5W
-YixYTUxIdHRwUmVxdWVzdDpXLmZKLFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6Vy53YSxJbWFnZURh
-dGE6Vy5TZyxMb2NhdGlvbjpXLnU4LE1vdXNlRXZlbnQ6Vy5BaixEcmFnRXZlbnQ6Vy5BaixQb2ludGVy
-RXZlbnQ6Vy5BaixXaGVlbEV2ZW50OlcuQWosRG9jdW1lbnRGcmFnbWVudDpXLnVILFNoYWRvd1Jvb3Q6
-Vy51SCxEb2N1bWVudFR5cGU6Vy51SCxOb2RlOlcudUgsTm9kZUxpc3Q6Vy5CSCxSYWRpb05vZGVMaXN0
-OlcuQkgsSFRNTFBhcmFncmFwaEVsZW1lbnQ6Vy5TTixQcm9ncmVzc0V2ZW50OlcuZXcsUmVzb3VyY2VQ
-cm9ncmVzc0V2ZW50OlcuZXcsSFRNTFNlbGVjdEVsZW1lbnQ6Vy5scCxIVE1MVGFibGVFbGVtZW50Olcu
-VGIsSFRNTFRhYmxlUm93RWxlbWVudDpXLkl2LEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OlcuV1AsSFRN
-TFRlbXBsYXRlRWxlbWVudDpXLnlZLENvbXBvc2l0aW9uRXZlbnQ6Vy53NixGb2N1c0V2ZW50OlcudzYs
-S2V5Ym9hcmRFdmVudDpXLnc2LFRleHRFdmVudDpXLnc2LFRvdWNoRXZlbnQ6Vy53NixVSUV2ZW50Olcu
-dzYsV2luZG93OlcuSzUsRE9NV2luZG93OlcuSzUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6Vy5D
-bSxTZXJ2aWNlV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNt
-LFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sQXR0cjpXLkNRLENsaWVudFJlY3Q6Vy53NCxET01SZWN0Olcu
-dzQsTmFtZWROb2RlTWFwOlcucmgsTW96TmFtZWRBdHRyTWFwOlcucmgsSURCS2V5UmFuZ2U6UC5oRixT
-VkdTY3JpcHRFbGVtZW50OlAuYkIsU1ZHQUVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlRWxlbWVudDpQLmQ1
-LFNWR0FuaW1hdGVNb3Rpb25FbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6UC5k
-NSxTVkdBbmltYXRpb25FbGVtZW50OlAuZDUsU1ZHQ2lyY2xlRWxlbWVudDpQLmQ1LFNWR0NsaXBQYXRo
-RWxlbWVudDpQLmQ1LFNWR0RlZnNFbGVtZW50OlAuZDUsU1ZHRGVzY0VsZW1lbnQ6UC5kNSxTVkdEaXNj
-YXJkRWxlbWVudDpQLmQ1LFNWR0VsbGlwc2VFbGVtZW50OlAuZDUsU1ZHRkVCbGVuZEVsZW1lbnQ6UC5k
-NSxTVkdGRUNvbG9yTWF0cml4RWxlbWVudDpQLmQ1LFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50
-OlAuZDUsU1ZHRkVDb21wb3NpdGVFbGVtZW50OlAuZDUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6
-UC5kNSxTVkdGRURpZmZ1c2VMaWdodGluZ0VsZW1lbnQ6UC5kNSxTVkdGRURpc3BsYWNlbWVudE1hcEVs
-ZW1lbnQ6UC5kNSxTVkdGRURpc3RhbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRUZsb29kRWxlbWVudDpQ
-LmQ1LFNWR0ZFRnVuY0FFbGVtZW50OlAuZDUsU1ZHRkVGdW5jQkVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNH
-RWxlbWVudDpQLmQ1LFNWR0ZFRnVuY1JFbGVtZW50OlAuZDUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50
-OlAuZDUsU1ZHRkVJbWFnZUVsZW1lbnQ6UC5kNSxTVkdGRU1lcmdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVy
-Z2VOb2RlRWxlbWVudDpQLmQ1LFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6UC5kNSxTVkdGRU9mZnNldEVs
-ZW1lbnQ6UC5kNSxTVkdGRVBvaW50TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5n
-RWxlbWVudDpQLmQ1LFNWR0ZFU3BvdExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFVGlsZUVsZW1lbnQ6UC5k
-NSxTVkdGRVR1cmJ1bGVuY2VFbGVtZW50OlAuZDUsU1ZHRmlsdGVyRWxlbWVudDpQLmQ1LFNWR0ZvcmVp
-Z25PYmplY3RFbGVtZW50OlAuZDUsU1ZHR0VsZW1lbnQ6UC5kNSxTVkdHZW9tZXRyeUVsZW1lbnQ6UC5k
-NSxTVkdHcmFwaGljc0VsZW1lbnQ6UC5kNSxTVkdJbWFnZUVsZW1lbnQ6UC5kNSxTVkdMaW5lRWxlbWVu
-dDpQLmQ1LFNWR0xpbmVhckdyYWRpZW50RWxlbWVudDpQLmQ1LFNWR01hcmtlckVsZW1lbnQ6UC5kNSxT
-VkdNYXNrRWxlbWVudDpQLmQ1LFNWR01ldGFkYXRhRWxlbWVudDpQLmQ1LFNWR1BhdGhFbGVtZW50OlAu
-ZDUsU1ZHUGF0dGVybkVsZW1lbnQ6UC5kNSxTVkdQb2x5Z29uRWxlbWVudDpQLmQ1LFNWR1BvbHlsaW5l
-RWxlbWVudDpQLmQ1LFNWR1JhZGlhbEdyYWRpZW50RWxlbWVudDpQLmQ1LFNWR1JlY3RFbGVtZW50OlAu
-ZDUsU1ZHU2V0RWxlbWVudDpQLmQ1LFNWR1N0b3BFbGVtZW50OlAuZDUsU1ZHU3R5bGVFbGVtZW50OlAu
-ZDUsU1ZHU1ZHRWxlbWVudDpQLmQ1LFNWR1N3aXRjaEVsZW1lbnQ6UC5kNSxTVkdTeW1ib2xFbGVtZW50
-OlAuZDUsU1ZHVFNwYW5FbGVtZW50OlAuZDUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OlAuZDUsU1ZHVGV4
-dEVsZW1lbnQ6UC5kNSxTVkdUZXh0UGF0aEVsZW1lbnQ6UC5kNSxTVkdUZXh0UG9zaXRpb25pbmdFbGVt
-ZW50OlAuZDUsU1ZHVGl0bGVFbGVtZW50OlAuZDUsU1ZHVXNlRWxlbWVudDpQLmQ1LFNWR1ZpZXdFbGVt
-ZW50OlAuZDUsU1ZHR3JhZGllbnRFbGVtZW50OlAuZDUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlv
-bkVsZW1lbnQ6UC5kNSxTVkdGRURyb3BTaGFkb3dFbGVtZW50OlAuZDUsU1ZHTVBhdGhFbGVtZW50OlAu
-ZDUsU1ZHRWxlbWVudDpQLmQ1fSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFmVGFncyh7RE9NRXJy
-b3I6dHJ1ZSxNZWRpYUVycm9yOnRydWUsTmF2aWdhdG9yOnRydWUsTmF2aWdhdG9yQ29uY3VycmVudEhh
-cmR3YXJlOnRydWUsTmF2aWdhdG9yVXNlck1lZGlhRXJyb3I6dHJ1ZSxPdmVyY29uc3RyYWluZWRFcnJv
-cjp0cnVlLFBvc2l0aW9uRXJyb3I6dHJ1ZSxSYW5nZTp0cnVlLFNRTEVycm9yOnRydWUsRGF0YVZpZXc6
-dHJ1ZSxBcnJheUJ1ZmZlclZpZXc6ZmFsc2UsRmxvYXQzMkFycmF5OnRydWUsRmxvYXQ2NEFycmF5OnRy
-dWUsSW50MTZBcnJheTp0cnVlLEludDMyQXJyYXk6dHJ1ZSxJbnQ4QXJyYXk6dHJ1ZSxVaW50MTZBcnJh
-eTp0cnVlLFVpbnQzMkFycmF5OnRydWUsVWludDhDbGFtcGVkQXJyYXk6dHJ1ZSxDYW52YXNQaXhlbEFy
-cmF5OnRydWUsVWludDhBcnJheTpmYWxzZSxIVE1MQXVkaW9FbGVtZW50OnRydWUsSFRNTEJSRWxlbWVu
-dDp0cnVlLEhUTUxCdXR0b25FbGVtZW50OnRydWUsSFRNTENhbnZhc0VsZW1lbnQ6dHJ1ZSxIVE1MQ29u
-dGVudEVsZW1lbnQ6dHJ1ZSxIVE1MRExpc3RFbGVtZW50OnRydWUsSFRNTERhdGFFbGVtZW50OnRydWUs
-SFRNTERhdGFMaXN0RWxlbWVudDp0cnVlLEhUTUxEZXRhaWxzRWxlbWVudDp0cnVlLEhUTUxEaWFsb2dF
-bGVtZW50OnRydWUsSFRNTERpdkVsZW1lbnQ6dHJ1ZSxIVE1MRW1iZWRFbGVtZW50OnRydWUsSFRNTEZp
-ZWxkU2V0RWxlbWVudDp0cnVlLEhUTUxIUkVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZEVsZW1lbnQ6dHJ1ZSxI
-VE1MSGVhZGluZ0VsZW1lbnQ6dHJ1ZSxIVE1MSHRtbEVsZW1lbnQ6dHJ1ZSxIVE1MSUZyYW1lRWxlbWVu
-dDp0cnVlLEhUTUxJbWFnZUVsZW1lbnQ6dHJ1ZSxIVE1MSW5wdXRFbGVtZW50OnRydWUsSFRNTExJRWxl
-bWVudDp0cnVlLEhUTUxMYWJlbEVsZW1lbnQ6dHJ1ZSxIVE1MTGVnZW5kRWxlbWVudDp0cnVlLEhUTUxM
-aW5rRWxlbWVudDp0cnVlLEhUTUxNYXBFbGVtZW50OnRydWUsSFRNTE1lZGlhRWxlbWVudDp0cnVlLEhU
-TUxNZW51RWxlbWVudDp0cnVlLEhUTUxNZXRhRWxlbWVudDp0cnVlLEhUTUxNZXRlckVsZW1lbnQ6dHJ1
-ZSxIVE1MTW9kRWxlbWVudDp0cnVlLEhUTUxPTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MT2JqZWN0RWxlbWVu
-dDp0cnVlLEhUTUxPcHRHcm91cEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0aW9uRWxlbWVudDp0cnVlLEhUTUxP
-dXRwdXRFbGVtZW50OnRydWUsSFRNTFBhcmFtRWxlbWVudDp0cnVlLEhUTUxQaWN0dXJlRWxlbWVudDp0
-cnVlLEhUTUxQcmVFbGVtZW50OnRydWUsSFRNTFByb2dyZXNzRWxlbWVudDp0cnVlLEhUTUxRdW90ZUVs
-ZW1lbnQ6dHJ1ZSxIVE1MU2NyaXB0RWxlbWVudDp0cnVlLEhUTUxTaGFkb3dFbGVtZW50OnRydWUsSFRN
-TFNsb3RFbGVtZW50OnRydWUsSFRNTFNvdXJjZUVsZW1lbnQ6dHJ1ZSxIVE1MU3BhbkVsZW1lbnQ6dHJ1
-ZSxIVE1MU3R5bGVFbGVtZW50OnRydWUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MVGFi
-bGVDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZURhdGFDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUhl
-YWRlckNlbGxFbGVtZW50OnRydWUsSFRNTFRhYmxlQ29sRWxlbWVudDp0cnVlLEhUTUxUZXh0QXJlYUVs
-ZW1lbnQ6dHJ1ZSxIVE1MVGltZUVsZW1lbnQ6dHJ1ZSxIVE1MVGl0bGVFbGVtZW50OnRydWUsSFRNTFRy
-YWNrRWxlbWVudDp0cnVlLEhUTUxVTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MVW5rbm93bkVsZW1lbnQ6dHJ1
-ZSxIVE1MVmlkZW9FbGVtZW50OnRydWUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6dHJ1ZSxIVE1MRm9udEVs
-ZW1lbnQ6dHJ1ZSxIVE1MRnJhbWVFbGVtZW50OnRydWUsSFRNTEZyYW1lU2V0RWxlbWVudDp0cnVlLEhU
-TUxNYXJxdWVlRWxlbWVudDp0cnVlLEhUTUxFbGVtZW50OmZhbHNlLEhUTUxBbmNob3JFbGVtZW50OnRy
-dWUsSFRNTEFyZWFFbGVtZW50OnRydWUsSFRNTEJhc2VFbGVtZW50OnRydWUsQmxvYjpmYWxzZSxIVE1M
-Qm9keUVsZW1lbnQ6dHJ1ZSxDREFUQVNlY3Rpb246dHJ1ZSxDaGFyYWN0ZXJEYXRhOnRydWUsQ29tbWVu
-dDp0cnVlLFByb2Nlc3NpbmdJbnN0cnVjdGlvbjp0cnVlLFRleHQ6dHJ1ZSxDU1NTdHlsZURlY2xhcmF0
-aW9uOnRydWUsTVNTdHlsZUNTU1Byb3BlcnRpZXM6dHJ1ZSxDU1MyUHJvcGVydGllczp0cnVlLFhNTERv
-Y3VtZW50OnRydWUsRG9jdW1lbnQ6ZmFsc2UsRE9NRXhjZXB0aW9uOnRydWUsRE9NSW1wbGVtZW50YXRp
-b246dHJ1ZSxET01SZWN0UmVhZE9ubHk6ZmFsc2UsRE9NVG9rZW5MaXN0OnRydWUsRWxlbWVudDpmYWxz
-ZSxBYm9ydFBheW1lbnRFdmVudDp0cnVlLEFuaW1hdGlvbkV2ZW50OnRydWUsQW5pbWF0aW9uUGxheWJh
-Y2tFdmVudDp0cnVlLEFwcGxpY2F0aW9uQ2FjaGVFcnJvckV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNo
-Q2xpY2tFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaEV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRmFp
-bEV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoZWRFdmVudDp0cnVlLEJlZm9yZUluc3RhbGxQcm9tcHRF
-dmVudDp0cnVlLEJlZm9yZVVubG9hZEV2ZW50OnRydWUsQmxvYkV2ZW50OnRydWUsQ2FuTWFrZVBheW1l
-bnRFdmVudDp0cnVlLENsaXBib2FyZEV2ZW50OnRydWUsQ2xvc2VFdmVudDp0cnVlLEN1c3RvbUV2ZW50
-OnRydWUsRGV2aWNlTW90aW9uRXZlbnQ6dHJ1ZSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OnRydWUsRXJy
-b3JFdmVudDp0cnVlLEV4dGVuZGFibGVFdmVudDp0cnVlLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6dHJ1
-ZSxGZXRjaEV2ZW50OnRydWUsRm9udEZhY2VTZXRMb2FkRXZlbnQ6dHJ1ZSxGb3JlaWduRmV0Y2hFdmVu
-dDp0cnVlLEdhbWVwYWRFdmVudDp0cnVlLEhhc2hDaGFuZ2VFdmVudDp0cnVlLEluc3RhbGxFdmVudDp0
-cnVlLE1lZGlhRW5jcnlwdGVkRXZlbnQ6dHJ1ZSxNZWRpYUtleU1lc3NhZ2VFdmVudDp0cnVlLE1lZGlh
-UXVlcnlMaXN0RXZlbnQ6dHJ1ZSxNZWRpYVN0cmVhbUV2ZW50OnRydWUsTWVkaWFTdHJlYW1UcmFja0V2
-ZW50OnRydWUsTWVzc2FnZUV2ZW50OnRydWUsTUlESUNvbm5lY3Rpb25FdmVudDp0cnVlLE1JRElNZXNz
-YWdlRXZlbnQ6dHJ1ZSxNdXRhdGlvbkV2ZW50OnRydWUsTm90aWZpY2F0aW9uRXZlbnQ6dHJ1ZSxQYWdl
-VHJhbnNpdGlvbkV2ZW50OnRydWUsUGF5bWVudFJlcXVlc3RFdmVudDp0cnVlLFBheW1lbnRSZXF1ZXN0
-VXBkYXRlRXZlbnQ6dHJ1ZSxQb3BTdGF0ZUV2ZW50OnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2
-YWlsYWJsZUV2ZW50OnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6dHJ1ZSxQcm9t
-aXNlUmVqZWN0aW9uRXZlbnQ6dHJ1ZSxQdXNoRXZlbnQ6dHJ1ZSxSVENEYXRhQ2hhbm5lbEV2ZW50OnRy
-dWUsUlRDRFRNRlRvbmVDaGFuZ2VFdmVudDp0cnVlLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6dHJ1
-ZSxSVENUcmFja0V2ZW50OnRydWUsU2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDp0cnVlLFNlbnNv
-ckVycm9yRXZlbnQ6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkVycm9yOnRydWUsU3BlZWNoUmVjb2duaXRp
-b25FdmVudDp0cnVlLFNwZWVjaFN5bnRoZXNpc0V2ZW50OnRydWUsU3RvcmFnZUV2ZW50OnRydWUsU3lu
-Y0V2ZW50OnRydWUsVHJhY2tFdmVudDp0cnVlLFRyYW5zaXRpb25FdmVudDp0cnVlLFdlYktpdFRyYW5z
-aXRpb25FdmVudDp0cnVlLFZSRGV2aWNlRXZlbnQ6dHJ1ZSxWUkRpc3BsYXlFdmVudDp0cnVlLFZSU2Vz
-c2lvbkV2ZW50OnRydWUsTW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDp0cnVlLFVTQkNvbm5lY3Rpb25F
-dmVudDp0cnVlLElEQlZlcnNpb25DaGFuZ2VFdmVudDp0cnVlLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OnRy
-dWUsT2ZmbGluZUF1ZGlvQ29tcGxldGlvbkV2ZW50OnRydWUsV2ViR0xDb250ZXh0RXZlbnQ6dHJ1ZSxF
-dmVudDpmYWxzZSxJbnB1dEV2ZW50OmZhbHNlLFN1Ym1pdEV2ZW50OmZhbHNlLEV2ZW50VGFyZ2V0OmZh
-bHNlLEZpbGU6dHJ1ZSxIVE1MRm9ybUVsZW1lbnQ6dHJ1ZSxIaXN0b3J5OnRydWUsSFRNTERvY3VtZW50
-OnRydWUsWE1MSHR0cFJlcXVlc3Q6dHJ1ZSxYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0OmZhbHNlLElt
-YWdlRGF0YTp0cnVlLExvY2F0aW9uOnRydWUsTW91c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBv
-aW50ZXJFdmVudDp0cnVlLFdoZWVsRXZlbnQ6dHJ1ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93
-Um9vdDp0cnVlLERvY3VtZW50VHlwZTp0cnVlLE5vZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05v
-ZGVMaXN0OnRydWUsSFRNTFBhcmFncmFwaEVsZW1lbnQ6dHJ1ZSxQcm9ncmVzc0V2ZW50OnRydWUsUmVz
-b3VyY2VQcm9ncmVzc0V2ZW50OnRydWUsSFRNTFNlbGVjdEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVFbGVt
-ZW50OnRydWUsSFRNTFRhYmxlUm93RWxlbWVudDp0cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRy
-dWUsSFRNTFRlbXBsYXRlRWxlbWVudDp0cnVlLENvbXBvc2l0aW9uRXZlbnQ6dHJ1ZSxGb2N1c0V2ZW50
-OnRydWUsS2V5Ym9hcmRFdmVudDp0cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1ZSxVSUV2
-ZW50OmZhbHNlLFdpbmRvdzp0cnVlLERPTVdpbmRvdzp0cnVlLERlZGljYXRlZFdvcmtlckdsb2JhbFNj
-b3BlOnRydWUsU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2hhcmVkV29ya2VyR2xvYmFsU2Nv
-cGU6dHJ1ZSxXb3JrZXJHbG9iYWxTY29wZTp0cnVlLEF0dHI6dHJ1ZSxDbGllbnRSZWN0OnRydWUsRE9N
-UmVjdDp0cnVlLE5hbWVkTm9kZU1hcDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLElEQktleVJhbmdl
-OnRydWUsU1ZHU2NyaXB0RWxlbWVudDp0cnVlLFNWR0FFbGVtZW50OnRydWUsU1ZHQW5pbWF0ZUVsZW1l
-bnQ6dHJ1ZSxTVkdBbmltYXRlTW90aW9uRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVt
-ZW50OnRydWUsU1ZHQW5pbWF0aW9uRWxlbWVudDp0cnVlLFNWR0NpcmNsZUVsZW1lbnQ6dHJ1ZSxTVkdD
-bGlwUGF0aEVsZW1lbnQ6dHJ1ZSxTVkdEZWZzRWxlbWVudDp0cnVlLFNWR0Rlc2NFbGVtZW50OnRydWUs
-U1ZHRGlzY2FyZEVsZW1lbnQ6dHJ1ZSxTVkdFbGxpcHNlRWxlbWVudDp0cnVlLFNWR0ZFQmxlbmRFbGVt
-ZW50OnRydWUsU1ZHRkVDb2xvck1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvbmVudFRyYW5zZmVy
-RWxlbWVudDp0cnVlLFNWR0ZFQ29tcG9zaXRlRWxlbWVudDp0cnVlLFNWR0ZFQ29udm9sdmVNYXRyaXhF
-bGVtZW50OnRydWUsU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVEaXNwbGFjZW1l
-bnRNYXBFbGVtZW50OnRydWUsU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVGbG9vZEVs
-ZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNBRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0JFbGVtZW50OnRydWUsU1ZH
-RkVGdW5jR0VsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNSRWxlbWVudDp0cnVlLFNWR0ZFR2F1c3NpYW5CbHVy
-RWxlbWVudDp0cnVlLFNWR0ZFSW1hZ2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZUVsZW1lbnQ6dHJ1ZSxT
-VkdGRU1lcmdlTm9kZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OnRydWUsU1ZHRkVP
-ZmZzZXRFbGVtZW50OnRydWUsU1ZHRkVQb2ludExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFU3BlY3VsYXJM
-aWdodGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVRpbGVFbGVt
-ZW50OnRydWUsU1ZHRkVUdXJidWxlbmNlRWxlbWVudDp0cnVlLFNWR0ZpbHRlckVsZW1lbnQ6dHJ1ZSxT
-VkdGb3JlaWduT2JqZWN0RWxlbWVudDp0cnVlLFNWR0dFbGVtZW50OnRydWUsU1ZHR2VvbWV0cnlFbGVt
-ZW50OnRydWUsU1ZHR3JhcGhpY3NFbGVtZW50OnRydWUsU1ZHSW1hZ2VFbGVtZW50OnRydWUsU1ZHTGlu
-ZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdNYXJrZXJFbGVtZW50
-OnRydWUsU1ZHTWFza0VsZW1lbnQ6dHJ1ZSxTVkdNZXRhZGF0YUVsZW1lbnQ6dHJ1ZSxTVkdQYXRoRWxl
-bWVudDp0cnVlLFNWR1BhdHRlcm5FbGVtZW50OnRydWUsU1ZHUG9seWdvbkVsZW1lbnQ6dHJ1ZSxTVkdQ
-b2x5bGluZUVsZW1lbnQ6dHJ1ZSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdSZWN0RWxl
-bWVudDp0cnVlLFNWR1NldEVsZW1lbnQ6dHJ1ZSxTVkdTdG9wRWxlbWVudDp0cnVlLFNWR1N0eWxlRWxl
-bWVudDp0cnVlLFNWR1NWR0VsZW1lbnQ6dHJ1ZSxTVkdTd2l0Y2hFbGVtZW50OnRydWUsU1ZHU3ltYm9s
-RWxlbWVudDp0cnVlLFNWR1RTcGFuRWxlbWVudDp0cnVlLFNWR1RleHRDb250ZW50RWxlbWVudDp0cnVl
-LFNWR1RleHRFbGVtZW50OnRydWUsU1ZHVGV4dFBhdGhFbGVtZW50OnRydWUsU1ZHVGV4dFBvc2l0aW9u
-aW5nRWxlbWVudDp0cnVlLFNWR1RpdGxlRWxlbWVudDp0cnVlLFNWR1VzZUVsZW1lbnQ6dHJ1ZSxTVkdW
-aWV3RWxlbWVudDp0cnVlLFNWR0dyYWRpZW50RWxlbWVudDp0cnVlLFNWR0NvbXBvbmVudFRyYW5zZmVy
-RnVuY3Rpb25FbGVtZW50OnRydWUsU1ZHRkVEcm9wU2hhZG93RWxlbWVudDp0cnVlLFNWR01QYXRoRWxl
-bWVudDp0cnVlLFNWR0VsZW1lbnQ6ZmFsc2V9KQpILkxaLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJh
-eUJ1ZmZlclZpZXciCkguUkcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5W
-UC4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILkRnLiRuYXRpdmVTdXBlcmNs
-YXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguV0IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVm
-ZmVyVmlldyIKSC5aRy4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlBnLiRu
-YXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXcifSkoKQpjb252ZXJ0QWxsVG9GYXN0T2Jq
-ZWN0KHcpCmNvbnZlcnRUb0Zhc3RPYmplY3QoJCk7KGZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBkb2N1bWVu
-dD09PSJ1bmRlZmluZWQiKXthKG51bGwpCnJldHVybn1pZih0eXBlb2YgZG9jdW1lbnQuY3VycmVudFNj
-cmlwdCE9J3VuZGVmaW5lZCcpe2EoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkKcmV0dXJufXZhciBzPWRv
-Y3VtZW50LnNjcmlwdHMKZnVuY3Rpb24gb25Mb2FkKGIpe2Zvcih2YXIgcT0wO3E8cy5sZW5ndGg7Kytx
-KXNbcV0ucmVtb3ZlRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKQphKGIudGFyZ2V0KX1m
-b3IodmFyIHI9MDtyPHMubGVuZ3RoOysrcilzW3JdLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9h
-ZCxmYWxzZSl9KShmdW5jdGlvbihhKXt2LmN1cnJlbnRTY3JpcHQ9YQppZih0eXBlb2YgZGFydE1haW5S
-dW5uZXI9PT0iZnVuY3Rpb24iKWRhcnRNYWluUnVubmVyKEwuSXEsW10pCmVsc2UgTC5JcShbXSl9KX0p
-KCkKLy8jIHNvdXJjZU1hcHBpbmdVUkw9bWlncmF0aW9uLmpzLm1hcAo=
+dC5pbmRleE9mKCJGaXJlZm94IikgPT0gLTEpIHJldHVybiBob29rczsKICB2YXIgZ2V0VGFnID0gaG9v
+a3MuZ2V0VGFnOwogIHZhciBxdWlja01hcCA9IHsKICAgICJCZWZvcmVVbmxvYWRFdmVudCI6ICJFdmVu
+dCIsCiAgICAiRGF0YVRyYW5zZmVyIjogIkNsaXBib2FyZCIsCiAgICAiR2VvR2VvbG9jYXRpb24iOiAi
+R2VvbG9jYXRpb24iLAogICAgIkxvY2F0aW9uIjogIiFMb2NhdGlvbiIsCiAgICAiV29ya2VyTWVzc2Fn
+ZUV2ZW50IjogIk1lc3NhZ2VFdmVudCIsCiAgICAiWE1MRG9jdW1lbnQiOiAiIURvY3VtZW50In07CiAg
+ZnVuY3Rpb24gZ2V0VGFnRmlyZWZveChvKSB7CiAgICB2YXIgdGFnID0gZ2V0VGFnKG8pOwogICAgcmV0
+dXJuIHF1aWNrTWFwW3RhZ10gfHwgdGFnOwogIH0KICBob29rcy5nZXRUYWcgPSBnZXRUYWdGaXJlZm94
+Owp9CkMueGk9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgdXNlckFnZW50ID0gdHlwZW9mIG5hdmlnYXRv
+ciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiAiIjsKICBpZiAodXNlckFnZW50Lmlu
+ZGV4T2YoIlRyaWRlbnQvIikgPT0gLTEpIHJldHVybiBob29rczsKICB2YXIgZ2V0VGFnID0gaG9va3Mu
+Z2V0VGFnOwogIHZhciBxdWlja01hcCA9IHsKICAgICJCZWZvcmVVbmxvYWRFdmVudCI6ICJFdmVudCIs
+CiAgICAiRGF0YVRyYW5zZmVyIjogIkNsaXBib2FyZCIsCiAgICAiSFRNTERERWxlbWVudCI6ICJIVE1M
+RWxlbWVudCIsCiAgICAiSFRNTERURWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiSFRNTFBocmFz
+ZUVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIlBvc2l0aW9uIjogIkdlb3Bvc2l0aW9uIgogIH07
+CiAgZnVuY3Rpb24gZ2V0VGFnSUUobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAgIHZhciBu
+ZXdUYWcgPSBxdWlja01hcFt0YWddOwogICAgaWYgKG5ld1RhZykgcmV0dXJuIG5ld1RhZzsKICAgIGlm
+ICh0YWcgPT0gIk9iamVjdCIpIHsKICAgICAgaWYgKHdpbmRvdy5EYXRhVmlldyAmJiAobyBpbnN0YW5j
+ZW9mIHdpbmRvdy5EYXRhVmlldykpIHJldHVybiAiRGF0YVZpZXciOwogICAgfQogICAgcmV0dXJuIHRh
+ZzsKICB9CiAgZnVuY3Rpb24gcHJvdG90eXBlRm9yVGFnSUUodGFnKSB7CiAgICB2YXIgY29uc3RydWN0
+b3IgPSB3aW5kb3dbdGFnXTsKICAgIGlmIChjb25zdHJ1Y3RvciA9PSBudWxsKSByZXR1cm4gbnVsbDsK
+ICAgIHJldHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdldFRh
+Z0lFOwogIGhvb2tzLnByb3RvdHlwZUZvclRhZyA9IHByb3RvdHlwZUZvclRhZ0lFOwp9CkMuaTc9ZnVu
+Y3Rpb24oaG9va3MpIHsgcmV0dXJuIGhvb2tzOyB9CgpDLkN0PW5ldyBQLmJ5KCkKQy5FcT1uZXcgUC5r
+NSgpCkMueE09bmV3IFAudTUoKQpDLlFrPW5ldyBQLkUzKCkKQy5Odj1uZXcgSC5rcigpCkMuTlU9bmV3
+IFAuSmkoKQpDLnBkPW5ldyBQLlpkKCkKQy5BZD1uZXcgTS5INygwLCJIaW50QWN0aW9uS2luZC5hZGRO
+dWxsYWJsZUhpbnQiKQpDLm5lPW5ldyBNLkg3KDEsIkhpbnRBY3Rpb25LaW5kLmFkZE5vbk51bGxhYmxl
+SGludCIpCkMubXk9bmV3IE0uSDcoMiwiSGludEFjdGlvbktpbmQuY2hhbmdlVG9OdWxsYWJsZUhpbnQi
+KQpDLnJ4PW5ldyBNLkg3KDMsIkhpbnRBY3Rpb25LaW5kLmNoYW5nZVRvTm9uTnVsbGFibGVIaW50IikK
+Qy53Vj1uZXcgTS5INyg0LCJIaW50QWN0aW9uS2luZC5yZW1vdmVOdWxsYWJsZUhpbnQiKQpDLmZSPW5l
+dyBNLkg3KDUsIkhpbnRBY3Rpb25LaW5kLnJlbW92ZU5vbk51bGxhYmxlSGludCIpCkMuQTM9bmV3IFAu
+TXgobnVsbCkKQy5uWD1uZXcgUC5vaihudWxsKQpDLmFrPUguVk0ocyhbMCwwLDMyNzc2LDMzNzkyLDEs
+MTAyNDAsMCwwXSksdC5WKQpDLmNtPUguVk0ocyhbIio6OmNsYXNzIiwiKjo6ZGlyIiwiKjo6ZHJhZ2dh
+YmxlIiwiKjo6aGlkZGVuIiwiKjo6aWQiLCIqOjppbmVydCIsIio6Oml0ZW1wcm9wIiwiKjo6aXRlbXJl
+ZiIsIio6Oml0ZW1zY29wZSIsIio6OmxhbmciLCIqOjpzcGVsbGNoZWNrIiwiKjo6dGl0bGUiLCIqOjp0
+cmFuc2xhdGUiLCJBOjphY2Nlc3NrZXkiLCJBOjpjb29yZHMiLCJBOjpocmVmbGFuZyIsIkE6Om5hbWUi
+LCJBOjpzaGFwZSIsIkE6OnRhYmluZGV4IiwiQTo6dGFyZ2V0IiwiQTo6dHlwZSIsIkFSRUE6OmFjY2Vz
+c2tleSIsIkFSRUE6OmFsdCIsIkFSRUE6OmNvb3JkcyIsIkFSRUE6Om5vaHJlZiIsIkFSRUE6OnNoYXBl
+IiwiQVJFQTo6dGFiaW5kZXgiLCJBUkVBOjp0YXJnZXQiLCJBVURJTzo6Y29udHJvbHMiLCJBVURJTzo6
+bG9vcCIsIkFVRElPOjptZWRpYWdyb3VwIiwiQVVESU86Om11dGVkIiwiQVVESU86OnByZWxvYWQiLCJC
+RE86OmRpciIsIkJPRFk6OmFsaW5rIiwiQk9EWTo6Ymdjb2xvciIsIkJPRFk6OmxpbmsiLCJCT0RZOjp0
+ZXh0IiwiQk9EWTo6dmxpbmsiLCJCUjo6Y2xlYXIiLCJCVVRUT046OmFjY2Vzc2tleSIsIkJVVFRPTjo6
+ZGlzYWJsZWQiLCJCVVRUT046Om5hbWUiLCJCVVRUT046OnRhYmluZGV4IiwiQlVUVE9OOjp0eXBlIiwi
+QlVUVE9OOjp2YWx1ZSIsIkNBTlZBUzo6aGVpZ2h0IiwiQ0FOVkFTOjp3aWR0aCIsIkNBUFRJT046OmFs
+aWduIiwiQ09MOjphbGlnbiIsIkNPTDo6Y2hhciIsIkNPTDo6Y2hhcm9mZiIsIkNPTDo6c3BhbiIsIkNP
+TDo6dmFsaWduIiwiQ09MOjp3aWR0aCIsIkNPTEdST1VQOjphbGlnbiIsIkNPTEdST1VQOjpjaGFyIiwi
+Q09MR1JPVVA6OmNoYXJvZmYiLCJDT0xHUk9VUDo6c3BhbiIsIkNPTEdST1VQOjp2YWxpZ24iLCJDT0xH
+Uk9VUDo6d2lkdGgiLCJDT01NQU5EOjpjaGVja2VkIiwiQ09NTUFORDo6Y29tbWFuZCIsIkNPTU1BTkQ6
+OmRpc2FibGVkIiwiQ09NTUFORDo6bGFiZWwiLCJDT01NQU5EOjpyYWRpb2dyb3VwIiwiQ09NTUFORDo6
+dHlwZSIsIkRBVEE6OnZhbHVlIiwiREVMOjpkYXRldGltZSIsIkRFVEFJTFM6Om9wZW4iLCJESVI6OmNv
+bXBhY3QiLCJESVY6OmFsaWduIiwiREw6OmNvbXBhY3QiLCJGSUVMRFNFVDo6ZGlzYWJsZWQiLCJGT05U
+Ojpjb2xvciIsIkZPTlQ6OmZhY2UiLCJGT05UOjpzaXplIiwiRk9STTo6YWNjZXB0IiwiRk9STTo6YXV0
+b2NvbXBsZXRlIiwiRk9STTo6ZW5jdHlwZSIsIkZPUk06Om1ldGhvZCIsIkZPUk06Om5hbWUiLCJGT1JN
+Ojpub3ZhbGlkYXRlIiwiRk9STTo6dGFyZ2V0IiwiRlJBTUU6Om5hbWUiLCJIMTo6YWxpZ24iLCJIMjo6
+YWxpZ24iLCJIMzo6YWxpZ24iLCJINDo6YWxpZ24iLCJINTo6YWxpZ24iLCJINjo6YWxpZ24iLCJIUjo6
+YWxpZ24iLCJIUjo6bm9zaGFkZSIsIkhSOjpzaXplIiwiSFI6OndpZHRoIiwiSFRNTDo6dmVyc2lvbiIs
+IklGUkFNRTo6YWxpZ24iLCJJRlJBTUU6OmZyYW1lYm9yZGVyIiwiSUZSQU1FOjpoZWlnaHQiLCJJRlJB
+TUU6Om1hcmdpbmhlaWdodCIsIklGUkFNRTo6bWFyZ2lud2lkdGgiLCJJRlJBTUU6OndpZHRoIiwiSU1H
+OjphbGlnbiIsIklNRzo6YWx0IiwiSU1HOjpib3JkZXIiLCJJTUc6OmhlaWdodCIsIklNRzo6aHNwYWNl
+IiwiSU1HOjppc21hcCIsIklNRzo6bmFtZSIsIklNRzo6dXNlbWFwIiwiSU1HOjp2c3BhY2UiLCJJTUc6
+OndpZHRoIiwiSU5QVVQ6OmFjY2VwdCIsIklOUFVUOjphY2Nlc3NrZXkiLCJJTlBVVDo6YWxpZ24iLCJJ
+TlBVVDo6YWx0IiwiSU5QVVQ6OmF1dG9jb21wbGV0ZSIsIklOUFVUOjphdXRvZm9jdXMiLCJJTlBVVDo6
+Y2hlY2tlZCIsIklOUFVUOjpkaXNhYmxlZCIsIklOUFVUOjppbnB1dG1vZGUiLCJJTlBVVDo6aXNtYXAi
+LCJJTlBVVDo6bGlzdCIsIklOUFVUOjptYXgiLCJJTlBVVDo6bWF4bGVuZ3RoIiwiSU5QVVQ6Om1pbiIs
+IklOUFVUOjptdWx0aXBsZSIsIklOUFVUOjpuYW1lIiwiSU5QVVQ6OnBsYWNlaG9sZGVyIiwiSU5QVVQ6
+OnJlYWRvbmx5IiwiSU5QVVQ6OnJlcXVpcmVkIiwiSU5QVVQ6OnNpemUiLCJJTlBVVDo6c3RlcCIsIklO
+UFVUOjp0YWJpbmRleCIsIklOUFVUOjp0eXBlIiwiSU5QVVQ6OnVzZW1hcCIsIklOUFVUOjp2YWx1ZSIs
+IklOUzo6ZGF0ZXRpbWUiLCJLRVlHRU46OmRpc2FibGVkIiwiS0VZR0VOOjprZXl0eXBlIiwiS0VZR0VO
+OjpuYW1lIiwiTEFCRUw6OmFjY2Vzc2tleSIsIkxBQkVMOjpmb3IiLCJMRUdFTkQ6OmFjY2Vzc2tleSIs
+IkxFR0VORDo6YWxpZ24iLCJMSTo6dHlwZSIsIkxJOjp2YWx1ZSIsIkxJTks6OnNpemVzIiwiTUFQOjpu
+YW1lIiwiTUVOVTo6Y29tcGFjdCIsIk1FTlU6OmxhYmVsIiwiTUVOVTo6dHlwZSIsIk1FVEVSOjpoaWdo
+IiwiTUVURVI6OmxvdyIsIk1FVEVSOjptYXgiLCJNRVRFUjo6bWluIiwiTUVURVI6OnZhbHVlIiwiT0JK
+RUNUOjp0eXBlbXVzdG1hdGNoIiwiT0w6OmNvbXBhY3QiLCJPTDo6cmV2ZXJzZWQiLCJPTDo6c3RhcnQi
+LCJPTDo6dHlwZSIsIk9QVEdST1VQOjpkaXNhYmxlZCIsIk9QVEdST1VQOjpsYWJlbCIsIk9QVElPTjo6
+ZGlzYWJsZWQiLCJPUFRJT046OmxhYmVsIiwiT1BUSU9OOjpzZWxlY3RlZCIsIk9QVElPTjo6dmFsdWUi
+LCJPVVRQVVQ6OmZvciIsIk9VVFBVVDo6bmFtZSIsIlA6OmFsaWduIiwiUFJFOjp3aWR0aCIsIlBST0dS
+RVNTOjptYXgiLCJQUk9HUkVTUzo6bWluIiwiUFJPR1JFU1M6OnZhbHVlIiwiU0VMRUNUOjphdXRvY29t
+cGxldGUiLCJTRUxFQ1Q6OmRpc2FibGVkIiwiU0VMRUNUOjptdWx0aXBsZSIsIlNFTEVDVDo6bmFtZSIs
+IlNFTEVDVDo6cmVxdWlyZWQiLCJTRUxFQ1Q6OnNpemUiLCJTRUxFQ1Q6OnRhYmluZGV4IiwiU09VUkNF
+Ojp0eXBlIiwiVEFCTEU6OmFsaWduIiwiVEFCTEU6OmJnY29sb3IiLCJUQUJMRTo6Ym9yZGVyIiwiVEFC
+TEU6OmNlbGxwYWRkaW5nIiwiVEFCTEU6OmNlbGxzcGFjaW5nIiwiVEFCTEU6OmZyYW1lIiwiVEFCTEU6
+OnJ1bGVzIiwiVEFCTEU6OnN1bW1hcnkiLCJUQUJMRTo6d2lkdGgiLCJUQk9EWTo6YWxpZ24iLCJUQk9E
+WTo6Y2hhciIsIlRCT0RZOjpjaGFyb2ZmIiwiVEJPRFk6OnZhbGlnbiIsIlREOjphYmJyIiwiVEQ6OmFs
+aWduIiwiVEQ6OmF4aXMiLCJURDo6Ymdjb2xvciIsIlREOjpjaGFyIiwiVEQ6OmNoYXJvZmYiLCJURDo6
+Y29sc3BhbiIsIlREOjpoZWFkZXJzIiwiVEQ6OmhlaWdodCIsIlREOjpub3dyYXAiLCJURDo6cm93c3Bh
+biIsIlREOjpzY29wZSIsIlREOjp2YWxpZ24iLCJURDo6d2lkdGgiLCJURVhUQVJFQTo6YWNjZXNza2V5
+IiwiVEVYVEFSRUE6OmF1dG9jb21wbGV0ZSIsIlRFWFRBUkVBOjpjb2xzIiwiVEVYVEFSRUE6OmRpc2Fi
+bGVkIiwiVEVYVEFSRUE6OmlucHV0bW9kZSIsIlRFWFRBUkVBOjpuYW1lIiwiVEVYVEFSRUE6OnBsYWNl
+aG9sZGVyIiwiVEVYVEFSRUE6OnJlYWRvbmx5IiwiVEVYVEFSRUE6OnJlcXVpcmVkIiwiVEVYVEFSRUE6
+OnJvd3MiLCJURVhUQVJFQTo6dGFiaW5kZXgiLCJURVhUQVJFQTo6d3JhcCIsIlRGT09UOjphbGlnbiIs
+IlRGT09UOjpjaGFyIiwiVEZPT1Q6OmNoYXJvZmYiLCJURk9PVDo6dmFsaWduIiwiVEg6OmFiYnIiLCJU
+SDo6YWxpZ24iLCJUSDo6YXhpcyIsIlRIOjpiZ2NvbG9yIiwiVEg6OmNoYXIiLCJUSDo6Y2hhcm9mZiIs
+IlRIOjpjb2xzcGFuIiwiVEg6OmhlYWRlcnMiLCJUSDo6aGVpZ2h0IiwiVEg6Om5vd3JhcCIsIlRIOjpy
+b3dzcGFuIiwiVEg6OnNjb3BlIiwiVEg6OnZhbGlnbiIsIlRIOjp3aWR0aCIsIlRIRUFEOjphbGlnbiIs
+IlRIRUFEOjpjaGFyIiwiVEhFQUQ6OmNoYXJvZmYiLCJUSEVBRDo6dmFsaWduIiwiVFI6OmFsaWduIiwi
+VFI6OmJnY29sb3IiLCJUUjo6Y2hhciIsIlRSOjpjaGFyb2ZmIiwiVFI6OnZhbGlnbiIsIlRSQUNLOjpk
+ZWZhdWx0IiwiVFJBQ0s6OmtpbmQiLCJUUkFDSzo6bGFiZWwiLCJUUkFDSzo6c3JjbGFuZyIsIlVMOjpj
+b21wYWN0IiwiVUw6OnR5cGUiLCJWSURFTzo6Y29udHJvbHMiLCJWSURFTzo6aGVpZ2h0IiwiVklERU86
+Omxvb3AiLCJWSURFTzo6bWVkaWFncm91cCIsIlZJREVPOjptdXRlZCIsIlZJREVPOjpwcmVsb2FkIiwi
+VklERU86OndpZHRoIl0pLHQuaSkKQy5WQz1ILlZNKHMoWzAsMCw2NTQ5MCw0NTA1NSw2NTUzNSwzNDgx
+NSw2NTUzNCwxODQzMV0pLHQuVikKQy5tSz1ILlZNKHMoWzAsMCwyNjYyNCwxMDIzLDY1NTM0LDIwNDcs
+NjU1MzQsMjA0N10pLHQuVikKQy5TcT1ILlZNKHMoWyJIRUFEIiwiQVJFQSIsIkJBU0UiLCJCQVNFRk9O
+VCIsIkJSIiwiQ09MIiwiQ09MR1JPVVAiLCJFTUJFRCIsIkZSQU1FIiwiRlJBTUVTRVQiLCJIUiIsIklN
+QUdFIiwiSU1HIiwiSU5QVVQiLCJJU0lOREVYIiwiTElOSyIsIk1FVEEiLCJQQVJBTSIsIlNPVVJDRSIs
+IlNUWUxFIiwiVElUTEUiLCJXQlIiXSksdC5pKQpDLmhVPUguVk0ocyhbXSksdC54KQpDLmRuPUguVk0o
+cyhbXSksSC5OMCgiamQ8TEwqPiIpKQpDLnhEPUguVk0ocyhbXSksdC5pKQpDLnRvPUguVk0ocyhbMCww
+LDMyNzIyLDEyMjg3LDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdC5WKQpDLnJrPUguVk0ocyhbQy5B
+ZCxDLm5lLEMubXksQy5yeCxDLndWLEMuZlJdKSxILk4wKCJqZDxINyo+IikpCkMuRjM9SC5WTShzKFsw
+LDAsMjQ1NzYsMTAyMyw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0pLHQuVikKQy5lYT1ILlZNKHMoWzAs
+MCwzMjc1NCwxMTI2Myw2NTUzNCwzNDgxNSw2NTUzNCwxODQzMV0pLHQuVikKQy5aSj1ILlZNKHMoWzAs
+MCwzMjcyMiwxMjI4Nyw2NTUzNSwzNDgxNSw2NTUzNCwxODQzMV0pLHQuVikKQy5XZD1ILlZNKHMoWzAs
+MCw2NTQ5MCwxMjI4Nyw2NTUzNSwzNDgxNSw2NTUzNCwxODQzMV0pLHQuVikKQy5ReD1ILlZNKHMoWyJi
+aW5kIiwiaWYiLCJyZWYiLCJyZXBlYXQiLCJzeW50YXgiXSksdC5pKQpDLkJJPUguVk0ocyhbIkE6Omhy
+ZWYiLCJBUkVBOjpocmVmIiwiQkxPQ0tRVU9URTo6Y2l0ZSIsIkJPRFk6OmJhY2tncm91bmQiLCJDT01N
+QU5EOjppY29uIiwiREVMOjpjaXRlIiwiRk9STTo6YWN0aW9uIiwiSU1HOjpzcmMiLCJJTlBVVDo6c3Jj
+IiwiSU5TOjpjaXRlIiwiUTo6Y2l0ZSIsIlZJREVPOjpwb3N0ZXIiXSksdC5pKQpDLkR4PW5ldyBILkxQ
+KDAse30sQy54RCxILk4wKCJMUDxxVSosek08ajgqPio+IikpCkMuQ009bmV3IEguTFAoMCx7fSxDLnhE
+LEguTjAoIkxQPHFVKixxVSo+IikpCkMuaUg9SC5WTShzKFtdKSxILk4wKCJqZDxHRCo+IikpCkMuV089
+bmV3IEguTFAoMCx7fSxDLmlILEguTjAoIkxQPEdEKixAPiIpKQpDLlkyPW5ldyBMLk85KCJOYXZpZ2F0
+aW9uVHJlZU5vZGVUeXBlLmRpcmVjdG9yeSIpCkMucmY9bmV3IEwuTzkoIk5hdmlnYXRpb25UcmVlTm9k
+ZVR5cGUuZmlsZSIpCkMuVGU9bmV3IEgud3YoImNhbGwiKQpDLm9FPW5ldyBQLkdZKCExKQpDLndRPW5l
+dyBQLkZ5KG51bGwsMil9KSgpOyhmdW5jdGlvbiBzdGF0aWNGaWVsZHMoKXskLnptPW51bGwKJC55aj0w
+CiQubUo9bnVsbAokLlA0PW51bGwKJC5ORj1udWxsCiQuVFg9bnVsbAokLng3PW51bGwKJC5udz1udWxs
+CiQudnY9bnVsbAokLkJ2PW51bGwKJC5TNj1udWxsCiQuazg9bnVsbAokLm1nPW51bGwKJC5VRD0hMQok
+LlgzPUMuTlUKJC54Zz1ILlZNKFtdLEguTjAoImpkPE1oPiIpKQokLnhvPW51bGwKJC5CTz1udWxsCiQu
+bHQ9bnVsbAokLkVVPW51bGwKJC5vcj1QLkZsKHQuTix0LlkpCiQuSTY9bnVsbAokLkZmPW51bGx9KSgp
+OyhmdW5jdGlvbiBsYXp5SW5pdGlhbGl6ZXJzKCl7dmFyIHM9aHVua0hlbHBlcnMubGF6eUZpbmFsLHI9
+aHVua0hlbHBlcnMubGF6eU9sZApzKCQsImZhIiwidyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygiXyRk
+YXJ0X2RhcnRDbG9zdXJlIil9KQpzKCQsIlUyIiwiU24iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5T
+Nyh7CnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0pKX0pCnMoJCwieHEiLCJs
+cSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHskbWV0aG9kJDpudWxsLAp0b1N0cmluZzpmdW5j
+dGlvbigpe3JldHVybiIkcmVjZWl2ZXIkIn19KSl9KQpzKCQsIlIxIiwiTjkiLGZ1bmN0aW9uKCl7cmV0
+dXJuIEguY00oSC5TNyhudWxsKSl9KQpzKCQsImZOIiwiaUkiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00o
+ZnVuY3Rpb24oKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5e251bGwuJG1ldGhv
+ZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChxKXtyZXR1cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsInFp
+IiwiVU4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5TNyh2b2lkIDApKX0pCnMoJCwicloiLCJaaCIs
+ZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1
+bWVudHMkJwp0cnl7KHZvaWQgMCkuJG1ldGhvZCQoJGFyZ3VtZW50c0V4cHIkKX1jYXRjaChxKXtyZXR1
+cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsImtxIiwick4iLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5N
+aihudWxsKSl9KQpzKCQsInR0IiwiYzMiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oZnVuY3Rpb24oKXt0
+cnl7bnVsbC4kbWV0aG9kJH1jYXRjaChxKXtyZXR1cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsImR0Iiwi
+SEsiLGZ1bmN0aW9uKCl7cmV0dXJuIEguY00oSC5Naih2b2lkIDApKX0pCnMoJCwiQTciLCJyMSIsZnVu
+Y3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXsodm9pZCAwKS4kbWV0aG9kJH1jYXRjaChx
+KXtyZXR1cm4gcS5tZXNzYWdlfX0oKSl9KQpzKCQsIldjIiwidXQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAu
+T2ooKX0pCnMoJCwia2giLCJyZiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IFAucGcoKS4kMCgpfSkKcygk
+LCJhWCIsIkhHIixmdW5jdGlvbigpe3JldHVybiBuZXcgUC5jMigpLiQwKCl9KQpzKCQsImJ0IiwiVjci
+LGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBJbnQ4QXJyYXkoSC5YRihILlZNKFstMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
+MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMSwtMiwtMiwtMiwtMiwtMiw2MiwtMiw2
+MiwtMiw2Myw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2MSwtMiwtMiwtMiwtMSwtMiwtMiwtMiww
+LDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIz
+LDI0LDI1LC0yLC0yLC0yLC0yLDYzLC0yLDI2LDI3LDI4LDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3
+LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLC0yLC0yLC0yLC0yLC0yXSx0
+LmEpKSl9KQpzKCQsIk01Iiwid1EiLGZ1bmN0aW9uKCl7cmV0dXJuIHR5cGVvZiBwcm9jZXNzIT0idW5k
+ZWZpbmVkIiYmT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHByb2Nlc3MpPT0iW29iamVjdCBw
+cm9jZXNzXSImJnByb2Nlc3MucGxhdGZvcm09PSJ3aW4zMiJ9KQpzKCQsIm1mIiwiejQiLGZ1bmN0aW9u
+KCl7cmV0dXJuIFAubnUoIl5bXFwtXFwuMC05QS1aX2Eten5dKiQiKX0pCnMoJCwiT1EiLCJ2WiIsZnVu
+Y3Rpb24oKXtyZXR1cm4gUC5LTigpfSkKcygkLCJTQyIsIkFOIixmdW5jdGlvbigpe3JldHVybiBQLnRN
+KFsiQSIsIkFCQlIiLCJBQ1JPTllNIiwiQUREUkVTUyIsIkFSRUEiLCJBUlRJQ0xFIiwiQVNJREUiLCJB
+VURJTyIsIkIiLCJCREkiLCJCRE8iLCJCSUciLCJCTE9DS1FVT1RFIiwiQlIiLCJCVVRUT04iLCJDQU5W
+QVMiLCJDQVBUSU9OIiwiQ0VOVEVSIiwiQ0lURSIsIkNPREUiLCJDT0wiLCJDT0xHUk9VUCIsIkNPTU1B
+TkQiLCJEQVRBIiwiREFUQUxJU1QiLCJERCIsIkRFTCIsIkRFVEFJTFMiLCJERk4iLCJESVIiLCJESVYi
+LCJETCIsIkRUIiwiRU0iLCJGSUVMRFNFVCIsIkZJR0NBUFRJT04iLCJGSUdVUkUiLCJGT05UIiwiRk9P
+VEVSIiwiRk9STSIsIkgxIiwiSDIiLCJIMyIsIkg0IiwiSDUiLCJINiIsIkhFQURFUiIsIkhHUk9VUCIs
+IkhSIiwiSSIsIklGUkFNRSIsIklNRyIsIklOUFVUIiwiSU5TIiwiS0JEIiwiTEFCRUwiLCJMRUdFTkQi
+LCJMSSIsIk1BUCIsIk1BUksiLCJNRU5VIiwiTUVURVIiLCJOQVYiLCJOT0JSIiwiT0wiLCJPUFRHUk9V
+UCIsIk9QVElPTiIsIk9VVFBVVCIsIlAiLCJQUkUiLCJQUk9HUkVTUyIsIlEiLCJTIiwiU0FNUCIsIlNF
+Q1RJT04iLCJTRUxFQ1QiLCJTTUFMTCIsIlNPVVJDRSIsIlNQQU4iLCJTVFJJS0UiLCJTVFJPTkciLCJT
+VUIiLCJTVU1NQVJZIiwiU1VQIiwiVEFCTEUiLCJUQk9EWSIsIlREIiwiVEVYVEFSRUEiLCJURk9PVCIs
+IlRIIiwiVEhFQUQiLCJUSU1FIiwiVFIiLCJUUkFDSyIsIlRUIiwiVSIsIlVMIiwiVkFSIiwiVklERU8i
+LCJXQlIiXSx0Lk4pfSkKcygkLCJYNCIsImhHIixmdW5jdGlvbigpe3JldHVybiBQLm51KCJeXFxTKyQi
+KX0pCnMoJCwid08iLCJvdyIsZnVuY3Rpb24oKXtyZXR1cm4gUC5ORChzZWxmKX0pCnMoJCwia3QiLCJS
+OCIsZnVuY3Rpb24oKXtyZXR1cm4gSC5ZZygiXyRkYXJ0X2RhcnRPYmplY3QiKX0pCnMoJCwiZksiLCJr
+SSIsZnVuY3Rpb24oKXtyZXR1cm4gZnVuY3Rpb24gRGFydE9iamVjdChhKXt0aGlzLm89YX19KQpyKCQs
+InF0IiwiekIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBULm1RKCl9KQpyKCQsIk9sIiwiVUUiLGZ1bmN0
+aW9uKCl7cmV0dXJuIFAuaEsoQy5vbC5nbVcoVy54MygpKS5ocmVmKS5naFkoKS5xKDAsImF1dGhUb2tl
+biIpfSkKcigkLCJoVCIsInlQIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3Rvcigi
+LmVkaXQtbGlzdCAucGFuZWwtY29udGVudCIpfSkKcigkLCJXNiIsImhMIixmdW5jdGlvbigpe3JldHVy
+biBXLlpyKCkucXVlcnlTZWxlY3RvcigiLmVkaXQtcGFuZWwgLnBhbmVsLWNvbnRlbnQiKX0pCnIoJCwi
+VFIiLCJEVyIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoImZvb3RlciIpfSkK
+cigkLCJFWSIsImZpIixmdW5jdGlvbigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiaGVhZGVy
+Iil9KQpyKCQsImF2IiwiRDkiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIj
+dW5pdC1uYW1lIil9KQpyKCQsImZlIiwiS0ciLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLlhBKCl9KQpz
+KCQsImVvIiwiblUiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBNLmxJKCQuSGsoKSl9KQpzKCQsInlyIiwi
+YkQiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBFLk9GKFAubnUoIi8iKSxQLm51KCJbXi9dJCIpLFAubnUo
+Il4vIikpfSkKcygkLCJNayIsIktrIixmdW5jdGlvbigpe3JldHVybiBuZXcgTC5JVihQLm51KCJbL1xc
+XFxdIiksUC5udSgiW14vXFxcXF0kIiksUC5udSgiXihcXFxcXFxcXFteXFxcXF0rXFxcXFteXFxcXC9d
+K3xbYS16QS1aXTpbL1xcXFxdKSIpLFAubnUoIl5bL1xcXFxdKD8hWy9cXFxcXSkiKSl9KQpzKCQsImFr
+IiwiRWIiLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBGLnJ1KFAubnUoIi8iKSxQLm51KCIoXlthLXpBLVpd
+Wy0rLmEtekEtWlxcZF0qOi8vfFteL10pJCIpLFAubnUoIlthLXpBLVpdWy0rLmEtekEtWlxcZF0qOi8v
+W14vXSoiKSxQLm51KCJeLyIpKX0pCnMoJCwibHMiLCJIayIsZnVuY3Rpb24oKXtyZXR1cm4gTy5SaCgp
+fSl9KSgpOyhmdW5jdGlvbiBuYXRpdmVTdXBwb3J0KCl7IWZ1bmN0aW9uKCl7dmFyIHM9ZnVuY3Rpb24o
+YSl7dmFyIG09e30KbVthXT0xCnJldHVybiBPYmplY3Qua2V5cyhodW5rSGVscGVycy5jb252ZXJ0VG9G
+YXN0T2JqZWN0KG0pKVswXX0Kdi5nZXRJc29sYXRlVGFnPWZ1bmN0aW9uKGEpe3JldHVybiBzKCJfX19k
+YXJ0XyIrYSt2Lmlzb2xhdGVUYWcpfQp2YXIgcj0iX19fZGFydF9pc29sYXRlX3RhZ3NfIgp2YXIgcT1P
+YmplY3Rbcl18fChPYmplY3Rbcl09T2JqZWN0LmNyZWF0ZShudWxsKSkKdmFyIHA9Il9aeFl4WCIKZm9y
+KHZhciBvPTA7O28rKyl7dmFyIG49cyhwKyJfIitvKyJfIikKaWYoIShuIGluIHEpKXtxW25dPTEKdi5p
+c29sYXRlVGFnPW4KYnJlYWt9fXYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWU9di5nZXRJc29sYXRlVGFnKCJk
+aXNwYXRjaF9yZWNvcmQiKX0oKQpodW5rSGVscGVycy5zZXRPclVwZGF0ZUludGVyY2VwdG9yc0J5VGFn
+KHtET01FcnJvcjpKLnZCLE1lZGlhRXJyb3I6Si52QixOYXZpZ2F0b3I6Si52QixOYXZpZ2F0b3JDb25j
+dXJyZW50SGFyZHdhcmU6Si52QixOYXZpZ2F0b3JVc2VyTWVkaWFFcnJvcjpKLnZCLE92ZXJjb25zdHJh
+aW5lZEVycm9yOkoudkIsUG9zaXRpb25FcnJvcjpKLnZCLFJhbmdlOkoudkIsU1FMRXJyb3I6Si52QixE
+YXRhVmlldzpILkVULEFycmF5QnVmZmVyVmlldzpILkVULEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRB
+cnJheTpILkRnLEludDE2QXJyYXk6SC54aixJbnQzMkFycmF5OkguZEUsSW50OEFycmF5OkguWkEsVWlu
+dDE2QXJyYXk6SC5kVCxVaW50MzJBcnJheTpILlBxLFVpbnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFz
+UGl4ZWxBcnJheTpILmVFLFVpbnQ4QXJyYXk6SC5WNixIVE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJS
+RWxlbWVudDpXLnFFLEhUTUxCdXR0b25FbGVtZW50OlcucUUsSFRNTENhbnZhc0VsZW1lbnQ6Vy5xRSxI
+VE1MQ29udGVudEVsZW1lbnQ6Vy5xRSxIVE1MRExpc3RFbGVtZW50OlcucUUsSFRNTERhdGFFbGVtZW50
+OlcucUUsSFRNTERhdGFMaXN0RWxlbWVudDpXLnFFLEhUTUxEZXRhaWxzRWxlbWVudDpXLnFFLEhUTUxE
+aWFsb2dFbGVtZW50OlcucUUsSFRNTERpdkVsZW1lbnQ6Vy5xRSxIVE1MRW1iZWRFbGVtZW50OlcucUUs
+SFRNTEZpZWxkU2V0RWxlbWVudDpXLnFFLEhUTUxIUkVsZW1lbnQ6Vy5xRSxIVE1MSGVhZEVsZW1lbnQ6
+Vy5xRSxIVE1MSGVhZGluZ0VsZW1lbnQ6Vy5xRSxIVE1MSHRtbEVsZW1lbnQ6Vy5xRSxIVE1MSUZyYW1l
+RWxlbWVudDpXLnFFLEhUTUxJbWFnZUVsZW1lbnQ6Vy5xRSxIVE1MSW5wdXRFbGVtZW50OlcucUUsSFRN
+TExJRWxlbWVudDpXLnFFLEhUTUxMYWJlbEVsZW1lbnQ6Vy5xRSxIVE1MTGVnZW5kRWxlbWVudDpXLnFF
+LEhUTUxMaW5rRWxlbWVudDpXLnFFLEhUTUxNYXBFbGVtZW50OlcucUUsSFRNTE1lZGlhRWxlbWVudDpX
+LnFFLEhUTUxNZW51RWxlbWVudDpXLnFFLEhUTUxNZXRhRWxlbWVudDpXLnFFLEhUTUxNZXRlckVsZW1l
+bnQ6Vy5xRSxIVE1MTW9kRWxlbWVudDpXLnFFLEhUTUxPTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MT2JqZWN0
+RWxlbWVudDpXLnFFLEhUTUxPcHRHcm91cEVsZW1lbnQ6Vy5xRSxIVE1MT3B0aW9uRWxlbWVudDpXLnFF
+LEhUTUxPdXRwdXRFbGVtZW50OlcucUUsSFRNTFBhcmFtRWxlbWVudDpXLnFFLEhUTUxQaWN0dXJlRWxl
+bWVudDpXLnFFLEhUTUxQcmVFbGVtZW50OlcucUUsSFRNTFByb2dyZXNzRWxlbWVudDpXLnFFLEhUTUxR
+dW90ZUVsZW1lbnQ6Vy5xRSxIVE1MU2NyaXB0RWxlbWVudDpXLnFFLEhUTUxTaGFkb3dFbGVtZW50Olcu
+cUUsSFRNTFNsb3RFbGVtZW50OlcucUUsSFRNTFNvdXJjZUVsZW1lbnQ6Vy5xRSxIVE1MU3BhbkVsZW1l
+bnQ6Vy5xRSxIVE1MU3R5bGVFbGVtZW50OlcucUUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6Vy5xRSxI
+VE1MVGFibGVDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZURhdGFDZWxsRWxlbWVudDpXLnFFLEhUTUxU
+YWJsZUhlYWRlckNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlQ29sRWxlbWVudDpXLnFFLEhUTUxUZXh0
+QXJlYUVsZW1lbnQ6Vy5xRSxIVE1MVGltZUVsZW1lbnQ6Vy5xRSxIVE1MVGl0bGVFbGVtZW50OlcucUUs
+SFRNTFRyYWNrRWxlbWVudDpXLnFFLEhUTUxVTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MVW5rbm93bkVsZW1l
+bnQ6Vy5xRSxIVE1MVmlkZW9FbGVtZW50OlcucUUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6Vy5xRSxIVE1M
+Rm9udEVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVFbGVtZW50OlcucUUsSFRNTEZyYW1lU2V0RWxlbWVudDpX
+LnFFLEhUTUxNYXJxdWVlRWxlbWVudDpXLnFFLEhUTUxFbGVtZW50OlcucUUsSFRNTEFuY2hvckVsZW1l
+bnQ6Vy5HaCxIVE1MQXJlYUVsZW1lbnQ6Vy5mWSxIVE1MQmFzZUVsZW1lbnQ6Vy5uQixCbG9iOlcuQXos
+SFRNTEJvZHlFbGVtZW50OlcuUVAsQ0RBVEFTZWN0aW9uOlcubngsQ2hhcmFjdGVyRGF0YTpXLm54LENv
+bW1lbnQ6Vy5ueCxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246Vy5ueCxUZXh0OlcubngsQ1NTU3R5bGVEZWNs
+YXJhdGlvbjpXLm9KLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOlcub0osQ1NTMlByb3BlcnRpZXM6Vy5vSixY
+TUxEb2N1bWVudDpXLlFGLERvY3VtZW50OlcuUUYsRE9NRXhjZXB0aW9uOlcuTmgsRE9NSW1wbGVtZW50
+YXRpb246Vy5hZSxET01SZWN0UmVhZE9ubHk6Vy5JQixET01Ub2tlbkxpc3Q6Vy5uNyxFbGVtZW50Olcu
+Y3YsQWJvcnRQYXltZW50RXZlbnQ6Vy5lYSxBbmltYXRpb25FdmVudDpXLmVhLEFuaW1hdGlvblBsYXli
+YWNrRXZlbnQ6Vy5lYSxBcHBsaWNhdGlvbkNhY2hlRXJyb3JFdmVudDpXLmVhLEJhY2tncm91bmRGZXRj
+aENsaWNrRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaEZh
+aWxFdmVudDpXLmVhLEJhY2tncm91bmRGZXRjaGVkRXZlbnQ6Vy5lYSxCZWZvcmVJbnN0YWxsUHJvbXB0
+RXZlbnQ6Vy5lYSxCZWZvcmVVbmxvYWRFdmVudDpXLmVhLEJsb2JFdmVudDpXLmVhLENhbk1ha2VQYXlt
+ZW50RXZlbnQ6Vy5lYSxDbGlwYm9hcmRFdmVudDpXLmVhLENsb3NlRXZlbnQ6Vy5lYSxDdXN0b21FdmVu
+dDpXLmVhLERldmljZU1vdGlvbkV2ZW50OlcuZWEsRGV2aWNlT3JpZW50YXRpb25FdmVudDpXLmVhLEVy
+cm9yRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlRXZlbnQ6Vy5lYSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50Olcu
+ZWEsRmV0Y2hFdmVudDpXLmVhLEZvbnRGYWNlU2V0TG9hZEV2ZW50OlcuZWEsRm9yZWlnbkZldGNoRXZl
+bnQ6Vy5lYSxHYW1lcGFkRXZlbnQ6Vy5lYSxIYXNoQ2hhbmdlRXZlbnQ6Vy5lYSxJbnN0YWxsRXZlbnQ6
+Vy5lYSxNZWRpYUVuY3J5cHRlZEV2ZW50OlcuZWEsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6Vy5lYSxNZWRp
+YVF1ZXJ5TGlzdEV2ZW50OlcuZWEsTWVkaWFTdHJlYW1FdmVudDpXLmVhLE1lZGlhU3RyZWFtVHJhY2tF
+dmVudDpXLmVhLE1lc3NhZ2VFdmVudDpXLmVhLE1JRElDb25uZWN0aW9uRXZlbnQ6Vy5lYSxNSURJTWVz
+c2FnZUV2ZW50OlcuZWEsTXV0YXRpb25FdmVudDpXLmVhLE5vdGlmaWNhdGlvbkV2ZW50OlcuZWEsUGFn
+ZVRyYW5zaXRpb25FdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0RXZlbnQ6Vy5lYSxQYXltZW50UmVxdWVz
+dFVwZGF0ZUV2ZW50OlcuZWEsUG9wU3RhdGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25B
+dmFpbGFibGVFdmVudDpXLmVhLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OlcuZWEsUHJv
+bWlzZVJlamVjdGlvbkV2ZW50OlcuZWEsUHVzaEV2ZW50OlcuZWEsUlRDRGF0YUNoYW5uZWxFdmVudDpX
+LmVhLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6Vy5lYSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50Olcu
+ZWEsUlRDVHJhY2tFdmVudDpXLmVhLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6Vy5lYSxTZW5z
+b3JFcnJvckV2ZW50OlcuZWEsU3BlZWNoUmVjb2duaXRpb25FcnJvcjpXLmVhLFNwZWVjaFJlY29nbml0
+aW9uRXZlbnQ6Vy5lYSxTcGVlY2hTeW50aGVzaXNFdmVudDpXLmVhLFN0b3JhZ2VFdmVudDpXLmVhLFN5
+bmNFdmVudDpXLmVhLFRyYWNrRXZlbnQ6Vy5lYSxUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxXZWJLaXRUcmFu
+c2l0aW9uRXZlbnQ6Vy5lYSxWUkRldmljZUV2ZW50OlcuZWEsVlJEaXNwbGF5RXZlbnQ6Vy5lYSxWUlNl
+c3Npb25FdmVudDpXLmVhLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6Vy5lYSxVU0JDb25uZWN0aW9u
+RXZlbnQ6Vy5lYSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6Vy5lYSxBdWRpb1Byb2Nlc3NpbmdFdmVudDpX
+LmVhLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDpXLmVhLFdlYkdMQ29udGV4dEV2ZW50OlcuZWEs
+RXZlbnQ6Vy5lYSxJbnB1dEV2ZW50OlcuZWEsU3VibWl0RXZlbnQ6Vy5lYSxFdmVudFRhcmdldDpXLkQw
+LEZpbGU6Vy5oSCxIVE1MRm9ybUVsZW1lbnQ6Vy5oNCxIaXN0b3J5OlcuYnIsSFRNTERvY3VtZW50Olcu
+VmIsWE1MSHR0cFJlcXVlc3Q6Vy5mSixYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0Olcud2EsSW1hZ2VE
+YXRhOlcuU2csTG9jYXRpb246Vy51OCxNb3VzZUV2ZW50OlcuQWosRHJhZ0V2ZW50OlcuQWosUG9pbnRl
+ckV2ZW50OlcuQWosV2hlZWxFdmVudDpXLkFqLERvY3VtZW50RnJhZ21lbnQ6Vy51SCxTaGFkb3dSb290
+OlcudUgsRG9jdW1lbnRUeXBlOlcudUgsTm9kZTpXLnVILE5vZGVMaXN0OlcuQkgsUmFkaW9Ob2RlTGlz
+dDpXLkJILEhUTUxQYXJhZ3JhcGhFbGVtZW50OlcuU04sUHJvZ3Jlc3NFdmVudDpXLmV3LFJlc291cmNl
+UHJvZ3Jlc3NFdmVudDpXLmV3LEhUTUxTZWxlY3RFbGVtZW50OlcubHAsSFRNTFRhYmxlRWxlbWVudDpX
+LlRiLEhUTUxUYWJsZVJvd0VsZW1lbnQ6Vy5JdixIVE1MVGFibGVTZWN0aW9uRWxlbWVudDpXLldQLEhU
+TUxUZW1wbGF0ZUVsZW1lbnQ6Vy55WSxDb21wb3NpdGlvbkV2ZW50OlcudzYsRm9jdXNFdmVudDpXLnc2
+LEtleWJvYXJkRXZlbnQ6Vy53NixUZXh0RXZlbnQ6Vy53NixUb3VjaEV2ZW50OlcudzYsVUlFdmVudDpX
+Lnc2LFdpbmRvdzpXLks1LERPTVdpbmRvdzpXLks1LERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOlcu
+Q20sU2VydmljZVdvcmtlckdsb2JhbFNjb3BlOlcuQ20sU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6Vy5D
+bSxXb3JrZXJHbG9iYWxTY29wZTpXLkNtLEF0dHI6Vy5DUSxDbGllbnRSZWN0OlcudzQsRE9NUmVjdDpX
+Lnc0LE5hbWVkTm9kZU1hcDpXLnJoLE1vek5hbWVkQXR0ck1hcDpXLnJoLElEQktleVJhbmdlOlAuaEYs
+U1ZHU2NyaXB0RWxlbWVudDpQLm5kLFNWR0FFbGVtZW50OlAuaGksU1ZHQW5pbWF0ZUVsZW1lbnQ6UC5o
+aSxTVkdBbmltYXRlTW90aW9uRWxlbWVudDpQLmhpLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50OlAu
+aGksU1ZHQW5pbWF0aW9uRWxlbWVudDpQLmhpLFNWR0NpcmNsZUVsZW1lbnQ6UC5oaSxTVkdDbGlwUGF0
+aEVsZW1lbnQ6UC5oaSxTVkdEZWZzRWxlbWVudDpQLmhpLFNWR0Rlc2NFbGVtZW50OlAuaGksU1ZHRGlz
+Y2FyZEVsZW1lbnQ6UC5oaSxTVkdFbGxpcHNlRWxlbWVudDpQLmhpLFNWR0ZFQmxlbmRFbGVtZW50OlAu
+aGksU1ZHRkVDb2xvck1hdHJpeEVsZW1lbnQ6UC5oaSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxlbWVu
+dDpQLmhpLFNWR0ZFQ29tcG9zaXRlRWxlbWVudDpQLmhpLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVtZW50
+OlAuaGksU1ZHRkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OlAuaGksU1ZHRkVEaXNwbGFjZW1lbnRNYXBF
+bGVtZW50OlAuaGksU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OlAuaGksU1ZHRkVGbG9vZEVsZW1lbnQ6
+UC5oaSxTVkdGRUZ1bmNBRWxlbWVudDpQLmhpLFNWR0ZFRnVuY0JFbGVtZW50OlAuaGksU1ZHRkVGdW5j
+R0VsZW1lbnQ6UC5oaSxTVkdGRUZ1bmNSRWxlbWVudDpQLmhpLFNWR0ZFR2F1c3NpYW5CbHVyRWxlbWVu
+dDpQLmhpLFNWR0ZFSW1hZ2VFbGVtZW50OlAuaGksU1ZHRkVNZXJnZUVsZW1lbnQ6UC5oaSxTVkdGRU1l
+cmdlTm9kZUVsZW1lbnQ6UC5oaSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OlAuaGksU1ZHRkVPZmZzZXRF
+bGVtZW50OlAuaGksU1ZHRkVQb2ludExpZ2h0RWxlbWVudDpQLmhpLFNWR0ZFU3BlY3VsYXJMaWdodGlu
+Z0VsZW1lbnQ6UC5oaSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6UC5oaSxTVkdGRVRpbGVFbGVtZW50OlAu
+aGksU1ZHRkVUdXJidWxlbmNlRWxlbWVudDpQLmhpLFNWR0ZpbHRlckVsZW1lbnQ6UC5oaSxTVkdGb3Jl
+aWduT2JqZWN0RWxlbWVudDpQLmhpLFNWR0dFbGVtZW50OlAuaGksU1ZHR2VvbWV0cnlFbGVtZW50OlAu
+aGksU1ZHR3JhcGhpY3NFbGVtZW50OlAuaGksU1ZHSW1hZ2VFbGVtZW50OlAuaGksU1ZHTGluZUVsZW1l
+bnQ6UC5oaSxTVkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6UC5oaSxTVkdNYXJrZXJFbGVtZW50OlAuaGks
+U1ZHTWFza0VsZW1lbnQ6UC5oaSxTVkdNZXRhZGF0YUVsZW1lbnQ6UC5oaSxTVkdQYXRoRWxlbWVudDpQ
+LmhpLFNWR1BhdHRlcm5FbGVtZW50OlAuaGksU1ZHUG9seWdvbkVsZW1lbnQ6UC5oaSxTVkdQb2x5bGlu
+ZUVsZW1lbnQ6UC5oaSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6UC5oaSxTVkdSZWN0RWxlbWVudDpQ
+LmhpLFNWR1NldEVsZW1lbnQ6UC5oaSxTVkdTdG9wRWxlbWVudDpQLmhpLFNWR1N0eWxlRWxlbWVudDpQ
+LmhpLFNWR1NWR0VsZW1lbnQ6UC5oaSxTVkdTd2l0Y2hFbGVtZW50OlAuaGksU1ZHU3ltYm9sRWxlbWVu
+dDpQLmhpLFNWR1RTcGFuRWxlbWVudDpQLmhpLFNWR1RleHRDb250ZW50RWxlbWVudDpQLmhpLFNWR1Rl
+eHRFbGVtZW50OlAuaGksU1ZHVGV4dFBhdGhFbGVtZW50OlAuaGksU1ZHVGV4dFBvc2l0aW9uaW5nRWxl
+bWVudDpQLmhpLFNWR1RpdGxlRWxlbWVudDpQLmhpLFNWR1VzZUVsZW1lbnQ6UC5oaSxTVkdWaWV3RWxl
+bWVudDpQLmhpLFNWR0dyYWRpZW50RWxlbWVudDpQLmhpLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVuY3Rp
+b25FbGVtZW50OlAuaGksU1ZHRkVEcm9wU2hhZG93RWxlbWVudDpQLmhpLFNWR01QYXRoRWxlbWVudDpQ
+LmhpLFNWR0VsZW1lbnQ6UC5oaX0pCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlTGVhZlRhZ3Moe0RPTUVy
+cm9yOnRydWUsTWVkaWFFcnJvcjp0cnVlLE5hdmlnYXRvcjp0cnVlLE5hdmlnYXRvckNvbmN1cnJlbnRI
+YXJkd2FyZTp0cnVlLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJy
+b3I6dHJ1ZSxQb3NpdGlvbkVycm9yOnRydWUsUmFuZ2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLERhdGFWaWV3
+OnRydWUsQXJyYXlCdWZmZXJWaWV3OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVlLEZsb2F0NjRBcnJheTp0
+cnVlLEludDE2QXJyYXk6dHJ1ZSxJbnQzMkFycmF5OnRydWUsSW50OEFycmF5OnRydWUsVWludDE2QXJy
+YXk6dHJ1ZSxVaW50MzJBcnJheTp0cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRydWUsQ2FudmFzUGl4ZWxB
+cnJheTp0cnVlLFVpbnQ4QXJyYXk6ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0cnVlLEhUTUxCUkVsZW1l
+bnQ6dHJ1ZSxIVE1MQnV0dG9uRWxlbWVudDp0cnVlLEhUTUxDYW52YXNFbGVtZW50OnRydWUsSFRNTENv
+bnRlbnRFbGVtZW50OnRydWUsSFRNTERMaXN0RWxlbWVudDp0cnVlLEhUTUxEYXRhRWxlbWVudDp0cnVl
+LEhUTUxEYXRhTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGV0YWlsc0VsZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9n
+RWxlbWVudDp0cnVlLEhUTUxEaXZFbGVtZW50OnRydWUsSFRNTEVtYmVkRWxlbWVudDp0cnVlLEhUTUxG
+aWVsZFNldEVsZW1lbnQ6dHJ1ZSxIVE1MSFJFbGVtZW50OnRydWUsSFRNTEhlYWRFbGVtZW50OnRydWUs
+SFRNTEhlYWRpbmdFbGVtZW50OnRydWUsSFRNTEh0bWxFbGVtZW50OnRydWUsSFRNTElGcmFtZUVsZW1l
+bnQ6dHJ1ZSxIVE1MSW1hZ2VFbGVtZW50OnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVlLEhUTUxMSUVs
+ZW1lbnQ6dHJ1ZSxIVE1MTGFiZWxFbGVtZW50OnRydWUsSFRNTExlZ2VuZEVsZW1lbnQ6dHJ1ZSxIVE1M
+TGlua0VsZW1lbnQ6dHJ1ZSxIVE1MTWFwRWxlbWVudDp0cnVlLEhUTUxNZWRpYUVsZW1lbnQ6dHJ1ZSxI
+VE1MTWVudUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0YUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0ZXJFbGVtZW50OnRy
+dWUsSFRNTE1vZEVsZW1lbnQ6dHJ1ZSxIVE1MT0xpc3RFbGVtZW50OnRydWUsSFRNTE9iamVjdEVsZW1l
+bnQ6dHJ1ZSxIVE1MT3B0R3JvdXBFbGVtZW50OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1M
+T3V0cHV0RWxlbWVudDp0cnVlLEhUTUxQYXJhbUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6
+dHJ1ZSxIVE1MUHJlRWxlbWVudDp0cnVlLEhUTUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVF
+bGVtZW50OnRydWUsSFRNTFNjcmlwdEVsZW1lbnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVlLEhU
+TUxTbG90RWxlbWVudDp0cnVlLEhUTUxTb3VyY2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50OnRy
+dWUsSFRNTFN0eWxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRNTFRh
+YmxlQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVI
+ZWFkZXJDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFF
+bGVtZW50OnRydWUsSFRNTFRpbWVFbGVtZW50OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxU
+cmFja0VsZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRy
+dWUsSFRNTFZpZGVvRWxlbWVudDp0cnVlLEhUTUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRF
+bGVtZW50OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxI
+VE1MTWFycXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVudDp0
+cnVlLEhUTUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsSFRN
+TEJvZHlFbGVtZW50OnRydWUsQ0RBVEFTZWN0aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENvbW1l
+bnQ6dHJ1ZSxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNsYXJh
+dGlvbjp0cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxYTUxE
+b2N1bWVudDp0cnVlLERvY3VtZW50OmZhbHNlLERPTUV4Y2VwdGlvbjp0cnVlLERPTUltcGxlbWVudGF0
+aW9uOnRydWUsRE9NUmVjdFJlYWRPbmx5OmZhbHNlLERPTVRva2VuTGlzdDp0cnVlLEVsZW1lbnQ6ZmFs
+c2UsQWJvcnRQYXltZW50RXZlbnQ6dHJ1ZSxBbmltYXRpb25FdmVudDp0cnVlLEFuaW1hdGlvblBsYXli
+YWNrRXZlbnQ6dHJ1ZSxBcHBsaWNhdGlvbkNhY2hlRXJyb3JFdmVudDp0cnVlLEJhY2tncm91bmRGZXRj
+aENsaWNrRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaEZh
+aWxFdmVudDp0cnVlLEJhY2tncm91bmRGZXRjaGVkRXZlbnQ6dHJ1ZSxCZWZvcmVJbnN0YWxsUHJvbXB0
+RXZlbnQ6dHJ1ZSxCZWZvcmVVbmxvYWRFdmVudDp0cnVlLEJsb2JFdmVudDp0cnVlLENhbk1ha2VQYXlt
+ZW50RXZlbnQ6dHJ1ZSxDbGlwYm9hcmRFdmVudDp0cnVlLENsb3NlRXZlbnQ6dHJ1ZSxDdXN0b21FdmVu
+dDp0cnVlLERldmljZU1vdGlvbkV2ZW50OnRydWUsRGV2aWNlT3JpZW50YXRpb25FdmVudDp0cnVlLEVy
+cm9yRXZlbnQ6dHJ1ZSxFeHRlbmRhYmxlRXZlbnQ6dHJ1ZSxFeHRlbmRhYmxlTWVzc2FnZUV2ZW50OnRy
+dWUsRmV0Y2hFdmVudDp0cnVlLEZvbnRGYWNlU2V0TG9hZEV2ZW50OnRydWUsRm9yZWlnbkZldGNoRXZl
+bnQ6dHJ1ZSxHYW1lcGFkRXZlbnQ6dHJ1ZSxIYXNoQ2hhbmdlRXZlbnQ6dHJ1ZSxJbnN0YWxsRXZlbnQ6
+dHJ1ZSxNZWRpYUVuY3J5cHRlZEV2ZW50OnRydWUsTWVkaWFLZXlNZXNzYWdlRXZlbnQ6dHJ1ZSxNZWRp
+YVF1ZXJ5TGlzdEV2ZW50OnRydWUsTWVkaWFTdHJlYW1FdmVudDp0cnVlLE1lZGlhU3RyZWFtVHJhY2tF
+dmVudDp0cnVlLE1lc3NhZ2VFdmVudDp0cnVlLE1JRElDb25uZWN0aW9uRXZlbnQ6dHJ1ZSxNSURJTWVz
+c2FnZUV2ZW50OnRydWUsTXV0YXRpb25FdmVudDp0cnVlLE5vdGlmaWNhdGlvbkV2ZW50OnRydWUsUGFn
+ZVRyYW5zaXRpb25FdmVudDp0cnVlLFBheW1lbnRSZXF1ZXN0RXZlbnQ6dHJ1ZSxQYXltZW50UmVxdWVz
+dFVwZGF0ZUV2ZW50OnRydWUsUG9wU3RhdGVFdmVudDp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25B
+dmFpbGFibGVFdmVudDp0cnVlLFByZXNlbnRhdGlvbkNvbm5lY3Rpb25DbG9zZUV2ZW50OnRydWUsUHJv
+bWlzZVJlamVjdGlvbkV2ZW50OnRydWUsUHVzaEV2ZW50OnRydWUsUlRDRGF0YUNoYW5uZWxFdmVudDp0
+cnVlLFJUQ0RUTUZUb25lQ2hhbmdlRXZlbnQ6dHJ1ZSxSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50OnRy
+dWUsUlRDVHJhY2tFdmVudDp0cnVlLFNlY3VyaXR5UG9saWN5VmlvbGF0aW9uRXZlbnQ6dHJ1ZSxTZW5z
+b3JFcnJvckV2ZW50OnRydWUsU3BlZWNoUmVjb2duaXRpb25FcnJvcjp0cnVlLFNwZWVjaFJlY29nbml0
+aW9uRXZlbnQ6dHJ1ZSxTcGVlY2hTeW50aGVzaXNFdmVudDp0cnVlLFN0b3JhZ2VFdmVudDp0cnVlLFN5
+bmNFdmVudDp0cnVlLFRyYWNrRXZlbnQ6dHJ1ZSxUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxXZWJLaXRUcmFu
+c2l0aW9uRXZlbnQ6dHJ1ZSxWUkRldmljZUV2ZW50OnRydWUsVlJEaXNwbGF5RXZlbnQ6dHJ1ZSxWUlNl
+c3Npb25FdmVudDp0cnVlLE1vam9JbnRlcmZhY2VSZXF1ZXN0RXZlbnQ6dHJ1ZSxVU0JDb25uZWN0aW9u
+RXZlbnQ6dHJ1ZSxJREJWZXJzaW9uQ2hhbmdlRXZlbnQ6dHJ1ZSxBdWRpb1Byb2Nlc3NpbmdFdmVudDp0
+cnVlLE9mZmxpbmVBdWRpb0NvbXBsZXRpb25FdmVudDp0cnVlLFdlYkdMQ29udGV4dEV2ZW50OnRydWUs
+RXZlbnQ6ZmFsc2UsSW5wdXRFdmVudDpmYWxzZSxTdWJtaXRFdmVudDpmYWxzZSxFdmVudFRhcmdldDpm
+YWxzZSxGaWxlOnRydWUsSFRNTEZvcm1FbGVtZW50OnRydWUsSGlzdG9yeTp0cnVlLEhUTUxEb2N1bWVu
+dDp0cnVlLFhNTEh0dHBSZXF1ZXN0OnRydWUsWE1MSHR0cFJlcXVlc3RFdmVudFRhcmdldDpmYWxzZSxJ
+bWFnZURhdGE6dHJ1ZSxMb2NhdGlvbjp0cnVlLE1vdXNlRXZlbnQ6dHJ1ZSxEcmFnRXZlbnQ6dHJ1ZSxQ
+b2ludGVyRXZlbnQ6dHJ1ZSxXaGVlbEV2ZW50OnRydWUsRG9jdW1lbnRGcmFnbWVudDp0cnVlLFNoYWRv
+d1Jvb3Q6dHJ1ZSxEb2N1bWVudFR5cGU6dHJ1ZSxOb2RlOmZhbHNlLE5vZGVMaXN0OnRydWUsUmFkaW9O
+b2RlTGlzdDp0cnVlLEhUTUxQYXJhZ3JhcGhFbGVtZW50OnRydWUsUHJvZ3Jlc3NFdmVudDp0cnVlLFJl
+c291cmNlUHJvZ3Jlc3NFdmVudDp0cnVlLEhUTUxTZWxlY3RFbGVtZW50OnRydWUsSFRNTFRhYmxlRWxl
+bWVudDp0cnVlLEhUTUxUYWJsZVJvd0VsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVTZWN0aW9uRWxlbWVudDp0
+cnVlLEhUTUxUZW1wbGF0ZUVsZW1lbnQ6dHJ1ZSxDb21wb3NpdGlvbkV2ZW50OnRydWUsRm9jdXNFdmVu
+dDp0cnVlLEtleWJvYXJkRXZlbnQ6dHJ1ZSxUZXh0RXZlbnQ6dHJ1ZSxUb3VjaEV2ZW50OnRydWUsVUlF
+dmVudDpmYWxzZSxXaW5kb3c6dHJ1ZSxET01XaW5kb3c6dHJ1ZSxEZWRpY2F0ZWRXb3JrZXJHbG9iYWxT
+Y29wZTp0cnVlLFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTp0cnVlLFNoYXJlZFdvcmtlckdsb2JhbFNj
+b3BlOnRydWUsV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxBdHRyOnRydWUsQ2xpZW50UmVjdDp0cnVlLERP
+TVJlY3Q6dHJ1ZSxOYW1lZE5vZGVNYXA6dHJ1ZSxNb3pOYW1lZEF0dHJNYXA6dHJ1ZSxJREJLZXlSYW5n
+ZTp0cnVlLFNWR1NjcmlwdEVsZW1lbnQ6dHJ1ZSxTVkdBRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVFbGVt
+ZW50OnRydWUsU1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlVHJhbnNmb3JtRWxl
+bWVudDp0cnVlLFNWR0FuaW1hdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdDaXJjbGVFbGVtZW50OnRydWUsU1ZH
+Q2xpcFBhdGhFbGVtZW50OnRydWUsU1ZHRGVmc0VsZW1lbnQ6dHJ1ZSxTVkdEZXNjRWxlbWVudDp0cnVl
+LFNWR0Rpc2NhcmRFbGVtZW50OnRydWUsU1ZHRWxsaXBzZUVsZW1lbnQ6dHJ1ZSxTVkdGRUJsZW5kRWxl
+bWVudDp0cnVlLFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OnRydWUsU1ZHRkVDb21wb25lbnRUcmFuc2Zl
+ckVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbnZvbHZlTWF0cml4
+RWxlbWVudDp0cnVlLFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxlbWVudDp0cnVlLFNWR0ZFRGlzcGxhY2Vt
+ZW50TWFwRWxlbWVudDp0cnVlLFNWR0ZFRGlzdGFudExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFRmxvb2RF
+bGVtZW50OnRydWUsU1ZHRkVGdW5jQUVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNCRWxlbWVudDp0cnVlLFNW
+R0ZFRnVuY0dFbGVtZW50OnRydWUsU1ZHRkVGdW5jUkVsZW1lbnQ6dHJ1ZSxTVkdGRUdhdXNzaWFuQmx1
+ckVsZW1lbnQ6dHJ1ZSxTVkdGRUltYWdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VFbGVtZW50OnRydWUs
+U1ZHRkVNZXJnZU5vZGVFbGVtZW50OnRydWUsU1ZHRkVNb3JwaG9sb2d5RWxlbWVudDp0cnVlLFNWR0ZF
+T2Zmc2V0RWxlbWVudDp0cnVlLFNWR0ZFUG9pbnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVNwZWN1bGFy
+TGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVTcG90TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVUaWxlRWxl
+bWVudDp0cnVlLFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6dHJ1ZSxTVkdGaWx0ZXJFbGVtZW50OnRydWUs
+U1ZHRm9yZWlnbk9iamVjdEVsZW1lbnQ6dHJ1ZSxTVkdHRWxlbWVudDp0cnVlLFNWR0dlb21ldHJ5RWxl
+bWVudDp0cnVlLFNWR0dyYXBoaWNzRWxlbWVudDp0cnVlLFNWR0ltYWdlRWxlbWVudDp0cnVlLFNWR0xp
+bmVFbGVtZW50OnRydWUsU1ZHTGluZWFyR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHTWFya2VyRWxlbWVu
+dDp0cnVlLFNWR01hc2tFbGVtZW50OnRydWUsU1ZHTWV0YWRhdGFFbGVtZW50OnRydWUsU1ZHUGF0aEVs
+ZW1lbnQ6dHJ1ZSxTVkdQYXR0ZXJuRWxlbWVudDp0cnVlLFNWR1BvbHlnb25FbGVtZW50OnRydWUsU1ZH
+UG9seWxpbmVFbGVtZW50OnRydWUsU1ZHUmFkaWFsR3JhZGllbnRFbGVtZW50OnRydWUsU1ZHUmVjdEVs
+ZW1lbnQ6dHJ1ZSxTVkdTZXRFbGVtZW50OnRydWUsU1ZHU3RvcEVsZW1lbnQ6dHJ1ZSxTVkdTdHlsZUVs
+ZW1lbnQ6dHJ1ZSxTVkdTVkdFbGVtZW50OnRydWUsU1ZHU3dpdGNoRWxlbWVudDp0cnVlLFNWR1N5bWJv
+bEVsZW1lbnQ6dHJ1ZSxTVkdUU3BhbkVsZW1lbnQ6dHJ1ZSxTVkdUZXh0Q29udGVudEVsZW1lbnQ6dHJ1
+ZSxTVkdUZXh0RWxlbWVudDp0cnVlLFNWR1RleHRQYXRoRWxlbWVudDp0cnVlLFNWR1RleHRQb3NpdGlv
+bmluZ0VsZW1lbnQ6dHJ1ZSxTVkdUaXRsZUVsZW1lbnQ6dHJ1ZSxTVkdVc2VFbGVtZW50OnRydWUsU1ZH
+Vmlld0VsZW1lbnQ6dHJ1ZSxTVkdHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdDb21wb25lbnRUcmFuc2Zl
+ckZ1bmN0aW9uRWxlbWVudDp0cnVlLFNWR0ZFRHJvcFNoYWRvd0VsZW1lbnQ6dHJ1ZSxTVkdNUGF0aEVs
+ZW1lbnQ6dHJ1ZSxTVkdFbGVtZW50OmZhbHNlfSkKSC5YSC4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJy
+YXlCdWZmZXJWaWV3IgpILlJHLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkgu
+VlAuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5EZy4kbmF0aXZlU3VwZXJj
+bGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILldCLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1
+ZmZlclZpZXciCkguWkcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5QZy4k
+bmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3In0pKCkKY29udmVydEFsbFRvRmFzdE9i
+amVjdCh3KQpjb252ZXJ0VG9GYXN0T2JqZWN0KCQpOyhmdW5jdGlvbihhKXtpZih0eXBlb2YgZG9jdW1l
+bnQ9PT0idW5kZWZpbmVkIil7YShudWxsKQpyZXR1cm59aWYodHlwZW9mIGRvY3VtZW50LmN1cnJlbnRT
+Y3JpcHQhPSd1bmRlZmluZWQnKXthKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpCnJldHVybn12YXIgcz1k
+b2N1bWVudC5zY3JpcHRzCmZ1bmN0aW9uIG9uTG9hZChiKXtmb3IodmFyIHE9MDtxPHMubGVuZ3RoOysr
+cSlzW3FdLnJlbW92ZUV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxmYWxzZSkKYShiLnRhcmdldCl9
+Zm9yKHZhciByPTA7cjxzLmxlbmd0aDsrK3Ipc1tyXS5hZGRFdmVudExpc3RlbmVyKCJsb2FkIixvbkxv
+YWQsZmFsc2UpfSkoZnVuY3Rpb24oYSl7di5jdXJyZW50U2NyaXB0PWEKaWYodHlwZW9mIGRhcnRNYWlu
+UnVubmVyPT09ImZ1bmN0aW9uIilkYXJ0TWFpblJ1bm5lcihMLklxLFtdKQplbHNlIEwuSXEoW10pfSl9
+KSgpCi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1pZ3JhdGlvbi5qcy5tYXAK
 ''';
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart b/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
index f37aa66..b416b03 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/edit_details.dart
@@ -174,7 +174,7 @@
         'description': description,
         if (function != null) 'function': function,
         if (link != null) 'link': link.toJson(),
-        if (!hintActions.isEmpty)
+        if (hintActions.isNotEmpty)
           'hintActions': hintActions.map((action) => action.toJson()).toList()
       };
 
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
index c80f4db..bbb473c 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
@@ -51,8 +51,12 @@
     rerunMigrationButton.onClick.listen((event) async {
       try {
         document.body.classes..add('rerunning');
-        await doPost('/rerun-migration');
-        window.location.reload();
+        var response = await doPost('/rerun-migration');
+        if (response['success'] as bool) {
+          window.location.reload();
+        } else {
+          handleRerunFailure(response['errors'] as List<Object>);
+        }
       } catch (e, st) {
         handleError('Failed to rerun migration', e, st);
       } finally {
@@ -168,7 +172,7 @@
       ..open('GET', pathWithQueryParameters(path, queryParameters), async: true)
       ..setRequestHeader('Content-Type', 'application/json; charset=UTF-8'));
 
-/// Perform a GET request on the path, return the json decoded response.
+/// Perform a POST request on the path, return the JSON-decoded response.
 Future<Map<String, Object>> doPost(String path, [Object body]) => doRequest(
     HttpRequest()
       ..open('POST', pathWithQueryParameters(path, {}), async: true)
@@ -183,7 +187,7 @@
 /// that case, though, because it may be an error response from the server with
 /// useful debugging information (stack trace etc).
 Future<T> doRequest<T>(HttpRequest xhr, [Object body]) async {
-  var completer = new Completer<HttpRequest>();
+  var completer = Completer<HttpRequest>();
   xhr.onLoad.listen((e) {
     completer.complete(xhr);
   });
@@ -288,6 +292,22 @@
   }
 }
 
+void handleRerunFailure(List<Object> errors) {
+  final popupPane = document.querySelector('.popup-pane');
+  popupPane.querySelector('h2').innerText = 'Failed to rerun from sources';
+  popupPane.querySelector('p').innerText =
+      'Sources contain static analysis errors:';
+  popupPane.querySelector('pre').innerText = errors.cast<Map>().map((error) {
+    return '${error['severity']} - ${error['message']} '
+        'at ${error['location']} - (${error['code']})';
+  }).join('\n');
+  popupPane.querySelector('a.bottom').style.display = 'none';
+  popupPane.style.display = 'initial';
+
+  // TODO(srawlins): I think we should lock down the entire web UI, except for
+  //  the "Rerun from source" button.
+}
+
 void handleError(String header, Object exception, Object stackTrace) {
   String subheader;
   if (exception is Map<String, Object> &&
@@ -303,8 +323,10 @@
   popupPane.querySelector('h2').innerText = header;
   popupPane.querySelector('p').innerText = subheader;
   popupPane.querySelector('pre').innerText = stackTrace.toString();
-  (popupPane.querySelector('a.bottom') as AnchorElement).href =
-      getGitHubErrorUri(header, subheader, stackTrace).toString();
+  var bottom = popupPane.querySelector('a.bottom') as AnchorElement;
+  bottom
+    ..href = getGitHubErrorUri(header, subheader, stackTrace).toString()
+    ..style.display = 'initial';
   popupPane..style.display = 'initial';
   logError('$header: $exception', stackTrace);
 }
@@ -780,7 +802,7 @@
                 loadFile(path, null, link.line, false);
                 document.body.classes.add('needs-rerun');
               } catch (e, st) {
-                handleError("Could not apply hint", e, st);
+                handleError('Could not apply hint', e, st);
               }
             })
             ..appendText(hintAction.kind.description));
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index 38a48e2..4a9aad9 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -73,7 +73,7 @@
   /// [removeViaComments]).
   NullabilityMigrationImpl(NullabilityMigrationListener listener,
       LineInfo Function(String) getLineInfo,
-      {bool permissive: false,
+      {bool permissive = false,
       NullabilityMigrationInstrumentation instrumentation,
       bool removeViaComments = false,
       bool warnOnWeakCode = true})
@@ -209,7 +209,7 @@
   static Location _computeLocation(
       LineInfo lineInfo, SourceEdit edit, Source source) {
     final locationInfo = lineInfo.getLocation(edit.offset);
-    var location = new Location(
+    var location = Location(
       source.fullName,
       edit.offset,
       edit.length,
diff --git a/pkg/nnbd_migration/lib/src/nullability_node.dart b/pkg/nnbd_migration/lib/src/nullability_node.dart
index 114b78f..e1bda51 100644
--- a/pkg/nnbd_migration/lib/src/nullability_node.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_node.dart
@@ -289,10 +289,10 @@
   /// Returns the edge created by the connection.
   NullabilityEdge connect(NullabilityNode sourceNode,
       NullabilityNode destinationNode, EdgeOrigin origin,
-      {bool hard: false,
+      {bool hard = false,
       bool checkable = true,
-      List<NullabilityNode> guards: const []}) {
-    var upstreamNodes = [sourceNode]..addAll(guards);
+      List<NullabilityNode> guards = const []}) {
+    var upstreamNodes = [sourceNode, ...guards];
     var kind = hard
         ? _NullabilityEdgeKind.hard
         : checkable
@@ -381,7 +381,7 @@
   /// Creates a graph edge that will try to force the given [node] to be
   /// non-nullable.
   NullabilityEdge makeNonNullable(NullabilityNode node, EdgeOrigin origin,
-      {bool hard: true, List<NullabilityNode> guards: const []}) {
+      {bool hard = true, List<NullabilityNode> guards = const []}) {
     return connect(node, never, origin, hard: hard, guards: guards);
   }
 
@@ -394,7 +394,7 @@
   /// Creates a graph edge that will try to force the given [node] to be
   /// nullable.
   void makeNullable(NullabilityNode node, EdgeOrigin origin,
-      {List<NullabilityNode> guards: const []}) {
+      {List<NullabilityNode> guards = const []}) {
     connect(always, node, origin, guards: guards);
   }
 
diff --git a/pkg/nnbd_migration/lib/src/potential_modification.dart b/pkg/nnbd_migration/lib/src/potential_modification.dart
index 08bf83e..3111a8e 100644
--- a/pkg/nnbd_migration/lib/src/potential_modification.dart
+++ b/pkg/nnbd_migration/lib/src/potential_modification.dart
@@ -42,7 +42,7 @@
           _KeepNode(node.thenElement),
           node.elseElement == null ? null : _KeepNode(node.elseElement));
     } else {
-      throw new UnimplementedError('TODO(paulberry)');
+      throw UnimplementedError('TODO(paulberry)');
     }
   }
 
diff --git a/pkg/nnbd_migration/lib/src/preview/preview_site.dart b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
index 42b087e..8d95d77 100644
--- a/pkg/nnbd_migration/lib/src/preview/preview_site.dart
+++ b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
@@ -219,7 +219,17 @@
       } else if (path == rerunMigrationPath) {
         await rerunMigration();
 
-        respondOk(request);
+        if (migrationState.hasErrors) {
+          return await respondJson(
+              request,
+              {
+                'success': false,
+                'errors': migrationState.analysisResult.toJson(),
+              },
+              HttpStatus.ok);
+        } else {
+          respondOk(request);
+        }
         return;
       } else if (path == applyHintPath) {
         final hintAction = HintAction.fromJson(await requestBodyJson(request));
diff --git a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
index ec45e53..020cdf4 100644
--- a/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/hint_utils.dart
@@ -142,7 +142,7 @@
   Map<int, List<AtomicEdit>> changesToRemove(String sourceText,
       {AtomicEditInfo info}) {
     bool appendSpace = false;
-    var removeOffset = this._removeOffset;
+    var removeOffset = _removeOffset;
     if (_isIdentifierCharBeforeOffset(sourceText, removeOffset) &&
         _isIdentifierCharAtOffset(sourceText, _removeEnd)) {
       if (sourceText[removeOffset] == ' ') {
diff --git a/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart b/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
index e8fdb4d..0e30a59 100644
--- a/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/multi_future_tracker.dart
@@ -33,7 +33,7 @@
   /// Maximum number of simultaneously incomplete [Future]s.
   final int parallel;
 
-  final Set<Future<void>> _trackedFutures = Set();
+  final Set<Future<void>> _trackedFutures = <Future<void>>{};
 
   MultiFutureTracker(this.parallel);
 
diff --git a/pkg/nnbd_migration/lib/src/utilities/permissive_mode.dart b/pkg/nnbd_migration/lib/src/utilities/permissive_mode.dart
index 1006efe..1d19c78 100644
--- a/pkg/nnbd_migration/lib/src/utilities/permissive_mode.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/permissive_mode.dart
@@ -20,7 +20,7 @@
 
   /// Executes [callback].  If [listener] is not `null`, and an exception
   /// occurs, the exception is caught and reported to the [listener].
-  void reportExceptionsIfPermissive(AstNode node, void callback()) {
+  void reportExceptionsIfPermissive(AstNode node, void Function() callback) {
     if (listener != null) {
       try {
         return callback();
diff --git a/pkg/nnbd_migration/lib/src/utilities/scoped_set.dart b/pkg/nnbd_migration/lib/src/utilities/scoped_set.dart
index 1169def..ea62206 100644
--- a/pkg/nnbd_migration/lib/src/utilities/scoped_set.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/scoped_set.dart
@@ -37,7 +37,7 @@
   /// before popping it.
   void doScoped(
       {List<T> elements = const [],
-      bool copyCurrent: false,
+      bool copyCurrent = false,
       void Function() action}) {
     pushScope(elements: elements, copyCurrent: copyCurrent);
     try {
@@ -59,7 +59,7 @@
 
   /// Begin a new scope, optionally with some known starting [elements], or
   /// copying the current scope, as a starting state.
-  void pushScope({List<T> elements = const [], bool copyCurrent: false}) =>
+  void pushScope({List<T> elements = const [], bool copyCurrent = false}) =>
       _scopeStack.add({
         ...elements,
         if (copyCurrent) ..._currentScope,
diff --git a/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart b/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
index 346b1e0..814525f 100644
--- a/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
+++ b/pkg/nnbd_migration/lib/src/utilities/subprocess_launcher.dart
@@ -38,7 +38,7 @@
   static Future<void> _printStream(Stream<List<int>> stream, Stdout output,
       {String prefix = '', Iterable<String> Function(String line) filter}) {
     assert(prefix != null);
-    if (filter == null) filter = (line) => [line];
+    filter ??= (line) => [line];
     return stream
         .transform(utf8.decoder)
         .transform(const LineSplitter())
@@ -52,7 +52,7 @@
   }
 
   SubprocessLauncher(this.context, [Map<String, String> environment])
-      : this.environmentDefaults = environment ?? <String, String>{};
+      : environmentDefaults = environment ?? <String, String>{};
 
   /// Wraps [runStreamedImmediate] as a closure around
   /// [maxParallel.addFutureFromClosure].
@@ -121,7 +121,7 @@
       Map result;
       try {
         result = json.decoder.convert(line) as Map;
-      } catch (FormatException) {
+      } on FormatException {
         // ignore
       }
       if (result != null) {
@@ -145,7 +145,7 @@
         if (environment[key].contains(quotables)) {
           return "$key='${environment[key]}'";
         } else {
-          return "$key=${environment[key]}";
+          return '$key=${environment[key]}';
         }
       }).join(' '));
       stderr.write(' ');
@@ -156,7 +156,7 @@
         if (arg.contains(quotables)) {
           stderr.write(" '$arg'");
         } else {
-          stderr.write(" $arg");
+          stderr.write(' $arg');
         }
       }
     }
@@ -193,7 +193,7 @@
     int exitCode = await process.exitCode;
     if (exitCode != 0 && !allowNonzeroExit) {
       throw ProcessException(executable, arguments,
-          "SubprocessLauncher got non-zero exitCode: $exitCode", exitCode);
+          'SubprocessLauncher got non-zero exitCode: $exitCode', exitCode);
     }
     return jsonObjects;
   }
diff --git a/pkg/nnbd_migration/pubspec.yaml b/pkg/nnbd_migration/pubspec.yaml
index e642a00..ac8b395 100644
--- a/pkg/nnbd_migration/pubspec.yaml
+++ b/pkg/nnbd_migration/pubspec.yaml
@@ -6,7 +6,7 @@
   sdk: '>=2.6.0 <3.0.0'
 dependencies:
   _fe_analyzer_shared: ^4.0.0
-  analyzer: ^0.40.1
+  analyzer: ^0.40.4
   analyzer_plugin: ^0.2.4
   args: ^1.4.4
   charcode: ^1.1.2
@@ -20,5 +20,6 @@
   yaml: ^2.1.15
 dev_dependencies:
   http: '>=0.11.3+17 <0.13.0'
+  pedantic: ^1.9.0
   test: ^1.6.4
   test_reflective_loader: ^0.1.8
diff --git a/pkg/nnbd_migration/test/abstract_context.dart b/pkg/nnbd_migration/test/abstract_context.dart
index f954485..d04f358 100644
--- a/pkg/nnbd_migration/test/abstract_context.dart
+++ b/pkg/nnbd_migration/test/abstract_context.dart
@@ -125,7 +125,7 @@
     setupResourceProvider();
     overlayResourceProvider = OverlayResourceProvider(resourceProvider);
 
-    new MockSdk(resourceProvider: resourceProvider);
+    MockSdk(resourceProvider: resourceProvider);
 
     newFolder(testsPath);
     newFile('$testsPath/.packages', content: '''
diff --git a/pkg/nnbd_migration/test/abstract_single_unit.dart b/pkg/nnbd_migration/test/abstract_single_unit.dart
index cfb022a..16f0f45 100644
--- a/pkg/nnbd_migration/test/abstract_single_unit.dart
+++ b/pkg/nnbd_migration/test/abstract_single_unit.dart
@@ -68,7 +68,7 @@
   void setUp() {
     var testRoot = AbstractContextTest.testsPath;
     if (analyzeWithNnbd) {
-      newFile(convertPath('$testRoot/analysis_options.yaml'), content: '''
+      newFile('$testRoot/analysis_options.yaml', content: '''
 analyzer:
   enable-experiment:
     - non-nullable
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index cbdf04c..2140235 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -49,13 +49,13 @@
     for (var path in input.keys) {
       newFile(path, content: input[path]);
     }
-    var listener = new TestMigrationListener();
+    var listener = TestMigrationListener();
     var migration = NullabilityMigration(listener, getLineInfo,
         permissive: _usePermissiveMode,
         removeViaComments: removeViaComments,
         warnOnWeakCode: warnOnWeakCode);
     for (var path in input.keys) {
-      if (!(await session.getFile(path)).isPart) {
+      if (!(session.getFile(path)).isPart) {
         for (var unit in (await session.getResolvedLibrary(path)).units) {
           migration.prepareInput(unit);
         }
@@ -63,7 +63,7 @@
     }
     _betweenStages();
     for (var path in input.keys) {
-      if (!(await session.getFile(path)).isPart) {
+      if (!(session.getFile(path)).isPart) {
         for (var unit in (await session.getResolvedLibrary(path)).units) {
           migration.processInput(unit);
         }
@@ -71,7 +71,7 @@
     }
     _betweenStages();
     for (var path in input.keys) {
-      if (!(await session.getFile(path)).isPart) {
+      if (!(session.getFile(path)).isPart) {
         for (var unit in (await session.getResolvedLibrary(path)).units) {
           migration.finalizeInput(unit);
         }
@@ -1710,7 +1710,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39609')
   Future<void> test_dynamic_dispatch_to_object_method() async {
     var content = '''
 String f(dynamic x) => x.toString();
@@ -1787,7 +1786,6 @@
     await _checkSingleFileChanges(content, expected);
   }
 
-  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/39609')
   Future<void> test_dynamic_toString() async {
     var content = '''
 String f(dynamic x) => x.toString();
@@ -4628,7 +4626,7 @@
   // here non-null is OK.
   int i1 = 0, i2 = i1.gcd(2);
   // here non-null is not OK.
-  int? i3 = 0, i4 = i3!.gcd(2), i5 = null;
+  int? i3 = 0, i4 = i3.gcd(2), i5 = null;
 }
 ''';
 
diff --git a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
index 46a5782..9683a92 100644
--- a/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_flow_analysis_test.dart
@@ -994,8 +994,7 @@
   f();
 }
 ''');
-    var fNode =
-        this.decoratedGenericFunctionTypeAnnotation('Function<T>() f').node;
+    var fNode = decoratedGenericFunctionTypeAnnotation('Function<T>() f').node;
     // No edge to never because it had been promoted before invoked.
     assertNoEdge(fNode, graph.never);
   }
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index ff8b433..8f9c943 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -41,7 +41,7 @@
 @reflectiveTest
 class AssignmentCheckerTest extends Object
     with EdgeTester, DecoratedTypeTester {
-  static const EdgeOrigin origin = const _TestEdgeOrigin();
+  static const EdgeOrigin origin = _TestEdgeOrigin();
 
   LibraryElementImpl _myLibrary;
 
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 6616c78..224da57 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -51,7 +51,7 @@
     return changes;
   }
 
-  void createPlanner({bool removeViaComments: false}) {
+  void createPlanner({bool removeViaComments = false}) {
     _planner = EditPlanner(testUnit.lineInfo, code,
         removeViaComments: removeViaComments);
   }
diff --git a/pkg/nnbd_migration/test/fix_builder_test.dart b/pkg/nnbd_migration/test/fix_builder_test.dart
index 010f005..4e3e6e9 100644
--- a/pkg/nnbd_migration/test/fix_builder_test.dart
+++ b/pkg/nnbd_migration/test/fix_builder_test.dart
@@ -3,13 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/element_type_provider.dart';
-import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:nnbd_migration/fix_reason_target.dart';
 import 'package:nnbd_migration/nnbd_migration.dart';
 import 'package:nnbd_migration/src/edit_plan.dart';
@@ -3364,10 +3362,8 @@
           identical(ElementTypeProvider.current, const ElementTypeProvider()));
       ElementTypeProvider.current = fixBuilder.migrationResolutionHooks;
       var assignment = node.thisOrAncestorOfType<AssignmentExpression>();
-      var isReadWrite = assignment.operator.type != TokenType.EQ;
-      var readType =
-          isReadWrite ? getReadType(node) ?? typeProvider.dynamicType : null;
-      var writeType = node.staticType;
+      var readType = assignment.readType;
+      var writeType = assignment.writeType;
       return AssignmentTargetInfo(readType, writeType);
     } finally {
       ElementTypeProvider.current = const ElementTypeProvider();
diff --git a/pkg/nnbd_migration/test/instrumentation_test.dart b/pkg/nnbd_migration/test/instrumentation_test.dart
index 1193181..19cfacf 100644
--- a/pkg/nnbd_migration/test/instrumentation_test.dart
+++ b/pkg/nnbd_migration/test/instrumentation_test.dart
@@ -122,7 +122,7 @@
 
   final List<EdgeInfo> edges = [];
 
-  Map<int, List<AtomicEdit>> changes = null;
+  Map<int, List<AtomicEdit>> changes;
 
   final Map<AstNode, DecoratedTypeInfo> implicitReturnType = {};
 
@@ -142,7 +142,7 @@
       {bool removeViaComments = false, bool warnOnWeakCode = true}) async {
     var sourcePath = convertPath('/home/test/lib/test.dart');
     newFile(sourcePath, content: content);
-    var listener = new TestMigrationListener();
+    var listener = TestMigrationListener();
     var migration = NullabilityMigration(listener, getLineInfo,
         instrumentation: _InstrumentationClient(this),
         removeViaComments: removeViaComments,
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
index cc7894d..e9393df 100644
--- a/pkg/nnbd_migration/test/migration_cli_test.dart
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -145,7 +145,7 @@
   NonNullableFix createNonNullableFix(
       DartFixListener listener,
       ResourceProvider resourceProvider,
-      LineInfo getLineInfo(String path),
+      LineInfo Function(String path) getLineInfo,
       Object bindAddress,
       {List<String> included = const <String>[],
       int preferredPort,
@@ -165,7 +165,7 @@
     }
   }
 
-  Future<void> runWithPreviewServer(Future<void> callback()) async {
+  Future<void> runWithPreviewServer(Future<void> Function() callback) async {
     _runWhilePreviewServerActive = callback;
     await run();
     if (_runWhilePreviewServerActive != null) {
@@ -192,7 +192,7 @@
 
   bool Function(String) overrideShouldBeMigrated;
 
-  void set logger(_TestLogger logger);
+  set logger(_TestLogger logger);
 
   _MockProcessManager get processManager;
 
@@ -389,7 +389,7 @@
   }
 
   Map<String, String> simpleProject(
-      {bool migrated: false,
+      {bool migrated = false,
       String sourceText,
       String pubspecText,
       String packageConfigText}) {
@@ -444,7 +444,7 @@
         'external bool operator ==(dynamic other)');
     expect(newCoreLibText, isNot(oldCoreLibText));
     coreLib.writeAsStringSync(newCoreLibText);
-    var projectDir = await createProjectDir(simpleProject());
+    var projectDir = createProjectDir(simpleProject());
     await assertRunFailure([projectDir], cli: cli);
     var output = logger.stdoutBuffer.toString();
     expect(output, contains(messages.sdkNnbdOff));
@@ -464,7 +464,7 @@
         'external bool operator ==(dynamic other)');
     expect(newCoreLibText, isNot(oldCoreLibText));
     coreLib.writeAsStringSync(newCoreLibText);
-    var projectDir = await createProjectDir(simpleProject());
+    var projectDir = createProjectDir(simpleProject());
     await assertRunFailure([projectDir], cli: cli);
     var output = logger.stdoutBuffer.toString();
     expect(output, contains(messages.sdkNnbdOff));
@@ -564,7 +564,7 @@
 
   test_lifecycle_apply_changes() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     var cliRunner = cli.decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
@@ -602,7 +602,7 @@
     - empty_constructor_bodies
 ''';
 
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli()
         .decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
     await cliRunner.run();
@@ -615,7 +615,7 @@
 
   test_lifecycle_contextdiscovery_handles_single() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli()
         .decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
     await cliRunner.run();
@@ -626,7 +626,7 @@
 
   test_lifecycle_exception_handling() async {
     var projectContents = simpleProject(sourceText: 'main() { print(0); }');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     injectArtificialException = true;
     await assertRunFailure([projectDir]);
     var errorOutput = logger.stderrBuffer.toString();
@@ -638,7 +638,7 @@
 
   test_lifecycle_exception_handling_ignore() async {
     var projectContents = simpleProject(sourceText: 'main() { print(0); }');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     injectArtificialException = true;
     var cli = _createCli();
     await runWithPreviewServer(cli, ['--ignore-exceptions', projectDir],
@@ -659,7 +659,7 @@
   test_lifecycle_exception_handling_multiple() async {
     var projectContents =
         simpleProject(sourceText: 'main() { print(0); print(1); }');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     injectArtificialException = true;
     await assertRunFailure([projectDir]);
     var errorOutput = logger.stderrBuffer.toString();
@@ -673,7 +673,7 @@
   test_lifecycle_exception_handling_with_error() async {
     var projectContents =
         simpleProject(sourceText: 'main() { print(0); unresolved; }');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     injectArtificialException = true;
     await assertRunFailure(['--ignore-errors', projectDir]);
     var errorOutput = logger.stderrBuffer.toString();
@@ -686,7 +686,7 @@
     var projectContents = simpleProject(sourceText: '''
 int f() => null
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     await assertRunFailure([projectDir]);
     var output = logger.stdoutBuffer.toString();
     expect(output, contains('1 analysis issue found'));
@@ -694,7 +694,7 @@
     expect(
         output,
         contains("error • Expected to find ';' at lib${sep}test.dart:1:12 • "
-            "(expected_token)"));
+            '(expected_token)'));
     expect(
         output,
         contains(
@@ -706,7 +706,7 @@
     var projectContents = simpleProject(sourceText: '''
 int? f() => null
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, ['--ignore-errors', projectDir],
         (url) async {
@@ -722,7 +722,7 @@
 
   test_lifecycle_no_preview() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli()
         .decodeCommandLineArgs(_parseArgs(['--no-web-preview', projectDir]));
     await cliRunner.run();
@@ -764,7 +764,7 @@
     }
 
     var projectContents = makeProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var testPath =
         resourceProvider.pathContext.join(projectDir, 'lib', 'test.dart');
     var analyzeButDoNotMigratePath = resourceProvider.pathContext
@@ -789,7 +789,7 @@
 
   test_lifecycle_preview() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       var localhostAddressText = Platform.environment.containsKey('FORCE_IPV6')
@@ -806,7 +806,7 @@
 
   test_lifecycle_preview_add_hint() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -835,7 +835,7 @@
 
   test_lifecycle_preview_apply_changes() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     bool applyHookCalled = false;
     cli._onApplyHook = () {
@@ -861,7 +861,7 @@
   }
 
   test_lifecycle_preview_extra_forward_slash() async {
-    var projectDir = await createProjectDir(simpleProject());
+    var projectDir = createProjectDir(simpleProject());
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       var uri = Uri.parse(url);
@@ -873,7 +873,7 @@
   test_lifecycle_preview_navigation_links() async {
     var projectContents = simpleProject(sourceText: 'int x;');
     projectContents['lib/src/test.dart'] = 'import "../test.dart"; int y = x;';
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -907,7 +907,7 @@
 
   test_lifecycle_preview_navigation_tree() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -940,7 +940,7 @@
 
   test_lifecycle_preview_on_host_any() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli()
       ..decodeCommandLineArgs(_parseArgs(['--preview-hostname=any']));
     await runWithPreviewServer(cli, [projectDir], (url) async {
@@ -953,7 +953,7 @@
 
   test_lifecycle_preview_region_link() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -994,7 +994,7 @@
 
   test_lifecycle_preview_region_table_path() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -1027,7 +1027,7 @@
   test_lifecycle_preview_rerun() async {
     var origSourceText = 'void f() {}';
     var projectContents = simpleProject(sourceText: origSourceText);
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       await assertPreviewServerResponsive(url);
@@ -1049,7 +1049,7 @@
 
   test_lifecycle_preview_rerun_added_file() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       await assertPreviewServerResponsive(url);
@@ -1072,7 +1072,7 @@
 
   test_lifecycle_preview_rerun_deleted_file() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     // Note: we use the summary to verify that the deletion was noticed
     var summaryPath = resourceProvider.convertPath('/summary.json');
@@ -1106,13 +1106,46 @@
     });
   }
 
+  test_lifecycle_preview_rerun_with_new_analysis_errors() async {
+    var origSourceText = 'void f(int i) {}';
+    var projectContents = simpleProject(sourceText: origSourceText);
+    var projectDir = createProjectDir(projectContents);
+    var cli = _createCli();
+    await runWithPreviewServer(cli, [projectDir], (url) async {
+      await assertPreviewServerResponsive(url);
+      var uri = Uri.parse(url);
+      var testPath =
+          resourceProvider.pathContext.join(projectDir, 'lib', 'test.dart');
+      var newSourceText = 'void f(int? i) {}';
+      resourceProvider.getFile(testPath).writeAsStringSync(newSourceText);
+      // We haven't rerun, so getting the file details from the server should
+      // still yield the original source text, with informational space.
+      expect(await getSourceFromServer(uri, testPath), 'void f(int  i) {}');
+      var response = await http.post(uri.replace(path: 'rerun-migration'),
+          headers: {'Content-Type': 'application/json; charset=UTF-8'});
+      assertHttpSuccess(response);
+      var body = jsonDecode(response.body);
+      expect(body['success'], isFalse);
+      expect(body['errors'], hasLength(1));
+      var error = body['errors'].single;
+      expect(error['severity'], equals('error'));
+      expect(
+          error['message'],
+          equals(
+              "This requires the 'non-nullable' language feature to be enabled"));
+      expect(error['location'],
+          equals(resourceProvider.pathContext.join('lib', 'test.dart:1:11')));
+      expect(error['code'], equals('experiment_not_enabled'));
+    });
+  }
+
   test_lifecycle_preview_serves_only_from_project_dir() async {
     var crazyFunctionName = 'crazyFunctionNameThatHasNeverBeenSeenBefore';
     var projectContents =
         simpleProject(sourceText: 'void $crazyFunctionName() {}');
-    var mainProjectDir = await createProjectDir(projectContents);
-    var otherProjectDir = await createProjectDir(projectContents,
-        posixPath: '/other_project_dir');
+    var mainProjectDir = createProjectDir(projectContents);
+    var otherProjectDir =
+        createProjectDir(projectContents, posixPath: '/other_project_dir');
     var cli = _createCli();
     await runWithPreviewServer(cli, [mainProjectDir], (url) async {
       await assertPreviewServerResponsive(url);
@@ -1141,7 +1174,7 @@
 
   test_lifecycle_preview_stack_hint_action() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -1176,7 +1209,7 @@
 
   test_lifecycle_preview_stacktrace_link() async {
     var projectContents = simpleProject(sourceText: 'int x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
@@ -1213,7 +1246,7 @@
     var projectContents = simpleProject(sourceText: '''
 int f() => null;
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     processManager._mockResult = ProcessResult(
         123 /* pid */,
         0 /* exitCode */,
@@ -1233,7 +1266,7 @@
     var projectContents = simpleProject(sourceText: '''
 int f() => null;
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     processManager._mockResult = ProcessResult(
         123 /* pid */,
         0 /* exitCode */,
@@ -1254,7 +1287,7 @@
 
   test_lifecycle_summary() async {
     var projectContents = simpleProject();
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var summaryPath = resourceProvider.convertPath('/summary.json');
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--summary', summaryPath, projectDir]));
@@ -1268,7 +1301,7 @@
 
   test_lifecycle_summary_does_not_double_count_hint_removals() async {
     var projectContents = simpleProject(sourceText: 'int/*?*/ x;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var summaryPath = resourceProvider.convertPath('/summary.json');
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--summary', summaryPath, projectDir]));
@@ -1283,7 +1316,7 @@
 
   test_lifecycle_summary_rewritten_upon_rerun() async {
     var projectContents = simpleProject(sourceText: 'int f(int/*?*/ i) => i;');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cli = _createCli();
     var summaryPath = resourceProvider.convertPath('/summary.json');
     await runWithPreviewServer(cli, ['--summary', summaryPath, projectDir],
@@ -1318,7 +1351,7 @@
 import 'package:does_not/exist.dart';
 int f() => null;
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     await assertRunFailure([projectDir]);
     var output = logger.stdoutBuffer.toString();
     expect(output, contains('1 analysis issue found'));
@@ -1431,7 +1464,7 @@
   test_package_config_does_not_exist() async {
     var projectContents = simpleProject()
       ..remove('.dart_tool/package_config.json');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1456,7 +1489,7 @@
 }
 ''';
     var projectContents = simpleProject(packageConfigText: packageConfigText);
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1474,7 +1507,7 @@
 }
 ''';
     var projectContents = simpleProject(packageConfigText: packageConfigText);
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1498,7 +1531,7 @@
 }
 ''';
     var projectContents = simpleProject(packageConfigText: packageConfigText);
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1639,7 +1672,7 @@
     var projectContents = simpleProject()
       ..remove('pubspec.yaml')
       ..remove('.dart_tool/package_config.json');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1657,7 +1690,7 @@
 environment:
   foo: 1
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1677,7 +1710,7 @@
 environment: 1
 ''';
     var projectContents = simpleProject(pubspecText: pubspecText);
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1694,7 +1727,7 @@
 ''';
     var projectContents = simpleProject(pubspecText: pubspecText)
       ..remove('.dart_tool/package_config.json');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1709,7 +1742,7 @@
     var projectContents = simpleProject(pubspecText: '''
 name: test
 ''');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     await cliRunner.run();
@@ -1726,7 +1759,7 @@
 
   test_pubspec_is_not_a_map() async {
     var projectContents = simpleProject(pubspecText: 'not-a-map');
-    var projectDir = await createProjectDir(projectContents);
+    var projectDir = createProjectDir(projectContents);
     var cliRunner = _createCli().decodeCommandLineArgs(
         _parseArgs(['--no-web-preview', '--apply-changes', projectDir]));
     expect(() async => await cliRunner.run(), throwsUnsupportedError);
@@ -1850,6 +1883,11 @@
   }
 
   @override
+  void trace(String message) {
+    throw UnimplementedError('TODO(paulberry)');
+  }
+
+  @override
   void write(String message) {
     stdoutBuffer.write(message);
   }
@@ -1858,9 +1896,4 @@
   void writeCharCode(int charCode) {
     stdoutBuffer.writeCharCode(charCode);
   }
-
-  @override
-  void trace(String message) {
-    throw UnimplementedError('TODO(paulberry)');
-  }
 }
diff --git a/pkg/nnbd_migration/test/migration_visitor_test_base.dart b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
index 3397d54..9fd3eeb 100644
--- a/pkg/nnbd_migration/test/migration_visitor_test_base.dart
+++ b/pkg/nnbd_migration/test/migration_visitor_test_base.dart
@@ -210,7 +210,7 @@
       Object guards = isEmpty,
       Object codeReference}) {
     var edges = getEdges(source, destination);
-    if (edges.length == 0) {
+    if (edges.isEmpty) {
       fail('Expected edge $source -> $destination, found none');
     } else if (edges.length != 1) {
       fail('Found multiple edges $source -> $destination');
diff --git a/pkg/nnbd_migration/test/test_all.dart b/pkg/nnbd_migration/test/test_all.dart
index 0be5fd9..b82bafb 100644
--- a/pkg/nnbd_migration/test/test_all.dart
+++ b/pkg/nnbd_migration/test/test_all.dart
@@ -20,6 +20,7 @@
 import 'fix_reason_target_test.dart' as fix_reason_target_test;
 import 'front_end/test_all.dart' as front_end;
 import 'instrumentation_test.dart' as instrumentation_test;
+import 'migration_cli_test.dart' as migration_cli_test;
 import 'node_builder_test.dart' as node_builder_test;
 import 'nullability_node_test.dart' as nullability_node_test;
 import 'preview/test_all.dart' as preview;
@@ -41,6 +42,7 @@
     fix_reason_target_test.main();
     front_end.main();
     instrumentation_test.main();
+    migration_cli_test.main();
     node_builder_test.main();
     nullability_node_test.main();
     preview.main();
diff --git a/pkg/nnbd_migration/tool/codegen/generate_resources.dart b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
index e1a9c86..43c9356 100644
--- a/pkg/nnbd_migration/tool/codegen/generate_resources.dart
+++ b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
@@ -88,7 +88,7 @@
   return lines.join('\n');
 }
 
-void compileWebFrontEnd({bool devMode = false}) async {
+Future<void> compileWebFrontEnd({bool devMode = false}) async {
   var sdkBinDir = path.dirname(Platform.resolvedExecutable);
   var dart2jsBinary = Platform.isWindows ? 'dart2js.bat' : 'dart2js';
   var dart2jsPath = path.join(sdkBinDir, dart2jsBinary);
diff --git a/pkg/nnbd_migration/tool/src/package.dart b/pkg/nnbd_migration/tool/src/package.dart
index 612d9cd..d8dd458 100644
--- a/pkg/nnbd_migration/tool/src/package.dart
+++ b/pkg/nnbd_migration/tool/src/package.dart
@@ -113,7 +113,7 @@
     return pathParts[indexOfName];
   }
 
-  static RegExp _pathAndPeriodSplitter = new RegExp('[\\/.]');
+  static final RegExp _pathAndPeriodSplitter = RegExp('[\\/.]');
 
   /// Initialize the package with a shallow clone.  Run only once per
   /// [GitPackage] instance.
@@ -171,7 +171,7 @@
 /// Abstraction for a package located within pkg or third_party/pkg.
 class SdkPackage extends Package {
   /// Where to find packages.  Constructor searches in-order.
-  static List<String> _searchPaths = [
+  static final List<String> _searchPaths = [
     'pkg',
     path.join('third_party', 'pkg'),
   ];
@@ -183,8 +183,9 @@
         _packagePath = potentialPath;
       }
     }
-    if (_packagePath == null)
+    if (_packagePath == null) {
       throw ArgumentError('Package $name not found in SDK');
+    }
   }
 
   /* late final */ String _packagePath;
diff --git a/pkg/nnbd_migration/tool/trial_migration.dart b/pkg/nnbd_migration/tool/trial_migration.dart
index e7bc2b6..616a5c2 100644
--- a/pkg/nnbd_migration/tool/trial_migration.dart
+++ b/pkg/nnbd_migration/tool/trial_migration.dart
@@ -222,7 +222,7 @@
   final List<MapEntry<String, int>> exceptionCountPerPackage;
 
   ExceptionCategory(this.topOfStack, Map<String, int> exceptions)
-      : this.exceptionCountPerPackage = exceptions.entries.toList()
+      : exceptionCountPerPackage = exceptions.entries.toList()
           ..sort((e1, e2) => e2.value.compareTo(e1.value));
 
   int get count => exceptionCountPerPackage.length;
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 70955b1..6391890 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -85,7 +85,7 @@
 front_end/test/fasta/text_serialization_test: Pass, ExtraSlow
 front_end/test/fasta/types/dart2js_benchmark_test: Pass, Slow
 front_end/test/fasta/types/large_app_benchmark_test: Pass, ExtraSlow
-front_end/test/incremental_compiler_leak_test: Pass, Slow
+front_end/test/incremental_compiler_leak_test: Pass, ExtraSlow
 front_end/test/incremental_dart2js_test: Pass, Slow
 front_end/test/minimal_incremental_kernel_generator_test: Slow, Pass
 front_end/testcases/*: Skip # These are not tests but input for tests.
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 64996c0..4c953dd 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -1249,10 +1249,12 @@
 
 class FastaCommandOutput extends CompilationCommandOutput
     with _StaticErrorOutput {
-  static void parseErrors(String stdout, List<StaticError> errors,
-      [List<StaticError> warnings]) {
+  static void parseErrors(
+      String stdout, List<StaticError> errors, List<StaticError> warnings) {
     _StaticErrorOutput._parseCfeErrors(
         ErrorSource.cfe, _errorRegexp, stdout, errors);
+    _StaticErrorOutput._parseCfeErrors(
+        ErrorSource.cfe, _warningRegexp, stdout, warnings);
   }
 
   /// Matches the first line of a Fasta error message. Fasta prints errors to
@@ -1268,6 +1270,19 @@
   static final _errorRegexp =
       RegExp(r"^([^:]+):(\d+):(\d+): Error: (.*)$", multiLine: true);
 
+  /// Matches the first line of a Fasta warning message. Fasta prints errors to
+  /// stdout that look like:
+  ///
+  ///     tests/language_2/some_test.dart:7:21: Warning: Some message.
+  ///     Try fixing the code to be less bad.
+  ///       var _ = <int>[if (1) 2];
+  ///                    ^
+  ///
+  /// The test runner only validates the main error message, and not the
+  /// suggested fixes, so we only parse the first line.
+  static final _warningRegexp =
+      RegExp(r"^([^:]+):(\d+):(\d+): Warning: (.*)$", multiLine: true);
+
   FastaCommandOutput(
       Command command,
       int exitCode,
@@ -1282,8 +1297,10 @@
   @override
   void _parseErrors() {
     var errors = <StaticError>[];
-    parseErrors(decodeUtf8(stdout), errors);
+    var warnings = <StaticError>[];
+    parseErrors(decodeUtf8(stdout), errors, warnings);
     errors.forEach(addError);
+    warnings.forEach(addWarning);
   }
 }
 
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 6b08ea0..4698cc2 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -25,12 +25,30 @@
 /// list allows the result of calling this to be spread into another list.
 List<String> _experimentsArgument(
     TestConfiguration configuration, TestFile testFile) {
-  if (configuration.experiments.isEmpty && testFile.experiments.isEmpty) {
+  var experiments = {
+    ...configuration.experiments,
+    ...testFile.experiments,
+    if (configuration.nnbdMode != NnbdMode.legacy)
+      'non-nullable',
+  };
+  if (experiments.isEmpty) {
     return const [];
   }
 
-  var experiments = {...configuration.experiments, ...testFile.experiments};
-  return ["--enable-experiment=${experiments.join(',')}"];
+  return ['--enable-experiment=${experiments.join(',')}'];
+}
+
+List<String> _nnbdModeArgument(TestConfiguration configuration) {
+  switch (configuration.nnbdMode) {
+    case NnbdMode.legacy:
+      return [];
+    case NnbdMode.strong:
+      return ['--sound-null-safety'];
+    case NnbdMode.weak:
+      return ['--no-sound-null-safety'];
+  }
+
+  throw 'unreachable';
 }
 
 /// Grouping of a command with its expected result.
@@ -175,6 +193,7 @@
       else if (_configuration.hotReloadRollback)
         '--hot-reload-rollback-test-mode',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -221,6 +240,7 @@
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...args
     ];
   }
@@ -245,6 +265,7 @@
       else if (_configuration.hotReloadRollback)
         '--hot-reload-rollback-test-mode',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -426,13 +447,18 @@
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
       ...testFile.dart2jsOptions,
+      ..._nnbdModeArgument(_configuration),
       ...args
     ];
   }
 
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
-    var compilerArguments = [...arguments, ..._configuration.dart2jsOptions];
+    var compilerArguments = [
+      ...arguments,
+      ..._configuration.dart2jsOptions,
+      ..._nnbdModeArgument(_configuration),
+    ];
 
     // TODO(athom): input filename extraction is copied from DDC. Maybe this
     // should be passed to computeCompilationArtifact, instead?
@@ -729,9 +755,14 @@
   static const String ndkPath = "third_party/android_tools/ndk";
   String get abiTriple => _isArm || _isArmX64
       ? "arm-linux-androideabi"
-      : _isArm64 ? "aarch64-linux-android" : null;
-  String get host =>
-      Platform.isLinux ? "linux" : Platform.isMacOS ? "darwin" : null;
+      : _isArm64
+          ? "aarch64-linux-android"
+          : null;
+  String get host => Platform.isLinux
+      ? "linux"
+      : Platform.isMacOS
+          ? "darwin"
+          : null;
 
   Command computeAssembleCommand(String tempDir, List arguments,
       Map<String, String> environmentOverrides) {
@@ -853,6 +884,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -900,6 +932,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -917,6 +950,7 @@
     return [
       if (_enableAsserts) '--enable_asserts',
       ...vmOptions,
+      ..._nnbdModeArgument(_configuration),
       ...testFile.sharedOptions,
       ..._configuration.sharedOptions,
       ..._experimentsArgument(_configuration, testFile),
@@ -958,7 +992,7 @@
       "ffi_2",
       "language_2",
       "lib_2",
-      "service",
+      "service_2",
       "standalone_2"
     };
 
@@ -1104,6 +1138,7 @@
           arguments.contains('--enable-asserts') ||
           arguments.contains('--enable_asserts'))
         '--enable-asserts',
+      ..._nnbdModeArgument(_configuration),
       ..._configuration.genKernelOptions,
     ];
 
diff --git a/pkg/test_runner/lib/src/environment.dart b/pkg/test_runner/lib/src/environment.dart
index f012f12..4d90271 100644
--- a/pkg/test_runner/lib/src/environment.dart
+++ b/pkg/test_runner/lib/src/environment.dart
@@ -30,6 +30,7 @@
   "jscl": _Variable.bool((c) => c.runtime.isJSCommandLine),
   "minified": _Variable.bool((c) => c.isMinified),
   "mode": _Variable((c) => c.mode.name, Mode.names),
+  "nnbd": _Variable((TestConfiguration c) => c.nnbdMode.name, NnbdMode.names),
   "runtime": _Variable(_runtimeName, _runtimeNames),
   "spec_parser": _Variable.bool((c) => c.compiler == Compiler.specParser),
   "system": _Variable(_systemName, _systemNames),
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 3ebeaee..e0c78fc 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -24,9 +24,9 @@
   'utils',
   'lib_2',
   'analyze_library',
-  'service',
+  'service_2',
   'kernel',
-  'observatory_ui',
+  'observatory_ui_2',
   'ffi_2'
 ];
 
@@ -448,13 +448,24 @@
         // option. Use it as a test selector pattern.
         var patterns = options.putIfAbsent("selectors", () => <String>[]);
 
+        var allSuiteDirectories = [
+          ...testSuiteDirectories,
+          "tests/co19",
+          "tests/co19_2",
+        ];
         // Allow passing in the full relative path to a test or directory and
         // infer the selector from it. This lets users use tab completion on
         // the command line.
-        for (var suiteDirectory in testSuiteDirectories) {
+        for (var suiteDirectory in allSuiteDirectories) {
           var path = suiteDirectory.toString();
           if (arg.startsWith("$path/") || arg.startsWith("$path\\")) {
             arg = arg.substring(path.lastIndexOf("/") + 1);
+
+            // Remove the `src/` subdirectories from the co19 and co19_2
+            // directories that do not appear in the test names.
+            if (arg.startsWith("co19")) {
+              arg = arg.replaceFirst(RegExp("src[/\]"), "");
+            }
             break;
           }
         }
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index dbd8d79..36024d9 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -31,6 +31,8 @@
   Path('runtime/tests/vm'),
   Path('runtime/observatory/tests/service'),
   Path('runtime/observatory/tests/observatory_ui'),
+  Path('runtime/observatory_2/tests/service_2'),
+  Path('runtime/observatory_2/tests/observatory_ui_2'),
   Path('samples'),
   Path('samples-dev'),
   Path('tests/corelib'),
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index 02d1f3e..400f88b 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -583,7 +583,7 @@
       _enqueueStandardTest(testFile, expectationSet, onTest);
     } else if (configuration.runtime.isBrowser) {
       _enqueueBrowserTest(testFile, expectationSet, onTest);
-    } else if (suiteName == 'service') {
+    } else if (suiteName == 'service' || suiteName == 'service_2') {
       _enqueueServiceTest(testFile, expectationSet, onTest);
     } else {
       _enqueueStandardTest(testFile, expectationSet, onTest);
@@ -678,7 +678,7 @@
       for (var name in testFile.otherResources) {
         var namePath = Path(name);
         var fromPath = testFile.path.directoryPath.join(namePath);
-        File('$tempDir/$name').parent.createSync(recursive: true);
+        File('$tempDir/$name').createSync(recursive: true);
         File(fromPath.toNativePath()).copySync('$tempDir/$name');
       }
     }
diff --git a/pkg/test_runner/tool/update_static_error_tests.dart b/pkg/test_runner/tool/update_static_error_tests.dart
index de25ab3..6b7379a 100644
--- a/pkg/test_runner/tool/update_static_error_tests.dart
+++ b/pkg/test_runner/tool/update_static_error_tests.dart
@@ -19,9 +19,9 @@
 const _usage =
     "Usage: dart update_static_error_tests.dart [flags...] <path glob>";
 
-final _dartPath = _findBinary("dart");
-final _analyzerPath = _findBinary("dartanalyzer");
-final _dart2jsPath = _findBinary("dart2js");
+final _dartPath = _findBinary("dart", "exe");
+final _analyzerPath = _findBinary("dartanalyzer", "bat");
+final _dart2jsPath = _findBinary("dart2js", "bat");
 
 Future<void> main(List<String> args) async {
   var sources = ErrorSource.all.map((e) => e.marker).toList();
@@ -268,8 +268,9 @@
     return null;
   }
   var errors = <StaticError>[];
-  FastaCommandOutput.parseErrors(result.stdout as String, errors);
-  return errors;
+  var warnings = <StaticError>[];
+  FastaCommandOutput.parseErrors(result.stdout as String, errors, warnings);
+  return [...errors, ...warnings];
 }
 
 /// Invoke dart2js on [path] and gather all static errors it reports.
@@ -301,8 +302,8 @@
 }
 
 /// Find the most recently-built [binary] in any of the build directories.
-String _findBinary(String binary) {
-  if (Platform.isWindows) binary += ".bat";
+String _findBinary(String name, String windowsExtension) {
+  String binary = Platform.isWindows ? "$name.$windowsExtension" : name;
 
   String newestPath;
   DateTime newestTime;
@@ -310,13 +311,13 @@
   var buildDirectory = Directory(Platform.isMacOS ? "xcodebuild" : "out");
   if (buildDirectory.existsSync()) {
     for (var config in buildDirectory.listSync()) {
-      var analyzerPath = p.join(config.path, "dart-sdk", "bin", binary);
-      var analyzerFile = File(analyzerPath);
-      if (!analyzerFile.existsSync()) continue;
-      var modified = analyzerFile.lastModifiedSync();
+      var path = p.join(config.path, "dart-sdk", "bin", binary);
+      var file = File(path);
+      if (!file.existsSync()) continue;
+      var modified = file.lastModifiedSync();
 
       if (newestTime == null || modified.isAfter(newestTime)) {
-        newestPath = analyzerPath;
+        newestPath = path;
         newestTime = modified;
       }
     }
diff --git a/pkg/testing/lib/src/chain.dart b/pkg/testing/lib/src/chain.dart
index e51bcb4..a6c982d 100644
--- a/pkg/testing/lib/src/chain.dart
+++ b/pkg/testing/lib/src/chain.dart
@@ -354,7 +354,12 @@
 
   final List<String> logs = <String>[];
 
-  Result(this.output, this.outcome, this.error, this.trace);
+  /// If set, running the test with '-D$autoFixCommand' will automatically
+  /// update the test to match new expectations.
+  final String autoFixCommand;
+
+  Result(this.output, this.outcome, this.error, this.trace,
+      {this.autoFixCommand});
 
   Result.pass(O output) : this(output, Expectation.Pass, null, null);
 
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index c30f096..9b247c9 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -533,6 +533,7 @@
   static const hasCustomScriptFlag = 1 << 22;
   static const hasAttributesFlag = 1 << 23;
   static const isExtensionMemberFlag = 1 << 24;
+  static const hasParameterFlagsFlag = 1 << 25;
 
   final int flags;
   final ObjectHandle name;
@@ -542,6 +543,8 @@
   final TypeParametersDeclaration typeParameters;
   final int numRequiredParameters;
   final List<ParameterDeclaration> parameters;
+  // Only contains the required flag for parameters when present.
+  final List<int> parameterFlags;
   final ObjectHandle returnType;
   final ObjectHandle nativeName;
   final Code code;
@@ -557,6 +560,7 @@
       this.typeParameters,
       this.numRequiredParameters,
       this.parameters,
+      this.parameterFlags,
       this.returnType,
       this.nativeName,
       this.code,
@@ -584,6 +588,10 @@
     for (var param in parameters) {
       param.write(writer);
     }
+    if ((flags & hasParameterFlagsFlag) != 0) {
+      writer.writePackedUInt30(parameterFlags.length);
+      parameterFlags.forEach((flags) => writer.writePackedUInt30(flags));
+    }
     writer.writePackedObject(returnType);
     if ((flags & isNativeFlag) != 0) {
       writer.writePackedObject(nativeName);
@@ -624,6 +632,10 @@
 
     final parameters = new List<ParameterDeclaration>.generate(
         numParameters, (_) => new ParameterDeclaration.read(reader));
+    final parameterFlags = ((flags & hasParameterFlagsFlag) != 0)
+        ? List<int>.generate(
+            reader.readPackedUInt30(), (_) => reader.readPackedUInt30())
+        : null;
     final returnType = reader.readPackedObject();
     final nativeName =
         ((flags & isNativeFlag) != 0) ? reader.readPackedObject() : null;
@@ -643,6 +655,7 @@
         typeParameters,
         numRequiredParameters,
         parameters,
+        parameterFlags,
         returnType,
         nativeName,
         code,
@@ -725,6 +738,9 @@
       sb.write('    type-params $typeParameters\n');
     }
     sb.write('    parameters $parameters (required: $numRequiredParameters)\n');
+    if ((flags & hasParameterFlagsFlag) != 0) {
+      sb.write('    parameter-flags $parameterFlags\n');
+    }
     sb.write('    return-type $returnType\n');
     if ((flags & hasAnnotationsFlag) != 0) {
       sb.write('    annotations $annotations\n');
@@ -820,6 +836,8 @@
   final LocalVariableTable localVariables;
   final List<ObjectHandle> nullableFields;
   final List<ClosureDeclaration> closures;
+  // Contains all parameter flags except for the required flags, which are
+  // kept instead in the FunctionDeclaration and ClosureDeclaration.
   final List<int> parameterFlags;
   final int forwardingStubTargetCpIndex;
   final int defaultFunctionTypeArgsCpIndex;
@@ -983,6 +1001,7 @@
   final int numRequiredParams;
   final int numNamedParams;
   final List<NameAndType> parameters;
+  // Only contains the required flag for parameters when present.
   final List<int> parameterFlags;
   final ObjectHandle returnType;
   ObjectHandle attributes;
@@ -1105,6 +1124,21 @@
         attributes);
   }
 
+  void _writeParamsToBuffer(
+      StringBuffer sb, List<NameAndType> params, List<int> flags) {
+    assert(flags == null || (params.length == flags.length));
+    for (int i = 0; i < params.length; i++) {
+      if (i != 0) {
+        sb.write(', ');
+      }
+      // We only store the required flag for ClosureDeclarations.
+      if (flags != null && flags[i] != 0) {
+        sb.write('required ');
+      }
+      sb.write(params[i]);
+    }
+  }
+
   @override
   String toString() {
     final StringBuffer sb = new StringBuffer();
@@ -1125,16 +1159,22 @@
       sb.write(' <${typeParams.join(', ')}>');
     }
     sb.write(' (');
-    sb.write(parameters.sublist(0, numRequiredParams).join(', '));
+    final requiredFlags = (flags & hasParameterFlagsFlag) != 0
+        ? parameterFlags.sublist(0, numRequiredParams)
+        : null;
+    _writeParamsToBuffer(
+        sb, parameters.sublist(0, numRequiredParams), requiredFlags);
     if (numRequiredParams != parameters.length) {
       if (numRequiredParams > 0) {
         sb.write(', ');
       }
-      if (numNamedParams > 0) {
-        sb.write('{ ${parameters.sublist(numRequiredParams).join(', ')} }');
-      } else {
-        sb.write('[ ${parameters.sublist(numRequiredParams).join(', ')} ]');
-      }
+      sb.write(numNamedParams > 0 ? '{ ' : '[ ');
+      final optionalFlags = (flags & hasParameterFlagsFlag) != 0
+          ? parameterFlags.sublist(numRequiredParams)
+          : null;
+      _writeParamsToBuffer(
+          sb, parameters.sublist(numRequiredParams), optionalFlags);
+      sb.write(numNamedParams > 0 ? ' }' : ' ]');
     }
     sb.write(') -> ');
     sb.writeln(returnType);
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index e2ddd4d..94a02db 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -794,6 +794,12 @@
     for (var param in function.namedParameters) {
       parameters.add(getParameterDeclaration(param));
     }
+    // We only need the required flags when loading the function declaration.
+    final parameterFlags =
+        getParameterFlags(function, mask: ParameterDeclaration.isRequiredFlag);
+    if (parameterFlags != null) {
+      flags |= FunctionDeclaration.hasParameterFlagsFlag;
+    }
 
     return new FunctionDeclaration(
         flags,
@@ -804,6 +810,7 @@
         typeParameters,
         function.requiredParameterCount,
         parameters,
+        parameterFlags,
         objectTable.getHandle(function.returnType),
         nativeName,
         code,
@@ -857,8 +864,11 @@
     return new ParameterDeclaration(nameHandle, typeHandle);
   }
 
-  List<int> getParameterFlags(FunctionNode function) {
-    int getFlags(VariableDeclaration variable) {
+  // Most uses of parameter flags in the VM only nee a subset of the flags,
+  // so the optional [mask] argument allows the caller to specify the subset
+  // that should be retained.
+  List<int> getParameterFlags(FunctionNode function, {int mask = -1}) {
+    int getFlags(VariableDeclaration variable, int mask) {
       int flags = 0;
       if (variable.isCovariant) {
         flags |= ParameterDeclaration.isCovariantFlag;
@@ -872,15 +882,15 @@
       if (variable.isRequired) {
         flags |= ParameterDeclaration.isRequiredFlag;
       }
-      return flags;
+      return flags & mask;
     }
 
     final List<int> paramFlags = <int>[];
     for (var param in function.positionalParameters) {
-      paramFlags.add(getFlags(param));
+      paramFlags.add(getFlags(param, mask));
     }
     for (var param in function.namedParameters) {
-      paramFlags.add(getFlags(param));
+      paramFlags.add(getFlags(param, mask));
     }
 
     for (int flags in paramFlags) {
@@ -1600,7 +1610,7 @@
       return;
     }
     if (condition is MethodInvocation &&
-        condition.name.name == '==' &&
+        condition.name.text == '==' &&
         (condition.receiver is NullLiteral ||
             condition.arguments.positional.single is NullLiteral)) {
       if (condition.receiver is NullLiteral) {
@@ -1625,8 +1635,7 @@
     if (condition is Not) {
       _genConditionAndJumpIf(condition.operand, !value, dest);
     } else if (condition is LogicalExpression) {
-      assert(condition.operator == '||' || condition.operator == '&&');
-      final isOR = (condition.operator == '||');
+      final isOR = (condition.operatorEnum == LogicalExpressionOperator.OR);
 
       Label shortCircuit, done;
       if (isOR == value) {
@@ -1845,7 +1854,7 @@
 
   // Generate additional code for 'operator ==' to handle nulls.
   void _genEqualsOperatorNullHandling(Member member) {
-    if (member.name.name != '==' ||
+    if (member.name.text != '==' ||
         locals.numParameters != 2 ||
         member.enclosingClass == coreTypes.objectClass) {
       return;
@@ -1880,10 +1889,16 @@
         int forwardingStubTargetCpIndex = null;
         int defaultFunctionTypeArgsCpIndex = null;
 
+        // We don't need the required flag when loading the code, but do need
+        // all other parameter flags.
+        final parameterFlagMask = ~ParameterDeclaration.isRequiredFlag;
+
         if (node is Constructor) {
-          parameterFlags = getParameterFlags(node.function);
+          parameterFlags =
+              getParameterFlags(node.function, mask: parameterFlagMask);
         } else if (node is Procedure) {
-          parameterFlags = getParameterFlags(node.function);
+          parameterFlags =
+              getParameterFlags(node.function, mask: parameterFlagMask);
 
           if (node.isForwardingStub) {
             forwardingStubTargetCpIndex =
@@ -2657,7 +2672,9 @@
       flags |= ClosureDeclaration.hasTypeParamsFlag;
     }
 
-    final List<int> parameterFlags = getParameterFlags(function);
+    // We only need the required flags when loading the closure declaration.
+    final parameterFlags =
+        getParameterFlags(function, mask: ParameterDeclaration.isRequiredFlag);
     if (parameterFlags != null) {
       flags |= ClosureDeclaration.hasParameterFlagsFlag;
     }
@@ -2911,8 +2928,7 @@
       (expr is VariableSet ||
           expr is PropertySet ||
           expr is StaticSet ||
-          expr is SuperPropertySet ||
-          expr is DirectPropertySet);
+          expr is SuperPropertySet);
 
   void _createArgumentsArray(int temp, List<DartType> typeArgs,
       List<Expression> args, bool storeLastArgumentToTemp) {
@@ -3058,55 +3074,6 @@
   }
 
   @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    final args = node.arguments;
-    _genArguments(node.receiver, args);
-    final target = node.target;
-    if (target is Procedure && !target.isGetter && !target.isSetter) {
-      _genDirectCallWithArgs(target, args, hasReceiver: true, node: node);
-    } else {
-      throw new UnsupportedOperationError(
-          'Unsupported DirectMethodInvocation with target ${target.runtimeType} $target');
-    }
-  }
-
-  @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    _generateNode(node.receiver);
-    final target = node.target;
-    if (target is Field || (target is Procedure && target.isGetter)) {
-      _genDirectCall(target, objectTable.getArgDescHandle(1), 1,
-          isGet: true, node: node);
-    } else {
-      throw new UnsupportedOperationError(
-          'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
-    }
-  }
-
-  @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    final int temp = locals.tempIndexInFrame(node);
-    final bool hasResult = !isExpressionWithoutResult(node);
-
-    _generateNode(node.receiver);
-    _generateNode(node.value);
-
-    if (hasResult) {
-      asm.emitStoreLocal(temp);
-    }
-
-    final target = node.target;
-    assert(target is Field || (target is Procedure && target.isSetter));
-    _genDirectCall(target, objectTable.getArgDescHandle(2), 2,
-        isSet: true, node: node);
-    asm.emitDrop1();
-
-    if (hasResult) {
-      asm.emitPush(temp);
-    }
-  }
-
-  @override
   visitFunctionExpression(FunctionExpression node) {
     _genClosure(node, '<anonymous closure>', node.function);
   }
@@ -3203,12 +3170,10 @@
 
   @override
   visitLogicalExpression(LogicalExpression node) {
-    assert(node.operator == '||' || node.operator == '&&');
-
     final Label shortCircuit = new Label();
     final Label done = new Label();
     final int temp = locals.tempIndexInFrame(node);
-    final isOR = (node.operator == '||');
+    final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);
 
     _genConditionAndJumpIf(node.left, isOR, shortCircuit);
 
@@ -3507,7 +3472,7 @@
     if (target == null) {
       final int temp = locals.tempIndexInFrame(node);
       _genNoSuchMethodForSuperCall(
-          node.name.name,
+          node.name.text,
           temp,
           cp.addArgDescByArguments(args, hasReceiver: true),
           args.types,
@@ -3531,7 +3496,7 @@
         hierarchy.getDispatchTarget(enclosingClass.superclass, node.name);
     if (target == null) {
       final int temp = locals.tempIndexInFrame(node);
-      _genNoSuchMethodForSuperCall(node.name.name, temp, cp.addArgDesc(1), [],
+      _genNoSuchMethodForSuperCall(node.name.text, temp, cp.addArgDesc(1), [],
           <Expression>[new ThisExpression()]);
       return;
     }
@@ -3548,7 +3513,7 @@
     final Member target = hierarchy
         .getDispatchTarget(enclosingClass.superclass, node.name, setter: true);
     if (target == null) {
-      _genNoSuchMethodForSuperCall(node.name.name, temp, cp.addArgDesc(2), [],
+      _genNoSuchMethodForSuperCall(node.name.text, temp, cp.addArgDesc(2), [],
           <Expression>[new ThisExpression(), node.value],
           storeLastArgumentToTemp: hasResult);
     } else {
@@ -3820,7 +3785,7 @@
         // closure call needs one temporary, so withTemp lets us use this
         // VariableGet's temporary when visiting the initializer.
         assert(init is MethodInvocation &&
-            init.name.name == "call" &&
+            init.name.text == "call" &&
             init.arguments.positional.length == 0);
         locals.withTemp(
             init, locals.tempIndexInFrame(node), () => _generateNode(init));
diff --git a/pkg/vm/lib/bytecode/generics.dart b/pkg/vm/lib/bytecode/generics.dart
index 6399d99..6fc5829 100644
--- a/pkg/vm/lib/bytecode/generics.dart
+++ b/pkg/vm/lib/bytecode/generics.dart
@@ -306,6 +306,6 @@
 /// function type. Such invocations can omit argument type checks.
 bool isUncheckedClosureCall(MethodInvocation node,
         StaticTypeContext staticTypeContext, BytecodeOptions options) =>
-    node.name.name == 'call' &&
+    node.name.text == 'call' &&
     getStaticType(node.receiver, staticTypeContext) is FunctionType &&
     !options.avoidClosureCallInstructions;
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 5ba6c9c..882fb58 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -1369,11 +1369,6 @@
   }
 
   @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    _visit(node, temps: 1);
-  }
-
-  @override
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     _visit(node, temps: 1);
   }
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 734c26e..8db0792 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -1805,7 +1805,7 @@
   }
 
   String mangleMemberName(Member member, bool isGetter, bool isSetter) {
-    final name = member.name.name;
+    final name = member.name.text;
     if (isGetter || (member is Procedure && member.isGetter)) {
       return mangleGetterName(name);
     }
@@ -1862,7 +1862,7 @@
   ObjectHandle getSelectorNameHandle(Name name,
       {bool isGetter: false, bool isSetter: false}) {
     return getNameHandle(
-        name.library, mangleSelectorName(name.name, isGetter, isSetter));
+        name.library, mangleSelectorName(name.text, isGetter, isSetter));
   }
 
   ObjectHandle getTopLevelClassHandle(Library library) {
diff --git a/pkg/vm/lib/bytecode/recognized_methods.dart b/pkg/vm/lib/bytecode/recognized_methods.dart
index a237c1f..f73ce50 100644
--- a/pkg/vm/lib/bytecode/recognized_methods.dart
+++ b/pkg/vm/lib/bytecode/recognized_methods.dart
@@ -61,7 +61,7 @@
     }
 
     final Expression receiver = node.receiver;
-    final String selector = node.name.name;
+    final String selector = node.name.text;
 
     switch (args.positional.length) {
       case 0:
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 4920fce..59a24ab 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -54,6 +54,10 @@
   bool get supportsLateFields => !flags.forceLateLoweringForTesting;
 
   @override
+  bool get supportsLateLoweringSentinel =>
+      flags.forceLateLoweringSentinelForTesting;
+
+  @override
   bool get useStaticFieldLowering => flags.forceStaticFieldLoweringForTesting;
 
   @override
@@ -149,8 +153,7 @@
       {void logger(String msg),
       ChangedStructureNotifier changedStructureNotifier}) {
     transformMixins.transformLibraries(
-        this, coreTypes, hierarchy, libraries, referenceFromIndex,
-        doSuperResolution: false /* resolution is done in Dart VM */);
+        this, coreTypes, hierarchy, libraries, referenceFromIndex);
     logger?.call("Transformed mixin applications");
 
     transformFfi.ReplacedMembers replacedFields =
diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart
index b93b258..324401f 100644
--- a/pkg/vm/lib/transformations/call_site_annotator.dart
+++ b/pkg/vm/lib/transformations/call_site_annotator.dart
@@ -67,7 +67,7 @@
 
     // TODO(34162): We don't need to save the type here for calls, just whether
     // or not it's a statically-checked call.
-    if (node.name.name == 'call' ||
+    if (node.name.text == 'call' ||
         hasGenericCovariantParameters(node.interfaceTarget)) {
       annotateWithType(node, node.receiver);
     }
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index cc02953..716ba06 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -137,7 +137,11 @@
   //
   // iOS 32 bit alignment:
   // https://developer.apple.com/documentation/uikit/app_and_environment/updating_your_app_from_32-bit_to_64-bit_architecture/updating_data_structures
-  Abi.wordSize32Align32: {NativeType.kDouble: 4, NativeType.kInt64: 4},
+  Abi.wordSize32Align32: {
+    NativeType.kDouble: 4,
+    NativeType.kInt64: 4,
+    NativeType.kUnit64: 4
+  },
 
   // The default for MSVC x86:
   // > The alignment-requirement for all data except structures, unions, and
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index 9ba04b2..13498bc 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -203,9 +203,9 @@
       if (f is Field) {
         if (f.initializer is! NullLiteral) {
           diagnosticReporter.report(
-              templateFfiFieldInitializer.withArguments(f.name.name),
+              templateFfiFieldInitializer.withArguments(f.name.text),
               f.fileOffset,
-              f.name.name.length,
+              f.name.text.length,
               f.fileUri);
         }
       }
@@ -214,16 +214,16 @@
       if (_isPointerType(type)) {
         if (nativeTypeAnnos.length != 0) {
           diagnosticReporter.report(
-              templateFfiFieldNoAnnotation.withArguments(f.name.name),
+              templateFfiFieldNoAnnotation.withArguments(f.name.text),
               f.fileOffset,
-              f.name.name.length,
+              f.name.text.length,
               f.fileUri);
         }
       } else if (nativeTypeAnnos.length != 1) {
         diagnosticReporter.report(
-            templateFfiFieldAnnotation.withArguments(f.name.name),
+            templateFfiFieldAnnotation.withArguments(f.name.text),
             f.fileOffset,
-            f.name.name.length,
+            f.name.text.length,
             f.fileUri);
       } else {
         final DartType nativeType = InterfaceType(
@@ -258,7 +258,7 @@
         if (i is FieldInitializer) {
           toRemove.add(i);
           diagnosticReporter.report(
-              templateFfiFieldInitializer.withArguments(i.field.name.name),
+              templateFfiFieldInitializer.withArguments(i.field.name.text),
               i.fileOffset,
               1,
               i.location.file);
@@ -274,7 +274,7 @@
     // C.#fromPointer(Pointer<Void> address) : super.fromPointer(address);
     final VariableDeclaration pointer = new VariableDeclaration("#pointer");
     final name = Name("#fromPointer");
-    final referenceFrom = indexedClass?.lookupConstructor(name.name);
+    final referenceFrom = indexedClass?.lookupConstructor(name.text);
     final Constructor ctor = Constructor(
         FunctionNode(EmptyStatement(), positionalParameters: [pointer]),
         name: name,
@@ -406,7 +406,9 @@
     //   _fromAddress<Int8>(_loadIntPtr(pointer, offset));
     final loadMethod = isPointer
         ? loadMethods[NativeType.kIntptr]
-        : optimizedTypes.contains(type) ? loadMethods[type] : loadStructMethod;
+        : optimizedTypes.contains(type)
+            ? loadMethods[type]
+            : loadStructMethod;
     Expression getterReturnValue = StaticInvocation(
         loadMethod,
         Arguments([
@@ -439,8 +441,9 @@
     Expression argumentExpression = VariableGet(argument)
       ..fileOffset = fileOffset;
     if (isPointer) {
-      argumentExpression = DirectPropertyGet(argumentExpression, addressGetter)
-        ..fileOffset = fileOffset;
+      argumentExpression =
+          PropertyGet(argumentExpression, addressGetter.name, addressGetter)
+            ..fileOffset = fileOffset;
     }
     return ReturnStatement(StaticInvocation(
         storeMethod,
@@ -461,7 +464,7 @@
         FunctionNode(getterStatement, returnType: field.type),
         fileUri: field.fileUri,
         reference:
-            indexedClass?.lookupProcedureNotSetter(field.name.name)?.reference)
+            indexedClass?.lookupProcedureNotSetter(field.name.text)?.reference)
       ..fileOffset = field.fileOffset
       ..isNonNullableByDefault = field.isNonNullableByDefault;
 
@@ -479,7 +482,7 @@
               returnType: VoidType(), positionalParameters: [argument]),
           fileUri: field.fileUri,
           reference:
-              indexedClass?.lookupProcedureSetter(field.name.name)?.reference)
+              indexedClass?.lookupProcedureSetter(field.name.text)?.reference)
         ..fileOffset = field.fileOffset
         ..isNonNullableByDefault = field.isNonNullableByDefault;
     }
@@ -501,7 +504,7 @@
         initializer: _runtimeBranchOnLayout(sizes),
         type: InterfaceType(intClass, Nullability.legacy),
         fileUri: struct.fileUri,
-        reference: indexedClass?.lookupField(name.name)?.reference)
+        reference: indexedClass?.lookupField(name.text)?.reference)
       ..fileOffset = struct.fileOffset;
     _makeEntryPoint(sizeOf);
     struct.addMember(sizeOf);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index f23c669..e198b10 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -342,7 +342,7 @@
         isStatic: true,
         isFinal: true,
         fileUri: currentLibrary.fileUri,
-        reference: currentLibraryIndex?.lookupField(name.name)?.reference)
+        reference: currentLibraryIndex?.lookupField(name.text)?.reference)
       ..fileOffset = node.fileOffset;
     currentLibrary.addMember(field);
     return StaticGet(field);
@@ -434,7 +434,7 @@
       return;
     }
     diagnosticReporter.report(
-        templateFfiNotStatic.withArguments(fromFunctionMethod.name.name),
+        templateFfiNotStatic.withArguments(fromFunctionMethod.name.text),
         node.fileOffset,
         1,
         node.location.file);
diff --git a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
index fd6484ca..e838c80 100644
--- a/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
+++ b/pkg/vm/lib/transformations/no_dynamic_invocations_annotator.dart
@@ -81,7 +81,7 @@
   }
 
   visitField(Field node) {
-    if (node.isStatic || node.name.name == 'call') {
+    if (node.isStatic || node.name.text == 'call') {
       return;
     }
 
@@ -104,7 +104,7 @@
   }
 
   visitProcedure(Procedure node) {
-    if (node.isStatic || node.name.name == 'call') {
+    if (node.isStatic || node.name.text == 'call') {
       return;
     }
 
@@ -190,17 +190,6 @@
   }
 
   @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    super.visitDirectMethodInvocation(node);
-
-    Selector selector;
-    if (node.receiver is! ThisExpression) {
-      nonThisSelectors
-          .add(selector ??= new Selector.doInvoke(node.target.name));
-    }
-  }
-
-  @override
   visitPropertyGet(PropertyGet node) {
     super.visitPropertyGet(node);
 
@@ -220,20 +209,6 @@
   }
 
   @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    super.visitDirectPropertyGet(node);
-
-    if (node.receiver is! ThisExpression) {
-      nonThisSelectors.add(new Selector.doGet(node.target.name));
-    }
-
-    final target = node.target;
-    if (target is Procedure && target.kind == ProcedureKind.Method) {
-      tearOffSelectors.add(new Selector.doInvoke(target.name));
-    }
-  }
-
-  @override
   visitPropertySet(PropertySet node) {
     super.visitPropertySet(node);
 
@@ -246,14 +221,4 @@
       }
     }
   }
-
-  @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    super.visitDirectPropertySet(node);
-
-    Selector selector;
-    if (node.receiver is! ThisExpression) {
-      nonThisSelectors.add(selector ??= new Selector.doSet(node.target.name));
-    }
-  }
 }
diff --git a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
index b059fd3..98592ef 100644
--- a/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
+++ b/pkg/vm/lib/transformations/obfuscation_prohibitions_annotator.dart
@@ -51,16 +51,16 @@
 
   @override
   visitConstructor(Constructor ctor) {
-    _addIfEntryPoint(ctor.annotations, ctor.name.name, ctor);
+    _addIfEntryPoint(ctor.annotations, ctor.name.text, ctor);
   }
 
   @override
   visitProcedure(Procedure proc) {
-    _addIfEntryPoint(proc.annotations, proc.name.name, proc);
+    _addIfEntryPoint(proc.annotations, proc.name.text, proc);
   }
 
   @override
   visitField(Field field) {
-    _addIfEntryPoint(field.annotations, field.name.name, field);
+    _addIfEntryPoint(field.annotations, field.name.text, field);
   }
 }
diff --git a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
index 2704c99..7aad1d8 100644
--- a/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
+++ b/pkg/vm/lib/transformations/protobuf_aware_treeshaker/transformer.dart
@@ -71,7 +71,7 @@
   final biClass =
       protobufLib.classes.where((klass) => klass.name == 'BuilderInfo').single;
   final addMethod =
-      biClass.members.singleWhere((Member member) => member.name.name == 'add');
+      biClass.members.singleWhere((Member member) => member.name.text == 'add');
 
   component.accept(collector);
 
@@ -125,9 +125,9 @@
   _UnusedFieldMetadataPruner(this.tagNumberClass, this.builderInfoClass,
       this.addMethod, Set<Selector> dynamicSelectors, this.coreTypes, this.info)
       : tagNumberField = tagNumberClass.fields
-            .firstWhere((f) => f.name.name == 'tagNumber')
+            .firstWhere((f) => f.name.text == 'tagNumber')
             .reference {
-    dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.name));
+    dynamicNames.addAll(dynamicSelectors.map((sel) => sel.target.text));
   }
 
   /// If a proto message field is never accessed (neither read nor written to),
@@ -140,7 +140,7 @@
       TransformationInfo info) {
     for (final klass in gmSubclasses) {
       final selectors = invokedMethods[klass] ?? Set<Selector>();
-      final builderInfoFields = klass.fields.where((f) => f.name.name == '_i');
+      final builderInfoFields = klass.fields.where((f) => f.name.text == '_i');
       if (builderInfoFields.isEmpty) {
         continue;
       }
@@ -152,7 +152,7 @@
   void _pruneBuilderInfoField(
       Field field, Set<Selector> selectors, Class gmSubclass) {
     names.clear();
-    names.addAll(selectors.map((sel) => sel.target.name));
+    names.addAll(selectors.map((sel) => sel.target.text));
     visitedClass = gmSubclass;
     _computeUsedTagNumbers(gmSubclass);
     field.initializer.accept(this);
@@ -166,7 +166,7 @@
           final constant = annotation.constant;
           if (constant is InstanceConstant &&
               constant.classReference == tagNumberClass.reference) {
-            final name = procedure.name.name;
+            final name = procedure.name.text;
             if (dynamicNames.contains(name) || names.contains(name)) {
               usedTagNumbers.add(
                   (constant.fieldValues[tagNumberField] as IntConstant).value);
@@ -216,7 +216,7 @@
   void _changeCascadeEntry(Expression initializer) {
     if (initializer is MethodInvocation &&
         initializer.interfaceTarget?.enclosingClass == builderInfoClass &&
-        fieldAddingMethods.contains(initializer.name.name)) {
+        fieldAddingMethods.contains(initializer.name.text)) {
       final tagNumber =
           (initializer.arguments.positional[0] as IntLiteral).value;
       if (!usedTagNumbers.contains(tagNumber)) {
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index d35e0a0..bad218c 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -114,7 +114,7 @@
   /// Result type may be saturated if this invocation was invalidated
   /// too many times.
   void setResult(TypeFlowAnalysis typeFlowAnalysis, Type type) {
-    assertx(type != null);
+    assert(type != null);
     result = type;
 
     if (invalidatedResult != null) {
@@ -204,7 +204,7 @@
 
   @override
   Type process(TypeFlowAnalysis typeFlowAnalysis) {
-    assertx(typeFlowAnalysis.currentInvocation == this);
+    assert(typeFlowAnalysis.currentInvocation == this);
 
     if (selector.member is Field) {
       return _processField(typeFlowAnalysis);
@@ -220,16 +220,16 @@
 
     switch (selector.callKind) {
       case CallKind.PropertyGet:
-        assertx(args.values.length == firstParamIndex);
-        assertx(args.names.isEmpty);
+        assert(args.values.length == firstParamIndex);
+        assert(args.names.isEmpty);
         fieldValue.isGetterUsed = true;
         return fieldValue.getValue(
             typeFlowAnalysis, field.isStatic ? null : args.values[0]);
 
       case CallKind.PropertySet:
       case CallKind.SetFieldInConstructor:
-        assertx(args.values.length == firstParamIndex + 1);
-        assertx(args.names.isEmpty);
+        assert(args.values.length == firstParamIndex + 1);
+        assert(args.names.isEmpty);
         if (selector.callKind == CallKind.PropertySet) {
           fieldValue.isSetterUsed = true;
         }
@@ -253,8 +253,8 @@
         return new Type.nullableAny();
 
       case CallKind.FieldInitializer:
-        assertx(args.values.length == firstParamIndex);
-        assertx(args.names.isEmpty);
+        assert(args.values.length == firstParamIndex);
+        assert(args.names.isEmpty);
         Type initializerResult = typeFlowAnalysis
             .getSummary(field)
             .apply(args, typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
@@ -290,27 +290,27 @@
         final summaryResult = summary.result;
         if (summaryResult is Type &&
             !typeFlowAnalysis.workList._isPending(this)) {
-          assertx(result == null || result == summaryResult);
+          assert(result == null || result == summaryResult);
           setResult(typeFlowAnalysis, summaryResult);
         }
         return summary.apply(
             args, typeFlowAnalysis.hierarchyCache, typeFlowAnalysis);
       } else {
-        assertx(selector.callKind == CallKind.Method);
+        assert(selector.callKind == CallKind.Method);
         return _processNoSuchMethod(args.receiver, typeFlowAnalysis);
       }
     } else {
       if (selector.callKind == CallKind.PropertyGet) {
         // Tear-off.
         // TODO(alexmarkov): capture receiver type
-        assertx((member is Procedure) && !member.isGetter && !member.isSetter);
+        assert((member is Procedure) && !member.isGetter && !member.isSetter);
         typeFlowAnalysis.addRawCall(new DirectSelector(member));
         typeFlowAnalysis._tearOffTaken.add(member);
         return new Type.nullableAny();
       } else {
         // Call via getter.
         // TODO(alexmarkov): capture receiver type
-        assertx((selector.callKind == CallKind.Method) &&
+        assert((selector.callKind == CallKind.Method) &&
             (member is Procedure) &&
             member.isGetter);
         typeFlowAnalysis.addRawCall(
@@ -325,7 +325,7 @@
 
   bool _argumentsValid() {
     final function = selector.member.function;
-    assertx(function != null);
+    assert(function != null);
 
     final int positionalArguments = args.positionalCount;
 
@@ -378,12 +378,12 @@
 
   _DispatchableInvocation(Selector selector, Args<Type> args)
       : super(selector, args) {
-    assertx(selector is! DirectSelector);
+    assert(selector is! DirectSelector);
   }
 
   @override
   Type process(TypeFlowAnalysis typeFlowAnalysis) {
-    assertx(typeFlowAnalysis.currentInvocation == this);
+    assert(typeFlowAnalysis.currentInvocation == this);
 
     // Collect all possible targets for this invocation,
     // along with more accurate receiver types for each target.
@@ -415,7 +415,7 @@
 
         if (target == kNoSuchMethodMarker) {
           // Non-dynamic call-sites must hit NSM-forwarders in Dart 2.
-          assertx(selector is DynamicSelector);
+          assert(selector is DynamicSelector);
           type = _processNoSuchMethod(receiver, typeFlowAnalysis);
         } else {
           final directSelector =
@@ -430,7 +430,7 @@
               .getInvocation(directSelector, directArgs);
 
           if (!_isPolymorphic) {
-            assertx(target == _monomorphicTarget);
+            assert(target == _monomorphicTarget);
             _monomorphicDirectInvocation = directInvocation;
           }
 
@@ -467,7 +467,7 @@
     }
 
     // TODO(alexmarkov): handle closures more precisely
-    if ((selector is DynamicSelector) && (selector.name.name == "call")) {
+    if ((selector is DynamicSelector) && (selector.name.text == "call")) {
       tracePrint("Possible closure call, result is dynamic");
       result = new Type.nullableAny();
     }
@@ -479,12 +479,12 @@
       Type receiver,
       Map<Member, _ReceiverTypeBuilder> targets,
       TypeFlowAnalysis typeFlowAnalysis) {
-    assertx(receiver != const EmptyType()); // should be filtered earlier
+    assert(receiver != const EmptyType()); // should be filtered earlier
 
     final bool isNullableReceiver = receiver is NullableType;
     if (isNullableReceiver) {
       receiver = (receiver as NullableType).baseType;
-      assertx(receiver is! NullableType);
+      assert(receiver is! NullableType);
     }
 
     if (selector is InterfaceSelector) {
@@ -492,7 +492,7 @@
           .getTFClass(selector.member.enclosingClass));
       receiver = receiver.intersection(
           staticReceiverType, typeFlowAnalysis.hierarchyCache);
-      assertx(receiver is! NullableType);
+      assert(receiver is! NullableType);
 
       if (kPrintTrace) {
         tracePrint("Narrowed down receiver type: $receiver");
@@ -507,7 +507,7 @@
           .specializeTypeCone((receiver as ConeType).cls);
     }
 
-    assertx(targets.isEmpty);
+    assert(targets.isEmpty);
 
     if (receiver is ConcreteType) {
       _collectTargetsForConcreteType(receiver, targets, typeFlowAnalysis);
@@ -518,7 +518,7 @@
     } else if (receiver is AnyType) {
       _collectTargetsForSelector(targets, typeFlowAnalysis);
     } else {
-      assertx(receiver is EmptyType);
+      assert(receiver is EmptyType);
     }
 
     if (isNullableReceiver) {
@@ -548,9 +548,8 @@
       TypeFlowAnalysis typeFlowAnalysis) {
     final TFClass cls = receiver.cls;
 
-    Member target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
-        cls.classNode, selector.name,
-        setter: selector.isSetter);
+    Member target =
+        (cls as _TFClassImpl).getDispatchTarget(selector, typeFlowAnalysis);
 
     if (target != null) {
       if (kPrintTrace) {
@@ -585,8 +584,8 @@
     if (selector is InterfaceSelector) {
       // TODO(alexmarkov): support generic types and make sure inferred types
       // are always same or better than static types.
-//      assertx(selector.member.enclosingClass ==
-//          _typeFlowAnalysis.environment.coreTypes.objectClass, details: selector);
+//      assert(selector.member.enclosingClass ==
+//          _typeFlowAnalysis.environment.coreTypes.objectClass);
       selector = new DynamicSelector(selector.callKind, selector.name);
     }
 
@@ -596,7 +595,7 @@
 
     dynamicTargetSet.addDependentInvocation(this);
 
-    assertx(targets.isEmpty);
+    assert(targets.isEmpty);
     for (Member target in dynamicTargetSet.targets) {
       _getReceiverTypeBuilder(targets, target).addType(receiver);
     }
@@ -624,8 +623,8 @@
   }
 
   void _setMonomorphicTarget(Member target) {
-    assertx(!_isPolymorphic);
-    assertx((_monomorphicTarget == null) || (_monomorphicTarget == target));
+    assert(!_isPolymorphic);
+    assert((_monomorphicTarget == null) || (_monomorphicTarget == target));
     _monomorphicTarget = target;
 
     _notifyCallSites();
@@ -693,8 +692,8 @@
         return;
       }
 
-      assertx(_type is ConcreteType);
-      assertx(_type != type);
+      assert(_type is ConcreteType);
+      assert(_type != type);
 
       _list = new List<ConcreteType>();
       _list.add(_type);
@@ -702,14 +701,14 @@
       _type = null;
     }
 
-    assertx(_list.last.cls.id < type.cls.id);
+    assert(_list.last.cls.id < type.cls.id);
     _list.add(type);
   }
 
   /// Appends an arbitrary Type. May be called only once.
   /// Should not be used in conjunction with [addConcreteType].
   void addType(Type type) {
-    assertx(_type == null && _list == null);
+    assert(_type == null && _list == null);
     _type = type;
   }
 
@@ -728,7 +727,7 @@
         t = new SetType(_list);
       }
     } else {
-      assertx(_list == null);
+      assert(_list == null);
     }
 
     if (_nullable) {
@@ -797,7 +796,7 @@
     }
 
     bool added = _invocations.add(invocation);
-    assertx(added);
+    assert(added);
     ++Statistics.invocationsAddedToCache;
     return invocation;
   }
@@ -833,7 +832,7 @@
     }
 
     final enclosingClass = field.enclosingClass;
-    assertx(enclosingClass != null);
+    assert(enclosingClass != null);
 
     // Default value is not observable if every generative constructor
     // is redirecting or initializes the field.
@@ -851,7 +850,7 @@
 
   void ensureInitialized(TypeFlowAnalysis typeFlowAnalysis, Type receiverType) {
     if (field.initializer != null) {
-      assertx(field.isStatic == (receiverType == null));
+      assert(field.isStatic == (receiverType == null));
       final args = !field.isStatic ? <Type>[receiverType] : const <Type>[];
       final initializerInvocation = typeFlowAnalysis._invocationsCache
           .getInvocation(
@@ -908,7 +907,7 @@
         : newValue.specialize(hierarchy).intersection(staticType, hierarchy);
     Type newType =
         value.union(narrowedNewValue, hierarchy).specialize(hierarchy);
-    assertx(newType.isSpecialized);
+    assert(newType.isSpecialized);
 
     if (newType != value) {
       if (kPrintTrace) {
@@ -934,6 +933,7 @@
 class _TFClassImpl extends TFClass {
   final Set<_TFClassImpl> supertypes; // List of super-types including this.
   final Set<_TFClassImpl> _allocatedSubtypes = new Set<_TFClassImpl>();
+  final Map<Selector, Member> _dispatchTargets = <Selector, Member>{};
   final _DependencyTracker dependencyTracker = new _DependencyTracker();
 
   /// Flag indicating if this class has a noSuchMethod() method not inherited
@@ -977,6 +977,18 @@
     _specializedConeType = null; // Reset cached specialization.
   }
 
+  Member getDispatchTarget(
+      Selector selector, TypeFlowAnalysis typeFlowAnalysis) {
+    Member target = _dispatchTargets[selector];
+    if (target == null) {
+      target = typeFlowAnalysis.hierarchyCache.hierarchy.getDispatchTarget(
+          classNode, selector.name,
+          setter: selector.isSetter);
+      _dispatchTargets[selector] = target;
+    }
+    return target;
+  }
+
   String dump() => "$this {supers: $supertypes}";
 }
 
@@ -1038,7 +1050,7 @@
     result = new List<Type>(flattenedTypeArgs.length);
     for (int i = 0; i < flattenedTypeArgs.length; ++i) {
       final translated = closedTypeTranslator.translate(flattenedTypeArgs[i]);
-      assertx(translated is RuntimeType || translated is UnknownType);
+      assert(translated is RuntimeType || translated is UnknownType);
       result[i] = translated;
     }
     cachedFlattenedTypeArgsForNonGeneric[klass] = result;
@@ -1076,7 +1088,7 @@
       : objectNoSuchMethod = hierarchy.getDispatchTarget(
             environment.coreTypes.objectClass, noSuchMethodName),
         super(environment.coreTypes, nullSafety) {
-    assertx(objectNoSuchMethod != null);
+    assert(objectNoSuchMethod != null);
   }
 
   @override
@@ -1093,8 +1105,8 @@
   }
 
   ConcreteType addAllocatedClass(Class cl) {
-    assertx(!cl.isAbstract);
-    assertx(!_sealed);
+    assert(!cl.isAbstract);
+    assert(!_sealed);
 
     final _TFClassImpl classImpl = getTFClass(cl);
 
@@ -1187,7 +1199,7 @@
   }
 
   void _addDynamicTarget(Class c, _DynamicTargetSet targetSet) {
-    assertx(!_sealed);
+    assert(!_sealed);
     final selector = targetSet.selector;
     final member = hierarchy.getDispatchTarget(c, selector.name,
         setter: selector.isSetter);
@@ -1238,11 +1250,11 @@
   bool _isPending(_Invocation invocation) => invocation.list != null;
 
   void enqueueInvocation(_Invocation invocation) {
-    assertx(invocation.result == null);
+    assert(invocation.result == null);
     if (_isPending(invocation)) {
       // Re-add the invocation to the tail of the pending queue.
       pending.remove(invocation);
-      assertx(!_isPending(invocation));
+      assert(!_isPending(invocation));
     }
     pending.add(invocation);
   }
@@ -1250,7 +1262,7 @@
   void invalidateInvocation(_Invocation invocation) {
     Statistics.invocationsInvalidated++;
     if (invocation.result != null) {
-      assertx(invocation.invalidatedResult == null);
+      assert(invocation.invalidatedResult == null);
       invocation.invalidatedResult = invocation.result;
       invocation.result = null;
     }
@@ -1267,7 +1279,7 @@
     }
     // Protobuf handler replaced contents of static field initializers.
     for (var field in fields) {
-      assertx(field.isStatic);
+      assert(field.isStatic);
       // Reset summary in order to rebuild it.
       _typeFlowAnalysis._summaries[field] = null;
       // Invalidate (and enqueue) field initializer invocation.
@@ -1285,7 +1297,7 @@
       if (pending.isEmpty && !invalidateProtobufFields()) {
         break;
       }
-      assertx(callStack.isEmpty && processing.isEmpty);
+      assert(callStack.isEmpty && processing.isEmpty);
       Statistics.iterationsOverInvocationsWorkList++;
       processInvocation(pending.first);
     }
@@ -1328,9 +1340,9 @@
         // same result.
         invocation.typeChecksNeeded = true;
         invalidateInvocation(invocation);
-        assertx(invocation.result == null);
-        assertx(invocation.invalidatedResult != null);
-        assertx(_isPending(invocation));
+        assert(invocation.result == null);
+        assert(invocation.invalidatedResult != null);
+        assert(_isPending(invocation));
         if (kPrintTrace) {
           tracePrint("Processing deferred due to deep call stack.");
           tracePrint(
@@ -1360,7 +1372,7 @@
       }
 
       final last = callStack.removeLast();
-      assertx(identical(last, invocation));
+      assert(identical(last, invocation));
 
       processing.remove(invocation);
 
@@ -1580,7 +1592,7 @@
 
       return workList.processInvocation(invocation);
     } else {
-      assertx(!isResultUsed);
+      assert(!isResultUsed);
 
       if (invocation.result == null) {
         workList.enqueueInvocation(invocation);
@@ -1613,7 +1625,7 @@
     if (kPrintDebug) {
       debugPrint("ADD RAW CALL: $selector");
     }
-    assertx(selector is! DynamicSelector); // TODO(alexmarkov)
+    assert(selector is! DynamicSelector); // TODO(alexmarkov)
 
     applyCall(null, selector, summaryCollector.rawArguments(selector),
         isResultUsed: false, processImmediately: false);
diff --git a/pkg/vm/lib/transformations/type_flow/calls.dart b/pkg/vm/lib/transformations/type_flow/calls.dart
index 8f46fd7..cdd0d0a 100644
--- a/pkg/vm/lib/transformations/type_flow/calls.dart
+++ b/pkg/vm/lib/transformations/type_flow/calls.dart
@@ -102,7 +102,7 @@
 
   DirectSelector(this.member, {CallKind callKind = CallKind.Method})
       : super(callKind) {
-    assertx((callKind == CallKind.Method) ||
+    assert((callKind == CallKind.Method) ||
         (callKind == CallKind.PropertyGet) ||
         memberAgreesToCallKind(member));
   }
@@ -194,7 +194,7 @@
 
   Args(this.values,
       {this.names = const <String>[], this.unknownArity = false}) {
-    assertx(isSorted(names));
+    assert(isSorted(names));
   }
 
   Args.withReceiver(Args<T> args, T receiver)
diff --git a/pkg/vm/lib/transformations/type_flow/native_code.dart b/pkg/vm/lib/transformations/type_flow/native_code.dart
index 8c50b21..0d00188 100644
--- a/pkg/vm/lib/transformations/type_flow/native_code.dart
+++ b/pkg/vm/lib/transformations/type_flow/native_code.dart
@@ -14,7 +14,6 @@
 
 import 'calls.dart';
 import 'types.dart';
-import 'utils.dart';
 import '../pragma.dart';
 
 abstract class EntryPointsListener {
@@ -43,7 +42,7 @@
 
   PragmaEntryPointsVisitor(
       this.entryPoints, this.nativeCodeOracle, this.matcher) {
-    assertx(matcher != null);
+    assert(matcher != null);
   }
 
   PragmaEntryPointType _annotationsDefineRoot(List<Expression> annotations) {
@@ -85,8 +84,8 @@
       Member target = proc;
       while (target is Procedure && target.isRedirectingFactoryConstructor) {
         target = getRedirectingFactoryBody(target).target;
-        assertx(target != null);
-        assertx(
+        assert(target != null);
+        assert(
             (target is Procedure && target.isFactory) || target is Constructor);
       }
       entryPoints
@@ -198,7 +197,7 @@
   final PragmaAnnotationParser _matcher;
 
   NativeCodeOracle(this._libraryIndex, this._matcher) {
-    assertx(_matcher != null);
+    assert(_matcher != null);
   }
 
   void addClassReferencedFromNativeCode(Class klass) {
diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
index 1e98f46..003bb2f 100644
--- a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
+++ b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
@@ -81,15 +81,15 @@
       return;
     }
     final messageClass = (_messageClasses[cls] ??= _MessageClass());
-    if (member is Field && member.name.name == metadataFieldName) {
+    if (member is Field && member.name.text == metadataFieldName) {
       // Update contents of static field initializer of metadata field (_i).
       // according to the used tag numbers.
-      assertx(member.isStatic);
+      assert(member.isStatic);
       if (messageClass._metadataField == null) {
         messageClass._metadataField = member;
         ++Statistics.protobufMessagesUsed;
       } else {
-        assertx(messageClass._metadataField == member);
+        assert(messageClass._metadataField == member);
       }
       _updateMetadataField(messageClass);
       return;
@@ -146,7 +146,7 @@
   bool _isUnusedMetadata(_MessageClass cls, MethodInvocation node) {
     if (node.interfaceTarget != null &&
         node.interfaceTarget.enclosingClass == _builderInfoClass &&
-        fieldAddingMethods.contains(node.name.name)) {
+        fieldAddingMethods.contains(node.name.text)) {
       final tagNumber = (node.arguments.positional[0] as IntLiteral).value;
       return !cls._usedTags.contains(tagNumber);
     }
diff --git a/pkg/vm/lib/transformations/type_flow/summary.dart b/pkg/vm/lib/transformations/type_flow/summary.dart
index c1bc768..ef97516 100644
--- a/pkg/vm/lib/transformations/type_flow/summary.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary.dart
@@ -27,7 +27,7 @@
   @override
   Type getComputedType(List<Type> types) {
     final type = types[index];
-    assertx(type != null);
+    assert(type != null);
     return type;
   }
 
@@ -102,9 +102,9 @@
   Type get argumentType => _argumentType;
 
   void _observeArgumentType(Type argType, TypeHierarchy typeHierarchy) {
-    assertx(argType.isSpecialized);
+    assert(argType.isSpecialized);
     _argumentType = _argumentType.union(argType, typeHierarchy);
-    assertx(_argumentType.isSpecialized);
+    assert(_argumentType.isSpecialized);
   }
 
   Type _observeNotPassed(TypeHierarchy typeHierarchy) {
@@ -199,7 +199,7 @@
   Type apply(List<Type> computedTypes, TypeHierarchy typeHierarchy,
       CallHandler callHandler) {
     Type type = null;
-    assertx(values.isNotEmpty);
+    assert(values.isNotEmpty);
     for (var value in values) {
       final valueType = value.getComputedType(computedTypes);
       type = type != null ? type.union(valueType, typeHierarchy) : valueType;
@@ -351,9 +351,9 @@
   }
 
   void _observeResultType(Type result, TypeHierarchy typeHierarchy) {
-    assertx(result.isSpecialized);
+    assert(result.isSpecialized);
     _resultType = _resultType.union(result, typeHierarchy);
-    assertx(_resultType.isSpecialized);
+    assert(_resultType.isSpecialized);
   }
 }
 
@@ -408,7 +408,7 @@
             }
           }
         } else {
-          assertx(typeArg is UnknownType);
+          assert(typeArg is UnknownType);
         }
         if (extractedType == null || extracted == extractedType) {
           extractedType = extracted;
@@ -458,7 +458,7 @@
     final types = new List<Type>(flattenedTypeArgs.length);
     for (int i = 0; i < types.length; ++i) {
       final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
-      assertx(computed is RuntimeType || computed is UnknownType);
+      assert(computed is RuntimeType || computed is UnknownType);
       if (computed is RuntimeType) hasRuntimeType = true;
       types[i] = computed;
     }
@@ -490,7 +490,7 @@
     final types = new List<RuntimeType>(flattenedTypeArgs.length);
     for (int i = 0; i < types.length; ++i) {
       final computed = flattenedTypeArgs[i].getComputedType(computedTypes);
-      assertx(computed is RuntimeType || computed is UnknownType);
+      assert(computed is RuntimeType || computed is UnknownType);
       if (computed is UnknownType) return const UnknownType();
       types[i] = computed;
     }
@@ -530,7 +530,7 @@
   bool canAlwaysSkip = true;
 
   TypeCheck(this.arg, this.type, this.node, this.staticType) {
-    assertx(node != null);
+    assert(node != null);
     isTestedOnlyOnCheckedEntryPoint =
         parameter != null && !parameter.isCovariant;
   }
@@ -551,7 +551,7 @@
     Type argType = arg.getComputedType(computedTypes);
     Type checkType = type.getComputedType(computedTypes);
     // TODO(sjindel/tfa): Narrow the result if possible.
-    assertx(checkType is UnknownType || checkType is RuntimeType);
+    assert(checkType is UnknownType || checkType is RuntimeType);
 
     bool canSkip = true; // Can this check be skipped on this invocation.
 
@@ -565,7 +565,7 @@
           typeHierarchy.fromStaticType(checkType.representedTypeRaw, true),
           typeHierarchy);
     } else {
-      assertx(false, details: "Cannot see $checkType on RHS of TypeCheck.");
+      throw "Cannot see $checkType on RHS of TypeCheck.";
     }
 
     // If this check might be skipped on an
@@ -628,9 +628,9 @@
     final args = arguments.values;
     final positionalArgCount = arguments.positionalCount;
     final namedArgCount = arguments.namedCount;
-    assertx(requiredParameterCount <= positionalArgCount);
-    assertx(positionalArgCount <= positionalParameterCount);
-    assertx(namedArgCount <= parameterCount - positionalParameterCount);
+    assert(requiredParameterCount <= positionalArgCount);
+    assert(positionalArgCount <= positionalParameterCount);
+    assert(namedArgCount <= parameterCount - positionalParameterCount);
 
     // Interpret statements sequentially, calculating the result type
     // of each statement and putting it into the 'types' list parallel
@@ -674,7 +674,7 @@
     int argIndex = 0;
     for (int i = positionalParameterCount; i < parameterCount; i++) {
       final Parameter param = _statements[i] as Parameter;
-      assertx(param.defaultValue != null);
+      assert(param.defaultValue != null);
       if ((argIndex < namedArgCount) && (argNames[argIndex] == param.name)) {
         final argType =
             args[positionalArgCount + argIndex].specialize(typeHierarchy);
@@ -687,12 +687,12 @@
           types[i] = argType;
         }
       } else {
-        assertx((argIndex == namedArgCount) ||
+        assert((argIndex == namedArgCount) ||
             (param.name.compareTo(argNames[argIndex]) < 0));
         types[i] = param._observeNotPassed(typeHierarchy);
       }
     }
-    assertx(argIndex == namedArgCount);
+    assert(argIndex == namedArgCount);
 
     for (int i = parameterCount; i < _statements.length; i++) {
       // Test if tracing is enabled to avoid expensive message formatting.
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index d76503d..b545936 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -77,8 +77,8 @@
   }
 
   TypeExpr _normalizeExpr(TypeExpr st, bool isResultUsed) {
-    assertx(!_inLoop);
-    assertx(st is! Use);
+    assert(!_inLoop);
+    assert(st is! Use);
     if (st is Statement) {
       if (isResultUsed && (st is Call)) {
         st.setResultUsed();
@@ -140,7 +140,7 @@
         return _handleLoop(st);
       }
     } else {
-      assertx(st is Type);
+      assert(st is Type);
       return st;
     }
   }
@@ -584,7 +584,7 @@
       this._nativeCodeOracle,
       this._genericInterfacesInfo,
       this._protobufHandler) {
-    assertx(_genericInterfacesInfo != null);
+    assert(_genericInterfacesInfo != null);
     constantAllocationCollector = new ConstantAllocationCollector(this);
     _nullMethodsAndGetters.addAll(getSelectors(
         _hierarchy, _environment.coreTypes.nullClass,
@@ -598,8 +598,8 @@
       {fieldSummaryType: FieldSummaryType.kInitializer}) {
     debugPrint(
         "===== ${member}${fieldSummaryType == FieldSummaryType.kFieldGuard ? " (guard)" : ""} =====");
-    assertx(!member.isAbstract);
-    assertx(!(member is Procedure && member.isRedirectingFactoryConstructor));
+    assert(!member.isAbstract);
+    assert(!(member is Procedure && member.isRedirectingFactoryConstructor));
 
     _protobufHandler?.beforeSummaryCreation(member);
 
@@ -633,7 +633,7 @@
           this, _summary, _receiver, null, _genericInterfacesInfo);
 
       if (fieldSummaryType == FieldSummaryType.kInitializer) {
-        assertx(member.initializer != null);
+        assert(member.initializer != null);
         _summary.result = _visit(member.initializer);
       } else {
         final Parameter valueParam =
@@ -727,7 +727,7 @@
         }
         _declareVariable(decl, param);
       }
-      assertx(count == _summary.parameterCount);
+      assert(count == _summary.parameterCount);
 
       _returnValue = new Join("%result", function.returnType);
       _summary.add(_returnValue);
@@ -762,7 +762,7 @@
         }
       }
 
-      if (member.name.name == '==') {
+      if (member.name.text == '==') {
         // In addition to what is returned from the function body,
         // operator == performs implicit comparison with null
         // and returns bool.
@@ -795,7 +795,7 @@
 
   Args<Type> rawArguments(Selector selector) {
     final member = selector.member;
-    assertx(member != null);
+    assert(member != null);
 
     final List<Type> args = <Type>[];
     final List<String> names = <String>[];
@@ -806,7 +806,7 @@
     }
 
     if (hasReceiverArg(member)) {
-      assertx(member.enclosingClass != null);
+      assert(member.enclosingClass != null);
       final receiver =
           new ConeType(_typesBuilder.getTFClass(member.enclosingClass));
       args.add(receiver);
@@ -816,7 +816,7 @@
       case CallKind.Method:
         if (member is! Field) {
           final function = member.function;
-          assertx(function != null);
+          assert(function != null);
 
           final int paramCount = function.positionalParameters.length +
               function.namedParameters.length;
@@ -893,7 +893,7 @@
     }
     final param = new Parameter(name, staticType);
     _summary.add(param);
-    assertx(param.index < _summary.parameterCount);
+    assert(param.index < _summary.parameterCount);
     if (param.index >= _summary.requiredParameterCount) {
       if (initializer != null) {
         if (initializer is ConstantExpression) {
@@ -910,16 +910,16 @@
         param.defaultValue = _nullType;
       }
     } else {
-      assertx(initializer == null);
+      assert(initializer == null);
     }
     return param;
   }
 
   void _declareVariable(VariableDeclaration decl, TypeExpr initialValue) {
     final int varIndex = _variablesInfo.varIndex[decl];
-    assertx(varIndex != null);
-    assertx(_variablesInfo.varDeclarations[varIndex] == decl);
-    assertx(_variableValues[varIndex] == null);
+    assert(varIndex != null);
+    assert(_variablesInfo.varDeclarations[varIndex] == decl);
+    assert(_variableValues[varIndex] == null);
     if (_variablesInfo.isCaptured(decl)) {
       final join = _makeJoin(varIndex, initialValue);
       _variableCells[varIndex] = join;
@@ -965,7 +965,7 @@
   }
 
   void _mergeVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
-    assertx(dst.length == src.length);
+    assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
       final TypeExpr dstValue = dst[i];
       final TypeExpr srcValue = src[i];
@@ -991,14 +991,14 @@
   }
 
   void _copyVariableValues(List<TypeExpr> dst, List<TypeExpr> src) {
-    assertx(dst.length == src.length);
+    assert(dst.length == src.length);
     for (int i = 0; i < dst.length; ++i) {
       dst[i] = src[i];
     }
   }
 
   bool _isIdenticalState(List<TypeExpr> state1, List<TypeExpr> state2) {
-    assertx(state1.length == state2.length);
+    assert(state1.length == state2.length);
     for (int i = 0; i < state1.length; ++i) {
       if (!identical(state1[i], state2[i])) {
         return false;
@@ -1011,7 +1011,7 @@
     final List<Join> joins = new List<Join>(_variablesInfo.numVariables);
     for (var i in _variablesInfo.getModifiedVariables(node)) {
       if (_variableCells[i] != null) {
-        assertx(_variableCells[i] == _variableValues[i]);
+        assert(_variableCells[i] == _variableValues[i]);
       } else {
         final join = _makeJoin(i, _variableValues[i]);
         joins[i] = join;
@@ -1032,7 +1032,7 @@
   void _restoreVariableCellsAfterTry(List<Join> joins) {
     for (int i = 0; i < joins.length; ++i) {
       if (joins[i] != null) {
-        assertx(_variableCells[i] == joins[i]);
+        assert(_variableCells[i] == joins[i]);
         _variableCells[i] = null;
       }
     }
@@ -1127,7 +1127,7 @@
   }
 
   TypeExpr _makeNarrowNotNull(TreeNode node, TypeExpr arg) {
-    assertx(node is NullCheck ||
+    assert(node is NullCheck ||
         node is MethodInvocation && isComparisonWithNull(node));
     if (arg is NarrowNotNull) {
       nullTests[node] = arg;
@@ -1165,7 +1165,7 @@
     } else if (arg is Join || arg is Call || arg is TypeCheck) {
       _summary.add(new Use(arg));
     } else {
-      assertx(arg is Type || arg is Parameter);
+      assert(arg is Type || arg is Parameter);
     }
   }
 
@@ -1289,8 +1289,8 @@
           in _hierarchy.computeSubtypesInformation().getSubtypesOf(cls)) {
         if (!c.isAbstract) {
           final candidate = _hierarchy.getDispatchTarget(c, _equalsName);
-          assertx(candidate != null);
-          assertx(!candidate.isAbstract);
+          assert(candidate != null);
+          assert(!candidate.isAbstract);
           if (candidate != _environment.coreTypes.objectEquals) {
             _cachedHasOverriddenEquals[cls] = true;
             return true;
@@ -1310,15 +1310,14 @@
   // either trueState or falseState.
   void _visitCondition(
       Expression node, List<TypeExpr> trueState, List<TypeExpr> falseState) {
-    assertx(_isIdenticalState(_variableValues, trueState));
-    assertx(_isIdenticalState(_variableValues, falseState));
+    assert(_isIdenticalState(_variableValues, trueState));
+    assert(_isIdenticalState(_variableValues, falseState));
     if (node is Not) {
       _visitCondition(node.operand, falseState, trueState);
       _variableValues = null;
       return;
     } else if (node is LogicalExpression) {
-      assertx(node.operator == '||' || node.operator == '&&');
-      final isOR = (node.operator == '||');
+      final isOR = (node.operatorEnum == LogicalExpressionOperator.OR);
       _visitCondition(node.left, trueState, falseState);
       if (isOR) {
         // expr1 || expr2
@@ -1350,8 +1349,8 @@
       return;
     } else if (node is MethodInvocation &&
         node.receiver is VariableGet &&
-        node.name.name == '==') {
-      assertx(node.arguments.positional.length == 1 &&
+        node.name.text == '==') {
+      assert(node.arguments.positional.length == 1 &&
           node.arguments.types.isEmpty &&
           node.arguments.named.isEmpty);
       final lhs = node.receiver as VariableGet;
@@ -1503,53 +1502,6 @@
   }
 
   @override
-  TypeExpr visitDirectMethodInvocation(DirectMethodInvocation node) {
-    final receiver = _visit(node.receiver);
-    final args = _visitArguments(receiver, node.arguments);
-    final target = node.target;
-    assertx(target is! Field);
-    assertx(!target.isGetter && !target.isSetter);
-    if (receiver is ThisExpression) {
-      _entryPointsListener.recordMemberCalledViaThis(target);
-    } else {
-      // Conservatively record direct invocations with non-this receiver
-      // as being done via interface selectors.
-      _entryPointsListener.recordMemberCalledViaInterfaceSelector(target);
-    }
-    return _makeCall(node, new DirectSelector(target), args);
-  }
-
-  @override
-  TypeExpr visitDirectPropertyGet(DirectPropertyGet node) {
-    final receiver = _visit(node.receiver);
-    final args = new Args<TypeExpr>([receiver]);
-    final target = node.target;
-    // No need to record this invocation as performed via this or via interface
-    // selector as PropertyGet invocations are not tracked at all.
-    return _makeCall(
-        node, new DirectSelector(target, callKind: CallKind.PropertyGet), args);
-  }
-
-  @override
-  TypeExpr visitDirectPropertySet(DirectPropertySet node) {
-    final receiver = _visit(node.receiver);
-    final value = _visit(node.value);
-    final args = new Args<TypeExpr>([receiver, value]);
-    final target = node.target;
-    assertx((target is Field) || ((target is Procedure) && target.isSetter));
-    if (receiver is ThisExpression) {
-      _entryPointsListener.recordMemberCalledViaThis(target);
-    } else {
-      // Conservatively record direct invocations with non-this receiver
-      // as being done via interface selectors.
-      _entryPointsListener.recordMemberCalledViaInterfaceSelector(target);
-    }
-    _makeCall(
-        node, new DirectSelector(target, callKind: CallKind.PropertySet), args);
-    return value;
-  }
-
-  @override
   TypeExpr visitFunctionExpression(FunctionExpression node) {
     _handleNestedFunctionNode(node.function);
     // TODO(alexmarkov): support function types.
@@ -1639,7 +1591,7 @@
     final receiver = _visit(receiverNode);
     final args = _visitArguments(receiver, node.arguments);
     final target = node.interfaceTarget;
-    if (receiverNode is ConstantExpression && node.name.name == '[]') {
+    if (receiverNode is ConstantExpression && node.name.text == '[]') {
       Constant constant = receiverNode.constant;
       if (constant is ListConstant) {
         return _handleIndexingIntoListConstant(constant);
@@ -1647,11 +1599,11 @@
     }
     TypeExpr result;
     if (target == null) {
-      if (node.name.name == '==') {
+      if (node.name.text == '==') {
         _makeCall(node, new DynamicSelector(CallKind.Method, node.name), args);
         return new Type.nullable(_boolType);
       }
-      if (node.name.name == 'call') {
+      if (node.name.text == 'call') {
         final recvType = _staticDartType(node.receiver);
         if ((recvType is FunctionType) ||
             (recvType == _environment.functionLegacyRawType)) {
@@ -1662,7 +1614,7 @@
       result = _makeCall(
           node, new DynamicSelector(CallKind.Method, node.name), args);
     } else {
-      assertx(target is Procedure && !target.isGetter);
+      assert(target is Procedure && !target.isGetter);
       // TODO(alexmarkov): overloaded arithmetic operators
       result = _makeCall(
           node,
@@ -1724,7 +1676,7 @@
       _makeCall(
           node, new DynamicSelector(CallKind.PropertySet, node.name), args);
     } else {
-      assertx((target is Field) || ((target is Procedure) && target.isSetter));
+      assert((target is Field) || ((target is Procedure) && target.isSetter));
       _makeCall(
           node,
           (node.receiver is ThisExpression)
@@ -1739,15 +1691,15 @@
 
   @override
   TypeExpr visitSuperMethodInvocation(SuperMethodInvocation node) {
-    assertx(kPartialMixinResolution);
-    assertx(_receiver != null, details: node);
+    assert(kPartialMixinResolution);
+    assert(_receiver != null, "Should have receiver. Node: $node");
     final args = _visitArguments(_receiver, node.arguments);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
     if (target == null) {
       return const EmptyType();
     } else {
-      assertx(target is Procedure && !target.isGetter);
+      assert(target is Procedure && !target.isGetter);
       _entryPointsListener.recordMemberCalledViaThis(target);
       return _makeCall(node, new DirectSelector(target), args);
     }
@@ -1755,8 +1707,8 @@
 
   @override
   TypeExpr visitSuperPropertyGet(SuperPropertyGet node) {
-    assertx(kPartialMixinResolution);
-    assertx(_receiver != null, details: node);
+    assert(kPartialMixinResolution);
+    assert(_receiver != null, "Should have receiver. Node: $node");
     final args = new Args<TypeExpr>([_receiver]);
     // Re-resolve target due to partial mixin resolution.
     final target = _hierarchy.getDispatchTarget(_superclass, node.name);
@@ -1770,15 +1722,15 @@
 
   @override
   TypeExpr visitSuperPropertySet(SuperPropertySet node) {
-    assertx(kPartialMixinResolution);
-    assertx(_receiver != null, details: node);
+    assert(kPartialMixinResolution);
+    assert(_receiver != null, "Should have receiver. Node: $node");
     final value = _visit(node.value);
     final args = new Args<TypeExpr>([_receiver, value]);
     // Re-resolve target due to partial mixin resolution.
     final target =
         _hierarchy.getDispatchTarget(_superclass, node.name, setter: true);
     if (target != null) {
-      assertx((target is Field) || ((target is Procedure) && target.isSetter));
+      assert((target is Field) || ((target is Procedure) && target.isSetter));
       _entryPointsListener.recordMemberCalledViaThis(target);
       _makeCall(node,
           new DirectSelector(target, callKind: CallKind.PropertySet), args);
@@ -1816,7 +1768,7 @@
     final args = _visitArguments(null, node.arguments,
         passTypeArguments: node.target.isFactory);
     final target = node.target;
-    assertx((target is! Field) && !target.isGetter && !target.isSetter);
+    assert((target is! Field) && !target.isGetter && !target.isSetter);
     TypeExpr result = _makeCall(node, new DirectSelector(target), args);
     if (target == unsafeCast) {
       // Async transformation inserts unsafeCasts to make sure
@@ -1835,7 +1787,7 @@
     final value = _visit(node.value);
     final args = new Args<TypeExpr>([value]);
     final target = node.target;
-    assertx((target is Field) || (target is Procedure) && target.isSetter);
+    assert((target is Field) || (target is Procedure) && target.isSetter);
     _makeCall(
         node, new DirectSelector(target, callKind: CallKind.PropertySet), args);
     return value;
@@ -1859,7 +1811,7 @@
 
   @override
   TypeExpr visitThisExpression(ThisExpression node) {
-    assertx(_receiver != null, details: node);
+    assert(_receiver != null, "Should have receiver. Node: $node");
     return _receiver;
   }
 
@@ -1881,12 +1833,6 @@
     if (v == null) {
       throw 'Unable to find variable ${node.variable} at ${node.location}';
     }
-
-    if ((node.promotedType != null) &&
-        (node.promotedType != const DynamicType())) {
-      return _makeNarrowAfterSuccessfulIsCheck(v, node.promotedType);
-    }
-
     return v;
   }
 
@@ -2193,7 +2139,7 @@
     } else {
       target = node.target;
     }
-    assertx(target != null);
+    assert(target != null);
     _makeCall(node, new DirectSelector(target), args);
     return null;
   }
@@ -2294,7 +2240,7 @@
     // building 'A<T>'.
     typesCache[type] = const UnknownType();
     final result = type.accept(this);
-    assertx(
+    assert(
         result is UnknownType || result is RuntimeType || result is Statement);
     typesCache[type] = result;
     return result;
@@ -2372,7 +2318,7 @@
     }
     if (type.parameter.parent is! Class) return const UnknownType();
     final interfaceClass = type.parameter.parent as Class;
-    assertx(receiver != null);
+    assert(receiver != null);
     // Undetermined nullability is equivalent to nonNullable when
     // instantiating type parameter, so convert it right away.
     Nullability nullability = type.nullability;
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
index 2c69ae0..1d78d39 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
@@ -4,7 +4,7 @@
 
 import 'package:kernel/ast.dart';
 
-import 'utils.dart' show assertx, UnionFind;
+import 'utils.dart' show UnionFind;
 import '../../metadata/procedure_attributes.dart';
 import '../../metadata/table_selector.dart';
 
@@ -101,7 +101,7 @@
     final map = getter ? _getterMemberIds : _methodOrSetterMemberIds;
     int memberId = map[member.enclosingClass][member.name];
     if (memberId == null) {
-      assertx(member is Procedure &&
+      assert(member is Procedure &&
               ((identical(map, _getterMemberIds) &&
                       (member.kind == ProcedureKind.Operator ||
                           member.kind == ProcedureKind.Setter)) ||
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 71e556b..cf64db8 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -180,7 +180,7 @@
 
   InferredType _convertType(Type type,
       {bool skipCheck: false, bool receiverNotInt: false}) {
-    assertx(type != null);
+    assert(type != null);
 
     Class concreteClass;
     Constant constantValue;
@@ -298,7 +298,7 @@
         _tableSelectorAssigner.registerGetterCall(
             selector.member, callSite.isNullableReceiver);
       } else {
-        assertx(node is MethodInvocation || node is PropertySet);
+        assert(node is MethodInvocation || node is PropertySet);
         _tableSelectorAssigner.registerMethodOrSetterCall(
             selector.member, callSite.isNullableReceiver);
       }
@@ -320,13 +320,13 @@
         Args<Type> argTypes = _typeFlowAnalysis.argumentTypes(member);
         final uncheckedParameters =
             _typeFlowAnalysis.uncheckedParameters(member);
-        assertx(argTypes != null);
+        assert(argTypes != null);
 
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
         final positionalParams = member.function.positionalParameters;
-        assertx(argTypes.positionalCount ==
+        assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
         for (int i = 0; i < positionalParams.length; i++) {
@@ -340,7 +340,7 @@
         final names = argTypes.names;
         for (int i = 0; i < names.length; i++) {
           final param = findNamedParameter(member.function, names[i]);
-          assertx(param != null);
+          assert(param != null);
           _setInferredType(param,
               argTypes.values[firstParamIndex + positionalParams.length + i],
               skipCheck: uncheckedParameters.contains(param));
@@ -438,24 +438,6 @@
   }
 
   @override
-  visitDirectMethodInvocation(DirectMethodInvocation node) {
-    _annotateCallSite(node, node.target);
-    super.visitDirectMethodInvocation(node);
-  }
-
-  @override
-  visitDirectPropertyGet(DirectPropertyGet node) {
-    _annotateCallSite(node, node.target);
-    super.visitDirectPropertyGet(node);
-  }
-
-  @override
-  visitDirectPropertySet(DirectPropertySet node) {
-    _annotateCallSite(node, node.target);
-    super.visitDirectPropertySet(node);
-  }
-
-  @override
   visitSuperMethodInvocation(SuperMethodInvocation node) {
     _annotateCallSite(node, node.interfaceTarget);
     super.visitSuperMethodInvocation(node);
@@ -653,7 +635,7 @@
           return extension.members
               .any((descriptor) => descriptor.member.asMember == m);
         }, orElse: () => null);
-        assertx(extension != null);
+        assert(extension != null);
 
         // Ensure we retain the [Extension] itself (though members might be
         // shaken)
@@ -691,8 +673,8 @@
   FieldMorpher(this.shaker);
 
   Member _createAccessorForRemovedField(Field field, bool isSetter) {
-    assertx(!field.isStatic);
-    assertx(!shaker.retainField(field));
+    assert(!field.isStatic);
+    assert(!shaker.retainField(field));
     Procedure accessor;
     if (isSetter) {
       final isAbstract = !shaker.isFieldSetterReachable(field);
@@ -945,7 +927,7 @@
     additionalInitializers.clear();
     node = defaultMember(node);
     if (additionalInitializers.isNotEmpty) {
-      assertx(node.initializers.last is SuperInitializer ||
+      assert(node.initializers.last is SuperInitializer ||
           node.initializers.last is RedirectingInitializer);
       additionalInitializers.forEach((i) => i.parent = node);
       node.initializers
@@ -1181,7 +1163,8 @@
     }
 
     final target = node.target;
-    assertx(shaker.isMemberBodyReachable(target), details: target);
+    assert(shaker.isMemberBodyReachable(target),
+        "Member body is not reachable: $target");
 
     if (!shaker._signatureShaker.isShakingSignature(target)) return node;
     final result = _fixArgumentEvaluationOrder(node, node.arguments);
@@ -1197,7 +1180,7 @@
     } else {
       if (!shaker.isMemberBodyReachable(node.target)) {
         // Annotations could contain references to constant fields.
-        assertx((node.target is Field) && (node.target as Field).isConst);
+        assert((node.target is Field) && (node.target as Field).isConst);
         shaker.addUsedMember(node.target);
       }
       return node;
@@ -1217,7 +1200,8 @@
       return _makeUnreachableCall([node.value]);
     } else {
       final target = node.target;
-      assertx(shaker.isMemberBodyReachable(target), details: node);
+      assert(shaker.isMemberBodyReachable(target),
+          "Target should be reachable: $node");
       if (target is Field && !shaker.retainField(target)) {
         return node.value;
       }
@@ -1226,45 +1210,6 @@
   }
 
   @override
-  TreeNode visitDirectMethodInvocation(DirectMethodInvocation node) {
-    node.transformChildren(this);
-    if (_isUnreachable(node)) {
-      return _makeUnreachableCall(
-          _flattenArguments(node.arguments, receiver: node.receiver));
-    } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node);
-      return node;
-    }
-  }
-
-  @override
-  TreeNode visitDirectPropertyGet(DirectPropertyGet node) {
-    node.transformChildren(this);
-    if (_isUnreachable(node)) {
-      return _makeUnreachableCall([node.receiver]);
-    } else {
-      final target = node.target;
-      assertx(shaker.isMemberBodyReachable(target), details: node);
-      assertx(target is! Field || shaker.isFieldGetterReachable(target),
-          details: node);
-      return node;
-    }
-  }
-
-  @override
-  TreeNode visitDirectPropertySet(DirectPropertySet node) {
-    node.transformChildren(this);
-    if (_isUnreachable(node)) {
-      return _makeUnreachableCall([node.receiver, node.value]);
-    } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node);
-      node.target =
-          fieldMorpher.adjustInstanceCallTarget(node.target, isSetter: true);
-      return node;
-    }
-  }
-
-  @override
   TreeNode visitConstructorInvocation(ConstructorInvocation node) {
     node.transformChildren(this);
     if (_isUnreachable(node)) {
@@ -1272,7 +1217,7 @@
     } else {
       if (!shaker.isMemberBodyReachable(node.target)) {
         // Annotations could contain references to const constructors.
-        assertx(node.isConst);
+        assert(node.isConst);
         shaker.addUsedMember(node.target);
       }
       if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
@@ -1288,7 +1233,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer(_flattenArguments(node.arguments));
     } else {
-      assertx(shaker.isMemberBodyReachable(node.target), details: node.target);
+      assert(shaker.isMemberBodyReachable(node.target),
+          "Target should be reachable: ${node.target}");
       if (!shaker._signatureShaker.isShakingSignature(node.target)) return node;
       _fixArgumentEvaluationOrderInInitializer(node.arguments);
       _rewriteArguments(node.arguments, node.target);
@@ -1316,7 +1262,8 @@
     if (_isUnreachable(node)) {
       return _makeUnreachableInitializer([node.value]);
     } else {
-      assertx(shaker.isMemberBodyReachable(node.field), details: node.field);
+      assert(shaker.isMemberBodyReachable(node.field),
+          "Field should be reachable: ${node.field}");
       if (!shaker.retainField(node.field)) {
         if (mayHaveSideEffects(node.value)) {
           return LocalInitializer(
@@ -1373,7 +1320,7 @@
   Procedure get unsafeCast {
     _unsafeCast ??= shaker.typeFlowAnalysis.environment.coreTypes.index
         .getTopLevelMember('dart:_internal', 'unsafeCast');
-    assertx(_unsafeCast != null);
+    assert(_unsafeCast != null);
     return _unsafeCast;
   }
 }
@@ -1439,7 +1386,7 @@
       node.typeParameters.clear();
       node.isAbstract = true;
       // Mixin applications cannot have static members.
-      assertx(node.mixedInType == null);
+      assert(node.mixedInType == null);
       node.annotations = const <Expression>[];
     }
 
@@ -1547,7 +1494,7 @@
       node.members.length = writeIndex;
 
       // We only retain the extension if at least one member is retained.
-      assertx(node.members.length > 0);
+      assert(node.members.length > 0);
       return node;
     }
     return null;
@@ -1597,7 +1544,7 @@
   }
 
   void defer(Member m) {
-    assertx(isShakingSignature(m));
+    assert(isShakingSignature(m));
     deferred.add(m);
   }
 
@@ -1606,7 +1553,7 @@
   void _update(Member member) {
     final alwaysPassedOptionals =
         analysis.alwaysPassedOptionalParameters(member);
-    assertx(alwaysPassedOptionals.isNotEmpty);
+    assert(alwaysPassedOptionals.isNotEmpty);
 
     final func = member.function;
     final newPositional =
diff --git a/pkg/vm/lib/transformations/type_flow/types.dart b/pkg/vm/lib/transformations/type_flow/types.dart
index 4a07a98..e7e0c1d 100644
--- a/pkg/vm/lib/transformations/type_flow/types.dart
+++ b/pkg/vm/lib/transformations/type_flow/types.dart
@@ -25,6 +25,10 @@
   /// instances specific to given [TypeHierarchy].
   TFClass(this.id, this.classNode);
 
+  /// Returns ConcreteType corresponding to this class without
+  /// any extra attributes.
+  ConcreteType get concreteType => ConcreteType(this);
+
   @override
   int get hashCode => id;
 
@@ -231,8 +235,8 @@
   final Type baseType;
 
   NullableType(this.baseType) {
-    assertx(baseType != null);
-    assertx(baseType is! NullableType);
+    assert(baseType != null);
+    assert(baseType is! NullableType);
   }
 
   @override
@@ -346,8 +350,8 @@
 
   /// Creates a new SetType using list of concrete types sorted by classId.
   SetType(this.types) {
-    assertx(types.length >= 2);
-    assertx(isSorted(types));
+    assert(types.length >= 2);
+    assert(isSorted(types));
   }
 
   @override
@@ -457,12 +461,40 @@
     return types;
   }
 
+  bool _isSubList(List<ConcreteType> sublist, List<ConcreteType> list) {
+    int i1 = 0;
+    int i2 = 0;
+    while ((i1 < sublist.length) && (i2 < list.length)) {
+      final t1 = sublist[i1];
+      final t2 = list[i2];
+      if (identical(t1, t2)) {
+        ++i1;
+        ++i2;
+      } else if (t1.cls.id > t2.cls.id) {
+        ++i2;
+      } else {
+        return false;
+      }
+    }
+    return i1 == sublist.length;
+  }
+
   @override
   Type union(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
     if (other.order < this.order) {
       return other.union(this, typeHierarchy);
     }
     if (other is SetType) {
+      if (types.length >= other.types.length) {
+        if (_isSubList(other.types, types)) {
+          return this;
+        }
+      } else {
+        if (_isSubList(types, other.types)) {
+          return other;
+        }
+      }
       return new SetType(_unionLists(types, other.types));
     } else if (other is ConcreteType) {
       return types.contains(other)
@@ -479,6 +511,7 @@
 
   @override
   Type intersection(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
     if (other.order < this.order) {
       return other.intersection(this, typeHierarchy);
     }
@@ -559,6 +592,7 @@
 
   @override
   Type union(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
     if (other.order < this.order) {
       return other.union(this, typeHierarchy);
     }
@@ -582,6 +616,7 @@
 
   @override
   Type intersection(Type other, TypeHierarchy typeHierarchy) {
+    if (identical(this, other)) return this;
     if (other.order < this.order) {
       return other.intersection(this, typeHierarchy);
     }
@@ -635,12 +670,13 @@
         numImmediateTypeArgs =
             typeArgs_ != null ? cls.classNode.typeParameters.length : 0 {
     // TODO(alexmarkov): support closures
-    assertx(!cls.classNode.isAbstract);
-    assertx(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
-    assertx(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
+    assert(!cls.classNode.isAbstract);
+    assert(typeArgs == null || cls.classNode.typeParameters.isNotEmpty);
+    assert(typeArgs == null || typeArgs.any((t) => t is RuntimeType));
   }
 
-  ConcreteType get raw => new ConcreteType(cls, null);
+  ConcreteType get raw => cls.concreteType;
+  bool get isRaw => typeArgs == null && constant == null;
 
   @override
   Class getConcreteClass(TypeHierarchy typeHierarchy) => cls.classNode;
@@ -680,7 +716,7 @@
       final interfaceOffset =
           typeHierarchy.genericInterfaceOffsetFor(cls.classNode, rhs.classNode);
 
-      assertx(usableTypeArgs.length - interfaceOffset >=
+      assert(usableTypeArgs.length - interfaceOffset >=
           runtimeType.numImmediateTypeArgs);
 
       for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
@@ -688,7 +724,7 @@
         if (ta is UnknownType) {
           return false;
         }
-        assertx(ta is RuntimeType);
+        assert(ta is RuntimeType);
         if (!ta.isSubtypeOfRuntimeType(
             typeHierarchy, runtimeType.typeArgs[i])) {
           return false;
@@ -787,7 +823,7 @@
             : <ConcreteType>[other, this];
         return new SetType(types);
       } else {
-        assertx(typeArgs != null ||
+        assert(typeArgs != null ||
             constant != null ||
             other.typeArgs != null ||
             other.constant != null);
@@ -889,18 +925,18 @@
             ? type.classNode.typeParameters.length
             : (type is FutureOrType ? 1 : 0) {
     if (_type is InterfaceType && numImmediateTypeArgs > 0) {
-      assertx(typeArgs != null);
-      assertx(typeArgs.length >= numImmediateTypeArgs);
-      assertx((_type as InterfaceType)
+      assert(typeArgs != null);
+      assert(typeArgs.length >= numImmediateTypeArgs);
+      assert((_type as InterfaceType)
           .typeArguments
           .every((t) => t == const DynamicType()));
     } else if (_type is FutureOrType) {
-      assertx(typeArgs != null);
-      assertx(typeArgs.length >= numImmediateTypeArgs);
+      assert(typeArgs != null);
+      assert(typeArgs.length >= numImmediateTypeArgs);
       DartType typeArgument = (_type as FutureOrType).typeArgument;
-      assertx(typeArgument == const DynamicType());
+      assert(typeArgument == const DynamicType());
     } else {
-      assertx(typeArgs == null);
+      assert(typeArgs == null);
     }
   }
 
@@ -945,7 +981,7 @@
     if (identical(this, other)) return true;
     if (other is RuntimeType) {
       if (other._type != _type) return false;
-      assertx(numImmediateTypeArgs == other.numImmediateTypeArgs);
+      assert(numImmediateTypeArgs == other.numImmediateTypeArgs);
       return typeArgs == null || listEquals(typeArgs, other.typeArgs);
     }
     return false;
@@ -1056,13 +1092,13 @@
 
     List<Type> usableTypeArgs = typeArgs;
     if (usableTypeArgs == null) {
-      assertx(thisClass.typeParameters.isEmpty);
+      assert(thisClass.typeParameters.isEmpty);
       usableTypeArgs =
           typeHierarchy.flattenedTypeArgumentsForNonGeneric(thisClass);
     }
     final interfaceOffset =
         typeHierarchy.genericInterfaceOffsetFor(thisClass, otherClass);
-    assertx(usableTypeArgs.length - interfaceOffset >=
+    assert(usableTypeArgs.length - interfaceOffset >=
         runtimeType.numImmediateTypeArgs);
     for (int i = 0; i < runtimeType.numImmediateTypeArgs; ++i) {
       if (!usableTypeArgs[interfaceOffset + i]
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 0e9dad1..f105c4f 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -57,8 +57,8 @@
             final getterId = tableSelectorAssigner.getterSelectorId(field);
             final setterId =
                 tableSelectorAssigner.methodOrSetterSelectorId(field);
-            assertx(getterId != kInvalidSelectorId);
-            assertx(setterId != kInvalidSelectorId);
+            assert(getterId != kInvalidSelectorId);
+            assert(setterId != kInvalidSelectorId);
             selectorUnionFind.union(getterId, setterId);
           }
         }
@@ -85,7 +85,7 @@
             member is Field || member is Procedure && member.isGetter
                 ? tableSelectorAssigner.getterSelectorId(member)
                 : tableSelectorAssigner.methodOrSetterSelectorId(member);
-        assertx(selectorId != kInvalidSelectorId);
+        assert(selectorId != kInvalidSelectorId);
         selectorId = selectorUnionFind.find(selectorId);
         info = selectorIdToInfo[selectorId];
         if (info == null) {
@@ -126,13 +126,13 @@
       }
       if (member is Procedure || member is Constructor) {
         final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
-        assertx(argTypes != null);
+        assert(argTypes != null);
 
         final int firstParamIndex =
             numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
 
         final positionalParams = member.function.positionalParameters;
-        assertx(argTypes.positionalCount ==
+        assert(argTypes.positionalCount ==
             firstParamIndex + positionalParams.length);
 
         for (int i = 0; i < positionalParams.length; i++) {
@@ -156,7 +156,7 @@
         }
         _applyToReturn(unboxingInfo, fieldValue);
       } else {
-        assertx(false);
+        assert(false, "Unexpected member: $member");
       }
     }
   }
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 79e7d7d..ca2e212 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -29,13 +29,6 @@
 const int kScopeIndent =
     const int.fromEnvironment('global.type.flow.scope.indent', defaultValue: 1);
 
-/// Extended 'assert': always checks condition.
-assertx(bool cond, {details}) {
-  if (!cond) {
-    throw 'Assertion failed.' + (details != null ? ' Details: $details' : '');
-  }
-}
-
 abstract class _Logger {
   log(Object message, [int scopeChange = 0]);
 }
@@ -292,7 +285,7 @@
     if (id1 == id2) return;
     final int w1 = _elements[id1];
     final int w2 = _elements[id2];
-    assertx(w1 < 0 && w2 < 0);
+    assert(w1 < 0 && w2 < 0);
     if (w1 < w2) {
       _elements[id1] += w2;
       _elements[id2] = id1;
@@ -322,7 +315,7 @@
     (expr is ConstantExpression && expr.constant is NullConstant);
 
 Expression getArgumentOfComparisonWithNull(MethodInvocation node) {
-  if (node.name.name == '==') {
+  if (node.name.text == '==') {
     final lhs = node.receiver;
     final rhs = node.arguments.positional.single;
     if (isNullLiteral(lhs)) {
diff --git a/pkg/vm/lib/transformations/unreachable_code_elimination.dart b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
index 6dd07b5..8444ce7 100644
--- a/pkg/vm/lib/transformations/unreachable_code_elimination.dart
+++ b/pkg/vm/lib/transformations/unreachable_code_elimination.dart
@@ -79,22 +79,23 @@
     node.transformChildren(this);
     final left = node.left;
     final right = node.right;
-    final operator = node.operator;
+    final operatorEnum = node.operatorEnum;
     if (_isBoolConstant(left)) {
       final leftValue = _getBoolConstantValue(left);
       if (_isBoolConstant(right)) {
         final rightValue = _getBoolConstantValue(right);
-        if (operator == '||') {
+        if (operatorEnum == LogicalExpressionOperator.OR) {
           return _createBoolLiteral(leftValue || rightValue, node.fileOffset);
-        } else if (operator == '&&') {
+        } else if (operatorEnum == LogicalExpressionOperator.AND) {
           return _createBoolLiteral(leftValue && rightValue, node.fileOffset);
         } else {
-          throw 'Unexpected LogicalExpression operator ${operator}: $node';
+          throw 'Unexpected LogicalExpression operator ${operatorEnum}: $node';
         }
       } else {
-        if (leftValue && operator == '||') {
+        if (leftValue && operatorEnum == LogicalExpressionOperator.OR) {
           return _createBoolLiteral(true, node.fileOffset);
-        } else if (!leftValue && operator == '&&') {
+        } else if (!leftValue &&
+            operatorEnum == LogicalExpressionOperator.AND) {
           return _createBoolLiteral(false, node.fileOffset);
         }
       }
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index bb04201..5e58043 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -522,11 +522,11 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  DirectCall           CP#0, 1
+  InterfaceCall        CP#0, 1
   ReturnTOS
 }
 ConstantPool {
-  [0] = DirectCall '#lib::A::get:_name', ArgDesc num-args 1, num-type-args 0, names []
+  [0] = InterfaceCall '#lib::A::get:_name', ArgDesc num-args 1, num-type-args 0, names []
   [1] = Reserved
 }
 
@@ -852,7 +852,7 @@
       : #lib::A::index = index, #lib::A::_name = _name, super dart.core::Object::•()
       ;
     method toString() → dart.core::String*
-      return this.{=#lib::A::_name};
+      return this.{#lib::A::_name};
     abstract member-signature get _identityHashCode() → dart.core::int*; -> dart.core::Object::_identityHashCode
     abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → dart.core::bool*; -> dart.core::Object::_instanceOf
     abstract member-signature method _simpleInstanceOf(dynamic type) → dart.core::bool*; -> dart.core::Object::_simpleInstanceOf
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
index 6ee10df..a894b41 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/constants.dart.expect
@@ -6,14 +6,14 @@
 RESULT: _T (dart.core::int)+
 ------------ strLiteral ------------
 
-RESULT: _T (dart.core::_OneByteString, abc)
+RESULT: _T (dart.core::_OneByteString, "abc")
 ------------ indexingIntoConstantList1 ------------
 %i = _Parameter #0 [_T (dart.core::int)+?]
 t1 = _Join [dart.core::int*] (_T (dart.core::_Smi, 1), _T (dart.core::_Smi, 2), _T (dart.core::_Smi, 3))
 RESULT: t1
 ------------ indexingIntoConstantList2 ------------
 %i = _Parameter #0 [_T (dart.core::int)+?]
-t1 = _Join [dart.core::Object*] (_T (dart.core::_OneByteString, hi), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
+t1 = _Join [dart.core::Object*] (_T (dart.core::_OneByteString, "hi"), _T (dart.core::_Smi, 33), _T {}?, _T (dart.core::_Smi, -5))
 RESULT: t1
 ------------ main ------------
 
@@ -23,4 +23,4 @@
 RESULT: _T (dart.core::_ImmutableList, const <dart.core::int*>[1, 2, 3])
 ------------ _constList2 ------------
 
-RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object*>[hi, 33, null, -5])
+RESULT: _T (dart.core::_ImmutableList, const <dart.core::Object*>["hi", 33, null, -5])
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
index e723799..250bacb 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/control_flow.dart.expect
@@ -24,17 +24,17 @@
 RESULT: _T {}?
 ------------ TestEnum.toString ------------
 %this = _Parameter #0 [_T (#lib::TestEnum)+]
-t1* = _Call direct get [#lib::TestEnum._name] (%this)
+t1* = _Call virtual get [#lib::TestEnum._name] (%this)
 RESULT: t1
 ------------ TestEnum.values ------------
 
-RESULT: _T (dart.core::_ImmutableList, const <#lib::TestEnum*>[const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: TestEnum.v1}, const #lib::TestEnum{#lib::TestEnum.index: 1, #lib::TestEnum._name: TestEnum.v2}])
+RESULT: _T (dart.core::_ImmutableList, const <#lib::TestEnum*>[const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}, const #lib::TestEnum{#lib::TestEnum.index: 1, #lib::TestEnum._name: "TestEnum.v2"}])
 ------------ TestEnum.v1 ------------
 
-RESULT: _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: TestEnum.v1})
+RESULT: _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"})
 ------------ TestEnum.v2 ------------
 
-RESULT: _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 1, #lib::TestEnum._name: TestEnum.v2})
+RESULT: _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 1, #lib::TestEnum._name: "TestEnum.v2"})
 ------------ foo ------------
 %x = _Parameter #0 [_T ANY?]
 RESULT: _T {}?
@@ -115,11 +115,11 @@
 %y = _Parameter #1 [_T (dart.core::String)+?]
 %z = _Parameter #2 [_T ANY?]
 t3* = _Call [dart.core::num.==] (%x, _T (dart.core::_Smi, 5))
-t4* = _Call [dart.core::String.==] (%y, _T (dart.core::_OneByteString, hi))
+t4* = _Call [dart.core::String.==] (%y, _T (dart.core::_OneByteString, "hi"))
 t5 = _Call direct [dart.core::Object.==] (%z, _T {}?)
 t6 = _Narrow (%z to _T ANY)
 t7 = _Call direct [#lib::foo] (_T (dart.core::_Smi, 5))
-t8 = _Call direct [#lib::foo] (_T (dart.core::_OneByteString, hi))
+t8 = _Call direct [#lib::foo] (_T (dart.core::_OneByteString, "hi"))
 t9 = _Call direct [#lib::foo] (t6)
 RESULT: _T {}?
 ------------ if8 ------------
@@ -129,8 +129,8 @@
 RESULT: _T {}?
 ------------ if9 ------------
 %x = _Parameter #0 [_T (#lib::TestEnum)+?]
-t1* = _Call [#lib::TestEnum.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: TestEnum.v1}))
-t2 = _Call direct [#lib::foo] (_T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: TestEnum.v1}))
+t1* = _Call [#lib::TestEnum.==] (%x, _T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
+t2 = _Call direct [#lib::foo] (_T (#lib::TestEnum, const #lib::TestEnum{#lib::TestEnum.index: 0, #lib::TestEnum._name: "TestEnum.v1"}))
 RESULT: _T {}?
 ------------ conditional1 ------------
 %cond1 = _Parameter #0 [_T (dart.core::bool)+?]
diff --git a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
index 436841d..413dedb 100644
--- a/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/summary_collector/hello.dart.expect
@@ -1,4 +1,4 @@
 ------------ main ------------
 %args = _Parameter #0 [_T (dart.core::List)+?]
-t1 = _Call direct [dart.core::print] (_T (dart.core::_OneByteString, Hello, world!))
+t1 = _Call direct [dart.core::print] (_T (dart.core::_OneByteString, "Hello, world!"))
 RESULT: _T {}?
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
index 5394341..76d2329 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/const_prop.dart.expect
@@ -13,9 +13,9 @@
 }
 class B extends core::Object /*isEnum*/  {
 [@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] [@vm.unboxing-info.metadata=()->i]  final field core::int* index;
-[@vm.inferred-type.metadata=dart.core::_OneByteString (value: B.b2)] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::String* _name;
+[@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  final field core::String* _name;
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7]  method toString() → core::String*
-    return [@vm.inferred-type.metadata=dart.core::_OneByteString (value: B.b2)] this.{=self::B::_name};
+    return [@vm.direct-call.metadata=#lib::B._name] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "B.b2")] this.{self::B::_name};
 }
 [@vm.unboxing-info.metadata=(i)->b]static method test0([@vm.inferred-type.metadata=dart.core::_Smi (value: 40)] core::int* arg) → void {
   core::print(arg);
@@ -32,15 +32,15 @@
   core::print(arg);
   core::print([@vm.inferred-type.metadata=dart.core::_Double (value: 100.0)] self::getD);
 }
-static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A* a0, [@vm.inferred-type.metadata=dart.core::_OneByteString (value: bazz)] core::String* a1) → void {
-  core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: foo)] a0.{self::A::foo});
-  core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: bar)] a0.{self::A::getBar}());
+static method testStrings([@vm.inferred-type.metadata=#lib::A] self::A* a0, [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "bazz")] core::String* a1) → void {
+  core::print([@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=dart.core::_OneByteString (value: "foo")] a0.{self::A::foo});
+  core::print([@vm.direct-call.metadata=#lib::A.getBar] [@vm.inferred-type.metadata=dart.core::_OneByteString (skip check) (value: "bar")] a0.{self::A::getBar}());
   core::print(a1);
 }
-static method testPassEnum([@vm.inferred-type.metadata=#lib::B (value: const #lib::B{#lib::B.index: 1, #lib::B._name: B.b2})] self::B* arg) → void {
+static method testPassEnum([@vm.inferred-type.metadata=#lib::B (value: const #lib::B{#lib::B.index: 1, #lib::B._name: "B.b2"})] self::B* arg) → void {
   self::testPassEnum2(arg);
 }
-static method testPassEnum2([@vm.inferred-type.metadata=#lib::B (value: const #lib::B{#lib::B.index: 1, #lib::B._name: B.b2})] self::B* arg) → void {
+static method testPassEnum2([@vm.inferred-type.metadata=#lib::B (value: const #lib::B{#lib::B.index: 1, #lib::B._name: "B.b2"})] self::B* arg) → void {
   core::print(arg);
 }
 static method getList() → dynamic
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
index edc8a9b..4c6d0e1 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/devirt.dart.expect
@@ -48,7 +48,7 @@
 static method callerA4([@vm.inferred-type.metadata=#lib::D?] self::A* aa) → void {
   [@vm.direct-call.metadata=#lib::C.foo??] [@vm.inferred-type.metadata=!? (skip check)] aa.{self::A::foo}();
 }
-static method callerE1([@vm.inferred-type.metadata=dart.core::_OneByteString (value: abc)] dynamic x) → void {
+static method callerE1([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "abc")] dynamic x) → void {
   [@vm.direct-call.metadata=dart.core::_StringBase.toString] [@vm.inferred-type.metadata=!? (skip check) (receiver not int)] x.{core::Object::toString}();
 }
 static method callerE2([@vm.inferred-type.metadata=#lib::E?] dynamic x) → void {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
index bfde4ce..101cd55 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination.dart.expect
@@ -25,9 +25,9 @@
   return _in::unsafeCast<core::int*>(x);
 static method testInt2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
   return _in::unsafeCast<core::int*>(x);
-static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: hi)] dynamic x) → dynamic
+static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "hi")] dynamic x) → dynamic
   return _in::unsafeCast<dynamic>(x);
-static method testObject([@vm.inferred-type.metadata=dart.core::_OneByteString (value: bye)] dynamic x) → dynamic
+static method testObject([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "bye")] dynamic x) → dynamic
   return x;
 static method testBOfInt([@vm.inferred-type.metadata=#lib::B<dart.core::int*>] dynamic x) → dynamic
   return _in::unsafeCast<self::B<core::int*>*>(x);
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart.expect
index 74ab653..11d1e0b 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd.dart.expect
@@ -31,7 +31,7 @@
   return _in::unsafeCast<core::int?>(x);
 static method testNullableInt2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
   return _in::unsafeCast<core::int?>(x);
-static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: hi)] dynamic x) → dynamic
+static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "hi")] dynamic x) → dynamic
   return _in::unsafeCast<dynamic>(x);
 static method testObject([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
   return x;
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
index b944e65..10ac8a6 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/type_cast_elimination_nnbd_strong.dart.expect
@@ -31,7 +31,7 @@
   return _in::unsafeCast<core::int?>(x);
 static method testNullableInt2([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
   return _in::unsafeCast<core::int?>(x);
-static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: hi)] dynamic x) → dynamic
+static method testDynamic([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "hi")] dynamic x) → dynamic
   return _in::unsafeCast<dynamic>(x);
 static method testObjectNegative([@vm.inferred-type.metadata=dart.core::Null? (value: null)] dynamic x) → dynamic
   return let dynamic #t1 = x in true ?{core::Object} #t1 as{ForNonNullableByDefault} core::Object : #t1{core::Object};
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index ecf01b8..082ed50 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -12,7 +12,7 @@
     ;
 }
 class B extends core::Object {
-  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString (value: hi)] dynamic unused4) → self::B*
+  constructor •([@vm.inferred-type.metadata=dart.core::_OneByteString (value: "hi")] dynamic unused4) → self::B*
     : dynamic #t1 = [@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::foo(), super core::Object::•()
     ;
 }
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 049e01d1..ca07f4f 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,21 @@
 # Changelog
 
+## 5.3.0
+- Added support for `dart:io` extensions version 1.4.
+- Update to version `3.40.0` of the spec.
+- Added `IsolateFlag` class.
+- Added `isolateFlags` property to `Isolate`.
+
+## 5.2.0
+- Added support for `dart:io` extensions version 1.3.
+- Added combination getter/setter `httpEnableTimelineLogging`.
+- Deprecated `getHttpEnableTimelineLogging` and `setHttpEnableTimelineLogging`.
+
+## 5.1.0
+- Added support for `dart:io` extensions version 1.2.
+- Added `getOpenFiles`, `getOpenFileById`, `getSpawnedProcesses`, and `getSpawnedProcessById` RPCs.
+- Added `OpenFileList`, `OpenFileRef`, `OpenFile`, `SpawnedProcessList`, `SpawnedProcessRef`, and `SpawnedProcess` objects.
+
 ## 5.0.0
 
 - **breaking**: Update to version `3.39.0` of the spec.
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index 52746bd..e2ae6d1 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -47,6 +47,13 @@
   return list;
 }
 
+List<vms.IsolateFlag> assertListOfIsolateFlag(List<vms.IsolateFlag> list) {
+  for (vms.IsolateFlag elem in list) {
+    assertIsolateFlag(elem);
+  }
+  return list;
+}
+
 String assertString(String obj) {
   assertNotNull(obj);
   if (obj.isEmpty) throw 'expected non-zero length string';
@@ -667,6 +674,7 @@
   assertString(obj.number);
   assertString(obj.name);
   assertBool(obj.isSystemIsolate);
+  assertListOfIsolateFlag(obj.isolateFlags);
   assertInt(obj.startTime);
   assertBool(obj.runnable);
   assertInt(obj.livePorts);
@@ -678,6 +686,13 @@
   return obj;
 }
 
+vms.IsolateFlag assertIsolateFlag(vms.IsolateFlag obj) {
+  assertNotNull(obj);
+  assertString(obj.name);
+  assertString(obj.valueAsString);
+  return obj;
+}
+
 vms.IsolateGroupRef assertIsolateGroupRef(vms.IsolateGroupRef obj) {
   assertNotNull(obj);
   assertString(obj.type);
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index fbcce7d..ae6691f 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -79,6 +79,7 @@
 src/org/dartlang/vm/service/element/InstanceRef.java
 src/org/dartlang/vm/service/element/InstanceSet.java
 src/org/dartlang/vm/service/element/Isolate.java
+src/org/dartlang/vm/service/element/IsolateFlag.java
 src/org/dartlang/vm/service/element/IsolateGroup.java
 src/org/dartlang/vm/service/element/IsolateGroupRef.java
 src/org/dartlang/vm/service/element/IsolateRef.java
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index e076127..d0564a6 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.39
+version=3.40
diff --git a/pkg/vm_service/lib/src/dart_io_extensions.dart b/pkg/vm_service/lib/src/dart_io_extensions.dart
index 4297e45..886b947 100644
--- a/pkg/vm_service/lib/src/dart_io_extensions.dart
+++ b/pkg/vm_service/lib/src/dart_io_extensions.dart
@@ -4,12 +4,22 @@
 
 // TODO(bkonyi): autogenerate from service_extensions.md
 
+import 'dart:collection';
+
 import 'package:meta/meta.dart';
 
 import 'vm_service.dart';
 
 extension DartIOExtension on VmService {
   static bool _factoriesRegistered = false;
+  static Map<String, Version> _isolateVersion = {};
+
+  Future<Version> _version(String isolateId) async {
+    if (_isolateVersion[isolateId] == null) {
+      _isolateVersion[isolateId] = await getDartIOVersion(isolateId);
+    }
+    return _isolateVersion[isolateId];
+  }
 
   /// The `getDartIOVersion` RPC returns the available version of the dart:io
   /// service protocol extensions.
@@ -41,6 +51,7 @@
   ///
   /// Warning: The returned [Future] will not complete if the target isolate is paused
   /// and will only complete when the isolate is resumed.
+  @Deprecated('Use httpEnableTimelineLogging instead.')
   Future<HttpTimelineLoggingState> getHttpEnableTimelineLogging(
           String isolateId) =>
       _callHelper('ext.dart.io.getHttpEnableTimelineLogging', isolateId);
@@ -49,11 +60,69 @@
   ///
   /// Warning: The returned [Future] will not complete if the target isolate is paused
   /// and will only complete when the isolate is resumed.
+  @Deprecated('Use httpEnableTimelineLogging instead.')
   Future<Success> setHttpEnableTimelineLogging(String isolateId, bool enable) =>
       _callHelper('ext.dart.io.setHttpEnableTimelineLogging', isolateId, args: {
         'enable': enable,
       });
 
+  /// The _httpEnableTimelineLogging_ RPC is used to set and inspect the value of
+  /// `HttpClient.enableTimelineLogging`, which determines if HTTP client requests
+  /// should be logged to the timeline. If `enabled` is provided, the state of
+  /// `HttpClient.enableTimelineLogging` will be updated to the value of `enabled`.
+  ///
+  /// If the value of `HttpClient.enableTimelineLogging` is changed, a
+  /// `HttpTimelineLoggingStateChange` event will be sent on the `Extension` stream.
+  Future<HttpTimelineLoggingState> httpEnableTimelineLogging(String isolateId,
+      [bool enabled]) async {
+    final version = await _version(isolateId);
+    // Parameter name changed in version 1.4.
+    final enableKey =
+        ((version.major == 1 && version.minor > 3) || version.major >= 2)
+            ? 'enabled'
+            : 'enable';
+    return _callHelper('ext.dart.io.httpEnableTimelineLogging', isolateId,
+        args: {
+          if (enabled != null) enableKey: enabled,
+        });
+  }
+
+  /// The `getOpenFiles` RPC is used to retrieve the list of files currently
+  /// opened files by `dart:io` from a given isolate.
+  Future<OpenFileList> getOpenFiles(String isolateId) => _callHelper(
+        'ext.dart.io.getOpenFiles',
+        isolateId,
+      );
+
+  /// The `getOpenFileById` RPC is used to retrieve information about files
+  /// currently opened by `dart:io` from a given isolate.
+  Future<OpenFile> getOpenFileById(String isolateId, int id) => _callHelper(
+        'ext.dart.io.getOpenFileById',
+        isolateId,
+        args: {
+          'id': id,
+        },
+      );
+
+  /// The `getSpawnedProcesses` RPC is used to retrieve the list of processed opened
+  /// by `dart:io` from a given isolate
+  Future<SpawnedProcessList> getSpawnedProcesses(String isolateId) =>
+      _callHelper(
+        'ext.dart.io.getSpawnedProcesses',
+        isolateId,
+      );
+
+  /// The `getSpawnedProcessById` RPC is used to retrieve information about a process
+  /// spawned by `dart:io` from a given isolate.
+  Future<SpawnedProcess> getSpawnedProcessById(String isolateId, int id) =>
+      _callHelper(
+        'ext.dart.io.getSpawnedProcessById',
+        isolateId,
+        args: {
+          'id': id,
+        },
+      );
+
   Future<T> _callHelper<T>(String method, String isolateId,
       {Map args = const {}}) {
     if (!_factoriesRegistered) {
@@ -70,9 +139,15 @@
   }
 
   static void _registerFactories() {
-    addTypeFactory('SocketStatistic', SocketStatistic.parse);
-    addTypeFactory('SocketProfile', SocketProfile.parse);
+    addTypeFactory('OpenFile', OpenFile.parse);
+    addTypeFactory('OpenFileList', OpenFileList.parse);
+    addTypeFactory('@OpenFile', OpenFileRef.parse);
     addTypeFactory('HttpTimelineLoggingState', HttpTimelineLoggingState.parse);
+    addTypeFactory('SpawnedProcess', SpawnedProcess.parse);
+    addTypeFactory('SpawnedProcessList', SpawnedProcessList.parse);
+    addTypeFactory('@SpawnedProcess', SpawnedProcessRef.parse);
+    addTypeFactory('SocketProfile', SocketProfile.parse);
+    addTypeFactory('SocketStatistic', SocketStatistic.parse);
     _factoriesRegistered = true;
   }
 }
@@ -162,3 +237,206 @@
   /// Whether or not HttpClient.enableTimelineLogging is set to true for a given isolate.
   final bool enabled;
 }
+
+/// A [SpawnedProcessRef] contains identifying information about a spawned process.
+class SpawnedProcessRef {
+  static SpawnedProcessRef parse(Map json) =>
+      json == null ? null : SpawnedProcessRef._fromJson(json);
+
+  SpawnedProcessRef({
+    @required this.id,
+    @required this.name,
+  });
+
+  SpawnedProcessRef._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        id = json['id'],
+        name = json['name'];
+
+  static const String type = 'SpawnedProcessRef';
+
+  /// The unique ID associated with this process.
+  final int id;
+
+  /// The name of the executable.
+  final String name;
+}
+
+/// A [SpawnedProcess] contains startup information of a spawned process.
+class SpawnedProcess extends Response implements SpawnedProcessRef {
+  static SpawnedProcess parse(Map json) =>
+      json == null ? null : SpawnedProcess._fromJson(json);
+
+  SpawnedProcess({
+    @required this.id,
+    @required this.name,
+    @required this.pid,
+    @required this.startedAt,
+    @required List<String> arguments,
+    @required this.workingDirectory,
+  }) : _arguments = arguments;
+
+  SpawnedProcess._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        id = json['id'],
+        name = json['name'],
+        pid = json['pid'],
+        startedAt = json['startedAt'],
+        _arguments = List<String>.from(
+            createServiceObject(json['arguments'], const ['String']) as List ??
+                []),
+        workingDirectory = json['workingDirectory'] {
+    type = json['type'];
+  }
+
+  /// The unique ID associated with this process.
+  final int id;
+
+  /// The name of the executable.
+  final String name;
+
+  /// The process ID associated with the process.
+  final int pid;
+
+  /// The time the process was started in milliseconds since epoch.
+  final int startedAt;
+
+  /// The list of arguments provided to the process at launch.
+  List<String> get arguments => UnmodifiableListView(_arguments);
+  final List<String> _arguments;
+
+  /// The working directory of the process at launch.
+  final String workingDirectory;
+}
+
+class SpawnedProcessList extends Response {
+  static SpawnedProcessList parse(Map json) =>
+      json == null ? null : SpawnedProcessList._fromJson(json);
+
+  SpawnedProcessList({@required List<SpawnedProcessRef> processes})
+      : _processes = processes;
+
+  SpawnedProcessList._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        _processes = List<SpawnedProcessRef>.from(
+            createServiceObject(json['processes'], const ['SpawnedProcessRef'])
+                    as List ??
+                []) {
+    type = json['type'];
+  }
+
+  /// A list of processes spawned through dart:io on a given isolate.
+  List<SpawnedProcessRef> get processes => UnmodifiableListView(_processes);
+  final List<SpawnedProcessRef> _processes;
+}
+
+/// A [OpenFileRef] contains identifying information about a currently opened file.
+class OpenFileRef {
+  static OpenFileRef parse(Map json) =>
+      json == null ? null : OpenFileRef._fromJson(json);
+
+  OpenFileRef({
+    @required this.id,
+    @required this.name,
+  });
+
+  OpenFileRef._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        id = json['id'],
+        name = json['name'];
+
+  static const String type = 'OpenFileRef';
+
+  /// The unique ID associated with this file.
+  final int id;
+
+  /// The path of the file.
+  final String name;
+}
+
+/// A [File] contains information about reads and writes to a currently opened file.
+class OpenFile extends Response implements OpenFileRef {
+  static OpenFile parse(Map json) =>
+      json == null ? null : OpenFile._fromJson(json);
+
+  OpenFile({
+    @required this.id,
+    @required this.name,
+    @required this.readBytes,
+    @required this.writeBytes,
+    @required this.readCount,
+    @required this.writeCount,
+    @required this.lastReadTime,
+    @required this.lastWriteTime,
+  });
+
+  OpenFile._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        id = json['id'],
+        name = json['name'],
+        readBytes = json['readBytes'],
+        writeBytes = json['writeBytes'],
+        readCount = json['readCount'],
+        writeCount = json['writeCount'],
+        lastReadTime =
+            DateTime.fromMillisecondsSinceEpoch(json['lastReadTime']),
+        lastWriteTime =
+            DateTime.fromMillisecondsSinceEpoch(json['lastWriteTime']) {
+    type = json['type'];
+  }
+
+  /// The unique ID associated with this file.
+  final int id;
+
+  /// The path of the file.
+  final String name;
+
+  /// The total number of bytes read from this file.
+  final int readBytes;
+
+  /// The total number of bytes written to this file.
+  final int writeBytes;
+
+  /// The number of reads made from this file.
+  final int readCount;
+
+  /// The number of writes made to this file.
+  final int writeCount;
+
+  /// The time at which this file was last read by this process.
+  final DateTime lastReadTime;
+
+  /// The time at which this file was last written to by this process.
+  final DateTime lastWriteTime;
+}
+
+class OpenFileList extends Response {
+  static OpenFileList parse(Map json) =>
+      json == null ? null : OpenFileList._fromJson(json);
+
+  OpenFileList({@required List<OpenFileRef> files}) : _files = files;
+
+  OpenFileList._fromJson(Map<String, dynamic> json)
+      :
+        // TODO(bkonyi): make this part of the vm_service.dart library so we can
+        // call super._fromJson.
+        _files = List<OpenFileRef>.from(
+            createServiceObject(json['files'], const ['OpenFileRef']) as List ??
+                []) {
+    type = json['type'];
+  }
+
+  /// A list of all files opened through dart:io on a given isolate.
+  List<OpenFileRef> get files => UnmodifiableListView(_files);
+  final List<OpenFileRef> _files;
+}
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 4f63e01..fd20c5b 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -28,7 +28,7 @@
         HeapSnapshotObjectNoData,
         HeapSnapshotObjectNullData;
 
-const String vmServiceVersion = '3.39.0';
+const String vmServiceVersion = '3.40.0';
 
 /// @optional
 const String optional = 'optional';
@@ -139,6 +139,7 @@
   'Instance': Instance.parse,
   '@Isolate': IsolateRef.parse,
   'Isolate': Isolate.parse,
+  'IsolateFlag': IsolateFlag.parse,
   '@IsolateGroup': IsolateGroupRef.parse,
   'IsolateGroup': IsolateGroup.parse,
   'InboundReferences': InboundReferences.parse,
@@ -4745,6 +4746,10 @@
   /// internal use. If `false`, this isolate is likely running user code.
   bool isSystemIsolate;
 
+  /// The list of isolate flags provided to this isolate. See Dart_IsolateFlags
+  /// in dart_api.h for the list of accepted isolate flags.
+  List<IsolateFlag> isolateFlags;
+
   /// The time that the VM started in milliseconds since the epoch.
   ///
   /// Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
@@ -4794,6 +4799,7 @@
     @required this.number,
     @required this.name,
     @required this.isSystemIsolate,
+    @required this.isolateFlags,
     @required this.startTime,
     @required this.runnable,
     @required this.livePorts,
@@ -4812,6 +4818,8 @@
     number = json['number'];
     name = json['name'];
     isSystemIsolate = json['isSystemIsolate'];
+    isolateFlags = List<IsolateFlag>.from(
+        createServiceObject(json['isolateFlags'], const ['IsolateFlag']) ?? []);
     startTime = json['startTime'];
     runnable = json['runnable'];
     livePorts = json['livePorts'];
@@ -4838,6 +4846,7 @@
       'number': number,
       'name': name,
       'isSystemIsolate': isSystemIsolate,
+      'isolateFlags': isolateFlags.map((f) => f.toJson()).toList(),
       'startTime': startTime,
       'runnable': runnable,
       'livePorts': livePorts,
@@ -4861,6 +4870,40 @@
   String toString() => '[Isolate]';
 }
 
+/// Represents the value of a single isolate flag. See [Isolate].
+class IsolateFlag {
+  static IsolateFlag parse(Map<String, dynamic> json) =>
+      json == null ? null : IsolateFlag._fromJson(json);
+
+  /// The name of the flag.
+  String name;
+
+  /// The value of this flag as a string.
+  String valueAsString;
+
+  IsolateFlag({
+    @required this.name,
+    @required this.valueAsString,
+  });
+
+  IsolateFlag._fromJson(Map<String, dynamic> json) {
+    name = json['name'];
+    valueAsString = json['valueAsString'];
+  }
+
+  Map<String, dynamic> toJson() {
+    var json = <String, dynamic>{};
+    json.addAll({
+      'name': name,
+      'valueAsString': valueAsString,
+    });
+    return json;
+  }
+
+  String toString() =>
+      '[IsolateFlag name: ${name}, valueAsString: ${valueAsString}]';
+}
+
 /// `IsolateGroupRef` is a reference to an `IsolateGroup` object.
 class IsolateGroupRef extends Response {
   static IsolateGroupRef parse(Map<String, dynamic> json) =>
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 66b2910..690f8b6 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -2,7 +2,7 @@
 description: >-
   A library to communicate with a service implementing the Dart VM
   service protocol.
-version: 5.0.0+1
+version: 5.3.0
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/pkg/vm_service/test/common/test_helper.dart b/pkg/vm_service/test/common/test_helper.dart
index 1b19ba1..836e323 100644
--- a/pkg/vm_service/test/common/test_helper.dart
+++ b/pkg/vm_service/test/common/test_helper.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 import 'dart:convert';
-import 'dart:io';
+import 'dart:io' as io;
 import 'package:vm_service/vm_service_io.dart';
 import 'package:vm_service/vm_service.dart';
 import 'package:test/test.dart';
@@ -30,21 +30,22 @@
 const String _TESTEE_ENV_KEY = 'SERVICE_TEST_TESTEE';
 const Map<String, String> _TESTEE_SPAWN_ENV = {_TESTEE_ENV_KEY: 'true'};
 bool _isTestee() {
-  return Platform.environment.containsKey(_TESTEE_ENV_KEY);
+  return io.Platform.environment.containsKey(_TESTEE_ENV_KEY);
 }
 
 Uri _getTestUri() {
-  if (Platform.script.scheme == 'data') {
+  if (io.Platform.script.scheme == 'data') {
     // If we're using pub to run these tests this value isn't a file URI.
     // We'll need to parse the actual URI out...
     final fileRegExp = RegExp(r'file:\/\/\/.*\.dart');
-    final path = fileRegExp.stringMatch(Platform.script.data.contentAsString());
+    final path =
+        fileRegExp.stringMatch(io.Platform.script.data.contentAsString());
     if (path == null) {
       throw 'Unable to determine file path for script!';
     }
     return Uri.parse(path);
   } else {
-    return Platform.script;
+    return io.Platform.script;
   }
 }
 
@@ -72,7 +73,7 @@
     if (!pause_on_exit) {
       // Wait around for the process to be killed.
       // ignore: unawaited_futures
-      stdin.first.then((_) => exit(0));
+      io.stdin.first.then((_) => io.exit(0));
     }
   }
 
@@ -92,20 +93,20 @@
     }
     if (!pause_on_exit) {
       // Wait around for the process to be killed.
-      stdin.first.then((_) => exit(0));
+      io.stdin.first.then((_) => io.exit(0));
     }
   }
 }
 
 class _ServiceTesteeLauncher {
-  Process process;
+  io.Process process;
   List<String> args;
   bool killedByTester = false;
 
   _ServiceTesteeLauncher() : args = [_getTestUri().toFilePath()];
 
   // Spawn the testee process.
-  Future<Process> _spawnProcess(
+  Future<io.Process> _spawnProcess(
     bool pause_on_start,
     bool pause_on_exit,
     bool pause_on_unhandled_exceptions,
@@ -127,14 +128,14 @@
         extraArgs);
   }
 
-  Future<Process> _spawnDartProcess(
+  Future<io.Process> _spawnDartProcess(
       bool pause_on_start,
       bool pause_on_exit,
       bool pause_on_unhandled_exceptions,
       bool testeeControlsServer,
       bool useAuthToken,
       List<String> extraArgs) {
-    String dartExecutable = Platform.executable;
+    String dartExecutable = io.Platform.executable;
 
     var fullArgs = <String>[
       '--disable-dart-dev',
@@ -143,7 +144,7 @@
       fullArgs.add('--pause-isolates-on-start');
     }
     if (pause_on_exit) {
-      fullArgs.add('--pause-isolates-on-exit');
+      fullArgs.add('--pause-isolates-on-io.exit');
     }
     if (!useAuthToken) {
       fullArgs.add('--disable-service-auth-codes');
@@ -156,7 +157,7 @@
       fullArgs.addAll(extraArgs);
     }
 
-    fullArgs.addAll(Platform.executableArguments);
+    fullArgs.addAll(io.Platform.executableArguments);
     if (!testeeControlsServer) {
       fullArgs.add('--enable-vm-service:0');
     }
@@ -165,7 +166,7 @@
     return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
   }
 
-  Future<Process> _spawnCommon(String executable, List<String> arguments,
+  Future<io.Process> _spawnCommon(String executable, List<String> arguments,
       Map<String, String> dartEnvironment) {
     var environment = _TESTEE_SPAWN_ENV;
     var bashEnvironment = StringBuffer();
@@ -176,7 +177,7 @@
       });
     }
     print('** Launching $bashEnvironment$executable ${arguments.join(' ')}');
-    return Process.start(executable, arguments, environment: environment);
+    return io.Process.start(executable, arguments, environment: environment);
   }
 
   Future<Uri> launch(
@@ -217,17 +218,17 @@
           first = false;
           print('** Signaled to run test queries on $uri');
         }
-        stdout.write('>testee>out> ${line}\n');
+        io.stdout.write('>testee>out> ${line}\n');
       });
       process.stderr
           .transform(utf8.decoder)
           .transform(LineSplitter())
           .listen((line) {
-        stdout.write('>testee>err> ${line}\n');
+        io.stdout.write('>testee>err> ${line}\n');
       });
       process.exitCode.then((exitCode) {
-        if ((exitCode != 0) && !killedByTester) {
-          throw "Testee exited with $exitCode";
+        if ((io.exitCode != 0) && !killedByTester) {
+          throw "Testee io.exited with $exitCode";
         }
         print("** Process exited");
       });
@@ -275,7 +276,7 @@
           var pid = process.process.pid;
           var wait = Duration(seconds: 10);
           print("Testee has pid $pid, waiting $wait before continuing");
-          sleep(wait);
+          io.sleep(wait);
         }
         setupAddresses(serverAddress);
         vm = await vmServiceConnectUri(serviceWebsocketAddress);
diff --git a/pkg/vm_service/test/file_service_test.dart b/pkg/vm_service/test/file_service_test.dart
new file mode 100644
index 0000000..c74fdae
--- /dev/null
+++ b/pkg/vm_service/test/file_service_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+
+import 'package:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+import 'common/test_helper.dart';
+
+Future setupFiles() async {
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
+  var writingFile;
+  var readingFile;
+
+  void closeDown() {
+    if (writingFile != null) {
+      writingFile.closeSync();
+    }
+    if (readingFile != null) {
+      readingFile.closeSync();
+    }
+    dir.deleteSync(recursive: true);
+  }
+
+  Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
+    closeDown();
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+    try {
+      final filePath = dir.path + io.Platform.pathSeparator + "file";
+      final f = io.File(filePath);
+      writingFile = await f.open(mode: io.FileMode.write);
+      await writingFile.writeByte(42);
+      await writingFile.writeByte(42);
+      await writingFile.writeByte(42);
+
+      final file = io.File.fromUri(io.Platform.script);
+      readingFile = await file.open();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+
+      // The utility functions should close the files after them, so we
+      // don't expect the calls below to result in open files.
+      final writeTemp = dir.path + io.Platform.pathSeparator + "other_file";
+      final utilFile = io.File(writeTemp);
+      await utilFile.writeAsString('foobar');
+      final readTemp = io.File(writeTemp);
+      await readTemp.readAsString();
+    } catch (e) {
+      closeDown();
+      rethrow;
+    }
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
+}
+
+var fileTests = <IsolateTest>[
+  (VmService service, IsolateRef isolate) async {
+    await service.callServiceExtension(
+      'ext.dart.io.setup',
+      isolateId: isolate.id,
+    );
+    try {
+      final result = await service.getOpenFiles(isolate.id);
+      expect(result, isA<OpenFileList>());
+      expect(result.files.length, equals(2));
+      final writing = await service.getOpenFileById(
+        isolate.id,
+        result.files[0].id,
+      );
+
+      expect(writing.readBytes, 0);
+      expect(writing.readCount, 0);
+      expect(writing.writeCount, 3);
+      expect(writing.writeBytes, 3);
+      expect(writing.lastWriteTime.millisecondsSinceEpoch, greaterThan(0));
+      expect(writing.lastReadTime.millisecondsSinceEpoch, 0);
+
+      final reading = await service.getOpenFileById(
+        isolate.id,
+        result.files[1].id,
+      );
+      expect(reading.readBytes, 5);
+      expect(reading.readCount, 5);
+      expect(reading.writeCount, 0);
+      expect(reading.writeBytes, 0);
+      expect(reading.lastWriteTime.millisecondsSinceEpoch, 0);
+      expect(reading.lastReadTime.millisecondsSinceEpoch, greaterThan(0));
+    } finally {
+      await service.callServiceExtension(
+        'ext.dart.io.cleanup',
+        isolateId: isolate.id,
+      );
+    }
+  },
+];
+
+main(args) async => runIsolateTests(args, fileTests, testeeBefore: setupFiles);
diff --git a/pkg/vm_service/test/get_isolate_rpc_test.dart b/pkg/vm_service/test/get_isolate_rpc_test.dart
new file mode 100644
index 0000000..ed901a3
--- /dev/null
+++ b/pkg/vm_service/test/get_isolate_rpc_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+var tests = <VMTest>[
+  (VmService service) async {
+    final vm = await service.getVM();
+    final result = await service.getIsolate(vm.isolates.first.id);
+    expect(result.id, startsWith('isolates/'));
+    expect(result.number, isNotNull);
+    expect(result.isolateFlags, isNotNull);
+    expect(result.isolateFlags.length, isPositive);
+    expect(result.isSystemIsolate, isFalse);
+    expect(result.json['_originNumber'], result.number);
+    expect(result.startTime, isPositive);
+    expect(result.livePorts, isPositive);
+    expect(result.pauseOnExit, isFalse);
+    expect(result.pauseEvent.type, 'Event');
+    expect(result.error, isNull);
+    expect(result.json['_numZoneHandles'], isPositive);
+    expect(result.json['_numScopedHandles'], isPositive);
+    expect(result.rootLib, isNotNull);
+    expect(result.libraries.length, isPositive);
+    expect(result.libraries[0], isNotNull);
+    expect(result.breakpoints.length, isZero);
+    expect(result.json['_heaps']['new']['type'], 'HeapSpace');
+    expect(result.json['_heaps']['old']['type'], 'HeapSpace');
+  },
+
+  (VmService service) async {
+    bool caughtException;
+    try {
+      await service.getIsolate('badid');
+      expect(false, isTrue, reason: 'Unreachable');
+    } on RPCError catch (e) {
+      caughtException = true;
+      expect(e.code, equals(RPCError.kInvalidParams));
+      expect(e.details, "getIsolate: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VmService service) async {
+    try {
+      await service.getIsolate('isolates/9999999999');
+      fail('successfully got isolate with bad ID');
+    } on SentinelException catch (e) {
+      expect(e.sentinel.kind, 'Collected');
+      expect(e.sentinel.valueAsString, '<collected>');
+    }
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
index 0b849c6..10157d5 100644
--- a/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
+++ b/pkg/vm_service/test/http_enable_timeline_logging_service_test.dart
@@ -2,9 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:vm_service/vm_service.dart';
-import 'package:vm_service/src/dart_io_extensions.dart';
+import 'dart:async';
+
 import 'package:test/test.dart';
+import 'package:vm_service/src/dart_io_extensions.dart';
+import 'package:vm_service/vm_service.dart';
+
 import 'common/service_test_common.dart';
 import 'common/test_helper.dart';
 
@@ -12,8 +15,36 @@
     'ext.dart.io.setHttpEnableTimelineLogging';
 const String kGetHttpEnableTimelineLogging =
     'ext.dart.io.getHttpEnableTimelineLogging';
+const String kHttpEnableTimelineLogging =
+    'ext.dart.io.httpEnableTimelineLogging';
+
 Future<void> setup() async {}
 
+Future<void> waitForStreamEvent(
+    VmService service, IsolateRef isolateRef, bool state,
+    {bool useSetter = true}) async {
+  final completer = Completer<void>();
+  final isolateId = isolateRef.id;
+  StreamSubscription sub;
+  sub = service.onExtensionEvent.listen((event) {
+    expect(event.extensionKind, 'HttpTimelineLoggingStateChange');
+    expect(event.extensionData.data['isolateId'], isolateRef.id);
+    expect(event.extensionData.data['enabled'], state);
+    sub.cancel();
+    completer.complete();
+  });
+  await service.streamListen(EventStreams.kExtension);
+
+  if (useSetter) {
+    // ignore: deprecated_member_use_from_same_package
+    await service.setHttpEnableTimelineLogging(isolateId, state);
+  } else {
+    await service.httpEnableTimelineLogging(isolateId, state);
+  }
+  await completer.future;
+  await service.streamCancel(EventStreams.kExtension);
+}
+
 var tests = <IsolateTest>[
   (VmService service, IsolateRef isolateRef) async {
     final isolate = await service.getIsolate(isolateRef.id);
@@ -23,22 +54,37 @@
         isolate.extensionRPCs.contains(kGetHttpEnableTimelineLogging), isTrue);
     expect(
         isolate.extensionRPCs.contains(kSetHttpEnableTimelineLogging), isTrue);
+    expect(isolate.extensionRPCs.contains(kHttpEnableTimelineLogging), isTrue);
   },
   (VmService service, IsolateRef isolateRef) async {
     final isolateId = isolateRef.id;
+    // ignore: deprecated_member_use_from_same_package
     dynamic response = await service.getHttpEnableTimelineLogging(isolateId);
     expect(response.enabled, false);
 
-    await service.setHttpEnableTimelineLogging(isolateId, true);
-
+    await waitForStreamEvent(service, isolateRef, true);
+    // ignore: deprecated_member_use_from_same_package
     response = await service.getHttpEnableTimelineLogging(isolateId);
     expect(response.enabled, true);
 
-    await service.setHttpEnableTimelineLogging(isolateId, false);
-
+    await waitForStreamEvent(service, isolateRef, false);
+    // ignore: deprecated_member_use_from_same_package
     response = await service.getHttpEnableTimelineLogging(isolateId);
     expect(response.enabled, false);
   },
+  (VmService service, IsolateRef isolateRef) async {
+    final isolateId = isolateRef.id;
+    dynamic response = await service.httpEnableTimelineLogging(isolateId, null);
+    expect(response.enabled, false);
+
+    await waitForStreamEvent(service, isolateRef, true, useSetter: false);
+    response = await service.httpEnableTimelineLogging(isolateId, null);
+    expect(response.enabled, true);
+
+    await waitForStreamEvent(service, isolateRef, false, useSetter: false);
+    response = await service.httpEnableTimelineLogging(isolateId);
+    expect(response.enabled, false);
+  },
 ];
 
 main([args = const <String>[]]) async =>
diff --git a/pkg/vm_service/test/process_service_test.dart b/pkg/vm_service/test/process_service_test.dart
new file mode 100644
index 0000000..a47359a
--- /dev/null
+++ b/pkg/vm_service/test/process_service_test.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+import 'package:vm_service/vm_service.dart';
+
+import 'common/test_helper.dart';
+
+final dartJITBinary = path.join(path.dirname(io.Platform.resolvedExecutable),
+    'dart' + path.extension(io.Platform.resolvedExecutable));
+
+Future setupProcesses() async {
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
+
+  final args = [
+    ...io.Platform.executableArguments,
+    '--pause_isolates_on_start',
+    io.Platform.script.toFilePath(),
+  ];
+  io.Process process1;
+  io.Process process2;
+  io.Process process3;
+
+  void closeDown() {
+    if (process1 != null) {
+      process1.kill();
+    }
+    if (process2 != null) {
+      process2.kill();
+    }
+    if (process3 != null) {
+      process3.kill();
+    }
+    dir.deleteSync(recursive: true);
+  }
+
+  Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
+    closeDown();
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+    try {
+      process1 = await io.Process.start(io.Platform.executable, args);
+      process2 =
+          await io.Process.start(io.Platform.executable, args..add('foobar'));
+      final codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
+      final codeFile = io.File(codeFilePath);
+      await codeFile.writeAsString('''
+          import "dart:io";
+
+          void main() async {
+            await stdin.drain();
+          }
+          ''');
+      process3 = await io.Process.start(
+          dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
+    } catch (_) {
+      closeDown();
+      rethrow;
+    }
+
+    final result = jsonEncode({
+      'type': 'foobar',
+      'pids': [process1.pid, process2.pid, process3.pid]
+    });
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) {
+    process3.stdin.close();
+    return process3.exitCode.then<ServiceExtensionResponse>((int exit) {
+      final result = jsonEncode({'type': 'foobar'});
+      return ServiceExtensionResponse.result(result);
+    });
+  }
+
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
+  registerExtension('ext.dart.io.closeStdin', closeStdin);
+}
+
+final processTests = <IsolateTest>[
+  // Initial.
+  (VmService service, IsolateRef isolate) async {
+    final setup = await service.callServiceExtension(
+      'ext.dart.io.setup',
+      isolateId: isolate.id,
+    );
+    try {
+      SpawnedProcessList all = await service.getSpawnedProcesses(isolate.id);
+      expect(all.processes.length, equals(3));
+
+      final first = await service.getSpawnedProcessById(
+        isolate.id,
+        all.processes[0].id,
+      );
+
+      expect(first.name, io.Platform.executable);
+      expect(first.pid, equals(setup.json['pids'][0]));
+      expect(first.arguments.contains('foobar'), isFalse);
+      expect(first.startedAt, greaterThan(0));
+
+      final second = await service.getSpawnedProcessById(
+        isolate.id,
+        all.processes[1].id,
+      );
+
+      expect(second.name, io.Platform.executable);
+      expect(second.pid, equals(setup.json['pids'][1]));
+      expect(second.arguments.contains('foobar'), isTrue);
+      expect(second.pid != first.pid, isTrue);
+      expect(second.startedAt, greaterThan(0));
+      expect(second.startedAt, greaterThanOrEqualTo(first.startedAt));
+
+      final third = await service.getSpawnedProcessById(
+        isolate.id,
+        all.processes[2].id,
+      );
+
+      expect(third.name, dartJITBinary);
+      expect(third.pid, equals(setup.json['pids'][2]));
+      expect(third.pid != first.pid, isTrue);
+      expect(third.pid != second.pid, isTrue);
+      expect(third.startedAt, greaterThanOrEqualTo(second.startedAt));
+
+      await service.callServiceExtension(
+        'ext.dart.io.closeStdin',
+        isolateId: isolate.id,
+      );
+      all = await service.getSpawnedProcesses(isolate.id);
+      expect(all.processes.length, equals(2));
+    } finally {
+      await service.callServiceExtension(
+        'ext.dart.io.cleanup',
+        isolateId: isolate.id,
+      );
+    }
+  },
+];
+
+main(args) async =>
+    runIsolateTests(args, processTests, testeeBefore: setupProcesses);
diff --git a/pkg/vm_service/test/server_test.dart b/pkg/vm_service/test/server_test.dart
index ab0347c..739af84 100644
--- a/pkg/vm_service/test/server_test.dart
+++ b/pkg/vm_service/test/server_test.dart
@@ -50,6 +50,7 @@
         startTime: 1,
         runnable: true,
         livePorts: 2,
+        isolateFlags: [],
         pauseOnExit: false,
         pauseEvent: Event(
           kind: EventKind.kResume,
@@ -57,6 +58,7 @@
         ),
         libraries: [],
         breakpoints: [],
+        isSystemIsolate: false,
       );
       var request = rpcRequest("getIsolate", params: {'isolateId': isolate.id});
       when(serviceMock.getIsolate(isolate.id))
@@ -77,6 +79,7 @@
         startTime: 1,
         runnable: true,
         livePorts: 2,
+        isolateFlags: [],
         pauseOnExit: false,
         pauseEvent: Event(
           kind: EventKind.kResume,
@@ -84,6 +87,7 @@
         ),
         libraries: [],
         breakpoints: [],
+        isSystemIsolate: false,
       );
       var request = rpcRequest("setVMTimelineFlags", params: {
         'isolateId': isolate.id,
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 1fbe545..49fb41a 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -936,6 +936,13 @@
   return list;
 }
 
+List<vms.IsolateFlag> assertListOfIsolateFlag(List<vms.IsolateFlag> list) {
+  for (vms.IsolateFlag elem in list) {
+    assertIsolateFlag(elem);
+  }
+  return list;
+}
+
 String assertString(String obj) {
   assertNotNull(obj);
   if (obj.isEmpty) throw 'expected non-zero length string';
diff --git a/pkg/wasm/lib/src/function.dart b/pkg/wasm/lib/src/function.dart
index c5840bf..4ac694e 100644
--- a/pkg/wasm/lib/src/function.dart
+++ b/pkg/wasm/lib/src/function.dart
@@ -9,15 +9,16 @@
 
 /// WasmFunction is a callable function from a WasmInstance.
 class WasmFunction {
+  String _name;
   Pointer<WasmerExportFunc> _func;
   List<int> _argTypes;
   int _returnType;
   Pointer<WasmerValue> _args;
   Pointer<WasmerValue> _result;
 
-  WasmFunction(this._func, this._argTypes, this._returnType) {
-    _args = allocate<WasmerValue>(count: _argTypes.length);
-    _result = allocate<WasmerValue>();
+  WasmFunction(this._name, this._func, this._argTypes, this._returnType)
+      : _args = allocate<WasmerValue>(count: _argTypes.length),
+        _result = allocate<WasmerValue>() {
     for (var i = 0; i < _argTypes.length; ++i) {
       _args[i].tag = _argTypes[i];
     }
@@ -42,15 +43,16 @@
         _args[i].f64 = arg;
         return true;
     }
+    return false;
   }
 
   dynamic apply(List<dynamic> args) {
     if (args.length != _argTypes.length) {
-      throw Exception("Wrong number arguments for WASM function");
+      throw ArgumentError("Wrong number arguments for WASM function: $_name");
     }
     for (var i = 0; i < args.length; ++i) {
       if (!_fillArg(args[i], i)) {
-        throw Exception("Bad argument type for WASM function");
+        throw ArgumentError("Bad argument type for WASM function: $_name");
       }
     }
     WasmRuntime().call(_func, _args, _argTypes.length, _result,
diff --git a/pkg/wasm/lib/src/module.dart b/pkg/wasm/lib/src/module.dart
index 1034a9e..4013966 100644
--- a/pkg/wasm/lib/src/module.dart
+++ b/pkg/wasm/lib/src/module.dart
@@ -14,14 +14,30 @@
   Pointer<WasmerModule> _module;
 
   /// Compile a module.
-  WasmModule(Uint8List data) {
-    _module = WasmRuntime().compile(data);
-  }
+  WasmModule(Uint8List data) : _module = WasmRuntime().compile(data) {}
 
   /// Instantiate the module with the given imports.
   WasmInstance instantiate(WasmImports imports) {
     return WasmInstance(_module, imports);
   }
+
+  /// Returns a description of all of the module's imports and exports, for
+  /// debugging.
+  String describe() {
+    var description = StringBuffer();
+    var runtime = WasmRuntime();
+    var imports = runtime.importDescriptors(_module);
+    for (var imp in imports) {
+      var kind = wasmerImpExpKindName(imp.kind);
+      description.write('import $kind: ${imp.moduleName}::${imp.name}\n');
+    }
+    var exports = runtime.exportDescriptors(_module);
+    for (var exp in exports) {
+      var kind = wasmerImpExpKindName(exp.kind);
+      description.write('export $kind: ${exp.name}\n');
+    }
+    return description.toString();
+  }
 }
 
 /// WasmImports holds all the imports for a WasmInstance.
@@ -31,9 +47,9 @@
   int _length;
 
   /// Create an imports object.
-  WasmImports([this._capacity = 4]) : _length = 0 {
-    _imports = allocate<WasmerImport>(count: this._capacity);
-  }
+  WasmImports([this._capacity = 4])
+      : _imports = allocate<WasmerImport>(count: _capacity),
+        _length = 0 {}
 
   /// Returns the number of imports.
   int get length => _length;
@@ -43,22 +59,82 @@
 class WasmInstance {
   Pointer<WasmerModule> _module;
   Pointer<WasmerInstance> _instance;
-  List<WasmFunction> _functions;
+  Pointer<WasmerMemory>? _exportedMemory;
+  Map<String, WasmFunction> _functions = {};
 
-  WasmInstance(this._module, WasmImports imports) {
+  WasmInstance(this._module, WasmImports imports)
+      : _instance = WasmRuntime()
+            .instantiate(_module, imports._imports, imports.length) {
     var runtime = WasmRuntime();
-    _instance = runtime.instantiate(_module, imports._imports, imports.length);
-    _functions = [];
     var exps = runtime.exports(_instance);
     for (var e in exps) {
       var kind = runtime.exportKind(e);
+      String name = runtime.exportName(e);
       if (kind == WasmerImpExpKindFunction) {
         var f = runtime.exportToFunction(e);
-        _functions.add(
-            WasmFunction(f, runtime.getArgTypes(f), runtime.getReturnType(f)));
+        _functions[name] = WasmFunction(
+            name, f, runtime.getArgTypes(f), runtime.getReturnType(f));
+      } else if (kind == WasmerImpExpKindMemory) {
+        // WASM currently allows only one memory per module.
+        _exportedMemory = runtime.exportToMemory(e);
       }
     }
   }
 
-  List<dynamic> get functions => _functions;
+  /// Searches the instantiated module for the given function. Returns null if
+  /// it is not found.
+  dynamic lookupFunction(String name) {
+    return _functions[name];
+  }
+
+  /// Returns the memory exported from this instance.
+  WasmMemory get memory {
+    if (_exportedMemory == null) {
+      throw Exception("Wasm module did not export its memory.");
+    }
+    return WasmMemory._fromExport(_exportedMemory as Pointer<WasmerMemory>);
+  }
+}
+
+/// WasmMemory contains the memory of a WasmInstance.
+class WasmMemory {
+  Pointer<WasmerMemory> _mem;
+  late Uint8List _view;
+
+  WasmMemory._fromExport(this._mem) {
+    _view = WasmRuntime().memoryView(_mem);
+  }
+
+  /// Create a new memory with the given number of initial pages, and optional
+  /// maximum number of pages.
+  WasmMemory(int pages, [int? maxPages])
+      : _mem = WasmRuntime().newMemory(pages, maxPages) {
+    _view = WasmRuntime().memoryView(_mem);
+  }
+
+  /// The WASM spec defines the page size as 64KiB.
+  static const int kPageSizeInBytes = 64 * 1024;
+
+  /// Returns the length of the memory in pages.
+  int get lengthInPages {
+    return WasmRuntime().memoryLength(_mem);
+  }
+
+  /// Returns the length of the memory in bytes.
+  int get lengthInBytes => _view.lengthInBytes;
+
+  /// Returns the byte at the given index.
+  int operator [](int index) => _view[index];
+
+  /// Sets the byte at the given index to value.
+  void operator []=(int index, int value) {
+    _view[index] = value;
+  }
+
+  /// Grow the memory by deltaPages.
+  void grow(int deltaPages) {
+    var runtime = WasmRuntime();
+    runtime.growMemory(_mem, deltaPages);
+    _view = runtime.memoryView(_mem);
+  }
 }
diff --git a/pkg/wasm/lib/src/runtime.dart b/pkg/wasm/lib/src/runtime.dart
index b8d3686..4ddec1d 100644
--- a/pkg/wasm/lib/src/runtime.dart
+++ b/pkg/wasm/lib/src/runtime.dart
@@ -10,33 +10,66 @@
 import 'package:path/path.dart' as path;
 import 'wasmer_api.dart';
 
+class WasmImportDescriptor {
+  int kind;
+  String moduleName;
+  String name;
+  WasmImportDescriptor(this.kind, this.moduleName, this.name);
+}
+
+class WasmExportDescriptor {
+  int kind;
+  String name;
+  WasmExportDescriptor(this.kind, this.name);
+}
+
 class WasmRuntime {
-  static WasmRuntime _inst;
+  static WasmRuntime? _inst;
 
   DynamicLibrary _lib;
-  WasmerCompileFn _compile;
-  WasmerInstantiateFn _instantiate;
-  WasmerInstanceExportsFn _instance_exports;
-  WasmerExportsLenFn _exports_len;
-  WasmerExportsGetFn _exports_get;
-  WasmerExportKindFn _export_kind;
-  WasmerExportToFuncFn _export_to_func;
-  WasmerExportFuncReturnsArityFn _export_func_returns_arity;
-  WasmerExportFuncReturnsFn _export_func_returns;
-  WasmerExportFuncParamsArityFn _export_func_params_arity;
-  WasmerExportFuncParamsFn _export_func_params;
-  WasmerExportFuncCallFn _export_func_call;
+  late WasmerCompileFn _compile;
+  late WasmerInstantiateFn _instantiate;
+  late WasmerInstanceExportsFn _instance_exports;
+  late WasmerExportsLenFn _exports_len;
+  late WasmerExportsGetFn _exports_get;
+  late WasmerExportKindFn _export_kind;
+  late WasmerExportToFuncFn _export_to_func;
+  late WasmerExportFuncReturnsArityFn _export_func_returns_arity;
+  late WasmerExportFuncReturnsFn _export_func_returns;
+  late WasmerExportFuncParamsArityFn _export_func_params_arity;
+  late WasmerExportFuncParamsFn _export_func_params;
+  late WasmerExportFuncCallFn _export_func_call;
+  late WasmerExportNamePtrFn _export_name_ptr;
+  late WasmerExportDescriptorsFn _export_descriptors;
+  late WasmerExportDescriptorsDestroyFn _export_descriptors_destroy;
+  late WasmerExportDescriptorsLenFn _export_descriptors_len;
+  late WasmerExportDescriptorsGetFn _export_descriptors_get;
+  late WasmerExportDescriptorKindFn _export_descriptor_kind;
+  late WasmerExportDescriptorNamePtrFn _export_descriptor_name_ptr;
+  late WasmerImportDescriptorModuleNamePtrFn _import_descriptor_module_name_ptr;
+  late WasmerImportDescriptorNamePtrFn _import_descriptor_name_ptr;
+  late WasmerImportDescriptorsFn _import_descriptors;
+  late WasmerImportDescriptorsDestroyFn _import_descriptors_destroy;
+  late WasmerImportDescriptorsLenFn _import_descriptors_len;
+  late WasmerImportDescriptorsGetFn _import_descriptors_get;
+  late WasmerImportDescriptorKindFn _import_descriptor_kind;
+  late WasmerExportToMemoryFn _export_to_memory;
+  late WasmerMemoryNewPtrFn _memory_new_ptr;
+  late WasmerMemoryGrowFn _memory_grow;
+  late WasmerMemoryLengthFn _memory_length;
+  late WasmerMemoryDataFn _memory_data;
+  late WasmerMemoryDataLengthFn _memory_data_length;
 
   factory WasmRuntime() {
     if (_inst == null) {
       _inst = WasmRuntime._init();
     }
-    return _inst;
+    return _inst as WasmRuntime;
   }
 
   static String _getLibName() {
-    if (Platform.isMacOS) return "libwasmer.dylib";
-    if (Platform.isLinux) return "libwasmer.so";
+    if (Platform.isMacOS) return "libwasmer_wrapper.dylib";
+    if (Platform.isLinux) return "libwasmer_wrapper.so";
     throw Exception("Wasm not currently supported on this platform");
   }
 
@@ -69,9 +102,8 @@
     return commonLibDir;
   }
 
-  WasmRuntime._init() {
-    var libPath = path.join(_getLibDir(), _getLibName());
-    _lib = DynamicLibrary.open(libPath);
+  WasmRuntime._init()
+      : _lib = DynamicLibrary.open(path.join(_getLibDir(), _getLibName())) {
     _compile = _lib.lookupFunction<NativeWasmerCompileFn, WasmerCompileFn>(
         'wasmer_compile');
     _instantiate =
@@ -103,6 +135,63 @@
         WasmerExportFuncParamsFn>('wasmer_export_func_params');
     _export_func_call = _lib.lookupFunction<NativeWasmerExportFuncCallFn,
         WasmerExportFuncCallFn>('wasmer_export_func_call');
+    _export_descriptors = _lib.lookupFunction<NativeWasmerExportDescriptorsFn,
+        WasmerExportDescriptorsFn>('wasmer_export_descriptors');
+    _export_descriptors_destroy = _lib.lookupFunction<
+        NativeWasmerExportDescriptorsDestroyFn,
+        WasmerExportDescriptorsDestroyFn>('wasmer_export_descriptors_destroy');
+    _export_descriptors_len = _lib.lookupFunction<
+        NativeWasmerExportDescriptorsLenFn,
+        WasmerExportDescriptorsLenFn>('wasmer_export_descriptors_len');
+    _export_descriptors_get = _lib.lookupFunction<
+        NativeWasmerExportDescriptorsGetFn,
+        WasmerExportDescriptorsGetFn>('wasmer_export_descriptors_get');
+    _export_descriptor_kind = _lib.lookupFunction<
+        NativeWasmerExportDescriptorKindFn,
+        WasmerExportDescriptorKindFn>('wasmer_export_descriptor_kind');
+    _export_name_ptr =
+        _lib.lookupFunction<NativeWasmerExportNamePtrFn, WasmerExportNamePtrFn>(
+            'wasmer_export_name_ptr');
+    _export_descriptor_name_ptr = _lib.lookupFunction<
+        NativeWasmerExportDescriptorNamePtrFn,
+        WasmerExportDescriptorNamePtrFn>('wasmer_export_descriptor_name_ptr');
+    _import_descriptors = _lib.lookupFunction<NativeWasmerImportDescriptorsFn,
+        WasmerImportDescriptorsFn>('wasmer_import_descriptors');
+    _import_descriptors_destroy = _lib.lookupFunction<
+        NativeWasmerImportDescriptorsDestroyFn,
+        WasmerImportDescriptorsDestroyFn>('wasmer_import_descriptors_destroy');
+    _import_descriptors_len = _lib.lookupFunction<
+        NativeWasmerImportDescriptorsLenFn,
+        WasmerImportDescriptorsLenFn>('wasmer_import_descriptors_len');
+    _import_descriptors_get = _lib.lookupFunction<
+        NativeWasmerImportDescriptorsGetFn,
+        WasmerImportDescriptorsGetFn>('wasmer_import_descriptors_get');
+    _import_descriptor_kind = _lib.lookupFunction<
+        NativeWasmerImportDescriptorKindFn,
+        WasmerImportDescriptorKindFn>('wasmer_import_descriptor_kind');
+    _import_descriptor_module_name_ptr = _lib.lookupFunction<
+            NativeWasmerImportDescriptorModuleNamePtrFn,
+            WasmerImportDescriptorModuleNamePtrFn>(
+        'wasmer_import_descriptor_module_name_ptr');
+    _import_descriptor_name_ptr = _lib.lookupFunction<
+        NativeWasmerImportDescriptorNamePtrFn,
+        WasmerImportDescriptorNamePtrFn>('wasmer_import_descriptor_name_ptr');
+    _export_to_memory = _lib.lookupFunction<NativeWasmerExportToMemoryFn,
+        WasmerExportToMemoryFn>('wasmer_export_to_memory');
+    _memory_new_ptr =
+        _lib.lookupFunction<NativeWasmerMemoryNewPtrFn, WasmerMemoryNewPtrFn>(
+            'wasmer_memory_new_ptr');
+    _memory_grow =
+        _lib.lookupFunction<NativeWasmerMemoryGrowFn, WasmerMemoryGrowFn>(
+            'wasmer_memory_grow');
+    _memory_length =
+        _lib.lookupFunction<NativeWasmerMemoryLengthFn, WasmerMemoryLengthFn>(
+            'wasmer_memory_length');
+    _memory_data =
+        _lib.lookupFunction<NativeWasmerMemoryDataFn, WasmerMemoryDataFn>(
+            'wasmer_memory_data');
+    _memory_data_length = _lib.lookupFunction<NativeWasmerMemoryDataLengthFn,
+        WasmerMemoryDataLengthFn>('wasmer_memory_data_length');
   }
 
   Pointer<WasmerModule> compile(Uint8List data) {
@@ -125,6 +214,49 @@
     return modulePtr;
   }
 
+  String _callStringWrapperFunction(Function fn, dynamic arg) {
+    var strPtr = allocate<WasmerByteArray>();
+    fn(arg, strPtr);
+    var str = strPtr.ref.string;
+    free(strPtr);
+    return str;
+  }
+
+  List<WasmExportDescriptor> exportDescriptors(Pointer<WasmerModule> module) {
+    var exportsPtrPtr = allocate<Pointer<WasmerExportDescriptors>>();
+    _export_descriptors(module, exportsPtrPtr);
+    Pointer<WasmerExportDescriptors> exportsPtr = exportsPtrPtr.value;
+    free(exportsPtrPtr);
+    var n = _export_descriptors_len(exportsPtr);
+    var exps = <WasmExportDescriptor>[];
+    for (var i = 0; i < n; ++i) {
+      var exp = _export_descriptors_get(exportsPtr, i);
+      exps.add(WasmExportDescriptor(_export_descriptor_kind(exp),
+          _callStringWrapperFunction(_export_descriptor_name_ptr, exp)));
+    }
+    _export_descriptors_destroy(exportsPtr);
+    return exps;
+  }
+
+  List<WasmImportDescriptor> importDescriptors(Pointer<WasmerModule> module) {
+    var importsPtrPtr = allocate<Pointer<WasmerImportDescriptors>>();
+    _import_descriptors(module, importsPtrPtr);
+    Pointer<WasmerImportDescriptors> importsPtr = importsPtrPtr.value;
+    free(importsPtrPtr);
+
+    var n = _import_descriptors_len(importsPtr);
+    var imps = <WasmImportDescriptor>[];
+    for (var i = 0; i < n; ++i) {
+      var imp = _import_descriptors_get(importsPtr, i);
+      imps.add(WasmImportDescriptor(
+          _import_descriptor_kind(imp),
+          _callStringWrapperFunction(_import_descriptor_module_name_ptr, imp),
+          _callStringWrapperFunction(_import_descriptor_name_ptr, imp)));
+    }
+    _import_descriptors_destroy(importsPtr);
+    return imps;
+  }
+
   Pointer<WasmerInstance> instantiate(Pointer<WasmerModule> module,
       Pointer<WasmerImport> imports, int numImports) {
     var instancePtrPtr = allocate<Pointer<WasmerInstance>>();
@@ -157,6 +289,10 @@
     return _export_kind(export);
   }
 
+  String exportName(Pointer<WasmerExport> export) {
+    return _callStringWrapperFunction(_export_name_ptr, export);
+  }
+
   Pointer<WasmerExportFunc> exportToFunction(Pointer<WasmerExport> export) {
     return _export_to_func(export);
   }
@@ -199,7 +335,7 @@
       throw Exception("Multiple return values are not supported");
     }
     var returnsPtr = allocate<Uint32>();
-    result = _export_func_params(func, returnsPtr, 1);
+    result = _export_func_returns(func, returnsPtr, 1);
     if (result != WasmerResultOk) {
       free(returnsPtr);
       throw Exception("Failed to get WASM function args");
@@ -216,4 +352,48 @@
       throw Exception("Failed to call WASM function");
     }
   }
+
+  Pointer<WasmerMemory> exportToMemory(Pointer<WasmerExport> export) {
+    var memPtrPtr = allocate<Pointer<WasmerMemory>>();
+    var result = _export_to_memory(export, memPtrPtr);
+    if (result != WasmerResultOk) {
+      free(memPtrPtr);
+      throw Exception("Failed to get exported memory");
+    }
+    Pointer<WasmerMemory> memPtr = memPtrPtr.value;
+    free(memPtrPtr);
+    return memPtr;
+  }
+
+  Pointer<WasmerMemory> newMemory(int pages, int? maxPages) {
+    var memPtrPtr = allocate<Pointer<WasmerMemory>>();
+    var limPtr = allocate<WasmerLimits>();
+    limPtr.ref.min = pages;
+    limPtr.ref.has_max = maxPages != null ? 1 : 0;
+    limPtr.ref.max = maxPages ?? 0;
+    var result = _memory_new_ptr(memPtrPtr, limPtr);
+    free(limPtr);
+    if (result != WasmerResultOk) {
+      free(memPtrPtr);
+      throw Exception("Failed to create memory");
+    }
+    Pointer<WasmerMemory> memPtr = memPtrPtr.value;
+    free(memPtrPtr);
+    return memPtr;
+  }
+
+  void growMemory(Pointer<WasmerMemory> memory, int deltaPages) {
+    var result = _memory_grow(memory, deltaPages);
+    if (result != WasmerResultOk) {
+      throw Exception("Failed to grow memory");
+    }
+  }
+
+  int memoryLength(Pointer<WasmerMemory> memory) {
+    return _memory_length(memory);
+  }
+
+  Uint8List memoryView(Pointer<WasmerMemory> memory) {
+    return _memory_data(memory).asTypedList(_memory_data_length(memory));
+  }
 }
diff --git a/pkg/wasm/lib/src/wasmer_api.dart b/pkg/wasm/lib/src/wasmer_api.dart
index dc5df74..94dd651 100644
--- a/pkg/wasm/lib/src/wasmer_api.dart
+++ b/pkg/wasm/lib/src/wasmer_api.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:convert';
 import 'dart:ffi';
 import 'dart:typed_data';
 
@@ -24,6 +25,21 @@
 const int WasmerImpExpKindMemory = 2;
 const int WasmerImpExpKindTable = 3;
 
+String wasmerImpExpKindName(int kind) {
+  switch (kind) {
+    case WasmerImpExpKindFunction:
+      return "function";
+    case WasmerImpExpKindGlobal:
+      return "global";
+    case WasmerImpExpKindMemory:
+      return "memory";
+    case WasmerImpExpKindTable:
+      return "table";
+    default:
+      return "unknown";
+  }
+}
+
 // wasmer_module_t
 class WasmerModule extends Struct {}
 
@@ -36,52 +52,68 @@
 // wasmer_export_t
 class WasmerExport extends Struct {}
 
+// wasmer_export_descriptors_t
+class WasmerExportDescriptors extends Struct {}
+
+// wasmer_export_descriptor_t
+class WasmerExportDescriptor extends Struct {}
+
 // wasmer_export_func_t
 class WasmerExportFunc extends Struct {}
 
+// wasmer_import_descriptors_t
+class WasmerImportDescriptors extends Struct {}
+
+// wasmer_import_descriptor_t
+class WasmerImportDescriptor extends Struct {}
+
+// wasmer_memory_t
+class WasmerMemory extends Struct {}
+
 // wasmer_import_t
 class WasmerImport extends Struct {
-  Pointer<Uint8> module_name;
+  external Pointer<Uint8> module_name;
 
   @Uint32()
-  int module_name_length;
+  external int module_name_length;
 
-  Pointer<Uint8> import_name;
+  external Pointer<Uint8> import_name;
 
   @Uint32()
-  int import_name_length;
+  external int import_name_length;
 
   // wasmer_import_export_kind
   @Uint32()
-  int tag;
+  external int tag;
 
   // wasmer_import_export_value, which is a union of wasmer_import_func_t*,
   // wasmer_table_t*, wasmer_memory_t*, and wasmer_global_t*. The tag determines
   // which type it is.
-  Pointer<Void> value;
+  external Pointer<Void> value;
 }
 
 // wasmer_byte_array
 class WasmerByteArray extends Struct {
-  Pointer<Uint8> bytes;
+  external Pointer<Uint8> bytes;
 
   @Uint32()
-  int length;
+  external int length;
 
   Uint8List get list => bytes.asTypedList(length);
+  String get string => utf8.decode(list);
 }
 
 // wasmer_value_t
 class WasmerValue extends Struct {
   // wasmer_value_tag
   @Uint32()
-  int tag;
+  external int tag;
 
   // wasmer_value, which is a union of int32_t, int64_t, float, and double. The
   // tag determines which type it is. It's declared as an int64_t because that's
   // large enough to hold all the types. We use ByteData to get the other types.
   @Int64()
-  int value;
+  external int value;
 
   int get _off32 => Endian.host == Endian.little ? 0 : 4;
   int get i64 => value;
@@ -93,8 +125,10 @@
   set i64(int val) => value = val;
   set _val(ByteData bytes) => value = bytes.getInt64(0, Endian.host);
   set i32(int val) => _val = ByteData(8)..setInt32(_off32, val, Endian.host);
-  set f32(num val) => _val = ByteData(8)..setFloat32(_off32, val, Endian.host);
-  set f64(num val) => _val = ByteData(8)..setFloat64(0, val, Endian.host);
+  set f32(num val) =>
+      _val = ByteData(8)..setFloat32(_off32, val as double, Endian.host);
+  set f64(num val) =>
+      _val = ByteData(8)..setFloat64(0, val as double, Endian.host);
 
   bool get isI32 => tag == WasmerValueTagI32;
   bool get isI64 => tag == WasmerValueTagI64;
@@ -102,6 +136,19 @@
   bool get isF64 => tag == WasmerValueTagF64;
 }
 
+// wasmer_limits_t
+class WasmerLimits extends Struct {
+  @Uint32()
+  external int min;
+
+  // bool
+  @Uint8()
+  external int has_max;
+
+  @Uint32()
+  external int max;
+}
+
 // wasmer_compile
 typedef NativeWasmerCompileFn = Uint32 Function(
     Pointer<Pointer<WasmerModule>>, Pointer<Uint8>, Uint32);
@@ -130,10 +177,89 @@
 typedef WasmerExportsGetFn = Pointer<WasmerExport> Function(
     Pointer<WasmerExports>, int);
 
-// wasmer_export_name
-typedef NativeWasmerExportNameFn = WasmerByteArray Function(
-    Pointer<WasmerExport>);
-typedef WasmerExportNameFn = WasmerByteArray Function(Pointer<WasmerExport>);
+// wasmer_export_descriptors
+typedef NativeWasmerExportDescriptorsFn = Void Function(
+    Pointer<WasmerModule>, Pointer<Pointer<WasmerExportDescriptors>>);
+typedef WasmerExportDescriptorsFn = void Function(
+    Pointer<WasmerModule>, Pointer<Pointer<WasmerExportDescriptors>>);
+
+// wasmer_export_descriptors_destroy
+typedef NativeWasmerExportDescriptorsDestroyFn = Void Function(
+    Pointer<WasmerExportDescriptors>);
+typedef WasmerExportDescriptorsDestroyFn = void Function(
+    Pointer<WasmerExportDescriptors>);
+
+// wasmer_export_descriptors_len
+typedef NativeWasmerExportDescriptorsLenFn = Int32 Function(
+    Pointer<WasmerExportDescriptors>);
+typedef WasmerExportDescriptorsLenFn = int Function(
+    Pointer<WasmerExportDescriptors>);
+
+// wasmer_export_descriptors_get
+typedef NativeWasmerExportDescriptorsGetFn = Pointer<WasmerExportDescriptor>
+    Function(Pointer<WasmerExportDescriptors>, Int32);
+typedef WasmerExportDescriptorsGetFn = Pointer<WasmerExportDescriptor> Function(
+    Pointer<WasmerExportDescriptors>, int);
+
+// wasmer_export_descriptor_kind
+typedef NativeWasmerExportDescriptorKindFn = Uint32 Function(
+    Pointer<WasmerExportDescriptor>);
+typedef WasmerExportDescriptorKindFn = int Function(
+    Pointer<WasmerExportDescriptor>);
+
+// wasmer_export_descriptor_name_ptr
+typedef NativeWasmerExportDescriptorNamePtrFn = Void Function(
+    Pointer<WasmerExportDescriptor>, Pointer<WasmerByteArray>);
+typedef WasmerExportDescriptorNamePtrFn = void Function(
+    Pointer<WasmerExportDescriptor>, Pointer<WasmerByteArray>);
+
+// wasmer_import_descriptors
+typedef NativeWasmerImportDescriptorsFn = Void Function(
+    Pointer<WasmerModule>, Pointer<Pointer<WasmerImportDescriptors>>);
+typedef WasmerImportDescriptorsFn = void Function(
+    Pointer<WasmerModule>, Pointer<Pointer<WasmerImportDescriptors>>);
+
+// wasmer_import_descriptors_destroy
+typedef NativeWasmerImportDescriptorsDestroyFn = Void Function(
+    Pointer<WasmerImportDescriptors>);
+typedef WasmerImportDescriptorsDestroyFn = void Function(
+    Pointer<WasmerImportDescriptors>);
+
+// wasmer_import_descriptors_len
+typedef NativeWasmerImportDescriptorsLenFn = Int32 Function(
+    Pointer<WasmerImportDescriptors>);
+typedef WasmerImportDescriptorsLenFn = int Function(
+    Pointer<WasmerImportDescriptors>);
+
+// wasmer_import_descriptors_get
+typedef NativeWasmerImportDescriptorsGetFn = Pointer<WasmerImportDescriptor>
+    Function(Pointer<WasmerImportDescriptors>, Int32);
+typedef WasmerImportDescriptorsGetFn = Pointer<WasmerImportDescriptor> Function(
+    Pointer<WasmerImportDescriptors>, int);
+
+// wasmer_import_descriptor_kind
+typedef NativeWasmerImportDescriptorKindFn = Uint32 Function(
+    Pointer<WasmerImportDescriptor>);
+typedef WasmerImportDescriptorKindFn = int Function(
+    Pointer<WasmerImportDescriptor>);
+
+// wasmer_import_descriptor_module_name_ptr
+typedef NativeWasmerImportDescriptorModuleNamePtrFn = Void Function(
+    Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
+typedef WasmerImportDescriptorModuleNamePtrFn = void Function(
+    Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
+
+// wasmer_import_descriptor_name_ptr
+typedef NativeWasmerImportDescriptorNamePtrFn = Void Function(
+    Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
+typedef WasmerImportDescriptorNamePtrFn = void Function(
+    Pointer<WasmerImportDescriptor>, Pointer<WasmerByteArray>);
+
+// wasmer_export_name_ptr
+typedef NativeWasmerExportNamePtrFn = Void Function(
+    Pointer<WasmerExport>, Pointer<WasmerByteArray>);
+typedef WasmerExportNamePtrFn = void Function(
+    Pointer<WasmerExport>, Pointer<WasmerByteArray>);
 
 // wasmer_export_kind
 typedef NativeWasmerExportKindFn = Uint32 Function(Pointer<WasmerExport>);
@@ -178,3 +304,33 @@
     Uint32);
 typedef WasmerExportFuncCallFn = int Function(Pointer<WasmerExportFunc>,
     Pointer<WasmerValue>, int, Pointer<WasmerValue>, int);
+
+// wasmer_export_to_memory
+typedef NativeWasmerExportToMemoryFn = Uint32 Function(
+    Pointer<WasmerExport>, Pointer<Pointer<WasmerMemory>>);
+typedef WasmerExportToMemoryFn = int Function(
+    Pointer<WasmerExport>, Pointer<Pointer<WasmerMemory>>);
+
+// wasmer_memory_new_ptr
+typedef NativeWasmerMemoryNewPtrFn = Uint32 Function(
+    Pointer<Pointer<WasmerMemory>>, Pointer<WasmerLimits>);
+typedef WasmerMemoryNewPtrFn = int Function(
+    Pointer<Pointer<WasmerMemory>>, Pointer<WasmerLimits>);
+
+// wasmer_memory_grow
+typedef NativeWasmerMemoryGrowFn = Uint32 Function(
+    Pointer<WasmerMemory>, Uint32);
+typedef WasmerMemoryGrowFn = int Function(Pointer<WasmerMemory>, int);
+
+// wasmer_memory_length
+typedef NativeWasmerMemoryLengthFn = Uint32 Function(Pointer<WasmerMemory>);
+typedef WasmerMemoryLengthFn = int Function(Pointer<WasmerMemory>);
+
+// wasmer_memory_data
+typedef NativeWasmerMemoryDataFn = Pointer<Uint8> Function(
+    Pointer<WasmerMemory>);
+typedef WasmerMemoryDataFn = Pointer<Uint8> Function(Pointer<WasmerMemory>);
+
+// wasmer_memory_data_length
+typedef NativeWasmerMemoryDataLengthFn = Uint32 Function(Pointer<WasmerMemory>);
+typedef WasmerMemoryDataLengthFn = int Function(Pointer<WasmerMemory>);
diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn
index e4b4445..5c2a3a9 100644
--- a/runtime/BUILD.gn
+++ b/runtime/BUILD.gn
@@ -207,6 +207,7 @@
   public_configs = [ ":dart_public_config" ]
   sources = [
     "include/dart_api.h",
+    "include/dart_api_dl.c",
     "include/dart_api_dl.h",
     "include/dart_native_api.h",
     "include/dart_tools_api.h",
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index a42626d..88e037b 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -51,10 +51,6 @@
       }
     }
     include_dirs = [ ".." ]
-    set_sources_assignment_filter([
-                                    "*_test.cc",
-                                    "*_test.h",
-                                  ])
     sources = builtin_impl_sources
   }
 }
@@ -325,19 +321,6 @@
 
     deps = [ "//third_party/zlib" ]
 
-    custom_sources_filter = [
-      "*_test.cc",
-      "*_test.h",
-    ]
-    if (!is_mac && !is_ios) {
-      # Dart tree uses *_macos.* instead of *_mac.*
-      custom_sources_filter += [
-        "*_macos.h",
-        "*_macos.cc",
-      ]
-    }
-    set_sources_assignment_filter(custom_sources_filter)
-
     defines = [ "DART_IO_SECURE_SOCKET_DISABLED" ]
 
     sources = io_impl_sources + cli_impl_sources
@@ -414,19 +397,6 @@
                  "..:dart_os_config",
                ] + extra_configs
     public_configs = [ "..:dart_public_config" ]
-    custom_sources_filter = [
-      "*_test.cc",
-      "*_test.h",
-      "builtin_gen_snapshot.cc",
-    ]
-    if (!is_mac && !is_ios) {
-      # Dart tree uses *_macos.* instead of *_mac.*
-      custom_sources_filter += [
-        "*_macos.h",
-        "*_macos.cc",
-      ]
-    }
-    set_sources_assignment_filter(custom_sources_filter)
 
     defines = []
     deps = [ "//third_party/zlib" ] + extra_deps
@@ -1033,10 +1003,7 @@
 
 shared_library("test_extension") {
   deps = [ ":dart" ]
-  sources = [
-    "test_extension.c",
-    "test_extension_dllmain_win.cc",
-  ]
+  sources = [ "test_extension.c" ]
   include_dirs = [ ".." ]
   defines = [
     # The only effect of DART_SHARED_LIB is to export the Dart API.
@@ -1046,6 +1013,7 @@
     cflags = [ "-fPIC" ]
   }
   if (is_win) {
+    sources += [ "test_extension_dllmain_win.cc" ]
     libs = [ "dart.lib" ]
     abs_root_out_dir = rebase_path(root_out_dir)
     ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
@@ -1054,10 +1022,7 @@
 
 shared_library("entrypoints_verification_test_extension") {
   deps = [ ":dart" ]
-  sources = [
-    "entrypoints_verification_test_extension.cc",
-    "entrypoints_verification_test_extension_dllmain_win.cc",
-  ]
+  sources = [ "entrypoints_verification_test_extension.cc" ]
   include_dirs = [ ".." ]
   defines = [
     # The only effect of DART_SHARED_LIB is to export the Dart API.
@@ -1067,6 +1032,7 @@
     cflags = [ "-fPIC" ]
   }
   if (is_win) {
+    sources += [ "entrypoints_verification_test_extension_dllmain_win.cc" ]
     libs = [ "dart.lib" ]
     abs_root_out_dir = rebase_path(root_out_dir)
     ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
@@ -1129,10 +1095,7 @@
 
 shared_library("sample_extension") {
   deps = [ ":dart" ]
-  sources = [
-    "../../samples/sample_extension/sample_extension.cc",
-    "../../samples/sample_extension/sample_extension_dllmain_win.cc",
-  ]
+  sources = [ "../../samples/sample_extension/sample_extension.cc" ]
   include_dirs = [ ".." ]
   defines = [
     # The only effect of DART_SHARED_LIB is to export the Dart API.
@@ -1142,6 +1105,8 @@
     cflags = [ "-fPIC" ]
   }
   if (is_win) {
+    sources +=
+        [ "../../samples/sample_extension/sample_extension_dllmain_win.cc" ]
     libs = [ "dart.lib" ]
     abs_root_out_dir = rebase_path(root_out_dir)
     ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index b8ea4eb..58323d0 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -45,6 +45,7 @@
   "file_macos.cc",
   "file_support.cc",
   "file_win.cc",
+  "file_win.h",
   "io_buffer.cc",
   "io_buffer.h",
   "isolate_data.cc",
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc
index ec96863..16b0984 100644
--- a/runtime/bin/directory_win.cc
+++ b/runtime/bin/directory_win.cc
@@ -13,6 +13,7 @@
 #include "bin/crypto.h"
 #include "bin/dartutils.h"
 #include "bin/file.h"
+#include "bin/file_win.h"
 #include "bin/namespace.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
@@ -21,8 +22,6 @@
 
 #undef DeleteFile
 
-#define MAX_LONG_PATH 32767
-
 namespace dart {
 namespace bin {
 
@@ -278,7 +277,12 @@
 }
 
 static bool DeleteRecursively(PathBuffer* path) {
-  DWORD attributes = GetFileAttributesW(path->AsStringW());
+  PathBuffer prefixed_path;
+  if (!prefixed_path.Add(PrefixLongDirectoryPath(path->AsScopedString()))) {
+    return false;
+  }
+
+  DWORD attributes = GetFileAttributesW(prefixed_path.AsStringW());
   if (attributes == INVALID_FILE_ATTRIBUTES) {
     return false;
   }
@@ -286,33 +290,34 @@
   // filesystem that we do not want to recurse into.
   if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
     // Just delete the junction itself.
-    return RemoveDirectoryW(path->AsStringW()) != 0;
+    return RemoveDirectoryW(prefixed_path.AsStringW()) != 0;
   }
   // If it's a file, remove it directly.
   if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
-    return DeleteFile(L"", path);
+    return DeleteFile(L"", &prefixed_path);
   }
 
-  if (!path->AddW(L"\\*")) {
+  if (!prefixed_path.AddW(L"\\*")) {
     return false;
   }
 
   WIN32_FIND_DATAW find_file_data;
-  HANDLE find_handle = FindFirstFileW(path->AsStringW(), &find_file_data);
+  HANDLE find_handle =
+      FindFirstFileW(prefixed_path.AsStringW(), &find_file_data);
 
   if (find_handle == INVALID_HANDLE_VALUE) {
     return false;
   }
 
   // Adjust the path by removing the '*' used for the search.
-  int path_length = path->length() - 1;
-  path->Reset(path_length);
+  int path_length = prefixed_path.length() - 1;
+  prefixed_path.Reset(path_length);
 
   do {
-    if (!DeleteEntry(&find_file_data, path)) {
+    if (!DeleteEntry(&find_file_data, &prefixed_path)) {
       break;
     }
-    path->Reset(path_length);  // DeleteEntry adds to the path.
+    prefixed_path.Reset(path_length);  // DeleteEntry adds to the path.
   } while (FindNextFileW(find_handle, &find_file_data) != 0);
 
   DWORD last_error = GetLastError();
@@ -324,8 +329,9 @@
     return false;
   }
   // All content deleted succesfully, try to delete directory.
-  path->Reset(path_length - 1);  // Drop the "\" from the end of the path.
-  return RemoveDirectoryW(path->AsStringW()) != 0;
+  prefixed_path.Reset(path_length -
+                      1);  // Drop the "\" from the end of the path.
+  return RemoveDirectoryW(prefixed_path.AsStringW()) != 0;
 }
 
 static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
@@ -349,7 +355,8 @@
 
 Directory::ExistsResult Directory::Exists(Namespace* namespc,
                                           const char* dir_name) {
-  Utf8ToWideScope system_name(dir_name);
+  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
+  Utf8ToWideScope system_name(prefixed_dir_name);
   return ExistsHelper(system_name.wide());
 }
 
@@ -369,7 +376,8 @@
 }
 
 bool Directory::Create(Namespace* namespc, const char* dir_name) {
-  Utf8ToWideScope system_name(dir_name);
+  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
+  Utf8ToWideScope system_name(prefixed_dir_name);
   int create_status = CreateDirectoryW(system_name.wide(), NULL);
   // If the directory already existed, treat it as a success.
   if ((create_status == 0) && (GetLastError() == ERROR_ALREADY_EXISTS) &&
@@ -475,10 +483,11 @@
 bool Directory::Delete(Namespace* namespc,
                        const char* dir_name,
                        bool recursive) {
+  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
   bool result = false;
-  Utf8ToWideScope system_dir_name(dir_name);
+  Utf8ToWideScope system_dir_name(prefixed_dir_name);
   if (!recursive) {
-    if (File::GetType(namespc, dir_name, true) == File::kIsDirectory) {
+    if (File::GetType(namespc, prefixed_dir_name, true) == File::kIsDirectory) {
       result = (RemoveDirectoryW(system_dir_name.wide()) != 0);
     } else {
       SetLastError(ERROR_FILE_NOT_FOUND);
@@ -495,18 +504,20 @@
 bool Directory::Rename(Namespace* namespc,
                        const char* path,
                        const char* new_path) {
-  Utf8ToWideScope system_path(path);
-  Utf8ToWideScope system_new_path(new_path);
+  const char* prefixed_dir = PrefixLongDirectoryPath(path);
+  Utf8ToWideScope system_path(prefixed_dir);
   ExistsResult exists = ExistsHelper(system_path.wide());
   if (exists != EXISTS) {
     return false;
   }
+  const char* prefixed_new_dir = PrefixLongDirectoryPath(new_path);
+  Utf8ToWideScope system_new_path(prefixed_new_dir);
   ExistsResult new_exists = ExistsHelper(system_new_path.wide());
   // MoveFile does not allow replacing existing directories. Therefore,
   // if the new_path is currently a directory we need to delete it
   // first.
   if (new_exists == EXISTS) {
-    bool success = Delete(namespc, new_path, true);
+    bool success = Delete(namespc, prefixed_new_dir, true);
     if (!success) {
       return false;
     }
diff --git a/runtime/bin/elf_loader.cc b/runtime/bin/elf_loader.cc
index c67f391..22c2cbc 100644
--- a/runtime/bin/elf_loader.cc
+++ b/runtime/bin/elf_loader.cc
@@ -476,7 +476,6 @@
                   ".bss does not have enough space.");
       vm_bss_ = reinterpret_cast<uword*>(base_->start() + header.memory_offset);
       isolate_bss_ = vm_bss_ + BSS::kVmEntryCount;
-      // We set applicable BSS entries in ResolveSymbols().
     }
   }
 
@@ -504,22 +503,10 @@
       output = vm_data;
     } else if (strcmp(name, kVmSnapshotInstructionsAsmSymbol) == 0) {
       output = vm_instrs;
-      if (output != nullptr) {
-        // Store the value of the symbol in the VM BSS, as it contains the
-        // address of the VM instructions section relative to the DSO base.
-        BSS::InitializeBSSEntry(BSS::Relocation::InstructionsRelocatedAddress,
-                                sym.value, vm_bss_);
-      }
     } else if (strcmp(name, kIsolateSnapshotDataAsmSymbol) == 0) {
       output = isolate_data;
     } else if (strcmp(name, kIsolateSnapshotInstructionsAsmSymbol) == 0) {
       output = isolate_instrs;
-      if (output != nullptr) {
-        // Store the value of the symbol in the isolate BSS, as it contains the
-        // address of the isolate instructions section relative to the DSO base.
-        BSS::InitializeBSSEntry(BSS::Relocation::InstructionsRelocatedAddress,
-                                sym.value, isolate_bss_);
-      }
     }
 
     if (output != nullptr) {
diff --git a/runtime/bin/ffi_test/ffi_test_functions.cc b/runtime/bin/ffi_test/ffi_test_functions.cc
index 3b915c0..c9e39e9 100644
--- a/runtime/bin/ffi_test/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions.cc
@@ -1042,4 +1042,13 @@
   return 42;
 }
 
+struct Struct43693 {
+  void* pSomePtr;
+  uint64_t someValue;
+};
+
+DART_EXPORT uint64_t Regress43693(Struct43693* my_struct) {
+  return my_struct->someValue;
+}
+
 }  // namespace dart
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc
index 33654c4..b371363 100644
--- a/runtime/bin/file_system_watcher_win.cc
+++ b/runtime/bin/file_system_watcher_win.cc
@@ -80,6 +80,9 @@
   const intptr_t kEventSize = sizeof(FILE_NOTIFY_INFORMATION);
   DirectoryWatchHandle* dir = reinterpret_cast<DirectoryWatchHandle*>(path_id);
   intptr_t available = dir->Available();
+  if (available <= 0) {
+    return Dart_NewList(0);
+  }
   intptr_t max_count = available / kEventSize + 1;
   Dart_Handle events = Dart_NewList(max_count);
   uint8_t* buffer = Dart_ScopeAllocate(available);
diff --git a/runtime/bin/file_win.cc b/runtime/bin/file_win.cc
index 21f8df2..46425dc 100644
--- a/runtime/bin/file_win.cc
+++ b/runtime/bin/file_win.cc
@@ -5,13 +5,15 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_WINDOWS)
 
-#include "bin/file.h"
+#include <functional>
+#include <memory>
+#include <string>
 
+#include <Shlwapi.h>  // NOLINT
 #include <WinIoCtl.h>  // NOLINT
 #include <fcntl.h>     // NOLINT
 #include <io.h>        // NOLINT
-#include <Shlwapi.h>   // NOLINT
-#undef StrDup  // defined in Shlwapi.h as StrDupW
+#undef StrDup          // defined in Shlwapi.h as StrDupW
 #include <stdio.h>     // NOLINT
 #include <string.h>    // NOLINT
 #include <sys/stat.h>  // NOLINT
@@ -20,6 +22,8 @@
 #include "bin/builtin.h"
 #include "bin/crypto.h"
 #include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/file_win.h"
 #include "bin/namespace.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
@@ -298,8 +302,146 @@
   return new File(new FileHandle(fd));
 }
 
+class StringRAII {
+ public:
+  explicit StringRAII(const char* s) : s_(s), own_(false) {}
+  explicit StringRAII(char* s) : s_(s), own_(true) {}
+  ~StringRAII() {
+    if (own_) {
+      free(const_cast<char*>(s_));
+    }
+  }
+  const char* str() const { return s_; }
+  const char* release() {
+    own_ = false;
+    return s_;
+  }
+
+ private:
+  bool own_;
+  const char* s_;
+};
+
+class Wchart {
+ public:
+  explicit Wchart(int size) {
+    buf_ = reinterpret_cast<wchar_t*>(malloc(size * sizeof(wchar_t)));
+  }
+  ~Wchart() { free(buf_); }
+  wchar_t* buf() const { return buf_; }
+
+ private:
+  wchar_t* buf_;
+};
+
+static StringRAII ConvertToAbsolutePath(const char* path,
+                                        bool* p_has_converted_successfully) {
+  const int kPathLength = 16384;
+  Wchart buffer(kPathLength);  // use some reasonably large initial buffer
+  Utf8ToWideScope path_utf8_to_wide(path);
+  *p_has_converted_successfully = true;
+  int full_path_length =
+      GetFullPathNameW(path_utf8_to_wide.wide(), kPathLength, buffer.buf(),
+                       /*lpFilePart=*/nullptr);
+  if (full_path_length == 0) {
+    *p_has_converted_successfully = false;
+    // GetFullPathNameW failed
+    return StringRAII(path);
+  }
+  if (full_path_length < kPathLength) {
+    WideToUtf8Scope scope(buffer.buf());
+    return StringRAII(strdup(scope.utf8()));
+  }
+
+  // Try again with bigger buffer.
+  Wchart bigger_buffer(full_path_length);
+  if (GetFullPathNameW(path_utf8_to_wide.wide(), full_path_length,
+                       bigger_buffer.buf(),
+                       /*lpFilePart=*/nullptr) == 0) {
+    *p_has_converted_successfully = false;
+    // GetFullPathNameW failed
+    return StringRAII(path);
+  }
+  WideToUtf8Scope scope(bigger_buffer.buf());
+  return StringRAII(strdup(scope.utf8()));
+}
+
+static StringRAII PrefixLongPathIfExceedLimit(
+    const char* path,
+    bool is_file,
+    std::function<char*(int)> allocate) {
+  // File name and Directory name have different size limit.
+  // Reference: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
+  const int path_short_limit = is_file ? MAX_PATH : MAX_DIRECTORY_PATH;
+
+  const char* kLongPathPrefix = "\\\\?\\";
+  const int kLongPathPrefixLength = 4;
+
+  // if absolute path is short or already prefixed, just return it.
+  if ((File::IsAbsolutePath(path) && strlen(path) < path_short_limit) ||
+      strncmp(path, kLongPathPrefix, kLongPathPrefixLength) == 0) {
+    return StringRAII(path);
+  }
+
+  // Long relative path have to be converted to absolute path before prefixing.
+  bool is_ok = true;
+  StringRAII absolute_path_raii = File::IsAbsolutePath(path)
+                                      ? StringRAII(path)
+                                      : ConvertToAbsolutePath(path, &is_ok);
+  if (!is_ok) {
+    return StringRAII(path);
+  }
+  const char* absolute_path = absolute_path_raii.str();
+  int length = strlen(absolute_path);
+  if (length < path_short_limit) {
+    // No need for a prefix if absolute path is short
+    return StringRAII(path);
+  }
+  if (strncmp(absolute_path, kLongPathPrefix, kLongPathPrefixLength) == 0) {
+    // Relative path converted to absolute could get a prefix.
+    return StringRAII(absolute_path);
+  }
+
+  // Add prefix and replace forward slashes with backward slashes.
+  char* result = allocate((kLongPathPrefixLength + length + 1) * sizeof(char));
+  strncpy(result, kLongPathPrefix, kLongPathPrefixLength);
+  for (int i = 0; i < length; i++) {
+    result[kLongPathPrefixLength + i] =
+        absolute_path[i] == '/' ? '\\' : absolute_path[i];
+  }
+  result[length + kLongPathPrefixLength] = '\0';
+  return StringRAII(result);
+}
+
+static const char* PrefixLongFilePath(const char* path) {
+  return PrefixLongPathIfExceedLimit(
+             path, /*is_file=*/true,
+             [](int size) {
+               return reinterpret_cast<char*>(Dart_ScopeAllocate(size));
+             })
+      .release();
+}
+
+static StringRAII PrefixLongFilePathNoScope(const char* path) {
+  return PrefixLongPathIfExceedLimit(path, /*is_file=*/true, [](int size) {
+    return reinterpret_cast<char*>(malloc(size));
+  });
+}
+
+const char* PrefixLongDirectoryPath(const char* path) {
+  return PrefixLongPathIfExceedLimit(
+             path, /*is_file=*/false,
+             [](int size) {
+               return reinterpret_cast<char*>(Dart_ScopeAllocate(size));
+             })
+      .release();
+}
+
 File* File::Open(Namespace* namespc, const char* path, FileOpenMode mode) {
-  Utf8ToWideScope system_name(path);
+  // File::Open can be called without scope(when launching isolate),
+  // so it mallocs prefixed path
+  StringRAII string_raii = PrefixLongFilePathNoScope(path);
+  Utf8ToWideScope system_name(string_raii.str());
   File* file = FileOpenW(system_name.wide(), mode);
   return file;
 }
@@ -364,8 +506,9 @@
 }
 
 bool File::Exists(Namespace* namespc, const char* name) {
+  StringRAII string_raii = PrefixLongFilePathNoScope(name);
+  Utf8ToWideScope system_name(string_raii.str());
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
   return StatHelper(system_name.wide(), &st);
 }
 
@@ -379,7 +522,7 @@
 }
 
 bool File::Create(Namespace* namespc, const char* name) {
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   int fd = _wopen(system_name.wide(), O_RDONLY | O_CREAT, 0666);
   if (fd < 0) {
     return false;
@@ -426,8 +569,8 @@
 bool File::CreateLink(Namespace* namespc,
                       const char* utf8_name,
                       const char* utf8_target) {
-  Utf8ToWideScope name(utf8_name);
-  Utf8ToWideScope target(utf8_target);
+  Utf8ToWideScope name(PrefixLongFilePath(utf8_name));
+  Utf8ToWideScope target(PrefixLongFilePath(utf8_target));
   DWORD flags = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE;
 
   File::Type type = File::GetType(namespc, utf8_target, true);
@@ -449,13 +592,13 @@
 }
 
 bool File::Delete(Namespace* namespc, const char* name) {
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   int status = _wremove(system_name.wide());
   return status != -1;
 }
 
 bool File::DeleteLink(Namespace* namespc, const char* name) {
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   bool result = false;
   DWORD attributes = GetFileAttributesW(system_name.wide());
   if ((attributes == INVALID_FILE_ATTRIBUTES) ||
@@ -477,13 +620,15 @@
 bool File::Rename(Namespace* namespc,
                   const char* old_path,
                   const char* new_path) {
-  File::Type type = GetType(namespc, old_path, false);
+  const char* prefixed_old_path = PrefixLongFilePath(old_path);
+  File::Type type = GetType(namespc, prefixed_old_path, false);
   if (type != kIsFile) {
     SetLastError(ERROR_FILE_NOT_FOUND);
     return false;
   }
-  Utf8ToWideScope system_old_path(old_path);
-  Utf8ToWideScope system_new_path(new_path);
+  const char* prefixed_new_path = PrefixLongFilePath(new_path);
+  Utf8ToWideScope system_old_path(prefixed_old_path);
+  Utf8ToWideScope system_new_path(prefixed_new_path);
   DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
   int move_status =
       MoveFileExW(system_old_path.wide(), system_new_path.wide(), flags);
@@ -493,23 +638,25 @@
 bool File::RenameLink(Namespace* namespc,
                       const char* old_path,
                       const char* new_path) {
-  File::Type type = GetType(namespc, old_path, false);
+  const char* prefixed_old_path = PrefixLongFilePath(old_path);
+  File::Type type = GetType(namespc, prefixed_old_path, false);
   if (type != kIsLink) {
     SetLastError(ERROR_FILE_NOT_FOUND);
     return false;
   }
-  Utf8ToWideScope system_old_path(old_path);
-  Utf8ToWideScope system_new_path(new_path);
+  Utf8ToWideScope system_old_path(prefixed_old_path);
+  const char* prefixed_new_path = PrefixLongFilePath(new_path);
+  Utf8ToWideScope system_new_path(prefixed_new_path);
   DWORD flags = MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING;
 
   // Junction links on Windows appear as special directories. MoveFileExW's
   // MOVEFILE_REPLACE_EXISTING does not allow for replacement of directories,
   // so we need to remove it before renaming a link. This step is only
   // necessary for junctions created by the old Link.create implementation.
-  if ((Directory::Exists(namespc, new_path) == Directory::EXISTS) &&
-      (GetType(namespc, new_path, false) == kIsLink)) {
+  if ((Directory::Exists(namespc, prefixed_new_path) == Directory::EXISTS) &&
+      (GetType(namespc, prefixed_new_path, false) == kIsLink)) {
     // Bail out if the DeleteLink call fails.
-    if (!DeleteLink(namespc, new_path)) {
+    if (!DeleteLink(namespc, prefixed_new_path)) {
       return false;
     }
   }
@@ -615,24 +762,26 @@
 bool File::Copy(Namespace* namespc,
                 const char* old_path,
                 const char* new_path) {
-  File::Type type = GetType(namespc, old_path, false);
+  const char* prefixed_old_path = PrefixLongFilePath(old_path);
+  const char* prefixed_new_path = PrefixLongFilePath(new_path);
+  File::Type type = GetType(namespc, prefixed_old_path, false);
   if (type != kIsFile) {
     SetLastError(ERROR_FILE_NOT_FOUND);
     return false;
   }
 
-  wchar_t* temp_file = CopyIntoTempFile(old_path, new_path);
+  wchar_t* temp_file = CopyIntoTempFile(prefixed_old_path, prefixed_new_path);
   if (temp_file == NULL) {
     // If temp file creation fails, fall back on doing a direct copy.
-    Utf8ToWideScope system_old_path(old_path);
-    Utf8ToWideScope system_new_path(new_path);
+    Utf8ToWideScope system_old_path(prefixed_old_path);
+    Utf8ToWideScope system_new_path(prefixed_new_path);
     return CopyFileExW(system_old_path.wide(), system_new_path.wide(), NULL,
                        NULL, NULL, 0) != 0;
   }
-  Utf8ToWideScope system_new_dest(new_path);
+  Utf8ToWideScope system_new_dest(prefixed_new_path);
 
   // Remove the existing file. Otherwise, renaming will fail.
-  if (Exists(namespc, new_path)) {
+  if (Exists(namespc, prefixed_new_path)) {
     DeleteFileW(system_new_dest.wide());
   }
 
@@ -647,7 +796,7 @@
 
 int64_t File::LengthFromPath(Namespace* namespc, const char* name) {
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   if (!StatHelper(system_name.wide(), &st)) {
     return -1;
   }
@@ -658,7 +807,8 @@
                              const char* pathname,
                              char* dest,
                              int dest_size) {
-  const wchar_t* name = StringUtilsWin::Utf8ToWide(pathname);
+  const wchar_t* name =
+      StringUtilsWin::Utf8ToWide(PrefixLongFilePath(pathname));
   HANDLE dir_handle = CreateFileW(
       name, GENERIC_READ,
       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
@@ -668,8 +818,10 @@
     return NULL;
   }
 
+  // Allocate a buffer for regular paths (smaller than MAX_PATH). If buffer is
+  // too small for a long path, allocate a bigger buffer and try again.
   int buffer_size =
-      sizeof(REPARSE_DATA_BUFFER) + 2 * (MAX_PATH + 1) * sizeof(WCHAR);
+      sizeof(REPARSE_DATA_BUFFER) + (MAX_PATH + 1) * sizeof(WCHAR);
   REPARSE_DATA_BUFFER* buffer =
       reinterpret_cast<REPARSE_DATA_BUFFER*>(Dart_ScopeAllocate(buffer_size));
   DWORD received_bytes;  // Value is not used.
@@ -677,9 +829,26 @@
                                buffer, buffer_size, &received_bytes, NULL);
   if (result == 0) {
     DWORD error = GetLastError();
-    CloseHandle(dir_handle);
-    SetLastError(error);
-    return NULL;
+    // If ERROR_MORE_DATA is thrown, the target path exceeds the size limit. A
+    // bigger buffer will be required.
+    if (error == ERROR_MORE_DATA) {
+      // Allocate a bigger buffer with MAX_LONG_PATH
+      buffer_size =
+          sizeof(REPARSE_DATA_BUFFER) + (MAX_LONG_PATH + 1) * sizeof(WCHAR);
+      buffer = reinterpret_cast<REPARSE_DATA_BUFFER*>(
+          Dart_ScopeAllocate(buffer_size));
+      result = DeviceIoControl(dir_handle, FSCTL_GET_REPARSE_POINT, NULL, 0,
+                               buffer, buffer_size, &received_bytes, NULL);
+      if (result == 0) {
+        // Overwrite the ERROR_MORE_DATA.
+        error = GetLastError();
+      }
+    }
+    if (result == 0) {
+      CloseHandle(dir_handle);
+      SetLastError(error);
+      return NULL;
+    }
   }
   if (CloseHandle(dir_handle) == 0) {
     return NULL;
@@ -726,11 +895,12 @@
 }
 
 void File::Stat(Namespace* namespc, const char* name, int64_t* data) {
-  File::Type type = GetType(namespc, name, false);
+  const char* prefixed_name = PrefixLongFilePath(name);
+  File::Type type = GetType(namespc, prefixed_name, false);
   data[kType] = type;
   if (type != kDoesNotExist) {
     struct _stat64 st;
-    Utf8ToWideScope system_name(name);
+    Utf8ToWideScope system_name(prefixed_name);
     int stat_status = _wstat64(system_name.wide(), &st);
     if (stat_status == 0) {
       data[kCreatedTime] = st.st_ctime * 1000;
@@ -746,7 +916,7 @@
 
 time_t File::LastAccessed(Namespace* namespc, const char* name) {
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   if (!StatHelper(system_name.wide(), &st)) {
     return -1;
   }
@@ -755,7 +925,7 @@
 
 time_t File::LastModified(Namespace* namespc, const char* name) {
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   if (!StatHelper(system_name.wide(), &st)) {
     return -1;
   }
@@ -767,7 +937,7 @@
                            int64_t millis) {
   // First get the current times.
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   if (!StatHelper(system_name.wide(), &st)) {
     return false;
   }
@@ -784,7 +954,7 @@
                            int64_t millis) {
   // First get the current times.
   struct __stat64 st;
-  Utf8ToWideScope system_name(name);
+  Utf8ToWideScope system_name(PrefixLongFilePath(name));
   if (!StatHelper(system_name.wide(), &st)) {
     return false;
   }
@@ -801,7 +971,6 @@
 bool File::IsAbsolutePath(const char* pathname) {
   if (pathname == NULL) return false;
   char first = pathname[0];
-  if (pathname == 0) return false;
   char second = pathname[1];
   if (first == '\\' && second == '\\') return true;
   if (second != ':') return false;
@@ -814,7 +983,7 @@
                                    const char* pathname,
                                    char* dest,
                                    int dest_size) {
-  Utf8ToWideScope system_name(pathname);
+  Utf8ToWideScope system_name(PrefixLongFilePath(pathname));
   HANDLE file_handle =
       CreateFileW(system_name.wide(), 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
                   FILE_FLAG_BACKUP_SEMANTICS, NULL);
@@ -838,9 +1007,8 @@
 
   // Remove leading \\?\ if possible, unless input used it.
   int offset = 0;
-  if ((result_size < MAX_PATH - 1 + 4) && (result_size > 4) &&
-      (wcsncmp(path.get(), L"\\\\?\\", 4) == 0) &&
-      (wcsncmp(system_name.wide(), L"\\\\?\\", 4) != 0)) {
+  if ((result_size > 4) && (wcsncmp(path.get(), L"\\\\?\\", 4) == 0) &&
+      (strncmp(pathname, "\\\\?\\", 4) != 0)) {
     offset = 4;
   }
   int utf8_size = WideCharToMultiByte(CP_UTF8, 0, path.get() + offset, -1,
@@ -878,8 +1046,13 @@
 File::Type File::GetType(Namespace* namespc,
                          const char* pathname,
                          bool follow_links) {
+  // File::GetType can be called without scope(when launching isolate),
+  // so it mallocs prefixed path.
+  StringRAII string_raii = PrefixLongFilePathNoScope(pathname);
+  const char* prefixed_path = string_raii.str();
+
   // Convert to wchar_t string.
-  Utf8ToWideScope name(pathname);
+  Utf8ToWideScope name(prefixed_path);
   DWORD attributes = GetFileAttributesW(name.wide());
   File::Type result = kIsFile;
   if (attributes == INVALID_FILE_ATTRIBUTES) {
@@ -919,7 +1092,8 @@
   USE(namespc_1);
   USE(namespc_2);
   BY_HANDLE_FILE_INFORMATION file_info[2];
-  const char* file_names[2] = {file_1, file_2};
+  const char* file_names[2] = {PrefixLongFilePath(file_1),
+                               PrefixLongFilePath(file_2)};
   for (int i = 0; i < 2; ++i) {
     Utf8ToWideScope wide_name(file_names[i]);
     HANDLE file_handle = CreateFileW(
diff --git a/runtime/bin/file_win.h b/runtime/bin/file_win.h
new file mode 100644
index 0000000..ef5f732
--- /dev/null
+++ b/runtime/bin/file_win.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_FILE_WIN_H_
+#define RUNTIME_BIN_FILE_WIN_H_
+
+#include "bin/file.h"
+
+// The limit for a regular directory is 248.
+// Reference: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
+#define MAX_DIRECTORY_PATH (MAX_PATH - 12)
+
+namespace dart {
+namespace bin {
+
+const char* PrefixLongDirectoryPath(const char* path);
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_FILE_WIN_H_
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 187cf92..eba26b5 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -446,7 +446,8 @@
   // First create a snapshot.
   result = Dart_CreateSnapshot(&vm_snapshot_data_buffer, &vm_snapshot_data_size,
                                &isolate_snapshot_data_buffer,
-                               &isolate_snapshot_data_size);
+                               &isolate_snapshot_data_size,
+                               /*is_core=*/true);
   CHECK_RESULT(result);
 
   // Now write the vm isolate and isolate snapshots out to the
@@ -539,7 +540,7 @@
   intptr_t isolate_snapshot_data_size = 0;
 
   result = Dart_CreateSnapshot(NULL, NULL, &isolate_snapshot_data_buffer,
-                               &isolate_snapshot_data_size);
+                               &isolate_snapshot_data_size, /*is_core=*/false);
   CHECK_RESULT(result);
 
   WriteFile(isolate_snapshot_data_filename, isolate_snapshot_data_buffer,
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 6c36240..9730817 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -117,7 +117,9 @@
   V(SecureSocket_Destroy, 1)                                                   \
   V(SecureSocket_FilterPointer, 1)                                             \
   V(SecureSocket_GetSelectedProtocol, 1)                                       \
-  V(SecureSocket_Handshake, 1)                                                 \
+  V(SecureSocket_Handshake, 2)                                                 \
+  V(SecureSocket_MarkAsTrusted, 3)                                             \
+  V(SecureSocket_NewX509CertificateWrapper, 1)                                 \
   V(SecureSocket_Init, 1)                                                      \
   V(SecureSocket_PeerCertificate, 1)                                           \
   V(SecureSocket_RegisterBadCertificateCallback, 2)                            \
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 0696dcb..4b51532 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -544,11 +544,8 @@
   result = Dart_SetDeferredLoadHandler(Loader::DeferredLoadHandler);
   CHECK_RESULT(result);
 
-  // TODO(bkonyi): remove after 2.10 branch.
-  const bool disable_dds = true;
-
   int vm_service_server_port = INVALID_VM_SERVICE_SERVER_PORT;
-  if (Options::disable_dart_dev() || disable_dds) {
+  if (Options::disable_dart_dev()) {
     vm_service_server_port = Options::vm_service_server_port();
   } else if (Options::vm_service_server_port() !=
              INVALID_VM_SERVICE_SERVER_PORT) {
@@ -556,15 +553,14 @@
   }
 
   // Load embedder specific bits and return.
-  if (!VmService::Setup((Options::disable_dart_dev() || disable_dds)
-                            ? Options::vm_service_server_ip()
-                            : DEFAULT_VM_SERVICE_SERVER_IP,
-                        vm_service_server_port, Options::vm_service_dev_mode(),
-                        Options::vm_service_auth_disabled(),
-                        Options::vm_write_service_info_filename(),
-                        Options::trace_loading(), Options::deterministic(),
-                        Options::enable_service_port_fallback(),
-                        !Options::disable_dart_dev() && !disable_dds)) {
+  if (!VmService::Setup(
+          Options::disable_dart_dev() ? Options::vm_service_server_ip()
+                                      : DEFAULT_VM_SERVICE_SERVER_IP,
+          vm_service_server_port, Options::vm_service_dev_mode(),
+          Options::vm_service_auth_disabled(),
+          Options::vm_write_service_info_filename(), Options::trace_loading(),
+          Options::deterministic(), Options::enable_service_port_fallback(),
+          !Options::disable_dart_dev())) {
     *error = Utils::StrDup(VmService::GetErrorMessage());
     return NULL;
   }
@@ -1240,8 +1236,9 @@
 // Note: must read platform only *after* VM flags are parsed because
 // they might affect how the platform is loaded.
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  // Load vm_platform_strong.dill for dart:* source support.
+  dfe.Init();
   if (script_name != nullptr) {
-    dfe.Init();
     uint8_t* application_kernel_buffer = NULL;
     intptr_t application_kernel_buffer_size = 0;
     dfe.ReadScript(script_name, &application_kernel_buffer,
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index f1d8649..1d2f619 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -485,8 +485,8 @@
   // The arguments to the VM are at positions 1 through i-1 in argv.
   Platform::SetExecutableArguments(i, argv);
 
+  bool implicitly_use_dart_dev = false;
   bool run_script = false;
-  int script_or_cmd_index = -1;
 
   // Get the script name.
   if (i < argc) {
@@ -496,11 +496,9 @@
     // to find the DartDev snapshot so we can forward the command and its
     // arguments.
     bool is_potential_file_path = !DartDevIsolate::ShouldParseCommand(argv[i]);
-    bool implicitly_use_dart_dev = false;
 #else
     bool is_potential_file_path = true;
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
-    script_or_cmd_index = i;
     if (Options::disable_dart_dev() ||
         (is_potential_file_path && !enable_vm_service_)) {
       *script_name = Utils::StrDup(argv[i]);
@@ -511,13 +509,14 @@
     else {  // NOLINT
       DartDevIsolate::set_should_run_dart_dev(true);
     }
-    // Handle the special case where the user is running a Dart program without
-    // using a DartDev command and wants to use the VM service. Here we'll run
-    // the program using DartDev as it's used to spawn a DDS instance
-    if (!Options::disable_dart_dev() && is_potential_file_path &&
-        enable_vm_service_) {
-      implicitly_use_dart_dev = true;
-      dart_options->AddArgument("run");
+    if (!Options::disable_dart_dev() && enable_vm_service_) {
+      // Handle the special case where the user is running a Dart program
+      // without using a DartDev command and wants to use the VM service. Here
+      // we'll run the program using DartDev as it's used to spawn a DDS
+      // instance.
+      if (is_potential_file_path) {
+        implicitly_use_dart_dev = true;
+      }
     }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
   }
@@ -548,6 +547,9 @@
   else {  // NOLINT
     return -1;
   }
+  USE(enable_dartdev_analytics);
+  USE(disable_dartdev_analytics);
+
   const char** vm_argv = temp_vm_options.arguments();
   int vm_argc = temp_vm_options.count();
 
@@ -591,26 +593,58 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
+  // If running with dartdev, attempt to parse VM flags which are part of the
+  // dartdev command (e.g., --enable-vm-service, --observe, etc).
+  if (!run_script) {
+    int tmp_i = i;
+    while (tmp_i < argc) {
+      OptionProcessor::TryProcess(argv[tmp_i], vm_options);
+      tmp_i++;
+    }
+  }
+  bool first_option = true;
   // Parse out options to be passed to dart main.
   while (i < argc) {
-    if (!run_script) {
-      OptionProcessor::TryProcess(argv[i], vm_options);
+    if (implicitly_use_dart_dev && first_option) {
+      // Special case where user enables VM service without using a dartdev
+      // run command. If 'run' is provided, it will be the first argument
+      // processed in this loop.
+      dart_options->AddArgument("run");
+    } else {
+      dart_options->AddArgument(argv[i]);
+      i++;
     }
-    dart_options->AddArgument(argv[i]);
-    i++;
+    // Add DDS specific flags immediately after the dartdev command.
+    if (first_option) {
+      // DDS is only enabled for the run command. Make sure we don't pass DDS
+      // specific flags along with other commands, otherwise argument parsing
+      // will fail unexpectedly.
+      bool run_command = implicitly_use_dart_dev;
+      if (!run_command && strcmp(argv[i - 1], "run") == 0) {
+        run_command = true;
+      }
+      if (!Options::disable_dart_dev() && enable_vm_service_ && run_command) {
+        const char* dds_format_str = "--launch-dds=%s:%d";
+        size_t size =
+            snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(),
+                     vm_service_server_port());
+        // Make room for '\0'.
+        ++size;
+        char* dds_uri = new char[size];
+        snprintf(dds_uri, size, dds_format_str, vm_service_server_ip(),
+                 vm_service_server_port());
+        dart_options->AddArgument(dds_uri);
+
+        // Only add --disable-service-auth-codes if dartdev is being run
+        // implicitly. Otherwise it will already be forwarded.
+        if (implicitly_use_dart_dev && Options::vm_service_auth_disabled()) {
+          dart_options->AddArgument("--disable-service-auth-codes");
+        }
+      }
+      first_option = false;
+    }
   }
 
-  if (!Options::disable_dart_dev() && enable_vm_service_) {
-    const char* dds_format_str = "--launch-dds=%s:%d";
-    size_t size = snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(),
-                           vm_service_server_port());
-    // Make room for '\0'.
-    ++size;
-    char* dds_uri = new char[size];
-    snprintf(dds_uri, size, dds_format_str, vm_service_server_ip(),
-             vm_service_server_port());
-    dart_options->AddArgument(dds_uri);
-  }
 
   // Verify consistency of arguments.
 
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 48553df..6f612fd 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -79,9 +79,9 @@
   kAppJIT,
 };
 
-static const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
-static const int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
-static const int INVALID_VM_SERVICE_SERVER_PORT = -1;
+static constexpr const char* DEFAULT_VM_SERVICE_SERVER_IP = "localhost";
+static constexpr int DEFAULT_VM_SERVICE_SERVER_PORT = 8181;
+static constexpr int INVALID_VM_SERVICE_SERVER_PORT = -1;
 
 class Options {
  public:
diff --git a/runtime/bin/namespace_win.cc b/runtime/bin/namespace_win.cc
index f31d37a1d..09a05f5 100644
--- a/runtime/bin/namespace_win.cc
+++ b/runtime/bin/namespace_win.cc
@@ -10,6 +10,8 @@
 #include <errno.h>
 #include <sys/stat.h>
 
+#include "bin/file.h"
+#include "bin/file_win.h"
 #include "bin/utils.h"
 #include "bin/utils_win.h"
 
@@ -46,6 +48,9 @@
 }
 
 bool Namespace::SetCurrent(Namespace* namespc, const char* path) {
+  // TODO(zichangguo): "\\?\" prepended long path doesn't work.
+  // https://github.com/dart-lang/sdk/issues/42416
+  path = PrefixLongDirectoryPath(path);
   Utf8ToWideScope system_path(path);
   bool result = SetCurrentDirectoryW(system_path.wide()) != 0;
   return result;
diff --git a/runtime/bin/process_fuchsia.cc b/runtime/bin/process_fuchsia.cc
index 495eceb..f5495d8 100644
--- a/runtime/bin/process_fuchsia.cc
+++ b/runtime/bin/process_fuchsia.cc
@@ -625,7 +625,8 @@
     LOG_INFO("ProcessStarter: Start() Calling fdio_spawn_vmo\n");
     zx_handle_t process = ZX_HANDLE_INVALID;
     char err_msg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
-    uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_DEFAULT_LDSVC;
+    uint32_t flags = FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_DEFAULT_LDSVC |
+                     FDIO_SPAWN_CLONE_UTC_CLOCK;
     status = fdio_spawn_vmo(ZX_HANDLE_INVALID, flags, vmo, program_arguments_,
                             program_environment_, actions_count, actions,
                             &process, err_msg);
diff --git a/runtime/bin/secure_socket_filter.cc b/runtime/bin/secure_socket_filter.cc
index 207971f..c7a89a5 100644
--- a/runtime/bin/secure_socket_filter.cc
+++ b/runtime/bin/secure_socket_filter.cc
@@ -32,6 +32,7 @@
 // To protect library initialization.
 Mutex* SSLFilter::mutex_ = nullptr;
 int SSLFilter::filter_ssl_index;
+int SSLFilter::ssl_cert_context_index;
 
 void SSLFilter::Init() {
   ASSERT(SSLFilter::mutex_ == nullptr);
@@ -143,7 +144,26 @@
 }
 
 void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
-  GetFilter(args)->Handshake();
+  Dart_Handle port = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  ASSERT(!Dart_IsNull(port));
+
+  Dart_Port port_id;
+  ThrowIfError(Dart_SendPortGetId(port, &port_id));
+  int result = GetFilter(args)->Handshake(port_id);
+  Dart_SetReturnValue(args, Dart_NewInteger(result));
+}
+
+void FUNCTION_NAME(SecureSocket_MarkAsTrusted)(Dart_NativeArguments args) {
+  GetFilter(args)->MarkAsTrusted(args);
+}
+
+void FUNCTION_NAME(SecureSocket_NewX509CertificateWrapper)(
+    Dart_NativeArguments args) {
+  intptr_t x509_pointer = DartUtils::GetNativeIntptrArgument(args, 0);
+  ASSERT(x509_pointer != 0);
+  X509* x509 = reinterpret_cast<X509*>(x509_pointer);
+  X509_up_ref(x509);
+  Dart_SetReturnValue(args, X509Helper::WrappedX509Certificate(x509));
 }
 
 void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
@@ -447,6 +467,8 @@
     SSL_library_init();
     filter_ssl_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
     ASSERT(filter_ssl_index >= 0);
+    ssl_cert_context_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+    ASSERT(ssl_cert_context_index >= 0);
     library_initialized_ = true;
   }
 }
@@ -477,7 +499,15 @@
   SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY);  // TODO(whesse): Is this right?
   SSL_set_ex_data(ssl_, filter_ssl_index, this);
   context->RegisterCallbacks(ssl_);
+  SSL_set_ex_data(ssl_, ssl_cert_context_index, context);
 
+  TrustEvaluateHandlerFunc trust_evaluate_handler =
+      context->GetTrustEvaluateHandler();
+  if (trust_evaluate_handler != nullptr) {
+    trust_evaluate_reply_port_ = Dart_NewNativePort(
+        "SSLCertContextTrustEvaluate", trust_evaluate_handler,
+        /*handle_concurrently=*/false);
+  }
   if (is_server_) {
     int certificate_mode =
         request_client_certificate ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
@@ -529,13 +559,37 @@
       }
     }
   }
-  Handshake();
+  // We don't expect certificate evaluation on first attempt,
+  // we expect requests for more bytes, therefore we could get away
+  // with passing illegal port.
+  Handshake(ILLEGAL_PORT);
 }
 
-void SSLFilter::Handshake() {
+void SSLFilter::MarkAsTrusted(Dart_NativeArguments args) {
+  intptr_t certificate_pointer = DartUtils::GetNativeIntptrArgument(args, 1);
+  ASSERT(certificate_pointer != 0);
+  certificate_trust_state_.reset(
+      new X509TrustState(reinterpret_cast<X509*>(certificate_pointer),
+                         DartUtils::GetNativeBooleanArgument(args, 2)));
+  if (SSL_LOG_STATUS) {
+    Syslog::Print("Mark %p as %strusted certificate\n",
+                  certificate_trust_state_.get()->x509(),
+                  certificate_trust_state_.get()->is_trusted() ? "" : "not ");
+  }
+}
+
+int SSLFilter::Handshake(Dart_Port reply_port) {
+  // Set reply port to be used by CertificateVerificationCallback
+  // invoked by SSL_do_handshake: this is where results of
+  // certificate evaluation will be communicated to.
+  reply_port_ = reply_port;
+
   // Try and push handshake along.
-  int status;
-  status = SSL_do_handshake(ssl_);
+  int status = SSL_do_handshake(ssl_);
+  int error = SSL_get_error(ssl_, status);
+  if (error == SSL_ERROR_WANT_CERTIFICATE_VERIFY) {
+    return SSL_ERROR_WANT_CERTIFICATE_VERIFY;
+  }
   if (callback_error != NULL) {
     // The SSL_do_handshake will try performing a handshake and might call
     // a CertificateCallback. If the certificate validation
@@ -545,7 +599,7 @@
   }
   if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
     in_handshake_ = true;
-    return;
+    return error;
   }
   SecureSocketUtils::CheckStatusSSL(
       status, "HandshakeException",
@@ -572,6 +626,8 @@
         Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
     in_handshake_ = false;
   }
+
+  return error;
 }
 
 void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
@@ -644,6 +700,10 @@
     Dart_DeletePersistentHandle(bad_certificate_callback_);
     bad_certificate_callback_ = NULL;
   }
+  if (trust_evaluate_reply_port_ != ILLEGAL_PORT) {
+    Dart_CloseNativePort(trust_evaluate_reply_port_);
+    trust_evaluate_reply_port_ = ILLEGAL_PORT;
+  }
   FreeResources();
 }
 
diff --git a/runtime/bin/secure_socket_filter.h b/runtime/bin/secure_socket_filter.h
index 70ad32e..826e28f 100644
--- a/runtime/bin/secure_socket_filter.h
+++ b/runtime/bin/secure_socket_filter.h
@@ -9,6 +9,8 @@
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 
+#include <memory>
+
 #include "bin/builtin.h"
 #include "bin/reference_counting.h"
 #include "bin/security_context.h"
@@ -21,6 +23,21 @@
 extern const unsigned char* root_certificates_pem;
 extern unsigned int root_certificates_pem_length;
 
+class X509TrustState {
+ public:
+  X509TrustState(const X509* x509, bool is_trusted)
+      : x509_(x509), is_trusted_(is_trusted) {}
+
+  const X509* x509() const { return x509_; }
+  bool is_trusted() const { return is_trusted_; }
+
+ private:
+  const X509* x509_;
+  bool is_trusted_;
+
+  DISALLOW_COPY_AND_ASSIGN(X509TrustState);
+};
+
 class SSLFilter : public ReferenceCounted<SSLFilter> {
  public:
   static void Init();
@@ -65,7 +82,8 @@
                Dart_Handle protocols_handle);
   void Destroy();
   void FreeResources();
-  void Handshake();
+  void MarkAsTrusted(Dart_NativeArguments args);
+  int Handshake(Dart_Port reply_port);
   void GetSelectedProtocol(Dart_NativeArguments args);
   void Renegotiate(bool use_session_cache,
                    bool request_client_certificate,
@@ -90,6 +108,17 @@
 
   // The index of the external data field in _ssl that points to the SSLFilter.
   static int filter_ssl_index;
+  // The index of the external data field in _ssl that points to the
+  // SSLCertContext.
+  static int ssl_cert_context_index;
+
+  const X509TrustState* certificate_trust_state() {
+    return certificate_trust_state_.get();
+  }
+  Dart_Port reply_port() const { return reply_port_; }
+  Dart_Port trust_evaluate_reply_port() const {
+    return trust_evaluate_reply_port_;
+  }
 
  private:
   static const intptr_t kInternalBIOSize;
@@ -98,6 +127,9 @@
 
   SSL* ssl_;
   BIO* socket_side_;
+  // Currently only one(root) certificate is evaluated via
+  // TrustEvaluate mechanism.
+  std::unique_ptr<X509TrustState> certificate_trust_state_;
 
   uint8_t* buffers_[kNumBuffers];
   int buffer_size_;
@@ -111,6 +143,9 @@
   bool is_server_;
   char* hostname_;
 
+  Dart_Port reply_port_ = ILLEGAL_PORT;
+  Dart_Port trust_evaluate_reply_port_ = ILLEGAL_PORT;
+
   static bool IsBufferEncrypted(int i) {
     return static_cast<BufferIndex>(i) >= kFirstEncrypted;
   }
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index 6a72909..8d2b2fc 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -36,6 +36,17 @@
       "Secure Sockets unsupported on this platform"));
 }
 
+void FUNCTION_NAME(SecureSocket_MarkAsTrusted)(Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+}
+
+void FUNCTION_NAME(SecureSocket_NewX509CertificateWrapper)(
+    Dart_NativeArguments args) {
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+}
+
 void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
     Dart_NativeArguments args) {
   Dart_ThrowException(DartUtils::NewDartArgumentError(
diff --git a/runtime/bin/security_context.h b/runtime/bin/security_context.h
index 8c37365..206a859 100644
--- a/runtime/bin/security_context.h
+++ b/runtime/bin/security_context.h
@@ -18,6 +18,9 @@
 // Forward declaration
 class SSLFilter;
 
+typedef void (*TrustEvaluateHandlerFunc)(Dart_Port dest_port_id,
+                                         Dart_CObject* message);
+
 class SSLCertContext : public ReferenceCounted<SSLCertContext> {
  public:
   static const intptr_t kApproximateSize;
@@ -83,6 +86,7 @@
   void set_trust_builtin(bool trust_builtin) { trust_builtin_ = trust_builtin; }
 
   void RegisterCallbacks(SSL* ssl);
+  TrustEvaluateHandlerFunc GetTrustEvaluateHandler() const;
 
  private:
   void AddCompiledInCerts();
diff --git a/runtime/bin/security_context_android.cc b/runtime/bin/security_context_android.cc
index d474999..e0e9378 100644
--- a/runtime/bin/security_context_android.cc
+++ b/runtime/bin/security_context_android.cc
@@ -57,6 +57,10 @@
   // verification mechanism.
 }
 
+TrustEvaluateHandlerFunc SSLCertContext::GetTrustEvaluateHandler() const {
+  return nullptr;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/security_context_fuchsia.cc b/runtime/bin/security_context_fuchsia.cc
index f66500e..e8f2f7a 100644
--- a/runtime/bin/security_context_fuchsia.cc
+++ b/runtime/bin/security_context_fuchsia.cc
@@ -50,6 +50,10 @@
   // verification mechanism.
 }
 
+TrustEvaluateHandlerFunc SSLCertContext::GetTrustEvaluateHandler() const {
+  return nullptr;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/security_context_linux.cc b/runtime/bin/security_context_linux.cc
index 8ca9049..e4a9312 100644
--- a/runtime/bin/security_context_linux.cc
+++ b/runtime/bin/security_context_linux.cc
@@ -70,6 +70,10 @@
   // verification mechanism.
 }
 
+TrustEvaluateHandlerFunc SSLCertContext::GetTrustEvaluateHandler() const {
+  return nullptr;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
index ea642aa..c130b6a 100644
--- a/runtime/bin/security_context_macos.cc
+++ b/runtime/bin/security_context_macos.cc
@@ -102,36 +102,110 @@
   return SecCertificateCreateWithData(NULL, cert_buf.get());
 }
 
-static int CertificateVerificationCallback(X509_STORE_CTX* ctx, void* arg) {
-  SSLCertContext* context = static_cast<SSLCertContext*>(arg);
+static ssl_verify_result_t CertificateVerificationCallback(SSL* ssl,
+                                                           uint8_t* out_alert) {
+  SSLFilter* filter = static_cast<SSLFilter*>(
+      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
+
+  const X509TrustState* certificate_trust_state =
+      filter->certificate_trust_state();
+  if (certificate_trust_state != nullptr) {
+    // Callback have been previously called to explicitly evaluate root_cert.
+    STACK_OF(X509)* unverified = sk_X509_dup(SSL_get_peer_full_cert_chain(ssl));
+    X509* root_cert = nullptr;
+    for (uintptr_t i = sk_X509_num(unverified); i > 0; i--) {
+      root_cert = sk_X509_shift(unverified);
+      if (root_cert == nullptr) {
+        break;
+      }
+    }
+    if (certificate_trust_state->x509() == root_cert) {
+      return certificate_trust_state->is_trusted() ? ssl_verify_ok
+                                                   : ssl_verify_invalid;
+    }
+  }
+
+  Dart_CObject dart_cobject_ssl;
+  dart_cobject_ssl.type = Dart_CObject_kInt64;
+  dart_cobject_ssl.value.as_int64 = reinterpret_cast<intptr_t>(ssl);
+
+  Dart_CObject reply_send_port;
+  reply_send_port.type = Dart_CObject_kSendPort;
+  reply_send_port.value.as_send_port.id = filter->reply_port();
+
+  Dart_CObject array;
+  array.type = Dart_CObject_kArray;
+  array.value.as_array.length = 2;
+  Dart_CObject* values[] = {&dart_cobject_ssl, &reply_send_port};
+  array.value.as_array.values = values;
+
+  Dart_PostCObject(filter->trust_evaluate_reply_port(), &array);
+  return ssl_verify_retry;
+}
+
+static void postReply(Dart_Port reply_port_id,
+                      bool success,
+                      X509* certificate = nullptr) {
+  Dart_CObject dart_cobject_success;
+  dart_cobject_success.type = Dart_CObject_kBool;
+  dart_cobject_success.value.as_bool = success;
+
+  Dart_CObject dart_cobject_certificate;
+  dart_cobject_certificate.type = Dart_CObject_kInt64;
+  dart_cobject_certificate.value.as_int64 =
+      reinterpret_cast<intptr_t>(certificate);
+
+  Dart_CObject array;
+  array.type = Dart_CObject_kArray;
+  array.value.as_array.length = 2;
+  Dart_CObject* values[] = {&dart_cobject_success, &dart_cobject_certificate};
+  array.value.as_array.values = values;
+
+  Dart_PostCObject(reply_port_id, &array);
+}
+
+static void TrustEvaluateHandler(Dart_Port dest_port_id,
+                                 Dart_CObject* message) {
+  CObjectArray request(message);
+  ASSERT(request.Length() == 2);
+
+  CObjectIntptr ssl_cobject(request[0]);
+  SSL* ssl = reinterpret_cast<SSL*>(ssl_cobject.Value());
+  SSLFilter* filter = static_cast<SSLFilter*>(
+      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
+  SSLCertContext* context = static_cast<SSLCertContext*>(
+      SSL_get_ex_data(ssl, SSLFilter::ssl_cert_context_index));
+  CObjectSendPort reply_port(request[1]);
+  Dart_Port reply_port_id = reply_port.Value();
+
+  STACK_OF(X509)* unverified = sk_X509_dup(SSL_get_peer_full_cert_chain(ssl));
 
   // Convert BoringSSL formatted certificates to SecCertificate certificates.
   ScopedCFMutableArrayRef cert_chain(NULL);
   X509* root_cert = NULL;
-  if (ctx->untrusted != NULL) {
-    STACK_OF(X509)* user_provided_certs = ctx->untrusted;
-    int num_certs = sk_X509_num(user_provided_certs);
-    int current_cert = 0;
-    cert_chain.set(CFArrayCreateMutable(NULL, num_certs, NULL));
-    X509* ca;
-    while ((ca = sk_X509_shift(user_provided_certs)) != NULL) {
-      ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
-      if (cert == NULL) {
-        return ctx->verify_cb(0, ctx);
-      }
-      CFArrayAppendValue(cert_chain.get(), cert.release());
-      ++current_cert;
+  int num_certs = sk_X509_num(unverified);
+  int current_cert = 0;
+  cert_chain.set(CFArrayCreateMutable(NULL, num_certs, NULL));
+  X509* ca;
+  while ((ca = sk_X509_shift(unverified)) != NULL) {
+    ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
+    if (cert == NULL) {
+      postReply(reply_port_id, /*success=*/false);
+      return;
+    }
+    CFArrayAppendValue(cert_chain.get(), cert.release());
+    ++current_cert;
 
-      if (current_cert == num_certs) {
-        root_cert = ca;
-      }
+    if (current_cert == num_certs) {
+      root_cert = ca;
     }
   }
 
+  SSL_CTX* ssl_ctx = SSL_get_SSL_CTX(ssl);
+  X509_STORE* store = SSL_CTX_get_cert_store(ssl_ctx);
   // Convert all trusted certificates provided by the user via
   // setTrustedCertificatesBytes or the command line into SecCertificates.
   ScopedCFMutableArrayRef trusted_certs(CFArrayCreateMutable(NULL, 0, NULL));
-  X509_STORE* store = ctx->ctx;
   ASSERT(store != NULL);
 
   if (store->objs != NULL) {
@@ -139,17 +213,14 @@
       X509* ca = sk_X509_OBJECT_value(store->objs, i)->data.x509;
       ScopedSecCertificateRef cert(CreateSecCertificateFromX509(ca));
       if (cert == NULL) {
-        return ctx->verify_cb(0, ctx);
+        postReply(reply_port_id, /*success=*/false);
+        return;
       }
       CFArrayAppendValue(trusted_certs.get(), cert.release());
     }
   }
 
   // Generate a policy for validating chains for SSL.
-  const int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
-  SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(ctx, ssl_index));
-  SSLFilter* filter = static_cast<SSLFilter*>(
-      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
   CFStringRef cfhostname = NULL;
   if (filter->hostname() != NULL) {
     cfhostname = CFStringCreateWithCString(NULL, filter->hostname(),
@@ -164,7 +235,8 @@
   OSStatus status = SecTrustCreateWithCertificates(cert_chain.get(),
                                                    policy.get(), trust.ptr());
   if (status != noErr) {
-    return ctx->verify_cb(0, ctx);
+    postReply(reply_port_id, /*success=*/false);
+    return;
   }
 
   // If the user provided any additional CA certificates, add them to the trust
@@ -172,7 +244,8 @@
   if (CFArrayGetCount(trusted_certs.get()) > 0) {
     status = SecTrustSetAnchorCertificates(trust.get(), trusted_certs.get());
     if (status != noErr) {
-      return ctx->verify_cb(0, ctx);
+      postReply(reply_port_id, /*success=*/false);
+      return;
     }
   }
 
@@ -181,7 +254,8 @@
   status =
       SecTrustSetAnchorCertificatesOnly(trust.get(), !context->trust_builtin());
   if (status != noErr) {
-    return ctx->verify_cb(0, ctx);
+    postReply(reply_port_id, /*success=*/false);
+    return;
   }
 
   SecTrustResultType trust_result;
@@ -199,29 +273,23 @@
   USE(res);
   status = SecTrustGetTrustResult(trust.get(), &trust_result);
 #else
+
   // SecTrustEvaluate is deprecated as of OSX 10.15 and iOS 13.
   status = SecTrustEvaluate(trust.get(), &trust_result);
 #endif
 
-  if (status != noErr) {
-    return ctx->verify_cb(0, ctx);
-  }
-
-  if ((trust_result == kSecTrustResultProceed) ||
-      (trust_result == kSecTrustResultUnspecified)) {
-    // Successfully verified certificate!
-    return ctx->verify_cb(1, ctx);
-  }
-
-  // Set current_cert to the root of the certificate chain. This will be passed
-  // to the callback provided by the user for additional verification steps.
-  ctx->current_cert = root_cert;
-  return ctx->verify_cb(0, ctx);
+  postReply(reply_port_id,
+            status == noErr && (trust_result == kSecTrustResultProceed ||
+                                trust_result == kSecTrustResultUnspecified),
+            root_cert);
 }
 
 void SSLCertContext::RegisterCallbacks(SSL* ssl) {
-  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
-  SSL_CTX_set_cert_verify_callback(ctx, CertificateVerificationCallback, this);
+  SSL_set_custom_verify(ssl, SSL_VERIFY_PEER, CertificateVerificationCallback);
+}
+
+TrustEvaluateHandlerFunc SSLCertContext::GetTrustEvaluateHandler() const {
+  return &TrustEvaluateHandler;
 }
 
 void SSLCertContext::TrustBuiltinRoots() {
diff --git a/runtime/bin/security_context_win.cc b/runtime/bin/security_context_win.cc
index 95673ca..1b49292 100644
--- a/runtime/bin/security_context_win.cc
+++ b/runtime/bin/security_context_win.cc
@@ -134,6 +134,10 @@
   // verification mechanism.
 }
 
+TrustEvaluateHandlerFunc SSLCertContext::GetTrustEvaluateHandler() const {
+  return nullptr;
+}
+
 }  // namespace bin
 }  // namespace dart
 
diff --git a/runtime/bin/snapshot_utils.cc b/runtime/bin/snapshot_utils.cc
index d31be2d..4a19ba2 100644
--- a/runtime/bin/snapshot_utils.cc
+++ b/runtime/bin/snapshot_utils.cc
@@ -489,8 +489,8 @@
   uint8_t* isolate_buffer = NULL;
   intptr_t isolate_size = 0;
 
-  Dart_Handle result =
-      Dart_CreateSnapshot(NULL, NULL, &isolate_buffer, &isolate_size);
+  Dart_Handle result = Dart_CreateSnapshot(NULL, NULL, &isolate_buffer,
+                                           &isolate_size, /*is_core=*/false);
   if (Dart_IsError(result)) {
     ErrorExit(kErrorExitCode, "%s\n", Dart_GetError(result));
   }
diff --git a/runtime/bin/utils_win.h b/runtime/bin/utils_win.h
index fdb4909..0e4fae9 100644
--- a/runtime/bin/utils_win.h
+++ b/runtime/bin/utils_win.h
@@ -9,6 +9,8 @@
 
 #include "platform/utils.h"
 
+#define MAX_LONG_PATH 32767
+
 namespace dart {
 namespace bin {
 
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 821ae12..5d7d117 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1242,6 +1242,8 @@
  *   snapshot. This buffer is scope allocated and is only valid
  *   until the next call to Dart_ExitScope.
  * \param size Returns the size of the buffer.
+ * \param is_core Create a snapshot containing core libraries.
+ *                Such snapshot should be agnostic to null safety mode.
  *
  * \return A valid handle if no error occurs during the operation.
  */
@@ -1249,7 +1251,8 @@
 Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
                     intptr_t* vm_snapshot_data_size,
                     uint8_t** isolate_snapshot_data_buffer,
-                    intptr_t* isolate_snapshot_data_size);
+                    intptr_t* isolate_snapshot_data_size,
+                    bool is_core);
 
 /**
  * Returns whether the buffer contains a kernel file.
@@ -3695,22 +3698,28 @@
 #define kSnapshotBuildIdCSymbol "kDartSnapshotBuildId"
 #define kVmSnapshotDataCSymbol "kDartVmSnapshotData"
 #define kVmSnapshotInstructionsCSymbol "kDartVmSnapshotInstructions"
+#define kVmSnapshotBssCSymbol "kDartVmSnapshotBss"
 #define kIsolateSnapshotDataCSymbol "kDartIsolateSnapshotData"
 #define kIsolateSnapshotInstructionsCSymbol "kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssCSymbol "kDartIsolateSnapshotBss"
 #else
 #define kSnapshotBuildIdCSymbol "_kDartSnapshotBuildId"
 #define kVmSnapshotDataCSymbol "_kDartVmSnapshotData"
 #define kVmSnapshotInstructionsCSymbol "_kDartVmSnapshotInstructions"
+#define kVmSnapshotBssCSymbol "_kDartVmSnapshotBss"
 #define kIsolateSnapshotDataCSymbol "_kDartIsolateSnapshotData"
 #define kIsolateSnapshotInstructionsCSymbol "_kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssCSymbol "_kDartIsolateSnapshotBss"
 #endif
 
 #define kSnapshotBuildIdAsmSymbol "_kDartSnapshotBuildId"
 #define kVmSnapshotDataAsmSymbol "_kDartVmSnapshotData"
 #define kVmSnapshotInstructionsAsmSymbol "_kDartVmSnapshotInstructions"
+#define kVmSnapshotBssAsmSymbol "_kDartVmSnapshotBss"
 #define kIsolateSnapshotDataAsmSymbol "_kDartIsolateSnapshotData"
 #define kIsolateSnapshotInstructionsAsmSymbol                                  \
   "_kDartIsolateSnapshotInstructions"
+#define kIsolateSnapshotBssAsmSymbol "_kDartIsolateSnapshotBss"
 
 /**
  *  Creates a precompiled snapshot.
diff --git a/runtime/include/dart_api_dl.c b/runtime/include/dart_api_dl.c
index 7709a02..c4a68f4 100644
--- a/runtime/include/dart_api_dl.c
+++ b/runtime/include/dart_api_dl.c
@@ -4,9 +4,9 @@
  * BSD-style license that can be found in the LICENSE file.
  */
 
-#include "include/dart_api_dl.h"
-#include "include/dart_version.h"
-#include "include/internal/dart_api_dl_impl.h"
+#include "dart_api_dl.h"               /* NOLINT */
+#include "dart_version.h"              /* NOLINT */
+#include "internal/dart_api_dl_impl.h" /* NOLINT */
 
 #include <string.h>
 
@@ -16,7 +16,7 @@
 
 #undef DART_API_DL_DEFINITIONS
 
-typedef void (*DartApiEntry_function)();
+typedef void* DartApiEntry_function;
 
 DartApiEntry_function FindFunctionPointer(const DartApiEntry* entries,
                                           const char* name) {
diff --git a/runtime/include/dart_api_dl.h b/runtime/include/dart_api_dl.h
index 85460c8..391f441 100644
--- a/runtime/include/dart_api_dl.h
+++ b/runtime/include/dart_api_dl.h
@@ -7,8 +7,8 @@
 #ifndef RUNTIME_INCLUDE_DART_API_DL_H_
 #define RUNTIME_INCLUDE_DART_API_DL_H_
 
-#include "include/dart_api.h"
-#include "include/dart_native_api.h"
+#include "dart_api.h"        /* NOLINT */
+#include "dart_native_api.h" /* NOLINT */
 
 /** \mainpage Dynamically Linked Dart API
  *
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc
index bdf51ec..1c89c6d 100644
--- a/runtime/lib/integers.cc
+++ b/runtime/lib/integers.cc
@@ -196,7 +196,7 @@
       if (result.IsSmi()) {
         return result.raw();
       }
-      return result.CheckAndCanonicalize(thread, NULL);
+      return result.Canonicalize(thread);
     }
   }
   return default_value.raw();
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index b33315f..4b381cb 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -158,62 +158,91 @@
   Class& klass = Class::Handle(zone);
   Closure& closure = Closure::Handle(zone);
 
-  MallocGrowableArray<ObjectPtr> working_set;
-  std::unique_ptr<WeakTable> visited(new WeakTable());
+  bool error_found = false;
+  Function& erroneous_closure_function = Function::Handle(zone);
+  Class& erroneous_nativewrapper_class = Class::Handle(zone);
+  const char* error_message = nullptr;
 
-  NoSafepointScope no_safepoint;
-  SendMessageValidator visitor(isolate->group(), visited.get(), &working_set);
+  {
+    NoSafepointScope no_safepoint;
+    // working_set contains only elements that have not been visited yet that
+    // need to be processed.
+    // So before adding elements to working_set ensure to check visited flag,
+    // set visited flag at the same time as the element is added.
+    MallocGrowableArray<ObjectPtr> working_set;
+    std::unique_ptr<WeakTable> visited(new WeakTable());
 
-  visited->SetValueExclusive(obj.raw(), 1);
-  working_set.Add(obj.raw());
+    SendMessageValidator visitor(isolate->group(), visited.get(), &working_set);
 
-  while (!working_set.is_empty()) {
-    ObjectPtr raw = working_set.RemoveLast();
+    visited->SetValueExclusive(obj.raw(), 1);
+    working_set.Add(obj.raw());
 
-    if (visited->GetValueExclusive(raw) > 0) {
-      continue;
-    }
-    visited->SetValueExclusive(raw, 1);
+    while (!working_set.is_empty() && !error_found) {
+      ObjectPtr raw = working_set.RemoveLast();
 
-    const intptr_t cid = raw->GetClassId();
-    switch (cid) {
-      // List below matches the one in raw_object_snapshot.cc
+      const intptr_t cid = raw->GetClassId();
+      switch (cid) {
+        // List below matches the one in raw_object_snapshot.cc
 #define MESSAGE_SNAPSHOT_ILLEGAL(type)                                         \
   case k##type##Cid:                                                           \
-    return Exceptions::CreateUnhandledException(                               \
-        zone, Exceptions::kArgumentValue,                                      \
-        "Illegal argument in isolate message : (object is a " #type ")");
+    error_message =                                                            \
+        "Illegal argument in isolate message : (object is a " #type ")";       \
+    error_found = true;                                                        \
+    break;
 
-      MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
-      MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
-      MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
-      MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
-      MESSAGE_SNAPSHOT_ILLEGAL(RegExp);
-      MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
-      MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
+        MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
+        MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
+        MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
+        MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
+        MESSAGE_SNAPSHOT_ILLEGAL(RegExp);
+        MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
+        MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
 
-      case kClosureCid: {
-        closure = Closure::RawCast(raw);
-        FunctionPtr func = closure.function();
-        // We only allow closure of top level methods or static functions in a
-        // class to be sent in isolate messages.
-        if (!Function::IsImplicitStaticClosureFunction(func)) {
-          return Exceptions::CreateUnhandledException(
-              zone, Exceptions::kArgumentValue, "Closures are not allowed");
-        }
-        break;
-      }
-      default:
-        if (cid >= kNumPredefinedCids) {
-          klass = class_table->At(cid);
-          if (klass.num_native_fields() != 0) {
-            return Exceptions::CreateUnhandledException(
-                zone, Exceptions::kArgumentValue,
-                "Objects that extend NativeWrapper are not allowed");
+        case kClosureCid: {
+          closure = Closure::RawCast(raw);
+          FunctionPtr func = closure.function();
+          // We only allow closure of top level methods or static functions in a
+          // class to be sent in isolate messages.
+          if (!Function::IsImplicitStaticClosureFunction(func)) {
+            // All other closures are errors.
+            erroneous_closure_function = func;
+            error_found = true;
+            break;
           }
+          break;
         }
+        default:
+          if (cid >= kNumPredefinedCids) {
+            klass = class_table->At(cid);
+            if (klass.num_native_fields() != 0) {
+              erroneous_nativewrapper_class = klass.raw();
+              error_found = true;
+              break;
+            }
+          }
+      }
+      raw->ptr()->VisitPointers(&visitor);
     }
-    raw->ptr()->VisitPointers(&visitor);
+  }
+  if (error_found) {
+    const char* exception_message;
+    if (error_message != nullptr) {
+      exception_message = error_message;
+    } else if (!erroneous_closure_function.IsNull()) {
+      exception_message = OS::SCreate(zone,
+                                      "Illegal argument in isolate message"
+                                      " : (object is a closure - %s)",
+                                      erroneous_closure_function.ToCString());
+    } else {
+      ASSERT(!erroneous_nativewrapper_class.IsNull());
+      exception_message =
+          OS::SCreate(zone,
+                      "Illegal argument in isolate message"
+                      " : (object extends NativeWrapper - %s)",
+                      erroneous_nativewrapper_class.ToCString());
+    }
+    return Exceptions::CreateUnhandledException(
+        zone, Exceptions::kArgumentValue, exception_message);
   }
   isolate->set_forward_table_new(nullptr);
   return obj.raw();
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 0bed69c..34ccc5b 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -707,7 +707,7 @@
   ASSERT(type.IsCanonical() || type.IsTypeParameter());
 
   if (type.IsInstantiated()) {
-    return type.Canonicalize();
+    return type.Canonicalize(Thread::Current(), nullptr);
   }
   TypeArguments& instantiator_type_args = TypeArguments::Handle();
   if (!instantiator.IsNull()) {
@@ -718,7 +718,7 @@
       instantiator_type_args, Object::null_type_arguments(), kAllFree,
       Heap::kOld));
   ASSERT(result.IsFinalized());
-  return result.Canonicalize();
+  return result.Canonicalize(Thread::Current(), nullptr);
 }
 
 DEFINE_NATIVE_ENTRY(MirrorSystem_libraries, 0, 0) {
@@ -985,7 +985,7 @@
   ASSERT(!func.IsNull());
   AbstractType& type = AbstractType::Handle(func.result_type());
   // Signatures of function types are instantiated, but not canonical.
-  return type.Canonicalize();
+  return type.Canonicalize(thread, nullptr);
 }
 
 DEFINE_NATIVE_ENTRY(ClassMirror_libraryUri, 0, 1) {
@@ -1332,7 +1332,7 @@
   const AbstractType& type = AbstractType::Handle(instance.GetType(Heap::kNew));
   // The static type of null is specified to be the bottom type, however, the
   // runtime type of null is the Null type, which we correctly return here.
-  return type.Canonicalize();
+  return type.Canonicalize(thread, nullptr);
 }
 
 DEFINE_NATIVE_ENTRY(ClosureMirror_function, 0, 1) {
@@ -1487,7 +1487,7 @@
       ASSERT(redirect_type.IsInstantiated(kFunctions));
       redirect_type ^= redirect_type.InstantiateFrom(
           type_arguments, Object::null_type_arguments(), kNoneFree, Heap::kOld);
-      redirect_type ^= redirect_type.Canonicalize();
+      redirect_type ^= redirect_type.Canonicalize(thread, nullptr);
     }
 
     type = redirect_type.raw();
@@ -1638,7 +1638,8 @@
   // We handle constructors in Dart code.
   ASSERT(!func.IsGenerativeConstructor());
   AbstractType& type = AbstractType::Handle(func.result_type());
-  type = type.Canonicalize();  // Instantiated signatures are not canonical.
+  type = type.Canonicalize(
+      thread, nullptr);  // Instantiated signatures are not canonical.
   return InstantiateType(type, instantiator);
 }
 
@@ -1756,7 +1757,8 @@
   const Function& func = Function::Handle(ref.GetFunctionReferent());
   AbstractType& type = AbstractType::Handle(
       func.ParameterTypeAt(func.NumImplicitParameters() + pos.Value()));
-  type = type.Canonicalize();  // Instantiated signatures are not canonical.
+  type = type.Canonicalize(
+      thread, nullptr);  // Instantiated signatures are not canonical.
   return InstantiateType(type, instantiator);
 }
 
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 7dd5823..f015232 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -23,7 +23,7 @@
       Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
   const char* msg = instance.ToCString();
   OS::PrintErr("Fatal error in dart:async: %s\n", msg);
-  FATAL(msg);
+  FATAL("%s", msg);
   return Object::null();
 }
 
@@ -367,7 +367,8 @@
         type_arg = interface_type_args.TypeAt(offset + i);
         extracted_type_args.SetTypeAt(i, type_arg);
       }
-      extracted_type_args = extracted_type_args.Canonicalize();  // Can be null.
+      extracted_type_args =
+          extracted_type_args.Canonicalize(thread, nullptr);  // Can be null.
     }
   }
   // Call the closure 'extract'.
@@ -496,9 +497,14 @@
   InvocationMirror::Kind kind;
   InvocationMirror::DecodeType(invocation_type.Value(), &level, &kind);
 
-  Function& function = Function::Handle();
+  Function& function = Function::Handle(zone);
   if (receiver.IsType()) {
-    Class& cls = Class::Handle(Type::Cast(receiver).type_class());
+    const auto& cls = Class::Handle(zone, Type::Cast(receiver).type_class());
+    const auto& error = Error::Handle(zone, cls.EnsureIsFinalized(thread));
+    if (!error.IsNull()) {
+      Exceptions::PropagateError(error);
+      UNREACHABLE();
+    }
     if (level == InvocationMirror::kConstructor) {
       function = cls.LookupConstructor(method_name);
       if (function.IsNull()) {
@@ -510,7 +516,7 @@
   } else if (receiver.IsClosure()) {
     function = Closure::Cast(receiver).function();
   } else {
-    Class& cls = Class::Handle(receiver.clazz());
+    auto& cls = Class::Handle(zone, receiver.clazz());
     if (level == InvocationMirror::kSuper) {
       cls = cls.SuperClass();
     }
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc
index 2e3cf1c..b49b14e 100644
--- a/runtime/lib/typed_data.cc
+++ b/runtime/lib/typed_data.cc
@@ -177,6 +177,21 @@
   return Bool::False().raw();
 }
 
+// Native methods for typed data allocation are recognized and implemented
+// both in FlowGraphBuilder::BuildGraphOfRecognizedMethod and interpreter.
+// These bodies exist only to assert that they are not used.
+#define TYPED_DATA_NEW(name)                                                   \
+  DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 0, 2) {                          \
+    UNREACHABLE();                                                             \
+    return Object::null();                                                     \
+  }
+
+#define TYPED_DATA_NEW_NATIVE(name) TYPED_DATA_NEW(name)
+
+CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
+#undef TYPED_DATA_NEW_NATIVE
+#undef TYPED_DATA_NEW
+
 // We check the length parameter against a possible maximum length for the
 // array based on available physical addressable memory on the system.
 //
@@ -188,28 +203,6 @@
 // into a _Smi.
 //
 // Argument 0 is type arguments and is ignored.
-#define TYPED_DATA_NEW(name)                                                   \
-  DEFINE_NATIVE_ENTRY(TypedData_##name##_new, 0, 2) {                          \
-    GET_NON_NULL_NATIVE_ARGUMENT(Integer, length, arguments->NativeArgAt(1));  \
-    const intptr_t cid = kTypedData##name##Cid;                                \
-    const intptr_t max = TypedData::MaxElements(cid);                          \
-    const int64_t len = length.AsInt64Value();                                 \
-    if (len < 0) {                                                             \
-      Exceptions::ThrowRangeError("length", length, 0, max);                   \
-    } else if (len > max) {                                                    \
-      const Instance& exception = Instance::Handle(                            \
-          zone, thread->isolate()->object_store()->out_of_memory());           \
-      Exceptions::Throw(thread, exception);                                    \
-    }                                                                          \
-    return TypedData::New(cid, static_cast<intptr_t>(len));                    \
-  }
-
-#define TYPED_DATA_NEW_NATIVE(name) TYPED_DATA_NEW(name)
-
-CLASS_LIST_TYPED_DATA(TYPED_DATA_NEW_NATIVE)
-#undef TYPED_DATA_NEW_NATIVE
-#undef TYPED_DATA_NEW
-
 #define TYPED_DATA_VIEW_NEW(native_name, cid)                                  \
   DEFINE_NATIVE_ENTRY(native_name, 0, 4) {                                     \
     GET_NON_NULL_NATIVE_ARGUMENT(TypedDataBase, typed_data,                    \
diff --git a/runtime/observatory/tests/service/async_next_regession_18877_test.dart b/runtime/observatory/tests/service/async_next_regession_18877_test.dart
index d0843b5..8b56841 100644
--- a/runtime/observatory/tests/service/async_next_regession_18877_test.dart
+++ b/runtime/observatory/tests/service/async_next_regession_18877_test.dart
@@ -38,10 +38,12 @@
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_A),
   stepOver, // foo()
+  stoppedAtLine(LINE_A),
   asyncNext,
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_B),
   stepOver, // foo()
+  stoppedAtLine(LINE_B),
   asyncNext,
   hasStoppedAtBreakpoint,
   stoppedAtLine(LINE_C),
diff --git a/runtime/observatory/tests/service/file_service_test.dart b/runtime/observatory/tests/service/file_service_test.dart
index 08c6d71..b347920 100644
--- a/runtime/observatory/tests/service/file_service_test.dart
+++ b/runtime/observatory/tests/service/file_service_test.dart
@@ -12,7 +12,7 @@
 import 'test_helper.dart';
 
 Future setupFiles() async {
-  var dir = await io.Directory.systemTemp.createTemp('file_service');
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
   var writingFile;
   var readingFile;
 
@@ -28,20 +28,20 @@
 
   Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
     closeDown();
-    var result = jsonEncode({'type': 'foobar'});
-    return new Future.value(new ServiceExtensionResponse.result(result));
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
   }
 
   Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
     try {
-      var filePath = dir.path + io.Platform.pathSeparator + "file";
-      var f = new io.File(filePath);
+      final filePath = dir.path + io.Platform.pathSeparator + "file";
+      final f = io.File(filePath);
       writingFile = await f.open(mode: io.FileMode.write);
       await writingFile.writeByte(42);
       await writingFile.writeByte(42);
       await writingFile.writeByte(42);
 
-      var file = new io.File.fromUri(io.Platform.script);
+      final file = io.File.fromUri(io.Platform.script);
       readingFile = await file.open();
       await readingFile.readByte();
       await readingFile.readByte();
@@ -51,18 +51,18 @@
 
       // The utility functions should close the files after them, so we
       // don't expect the calls below to result in open files.
-      var writeTemp = dir.path + io.Platform.pathSeparator + "other_file";
-      var utilFile = new io.File(writeTemp);
+      final writeTemp = dir.path + io.Platform.pathSeparator + "other_file";
+      final utilFile = io.File(writeTemp);
       await utilFile.writeAsString('foobar');
-      var readTemp = new io.File(writeTemp);
-      var result = await readTemp.readAsString();
+      final readTemp = io.File(writeTemp);
+      final result = await readTemp.readAsString();
       Expect.equals(result, 'foobar');
     } catch (e) {
       closeDown();
       throw e;
     }
-    var result = jsonEncode({'type': 'foobar'});
-    return new Future.value(new ServiceExtensionResponse.result(result));
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
   }
 
   registerExtension('ext.dart.io.cleanup', cleanup);
@@ -73,30 +73,29 @@
   (Isolate isolate) async {
     await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
     try {
-      var result =
+      final result =
           await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenFiles', {});
-      expect(result['type'], equals('_openfiles'));
+      expect(result['type'], equals('OpenFileList'));
+      expect(result['files'].length, equals(2));
+      final writing = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getOpenFileById', {'id': result['files'][0]['id']});
 
-      expect(result['data'].length, equals(2));
-      var writing = await isolate.invokeRpcNoUpgrade(
-          'ext.dart.io.getFileByID', {'id': result['data'][0]['id']});
-
-      expect(writing['totalRead'], equals(0));
+      expect(writing['readBytes'], equals(0));
       expect(writing['readCount'], equals(0));
       expect(writing['writeCount'], equals(3));
-      expect(writing['totalWritten'], equals(3));
-      expect(writing['lastWrite'], greaterThan(0));
-      expect(writing['lastRead'], equals(0));
+      expect(writing['writeBytes'], equals(3));
+      expect(writing['lastWriteTime'], greaterThan(0));
+      expect(writing['lastReadTime'], equals(0));
 
-      var reading = await isolate.invokeRpcNoUpgrade(
-          'ext.dart.io.getFileByID', {'id': result['data'][1]['id']});
+      final reading = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getOpenFileById', {'id': result['files'][1]['id']});
 
-      expect(reading['totalRead'], equals(5));
+      expect(reading['readBytes'], equals(5));
       expect(reading['readCount'], equals(5));
       expect(reading['writeCount'], equals(0));
-      expect(reading['totalWritten'], equals(0));
-      expect(reading['lastWrite'], equals(0));
-      expect(reading['lastRead'], greaterThan(0));
+      expect(reading['writeBytes'], equals(0));
+      expect(reading['lastWriteTime'], equals(0));
+      expect(reading['lastReadTime'], greaterThan(0));
     } finally {
       await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
     }
diff --git a/runtime/observatory/tests/service/get_isolate_rpc_test.dart b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
index adffeb7..4e79317 100644
--- a/runtime/observatory/tests/service/get_isolate_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_isolate_rpc_test.dart
@@ -16,6 +16,8 @@
     expect(result['type'], equals('Isolate'));
     expect(result['id'], startsWith('isolates/'));
     expect(result['number'], isA<String>());
+    expect(result['isolateFlags'], isA<List>());
+    expect(result['isolateFlags'].length, isPositive);
     expect(result['isSystemIsolate'], isFalse);
     expect(result['_originNumber'], equals(result['number']));
     expect(result['startTime'], isPositive);
diff --git a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
index 73ac5bd..d03bffb 100644
--- a/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_retaining_path_rpc_test.dart
@@ -21,9 +21,13 @@
 var target3 = new _TestClass();
 var target4 = new _TestClass();
 var target5 = new _TestClass();
+@pragma("vm:entry-point") // Prevent obfuscation
 var globalObject = new _TestClass();
+@pragma("vm:entry-point") // Prevent obfuscation
 var globalList = new List(100);
+@pragma("vm:entry-point") // Prevent obfuscation
 var globalMap1 = new Map();
+@pragma("vm:entry-point") // Prevent obfuscation
 var globalMap2 = new Map();
 
 void warmup() {
@@ -93,9 +97,9 @@
       'limit': 100,
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
-    expect(result['gcRootType'], 'static fields table');
-    expect(result['elements'].length, equals(1));
-    expect(result['elements'][0]['value']['type'], equals('@Instance'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(2));
+    expect(result['elements'][1]['value']['name'], equals('globalObject'));
   },
 
   // missing limit.
@@ -125,10 +129,10 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['gcRootType'], 'static fields table');
-    expect(result['elements'].length, equals(2));
-    expect(result['elements'][0]['value']['type'], equals('@Instance'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
     expect(result['elements'][1]['parentField'], equals('x'));
+    expect(result['elements'][2]['value']['name'], equals('globalObject'));
   },
 
   (Isolate isolate) async {
@@ -139,10 +143,10 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['gcRootType'], 'static fields table');
-    expect(result['elements'].length, equals(2));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
     expect(result['elements'][1]['parentField'], equals('y'));
-    expect(result['elements'][1]['value']['type'], equals('@Instance'));
+    expect(result['elements'][2]['value']['name'], equals('globalObject'));
   },
 
   (Isolate isolate) async {
@@ -153,10 +157,10 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['gcRootType'], 'static fields table');
-    expect(result['elements'].length, equals(2));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
     expect(result['elements'][1]['parentListIndex'], equals(12));
-    expect(result['elements'][1]['value']['type'], equals('@Instance'));
+    expect(result['elements'][2]['value']['name'], equals('globalList'));
   },
 
   (Isolate isolate) async {
@@ -167,11 +171,11 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['gcRootType'], 'static fields table');
-    expect(result['elements'].length, equals(2));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
     expect(
         result['elements'][1]['parentMapKey']['valueAsString'], equals('key'));
-    expect(result['elements'][1]['value']['type'], equals('@Instance'));
+    expect(result['elements'][2]['value']['name'], equals('globalMap1'));
   },
 
   (Isolate isolate) async {
@@ -182,10 +186,10 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'].length, equals(2));
+    expect(result['elements'].length, equals(3));
     expect(result['elements'][1]['parentMapKey']['class']['name'],
         equals('_TestClass'));
-    expect(result['elements'][1]['value']['type'], equals('@Instance'));
+    expect(result['elements'][2]['value']['name'], equals('globalMap2'));
   },
 
   // object store
diff --git a/runtime/observatory/tests/service/get_user_level_retaining_path_rpc_test.dart b/runtime/observatory/tests/service/get_user_level_retaining_path_rpc_test.dart
index 9f69aeb..535c882 100644
--- a/runtime/observatory/tests/service/get_user_level_retaining_path_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_user_level_retaining_path_rpc_test.dart
@@ -53,9 +53,10 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'].length, equals(1));
+    expect(result['elements'].length, equals(2));
     expect(
         result['elements'][0]['value']['class']['name'], equals('_TestConst'));
+    expect(result['elements'][1]['value']['name'], equals('x'));
   },
 
   // Expect a simple path through variable fn instead of long path filled
@@ -68,8 +69,9 @@
     };
     var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
     expect(result['type'], equals('RetainingPath'));
-    expect(result['elements'].length, equals(1));
+    expect(result['elements'].length, equals(2));
     expect(result['elements'][0]['value']['class']['name'], equals('_Closure'));
+    expect(result['elements'][1]['value']['name'], equals('fn'));
   }
 ];
 
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 8e949ec..8b56393 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(39));
+    expect(result['minor'], equals(40));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory/tests/service/inbound_references_test.dart b/runtime/observatory/tests/service/inbound_references_test.dart
index 267f1b1..5c10ae1 100644
--- a/runtime/observatory/tests/service/inbound_references_test.dart
+++ b/runtime/observatory/tests/service/inbound_references_test.dart
@@ -48,6 +48,8 @@
         r['source'].clazz.name == 'Node');
     hasReferenceSuchThat(
         (r) => r['parentListIndex'] == 1 && r['source'].isList);
+    hasReferenceSuchThat(
+        (r) => r['source'] is Field && r['source'].name == 'e');
   }
 ];
 
diff --git a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
index 6f98284..e922a19 100644
--- a/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
+++ b/runtime/observatory/tests/service/pause_on_unhandled_async_exceptions2_test.dart
@@ -44,20 +44,13 @@
     var stack = await isolate.getStack();
     expect(stack['asyncCausalFrames'], isNotNull);
     var asyncStack = stack['asyncCausalFrames'];
-    if (useCausalAsyncStacks) {
-      expect(asyncStack.length, greaterThanOrEqualTo(4));
-      expect(asyncStack[0].toString(), contains('doThrow'));
-      expect(asyncStack[1].toString(), contains('asyncThrower'));
-      expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
-      expect(asyncStack[3].toString(), contains('testeeMain'));
-      expect(await asyncStack[3].location.toUserString(),
-          contains('.dart:$LINE_A'));
-    } else {
-      expect(asyncStack.length, greaterThanOrEqualTo(2));
-      expect(asyncStack[0].toString(), contains('doThrow'));
-      expect(asyncStack[1].toString(), contains('asyncThrower'));
-      // There was no await'er for "doThrow()".
-    }
+    expect(asyncStack.length, greaterThanOrEqualTo(4));
+    expect(asyncStack[0].toString(), contains('doThrow'));
+    expect(asyncStack[1].toString(), contains('asyncThrower'));
+    expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    expect(asyncStack[3].toString(), contains('testeeMain'));
+    expect(
+        await asyncStack[3].location.toUserString(), contains('.dart:$LINE_A'));
   }
 ];
 
diff --git a/runtime/observatory/tests/service/positive_token_pos_test.dart b/runtime/observatory/tests/service/positive_token_pos_test.dart
index ee8dbad..b9c25a8 100644
--- a/runtime/observatory/tests/service/positive_token_pos_test.dart
+++ b/runtime/observatory/tests/service/positive_token_pos_test.dart
@@ -30,13 +30,8 @@
     // See issue #27128.
     var frame = stack['frames'][0];
     expect(frame.function.qualifiedName, equals('helper.async_op'));
-    if (useCausalAsyncStacks) {
-      expect(await frame.location.getLine(), equals(14));
-      expect(await frame.location.getColumn(), equals(1));
-    } else {
-      expect(await frame.location.getLine(), equals(12));
-      expect(await frame.location.getColumn(), equals(7));
-    }
+    expect(await frame.location.getLine(), equals(14));
+    expect(await frame.location.getColumn(), equals(1));
 
     frame = stack['frames'][1];
     expect(frame.function.name, equals('testMain'));
diff --git a/runtime/observatory/tests/service/process_service_test.dart b/runtime/observatory/tests/service/process_service_test.dart
index ced9326..8840ef1 100644
--- a/runtime/observatory/tests/service/process_service_test.dart
+++ b/runtime/observatory/tests/service/process_service_test.dart
@@ -13,20 +13,20 @@
 
 import 'test_helper.dart';
 
-final dartJITBinary = path.join(path.dirname(io.Platform.executable),
-    'dart' + path.extension(io.Platform.executable));
+final dartJITBinary = path.join(path.dirname(io.Platform.resolvedExecutable),
+    'dart' + path.extension(io.Platform.resolvedExecutable));
 
 Future setupProcesses() async {
-  var dir = await io.Directory.systemTemp.createTemp('file_service');
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
 
-  var args = [
+  final args = [
     ...io.Platform.executableArguments,
     '--pause_isolates_on_start',
     io.Platform.script.toFilePath(),
   ];
-  var process1;
-  var process2;
-  var process3;
+  io.Process process1;
+  io.Process process2;
+  io.Process process3;
 
   void closeDown() {
     if (process1 != null) {
@@ -43,8 +43,8 @@
 
   Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
     closeDown();
-    var result = jsonEncode({'type': 'foobar'});
-    return new Future.value(new ServiceExtensionResponse.result(result));
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
   }
 
   Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
@@ -52,8 +52,8 @@
       process1 = await io.Process.start(io.Platform.executable, args);
       process2 =
           await io.Process.start(io.Platform.executable, args..add('foobar'));
-      var codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
-      var codeFile = new io.File(codeFilePath);
+      final codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
+      final codeFile = io.File(codeFilePath);
       await codeFile.writeAsString('''
           import "dart:io";
 
@@ -63,23 +63,23 @@
           ''');
       process3 = await io.Process.start(
           dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
-    } catch (e) {
+    } catch (_) {
       closeDown();
-      throw e;
+      rethrow;
     }
 
-    var result = jsonEncode({
+    final result = jsonEncode({
       'type': 'foobar',
       'pids': [process1.pid, process2.pid, process3.pid]
     });
-    return new Future.value(new ServiceExtensionResponse.result(result));
+    return Future.value(ServiceExtensionResponse.result(result));
   }
 
   Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) {
     process3.stdin.close();
     return process3.exitCode.then<ServiceExtensionResponse>((int exit) {
-      var result = jsonEncode({'type': 'foobar'});
-      return new ServiceExtensionResponse.result(result);
+      final result = jsonEncode({'type': 'foobar'});
+      return ServiceExtensionResponse.result(result);
     });
   }
 
@@ -88,26 +88,28 @@
   registerExtension('ext.dart.io.closeStdin', closeStdin);
 }
 
-var processTests = <IsolateTest>[
+final processTests = <IsolateTest>[
   // Initial.
   (Isolate isolate) async {
-    var setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
+    final setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
     try {
-      var all =
-          await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
-      expect(all['type'], equals('_startedprocesses'));
+      var all = await isolate
+          .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {});
+      expect(all['type'], equals('SpawnedProcessList'));
 
-      expect(all['data'].length, equals(3));
+      expect(all['processes'].length, equals(3));
 
-      var first = await isolate.invokeRpcNoUpgrade(
-          'ext.dart.io.getProcessById', {'id': all['data'][0]['id']});
+      final first = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][0]['id']});
       expect(first['name'], io.Platform.executable);
       expect(first['pid'], equals(setup['pids'][0]));
       expect(first['arguments'].contains('foobar'), isFalse);
       expect(first['startedAt'], greaterThan(0));
 
-      var second = await isolate.invokeRpcNoUpgrade(
-          'ext.dart.io.getProcessById', {'id': all['data'][1]['id']});
+      final second = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][1]['id']});
       expect(second['name'], io.Platform.executable);
       expect(second['pid'], equals(setup['pids'][1]));
       expect(second['arguments'].contains('foobar'), isTrue);
@@ -115,8 +117,9 @@
       expect(second['startedAt'], greaterThan(0));
       expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));
 
-      var third = await isolate.invokeRpcNoUpgrade(
-          'ext.dart.io.getProcessById', {'id': all['data'][2]['id']});
+      final third = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][2]['id']});
       expect(third['name'], dartJITBinary);
       expect(third['pid'], equals(setup['pids'][2]));
       expect(third['pid'] != first['pid'], isTrue);
@@ -124,9 +127,10 @@
       expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));
 
       await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {});
-      all = await isolate.invokeRpcNoUpgrade('ext.dart.io.getProcesses', {});
-      expect(all['type'], equals('_startedprocesses'));
-      expect(all['data'].length, equals(2));
+      all = await isolate
+          .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {});
+      expect(all['type'], equals('SpawnedProcessList'));
+      expect(all['processes'].length, equals(2));
     } finally {
       await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
     }
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index c16feab..bc2bb42 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -15,10 +15,8 @@
 [ $arch == arm ]
 process_service_test: Pass, Fail # Issue 24344
 
-# Test uses service API and relies on correct class names
 [ $builder_tag == obfuscated ]
-dominator_tree_vm_test: SkipByDesign
-dominator_tree_vm_with_double_field_test: SkipByDesign
+*: SkipByDesign # Responses full of obfuscated names
 
 # Tests with known analyzer issues
 [ $compiler == dart2analyzer ]
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index accf0d4..9e721f2 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -29,6 +29,15 @@
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
 
+[ $compiler == dartk ]
+bad_reload_test: RuntimeError # Issue 34025
+coverage_optimized_function_test: Pass, Slow
+evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
+evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
+evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
+get_source_report_test: RuntimeError # Should pass again when constant evaluation is relanded, see http://dartbug.com/36600
+pause_on_unhandled_async_exceptions2_test: Pass, Slow
+
 [ $compiler == dartkp ]
 add_breakpoint_rpc_kernel_test: SkipByDesign
 async_generator_breakpoint_test: SkipByDesign
@@ -201,19 +210,12 @@
 [ $arch != simarm && $arch != simarm64 && $compiler == dartk ]
 complex_reload_test: RuntimeError
 
-[ $compiler == dartkb && ($builder_tag == bytecode_interpreter || $builder_tag == bytecode_mixed) ]
-*: Skip # There are still timeouts in the interpreter and mixed modes which cause infra timeouts.
-
-[ $mode == debug && $system == windows ]
-debugger_location_second_test: Skip, Timeout
-debugger_location_test: Skip, Timeout
-
-[ $mode == debug && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $mode == debug ]
 isolate_lifecycle_test: Skip # Flaky.
 pause_idle_isolate_test: Skip # Flaky
 rewind_optimized_out_test: Pass, Slow
 
-[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $system == windows ]
 add_breakpoint_rpc_kernel_test: Skip # Timeout
 break_on_default_constructor_test: Skip # Issues 32137 and 32138.
 breakpoint_in_parts_class_test: Skip # Timeout
@@ -264,7 +266,7 @@
 step_through_switch_test: Skip # Times out. Issue 32137.
 step_through_switch_with_continue_test: Skip # Times out. Issue 32137.
 
-[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
 add_breakpoint_rpc_kernel_test: RuntimeError # Issue #34736
 async_generator_breakpoint_test: SkipByDesign # No incremental compiler available.
 bad_reload_test: Skip # Times out on sim architectures, also RuntimeError.
@@ -294,11 +296,6 @@
 simple_reload_test: RuntimeError, Timeout
 valid_source_locations_test: Skip # Issue 34736, too slow.
 
-[ $compiler == dartk || $compiler == dartkb ]
-bad_reload_test: RuntimeError # Issue 34025
-coverage_optimized_function_test: Pass, Slow
-evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
-evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
-evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
-get_source_report_test: RuntimeError # Should pass again when constant evaluation is relanded, see http://dartbug.com/36600
-pause_on_unhandled_async_exceptions2_test: Pass, Slow
+[ $mode == debug && $system == windows ]
+debugger_location_second_test: Skip, Timeout
+debugger_location_test: Skip, Timeout
diff --git a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart b/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
deleted file mode 100644
index 8996577..0000000
--- a/runtime/observatory/tests/service/tcp_socket_closing_service_test.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' as io;
-import 'package:observatory/service_io.dart';
-import 'package:test/test.dart';
-import 'test_helper.dart';
-
-/// Test that we correctly remove sockets that have been closed from the list
-/// of open sockets. We explicitly leave one socket open.
-
-Future setup() async {
-  var serverSocket = await io.ServerSocket.bind('127.0.0.1', 0);
-  serverSocket.listen((s) {
-    s.drain();
-    s.close();
-  });
-  var socket = await io.Socket.connect("127.0.0.1", serverSocket.port);
-  socket.write("foobar");
-  socket.write("foobar");
-
-  await socket.flush();
-  await socket.close();
-  await socket.drain();
-
-  var socket2 = await io.Socket.connect("127.0.0.1", serverSocket.port);
-  socket2.write("foobarfoobar");
-  await socket2.flush();
-  await socket2.close();
-  await socket2.drain();
-  await serverSocket.close();
-
-  var server = await io.RawDatagramSocket.bind('127.0.0.1', 0);
-  server.listen((io.RawSocketEvent event) {
-    if (event == io.RawSocketEvent.read) {
-      io.Datagram dg = server.receive();
-      dg.data.forEach((x) => true);
-      server.close();
-    }
-  });
-  var client = await io.RawDatagramSocket.bind('127.0.0.1', 0);
-  client.send(utf8.encoder.convert('foobar'),
-      new io.InternetAddress('127.0.0.1'), server.port);
-  client.close();
-
-  // The one socket to expect.
-  await io.ServerSocket.bind('127.0.0.1', 0);
-}
-
-var tests = <IsolateTest>[
-  // Initial.
-  (Isolate isolate) async {
-    var result =
-        await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
-    expect(result['type'], equals('_opensockets'));
-    // We expect only one socket to be open, the server socket create at the
-    // end of test.
-    expect(result['data'].length, equals(1));
-    var server = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][0]['id']});
-    expect(server['listening'], isTrue);
-    expect(server['lastRead'], equals(0));
-    expect(server['totalRead'], equals(0));
-    expect(server['lastWrite'], equals(0));
-    expect(server['totalWritten'], equals(0));
-    expect(server['writeCount'], equals(0));
-    expect(server['readCount'], equals(0));
-  },
-];
-
-main(args) async => runIsolateTests(args, tests, testeeBefore: setup);
diff --git a/runtime/observatory/tests/service/tcp_socket_service_test.dart b/runtime/observatory/tests/service/tcp_socket_service_test.dart
deleted file mode 100644
index 9e61a01..0000000
--- a/runtime/observatory/tests/service/tcp_socket_service_test.dart
+++ /dev/null
@@ -1,170 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' as io;
-import 'package:observatory/service_io.dart';
-import 'package:test/test.dart';
-import 'test_helper.dart';
-
-Future setupTCP() async {
-  // Note that we don't close after us, by design we leave the sockets opens
-  // to allow us to query them from the other isolate.
-  var serverSocket = await io.ServerSocket.bind('127.0.0.1', 0);
-  serverSocket.listen((s) {
-    utf8.decoder.bind(s).listen(print);
-    s.close();
-  });
-  var socket = await io.Socket.connect("127.0.0.1", serverSocket.port);
-  socket.write("foobar");
-  socket.write("foobar");
-  await socket.flush();
-
-  var socket2 = await io.Socket.connect("127.0.0.1", serverSocket.port);
-  socket2.write("foobarfoobar");
-  await socket2.flush();
-}
-
-var tcpTests = <IsolateTest>[
-  // Initial.
-  (Isolate isolate) async {
-    var result =
-        await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
-    expect(result['type'], equals('_opensockets'));
-    // We expect 3 sockets to be open (in this order):
-    //   The server socket accepting connections, on port X
-    //   The accepted connection on the client, on port Y
-    //   The client connection, on port X
-    if (result['data'].length != 5) {
-      print(result['data']);
-    }
-    expect(result['data'].length, equals(5));
-    // The first socket will have a name like listening:127.0.0.1:X
-    // The second will have a name like 127.0.0.1:Y
-    // The third will have a name like 127.0.0.1:X
-    expect(result['data'][0]['name'].startsWith('listening:127.0.0.1'), isTrue);
-    expect(result['data'][1]['name'].startsWith('127.0.0.1:'), isTrue);
-    expect(result['data'][2]['name'].startsWith('127.0.0.1:'), isTrue);
-
-    var listening = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][0]['id']});
-    expect(listening['id'], equals(result['data'][0]['id']));
-    expect(listening['listening'], isTrue);
-    expect(listening['socketType'], equals('TCP'));
-    expect(listening['port'], greaterThanOrEqualTo(1024));
-    expect(listening['lastRead'], greaterThan(0));
-
-    expect(listening['totalRead'], equals(2));
-    expect(listening['lastWrite'], equals(0));
-    expect(listening['totalWritten'], equals(0));
-    expect(listening['writeCount'], equals(0));
-    expect(listening['readCount'], equals(2));
-    expect(listening['remoteHost'], equals('NA'));
-    expect(listening['remotePort'], equals('NA'));
-
-    var client = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][1]['id']});
-    expect(client['id'], equals(result['data'][1]['id']));
-
-    var server = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][2]['id']});
-    expect(server['id'], equals(result['data'][2]['id']));
-
-    // We expect the client to be connected on the port and
-    // host of the listening socket.
-    expect(client['remotePort'], equals(listening['port']));
-    expect(client['remoteHost'], equals(listening['host']));
-    // We expect the third socket (accepted server) to be connected to the
-    // same port and host as the listening socket (the listening one).
-    expect(server['port'], equals(listening['port']));
-    expect(server['host'], equals(listening['host']));
-
-    expect(client['listening'], isFalse);
-    expect(server['listening'], isFalse);
-
-    expect(client['socketType'], equals('TCP'));
-    expect(server['socketType'], equals('TCP'));
-
-    // We are using no reserved ports.
-    expect(client['port'], greaterThanOrEqualTo(1024));
-    expect(server['port'], greaterThanOrEqualTo(1024));
-
-    // The client and server "mirror" each other in reads and writes, and the
-    // timestamps are in correct order.
-    expect(client['lastRead'], equals(0));
-    expect(server['lastRead'], greaterThan(0));
-    expect(client['totalRead'], equals(0));
-    expect(server['totalRead'], equals(12));
-    expect(client['readCount'], equals(0));
-    expect(server['readCount'], greaterThanOrEqualTo(1));
-
-    expect(client['lastWrite'], greaterThan(0));
-    expect(server['lastWrite'], equals(0));
-    expect(client['totalWritten'], equals(12));
-    expect(server['totalWritten'], equals(0));
-    expect(client['writeCount'], greaterThanOrEqualTo(2));
-    expect(server['writeCount'], equals(0));
-
-    // Order
-    // Stopwatch resolution on windows can make us have the same timestamp.
-    if (io.Platform.isWindows) {
-      expect(server['lastRead'], greaterThanOrEqualTo(client['lastWrite']));
-    } else {
-      expect(server['lastRead'], greaterThan(client['lastWrite']));
-    }
-
-    var secondClient = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][3]['id']});
-    expect(secondClient['id'], equals(result['data'][3]['id']));
-    var secondServer = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][4]['id']});
-    expect(secondServer['id'], equals(result['data'][4]['id']));
-
-    // We expect the client to be connected on the port and
-    // host of the listening socket.
-    expect(secondClient['remotePort'], equals(listening['port']));
-    expect(secondClient['remoteHost'], equals(listening['host']));
-    // We expect the third socket (accepted server) to be connected to the
-    // same port and host as the listening socket (the listening one).
-    expect(secondServer['port'], equals(listening['port']));
-    expect(secondServer['host'], equals(listening['host']));
-
-    expect(secondClient['listening'], isFalse);
-    expect(secondServer['listening'], isFalse);
-
-    expect(secondClient['socketType'], equals('TCP'));
-    expect(secondServer['socketType'], equals('TCP'));
-
-    // We are using no reserved ports.
-    expect(secondClient['port'], greaterThanOrEqualTo(1024));
-    expect(secondServer['port'], greaterThanOrEqualTo(1024));
-
-    // The client and server "mirror" each other in reads and writes, and the
-    // timestamps are in correct order.
-    expect(secondClient['lastRead'], equals(0));
-    expect(secondServer['lastRead'], greaterThan(0));
-    expect(secondClient['totalRead'], equals(0));
-    expect(secondServer['totalRead'], equals(12));
-    expect(secondClient['readCount'], equals(0));
-    expect(secondServer['readCount'], greaterThanOrEqualTo(1));
-
-    expect(secondClient['lastWrite'], greaterThan(0));
-    expect(secondServer['lastWrite'], equals(0));
-    expect(secondClient['totalWritten'], equals(12));
-    expect(secondServer['totalWritten'], equals(0));
-    expect(secondClient['writeCount'], greaterThanOrEqualTo(1));
-    expect(secondServer['writeCount'], equals(0));
-
-    // Order
-    // Stopwatch resolution on windows make us sometimes report the same value.
-    if (io.Platform.isWindows) {
-      expect(server['lastRead'], greaterThanOrEqualTo(client['lastWrite']));
-    } else {
-      expect(server['lastRead'], greaterThan(client['lastWrite']));
-    }
-  },
-];
-
-main(args) async => runIsolateTests(args, tcpTests, testeeBefore: setupTCP);
diff --git a/runtime/observatory/tests/service/udp_socket_service_test.dart b/runtime/observatory/tests/service/udp_socket_service_test.dart
deleted file mode 100644
index e49aa97..0000000
--- a/runtime/observatory/tests/service/udp_socket_service_test.dart
+++ /dev/null
@@ -1,93 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' as io;
-import 'package:observatory/service_io.dart';
-import 'package:test/test.dart';
-import 'test_helper.dart';
-
-Future setupUDP() async {
-  // Service might attach to us after we completed the setup but
-  // before we actually received a datagram - if it will start inspecting
-  // IO metrics at that point then it will see that no reads happened
-  // and the test will fail. That is why we don't consider setup complete
-  // until after we received the datagram.
-  final doneCompleter = Completer<void>();
-
-  var server = await io.RawDatagramSocket.bind('127.0.0.1', 0);
-  server.listen((io.RawSocketEvent event) {
-    if (event == io.RawSocketEvent.read) {
-      io.Datagram dg = server.receive();
-      dg.data.forEach((x) => true);
-      if (!doneCompleter.isCompleted) {
-        doneCompleter.complete(null);
-      }
-    }
-  });
-  var client = await io.RawDatagramSocket.bind('127.0.0.1', 0);
-  client.send(utf8.encoder.convert('foobar'),
-      new io.InternetAddress('127.0.0.1'), server.port);
-
-  // Wait for datagram to arrive.
-  await doneCompleter.future;
-}
-
-var udpTests = <IsolateTest>[
-  // Initial.
-  (Isolate isolate) async {
-    var result =
-        await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenSockets', {});
-    expect(result['type'], equals('_opensockets'));
-    // We expect 2 sockets to be open (in this order):
-    //   The server socket accepting connections, on port X
-    //   The client socket on port Y
-    expect(result['data'].length, equals(2));
-    // The first socket will have a name like listening:127.0.0.1:X
-    // The second will have a name like 127.0.0.1:Y
-    // The third will have a name like 127.0.0.1:X
-    expect(result['data'][0]['name'].startsWith('127.0.0.1'), isTrue);
-    expect(result['data'][1]['name'].startsWith('127.0.0.1:'), isTrue);
-
-    var server = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][0]['id']});
-    expect(server['id'], equals(result['data'][0]['id']));
-    expect(server['remotePort'], equals('NA'));
-    expect(server['remoteHost'], equals('NA'));
-    expect(server['listening'], isFalse);
-    expect(server['socketType'], equals('UDP'));
-    expect(server['port'], greaterThanOrEqualTo(1024));
-    final now = DateTime.now().millisecondsSinceEpoch;
-    expect(
-        server['lastRead'], closeTo(now, Duration(seconds: 10).inMilliseconds));
-    expect(server['totalRead'], equals(6));
-    expect(server['lastWrite'], equals(0));
-    expect(server['totalWritten'], equals(0));
-    expect(server['writeCount'], equals(0));
-    expect(server['readCount'], greaterThanOrEqualTo(1));
-
-    var client = await isolate.invokeRpcNoUpgrade(
-        'ext.dart.io.getSocketByID', {'id': result['data'][1]['id']});
-    expect(client['id'], equals(result['data'][1]['id']));
-    expect(client['remotePort'], equals('NA'));
-    expect(client['remoteHost'], equals('NA'));
-    expect(client['listening'], isFalse);
-    expect(client['socketType'], equals('UDP'));
-    expect(client['port'], greaterThanOrEqualTo(1024));
-    expect(client['lastRead'], equals(0));
-    expect(client['totalRead'], equals(0));
-    // Stopwatch resolution on windows makes us sometimes report 0;
-    if (io.Platform.isWindows) {
-      expect(client['lastWrite'], greaterThanOrEqualTo(0));
-    } else {
-      expect(client['lastWrite'], greaterThan(0));
-    }
-    expect(client['totalWritten'], equals(6));
-    expect(client['writeCount'], greaterThanOrEqualTo(1));
-    expect(client['readCount'], equals(0));
-  },
-];
-
-main(args) async => runIsolateTests(args, udpTests, testeeBefore: setupUDP);
diff --git a/runtime/observatory_2/.gitignore b/runtime/observatory_2/.gitignore
new file mode 100644
index 0000000..c73eaff
--- /dev/null
+++ b/runtime/observatory_2/.gitignore
@@ -0,0 +1,5 @@
+bootstrap_css
+out
+build
+.pub
+.idea
diff --git a/runtime/observatory_2/BUILD.gn b/runtime/observatory_2/BUILD.gn
new file mode 100644
index 0000000..1762e1a
--- /dev/null
+++ b/runtime/observatory_2/BUILD.gn
@@ -0,0 +1,272 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("../../build/dart/copy_tree.gni")
+import("../../build/dart/dart_action.gni")
+import("observatory_sources.gni")
+
+prebuilt_dart2js_action("build_observatory") {
+  visibility = [ ":copy_main_dart_js" ]
+
+  script = "web/main.dart"
+
+  # dart2js produces a .deps file, but it is not in a format that is understood
+  # by ninja, so we explicitly list all the sources here.
+  inputs = [ "../../.packages" ] + observatory_sources
+
+  output = "$target_gen_dir/observatory/web/main.dart.js"
+  outputs = [ output ]
+  if (is_debug) {
+    outputs += [ "$target_gen_dir/observatory/web/main.dart.js.map" ]
+  }
+
+  version_string = exec_script("../../tools/make_version.py",
+                               [
+                                 "--quiet",
+                                 "--no_git_hash",
+                               ],  # Arguments to the script
+                               "trim string",  # Input conversions
+                               [
+                                 "../../tools/VERSION",
+                                 "../tools/utils.py",
+                               ])  # Dependencies
+
+  args = [
+    "-DOBS_VER=${version_string}",
+    "-o",
+    rebase_path(output),
+    "--packages=" + rebase_path("../../.packages"),
+  ]
+  if (is_debug) {
+    args += [ "--enable-asserts" ]
+  } else {
+    args += [ "--minify" ]
+  }
+}
+
+# The rules here down to "deploy_observatory" copy files into place such that
+# they can be packaged into a tar file. These rules do the following copies:
+#
+# web/* ->
+#     $target_out_dir/observatory/deployed/web
+# $target_gen_dir/observatory/web/main.dart.js ->
+#     $target_out_dir/observatory/deployed/web/main.dart.js
+# ../../third_party/observatory_pub_packages/packages/$PACKAGE/lib/* ->
+#     $target_out_dir/observatory/deployed/web/packages/$PACKAGE
+# lib/* ->
+#     $target_out_dir/observatory/deployed/web/packages/observatory
+#
+# Files matching "observatory_ignore_patterns" are excluded.
+
+# Files matching these patterns are filtered out of the Observatory assets.
+observatory_ignore_patterns = [
+  # "\$sdk", this is the first element concatenated into the string below.
+  "*.concat.js",
+  "*.dart",
+  "*.log",
+  "*.precompiled.js",
+  "*.scriptUrls",
+  "*_buildLogs*",
+  "*~",
+  "CustomElements.*",
+  "HTMLImports.*",
+  "MutationObserver.*",
+  "ShadowDOM.*",
+  "bower.json",
+  "dart_support.*",
+  "interop_support.*",
+  "package.json",
+  "unittest*",
+]
+
+if (!is_debug) {
+  observatory_ignore_patterns += [ "*.map" ]
+}
+
+# The ignore_patterns entry in the scopes accepted by copy_trees() is a
+# string of comma delimited patterns.
+observatory_ignore_string = "\$sdk"
+foreach(pattern, observatory_ignore_patterns) {
+  observatory_ignore_string = "$observatory_ignore_string,$pattern"
+}
+
+copy_tree_specs = []
+
+copy_tree_specs += [
+  {
+    target = "copy_web_package"
+    visibility = [ ":deploy_observatory" ]
+    source = "web"
+    dest = "$target_out_dir/observatory/deployed/web"
+    ignore_patterns = observatory_ignore_string
+  },
+]
+
+copy_tree_specs += [
+  {
+    target = "copy_observatory_package"
+    visibility = [ ":deploy_observatory" ]
+    source = "lib"
+    dest = "$target_out_dir/observatory/deployed/web/packages/observatory"
+    ignore_patterns = observatory_ignore_string
+  },
+]
+
+# This is not a rule, rather, it generates rules with names of the form:
+#   "copy_$package_package" for the packages in observatory_pub_packages.
+copy_trees("copy_observatory_packages") {
+  sources = copy_tree_specs
+}
+
+copy("copy_main_dart_js") {
+  visibility = [ ":deploy_observatory" ]
+  deps = [ ":build_observatory" ]
+  sources = [ "$target_gen_dir/observatory/web/main.dart.js" ]
+  if (is_debug) {
+    sources += [ "$target_gen_dir/observatory/web/main.dart.js.map" ]
+  }
+  outputs = [ "$target_out_dir/observatory/deployed/web/{{source_file_part}}" ]
+}
+
+group("deploy_observatory") {
+  deps = [
+    ":copy_main_dart_js",
+    ":copy_observatory_package",
+    ":copy_web_package",
+  ]
+}
+
+template("observatory_archive") {
+  enable_compression = false
+  if (defined(invoker.compress) && invoker.compress) {
+    enable_compression = true
+  }
+  action(target_name) {
+    deps = [ ":deploy_observatory" ]
+
+    output_name = target_name
+
+    output = "$target_gen_dir/${output_name}.tar"
+    outputs = [ output ]
+
+    script = "../tools/create_archive.py"
+    args = [
+      "--tar_output",
+      rebase_path(output),
+      "--client_root",
+      rebase_path("$target_out_dir/observatory/deployed/web/"),
+    ]
+    if (enable_compression) {
+      args += [ "--compress" ]
+    }
+  }
+}
+
+observatory_archive("compressed_observatory_archive") {
+  compress = true
+}
+
+copy("copy_compressed_observatory_archive") {
+  archive_target = ":compressed_observatory_archive"
+  deps = [ archive_target ]
+  archive_dir = get_label_info(archive_target, "target_gen_dir")
+  archive_name = get_label_info(archive_target, "name")
+  archive_file = "${archive_dir}/${archive_name}.tar"
+  sources = [ archive_file ]
+  outputs = [ "$root_out_dir/${archive_name}.tar" ]
+}
+
+observatory_archive("observatory_archive") {
+  compress = false
+}
+
+copy("copy_observatory_archive") {
+  archive_target = ":observatory_archive"
+  deps = [ archive_target ]
+  archive_dir = get_label_info(archive_target, "target_gen_dir")
+  archive_name = get_label_info(archive_target, "name")
+  archive_file = "${archive_dir}/${archive_name}.tar"
+  sources = [ archive_file ]
+  outputs = [ "$root_out_dir/${archive_name}.tar" ]
+}
+
+# Generates a .cc file containing the bytes of the observatory archive in a C
+# array.
+#
+# Parameters:
+#  inner_namespace (required):
+#    The inner C++ namespace that the C array lives in.
+#
+#  outer_namespace (required):
+#    The outer C++ namespace that the C array lives in.
+#
+#  archive_file (required):
+#    The path to the observatory archive.
+#
+template("observatory_archive_source") {
+  assert(defined(invoker.inner_namespace),
+         "Need inner_namespace in $target_name")
+  assert(defined(invoker.outer_namespace),
+         "Need outer_namespace in $target_name")
+  assert(defined(invoker.archive_file), "Need archive_file in $target_name")
+
+  action(target_name) {
+    forward_variables_from(invoker, [ "deps" ])
+
+    inputs = [ invoker.archive_file ]
+
+    output = "$target_gen_dir/${target_name}.cc"
+    outputs = [ output ]
+
+    script = "../tools/create_archive.py"
+    args = [
+      "--tar_input",
+      rebase_path(invoker.archive_file),
+      "--output",
+      rebase_path(output),
+      "--outer_namespace",
+      invoker.outer_namespace,
+      "--inner_namespace",
+      invoker.inner_namespace,
+      "--name",
+      "observatory_assets_archive",
+    ]
+  }
+}
+
+observatory_archive_source("embedded_archive_observatory") {
+  outer_namespace = "dart"
+  inner_namespace = "observatory"
+
+  # TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
+  archive_target = ":observatory_archive"
+  deps = [ archive_target ]
+  archive_dir = get_label_info(archive_target, "target_gen_dir")
+  archive_name = get_label_info(archive_target, "name")
+  archive_file = "${archive_dir}/${archive_name}.tar"
+}
+
+source_set("embedded_observatory_archive") {
+  deps = [ ":embedded_archive_observatory" ]
+
+  sources = [ rebase_path("$target_gen_dir/embedded_archive_observatory.cc") ]
+}
+
+observatory_archive_source("standalone_archive_observatory") {
+  outer_namespace = "dart"
+  inner_namespace = "bin"
+
+  # TODO(zra): In a Fuchsia build, use a prebuilt Observatory archive.
+  archive_target = ":compressed_observatory_archive"
+  deps = [ archive_target ]
+  archive_dir = get_label_info(archive_target, "target_gen_dir")
+  archive_name = get_label_info(archive_target, "name")
+  archive_file = "${archive_dir}/${archive_name}.tar"
+}
+
+source_set("standalone_observatory_archive") {
+  deps = [ ":standalone_archive_observatory" ]
+
+  sources = [ rebase_path("$target_gen_dir/standalone_archive_observatory.cc") ]
+}
diff --git a/runtime/observatory_2/HACKING.md b/runtime/observatory_2/HACKING.md
new file mode 100644
index 0000000..b645f9e
--- /dev/null
+++ b/runtime/observatory_2/HACKING.md
@@ -0,0 +1,174 @@
+# Hacking Observatory
+
+These instructions will guide you through the Observatory development and
+testing workflow.
+
+## SDK Setup & Build
+Getting ready to start.
+
+Before you start to hack on Observatory, follow the [instructions][build_sdk] to
+have a working environment in which you are able to build and test the Dart SDK.
+
+## Run existing tests
+Before hacking Observatory let's run the existing Observatory tests.
+We suggest to run all the test in __debug__ mode.
+
+First build the sdk in debug mode
+```
+$ ./tools/build.py --mode debug create_sdk
+```
+
+From the root of the sdk repository run:
+```
+$ ./tools/test.py -mdebug service
+```
+
+## Serve Observatory
+Observatory is built as part of building the sdk. Previously, it was recommended
+to run the Observatory using `pub serve` to avoid having to rebuild the sdk for
+each change to Observatory. However, `pub serve` was deprecated as part of the
+transition to Dart 2.0.
+
+[Issue #35678](https://github.com/dart-lang/sdk/issues/35678)
+tracks changes required to allow for `package:build_runner` to run Observatory
+without having to rebuild the sdk after each change.
+
+## Connect to a VM
+Start a Dart VM with the ``--observe`` flag (as explained in the
+[get started guide][observatory_get_started]) and connect your Observatory
+instance to that VM.
+
+Example script (file name ```clock.dart```):
+```dart
+import 'dart:async' show Timer, Duration;
+
+main() {
+  bool tick = true;
+  new Timer.periodic(const Duration(seconds: 1), (Timer t) {
+    print(tick ? 'tick' : 'tock');
+    tick = !tick;
+  });
+}
+```
+Start the script:
+```
+$ dart --disable-service-origin-check --observe clock.dart
+```
+
+## Code Reviews
+The development workflow of Dart (and Observatory) is based on code reviews.
+
+Follow the code review [instructions][code_review] to be able to successfully
+submit your code.
+
+The main reviewers for Observatory related CLs are:
+  - asiva
+  - bkonyi
+  - rmacnak
+
+## Write a new service test
+All the service tests are located in the ```tests/service``` folder.
+Test file names follow the convention ```<description>_test.dart```
+(e.g. ```a_brief_description_test.dart```).
+
+The test is generally structured in the following way.
+```dart
+import 'package:test/test.dart';
+
+main() {
+  // Some code that you need to test.
+  var a = 1 + 2;
+
+  // Some assertions to check the results.
+  expect(a, equal(3));
+}
+```
+See the official [test library][test_library] instructions;
+
+The ```test_helper.dart``` file expose some functions that allow to run a part
+of the code into another __VM__.
+
+To test synchronous operations:
+```dart
+import 'test_helper.dart';
+
+code() {
+  // Write the code you want to be execute into another VM.
+}
+
+var tests = [
+  // A series of tests that you want to run against the above code.
+  (Isolate isolate) async {
+    await isolate.reload();
+    // Use the isolate to communicate to the VM.
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args,
+                                        tests,
+                                        testeeConcurrent: code);
+```
+
+In order to test asynchronous operations:
+```dart
+import 'test_helper.dart';
+
+code() async {
+  // Write the asynchronous code you want to be execute into another VM.
+}
+
+var tests = [
+  // A series of tests that you want to run against the above code.
+  (Isolate isolate) async {
+    await isolate.reload();
+    // Use the isolate to communicate to the VM.
+  }
+];
+
+main(args) async => runIsolateTests(args,
+                                    tests,
+                                    testeeConcurrent: code);
+```
+
+Both ```runIsolateTests``` and ```runIsolateTestsSynchronous``` have the
+following named parameters:
+ - __testeeBefore__ (void()) a function that is going to be executed before
+the test
+ - __testeeConcurrent__ (void()) test that is going to be executed
+ - __pause_on_start__ (bool, default: false) pause the Isolate before the first
+instruction
+ - __pause_on_exit__ (bool, default: false) pause the Isolate after the last
+instruction
+ - __pause_on_unhandled_exceptions__ (bool, default: false) pause the Isolate at
+an unhandled exception
+ - __trace_service__ (bool, default: false) trace VM service requests
+ - __trace_compiler__ (bool, default: false) trace compiler operations
+ - __verbose_vm__ (bool, default: false) verbose logging
+
+
+Some common and reusable test are available from ```service_test_common.dart```:
+ - hasPausedFor
+   - hasStoppedAtBreakpoint
+   - hasStoppedWithUnhandledException
+   - hasStoppedAtExit
+   - hasPausedAtStartcode_review
+and utility functions:
+ - subscribeToStream
+ - cancelStreamSubscription
+ - asyncStepOver
+ - setBreakpointAtLine
+ - resumeIsolate
+ - resumeAndAwaitEvent
+ - resumeIsolateAndAwaitEvent
+ - stepOver
+ - getClassFromRootLib
+ - rootLibraryFieldValue
+
+## Run your tests
+See: __Run existing tests__
+
+[build_sdk]: https://github.com/dart-lang/sdk/wiki/Building "Building the Dart SDK"
+[open_observatory]: http://localhost:8080/ "Open Observatory"
+[observatory_get_started]: https://dart-lang.github.io/observatory/get-started.html "Observatory get started"
+[code_review]: https://github.com/dart-lang/sdk/wiki/Code-review-workflow-with-GitHub-and-reitveld "Code Review"
+[test_library]: https://pub.dartlang.org/packages/test "Test Library"
diff --git a/runtime/observatory_2/analysis_options.yaml b/runtime/observatory_2/analysis_options.yaml
new file mode 100644
index 0000000..6babf28
--- /dev/null
+++ b/runtime/observatory_2/analysis_options.yaml
@@ -0,0 +1,17 @@
+analyzer:
+  errors:
+    dead_code: ignore
+    unused_local_variable: ignore
+  exclude:
+    - tests/service/bad_reload/v2/main.dart
+    - tests/service/complex_reload/v2/main.dart
+    - tests/service/developer_extension_test.dart
+    - tests/service/evaluate_activation_in_method_class_test.dart
+    - tests/service/get_isolate_after_language_error_test.dart
+    - tests/service/get_user_level_retaining_path_rpc_test.dart
+    - tests/service/pause_on_unhandled_async_exceptions_test.dart
+
+linter:
+  rules:
+    - prefer_final_fields
+    - prefer_final_locals
diff --git a/runtime/observatory_2/bin/heap_snapshot.dart b/runtime/observatory_2/bin/heap_snapshot.dart
new file mode 100644
index 0000000..495c778
--- /dev/null
+++ b/runtime/observatory_2/bin/heap_snapshot.dart
@@ -0,0 +1,421 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// A way to test heap snapshot loading and analysis outside of Observatory, and
+// to handle snapshots that require more memory to analyze than is available in
+// a web browser.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:observatory_2/object_graph.dart';
+
+Future<SnapshotGraph> load(String uri) async {
+  final ws = await WebSocket.connect(uri,
+      compression: CompressionOptions.compressionOff);
+
+  final getVM = new Completer<String>();
+  final reader = new SnapshotReader();
+
+  reader.onProgress.listen(print);
+
+  ws.listen((dynamic response) {
+    if (response is String) {
+      response = json.decode(response);
+      if (response['id'] == 1) {
+        getVM.complete(response['result']['isolates'][0]['id']);
+      }
+    } else if (response is List<int>) {
+      response = new Uint8List.fromList(response);
+      final dataOffset =
+          new ByteData.view(response.buffer).getUint32(0, Endian.little);
+      dynamic metadata = new Uint8List.view(response.buffer, 4, dataOffset - 4);
+      final data = new Uint8List.view(
+          response.buffer, dataOffset, response.length - dataOffset);
+      metadata = utf8.decode(metadata);
+      metadata = json.decode(metadata);
+      var event = metadata['params']['event'];
+      if (event['kind'] == 'HeapSnapshot') {
+        bool last = event['last'] == true;
+        reader.add(data);
+        if (last) {
+          reader.close();
+          ws.close();
+        }
+      }
+    }
+  });
+
+  ws.add(json.encode({
+    'jsonrpc': '2.0',
+    'method': 'getVM',
+    'params': {},
+    'id': 1,
+  }));
+
+  final String isolateId = await getVM.future;
+
+  ws.add(json.encode({
+    'jsonrpc': '2.0',
+    'method': 'streamListen',
+    'params': {'streamId': 'HeapSnapshot'},
+    'id': 2,
+  }));
+  ws.add(json.encode({
+    'jsonrpc': '2.0',
+    'method': 'requestHeapSnapshot',
+    'params': {'isolateId': isolateId},
+    'id': 3,
+  }));
+
+  return reader.done;
+}
+
+String makeData(dynamic root) {
+  // 'root' can be arbitrarily deep, so we can't directly represent it as a
+  // JSON tree, which cause a stack overflow here encoding it and in the JS
+  // engine decoding it. Instead we flatten the tree into a list of tuples with
+  // a parent pointer and re-inflate it in JS.
+  final indices = <dynamic, int>{};
+  final preorder = <dynamic>[];
+  preorder.add(root);
+
+  for (var index = 0; index < preorder.length; index++) {
+    final object = preorder[index];
+    preorder.addAll(object.children);
+  }
+
+  final flattened = <dynamic>[];
+  for (var index = 0; index < preorder.length; index++) {
+    final object = preorder[index];
+    indices[object] = index;
+
+    flattened.add(object.description);
+    flattened.add(object.klass.name);
+    flattened.add(object.retainedSize);
+    if (index == 0) {
+      flattened.add(null);
+    } else {
+      flattened.add(indices[object.parent] as int);
+    }
+  }
+
+  return json.encode(flattened);
+}
+
+var css = '''
+.treemapTile {
+    position: absolute;
+    box-sizing: border-box;
+    border: solid 1px;
+    font-size: 10;
+    text-align: center;
+    overflow: hidden;
+    white-space: nowrap;
+    cursor: default;
+}
+''';
+
+var js = '''
+function hash(string) {
+  // Jenkin's one_at_a_time.
+  let h = string.length;
+  for (let i = 0; i < string.length; i++) {
+    h += string.charCodeAt(i);
+    h += h << 10;
+    h ^= h >> 6;
+  }
+  h += h << 3;
+  h ^= h >> 11;
+  h += h << 15;
+  return h;
+}
+
+function color(string) {
+  let hue = hash(string) % 360;
+  return "hsl(" + hue + ",60%,60%)";
+}
+
+function prettySize(size) {
+  if (size < 1024) return size + "B";
+  size /= 1024;
+  if (size < 1024) return size.toFixed(1) + "KiB";
+  size /= 1024;
+  if (size < 1024) return size.toFixed(1) + "MiB";
+  size /= 1024;
+  return size.toFixed(1) + "GiB";
+}
+
+function prettyPercent(fraction) {
+  return (fraction * 100).toFixed(1);
+}
+
+function createTreemapTile(v, width, height, depth) {
+  let div = document.createElement("div");
+  div.className = "treemapTile";
+  div.style["background-color"] = color(v.type);
+  div.ondblclick = function(event) {
+    event.stopPropagation();
+    if (depth == 0) {
+      let dom = v.parent;
+      if (dom == undefined) {
+        // Already at root.
+      } else {
+        showDominatorTree(dom);  // Zoom out.
+      }
+    } else {
+      showDominatorTree(v);  // Zoom in.
+    }
+  };
+
+  let left = 0;
+  let top = 0;
+
+  const kPadding = 5;
+  const kBorder = 1;
+  left += kPadding - kBorder;
+  top += kPadding - kBorder;
+  width -= 2 * kPadding;
+  height -= 2 * kPadding;
+
+  let label = v.name + " [" + prettySize(v.size) + "]";
+  div.title = label;
+
+  if (width < 10 || height < 10) {
+    // Too small: don't render label or children.
+    return div;
+  }
+
+  div.appendChild(document.createTextNode(label));
+  const kLabelHeight = 9;
+  top += kLabelHeight;
+  height -= kLabelHeight;
+
+  if (depth > 2) {
+    // Too deep: don't render children.
+    return div;
+  }
+  if (width < 4 || height < 4) {
+    // Too small: don't render children.
+    return div;
+  }
+
+  let children = new Array();
+  v.children.forEach(function(c) {
+    // Size 0 children seem to confuse the layout algorithm (accumulating
+    // rounding errors?).
+    if (c.size > 0) {
+      children.push(c);
+    }
+  });
+  children.sort(function (a, b) {
+    return b.size - a.size;
+  });
+
+  const scale = width * height / v.size;
+
+  // Bruls M., Huizing K., van Wijk J.J. (2000) Squarified Treemaps. In: de
+  // Leeuw W.C., van Liere R. (eds) Data Visualization 2000. Eurographics.
+  // Springer, Vienna.
+  for (let rowStart = 0;  // Index of first child in the next row.
+       rowStart < children.length;) {
+    // Prefer wider rectangles, the better to fit text labels.
+    const GOLDEN_RATIO = 1.61803398875;
+    let verticalSplit = (width / height) > GOLDEN_RATIO;
+
+    let space;
+    if (verticalSplit) {
+      space = height;
+    } else {
+      space = width;
+    }
+
+    let rowMin = children[rowStart].size * scale;
+    let rowMax = rowMin;
+    let rowSum = 0;
+    let lastRatio = 0;
+
+    let rowEnd;  // One after index of last child in the next row.
+    for (rowEnd = rowStart; rowEnd < children.length; rowEnd++) {
+      let size = children[rowEnd].size * scale;
+      if (size < rowMin) rowMin = size;
+      if (size > rowMax) rowMax = size;
+      rowSum += size;
+
+      let ratio = Math.max((space * space * rowMax) / (rowSum * rowSum),
+                           (rowSum * rowSum) / (space * space * rowMin));
+      if ((lastRatio != 0) && (ratio > lastRatio)) {
+        // Adding the next child makes the aspect ratios worse: remove it and
+        // add the row.
+        rowSum -= size;
+        break;
+      }
+      lastRatio = ratio;
+    }
+
+    let rowLeft = left;
+    let rowTop = top;
+    let rowSpace = rowSum / space;
+
+    for (let i = rowStart; i < rowEnd; i++) {
+      let child = children[i];
+      let size = child.size * scale;
+
+      let childWidth;
+      let childHeight;
+      if (verticalSplit) {
+        childWidth = rowSpace;
+        childHeight = size / childWidth;
+      } else {
+        childHeight = rowSpace;
+        childWidth = size / childHeight;
+      }
+
+      let childDiv = createTreemapTile(child, childWidth, childHeight, depth + 1);
+      childDiv.style.left = rowLeft + "px";
+      childDiv.style.top = rowTop + "px";
+      // Oversize the final div by kBorder to make the borders overlap.
+      childDiv.style.width = (childWidth + kBorder) + "px";
+      childDiv.style.height = (childHeight + kBorder) + "px";
+      div.appendChild(childDiv);
+
+      if (verticalSplit)
+        rowTop += childHeight;
+      else
+        rowLeft += childWidth;
+    }
+
+    if (verticalSplit) {
+      left += rowSpace;
+      width -= rowSpace;
+    } else {
+      top += rowSpace;
+      height -= rowSpace;
+    }
+
+    rowStart = rowEnd;
+  }
+
+  return div;
+}
+
+function setBody(div) {
+  let body = document.body;
+  while (body.firstChild) {
+    body.removeChild(body.firstChild);
+  }
+  body.appendChild(div);
+}
+
+function showDominatorTree(v) {
+  let header = document.createElement("div");
+  header.textContent = "Dominator Tree";
+  header.title =
+    "Double click a box to zoom in.\\n" +
+    "Double click the outermost box to zoom out.";
+  header.className = "headerRow";
+  header.style["flex-grow"] = 0;
+  header.style["padding"] = "5px";
+  header.style["border-bottom"] = "solid 1px";
+
+  let content = document.createElement("div");
+  content.style["flex-basis"] = 0;
+  content.style["flex-grow"] = 1;
+
+  let column = document.createElement("div");
+  column.style["width"] = "100%";
+  column.style["height"] = "100%";
+  column.style["border"] = "solid 2px";
+  column.style["display"] = "flex";
+  column.style["flex-direction"] = "column";
+  column.appendChild(header);
+  column.appendChild(content);
+
+  setBody(column);
+
+  // Add the content div to the document first so the browser will calculate
+  // the available width and height.
+  let w = content.offsetWidth;
+  let h = content.offsetHeight;
+
+  let topTile = createTreemapTile(v, w, h, 0);
+  topTile.style.width = w;
+  topTile.style.height = h;
+  topTile.style.border = "none";
+  content.appendChild(topTile);
+}
+
+function inflateData(flattened) {
+  // 'root' can be arbitrarily deep, so we need to use an explicit stack
+  // instead of the call stack.
+  let nodes = new Array();
+  let i = 0;
+  while (i < flattened.length) {
+    let node = {
+      "name": flattened[i++],
+      "type": flattened[i++],
+      "size": flattened[i++],
+      "children": [],
+      "parent": null
+    };
+    nodes.push(node);
+
+    let parentIndex = flattened[i++];
+    if (parentIndex != null) {
+      let parent = nodes[parentIndex];
+      parent.children.push(node);
+      node.parent = parent;
+    }
+  }
+
+  return nodes[0];
+}
+
+var root = __DATA__;
+root = inflateData(root);
+
+showDominatorTree(root);
+''';
+
+var html = '''
+<html>
+  <head>
+    <title>Dart Heap Snapshot</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <style>$css</style>
+  </head>
+  <body>
+    <script>$js</script>
+  </body>
+</html>
+''';
+
+main(List<String> args) async {
+  if (args.length < 1) {
+    print('Usage: heap_snapshot.dart <vm-service-uri>');
+    exitCode = 1;
+    return;
+  }
+
+  var uri = Uri.parse(args[0]);
+  if (uri.scheme == 'http') {
+    uri = uri.replace(scheme: 'ws');
+  } else if (uri.scheme == 'https') {
+    uri = uri.replace(scheme: 'wss');
+  }
+  if (!uri.path.endsWith('/ws')) {
+    uri = uri.resolve('ws');
+  }
+
+  final snapshot = await load(uri.toString());
+
+  final dir = await Directory.systemTemp.createTemp('heap-snapshot');
+  final path = dir.path + '/merged-dominator.html';
+  final file = await File(path).create();
+  final tree = makeData(snapshot.mergedRoot);
+  await file.writeAsString(html.replaceAll('__DATA__', tree));
+  print('Wrote file://' + path);
+}
diff --git a/runtime/observatory_2/bin/shell.dart b/runtime/observatory_2/bin/shell.dart
new file mode 100644
index 0000000..f17f11e
--- /dev/null
+++ b/runtime/observatory_2/bin/shell.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library shell;
+
+import 'package:observatory_2/service_io.dart';
+
+import 'dart:io';
+
+// Simple demo for service_io library. Connects to localhost on the default
+// port, picks the first isolate, reads requests from stdin, and prints
+// results to stdout. Example session:
+// <<< isolate isolates/1071334835
+// >>> /classes/40
+// <<< {"type":"Class","id":"classes\/40","name":"num","user_name":"num",...
+// >>> /objects/0
+// >>> {"type":"Array","class":{"type":"@Class","id":"classes\/62",...
+
+void repl(VM vm, Isolate isolate, String lastResult) {
+  print(lastResult);
+  Map params = {
+    'objectId': stdin.readLineSync(),
+  };
+  isolate.invokeRpcNoUpgrade('getObject', params).then((Map result) {
+    repl(vm, isolate, result.toString());
+  });
+}
+
+void main() {
+  String addr = 'ws://localhost:8181/ws';
+  new WebSocketVM(new WebSocketVMTarget(addr)).load().then((serviceObject) {
+    VM vm = serviceObject;
+    Isolate isolate = vm.isolates.first;
+    repl(vm, isolate, 'isolate ${isolate.id}');
+  });
+}
diff --git a/runtime/observatory_2/lib/allocation_profile.dart b/runtime/observatory_2/lib/allocation_profile.dart
new file mode 100644
index 0000000..70e8bae
--- /dev/null
+++ b/runtime/observatory_2/lib/allocation_profile.dart
@@ -0,0 +1,10 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library allocation_profiler;
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+
+part 'src/allocation_profile/allocation_profile.dart';
diff --git a/runtime/observatory_2/lib/app.dart b/runtime/observatory_2/lib/app.dart
new file mode 100644
index 0000000..86de2ed
--- /dev/null
+++ b/runtime/observatory_2/lib/app.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library app;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:html';
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/service_html.dart';
+import 'package:observatory_2/elements.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/event.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/repositories.dart';
+import 'package:observatory_2/tracer.dart';
+import 'package:observatory_2/utils.dart';
+import 'package:stack_trace/stack_trace.dart';
+import 'package:usage/usage_html.dart';
+
+export 'package:observatory_2/utils.dart';
+
+part 'src/app/application.dart';
+part 'src/app/location_manager.dart';
+part 'src/app/notification.dart';
+part 'src/app/page.dart';
+part 'src/app/settings.dart';
+part 'src/app/view_model.dart';
diff --git a/runtime/observatory_2/lib/cli.dart b/runtime/observatory_2/lib/cli.dart
new file mode 100644
index 0000000..607c58a
--- /dev/null
+++ b/runtime/observatory_2/lib/cli.dart
@@ -0,0 +1,9 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library cli;
+
+import 'dart:async';
+
+part 'src/cli/command.dart';
diff --git a/runtime/observatory_2/lib/debugger.dart b/runtime/observatory_2/lib/debugger.dart
new file mode 100644
index 0000000..c6a8d27
--- /dev/null
+++ b/runtime/observatory_2/lib/debugger.dart
@@ -0,0 +1,12 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library debugger;
+
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart';
+
+part 'src/debugger/debugger.dart';
+part 'src/debugger/debugger_location.dart';
diff --git a/runtime/observatory_2/lib/elements.dart b/runtime/observatory_2/lib/elements.dart
new file mode 100644
index 0000000..b4f60b7
--- /dev/null
+++ b/runtime/observatory_2/lib/elements.dart
@@ -0,0 +1,99 @@
+library observatory_elements;
+
+export 'package:observatory_2/src/elements/allocation_profile.dart';
+export 'package:observatory_2/src/elements/class_allocation_profile.dart';
+export 'package:observatory_2/src/elements/class_instances.dart';
+export 'package:observatory_2/src/elements/class_ref.dart';
+export 'package:observatory_2/src/elements/class_tree.dart';
+export 'package:observatory_2/src/elements/class_view.dart';
+export 'package:observatory_2/src/elements/code_ref.dart';
+export 'package:observatory_2/src/elements/code_view.dart';
+export 'package:observatory_2/src/elements/containers/search_bar.dart';
+export 'package:observatory_2/src/elements/containers/virtual_collection.dart';
+export 'package:observatory_2/src/elements/containers/virtual_tree.dart';
+export 'package:observatory_2/src/elements/context_ref.dart';
+export 'package:observatory_2/src/elements/context_view.dart';
+export 'package:observatory_2/src/elements/cpu_profile.dart';
+export 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
+export 'package:observatory_2/src/elements/cpu_profile_table.dart';
+export 'package:observatory_2/src/elements/curly_block.dart';
+export 'package:observatory_2/src/elements/debugger.dart';
+export 'package:observatory_2/src/elements/error_ref.dart';
+export 'package:observatory_2/src/elements/error_view.dart';
+export 'package:observatory_2/src/elements/eval_box.dart';
+export 'package:observatory_2/src/elements/field_ref.dart';
+export 'package:observatory_2/src/elements/field_view.dart';
+export 'package:observatory_2/src/elements/flag_list.dart';
+export 'package:observatory_2/src/elements/function_ref.dart';
+export 'package:observatory_2/src/elements/function_view.dart';
+export 'package:observatory_2/src/elements/general_error.dart';
+export 'package:observatory_2/src/elements/heap_map.dart';
+export 'package:observatory_2/src/elements/heap_snapshot.dart';
+export 'package:observatory_2/src/elements/process_snapshot.dart';
+export 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
+export 'package:observatory_2/src/elements/icdata_ref.dart';
+export 'package:observatory_2/src/elements/icdata_view.dart';
+export 'package:observatory_2/src/elements/instance_ref.dart';
+export 'package:observatory_2/src/elements/instance_view.dart';
+export 'package:observatory_2/src/elements/isolate/counter_chart.dart';
+export 'package:observatory_2/src/elements/isolate/location.dart';
+export 'package:observatory_2/src/elements/isolate/run_state.dart';
+export 'package:observatory_2/src/elements/isolate/shared_summary.dart';
+export 'package:observatory_2/src/elements/isolate/summary.dart';
+export 'package:observatory_2/src/elements/isolate_reconnect.dart';
+export 'package:observatory_2/src/elements/isolate_ref.dart';
+export 'package:observatory_2/src/elements/isolate_view.dart';
+export 'package:observatory_2/src/elements/json_view.dart';
+export 'package:observatory_2/src/elements/library_ref.dart';
+export 'package:observatory_2/src/elements/library_view.dart';
+export 'package:observatory_2/src/elements/local_var_descriptors_ref.dart';
+export 'package:observatory_2/src/elements/logging.dart';
+export 'package:observatory_2/src/elements/megamorphiccache_ref.dart';
+export 'package:observatory_2/src/elements/megamorphiccache_view.dart';
+export 'package:observatory_2/src/elements/metric/details.dart';
+export 'package:observatory_2/src/elements/metric/graph.dart';
+export 'package:observatory_2/src/elements/metrics.dart';
+export 'package:observatory_2/src/elements/native_memory_profiler.dart';
+export 'package:observatory_2/src/elements/nav/class_menu.dart';
+export 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+export 'package:observatory_2/src/elements/nav/library_menu.dart';
+export 'package:observatory_2/src/elements/nav/menu_item.dart';
+export 'package:observatory_2/src/elements/nav/notify.dart';
+export 'package:observatory_2/src/elements/nav/notify_event.dart';
+export 'package:observatory_2/src/elements/nav/notify_exception.dart';
+export 'package:observatory_2/src/elements/nav/refresh.dart';
+export 'package:observatory_2/src/elements/nav/top_menu.dart';
+export 'package:observatory_2/src/elements/nav/vm_menu.dart';
+export 'package:observatory_2/src/elements/object_common.dart';
+export 'package:observatory_2/src/elements/object_view.dart';
+export 'package:observatory_2/src/elements/objectpool_ref.dart';
+export 'package:observatory_2/src/elements/objectpool_view.dart';
+export 'package:observatory_2/src/elements/objectstore_view.dart';
+export 'package:observatory_2/src/elements/observatory_application.dart';
+export 'package:observatory_2/src/elements/pc_descriptors_ref.dart';
+export 'package:observatory_2/src/elements/persistent_handles.dart';
+export 'package:observatory_2/src/elements/ports.dart';
+export 'package:observatory_2/src/elements/sample_buffer_control.dart';
+export 'package:observatory_2/src/elements/script_inset.dart';
+export 'package:observatory_2/src/elements/script_ref.dart';
+export 'package:observatory_2/src/elements/script_view.dart';
+export 'package:observatory_2/src/elements/sentinel_value.dart';
+export 'package:observatory_2/src/elements/sentinel_view.dart';
+export 'package:observatory_2/src/elements/singletargetcache_ref.dart';
+export 'package:observatory_2/src/elements/singletargetcache_view.dart';
+export 'package:observatory_2/src/elements/source_inset.dart';
+export 'package:observatory_2/src/elements/source_link.dart';
+export 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
+export 'package:observatory_2/src/elements/strongly_reachable_instances.dart';
+export 'package:observatory_2/src/elements/subtypetestcache_ref.dart';
+export 'package:observatory_2/src/elements/subtypetestcache_view.dart';
+export 'package:observatory_2/src/elements/timeline/dashboard.dart';
+export 'package:observatory_2/src/elements/timeline_page.dart';
+export 'package:observatory_2/src/elements/type_arguments_ref.dart';
+export 'package:observatory_2/src/elements/unknown_ref.dart';
+export 'package:observatory_2/src/elements/unlinkedcall_ref.dart';
+export 'package:observatory_2/src/elements/unlinkedcall_view.dart';
+export 'package:observatory_2/src/elements/view_footer.dart';
+export 'package:observatory_2/src/elements/vm_connect.dart';
+export 'package:observatory_2/src/elements/vm_connect_target.dart';
+export 'package:observatory_2/src/elements/vm_view.dart';
diff --git a/runtime/observatory_2/lib/event.dart b/runtime/observatory_2/lib/event.dart
new file mode 100644
index 0000000..67d89db
--- /dev/null
+++ b/runtime/observatory_2/lib/event.dart
@@ -0,0 +1,380 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+
+class VMUpdateEvent implements M.VMUpdateEvent {
+  final DateTime timestamp;
+  final M.VMRef vm;
+  VMUpdateEvent(this.timestamp, this.vm) {
+    assert(timestamp != null);
+    assert(vm != null);
+  }
+}
+
+class IsolateStartEvent implements M.IsolateStartEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  IsolateStartEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class IsolateRunnableEvent implements M.IsolateRunnableEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  IsolateRunnableEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class IsolateExitEvent implements M.IsolateExitEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  IsolateExitEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class IsolateUpdateEvent implements M.IsolateUpdateEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  IsolateUpdateEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class IsolateReloadEvent implements M.IsolateReloadEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.ErrorRef error;
+  IsolateReloadEvent(this.timestamp, this.isolate, this.error) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(error != null);
+  }
+}
+
+class ServiceExtensionAddedEvent implements M.ServiceExtensionAddedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final String extensionRPC;
+  ServiceExtensionAddedEvent(this.timestamp, this.isolate, this.extensionRPC) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(extensionRPC != null);
+  }
+}
+
+class DebuggerSettingsUpdateEvent implements M.DebuggerSettingsUpdateEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  DebuggerSettingsUpdateEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class PauseStartEvent implements M.PauseStartEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  PauseStartEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class PauseExitEvent implements M.PauseExitEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  PauseExitEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class PauseBreakpointEvent implements M.PauseBreakpointEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final Iterable<M.Breakpoint> pauseBreakpoints;
+  final M.Frame topFrame;
+  final bool atAsyncSuspension;
+
+  /// [optional]
+  final M.Breakpoint breakpoint;
+  PauseBreakpointEvent(
+      this.timestamp,
+      this.isolate,
+      Iterable<M.Breakpoint> pauseBreakpoints,
+      this.topFrame,
+      this.atAsyncSuspension,
+      [this.breakpoint])
+      : pauseBreakpoints = new List.unmodifiable(pauseBreakpoints) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(pauseBreakpoints != null);
+    assert(topFrame != null);
+    assert(atAsyncSuspension != null);
+  }
+}
+
+class PauseInterruptedEvent implements M.PauseInterruptedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  final bool atAsyncSuspension;
+  PauseInterruptedEvent(
+      this.timestamp, this.isolate, this.topFrame, this.atAsyncSuspension) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(atAsyncSuspension != null);
+  }
+}
+
+class PausePostRequestEvent implements M.PausePostRequestEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  final bool atAsyncSuspension;
+  PausePostRequestEvent(
+      this.timestamp, this.isolate, this.topFrame, this.atAsyncSuspension) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(atAsyncSuspension != null);
+  }
+}
+
+class PauseExceptionEvent implements M.PauseExceptionEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  final M.InstanceRef exception;
+  PauseExceptionEvent(
+      this.timestamp, this.isolate, this.topFrame, this.exception) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(topFrame != null);
+    assert(exception != null);
+  }
+}
+
+class ResumeEvent implements M.ResumeEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Frame topFrame;
+  ResumeEvent(this.timestamp, this.isolate, this.topFrame) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class BreakpointAddedEvent implements M.BreakpointAddedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  BreakpointAddedEvent(this.timestamp, this.isolate, this.breakpoint) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(breakpoint != null);
+  }
+}
+
+class BreakpointResolvedEvent implements M.BreakpointResolvedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  BreakpointResolvedEvent(this.timestamp, this.isolate, this.breakpoint) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(breakpoint != null);
+  }
+}
+
+class BreakpointRemovedEvent implements M.BreakpointRemovedEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.Breakpoint breakpoint;
+  BreakpointRemovedEvent(this.timestamp, this.isolate, this.breakpoint) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(breakpoint != null);
+  }
+}
+
+class InspectEvent implements M.InspectEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final M.InstanceRef inspectee;
+  InspectEvent(this.timestamp, this.isolate, this.inspectee) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(inspectee != null);
+  }
+}
+
+class NoneEvent implements M.NoneEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  NoneEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class GCEvent implements M.GCEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  GCEvent(this.timestamp, this.isolate) {
+    assert(timestamp != null);
+    assert(isolate != null);
+  }
+}
+
+class LoggingEvent implements M.LoggingEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final Map logRecord;
+  LoggingEvent(this.timestamp, this.isolate, this.logRecord) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(logRecord != null);
+  }
+}
+
+class ExtensionEvent implements M.ExtensionEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final String extensionKind;
+  final M.ExtensionData extensionData;
+  ExtensionEvent(
+      this.timestamp, this.isolate, this.extensionKind, this.extensionData) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(extensionKind != null);
+    assert(extensionData != null);
+  }
+}
+
+class TimelineEventsEvent implements M.TimelineEventsEvent {
+  final DateTime timestamp;
+  final M.IsolateRef isolate;
+  final Iterable<M.TimelineEvent> timelineEvents;
+  TimelineEventsEvent(
+      this.timestamp, this.isolate, Iterable<M.TimelineEvent> timelineEvents)
+      : timelineEvents = new List.unmodifiable(timelineEvents) {
+    assert(timestamp != null);
+    assert(isolate != null);
+    assert(timelineEvents != null);
+  }
+}
+
+class ConnectionClosedEvent implements M.ConnectionClosedEvent {
+  final DateTime timestamp;
+  final String reason;
+  ConnectionClosedEvent(this.timestamp, this.reason) {
+    assert(timestamp != null);
+    assert(reason != null);
+  }
+}
+
+class ServiceRegisteredEvent implements M.ServiceRegisteredEvent {
+  final DateTime timestamp;
+  final String service;
+  final String method;
+  final String alias;
+  ServiceRegisteredEvent(
+      this.timestamp, this.service, this.method, this.alias) {
+    assert(timestamp != null);
+    assert(service != null);
+    assert(method != null);
+    assert(alias != null);
+  }
+}
+
+class ServiceUnregisteredEvent implements M.ServiceUnregisteredEvent {
+  final DateTime timestamp;
+  final String service;
+  final String method;
+  ServiceUnregisteredEvent(this.timestamp, this.service, this.method) {
+    assert(timestamp != null);
+    assert(service != null);
+    assert(method != null);
+  }
+}
+
+M.Event createEventFromServiceEvent(S.ServiceEvent event) {
+  switch (event.kind) {
+    case S.ServiceEvent.kVMUpdate:
+      return new VMUpdateEvent(event.timestamp, event.vm);
+    case S.ServiceEvent.kIsolateStart:
+      return new IsolateStartEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kIsolateRunnable:
+      return new IsolateRunnableEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kIsolateUpdate:
+      return new IsolateUpdateEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kIsolateReload:
+      return new IsolateReloadEvent(
+          event.timestamp, event.isolate, event.error);
+    case S.ServiceEvent.kIsolateExit:
+      return new IsolateExitEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kBreakpointAdded:
+      return new BreakpointAddedEvent(
+          event.timestamp, event.isolate, event.breakpoint);
+    case S.ServiceEvent.kBreakpointResolved:
+      return new BreakpointResolvedEvent(
+          event.timestamp, event.isolate, event.breakpoint);
+    case S.ServiceEvent.kBreakpointRemoved:
+      return new BreakpointRemovedEvent(
+          event.timestamp, event.isolate, event.breakpoint);
+    case S.ServiceEvent.kDebuggerSettingsUpdate:
+      return new DebuggerSettingsUpdateEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kResume:
+      return new ResumeEvent(event.timestamp, event.isolate, event.topFrame);
+    case S.ServiceEvent.kPauseStart:
+      return new PauseStartEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kPauseExit:
+      return new PauseExitEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kPausePostRequest:
+      return new PausePostRequestEvent(event.timestamp, event.isolate,
+          event.topFrame, event.atAsyncSuspension);
+    case S.ServiceEvent.kPauseBreakpoint:
+      return new PauseBreakpointEvent(
+          event.timestamp,
+          event.isolate,
+          event.pauseBreakpoints,
+          event.topFrame,
+          event.atAsyncSuspension,
+          event.breakpoint);
+    case S.Isolate.kLoggingStream:
+      return new LoggingEvent(event.timestamp, event.isolate, event.logRecord);
+    case S.ServiceEvent.kPauseInterrupted:
+      return new PauseInterruptedEvent(event.timestamp, event.isolate,
+          event.topFrame, event.atAsyncSuspension);
+    case S.ServiceEvent.kPauseException:
+      return new PauseExceptionEvent(
+          event.timestamp, event.isolate, event.topFrame, event.exception);
+    case S.ServiceEvent.kInspect:
+      return new InspectEvent(event.timestamp, event.isolate, event.inspectee);
+    case S.ServiceEvent.kGC:
+      return new GCEvent(event.timestamp, event.isolate);
+    case S.ServiceEvent.kServiceRegistered:
+      return new ServiceRegisteredEvent(
+          event.timestamp, event.service, event.method, event.alias);
+    case S.ServiceEvent.kServiceUnregistered:
+      return new ServiceUnregisteredEvent(
+          event.timestamp, event.service, event.method);
+    case S.ServiceEvent.kNone:
+      return new NoneEvent(event.timestamp, event.isolate);
+    default:
+      // Ignore unrecognized events.
+      Logger.root.severe('Unrecognized event: $event');
+      return null;
+  }
+}
diff --git a/runtime/observatory_2/lib/models.dart b/runtime/observatory_2/lib/models.dart
new file mode 100644
index 0000000..9ea69d9
--- /dev/null
+++ b/runtime/observatory_2/lib/models.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library models;
+
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:observatory_2/object_graph.dart';
+
+part 'src/models/exceptions.dart';
+
+part 'src/models/objects/allocation_profile.dart';
+part 'src/models/objects/breakpoint.dart';
+part 'src/models/objects/class.dart';
+part 'src/models/objects/code.dart';
+part 'src/models/objects/context.dart';
+part 'src/models/objects/error.dart';
+part 'src/models/objects/event.dart';
+part 'src/models/objects/extension_data.dart';
+part 'src/models/objects/field.dart';
+part 'src/models/objects/flag.dart';
+part 'src/models/objects/frame.dart';
+part 'src/models/objects/function.dart';
+part 'src/models/objects/guarded.dart';
+part 'src/models/objects/heap_space.dart';
+part 'src/models/objects/icdata.dart';
+part 'src/models/objects/inbound_references.dart';
+part 'src/models/objects/instance.dart';
+part 'src/models/objects/isolate.dart';
+part 'src/models/objects/isolate_group.dart';
+part 'src/models/objects/library.dart';
+part 'src/models/objects/local_var_descriptors.dart';
+part 'src/models/objects/map_association.dart';
+part 'src/models/objects/megamorphiccache.dart';
+part 'src/models/objects/metric.dart';
+part 'src/models/objects/notification.dart';
+part 'src/models/objects/object.dart';
+part 'src/models/objects/objectpool.dart';
+part 'src/models/objects/objectstore.dart';
+part 'src/models/objects/pc_descriptors.dart';
+part 'src/models/objects/persistent_handles.dart';
+part 'src/models/objects/ports.dart';
+part 'src/models/objects/retaining_path.dart';
+part 'src/models/objects/sample_profile.dart';
+part 'src/models/objects/script.dart';
+part 'src/models/objects/sentinel.dart';
+part 'src/models/objects/service.dart';
+part 'src/models/objects/single_target_cache.dart';
+part 'src/models/objects/source_location.dart';
+part 'src/models/objects/subtype_test_cache.dart';
+part 'src/models/objects/target.dart';
+part 'src/models/objects/thread.dart';
+part 'src/models/objects/timeline.dart';
+part 'src/models/objects/timeline_event.dart';
+part 'src/models/objects/type_arguments.dart';
+part 'src/models/objects/unknown.dart';
+part 'src/models/objects/unlinked_call.dart';
+part 'src/models/objects/vm.dart';
+part 'src/models/objects/zone.dart';
+
+part 'src/models/repositories/allocation_profile.dart';
+part 'src/models/repositories/breakpoint.dart';
+part 'src/models/repositories/class.dart';
+part 'src/models/repositories/context.dart';
+part 'src/models/repositories/editor.dart';
+part 'src/models/repositories/eval.dart';
+part 'src/models/repositories/event.dart';
+part 'src/models/repositories/field.dart';
+part 'src/models/repositories/flag.dart';
+part 'src/models/repositories/function.dart';
+part 'src/models/repositories/heap_snapshot.dart';
+part 'src/models/repositories/icdata.dart';
+part 'src/models/repositories/inbound_references.dart';
+part 'src/models/repositories/instance.dart';
+part 'src/models/repositories/isolate.dart';
+part 'src/models/repositories/isolate_group.dart';
+part 'src/models/repositories/library.dart';
+part 'src/models/repositories/megamorphiccache.dart';
+part 'src/models/repositories/metric.dart';
+part 'src/models/repositories/notification.dart';
+part 'src/models/repositories/object.dart';
+part 'src/models/repositories/objectpool.dart';
+part 'src/models/repositories/objectstore.dart';
+part 'src/models/repositories/persistent_handles.dart';
+part 'src/models/repositories/ports.dart';
+part 'src/models/repositories/reachable_size.dart';
+part 'src/models/repositories/retained_size.dart';
+part 'src/models/repositories/retaining_path.dart';
+part 'src/models/repositories/sample_profile.dart';
+part 'src/models/repositories/script.dart';
+part 'src/models/repositories/single_target_cache.dart';
+part 'src/models/repositories/strongly_reachable_instances.dart';
+part 'src/models/repositories/subtype_test_cache.dart';
+part 'src/models/repositories/target.dart';
+part 'src/models/repositories/timeline.dart';
+part 'src/models/repositories/type_arguments.dart';
+part 'src/models/repositories/unlinked_call.dart';
+part 'src/models/repositories/vm.dart';
diff --git a/runtime/observatory_2/lib/object_graph.dart b/runtime/observatory_2/lib/object_graph.dart
new file mode 100644
index 0000000..0e891ce
--- /dev/null
+++ b/runtime/observatory_2/lib/object_graph.dart
@@ -0,0 +1,1634 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library object_graph;
+
+import 'dart:async';
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:typed_data';
+
+/// Decodes and analyzes heap snapshots produced by the Dart VM.
+abstract class SnapshotReader {
+  factory SnapshotReader() => _SnapshotReader._new();
+
+  void add(Uint8List chunk);
+  Future<SnapshotGraph> close();
+
+  Future<SnapshotGraph> get done;
+  Stream<String> get onProgress;
+}
+
+class _SnapshotReader implements SnapshotReader {
+  bool _closed = false;
+  var _chunks = <Uint8List>[];
+  final _onProgress = new StreamController<String>.broadcast();
+  final _done = new Completer<SnapshotGraph>();
+
+  _SnapshotReader._new();
+
+  void add(Uint8List chunk) {
+    if (_closed) {
+      throw new StateError("Stream is closed");
+    }
+    _chunks.add(chunk);
+    _onProgress.add("Receiving snapshot chunk ${_chunks.length}...");
+
+    // TODO(rmacnak): Incremental loading.
+  }
+
+  Future<SnapshotGraph> close() {
+    if (_closed) {
+      throw new StateError("Stream is closed");
+    }
+    _closed = true;
+
+    var graph = new _SnapshotGraph._new();
+    var chunks = _chunks;
+    _chunks = null; // Let the binary chunks be GCable.
+    _done.complete(graph._load(chunks, _onProgress));
+    return _done.future;
+  }
+
+  Future<SnapshotGraph> get done => _done.future;
+  Stream<String> get onProgress => _onProgress.stream;
+}
+
+Uint8List _newUint8Array(int size) {
+  try {
+    return new Uint8List(size);
+  } on ArgumentError catch (e) {
+    // JS throws a misleading invalid argument error. Convert to a more user-friendly message.
+    throw new Exception(
+        "OutOfMemoryError: Not enough memory available to analyze the snapshot.");
+  }
+}
+
+Uint16List _newUint16Array(int size) {
+  try {
+    return new Uint16List(size);
+  } on ArgumentError catch (e) {
+    // JS throws a misleading invalid argument error. Convert to a more user-friendly message.
+    throw new Exception(
+        "OutOfMemoryError: Not enough memory available to analyze the snapshot.");
+  }
+}
+
+Uint32List _newUint32Array(int size) {
+  try {
+    return new Uint32List(size);
+  } on ArgumentError catch (e) {
+    // JS throws a misleading invalid argument error. Convert to a more user-friendly message.
+    throw new Exception(
+        "OutOfMemoryError: Not enough memory available to analyze the snapshot.");
+  }
+}
+
+class _ReadStream {
+  final List<Uint8List> _buffers;
+  Uint8List _currentBuffer = Uint8List(0);
+  int _bufferIndex = 0;
+  int _byteIndex = 0;
+
+  _ReadStream._new(this._buffers);
+
+  bool atEnd() {
+    return _bufferIndex >= _buffers.length &&
+        _byteIndex >= _currentBuffer.length;
+  }
+
+  int readByte() {
+    int i = _byteIndex;
+    Uint8List b = _currentBuffer;
+    if (i < b.length) {
+      int r = b[i];
+      _byteIndex = i + 1;
+      return r;
+    }
+
+    return _readByteSlowPath();
+  }
+
+  int _readByteSlowPath() {
+    int i = _byteIndex;
+    Uint8List b = _currentBuffer;
+    while (i >= b.length) {
+      if (_bufferIndex >= _buffers.length) {
+        throw new StateError("Attempt to read past the end of a stream");
+      }
+      b = _currentBuffer = _buffers[_bufferIndex++];
+      i = 0;
+    }
+    int r = b[i];
+    _byteIndex = i + 1;
+    return r;
+  }
+
+  /// Read one ULEB128 number.
+  int readUnsigned() {
+    int result = 0;
+    int shift = 0;
+    for (;;) {
+      int part = readByte();
+      result |= (part & 0x7F) << shift;
+      if ((part & 0x80) == 0) {
+        break;
+      }
+      shift += 7;
+    }
+    return result;
+  }
+
+  /// Read one SLEB128 number.
+  int readSigned() {
+    int result = 0;
+    int shift = 0;
+    for (;;) {
+      int part = readByte();
+      result |= (part & 0x7F) << shift;
+      shift += 7;
+      if ((part & 0x80) == 0) {
+        if ((part & 0x40) != 0) {
+          result |= (-1 << shift);
+        }
+        break;
+      }
+    }
+    return result;
+  }
+
+  double readFloat64() {
+    final bytes = _newUint8Array(8);
+    for (var i = 0; i < 8; i++) {
+      bytes[i] = readByte();
+    }
+    return new Float64List.view(bytes.buffer)[0];
+  }
+
+  String readUtf8() {
+    final len = readUnsigned();
+    final bytes = _newUint8Array(len);
+    for (var i = 0; i < len; i++) {
+      bytes[i] = readByte();
+    }
+    return new Utf8Codec(allowMalformed: true).decode(bytes);
+  }
+
+  String readLatin1() {
+    final len = readUnsigned();
+    final codeUnits = _newUint8Array(len);
+    for (var i = 0; i < len; i++) {
+      codeUnits[i] = readByte();
+    }
+    return new String.fromCharCodes(codeUnits);
+  }
+
+  String readUtf16() {
+    final len = readUnsigned();
+    final codeUnits = _newUint16Array(len);
+    for (var i = 0; i < len; i++) {
+      codeUnits[i] = readByte() | (readByte() << 8);
+    }
+    return new String.fromCharCodes(codeUnits);
+  }
+}
+
+// Node indices for the root and sentinel nodes. Note that using 0 as the
+// sentinel means a newly allocated typed array comes initialized with all
+// elements as the sentinel.
+const _ROOT = 1;
+const _SENTINEL = 0;
+
+/// An object in a heap snapshot.
+abstract class SnapshotObject {
+  // If this object has been obtained from [successors] or [predecessors], the
+  // name of slot. Otherwise, the empty string.
+  String get label;
+
+  // The value for primitives. Otherwise, the class name.
+  String get description;
+
+  /// [internalSize] + [externalSize].
+  int get shallowSize;
+
+  /// The number of bytes in the Dart heap occupied by this object. May be 0
+  /// for objects that are in another heap but referenced from the heap of
+  /// interest. May also be 0 for synthetic objects such as the root.
+  int get internalSize;
+
+  /// The sum of all external allocations associated with this object.
+  /// See Dart_NewFinalizableHandle and Dart_NewWeakPersistentHandle.
+  int get externalSize;
+
+  /// The [shallowSize] of this object, plus the retainedSize of all its
+  /// children in the dominator tree. This is the amount of memory that would
+  /// be freed if the last reference to this object was erased.
+  int get retainedSize;
+
+  SnapshotClass get klass;
+
+  /// The objects directly referenced by this object. The [SnapshotObject]s
+  /// returned by this iterable have their [label] set to name of the slot
+  /// if it is available.
+  Iterable<SnapshotObject> get successors;
+
+  /// The objects directly referencing this object. The [SnapshotObject]s
+  /// returned by this iterable have their [label] set to name of the slot
+  /// if it is available.
+  Iterable<SnapshotObject> get predecessors;
+
+  /// The immediate dominator of this object. For the root object, returns self.
+  ///
+  /// See https://en.wikipedia.org/wiki/Dominator_(graph_theory).
+  SnapshotObject get parent;
+
+  /// The objects for which this object is the immediate dominator.
+  ///
+  /// See https://en.wikipedia.org/wiki/Dominator_(graph_theory).
+  Iterable<SnapshotObject> get children;
+
+  /// An iterable containing only this object. For polymorphism with
+  /// SnapshotMergedDominators.
+  Iterable<SnapshotObject> get objects;
+}
+
+class _SnapshotObject implements SnapshotObject {
+  final int _id;
+  final _SnapshotGraph _graph;
+  final String label;
+
+  _SnapshotObject._new(this._id, this._graph, this.label);
+
+  bool operator ==(Object other) {
+    if (other is _SnapshotObject) {
+      return _id == other._id && _graph == other._graph;
+    }
+    return false;
+  }
+
+  int get hashCode => _id ^ _graph.hashCode;
+
+  int get shallowSize => internalSize + externalSize;
+  int get internalSize => _graph._internalSizes[_id];
+  int get externalSize => _graph._externalSizes[_id];
+  int get retainedSize => _graph._retainedSizes[_id];
+
+  String get description => _graph._describeObject(_id);
+  SnapshotClass get klass => _graph._classes[_graph._cids[_id]];
+
+  Iterable<SnapshotObject> get successors sync* {
+    final id = _id;
+    final cid = _graph._cids[id];
+    final startSuccIndex = _graph._firstSuccs[id];
+    final limitSuccIndex = _graph._firstSuccs[id + 1];
+    for (var nextSuccIndex = startSuccIndex;
+        nextSuccIndex < limitSuccIndex;
+        nextSuccIndex++) {
+      final index = nextSuccIndex - startSuccIndex;
+      final succId = _graph._succs[nextSuccIndex];
+      final name = _graph._edgeName(cid, index);
+      yield _SnapshotObject._new(succId, _graph, name);
+    }
+  }
+
+  Iterable<SnapshotObject> get predecessors sync* {
+    var firstSuccs = _graph._firstSuccs;
+    var succs = _graph._succs;
+    var id = _id;
+    var N = _graph._N;
+    for (var predId = 1; predId <= N; predId++) {
+      var base = firstSuccs[predId];
+      var limit = firstSuccs[predId + 1];
+      for (var i = base; i < limit; i++) {
+        if (succs[i] == id) {
+          var cid = _graph._cids[predId];
+          var name = _graph._edgeName(cid, i - base);
+          yield _SnapshotObject._new(predId, _graph, name);
+        }
+      }
+    }
+  }
+
+  SnapshotObject get parent {
+    if (_id == _ROOT) {
+      return this;
+    }
+    return _SnapshotObject._new(_graph._doms[_id], _graph, "");
+  }
+
+  Iterable<SnapshotObject> get children sync* {
+    var N = _graph._N;
+    var doms = _graph._doms;
+    var parentId = _id;
+    for (var childId = _ROOT; childId <= N; childId++) {
+      if (doms[childId] == parentId) {
+        yield _SnapshotObject._new(childId, _graph, "");
+      }
+    }
+  }
+
+  Iterable<SnapshotObject> get objects sync* {
+    yield this;
+  }
+}
+
+class _SyntheticSnapshotObject implements SnapshotObject {
+  String _description;
+  SnapshotClass _klass;
+  int _internalSize;
+  int _externalSize;
+  int _retainedSize;
+  List<SnapshotObject> _successors;
+  List<SnapshotObject> _predecessors;
+  SnapshotObject _parent;
+  List<SnapshotObject> _children;
+
+  String get label => null;
+  String get description => _description;
+  SnapshotClass get klass => _klass;
+
+  int get shallowSize => internalSize + externalSize;
+  int get internalSize => _internalSize;
+  int get externalSize => _externalSize;
+  int get retainedSize => _retainedSize;
+
+  Iterable<SnapshotObject> get successors => _successors;
+  Iterable<SnapshotObject> get predecessors => _predecessors;
+  SnapshotObject get parent => _parent;
+  Iterable<SnapshotObject> get children => _children;
+
+  Iterable<SnapshotObject> get objects sync* {
+    yield this;
+  }
+}
+
+/// A set of sibling objects in the graph's dominator tree that have the same
+/// class.
+abstract class SnapshotMergedDominator {
+  SnapshotClass get klass;
+
+  /// "n instances of Class".
+  String get description;
+
+  /// [internalSize] + [externalSize].
+  int get shallowSize;
+
+  /// The sum of [internalSize] for all objects in this set.
+  int get internalSize;
+
+  /// The sum of [externalSize] for all objects in this set.
+  int get externalSize;
+
+  /// The sum of [externalSize] for all objects in this set.
+  /// This is the amount of memory that would be freed if all references to
+  /// objects in this set were erased.
+  int get retainedSize;
+
+  /// The number of objects in this set. Polymorphic with
+  /// [SnapshotClass.instanceCount].
+  int get instanceCount;
+
+  SnapshotMergedDominator get parent;
+  Iterable<SnapshotMergedDominator> get children;
+
+  Iterable<SnapshotObject> get objects;
+}
+
+// A node in the dominator tree where siblings with the same class are merged.
+// That is, a set of objects with the same cid whose parent chains in the
+// dominator tree have the same cids at each level. [id_] is the representative
+// object of this set. The other members of the set are found by walking the
+// mergedDomNext links until finding the sentinel node or a node with a
+// different class.
+class _SnapshotMergedDominator implements SnapshotMergedDominator {
+  final int _id;
+  final _SnapshotGraph _graph;
+  final _SnapshotMergedDominator _parent;
+
+  _SnapshotMergedDominator._new(this._id, this._graph, this._parent);
+
+  bool operator ==(Object other) {
+    if (other is _SnapshotMergedDominator) {
+      return _id == other._id && _graph == other._graph;
+    }
+    return false;
+  }
+
+  int get hashCode => _id ^ _graph.hashCode;
+
+  String get description {
+    return _id == _ROOT
+        ? "Live Objects + External"
+        : "$instanceCount instances of ${klass.name}";
+  }
+
+  SnapshotClass get klass => _graph._classes[_graph._cids[_id]];
+
+  int get shallowSize => internalSize + externalSize;
+
+  int get internalSize {
+    var cids = _graph._cids;
+    var size = 0;
+    var sibling = _id;
+    while (sibling != _SENTINEL && cids[sibling] == cids[_id]) {
+      size += _graph._internalSizes[sibling];
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return size;
+  }
+
+  int get externalSize {
+    var cids = _graph._cids;
+    var size = 0;
+    var sibling = _id;
+    while (sibling != _SENTINEL && cids[sibling] == cids[_id]) {
+      size += _graph._externalSizes[sibling];
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return size;
+  }
+
+  int get retainedSize {
+    var cids = _graph._cids;
+    var size = 0;
+    var sibling = _id;
+    while (sibling != _SENTINEL && cids[sibling] == cids[_id]) {
+      size += _graph._retainedSizes[sibling];
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return size;
+  }
+
+  int get instanceCount {
+    var cids = _graph._cids;
+    var count = 0;
+    var sibling = _id;
+    while (sibling != _SENTINEL && cids[sibling] == cids[_id]) {
+      count++;
+      sibling = _graph._mergedDomNext[sibling];
+    }
+    return count;
+  }
+
+  Iterable<SnapshotObject> get objects sync* {
+    var cids = _graph._cids;
+    var sibling = _id;
+    while (sibling != _SENTINEL && cids[sibling] == cids[_id]) {
+      yield _SnapshotObject._new(sibling, _graph, "");
+      sibling = _graph._mergedDomNext[sibling];
+    }
+  }
+
+  SnapshotMergedDominator get parent => _parent ?? this;
+
+  Iterable<SnapshotMergedDominator> get children sync* {
+    var next = _graph._mergedDomNext;
+    var cids = _graph._cids;
+    var prev = _SENTINEL;
+    var child = _graph._mergedDomHead[_id];
+    // Walk the list of children and look for the representative objects, i.e.
+    // the first sibling of each cid.
+    while (child != _SENTINEL) {
+      if (prev == _SENTINEL || cids[prev] != cids[child]) {
+        yield _SnapshotMergedDominator._new(child, _graph, this);
+      }
+      prev = child;
+      child = next[child];
+    }
+  }
+}
+
+class _SyntheticSnapshotMergedDominator implements SnapshotMergedDominator {
+  String _description;
+  SnapshotClass _klass;
+  int _internalSize;
+  int _externalSize;
+  int _retainedSize;
+  List<SnapshotObject> _objects;
+  SnapshotMergedDominator _parent;
+  List<SnapshotMergedDominator> _children;
+
+  SnapshotClass get klass => _klass;
+  String get description => _description;
+  int get shallowSize => internalSize + externalSize;
+  int get internalSize => _internalSize;
+  int get externalSize => _externalSize;
+  int get retainedSize => _retainedSize;
+  int get instanceCount => _objects.length;
+  SnapshotMergedDominator get parent => _parent;
+  Iterable<SnapshotMergedDominator> get children => _children;
+  Iterable<SnapshotObject> get objects => _objects;
+}
+
+/// A class in a heap snapshot.
+abstract class SnapshotClass {
+  String get name;
+  String get qualifiedName;
+
+  int get shallowSize;
+  int get externalSize;
+  int get internalSize;
+  int get ownedSize;
+
+  int get instanceCount;
+  Iterable<SnapshotObject> get instances;
+}
+
+class _SnapshotClass implements SnapshotClass {
+  final _SnapshotGraph _graph;
+  final int _cid;
+  final String name;
+  String get qualifiedName => "$libUri $name";
+  final String libName;
+  final String libUri;
+  final Map<int, String> fields = new Map<int, String>();
+
+  int totalExternalSize = 0;
+  int totalInternalSize = 0;
+  int totalInstanceCount = 0;
+
+  int ownedSize = 0;
+
+  int liveExternalSize = 0;
+  int liveInternalSize = 0;
+  int liveInstanceCount = 0;
+
+  int get shallowSize => internalSize + externalSize;
+  int get internalSize => liveInternalSize;
+  int get externalSize => liveExternalSize;
+  int get instanceCount => liveInstanceCount;
+
+  Iterable<SnapshotObject> get instances sync* {
+    final N = _graph._N;
+    for (var id = 1; id <= N; id++) {
+      if (_graph._cids[id] == _cid && _graph._retainedSizes[id] > 0) {
+        yield _SnapshotObject._new(id, _graph, "");
+      }
+    }
+  }
+
+  _SnapshotClass._new(
+      this._graph, this._cid, this.name, this.libName, this.libUri);
+}
+
+/// The analyzed graph from a heap snapshot.
+abstract class SnapshotGraph {
+  String get description;
+
+  int get internalSize;
+  int get externalSize;
+  // [internalSize] + [externalSize]
+  int get size;
+
+  // The amount of memory reserved for the heap. [internalSize] will always be
+  // less than or equal to [capacity].
+  int get capacity;
+
+  Iterable<SnapshotClass> get classes;
+  Iterable<SnapshotObject> get objects;
+
+  SnapshotObject get root;
+  SnapshotObject get extendedRoot;
+  SnapshotMergedDominator get mergedRoot;
+  SnapshotMergedDominator get extendedMergedRoot;
+
+  // TODO: Insist that the client remember the chunks if needed? Always keeping
+  // this increasing the peak memory usage during analysis.
+  List<Uint8List> get chunks;
+}
+
+const _tagNone = 0;
+const _tagNull = 1;
+const _tagBool = 2;
+const _tagInt = 3;
+const _tagDouble = 4;
+const _tagLatin1 = 5;
+const _tagUtf16 = 6;
+const _tagLength = 7;
+const _tagName = 8;
+
+const _kSentinelName = "<omitted-object>";
+const _kRootName = "Live Objects + External";
+const _kUnknownFieldName = "<unknown>";
+
+class _SnapshotGraph implements SnapshotGraph {
+  List<Uint8List> _chunks;
+  List<Uint8List> get chunks => _chunks;
+
+  _SnapshotGraph._new();
+
+  String get description => _description;
+
+  int get size => _liveInternalSize + _liveExternalSize;
+  int get internalSize => _liveInternalSize;
+  int get externalSize => _liveExternalSize;
+  int get capacity => _capacity;
+
+  SnapshotObject get root => _SnapshotObject._new(_ROOT, this, "Root");
+  SnapshotMergedDominator get mergedRoot =>
+      _SnapshotMergedDominator._new(_ROOT, this, null);
+
+  SnapshotObject _extendedRoot;
+  SnapshotObject get extendedRoot {
+    if (_extendedRoot == null) {
+      _createExtended();
+    }
+    return _extendedRoot;
+  }
+
+  SnapshotMergedDominator _extendedMergedRoot;
+  SnapshotMergedDominator get extendedMergedRoot {
+    if (_extendedMergedRoot == null) {
+      _createExtended();
+    }
+    return _extendedMergedRoot;
+  }
+
+  void _createExtended() {
+    var capacity = new _SyntheticSnapshotObject();
+    var uncollected = new _SyntheticSnapshotObject();
+    var fragmentation = new _SyntheticSnapshotObject();
+    var live = root;
+    var mcapacity = new _SyntheticSnapshotMergedDominator();
+    var muncollected = new _SyntheticSnapshotMergedDominator();
+    var mfragmentation = new _SyntheticSnapshotMergedDominator();
+    var mlive = mergedRoot;
+
+    capacity._description = "Capacity + External";
+    capacity._klass = live.klass;
+    capacity._internalSize = _capacity;
+    capacity._externalSize = _totalExternalSize;
+    capacity._retainedSize = capacity._internalSize + capacity._externalSize;
+    capacity._successors = <SnapshotObject>[live, uncollected, fragmentation];
+    capacity._predecessors = <SnapshotObject>[];
+    capacity._children = <SnapshotObject>[live, uncollected, fragmentation];
+
+    mcapacity._description = "Capacity + External";
+    mcapacity._klass = mlive.klass;
+    mcapacity._internalSize = _capacity;
+    mcapacity._externalSize = _totalExternalSize;
+    mcapacity._retainedSize = mcapacity._internalSize + mcapacity._externalSize;
+    mcapacity._children = <SnapshotMergedDominator>[
+      mlive,
+      muncollected,
+      mfragmentation
+    ];
+    mcapacity._objects = <SnapshotObject>[capacity];
+
+    uncollected._description = "Uncollected Garbage";
+    uncollected._klass = live.klass;
+    uncollected._internalSize = _totalInternalSize - _liveInternalSize;
+    uncollected._externalSize = _totalExternalSize - _liveExternalSize;
+    uncollected._retainedSize =
+        uncollected._internalSize + uncollected._externalSize;
+    uncollected._successors = <SnapshotObject>[];
+    uncollected._predecessors = <SnapshotObject>[capacity];
+    uncollected._parent = capacity;
+    uncollected._children = <SnapshotObject>[];
+
+    muncollected._description = "Uncollected Garbage";
+    muncollected._klass = mlive.klass;
+    muncollected._internalSize = _totalInternalSize - _liveInternalSize;
+    muncollected._externalSize = _totalExternalSize - _liveExternalSize;
+    muncollected._retainedSize =
+        muncollected._internalSize + muncollected._externalSize;
+    muncollected._parent = mcapacity;
+    muncollected._children = <SnapshotMergedDominator>[];
+    muncollected._objects = <SnapshotObject>[uncollected];
+
+    fragmentation._description = "Free";
+    fragmentation._klass = live.klass;
+    fragmentation._internalSize = _capacity - _totalInternalSize;
+    fragmentation._externalSize = 0;
+    fragmentation._retainedSize = fragmentation._internalSize;
+    fragmentation._successors = <SnapshotObject>[];
+    fragmentation._predecessors = <SnapshotObject>[capacity];
+    fragmentation._parent = capacity;
+    fragmentation._children = <SnapshotObject>[];
+
+    mfragmentation._description = "Free";
+    mfragmentation._klass = mlive.klass;
+    mfragmentation._internalSize = _capacity - _totalInternalSize;
+    mfragmentation._externalSize = 0;
+    mfragmentation._retainedSize = mfragmentation._internalSize;
+    mfragmentation._parent = mcapacity;
+    mfragmentation._children = <SnapshotMergedDominator>[];
+    mfragmentation._objects = <SnapshotObject>[fragmentation];
+
+    _extendedRoot = capacity;
+    _extendedMergedRoot = mcapacity;
+  }
+
+  Iterable<SnapshotObject> get objects sync* {
+    final N = _N;
+    for (var id = 1; id <= N; id++) {
+      if (_retainedSizes[id] > 0) {
+        yield _SnapshotObject._new(id, this, "");
+      }
+    }
+  }
+
+  String _describeObject(int oid) {
+    if (oid == _SENTINEL) {
+      return _kSentinelName;
+    }
+    if (oid == _ROOT) {
+      return _kRootName;
+    }
+    var cls = _className(oid);
+    var data = _nonReferenceData[oid];
+    if (data == null) {
+      return cls;
+    } else {
+      return "$cls($data)";
+    }
+  }
+
+  String _className(int oid) {
+    var cid = _cids[oid];
+    var cls = _classes[cid];
+    if (cls == null) {
+      return "Class$cid";
+    }
+    return cls.name;
+  }
+
+  String _edgeName(int cid, int index) {
+    var c = _classes[cid];
+    if (c == null) {
+      return _kUnknownFieldName;
+    }
+    var n = c.fields[index];
+    if (n == null) {
+      return _kUnknownFieldName;
+    }
+    return n;
+  }
+
+  Iterable<SnapshotClass> get classes sync* {
+    for (final c in _classes) {
+      // Not all CIDs are occupied.
+      if (c != null) {
+        yield c;
+      }
+    }
+  }
+
+  Future<SnapshotGraph> _load(
+      List<Uint8List> chunks, StreamController<String> onProgress) async {
+    _chunks = chunks;
+    var stream = _ReadStream._new(chunks);
+    chunks = null;
+
+    // The phases of loading are placed in explicit `new Future(compuation)` so
+    // they will be deferred to the message loop. Ordinary async-await will only
+    // defer to the microtask loop.
+
+    onProgress.add("Loading classes...");
+    await new Future(() => _readClasses(stream));
+
+    onProgress.add("Loading objects...");
+    await new Future(() => _readObjects(stream));
+
+    onProgress.add("Loading external properties...");
+    await new Future(() => _readExternalProperties(stream));
+
+    stream = null;
+
+    onProgress.add("Compute class table...");
+    await new Future(() => _computeClassTable());
+
+    onProgress.add("Finding depth-first order...");
+    await new Future(() => _dfs());
+
+    onProgress.add("Finding predecessors...");
+    await new Future(() => _buildPredecessors());
+
+    onProgress.add("Finding dominators...");
+    await new Future(() => _buildDominators());
+
+    _semi = null;
+    _parent = null;
+
+    onProgress.add("Finding in-degree(1) groups...");
+    await new Future(() => _buildOwnedSizes());
+
+    _firstPreds = null;
+    _preds = null;
+
+    onProgress.add("Finding retained sizes...");
+    await new Future(() => _calculateRetainedSizes());
+
+    _vertex = null;
+
+    onProgress.add("Linking dominator tree children...");
+    await new Future(() => _linkDominatorChildren());
+
+    onProgress.add("Sorting dominator tree children...");
+    await new Future(() => _sortDominatorChildren());
+
+    onProgress.add("Merging dominator tree siblings...");
+    await new Future(() => _mergeDominatorSiblings());
+
+    onProgress.add("Loaded");
+    // We await here so SnapshotReader clients see all progress events before
+    // seeing the done future as completed.
+    await onProgress.close();
+
+    return this;
+  }
+
+  Uint8List _encoded;
+
+  String _description;
+
+  int _kStackCid;
+  int _kFieldCid;
+  int _numCids;
+  int _N; // Objects in the snapshot.
+  int _Nconnected; // Objects reachable from root.
+  int _E; // References in the snapshot.
+
+  int _capacity;
+  int _liveInternalSize;
+  int _liveExternalSize;
+  int _totalInternalSize;
+  int _totalExternalSize;
+
+  List<_SnapshotClass> _classes;
+
+  // Indexed by node id, with id 0 representing invalid/uninitialized.
+  // From snapshot.
+  List _nonReferenceData;
+  Uint16List _cids;
+  Uint32List _internalSizes;
+  Uint32List _externalSizes;
+  Uint32List _firstSuccs;
+  Uint32List _succs;
+
+  // Intermediates.
+  Uint32List _vertex;
+  Uint32List _parent;
+  Uint32List _semi;
+  Uint32List _firstPreds; // Offset into preds.
+  Uint32List _preds;
+
+  // Outputs.
+  Uint32List _doms;
+  Uint32List _retainedSizes;
+  Uint32List _mergedDomHead;
+  Uint32List _mergedDomNext;
+
+  void _readClasses(_ReadStream stream) {
+    for (var i = 0; i < 8; i++) {
+      stream.readByte(); // Magic value.
+    }
+    stream.readUnsigned(); // Flags
+    _description = stream.readUtf8();
+
+    _totalInternalSize = stream.readUnsigned();
+    _capacity = stream.readUnsigned();
+    _totalExternalSize = stream.readUnsigned();
+
+    var K = stream.readUnsigned();
+    var classes = new List<_SnapshotClass>.filled(K + 1, null);
+    classes[0] = _SnapshotClass._new(this, 0, "Root", "", "");
+
+    for (var cid = 1; cid <= K; cid++) {
+      int flags = stream.readUnsigned();
+      String name = stream.readUtf8();
+      String libName = stream.readUtf8();
+      String libUri = stream.readUtf8();
+      String reserved = stream.readUtf8();
+      final cls = _SnapshotClass._new(this, cid, name, libName, libUri);
+      int edgeCount = stream.readUnsigned();
+      for (int i = 0; i < edgeCount; i++) {
+        int flags = stream.readUnsigned();
+        int index = stream.readUnsigned();
+        String fieldName = stream.readUtf8();
+        String reserved = stream.readUtf8();
+        cls.fields[index] = fieldName;
+      }
+      classes[cid] = cls;
+    }
+
+    _numCids = K;
+    _classes = classes;
+  }
+
+  void _readObjects(_ReadStream stream) {
+    final E = stream.readUnsigned();
+    final N = stream.readUnsigned();
+
+    // The negative check accounts for int64 overflow in readUnsigned.
+    const maxUint32 = 0xFFFFFFFF;
+    if (N < 0 || N + 2 >= maxUint32) {
+      throw new Exception("Snapshot contains too many objects: $N");
+    }
+    if (E < 0 || E + 2 >= maxUint32) {
+      throw new Exception("Snapshot contains too many references: $E");
+    }
+
+    _N = N;
+    _E = E;
+
+    var internalSizes = _newUint32Array(N + 1);
+    var cids = _newUint16Array(N + 1);
+    var nonReferenceData = new List(N + 1);
+    var firstSuccs = _newUint32Array(N + 2);
+    var succs = _newUint32Array(E);
+    var eid = 0;
+    for (var oid = 1; oid <= N; oid++) {
+      var cid = stream.readUnsigned();
+      cids[oid] = cid;
+
+      var internalSize = stream.readUnsigned();
+      internalSizes[oid] = internalSize;
+
+      var nonReferenceDataTag = stream.readUnsigned();
+      switch (nonReferenceDataTag) {
+        case _tagNone:
+          break;
+        case _tagNull:
+          nonReferenceData[oid] = "null";
+          break;
+        case _tagBool:
+          nonReferenceData[oid] = stream.readByte() != 0;
+          break;
+        case _tagInt:
+          nonReferenceData[oid] = stream.readSigned();
+          break;
+        case _tagDouble:
+          nonReferenceData[oid] = stream.readFloat64();
+          break;
+        case _tagLatin1:
+          var len = stream.readUnsigned();
+          var str = stream.readLatin1();
+          if (str.length < len) {
+            nonReferenceData[oid] = '$str...';
+          } else {
+            nonReferenceData[oid] = str;
+          }
+          break;
+        case _tagUtf16:
+          int len = stream.readUnsigned();
+          var str = stream.readUtf16();
+          if (str.length < len) {
+            nonReferenceData[oid] = '$str...';
+          } else {
+            nonReferenceData[oid] = str;
+          }
+          break;
+        case _tagLength:
+          nonReferenceData[oid] = stream.readUnsigned(); // Length
+          break;
+        case _tagName:
+          nonReferenceData[oid] = stream.readUtf8(); // Name
+          break;
+        default:
+          throw "Unknown tag $nonReferenceDataTag";
+      }
+
+      firstSuccs[oid] = eid;
+      var referenceCount = stream.readUnsigned();
+      while (referenceCount > 0) {
+        var childOid = stream.readUnsigned();
+        succs[eid] = childOid;
+        eid++;
+        referenceCount--;
+      }
+    }
+    firstSuccs[N + 1] = eid;
+
+    assert(eid <= E);
+    _E = eid;
+    _internalSizes = internalSizes;
+    _cids = cids;
+    _nonReferenceData = nonReferenceData;
+    _firstSuccs = firstSuccs;
+    _succs = succs;
+  }
+
+  void _readExternalProperties(_ReadStream stream) {
+    final N = _N;
+    final externalPropertyCount = stream.readUnsigned();
+
+    final externalSizes = _newUint32Array(N + 1);
+    for (var i = 0; i < externalPropertyCount; i++) {
+      final oid = stream.readUnsigned();
+      final externalSize = stream.readUnsigned();
+      final name = stream.readUtf8();
+      externalSizes[oid] += externalSize;
+    }
+
+    _externalSizes = externalSizes;
+  }
+
+  void _computeClassTable() {
+    final N = _N;
+    final classes = _classes;
+    final cids = _cids;
+    final internalSizes = _internalSizes;
+    final externalSizes = _externalSizes;
+    var totalInternalSize = 0;
+    var totalExternalSize = 0;
+
+    for (var oid = 1; oid <= N; oid++) {
+      var internalSize = internalSizes[oid];
+      totalInternalSize += internalSize;
+
+      var externalSize = externalSizes[oid];
+      totalExternalSize += externalSize;
+
+      var cls = classes[cids[oid]];
+      cls.totalInternalSize += internalSize;
+      cls.totalExternalSize += externalSize;
+      cls.totalInstanceCount++;
+    }
+
+    _totalInternalSize = totalInternalSize;
+    _totalExternalSize = totalExternalSize;
+  }
+
+  void _dfs() {
+    final N = _N;
+    final firstSuccs = _firstSuccs;
+    final succs = _succs;
+
+    final stackNodes = _newUint32Array(N);
+    final stackCurrentEdgePos = _newUint32Array(N);
+
+    final vertex = _newUint32Array(N + 1);
+    final semi = _newUint32Array(N + 1);
+    final parent = _newUint32Array(N + 1);
+    var dfsNumber = 0;
+
+    var stackTop = 0;
+
+    // Push root.
+    stackNodes[0] = _ROOT;
+    stackCurrentEdgePos[0] = firstSuccs[_ROOT];
+
+    while (stackTop >= 0) {
+      var v = stackNodes[stackTop];
+      var edgePos = stackCurrentEdgePos[stackTop];
+
+      if (semi[v] == 0) {
+        // First visit.
+        dfsNumber++;
+        semi[v] = dfsNumber;
+        vertex[dfsNumber] = v;
+      }
+
+      if (edgePos < firstSuccs[v + 1]) {
+        var childId = succs[edgePos];
+        edgePos++;
+        stackCurrentEdgePos[stackTop] = edgePos;
+
+        if (childId == _SENTINEL) {
+          // Omitted target.
+        } else if (semi[childId] == 0) {
+          parent[childId] = v;
+
+          // Push child.
+          stackTop++;
+          stackNodes[stackTop] = childId;
+          stackCurrentEdgePos[stackTop] = firstSuccs[childId];
+        }
+      } else {
+        // Done with all children.
+        stackTop--;
+      }
+    }
+
+    if (dfsNumber != N) {
+      // This may happen in filtered snapshots.
+      print('Heap snapshot contains ${N - dfsNumber} unreachable nodes.');
+    }
+
+    assert(() {
+      for (var i = 1; i <= dfsNumber; i++) {
+        var v = vertex[i];
+        assert(semi[v] != _SENTINEL);
+      }
+      assert(parent[1] == _SENTINEL);
+      for (var i = 2; i <= dfsNumber; i++) {
+        var v = vertex[i];
+        assert(parent[v] != _SENTINEL);
+      }
+      return true;
+    }());
+
+    if (dfsNumber != N) {
+      // Remove successors of unconnected nodes
+      for (var i = _ROOT + 1; i <= N; i++) {
+        if (parent[i] == _SENTINEL) {
+          var startSuccIndex = firstSuccs[i];
+          var limitSuccIndex = firstSuccs[i + 1];
+          for (var succIndex = startSuccIndex;
+              succIndex < limitSuccIndex;
+              succIndex++) {
+            succs[succIndex] = _SENTINEL;
+          }
+        }
+      }
+    }
+
+    _Nconnected = dfsNumber;
+    _vertex = vertex;
+    _semi = semi;
+    _parent = parent;
+  }
+
+  void _buildPredecessors() {
+    final N = _N;
+    final Nconnected = _Nconnected;
+    final E = _E;
+    final firstSuccs = _firstSuccs;
+    final succs = _succs;
+
+    // This is first filled with the predecessor counts, then reused to hold the
+    // offset to the first predecessor (see alias below).
+    // + 1 because 0 is a sentinel
+    // + 1 so the number of predecessors can be found from the difference with
+    // the next node's offset.
+    final numPreds = _newUint32Array(N + 2);
+    final preds = _newUint32Array(E);
+
+    // Count predecessors of each node.
+    for (var succIndex = 0; succIndex < E; succIndex++) {
+      final succId = succs[succIndex];
+      if (succId != _SENTINEL) {
+        numPreds[succId]++;
+      }
+    }
+
+    // Assign indices into predecessors array.
+    final firstPreds = numPreds; // Alias.
+    final nextPreds = _newUint32Array(N + 1);
+    var predIndex = 0;
+    for (var i = 1; i <= N; i++) {
+      var thisPredIndex = predIndex;
+      predIndex += numPreds[i];
+      firstPreds[i] = thisPredIndex;
+      nextPreds[i] = thisPredIndex;
+    }
+    if (N == Nconnected) {
+      assert(predIndex == E);
+    }
+    firstPreds[N + 1] = predIndex; // Extra entry for cheap boundary detection.
+
+    // Fill predecessors array.
+    for (var i = 1; i <= N; i++) {
+      var startSuccIndex = firstSuccs[i];
+      var limitSuccIndex = firstSuccs[i + 1];
+      for (var succIndex = startSuccIndex;
+          succIndex < limitSuccIndex;
+          succIndex++) {
+        var succId = succs[succIndex];
+        if (succId != _SENTINEL) {
+          var predIndex = nextPreds[succId]++;
+          preds[predIndex] = i;
+        }
+      }
+    }
+
+    _firstPreds = firstPreds;
+    _preds = preds;
+  }
+
+  // Fold the size of any object with in-degree(1) into its parent.
+  // Requires the DFS numbering and predecessor lists.
+  void _buildOwnedSizes() {
+    final N = _N;
+    final Nconnected = _Nconnected;
+    final kStackCid = _kStackCid;
+    final kFieldCid = _kFieldCid;
+
+    final cids = _cids;
+    final internalSizes = _internalSizes;
+    final externalSizes = _externalSizes;
+    final vertex = _vertex;
+    final firstPreds = _firstPreds;
+    final preds = _preds;
+
+    final ownedSizes = _newUint32Array(N + 1);
+    for (var i = 1; i <= Nconnected; i++) {
+      final v = vertex[i];
+      ownedSizes[v] = internalSizes[v] + externalSizes[v];
+    }
+
+    for (var i = Nconnected; i > 1; i--) {
+      var w = vertex[i];
+      assert(w != _ROOT);
+
+      var onlyPred = _SENTINEL;
+
+      var startPred = firstPreds[w];
+      var limitPred = firstPreds[w + 1];
+      for (var predIndex = startPred; predIndex < limitPred; predIndex++) {
+        var v = preds[predIndex];
+        if (v == w) {
+          // Ignore self-predecessor.
+        } else if (onlyPred == _SENTINEL) {
+          onlyPred = v;
+        } else if (onlyPred == v) {
+          // Repeated predecessor.
+        } else {
+          // Multiple-predecessors.
+          onlyPred = _SENTINEL;
+          break;
+        }
+      }
+
+      // If this object has a single precessor which is not a Field, Stack or
+      // the root, blame its size against the precessor.
+      if ((onlyPred != _SENTINEL) &&
+          (onlyPred != _ROOT) &&
+          (cids[onlyPred] != kStackCid) &&
+          (cids[onlyPred] != kFieldCid)) {
+        assert(onlyPred != w);
+        ownedSizes[onlyPred] += ownedSizes[w];
+        ownedSizes[w] = 0;
+      }
+    }
+
+    // TODO(rmacnak): Maybe keep the per-objects sizes to be able to provide
+    // examples of large owners for each class.
+    final classes = _classes;
+    for (var i = 1; i <= Nconnected; i++) {
+      final v = vertex[i];
+      final cid = cids[v];
+      final cls = classes[cid];
+      cls.ownedSize += ownedSizes[v];
+    }
+  }
+
+  static int _eval(int v, Uint32List ancestor, Uint32List semi,
+      Uint32List label, Uint32List stackNode, Uint8List stackState) {
+    if (ancestor[v] == _SENTINEL) {
+      return label[v];
+    } else {
+      {
+        // Inlined 'compress' with an explicit stack to prevent JS stack
+        // overflow.
+        var top = 0;
+        stackNode[top] = v;
+        stackState[top] = 0;
+        while (top >= 0) {
+          var v = stackNode[top];
+          var state = stackState[top];
+          if (state == 0) {
+            assert(ancestor[v] != 0);
+            if (ancestor[ancestor[v]] != 0) {
+              stackState[top] = 1;
+              // Recurse with ancestor[v]
+              top++;
+              stackNode[top] = ancestor[v];
+              stackState[top] = 0;
+            } else {
+              top--;
+            }
+          } else {
+            assert(state == 1);
+            if (semi[label[ancestor[v]]] < semi[label[v]]) {
+              label[v] = label[ancestor[v]];
+            }
+            ancestor[v] = ancestor[ancestor[v]];
+            top--;
+          }
+        }
+      }
+
+      if (semi[label[ancestor[v]]] >= semi[label[v]]) {
+        return label[v];
+      } else {
+        return label[ancestor[v]];
+      }
+    }
+  }
+
+  // Note the version in the main text of Lengauer & Tarjan incorrectly
+  // uses parent instead of ancestor. The correct version is in Appendix B.
+  static void _link(int v, int w, Uint32List size, Uint32List label,
+      Uint32List semi, Uint32List child, Uint32List ancestor) {
+    assert(size[0] == 0);
+    assert(label[0] == 0);
+    assert(semi[0] == 0);
+    var s = w;
+    while (semi[label[w]] < semi[label[child[s]]]) {
+      if (size[s] + size[child[child[s]]] >= 2 * size[child[s]]) {
+        ancestor[child[s]] = s;
+        child[s] = child[child[s]];
+      } else {
+        size[child[s]] = size[s];
+        s = ancestor[s] = child[s];
+      }
+    }
+    label[s] = label[w];
+    size[v] = size[v] + size[w];
+    if (size[v] < 2 * size[w]) {
+      var tmp = s;
+      s = child[v];
+      child[v] = tmp;
+    }
+    while (s != 0) {
+      ancestor[s] = v;
+      s = child[s];
+    }
+  }
+
+  // T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
+  // in a Flowgraph."
+  void _buildDominators() {
+    final N = _N;
+    final Nconnected = _Nconnected;
+
+    final vertex = _vertex;
+    final semi = _semi;
+    final parent = _parent;
+    final firstPreds = _firstPreds;
+    final preds = _preds;
+
+    final dom = _newUint32Array(N + 1);
+
+    final ancestor = _newUint32Array(N + 1);
+    final label = _newUint32Array(N + 1);
+    for (var i = 1; i <= N; i++) {
+      label[i] = i;
+    }
+    final buckets = new List(N + 1);
+    final child = _newUint32Array(N + 1);
+    final size = _newUint32Array(N + 1);
+    for (var i = 1; i <= N; i++) {
+      size[i] = 1;
+    }
+    final stackNode = _newUint32Array(N + 1);
+    final stackState = _newUint8Array(N + 1);
+
+    for (var i = Nconnected; i > 1; i--) {
+      var w = vertex[i];
+      assert(w != _ROOT);
+
+      // Lengauer & Tarjan Step 2.
+      var startPred = firstPreds[w];
+      var limitPred = firstPreds[w + 1];
+      for (var predIndex = startPred; predIndex < limitPred; predIndex++) {
+        var v = preds[predIndex];
+        var u = _eval(v, ancestor, semi, label, stackNode, stackState);
+        if (semi[u] < semi[w]) {
+          semi[w] = semi[u];
+        }
+      }
+
+      // w.semi.bucket.add(w);
+      var tmp = vertex[semi[w]];
+      if (buckets[tmp] == null) {
+        buckets[tmp] = new List();
+      }
+      buckets[tmp].add(w);
+
+      _link(parent[w], w, size, label, semi, child, ancestor);
+
+      // Lengauer & Tarjan Step 3.
+      tmp = parent[w];
+      var bucket = buckets[tmp];
+      buckets[tmp] = null;
+      if (bucket != null) {
+        for (var v in bucket) {
+          var u = _eval(v, ancestor, semi, label, stackNode, stackState);
+          dom[v] = semi[u] < semi[v] ? u : parent[w];
+        }
+      }
+    }
+    for (var i = _ROOT; i <= N; i++) {
+      assert(buckets[i] == null);
+    }
+    // Lengauer & Tarjan Step 4.
+    for (var i = 2; i <= Nconnected; i++) {
+      var w = vertex[i];
+      if (dom[w] != vertex[semi[w]]) {
+        dom[w] = dom[dom[w]];
+      }
+    }
+
+    _doms = dom;
+  }
+
+  void _calculateRetainedSizes() {
+    final N = _N;
+    final Nconnected = _Nconnected;
+
+    var liveInternalSize = 0;
+    var liveExternalSize = 0;
+    final classes = _classes;
+    final cids = _cids;
+    final internalSizes = _internalSizes;
+    final externalSizes = _externalSizes;
+    final vertex = _vertex;
+    final doms = _doms;
+
+    // Sum internal and external sizes.
+    for (var i = 1; i <= Nconnected; i++) {
+      var v = vertex[i];
+      var internalSize = internalSizes[v];
+      var externalSize = externalSizes[v];
+      liveInternalSize += internalSize;
+      liveExternalSize += externalSize;
+
+      var cls = classes[cids[v]];
+      cls.liveInternalSize += internalSize;
+      cls.liveExternalSize += externalSize;
+      cls.liveInstanceCount++;
+    }
+
+    // Start with retained size as shallow size + external size. For reachable
+    // objects only; leave unreachable objects with a retained size of 0 so
+    // they can be filtered during graph iterations.
+    var retainedSizes = new Uint32List(N + 1);
+    assert(Nconnected <= N);
+    for (var i = 0; i <= Nconnected; i++) {
+      var v = vertex[i];
+      retainedSizes[v] = internalSizes[v] + externalSizes[v];
+    }
+
+    // In post order (bottom up), add retained size to dominator's retained
+    // size, skipping root.
+    for (var i = Nconnected; i > 1; i--) {
+      var v = vertex[i];
+      assert(v != _ROOT);
+      retainedSizes[doms[v]] += retainedSizes[v];
+    }
+
+    // Root retains everything.
+    assert(retainedSizes[_ROOT] == (liveInternalSize + liveExternalSize));
+
+    _retainedSizes = retainedSizes;
+    _liveInternalSize = liveInternalSize;
+    _liveExternalSize = liveExternalSize;
+
+    print("internal-garbage: ${_totalInternalSize - _liveInternalSize}");
+    print("external-garbage: ${_totalExternalSize - _liveExternalSize}");
+    print("fragmentation: ${_capacity - _totalInternalSize}");
+    assert(_liveInternalSize <= _totalInternalSize);
+    assert(_liveExternalSize <= _totalExternalSize);
+    assert(_totalInternalSize <= _capacity);
+  }
+
+  // Build linked lists of the children for each node in the dominator tree.
+  void _linkDominatorChildren() {
+    final N = _N;
+    final doms = _doms;
+    final head = _newUint32Array(N + 1);
+    final next = _newUint32Array(N + 1);
+
+    for (var child = _ROOT; child <= N; child++) {
+      var parent = doms[child];
+      next[child] = head[parent];
+      head[parent] = child;
+    }
+
+    _mergedDomHead = head;
+    _mergedDomNext = next;
+  }
+
+  // Merge the given lists according to the given key in ascending order.
+  // Returns the head of the merged list.
+  static int _mergeSorted(
+      int head1, int head2, Uint32List next, Uint16List key) {
+    var head = head1;
+    var beforeInsert = _SENTINEL;
+    var afterInsert = head1;
+    var startInsert = head2;
+
+    while (startInsert != _SENTINEL) {
+      while ((afterInsert != _SENTINEL) &&
+          (key[afterInsert] <= key[startInsert])) {
+        beforeInsert = afterInsert;
+        afterInsert = next[beforeInsert];
+      }
+
+      var endInsert = startInsert;
+      var peek = next[endInsert];
+
+      while ((peek != _SENTINEL) && (key[peek] < key[afterInsert])) {
+        endInsert = peek;
+        peek = next[endInsert];
+      }
+      assert(endInsert != _SENTINEL);
+
+      if (beforeInsert == _SENTINEL) {
+        head = startInsert;
+      } else {
+        next[beforeInsert] = startInsert;
+      }
+      next[endInsert] = afterInsert;
+
+      startInsert = peek;
+      beforeInsert = endInsert;
+    }
+
+    return head;
+  }
+
+  void _sortDominatorChildren() {
+    final N = _N;
+    final cids = _cids;
+    final head = _mergedDomHead;
+    final next = _mergedDomNext;
+
+    // Returns the new head of the sorted list.
+    int sort(int head) {
+      if (head == _SENTINEL) return _SENTINEL;
+      if (next[head] == _SENTINEL) return head;
+
+      // Find the middle of the list.
+      int head1 = head;
+      int slow = head;
+      int fast = head;
+      while (next[fast] != _SENTINEL && next[next[fast]] != _SENTINEL) {
+        slow = next[slow];
+        fast = next[next[fast]];
+      }
+
+      // Split the list in half.
+      int head2 = next[slow];
+      next[slow] = _SENTINEL;
+
+      // Recursively sort the sublists and merge.
+      assert(head1 != head2);
+      int newHead1 = sort(head1);
+      int newHead2 = sort(head2);
+      return _mergeSorted(newHead1, newHead2, next, cids);
+    }
+
+    // Sort all list of dominator tree children by cid.
+    for (var parent = _ROOT; parent <= N; parent++) {
+      head[parent] = sort(head[parent]);
+    }
+  }
+
+  void _mergeDominatorSiblings() {
+    var N = _N;
+    var cids = _cids;
+    var head = _mergedDomHead;
+    var next = _mergedDomNext;
+    var workStack = _newUint32Array(N);
+    var workStackTop = 0;
+
+    mergeChildrenAndSort(var parent1, var end) {
+      assert(parent1 != _SENTINEL);
+      if (next[parent1] == end) return;
+
+      // Find the middle of the list.
+      int slow = parent1;
+      int fast = parent1;
+      while (next[fast] != end && next[next[fast]] != end) {
+        slow = next[slow];
+        fast = next[next[fast]];
+      }
+
+      int parent2 = next[slow];
+
+      assert(parent2 != _SENTINEL);
+      assert(parent1 != parent2);
+      assert(cids[parent1] == cids[parent2]);
+
+      // Recursively sort the sublists.
+      mergeChildrenAndSort(parent1, parent2);
+      mergeChildrenAndSort(parent2, end);
+
+      // Merge sorted sublists.
+      head[parent1] = _mergeSorted(head[parent1], head[parent2], next, cids);
+
+      // Children moved to parent1.
+      head[parent2] = _SENTINEL;
+    }
+
+    // Push root.
+    workStack[workStackTop++] = _ROOT;
+
+    while (workStackTop > 0) {
+      var parent = workStack[--workStackTop];
+
+      var child = head[parent];
+      while (child != _SENTINEL) {
+        // Push child.
+        workStack[workStackTop++] = child;
+
+        // Find next sibling with a different cid.
+        var after = child;
+        while (after != _SENTINEL && cids[after] == cids[child]) {
+          after = next[after];
+        }
+
+        // From all the siblings between child and after, take their children,
+        // merge them and given to child.
+        mergeChildrenAndSort(child, after);
+
+        child = after;
+      }
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/repositories.dart b/runtime/observatory_2/lib/repositories.dart
new file mode 100644
index 0000000..35579ef
--- /dev/null
+++ b/runtime/observatory_2/lib/repositories.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library repositories;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:html';
+import 'dart:typed_data';
+import 'package:observatory_2/allocation_profile.dart';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:observatory_2/object_graph.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/service_common.dart' as SC;
+import 'package:observatory_2/src/repositories/timeline_base.dart';
+
+part 'src/repositories/allocation_profile.dart';
+part 'src/repositories/breakpoint.dart';
+part 'src/repositories/class.dart';
+part 'src/repositories/context.dart';
+part 'src/repositories/editor.dart';
+part 'src/repositories/eval.dart';
+part 'src/repositories/event.dart';
+part 'src/repositories/field.dart';
+part 'src/repositories/flag.dart';
+part 'src/repositories/function.dart';
+part 'src/repositories/heap_snapshot.dart';
+part 'src/repositories/icdata.dart';
+part 'src/repositories/inbound_references.dart';
+part 'src/repositories/instance.dart';
+part 'src/repositories/isolate.dart';
+part 'src/repositories/isolate_group.dart';
+part 'src/repositories/library.dart';
+part 'src/repositories/megamorphiccache.dart';
+part 'src/repositories/metric.dart';
+part 'src/repositories/notification.dart';
+part 'src/repositories/object.dart';
+part 'src/repositories/objectpool.dart';
+part 'src/repositories/objectstore.dart';
+part 'src/repositories/persistent_handles.dart';
+part 'src/repositories/ports.dart';
+part 'src/repositories/reachable_size.dart';
+part 'src/repositories/retained_size.dart';
+part 'src/repositories/retaining_path.dart';
+part 'src/repositories/sample_profile.dart';
+part 'src/repositories/script.dart';
+part 'src/repositories/settings.dart';
+part 'src/repositories/single_target_cache.dart';
+part 'src/repositories/strongly_reachable_instances.dart';
+part 'src/repositories/subtype_test_cache.dart';
+part 'src/repositories/target.dart';
+part 'src/repositories/timeline.dart';
+part 'src/repositories/type_arguments.dart';
+part 'src/repositories/unlinked_call.dart';
+part 'src/repositories/vm.dart';
diff --git a/runtime/observatory_2/lib/sample_profile.dart b/runtime/observatory_2/lib/sample_profile.dart
new file mode 100644
index 0000000..adae259
--- /dev/null
+++ b/runtime/observatory_2/lib/sample_profile.dart
@@ -0,0 +1,13 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library sample_profiler;
+
+import 'dart:async';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart';
+import 'package:observatory_2/utils.dart';
+
+part 'src/sample_profile/sample_profile.dart';
diff --git a/runtime/observatory_2/lib/service.dart b/runtime/observatory_2/lib/service.dart
new file mode 100644
index 0000000..8544b93a
--- /dev/null
+++ b/runtime/observatory_2/lib/service.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library service;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:typed_data';
+import 'dart:math' as math;
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/event.dart' show createEventFromServiceEvent;
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/object_graph.dart';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:observatory_2/service_common.dart';
+import 'package:observatory_2/tracer.dart';
+
+part 'src/service/object.dart';
diff --git a/runtime/observatory_2/lib/service_common.dart b/runtime/observatory_2/lib/service_common.dart
new file mode 100644
index 0000000..b61f4a0
--- /dev/null
+++ b/runtime/observatory_2/lib/service_common.dart
@@ -0,0 +1,339 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library service_common;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:typed_data';
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart';
+
+// Export the service library.
+export 'package:observatory_2/service.dart';
+
+/// Description of a VM target.
+class WebSocketVMTarget implements M.Target {
+  // Last time this VM has been connected to.
+  int lastConnectionTime = 0;
+  bool get hasEverConnected => lastConnectionTime > 0;
+
+  // Chrome VM or standalone;
+  bool chrome = false;
+  bool get standalone => !chrome;
+
+  // User defined name.
+  String name;
+  // Network address of VM.
+  String networkAddress;
+
+  WebSocketVMTarget(this.networkAddress) {
+    name = networkAddress;
+  }
+
+  WebSocketVMTarget.fromMap(Map json) {
+    lastConnectionTime = json['lastConnectionTime'];
+    chrome = json['chrome'];
+    name = json['name'];
+    networkAddress = json['networkAddress'];
+    if (name == null) {
+      name = networkAddress;
+    }
+  }
+
+  Map toJson() {
+    return {
+      'lastConnectionTime': lastConnectionTime,
+      'chrome': chrome,
+      'name': name,
+      'networkAddress': networkAddress,
+    };
+  }
+}
+
+class _WebSocketRequest {
+  final String method;
+  final Map params;
+  final Completer<Map> completer;
+
+  _WebSocketRequest(this.method, this.params)
+      : completer = new Completer<Map>();
+}
+
+/// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html].
+abstract class CommonWebSocket {
+  Future<void> connect(WebSocketVMTarget target, void onOpen(),
+      void onMessage(dynamic data), void onError(), void onClose());
+  bool get isOpen;
+  void send(dynamic data);
+  void close();
+  Future<ByteData> nonStringToByteData(dynamic data);
+}
+
+/// A [CommonWebSocketVM] communicates with a Dart VM over a CommonWebSocket.
+/// The Dart VM can be embedded in Chromium or standalone.
+abstract class CommonWebSocketVM extends VM {
+  final Completer _connected = new Completer();
+  final Completer<String> _disconnected = new Completer<String>();
+  final WebSocketVMTarget target;
+  final Map<String, _WebSocketRequest> _delayedRequests =
+      new Map<String, _WebSocketRequest>();
+  final Map<String, _WebSocketRequest> _pendingRequests =
+      new Map<String, _WebSocketRequest>();
+  int _requestSerial = 0;
+  bool _hasInitiatedConnect = false;
+  Utf8Decoder _utf8Decoder = const Utf8Decoder();
+
+  String get displayName => '${name}@${target.name}';
+
+  CommonWebSocket _webSocket;
+
+  CommonWebSocketVM(this.target, this._webSocket) {
+    assert(target != null);
+  }
+
+  void _notifyConnect() {
+    if (!_connected.isCompleted) {
+      Logger.root
+          .info('WebSocketVM connection opened: ${target.networkAddress}');
+      _connected.complete(this);
+    }
+  }
+
+  Future get onConnect => _connected.future;
+  bool get wasOrIsConnected => _connected.isCompleted;
+  bool get isConnected => wasOrIsConnected && !isDisconnected;
+  void _notifyDisconnect(String reason) {
+    if (!_disconnected.isCompleted) {
+      Logger.root
+          .info('WebSocketVM connection error: ${target.networkAddress}');
+      _disconnected.complete(reason);
+    }
+  }
+
+  Future<String> get onDisconnect => _disconnected.future;
+  bool get isDisconnected => _disconnected.isCompleted;
+
+  void disconnect({String reason: 'WebSocket closed'}) {
+    if (_hasInitiatedConnect) {
+      if (_webSocket != null) {
+        _webSocket.close();
+      }
+    }
+    // We don't need to cancel requests and notify here.  These
+    // functions will be called again when the onClose callback
+    // fires. However, we may have a better 'reason' string now, so
+    // let's take care of business.
+    _cancelAllRequests(reason);
+    _notifyDisconnect(reason);
+  }
+
+  Future<Map> invokeRpcRaw(String method, Map params) async {
+    if (!_hasInitiatedConnect) {
+      _hasInitiatedConnect = true;
+      try {
+        await _webSocket.connect(
+            target, _onOpen, _onMessage, _onError, _onClose);
+      } catch (_, stack) {
+        _webSocket = null;
+        var exception = new NetworkRpcException('WebSocket closed');
+        return new Future.error(exception, stack);
+      }
+    }
+    if (_disconnected.isCompleted) {
+      // This connection was closed already.
+      var exception = new NetworkRpcException(await onDisconnect);
+      return new Future.error(exception);
+    }
+    String serial = (_requestSerial++).toString();
+    var request = new _WebSocketRequest(method, params);
+    if ((_webSocket != null) && _webSocket.isOpen) {
+      // Already connected, send request immediately.
+      _sendRequest(serial, request);
+    } else {
+      // Not connected yet, add to delayed requests.
+      _delayedRequests[serial] = request;
+    }
+    return request.completer.future;
+  }
+
+  void _onClose() {
+    _cancelAllRequests('WebSocket closed');
+    _notifyDisconnect('WebSocket closed');
+  }
+
+  // WebSocket error event handler.
+  void _onError() {
+    // TODO(turnidge): The implementors of CommonWebSocket have more
+    // error information available.  Consider providing that here.
+    _cancelAllRequests('WebSocket closed due to error');
+    _notifyDisconnect('WebSocket closed due to error');
+  }
+
+  // WebSocket open event handler.
+  void _onOpen() {
+    target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch;
+    _sendAllDelayedRequests();
+    _notifyConnect();
+  }
+
+  Map _parseJSON(String message) {
+    var map;
+    try {
+      map = json.decode(message);
+    } catch (e, st) {
+      Logger.root.severe('Disconnecting: Error decoding message: $e\n$st');
+      disconnect(reason: 'Connection saw corrupt JSON message: $e');
+      return null;
+    }
+    if (map == null) {
+      Logger.root.severe("Disconnecting: Unable to decode 'null' message");
+      disconnect(reason: "Connection saw 'null' message");
+      return null;
+    }
+    return map;
+  }
+
+  void _onBinaryMessage(dynamic data) {
+    _webSocket.nonStringToByteData(data).then((ByteData bytes) {
+      var metadataOffset = 4;
+      var dataOffset = bytes.getUint32(0, Endian.little);
+      var metadataLength = dataOffset - metadataOffset;
+      var dataLength = bytes.lengthInBytes - dataOffset;
+      var metadata = _utf8Decoder.convert(new Uint8List.view(
+          bytes.buffer, bytes.offsetInBytes + metadataOffset, metadataLength));
+      var data = new Uint8List.view(
+          bytes.buffer, bytes.offsetInBytes + dataOffset, dataLength);
+      var map = _parseJSON(metadata);
+      if (map == null || map['method'] != 'streamNotify') {
+        return;
+      }
+      var event = map['params']['event'];
+      var streamId = map['params']['streamId'];
+      scheduleMicrotask(() {
+        postServiceEvent(streamId, event, data);
+      });
+    });
+  }
+
+  void _onStringMessage(String data) {
+    var map = _parseJSON(data);
+    if (map == null) {
+      return;
+    }
+
+    if (map['method'] == 'streamNotify') {
+      var event = map['params']['event'];
+      var streamId = map['params']['streamId'];
+      scheduleMicrotask(() {
+        postServiceEvent(streamId, event, null);
+      });
+      return;
+    }
+
+    // Extract serial and result.
+    var serial = map['id'];
+
+    // Complete request.
+    var request = _pendingRequests.remove(serial);
+    if (request == null) {
+      Logger.root.severe('Received unexpected message: ${map}');
+      return;
+    }
+    if (request.method != 'getTagProfile' &&
+        request.method != 'getIsolateMetric' &&
+        request.method != 'getVMMetric') {
+      Logger.root.info('RESPONSE [${serial}] ${request.method}');
+    }
+
+    var result = map['result'];
+    if (result != null) {
+      request.completer.complete(result);
+    } else {
+      var exception = new ServerRpcException.fromMap(map['error']);
+      request.completer.completeError(exception);
+    }
+  }
+
+  // WebSocket message event handler.
+  void _onMessage(dynamic data) {
+    if (data is! String) {
+      _onBinaryMessage(data);
+    } else {
+      _onStringMessage(data);
+    }
+  }
+
+  void _cancelRequests(
+      Map<String, _WebSocketRequest> requests, String message) {
+    requests.forEach((String serial, _WebSocketRequest request) {
+      var exception = new NetworkRpcException(message +
+          '(id: $serial method: ${request.method} params: ${request.params})');
+      request.completer.completeError(exception);
+    });
+    requests.clear();
+  }
+
+  /// Cancel all pending and delayed requests by completing them with an error.
+  void _cancelAllRequests(String reason) {
+    String message = 'Canceling request: $reason';
+    if (_pendingRequests.length > 0) {
+      Logger.root.info('Canceling all pending requests.');
+      _cancelRequests(_pendingRequests, message);
+    }
+    if (_delayedRequests.length > 0) {
+      Logger.root.info('Canceling all delayed requests.');
+      _cancelRequests(_delayedRequests, message);
+    }
+  }
+
+  /// Send all delayed requests.
+  void _sendAllDelayedRequests() {
+    assert(_webSocket.isOpen);
+    if (_delayedRequests.length == 0) {
+      return;
+    }
+    Logger.root.info('Sending all delayed requests.');
+    // Send all delayed requests.
+    _delayedRequests.forEach(_sendRequest);
+    // Clear all delayed requests.
+    _delayedRequests.clear();
+  }
+
+  /// Send the request over WebSocket.
+  void _sendRequest(String serial, _WebSocketRequest request) {
+    assert(_webSocket.isOpen);
+    // Mark request as pending.
+    assert(_pendingRequests.containsKey(serial) == false);
+    _pendingRequests[serial] = request;
+    var message;
+    // Encode message.
+    if (target.chrome) {
+      message = json.encode({
+        'id': int.parse(serial),
+        'method': 'Dart.observatoryQuery',
+        'params': {'id': serial, 'query': request.method}
+      });
+    } else {
+      message = json.encode({
+        'jsonrpc': '2.0',
+        'id': serial,
+        'method': request.method,
+        'params': request.params
+      });
+    }
+    if (request.method != 'getTagProfile' &&
+        request.method != 'getIsolateMetric' &&
+        request.method != 'getVMMetric') {
+      Logger.root.info(
+          'GET [${serial}] ${request.method}(${request.params}) from ${target.networkAddress}');
+    }
+    // Send message.
+    _webSocket.send(message);
+  }
+
+  String toString() => displayName;
+}
diff --git a/runtime/observatory_2/lib/service_html.dart b/runtime/observatory_2/lib/service_html.dart
new file mode 100644
index 0000000..bb06c69
--- /dev/null
+++ b/runtime/observatory_2/lib/service_html.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library service_html;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:html';
+import 'dart:typed_data';
+
+import 'package:observatory_2/service_common.dart';
+
+// Export the service library.
+export 'package:observatory_2/service_common.dart';
+
+class _HtmlWebSocket implements CommonWebSocket {
+  WebSocket _webSocket;
+
+  Future<void> connect(WebSocketVMTarget target, void onOpen(),
+      void onMessage(dynamic data), void onError(), void onClose()) async {
+    // The VM service will attempt to redirect our websocket connection request
+    // to DDS, but the dart:html WebSocket doesn't follow redirects. Instead of
+    // relying on a redirect, we'll request the websocket URI from the service.
+
+    // TODO(bkonyi): re-enable when DDS is enabled. Currently causing Observatory
+    // failures when running with Flutter (see
+    // https://github.com/flutter/flutter/issues/64333)
+    /*Uri getWebSocketUriRequest = Uri.parse(target.networkAddress);
+    getWebSocketUriRequest =
+        getWebSocketUriRequest.replace(scheme: 'http', pathSegments: [
+      ...getWebSocketUriRequest.pathSegments.where((e) => e != 'ws'),
+      'getWebSocketTarget',
+    ]);
+    final response = json.decode(await HttpRequest.getString(
+      getWebSocketUriRequest.toString(),
+    ));
+    if (!response.containsKey('result') ||
+        !response['result'].containsKey('uri')) {
+      onError();
+      return;
+    }
+    target.networkAddress = response['result']['uri'];
+    */
+    _webSocket = new WebSocket(target.networkAddress);
+    _webSocket.onClose.listen((CloseEvent) => onClose());
+    _webSocket.onError.listen((Event) => onError());
+    _webSocket.onOpen.listen((Event) => onOpen());
+    _webSocket.onMessage.listen((MessageEvent event) => onMessage(event.data));
+  }
+
+  bool get isOpen => _webSocket.readyState == WebSocket.OPEN;
+
+  void send(dynamic data) {
+    _webSocket.send(data);
+  }
+
+  void close() {
+    _webSocket.close();
+  }
+
+  Future<ByteData> nonStringToByteData(dynamic data) {
+    assert(data is Blob);
+    FileReader fileReader = new FileReader();
+    fileReader.readAsArrayBuffer(data);
+    return fileReader.onLoadEnd.first.then((e) {
+      Uint8List result = fileReader.result as Uint8List;
+      return new ByteData.view(
+          result.buffer, result.offsetInBytes, result.length);
+    });
+  }
+}
+
+/// The [WebSocketVM] communicates with a Dart VM over WebSocket. The Dart VM
+/// can be embedded in Chromium or standalone. In the case of Chromium, we
+/// make the service requests via the Chrome Remote Debugging Protocol.
+class WebSocketVM extends CommonWebSocketVM {
+  WebSocketVM(WebSocketVMTarget target) : super(target, new _HtmlWebSocket());
+}
diff --git a/runtime/observatory_2/lib/service_io.dart b/runtime/observatory_2/lib/service_io.dart
new file mode 100644
index 0000000..6b5ad38d
--- /dev/null
+++ b/runtime/observatory_2/lib/service_io.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library service_io;
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:typed_data';
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/service_common.dart';
+
+// Export the service library.
+export 'package:observatory_2/service_common.dart';
+
+class _IOWebSocket implements CommonWebSocket {
+  WebSocket _webSocket;
+
+  Future<void> connect(WebSocketVMTarget target, void onOpen(),
+      void onMessage(dynamic data), void onError(), void onClose()) async {
+    try {
+      _webSocket = await WebSocket.connect(target.networkAddress);
+      _webSocket.listen(onMessage,
+          onError: (dynamic) => onError(),
+          onDone: onClose,
+          cancelOnError: true);
+      onOpen();
+    } catch (_) {
+      onError();
+    }
+  }
+
+  bool get isOpen =>
+      (_webSocket != null) && (_webSocket.readyState == WebSocket.open);
+
+  void send(dynamic data) {
+    _webSocket.add(data);
+  }
+
+  void close() {
+    if (_webSocket != null) {
+      _webSocket.close();
+    }
+  }
+
+  Future<ByteData> nonStringToByteData(dynamic data) {
+    assert(data is Uint8List);
+    Logger.root.info('Binary data size in bytes: ${data.lengthInBytes}');
+    return new Future.sync(() =>
+        new ByteData.view(data.buffer, data.offsetInBytes, data.lengthInBytes));
+  }
+}
+
+/// The [WebSocketVM] communicates with a Dart VM over WebSocket.
+class WebSocketVM extends CommonWebSocketVM {
+  WebSocketVM(WebSocketVMTarget target) : super(target, new _IOWebSocket());
+}
diff --git a/runtime/observatory_2/lib/src/allocation_profile/allocation_profile.dart b/runtime/observatory_2/lib/src/allocation_profile/allocation_profile.dart
new file mode 100644
index 0000000..c1e7aa1
--- /dev/null
+++ b/runtime/observatory_2/lib/src/allocation_profile/allocation_profile.dart
@@ -0,0 +1,90 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of allocation_profiler;
+
+class AllocationProfile implements M.AllocationProfile {
+  static const _lastServiceGC = 'dateLastServiceGC';
+  final DateTime lastServiceGC;
+  static const _lastAccumulatorReset = 'dateLastAccumulatorReset';
+  final DateTime lastAccumulatorReset;
+  final S.HeapSpace newSpace;
+  final S.HeapSpace oldSpace;
+  final S.HeapSpace totalSpace;
+  final Iterable<M.ClassHeapStats> members;
+
+  AllocationProfile(S.ServiceMap map, {Map/*<String, List<String>>*/ defaults})
+      : lastAccumulatorReset = _intString2DateTime(map[_lastAccumulatorReset]),
+        lastServiceGC = _intString2DateTime(map[_lastServiceGC]),
+        oldSpace = new S.HeapSpace()..update(map['_heaps']['old']),
+        newSpace = new S.HeapSpace()..update(map['_heaps']['new']),
+        totalSpace = new S.HeapSpace(),
+        members = _convertMembers(map['members'], defaults: defaults) {
+    totalSpace.add(oldSpace);
+    totalSpace.add(newSpace);
+  }
+
+  static DateTime _intString2DateTime(String milliseconds) {
+    if ((milliseconds == null) || milliseconds == '') {
+      return null;
+    }
+    return new DateTime.fromMillisecondsSinceEpoch(int.parse(milliseconds));
+  }
+
+  static ClassHeapStats _convertMember(/*S.ServiceMap*/ map) {
+    assert(map['type'] == 'ClassHeapStats');
+    return new ClassHeapStats(map);
+  }
+
+  static List<M.ClassHeapStats> _convertMembers(Iterable/*<S.ServiceMap>*/ raw,
+      {Map/*<String, List<String>>*/ defaults}) {
+    final List<M.ClassHeapStats> members =
+        raw.map<ClassHeapStats>(_convertMember).toList();
+    if (defaults == null) {
+      return members;
+    }
+    final Map<String, List<ClassHeapStats>> aliases =
+        new Map.fromIterable(defaults.keys, value: (_) => <ClassHeapStats>[]);
+    final Map<String, List<ClassHeapStats>> accumulators =
+        <String, List<ClassHeapStats>>{};
+    defaults.forEach((/*String*/ key, /*List<String>*/ values) {
+      final classes = aliases[key];
+      accumulators.addAll(new Map.fromIterable(values, value: (_) => classes));
+    });
+    final List<M.ClassHeapStats> result = <M.ClassHeapStats>[];
+    members.forEach((M.ClassHeapStats member) {
+      if (accumulators.containsKey(member.clazz.id)) {
+        accumulators[member.clazz.id].add(member);
+      } else {
+        result.add(member);
+      }
+    });
+    return result
+      ..addAll(
+          aliases.keys.map((key) => new ClassesHeapStats(key, aliases[key])));
+  }
+}
+
+class ClassHeapStats implements M.ClassHeapStats {
+  final S.Class clazz;
+  final String displayName = null;
+  final S.Allocations newSpace;
+  final S.Allocations oldSpace;
+
+  ClassHeapStats(Map map)
+      : clazz = map['class'],
+        oldSpace = new S.Allocations()..update(map['_old']),
+        newSpace = new S.Allocations()..update(map['_new']);
+}
+
+class ClassesHeapStats implements M.ClassHeapStats {
+  final S.Class clazz = null;
+  final String displayName;
+  final S.Allocations newSpace;
+  final S.Allocations oldSpace;
+
+  ClassesHeapStats(this.displayName, Iterable<ClassHeapStats> classes)
+      : oldSpace = new S.Allocations()..combine(classes.map((m) => m.oldSpace)),
+        newSpace = new S.Allocations()..combine(classes.map((m) => m.newSpace));
+}
diff --git a/runtime/observatory_2/lib/src/app/analytics.dart b/runtime/observatory_2/lib/src/app/analytics.dart
new file mode 100644
index 0000000..a34c2da
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/analytics.dart
@@ -0,0 +1,38 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+// TODO(eernst): Use 'bool.fromEnvironment' below when possible;
+// for now we use a dual `defaultValue` rewrite.
+const _obsVer = (String.fromEnvironment('OBS_VER', defaultValue: '1') ==
+        String.fromEnvironment('OBS_VER', defaultValue: '2'))
+    ? String.fromEnvironment('OBS_VER')
+    : null;
+
+class Analytics {
+  static final _UA = 'UA-26406144-17';
+  static final _name = 'Observatory';
+  static final _version = _obsVer;
+  static final _googleAnalytics = new AnalyticsHtml(_UA, _name, _version);
+
+  static initialize() {
+    // We only send screen views. This is allowed without user permission.
+    // Note, before flipping this to be true we need a UI to allow users to
+    // control this.
+    _googleAnalytics.analyticsOpt = AnalyticsOpt.optOut;
+  }
+
+  /// Called whenever an Observatory page is viewed.
+  static Future reportPageView(Uri uri) {
+    // Only report analytics when running in JavaScript.
+    if (Utils.runningInJavaScript()) {
+      // The screen name is the uri's path. e.g. inspect, profile.
+      final screenName = uri.path;
+      return _googleAnalytics.sendScreenView(screenName);
+    } else {
+      return new Future.value(null);
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/app/application.dart b/runtime/observatory_2/lib/src/app/application.dart
new file mode 100644
index 0000000..768c3b4
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/application.dart
@@ -0,0 +1,294 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+/// The observatory application. Instances of this are created and owned
+/// by the observatory_application custom element.
+class ObservatoryApplication {
+  static ObservatoryApplication app;
+  final RenderingQueue queue = new RenderingQueue();
+  final TargetRepository targets = new TargetRepository(isConnectedVMTarget);
+  final EventRepository events = new EventRepository();
+  final NotificationRepository notifications = new NotificationRepository();
+  final _pageRegistry = <Page>[];
+  LocationManager _locationManager;
+  LocationManager get locationManager => _locationManager;
+  Page currentPage;
+  bool _vmConnected = false;
+  VM _vm;
+  VM get vm => _vm;
+
+  static bool isConnectedVMTarget(M.Target target) {
+    if (app._vm is CommonWebSocketVM) {
+      if ((app._vm as CommonWebSocketVM).target == target) {
+        return app._vm.isConnected;
+      }
+    }
+    return false;
+  }
+
+  _switchVM(VM newVM) {
+    final VM oldVM = _vm;
+
+    Logger.root.info('_switchVM from:${oldVM} to:${newVM}');
+
+    if (oldVM == newVM) {
+      // Do nothing.
+      return;
+    }
+
+    if (oldVM != null) {
+      print('disconnecting from the old VM ${oldVM}--');
+      // Disconnect from current VM.
+      stopGCEventListener();
+      notifications.deleteAll();
+      oldVM.disconnect();
+    }
+
+    if (newVM != null) {
+      // Mark that we haven't connected yet.
+      _vmConnected = false;
+      // On connect:
+      newVM.onConnect.then((_) async {
+        // We connected.
+        _vmConnected = true;
+        notifications.deleteDisconnectEvents();
+        await newVM.load();
+        // TODO(cbernaschina) smart connection of streams in the events object.
+        newVM.listenEventStream(VM.kVMStream, _onEvent);
+        newVM.listenEventStream(VM.kIsolateStream, _onEvent);
+        newVM.listenEventStream(VM.kDebugStream, _onEvent);
+        newVM.listenEventStream(VM.kServiceStream, _onEvent);
+      });
+      // On disconnect:
+      newVM.onDisconnect.then((String reason) {
+        if (this.vm != newVM) {
+          // This disconnect event occurred *after* a new VM was installed.
+          return;
+        }
+        // Let anyone looking at the targets know that we have disconnected
+        // from one.
+        targets.emitDisconnectEvent();
+        if (!_vmConnected) {
+          // Connection error. Navigate back to the connect page.
+          Logger.root.info('Connection failed, navigating to VM connect page.');
+          // Clear the vm.
+          _vm = null;
+          app.locationManager.go(Uris.vmConnect());
+        } else {
+          // Disconnect. Stay at the current page and push an a connection
+          // closed event.
+          Logger.root.info('Lost an existing connection to a VM');
+          events.add(new ConnectionClosedEvent(new DateTime.now(), reason));
+        }
+      });
+    }
+
+    _vm = newVM;
+  }
+
+  StreamSubscription _gcSubscription;
+  StreamSubscription _loggingSubscription;
+
+  Future startGCEventListener() async {
+    if (_gcSubscription != null || _vm == null) {
+      return;
+    }
+    _gcSubscription = await _vm.listenEventStream(VM.kGCStream, _onEvent);
+  }
+
+  Future startLoggingEventListener() async {
+    if (_loggingSubscription != null || _vm == null) {
+      return;
+    }
+    _loggingSubscription =
+        await _vm.listenEventStream(Isolate.kLoggingStream, _onEvent);
+  }
+
+  Future stopGCEventListener() async {
+    if (_gcSubscription == null) {
+      return;
+    }
+    _gcSubscription.cancel();
+    _gcSubscription = null;
+  }
+
+  Future stopLoggingEventListener() async {
+    if (_loggingSubscription == null) {
+      return;
+    }
+    _loggingSubscription.cancel();
+    _loggingSubscription = null;
+  }
+
+  final ObservatoryApplicationElement rootElement;
+
+  ServiceObject lastErrorOrException;
+
+  void _initOnce() {
+    assert(app == null);
+    app = this;
+    _registerPages();
+    // Visit the current page.
+    locationManager._visit();
+  }
+
+  void _deletePauseEvents(e) {
+    notifications.deletePauseEvents(isolate: e.isolate);
+  }
+
+  void _addNotification(M.Event e) {
+    notifications.add(new EventNotification(e));
+  }
+
+  void _onEvent(ServiceEvent event) {
+    assert(event.kind != ServiceEvent.kNone);
+    M.Event e = createEventFromServiceEvent(event);
+    if (e != null) {
+      events.add(e);
+    }
+  }
+
+  void _registerPages() {
+    _pageRegistry.add(new VMPage(this));
+    _pageRegistry.add(new FlagsPage(this));
+    _pageRegistry.add(new NativeMemoryProfilerPage(this));
+    _pageRegistry.add(new InspectPage(this));
+    _pageRegistry.add(new ClassTreePage(this));
+    _pageRegistry.add(new DebuggerPage(this));
+    _pageRegistry.add(new ObjectStorePage(this));
+    _pageRegistry.add(new CpuProfilerPage(this));
+    _pageRegistry.add(new TableCpuProfilerPage(this));
+    _pageRegistry.add(new AllocationProfilerPage(this));
+    _pageRegistry.add(new HeapMapPage(this));
+    _pageRegistry.add(new HeapSnapshotPage(this));
+    _pageRegistry.add(new VMConnectPage(this));
+    _pageRegistry.add(new IsolateReconnectPage(this));
+    _pageRegistry.add(new ErrorViewPage(this));
+    _pageRegistry.add(new MetricsPage(this));
+    _pageRegistry.add(new PersistentHandlesPage(this));
+    _pageRegistry.add(new PortsPage(this));
+    _pageRegistry.add(new LoggingPage(this));
+    _pageRegistry.add(new TimelinePage(this));
+    _pageRegistry.add(new TimelineDashboardPage(this));
+    _pageRegistry.add(new ProcessSnapshotPage(this));
+    // Note that ErrorPage must be the last entry in the list as it is
+    // the catch all.
+    _pageRegistry.add(new ErrorPage(this));
+  }
+
+  void _visit(Uri uri, Map internalArguments) {
+    if (internalArguments['trace'] != null) {
+      var traceArg = internalArguments['trace'];
+      if (traceArg == 'on') {
+        Tracer.start();
+      } else if (traceArg == 'off') {
+        Tracer.stop();
+      }
+    }
+    if (Tracer.current != null) {
+      Tracer.current.reset();
+    }
+    for (var i = 0; i < _pageRegistry.length; i++) {
+      var page = _pageRegistry[i];
+      if (page.canVisit(uri)) {
+        _installPage(page);
+        page.visit(uri, internalArguments);
+        return;
+      }
+    }
+    throw new ArgumentError.value(uri, 'uri');
+  }
+
+  /// Set the Observatory application page.
+  void _installPage(Page page) {
+    assert(page != null);
+    if (currentPage == page) {
+      // Already installed.
+      return;
+    }
+    if (currentPage != null) {
+      Logger.root.info('Uninstalling page: $currentPage');
+      currentPage.onUninstall();
+      // Clear children.
+      rootElement.children.clear();
+    }
+    Logger.root.info('Installing page: $page');
+    try {
+      page.onInstall();
+    } catch (e) {
+      Logger.root.severe('Failed to install page: $e');
+    }
+    // Add new page.
+    rootElement.children.add(page.element);
+
+    // Remember page.
+    currentPage = page;
+  }
+
+  ObservatoryApplication(this.rootElement) {
+    _locationManager = new LocationManager(this);
+    targets.onChange.listen((TargetChangeEvent e) {
+      if (e.disconnected) {
+        // We don't care about disconnected events.
+        return;
+      }
+      if (targets.current == null) {
+        _switchVM(null);
+      } else {
+        final bool currentTarget =
+            (_vm as WebSocketVM)?.target == targets.current;
+        final bool currentTargetConnected = (_vm != null) && _vm.isConnected;
+        if (!currentTarget || !currentTargetConnected) {
+          _switchVM(new WebSocketVM(targets.current));
+          _vm.onConnect.then((_) {
+            app.locationManager.go(Uris.vm());
+          });
+          _vm.load();
+        } else if (currentTargetConnected) {
+          app.locationManager.go(Uris.vm());
+        }
+      }
+    });
+
+    Logger.root.info('Setting initial target to ${targets.current.name}');
+    _switchVM(new WebSocketVM(targets.current));
+    _initOnce();
+
+    // delete pause events.
+    events.onIsolateExit.listen(_deletePauseEvents);
+    events.onResume.listen(_deletePauseEvents);
+    events.onPauseStart.listen(_deletePauseEvents);
+    events.onPauseExit.listen(_deletePauseEvents);
+    events.onPauseBreakpoint.listen(_deletePauseEvents);
+    events.onPauseInterrupted.listen(_deletePauseEvents);
+    events.onPauseException.listen(_deletePauseEvents);
+
+    // show notification for an event.
+    events.onIsolateReload.listen(_addNotification);
+    events.onPauseExit.listen(_addNotification);
+    events.onPauseBreakpoint.listen(_addNotification);
+    events.onPauseInterrupted.listen(_addNotification);
+    events.onPauseException.listen(_addNotification);
+    events.onInspect.listen(_addNotification);
+    events.onConnectionClosed.listen(_addNotification);
+  }
+
+  void handleException(e, st) {
+    if (e is ServerRpcException) {
+      if (e.code == ServerRpcException.kFeatureDisabled) return;
+      if (e.code == ServerRpcException.kIsolateMustBePaused) return;
+      if (e.code == ServerRpcException.kCannotAddBreakpoint) return;
+      Logger.root.fine('Dropping exception: ${e}\n${st}');
+    }
+
+    // TODO(turnidge): Report this failure via analytics.
+    Logger.root.warning('Caught exception: ${e}\n${st}');
+    notifications.add(new ExceptionNotification(e, stacktrace: st));
+  }
+
+  // This map keeps track of which curly-blocks have been expanded by the user.
+  Map<String, bool> expansions = {};
+}
diff --git a/runtime/observatory_2/lib/src/app/location_manager.dart b/runtime/observatory_2/lib/src/app/location_manager.dart
new file mode 100644
index 0000000..a0e1af1
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/location_manager.dart
@@ -0,0 +1,167 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+class LocationManager {
+  final ObservatoryApplication _app;
+
+  /// [internalArguments] are parameters specified after a '---' in the
+  /// application URL.
+  final Map<String, String> internalArguments = new Map<String, String>();
+
+  Uri _uri;
+
+  /// [uri] is the application uri. Application uris consist of a path and
+  /// the queryParameters map.
+  Uri get uri => _uri;
+
+  LocationManager(this._app) {
+    window.onPopState.listen(_onBrowserNavigation);
+    // Determine initial application path.
+    var applicationPath = '${window.location.hash}';
+    if ((window.location.hash == '') || (window.location.hash == '#')) {
+      // Observatory has loaded but no application path has been specified,
+      // use the default.
+      // By default we navigate to the VM page.
+      applicationPath = Uris.vm();
+    }
+    // Update current application path.
+    window.history
+        .replaceState(applicationPath, document.title, applicationPath);
+    _updateApplicationLocation(applicationPath);
+  }
+
+  bool getBoolParameter(String name, bool defaultValue) {
+    var value = uri.queryParameters[name];
+    if ("true" == value) return true;
+    if ("false" == value) return false;
+    return defaultValue;
+  }
+
+  /// Called whenever the browser changes the location bar (e.g. forward or
+  /// back button press).
+  void _onBrowserNavigation(PopStateEvent event) {
+    _updateApplicationLocation(window.location.hash);
+    _visit();
+  }
+
+  /// Given an application url, generate an href link.
+  String makeLink(String url) => '#$url';
+
+  /// Update the application location. After this function returns,
+  /// [uri] and [debugArguments] will be updated.
+  _updateApplicationLocation(String url) {
+    if (url == Uris.vmConnect()) {
+      // When we go to the vm-connect page, drop all notifications.
+      _app.notifications.deleteAll();
+    }
+
+    // Chop off leading '#'.
+    if (url.startsWith('#')) {
+      url = url.substring(1);
+    }
+    // Fall through handles '#/'
+    // Chop off leading '/'.
+    if (url.startsWith('/')) {
+      url = url.substring(1);
+    }
+    // Parse out debug arguments.
+    if (url.contains('---')) {
+      var chunks = url.split('---');
+      url = chunks[0];
+      if ((chunks.length > 1) && (chunks[1] != '')) {
+        internalArguments.clear();
+        try {
+          internalArguments.addAll(Uri.splitQueryString(chunks[1]));
+        } catch (e) {
+          Logger.root.warning('Could not parse debug arguments ${e}');
+        }
+      }
+    }
+    _uri = Uri.parse(url);
+  }
+
+  /// Add [url] to the browser history.
+  _addToBrowserHistory(String url) {
+    window.history.pushState(url, document.title, url);
+  }
+
+  /// Notify the current page that something has changed.
+  _visit() {
+    Chain.capture(() => _app._visit(_uri, internalArguments), onError: (e, st) {
+      if (e is IsolateNotFound) {
+        var newPath = ((_app.vm == null || _app.vm.isDisconnected)
+            ? '/vm-connect'
+            : '/isolate-reconnect');
+        var parameters = <String, dynamic>{};
+        parameters.addAll(_uri.queryParameters);
+        parameters['originalUri'] = _uri.toString();
+        parameters['isolateId'] = parameters['isolateId'];
+        var generatedUri = new Uri(path: newPath, queryParameters: parameters);
+        go(makeLink(generatedUri.toString()), true);
+        return;
+      }
+      // Surface any uncaught exceptions.
+      _app.handleException(e, st);
+    });
+  }
+
+  /// Navigate to [url].
+  void go(String url, [bool addToBrowserHistory = true]) {
+    if (addToBrowserHistory) {
+      _addToBrowserHistory(url);
+    }
+    _updateApplicationLocation(url);
+    _visit();
+  }
+
+  /// Starting with the current uri path and queryParameters, update
+  /// queryParameters present in [updateParameters], then generate a new uri
+  /// and navigate to that.
+  goReplacingParameters(Map updatedParameters,
+      [bool addToBrowserHistory = true]) {
+    go(makeLinkReplacingParameters(updatedParameters), addToBrowserHistory);
+  }
+
+  makeLinkReplacingParameters(Map updatedParameters) {
+    var parameters = new Map.from(_uri.queryParameters);
+    updatedParameters.forEach((k, v) {
+      parameters[k] = v;
+    });
+    // Ensure path starts with a slash.
+    var path = uri.path.startsWith('/') ? uri.path : '/${uri.path}';
+    var generatedUri = new Uri(path: path, queryParameters: parameters);
+    return makeLink(generatedUri.toString());
+  }
+
+  goForwardingParameters(String newPath, [bool addToBrowserHistory = true]) {
+    go(makeLinkForwardingParameters(newPath), addToBrowserHistory);
+  }
+
+  makeLinkForwardingParameters(String newPath) {
+    var parameters = _uri.queryParameters;
+    var generatedUri = new Uri(path: newPath, queryParameters: parameters);
+    return makeLink(generatedUri.toString());
+  }
+
+  /// Utility event handler when clicking on application url link.
+  void onGoto(MouseEvent event) {
+    if ((event.button > 0) ||
+        event.metaKey ||
+        event.ctrlKey ||
+        event.shiftKey ||
+        event.altKey) {
+      // Mouse event is not a left-click OR
+      // mouse event is a left-click with a modifier key:
+      // let browser handle.
+      return;
+    }
+    event.preventDefault();
+    // 'currentTarget' is the dom element that would process the event.
+    // If we use 'target' we might get an <em> element or somesuch.
+    Element target = event.currentTarget;
+    go(target.attributes['href']);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/app/notification.dart b/runtime/observatory_2/lib/src/app/notification.dart
new file mode 100644
index 0000000..1f5f9d7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/notification.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+class ExceptionNotification implements M.ExceptionNotification {
+  final exception;
+
+  /// [optional]
+  final StackTrace stacktrace;
+  ExceptionNotification(this.exception, {this.stacktrace});
+}
+
+class EventNotification implements M.EventNotification {
+  final M.Event event;
+  EventNotification(this.event);
+}
diff --git a/runtime/observatory_2/lib/src/app/page.dart b/runtime/observatory_2/lib/src/app/page.dart
new file mode 100644
index 0000000..a366acf
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/page.dart
@@ -0,0 +1,1024 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+final _allocationProfileRepository = new AllocationProfileRepository();
+final _breakpointRepository = new BreakpointRepository();
+final _classRepository = new ClassRepository();
+final _classSampleProfileRepository = new ClassSampleProfileRepository();
+final _contextRepository = new ContextRepository();
+final _evalRepository = new EvalRepository();
+final _fieldRepository = new FieldRepository();
+final _functionRepository = new FunctionRepository();
+final _heapSnapshotRepository = new HeapSnapshotRepository();
+final _icdataRepository = new ICDataRepository();
+final _inboundReferencesRepository = new InboundReferencesRepository();
+final _isolateSampleProfileRepository = new IsolateSampleProfileRepository();
+final _libraryRepository = new LibraryRepository();
+final _megamorphicCacheRepository = new MegamorphicCacheRepository();
+final _metricRepository = new MetricRepository();
+final _nativeMemorySampleProfileRepository =
+    new NativeMemorySampleProfileRepository();
+final _objectPoolRepository = new ObjectPoolRepository();
+final _objectRepository = new ObjectRepository();
+final _objectstoreRepository = new ObjectStoreRepository();
+final _persistentHandlesRepository = new PersistentHandlesRepository();
+final _portsRepository = new PortsRepository();
+final _scriptRepository = new ScriptRepository();
+final _singleTargetCacheRepository = new SingleTargetCacheRepository();
+final _stronglyReachangleInstancesRepository =
+    new StronglyReachableInstancesRepository();
+final _subtypeTestCacheRepository = new SubtypeTestCacheRepository();
+final _timelineRepository = new TimelineRepository();
+final _typeArgumentsRepository = new TypeArgumentsRepository();
+final _unlinkedCallRepository = new UnlinkedCallRepository();
+final _vmrepository = new VMRepository();
+
+class IsolateNotFound implements Exception {
+  String isolateId;
+  IsolateNotFound(this.isolateId);
+  String toString() => "IsolateNotFound: $isolateId";
+}
+
+RetainedSizeRepository _retainedSizeRepository = new RetainedSizeRepository();
+ReachableSizeRepository _reachableSizeRepository =
+    new ReachableSizeRepository();
+RetainingPathRepository _retainingPathRepository =
+    new RetainingPathRepository();
+
+/// A [Page] controls the user interface of Observatory. At any given time
+/// one page will be the current page. Pages are registered at startup.
+/// When the user navigates within the application, each page is asked if it
+/// can handle the current location, the first page to say yes, wins.
+abstract class Page {
+  final ObservatoryApplication app;
+  final Map<String, String> internalArguments = <String, String>{};
+  HtmlElement element;
+
+  Page(this.app);
+
+  /// Called when the page is installed, this callback must initialize
+  /// [element].
+  void onInstall();
+
+  /// Called when the page is uninstalled, this callback must clear
+  /// [element].
+  void onUninstall() {
+    element = null;
+  }
+
+  /// Called when the page should update its state based on [uri].
+  void visit(Uri uri, Map internalArguments) {
+    this.internalArguments.clear();
+    this.internalArguments.addAll(internalArguments);
+    _visit(uri);
+  }
+
+  // Overridden by subclasses.
+  void _visit(Uri uri);
+
+  /// Called to test whether this page can visit [uri].
+  bool canVisit(Uri uri);
+}
+
+/// A [MatchingPage] matches a single uri path.
+abstract class MatchingPage extends Page {
+  final String path;
+  MatchingPage(this.path, app) : super(app);
+
+  void _visit(Uri uri) {
+    assert(uri != null);
+    assert(canVisit(uri));
+  }
+
+  Future<Isolate> getIsolate(Uri uri) {
+    var isolateId = uri.queryParameters['isolateId'];
+    return app.vm.getIsolate(isolateId).then((isolate) {
+      if (isolate == null) {
+        throw new IsolateNotFound(isolateId);
+      }
+      return isolate;
+    });
+  }
+
+  EditorRepository getEditor(Uri uri) {
+    final editor = uri.queryParameters['editor'];
+    return new EditorRepository(app.vm, editor: editor);
+    return null;
+  }
+
+  bool canVisit(Uri uri) => uri.path == path;
+}
+
+/// A [SimplePage] matches a single uri path and displays a single element.
+class SimplePage extends MatchingPage {
+  final String elementTagName;
+  SimplePage(String path, this.elementTagName, app) : super(path, app);
+
+  void onInstall() {
+    if (element == null) {
+      element = new Element.tag(elementTagName);
+    }
+  }
+}
+
+/// Error page for unrecognized paths.
+class ErrorPage extends Page {
+  ErrorPage(app) : super(app);
+
+  void onInstall() {
+    if (element == null) {
+      // Lazily create page.
+      element =
+          new GeneralErrorElement(app.notifications, queue: app.queue).element;
+    }
+  }
+
+  void _visit(Uri uri) {
+    assert(element != null);
+    assert(canVisit(uri));
+
+    (element as GeneralErrorElement).message = "Path '${uri.path}' not found";
+  }
+
+  /// Catch all.
+  bool canVisit(Uri uri) => true;
+}
+
+/// Top-level vm info page.
+class VMPage extends MatchingPage {
+  VMPage(app) : super('vm', app);
+
+  final DivElement container = new DivElement();
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    if (app.vm == null) {
+      Logger.root.severe('VMPage has no VM');
+      // Reroute to vm-connect.
+      app.locationManager.go(Uris.vmConnect());
+      return;
+    }
+    app.vm.reload().then((serviceObject) {
+      VM vm = serviceObject;
+      container.children = <Element>[
+        new VMViewElement(
+                vm,
+                _vmrepository,
+                app.events,
+                app.notifications,
+                new IsolateRepository(app.vm),
+                new IsolateGroupRepository(app.vm),
+                _scriptRepository,
+                queue: app.queue)
+            .element
+      ];
+    }).catchError((e, stack) {
+      Logger.root.severe('VMPage visit error: $e');
+      Logger.root.severe('Stack: $stack');
+      // Reroute to vm-connect.
+      app.locationManager.go(Uris.vmConnect());
+    });
+  }
+}
+
+class FlagsPage extends SimplePage {
+  FlagsPage(app) : super('flags', 'flag-list', app);
+
+  @override
+  onInstall() {
+    element = new FlagListElement(
+            app.vm, app.events, new FlagsRepository(app.vm), app.notifications,
+            queue: app.queue)
+        .element;
+  }
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+  }
+}
+
+class NativeMemoryProfilerPage extends SimplePage {
+  NativeMemoryProfilerPage(app)
+      : super('native-memory-profile', 'native-memory-profile', app);
+  @override
+  onInstall() {
+    if (element == null) {
+      element = new NativeMemoryProfileElement(app.vm, app.events,
+              app.notifications, _nativeMemorySampleProfileRepository,
+              queue: app.queue)
+          .element;
+    }
+    assert(element != null);
+  }
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+  }
+}
+
+class InspectPage extends MatchingPage {
+  InspectPage(app) : super('inspect', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      var objectId = uri.queryParameters['objectId'];
+      if (objectId == null) {
+        isolate.reload().then(_visitObject);
+      } else {
+        isolate.getObject(objectId).then(_visitObject);
+      }
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+
+  Future _visitObject(obj) async {
+    container.children = <Element>[];
+    await obj.reload();
+    if (obj is Class) {
+      container.children = <Element>[
+        new ClassViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _fieldRepository,
+                _scriptRepository,
+                _objectRepository,
+                _evalRepository,
+                _stronglyReachangleInstancesRepository,
+                _classSampleProfileRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Code) {
+      await obj.loadScript();
+      container.children = <Element>[
+        new CodeViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Context) {
+      container.children = <Element>[
+        new ContextViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _contextRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is DartError) {
+      container.children = <Element>[
+        new ErrorViewElement(app.notifications, obj, queue: app.queue).element
+      ];
+    } else if (obj is Field) {
+      container.children = <Element>[
+        new FieldViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _fieldRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Instance) {
+      container.children = <Element>[
+        new InstanceViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _evalRepository,
+                _typeArgumentsRepository,
+                _breakpointRepository,
+                _functionRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Isolate) {
+      container.children = <Element>[
+        new IsolateViewElement(
+                app.vm,
+                obj,
+                app.events,
+                app.notifications,
+                new IsolateRepository(app.vm),
+                _scriptRepository,
+                _functionRepository,
+                _libraryRepository,
+                _objectRepository,
+                _evalRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is ServiceFunction) {
+      container.children = <Element>[
+        new FunctionViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _functionRepository,
+                _classRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is ICData) {
+      container.children = <Element>[
+        new ICDataViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _icdataRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is SingleTargetCache) {
+      container.children = <Element>[
+        new SingleTargetCacheViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _singleTargetCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is SubtypeTestCache) {
+      container.children = <Element>[
+        new SubtypeTestCacheViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _subtypeTestCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is UnlinkedCall) {
+      container.children = <Element>[
+        new UnlinkedCallViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _unlinkedCallRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Library) {
+      container.children = <Element>[
+        new LibraryViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _libraryRepository,
+                _fieldRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _scriptRepository,
+                _objectRepository,
+                _evalRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is MegamorphicCache) {
+      container.children = <Element>[
+        new MegamorphicCacheViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _megamorphicCacheRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is ObjectPool) {
+      container.children = <Element>[
+        new ObjectPoolViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectPoolRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Script) {
+      var pos;
+      if (app.locationManager.internalArguments['pos'] != null) {
+        try {
+          pos = int.parse(app.locationManager.internalArguments['pos']);
+        } catch (_) {}
+      }
+      container.children = <Element>[
+        new ScriptViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _scriptRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                _objectRepository,
+                pos: pos,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is HeapObject) {
+      container.children = <Element>[
+        new ObjectViewElement(
+                app.vm,
+                obj.isolate,
+                obj,
+                app.events,
+                app.notifications,
+                _objectRepository,
+                _retainedSizeRepository,
+                _reachableSizeRepository,
+                _inboundReferencesRepository,
+                _retainingPathRepository,
+                queue: app.queue)
+            .element
+      ];
+    } else if (obj is Sentinel) {
+      container.children = <Element>[
+        new SentinelViewElement(
+                app.vm, obj.isolate, obj, app.events, app.notifications,
+                queue: app.queue)
+            .element
+      ];
+    } else {
+      container.children = <Element>[
+        new JSONViewElement(obj, app.notifications, queue: app.queue).element
+      ];
+    }
+  }
+}
+
+/// Class tree page.
+class ClassTreePage extends SimplePage {
+  ClassTreePage(app) : super('class-tree', 'class-tree', app);
+
+  final DivElement container = new DivElement();
+
+  @override
+  void onInstall() {
+    element = container;
+  }
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new ClassTreeElement(app.vm, isolate, app.events, app.notifications,
+                _classRepository)
+            .element
+      ];
+    });
+  }
+}
+
+class DebuggerPage extends MatchingPage {
+  DebuggerPage(app) : super('debugger', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) async {
+      container.children = <Element>[
+        new DebuggerPageElement(
+                isolate, _objectRepository, _scriptRepository, app.events)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+
+  @override
+  void onUninstall() {
+    super.onUninstall();
+    container.children = const [];
+  }
+}
+
+class ObjectStorePage extends MatchingPage {
+  ObjectStorePage(app) : super('object-store', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) async {
+      container.children = <Element>[
+        new ObjectStoreViewElement(isolate.vm, isolate, app.events,
+                app.notifications, _objectstoreRepository, _objectRepository)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+}
+
+class CpuProfilerPage extends MatchingPage {
+  CpuProfilerPage(app) : super('profiler', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new CpuProfileElement(isolate.vm, isolate, app.events,
+                app.notifications, _isolateSampleProfileRepository)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+}
+
+class TableCpuProfilerPage extends MatchingPage {
+  TableCpuProfilerPage(app) : super('profiler-table', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new CpuProfileTableElement(isolate.vm, isolate, app.events,
+                app.notifications, _isolateSampleProfileRepository)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    assert(element != null);
+  }
+}
+
+class AllocationProfilerPage extends MatchingPage {
+  AllocationProfilerPage(app) : super('allocation-profiler', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new AllocationProfileElement(isolate.vm, isolate, app.events,
+                app.notifications, _allocationProfileRepository,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+    app.startGCEventListener();
+  }
+
+  @override
+  void onUninstall() {
+    super.onUninstall();
+    app.stopGCEventListener();
+    container.children = const [];
+  }
+}
+
+class PortsPage extends MatchingPage {
+  PortsPage(app) : super('ports', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new PortsElement(isolate.vm, isolate, app.events, app.notifications,
+                _portsRepository, _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+}
+
+class PersistentHandlesPage extends MatchingPage {
+  PersistentHandlesPage(app) : super('persistent-handles', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new PersistentHandlesPageElement(
+                isolate.vm,
+                isolate,
+                app.events,
+                app.notifications,
+                _persistentHandlesRepository,
+                _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+}
+
+class HeapMapPage extends MatchingPage {
+  HeapMapPage(app) : super('heap-map', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new HeapMapElement(isolate.vm, isolate, app.events, app.notifications,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+}
+
+class HeapSnapshotPage extends MatchingPage {
+  HeapSnapshotPage(app) : super('heap-snapshot', app);
+
+  final DivElement container = new DivElement();
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new HeapSnapshotElement(isolate.vm, isolate, app.events,
+                app.notifications, _heapSnapshotRepository, _objectRepository,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+}
+
+class LoggingPage extends MatchingPage {
+  LoggingPage(app) : super('logging', app);
+
+  final DivElement container = new DivElement();
+
+  @override
+  void onInstall() {
+    element = container;
+    container.children = const [];
+    app.startLoggingEventListener();
+  }
+
+  @override
+  void onUninstall() {
+    super.onUninstall();
+    container.children = const [];
+    app.stopLoggingEventListener();
+  }
+
+  void _visit(Uri uri) {
+    assert(element != null);
+    assert(canVisit(uri));
+    getIsolate(uri).then((isolate) {
+      container.children = <Element>[
+        new LoggingPageElement(app.vm, isolate, app.events, app.notifications,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+}
+
+class ErrorViewPage extends Page {
+  ErrorViewPage(app) : super(app);
+
+  void onInstall() {
+    element = new ErrorViewElement(
+            app.notifications, app.lastErrorOrException as DartError,
+            queue: app.queue)
+        .element;
+  }
+
+  void _visit(Uri uri) {
+    assert(element != null);
+    assert(canVisit(uri));
+  }
+
+  // TODO(turnidge): How to test this page?
+  bool canVisit(Uri uri) => uri.path == 'error';
+}
+
+class VMConnectPage extends Page {
+  VMConnectPage(app) : super(app);
+
+  void onInstall() {
+    if (element == null) {
+      element = new VMConnectElement(ObservatoryApplication.app.targets,
+              ObservatoryApplication.app.notifications,
+              queue: ObservatoryApplication.app.queue)
+          .element;
+    }
+    assert(element != null);
+  }
+
+  void _visit(Uri uri) {
+    assert(element != null);
+    assert(canVisit(uri));
+  }
+
+  bool canVisit(Uri uri) => uri.path == 'vm-connect';
+}
+
+class IsolateReconnectPage extends Page {
+  IsolateReconnectPage(app) : super(app);
+
+  final DivElement container = new DivElement();
+
+  void onInstall() {
+    element = container;
+  }
+
+  void _visit(Uri uri) {
+    app.vm.reload();
+    container.children = <Element>[
+      new IsolateReconnectElement(
+              app.vm,
+              app.events,
+              app.notifications,
+              uri.queryParameters['isolateId'],
+              Uri.parse(uri.queryParameters['originalUri']))
+          .element
+    ];
+    assert(element != null);
+    assert(canVisit(uri));
+  }
+
+  bool canVisit(Uri uri) => uri.path == 'isolate-reconnect';
+}
+
+class MetricsPage extends MatchingPage {
+  MetricsPage(app) : super('metrics', app);
+
+  final DivElement container = new DivElement();
+
+  Isolate lastIsolate;
+
+  void _visit(Uri uri) {
+    super._visit(uri);
+    getIsolate(uri).then((isolate) async {
+      lastIsolate = isolate;
+      container.children = const [];
+      await _metricRepository.startSampling(isolate);
+      container.children = <Element>[
+        new MetricsPageElement(isolate.vm, isolate, app.events,
+                app.notifications, _metricRepository,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+
+  @override
+  void onUninstall() {
+    super.onUninstall();
+    _metricRepository.stopSampling(lastIsolate);
+    container.children = const [];
+  }
+}
+
+class TimelinePage extends Page {
+  TimelinePage(app) : super(app);
+
+  void onInstall() {
+    element = new TimelinePageElement(
+            app.vm, _timelineRepository, app.events, app.notifications,
+            queue: app.queue)
+        .element;
+  }
+
+  void _visit(Uri uri) {
+    assert(canVisit(uri));
+  }
+
+  bool canVisit(Uri uri) => uri.path == 'timeline';
+}
+
+class TimelineDashboardPage extends Page {
+  TimelineDashboardPage(app) : super(app);
+
+  DivElement container = new DivElement();
+
+  void onInstall() {
+    if (element == null) {
+      element = container;
+    }
+  }
+
+  void _visit(Uri uri) {
+    assert(canVisit(uri));
+    app.vm.load().then((_) {
+      container.children = <Element>[
+        new TimelineDashboardElement(
+                app.vm, _timelineRepository, app.notifications,
+                queue: app.queue)
+            .element
+      ];
+    });
+  }
+
+  @override
+  void onUninstall() {
+    super.onUninstall();
+    container.children = const [];
+  }
+
+  bool canVisit(Uri uri) => uri.path == 'timeline-dashboard';
+}
+
+class ProcessSnapshotPage extends Page {
+  ProcessSnapshotPage(app) : super(app);
+
+  void onInstall() {
+    element = new ProcessSnapshotElement(app.vm, app.events, app.notifications,
+            queue: app.queue)
+        .element;
+  }
+
+  void _visit(Uri uri) {
+    assert(canVisit(uri));
+  }
+
+  bool canVisit(Uri uri) => uri.path == 'process-snapshot';
+}
diff --git a/runtime/observatory_2/lib/src/app/settings.dart b/runtime/observatory_2/lib/src/app/settings.dart
new file mode 100644
index 0000000..da6d8a8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/settings.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+/// Static settings database.
+class _Settings {
+  static Storage _storage = window.localStorage;
+
+  /// Associated [value] with [key]. [value] must be JSON encodable.
+  static void set(String key, dynamic value) {
+    _storage[key] = json.encode(value);
+  }
+
+  /// Get value associated with [key]. Return value will be a JSON encodable
+  /// object.
+  static dynamic get(String key) {
+    var value = _storage[key];
+    if (value == null) {
+      return null;
+    }
+    return json.decode(value);
+  }
+}
+
+/// A group of settings each prefixed with group name and a dot.
+class SettingsGroup {
+  /// Group name
+  final String group;
+
+  SettingsGroup(this.group);
+
+  String _fullKey(String key) => '$group.$key';
+
+  void set(String key, dynamic value) {
+    var fullKey = _fullKey(key);
+    _Settings.set(fullKey, value);
+  }
+
+  dynamic get(String key) {
+    var fullKey = _fullKey(key);
+    return _Settings.get(fullKey);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/app/view_model.dart b/runtime/observatory_2/lib/src/app/view_model.dart
new file mode 100644
index 0000000..f210e13
--- /dev/null
+++ b/runtime/observatory_2/lib/src/app/view_model.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of app;
+
+typedef String ValueFormatter(dynamic value);
+
+class SortedTableColumn {
+  static String toStringFormatter(dynamic v) {
+    return v != null ? v.toString() : '<null>';
+  }
+
+  final String label;
+  final ValueFormatter formatter;
+  SortedTableColumn.withFormatter(this.label, this.formatter);
+  SortedTableColumn(this.label) : formatter = toStringFormatter;
+}
+
+class SortedTableRow {
+  final List values;
+  SortedTableRow(this.values);
+}
+
+class SortedTable {
+  final List<SortedTableColumn> columns;
+  final List<SortedTableRow> rows = <SortedTableRow>[];
+  final List<int> sortedRows = [];
+
+  SortedTable(this.columns);
+
+  int _sortColumnIndex = 0;
+  set sortColumnIndex(var index) {
+    assert(index >= 0);
+    assert(index < columns.length);
+    _sortColumnIndex = index;
+  }
+
+  int get sortColumnIndex => _sortColumnIndex;
+  bool _sortDescending = true;
+  bool get sortDescending => _sortDescending;
+  set sortDescending(var descending) {
+    _sortDescending = descending;
+  }
+
+  dynamic getSortKeyFor(int row, int col) {
+    return rows[row].values[col];
+  }
+
+  int _sortFuncDescending(int i, int j) {
+    var a = getSortKeyFor(i, _sortColumnIndex);
+    var b = getSortKeyFor(j, _sortColumnIndex);
+    return b.compareTo(a);
+  }
+
+  int _sortFuncAscending(int i, int j) {
+    var a = getSortKeyFor(i, _sortColumnIndex);
+    var b = getSortKeyFor(j, _sortColumnIndex);
+    return a.compareTo(b);
+  }
+
+  void sort() {
+    assert(_sortColumnIndex >= 0);
+    assert(_sortColumnIndex < columns.length);
+    if (_sortDescending) {
+      sortedRows.sort(_sortFuncDescending);
+    } else {
+      sortedRows.sort(_sortFuncAscending);
+    }
+  }
+
+  void clearRows() {
+    rows.clear();
+    sortedRows.clear();
+  }
+
+  void addRow(SortedTableRow row) {
+    sortedRows.add(rows.length);
+    rows.add(row);
+  }
+
+  String getFormattedValue(int row, int column) {
+    var value = getValue(row, column);
+    var formatter = columns[column].formatter;
+    return formatter(value);
+  }
+
+  String getColumnLabel(int column) {
+    assert(column >= 0);
+    assert(column < columns.length);
+    // TODO(johnmccutchan): Move expander display decisions into html once
+    // tables and templates are better supported.
+    const arrowUp = '\u25BC';
+    const arrowDown = '\u25B2';
+    if (column != _sortColumnIndex) {
+      return columns[column].label + '\u2003';
+    }
+    return columns[column].label + (_sortDescending ? arrowUp : arrowDown);
+  }
+
+  dynamic getValue(int row, int column) {
+    return rows[row].values[column];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/cli/command.dart b/runtime/observatory_2/lib/src/cli/command.dart
new file mode 100644
index 0000000..0a0fc42
--- /dev/null
+++ b/runtime/observatory_2/lib/src/cli/command.dart
@@ -0,0 +1,280 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of cli;
+
+// Splits a line into a list of string args.  Each arg retains any
+// trailing whitespace so that we can reconstruct the original command
+// line from the pieces.
+List<String> _splitLine(String line) {
+  line = line.trimLeft();
+  var args = <String>[];
+  int pos = 0;
+  while (pos < line.length) {
+    int startPos = pos;
+
+    // Advance to end of word.
+    for (; pos < line.length && line[pos] != ' '; pos++);
+
+    // Advance to end of spaces.
+    for (; pos < line.length && line[pos] == ' '; pos++);
+
+    args.add(line.substring(startPos, pos));
+  }
+  return args;
+}
+
+// Concatenates the first 'count' args.
+String _concatArgs(List<String> args, int count) {
+  if (count == 0) {
+    return '';
+  }
+  return '${args.sublist(0, count).join('')}';
+}
+
+// Shared functionality for RootCommand and Command.
+abstract class _CommandBase {
+  _CommandBase(List<Command> children) {
+    assert(children != null);
+    _children.addAll(children);
+    for (var child in _children) {
+      child._parent = this;
+    }
+  }
+
+  // A command may optionally have sub-commands.
+  List<Command> _children = <Command>[];
+
+  _CommandBase _parent;
+  int get _depth => (_parent == null ? 0 : _parent._depth + 1);
+
+  // Override in subclasses to provide command-specific argument completion.
+  //
+  // Given a list of arguments to this command, provide a list of
+  // possible completions for those arguments.
+  Future<List<String>> complete(List<String> args) =>
+      new Future.value(<String>[]);
+
+  // Override in subclasses to provide command-specific execution.
+  Future run(List<String> args);
+
+  // Returns a list of local subcommands which match the args.
+  List<Command> _matchLocal(String argWithSpace, bool preferExact) {
+    var matches = <Command>[];
+    var arg = argWithSpace.trimRight();
+    for (var child in _children) {
+      if (child.name.startsWith(arg)) {
+        if (preferExact && ((child.name == arg) || (child.alias == arg))) {
+          return [child];
+        }
+        matches.add(child);
+      }
+    }
+    return matches;
+  }
+
+  // Returns the set of commands could be triggered by a list of
+  // arguments.
+  List<Command> _match(List<String> args, bool preferExact) {
+    if (args.isEmpty) {
+      return <Command>[];
+    }
+    bool lastArg = (args.length == 1);
+    var matches = _matchLocal(args[0], !lastArg || preferExact);
+    if (matches.isEmpty) {
+      return <Command>[];
+    } else if (matches.length == 1) {
+      var childMatches = matches[0]._match(args.sublist(1), preferExact);
+      if (childMatches.isEmpty) {
+        return matches;
+      } else {
+        return childMatches;
+      }
+    } else {
+      return matches;
+    }
+  }
+
+  // Builds a list of completions for this command.
+  Future<List<String>> _buildCompletions(
+      List<String> args, bool addEmptyString) {
+    return complete(args.sublist(_depth, args.length)).then((completions) {
+      if (addEmptyString &&
+          completions.isEmpty &&
+          args[args.length - 1] == '') {
+        // Special case allowance for an empty particle at the end of
+        // the command.
+        completions = <String>[''];
+      }
+      var prefix = _concatArgs(args, _depth);
+      return completions.map((str) => '${prefix}${str}').toList();
+    });
+  }
+}
+
+// The root of a tree of commands.
+class RootCommand extends _CommandBase {
+  RootCommand(List<Command> children, [List<String> history])
+      : this._(children, history ?? ['']);
+
+  RootCommand._(List<Command> children, List<String> history)
+      : history = history,
+        historyPos = history.length - 1,
+        super(children);
+
+  // Provides a list of possible completions for a line of text.
+  Future<List<String>> completeCommand(String line) {
+    var args = _splitLine(line);
+    bool showAll = line.endsWith(' ') || args.isEmpty;
+    if (showAll) {
+      // Adding an empty string to the end causes us to match all
+      // subcommands of the last command.
+      args.add('');
+    }
+    var commands = _match(args, false);
+    if (commands.isEmpty) {
+      // No matching commands.
+      return new Future.value(<String>[]);
+    }
+    int matchLen = commands[0]._depth;
+    if (matchLen < args.length) {
+      // We were able to find a command which matches a prefix of the
+      // args, but not the full list.
+      if (commands.length == 1) {
+        // The matching command is unique.  Attempt to provide local
+        // argument completion from the command.
+        return commands[0]._buildCompletions(args, true);
+      } else {
+        // An ambiguous prefix match leaves us nowhere.  The user is
+        // typing a bunch of stuff that we don't know how to complete.
+        return new Future.value(<String>[]);
+      }
+    }
+
+    // We have found a set of commands which match all of the args.
+    // Return the completion strings.
+    var prefix = _concatArgs(args, args.length - 1);
+    var completions =
+        commands.map((command) => '${prefix}${command.name} ').toList();
+    if (matchLen == args.length) {
+      // If we are showing all possiblities, also include local
+      // completions for the parent command.
+      return commands[0]
+          ._parent
+          ._buildCompletions(args, false)
+          .then((localCompletions) {
+        completions.addAll(localCompletions);
+        return completions;
+      });
+    }
+    return new Future.value(completions);
+  }
+
+  // Runs a command.
+  Future runCommand(String line) {
+    _historyAdvance(line);
+    var args = _splitLine(line);
+    var commands = _match(args, true);
+    if (commands.isEmpty) {
+      return new Future.error(new NoSuchCommandException(line));
+    } else if (commands.length == 1) {
+      return commands[0].run(args.sublist(commands[0]._depth));
+    } else {
+      return new Future.error(new AmbiguousCommandException(line, commands));
+    }
+  }
+
+  // Find all matching commands.  Useful for implementing help systems.
+  List<Command> matchCommand(List<String> args, bool preferExact) {
+    if (args.isEmpty) {
+      // Adding an empty string to the end causes us to match all
+      // subcommands of the last command.
+      args.add('');
+    }
+    return _match(args, preferExact);
+  }
+
+  // Command line history always contains one slot to hold the current
+  // line, so we start off with one entry.
+  List<String> history;
+  int historyPos;
+
+  String historyPrev(String line) {
+    if (historyPos == 0) {
+      return line;
+    }
+    history[historyPos] = line;
+    historyPos--;
+    return history[historyPos];
+  }
+
+  String historyNext(String line) {
+    if (historyPos == history.length - 1) {
+      return line;
+    }
+    history[historyPos] = line;
+    historyPos++;
+    return history[historyPos];
+  }
+
+  void _historyAdvance(String line) {
+    // Replace the last history line.
+    historyPos = history.length - 1;
+    history[historyPos] = line;
+
+    // Create an empty spot for the next line.
+    history.add('');
+    historyPos++;
+  }
+
+  Future run(List<String> args) {
+    throw 'should-not-execute-the-root-command';
+  }
+
+  toString() => 'RootCommand';
+}
+
+// A node in the command tree.
+abstract class Command extends _CommandBase {
+  Command(this.name, List<Command> children) : super(children);
+
+  final String name;
+  String alias;
+
+  String get fullName {
+    if (_parent is RootCommand) {
+      return name;
+    } else {
+      Command parent = _parent;
+      return '${parent.fullName} $name';
+    }
+  }
+
+  toString() => 'Command(${name})';
+}
+
+abstract class CommandException implements Exception {}
+
+class AmbiguousCommandException extends CommandException {
+  AmbiguousCommandException(this.command, this.matches);
+
+  final String command;
+  final List<Command> matches;
+
+  @override
+  String toString() {
+    List<String> matchNames =
+        matches.map((Command command) => '${command.fullName}').toList();
+    return "Command '$command' is ambiguous: $matchNames";
+  }
+}
+
+class NoSuchCommandException extends CommandException {
+  NoSuchCommandException(this.command);
+
+  final String command;
+
+  @override
+  String toString() => "No such command: '$command'";
+}
diff --git a/runtime/observatory_2/lib/src/debugger/debugger.dart b/runtime/observatory_2/lib/src/debugger/debugger.dart
new file mode 100644
index 0000000..fb297c7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/debugger/debugger.dart
@@ -0,0 +1,14 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of debugger;
+
+// TODO(turnidge): Move more of ObservatoryDebugger to this class.
+abstract class Debugger {
+  VM get vm;
+  Isolate get isolate;
+  M.ObjectRepository objects;
+  ServiceMap get stack;
+  int get currentFrame;
+}
diff --git a/runtime/observatory_2/lib/src/debugger/debugger_location.dart b/runtime/observatory_2/lib/src/debugger/debugger_location.dart
new file mode 100644
index 0000000..a186fd4
--- /dev/null
+++ b/runtime/observatory_2/lib/src/debugger/debugger_location.dart
@@ -0,0 +1,462 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of debugger;
+
+class DebuggerLocation {
+  DebuggerLocation.file(this.script, this.line, this.col);
+  DebuggerLocation.func(this.function);
+  DebuggerLocation.error(this.errorMessage);
+
+  static RegExp sourceLocMatcher = new RegExp(r'^([^\d:][^:]+:)?(\d+)(:\d+)?');
+  static RegExp packageLocMatcher =
+      new RegExp(r'^package:([^\d:][^:]+:)?(\d+)(:\d+)?');
+  static RegExp functionMatcher = new RegExp(r'^([^.]+)([.][^.]+)?');
+
+  /// Parses a source location description.
+  ///
+  /// Formats:
+  ///   ''                     -  current position
+  ///   13                     -  line 13, current script
+  ///   13:20                  -  line 13, col 20, current script
+  ///   script.dart:13         -  line 13, script.dart
+  ///   script.dart:13:20      -  line 13, col 20, script.dart
+  ///   package:a/b.dart:13    -  line 13, "b.dart" in package "a".
+  ///   package:a/b.dart:13:20 -  line 13, col 20, "b.dart" in package "a".
+  ///   main                   -  function
+  ///   FormatException        -  constructor
+  ///   _SHA1._updateHash      -  method
+  static Future<DebuggerLocation> parse(Debugger debugger, String locDesc) {
+    if (locDesc == '') {
+      // Special case: '' means return current location.
+      return _currentLocation(debugger);
+    }
+
+    // Parse the location description.
+    var match = sourceLocMatcher.firstMatch(locDesc);
+    if (match != null) {
+      return _parseScriptLine(debugger, match);
+    }
+    match = packageLocMatcher.firstMatch(locDesc);
+    if (match != null) {
+      return _parseScriptLine(debugger, match, package: true);
+    }
+    match = functionMatcher.firstMatch(locDesc);
+    if (match != null) {
+      return _parseFunction(debugger, match);
+    }
+    return new Future.value(
+        new DebuggerLocation.error("Invalid source location '${locDesc}'"));
+  }
+
+  static Future<Frame> _currentFrame(Debugger debugger) async {
+    ServiceMap stack = debugger.stack;
+    if (stack == null || stack['frames'].length == 0) {
+      return null;
+    }
+    return stack['frames'][debugger.currentFrame];
+  }
+
+  static Future<DebuggerLocation> _currentLocation(Debugger debugger) async {
+    var frame = await _currentFrame(debugger);
+    if (frame == null) {
+      return new DebuggerLocation.error(
+          'A script must be provided when the stack is empty');
+    }
+    Script script = frame.location.script;
+    await script.load();
+    var line = script.tokenToLine(frame.location.tokenPos);
+    var col = script.tokenToCol(frame.location.tokenPos);
+    return new DebuggerLocation.file(script, line, col);
+  }
+
+  static Future<DebuggerLocation> _parseScriptLine(
+      Debugger debugger, Match match,
+      {bool package = false}) async {
+    var scriptName = match.group(1);
+    if (package) {
+      scriptName = "package:$scriptName";
+    }
+    if (scriptName != null) {
+      scriptName = scriptName.substring(0, scriptName.length - 1);
+    }
+    var lineStr = match.group(2);
+    assert(lineStr != null);
+    var colStr = match.group(3);
+    if (colStr != null) {
+      colStr = colStr.substring(1);
+    }
+    var line = int.tryParse(lineStr) ?? -1;
+    var col = (colStr != null ? int.tryParse(colStr) ?? -1 : null);
+    if (line == -1) {
+      return new Future.value(
+          new DebuggerLocation.error("Line '${lineStr}' must be an integer"));
+    }
+    if (col == -1) {
+      return new Future.value(
+          new DebuggerLocation.error("Column '${colStr}' must be an integer"));
+    }
+
+    if (scriptName != null) {
+      // Resolve the script.
+      Set<Script> scripts = await _lookupScript(debugger.isolate, scriptName);
+      if (scripts.length == 0) {
+        scripts =
+            await _lookupScript(debugger.isolate, scriptName, useUri: true);
+      }
+      if (scripts.length == 0) {
+        return new DebuggerLocation.error("Script '${scriptName}' not found");
+      } else if (scripts.length == 1) {
+        return new DebuggerLocation.file(scripts.single, line, col);
+      } else {
+        // TODO(turnidge): Allow the user to disambiguate.
+        return new DebuggerLocation.error(
+            "Script '${scriptName}' is ambiguous");
+      }
+    } else {
+      // No script provided.  Default to top of stack for now.
+      var frame = await _currentFrame(debugger);
+      if (frame == null) {
+        return new Future.value(new DebuggerLocation.error(
+            'A script must be provided when the stack is empty'));
+      }
+      Script script = frame.location.script;
+      await script.load();
+      return new DebuggerLocation.file(script, line, col);
+    }
+  }
+
+  static Future<Set<Script>> _lookupScript(Isolate isolate, String name,
+      {bool allowPrefix: false, bool useUri: false}) {
+    var pending = <Future>[];
+    for (var lib in isolate.libraries) {
+      if (!lib.loaded) {
+        pending.add(lib.load());
+      }
+    }
+    return Future.wait(pending).then((_) {
+      var matches = <Script>{};
+      for (var lib in isolate.libraries) {
+        for (var script in lib.scripts) {
+          final String haystack = useUri ? script.uri : script.name;
+          if (allowPrefix) {
+            if (haystack.startsWith(name)) {
+              matches.add(script);
+            }
+          } else {
+            if (name == haystack) {
+              matches.add(script);
+            }
+          }
+        }
+      }
+      return matches;
+    });
+  }
+
+  static List<ServiceFunction> _lookupFunction(Isolate isolate, String name,
+      {bool allowPrefix: false}) {
+    var matches = <ServiceFunction>[];
+    for (var lib in isolate.libraries) {
+      assert(lib.loaded);
+      for (var function in lib.functions) {
+        if (allowPrefix) {
+          if (function.name.startsWith(name)) {
+            matches.add(function);
+          }
+        } else {
+          if (name == function.name) {
+            matches.add(function);
+          }
+        }
+      }
+    }
+    return matches;
+  }
+
+  static Future<List<Class>> _lookupClass(Isolate isolate, String name,
+      {bool allowPrefix: false}) async {
+    if (isolate == null) {
+      return [];
+    }
+    var pending = <Future>[];
+    for (var lib in isolate.libraries) {
+      assert(lib.loaded);
+      for (var cls in lib.classes) {
+        if (!cls.loaded) {
+          pending.add(cls.load());
+        }
+      }
+    }
+    await Future.wait(pending);
+    var matches = <Class>[];
+    for (var lib in isolate.libraries) {
+      for (var cls in lib.classes) {
+        if (allowPrefix) {
+          if (cls.name.startsWith(name)) {
+            matches.add(cls);
+          }
+        } else {
+          if (name == cls.name) {
+            matches.add(cls);
+          }
+        }
+      }
+    }
+    return matches;
+  }
+
+  static ServiceFunction _getConstructor(Class cls, String name) {
+    for (var function in cls.functions) {
+      assert(cls.loaded);
+      if (name == function.name) {
+        return function;
+      }
+    }
+    return null;
+  }
+
+  // TODO(turnidge): This does not handle named functions which are
+  // inside of named functions, e.g. foo.bar.baz.
+  static Future<DebuggerLocation> _parseFunction(
+      Debugger debugger, Match match) {
+    Isolate isolate = debugger.isolate;
+    var base = match.group(1);
+    var qualifier = match.group(2);
+    assert(base != null);
+
+    return _lookupClass(isolate, base).then((classes) {
+      var functions = [];
+      if (qualifier == null) {
+        // Unqualified name is either a function or a constructor.
+        functions.addAll(_lookupFunction(isolate, base));
+
+        for (var cls in classes) {
+          // Look for a self-named constructor.
+          var constructor = _getConstructor(cls, cls.name);
+          if (constructor != null) {
+            functions.add(constructor);
+          }
+        }
+      } else {
+        // Qualified name.
+        var functionName = qualifier.substring(1);
+        for (var cls in classes) {
+          assert(cls.loaded);
+          for (var function in cls.functions) {
+            if (function.kind == M.FunctionKind.constructor) {
+              // Constructor names are class-qualified.
+              if (match.group(0) == function.name) {
+                functions.add(function);
+              }
+            } else {
+              if (functionName == function.name) {
+                functions.add(function);
+              }
+            }
+          }
+        }
+      }
+      if (functions.length == 0) {
+        return new DebuggerLocation.error(
+            "Function '${match.group(0)}' not found");
+      } else if (functions.length == 1) {
+        return new DebuggerLocation.func(functions[0]);
+      } else {
+        // TODO(turnidge): Allow the user to disambiguate.
+        return new DebuggerLocation.error(
+            "Function '${match.group(0)}' is ambiguous");
+      }
+    });
+  }
+
+  static RegExp partialSourceLocMatcher =
+      new RegExp(r'^([^\d:]?[^:]+[:]?)?(\d+)?([:]\d*)?');
+  static RegExp partialFunctionMatcher = new RegExp(r'^([^.]*)([.][^.]*)?');
+
+  /// Completes a partial source location description.
+  static Future<List<String>> complete(Debugger debugger, String locDesc) {
+    var pending = <Future<List<String>>>[];
+    var match = partialFunctionMatcher.firstMatch(locDesc);
+    if (match != null) {
+      pending.add(_completeFunction(debugger, match));
+    }
+
+    match = partialSourceLocMatcher.firstMatch(locDesc);
+    if (match != null) {
+      pending.add(_completeFile(debugger, match));
+    }
+
+    return Future.wait(pending).then((List<List<String>> responses) {
+      var completions = <String>[];
+      for (var response in responses) {
+        completions.addAll(response);
+      }
+      return completions;
+    });
+  }
+
+  static Future<List<String>> _completeFunction(
+      Debugger debugger, Match match) {
+    Isolate isolate = debugger.isolate;
+    var base = match.group(1);
+    var qualifier = match.group(2);
+    base = (base == null ? '' : base);
+
+    if (qualifier == null) {
+      return _lookupClass(isolate, base, allowPrefix: true).then((classes) {
+        var completions = <String>[];
+
+        // Complete top-level function names.
+        var functions = _lookupFunction(isolate, base, allowPrefix: true);
+        var funcNames = functions.map((f) => f.name).toList();
+        funcNames.sort();
+        completions.addAll(funcNames);
+
+        // Complete class names.
+        var classNames = classes.map((f) => f.name).toList();
+        classNames.sort();
+        completions.addAll(classNames);
+
+        return completions;
+      });
+    } else {
+      return _lookupClass(isolate, base, allowPrefix: false).then((classes) {
+        var completions = <String>[];
+        for (var cls in classes) {
+          for (var function in cls.functions) {
+            if (function.kind == M.FunctionKind.constructor) {
+              if (function.name.startsWith(match.group(0))) {
+                completions.add(function.name);
+              }
+            } else {
+              if (function.qualifiedName.startsWith(match.group(0))) {
+                completions.add(function.qualifiedName);
+              }
+            }
+          }
+        }
+        completions.sort();
+        return completions;
+      });
+    }
+  }
+
+  static bool _startsWithDigit(String s) {
+    return '0'.compareTo(s[0]) <= 0 && '9'.compareTo(s[0]) >= 0;
+  }
+
+  static Future<List<String>> _completeFile(
+      Debugger debugger, Match match) async {
+    var scriptName;
+    var scriptNameComplete = false;
+    var lineStr;
+    var lineStrComplete = false;
+    var colStr;
+    if (_startsWithDigit(match.group(1))) {
+      // CASE 1: We have matched a prefix of (lineStr:)(colStr)
+      var frame = await _currentFrame(debugger);
+      if (frame == null) {
+        return [];
+      }
+      scriptName = frame.location.script.name;
+      scriptNameComplete = true;
+      lineStr = match.group(1);
+      lineStr = (lineStr == null ? '' : lineStr);
+      if (lineStr.endsWith(':')) {
+        lineStr = lineStr.substring(0, lineStr.length - 1);
+        lineStrComplete = true;
+      }
+      colStr = match.group(2);
+      colStr = (colStr == null ? '' : colStr);
+    } else {
+      // CASE 2: We have matched a prefix of (scriptName:)(lineStr)(:colStr)
+      scriptName = match.group(1);
+      scriptName = (scriptName == null ? '' : scriptName);
+      if (scriptName.endsWith(':')) {
+        scriptName = scriptName.substring(0, scriptName.length - 1);
+        scriptNameComplete = true;
+      }
+      lineStr = match.group(2);
+      lineStr = (lineStr == null ? '' : lineStr);
+      colStr = match.group(3);
+      colStr = (colStr == null ? '' : colStr);
+      if (colStr.startsWith(':')) {
+        lineStrComplete = true;
+        colStr = colStr.substring(1);
+      }
+    }
+
+    if (!scriptNameComplete) {
+      // The script name is incomplete.  Complete it.
+      var scripts =
+          await _lookupScript(debugger.isolate, scriptName, allowPrefix: true);
+      var completions = <String>[];
+      for (var script in scripts) {
+        completions.add(script.name + ':');
+      }
+      completions.sort();
+      return completions;
+    } else {
+      // The script name is complete.  Look it up.
+      var scripts =
+          await _lookupScript(debugger.isolate, scriptName, allowPrefix: false);
+      if (scripts.isEmpty) {
+        return [];
+      }
+      var script = scripts.first;
+      await script.load();
+      if (!lineStrComplete) {
+        // Complete the line.
+        var sharedPrefix = '${script.name}:';
+        var completions = <String>[];
+        var report = await script.isolate
+            .getSourceReport([Isolate.kPossibleBreakpointsReport], script);
+        Set<int> possibleBpts = getPossibleBreakpointLines(report, script);
+        for (var line in possibleBpts) {
+          var currentLineStr = line.toString();
+          if (currentLineStr.startsWith(lineStr)) {
+            completions.add('${sharedPrefix}${currentLineStr} ');
+            completions.add('${sharedPrefix}${currentLineStr}:');
+          }
+        }
+        return completions;
+      } else {
+        // Complete the column.
+        int lineNum = int.parse(lineStr);
+        var scriptLine = script.getLine(lineNum);
+        var sharedPrefix = '${script.name}:${lineStr}:';
+        var completions = <String>[];
+        int maxCol = scriptLine.text.trimRight().runes.length;
+        for (int i = 1; i <= maxCol; i++) {
+          var currentColStr = i.toString();
+          if (currentColStr.startsWith(colStr)) {
+            completions.add('${sharedPrefix}${currentColStr} ');
+          }
+        }
+        return completions;
+      }
+    }
+  }
+
+  String toString() {
+    if (valid) {
+      if (function != null) {
+        return '${function.qualifiedName}';
+      } else if (col != null) {
+        return '${script.name}:${line}:${col}';
+      } else {
+        return '${script.name}:${line}';
+      }
+    }
+    return 'invalid source location (${errorMessage})';
+  }
+
+  Script script;
+  int line;
+  int col;
+  ServiceFunction function;
+  String errorMessage;
+  bool get valid => (errorMessage == null);
+}
diff --git a/runtime/observatory_2/lib/src/elements/allocation_profile.dart b/runtime/observatory_2/lib/src/elements/allocation_profile.dart
new file mode 100644
index 0000000..a233b73
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/allocation_profile.dart
@@ -0,0 +1,573 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/utils.dart';
+
+enum _SortingField {
+  newInstances,
+  newInternalSize,
+  newExternalSize,
+  newSize,
+  oldInstances,
+  oldInternalSize,
+  oldExternalSize,
+  oldSize,
+  instances,
+  internalSize,
+  externalSize,
+  size,
+  className,
+}
+
+enum _SortingDirection { ascending, descending }
+
+class AllocationProfileElement extends CustomElement implements Renderable {
+  RenderingScheduler<AllocationProfileElement> _r;
+
+  Stream<RenderedEvent<AllocationProfileElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.AllocationProfileRepository _repository;
+  M.AllocationProfile _profile;
+  bool _autoRefresh = false;
+  bool _isCompacted = false;
+  StreamSubscription _gcSubscription;
+  _SortingField _sortingField = _SortingField.size;
+  _SortingDirection _sortingDirection = _SortingDirection.descending;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory AllocationProfileElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.AllocationProfileRepository repository,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(repository != null);
+    AllocationProfileElement e = new AllocationProfileElement.created();
+    e._r = new RenderingScheduler<AllocationProfileElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._repository = repository;
+    return e;
+  }
+
+  AllocationProfileElement.created() : super.created('allocation-profile');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+    _gcSubscription = _events.onGCEvent.listen((e) {
+      if (_autoRefresh && (e.isolate.id == _isolate.id)) {
+        _refresh();
+      }
+    });
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _gcSubscription.cancel();
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('allocation profile'),
+        (new NavRefreshElement(
+                label: 'Download', disabled: _profile == null, queue: _r.queue)
+              ..onRefresh.listen((_) => _downloadCSV()))
+            .element,
+        (new NavRefreshElement(label: 'GC', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: true)))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        new DivElement()
+          ..classes = ['nav-option']
+          ..children = <Element>[
+            new CheckboxInputElement()
+              ..id = 'allocation-profile-auto-refresh'
+              ..checked = _autoRefresh
+              ..onChange.listen((_) => _autoRefresh = !_autoRefresh),
+            new LabelElement()
+              ..htmlFor = 'allocation-profile-auto-refresh'
+              ..text = 'Auto-refresh on GC'
+          ],
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Allocation Profile',
+          new HRElement()
+        ]
+    ];
+    if (_profile == null) {
+      children.addAll([
+        new DivElement()
+          ..classes = ['content-centered-big']
+          ..children = <Element>[new HeadingElement.h2()..text = 'Loading...']
+      ]);
+    } else {
+      children.addAll([
+        new DivElement()
+          ..classes = ['content-centered-big']
+          ..children = _isCompacted
+              ? []
+              : [
+                  new DivElement()
+                    ..classes = ['memberList']
+                    ..children = <Element>[
+                      new DivElement()
+                        ..classes = ['memberItem']
+                        ..children = <Element>[
+                          new DivElement()
+                            ..classes = ['memberName']
+                            ..text = 'last forced GC at',
+                          new DivElement()
+                            ..classes = ['memberValue']
+                            ..text = _profile.lastServiceGC == null
+                                ? '---'
+                                : '${_profile.lastServiceGC}',
+                        ],
+                    ],
+                  new HRElement(),
+                ],
+        new DivElement()
+          ..classes = ['content-centered-big', 'compactable']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['heap-space', 'left']
+              ..children = _isCompacted
+                  ? [
+                      new HeadingElement.h2()
+                        ..text = 'New Generation '
+                            '(${_usedCaption(_profile.newSpace)})',
+                    ]
+                  : [
+                      new HeadingElement.h2()..text = 'New Generation',
+                      new BRElement(),
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = _createSpaceMembers(_profile.newSpace),
+                    ],
+            new DivElement()
+              ..classes = ['heap-space', 'left']
+              ..children = _isCompacted
+                  ? [
+                      new HeadingElement.h2()
+                        ..text = 'Old Generation '
+                            '(${_usedCaption(_profile.oldSpace)})',
+                    ]
+                  : [
+                      new HeadingElement.h2()..text = 'Old Generation',
+                      new BRElement(),
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = _createSpaceMembers(_profile.oldSpace),
+                    ],
+            new DivElement()
+              ..classes = ['heap-space', 'left']
+              ..children = _isCompacted
+                  ? [
+                      new HeadingElement.h2()
+                        ..text = 'Total '
+                            '(${_usedCaption(_profile.totalSpace)})',
+                    ]
+                  : [
+                      new HeadingElement.h2()..text = 'Total',
+                      new BRElement(),
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = _createSpaceMembers(_profile.totalSpace),
+                    ],
+            new ButtonElement()
+              ..classes = ['compact']
+              ..text = _isCompacted ? 'expand ▼' : 'compact ▲'
+              ..onClick.listen((_) {
+                _isCompacted = !_isCompacted;
+                _r.dirty();
+              }),
+            new HRElement()
+          ],
+        new DivElement()
+          ..classes = _isCompacted ? ['collection', 'expanded'] : ['collection']
+          ..children = <Element>[
+            new VirtualCollectionElement(
+                    _createCollectionLine, _updateCollectionLine,
+                    createHeader: _createCollectionHeader,
+                    search: _search,
+                    items: _profile.members.toList()..sort(_createSorter()),
+                    queue: _r.queue)
+                .element
+          ]
+      ]);
+    }
+  }
+
+  _createSorter() {
+    var getter;
+    switch (_sortingField) {
+      case _SortingField.newInternalSize:
+        getter = _getNewInternalSize;
+        break;
+      case _SortingField.newExternalSize:
+        getter = _getNewExternalSize;
+        break;
+      case _SortingField.newSize:
+        getter = _getNewSize;
+        break;
+      case _SortingField.newInstances:
+        getter = _getNewInstances;
+        break;
+      case _SortingField.oldInternalSize:
+        getter = _getOldInternalSize;
+        break;
+      case _SortingField.oldExternalSize:
+        getter = _getOldExternalSize;
+        break;
+      case _SortingField.oldSize:
+        getter = _getOldSize;
+        break;
+      case _SortingField.oldInstances:
+        getter = _getOldInstances;
+        break;
+      case _SortingField.internalSize:
+        getter = _getInternalSize;
+        break;
+      case _SortingField.externalSize:
+        getter = _getExternalSize;
+        break;
+      case _SortingField.size:
+        getter = _getSize;
+        break;
+      case _SortingField.instances:
+        getter = _getInstances;
+        break;
+      case _SortingField.className:
+        getter = (M.ClassHeapStats s) => s.clazz.name;
+        break;
+    }
+    switch (_sortingDirection) {
+      case _SortingDirection.ascending:
+        int sort(M.ClassHeapStats a, M.ClassHeapStats b) {
+          return getter(a).compareTo(getter(b));
+        }
+        return sort;
+      case _SortingDirection.descending:
+        int sort(M.ClassHeapStats a, M.ClassHeapStats b) {
+          return getter(b).compareTo(getter(a));
+        }
+        return sort;
+    }
+  }
+
+  static HtmlElement _createCollectionLine() => new DivElement()
+    ..classes = ['collection-item']
+    ..children = <Element>[
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['instances']
+        ..text = '0',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['instances']
+        ..text = '0',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['bytes']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['instances']
+        ..text = '0',
+      new SpanElement()..classes = ['name']
+    ];
+
+  List<HtmlElement> _createCollectionHeader() => [
+        new DivElement()
+          ..classes = ['collection-item']
+          ..children = <Element>[
+            new SpanElement()
+              ..classes = ['group']
+              ..text = 'New Generation',
+            new SpanElement()
+              ..classes = ['group']
+              ..text = 'Old Generation',
+            new SpanElement()
+              ..classes = ['group']
+              ..text = 'Total',
+            new SpanElement()
+              ..classes = ['group']
+              ..text = '',
+          ],
+        new DivElement()
+          ..classes = ['collection-item']
+          ..children = <Element>[
+            _createHeaderButton(const ['bytes'], 'Internal',
+                _SortingField.newInternalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'External',
+                _SortingField.newExternalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'Size', _SortingField.newSize,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['instances'], 'Instances',
+                _SortingField.newInstances, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'Internal',
+                _SortingField.oldInternalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'External',
+                _SortingField.oldExternalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'Size', _SortingField.oldSize,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['instances'], 'Instances',
+                _SortingField.oldInstances, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'Internal',
+                _SortingField.internalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'External',
+                _SortingField.externalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['bytes'], 'Size', _SortingField.size,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['instances'], 'Instances',
+                _SortingField.instances, _SortingDirection.descending),
+            _createHeaderButton(const ['name'], 'Class',
+                _SortingField.className, _SortingDirection.ascending)
+          ],
+      ];
+
+  ButtonElement _createHeaderButton(List<String> classes, String text,
+          _SortingField field, _SortingDirection direction) =>
+      new ButtonElement()
+        ..classes = classes
+        ..text = _sortingField != field
+            ? text
+            : _sortingDirection == _SortingDirection.ascending
+                ? '$text▼'
+                : '$text▲'
+        ..onClick.listen((_) => _setSorting(field, direction));
+
+  void _setSorting(_SortingField field, _SortingDirection defaultDirection) {
+    if (_sortingField == field) {
+      switch (_sortingDirection) {
+        case _SortingDirection.descending:
+          _sortingDirection = _SortingDirection.ascending;
+          break;
+        case _SortingDirection.ascending:
+          _sortingDirection = _SortingDirection.descending;
+          break;
+      }
+    } else {
+      _sortingDirection = defaultDirection;
+      _sortingField = field;
+    }
+    _r.dirty();
+  }
+
+  void _updateCollectionLine(Element e, itemDynamic, index) {
+    M.ClassHeapStats item = itemDynamic;
+    e.children[0].text = Utils.formatSize(_getNewInternalSize(item));
+    e.children[1].text = Utils.formatSize(_getNewExternalSize(item));
+    e.children[2].text = Utils.formatSize(_getNewSize(item));
+    e.children[3].text = '${_getNewInstances(item)}';
+    e.children[4].text = Utils.formatSize(_getOldInternalSize(item));
+    e.children[5].text = Utils.formatSize(_getOldExternalSize(item));
+    e.children[6].text = Utils.formatSize(_getOldSize(item));
+    e.children[7].text = '${_getOldInstances(item)}';
+    e.children[8].text = Utils.formatSize(_getInternalSize(item));
+    e.children[9].text = Utils.formatSize(_getExternalSize(item));
+    e.children[10].text = Utils.formatSize(_getSize(item));
+    e.children[11].text = '${_getInstances(item)}';
+    e.children[12] = new ClassRefElement(_isolate, item.clazz, queue: _r.queue)
+        .element
+      ..classes = ['name'];
+  }
+
+  bool _search(Pattern pattern, itemDynamic) {
+    M.ClassHeapStats item = itemDynamic;
+    return item.clazz.name.contains(pattern);
+  }
+
+  static String _usedCaption(M.HeapSpace space) =>
+      '${Utils.formatSize(space.used)}'
+      ' of '
+      '${Utils.formatSize(space.capacity)}';
+
+  static List<Element> _createSpaceMembers(M.HeapSpace space) {
+    final used = _usedCaption(space);
+    final ext = '${Utils.formatSize(space.external)}';
+    final collections = '${space.collections}';
+    final avgCollectionTime =
+        '${Utils.formatDurationInMilliseconds(space.avgCollectionTime)} ms';
+    final totalCollectionTime =
+        '${Utils.formatDurationInSeconds(space.totalCollectionTime)} secs';
+    final avgCollectionPeriod =
+        '${Utils.formatDurationInMilliseconds(space.avgCollectionPeriod)} ms';
+    return [
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'used',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = used
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'external',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = ext
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'collections',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = collections
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'average collection time',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = avgCollectionTime
+        ],
+    ];
+  }
+
+  Future _refresh({bool gc: false, bool reset: false}) async {
+    _profile = null;
+    _r.dirty();
+    _profile = await _repository.get(_isolate, gc: gc, reset: reset);
+    _r.dirty();
+  }
+
+  void _downloadCSV() {
+    assert(_profile != null);
+    final header = [
+          '"New Internal"',
+          '"New External"',
+          '"New Size"',
+          '"New Instances"',
+          '"Old Internal"',
+          '"Old External"',
+          '"Old Size"',
+          '"Old Instances"',
+          '"Internal"',
+          '"External"',
+          '"Size"',
+          '"Instances"',
+          'Class'
+        ].join(',') +
+        '\n';
+    AnchorElement tl = document.createElement('a');
+    tl
+      ..attributes['href'] = 'data:text/plain;charset=utf-8,' +
+          Uri.encodeComponent(header +
+              (_profile.members.toList()..sort(_createSorter()))
+                  .map(_csvOut)
+                  .join('\n'))
+      ..attributes['download'] = 'heap-profile.csv'
+      ..click();
+  }
+
+  static _csvOut(M.ClassHeapStats s) {
+    return [
+      _getNewInternalSize(s),
+      _getNewExternalSize(s),
+      _getNewSize(s),
+      _getNewInstances(s),
+      _getOldInternalSize(s),
+      _getOldExternalSize(s),
+      _getOldSize(s),
+      _getOldInstances(s),
+      _getInternalSize(s),
+      _getExternalSize(s),
+      _getSize(s),
+      _getInstances(s),
+      s.clazz.name
+    ].join(',');
+  }
+
+  static int _getNewInstances(M.ClassHeapStats s) => s.newSpace.instances;
+  static int _getNewInternalSize(M.ClassHeapStats s) => s.newSpace.internalSize;
+  static int _getNewExternalSize(M.ClassHeapStats s) => s.newSpace.externalSize;
+  static int _getNewSize(M.ClassHeapStats s) => s.newSpace.size;
+  static int _getOldInstances(M.ClassHeapStats s) => s.oldSpace.instances;
+  static int _getOldInternalSize(M.ClassHeapStats s) => s.oldSpace.internalSize;
+  static int _getOldExternalSize(M.ClassHeapStats s) => s.oldSpace.externalSize;
+  static int _getOldSize(M.ClassHeapStats s) => s.oldSpace.size;
+  static int _getInstances(M.ClassHeapStats s) =>
+      s.newSpace.instances + s.oldSpace.instances;
+  static int _getInternalSize(M.ClassHeapStats s) =>
+      s.newSpace.internalSize + s.oldSpace.internalSize;
+  static int _getExternalSize(M.ClassHeapStats s) =>
+      s.newSpace.externalSize + s.oldSpace.externalSize;
+  static int _getSize(M.ClassHeapStats s) => s.newSpace.size + s.oldSpace.size;
+}
diff --git a/runtime/observatory_2/lib/src/elements/class_allocation_profile.dart b/runtime/observatory_2/lib/src/elements/class_allocation_profile.dart
new file mode 100644
index 0000000..219a00a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/class_allocation_profile.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/sample_buffer_control.dart';
+import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
+
+class ClassAllocationProfileElement extends CustomElement
+    implements Renderable {
+  RenderingScheduler<ClassAllocationProfileElement> _r;
+
+  Stream<RenderedEvent<ClassAllocationProfileElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.Class _cls;
+  M.ClassSampleProfileRepository _profiles;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag = M.SampleProfileTag.none;
+  ProfileTreeMode _mode = ProfileTreeMode.function;
+  M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
+
+  M.IsolateRef get isolate => _isolate;
+  M.Class get cls => _cls;
+
+  factory ClassAllocationProfileElement(M.VM vm, M.IsolateRef isolate,
+      M.Class cls, M.ClassSampleProfileRepository profiles,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(cls != null);
+    assert(profiles != null);
+    ClassAllocationProfileElement e =
+        new ClassAllocationProfileElement.created();
+    e._r =
+        new RenderingScheduler<ClassAllocationProfileElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._cls = cls;
+    e._profiles = profiles;
+    return e;
+  }
+
+  ClassAllocationProfileElement.created()
+      : super.created('class-allocation-profile');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _request();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    if (_progress == null) {
+      children = const [];
+      return;
+    }
+    final content = <HtmlElement>[
+      (new SampleBufferControlElement(_vm, _progress, _progressStream,
+              selectedTag: _tag, queue: _r.queue)
+            ..onTagChange.listen((e) {
+              _tag = e.element.selectedTag;
+              _request(forceFetch: true);
+            }))
+          .element
+    ];
+    if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+      CpuProfileVirtualTreeElement tree;
+      content.addAll([
+        new BRElement(),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                showFilter: false,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
+        new BRElement(),
+        (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+                queue: _r.queue))
+            .element
+      ]);
+    }
+    children = content;
+  }
+
+  Future _request({bool forceFetch: false}) async {
+    _progress = null;
+    _progressStream =
+        _profiles.get(_isolate, _cls, _tag, forceFetch: forceFetch);
+    _r.dirty();
+    _progress = (await _progressStream.first).progress;
+    _r.dirty();
+    if (M.isSampleProcessRunning(_progress.status)) {
+      _progress = (await _progressStream.last).progress;
+      _r.dirty();
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/class_instances.dart b/runtime/observatory_2/lib/src/elements/class_instances.dart
new file mode 100644
index 0000000..bc3e101
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/class_instances.dart
@@ -0,0 +1,194 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/inbound_references.dart';
+import 'package:observatory_2/src/elements/retaining_path.dart';
+import 'package:observatory_2/src/elements/sentinel_value.dart';
+import 'package:observatory_2/src/elements/strongly_reachable_instances.dart';
+import 'package:observatory_2/utils.dart';
+
+class ClassInstancesElement extends CustomElement implements Renderable {
+  RenderingScheduler<ClassInstancesElement> _r;
+
+  Stream<RenderedEvent<ClassInstancesElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.Class _cls;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.StronglyReachableInstancesRepository _stronglyReachableInstances;
+  M.ObjectRepository _objects;
+  M.Guarded<M.Instance> _retainedSize = null;
+  bool _loadingRetainedBytes = false;
+  M.Guarded<M.Instance> _reachableSize = null;
+  bool _loadingReachableBytes = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.Class get cls => _cls;
+
+  factory ClassInstancesElement(
+      M.IsolateRef isolate,
+      M.Class cls,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.StronglyReachableInstancesRepository stronglyReachableInstances,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cls != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(stronglyReachableInstances != null);
+    assert(objects != null);
+    ClassInstancesElement e = new ClassInstancesElement.created();
+    e._r = new RenderingScheduler<ClassInstancesElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._cls = cls;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._stronglyReachableInstances = stronglyReachableInstances;
+    e._objects = objects;
+    return e;
+  }
+
+  ClassInstancesElement.created() : super.created('class-instances');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  StronglyReachableInstancesElement _strong;
+
+  void render() {
+    _strong = _strong ??
+        new StronglyReachableInstancesElement(
+            _isolate, _cls, _stronglyReachableInstances, _objects,
+            queue: _r.queue);
+    final instanceCount = _cls.newSpace.instances + _cls.oldSpace.instances;
+    final size = Utils.formatSize(_cls.newSpace.size + _cls.oldSpace.size);
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = const ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = const ['memberName']
+                ..text = 'currently allocated',
+              new DivElement()
+                ..classes = const ['memberValue']
+                ..text = 'count ${instanceCount} (shallow size ${size})'
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'strongly reachable ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = <Element>[_strong.element]
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Space reachable from this object, '
+                'excluding class references'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Reachable size ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createReachableSizeValue()
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Space that would be reclaimed if references to this '
+                'object were replaced with null'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Retained size ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createRetainedSizeValue()
+            ],
+        ]
+    ];
+  }
+
+  List<Element> _createReachableSizeValue() {
+    final content = <Element>[];
+    if (_reachableSize != null) {
+      if (_reachableSize.isSentinel) {
+        content.add(
+            new SentinelValueElement(_reachableSize.asSentinel, queue: _r.queue)
+                .element);
+      } else {
+        content.add(new SpanElement()
+          ..text = Utils.formatSize(
+              int.parse(_reachableSize.asValue.valueAsString)));
+      }
+    } else {
+      content.add(new SpanElement()..text = '...');
+    }
+    final button = new ButtonElement()
+      ..classes = ['reachable_size']
+      ..disabled = _loadingReachableBytes
+      ..text = '↺';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _loadingReachableBytes = true;
+      _reachableSize = await _reachableSizes.get(_isolate, _cls.id);
+      _r.dirty();
+    });
+    content.add(button);
+    return content;
+  }
+
+  List<Element> _createRetainedSizeValue() {
+    final content = <Element>[];
+    if (_retainedSize != null) {
+      if (_retainedSize.isSentinel) {
+        content.add(
+            new SentinelValueElement(_retainedSize.asSentinel, queue: _r.queue)
+                .element);
+      } else {
+        content.add(new SpanElement()
+          ..text =
+              Utils.formatSize(int.parse(_retainedSize.asValue.valueAsString)));
+      }
+    } else {
+      content.add(new SpanElement()..text = '...');
+    }
+    final button = new ButtonElement()
+      ..classes = ['retained_size']
+      ..disabled = _loadingRetainedBytes
+      ..text = '↺';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _loadingRetainedBytes = true;
+      _retainedSize = await _retainedSizes.get(_isolate, _cls.id);
+      _r.dirty();
+    });
+    content.add(button);
+    return content;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/class_ref.dart b/runtime/observatory_2/lib/src/elements/class_ref.dart
new file mode 100644
index 0000000..e9f35b3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/class_ref.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class ClassRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ClassRefElement> _r;
+
+  Stream<RenderedEvent<ClassRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ClassRef _class;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ClassRef get cls => _class;
+
+  factory ClassRefElement(M.IsolateRef isolate, M.ClassRef cls,
+      {RenderingQueue queue}) {
+    assert(cls != null);
+    ClassRefElement e = new ClassRefElement.created();
+    e._r = new RenderingScheduler<ClassRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._class = cls;
+    return e;
+  }
+
+  ClassRefElement.created() : super.created('class-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(
+          href: (_isolate == null)
+              ? null
+              : Uris.inspect(_isolate, object: _class))
+        ..text = _class.name
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/class_tree.dart b/runtime/observatory_2/lib/src/elements/class_tree.dart
new file mode 100644
index 0000000..68eb936
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/class_tree.dart
@@ -0,0 +1,188 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library class_tree_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+
+class ClassTreeElement extends CustomElement implements Renderable {
+  RenderingScheduler<ClassTreeElement> _r;
+
+  Stream<RenderedEvent<ClassTreeElement>> get onRendered => _r.onRendered;
+
+  M.VMRef _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.ClassRepository _classes;
+  M.Class _object;
+  final _subclasses = <String, Iterable<M.Class>>{};
+  final _mixins = <String, List<M.Instance>>{};
+
+  factory ClassTreeElement(
+      M.VMRef vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ClassRepository classes,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(classes != null);
+    ClassTreeElement e = new ClassTreeElement.created();
+    e._r = new RenderingScheduler<ClassTreeElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._classes = classes;
+    return e;
+  }
+
+  ClassTreeElement.created() : super.created('class-tree');
+
+  @override
+  void attached() {
+    super.attached();
+    _refresh();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  VirtualTreeElement _tree;
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('class hierarchy'),
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()
+            ..text = 'Class Hierarchy (${_subclasses.length})',
+          new BRElement(),
+          new HRElement(),
+          _object == null
+              ? (new HeadingElement.h2()..text = 'Loading...')
+              : _createTree()
+        ]
+    ];
+  }
+
+  Element _createTree() {
+    _tree = new VirtualTreeElement(_create, _update, _children,
+        items: [_object], search: _search, queue: _r.queue);
+    _tree.expand(_object, autoExpandSingleChildNodes: true);
+    return _tree.element;
+  }
+
+  Future _refresh() async {
+    _object = null;
+    _subclasses.clear();
+    _mixins.clear();
+    _object = await _register(await _classes.getObject(_isolate));
+    _r.dirty();
+  }
+
+  Future<M.Class> _register(M.Class cls) async {
+    _subclasses[cls.id] = await Future.wait(
+        (await Future.wait(cls.subclasses.map(_getActualChildrens)))
+            .expand((f) => f)
+            .map(_register));
+    return cls;
+  }
+
+  Future<Iterable<M.Class>> _getActualChildrens(M.ClassRef ref) async {
+    var cls = await _classes.get(_isolate, ref.id);
+    if (cls.isPatch) {
+      return const [];
+    }
+    if (cls.mixin == null) {
+      return [cls];
+    }
+    return (await Future.wait(cls.subclasses.map(_getActualChildrens)))
+        .expand((f) => f)
+          ..forEach((subcls) {
+            _mixins[subcls.id] = (_mixins[subcls.id] ?? [])..add(cls.mixin);
+          });
+  }
+
+  static HtmlElement _create(toggle) {
+    return new DivElement()
+      ..classes = ['class-tree-item']
+      ..children = <Element>[
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  void _update(HtmlElement el, classDynamic, int index) {
+    M.Class cls = classDynamic;
+    virtualTreeUpdateLines(el.children[0], index);
+    if (cls.subclasses.isEmpty) {
+      el.children[1].text = '';
+    } else {
+      el.children[1].text = _tree.isExpanded(cls) ? '▼' : '►';
+    }
+    el.children[2].children = <Element>[
+      new ClassRefElement(_isolate, cls, queue: _r.queue).element
+    ];
+    if (_mixins[cls.id] != null) {
+      el.children[2].children.addAll(_createMixins(_mixins[cls.id]));
+    }
+  }
+
+  bool _search(Pattern pattern, classDynamic) {
+    M.Class cls = classDynamic;
+    return cls.name.contains(pattern);
+  }
+
+  List<Element> _createMixins(List<M.Instance> types) {
+    final children = types
+        .expand((type) => <Element>[
+              new SpanElement()..text = ', ',
+              type.typeClass == null
+                  ? (new SpanElement()..text = type.name.split('<').first)
+                  : new ClassRefElement(_isolate, type.typeClass,
+                          queue: _r.queue)
+                      .element
+            ])
+        .toList();
+    children.first.text = ' with ';
+    return children;
+  }
+
+  Iterable<M.Class> _children(classDynamic) {
+    M.Class cls = classDynamic;
+    return _subclasses[cls.id];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/class_view.dart b/runtime/observatory_2/lib/src/elements/class_view.dart
new file mode 100644
index 0000000..4dd190e
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/class_view.dart
@@ -0,0 +1,495 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library class_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_allocation_profile.dart';
+import 'package:observatory_2/src/elements/class_instances.dart';
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/error_ref.dart';
+import 'package:observatory_2/src/elements/eval_box.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/library_ref.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/source_inset.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ClassViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ClassViewElement> _r;
+
+  Stream<RenderedEvent<ClassViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Class _cls;
+  M.ClassRepository _classes;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.StronglyReachableInstancesRepository _stronglyReachableInstances;
+  M.FieldRepository _fields;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+  M.EvalRepository _eval;
+  M.ClassSampleProfileRepository _profiles;
+  Iterable<M.Field> _classFields;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Class get cls => _cls;
+
+  factory ClassViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Class cls,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ClassRepository classes,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.FieldRepository fields,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      M.EvalRepository eval,
+      M.StronglyReachableInstancesRepository stronglyReachable,
+      M.ClassSampleProfileRepository profiles,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(cls != null);
+    assert(classes != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(fields != null);
+    assert(scripts != null);
+    assert(objects != null);
+    assert(eval != null);
+    assert(stronglyReachable != null);
+    assert(profiles != null);
+    ClassViewElement e = new ClassViewElement.created();
+    e._r = new RenderingScheduler<ClassViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._cls = cls;
+    e._classes = classes;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._fields = fields;
+    e._scripts = scripts;
+    e._objects = objects;
+    e._eval = eval;
+    e._stronglyReachableInstances = stronglyReachable;
+    e._profiles = profiles;
+    return e;
+  }
+
+  ClassViewElement.created() : super.created('class-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _loadAdditionalData();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  ObjectCommonElement _common;
+  ClassInstancesElement _classInstances;
+  bool _loadProfile = false;
+
+  void render() {
+    _common = _common ??
+        new ObjectCommonElement(_isolate, _cls, _retainedSizes, _reachableSizes,
+            _references, _retainingPaths, _objects,
+            queue: _r.queue);
+    _classInstances = _classInstances ??
+        new ClassInstancesElement(_isolate, _cls, _retainedSizes,
+            _reachableSizes, _stronglyReachableInstances, _objects,
+            queue: _r.queue);
+    var header = '';
+    if (_cls.isAbstract) {
+      header += 'abstract ';
+    }
+    if (_cls.isPatch) {
+      header += 'patch ';
+    }
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavClassMenuElement(_isolate, _cls, queue: _r.queue).element,
+        (new NavRefreshElement(
+                label: 'Refresh Allocation Profile', queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _loadProfile = true;
+                _r.dirty();
+              }))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _common = null;
+                _classInstances = null;
+                _fieldsExpanded = null;
+                _functionsExpanded = null;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = '$header class ${_cls.name}',
+          new HRElement(),
+          _common.element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = _createMembers(),
+          new DivElement()
+            ..children = _cls.error == null
+                ? const []
+                : [
+                    new HRElement(),
+                    new ErrorRefElement(_cls.error, queue: _r.queue).element
+                  ],
+          new HRElement(),
+          new EvalBoxElement(_isolate, _cls, _objects, _eval, queue: _r.queue)
+              .element,
+          new HRElement(),
+          new HeadingElement.h2()..text = 'Fields & Functions',
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = _createElements(),
+          new HRElement(),
+          new HeadingElement.h2()..text = 'Instances',
+          new DivElement()..children = [_classInstances.element],
+          new HRElement(),
+          new HeadingElement.h2()..text = 'Allocations',
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Tracing allocations?	',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _cls.traceAllocations
+                    ? [
+                        new SpanElement()..text = 'Yes ',
+                        new ButtonElement()
+                          ..text = 'disable'
+                          ..onClick.listen((e) async {
+                            (e.target as ButtonElement).disabled = true;
+                            await _profiles.disable(_isolate, _cls);
+                            _loadProfile = true;
+                            _refresh();
+                          })
+                      ]
+                    : [
+                        new SpanElement()..text = 'No ',
+                        new ButtonElement()
+                          ..text = 'enable'
+                          ..onClick.listen((e) async {
+                            (e.target as ButtonElement).disabled = true;
+                            await _profiles.enable(_isolate, _cls);
+                            _refresh();
+                          })
+                      ]
+            ],
+          new DivElement()
+            ..children = _loadProfile
+                ? [
+                    new ClassAllocationProfileElement(
+                            _vm, _isolate, _cls, _profiles,
+                            queue: _r.queue)
+                        .element
+                  ]
+                : const [],
+          new DivElement()
+            ..children = _cls.location != null
+                ? [
+                    new HRElement(),
+                    new SourceInsetElement(_isolate, _cls.location, _scripts,
+                            _objects, _events,
+                            queue: _r.queue)
+                        .element
+                  ]
+                : const [],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  bool _fieldsExpanded;
+  bool _functionsExpanded;
+
+  List<Element> _createMembers() {
+    final members = <Element>[];
+    if (_cls.library != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'library',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              new LibraryRefElement(_isolate, _cls.library, queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_cls.location != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'script',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              new SourceLinkElement(_isolate, _cls.location, _scripts,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_cls.superclass != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'superclass',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              new ClassRefElement(_isolate, _cls.superclass, queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_cls.superType != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'supertype',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              new InstanceRefElement(_isolate, _cls.superType, _objects,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (cls.mixin != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'mixin',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              new InstanceRefElement(_isolate, _cls.mixin, _objects,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_cls.subclasses.length > 0) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'extended by',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = (_cls.subclasses
+                .expand((subcls) => <Element>[
+                      new ClassRefElement(_isolate, subcls, queue: _r.queue)
+                          .element,
+                      new SpanElement()..text = ', '
+                    ])
+                .toList()
+                  ..removeLast())
+        ]);
+    }
+
+    members.add(new BRElement());
+
+    if (_cls.interfaces.length > 0) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'implements',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = (_cls.interfaces
+                .expand((interf) => <Element>[
+                      new InstanceRefElement(_isolate, interf, _objects,
+                              queue: _r.queue)
+                          .element,
+                      new SpanElement()..text = ', '
+                    ])
+                .toList()
+                  ..removeLast())
+        ]);
+    }
+    if (_cls.name != _cls.vmName) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'vm name',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = '${_cls.vmName}'
+        ]);
+    }
+    return members;
+  }
+
+  List<Element> _createElements() {
+    final members = <Element>[];
+    if (_classFields != null && _classFields.isNotEmpty) {
+      final fields = _classFields.toList();
+      _fieldsExpanded = _fieldsExpanded ?? (fields.length <= 8);
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'fields ${fields.length}',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              (new CurlyBlockElement(expanded: _fieldsExpanded)
+                    ..onToggle
+                        .listen((e) => _fieldsExpanded = e.control.expanded)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = (fields
+                            .map<Element>((f) => new DivElement()
+                              ..classes = ['memberItem']
+                              ..children = <Element>[
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..children = <Element>[
+                                    new FieldRefElement(_isolate, f, _objects,
+                                            queue: _r.queue)
+                                        .element
+                                  ],
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = f.staticValue == null
+                                      ? const []
+                                      : [
+                                          anyRef(
+                                              _isolate, f.staticValue, _objects,
+                                              queue: _r.queue)
+                                        ]
+                              ])
+                            .toList())
+                    ])
+                  .element
+            ]
+        ]);
+    }
+
+    if (_cls.functions.isNotEmpty) {
+      final functions = _cls.functions.toList();
+      _functionsExpanded = _functionsExpanded ?? (functions.length <= 8);
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'functions (${functions.length})',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              (new CurlyBlockElement(expanded: _functionsExpanded)
+                    ..onToggle
+                        .listen((e) => _functionsExpanded = e.control.expanded)
+                    ..content = (functions
+                        .map<Element>((f) => new DivElement()
+                          ..classes = ['indent']
+                          ..children = <Element>[
+                            new FunctionRefElement(_isolate, f, queue: _r.queue)
+                                .element
+                          ])
+                        .toList()))
+                  .element
+            ]
+        ]);
+    }
+    return members;
+  }
+
+  Future _refresh() async {
+    _cls = await _classes.get(_isolate, _cls.id);
+    await _loadAdditionalData();
+    _r.dirty();
+  }
+
+  Future _loadAdditionalData() async {
+    _classFields =
+        await Future.wait(_cls.fields.map((f) => _fields.get(_isolate, f.id)));
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/code_ref.dart b/runtime/observatory_2/lib/src/elements/code_ref.dart
new file mode 100644
index 0000000..e0c3ab8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/code_ref.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library code_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, CodeRef, isSyntheticCode;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class CodeRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<CodeRefElement> _r;
+
+  Stream<RenderedEvent<CodeRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.CodeRef _code;
+
+  M.IsolateRef get isolate => _isolate;
+  M.CodeRef get code => _code;
+
+  factory CodeRefElement(M.IsolateRef isolate, M.CodeRef code,
+      {RenderingQueue queue}) {
+    assert(code != null);
+    CodeRefElement e = new CodeRefElement.created();
+    e._r = new RenderingScheduler<CodeRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._code = code;
+    return e;
+  }
+
+  CodeRefElement.created() : super.created('code-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(
+          href: ((M.isSyntheticCode(_code.kind)) || (_isolate == null))
+              ? null
+              : Uris.inspect(_isolate, object: _code))
+        ..text = _code.name
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/code_view.dart b/runtime/observatory_2/lib/src/elements/code_view.dart
new file mode 100644
index 0000000..5d27eba
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/code_view.dart
@@ -0,0 +1,642 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library code_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/app.dart'
+    show SortedTable, SortedTableColumn, SortedTableRow;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/objectpool_ref.dart';
+import 'package:observatory_2/utils.dart';
+
+class DisassemblyTable extends SortedTable {
+  DisassemblyTable(columns) : super(columns);
+}
+
+class InlineTable extends SortedTable {
+  InlineTable(columns) : super(columns);
+}
+
+class CodeViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<CodeViewElement> _r;
+
+  Stream<RenderedEvent<CodeViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Code _code;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+  DisassemblyTable disassemblyTable;
+  InlineTable inlineTable;
+
+  static const kDisassemblyColumnIndex = 3;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Code get context => _code;
+
+  factory CodeViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Code code,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(code != null);
+    assert(objects != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    CodeViewElement e = new CodeViewElement.created();
+    e._r = new RenderingScheduler<CodeViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._code = code;
+    e._objects = objects;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    return e;
+  }
+
+  CodeViewElement.created() : super.created('code-view') {
+    var columns = [
+      new SortedTableColumn('Address'),
+      new SortedTableColumn('Inclusive'),
+      new SortedTableColumn('Exclusive'),
+      new SortedTableColumn('Disassembly'),
+      new SortedTableColumn('Objects'),
+    ];
+    disassemblyTable = new DisassemblyTable(columns);
+    columns = [
+      new SortedTableColumn('Address'),
+      new SortedTableColumn('Inclusive'),
+      new SortedTableColumn('Exclusive'),
+      new SortedTableColumn('Functions'),
+    ];
+    inlineTable = new InlineTable(columns);
+  }
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  TableElement _disassemblyTable;
+  TableElement _inlineRangeTable;
+  Element _disassemblyTableBody;
+  Element _inlineRangeTableBody;
+
+  void render() {
+    if (_inlineRangeTable == null) {
+      _inlineRangeTable = new TableElement()..classes = ['table'];
+      _inlineRangeTable.createTHead().children = <Element>[
+        new TableRowElement()
+          ..children = <Element>[
+            document.createElement('th')
+              ..classes = ['address']
+              ..text = 'Address Range',
+            document.createElement('th')
+              ..classes = ['tick']
+              ..text = 'Inclusive',
+            document.createElement('th')
+              ..classes = ['tick']
+              ..text = 'Exclusive',
+            document.createElement('th')..text = 'Functions',
+          ]
+      ];
+      _inlineRangeTableBody = _inlineRangeTable.createTBody();
+      _inlineRangeTableBody.classes = ['monospace'];
+    }
+    if (_disassemblyTable == null) {
+      _disassemblyTable = new TableElement()..classes = ['table'];
+      _disassemblyTable.createTHead().children = <Element>[
+        new TableRowElement()
+          ..children = <Element>[
+            document.createElement('th')
+              ..classes = ['address']
+              ..text = 'Address Range',
+            document.createElement('th')
+              ..classes = ['tick']
+              ..title = 'Ticks with PC on the stack'
+              ..text = 'Inclusive',
+            document.createElement('th')
+              ..classes = ['tick']
+              ..title = 'Ticks with PC at top of stack'
+              ..text = 'Exclusive',
+            document.createElement('th')
+              ..classes = ['disassembly']
+              ..text = 'Disassembly',
+            document.createElement('th')
+              ..classes = ['object']
+              ..text = 'Object',
+          ]
+      ];
+      _disassemblyTableBody = _disassemblyTable.createTBody();
+      _disassemblyTableBody.classes = ['monospace'];
+    }
+    final inlinedFunctions = _code.inlinedFunctions.toList();
+    final S.Code code = _code as S.Code;
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu(_code.name),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'refresh ticks', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refreshTicks();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h1()
+            ..text = (M.isDartCode(_code.kind) && _code.isOptimized)
+                ? 'Optimized code for ${_code.name}'
+                : 'Code for ${_code.name}',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _code, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Kind',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = _codeKindToString(_code.kind)
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = M.isDartCode(_code.kind)
+                    ? const []
+                    : [
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text = 'Optimized',
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..text = _code.isOptimized ? 'Yes' : 'No'
+                      ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Function',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      new FunctionRefElement(_isolate, _code.function,
+                              queue: _r.queue)
+                          .element
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = code.profile == null
+                    ? const []
+                    : [
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text = 'Inclusive',
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..text = '${code.profile.formattedInclusiveTicks}'
+                      ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = code.profile == null
+                    ? const []
+                    : [
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text = 'Exclusive',
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..text = '${code.profile.formattedExclusiveTicks}'
+                      ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Object pool',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      new ObjectPoolRefElement(_isolate, _code.objectPool,
+                              queue: _r.queue)
+                          .element
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = inlinedFunctions.isNotEmpty
+                    ? const []
+                    : [
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text =
+                              'inlined functions (${inlinedFunctions.length})',
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..children = <Element>[
+                            (new CurlyBlockElement(
+                                    expanded: inlinedFunctions.length < 8,
+                                    queue: _r.queue)
+                                  ..content = inlinedFunctions
+                                      .map<Element>((f) =>
+                                          new FunctionRefElement(_isolate, f,
+                                                  queue: _r.queue)
+                                              .element)
+                                      .toList())
+                                .element
+                          ]
+                      ]
+            ],
+          new HRElement(),
+          _inlineRangeTable,
+          new HRElement(),
+          _disassemblyTable
+        ],
+    ];
+    _updateDisassembly();
+    _updateInline();
+  }
+
+  Future _refresh() async {
+    S.Code code = _code as S.Code;
+    await code.reload();
+    _r.dirty();
+  }
+
+  Future _refreshTicks() async {
+    S.Code code = _code as S.Code;
+    final isolate = code.isolate;
+    S.ServiceMap response =
+        await isolate.invokeRpc('_getCpuProfile', {'tags': 'None'});
+    final cpuProfile = new SampleProfile();
+    await cpuProfile.load(isolate, response);
+    _r.dirty();
+  }
+
+  String _formattedAddress(S.CodeInstruction instruction) {
+    if (instruction.address == 0) {
+      return '';
+    }
+    return '0x${instruction.address.toRadixString(16)}';
+  }
+
+  String _formattedAddressRange(S.CodeInlineInterval interval) {
+    String start = interval.start.toRadixString(16);
+    String end = interval.end.toRadixString(16);
+    return '[0x$start, 0x$end)';
+  }
+
+  String _formattedInclusiveInterval(S.CodeInlineInterval interval) {
+    S.Code code = _code as S.Code;
+    if (code.profile == null) {
+      return '';
+    }
+    var intervalTick = code.profile.intervalTicks[interval.start];
+    if (intervalTick == null) {
+      return '';
+    }
+    // Don't show inclusive ticks if they are the same as exclusive ticks.
+    if (intervalTick.inclusiveTicks == intervalTick.exclusiveTicks) {
+      return '';
+    }
+    var pcent = Utils.formatPercent(
+        intervalTick.inclusiveTicks, code.profile.profile.sampleCount);
+    return '$pcent (${intervalTick.inclusiveTicks})';
+  }
+
+  String _formattedExclusiveInterval(S.CodeInlineInterval interval) {
+    S.Code code = _code as S.Code;
+    if (code.profile == null) {
+      return '';
+    }
+    var intervalTick = code.profile.intervalTicks[interval.start];
+    if (intervalTick == null) {
+      return '';
+    }
+    var pcent = Utils.formatPercent(
+        intervalTick.exclusiveTicks, code.profile.profile.sampleCount);
+    return '$pcent (${intervalTick.exclusiveTicks})';
+  }
+
+  String _formattedInclusive(S.CodeInstruction instruction) {
+    S.Code code = _code as S.Code;
+    if (code.profile == null) {
+      return '';
+    }
+    var tick = code.profile.addressTicks[instruction.address];
+    if (tick == null) {
+      return '';
+    }
+    // Don't show inclusive ticks if they are the same as exclusive ticks.
+    if (tick.inclusiveTicks == tick.exclusiveTicks) {
+      return '';
+    }
+    var pcent = Utils.formatPercent(
+        tick.inclusiveTicks, code.profile.profile.sampleCount);
+    return '$pcent (${tick.inclusiveTicks})';
+  }
+
+  String _formattedExclusive(S.CodeInstruction instruction) {
+    S.Code code = _code as S.Code;
+    if (code.profile == null) {
+      return '';
+    }
+    var tick = code.profile.addressTicks[instruction.address];
+    if (tick == null) {
+      return '';
+    }
+    var pcent = Utils.formatPercent(
+        tick.exclusiveTicks, code.profile.profile.sampleCount);
+    return '$pcent (${tick.exclusiveTicks})';
+  }
+
+  void _updateDisassemblyTable() {
+    S.Code code = _code as S.Code;
+    disassemblyTable.clearRows();
+    if (code == null) {
+      return;
+    }
+    for (S.CodeInstruction instruction in code.instructions) {
+      var row = [
+        _formattedAddress(instruction),
+        _formattedInclusive(instruction),
+        _formattedExclusive(instruction),
+        instruction.human,
+        instruction.object
+      ];
+      disassemblyTable.addRow(new SortedTableRow(row));
+    }
+  }
+
+  void _addDisassemblyDOMRow() {
+    var tableBody = _disassemblyTableBody;
+    assert(tableBody != null);
+    var tr = new TableRowElement();
+
+    var cell;
+
+    // Add new space.
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+
+    tableBody.children.add(tr);
+  }
+
+  void _fillDisassemblyDOMRow(TableRowElement tr, int rowIndex) {
+    final row = disassemblyTable.rows[rowIndex];
+    final n = row.values.length;
+    for (var i = 0; i < n; i++) {
+      final cell = tr.children[i];
+      final content = row.values[i];
+      if (content is S.HeapObject) {
+        cell.children = <Element>[
+          anyRef(_isolate, content, _objects, queue: _r.queue)
+        ];
+      } else if (content != null) {
+        String text = '$content';
+        if (i == kDisassemblyColumnIndex) {
+          // Disassembly might be a comment. Reduce indentation, change styling,
+          // widen to span next column (which should be empty).
+          if (text.startsWith('        ;;')) {
+            cell.attributes['colspan'] = '2';
+            cell.classes.add('code-comment');
+            text = text.substring(6);
+          } else {
+            cell.attributes['colspan'] = '1';
+            cell.classes.remove('code-comment');
+          }
+        }
+        cell.text = text;
+      }
+    }
+  }
+
+  void _updateDisassemblyDOMTable() {
+    var tableBody = _disassemblyTableBody;
+    assert(tableBody != null);
+    // Resize DOM table.
+    if (tableBody.children.length > disassemblyTable.sortedRows.length) {
+      // Shrink the table.
+      var deadRows =
+          tableBody.children.length - disassemblyTable.sortedRows.length;
+      for (var i = 0; i < deadRows; i++) {
+        tableBody.children.removeLast();
+      }
+    } else if (tableBody.children.length < disassemblyTable.sortedRows.length) {
+      // Grow table.
+      var newRows =
+          disassemblyTable.sortedRows.length - tableBody.children.length;
+      for (var i = 0; i < newRows; i++) {
+        _addDisassemblyDOMRow();
+      }
+    }
+
+    assert(tableBody.children.length == disassemblyTable.sortedRows.length);
+
+    // Fill table.
+    var i = 0;
+    for (var tr in tableBody.children) {
+      var rowIndex = disassemblyTable.sortedRows[i];
+      _fillDisassemblyDOMRow(tr, rowIndex);
+      i++;
+    }
+  }
+
+  void _updateDisassembly() {
+    _updateDisassemblyTable();
+    _updateDisassemblyDOMTable();
+  }
+
+  void _updateInlineTable() {
+    inlineTable.clearRows();
+    S.Code code = _code as S.Code;
+    for (S.CodeInlineInterval interval in code.inlineIntervals) {
+      var row = [
+        interval,
+        _formattedInclusiveInterval(interval),
+        _formattedExclusiveInterval(interval),
+        interval.functions
+      ];
+      inlineTable.addRow(new SortedTableRow(row));
+    }
+  }
+
+  void _addInlineDOMRow() {
+    var tableBody = _inlineRangeTableBody;
+    assert(tableBody != null);
+    var tr = new TableRowElement();
+
+    var cell;
+
+    // Add new space.
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+    cell.classes.add('monospace');
+    cell = tr.insertCell(-1);
+
+    tableBody.children.add(tr);
+  }
+
+  void _fillInlineDOMRow(TableRowElement tr, int rowIndex) {
+    var row = inlineTable.rows[rowIndex];
+    var columns = row.values.length;
+    var addressRangeColumn = 0;
+    var functionsColumn = columns - 1;
+
+    {
+      var addressRangeCell = tr.children[addressRangeColumn];
+      var interval = row.values[addressRangeColumn];
+      var addressRangeString = _formattedAddressRange(interval);
+      var addressRangeElement = new SpanElement();
+      addressRangeElement.classes.add('monospace');
+      addressRangeElement.text = addressRangeString;
+      addressRangeCell.children.clear();
+      addressRangeCell.children.add(addressRangeElement);
+    }
+
+    for (var i = addressRangeColumn + 1; i < columns - 1; i++) {
+      var cell = tr.children[i];
+      cell.text = row.values[i].toString();
+    }
+    var functions = row.values[functionsColumn];
+    var functionsCell = tr.children[functionsColumn];
+    functionsCell.children.clear();
+    for (var func in functions) {
+      functionsCell.children
+          .add(new FunctionRefElement(_isolate, func, queue: _r.queue).element);
+      var gap = new SpanElement();
+      gap.style.minWidth = '1em';
+      gap.text = ' ';
+      functionsCell.children.add(gap);
+    }
+  }
+
+  void _updateInlineDOMTable() {
+    var tableBody = _inlineRangeTableBody;
+    // Resize DOM table.
+    if (tableBody.children.length > inlineTable.sortedRows.length) {
+      // Shrink the table.
+      var deadRows = tableBody.children.length - inlineTable.sortedRows.length;
+      for (var i = 0; i < deadRows; i++) {
+        tableBody.children.removeLast();
+      }
+    } else if (tableBody.children.length < inlineTable.sortedRows.length) {
+      // Grow table.
+      var newRows = inlineTable.sortedRows.length - tableBody.children.length;
+      for (var i = 0; i < newRows; i++) {
+        _addInlineDOMRow();
+      }
+    }
+    assert(tableBody.children.length == inlineTable.sortedRows.length);
+    // Fill table.
+    for (var i = 0; i < inlineTable.sortedRows.length; i++) {
+      var rowIndex = inlineTable.sortedRows[i];
+      var tr = tableBody.children[i];
+      _fillInlineDOMRow(tr, rowIndex);
+    }
+  }
+
+  void _updateInline() {
+    _updateInlineTable();
+    _updateInlineDOMTable();
+  }
+
+  static String _codeKindToString(M.CodeKind kind) {
+    switch (kind) {
+      case M.CodeKind.dart:
+        return 'dart';
+      case M.CodeKind.native:
+        return 'native';
+      case M.CodeKind.stub:
+        return 'stub';
+      case M.CodeKind.tag:
+        return 'tag';
+      case M.CodeKind.collected:
+        return 'collected';
+    }
+    throw new Exception('Unknown CodeKind ($kind)');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/containers/search_bar.dart b/runtime/observatory_2/lib/src/elements/containers/search_bar.dart
new file mode 100644
index 0000000..f4d83c6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/containers/search_bar.dart
@@ -0,0 +1,205 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as math;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class SearchResultSelected {
+  final SearchBarElement element;
+  final dynamic item;
+  SearchResultSelected(this.element, this.item);
+}
+
+typedef Iterable<dynamic> SearchBarSearchCallback(Pattern pattern);
+
+class SearchBarElement extends CustomElement implements Renderable {
+  RenderingScheduler<SearchBarElement> _r;
+
+  StreamController<SearchResultSelected> _onSearchResultSelected =
+      new StreamController<SearchResultSelected>.broadcast();
+
+  Stream<RenderedEvent<SearchBarElement>> get onRendered => _r.onRendered;
+  Stream<SearchResultSelected> get onSearchResultSelected =>
+      _onSearchResultSelected.stream;
+
+  StreamSubscription _onKeyDownSubscription;
+
+  Element _workspace;
+  SearchBarSearchCallback _search;
+  bool _isOpen;
+  bool _focusRequested = false;
+  String _lastValue = '';
+  List _results = const [];
+  int _current = 0;
+
+  bool get isOpen => _isOpen;
+  dynamic get current => _results.isNotEmpty ? _results[_current] : null;
+
+  set isOpen(bool value) {
+    if (!value) {
+      _input.value = '';
+      _lastValue = '';
+      if (_results.isNotEmpty) {
+        _results = const [];
+        _current = 0;
+        _triggerSearchResultSelected();
+      }
+    }
+    _isOpen = _r.checkAndReact(_isOpen, value);
+  }
+
+  factory SearchBarElement(SearchBarSearchCallback search,
+      {bool isOpen: false, Element workspace, RenderingQueue queue}) {
+    assert(search != null);
+    assert(isOpen != null);
+    SearchBarElement e = new SearchBarElement.created();
+    e._r = new RenderingScheduler<SearchBarElement>(e, queue: queue);
+    e._search = search;
+    e._isOpen = isOpen;
+    e._workspace = workspace;
+    return e;
+  }
+
+  SearchBarElement.created() : super.created('search-bar');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _workspace?.tabIndex = 1;
+    _onKeyDownSubscription = (_workspace ?? window).onKeyDown.listen((e) {
+      if (e.key.toLowerCase() == 'f' &&
+          !e.shiftKey &&
+          !e.altKey &&
+          e.ctrlKey != e.metaKey) {
+        if (e.metaKey == window.navigator.platform.startsWith('Mac')) {
+          e.stopPropagation();
+          e.preventDefault();
+          isOpen = true;
+          _focusRequested = true;
+          _r.dirty();
+        }
+      }
+    });
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    _onKeyDownSubscription.cancel();
+  }
+
+  TextInputElement _input;
+  SpanElement _resultsArea;
+
+  void render() {
+    if (_input == null) {
+      _input = new TextInputElement()
+        ..onKeyPress.listen((e) {
+          if (e.keyCode == KeyCode.ENTER) {
+            if (_input.value == '') {
+              _lastValue = '';
+              if (_results.isNotEmpty) {
+                _results = const [];
+                _current = 0;
+                _triggerSearchResultSelected();
+                _r.dirty();
+              }
+            } else if (_input.value != _lastValue) {
+              _lastValue = _input.value;
+              _results = _doSearch(_input.value);
+              _current = 0;
+              _triggerSearchResultSelected();
+              _r.dirty();
+            } else {
+              if (e.shiftKey) {
+                _prev();
+              } else {
+                _next();
+              }
+            }
+          }
+        });
+      _resultsArea = new SpanElement();
+      children = <Element>[
+        _input,
+        _resultsArea,
+        new ButtonElement()
+          ..text = '❌'
+          ..onClick.listen((_) {
+            isOpen = false;
+          })
+      ];
+    }
+    _resultsArea.nodes = [
+      new ButtonElement()
+        ..text = '▲'
+        ..disabled = _results.isEmpty
+        ..onClick.listen((_) => _prev()),
+      new Text(
+          '${math.min(_current + 1, _results.length)} / ${_results.length}'),
+      new ButtonElement()
+        ..text = '▼'
+        ..disabled = _results.isEmpty
+        ..onClick.listen((_) => _next()),
+    ];
+    style.visibility = isOpen ? null : 'collapse';
+    if (_focusRequested) {
+      _input.focus();
+      _focusRequested = false;
+    }
+  }
+
+  void update() {
+    if (!isOpen || _lastValue == '') {
+      return;
+    }
+    final item = current;
+    _results = _doSearch(_lastValue);
+    _current = math.max(0, _results.indexOf(item));
+    _r.dirty();
+  }
+
+  List<dynamic> _doSearch(String value) =>
+      _search(new _CaseInsensitivePatternString(value)).toList(growable: false);
+
+  void _prev() {
+    if (_results.isEmpty) {
+      return;
+    }
+    _current = (_current + _results.length - 1) % _results.length;
+    _triggerSearchResultSelected();
+    _r.dirty();
+  }
+
+  void _next() {
+    if (_results.isEmpty) {
+      return;
+    }
+    _current = (_current + 1) % _results.length;
+    _triggerSearchResultSelected();
+    _r.dirty();
+  }
+
+  void _triggerSearchResultSelected() {
+    _onSearchResultSelected.add(new SearchResultSelected(this, current));
+  }
+}
+
+class _CaseInsensitivePatternString implements Pattern {
+  final String _pattern;
+
+  _CaseInsensitivePatternString(String pattern)
+      : this._pattern = pattern.toLowerCase();
+
+  Iterable<Match> allMatches(String string, [int start = 0]) =>
+      _pattern.allMatches(string.toLowerCase(), start);
+
+  Match matchAsPrefix(String string, [int start = 0]) =>
+      _pattern.matchAsPrefix(string.toLowerCase(), start);
+}
diff --git a/runtime/observatory_2/lib/src/elements/containers/virtual_collection.dart b/runtime/observatory_2/lib/src/elements/containers/virtual_collection.dart
new file mode 100644
index 0000000..28bc24d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/containers/virtual_collection.dart
@@ -0,0 +1,259 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as math;
+import 'package:observatory_2/src/elements/containers/search_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+typedef HtmlElement VirtualCollectionCreateCallback();
+typedef List<HtmlElement> VirtualCollectionHeaderCallback();
+typedef void VirtualCollectionUpdateCallback(
+    HtmlElement el, dynamic item, int index);
+typedef bool VirtualCollectionSearchCallback(Pattern pattern, dynamic item);
+
+class VirtualCollectionElement extends CustomElement implements Renderable {
+  RenderingScheduler<VirtualCollectionElement> _r;
+
+  Stream<RenderedEvent<VirtualCollectionElement>> get onRendered =>
+      _r.onRendered;
+
+  VirtualCollectionCreateCallback _create;
+  VirtualCollectionHeaderCallback _createHeader;
+  VirtualCollectionUpdateCallback _update;
+  VirtualCollectionSearchCallback _search;
+  double _itemHeight;
+  int _top;
+  double _height;
+  List _items;
+  StreamSubscription _onScrollSubscription;
+  StreamSubscription _onResizeSubscription;
+
+  List get items => _items;
+
+  set items(Iterable value) {
+    _items = new List.unmodifiable(value);
+    _top = null;
+    _searcher?.update();
+    _r.dirty();
+  }
+
+  factory VirtualCollectionElement(VirtualCollectionCreateCallback create,
+      VirtualCollectionUpdateCallback update,
+      {Iterable items: const [],
+      VirtualCollectionHeaderCallback createHeader,
+      VirtualCollectionSearchCallback search,
+      RenderingQueue queue}) {
+    assert(create != null);
+    assert(update != null);
+    assert(items != null);
+    VirtualCollectionElement e = new VirtualCollectionElement.created();
+    e._r = new RenderingScheduler<VirtualCollectionElement>(e, queue: queue);
+    e._create = create;
+    e._createHeader = createHeader;
+    e._update = update;
+    e._search = search;
+    e._items = new List.unmodifiable(items);
+    return e;
+  }
+
+  VirtualCollectionElement.created() : super.created('virtual-collection');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _top = null;
+    _itemHeight = null;
+    _onScrollSubscription = _viewport.onScroll.listen(_onScroll);
+    _onResizeSubscription = window.onResize.listen(_onResize);
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = const [];
+    _onScrollSubscription.cancel();
+    _onResizeSubscription.cancel();
+  }
+
+  DivElement _header;
+  SearchBarElement _searcher;
+  final DivElement _viewport = new DivElement()
+    ..classes = ['viewport', 'container'];
+  final DivElement _spacer = new DivElement()..classes = ['spacer'];
+  final DivElement _buffer = new DivElement()..classes = ['buffer'];
+
+  static int safeFloor(double x) {
+    if (x.isNaN) return 0;
+    return x.floor();
+  }
+
+  static int safeCeil(double x) {
+    if (x.isNaN) return 0;
+    return x.ceil();
+  }
+
+  dynamic getItemFromElement(HtmlElement element) {
+    final el_index = _buffer.children.indexOf(element);
+    if (el_index < 0) {
+      return null;
+    }
+    final item_index =
+        _top + el_index - safeFloor(_buffer.children.length * _inverse_preload);
+    if (0 <= item_index && item_index < items.length) {
+      return _items[item_index];
+    }
+    return null;
+  }
+
+  /// The preloaded element before and after the visible area are:
+  /// 1/preload_size of the number of items in the visble area.
+  static const int _preload = 2;
+
+  /// L = length of all the elements loaded
+  /// l = length of the visible area
+  ///
+  /// L = l + 2 * l / _preload
+  /// l = L * _preload / (_preload + 2)
+  ///
+  /// tail = l / _preload = L * 1 / (_preload + 2) = L * _inverse_preload
+  static const double _inverse_preload = 1 / (_preload + 2);
+
+  var _takeIntoView;
+
+  void takeIntoView(item) {
+    _takeIntoView = item;
+    _r.dirty();
+  }
+
+  void render() {
+    if (children.isEmpty) {
+      children = <Element>[
+        _viewport
+          ..children = <Element>[
+            _spacer
+              ..children = <Element>[
+                _buffer..children = <Element>[_create()]
+              ],
+          ]
+      ];
+      if (_search != null) {
+        _searcher =
+            _searcher ?? new SearchBarElement(_doSearch, queue: _r.queue)
+              ..onSearchResultSelected.listen((e) {
+                takeIntoView(e.item);
+              });
+        children.insert(0, _searcher.element);
+      }
+      if (_createHeader != null) {
+        _header = new DivElement()
+          ..classes = ['header', 'container']
+          ..children = _createHeader();
+        children.insert(0, _header);
+        final rect = _header.getBoundingClientRect();
+        _header.classes.add('attached');
+        _viewport.style.top = '${rect.height}px';
+        final width = _header.children.fold(0.0, _foldWidth);
+        _buffer.style.minWidth = '${width}px';
+      }
+      _itemHeight = _buffer.children[0].getBoundingClientRect().height;
+      _height = getBoundingClientRect().height;
+    }
+
+    if (_takeIntoView != null) {
+      final index = items.indexOf(_takeIntoView);
+      if (index >= 0) {
+        final minScrollTop = _itemHeight * (index + 1) - _height;
+        final maxScrollTop = _itemHeight * index;
+        _viewport.scrollTop =
+            safeFloor((maxScrollTop - minScrollTop) / 2 + minScrollTop);
+      }
+      _takeIntoView = null;
+    }
+
+    final top = safeFloor(_viewport.scrollTop / _itemHeight);
+
+    _spacer.style.height = '${_itemHeight * (_items.length)}px';
+    final tail_length = safeCeil(_height / _itemHeight / _preload);
+    final length = tail_length * 2 + tail_length * _preload;
+
+    if (_buffer.children.length < length) {
+      while (_buffer.children.length != length) {
+        var e = _create();
+        e..style.display = 'hidden';
+        _buffer.children.add(e);
+      }
+      _top = null; // force update;
+    }
+
+    if ((_top == null) || ((top - _top).abs() >= tail_length)) {
+      _buffer.style.top = '${_itemHeight * (top - tail_length)}px';
+      int i = top - tail_length;
+      for (final HtmlElement e in _buffer.children) {
+        if (0 <= i && i < _items.length) {
+          e.style.display = null;
+          _update(e, _items[i], i);
+        } else {
+          e.style.display = 'hidden';
+        }
+        i++;
+      }
+      _top = top;
+    }
+
+    if (_searcher != null) {
+      final current = _searcher.current;
+      int i = _top - tail_length;
+      for (final HtmlElement e in _buffer.children) {
+        if (0 <= i && i < _items.length) {
+          if (_items[i] == current) {
+            e.classes.add('marked');
+          } else {
+            e.classes.remove('marked');
+          }
+        }
+        i++;
+      }
+    }
+    _updateHeader();
+  }
+
+  double _foldWidth(double value, Element child) {
+    return math.max(value, child.getBoundingClientRect().width);
+  }
+
+  void _updateHeader() {
+    if (_header != null) {
+      _header.style.left = '${-_viewport.scrollLeft}px';
+      final width = _buffer.getBoundingClientRect().width;
+      _header.children.last.style.width = '${width}px';
+    }
+  }
+
+  void _onScroll(_) {
+    _r.dirty();
+    // We anticipate the header in advance to avoid flickering
+    _updateHeader();
+  }
+
+  void _onResize(_) {
+    final newHeight = getBoundingClientRect().height;
+    if (newHeight > _height) {
+      _height = newHeight;
+      _r.dirty();
+    } else {
+      // Even if we are not updating the structure the computed size is going to
+      // change
+      _updateHeader();
+    }
+  }
+
+  Iterable<dynamic> _doSearch(Pattern search) {
+    return _items.where((item) => _search(search, item));
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/containers/virtual_tree.dart b/runtime/observatory_2/lib/src/elements/containers/virtual_tree.dart
new file mode 100644
index 0000000..ac5be43
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/containers/virtual_tree.dart
@@ -0,0 +1,183 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:collection';
+import 'dart:math' as Math;
+import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+typedef HtmlElement VirtualTreeCreateCallback(
+    toggle({bool autoToggleSingleChildNodes, bool autoToggleWholeTree}));
+typedef void VirtualTreeUpdateCallback(HtmlElement el, dynamic item, int depth);
+typedef Iterable<dynamic> VritualTreeGetChildrenCallback(dynamic value);
+typedef bool VirtualTreeSearchCallback(Pattern pattern, dynamic item);
+
+void virtualTreeUpdateLines(SpanElement element, int n) {
+  n = Math.max(0, n);
+  while (element.children.length > n) {
+    element.children.removeLast();
+  }
+  while (element.children.length < n) {
+    element.children.add(new SpanElement());
+  }
+}
+
+class VirtualTreeElement extends CustomElement implements Renderable {
+  RenderingScheduler<VirtualTreeElement> _r;
+
+  Stream<RenderedEvent<VirtualTreeElement>> get onRendered => _r.onRendered;
+
+  VritualTreeGetChildrenCallback _children;
+  List _items;
+  List _depths;
+  final Set _expanded = new Set();
+
+  List get items => _items;
+
+  set items(Iterable value) {
+    _items = new List.unmodifiable(value);
+    _expanded.clear();
+    _r.dirty();
+  }
+
+  factory VirtualTreeElement(VirtualTreeCreateCallback create,
+      VirtualTreeUpdateCallback update, VritualTreeGetChildrenCallback children,
+      {Iterable items: const [],
+      VirtualTreeSearchCallback search,
+      RenderingQueue queue}) {
+    assert(create != null);
+    assert(update != null);
+    assert(children != null);
+    assert(items != null);
+    VirtualTreeElement e = new VirtualTreeElement.created();
+    e._r = new RenderingScheduler<VirtualTreeElement>(e, queue: queue);
+    e._children = children;
+    e._collection = new VirtualCollectionElement(() {
+      var element;
+      return element = create((
+          {bool autoToggleSingleChildNodes: false,
+          bool autoToggleWholeTree: false}) {
+        var item = e._collection.getItemFromElement(element);
+        if (e.isExpanded(item)) {
+          e.collapse(item,
+              autoCollapseWholeTree: autoToggleWholeTree,
+              autoCollapseSingleChildNodes: autoToggleSingleChildNodes);
+        } else {
+          e.expand(item,
+              autoExpandWholeTree: autoToggleWholeTree,
+              autoExpandSingleChildNodes: autoToggleSingleChildNodes);
+        }
+      });
+    }, (HtmlElement el, dynamic item, int index) {
+      update(el, item, e._depths[index]);
+    }, search: search, queue: queue);
+    e._items = new List.unmodifiable(items);
+    return e;
+  }
+
+  VirtualTreeElement.created() : super.created('virtual-tree');
+
+  bool isExpanded(item) {
+    return _expanded.contains(item);
+  }
+
+  void expand(item,
+      {bool autoExpandSingleChildNodes: false,
+      bool autoExpandWholeTree: false}) {
+    if (_expanded.add(item)) _r.dirty();
+    if (autoExpandWholeTree) {
+      // The tree is potentially very deep, simple recursion can produce a
+      // Stack Overflow
+      Queue pendingNodes = new Queue();
+      pendingNodes.addAll(_children(item));
+      while (pendingNodes.isNotEmpty) {
+        final item = pendingNodes.removeFirst();
+        if (_expanded.add(item)) _r.dirty();
+        pendingNodes.addAll(_children(item));
+      }
+    } else if (autoExpandSingleChildNodes) {
+      var children = _children(item);
+      while (children.length == 1) {
+        _expanded.add(children.first);
+        children = _children(children.first);
+      }
+    }
+  }
+
+  void collapse(item,
+      {bool autoCollapseSingleChildNodes: false,
+      bool autoCollapseWholeTree: false}) {
+    if (_expanded.remove(item)) _r.dirty();
+    if (autoCollapseWholeTree) {
+      // The tree is potentially very deep, simple recursion can produce a
+      // Stack Overflow
+      Queue pendingNodes = new Queue();
+      pendingNodes.addAll(_children(item));
+      while (pendingNodes.isNotEmpty) {
+        final item = pendingNodes.removeFirst();
+        if (_expanded.remove(item)) _r.dirty();
+        pendingNodes.addAll(_children(item));
+      }
+    } else if (autoCollapseSingleChildNodes) {
+      var children = _children(item);
+      while (children.length == 1) {
+        _expanded.remove(children.first);
+        children = _children(children.first);
+      }
+    }
+  }
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = const [];
+  }
+
+  VirtualCollectionElement _collection;
+
+  void render() {
+    if (children.length == 0) {
+      children = <Element>[_collection.element];
+    }
+
+    final items = [];
+    final depths = new List.filled(_items.length, 0, growable: true);
+
+    {
+      final toDo = new Queue();
+
+      toDo.addAll(_items);
+      while (toDo.isNotEmpty) {
+        final item = toDo.removeFirst();
+
+        items.add(item);
+        if (isExpanded(item)) {
+          final children = _children(item);
+          children
+              .toList(growable: false)
+              .reversed
+              .forEach((c) => toDo.addFirst(c));
+          final depth = depths[items.length - 1];
+          depths.insertAll(
+              items.length, new List.filled(children.length, depth + 1));
+        }
+      }
+    }
+
+    _depths = depths;
+    _collection.items = items;
+
+    _r.waitFor([_collection.onRendered.first]);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/context_ref.dart b/runtime/observatory_2/lib/src/elements/context_ref.dart
new file mode 100644
index 0000000..85531a2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/context_ref.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class ContextRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ContextRefElement> _r;
+
+  Stream<RenderedEvent<ContextRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ContextRef _context;
+  M.ObjectRepository _objects;
+  M.Context _loadedContext;
+  bool _expandable;
+  bool _expanded = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ContextRef get context => _context;
+
+  factory ContextRefElement(
+      M.IsolateRef isolate, M.ContextRef context, M.ObjectRepository objects,
+      {RenderingQueue queue, bool expandable: true}) {
+    assert(isolate != null);
+    assert(context != null);
+    assert(objects != null);
+    ContextRefElement e = new ContextRefElement.created();
+    e._r = new RenderingScheduler<ContextRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._context = context;
+    e._objects = objects;
+    e._expandable = expandable;
+    return e;
+  }
+
+  ContextRefElement.created() : super.created('context-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  Future _refresh() async {
+    _loadedContext = await _objects.get(_isolate, _context.id);
+    _r.dirty();
+  }
+
+  void render() {
+    var children = <HtmlElement>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _context))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'Context',
+          new SpanElement()..text = ' (${_context.length})',
+        ],
+    ];
+    if (_expandable) {
+      children.addAll([
+        new SpanElement()..text = ' ',
+        (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..children = _createValue()
+              ]
+              ..onToggle.listen((e) async {
+                _expanded = e.control.expanded;
+                if (_expanded) {
+                  e.control.disabled = true;
+                  await _refresh();
+                  e.control.disabled = false;
+                }
+              }))
+            .element
+      ]);
+    }
+    this.children = children;
+  }
+
+  List<Element> _createValue() {
+    if (_loadedContext == null) {
+      return [new SpanElement()..text = 'Loading...'];
+    }
+    var members = <Element>[];
+    if (_loadedContext.parentContext != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'parent context',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new ContextRefElement(
+                      _isolate, _loadedContext.parentContext, _objects,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_loadedContext.variables.isNotEmpty) {
+      var variables = _loadedContext.variables.toList();
+      for (var index = 0; index < variables.length; index++) {
+        var variable = variables[index];
+        members.add(new DivElement()
+          ..classes = ['memberItem']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['memberName']
+              ..text = '[ $index ]',
+            new DivElement()
+              ..classes = ['memberName']
+              ..children = <Element>[
+                anyRef(_isolate, variable.value, _objects, queue: _r.queue)
+              ]
+          ]);
+      }
+    }
+    return [
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = members
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/context_view.dart b/runtime/observatory_2/lib/src/elements/context_view.dart
new file mode 100644
index 0000000..3b759eb
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/context_view.dart
@@ -0,0 +1,195 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ContextViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ContextViewElement> _r;
+
+  Stream<RenderedEvent<ContextViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Context _context;
+  M.ContextRepository _contexts;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Context get context => _context;
+
+  factory ContextViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Context context,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ContextRepository contexts,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(context != null);
+    assert(contexts != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    ContextViewElement e = new ContextViewElement.created();
+    e._r = new RenderingScheduler<ContextViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._context = context;
+    e._contexts = contexts;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  ContextViewElement.created() : super.created('context-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavClassMenuElement(_isolate, _context.clazz, queue: _r.queue)
+            .element,
+        navMenu('instance'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _context = await _contexts.get(_isolate, _context.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Context',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _context, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element
+        ]
+    ];
+    if (_context.parentContext != null) {
+      content.addAll([
+        new BRElement(),
+        new DivElement()
+          ..classes = ['content-centered-big']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['memberList']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberItem']
+                  ..children = <Element>[
+                    new DivElement()
+                      ..classes = ['memberName']
+                      ..text = 'parent context',
+                    new DivElement()
+                      ..classes = ['memberName']
+                      ..children = <Element>[
+                        new ContextRefElement(
+                                _isolate, _context.parentContext, _objects,
+                                queue: _r.queue)
+                            .element
+                      ]
+                  ]
+              ]
+          ]
+      ]);
+    }
+    content.add(new HRElement());
+    if (_context.variables.isNotEmpty) {
+      int index = 0;
+      content.addAll([
+        new DivElement()
+          ..classes = ['content-centered-big']
+          ..children = <Element>[
+            new SpanElement()..text = 'Variables ',
+            (new CurlyBlockElement(expanded: true, queue: _r.queue)
+                  ..content = <Element>[
+                    new DivElement()
+                      ..classes = ['memberList']
+                      ..children = _context.variables
+                          .map<Element>((variable) => new DivElement()
+                            ..classes = ['memberItem']
+                            ..children = <Element>[
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..text = '[ ${++index} ]',
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..children = <Element>[
+                                  anyRef(_isolate, variable.value, _objects,
+                                      queue: _r.queue)
+                                ]
+                            ])
+                          .toList()
+                  ])
+                .element
+          ]
+      ]);
+    }
+    content.add(new DivElement()
+      ..classes = ['content-centered-big']
+      ..children = <Element>[new ViewFooterElement(queue: _r.queue).element]);
+    children = content;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/cpu_profile.dart b/runtime/observatory_2/lib/src/elements/cpu_profile.dart
new file mode 100644
index 0000000..57ad7e1
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/cpu_profile.dart
@@ -0,0 +1,169 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cpu_profile_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/sample_buffer_control.dart';
+import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
+
+class CpuProfileElement extends CustomElement implements Renderable {
+  RenderingScheduler<CpuProfileElement> _r;
+
+  Stream<RenderedEvent<CpuProfileElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.IsolateSampleProfileRepository _profiles;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag = M.SampleProfileTag.none;
+  ProfileTreeMode _mode = ProfileTreeMode.function;
+  M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
+  String _filter = '';
+
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.IsolateSampleProfileRepository get profiles => _profiles;
+  M.VMRef get vm => _vm;
+
+  factory CpuProfileElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.IsolateSampleProfileRepository profiles,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(profiles != null);
+    CpuProfileElement e = new CpuProfileElement.created();
+    e._r = new RenderingScheduler<CpuProfileElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._profiles = profiles;
+    return e;
+  }
+
+  CpuProfileElement.created() : super.created('cpu-profile');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _request();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('cpu profile', link: Uris.cpuProfiler(_isolate)),
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        (new NavRefreshElement(label: 'Clear', queue: _r.queue)
+              ..onRefresh.listen(_clearCpuProfile))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+    ];
+    if (_progress == null) {
+      children = content;
+      return;
+    }
+    content.add((new SampleBufferControlElement(_vm, _progress, _progressStream,
+            selectedTag: _tag, queue: _r.queue)
+          ..onTagChange.listen((e) {
+            _tag = e.element.selectedTag;
+            _request();
+          }))
+        .element);
+    if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+      CpuProfileVirtualTreeElement tree;
+      content.addAll([
+        new BRElement(),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                filter: _filter,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onFilterChange.listen((e) {
+                _filter = e.element.filter.trim();
+                tree.filters = _filter.isNotEmpty
+                    ? [
+                        (node) {
+                          return node.name.contains(_filter);
+                        }
+                      ]
+                    : const [];
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
+        new BRElement(),
+        (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+                queue: _r.queue))
+            .element
+      ]);
+    }
+    children = content;
+  }
+
+  Future _request({bool clear: false, bool forceFetch: false}) async {
+    _progress = null;
+    _progressStream =
+        _profiles.get(isolate, _tag, clear: clear, forceFetch: forceFetch);
+    _r.dirty();
+    _progress = (await _progressStream.first).progress;
+    _r.dirty();
+    if (M.isSampleProcessRunning(_progress.status)) {
+      _progress = (await _progressStream.last).progress;
+      _r.dirty();
+    }
+  }
+
+  Future _clearCpuProfile(RefreshEvent e) async {
+    e.element.disabled = true;
+    await _request(clear: true);
+    e.element.disabled = false;
+  }
+
+  Future _refresh(e) async {
+    e.element.disabled = true;
+    await _request(forceFetch: true);
+    e.element.disabled = false;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/cpu_profile/virtual_tree.dart b/runtime/observatory_2/lib/src/elements/cpu_profile/virtual_tree.dart
new file mode 100644
index 0000000..2889650
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/cpu_profile/virtual_tree.dart
@@ -0,0 +1,308 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as Math;
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/stack_trace_tree_config.dart'
+    show ProfileTreeMode;
+import 'package:observatory_2/src/elements/code_ref.dart';
+import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/utils.dart';
+
+export 'package:observatory_2/src/elements/stack_trace_tree_config.dart'
+    show ProfileTreeMode;
+
+class CpuProfileVirtualTreeElement extends CustomElement implements Renderable {
+  RenderingScheduler<CpuProfileVirtualTreeElement> _r;
+
+  Stream<RenderedEvent<CpuProfileVirtualTreeElement>> get onRendered =>
+      _r.onRendered;
+
+  M.ProfileTreeDirection _direction;
+  ProfileTreeMode _mode;
+  M.SampleProfileType _type;
+  M.IsolateRef _isolate;
+  M.SampleProfile _profile;
+  Iterable<M.CallTreeNodeFilter> _filters;
+
+  M.ProfileTreeDirection get direction => _direction;
+  ProfileTreeMode get mode => _mode;
+  M.SampleProfileType get type => _type;
+  M.IsolateRef get isolate => _isolate;
+  M.SampleProfile get profile => _profile;
+  Iterable<M.CallTreeNodeFilter> get filters => _filters;
+
+  set direction(M.ProfileTreeDirection value) =>
+      _direction = _r.checkAndReact(_direction, value);
+  set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+  set filters(Iterable<M.CallTreeNodeFilter> value) {
+    _filters = new List.unmodifiable(value);
+    _r.dirty();
+  }
+
+  factory CpuProfileVirtualTreeElement(Object owner, M.SampleProfile profile,
+      {ProfileTreeMode mode: ProfileTreeMode.function,
+      M.SampleProfileType type: M.SampleProfileType.cpu,
+      M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+      RenderingQueue queue}) {
+    assert(profile != null);
+    assert(mode != null);
+    assert(direction != null);
+    CpuProfileVirtualTreeElement e = new CpuProfileVirtualTreeElement.created();
+    e._r =
+        new RenderingScheduler<CpuProfileVirtualTreeElement>(e, queue: queue);
+    e._isolate = owner;
+    e._profile = profile;
+    e._mode = mode;
+    e._type = type;
+    e._direction = direction;
+    return e;
+  }
+
+  CpuProfileVirtualTreeElement.created()
+      : super.created('cpu-profile-virtual-tree');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  VirtualTreeElement _tree;
+
+  void render() {
+    var tree;
+    var create;
+    var update;
+    var search;
+    switch (type) {
+      case M.SampleProfileType.cpu:
+        create = _createCpuRow;
+        if (mode == ProfileTreeMode.code) {
+          update = _updateCpuCodeRow;
+          search = _searchCode;
+          tree = _profile.loadCodeTree(_direction);
+        } else if (mode == ProfileTreeMode.function) {
+          update = _updateCpuFunctionRow;
+          search = _searchFunction;
+          tree = _profile.loadFunctionTree(_direction);
+        } else {
+          throw new Exception('Unknown ProfileTreeMode: $mode');
+        }
+        break;
+      case M.SampleProfileType.memory:
+        create = _createMemoryRow;
+        if (mode == ProfileTreeMode.code) {
+          update = _updateMemoryCodeRow;
+          search = _searchCode;
+          tree = _profile.loadCodeTree(_direction);
+        } else if (mode == ProfileTreeMode.function) {
+          update = _updateMemoryFunctionRow;
+          search = _searchFunction;
+          tree = _profile.loadFunctionTree(_direction);
+        } else {
+          throw new Exception('Unknown ProfileTreeMode: $mode');
+        }
+        break;
+      default:
+        throw new Exception('Unknown SampleProfileType: $type');
+    }
+    if (filters != null) {
+      tree = filters.fold(tree, (tree, filter) {
+        return tree?.filtered(filter);
+      });
+    }
+    if (tree == null) {
+      children = <Element>[new HeadingElement.h1()..text = 'No Results'];
+      return;
+    }
+    _tree = new VirtualTreeElement(create, update, _getChildren,
+        items: tree.root.children, search: search, queue: _r.queue);
+    if (tree.root.children.length == 0) {
+      children = <Element>[
+        new DivElement()
+          ..classes = ['tree-item']
+          ..children = <Element>[new HeadingElement.h1()..text = 'No Samples']
+      ];
+      return;
+    } else if (tree.root.children.length == 1) {
+      _tree.expand(tree.root.children.first, autoExpandSingleChildNodes: true);
+    }
+    children = <Element>[_tree.element];
+  }
+
+  static HtmlElement _createCpuRow(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['inclusive']
+          ..title = 'global % on stack',
+        new SpanElement()
+          ..classes = ['exclusive']
+          ..title = 'global % executing',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'tree node %',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createMemoryRow(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['inclusive']
+          ..title = 'memory allocated from resulting calls: ',
+        new SpanElement()
+          ..classes = ['exclusive']
+          ..title = 'memory allocated during execution: ',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'tree node %',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static Iterable<M.CallTreeNode> _getChildren(nodeDynamic) {
+    M.CallTreeNode node = nodeDynamic;
+    return node.children;
+  }
+
+  static const String _expandedIcon = '▼';
+  static const String _collapsedIcon = '►';
+
+  void _updateCpuFunctionRow(HtmlElement element, itemDynamic, int depth) {
+    M.FunctionCallTreeNode item = itemDynamic;
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileFunction.normalizedExclusiveTicks);
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text =
+          _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(item.percentage);
+    element.children[5] = (new FunctionRefElement(
+            _isolate, item.profileFunction.function,
+            queue: _r.queue)
+          ..classes = ['name'])
+        .element;
+  }
+
+  void _updateMemoryFunctionRow(HtmlElement element, itemDynamic, int depth) {
+    M.FunctionCallTreeNode item = itemDynamic;
+    element.children[0].text =
+        Utils.formatSize(item.inclusiveNativeAllocations);
+    element.children[0].title = 'memory allocated from resulting calls: '
+        '${item.inclusiveNativeAllocations}B';
+    element.children[1].text =
+        Utils.formatSize(item.exclusiveNativeAllocations);
+    element.children[1].title = 'memory allocated during execution: '
+        '${item.exclusiveNativeAllocations}B';
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text =
+          _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(item.percentage);
+    element.children[5] = (new FunctionRefElement(
+            null, item.profileFunction.function,
+            queue: _r.queue)
+          ..classes = ['name'])
+        .element;
+  }
+
+  bool _searchFunction(Pattern pattern, itemDynamic) {
+    M.FunctionCallTreeNode item = itemDynamic;
+    return M
+        .getFunctionFullName(item.profileFunction.function)
+        .contains(pattern);
+  }
+
+  void _updateCpuCodeRow(HtmlElement element, itemDynamic, int depth) {
+    M.CodeCallTreeNode item = itemDynamic;
+    element.children[0].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedInclusiveTicks);
+    element.children[1].text = Utils.formatPercentNormalized(
+        item.profileCode.normalizedExclusiveTicks);
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text =
+          _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(item.percentage);
+    element.children[5] =
+        (new CodeRefElement(_isolate, item.profileCode.code, queue: _r.queue)
+              ..classes = ['name'])
+            .element;
+  }
+
+  void _updateMemoryCodeRow(HtmlElement element, itemDynamic, int depth) {
+    M.CodeCallTreeNode item = itemDynamic;
+    element.children[0].text =
+        Utils.formatSize(item.inclusiveNativeAllocations);
+    element.children[0].title = 'memory allocated from resulting calls: '
+        '${item.inclusiveNativeAllocations}B';
+    element.children[1].text =
+        Utils.formatSize(item.exclusiveNativeAllocations);
+    element.children[1].title = 'memory allocated during execution: '
+        '${item.exclusiveNativeAllocations}B';
+    _updateLines(element.children[2].children, depth);
+    if (item.children.isNotEmpty) {
+      element.children[3].text =
+          _tree.isExpanded(item) ? _expandedIcon : _collapsedIcon;
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = Utils.formatPercentNormalized(item.percentage);
+    element.children[5] =
+        (new CodeRefElement(null, item.profileCode.code, queue: _r.queue)
+              ..classes = ['name'])
+            .element;
+  }
+
+  bool _searchCode(Pattern pattern, itemDynamic) {
+    M.CodeCallTreeNode item = itemDynamic;
+    return item.profileCode.code.name.contains(pattern);
+  }
+
+  static _updateLines(List<Element> lines, int n) {
+    n = Math.max(0, n);
+    while (lines.length > n) {
+      lines.removeLast();
+    }
+    while (lines.length < n) {
+      lines.add(new SpanElement());
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/cpu_profile_table.dart b/runtime/observatory_2/lib/src/elements/cpu_profile_table.dart
new file mode 100644
index 0000000..c68d00a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/cpu_profile_table.dart
@@ -0,0 +1,473 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library cpu_profile_table_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
+import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/sample_buffer_control.dart';
+import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
+import 'package:observatory_2/utils.dart';
+
+enum _Table { functions, caller, callee }
+
+enum _SortingField { exclusive, inclusive, caller, callee, method }
+
+enum _SortingDirection { ascending, descending }
+
+class CpuProfileTableElement extends CustomElement implements Renderable {
+  RenderingScheduler<CpuProfileTableElement> _r;
+
+  Stream<RenderedEvent<CpuProfileTableElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.IsolateSampleProfileRepository _profiles;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  final _sortingField = <_Table, _SortingField>{
+    _Table.functions: _SortingField.exclusive,
+    _Table.caller: _SortingField.caller,
+    _Table.callee: _SortingField.callee,
+  };
+  final _sortingDirection = <_Table, _SortingDirection>{
+    _Table.functions: _SortingDirection.descending,
+    _Table.caller: _SortingDirection.descending,
+    _Table.callee: _SortingDirection.descending,
+  };
+  String _filter = '';
+
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.IsolateSampleProfileRepository get profiles => _profiles;
+  M.VMRef get vm => _vm;
+
+  factory CpuProfileTableElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.IsolateSampleProfileRepository profiles,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(profiles != null);
+    CpuProfileTableElement e = new CpuProfileTableElement.created();
+    e._r = new RenderingScheduler<CpuProfileTableElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._profiles = profiles;
+    return e;
+  }
+
+  CpuProfileTableElement.created() : super.created('cpu-profile-table');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _request();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('cpu profile (table)'),
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        (new NavRefreshElement(label: 'Clear', queue: _r.queue)
+              ..onRefresh.listen(_clearCpuSamples))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+    ];
+    if (_progress == null) {
+      children = content;
+      return;
+    }
+    content.add(new SampleBufferControlElement(_vm, _progress, _progressStream,
+            showTag: false, queue: _r.queue)
+        .element);
+    if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+      content.add(new BRElement());
+      content.addAll(_createTables());
+      content.add(new BRElement());
+      content.addAll(_createTree());
+    }
+    children = content;
+  }
+
+  M.ProfileFunction _selected;
+  VirtualCollectionElement _functions;
+  VirtualCollectionElement _callers;
+  VirtualCollectionElement _callees;
+
+  List<Element> _createTables() {
+    _functions = _functions ??
+        new VirtualCollectionElement(_createFunction, _updateFunction,
+            createHeader: _createFunctionHeader,
+            search: _searchFunction,
+            queue: _r.queue);
+    // If there's no samples, don't populate the function list.
+    _functions.items = (_progress.profile.sampleCount != 0)
+        ? _progress.profile.functions.toList()
+        : []
+      ..sort(_createSorter(_Table.functions));
+    _functions.takeIntoView(_selected);
+    _callers = _callers ??
+        new VirtualCollectionElement(_createCaller, _updateCaller,
+            createHeader: _createCallerHeader,
+            search: _searchFunction,
+            queue: _r.queue);
+    _callees = _callees ??
+        new VirtualCollectionElement(_createCallee, _updateCallee,
+            createHeader: _createCalleeHeader,
+            search: _searchFunction,
+            queue: _r.queue);
+    if (_selected != null) {
+      _callers.items = _selected.callers.keys.toList()
+        ..sort(_createSorter(_Table.caller));
+      _callees.items = _selected.callees.keys.toList()
+        ..sort(_createSorter(_Table.callee));
+    } else {
+      _callers.items = const [];
+      _callees.items = const [];
+    }
+    return <Element>[
+      new DivElement()
+        ..classes = ['profile-trees']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['profile-trees-all']
+            ..children = <Element>[_functions.element],
+          new DivElement()
+            ..classes = ['profile-trees-current']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['profile-trees-caller']
+                ..children = <Element>[_callers.element],
+              new DivElement()
+                ..classes = ['profile-trees-selected']
+                ..children = _selected == null
+                    ? [new SpanElement()..text = 'No element selected']
+                    : [
+                        new FunctionRefElement(_isolate, _selected.function,
+                                queue: _r.queue)
+                            .element
+                      ],
+              new DivElement()
+                ..classes = ['profile-trees-callee']
+                ..children = <Element>[_callees.element]
+            ]
+        ]
+    ];
+  }
+
+  HtmlElement _createFunction() {
+    final element = new DivElement()
+      ..classes = ['function-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['exclusive']
+          ..text = '0%',
+        new SpanElement()
+          ..classes = ['inclusive']
+          ..text = '0%',
+        new SpanElement()..classes = ['name']
+      ];
+    element.onClick.listen((e) {
+      if (e.target is AnchorElement) {
+        return;
+      }
+      _selected = _functions.getItemFromElement(element);
+      _r.dirty();
+    });
+    return element;
+  }
+
+  void _updateFunction(Element e, itemDynamic, int index) {
+    M.ProfileFunction item = itemDynamic;
+    if (item == _selected) {
+      e.classes = ['function-item', 'selected'];
+    } else {
+      e.classes = ['function-item'];
+    }
+    e.children[0].text = Utils.formatPercentNormalized(_getExclusiveT(item));
+    e.children[1].text = Utils.formatPercentNormalized(_getInclusiveT(item));
+    e.children[2].text = M.getFunctionFullName(item.function);
+  }
+
+  List<HtmlElement> _createFunctionHeader() => [
+        new DivElement()
+          ..classes = ['function-item']
+          ..children = <Element>[
+            _createHeaderButton(
+                const ['exclusive'],
+                'Execution(%)',
+                _Table.functions,
+                _SortingField.exclusive,
+                _SortingDirection.descending),
+            _createHeaderButton(
+                const ['inclusive'],
+                'Stack(%)',
+                _Table.functions,
+                _SortingField.inclusive,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['name'], 'Method', _Table.functions,
+                _SortingField.method, _SortingDirection.ascending),
+          ]
+      ];
+
+  bool _searchFunction(Pattern pattern, itemDynamic) {
+    M.ProfileFunction item = itemDynamic;
+    return M.getFunctionFullName(item.function).contains(pattern);
+  }
+
+  void _setSorting(
+      _Table table, _SortingField field, _SortingDirection defaultDirection) {
+    if (_sortingField[table] == field) {
+      switch (_sortingDirection[table]) {
+        case _SortingDirection.descending:
+          _sortingDirection[table] = _SortingDirection.ascending;
+          break;
+        case _SortingDirection.ascending:
+          _sortingDirection[table] = _SortingDirection.descending;
+          break;
+      }
+    } else {
+      _sortingDirection[table] = defaultDirection;
+      _sortingField[table] = field;
+    }
+    _r.dirty();
+  }
+
+  HtmlElement _createCallee() {
+    final element = new DivElement()
+      ..classes = ['function-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['inclusive']
+          ..text = '0%',
+        new SpanElement()..classes = ['name']
+      ];
+    element.onClick.listen((e) {
+      if (e.target is AnchorElement) {
+        return;
+      }
+      _selected = _callees.getItemFromElement(element);
+      _r.dirty();
+    });
+    return element;
+  }
+
+  void _updateCallee(Element e, item, int index) {
+    e.children[0].text = Utils.formatPercentNormalized(_getCalleeT(item));
+    e.children[1].text = M.getFunctionFullName(item.function);
+  }
+
+  List<HtmlElement> _createCalleeHeader() => [
+        new DivElement()
+          ..classes = ['function-item']
+          ..children = <Element>[
+            _createHeaderButton(
+                const ['inclusive'],
+                'Callees(%)',
+                _Table.callee,
+                _SortingField.callee,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['name'], 'Method', _Table.callee,
+                _SortingField.method, _SortingDirection.ascending),
+          ]
+      ];
+
+  HtmlElement _createCaller() {
+    final element = new DivElement()
+      ..classes = ['function-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['inclusive']
+          ..text = '0%',
+        new SpanElement()..classes = ['name']
+      ];
+    element.onClick.listen((e) {
+      if (e.target is AnchorElement) {
+        return;
+      }
+      _selected = _callers.getItemFromElement(element);
+      _r.dirty();
+    });
+    return element;
+  }
+
+  void _updateCaller(Element e, item, int index) {
+    e.children[0].text = Utils.formatPercentNormalized(_getCallerT(item));
+    e.children[1].text = M.getFunctionFullName(item.function);
+  }
+
+  List<HtmlElement> _createCallerHeader() => [
+        new DivElement()
+          ..classes = ['function-item']
+          ..children = <Element>[
+            _createHeaderButton(
+                const ['inclusive'],
+                'Callers(%)',
+                _Table.caller,
+                _SortingField.caller,
+                _SortingDirection.descending),
+            _createHeaderButton(const ['name'], 'Method', _Table.caller,
+                _SortingField.method, _SortingDirection.ascending),
+          ]
+      ];
+
+  ButtonElement _createHeaderButton(List<String> classes, String text,
+          _Table table, _SortingField field, _SortingDirection direction) =>
+      new ButtonElement()
+        ..classes = classes
+        ..text = _sortingField[table] != field
+            ? text
+            : _sortingDirection[table] == _SortingDirection.ascending
+                ? '$text▼'
+                : '$text▲'
+        ..onClick.listen((_) => _setSorting(table, field, direction));
+
+  List<Element> _createTree() {
+    CpuProfileVirtualTreeElement tree;
+    return [
+      (new StackTraceTreeConfigElement(
+              showMode: false,
+              showDirection: false,
+              mode: ProfileTreeMode.function,
+              direction: M.ProfileTreeDirection.exclusive,
+              filter: _filter,
+              queue: _r.queue)
+            ..onFilterChange.listen((e) {
+              _filter = e.element.filter.trim();
+              tree.filters = _filter.isNotEmpty
+                  ? [
+                      _filterTree,
+                      (node) {
+                        return node.name.contains(_filter);
+                      }
+                    ]
+                  : [_filterTree];
+            }))
+          .element,
+      new BRElement(),
+      (tree = new CpuProfileVirtualTreeElement(_isolate, _progress.profile,
+              mode: ProfileTreeMode.function,
+              direction: M.ProfileTreeDirection.exclusive,
+              queue: _r.queue)
+            ..filters = _filter.isNotEmpty
+                ? [
+                    _filterTree,
+                    (node) {
+                      return node.name.contains(_filter);
+                    }
+                  ]
+                : [_filterTree])
+          .element
+    ];
+  }
+
+  bool _filterTree(nodeDynamic) {
+    M.FunctionCallTreeNode node = nodeDynamic;
+    return node.profileFunction == _selected;
+  }
+
+  Future _request({bool clear: false, bool forceFetch: false}) async {
+    _progress = null;
+    _progressStream = _profiles.get(isolate, M.SampleProfileTag.vmOnly,
+        clear: clear, forceFetch: forceFetch);
+    _r.dirty();
+    _progress = (await _progressStream.first).progress;
+    _r.dirty();
+    if (M.isSampleProcessRunning(_progress.status)) {
+      _progress = (await _progressStream.last).progress;
+      _r.dirty();
+    }
+  }
+
+  Future _clearCpuSamples(RefreshEvent e) async {
+    e.element.disabled = true;
+    await _request(clear: true);
+    e.element.disabled = false;
+  }
+
+  Future _refresh(e) async {
+    e.element.disabled = true;
+    await _request(forceFetch: true);
+    e.element.disabled = false;
+  }
+
+  _createSorter(_Table table) {
+    var getter;
+    switch (_sortingField[table]) {
+      case _SortingField.exclusive:
+        getter = _getExclusiveT;
+        break;
+      case _SortingField.inclusive:
+        getter = _getInclusiveT;
+        break;
+      case _SortingField.callee:
+        getter = _getCalleeT;
+        break;
+      case _SortingField.caller:
+        getter = _getCallerT;
+        break;
+      case _SortingField.method:
+        getter = (M.ProfileFunction s) => M.getFunctionFullName(s.function);
+        break;
+    }
+    switch (_sortingDirection[table]) {
+      case _SortingDirection.ascending:
+        int sort(a, b) {
+          return getter(a).compareTo(getter(b));
+        }
+        return sort;
+      case _SortingDirection.descending:
+        int sort(a, b) {
+          return getter(b).compareTo(getter(a));
+        }
+        return sort;
+    }
+  }
+
+  static double _getExclusiveT(M.ProfileFunction f) =>
+      f.normalizedExclusiveTicks;
+  static double _getInclusiveT(M.ProfileFunction f) =>
+      f.normalizedInclusiveTicks;
+  double _getCalleeT(M.ProfileFunction f) =>
+      _selected.callees[f] / _selected.callees.values.reduce((a, b) => a + b);
+  double _getCallerT(M.ProfileFunction f) =>
+      _selected.callers[f] / _selected.callers.values.reduce((a, b) => a + b);
+}
diff --git a/runtime/observatory_2/lib/src/elements/css/shared.css b/runtime/observatory_2/lib/src/elements/css/shared.css
new file mode 100644
index 0000000..f8c0756
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/css/shared.css
@@ -0,0 +1,2875 @@
+/* Global styles */
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+
+body {
+  padding-top: 56px;
+  color: #333;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+button {
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+.content {
+  padding-left: 10%;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+.content-centered {
+  padding-left: 10%;
+  padding-right: 10%;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+.content-centered-big {
+  padding-left: 5%;
+  padding-right: 5%;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+h1 {
+  font: 400 18px 'Montserrat', sans-serif;
+}
+
+h2 {
+  font: 400 16px 'Montserrat', sans-serif;
+}
+
+.memberList {
+  display: table;
+}
+
+.memberItem {
+  display: table-row;
+}
+
+.memberName, .memberValue {
+  display: table-cell;
+  vertical-align: top;
+  padding: 3px 0 3px 1em;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+
+.memberSmall {
+  display: table-cell;
+  vertical-align: top;
+  padding: 3px 0 3px 1em;
+  font: 400 12px 'Montserrat', sans-serif;
+}
+
+.monospace {
+  font-family: consolas, courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  white-space: nowrap;
+}
+
+a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+a[href]:hover {
+  text-decoration: underline;
+}
+
+em {
+  color: inherit;
+  font-style: italic;
+}
+
+b {
+  color: inherit;
+  font-weight: bold;
+}
+
+hr {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  border: 0;
+  border-top: 1px solid #eee;
+  height: 0;
+  box-sizing: content-box;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 20px;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 10px 15px;
+  margin-bottom: -1px;
+  background-color: #fff;
+}
+
+.list-group-item:first-child {
+  /* rounded top corners */
+  border-top-right-radius:4px;
+  border-top-left-radius:4px;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  /* rounded bottom corners */
+  border-bottom-right-radius: 4px;
+  border-bottom-left-radius:4px;
+}
+
+.full {
+  height: 100%;
+  width: 100;
+}
+
+.flex-row {
+  display: flex;
+  flex-direction: row;
+}
+
+/* Flex row container */
+.flex-row {
+  display: flex;
+  flex-direction: row;
+}
+
+.flex-row-wrap {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+}
+
+.flex-row-wrap-right {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: flex-end;
+}
+
+.flex-row-spaced {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+  flex-wrap: wrap;
+}
+
+.inline-flex-row {
+  display: inline-flex;
+  flex-direction: row;
+}
+
+/* Flex column container */
+.flex-column {
+  display: flex;
+  flex-direction: column;
+}
+
+.flex-item-fit {
+  flex-grow: 1;
+  flex-shrink: 1;
+  flex-basis: auto;
+}
+
+.flex-item-no-shrink {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: auto;
+}
+
+.flex-item-fill {
+  flex-grow: 0;
+  flex-shrink: 1;  /* shrink when pressured */
+  flex-basis: 100%;  /* try and take 100% */
+}
+
+.flex-item-fixed-1-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 8.3%;
+}
+
+.flex-item-fixed-2-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 16.6%;
+}
+
+.flex-item-fixed-4-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 33.3333%;
+}
+
+.flex-item-fixed-6-12, .flex-item-50-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 50%;
+}
+
+.flex-item-fixed-8-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 66.6666%;
+}
+
+.flex-item-fixed-9-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 75%;
+}
+
+
+.flex-item-fixed-12-12 {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 100%;
+}
+
+.flex-item-10-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 10%;
+}
+
+.flex-item-15-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 15%;
+}
+
+.flex-item-20-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 20%;
+}
+
+.flex-item-30-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 30%;
+}
+
+.flex-item-40-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 40%;
+}
+
+.flex-item-45-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 45%;
+}
+
+.flex-item-50-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 50%;
+}
+
+.flex-item-60-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 60%;
+}
+
+.flex-item-70-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 70%;
+}
+
+.flex-item-80-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 80%;
+}
+
+.flex-item-90-percent {
+  flex-grow: 0;
+  flex-shrink: 0;
+  flex-basis: 90%;
+}
+
+.flex-item-even {
+  flex-grow: 1;
+  flex-shrink: 0;
+  padding: 5px;
+}
+
+.indent {
+  margin-left: 1.5em;
+  font: 400 14px 'Montserrat', sans-serif;
+  line-height: 150%;
+}
+
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  border-radius: 4px;
+  box-shadow: inset 0 1px 1px rgba(0,0,0,0.05);
+}
+
+.break-wrap {
+  word-wrap: break-word;
+}
+
+body.busy, body.busy * {
+  cursor: progress !important;
+}
+
+.pointer {
+  cursor: pointer;
+}
+
+.shadow {
+  box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16),
+              0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
+
+input.textbox {
+  width: 20em;
+  font: 400 16px 'Montserrat', sans-serif;
+}
+
+select, button, input {
+  border-radius: 0px;
+  border-style: solid;
+  border-width: 1px;
+}
+
+button.link {
+  background-color: transparent;
+  color: #0489c3;
+  border-style: none;
+  border-width: 0;
+}
+
+button.big {
+  font-size: 20px;
+}
+
+@-webkit-keyframes fadeIn {
+  0%   { opacity: 0; }
+  100% { opacity: 1; }
+}
+
+@-moz-keyframes fadeIn {
+  0%   { opacity: 0; }
+  100% { opacity: 1; }
+}
+
+@keyframes fadeIn {
+  0%   { opacity: 0; }
+  100% { opacity: 1; }
+}
+
+@-webkit-keyframes shake {
+  0%, 100% {
+    -webkit-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  10%, 30%, 50%, 70%, 90% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  20%, 40%, 60%, 80% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+}
+
+@keyframes shake {
+  0%, 100% {
+    -webkit-transform: translate3d(0, 0, 0);
+    -ms-transform: translate3d(0, 0, 0);
+    transform: translate3d(0, 0, 0);
+  }
+
+  10%, 30%, 50%, 70%, 90% {
+    -webkit-transform: translate3d(-10px, 0, 0);
+    -ms-transform: translate3d(-10px, 0, 0);
+    transform: translate3d(-10px, 0, 0);
+  }
+
+  20%, 40%, 60%, 80% {
+    -webkit-transform: translate3d(10px, 0, 0);
+    -ms-transform: translate3d(10px, 0, 0);
+    transform: translate3d(10px, 0, 0);
+  }
+}
+
+.shake {
+  animation: shake 0.5s;
+  -webkit-animation: shake 0.5s;
+}
+
+/* allocation-profile */
+
+.allocation-profile .heap-space {
+  display: inline-block;
+  width: 33%;
+}
+
+.allocation-profile .heap-space.right,
+.allocation-profile .heap-space.right .memberList,
+.allocation-profile .heap-space.right .legend * {
+  direction: rtl;
+}
+
+.allocation-profile .compactable {
+  position: relative;
+}
+
+.allocation-profile .compact {
+  position: absolute;
+  bottom: 20px;
+  left: 50%;
+  width: 8em;
+  margin-left: -4em;
+}
+
+.allocation-profile .heap-space.right * {
+  direction: ltr;
+  text-align: right;
+}
+
+.allocation-profile div.chart {
+  display: block;
+  position: relative;
+  height: 150px;
+}
+.allocation-profile div.chart > div.host {
+  display: inline-block;
+  position: absolute;
+  bottom: 0px;
+  top: 0;
+}
+.allocation-profile div.chart > div.legend {
+  position: absolute;
+  width: 150px;
+  top: 25px;
+  bottom: 0;
+  overflow-y: auto;
+}
+.allocation-profile .heap-space.left div.host {
+  left: 200px;
+  width: 180px;
+}
+.allocation-profile .heap-space.right div.host {
+  right: 150px;
+  width: 180px;
+}
+.allocation-profile .heap-space.left div.legend {
+  left: 0;
+}
+.allocation-profile .heap-space.right div.legend {
+  right: 0;
+}
+
+.allocation-profile .collection {
+  height: 100%;
+}
+
+.allocation-profile .collection.expanded {
+  top: 160px;
+}
+
+.allocation-profile .container {
+  padding-left: 5%;
+  padding-right: 5%;
+}
+
+.allocation-profile .collection-item {
+  background-color: #FFFFFF;
+  box-sizing: border-box;
+  line-height: 20px;
+}
+
+.allocation-profile .collection-item:hover {
+  background-color: #d2e7fe;
+}
+
+.allocation-profile .header .collection-item:hover {
+  background-color: #FFFFFF;
+}
+
+.allocation-profile .header .collection-item:last-child {
+  margin-bottom: -3px;
+  border-bottom: solid 1px #AAAAAA;
+}
+
+.allocation-profile .header .collection-item span {
+  font-weight: bolder;
+}
+
+.allocation-profile .collection-item :nth-child(2n+2).group,
+.allocation-profile .collection-item :nth-child(8n+1),
+.allocation-profile .collection-item :nth-child(8n+2),
+.allocation-profile .collection-item :nth-child(8n+3),
+.allocation-profile .collection-item :nth-child(8n+4) {
+  background-color: #EEEEEE;
+}
+
+.allocation-profile .collection-item:hover :nth-child(2n+1).group,
+.allocation-profile .collection-item:hover :nth-child(8n+1),
+.allocation-profile .collection-item:hover :nth-child(8n+2),
+.allocation-profile .collection-item:hover :nth-child(8n+3),
+.allocation-profile .collection-item:hover :nth-child(8n+4) {
+  background-color: #afd5fd;
+}
+
+.allocation-profile .header .collection-item :nth-child(2n+2).group,
+.allocation-profile .header .collection-item :nth-child(8n+5),
+.allocation-profile .header .collection-item :nth-child(8n+6),
+.allocation-profile .header .collection-item :nth-child(8n+7),
+.allocation-profile .header .collection-item :nth-child(8n+8) {
+  background-color: #FFFFFF;
+}
+
+.allocation-profile .header .collection-item :nth-child(2n+1).group,
+.allocation-profile .header .collection-item :nth-child(8n+1),
+.allocation-profile .header .collection-item :nth-child(8n+2),
+.allocation-profile .header .collection-item :nth-child(8n+3),
+.allocation-profile .header .collection-item :nth-child(8n+4) {
+  background-color: #DDDDDD;
+}
+
+.allocation-profile .collection-item .group {
+  display: inline-block;
+  width: 24em;
+  text-align: center;
+  padding-right: 0.5em;
+  line-height: 20px;
+  border-right: solid 1px #AAAAAA;
+}
+
+.allocation-profile .collection-item .bytes {
+  display: inline-block;
+  width: 6em;
+  text-align: right;
+  line-height: 20px;
+  padding-right: 0.5em;
+}
+
+.allocation-profile .collection-item .instances {
+  display: inline-block;
+  width: 6em;
+  text-align: right;
+  padding-right: 0.5em;
+  line-height: 20px;
+  border-right: solid 1px #AAAAAA;
+}
+
+.allocation-profile .collection-item .name {
+  padding-left: 0.5em;
+  padding-right: 0.5em;
+  display: inline-block;
+}
+
+.allocation-profile .collection-item > button,
+.allocation-profile .collection-item > button:active {
+  background-color: transparent;
+  color: #0489c3;
+  border-style: none;
+}
+
+.allocation-profile .collection-item > button:hover {
+  text-decoration: underline;
+}
+
+/* class-ref */
+
+.class-ref > a[href]:hover {
+    text-decoration: underline;
+}
+.class-ref > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+
+/* code-ref */
+
+.code-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.code-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.code-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* class-tree */
+
+.class-tree {
+  position: relative;
+  display: block;
+  height: 100%;
+}
+
+.class-tree .virtual-tree {
+  position: absolute;
+  height: auto;
+  top: 60px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+
+.class-tree .virtual-tree .container {
+  padding-left: 10%;
+  padding-right: 10%;
+}
+
+.class-tree .virtual-tree .class-tree-item {
+  line-height: 25px;
+  height: 25px;
+}
+
+.class-tree .virtual-tree .class-tree-item .name {
+  margin-left: 0.5em;
+  margin-right: 0.5em;
+}
+
+/* code-view */
+
+.code-view .table {
+  table-layout: fixed;
+}
+
+.code-view th:nth-of-type(1),
+.code-view td:nth-of-type(1) {
+  min-width: 10em;
+  text-align: left;
+}
+
+.code-view th:nth-of-type(2),
+.code-view td:nth-of-type(2) {
+  min-width: 8em;
+  text-align: left;
+}
+
+.code-view th:nth-of-type(3),
+.code-view td:nth-of-type(3) {
+  min-width: 8em;
+  text-align: left;
+}
+
+.code-view th:nth-of-type(4),
+.code-view td:nth-of-type(4) {
+  text-align: left;
+  overflow: visible;
+  white-space: pre;
+  padding-right: 1em;
+  width: 1px;
+}
+
+.code-view th:nth-of-type(5),
+.code-view td:nth-of-type(5) {
+  text-align: left;
+  overflow: visible;
+}
+
+.code-view tr:hover > td {
+  background-color: #F4C7C3;
+}
+
+.code-view .code-comment {
+  color: grey;
+  font-style: italic;
+}
+
+/* context-ref */
+
+.context-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.context-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.context-ref > a[href] * {
+  color: inherit;
+}
+.context-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* cpu-profile */
+
+.cpu-profile {
+  position: relative;
+  display: block;
+  height: 100%;
+}
+
+.cpu-profile > .cpu-profile-virtual-tree {
+  position: absolute;
+  height: auto;
+  top: 320px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+
+/* cpu-profile-table */
+
+.cpu-profile-table {
+  position: relative;
+  display: block;
+  height: 100%;
+}
+.cpu-profile-table .cpu-profile-virtual-tree {
+  height: 100%;
+  min-height: 600px;
+  padding-top: 250px;
+  margin-top: -250px;
+}
+.cpu-profile-table .profile-trees {
+  vertical-align: text-top;
+  min-width: 100%;
+  height: 100%;
+  padding-top: 160px;
+  margin-top: -160px;
+  padding-bottom: 100px;
+  margin-bottom: -100px;
+  padding-left: 5%;
+  padding-right: 5%;
+  min-height: 600px;
+}
+.cpu-profile-table .profile-trees .virtual-collection {
+  height: 100%;
+  width: 100%;
+  border: solid 1px #888888;
+  box-shadow: 2px 2px 5px #888888;
+}
+.cpu-profile-table .profile-trees > .profile-trees-all {
+  vertical-align: text-top;
+  display: inline-block;
+  width: 50%;
+  height: 100%;
+  padding: 5px;
+}
+.cpu-profile-table .profile-trees > .profile-trees-current {
+  vertical-align: text-top;
+  display: inline-block;
+  width: 50%;
+  height: 100%;
+}
+.cpu-profile-table .profile-trees .profile-trees-caller {
+  vertical-align: text-top;
+  display: inline-block;
+  width: 100%;
+  height: 50%;
+  padding: 5px;
+  margin-top: -17px;
+  padding-top: 22px;
+}
+.cpu-profile-table .profile-trees .profile-trees-selected {
+  vertical-align: text-top;
+  display: block;
+  height: 24px;
+  line-height: 24px;
+  margin: 5px;
+  border: solid 1px #888888;
+  box-shadow: 2px 2px 5px #888888;
+  padding-left: 5px;
+  padding-right: 5px;
+}
+.cpu-profile-table .profile-trees .profile-trees-selected > * {
+  white-space: nowrap;
+  text-overflow: ellipsis;
+  overflow: hidden;
+  display: inline-block;
+  width: 100%;
+}
+.cpu-profile-table .profile-trees .profile-trees-callee {
+  vertical-align: text-top;
+  display: inline-block;
+  width: 100%;
+  height: 50%;
+  padding: 5px;
+  margin-bottom: -17px;
+  padding-bottom: 22px;
+}
+.cpu-profile-table .function-item {
+  box-sizing: border-box;
+  line-height: 20px;
+}
+.cpu-profile-table .header {
+  box-sizing: border-box;
+  line-height: 20px;
+}
+.cpu-profile-table .header .function-item:last-child {
+  margin-bottom: -3px;
+  border-bottom: solid 1px #AAAAAA;
+}
+.cpu-profile-table .function-item .inclusive,
+.cpu-profile-table .function-item .exclusive {
+  display: inline-block;
+  width: 7em;
+  text-align: right;
+  padding-right: 0.5em;
+  line-height: 20px;
+}
+.cpu-profile-table .buffer .function-item .inclusive {
+  background-color: #EEEEEE;
+}
+.cpu-profile-table .buffer .function-item.selected .inclusive {
+  background-color: #51a3fb;
+}
+.cpu-profile-table .buffer .function-item:hover .inclusive {
+  background-color: #afd5fd;
+}
+.cpu-profile-table .header .function-item .inclusive {
+  background-color: #DDDDDD;
+}
+.cpu-profile-table .buffer .function-item.selected {
+  background-color: #60abfb;
+}
+.cpu-profile-table .buffer .function-item:hover {
+  background-color: #d2e7fe;
+}
+.cpu-profile-table .function-item .exclusive {
+}
+.cpu-profile-table .function-item .name {
+  padding-left: 0.5em;
+  padding-left: 0.5em;
+}
+.cpu-profile-table .function-item > button,
+.cpu-profile-table .function-item > button:active {
+  background-color: transparent;
+  color: #0489c3;
+  border-style: none;
+}
+.cpu-profile-table .function-item > button:hover {
+  text-decoration: underline;
+}
+
+/* cpu-profile-virtual-tree */
+
+.cpu-profile-virtual-tree {
+  display: block;
+  height: 600px;
+}
+
+.cpu-profile-virtual-tree .tree-item {
+  box-sizing: border-box;
+  line-height: 30px;
+  height: 30px;
+  padding-left: 5%;
+  padding-right: 5%;
+}
+
+.cpu-profile-virtual-tree .tree-item > .inclusive,
+.cpu-profile-virtual-tree .tree-item > .exclusive,
+.cpu-profile-virtual-tree .tree-item > .percentage {
+  display: inline-block;
+  text-align: right;
+  width: 4em;
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+}
+
+.cpu-profile-virtual-tree .tree-item > .exclusive {
+  margin-right: 1.5em;
+}
+
+.cpu-profile-virtual-tree .tree-item > .name {
+  display: inline;
+  margin-left: 0.5em;
+  margin-right: 0.5em;
+}
+
+/* curly-block */
+
+.curly-block span.curly-block {
+  color: #0489c3;
+  cursor: pointer;
+}
+.curly-block span.curly-block.disabled {
+  color: white;
+  cursor: wait;
+}
+
+/* debugger-console */
+
+.debugger-console {
+  display: block;
+  margin: 0px 20px 10px 20px;
+}
+.debugger-console .normal {
+  font: normal 14px consolas, courier, monospace;
+  white-space: pre;
+  line-height: 125%;
+}
+.debugger-console .bold {
+  font: bold 14px consolas, courier, monospace;
+  white-space: pre;
+  line-height: 125%;
+}
+.debugger-console .red {
+  font: normal 14px consolas, courier, monospace;
+  white-space: pre;
+  line-height: 125%;
+  color: red;
+}
+.debugger-console .green {
+  font: normal 14px consolas, courier, monospace;
+  white-space: pre;
+  line-height: 125%;
+  color: green;
+}
+.debugger-console .spacer {
+  height: 20px;
+}
+
+/* debugger-frame */
+
+.debugger-frame {
+  display: block;
+  position: relative;
+  padding: 5px;
+  border: 1px solid white;
+}
+.debugger-frame:hover {
+  border: 1px solid #e0e0e0;
+}
+.debugger-frame.shadow {
+  box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.16),
+               0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
+.debugger-frame.causalFrame {
+  background-color: #D7CCC8;
+}
+.debugger-frame.current {
+  box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.26),
+               0 2px 5px 0 rgba(0, 0, 0, 0.46);
+  border: 1px solid #444;
+}
+.debugger-frame > button {
+  display: block;
+  width: 100%;
+  text-align: left;
+  background-color: transparent;
+  border: none;
+}
+.debugger-frame .frameSummaryText {
+  display: inline-block;
+  padding: 5px;
+}
+.debugger-frame .frameId {
+  display: inline-block;
+  width: 60px;
+}
+.debugger-frame .frameExpander {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  display: none;
+}
+.debugger-frame:hover .frameExpander{
+  display: inline-block;
+}
+.debugger-frame .frameContractor {
+  position: absolute;
+  right: 5px;
+  bottom: 5px;
+  display: inline-block;
+}
+.debugger-frame .frameContractor > button {
+  background-color: transparent;
+  border: none;
+}
+.debugger-frame .flex-item-script {
+  flex-grow: 1;
+  flex-shrink: 1;
+  flex-basis: 765px;
+}
+.debugger-frame .flex-item-vars {
+  flex-grow: 5;
+  flex-shrink: 0;
+  flex-basis: 250px;
+  overflow-x: hidden;
+}
+.debugger-frame .frameVars {
+  position: relative;
+  top: 5px;
+  padding-left:2em;
+  padding-bottom: 5px;
+}
+
+/* debugger-input */
+
+.debugger-input .container {
+  height: 100%;
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+.debugger-input .textBox {
+  flex: 1 1 auto;
+  margin: 20px;
+  padding: 5px;
+  font: 400 16px consolas, courier, monospace;
+  width: 95%;
+}
+.debugger-input .modalPrompt {
+  flex: 0 0 auto;
+  margin-top: 20px;
+  margin-left: 20px;
+  padding: 5px;
+  font: 400 16px consolas, courier, monospace;
+  color: red;
+}
+.debugger-input .modalPrompt.hidden {
+  display: none;
+}
+
+/* debugger-message */
+
+.debugger-message {
+  display: block;
+  position: relative;
+  padding: 5px;
+  border: 1px solid white;
+}
+.debugger-message:hover {
+  border: 1px solid #e0e0e0;
+}
+.debugger-message.shadow {
+  box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.16),
+  0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
+.debugger-message.current {
+  box-shadow:  0 2px 10px 0 rgba(0, 0, 0, 0.26),
+  0 2px 5px 0 rgba(0, 0, 0, 0.46);
+  border: 1px solid #444;
+}
+.debugger-message > button {
+  display: block;
+  width: 100%;
+  text-align: left;
+  background-color: transparent;
+  border: none;
+}
+.debugger-message .messageSummaryText {
+  display: inline-block;
+  padding: 5px;
+}
+.debugger-message .messageId {
+  display: inline-block;
+  font-weight: bold;
+  width: 100px;
+}
+.debugger-message .messageExpander {
+  position: absolute;
+  right: 5px;
+  top: 5px;
+  display: none;
+}
+.debugger-message:hover .messageExpander {
+  display: inline-block;
+}
+.debugger-message.shadow:hover .messageExpander {
+  display: none;
+}
+.debugger-message .messageContractor {
+  position: absolute;
+  right: 5px;
+  bottom: 5px;
+  display: inline-block;
+}
+.debugger-message .flex-item-script {
+  flex-grow: 1;
+  flex-shrink: 1;
+  flex-basis: 765px;
+}
+.debugger-message .flex-item-vars {
+  flex-grow: 5;
+  flex-shrink: 0;
+  flex-basis: 225px;
+}
+
+/* debugger-page */
+
+.debugger-page {
+  height: 100%;
+}
+.debugger-page .variable {
+  height: 100%;
+  margin-bottom: -75px;
+  padding-bottom: 75px;
+}
+.debugger-page .stack {
+  flex: 0 0 auto;
+  overflow-y: auto;
+  height: 62%;
+}
+.debugger-page .splitter {
+  height: 0px;
+  margin: 0px;
+  font-size: 1px;
+  border-bottom: 1px solid #888;
+}
+.debugger-page .console {
+  flex: 1 1 auto;
+  overflow-x: auto;
+  overflow-y: auto;
+  height: 38%;
+}
+.debugger-page .commandline {
+  flex: 0 0 auto;
+}
+
+/* debugger-stack */
+
+.debugger-stack {
+  position: relative;
+}
+.debugger-stack .sampledMessage {
+  margin: 0px 20px 10px 20px;
+  font: 400 14px 'Montserrat', sans-serif;
+  line-height: 125%;
+}
+.debugger-stack .sampledMessage > button {
+  background-color: transparent;
+  border: none;
+  color: #0489c3;
+  text-decoration: none;
+  margin-right: 1em;
+}
+.debugger-stack .sampledMessage > button:hover {
+    text-decoration: underline;
+}
+.debugger-stack .splitter {
+  height: 0px;
+  margin: 0px;
+  font-size: 1px;
+  border-bottom: 1px dashed #888;
+}
+.debugger-stack .noMessages,
+.debugger-stack .noStack {
+  margin: 10px 0px 10px 25px;
+  font: bold 14px 'Montserrat', sans-serif;
+  line-height: 125%;
+}
+
+.debugger-stack .sampledMessage.hidden,
+.debugger-stack .noMessages.hidden,
+.debugger-stack .noStack.hidden {
+  display: none;
+}
+
+/* error-ref */
+
+.error-ref > pre {
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding-left: 10px;
+  padding-right: 10px;
+  font-family: consolas, courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  white-space: pre;
+}
+
+/* eval-box */
+
+.eval-box a[href]:hover {
+    text-decoration: underline;
+}
+.eval-box a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+.eval-box .quicks > button:hover {
+  background-color: transparent;
+  border: none;
+  text-decoration: underline;
+}
+.eval-box .quicks > button {
+  background-color: transparent;
+  border: none;
+  color: #0489c3;
+  padding: 0;
+  margin-right: 1em;
+  text-decoration: none;
+}
+.eval-box .emphasize {
+  font-style: italic;
+}
+.eval-box .indent {
+  margin-left: 1.5em;
+  font: 400 14px 'Montserrat', sans-serif;
+  line-height: 150%;
+}
+.eval-box .stackTraceBox {
+  margin-left: 1.5em;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 10px;
+  font-family: consolas, courier, monospace;
+  font-size: 12px;
+  white-space: pre;
+  overflow-x: auto;
+}
+.eval-box .heading {
+  line-height: 30px;
+  position: relative;
+  box-sizing: border-box;
+  width: 100%;
+  min-width: 450px;
+  padding-right: 150px;
+}
+.eval-box .heading .textbox {
+  width: 100%;
+  min-width: 300px;
+}
+.eval-box .heading .buttons {
+  position: absolute;
+  top: 0;
+  right: 0px;
+}
+.eval-box .heading .buttons button{
+  margin-right: 1em;
+}
+.eval-box.historyExpr,
+.eval-box .historyValue {
+  vertical-align: text-top;
+  font: 400 14px 'Montserrat', sans-serif;
+}
+.eval-box .historyExpr button {
+  display: block;
+  color: black;
+  border: none;
+  background: none;
+  text-decoration: none;
+  padding: 6px 6px;
+  cursor: pointer;
+  white-space: pre-line;
+}
+.eval-box .historyExpr button:hover {
+  background-color: #fff3e3;
+}
+.eval-box .historyValue {
+  display: block;
+  padding: 6px 6px;
+}
+.eval-box .historyDelete button {
+  border: none;
+  background: none;
+}
+eval-box .historyDelete button:hover {
+  color: #BB3311;
+}
+
+/* flag-list */
+
+.flag-list .comment {
+  color: #aaa;
+}
+
+.flag-list .flag {
+  padding: 3px 0;
+}
+
+.flag-list .name {
+  font-weight: bold;
+  margin-right: 0.7em;
+}
+
+.flag-list .value {
+  margin-left: 0.7em;
+}
+
+/* function-ref */
+
+.function-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.function-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.function-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* heap-snapshot */
+
+.heap-snapshot .statusMessage {
+  font-size: 150%;
+  font-weight: bold;
+}
+.heap-snapshot .statusBox {
+  height: 100%;
+  padding: 1em;
+}
+.heap-snapshot .explanation {
+  display: block;
+  display: -webkit-box;
+  -webkit-line-clamp: 4;
+  -webkit-box-orient: vertical;
+  max-height: 80px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.heap-snapshot .virtual-tree {
+  position: absolute;
+  height: auto;
+  top: 250px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+.heap-snapshot .tree-item {
+  box-sizing: border-box;
+  line-height: 30px;
+  height: 30px;
+  padding-left: 5%;
+  padding-right: 5%;
+
+  display: flex;
+  flex-direction: row;
+}
+.heap-snapshot .tree-item > .size,
+.heap-snapshot .tree-item > .percentage {
+  text-align: right;
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+  flex-basis: 5em;
+  flex-grow: 0;
+  flex-shrink: 0;
+}
+.heap-snapshot .tree-item > .edge {
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+  flex-basis: 0;
+  flex-grow: 1;
+  flex-shrink: 1;
+}
+.heap-snapshot .tree-item > .name {
+  margin-left: 0.5em;
+  margin-right: 0.5em;
+  flex-basis: 0;
+  flex-grow: 4;
+  flex-shrink: 4;
+}
+.heap-snapshot .tree-item > .link {
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+  flex-grow: 0;
+  flex-shrink: 0;
+}
+
+
+/* icdata-ref */
+
+.icdata-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.icdata-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.icdata-ref > a[href] * {
+  color: inherit;
+}
+.icdata-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* inbound-reference */
+
+.inbound-reference > a[href]:hover {
+  text-decoration: underline;
+}
+.inbound-reference > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+.inbound-reference .indent {
+  margin-left: 1.5em;
+  font: 400 14px 'Montserrat', sans-serif;
+  line-height: 150%;
+}
+.inbound-reference .stackTraceBox {
+  margin-left: 1.5em;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 10px;
+  font-family: consolas, courier, monospace;
+  font-size: 12px;
+  white-space: pre;
+  overflow-x: auto;
+}
+
+/* instance-ref */
+
+.instance-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.instance-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.instance-ref > a[href] * {
+  color: inherit;
+}
+.instance-ref .emphasize {
+  font-style: italic;
+}
+.instance-ref .indent {
+  margin-left: 1.5em;
+  font: 400 14px 'Montserrat', sans-serif;
+  line-height: 150%;
+}
+.instance-ref .stackTraceBox {
+  margin-left: 1.5em;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 10px;
+  font-family: consolas, courier, monospace;
+  font-size: 12px;
+  white-space: pre;
+  overflow-x: auto;
+}
+
+/* isolate-counter-chart */
+
+.isolate-counter-chart {
+  display: block;
+  position: relative;
+  height: 300px;
+  min-width: 350px;
+}
+.isolate-counter-chart > div.host {
+  position: absolute;
+  left: 0;
+  bottom: 20px;
+  top: 5px;
+  right: 250px;
+}
+.isolate-counter-chart > div.legend {
+  position: absolute;
+  width: 250px;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  overflow-y: auto;
+}
+
+/* isolate-location */
+
+.isolate-location > span {
+  font-weight: bold;
+}
+.isolate-location > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.isolate-location > a[href]:hover {
+  text-decoration: underline;
+}
+
+/* isolate-reconnect */
+
+.isolate-reconnect div.doubleSpaced {
+  line-height: 2em;
+}
+
+/* isolate-ref */
+
+.isolate-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.isolate-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+/* isolate-run-state */
+
+.isolate-run-state > span {
+  font-weight: bold;
+}
+
+/* isolate-shared-summary */
+
+.isolate-shared-summary {
+  display: block;
+}
+
+.isolate-ref-container {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  padding: 5px;
+  font-weight: bolder;
+}
+
+.isolate-state-container {
+  display: inline-block;
+}
+
+.isolate-shared-summary > .summary {
+  height: 350px;
+  position: relative;
+}
+.isolate-shared-summary .menu {
+  float: right;
+  top: 0;
+  right: 0;
+}
+.isolate-shared-summary .isolate-counter-chart {
+  position: absolute;
+  left: 0;
+  top: 0;
+  right: 230px;
+  clear: both;
+}
+.isolate-shared-summary .errorBox {
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 2em;
+  font-family: consolas, courier, monospace;
+  font-size: 1em;
+  line-height: 1.2em;
+  white-space: pre;
+}
+
+/* library-ref */
+
+.library-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.library-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.library-ref .emphasize {
+  font-style: italic;
+}
+
+
+.nav-option {
+  float: right;
+  margin: 3px;
+  padding: 8px;
+}
+
+.nav-option label {
+  color: white;
+}
+
+/* logging-list */
+
+.logging-list .outlined {
+  -webkit-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+  -moz-box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+  box-shadow: 0px 0px 2px 1px rgba(0,0,0,0.75);
+  margin: 4px;
+}
+.logging-list .logItem {
+  display: inline-block;
+  font: normal 14px consolas, courier, monospace;
+  white-space: pre;
+  line-height: 125%;
+  width: 100%;
+}
+.logging-list .level {
+  display: inline-block;
+  width: 5em;
+}
+.logging-list .time {
+  display: inline-block;
+  width: 12em;
+}
+.logging-list .FINEST {
+  background-color: #FAFAFA;
+}
+.logging-list .FINER {
+  background-color: #ECEFF1;
+}
+.logging-list .FINE {
+  background-color: #EFEBE9;
+}
+.logging-list .CONFIG {
+  background-color: #FFF3E0;
+}
+.logging-list .INFO {
+  background-color: #F1F8E9;
+}
+.logging-list .WARNING {
+  background-color: #FFE0B2;
+}
+.logging-list .SEVERE {
+  background-color: #FFCCBC;
+}
+.logging-list .SHOUT {
+  background-color: #FFCDD2;
+}
+
+/* memory-graph */
+
+.memory-graph .chart-legend-row,
+.memory-graph .chart-legend-row div {
+  display: inline;
+}
+
+.memory-graph .chart-legend-row div.chart-legend-color {
+  display: inline-block;
+  margin: auto 8px;
+}
+
+.memory-graph .chart-legend-row:nth-child(2n) div.chart-legend-color {
+  display: none;
+}
+
+/* megamorphic-cache-ref */
+
+.megamorphic-cache-ref > a[href]:hover {
+    text-decoration: underline;
+}
+.megamorphic-cache-ref > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+.megamorphic-cache-ref > a[href] * {
+    color: inherit;
+}
+.megamorphic-ref .emphasize {
+  font-style: italic;
+}
+
+/* dashboards common */
+
+.memory-dashboard,
+.timeline-dashboard {
+  display: block;
+  height: 100%;
+  margin-top: -30px;
+}
+
+.memory-profile > div > h1,
+.timeline-dashboard > div > h1 {
+  overflow: hidden;
+  border-bottom: 1px solid #d5d5d5;
+}
+
+.memory-dashboard button:disabled,
+.timeline-dashboard button:disabled,
+.memory-dashboard button:disabled:hover,
+.timeline-dashboard button:disabled:hover {
+  text-decoration: none;
+  background-color: #eee;
+  background-image: linear-gradient(#eee, #eee);
+  border: 1px solid #eee;
+  border-radius: 2px;
+  cursor: default;
+}
+
+.timeline-dashboard p {
+  margin-top: 0.4em;
+}
+
+.memory-dashboard button,
+.timeline-dashboard button,
+.memory-dashboard button:active,
+.timeline-dashboard button:active {
+  text-decoration: none;
+  background-color: #ddd;
+  background-image: linear-gradient(#eee, #ddd);
+  border: 1px solid #d5d5d5;
+  border-radius: 2px;
+  cursor: pointer;
+}
+
+.memory-dashboard button:hover,
+.timeline-dashboard button:hover {
+  text-decoration: none;
+  background-color: #ccc;
+  background-image: linear-gradient(#ddd, #ccc);
+  border-color: #c7c7c7;
+}
+
+.memory-profile .header_button,
+.timeline-dashboard .header_button {
+  padding: 3px 5px;
+  margin: 0px 1px;
+  min-width: 130px;
+}
+
+.memory-profile .header_button,
+.timeline-dashboard .header_button {
+  margin-left: 6px;
+}
+
+.header_button.left-pad {
+  margin-left: 75px;
+}
+
+.memory-profile .header_button:first-child,
+.timeline-dashboard .header_button:first-child {
+  margin-left: 30px;
+}
+
+.memory-profile .tab_buttons,
+.timeline-dashboard .tab_buttons {
+  position: relative;
+  top: 1px;
+  float: right;
+}
+
+.memory-profile .tab_buttons button,
+.timeline-dashboard .tab_buttons button {
+  padding: 5px 5px;
+  min-width: 100px
+}
+
+.memory-profile .tab_buttons button:not(:first-child),
+.timeline-dashboard .tab_buttons button:not(:first-child) {
+  border-top-left-radius: 0px;
+  border-bottom-left-radius: 0px;
+}
+
+.memory-profile .tab_buttons button:not(:last-child),
+.timeline-dashboard  .tab_buttons button:not(:last-child) {
+  border-top-right-radius: 0px;
+  border-bottom-right-radius: 0px;
+}
+
+
+/* memory-dashboard */
+
+.memory-dashboard .memory-graph {
+  height: 350px;
+}
+
+.memory-dashboard .memory-profile {
+  position: absolute;
+  bottom: 20px;
+  left: 0;
+  right: 0;
+  top: 300px;
+}
+
+.memory-dashboard .memory-profile .memory-allocations {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  top: 39px;
+}
+
+.memory-dashboard .memory-profile .memory-snapshot {
+  position: absolute;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  top: 45px;
+}
+
+/* metric-graph */
+
+.metric-graph {
+  display: block;
+}
+
+.metric-graph .graph {
+  height: 100%;
+  margin-top: -30px;
+  padding: 20px;
+  padding-top: 60px;
+}
+
+.metric-graph .graph > div {
+  height: 100%;
+}
+
+/* memory-allocations */
+
+.memory-allocations .container {
+  padding-left: 5%;
+  padding-right: 5%;
+}
+
+.memory-allocations .collection-item {
+  background-color: #FFFFFF;
+  box-sizing: border-box;
+  line-height: 20px;
+}
+
+.memory-allocations .collection-item:hover {
+  background-color: #d2e7fe;
+}
+
+.memory-allocations .header .collection-item:hover {
+  background-color: #FFFFFF;
+}
+
+.memory-allocations .header .collection-item:last-child {
+  margin-bottom: -3px;
+  border-bottom: solid 1px #AAAAAA;
+}
+
+.memory-allocations .header .collection-item span {
+  font-weight: bolder;
+}
+
+.memory-allocations .collection-item :nth-child(2n+2).group,
+.memory-allocations .collection-item :nth-child(4n+3),
+.memory-allocations .collection-item :nth-child(4n+4) {
+  background-color: #EEEEEE;
+}
+
+.memory-allocations .collection-item:hover :nth-child(2n+2).group,
+.memory-allocations .collection-item:hover :nth-child(4n+3),
+.memory-allocations .collection-item:hover :nth-child(4n+4) {
+  background-color: #afd5fd;
+}
+
+.memory-allocations .header .collection-item :nth-child(2n+1).group,
+.memory-allocations .header .collection-item :nth-child(4n+1),
+.memory-allocations .header .collection-item :nth-child(4n+2) {
+  background-color: #FFFFFF;
+}
+
+.memory-allocations .header .collection-item :nth-child(2n+2).group,
+.memory-allocations .header .collection-item :nth-child(4n+3),
+.memory-allocations .header .collection-item :nth-child(4n+4) {
+  background-color: #DDDDDD;
+}
+
+.memory-allocations .collection-item .group {
+  display: inline-block;
+  width: 12em;
+  text-align: right;
+  padding-right: 0.5em;
+  line-height: 20px;
+  border-right: solid 1px #AAAAAA;
+}
+
+.memory-allocations .collection-item .bytes {
+  display: inline-block;
+  width: 6em;
+  text-align: right;
+  line-height: 20px;
+  padding-right: 0.5em;
+}
+
+.memory-allocations .collection-item .instances {
+  display: inline-block;
+  width: 6em;
+  text-align: right;
+  padding-right: 0.5em;
+  line-height: 20px;
+  border-right: solid 1px #AAAAAA;
+}
+
+.memory-allocations .collection-item .name {
+  padding-left: 0.5em;
+  padding-right: 0.5em;
+  display: inline-block;
+}
+
+.memory-allocations .collection-item > button,
+.memory-allocations .collection-item > button:active,
+.memory-allocations .collection-item .group button,
+.memory-allocations .collection-item .group button:active {
+  background: transparent;
+  color: #0489c3;
+  border: 0px none;
+  border-radius: 0px;
+  padding: 0;
+}
+
+.memory-allocations .collection-item > button:hover,
+.memory-allocations .collection-item .group button:hover {
+  text-decoration: underline;
+  border-radius: 0px;
+}
+
+
+/* memory-snapshot */
+
+.memory-snapshot .statusMessage {
+  font-size: 150%;
+  font-weight: bold;
+}
+.memory-snapshot .statusBox {
+  height: 100%;
+  padding: 1em;
+}
+.memory-snapshot .explanation {
+  display: block;
+  display: -webkit-box;
+  -webkit-line-clamp: 4;
+  -webkit-box-orient: vertical;
+  max-height: 80px;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+.memory-snapshot .virtual-tree {
+  position: absolute;
+  height: auto;
+  top: 50px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+.memory-snapshot .tree-item {
+  box-sizing: border-box;
+  line-height: 30px;
+  height: 30px;
+  padding-left: 5%;
+  padding-right: 5%;
+}
+.memory-snapshot .tree-item > .size,
+.memory-snapshot .tree-item > .percentage {
+  display: inline-block;
+  text-align: right;
+  width: 4em;
+  margin-left: 0.25em;
+  margin-right: 0.25em;
+}
+
+.memory-snapshot .tree-item > .name {
+  display: inline;
+  margin-left: 0.5em;
+}
+
+/* metric-graph */
+
+.metrics-page > div {
+  display: block;
+  height: 100%;
+}
+
+.metrics-page > div > .graph {
+  display: block;
+  height: 100%;
+  margin-top: -300px;
+  padding-top: 300px;
+}
+
+/* nav-bar */
+
+nav.nav-bar {
+  line-height: normal;
+  position: fixed;
+  top: 0;
+  width: 100%;
+  z-index: 1000;
+}
+nav.nav-bar > ul {
+  display: inline-table;
+  position: relative;
+  list-style: none;
+  padding-left: 0;
+  margin: 0;
+  width: 100%;
+  z-index: 1000;
+  font: 400 16px 'Montserrat', sans-serif;
+  color: white;
+  background-color: #0489c3;
+}
+
+/* nav-menu */
+li.nav-menu:before {
+  display: inline-block;
+  content: '>';
+  margin-left: 0.5em;
+  margin-right: 0.5em;
+}
+nav.nav-bar > ul *:first-child li.nav-menu:before,
+nav.nav-bar > ul .nav-reload > li:before {
+  content: '';
+  margin-left: 0;
+  margin-right: 0;
+}
+li.nav-menu, .nav-menu_label {
+  display: inline-block;
+}
+.nav-menu_label > a {
+  display: inline-block;
+  padding: 12px 8px;
+  color: White;
+  text-decoration: none;
+}
+.nav-menu_label:hover > a {
+  background: #455;
+}
+.nav-menu_label > ul {
+  display: none;
+  position: absolute;
+  top: 98%;
+  list-style: none;
+  margin: 0;
+  padding: 0;
+  width: auto;
+  z-index: 1000;
+  font: 400 16px 'Montserrat', sans-serif;
+  color: white;
+  background: #567;
+}
+.nav-menu_label > ul:after {
+  content: ""; clear: both; display: block;
+}
+.nav-menu_label:hover > ul {
+  display: block;
+}
+
+/* nav-menu-item */
+
+.nav-menu-item li.nav-menu-item {
+  float: none;
+  border-top: 1px solid #677;
+  border-bottom: 1px solid #556; position: relative;
+}
+.nav-menu-item li.nav-menu-item:hover {
+  background: #455;
+}
+.nav-menu-item li.nav-menu-item > a {
+  display: block;
+  padding: 12px 12px;
+  color: white;
+  text-decoration: none;
+}
+.nav-menu-item li.nav-menu-item > ul {
+  display: none;
+  position: absolute;
+  top:0;
+  left: 100%;
+  list-style: none;
+  padding: 0;
+  margin-left: 0;
+  width: auto;
+  z-index: 1000;
+  font: 400 16px 'Montserrat', sans-serif;
+  color: white;
+  background: #567;
+}
+.nav-menu-item li.nav-menu-item > ul:after {
+  content: ""; clear: both; display: block;
+}
+.nav-menu-item li.nav-menu-item:hover > ul {
+  display: block;
+}
+
+/* nav-notify */
+
+.nav-notify > div {
+  float: right;
+}
+.nav-notify > div > div {
+  display: block;
+  position: absolute;
+  top: 98%;
+  right: 0;
+  margin: 0;
+  padding: 0;
+  width: auto;
+  z-index: 1000;
+  background: none;
+}
+
+/* nav-exception & nav-event */
+
+.nav-exception > div, .nav-event > div {
+  position: relative;
+  padding: 16px;
+  margin-top: 10px;
+  margin-right: 10px;
+  padding-right: 25px;
+  width: 500px;
+  color: #ddd;
+  background: rgba(0,0,0,.6);
+  border: solid 2px white;
+  box-shadow: 0 0 5px black;
+  border-radius: 5px;
+  animation: fadein 1s;
+}
+
+.nav-exception *, .nav-event * {
+  color: #ddd;
+  font-size: 12px;
+}
+
+.nav-exception > div > a[href],
+.nav-event > div > a[href] {
+  color: white;
+  text-decoration: none;
+}
+
+.nav-exception > div > a[href]:hover,
+.nav-event > div > a[href]:hover {
+  text-decoration: underline;
+}
+
+.nav-exception > div > div {
+  margin-left:20px;
+  white-space: pre
+}
+
+.nav-exception > div > button, .nav-event > div > button {
+  background: transparent;
+  border: none;
+  position: absolute;
+  display: block;
+  top: 4px;
+  right: 4px;
+  height: 18px;
+  width: 18px;
+  line-height: 16px;
+  border-radius: 9px;
+  color: white;
+  font-size: 18px;
+  cursor: pointer;
+  text-align: center;
+}
+
+.nav-exception > div > button:hover, .nav-event > div > button:hover {
+  background: rgba(255,255,255,0.5);
+}
+
+/* nav-refresh */
+
+.nav-refresh > li > button {
+  color: #000;
+  margin: 3px;
+  padding: 8px;
+  border-width: 2px;
+  line-height: 13px;
+  font-size: 13px;
+  font: 400 'Montserrat', sans-serif;
+}
+.nav-refresh > li > button[disabled] {
+  color: #aaa;
+  cursor: wait;
+}
+.nav-refresh > li {
+  float: right;
+  margin: 0;
+}
+
+/* nav-refresh */
+
+.nav-reload > li > button {
+  color: #000;
+  margin: 3px;
+  padding: 8px;
+  border-width: 2px;
+  line-height: 13px;
+  font-size: 13px;
+  font: 400 'Montserrat', sans-serif;
+}
+.nav-reload ul > li {
+  display: block;
+  width: 100%;
+  padding: 2px;
+}
+.nav-reload ul > li > button {
+  display: inline-block;
+  padding: 8px;
+  width: 100%;
+}
+.nav-reload > li > button[disabled],
+.nav-reload ul > li > button[disabled] {
+  color: #aaa;
+  cursor: wait;
+}
+.nav-reload > li {
+  float: right;
+  margin: 0;
+}
+
+/* object-common && class-instances */
+
+.class-instances button:hover,
+.object-common button:hover {
+  background-color: transparent;
+  border: none;
+  text-decoration: underline;
+}
+.class-instances button,
+.object-common button {
+  background-color: transparent;
+  border: none;
+  color: #0489c3;
+  padding: 0;
+  margin: -8px 4px;
+  font-size: 20px;
+  text-decoration: none;
+}
+
+/* object-pool-ref */
+
+.object-pool-ref > a[href]:hover {
+  text-decoration: underline;
+}
+
+.object-pool-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.object-pool-ref > a[href] * {
+  color: inherit;
+}
+.object-pool-ref .emphasize {
+  font-style: italic;
+}
+
+/* object-pool-view */
+
+.object-pool-view .hexadecimal {
+  font-family: monospace;
+}
+
+/* observatory-application */
+
+.observatory-application {
+  display: block;
+  height: 100%;
+}
+
+.observatory-application > div {
+  display: block;
+  height: 100%;
+}
+
+/* persistent-handles-page */
+
+.persistent-handles-page {
+  display: block;
+  height: 100%;
+}
+.persistent-handles-page .persistent-handles,
+.persistent-handles-page .weak-persistent-handles {
+  margin-top: -70px;
+  padding-top: 70px;
+  height: 50%;
+}
+.persistent-handles-page .weak-item,
+.persistent-handles-page .collection-item {
+  box-sizing: border-box;
+  line-height: 20px;
+  padding-left: 5%;
+  padding-right: 5%;
+}
+.persistent-handles-page .header {
+  box-sizing: border-box;
+  line-height: 20px;
+}
+.persistent-handles-page .header .weak-item:last-child {
+  margin-bottom: -3px;
+  border-bottom: solid 1px #AAAAAA;
+}
+.persistent-handles-page .weak-item .external-size,
+.persistent-handles-page .weak-item .peer,
+.persistent-handles-page .weak-item .object {
+  display: inline-block;
+  width: 7em;
+  text-align: right;
+  padding-right: 0.5em;
+  line-height: 20px;
+}
+.persistent-handles-page .weak-item .peer {
+  width: 11em;
+  font-family: monospace;
+}
+.persistent-handles-page .weak-item .object {
+  text-align: left;
+  width: 25em;
+}
+.persistent-handles-page .buffer .weak-item:hover {
+  background-color: #d2e7fe;
+}
+.persistent-handles-page .weak-item .finalizer {
+  padding-left: 0.5em;
+}
+.persistent-handles-page .weak-item > button,
+.persistent-handles-page .weak-item > button:active {
+  background-color: transparent;
+  color: #0489c3;
+  border-style: none;
+}
+.persistent-handles-page .weak-item > button:hover {
+  text-decoration: underline;
+}
+
+/* ports-page */
+
+.ports-page .port-number {
+  font-weight: bold;
+}
+
+/* script-ref */
+
+.script-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.script-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.script-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* source-link */
+
+.source-link > a[href]:hover {
+    text-decoration: underline;
+}
+
+.source-link > a[href] {
+    color: #0489c3;
+    text-decoration: none;
+}
+
+
+/* observatory-application */
+
+.observatory-application {
+  display: block;
+  height: 100%;
+}
+
+.observatory-application > div {
+  display: block;
+  height: 100%;
+}
+
+/* sample-buffer-control */
+
+.sample-buffer-control {
+  white-space: nowrap;
+}
+
+.sample-buffer-control .statusMessage {
+  font-size: 150%;
+  font-weight: bold;
+}
+
+.sample-buffer-control .statusBox {
+  height: 100%;
+  padding: 1em;
+}
+
+.sample-buffer-control .center {
+  align-items: center;
+  justify-content: center;
+}
+
+.sample-buffer-control .notice {
+  background-color: #fcf8e3;
+}
+
+.sample-buffer-control .red {
+  background-color: #f2dede;
+}
+
+.sample-buffer-control .shadow {
+  box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.16),
+              0 2px 5px 0 rgba(0, 0, 0, 0.26);
+}
+
+/* script-inset */
+
+.script-inset {
+  position: relative;
+}
+.script-inset button.refresh,
+.script-inset button.toggle-profile {
+  background-color: transparent;
+  padding: 0;
+  margin: 0;
+  border: none;
+  position: absolute;
+  display: inline-block;
+  top: 5px;
+}
+.script-inset button.refresh > svg,
+.script-inset button.toggle-profile > svg {
+  fill: #888888;
+}
+.script-inset button.refresh {
+  right: 5px;
+}
+.script-inset button.toggle-profile {
+  right: 30px;
+}
+.script-inset button.toggle-profile.enabled > svg {
+  fill: #BB3322;
+}
+.script-inset a {
+  color: #0489c3;
+  text-decoration: none;
+}
+.script-inset a:hover {
+  text-decoration: underline;
+}
+.script-inset .sourceInset {
+}
+.script-inset .sourceTable {
+  position: relative;
+  background-color: #f5f5f5;
+  border: 1px solid #ccc;
+  padding: 10px;
+  width: 100%;
+  box-sizing: border-box;
+  overflow-x: scroll;
+}
+.script-inset .sourceRow {
+  display: flex;
+  flex-direction: row;
+  width: 100%;
+}
+.script-inset .sourceItem,
+.script-inset .sourceItemCurrent {
+  vertical-align: top;
+  font: 400 14px consolas, courier, monospace;
+  line-height: 125%;
+  white-space: pre;
+  max-width: 0;
+}
+.script-inset .currentLine {
+  background-color: #fff;
+}
+.script-inset .currentCol {
+  background-color: #6cf;
+}
+.script-inset .hitsCurrent,
+.script-inset .hitsNone,
+.script-inset .hitsNotExecuted,
+.script-inset .hitsExecuted,
+.script-inset .hitsCompiled,
+.script-inset .hitsNotCompiled {
+  display: table-cell;
+  vertical-align: top;
+  font: 400 14px consolas, courier, monospace;
+  margin-left: 5px;
+  margin-right: 5px;
+  text-align: right;
+  color: #a8a8a8;
+}
+.script-inset .hitsCurrent {
+  background-color: #6cf;
+  color: black;
+}
+.script-inset .hitsNotExecuted {
+  background-color: #faa;
+}
+.script-inset .hitsExecuted {
+  background-color: #aea;
+}
+.script-inset .hitsCompiled {
+  background-color: #e0e0e0;
+}
+.script-inset .hitsNotCompiled {
+  background-color: #f0c5c5;
+}
+.script-inset .noCopy {}
+.script-inset .emptyBreakpoint,
+.script-inset .possibleBreakpoint,
+.script-inset .busyBreakpoint,
+.script-inset .unresolvedBreakpoint,
+.script-inset .resolvedBreakpoint  {
+  display: table-cell;
+  vertical-align: top;
+  font: 400 14px consolas, courier, monospace;
+  width: 1em;
+  text-align: center;
+  cursor: pointer;
+}
+.script-inset .possibleBreakpoint {
+  color: #e0e0e0;
+}
+.script-inset .possibleBreakpoint:hover {
+  color: white;
+  background-color: #777;
+}
+.script-inset .busyBreakpoint {
+  color: white;
+  background-color: black;
+  cursor: wait;
+}
+.script-inset .unresolvedBreakpoint {
+  color: white;
+  background-color: #cac;
+}
+.script-inset .resolvedBreakpoint {
+  color: white;
+  background-color: #e66;
+}
+.script-inset .unresolvedBreakAnnotation {
+  color: white;
+  background-color: #cac;
+}
+.script-inset .resolvedBreakAnnotation {
+  color: white;
+  background-color: #e66;
+}
+.script-inset .notSourceProfile,
+.script-inset .noProfile,
+.script-inset .coldProfile,
+.script-inset .mediumProfile,
+.script-inset .hotProfile {
+  display: table-cell;
+  vertical-align: top;
+  font: 400 14px consolas, courier, monospace;
+  width: 4em;
+  text-align: right;
+  cursor: pointer;
+  margin-left: 5px;
+  margin-right: 5px;
+}
+.script-inset .notSourceProfile {
+}
+.script-inset .noProfile {
+  background-color: #e0e0e0;
+}
+.script-inset .coldProfile {
+  background-color: #aea;
+}
+.script-inset .mediumProfile {
+  background-color: #fe9;
+}
+.script-inset .hotProfile {
+  background-color: #faa;
+}
+
+/* search-bar */
+
+.search-bar {
+  background: white;
+  padding: 5px;
+}
+.search-bar > input {
+  width: 300px;
+  line-height: 20px;
+  border-color: #DDDDDD;
+  padding-left: 2px;
+  padding-right: 2px;
+}
+
+.search-bar button:enabled,
+.search-bar button:enabled:hover,
+.search-bar button:disabled,
+.search-bar button:disabled:hover,
+.search-bar button:active {
+  border: none;
+  background: none;
+  background-color: transparent;
+  line-height: 20px;
+  margin-left: 0.5em;
+  margin-right: 0.5em;
+  outline: none;
+}
+
+.search-bar button:disabled,
+.search-bar button:disabled:hover {
+  color: #DDDDDD;
+}
+
+.search-bar button:enabled,
+.search-bar button:enabled:active {
+  color: #BBBBBB;
+}
+
+.search-bar button:enabled:hover {
+  color: #AAAAAA;
+  text-shadow: 1px 1px 2px #dddddd;
+}
+
+/* stack-trace-tree-config */
+
+.stack-trace-tree-config {
+  white-space: nowrap;
+}
+
+/* timeline-dashboard */
+
+.timeline-dashboard .iframe {
+  position: absolute;
+  top: 90px;
+  bottom: 0;
+  left: 0;
+  right: 0;
+}
+.timeline-dashboard h1 {
+  margin-bottom: 5px;
+}
+.timeline-dashboard .iframe iframe {
+  width: 100%;
+  height: 100%;
+  border: none;
+}
+
+/* timeline-page */
+
+.timeline-page .iframe {
+  height: 100%;
+  width: 100%;
+  margin-top: -120px;
+  padding-top: 120px;
+}
+.timeline-page .iframe iframe {
+  width: 100%;
+  height: 100%;
+  border: none;
+}
+
+/* type-arguments-ref */
+
+.type-arguments-ref a[href]:hover {
+  text-decoration: underline;
+}
+.type-arguments-ref a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.type-arguments-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* token-stream-ref */
+
+.token-stream-ref a[href]:hover {
+  text-decoration: underline;
+}
+.token-stream-ref a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.token-stream-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* unknown-ref */
+
+.unknown-ref > a[href]:hover {
+  text-decoration: underline;
+}
+.unknown-ref > a[href] {
+  color: #0489c3;
+  text-decoration: none;
+}
+.unknown-ref > a[href] * {
+  color: inherit;
+}
+.unknown-ref .emphasize {
+  font-style: italic;
+}
+
+
+/* view-footer */
+
+.view-footer {
+  padding: 1em;
+  padding-top: 10.3em;
+  float: right;
+  align-content: right;
+}
+
+.view-footer > a {
+  margin-bottom: 0.17em;
+  font-size: 90%;
+  float: right;
+  clear: both;
+  display: block;
+}
+
+/* virtual-collection */
+
+.virtual-collection {
+  position: relative;
+  display: block;
+  overflow-x: hidden;
+  width: 100%;
+  height: 100%;
+}
+
+.virtual-collection .viewport {
+  position: absolute;
+  display: block;
+  overflow-y: auto;
+  overflow-x: auto;
+  top: 0;
+  bottom: 0;
+  right: 0;
+  left: 0;
+}
+
+.virtual-collection .header {
+  background: white;
+  position: relative;
+  display: block;
+  z-index: +1;
+}
+
+.virtual-collection .search-bar {
+  position: relative;
+  display: block;
+  z-index: +1;
+  float: right;
+  top: 2px;
+  right: 25px;
+  border-bottom-left-radius: 5px;
+  border-bottom-right-radius: 5px;
+  box-shadow: 0px 1px 2px #AAAAAA;
+}
+
+.virtual-collection .spacer {
+  overflow: hidden;
+  background: transparent;
+  display: inline-block;
+  min-width: 100%;
+}
+
+.virtual-collection .buffer {
+  background: transparent;
+  position: relative;
+  display: inline-block;
+  min-width: 100%;
+}
+
+.virtual-collection .header > div,
+.virtual-collection .buffer > div {
+  white-space: nowrap;
+}
+
+.virtual-collection .header.attached > div,
+.virtual-collection .buffer > div {
+/*  display: inline-block;*/
+}
+
+.virtual-collection .buffer > div {
+  min-width: 100%;
+  white-space: nowrap;
+}
+
+.virtual-collection .marked,
+.virtual-collection .marked * {
+  background: yellow !important;
+}
+
+/* virtual-tree */
+
+.virtual-tree .expander,
+.virtual-tree .expander:hover,
+.virtual-tree .expander:active {
+  display: inline-block;
+  text-align: center;
+  font-weight: bold;
+  font-size: 18px;
+  width: 19px;
+  border: 0px none;
+  background: transparent;
+  padding: 0;
+}
+
+.virtual-tree .expander:focus {
+  outline: none;
+}
+
+.virtual-tree .lines,
+.virtual-tree .lines > span {
+  display: inline-block;
+  vertical-align: top;
+  height: 100%;
+  line-height: 100%;
+}
+
+.virtual-tree .lines:before,
+.virtual-tree .lines > span:before {
+  display: inline-block;
+  content: '';
+}
+
+.virtual-tree .lines > span {
+  width: 3px;
+  margin-left: 8px;
+  margin-right: 8px;
+}
+
+.virtual-tree .lines > span:nth-child(5n) {
+  background-color: #673AB7;
+}
+
+.virtual-tree .lines > span:nth-child(5n+1) {
+  background-color: #F44336;
+}
+
+.virtual-tree .lines > span:nth-child(5n+2) {
+  background-color: #4CAF50;
+}
+
+.virtual-tree .lines > span:nth-child(5n+3) {
+  background-color: #3F51B5;
+}
+
+.virtual-tree .lines > span:nth-child(5n+4) {
+  background-color: #FF9800;
+}
+
+/* vm-connect-target */
+
+.vm-connect-target > a {
+  color: #0489c3;
+  text-decoration: none;
+}
+
+.vm-connect-target > a:hover {
+  text-decoration: underline;
+}
+
+.vm-connect-target > button.delete-button {
+  margin-left: 0.28em;
+  padding: 4px;
+  background: transparent;
+  border: none !important;
+}
+
+.vm-connect-target > button.delete-button:hover {
+  background: #ff0000;
+}
+
+/* vm-connect */
+
+.vm-connect ul {
+  list-style-type: none;
+}
+
+.treemapTile {
+  position: absolute;
+  box-sizing: border-box;
+  border: solid 1px;
+  font-size: 10px;
+  text-align: center;
+  overflow: hidden;
+  white-space: nowrap;
+  cursor: default;
+}
diff --git a/runtime/observatory_2/lib/src/elements/curly_block.dart b/runtime/observatory_2/lib/src/elements/curly_block.dart
new file mode 100644
index 0000000..a5f2cc2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/curly_block.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library curly_block_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class CurlyBlockToggleEvent {
+  final CurlyBlockElement control;
+
+  CurlyBlockToggleEvent(this.control);
+}
+
+class CurlyBlockElement extends CustomElement implements Renderable {
+  RenderingScheduler<CurlyBlockElement> _r;
+
+  final StreamController<CurlyBlockToggleEvent> _onToggle =
+      new StreamController<CurlyBlockToggleEvent>.broadcast();
+  Stream<CurlyBlockToggleEvent> get onToggle => _onToggle.stream;
+  Stream<RenderedEvent<CurlyBlockElement>> get onRendered => _r.onRendered;
+
+  bool _expanded;
+  bool _disabled;
+  Iterable<Element> _content = const [];
+
+  bool get expanded => _expanded;
+  bool get disabled => _disabled;
+  Iterable<Element> get content => _content;
+
+  set expanded(bool value) {
+    if (_expanded != value) _onToggle.add(new CurlyBlockToggleEvent(this));
+    _expanded = _r.checkAndReact(_expanded, value);
+  }
+
+  set disabled(bool value) => _disabled = _r.checkAndReact(_disabled, value);
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory CurlyBlockElement(
+      {bool expanded: false, bool disabled: false, RenderingQueue queue}) {
+    assert(expanded != null);
+    assert(disabled != null);
+    CurlyBlockElement e = new CurlyBlockElement.created();
+    e._r = new RenderingScheduler<CurlyBlockElement>(e, queue: queue);
+    e._expanded = expanded;
+    e._disabled = disabled;
+    return e;
+  }
+
+  CurlyBlockElement.created() : super.created('curly-block');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void toggle() {
+    if (disabled) {
+      _r.scheduleNotification();
+      return;
+    }
+    expanded = !expanded;
+  }
+
+  void render() {
+    List<Element> content = <Element>[new SpanElement()..text = '{'];
+    SpanElement label = new SpanElement()
+      ..classes = disabled ? ['curly-block', 'disabled'] : ['curly-block']
+      ..innerHtml = expanded
+          ? '&nbsp;&nbsp;&#8863;&nbsp;&nbsp;'
+          : '&nbsp;&nbsp;&#8862;&nbsp;&nbsp;';
+    if (disabled) {
+      content.add(label);
+    } else {
+      content.add(new AnchorElement()
+        ..onClick.listen((_) {
+          toggle();
+        })
+        ..children = <Element>[label]);
+    }
+    if (expanded) {
+      content.add(new BRElement());
+      content.addAll(_content);
+    }
+    content.add(new SpanElement()..text = '}');
+    children = content;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/debugger.dart b/runtime/observatory_2/lib/src/elements/debugger.dart
new file mode 100644
index 0000000..9ec8688
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/debugger.dart
@@ -0,0 +1,3372 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library debugger_page_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math';
+import 'dart:svg';
+
+import 'package:logging/logging.dart';
+import 'package:observatory_2/app.dart';
+import 'package:observatory_2/cli.dart';
+import 'package:observatory_2/debugger.dart';
+import 'package:observatory_2/event.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/repositories.dart' as R;
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/source_inset.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+
+// TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
+abstract class DebuggerCommand extends Command {
+  ObservatoryDebugger debugger;
+
+  DebuggerCommand(this.debugger, name, List<Command> children)
+      : super(name, children);
+
+  String get helpShort;
+  String get helpLong;
+}
+
+// TODO(turnidge): Rewrite HelpCommand so that it is a general utility
+// provided by the cli library.
+class HelpCommand extends DebuggerCommand {
+  HelpCommand(Debugger debugger)
+      : super(debugger, 'help', <Command>[
+          new HelpHotkeysCommand(debugger),
+        ]);
+
+  String _nameAndAlias(Command cmd) {
+    if (cmd.alias == null) {
+      return cmd.fullName;
+    } else {
+      return '${cmd.fullName}, ${cmd.alias}';
+    }
+  }
+
+  Future run(List<String> args) {
+    var con = debugger.console;
+    if (args.length == 0) {
+      // Print list of all top-level commands.
+      var commands = debugger.cmd.matchCommand(<String>[], false);
+      commands.sort((a, b) => a.name.compareTo(b.name));
+      con.print('List of commands:\n');
+      for (DebuggerCommand command in commands) {
+        con.print('${_nameAndAlias(command).padRight(12)} '
+            '- ${command.helpShort}');
+      }
+      con.print(
+          "\nFor more information on a specific command type 'help <command>'\n"
+          "For a list of hotkeys type 'help hotkeys'\n"
+          "\n"
+          "Command prefixes are accepted (e.g. 'h' for 'help')\n"
+          "Hit [TAB] to complete a command (try 'is[TAB][TAB]')\n"
+          "Hit [ENTER] to repeat the last command\n"
+          "Use up/down arrow for command history\n");
+      return new Future.value(null);
+    } else {
+      // Print any matching commands.
+      var commands = debugger.cmd.matchCommand(args, true);
+      commands.sort((a, b) => a.name.compareTo(b.name));
+      if (commands.isEmpty) {
+        var line = args.join(' ');
+        con.print("No command matches '${line}'");
+        return new Future.value(null);
+      }
+      con.print('');
+      for (DebuggerCommand command in commands) {
+        con.printBold(_nameAndAlias(command));
+        con.print(command.helpLong);
+
+        var newArgs = <String>[];
+        newArgs.addAll(args.take(args.length - 1));
+        newArgs.add(command.name);
+        newArgs.add('');
+        var subCommands = debugger.cmd.matchCommand(newArgs, false);
+        subCommands.remove(command);
+        if (subCommands.isNotEmpty) {
+          subCommands.sort((a, b) => a.name.compareTo(b.name));
+          con.print('Subcommands:\n');
+          for (DebuggerCommand subCommand in subCommands) {
+            con.print('    ${subCommand.fullName.padRight(16)} '
+                '- ${subCommand.helpShort}');
+          }
+          con.print('');
+        }
+      }
+      return new Future.value(null);
+    }
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    var commands = debugger.cmd.matchCommand(args, false);
+    var result = commands.map((command) => '${command.fullName} ');
+    return new Future.value(result.toList());
+  }
+
+  String helpShort =
+      'List commands or provide details about a specific command';
+
+  String helpLong =
+      'List commands or provide details about a specific command.\n'
+      '\n'
+      'Syntax: help            - Show a list of all commands\n'
+      '        help <command>  - Help for a specific command\n';
+}
+
+class HelpHotkeysCommand extends DebuggerCommand {
+  HelpHotkeysCommand(Debugger debugger)
+      : super(debugger, 'hotkeys', <Command>[]);
+
+  Future run(List<String> args) {
+    var con = debugger.console;
+    con.print("List of hotkeys:\n"
+        "\n"
+        "[TAB]        - complete a command\n"
+        "[Up Arrow]   - history previous\n"
+        "[Down Arrow] - history next\n"
+        "\n"
+        "[Page Up]    - move up one frame\n"
+        "[Page Down]  - move down one frame\n"
+        "\n"
+        "[F7]         - continue execution of the current isolate\n"
+        "[Ctrl ;]     - pause execution of the current isolate\n"
+        "\n"
+        "[F8]         - toggle breakpoint at current location\n"
+        "[F9]         - next\n"
+        "[F10]        - step\n"
+        "\n");
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Provide a list of hotkeys';
+
+  String helpLong = 'Provide a list of key hotkeys.\n'
+      '\n'
+      'Syntax: help hotkeys\n';
+}
+
+class PrintCommand extends DebuggerCommand {
+  PrintCommand(Debugger debugger) : super(debugger, 'print', <Command>[]) {
+    alias = 'p';
+  }
+
+  Future run(List<String> args) async {
+    if (args.length < 1) {
+      debugger.console.print('print expects arguments');
+      return;
+    }
+    if (debugger.currentFrame == null) {
+      debugger.console.print('No stack');
+      return;
+    }
+    var expression = args.join('');
+    var response =
+        await debugger.isolate.evalFrame(debugger.currentFrame, expression);
+    if (response is S.DartError) {
+      debugger.console.print(response.message);
+    } else if (response is S.Sentinel) {
+      debugger.console.print(response.valueAsString);
+    } else {
+      debugger.console.print('= ', newline: false);
+      debugger.console.printRef(debugger.isolate, response, debugger.objects);
+    }
+  }
+
+  String helpShort = 'Evaluate and print an expression in the current frame';
+
+  String helpLong = 'Evaluate and print an expression in the current frame.\n'
+      '\n'
+      'Syntax: print <expression>\n'
+      '        p <expression>\n';
+}
+
+class DownCommand extends DebuggerCommand {
+  DownCommand(Debugger debugger) : super(debugger, 'down', <Command>[]);
+
+  Future run(List<String> args) {
+    int count = 1;
+    if (args.length == 1) {
+      count = int.parse(args[0]);
+    } else if (args.length > 1) {
+      debugger.console.print('down expects 0 or 1 argument');
+      return new Future.value(null);
+    }
+    if (debugger.currentFrame == null) {
+      debugger.console.print('No stack');
+      return new Future.value(null);
+    }
+    try {
+      debugger.downFrame(count);
+      debugger.console.print('frame = ${debugger.currentFrame}');
+    } catch (e) {
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
+    }
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Move down one or more frames (hotkey: [Page Down])';
+
+  String helpLong = 'Move down one or more frames.\n'
+      '\n'
+      'Hotkey: [Page Down]\n'
+      '\n'
+      'Syntax: down\n'
+      '        down <count>\n';
+}
+
+class UpCommand extends DebuggerCommand {
+  UpCommand(Debugger debugger) : super(debugger, 'up', <Command>[]);
+
+  Future run(List<String> args) {
+    int count = 1;
+    if (args.length == 1) {
+      count = int.parse(args[0]);
+    } else if (args.length > 1) {
+      debugger.console.print('up expects 0 or 1 argument');
+      return new Future.value(null);
+    }
+    if (debugger.currentFrame == null) {
+      debugger.console.print('No stack');
+      return new Future.value(null);
+    }
+    try {
+      debugger.upFrame(count);
+      debugger.console.print('frame = ${debugger.currentFrame}');
+    } on RangeError catch (e) {
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
+    }
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Move up one or more frames (hotkey: [Page Up])';
+
+  String helpLong = 'Move up one or more frames.\n'
+      '\n'
+      'Hotkey: [Page Up]\n'
+      '\n'
+      'Syntax: up\n'
+      '        up <count>\n';
+}
+
+class FrameCommand extends DebuggerCommand {
+  FrameCommand(Debugger debugger) : super(debugger, 'frame', <Command>[]) {
+    alias = 'f';
+  }
+
+  Future run(List<String> args) {
+    int frame = 1;
+    if (args.length == 1) {
+      frame = int.parse(args[0]);
+    } else {
+      debugger.console.print('frame expects 1 argument');
+      return new Future.value(null);
+    }
+    if (debugger.currentFrame == null) {
+      debugger.console.print('No stack');
+      return new Future.value(null);
+    }
+    try {
+      debugger.currentFrame = frame;
+      debugger.console.print('frame = ${debugger.currentFrame}');
+    } on RangeError catch (e) {
+      debugger.console
+          .print('frame must be in range [${e.start}..${e.end - 1}]');
+    }
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Set the current frame';
+
+  String helpLong = 'Set the current frame.\n'
+      '\n'
+      'Syntax: frame <number>\n'
+      '        f <count>\n';
+}
+
+class PauseCommand extends DebuggerCommand {
+  PauseCommand(Debugger debugger) : super(debugger, 'pause', <Command>[]);
+
+  Future run(List<String> args) {
+    return debugger.pause();
+  }
+
+  String helpShort = 'Pause the isolate (hotkey: [Ctrl ;])';
+
+  String helpLong = 'Pause the isolate.\n'
+      '\n'
+      'Hotkey: [Ctrl ;]\n'
+      '\n'
+      'Syntax: pause\n';
+}
+
+class ContinueCommand extends DebuggerCommand {
+  ContinueCommand(Debugger debugger)
+      : super(debugger, 'continue', <Command>[]) {
+    alias = 'c';
+  }
+
+  Future run(List<String> args) {
+    return debugger.resume();
+  }
+
+  String helpShort = 'Resume execution of the isolate (hotkey: [F7])';
+
+  String helpLong = 'Continue running the isolate.\n'
+      '\n'
+      'Hotkey: [F7]\n'
+      '\n'
+      'Syntax: continue\n'
+      '        c\n';
+}
+
+class SmartNextCommand extends DebuggerCommand {
+  SmartNextCommand(Debugger debugger) : super(debugger, 'next', <Command>[]) {
+    alias = 'n';
+  }
+
+  Future run(List<String> args) async {
+    return debugger.smartNext();
+  }
+
+  String helpShort =
+      'Continue running the isolate until it reaches the next source location '
+      'in the current function (hotkey: [F9])';
+
+  String helpLong =
+      'Continue running the isolate until it reaches the next source location '
+      'in the current function.\n'
+      '\n'
+      'Hotkey: [F9]\n'
+      '\n'
+      'Syntax: next\n';
+}
+
+class SyncNextCommand extends DebuggerCommand {
+  SyncNextCommand(Debugger debugger)
+      : super(debugger, 'next-sync', <Command>[]);
+
+  Future run(List<String> args) {
+    return debugger.syncNext();
+  }
+
+  String helpShort = 'Run until return/unwind to current activation.';
+
+  String helpLong =
+      'Continue running the isolate until control returns to the current '
+      'activation or one of its callers.\n'
+      '\n'
+      'Syntax: next-sync\n';
+}
+
+class AsyncNextCommand extends DebuggerCommand {
+  AsyncNextCommand(Debugger debugger)
+      : super(debugger, 'next-async', <Command>[]);
+
+  Future run(List<String> args) {
+    return debugger.asyncNext();
+  }
+
+  String helpShort = 'Step over await or yield';
+
+  String helpLong =
+      'Continue running the isolate until control returns to the current '
+      'activation of an async or async* function.\n'
+      '\n'
+      'Syntax: next-async\n';
+}
+
+class StepCommand extends DebuggerCommand {
+  StepCommand(Debugger debugger) : super(debugger, 'step', <Command>[]) {
+    alias = 's';
+  }
+
+  Future run(List<String> args) {
+    return debugger.step();
+  }
+
+  String helpShort =
+      'Continue running the isolate until it reaches the next source location'
+      ' (hotkey: [F10]';
+
+  String helpLong =
+      'Continue running the isolate until it reaches the next source '
+      'location.\n'
+      '\n'
+      'Hotkey: [F10]\n'
+      '\n'
+      'Syntax: step\n';
+}
+
+class RewindCommand extends DebuggerCommand {
+  RewindCommand(Debugger debugger) : super(debugger, 'rewind', <Command>[]);
+
+  Future run(List<String> args) async {
+    try {
+      int count = 1;
+      if (args.length == 1) {
+        count = int.tryParse(args[0]);
+        if (count == null || count < 1 || count >= debugger.stackDepth) {
+          debugger.console.print(
+              'Frame must be an int in bounds [1..${debugger.stackDepth - 1}]:'
+              ' saw ${args[0]}');
+          return;
+        }
+      } else if (args.length > 1) {
+        debugger.console.print('rewind expects 0 or 1 argument');
+        return;
+      }
+      await debugger.rewind(count);
+    } on S.ServerRpcException catch (e) {
+      if (e.code == S.ServerRpcException.kCannotResume) {
+        debugger.console.printRed(e.data['details']);
+      } else {
+        rethrow;
+      }
+    }
+  }
+
+  String helpShort = 'Rewind the stack to a previous frame';
+
+  String helpLong = 'Rewind the stack to a previous frame.\n'
+      '\n'
+      'Syntax: rewind\n'
+      '        rewind <count>\n';
+}
+
+class ReloadCommand extends DebuggerCommand {
+  final M.IsolateRepository _isolates;
+
+  ReloadCommand(Debugger debugger, this._isolates)
+      : super(debugger, 'reload', <Command>[]);
+
+  Future run(List<String> args) async {
+    try {
+      if (args.length > 0) {
+        debugger.console.print('reload expects no arguments');
+        return;
+      }
+      if (_isolates.reloadSourcesServices.isEmpty) {
+        await _isolates.reloadSources(debugger.isolate);
+      } else {
+        await _isolates.reloadSources(debugger.isolate,
+            service: _isolates.reloadSourcesServices.first);
+      }
+      debugger.console.print('reload complete');
+      await debugger.refreshStack();
+    } on S.ServerRpcException catch (e) {
+      if (e.code == S.ServerRpcException.kIsolateReloadBarred ||
+          e.code == S.ServerRpcException.kIsolateIsReloading) {
+        debugger.console.printRed(e.data['details']);
+      } else {
+        rethrow;
+      }
+    }
+  }
+
+  String helpShort = 'Reload the sources for the current isolate';
+
+  String helpLong = 'Reload the sources for the current isolate.\n'
+      '\n'
+      'Syntax: reload\n';
+}
+
+class ClsCommand extends DebuggerCommand {
+  ClsCommand(Debugger debugger) : super(debugger, 'cls', <Command>[]) {}
+
+  Future run(List<String> args) {
+    debugger.console.clear();
+    debugger.console.newline();
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Clear the console';
+
+  String helpLong = 'Clear the console.\n'
+      '\n'
+      'Syntax: cls\n';
+}
+
+class LogCommand extends DebuggerCommand {
+  LogCommand(Debugger debugger) : super(debugger, 'log', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (args.length == 0) {
+      debugger.console.print('Current log level: '
+          '${debugger._consolePrinter._minimumLogLevel.name}');
+      return new Future.value(null);
+    }
+    if (args.length > 1) {
+      debugger.console.print("log expects zero or one arguments");
+      return new Future.value(null);
+    }
+    var level = _findLevel(args[0]);
+    if (level == null) {
+      debugger.console.print('No such log level: ${args[0]}');
+      return new Future.value(null);
+    }
+    debugger._consolePrinter._minimumLogLevel = level;
+    debugger.console.print('Set log level to: ${level.name}');
+    return new Future.value(null);
+  }
+
+  Level _findLevel(String levelName) {
+    levelName = levelName.toUpperCase();
+    for (var level in Level.LEVELS) {
+      if (level.name == levelName) {
+        return level;
+      }
+    }
+    return null;
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    var prefix = args[0].toUpperCase();
+    var result = <String>[];
+    for (var level in Level.LEVELS) {
+      if (level.name.startsWith(prefix)) {
+        result.add(level.name);
+      }
+    }
+    return new Future.value(result);
+  }
+
+  String helpShort = 'Control which log messages are displayed';
+
+  String helpLong =
+      'Get or set the minimum log level that should be displayed.\n'
+      '\n'
+      'Log levels (in ascending order): ALL, FINEST, FINER, FINE, CONFIG, '
+      'INFO, WARNING, SEVERE, SHOUT, OFF\n'
+      '\n'
+      'Default: OFF\n'
+      '\n'
+      'Syntax: log          '
+      '# Display the current minimum log level.\n'
+      '        log <level>  '
+      '# Set the minimum log level to <level>.\n'
+      '        log OFF      '
+      '# Display no log messages.\n'
+      '        log ALL      '
+      '# Display all log messages.\n';
+}
+
+class FinishCommand extends DebuggerCommand {
+  FinishCommand(Debugger debugger) : super(debugger, 'finish', <Command>[]);
+
+  Future run(List<String> args) {
+    if (debugger.isolatePaused()) {
+      var event = debugger.isolate.pauseEvent;
+      if (event is M.PauseStartEvent) {
+        debugger.console
+            .print("Type 'continue' [F7] or 'step' [F10] to start the isolate");
+        return new Future.value(null);
+      }
+      if (event is M.PauseExitEvent) {
+        debugger.console.print("Type 'continue' [F7] to exit the isolate");
+        return new Future.value(null);
+      }
+      return debugger.isolate.stepOut();
+    } else {
+      debugger.console.print('The program is already running');
+      return new Future.value(null);
+    }
+  }
+
+  String helpShort =
+      'Continue running the isolate until the current function exits';
+
+  String helpLong =
+      'Continue running the isolate until the current function exits.\n'
+      '\n'
+      'Syntax: finish\n';
+}
+
+class SetCommand extends DebuggerCommand {
+  SetCommand(Debugger debugger) : super(debugger, 'set', <Command>[]);
+
+  static var _boeValues = ['All', 'None', 'Unhandled'];
+  static var _boolValues = ['false', 'true'];
+
+  static var _options = {
+    'break-on-exception': [
+      _boeValues,
+      _setBreakOnException,
+      (debugger, _) => debugger.breakOnException
+    ],
+    'up-is-down': [
+      _boolValues,
+      _setUpIsDown,
+      (debugger, _) => debugger.upIsDown
+    ],
+    'causal-async-stacks': [
+      _boolValues,
+      _setCausalAsyncStacks,
+      (debugger, _) => debugger.saneAsyncStacks
+    ],
+    'awaiter-stacks': [
+      _boolValues,
+      _setAwaiterStacks,
+      (debugger, _) => debugger.awaiterStacks
+    ]
+  };
+
+  static Future _setBreakOnException(debugger, name, value) async {
+    var result = await debugger.isolate.setExceptionPauseMode(value);
+    if (result.isError) {
+      debugger.console.print(result.toString());
+    } else {
+      // Printing will occur elsewhere.
+      debugger.breakOnException = value;
+    }
+  }
+
+  static Future _setUpIsDown(debugger, name, value) async {
+    if (value == 'true') {
+      debugger.upIsDown = true;
+    } else {
+      debugger.upIsDown = false;
+    }
+    debugger.console.print('${name} = ${value}');
+  }
+
+  static Future _setCausalAsyncStacks(debugger, name, value) async {
+    if (value == 'true') {
+      debugger.causalAsyncStacks = true;
+    } else {
+      debugger.causalAsyncStacks = false;
+    }
+    debugger.refreshStack();
+    debugger.console.print('${name} = ${value}');
+  }
+
+  static Future _setAwaiterStacks(debugger, name, value) async {
+    debugger.awaiterStacks = (value == 'true');
+    debugger.refreshStack();
+    debugger.console.print('${name} == ${value}');
+  }
+
+  Future run(List<String> args) async {
+    if (args.length == 0) {
+      for (var name in _options.keys) {
+        dynamic getHandler = _options[name][2];
+        var value = await getHandler(debugger, name);
+        debugger.console.print("${name} = ${value}");
+      }
+    } else if (args.length == 1) {
+      var name = args[0].trim();
+      var optionInfo = _options[name];
+      if (optionInfo == null) {
+        debugger.console.print("unrecognized option: $name");
+        return;
+      } else {
+        dynamic getHandler = optionInfo[2];
+        var value = await getHandler(debugger, name);
+        debugger.console.print("${name} = ${value}");
+      }
+    } else if (args.length == 2) {
+      var name = args[0].trim();
+      var value = args[1].trim();
+      var optionInfo = _options[name];
+      if (optionInfo == null) {
+        debugger.console.print("unrecognized option: $name");
+        return;
+      }
+      dynamic validValues = optionInfo[0];
+      if (!validValues.contains(value)) {
+        debugger.console.print("'${value}' is not in ${validValues}");
+        return;
+      }
+      dynamic setHandler = optionInfo[1];
+      await setHandler(debugger, name, value);
+    } else {
+      debugger.console.print("set expects 0, 1, or 2 arguments");
+    }
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length < 1 || args.length > 2) {
+      return new Future.value([args.join('')]);
+    }
+    var result = <String>[];
+    if (args.length == 1) {
+      var prefix = args[0];
+      for (var option in _options.keys) {
+        if (option.startsWith(prefix)) {
+          result.add('${option} ');
+        }
+      }
+    }
+    if (args.length == 2) {
+      var name = args[0].trim();
+      var prefix = args[1];
+      var optionInfo = _options[name];
+      if (optionInfo != null) {
+        var validValues = optionInfo[0];
+        for (var value in validValues) {
+          if (value.startsWith(prefix)) {
+            result.add('${args[0]}${value} ');
+          }
+        }
+      }
+    }
+    return new Future.value(result);
+  }
+
+  String helpShort = 'Set a debugger option';
+
+  String helpLong = 'Set a debugger option.\n'
+      '\n'
+      'Known options:\n'
+      '  break-on-exception    # Should the debugger break on exceptions?\n'
+      "                        # ${_boeValues}\n"
+      '  up-is-down            # Reverse meaning of up/down commands?\n'
+      "                        # ${_boolValues}\n"
+      '\n'
+      'Syntax: set                    # Display all option settings\n'
+      '        set <option>           # Get current value for option\n'
+      '        set <option> <value>   # Set value for option';
+}
+
+class BreakCommand extends DebuggerCommand {
+  BreakCommand(Debugger debugger) : super(debugger, 'break', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (args.length > 1) {
+      debugger.console.print('not implemented');
+      return;
+    }
+    var arg = (args.length == 0 ? '' : args[0]);
+    var loc = await DebuggerLocation.parse(debugger, arg);
+    if (loc.valid) {
+      if (loc.function != null) {
+        try {
+          await debugger.isolate.addBreakpointAtEntry(loc.function);
+        } on S.ServerRpcException catch (e) {
+          if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
+            debugger.console.print('Unable to set breakpoint at ${loc}');
+          } else {
+            rethrow;
+          }
+        }
+      } else {
+        assert(loc.script != null);
+        var script = loc.script;
+        await script.load();
+        if (loc.line < 1 || loc.line > script.lines.length) {
+          debugger.console.print(
+              'line number must be in range [1..${script.lines.length}]');
+          return;
+        }
+        try {
+          await debugger.isolate.addBreakpoint(script, loc.line, loc.col);
+        } on S.ServerRpcException catch (e) {
+          if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
+            debugger.console.print('Unable to set breakpoint at ${loc}');
+          } else {
+            rethrow;
+          }
+        }
+      }
+    } else {
+      debugger.console.print(loc.errorMessage);
+    }
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    // TODO - fix DebuggerLocation complete
+    return new Future.value(DebuggerLocation.complete(debugger, args[0]));
+  }
+
+  String helpShort = 'Add a breakpoint by source location or function name'
+      ' (hotkey: [F8])';
+
+  String helpLong = 'Add a breakpoint by source location or function name.\n'
+      '\n'
+      'Hotkey: [F8]\n'
+      '\n'
+      'Syntax: break                       '
+      '# Break at the current position\n'
+      '        break <line>                '
+      '# Break at a line in the current script\n'
+      '                                    '
+      '  (e.g \'break 11\')\n'
+      '        break <line>:<col>          '
+      '# Break at a line:col in the current script\n'
+      '                                    '
+      '  (e.g \'break 11:8\')\n'
+      '        break <script>:<line>       '
+      '# Break at a line:col in a specific script\n'
+      '                                    '
+      '  (e.g \'break test.dart:11\')\n'
+      '        break <script>:<line>:<col> '
+      '# Break at a line:col in a specific script\n'
+      '                                    '
+      '  (e.g \'break test.dart:11:8\')\n'
+      '        break <function>            '
+      '# Break at the named function\n'
+      '                                    '
+      '  (e.g \'break main\' or \'break Class.someFunction\')\n';
+}
+
+class ClearCommand extends DebuggerCommand {
+  ClearCommand(Debugger debugger) : super(debugger, 'clear', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (args.length > 1) {
+      debugger.console.print('not implemented');
+      return;
+    }
+    var arg = (args.length == 0 ? '' : args[0]);
+    var loc = await DebuggerLocation.parse(debugger, arg);
+    if (!loc.valid) {
+      debugger.console.print(loc.errorMessage);
+      return;
+    }
+    if (loc.function != null) {
+      debugger.console.print('Ignoring breakpoint at $loc: '
+          'Clearing function breakpoints not yet implemented');
+      return;
+    }
+
+    var script = loc.script;
+    if (loc.line < 1 || loc.line > script.lines.length) {
+      debugger.console
+          .print('line number must be in range [1..${script.lines.length}]');
+      return;
+    }
+    var lineInfo = script.getLine(loc.line);
+    var bpts = lineInfo.breakpoints;
+    var foundBreakpoint = false;
+    if (bpts != null) {
+      var bptList = bpts.toList();
+      for (var bpt in bptList) {
+        if (loc.col == null ||
+            loc.col == script.tokenToCol(bpt.location.tokenPos)) {
+          foundBreakpoint = true;
+          var result = await debugger.isolate.removeBreakpoint(bpt);
+          if (result is S.DartError) {
+            debugger.console.print(
+                'Error clearing breakpoint ${bpt.number}: ${result.message}');
+          }
+        }
+      }
+    }
+    if (!foundBreakpoint) {
+      debugger.console.print('No breakpoint found at ${loc}');
+    }
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    return new Future.value(DebuggerLocation.complete(debugger, args[0]));
+  }
+
+  String helpShort = 'Remove a breakpoint by source location or function name'
+      ' (hotkey: [F8])';
+
+  String helpLong = 'Remove a breakpoint by source location or function name.\n'
+      '\n'
+      'Hotkey: [F8]\n'
+      '\n'
+      'Syntax: clear                       '
+      '# Clear at the current position\n'
+      '        clear <line>                '
+      '# Clear at a line in the current script\n'
+      '                                    '
+      '  (e.g \'clear 11\')\n'
+      '        clear <line>:<col>          '
+      '# Clear at a line:col in the current script\n'
+      '                                    '
+      '  (e.g \'clear 11:8\')\n'
+      '        clear <script>:<line>       '
+      '# Clear at a line:col in a specific script\n'
+      '                                    '
+      '  (e.g \'clear test.dart:11\')\n'
+      '        clear <script>:<line>:<col> '
+      '# Clear at a line:col in a specific script\n'
+      '                                    '
+      '  (e.g \'clear test.dart:11:8\')\n'
+      '        clear <function>            '
+      '# Clear at the named function\n'
+      '                                    '
+      '  (e.g \'clear main\' or \'clear Class.someFunction\')\n';
+}
+
+// TODO(turnidge): Add argument completion.
+class DeleteCommand extends DebuggerCommand {
+  DeleteCommand(Debugger debugger) : super(debugger, 'delete', <Command>[]);
+
+  Future run(List<String> args) {
+    if (args.length < 1) {
+      debugger.console.print('delete expects one or more arguments');
+      return new Future.value(null);
+    }
+    List toRemove = [];
+    for (var arg in args) {
+      int id = int.parse(arg);
+      var bptToRemove = null;
+      for (var bpt in debugger.isolate.breakpoints.values) {
+        if (bpt.number == id) {
+          bptToRemove = bpt;
+          break;
+        }
+      }
+      if (bptToRemove == null) {
+        debugger.console.print("Invalid breakpoint id '${id}'");
+        return new Future.value(null);
+      }
+      toRemove.add(bptToRemove);
+    }
+    List<Future> pending = [];
+    for (var bpt in toRemove) {
+      pending.add(debugger.isolate.removeBreakpoint(bpt));
+    }
+    return Future.wait(pending);
+  }
+
+  String helpShort = 'Remove a breakpoint by breakpoint id';
+
+  String helpLong = 'Remove a breakpoint by breakpoint id.\n'
+      '\n'
+      'Syntax: delete <bp-id>\n'
+      '        delete <bp-id> <bp-id> ...\n';
+}
+
+class InfoBreakpointsCommand extends DebuggerCommand {
+  InfoBreakpointsCommand(Debugger debugger)
+      : super(debugger, 'breakpoints', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (debugger.isolate.breakpoints.isEmpty) {
+      debugger.console.print('No breakpoints');
+    }
+    List bpts = debugger.isolate.breakpoints.values.toList();
+    bpts.sort((a, b) => a.number - b.number);
+    for (var bpt in bpts) {
+      var bpId = bpt.number;
+      var locString = await bpt.location.toUserString();
+      if (!bpt.resolved) {
+        debugger.console.print('Future breakpoint ${bpId} at ${locString}');
+      } else {
+        debugger.console.print('Breakpoint ${bpId} at ${locString}');
+      }
+    }
+  }
+
+  String helpShort = 'List all breakpoints';
+
+  String helpLong = 'List all breakpoints.\n'
+      '\n'
+      'Syntax: info breakpoints\n';
+}
+
+class InfoFrameCommand extends DebuggerCommand {
+  InfoFrameCommand(Debugger debugger) : super(debugger, 'frame', <Command>[]);
+
+  Future run(List<String> args) {
+    if (args.length > 0) {
+      debugger.console.print('info frame expects no arguments');
+      return new Future.value(null);
+    }
+    debugger.console.print('frame = ${debugger.currentFrame}');
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Show current frame';
+
+  String helpLong = 'Show current frame.\n'
+      '\n'
+      'Syntax: info frame\n';
+}
+
+class IsolateCommand extends DebuggerCommand {
+  IsolateCommand(Debugger debugger)
+      : super(debugger, 'isolate', <Command>[
+          new IsolateListCommand(debugger),
+          new IsolateNameCommand(debugger),
+        ]) {
+    alias = 'i';
+  }
+
+  Future run(List<String> args) {
+    if (args.length != 1) {
+      debugger.console.print('isolate expects one argument');
+      return new Future.value(null);
+    }
+    var arg = args[0].trim();
+    var num = int.tryParse(arg);
+
+    var candidate;
+    for (var isolate in debugger.vm.isolates) {
+      if (num != null && num == isolate.number) {
+        candidate = isolate;
+        break;
+      } else if (arg == isolate.name) {
+        if (candidate != null) {
+          debugger.console.print("Isolate identifier '${arg}' is ambiguous: "
+              'use the isolate number instead');
+          return new Future.value(null);
+        }
+        candidate = isolate;
+      }
+    }
+    if (candidate == null) {
+      debugger.console.print("Invalid isolate identifier '${arg}'");
+    } else {
+      if (candidate == debugger.isolate) {
+        debugger.console.print(
+            "Current isolate is already ${candidate.number} '${candidate.name}'");
+      } else {
+        new AnchorElement(href: Uris.debugger(candidate)).click();
+      }
+    }
+    return new Future.value(null);
+  }
+
+  Future<List<String>> complete(List<String> args) {
+    if (args.length != 1) {
+      return new Future.value([args.join('')]);
+    }
+    var result = <String>[];
+    for (var isolate in debugger.vm.isolates) {
+      var str = isolate.number.toString();
+      if (str.startsWith(args[0])) {
+        result.add('$str ');
+      }
+    }
+    for (var isolate in debugger.vm.isolates) {
+      if (isolate.name.startsWith(args[0])) {
+        result.add('${isolate.name} ');
+      }
+    }
+    return new Future.value(result);
+  }
+
+  String helpShort = 'Switch, list, rename, or reload isolates';
+
+  String helpLong = 'Switch the current isolate.\n'
+      '\n'
+      'Syntax: isolate <number>\n'
+      '        isolate <name>\n';
+}
+
+String _isolateRunState(S.Isolate isolate) {
+  if (isolate.paused) {
+    return 'paused';
+  } else if (isolate.running) {
+    return 'running';
+  } else if (isolate.idle) {
+    return 'idle';
+  } else {
+    return 'unknown';
+  }
+}
+
+class IsolateListCommand extends DebuggerCommand {
+  IsolateListCommand(Debugger debugger) : super(debugger, 'list', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (debugger.vm == null) {
+      debugger.console.print("Internal error: vm has not been set");
+      return;
+    }
+
+    // Refresh all isolates first.
+    var pending = <Future>[];
+    for (var isolate in debugger.vm.isolates) {
+      pending.add(isolate.reload());
+    }
+    await Future.wait(pending);
+
+    const maxIdLen = 10;
+    const maxRunStateLen = 7;
+    var maxNameLen = 'NAME'.length;
+    for (var isolate in debugger.vm.isolates) {
+      maxNameLen = max(maxNameLen, isolate.name.length);
+    }
+    debugger.console.print("${'ID'.padLeft(maxIdLen, ' ')} "
+        "${'ORIGIN'.padLeft(maxIdLen, ' ')} "
+        "${'NAME'.padRight(maxNameLen, ' ')} "
+        "${'STATE'.padRight(maxRunStateLen, ' ')} "
+        "CURRENT");
+    for (var isolate in debugger.vm.isolates) {
+      String current = (isolate == debugger.isolate ? '*' : '');
+      debugger.console
+          .print("${isolate.number.toString().padLeft(maxIdLen, ' ')} "
+              "${isolate.originNumber.toString().padLeft(maxIdLen, ' ')} "
+              "${isolate.name.padRight(maxNameLen, ' ')} "
+              "${_isolateRunState(isolate).padRight(maxRunStateLen, ' ')} "
+              "${current}");
+    }
+    debugger.console.newline();
+  }
+
+  String helpShort = 'List all isolates';
+
+  String helpLong = 'List all isolates.\n'
+      '\n'
+      'Syntax: isolate list\n';
+}
+
+class IsolateNameCommand extends DebuggerCommand {
+  IsolateNameCommand(Debugger debugger) : super(debugger, 'name', <Command>[]);
+
+  Future run(List<String> args) {
+    if (args.length != 1) {
+      debugger.console.print('isolate name expects one argument');
+      return new Future.value(null);
+    }
+    return debugger.isolate.setName(args[0]);
+  }
+
+  String helpShort = 'Rename the current isolate';
+
+  String helpLong = 'Rename the current isolate.\n'
+      '\n'
+      'Syntax: isolate name <name>\n';
+}
+
+class InfoCommand extends DebuggerCommand {
+  InfoCommand(Debugger debugger)
+      : super(debugger, 'info', <Command>[
+          new InfoBreakpointsCommand(debugger),
+          new InfoFrameCommand(debugger)
+        ]);
+
+  Future run(List<String> args) {
+    debugger.console.print("'info' expects a subcommand (see 'help info')");
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Show information on a variety of topics';
+
+  String helpLong = 'Show information on a variety of topics.\n'
+      '\n'
+      'Syntax: info <subcommand>\n';
+}
+
+class RefreshStackCommand extends DebuggerCommand {
+  RefreshStackCommand(Debugger debugger)
+      : super(debugger, 'stack', <Command>[]);
+
+  Future run(List<String> args) {
+    return debugger.refreshStack();
+  }
+
+  String helpShort = 'Refresh isolate stack';
+
+  String helpLong = 'Refresh isolate stack.\n'
+      '\n'
+      'Syntax: refresh stack\n';
+}
+
+class RefreshCommand extends DebuggerCommand {
+  RefreshCommand(Debugger debugger)
+      : super(debugger, 'refresh', <Command>[
+          new RefreshStackCommand(debugger),
+        ]);
+
+  Future run(List<String> args) {
+    debugger.console
+        .print("'refresh' expects a subcommand (see 'help refresh')");
+    return new Future.value(null);
+  }
+
+  String helpShort = 'Refresh debugging information of various sorts';
+
+  String helpLong = 'Refresh debugging information of various sorts.\n'
+      '\n'
+      'Syntax: refresh <subcommand>\n';
+}
+
+class VmListCommand extends DebuggerCommand {
+  VmListCommand(Debugger debugger) : super(debugger, 'list', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (args.length > 0) {
+      debugger.console.print('vm list expects no arguments');
+      return;
+    }
+    if (debugger.vm == null) {
+      debugger.console.print("No connected VMs");
+      return;
+    }
+    // TODO(turnidge): Right now there is only one vm listed.
+    var vmList = [debugger.vm];
+
+    var maxAddrLen = 'ADDRESS'.length;
+    var maxNameLen = 'NAME'.length;
+
+    for (var vm in vmList) {
+      maxAddrLen = max(maxAddrLen, vm.target.networkAddress.length);
+      maxNameLen = max(maxNameLen, vm.name.length);
+    }
+
+    debugger.console.print("${'ADDRESS'.padRight(maxAddrLen, ' ')} "
+        "${'NAME'.padRight(maxNameLen, ' ')} "
+        "CURRENT");
+    for (var vm in vmList) {
+      String current = (vm == debugger.vm ? '*' : '');
+      debugger.console
+          .print("${vm.target.networkAddress.padRight(maxAddrLen, ' ')} "
+              "${vm.name.padRight(maxNameLen, ' ')} "
+              "${current}");
+    }
+  }
+
+  String helpShort = 'List all connected Dart virtual machines';
+
+  String helpLong = 'List all connected Dart virtual machines..\n'
+      '\n'
+      'Syntax: vm list\n';
+}
+
+class VmNameCommand extends DebuggerCommand {
+  VmNameCommand(Debugger debugger) : super(debugger, 'name', <Command>[]);
+
+  Future run(List<String> args) async {
+    if (args.length != 1) {
+      debugger.console.print('vm name expects one argument');
+      return;
+    }
+    if (debugger.vm == null) {
+      debugger.console.print('There is no current vm');
+      return;
+    }
+    await debugger.vm.setName(args[0]);
+  }
+
+  String helpShort = 'Rename the current Dart virtual machine';
+
+  String helpLong = 'Rename the current Dart virtual machine.\n'
+      '\n'
+      'Syntax: vm name <name>\n';
+}
+
+class VmCommand extends DebuggerCommand {
+  VmCommand(Debugger debugger)
+      : super(debugger, 'vm', <Command>[
+          new VmListCommand(debugger),
+          new VmNameCommand(debugger),
+        ]);
+
+  Future run(List<String> args) async {
+    debugger.console.print("'vm' expects a subcommand (see 'help vm')");
+  }
+
+  String helpShort = 'Manage a Dart virtual machine';
+
+  String helpLong = 'Manage a Dart virtual machine.\n'
+      '\n'
+      'Syntax: vm <subcommand>\n';
+}
+
+class _ConsoleStreamPrinter {
+  ObservatoryDebugger _debugger;
+
+  _ConsoleStreamPrinter(this._debugger);
+  Level _minimumLogLevel = Level.OFF;
+  String _savedStream;
+  String _savedIsolate;
+  String _savedLine;
+  List<String> _buffer = [];
+
+  void onEvent(String streamName, S.ServiceEvent event) {
+    if (event.kind == S.ServiceEvent.kLogging) {
+      // Check if we should print this log message.
+      if (event.logRecord['level'].value < _minimumLogLevel.value) {
+        return;
+      }
+    }
+    String isolateName = event.isolate.name;
+    // If we get a line from a different isolate/stream, flush
+    // any pending output, even if it is not newline-terminated.
+    if ((_savedIsolate != null && isolateName != _savedIsolate) ||
+        (_savedStream != null && streamName != _savedStream)) {
+      flush();
+    }
+    String data;
+    bool hasNewline;
+    if (event.kind == S.ServiceEvent.kLogging) {
+      data = event.logRecord["message"].valueAsString;
+      hasNewline = true;
+    } else {
+      data = event.bytesAsString;
+      hasNewline = data.endsWith('\n');
+    }
+    if (_savedLine != null) {
+      data = _savedLine + data;
+      _savedIsolate = null;
+      _savedStream = null;
+      _savedLine = null;
+    }
+    var lines = data.split('\n').where((line) => line != '').toList();
+    if (lines.isEmpty) {
+      return;
+    }
+    int limit = (hasNewline ? lines.length : lines.length - 1);
+    for (int i = 0; i < limit; i++) {
+      _buffer.add(_format(isolateName, streamName, lines[i]));
+    }
+    // If there is no newline, we save the last line of output for next time.
+    if (!hasNewline) {
+      _savedIsolate = isolateName;
+      _savedStream = streamName;
+      _savedLine = lines[lines.length - 1];
+    }
+  }
+
+  void flush() {
+    // If there is any saved output, flush it now.
+    if (_savedLine != null) {
+      _buffer.add(_format(_savedIsolate, _savedStream, _savedLine));
+      _savedIsolate = null;
+      _savedStream = null;
+      _savedLine = null;
+    }
+    if (_buffer.isNotEmpty) {
+      _debugger.console.printStdio(_buffer);
+      _buffer.clear();
+    }
+  }
+
+  String _format(String isolateName, String streamName, String line) {
+    return '${isolateName}:${streamName}> ${line}';
+  }
+}
+
+// Tracks the state for an isolate debugging session.
+class ObservatoryDebugger extends Debugger {
+  final SettingsGroup settings = new SettingsGroup('debugger');
+  RootCommand cmd;
+  DebuggerPageElement page;
+  DebuggerConsoleElement console;
+  DebuggerInputElement input;
+  DebuggerStackElement stackElement;
+  S.ServiceMap stack;
+  final S.Isolate isolate;
+  String breakOnException = "none"; // Last known setting.
+
+  int get currentFrame => _currentFrame;
+
+  void set currentFrame(int value) {
+    if (value != null && (value < 0 || value >= stackDepth)) {
+      throw new RangeError.range(value, 0, stackDepth);
+    }
+    _currentFrame = value;
+    if (stackElement != null) {
+      stackElement.setCurrentFrame(value);
+    }
+  }
+
+  int _currentFrame = null;
+
+  bool get upIsDown => _upIsDown;
+  void set upIsDown(bool value) {
+    settings.set('up-is-down', value);
+    _upIsDown = value;
+  }
+
+  bool _upIsDown;
+
+  bool get causalAsyncStacks => _causalAsyncStacks;
+  void set causalAsyncStacks(bool value) {
+    settings.set('causal-async-stacks', value);
+    _causalAsyncStacks = value;
+  }
+
+  bool _causalAsyncStacks;
+
+  bool get awaiterStacks => _awaiterStacks;
+  void set awaiterStacks(bool value) {
+    settings.set('awaiter-stacks', value);
+    _causalAsyncStacks = value;
+  }
+
+  bool _awaiterStacks;
+
+  static const String kAwaiterStackFrames = 'awaiterFrames';
+  static const String kAsyncCausalStackFrames = 'asyncCausalFrames';
+  static const String kStackFrames = 'frames';
+
+  void upFrame(int count) {
+    if (_upIsDown) {
+      currentFrame += count;
+    } else {
+      currentFrame -= count;
+    }
+  }
+
+  void downFrame(int count) {
+    if (_upIsDown) {
+      currentFrame -= count;
+    } else {
+      currentFrame += count;
+    }
+  }
+
+  int get stackDepth {
+    if (awaiterStacks) {
+      var awaiterStackFrames = stack[kAwaiterStackFrames];
+      if (awaiterStackFrames != null) {
+        return awaiterStackFrames.length;
+      }
+    }
+    if (causalAsyncStacks) {
+      var asyncCausalStackFrames = stack[kAsyncCausalStackFrames];
+      if (asyncCausalStackFrames != null) {
+        return asyncCausalStackFrames.length;
+      }
+    }
+    return stack[kStackFrames].length;
+  }
+
+  List get stackFrames {
+    if (awaiterStacks) {
+      var awaiterStackFrames = stack[kAwaiterStackFrames];
+      if (awaiterStackFrames != null) {
+        return awaiterStackFrames;
+      }
+    }
+    if (causalAsyncStacks) {
+      var asyncCausalStackFrames = stack[kAsyncCausalStackFrames];
+      if (asyncCausalStackFrames != null) {
+        return asyncCausalStackFrames;
+      }
+    }
+    return stack[kStackFrames] ?? [];
+  }
+
+  static final _history = [''];
+
+  ObservatoryDebugger(this.isolate) {
+    _loadSettings();
+    cmd = new RootCommand([
+      new AsyncNextCommand(this),
+      new BreakCommand(this),
+      new ClearCommand(this),
+      new ClsCommand(this),
+      new ContinueCommand(this),
+      new DeleteCommand(this),
+      new DownCommand(this),
+      new FinishCommand(this),
+      new FrameCommand(this),
+      new HelpCommand(this),
+      new InfoCommand(this),
+      new IsolateCommand(this),
+      new LogCommand(this),
+      new PauseCommand(this),
+      new PrintCommand(this),
+      new ReloadCommand(this, new R.IsolateRepository(this.isolate.vm)),
+      new RefreshCommand(this),
+      new RewindCommand(this),
+      new SetCommand(this),
+      new SmartNextCommand(this),
+      new StepCommand(this),
+      new SyncNextCommand(this),
+      new UpCommand(this),
+      new VmCommand(this),
+    ], _history);
+    _consolePrinter = new _ConsoleStreamPrinter(this);
+  }
+
+  void _loadSettings() {
+    _upIsDown = settings.get('up-is-down');
+    _causalAsyncStacks = settings.get('causal-async-stacks') ?? true;
+    _awaiterStacks = settings.get('awaiter-stacks') ?? true;
+  }
+
+  S.VM get vm => page.app.vm;
+
+  void init() {
+    console.printBold('Debugging isolate isolate ${isolate.number} '
+        '\'${isolate.name}\' ');
+    console.printBold('Type \'h\' for help');
+    // Wait a bit and if polymer still hasn't set up the isolate,
+    // report this to the user.
+    new Timer(const Duration(seconds: 1), () {
+      if (isolate == null) {
+        reportStatus();
+      }
+    });
+
+    if ((breakOnException != isolate.exceptionsPauseInfo) &&
+        (isolate.exceptionsPauseInfo != null)) {
+      breakOnException = isolate.exceptionsPauseInfo;
+    }
+
+    isolate.reload().then((serviceObject) {
+      S.Isolate response = serviceObject;
+      if (response.isSentinel) {
+        // The isolate has gone away.  The IsolateExit event will
+        // clear the isolate for the debugger page.
+        return;
+      }
+      // TODO(turnidge): Currently the debugger relies on all libs
+      // being loaded.  Fix this.
+      var pending = <Future>[];
+      for (var lib in response.libraries) {
+        if (!lib.loaded) {
+          pending.add(lib.load());
+        }
+      }
+      Future.wait(pending).then((_) {
+        refreshStack();
+      }).catchError((e) {
+        print("UNEXPECTED ERROR $e");
+        reportStatus();
+      });
+    });
+  }
+
+  Future refreshStack() async {
+    try {
+      if (isolate != null) {
+        await _refreshStack(isolate.pauseEvent);
+      }
+      flushStdio();
+      reportStatus();
+    } catch (e, st) {
+      console.printRed("Unexpected error in refreshStack: $e\n$st");
+    }
+  }
+
+  bool isolatePaused() {
+    // TODO(turnidge): Stop relying on the isolate to track the last
+    // pause event.  Since we listen to events directly in the
+    // debugger, this could introduce a race.
+    return isolate.status == M.IsolateStatus.paused;
+  }
+
+  void warnOutOfDate() {
+    // Wait a bit, then tell the user that the stack may be out of date.
+    new Timer(const Duration(seconds: 2), () {
+      if (!isolatePaused()) {
+        stackElement.isSampled = true;
+      }
+    });
+  }
+
+  Future<S.ServiceMap> _refreshStack(M.DebugEvent pauseEvent) {
+    return isolate.getStack().then((result) {
+      if (result.isSentinel) {
+        // The isolate has gone away.  The IsolateExit event will
+        // clear the isolate for the debugger page.
+        return;
+      }
+      stack = result;
+      stackElement.updateStack(stack, pauseEvent);
+      if (stack['frames'].length > 0) {
+        currentFrame = 0;
+      } else {
+        currentFrame = null;
+      }
+      input.focus();
+    });
+  }
+
+  void reportStatus() {
+    flushStdio();
+    if (isolate == null) {
+      console.print('No current isolate');
+    } else if (isolate.idle) {
+      console.print('Isolate is idle');
+    } else if (isolate.running) {
+      console.print("Isolate is running (type 'pause' to interrupt)");
+    } else if (isolate.pauseEvent != null) {
+      _reportPause(isolate.pauseEvent);
+    } else {
+      console.print('Isolate is in unknown state');
+    }
+    warnOutOfDate();
+  }
+
+  void _reportIsolateError(S.Isolate isolate, M.DebugEvent event) {
+    if (isolate == null) {
+      return;
+    }
+    S.DartError error = isolate.error;
+    if (error == null) {
+      return;
+    }
+    console.newline();
+    if (event is M.PauseExceptionEvent) {
+      console.printBold('Isolate will exit due to an unhandled exception:');
+    } else {
+      console.printBold('Isolate has exited due to an unhandled exception:');
+    }
+    console.print(error.message);
+    console.newline();
+    if (event is M.PauseExceptionEvent &&
+        (error.exception.isStackOverflowError ||
+            error.exception.isOutOfMemoryError)) {
+      console.printBold(
+          'When an unhandled stack overflow or OOM exception occurs, the VM '
+          'has run out of memory and cannot keep the stack alive while '
+          'paused.');
+    } else {
+      console.printBold("Type 'set break-on-exception Unhandled' to pause the"
+          " isolate when an unhandled exception occurs.");
+      console.printBold("You can make this the default by running with "
+          "--pause-isolates-on-unhandled-exceptions");
+    }
+  }
+
+  void _reportPause(M.DebugEvent event) {
+    if (event is M.NoneEvent) {
+      console.print("Paused until embedder makes the isolate runnable.");
+    } else if (event is M.PauseStartEvent) {
+      console.print("Paused at isolate start "
+          "(type 'continue' [F7] or 'step' [F10] to start the isolate')");
+    } else if (event is M.PauseExitEvent) {
+      console.print("Paused at isolate exit "
+          "(type 'continue' or [F7] to exit the isolate')");
+      _reportIsolateError(isolate, event);
+    } else if (event is M.PauseExceptionEvent) {
+      console.print("Paused at an unhandled exception "
+          "(type 'continue' or [F7] to exit the isolate')");
+      _reportIsolateError(isolate, event);
+    } else if (stack['frames'].length > 0) {
+      S.Frame frame = stack['frames'][0];
+      var script = frame.location.script;
+      script.load().then((_) {
+        var line = script.tokenToLine(frame.location.tokenPos);
+        var col = script.tokenToCol(frame.location.tokenPos);
+        if ((event is M.PauseBreakpointEvent) && (event.breakpoint != null)) {
+          var bpId = event.breakpoint.number;
+          console.print('Paused at breakpoint ${bpId} at '
+              '${script.name}:${line}:${col}');
+        } else if ((event is M.PauseExceptionEvent) &&
+            (event.exception != null)) {
+          console.print('Paused due to exception at '
+              '${script.name}:${line}:${col}');
+          // This seems to be missing if we are paused-at-exception after
+          // paused-at-isolate-exit. Maybe we shutdown part of the debugger too
+          // soon?
+          console.printRef(isolate, event.exception, objects);
+        } else {
+          console.print('Paused at ${script.name}:${line}:${col}');
+        }
+      });
+    } else {
+      console.print("Paused in message loop (type 'continue' or [F7] "
+          "to resume processing messages)");
+    }
+  }
+
+  Future _reportBreakpointEvent(S.ServiceEvent event) async {
+    var bpt = event.breakpoint;
+    var verb = null;
+    switch (event.kind) {
+      case S.ServiceEvent.kBreakpointAdded:
+        verb = 'added';
+        break;
+      case S.ServiceEvent.kBreakpointResolved:
+        verb = 'resolved';
+        break;
+      case S.ServiceEvent.kBreakpointRemoved:
+        verb = 'removed';
+        break;
+      default:
+        break;
+    }
+    var script = bpt.location.script;
+    await script.load();
+
+    var bpId = bpt.number;
+    var locString = await bpt.location.toUserString();
+    if (bpt.resolved) {
+      console.print('Breakpoint ${bpId} ${verb} at ${locString}');
+    } else {
+      console.print('Future breakpoint ${bpId} ${verb} at ${locString}');
+    }
+  }
+
+  void onEvent(S.ServiceEvent event) {
+    switch (event.kind) {
+      case S.ServiceEvent.kVMUpdate:
+        S.VM vm = event.owner;
+        console.print("VM ${vm.displayName} renamed to '${vm.name}'");
+        break;
+
+      case S.ServiceEvent.kIsolateStart:
+        {
+          S.Isolate iso = event.owner;
+          console.print("Isolate ${iso.number} '${iso.name}' has been created");
+        }
+        break;
+
+      case S.ServiceEvent.kIsolateExit:
+        {
+          S.Isolate iso = event.owner;
+          if (iso == isolate) {
+            console.print("The current isolate ${iso.number} '${iso.name}' "
+                "has exited");
+            var isolates = vm.isolates;
+            if (isolates.length > 0) {
+              var newIsolate = isolates.first;
+              new AnchorElement(href: Uris.debugger(newIsolate)).click();
+            } else {
+              new AnchorElement(href: Uris.vm()).click();
+            }
+          } else {
+            console.print("Isolate ${iso.number} '${iso.name}' has exited");
+          }
+        }
+        break;
+
+      case S.ServiceEvent.kDebuggerSettingsUpdate:
+        if (breakOnException != event.exceptions) {
+          breakOnException = event.exceptions;
+          console.print("Now pausing for exceptions: $breakOnException");
+        }
+        break;
+
+      case S.ServiceEvent.kIsolateUpdate:
+        S.Isolate iso = event.owner;
+        console.print("Isolate ${iso.number} renamed to '${iso.name}'");
+        break;
+
+      case S.ServiceEvent.kIsolateReload:
+        var reloadError = event.reloadError;
+        if (reloadError != null) {
+          console.print('Isolate reload failed: ${event.reloadError}');
+        } else {
+          console.print('Isolate reloaded.');
+        }
+        break;
+
+      case S.ServiceEvent.kPauseStart:
+      case S.ServiceEvent.kPauseExit:
+      case S.ServiceEvent.kPauseBreakpoint:
+      case S.ServiceEvent.kPauseInterrupted:
+      case S.ServiceEvent.kPauseException:
+        if (event.owner == isolate) {
+          var e = createEventFromServiceEvent(event);
+          _refreshStack(e).then((_) async {
+            flushStdio();
+            if (isolate != null) {
+              await isolate.reload();
+            }
+            _reportPause(e);
+          });
+        }
+        break;
+
+      case S.ServiceEvent.kResume:
+        if (event.owner == isolate) {
+          flushStdio();
+          console.print('Continuing...');
+        }
+        break;
+
+      case S.ServiceEvent.kBreakpointAdded:
+      case S.ServiceEvent.kBreakpointResolved:
+      case S.ServiceEvent.kBreakpointRemoved:
+        if (event.owner == isolate) {
+          _reportBreakpointEvent(event);
+        }
+        break;
+
+      case S.ServiceEvent.kIsolateRunnable:
+      case S.ServiceEvent.kHeapSnapshot:
+      case S.ServiceEvent.kGC:
+      case S.ServiceEvent.kInspect:
+        // Ignore.
+        break;
+
+      case S.ServiceEvent.kLogging:
+        _consolePrinter.onEvent(event.logRecord['level'].name, event);
+        break;
+
+      default:
+        console.print('Unrecognized event: $event');
+        break;
+    }
+  }
+
+  _ConsoleStreamPrinter _consolePrinter;
+
+  void flushStdio() {
+    _consolePrinter.flush();
+  }
+
+  void onStdout(S.ServiceEvent event) {
+    _consolePrinter.onEvent('stdout', event);
+  }
+
+  void onStderr(S.ServiceEvent event) {
+    _consolePrinter.onEvent('stderr', event);
+  }
+
+  static String _commonPrefix(String a, String b) {
+    int pos = 0;
+    while (pos < a.length && pos < b.length) {
+      if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) {
+        break;
+      }
+      pos++;
+    }
+    return a.substring(0, pos);
+  }
+
+  static String _foldCompletions(List<String> values) {
+    if (values.length == 0) {
+      return '';
+    }
+    var prefix = values[0];
+    for (int i = 1; i < values.length; i++) {
+      prefix = _commonPrefix(prefix, values[i]);
+    }
+    return prefix;
+  }
+
+  Future<String> complete(String line) {
+    return cmd.completeCommand(line).then((completions) {
+      if (completions.length == 0) {
+        // No completions.  Leave the line alone.
+        return line;
+      } else if (completions.length == 1) {
+        // Unambiguous completion.
+        return completions[0];
+      } else {
+        // Ambiguous completion.
+        completions = completions.map((s) => s.trimRight()).toList();
+        console.printBold(completions.toString());
+        return _foldCompletions(completions);
+      }
+    });
+  }
+
+  // TODO(turnidge): Implement real command line history.
+  String lastCommand;
+
+  Future run(String command) {
+    if (command == '' && lastCommand != null) {
+      command = lastCommand;
+    }
+    console.printBold('\$ $command');
+    return cmd.runCommand(command).then((_) {
+      lastCommand = command;
+    }).catchError((e, s) {
+      console.printRed('Unable to execute command because the connection '
+          'to the VM has been closed');
+    }, test: (e) => e is S.NetworkRpcException).catchError((e, s) {
+      console.printRed(e.toString());
+    }, test: (e) => e is CommandException).catchError((e, s) {
+      if (s != null) {
+        console.printRed('Internal error: $e\n$s');
+      } else {
+        console.printRed('Internal error: $e\n');
+      }
+    });
+  }
+
+  String historyPrev(String command) {
+    return cmd.historyPrev(command);
+  }
+
+  String historyNext(String command) {
+    return cmd.historyNext(command);
+  }
+
+  Future pause() {
+    if (!isolatePaused()) {
+      return isolate.pause();
+    } else {
+      console.print('The program is already paused');
+      return new Future.value(null);
+    }
+  }
+
+  Future resume() {
+    if (isolatePaused()) {
+      return isolate.resume().then((_) {
+        warnOutOfDate();
+      });
+    } else {
+      console.print('The program must be paused');
+      return new Future.value(null);
+    }
+  }
+
+  Future toggleBreakpoint() async {
+    var loc = await DebuggerLocation.parse(this, '');
+    var script = loc.script;
+    var line = loc.line;
+    if (script != null && line != null) {
+      var bpts = script.getLine(line).breakpoints;
+      if (bpts == null || bpts.isEmpty) {
+        // Set a new breakpoint.
+        // TODO(turnidge): Set this breakpoint at current column.
+        await isolate.addBreakpoint(script, line);
+      } else {
+        // TODO(turnidge): Clear this breakpoint at current column.
+        var pending = <Future>[];
+        for (var bpt in bpts) {
+          pending.add(isolate.removeBreakpoint(bpt));
+        }
+        await Future.wait(pending);
+      }
+    }
+    return new Future.value(null);
+  }
+
+  Future smartNext() async {
+    if (isolatePaused()) {
+      M.AsyncSuspensionEvent event = isolate.pauseEvent;
+      if (event.atAsyncSuspension) {
+        return asyncNext();
+      } else {
+        return syncNext();
+      }
+    } else {
+      console.print('The program is already running');
+    }
+  }
+
+  Future asyncNext() async {
+    if (isolatePaused()) {
+      M.AsyncSuspensionEvent event = isolate.pauseEvent;
+      if (!event.atAsyncSuspension) {
+        console.print("No async continuation at this location");
+      } else {
+        return isolate.stepOverAsyncSuspension();
+      }
+    } else {
+      console.print('The program is already running');
+    }
+  }
+
+  Future syncNext() async {
+    if (isolatePaused()) {
+      var event = isolate.pauseEvent;
+      if (event is M.PauseStartEvent) {
+        console
+            .print("Type 'continue' [F7] or 'step' [F10] to start the isolate");
+        return null;
+      }
+      if (event is M.PauseExitEvent) {
+        console.print("Type 'continue' [F7] to exit the isolate");
+        return null;
+      }
+      return isolate.stepOver();
+    } else {
+      console.print('The program is already running');
+      return null;
+    }
+  }
+
+  Future step() {
+    if (isolatePaused()) {
+      var event = isolate.pauseEvent;
+      if (event is M.PauseExitEvent) {
+        console.print("Type 'continue' [F7] to exit the isolate");
+        return new Future.value(null);
+      }
+      return isolate.stepInto();
+    } else {
+      console.print('The program is already running');
+      return new Future.value(null);
+    }
+  }
+
+  Future rewind(int count) {
+    if (isolatePaused()) {
+      var event = isolate.pauseEvent;
+      if (event is M.PauseExitEvent) {
+        console.print("Type 'continue' [F7] to exit the isolate");
+        return new Future.value(null);
+      }
+      return isolate.rewind(count);
+    } else {
+      console.print('The program must be paused');
+      return new Future.value(null);
+    }
+  }
+}
+
+class DebuggerPageElement extends CustomElement implements Renderable {
+  S.Isolate _isolate;
+  ObservatoryDebugger _debugger;
+  M.ObjectRepository _objects;
+  M.ScriptRepository _scripts;
+  M.EventRepository _events;
+
+  factory DebuggerPageElement(S.Isolate isolate, M.ObjectRepository objects,
+      M.ScriptRepository scripts, M.EventRepository events) {
+    assert(isolate != null);
+    assert(objects != null);
+    assert(scripts != null);
+    assert(events != null);
+    final DebuggerPageElement e = new DebuggerPageElement.created();
+    final debugger = new ObservatoryDebugger(isolate);
+    debugger.page = e;
+    debugger.objects = objects;
+    e._isolate = isolate;
+    e._debugger = debugger;
+    e._objects = objects;
+    e._scripts = scripts;
+    e._events = events;
+    return e;
+  }
+
+  DebuggerPageElement.created() : super.created('debugger-page');
+
+  Future<StreamSubscription> _vmSubscriptionFuture;
+  Future<StreamSubscription> _isolateSubscriptionFuture;
+  Future<StreamSubscription> _debugSubscriptionFuture;
+  Future<StreamSubscription> _stdoutSubscriptionFuture;
+  Future<StreamSubscription> _stderrSubscriptionFuture;
+  Future<StreamSubscription> _logSubscriptionFuture;
+
+  ObservatoryApplication get app => ObservatoryApplication.app;
+
+  Timer _timer;
+
+  static final consoleElement = new DebuggerConsoleElement();
+
+  @override
+  void attached() {
+    super.attached();
+
+    final stackDiv = new DivElement()..classes = ['stack'];
+    final stackElement = new DebuggerStackElement(
+        _isolate, _debugger, stackDiv, _objects, _scripts, _events);
+    stackDiv.children = <Element>[stackElement.element];
+    final consoleDiv = new DivElement()
+      ..classes = ['console']
+      ..children = <Element>[consoleElement.element];
+    final commandElement = new DebuggerInputElement(_isolate, _debugger);
+    final commandDiv = new DivElement()
+      ..classes = ['commandline']
+      ..children = <Element>[commandElement.element];
+
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: app.queue).element,
+        new NavVMMenuElement(app.vm, app.events, queue: app.queue).element,
+        new NavIsolateMenuElement(_isolate, app.events, queue: app.queue)
+            .element,
+        navMenu('debugger'),
+        new NavNotifyElement(app.notifications,
+                notifyOnPause: false, queue: app.queue)
+            .element
+      ]),
+      new DivElement()
+        ..classes = ['variable']
+        ..children = <Element>[
+          stackDiv,
+          new DivElement()
+            ..children = <Element>[
+              new HRElement()..classes = ['splitter']
+            ],
+          consoleDiv,
+        ],
+      commandDiv
+    ];
+
+    DebuggerConsoleElement._scrollToBottom(consoleDiv);
+
+    // Wire the debugger object to the stack, console, and command line.
+    _debugger.stackElement = stackElement;
+    _debugger.console = consoleElement;
+    _debugger.input = commandElement;
+    _debugger.input._debugger = _debugger;
+    _debugger.init();
+
+    _vmSubscriptionFuture =
+        app.vm.listenEventStream(S.VM.kVMStream, _debugger.onEvent);
+    _isolateSubscriptionFuture =
+        app.vm.listenEventStream(S.VM.kIsolateStream, _debugger.onEvent);
+    _debugSubscriptionFuture =
+        app.vm.listenEventStream(S.VM.kDebugStream, _debugger.onEvent);
+    _stdoutSubscriptionFuture =
+        app.vm.listenEventStream(S.VM.kStdoutStream, _debugger.onStdout);
+    if (_stdoutSubscriptionFuture != null) {
+      // TODO(turnidge): How do we want to handle this in general?
+      _stdoutSubscriptionFuture.catchError((e, st) {
+        Logger.root.info('Failed to subscribe to stdout: $e\n$st\n');
+        _stdoutSubscriptionFuture = null;
+      });
+    }
+    _stderrSubscriptionFuture =
+        app.vm.listenEventStream(S.VM.kStderrStream, _debugger.onStderr);
+    if (_stderrSubscriptionFuture != null) {
+      // TODO(turnidge): How do we want to handle this in general?
+      _stderrSubscriptionFuture.catchError((e, st) {
+        Logger.root.info('Failed to subscribe to stderr: $e\n$st\n');
+        _stderrSubscriptionFuture = null;
+      });
+    }
+    _logSubscriptionFuture =
+        app.vm.listenEventStream(S.Isolate.kLoggingStream, _debugger.onEvent);
+    // Turn on the periodic poll timer for this page.
+    _timer = new Timer.periodic(const Duration(milliseconds: 100), (_) {
+      _debugger.flushStdio();
+    });
+
+    onClick.listen((event) {
+      // Random clicks should focus on the text box.  If the user selects
+      // a range, don't interfere.
+      var selection = window.getSelection();
+      if (selection == null ||
+          (selection.type != 'Range' && selection.type != 'text')) {
+        _debugger.input.focus();
+      }
+    });
+  }
+
+  @override
+  void render() {
+    /* nothing to do */
+  }
+
+  @override
+  void detached() {
+    _timer.cancel();
+    children = const [];
+    S.cancelFutureSubscription(_vmSubscriptionFuture);
+    _vmSubscriptionFuture = null;
+    S.cancelFutureSubscription(_isolateSubscriptionFuture);
+    _isolateSubscriptionFuture = null;
+    S.cancelFutureSubscription(_debugSubscriptionFuture);
+    _debugSubscriptionFuture = null;
+    S.cancelFutureSubscription(_stdoutSubscriptionFuture);
+    _stdoutSubscriptionFuture = null;
+    S.cancelFutureSubscription(_stderrSubscriptionFuture);
+    _stderrSubscriptionFuture = null;
+    S.cancelFutureSubscription(_logSubscriptionFuture);
+    _logSubscriptionFuture = null;
+    super.detached();
+  }
+}
+
+class DebuggerStackElement extends CustomElement implements Renderable {
+  S.Isolate _isolate;
+  M.ObjectRepository _objects;
+  M.ScriptRepository _scripts;
+  M.EventRepository _events;
+  Element _scroller;
+  DivElement _isSampled;
+  bool get isSampled => !_isSampled.classes.contains('hidden');
+  set isSampled(bool value) {
+    if (value != isSampled) {
+      _isSampled.classes.toggle('hidden');
+    }
+  }
+
+  DivElement _hasStack;
+  bool get hasStack => _hasStack.classes.contains('hidden');
+  set hasStack(bool value) {
+    if (value != hasStack) {
+      _hasStack.classes.toggle('hidden');
+    }
+  }
+
+  DivElement _hasMessages;
+  bool get hasMessages => _hasMessages.classes.contains('hidden');
+  set hasMessages(bool value) {
+    if (value != hasMessages) {
+      _hasMessages.classes.toggle('hidden');
+    }
+  }
+
+  UListElement _frameList;
+  UListElement _messageList;
+  int currentFrame;
+  ObservatoryDebugger _debugger;
+
+  factory DebuggerStackElement(
+      S.Isolate isolate,
+      ObservatoryDebugger debugger,
+      Element scroller,
+      M.ObjectRepository objects,
+      M.ScriptRepository scripts,
+      M.EventRepository events) {
+    assert(isolate != null);
+    assert(debugger != null);
+    assert(scroller != null);
+    assert(objects != null);
+    assert(scripts != null);
+    assert(events != null);
+    final DebuggerStackElement e = new DebuggerStackElement.created();
+    e._isolate = isolate;
+    e._debugger = debugger;
+    e._scroller = scroller;
+    e._objects = objects;
+    e._scripts = scripts;
+    e._events = events;
+
+    var btnPause;
+    var btnRefresh;
+    e.children = <Element>[
+      e._isSampled = new DivElement()
+        ..classes = ['sampledMessage', 'hidden']
+        ..children = <Element>[
+          new SpanElement()
+            ..text = 'The program is not paused. '
+                'The stack trace below may be out of date.',
+          new BRElement(),
+          new BRElement(),
+          btnPause = new ButtonElement()
+            ..text = '[Pause Isolate]'
+            ..onClick.listen((_) async {
+              btnPause.disabled = true;
+              try {
+                await debugger.isolate.pause();
+              } finally {
+                btnPause.disabled = false;
+              }
+            }),
+          btnRefresh = new ButtonElement()
+            ..text = '[Refresh Stack]'
+            ..onClick.listen((_) async {
+              btnRefresh.disabled = true;
+              try {
+                await debugger.refreshStack();
+              } finally {
+                btnRefresh.disabled = false;
+              }
+            }),
+          new BRElement(),
+          new BRElement(),
+          new HRElement()..classes = ['splitter']
+        ],
+      e._hasStack = new DivElement()
+        ..classes = ['noStack', 'hidden']
+        ..text = 'No stack',
+      e._frameList = new UListElement()..classes = ['list-group'],
+      new HRElement(),
+      e._hasMessages = new DivElement()
+        ..classes = ['noMessages', 'hidden']
+        ..text = 'No pending messages',
+      e._messageList = new UListElement()..classes = ['messageList']
+    ];
+    return e;
+  }
+
+  void render() {
+    /* nothing to do */
+  }
+
+  _addFrame(List frameList, S.Frame frameInfo) {
+    final frameElement = new DebuggerFrameElement(
+        _isolate, frameInfo, _scroller, _objects, _scripts, _events,
+        queue: app.queue);
+
+    if (frameInfo.index == currentFrame) {
+      frameElement.setCurrent(true);
+    } else {
+      frameElement.setCurrent(false);
+    }
+
+    var li = new LIElement();
+    li.classes.add('list-group-item');
+    li.children.insert(0, frameElement.element);
+
+    frameList.insert(0, li);
+  }
+
+  _addMessage(List messageList, S.ServiceMessage messageInfo) {
+    final messageElement = new DebuggerMessageElement(
+        _isolate, messageInfo, _objects, _scripts, _events,
+        queue: app.queue);
+
+    var li = new LIElement();
+    li.classes.add('list-group-item');
+    li.children.insert(0, messageElement.element);
+
+    messageList.add(li);
+  }
+
+  ObservatoryApplication get app => ObservatoryApplication.app;
+
+  void updateStackFrames(S.ServiceMap newStack) {
+    List frameElements = _frameList.children;
+    List newFrames;
+    if (_debugger.awaiterStacks &&
+        (newStack[ObservatoryDebugger.kAwaiterStackFrames] != null)) {
+      newFrames = newStack[ObservatoryDebugger.kAwaiterStackFrames];
+    } else if (_debugger.causalAsyncStacks &&
+        (newStack[ObservatoryDebugger.kAsyncCausalStackFrames] != null)) {
+      newFrames = newStack[ObservatoryDebugger.kAsyncCausalStackFrames];
+    } else {
+      newFrames = newStack[ObservatoryDebugger.kStackFrames];
+    }
+
+    // Remove any frames whose functions don't match, starting from
+    // bottom of stack.
+    int oldPos = frameElements.length - 1;
+    int newPos = newFrames.length - 1;
+    while (oldPos >= 0 && newPos >= 0) {
+      DebuggerFrameElement dbgFrameElement =
+          CustomElement.reverse(frameElements[oldPos].children[0]);
+      if (!dbgFrameElement.matchFrame(newFrames[newPos])) {
+        // The rest of the frame elements no longer match.  Remove them.
+        for (int i = 0; i <= oldPos; i++) {
+          // NOTE(turnidge): removeRange is missing, sadly.
+          frameElements.removeAt(0);
+        }
+        break;
+      }
+      oldPos--;
+      newPos--;
+    }
+
+    // Remove any extra frames.
+    if (frameElements.length > newFrames.length) {
+      // Remove old frames from the top of stack.
+      int removeCount = frameElements.length - newFrames.length;
+      for (int i = 0; i < removeCount; i++) {
+        frameElements.removeAt(0);
+      }
+    }
+
+    // Add any new frames.
+    int newCount = 0;
+    if (frameElements.length < newFrames.length) {
+      // Add new frames to the top of stack.
+      newCount = newFrames.length - frameElements.length;
+      for (int i = newCount - 1; i >= 0; i--) {
+        _addFrame(frameElements, newFrames[i]);
+      }
+    }
+    assert(frameElements.length == newFrames.length);
+
+    if (frameElements.isNotEmpty) {
+      for (int i = newCount; i < frameElements.length; i++) {
+        DebuggerFrameElement dbgFrameElement =
+            CustomElement.reverse(frameElements[i].children[0]);
+        dbgFrameElement.updateFrame(newFrames[i]);
+      }
+    }
+
+    hasStack = frameElements.isNotEmpty;
+  }
+
+  void updateStackMessages(S.ServiceMap newStack) {
+    List messageElements = _messageList.children;
+    List newMessages = newStack['messages'];
+
+    // Remove any extra message elements.
+    if (messageElements.length > newMessages.length) {
+      // Remove old messages from the front of the queue.
+      int removeCount = messageElements.length - newMessages.length;
+      for (int i = 0; i < removeCount; i++) {
+        messageElements.removeAt(0);
+      }
+    }
+
+    // Add any new messages to the tail of the queue.
+    int newStartingIndex = messageElements.length;
+    if (messageElements.length < newMessages.length) {
+      for (int i = newStartingIndex; i < newMessages.length; i++) {
+        _addMessage(messageElements, newMessages[i]);
+      }
+    }
+    assert(messageElements.length == newMessages.length);
+
+    if (messageElements.isNotEmpty) {
+      // Update old messages.
+      for (int i = 0; i < newStartingIndex; i++) {
+        DebuggerMessageElement e =
+            CustomElement.reverse(messageElements[i].children[0]);
+        e.updateMessage(newMessages[i]);
+      }
+    }
+
+    hasMessages = messageElements.isNotEmpty;
+  }
+
+  void updateStack(S.ServiceMap newStack, M.DebugEvent pauseEvent) {
+    updateStackFrames(newStack);
+    updateStackMessages(newStack);
+    isSampled = pauseEvent == null;
+  }
+
+  void setCurrentFrame(int value) {
+    currentFrame = value;
+    List frameElements = _frameList.children;
+    for (var frameElement in frameElements) {
+      DebuggerFrameElement dbgFrameElement =
+          CustomElement.reverse(frameElement.children[0]);
+      if (dbgFrameElement.frame.index == currentFrame) {
+        dbgFrameElement.setCurrent(true);
+      } else {
+        dbgFrameElement.setCurrent(false);
+      }
+    }
+  }
+
+  DebuggerStackElement.created() : super.created('debugger-stack');
+}
+
+class DebuggerFrameElement extends CustomElement implements Renderable {
+  RenderingScheduler<DebuggerFrameElement> _r;
+
+  Stream<RenderedEvent<DebuggerFrameElement>> get onRendered => _r.onRendered;
+
+  Element _scroller;
+  DivElement _varsDiv;
+  M.Isolate _isolate;
+  S.Frame _frame;
+  S.Frame get frame => _frame;
+  M.ObjectRepository _objects;
+  M.ScriptRepository _scripts;
+  M.EventRepository _events;
+
+  // Is this the current frame?
+  bool _current = false;
+
+  // Has this frame been pinned open?
+  bool _pinned = false;
+
+  bool _expanded = false;
+
+  void setCurrent(bool value) {
+    Future load = (_frame.function != null)
+        ? _frame.function.load()
+        : new Future.value(null);
+    load.then((func) {
+      _current = value;
+      if (_current) {
+        _expand();
+        scrollIntoView();
+      } else {
+        if (_pinned) {
+          _expand();
+        } else {
+          _unexpand();
+        }
+      }
+    });
+  }
+
+  factory DebuggerFrameElement(
+      M.Isolate isolate,
+      S.Frame frame,
+      Element scroller,
+      M.ObjectRepository objects,
+      M.ScriptRepository scripts,
+      M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(frame != null);
+    assert(scroller != null);
+    assert(objects != null);
+    assert(scripts != null);
+    assert(events != null);
+    final DebuggerFrameElement e = new DebuggerFrameElement.created();
+    e._r = new RenderingScheduler<DebuggerFrameElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._frame = frame;
+    e._scroller = scroller;
+    e._objects = objects;
+    e._scripts = scripts;
+    e._events = events;
+    return e;
+  }
+
+  DebuggerFrameElement.created() : super.created('debugger-frame');
+
+  void render() {
+    if (_pinned) {
+      classes.add('shadow');
+    } else {
+      classes.remove('shadow');
+    }
+    if (_current) {
+      classes.add('current');
+    } else {
+      classes.remove('current');
+    }
+    if ((_frame.kind == M.FrameKind.asyncSuspensionMarker) ||
+        (_frame.kind == M.FrameKind.asyncCausal)) {
+      classes.add('causalFrame');
+    }
+    if (_frame.kind == M.FrameKind.asyncSuspensionMarker) {
+      final content = <Element>[
+        new SpanElement()..children = _createMarkerHeader(_frame.marker)
+      ];
+      children = content;
+      return;
+    }
+    ButtonElement expandButton;
+    final content = <Element>[
+      expandButton = new ButtonElement()
+        ..children = _createHeader()
+        ..onClick.listen((e) async {
+          if (e.target is AnchorElement) {
+            return;
+          }
+          expandButton.disabled = true;
+          await _toggleExpand();
+          expandButton.disabled = false;
+        })
+    ];
+    if (_expanded) {
+      final homeMethod = _frame.function.homeMethod;
+      String homeMethodName;
+      if ((homeMethod.dartOwner is S.Class) && homeMethod.isStatic) {
+        homeMethodName = '<class>';
+      } else if (homeMethod.dartOwner is S.Library) {
+        homeMethodName = '<library>';
+      }
+      ButtonElement collapseButton;
+      content.addAll([
+        new DivElement()
+          ..classes = ['frameDetails']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['flex-row-wrap']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['flex-item-script']
+                  ..children = _frame.function?.location == null
+                      ? const []
+                      : [
+                          (new SourceInsetElement(
+                                  _isolate,
+                                  _frame.function.location,
+                                  _scripts,
+                                  _objects,
+                                  _events,
+                                  currentPos: _frame.location.tokenPos,
+                                  variables: _frame.variables,
+                                  inDebuggerContext: true,
+                                  queue: _r.queue))
+                              .element
+                        ],
+                new DivElement()
+                  ..classes = ['flex-item-vars']
+                  ..children = <Element>[
+                    _varsDiv = new DivElement()
+                      ..classes = ['memberList', 'frameVars']
+                      ..children = ([
+                        new DivElement()
+                          ..classes = ['memberItem']
+                          ..children = homeMethodName == null
+                              ? const []
+                              : [
+                                  new DivElement()
+                                    ..classes = ['memberName']
+                                    ..text = homeMethodName,
+                                  new DivElement()
+                                    ..classes = ['memberName']
+                                    ..children = <Element>[
+                                      anyRef(_isolate, homeMethod.dartOwner,
+                                          _objects,
+                                          queue: _r.queue)
+                                    ]
+                                ]
+                      ]..addAll(_frame.variables
+                          .map<Element>((v) => new DivElement()
+                            ..classes = ['memberItem']
+                            ..children = <Element>[
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..text = v.name,
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..children = <Element>[
+                                  anyRef(_isolate, v['value'], _objects,
+                                      queue: _r.queue)
+                                ]
+                            ])
+                          .toList()))
+                  ]
+              ],
+            new DivElement()
+              ..classes = ['frameContractor']
+              ..children = <Element>[
+                collapseButton = new ButtonElement()
+                  ..onClick.listen((e) async {
+                    collapseButton.disabled = true;
+                    await _toggleExpand();
+                    collapseButton.disabled = false;
+                  })
+                  ..children = <Element>[iconExpandLess.clone(true)]
+              ]
+          ]
+      ]);
+    }
+    children = content;
+  }
+
+  List<Element> _createMarkerHeader(String marker) {
+    final content = <Element>[
+      new DivElement()
+        ..classes = ['frameSummaryText']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['frameId']
+            ..text = 'Frame ${_frame.index}',
+          new SpanElement()..text = '$marker',
+        ]
+    ];
+    return [
+      new DivElement()
+        ..classes = ['frameSummary']
+        ..children = content
+    ];
+  }
+
+  List<Element> _createHeader() {
+    final content = <Element>[
+      new DivElement()
+        ..classes = ['frameSummaryText']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['frameId']
+            ..text = 'Frame ${_frame.index}',
+          new SpanElement()
+            ..children = _frame.function == null
+                ? const []
+                : [
+                    new FunctionRefElement(_isolate, _frame.function,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new SpanElement()..text = ' ( ',
+          new SpanElement()
+            ..children = _frame.function?.location == null
+                ? const []
+                : [
+                    new SourceLinkElement(
+                            _isolate, _frame.function.location, _scripts,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new SpanElement()..text = ' )'
+        ]
+    ];
+    if (!_expanded) {
+      content.add(new DivElement()
+        ..classes = ['frameExpander']
+        ..children = <Element>[iconExpandMore.clone(true)]);
+    }
+    return [
+      new DivElement()
+        ..classes = ['frameSummary']
+        ..children = content
+    ];
+  }
+
+  String makeExpandKey(String key) {
+    return '${_frame.function.qualifiedName}/${key}';
+  }
+
+  bool matchFrame(S.Frame newFrame) {
+    if (newFrame.kind != _frame.kind) {
+      return false;
+    }
+    if (newFrame.function == null) {
+      return frame.function == null;
+    }
+    return (newFrame.function.id == _frame.function.id &&
+        newFrame.location.script.id == frame.location.script.id);
+  }
+
+  void updateFrame(S.Frame newFrame) {
+    assert(matchFrame(newFrame));
+    _frame = newFrame;
+  }
+
+  S.Script get script => _frame.location.script;
+
+  int _varsTop(DivElement varsDiv) {
+    const minTop = 0;
+    if (varsDiv == null) {
+      return minTop;
+    }
+    final num paddingTop = document.body.contentEdge.top;
+    final Rectangle parent = varsDiv.parent.getBoundingClientRect();
+    final int varsHeight = varsDiv.clientHeight;
+    final int maxTop = (parent.height - varsHeight).toInt();
+    final int adjustedTop = (paddingTop - parent.top).toInt();
+    return max(minTop, min(maxTop, adjustedTop));
+  }
+
+  void _onScroll(event) {
+    if (!_expanded || _varsDiv == null) {
+      return;
+    }
+    String currentTop = _varsDiv.style.top;
+    int newTop = _varsTop(_varsDiv);
+    if (currentTop != newTop) {
+      _varsDiv.style.top = '${newTop}px';
+    }
+  }
+
+  void _expand() {
+    _expanded = true;
+    _subscribeToScroll();
+    _r.dirty();
+  }
+
+  void _unexpand() {
+    _expanded = false;
+    _unsubscribeToScroll();
+    _r.dirty();
+  }
+
+  StreamSubscription _scrollSubscription;
+  StreamSubscription _resizeSubscription;
+
+  void _subscribeToScroll() {
+    if (_scroller != null) {
+      if (_scrollSubscription == null) {
+        _scrollSubscription = _scroller.onScroll.listen(_onScroll);
+      }
+      if (_resizeSubscription == null) {
+        _resizeSubscription = window.onResize.listen(_onScroll);
+      }
+    }
+  }
+
+  void _unsubscribeToScroll() {
+    if (_scrollSubscription != null) {
+      _scrollSubscription.cancel();
+      _scrollSubscription = null;
+    }
+    if (_resizeSubscription != null) {
+      _resizeSubscription.cancel();
+      _resizeSubscription = null;
+    }
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    if (_expanded) {
+      _subscribeToScroll();
+    }
+  }
+
+  void detached() {
+    _r.disable(notify: true);
+    super.detached();
+    _unsubscribeToScroll();
+  }
+
+  Future _toggleExpand() async {
+    await _frame.function.load();
+    _pinned = !_pinned;
+    if (_pinned) {
+      _expand();
+    } else {
+      _unexpand();
+    }
+  }
+}
+
+class DebuggerMessageElement extends CustomElement implements Renderable {
+  RenderingScheduler<DebuggerMessageElement> _r;
+
+  Stream<RenderedEvent<DebuggerMessageElement>> get onRendered => _r.onRendered;
+
+  S.Isolate _isolate;
+  S.ServiceMessage _message;
+  S.ServiceObject _preview;
+  M.ObjectRepository _objects;
+  M.ScriptRepository _scripts;
+  M.EventRepository _events;
+
+  // Is this the current message?
+  bool _current = false;
+
+  // Has this message been pinned open?
+  bool _pinned = false;
+
+  bool _expanded = false;
+
+  factory DebuggerMessageElement(
+      S.Isolate isolate,
+      S.ServiceMessage message,
+      M.ObjectRepository objects,
+      M.ScriptRepository scripts,
+      M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(message != null);
+    assert(objects != null);
+    assert(events != null);
+    final DebuggerMessageElement e = new DebuggerMessageElement.created();
+    e._r = new RenderingScheduler<DebuggerMessageElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._message = message;
+    e._objects = objects;
+    e._scripts = scripts;
+    e._events = events;
+    return e;
+  }
+
+  DebuggerMessageElement.created() : super.created('debugger-message');
+
+  void render() {
+    if (_pinned) {
+      classes.add('shadow');
+    } else {
+      classes.remove('shadow');
+    }
+    if (_current) {
+      classes.add('current');
+    } else {
+      classes.remove('current');
+    }
+    ButtonElement expandButton;
+    final content = <Element>[
+      expandButton = new ButtonElement()
+        ..children = _createHeader()
+        ..onClick.listen((e) async {
+          if (e.target is AnchorElement) {
+            return;
+          }
+          expandButton.disabled = true;
+          await _toggleExpand();
+          expandButton.disabled = false;
+        })
+    ];
+    if (_expanded) {
+      ButtonElement collapseButton;
+      ButtonElement previewButton;
+      content.addAll([
+        new DivElement()
+          ..classes = ['messageDetails']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['flex-row-wrap']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['flex-item-script']
+                  ..children = _message.handler == null
+                      ? const []
+                      : [
+                          new SourceInsetElement(
+                                  _isolate,
+                                  _message.handler.location,
+                                  _scripts,
+                                  _objects,
+                                  _events,
+                                  inDebuggerContext: true,
+                                  queue: _r.queue)
+                              .element
+                        ],
+                new DivElement()
+                  ..classes = ['flex-item-vars']
+                  ..children = <Element>[
+                    new DivElement()
+                      ..classes = ['memberItem']
+                      ..children = <Element>[
+                        new DivElement()..classes = ['memberName'],
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..children = ([
+                            previewButton = new ButtonElement()
+                              ..text = 'preview'
+                              ..onClick.listen((_) {
+                                previewButton.disabled = true;
+                              })
+                          ]..addAll(_preview == null
+                              ? const []
+                              : [
+                                  anyRef(_isolate, _preview, _objects,
+                                      queue: _r.queue)
+                                ]))
+                      ]
+                  ]
+              ],
+            new DivElement()
+              ..classes = ['messageContractor']
+              ..children = <Element>[
+                collapseButton = new ButtonElement()
+                  ..onClick.listen((e) async {
+                    collapseButton.disabled = true;
+                    await _toggleExpand();
+                    collapseButton.disabled = false;
+                  })
+                  ..children = <Element>[iconExpandLess.clone(true)]
+              ]
+          ]
+      ]);
+    }
+    children = content;
+  }
+
+  void updateMessage(S.ServiceMessage message) {
+    assert(_message != null);
+    _message = message;
+    _r.dirty();
+  }
+
+  List<Element> _createHeader() {
+    final content = <Element>[
+      new DivElement()
+        ..classes = ['messageSummaryText']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['messageId']
+            ..text = 'message ${_message.index}',
+          new SpanElement()
+            ..children = _message.handler == null
+                ? const []
+                : [
+                    new FunctionRefElement(_isolate, _message.handler,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new SpanElement()..text = ' ( ',
+          new SpanElement()
+            ..children = _message.location == null
+                ? const []
+                : [
+                    new SourceLinkElement(_isolate, _message.location, _scripts,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new SpanElement()..text = ' )'
+        ]
+    ];
+    if (!_expanded) {
+      content.add(new DivElement()
+        ..classes = ['messageExpander']
+        ..children = <Element>[iconExpandMore.clone(true)]);
+    }
+    return [
+      new DivElement()
+        ..classes = ['messageSummary']
+        ..children = content
+    ];
+  }
+
+  void setCurrent(bool value) {
+    _current = value;
+    if (_current) {
+      _expanded = true;
+      scrollIntoView();
+      _r.dirty();
+    } else {
+      _expanded = _pinned;
+    }
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  Future _toggleExpand() async {
+    var function = _message.handler;
+    if (function != null) {
+      await function.load();
+    }
+    _pinned = _pinned;
+    _expanded = true;
+    _r.dirty();
+  }
+
+  Future<S.ServiceObject> previewMessage(_) {
+    return _message.isolate.getObject(_message.messageObjectId).then((result) {
+      _preview = result;
+      return result;
+    });
+  }
+}
+
+class DebuggerConsoleElement extends CustomElement implements Renderable {
+  factory DebuggerConsoleElement() {
+    final DebuggerConsoleElement e = new DebuggerConsoleElement.created();
+    e.children = <Element>[new BRElement()];
+    return e;
+  }
+
+  DebuggerConsoleElement.created() : super.created('debugger-console');
+
+  /// Is [container] scrolled to the within [threshold] pixels of the bottom?
+  static bool _isScrolledToBottom(DivElement container, [int threshold = 2]) {
+    if (container == null) {
+      return false;
+    }
+    // scrollHeight -> complete height of element including scrollable area.
+    // clientHeight -> height of element on page.
+    // scrollTop -> how far is an element scrolled (from 0 to scrollHeight).
+    final distanceFromBottom =
+        container.scrollHeight - container.clientHeight - container.scrollTop;
+    const threshold = 2; // 2 pixel slop.
+    return distanceFromBottom <= threshold;
+  }
+
+  /// Scroll [container] so the bottom content is visible.
+  static _scrollToBottom(DivElement container) {
+    if (container == null) {
+      return;
+    }
+    // Adjust scroll so that the bottom of the content is visible.
+    container.scrollTop = container.scrollHeight - container.clientHeight;
+  }
+
+  void _append(HtmlElement span) {
+    bool autoScroll = _isScrolledToBottom(parent);
+    children.add(span);
+    if (autoScroll) {
+      _scrollToBottom(parent);
+    }
+  }
+
+  void print(String line, {bool newline: true}) {
+    var span = new SpanElement();
+    span.classes.add('normal');
+    span.appendText(line);
+    if (newline) {
+      span.appendText('\n');
+    }
+    _append(span);
+  }
+
+  void printBold(String line, {bool newline: true}) {
+    var span = new SpanElement();
+    span.classes.add('bold');
+    span.appendText(line);
+    if (newline) {
+      span.appendText('\n');
+    }
+    _append(span);
+  }
+
+  void printRed(String line, {bool newline: true}) {
+    var span = new SpanElement();
+    span.classes.add('red');
+    span.appendText(line);
+    if (newline) {
+      span.appendText('\n');
+    }
+    _append(span);
+  }
+
+  void printStdio(List<String> lines) {
+    bool autoScroll = _isScrolledToBottom(parent);
+    for (var line in lines) {
+      var span = new SpanElement();
+      span.classes.add('green');
+      span.appendText(line);
+      span.appendText('\n');
+      children.add(span);
+    }
+    if (autoScroll) {
+      _scrollToBottom(parent);
+    }
+  }
+
+  void printRef(S.Isolate isolate, S.Instance ref, M.ObjectRepository objects,
+      {bool newline: true}) {
+    _append(new InstanceRefElement(isolate, ref, objects, queue: app.queue)
+        .element);
+    if (newline) {
+      this.newline();
+    }
+  }
+
+  void newline() {
+    _append(new BRElement());
+  }
+
+  void clear() {
+    children.clear();
+  }
+
+  void render() {
+    /* nothing to do */
+  }
+
+  ObservatoryApplication get app => ObservatoryApplication.app;
+}
+
+class DebuggerInputElement extends CustomElement implements Renderable {
+  S.Isolate _isolate;
+  ObservatoryDebugger _debugger;
+  bool _busy = false;
+  final _modalPromptDiv = new DivElement()..classes = ['modalPrompt', 'hidden'];
+  final _textBox = new TextInputElement()
+    ..classes = ['textBox']
+    ..autofocus = true;
+  String get modalPrompt => _modalPromptDiv.text;
+  set modalPrompt(String value) {
+    if (_modalPromptDiv.text == '') {
+      _modalPromptDiv.classes.remove('hidden');
+    }
+    _modalPromptDiv.text = value;
+    if (_modalPromptDiv.text == '') {
+      _modalPromptDiv.classes.add('hidden');
+    }
+  }
+
+  String get text => _textBox.value;
+  set text(String value) => _textBox.value = value;
+  var modalCallback = null;
+
+  factory DebuggerInputElement(
+      S.Isolate isolate, ObservatoryDebugger debugger) {
+    final DebuggerInputElement e = new DebuggerInputElement.created();
+    e.children = <Element>[e._modalPromptDiv, e._textBox];
+    e._textBox.select();
+    e._textBox.onKeyDown.listen(e._onKeyDown);
+    return e;
+  }
+
+  DebuggerInputElement.created() : super.created('debugger-input');
+
+  void _onKeyDown(KeyboardEvent e) {
+    if (_busy) {
+      e.preventDefault();
+      return;
+    }
+    _busy = true;
+    if (modalCallback != null) {
+      if (e.keyCode == KeyCode.ENTER) {
+        var response = text;
+        modalCallback(response).whenComplete(() {
+          text = '';
+          _busy = false;
+        });
+      } else {
+        _busy = false;
+      }
+      return;
+    }
+    switch (e.keyCode) {
+      case KeyCode.TAB:
+        e.preventDefault();
+        int cursorPos = _textBox.selectionStart;
+        _debugger.complete(text.substring(0, cursorPos)).then((completion) {
+          text = completion + text.substring(cursorPos);
+          // TODO(turnidge): Move the cursor to the end of the
+          // completion, rather than the end of the string.
+        }).whenComplete(() {
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.ENTER:
+        var command = text;
+        _debugger.run(command).whenComplete(() {
+          text = '';
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.UP:
+        e.preventDefault();
+        text = _debugger.historyPrev(text);
+        _busy = false;
+        break;
+
+      case KeyCode.DOWN:
+        e.preventDefault();
+        text = _debugger.historyNext(text);
+        _busy = false;
+        break;
+
+      case KeyCode.PAGE_UP:
+        e.preventDefault();
+        try {
+          _debugger.upFrame(1);
+        } on RangeError catch (_) {
+          // Ignore.
+        }
+        _busy = false;
+        break;
+
+      case KeyCode.PAGE_DOWN:
+        e.preventDefault();
+        try {
+          _debugger.downFrame(1);
+        } on RangeError catch (_) {
+          // Ignore.
+        }
+        _busy = false;
+        break;
+
+      case KeyCode.F7:
+        e.preventDefault();
+        _debugger.resume().whenComplete(() {
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.F8:
+        e.preventDefault();
+        _debugger.toggleBreakpoint().whenComplete(() {
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.F9:
+        e.preventDefault();
+        _debugger.smartNext().whenComplete(() {
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.F10:
+        e.preventDefault();
+        _debugger.step().whenComplete(() {
+          _busy = false;
+        });
+        break;
+
+      case KeyCode.SEMICOLON:
+        if (e.ctrlKey) {
+          e.preventDefault();
+          _debugger.console.printRed('^;');
+          _debugger.pause().whenComplete(() {
+            _busy = false;
+          });
+        } else {
+          _busy = false;
+        }
+        break;
+
+      default:
+        _busy = false;
+        break;
+    }
+  }
+
+  void enterMode(String prompt, callback) {
+    assert(modalPrompt == null);
+    modalPrompt = prompt;
+    modalCallback = callback;
+  }
+
+  void exitMode() {
+    assert(modalPrompt != null);
+    modalPrompt = null;
+    modalCallback = null;
+  }
+
+  void focus() {
+    _textBox.focus();
+  }
+
+  void render() {
+    // Nothing to do.
+  }
+}
+
+final SvgSvgElement iconExpandLess = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PolygonElement()
+      ..setAttribute('points', '12,8 6,14 7.4,15.4 12,10.8 16.6,15.4 18,14 ')
+  ];
+
+final SvgSvgElement iconExpandMore = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PolygonElement()
+      ..setAttribute('points', '16.6,8.6 12,13.2 7.4,8.6 6,10 12,16 18,10 ')
+  ];
+
+final SvgSvgElement iconChevronRight = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute('d', 'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z')
+  ];
+
+final SvgSvgElement iconChevronLeft = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute('d', 'M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z')
+  ];
+
+final SvgSvgElement iconHorizontalThreeDot = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2z')
+  ];
+
+final SvgSvgElement iconVerticalThreeDot = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 '
+              '2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 '
+              '2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 '
+              '2-.9 2-2-.9-2-2-2z')
+  ];
+
+final SvgSvgElement iconInfo = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 '
+              '10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z')
+  ];
+
+final SvgSvgElement iconInfoOutline = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 '
+              '10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 '
+              '0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 '
+              '9h2V7h-2v2z')
+  ];
diff --git a/runtime/observatory_2/lib/src/elements/error_ref.dart b/runtime/observatory_2/lib/src/elements/error_ref.dart
new file mode 100644
index 0000000..47100de
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/error_ref.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library error_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' show ErrorRef;
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class ErrorRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ErrorRefElement> _r;
+
+  Stream<RenderedEvent<ErrorRefElement>> get onRendered => _r.onRendered;
+
+  ErrorRef _error;
+
+  ErrorRef get error => _error;
+
+  factory ErrorRefElement(ErrorRef error, {RenderingQueue queue}) {
+    assert(error != null);
+    ErrorRefElement e = new ErrorRefElement.created();
+    e._r = new RenderingScheduler<ErrorRefElement>(e, queue: queue);
+    e._error = error;
+    return e;
+  }
+
+  ErrorRefElement.created() : super.created('error-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[new PreElement()..text = error.message];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/error_view.dart b/runtime/observatory_2/lib/src/elements/error_view.dart
new file mode 100644
index 0000000..d4edfb2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/error_view.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library error_view_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ErrorViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ErrorViewElement> _r;
+
+  Stream<RenderedEvent<ErrorViewElement>> get onRendered => _r.onRendered;
+
+  M.Error _error;
+  M.NotificationRepository _notifications;
+
+  M.Error get error => _error;
+
+  factory ErrorViewElement(
+      M.NotificationRepository notifications, M.Error error,
+      {RenderingQueue queue}) {
+    assert(error != null);
+    assert(notifications != null);
+    ErrorViewElement e = new ErrorViewElement.created();
+    e._r = new RenderingScheduler<ErrorViewElement>(e, queue: queue);
+    e._error = error;
+    e._notifications = notifications;
+    return e;
+  }
+
+  ErrorViewElement.created() : super.created('error-view');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()
+            ..text = 'Error: ${_kindToString(_error.kind)}',
+          new BRElement(),
+          new DivElement()
+            ..classes = ['well']
+            ..children = <Element>[new PreElement()..text = error.message]
+        ],
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+
+  static String _kindToString(M.ErrorKind kind) {
+    switch (kind) {
+      case M.ErrorKind.unhandledException:
+        return 'Unhandled Exception';
+      case M.ErrorKind.languageError:
+        return 'Language Error';
+      case M.ErrorKind.internalError:
+        return 'Internal Error';
+      case M.ErrorKind.terminationError:
+        return 'Termination Error';
+    }
+    throw new Exception('Unknown M.ErrorKind ($kind)');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/eval_box.dart b/runtime/observatory_2/lib/src/elements/eval_box.dart
new file mode 100644
index 0000000..771ddf9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/eval_box.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library eval_box_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+
+class EvalBoxElement extends CustomElement implements Renderable {
+  RenderingScheduler<EvalBoxElement> _r;
+
+  Stream<RenderedEvent<EvalBoxElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ObjectRef _context;
+  M.ObjectRepository _objects;
+  M.EvalRepository _eval;
+  final _results = <_ExpressionDescription>[];
+  String _expression = '';
+  bool _multiline;
+  Iterable<String> _quickExpressions;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ObjectRef get context => _context;
+
+  factory EvalBoxElement(M.IsolateRef isolate, M.ObjectRef context,
+      M.ObjectRepository objects, M.EvalRepository eval,
+      {bool multiline: false,
+      Iterable<String> quickExpressions: const [],
+      RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(context != null);
+    assert(objects != null);
+    assert(eval != null);
+    assert(multiline != null);
+    assert(quickExpressions != null);
+    EvalBoxElement e = new EvalBoxElement.created();
+    e._r = new RenderingScheduler<EvalBoxElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._context = context;
+    e._objects = objects;
+    e._eval = eval;
+    e._multiline = multiline;
+    e._quickExpressions = new List.unmodifiable(quickExpressions);
+    return e;
+  }
+
+  EvalBoxElement.created() : super.created('eval-box');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _results.clear();
+  }
+
+  void render() {
+    children = <Element>[
+      new DivElement()
+        ..classes = ['quicks']
+        ..children = _quickExpressions
+            .map<Element>((q) => new ButtonElement()
+              ..text = q
+              ..onClick.listen((_) {
+                _expression = q;
+                _run();
+              }))
+            .toList(),
+      new DivElement()
+        ..classes = ['heading']
+        ..children = <Element>[
+          new FormElement()
+            ..autocomplete = 'on'
+            ..children = <Element>[
+              _multiline ? _createEvalTextArea() : _createEvalTextBox(),
+              new SpanElement()
+                ..classes = ['buttons']
+                ..children = <Element>[
+                  _createEvalButton(),
+                  _createMultilineCheckbox(),
+                  new SpanElement()..text = 'Multi-line'
+                ]
+            ]
+        ],
+      new TableElement()
+        ..children = _results.reversed
+            .map<Element>((result) => new TableRowElement()
+              ..children = <Element>[
+                new TableCellElement()
+                  ..classes = ['historyExpr']
+                  ..children = <Element>[
+                    new ButtonElement()
+                      ..text = result.expression
+                      ..onClick.listen((_) {
+                        _expression = result.expression;
+                        _r.dirty();
+                      })
+                  ],
+                new TableCellElement()
+                  ..classes = ['historyValue']
+                  ..children = <Element>[
+                    result.isPending
+                        ? (new SpanElement()..text = 'Pending...')
+                        : anyRef(_isolate, result.value, _objects,
+                            queue: _r.queue)
+                  ],
+                new TableCellElement()
+                  ..classes = ['historyDelete']
+                  ..children = <Element>[
+                    new ButtonElement()
+                      ..text = '✖ Remove'
+                      ..onClick.listen((_) {
+                        _results.remove(result);
+                        _r.dirty();
+                      })
+                  ]
+              ])
+            .toList()
+    ];
+  }
+
+  TextAreaElement _createEvalTextArea() {
+    var area = new TextAreaElement()
+      ..classes = ['textbox']
+      ..placeholder = 'evaluate an expression'
+      ..value = _expression
+      ..onKeyUp.where((e) => e.key == '\n').listen((e) {
+        e.preventDefault();
+        _run();
+      });
+    area.onInput.listen((e) {
+      _expression = area.value;
+    });
+    return area;
+  }
+
+  TextInputElement _createEvalTextBox() {
+    _expression = (_expression ?? '').split('\n')[0];
+    var textbox = new TextInputElement()
+      ..classes = ['textbox']
+      ..placeholder = 'evaluate an expression'
+      ..value = _expression
+      ..onKeyUp.where((e) => e.key == '\n').listen((e) {
+        e.preventDefault();
+        _run();
+      });
+    textbox.onInput.listen((e) {
+      _expression = textbox.value;
+    });
+    return textbox;
+  }
+
+  ButtonElement _createEvalButton() {
+    final button = new ButtonElement()
+      ..text = 'Evaluate'
+      ..onClick.listen((e) {
+        e.preventDefault();
+        _run();
+      });
+    return button;
+  }
+
+  CheckboxInputElement _createMultilineCheckbox() {
+    final checkbox = new CheckboxInputElement()..checked = _multiline;
+    checkbox.onClick.listen((e) {
+      e.preventDefault();
+      _multiline = checkbox.checked;
+      _r.dirty();
+    });
+    return checkbox;
+  }
+
+  Future _run() async {
+    if (_expression == null || _expression.isEmpty) return;
+    final expression = _expression;
+    _expression = null;
+    final result = new _ExpressionDescription.pending(expression);
+    _results.add(result);
+    _r.dirty();
+    final index = _results.indexOf(result);
+    _results[index] = new _ExpressionDescription(
+        expression, await _eval.evaluate(_isolate, _context, expression));
+    _r.dirty();
+  }
+}
+
+class _ExpressionDescription {
+  final String expression;
+  final M.ObjectRef value;
+  bool get isPending => value == null;
+
+  _ExpressionDescription(this.expression, this.value);
+  _ExpressionDescription.pending(this.expression) : value = null;
+}
diff --git a/runtime/observatory_2/lib/src/elements/field_ref.dart b/runtime/observatory_2/lib/src/elements/field_ref.dart
new file mode 100644
index 0000000..ad75c94
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/field_ref.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+
+class FieldRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<FieldRefElement> _r;
+
+  Stream<RenderedEvent<FieldRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.FieldRef _field;
+  M.ObjectRepository _objects;
+  bool _expandable;
+
+  M.IsolateRef get isolate => _isolate;
+  M.FieldRef get field => _field;
+
+  factory FieldRefElement(
+      M.IsolateRef isolate, M.FieldRef field, M.ObjectRepository objects,
+      {RenderingQueue queue, bool expandable: true}) {
+    assert(isolate != null);
+    assert(field != null);
+    assert(objects != null);
+    FieldRefElement e = new FieldRefElement.created();
+    e._r = new RenderingScheduler<FieldRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._field = field;
+    e._objects = objects;
+    e._expandable = expandable;
+    return e;
+  }
+
+  FieldRefElement.created() : super.created('field-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var header = '';
+    if (_field.isStatic) {
+      if (_field.dartOwner is M.ClassRef) {
+        header += 'static ';
+      } else {
+        header += 'top-level ';
+      }
+    }
+    if (_field.isFinal) {
+      header += 'final ';
+    } else if (_field.isConst) {
+      header += 'const ';
+    } else if (_field.declaredType.name == 'dynamic') {
+      header += 'var ';
+    }
+    if (_field.declaredType.name == 'dynamic') {
+      children = <Element>[
+        new SpanElement()..text = header,
+        new AnchorElement(href: Uris.inspect(_isolate, object: _field))
+          ..text = _field.name
+      ];
+    } else {
+      children = <Element>[
+        new SpanElement()..text = header,
+        new InstanceRefElement(_isolate, _field.declaredType, _objects,
+                queue: _r.queue, expandable: _expandable)
+            .element,
+        new SpanElement()..text = ' ',
+        new AnchorElement(href: Uris.inspect(_isolate, object: _field))
+          ..text = _field.name
+      ];
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/field_view.dart b/runtime/observatory_2/lib/src/elements/field_view.dart
new file mode 100644
index 0000000..5e4979f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/field_view.dart
@@ -0,0 +1,291 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library field_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/library_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/script_inset.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class FieldViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<FieldViewElement> _r;
+
+  Stream<RenderedEvent<FieldViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Field _field;
+  M.LibraryRef _library;
+  M.FieldRepository _fields;
+  M.ClassRepository _classes;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Field get field => _field;
+
+  factory FieldViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Field field,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.FieldRepository fields,
+      M.ClassRepository classes,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(field != null);
+    assert(fields != null);
+    assert(classes != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(scripts != null);
+    assert(objects != null);
+    FieldViewElement e = new FieldViewElement.created();
+    e._r = new RenderingScheduler<FieldViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._field = field;
+    e._fields = fields;
+    e._classes = classes;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._scripts = scripts;
+    e._objects = objects;
+    if (field.dartOwner is M.LibraryRef) {
+      e._library = field.dartOwner;
+    }
+    return e;
+  }
+
+  FieldViewElement.created() : super.created('field-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var header = '';
+    if (_field.isStatic) {
+      if (_field.dartOwner is M.ClassRef) {
+        header += 'static ';
+      } else {
+        header += 'top-level ';
+      }
+    }
+    if (_field.isFinal) {
+      header += 'final ';
+    } else if (_field.isConst) {
+      header += 'const ';
+    }
+    if (_field.declaredType.name == 'dynamic') {
+      header += 'var';
+    } else {
+      header += _field.declaredType.name;
+    }
+    children = <Element>[
+      navBar(_createMenu()),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = '$header ${field.name}',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _field, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = _createMembers(),
+          new HRElement(),
+          new DivElement()
+            ..children = _field.location == null
+                ? const []
+                : [
+                    new ScriptInsetElement(_isolate, _field.location.script,
+                            _scripts, _objects, _events,
+                            startPos: field.location.tokenPos,
+                            endPos: field.location.tokenPos,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  List<Element> _createMenu() {
+    final menu = <Element>[
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
+    ];
+    if (_library != null) {
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
+    } else if (_field.dartOwner is M.ClassRef) {
+      menu.add(
+          new NavClassMenuElement(_isolate, _field.dartOwner, queue: _r.queue)
+              .element);
+    }
+    menu.addAll(<Element>[
+      navMenu(_field.name),
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
+    ]);
+    return menu;
+  }
+
+  List<Element> _createMembers() {
+    final members = <Element>[
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'owner',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              _field.dartOwner == null
+                  ? (new SpanElement()..text = '...')
+                  : anyRef(_isolate, _field.dartOwner, _objects,
+                      queue: _r.queue)
+            ]
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'script',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new SourceLinkElement(_isolate, field.location, _scripts,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]
+    ];
+    if (!_field.isStatic) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..title = 'The types observed for this field at runtime. '
+            'Fields that are observed to have a single type at runtime '
+            'or to never be null may allow for additional optimization.'
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'observed types',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = _createGuard()
+        ]);
+    }
+    if (_field.staticValue != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'static value',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              anyRef(_isolate, _field.staticValue, _objects, queue: _r.queue)
+            ]
+        ]);
+    }
+    return members;
+  }
+
+  List<Element> _createGuard() {
+    final guard = <Element>[];
+    switch (_field.guardClassKind) {
+      case M.GuardClassKind.unknown:
+        guard.add(new SpanElement()..text = 'none');
+        break;
+      case M.GuardClassKind.dynamic:
+        guard.add(new SpanElement()..text = 'various');
+        break;
+      case M.GuardClassKind.single:
+        guard.add(
+            new ClassRefElement(_isolate, _field.guardClass, queue: _r.queue)
+                .element);
+        break;
+    }
+    guard.add(new SpanElement()
+      ..text =
+          _field.guardNullable ? '— null observed' : '— null not observed');
+    return guard;
+  }
+
+  Future _refresh() async {
+    _field = await _fields.get(_isolate, _field.id);
+    if (_field.dartOwner is M.LibraryRef) {
+      _library = _field.dartOwner;
+    } else if (_field.dartOwner is M.ClassRef) {
+      _library = (await _classes.get(_isolate, _field.dartOwner.id)).library;
+    }
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/flag_list.dart b/runtime/observatory_2/lib/src/elements/flag_list.dart
new file mode 100644
index 0000000..5f540fc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/flag_list.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library flag_list_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class FlagListElement extends CustomElement implements Renderable {
+  RenderingScheduler<FlagListElement> _r;
+
+  Stream<RenderedEvent<FlagListElement>> get onRendered => _r.onRendered;
+
+  M.VMRef _vm;
+  M.EventRepository _events;
+  M.FlagsRepository _repository;
+  M.NotificationRepository _notifications;
+  Iterable<M.Flag> _flags;
+
+  M.VMRef get vm => _vm;
+
+  factory FlagListElement(M.VMRef vm, M.EventRepository events,
+      M.FlagsRepository repository, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    assert(repository != null);
+    assert(notifications != null);
+    FlagListElement e = new FlagListElement.created();
+    e._r = new RenderingScheduler<FlagListElement>(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    e._repository = repository;
+    e._notifications = notifications;
+    return e;
+  }
+
+  FlagListElement.created() : super.created('flag-list');
+
+  @override
+  void attached() {
+    super.attached();
+    _refresh();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    final content = <Element>[];
+    if (_flags == null) {
+      content.add(new HeadingElement.h1()..text = 'Loading Flags...');
+    } else {
+      final modified = _flags.where(_isModified);
+      final unmodified = _flags.where(_isUnmodified);
+
+      if (modified.isNotEmpty) {
+        content.add(new HeadingElement.h1()..text = 'Modified Flags');
+        content.add(new BRElement());
+        content.addAll(modified.expand(_renderFlag));
+        content.add(new HRElement());
+      }
+
+      content.add(new HeadingElement.h1()..text = 'Unmodified Flags');
+      content.add(new BRElement());
+
+      if (unmodified.isEmpty) {
+        content.add(new HeadingElement.h2()..text = 'None');
+      } else {
+        content.addAll(unmodified.expand(_renderFlag));
+      }
+    }
+
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        navMenu('flags', link: Uris.flags()),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                try {
+                  await _refresh();
+                } finally {
+                  e.element.disabled = false;
+                }
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = content,
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+
+  Future _refresh() {
+    return _repository.list().then((flags) {
+      _flags = flags;
+      _r.dirty();
+    });
+  }
+
+  static bool _isModified(M.Flag flag) => flag.modified;
+  static bool _isUnmodified(M.Flag flag) => !flag.modified;
+
+  static List<Element> _renderFlag(M.Flag flag) {
+    return [
+      new SpanElement()
+        ..classes = ['comment']
+        ..text = '// ${flag.comment}',
+      new DivElement()
+        ..classes =
+            flag.modified ? ['flag', 'modified'] : ['flag', 'unmodified']
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['name']
+            ..text = flag.name,
+          new SpanElement()..text = '=',
+          new SpanElement()
+            ..classes = ['value']
+            ..text = flag.valueAsString ?? 'NULL'
+        ],
+      new BRElement(),
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/function_ref.dart b/runtime/observatory_2/lib/src/elements/function_ref.dart
new file mode 100644
index 0000000..27c270b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/function_ref.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library function_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show
+        IsolateRef,
+        FunctionRef,
+        isSyntheticFunction,
+        ClassRef,
+        ObjectRef,
+        getFunctionFullName;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class FunctionRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<FunctionRefElement> _r;
+
+  Stream<RenderedEvent<FunctionRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.FunctionRef _function;
+  bool _qualified;
+
+  M.IsolateRef get isolate => _isolate;
+  M.FunctionRef get function => _function;
+  bool get qualified => _qualified;
+
+  factory FunctionRefElement(M.IsolateRef isolate, M.FunctionRef function,
+      {bool qualified: true, RenderingQueue queue}) {
+    assert(function != null);
+    assert(qualified != null);
+    FunctionRefElement e = new FunctionRefElement.created();
+    e._r = new RenderingScheduler<FunctionRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._function = function;
+    e._qualified = qualified;
+    return e;
+  }
+
+  FunctionRefElement.created() : super.created('function-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    title = '';
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    var content = <Element>[
+      new AnchorElement(
+          href: (M.isSyntheticFunction(_function.kind) || (_isolate == null))
+              ? null
+              : Uris.inspect(_isolate, object: _function))
+        ..text = _function.name
+    ];
+    if (qualified) {
+      M.ObjectRef owner = _function.dartOwner;
+      while (owner is M.FunctionRef) {
+        M.FunctionRef function = (owner as M.FunctionRef);
+        content.addAll([
+          new SpanElement()..text = '.',
+          new AnchorElement(
+              href: (M.isSyntheticFunction(function.kind) || (_isolate == null))
+                  ? null
+                  : Uris.inspect(_isolate, object: function))
+            ..text = function.name
+        ]);
+        owner = function.dartOwner;
+      }
+      if (owner is M.ClassRef) {
+        content.addAll([
+          new SpanElement()..text = '.',
+          new ClassRefElement(_isolate, owner, queue: _r.queue).element
+        ]);
+      }
+    }
+    children = content.reversed.toList(growable: false);
+    title = M.getFunctionFullName(_function);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/function_view.dart b/runtime/observatory_2/lib/src/elements/function_view.dart
new file mode 100644
index 0000000..7077bc3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/function_view.dart
@@ -0,0 +1,447 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library function_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/code_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/library_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/source_inset.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class FunctionViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<FunctionViewElement> _r;
+
+  Stream<RenderedEvent<FunctionViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.ServiceFunction _function;
+  M.LibraryRef _library;
+  M.FunctionRepository _functions;
+  M.ClassRepository _classes;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.ServiceFunction get function => _function;
+
+  factory FunctionViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.ServiceFunction function,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.FunctionRepository functions,
+      M.ClassRepository classes,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(function != null);
+    assert(functions != null);
+    assert(classes != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(scripts != null);
+    assert(objects != null);
+    FunctionViewElement e = new FunctionViewElement.created();
+    e._r = new RenderingScheduler<FunctionViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._function = function;
+    e._functions = functions;
+    e._classes = classes;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._scripts = scripts;
+    e._objects = objects;
+    if (function.dartOwner is M.LibraryRef) {
+      e._library = function.dartOwner;
+    }
+    return e;
+  }
+
+  FunctionViewElement.created() : super.created('function-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(_createMenu()),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Function ${_function.name}',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _function, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = _createMembers(),
+          new HRElement(),
+          new DivElement()
+            ..children = _function.location == null
+                ? const []
+                : [
+                    new SourceInsetElement(_isolate, _function.location,
+                            _scripts, _objects, _events,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  List<Element> _createMenu() {
+    final menu = <Element>[
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
+    ];
+    if (_library != null) {
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
+    } else if (_function.dartOwner is M.ClassRef) {
+      menu.add(new NavClassMenuElement(_isolate, _function.dartOwner,
+              queue: _r.queue)
+          .element);
+    }
+    menu.addAll(<Element>[
+      navMenu(_function.name),
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
+    ]);
+    return menu;
+  }
+
+  List<Element> _createMembers() {
+    final members = <Element>[
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'kind',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new SpanElement()
+                ..text = '${_function.isStatic ? "static " : ""}'
+                    '${_function.isConst ? "const " : ""}'
+                    '${_functionKindToString(_function.kind)}'
+            ]
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'owner',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              _function.dartOwner == null
+                  ? (new SpanElement()..text = '...')
+                  : anyRef(_isolate, _function.dartOwner, _objects,
+                      queue: _r.queue)
+            ]
+        ]
+    ];
+    if (_function.field != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'script',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new FieldRefElement(_isolate, _function.field, _objects,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    members.add(new DivElement()
+      ..classes = ['memberItem']
+      ..children = <Element>[
+        new DivElement()
+          ..classes = ['memberName']
+          ..text = 'script',
+        new DivElement()
+          ..classes = ['memberName']
+          ..children = <Element>[
+            new SourceLinkElement(_isolate, _function.location, _scripts,
+                    queue: _r.queue)
+                .element
+          ]
+      ]);
+    if (_function.code != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'current code',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new CodeRefElement(_isolate, _function.code, queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+    if (_function.unoptimizedCode != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'unoptimized code',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new CodeRefElement(_isolate, _function.unoptimizedCode,
+                      queue: _r.queue)
+                  .element,
+              new SpanElement()
+                ..title = 'This count is used to determine when a function '
+                    'will be optimized.  It is a combination of call '
+                    'counts and other factors.'
+                ..text = ' (usage count: ${function.usageCounter})'
+            ]
+        ]);
+    }
+    if (_function.bytecode != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'bytecode',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new CodeRefElement(_isolate, _function.bytecode, queue: _r.queue)
+                  .element,
+            ]
+        ]);
+    }
+    members.add(new DivElement()
+      ..classes = ['memberItem']
+      ..text = ' ');
+
+    if (_function.icDataArray != null) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'ic data array',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              new InstanceRefElement(_isolate, _function.icDataArray, _objects,
+                      queue: _r.queue)
+                  .element
+            ]
+        ]);
+    }
+
+    members.addAll([
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'deoptimizations',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = '${_function.deoptimizations}'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'optimizable',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.isOptimizable ? 'yes' : 'no'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'inlinable',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.isInlinable ? 'yes' : 'no'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'intrinsic',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.hasIntrinsic ? 'yes' : 'no'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'recognized',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.isRecognized ? 'yes' : 'no'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'native',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.isNative ? 'yes' : 'no'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'vm name',
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = _function.vmName
+        ]
+    ]);
+    return members;
+  }
+
+  Future _refresh() async {
+    _function = await _functions.get(_isolate, _function.id);
+    if (_function.dartOwner is M.LibraryRef) {
+      _library = _function.dartOwner;
+    } else if (_function.dartOwner is M.ClassRef) {
+      _library = (await _classes.get(_isolate, _function.dartOwner.id)).library;
+    }
+    _r.dirty();
+  }
+
+  static String _functionKindToString(M.FunctionKind kind) {
+    switch (kind) {
+      case M.FunctionKind.regular:
+        return 'regular';
+      case M.FunctionKind.closure:
+        return 'closure';
+      case M.FunctionKind.implicitClosure:
+        return 'implicit closure';
+      case M.FunctionKind.getter:
+        return 'getter';
+      case M.FunctionKind.setter:
+        return 'setter';
+      case M.FunctionKind.constructor:
+        return 'constructor';
+      case M.FunctionKind.implicitGetter:
+        return 'implicit getter';
+      case M.FunctionKind.implicitSetter:
+        return 'implicit setter';
+      case M.FunctionKind.implicitStaticGetter:
+        return 'implicit static getter';
+      case M.FunctionKind.fieldInitializer:
+        return 'field initializer';
+      case M.FunctionKind.irregexpFunction:
+        return 'irregexp function';
+      case M.FunctionKind.methodExtractor:
+        return 'method extractor';
+      case M.FunctionKind.noSuchMethodDispatcher:
+        return 'noSuchMethod dispatcher';
+      case M.FunctionKind.invokeFieldDispatcher:
+        return 'invokeField dispatcher';
+      case M.FunctionKind.collected:
+        return 'collected';
+      case M.FunctionKind.native:
+        return 'native';
+      case M.FunctionKind.ffiTrampoline:
+        return 'ffi trampoline';
+      case M.FunctionKind.stub:
+        return 'stub';
+      case M.FunctionKind.tag:
+        return 'tag';
+      case M.FunctionKind.signatureFunction:
+        return 'signature function';
+      case M.FunctionKind.dynamicInvocationForwarder:
+        return 'dynamic invocation forwarder';
+    }
+    throw new Exception('Unknown Functionkind ($kind)');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/general_error.dart b/runtime/observatory_2/lib/src/elements/general_error.dart
new file mode 100644
index 0000000..9a4f917
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/general_error.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library general_error_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+
+class GeneralErrorElement extends CustomElement implements Renderable {
+  RenderingScheduler<GeneralErrorElement> _r;
+
+  Stream<RenderedEvent<GeneralErrorElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _notifications;
+  String _message;
+
+  String get message => _message;
+
+  set message(String value) => _message = _r.checkAndReact(_message, value);
+
+  factory GeneralErrorElement(M.NotificationRepository notifications,
+      {String message: '', RenderingQueue queue}) {
+    assert(notifications != null);
+    assert(message != null);
+    GeneralErrorElement e = new GeneralErrorElement.created();
+    e._r = new RenderingScheduler<GeneralErrorElement>(e, queue: queue);
+    e._message = message;
+    e._notifications = notifications;
+    return e;
+  }
+
+  GeneralErrorElement.created() : super.created('general-error');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()..text = 'Error',
+          new BRElement(),
+          new DivElement()
+            ..classes = ['well']
+            ..text = message
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/heap_map.dart b/runtime/observatory_2/lib/src/elements/heap_map.dart
new file mode 100644
index 0000000..71aa6ca
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/heap_map.dart
@@ -0,0 +1,317 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library heap_map_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+
+class HeapMapElement extends CustomElement implements Renderable {
+  RenderingScheduler<HeapMapElement> _r;
+
+  Stream<RenderedEvent<HeapMapElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory HeapMapElement(M.VM vm, M.IsolateRef isolate,
+      M.EventRepository events, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    HeapMapElement e = new HeapMapElement.created();
+    e._r = new RenderingScheduler<HeapMapElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    return e;
+  }
+
+  HeapMapElement.created() : super.created('heap-map');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  CanvasElement _canvas;
+  var _fragmentationData;
+  double _pageHeight;
+  final _classIdToColor = {};
+  final _colorToClassId = {};
+  final _classIdToName = {};
+
+  static final _freeColor = [255, 255, 255, 255];
+  static final _pageSeparationColor = [0, 0, 0, 255];
+  static const _PAGE_SEPARATION_HEIGHT = 4;
+  // Many browsers will not display a very tall canvas.
+  // TODO(koda): Improve interface for huge heaps.
+  static const _MAX_CANVAS_HEIGHT = 6000;
+
+  String _status;
+  S.ServiceMap _fragmentation;
+
+  void render() {
+    if (_canvas == null) {
+      _canvas = new CanvasElement()
+        ..width = 1
+        ..height = 1
+        ..onMouseMove.listen(_handleMouseMove);
+    }
+
+    // Set hover text to describe the object under the cursor.
+    _canvas.title = _status;
+
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('heap map'),
+        (new NavRefreshElement(label: 'Mark-Compact', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "mark-compact")))
+            .element,
+        (new NavRefreshElement(label: 'Mark-Sweep', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "mark-sweep")))
+            .element,
+        (new NavRefreshElement(label: 'Scavenge', queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh(gc: "scavenge")))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        (new NavNotifyElement(_notifications, queue: _r.queue)).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = _status,
+          new HRElement(),
+        ],
+      new DivElement()
+        ..classes = ['flex-row']
+        ..children = <Element>[_canvas]
+    ];
+  }
+
+  // Encode color as single integer, to enable using it as a map key.
+  int _packColor(Iterable<int> color) {
+    int packed = 0;
+    for (var component in color) {
+      packed = packed * 256 + component;
+    }
+    return packed;
+  }
+
+  void _addClass(int classId, String name, Iterable<int> color) {
+    _classIdToName[classId] = name.split('@')[0];
+    _classIdToColor[classId] = color;
+    _colorToClassId[_packColor(color)] = classId;
+  }
+
+  void _updateClassList(classList, int freeClassId) {
+    for (var member in classList['classes']) {
+      if (member is! S.Class) {
+        // TODO(turnidge): The printing for some of these non-class
+        // members is broken.  Fix this:
+        //
+        // Logger.root.info('$member');
+        print('Ignoring non-class in class list');
+        continue;
+      }
+      var classId = int.parse(member.id.split('/').last);
+      var color = _classIdToRGBA(classId);
+      _addClass(classId, member.name, color);
+    }
+    _addClass(freeClassId, 'Free', _freeColor);
+    _addClass(0, '', _pageSeparationColor);
+  }
+
+  Iterable<int> _classIdToRGBA(int classId) {
+    // TODO(koda): Pick random hue, but fixed saturation and value.
+    var rng = new Random(classId);
+    return [rng.nextInt(128), rng.nextInt(128), rng.nextInt(128), 255];
+  }
+
+  String _classNameAt(Point<num> point) {
+    var color = new PixelReference(_fragmentationData, point).color;
+    return _classIdToName[_colorToClassId[_packColor(color)]];
+  }
+
+  ObjectInfo _objectAt(Point<num> point) {
+    if (_fragmentation == null || _canvas == null) {
+      return null;
+    }
+    var pagePixels = _pageHeight * _fragmentationData.width;
+    var index = new PixelReference(_fragmentationData, point).index;
+    var pageIndex = index ~/ pagePixels;
+    num pageOffset = index % pagePixels;
+    var pages = _fragmentation['pages'];
+    if (pageIndex < 0 || pageIndex >= pages.length) {
+      return null;
+    }
+    // Scan the page to find start and size.
+    var page = pages[pageIndex];
+    var objects = page['objects'];
+    var offset = 0;
+    var size = 0;
+    for (var i = 0; i < objects.length; i += 2) {
+      size = objects[i];
+      offset += size;
+      if (offset > pageOffset) {
+        pageOffset = offset - size;
+        break;
+      }
+    }
+    return new ObjectInfo(
+        int.parse(page['objectStart']) +
+            pageOffset * _fragmentation['unitSizeBytes'],
+        size * _fragmentation['unitSizeBytes']);
+  }
+
+  void _handleMouseMove(MouseEvent event) {
+    var info = _objectAt(event.offset);
+    if (info == null) {
+      _status = '';
+      _r.dirty();
+      return;
+    }
+    var addressString = '${info.size}B @ 0x${info.address.toRadixString(16)}';
+    var className = _classNameAt(event.offset);
+    _status = (className == '') ? '-' : '$className $addressString';
+    _r.dirty();
+  }
+
+  void _updateFragmentationData() {
+    if (_fragmentation == null || _canvas == null) {
+      return;
+    }
+    _updateClassList(
+        _fragmentation['classList'], _fragmentation['freeClassId']);
+    var pages = _fragmentation['pages'];
+    var width = max(_canvas.parent.client.width, 1);
+    _pageHeight = _PAGE_SEPARATION_HEIGHT +
+        _fragmentation['pageSizeBytes'] ~/
+            _fragmentation['unitSizeBytes'] ~/
+            width;
+    var height = min(_pageHeight * pages.length, _MAX_CANVAS_HEIGHT);
+    _fragmentationData = _canvas.context2D.createImageData(width, height);
+    _canvas.width = _fragmentationData.width;
+    _canvas.height = _fragmentationData.height;
+    _renderPages(0);
+  }
+
+  // Renders and draws asynchronously, one page at a time to avoid
+  // blocking the UI.
+  void _renderPages(int startPage) {
+    var pages = _fragmentation['pages'];
+    _status = 'Loaded $startPage of ${pages.length} pages';
+    _r.dirty();
+    var startY = (startPage * _pageHeight).round();
+    var endY = startY + _pageHeight.round();
+    if (startPage >= pages.length || endY > _fragmentationData.height) {
+      return;
+    }
+    var pixel = new PixelReference(_fragmentationData, new Point(0, startY));
+    var objects = pages[startPage]['objects'];
+    for (var i = 0; i < objects.length; i += 2) {
+      var count = objects[i];
+      var classId = objects[i + 1];
+      var color = _classIdToColor[classId];
+      while (count-- > 0) {
+        pixel.color = color;
+        pixel = pixel.next();
+      }
+    }
+    while (pixel.point.y < endY) {
+      pixel.color = _pageSeparationColor;
+      pixel = pixel.next();
+    }
+    _canvas.context2D.putImageData(
+        _fragmentationData, 0, 0, 0, startY, _fragmentationData.width, endY);
+    // Continue with the next page, asynchronously.
+    new Future(() {
+      _renderPages(startPage + 1);
+    });
+  }
+
+  Future _refresh({String gc}) {
+    final isolate = _isolate as S.Isolate;
+    var params = {};
+    if (gc != null) {
+      params['gc'] = gc;
+    }
+    return isolate.invokeRpc('_getHeapMap', params).then((serviceObject) {
+      S.ServiceMap response = serviceObject;
+      assert(response['type'] == 'HeapMap');
+      _fragmentation = response;
+      _updateFragmentationData();
+    });
+  }
+}
+
+// A reference to a particular pixel of ImageData.
+class PixelReference {
+  final _data;
+  var _dataIndex;
+  static const NUM_COLOR_COMPONENTS = 4;
+
+  PixelReference(ImageData data, Point<num> point)
+      : _data = data,
+        _dataIndex = (point.y * data.width + point.x) * NUM_COLOR_COMPONENTS;
+
+  PixelReference._fromDataIndex(this._data, this._dataIndex);
+
+  Point<num> get point => new Point(index % _data.width, index ~/ _data.width);
+
+  void set color(Iterable<int> color) {
+    _data.data.setRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS, color);
+  }
+
+  Iterable<int> get color =>
+      _data.data.getRange(_dataIndex, _dataIndex + NUM_COLOR_COMPONENTS);
+
+  // Returns the next pixel in row-major order.
+  PixelReference next() => new PixelReference._fromDataIndex(
+      _data, _dataIndex + NUM_COLOR_COMPONENTS);
+
+  // The row-major index of this pixel.
+  int get index => _dataIndex ~/ NUM_COLOR_COMPONENTS;
+}
+
+class ObjectInfo {
+  final address;
+  final size;
+  ObjectInfo(this.address, this.size);
+}
diff --git a/runtime/observatory_2/lib/src/elements/heap_snapshot.dart b/runtime/observatory_2/lib/src/elements/heap_snapshot.dart
new file mode 100644
index 0000000..bfe8412
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/heap_snapshot.dart
@@ -0,0 +1,1529 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:math' as Math;
+import 'dart:typed_data';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/object_graph.dart';
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/tree_map.dart';
+import 'package:observatory_2/repositories.dart';
+import 'package:observatory_2/utils.dart';
+
+enum HeapSnapshotTreeMode {
+  classesTable,
+  classesTableDiff,
+  classesTreeMap,
+  classesTreeMapDiff,
+  dominatorTree,
+  dominatorTreeMap,
+  mergedDominatorTree,
+  mergedDominatorTreeDiff,
+  mergedDominatorTreeMap,
+  mergedDominatorTreeMapDiff,
+  ownershipTable,
+  ownershipTableDiff,
+  ownershipTreeMap,
+  ownershipTreeMapDiff,
+  predecessors,
+  successors,
+}
+
+// Note the order of these lists is reflected in the UI, and the first option
+// is the default.
+const viewModes = [
+  HeapSnapshotTreeMode.mergedDominatorTreeMap,
+  HeapSnapshotTreeMode.mergedDominatorTree,
+  HeapSnapshotTreeMode.dominatorTreeMap,
+  HeapSnapshotTreeMode.dominatorTree,
+  HeapSnapshotTreeMode.ownershipTreeMap,
+  HeapSnapshotTreeMode.ownershipTable,
+  HeapSnapshotTreeMode.classesTreeMap,
+  HeapSnapshotTreeMode.classesTable,
+  HeapSnapshotTreeMode.successors,
+  HeapSnapshotTreeMode.predecessors,
+];
+
+const diffModes = [
+  HeapSnapshotTreeMode.mergedDominatorTreeMapDiff,
+  HeapSnapshotTreeMode.mergedDominatorTreeDiff,
+  HeapSnapshotTreeMode.ownershipTreeMapDiff,
+  HeapSnapshotTreeMode.ownershipTableDiff,
+  HeapSnapshotTreeMode.classesTreeMapDiff,
+  HeapSnapshotTreeMode.classesTableDiff,
+];
+
+abstract class DiffTreeMap<T> extends TreeMap<T> {
+  int getSizeA(T node);
+  int getSizeB(T node);
+
+  // We need to sum gains and losses separately because they both contribute
+  // area to the tree map tiles, i.e., losses don't have negative area in the
+  // visualization. For this reason, common is not necessarily
+  // max(sizeA,sizeB)-min(sizeA,sizeB), gain is not necessarily
+  // abs(sizeB-sizeA), etc.
+  int getGain(T node);
+  int getLoss(T node);
+  int getCommon(T node);
+
+  String getName(T node);
+  String getType(T node);
+
+  int getArea(T node) => getCommon(node) + getGain(node) + getLoss(node);
+  String getLabel(T node) {
+    var name = getName(node);
+    var sizeA = Utils.formatSize(getSizeA(node));
+    var sizeB = Utils.formatSize(getSizeB(node));
+    return "$name [$sizeA → $sizeB]";
+  }
+
+  String getBackground(T node) {
+    int l = getLoss(node);
+    int c = getCommon(node);
+    int g = getGain(node);
+    int a = l + c + g;
+    if (a == 0) {
+      return "white";
+    }
+    // Stripes of green, white and red whose areas are poritional to loss, common and gain.
+    String stop1 = (l / a * 100).toString();
+    String stop2 = ((l + c) / a * 100).toString();
+    return "linear-gradient(to right, #66FF99 $stop1%, white $stop1% $stop2%, #FF6680 $stop2%)";
+  }
+}
+
+class DominatorTreeMap extends NormalTreeMap<SnapshotObject> {
+  HeapSnapshotElement element;
+  DominatorTreeMap(this.element);
+
+  int getSize(SnapshotObject node) => node.retainedSize;
+  String getType(SnapshotObject node) => node.klass.name;
+  String getName(SnapshotObject node) => node.description;
+  SnapshotObject getParent(SnapshotObject node) => node.parent;
+  Iterable<SnapshotObject> getChildren(SnapshotObject node) => node.children;
+  void onSelect(SnapshotObject node) {
+    element.selection = List.from(node.objects);
+    element._r.dirty();
+  }
+
+  void onDetails(SnapshotObject node) {
+    element.selection = List.from(node.objects);
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+class MergedDominatorTreeMap extends NormalTreeMap<SnapshotMergedDominator> {
+  HeapSnapshotElement element;
+  MergedDominatorTreeMap(this.element);
+
+  int getSize(SnapshotMergedDominator node) => node.retainedSize;
+  String getType(SnapshotMergedDominator node) => node.klass.name;
+  String getName(SnapshotMergedDominator node) => node.description;
+  SnapshotMergedDominator getParent(SnapshotMergedDominator node) =>
+      node.parent;
+  Iterable<SnapshotMergedDominator> getChildren(SnapshotMergedDominator node) =>
+      node.children;
+  void onSelect(SnapshotMergedDominator node) {
+    element.mergedSelection = node;
+    element._r.dirty();
+  }
+
+  void onDetails(SnapshotMergedDominator node) {
+    element.selection = List.from(node.objects);
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+class MergedDominatorDiffTreeMap extends DiffTreeMap<MergedDominatorDiff> {
+  HeapSnapshotElement element;
+  MergedDominatorDiffTreeMap(this.element);
+
+  int getSizeA(MergedDominatorDiff node) => node.retainedSizeA;
+  int getSizeB(MergedDominatorDiff node) => node.retainedSizeB;
+  int getGain(MergedDominatorDiff node) => node.retainedGain;
+  int getLoss(MergedDominatorDiff node) => node.retainedLoss;
+  int getCommon(MergedDominatorDiff node) => node.retainedCommon;
+
+  String getType(MergedDominatorDiff node) => node.name;
+  String getName(MergedDominatorDiff node) => "instances of ${node.name}";
+  MergedDominatorDiff getParent(MergedDominatorDiff node) => node.parent;
+  Iterable<MergedDominatorDiff> getChildren(MergedDominatorDiff node) =>
+      node.children;
+  void onSelect(MergedDominatorDiff node) {
+    element.mergedDiffSelection = node;
+    element._r.dirty();
+  }
+
+  void onDetails(MergedDominatorDiff node) {
+    element._snapshotA = element._snapshotB;
+    element.selection = node.objectsB;
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+// Using `null` to represent the root.
+class ClassesShallowTreeMap extends NormalTreeMap<SnapshotClass> {
+  HeapSnapshotElement element;
+  SnapshotGraph snapshot;
+
+  ClassesShallowTreeMap(this.element, this.snapshot);
+
+  int getSize(SnapshotClass node) =>
+      node == null ? snapshot.size : node.shallowSize;
+  String getType(SnapshotClass node) => node == null ? "Classes" : node.name;
+  String getName(SnapshotClass node) => node == null
+      ? "${snapshot.classes.length} classes"
+      : "${node.instanceCount} instances of ${node.name}";
+
+  SnapshotClass getParent(SnapshotClass node) => null;
+  Iterable<SnapshotClass> getChildren(SnapshotClass node) =>
+      node == null ? snapshot.classes : <SnapshotClass>[];
+  void onSelect(SnapshotClass node) {}
+  void onDetails(SnapshotClass node) {
+    element.selection = List.from(node.instances);
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+// Using `null` to represent the root.
+class ClassesShallowDiffTreeMap extends DiffTreeMap<SnapshotClassDiff> {
+  HeapSnapshotElement element;
+  List<SnapshotClassDiff> classes;
+
+  ClassesShallowDiffTreeMap(this.element, this.classes);
+
+  int getSizeA(SnapshotClassDiff node) {
+    if (node != null) return node.shallowSizeA;
+    int s = 0;
+    for (var cls in classes) s += cls.shallowSizeA;
+    return s;
+  }
+
+  int getSizeB(SnapshotClassDiff node) {
+    if (node != null) return node.shallowSizeB;
+    int s = 0;
+    for (var cls in classes) s += cls.shallowSizeB;
+    return s;
+  }
+
+  int getGain(SnapshotClassDiff node) {
+    if (node != null) return node.shallowSizeGain;
+    int s = 0;
+    for (var cls in classes) s += cls.shallowSizeGain;
+    return s;
+  }
+
+  int getLoss(SnapshotClassDiff node) {
+    if (node != null) return node.shallowSizeLoss;
+    int s = 0;
+    for (var cls in classes) s += cls.shallowSizeLoss;
+    return s;
+  }
+
+  int getCommon(SnapshotClassDiff node) {
+    if (node != null) return node.shallowSizeCommon;
+    int s = 0;
+    for (var cls in classes) s += cls.shallowSizeCommon;
+    return s;
+  }
+
+  String getType(SnapshotClassDiff node) =>
+      node == null ? "Classes" : node.name;
+  String getName(SnapshotClassDiff node) =>
+      node == null ? "${classes.length} classes" : "instances of ${node.name}";
+  SnapshotClassDiff getParent(SnapshotClassDiff node) => null;
+  Iterable<SnapshotClassDiff> getChildren(SnapshotClassDiff node) =>
+      node == null ? classes : <SnapshotClassDiff>[];
+  void onSelect(SnapshotClassDiff node) {}
+  void onDetails(SnapshotClassDiff node) {
+    element._snapshotA = element._snapshotB;
+    element.selection = node.objectsB;
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+// Using `null` to represent the root.
+class ClassesOwnershipTreeMap extends NormalTreeMap<SnapshotClass> {
+  HeapSnapshotElement element;
+  SnapshotGraph snapshot;
+
+  ClassesOwnershipTreeMap(this.element, this.snapshot);
+
+  int getSize(SnapshotClass node) =>
+      node == null ? snapshot.size : node.ownedSize;
+  String getType(SnapshotClass node) => node == null ? "classes" : node.name;
+  String getName(SnapshotClass node) => node == null
+      ? "${snapshot.classes.length} Classes"
+      : "${node.instanceCount} instances of ${node.name}";
+  SnapshotClass getParent(SnapshotClass node) => null;
+  Iterable<SnapshotClass> getChildren(SnapshotClass node) =>
+      node == null ? snapshot.classes : <SnapshotClass>[];
+  void onSelect(SnapshotClass node) {}
+  void onDetails(SnapshotClass node) {
+    element.selection = List.from(node.instances);
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+// Using `null` to represent the root.
+class ClassesOwnershipDiffTreeMap extends DiffTreeMap<SnapshotClassDiff> {
+  HeapSnapshotElement element;
+  List<SnapshotClassDiff> classes;
+
+  ClassesOwnershipDiffTreeMap(this.element, this.classes);
+
+  int getSizeA(SnapshotClassDiff node) {
+    if (node != null) return node.ownedSizeA;
+    int s = 0;
+    for (var cls in classes) s += cls.ownedSizeA;
+    return s;
+  }
+
+  int getSizeB(SnapshotClassDiff node) {
+    if (node != null) return node.ownedSizeB;
+    int s = 0;
+    for (var cls in classes) s += cls.ownedSizeB;
+    return s;
+  }
+
+  int getGain(SnapshotClassDiff node) {
+    if (node != null) return node.ownedSizeGain;
+    int s = 0;
+    for (var cls in classes) s += cls.ownedSizeGain;
+    return s;
+  }
+
+  int getLoss(SnapshotClassDiff node) {
+    if (node != null) return node.ownedSizeLoss;
+    int s = 0;
+    for (var cls in classes) s += cls.ownedSizeLoss;
+    return s;
+  }
+
+  int getCommon(SnapshotClassDiff node) {
+    if (node != null) return node.ownedSizeCommon;
+    int s = 0;
+    for (var cls in classes) s += cls.ownedSizeCommon;
+    return s;
+  }
+
+  String getType(SnapshotClassDiff node) =>
+      node == null ? "Classes" : node.name;
+  String getName(SnapshotClassDiff node) =>
+      node == null ? "${classes.length} classes" : "instances of ${node.name}";
+  SnapshotClassDiff getParent(SnapshotClassDiff node) => null;
+  Iterable<SnapshotClassDiff> getChildren(SnapshotClassDiff node) =>
+      node == null ? classes : <SnapshotClassDiff>[];
+  void onSelect(SnapshotClassDiff node) {}
+  void onDetails(SnapshotClassDiff node) {
+    element._snapshotA = element._snapshotB;
+    element.selection = node.objectsB;
+    element._mode = HeapSnapshotTreeMode.successors;
+    element._r.dirty();
+  }
+}
+
+class SnapshotClassDiff {
+  SnapshotClass _a;
+  SnapshotClass _b;
+
+  int get shallowSizeA => _a == null ? 0 : _a.shallowSize;
+  int get ownedSizeA => _a == null ? 0 : _a.ownedSize;
+  int get instanceCountA => _a == null ? 0 : _a.instanceCount;
+
+  int get shallowSizeB => _b == null ? 0 : _b.shallowSize;
+  int get ownedSizeB => _b == null ? 0 : _b.ownedSize;
+  int get instanceCountB => _b == null ? 0 : _b.instanceCount;
+
+  int get shallowSizeDiff => shallowSizeB - shallowSizeA;
+  int get ownedSizeDiff => ownedSizeB - ownedSizeA;
+  int get instanceCountDiff => instanceCountB - instanceCountA;
+
+  int get shallowSizeGain =>
+      shallowSizeB > shallowSizeA ? shallowSizeB - shallowSizeA : 0;
+  int get ownedSizeGain =>
+      ownedSizeB > ownedSizeA ? ownedSizeB - ownedSizeA : 0;
+  int get shallowSizeLoss =>
+      shallowSizeA > shallowSizeB ? shallowSizeA - shallowSizeB : 0;
+  int get ownedSizeLoss =>
+      ownedSizeA > ownedSizeB ? ownedSizeA - ownedSizeB : 0;
+  int get shallowSizeCommon =>
+      shallowSizeB > shallowSizeA ? shallowSizeA : shallowSizeB;
+  int get ownedSizeCommon => ownedSizeB > ownedSizeA ? ownedSizeA : ownedSizeB;
+
+  String get name => _a == null ? _b.name : _a.name;
+
+  List<SnapshotObject> get objectsA =>
+      _a == null ? <SnapshotObject>[] : _a.instances.toList();
+  List<SnapshotObject> get objectsB =>
+      _b == null ? <SnapshotObject>[] : _b.instances.toList();
+
+  static List<SnapshotClassDiff> from(
+      SnapshotGraph graphA, SnapshotGraph graphB) {
+    // Matching classes by SnapshotClass.qualifiedName.
+    var classesB = new Map<String, SnapshotClass>();
+    var classesDiff = <SnapshotClassDiff>[];
+    for (var classB in graphB.classes) {
+      classesB[classB.qualifiedName] = classB;
+    }
+    for (var classA in graphA.classes) {
+      var classDiff = new SnapshotClassDiff();
+      var qualifiedName = classA.qualifiedName;
+      var name = classA.name;
+      classDiff._a = classA;
+      var classB = classesB[qualifiedName];
+      if (classB != null) {
+        classesB.remove(qualifiedName);
+        classDiff._b = classB;
+      }
+      classesDiff.add(classDiff);
+    }
+    for (var classB in classesB.values) {
+      var classDiff = new SnapshotClassDiff();
+      classDiff._b = classB;
+      classesDiff.add(classDiff);
+    }
+    return classesDiff;
+  }
+}
+
+class MergedDominatorDiff {
+  SnapshotMergedDominator _a;
+  SnapshotMergedDominator _b;
+  MergedDominatorDiff parent;
+  List<MergedDominatorDiff> children;
+  int retainedGain = -1;
+  int retainedLoss = -1;
+  int retainedCommon = -1;
+
+  int get shallowSizeA => _a == null ? 0 : _a.shallowSize;
+  int get retainedSizeA => _a == null ? 0 : _a.retainedSize;
+  int get instanceCountA => _a == null ? 0 : _a.instanceCount;
+
+  int get shallowSizeB => _b == null ? 0 : _b.shallowSize;
+  int get retainedSizeB => _b == null ? 0 : _b.retainedSize;
+  int get instanceCountB => _b == null ? 0 : _b.instanceCount;
+
+  int get shallowSizeDiff => shallowSizeB - shallowSizeA;
+  int get retainedSizeDiff => retainedSizeB - retainedSizeA;
+  int get instanceCountDiff => instanceCountB - instanceCountA;
+
+  String get name => _a == null ? _b.klass.name : _a.klass.name;
+
+  List<SnapshotObject> get objectsA =>
+      _a == null ? <SnapshotObject>[] : _a.objects.toList();
+  List<SnapshotObject> get objectsB =>
+      _b == null ? <SnapshotObject>[] : _b.objects.toList();
+
+  static MergedDominatorDiff from(
+      SnapshotMergedDominator a, SnapshotMergedDominator b) {
+    var root = new MergedDominatorDiff();
+    root._a = a;
+    root._b = b;
+
+    // We must use an explicit stack instead of the call stack because the
+    // dominator tree can be arbitrarily deep. We need to compute the full
+    // tree to compute areas, so we do this eagerly to avoid having to
+    // repeatedly test for initialization.
+    var worklist = <MergedDominatorDiff>[];
+    worklist.add(root);
+    // Compute children top-down.
+    for (var i = 0; i < worklist.length; i++) {
+      worklist[i]._computeChildren(worklist);
+    }
+    // Compute area botton-up.
+    for (var i = worklist.length - 1; i >= 0; i--) {
+      worklist[i]._computeArea();
+    }
+
+    return root;
+  }
+
+  void _computeChildren(List<MergedDominatorDiff> worklist) {
+    assert(children == null);
+    children = <MergedDominatorDiff>[];
+
+    // Matching children by MergedObjectVertex.klass.qualifiedName.
+    final childrenB = <String, SnapshotMergedDominator>{};
+    if (_b != null)
+      for (var childB in _b.children) {
+        childrenB[childB.klass.qualifiedName] = childB;
+      }
+    if (_a != null)
+      for (var childA in _a.children) {
+        var childDiff = new MergedDominatorDiff();
+        childDiff.parent = this;
+        childDiff._a = childA;
+        var qualifiedName = childA.klass.qualifiedName;
+        var childB = childrenB[qualifiedName];
+        if (childB != null) {
+          childrenB.remove(qualifiedName);
+          childDiff._b = childB;
+        }
+        children.add(childDiff);
+        worklist.add(childDiff);
+      }
+    for (var childB in childrenB.values) {
+      var childDiff = new MergedDominatorDiff();
+      childDiff.parent = this;
+      childDiff._b = childB;
+      children.add(childDiff);
+      worklist.add(childDiff);
+    }
+
+    if (children.length == 0) {
+      // Compress.
+      children = const <MergedDominatorDiff>[];
+    }
+  }
+
+  void _computeArea() {
+    int g = 0;
+    int l = 0;
+    int c = 0;
+    for (var child in children) {
+      g += child.retainedGain;
+      l += child.retainedLoss;
+      c += child.retainedCommon;
+    }
+    int d = shallowSizeDiff;
+    if (d > 0) {
+      g += d;
+      c += shallowSizeA;
+    } else {
+      l -= d;
+      c += shallowSizeB;
+    }
+    assert(retainedSizeA + g - l == retainedSizeB);
+    retainedGain = g;
+    retainedLoss = l;
+    retainedCommon = c;
+  }
+}
+
+class HeapSnapshotElement extends CustomElement implements Renderable {
+  RenderingScheduler<HeapSnapshotElement> _r;
+
+  Stream<RenderedEvent<HeapSnapshotElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.HeapSnapshotRepository _snapshots;
+  M.ObjectRepository _objects;
+  SnapshotReader _reader;
+  String _status;
+  List<SnapshotGraph> _loadedSnapshots = <SnapshotGraph>[];
+  SnapshotGraph _snapshotA;
+  SnapshotGraph _snapshotB;
+  HeapSnapshotTreeMode _mode = HeapSnapshotTreeMode.mergedDominatorTreeMap;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.HeapSnapshotRepository get profiles => _snapshots;
+  M.VMRef get vm => _vm;
+
+  List<SnapshotObject> selection;
+  SnapshotMergedDominator mergedSelection;
+  MergedDominatorDiff mergedDiffSelection;
+
+  factory HeapSnapshotElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.HeapSnapshotRepository snapshots,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(snapshots != null);
+    assert(objects != null);
+    HeapSnapshotElement e = new HeapSnapshotElement.created();
+    e._r = new RenderingScheduler<HeapSnapshotElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._snapshots = snapshots;
+    e._objects = objects;
+    return e;
+  }
+
+  HeapSnapshotElement.created() : super.created('heap-snapshot');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('heap snapshot'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..disabled = _reader != null
+              ..onRefresh.listen((e) {
+                _refresh();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'save', queue: _r.queue)
+              ..disabled = _reader != null
+              ..onRefresh.listen((e) {
+                _save();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'load', queue: _r.queue)
+              ..disabled = _reader != null
+              ..onRefresh.listen((e) {
+                _load();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+    ];
+    if (_reader != null) {
+      // Loading
+      content.addAll(_createStatusMessage('Loading snapshot...',
+          description: _status, progress: 1));
+    } else if (_snapshotA != null) {
+      // Loaded
+      content.addAll(_createReport());
+    }
+    children = content;
+  }
+
+  _refresh() {
+    _reader = null;
+    _snapshotLoading(_snapshots.get(isolate));
+  }
+
+  _save() {
+    var blob = new Blob(_snapshotA.chunks, 'application/octet-stream');
+    var blobUrl = Url.createObjectUrl(blob);
+    var link = new AnchorElement();
+    link.href = blobUrl;
+    var now = new DateTime.now();
+    link.download = 'dart-heap-${now.year}-${now.month}-${now.day}.bin';
+    link.click();
+  }
+
+  _load() {
+    var input = new InputElement();
+    input.type = 'file';
+    input.multiple = false;
+    input.onChange.listen((event) {
+      var file = input.files[0];
+      var reader = new FileReader();
+      reader.onLoad.listen((event) async {
+        var encoded = <Uint8List>[reader.result];
+        var snapshotReader = new SnapshotReader();
+        _snapshotLoading(snapshotReader);
+        snapshotReader.add(reader.result);
+        snapshotReader.close();
+      });
+      reader.readAsArrayBuffer(file);
+    });
+    input.click();
+  }
+
+  _snapshotLoading(SnapshotReader reader) async {
+    _status = '';
+    _reader = reader;
+    reader.onProgress.listen((String status) {
+      _status = status;
+      _r.dirty();
+    });
+    _snapshotLoaded(await reader.done);
+  }
+
+  _snapshotLoaded(SnapshotGraph snapshot) {
+    _reader = null;
+    _loadedSnapshots.add(snapshot);
+    _snapshotA = snapshot;
+    _snapshotB = snapshot;
+    selection = null;
+    mergedSelection = null;
+    mergedDiffSelection = null;
+    _r.dirty();
+  }
+
+  static List<Element> _createStatusMessage(String message,
+      {String description: '', double progress: 0.0}) {
+    return [
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['statusBox', 'shadow', 'center']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['statusMessage']
+                ..text = message,
+              new DivElement()
+                ..classes = ['statusDescription']
+                ..text = description,
+              new DivElement()
+                ..style.background = '#0489c3'
+                ..style.width = '$progress%'
+                ..style.height = '15px'
+                ..style.borderRadius = '4px'
+            ]
+        ]
+    ];
+  }
+
+  VirtualTreeElement _tree;
+
+  void _createTreeMap<T>(List<HtmlElement> report, TreeMap<T> treemap, T root) {
+    final content = new DivElement();
+    content.style.border = '1px solid black';
+    content.style.width = '100%';
+    content.style.height = '100%';
+    content.text = 'Performing layout...';
+    Timer.run(() {
+      // Generate the treemap after the content div has been added to the
+      // document so that we can ask the browser how much space is
+      // available for treemap layout.
+      treemap.showIn(root, content);
+    });
+
+    final text =
+        'Double-click a tile to zoom in. Double-click the outermost tile to zoom out. Right-click a tile to inspect its objects.';
+    report.addAll([
+      new DivElement()
+        ..classes = ['content-centered-big', 'explanation']
+        ..text = text,
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..style.width = '100%'
+        ..style.height = '100%'
+        ..children = [content]
+    ]);
+  }
+
+  List<Element> _createReport() {
+    var report = <HtmlElement>[
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Snapshot A',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = _createSnapshotSelectA()
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Snapshot B',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = _createSnapshotSelectB()
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = (_snapshotA == _snapshotB) ? 'View ' : 'Compare ',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = _createModeSelect()
+                ]
+            ]
+        ],
+    ];
+    switch (_mode) {
+      case HeapSnapshotTreeMode.dominatorTree:
+        if (selection == null) {
+          selection = List.from(_snapshotA.extendedRoot.objects);
+        }
+        _tree = new VirtualTreeElement(
+            _createDominator, _updateDominator, _getChildrenDominator,
+            items: selection, queue: _r.queue);
+        if (selection.length == 1) {
+          _tree.expand(selection.first);
+        }
+        final text = 'In a heap dominator tree, an object X is a parent of '
+            'object Y if every path from the root to Y goes through '
+            'X. This allows you to find "choke points" that are '
+            'holding onto a lot of memory. If an object becomes '
+            'garbage, all its children in the dominator tree become '
+            'garbage as well.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.dominatorTreeMap:
+        if (selection == null) {
+          selection = List.from(_snapshotA.extendedRoot.objects);
+        }
+        _createTreeMap(report, new DominatorTreeMap(this), selection.first);
+        break;
+      case HeapSnapshotTreeMode.mergedDominatorTree:
+        _tree = new VirtualTreeElement(_createMergedDominator,
+            _updateMergedDominator, _getChildrenMergedDominator,
+            items: _getChildrenMergedDominator(_snapshotA.extendedMergedRoot),
+            queue: _r.queue);
+        _tree.expand(_snapshotA.extendedMergedRoot);
+        final text = 'A heap dominator tree, where siblings with the same class'
+            ' have been merged into a single node.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.mergedDominatorTreeDiff:
+        var root = MergedDominatorDiff.from(
+            _snapshotA.mergedRoot, _snapshotB.mergedRoot);
+        _tree = new VirtualTreeElement(_createMergedDominatorDiff,
+            _updateMergedDominatorDiff, _getChildrenMergedDominatorDiff,
+            items: _getChildrenMergedDominatorDiff(root), queue: _r.queue);
+        _tree.expand(root);
+        final text = 'A heap dominator tree, where siblings with the same class'
+            ' have been merged into a single node.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.mergedDominatorTreeMap:
+        if (mergedSelection == null) {
+          mergedSelection = _snapshotA.extendedMergedRoot;
+        }
+        _createTreeMap(
+            report, new MergedDominatorTreeMap(this), mergedSelection);
+        break;
+      case HeapSnapshotTreeMode.mergedDominatorTreeMapDiff:
+        if (mergedDiffSelection == null) {
+          mergedDiffSelection = MergedDominatorDiff.from(
+              _snapshotA.mergedRoot, _snapshotB.mergedRoot);
+        }
+        _createTreeMap(
+            report, new MergedDominatorDiffTreeMap(this), mergedDiffSelection);
+        break;
+      case HeapSnapshotTreeMode.ownershipTable:
+        final items = _snapshotA.classes.where((c) => c.ownedSize > 0).toList();
+        items.sort((a, b) => b.ownedSize - a.ownedSize);
+        _tree = new VirtualTreeElement(
+            _createOwnership, _updateOwnership, _getChildrenOwnership,
+            items: items, queue: _r.queue);
+        _tree.expand(_snapshotA.root);
+        final text = 'An object X is said to "own" object Y if X is the only '
+            'object that references Y, or X owns the only object that '
+            'references Y. In particular, objects "own" the space of any '
+            'unshared lists or maps they reference.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.ownershipTableDiff:
+        final items = SnapshotClassDiff.from(_snapshotA, _snapshotB);
+        items.sort((a, b) => b.ownedSizeB - a.ownedSizeB);
+        items.sort((a, b) => b.ownedSizeA - a.ownedSizeA);
+        items.sort((a, b) => b.ownedSizeDiff - a.ownedSizeDiff);
+        _tree = new VirtualTreeElement(_createOwnershipDiff,
+            _updateOwnershipDiff, _getChildrenOwnershipDiff,
+            items: items, queue: _r.queue);
+        _tree.expand(_snapshotA.root);
+        final text = 'An object X is said to "own" object Y if X is the only '
+            'object that references Y, or X owns the only object that '
+            'references Y. In particular, objects "own" the space of any '
+            'unshared lists or maps they reference.';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.ownershipTreeMap:
+        _createTreeMap(
+            report, new ClassesOwnershipTreeMap(this, _snapshotA), null);
+        break;
+      case HeapSnapshotTreeMode.ownershipTreeMapDiff:
+        final items = SnapshotClassDiff.from(_snapshotA, _snapshotB);
+        _createTreeMap(
+            report, new ClassesOwnershipDiffTreeMap(this, items), null);
+        break;
+      case HeapSnapshotTreeMode.successors:
+        if (selection == null) {
+          selection = List.from(_snapshotA.root.objects);
+        }
+        _tree = new VirtualTreeElement(
+            _createSuccessor, _updateSuccessor, _getChildrenSuccessor,
+            items: selection, queue: _r.queue);
+        if (selection.length == 1) {
+          _tree.expand(selection.first);
+        }
+        final text = '';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.predecessors:
+        if (selection == null) {
+          selection = List.from(_snapshotA.root.objects);
+        }
+        _tree = new VirtualTreeElement(
+            _createPredecessor, _updatePredecessor, _getChildrenPredecessor,
+            items: selection, queue: _r.queue);
+        if (selection.length == 1) {
+          _tree.expand(selection.first);
+        }
+        final text = '';
+        report.addAll([
+          new DivElement()
+            ..classes = ['content-centered-big', 'explanation']
+            ..text = text,
+          _tree.element
+        ]);
+        break;
+      case HeapSnapshotTreeMode.classesTable:
+        final items = _snapshotA.classes.toList();
+        items.sort((a, b) => b.shallowSize - a.shallowSize);
+        _tree = new VirtualTreeElement(
+            _createClass, _updateClass, _getChildrenClass,
+            items: items, queue: _r.queue);
+        report.add(_tree.element);
+        break;
+      case HeapSnapshotTreeMode.classesTableDiff:
+        final items = SnapshotClassDiff.from(_snapshotA, _snapshotB);
+        items.sort((a, b) => b.shallowSizeB - a.shallowSizeB);
+        items.sort((a, b) => b.shallowSizeA - a.shallowSizeA);
+        items.sort((a, b) => b.shallowSizeDiff - a.shallowSizeDiff);
+        _tree = new VirtualTreeElement(
+            _createClassDiff, _updateClassDiff, _getChildrenClassDiff,
+            items: items, queue: _r.queue);
+        report.add(_tree.element);
+        break;
+      case HeapSnapshotTreeMode.classesTreeMap:
+        _createTreeMap(
+            report, new ClassesShallowTreeMap(this, _snapshotA), null);
+        break;
+
+      case HeapSnapshotTreeMode.classesTreeMapDiff:
+        final items = SnapshotClassDiff.from(_snapshotA, _snapshotB);
+        _createTreeMap(
+            report, new ClassesShallowDiffTreeMap(this, items), null);
+        break;
+      default:
+        break;
+    }
+    return report;
+  }
+
+  static HtmlElement _createDominator(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap being retained',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()..classes = ['name'],
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[inspect]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[incoming]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[dominator-map]",
+      ];
+  }
+
+  static HtmlElement _createSuccessor(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size',
+        new SpanElement()
+          ..classes = ['edge']
+          ..title = 'name of outgoing field',
+        new SpanElement()..classes = ['name'],
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[incoming]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[dominator-tree]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[dominator-map]",
+      ];
+  }
+
+  static HtmlElement _createPredecessor(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size',
+        new SpanElement()
+          ..classes = ['edge']
+          ..title = 'name of incoming field',
+        new SpanElement()..classes = ['name'],
+        new SpanElement()
+          ..classes = ['link']
+          ..text = "[inspect]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[dominator-tree]",
+        new AnchorElement()
+          ..classes = ['link']
+          ..text = "[dominator-map]",
+      ];
+  }
+
+  static HtmlElement _createMergedDominator(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap being retained',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createMergedDominatorDiff(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap being retained',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size A',
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap being retained',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size B',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'retained size change',
+        new SpanElement()..classes = ['lines'],
+        new ButtonElement()
+          ..classes = ['expander']
+          ..onClick.listen((_) => toggle(autoToggleSingleChildNodes: true)),
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createOwnership(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap owned',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'owned size',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createOwnershipDiff(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap owned A',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'owned size A',
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap owned B',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'owned size B',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'owned size change',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createClass(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['percentage']
+          ..title = 'percentage of heap owned',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'shallow size',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'instance count',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static HtmlElement _createClassDiff(toggle) {
+    return new DivElement()
+      ..classes = ['tree-item']
+      ..children = <Element>[
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'shallow size A',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'instance count A',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'shallow size B',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'instance count B',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'shallow size diff',
+        new SpanElement()
+          ..classes = ['size']
+          ..title = 'instance count diff',
+        new SpanElement()..classes = ['name']
+      ];
+  }
+
+  static const int kMaxChildren = 100;
+  static const int kMinRetainedSize = 4096;
+
+  static Iterable _getChildrenDominator(nodeDynamic) {
+    SnapshotObject node = nodeDynamic;
+    final list = node.children
+        .where((child) => child.retainedSize >= kMinRetainedSize)
+        .toList();
+    list.sort((a, b) => b.retainedSize - a.retainedSize);
+    return list.take(kMaxChildren).toList();
+  }
+
+  static Iterable _getChildrenSuccessor(nodeDynamic) {
+    SnapshotObject node = nodeDynamic;
+    return node.successors.take(kMaxChildren).toList();
+  }
+
+  static Iterable _getChildrenPredecessor(nodeDynamic) {
+    SnapshotObject node = nodeDynamic;
+    return node.predecessors.take(kMaxChildren).toList();
+  }
+
+  static Iterable _getChildrenMergedDominator(nodeDynamic) {
+    SnapshotMergedDominator node = nodeDynamic;
+    final list = node.children
+        .where((child) => child.retainedSize >= kMinRetainedSize)
+        .toList();
+    list.sort((a, b) => b.retainedSize - a.retainedSize);
+    return list.take(kMaxChildren).toList();
+  }
+
+  static Iterable _getChildrenMergedDominatorDiff(nodeDynamic) {
+    MergedDominatorDiff node = nodeDynamic;
+    final list = node.children
+        .where((child) =>
+            child.retainedSizeA >= kMinRetainedSize ||
+            child.retainedSizeB >= kMinRetainedSize)
+        .toList();
+    list.sort((a, b) => b.retainedSizeDiff - a.retainedSizeDiff);
+    return list.take(kMaxChildren).toList();
+  }
+
+  static Iterable _getChildrenOwnership(item) {
+    return const [];
+  }
+
+  static Iterable _getChildrenOwnershipDiff(item) {
+    return const [];
+  }
+
+  static Iterable _getChildrenClass(item) {
+    return const [];
+  }
+
+  static Iterable _getChildrenClassDiff(item) {
+    return const [];
+  }
+
+  void _updateDominator(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotObject node = nodeDynamic;
+    element.children[0].text = Utils.formatPercentNormalized(
+        node.retainedSize * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.retainedSize);
+    _updateLines(element.children[2].children, depth);
+    if (_getChildrenDominator(node).isNotEmpty) {
+      element.children[3].text = _tree.isExpanded(node) ? '▼' : '►';
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4].text = node.description;
+    element.children[5].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.successors;
+      _r.dirty();
+    });
+    element.children[6].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.predecessors;
+      _r.dirty();
+    });
+    element.children[7].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.dominatorTreeMap;
+      _r.dirty();
+    });
+  }
+
+  void _updateSuccessor(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotObject node = nodeDynamic;
+    _updateLines(element.children[0].children, depth);
+    if (_getChildrenSuccessor(node).isNotEmpty) {
+      element.children[1].text = _tree.isExpanded(node) ? '▼' : '►';
+    } else {
+      element.children[1].text = '';
+    }
+    element.children[2].text = Utils.formatSize(node.retainedSize);
+    element.children[3].text = node.label;
+    element.children[4].text = node.description;
+    element.children[5].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.predecessors;
+      _r.dirty();
+    });
+    element.children[6].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.dominatorTree;
+      _r.dirty();
+    });
+    element.children[7].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.dominatorTreeMap;
+      _r.dirty();
+    });
+  }
+
+  void _updatePredecessor(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotObject node = nodeDynamic;
+    _updateLines(element.children[0].children, depth);
+    if (_getChildrenSuccessor(node).isNotEmpty) {
+      element.children[1].text = _tree.isExpanded(node) ? '▼' : '►';
+    } else {
+      element.children[1].text = '';
+    }
+    element.children[2].text = Utils.formatSize(node.retainedSize);
+    element.children[3].text = node.label;
+    element.children[4].text = node.description;
+    element.children[5].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.successors;
+      _r.dirty();
+    });
+    element.children[6].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.dominatorTree;
+      _r.dirty();
+    });
+    element.children[7].onClick.listen((_) {
+      selection = List.from(node.objects);
+      _mode = HeapSnapshotTreeMode.dominatorTreeMap;
+      _r.dirty();
+    });
+  }
+
+  void _updateMergedDominator(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotMergedDominator node = nodeDynamic;
+    element.children[0].text = Utils.formatPercentNormalized(
+        node.retainedSize * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.retainedSize);
+    _updateLines(element.children[2].children, depth);
+    if (_getChildrenMergedDominator(node).isNotEmpty) {
+      element.children[3].text = _tree.isExpanded(node) ? '▼' : '►';
+    } else {
+      element.children[3].text = '';
+    }
+    element.children[4]
+      ..text = '${node.instanceCount} instances of ${node.klass.name}';
+  }
+
+  void _updateMergedDominatorDiff(HtmlElement element, nodeDynamic, int depth) {
+    MergedDominatorDiff node = nodeDynamic;
+    element.children[0].text = Utils.formatPercentNormalized(
+        node.retainedSizeA * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.retainedSizeA);
+    element.children[2].text = Utils.formatPercentNormalized(
+        node.retainedSizeB * 1.0 / _snapshotB.size);
+    element.children[3].text = Utils.formatSize(node.retainedSizeB);
+    element.children[4].text = (node.retainedSizeDiff > 0 ? '+' : '') +
+        Utils.formatSize(node.retainedSizeDiff);
+    element.children[4].style.color =
+        node.retainedSizeDiff > 0 ? "red" : "green";
+    _updateLines(element.children[5].children, depth);
+    if (_getChildrenMergedDominatorDiff(node).isNotEmpty) {
+      element.children[6].text = _tree.isExpanded(node) ? '▼' : '►';
+    } else {
+      element.children[6].text = '';
+    }
+    element.children[7]
+      ..text =
+          '${node.instanceCountA} → ${node.instanceCountB} instances of ${node.name}';
+  }
+
+  void _updateOwnership(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotClass node = nodeDynamic;
+    element.children[0].text =
+        Utils.formatPercentNormalized(node.ownedSize * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.ownedSize);
+    element.children[2].text = node.name;
+  }
+
+  void _updateOwnershipDiff(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotClassDiff node = nodeDynamic;
+    element.children[0].text =
+        Utils.formatPercentNormalized(node.ownedSizeA * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.ownedSizeA);
+    element.children[2].text =
+        Utils.formatPercentNormalized(node.ownedSizeB * 1.0 / _snapshotB.size);
+    element.children[3].text = Utils.formatSize(node.ownedSizeB);
+    element.children[4].text = (node.ownedSizeDiff > 0 ? "+" : "") +
+        Utils.formatSize(node.ownedSizeDiff);
+    element.children[4].style.color = node.ownedSizeDiff > 0 ? "red" : "green";
+    element.children[5].text = node.name;
+  }
+
+  void _updateClass(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotClass node = nodeDynamic;
+    element.children[0].text =
+        Utils.formatPercentNormalized(node.shallowSize * 1.0 / _snapshotA.size);
+    element.children[1].text = Utils.formatSize(node.shallowSize);
+    element.children[2].text = node.instanceCount.toString();
+    element.children[3].text = node.name;
+  }
+
+  void _updateClassDiff(HtmlElement element, nodeDynamic, int depth) {
+    SnapshotClassDiff node = nodeDynamic;
+    element.children[0].text = Utils.formatSize(node.shallowSizeA);
+    element.children[1].text = node.instanceCountA.toString();
+    element.children[2].text = Utils.formatSize(node.shallowSizeB);
+    element.children[3].text = node.instanceCountB.toString();
+    element.children[4].text = (node.shallowSizeDiff > 0 ? "+" : "") +
+        Utils.formatSize(node.shallowSizeDiff);
+    element.children[4].style.color =
+        node.shallowSizeDiff > 0 ? "red" : "green";
+    element.children[5].text = (node.instanceCountDiff > 0 ? "+" : "") +
+        node.instanceCountDiff.toString();
+    element.children[5].style.color =
+        node.instanceCountDiff > 0 ? "red" : "green";
+    element.children[6].text = node.name;
+  }
+
+  static _updateLines(List<Element> lines, int n) {
+    n = Math.max(0, n);
+    while (lines.length > n) {
+      lines.removeLast();
+    }
+    while (lines.length < n) {
+      lines.add(new SpanElement());
+    }
+  }
+
+  static String modeToString(HeapSnapshotTreeMode mode) {
+    switch (mode) {
+      case HeapSnapshotTreeMode.dominatorTree:
+        return 'Dominators (tree)';
+      case HeapSnapshotTreeMode.dominatorTreeMap:
+        return 'Dominators (treemap)';
+      case HeapSnapshotTreeMode.mergedDominatorTree:
+      case HeapSnapshotTreeMode.mergedDominatorTreeDiff:
+        return 'Dominators (tree, siblings merged by class)';
+      case HeapSnapshotTreeMode.mergedDominatorTreeMap:
+      case HeapSnapshotTreeMode.mergedDominatorTreeMapDiff:
+        return 'Dominators (treemap, siblings merged by class)';
+      case HeapSnapshotTreeMode.ownershipTable:
+      case HeapSnapshotTreeMode.ownershipTableDiff:
+        return 'Ownership (table)';
+      case HeapSnapshotTreeMode.ownershipTreeMap:
+      case HeapSnapshotTreeMode.ownershipTreeMapDiff:
+        return 'Ownership (treemap)';
+      case HeapSnapshotTreeMode.classesTable:
+      case HeapSnapshotTreeMode.classesTableDiff:
+        return 'Classes (table)';
+      case HeapSnapshotTreeMode.classesTreeMap:
+      case HeapSnapshotTreeMode.classesTreeMapDiff:
+        return 'Classes (treemap)';
+      case HeapSnapshotTreeMode.successors:
+        return 'Successors / outgoing references';
+      case HeapSnapshotTreeMode.predecessors:
+        return 'Predecessors / incoming references';
+    }
+    throw new Exception('Unknown HeapSnapshotTreeMode: $mode');
+  }
+
+  List<Element> _createModeSelect() {
+    var s;
+    var modes = _snapshotA == _snapshotB ? viewModes : diffModes;
+    if (!modes.contains(_mode)) {
+      _mode = modes[0];
+      _r.dirty();
+    }
+    return [
+      s = new SelectElement()
+        ..classes = ['analysis-select']
+        ..value = modeToString(_mode)
+        ..children = modes.map((mode) {
+          return new OptionElement(
+              value: modeToString(mode), selected: _mode == mode)
+            ..text = modeToString(mode);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _mode = modes[s.selectedIndex];
+          _r.dirty();
+        })
+    ];
+  }
+
+  String snapshotToString(snapshot) {
+    if (snapshot == null) return "None";
+    return snapshot.description +
+        " " +
+        Utils.formatSize(snapshot.capacity + snapshot.externalSize);
+  }
+
+  List<Element> _createSnapshotSelectA() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['analysis-select']
+        ..value = snapshotToString(_snapshotA)
+        ..children = _loadedSnapshots.map((snapshot) {
+          return new OptionElement(
+              value: snapshotToString(snapshot),
+              selected: _snapshotA == snapshot)
+            ..text = snapshotToString(snapshot);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _snapshotA = _loadedSnapshots[s.selectedIndex];
+          selection = null;
+          mergedSelection = null;
+          mergedDiffSelection = null;
+          _r.dirty();
+        })
+    ];
+  }
+
+  List<Element> _createSnapshotSelectB() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['analysis-select']
+        ..value = snapshotToString(_snapshotB)
+        ..children = _loadedSnapshots.map((snapshot) {
+          return new OptionElement(
+              value: snapshotToString(snapshot),
+              selected: _snapshotB == snapshot)
+            ..text = snapshotToString(snapshot);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _snapshotB = _loadedSnapshots[s.selectedIndex];
+          selection = null;
+          mergedSelection = null;
+          mergedDiffSelection = null;
+          _r.dirty();
+        })
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/any_ref.dart b/runtime/observatory_2/lib/src/elements/helpers/any_ref.dart
new file mode 100644
index 0000000..1bcfcea
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/any_ref.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/code_ref.dart';
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/error_ref.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/icdata_ref.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/library_ref.dart';
+import 'package:observatory_2/src/elements/local_var_descriptors_ref.dart';
+import 'package:observatory_2/src/elements/megamorphiccache_ref.dart';
+import 'package:observatory_2/src/elements/objectpool_ref.dart';
+import 'package:observatory_2/src/elements/pc_descriptors_ref.dart';
+import 'package:observatory_2/src/elements/script_ref.dart';
+import 'package:observatory_2/src/elements/sentinel_value.dart';
+import 'package:observatory_2/src/elements/singletargetcache_ref.dart';
+import 'package:observatory_2/src/elements/subtypetestcache_ref.dart';
+import 'package:observatory_2/src/elements/type_arguments_ref.dart';
+import 'package:observatory_2/src/elements/unknown_ref.dart';
+import 'package:observatory_2/src/elements/unlinkedcall_ref.dart';
+
+Element anyRef(M.IsolateRef isolate, ref, M.ObjectRepository objects,
+    {RenderingQueue queue, bool expandable: true}) {
+  if (ref == null) {
+    return new SpanElement()..text = "???";
+  }
+  if (ref is M.Guarded) {
+    if (ref.isSentinel) {
+      return anyRef(isolate, ref.asSentinel, objects,
+          queue: queue, expandable: expandable);
+    } else {
+      return anyRef(isolate, ref.asValue, objects,
+          queue: queue, expandable: expandable);
+    }
+  } else if (ref is M.ObjectRef) {
+    if (ref is M.ClassRef) {
+      return new ClassRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.CodeRef) {
+      return new CodeRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.ContextRef) {
+      return new ContextRefElement(isolate, ref, objects,
+              queue: queue, expandable: expandable)
+          .element;
+    } else if (ref is M.Error) {
+      return new ErrorRefElement(ref, queue: queue).element;
+    } else if (ref is M.FieldRef) {
+      return new FieldRefElement(isolate, ref, objects,
+              queue: queue, expandable: expandable)
+          .element;
+    } else if (ref is M.FunctionRef) {
+      return new FunctionRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.ICDataRef) {
+      return new ICDataRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.InstanceRef) {
+      return new InstanceRefElement(isolate, ref, objects,
+              queue: queue, expandable: expandable)
+          .element;
+    } else if (ref is M.LibraryRef) {
+      return new LibraryRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.LocalVarDescriptorsRef) {
+      return new LocalVarDescriptorsRefElement(isolate, ref, queue: queue)
+          .element;
+    } else if (ref is M.MegamorphicCacheRef) {
+      return new MegamorphicCacheRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.ObjectPoolRef) {
+      return new ObjectPoolRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.PcDescriptorsRef) {
+      return new PcDescriptorsRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.ScriptRef) {
+      return new ScriptRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.SingleTargetCacheRef) {
+      return new SingleTargetCacheRefElement(isolate, ref, queue: queue)
+          .element;
+    } else if (ref is M.SubtypeTestCacheRef) {
+      return new SubtypeTestCacheRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.TypeArgumentsRef) {
+      return new TypeArgumentsRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.UnknownObjectRef) {
+      return new UnknownObjectRefElement(isolate, ref, queue: queue).element;
+    } else if (ref is M.UnlinkedCallRef) {
+      return new UnlinkedCallRefElement(isolate, ref, queue: queue).element;
+    } else {
+      return new AnchorElement(href: Uris.inspect(isolate, object: ref))
+        ..text = 'object';
+    }
+  } else if (ref is M.Sentinel) {
+    return new SentinelValueElement(ref, queue: queue).element;
+  }
+  throw new Exception('Unknown ref type (${ref.runtimeType})');
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/custom_element.dart b/runtime/observatory_2/lib/src/elements/helpers/custom_element.dart
new file mode 100644
index 0000000..2af0d6c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/custom_element.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+
+HtmlElement element(CustomElement e) => e.element;
+
+class CustomElement {
+  static Expando reverseElements = new Expando();
+  static CustomElement reverse(HtmlElement element) => reverseElements[element];
+
+  static List<CustomElement> toBeAttached = <CustomElement>[];
+  static void drainAttached() {
+    // Send 'attached' to elements that have been attached to the document.
+    bool fired = false;
+    var connectedElements = toBeAttached
+        .where((CustomElement element) => element.element.isConnected)
+        .toList();
+    for (CustomElement element in connectedElements) {
+      toBeAttached.remove(element);
+      element.attached();
+      fired = true;
+    }
+
+    if (toBeAttached.isEmpty) {
+      return; // Done.
+    }
+
+    if (fired) {
+      // The 'attached' events above may have scheduled microtasks that will
+      // will add more CustomElements to be document, e.g. 'render'.
+      scheduleMicrotask(() => drainAttached());
+    }
+
+    while (!toBeAttached.isEmpty) {
+      // Either this element will never be attached or it will be attached
+      // after a turn of the outer event loop. Fire 'attached' in case it is
+      // the latter, since firing it out of order is preferrable to not firing
+      // it at all.
+      CustomElement element = toBeAttached.removeLast();
+      print("Warning: created but not in document: $element");
+      element.attached();
+    }
+  }
+
+  final HtmlElement element;
+  CustomElement.created(String elementClass)
+      : element = document.createElement("shadow") {
+    reverseElements[element] = this;
+    element.classes = [elementClass];
+
+    if (toBeAttached.isEmpty) {
+      scheduleMicrotask(() => drainAttached());
+    }
+    toBeAttached.add(this);
+  }
+
+  void attached() {}
+  void detached() {}
+
+  Element get parent => element.parent;
+
+  List<Element> get children => element.children;
+  set children(List<Element> c) => element.children = c;
+
+  CssClassSet get classes => element.classes;
+  set classes(dynamic c) => element.classes = c;
+
+  String get title => element.title;
+  set title(String t) => element.title = t;
+
+  String get text => element.text;
+  set text(String t) => element.text = t;
+
+  CssStyleDeclaration get style => element.style;
+
+  ElementStream<MouseEvent> get onClick => element.onClick;
+
+  Rectangle getBoundingClientRect() => element.getBoundingClientRect();
+
+  List<Node> getElementsByClassName(String c) =>
+      element.getElementsByClassName(c);
+
+  void scrollIntoView() => element.scrollIntoView();
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/nav_bar.dart b/runtime/observatory_2/lib/src/elements/helpers/nav_bar.dart
new file mode 100644
index 0000000..050041b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/nav_bar.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+Element navBar(Iterable<Element> content) {
+  assert(content != null);
+  return document.createElement('nav')
+    ..classes = ['nav-bar']
+    ..children = <Element>[
+      new UListElement()..children = content,
+    ];
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/nav_menu.dart b/runtime/observatory_2/lib/src/elements/helpers/nav_menu.dart
new file mode 100644
index 0000000..02cf8ef
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/nav_menu.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+
+navMenu(String label, {String link, Iterable<Element> content: const []}) {
+  assert(label != null);
+  assert(content != null);
+  return new LIElement()
+    ..classes = ['nav-menu']
+    ..children = <Element>[
+      new SpanElement()
+        ..classes = ['nav-menu_label']
+        ..children = <Element>[
+          new AnchorElement(href: link)..text = label,
+          new UListElement()..children = content
+        ]
+    ];
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/rendering_queue.dart b/runtime/observatory_2/lib/src/elements/helpers/rendering_queue.dart
new file mode 100644
index 0000000..e244619
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/rendering_queue.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:collection';
+import 'dart:async';
+
+/// A generic rendering task that can be scheduled.
+abstract class RenderingTask {
+  /// Rendering synchronous callback.
+  void render();
+}
+
+/// A generic synchronization system for rendering operations.
+abstract class RenderingBarrier {
+  /// Future to the next synchronization barrier (ms from application start).
+  Future<num> get next;
+}
+
+/// Synchronization system based on the AnimationFrame.
+class NextAnimationFrameBarrier implements RenderingBarrier {
+  Future<num> get next => window.animationFrame;
+}
+
+/// MOCK synchronization system for manual barrier triggering.
+class RenderingBarrierMock implements RenderingBarrier {
+  final StreamController<num> _stream = new StreamController<num>.broadcast();
+  num _ms = 0;
+
+  Future<num> get next => _stream.stream.first;
+
+  /// Trigger the next barrier with an optional numer of ms elapsed.
+  void triggerRenderingBarrier({num step: 20}) {
+    assert(step != null);
+    _stream.add(_ms += step);
+  }
+}
+
+/// RenderingTask queuing and synchronization system.
+class RenderingQueue {
+  final RenderingBarrier _barrier;
+  final Queue<RenderingTask> _queue = new Queue<RenderingTask>();
+
+  bool get isEmpty => _queue.isEmpty;
+  bool get isNotEmpty => _queue.isNotEmpty;
+
+  /// Creates a RenderingQueue with the default synchronization barrier.
+  RenderingQueue() : this.fromBarrier(new NextAnimationFrameBarrier());
+
+  /// Creates a RenderingQueue with a custom synchronization barrier.
+  RenderingQueue.fromBarrier(this._barrier) {
+    assert(this._barrier != null);
+  }
+
+  /// Add a task to the queue.
+  /// If the current rendering phase is running it will be executed during this
+  /// rendering cycle, otherwise it will be queued for the next one.
+  void enqueue(RenderingTask r, {bool waitForBarrier: true}) {
+    assert(r != null);
+    final wasEmpty = _queue.isEmpty;
+    _queue.addLast(r);
+    // If no task are in the queue there is no rendering phase scheduled.
+    if (wasEmpty) {
+      if (waitForBarrier) {
+        _render();
+      } else {
+        // We schedule the _renderLoop as a microtask to allow the
+        // scheduleRendering method to terminate, due to the fact that it is
+        // generally invoked from inside a HtmlElement.attached method
+        scheduleMicrotask(_renderLoop);
+      }
+    }
+  }
+
+  Future _render() async {
+    await _barrier.next;
+    _renderLoop();
+  }
+
+  void _renderLoop() {
+    while (_queue.isNotEmpty) {
+      _queue.first.render();
+      _queue.removeFirst();
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/rendering_scheduler.dart b/runtime/observatory_2/lib/src/elements/helpers/rendering_scheduler.dart
new file mode 100644
index 0000000..107664b0
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/rendering_scheduler.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
+export 'package:observatory_2/src/elements/helpers/rendering_queue.dart';
+
+/// A generic renderable object.
+abstract class Renderable {
+  void render();
+}
+
+/// Event related to a Renderable rendering phase.
+class RenderedEvent<T> {
+  /// Renderable to which the event is related
+  final T element;
+
+  /// Is another rendering scheduled for this element.
+  final bool otherRenderScheduled;
+
+  RenderedEvent(this.element, this.otherRenderScheduled) {
+    assert(element != null);
+    assert(otherRenderScheduled != null);
+  }
+}
+
+/// Scheduler for rendering operations.
+class RenderingScheduler<T extends Renderable> implements RenderingTask {
+  bool _enabled = false;
+  bool _dirty = false;
+  bool _renderingScheduled = false;
+  bool _notificationScheduled = false;
+  bool _waitForBarrier = false;
+
+  /// Element managed by this scheduler.
+  final T element;
+
+  /// Queue used for rendering operations.
+  final RenderingQueue queue;
+
+  final List<Future> _wait = <Future>[];
+
+  /// Does the element need a new rendering cycle.
+  bool get isDirty => _dirty;
+
+  /// Is the scheduler enabled.
+  bool get isEnabled => _enabled;
+
+  final StreamController<RenderedEvent<T>> _onRendered =
+      new StreamController<RenderedEvent<T>>.broadcast();
+  Stream<RenderedEvent<T>> get onRendered => _onRendered.stream;
+
+  /// Creates a new scheduler for an element.
+  /// If no queue is provided it will create a new default configured queue.
+  factory RenderingScheduler(T element, {RenderingQueue queue}) {
+    assert(element != null);
+    if (queue == null) {
+      queue = new RenderingQueue();
+    }
+    return new RenderingScheduler<T>._(element, queue);
+  }
+
+  RenderingScheduler._(this.element, this.queue);
+
+  /// Enable the scheduler.
+  /// New dirty or schedule request will be considered.
+  void enable() {
+    if (_enabled) return;
+    _enabled = true;
+    scheduleRendering();
+  }
+
+  /// Disable the scheduler.
+  /// New dirty or schedule request will be discarded.
+  /// [optional] notify: send a final RenderEvent.
+  void disable({bool notify: false}) {
+    assert(notify != null);
+    if (!_enabled) return;
+    _enabled = false;
+    if (notify) scheduleNotification();
+  }
+
+  /// Set the object as dirty. A rendering will be scheduled.
+  void dirty() {
+    if (_dirty) return;
+    _dirty = true;
+    scheduleRendering();
+  }
+
+  /// Checks for modification during attribute set.
+  /// If value changes a new rendering is scheduled.
+  /// set attr(T v) => _attr = _r.checkAndReact(_attr, v);
+  T checkAndReact<T>(T oldValue, T newValue) {
+    if (oldValue != newValue)
+      dirty();
+    else
+      scheduleNotification();
+    return newValue;
+  }
+
+  /// Schedules a new rendering phase.
+  void scheduleRendering() {
+    if (_renderingScheduled) return;
+    if (!_enabled) return;
+    queue.enqueue(this, waitForBarrier: _waitForBarrier);
+    _waitForBarrier = true;
+    _renderingScheduled = true;
+  }
+
+  /// Renders the element (if the scheduler is enabled).
+  /// It will clear the dirty flag.
+  void render() {
+    _renderingScheduled = false;
+    if (!_enabled) return;
+    _dirty = false;
+    _wait.clear();
+    element.render();
+    scheduleNotification();
+    if (_dirty) scheduleRendering();
+  }
+
+  /// Schedules a notification.
+  void scheduleNotification() {
+    if (_notificationScheduled) return;
+    _notify();
+    _notificationScheduled = true;
+  }
+
+  void waitFor(Iterable<Future> it) {
+    _wait.addAll(it);
+  }
+
+  Future _notify() async {
+    await Future.wait(_wait);
+    _wait.clear();
+    _onRendered.add(new RenderedEvent<T>(element, _dirty));
+    _notificationScheduled = false;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/tag.dart b/runtime/observatory_2/lib/src/elements/helpers/tag.dart
new file mode 100644
index 0000000..65c269a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/tag.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+
+HtmlElement element(CustomElement e) => e.element;
+
+class CustomElement {
+  static Expando reverseElements = new Expando();
+  static CustomElement reverse(HtmlElement element) => reverseElements[element];
+
+  static List<CustomElement> toBeAttached = <CustomElement>[];
+  static void drainAttached() {
+    // Send 'attached' to elements that have been attached to the document.
+    bool fired = false;
+    var connectedElements = toBeAttached
+        .where((CustomElement element) => element.element.isConnected)
+        .toList();
+    for (CustomElement element in connectedElements) {
+      toBeAttached.remove(element);
+      element.attached();
+      fired = true;
+    }
+
+    if (toBeAttached.isEmpty) {
+      return; // Done.
+    }
+
+    if (fired) {
+      // The 'attached' events above may have scheduled microtasks that will
+      // will add more CustomElements to be document, e.g. 'render'.
+      scheduleMicrotask(() => drainAttached());
+    }
+
+    while (!toBeAttached.isEmpty) {
+      // Either this element will never be attached or it will be attached
+      // after a turn of the outer event loop. Fire 'attached' in case it is
+      // the latter, since firing it out of order is preferrable to not firing
+      // it at all.
+      CustomElement element = toBeAttached.removeLast();
+      print("Warning: created but not in document: $element");
+      element.attached();
+    }
+  }
+
+  final HtmlElement element;
+  CustomElement.created(Tag tag) : element = document.createElement("shadow") {
+    reverseElements[element] = this;
+    element.classes = [tag.name];
+
+    if (toBeAttached.isEmpty) {
+      scheduleMicrotask(() => drainAttached());
+    }
+    toBeAttached.add(this);
+  }
+
+  void attached() {}
+  void detached() {}
+
+  Element get parent => element.parent;
+
+  List<Element> get children => element.children;
+  set children(List<Element> c) => element.children = c;
+
+  CssClassSet get classes => element.classes;
+  set classes(dynamic c) => element.classes = c;
+
+  String get title => element.title;
+  set title(String t) => element.title = t;
+
+  String get text => element.text;
+  set text(String t) => element.text = t;
+
+  CssStyleDeclaration get style => element.style;
+
+  ElementStream<MouseEvent> get onClick => element.onClick;
+
+  Rectangle getBoundingClientRect() => element.getBoundingClientRect();
+
+  List<Node> getElementsByClassName(String c) =>
+      element.getElementsByClassName(c);
+
+  void scrollIntoView() => element.scrollIntoView();
+}
+
+/// Utility class for Custom Tags registration.
+class Tag<T extends CustomElement> {
+  /// Tag name.
+  final String name;
+
+  /// Dependent tags that need to be registred for this tag to work properly.
+  final Iterable<Tag> dependencies;
+
+  const Tag(this.name, {this.dependencies: const []});
+}
diff --git a/runtime/observatory_2/lib/src/elements/helpers/uris.dart b/runtime/observatory_2/lib/src/elements/helpers/uris.dart
new file mode 100644
index 0000000..c9e3ade
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/helpers/uris.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+
+/// Utility class for URIs generation.
+abstract class Uris {
+  static String _isolatePage(String path, M.IsolateRef isolate,
+      {M.ObjectRef object}) {
+    final parameters = {'isolateId': isolate.id};
+    if (object != null) parameters['objectId'] = object.id;
+    return '#' + new Uri(path: path, queryParameters: parameters).toString();
+  }
+
+  static String allocationProfiler(M.IsolateRef isolate) =>
+      _isolatePage('/allocation-profiler', isolate);
+  static String classTree(M.IsolateRef isolate) =>
+      _isolatePage('/class-tree', isolate);
+  static String cpuProfiler(M.IsolateRef isolate) =>
+      _isolatePage('/profiler', isolate);
+  static String cpuProfilerTable(M.IsolateRef isolate) =>
+      _isolatePage('/profiler-table', isolate);
+  static String debugger(M.IsolateRef isolate) =>
+      _isolatePage('/debugger', isolate);
+  static String flags() => '#/flags';
+  static String heapMap(M.IsolateRef isolate) =>
+      _isolatePage('/heap-map', isolate);
+  static String heapSnapshot(M.IsolateRef isolate) =>
+      _isolatePage('/heap-snapshot', isolate);
+  static String inspect(M.IsolateRef isolate, {M.ObjectRef object, int pos}) {
+    if (pos == null) {
+      return _isolatePage('/inspect', isolate, object: object);
+    }
+    return _isolatePage('/inspect', isolate, object: object) + '---pos=${pos}';
+  }
+
+  static String logging(M.IsolateRef isolate) =>
+      _isolatePage('/logging', isolate);
+  static String metrics(M.IsolateRef isolate) =>
+      _isolatePage('/metrics', isolate);
+  static String nativeMemory() => '#/native-memory-profile';
+  static String processSnapshot() => '#/process-snapshot';
+  static String objectStore(M.IsolateRef isolate) =>
+      _isolatePage('/object-store', isolate);
+  static String persistentHandles(M.IsolateRef isolate) =>
+      _isolatePage('/persistent-handles', isolate);
+  static String ports(M.IsolateRef isolate) => _isolatePage('/ports', isolate);
+  static String timeline() => '#/timeline';
+  static String vm() => '#/vm';
+  static String vmConnect() => '#/vm-connect';
+}
diff --git a/runtime/observatory_2/lib/src/elements/icdata_ref.dart b/runtime/observatory_2/lib/src/elements/icdata_ref.dart
new file mode 100644
index 0000000..1ee4082
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/icdata_ref.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, ICDataRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class ICDataRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ICDataRefElement> _r;
+
+  Stream<RenderedEvent<ICDataRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ICDataRef _icdata;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ICDataRef get icdata => _icdata;
+
+  factory ICDataRefElement(M.IsolateRef isolate, M.ICDataRef icdata,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(icdata != null);
+    ICDataRefElement e = new ICDataRefElement.created();
+    e._r = new RenderingScheduler<ICDataRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._icdata = icdata;
+    return e;
+  }
+
+  ICDataRefElement.created() : super.created('icdata-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _icdata))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'ICData',
+          new SpanElement()..text = ' (${_icdata.selector})'
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/icdata_view.dart b/runtime/observatory_2/lib/src/elements/icdata_view.dart
new file mode 100644
index 0000000..8018897
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/icdata_view.dart
@@ -0,0 +1,189 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ICDataViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ICDataViewElement> _r;
+
+  Stream<RenderedEvent<ICDataViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.ICData _icdata;
+  M.ICDataRepository _icdatas;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.ICData get icdata => _icdata;
+
+  factory ICDataViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.ICData icdata,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ICDataRepository icdatas,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(icdata != null);
+    assert(icdatas != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    ICDataViewElement e = new ICDataViewElement.created();
+    e._r = new RenderingScheduler<ICDataViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._icdata = icdata;
+    e._icdatas = icdatas;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  ICDataViewElement.created() : super.created('icdata-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('icdata'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _icdata = await _icdatas.get(_isolate, _icdata.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'ICData',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _icdata, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'selector',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = _icdata.selector
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'owner',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      _icdata.dartOwner == null
+                          ? (new SpanElement()..text = '<none>')
+                          : anyRef(_isolate, _icdata.dartOwner, _objects,
+                              queue: _r.queue)
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'argumentsDescriptor',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      _icdata.argumentsDescriptor == null
+                          ? (new SpanElement()..text = '<none>')
+                          : anyRef(
+                              _isolate, _icdata.argumentsDescriptor, _objects,
+                              queue: _r.queue)
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'entries',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      _icdata.entries == null
+                          ? (new SpanElement()..text = '<none>')
+                          : anyRef(_isolate, _icdata.entries, _objects,
+                              queue: _r.queue)
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/img/chromium_icon.png b/runtime/observatory_2/lib/src/elements/img/chromium_icon.png
new file mode 100644
index 0000000..a467bca
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/img/chromium_icon.png
Binary files differ
diff --git a/runtime/observatory_2/lib/src/elements/img/dart_icon.png b/runtime/observatory_2/lib/src/elements/img/dart_icon.png
new file mode 100644
index 0000000..6341f65
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/img/dart_icon.png
Binary files differ
diff --git a/runtime/observatory_2/lib/src/elements/img/isolate_icon.png b/runtime/observatory_2/lib/src/elements/img/isolate_icon.png
new file mode 100644
index 0000000..a739a54
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/img/isolate_icon.png
Binary files differ
diff --git a/runtime/observatory_2/lib/src/elements/inbound_references.dart b/runtime/observatory_2/lib/src/elements/inbound_references.dart
new file mode 100644
index 0000000..2f93dc8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/inbound_references.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class InboundReferencesElement extends CustomElement implements Renderable {
+  RenderingScheduler<InboundReferencesElement> _r;
+
+  Stream<RenderedEvent<InboundReferencesElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ObjectRef _object;
+  M.InboundReferencesRepository _references;
+  M.ObjectRepository _objects;
+  M.InboundReferences _inbounds;
+  bool _expanded = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ObjectRef get object => _object;
+
+  factory InboundReferencesElement(M.IsolateRef isolate, M.ObjectRef object,
+      M.InboundReferencesRepository references, M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(object != null);
+    assert(references != null);
+    assert(objects != null);
+    InboundReferencesElement e = new InboundReferencesElement.created();
+    e._r = new RenderingScheduler<InboundReferencesElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._object = object;
+    e._references = references;
+    e._objects = objects;
+    return e;
+  }
+
+  InboundReferencesElement.created() : super.created('inbound-references');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    final curlyBlock =
+        new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+          ..content = _createContent()
+          ..onToggle.listen((e) async {
+            _expanded = e.control.expanded;
+            if (_expanded) {
+              e.control.disabled = true;
+              await _refresh();
+              e.control.disabled = false;
+            }
+          });
+    children = <Element>[curlyBlock.element];
+    _r.waitFor([curlyBlock.onRendered.first]);
+  }
+
+  Future _refresh() async {
+    _inbounds = await _references.get(_isolate, _object.id);
+    _r.dirty();
+  }
+
+  List<Element> _createContent() {
+    if (_inbounds == null) {
+      return const [];
+    }
+    return _inbounds.elements.map<Element>(_createItem).toList();
+  }
+
+  Element _createItem(M.InboundReference reference) {
+    final content = <Element>[];
+
+    if (reference.parentField != null) {
+      content.addAll([
+        new SpanElement()..text = 'referenced by ',
+        anyRef(_isolate, reference.parentField, _objects, queue: _r.queue),
+        new SpanElement()..text = ' of '
+      ]);
+    } else if (reference.parentListIndex != null) {
+      content.add(new SpanElement()
+        ..text = 'referenced by [ ${reference.parentListIndex} ] of ');
+    } else if (reference.parentWordOffset != null) {
+      content.add(new SpanElement()
+        ..text = 'referenced by offset ${reference.parentWordOffset} of ');
+    }
+
+    content.addAll([
+      anyRef(_isolate, reference.source, _objects, queue: _r.queue),
+      new InboundReferencesElement(
+              _isolate, reference.source, _references, _objects,
+              queue: _r.queue)
+          .element
+    ]);
+
+    return new DivElement()
+      ..classes = ['indent']
+      ..children = content;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/instance_ref.dart b/runtime/observatory_2/lib/src/elements/instance_ref.dart
new file mode 100644
index 0000000..51f3616
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/instance_ref.dart
@@ -0,0 +1,342 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/utils.dart';
+
+class InstanceRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<InstanceRefElement> _r;
+
+  Stream<RenderedEvent<InstanceRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.InstanceRef _instance;
+  M.ObjectRepository _objects;
+  M.Instance _loadedInstance;
+  bool _expandable;
+  bool _expanded = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.InstanceRef get instance => _instance;
+
+  factory InstanceRefElement(
+      M.IsolateRef isolate, M.InstanceRef instance, M.ObjectRepository objects,
+      {RenderingQueue queue, bool expandable: true}) {
+    assert(isolate != null);
+    assert(instance != null);
+    assert(objects != null);
+    InstanceRefElement e = new InstanceRefElement.created();
+    e._r = new RenderingScheduler<InstanceRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._instance = instance;
+    e._objects = objects;
+    e._expandable = expandable;
+    return e;
+  }
+
+  InstanceRefElement.created() : super.created('instance-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    final content = _createLink();
+
+    if (_expandable && _hasValue()) {
+      content.addAll([
+        new SpanElement()..text = ' ',
+        (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..children = _createValue()
+              ]
+              ..onToggle.listen((e) async {
+                _expanded = e.control.expanded;
+                if (_expanded) {
+                  e.control.disabled = true;
+                  await _refresh();
+                  e.control.disabled = false;
+                }
+              }))
+            .element
+      ]);
+    }
+
+    children = content;
+  }
+
+  Future _refresh() async {
+    _loadedInstance = await _objects.get(_isolate, _instance.id);
+    _r.dirty();
+  }
+
+  List<Element> _createShowMoreButton() {
+    if (_loadedInstance.count == null) {
+      return [];
+    }
+    final count = _loadedInstance.count;
+    final button = new ButtonElement()..text = 'show next ${count}';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _loadedInstance = await _objects.get(_isolate, _instance.id);
+      _r.dirty();
+    });
+    return [button];
+  }
+
+  List<Element> _createLink() {
+    switch (_instance.kind) {
+      case M.InstanceKind.vNull:
+      case M.InstanceKind.bool:
+      case M.InstanceKind.int:
+      case M.InstanceKind.double:
+      case M.InstanceKind.float32x4:
+      case M.InstanceKind.float64x2:
+      case M.InstanceKind.int32x4:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..text = _instance.valueAsString
+        ];
+      case M.InstanceKind.string:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..text = Utils.formatStringAsLiteral(
+                _instance.valueAsString, _instance.valueAsStringIsTruncated)
+        ];
+      case M.InstanceKind.type:
+      case M.InstanceKind.typeRef:
+      case M.InstanceKind.typeParameter:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..text = _instance.name
+        ];
+      case M.InstanceKind.closure:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..children = <Element>[
+              new SpanElement()
+                ..classes = ['emphasize']
+                ..text = 'Closure',
+              new SpanElement()..text = ' (${_instance.closureFunction.name})'
+            ]
+        ];
+      case M.InstanceKind.regExp:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..children = <Element>[
+              new SpanElement()
+                ..classes = ['emphasize']
+                ..text = _instance.clazz.name,
+              new SpanElement()..text = ' (${_instance.pattern.valueAsString})'
+            ]
+        ];
+      case M.InstanceKind.stackTrace:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..children = <Element>[
+              new SpanElement()
+                ..classes = ['emphasize']
+                ..text = _instance.clazz.name,
+            ]
+        ];
+      case M.InstanceKind.plainInstance:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..classes = ['emphasize']
+            ..text = _instance.clazz.name
+        ];
+      case M.InstanceKind.list:
+      case M.InstanceKind.map:
+      case M.InstanceKind.uint8ClampedList:
+      case M.InstanceKind.uint8List:
+      case M.InstanceKind.uint16List:
+      case M.InstanceKind.uint32List:
+      case M.InstanceKind.uint64List:
+      case M.InstanceKind.int8List:
+      case M.InstanceKind.int16List:
+      case M.InstanceKind.int32List:
+      case M.InstanceKind.int64List:
+      case M.InstanceKind.float32List:
+      case M.InstanceKind.float64List:
+      case M.InstanceKind.int32x4List:
+      case M.InstanceKind.float32x4List:
+      case M.InstanceKind.float64x2List:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..children = <Element>[
+              new SpanElement()
+                ..classes = ['emphasize']
+                ..text = _instance.clazz.name,
+              new SpanElement()..text = ' (${_instance.length})'
+            ]
+        ];
+      case M.InstanceKind.mirrorReference:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..classes = ['emphasize']
+            ..text = _instance.clazz.name
+        ];
+      case M.InstanceKind.weakProperty:
+        return [
+          new AnchorElement(href: Uris.inspect(_isolate, object: _instance))
+            ..classes = ['emphasize']
+            ..text = _instance.clazz.name
+        ];
+    }
+    throw new Exception('Unknown InstanceKind: ${_instance.kind}');
+  }
+
+  bool _hasValue() {
+    switch (_instance.kind) {
+      case M.InstanceKind.closure:
+      case M.InstanceKind.plainInstance:
+      case M.InstanceKind.mirrorReference:
+      case M.InstanceKind.stackTrace:
+      case M.InstanceKind.weakProperty:
+        return true;
+      case M.InstanceKind.list:
+      case M.InstanceKind.map:
+      case M.InstanceKind.uint8ClampedList:
+      case M.InstanceKind.uint8List:
+      case M.InstanceKind.uint16List:
+      case M.InstanceKind.uint32List:
+      case M.InstanceKind.uint64List:
+      case M.InstanceKind.int8List:
+      case M.InstanceKind.int16List:
+      case M.InstanceKind.int32List:
+      case M.InstanceKind.int64List:
+      case M.InstanceKind.float32List:
+      case M.InstanceKind.float64List:
+      case M.InstanceKind.int32x4List:
+      case M.InstanceKind.float32x4List:
+      case M.InstanceKind.float64x2List:
+        return _instance.length > 0;
+      default:
+        return false;
+    }
+  }
+
+  List<Element> _createValue() {
+    if (_loadedInstance == null) {
+      return [new SpanElement()..text = 'Loading...'];
+    }
+    switch (_instance.kind) {
+      case M.InstanceKind.closure:
+        {
+          var members = <Element>[];
+          if (_loadedInstance.closureFunction != null) {
+            members.add(new DivElement()
+              ..children = <Element>[
+                new SpanElement()..text = 'function = ',
+                anyRef(_isolate, _loadedInstance.closureFunction, _objects,
+                    queue: _r.queue)
+              ]);
+          }
+          if (_loadedInstance.closureContext != null) {
+            members.add(new DivElement()
+              ..children = <Element>[
+                new SpanElement()..text = 'context = ',
+                anyRef(_isolate, _loadedInstance.closureContext, _objects,
+                    queue: _r.queue)
+              ]);
+          }
+          return members;
+        }
+      case M.InstanceKind.plainInstance:
+        return _loadedInstance.fields
+            .map<Element>((f) => new DivElement()
+              ..children = <Element>[
+                new FieldRefElement(_isolate, f.decl, _objects, queue: _r.queue)
+                    .element,
+                new SpanElement()..text = ' = ',
+                anyRef(_isolate, f.value, _objects, queue: _r.queue)
+              ])
+            .toList();
+      case M.InstanceKind.list:
+        var index = 0;
+        return _loadedInstance.elements
+            .map<Element>((element) => new DivElement()
+              ..children = <Element>[
+                new SpanElement()..text = '[ ${index++} ] : ',
+                anyRef(_isolate, element, _objects, queue: _r.queue)
+              ])
+            .toList()
+              ..addAll(_createShowMoreButton());
+      case M.InstanceKind.map:
+        return _loadedInstance.associations
+            .map<Element>((association) => new DivElement()
+              ..children = <Element>[
+                new SpanElement()..text = '[ ',
+                anyRef(_isolate, association.key, _objects, queue: _r.queue),
+                new SpanElement()..text = ' ] : ',
+                anyRef(_isolate, association.value, _objects, queue: _r.queue)
+              ])
+            .toList()
+              ..addAll(_createShowMoreButton());
+      case M.InstanceKind.uint8ClampedList:
+      case M.InstanceKind.uint8List:
+      case M.InstanceKind.uint16List:
+      case M.InstanceKind.uint32List:
+      case M.InstanceKind.uint64List:
+      case M.InstanceKind.int8List:
+      case M.InstanceKind.int16List:
+      case M.InstanceKind.int32List:
+      case M.InstanceKind.int64List:
+      case M.InstanceKind.float32List:
+      case M.InstanceKind.float64List:
+      case M.InstanceKind.int32x4List:
+      case M.InstanceKind.float32x4List:
+      case M.InstanceKind.float64x2List:
+        var index = 0;
+        return _loadedInstance.typedElements
+            .map<Element>((e) => new DivElement()..text = '[ ${index++} ] : $e')
+            .toList()
+              ..addAll(_createShowMoreButton());
+      case M.InstanceKind.mirrorReference:
+        return [
+          new SpanElement()..text = '<referent> : ',
+          anyRef(_isolate, _loadedInstance.referent, _objects, queue: _r.queue)
+        ];
+      case M.InstanceKind.stackTrace:
+        return [
+          new DivElement()
+            ..classes = ['stackTraceBox']
+            ..text = _instance.valueAsString
+        ];
+      case M.InstanceKind.weakProperty:
+        return [
+          new SpanElement()..text = '<key> : ',
+          new InstanceRefElement(_isolate, _loadedInstance.key, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new SpanElement()..text = '<value> : ',
+          new InstanceRefElement(_isolate, _loadedInstance.value, _objects,
+                  queue: _r.queue)
+              .element,
+        ];
+      default:
+        return [];
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/instance_view.dart b/runtime/observatory_2/lib/src/elements/instance_view.dart
new file mode 100644
index 0000000..1b78e7d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/instance_view.dart
@@ -0,0 +1,527 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library instance_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/eval_box.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/library_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/source_inset.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+import 'package:observatory_2/utils.dart';
+
+class InstanceViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<InstanceViewElement> _r;
+
+  Stream<RenderedEvent<InstanceViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Instance _instance;
+  M.LibraryRef _library;
+  M.ObjectRepository _objects;
+  M.ClassRepository _classes;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ScriptRepository _scripts;
+  M.EvalRepository _eval;
+  M.TypeArguments _typeArguments;
+  M.TypeArgumentsRepository _arguments;
+  M.BreakpointRepository _breakpoints;
+  M.FunctionRepository _functions;
+  M.SourceLocation _location;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Instance get instance => _instance;
+
+  factory InstanceViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Instance instance,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ObjectRepository objects,
+      M.ClassRepository classes,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ScriptRepository scripts,
+      M.EvalRepository eval,
+      M.TypeArgumentsRepository arguments,
+      M.BreakpointRepository breakpoints,
+      M.FunctionRepository functions,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(instance != null);
+    assert(objects != null);
+    assert(classes != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(scripts != null);
+    assert(eval != null);
+    assert(arguments != null);
+    assert(breakpoints != null);
+    assert(functions != null);
+    InstanceViewElement e = new InstanceViewElement.created();
+    e._r = new RenderingScheduler<InstanceViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._instance = instance;
+    e._objects = objects;
+    e._classes = classes;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._scripts = scripts;
+    e._eval = eval;
+    e._arguments = arguments;
+    e._breakpoints = breakpoints;
+    e._functions = functions;
+    return e;
+  }
+
+  InstanceViewElement.created() : super.created('instance-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _loadExtraData();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final content = <Element>[
+      new HeadingElement.h2()
+        ..text = M.isAbstractType(_instance.kind)
+            ? 'type ${_instance.name}'
+            : 'instance of ${_instance.clazz.name}',
+      new HRElement(),
+      new ObjectCommonElement(_isolate, _instance, _retainedSizes,
+              _reachableSizes, _references, _retainingPaths, _objects,
+              queue: _r.queue)
+          .element,
+      new BRElement(),
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = _createMembers(),
+      new HRElement(),
+      new EvalBoxElement(_isolate, _instance, _objects, _eval,
+              quickExpressions: const ['toString()', 'runtimeType'],
+              queue: _r.queue)
+          .element
+    ];
+    if (_location != null) {
+      content.addAll([
+        new HRElement(),
+        new SourceInsetElement(_isolate, _location, _scripts, _objects, _events,
+                queue: _r.queue)
+            .element
+      ]);
+    }
+    content.addAll(
+        [new HRElement(), new ViewFooterElement(queue: _r.queue).element]);
+    children = <Element>[
+      navBar(_createMenu()),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = content
+    ];
+  }
+
+  List<Element> _createMenu() {
+    final menu = <Element>[
+      new NavTopMenuElement(queue: _r.queue).element,
+      new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+      new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element
+    ];
+    if (_library != null) {
+      menu.add(new NavLibraryMenuElement(_isolate, _library, queue: _r.queue)
+          .element);
+    }
+    menu.addAll(<Element>[
+      new NavClassMenuElement(_isolate, _instance.clazz, queue: _r.queue)
+          .element,
+      navMenu('instance'),
+      (new NavRefreshElement(queue: _r.queue)
+            ..onRefresh.listen((e) {
+              e.element.disabled = true;
+              _refresh();
+            }))
+          .element,
+      new NavNotifyElement(_notifications, queue: _r.queue).element
+    ]);
+    return menu;
+  }
+
+  Element memberHalf(String cssClass, dynamic half) {
+    var result = new DivElement()..classes = [cssClass];
+    if (half is String) {
+      result.text = half;
+    } else {
+      result.children = <Element>[
+        anyRef(_isolate, half, _objects, queue: _r.queue)
+      ];
+    }
+    return result;
+  }
+
+  Element member(dynamic name, dynamic value) {
+    return new DivElement()
+      ..classes = ['memberItem']
+      ..children = <Element>[
+        memberHalf('memberName', name),
+        memberHalf('memberValue', value),
+      ];
+  }
+
+  List<Element> _createMembers() {
+    final members = <Element>[];
+    if (_instance.valueAsString != null) {
+      if (_instance.kind == M.InstanceKind.string) {
+        members.add(member(
+            'value as literal',
+            Utils.formatStringAsLiteral(
+                _instance.valueAsString, _instance.valueAsStringIsTruncated)));
+      } else {
+        members.add(member('value', _instance.valueAsString));
+      }
+    }
+    if (_instance.typeClass != null) {
+      members.add(member('type class', _instance.typeClass));
+    }
+    if (_typeArguments != null && _typeArguments.types.isNotEmpty) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'type arguments',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = ([new SpanElement()..text = '< ']
+              ..addAll(_typeArguments.types.expand((type) => [
+                    new InstanceRefElement(_isolate, type, _objects,
+                            queue: _r.queue)
+                        .element,
+                    new SpanElement()..text = ', '
+                  ]))
+              ..removeLast()
+              ..add(new SpanElement()..text = ' >'))
+        ]);
+    }
+    if (_instance.parameterizedClass != null) {
+      members.add(member('parameterized class', _instance.parameterizedClass));
+    }
+    if (_instance.parameterIndex != null) {
+      members.add(member('parameter index', '${_instance.parameterIndex}'));
+    }
+    if (_instance.targetType != null) {
+      members.add(member('target type', _instance.targetType));
+    }
+    if (_instance.bound != null) {
+      members.add(member('bound', _instance.bound));
+    }
+    if (_instance.closureFunction != null) {
+      members.add(member('closure function', _instance.closureFunction));
+    }
+    if (_instance.closureContext != null) {
+      members.add(member('closure context', _instance.closureContext));
+    }
+    if (_instance.kind == M.InstanceKind.closure) {
+      ButtonElement btn;
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'closure breakpoint',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              btn = new ButtonElement()
+                ..text = _instance.activationBreakpoint == null
+                    ? 'break on activation'
+                    : 'remove'
+                ..onClick.listen((_) {
+                  btn.disabled = true;
+                  _toggleBreakpoint();
+                })
+            ]
+        ]);
+    }
+
+    if (_instance.nativeFields != null && _instance.nativeFields.isNotEmpty) {
+      int i = 0;
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'native fields (${_instance.nativeFields.length})',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              (new CurlyBlockElement(
+                      expanded: _instance.nativeFields.length <= 100,
+                      queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = _instance.nativeFields
+                            .map<Element>(
+                                (f) => member('[ ${i++} ]', '[ ${f.value} ]'))
+                            .toList()
+                    ])
+                  .element
+            ]
+        ]);
+    }
+
+    if (_instance.fields != null && _instance.fields.isNotEmpty) {
+      final fields = _instance.fields.toList();
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'fields (${fields.length})',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              (new CurlyBlockElement(
+                      expanded: fields.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = fields
+                            .map<Element>((f) => member(f.decl, f.value))
+                            .toList()
+                    ])
+                  .element
+            ]
+        ]);
+    }
+
+    if (_instance.elements != null && _instance.elements.isNotEmpty) {
+      final elements = _instance.elements.toList();
+      int i = 0;
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'elements (${_instance.length})',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              (new CurlyBlockElement(
+                      expanded: elements.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = elements
+                            .map<Element>(
+                                (element) => member('[ ${i++} ]', element))
+                            .toList()
+                    ])
+                  .element
+            ]
+        ]);
+      if (_instance.length != elements.length) {
+        members.add(member(
+            '...', '${_instance.length - elements.length} omitted elements'));
+      }
+    }
+
+    if (_instance.associations != null && _instance.associations.isNotEmpty) {
+      final associations = _instance.associations.toList();
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'associations (${_instance.length})',
+          new DivElement()
+            ..classes = ['memberName']
+            ..children = <Element>[
+              (new CurlyBlockElement(
+                      expanded: associations.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = associations
+                            .map<Element>((a) => new DivElement()
+                              ..classes = ['memberItem']
+                              ..children = <Element>[
+                                new DivElement()
+                                  ..classes = ['memberName']
+                                  ..children = <Element>[
+                                    new SpanElement()..text = '[ ',
+                                    anyRef(_isolate, a.key, _objects,
+                                        queue: _r.queue),
+                                    new SpanElement()..text = ' ]',
+                                  ],
+                                new DivElement()
+                                  ..classes = ['memberValue']
+                                  ..children = <Element>[
+                                    anyRef(_isolate, a.value, _objects,
+                                        queue: _r.queue)
+                                  ]
+                              ])
+                            .toList()
+                    ])
+                  .element
+            ]
+        ]);
+      if (_instance.length != associations.length) {
+        members.add(member('...',
+            '${_instance.length - associations.length} omitted elements'));
+      }
+    }
+
+    if (_instance.typedElements != null && _instance.typedElements.isNotEmpty) {
+      final typedElements = _instance.typedElements.toList();
+      int i = 0;
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'elements (${_instance.length})',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = <Element>[
+              (new CurlyBlockElement(
+                      expanded: typedElements.length <= 100, queue: _r.queue)
+                    ..content = <Element>[
+                      new DivElement()
+                        ..classes = ['memberList']
+                        ..children = typedElements
+                            .map<Element>((e) => member('[ ${i++} ]', '$e'))
+                            .toList()
+                    ])
+                  .element
+            ]
+        ]);
+      if (_instance.length != typedElements.length) {
+        members.add(member('...',
+            '${_instance.length - typedElements.length} omitted elements'));
+      }
+    }
+
+    if (_instance.kind == M.InstanceKind.regExp) {
+      members.add(member('pattern', _instance.pattern));
+      members.add(
+          member('isCaseSensitive', _instance.isCaseSensitive ? 'yes' : 'no'));
+      members.add(member('isMultiLine', _instance.isMultiLine ? 'yes' : 'no'));
+      if (_instance.oneByteFunction != null) {
+        members.add(member('oneByteFunction', _instance.oneByteFunction));
+      }
+      if (_instance.twoByteFunction != null) {
+        members.add(member('twoByteFunction', _instance.twoByteFunction));
+      }
+      if (_instance.externalOneByteFunction != null) {
+        members.add(member(
+            'externalOneByteFunction', _instance.externalOneByteFunction));
+      }
+      if (_instance.externalTwoByteFunction != null) {
+        members.add(member(
+            'externalTwoByteFunction', _instance.externalTwoByteFunction));
+      }
+      if (_instance.oneByteBytecode != null) {
+        members.add(member('oneByteBytecode', _instance.oneByteBytecode));
+      }
+      if (_instance.twoByteBytecode != null) {
+        members.add(member('twoByteBytecode', _instance.twoByteBytecode));
+      }
+    }
+
+    if (_instance.kind == M.InstanceKind.mirrorReference) {
+      members.add(member('referent', _instance.referent));
+    }
+
+    if (_instance.kind == M.InstanceKind.weakProperty) {
+      members.add(member('key', _instance.key));
+      members.add(member('value', _instance.value));
+    }
+
+    return members;
+  }
+
+  Future _refresh() async {
+    _instance = await _objects.get(_isolate, _instance.id);
+    await _loadExtraData();
+    _r.dirty();
+  }
+
+  Future _loadExtraData() async {
+    _library = (await _classes.get(_isolate, _instance.clazz.id)).library;
+    if (_instance.typeArguments != null) {
+      _typeArguments =
+          await _arguments.get(_isolate, _instance.typeArguments.id);
+    } else {
+      _typeArguments = null;
+    }
+    if (_instance.closureFunction != null) {
+      _location = (await _functions.get(_isolate, _instance.closureFunction.id))
+          .location;
+    } else if (_instance.typeClass != null) {
+      _location =
+          (await _classes.get(_isolate, _instance.typeClass.id)).location;
+    }
+    _r.dirty();
+  }
+
+  Future _toggleBreakpoint() async {
+    if (_instance.activationBreakpoint == null) {
+      await _breakpoints.addOnActivation(_isolate, _instance);
+    } else {
+      await _breakpoints.remove(_isolate, _instance.activationBreakpoint);
+    }
+    await _refresh();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate/counter_chart.dart b/runtime/observatory_2/lib/src/elements/isolate/counter_chart.dart
new file mode 100644
index 0000000..0464570
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate/counter_chart.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class IsolateCounterChartElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateCounterChartElement> _r;
+
+  Stream<RenderedEvent<IsolateCounterChartElement>> get onRendered =>
+      _r.onRendered;
+
+  Map _counters;
+  StreamSubscription _subscription;
+
+  factory IsolateCounterChartElement(Map counters, {RenderingQueue queue}) {
+    assert(counters != null);
+    IsolateCounterChartElement e = new IsolateCounterChartElement.created();
+    e._r = new RenderingScheduler<IsolateCounterChartElement>(e, queue: queue);
+    e._counters = counters;
+    return e;
+  }
+
+  IsolateCounterChartElement.created() : super.created('isolate-counter-chart');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = window.onResize.listen((_) => _r.dirty());
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    var members = <Element>[];
+    _counters.forEach((key, value) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = key,
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = value,
+        ]);
+    });
+
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = members
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate/location.dart b/runtime/observatory_2/lib/src/elements/isolate/location.dart
new file mode 100644
index 0000000..a71ee86
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate/location.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/source_link.dart';
+
+class IsolateLocationElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateLocationElement> _r;
+
+  Stream<RenderedEvent<IsolateLocationElement>> get onRendered => _r.onRendered;
+
+  M.Isolate _isolate;
+  M.EventRepository _events;
+  M.ScriptRepository _scripts;
+  StreamSubscription _debugSubscription;
+  StreamSubscription _isolateSubscription;
+
+  factory IsolateLocationElement(
+      M.Isolate isolate, M.EventRepository events, M.ScriptRepository scripts,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    assert(scripts != null);
+    IsolateLocationElement e = new IsolateLocationElement.created();
+    e._r = new RenderingScheduler<IsolateLocationElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    e._scripts = scripts;
+    return e;
+  }
+
+  IsolateLocationElement.created() : super.created('isolate-location');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _debugSubscription = _events.onDebugEvent.listen(_eventListener);
+    _isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _debugSubscription.cancel();
+    _isolateSubscription.cancel();
+  }
+
+  void render() {
+    switch (_isolate.status) {
+      case M.IsolateStatus.loading:
+        children = <Element>[new SpanElement()..text = 'not yet runnable'];
+        break;
+      case M.IsolateStatus.running:
+        children = <Element>[
+          new SpanElement()..text = 'at ',
+          new FunctionRefElement(
+                  _isolate, M.topFrame(_isolate.pauseEvent).function,
+                  queue: _r.queue)
+              .element,
+          new SpanElement()..text = ' (',
+          new SourceLinkElement(
+                  _isolate, M.topFrame(_isolate.pauseEvent).location, _scripts,
+                  queue: _r.queue)
+              .element,
+          new SpanElement()..text = ') '
+        ];
+        break;
+      case M.IsolateStatus.paused:
+        if (_isolate.pauseEvent is M.PauseStartEvent) {
+          children = <Element>[new SpanElement()..text = 'at isolate start'];
+        } else if (_isolate.pauseEvent is M.PauseExitEvent) {
+          children = <Element>[new SpanElement()..text = 'at isolate exit'];
+        } else if (_isolate.pauseEvent is M.NoneEvent) {
+          children = <Element>[new SpanElement()..text = 'not yet runnable'];
+        } else {
+          final content = <Element>[];
+          if (_isolate.pauseEvent is M.PauseBreakpointEvent) {
+            content.add(new SpanElement()..text = 'by breakpoint');
+          } else if (_isolate.pauseEvent is M.PauseExceptionEvent) {
+            content.add(new SpanElement()..text = 'by exception');
+          }
+          if (M.topFrame(_isolate.pauseEvent) != null) {
+            content.addAll([
+              new SpanElement()..text = ' at ',
+              new FunctionRefElement(
+                      _isolate, M.topFrame(_isolate.pauseEvent).function,
+                      queue: _r.queue)
+                  .element,
+              new SpanElement()..text = ' (',
+              new SourceLinkElement(_isolate,
+                      M.topFrame(_isolate.pauseEvent).location, _scripts,
+                      queue: _r.queue)
+                  .element,
+              new SpanElement()..text = ') '
+            ]);
+          }
+          children = content;
+        }
+        break;
+      default:
+        children = const [];
+    }
+  }
+
+  void _eventListener(e) {
+    if (e.isolate.id == _isolate.id) {
+      _r.dirty();
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate/run_state.dart b/runtime/observatory_2/lib/src/elements/isolate/run_state.dart
new file mode 100644
index 0000000..c87692a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate/run_state.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class IsolateRunStateElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateRunStateElement> _r;
+
+  Stream<RenderedEvent<IsolateRunStateElement>> get onRendered => _r.onRendered;
+
+  M.Isolate _isolate;
+  M.EventRepository _events;
+  StreamSubscription _debugSubscription;
+  StreamSubscription _isolateSubscription;
+
+  factory IsolateRunStateElement(M.Isolate isolate, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    IsolateRunStateElement e = new IsolateRunStateElement.created();
+    e._r = new RenderingScheduler<IsolateRunStateElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    return e;
+  }
+
+  IsolateRunStateElement.created() : super.created('isolate-run-state');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _debugSubscription = _events.onDebugEvent.listen(_eventListener);
+    _isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _debugSubscription.cancel();
+    _isolateSubscription.cancel();
+  }
+
+  void render() {
+    switch (_isolate.status) {
+      case M.IsolateStatus.loading:
+        children = <Element>[new SpanElement()..text = 'loading... '];
+        break;
+      case M.IsolateStatus.running:
+        children = <Element>[new SpanElement()..text = 'running '];
+        break;
+      case M.IsolateStatus.idle:
+        children = <Element>[new SpanElement()..text = 'idle '];
+        break;
+      case M.IsolateStatus.paused:
+        children = <Element>[
+          new SpanElement()
+            ..title = '${_isolate.pauseEvent.timestamp}'
+            ..text = 'paused '
+        ];
+        break;
+    }
+  }
+
+  void _eventListener(e) {
+    if (e.isolate.id == _isolate.id) {
+      _isolate = e.isolate;
+      _r.dirty();
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate/shared_summary.dart b/runtime/observatory_2/lib/src/elements/isolate/shared_summary.dart
new file mode 100644
index 0000000..b9d5e58
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate/shared_summary.dart
@@ -0,0 +1,177 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/utils.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/isolate/counter_chart.dart';
+
+class IsolateSharedSummaryElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateSharedSummaryElement> _r;
+
+  Stream<RenderedEvent<IsolateSharedSummaryElement>> get onRendered =>
+      _r.onRendered;
+
+  M.Isolate _isolate;
+  M.EventRepository _events;
+  StreamSubscription _isolateSubscription;
+
+  factory IsolateSharedSummaryElement(
+      M.Isolate isolate, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    IsolateSharedSummaryElement e = new IsolateSharedSummaryElement.created();
+    e._r = new RenderingScheduler<IsolateSharedSummaryElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    return e;
+  }
+
+  IsolateSharedSummaryElement.created()
+      : super.created('isolate-shared-summary');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _isolateSubscription = _events.onIsolateEvent.listen(_eventListener);
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _isolateSubscription.cancel();
+  }
+
+  void render() {
+    final newHeapUsed = Utils.formatSize(_isolate.newSpace.used);
+    final newHeapCapacity = Utils.formatSize(_isolate.newSpace.capacity);
+    final oldHeapUsed = Utils.formatSize(_isolate.oldSpace.used);
+    final oldHeapCapacity = Utils.formatSize(_isolate.oldSpace.capacity);
+    final content = <Element>[
+      new DivElement()
+        ..classes = ['menu']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'new heap',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '$newHeapUsed of $newHeapCapacity',
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'old heap',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '$oldHeapUsed of $oldHeapCapacity',
+                ]
+            ],
+          new BRElement(),
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.debugger(_isolate))
+                ..text = 'debugger'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.classTree(_isolate))
+                ..text = 'class hierarchy'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.cpuProfiler(_isolate))
+                ..text = 'cpu profile'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
+                ..text = 'cpu profile (table)'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.allocationProfiler(_isolate))
+                ..text = 'allocation profile'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.heapSnapshot(_isolate))
+                ..text = 'heap snapshot'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.heapMap(_isolate))..text = 'heap map'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.metrics(_isolate))..text = 'metrics'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.persistentHandles(_isolate))
+                ..text = 'persistent handles'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.ports(_isolate))..text = 'ports'
+            ],
+          new DivElement()
+            ..children = <Element>[
+              new SpanElement()..text = 'see ',
+              new AnchorElement(href: Uris.logging(_isolate))..text = 'logging'
+            ]
+        ],
+      new IsolateCounterChartElement(_isolate.counters, queue: _r.queue).element
+    ];
+    if (_isolate.error != null) {
+      children = <Element>[
+        new PreElement()
+          ..classes = ['errorBox']
+          ..text = _isolate.error.message,
+        new DivElement()
+          ..classes = ['summary']
+          ..children = content
+      ];
+    } else {
+      children = <Element>[
+        new DivElement()
+          ..classes = ['summary']
+          ..children = content
+      ];
+    }
+  }
+
+  void _eventListener(e) {
+    if (e.isolate.id == _isolate.id) {
+      _isolate = e.isolate;
+      _r.dirty();
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate/summary.dart b/runtime/observatory_2/lib/src/elements/isolate/summary.dart
new file mode 100644
index 0000000..2c3f156
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate/summary.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/utils.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/isolate_ref.dart';
+import 'package:observatory_2/src/elements/isolate/location.dart';
+import 'package:observatory_2/src/elements/isolate/run_state.dart';
+import 'package:observatory_2/src/elements/isolate/shared_summary.dart';
+
+class IsolateSummaryElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateSummaryElement> _r;
+
+  Stream<RenderedEvent<IsolateSummaryElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.IsolateRepository _isolates;
+  M.ScriptRepository _scripts;
+  M.Isolate _loadedIsolate;
+
+  factory IsolateSummaryElement(
+      M.IsolateRef isolate,
+      M.IsolateRepository isolates,
+      M.EventRepository events,
+      M.ScriptRepository scripts,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(isolates != null);
+    assert(events != null);
+    assert(scripts != null);
+    IsolateSummaryElement e = new IsolateSummaryElement.created();
+    e._r = new RenderingScheduler<IsolateSummaryElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._isolates = isolates;
+    e._events = events;
+    e._scripts = scripts;
+    return e;
+  }
+
+  IsolateSummaryElement.created() : super.created('isolate-summary');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _load();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    if (_loadedIsolate == null) {
+      children = <Element>[
+        new SpanElement()..text = 'loading ',
+        new IsolateRefElement(_isolate, _events, queue: _r.queue).element
+      ];
+    } else {
+      children = <Element>[
+        linkAndStatusRow(),
+        new BRElement(),
+        memoryRow(),
+        new BRElement(),
+        toolsRow(),
+      ];
+    }
+  }
+
+  Element linkAndStatusRow() {
+    return new DivElement()
+      ..classes = ['flex-row-wrap']
+      ..children = <Element>[
+        new DivElement()
+          ..classes = ['isolate-ref-container']
+          ..children = <Element>[
+            new IsolateRefElement(_isolate, _events, queue: _r.queue).element
+          ],
+        new DivElement()..style.flex = '1',
+        new DivElement()
+          ..classes = ['flex-row', 'isolate-state-container']
+          ..children = <Element>[
+            new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
+                .element,
+            new IsolateLocationElement(_isolate, _events, _scripts,
+                    queue: _r.queue)
+                .element,
+            new SpanElement()..text = ' [',
+            new AnchorElement(href: Uris.debugger(_isolate))..text = 'debug',
+            new SpanElement()..text = ']'
+          ]
+      ];
+  }
+
+  Element memoryRow() {
+    final isolate = _isolate as M.Isolate;
+    final newHeapUsed = Utils.formatSize(isolate.newSpace.used);
+    final newHeapCapacity = Utils.formatSize(isolate.newSpace.capacity);
+    final oldHeapUsed = Utils.formatSize(isolate.oldSpace.used);
+    final oldHeapCapacity = Utils.formatSize(isolate.oldSpace.capacity);
+    final heapUsed =
+        Utils.formatSize(isolate.newSpace.used + isolate.oldSpace.used);
+    final heapCapacity =
+        Utils.formatSize(isolate.newSpace.capacity + isolate.oldSpace.capacity);
+    return new DivElement()
+      ..classes = ['flex-row-wrap-right']
+      ..children = <Element>[
+        new DivElement()
+          ..style.padding = '5px'
+          ..text = 'new-space $newHeapUsed of $newHeapCapacity',
+        new DivElement()
+          ..style.padding = '5px'
+          ..text = '/',
+        new DivElement()
+          ..style.padding = '5px'
+          ..text = 'old-space $oldHeapUsed of $oldHeapCapacity',
+        new DivElement()
+          ..style.padding = '5px'
+          ..text = '/',
+        new DivElement()
+          ..style.padding = '5px'
+          ..text = 'heap $heapUsed of $heapCapacity',
+      ];
+  }
+
+  Element toolsRow() {
+    return new DivElement()
+      ..classes = ['flex-row-spaced']
+      ..children = <Element>[
+        new AnchorElement(href: Uris.debugger(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'debugger',
+        new AnchorElement(href: Uris.classTree(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'class hierarchy',
+        new AnchorElement(href: Uris.cpuProfiler(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'cpu profile',
+        new AnchorElement(href: Uris.cpuProfilerTable(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'cpu profile (table)',
+        new AnchorElement(href: Uris.allocationProfiler(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'allocation profile',
+        new AnchorElement(href: Uris.heapSnapshot(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'heap snapshot',
+        new AnchorElement(href: Uris.heapMap(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'heap map',
+        new AnchorElement(href: Uris.metrics(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'metrics',
+        new AnchorElement(href: Uris.persistentHandles(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'persistent handles',
+        new AnchorElement(href: Uris.ports(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'ports',
+        new AnchorElement(href: Uris.logging(_isolate))
+          ..classes = ['flex-item-even']
+          ..text = 'logging',
+      ];
+  }
+
+  Future _load() async {
+    _loadedIsolate = await _isolates.get(_isolate);
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate_reconnect.dart b/runtime/observatory_2/lib/src/elements/isolate_reconnect.dart
new file mode 100644
index 0000000..f4b9e23
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate_reconnect.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library isolate_reconnect_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class IsolateReconnectElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateReconnectElement> _r;
+
+  Stream<RenderedEvent<IsolateReconnectElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  String _missing;
+  Uri _uri;
+  M.EventRepository _events;
+  StreamSubscription _subscription;
+
+  M.VM get vm => _vm;
+  String get missing => _missing;
+  Uri get uri => _uri;
+
+  M.NotificationRepository _notifications;
+  factory IsolateReconnectElement(M.VM vm, M.EventRepository events,
+      M.NotificationRepository notifications, String missing, Uri uri,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    assert(missing != null);
+    assert(uri != null);
+    assert(notifications != null);
+    IsolateReconnectElement e = new IsolateReconnectElement.created();
+    e._r = new RenderingScheduler<IsolateReconnectElement>(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    e._missing = missing;
+    e._uri = uri;
+    e._notifications = notifications;
+    return e;
+  }
+
+  IsolateReconnectElement.created() : super.created('isolate-reconnect');
+
+  @override
+  void attached() {
+    super.attached();
+    _subscription = _events.onVMUpdate.listen((e) {
+      _vm = e.vm;
+      _r.dirty();
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()..text = 'Isolate $_missing no longer exists',
+          new HRElement(),
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = (_vm.isolates.map<Element>((isolate) {
+              final query = new Map<String, dynamic>.from(_uri.queryParameters);
+              query['isolateId'] = isolate.id;
+              final href = new Uri(path: _uri.path, queryParameters: query);
+              return new DivElement()
+                ..classes = ['memberItem', 'doubleSpaced']
+                ..children = <Element>[
+                  new SpanElement()..text = 'Continue in ',
+                  new AnchorElement(href: '#$href')
+                    ..classes = ['isolate-link']
+                    ..text = '${isolate.id} (${isolate.name})'
+                ];
+            }).toList()
+              ..add(new DivElement()
+                ..classes = ['memberItem', 'doubleSpaced']
+                ..children = <Element>[
+                  new SpanElement()..text = 'Go to ',
+                  new AnchorElement(href: Uris.vm())..text = 'isolates summary',
+                ]))
+        ],
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate_ref.dart b/runtime/observatory_2/lib/src/elements/isolate_ref.dart
new file mode 100644
index 0000000..ceebf22
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate_ref.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library isolate_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, EventRepository;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class IsolateRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateRefElement> _r;
+
+  Stream<RenderedEvent<IsolateRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  StreamSubscription _updatesSubscription;
+
+  M.IsolateRef get isolate => _isolate;
+
+  factory IsolateRefElement(M.IsolateRef isolate, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    IsolateRefElement e = new IsolateRefElement.created();
+    e._r = new RenderingScheduler<IsolateRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    return e;
+  }
+
+  IsolateRefElement.created() : super.created('isolate-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _updatesSubscription = _events.onIsolateUpdate
+        .where((e) => e.isolate.id == isolate.id)
+        .listen((e) {
+      _isolate = e.isolate;
+      _r.dirty();
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _updatesSubscription.cancel();
+  }
+
+  void render() {
+    final isolateType = isolate.isSystemIsolate ? 'System Isolate' : 'Isolate';
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(isolate))
+        ..text = '$isolateType ${isolate.number} (${isolate.name})'
+        ..classes = ['isolate-ref']
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/isolate_view.dart b/runtime/observatory_2/lib/src/elements/isolate_view.dart
new file mode 100644
index 0000000..269f207
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/isolate_view.dart
@@ -0,0 +1,402 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library isolate_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/eval_box.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/isolate/location.dart';
+import 'package:observatory_2/src/elements/isolate/run_state.dart';
+import 'package:observatory_2/src/elements/isolate/shared_summary.dart';
+import 'package:observatory_2/src/elements/library_ref.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/reload.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/script_inset.dart';
+import 'package:observatory_2/src/elements/source_inset.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+import 'package:observatory_2/utils.dart';
+
+class IsolateViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<IsolateViewElement> _r;
+
+  Stream<RenderedEvent<IsolateViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.Isolate _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.IsolateRepository _isolates;
+  M.ScriptRepository _scripts;
+  M.FunctionRepository _functions;
+  M.LibraryRepository _libraries;
+  M.ObjectRepository _objects;
+  M.EvalRepository _eval;
+  M.ServiceFunction _function;
+  M.ScriptRef _rootScript;
+  StreamSubscription _subscription;
+
+  M.VMRef get vm => _vm;
+  M.Isolate get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory IsolateViewElement(
+      M.VM vm,
+      M.Isolate isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.IsolateRepository isolates,
+      M.ScriptRepository scripts,
+      M.FunctionRepository functions,
+      M.LibraryRepository libraries,
+      M.ObjectRepository objects,
+      M.EvalRepository eval,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(isolates != null);
+    assert(scripts != null);
+    assert(functions != null);
+    assert(objects != null);
+    assert(eval != null);
+    assert(libraries != null);
+    IsolateViewElement e = new IsolateViewElement.created();
+    e._r = new RenderingScheduler<IsolateViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._isolates = isolates;
+    e._scripts = scripts;
+    e._functions = functions;
+    e._objects = objects;
+    e._eval = eval;
+    e._libraries = libraries;
+    return e;
+  }
+
+  IsolateViewElement.created() : super.created('isolate-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _loadExtraData();
+    _subscription = _events.onIsolateUpdate.listen((e) {
+      if (e.isolate.id == _isolate) {
+        _isolate = isolate;
+        _r.dirty();
+      }
+    });
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _subscription.cancel();
+  }
+
+  void render() {
+    final uptime = new DateTime.now().difference(_isolate.startTime);
+    final libraries = _isolate.libraries.toList();
+    final List<M.Thread> threads = _isolate.threads;
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        (new NavReloadElement(_isolate, _isolates, _events, queue: _r.queue)
+              ..onReload.listen((_) async {
+                _isolate = await _isolates.get(_isolate);
+                await _loadExtraData();
+                _r.dirty();
+              }))
+            .element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _isolate = await _isolates.get(_isolate);
+                await _loadExtraData();
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Isolate ${_isolate.name}',
+          new BRElement(),
+          new DivElement()
+            ..classes = ['flex-row']
+            ..children = <Element>[
+              new DivElement()..style.flex = '1',
+              new DivElement()
+                ..children = <Element>[
+                  new IsolateRunStateElement(_isolate, _events, queue: _r.queue)
+                      .element,
+                  new IsolateLocationElement(_isolate, _events, _scripts,
+                          queue: _r.queue)
+                      .element,
+                  new SpanElement()..text = ' [',
+                  new AnchorElement(href: Uris.debugger(_isolate))
+                    ..text = 'debug',
+                  new SpanElement()..text = ']'
+                ]
+            ],
+          new DivElement()
+            ..children = _function != null
+                ? [
+                    new BRElement(),
+                    (new SourceInsetElement(_isolate, _function.location,
+                            _scripts, _objects, _events,
+                            currentPos: M
+                                .topFrame(isolate.pauseEvent)
+                                .location
+                                .tokenPos,
+                            queue: _r.queue)
+                          ..classes = ['header_inset'])
+                        .element
+                  ]
+                : const [],
+          new HRElement(),
+          new IsolateSharedSummaryElement(_isolate, _events, queue: _r.queue)
+              .element,
+          new HRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'started at',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '${_isolate.startTime}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'uptime',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '$uptime'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'root library',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      _isolate.rootLibrary == null
+                          ? (new SpanElement()..text = 'loading...')
+                          : new LibraryRefElement(
+                                  _isolate, _isolate.rootLibrary,
+                                  queue: _r.queue)
+                              .element
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = _isolate.entry != null
+                    ? [
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text = 'entry',
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..children = <Element>[
+                            new FunctionRefElement(_isolate, _isolate.entry,
+                                    queue: _r.queue)
+                                .element
+                          ]
+                      ]
+                    : const [],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'isolate id',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '${_isolate.number}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'service protocol extensions',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '${_isolate.extensionRPCs}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'allocated zone handle count',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '${_isolate.numZoneHandles}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'allocated scoped handle count',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = '${_isolate.numScopedHandles}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'object store',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      new AnchorElement(href: Uris.objectStore(_isolate))
+                        ..text = 'object store'
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'zone capacity high watermark'
+                    ..title = '''The maximum amount of native zone memory
+                    allocated by the isolate over it\'s life.''',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = Utils.formatSize(_isolate.zoneHighWatermark)
+                    ..title = '${_isolate.zoneHighWatermark}B'
+                ],
+              new BRElement(),
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'libraries (${libraries.length})',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      (new CurlyBlockElement(queue: _r.queue)
+                            ..content = libraries
+                                .map<Element>((l) => new DivElement()
+                                  ..children = <Element>[
+                                    new LibraryRefElement(_isolate, l,
+                                            queue: _r.queue)
+                                        .element
+                                  ])
+                                .toList())
+                          .element
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'threads (${threads.length})',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = <Element>[
+                      (new CurlyBlockElement(queue: _r.queue)
+                            ..content =
+                                threads.map<Element>(_populateThreadInfo))
+                          .element
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new EvalBoxElement(_isolate, _isolate.rootLibrary, _objects, _eval,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..children = _rootScript != null
+                ? [
+                    new HRElement(),
+                    new ScriptInsetElement(
+                            _isolate, _rootScript, _scripts, _objects, _events,
+                            queue: _r.queue)
+                        .element
+                  ]
+                : const [],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  DivElement _populateThreadInfo(M.Thread t) {
+    return new DivElement()
+      ..classes = ['indent']
+      ..children = <Element>[
+        new SpanElement()..text = '${t.id} ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = <Element>[
+                new DivElement()
+                  ..classes = ['indent']
+                  ..text = 'kind ${t.kindString}',
+                new DivElement()
+                  ..classes = ['indent']
+                  ..title = '${t.zoneHighWatermark}B'
+                  ..text = 'zone capacity high watermark '
+                      '${Utils.formatSize(t.zoneHighWatermark)}',
+                new DivElement()
+                  ..classes = ['indent']
+                  ..title = '${t.zoneCapacity}B'
+                  ..text = 'current zone capacity ' +
+                      '${Utils.formatSize(t.zoneCapacity)}',
+              ])
+            .element
+      ];
+  }
+
+  Future _loadExtraData() async {
+    _function = null;
+    _rootScript = null;
+    final frame = M.topFrame(_isolate.pauseEvent);
+    if (frame != null) {
+      _function = await _functions.get(_isolate, frame.function.id);
+    }
+    if (_isolate.rootLibrary != null) {
+      final rootLibrary =
+          await _libraries.get(_isolate, _isolate.rootLibrary.id);
+      _rootScript = rootLibrary.rootScript;
+    }
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/json_view.dart b/runtime/observatory_2/lib/src/elements/json_view.dart
new file mode 100644
index 0000000..f003d60
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/json_view.dart
@@ -0,0 +1,148 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library json_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class JSONViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<JSONViewElement> _r;
+
+  Stream<RenderedEvent<JSONViewElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _notifications;
+  Map _map;
+
+  M.NotificationRepository get notifications => _notifications;
+  Map get map => _map;
+
+  factory JSONViewElement(Map map, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(notifications != null);
+    assert(map != null);
+    JSONViewElement e = new JSONViewElement.created();
+    e._r = new RenderingScheduler<JSONViewElement>(e, queue: queue);
+    e._notifications = notifications;
+    e._map = map;
+    return e;
+  }
+
+  JSONViewElement.created() : super.created('json-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Object',
+          new HRElement(),
+          new PreElement()..text = JSONPretty.stringify(_map),
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
+
+class JSONPretty {
+  JSONPretty._();
+
+  static String stringify(Map map) => new JSONPretty._()._stringify(map);
+
+  String _stringify(Map map) {
+    _buffer.clear();
+    _buffer.write('{\n');
+    _printMap(map, 0);
+    _buffer.write('}\n');
+    return _buffer.toString();
+  }
+
+  void _printMap(Map map, int depth) {
+    if (_seen.contains(map)) {
+      return;
+    }
+    _seen.add(map);
+    for (var k in map.keys) {
+      var v = map[k];
+      if (v is Map) {
+        _writeIndent(depth);
+        _buffer.write('"$k": {\n');
+        _printMap(v, depth + 1);
+        _writeIndent(depth);
+        _buffer.write('}\n');
+      } else if (v is List) {
+        _writeIndent(depth);
+        _buffer.write('"$k": [\n');
+        _printList(v, depth + 1);
+        _writeIndent(depth);
+        _buffer.write(']\n');
+      } else {
+        _writeIndent(depth);
+        _buffer.write('"$k": $v');
+        _buffer.write('\n');
+      }
+    }
+    _seen.remove(map);
+  }
+
+  void _printList(List list, int depth) {
+    if (_seen.contains(list)) {
+      return;
+    }
+    _seen.add(list);
+    for (var v in list) {
+      if (v is Map) {
+        _writeIndent(depth);
+        _buffer.write('{\n');
+        _printMap(v, depth + 1);
+        _writeIndent(depth);
+        _buffer.write('}\n');
+      } else if (v is List) {
+        _writeIndent(depth);
+        _buffer.write('[\n');
+        _printList(v, depth + 1);
+        _writeIndent(depth);
+        _buffer.write(']\n');
+      } else {
+        _writeIndent(depth);
+        _buffer.write(v);
+        _buffer.write('\n');
+      }
+    }
+    _seen.remove(list);
+  }
+
+  void _writeIndent(int depth) {
+    const tab = '  '; // 2 spaces.
+    _buffer.write(tab * depth);
+  }
+
+  final _buffer = new StringBuffer();
+  final _seen = new Set();
+}
diff --git a/runtime/observatory_2/lib/src/elements/library_ref.dart b/runtime/observatory_2/lib/src/elements/library_ref.dart
new file mode 100644
index 0000000..83d58cc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/library_ref.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library library_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, LibraryRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class LibraryRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<LibraryRefElement> _r;
+
+  Stream<RenderedEvent<LibraryRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.LibraryRef _library;
+
+  M.IsolateRef get isolate => _isolate;
+  M.LibraryRef get library => _library;
+
+  factory LibraryRefElement(M.IsolateRef isolate, M.LibraryRef library,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(library != null);
+    LibraryRefElement e = new LibraryRefElement.created();
+    e._r = new RenderingScheduler<LibraryRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._library = library;
+    return e;
+  }
+
+  LibraryRefElement.created() : super.created('library-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final name = _library.name;
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _library))
+        ..text = (name == null || name.isEmpty) ? 'unnamed' : name
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/library_view.dart b/runtime/observatory_2/lib/src/elements/library_view.dart
new file mode 100644
index 0000000..b1c9656
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/library_view.dart
@@ -0,0 +1,333 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library library_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/eval_box.dart';
+import 'package:observatory_2/src/elements/field_ref.dart';
+import 'package:observatory_2/src/elements/function_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/library_ref.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/library_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/script_ref.dart';
+import 'package:observatory_2/src/elements/script_inset.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class LibraryViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<LibraryViewElement> _r;
+
+  Stream<RenderedEvent<LibraryViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Library _library;
+  M.LibraryRepository _libraries;
+  M.FieldRepository _fields;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+  M.EvalRepository _eval;
+  Iterable<M.Field> _variables;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Library get library => _library;
+
+  factory LibraryViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Library library,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.LibraryRepository libraries,
+      M.FieldRepository fields,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      M.EvalRepository eval,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(library != null);
+    assert(libraries != null);
+    assert(fields != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(scripts != null);
+    assert(objects != null);
+    assert(eval != null);
+    LibraryViewElement e = new LibraryViewElement.created();
+    e._r = new RenderingScheduler<LibraryViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._library = library;
+    e._libraries = libraries;
+    e._fields = fields;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._scripts = scripts;
+    e._objects = objects;
+    e._eval = eval;
+    return e;
+  }
+
+  LibraryViewElement.created() : super.created('library-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final rootScript = library.rootScript;
+
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavLibraryMenuElement(_isolate, _library, queue: _r.queue).element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Library',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _library, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'uri',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = _library.uri
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'vm name',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = _library.vmName
+                ]
+            ],
+          new HRElement(),
+          new EvalBoxElement(_isolate, _library, _objects, _eval,
+                  queue: _r.queue)
+              .element,
+          new HRElement(),
+          _createDependencies(),
+          new BRElement(),
+          _createScripts(),
+          new BRElement(),
+          _createClasses(),
+          new BRElement(),
+          _createVariables(),
+          new BRElement(),
+          _createFunctions(),
+          if (rootScript != null) ...[
+            new HRElement(),
+            new ScriptInsetElement(
+                    _isolate, rootScript, _scripts, _objects, _events,
+                    queue: _r.queue)
+                .element
+          ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  Future _refresh() async {
+    _library = await _libraries.get(_isolate, _library.id);
+    _variables = null;
+    _r.dirty();
+    _variables = await Future.wait(
+        _library.variables.map((field) => _fields.get(_isolate, field.id)));
+    _r.dirty();
+  }
+
+  Element _createDependencies() {
+    if (_library.dependencies.isEmpty) {
+      return new SpanElement();
+    }
+    final dependencies = _library.dependencies.toList();
+    return new DivElement()
+      ..children = <Element>[
+        new SpanElement()..text = 'dependencies (${dependencies.length}) ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = dependencies
+                  .map<Element>((d) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new SpanElement()
+                        ..text = d.isImport ? 'import ' : 'export ',
+                      new LibraryRefElement(_isolate, d.target, queue: _r.queue)
+                          .element,
+                      new SpanElement()
+                        ..text = d.prefix == null ? '' : ' as ${d.prefix}',
+                      new SpanElement()..text = d.isDeferred ? ' deferred' : '',
+                    ])
+                  .toList())
+            .element
+      ];
+  }
+
+  Element _createScripts() {
+    if (_library.scripts.isEmpty) {
+      return new SpanElement();
+    }
+    final scripts = _library.scripts.toList();
+    return new DivElement()
+      ..children = <Element>[
+        new SpanElement()..text = 'scripts (${scripts.length}) ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = scripts
+                  .map<Element>((s) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new ScriptRefElement(_isolate, s, queue: _r.queue).element
+                    ])
+                  .toList())
+            .element
+      ];
+  }
+
+  Element _createClasses() {
+    if (_library.classes.isEmpty) {
+      return new SpanElement();
+    }
+    final classes = _library.classes.toList();
+    return new DivElement()
+      ..children = <Element>[
+        new SpanElement()..text = 'classes (${classes.length}) ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = classes
+                  .map<Element>((c) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new ClassRefElement(_isolate, c, queue: _r.queue).element
+                    ])
+                  .toList())
+            .element
+      ];
+  }
+
+  Element _createVariables() {
+    if (_library.variables.isEmpty) {
+      return new SpanElement();
+    }
+    final variables = _library.variables.toList();
+    return new DivElement()
+      ..children = <Element>[
+        new SpanElement()..text = 'variables (${variables.length}) ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = <Element>[
+                _variables == null
+                    ? (new SpanElement()..text = 'loading...')
+                    : (new DivElement()
+                      ..classes = ['indent', 'memberList']
+                      ..children = _variables
+                          .map<Element>((f) => new DivElement()
+                            ..classes = ['memberItem']
+                            ..children = <Element>[
+                              new DivElement()
+                                ..classes = ['memberName']
+                                ..children = <Element>[
+                                  new FieldRefElement(_isolate, f, _objects,
+                                          queue: _r.queue)
+                                      .element
+                                ],
+                              new DivElement()
+                                ..classes = ['memberValue']
+                                ..children = <Element>[
+                                  new SpanElement()..text = ' = ',
+                                  anyRef(_isolate, f.staticValue, _objects,
+                                      queue: _r.queue)
+                                ]
+                            ])
+                          .toList())
+              ])
+            .element
+      ];
+  }
+
+  Element _createFunctions() {
+    if (_library.functions.isEmpty) {
+      return new SpanElement();
+    }
+    final functions = _library.functions.toList();
+    return new DivElement()
+      ..children = <Element>[
+        new SpanElement()..text = 'functions (${functions.length}) ',
+        (new CurlyBlockElement(queue: _r.queue)
+              ..content = functions
+                  .map<Element>((f) => new DivElement()
+                    ..classes = ['indent']
+                    ..children = <Element>[
+                      new FunctionRefElement(_isolate, f, queue: _r.queue)
+                          .element
+                    ])
+                  .toList())
+            .element
+      ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/local_var_descriptors_ref.dart b/runtime/observatory_2/lib/src/elements/local_var_descriptors_ref.dart
new file mode 100644
index 0000000..7bf512a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/local_var_descriptors_ref.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, LocalVarDescriptorsRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class LocalVarDescriptorsRefElement extends CustomElement
+    implements Renderable {
+  RenderingScheduler<LocalVarDescriptorsRefElement> _r;
+
+  Stream<RenderedEvent<LocalVarDescriptorsRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.LocalVarDescriptorsRef _localVar;
+
+  M.IsolateRef get isolate => _isolate;
+  M.LocalVarDescriptorsRef get localVar => _localVar;
+
+  factory LocalVarDescriptorsRefElement(
+      M.IsolateRef isolate, M.LocalVarDescriptorsRef localVar,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(localVar != null);
+    LocalVarDescriptorsRefElement e =
+        new LocalVarDescriptorsRefElement.created();
+    e._r =
+        new RenderingScheduler<LocalVarDescriptorsRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._localVar = localVar;
+    return e;
+  }
+
+  LocalVarDescriptorsRefElement.created() : super.created('var-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final text = (_localVar.name == null || _localVar.name == '')
+        ? 'LocalVarDescriptors'
+        : _localVar.name;
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _localVar))
+        ..text = text
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/logging.dart b/runtime/observatory_2/lib/src/elements/logging.dart
new file mode 100644
index 0000000..dd922a2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/logging.dart
@@ -0,0 +1,115 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library logging_page;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/logging_list.dart';
+import 'package:observatory_2/src/elements/nav/class_menu.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class LoggingPageElement extends CustomElement implements Renderable {
+  RenderingScheduler<LoggingPageElement> _r;
+
+  Stream<RenderedEvent<LoggingPageElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  Level _level = Level.ALL;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory LoggingPageElement(M.VM vm, M.IsolateRef isolate,
+      M.EventRepository events, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    LoggingPageElement e = new LoggingPageElement.created();
+    e._r = new RenderingScheduler<LoggingPageElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    return e;
+  }
+
+  LoggingPageElement.created() : super.created('logging-page');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  LoggingListElement _logs;
+
+  void render() {
+    _logs = _logs ?? new LoggingListElement(_isolate, _events);
+    _logs.level = _level;
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('logging'),
+        (new NavRefreshElement(label: 'clear', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _logs = null;
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Logging',
+          new SpanElement()..text = 'Show messages with severity ',
+          _createLevelSelector(),
+          new HRElement(),
+          _logs.element
+        ]
+    ];
+  }
+
+  Element _createLevelSelector() {
+    var s = new SelectElement()
+      ..value = _level.name
+      ..children = Level.LEVELS.map((level) {
+        return new OptionElement(value: level.name, selected: _level == level)
+          ..text = level.name;
+      }).toList(growable: false);
+    s.onChange.listen((_) {
+      _level = Level.LEVELS[s.selectedIndex];
+      _r.dirty();
+    });
+    return s;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/logging_list.dart b/runtime/observatory_2/lib/src/elements/logging_list.dart
new file mode 100644
index 0000000..bb160964
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/logging_list.dart
@@ -0,0 +1,84 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/utils.dart';
+
+class LoggingListElement extends CustomElement implements Renderable {
+  RenderingScheduler<LoggingListElement> _r;
+
+  Stream<RenderedEvent<LoggingListElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  StreamSubscription _subscription;
+  Level _level = Level.ALL;
+  final _logs = <Map>[];
+
+  M.IsolateRef get isolate => _isolate;
+  Level get level => _level;
+
+  set level(Level value) => _level = _r.checkAndReact(_level, value);
+
+  factory LoggingListElement(M.IsolateRef isolate, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    LoggingListElement e = new LoggingListElement.created();
+    e._r = new RenderingScheduler<LoggingListElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    return e;
+  }
+
+  LoggingListElement.created() : super.created('logging-list');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _subscription = _events.onLoggingEvent.listen((e) {
+      if (e.isolate.id == _isolate.id) {
+        _logs.add(e.logRecord);
+        if (_shouldBeVisible(_logs.last)) {
+          _r.dirty();
+        }
+      }
+    });
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _subscription.cancel();
+  }
+
+  void render() {
+    children = _logs
+        .where(_shouldBeVisible)
+        .map<Element>((logRecord) => new DivElement()
+          ..classes = ['logItem', logRecord['level'].name]
+          ..children = <Element>[
+            new SpanElement()
+              ..classes = ['level']
+              ..text = logRecord['level'].name,
+            new SpanElement()
+              ..classes = ['time']
+              ..text = Utils.formatDateTime(logRecord['time']),
+            new SpanElement()
+              ..classes = ['message']
+              ..text = logRecord["message"].valueAsString
+          ])
+        .toList();
+  }
+
+  bool _shouldBeVisible(Map record) => _level.compareTo(record['level']) <= 0;
+}
diff --git a/runtime/observatory_2/lib/src/elements/megamorphiccache_ref.dart b/runtime/observatory_2/lib/src/elements/megamorphiccache_ref.dart
new file mode 100644
index 0000000..f38b59a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/megamorphiccache_ref.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, MegamorphicCacheRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class MegamorphicCacheRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<MegamorphicCacheRefElement> _r;
+
+  Stream<RenderedEvent<MegamorphicCacheRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.MegamorphicCacheRef _cache;
+
+  M.IsolateRef get isolate => _isolate;
+  M.MegamorphicCacheRef get cache => _cache;
+
+  factory MegamorphicCacheRefElement(
+      M.IsolateRef isolate, M.MegamorphicCacheRef cache,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cache != null);
+    MegamorphicCacheRefElement e = new MegamorphicCacheRefElement.created();
+    e._r = new RenderingScheduler<MegamorphicCacheRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._cache = cache;
+    return e;
+  }
+
+  MegamorphicCacheRefElement.created() : super.created('megamorphic-cache-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _cache))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'MegarmorphicCache',
+          new SpanElement()..text = ' (${_cache.selector})'
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/megamorphiccache_view.dart b/runtime/observatory_2/lib/src/elements/megamorphiccache_view.dart
new file mode 100644
index 0000000..71bb435
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/megamorphiccache_view.dart
@@ -0,0 +1,185 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library megamorphiccache_view;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class MegamorphicCacheViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<MegamorphicCacheViewElement> _r;
+
+  Stream<RenderedEvent<MegamorphicCacheViewElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.MegamorphicCache _cache;
+  M.MegamorphicCacheRepository _caches;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.MegamorphicCache get cache => _cache;
+
+  factory MegamorphicCacheViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.MegamorphicCache cache,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.MegamorphicCacheRepository caches,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(cache != null);
+    assert(caches != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    MegamorphicCacheViewElement e = new MegamorphicCacheViewElement.created();
+    e._r = new RenderingScheduler<MegamorphicCacheViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._cache = cache;
+    e._caches = caches;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  MegamorphicCacheViewElement.created()
+      : super.created('megamorphiccache-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('megamorphic inline cache'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _cache = await _caches.get(_isolate, _cache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Megamorphic Cache',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _cache, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'selector',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = '${_cache.selector}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'mask',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = '${_cache.mask}'
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'buckets',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      anyRef(_isolate, _cache.buckets, _objects,
+                          queue: _r.queue)
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'argumentsDescriptor',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      anyRef(_isolate, _cache.argumentsDescriptor, _objects,
+                          queue: _r.queue)
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/metric/details.dart b/runtime/observatory_2/lib/src/elements/metric/details.dart
new file mode 100644
index 0000000..b2d4eb2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/metric/details.dart
@@ -0,0 +1,168 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class MetricDetailsElement extends CustomElement implements Renderable {
+  RenderingScheduler<MetricDetailsElement> _r;
+
+  Stream<RenderedEvent<MetricDetailsElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.Metric _metric;
+  M.MetricRepository _metrics;
+
+  M.IsolateRef get isolate => _isolate;
+  M.Metric get metric => _metric;
+
+  factory MetricDetailsElement(
+      M.IsolateRef isolate, M.Metric metric, M.MetricRepository metrics,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(metric != null);
+    assert(metrics != null);
+    MetricDetailsElement e = new MetricDetailsElement.created();
+    e._r = new RenderingScheduler<MetricDetailsElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._metric = metric;
+    e._metrics = metrics;
+    return e;
+  }
+
+  MetricDetailsElement.created() : super.created('metric-details');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'name',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..text = _metric.name,
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'description',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..text = _metric.description,
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'refresh rate',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createRefreshRateSelect(),
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'buffer size',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createBufferSizeSelect(),
+            ]
+        ]
+    ];
+  }
+
+  List<Element> _createRefreshRateSelect() {
+    final current = _metrics.getSamplingRate(_isolate, _metric);
+    var s;
+    return [
+      s = new SelectElement()
+        ..value = _rateToString(current)
+        ..children = M.MetricSamplingRate.values.map((rate) {
+          return new OptionElement(
+              value: _rateToString(current), selected: current == rate)
+            ..text = _rateToString(rate);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _metrics.setSamplingRate(
+              _isolate, _metric, M.MetricSamplingRate.values[s.selectedIndex]);
+          _r.dirty();
+        })
+    ];
+  }
+
+  List<Element> _createBufferSizeSelect() {
+    final current = _metrics.getBufferSize(_isolate, _metric);
+    var s;
+    return [
+      s = new SelectElement()
+        ..value = _sizeToString(current)
+        ..children = M.MetricBufferSize.values.map((rate) {
+          return new OptionElement(
+              value: _sizeToString(current), selected: current == rate)
+            ..text = _sizeToString(rate);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _metrics.setBufferSize(
+              _isolate, _metric, M.MetricBufferSize.values[s.selectedIndex]);
+          _r.dirty();
+        })
+    ];
+  }
+
+  static String _rateToString(M.MetricSamplingRate rate) {
+    switch (rate) {
+      case M.MetricSamplingRate.off:
+        return 'Never';
+      case M.MetricSamplingRate.e100ms:
+        return 'Ten times per second';
+      case M.MetricSamplingRate.e1s:
+        return 'Once a second';
+      case M.MetricSamplingRate.e2s:
+        return 'Every two seconds';
+      case M.MetricSamplingRate.e4s:
+        return 'Every four seconds';
+      case M.MetricSamplingRate.e8s:
+        return 'Every eight seconds';
+    }
+    throw new Exception('Unknown MetricSamplingRate ($rate)');
+  }
+
+  static String _sizeToString(M.MetricBufferSize size) {
+    switch (size) {
+      case M.MetricBufferSize.n10samples:
+        return '10';
+      case M.MetricBufferSize.n100samples:
+        return '100';
+      case M.MetricBufferSize.n1000samples:
+        return '1000';
+    }
+    throw new Exception('Unknown MetricSamplingRate ($size)');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/metric/graph.dart b/runtime/observatory_2/lib/src/elements/metric/graph.dart
new file mode 100644
index 0000000..4120020
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/metric/graph.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class MetricGraphElement extends CustomElement implements Renderable {
+  RenderingScheduler<MetricGraphElement> _r;
+
+  Stream<RenderedEvent<MetricGraphElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.Metric _metric;
+  M.MetricRepository _metrics;
+  Timer _timer;
+
+  M.IsolateRef get isolate => _isolate;
+  M.Metric get metric => _metric;
+
+  factory MetricGraphElement(
+      M.IsolateRef isolate, M.Metric metric, M.MetricRepository metrics,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(metric != null);
+    assert(metrics != null);
+    MetricGraphElement e = new MetricGraphElement.created();
+    e._r = new RenderingScheduler<MetricGraphElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._metric = metric;
+    e._metrics = metrics;
+    return e;
+  }
+
+  MetricGraphElement.created() : super.created('metric-graph');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _timer = new Timer.periodic(const Duration(seconds: 1), (_) => _r.dirty());
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _timer.cancel();
+  }
+
+  void render() {
+    final min = _metrics.getMinValue(_isolate, _metric);
+    final max = _metrics.getMaxValue(_isolate, _metric);
+    final rows = _metrics
+        .getSamples(_isolate, _metric)
+        .map((s) => [s.time.millisecondsSinceEpoch, s.value])
+        .toList();
+    final current = rows.last.last;
+
+    var message = 'current: $current';
+    if (min != null) {
+      message = 'min: $min, $message';
+    }
+    if (max != null) {
+      message = message + ', max: $max';
+    }
+
+    final host = new DivElement();
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = min == null
+                ? const []
+                : [
+                    new DivElement()
+                      ..classes = ['memberName']
+                      ..text = 'min',
+                    new DivElement()
+                      ..classes = ['memberValue']
+                      ..text = '$min'
+                  ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'current',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..text = '$current'
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = max == null
+                ? const []
+                : [
+                    new DivElement()
+                      ..classes = ['memberName']
+                      ..text = 'max',
+                    new DivElement()
+                      ..classes = ['memberValue']
+                      ..text = '$max'
+                  ]
+        ],
+    ];
+    if (rows.length <= 1) {
+      return;
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/metrics.dart b/runtime/observatory_2/lib/src/elements/metrics.dart
new file mode 100644
index 0000000..b75d7ca
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/metrics.dart
@@ -0,0 +1,159 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library metrics;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/metric/details.dart';
+import 'package:observatory_2/src/elements/metric/graph.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+
+class MetricsPageElement extends CustomElement implements Renderable {
+  RenderingScheduler<MetricsPageElement> _r;
+
+  Stream<RenderedEvent<MetricsPageElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.MetricRepository _metrics;
+  List<M.Metric> _available;
+  M.Metric _selected;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory MetricsPageElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.MetricRepository metrics,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    MetricsPageElement e = new MetricsPageElement.created();
+    e._r = new RenderingScheduler<MetricsPageElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._metrics = metrics;
+    return e;
+  }
+
+  MetricsPageElement.created() : super.created('metrics-page');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('metrics'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) {
+                e.element.disabled = true;
+                _refresh();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Metrics',
+          new HRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Metric',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = _available == null
+                        ? [new SpanElement()..text = 'Loading..']
+                        : _createMetricSelect()
+                ]
+            ],
+          new HRElement(),
+          new DivElement()
+            ..children = _selected == null
+                ? const []
+                : [
+                    new MetricDetailsElement(_isolate, _selected, _metrics,
+                            queue: _r.queue)
+                        .element
+                  ],
+          new HRElement(),
+          new DivElement()
+            ..classes = ['graph']
+            ..children = _selected == null
+                ? const []
+                : [
+                    new MetricGraphElement(_isolate, _selected, _metrics,
+                            queue: _r.queue)
+                        .element
+                  ]
+        ],
+    ];
+  }
+
+  Future _refresh() async {
+    _available = (await _metrics.list(_isolate)).toList();
+    if (!_available.contains(_selected)) {
+      _selected = _available.first;
+    }
+    _r.dirty();
+  }
+
+  List<Element> _createMetricSelect() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..value = _selected.name
+        ..children = _available.map((metric) {
+          return new OptionElement(
+              value: metric.name, selected: _selected == metric)
+            ..text = metric.name;
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _selected = _available[s.selectedIndex];
+          _r.dirty();
+        })
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/native_memory_profiler.dart b/runtime/observatory_2/lib/src/elements/native_memory_profiler.dart
new file mode 100644
index 0000000..5eae524
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/native_memory_profiler.dart
@@ -0,0 +1,157 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library native_memory_profile;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/cpu_profile/virtual_tree.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/sample_buffer_control.dart';
+import 'package:observatory_2/src/elements/stack_trace_tree_config.dart';
+
+class NativeMemoryProfileElement extends CustomElement implements Renderable {
+  RenderingScheduler<NativeMemoryProfileElement> _r;
+
+  Stream<RenderedEvent<NativeMemoryProfileElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.NativeMemorySampleProfileRepository _profiles;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag = M.SampleProfileTag.none;
+  ProfileTreeMode _mode = ProfileTreeMode.function;
+  M.ProfileTreeDirection _direction = M.ProfileTreeDirection.exclusive;
+  String _filter = '';
+
+  M.NotificationRepository get notifications => _notifications;
+  M.NativeMemorySampleProfileRepository get profiles => _profiles;
+
+  factory NativeMemoryProfileElement(
+      M.VM vm,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.NativeMemorySampleProfileRepository profiles,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(profiles != null);
+    NativeMemoryProfileElement e = new NativeMemoryProfileElement.created();
+    e._r = new RenderingScheduler<NativeMemoryProfileElement>(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    e._notifications = notifications;
+    e._profiles = profiles;
+    return e;
+  }
+
+  NativeMemoryProfileElement.created() : super.created('native-memory-profile');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _request();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    var content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        navMenu('native memory profile', link: Uris.nativeMemory()),
+        (new NavRefreshElement(queue: _r.queue)..onRefresh.listen(_refresh))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+    ];
+    if (_progress == null) {
+      children = content;
+      return;
+    }
+    content.add((new SampleBufferControlElement(_vm, _progress, _progressStream,
+            selectedTag: _tag, queue: _r.queue)
+          ..onTagChange.listen((e) {
+            _tag = e.element.selectedTag;
+            _request();
+          }))
+        .element);
+    if (_progress.status == M.SampleProfileLoadingStatus.loaded) {
+      CpuProfileVirtualTreeElement tree;
+      content.addAll([
+        new BRElement(),
+        (new StackTraceTreeConfigElement(
+                mode: _mode,
+                direction: _direction,
+                filter: _filter,
+                queue: _r.queue)
+              ..onModeChange.listen((e) {
+                _mode = tree.mode = e.element.mode;
+              })
+              ..onFilterChange.listen((e) {
+                _filter = e.element.filter.trim();
+                tree.filters = _filter.isNotEmpty
+                    ? [
+                        (node) {
+                          return node.name.contains(_filter);
+                        }
+                      ]
+                    : const [];
+              })
+              ..onDirectionChange.listen((e) {
+                _direction = tree.direction = e.element.direction;
+              }))
+            .element,
+        new BRElement(),
+        (tree = new CpuProfileVirtualTreeElement(null, _progress.profile,
+                queue: _r.queue, type: M.SampleProfileType.memory))
+            .element,
+      ]);
+    }
+    children = content;
+  }
+
+  Future _request({bool forceFetch: false}) async {
+    if (forceFetch) {
+      for (M.Isolate isolate in _vm.isolates) {
+        await isolate.collectAllGarbage();
+      }
+    }
+    _progress = null;
+    _progressStream = _profiles.get(_vm, _tag, forceFetch: forceFetch);
+    _r.dirty();
+    _progress = (await _progressStream.first).progress;
+    _r.dirty();
+    if (M.isSampleProcessRunning(_progress.status)) {
+      _progress = (await _progressStream.last).progress;
+      _r.dirty();
+    }
+  }
+
+  Future _refresh(e) async {
+    e.element.disabled = true;
+    await _request(forceFetch: true);
+    e.element.disabled = false;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/class_menu.dart b/runtime/observatory_2/lib/src/elements/nav/class_menu.dart
new file mode 100644
index 0000000..3198130
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/class_menu.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, ClassRef;
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class NavClassMenuElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavClassMenuElement> _r;
+
+  Stream<RenderedEvent<NavClassMenuElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ClassRef _cls;
+  Iterable<Element> _content = const [];
+
+  M.IsolateRef get isolate => _isolate;
+  M.ClassRef get cls => _cls;
+  Iterable<Element> get content => _content;
+
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavClassMenuElement(M.IsolateRef isolate, M.ClassRef cls,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cls != null);
+    NavClassMenuElement e = new NavClassMenuElement.created();
+    e._r = new RenderingScheduler<NavClassMenuElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._cls = cls;
+    return e;
+  }
+
+  NavClassMenuElement.created() : super.created('nav-class-menu');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      navMenu(cls.name,
+          content: _content, link: Uris.inspect(isolate, object: cls))
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/isolate_menu.dart b/runtime/observatory_2/lib/src/elements/nav/isolate_menu.dart
new file mode 100644
index 0000000..f2de56d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/isolate_menu.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, EventRepository;
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/menu_item.dart';
+
+class NavIsolateMenuElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavIsolateMenuElement> _r;
+
+  Stream<RenderedEvent<NavIsolateMenuElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  StreamSubscription _updatesSubscription;
+  Iterable<Element> _content = const [];
+
+  M.IsolateRef get isolate => _isolate;
+  Iterable<Element> get content => _content;
+
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavIsolateMenuElement(M.IsolateRef isolate, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(events != null);
+    NavIsolateMenuElement e = new NavIsolateMenuElement.created();
+    e._r = new RenderingScheduler<NavIsolateMenuElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._events = events;
+    return e;
+  }
+
+  NavIsolateMenuElement.created() : super.created('nav-isolate-menu');
+
+  @override
+  void attached() {
+    super.attached();
+    _updatesSubscription = _events.onIsolateUpdate
+        .where((e) => e.isolate.id == isolate.id)
+        .listen((e) {
+      _isolate = e.isolate;
+      _r.dirty();
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    assert(_updatesSubscription != null);
+    _updatesSubscription.cancel();
+    _updatesSubscription = null;
+  }
+
+  void render() {
+    final content = <Element>[
+      new NavMenuItemElement('debugger',
+              queue: _r.queue, link: Uris.debugger(isolate))
+          .element,
+      new NavMenuItemElement('class hierarchy',
+              queue: _r.queue, link: Uris.classTree(isolate))
+          .element,
+      new NavMenuItemElement('cpu profile',
+              queue: _r.queue, link: Uris.cpuProfiler(isolate))
+          .element,
+      new NavMenuItemElement('cpu profile (table)',
+              queue: _r.queue, link: Uris.cpuProfilerTable(isolate))
+          .element,
+      new NavMenuItemElement('allocation profile',
+              queue: _r.queue, link: Uris.allocationProfiler(isolate))
+          .element,
+      new NavMenuItemElement('heap snapshot',
+              queue: _r.queue, link: Uris.heapSnapshot(isolate))
+          .element,
+      new NavMenuItemElement('heap map',
+              queue: _r.queue, link: Uris.heapMap(isolate))
+          .element,
+      new NavMenuItemElement('metrics',
+              queue: _r.queue, link: Uris.metrics(isolate))
+          .element,
+      new NavMenuItemElement('persistent handles',
+              queue: _r.queue, link: Uris.persistentHandles(isolate))
+          .element,
+      new NavMenuItemElement('ports',
+              queue: _r.queue, link: Uris.ports(isolate))
+          .element,
+      new NavMenuItemElement('logging',
+              queue: _r.queue, link: Uris.logging(isolate))
+          .element,
+    ]..addAll(_content);
+    children = <Element>[
+      navMenu(isolate.name, content: content, link: Uris.inspect(isolate))
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/library_menu.dart b/runtime/observatory_2/lib/src/elements/nav/library_menu.dart
new file mode 100644
index 0000000..83208cc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/library_menu.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, LibraryRef;
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class NavLibraryMenuElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavLibraryMenuElement> _r;
+
+  Stream<RenderedEvent<NavLibraryMenuElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.LibraryRef _library;
+  Iterable<Element> _content = const [];
+
+  M.IsolateRef get isolate => _isolate;
+  M.LibraryRef get library => _library;
+  Iterable<Element> get content => _content;
+
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavLibraryMenuElement(M.IsolateRef isolate, M.LibraryRef library,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(library != null);
+    NavLibraryMenuElement e = new NavLibraryMenuElement.created();
+    e._r = new RenderingScheduler<NavLibraryMenuElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._library = library;
+    return e;
+  }
+
+  NavLibraryMenuElement.created() : super.created('nav-library-menu');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      navMenu(library.name,
+          content: _content,
+          link: Uris.inspect(isolate, object: library).toString())
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/menu_item.dart b/runtime/observatory_2/lib/src/elements/nav/menu_item.dart
new file mode 100644
index 0000000..6350335
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/menu_item.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class NavMenuItemElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavMenuItemElement> _r;
+
+  Stream<RenderedEvent<NavMenuItemElement>> get onRendered => _r.onRendered;
+
+  String _label;
+  String _link;
+  Iterable<Element> _content = const <Element>[];
+
+  String get label => _label;
+  String get link => _link;
+  Iterable<Element> get content => _content;
+
+  set label(String value) => _label = _r.checkAndReact(_label, value);
+  set link(String value) => _link = _r.checkAndReact(_link, value);
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavMenuItemElement(String label,
+      {String link, RenderingQueue queue}) {
+    assert(label != null);
+    NavMenuItemElement e = new NavMenuItemElement.created();
+    e._r = new RenderingScheduler<NavMenuItemElement>(e, queue: queue);
+    e._label = label;
+    e._link = link;
+    return e;
+  }
+
+  NavMenuItemElement.created() : super.created('nav-menu-item');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new LIElement()
+        ..classes = ['nav-menu-item']
+        ..children = <Element>[
+          new AnchorElement(href: link)..text = label,
+          new UListElement()..children = _content
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/notify.dart b/runtime/observatory_2/lib/src/elements/nav/notify.dart
new file mode 100644
index 0000000..ba57035
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/notify.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/nav/notify_event.dart';
+import 'package:observatory_2/src/elements/nav/notify_exception.dart';
+
+class NavNotifyElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavNotifyElement> _r;
+
+  Stream<RenderedEvent<NavNotifyElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _repository;
+  StreamSubscription _subscription;
+
+  bool _notifyOnPause;
+
+  bool get notifyOnPause => _notifyOnPause;
+
+  set notifyOnPause(bool value) =>
+      _notifyOnPause = _r.checkAndReact(_notifyOnPause, value);
+
+  factory NavNotifyElement(M.NotificationRepository repository,
+      {bool notifyOnPause: true, RenderingQueue queue}) {
+    assert(repository != null);
+    assert(notifyOnPause != null);
+    NavNotifyElement e = new NavNotifyElement.created();
+    e._r = new RenderingScheduler<NavNotifyElement>(e, queue: queue);
+    e._repository = repository;
+    e._notifyOnPause = notifyOnPause;
+    return e;
+  }
+
+  NavNotifyElement.created() : super.created('nav-notify');
+
+  @override
+  void attached() {
+    super.attached();
+    _subscription = _repository.onChange.listen((_) => _r.dirty());
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    children = <Element>[
+      new DivElement()
+        ..children = <Element>[
+          new DivElement()
+            ..children = _repository
+                .list()
+                .where(_filter)
+                .map<Element>(_toElement)
+                .toList()
+        ]
+    ];
+  }
+
+  bool _filter(M.Notification notification) {
+    if (!_notifyOnPause && notification is M.EventNotification) {
+      return notification.event is! M.PauseEvent;
+    }
+    return true;
+  }
+
+  Element _toElement(M.Notification notification) {
+    if (notification is M.EventNotification) {
+      return (new NavNotifyEventElement(notification.event, queue: _r.queue)
+            ..onDelete.listen((_) => _repository.delete(notification)))
+          .element;
+    } else if (notification is M.ExceptionNotification) {
+      return (new NavNotifyExceptionElement(notification.exception,
+              stacktrace: notification.stacktrace, queue: _r.queue)
+            ..onDelete.listen((_) => _repository.delete(notification)))
+          .element;
+    } else {
+      assert(false);
+      return new DivElement()..text = 'Invalid Notification Type';
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/notify_event.dart b/runtime/observatory_2/lib/src/elements/nav/notify_event.dart
new file mode 100644
index 0000000..3c8308b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/notify_event.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class EventDeleteEvent {
+  final M.Event event;
+  EventDeleteEvent(this.event);
+}
+
+class NavNotifyEventElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavNotifyEventElement> _r;
+
+  Stream<RenderedEvent<NavNotifyEventElement>> get onRendered => _r.onRendered;
+
+  final StreamController<EventDeleteEvent> _onDelete =
+      new StreamController<EventDeleteEvent>.broadcast();
+  Stream<EventDeleteEvent> get onDelete => _onDelete.stream;
+
+  M.Event _event;
+
+  M.Event get event => _event;
+
+  factory NavNotifyEventElement(M.Event event, {RenderingQueue queue}) {
+    assert(event != null);
+    NavNotifyEventElement e = new NavNotifyEventElement.created();
+    e._r = new RenderingScheduler<NavNotifyEventElement>(e, queue: queue);
+    e._event = event;
+    return e;
+  }
+
+  NavNotifyEventElement.created() : super.created('nav-event');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[];
+    List<Element> content;
+    if (event is M.PauseStartEvent) {
+      content = _managePauseStartEvent(event as M.PauseStartEvent);
+    } else if (event is M.PauseExitEvent) {
+      content = _managePauseExitEvent(event as M.PauseExitEvent);
+    } else if (event is M.PauseBreakpointEvent) {
+      content = _managePauseBreakpointEvent(event as M.PauseBreakpointEvent);
+    } else if (event is M.PauseInterruptedEvent) {
+      content = _managePauseInterruptedEvent(event as M.PauseInterruptedEvent);
+    } else if (event is M.PauseExceptionEvent) {
+      content = _managePauseExceptionEvent(event as M.PauseExceptionEvent);
+    } else if (event is M.NoneEvent) {
+      content = _manageNoneEvent(event as M.NoneEvent);
+    } else if (event is M.ConnectionClosedEvent) {
+      content = _manageConnectionClosedEvent(event as M.ConnectionClosedEvent);
+    } else if (event is M.InspectEvent) {
+      content = _manageInspectEvent(event as M.InspectEvent);
+    } else if (event is M.IsolateReloadEvent) {
+      content = _manageIsolateReloadEvent(event as M.IsolateReloadEvent);
+    } else {
+      return;
+    }
+    children = <Element>[
+      new DivElement()
+        ..children = <Element>[]
+        ..children.addAll(content)
+        ..children.add(new ButtonElement()
+          ..innerHtml = '&times;'
+          ..onClick.map(_toEvent).listen(_delete))
+    ];
+  }
+
+  static List<Element> _managePauseStartEvent(M.PauseStartEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused at isolate start',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseExitEvent(M.PauseExitEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused at isolate exit',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseBreakpointEvent(
+      M.PauseBreakpointEvent event) {
+    String message = ' is paused';
+    if (event.breakpoint != null) {
+      message += ' at breakpoint ${event.breakpoint.number}';
+    }
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = message,
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseInterruptedEvent(
+      M.PauseInterruptedEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _managePauseExceptionEvent(M.PauseExceptionEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused due to exception',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageNoneEvent(M.NoneEvent event) {
+    return [
+      new SpanElement()..text = 'Isolate ',
+      new AnchorElement(href: Uris.inspect(event.isolate))
+        ..text = event.isolate.name,
+      new SpanElement()..text = ' is paused',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.debugger(event.isolate))..text = 'debug',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageConnectionClosedEvent(
+      M.ConnectionClosedEvent event) {
+    return [
+      new SpanElement()..text = 'Disconnected from VM: ${event.reason}',
+      new BRElement(),
+      new BRElement(),
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.vmConnect())..text = 'Connect to a VM',
+      new SpanElement()..text = ']'
+    ];
+  }
+
+  static List<Element> _manageInspectEvent(M.InspectEvent event) {
+    return [
+      new SpanElement()..text = 'Inspect ${event.inspectee.id}',
+      new BRElement(), new BRElement(), new SpanElement()..text = '[',
+      new AnchorElement(
+          href: Uris.inspect(event.isolate, object: event.inspectee))
+        ..text = 'Inspect',
+      new SpanElement()..text = ']'
+      // TODO(cbernaschina) add InstanceRefElement back.
+      //new InstanceRefElement()..instance = event.inspectee
+    ];
+  }
+
+  static List<Element> _manageIsolateReloadEvent(M.IsolateReloadEvent event) {
+    if (event.error != null) {
+      return [
+        new SpanElement()..text = 'Isolate reload failed:',
+        new BRElement(),
+        new BRElement(),
+        new DivElement()
+          ..classes = ["indent", "error"]
+          ..text = event.error.message.toString()
+      ];
+    } else {
+      return [new SpanElement()..text = 'Isolate reload'];
+    }
+  }
+
+  EventDeleteEvent _toEvent(_) {
+    return new EventDeleteEvent(_event);
+  }
+
+  void _delete(EventDeleteEvent e) {
+    _onDelete.add(e);
+  }
+
+  void delete() {
+    _onDelete.add(new EventDeleteEvent(_event));
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/notify_exception.dart b/runtime/observatory_2/lib/src/elements/nav/notify_exception.dart
new file mode 100644
index 0000000..37b6457
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/notify_exception.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/models.dart' show ConnectionException;
+
+class ExceptionDeleteEvent {
+  final dynamic exception;
+  final StackTrace stacktrace;
+
+  ExceptionDeleteEvent(this.exception, {this.stacktrace});
+}
+
+class NavNotifyExceptionElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavNotifyExceptionElement> _r;
+
+  Stream<RenderedEvent<NavNotifyExceptionElement>> get onRendered =>
+      _r.onRendered;
+
+  final StreamController<ExceptionDeleteEvent> _onDelete =
+      new StreamController<ExceptionDeleteEvent>.broadcast();
+  Stream<ExceptionDeleteEvent> get onDelete => _onDelete.stream;
+
+  dynamic _exception;
+  StackTrace _stacktrace;
+
+  dynamic get exception => _exception;
+  StackTrace get stacktrace => _stacktrace;
+
+  factory NavNotifyExceptionElement(dynamic exception,
+      {StackTrace stacktrace: null, RenderingQueue queue}) {
+    assert(exception != null);
+    NavNotifyExceptionElement e = new NavNotifyExceptionElement.created();
+    e._r = new RenderingScheduler<NavNotifyExceptionElement>(e, queue: queue);
+    e._exception = exception;
+    e._stacktrace = stacktrace;
+    return e;
+  }
+
+  NavNotifyExceptionElement.created() : super.created('nav-exception');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    if (exception is ConnectionException) {
+      renderConnectionException();
+    } else {
+      renderGenericException();
+    }
+  }
+
+  void renderConnectionException() {
+    children = <Element>[
+      new DivElement()
+        ..children = <Element>[
+          new SpanElement()
+            ..text = 'The request cannot be completed because the '
+                'VM is currently disconnected',
+          new BRElement(),
+          new BRElement(),
+          new SpanElement()..text = '[',
+          new AnchorElement(href: Uris.vmConnect())
+            ..text = 'Connect to a different VM',
+          new SpanElement()..text = ']',
+          new ButtonElement()
+            ..innerHtml = '&times;'
+            ..onClick.map(_toEvent).listen(_delete)
+        ]
+    ];
+  }
+
+  void renderGenericException() {
+    List<Element> content;
+    content = <Element>[
+      new SpanElement()..text = 'Unexpected exception:',
+      new BRElement(),
+      new BRElement(),
+      new DivElement()..text = exception.toString(),
+      new BRElement()
+    ];
+    if (stacktrace != null) {
+      content.addAll(<Element>[
+        new SpanElement()..text = 'StackTrace:',
+        new BRElement(),
+        new BRElement(),
+        new DivElement()..text = stacktrace.toString(),
+        new BRElement()
+      ]);
+    }
+    content.addAll(<Element>[
+      new SpanElement()..text = '[',
+      new AnchorElement(href: Uris.vmConnect())
+        ..text = 'Connect to a different VM',
+      new SpanElement()..text = ']',
+      new ButtonElement()
+        ..innerHtml = '&times;'
+        ..onClick.map(_toEvent).listen(_delete)
+    ]);
+    children = <Element>[new DivElement()..children = content];
+  }
+
+  ExceptionDeleteEvent _toEvent(_) {
+    return new ExceptionDeleteEvent(exception, stacktrace: stacktrace);
+  }
+
+  void _delete(ExceptionDeleteEvent e) {
+    _onDelete.add(e);
+  }
+
+  void delete() {
+    _onDelete.add(new ExceptionDeleteEvent(exception, stacktrace: stacktrace));
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/refresh.dart b/runtime/observatory_2/lib/src/elements/nav/refresh.dart
new file mode 100644
index 0000000..42e9ce6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/refresh.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class RefreshEvent {
+  final NavRefreshElement element;
+  RefreshEvent(this.element);
+}
+
+class NavRefreshElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavRefreshElement> _r;
+
+  Stream<RenderedEvent<NavRefreshElement>> get onRendered => _r.onRendered;
+
+  final StreamController<RefreshEvent> _onRefresh =
+      new StreamController<RefreshEvent>.broadcast();
+  Stream<RefreshEvent> get onRefresh => _onRefresh.stream;
+
+  bool _disabled;
+  String _label;
+
+  bool get disabled => _disabled;
+  String get label => _label;
+
+  set disabled(bool value) => _disabled = _r.checkAndReact(_disabled, value);
+  set label(String value) => _label = _r.checkAndReact(_label, value);
+
+  factory NavRefreshElement(
+      {String label: 'Refresh', bool disabled: false, RenderingQueue queue}) {
+    assert(label != null);
+    assert(disabled != null);
+    NavRefreshElement e = new NavRefreshElement.created();
+    e._r = new RenderingScheduler<NavRefreshElement>(e, queue: queue);
+    e._label = label;
+    e._disabled = disabled;
+    return e;
+  }
+
+  NavRefreshElement.created() : super.created('nav-refresh');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      new LIElement()
+        ..children = <Element>[
+          new ButtonElement()
+            ..text = label
+            ..disabled = disabled
+            ..onClick.map(_toEvent).listen(_refresh)
+        ]
+    ];
+  }
+
+  RefreshEvent _toEvent(_) {
+    return new RefreshEvent(this);
+  }
+
+  void _refresh(RefreshEvent e) {
+    if (_disabled) return;
+    _onRefresh.add(e);
+  }
+
+  void refresh() {
+    if (_disabled) return;
+    _refresh(new RefreshEvent(this));
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/reload.dart b/runtime/observatory_2/lib/src/elements/nav/reload.dart
new file mode 100644
index 0000000..2f578a3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/reload.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, IsolateRepository, EventRepository;
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class ReloadEvent {
+  final NavReloadElement element;
+  ReloadEvent(this.element);
+}
+
+class NavReloadElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavReloadElement> _r;
+
+  Stream<RenderedEvent<NavReloadElement>> get onRendered => _r.onRendered;
+
+  final StreamController<ReloadEvent> _onReload =
+      new StreamController<ReloadEvent>.broadcast();
+  Stream<ReloadEvent> get onReload => _onReload.stream;
+
+  M.IsolateRef _isolate;
+  M.IsolateRepository _isolates;
+  M.EventRepository _events;
+  StreamSubscription _sub;
+  bool _disabled = false;
+
+  factory NavReloadElement(M.IsolateRef isolate, M.IsolateRepository isolates,
+      M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(isolates != null);
+    assert(events != null);
+    NavReloadElement e = new NavReloadElement.created();
+    e._r = new RenderingScheduler<NavReloadElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._isolates = isolates;
+    e._events = events;
+    return e;
+  }
+
+  NavReloadElement.created() : super.created('nav-reload');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _sub = _events.onServiceEvent.listen((_) => _r.dirty());
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _sub.cancel();
+    _sub = null;
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    final children = <Element>[];
+    if (_isolates.reloadSourcesServices.isEmpty) {
+      children.add(new LIElement()
+        ..children = <Element>[
+          new ButtonElement()
+            ..text = 'Reload Source'
+            ..disabled = _disabled
+            ..onClick.listen((_) => _reload())
+        ]);
+    } else if (_isolates.reloadSourcesServices.length == 1) {
+      children.add(new LIElement()
+        ..children = <Element>[
+          new ButtonElement()
+            ..text = 'Reload Source'
+            ..disabled = _disabled
+            ..onClick
+                .listen((_) => _reload(_isolates.reloadSourcesServices.single))
+        ]);
+    } else {
+      final content = _isolates.reloadSourcesServices.map((s) => new LIElement()
+        ..children = <Element>[
+          new ButtonElement()
+            ..text = s.alias
+            ..disabled = _disabled
+            ..onClick.listen((_) => _reload(s))
+        ]);
+      children.add(navMenu('Reload Source', content: content));
+    }
+    this.children = children;
+  }
+
+  Future _reload([service]) async {
+    _disabled = true;
+    _r.dirty();
+    await _isolates.reloadSources(_isolate, service: service);
+    _disabled = false;
+    _r.dirty();
+    _onReload.add(new ReloadEvent(this));
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/top_menu.dart b/runtime/observatory_2/lib/src/elements/nav/top_menu.dart
new file mode 100644
index 0000000..65ba440
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/top_menu.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/menu_item.dart';
+
+class NavTopMenuElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavTopMenuElement> _r;
+
+  Stream<RenderedEvent<NavTopMenuElement>> get onRendered => _r.onRendered;
+
+  Iterable<Element> _content = const <Element>[];
+
+  Iterable<Element> get content => _content;
+
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavTopMenuElement({RenderingQueue queue}) {
+    NavTopMenuElement e = new NavTopMenuElement.created();
+    e._r = new RenderingScheduler<NavTopMenuElement>(e, queue: queue);
+    return e;
+  }
+
+  NavTopMenuElement.created() : super.created('nav-top-menu');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final content = (<Element>[
+      new NavMenuItemElement('Connect to a VM', link: Uris.vmConnect()).element,
+    ]..addAll(_content));
+    children = <Element>[
+      navMenu('Observatory', link: Uris.vm(), content: content)
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/nav/vm_menu.dart b/runtime/observatory_2/lib/src/elements/nav/vm_menu.dart
new file mode 100644
index 0000000..6426ba4
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/nav/vm_menu.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show VM, EventRepository;
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/menu_item.dart';
+
+class NavVMMenuElement extends CustomElement implements Renderable {
+  RenderingScheduler<NavVMMenuElement> _r;
+
+  Stream<RenderedEvent<NavVMMenuElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.EventRepository _events;
+  StreamSubscription _updatesSubscription;
+  Iterable<Element> _content = const [];
+
+  M.VM get vm => _vm;
+  Iterable<Element> get content => _content;
+
+  set content(Iterable<Element> value) {
+    _content = value.toList();
+    _r.dirty();
+  }
+
+  factory NavVMMenuElement(M.VM vm, M.EventRepository events,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    NavVMMenuElement e = new NavVMMenuElement.created();
+    e._r = new RenderingScheduler<NavVMMenuElement>(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    return e;
+  }
+
+  NavVMMenuElement.created() : super.created('nav-vm-menu');
+
+  @override
+  void attached() {
+    super.attached();
+    _updatesSubscription = _events.onVMUpdate.listen((e) {
+      _vm = e.vm;
+      _r.dirty();
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _updatesSubscription.cancel();
+  }
+
+  void render() {
+    final content = (_vm.isolates.map<Element>((isolate) {
+      return new NavMenuItemElement(isolate.name,
+              queue: _r.queue, link: Uris.inspect(isolate))
+          .element;
+    }).toList()
+      ..addAll(_content));
+    children = <Element>[
+      navMenu(vm.displayName, link: Uris.vm(), content: content)
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/object_common.dart b/runtime/observatory_2/lib/src/elements/object_common.dart
new file mode 100644
index 0000000..9d896a3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/object_common.dart
@@ -0,0 +1,226 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/inbound_references.dart';
+import 'package:observatory_2/src/elements/retaining_path.dart';
+import 'package:observatory_2/src/elements/sentinel_value.dart';
+import 'package:observatory_2/utils.dart';
+
+class ObjectCommonElement extends CustomElement implements Renderable {
+  RenderingScheduler<ObjectCommonElement> _r;
+
+  Stream<RenderedEvent<ObjectCommonElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.Object _object;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+  M.Guarded<M.Instance> _retainedSize = null;
+  bool _loadingRetainedBytes = false;
+  M.Guarded<M.Instance> _reachableSize = null;
+  bool _loadingReachableBytes = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.Object get object => _object;
+
+  factory ObjectCommonElement(
+      M.IsolateRef isolate,
+      M.Object object,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(object != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    ObjectCommonElement e = new ObjectCommonElement.created();
+    e._r = new RenderingScheduler<ObjectCommonElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._object = object;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._objects = objects;
+    e._retainingPaths = retainingPaths;
+    return e;
+  }
+
+  ObjectCommonElement.created() : super.created('object-common');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  RetainingPathElement _path;
+  InboundReferencesElement _inbounds;
+
+  void render() {
+    _path = _path ??
+        new RetainingPathElement(_isolate, _object, _retainingPaths, _objects,
+            queue: _r.queue);
+    _inbounds = _inbounds ??
+        new InboundReferencesElement(_isolate, _object, _references, _objects,
+            queue: _r.queue);
+    children = <Element>[
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Class ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = <Element>[
+                  _object.clazz == null
+                      ? (new SpanElement()..text = '...')
+                      : new ClassRefElement(_isolate, _object.clazz,
+                              queue: _r.queue)
+                          .element
+                ]
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Space for this object in memory'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Shallow size ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..text = Utils.formatSize(_object.size ?? 0)
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Space reachable from this object, '
+                'excluding class references'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Reachable size ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createReachableSizeValue()
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Space that would be reclaimed if references to this '
+                'object were replaced with null'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Retained size ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = _createRetainedSizeValue()
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Retaining path ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = <Element>[_path.element]
+            ],
+          new DivElement()
+            ..classes = ['memberItem']
+            ..title = 'Objects which directly reference this object'
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberName']
+                ..text = 'Inbound references ',
+              new DivElement()
+                ..classes = ['memberValue']
+                ..children = <Element>[_inbounds.element]
+            ]
+        ]
+    ];
+  }
+
+  List<Element> _createReachableSizeValue() {
+    final content = <Element>[];
+    if (_reachableSize != null) {
+      if (_reachableSize.isSentinel) {
+        content.add(
+            new SentinelValueElement(_reachableSize.asSentinel, queue: _r.queue)
+                .element);
+      } else {
+        content.add(new SpanElement()
+          ..text = Utils.formatSize(
+              int.parse(_reachableSize.asValue.valueAsString)));
+      }
+    } else {
+      content.add(new SpanElement()..text = '...');
+    }
+    final button = new ButtonElement()
+      ..classes = ['reachable_size']
+      ..disabled = _loadingReachableBytes
+      ..text = '↺';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _loadingReachableBytes = true;
+      _reachableSize = await _reachableSizes.get(_isolate, _object.id);
+      _r.dirty();
+    });
+    content.add(button);
+    return content;
+  }
+
+  List<Element> _createRetainedSizeValue() {
+    final content = <Element>[];
+    if (_retainedSize != null) {
+      if (_retainedSize.isSentinel) {
+        content.add(
+            new SentinelValueElement(_retainedSize.asSentinel, queue: _r.queue)
+                .element);
+      } else {
+        content.add(new SpanElement()
+          ..text =
+              Utils.formatSize(int.parse(_retainedSize.asValue.valueAsString)));
+      }
+    } else {
+      content.add(new SpanElement()..text = '...');
+    }
+    final button = new ButtonElement()
+      ..classes = ['retained_size']
+      ..disabled = _loadingRetainedBytes
+      ..text = '↺';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _loadingRetainedBytes = true;
+      _retainedSize = await _retainedSizes.get(_isolate, _object.id);
+      _r.dirty();
+    });
+    content.add(button);
+    return content;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/object_view.dart b/runtime/observatory_2/lib/src/elements/object_view.dart
new file mode 100644
index 0000000..ee41d78
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/object_view.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ObjectViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ObjectViewElement> _r;
+
+  Stream<RenderedEvent<ObjectViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Object _object;
+  M.ObjectRepository _objects;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Context get object => _object;
+
+  factory ObjectViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Object object,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ObjectRepository objects,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(object != null);
+    assert(objects != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    ObjectViewElement e = new ObjectViewElement.created();
+    e._r = new RenderingScheduler<ObjectViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._object = object;
+    e._objects = objects;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    return e;
+  }
+
+  ObjectViewElement.created() : super.created('object-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('object'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _object = await _objects.get(_isolate, _object.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Object',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _object, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/objectpool_ref.dart b/runtime/observatory_2/lib/src/elements/objectpool_ref.dart
new file mode 100644
index 0000000..28d89b4
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/objectpool_ref.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, ObjectPoolRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class ObjectPoolRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ObjectPoolRefElement> _r;
+
+  Stream<RenderedEvent<ObjectPoolRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ObjectPoolRef _pool;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ObjectPoolRef get pool => _pool;
+
+  factory ObjectPoolRefElement(M.IsolateRef isolate, M.ObjectPoolRef pool,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(pool != null);
+    ObjectPoolRefElement e = new ObjectPoolRefElement.created();
+    e._r = new RenderingScheduler<ObjectPoolRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._pool = pool;
+    return e;
+  }
+
+  ObjectPoolRefElement.created() : super.created('object-pool-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _pool))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'ObjectPool',
+          new SpanElement()..text = ' (${_pool.length})'
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/objectpool_view.dart b/runtime/observatory_2/lib/src/elements/objectpool_view.dart
new file mode 100644
index 0000000..a99091a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/objectpool_view.dart
@@ -0,0 +1,167 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library objectpool_view;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ObjectPoolViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ObjectPoolViewElement> _r;
+
+  Stream<RenderedEvent<ObjectPoolViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.ObjectPool _pool;
+  M.ObjectPoolRepository _pools;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.ObjectPoolRef get pool => _pool;
+
+  factory ObjectPoolViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.ObjectPool pool,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ObjectPoolRepository pools,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(pool != null);
+    assert(pools != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    ObjectPoolViewElement e = new ObjectPoolViewElement.created();
+    e._r = new RenderingScheduler<ObjectPoolViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._pool = pool;
+    e._pools = pools;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  ObjectPoolViewElement.created() : super.created('object-pool-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('instance'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _pool = await _pools.get(_isolate, _pool.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'ObjectPool',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _pool, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new HRElement(),
+          new HeadingElement.h3()..text = 'entries (${_pool.entries.length})',
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = _pool.entries
+                .map<Element>((entry) => new DivElement()
+                  ..classes = ['memberItem']
+                  ..children = <Element>[
+                    new DivElement()
+                      ..classes = ['memberName', 'hexadecimal']
+                      ..text = '[PP+0x${entry.offset.toRadixString(16)}]',
+                    new DivElement()
+                      ..classes = ['memberName']
+                      ..children = _createEntry(entry)
+                  ])
+                .toList(),
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  List<Element> _createEntry(M.ObjectPoolEntry entry) {
+    switch (entry.kind) {
+      case M.ObjectPoolEntryKind.nativeEntryData:
+      case M.ObjectPoolEntryKind.object:
+        return [anyRef(_isolate, entry.asObject, _objects, queue: _r.queue)];
+      case M.ObjectPoolEntryKind.immediate:
+        return [
+          new SpanElement()
+            ..text = 'Immediate 0x${entry.asInteger.toRadixString(16)}'
+        ];
+      case M.ObjectPoolEntryKind.nativeEntry:
+        return [
+          new SpanElement()
+            ..text = 'NativeEntry 0x${entry.asInteger.toRadixString(16)}'
+        ];
+    }
+    throw new Exception('Unknown ObjectPoolEntryKind (${entry.kind})');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/objectstore_view.dart b/runtime/observatory_2/lib/src/elements/objectstore_view.dart
new file mode 100644
index 0000000..864ca59
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/objectstore_view.dart
@@ -0,0 +1,130 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library objectstore_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ObjectStoreViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ObjectStoreViewElement> _r;
+
+  Stream<RenderedEvent<ObjectStoreViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.ObjectStore _store;
+  M.ObjectStoreRepository _stores;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory ObjectStoreViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ObjectStoreRepository stores,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(stores != null);
+    assert(objects != null);
+    ObjectStoreViewElement e = new ObjectStoreViewElement.created();
+    e._r = new RenderingScheduler<ObjectStoreViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._stores = stores;
+    e._objects = objects;
+    return e;
+  }
+
+  ObjectStoreViewElement.created() : super.created('objectstore-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final fields = _store?.fields?.toList(growable: false);
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        (new NavRefreshElement(disabled: _store == null, queue: _r.queue)
+              ..onRefresh.listen((e) => _refresh()))
+            .element,
+        (new NavNotifyElement(_notifications, queue: _r.queue).element)
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h1()
+            ..text = fields == null
+                ? 'Object Store'
+                : 'Object Store (${fields.length})',
+          new HRElement(),
+          fields == null
+              ? (new HeadingElement.h2()..text = 'Loading...')
+              : (new DivElement()
+                ..classes = ['memberList']
+                ..children = fields
+                    .map<Element>((field) => new DivElement()
+                      ..classes = ['memberItem']
+                      ..children = <Element>[
+                        new DivElement()
+                          ..classes = ['memberName']
+                          ..text = field.name,
+                        new DivElement()
+                          ..classes = ['memberValue']
+                          ..children = <Element>[
+                            anyRef(_isolate, field.value, _objects,
+                                queue: _r.queue)
+                          ]
+                      ])
+                    .toList()),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  Future _refresh() async {
+    _store = null;
+    _r.dirty();
+    _store = await _stores.get(_isolate);
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/observatory_application.dart b/runtime/observatory_2/lib/src/elements/observatory_application.dart
new file mode 100644
index 0000000..83af0a8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/observatory_application.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library observatory_application_element;
+
+import 'package:observatory_2/app.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+/// Main application tag. Responsible for instantiating an instance of
+/// [ObservatoryApplication] which is passed declaratively to all child
+/// elements.
+class ObservatoryApplicationElement extends CustomElement {
+  ObservatoryApplication app;
+
+  ObservatoryApplicationElement.created()
+      : super.created('observatory-application');
+
+  @override
+  void attached() {
+    super.attached();
+    app = new ObservatoryApplication(this);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/pc_descriptors_ref.dart b/runtime/observatory_2/lib/src/elements/pc_descriptors_ref.dart
new file mode 100644
index 0000000..16cca1d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/pc_descriptors_ref.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, PcDescriptorsRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class PcDescriptorsRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<PcDescriptorsRefElement> _r;
+
+  Stream<RenderedEvent<PcDescriptorsRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.PcDescriptorsRef _descriptors;
+
+  M.IsolateRef get isolate => _isolate;
+  M.PcDescriptorsRef get descriptors => _descriptors;
+
+  factory PcDescriptorsRefElement(
+      M.IsolateRef isolate, M.PcDescriptorsRef descriptors,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(descriptors != null);
+    PcDescriptorsRefElement e = new PcDescriptorsRefElement.created();
+    e._r = new RenderingScheduler<PcDescriptorsRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._descriptors = descriptors;
+    return e;
+  }
+
+  PcDescriptorsRefElement.created() : super.created('pc-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final text = (_descriptors.name == null || _descriptors.name == '')
+        ? 'PcDescriptors'
+        : _descriptors.name;
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _descriptors))
+        ..text = text
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/persistent_handles.dart b/runtime/observatory_2/lib/src/elements/persistent_handles.dart
new file mode 100644
index 0000000..b85ad5f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/persistent_handles.dart
@@ -0,0 +1,261 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library persitent_handles_page;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/containers/virtual_collection.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/utils.dart';
+
+enum _SortingField { externalSize, peer, finalizerCallback }
+
+enum _SortingDirection { ascending, descending }
+
+class PersistentHandlesPageElement extends CustomElement implements Renderable {
+  RenderingScheduler<PersistentHandlesPageElement> _r;
+
+  Stream<RenderedEvent<PersistentHandlesPageElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.PersistentHandlesRepository _repository;
+  M.ObjectRepository _objects;
+  M.PersistentHandles _handles;
+  _SortingField _sortingField = _SortingField.externalSize;
+  _SortingDirection _sortingDirection = _SortingDirection.descending;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory PersistentHandlesPageElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.PersistentHandlesRepository repository,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(repository != null);
+    assert(objects != null);
+    PersistentHandlesPageElement e = new PersistentHandlesPageElement.created();
+    e._r =
+        new RenderingScheduler<PersistentHandlesPageElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._repository = repository;
+    e._objects = objects;
+    return e;
+  }
+
+  PersistentHandlesPageElement.created()
+      : super.created('persistent-handles-page');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('persistent handles'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ])
+    ]
+      ..addAll(_createHandlers('Persistent Handles',
+          _handles?.elements?.toList(), _createLine, _updateLine))
+      ..add(new BRElement())
+      ..addAll(_createHandlers(
+          'Weak Persistent Handles',
+          _handles == null
+              ? null
+              : (_handles.weakElements.toList()..sort(_createSorter())),
+          _createWeakLine,
+          _updateWeakLine,
+          createHeader: _createWeakHeader));
+  }
+
+  List<Element> _createHandlers(String name, List items, create, update,
+      {createHeader}) {
+    return [
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h1()
+            ..text = items == null ? '$name' : '$name (${items.length})',
+          new HRElement(),
+        ],
+      new DivElement()
+        ..classes = ['persistent-handles']
+        ..children = <Element>[
+          items == null
+              ? (new HeadingElement.h2()
+                ..classes = ['content-centered-big']
+                ..text = 'Loading...')
+              : new VirtualCollectionElement(create, update,
+                      items: items, createHeader: createHeader, queue: _r.queue)
+                  .element
+        ]
+    ];
+  }
+
+  _createSorter() {
+    var getter;
+    switch (_sortingField) {
+      case _SortingField.externalSize:
+        getter = _getExternalSize;
+        break;
+      case _SortingField.peer:
+        getter = _getPeer;
+        break;
+      case _SortingField.finalizerCallback:
+        getter = _getFinalizerCallback;
+        break;
+    }
+    switch (_sortingDirection) {
+      case _SortingDirection.ascending:
+        int sort(M.WeakPersistentHandle a, M.WeakPersistentHandle b) {
+          return getter(a).compareTo(getter(b));
+        }
+        return sort;
+      case _SortingDirection.descending:
+        int sort(M.WeakPersistentHandle a, M.WeakPersistentHandle b) {
+          return getter(b).compareTo(getter(a));
+        }
+        return sort;
+    }
+  }
+
+  static HtmlElement _createLine() => new DivElement()
+    ..classes = ['collection-item']
+    ..text = 'object';
+
+  static HtmlElement _createWeakLine() => new DivElement()
+    ..classes = ['weak-item']
+    ..children = <Element>[
+      new SpanElement()
+        ..classes = ['external-size']
+        ..text = '0B',
+      new SpanElement()
+        ..classes = ['peer']
+        ..text = '0x00000',
+      new SpanElement()..classes = ['object'],
+      new SpanElement()
+        ..classes = ['finalizer']
+        ..text = 'dart::Class::Method()'
+    ];
+
+  List<HtmlElement> _createWeakHeader() => [
+        new DivElement()
+          ..classes = ['weak-item']
+          ..children = <Element>[
+            _createHeaderButton(const ['external-size'], 'External Size',
+                _SortingField.externalSize, _SortingDirection.descending),
+            _createHeaderButton(const ['peer'], 'Peer', _SortingField.peer,
+                _SortingDirection.descending),
+            new SpanElement()
+              ..classes = ['object']
+              ..text = 'Object',
+            _createHeaderButton(const ['finalizer'], 'Finalizer Callback',
+                _SortingField.finalizerCallback, _SortingDirection.ascending)
+          ]
+      ];
+
+  ButtonElement _createHeaderButton(List<String> classes, String text,
+          _SortingField field, _SortingDirection direction) =>
+      new ButtonElement()
+        ..classes = classes
+        ..text = _sortingField != field
+            ? text
+            : _sortingDirection == _SortingDirection.ascending
+                ? '$text▼'
+                : '$text▲'
+        ..onClick.listen((_) => _setSorting(field, direction));
+
+  void _setSorting(_SortingField field, _SortingDirection defaultDirection) {
+    if (_sortingField == field) {
+      switch (_sortingDirection) {
+        case _SortingDirection.descending:
+          _sortingDirection = _SortingDirection.ascending;
+          break;
+        case _SortingDirection.ascending:
+          _sortingDirection = _SortingDirection.descending;
+          break;
+      }
+    } else {
+      _sortingDirection = defaultDirection;
+      _sortingField = field;
+    }
+    _r.dirty();
+  }
+
+  void _updateWeakLine(Element e, itemDynamic, index) {
+    M.WeakPersistentHandle item = itemDynamic;
+    e.children[0].text = Utils.formatSize(_getExternalSize(item));
+    e.children[1].text = '${_getPeer(item)}';
+    e.children[2] = anyRef(_isolate, item.object, _objects, queue: _r.queue)
+      ..classes = ['object'];
+    e.children[3]
+      ..text = '${_getFinalizerCallback(item)}'
+      ..title = '${_getFinalizerCallback(item)}';
+  }
+
+  void _updateLine(Element e, itemDynamic, index) {
+    M.PersistentHandle item = itemDynamic;
+    e.children = <Element>[
+      anyRef(_isolate, item.object, _objects, queue: _r.queue)
+        ..classes = ['object']
+    ];
+  }
+
+  Future _refresh({bool gc: false, bool reset: false}) async {
+    _handles = null;
+    _r.dirty();
+    _handles = await _repository.get(_isolate);
+    _r.dirty();
+  }
+
+  static int _getExternalSize(M.WeakPersistentHandle h) => h.externalSize;
+  static String _getPeer(M.WeakPersistentHandle h) => h.peer;
+  static String _getFinalizerCallback(M.WeakPersistentHandle h) =>
+      '${h.callbackSymbolName} (${h.callbackAddress})';
+}
diff --git a/runtime/observatory_2/lib/src/elements/ports.dart b/runtime/observatory_2/lib/src/elements/ports.dart
new file mode 100644
index 0000000..e8e4a49
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/ports.dart
@@ -0,0 +1,140 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class PortsElement extends CustomElement implements Renderable {
+  RenderingScheduler<PortsElement> _r;
+
+  Stream<RenderedEvent<PortsElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.PortsRepository _ports;
+  M.ObjectRepository _objects;
+  M.Ports _isolatePorts;
+
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.PortsRepository get ports => _ports;
+  M.VMRef get vm => _vm;
+
+  factory PortsElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.PortsRepository ports,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(ports != null);
+    assert(objects != null);
+    PortsElement e = new PortsElement.created();
+    e._r = new RenderingScheduler<PortsElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._ports = ports;
+    e._objects = objects;
+    return e;
+  }
+
+  PortsElement.created() : super.created('ports-page');
+
+  int get portCount {
+    return _isolatePorts == null ? 0 : _isolatePorts.elements.length;
+  }
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('ports'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((_) => _refresh()))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()..text = 'Ports ($portCount)',
+          new HRElement(),
+          new BRElement(),
+          new DivElement()..children = _createList(),
+        ],
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+
+  List<Element> _createList() {
+    if (_isolatePorts == null) {
+      return const [];
+    }
+    int i = 0;
+    return _isolatePorts.elements
+        .map<Element>((port) => new DivElement()
+          ..classes = ['memberItem']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['memberName']
+              ..children = <Element>[
+                new SpanElement()
+                  ..classes = ['port-number']
+                  ..text = '[ ${++i} ] ',
+                new SpanElement()..text = '${port.name}'
+              ],
+            new DivElement()
+              ..classes = ['memberValue']
+              ..children = <Element>[
+                anyRef(_isolate, port.handler, _objects, queue: _r.queue)
+              ]
+          ])
+        .toList();
+  }
+
+  Future _refresh() async {
+    _isolatePorts = null;
+    _r.dirty();
+    _isolatePorts = await _ports.get(_isolate);
+    _r.dirty();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/process_snapshot.dart b/runtime/observatory_2/lib/src/elements/process_snapshot.dart
new file mode 100644
index 0000000..82593da
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/process_snapshot.dart
@@ -0,0 +1,279 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:convert';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/object_graph.dart';
+import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/containers/virtual_tree.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/tree_map.dart';
+import 'package:observatory_2/repositories.dart';
+import 'package:observatory_2/utils.dart';
+
+class ProcessItemTreeMap extends NormalTreeMap<Map> {
+  ProcessSnapshotElement element;
+  ProcessItemTreeMap(this.element);
+
+  int getSize(Map node) => node["size"];
+  String getType(Map node) => node["name"];
+  String getName(Map node) => node["name"];
+  String getTooltip(Map node) => getLabel(node) + "\n" + node["description"];
+  Map getParent(Map node) => node["parent"];
+  Iterable<Map> getChildren(Map node) => new List<Map>.from(node["children"]);
+  void onSelect(Map node) {
+    element.selection = node;
+    element._r.dirty();
+  }
+
+  void onDetails(Map node) {}
+}
+
+class ProcessSnapshotElement extends CustomElement implements Renderable {
+  RenderingScheduler<ProcessSnapshotElement> _r;
+
+  Stream<RenderedEvent<ProcessSnapshotElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.NotificationRepository get notifications => _notifications;
+  M.VMRef get vm => _vm;
+
+  List<Map> _loadedSnapshots = <Map>[];
+  Map selection;
+  Map _snapshotA;
+  Map _snapshotB;
+
+  factory ProcessSnapshotElement(
+      M.VM vm, M.EventRepository events, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(events != null);
+    assert(notifications != null);
+    ProcessSnapshotElement e = new ProcessSnapshotElement.created();
+    e._r = new RenderingScheduler<ProcessSnapshotElement>(e, queue: queue);
+    e._vm = vm;
+    e._events = events;
+    e._notifications = notifications;
+    return e;
+  }
+
+  ProcessSnapshotElement.created() : super.created('process-snapshot');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final content = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        navMenu('process snapshot'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) {
+                _refresh();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'save', queue: _r.queue)
+              ..disabled = _snapshotA == null
+              ..onRefresh.listen((e) {
+                _save();
+              }))
+            .element,
+        (new NavRefreshElement(label: 'load', queue: _r.queue)
+              ..onRefresh.listen((e) {
+                _load();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+    ];
+    if (_snapshotA == null) {
+      // Loading
+      content.add(new SpanElement()..text = "Loading");
+    } else {
+      // Loaded
+      content.addAll(_createReport());
+    }
+    children = content;
+  }
+
+  _refresh() async {
+    Map snapshot =
+        await (vm as dynamic).invokeRpcNoUpgrade("getProcessMemoryUsage", {});
+    _snapshotLoaded(snapshot);
+  }
+
+  _save() {
+    var blob = new Blob([jsonEncode(_snapshotA)], 'application/json');
+    var blobUrl = Url.createObjectUrl(blob);
+    var link = new AnchorElement();
+    link.href = blobUrl;
+    var now = new DateTime.now();
+    link.download = 'dart-process-${now.year}-${now.month}-${now.day}.json';
+    link.click();
+  }
+
+  _load() {
+    var input = new InputElement();
+    input.type = 'file';
+    input.multiple = false;
+    input.onChange.listen((event) {
+      var file = input.files[0];
+      var reader = new FileReader();
+      reader.onLoad.listen((event) async {
+        _snapshotLoaded(jsonDecode(reader.result));
+      });
+      reader.readAsText(file);
+    });
+    input.click();
+  }
+
+  _snapshotLoaded(Map snapshot) {
+    _loadedSnapshots.add(snapshot);
+    _snapshotA = snapshot;
+    _snapshotB = snapshot;
+    _r.dirty();
+  }
+
+  void _createTreeMap<T>(List<HtmlElement> report, TreeMap<T> treemap, T root) {
+    final content = new DivElement();
+    content.style.border = '1px solid black';
+    content.style.width = '100%';
+    content.style.height = '100%';
+    content.text = 'Performing layout...';
+    Timer.run(() {
+      // Generate the treemap after the content div has been added to the
+      // document so that we can ask the browser how much space is
+      // available for treemap layout.
+      treemap.showIn(root, content);
+    });
+
+    final text =
+        'Double-click a tile to zoom in. Double-click the outermost tile to '
+        'zoom out. Process memory that is not further subdivided is non-Dart '
+        'memory not known to the VM.';
+    report.addAll([
+      new DivElement()
+        ..classes = ['content-centered-big', 'explanation']
+        ..text = text,
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..style.width = '100%'
+        ..style.height = '100%'
+        ..children = [content]
+    ]);
+  }
+
+  List<Element> _createReport() {
+    var report = <HtmlElement>[
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Snapshot A',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = _createSnapshotSelectA()
+                ],
+              // TODO(rmacnak): Diffing.
+              // new DivElement()
+              //  ..classes = ['memberItem']
+              //  ..children = <Element>[
+              //    new DivElement()
+              //      ..classes = ['memberName']
+              //      ..text = 'Snapshot B',
+              //    new DivElement()
+              //      ..classes = ['memberName']
+              //      ..children = _createSnapshotSelectB()
+              //  ],
+            ]
+        ],
+    ];
+    if (selection == null) {
+      selection = _snapshotA["root"];
+    }
+    _createTreeMap(report, new ProcessItemTreeMap(this), selection);
+    return report;
+  }
+
+  String snapshotToString(snapshot) {
+    if (snapshot == null) return "None";
+    return snapshot["root"]["name"] +
+        " " +
+        Utils.formatSize(snapshot["root"]["size"]);
+  }
+
+  List<Element> _createSnapshotSelectA() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['analysis-select']
+        ..value = snapshotToString(_snapshotA)
+        ..children = _loadedSnapshots.map((snapshot) {
+          return new OptionElement(
+              value: snapshotToString(snapshot),
+              selected: _snapshotA == snapshot)
+            ..text = snapshotToString(snapshot);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _snapshotA = _loadedSnapshots[s.selectedIndex];
+          selection = null;
+          _r.dirty();
+        })
+    ];
+  }
+
+  List<Element> _createSnapshotSelectB() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['analysis-select']
+        ..value = snapshotToString(_snapshotB)
+        ..children = _loadedSnapshots.map((snapshot) {
+          return new OptionElement(
+              value: snapshotToString(snapshot),
+              selected: _snapshotB == snapshot)
+            ..text = snapshotToString(snapshot);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _snapshotB = _loadedSnapshots[s.selectedIndex];
+          selection = null;
+          _r.dirty();
+        })
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/retaining_path.dart b/runtime/observatory_2/lib/src/elements/retaining_path.dart
new file mode 100644
index 0000000..9ba99e5
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/retaining_path.dart
@@ -0,0 +1,127 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class RetainingPathElement extends CustomElement implements Renderable {
+  RenderingScheduler<RetainingPathElement> _r;
+
+  Stream<RenderedEvent<RetainingPathElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ObjectRef _object;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+  M.RetainingPath _path;
+  bool _expanded = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ObjectRef get object => _object;
+
+  factory RetainingPathElement(M.IsolateRef isolate, M.ObjectRef object,
+      M.RetainingPathRepository retainingPaths, M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(object != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    RetainingPathElement e = new RetainingPathElement.created();
+    e._r = new RenderingScheduler<RetainingPathElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._object = object;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  RetainingPathElement.created() : super.created('retaining-path');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    final curlyBlock =
+        new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+          ..content = _createContent()
+          ..onToggle.listen((e) async {
+            _expanded = e.control.expanded;
+            if (_expanded) {
+              e.control.disabled = true;
+              await _refresh();
+              e.control.disabled = false;
+            }
+          });
+    children = <Element>[curlyBlock.element];
+    _r.waitFor([curlyBlock.onRendered.first]);
+  }
+
+  Future _refresh() async {
+    _path = null;
+    _path = await _retainingPaths.get(_isolate, _object.id);
+    _r.dirty();
+  }
+
+  List<Element> _createContent() {
+    if (_path == null) {
+      return [new SpanElement()..text = 'Loading'];
+    }
+
+    var elements = <Element>[];
+    bool first = true;
+    for (var item in _path.elements) {
+      elements.add(_createItem(item, first));
+      first = false;
+    }
+    elements.add(_createGCRootItem(_path.gcRootType));
+    return elements;
+  }
+
+  Element _createItem(M.RetainingPathItem item, bool first) {
+    final content = <Element>[];
+
+    if (first) {
+      // No prefix.
+    } else if (item.parentField != null) {
+      content
+          .add(new SpanElement()..text = 'retained by ${item.parentField} of ');
+    } else if (item.parentListIndex != null) {
+      content.add(new SpanElement()
+        ..text = 'retained by [ ${item.parentListIndex} ] of ');
+    } else if (item.parentWordOffset != null) {
+      content.add(new SpanElement()
+        ..text = 'retained by offset ${item.parentWordOffset} of ');
+    } else {
+      content.add(new SpanElement()..text = 'retained by ');
+    }
+
+    content.add(anyRef(_isolate, item.source, _objects, queue: _r.queue));
+
+    return new DivElement()
+      ..classes = ['indent']
+      ..children = content;
+  }
+
+  Element _createGCRootItem(String gcRootType) {
+    return new DivElement()
+      ..classes = ['indent']
+      ..text = 'retained by a GC root ($gcRootType)';
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/sample_buffer_control.dart b/runtime/observatory_2/lib/src/elements/sample_buffer_control.dart
new file mode 100644
index 0000000..05ca174
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/sample_buffer_control.dart
@@ -0,0 +1,270 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/utils.dart';
+
+class SampleBufferControlChangedElement {
+  final SampleBufferControlElement element;
+  SampleBufferControlChangedElement(this.element);
+}
+
+class SampleBufferControlElement extends CustomElement implements Renderable {
+  RenderingScheduler<SampleBufferControlElement> _r;
+
+  Stream<RenderedEvent<SampleBufferControlElement>> get onRendered =>
+      _r.onRendered;
+
+  StreamController<SampleBufferControlChangedElement> _onTagChange =
+      new StreamController<SampleBufferControlChangedElement>.broadcast();
+  Stream<SampleBufferControlChangedElement> get onTagChange =>
+      _onTagChange.stream;
+
+  M.VM _vm;
+  Stream<M.SampleProfileLoadingProgressEvent> _progressStream;
+  M.SampleProfileLoadingProgress _progress;
+  M.SampleProfileTag _tag;
+  bool _showTag = false;
+  bool _profileVM = false;
+  StreamSubscription _subscription;
+
+  M.SampleProfileLoadingProgress get progress => _progress;
+  M.SampleProfileTag get selectedTag => _tag;
+  bool get showTag => _showTag;
+  bool get profileVM => _profileVM;
+
+  set selectedTag(M.SampleProfileTag value) =>
+      _tag = _r.checkAndReact(_tag, value);
+  set showTag(bool value) => _showTag = _r.checkAndReact(_showTag, value);
+  set profileVM(bool value) => _profileVM = _r.checkAndReact(_profileVM, value);
+
+  factory SampleBufferControlElement(
+      M.VM vm,
+      M.SampleProfileLoadingProgress progress,
+      Stream<M.SampleProfileLoadingProgressEvent> progressStream,
+      {M.SampleProfileTag selectedTag: M.SampleProfileTag.none,
+      bool showTag: true,
+      RenderingQueue queue}) {
+    assert(progress != null);
+    assert(progressStream != null);
+    assert(selectedTag != null);
+    assert(showTag != null);
+    SampleBufferControlElement e = new SampleBufferControlElement.created();
+    e._r = new RenderingScheduler<SampleBufferControlElement>(e, queue: queue);
+    e._vm = vm;
+    e._progress = progress;
+    e._progressStream = progressStream;
+    e._tag = selectedTag;
+    e._showTag = showTag;
+    return e;
+  }
+
+  SampleBufferControlElement.created() : super.created('sample-buffer-control');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = _progressStream.listen((e) {
+      _progress = e.progress;
+      _r.dirty();
+    });
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = const [];
+    _subscription.cancel();
+  }
+
+  void render() {
+    var content = <Element>[
+      new HeadingElement.h2()..text = 'Sample buffer',
+      new HRElement()
+    ];
+    switch (_progress.status) {
+      case M.SampleProfileLoadingStatus.fetching:
+        content.addAll(_createStatusMessage('Fetching profile from VM...'));
+        break;
+      case M.SampleProfileLoadingStatus.loading:
+        content.addAll(_createStatusMessage('Loading profile...',
+            progress: _progress.progress));
+        break;
+      case M.SampleProfileLoadingStatus.disabled:
+        content.addAll(_createDisabledMessage());
+        break;
+      case M.SampleProfileLoadingStatus.loaded:
+        content.addAll(_createStatusReport());
+        break;
+    }
+    children = <Element>[
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = content
+    ];
+  }
+
+  static List<Element> _createStatusMessage(String message,
+      {double progress: 0.0}) {
+    return [
+      new DivElement()
+        ..classes = ['statusBox', 'shadow', 'center']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['statusMessage']
+            ..text = message,
+          new DivElement()
+            ..style.background = '#0489c3'
+            ..style.width = '$progress%'
+            ..style.height = '15px'
+            ..style.borderRadius = '4px'
+        ]
+    ];
+  }
+
+  List<Element> _createDisabledMessage() {
+    return [
+      new DivElement()
+        ..classes = ['statusBox' 'shadow' 'center']
+        ..children = <Element>[
+          new DivElement()
+            ..children = <Element>[
+              new HeadingElement.h1()..text = 'Profiling is disabled',
+              new BRElement(),
+              new DivElement()
+                ..innerHtml = 'Perhaps the <b>profile</b> '
+                    'flag has been disabled for this VM.',
+              new BRElement(),
+              new ButtonElement()
+                ..text = 'Enable profiler'
+                ..onClick.listen((_) {
+                  _enableProfiler();
+                })
+            ]
+        ]
+    ];
+  }
+
+  List<Element> _createStatusReport() {
+    final fetchT = Utils.formatDurationInSeconds(_progress.fetchingTime);
+    final loadT = Utils.formatDurationInSeconds(_progress.loadingTime);
+    final sampleCount = _progress.profile.sampleCount;
+    final refreshT = new DateTime.now();
+    final maxStackDepth = _progress.profile.maxStackDepth;
+    final sampleRate = _progress.profile.sampleRate.toStringAsFixed(0);
+    final timeSpan = _progress.profile.sampleCount == 0
+        ? '0s'
+        : Utils.formatTimePrecise(_progress.profile.timeSpan);
+
+    var content = <Element>[
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Refreshed at',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = '$refreshT (fetched in ${fetchT}s) (loaded in ${loadT}s)'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Profile contains ',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = '$sampleCount samples (spanning $timeSpan)'
+        ],
+      new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Sampling',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..text = '$maxStackDepth stack frames @ ${sampleRate}Hz'
+        ],
+    ];
+    if (_showTag) {
+      content.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Tag Order',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = _createTagSelect()
+        ]);
+    }
+    return [
+      new DivElement()
+        ..classes = ['memberList']
+        ..children = content
+    ];
+  }
+
+  List<Element> _createTagSelect() {
+    var values = M.SampleProfileTag.values;
+    if (!_profileVM) {
+      values = const [
+        M.SampleProfileTag.userOnly,
+        M.SampleProfileTag.vmOnly,
+        M.SampleProfileTag.none
+      ];
+    }
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['tag-select']
+        ..value = tagToString(_tag)
+        ..children = values.map((tag) {
+          return new OptionElement(
+              value: tagToString(tag), selected: _tag == tag)
+            ..text = tagToString(tag);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _tag = values[s.selectedIndex];
+        })
+        ..onChange.map(_toEvent).listen(_triggerModeChange),
+    ];
+  }
+
+  static String tagToString(M.SampleProfileTag tag) {
+    switch (tag) {
+      case M.SampleProfileTag.userVM:
+        return 'User > VM';
+      case M.SampleProfileTag.userOnly:
+        return 'User';
+      case M.SampleProfileTag.vmUser:
+        return 'VM > User';
+      case M.SampleProfileTag.vmOnly:
+        return 'VM';
+      case M.SampleProfileTag.none:
+        return 'None';
+    }
+    throw new Exception('Unknown tagToString');
+  }
+
+  SampleBufferControlChangedElement _toEvent(_) {
+    return new SampleBufferControlChangedElement(this);
+  }
+
+  void _enableProfiler() {
+    _vm.enableProfiler().then((_) {
+      _triggerModeChange(_toEvent(null));
+    });
+  }
+
+  void _triggerModeChange(e) => _onTagChange.add(e);
+}
diff --git a/runtime/observatory_2/lib/src/elements/script_inset.dart b/runtime/observatory_2/lib/src/elements/script_inset.dart
new file mode 100644
index 0000000..c4a0094
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/script_inset.dart
@@ -0,0 +1,1403 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library script_inset_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:svg';
+import 'package:observatory_2/app.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/utils.dart';
+
+class ScriptInsetElement extends CustomElement implements Renderable {
+  RenderingScheduler<ScriptInsetElement> _r;
+
+  Stream<RenderedEvent<ScriptInsetElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ScriptRef _script;
+  M.Script _loadedScript;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+  M.EventRepository _events;
+  StreamSubscription _subscription;
+  int _startPos;
+  int _endPos;
+  int _currentPos;
+  bool _inDebuggerContext;
+  Iterable _variables;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ScriptRef get script => _script;
+
+  factory ScriptInsetElement(
+      M.IsolateRef isolate,
+      M.ScriptRef script,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      M.EventRepository events,
+      {int startPos,
+      int endPos,
+      int currentPos,
+      bool inDebuggerContext: false,
+      Iterable variables: const [],
+      RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(script != null);
+    assert(scripts != null);
+    assert(objects != null);
+    assert(events != null);
+    assert(inDebuggerContext != null);
+    assert(variables != null);
+    ScriptInsetElement e = new ScriptInsetElement.created();
+    e._r = new RenderingScheduler<ScriptInsetElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._script = script;
+    e._scripts = scripts;
+    e._objects = objects;
+    e._events = events;
+    e._startPos = startPos;
+    e._endPos = endPos;
+    e._currentPos = currentPos;
+    e._inDebuggerContext = inDebuggerContext;
+    e._variables = new List.unmodifiable(variables);
+    return e;
+  }
+
+  ScriptInsetElement.created() : super.created('script-inset');
+
+  bool get noSource => _startPos == -1 || _loadedScript.source == null;
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+    _subscription = _events.onDebugEvent
+        .where((e) => e is M.BreakpointEvent)
+        .map((e) => (e as M.BreakpointEvent).breakpoint)
+        .listen((M.Breakpoint b) async {
+      final M.Location loc = b.location;
+      int line;
+      if (loc.script.id == script.id) {
+        if (loc.tokenPos != null) {
+          line = _loadedScript.tokenToLine(loc.tokenPos);
+        } else {
+          line = (loc as dynamic).line;
+        }
+      } else {
+        try {
+          line = (loc as dynamic).line;
+        } on NoSuchMethodError {
+          if (loc.tokenPos != null) {
+            M.Script scriptUsed = await _scripts.get(_isolate, loc.script.id);
+            line = scriptUsed.tokenToLine(loc.tokenPos);
+          }
+        }
+      }
+      if ((line == null) || ((line >= _startLine) && (line <= _endLine))) {
+        _r.dirty();
+      }
+    });
+    _refresh();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _subscription.cancel();
+  }
+
+  void render() {
+    if (_loadedScript == null) {
+      children = <Element>[new SpanElement()..text = 'Loading...'];
+    } else if (noSource) {
+      children = <Element>[new SpanElement()..text = 'No source'];
+    } else {
+      final table = linesTable();
+      var firstBuild = false;
+      if (container == null) {
+        // Indirect to avoid deleting the style element.
+        container = new DivElement();
+
+        firstBuild = true;
+      }
+      children = <Element>[container];
+      container.children.clear();
+      container.children.add(table);
+      _makeCssClassUncopyable(table, "noCopy");
+      if (firstBuild) {
+        _scrollToCurrentPos();
+      }
+    }
+  }
+
+  Future _refresh() async {
+    _loadedScript = await _scripts.get(_isolate, _script.id);
+    await _refreshSourceReport();
+    await _computeAnnotations();
+    _r.dirty();
+  }
+
+  ButtonElement _refreshButton;
+  ButtonElement _toggleProfileButton;
+
+  int _currentLine;
+  int _currentCol;
+  int _startLine;
+  int _endLine;
+
+  Map/*<int, List<S.ServiceMap>>*/ _rangeMap = {};
+  Set _callSites = new Set<S.CallSite>();
+  Set _possibleBreakpointLines = new Set<int>();
+  Map<int, ScriptLineProfile> _profileMap = {};
+
+  var _annotations = [];
+  var _annotationsCursor;
+
+  bool _includeProfile = false;
+
+  String makeLineClass(int line) {
+    return 'script-inset-line-$line';
+  }
+
+  void _scrollToCurrentPos() {
+    var lines = getElementsByClassName(makeLineClass(_currentLine));
+    if (lines.length > 0) {
+      (lines[0] as dynamic).scrollIntoView();
+    }
+  }
+
+  Element a(String text) => new AnchorElement()..text = text;
+  Element span(String text) => new SpanElement()..text = text;
+
+  Element hitsCurrent(Element element) {
+    element.classes.add('hitsCurrent');
+    element.title = "";
+    return element;
+  }
+
+  Element hitsUnknown(Element element) {
+    element.classes.add('hitsNone');
+    element.title = "";
+    return element;
+  }
+
+  Element hitsNotExecuted(Element element) {
+    element.classes.add('hitsNotExecuted');
+    element.title = "Line did not execute";
+    return element;
+  }
+
+  Element hitsExecuted(Element element) {
+    element.classes.add('hitsExecuted');
+    element.title = "Line did execute";
+    return element;
+  }
+
+  Element hitsCompiled(Element element) {
+    element.classes.add('hitsCompiled');
+    element.title = "Line in compiled function";
+    return element;
+  }
+
+  Element hitsNotCompiled(Element element) {
+    element.classes.add('hitsNotCompiled');
+    element.title = "Line in uncompiled function";
+    return element;
+  }
+
+  Element container;
+
+  // Build _rangeMap and _callSites from a source report.
+  Future _refreshSourceReport() async {
+    if (noSource) return;
+
+    var reports = [
+      S.Isolate.kCallSitesReport,
+      S.Isolate.kPossibleBreakpointsReport
+    ];
+    if (_includeProfile) {
+      reports.add(S.Isolate.kProfileReport);
+    }
+    S.Isolate isolate = _isolate as S.Isolate;
+    dynamic sourceReport =
+        await isolate.getSourceReport(reports, script, _startPos, _endPos);
+    _possibleBreakpointLines =
+        S.getPossibleBreakpointLines(sourceReport, script);
+    _rangeMap.clear();
+    _callSites.clear();
+    _profileMap.clear();
+    for (var range in sourceReport['ranges']) {
+      int startLine = _loadedScript.tokenToLine(range['startPos']);
+      int endLine = _loadedScript.tokenToLine(range['endPos']);
+      // TODO(turnidge): Track down the root cause of null startLine/endLine.
+      if ((startLine != null) && (endLine != null)) {
+        for (var line = startLine; line <= endLine; line++) {
+          var rangeList = _rangeMap[line];
+          if (rangeList == null) {
+            _rangeMap[line] = [range];
+          } else {
+            rangeList.add(range);
+          }
+        }
+      }
+      if (_includeProfile && range['profile'] != null) {
+        List positions = range['profile']['positions'];
+        List exclusiveTicks = range['profile']['exclusiveTicks'];
+        List inclusiveTicks = range['profile']['inclusiveTicks'];
+        int sampleCount = range['profile']['metadata']['sampleCount'];
+        assert(positions.length == exclusiveTicks.length);
+        assert(positions.length == inclusiveTicks.length);
+        for (int i = 0; i < positions.length; i++) {
+          if (positions[i] is String) {
+            // String positions are classifying token positions.
+            // TODO(johnmccutchan): Add classifier data to UI.
+            continue;
+          }
+          int line = _loadedScript.tokenToLine(positions[i]);
+          ScriptLineProfile lineProfile = _profileMap[line];
+          if (lineProfile == null) {
+            lineProfile = new ScriptLineProfile(line, sampleCount);
+            _profileMap[line] = lineProfile;
+          }
+          lineProfile.process(exclusiveTicks[i], inclusiveTicks[i]);
+        }
+      }
+      if (range['compiled']) {
+        var rangeCallSites = range['callSites'];
+        if (rangeCallSites != null) {
+          for (var callSiteMap in rangeCallSites) {
+            _callSites.add(new S.CallSite.fromMap(callSiteMap, script));
+          }
+        }
+      }
+    }
+  }
+
+  Future _computeAnnotations() async {
+    if (noSource) return;
+
+    _startLine = (_startPos != null
+        ? _loadedScript.tokenToLine(_startPos)
+        : 1 + _loadedScript.lineOffset);
+    _currentLine =
+        (_currentPos != null ? _loadedScript.tokenToLine(_currentPos) : null);
+    _currentCol =
+        (_currentPos != null ? (_loadedScript.tokenToCol(_currentPos)) : null);
+    if (_currentCol != null) {
+      _currentCol--; // make this 0-based.
+    }
+
+    S.Script script = _loadedScript as S.Script;
+
+    _endLine = (_endPos != null
+        ? _loadedScript.tokenToLine(_endPos)
+        : script.lines.length + _loadedScript.lineOffset);
+
+    if (_startLine == null || _endLine == null) {
+      return;
+    }
+
+    _annotations.clear();
+
+    addCurrentExecutionAnnotation();
+    addBreakpointAnnotations();
+
+    if (!_inDebuggerContext && script.library != null) {
+      await loadDeclarationsOfLibrary(script.library);
+      addLibraryAnnotations();
+      addDependencyAnnotations();
+      addPartAnnotations();
+      addClassAnnotations();
+      addFieldAnnotations();
+      addFunctionAnnotations();
+      addCallSiteAnnotations();
+    }
+
+    addLocalVariableAnnotations();
+
+    _annotations.sort();
+  }
+
+  void addCurrentExecutionAnnotation() {
+    if (_currentLine != null) {
+      var a = new CurrentExecutionAnnotation(_isolate, _objects, _r.queue);
+      a.line = _currentLine;
+      a.columnStart = _currentCol;
+      S.Script script = _loadedScript as S.Script;
+      var length = script.guessTokenLength(_currentLine, _currentCol);
+      if (length == null) {
+        length = 1;
+      }
+      a.columnStop = _currentCol + length;
+      _annotations.add(a);
+    }
+  }
+
+  void addBreakpointAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    for (var line = _startLine; line <= _endLine; line++) {
+      var bpts = script.getLine(line).breakpoints;
+      if (bpts != null) {
+        for (var bpt in bpts) {
+          if (bpt.location != null) {
+            _annotations.add(
+                new BreakpointAnnotation(_isolate, _objects, _r.queue, bpt));
+          }
+        }
+      }
+    }
+  }
+
+  Future loadDeclarationsOfLibrary(S.Library lib) {
+    return lib.load().then((serviceObject) {
+      S.Library lib = serviceObject;
+      var loads = <Future>[];
+      for (var func in lib.functions) {
+        loads.add(func.load());
+      }
+      for (var field in lib.variables) {
+        loads.add(field.load());
+      }
+      for (var cls in lib.classes) {
+        loads.add(loadDeclarationsOfClass(cls));
+      }
+      return Future.wait(loads);
+    });
+  }
+
+  Future loadDeclarationsOfClass(S.Class cls) {
+    return cls.load().then((serviceObject) {
+      S.Class cls = serviceObject;
+      var loads = <Future>[];
+      for (var func in cls.functions) {
+        loads.add(func.load());
+      }
+      for (var field in cls.fields) {
+        loads.add(field.load());
+      }
+      return Future.wait(loads);
+    });
+  }
+
+  void addLibraryAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    for (S.ScriptLine line in script.lines) {
+      // TODO(rmacnak): Use a real scanner.
+      var pattern = new RegExp("library ${script.library.name}");
+      var match = pattern.firstMatch(line.text);
+      if (match != null) {
+        var anno = new LibraryAnnotation(
+            _isolate,
+            _objects,
+            _r.queue,
+            _loadedScript.library,
+            Uris.inspect(isolate, object: _loadedScript.library));
+        anno.line = line.line;
+        anno.columnStart = match.start + 8;
+        anno.columnStop = match.end;
+        _annotations.add(anno);
+      }
+      // TODO(rmacnak): Use a real scanner.
+      pattern = new RegExp("part of ${script.library.name}");
+      match = pattern.firstMatch(line.text);
+      if (match != null) {
+        var anno = new LibraryAnnotation(
+            _isolate,
+            _objects,
+            _r.queue,
+            _loadedScript.library,
+            Uris.inspect(isolate, object: _loadedScript.library));
+        anno.line = line.line;
+        anno.columnStart = match.start + 8;
+        anno.columnStop = match.end;
+        _annotations.add(anno);
+      }
+    }
+  }
+
+  M.Library resolveDependency(String relativeUri) {
+    S.Script script = _loadedScript as S.Script;
+    // This isn't really correct: we need to ask the embedder to do the
+    // uri canonicalization for us, but Observatory isn't in a position
+    // to invoke the library tag handler. Handle the most common cases.
+    var targetUri = Uri.parse(_loadedScript.library.uri).resolve(relativeUri);
+    for (M.Library l in script.isolate.libraries) {
+      if (targetUri.toString() == l.uri) {
+        return l;
+      }
+    }
+    if (targetUri.scheme == 'package') {
+      var targetUriString = "packages/${targetUri.path}";
+      for (M.Library l in script.isolate.libraries) {
+        if (targetUriString == l.uri) {
+          return l;
+        }
+      }
+    }
+
+    print("Could not resolve library dependency: $relativeUri");
+    return null;
+  }
+
+  void addDependencyAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    // TODO(rmacnak): Use a real scanner.
+    var patterns = [
+      new RegExp("import '(.*)'"),
+      new RegExp('import "(.*)"'),
+      new RegExp("export '(.*)'"),
+      new RegExp('export "(.*)"'),
+    ];
+    for (S.ScriptLine line in script.lines) {
+      for (var pattern in patterns) {
+        var match = pattern.firstMatch(line.text);
+        if (match != null) {
+          M.Library target = resolveDependency(match[1]);
+          if (target != null) {
+            var anno = new LibraryAnnotation(_isolate, _objects, _r.queue,
+                target, Uris.inspect(isolate, object: target));
+            anno.line = line.line;
+            anno.columnStart = match.start + 8;
+            anno.columnStop = match.end - 1;
+            _annotations.add(anno);
+          }
+        }
+      }
+    }
+  }
+
+  M.Script resolvePart(String relativeUri) {
+    S.Script script = _loadedScript as S.Script;
+    var rootUri = Uri.parse(script.library.uri);
+    if (rootUri.scheme == 'dart') {
+      // The relative paths from dart:* libraries to their parts are not valid.
+      rootUri = Uri.parse(script.library.uri + '/');
+    }
+    var targetUri = rootUri.resolve(relativeUri);
+    for (M.Script s in script.library.scripts) {
+      if (targetUri.toString() == s.uri) {
+        return s;
+      }
+    }
+    print("Could not resolve part: $relativeUri");
+    return null;
+  }
+
+  void addPartAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    // TODO(rmacnak): Use a real scanner.
+    var patterns = [
+      new RegExp("part '(.*)'"),
+      new RegExp('part "(.*)"'),
+    ];
+    for (S.ScriptLine line in script.lines) {
+      for (var pattern in patterns) {
+        var match = pattern.firstMatch(line.text);
+        if (match != null) {
+          S.Script part = resolvePart(match[1]);
+          if (part != null) {
+            var anno = new PartAnnotation(_isolate, _objects, _r.queue, part,
+                Uris.inspect(isolate, object: part));
+            anno.line = line.line;
+            anno.columnStart = match.start + 6;
+            anno.columnStop = match.end - 1;
+            _annotations.add(anno);
+          }
+        }
+      }
+    }
+  }
+
+  void addClassAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    for (var cls in script.library.classes) {
+      if ((cls.location != null) && (cls.location.script == script)) {
+        var a = new ClassDeclarationAnnotation(_isolate, _objects, _r.queue,
+            cls, Uris.inspect(isolate, object: cls));
+        _annotations.add(a);
+      }
+    }
+  }
+
+  void addFieldAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    for (var field in script.library.variables) {
+      if ((field.location != null) && (field.location.script == script)) {
+        var a = new FieldDeclarationAnnotation(_isolate, _objects, _r.queue,
+            field, Uris.inspect(isolate, object: field));
+        _annotations.add(a);
+      }
+    }
+    for (var cls in script.library.classes) {
+      for (var field in cls.fields) {
+        if ((field.location != null) && (field.location.script == script)) {
+          var a = new FieldDeclarationAnnotation(_isolate, _objects, _r.queue,
+              field, Uris.inspect(isolate, object: field));
+          _annotations.add(a);
+        }
+      }
+    }
+  }
+
+  void addFunctionAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    for (var func in script.library.functions) {
+      if ((func.location != null) &&
+          (func.location.script == script) &&
+          (func.kind != M.FunctionKind.implicitGetter) &&
+          (func.kind != M.FunctionKind.implicitSetter)) {
+        // We annotate a field declaration with the field instead of the
+        // implicit getter or setter.
+        var a = new FunctionDeclarationAnnotation(_isolate, _objects, _r.queue,
+            func, Uris.inspect(isolate, object: func));
+        _annotations.add(a);
+      }
+    }
+    for (var cls in script.library.classes) {
+      S.Script script = _loadedScript as S.Script;
+      for (var func in cls.functions) {
+        if ((func.location != null) &&
+            (func.location.script == script) &&
+            (func.kind != M.FunctionKind.implicitGetter) &&
+            (func.kind != M.FunctionKind.implicitSetter)) {
+          // We annotate a field declaration with the field instead of the
+          // implicit getter or setter.
+          var a = new FunctionDeclarationAnnotation(_isolate, _objects,
+              _r.queue, func, Uris.inspect(isolate, object: func));
+          _annotations.add(a);
+        }
+      }
+    }
+  }
+
+  void addCallSiteAnnotations() {
+    for (var callSite in _callSites) {
+      _annotations
+          .add(new CallSiteAnnotation(_isolate, _objects, _r.queue, callSite));
+    }
+  }
+
+  void addLocalVariableAnnotations() {
+    S.Script script = _loadedScript as S.Script;
+    // We have local variable information.
+    if (_variables != null) {
+      // For each variable.
+      for (var variable in _variables) {
+        // Find variable usage locations.
+        var locations = script.scanForLocalVariableLocations(
+            variable['name'], variable['_tokenPos'], variable['_endTokenPos']);
+
+        // Annotate locations.
+        for (var location in locations) {
+          _annotations.add(new LocalVariableAnnotation(
+              _isolate, _objects, _r.queue, location, variable['value']));
+        }
+      }
+    }
+  }
+
+  ButtonElement _newRefreshButton() {
+    var button = new ButtonElement();
+    button.classes = ['refresh'];
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      await _refresh();
+      button.disabled = false;
+    });
+    button.title = 'Refresh coverage';
+    button.children = <Element>[_iconRefresh.clone(true)];
+    return button;
+  }
+
+  ButtonElement _newToggleProfileButton() {
+    ButtonElement button = new ButtonElement();
+    button.classes =
+        _includeProfile ? ['toggle-profile', 'enabled'] : ['toggle-profile'];
+    button.title = 'Toggle CPU profile information';
+    button.onClick.listen((_) async {
+      _includeProfile = !_includeProfile;
+      button.classes.toggle('enabled');
+      button.disabled = true;
+      _refresh();
+      button.disabled = false;
+    });
+    button.children = <Element>[_iconWhatsHot.clone(true)];
+    return button;
+  }
+
+  Element linesTable() {
+    S.Script script = _loadedScript as S.Script;
+    var table = new DivElement();
+    table.classes.add("sourceTable");
+
+    _refreshButton = _newRefreshButton();
+    _toggleProfileButton = _newToggleProfileButton();
+    table.append(_refreshButton);
+    table.append(_toggleProfileButton);
+
+    if (_startLine == null || _endLine == null) {
+      return table;
+    }
+
+    var endLine = (_endPos != null
+        ? _loadedScript.tokenToLine(_endPos)
+        : script.lines.length + _loadedScript.lineOffset);
+    var lineNumPad = endLine.toString().length;
+
+    _annotationsCursor = 0;
+
+    int blankLineCount = 0;
+    for (int i = _startLine; i <= _endLine; i++) {
+      var line = script.getLine(i);
+      if (line.isBlank) {
+        // Try to introduce ellipses if there are 4 or more contiguous
+        // blank lines.
+        blankLineCount++;
+      } else {
+        if (blankLineCount > 0) {
+          int firstBlank = i - blankLineCount;
+          int lastBlank = i - 1;
+          if (blankLineCount < 4) {
+            // Too few blank lines for an ellipsis.
+            for (int j = firstBlank; j <= lastBlank; j++) {
+              table.append(lineElement(script.getLine(j), lineNumPad));
+            }
+          } else {
+            // Add an ellipsis for the skipped region.
+            table.append(lineElement(script.getLine(firstBlank), lineNumPad));
+            table.append(lineElement(null, lineNumPad));
+            table.append(lineElement(script.getLine(lastBlank), lineNumPad));
+          }
+          blankLineCount = 0;
+        }
+        table.append(lineElement(line, lineNumPad));
+      }
+    }
+
+    return table;
+  }
+
+  // Assumes annotations are sorted.
+  Annotation nextAnnotationOnLine(int line) {
+    if (_annotationsCursor >= _annotations.length) return null;
+    var annotation = _annotations[_annotationsCursor];
+
+    // Fast-forward past any annotations before the first line that
+    // we are displaying.
+    while (annotation.line < line) {
+      _annotationsCursor++;
+      if (_annotationsCursor >= _annotations.length) return null;
+      annotation = _annotations[_annotationsCursor];
+    }
+
+    // Next annotation is for a later line, don't advance past it.
+    if (annotation.line != line) return null;
+    _annotationsCursor++;
+    return annotation;
+  }
+
+  Element lineElement(S.ScriptLine line, int lineNumPad) {
+    var e = new DivElement();
+    e.classes.add("sourceRow");
+    e.append(lineBreakpointElement(line));
+    e.append(lineNumberElement(line, lineNumPad));
+    if (_includeProfile) {
+      e.append(lineProfileElement(line, false));
+      e.append(lineProfileElement(line, true));
+    }
+    e.append(lineSourceElement(line));
+    return e;
+  }
+
+  Element lineProfileElement(S.ScriptLine line, bool self) {
+    var e = span('');
+    e.classes.add('noCopy');
+    if (self) {
+      e.title = 'Self %';
+    } else {
+      e.title = 'Total %';
+    }
+
+    if (line == null) {
+      e.classes.add('notSourceProfile');
+      e.text = nbsp;
+      return e;
+    }
+
+    var ranges = _rangeMap[line.line];
+    if ((ranges == null) || ranges.isEmpty) {
+      e.classes.add('notSourceProfile');
+      e.text = nbsp;
+      return e;
+    }
+
+    ScriptLineProfile lineProfile = _profileMap[line.line];
+    if (lineProfile == null) {
+      e.classes.add('noProfile');
+      e.text = nbsp;
+      return e;
+    }
+
+    if (self) {
+      e.text = lineProfile.formattedSelfTicks;
+    } else {
+      e.text = lineProfile.formattedTotalTicks;
+    }
+
+    if (lineProfile.isHot(self)) {
+      e.classes.add('hotProfile');
+    } else if (lineProfile.isMedium(self)) {
+      e.classes.add('mediumProfile');
+    } else {
+      e.classes.add('coldProfile');
+    }
+
+    return e;
+  }
+
+  Element lineBreakpointElement(S.ScriptLine line) {
+    var e = new DivElement();
+    if (line == null || !_possibleBreakpointLines.contains(line.line)) {
+      e.classes.add('noCopy');
+      e.classes.add("emptyBreakpoint");
+      e.text = nbsp;
+      return e;
+    }
+
+    e.text = 'B';
+    var busy = false;
+    void update() {
+      e.classes.clear();
+      e.classes.add('noCopy');
+      if (busy) {
+        e.classes.add("busyBreakpoint");
+      } else if (line.breakpoints != null) {
+        bool resolved = false;
+        for (var bpt in line.breakpoints) {
+          if (bpt.resolved) {
+            resolved = true;
+            break;
+          }
+        }
+        if (resolved) {
+          e.classes.add("resolvedBreakpoint");
+        } else {
+          e.classes.add("unresolvedBreakpoint");
+        }
+      } else {
+        e.classes.add("possibleBreakpoint");
+      }
+    }
+
+    e.onClick.listen((event) {
+      if (busy) {
+        return;
+      }
+      busy = true;
+      if (line.breakpoints == null) {
+        // No breakpoint.  Add it.
+        line.script.isolate
+            .addBreakpoint(line.script, line.line)
+            .catchError((e, st) {
+          if (e is! S.ServerRpcException ||
+              (e as S.ServerRpcException).code !=
+                  S.ServerRpcException.kCannotAddBreakpoint) {
+            ObservatoryApplication.app.handleException(e, st);
+          }
+        }).whenComplete(() {
+          busy = false;
+          update();
+        });
+      } else {
+        // Existing breakpoint.  Remove it.
+        List<Future> pending = [];
+        for (var bpt in line.breakpoints) {
+          pending.add(line.script.isolate.removeBreakpoint(bpt));
+        }
+        Future.wait(pending).then((_) {
+          busy = false;
+          update();
+        });
+      }
+      update();
+    });
+    update();
+    return e;
+  }
+
+  Element lineNumberElement(S.ScriptLine line, int lineNumPad) {
+    var lineNumber = line == null ? "..." : line.line;
+    var e =
+        span("$nbsp${lineNumber.toString().padLeft(lineNumPad, nbsp)}$nbsp");
+    e.classes.add('noCopy');
+    if (lineNumber == _currentLine) {
+      hitsCurrent(e);
+      return e;
+    }
+    var ranges = _rangeMap[lineNumber];
+    if ((ranges == null) || ranges.isEmpty) {
+      // This line is not code.
+      hitsUnknown(e);
+      return e;
+    }
+    bool compiled = true;
+    bool hasCallInfo = false;
+    bool executed = false;
+    for (var range in ranges) {
+      if (range['compiled']) {
+        for (var callSite in range['callSites']) {
+          var callLine = line.script.tokenToLine(callSite['tokenPos']);
+          if (lineNumber == callLine) {
+            // The call site is on the current line.
+            hasCallInfo = true;
+            for (var cacheEntry in callSite['cacheEntries']) {
+              if (cacheEntry['count'] > 0) {
+                // If any call site on the line has been executed, we
+                // mark the line as executed.
+                executed = true;
+                break;
+              }
+            }
+          }
+        }
+      } else {
+        // If any range isn't compiled, show the line as not compiled.
+        // This is necessary so that nested functions appear to be uncompiled.
+        compiled = false;
+      }
+    }
+    if (executed) {
+      hitsExecuted(e);
+    } else if (hasCallInfo) {
+      hitsNotExecuted(e);
+    } else if (compiled) {
+      hitsCompiled(e);
+    } else {
+      hitsNotCompiled(e);
+    }
+    return e;
+  }
+
+  Element lineSourceElement(S.ScriptLine line) {
+    var e = new DivElement();
+    e.classes.add("sourceItem");
+
+    if (line != null) {
+      e.classes.add(makeLineClass(line.line));
+      if (line.line == _currentLine) {
+        e.classes.add("currentLine");
+      }
+
+      var position = 0;
+      consumeUntil(var stop) {
+        if (stop <= position) {
+          return null; // Empty gap between annotations/boundries.
+        }
+        if (stop > line.text.length) {
+          // Approximated token length can run past the end of the line.
+          stop = line.text.length;
+        }
+
+        var chunk = line.text.substring(position, stop);
+        var chunkNode = span(chunk);
+        e.append(chunkNode);
+        position = stop;
+        return chunkNode;
+      }
+
+      // TODO(rmacnak): Tolerate overlapping annotations.
+      var annotation;
+      while ((annotation = nextAnnotationOnLine(line.line)) != null) {
+        consumeUntil(annotation.columnStart);
+        annotation.applyStyleTo(consumeUntil(annotation.columnStop));
+      }
+      consumeUntil(line.text.length);
+    }
+
+    // So blank lines are included when copying script to the clipboard.
+    e.append(span('\n'));
+
+    return e;
+  }
+
+  /// Exclude nodes from being copied, for example the line numbers and
+  /// breakpoint toggles in script insets. Must be called after [root]'s
+  /// children have been added, and only supports one node at a time.
+  static void _makeCssClassUncopyable(Element root, String className) {
+    var noCopyNodes = root.getElementsByClassName(className);
+    for (HtmlElement node in noCopyNodes) {
+      node.style.setProperty('-moz-user-select', 'none');
+      node.style.setProperty('-khtml-user-select', 'none');
+      node.style.setProperty('-webkit-user-select', 'none');
+      node.style.setProperty('-ms-user-select', 'none');
+      node.style.setProperty('user-select', 'none');
+    }
+    root.onCopy.listen((event) {
+      // Mark the nodes as hidden before the copy happens, then mark them as
+      // visible on the next event loop turn.
+      for (HtmlElement node in noCopyNodes) {
+        node.style.visibility = 'hidden';
+      }
+      Timer.run(() {
+        for (HtmlElement node in noCopyNodes) {
+          node.style.visibility = 'visible';
+        }
+      });
+    });
+  }
+}
+
+const nbsp = "\u00A0";
+
+void addInfoBox(Element content, Function infoBoxGenerator) {
+  var infoBox;
+  var show = false;
+  var originalBackground = content.style.backgroundColor;
+  buildInfoBox() {
+    infoBox = infoBoxGenerator();
+    infoBox.style.position = 'absolute';
+    infoBox.style.padding = '1em';
+    infoBox.style.border = 'solid black 2px';
+    infoBox.style.zIndex = '10';
+    infoBox.style.backgroundColor = 'white';
+    infoBox.style.cursor = 'auto';
+    // Don't inherit pre formatting from the script lines.
+    infoBox.style.whiteSpace = 'normal';
+    content.append(infoBox);
+  }
+
+  content.onClick.listen((event) {
+    show = !show;
+    if (infoBox == null) buildInfoBox(); // Created lazily on the first click.
+    infoBox.style.display = show ? 'block' : 'none';
+    content.style.backgroundColor = show ? 'white' : originalBackground;
+  });
+
+  // Causes infoBox to be positioned relative to the bottom-left of content.
+  content.style.display = 'inline-block';
+  content.style.cursor = 'pointer';
+}
+
+void addLink(Element content, String target) {
+  // Ick, destructive but still compatible with also adding an info box.
+  var a = new AnchorElement(href: target);
+  a.text = content.text;
+  content.text = '';
+  content.append(a);
+}
+
+abstract class Annotation implements Comparable<Annotation> {
+  M.IsolateRef _isolate;
+  M.ObjectRepository _objects;
+  RenderingQueue queue;
+  int line;
+  int columnStart;
+  int columnStop;
+  int get priority;
+
+  Annotation(this._isolate, this._objects, this.queue);
+
+  void applyStyleTo(element);
+
+  int compareTo(Annotation other) {
+    if (line == other.line) {
+      if (columnStart == other.columnStart) {
+        return priority.compareTo(other.priority);
+      }
+      return columnStart.compareTo(other.columnStart);
+    }
+    return line.compareTo(other.line);
+  }
+
+  Element table() {
+    var e = new DivElement();
+    e.style.display = "table";
+    e.style.color = "#333";
+    e.style.font = "400 14px 'Montserrat', sans-serif";
+    return e;
+  }
+
+  Element row([content]) {
+    var e = new DivElement();
+    e.style.display = "table-row";
+    if (content is String) e.text = content;
+    if (content is Element) e.children.add(content);
+    return e;
+  }
+
+  Element cell(content) {
+    var e = new DivElement();
+    e.style.display = "table-cell";
+    e.style.padding = "3px";
+    if (content is String) e.text = content;
+    if (content is Element) e.children.add(content);
+    return e;
+  }
+
+  Element serviceRef(object) {
+    return anyRef(_isolate, object, _objects, queue: queue);
+  }
+}
+
+class CurrentExecutionAnnotation extends Annotation {
+  int priority = 0; // highest priority.
+
+  CurrentExecutionAnnotation(
+      M.IsolateRef isolate, M.ObjectRepository objects, RenderingQueue queue)
+      : super(isolate, objects, queue);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.classes.add("currentCol");
+    element.title = "Current execution";
+  }
+}
+
+class BreakpointAnnotation extends Annotation {
+  M.Breakpoint bpt;
+  int priority = 1;
+
+  BreakpointAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, this.bpt)
+      : super(isolate, objects, queue) {
+    S.Script script = bpt.location.script;
+    var location = bpt.location;
+    if (location.tokenPos != null) {
+      var pos = location.tokenPos;
+      line = script.tokenToLine(pos);
+      columnStart = script.tokenToCol(pos) - 1; // tokenToCol is 1-origin.
+    } else if (location is M.UnresolvedSourceLocation) {
+      line = location.line;
+      columnStart = location.column;
+      if (columnStart == null) {
+        columnStart = 0;
+      }
+    }
+    var length = script.guessTokenLength(line, columnStart);
+    if (length == null) {
+      length = 1;
+    }
+    columnStop = columnStart + length;
+  }
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    S.Script script = bpt.location.script;
+    var pos = bpt.location.tokenPos;
+    int line = script.tokenToLine(pos);
+    int column = script.tokenToCol(pos);
+    if (bpt.resolved) {
+      element.classes.add("resolvedBreakAnnotation");
+    } else {
+      element.classes.add("unresolvedBreakAnnotation");
+    }
+    element.title = "Breakpoint ${bpt.number} at ${line}:${column}";
+  }
+}
+
+class LibraryAnnotation extends Annotation {
+  S.Library target;
+  String url;
+  int priority = 2;
+
+  LibraryAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, this.target, this.url)
+      : super(isolate, objects, queue);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.title = "library ${target.uri}";
+    addLink(element, url);
+  }
+}
+
+class PartAnnotation extends Annotation {
+  S.Script part;
+  String url;
+  int priority = 2;
+
+  PartAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, this.part, this.url)
+      : super(isolate, objects, queue);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.title = "script ${part.uri}";
+    addLink(element, url);
+  }
+}
+
+class LocalVariableAnnotation extends Annotation {
+  final value;
+  int priority = 2;
+
+  LocalVariableAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, S.LocalVarLocation location, this.value)
+      : super(isolate, objects, queue) {
+    line = location.line;
+    columnStart = location.column;
+    columnStop = location.endColumn;
+  }
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.style.fontWeight = "bold";
+    element.title = "${value.shortName}";
+  }
+}
+
+class CallSiteAnnotation extends Annotation {
+  S.CallSite callSite;
+  int priority = 2;
+
+  CallSiteAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, this.callSite)
+      : super(isolate, objects, queue) {
+    line = callSite.line;
+    columnStart = callSite.column - 1; // Call site is 1-origin.
+    var tokenLength = callSite.script.guessTokenLength(line, columnStart);
+    if (tokenLength == null) {
+      tokenLength = callSite.name.length; // Approximate.
+      if (callSite.name.startsWith("get:") || callSite.name.startsWith("set:"))
+        tokenLength -= 4;
+    }
+    columnStop = columnStart + tokenLength;
+  }
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.style.fontWeight = "bold";
+    element.title = "Call site: ${callSite.name}";
+
+    addInfoBox(element, () {
+      var details = table();
+      if (callSite.entries.isEmpty) {
+        details.append(row('Call of "${callSite.name}" did not execute'));
+      } else {
+        var r = row();
+        r.append(cell("Container"));
+        r.append(cell("Count"));
+        r.append(cell("Target"));
+        details.append(r);
+
+        for (var entry in callSite.entries) {
+          var r = row();
+          if (entry.receiver == null) {
+            r.append(cell(""));
+          } else {
+            r.append(cell(serviceRef(entry.receiver)));
+          }
+          r.append(cell(entry.count.toString()));
+          r.append(cell(serviceRef(entry.target)));
+          details.append(r);
+        }
+      }
+      return details;
+    });
+  }
+}
+
+abstract class DeclarationAnnotation extends Annotation {
+  String url;
+  int priority = 2;
+
+  DeclarationAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, decl, this.url)
+      : super(isolate, objects, queue) {
+    assert(decl.loaded);
+    S.SourceLocation location = decl.location;
+    if (location == null) {
+      line = 0;
+      columnStart = 0;
+      columnStop = 0;
+      return;
+    }
+
+    S.Script script = location.script;
+    line = script.tokenToLine(location.tokenPos);
+    columnStart = script.tokenToCol(location.tokenPos);
+    if ((line == null) || (columnStart == null)) {
+      line = 0;
+      columnStart = 0;
+      columnStop = 0;
+    } else {
+      columnStart--; // 1-origin -> 0-origin.
+
+      // The method's token position is at the beginning of the method
+      // declaration, which may be a return type annotation, metadata, static
+      // modifier, etc. Try to scan forward to position this annotation on the
+      // function's name instead.
+      var lineSource = script.getLine(line).text;
+      var betterStart = lineSource.indexOf(decl.name, columnStart);
+      if (betterStart != -1) {
+        columnStart = betterStart;
+      }
+      columnStop = columnStart + decl.name.length;
+    }
+  }
+}
+
+class ClassDeclarationAnnotation extends DeclarationAnnotation {
+  S.Class klass;
+
+  ClassDeclarationAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, S.Class cls, String url)
+      : klass = cls,
+        super(isolate, objects, queue, cls, url);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    element.title = "class ${klass.name}";
+    addLink(element, url);
+  }
+}
+
+class FieldDeclarationAnnotation extends DeclarationAnnotation {
+  S.Field field;
+
+  FieldDeclarationAnnotation(M.IsolateRef isolate, M.ObjectRepository objects,
+      RenderingQueue queue, S.Field fld, String url)
+      : field = fld,
+        super(isolate, objects, queue, fld, url);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    var tooltip = "field ${field.name}";
+    element.title = tooltip;
+    addLink(element, url);
+  }
+}
+
+class FunctionDeclarationAnnotation extends DeclarationAnnotation {
+  S.ServiceFunction function;
+
+  FunctionDeclarationAnnotation(
+      M.IsolateRef isolate,
+      M.ObjectRepository objects,
+      RenderingQueue queue,
+      S.ServiceFunction func,
+      String url)
+      : function = func,
+        super(isolate, objects, queue, func, url);
+
+  void applyStyleTo(element) {
+    if (element == null) {
+      return; // TODO(rmacnak): Handling overlapping annotations.
+    }
+    var tooltip = "method ${function.name}";
+    if (function.isOptimizable == false) {
+      tooltip += "\nUnoptimizable!";
+    }
+    if (function.isInlinable == false) {
+      tooltip += "\nNot inlinable!";
+    }
+    if (function.deoptimizations > 0) {
+      tooltip += "\nDeoptimized ${function.deoptimizations} times!";
+    }
+    element.title = tooltip;
+
+    if (function.isOptimizable == false ||
+        function.isInlinable == false ||
+        function.deoptimizations > 0) {
+      element.style.backgroundColor = "#EEA7A7"; // Low-saturation red.
+    }
+
+    addLink(element, url);
+  }
+}
+
+class ScriptLineProfile {
+  ScriptLineProfile(this.line, this.sampleCount);
+
+  static const kHotThreshold = 0.05; // 5%.
+  static const kMediumThreshold = 0.02; // 2%.
+
+  final int line;
+  final int sampleCount;
+
+  int selfTicks = 0;
+  int totalTicks = 0;
+
+  void process(int exclusive, int inclusive) {
+    selfTicks += exclusive;
+    totalTicks += inclusive;
+  }
+
+  String get formattedSelfTicks {
+    return Utils.formatPercent(selfTicks, sampleCount);
+  }
+
+  String get formattedTotalTicks {
+    return Utils.formatPercent(totalTicks, sampleCount);
+  }
+
+  double _percent(bool self) {
+    if (sampleCount == 0) {
+      return 0.0;
+    }
+    if (self) {
+      return selfTicks / sampleCount;
+    } else {
+      return totalTicks / sampleCount;
+    }
+  }
+
+  bool isHot(bool self) => _percent(self) > kHotThreshold;
+  bool isMedium(bool self) => _percent(self) > kMediumThreshold;
+}
+
+final SvgSvgElement _iconRefresh = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 '
+              '3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 '
+              '7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 '
+              '0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 '
+              '1.78L13 11h7V4l-2.35 2.35z')
+  ];
+
+final SvgSvgElement _iconWhatsHot = new SvgSvgElement()
+  ..setAttribute('width', '24')
+  ..setAttribute('height', '24')
+  ..children = <Element>[
+    new PathElement()
+      ..setAttribute(
+          'd',
+          'M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 '
+              '3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 '
+              '4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 '
+              '17.41 3.8 13.5.67zM11.71 19c-1.78 '
+              '0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 '
+              '1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 '
+              '4.04 0 2.65-2.15 4.8-4.8 4.8z')
+  ];
diff --git a/runtime/observatory_2/lib/src/elements/script_ref.dart b/runtime/observatory_2/lib/src/elements/script_ref.dart
new file mode 100644
index 0000000..02bf797
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/script_ref.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library script_ref_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, ScriptRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class ScriptRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<ScriptRefElement> _r;
+
+  Stream<RenderedEvent<ScriptRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ScriptRef _script;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ScriptRef get script => _script;
+
+  factory ScriptRefElement(M.IsolateRef isolate, M.ScriptRef script,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(script != null);
+    ScriptRefElement e = new ScriptRefElement.created();
+    e._r = new RenderingScheduler<ScriptRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._script = script;
+    return e;
+  }
+
+  ScriptRefElement.created() : super.created('script-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    var displayUri = script.uri.split('/').last;
+    if (displayUri.isEmpty) {
+      displayUri = 'N/A';
+    }
+
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(isolate, object: script))
+        ..title = script.uri
+        ..text = displayUri
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/script_view.dart b/runtime/observatory_2/lib/src/elements/script_view.dart
new file mode 100644
index 0000000..349aabc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/script_view.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library script_view;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/context_ref.dart';
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/library_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/script_inset.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class ScriptViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<ScriptViewElement> _r;
+
+  Stream<RenderedEvent<ScriptViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.Script _script;
+  M.ScriptRepository _scripts;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+  int _pos;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.Script get script => _script;
+
+  factory ScriptViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Script script,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.ScriptRepository scripts,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {int pos,
+      RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(script != null);
+    assert(scripts != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    ScriptViewElement e = new ScriptViewElement.created();
+    e._r = new RenderingScheduler<ScriptViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._script = script;
+    e._scripts = scripts;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    e._pos = pos;
+    return e;
+  }
+
+  ScriptViewElement.created() : super.created('script-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        new NavLibraryMenuElement(_isolate, _script.library, queue: _r.queue)
+            .element,
+        navMenu('object'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _script = await _scripts.get(_isolate, _script.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Script',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _script, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new BRElement(),
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'load time',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = '${_script.loadTime}'
+                ],
+            ],
+          new HRElement(),
+          new ScriptInsetElement(_isolate, _script, _scripts, _objects, _events,
+                  currentPos: _pos, queue: _r.queue)
+              .element,
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/sentinel_value.dart b/runtime/observatory_2/lib/src/elements/sentinel_value.dart
new file mode 100644
index 0000000..c29c6c6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/sentinel_value.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/models.dart' as M show Sentinel, SentinelKind;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class SentinelValueElement extends CustomElement implements Renderable {
+  RenderingScheduler<SentinelValueElement> _r;
+
+  Stream<RenderedEvent<SentinelValueElement>> get onRendered => _r.onRendered;
+
+  M.Sentinel _sentinel;
+
+  M.Sentinel get sentinel => _sentinel;
+
+  factory SentinelValueElement(M.Sentinel sentinel, {RenderingQueue queue}) {
+    assert(sentinel != null);
+    SentinelValueElement e = new SentinelValueElement.created();
+    e._r = new RenderingScheduler<SentinelValueElement>(e, queue: queue);
+    e._sentinel = sentinel;
+    return e;
+  }
+
+  SentinelValueElement.created() : super.created('sentinel-value');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    text = '';
+    title = '';
+  }
+
+  void render() {
+    text = _sentinel.valueAsString;
+    title = _sentinelKindToDescription(_sentinel.kind);
+  }
+
+  static String _sentinelKindToDescription(M.SentinelKind kind) {
+    switch (kind) {
+      case M.SentinelKind.collected:
+        return 'This object has been reclaimed by the garbage collector.';
+      case M.SentinelKind.expired:
+        return 'The handle to this object has expired. '
+            'Consider refreshing the page.';
+      case M.SentinelKind.notInitialized:
+        return 'This object will be initialized once it is accessed by '
+            'the program.';
+      case M.SentinelKind.initializing:
+        return 'This object is currently being initialized.';
+      case M.SentinelKind.optimizedOut:
+        return 'This object is no longer needed and has been removed by the '
+            'optimizing compiler.';
+      case M.SentinelKind.free:
+        return '';
+    }
+    throw new Exception('Unknown SentinelKind: $kind');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/sentinel_view.dart b/runtime/observatory_2/lib/src/elements/sentinel_view.dart
new file mode 100644
index 0000000..5628e78
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/sentinel_view.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class SentinelViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<SentinelViewElement> _r;
+
+  Stream<RenderedEvent<SentinelViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.Sentinel _sentinel;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+
+  M.Sentinel get sentinel => _sentinel;
+
+  factory SentinelViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.Sentinel sentinel,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(sentinel != null);
+    assert(events != null);
+    assert(notifications != null);
+    SentinelViewElement e = new SentinelViewElement.created();
+    e._r = new RenderingScheduler<SentinelViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._sentinel = sentinel;
+    e._events = events;
+    e._notifications = notifications;
+    return e;
+  }
+
+  SentinelViewElement.created() : super.created('sentinel-view');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    text = '';
+    title = '';
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('sentinel'),
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()
+            ..text = 'Sentinel: #{_sentinel.valueAsString}',
+          new HRElement(),
+          new DivElement()..text = _sentinelKindToDescription(_sentinel.kind),
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+
+  static String _sentinelKindToDescription(M.SentinelKind kind) {
+    switch (kind) {
+      case M.SentinelKind.collected:
+        return 'This object has been reclaimed by the garbage collector.';
+      case M.SentinelKind.expired:
+        return 'The handle to this object has expired. '
+            'Consider refreshing the page.';
+      case M.SentinelKind.notInitialized:
+        return 'This object will be initialized once it is accessed by '
+            'the program.';
+      case M.SentinelKind.initializing:
+        return 'This object is currently being initialized.';
+      case M.SentinelKind.optimizedOut:
+        return 'This object is no longer needed and has been removed by the '
+            'optimizing compiler.';
+      case M.SentinelKind.free:
+        return '';
+    }
+    throw new Exception('Unknown SentinelKind: $kind');
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/singletargetcache_ref.dart b/runtime/observatory_2/lib/src/elements/singletargetcache_ref.dart
new file mode 100644
index 0000000..f47d008
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/singletargetcache_ref.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, SingleTargetCacheRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class SingleTargetCacheRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<SingleTargetCacheRefElement> _r;
+
+  Stream<RenderedEvent<SingleTargetCacheRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.SingleTargetCacheRef _singleTargetCache;
+
+  M.IsolateRef get isolate => _isolate;
+  M.SingleTargetCacheRef get singleTargetCache => _singleTargetCache;
+
+  factory SingleTargetCacheRefElement(
+      M.IsolateRef isolate, M.SingleTargetCacheRef singleTargetCache,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(singleTargetCache != null);
+    SingleTargetCacheRefElement e = new SingleTargetCacheRefElement.created();
+    e._r = new RenderingScheduler<SingleTargetCacheRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._singleTargetCache = singleTargetCache;
+    return e;
+  }
+
+  SingleTargetCacheRefElement.created()
+      : super.created('singletargetcache-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(
+          href: Uris.inspect(_isolate, object: _singleTargetCache))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'SingleTargetCache',
+          new SpanElement()..text = ' (${_singleTargetCache.target.name})'
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/singletargetcache_view.dart b/runtime/observatory_2/lib/src/elements/singletargetcache_view.dart
new file mode 100644
index 0000000..b8d3224
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/singletargetcache_view.dart
@@ -0,0 +1,178 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class SingleTargetCacheViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<SingleTargetCacheViewElement> _r;
+
+  Stream<RenderedEvent<SingleTargetCacheViewElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.SingleTargetCache _singleTargetCache;
+  M.SingleTargetCacheRepository _singleTargetCaches;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.SingleTargetCache get singleTargetCache => _singleTargetCache;
+
+  factory SingleTargetCacheViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.SingleTargetCache singleTargetCache,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.SingleTargetCacheRepository singleTargetCaches,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(singleTargetCache != null);
+    assert(singleTargetCaches != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    SingleTargetCacheViewElement e = new SingleTargetCacheViewElement.created();
+    e._r =
+        new RenderingScheduler<SingleTargetCacheViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._singleTargetCache = singleTargetCache;
+    e._singleTargetCaches = singleTargetCaches;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  SingleTargetCacheViewElement.created()
+      : super.created(
+          'singletargetcache-view',
+        );
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('singleTargetCache'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _singleTargetCache = await _singleTargetCaches.get(
+                    _isolate, _singleTargetCache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'SingleTargetCache',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _singleTargetCache, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'target',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      anyRef(_isolate, _singleTargetCache.target, _objects,
+                          queue: _r.queue)
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'lowerLimit',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      new SpanElement()
+                        ..text = _singleTargetCache.lowerLimit.toString()
+                    ]
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'upperLimit',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      new SpanElement()
+                        ..text = _singleTargetCache.upperLimit.toString()
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/source_inset.dart b/runtime/observatory_2/lib/src/elements/source_inset.dart
new file mode 100644
index 0000000..ac94f30
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/source_inset.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library source_inset_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/script_inset.dart';
+
+class SourceInsetElement extends CustomElement implements Renderable {
+  RenderingScheduler<SourceInsetElement> _r;
+
+  Stream<RenderedEvent<SourceInsetElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.SourceLocation _location;
+  M.ScriptRepository _scripts;
+  M.ObjectRepository _objects;
+  M.EventRepository _events;
+  int _currentPos;
+  bool _inDebuggerContext;
+  Iterable _variables;
+
+  M.IsolateRef get isolate => _isolate;
+  M.SourceLocation get location => _location;
+
+  factory SourceInsetElement(
+      M.IsolateRef isolate,
+      M.SourceLocation location,
+      M.ScriptRepository scripts,
+      M.ObjectRepository objects,
+      M.EventRepository events,
+      {int currentPos,
+      bool inDebuggerContext: false,
+      Iterable variables: const [],
+      RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(location != null);
+    assert(scripts != null);
+    assert(objects != null);
+    assert(events != null);
+    assert(inDebuggerContext != null);
+    assert(variables != null);
+    SourceInsetElement e = new SourceInsetElement.created();
+    e._r = new RenderingScheduler<SourceInsetElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._location = location;
+    e._scripts = scripts;
+    e._objects = objects;
+    e._events = events;
+    e._currentPos = currentPos;
+    e._inDebuggerContext = inDebuggerContext;
+    e._variables = variables;
+    return e;
+  }
+
+  SourceInsetElement.created() : super.created('source-inset');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      new ScriptInsetElement(
+              _isolate, _location.script, _scripts, _objects, _events,
+              startPos: _location.tokenPos,
+              endPos: _location.endTokenPos,
+              currentPos: _currentPos,
+              inDebuggerContext: _inDebuggerContext,
+              variables: _variables,
+              queue: _r.queue)
+          .element
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/source_link.dart b/runtime/observatory_2/lib/src/elements/source_link.dart
new file mode 100644
index 0000000..8820b50
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/source_link.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library source_link_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart'
+    show IsolateRef, SourceLocation, Script, ScriptRepository;
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class SourceLinkElement extends CustomElement implements Renderable {
+  RenderingScheduler<SourceLinkElement> _r;
+
+  Stream<RenderedEvent<SourceLinkElement>> get onRendered => _r.onRendered;
+
+  IsolateRef _isolate;
+  SourceLocation _location;
+  Script _script;
+  ScriptRepository _repository;
+
+  IsolateRef get isolate => _isolate;
+  SourceLocation get location => _location;
+
+  factory SourceLinkElement(
+      IsolateRef isolate, SourceLocation location, ScriptRepository repository,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(location != null);
+    SourceLinkElement e = new SourceLinkElement.created();
+    e._r = new RenderingScheduler<SourceLinkElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._location = location;
+    e._repository = repository;
+    return e;
+  }
+
+  SourceLinkElement.created() : super.created('source-link');
+
+  @override
+  void attached() {
+    super.attached();
+    _repository.get(_isolate, _location.script.id).then((script) {
+      _script = script;
+      _r.dirty();
+    }, onError: (e) {
+      // The script object has expired, likely due to a hot reload.
+      (_isolate as S.Isolate).getScripts().then((scripts) {
+        for (final script in scripts) {
+          if (script.uri == _location.script.uri) {
+            _script = script;
+            _r.dirty();
+            return;
+          }
+        }
+        // Rethrow the original exception if we can't find a match.
+        throw e;
+      });
+    });
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  Future render() async {
+    if (_script == null) {
+      children = <Element>[new SpanElement()..text = '<LOADING>'];
+    } else {
+      String label = _script.uri.split('/').last;
+      int token = _location.tokenPos;
+      int line = _script.tokenToLine(token);
+      int column = _script.tokenToCol(token);
+      children = <Element>[
+        new AnchorElement(
+            href: Uris.inspect(isolate, object: _script, pos: token))
+          ..title = _script.uri
+          ..text = '${label}:${line}:${column}'
+      ];
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/stack_trace_tree_config.dart b/runtime/observatory_2/lib/src/elements/stack_trace_tree_config.dart
new file mode 100644
index 0000000..6e32334
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/stack_trace_tree_config.dart
@@ -0,0 +1,262 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+enum ProfileTreeMode {
+  code,
+  function,
+}
+
+class StackTraceTreeConfigChangedEvent {
+  final StackTraceTreeConfigElement element;
+  StackTraceTreeConfigChangedEvent(this.element);
+}
+
+class StackTraceTreeConfigElement extends CustomElement implements Renderable {
+  RenderingScheduler<StackTraceTreeConfigElement> _r;
+
+  Stream<RenderedEvent<StackTraceTreeConfigElement>> get onRendered =>
+      _r.onRendered;
+
+  StreamController<StackTraceTreeConfigChangedEvent> _onModeChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  StreamController<StackTraceTreeConfigChangedEvent> _onDirectionChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  StreamController<StackTraceTreeConfigChangedEvent> _onFilterChange =
+      new StreamController<StackTraceTreeConfigChangedEvent>.broadcast();
+  Stream<StackTraceTreeConfigChangedEvent> get onModeChange =>
+      _onModeChange.stream;
+  Stream<StackTraceTreeConfigChangedEvent> get onDirectionChange =>
+      _onDirectionChange.stream;
+  Stream<StackTraceTreeConfigChangedEvent> get onFilterChange =>
+      _onFilterChange.stream;
+
+  bool _showMode;
+  bool _showDirection;
+  bool _showFilter;
+  ProfileTreeMode _mode;
+  M.ProfileTreeDirection _direction;
+  String _filter;
+
+  bool get showMode => _showMode;
+  bool get showDirection => _showDirection;
+  bool get showFilter => _showFilter;
+  ProfileTreeMode get mode => _mode;
+  M.ProfileTreeDirection get direction => _direction;
+  String get filter => _filter;
+
+  set showMode(bool value) => _showMode = _r.checkAndReact(_showMode, value);
+  set showDirection(bool value) =>
+      _showDirection = _r.checkAndReact(_showDirection, value);
+  set showFilter(bool value) =>
+      _showFilter = _r.checkAndReact(_showFilter, value);
+  set mode(ProfileTreeMode value) => _mode = _r.checkAndReact(_mode, value);
+  set direction(M.ProfileTreeDirection value) =>
+      _direction = _r.checkAndReact(_direction, value);
+  set filter(String value) => _filter = _r.checkAndReact(_filter, value);
+
+  factory StackTraceTreeConfigElement(
+      {bool showMode: true,
+      bool showDirection: true,
+      bool showFilter: true,
+      String filter: '',
+      ProfileTreeMode mode: ProfileTreeMode.function,
+      M.ProfileTreeDirection direction: M.ProfileTreeDirection.exclusive,
+      RenderingQueue queue}) {
+    assert(showMode != null);
+    assert(showDirection != null);
+    assert(showFilter != null);
+    assert(mode != null);
+    assert(direction != null);
+    assert(filter != null);
+    StackTraceTreeConfigElement e = new StackTraceTreeConfigElement.created();
+    e._r = new RenderingScheduler<StackTraceTreeConfigElement>(e, queue: queue);
+    e._showMode = showMode;
+    e._showDirection = showDirection;
+    e._showFilter = showFilter;
+    e._mode = mode;
+    e._direction = direction;
+    e._filter = filter;
+    return e;
+  }
+
+  StackTraceTreeConfigElement.created()
+      : super.created('stack-trace-tree-config');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = const [];
+  }
+
+  void render() {
+    children = <Element>[
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'Tree display',
+          new HRElement(),
+          new DivElement()
+            ..classes = ['row']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberList']
+                ..children = _createMembers()
+            ]
+        ]
+    ];
+  }
+
+  List<Element> _createMembers() {
+    var members = <Element>[];
+    if (_showMode) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Mode',
+          new DivElement()
+            ..classes = ['memberValue']
+            ..children = _createModeSelect()
+        ]);
+    }
+    if (_showDirection) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Call Tree Direction',
+          new SpanElement()
+            ..classes = ['memberValue']
+            ..children = _createDirectionSelect()
+        ]);
+    }
+    if (showFilter) {
+      members.add(new DivElement()
+        ..classes = ['memberItem']
+        ..children = <Element>[
+          new DivElement()
+            ..classes = ['memberName']
+            ..text = 'Call Tree Filter'
+            ..title = 'case-sensitive substring match',
+          new SpanElement()
+            ..classes = ['memberValue']
+            ..children = _createFilter()
+        ]);
+    }
+    return members;
+  }
+
+  String get modeDescription {
+    if (_mode == ProfileTreeMode.function) {
+      return 'Inlined frames expanded.';
+    } else {
+      return 'Inlined frames not expanded.';
+    }
+  }
+
+  List<Element> _createModeSelect() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['mode-select']
+        ..value = modeToString(_mode)
+        ..children = ProfileTreeMode.values.map((mode) {
+          return new OptionElement(
+              value: modeToString(mode), selected: _mode == mode)
+            ..text = modeToString(mode);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _mode = ProfileTreeMode.values[s.selectedIndex];
+          _r.dirty();
+        })
+        ..onChange.map(_toEvent).listen(_triggerModeChange),
+      new SpanElement()..text = ' $modeDescription'
+    ];
+  }
+
+  String get directionDescription {
+    if (_direction == M.ProfileTreeDirection.inclusive) {
+      return 'Tree is rooted at "main". Child nodes are callees.';
+    } else {
+      return 'Tree is rooted at top-of-stack. Child nodes are callers.';
+    }
+  }
+
+  List<Element> _createDirectionSelect() {
+    var s;
+    return [
+      s = new SelectElement()
+        ..classes = ['direction-select']
+        ..value = directionToString(_direction)
+        ..children = M.ProfileTreeDirection.values.map((direction) {
+          return new OptionElement(
+              value: directionToString(direction),
+              selected: _direction == direction)
+            ..text = directionToString(direction);
+        }).toList(growable: false)
+        ..onChange.listen((_) {
+          _direction = M.ProfileTreeDirection.values[s.selectedIndex];
+          _r.dirty();
+        })
+        ..onChange.map(_toEvent).listen(_triggerDirectionChange),
+      new SpanElement()..text = ' $directionDescription'
+    ];
+  }
+
+  List<Element> _createFilter() {
+    var t;
+    return [
+      t = new TextInputElement()
+        ..placeholder = 'Search filter'
+        ..value = filter
+        ..onChange.listen((_) {
+          _filter = t.value;
+        })
+        ..onChange.map(_toEvent).listen(_triggerFilterChange)
+    ];
+  }
+
+  static String modeToString(ProfileTreeMode mode) {
+    switch (mode) {
+      case ProfileTreeMode.code:
+        return 'Code';
+      case ProfileTreeMode.function:
+        return 'Function';
+    }
+    throw new Exception('Unknown ProfileTreeMode');
+  }
+
+  static String directionToString(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive:
+        return 'Top down';
+      case M.ProfileTreeDirection.exclusive:
+        return 'Bottom up';
+    }
+    throw new Exception('Unknown ProfileTreeDirection');
+  }
+
+  StackTraceTreeConfigChangedEvent _toEvent(_) {
+    return new StackTraceTreeConfigChangedEvent(this);
+  }
+
+  void _triggerModeChange(e) => _onModeChange.add(e);
+  void _triggerDirectionChange(e) => _onDirectionChange.add(e);
+  void _triggerFilterChange(e) => _onFilterChange.add(e);
+}
diff --git a/runtime/observatory_2/lib/src/elements/strongly_reachable_instances.dart b/runtime/observatory_2/lib/src/elements/strongly_reachable_instances.dart
new file mode 100644
index 0000000..45e11e8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/strongly_reachable_instances.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/instance_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class StronglyReachableInstancesElement extends CustomElement
+    implements Renderable {
+  RenderingScheduler<StronglyReachableInstancesElement> _r;
+
+  Stream<RenderedEvent<StronglyReachableInstancesElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.ClassRef _cls;
+  M.StronglyReachableInstancesRepository _stronglyReachableInstances;
+  M.ObjectRepository _objects;
+  M.InstanceSet _result;
+  bool _expanded = false;
+
+  M.IsolateRef get isolate => _isolate;
+  M.ClassRef get cls => _cls;
+
+  factory StronglyReachableInstancesElement(
+      M.IsolateRef isolate,
+      M.ClassRef cls,
+      M.StronglyReachableInstancesRepository stronglyReachable,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(cls != null);
+    assert(stronglyReachable != null);
+    assert(objects != null);
+    StronglyReachableInstancesElement e =
+        new StronglyReachableInstancesElement.created();
+    e._r = new RenderingScheduler<StronglyReachableInstancesElement>(e,
+        queue: queue);
+    e._isolate = isolate;
+    e._cls = cls;
+    e._stronglyReachableInstances = stronglyReachable;
+    e._objects = objects;
+    return e;
+  }
+
+  StronglyReachableInstancesElement.created()
+      : super.created('strongly-reachable-instances');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      (new CurlyBlockElement(expanded: _expanded, queue: _r.queue)
+            ..content = _createContent()
+            ..onToggle.listen((e) async {
+              _expanded = e.control.expanded;
+              e.control.disabled = true;
+              await _refresh();
+              e.control.disabled = false;
+            }))
+          .element
+    ];
+  }
+
+  Future _refresh() async {
+    _result = null;
+    _result = await _stronglyReachableInstances.get(_isolate, _cls);
+    _r.dirty();
+  }
+
+  List<Element> _createContent() {
+    if (_result == null) {
+      return [new SpanElement()..text = 'Loading...'];
+    }
+    final content = _result.instances
+        .map<Element>((sample) => new DivElement()
+          ..children = <Element>[
+            anyRef(_isolate, sample, _objects, queue: _r.queue)
+          ])
+        .toList();
+    content.add(new DivElement()
+      ..children = ([]
+        ..addAll(_createShowMoreButton())
+        ..add(new SpanElement()..text = ' of total ${_result.count}')));
+    return content;
+  }
+
+  List<Element> _createShowMoreButton() {
+    final samples = _result.instances.toList();
+    if (samples.length == _result.count) {
+      return [];
+    }
+    final count = samples.length;
+    final button = new ButtonElement()..text = 'show next ${count}';
+    button.onClick.listen((_) async {
+      button.disabled = true;
+      _result = await _stronglyReachableInstances.get(_isolate, _cls,
+          limit: count * 2);
+      _r.dirty();
+    });
+    return [button];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/subtypetestcache_ref.dart b/runtime/observatory_2/lib/src/elements/subtypetestcache_ref.dart
new file mode 100644
index 0000000..6cb5a25
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/subtypetestcache_ref.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M
+    show IsolateRef, SubtypeTestCacheRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class SubtypeTestCacheRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<SubtypeTestCacheRefElement> _r;
+
+  Stream<RenderedEvent<SubtypeTestCacheRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.SubtypeTestCacheRef _subtypeTestCache;
+
+  M.IsolateRef get isolate => _isolate;
+  M.SubtypeTestCacheRef get subtypeTestCache => _subtypeTestCache;
+
+  factory SubtypeTestCacheRefElement(
+      M.IsolateRef isolate, M.SubtypeTestCacheRef subtypeTestCache,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(subtypeTestCache != null);
+    SubtypeTestCacheRefElement e = new SubtypeTestCacheRefElement.created();
+    e._r = new RenderingScheduler<SubtypeTestCacheRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._subtypeTestCache = subtypeTestCache;
+    return e;
+  }
+
+  SubtypeTestCacheRefElement.created() : super.created('subtypetestcache-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _subtypeTestCache))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'SubtypeTestCache',
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/subtypetestcache_view.dart b/runtime/observatory_2/lib/src/elements/subtypetestcache_view.dart
new file mode 100644
index 0000000..ba42732
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/subtypetestcache_view.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class SubtypeTestCacheViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<SubtypeTestCacheViewElement> _r;
+
+  Stream<RenderedEvent<SubtypeTestCacheViewElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.SubtypeTestCache _subtypeTestCache;
+  M.SubtypeTestCacheRepository _subtypeTestCaches;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.SubtypeTestCache get subtypeTestCache => _subtypeTestCache;
+
+  factory SubtypeTestCacheViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.SubtypeTestCache subtypeTestCache,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.SubtypeTestCacheRepository subtypeTestCaches,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(subtypeTestCache != null);
+    assert(subtypeTestCaches != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    SubtypeTestCacheViewElement e = new SubtypeTestCacheViewElement.created();
+    e._r = new RenderingScheduler<SubtypeTestCacheViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._subtypeTestCache = subtypeTestCache;
+    e._subtypeTestCaches = subtypeTestCaches;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  SubtypeTestCacheViewElement.created()
+      : super.created('subtypetestcache-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('subtypeTestCache'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _subtypeTestCache = await _subtypeTestCaches.get(
+                    _isolate, _subtypeTestCache.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'SubtypeTestCache',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _subtypeTestCache, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'cache',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      anyRef(_isolate, _subtypeTestCache.cache, _objects,
+                          queue: _r.queue)
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/timeline/dashboard.dart b/runtime/observatory_2/lib/src/elements/timeline/dashboard.dart
new file mode 100644
index 0000000..8826324
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/timeline/dashboard.dart
@@ -0,0 +1,229 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This page is not directly reachable from the main Observatory ui.
+/// It is mainly mented to be used from editors as an integrated tool.
+///
+/// This page mainly targeting developers and not VM experts, so concepts like
+/// timeline streams are hidden away.
+///
+/// The page exposes two views over the timeline data.
+/// Both of them are filtered based on the optional argument `mode`.
+/// See [_TimelineView] for the explanation of the two possible values.
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:convert';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+
+/// The two possible views are available.
+/// * `string`
+///   The events are just filtered by `mode` and maintain their original
+///   timestamp.
+/// * `frame`
+///   The events are organized by frame.
+///   The events are shifted in order to give a high level view of the
+///   computation involved in a frame.
+///   The frame are concatenated one after the other taking care of not
+///   overlapping the related events.
+enum _TimelineView { strict, frame }
+
+class TimelineDashboardElement extends CustomElement implements Renderable {
+  RenderingScheduler<TimelineDashboardElement> _r;
+
+  Stream<RenderedEvent<TimelineDashboardElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.TimelineRepository _repository;
+  M.NotificationRepository _notifications;
+  M.TimelineFlags _flags;
+  _TimelineView _view = _TimelineView.strict;
+
+  M.VM get vm => _vm;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory TimelineDashboardElement(M.VM vm, M.TimelineRepository repository,
+      M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(repository != null);
+    assert(notifications != null);
+    TimelineDashboardElement e = new TimelineDashboardElement.created();
+    e._r = new RenderingScheduler<TimelineDashboardElement>(e, queue: queue);
+    e._vm = vm;
+    e._repository = repository;
+    e._notifications = notifications;
+    if (vm.embedder == 'Flutter') {
+      e._view = _TimelineView.frame;
+    }
+    return e;
+  }
+
+  TimelineDashboardElement.created() : super.created('timeline-dashboard');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _refresh();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  IFrameElement _frame;
+  DivElement _content;
+
+  void render() {
+    if (_frame == null) {
+      _frame = new IFrameElement();
+    }
+    if (_content == null) {
+      _content = new DivElement()..classes = ['content-centered-big'];
+    }
+    _frame.src = _makeFrameUrl();
+    _content.children = <Element>[
+      new HeadingElement.h2()
+        ..nodes = ([new Text("Timeline View")]
+          ..addAll(_createButtons())
+          ..addAll(_createTabs())),
+      new ParagraphElement()
+        ..text = (_view == _TimelineView.frame
+            ? 'Logical view of the computation involved in each frame '
+                '(timestamps may not be preserved)'
+            : 'Sequence of events generated during the execution '
+                '(timestamps are preserved)')
+    ];
+    if (children.isEmpty) {
+      children = <Element>[
+        navBar(<Element>[
+          new NavNotifyElement(_notifications, queue: _r.queue).element
+        ]),
+        _content,
+        new DivElement()
+          ..classes = ['iframe']
+          ..children = <Element>[_frame]
+      ];
+    }
+  }
+
+  List<Node> _createButtons() {
+    if (_flags == null) {
+      return [new Text('Loading')];
+    }
+    if (_suggestedProfile(_flags.profiles).streams.any((s) => !s.isRecorded)) {
+      return [
+        new ButtonElement()
+          ..classes = ['header_button']
+          ..text = 'Enable'
+          ..title = 'The Timeline is not fully enabled, click to enable'
+          ..onClick.listen((e) => _enable()),
+      ];
+    }
+    return [
+      new ButtonElement()
+        ..classes = ['header_button']
+        ..text = 'Load from VM'
+        ..title = 'Load the timeline'
+        ..onClick.listen((e) => _refresh()),
+      new ButtonElement()
+        ..classes = ['header_button']
+        ..text = 'Reset Timeline'
+        ..title = 'Reset the current timeline'
+        ..onClick.listen((e) => _clear()),
+      new ButtonElement()
+        ..classes = ['header_button', 'left-pad']
+        ..text = 'Save to File…'
+        ..title = 'Save the current Timeline to file'
+        ..onClick.listen((e) => _save()),
+      new ButtonElement()
+        ..classes = ['header_button']
+        ..text = 'Load from File…'
+        ..title = 'Load a saved timeline from file'
+        ..onClick.listen((e) => _load()),
+    ];
+  }
+
+  List<Element> _createTabs() {
+    if (_vm.embedder != 'Flutter') {
+      return const [];
+    }
+    return [
+      new SpanElement()
+        ..classes = ['tab_buttons']
+        ..children = <Element>[
+          new ButtonElement()
+            ..text = 'Frame View'
+            ..title = 'Logical view of the computation involved in each frame\n'
+                'Timestamps may not be preserved'
+            ..disabled = _view == _TimelineView.frame
+            ..onClick.listen((_) {
+              _view = _TimelineView.frame;
+              _r.dirty();
+            }),
+          new ButtonElement()
+            ..text = 'Time View'
+            ..title = 'Sequence of events generated during the execution\n'
+                'Timestamps are preserved'
+            ..disabled = _view == _TimelineView.strict
+            ..onClick.listen((_) {
+              _view = _TimelineView.strict;
+              _r.dirty();
+            }),
+        ]
+    ];
+  }
+
+  String _makeFrameUrl() {
+    final String mode = 'basic';
+    final String view = _view == _TimelineView.frame ? 'frame' : 'strict';
+    return 'timeline.html#mode=$mode&view=$view';
+  }
+
+  M.TimelineProfile _suggestedProfile(Iterable<M.TimelineProfile> profiles) {
+    return profiles
+        .where((profile) => profile.name == 'Flutter Developer')
+        .single;
+  }
+
+  Future _enable() async {
+    await _repository.setRecordedStreams(
+        vm, _suggestedProfile(_flags.profiles).streams);
+    _refresh();
+  }
+
+  Future _refresh() async {
+    _flags = await _repository.getFlags(vm);
+    _r.dirty();
+    final traceData =
+        Map<String, dynamic>.from(await _repository.getTimeline(vm));
+    return _postMessage('refresh', traceData);
+  }
+
+  Future _clear() async {
+    await _repository.clear(_vm);
+    return _postMessage('clear');
+  }
+
+  Future _save() => _postMessage('save');
+
+  Future _load() => _postMessage('load');
+
+  Future _postMessage(String method,
+      [Map<String, dynamic> params = const <String, dynamic>{}]) async {
+    var message = {'method': method, 'params': params};
+    _frame.contentWindow
+        .postMessage(json.encode(message), window.location.href);
+    return null;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/timeline_page.dart b/runtime/observatory_2/lib/src/elements/timeline_page.dart
new file mode 100644
index 0000000..d16c393
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/timeline_page.dart
@@ -0,0 +1,323 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library timeline_page_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'dart:convert';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+
+class TimelinePageElement extends CustomElement implements Renderable {
+  RenderingScheduler<TimelinePageElement> _r;
+
+  Stream<RenderedEvent<TimelinePageElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.TimelineRepository _repository;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.TimelineRecorder _recorder;
+  Set<M.TimelineStream> _availableStreams;
+  Set<M.TimelineStream> _recordedStreams;
+  Set<M.TimelineProfile> _profiles;
+
+  M.VM get vm => _vm;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory TimelinePageElement(M.VM vm, M.TimelineRepository repository,
+      M.EventRepository events, M.NotificationRepository notifications,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(repository != null);
+    assert(events != null);
+    assert(notifications != null);
+    TimelinePageElement e = new TimelinePageElement.created();
+    e._r = new RenderingScheduler<TimelinePageElement>(e, queue: queue);
+    e._vm = vm;
+    e._repository = repository;
+    e._events = events;
+    e._notifications = notifications;
+    return e;
+  }
+
+  TimelinePageElement.created() : super.created('timeline-page');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _updateRecorderUI();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  IFrameElement _frame;
+  DivElement _content;
+
+  bool get usingVMRecorder =>
+      _recorder.name != "Fuchsia" &&
+      _recorder.name != "Systrace" &&
+      _recorder.name != "Macos";
+
+  void render() {
+    if (_frame == null) {
+      _frame = new IFrameElement()..src = 'timeline.html';
+      _frame.onLoad.listen((event) {
+        _refresh();
+      });
+    }
+    if (_content == null) {
+      _content = new DivElement()..classes = ['content-centered-big'];
+    }
+    _content.children = <Element>[
+      new HeadingElement.h1()..text = 'Timeline settings',
+      _recorder == null
+          ? (new DivElement()..text = 'Loading...')
+          : (new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Recorder:',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..text = _recorder.name
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Recorded Streams Profile:',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = _createProfileSelect()
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'Recorded Streams:',
+                  new DivElement()
+                    ..classes = ['memberValue']
+                    ..children = _availableStreams
+                        .map<Element>(_makeStreamToggle)
+                        .toList()
+                ]
+            ])
+    ];
+
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(vm, _events, queue: _r.queue).element,
+        navMenu('timeline', link: Uris.timeline()),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _refresh();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'clear', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _clear();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'save', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _save();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        (new NavRefreshElement(label: 'load', queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                await _load();
+                e.element.disabled = !usingVMRecorder;
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      _content,
+      _createIFrameOrMessage(),
+    ];
+  }
+
+  HtmlElement _createIFrameOrMessage() {
+    if (_recorder == null) {
+      return new DivElement()
+        ..classes = ['content-centered-big']
+        ..text = 'Loading...';
+    }
+
+    if (_recorder.name == "Fuchsia") {
+      return new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new BRElement(),
+          new SpanElement()
+            ..text =
+                "This VM is forwarding timeline events to Fuchsia's system tracing. See the ",
+          new AnchorElement()
+            ..text = "Fuchsia Tracing Usage Guide"
+            ..href = "https://fuchsia.dev/fuchsia-src/development/tracing",
+          new SpanElement()..text = ".",
+        ];
+    }
+
+    if (_recorder.name == "Systrace") {
+      return new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new BRElement(),
+          new SpanElement()
+            ..text =
+                "This VM is forwarding timeline events to Android's systrace. See the ",
+          new AnchorElement()
+            ..text = "systrace usage guide"
+            ..href =
+                "https://developer.android.com/studio/command-line/systrace",
+          new SpanElement()..text = ".",
+        ];
+    }
+
+    if (_recorder.name == "Macos") {
+      return new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new BRElement(),
+          new SpanElement()
+            ..text =
+                "This VM is forwarding timeline events to macOS's Unified Logging. "
+                    "To track these events, open 'Instruments' and add the 'os_signpost' Filter. See the ",
+          new AnchorElement()
+            ..text = "Instruments Usage Guide"
+            ..href = "https://help.apple.com/instruments",
+          new SpanElement()..text = ".",
+        ];
+    }
+
+    return new DivElement()
+      ..classes = ['iframe']
+      ..children = <Element>[_frame];
+  }
+
+  List<Element> _createProfileSelect() {
+    return [
+      new SpanElement()
+        ..children = (_profiles.expand((profile) {
+          return <Element>[
+            new ButtonElement()
+              ..text = profile.name
+              ..onClick.listen((_) {
+                _applyPreset(profile);
+              }),
+            new SpanElement()..text = ' - '
+          ];
+        }).toList()
+          ..removeLast())
+    ];
+  }
+
+  Future _refresh() async {
+    _postMessage('loading');
+    final traceData = await _repository.getTimeline(vm);
+    return _postMessage('refresh', traceData);
+  }
+
+  Future _clear() async {
+    await _repository.clear(vm);
+    return _postMessage('clear');
+  }
+
+  Future _save() async {
+    return _postMessage('save');
+  }
+
+  Future _load() async {
+    return _postMessage('load');
+  }
+
+  Future _postMessage(String method,
+      [Map<String, dynamic> params = const <String, dynamic>{}]) async {
+    if (_frame.contentWindow == null) {
+      return null;
+    }
+    var message = {'method': method, 'params': params};
+    _frame.contentWindow
+        .postMessage(json.encode(message), window.location.href);
+    return null;
+  }
+
+  void _applyPreset(M.TimelineProfile profile) {
+    _recordedStreams = new Set<M.TimelineStream>.from(profile.streams);
+    _applyStreamChanges();
+    _updateRecorderUI();
+  }
+
+  Future _updateRecorderUI() async {
+    // Grab the current timeline flags.
+    final M.TimelineFlags flags = await _repository.getFlags(vm);
+    // Grab the recorder name.
+    _recorder = flags.recorder;
+    // Update the set of available streams.
+    _availableStreams = new Set<M.TimelineStream>.from(flags.streams);
+    // Update the set of recorded streams.
+    _recordedStreams = new Set<M.TimelineStream>.from(
+        flags.streams.where((s) => s.isRecorded));
+    // Update the set of presets.
+    _profiles = new Set<M.TimelineProfile>.from(flags.profiles);
+    // Refresh the UI.
+    _r.dirty();
+  }
+
+  Element _makeStreamToggle(M.TimelineStream stream) {
+    LabelElement label = new LabelElement();
+    label.style.paddingLeft = '8px';
+    SpanElement span = new SpanElement();
+    span.text = stream.name;
+    InputElement checkbox = new InputElement();
+    checkbox.onChange.listen((_) {
+      if (checkbox.checked) {
+        _recordedStreams.add(stream);
+      } else {
+        _recordedStreams.remove(stream);
+      }
+      _applyStreamChanges();
+      _updateRecorderUI();
+    });
+    checkbox.type = 'checkbox';
+    checkbox.checked = _recordedStreams.contains(stream);
+    label.children.add(checkbox);
+    label.children.add(span);
+    return label;
+  }
+
+  Future _applyStreamChanges() {
+    return _repository.setRecordedStreams(vm, _recordedStreams);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/tree_map.dart b/runtime/observatory_2/lib/src/elements/tree_map.dart
new file mode 100644
index 0000000..1ebc789
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/tree_map.dart
@@ -0,0 +1,193 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:math' as Math;
+import 'package:observatory_2/utils.dart';
+
+abstract class TreeMap<T> {
+  int getArea(T node);
+  String getBackground(T node);
+  String getLabel(T node);
+  String getTooltip(T node) => getLabel(node);
+  T getParent(T node);
+  Iterable<T> getChildren(T node);
+  void onSelect(T node);
+  void onDetails(T node);
+
+  void showIn(T node, DivElement content) {
+    final w = content.offsetWidth.toDouble();
+    final h = content.offsetHeight.toDouble();
+    final topTile = _createTreemapTile(node, w, h, 0, content);
+    topTile.style.width = "${w}px";
+    topTile.style.height = "${h}px";
+    topTile.style.border = "none";
+    content.children = [topTile];
+  }
+
+  Element _createTreemapTile(
+      T node, double width, double height, int depth, DivElement content) {
+    final div = new DivElement();
+    div.className = "treemapTile";
+    div.style.background = getBackground(node);
+    div.onDoubleClick.listen((event) {
+      event.stopPropagation();
+      if (depth == 0) {
+        onSelect(getParent(node)); // Zoom out.
+      } else {
+        onSelect(node); // Zoom in.
+      }
+    });
+    div.onContextMenu.listen((event) {
+      event.stopPropagation();
+      onDetails(node);
+    });
+
+    double left = 0.0;
+    double top = 0.0;
+
+    const kPadding = 5;
+    const kBorder = 1;
+    left += kPadding - kBorder;
+    top += kPadding - kBorder;
+    width -= 2 * kPadding;
+    height -= 2 * kPadding;
+
+    div.title = getTooltip(node);
+
+    if (width < 10 || height < 10) {
+      // Too small: don't render label or children.
+      return div;
+    }
+
+    div.append(new SpanElement()..text = getLabel(node));
+    const kLabelHeight = 9.0;
+    top += kLabelHeight;
+    height -= kLabelHeight;
+
+    if (depth > 2) {
+      // Too deep: don't render children.
+      return div;
+    }
+    if (width < 4 || height < 4) {
+      // Too small: don't render children.
+      return div;
+    }
+
+    final children = <T>[];
+    for (T c in getChildren(node)) {
+      // Size 0 children seem to confuse the layout algorithm (accumulating
+      // rounding errors?).
+      if (getArea(c) > 0) {
+        children.add(c);
+      }
+    }
+    children.sort((a, b) => getArea(b) - getArea(a));
+
+    final double scale = width * height / getArea(node);
+
+    // Bruls M., Huizing K., van Wijk J.J. (2000) Squarified Treemaps. In: de
+    // Leeuw W.C., van Liere R. (eds) Data Visualization 2000. Eurographics.
+    // Springer, Vienna.
+    for (int rowStart = 0; // Index of first child in the next row.
+        rowStart < children.length;) {
+      // Prefer wider rectangles, the better to fit text labels.
+      const double GOLDEN_RATIO = 1.61803398875;
+      final bool verticalSplit = (width / height) > GOLDEN_RATIO;
+
+      double space;
+      if (verticalSplit) {
+        space = height;
+      } else {
+        space = width;
+      }
+
+      double rowMin = getArea(children[rowStart]) * scale;
+      double rowMax = rowMin;
+      double rowSum = 0.0;
+      double lastRatio = 0.0;
+
+      int rowEnd; // One after index of last child in the next row.
+      for (rowEnd = rowStart; rowEnd < children.length; rowEnd++) {
+        double size = getArea(children[rowEnd]) * scale;
+        if (size < rowMin) rowMin = size;
+        if (size > rowMax) rowMax = size;
+        rowSum += size;
+
+        double ratio = Math.max((space * space * rowMax) / (rowSum * rowSum),
+            (rowSum * rowSum) / (space * space * rowMin));
+        if ((lastRatio != 0) && (ratio > lastRatio)) {
+          // Adding the next child makes the aspect ratios worse: remove it and
+          // add the row.
+          rowSum -= size;
+          break;
+        }
+        lastRatio = ratio;
+      }
+
+      double rowLeft = left;
+      double rowTop = top;
+      double rowSpace = rowSum / space;
+
+      for (int i = rowStart; i < rowEnd; i++) {
+        T child = children[i];
+        double size = getArea(child) * scale;
+
+        double childWidth;
+        double childHeight;
+        if (verticalSplit) {
+          childWidth = rowSpace;
+          childHeight = size / childWidth;
+        } else {
+          childHeight = rowSpace;
+          childWidth = size / childHeight;
+        }
+
+        Element childDiv = _createTreemapTile(
+            child, childWidth, childHeight, depth + 1, content);
+        childDiv.style.left = "${rowLeft}px";
+        childDiv.style.top = "${rowTop}px";
+        // Oversize the final div by kBorder to make the borders overlap.
+        childDiv.style.width = "${childWidth + kBorder}px";
+        childDiv.style.height = "${childHeight + kBorder}px";
+        div.append(childDiv);
+
+        if (verticalSplit)
+          rowTop += childHeight;
+        else
+          rowLeft += childWidth;
+      }
+
+      if (verticalSplit) {
+        left += rowSpace;
+        width -= rowSpace;
+      } else {
+        top += rowSpace;
+        height -= rowSpace;
+      }
+
+      rowStart = rowEnd;
+    }
+
+    return div;
+  }
+}
+
+abstract class NormalTreeMap<T> extends TreeMap<T> {
+  int getSize(T node);
+  String getName(T node);
+  String getType(T node);
+
+  int getArea(T node) => getSize(node);
+  String getLabel(T node) {
+    String name = getName(node);
+    String size = Utils.formatSize(getSize(node));
+    return "$name [$size]";
+  }
+
+  String getBackground(T node) {
+    int hue = getType(node).hashCode % 360;
+    return "hsl($hue,60%,60%)";
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/type_arguments_ref.dart b/runtime/observatory_2/lib/src/elements/type_arguments_ref.dart
new file mode 100644
index 0000000..a8cbd8d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/type_arguments_ref.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class TypeArgumentsRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<TypeArgumentsRefElement> _r;
+
+  Stream<RenderedEvent<TypeArgumentsRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.TypeArgumentsRef _arguments;
+
+  M.IsolateRef get isolate => _isolate;
+  M.TypeArgumentsRef get arguments => _arguments;
+
+  factory TypeArgumentsRefElement(M.IsolateRef isolate, M.TypeArgumentsRef args,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(args != null);
+    TypeArgumentsRefElement e = new TypeArgumentsRefElement.created();
+    e._r = new RenderingScheduler<TypeArgumentsRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._arguments = args;
+    return e;
+  }
+
+  TypeArgumentsRefElement.created() : super.created('type-arguments-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    final text = (_arguments.name == null || _arguments.name == '')
+        ? 'TypeArguments'
+        : _arguments.name;
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _arguments))
+        ..text = text
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/unknown_ref.dart b/runtime/observatory_2/lib/src/elements/unknown_ref.dart
new file mode 100644
index 0000000..092bd3b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/unknown_ref.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, UnknownObjectRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class UnknownObjectRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<UnknownObjectRefElement> _r;
+
+  Stream<RenderedEvent<UnknownObjectRefElement>> get onRendered =>
+      _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.UnknownObjectRef _obj;
+
+  M.IsolateRef get isolate => _isolate;
+  M.UnknownObjectRef get obj => _obj;
+
+  factory UnknownObjectRefElement(M.IsolateRef isolate, M.UnknownObjectRef obj,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(obj != null);
+    UnknownObjectRefElement e = new UnknownObjectRefElement.created();
+    e._r = new RenderingScheduler<UnknownObjectRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._obj = obj;
+    return e;
+  }
+
+  UnknownObjectRefElement.created() : super.created('unknown-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _obj))
+        ..classes = ['emphasize']
+        ..text = _obj.vmType
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/unlinkedcall_ref.dart b/runtime/observatory_2/lib/src/elements/unlinkedcall_ref.dart
new file mode 100644
index 0000000..e305f1c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/unlinkedcall_ref.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/models.dart' as M show IsolateRef, UnlinkedCallRef;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+
+class UnlinkedCallRefElement extends CustomElement implements Renderable {
+  RenderingScheduler<UnlinkedCallRefElement> _r;
+
+  Stream<RenderedEvent<UnlinkedCallRefElement>> get onRendered => _r.onRendered;
+
+  M.IsolateRef _isolate;
+  M.UnlinkedCallRef _unlinkedcall;
+
+  M.IsolateRef get isolate => _isolate;
+  M.UnlinkedCallRef get unlinkedcall => _unlinkedcall;
+
+  factory UnlinkedCallRefElement(
+      M.IsolateRef isolate, M.UnlinkedCallRef unlinkedcall,
+      {RenderingQueue queue}) {
+    assert(isolate != null);
+    assert(unlinkedcall != null);
+    UnlinkedCallRefElement e = new UnlinkedCallRefElement.created();
+    e._r = new RenderingScheduler<UnlinkedCallRefElement>(e, queue: queue);
+    e._isolate = isolate;
+    e._unlinkedcall = unlinkedcall;
+    return e;
+  }
+
+  UnlinkedCallRefElement.created() : super.created('unlinkedcall-ref');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement(href: Uris.inspect(_isolate, object: _unlinkedcall))
+        ..children = <Element>[
+          new SpanElement()
+            ..classes = ['emphasize']
+            ..text = 'UnlinkedCall',
+          new SpanElement()..text = ' (${_unlinkedcall.selector})'
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/unlinkedcall_view.dart b/runtime/observatory_2/lib/src/elements/unlinkedcall_view.dart
new file mode 100644
index 0000000..76c29c0
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/unlinkedcall_view.dart
@@ -0,0 +1,161 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/curly_block.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/nav_menu.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/isolate_menu.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/object_common.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+
+class UnlinkedCallViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<UnlinkedCallViewElement> _r;
+
+  Stream<RenderedEvent<UnlinkedCallViewElement>> get onRendered =>
+      _r.onRendered;
+
+  M.VM _vm;
+  M.IsolateRef _isolate;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.UnlinkedCall _unlinkedcall;
+  M.UnlinkedCallRepository _unlinkedcalls;
+  M.RetainedSizeRepository _retainedSizes;
+  M.ReachableSizeRepository _reachableSizes;
+  M.InboundReferencesRepository _references;
+  M.RetainingPathRepository _retainingPaths;
+  M.ObjectRepository _objects;
+
+  M.VMRef get vm => _vm;
+  M.IsolateRef get isolate => _isolate;
+  M.NotificationRepository get notifications => _notifications;
+  M.UnlinkedCall get unlinkedcall => _unlinkedcall;
+
+  factory UnlinkedCallViewElement(
+      M.VM vm,
+      M.IsolateRef isolate,
+      M.UnlinkedCall unlinkedcall,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.UnlinkedCallRepository unlinkedcalls,
+      M.RetainedSizeRepository retainedSizes,
+      M.ReachableSizeRepository reachableSizes,
+      M.InboundReferencesRepository references,
+      M.RetainingPathRepository retainingPaths,
+      M.ObjectRepository objects,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(isolate != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(unlinkedcall != null);
+    assert(unlinkedcalls != null);
+    assert(retainedSizes != null);
+    assert(reachableSizes != null);
+    assert(references != null);
+    assert(retainingPaths != null);
+    assert(objects != null);
+    UnlinkedCallViewElement e = new UnlinkedCallViewElement.created();
+    e._r = new RenderingScheduler<UnlinkedCallViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._isolate = isolate;
+    e._events = events;
+    e._notifications = notifications;
+    e._unlinkedcall = unlinkedcall;
+    e._unlinkedcalls = unlinkedcalls;
+    e._retainedSizes = retainedSizes;
+    e._reachableSizes = reachableSizes;
+    e._references = references;
+    e._retainingPaths = retainingPaths;
+    e._objects = objects;
+    return e;
+  }
+
+  UnlinkedCallViewElement.created() : super.created('unlinkedcall-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        new NavIsolateMenuElement(_isolate, _events, queue: _r.queue).element,
+        navMenu('unlinkedcall'),
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _unlinkedcall =
+                    await _unlinkedcalls.get(_isolate, _unlinkedcall.id);
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered-big']
+        ..children = <Element>[
+          new HeadingElement.h2()..text = 'UnlinkedCall',
+          new HRElement(),
+          new ObjectCommonElement(_isolate, _unlinkedcall, _retainedSizes,
+                  _reachableSizes, _references, _retainingPaths, _objects,
+                  queue: _r.queue)
+              .element,
+          new DivElement()
+            ..classes = ['memberList']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'selector',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = _unlinkedcall.selector
+                ],
+              new DivElement()
+                ..classes = ['memberItem']
+                ..children = <Element>[
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..text = 'argumentsDescriptor',
+                  new DivElement()
+                    ..classes = ['memberName']
+                    ..children = <Element>[
+                      _unlinkedcall.argumentsDescriptor == null
+                          ? (new SpanElement()..text = '<none>')
+                          : anyRef(_isolate, _unlinkedcall.argumentsDescriptor,
+                              _objects,
+                              queue: _r.queue)
+                    ]
+                ]
+            ],
+          new HRElement(),
+          new ViewFooterElement(queue: _r.queue).element
+        ]
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/view_footer.dart b/runtime/observatory_2/lib/src/elements/view_footer.dart
new file mode 100644
index 0000000..d3fddb7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/view_footer.dart
@@ -0,0 +1,49 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library view_footer_element;
+
+import 'dart:html';
+import 'dart:async';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+
+class ViewFooterElement extends CustomElement implements Renderable {
+  RenderingScheduler<ViewFooterElement> _r;
+
+  Stream<RenderedEvent<ViewFooterElement>> get onRendered => _r.onRendered;
+
+  factory ViewFooterElement({RenderingQueue queue}) {
+    ViewFooterElement e = new ViewFooterElement.created();
+    e._r = new RenderingScheduler<ViewFooterElement>(e, queue: queue);
+    return e;
+  }
+
+  ViewFooterElement.created() : super.created('view-footer');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement()
+        ..href = 'https://dart-lang.github.io/observatory/'
+        ..text = 'View documentation',
+      new AnchorElement()
+        ..href =
+            'https://github.com/dart-lang/sdk/issues/new?title=Observatory:&amp;body=Observatory%20Feedback'
+        ..text = 'File a bug report'
+    ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/vm_connect.dart b/runtime/observatory_2/lib/src/elements/vm_connect.dart
new file mode 100644
index 0000000..fe30bc9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/vm_connect.dart
@@ -0,0 +1,168 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm_connect_element;
+
+import 'dart:async';
+import 'dart:html';
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+import 'package:observatory_2/src/elements/vm_connect_target.dart';
+
+class VMConnectElement extends CustomElement implements Renderable {
+  RenderingScheduler<VMConnectElement> _r;
+
+  Stream<RenderedEvent<VMConnectElement>> get onRendered => _r.onRendered;
+
+  M.NotificationRepository _notifications;
+  M.TargetRepository _targets;
+  StreamSubscription _targetsSubscription;
+
+  String _address;
+
+  factory VMConnectElement(
+      M.TargetRepository targets, M.NotificationRepository notifications,
+      {String address: '', RenderingQueue queue}) {
+    assert(address != null);
+    assert(notifications != null);
+    assert(targets != null);
+    VMConnectElement e = new VMConnectElement.created();
+    e._r = new RenderingScheduler<VMConnectElement>(e, queue: queue);
+    e._address = address;
+    e._notifications = notifications;
+    e._targets = targets;
+    return e;
+  }
+
+  VMConnectElement.created() : super.created('vm-connect');
+
+  @override
+  void attached() {
+    super.attached();
+    _targetsSubscription = _targets.onChange.listen((_) => _r.dirty());
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+    _targetsSubscription.cancel();
+  }
+
+  void render() {
+    final host = window.location.hostname;
+    final port = window.location.port;
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      new DivElement()
+        ..classes = ['content-centered']
+        ..children = <Element>[
+          new HeadingElement.h1()..text = 'Connect to a Dart VM',
+          new HRElement(),
+          new BRElement(),
+          new DivElement()
+            ..classes = ['flex-row']
+            ..children = <Element>[
+              new DivElement()
+                ..classes = ['flex-item-40-percent']
+                ..children = <Element>[
+                  new HeadingElement.h2()..text = 'Connect over WebSocket',
+                  new BRElement(),
+                  new UListElement()
+                    ..children = _targets.list().map<Element>((target) {
+                      final bool current = _targets.isConnectedVMTarget(target);
+                      return new LIElement()
+                        ..children = <Element>[
+                          (new VMConnectTargetElement(target,
+                                  current: current, queue: _r.queue)
+                                ..onConnect.listen(_connect)
+                                ..onDelete.listen(_delete))
+                              .element
+                        ];
+                    }).toList(),
+                  new HRElement(),
+                  new FormElement()
+                    ..autocomplete = 'on'
+                    ..children = <Element>[
+                      _createAddressBox(),
+                      new SpanElement()..text = ' ',
+                      new ButtonElement()
+                        ..classes = ['vm_connect']
+                        ..text = 'Connect'
+                        ..onClick.listen((e) {
+                          e.preventDefault();
+                          _createAndConnect();
+                        }),
+                    ],
+                  new BRElement(),
+                  new PreElement()
+                    ..classes = ['well']
+                    ..text = 'Run Standalone with: \'--observe\'',
+                ],
+              new DivElement()..classes = ['flex-item-20-percent'],
+            ],
+        ],
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+
+  TextInputElement _createAddressBox() {
+    var textbox = new TextInputElement()
+      ..classes = ['textbox']
+      ..placeholder = 'http://127.0.0.1:8181/...'
+      ..value = _address
+      ..onKeyUp.where((e) => e.key == '\n').listen((e) {
+        e.preventDefault();
+        _createAndConnect();
+      });
+    textbox.onInput.listen((e) {
+      _address = textbox.value;
+    });
+    return textbox;
+  }
+
+  void _createAndConnect() {
+    if (_address == null || _address.isEmpty) return;
+    String normalizedNetworkAddress = _normalizeStandaloneAddress(_address);
+    _targets.add(normalizedNetworkAddress);
+    var target = _targets.find(normalizedNetworkAddress);
+    assert(target != null);
+    _targets.setCurrent(target);
+    // the navigation to the VM page is done in the ObservatoryApplication
+  }
+
+  void _connect(TargetEvent e) {
+    _targets.setCurrent(e.target);
+  }
+
+  void _delete(TargetEvent e) => _targets.delete(e.target);
+
+  static String _normalizeStandaloneAddress(String networkAddress) {
+    if (!networkAddress.startsWith('http') &&
+        !networkAddress.startsWith('ws')) {
+      networkAddress = 'http://$networkAddress';
+    }
+    try {
+      Uri uri = Uri.parse(networkAddress);
+      if (uri.path.endsWith('/ws')) {
+        return 'ws://${uri.authority}${uri.path}';
+      }
+      return 'ws://${uri.authority}${uri.path}/ws';
+    } catch (e) {
+      print('caught exception with: $networkAddress -- $e');
+      return networkAddress;
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/vm_connect_target.dart b/runtime/observatory_2/lib/src/elements/vm_connect_target.dart
new file mode 100644
index 0000000..2b90b81
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/vm_connect_target.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M show Target;
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+
+class TargetEvent {
+  final M.Target target;
+
+  TargetEvent(this.target);
+}
+
+class VMConnectTargetElement extends CustomElement implements Renderable {
+  RenderingScheduler<VMConnectTargetElement> _r;
+
+  Stream<RenderedEvent<VMConnectTargetElement>> get onRendered => _r.onRendered;
+
+  final StreamController<TargetEvent> _onConnect =
+      new StreamController<TargetEvent>.broadcast();
+  Stream<TargetEvent> get onConnect => _onConnect.stream;
+  final StreamController<TargetEvent> _onDelete =
+      new StreamController<TargetEvent>.broadcast();
+  Stream<TargetEvent> get onDelete => _onDelete.stream;
+
+  M.Target _target;
+  bool _current;
+
+  M.Target get target => _target;
+  bool get current => _current;
+
+  factory VMConnectTargetElement(M.Target target,
+      {bool current: false, RenderingQueue queue}) {
+    assert(target != null);
+    assert(current != null);
+    VMConnectTargetElement e = new VMConnectTargetElement.created();
+    e._r = new RenderingScheduler<VMConnectTargetElement>(e, queue: queue);
+    e._target = target;
+    e._current = current;
+    return e;
+  }
+
+  VMConnectTargetElement.created() : super.created('vm-connect-target');
+
+  @override
+  void attached() {
+    super.attached();
+    _r.enable();
+  }
+
+  @override
+  void detached() {
+    super.detached();
+    children = <Element>[];
+    _r.disable(notify: true);
+  }
+
+  void connect() {
+    _connect(new TargetEvent(target));
+  }
+
+  void delete() {
+    _delete(new TargetEvent(target));
+  }
+
+  void render() {
+    children = <Element>[
+      new AnchorElement()
+        ..text = current ? '${target.name} (Connected)' : '${target.name}'
+        ..onClick.where(_filter).map(_toEvent).listen(_connect),
+      new ButtonElement()
+        ..text = '✖ Remove'
+        ..classes = ['delete-button']
+        ..onClick.map(_toEvent).listen(_delete)
+    ];
+  }
+
+  void _connect(TargetEvent e) {
+    _onConnect.add(e);
+  }
+
+  void _delete(TargetEvent e) {
+    _onDelete.add(e);
+  }
+
+  TargetEvent _toEvent(_) {
+    return new TargetEvent(target);
+  }
+
+  static bool _filter(MouseEvent event) {
+    return !(event.button > 0 ||
+        event.metaKey ||
+        event.ctrlKey ||
+        event.shiftKey ||
+        event.altKey);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/elements/vm_view.dart b/runtime/observatory_2/lib/src/elements/vm_view.dart
new file mode 100644
index 0000000..014cd50
--- /dev/null
+++ b/runtime/observatory_2/lib/src/elements/vm_view.dart
@@ -0,0 +1,367 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm_view_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/src/elements/helpers/nav_bar.dart';
+import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
+import 'package:observatory_2/src/elements/helpers/custom_element.dart';
+import 'package:observatory_2/src/elements/helpers/uris.dart';
+import 'package:observatory_2/src/elements/isolate/summary.dart';
+import 'package:observatory_2/src/elements/nav/notify.dart';
+import 'package:observatory_2/src/elements/nav/refresh.dart';
+import 'package:observatory_2/src/elements/nav/top_menu.dart';
+import 'package:observatory_2/src/elements/nav/vm_menu.dart';
+import 'package:observatory_2/src/elements/view_footer.dart';
+import 'package:observatory_2/utils.dart';
+
+class VMViewElement extends CustomElement implements Renderable {
+  RenderingScheduler<VMViewElement> _r;
+
+  Stream<RenderedEvent<VMViewElement>> get onRendered => _r.onRendered;
+
+  M.VM _vm;
+  M.VMRepository _vms;
+  M.EventRepository _events;
+  M.NotificationRepository _notifications;
+  M.IsolateRepository _isolates;
+  M.IsolateGroupRepository _isolateGroups;
+  M.ScriptRepository _scripts;
+  StreamSubscription _vmSubscription;
+  StreamSubscription _startSubscription;
+  StreamSubscription _exitSubscription;
+
+  M.VMRef get vm => _vm;
+  M.NotificationRepository get notifications => _notifications;
+
+  factory VMViewElement(
+      M.VM vm,
+      M.VMRepository vms,
+      M.EventRepository events,
+      M.NotificationRepository notifications,
+      M.IsolateRepository isolates,
+      M.IsolateGroupRepository isolateGroups,
+      M.ScriptRepository scripts,
+      {RenderingQueue queue}) {
+    assert(vm != null);
+    assert(vms != null);
+    assert(events != null);
+    assert(notifications != null);
+    assert(isolates != null);
+    assert(scripts != null);
+    VMViewElement e = new VMViewElement.created();
+    e._r = new RenderingScheduler<VMViewElement>(e, queue: queue);
+    e._vm = vm;
+    e._vms = vms;
+    e._events = events;
+    e._notifications = notifications;
+    e._isolates = isolates;
+    e._isolateGroups = isolateGroups;
+    e._scripts = scripts;
+    return e;
+  }
+
+  VMViewElement.created() : super.created('vm-view');
+
+  @override
+  attached() {
+    super.attached();
+    _r.enable();
+    _vmSubscription = _events.onVMUpdate.listen((e) {
+      _vm = e.vm;
+      _r.dirty();
+    });
+    _startSubscription = _events.onIsolateStart.listen((_) => _r.dirty());
+    _exitSubscription = _events.onIsolateExit.listen((_) => _r.dirty());
+    _loadExtraData();
+  }
+
+  @override
+  detached() {
+    super.detached();
+    _r.disable(notify: true);
+    children = <Element>[];
+    _vmSubscription.cancel();
+    _startSubscription.cancel();
+    _exitSubscription.cancel();
+  }
+
+  Future _loadExtraData() async {
+    for (var group in _vm.isolateGroups) {
+      await _isolateGroups.get(group);
+    }
+    for (var group in _vm.systemIsolateGroups) {
+      await _isolateGroups.get(group);
+    }
+    _r.dirty();
+  }
+
+  void render() {
+    children = <Element>[
+      navBar(<Element>[
+        new NavTopMenuElement(queue: _r.queue).element,
+        new NavVMMenuElement(_vm, _events, queue: _r.queue).element,
+        (new NavRefreshElement(queue: _r.queue)
+              ..onRefresh.listen((e) async {
+                e.element.disabled = true;
+                _vm = await _vms.get(_vm);
+                _loadExtraData();
+                _r.dirty();
+              }))
+            .element,
+        new NavNotifyElement(_notifications, queue: _r.queue).element
+      ]),
+      describeProcess(),
+      describeVM(),
+      describeIsolateGroups(),
+      describeSystemIsolateGroups(),
+      new ViewFooterElement(queue: _r.queue).element
+    ];
+  }
+
+  Element describeProcess() {
+    return new DivElement()
+      ..classes = ['content-centered-big']
+      ..children = <HtmlElement>[
+        new HeadingElement.h1()..text = 'Process',
+        new DivElement()
+          ..classes = ['memberList']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'pid',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = '${_vm.pid}'
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'current memory'
+                  ..title =
+                      'current value of the resident set size of the process running this VM',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.currentRSS != null
+                      ? Utils.formatSize(_vm.currentRSS)
+                      : "unavailable"
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'peak memory'
+                  ..title =
+                      'highest value of the resident set size of the process running this VM',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.maxRSS != null
+                      ? Utils.formatSize(_vm.maxRSS)
+                      : "unavailable"
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'malloc memory',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.heapAllocatedMemoryUsage != null
+                      ? Utils.formatSize(_vm.heapAllocatedMemoryUsage)
+                      : 'unavailable'
+                  ..title = _vm.heapAllocatedMemoryUsage != null
+                      ? '${_vm.heapAllocatedMemoryUsage} bytes'
+                      : null
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'malloc allocation count',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.heapAllocationCount != null
+                      ? '${_vm.heapAllocationCount}'
+                      : 'unavailable'
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..children = <Element>[
+                    new SpanElement()..text = 'view ',
+                    new AnchorElement(href: Uris.nativeMemory())
+                      ..text = 'malloc profile'
+                  ],
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..children = <Element>[
+                    new SpanElement()..text = 'view ',
+                    new AnchorElement(href: Uris.processSnapshot())
+                      ..text = 'process memory'
+                  ]
+              ]
+          ],
+        new BRElement(),
+      ];
+  }
+
+  Element describeVM() {
+    final uptime = new DateTime.now().difference(_vm.startTime);
+    return new DivElement()
+      ..classes = ['content-centered-big']
+      ..children = <HtmlElement>[
+        new HeadingElement.h1()..text = 'VM',
+        new DivElement()
+          ..classes = ['memberList']
+          ..children = <Element>[
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'name',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.displayName
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'version',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.version
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'embedder',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.embedder ?? "UNKNOWN"
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'current memory'
+                  ..title = 'current amount of memory consumed by the Dart VM',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = _vm.currentMemory != null
+                      ? Utils.formatSize(_vm.currentMemory)
+                      : "unavailable"
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'started at',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = '${_vm.startTime}'
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'uptime',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = '$uptime'
+              ],
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..text = 'refreshed at',
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..text = '${new DateTime.now()}'
+              ],
+            new BRElement(),
+            new DivElement()
+              ..classes = ['memberItem']
+              ..children = <Element>[
+                new DivElement()
+                  ..classes = ['memberName']
+                  ..children = <Element>[
+                    new SpanElement()..text = 'see ',
+                    new AnchorElement(href: Uris.flags())..text = 'flags'
+                  ],
+                new DivElement()
+                  ..classes = ['memberValue']
+                  ..children = <Element>[
+                    new SpanElement()..text = 'view ',
+                    new AnchorElement(href: Uris.timeline())..text = 'timeline'
+                  ]
+              ],
+          ],
+        new BRElement(),
+      ];
+  }
+
+  Element describeIsolateGroups() {
+    final isolateGroups = _vm.isolateGroups.toList();
+    return new DivElement()
+      ..children = isolateGroups.map(describeIsolateGroup).toList();
+  }
+
+  Element describeSystemIsolateGroups() {
+    final isolateGroups = _vm.systemIsolateGroups.toList();
+    return new DivElement()
+      ..children = isolateGroups.map(describeIsolateGroup).toList();
+  }
+
+  Element describeIsolateGroup(M.IsolateGroupRef group) {
+    final isolateType =
+        group.isSystemIsolateGroup ? 'System Isolate' : 'Isolate';
+    final isolates = (group as M.IsolateGroup).isolates;
+    return new DivElement()
+      ..classes = ['content-centered-big']
+      ..children = <Element>[
+        new HRElement(),
+        new HeadingElement.h1()
+          ..text = "$isolateType Group ${group.number} (${group.name})",
+        new LIElement()
+          ..classes = ['list-group-item']
+          ..children = <Element>[
+            new UListElement()
+              ..classes = ['list-group']
+              ..children = isolates.map(describeIsolate).toList(),
+          ],
+      ];
+  }
+
+  Element describeIsolate(M.IsolateRef isolate) {
+    return new LIElement()
+      ..classes = ['list-group-item']
+      ..children = <Element>[
+        new IsolateSummaryElement(isolate, _isolates, _events, _scripts,
+                queue: _r.queue)
+            .element
+      ];
+  }
+}
diff --git a/runtime/observatory_2/lib/src/models/exceptions.dart b/runtime/observatory_2/lib/src/models/exceptions.dart
new file mode 100644
index 0000000..81a7ba7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/exceptions.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class BasicException implements Exception {
+  String get message;
+}
+
+abstract class ConnectionException implements BasicException {}
+
+abstract class ResponseException implements BasicException {}
+
+abstract class RequestException implements BasicException {}
+
+abstract class ParseErrorException implements RequestException {}
+
+abstract class InvalidRequestException implements RequestException {}
+
+abstract class MethodNotFoundException implements RequestException {}
+
+abstract class InvalidParamsException implements RequestException {}
+
+abstract class InternalErrorException implements RequestException {}
+
+abstract class FeatureDisabledException implements RequestException {}
+
+abstract class CannotAddBreakpointException implements RequestException {}
+
+abstract class StreamAlreadySubscribedException implements RequestException {}
+
+abstract class StreamNotSubscribedException implements RequestException {}
+
+abstract class IsolateMustBeRunnableException implements RequestException {}
+
+abstract class IsolateMustBePausedException implements RequestException {}
+
+abstract class IsolateIsReloadingException implements RequestException {}
+
+abstract class FileSystemAlreadyExistsException implements RequestException {}
+
+abstract class FileSystemDoesNotExistException implements RequestException {}
+
+abstract class FileDoesNotExistException implements RequestException {}
+
+abstract class IsolateReloadFailedException implements RequestException {}
+
+abstract class UnknownException implements RequestException {}
diff --git a/runtime/observatory_2/lib/src/models/objects/allocation_profile.dart b/runtime/observatory_2/lib/src/models/objects/allocation_profile.dart
new file mode 100644
index 0000000..f9aa5a6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/allocation_profile.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class AllocationProfile {
+  DateTime get lastServiceGC;
+  DateTime get lastAccumulatorReset;
+  HeapSpace get newSpace;
+  HeapSpace get oldSpace;
+  HeapSpace get totalSpace;
+  Iterable<ClassHeapStats> get members;
+}
+
+abstract class ClassHeapStats {
+  /// [Optional] at least one between clazz and displayName should be non null
+  ClassRef get clazz;
+
+  /// [Optional] at least one between clazz and displayName should be non null
+  String get displayName;
+  Allocations get newSpace;
+  Allocations get oldSpace;
+}
+
+abstract class Allocations {
+  int instances = 0;
+  int internalSize = 0;
+  int externalSize = 0;
+  int size = 0;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/breakpoint.dart b/runtime/observatory_2/lib/src/models/objects/breakpoint.dart
new file mode 100644
index 0000000..28ed56c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/breakpoint.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Breakpoint extends Object {
+  /// A number identifying this breakpoint to the user.
+  int get number;
+
+  /// Has this breakpoint been assigned to a specific program location?
+  bool get resolved;
+
+  /// [optional]Is this a breakpoint that was added synthetically as part of a
+  /// step OverAsyncSuspension resume command?
+  bool get isSyntheticAsyncContinuation;
+
+  /// SourceLocation when breakpoint is resolved, UnresolvedSourceLocation
+  /// when a breakpoint is not resolved.
+  Location get location;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/class.dart b/runtime/observatory_2/lib/src/models/objects/class.dart
new file mode 100644
index 0000000..47a1a34
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/class.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ClassRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+}
+
+abstract class Class extends Object implements ClassRef {
+  /// The error which occurred during class finalization, if it exists.
+  /// [optional]
+  ErrorRef get error;
+
+  /// Is this an abstract class?
+  bool get isAbstract;
+
+  /// Is this a const class?
+  bool get isConst;
+
+  /// [internal]
+  bool get isPatch;
+
+  /// [optional] The library which contains this class.
+  LibraryRef get library;
+
+  /// [optional] The location of this class in the source code.
+  SourceLocation get location;
+
+  /// [optional] The superclass of this class, if any.
+  ClassRef get superclass;
+
+  /// [optional]The supertype for this class, if any.
+  ///
+  /// The value will be of the kind: Type.
+  InstanceRef get superType;
+
+  /// A list of interface types for this class.
+  ///
+  /// The values will be of the kind: Type.
+  Iterable<InstanceRef> get interfaces;
+
+  /// The mixin type for this class, if any.
+  ///
+  /// [optional] The value will be of the kind: Type.
+  InstanceRef get mixin;
+
+  /// A list of fields in this class. Does not include fields from
+  /// superclasses.
+  Iterable<FieldRef> get fields;
+
+  /// A list of functions in this class. Does not include functions
+  /// from superclasses.
+  Iterable<FunctionRef> get functions;
+
+  // A list of subclasses of this class.
+  Iterable<ClassRef> get subclasses;
+
+  bool get hasAllocations;
+  bool get hasNoAllocations;
+
+  Allocations get newSpace;
+  Allocations get oldSpace;
+
+  bool get traceAllocations;
+}
+
+abstract class InstanceSet {
+  int get count;
+  Iterable<ObjectRef> get instances;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/code.dart b/runtime/observatory_2/lib/src/models/objects/code.dart
new file mode 100644
index 0000000..12d84df
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/code.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum CodeKind { dart, native, stub, tag, collected }
+
+bool isSyntheticCode(CodeKind kind) {
+  switch (kind) {
+    case CodeKind.collected:
+    case CodeKind.native:
+    case CodeKind.tag:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isDartCode(CodeKind kind) => !isSyntheticCode(kind);
+
+abstract class CodeRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+
+  // What kind of code object is this?
+  CodeKind get kind;
+
+  bool get isOptimized;
+}
+
+abstract class Code extends Object implements CodeRef {
+  FunctionRef get function;
+  ObjectPoolRef get objectPool;
+  Iterable<FunctionRef> get inlinedFunctions;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/context.dart b/runtime/observatory_2/lib/src/models/objects/context.dart
new file mode 100644
index 0000000..7378086
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/context.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ContextRef extends ObjectRef {
+  /// The number of variables in this context.
+  int get length;
+}
+
+abstract class Context extends Object implements ContextRef {
+  /// [optional] The enclosing context for this context.
+  Context get parentContext;
+
+  // The variables in this context object.
+  Iterable<ContextElement> get variables;
+}
+
+abstract class ContextElement {
+  Guarded<InstanceRef> get value;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/error.dart b/runtime/observatory_2/lib/src/models/objects/error.dart
new file mode 100644
index 0000000..56eff8b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/error.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum ErrorKind {
+  /// The isolate has encountered an unhandled Dart exception.
+  unhandledException,
+
+  /// The isolate has encountered a Dart language error in the program.
+  languageError,
+
+  /// The isolate has encountered an internal error. These errors should be
+  /// reported as bugs.
+  internalError,
+
+  /// The isolate has been terminated by an external source.
+  terminationError
+}
+
+abstract class ErrorRef extends ObjectRef {
+  ErrorKind get kind;
+  String get message;
+}
+
+abstract class Error extends Object implements ErrorRef {}
diff --git a/runtime/observatory_2/lib/src/models/objects/event.dart b/runtime/observatory_2/lib/src/models/objects/event.dart
new file mode 100644
index 0000000..24ed7e3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/event.dart
@@ -0,0 +1,210 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Event {
+  /// The timestamp (in milliseconds since the epoch) associated with this
+  /// event. For some isolate pause events, the timestamp is from when the
+  /// isolate was paused. For other events, the timestamp is from when the
+  /// event was created.
+  DateTime get timestamp;
+  static bool isPauseEvent(Event event) {
+    return event is PauseStartEvent ||
+        event is PauseExitEvent ||
+        event is PauseBreakpointEvent ||
+        event is PauseInterruptedEvent ||
+        event is PauseExceptionEvent ||
+        event is PausePostRequestEvent ||
+        event is NoneEvent;
+  }
+}
+
+abstract class VMEvent extends Event {
+  /// The vm with which this event is associated.
+  VMRef get vm;
+}
+
+abstract class VMUpdateEvent extends VMEvent {}
+
+abstract class IsolateEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+}
+
+abstract class IsolateStartEvent extends IsolateEvent {}
+
+abstract class IsolateRunnableEvent extends IsolateEvent {}
+
+abstract class IsolateExitEvent extends IsolateEvent {}
+
+abstract class IsolateUpdateEvent extends IsolateEvent {}
+
+abstract class IsolateReloadEvent extends IsolateEvent {
+  ErrorRef get error;
+}
+
+abstract class ServiceExtensionAddedEvent extends IsolateEvent {
+  /// The RPC name of the extension that was added.
+  String get extensionRPC;
+}
+
+abstract class DebugEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+}
+
+abstract class BreakpointEvent extends DebugEvent {
+  /// [optional] The breakpoint associated with this event.
+  Breakpoint get breakpoint;
+}
+
+abstract class PauseEvent extends DebugEvent {}
+
+abstract class AsyncSuspensionEvent extends PauseEvent {
+  /// Is the isolate paused at an await, yield, or yield* statement?
+  bool get atAsyncSuspension;
+}
+
+abstract class DebuggerSettingsUpdateEvent extends DebugEvent {}
+
+abstract class PauseStartEvent extends PauseEvent {}
+
+abstract class PauseExitEvent extends PauseEvent {}
+
+abstract class PauseBreakpointEvent extends AsyncSuspensionEvent {
+  /// [optional] The breakpoint at which we are currently paused.
+  Breakpoint get breakpoint;
+
+  /// The list of breakpoints at which we are currently paused
+  /// for a PauseBreakpoint event.
+  ///
+  /// This list may be empty. For example, while single-stepping, the
+  /// VM sends a PauseBreakpoint event with no breakpoints.
+  ///
+  /// If there is more than one breakpoint set at the program position,
+  /// then all of them will be provided.
+  Iterable<Breakpoint> get pauseBreakpoints;
+
+  /// The top stack frame associated with this event.
+  Frame get topFrame;
+}
+
+abstract class PauseInterruptedEvent extends AsyncSuspensionEvent {
+  /// [optional] The top stack frame associated with this event. There will be
+  /// no top frame if the isolate is idle (waiting in the message loop).
+  Frame get topFrame;
+}
+
+abstract class PausePostRequestEvent extends AsyncSuspensionEvent {
+  /// [optional] The top stack frame associated with this event. There will be
+  /// no top frame if the isolate is idle (waiting in the message loop).
+  Frame get topFrame;
+}
+
+abstract class PauseExceptionEvent extends PauseEvent {
+  /// The top stack frame associated with this event.
+  Frame get topFrame;
+
+  /// The exception associated with this event
+  InstanceRef get exception;
+}
+
+abstract class ResumeEvent extends DebugEvent {
+  /// [optional] The top stack frame associated with this event. It is provided
+  /// at all times except for the initial resume event that is delivered when an
+  /// isolate begins execution.
+  Frame get topFrame;
+}
+
+abstract class BreakpointAddedEvent extends BreakpointEvent {}
+
+abstract class BreakpointResolvedEvent extends BreakpointEvent {}
+
+abstract class BreakpointRemovedEvent extends BreakpointEvent {}
+
+abstract class InspectEvent extends DebugEvent {
+  /// The argument passed to dart:developer.inspect.
+  InstanceRef get inspectee;
+}
+
+abstract class NoneEvent extends PauseEvent {}
+
+abstract class GCEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+}
+
+abstract class ExtensionEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+
+  /// The extension event kind.
+  String get extensionKind;
+
+  /// The extension event data.
+  ExtensionData get extensionData;
+}
+
+abstract class LoggingEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+
+  // TODO(cbernaschina) objectify
+  Map get logRecord;
+}
+
+abstract class TimelineEventsEvent extends Event {
+  /// The isolate with which this event is associated.
+  IsolateRef get isolate;
+
+  /// An array of TimelineEvents
+  Iterable<TimelineEvent> get timelineEvents;
+}
+
+abstract class ConnectionClosedEvent extends Event {
+  /// The reason of the closed connection
+  String get reason;
+}
+
+Frame topFrame(DebugEvent event) {
+  if (event is PauseBreakpointEvent) {
+    return event.topFrame;
+  }
+  if (event is PauseInterruptedEvent) {
+    return event.topFrame;
+  }
+  if (event is PauseExceptionEvent) {
+    return event.topFrame;
+  }
+  if (event is ResumeEvent) {
+    return event.topFrame;
+  }
+  return null;
+}
+
+bool isAtAsyncSuspension(DebugEvent event) {
+  if (event is PauseBreakpointEvent) {
+    return event.atAsyncSuspension;
+  }
+  if (event is PauseInterruptedEvent) {
+    return event.atAsyncSuspension;
+  }
+  return false;
+}
+
+abstract class ServiceEvent extends Event {
+  /// The identifier of the service
+  String get service;
+
+  /// The JSON-RPC 2.0 Method that identifes this instance
+  String get method;
+}
+
+abstract class ServiceRegisteredEvent extends ServiceEvent {
+  /// The alias associated with this new instance
+  String get alias;
+}
+
+abstract class ServiceUnregisteredEvent extends ServiceEvent {}
diff --git a/runtime/observatory_2/lib/src/models/objects/extension_data.dart b/runtime/observatory_2/lib/src/models/objects/extension_data.dart
new file mode 100644
index 0000000..80a0012
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/extension_data.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ExtensionData implements Map<String, dynamic> {}
diff --git a/runtime/observatory_2/lib/src/models/objects/field.dart b/runtime/observatory_2/lib/src/models/objects/field.dart
new file mode 100644
index 0000000..ca59328c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/field.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class FieldRef extends ObjectRef {
+  /// The name of this field.
+  String get name;
+
+  /// The owner of this field, which can be either a Library or a
+  /// Class.
+  ObjectRef get dartOwner;
+
+  /// The declared type of this field.
+  ///
+  /// The value will always be of one of the kinds:
+  /// Type, TypeRef, TypeParameter.
+  InstanceRef get declaredType;
+
+  /// Is this field const?
+  bool get isConst;
+
+  /// Is this field final?
+  bool get isFinal;
+
+  /// Is this field static?
+  bool get isStatic;
+}
+
+enum GuardClassKind { unknown, single, dynamic }
+
+abstract class Field extends Object implements FieldRef {
+  /// [optional] The value of this field, if the field is static.
+  ObjectRef get staticValue;
+
+  /// [optional] The location of this field in the source code.
+  SourceLocation get location;
+
+  GuardClassKind get guardClassKind;
+  ClassRef get guardClass;
+  bool get guardNullable;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/flag.dart b/runtime/observatory_2/lib/src/models/objects/flag.dart
new file mode 100644
index 0000000..3813f88
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/flag.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class Flag {
+  /// The name of the flag.
+  String get name;
+
+  /// A description of the flag.
+  String get comment;
+
+  /// Has this flag been modified from its default setting?
+  bool get modified;
+
+  /// The value of this flag as a string. [optional]
+  ///
+  /// If this property is absent, then the value of the flag was NULL.
+  String get valueAsString;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/frame.dart b/runtime/observatory_2/lib/src/models/objects/frame.dart
new file mode 100644
index 0000000..12140f6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/frame.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum FrameKind { regular, asyncCausal, asyncSuspensionMarker, asyncActivation }
+
+abstract class Frame {
+  FrameKind get kind;
+  String get marker;
+  FunctionRef get function;
+  SourceLocation get location;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/function.dart b/runtime/observatory_2/lib/src/models/objects/function.dart
new file mode 100644
index 0000000..82d3d7f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/function.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum FunctionKind {
+  regular,
+  closure,
+  implicitClosure,
+  getter,
+  setter,
+  constructor,
+  implicitGetter,
+  implicitSetter,
+  implicitStaticGetter,
+  fieldInitializer,
+  irregexpFunction,
+  methodExtractor,
+  noSuchMethodDispatcher,
+  invokeFieldDispatcher,
+  collected,
+  native,
+  ffiTrampoline,
+  stub,
+  tag,
+  signatureFunction,
+  dynamicInvocationForwarder
+}
+
+bool isSyntheticFunction(FunctionKind kind) {
+  switch (kind) {
+    case FunctionKind.collected:
+    case FunctionKind.native:
+    case FunctionKind.stub:
+    case FunctionKind.tag:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isDartFunction(FunctionKind kind) => !isSyntheticFunction(kind);
+bool isStubFunction(FunctionKind kind) => kind == FunctionKind.stub;
+bool hasDartCode(FunctionKind kind) =>
+    isDartFunction(kind) || isStubFunction(kind);
+
+String getFunctionFullName(FunctionRef function) {
+  var content = <String>[function.name];
+  ObjectRef owner = function.dartOwner;
+  while (owner is FunctionRef) {
+    FunctionRef function = (owner as FunctionRef);
+    content.add(function.name);
+    owner = function.dartOwner;
+  }
+  if (owner is ClassRef) {
+    content.add(owner.name);
+  }
+  return content.reversed.join('.');
+}
+
+abstract class FunctionRef extends ObjectRef {
+  /// The name of this class.
+  String get name;
+
+  /// The owner of this function, which can be a LibraryRef, ClassRef,
+  /// or a FunctionRef.
+  ObjectRef get dartOwner; // owner
+
+  /// Is this function static?
+  bool get isStatic;
+
+  /// Is this function const?
+  bool get isConst;
+
+  /// The kind of the function.
+  FunctionKind get kind;
+}
+
+abstract class ServiceFunction extends Object implements FunctionRef {
+  /// The location of this function in the source code. [optional]
+  SourceLocation get location;
+
+  /// The compiled code associated with this function. [optional]
+  CodeRef get code;
+
+  /// [optional]
+  CodeRef get unoptimizedCode;
+
+  /// [optional]
+  CodeRef get bytecode;
+
+  /// [optional]
+  FieldRef get field;
+  int get usageCounter;
+  InstanceRef get icDataArray;
+  int get deoptimizations;
+  bool get isOptimizable;
+  bool get isInlinable;
+  bool get hasIntrinsic;
+  bool get isRecognized;
+  bool get isNative;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/guarded.dart b/runtime/observatory_2/lib/src/models/objects/guarded.dart
new file mode 100644
index 0000000..82bf1ee
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/guarded.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Guarded<T> {
+  bool get isValue;
+  bool get isSentinel;
+  Sentinel get asSentinel;
+  T get asValue;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/heap_space.dart b/runtime/observatory_2/lib/src/models/objects/heap_space.dart
new file mode 100644
index 0000000..cf62fbf
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/heap_space.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class HeapSpace {
+  int get used;
+  int get capacity;
+  int get collections;
+  int get external;
+  Duration get avgCollectionTime;
+  Duration get totalCollectionTime;
+  Duration get avgCollectionPeriod;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/icdata.dart b/runtime/observatory_2/lib/src/models/objects/icdata.dart
new file mode 100644
index 0000000..d975301
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/icdata.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ICDataRef extends ObjectRef {
+  String get selector;
+}
+
+abstract class ICData extends Object implements ICDataRef {
+  ObjectRef get dartOwner;
+  InstanceRef get argumentsDescriptor;
+  InstanceRef get entries;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/inbound_references.dart b/runtime/observatory_2/lib/src/models/objects/inbound_references.dart
new file mode 100644
index 0000000..ea18744
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/inbound_references.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class InboundReferences {
+  Iterable<InboundReference> get elements;
+}
+
+abstract class InboundReference {
+  ObjectRef get source;
+
+  /// [optional]
+  ObjectRef get parentField;
+
+  /// [optional]
+  int get parentListIndex;
+
+  /// [optional]
+  int get parentWordOffset;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/instance.dart b/runtime/observatory_2/lib/src/models/objects/instance.dart
new file mode 100644
index 0000000..66965e9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/instance.dart
@@ -0,0 +1,455 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum InstanceKind {
+  /// A general instance of the Dart class Object.
+  plainInstance,
+
+  /// null instance.
+  vNull,
+
+  /// true or false.
+  bool,
+
+  /// An instance of the Dart class double.
+  double,
+
+  /// An instance of the Dart class int.
+  int,
+
+  /// An instance of the Dart class String.
+  string,
+
+  /// An instance of the built-in VM List implementation. User-defined
+  /// Lists will be PlainInstance.
+  list,
+
+  /// An instance of the built-in VM Map implementation. User-defined
+  /// Maps will be PlainInstance.
+  map,
+
+  /// Vector instance kinds.
+  float32x4,
+
+  /// Vector instance kinds.
+  float64x2,
+
+  /// Vector instance kinds.
+  int32x4,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  uint8ClampedList,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  uint8List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  uint16List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  uint32List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  uint64List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  int8List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  int16List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  int32List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  int64List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  float32List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  float64List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  int32x4List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  float32x4List,
+
+  /// An instance of the built-in VM TypedData implementations. User-defined
+  /// TypedDatas will be PlainInstance.
+  float64x2List,
+
+  /// An instance of the Dart class StackTrace.
+  stackTrace,
+
+  /// An instance of the built-in VM Closure implementation. User-defined
+  /// Closures will be PlainInstance.
+  closure,
+
+  /// An instance of the Dart class MirrorReference.
+  mirrorReference,
+
+  /// An instance of the Dart class RegExp.
+  regExp,
+
+  /// An instance of the Dart class WeakProperty.
+  weakProperty,
+
+  /// An instance of the Dart class Type.
+  type,
+
+  /// An instance of the Dart class TypeParameter.
+  typeParameter,
+
+  /// An instance of the Dart class TypeRef.
+  typeRef,
+}
+
+bool isTypedData(InstanceKind kind) {
+  switch (kind) {
+    case InstanceKind.uint8ClampedList:
+    case InstanceKind.uint8List:
+    case InstanceKind.uint16List:
+    case InstanceKind.uint32List:
+    case InstanceKind.uint64List:
+    case InstanceKind.int8List:
+    case InstanceKind.int16List:
+    case InstanceKind.int32List:
+    case InstanceKind.int64List:
+    case InstanceKind.float32List:
+    case InstanceKind.float64List:
+    case InstanceKind.int32x4List:
+    case InstanceKind.float32x4List:
+    case InstanceKind.float64x2List:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isSimdValue(InstanceKind kind) {
+  switch (kind) {
+    case InstanceKind.float32x4:
+    case InstanceKind.float64x2:
+    case InstanceKind.int32x4:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool isAbstractType(InstanceKind kind) {
+  switch (kind) {
+    case InstanceKind.type:
+    case InstanceKind.typeRef:
+    case InstanceKind.typeParameter:
+      return true;
+    default:
+      return false;
+  }
+}
+
+abstract class InstanceRef extends ObjectRef {
+  /// What kind of instance is this?
+  InstanceKind get kind;
+
+  /// Instance references always include their class.
+  ClassRef get clazz;
+
+  /// [optional] The value of this instance as a string.
+  ///
+  /// Provided for the instance kinds:
+  ///   Null (null)
+  ///   Bool (true or false)
+  ///   Double (suitable for passing to Double.parse())
+  ///   Int (suitable for passing to int.parse())
+  ///   String (value may be truncated)
+  ///   Float32x4
+  ///   Float64x2
+  ///   Int32x4
+  ///   StackTrace
+  String get valueAsString;
+
+  /// [optional] The valueAsString for String references may be truncated. If so,
+  /// this property is added with the value 'true'.
+  ///
+  /// New code should use 'length' and 'count' instead.
+  bool get valueAsStringIsTruncated;
+
+  /// [optional] The length of a List or the number of associations in a Map or
+  /// the number of codeunits in a String.
+  ///
+  /// Provided for instance kinds:
+  ///   String
+  ///   List
+  ///   Map
+  ///   Uint8ClampedList
+  ///   Uint8List
+  ///   Uint16List
+  ///   Uint32List
+  ///   Uint64List
+  ///   Int8List
+  ///   Int16List
+  ///   Int32List
+  ///   Int64List
+  ///   Float32List
+  ///   Float64List
+  ///   Int32x4List
+  ///   Float32x4List
+  ///   Float64x2List
+  int get length;
+
+  /// [optional] The name of a Type instance.
+  ///
+  /// Provided for instance kinds:
+  ///   Type
+  String get name;
+
+  /// [optional] The corresponding Class if this Type is canonical.
+  ///
+  /// Provided for instance kinds:
+  ///   Type
+  ClassRef get typeClass;
+
+  /// [optional] The parameterized class of a type parameter:
+  ///
+  /// Provided for instance kinds:
+  ///   TypeParameter
+  ClassRef get parameterizedClass;
+
+  /// [optional] The pattern of a RegExp instance.
+  ///
+  /// The pattern is always an instance of kind String.
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  InstanceRef get pattern;
+
+  /// [optional] The function associated with a Closure instance.
+  ///
+  /// Provided for instance kinds:
+  ///   Closure
+  FunctionRef get closureFunction;
+
+  /// [optional] The context associated with a Closure instance.
+  ///
+  /// Provided for instance kinds:
+  ///   Closure
+  ContextRef get closureContext;
+}
+
+abstract class Instance extends Object implements InstanceRef {
+  /// [optional] The index of the first element or association or codeunit
+  /// returned. This is only provided when it is non-zero.
+  ///
+  /// Provided for instance kinds:
+  ///   String
+  ///   List
+  ///   Map
+  ///   Uint8ClampedList
+  ///   Uint8List
+  ///   Uint16List
+  ///   Uint32List
+  ///   Uint64List
+  ///   Int8List
+  ///   Int16List
+  ///   Int32List
+  ///   Int64List
+  ///   Float32List
+  ///   Float64List
+  ///   Int32x4List
+  ///   Float32x4List
+  ///   Float64x2List
+  int get offset;
+
+  /// [optional] The number of elements or associations or codeunits returned.
+  /// This is only provided when it is less than length.
+  ///
+  /// Provided for instance kinds:
+  ///   String
+  ///   List
+  ///   Map
+  ///   Uint8ClampedList
+  ///   Uint8List
+  ///   Uint16List
+  ///   Uint32List
+  ///   Uint64List
+  ///   Int8List
+  ///   Int16List
+  ///   Int32List
+  ///   Int64List
+  ///   Float32List
+  ///   Float64List
+  ///   Int32x4List
+  ///   Float32x4List
+  ///   Float64x2List
+  int get count;
+
+  /// [optional] The elements of a TypedData instance.
+  ///
+  /// Provided for instance kinds:
+  ///   Uint8ClampedList
+  ///   Uint8List
+  ///   Uint16List
+  ///   Uint32List
+  ///   Uint64List
+  ///   Int8List
+  ///   Int16List
+  ///   Int32List
+  ///   Int64List
+  ///   Float32List
+  ///   Float64List
+  ///   Int32x4List
+  ///   Float32x4List
+  ///   Float64x2List
+  List<dynamic> get typedElements;
+
+  /// [optional] The native fields of this Instance.
+  Iterable<NativeField> get nativeFields;
+
+  /// [optional] The fields of this Instance.
+  Iterable<BoundField> get fields;
+
+  /// [optional] The elements of a List instance.
+  ///
+  /// Provided for instance kinds:
+  ///   List
+  Iterable<Guarded<ObjectRef>> get elements;
+  // It should be:
+  // Iterable<Guarded<InstanceRef>> get elements;
+  // In some situations we obtain lists of non Instances
+
+  /// [optional] The elements of a Map instance.
+  ///
+  /// Provided for instance kinds:
+  ///   Map
+  Iterable<MapAssociation> get associations;
+
+  /// [optional] The key for a WeakProperty instance.
+  ///
+  /// Provided for instance kinds:
+  ///   WeakProperty
+  InstanceRef get key;
+
+  /// [optional] The key for a WeakProperty instance.
+  ///
+  /// Provided for instance kinds:
+  ///   WeakProperty
+  InstanceRef get value;
+
+  /// [optional] The referent of a MirrorReference instance.
+  ///
+  /// Provided for instance kinds:
+  ///   MirrorReference
+  ObjectRef get referent;
+
+  /// [optional] The type arguments for this type.
+  ///
+  /// Provided for instance kinds:
+  ///   Type
+  TypeArgumentsRef get typeArguments;
+
+  /// [optional] The index of a TypeParameter instance.
+  ///
+  /// Provided for instance kinds:
+  ///   TypeParameter
+  int get parameterIndex;
+
+  /// [optional] The referent of a TypeRef instance.
+  ///
+  /// The value will always be of one of the kinds:
+  /// Type, TypeRef, TypeParameter.
+  ///
+  /// Provided for instance kinds:
+  ///   TypeRef
+  InstanceRef get targetType;
+
+  /// [optional] The bound of a TypeParameter.
+  ///
+  /// The value will always be of one of the kinds:
+  /// Type, TypeRef, TypeParameter.
+  ///
+  /// Provided for instance kinds:
+  ///   TypeParameter
+  InstanceRef get bound;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   Closure
+  Breakpoint get activationBreakpoint;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  bool get isCaseSensitive;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  bool get isMultiLine;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  FunctionRef get oneByteFunction;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  FunctionRef get twoByteFunction;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  FunctionRef get externalOneByteFunction;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  FunctionRef get externalTwoByteFunction;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  InstanceRef get oneByteBytecode;
+
+  /// [optional]
+  ///
+  /// Provided for instance kinds:
+  ///   RegExp
+  InstanceRef get twoByteBytecode;
+}
+
+abstract class BoundField {
+  FieldRef get decl;
+  Guarded<InstanceRef> get value;
+}
+
+abstract class NativeField {
+  int get value;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/isolate.dart b/runtime/observatory_2/lib/src/models/objects/isolate.dart
new file mode 100644
index 0000000..a3c063a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/isolate.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class IsolateRef {
+  /// The id which is passed to the getIsolate RPC to reload this
+  /// isolate.
+  String get id;
+
+  /// A numeric id for this isolate, represented as a string. Unique.
+  int get number;
+
+  /// A name identifying this isolate. Not guaranteed to be unique.
+  String get name;
+
+  /// True if the isolate is a system isolate which is not running user code.
+  bool get isSystemIsolate;
+
+  /// Trigger a full GC, collecting all unreachable or weakly reachable objects.
+  Future collectAllGarbage();
+}
+
+enum IsolateStatus { loading, idle, running, paused }
+
+abstract class Isolate extends IsolateRef {
+  /// The time that the VM started in milliseconds since the epoch.
+  DateTime get startTime;
+
+  /// Is the isolate in a runnable state?
+  bool get runnable;
+
+  /// The number of live ports for this isolate.
+  //int get livePorts;
+
+  /// Will this isolate pause when exiting?
+  //bool get pauseOnExit;
+
+  /// The last pause event delivered to the isolate. If the isolate is
+  /// running, this will be a resume event.
+  Event get pauseEvent;
+
+  /// [optional] The root library for this isolate.
+  ///
+  /// Guaranteed to be initialized when the IsolateRunnable event fires.
+  LibraryRef get rootLibrary;
+
+  /// A list of all libraries for this isolate.
+  ///
+  /// Guaranteed to be initialized when the IsolateRunnable event fires.
+  Iterable<LibraryRef> get libraries;
+
+  /// A list of all breakpoints for this isolate.
+  //Iterable<Breakpoint> get breakpoints;
+
+  /// [optional] The error that is causing this isolate to exit, if applicable.
+  Error get error;
+
+  /// The list of threads associated with this isolate.
+  Iterable<Thread> get threads;
+
+  /// The maximum amount of zone memory in bytes allocated by the isolate in
+  /// all threads at a given time. Calculated using the high watermarks of each
+  /// thread alive when a thread is unscheduled.
+  int get zoneHighWatermark;
+
+  /// The number of zone handles currently held by this isolate.
+  int get numZoneHandles;
+
+  /// The number of scoped handles currently held by this isolate.
+  int get numScopedHandles;
+
+  /// The current pause on exception mode for this isolate.
+  //ExceptionPauseMode get exceptionPauseMode;
+
+  /// [optional] The list of service extension RPCs that are registered for this
+  /// isolate, if any.
+  Iterable<String> get extensionRPCs;
+
+  Map get counters;
+  HeapSpace get newSpace;
+  HeapSpace get oldSpace;
+
+  IsolateStatus get status;
+
+  /// [optional]
+  FunctionRef get entry;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/isolate_group.dart b/runtime/observatory_2/lib/src/models/objects/isolate_group.dart
new file mode 100644
index 0000000..7b7a83c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/isolate_group.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class IsolateGroupRef {
+  /// The id which is passed to the getIsolateGroup RPC to reload this
+  /// isolate group.
+  String get id;
+
+  /// A numeric id for this isolate group, represented as a string. Unique.
+  int get number;
+
+  /// A name identifying this isolate group. Not guaranteed to be unique.
+  String get name;
+
+  bool get isSystemIsolateGroup;
+}
+
+abstract class IsolateGroup extends IsolateGroupRef {
+  /// A list of all isolates in this isolate group.
+  Iterable<IsolateRef> get isolates;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/library.dart b/runtime/observatory_2/lib/src/models/objects/library.dart
new file mode 100644
index 0000000..83bab54
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/library.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class LibraryRef extends ObjectRef {
+  /// The name of this library.
+  String get name;
+
+  /// The uri of this library.
+  String get uri;
+}
+
+abstract class Library extends Object implements LibraryRef {
+  /// Is this library debuggable? Default true.
+  //bool get debuggable;
+
+  /// A list of the imports for this library.
+  Iterable<LibraryDependency> get dependencies;
+
+  /// A list of the scripts which constitute this library.
+  Iterable<ScriptRef> get scripts;
+
+  /// A list of the top-level variables in this library.
+  Iterable<FieldRef> get variables;
+
+  /// A list of the top-level functions in this library.
+  Iterable<FunctionRef> get functions;
+
+  /// A list of all classes in this library.
+  Iterable<ClassRef> get classes;
+
+  ScriptRef get rootScript;
+  String get vmName;
+}
+
+abstract class LibraryDependency {
+  bool get isImport;
+  bool get isDeferred;
+  LibraryRef get target;
+
+  /// [optional]
+  String get prefix;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/local_var_descriptors.dart b/runtime/observatory_2/lib/src/models/objects/local_var_descriptors.dart
new file mode 100644
index 0000000..5643b80
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/local_var_descriptors.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class LocalVarDescriptorsRef extends ObjectRef {
+  /// [optional]
+  String get name;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/map_association.dart b/runtime/observatory_2/lib/src/models/objects/map_association.dart
new file mode 100644
index 0000000..9f786f9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/map_association.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class MapAssociation {
+  Guarded<InstanceRef> get key;
+  Guarded<InstanceRef> get value;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/megamorphiccache.dart b/runtime/observatory_2/lib/src/models/objects/megamorphiccache.dart
new file mode 100644
index 0000000..74657de
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/megamorphiccache.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class MegamorphicCacheRef extends ObjectRef {
+  String get selector;
+}
+
+abstract class MegamorphicCache extends Object implements MegamorphicCacheRef {
+  String get selector;
+  int get mask;
+  InstanceRef get buckets;
+  InstanceRef get argumentsDescriptor;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/metric.dart b/runtime/observatory_2/lib/src/models/objects/metric.dart
new file mode 100644
index 0000000..fd8f7ac
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/metric.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Metric {
+  String get id;
+  String get name;
+  String get description;
+}
+
+abstract class MetricSample {
+  double get value;
+  DateTime get time;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/notification.dart b/runtime/observatory_2/lib/src/models/objects/notification.dart
new file mode 100644
index 0000000..1f46766
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/notification.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Notification {}
+
+abstract class ExceptionNotification implements Notification {
+  get exception;
+
+  /// [optional]
+  StackTrace get stacktrace;
+}
+
+abstract class EventNotification implements Notification {
+  Event get event;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/object.dart b/runtime/observatory_2/lib/src/models/objects/object.dart
new file mode 100644
index 0000000..044072f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/object.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ObjectRef {
+  /// A unique identifier for an Object.
+  String get id;
+}
+
+abstract class Object implements ObjectRef {
+  /// [optional] If an object is allocated in the Dart heap, it will have
+  /// a corresponding class object.
+  ///
+  /// The class of a non-instance is not a Dart class, but is instead
+  /// an internal vm object.
+  ///
+  /// Moving an Object into or out of the heap is considered a
+  /// backwards compatible change for types other than Instance.
+  ClassRef get clazz;
+
+  /// [optional] The size of this object in the heap.
+  ///
+  /// If an object is not heap-allocated, then this field is omitted.
+  ///
+  /// Note that the size can be zero for some objects. In the current
+  /// VM implementation, this occurs for small integers, which are
+  /// stored entirely within their object pointers.
+  int get size;
+
+  String get vmName;
+}
+
+abstract class RetainingObject {
+  int get retainedSize;
+  ObjectRef get object;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/objectpool.dart b/runtime/observatory_2/lib/src/models/objects/objectpool.dart
new file mode 100644
index 0000000..ba65961
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/objectpool.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ObjectPoolRef extends ObjectRef {
+  int get length;
+}
+
+abstract class ObjectPool extends Object implements ObjectPoolRef {
+  Iterable<ObjectPoolEntry> get entries;
+}
+
+enum ObjectPoolEntryKind { object, immediate, nativeEntryData, nativeEntry }
+
+abstract class ObjectPoolEntry {
+  int get offset;
+  ObjectPoolEntryKind get kind;
+  ObjectRef get asObject;
+  int get asInteger;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/objectstore.dart b/runtime/observatory_2/lib/src/models/objects/objectstore.dart
new file mode 100644
index 0000000..694f858
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/objectstore.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ObjectStore {
+  Iterable<NamedField> get fields;
+}
+
+abstract class NamedField {
+  String get name;
+  ObjectRef get value;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/pc_descriptors.dart b/runtime/observatory_2/lib/src/models/objects/pc_descriptors.dart
new file mode 100644
index 0000000..fea4ce6
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/pc_descriptors.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class PcDescriptorsRef extends ObjectRef {
+  /// [optional]
+  String get name;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/persistent_handles.dart b/runtime/observatory_2/lib/src/models/objects/persistent_handles.dart
new file mode 100644
index 0000000..ff81ff2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/persistent_handles.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class PersistentHandles {
+  Iterable<PersistentHandle> get elements;
+  Iterable<WeakPersistentHandle> get weakElements;
+}
+
+abstract class PersistentHandle {
+  ObjectRef get object;
+}
+
+abstract class WeakPersistentHandle implements PersistentHandle {
+  int get externalSize;
+  String get peer;
+  String get callbackSymbolName;
+  String get callbackAddress;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/ports.dart b/runtime/observatory_2/lib/src/models/objects/ports.dart
new file mode 100644
index 0000000..209357e
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/ports.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Ports {
+  Iterable<Port> get elements;
+}
+
+abstract class Port {
+  String get name;
+  ObjectRef get handler;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/retaining_path.dart b/runtime/observatory_2/lib/src/models/objects/retaining_path.dart
new file mode 100644
index 0000000..360d81d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/retaining_path.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class RetainingPath {
+  Iterable<RetainingPathItem> get elements;
+
+  String get gcRootType;
+}
+
+abstract class RetainingPathItem {
+  ObjectRef get source;
+
+  /// [optional]
+  String get parentField;
+
+  /// [optional]
+  int get parentListIndex;
+
+  /// [optional]
+  int get parentWordOffset;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/sample_profile.dart b/runtime/observatory_2/lib/src/models/objects/sample_profile.dart
new file mode 100644
index 0000000..582e571
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/sample_profile.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum ProfileTreeDirection { inclusive, exclusive }
+
+abstract class SampleProfile {
+  int get sampleCount;
+  int get maxStackDepth;
+  double get sampleRate;
+  double get timeSpan;
+  List<ProfileCode> get codes;
+  List<ProfileFunction> get functions;
+
+  FunctionCallTree loadFunctionTree(ProfileTreeDirection direction);
+  CodeCallTree loadCodeTree(ProfileTreeDirection direction);
+}
+
+abstract class Profile {
+  double get normalizedExclusiveTicks;
+  double get normalizedInclusiveTicks;
+  void clearTicks();
+  void tickTag();
+}
+
+abstract class ProfileCode extends Profile {
+  CodeRef get code;
+  Map<ProfileCode, int> get callers;
+  Map<ProfileCode, int> get callees;
+}
+
+abstract class ProfileFunction extends Profile {
+  FunctionRef get function;
+  String get resolvedUrl;
+  Map<ProfileFunction, int> get callers;
+  Map<ProfileFunction, int> get callees;
+}
+
+typedef bool CallTreeNodeFilter(CallTreeNode);
+
+abstract class CallTree {
+  CallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CodeCallTree extends CallTree {
+  CodeCallTreeNode get root;
+  CodeCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class FunctionCallTree extends CallTree {
+  FunctionCallTreeNode get root;
+  FunctionCallTree filtered(CallTreeNodeFilter filter);
+}
+
+abstract class CallTreeNode {
+  double get percentage;
+  int get count;
+  int get inclusiveNativeAllocations;
+  int get exclusiveNativeAllocations;
+  Iterable<CallTreeNode> get children;
+  void sortChildren();
+
+  void tick(Map sample, {bool exclusive = false});
+}
+
+abstract class CodeCallTreeNode extends CallTreeNode {
+  ProfileCode get profileCode;
+  Iterable<CodeCallTreeNode> get children;
+}
+
+abstract class FunctionCallTreeNode extends CallTreeNode {
+  ProfileFunction get profileFunction;
+  Iterable<FunctionCallTreeNode> get children;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/script.dart b/runtime/observatory_2/lib/src/models/objects/script.dart
new file mode 100644
index 0000000..df4b63b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/script.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ScriptRef extends ObjectRef {
+  /// The uri from which this script was loaded.
+  String get uri;
+}
+
+abstract class Script extends Object implements ScriptRef {
+  /// The library which owns this script.
+  LibraryRef get library;
+
+  /// The source code for this script. For certain built-in scripts,
+  /// this may be reconstructed without source comments.
+  String get source;
+
+  DateTime get loadTime;
+  int get firstTokenPos;
+  int get lastTokenPos;
+  int get lineOffset;
+  int get columnOffset;
+
+  int tokenToLine(int token);
+  int tokenToCol(int token);
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/sentinel.dart b/runtime/observatory_2/lib/src/models/objects/sentinel.dart
new file mode 100644
index 0000000..ca6747a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/sentinel.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum SentinelKind {
+  /// Indicates that the object referred to has been collected by the GC.
+  collected,
+
+  /// Indicates that an object id has expired.
+  expired,
+
+  /// Indicates that a variable or field has not been initialized.
+  notInitialized,
+
+  /// Indicates that a variable or field is in the process of being initialized.
+  initializing,
+
+  /// Indicates that a variable has been eliminated by the optimizing compiler.
+  optimizedOut,
+
+  /// Reserved for future use.
+  free,
+}
+
+abstract class Sentinel {
+  /// What kind of sentinel is this?
+  SentinelKind get kind;
+
+  /// A reasonable string representation of this sentinel.
+  String get valueAsString;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/service.dart b/runtime/observatory_2/lib/src/models/objects/service.dart
new file mode 100644
index 0000000..75d7522
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/service.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Service {
+  String get alias;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/single_target_cache.dart b/runtime/observatory_2/lib/src/models/objects/single_target_cache.dart
new file mode 100644
index 0000000..5178e7a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/single_target_cache.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class SingleTargetCacheRef extends ObjectRef {
+  Code get target;
+}
+
+abstract class SingleTargetCache extends Object
+    implements SingleTargetCacheRef {
+  int get lowerLimit;
+  int get upperLimit;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/source_location.dart b/runtime/observatory_2/lib/src/models/objects/source_location.dart
new file mode 100644
index 0000000..8a03f13
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/source_location.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Location {
+  /// The script containing the source location.
+  ScriptRef get script;
+
+  /// [optional] The first token of the location.
+  int get tokenPos;
+}
+
+abstract class SourceLocation implements Location {
+  /// The first token of the location.
+  int get tokenPos;
+
+  /// [optional] The last token of the location if this is a range.
+  int get endTokenPos;
+}
+
+abstract class UnresolvedSourceLocation implements Location {
+  /// [optional] The uri of the script containing the source location if the
+  /// script has yet to be loaded.
+  String get scriptUri;
+
+  /// [optional] An approximate line number for the source location. This may
+  /// change when the location is resolved.
+  int get line;
+
+  /// [optional] An approximate column number for the source location. This may
+  /// change when the location is resolved.
+  int get column;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/subtype_test_cache.dart b/runtime/observatory_2/lib/src/models/objects/subtype_test_cache.dart
new file mode 100644
index 0000000..cf56939
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/subtype_test_cache.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class SubtypeTestCacheRef extends ObjectRef {}
+
+abstract class SubtypeTestCache extends Object implements SubtypeTestCacheRef {
+  InstanceRef get cache;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/target.dart b/runtime/observatory_2/lib/src/models/objects/target.dart
new file mode 100644
index 0000000..a58673f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/target.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Target {
+  String get name;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/thread.dart b/runtime/observatory_2/lib/src/models/objects/thread.dart
new file mode 100644
index 0000000..8d16a8c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/thread.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+enum ThreadKind {
+  unknownTask,
+  mutatorTask,
+  compilerTask,
+  sweeperTask,
+  markerTask,
+  finalizerTask
+}
+
+abstract class Thread {
+  /// The id associated with the thread on creation.
+  String get id;
+
+  /// The task type associated with the thread.
+  ThreadKind get kind;
+
+  String get kindString;
+
+  /// The maximum amount of zone memory in bytes allocated by a thread at a
+  /// given time throughout the entire life of the thread.
+  int get zoneHighWatermark;
+
+  /// The current Zone capacity available to this thread.
+  int get zoneCapacity;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/timeline.dart b/runtime/observatory_2/lib/src/models/objects/timeline.dart
new file mode 100644
index 0000000..ae5e7b2
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/timeline.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class TimelineRecorder {
+  String get name;
+}
+
+abstract class TimelineStream {
+  String get name;
+  bool get isRecorded;
+}
+
+abstract class TimelineProfile {
+  String get name;
+  Iterable<TimelineStream> get streams;
+}
+
+abstract class TimelineFlags {
+  TimelineRecorder get recorder;
+  Iterable<TimelineStream> get streams;
+  Iterable<TimelineProfile> get profiles;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/timeline_event.dart b/runtime/observatory_2/lib/src/models/objects/timeline_event.dart
new file mode 100644
index 0000000..61bf444
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/timeline_event.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class TimelineEvent implements Map<String, dynamic> {}
diff --git a/runtime/observatory_2/lib/src/models/objects/type_arguments.dart b/runtime/observatory_2/lib/src/models/objects/type_arguments.dart
new file mode 100644
index 0000000..a3614dd
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/type_arguments.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class TypeArgumentsRef extends ObjectRef {
+  /// A name for this type argument list.
+  String get name;
+}
+
+abstract class TypeArguments extends Object implements TypeArgumentsRef {
+  /// A list of types.
+  ///
+  /// The value will always be one of the kinds:
+  /// Type, TypeRef, TypeParameter.
+  Iterable<InstanceRef> get types;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/unknown.dart b/runtime/observatory_2/lib/src/models/objects/unknown.dart
new file mode 100644
index 0000000..3faeed0
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/unknown.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class UnknownObjectRef extends ObjectRef {
+  String get vmType;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/unlinked_call.dart b/runtime/observatory_2/lib/src/models/objects/unlinked_call.dart
new file mode 100644
index 0000000..ed07750
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/unlinked_call.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class UnlinkedCallRef extends ObjectRef {
+  String get selector;
+}
+
+abstract class UnlinkedCall extends Object implements UnlinkedCallRef {
+  InstanceRef get argumentsDescriptor;
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/vm.dart b/runtime/observatory_2/lib/src/models/objects/vm.dart
new file mode 100644
index 0000000..b69d744
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/vm.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class VMRef {
+  /// A name identifying this vm. Not guaranteed to be unique.
+  String get name;
+
+  /// [Not actually from the apis]
+  /// A name used to identify the VM in the UI.
+  String get displayName;
+}
+
+abstract class VM implements VMRef {
+  /// Word length on target architecture (e.g. 32, 64).
+  int get architectureBits;
+
+  /// The CPU we are generating code for.
+  String get targetCPU;
+
+  /// The CPU we are actually running on.
+  String get hostCPU;
+
+  /// The Dart VM version string.
+  String get version;
+
+  String get embedder;
+
+  /// The amount of memory currently allocated by native code in zones.
+  int get nativeZoneMemoryUsage;
+
+  /// The process id for the VM.
+  int get pid;
+
+  /// The current amount of native heap allocated memory within the VM.
+  int get heapAllocatedMemoryUsage;
+
+  /// The current number of allocations on the native heap within the VM.
+  int get heapAllocationCount;
+
+  int get currentMemory;
+  int get maxRSS;
+  int get currentRSS;
+
+  /// The time that the VM started in milliseconds since the epoch.
+  ///
+  /// Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
+  DateTime get startTime;
+
+  // A list of isolates running in the VM.
+  Iterable<IsolateRef> get isolates;
+  Iterable<IsolateRef> get systemIsolates;
+  Iterable<IsolateGroupRef> get isolateGroups;
+  Iterable<IsolateGroupRef> get systemIsolateGroups;
+
+  /// Enable the sampling profiler.
+  Future enableProfiler();
+}
diff --git a/runtime/observatory_2/lib/src/models/objects/zone.dart b/runtime/observatory_2/lib/src/models/objects/zone.dart
new file mode 100644
index 0000000..51840cb
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/objects/zone.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class Zone {
+  /// The total amount of memory in bytes allocated in the zone, including
+  /// memory that is not actually being used.
+  int get capacity;
+
+  /// The total amount of memory in bytes actually used in the zone.
+  int get used;
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/allocation_profile.dart b/runtime/observatory_2/lib/src/models/repositories/allocation_profile.dart
new file mode 100644
index 0000000..ecb127b
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/allocation_profile.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class AllocationProfileRepository {
+  Future<AllocationProfile> get(IsolateRef isolate,
+      {bool gc: false, bool reset: false, bool combine: false});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/breakpoint.dart b/runtime/observatory_2/lib/src/models/repositories/breakpoint.dart
new file mode 100644
index 0000000..1727dd3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/breakpoint.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class BreakpointRepository {
+  Future addOnActivation(IsolateRef isolate, Instance closure);
+  Future remove(IsolateRef isolate, Breakpoint breakpoint);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/class.dart b/runtime/observatory_2/lib/src/models/repositories/class.dart
new file mode 100644
index 0000000..3695527
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/class.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ClassRepository {
+  Future<Class> getObject(IsolateRef isolate);
+  Future<Class> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/context.dart b/runtime/observatory_2/lib/src/models/repositories/context.dart
new file mode 100644
index 0000000..1c3fcf9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/context.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ContextRepository {
+  Future<Context> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/editor.dart b/runtime/observatory_2/lib/src/models/repositories/editor.dart
new file mode 100644
index 0000000..aef7199
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/editor.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class EditorRepository {
+  bool get isAvailable;
+
+  Future openClass(IsolateRef isolate, ClassRef clazz);
+  Future openField(IsolateRef isolate, FieldRef clazz);
+  Future openFunction(IsolateRef isolate, FunctionRef clazz);
+  Future openObject(IsolateRef isolate, ObjectRef clazz);
+  Future openSourceLocation(IsolateRef isolate, SourceLocation location);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/eval.dart b/runtime/observatory_2/lib/src/models/repositories/eval.dart
new file mode 100644
index 0000000..2bd4c61
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/eval.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class EvalRepository {
+  Future<ObjectRef> evaluate(
+      IsolateRef isolate, ObjectRef context, String expression,
+      {bool disableBreakpoints: false});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/event.dart b/runtime/observatory_2/lib/src/models/repositories/event.dart
new file mode 100644
index 0000000..ae5367e
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/event.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class EventRepository {
+  Stream<Event> get onEvent;
+  Stream<VMEvent> get onVMEvent;
+  Stream<VMUpdateEvent> get onVMUpdate;
+  Stream<IsolateEvent> get onIsolateEvent;
+  Stream<IsolateStartEvent> get onIsolateStart;
+  Stream<IsolateRunnableEvent> get onIsolateRunnable;
+  Stream<IsolateExitEvent> get onIsolateExit;
+  Stream<IsolateUpdateEvent> get onIsolateUpdate;
+  Stream<IsolateReloadEvent> get onIsolateReload;
+  Stream<ServiceExtensionAddedEvent> get onServiceExtensionAdded;
+  Stream<DebugEvent> get onDebugEvent;
+  Stream<PauseStartEvent> get onPauseStart;
+  Stream<PauseExitEvent> get onPauseExit;
+  Stream<PauseBreakpointEvent> get onPauseBreakpoint;
+  Stream<PauseInterruptedEvent> get onPauseInterrupted;
+  Stream<PauseExceptionEvent> get onPauseException;
+  Stream<ResumeEvent> get onResume;
+  Stream<BreakpointAddedEvent> get onBreakpointAdded;
+  Stream<BreakpointResolvedEvent> get onBreakpointResolved;
+  Stream<BreakpointRemovedEvent> get onBreakpointRemoved;
+  Stream<InspectEvent> get onInspect;
+  Stream<GCEvent> get onGCEvent;
+  Stream<LoggingEvent> get onLoggingEvent;
+  Stream<ExtensionEvent> get onExtensionEvent;
+  Stream<TimelineEventsEvent> get onTimelineEvents;
+  Stream<ConnectionClosedEvent> get onConnectionClosed;
+  Stream<ServiceEvent> get onServiceEvent;
+  Stream<ServiceRegisteredEvent> get onServiceRegistered;
+  Stream<ServiceUnregisteredEvent> get onServiceUnregistered;
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/field.dart b/runtime/observatory_2/lib/src/models/repositories/field.dart
new file mode 100644
index 0000000..6892b17
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/field.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class FieldRepository {
+  Future<Field> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/flag.dart b/runtime/observatory_2/lib/src/models/repositories/flag.dart
new file mode 100644
index 0000000..358b933
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/flag.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class FlagsRepository {
+  Future<Iterable<Flag>> list();
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/function.dart b/runtime/observatory_2/lib/src/models/repositories/function.dart
new file mode 100644
index 0000000..56298d7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/function.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class FunctionRepository {
+  Future<ServiceFunction> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/heap_snapshot.dart b/runtime/observatory_2/lib/src/models/repositories/heap_snapshot.dart
new file mode 100644
index 0000000..3bc6305
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/heap_snapshot.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class HeapSnapshotRepository {
+  SnapshotReader get(IsolateRef isolate);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/icdata.dart b/runtime/observatory_2/lib/src/models/repositories/icdata.dart
new file mode 100644
index 0000000..7b3b752
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/icdata.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ICDataRepository {
+  Future<ICData> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/inbound_references.dart b/runtime/observatory_2/lib/src/models/repositories/inbound_references.dart
new file mode 100644
index 0000000..09cdcca
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/inbound_references.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class InboundReferencesRepository {
+  Future<InboundReferences> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/instance.dart b/runtime/observatory_2/lib/src/models/repositories/instance.dart
new file mode 100644
index 0000000..4da307f
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/instance.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class InstanceRepository {
+  Future<Instance> get(IsolateRef isolate, String id, {int count});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/isolate.dart b/runtime/observatory_2/lib/src/models/repositories/isolate.dart
new file mode 100644
index 0000000..98c5976
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/isolate.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class IsolateRepository {
+  Iterable<Service> get reloadSourcesServices;
+  Future<Isolate> get(IsolateRef isolate);
+  Future reloadSources(IsolateRef isolate, {Service service});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/isolate_group.dart b/runtime/observatory_2/lib/src/models/repositories/isolate_group.dart
new file mode 100644
index 0000000..ccf2422
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/isolate_group.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class IsolateGroupRepository {
+  Future<IsolateGroup> get(IsolateGroupRef isolateGroup);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/library.dart b/runtime/observatory_2/lib/src/models/repositories/library.dart
new file mode 100644
index 0000000..7e68be7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/library.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class LibraryRepository {
+  Future<Library> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/megamorphiccache.dart b/runtime/observatory_2/lib/src/models/repositories/megamorphiccache.dart
new file mode 100644
index 0000000..cfddc73
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/megamorphiccache.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class MegamorphicCacheRepository {
+  Future<MegamorphicCache> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/metric.dart b/runtime/observatory_2/lib/src/models/repositories/metric.dart
new file mode 100644
index 0000000..ee10fdb
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/metric.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum MetricBufferSize { n10samples, n100samples, n1000samples }
+
+enum MetricSamplingRate { off, e100ms, e1s, e2s, e4s, e8s }
+
+abstract class MetricRepository {
+  Future<Iterable<Metric>> list(IsolateRef isolate);
+  void setSamplingRate(IsolateRef isolate, Metric metric, MetricSamplingRate r);
+  MetricSamplingRate getSamplingRate(IsolateRef isolate, Metric metric);
+  void setBufferSize(IsolateRef isolate, Metric metric, MetricBufferSize r);
+  MetricBufferSize getBufferSize(IsolateRef isolate, Metric metric);
+  Iterable<MetricSample> getSamples(IsolateRef isolate, Metric metric);
+  double getMinValue(IsolateRef isolate, Metric metric);
+  double getMaxValue(IsolateRef isolate, Metric metric);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/notification.dart b/runtime/observatory_2/lib/src/models/repositories/notification.dart
new file mode 100644
index 0000000..c9c7824
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/notification.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class NotificationChangeEvent {
+  NotificationRepository get repository;
+}
+
+abstract class NotificationRepository {
+  Stream<NotificationChangeEvent> get onChange;
+  Iterable<Notification> list();
+  void delete(Notification notification);
+  void deleteAll();
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/object.dart b/runtime/observatory_2/lib/src/models/repositories/object.dart
new file mode 100644
index 0000000..3350db4
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/object.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ObjectRepository {
+  Future<Object> get(IsolateRef isolate, String id, {int count});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/objectpool.dart b/runtime/observatory_2/lib/src/models/repositories/objectpool.dart
new file mode 100644
index 0000000..36f51ba
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/objectpool.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ObjectPoolRepository {
+  Future<ObjectPool> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/objectstore.dart b/runtime/observatory_2/lib/src/models/repositories/objectstore.dart
new file mode 100644
index 0000000..ee1735c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/objectstore.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ObjectStoreRepository {
+  Future<ObjectStore> get(IsolateRef isolate);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/persistent_handles.dart b/runtime/observatory_2/lib/src/models/repositories/persistent_handles.dart
new file mode 100644
index 0000000..62d6323
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/persistent_handles.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class PersistentHandlesRepository {
+  Future<PersistentHandles> get(IsolateRef isolate);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/ports.dart b/runtime/observatory_2/lib/src/models/repositories/ports.dart
new file mode 100644
index 0000000..bbb8c80
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/ports.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class PortsRepository {
+  Future<Ports> get(IsolateRef isolate);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/reachable_size.dart b/runtime/observatory_2/lib/src/models/repositories/reachable_size.dart
new file mode 100644
index 0000000..fc1292fb
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/reachable_size.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class ReachableSizeRepository {
+  Future<Guarded<Instance>> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/retained_size.dart b/runtime/observatory_2/lib/src/models/repositories/retained_size.dart
new file mode 100644
index 0000000..3b4fe8e
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/retained_size.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class RetainedSizeRepository {
+  Future<Guarded<Instance>> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/retaining_path.dart b/runtime/observatory_2/lib/src/models/repositories/retaining_path.dart
new file mode 100644
index 0000000..1999846
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/retaining_path.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class RetainingPathRepository {
+  Future<RetainingPath> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/sample_profile.dart b/runtime/observatory_2/lib/src/models/repositories/sample_profile.dart
new file mode 100644
index 0000000..4a21ed8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/sample_profile.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+enum SampleProfileTag { userVM, userOnly, vmUser, vmOnly, none }
+
+enum SampleProfileLoadingStatus { disabled, fetching, loading, loaded }
+
+enum SampleProfileType { cpu, memory }
+
+bool isSampleProcessRunning(SampleProfileLoadingStatus status) {
+  switch (status) {
+    case SampleProfileLoadingStatus.fetching:
+    case SampleProfileLoadingStatus.loading:
+      return true;
+    default:
+      return false;
+  }
+}
+
+abstract class SampleProfileLoadingProgressEvent {
+  SampleProfileLoadingProgress get progress;
+}
+
+abstract class SampleProfileLoadingProgress {
+  SampleProfileLoadingStatus get status;
+  double get progress;
+  Duration get fetchingTime;
+  Duration get loadingTime;
+  SampleProfile get profile;
+}
+
+abstract class ClassSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(
+      IsolateRef isolate, ClassRef cls, SampleProfileTag tag,
+      {bool clear: false, bool forceFetch: false});
+  Future enable(IsolateRef isolate, ClassRef cls);
+  Future disable(IsolateRef isolate, ClassRef cls);
+}
+
+abstract class IsolateSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(
+      IsolateRef isolate, SampleProfileTag tag,
+      {bool clear: false, bool forceFetch: false});
+}
+
+abstract class NativeMemorySampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(VM vm, SampleProfileTag tag,
+      {bool clear: false, bool forceFetch: false});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/script.dart b/runtime/observatory_2/lib/src/models/repositories/script.dart
new file mode 100644
index 0000000..3ba2dc3
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/script.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class ScriptRepository {
+  Future<Script> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/single_target_cache.dart b/runtime/observatory_2/lib/src/models/repositories/single_target_cache.dart
new file mode 100644
index 0000000..bc4a767
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/single_target_cache.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class SingleTargetCacheRepository {
+  Future<SingleTargetCache> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart b/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart
new file mode 100644
index 0000000..c0449f8
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class StronglyReachableInstancesRepository {
+  Future<InstanceSet> get(IsolateRef isolate, ClassRef cls, {int limit: 100});
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/subtype_test_cache.dart b/runtime/observatory_2/lib/src/models/repositories/subtype_test_cache.dart
new file mode 100644
index 0000000..1a03805
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/subtype_test_cache.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class SubtypeTestCacheRepository {
+  Future<SubtypeTestCache> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/target.dart b/runtime/observatory_2/lib/src/models/repositories/target.dart
new file mode 100644
index 0000000..2c2db92
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/target.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class TargetChangeEvent {
+  TargetRepository get repository;
+}
+
+abstract class TargetRepository {
+  Stream<TargetChangeEvent> get onChange;
+
+  Target get current;
+  Iterable<Target> list();
+  void add(String address);
+  void setCurrent(Target t);
+  void delete(Target o);
+  Target find(String networkAddress);
+  bool isConnectedVMTarget(Target target);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/timeline.dart b/runtime/observatory_2/lib/src/models/repositories/timeline.dart
new file mode 100644
index 0000000..3d528c9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/timeline.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class TimelineRepository {
+  Future<TimelineFlags> getFlags(VMRef ref);
+  Future setRecordedStreams(VMRef ref, Iterable<TimelineStream> streams);
+  Future clear(VMRef ref);
+  Future<Map> getTimeline(VMRef ref);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/type_arguments.dart b/runtime/observatory_2/lib/src/models/repositories/type_arguments.dart
new file mode 100644
index 0000000..dee8170
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/type_arguments.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class TypeArgumentsRepository {
+  Future<TypeArguments> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/unlinked_call.dart b/runtime/observatory_2/lib/src/models/repositories/unlinked_call.dart
new file mode 100644
index 0000000..fd60305
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/unlinked_call.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of models;
+
+abstract class UnlinkedCallRepository {
+  Future<UnlinkedCall> get(IsolateRef isolate, String id);
+}
diff --git a/runtime/observatory_2/lib/src/models/repositories/vm.dart b/runtime/observatory_2/lib/src/models/repositories/vm.dart
new file mode 100644
index 0000000..fd646bc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/models/repositories/vm.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of models;
+
+abstract class VMRepository {
+  Future<VM> get(VMRef ref);
+}
diff --git a/runtime/observatory_2/lib/src/repositories/allocation_profile.dart b/runtime/observatory_2/lib/src/repositories/allocation_profile.dart
new file mode 100644
index 0000000..365a6fc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/allocation_profile.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class AllocationProfileRepository implements M.AllocationProfileRepository {
+  static const _api = '_getAllocationProfile';
+  static const _defaultsApi = '_getDefaultClassesAliases';
+
+  Future<M.AllocationProfile> get(M.IsolateRef i,
+      {bool gc: false, bool reset: false, bool combine: false}) async {
+    assert(gc != null);
+    assert(reset != null);
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    var params = {};
+    if (gc) {
+      params['gc'] = 'true';
+    }
+    if (reset) {
+      params['reset'] = true;
+    }
+    final dynamic response = await isolate.invokeRpc(_api, params);
+    Map defaults;
+    if (combine) {
+      defaults = await isolate.vm.invokeRpcNoUpgrade(_defaultsApi, {});
+      defaults = defaults['map'];
+    }
+    isolate.updateHeapsFromMap(response['_heaps']);
+    for (S.ServiceMap clsAllocations in response['members']) {
+      S.Class cls = clsAllocations['class'];
+      if (cls == null) {
+        continue;
+      }
+      cls.newSpace.update(clsAllocations['_new']);
+      cls.oldSpace.update(clsAllocations['_old']);
+    }
+    return new AllocationProfile(response, defaults: defaults);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/breakpoint.dart b/runtime/observatory_2/lib/src/repositories/breakpoint.dart
new file mode 100644
index 0000000..99a66ca
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/breakpoint.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class BreakpointRepository extends M.BreakpointRepository {
+  Future addOnActivation(M.IsolateRef i, M.Instance closure) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    await isolate.addBreakOnActivation(closure);
+  }
+
+  Future remove(M.IsolateRef i, M.Breakpoint breakpoint) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    await isolate.removeBreakpoint(breakpoint);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/class.dart b/runtime/observatory_2/lib/src/repositories/class.dart
new file mode 100644
index 0000000..5f8f391
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/class.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ClassRepository extends M.ClassRepository {
+  Future<M.Class> getObject(M.IsolateRef i) {
+    final isolate = i as S.Isolate;
+    assert(isolate != null);
+    return isolate.getClassHierarchy();
+  }
+
+  Future<M.Class> get(M.IsolateRef i, String id) async {
+    final isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.Class;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/context.dart b/runtime/observatory_2/lib/src/repositories/context.dart
new file mode 100644
index 0000000..a861f6a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/context.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ContextRepository extends M.ContextRepository {
+  Future<M.Context> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.Context;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/editor.dart b/runtime/observatory_2/lib/src/repositories/editor.dart
new file mode 100644
index 0000000..d58cb36
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/editor.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class EditorRepository extends M.EditorRepository {
+  final S.VM _vm;
+  final String _editor;
+
+  bool get isAvailable => _getService() != null;
+
+  EditorRepository(S.VM vm, {String editor})
+      : _vm = vm,
+        _editor = editor {
+    assert(_vm != null);
+  }
+
+  S.Service _getService() {
+    Iterable<M.Service> services =
+        _vm.services.where((s) => s.service == 'openSourceLocation');
+    if (_editor != null) {
+      services = services.where((s) => s.alias == _editor);
+    }
+    if (services.isNotEmpty) {
+      return services.first;
+    }
+    return null;
+  }
+
+  Future openClass(M.IsolateRef i, M.ClassRef c) async {
+    S.Class clazz = c as S.Class;
+    assert(clazz != null);
+    if (!clazz.loaded) {
+      await clazz.load();
+    }
+    if (clazz.location == null) {
+      return new Future.value();
+    }
+    return await openSourceLocation(i, clazz.location);
+  }
+
+  Future openField(M.IsolateRef i, M.FieldRef f) async {
+    S.Field field = f as S.Field;
+    assert(field != null);
+    if (!field.loaded) {
+      await field.load();
+    }
+    if (field.location == null) {
+      return new Future.value();
+    }
+    return await openSourceLocation(i, field.location);
+  }
+
+  Future openFunction(M.IsolateRef i, M.FunctionRef f) async {
+    S.ServiceFunction field = f as S.ServiceFunction;
+    assert(field != null);
+    if (!field.loaded) {
+      await field.load();
+    }
+    if (field.location == null) {
+      return new Future.value();
+    }
+    return await openSourceLocation(i, field.location);
+  }
+
+  Future openObject(M.IsolateRef i, M.ObjectRef o) async {
+    assert(o != null);
+    if (o is M.ClassRef) {
+      return await openClass(i, o);
+    }
+    if (o is M.InstanceRef) {
+      return await openClass(i, o.clazz);
+    }
+    if (o is M.FieldRef) {
+      return await openField(i, o);
+    }
+    if (o is M.FunctionRef) {
+      return await openFunction(i, o);
+    }
+    if (o is M.InstanceRef) {
+      if (o.closureFunction != null) {
+        return await openFunction(i, o.closureFunction);
+      }
+      return await openClass(i, o.clazz);
+    }
+    return new Future.value();
+  }
+
+  Future openSourceLocation(M.IsolateRef i, M.SourceLocation l) async {
+    final isolate = i as S.Isolate;
+    assert(isolate != null);
+    assert(l != null);
+    return await isolate.invokeRpc(_getService().method,
+        {'scriptId': l.script.id, 'tokenPos': l.tokenPos});
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/eval.dart b/runtime/observatory_2/lib/src/repositories/eval.dart
new file mode 100644
index 0000000..57ab1ec
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/eval.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class EvalRepository extends M.EvalRepository {
+  Future<M.ObjectRef> evaluate(M.IsolateRef i, M.ObjectRef o, String e,
+      {bool disableBreakpoints: false}) async {
+    S.Isolate isolate = i as S.Isolate;
+    S.ServiceObject object = o as S.HeapObject;
+    assert(isolate != null);
+    assert(object != null);
+    assert(e != null);
+    return await isolate.eval(object, e,
+        disableBreakpoints: disableBreakpoints);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/event.dart b/runtime/observatory_2/lib/src/repositories/event.dart
new file mode 100644
index 0000000..39313a9
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/event.dart
@@ -0,0 +1,139 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class EventRepository implements M.EventRepository {
+  final StreamController<M.Event> _onEvent;
+  Stream<M.Event> get onEvent => _onEvent.stream;
+
+  final Stream<M.VMEvent> onVMEvent;
+  final Stream<M.VMUpdateEvent> onVMUpdate;
+  final Stream<M.IsolateEvent> onIsolateEvent;
+  final Stream<M.IsolateStartEvent> onIsolateStart;
+  final Stream<M.IsolateRunnableEvent> onIsolateRunnable;
+  final Stream<M.IsolateExitEvent> onIsolateExit;
+  final Stream<M.IsolateUpdateEvent> onIsolateUpdate;
+  final Stream<M.IsolateReloadEvent> onIsolateReload;
+  final Stream<M.ServiceExtensionAddedEvent> onServiceExtensionAdded;
+  final Stream<M.DebugEvent> onDebugEvent;
+  final Stream<M.PauseStartEvent> onPauseStart;
+  final Stream<M.PauseExitEvent> onPauseExit;
+  final Stream<M.PauseBreakpointEvent> onPauseBreakpoint;
+  final Stream<M.PauseInterruptedEvent> onPauseInterrupted;
+  final Stream<M.PauseExceptionEvent> onPauseException;
+  final Stream<M.ResumeEvent> onResume;
+  final Stream<M.BreakpointAddedEvent> onBreakpointAdded;
+  final Stream<M.BreakpointResolvedEvent> onBreakpointResolved;
+  final Stream<M.BreakpointRemovedEvent> onBreakpointRemoved;
+  final Stream<M.InspectEvent> onInspect;
+  final Stream<M.GCEvent> onGCEvent;
+  final Stream<M.LoggingEvent> onLoggingEvent;
+  final Stream<M.ExtensionEvent> onExtensionEvent;
+  final Stream<M.TimelineEventsEvent> onTimelineEvents;
+  final Stream<M.ConnectionClosedEvent> onConnectionClosed;
+  final Stream<M.ServiceEvent> onServiceEvent;
+  final Stream<M.ServiceRegisteredEvent> onServiceRegistered;
+  final Stream<M.ServiceUnregisteredEvent> onServiceUnregistered;
+
+  static Stream<T> where<T extends M.Event>(
+      Stream<M.Event> stream, bool predicate(M.Event event)) {
+    var controller = new StreamController<T>.broadcast();
+    stream.listen(
+      (M.Event event) {
+        if (predicate(event)) {
+          controller.add(event as T);
+        }
+      },
+      onError: (error) => controller.addError(error),
+      onDone: () => controller.close(),
+    );
+    return controller.stream;
+  }
+
+  EventRepository() : this._(new StreamController<M.Event>.broadcast());
+
+  EventRepository._(StreamController<M.Event> controller)
+      : this.__(
+            controller,
+            where<M.VMEvent>(controller.stream, (e) => e is M.VMEvent),
+            where<M.IsolateEvent>(
+                controller.stream, (e) => e is M.IsolateEvent),
+            where<M.DebugEvent>(controller.stream, (e) => e is M.DebugEvent),
+            where<M.GCEvent>(controller.stream, (e) => e is M.GCEvent),
+            where<M.LoggingEvent>(
+                controller.stream, (e) => e is M.LoggingEvent),
+            where<M.ExtensionEvent>(
+                controller.stream, (e) => e is M.ExtensionEvent),
+            where<M.TimelineEventsEvent>(
+                controller.stream, (e) => e is M.TimelineEventsEvent),
+            where<M.ConnectionClosedEvent>(
+                controller.stream, (e) => e is M.ConnectionClosedEvent),
+            where<M.ServiceEvent>(
+                controller.stream, (e) => e is M.ServiceEvent));
+
+  EventRepository.__(
+      StreamController<M.Event> controller,
+      Stream<M.VMEvent> onVMEvent,
+      Stream<M.IsolateEvent> onIsolateEvent,
+      Stream<M.DebugEvent> onDebugEvent,
+      Stream<M.GCEvent> onGCEvent,
+      Stream<M.LoggingEvent> onLoggingEvent,
+      Stream<M.ExtensionEvent> onExtensionEvent,
+      Stream<M.TimelineEventsEvent> onTimelineEvents,
+      Stream<M.ConnectionClosedEvent> onConnectionClosed,
+      Stream<M.ServiceEvent> onServiceEvent)
+      : _onEvent = controller,
+        onVMEvent = onVMEvent,
+        onVMUpdate =
+            where<M.VMUpdateEvent>(onVMEvent, (e) => e is M.VMUpdateEvent),
+        onIsolateEvent = onIsolateEvent,
+        onIsolateStart = where<M.IsolateStartEvent>(
+            onIsolateEvent, (e) => e is M.IsolateStartEvent),
+        onIsolateRunnable = where<M.IsolateRunnableEvent>(
+            onIsolateEvent, (e) => e is M.IsolateRunnableEvent),
+        onIsolateExit = where<M.IsolateExitEvent>(
+            onIsolateEvent, (e) => e is M.IsolateExitEvent),
+        onIsolateUpdate = where<M.IsolateUpdateEvent>(
+            onIsolateEvent, (e) => e is M.IsolateUpdateEvent),
+        onIsolateReload = where<M.IsolateReloadEvent>(
+            onIsolateEvent, (e) => e is M.IsolateReloadEvent),
+        onServiceExtensionAdded = where<M.ServiceExtensionAddedEvent>(
+            onIsolateEvent, (e) => e is M.ServiceExtensionAddedEvent),
+        onDebugEvent = onDebugEvent,
+        onPauseStart = where<M.PauseStartEvent>(
+            onDebugEvent, (e) => e is M.PauseStartEvent),
+        onPauseExit =
+            where<M.PauseExitEvent>(onDebugEvent, (e) => e is M.PauseExitEvent),
+        onPauseBreakpoint = where<M.PauseBreakpointEvent>(
+            onDebugEvent, (e) => e is M.PauseBreakpointEvent),
+        onPauseInterrupted = where<M.PauseInterruptedEvent>(
+            onDebugEvent, (e) => e is M.PauseInterruptedEvent),
+        onPauseException = where<M.PauseExceptionEvent>(
+            onDebugEvent, (e) => e is M.PauseExceptionEvent),
+        onResume =
+            where<M.ResumeEvent>(onDebugEvent, (e) => e is M.ResumeEvent),
+        onBreakpointAdded = where<M.BreakpointAddedEvent>(
+            onDebugEvent, (e) => e is M.BreakpointAddedEvent),
+        onBreakpointResolved = where<M.BreakpointResolvedEvent>(
+            onDebugEvent, (e) => e is M.BreakpointResolvedEvent),
+        onBreakpointRemoved = where<M.BreakpointRemovedEvent>(
+            onDebugEvent, (e) => e is M.BreakpointRemovedEvent),
+        onInspect =
+            where<M.InspectEvent>(onDebugEvent, (e) => e is M.InspectEvent),
+        onGCEvent = onGCEvent,
+        onLoggingEvent = onLoggingEvent,
+        onExtensionEvent = onExtensionEvent,
+        onTimelineEvents = onTimelineEvents,
+        onConnectionClosed = onConnectionClosed,
+        onServiceEvent = onServiceEvent,
+        onServiceRegistered = where<M.ServiceRegisteredEvent>(
+            onServiceEvent, (e) => e is M.ServiceRegisteredEvent),
+        onServiceUnregistered = where<M.ServiceUnregisteredEvent>(
+            onServiceEvent, (e) => e is M.ServiceUnregisteredEvent);
+
+  void add(M.Event e) {
+    _onEvent.add(e);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/field.dart b/runtime/observatory_2/lib/src/repositories/field.dart
new file mode 100644
index 0000000..932a84d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/field.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class FieldRepository extends M.FieldRepository {
+  Future<M.Field> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.Field;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/flag.dart b/runtime/observatory_2/lib/src/repositories/flag.dart
new file mode 100644
index 0000000..13ab784
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/flag.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class Flag implements M.Flag {
+  final String name;
+  final String comment;
+  final bool modified;
+  final String valueAsString;
+  Flag(this.name, this.comment, this.modified, this.valueAsString) {
+    assert(name != null);
+    assert(comment != null);
+    assert(modified != null);
+  }
+}
+
+class FlagsRepository implements M.FlagsRepository {
+  final S.VM vm;
+
+  FlagsRepository(this.vm);
+
+  Future<Iterable<Flag>> list() async {
+    var result = <Flag>[];
+    for (var map in ((await vm.getFlagList()) as S.ServiceMap)['flags']) {
+      result.add(_toFlag(map));
+    }
+    return result;
+  }
+
+  static Flag _toFlag(Map map) {
+    return new Flag(
+        map['name'], map['comment'], map['modified'], map['valueAsString']);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/function.dart b/runtime/observatory_2/lib/src/repositories/function.dart
new file mode 100644
index 0000000..68527c5
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/function.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class FunctionRepository extends M.FunctionRepository {
+  Future<M.ServiceFunction> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.ServiceFunction;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/heap_snapshot.dart b/runtime/observatory_2/lib/src/repositories/heap_snapshot.dart
new file mode 100644
index 0000000..c574d17
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/heap_snapshot.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class HeapSnapshotRepository implements M.HeapSnapshotRepository {
+  SnapshotReader get(M.IsolateRef i) {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return isolate.fetchHeapSnapshot();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/icdata.dart b/runtime/observatory_2/lib/src/repositories/icdata.dart
new file mode 100644
index 0000000..dd02f66
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/icdata.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ICDataRepository extends M.ICDataRepository {
+  Future<M.ICData> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.ICData;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/inbound_references.dart b/runtime/observatory_2/lib/src/repositories/inbound_references.dart
new file mode 100644
index 0000000..a9b63e0
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/inbound_references.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class InboundReferencesRepository implements M.InboundReferencesRepository {
+  Future<M.InboundReferences> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response = await isolate
+        .invokeRpc('getInboundReferences', {'targetId': id, 'limit': 100});
+    return new S.InboundReferences(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/instance.dart b/runtime/observatory_2/lib/src/repositories/instance.dart
new file mode 100644
index 0000000..b62b140
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/instance.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class InstanceRepository extends M.InstanceRepository {
+  Future<M.Instance> get(M.IsolateRef i, String id,
+      {int count: S.kDefaultFieldLimit}) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    assert(count != null);
+    return (await isolate.getObject(id, count: count)) as S.Instance;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/isolate.dart b/runtime/observatory_2/lib/src/repositories/isolate.dart
new file mode 100644
index 0000000..68b8ae1
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/isolate.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class IsolateRepository extends M.IsolateRepository {
+  final S.VM _vm;
+
+  Iterable<M.Service> get reloadSourcesServices =>
+      _vm.services.where((S.Service s) => s.service == 'reloadSources');
+
+  IsolateRepository(this._vm) {
+    assert(_vm != null);
+  }
+
+  Future<M.Isolate> get(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    try {
+      await isolate.reload();
+    } on SC.NetworkRpcException catch (_) {
+      /* ignore */
+    }
+    return isolate;
+  }
+
+  Future reloadSources(M.IsolateRef i, {M.Service service}) async {
+    if (service == null) {
+      S.Isolate isolate = i as S.Isolate;
+      assert(isolate != null);
+      await isolate.reloadSources();
+    } else {
+      S.Service srv = service as S.Service;
+      assert(srv != null);
+      await _vm.invokeRpcNoUpgrade(srv.method, {'isolateId': i.id});
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/isolate_group.dart b/runtime/observatory_2/lib/src/repositories/isolate_group.dart
new file mode 100644
index 0000000..fabc9d7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/isolate_group.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class IsolateGroupRepository extends M.IsolateGroupRepository {
+  final S.VM _vm;
+
+  IsolateGroupRepository(this._vm) : assert(_vm != null);
+
+  Future<M.IsolateGroup> get(M.IsolateGroupRef i) async {
+    S.IsolateGroup isolateGroup = i as S.IsolateGroup;
+    assert(isolateGroup != null);
+    try {
+      await isolateGroup.reload();
+    } on SC.NetworkRpcException catch (_) {
+      /* ignore */
+    }
+    return isolateGroup;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/library.dart b/runtime/observatory_2/lib/src/repositories/library.dart
new file mode 100644
index 0000000..74d8b48
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/library.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class LibraryRepository extends M.LibraryRepository {
+  LibraryRepository();
+
+  Future<M.Library> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.Library;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/megamorphiccache.dart b/runtime/observatory_2/lib/src/repositories/megamorphiccache.dart
new file mode 100644
index 0000000..8672e32
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/megamorphiccache.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class MegamorphicCacheRepository extends M.MegamorphicCacheRepository {
+  Future<M.MegamorphicCache> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.MegamorphicCache;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/metric.dart b/runtime/observatory_2/lib/src/repositories/metric.dart
new file mode 100644
index 0000000..2d90187
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/metric.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class Metric implements M.Metric {
+  final String id;
+  String get name => internal.name;
+  String get description => internal.description;
+  final internal;
+
+  Metric(this.id, this.internal);
+}
+
+class MetricSample implements M.MetricSample {
+  final double value;
+  final DateTime time = new DateTime.now();
+  MetricSample(this.value);
+}
+
+class MetricRepository implements M.MetricRepository {
+  final Map<S.Isolate, Map<Metric, List<M.MetricSample>>> _samples =
+      <S.Isolate, Map<Metric, List<M.MetricSample>>>{};
+  final Map<S.Isolate, Map<Metric, int>> _rates =
+      <S.Isolate, Map<Metric, int>>{};
+  final Map<S.Isolate, Map<Metric, int>> _sizes =
+      <S.Isolate, Map<Metric, int>>{};
+  Timer _timer;
+  int count = 0;
+
+  Future<Iterable<Metric>> list(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    if (_samples.containsKey(isolate)) {
+      return _samples[isolate].keys;
+    }
+    return const [];
+  }
+
+  Future startSampling(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    if (!_samples.containsKey(isolate)) {
+      await isolate.refreshMetrics();
+      final samples = _samples[isolate] = <Metric, List<M.MetricSample>>{};
+      final rates = _rates[isolate] = <Metric, int>{};
+      final sizes = _sizes[isolate] = <Metric, int>{};
+      final metrics = []
+        ..addAll(isolate.dartMetrics.keys
+            .map((name) => new Metric(name, isolate.dartMetrics[name]))
+            .toList())
+        ..addAll(isolate.nativeMetrics.keys
+            .map((name) => new Metric(name, isolate.nativeMetrics[name]))
+            .toList());
+      for (final metric in metrics) {
+        samples[metric] = [new MetricSample(metric.internal.value)];
+        rates[metric] = _rateToInteger(M.MetricSamplingRate.off);
+        sizes[metric] = _sizeToInteger(M.MetricBufferSize.n100samples);
+      }
+      if (_samples.length == 1) {
+        count = 0;
+        _timer = new Timer.periodic(new Duration(milliseconds: 100), _update);
+      }
+    }
+  }
+
+  Future stopSampling(M.IsolateRef isolate) async {
+    if (_samples.containsKey(isolate)) {
+      _samples.remove(isolate);
+      _rates.remove(isolate);
+      _sizes.remove(isolate);
+      if (_samples.isEmpty) {
+        _timer.cancel();
+      }
+    }
+  }
+
+  M.MetricSamplingRate getSamplingRate(M.IsolateRef i, M.Metric m) {
+    if (_rates.containsKey(i)) {
+      final metrics = _rates[i];
+      if (metrics.containsKey(m)) {
+        switch (metrics[m]) {
+          case 0:
+            return M.MetricSamplingRate.off;
+          case 1:
+            return M.MetricSamplingRate.e100ms;
+          case 10:
+            return M.MetricSamplingRate.e1s;
+          case 20:
+            return M.MetricSamplingRate.e2s;
+          case 40:
+            return M.MetricSamplingRate.e4s;
+          case 80:
+            return M.MetricSamplingRate.e8s;
+        }
+      }
+    }
+    throw new Exception('Sampling for isolate ${i.id} is not started');
+  }
+
+  void setSamplingRate(M.IsolateRef i, M.Metric m, M.MetricSamplingRate r) {
+    if (_rates.containsKey(i)) {
+      final metrics = _rates[i];
+      if (metrics.containsKey(m)) {
+        metrics[m] = _rateToInteger(r);
+      }
+    } else {
+      throw new Exception('Sampling for isolate ${i.id} is not started');
+    }
+  }
+
+  M.MetricBufferSize getBufferSize(M.IsolateRef i, M.Metric m) {
+    if (_sizes.containsKey(i)) {
+      final metrics = _sizes[i];
+      if (metrics.containsKey(m)) {
+        switch (metrics[m]) {
+          case 10:
+            return M.MetricBufferSize.n10samples;
+          case 100:
+            return M.MetricBufferSize.n100samples;
+          case 1000:
+            return M.MetricBufferSize.n1000samples;
+        }
+      }
+    }
+    throw new Exception('Sampling for isolate ${i.id} is not started');
+  }
+
+  void setBufferSize(M.IsolateRef i, M.Metric m, M.MetricBufferSize s) {
+    if (_sizes.containsKey(i)) {
+      final metrics = _sizes[i];
+      if (metrics.containsKey(m)) {
+        metrics[m] = _sizeToInteger(s);
+      }
+    } else {
+      throw new Exception('Sampling for isolate ${i.id} is not started');
+    }
+  }
+
+  static int _rateToInteger(M.MetricSamplingRate r) {
+    switch (r) {
+      case M.MetricSamplingRate.off:
+        return 0;
+      case M.MetricSamplingRate.e100ms:
+        return 1;
+      case M.MetricSamplingRate.e1s:
+        return 10;
+      case M.MetricSamplingRate.e2s:
+        return 20;
+      case M.MetricSamplingRate.e4s:
+        return 40;
+      case M.MetricSamplingRate.e8s:
+        return 80;
+    }
+    throw new Exception('Unknown MetricSamplingRate ($r)');
+  }
+
+  static int _sizeToInteger(M.MetricBufferSize s) {
+    switch (s) {
+      case M.MetricBufferSize.n10samples:
+        return 10;
+      case M.MetricBufferSize.n100samples:
+        return 100;
+      case M.MetricBufferSize.n1000samples:
+        return 1000;
+    }
+    throw new Exception('Unknown MetricBufferSize ($s)');
+  }
+
+  Iterable<M.MetricSample> getSamples(M.IsolateRef i, M.Metric m) {
+    if (_samples.containsKey(i)) {
+      final metrics = _samples[i];
+      if (metrics.containsKey(m)) {
+        return metrics[m];
+      }
+    }
+    return null;
+  }
+
+  double getMinValue(M.IsolateRef i, M.Metric m) {
+    Metric metric = m as Metric;
+    assert(metric != null);
+    return metric.internal.min;
+  }
+
+  double getMaxValue(M.IsolateRef i, M.Metric m) {
+    Metric metric = m as Metric;
+    assert(metric != null);
+    return metric.internal.max;
+  }
+
+  void _update(_) {
+    for (final isolate in _rates.keys) {
+      final metrics = _rates[isolate];
+      for (final metric in metrics.keys) {
+        final rate = metrics[metric];
+        if (rate != 0 && count % rate == 0) {
+          final size = _sizes[isolate][metric];
+          final samples = _samples[isolate][metric];
+          metric.internal.reload().then((m) {
+            if (samples.length >= size) {
+              samples.removeRange(0, samples.length - size + 1);
+            }
+            samples.add(new MetricSample(m.value));
+          });
+        }
+      }
+    }
+    ++count;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/notification.dart b/runtime/observatory_2/lib/src/repositories/notification.dart
new file mode 100644
index 0000000..19eb99e
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/notification.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class NotificationChangeEvent implements M.NotificationChangeEvent {
+  final NotificationRepository repository;
+  NotificationChangeEvent(this.repository);
+}
+
+class NotificationRepository implements M.NotificationRepository {
+  final List<M.Notification> _list = <M.Notification>[];
+
+  final StreamController<M.NotificationChangeEvent> _onChange =
+      new StreamController<M.NotificationChangeEvent>.broadcast();
+  Stream<M.NotificationChangeEvent> get onChange => _onChange.stream;
+
+  void add(M.Notification notification) {
+    assert(notification != null);
+    _list.add(notification);
+    _notify();
+  }
+
+  Iterable<M.Notification> list() => _list;
+
+  void delete(M.Notification notification) {
+    if (_list.remove(notification)) _notify();
+  }
+
+  void deleteAll() {
+    if (_list.isNotEmpty) {
+      _list.clear();
+      _notify();
+    }
+  }
+
+  NotificationRepository();
+
+  void _notify() {
+    _onChange.add(new NotificationChangeEvent(this));
+  }
+
+  void deleteWhere(bool test(M.Notification element)) {
+    int length = _list.length;
+    _list.removeWhere(test);
+    if (_list.length != length) _notify();
+  }
+
+  void deletePauseEvents({M.Isolate isolate}) {
+    if (isolate == null) {
+      deleteWhere((notification) {
+        return notification is M.EventNotification &&
+            notification.event is M.PauseEvent;
+      });
+    } else {
+      deleteWhere((notification) {
+        if (notification is M.EventNotification) {
+          var event = notification.event;
+          if (event is M.PauseEvent) {
+            return event.isolate == isolate;
+          }
+        }
+        return false;
+      });
+    }
+  }
+
+  void deleteDisconnectEvents() {
+    deleteWhere((notification) {
+      return notification is M.EventNotification &&
+          notification.event is M.ConnectionClosedEvent;
+    });
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/object.dart b/runtime/observatory_2/lib/src/repositories/object.dart
new file mode 100644
index 0000000..aaab258
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/object.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ObjectRepository extends M.ObjectRepository {
+  ObjectRepository();
+  Future<M.Object> get(M.IsolateRef i, String id,
+      {int count: S.kDefaultFieldLimit}) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    assert(count != null);
+    return (await isolate.getObject(id, count: count)) as S.HeapObject;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/objectpool.dart b/runtime/observatory_2/lib/src/repositories/objectpool.dart
new file mode 100644
index 0000000..e626f88
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/objectpool.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ObjectPoolRepository extends M.ObjectPoolRepository {
+  Future<M.ObjectPool> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.ObjectPool;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/objectstore.dart b/runtime/observatory_2/lib/src/repositories/objectstore.dart
new file mode 100644
index 0000000..7456d9a
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/objectstore.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ObjectStoreRepository implements M.ObjectStoreRepository {
+  Future<M.ObjectStore> get(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return isolate.getObjectStore();
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/persistent_handles.dart b/runtime/observatory_2/lib/src/repositories/persistent_handles.dart
new file mode 100644
index 0000000..db94cbc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/persistent_handles.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class PersistentHandlesRepository implements M.PersistentHandlesRepository {
+  Future<M.PersistentHandles> get(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response = await isolate.invokeRpc('_getPersistentHandles', {});
+    return new S.PersistentHandles(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/ports.dart b/runtime/observatory_2/lib/src/repositories/ports.dart
new file mode 100644
index 0000000..324ef74
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/ports.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class PortsRepository implements M.PortsRepository {
+  Future<M.Ports> get(M.IsolateRef i) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response = await isolate.invokeRpc('_getPorts', {});
+    return new S.Ports(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/reachable_size.dart b/runtime/observatory_2/lib/src/repositories/reachable_size.dart
new file mode 100644
index 0000000..d25d359
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/reachable_size.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class ReachableSizeRepository implements M.ReachableSizeRepository {
+  Future<M.Guarded<M.Instance>> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response =
+        await isolate.invokeRpc('_getReachableSize', {'targetId': id});
+    return new S.Guarded<S.Instance>(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/retained_size.dart b/runtime/observatory_2/lib/src/repositories/retained_size.dart
new file mode 100644
index 0000000..6d3cef5
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/retained_size.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class RetainedSizeRepository implements M.RetainedSizeRepository {
+  Future<M.Guarded<M.Instance>> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response =
+        await isolate.invokeRpc('_getRetainedSize', {'targetId': id});
+    return new S.Guarded<S.Instance>(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/retaining_path.dart b/runtime/observatory_2/lib/src/repositories/retaining_path.dart
new file mode 100644
index 0000000..cfe4c38
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/retaining_path.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class RetainingPathRepository implements M.RetainingPathRepository {
+  Future<M.RetainingPath> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    final response = await isolate
+        .invokeRpc('getRetainingPath', {'targetId': id, 'limit': 100});
+    return new S.RetainingPath(response);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/sample_profile.dart b/runtime/observatory_2/lib/src/repositories/sample_profile.dart
new file mode 100644
index 0000000..944eaba
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/sample_profile.dart
@@ -0,0 +1,174 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class SampleProfileLoadingProgressEvent
+    implements M.SampleProfileLoadingProgressEvent {
+  final SampleProfileLoadingProgress progress;
+  SampleProfileLoadingProgressEvent(this.progress);
+}
+
+class SampleProfileLoadingProgress extends M.SampleProfileLoadingProgress {
+  StreamController<SampleProfileLoadingProgressEvent> _onProgress =
+      StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+  Stream<SampleProfileLoadingProgressEvent> get onProgress =>
+      _onProgress.stream;
+
+  final S.ServiceObjectOwner owner;
+  final S.Class cls;
+  final M.SampleProfileTag tag;
+  final bool clear;
+  final M.SampleProfileType type;
+
+  M.SampleProfileLoadingStatus _status = M.SampleProfileLoadingStatus.fetching;
+  double _progress = 0.0;
+  final _fetchingTime = Stopwatch();
+  final _loadingTime = Stopwatch();
+  SampleProfile _profile;
+
+  M.SampleProfileLoadingStatus get status => _status;
+  double get progress => _progress;
+  Duration get fetchingTime => _fetchingTime.elapsed;
+  Duration get loadingTime => _loadingTime.elapsed;
+  SampleProfile get profile => _profile;
+
+  SampleProfileLoadingProgress(this.owner, this.tag, this.clear,
+      {this.type: M.SampleProfileType.cpu, this.cls}) {
+    _run();
+  }
+
+  Future _run() async {
+    _fetchingTime.start();
+    try {
+      if (clear && (type == M.SampleProfileType.cpu)) {
+        await owner.invokeRpc('clearCpuSamples', {});
+      }
+
+      var response;
+      if (type == M.SampleProfileType.cpu) {
+        response = cls != null
+            ? await cls.getAllocationSamples()
+            : await owner.invokeRpc('getCpuSamples', {'_code': true});
+      } else if (type == M.SampleProfileType.memory) {
+        assert(owner is M.VM);
+        response = await owner
+            .invokeRpc('_getNativeAllocationSamples', {'_code': true});
+      } else {
+        throw Exception('Unknown M.SampleProfileType: $type');
+      }
+
+      _fetchingTime.stop();
+      _loadingTime.start();
+      _status = M.SampleProfileLoadingStatus.loading;
+      _triggerOnProgress();
+
+      SampleProfile profile = SampleProfile();
+      Stream<double> progress = profile.loadProgress(owner, response);
+      progress.listen((value) {
+        _progress = value;
+        _triggerOnProgress();
+      });
+
+      await progress.drain();
+
+      profile.tagOrder = tag;
+      profile.buildFunctionCallerAndCallees();
+      _profile = profile;
+
+      _loadingTime.stop();
+      _status = M.SampleProfileLoadingStatus.loaded;
+      _triggerOnProgress();
+    } catch (e) {
+      if (e is S.ServerRpcException) {
+        if (e.code == S.ServerRpcException.kFeatureDisabled) {
+          _status = M.SampleProfileLoadingStatus.disabled;
+          _triggerOnProgress();
+        }
+      }
+      rethrow;
+    } finally {
+      _onProgress.close();
+    }
+  }
+
+  void _triggerOnProgress() {
+    _onProgress.add(SampleProfileLoadingProgressEvent(this));
+  }
+
+  void reuse(M.SampleProfileTag t) {
+    _profile.tagOrder = t;
+    final onProgress =
+        StreamController<SampleProfileLoadingProgressEvent>.broadcast();
+    Timer.run(() {
+      onProgress.add(SampleProfileLoadingProgressEvent(this));
+      onProgress.close();
+    });
+    _onProgress = onProgress;
+  }
+}
+
+class IsolateSampleProfileRepository
+    implements M.IsolateSampleProfileRepository {
+  SampleProfileLoadingProgress _last;
+
+  Stream<SampleProfileLoadingProgressEvent> get(
+      M.IsolateRef i, M.SampleProfileTag t,
+      {bool clear: false, bool forceFetch: false}) {
+    assert(clear != null);
+    assert(forceFetch != null);
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    if ((_last != null) && !clear && !forceFetch && (_last.owner == isolate)) {
+      _last.reuse(t);
+    } else {
+      _last = SampleProfileLoadingProgress(isolate, t, clear);
+    }
+    return _last.onProgress;
+  }
+}
+
+class ClassSampleProfileRepository implements M.ClassSampleProfileRepository {
+  Stream<SampleProfileLoadingProgressEvent> get(
+      covariant M.Isolate i, M.ClassRef c, M.SampleProfileTag t,
+      {bool clear: false, bool forceFetch: false}) {
+    S.Isolate isolate = i as S.Isolate;
+    S.Class cls = c as S.Class;
+    assert(isolate != null);
+    assert(cls != null);
+    return SampleProfileLoadingProgress(isolate, t, false, cls: cls).onProgress;
+  }
+
+  Future enable(M.IsolateRef i, M.ClassRef c) {
+    S.Class cls = c as S.Class;
+    assert(cls != null);
+    return cls.setTraceAllocations(true);
+  }
+
+  Future disable(M.IsolateRef i, M.ClassRef c) {
+    S.Class cls = c as S.Class;
+    assert(cls != null);
+    return cls.setTraceAllocations(false);
+  }
+}
+
+class NativeMemorySampleProfileRepository
+    implements M.NativeMemorySampleProfileRepository {
+  SampleProfileLoadingProgress _last;
+
+  Stream<SampleProfileLoadingProgressEvent> get(M.VM vm, M.SampleProfileTag t,
+      {bool forceFetch: false, bool clear: false}) {
+    assert(forceFetch != null);
+    S.VM owner = vm as S.VM;
+    assert(owner != null);
+
+    if ((_last != null) && (_last.profile != null) && !forceFetch) {
+      _last.reuse(t);
+    } else {
+      _last = SampleProfileLoadingProgress(owner, t, false,
+          type: M.SampleProfileType.memory);
+    }
+    return _last.onProgress;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/script.dart b/runtime/observatory_2/lib/src/repositories/script.dart
new file mode 100644
index 0000000..e0fea2d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/script.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class ScriptRepository implements M.ScriptRepository {
+  Future<M.Script> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(i != null);
+    assert(id != null);
+    return (await isolate.getObject(id)) as M.Script;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/settings.dart b/runtime/observatory_2/lib/src/repositories/settings.dart
new file mode 100644
index 0000000..5cfffc0
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/settings.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+/// Static settings database.
+class _Settings {
+  static Storage _storage = window.localStorage;
+
+  /// Associated [value] with [key]. [value] must be JSON encodable.
+  static void set(String key, dynamic value) {
+    _storage[key] = json.encode(value);
+  }
+
+  /// Get value associated with [key]. Return value will be a JSON encodable
+  /// object.
+  static dynamic get(String key) {
+    var value = _storage[key];
+    if (value == null) {
+      return null;
+    }
+    return json.decode(value);
+  }
+}
+
+/// A group of settings each prefixed with group name and a dot.
+class SettingsRepository {
+  /// Group name
+  final String group;
+
+  SettingsRepository(this.group);
+
+  String _fullKey(String key) => '$group.$key';
+
+  void set(String key, dynamic value) {
+    var fullKey = _fullKey(key);
+    _Settings.set(fullKey, value);
+  }
+
+  dynamic get(String key) {
+    var fullKey = _fullKey(key);
+    return _Settings.get(fullKey);
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/single_target_cache.dart b/runtime/observatory_2/lib/src/repositories/single_target_cache.dart
new file mode 100644
index 0000000..745a062
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/single_target_cache.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class SingleTargetCacheRepository extends M.SingleTargetCacheRepository {
+  Future<M.SingleTargetCache> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.SingleTargetCache;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart b/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart
new file mode 100644
index 0000000..a015928
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class StronglyReachableInstancesRepository
+    implements M.StronglyReachableInstancesRepository {
+  Future<M.InstanceSet> get(M.IsolateRef i, M.ClassRef c,
+      {int limit: 100}) async {
+    S.Isolate isolate = i as S.Isolate;
+    S.Class cls = c as S.Class;
+    assert(isolate != null);
+    assert(cls != null);
+    assert(limit != null);
+    return (await isolate.getInstances(cls, limit)) as S.InstanceSet;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/subtype_test_cache.dart b/runtime/observatory_2/lib/src/repositories/subtype_test_cache.dart
new file mode 100644
index 0000000..a5fd708
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/subtype_test_cache.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class SubtypeTestCacheRepository extends M.SubtypeTestCacheRepository {
+  Future<M.SubtypeTestCache> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.SubtypeTestCache;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/target.dart b/runtime/observatory_2/lib/src/repositories/target.dart
new file mode 100644
index 0000000..4fb1fb1
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/target.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+typedef bool IsConnectedVMTargetDelegate(M.Target target);
+
+class TargetChangeEvent implements M.TargetChangeEvent {
+  final TargetRepository repository;
+  final bool disconnected;
+  TargetChangeEvent(this.repository, [this.disconnected = false]);
+}
+
+class TargetRepository implements M.TargetRepository {
+  static const _historyKey = 'history';
+
+  final StreamController<TargetChangeEvent> _onChange;
+  final Stream<TargetChangeEvent> onChange;
+  final SettingsRepository _settings = new SettingsRepository('targetManager');
+
+  final List<SC.WebSocketVMTarget> _list = <SC.WebSocketVMTarget>[];
+  SC.WebSocketVMTarget current;
+  final IsConnectedVMTargetDelegate _isConnectedVMTarget;
+
+  factory TargetRepository(IsConnectedVMTargetDelegate isConnectedVMTarget) {
+    var controller = new StreamController<TargetChangeEvent>();
+    var stream = controller.stream.asBroadcastStream();
+    return new TargetRepository._(isConnectedVMTarget, controller, stream);
+  }
+
+  TargetRepository._(this._isConnectedVMTarget, this._onChange, this.onChange) {
+    _restore();
+    final defaultAddress = _networkAddressOfDefaultTarget();
+    var defaultTarget = find(defaultAddress);
+    // Add the default address if it doesn't already exist.
+    if (defaultTarget == null) {
+      defaultTarget = new SC.WebSocketVMTarget(defaultAddress);
+      _list.insert(0, defaultTarget);
+    }
+    // Set the current target to the default target.
+    current = defaultTarget;
+  }
+
+  void add(String address) {
+    if (find(address) != null) {
+      return;
+    }
+    _list.insert(0, new SC.WebSocketVMTarget(address));
+    _onChange.add(new TargetChangeEvent(this));
+    _store();
+  }
+
+  Iterable<M.Target> list() => _list.toList();
+
+  void setCurrent(M.Target t) {
+    SC.WebSocketVMTarget target = t as SC.WebSocketVMTarget;
+    if (!_list.contains(target)) {
+      return;
+    }
+    current = target;
+    current.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch;
+    _onChange.add(new TargetChangeEvent(this));
+    _store();
+  }
+
+  void emitDisconnectEvent() {
+    _onChange.add(new TargetChangeEvent(this, true));
+  }
+
+  void delete(o) {
+    if (_list.remove(o)) {
+      if (o == current) {
+        current = null;
+      }
+      _onChange.add(new TargetChangeEvent(this));
+      _store();
+    }
+  }
+
+  /// Read settings from data store.
+  void _restore() {
+    _list.clear();
+    var loaded = _settings.get(_historyKey);
+    if (loaded == null) {
+      return;
+    }
+    for (var i in loaded) {
+      _list.add(new SC.WebSocketVMTarget.fromMap(i));
+    }
+    _list.sort((SC.WebSocketVMTarget a, SC.WebSocketVMTarget b) {
+      return b.lastConnectionTime.compareTo(a.lastConnectionTime);
+    });
+  }
+
+  /// After making a change, update settings.
+  void _store() {
+    _settings.set(_historyKey, _list);
+  }
+
+  /// Find by networkAddress.
+  SC.WebSocketVMTarget find(String networkAddress) {
+    for (SC.WebSocketVMTarget item in _list) {
+      if (item.networkAddress == networkAddress) {
+        return item;
+      }
+    }
+    return null;
+  }
+
+  static String _networkAddressOfDefaultTarget() {
+    // It is possible to override the default port and host by adding extra
+    // query parameters:
+    // http://localhost:8080?override-port=8181
+    // http://localhost:8080?override-port=8181&override-host=10.0.0.2
+    final Uri serverAddress = Uri.parse(window.location.toString());
+    final String port = serverAddress.queryParameters['override-port'];
+    final String host = serverAddress.queryParameters['override-host'];
+    final Uri wsAddress = new Uri(
+      scheme: 'ws',
+      host: host ?? serverAddress.host,
+      port: int.tryParse(port ?? '') ?? serverAddress.port,
+      path: serverAddress.path.isEmpty ? '/ws' : serverAddress.path + 'ws',
+    );
+    return wsAddress.toString();
+  }
+
+  bool isConnectedVMTarget(M.Target target) => _isConnectedVMTarget(target);
+}
diff --git a/runtime/observatory_2/lib/src/repositories/timeline.dart b/runtime/observatory_2/lib/src/repositories/timeline.dart
new file mode 100644
index 0000000..7c0e4a7
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/timeline.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class TimelineRepository extends TimelineRepositoryBase
+    implements M.TimelineRepository {
+  static const _kStackFrames = 'stackFrames';
+  static const _kTraceEvents = 'traceEvents';
+
+  Future<M.TimelineFlags> getFlags(M.VMRef ref) async {
+    S.VM vm = ref as S.VM;
+    S.ServiceMap response = await vm.invokeRpc('getVMTimelineFlags', {});
+    return new S.TimelineFlags(response);
+  }
+
+  Future setRecordedStreams(M.VMRef ref, Iterable<M.TimelineStream> streams) {
+    S.VM vm = ref as S.VM;
+    assert(vm != null);
+    return vm.invokeRpc('setVMTimelineFlags', {
+      'recordedStreams': '[${streams.map((s) => s.name).join(', ')}]',
+    });
+  }
+
+  Future clear(M.VMRef ref) {
+    S.VM vm = ref as S.VM;
+    return vm.invokeRpc('clearVMTimeline', {});
+  }
+
+  Future<void> _formatSamples(
+      M.Isolate isolate, Map traceObject, S.ServiceMap cpuSamples) async {
+    const kRootFrameId = 0;
+    final profile = SampleProfile();
+    await profile.load(isolate as S.ServiceObjectOwner, cpuSamples);
+    final trie = profile.loadFunctionTree(M.ProfileTreeDirection.inclusive);
+    final root = trie.root;
+    int nextId = kRootFrameId;
+    processFrame(FunctionCallTreeNode current, FunctionCallTreeNode parent) {
+      int id = nextId;
+      ++nextId;
+      current.frameId = id;
+      // Skip the root.
+      if (id != kRootFrameId) {
+        final function = current.profileFunction.function;
+        final key = '${isolate.id}-$id';
+        traceObject[_kStackFrames][key] = {
+          'category': 'Dart',
+          'name': function.qualifiedName,
+          'resolvedUrl': current.profileFunction.resolvedUrl,
+          if (parent != null && parent.frameId != kRootFrameId)
+            'parent': '${isolate.id}-${parent.frameId}',
+        };
+      }
+
+      for (final child in current.children) {
+        processFrame(child, current);
+      }
+    }
+
+    processFrame(root, null);
+
+    for (final sample in profile.samples) {
+      FunctionCallTreeNode trie = sample[SampleProfile.kTimelineFunctionTrie];
+
+      if (trie.frameId != kRootFrameId) {
+        traceObject[_kTraceEvents].add({
+          'ph': 'P', // kind = sample event
+          'name': '', // Blank to keep about:tracing happy
+          'pid': profile.pid,
+          'tid': sample['tid'],
+          'ts': sample['timestamp'],
+          'cat': 'Dart',
+          'sf': '${isolate.id}-${trie.frameId}',
+        });
+      }
+    }
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/timeline_base.dart b/runtime/observatory_2/lib/src/repositories/timeline_base.dart
new file mode 100644
index 0000000..43a7e29
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/timeline_base.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+import 'dart:async';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service.dart' as S;
+
+class TimelineRepositoryBase {
+  static const _kStackFrames = 'stackFrames';
+  static const _kTraceEvents = 'traceEvents';
+  static const kTimeOriginMicros = 'timeOriginMicros';
+  static const kTimeExtentMicros = 'timeExtentMicros';
+
+  Future<void> _formatSamples(M.Isolate isolate, Map traceObject,
+      Future<S.ServiceObject> cpuSamples) async {
+    const kRootFrameId = 0;
+    final profile = SampleProfile();
+    await profile.load(isolate as S.ServiceObjectOwner, await cpuSamples);
+    final trie = profile.loadFunctionTree(M.ProfileTreeDirection.inclusive);
+    final root = trie.root;
+    int nextId = kRootFrameId;
+    processFrame(FunctionCallTreeNode current, FunctionCallTreeNode parent) {
+      int id = nextId;
+      ++nextId;
+      current.frameId = id;
+      // Skip the root.
+      if (id != kRootFrameId) {
+        final function = current.profileFunction.function;
+        final key = '${isolate.id}-$id';
+        traceObject[_kStackFrames][key] = {
+          'category': 'Dart',
+          'name': function.qualifiedName,
+          'resolvedUrl': current.profileFunction.resolvedUrl,
+          if (parent != null && parent.frameId != kRootFrameId)
+            'parent': '${isolate.id}-${parent.frameId}',
+        };
+      }
+
+      for (final child in current.children) {
+        processFrame(child, current);
+      }
+    }
+
+    processFrame(root, null);
+
+    for (final sample in profile.samples) {
+      FunctionCallTreeNode trie = sample[SampleProfile.kTimelineFunctionTrie];
+
+      if (trie.frameId != kRootFrameId) {
+        traceObject[_kTraceEvents].add({
+          'ph': 'P', // kind = sample event
+          'name': '', // Blank to keep about:tracing happy
+          'pid': profile.pid,
+          'tid': sample['tid'],
+          'ts': sample['timestamp'],
+          'cat': 'Dart',
+          'sf': '${isolate.id}-${trie.frameId}',
+        });
+      }
+    }
+  }
+
+  Future<Map> getCpuProfileTimeline(M.VMRef ref,
+      {int timeOriginMicros, int timeExtentMicros}) async {
+    final S.VM vm = ref as S.VM;
+    final traceObject = <String, dynamic>{
+      _kStackFrames: {},
+      _kTraceEvents: [],
+    };
+
+    await Future.wait(vm.isolates.map((isolate) {
+      final samples = vm.invokeRpc('getCpuSamples', {
+        'isolateId': isolate.id,
+        if (timeOriginMicros != null) kTimeOriginMicros: timeOriginMicros,
+        if (timeExtentMicros != null) kTimeExtentMicros: timeExtentMicros,
+      });
+      return _formatSamples(isolate, traceObject, samples);
+    }));
+
+    return traceObject;
+  }
+
+  Future<Map> getTimeline(M.VMRef ref) async {
+    final S.VM vm = ref as S.VM;
+    final S.ServiceMap vmTimelineResponse =
+        await vm.invokeRpc('getVMTimeline', {});
+    final timeOriginMicros = vmTimelineResponse[kTimeOriginMicros];
+    final timeExtentMicros = vmTimelineResponse[kTimeExtentMicros];
+    var traceObject = <String, dynamic>{
+      _kStackFrames: {},
+      _kTraceEvents: [],
+    };
+    try {
+      final cpuProfile = await getCpuProfileTimeline(
+        vm,
+        timeOriginMicros: timeOriginMicros,
+        timeExtentMicros: timeExtentMicros,
+      );
+      traceObject = cpuProfile;
+    } on S.ServerRpcException catch (e) {
+      if (e.code != S.ServerRpcException.kFeatureDisabled) {
+        rethrow;
+      }
+      Logger.root.info(
+          "CPU profiler is disabled. Creating timeline without CPU profile.");
+    }
+    traceObject[_kTraceEvents].addAll(vmTimelineResponse[_kTraceEvents]);
+    return traceObject;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/type_arguments.dart b/runtime/observatory_2/lib/src/repositories/type_arguments.dart
new file mode 100644
index 0000000..c84f548
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/type_arguments.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class TypeArgumentsRepository implements M.TypeArgumentsRepository {
+  Future<M.TypeArguments> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(i != null);
+    assert(id != null);
+    return (await isolate.getObject(id)) as M.TypeArguments;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/unlinked_call.dart b/runtime/observatory_2/lib/src/repositories/unlinked_call.dart
new file mode 100644
index 0000000..6f2119c
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/unlinked_call.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+part of repositories;
+
+class UnlinkedCallRepository extends M.UnlinkedCallRepository {
+  Future<M.UnlinkedCall> get(M.IsolateRef i, String id) async {
+    S.Isolate isolate = i as S.Isolate;
+    assert(isolate != null);
+    return (await isolate.getObject(id)) as S.UnlinkedCall;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/repositories/vm.dart b/runtime/observatory_2/lib/src/repositories/vm.dart
new file mode 100644
index 0000000..514e374
--- /dev/null
+++ b/runtime/observatory_2/lib/src/repositories/vm.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of repositories;
+
+class VMRepository implements M.VMRepository {
+  Future<M.VM> get(M.VMRef ref) async {
+    S.VM vm = ref as S.VM;
+    assert(vm != null);
+    await vm.reload();
+    return vm;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/sample_profile/sample_profile.dart b/runtime/observatory_2/lib/src/sample_profile/sample_profile.dart
new file mode 100644
index 0000000..48667cc
--- /dev/null
+++ b/runtime/observatory_2/lib/src/sample_profile/sample_profile.dart
@@ -0,0 +1,1255 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of sample_profiler;
+
+abstract class CallTreeNode<NodeT extends M.CallTreeNode>
+    implements M.CallTreeNode {
+  final List<NodeT> children;
+  int get count => _count;
+  int _count = 0;
+  int inclusiveNativeAllocations = 0;
+  int exclusiveNativeAllocations = 0;
+  double get percentage => _percentage;
+  double _percentage = 0.0;
+  final attributes = <String>{};
+
+  // Used for building timeline
+  int frameId = null;
+  int parentId = null;
+
+  // Either a ProfileCode or a ProfileFunction.
+  Object get profileData;
+  String get name;
+
+  CallTreeNode(this.children,
+      [this._count = 0,
+      this.inclusiveNativeAllocations = 0,
+      this.exclusiveNativeAllocations = 0]) {}
+
+  NodeT getChild(int index);
+
+  void sortChildren() {
+    children.sort((a, b) => b.count - a.count);
+    children.forEach((NodeT child) => child.sortChildren());
+  }
+
+  void tick(Map sample, {bool exclusive = false}) {
+    ++_count;
+    if (SampleProfile._isNativeAllocationSample(sample)) {
+      final allocationSize = sample[SampleProfile._kNativeAllocationSizeBytes];
+      if (exclusive) {
+        exclusiveNativeAllocations += allocationSize;
+      }
+      inclusiveNativeAllocations += allocationSize;
+    }
+  }
+}
+
+class CodeCallTreeNode extends CallTreeNode<CodeCallTreeNode>
+    implements M.CodeCallTreeNode {
+  final ProfileCode profileCode;
+  final SampleProfile profile;
+
+  Object get profileData => profileCode;
+
+  String get name => profileCode.code.name;
+
+  final attributes = <String>{};
+  CodeCallTreeNode(this.profileCode, int count, int inclusiveNativeAllocations,
+      int exclusiveNativeAllocations)
+      : profile = profileCode.profile,
+        super(<CodeCallTreeNode>[], count, inclusiveNativeAllocations,
+            exclusiveNativeAllocations) {
+    attributes.addAll(profileCode.attributes);
+  }
+
+  CodeCallTreeNode.fromIndex(this.profile, int tableIndex)
+      : profileCode = profile.codes[tableIndex],
+        super(<CodeCallTreeNode>[]);
+
+  CodeCallTreeNode getChild(int codeTableIndex) {
+    final length = children.length;
+    int i = 0;
+    while (i < length) {
+      final child = children[i];
+      final childTableIndex = child.profileCode.tableIndex;
+      if (childTableIndex == codeTableIndex) {
+        return child;
+      }
+      if (childTableIndex > codeTableIndex) {
+        break;
+      }
+      ++i;
+    }
+    final child = CodeCallTreeNode.fromIndex(profile, codeTableIndex);
+    if (i < length) {
+      children.insert(i, child);
+    } else {
+      children.add(child);
+    }
+    return child;
+  }
+}
+
+class CallTree<NodeT extends CallTreeNode> {
+  final bool inclusive;
+  final NodeT root;
+
+  CallTree(this.inclusive, this.root);
+}
+
+class CodeCallTree extends CallTree<CodeCallTreeNode>
+    implements M.CodeCallTree {
+  CodeCallTree(bool inclusive, CodeCallTreeNode root) : super(inclusive, root) {
+    if ((root.inclusiveNativeAllocations != null) &&
+        (root.inclusiveNativeAllocations != 0)) {
+      _setCodeMemoryPercentage(null, root);
+    } else {
+      _setCodePercentage(null, root);
+    }
+  }
+
+  CodeCallTree filtered(CallTreeNodeFilter filter) {
+    final treeFilter = _FilteredCodeCallTreeBuilder(filter, this);
+    treeFilter.build();
+    if ((treeFilter.filtered.root.inclusiveNativeAllocations != null) &&
+        (treeFilter.filtered.root.inclusiveNativeAllocations != 0)) {
+      _setCodeMemoryPercentage(null, treeFilter.filtered.root);
+    } else {
+      _setCodePercentage(null, treeFilter.filtered.root);
+    }
+    return treeFilter.filtered;
+  }
+
+  _setCodePercentage(CodeCallTreeNode parent, CodeCallTreeNode node) {
+    assert(node != null);
+    var parentPercentage = 1.0;
+    var parentCount = node.count;
+    if (parent != null) {
+      parentPercentage = parent._percentage;
+      parentCount = parent.count;
+    }
+    if (inclusive) {
+      node._percentage = parentPercentage * (node.count / parentCount);
+    } else {
+      node._percentage = (node.count / parentCount);
+    }
+    for (var child in node.children) {
+      _setCodePercentage(node, child);
+    }
+  }
+
+  _setCodeMemoryPercentage(CodeCallTreeNode parent, CodeCallTreeNode node) {
+    assert(node != null);
+    var parentPercentage = 1.0;
+    var parentMemory = node.inclusiveNativeAllocations;
+    if (parent != null) {
+      parentPercentage = parent._percentage;
+      parentMemory = parent.inclusiveNativeAllocations;
+    }
+    if (inclusive) {
+      node._percentage =
+          parentPercentage * (node.inclusiveNativeAllocations / parentMemory);
+    } else {
+      node._percentage = (node.inclusiveNativeAllocations / parentMemory);
+    }
+    for (var child in node.children) {
+      _setCodeMemoryPercentage(node, child);
+    }
+    node.children.sort((a, b) {
+      return b.inclusiveNativeAllocations - a.inclusiveNativeAllocations;
+    });
+  }
+
+  _recordCallerAndCalleesInner(
+      CodeCallTreeNode caller, CodeCallTreeNode callee) {
+    if (caller != null) {
+      caller.profileCode._recordCallee(callee.profileCode, callee.count);
+      callee.profileCode._recordCaller(caller.profileCode, caller.count);
+    }
+
+    for (var child in callee.children) {
+      _recordCallerAndCalleesInner(callee, child);
+    }
+  }
+
+  _recordCallerAndCallees() {
+    for (var child in root.children) {
+      _recordCallerAndCalleesInner(null, child);
+    }
+  }
+}
+
+class FunctionCallTreeNodeCode {
+  final ProfileCode code;
+  final int ticks;
+  FunctionCallTreeNodeCode(this.code, this.ticks);
+}
+
+class FunctionCallTreeNode extends CallTreeNode<FunctionCallTreeNode>
+    implements M.FunctionCallTreeNode {
+  final ProfileFunction profileFunction;
+  final SampleProfile profile;
+  final codes = <FunctionCallTreeNodeCode>[];
+  int _totalCodeTicks = 0;
+  int get totalCodesTicks => _totalCodeTicks;
+
+  String get name => M.getFunctionFullName(profileFunction.function);
+  Object get profileData => profileFunction;
+
+  FunctionCallTreeNode(this.profileFunction, int count,
+      inclusiveNativeAllocations, exclusiveNativeAllocations)
+      : profile = profileFunction.profile,
+        super(<FunctionCallTreeNode>[], count, inclusiveNativeAllocations,
+            exclusiveNativeAllocations) {
+    profileFunction._addKindBasedAttributes(attributes);
+  }
+
+  FunctionCallTreeNode.fromIndex(this.profile, int tableIndex)
+      : profileFunction = profile.functions[tableIndex],
+        super(<FunctionCallTreeNode>[]);
+
+  FunctionCallTreeNode getChild(int functionTableIndex) {
+    final length = children.length;
+    int i = 0;
+    while (i < length) {
+      final child = children[i];
+      final childTableIndex = child.profileFunction.tableIndex;
+      if (childTableIndex == functionTableIndex) {
+        return child;
+      }
+      if (childTableIndex > functionTableIndex) {
+        break;
+      }
+      ++i;
+    }
+    final child = FunctionCallTreeNode.fromIndex(profile, functionTableIndex);
+    if (i < length) {
+      children.insert(i, child);
+    } else {
+      children.add(child);
+    }
+    return child;
+  }
+}
+
+/// Predicate filter function. Returns true if path from root to [node] and all
+/// of [node]'s children should be added to the filtered tree.
+typedef CallTreeNodeFilter = bool Function(CallTreeNode node);
+
+/// Build a filter version of a FunctionCallTree.
+abstract class _FilteredCallTreeBuilder<NodeT extends CallTreeNode> {
+  /// The filter.
+  final CallTreeNodeFilter filter;
+
+  /// The unfiltered tree.
+  final CallTree _unfilteredTree;
+
+  /// The filtered tree (construct by [build]).
+  final CallTree filtered;
+  final List _currentPath = [];
+
+  /// Construct a filtered tree builder using [filter] and [tree].
+  _FilteredCallTreeBuilder(this.filter, CallTree tree, this.filtered)
+      : _unfilteredTree = tree;
+
+  /// Build the filtered tree.
+  build() {
+    assert(filtered != null);
+    assert(filter != null);
+    assert(_unfilteredTree != null);
+    _descend(_unfilteredTree.root);
+  }
+
+  CallTreeNode _findInChildren(CallTreeNode current, CallTreeNode needle) {
+    for (var child in current.children) {
+      if ((child as CallTreeNode).profileData == needle.profileData) {
+        return child;
+      }
+    }
+    return null;
+  }
+
+  NodeT _copyNode(NodeT node);
+
+  /// Add all nodes in [_currentPath].
+  FunctionCallTreeNode _addCurrentPath() {
+    FunctionCallTreeNode current = filtered.root;
+    // Tree root is always the first element of the current path.
+    assert(_unfilteredTree.root == _currentPath[0]);
+    // Assert that unfiltered tree's root and filtered tree's root are different.
+    assert(_unfilteredTree.root != current);
+    for (var i = 1; i < _currentPath.length; i++) {
+      // toAdd is from the unfiltered tree.
+      var toAdd = _currentPath[i];
+      // See if we already have a node for toAdd in the filtered tree.
+      var child = _findInChildren(current, toAdd);
+      if (child == null) {
+        // New node.
+        child = _copyNode(toAdd);
+        current.children.add(child);
+      }
+      current = child;
+    }
+    return current;
+  }
+
+  /// Starting at [current] append [next] and all of [next]'s sub-trees
+  _appendTree(CallTreeNode current, CallTreeNode next) {
+    if (next == null) {
+      return;
+    }
+    var child = _findInChildren(current, next);
+    if (child == null) {
+      child = _copyNode(next);
+      current.children.add(child);
+    }
+    current = child;
+    for (var nextChild in next.children) {
+      _appendTree(current, nextChild);
+    }
+  }
+
+  /// Add path from root to [child], [child], and all of [child]'s sub-trees
+  /// to filtered tree.
+  _addTree(CallTreeNode child) {
+    var current = _addCurrentPath();
+    _appendTree(current, child);
+  }
+
+  /// Descend further into the tree. [current] is from the unfiltered tree.
+  _descend(CallTreeNode current) {
+    if (current == null) {
+      return;
+    }
+    _currentPath.add(current);
+
+    if (filter(current)) {
+      // Filter matched.
+      if (current.children.length == 0) {
+        // Have no children. Add this path.
+        _addTree(null);
+      } else {
+        // Add all child trees.
+        for (var child in current.children) {
+          _addTree(child);
+        }
+      }
+    } else {
+      // Did not match, descend to each child.
+      for (var child in current.children) {
+        _descend(child);
+      }
+    }
+
+    var last = _currentPath.removeLast();
+    assert(current == last);
+  }
+}
+
+class _FilteredFunctionCallTreeBuilder
+    extends _FilteredCallTreeBuilder<FunctionCallTreeNode> {
+  _FilteredFunctionCallTreeBuilder(
+      CallTreeNodeFilter filter, FunctionCallTree tree)
+      : super(
+            filter,
+            tree,
+            FunctionCallTree(
+                tree.inclusive,
+                FunctionCallTreeNode(
+                    tree.root.profileData,
+                    tree.root.count,
+                    tree.root.inclusiveNativeAllocations,
+                    tree.root.exclusiveNativeAllocations)));
+
+  _copyNode(FunctionCallTreeNode node) {
+    return FunctionCallTreeNode(node.profileData, node.count,
+        node.inclusiveNativeAllocations, node.exclusiveNativeAllocations);
+  }
+}
+
+class _FilteredCodeCallTreeBuilder
+    extends _FilteredCallTreeBuilder<CodeCallTreeNode> {
+  _FilteredCodeCallTreeBuilder(CallTreeNodeFilter filter, CodeCallTree tree)
+      : super(
+            filter,
+            tree,
+            CodeCallTree(
+                tree.inclusive,
+                CodeCallTreeNode(
+                    tree.root.profileData,
+                    tree.root.count,
+                    tree.root.inclusiveNativeAllocations,
+                    tree.root.exclusiveNativeAllocations)));
+
+  _copyNode(CodeCallTreeNode node) {
+    return CodeCallTreeNode(node.profileData, node.count,
+        node.inclusiveNativeAllocations, node.exclusiveNativeAllocations);
+  }
+}
+
+class FunctionCallTree extends CallTree<FunctionCallTreeNode>
+    implements M.FunctionCallTree {
+  FunctionCallTree(bool inclusive, FunctionCallTreeNode root)
+      : super(inclusive, root) {
+    if ((root.inclusiveNativeAllocations != null) &&
+        (root.inclusiveNativeAllocations != 0)) {
+      _setFunctionMemoryPercentage(null, root);
+    } else {
+      _setFunctionPercentage(null, root);
+    }
+  }
+
+  FunctionCallTree filtered(CallTreeNodeFilter filter) {
+    final treeFilter = _FilteredFunctionCallTreeBuilder(filter, this);
+    treeFilter.build();
+    if ((treeFilter.filtered.root.inclusiveNativeAllocations != null) &&
+        (treeFilter.filtered.root.inclusiveNativeAllocations != 0)) {
+      _setFunctionMemoryPercentage(null, treeFilter.filtered.root);
+    } else {
+      _setFunctionPercentage(null, treeFilter.filtered.root);
+    }
+    return treeFilter.filtered;
+  }
+
+  void _setFunctionPercentage(
+      FunctionCallTreeNode parent, FunctionCallTreeNode node) {
+    assert(node != null);
+    var parentPercentage = 1.0;
+    var parentCount = node.count;
+    if (parent != null) {
+      parentPercentage = parent._percentage;
+      parentCount = parent.count;
+    }
+    if (inclusive) {
+      node._percentage = parentPercentage * (node.count / parentCount);
+    } else {
+      node._percentage = (node.count / parentCount);
+    }
+    for (var child in node.children) {
+      _setFunctionPercentage(node, child);
+    }
+  }
+
+  void _setFunctionMemoryPercentage(
+      FunctionCallTreeNode parent, FunctionCallTreeNode node) {
+    assert(node != null);
+    var parentPercentage = 1.0;
+    var parentMemory = node.inclusiveNativeAllocations;
+    if (parent != null) {
+      parentPercentage = parent._percentage;
+      parentMemory = parent.inclusiveNativeAllocations;
+    }
+    if (inclusive) {
+      node._percentage =
+          parentPercentage * (node.inclusiveNativeAllocations / parentMemory);
+    } else {
+      node._percentage = (node.inclusiveNativeAllocations / parentMemory);
+    }
+    for (var child in node.children) {
+      _setFunctionMemoryPercentage(node, child);
+    }
+    node.children.sort((a, b) {
+      return b.inclusiveNativeAllocations - a.inclusiveNativeAllocations;
+    });
+  }
+
+  _markFunctionCallsInner(
+      FunctionCallTreeNode caller, FunctionCallTreeNode callee) {
+    if (caller != null) {
+      caller.profileFunction
+          ._recordCallee(callee.profileFunction, callee.count);
+      callee.profileFunction
+          ._recordCaller(caller.profileFunction, caller.count);
+    }
+    for (var child in callee.children) {
+      _markFunctionCallsInner(callee, child);
+    }
+  }
+
+  _markFunctionCalls() {
+    for (var child in root.children) {
+      _markFunctionCallsInner(null, child);
+    }
+  }
+}
+
+class CodeTick {
+  final int exclusiveTicks;
+  final int inclusiveTicks;
+  CodeTick(this.exclusiveTicks, this.inclusiveTicks);
+}
+
+class InlineIntervalTick {
+  final int startAddress;
+  int _inclusiveTicks = 0;
+  int get inclusiveTicks => _inclusiveTicks;
+  int _exclusiveTicks = 0;
+  int get exclusiveTicks => _exclusiveTicks;
+  InlineIntervalTick(this.startAddress);
+}
+
+class ProfileCode implements M.ProfileCode {
+  final int tableIndex;
+  final SampleProfile profile;
+  final Code code;
+  int exclusiveTicks;
+  int inclusiveTicks;
+  double normalizedExclusiveTicks = 0.0;
+  double normalizedInclusiveTicks = 0.0;
+  final addressTicks = <int, CodeTick>{};
+  final intervalTicks = <int, InlineIntervalTick>{};
+  String formattedInclusiveTicks = '';
+  String formattedExclusiveTicks = '';
+  String formattedExclusivePercent = '';
+  final Set<String> attributes = <String>{};
+  final callers = <ProfileCode, int>{};
+  final callees = <ProfileCode, int>{};
+
+  void _processTicks(List<dynamic> profileTicks) {
+    assert(profileTicks != null);
+    assert((profileTicks.length % 3) == 0);
+    for (var i = 0; i < profileTicks.length; i += 3) {
+      // TODO(observatory): Address is not necessarily representable as a JS
+      // integer.
+      var address = int.parse(profileTicks[i] as String, radix: 16);
+      var exclusive = profileTicks[i + 1] as int;
+      var inclusive = profileTicks[i + 2] as int;
+      var tick = CodeTick(exclusive, inclusive);
+      addressTicks[address] = tick;
+
+      var interval = code.findInterval(address);
+      if (interval != null) {
+        var intervalTick = intervalTicks[interval.start];
+        if (intervalTick == null) {
+          // Insert into map.
+          intervalTick = InlineIntervalTick(interval.start);
+          intervalTicks[interval.start] = intervalTick;
+        }
+        intervalTick._inclusiveTicks += inclusive;
+        intervalTick._exclusiveTicks += exclusive;
+      }
+    }
+  }
+
+  void clearTicks() {
+    exclusiveTicks = 0;
+    inclusiveTicks = 0;
+    normalizedExclusiveTicks = 0;
+    normalizedInclusiveTicks = 0;
+    formattedInclusiveTicks = '';
+    formattedExclusiveTicks = '';
+    formattedExclusivePercent = '';
+  }
+
+  ProfileCode.fromMap(this.tableIndex, this.profile, this.code, Map data) {
+    assert(profile != null);
+    assert(code != null);
+
+    code.profile = this;
+
+    if (code.kind == M.CodeKind.stub) {
+      attributes.add('stub');
+    } else if (code.kind == M.CodeKind.dart) {
+      if (code.isNative) {
+        attributes.add('ffi'); // Not to be confused with a C function.
+      } else {
+        attributes.add('dart');
+      }
+      if (code.hasIntrinsic) {
+        attributes.add('intrinsic');
+      }
+      if (code.isOptimized) {
+        attributes.add('optimized');
+      } else {
+        attributes.add('unoptimized');
+      }
+    } else if (code.kind == M.CodeKind.tag) {
+      attributes.add('tag');
+    } else if (code.kind == M.CodeKind.native) {
+      attributes.add('native');
+    }
+    inclusiveTicks = data['inclusiveTicks'];
+    exclusiveTicks = data['exclusiveTicks'];
+
+    normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount;
+
+    normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount;
+
+    var ticks = data['ticks'];
+    if (ticks != null) {
+      _processTicks(ticks);
+    }
+
+    formattedExclusivePercent =
+        Utils.formatPercent(exclusiveTicks, profile.sampleCount);
+
+    formattedInclusiveTicks =
+        '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
+        '($inclusiveTicks)';
+
+    formattedExclusiveTicks =
+        '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
+        '($exclusiveTicks)';
+  }
+
+  _recordCaller(ProfileCode caller, int count) {
+    var r = callers[caller];
+    if (r == null) {
+      r = 0;
+    }
+    callers[caller] = r + count;
+  }
+
+  _recordCallee(ProfileCode callee, int count) {
+    var r = callees[callee];
+    if (r == null) {
+      r = 0;
+    }
+    callees[callee] = r + count;
+  }
+
+  void _normalizeTicks() {
+    normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount;
+    normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount;
+
+    formattedExclusivePercent =
+        Utils.formatPercent(exclusiveTicks, profile.sampleCount);
+
+    formattedInclusiveTicks =
+        '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
+        '($inclusiveTicks)';
+
+    formattedExclusiveTicks =
+        '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
+        '($exclusiveTicks)';
+  }
+
+  void tickTag() {
+    // All functions *except* those for tags are ticked in the VM while
+    // generating the CpuSamples response.
+    if (code.kind != M.CodeKind.tag) {
+      throw StateError('Only tags should be ticked. '
+          'Attempted to tick: ${code.name}');
+    }
+    ++exclusiveTicks;
+    ++inclusiveTicks;
+    _normalizeTicks();
+  }
+}
+
+class ProfileFunction implements M.ProfileFunction {
+  final int tableIndex;
+  final SampleProfile profile;
+  final ServiceFunction function;
+  final String resolvedUrl;
+  final callers = <ProfileFunction, int>{};
+  final callees = <ProfileFunction, int>{};
+
+  // Absolute ticks:
+  int exclusiveTicks = 0;
+  int inclusiveTicks = 0;
+
+  // Global percentages:
+  double normalizedExclusiveTicks = 0.0;
+  double normalizedInclusiveTicks = 0.0;
+
+  String formattedInclusiveTicks = '';
+  String formattedExclusiveTicks = '';
+  String formattedExclusivePercent = '';
+  final attributes = <String>{};
+
+  void clearTicks() {
+    exclusiveTicks = 0;
+    inclusiveTicks = 0;
+    normalizedExclusiveTicks = 0;
+    normalizedInclusiveTicks = 0;
+    formattedInclusiveTicks = '';
+    formattedExclusiveTicks = '';
+    formattedExclusivePercent = '';
+  }
+
+  void _addKindBasedAttributes(Set<String> attribs) {
+    if (function.kind == M.FunctionKind.tag) {
+      attribs.add('tag');
+    } else if (function.kind == M.FunctionKind.stub) {
+      attribs.add('stub');
+    } else if (function.kind == M.FunctionKind.native) {
+      attribs.add('native');
+    } else if (M.isSyntheticFunction(function.kind)) {
+      attribs.add('synthetic');
+    } else if (function.isNative) {
+      attribs.add('ffi'); // Not to be confused with a C function.
+    } else {
+      attribs.add('dart');
+    }
+    if (function.hasIntrinsic == true) {
+      attribs.add('intrinsic');
+    }
+  }
+
+  ProfileFunction.fromMap(
+      this.tableIndex, this.profile, this.function, Map data)
+      : resolvedUrl = data['resolvedUrl'] {
+    function.profile = this;
+    _addKindBasedAttributes(attributes);
+    exclusiveTicks = data['exclusiveTicks'];
+    inclusiveTicks = data['inclusiveTicks'];
+    _normalizeTicks();
+  }
+
+  _recordCaller(ProfileFunction caller, int count) {
+    var r = callers[caller];
+    if (r == null) {
+      r = 0;
+    }
+    callers[caller] = r + count;
+  }
+
+  _recordCallee(ProfileFunction callee, int count) {
+    var r = callees[callee];
+    if (r == null) {
+      r = 0;
+    }
+    callees[callee] = r + count;
+  }
+
+  void _normalizeTicks() {
+    normalizedExclusiveTicks = exclusiveTicks / profile.sampleCount;
+    normalizedInclusiveTicks = inclusiveTicks / profile.sampleCount;
+
+    formattedExclusivePercent =
+        Utils.formatPercent(exclusiveTicks, profile.sampleCount);
+
+    formattedInclusiveTicks =
+        '${Utils.formatPercent(inclusiveTicks, profile.sampleCount)} '
+        '($inclusiveTicks)';
+
+    formattedExclusiveTicks =
+        '${Utils.formatPercent(exclusiveTicks, profile.sampleCount)} '
+        '($exclusiveTicks)';
+  }
+
+  void tickTag() {
+    // All functions *except* those for functions are ticked in the VM while
+    // generating the CpuSamples response.
+    if (function.kind != M.FunctionKind.tag) {
+      throw StateError('Only tags should be ticked. '
+          'Attempted to tick: ${function.name}');
+    }
+    ++exclusiveTicks;
+    ++inclusiveTicks;
+    _normalizeTicks();
+  }
+}
+
+class SampleProfile extends M.SampleProfile {
+  Isolate isolate;
+
+  int sampleCount = 0;
+  int samplePeriod = 0;
+  double sampleRate = 0.0;
+  int pid = 0;
+  int maxStackDepth = 0;
+
+  double timeSpan = 0.0;
+
+  M.SampleProfileTag tagOrder = M.SampleProfileTag.none;
+
+  final _functionTagMapping = <String, int>{};
+  final _codeTagMapping = <String, int>{};
+
+  final List samples = [];
+  final codes = <ProfileCode>[];
+  bool _builtCodeCalls = false;
+  final functions = <ProfileFunction>[];
+  bool _builtFunctionCalls = false;
+
+  static const String _kCode = 'code';
+  static const String _kCodes = '_codes';
+  static const String _kCodeStack = '_codeStack';
+  static const String _kFunction = 'function';
+  static const String _kFunctions = 'functions';
+  static const String _kNativeAllocationSizeBytes =
+      '_nativeAllocationSizeBytes';
+  static const String _kPid = 'pid';
+  static const String _kSampleCount = 'sampleCount';
+  static const String _kSamplePeriod = 'samplePeriod';
+  static const String _kSamples = 'samples';
+  static const String _kStack = 'stack';
+  static const String _kMaxStackDepth = 'maxStackDepth';
+  static const String _kTimeSpan = 'timespan';
+  static const String _kUserTag = 'userTag';
+  static const String _kVmTag = 'vmTag';
+
+  // Names of special tag types.
+  static const String kNativeTag = 'Native';
+  static const String kRootTag = 'Root';
+  static const String kRuntimeTag = 'Runtime';
+  static const String kTruncatedTag = '[Truncated]';
+
+  // Used to stash trie information in samples for timeline processing.
+  static const String kTimelineFunctionTrie = 'timelineFunctionTrie';
+
+  CodeCallTree loadCodeTree(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive:
+        return _loadCodeTree(true);
+      case M.ProfileTreeDirection.exclusive:
+        return _loadCodeTree(false);
+    }
+    throw Exception('Unknown ProfileTreeDirection');
+  }
+
+  FunctionCallTree loadFunctionTree(M.ProfileTreeDirection direction) {
+    switch (direction) {
+      case M.ProfileTreeDirection.inclusive:
+        return _loadFunctionTree(true);
+      case M.ProfileTreeDirection.exclusive:
+        return _loadFunctionTree(false);
+    }
+    throw Exception('Unknown ProfileTreeDirection');
+  }
+
+  buildCodeCallerAndCallees() {
+    if (_builtCodeCalls) {
+      return;
+    }
+    _builtCodeCalls = true;
+    var tree = loadCodeTree(M.ProfileTreeDirection.inclusive);
+    tree._recordCallerAndCallees();
+  }
+
+  buildFunctionCallerAndCallees() {
+    if (_builtFunctionCalls) {
+      return;
+    }
+    _builtFunctionCalls = true;
+    var tree = loadFunctionTree(M.ProfileTreeDirection.inclusive);
+    tree._markFunctionCalls();
+  }
+
+  clear() {
+    pid = -1;
+    sampleCount = 0;
+    samplePeriod = 0;
+    sampleRate = 0.0;
+    maxStackDepth = 0;
+    timeSpan = 0.0;
+    codes.clear();
+    functions.clear();
+    _builtCodeCalls = false;
+    _builtFunctionCalls = false;
+  }
+
+  Future load(ServiceObjectOwner owner, ServiceMap profile) async {
+    await loadProgress(owner, profile).drain();
+  }
+
+  static Future sleep([Duration duration = const Duration(microseconds: 0)]) =>
+      Future.delayed(duration);
+
+  Future _loadCommon(ServiceObjectOwner owner, ServiceMap profile,
+      [StreamController<double> progress]) async {
+    final watch = Stopwatch();
+    watch.start();
+    int count = 0;
+    var needToUpdate = () {
+      if (progress == null) {
+        return false;
+      }
+      count++;
+      if (((count % 256) == 0) && (watch.elapsedMilliseconds > 16)) {
+        watch.reset();
+        return true;
+      }
+      return false;
+    };
+    var signal = (double p) {
+      if (progress == null) {
+        return null;
+      }
+      progress.add(p);
+      return sleep();
+    };
+    try {
+      clear();
+      progress?.add(0.0);
+      if (profile == null) {
+        return;
+      }
+
+      if ((owner != null) && (owner is Isolate)) {
+        isolate = owner;
+        isolate.resetCachedProfileData();
+      }
+
+      pid = profile[_kPid];
+      sampleCount = profile[_kSampleCount];
+      samplePeriod = profile[_kSamplePeriod];
+      sampleRate = (Duration.microsecondsPerSecond / samplePeriod);
+      maxStackDepth = profile[_kMaxStackDepth];
+      timeSpan = profile[_kTimeSpan];
+
+      num length = 0;
+
+      if (profile.containsKey(_kCodes)) {
+        length += profile[_kCodes].length;
+      }
+      length += profile[_kFunctions].length;
+
+      // Process code table.
+      int tableIndex = 0;
+      if (profile.containsKey(_kCodes)) {
+        for (var codeRegion in profile[_kCodes]) {
+          if (needToUpdate()) {
+            await signal(count * 100.0 / length);
+          }
+          Code code = codeRegion[_kCode];
+          assert(code != null);
+          codes.add(ProfileCode.fromMap(tableIndex, this, code, codeRegion));
+          ++tableIndex;
+        }
+      }
+      // Process function table.
+      tableIndex = 0;
+      for (var profileFunction in profile[_kFunctions]) {
+        if (needToUpdate()) {
+          await signal(count * 100 / length);
+        }
+        ServiceFunction function = profileFunction[_kFunction];
+        assert(function != null);
+        functions.add(ProfileFunction.fromMap(
+            tableIndex, this, function, profileFunction));
+        ++tableIndex;
+      }
+      if (profile.containsKey(_kCodes)) {
+        _buildCodeTagMapping();
+      }
+
+      _buildFunctionTagMapping();
+
+      samples.addAll(profile[_kSamples]);
+    } finally {
+      progress?.close();
+    }
+  }
+
+  Stream<double> loadProgress(ServiceObjectOwner owner, ServiceMap profile) {
+    Logger.root.info('sampling counters ${profile['_counters']}');
+
+    var progress = StreamController<double>.broadcast();
+
+    _loadCommon(owner, profile, progress);
+    return progress.stream;
+  }
+
+  // Helpers for reading optional flags from a sample.
+  static bool _isNativeEntryTag(Map sample) =>
+      sample.containsKey('nativeEntryTag');
+  static bool _isRuntimeEntryTag(Map sample) =>
+      sample.containsKey('runtimeEntryTag');
+  static bool _isTruncated(Map sample) => sample.containsKey('truncated');
+  static bool _isNativeAllocationSample(Map sample) =>
+      sample.containsKey('_nativeAllocationSizeBytes');
+
+  int _getProfileFunctionTagIndex(String tag) {
+    if (_functionTagMapping.containsKey(tag)) {
+      return _functionTagMapping[tag];
+    }
+    throw ArgumentError('$tag is not a valid tag!');
+  }
+
+  int _getProfileCodeTagIndex(String tag) {
+    if (_codeTagMapping.containsKey(tag)) {
+      return _codeTagMapping[tag];
+    }
+    throw ArgumentError('$tag is not a valid tag!');
+  }
+
+  void _buildFunctionTagMapping() {
+    for (int i = 0; i < functions.length; ++i) {
+      final function = functions[i].function;
+      if (function.kind == M.FunctionKind.tag) {
+        _functionTagMapping[function.name] = i;
+      }
+    }
+  }
+
+  void _buildCodeTagMapping() {
+    for (int i = 0; i < codes.length; ++i) {
+      final code = codes[i].code;
+      if (code.kind == M.CodeKind.tag) {
+        _codeTagMapping[code.name] = i;
+      }
+    }
+  }
+
+  void _clearProfileFunctionTagTicks() =>
+      _functionTagMapping.forEach((String name, int tableIndex) {
+        // Truncated tag is ticked in the VM, so don't clear it.
+        if (name != kTruncatedTag) {
+          functions[tableIndex].clearTicks();
+        }
+      });
+
+  void _clearProfileCodeTagTicks() =>
+      _codeTagMapping.forEach((String name, int tableIndex) {
+        // Truncated tag is ticked in the VM, so don't clear it.
+        if (name != kTruncatedTag) {
+          codes[tableIndex].clearTicks();
+        }
+      });
+
+  NodeT _appendUserTag<NodeT extends CallTreeNode>(
+      String userTag, NodeT current, Map sample) {
+    bool isCode = (current is CodeCallTreeNode);
+    try {
+      final tableIndex = isCode
+          ? _getProfileCodeTagIndex(userTag)
+          : _getProfileFunctionTagIndex(userTag);
+      current = current.getChild(tableIndex);
+      current.tick(sample);
+    } catch (_) {/* invalid tag */} finally {
+      return current;
+    }
+  }
+
+  NodeT _appendTruncatedTag<NodeT extends CallTreeNode>(
+      NodeT current, Map sample) {
+    final isCode = (current is CodeCallTreeNode);
+    try {
+      final tableIndex = isCode
+          ? _getProfileCodeTagIndex(kTruncatedTag)
+          : _getProfileFunctionTagIndex(kTruncatedTag);
+      current = current.getChild(tableIndex);
+      current.tick(sample);
+      // We don't need to tick the tag itself since this is done in the VM for
+      // the truncated tag, unlike other VM and user tags.
+    } catch (_) {/* invalid tag */} finally {
+      return current;
+    }
+  }
+
+  FunctionCallTreeNode _getFunctionTagAndTick(
+      String tag, FunctionCallTreeNode current, Map sample) {
+    try {
+      final tableIndex = _getProfileFunctionTagIndex(tag);
+      current = current.getChild(tableIndex);
+      current.tick(sample);
+    } catch (_) {/* invalid tag */} finally {
+      return current;
+    }
+  }
+
+  CodeCallTreeNode _getCodeTagAndTick(
+      String tag, CodeCallTreeNode current, Map sample) {
+    try {
+      final tableIndex = _getProfileCodeTagIndex(tag);
+      current = current.getChild(tableIndex);
+      current.tick(sample);
+    } catch (_) {/* invalid tag */} finally {
+      return current;
+    }
+  }
+
+  NodeT _getTagAndTick<NodeT extends CallTreeNode>(
+      String tag, NodeT current, Map sample) {
+    if (current is FunctionCallTreeNode) {
+      return _getFunctionTagAndTick(tag, current, sample) as NodeT;
+    } else if (current is CodeCallTreeNode) {
+      return _getCodeTagAndTick(tag, current, sample) as NodeT;
+    }
+    throw ArgumentError('Unexpected tree type: $NodeT');
+  }
+
+  NodeT _appendVMTag<NodeT extends CallTreeNode>(
+      String vmTag, NodeT current, Map sample) {
+    if (_isNativeEntryTag(sample)) {
+      return _getTagAndTick(kNativeTag, current, sample);
+    } else if (_isRuntimeEntryTag(sample)) {
+      return _getTagAndTick(kRuntimeTag, current, sample);
+    } else {
+      return _getTagAndTick(vmTag, current, sample);
+    }
+  }
+
+  NodeT _appendSpecificNativeRuntimeEntryVMTag<NodeT extends CallTreeNode>(
+      NodeT current, Map sample) {
+    // Only Native and Runtime entries have a second VM tag.
+    if (!_isNativeEntryTag(sample) && !_isRuntimeEntryTag(sample)) {
+      return current;
+    }
+    final vmTag = sample[_kVmTag];
+    return _getTagAndTick(vmTag, current, sample);
+  }
+
+  NodeT _appendVMTags<NodeT extends CallTreeNode>(
+      String vmTag, NodeT current, Map sample) {
+    current = _appendVMTag(vmTag, current, sample);
+    current = _appendSpecificNativeRuntimeEntryVMTag(current, sample);
+    return current;
+  }
+
+  void _tickTags(String vmTag, String userTag, bool tickCode) {
+    if (tickCode) {
+      final vmTagIndex = _getProfileCodeTagIndex(vmTag);
+      codes[vmTagIndex].tickTag();
+
+      final userTagIndex = _getProfileCodeTagIndex(userTag);
+      codes[userTagIndex].tickTag();
+    } else {
+      final vmTagIndex = _getProfileFunctionTagIndex(vmTag);
+      functions[vmTagIndex].tickTag();
+
+      final userTagIndex = _getProfileFunctionTagIndex(userTag);
+      functions[userTagIndex].tickTag();
+    }
+  }
+
+  NodeT _appendTags<NodeT extends CallTreeNode>(
+      String vmTag, String userTag, NodeT current, Map sample) {
+    final tickCode = (current is M.CodeCallTreeNode);
+    _tickTags(vmTag, userTag, tickCode);
+    if (tagOrder == M.SampleProfileTag.none) {
+      return current;
+    }
+    // User first.
+    if (tagOrder == M.SampleProfileTag.userVM ||
+        tagOrder == M.SampleProfileTag.userOnly) {
+      current = _appendUserTag(userTag, current, sample);
+      // Only user.
+      if (tagOrder == M.SampleProfileTag.userOnly) {
+        return current;
+      }
+      return _appendVMTags(vmTag, current, sample);
+    }
+
+    // VM first.
+    current = _appendVMTags(vmTag, current, sample);
+    // Only VM.
+    if (tagOrder == M.SampleProfileTag.vmOnly) {
+      return current;
+    }
+    return _appendUserTag(userTag, current, sample);
+  }
+
+  NodeT _processFrame<NodeT extends CallTreeNode>(NodeT parent, int sampleIndex,
+      Map sample, List<int> stack, int frameIndex, bool inclusive) {
+    final child = parent.getChild(stack[frameIndex]);
+    child.tick(sample, exclusive: (frameIndex == 0));
+    return child;
+  }
+
+  FunctionCallTreeNode buildFunctionTrie(bool inclusive) {
+    final root = FunctionCallTreeNode.fromIndex(
+        this, _getProfileFunctionTagIndex(kRootTag));
+
+    for (int sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
+      final sample = samples[sampleIndex];
+      FunctionCallTreeNode current = root;
+      // Tick the root for each sample as we always visit the root node.
+      root.tick(sample);
+
+      // VM + User tags.
+      final vmTag = sample[_kVmTag];
+      final userTag = sample[_kUserTag];
+      final stack = sample[_kStack].cast<int>();
+      current = _appendTags(vmTag, userTag, current, sample);
+
+      if (inclusive) {
+        if (_isTruncated(sample)) {
+          current = _appendTruncatedTag(current, sample);
+        }
+        for (int frameIndex = stack.length - 1; frameIndex >= 0; --frameIndex) {
+          current = _processFrame(
+              current, sampleIndex, sample, stack, frameIndex, true);
+        }
+
+        // Used by the timeline to find the root of each sample.
+        sample[kTimelineFunctionTrie] = current;
+      } else {
+        for (int frameIndex = 0; frameIndex < stack.length; ++frameIndex) {
+          current = _processFrame(
+              current, sampleIndex, sample, stack, frameIndex, false);
+        }
+
+        if (_isTruncated(sample)) {
+          current = _appendTruncatedTag(current, sample);
+        }
+      }
+    }
+    return root;
+  }
+
+  CodeCallTreeNode buildCodeTrie(bool inclusive) {
+    final root =
+        CodeCallTreeNode.fromIndex(this, _getProfileCodeTagIndex(kRootTag));
+
+    for (int sampleIndex = 0; sampleIndex < samples.length; ++sampleIndex) {
+      final sample = samples[sampleIndex];
+
+      CodeCallTreeNode current = root;
+      // Tick the root for each sample as we always visit the root node.
+      root.tick(sample);
+
+      // VM + User tags.
+      final vmTag = sample[_kVmTag];
+      final userTag = sample[_kUserTag];
+      final stack = sample[_kCodeStack].cast<int>();
+      current = _appendTags(vmTag, userTag, current, sample);
+
+      if (inclusive) {
+        if (_isTruncated(sample)) {
+          current = _appendTruncatedTag(current, sample);
+        }
+        for (int frameIndex = stack.length - 1; frameIndex >= 0; --frameIndex) {
+          current = _processFrame(
+              current, sampleIndex, sample, stack, frameIndex, true);
+        }
+      } else {
+        for (int frameIndex = 0; frameIndex < stack.length; ++frameIndex) {
+          current = _processFrame(
+              current, sampleIndex, sample, stack, frameIndex, false);
+        }
+
+        if (_isTruncated(sample)) {
+          current = _appendTruncatedTag(current, sample);
+        }
+      }
+    }
+    return root;
+  }
+
+  FunctionCallTree _loadFunctionTree(bool inclusive) {
+    // Since we're only ticking tag functions when building the trie, we need
+    // to clean up ticks from previous tree builds.
+    _clearProfileFunctionTagTicks();
+
+    // Read the tree, returns the root node.
+    final root = buildFunctionTrie(inclusive);
+    root.sortChildren();
+    return FunctionCallTree(inclusive, root);
+  }
+
+  CodeCallTree _loadCodeTree(bool inclusive) {
+    // Since we're only ticking tag code when building the trie, we need
+    // to clean up ticks from previous tree builds.
+    _clearProfileCodeTagTicks();
+
+    // Read the tree, returns the root node.
+    final root = buildCodeTrie(inclusive);
+    root.sortChildren();
+    return CodeCallTree(inclusive, root);
+  }
+
+  int approximateMillisecondsForCount(count) {
+    return (count * samplePeriod) ~/ Duration.microsecondsPerMillisecond;
+  }
+
+  double approximateSecondsForCount(count) {
+    return (count * samplePeriod) / Duration.microsecondsPerSecond;
+  }
+}
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
new file mode 100644
index 0000000..046513d
--- /dev/null
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -0,0 +1,4926 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of service;
+
+// Some value smaller than the object ring, so requesting a large array
+// doesn't result in an expired ref because the elements lapped it in the
+// object ring.
+const int kDefaultFieldLimit = 100;
+
+/// Helper function for canceling a Future<StreamSubscription>.
+Future cancelFutureSubscription(
+    Future<StreamSubscription> subscriptionFuture) async {
+  if (subscriptionFuture != null) {
+    var subscription = await subscriptionFuture;
+    return subscription.cancel();
+  } else {
+    return null;
+  }
+}
+
+/// An RpcException represents an exceptional event that happened
+/// while invoking an rpc.
+abstract class RpcException implements Exception, M.BasicException {
+  RpcException(this.message);
+
+  String message;
+}
+
+/// A ServerRpcException represents an error returned by the VM.
+class ServerRpcException extends RpcException implements M.RequestException {
+  /// A list of well-known server error codes.
+  static const kParseError = -32700;
+  static const kInvalidRequest = -32600;
+  static const kMethodNotFound = -32601;
+  static const kInvalidParams = -32602;
+  static const kInternalError = -32603;
+  static const kFeatureDisabled = 100;
+  static const kCannotAddBreakpoint = 102;
+  static const kStreamAlreadySubscribed = 103;
+  static const kStreamNotSubscribed = 104;
+  static const kIsolateMustBeRunnable = 105;
+  static const kIsolateMustBePaused = 106;
+  static const kCannotResume = 107;
+  static const kIsolateIsReloading = 108;
+  static const kIsolateReloadBarred = 109;
+  static const kIsolateMustHaveReloaded = 110;
+  static const kServiceAlreadyRegistered = 111;
+  static const kServiceDisappeared = 112;
+  static const kExpressionCompilationError = 113;
+
+  static const kFileSystemAlreadyExists = 1001;
+  static const kFileSystemDoesNotExist = 1002;
+  static const kFileDoesNotExist = 1003;
+
+  int code;
+  Map data;
+
+  static _getMessage(Map errorMap) {
+    Map data = errorMap['data'];
+    if (data != null && data['details'] != null) {
+      return data['details'];
+    } else {
+      return errorMap['message'];
+    }
+  }
+
+  ServerRpcException.fromMap(Map errorMap) : super(_getMessage(errorMap)) {
+    code = errorMap['code'];
+    data = errorMap['data'];
+  }
+
+  String toString() => 'ServerRpcException(${message})';
+}
+
+/// A NetworkRpcException is used to indicate that an rpc has
+/// been canceled due to network error.
+class NetworkRpcException extends RpcException
+    implements M.ConnectionException {
+  NetworkRpcException(String message) : super(message);
+
+  String toString() => 'NetworkRpcException(${message})';
+}
+
+Future<ServiceObject> ignoreNetworkErrors(Object error,
+    [ServiceObject resultOnNetworkError = null]) {
+  if (error is NetworkRpcException) {
+    return new Future.value(resultOnNetworkError);
+  }
+  return new Future.error(error);
+}
+
+class MalformedResponseRpcException extends RpcException {
+  MalformedResponseRpcException(String message, this.response) : super(message);
+
+  Map response;
+
+  String toString() => 'MalformedResponseRpcException(${message})';
+}
+
+/// A [ServiceObject] represents a persistent object within the vm.
+abstract class ServiceObject implements M.ObjectRef {
+  static int LexicalSortName(ServiceObject o1, ServiceObject o2) {
+    return o1.name.compareTo(o2.name);
+  }
+
+  List<T> removeDuplicatesAndSortLexical<T extends ServiceObject>(
+      List<T> list) {
+    return list.toSet().toList()..sort(LexicalSortName);
+  }
+
+  /// The owner of this [ServiceObject].  This can be an [Isolate], a
+  /// [VM], or null.
+  ServiceObjectOwner get owner => _owner;
+  ServiceObjectOwner _owner;
+
+  /// The [VM] which owns this [ServiceObject].
+  VM get vm => _owner.vm;
+
+  /// The [Isolate] which owns this [ServiceObject].  May be null.
+  Isolate get isolate => _owner.isolate;
+
+  /// The id of this object.
+  String get id => _id;
+  String _id;
+
+  /// The user-level type of this object.
+  String get type => _type;
+  String _type;
+
+  /// The vm type of this object.
+  String get vmType => _vmType;
+  String _vmType;
+
+  bool get isICData => vmType == 'ICData';
+  bool get isMegamorphicCache => vmType == 'MegamorphicCache';
+  bool get isInstructions => vmType == 'Instructions';
+  bool get isObjectPool => vmType == 'ObjectPool';
+  bool get isContext => type == 'Context';
+  bool get isError => type == 'Error';
+  bool get isInstance => type == 'Instance';
+  bool get isSentinel => type == 'Sentinel';
+  bool get isMessage => type == 'Message';
+
+  // Kinds of Instance.
+  bool get isAbstractType => false;
+  bool get isNull => false;
+  bool get isBool => false;
+  bool get isDouble => false;
+  bool get isString => false;
+  bool get isInt => false;
+  bool get isList => false;
+  bool get isMap => false;
+  bool get isTypedData => false;
+  bool get isRegExp => false;
+  bool get isMirrorReference => false;
+  bool get isWeakProperty => false;
+  bool get isClosure => false;
+  bool get isStackTrace => false;
+  bool get isSimdValue => false;
+  bool get isPlainInstance => false;
+
+  /// Has this object been fully loaded?
+  bool get loaded => _loaded;
+  bool _loaded = false;
+  // TODO(turnidge): Make loaded observable and get rid of loading
+  // from Isolate.
+
+  /// Is this object cacheable?  That is, is it impossible for the [id]
+  /// of this object to change?
+  bool _canCache;
+  bool get canCache => _canCache;
+
+  /// Is this object immutable after it is [loaded]?
+  bool get immutable => false;
+
+  String name;
+  String vmName;
+
+  /// Creates an empty [ServiceObject].
+  ServiceObject._empty(this._owner);
+
+  /// Creates a [ServiceObject] initialized from [map].
+  factory ServiceObject._fromMap(ServiceObjectOwner owner, Map map) {
+    if (map == null) {
+      return null;
+    }
+    if (!_isServiceMap(map)) {
+      Logger.root.severe('Malformed service object: $map');
+    }
+    assert(_isServiceMap(map));
+    var type = _stripRef(map['type']);
+    var vmType = map['_vmType'] != null ? map['_vmType'] : type;
+    var obj = null;
+    assert(type != 'VM');
+    switch (type) {
+      case 'Breakpoint':
+        obj = new Breakpoint._empty(owner);
+        break;
+      case 'Class':
+        obj = new Class._empty(owner);
+        break;
+      case 'Code':
+        obj = new Code._empty(owner);
+        break;
+      case 'Context':
+        obj = new Context._empty(owner);
+        break;
+      case 'Counter':
+        obj = new ServiceMetric._empty(owner);
+        break;
+      case 'Error':
+        obj = new DartError._empty(owner);
+        break;
+      case 'Field':
+        obj = new Field._empty(owner);
+        break;
+      case 'Frame':
+        obj = new Frame._empty(owner);
+        break;
+      case 'Function':
+      case 'NativeFunction':
+        obj = new ServiceFunction._empty(owner);
+        break;
+      case 'Gauge':
+        obj = new ServiceMetric._empty(owner);
+        break;
+      case 'Isolate':
+        obj = new Isolate._empty(owner.vm);
+        break;
+      case 'IsolateGroup':
+        obj = new IsolateGroup._empty(owner.vm);
+        break;
+      case 'Library':
+        obj = new Library._empty(owner);
+        break;
+      case 'Message':
+        obj = new ServiceMessage._empty(owner);
+        break;
+      case 'SourceLocation':
+        obj = new SourceLocation._empty(owner);
+        break;
+      case '_Thread':
+        obj = new Thread._empty(owner);
+        break;
+      case 'UnresolvedSourceLocation':
+        obj = new UnresolvedSourceLocation._empty(owner);
+        break;
+      case 'Object':
+        switch (vmType) {
+          case 'ICData':
+            obj = new ICData._empty(owner);
+            break;
+          case 'LocalVarDescriptors':
+            obj = new LocalVarDescriptors._empty(owner);
+            break;
+          case 'MegamorphicCache':
+            obj = new MegamorphicCache._empty(owner);
+            break;
+          case 'ObjectPool':
+            obj = new ObjectPool._empty(owner);
+            break;
+          case 'PcDescriptors':
+            obj = new PcDescriptors._empty(owner);
+            break;
+          case 'SingleTargetCache':
+            obj = new SingleTargetCache._empty(owner);
+            break;
+          case 'SubtypeTestCache':
+            obj = new SubtypeTestCache._empty(owner);
+            break;
+          case 'UnlinkedCall':
+            obj = new UnlinkedCall._empty(owner);
+            break;
+        }
+        break;
+      case 'Event':
+        obj = new ServiceEvent._empty(owner);
+        break;
+      case 'Script':
+        obj = new Script._empty(owner);
+        break;
+      case 'Socket':
+        obj = new Socket._empty(owner);
+        break;
+      case 'Sentinel':
+        obj = new Sentinel._empty(owner);
+        break;
+      case 'InstanceSet':
+        obj = new InstanceSet._empty(owner);
+        break;
+      case 'TypeArguments':
+        obj = new TypeArguments._empty(owner);
+        break;
+      case 'Instance':
+        obj = new Instance._empty(owner);
+        break;
+      default:
+        break;
+    }
+    if (obj == null) {
+      obj = new ServiceMap._empty(owner);
+    }
+    obj.updateFromServiceMap(map);
+    return obj;
+  }
+
+  /// If [this] was created from a reference, load the full object
+  /// from the service by calling [reload]. Else, return [this].
+  Future<ServiceObject> load() {
+    if (loaded) {
+      return new Future.value(this);
+    }
+    // Call reload which will fill in the entire object.
+    return reload();
+  }
+
+  Future<ServiceObject> _inProgressReload;
+
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) {
+    Map params = {
+      'objectId': id,
+      'count': count,
+    };
+    return isolate.invokeRpcNoUpgrade('getObject', params);
+  }
+
+  /// Reload [this]. Returns a future which completes to [this] or
+  /// an exception.
+  Future<ServiceObject> reload({int count: kDefaultFieldLimit}) {
+    // TODO(turnidge): Checking for a null id should be part of the
+    // "immutable" check.
+    bool hasId = (id != null) && (id != '');
+    bool isVM = this is VM;
+    // We should always reload the VM.
+    // We can't reload objects without an id.
+    // We shouldn't reload an immutable and already loaded object.
+    bool skipLoad = !isVM && (!hasId || (immutable && loaded));
+    if (skipLoad) {
+      return new Future.value(this);
+    }
+    if (_inProgressReload == null) {
+      var completer = new Completer<ServiceObject>();
+      _inProgressReload = completer.future;
+      _fetchDirect(count: count).then((Map map) {
+        var mapType = _stripRef(map['type']);
+        if (mapType == 'Sentinel') {
+          // An object may have been collected, etc.
+          completer.complete(new ServiceObject._fromMap(owner, map));
+        } else {
+          // TODO(turnidge): Check for vmType changing as well?
+          assert(mapType == _type);
+          updateFromServiceMap(map);
+          completer.complete(this);
+        }
+      }).catchError((e, st) {
+        Logger.root.severe("Unable to reload object: $e\n$st");
+        _inProgressReload = null;
+        completer.completeError(e, st);
+      }).whenComplete(() {
+        // This reload is complete.
+        _inProgressReload = null;
+      });
+    }
+    return _inProgressReload;
+  }
+
+  /// Update [this] using [map] as a source. [map] can be a reference.
+  void updateFromServiceMap(Map map) {
+    assert(_isServiceMap(map));
+
+    // Don't allow the type to change on an object update.
+    var mapIsRef = _hasRef(map['type']);
+    var mapType = _stripRef(map['type']);
+    assert(_type == null || _type == mapType);
+
+    _canCache = map['fixedId'] == true;
+    if (_id != null && _id != map['id']) {
+      // It is only safe to change an id when the object isn't cacheable.
+      assert(!canCache);
+    }
+    _id = map['id'];
+
+    _type = mapType;
+
+    // When the response specifies a specific vmType, use it.
+    // Otherwise the vmType of the response is the same as the 'user'
+    // type.
+    if (map.containsKey('_vmType')) {
+      _vmType = _stripRef(map['_vmType']);
+    } else {
+      _vmType = _type;
+    }
+
+    _update(map, mapIsRef);
+  }
+
+  // Updates internal state from [map]. [map] can be a reference.
+  void _update(Map map, bool mapIsRef);
+
+  // Helper that can be passed to .catchError that ignores the error.
+  _ignoreError(error, stackTrace) {
+    // do nothing.
+  }
+}
+
+abstract class HeapObject extends ServiceObject implements M.Object {
+  Class clazz;
+  int size;
+  int retainedSize;
+
+  HeapObject._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    if (map['class'] != null) {
+      // Sent with refs for some types. Load it if available, but don't clobber
+      // it with null for kinds that only send if for full responses.
+      clazz = map['class'];
+    }
+
+    // Load the full class object if the isolate is runnable.
+    if (clazz != null) {
+      if (clazz.isolate.runnable) {
+        // No one awaits on this request so we silence any network errors
+        // that occur here but forward other errors.
+        clazz.load().catchError((error) => ignoreNetworkErrors(error, clazz));
+      }
+    }
+
+    if (mapIsRef) {
+      return;
+    }
+    size = map['size'];
+  }
+}
+
+class RetainingObject implements M.RetainingObject {
+  int get retainedSize => object.retainedSize;
+  final HeapObject object;
+  RetainingObject(this.object);
+}
+
+abstract class ServiceObjectOwner extends ServiceObject {
+  /// Creates an empty [ServiceObjectOwner].
+  ServiceObjectOwner._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  /// Builds a [ServiceObject] corresponding to the [id] from [map].
+  /// The result may come from the cache.  The result will not necessarily
+  /// be [loaded].
+  ServiceObject getFromMap(Map map);
+
+  Future<ServiceObject> invokeRpc(String method, Map params);
+}
+
+abstract class Location implements M.Location {
+  Script get script;
+  int get tokenPos;
+  Future<int> getLine();
+  Future<int> getColumn();
+  Future<String> toUserString();
+}
+
+/// A [SourceLocation] represents a location or range in the source code.
+class SourceLocation extends ServiceObject
+    implements Location, M.SourceLocation {
+  Script script;
+  int tokenPos;
+  int endTokenPos;
+
+  Future<int> getLine() async {
+    await script.load();
+    return script.tokenToLine(tokenPos);
+  }
+
+  Future<int> getColumn() async {
+    await script.load();
+    return script.tokenToCol(tokenPos);
+  }
+
+  SourceLocation._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _upgradeCollection(map, owner);
+    script = map['script'];
+    tokenPos = map['tokenPos'];
+    endTokenPos = map['endTokenPos'];
+
+    assert(script != null && tokenPos != null);
+  }
+
+  Future<String> toUserString() async {
+    int line = await getLine();
+    int column = await getColumn();
+    return '${script.name}:${line}:${column}';
+  }
+
+  String toString() {
+    if (endTokenPos == null) {
+      return '${script.name}:token(${tokenPos})';
+    } else {
+      return '${script.name}:tokens(${tokenPos}-${endTokenPos})';
+    }
+  }
+}
+
+/// An [UnresolvedSourceLocation] represents a location in the source
+// code which has not been precisely mapped to a token position.
+class UnresolvedSourceLocation extends ServiceObject
+    implements Location, M.UnresolvedSourceLocation {
+  Script script;
+  String scriptUri;
+  int line;
+  int column;
+  int tokenPos;
+
+  Future<int> getLine() async {
+    if (tokenPos != null) {
+      await script.load();
+      return script.tokenToLine(tokenPos);
+    } else {
+      return line;
+    }
+  }
+
+  Future<int> getColumn() async {
+    if (tokenPos != null) {
+      await script.load();
+      return script.tokenToCol(tokenPos);
+    } else {
+      return column;
+    }
+  }
+
+  UnresolvedSourceLocation._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _upgradeCollection(map, owner);
+    script = map['script'];
+    scriptUri = map['scriptUri'];
+    line = map['line'];
+    column = map['column'];
+    tokenPos = map['tokenPos'];
+
+    assert(script != null || scriptUri != null);
+    assert(line != null || tokenPos != null);
+  }
+
+  Future<String> toUserString() async {
+    StringBuffer sb = new StringBuffer();
+
+    int line = await getLine();
+    int column = await getColumn();
+
+    if (script != null) {
+      sb.write('${script.name}:');
+    } else {
+      sb.write('${scriptUri}:');
+    }
+    if (column != null) {
+      sb.write('${line}:${column}');
+    } else {
+      sb.write('${line}');
+    }
+    return sb.toString();
+  }
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    if (script != null) {
+      sb.write('${script.name}:');
+    } else {
+      sb.write('${scriptUri}:');
+    }
+    if (tokenPos != null) {
+      sb.write('token(${tokenPos})');
+    } else if (column != null) {
+      sb.write('${line}:${column}');
+    } else {
+      sb.write('${line}');
+    }
+    sb.write('[unresolved]');
+    return sb.toString();
+  }
+}
+
+class _EventStreamState {
+  VM _vm;
+  String streamId;
+
+  Function _onDone;
+
+  // A list of all subscribed controllers for this stream.
+  List _controllers = [];
+
+  // Completes when the listen rpc is finished.
+  Future _listenFuture;
+
+  // Completes when then cancel rpc is finished.
+  Future _cancelFuture;
+
+  _EventStreamState(this._vm, this.streamId, this._onDone);
+
+  Future _cancelController(StreamController controller) {
+    _controllers.remove(controller);
+    if (_controllers.isEmpty) {
+      assert(_listenFuture != null);
+      _listenFuture = null;
+      _cancelFuture = _vm._streamCancel(streamId);
+      _cancelFuture.then((_) {
+        if (_controllers.isEmpty) {
+          // No new listeners showed up during cancelation.
+          _onDone();
+        }
+      }).catchError((e) {
+        /* ignore */
+      });
+    }
+    // No need to wait for _cancelFuture here.
+    return new Future.value(null);
+  }
+
+  Future<Stream<ServiceEvent>> addStream() async {
+    var controller;
+    controller = new StreamController<ServiceEvent>(
+        onCancel: () => _cancelController(controller));
+    _controllers.add(controller);
+    if (_cancelFuture != null) {
+      try {
+        await _cancelFuture;
+      } on NetworkRpcException catch (_) {/* ignore */}
+    }
+    if (_listenFuture == null) {
+      _listenFuture = _vm._streamListen(streamId);
+    }
+    try {
+      await _listenFuture;
+    } on NetworkRpcException catch (_) {/* ignore */}
+    return controller.stream;
+  }
+
+  void addEvent(ServiceEvent event) {
+    for (var controller in _controllers) {
+      controller.add(event);
+    }
+  }
+}
+
+/// State for a VM being inspected.
+abstract class VM extends ServiceObjectOwner implements M.VM {
+  VM get vm => this;
+  Isolate get isolate => null;
+  WebSocketVMTarget get target;
+
+  // TODO(turnidge): The connection should not be stored in the VM object.
+  bool get isDisconnected;
+  bool get isConnected;
+
+  // Used for verbose logging.
+  bool verbose = false;
+
+  // TODO(johnmccutchan): Ensure that isolates do not end up in _cache.
+  Map<String, ServiceObject> _cache = new Map<String, ServiceObject>();
+  final Map<String, Isolate> _isolateCache = <String, Isolate>{};
+  final Map<String, IsolateGroup> _isolateGroupCache = <String, IsolateGroup>{};
+
+  // The list of live isolates, ordered by isolate start time.
+  final List<Isolate> isolates = <Isolate>[];
+  final List<Isolate> systemIsolates = <Isolate>[];
+
+  final List<IsolateGroup> isolateGroups = <IsolateGroup>[];
+  final List<IsolateGroup> systemIsolateGroups = <IsolateGroup>[];
+
+  final List<Service> services = <Service>[];
+
+  String version = 'unknown';
+  String hostCPU;
+  String targetCPU;
+  String embedder;
+  int architectureBits;
+  bool assertsEnabled = false;
+  bool typeChecksEnabled = false;
+  int nativeZoneMemoryUsage = 0;
+  int pid = 0;
+  int heapAllocatedMemoryUsage = 0;
+  int heapAllocationCount = 0;
+  int currentMemory;
+  int maxRSS;
+  int currentRSS;
+  bool profileVM = false;
+  DateTime startTime;
+  DateTime refreshTime;
+  Duration get upTime {
+    if (startTime == null) {
+      return null;
+    }
+    return (new DateTime.now().difference(startTime));
+  }
+
+  VM() : super._empty(null) {
+    updateFromServiceMap({'name': 'vm', 'type': '@VM'});
+  }
+
+  void postServiceEvent(String streamId, Map response, Uint8List data) {
+    var map = response;
+    assert(!map.containsKey('_data'));
+    if (data != null) {
+      map['_data'] = data;
+    }
+    if (map['type'] != 'Event') {
+      Logger.root.severe("Expected 'Event' but found '${map['type']}'");
+      return;
+    }
+
+    var eventIsolate = map['isolate'];
+    var event;
+    if (eventIsolate == null) {
+      event = new ServiceObject._fromMap(vm, map);
+    } else {
+      // getFromMap creates the Isolate if it hasn't been seen already.
+      var isolate = getFromMap(map['isolate']);
+      event = new ServiceObject._fromMap(isolate, map);
+      if (event.kind == ServiceEvent.kIsolateExit) {
+        _isolateCache.remove(isolate.id);
+        _buildIsolateList();
+      }
+      if (event.kind == ServiceEvent.kIsolateRunnable) {
+        // Force reload once the isolate becomes runnable so that we
+        // update the root library.
+        isolate.reload();
+      }
+    }
+    var eventStream = _eventStreams[streamId];
+    if (eventStream != null) {
+      eventStream.addEvent(event);
+    } else {
+      Logger.root.warning("Ignoring unexpected event on stream '${streamId}'");
+    }
+  }
+
+  int _compareIsolates(Isolate a, Isolate b) {
+    var aStart = a.startTime;
+    var bStart = b.startTime;
+    if (aStart == null) {
+      if (bStart == null) {
+        return 0;
+      } else {
+        return 1;
+      }
+    }
+    if (bStart == null) {
+      return -1;
+    }
+    return aStart.compareTo(bStart);
+  }
+
+  void _buildIsolateList() {
+    var isolateList =
+        _isolateCache.values.where((i) => !i.isSystemIsolate).toList();
+    isolateList.sort(_compareIsolates);
+    isolates.clear();
+    isolates.addAll(isolateList);
+
+    var systemIsolateList =
+        _isolateCache.values.where((i) => i.isSystemIsolate).toList();
+    systemIsolateList.sort(_compareIsolates);
+    systemIsolates.clear();
+    systemIsolates.addAll(systemIsolateList);
+  }
+
+  void _removeDeadIsolates(List newIsolates) {
+    // Build a set of new isolates.
+    var newIsolateSet = new Set();
+    newIsolates.forEach((iso) => newIsolateSet.add(iso.id));
+
+    // Remove any old isolates which no longer exist.
+    List toRemove = [];
+    _isolateCache.forEach((id, _) {
+      if (!newIsolateSet.contains(id)) {
+        toRemove.add(id);
+      }
+    });
+    toRemove.forEach((id) => _isolateCache.remove(id));
+    _buildIsolateList();
+  }
+
+  static final String _isolateIdPrefix = 'isolates/';
+  static final String _isolateGroupIdPrefix = 'isolateGroups/';
+
+  ServiceObject getFromMap(Map map) {
+    if (map == null) {
+      return null;
+    }
+    var type = _stripRef(map['type']);
+    if (type == 'VM') {
+      // Update this VM object.
+      updateFromServiceMap(map);
+      return this;
+    }
+
+    String id = map['id'];
+    if ((id != null)) {
+      if (id.startsWith(_isolateIdPrefix)) {
+        // Check cache.
+        var isolate = _isolateCache[id];
+        if (isolate == null) {
+          // Add new isolate to the cache.
+          isolate = ServiceObject._fromMap(this, map);
+          _isolateCache[id] = isolate;
+          _buildIsolateList();
+
+          // Eagerly load the isolate.
+          isolate.load().catchError((e, stack) {
+            Logger.root.info('Eagerly loading an isolate failed: $e\n$stack');
+          });
+        } else {
+          isolate.updateFromServiceMap(map);
+        }
+        return isolate;
+      }
+      if (id.startsWith(_isolateGroupIdPrefix)) {
+        // Check cache.
+        var isolateGroup = _isolateGroupCache[id];
+        if (isolateGroup == null) {
+          // Add new isolate to the cache.
+          isolateGroup = new ServiceObject._fromMap(this, map);
+          _isolateGroupCache[id] = isolateGroup;
+          _buildIsolateGroupList();
+
+          // Eagerly load the isolate.
+          isolateGroup.load().catchError((e, stack) {
+            Logger.root
+                .info('Eagerly loading an isolate group failed: $e\n$stack');
+          });
+        } else {
+          isolateGroup.updateFromServiceMap(map);
+        }
+        return isolateGroup;
+      }
+    }
+
+    // Build the object from the map directly.
+    return new ServiceObject._fromMap(this, map);
+  }
+
+  // Note that this function does not reload the isolate if it found
+  // in the cache.
+  Future<Isolate> getIsolate(String isolateId) {
+    if (!loaded) {
+      // Trigger a VM load, then get the isolate.
+      return load().then((_) => getIsolate(isolateId)).catchError(_ignoreError);
+    }
+    return new Future.value(_isolateCache[isolateId]);
+  }
+
+  int _compareIsolateGroups(IsolateGroup a, IsolateGroup b) {
+    return a.id.compareTo(b.id);
+  }
+
+  void _buildIsolateGroupList() {
+    final isolateGroupList = _isolateGroupCache.values
+        .where((g) => !g.isSystemIsolateGroup)
+        .toList();
+    isolateGroupList.sort(_compareIsolateGroups);
+    isolateGroups.clear();
+    isolateGroups.addAll(isolateGroupList);
+
+    final systemIsolateGroupList =
+        _isolateGroupCache.values.where((g) => g.isSystemIsolateGroup).toList();
+    systemIsolateGroupList.sort(_compareIsolateGroups);
+    systemIsolateGroups.clear();
+    systemIsolateGroups.addAll(systemIsolateGroupList);
+  }
+
+  void _removeDeadIsolateGroups(List newIsolateGroups) {
+    // Build a set of new isolates.
+    final Set newIsolateGroupSet =
+        newIsolateGroups.map((iso) => iso.id).toSet();
+
+    // Remove any old isolates which no longer exist.
+    _isolateGroupCache.removeWhere((id, _) => !newIsolateGroupSet.contains(id));
+    _buildIsolateGroupList();
+  }
+
+  // Implemented in subclass.
+  Future<Map> invokeRpcRaw(String method, Map params);
+
+  Future<Map> invokeRpcNoUpgrade(String method, Map params) {
+    return invokeRpcRaw(method, params).then<Map>((Map response) {
+      var map = response;
+      if (Tracer.current != null) {
+        Tracer.current
+            .trace("Received response for ${method}/${params}}", map: map);
+      }
+      if (!_isServiceMap(map)) {
+        var exception = new MalformedResponseRpcException(
+            "Response is missing the 'type' field", map);
+        return new Future.error(exception);
+      }
+      return new Future<Map>.value(map);
+    }).catchError((e) {
+      // Errors pass through.
+      return new Future<Map>.error(e);
+    });
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params)
+        .then<ServiceObject>((Map response) {
+      var obj = new ServiceObject._fromMap(this, response);
+      if ((obj != null) && obj.canCache) {
+        String objId = obj.id;
+        _cache.putIfAbsent(objId, () => obj);
+      }
+      return obj;
+    }).catchError((e) {
+      return new Future<ServiceObject>.error(e);
+    });
+  }
+
+  void _dispatchEventToIsolate(ServiceEvent event) {
+    var isolate = event.isolate;
+    if (isolate != null) {
+      isolate._onEvent(event);
+    }
+  }
+
+  void _updateService(ServiceEvent event) {
+    switch (event.kind) {
+      case ServiceEvent.kServiceRegistered:
+        services.add(new Service(event.alias, event.method, event.service));
+        break;
+      case ServiceEvent.kServiceUnregistered:
+        services.removeWhere((s) => s.method == event.method);
+        break;
+    }
+  }
+
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) async {
+    if (!loaded) {
+      // The vm service relies on these events to keep the VM and
+      // Isolate types up to date.
+      try {
+        await listenEventStream(kVMStream, _dispatchEventToIsolate);
+        await listenEventStream(kIsolateStream, _dispatchEventToIsolate);
+        await listenEventStream(kDebugStream, _dispatchEventToIsolate);
+        await listenEventStream(kHeapSnapshotStream, _dispatchEventToIsolate);
+        await listenEventStream(kServiceStream, _updateService);
+      } on NetworkRpcException catch (_) {
+        // ignore network errors here.
+      }
+    }
+    return await invokeRpcNoUpgrade('getVM', {});
+  }
+
+  Future setName(String newName) {
+    return invokeRpc('setVMName', {'name': newName});
+  }
+
+  Future<ServiceObject> getFlagList() {
+    return invokeRpc('getFlagList', {});
+  }
+
+  Future enableProfiler() {
+    return invokeRpc("_enableProfiler", {});
+  }
+
+  Future<ServiceObject> _streamListen(String streamId) {
+    Map params = {
+      'streamId': streamId,
+    };
+    // Ignore network errors on stream listen.
+    return invokeRpc('streamListen', params)
+        .catchError((e) => ignoreNetworkErrors(e));
+  }
+
+  Future<ServiceObject> _streamCancel(String streamId) {
+    Map params = {
+      'streamId': streamId,
+    };
+    // Ignore network errors on stream cancel.
+    return invokeRpc('streamCancel', params)
+        .catchError((e) => ignoreNetworkErrors(e));
+  }
+
+  // A map from stream id to event stream state.
+  Map<String, _EventStreamState> _eventStreams = {};
+
+  // Well-known stream ids.
+  static const kVMStream = 'VM';
+  static const kIsolateStream = 'Isolate';
+  static const kTimelineStream = 'Timeline';
+  static const kDebugStream = 'Debug';
+  static const kGCStream = 'GC';
+  static const kStdoutStream = 'Stdout';
+  static const kStderrStream = 'Stderr';
+  static const kHeapSnapshotStream = 'HeapSnapshot';
+  static const kServiceStream = 'Service';
+
+  /// Returns a single-subscription Stream object for a VM event stream.
+  Future<Stream<ServiceEvent>> getEventStream(String streamId) async {
+    var eventStream = _eventStreams.putIfAbsent(
+        streamId,
+        () => new _EventStreamState(
+            this, streamId, () => _eventStreams.remove(streamId)));
+    Stream<ServiceEvent> stream = await eventStream.addStream();
+    return stream;
+  }
+
+  /// Helper function for listening to an event stream.
+  Future<StreamSubscription> listenEventStream(
+      String streamId, Function function) async {
+    var stream = await getEventStream(streamId);
+    return stream.listen(function);
+  }
+
+  /// Force the VM to disconnect.
+  void disconnect();
+
+  /// Completes when the VM first connects.
+  Future get onConnect;
+
+  /// Completes when the VM disconnects or there was an error connecting.
+  Future<String> get onDisconnect;
+
+  void _update(Map map, bool mapIsRef) {
+    name = map['name'];
+    vmName = map.containsKey('_vmName') ? map['_vmName'] : name;
+    if (mapIsRef) {
+      return;
+    }
+    // Note that upgrading the collection creates any isolates in the
+    // isolate list which are new.
+    _upgradeCollection(map, vm);
+
+    _loaded = true;
+    version = map['version'];
+    hostCPU = map['hostCPU'];
+    targetCPU = map['targetCPU'];
+    architectureBits = map['architectureBits'];
+    int startTimeMillis = map['startTime'];
+    startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeMillis);
+    refreshTime = new DateTime.now();
+    if (map['_nativeZoneMemoryUsage'] != null) {
+      nativeZoneMemoryUsage = map['_nativeZoneMemoryUsage'];
+    }
+    pid = map['pid'];
+    heapAllocatedMemoryUsage = map['_heapAllocatedMemoryUsage'];
+    heapAllocationCount = map['_heapAllocationCount'];
+    embedder = map['_embedder'];
+    currentMemory = map['_currentMemory'];
+    maxRSS = map['_maxRSS'];
+    currentRSS = map['_currentRSS'];
+    profileVM = map['_profilerMode'] == 'VM';
+    assertsEnabled = map['_assertsEnabled'];
+    typeChecksEnabled = map['_typeChecksEnabled'];
+    _removeDeadIsolates([
+      ...map['isolates'],
+      ...map['systemIsolates'],
+    ]);
+    _removeDeadIsolateGroups([
+      ...map['isolateGroups'],
+      ...map['systemIsolateGroups'],
+    ]);
+  }
+
+  // Reload all isolates.
+  Future reloadIsolates() {
+    var reloads = <Future>[];
+    for (var isolate in isolates) {
+      var reload = isolate.reload().catchError((e) {
+        Logger.root.info('Bulk reloading of isolates failed: $e');
+      });
+      reloads.add(reload);
+    }
+    return Future.wait(reloads);
+  }
+}
+
+/// Snapshot in time of tag counters.
+class TagProfileSnapshot {
+  final double seconds;
+  final List<int> counters;
+  int get sum => _sum;
+  int _sum = 0;
+  TagProfileSnapshot(this.seconds, int countersLength)
+      : counters = new List<int>.filled(countersLength, 0);
+
+  /// Set [counters] and update [sum].
+  void set(List<int> counters) {
+    this.counters.setAll(0, counters);
+    for (var i = 0; i < this.counters.length; i++) {
+      _sum += this.counters[i];
+    }
+  }
+
+  /// Set [counters] with the delta from [counters] to [old_counters]
+  /// and update [sum].
+  void delta(List<int> counters, List<int> old_counters) {
+    for (var i = 0; i < this.counters.length; i++) {
+      this.counters[i] = counters[i] - old_counters[i];
+      _sum += this.counters[i];
+    }
+  }
+
+  /// Update [counters] with new maximum values seen in [counters].
+  void max(List<int> counters) {
+    for (var i = 0; i < counters.length; i++) {
+      var c = counters[i];
+      this.counters[i] = this.counters[i] > c ? this.counters[i] : c;
+    }
+  }
+
+  /// Zero [counters].
+  void zero() {
+    for (var i = 0; i < counters.length; i++) {
+      counters[i] = 0;
+    }
+  }
+}
+
+class TagProfile {
+  final List<String> names = <String>[];
+  final List<TagProfileSnapshot> snapshots = <TagProfileSnapshot>[];
+  double get updatedAtSeconds => _seconds;
+  double _seconds;
+  TagProfileSnapshot _maxSnapshot;
+  int _historySize;
+  int _countersLength = 0;
+
+  TagProfile(this._historySize);
+
+  void _processTagProfile(double seconds, Map tagProfile) {
+    _seconds = seconds;
+    var counters = tagProfile['counters'];
+    if (names.length == 0) {
+      // Initialization.
+      names.addAll(tagProfile['names']);
+      _countersLength = tagProfile['counters'].length;
+      for (var i = 0; i < _historySize; i++) {
+        var snapshot = new TagProfileSnapshot(0.0, _countersLength);
+        snapshot.zero();
+        snapshots.add(snapshot);
+      }
+      // The counters monotonically grow, keep track of the maximum value.
+      _maxSnapshot = new TagProfileSnapshot(0.0, _countersLength);
+      _maxSnapshot.set(counters);
+      return;
+    }
+    var snapshot = new TagProfileSnapshot(seconds, _countersLength);
+    // We snapshot the delta from the current counters to the maximum counter
+    // values.
+    snapshot.delta(counters, _maxSnapshot.counters);
+    _maxSnapshot.max(counters);
+    snapshots.add(snapshot);
+    // Only keep _historySize snapshots.
+    if (snapshots.length > _historySize) {
+      snapshots.removeAt(0);
+    }
+  }
+}
+
+class InboundReferences implements M.InboundReferences {
+  final Iterable<InboundReference> elements;
+
+  InboundReferences(ServiceMap map)
+      : this.elements = map['references']
+            .map<InboundReference>((rmap) => new InboundReference(rmap))
+            .toList();
+}
+
+class InboundReference implements M.InboundReference {
+  final ServiceObject /*HeapObject*/ source;
+  final HeapObject parentField;
+  final int parentListIndex;
+  final int parentWordOffset;
+
+  InboundReference(Map map)
+      : source = map['source'],
+        parentField = map['parentField'],
+        parentListIndex = map['parentListIndex'],
+        parentWordOffset = map['_parentWordOffset'];
+}
+
+class RetainingPath implements M.RetainingPath {
+  final Iterable<RetainingPathItem> elements;
+  final String gcRootType;
+
+  RetainingPath(ServiceMap map)
+      : this.elements = map['elements']
+            .map<RetainingPathItem>((rmap) => new RetainingPathItem(rmap))
+            .toList(),
+        this.gcRootType = map['gcRootType'];
+}
+
+class RetainingPathItem implements M.RetainingPathItem {
+  final ServiceObject /*HeapObject*/ source;
+  final String parentField;
+  final int parentListIndex;
+  final int parentWordOffset;
+
+  RetainingPathItem(Map map)
+      : source = map['value'],
+        parentField = map['parentField'],
+        parentListIndex = map['parentListIndex'],
+        parentWordOffset = map['_parentWordOffset'];
+}
+
+class Ports implements M.Ports {
+  final Iterable<Port> elements;
+
+  Ports(ServiceMap map)
+      : this.elements =
+            map['ports'].map<Port>((rmap) => new Port(rmap)).toList();
+}
+
+class Port implements M.Port {
+  final String name;
+  final HeapObject handler;
+
+  Port(ServiceMap map)
+      : name = map['name'],
+        handler = map['handler'];
+}
+
+class PersistentHandles implements M.PersistentHandles {
+  final Iterable<PersistentHandle> elements;
+  final Iterable<WeakPersistentHandle> weakElements;
+
+  PersistentHandles(ServiceMap map)
+      : this.elements = map['persistentHandles']
+            .map<PersistentHandle>((rmap) => new PersistentHandle(rmap))
+            .toList(),
+        this.weakElements = map['weakPersistentHandles']
+            .map<WeakPersistentHandle>((rmap) => new WeakPersistentHandle(rmap))
+            .toList();
+}
+
+class PersistentHandle implements M.PersistentHandle {
+  final HeapObject object;
+
+  PersistentHandle(ServiceMap map) : object = map['object'];
+}
+
+class WeakPersistentHandle implements M.WeakPersistentHandle {
+  final int externalSize;
+  final String peer;
+  final String callbackSymbolName;
+  final String callbackAddress;
+  final HeapObject object;
+
+  WeakPersistentHandle(ServiceMap map)
+      : externalSize = int.parse(map['externalSize']),
+        peer = map['peer'],
+        callbackSymbolName = map['callbackSymbolName'],
+        callbackAddress = map['callbackAddress'],
+        object = map['object'];
+}
+
+class HeapSpace implements M.HeapSpace {
+  int used = 0;
+  int capacity = 0;
+  int external = 0;
+  int collections = 0;
+  double totalCollectionTimeInSeconds = 0.0;
+  double averageCollectionPeriodInMillis = 0.0;
+
+  Duration get avgCollectionTime {
+    final mcs = totalCollectionTimeInSeconds *
+        Duration.microsecondsPerSecond /
+        math.max(collections, 1);
+    return new Duration(microseconds: mcs.ceil());
+  }
+
+  Duration get totalCollectionTime {
+    final mcs = totalCollectionTimeInSeconds * Duration.microsecondsPerSecond;
+    return new Duration(microseconds: mcs.ceil());
+  }
+
+  Duration get avgCollectionPeriod {
+    final mcs =
+        averageCollectionPeriodInMillis * Duration.microsecondsPerMillisecond;
+    return new Duration(microseconds: mcs.ceil());
+  }
+
+  void update(Map heapMap) {
+    used = heapMap['used'];
+    capacity = heapMap['capacity'];
+    external = heapMap['external'];
+    collections = heapMap['collections'];
+    totalCollectionTimeInSeconds = heapMap['time'];
+    averageCollectionPeriodInMillis = heapMap['avgCollectionPeriodMillis'];
+  }
+
+  void add(HeapSpace other) {
+    used += other.used;
+    capacity += other.capacity;
+    external += other.external;
+    collections += other.collections;
+    totalCollectionTimeInSeconds += other.totalCollectionTimeInSeconds;
+    if (collections == 0) {
+      averageCollectionPeriodInMillis = 0.0;
+    } else {
+      averageCollectionPeriodInMillis =
+          (totalCollectionTimeInSeconds / collections) * 1000.0;
+    }
+  }
+}
+
+class IsolateGroup extends ServiceObjectOwner implements M.IsolateGroup {
+  IsolateGroup._empty(ServiceObjectOwner owner)
+      : assert(owner is VM),
+        super._empty(owner);
+
+  @override
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, vm);
+    name = map['name'];
+    vmName = map.containsKey('_vmName') ? map['_vmName'] : name;
+    number = int.tryParse(map['number']);
+    isSystemIsolateGroup = map['isSystemIsolateGroup'];
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    isolates.clear();
+    for (var isolate in map['isolates']) {
+      isolates.add(isolate);
+    }
+    isolates.sort(ServiceObject.LexicalSortName);
+    vm._buildIsolateGroupList();
+  }
+
+  @override
+  ServiceObject getFromMap(Map map) {
+    if (map == null) {
+      return null;
+    }
+    final mapType = _stripRef(map['type']);
+    if (mapType == 'IsolateGroup') {
+      // There are sometimes isolate group refs in ServiceEvents.
+      return vm.getFromMap(map);
+    }
+    String mapId = map['id'];
+    var obj = (mapId != null) ? _cache[mapId] : null;
+    if (obj != null) {
+      obj.updateFromServiceMap(map);
+      return obj;
+    }
+    // Build the object from the map directly.
+    obj = new ServiceObject._fromMap(this, map);
+    if ((obj != null) && obj.canCache) {
+      _cache[mapId] = obj;
+    }
+    return obj;
+  }
+
+  Future<Map> invokeRpcNoUpgrade(String method, Map params) {
+    params['isolateGroupId'] = id;
+    return vm.invokeRpcNoUpgrade(method, params);
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params)
+        .then((Map response) => getFromMap(response));
+  }
+
+  @override
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) {
+    Map params = {
+      'isolateGroupId': id,
+    };
+    return vm.invokeRpcNoUpgrade('getIsolateGroup', params);
+  }
+
+  @override
+  final List<Isolate> isolates = <Isolate>[];
+
+  @override
+  int number;
+
+  bool isSystemIsolateGroup;
+
+  final Map<String, ServiceObject> _cache = Map<String, ServiceObject>();
+}
+
+/// State for a running isolate.
+class Isolate extends ServiceObjectOwner implements M.Isolate {
+  static const kLoggingStream = 'Logging';
+  static const kExtensionStream = 'Extension';
+
+  VM get vm => owner;
+  Isolate get isolate => this;
+  int number;
+  int originNumber;
+  DateTime startTime;
+  Duration get upTime {
+    if (startTime == null) {
+      return null;
+    }
+    return (new DateTime.now().difference(startTime));
+  }
+
+  Map counters = {};
+
+  void _updateRunState() {
+    topFrame = M.topFrame(pauseEvent);
+    paused = (pauseEvent != null && !(pauseEvent is M.ResumeEvent));
+    running = (!paused && topFrame != null);
+    idle = (!paused && topFrame == null);
+  }
+
+  M.DebugEvent pauseEvent = null;
+  bool paused = false;
+  bool running = false;
+  bool idle = false;
+  bool loading = true;
+  bool runnable = false;
+  bool ioEnabled = false;
+  M.IsolateStatus get status {
+    if (paused) {
+      return M.IsolateStatus.paused;
+    }
+    if (running) {
+      return M.IsolateStatus.running;
+    }
+    if (idle) {
+      return M.IsolateStatus.idle;
+    }
+    return M.IsolateStatus.loading;
+  }
+
+  final List<String> extensionRPCs = <String>[];
+
+  Map<String, ServiceObject> _cache = new Map<String, ServiceObject>();
+  final TagProfile tagProfile = new TagProfile(20);
+
+  Isolate._empty(ServiceObjectOwner owner) : super._empty(owner) {
+    assert(owner is VM);
+  }
+
+  void resetCachedProfileData() {
+    _cache.values.forEach((value) {
+      if (value is Code) {
+        Code code = value;
+        code.profile = null;
+      } else if (value is ServiceFunction) {
+        ServiceFunction function = value;
+        function.profile = null;
+      }
+    });
+  }
+
+  static const kCallSitesReport = '_CallSites';
+  static const kPossibleBreakpointsReport = 'PossibleBreakpoints';
+  static const kProfileReport = '_Profile';
+
+  Future<ServiceObject> getSourceReport(List<String> report_kinds,
+      [Script script, int startPos, int endPos]) {
+    var params = <String, dynamic>{'reports': report_kinds};
+    if (script != null) {
+      params['scriptId'] = script.id;
+    }
+    if (startPos != null) {
+      params['tokenPos'] = startPos;
+    }
+    if (endPos != null) {
+      params['endTokenPos'] = endPos;
+    }
+    return invokeRpc('getSourceReport', params);
+  }
+
+  Future<ServiceMap> reloadSources(
+      {String rootLibUri, String packagesUri, bool pause}) {
+    Map<String, dynamic> params = <String, dynamic>{};
+    if (rootLibUri != null) {
+      params['rootLibUri'] = rootLibUri;
+    }
+    if (packagesUri != null) {
+      params['packagesUri'] = packagesUri;
+    }
+    if (pause != null) {
+      params['pause'] = pause;
+    }
+    return invokeRpc('reloadSources', params).then((result) {
+      _cache.clear();
+      return result as ServiceMap;
+    });
+  }
+
+  void _handleIsolateReloadEvent(ServiceEvent event) {
+    if (event.reloadError == null) {
+      _cache.clear();
+    }
+  }
+
+  Future collectAllGarbage() {
+    return invokeRpc('_collectAllGarbage', {});
+  }
+
+  /// Fetches and builds the class hierarchy for this isolate. Returns the
+  /// Object class object.
+  Future<Class> getClassHierarchy() async {
+    var classRefs = await invokeRpc('getClassList', {});
+    var classes = await _loadClasses(classRefs);
+    return _buildClassHierarchy(classes);
+  }
+
+  Future<ServiceObject> getPorts() {
+    return invokeRpc('_getPorts', {});
+  }
+
+  Future<ServiceObject> getPersistentHandles() {
+    return invokeRpc('_getPersistentHandles', {});
+  }
+
+  /// Given the class list, loads each class.
+  Future<List<Class>> _loadClasses(ServiceMap classList) {
+    assert(classList.type == 'ClassList');
+    var futureClasses = <Future<Class>>[];
+    for (var cls in classList['classes']) {
+      // Skip over non-class classes.
+      if (cls is Class) {
+        futureClasses.add(cls.load().then<Class>((_) => cls));
+      }
+    }
+    return Future.wait(futureClasses);
+  }
+
+  /// Builds the class hierarchy and returns the Object class.
+  Future<Class> _buildClassHierarchy(List<Class> classes) {
+    rootClasses.clear();
+    objectClass = null;
+    for (var cls in classes) {
+      if (cls.superclass == null) {
+        rootClasses.add(cls);
+      }
+      if ((cls.vmName == 'Object') &&
+          (cls.isPatch == false) &&
+          (cls.library.uri == 'dart:core')) {
+        objectClass = cls;
+      }
+    }
+    assert(objectClass != null);
+    return new Future.value(objectClass);
+  }
+
+  ServiceObject getFromMap(Map map) {
+    if (map == null) {
+      return null;
+    }
+    var mapType = _stripRef(map['type']);
+    if (mapType == 'Isolate') {
+      // There are sometimes isolate refs in ServiceEvents.
+      return vm.getFromMap(map);
+    }
+    String mapId = map['id'];
+    var obj = (mapId != null) ? _cache[mapId] : null;
+    if (obj != null) {
+      obj.updateFromServiceMap(map);
+      return obj;
+    }
+    // Build the object from the map directly.
+    obj = new ServiceObject._fromMap(this, map);
+    if ((obj != null) && obj.canCache) {
+      _cache[mapId] = obj;
+    }
+    return obj;
+  }
+
+  Future<Map> invokeRpcNoUpgrade(String method, Map params) {
+    params['isolateId'] = id;
+    return vm.invokeRpcNoUpgrade(method, params);
+  }
+
+  Future<ServiceObject> invokeRpc(String method, Map params) {
+    return invokeRpcNoUpgrade(method, params).then((Map response) {
+      return getFromMap(response);
+    });
+  }
+
+  Future<ServiceObject> getObject(String objectId,
+      {bool reload: true, int count: kDefaultFieldLimit}) {
+    assert(objectId != null && objectId != '');
+    var obj = _cache[objectId];
+    if (obj != null) {
+      if (reload) {
+        return obj.reload(count: count);
+      }
+      // Returned cached object.
+      return new Future.value(obj);
+    }
+    Map params = {
+      'objectId': objectId,
+      'count': count,
+    };
+    return isolate.invokeRpc('getObject', params);
+  }
+
+  Future<List<Script>> getScripts() async {
+    final response = await invokeRpc('getScripts', {}) as ServiceMap;
+    assert(response.type == 'ScriptList');
+    return response['scripts'].cast<Script>();
+  }
+
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) async {
+    return invokeRpcNoUpgrade('getIsolate', {});
+  }
+
+  Class objectClass;
+  final rootClasses = <Class>[];
+
+  Library rootLibrary;
+  List<Library> libraries = <Library>[];
+  Frame topFrame;
+
+  String name;
+  String vmName;
+  ServiceFunction entry;
+
+  final HeapSpace newSpace = new HeapSpace();
+  final HeapSpace oldSpace = new HeapSpace();
+
+  String fileAndLine;
+
+  DartError error;
+  SnapshotReader _snapshotFetch;
+
+  List<Thread> get threads => _threads;
+  final List<Thread> _threads = <Thread>[];
+
+  int get zoneHighWatermark => _zoneHighWatermark;
+  int _zoneHighWatermark = 0;
+
+  int get numZoneHandles => _numZoneHandles;
+  int _numZoneHandles;
+
+  int get numScopedHandles => _numScopedHandles;
+  int _numScopedHandles;
+
+  bool isSystemIsolate;
+
+  void _loadHeapSnapshot(ServiceEvent event) {
+    if (_snapshotFetch == null) {
+      // No outstanding snapshot request. Presumably another client asked for a
+      // snapshot.
+      Logger.root.info("Dropping unsolicited heap snapshot chunk");
+      return;
+    }
+
+    // Occasionally these actually arrive out of order.
+    _snapshotFetch.add(event.data);
+    if (event.lastChunk) {
+      _snapshotFetch.close();
+      _snapshotFetch = null;
+    }
+  }
+
+  SnapshotReader fetchHeapSnapshot() {
+    if (_snapshotFetch == null) {
+      _snapshotFetch = new SnapshotReader();
+      // isolate.vm.streamListen('HeapSnapshot');
+      isolate.invokeRpcNoUpgrade('requestHeapSnapshot', {});
+    }
+    return _snapshotFetch;
+  }
+
+  void updateHeapsFromMap(Map map) {
+    newSpace.update(map['new']);
+    oldSpace.update(map['old']);
+  }
+
+  void _update(Map map, bool mapIsRef) {
+    name = map['name'];
+    vmName = map.containsKey('_vmName') ? map['_vmName'] : name;
+    number = int.tryParse(map['number']);
+    isSystemIsolate = map['isSystemIsolate'];
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    loading = false;
+    runnable = map['runnable'] == true;
+    _upgradeCollection(map, isolate);
+    originNumber = int.tryParse(map['_originNumber']);
+    rootLibrary = map['rootLib'];
+    if (map['entry'] != null) {
+      entry = map['entry'];
+    }
+    var savedStartTime = startTime;
+    int startTimeInMillis = map['startTime'];
+    startTime = new DateTime.fromMillisecondsSinceEpoch(startTimeInMillis);
+    var countersMap = map['_tagCounters'];
+    if (countersMap != null) {
+      var names = countersMap['names'];
+      var counts = countersMap['counters'];
+      assert(names.length == counts.length);
+      var sum = 0;
+      for (var i = 0; i < counts.length; i++) {
+        sum += counts[i];
+      }
+      var _counters = {};
+      if (sum == 0) {
+        for (var i = 0; i < names.length; i++) {
+          _counters[names[i]] = '0.0%';
+        }
+      } else {
+        for (var i = 0; i < names.length; i++) {
+          _counters[names[i]] =
+              (counts[i] / sum * 100.0).toStringAsFixed(2) + '%';
+        }
+      }
+      counters = _counters;
+    }
+
+    updateHeapsFromMap(map['_heaps']);
+    _updateBreakpoints(map['breakpoints']);
+    if (map['_debuggerSettings'] != null) {
+      exceptionsPauseInfo = map['_debuggerSettings']['_exceptions'];
+    } else {
+      exceptionsPauseInfo = "none";
+    }
+
+    var newPauseEvent = map['pauseEvent'];
+    assert((pauseEvent == null) ||
+        (newPauseEvent == null) ||
+        !newPauseEvent.timestamp.isBefore(pauseEvent.timestamp));
+    pauseEvent = createEventFromServiceEvent(newPauseEvent);
+    _updateRunState();
+    error = map['error'];
+
+    libraries.clear();
+    for (Library l in map['libraries']) libraries.add(l);
+    libraries.sort(ServiceObject.LexicalSortName);
+    if (savedStartTime == null) {
+      vm._buildIsolateList();
+    }
+
+    extensionRPCs.clear();
+    if (map['extensionRPCs'] != null) {
+      for (String e in map['extensionRPCs']) extensionRPCs.add(e);
+    }
+
+    threads.clear();
+    if (map['_threads'] != null) {
+      for (Thread t in map['_threads']) threads.add(t);
+    }
+
+    int currentZoneHighWatermark = 0;
+    for (var i = 0; i < threads.length; i++) {
+      currentZoneHighWatermark += threads[i].zoneHighWatermark;
+    }
+
+    if (currentZoneHighWatermark > _zoneHighWatermark) {
+      _zoneHighWatermark = currentZoneHighWatermark;
+    }
+
+    _numZoneHandles = map['_numZoneHandles'];
+    _numScopedHandles = map['_numScopedHandles'];
+  }
+
+  Future<TagProfile> updateTagProfile() {
+    return isolate.invokeRpcNoUpgrade('_getTagProfile', {}).then((Map map) {
+      var seconds = new DateTime.now().millisecondsSinceEpoch / 1000.0;
+      tagProfile._processTagProfile(seconds, map);
+      return tagProfile;
+    });
+  }
+
+  Map<int, Breakpoint> breakpoints = <int, Breakpoint>{};
+  String exceptionsPauseInfo;
+
+  void _updateBreakpoints(List newBpts) {
+    // Build a set of new breakpoints.
+    var newBptSet = new Set();
+    newBpts.forEach((bpt) => newBptSet.add(bpt.number));
+
+    // Remove any old breakpoints which no longer exist.
+    List toRemove = [];
+    breakpoints.forEach((key, _) {
+      if (!newBptSet.contains(key)) {
+        toRemove.add(key);
+      }
+    });
+    toRemove.forEach((key) => breakpoints.remove(key));
+
+    // Add all new breakpoints.
+    newBpts.forEach((bpt) => (breakpoints[bpt.number] = bpt));
+  }
+
+  void _addBreakpoint(Breakpoint bpt) {
+    breakpoints[bpt.number] = bpt;
+  }
+
+  void _removeBreakpoint(Breakpoint bpt) {
+    breakpoints.remove(bpt.number);
+    bpt.remove();
+  }
+
+  void _onEvent(ServiceEvent event) {
+    switch (event.kind) {
+      case ServiceEvent.kIsolateStart:
+      case ServiceEvent.kIsolateRunnable:
+      case ServiceEvent.kIsolateExit:
+      case ServiceEvent.kInspect:
+        // Handled elsewhere.
+        break;
+      case ServiceEvent.kIsolateReload:
+        _handleIsolateReloadEvent(event);
+        break;
+      case ServiceEvent.kBreakpointAdded:
+        _addBreakpoint(event.breakpoint);
+        break;
+
+      case ServiceEvent.kIsolateUpdate:
+      case ServiceEvent.kBreakpointResolved:
+      case ServiceEvent.kDebuggerSettingsUpdate:
+        // Update occurs as side-effect of caching.
+        break;
+
+      case ServiceEvent.kBreakpointRemoved:
+        _removeBreakpoint(event.breakpoint);
+        break;
+
+      case ServiceEvent.kPauseStart:
+      case ServiceEvent.kPauseExit:
+      case ServiceEvent.kPauseBreakpoint:
+      case ServiceEvent.kPauseInterrupted:
+      case ServiceEvent.kPauseException:
+      case ServiceEvent.kPausePostRequest:
+      case ServiceEvent.kNone:
+      case ServiceEvent.kResume:
+        assert((pauseEvent == null) ||
+            !event.timestamp.isBefore(pauseEvent.timestamp));
+        pauseEvent = createEventFromServiceEvent(event);
+        _updateRunState();
+        break;
+
+      case ServiceEvent.kHeapSnapshot:
+        _loadHeapSnapshot(event);
+        break;
+
+      case ServiceEvent.kGC:
+        // Ignore GC events for now.
+        break;
+
+      default:
+        // Log unexpected events.
+        Logger.root.severe('Unexpected event: $event');
+        break;
+    }
+  }
+
+  Future<Breakpoint> addBreakpoint(Script script, int line, [int col]) {
+    Map params = {
+      'scriptId': script.id,
+      'line': line,
+    };
+    if (col != null) {
+      params['column'] = col;
+    }
+    return invokeRpc('addBreakpoint', params)
+        .then((result) => result as Breakpoint);
+  }
+
+  Future<Breakpoint> addBreakpointByScriptUri(String uri, int line, [int col]) {
+    Map params = {
+      'scriptUri': uri,
+      'line': line.toString(),
+    };
+    if (col != null) {
+      params['column'] = col.toString();
+    }
+    return invokeRpc('addBreakpointWithScriptUri', params)
+        .then((result) => result as Breakpoint);
+  }
+
+  Future<Breakpoint> addBreakpointAtEntry(ServiceFunction function) {
+    return invokeRpc('addBreakpointAtEntry', {'functionId': function.id})
+        .then((result) => result as Breakpoint);
+  }
+
+  Future<Breakpoint> addBreakOnActivation(Instance closure) {
+    return invokeRpc('_addBreakpointAtActivation', {'objectId': closure.id})
+        .then((result) => result as Breakpoint);
+  }
+
+  Future removeBreakpoint(Breakpoint bpt) {
+    return invokeRpc('removeBreakpoint', {'breakpointId': bpt.id});
+  }
+
+  Future pause() {
+    return invokeRpc('pause', {});
+  }
+
+  Future resume() {
+    return invokeRpc('resume', {});
+  }
+
+  Future stepInto() {
+    return invokeRpc('resume', {'step': 'Into'});
+  }
+
+  Future stepOver() {
+    return invokeRpc('resume', {'step': 'Over'});
+  }
+
+  Future stepOverAsyncSuspension() {
+    return invokeRpc('resume', {'step': 'OverAsyncSuspension'});
+  }
+
+  Future stepOut() {
+    return invokeRpc('resume', {'step': 'Out'});
+  }
+
+  Future rewind(int count) {
+    return invokeRpc('resume', {'step': 'Rewind', 'frameIndex': count});
+  }
+
+  Future setName(String newName) {
+    return invokeRpc('setName', {'name': newName});
+  }
+
+  Future setExceptionPauseMode(String mode) {
+    return invokeRpc('setExceptionPauseMode', {'mode': mode});
+  }
+
+  Future<ServiceMap> getStack() {
+    return invokeRpc('getStack', {}).then((response) => response as ServiceMap);
+  }
+
+  Future<ObjectStore> getObjectStore() {
+    return invokeRpcNoUpgrade('_getObjectStore', {}).then((map) {
+      ObjectStore objectStore = new ObjectStore._empty(this);
+      objectStore._update(map, false);
+      return objectStore;
+    });
+  }
+
+  Future<ServiceObject> invoke(ServiceObject target, String selector,
+      [List<ServiceObject> arguments = const <ServiceObject>[]]) {
+    Map params = {
+      'targetId': target.id,
+      'selector': selector,
+      'argumentIds': arguments.map((arg) => arg.id).toList(),
+    };
+    return invokeRpc('invoke', params);
+  }
+
+  Future<ServiceObject> eval(ServiceObject target, String expression,
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+    Map params = {
+      'targetId': target.id,
+      'expression': expression,
+      'disableBreakpoints': disableBreakpoints,
+    };
+    if (scope != null) {
+      Map<String, String> scopeWithIds = new Map();
+      scope.forEach((String name, ServiceObject object) {
+        scopeWithIds[name] = object.id;
+      });
+      params["scope"] = scopeWithIds;
+    }
+    return invokeRpc('evaluate', params);
+  }
+
+  Future<ServiceObject> evalFrame(int frameIndex, String expression,
+      {Map<String, ServiceObject> scope,
+      bool disableBreakpoints: false}) async {
+    Map params = {
+      'frameIndex': frameIndex,
+      'expression': expression,
+      'disableBreakpoints': disableBreakpoints,
+    };
+    if (scope != null) {
+      Map<String, String> scopeWithIds = new Map();
+      scope.forEach((String name, ServiceObject object) {
+        scopeWithIds[name] = object.id;
+      });
+      params["scope"] = scopeWithIds;
+    }
+
+    try {
+      return await invokeRpc('evaluateInFrame', params);
+    } on ServerRpcException catch (error) {
+      if (error.code == ServerRpcException.kExpressionCompilationError) {
+        Map map = {
+          'type': 'Error',
+          'message': error.data.toString(),
+          'kind': 'LanguageError',
+          'exception': null,
+          'stacktrace': null,
+        };
+        return new ServiceObject._fromMap(null, map);
+      } else
+        rethrow;
+    }
+  }
+
+  Future<ServiceObject> getReachableSize(ServiceObject target) {
+    Map params = {
+      'targetId': target.id,
+    };
+    return invokeRpc('_getReachableSize', params);
+  }
+
+  Future<ServiceObject> getRetainedSize(ServiceObject target) {
+    Map params = {
+      'targetId': target.id,
+    };
+    return invokeRpc('_getRetainedSize', params);
+  }
+
+  Future<ServiceObject> getRetainingPath(ServiceObject target, var limit) {
+    Map params = {
+      'targetId': target.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getRetainingPath', params);
+  }
+
+  Future<ServiceObject> getInboundReferences(ServiceObject target, var limit) {
+    Map params = {
+      'targetId': target.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getInboundReferences', params);
+  }
+
+  Future<ServiceObject> getTypeArgumentsList(bool onlyWithInstantiations) {
+    Map params = {
+      'onlyWithInstantiations': onlyWithInstantiations,
+    };
+    return invokeRpc('_getTypeArgumentsList', params);
+  }
+
+  Future<ServiceObject> getInstances(Class cls, var limit) {
+    Map params = {
+      'objectId': cls.id,
+      'limit': limit.toString(),
+    };
+    return invokeRpc('getInstances', params);
+  }
+
+  final Map<String, ServiceMetric> dartMetrics = <String, ServiceMetric>{};
+
+  final Map<String, ServiceMetric> nativeMetrics = <String, ServiceMetric>{};
+
+  Future<Map<String, ServiceMetric>> _refreshMetrics(
+      String metricType, Map<String, ServiceMetric> metricsMap) {
+    return invokeRpc('_getIsolateMetricList', {'type': metricType})
+        .then((dynamic result) {
+      // Clear metrics map.
+      metricsMap.clear();
+      // Repopulate metrics map.
+      var metrics = result['metrics'];
+      for (var metric in metrics) {
+        metricsMap[metric.id] = metric;
+      }
+      return metricsMap;
+    });
+  }
+
+  Future<Map<String, ServiceMetric>> refreshDartMetrics() {
+    return _refreshMetrics('Dart', dartMetrics);
+  }
+
+  Future<Map<String, ServiceMetric>> refreshNativeMetrics() {
+    return _refreshMetrics('Native', nativeMetrics);
+  }
+
+  Future refreshMetrics() {
+    return Future.wait([refreshDartMetrics(), refreshNativeMetrics()]);
+  }
+
+  String toString() => "Isolate($name)";
+}
+
+class NamedField implements M.NamedField {
+  final String name;
+  final M.ObjectRef value;
+  NamedField(this.name, this.value);
+}
+
+class ObjectStore extends ServiceObject implements M.ObjectStore {
+  List<NamedField> fields = <NamedField>[];
+
+  ObjectStore._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    // Extract full properties.
+    _upgradeCollection(map, isolate);
+
+    if (mapIsRef) {
+      return;
+    }
+
+    fields.clear();
+    map['fields'].forEach((key, value) {
+      fields.add(new NamedField(key, value));
+    });
+    _loaded = true;
+  }
+}
+
+/// A [ServiceObject] which implements [Map].
+class ServiceMap extends ServiceObject
+    implements Map<String, dynamic>, M.UnknownObjectRef {
+  final Map<String, dynamic> _map = {};
+  static String objectIdRingPrefix = 'objects/';
+
+  bool get immutable => false;
+
+  ServiceMap._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _loaded = !mapIsRef;
+
+    _upgradeCollection(map, owner);
+    // TODO(turnidge): Currently _map.clear() prevents us from
+    // upgrading an already upgraded submap.  Is clearing really the
+    // right thing to do here?
+    _map.clear();
+    _map.addAll(map);
+
+    name = _map['name'];
+    vmName = (_map.containsKey('_vmName') ? _map['_vmName'] : name);
+  }
+
+  // TODO(turnidge): These are temporary until we have a proper root
+  // object for all dart heap objects.
+  int get size => _map['size'];
+  int get clazz => _map['class'];
+
+  // Forward Map interface calls.
+  void addAll(Map other) => _map.addAll(other);
+  void clear() => _map.clear();
+  bool containsValue(v) => _map.containsValue(v);
+  bool containsKey(k) => _map.containsKey(k);
+  void forEach(Function f) => _map.forEach(f);
+  putIfAbsent(key, Function ifAbsent) => _map.putIfAbsent(key, ifAbsent);
+  void remove(key) => _map.remove(key);
+  operator [](k) => _map[k];
+  operator []=(k, v) => _map[k] = v;
+  bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
+  Iterable<String> get keys => _map.keys;
+  Iterable get values => _map.values;
+  int get length => _map.length;
+
+  // Suppress compile-time error about missing Map methods.
+  noSuchMethod(_) => throw "Unimplemented ServiceMap method";
+
+  String toString() => "ServiceMap($_map)";
+}
+
+M.ErrorKind stringToErrorKind(String value) {
+  switch (value) {
+    case 'UnhandledException':
+      return M.ErrorKind.unhandledException;
+    case 'LanguageError':
+      return M.ErrorKind.unhandledException;
+    case 'InternalError':
+      return M.ErrorKind.internalError;
+    case 'TerminationError':
+      return M.ErrorKind.terminationError;
+  }
+  var message = 'Unrecognized error kind: $value';
+  Logger.root.severe(message);
+  throw new ArgumentError(message);
+}
+
+/// A [DartError] is peered to a Dart Error object.
+class DartError extends HeapObject implements M.Error {
+  DartError._empty(ServiceObject owner) : super._empty(owner);
+
+  M.ErrorKind kind;
+  String message;
+  Instance exception;
+  Instance stacktrace;
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, owner);
+    super._update(map, mapIsRef);
+
+    message = map['message'];
+    kind = stringToErrorKind(map['kind']);
+    exception = map['exception'];
+    stacktrace = map['stacktrace'];
+    name = 'DartError($message)';
+    vmName = name;
+  }
+
+  String toString() => 'DartError($message)';
+}
+
+Level _findLogLevel(int value) {
+  for (var level in Level.LEVELS) {
+    if (level.value == value) {
+      return level;
+    }
+  }
+  return new Level('$value', value);
+}
+
+/// A [ServiceEvent] is an asynchronous event notification from the vm.
+class ServiceEvent extends ServiceObject {
+  /// The possible 'kind' values.
+  static const kVMUpdate = 'VMUpdate';
+  static const kVMFlagUpdate = 'VMFlagUpdate';
+  static const kIsolateStart = 'IsolateStart';
+  static const kIsolateRunnable = 'IsolateRunnable';
+  static const kIsolateExit = 'IsolateExit';
+  static const kIsolateUpdate = 'IsolateUpdate';
+  static const kIsolateReload = 'IsolateReload';
+  static const kIsolateSpawn = 'IsolateSpawn';
+  static const kServiceExtensionAdded = 'ServiceExtensionAdded';
+  static const kPauseStart = 'PauseStart';
+  static const kPauseExit = 'PauseExit';
+  static const kPauseBreakpoint = 'PauseBreakpoint';
+  static const kPauseInterrupted = 'PauseInterrupted';
+  static const kPauseException = 'PauseException';
+  static const kPausePostRequest = 'PausePostRequest';
+  static const kNone = 'None';
+  static const kResume = 'Resume';
+  static const kBreakpointAdded = 'BreakpointAdded';
+  static const kBreakpointResolved = 'BreakpointResolved';
+  static const kBreakpointRemoved = 'BreakpointRemoved';
+  static const kHeapSnapshot = 'HeapSnapshot';
+  static const kGC = 'GC';
+  static const kInspect = 'Inspect';
+  static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
+  static const kConnectionClosed = 'ConnectionClosed';
+  static const kLogging = 'Logging';
+  static const kExtension = 'Extension';
+  static const kTimelineEvents = 'TimelineEvents';
+  static const kTimelineStreamSubscriptionsUpdate =
+      'TimelineStreamSubscriptionsUpdate';
+  static const kServiceRegistered = 'ServiceRegistered';
+  static const kServiceUnregistered = 'ServiceUnregistered';
+  static const kDartDevelopmentServiceConnected =
+      'DartDevelopmentServiceConnected';
+
+  ServiceEvent._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  ServiceEvent.connectionClosed(this.reason) : super._empty(null) {
+    kind = kConnectionClosed;
+  }
+
+  String kind;
+  DateTime timestamp;
+  String flag;
+  String newValue;
+  List<M.Breakpoint> pauseBreakpoints;
+  Breakpoint breakpoint;
+  Frame topFrame;
+  DartError error;
+  String extensionRPC;
+  Instance exception;
+  DartError reloadError;
+  bool atAsyncSuspension;
+  Instance inspectee;
+  Uint8List data;
+  int count;
+  String reason;
+  String exceptions;
+  String bytesAsString;
+  Map logRecord;
+  String extensionKind;
+  Map extensionData;
+  List timelineEvents;
+  List<String> updatedStreams;
+  String spawnToken;
+  String spawnError;
+  String editor;
+  ServiceObject object;
+  String method;
+  String service;
+  String alias;
+  String message;
+  Uri uri;
+
+  bool lastChunk;
+
+  bool get isPauseEvent {
+    return (kind == kPauseStart ||
+        kind == kPauseExit ||
+        kind == kPauseBreakpoint ||
+        kind == kPauseInterrupted ||
+        kind == kPauseException ||
+        kind == kPausePostRequest ||
+        kind == kNone);
+  }
+
+  void _update(Map map, bool mapIsRef) {
+    _loaded = true;
+    _upgradeCollection(map, owner);
+
+    assert(map['isolate'] == null || owner == map['isolate']);
+    timestamp = new DateTime.fromMillisecondsSinceEpoch(map['timestamp']);
+    kind = map['kind'];
+    name = 'ServiceEvent $kind';
+    vmName = name;
+    if (map['breakpoint'] != null) {
+      breakpoint = map['breakpoint'];
+    }
+    if (map['pauseBreakpoints'] != null) {
+      pauseBreakpoints = new List<Breakpoint>.from(map['pauseBreakpoints']);
+      if (pauseBreakpoints.length > 0) {
+        breakpoint = pauseBreakpoints[0];
+      }
+    } else {
+      pauseBreakpoints = const [];
+    }
+    if (map['error'] != null) {
+      error = map['error'];
+    }
+    if (map['extensionRPC'] != null) {
+      extensionRPC = map['extensionRPC'];
+    }
+    topFrame = map['topFrame'];
+    if (map['exception'] != null) {
+      exception = map['exception'];
+    }
+    atAsyncSuspension = map['atAsyncSuspension'] != null;
+    if (map['inspectee'] != null) {
+      inspectee = map['inspectee'];
+    }
+    if (map['_data'] != null) {
+      data = map['_data'];
+    }
+    lastChunk = map['last'] ?? false;
+    if (map['count'] != null) {
+      count = map['count'];
+    }
+    reloadError = map['reloadError'];
+    if (map['_debuggerSettings'] != null &&
+        map['_debuggerSettings']['_exceptions'] != null) {
+      exceptions = map['_debuggerSettings']['_exceptions'];
+    }
+    if (map['bytes'] != null) {
+      var bytes = base64Decode(map['bytes']);
+      bytesAsString = utf8.decode(bytes);
+    }
+    if (map['logRecord'] != null) {
+      logRecord = map['logRecord'];
+      logRecord['time'] =
+          new DateTime.fromMillisecondsSinceEpoch(logRecord['time']);
+      logRecord['level'] = _findLogLevel(logRecord['level']);
+    }
+    if (map['extensionKind'] != null) {
+      extensionKind = map['extensionKind'];
+      extensionData = map['extensionData'];
+    }
+    if (map['timelineEvents'] != null) {
+      timelineEvents = map['timelineEvents'];
+    }
+    if (map['updatedStreams'] != null) {
+      updatedStreams = map['updatedStreams'].cast<String>();
+    }
+    if (map['spawnToken'] != null) {
+      spawnToken = map['spawnToken'];
+    }
+    if (map['spawnError'] != null) {
+      spawnError = map['spawnError'];
+    }
+    if (map['editor'] != null) {
+      editor = map['editor'];
+    }
+    if (map['object'] != null) {
+      object = map['object'];
+    }
+    if (map['service'] != null) {
+      service = map['service'];
+    }
+    if (map['method'] != null) {
+      method = map['method'];
+    }
+    if (map['alias'] != null) {
+      alias = map['alias'];
+    }
+    if (map['flag'] != null) {
+      flag = map['flag'];
+    }
+    if (map['newValue'] != null) {
+      newValue = map['newValue'];
+    }
+    if (map['message'] != null) {
+      message = map['message'];
+    }
+    if (map['uri'] != null) {
+      uri = Uri.parse(map['uri']);
+    }
+  }
+
+  String toString() {
+    var ownerName = owner.id != null ? owner.id.toString() : owner.name;
+    if (data == null) {
+      return "ServiceEvent(owner='${ownerName}', kind='${kind}', "
+          "time=${timestamp})";
+    } else {
+      return "ServiceEvent(owner='${ownerName}', kind='${kind}', "
+          "data.lengthInBytes=${data.lengthInBytes}, time=${timestamp})";
+    }
+  }
+}
+
+class Breakpoint extends ServiceObject implements M.Breakpoint {
+  Breakpoint._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  final M.ClassRef clazz = null;
+  final int size = null;
+
+  // TODO(turnidge): Add state to track if a breakpoint has been
+  // removed from the program.  Remove from the cache when deleted.
+  bool get immutable => false;
+
+  // A unique integer identifier for this breakpoint.
+  int number;
+
+  // Either SourceLocation or UnresolvedSourceLocation.
+  Location location;
+
+  // The breakpoint is in a file which is not yet loaded.
+  bool latent;
+
+  // The breakpoint has been assigned to a final source location.
+  bool resolved;
+
+  // The breakpoint was synthetically created as part of an
+  // 'OverAsyncContinuation' resume request.
+  bool isSyntheticAsyncContinuation;
+
+  void _update(Map map, bool mapIsRef) {
+    _loaded = true;
+    _upgradeCollection(map, owner);
+
+    var newNumber = map['breakpointNumber'];
+    // number never changes.
+    assert((number == null) || (number == newNumber));
+    number = newNumber;
+    resolved = map['resolved'];
+
+    var oldLocation = location;
+    var newLocation = map['location'];
+    if (oldLocation is UnresolvedSourceLocation &&
+        newLocation is SourceLocation) {
+      // Breakpoint has been resolved.  Remove old breakpoint.
+      var oldScript = oldLocation.script;
+      if (oldScript != null && oldScript.loaded) {
+        oldScript._removeBreakpoint(this);
+      }
+    }
+    location = newLocation;
+    var newScript = location.script;
+    if (newScript != null && newScript.loaded) {
+      newScript._addBreakpoint(this);
+    }
+
+    isSyntheticAsyncContinuation = map['isSyntheticAsyncContinuation'] != null;
+
+    assert(resolved || location is UnresolvedSourceLocation);
+  }
+
+  void remove() {
+    location.script._removeBreakpoint(this);
+  }
+
+  String toString() {
+    if (number != null) {
+      if (isSyntheticAsyncContinuation) {
+        return 'Synthetic Async Continuation Breakpoint ${number}';
+      } else {
+        return 'Breakpoint ${number} at ${location}';
+      }
+    } else {
+      return 'Uninitialized breakpoint';
+    }
+  }
+}
+
+class LibraryDependency implements M.LibraryDependency {
+  final bool isImport;
+  final bool isDeferred;
+  final String prefix;
+  final Library target;
+
+  bool get isExport => !isImport;
+
+  LibraryDependency._(this.isImport, this.isDeferred, this.prefix, this.target);
+
+  static _fromMap(map) => new LibraryDependency._(
+      map["isImport"], map["isDeferred"], map["prefix"], map["target"]);
+}
+
+class Library extends HeapObject implements M.Library {
+  String uri;
+  final List<LibraryDependency> dependencies = <LibraryDependency>[];
+  final List<Script> scripts = <Script>[];
+  final List<Class> classes = <Class>[];
+  final List<Field> variables = <Field>[];
+  final List<ServiceFunction> functions = <ServiceFunction>[];
+  bool _debuggable;
+  bool get debuggable => _debuggable;
+  bool get immutable => false;
+
+  bool isDart(String libraryName) {
+    return uri == 'dart:$libraryName';
+  }
+
+  Library._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    uri = map['uri'];
+    var shortUri = uri;
+    if (uri.startsWith('file://') || uri.startsWith('http://')) {
+      shortUri = uri.substring(uri.lastIndexOf('/') + 1);
+    }
+    name = map['name'];
+    if (name.isEmpty) {
+      // When there is no name for a library, use the shortUri.
+      name = shortUri;
+    }
+    vmName = (map.containsKey('_vmName') ? map['_vmName'] : name);
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    _debuggable = map['debuggable'];
+    dependencies.clear();
+    for (var dependency in map["dependencies"]) {
+      dependencies.add(LibraryDependency._fromMap(dependency));
+    }
+    scripts.clear();
+    scripts.addAll(
+        removeDuplicatesAndSortLexical(new List<Script>.from(map['scripts'])));
+    classes.clear();
+    for (Class c in map['classes']) classes.add(c);
+    classes.sort(ServiceObject.LexicalSortName);
+    variables.clear();
+    for (Field v in map['variables']) variables.add(v);
+    variables.sort(ServiceObject.LexicalSortName);
+    functions.clear();
+    for (ServiceFunction f in map['functions']) functions.add(f);
+    functions.sort(ServiceObject.LexicalSortName);
+  }
+
+  Future<ServiceObject> evaluate(String expression,
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
+  }
+
+  Script get rootScript {
+    for (Script script in scripts) {
+      if (script.uri == uri) return script;
+    }
+    return null;
+  }
+
+  String toString() => "Library($uri)";
+}
+
+class Allocations implements M.Allocations {
+  // Indexes into VM provided array. (see vm/class_table.h).
+
+  int instances = 0;
+  int internalSize = 0;
+  int externalSize = 0;
+  int size = 0;
+
+  void update(List stats) {
+    instances = stats[0];
+    internalSize = stats[1];
+    externalSize = stats[2];
+    size = internalSize + externalSize;
+  }
+
+  void combine(Iterable<Allocations> allocations) {
+    instances = allocations.fold(0, (v, a) => v + a.instances);
+    internalSize = allocations.fold(0, (v, a) => v + a.internalSize);
+    externalSize = allocations.fold(0, (v, a) => v + a.externalSize);
+    size = allocations.fold(0, (v, a) => v + a.size);
+  }
+
+  bool get empty => size == 0;
+  bool get notEmpty => size != 0;
+}
+
+class Class extends HeapObject implements M.Class {
+  Library library;
+
+  bool isAbstract;
+  bool isConst;
+  bool isFinalized;
+  bool isPatch;
+  bool isImplemented;
+
+  SourceLocation location;
+
+  DartError error;
+
+  final Allocations newSpace = new Allocations();
+  final Allocations oldSpace = new Allocations();
+
+  bool get hasAllocations => newSpace.notEmpty || oldSpace.notEmpty;
+  bool get hasNoAllocations => newSpace.empty && oldSpace.empty;
+  bool traceAllocations = false;
+  final List<Field> fields = <Field>[];
+  final List<ServiceFunction> functions = <ServiceFunction>[];
+
+  Class superclass;
+  final List<Instance> interfaces = <Instance>[];
+  final List<Class> subclasses = <Class>[];
+
+  Instance superType;
+  Instance mixin;
+
+  bool get immutable => false;
+
+  Class._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    name = map['name'];
+    vmName = (map.containsKey('_vmName') ? map['_vmName'] : name);
+    if (vmName == '::') {
+      name = 'top-level-class'; // Better than ''
+    }
+    var idPrefix = "classes/";
+    assert(id.startsWith(idPrefix));
+
+    if (mapIsRef) {
+      return;
+    }
+
+    // We are fully loaded.
+    _loaded = true;
+
+    // Extract full properties.
+    _upgradeCollection(map, isolate);
+
+    // Some builtin classes aren't associated with a library.
+    if (map['library'] is Library) {
+      library = map['library'];
+    } else {
+      library = null;
+    }
+
+    location = map['location'];
+    isAbstract = map['abstract'];
+    isConst = map['const'];
+    isFinalized = map['_finalized'];
+    isPatch = map['_patch'];
+    isImplemented = map['_implemented'];
+
+    subclasses.clear();
+    for (Class c in map['subclasses']) subclasses.add(c);
+    subclasses.sort(ServiceObject.LexicalSortName);
+
+    interfaces.clear();
+    for (Instance i in map['interfaces']) interfaces.add(i);
+    interfaces.sort(ServiceObject.LexicalSortName);
+
+    fields.clear();
+    for (Field f in map['fields']) fields.add(f);
+    fields.sort(ServiceObject.LexicalSortName);
+
+    functions.clear();
+    for (ServiceFunction f in map['functions']) functions.add(f);
+    functions.sort(ServiceObject.LexicalSortName);
+
+    superclass = map['super'];
+    // Work-around Object not tracking its subclasses in the VM.
+    if (superclass != null && superclass.name == "Object") {
+      superclass._addSubclass(this);
+    }
+    superType = map['superType'];
+    mixin = map['mixin'];
+
+    error = map['error'];
+
+    traceAllocations =
+        (map['_traceAllocations'] != null) ? map['_traceAllocations'] : false;
+  }
+
+  void _addSubclass(Class subclass) {
+    if (subclasses.contains(subclass)) {
+      return;
+    }
+    subclasses.add(subclass);
+    subclasses.sort(ServiceObject.LexicalSortName);
+  }
+
+  Future<ServiceObject> evaluate(String expression,
+      {Map<String, ServiceObject> scope, disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
+  }
+
+  Future<ServiceObject> setTraceAllocations(bool enable) {
+    return isolate.invokeRpc('_setTraceClassAllocation', {
+      'enable': enable,
+      'classId': id,
+    });
+  }
+
+  Future<ServiceObject> getAllocationSamples() {
+    var params = {
+      'classId': id,
+    };
+    return isolate.invokeRpc('_getAllocationSamples', params);
+  }
+
+  String toString() => 'Class($vmName)';
+}
+
+M.InstanceKind stringToInstanceKind(String s) {
+  switch (s) {
+    case 'PlainInstance':
+      return M.InstanceKind.plainInstance;
+    case 'Null':
+      return M.InstanceKind.vNull;
+    case 'Bool':
+      return M.InstanceKind.bool;
+    case 'Double':
+      return M.InstanceKind.double;
+    case 'Int':
+      return M.InstanceKind.int;
+    case 'String':
+      return M.InstanceKind.string;
+    case 'List':
+      return M.InstanceKind.list;
+    case 'Map':
+      return M.InstanceKind.map;
+    case 'Float32x4':
+      return M.InstanceKind.float32x4;
+    case 'Float64x2':
+      return M.InstanceKind.float64x2;
+    case 'Int32x4':
+      return M.InstanceKind.int32x4;
+    case 'Uint8ClampedList':
+      return M.InstanceKind.uint8ClampedList;
+    case 'Uint8List':
+      return M.InstanceKind.uint8List;
+    case 'Uint16List':
+      return M.InstanceKind.uint16List;
+    case 'Uint32List':
+      return M.InstanceKind.uint32List;
+    case 'Uint64List':
+      return M.InstanceKind.uint64List;
+    case 'Int8List':
+      return M.InstanceKind.int8List;
+    case 'Int16List':
+      return M.InstanceKind.int16List;
+    case 'Int32List':
+      return M.InstanceKind.int32List;
+    case 'Int64List':
+      return M.InstanceKind.int64List;
+    case 'Float32List':
+      return M.InstanceKind.float32List;
+    case 'Float64List':
+      return M.InstanceKind.float64List;
+    case 'Int32x4List':
+      return M.InstanceKind.int32x4List;
+    case 'Float32x4List':
+      return M.InstanceKind.float32x4List;
+    case 'Float64x2List':
+      return M.InstanceKind.float64x2List;
+    case 'StackTrace':
+      return M.InstanceKind.stackTrace;
+    case 'Closure':
+      return M.InstanceKind.closure;
+    case 'MirrorReference':
+      return M.InstanceKind.mirrorReference;
+    case 'RegExp':
+      return M.InstanceKind.regExp;
+    case 'WeakProperty':
+      return M.InstanceKind.weakProperty;
+    case 'Type':
+      return M.InstanceKind.type;
+    case 'TypeParameter':
+      return M.InstanceKind.typeParameter;
+    case 'TypeRef':
+      return M.InstanceKind.typeRef;
+  }
+  var message = 'Unrecognized instance kind: $s';
+  Logger.root.severe(message);
+  throw new ArgumentError(message);
+}
+
+class Guarded<T extends ServiceObject> implements M.Guarded<T> {
+  bool get isValue => asValue != null;
+  bool get isSentinel => asSentinel != null;
+  final Sentinel asSentinel;
+  final T asValue;
+
+  factory Guarded(ServiceObject obj) {
+    if (obj is Sentinel) {
+      return new Guarded.fromSentinel(obj);
+    } else if (obj is T) {
+      return new Guarded.fromValue(obj);
+    }
+    throw new Exception('${obj.type} is neither Sentinel or $T');
+  }
+
+  Guarded.fromSentinel(this.asSentinel) : asValue = null;
+  Guarded.fromValue(this.asValue) : asSentinel = null;
+}
+
+class BoundField implements M.BoundField {
+  final Field decl;
+  final Guarded<Instance> value;
+  BoundField(this.decl, value) : value = new Guarded(value);
+}
+
+class NativeField implements M.NativeField {
+  final int value;
+  NativeField(this.value);
+}
+
+class MapAssociation implements M.MapAssociation {
+  final Guarded<Instance> key;
+  final Guarded<Instance> value;
+  MapAssociation(key, value)
+      : key = new Guarded(key),
+        value = new Guarded(value);
+}
+
+class Instance extends HeapObject implements M.Instance {
+  M.InstanceKind kind;
+  String valueAsString; // If primitive.
+  bool valueAsStringIsTruncated;
+  ServiceFunction closureFunction; // If a closure.
+  Context closureContext; // If a closure.
+  int length; // If a List, Map or TypedData.
+  int count;
+  int offset;
+  Instance pattern; // If a RegExp.
+
+  String name;
+  Class typeClass;
+  Class parameterizedClass;
+  TypeArguments typeArguments;
+  int parameterIndex;
+  Instance targetType;
+  Instance bound;
+
+  Iterable<BoundField> fields;
+  var nativeFields;
+  Iterable<Guarded<HeapObject>> elements; // If a List.
+  Iterable<MapAssociation> associations; // If a Map.
+  List<dynamic> typedElements; // If a TypedData.
+  HeapObject referent; // If a MirrorReference.
+  Instance key; // If a WeakProperty.
+  Instance value; // If a WeakProperty.
+  Breakpoint activationBreakpoint; // If a Closure.
+  ServiceFunction oneByteFunction; // If a RegExp.
+  ServiceFunction twoByteFunction; // If a RegExp.
+  ServiceFunction externalOneByteFunction; // If a RegExp.
+  ServiceFunction externalTwoByteFunction; // If a RegExp.
+  Instance oneByteBytecode; // If a RegExp.
+  Instance twoByteBytecode; // If a RegExp.
+  bool isCaseSensitive; // If a RegExp.
+  bool isMultiLine; // If a RegExp.
+
+  bool get isAbstractType => M.isAbstractType(kind);
+  bool get isNull => kind == M.InstanceKind.vNull;
+  bool get isBool => kind == M.InstanceKind.bool;
+  bool get isDouble => kind == M.InstanceKind.double;
+  bool get isString => kind == M.InstanceKind.string;
+  bool get isInt => kind == M.InstanceKind.int;
+  bool get isList => kind == M.InstanceKind.list;
+  bool get isMap => kind == M.InstanceKind.map;
+  bool get isTypedData {
+    return M.isTypedData(kind);
+  }
+
+  bool get isSimdValue {
+    return M.isSimdValue(kind);
+  }
+
+  bool get isRegExp => kind == M.InstanceKind.regExp;
+  bool get isMirrorReference => kind == M.InstanceKind.mirrorReference;
+  bool get isWeakProperty => kind == M.InstanceKind.weakProperty;
+  bool get isClosure => kind == M.InstanceKind.closure;
+  bool get isStackTrace => kind == M.InstanceKind.stackTrace;
+  bool get isStackOverflowError {
+    if (clazz == null) {
+      return false;
+    }
+    if (clazz.library == null) {
+      return false;
+    }
+    return (clazz.name == 'StackOverflowError') && clazz.library.isDart('core');
+  }
+
+  bool get isOutOfMemoryError {
+    if (clazz == null) {
+      return false;
+    }
+    if (clazz.library == null) {
+      return false;
+    }
+    return (clazz.name == 'OutOfMemoryError') && clazz.library.isDart('core');
+  }
+
+  // TODO(turnidge): Is this properly backwards compatible when new
+  // instance kinds are added?
+  bool get isPlainInstance => kind == 'PlainInstance';
+
+  Instance._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    // Extract full properties.1
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    kind = stringToInstanceKind(map['kind']);
+    valueAsString = map['valueAsString'];
+    // Coerce absence to false.
+    valueAsStringIsTruncated = map['valueAsStringIsTruncated'] == true;
+    closureFunction = map['closureFunction'];
+    name = map['name'];
+    length = map['length'];
+    pattern = map['pattern'];
+    typeClass = map['typeClass'];
+
+    final context = map['closureContext'];
+    if (context is Context) {
+      closureContext = context;
+    } else if (context != null) {
+      assert(context is Instance && context.isNull);
+    }
+
+    if (mapIsRef) {
+      return;
+    }
+
+    count = map['count'];
+    offset = map['offset'];
+    isCaseSensitive = map['isCaseSensitive'];
+    isMultiLine = map['isMultiLine'];
+    bool isCompiled = map['_oneByteFunction'] is ServiceFunction;
+    oneByteFunction = isCompiled ? map['_oneByteFunction'] : null;
+    twoByteFunction = isCompiled ? map['_twoByteFunction'] : null;
+    externalOneByteFunction =
+        isCompiled ? map['_externalOneByteFunction'] : null;
+    externalTwoByteFunction =
+        isCompiled ? map['_externalTwoByteFunction'] : null;
+    oneByteBytecode = map['_oneByteBytecode'];
+    twoByteBytecode = map['_twoByteBytecode'];
+
+    if (map['fields'] != null) {
+      var fields = <BoundField>[];
+      for (var f in map['fields']) {
+        fields.add(new BoundField(f['decl'], f['value']));
+      }
+      this.fields = fields;
+    } else {
+      fields = null;
+    }
+    if (map['_nativeFields'] != null) {
+      nativeFields = map['_nativeFields']
+          .map<NativeField>((f) => new NativeField(f['value']))
+          .toList();
+    } else {
+      nativeFields = null;
+    }
+    if (map['elements'] != null) {
+      // Should be:
+      // elements = map['elements'].map((e) => new Guarded<Instance>(e)).toList();
+      // some times we obtain object that are not InstanceRef
+      var localElements = <Guarded<HeapObject>>[];
+      for (var element in map['elements']) {
+        localElements.add(new Guarded<HeapObject>(element));
+      }
+      elements = localElements;
+    } else {
+      elements = null;
+    }
+    if (map['associations'] != null) {
+      associations = map['associations']
+          .map<MapAssociation>((a) => new MapAssociation(a['key'], a['value']))
+          .toList();
+    } else {
+      associations = null;
+    }
+    ;
+    if (map['bytes'] != null) {
+      Uint8List bytes = base64Decode(map['bytes']);
+      switch (map['kind']) {
+        case "Uint8ClampedList":
+          typedElements = bytes.buffer.asUint8ClampedList();
+          break;
+        case "Uint8List":
+          typedElements = bytes.buffer.asUint8List();
+          break;
+        case "Uint16List":
+          typedElements = bytes.buffer.asUint16List();
+          break;
+        case "Uint32List":
+          typedElements = bytes.buffer.asUint32List();
+          break;
+        case "Uint64List":
+          typedElements = bytes.buffer.asUint64List();
+          break;
+        case "Int8List":
+          typedElements = bytes.buffer.asInt8List();
+          break;
+        case "Int16List":
+          typedElements = bytes.buffer.asInt16List();
+          break;
+        case "Int32List":
+          typedElements = bytes.buffer.asInt32List();
+          break;
+        case "Int64List":
+          typedElements = bytes.buffer.asInt64List();
+          break;
+        case "Float32List":
+          typedElements = bytes.buffer.asFloat32List();
+          break;
+        case "Float64List":
+          typedElements = bytes.buffer.asFloat64List();
+          break;
+        case "Int32x4List":
+          typedElements = bytes.buffer.asInt32x4List();
+          break;
+        case "Float32x4List":
+          typedElements = bytes.buffer.asFloat32x4List();
+          break;
+        case "Float64x2List":
+          typedElements = bytes.buffer.asFloat64x2List();
+          break;
+      }
+    } else {
+      typedElements = null;
+    }
+    parameterizedClass = map['parameterizedClass'];
+    typeArguments = map['typeArguments'];
+    parameterIndex = map['parameterIndex'];
+    targetType = map['targetType'];
+    bound = map['bound'];
+
+    referent = map['mirrorReferent'];
+    key = map['propertyKey'];
+    value = map['propertyValue'];
+    activationBreakpoint = map['_activationBreakpoint'];
+
+    // We are fully loaded.
+    _loaded = true;
+  }
+
+  String get shortName {
+    if (isClosure) {
+      return closureFunction.qualifiedName;
+    }
+    if (valueAsString != null) {
+      return valueAsString;
+    }
+    return 'a ${clazz.name}';
+  }
+
+  Future<ServiceObject> evaluate(String expression,
+      {Map<String, ServiceObject> scope, bool disableBreakpoints: false}) {
+    return isolate.eval(this, expression,
+        scope: scope, disableBreakpoints: disableBreakpoints);
+  }
+
+  String toString() => 'Instance($shortName)';
+}
+
+class Context extends HeapObject implements M.Context {
+  Context parentContext;
+  int length;
+  Iterable<ContextElement> variables;
+
+  Context._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    // Extract full properties.
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    length = map['length'];
+    parentContext = map['parent'];
+
+    if (mapIsRef) {
+      return;
+    }
+
+    if (map['variables'] == null) {
+      variables = <ContextElement>[];
+    } else {
+      var localVariables = <ContextElement>[];
+      for (var element in map['variables']) {
+        localVariables.add(new ContextElement(element));
+      }
+      variables = localVariables;
+    }
+
+    // We are fully loaded.
+    _loaded = true;
+  }
+
+  String toString() => 'Context($length)';
+}
+
+class ContextElement extends M.ContextElement {
+  final Guarded<Instance> value;
+
+  ContextElement(Map map) : value = new Guarded<Instance>(map['value']);
+}
+
+M.FunctionKind stringToFunctionKind(String value) {
+  switch (value) {
+    case 'RegularFunction':
+      return M.FunctionKind.regular;
+    case 'ClosureFunction':
+      return M.FunctionKind.closure;
+    case 'ImplicitClosureFunction':
+      return M.FunctionKind.implicitClosure;
+    case 'GetterFunction':
+      return M.FunctionKind.getter;
+    case 'SetterFunction':
+      return M.FunctionKind.setter;
+    case 'Constructor':
+      return M.FunctionKind.constructor;
+    case 'ImplicitGetter':
+      return M.FunctionKind.implicitGetter;
+    case 'ImplicitSetter':
+      return M.FunctionKind.implicitSetter;
+    case 'ImplicitStaticGetter':
+      return M.FunctionKind.implicitStaticGetter;
+    case 'FieldInitializer':
+      return M.FunctionKind.fieldInitializer;
+    case 'IrregexpFunction':
+      return M.FunctionKind.irregexpFunction;
+    case 'MethodExtractor':
+      return M.FunctionKind.methodExtractor;
+    case 'NoSuchMethodDispatcher':
+      return M.FunctionKind.noSuchMethodDispatcher;
+    case 'InvokeFieldDispatcher':
+      return M.FunctionKind.invokeFieldDispatcher;
+    case 'Collected':
+      return M.FunctionKind.collected;
+    case 'Native':
+      return M.FunctionKind.native;
+    case 'FfiTrampoline':
+      return M.FunctionKind.ffiTrampoline;
+    case 'Stub':
+      return M.FunctionKind.stub;
+    case 'Tag':
+      return M.FunctionKind.tag;
+    case 'SignatureFunction':
+      return M.FunctionKind.signatureFunction;
+    case 'DynamicInvocationForwarder':
+      return M.FunctionKind.dynamicInvocationForwarder;
+  }
+  var message = 'Unrecognized function kind: $value';
+  Logger.root.severe(message);
+  throw new ArgumentError(message);
+}
+
+class ServiceFunction extends HeapObject implements M.ServiceFunction {
+  // owner is a Library, Class, or ServiceFunction.
+  M.ObjectRef dartOwner;
+  Library library;
+  bool isStatic;
+  bool isConst;
+  SourceLocation location;
+  Code code;
+  Code unoptimizedCode;
+  Code bytecode;
+  bool isOptimizable;
+  bool isInlinable;
+  bool hasIntrinsic;
+  bool isRecognized;
+  bool isNative;
+  M.FunctionKind kind;
+  int deoptimizations;
+  String qualifiedName;
+  int usageCounter;
+  bool isDart;
+  ProfileFunction profile;
+  Instance icDataArray;
+  Field field;
+
+  bool get immutable => false;
+
+  ServiceFunction._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, owner);
+    super._update(map, mapIsRef);
+
+    name = map['name'];
+    vmName = (map.containsKey('_vmName') ? map['_vmName'] : name);
+
+    dartOwner = map['owner'];
+    kind = stringToFunctionKind(map['_kind']);
+    isDart = M.isDartFunction(kind);
+
+    if (dartOwner is ServiceFunction) {
+      ServiceFunction ownerFunction = dartOwner;
+      library = ownerFunction.library;
+      qualifiedName = "${ownerFunction.qualifiedName}.${name}";
+    } else if (dartOwner is Class) {
+      Class ownerClass = dartOwner;
+      library = ownerClass.library;
+      qualifiedName = "${ownerClass.name}.${name}";
+    } else {
+      library = dartOwner;
+      qualifiedName = name;
+    }
+
+    hasIntrinsic = map['_intrinsic'];
+    isNative = map['_native'];
+
+    if (mapIsRef) {
+      return;
+    }
+
+    _loaded = true;
+    isStatic = map['static'];
+    isConst = map['const'];
+    location = map['location'];
+    code = map['code'];
+    isOptimizable = map['_optimizable'];
+    isInlinable = map['_inlinable'];
+    isRecognized = map['_recognized'];
+    unoptimizedCode = map['_unoptimizedCode'];
+    bytecode = map['_bytecode'];
+    deoptimizations = map['_deoptimizations'];
+    usageCounter = map['_usageCounter'];
+    icDataArray = map['_icDataArray'];
+    field = map['_field'];
+  }
+
+  ServiceFunction get homeMethod {
+    var m = this;
+    while (m.dartOwner is ServiceFunction) {
+      m = m.dartOwner;
+    }
+    return m;
+  }
+
+  String toString() {
+    return "ServiceFunction($qualifiedName)";
+  }
+}
+
+M.SentinelKind stringToSentinelKind(String s) {
+  switch (s) {
+    case 'Collected':
+      return M.SentinelKind.collected;
+    case 'Expired':
+      return M.SentinelKind.expired;
+    case 'NotInitialized':
+      return M.SentinelKind.notInitialized;
+    case 'BeingInitialized':
+      return M.SentinelKind.initializing;
+    case 'OptimizedOut':
+      return M.SentinelKind.optimizedOut;
+    case 'Free':
+      return M.SentinelKind.free;
+  }
+  var message = 'Unrecognized sentinel kind: $s';
+  Logger.root.severe(message);
+  throw new ArgumentError(message);
+}
+
+class Sentinel extends ServiceObject implements M.Sentinel {
+  M.SentinelKind kind;
+  String valueAsString;
+
+  Sentinel._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    // Extract full properties.
+    _upgradeCollection(map, isolate);
+
+    kind = stringToSentinelKind(map['kind']);
+    valueAsString = map['valueAsString'];
+    _loaded = true;
+  }
+
+  String toString() => 'Sentinel($kind)';
+  String get shortName => valueAsString;
+}
+
+class Thread extends ServiceObject implements M.Thread {
+  M.ThreadKind get kind => _kind;
+  M.ThreadKind _kind;
+  String get kindString => _kindString;
+  String _kindString;
+  int get zoneHighWatermark => _zoneHighWatermark;
+  int _zoneHighWatermark;
+  int get zoneCapacity => _zoneCapacity;
+  int _zoneCapacity;
+
+  Thread._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    String rawKind = map['kind'];
+
+    switch (rawKind) {
+      case "kUnknownTask":
+        _kind = M.ThreadKind.unknownTask;
+        _kindString = 'unknown';
+        break;
+      case "kMutatorTask":
+        _kind = M.ThreadKind.mutatorTask;
+        _kindString = 'mutator';
+        break;
+      case "kCompilerTask":
+        _kind = M.ThreadKind.compilerTask;
+        _kindString = 'compiler';
+        break;
+      case "kSweeperTask":
+        _kind = M.ThreadKind.sweeperTask;
+        _kindString = 'sweeper';
+        break;
+      case "kMarkerTask":
+        _kind = M.ThreadKind.markerTask;
+        _kindString = 'marker';
+        break;
+      default:
+        assert(false);
+    }
+
+    _zoneHighWatermark = int.parse(map['_zoneHighWatermark']);
+    _zoneCapacity = int.parse(map['_zoneCapacity']);
+  }
+}
+
+class Zone implements M.Zone {
+  int get capacity => _capacity;
+  int _capacity;
+  int get used => _used;
+  int _used;
+
+  Zone(this._capacity, this._used);
+}
+
+class Field extends HeapObject implements M.Field {
+  // Library or Class.
+  HeapObject dartOwner;
+  Library library;
+  Instance declaredType;
+  bool isStatic;
+  bool isFinal;
+  bool isConst;
+  ServiceObject staticValue;
+  String name;
+  String vmName;
+
+  bool guardNullable;
+  M.GuardClassKind guardClassKind;
+  Class guardClass;
+  String guardLength;
+  SourceLocation location;
+
+  Field._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    // Extract full properties.
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    name = map['name'];
+    vmName = (map.containsKey('_vmName') ? map['_vmName'] : name);
+    dartOwner = map['owner'];
+    declaredType = map['declaredType'];
+    isStatic = map['static'];
+    isFinal = map['final'];
+    isConst = map['const'];
+
+    if (dartOwner is Class) {
+      Class ownerClass = dartOwner;
+      library = ownerClass.library;
+    } else {
+      library = dartOwner;
+    }
+
+    if (mapIsRef) {
+      return;
+    }
+    staticValue = map['staticValue'];
+
+    guardNullable = map['_guardNullable'];
+    if (map['_guardClass'] is Class) {
+      guardClass = map['_guardClass'];
+      guardClassKind = M.GuardClassKind.single;
+    } else {
+      switch (map['_guardClass']) {
+        case 'various':
+          guardClassKind = M.GuardClassKind.dynamic;
+          break;
+        case 'unknown':
+        default:
+          guardClassKind = M.GuardClassKind.unknown;
+          break;
+      }
+    }
+
+    guardLength = map['_guardLength'];
+    location = map['location'];
+    _loaded = true;
+  }
+
+  String toString() => 'Field(${dartOwner.name}.$name)';
+}
+
+class ScriptLine {
+  final Script script;
+  final int line;
+  final String text;
+  Set<Breakpoint> breakpoints;
+
+  ScriptLine(this.script, this.line, this.text);
+
+  bool get isBlank {
+    return text.isEmpty || text.trim().isEmpty;
+  }
+
+  bool _isTrivial = null;
+  bool get isTrivial {
+    if (_isTrivial == null) {
+      _isTrivial = _isTrivialLine(text);
+    }
+    return _isTrivial;
+  }
+
+  static bool _isTrivialToken(String token) {
+    if (token == 'else') {
+      return true;
+    }
+    for (var c in token.split('')) {
+      switch (c) {
+        case '{':
+        case '}':
+        case '(':
+        case ')':
+        case ';':
+          break;
+        default:
+          return false;
+      }
+    }
+    return true;
+  }
+
+  static bool _isTrivialLine(String text) {
+    if (text.trimLeft().startsWith('//')) {
+      return true;
+    }
+    var wsTokens = text.split(new RegExp(r"(\s)+"));
+    for (var wsToken in wsTokens) {
+      var tokens = wsToken.split(new RegExp(r"(\b)"));
+      for (var token in tokens) {
+        if (!_isTrivialToken(token)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  void addBreakpoint(Breakpoint bpt) {
+    if (breakpoints == null) {
+      breakpoints = new Set<Breakpoint>();
+    }
+    breakpoints.add(bpt);
+  }
+
+  void removeBreakpoint(Breakpoint bpt) {
+    assert(breakpoints != null && breakpoints.contains(bpt));
+    breakpoints.remove(bpt);
+    if (breakpoints.isEmpty) {
+      breakpoints = null;
+    }
+  }
+}
+
+class CallSite {
+  final String name;
+  // TODO(turnidge): Use SourceLocation here instead.
+  final Script script;
+  final int tokenPos;
+  final List<CallSiteEntry> entries;
+
+  CallSite(this.name, this.script, this.tokenPos, this.entries);
+
+  int get line => script.tokenToLine(tokenPos);
+  int get column => script.tokenToCol(tokenPos);
+
+  int get aggregateCount {
+    var count = 0;
+    for (var entry in entries) {
+      count += entry.count;
+    }
+    return count;
+  }
+
+  factory CallSite.fromMap(Map siteMap, Script script) {
+    var name = siteMap['name'];
+    var tokenPos = siteMap['tokenPos'];
+    var entries = <CallSiteEntry>[];
+    for (var entryMap in siteMap['cacheEntries']) {
+      entries.add(new CallSiteEntry.fromMap(entryMap));
+    }
+    return new CallSite(name, script, tokenPos, entries);
+  }
+
+  bool operator ==(Object other) {
+    if (other is CallSite) {
+      return (script == other.script) && (tokenPos == other.tokenPos);
+    }
+    return false;
+  }
+
+  int get hashCode => (script.hashCode << 8) | tokenPos;
+
+  String toString() => "CallSite($name, $tokenPos)";
+}
+
+class CallSiteEntry {
+  final /* Class | Library */ receiver;
+  final int count;
+  final ServiceFunction target;
+
+  CallSiteEntry(this.receiver, this.count, this.target);
+
+  factory CallSiteEntry.fromMap(Map entryMap) {
+    return new CallSiteEntry(
+        entryMap['receiver'], entryMap['count'], entryMap['target']);
+  }
+
+  String toString() => "CallSiteEntry(${receiver.name}, $count)";
+}
+
+/// The location of a local variable reference in a script.
+class LocalVarLocation {
+  final int line;
+  final int column;
+  final int endColumn;
+  LocalVarLocation(this.line, this.column, this.endColumn);
+}
+
+class Script extends HeapObject implements M.Script {
+  final lines = <ScriptLine>[];
+  String uri;
+  String kind;
+  DateTime loadTime;
+  int firstTokenPos;
+  int lastTokenPos;
+  int lineOffset;
+  int columnOffset;
+  Library library;
+
+  String source;
+
+  bool get immutable => true;
+
+  String _shortUri;
+
+  Script._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  /// Retrieves line number [line] if it exists.
+  ScriptLine getLine(int line) {
+    assert(_loaded);
+    assert(line >= 1);
+    var index = (line - lineOffset - 1);
+    if (lines.length < index) {
+      return null;
+    }
+    return lines[line - lineOffset - 1];
+  }
+
+  /// This function maps a token position to a line number.
+  /// The VM considers the first line to be line 1.
+  int tokenToLine(int tokenPos) => _tokenToLine[tokenPos];
+  Map _tokenToLine = {};
+
+  /// This function maps a token position to a column number.
+  /// The VM considers the first column to be column 1.
+  int tokenToCol(int tokenPos) => _tokenToCol[tokenPos];
+  Map _tokenToCol = {};
+
+  int guessTokenLength(int line, int column) {
+    String source = getLine(line).text;
+
+    var pos = column;
+    if (pos >= source.length) {
+      return null;
+    }
+
+    var c = source.codeUnitAt(pos);
+    if (c == 123) return 1; // { - Map literal
+
+    if (c == 91) return 1; // [ - List literal, index, index assignment
+
+    if (c == 40) return 1; // ( - Closure call
+
+    if (_isOperatorChar(c)) {
+      while (++pos < source.length && _isOperatorChar(source.codeUnitAt(pos)));
+      return pos - column;
+    }
+
+    if (_isInitialIdentifierChar(c)) {
+      while (
+          ++pos < source.length && _isIdentifierChar(source.codeUnitAt(pos)));
+      return pos - column;
+    }
+
+    return null;
+  }
+
+  static bool _isOperatorChar(int c) {
+    switch (c) {
+      case 25: // %
+      case 26: // &
+      case 42: // *
+      case 43: // +
+      case 45: // -:
+      case 47: // /
+      case 60: // <
+      case 61: // =
+      case 62: // >
+      case 94: // ^
+      case 124: // |
+      case 126: // ~
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  static bool _isInitialIdentifierChar(int c) {
+    if (c >= 65 && c <= 90) return true; // Upper
+    if (c >= 97 && c <= 122) return true; // Lower
+    if (c == 95) return true; // Underscore
+    if (c == 36) return true; // Dollar
+    return false;
+  }
+
+  static bool _isIdentifierChar(int c) {
+    if (_isInitialIdentifierChar(c)) return true;
+    return c >= 48 && c <= 57; // Digit
+  }
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    uri = map['uri'];
+    kind = map['_kind'];
+    _shortUri = uri.substring(uri.lastIndexOf('/') + 1);
+    name = _shortUri;
+    vmName = uri;
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    int loadTimeMillis = map['_loadTime'];
+    loadTime = new DateTime.fromMillisecondsSinceEpoch(loadTimeMillis);
+    lineOffset = map['lineOffset'];
+    columnOffset = map['columnOffset'];
+    _parseTokenPosTable(map['tokenPosTable']);
+    source = map['source'];
+    _processSource(map['source']);
+    library = map['library'];
+  }
+
+  void _parseTokenPosTable(List table) {
+    if (table == null) {
+      return;
+    }
+    _tokenToLine.clear();
+    _tokenToCol.clear();
+    firstTokenPos = null;
+    lastTokenPos = null;
+    var lineSet = new Set();
+
+    for (List line in table) {
+      // Each entry begins with a line number...
+      int lineNumber = line[0];
+      lineSet.add(lineNumber);
+      for (var pos = 1; pos < line.length; pos += 2) {
+        // ...and is followed by (token offset, col number) pairs.
+        int tokenOffset = line[pos];
+        int colNumber = line[pos + 1];
+        if (firstTokenPos == null) {
+          // Mark first token position.
+          firstTokenPos = tokenOffset;
+          lastTokenPos = tokenOffset;
+        } else {
+          // Keep track of max and min token positions.
+          firstTokenPos =
+              (firstTokenPos <= tokenOffset) ? firstTokenPos : tokenOffset;
+          lastTokenPos =
+              (lastTokenPos >= tokenOffset) ? lastTokenPos : tokenOffset;
+        }
+        _tokenToLine[tokenOffset] = lineNumber;
+        _tokenToCol[tokenOffset] = colNumber;
+      }
+    }
+  }
+
+  void _processSource(String source) {
+    if (source == null) {
+      return;
+    }
+    var sourceLines = source.split('\n');
+    if (sourceLines.length == 0) {
+      return;
+    }
+    lines.clear();
+    Logger.root.info('Adding ${sourceLines.length} source lines for ${uri}');
+    for (var i = 0; i < sourceLines.length; i++) {
+      lines.add(new ScriptLine(this, i + lineOffset + 1, sourceLines[i]));
+    }
+    for (var bpt in isolate.breakpoints.values) {
+      if (bpt.location.script == this) {
+        _addBreakpoint(bpt);
+      }
+    }
+  }
+
+  // Note, this may return source beyond the token length if [guessTokenLength]
+  // fails.
+  String getToken(int tokenPos) {
+    final int line = tokenToLine(tokenPos);
+    int column = tokenToCol(tokenPos);
+    if ((line == null) || (column == null)) {
+      return null;
+    }
+    // Line and column numbers start at 1 in the VM.
+    column -= 1;
+    String sourceLine = getLine(line)?.text;
+    if (sourceLine == null) {
+      return null;
+    }
+    final int length = guessTokenLength(line, column);
+    if (length == null) {
+      return sourceLine.substring(column);
+    } else {
+      return sourceLine.substring(column, column + length);
+    }
+  }
+
+  void _addBreakpoint(Breakpoint bpt) {
+    var line;
+    if (bpt.location.tokenPos != null) {
+      line = tokenToLine(bpt.location.tokenPos);
+    } else {
+      UnresolvedSourceLocation loc = bpt.location;
+      line = loc.line;
+    }
+    getLine(line)?.addBreakpoint(bpt);
+  }
+
+  void _removeBreakpoint(Breakpoint bpt) {
+    var line;
+    if (bpt.location.tokenPos != null) {
+      line = tokenToLine(bpt.location.tokenPos);
+    } else {
+      UnresolvedSourceLocation loc = bpt.location;
+      line = loc.line;
+    }
+    if (line != null) {
+      getLine(line)?.removeBreakpoint(bpt);
+    }
+  }
+
+  List<LocalVarLocation> scanLineForLocalVariableLocations(Pattern pattern,
+      String name, String lineContents, int lineNumber, int columnOffset) {
+    var r = <LocalVarLocation>[];
+
+    pattern.allMatches(lineContents).forEach((Match match) {
+      // We have a match but our regular expression may have matched extra
+      // characters on either side of the name. Tighten the location.
+      var nameStart = match.input.indexOf(name, match.start);
+      var column = nameStart + columnOffset;
+      var endColumn = column + name.length;
+      var localVarLocation =
+          new LocalVarLocation(lineNumber, column, endColumn);
+      r.add(localVarLocation);
+    });
+
+    return r;
+  }
+
+  List<LocalVarLocation> scanForLocalVariableLocations(
+      String name, int tokenPos, int endTokenPos) {
+    // A pattern that matches:
+    // start of line OR non-(alpha numeric OR period) character followed by
+    // name followed by
+    // a non-alpha numerc character.
+    //
+    // NOTE: This pattern can over match on both ends. This is corrected for
+    // [scanLineForLocalVariableLocationse].
+    var pattern = new RegExp("(^|[^A-Za-z0-9\.])$name[^A-Za-z0-9]");
+
+    // Result.
+    var r = <LocalVarLocation>[];
+
+    // Limits.
+    final lastLine = tokenToLine(endTokenPos);
+    if (lastLine == null) {
+      return r;
+    }
+
+    var lastColumn = tokenToCol(endTokenPos);
+    if (lastColumn == null) {
+      return r;
+    }
+    // Current scan position.
+    var line = tokenToLine(tokenPos);
+    if (line == null) {
+      return r;
+    }
+    var column = tokenToCol(tokenPos);
+    if (column == null) {
+      return r;
+    }
+
+    // Move back by name length.
+    // TODO(johnmccutchan): Fix LocalVarDescriptor to set column before the
+    // identifier name.
+    column = math.max(0, column - name.length);
+
+    var lineContents;
+
+    if (line == lastLine) {
+      // Only one line.
+      if (!getLine(line).isTrivial) {
+        // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
+        // code. e.g.:
+        // io_sink.dart source line 23 ends at column 39
+        // io_sink.dart snapshotted source line 23 ends at column 35.
+        lastColumn = math.min(getLine(line).text.length, lastColumn);
+        lineContents = getLine(line).text.substring(column, lastColumn - 1);
+        return scanLineForLocalVariableLocations(
+            pattern, name, lineContents, line, column);
+      }
+    }
+
+    // Scan first line.
+    if (!getLine(line).isTrivial) {
+      lineContents = getLine(line).text.substring(column);
+      r.addAll(scanLineForLocalVariableLocations(
+          pattern, name, lineContents, line++, column));
+    }
+
+    // Scan middle lines.
+    while (line < (lastLine - 1)) {
+      if (getLine(line).isTrivial) {
+        line++;
+        continue;
+      }
+      lineContents = getLine(line).text;
+      r.addAll(scanLineForLocalVariableLocations(
+          pattern, name, lineContents, line++, 0));
+    }
+
+    // Scan last line.
+    if (!getLine(line).isTrivial) {
+      // TODO(johnmccutchan): end token pos -> column can lie for snapshotted
+      // code. e.g.:
+      // io_sink.dart source line 23 ends at column 39
+      // io_sink.dart snapshotted source line 23 ends at column 35.
+      lastColumn = math.min(getLine(line).text.length, lastColumn);
+      lineContents = getLine(line).text.substring(0, lastColumn - 1);
+      r.addAll(scanLineForLocalVariableLocations(
+          pattern, name, lineContents, line, 0));
+    }
+    return r;
+  }
+}
+
+class PcDescriptor {
+  final int pcOffset;
+  final int deoptId;
+  final int tokenPos;
+  final int tryIndex;
+  final String kind;
+  Script script;
+  String formattedLine;
+  PcDescriptor(
+      this.pcOffset, this.deoptId, this.tokenPos, this.tryIndex, this.kind);
+
+  String formattedDeoptId() {
+    if (deoptId == -1) {
+      return 'N/A';
+    }
+    return deoptId.toString();
+  }
+
+  String formattedTokenPos() {
+    if (tokenPos == -1) {
+      return '';
+    }
+    return tokenPos.toString();
+  }
+
+  void processScript(Script script) {
+    this.script = null;
+    if (tokenPos == -1) {
+      return;
+    }
+    var line = script.tokenToLine(tokenPos);
+    if (line == null) {
+      return;
+    }
+    this.script = script;
+    var scriptLine = script.getLine(line);
+    formattedLine = scriptLine.text;
+  }
+}
+
+class PcDescriptors extends ServiceObject implements M.PcDescriptorsRef {
+  Class clazz;
+  int size;
+  bool get immutable => true;
+  final List<PcDescriptor> descriptors = <PcDescriptor>[];
+
+  PcDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner) {}
+
+  void _update(Map m, bool mapIsRef) {
+    if (mapIsRef) {
+      return;
+    }
+    _upgradeCollection(m, isolate);
+    clazz = m['class'];
+    size = m['size'];
+    descriptors.clear();
+    for (var descriptor in m['members']) {
+      var pcOffset = int.parse(descriptor['pcOffset'], radix: 16);
+      var deoptId = descriptor['deoptId'];
+      var tokenPos = descriptor['tokenPos'];
+      var tryIndex = descriptor['tryIndex'];
+      var kind = descriptor['kind'].trim();
+      descriptors
+          .add(new PcDescriptor(pcOffset, deoptId, tokenPos, tryIndex, kind));
+    }
+  }
+}
+
+class LocalVarDescriptor implements M.LocalVarDescriptorsRef {
+  final String id;
+  final String name;
+  final int index;
+  final int declarationPos;
+  final int beginPos;
+  final int endPos;
+  final int scopeId;
+  final String kind;
+
+  LocalVarDescriptor(this.id, this.name, this.index, this.declarationPos,
+      this.beginPos, this.endPos, this.scopeId, this.kind);
+}
+
+class LocalVarDescriptors extends ServiceObject {
+  Class clazz;
+  int size;
+  bool get immutable => true;
+  final List<LocalVarDescriptor> descriptors = <LocalVarDescriptor>[];
+  LocalVarDescriptors._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map m, bool mapIsRef) {
+    if (mapIsRef) {
+      return;
+    }
+    _upgradeCollection(m, isolate);
+    clazz = m['class'];
+    size = m['size'];
+    descriptors.clear();
+    for (var descriptor in m['members']) {
+      var id = descriptor['name'];
+      var name = descriptor['name'];
+      var index = descriptor['index'];
+      var declarationPos = descriptor['declarationTokenPos'];
+      var beginPos = descriptor['scopeStartTokenPos'];
+      var endPos = descriptor['scopeEndTokenPos'];
+      var scopeId = descriptor['scopeId'];
+      var kind = descriptor['kind'].trim();
+      descriptors.add(new LocalVarDescriptor(
+          id, name, index, declarationPos, beginPos, endPos, scopeId, kind));
+    }
+  }
+}
+
+class ObjectPool extends HeapObject implements M.ObjectPool {
+  bool get immutable => false;
+
+  int length;
+  List<ObjectPoolEntry> entries;
+
+  ObjectPool._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    length = map['length'];
+    if (mapIsRef) {
+      return;
+    }
+    entries = map['_entries']
+        .map<ObjectPoolEntry>((map) => new ObjectPoolEntry(map))
+        .toList();
+  }
+}
+
+class ObjectPoolEntry implements M.ObjectPoolEntry {
+  final int offset;
+  final M.ObjectPoolEntryKind kind;
+  final M.ObjectRef asObject;
+  final int asInteger;
+
+  factory ObjectPoolEntry(map) {
+    M.ObjectPoolEntryKind kind = stringToObjectPoolEntryKind(map['kind']);
+    int offset = map['offset'];
+    switch (kind) {
+      case M.ObjectPoolEntryKind.nativeEntryData:
+      case M.ObjectPoolEntryKind.object:
+        return new ObjectPoolEntry._fromObject(map['value'], offset);
+      default:
+        return new ObjectPoolEntry._fromInteger(kind, map['value'], offset);
+    }
+  }
+
+  ObjectPoolEntry._fromObject(this.asObject, this.offset)
+      : kind = M.ObjectPoolEntryKind.object,
+        asInteger = null;
+
+  ObjectPoolEntry._fromInteger(this.kind, this.asInteger, this.offset)
+      : asObject = null;
+}
+
+M.ObjectPoolEntryKind stringToObjectPoolEntryKind(String kind) {
+  switch (kind) {
+    case 'Object':
+      return M.ObjectPoolEntryKind.object;
+    case 'Immediate':
+      return M.ObjectPoolEntryKind.immediate;
+    case 'NativeEntryData':
+      return M.ObjectPoolEntryKind.nativeEntryData;
+    case 'NativeFunction':
+    case 'NativeFunctionWrapper':
+      return M.ObjectPoolEntryKind.nativeEntry;
+  }
+  throw new Exception('Unknown ObjectPoolEntryKind ($kind)');
+}
+
+class ICData extends HeapObject implements M.ICData {
+  HeapObject dartOwner;
+  String selector;
+  Instance argumentsDescriptor;
+  Instance entries;
+
+  bool get immutable => false;
+
+  ICData._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    dartOwner = map['_owner'];
+    selector = map['_selector'];
+    if (mapIsRef) {
+      return;
+    }
+    argumentsDescriptor = map['_argumentsDescriptor'];
+    entries = map['_entries'];
+  }
+}
+
+class UnlinkedCall extends HeapObject implements M.UnlinkedCall {
+  String selector;
+  Instance argumentsDescriptor;
+
+  bool get immutable => false;
+
+  UnlinkedCall._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    selector = map['_selector'];
+    if (mapIsRef) {
+      return;
+    }
+    argumentsDescriptor = map['_argumentsDescriptor'];
+  }
+}
+
+class SingleTargetCache extends HeapObject implements M.SingleTargetCache {
+  Code target;
+  int lowerLimit;
+  int upperLimit;
+
+  bool get immutable => false;
+
+  SingleTargetCache._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    target = map['_target'];
+    if (mapIsRef) {
+      return;
+    }
+    lowerLimit = map['_lowerLimit'];
+    upperLimit = map['_upperLimit'];
+  }
+}
+
+class SubtypeTestCache extends HeapObject implements M.SubtypeTestCache {
+  Instance cache;
+
+  bool get immutable => false;
+
+  SubtypeTestCache._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    if (mapIsRef) {
+      return;
+    }
+    cache = map['_cache'];
+  }
+}
+
+class TypeArguments extends HeapObject implements M.TypeArguments {
+  HeapObject dartOwner;
+  String name;
+  Iterable<Instance> types;
+
+  TypeArguments._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    dartOwner = map['_owner'];
+    name = map['name'];
+    if (mapIsRef) {
+      return;
+    }
+    types = new List<Instance>.from(map['types']);
+  }
+}
+
+class InstanceSet extends HeapObject implements M.InstanceSet {
+  HeapObject dartOwner;
+  int count;
+  Iterable<HeapObject> instances;
+
+  InstanceSet._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    if (mapIsRef) {
+      return;
+    }
+    count = map['totalCount'];
+    instances = new List<HeapObject>.from(map['instances']);
+  }
+}
+
+class MegamorphicCache extends HeapObject implements M.MegamorphicCache {
+  int mask;
+  Instance buckets;
+  String selector;
+  Instance argumentsDescriptor;
+
+  bool get immutable => false;
+
+  MegamorphicCache._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    _upgradeCollection(map, isolate);
+    super._update(map, mapIsRef);
+
+    selector = map['_selector'];
+    if (mapIsRef) {
+      return;
+    }
+
+    mask = map['_mask'];
+    buckets = map['_buckets'];
+    argumentsDescriptor = map['_argumentsDescriptor'];
+  }
+}
+
+class CodeInstruction {
+  final int address;
+  final int pcOffset;
+  final String machine;
+  final String human;
+  final ServiceObject object;
+  CodeInstruction jumpTarget;
+  List<PcDescriptor> descriptors = <PcDescriptor>[];
+
+  CodeInstruction(
+      this.address, this.pcOffset, this.machine, this.human, this.object);
+
+  bool get isComment => address == 0;
+  bool get hasDescriptors => descriptors.length > 0;
+
+  bool _isJumpInstruction() {
+    return human.startsWith('j');
+  }
+
+  int _getJumpAddress() {
+    assert(_isJumpInstruction());
+    var chunks = human.split(' ');
+    if (chunks.length != 2) {
+      // We expect jump instructions to be of the form 'j.. address'.
+      return 0;
+    }
+    var address = chunks[1];
+    if (address.startsWith('0x')) {
+      // Chop off the 0x.
+      address = address.substring(2);
+    }
+    try {
+      return int.parse(address, radix: 16);
+    } catch (_) {
+      return 0;
+    }
+  }
+
+  void _resolveJumpTarget(
+      List<CodeInstruction> instructionsByAddressOffset, int startAddress) {
+    if (!_isJumpInstruction()) {
+      return;
+    }
+    int address = _getJumpAddress();
+    if (address == 0) {
+      return;
+    }
+    var relativeAddress = address - startAddress;
+    if (relativeAddress < 0) {
+      Logger.root.warning('Bad address resolving jump target $relativeAddress');
+      return;
+    }
+    if (relativeAddress >= instructionsByAddressOffset.length) {
+      Logger.root.warning('Bad address resolving jump target $relativeAddress');
+      return;
+    }
+    jumpTarget = instructionsByAddressOffset[relativeAddress];
+  }
+}
+
+M.CodeKind stringToCodeKind(String s) {
+  if (s == 'Native') {
+    return M.CodeKind.native;
+  } else if (s == 'Dart') {
+    return M.CodeKind.dart;
+  } else if (s == 'Collected') {
+    return M.CodeKind.collected;
+  } else if (s == 'Tag') {
+    return M.CodeKind.tag;
+  } else if (s == 'Stub') {
+    return M.CodeKind.stub;
+  }
+  var message = 'Unrecognized code kind: $s';
+  Logger.root.severe(message);
+  throw new ArgumentError(message);
+}
+
+class CodeInlineInterval {
+  final int start;
+  final int end;
+  final List<ServiceFunction> functions = <ServiceFunction>[];
+  bool contains(int pc) => (pc >= start) && (pc < end);
+  CodeInlineInterval(this.start, this.end);
+}
+
+class Code extends HeapObject implements M.Code {
+  M.CodeKind kind;
+  ObjectPool objectPool;
+  ServiceFunction function;
+  Script script;
+  bool isOptimized;
+  bool hasIntrinsic;
+  bool isNative;
+
+  int startAddress = 0;
+  int endAddress = 0;
+  final instructions = <CodeInstruction>[];
+  List<CodeInstruction> instructionsByAddressOffset;
+
+  ProfileCode profile;
+  final List<CodeInlineInterval> inlineIntervals = <CodeInlineInterval>[];
+  final List<ServiceFunction> inlinedFunctions = <ServiceFunction>[];
+
+  bool get immutable => true;
+
+  Code._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  void _updateDescriptors(Script script) {
+    this.script = script;
+    for (var instruction in instructions) {
+      for (var descriptor in instruction.descriptors) {
+        descriptor.processScript(script);
+      }
+    }
+  }
+
+  Future loadScript() {
+    if (script != null) {
+      // Already done.
+      return null;
+    }
+    if (kind != M.CodeKind.dart) {
+      return null;
+    }
+    if (function == null) {
+      return null;
+    }
+    if ((function.location == null) || (function.location.script == null)) {
+      // Attempt to load the function.
+      return function.load().then((func) {
+        var script = function.location.script;
+        if (script == null) {
+          // Function doesn't have an associated script.
+          return null;
+        }
+        // Load the script and then update descriptors.
+        return script.load().then((_) => _updateDescriptors(script));
+      });
+    }
+    {
+      // Load the script and then update descriptors.
+      var script = function.location.script;
+      return script.load().then((_) => _updateDescriptors(script));
+    }
+  }
+
+  /// Reload [this]. Returns a future which completes to [this] or an
+  /// exception.
+  Future<ServiceObject> reload({int count: kDefaultFieldLimit}) {
+    assert(kind != null);
+    if (isDartCode) {
+      // We only reload Dart code.
+      return super.reload(count: count);
+    }
+    return new Future.value(this);
+  }
+
+  void _update(Map m, bool mapIsRef) {
+    name = m['name'];
+    vmName = (m.containsKey('_vmName') ? m['_vmName'] : name);
+    isOptimized = m['_optimized'];
+    kind = stringToCodeKind(m['kind']);
+    hasIntrinsic = m['_intrinsic'];
+    isNative = m['_native'];
+    if (mapIsRef) {
+      return;
+    }
+    _loaded = true;
+    startAddress = int.parse(m['_startAddress'], radix: 16);
+    endAddress = int.parse(m['_endAddress'], radix: 16);
+    function = isolate.getFromMap(m['function']);
+    objectPool = isolate.getFromMap(m['_objectPool']);
+    var disassembly = m['_disassembly'];
+    if (disassembly != null) {
+      _processDisassembly(disassembly);
+    }
+    var descriptors = m['_descriptors'];
+    if (descriptors != null) {
+      descriptors = descriptors['members'];
+      _processDescriptors(descriptors);
+    }
+    hasDisassembly = (instructions.length != 0) && (kind == M.CodeKind.dart);
+    inlinedFunctions.clear();
+    var inlinedFunctionsTable = m['_inlinedFunctions'];
+    var inlinedIntervals = m['_inlinedIntervals'];
+    if (inlinedFunctionsTable != null) {
+      // Iterate and upgrade each ServiceFunction.
+      for (var i = 0; i < inlinedFunctionsTable.length; i++) {
+        // Upgrade each function and set it back in the list.
+        var func = isolate.getFromMap(inlinedFunctionsTable[i]);
+        inlinedFunctionsTable[i] = func;
+        if (!inlinedFunctions.contains(func)) {
+          inlinedFunctions.add(func);
+        }
+      }
+    }
+    if ((inlinedIntervals == null) || (inlinedFunctionsTable == null)) {
+      // No inline information.
+      inlineIntervals.clear();
+      return;
+    }
+    _processInline(inlinedFunctionsTable, inlinedIntervals);
+
+    _upgradeCollection(m, isolate);
+    super._update(m, mapIsRef);
+  }
+
+  CodeInlineInterval findInterval(int pc) {
+    for (var i = 0; i < inlineIntervals.length; i++) {
+      var interval = inlineIntervals[i];
+      if (interval.contains(pc)) {
+        return interval;
+      }
+    }
+    return null;
+  }
+
+  void _processInline(List/*<ServiceFunction>*/ inlinedFunctionsTable,
+      List/*<List<int>>*/ inlinedIntervals) {
+    for (var i = 0; i < inlinedIntervals.length; i++) {
+      var inlinedInterval = inlinedIntervals[i];
+      var start = inlinedInterval[0] + startAddress;
+      var end = inlinedInterval[1] + startAddress;
+      var codeInlineInterval = new CodeInlineInterval(start, end);
+      for (var i = 2; i < inlinedInterval.length - 1; i++) {
+        var inline_id = inlinedInterval[i];
+        if (inline_id < 0) {
+          continue;
+        }
+        var function = inlinedFunctionsTable[inline_id];
+        codeInlineInterval.functions.add(function);
+      }
+      inlineIntervals.add(codeInlineInterval);
+    }
+  }
+
+  bool hasDisassembly = false;
+
+  void _processDisassembly(List disassembly) {
+    assert(disassembly != null);
+    instructions.clear();
+    instructionsByAddressOffset = new List(endAddress - startAddress);
+
+    assert((disassembly.length % 4) == 0);
+    for (var i = 0; i < disassembly.length; i += 4) {
+      var address = 0; // Assume code comment.
+      var machine = disassembly[i + 1];
+      var human = disassembly[i + 2];
+      var object = disassembly[i + 3];
+      if (object != null) {
+        object = new ServiceObject._fromMap(owner, object);
+      }
+      var pcOffset = 0;
+      if (disassembly[i] != null) {
+        // Not a code comment, extract address.
+        address = int.parse(disassembly[i], radix: 16);
+        pcOffset = address - startAddress;
+      }
+      var instruction =
+          new CodeInstruction(address, pcOffset, machine, human, object);
+      instructions.add(instruction);
+      if (disassembly[i] != null) {
+        // Not a code comment.
+        instructionsByAddressOffset[pcOffset] = instruction;
+      }
+    }
+    for (var instruction in instructions) {
+      instruction._resolveJumpTarget(instructionsByAddressOffset, startAddress);
+    }
+  }
+
+  void _processDescriptors(List descriptors) {
+    for (Map descriptor in descriptors) {
+      var pcOffset = int.parse(descriptor['pcOffset'], radix: 16);
+      var address = startAddress + pcOffset;
+      var deoptId = descriptor['deoptId'];
+      var tokenPos = descriptor['tokenPos'];
+      var tryIndex = descriptor['tryIndex'];
+      var kind = descriptor['kind'].trim();
+
+      var instruction = instructionsByAddressOffset[address - startAddress];
+      if (instruction != null) {
+        instruction.descriptors
+            .add(new PcDescriptor(pcOffset, deoptId, tokenPos, tryIndex, kind));
+      } else {
+        Logger.root.warning(
+            'Could not find instruction with pc descriptor address: $address');
+      }
+    }
+  }
+
+  /// Returns true if [address] is contained inside [this].
+  bool contains(int address) {
+    return (address >= startAddress) && (address < endAddress);
+  }
+
+  bool get isDartCode => (kind == M.CodeKind.dart) || (kind == M.CodeKind.stub);
+
+  String toString() => 'Code($kind, $name)';
+}
+
+class SocketKind {
+  final _value;
+  const SocketKind._internal(this._value);
+  String toString() => '$_value';
+
+  static SocketKind fromString(String s) {
+    if (s == 'Listening') {
+      return Listening;
+    } else if (s == 'Normal') {
+      return Normal;
+    } else if (s == 'Pipe') {
+      return Pipe;
+    } else if (s == 'Internal') {
+      return Internal;
+    }
+    var message = 'Unrecognized socket kind: $s';
+    Logger.root.warning(message);
+    throw new ArgumentError(message);
+  }
+
+  static const Listening = const SocketKind._internal('Listening');
+  static const Normal = const SocketKind._internal('Normal');
+  static const Pipe = const SocketKind._internal('Pipe');
+  static const Internal = const SocketKind._internal('Internal');
+}
+
+/// A snapshot of statistics associated with a [Socket].
+class SocketStats {
+  final int bytesRead;
+  final int bytesWritten;
+  final int readCalls;
+  final int writeCalls;
+  final int available;
+
+  SocketStats(this.bytesRead, this.bytesWritten, this.readCalls,
+      this.writeCalls, this.available);
+}
+
+/// A peer to a Socket in dart:io. Sockets can represent network sockets or
+/// OS pipes. Each socket is owned by another ServceObject, for example,
+/// a process or an HTTP server.
+class Socket extends ServiceObject {
+  Socket._empty(ServiceObjectOwner owner) : super._empty(owner);
+
+  ServiceObject socketOwner;
+
+  bool get isPipe => (kind == SocketKind.Pipe);
+
+  SocketStats latest;
+  SocketStats previous;
+
+  SocketKind kind;
+
+  String protocol = '';
+
+  bool readClosed = false;
+  bool writeClosed = false;
+  bool closing = false;
+
+  /// Listening for connections.
+  bool listening = false;
+
+  int fd;
+
+  String localAddress;
+  int localPort;
+  String remoteAddress;
+  int remotePort;
+
+  // Updates internal state from [map]. [map] can be a reference.
+  void _update(Map map, bool mapIsRef) {
+    name = map['name'];
+    vmName = map['name'];
+
+    kind = SocketKind.fromString(map['kind']);
+
+    if (mapIsRef) {
+      return;
+    }
+
+    _loaded = true;
+
+    _upgradeCollection(map, isolate);
+
+    readClosed = map['readClosed'];
+    writeClosed = map['writeClosed'];
+    closing = map['closing'];
+    listening = map['listening'];
+
+    protocol = map['protocol'];
+
+    localAddress = map['localAddress'];
+    localPort = map['localPort'];
+    remoteAddress = map['remoteAddress'];
+    remotePort = map['remotePort'];
+
+    fd = map['fd'];
+    socketOwner = map['owner'];
+  }
+}
+
+class ServiceMetric extends ServiceObject implements M.Metric {
+  ServiceMetric._empty(ServiceObjectOwner owner) : super._empty(owner) {}
+
+  bool get immutable => false;
+
+  Future<Map> _fetchDirect({int count: kDefaultFieldLimit}) {
+    assert(owner is Isolate);
+    return isolate.invokeRpcNoUpgrade('_getIsolateMetric', {'metricId': id});
+  }
+
+  String description;
+  double value = 0.0;
+  // Only a gauge has a non-null min and max.
+  double min;
+  double max;
+
+  bool get isGauge => (min != null) && (max != null);
+
+  void _update(Map map, bool mapIsRef) {
+    name = map['name'];
+    description = map['description'];
+    vmName = map['name'];
+    value = map['value'];
+    min = map['min'];
+    max = map['max'];
+  }
+
+  String toString() => "ServiceMetric($_id)";
+}
+
+Future<Null> printFrames(List frames) async {
+  for (int i = 0; i < frames.length; i++) {
+    final Frame frame = frames[i];
+    String frameText = await frame.toUserString();
+    print('#${i.toString().padLeft(3)}: $frameText');
+  }
+}
+
+class Frame extends ServiceObject implements M.Frame {
+  M.FrameKind kind = M.FrameKind.regular;
+  int index;
+  ServiceFunction function;
+  SourceLocation location;
+  Code code;
+  List<ServiceMap> variables = <ServiceMap>[];
+  String marker;
+
+  Frame._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _loaded = true;
+    _upgradeCollection(map, owner);
+    this.kind = _fromString(map['kind']);
+    this.marker = map['marker'];
+    this.index = map['index'];
+    this.function = map['function'];
+    this.location = map['location'];
+    this.code = map['code'];
+    if (map['vars'] == null) {
+      this.variables = <ServiceMap>[];
+    } else {
+      this.variables = new List<ServiceMap>.from(map['vars']);
+    }
+  }
+
+  M.FrameKind _fromString(String frameKind) {
+    if (frameKind == null) {
+      return M.FrameKind.regular;
+    }
+    switch (frameKind) {
+      case 'Regular':
+        return M.FrameKind.regular;
+      case 'AsyncCausal':
+        return M.FrameKind.asyncCausal;
+      case 'AsyncSuspensionMarker':
+        return M.FrameKind.asyncSuspensionMarker;
+      case 'AsyncActivation':
+        return M.FrameKind.asyncActivation;
+      default:
+        throw new UnsupportedError('Unknown FrameKind: $frameKind');
+    }
+  }
+
+  String toString() {
+    if (function != null) {
+      return "Frame([$kind] ${function.qualifiedName} $location)";
+    } else if (location != null) {
+      return "Frame([$kind] $location)";
+    } else {
+      return "Frame([$kind])";
+    }
+  }
+
+  Future<String> toUserString() async {
+    if (function != null) {
+      return "Frame([$kind] ${function.qualifiedName} "
+          "${await location.toUserString()})";
+    } else if (location != null) {
+      return "Frame([$kind] ${await location.toUserString()}";
+    } else {
+      return "Frame([$kind])";
+    }
+  }
+}
+
+class ServiceMessage extends ServiceObject {
+  int index;
+  String messageObjectId;
+  int size;
+  ServiceFunction handler;
+  SourceLocation location;
+
+  ServiceMessage._empty(ServiceObject owner) : super._empty(owner);
+
+  void _update(Map map, bool mapIsRef) {
+    assert(!mapIsRef);
+    _loaded = true;
+    _upgradeCollection(map, owner);
+    this.messageObjectId = map['messageObjectId'];
+    this.index = map['index'];
+    this.size = map['size'];
+    this.handler = map['handler'];
+    this.location = map['location'];
+  }
+}
+
+// Helper function to extract possible breakpoint locations from a
+// SourceReport for some script.
+Set<int> getPossibleBreakpointLines(ServiceMap report, Script script) {
+  var result = new Set<int>();
+  int scriptIndex;
+  int numScripts = report['scripts'].length;
+  for (scriptIndex = 0; scriptIndex < numScripts; scriptIndex++) {
+    if (report['scripts'][scriptIndex].id == script.id) {
+      break;
+    }
+  }
+  if (scriptIndex == numScripts) {
+    return result;
+  }
+  if (script.source == null) {
+    return result;
+  }
+  var ranges = report['ranges'];
+  if (ranges != null) {
+    for (var range in ranges) {
+      if (range['scriptIndex'] != scriptIndex) {
+        continue;
+      }
+      if (range['compiled']) {
+        var possibleBpts = range['possibleBreakpoints'];
+        if (possibleBpts != null) {
+          for (var tokenPos in possibleBpts) {
+            result.add(script.tokenToLine(tokenPos));
+          }
+        }
+      } else {
+        int startLine = script.tokenToLine(range['startPos']);
+        int endLine = script.tokenToLine(range['endPos']);
+        for (int line = startLine; line <= endLine; line++) {
+          if (!script.getLine(line).isTrivial) {
+            result.add(line);
+          }
+        }
+      }
+    }
+  }
+  return result;
+}
+
+// Returns true if [map] is a service map. i.e. it has the following keys:
+// 'id' and a 'type'.
+bool _isServiceMap(Map m) {
+  return (m != null) && (m['type'] != null);
+}
+
+bool _hasRef(String type) => type.startsWith('@');
+String _stripRef(String type) => (_hasRef(type) ? type.substring(1) : type);
+
+/// Recursively upgrades all [ServiceObject]s inside [collection] which must
+/// be an [Map] or an [List]. Upgraded elements will be
+/// associated with [vm] and [isolate].
+void _upgradeCollection(collection, ServiceObjectOwner owner) {
+  if (collection is ServiceMap) {
+    return; // Already upgraded.
+  }
+
+  if (collection is Map) {
+    _upgradeMap(collection, owner);
+  } else if (collection is List) {
+    _upgradeList(collection, owner);
+  }
+}
+
+void _upgradeMap(Map map, ServiceObjectOwner owner) {
+  map.forEach((k, v) {
+    if ((v is Map) && _isServiceMap(v)) {
+      map[k] = owner.getFromMap(v);
+    } else if (v is List) {
+      _upgradeList(v, owner);
+    } else if (v is Map) {
+      _upgradeMap(v, owner);
+    }
+  });
+}
+
+void _upgradeList(List list, ServiceObjectOwner owner) {
+  if (list is Uint8List) {
+    // Nothing to upgrade; avoid slowly visiting every byte
+    // of large binary responses.
+    return;
+  }
+
+  for (var i = 0; i < list.length; i++) {
+    var v = list[i];
+    if ((v is Map) && _isServiceMap(v)) {
+      list[i] = owner.getFromMap(v);
+    } else if (v is List) {
+      _upgradeList(v, owner);
+    } else if (v is Map) {
+      _upgradeMap(v, owner);
+    }
+  }
+}
+
+class Service implements M.Service {
+  final String alias;
+  final String method;
+  final String service;
+
+  Service(this.alias, this.method, this.service) {
+    assert(this.alias != null);
+    assert(this.method != null);
+    assert(this.service != null);
+  }
+}
+
+class TimelineRecorder implements M.TimelineRecorder {
+  final String name;
+  const TimelineRecorder(this.name);
+}
+
+class TimelineStream implements M.TimelineStream {
+  final String name;
+  final bool isRecorded;
+  const TimelineStream(this.name, this.isRecorded);
+}
+
+class TimelineProfile implements M.TimelineProfile {
+  final String name;
+  final Iterable<TimelineStream> streams;
+  const TimelineProfile(this.name, this.streams);
+}
+
+class TimelineFlags implements M.TimelineFlags {
+  // Dart developers care about the following streams:
+  static final Set<String> _dart =
+      new Set<String>.from(const <String>['GC', 'Compiler', 'Dart']);
+
+  // Dart developers care about the following streams:
+  static final Set<String> _flutter =
+      new Set<String>.from(const <String>['GC', 'Dart', 'Embedder']);
+
+  // VM developers care about the following streams:
+  static final Set<String> _vm = new Set<String>.from(const <String>[
+    'GC',
+    'Compiler',
+    'Dart',
+    'Debugger',
+    'Embedder',
+    'Isolate',
+    'VM',
+  ]);
+
+  final TimelineRecorder recorder;
+  final List<TimelineStream> streams;
+  final List<TimelineProfile> profiles;
+
+  factory TimelineFlags(ServiceMap response) {
+    assert(response['type'] == 'TimelineFlags');
+
+    assert(response['recorderName'] != null);
+    final TimelineRecorder recorder =
+        new TimelineRecorder(response['recorderName']);
+
+    assert(response['recordedStreams'] != null);
+    final Set<String> recorded =
+        new Set<String>.from(response['recordedStreams']);
+
+    assert(response['availableStreams'] != null);
+    final List<TimelineStream> streams = response['availableStreams']
+        .map<TimelineStream>((/*String*/ name) =>
+            new TimelineStream(name, recorded.contains(name)))
+        .toList();
+
+    final List<TimelineProfile> profiles = [
+      const TimelineProfile('None', const []),
+      new TimelineProfile('Dart Developer',
+          streams.where((s) => _dart.contains(s.name)).toList()),
+      new TimelineProfile('Flutter Developer',
+          streams.where((s) => _flutter.contains(s.name)).toList()),
+      new TimelineProfile(
+          'VM Developer', streams.where((s) => _vm.contains(s.name)).toList()),
+      new TimelineProfile('All', streams),
+    ];
+
+    return new TimelineFlags._(recorder, streams, profiles);
+  }
+
+  const TimelineFlags._(this.recorder, this.streams, this.profiles);
+}
diff --git a/runtime/observatory_2/lib/tracer.dart b/runtime/observatory_2/lib/tracer.dart
new file mode 100644
index 0000000..3a18cfd
--- /dev/null
+++ b/runtime/observatory_2/lib/tracer.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library tracer;
+
+import 'dart:async';
+
+import 'package:logging/logging.dart';
+
+_deepCopy(src) {
+  if (src is Map) {
+    var dest = {};
+    src.forEach((key, val) {
+      dest[key] = _deepCopy(val);
+    });
+    return dest;
+  } else if (src is List) {
+    var dest = [];
+    src.forEach((val) {
+      dest.add(_deepCopy(val));
+    });
+    return dest;
+  } else {
+    return src;
+  }
+}
+
+class TraceEvent {
+  TraceEvent.msg(this._time, this.message, Map originalMap) {
+    map = _deepCopy(originalMap);
+  }
+
+  String get timeStamp => "T+${_time}us";
+
+  String toString() {
+    return "[${timeStamp}] ${message}";
+  }
+
+  int _time;
+  String message;
+  Map map;
+}
+
+class Tracer {
+  // The current global tracer.
+  static Tracer get current => _current;
+
+  static Tracer _current;
+
+  static void start() {
+    if (_current == null) {
+      _current = new Tracer();
+    }
+  }
+
+  static void stop() {
+    if (_current != null) {
+      _current.cancel();
+      _current = null;
+    }
+  }
+
+  // The tracer subscribes to all logging events.
+  StreamSubscription loggerSub = null;
+
+  // The start time for the current request.
+  Stopwatch _time;
+
+  // A list of all tracing events for thre current request.
+  List<TraceEvent> events = <TraceEvent>[];
+
+  Tracer() {
+    _time = new Stopwatch();
+    _time.start();
+    loggerSub = Logger.root.onRecord.listen((LogRecord rec) {
+      // Echo all log messages to the trace.
+      trace('${rec.level.name}: ${rec.message}');
+    });
+    reset();
+  }
+
+  void cancel() {
+    loggerSub.cancel();
+  }
+
+  void reset() {
+    _time.reset();
+    events.clear();
+  }
+
+  TraceEvent trace(String message, {Map map: null}) {
+    var event = new TraceEvent.msg(_time.elapsedMicroseconds, message, map);
+    events.add(event);
+    return event;
+  }
+}
diff --git a/runtime/observatory_2/lib/utils.dart b/runtime/observatory_2/lib/utils.dart
new file mode 100644
index 0000000..821e88f
--- /dev/null
+++ b/runtime/observatory_2/lib/utils.dart
@@ -0,0 +1,309 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library utils;
+
+import 'dart:async';
+import 'dart:math';
+
+enum DurationComponent {
+  Days,
+  Hours,
+  Minutes,
+  Seconds,
+  Milliseconds,
+  Microseconds
+}
+
+class Utils {
+  static String formatPercentNormalized(double x) {
+    var percent = 100.0 * x;
+    return '${percent.toStringAsFixed(2)}%';
+  }
+
+  static String formatPercent(num a, num total) {
+    return formatPercentNormalized(a / total);
+  }
+
+  static String zeroPad(int value, int pad) {
+    String prefix = "";
+    while (pad > 1) {
+      int pow10 = pow(10, pad - 1);
+      if (value < pow10) {
+        prefix = prefix + "0";
+      }
+      pad--;
+    }
+    return "${prefix}${value}";
+  }
+
+  static String formatCommaSeparated(int v) {
+    const COMMA_EVERY = 1000;
+    if (v < COMMA_EVERY) {
+      return v.toString();
+    }
+    var mod = v % COMMA_EVERY;
+    v ~/= COMMA_EVERY;
+    var r = '${zeroPad(mod, 3)}';
+    while (v > COMMA_EVERY) {
+      mod = v % COMMA_EVERY;
+      r = '${zeroPad(mod, 3)},$r';
+      v ~/= COMMA_EVERY;
+    }
+    if (v != 0) {
+      r = '$v,$r';
+    }
+    return r;
+  }
+
+  static String formatTimePrecise(double time) {
+    if (time == null) {
+      return "-";
+    }
+    const millisPerSecond = 1000;
+
+    var millis = (time * millisPerSecond).round();
+    return formatTimeMilliseconds(millis);
+  }
+
+  static String formatTimeMilliseconds(int millis) {
+    const millisPerHour = 60 * 60 * 1000;
+    const millisPerMinute = 60 * 1000;
+    const millisPerSecond = 1000;
+
+    var hours = millis ~/ millisPerHour;
+    millis = millis % millisPerHour;
+
+    var minutes = millis ~/ millisPerMinute;
+    millis = millis % millisPerMinute;
+
+    var seconds = millis ~/ millisPerSecond;
+    millis = millis % millisPerSecond;
+
+    if (hours > 0) {
+      return ("${zeroPad(hours, 2)}"
+          ":${zeroPad(minutes, 2)}"
+          ":${zeroPad(seconds, 2)}"
+          ".${zeroPad(millis, 3)}");
+    } else if (minutes > 0) {
+      return ("${zeroPad(minutes, 2)}"
+          ":${zeroPad(seconds, 2)}"
+          ".${zeroPad(millis, 3)}");
+    } else {
+      return ("${zeroPad(seconds, 2)}"
+          ".${zeroPad(millis, 3)}");
+    }
+  }
+
+  static String formatSize(bytesDynamic) {
+    int bytes = bytesDynamic.toInt();
+    int absBytes = bytes >= 0 ? bytes : -bytes;
+    const int digits = 1;
+    const int bytesPerKB = 1024;
+    const int bytesPerMB = 1024 * bytesPerKB;
+    const int bytesPerGB = 1024 * bytesPerMB;
+    const int bytesPerTB = 1024 * bytesPerGB;
+
+    if (absBytes < bytesPerKB) {
+      return "${bytes}B";
+    } else if (absBytes < bytesPerMB) {
+      return "${(bytes / bytesPerKB).toStringAsFixed(digits)}KB";
+    } else if (absBytes < bytesPerGB) {
+      return "${(bytes / bytesPerMB).toStringAsFixed(digits)}MB";
+    } else if (absBytes < bytesPerTB) {
+      return "${(bytes / bytesPerGB).toStringAsFixed(digits)}GB";
+    } else {
+      return "${(bytes / bytesPerTB).toStringAsFixed(digits)}TB";
+    }
+  }
+
+  static String formatTime(double time) {
+    if (time == null) {
+      return "-";
+    }
+    const millisPerHour = 60 * 60 * 1000;
+    const millisPerMinute = 60 * 1000;
+    const millisPerSecond = 1000;
+
+    var millis = (time * millisPerSecond).round();
+
+    var hours = millis ~/ millisPerHour;
+    millis = millis % millisPerHour;
+
+    var minutes = millis ~/ millisPerMinute;
+    millis = millis % millisPerMinute;
+
+    var seconds = millis ~/ millisPerSecond;
+
+    if (hours != 0) {
+      return '${hours}h ${minutes}m ${seconds}s';
+    }
+    if (minutes != 0) {
+      return '${minutes}m ${seconds}s';
+    }
+    return '${seconds}s';
+  }
+
+  static String formatDateTime(DateTime now) {
+    return '${now.year}-${now.month}-${now.day} '
+        '${now.hour.toString().padLeft(2)}:'
+        '${now.minute.toString().padLeft(2)}:'
+        '${now.second.toString().padLeft(2)}';
+  }
+
+  static String formatDuration(Duration duration,
+      {DurationComponent precision = DurationComponent.Microseconds,
+      String future = '',
+      String past = 'ago'}) {
+    var value = duration.inMicroseconds.abs();
+    switch (precision) {
+      case DurationComponent.Days:
+        value = (value / Duration.microsecondsPerDay).round();
+        break;
+      case DurationComponent.Hours:
+        value = (value / Duration.microsecondsPerHour).round();
+        break;
+      case DurationComponent.Minutes:
+        value = (value / Duration.microsecondsPerMinute).round();
+        break;
+      case DurationComponent.Seconds:
+        value = (value / Duration.microsecondsPerSecond).round();
+        break;
+      case DurationComponent.Milliseconds:
+        value = (value / Duration.microsecondsPerMillisecond).round();
+        break;
+      case DurationComponent.Microseconds:
+        break;
+    }
+    final components = <String>[];
+    if (duration.isNegative) {
+      if (!past.isEmpty) {
+        components.add(past);
+      }
+    } else {
+      if (!future.isEmpty) {
+        components.add(future);
+      }
+    }
+    switch (precision) {
+      case DurationComponent.Microseconds:
+        components.add('${value % Duration.microsecondsPerMillisecond}μs');
+        value = (value / Duration.microsecondsPerMillisecond).floor();
+        if (value != 0) {
+          continue Milliseconds;
+        }
+        break;
+      Milliseconds:
+      case DurationComponent.Milliseconds:
+        components.add('${value % Duration.millisecondsPerSecond}ms');
+        value = (value / Duration.millisecondsPerSecond).floor();
+        if (value != 0) {
+          continue Seconds;
+        }
+        break;
+      Seconds:
+      case DurationComponent.Seconds:
+        components.add('${value % Duration.secondsPerMinute}s');
+        value = (value / Duration.secondsPerMinute).floor();
+        ;
+        if (value != 0) {
+          continue Minutes;
+        }
+        break;
+      Minutes:
+      case DurationComponent.Minutes:
+        components.add('${value % Duration.minutesPerHour}m');
+        value = (value / Duration.minutesPerHour).floor();
+        if (value != 0) {
+          continue Hours;
+        }
+        break;
+      Hours:
+      case DurationComponent.Hours:
+        components.add('${value % Duration.hoursPerDay}h');
+        value = (value / Duration.hoursPerDay).floor();
+        if (value != 0) {
+          continue Days;
+        }
+        break;
+      Days:
+      case DurationComponent.Days:
+        components.add('${value}d');
+    }
+    return components.reversed.join(' ');
+  }
+
+  static String formatSeconds(double x) {
+    return x.toStringAsFixed(2);
+  }
+
+  static String formatMillis(double x) {
+    return x.toStringAsFixed(2);
+  }
+
+  static String formatDurationInSeconds(Duration x) =>
+      formatSeconds(x.inMicroseconds / Duration.microsecondsPerSecond);
+
+  static String formatDurationInMilliseconds(Duration x) =>
+      formatMillis(x.inMicroseconds / Duration.microsecondsPerMillisecond);
+
+  static bool runningInJavaScript() => identical(1.0, 1);
+
+  static formatStringAsLiteral(String value, [bool wasTruncated = false]) {
+    var result = <int>[];
+    result.add("'".codeUnitAt(0));
+    for (int codeUnit in value.codeUnits) {
+      if (codeUnit == '\n'.codeUnitAt(0))
+        result.addAll('\\n'.codeUnits);
+      else if (codeUnit == '\r'.codeUnitAt(0))
+        result.addAll('\\r'.codeUnits);
+      else if (codeUnit == '\f'.codeUnitAt(0))
+        result.addAll('\\f'.codeUnits);
+      else if (codeUnit == '\b'.codeUnitAt(0))
+        result.addAll('\\b'.codeUnits);
+      else if (codeUnit == '\t'.codeUnitAt(0))
+        result.addAll('\\t'.codeUnits);
+      else if (codeUnit == '\v'.codeUnitAt(0))
+        result.addAll('\\v'.codeUnits);
+      else if (codeUnit == '\$'.codeUnitAt(0))
+        result.addAll('\\\$'.codeUnits);
+      else if (codeUnit == '\\'.codeUnitAt(0))
+        result.addAll('\\\\'.codeUnits);
+      else if (codeUnit == "'".codeUnitAt(0))
+        result.addAll("'".codeUnits);
+      else if (codeUnit < 32) {
+        var escapeSequence = "\\u" + codeUnit.toRadixString(16).padLeft(4, "0");
+        result.addAll(escapeSequence.codeUnits);
+      } else
+        result.add(codeUnit);
+    }
+    if (wasTruncated) {
+      result.addAll("...".codeUnits);
+    } else {
+      result.add("'".codeUnitAt(0));
+    }
+    return new String.fromCharCodes(result);
+  }
+}
+
+/// A [Task] that can be scheduled on the Dart event queue.
+class Task {
+  Timer _timer;
+  final Function callback;
+
+  Task(this.callback);
+
+  /// Queue [this] to run on the next Dart event queue pump. Does nothing
+  /// if [this] is already queued.
+  queue() {
+    if (_timer != null) {
+      // Already scheduled.
+      return;
+    }
+    _timer = new Timer(Duration.zero, () {
+      _timer = null;
+      callback();
+    });
+  }
+}
diff --git a/runtime/observatory_2/observatory_sources.gni b/runtime/observatory_2/observatory_sources.gni
new file mode 100644
index 0000000..e78a449
--- /dev/null
+++ b/runtime/observatory_2/observatory_sources.gni
@@ -0,0 +1,284 @@
+# Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# DO NOT EDIT. This file is generated by update_sources.py in this directory.
+
+# This file contains all dart, css, and html sources for Observatory.
+observatory_sources = [
+  "lib/allocation_profile.dart",
+  "lib/app.dart",
+  "lib/cli.dart",
+  "lib/debugger.dart",
+  "lib/elements.dart",
+  "lib/event.dart",
+  "lib/models.dart",
+  "lib/object_graph.dart",
+  "lib/repositories.dart",
+  "lib/sample_profile.dart",
+  "lib/service.dart",
+  "lib/service_common.dart",
+  "lib/service_html.dart",
+  "lib/service_io.dart",
+  "lib/src/allocation_profile/allocation_profile.dart",
+  "lib/src/app/application.dart",
+  "lib/src/app/location_manager.dart",
+  "lib/src/app/notification.dart",
+  "lib/src/app/page.dart",
+  "lib/src/app/settings.dart",
+  "lib/src/app/view_model.dart",
+  "lib/src/cli/command.dart",
+  "lib/src/debugger/debugger.dart",
+  "lib/src/debugger/debugger_location.dart",
+  "lib/src/elements/allocation_profile.dart",
+  "lib/src/elements/class_allocation_profile.dart",
+  "lib/src/elements/class_instances.dart",
+  "lib/src/elements/class_ref.dart",
+  "lib/src/elements/class_tree.dart",
+  "lib/src/elements/class_view.dart",
+  "lib/src/elements/code_ref.dart",
+  "lib/src/elements/code_view.dart",
+  "lib/src/elements/containers/search_bar.dart",
+  "lib/src/elements/containers/virtual_collection.dart",
+  "lib/src/elements/containers/virtual_tree.dart",
+  "lib/src/elements/context_ref.dart",
+  "lib/src/elements/context_view.dart",
+  "lib/src/elements/cpu_profile.dart",
+  "lib/src/elements/cpu_profile/virtual_tree.dart",
+  "lib/src/elements/cpu_profile_table.dart",
+  "lib/src/elements/css/shared.css",
+  "lib/src/elements/curly_block.dart",
+  "lib/src/elements/debugger.dart",
+  "lib/src/elements/error_ref.dart",
+  "lib/src/elements/error_view.dart",
+  "lib/src/elements/eval_box.dart",
+  "lib/src/elements/field_ref.dart",
+  "lib/src/elements/field_view.dart",
+  "lib/src/elements/flag_list.dart",
+  "lib/src/elements/function_ref.dart",
+  "lib/src/elements/function_view.dart",
+  "lib/src/elements/general_error.dart",
+  "lib/src/elements/heap_map.dart",
+  "lib/src/elements/heap_snapshot.dart",
+  "lib/src/elements/helpers/any_ref.dart",
+  "lib/src/elements/helpers/custom_element.dart",
+  "lib/src/elements/helpers/nav_bar.dart",
+  "lib/src/elements/helpers/nav_menu.dart",
+  "lib/src/elements/helpers/rendering_queue.dart",
+  "lib/src/elements/helpers/rendering_scheduler.dart",
+  "lib/src/elements/helpers/uris.dart",
+  "lib/src/elements/icdata_ref.dart",
+  "lib/src/elements/icdata_view.dart",
+  "lib/src/elements/img/chromium_icon.png",
+  "lib/src/elements/img/dart_icon.png",
+  "lib/src/elements/img/isolate_icon.png",
+  "lib/src/elements/inbound_references.dart",
+  "lib/src/elements/instance_ref.dart",
+  "lib/src/elements/instance_view.dart",
+  "lib/src/elements/isolate/counter_chart.dart",
+  "lib/src/elements/isolate/location.dart",
+  "lib/src/elements/isolate/run_state.dart",
+  "lib/src/elements/isolate/shared_summary.dart",
+  "lib/src/elements/isolate/summary.dart",
+  "lib/src/elements/isolate_reconnect.dart",
+  "lib/src/elements/isolate_ref.dart",
+  "lib/src/elements/isolate_view.dart",
+  "lib/src/elements/json_view.dart",
+  "lib/src/elements/library_ref.dart",
+  "lib/src/elements/library_view.dart",
+  "lib/src/elements/local_var_descriptors_ref.dart",
+  "lib/src/elements/logging.dart",
+  "lib/src/elements/logging_list.dart",
+  "lib/src/elements/megamorphiccache_ref.dart",
+  "lib/src/elements/megamorphiccache_view.dart",
+  "lib/src/elements/metric/details.dart",
+  "lib/src/elements/metric/graph.dart",
+  "lib/src/elements/metrics.dart",
+  "lib/src/elements/native_memory_profiler.dart",
+  "lib/src/elements/nav/class_menu.dart",
+  "lib/src/elements/nav/isolate_menu.dart",
+  "lib/src/elements/nav/library_menu.dart",
+  "lib/src/elements/nav/menu_item.dart",
+  "lib/src/elements/nav/notify.dart",
+  "lib/src/elements/nav/notify_event.dart",
+  "lib/src/elements/nav/notify_exception.dart",
+  "lib/src/elements/nav/refresh.dart",
+  "lib/src/elements/nav/reload.dart",
+  "lib/src/elements/nav/top_menu.dart",
+  "lib/src/elements/nav/vm_menu.dart",
+  "lib/src/elements/object_common.dart",
+  "lib/src/elements/object_view.dart",
+  "lib/src/elements/objectpool_ref.dart",
+  "lib/src/elements/objectpool_view.dart",
+  "lib/src/elements/objectstore_view.dart",
+  "lib/src/elements/observatory_application.dart",
+  "lib/src/elements/pc_descriptors_ref.dart",
+  "lib/src/elements/persistent_handles.dart",
+  "lib/src/elements/ports.dart",
+  "lib/src/elements/process_snapshot.dart",
+  "lib/src/elements/retaining_path.dart",
+  "lib/src/elements/sample_buffer_control.dart",
+  "lib/src/elements/script_inset.dart",
+  "lib/src/elements/script_ref.dart",
+  "lib/src/elements/script_view.dart",
+  "lib/src/elements/sentinel_value.dart",
+  "lib/src/elements/sentinel_view.dart",
+  "lib/src/elements/singletargetcache_ref.dart",
+  "lib/src/elements/singletargetcache_view.dart",
+  "lib/src/elements/source_inset.dart",
+  "lib/src/elements/source_link.dart",
+  "lib/src/elements/stack_trace_tree_config.dart",
+  "lib/src/elements/strongly_reachable_instances.dart",
+  "lib/src/elements/subtypetestcache_ref.dart",
+  "lib/src/elements/subtypetestcache_view.dart",
+  "lib/src/elements/timeline/dashboard.dart",
+  "lib/src/elements/timeline_page.dart",
+  "lib/src/elements/tree_map.dart",
+  "lib/src/elements/type_arguments_ref.dart",
+  "lib/src/elements/unknown_ref.dart",
+  "lib/src/elements/unlinkedcall_ref.dart",
+  "lib/src/elements/unlinkedcall_view.dart",
+  "lib/src/elements/view_footer.dart",
+  "lib/src/elements/vm_connect.dart",
+  "lib/src/elements/vm_connect_target.dart",
+  "lib/src/elements/vm_view.dart",
+  "lib/src/models/exceptions.dart",
+  "lib/src/models/objects/allocation_profile.dart",
+  "lib/src/models/objects/breakpoint.dart",
+  "lib/src/models/objects/class.dart",
+  "lib/src/models/objects/code.dart",
+  "lib/src/models/objects/context.dart",
+  "lib/src/models/objects/error.dart",
+  "lib/src/models/objects/event.dart",
+  "lib/src/models/objects/extension_data.dart",
+  "lib/src/models/objects/field.dart",
+  "lib/src/models/objects/flag.dart",
+  "lib/src/models/objects/frame.dart",
+  "lib/src/models/objects/function.dart",
+  "lib/src/models/objects/guarded.dart",
+  "lib/src/models/objects/heap_space.dart",
+  "lib/src/models/objects/icdata.dart",
+  "lib/src/models/objects/inbound_references.dart",
+  "lib/src/models/objects/instance.dart",
+  "lib/src/models/objects/isolate.dart",
+  "lib/src/models/objects/isolate_group.dart",
+  "lib/src/models/objects/library.dart",
+  "lib/src/models/objects/local_var_descriptors.dart",
+  "lib/src/models/objects/map_association.dart",
+  "lib/src/models/objects/megamorphiccache.dart",
+  "lib/src/models/objects/metric.dart",
+  "lib/src/models/objects/notification.dart",
+  "lib/src/models/objects/object.dart",
+  "lib/src/models/objects/objectpool.dart",
+  "lib/src/models/objects/objectstore.dart",
+  "lib/src/models/objects/pc_descriptors.dart",
+  "lib/src/models/objects/persistent_handles.dart",
+  "lib/src/models/objects/ports.dart",
+  "lib/src/models/objects/retaining_path.dart",
+  "lib/src/models/objects/sample_profile.dart",
+  "lib/src/models/objects/script.dart",
+  "lib/src/models/objects/sentinel.dart",
+  "lib/src/models/objects/service.dart",
+  "lib/src/models/objects/single_target_cache.dart",
+  "lib/src/models/objects/source_location.dart",
+  "lib/src/models/objects/subtype_test_cache.dart",
+  "lib/src/models/objects/target.dart",
+  "lib/src/models/objects/thread.dart",
+  "lib/src/models/objects/timeline.dart",
+  "lib/src/models/objects/timeline_event.dart",
+  "lib/src/models/objects/type_arguments.dart",
+  "lib/src/models/objects/unknown.dart",
+  "lib/src/models/objects/unlinked_call.dart",
+  "lib/src/models/objects/vm.dart",
+  "lib/src/models/objects/zone.dart",
+  "lib/src/models/repositories/allocation_profile.dart",
+  "lib/src/models/repositories/breakpoint.dart",
+  "lib/src/models/repositories/class.dart",
+  "lib/src/models/repositories/context.dart",
+  "lib/src/models/repositories/editor.dart",
+  "lib/src/models/repositories/eval.dart",
+  "lib/src/models/repositories/event.dart",
+  "lib/src/models/repositories/field.dart",
+  "lib/src/models/repositories/flag.dart",
+  "lib/src/models/repositories/function.dart",
+  "lib/src/models/repositories/heap_snapshot.dart",
+  "lib/src/models/repositories/icdata.dart",
+  "lib/src/models/repositories/inbound_references.dart",
+  "lib/src/models/repositories/instance.dart",
+  "lib/src/models/repositories/isolate.dart",
+  "lib/src/models/repositories/isolate_group.dart",
+  "lib/src/models/repositories/library.dart",
+  "lib/src/models/repositories/megamorphiccache.dart",
+  "lib/src/models/repositories/metric.dart",
+  "lib/src/models/repositories/notification.dart",
+  "lib/src/models/repositories/object.dart",
+  "lib/src/models/repositories/objectpool.dart",
+  "lib/src/models/repositories/objectstore.dart",
+  "lib/src/models/repositories/persistent_handles.dart",
+  "lib/src/models/repositories/ports.dart",
+  "lib/src/models/repositories/reachable_size.dart",
+  "lib/src/models/repositories/retained_size.dart",
+  "lib/src/models/repositories/retaining_path.dart",
+  "lib/src/models/repositories/sample_profile.dart",
+  "lib/src/models/repositories/script.dart",
+  "lib/src/models/repositories/single_target_cache.dart",
+  "lib/src/models/repositories/strongly_reachable_instances.dart",
+  "lib/src/models/repositories/subtype_test_cache.dart",
+  "lib/src/models/repositories/target.dart",
+  "lib/src/models/repositories/timeline.dart",
+  "lib/src/models/repositories/type_arguments.dart",
+  "lib/src/models/repositories/unlinked_call.dart",
+  "lib/src/models/repositories/vm.dart",
+  "lib/src/repositories/allocation_profile.dart",
+  "lib/src/repositories/breakpoint.dart",
+  "lib/src/repositories/class.dart",
+  "lib/src/repositories/context.dart",
+  "lib/src/repositories/editor.dart",
+  "lib/src/repositories/eval.dart",
+  "lib/src/repositories/event.dart",
+  "lib/src/repositories/field.dart",
+  "lib/src/repositories/flag.dart",
+  "lib/src/repositories/function.dart",
+  "lib/src/repositories/heap_snapshot.dart",
+  "lib/src/repositories/icdata.dart",
+  "lib/src/repositories/inbound_references.dart",
+  "lib/src/repositories/instance.dart",
+  "lib/src/repositories/isolate.dart",
+  "lib/src/repositories/isolate_group.dart",
+  "lib/src/repositories/library.dart",
+  "lib/src/repositories/megamorphiccache.dart",
+  "lib/src/repositories/metric.dart",
+  "lib/src/repositories/notification.dart",
+  "lib/src/repositories/object.dart",
+  "lib/src/repositories/objectpool.dart",
+  "lib/src/repositories/objectstore.dart",
+  "lib/src/repositories/persistent_handles.dart",
+  "lib/src/repositories/ports.dart",
+  "lib/src/repositories/reachable_size.dart",
+  "lib/src/repositories/retained_size.dart",
+  "lib/src/repositories/retaining_path.dart",
+  "lib/src/repositories/sample_profile.dart",
+  "lib/src/repositories/script.dart",
+  "lib/src/repositories/settings.dart",
+  "lib/src/repositories/single_target_cache.dart",
+  "lib/src/repositories/strongly_reachable_instances.dart",
+  "lib/src/repositories/subtype_test_cache.dart",
+  "lib/src/repositories/target.dart",
+  "lib/src/repositories/timeline.dart",
+  "lib/src/repositories/timeline_base.dart",
+  "lib/src/repositories/type_arguments.dart",
+  "lib/src/repositories/unlinked_call.dart",
+  "lib/src/repositories/vm.dart",
+  "lib/src/sample_profile/sample_profile.dart",
+  "lib/src/service/object.dart",
+  "lib/tracer.dart",
+  "lib/utils.dart",
+  "web/favicon.ico",
+  "web/index.html",
+  "web/main.dart",
+  "web/third_party/trace_viewer_full.html",
+  "web/third_party/webcomponents.min.js",
+  "web/timeline.html",
+  "web/timeline.js",
+  "web/timeline_message_handler.js",
+]
diff --git a/runtime/observatory_2/pubspec.yaml b/runtime/observatory_2/pubspec.yaml
new file mode 100644
index 0000000..efd6952
--- /dev/null
+++ b/runtime/observatory_2/pubspec.yaml
@@ -0,0 +1,11 @@
+name: observatory
+environment:
+  sdk: '>=2.2.2 <3.0.0'
+
+dependencies:
+  usage: 'any'
+
+dev_dependencies:
+  build_runner: '>=1.6.2 <2.0.0'
+  build_web_compilers: '>=2.6.1 <3.0.0'
+
diff --git a/runtime/observatory_2/tests/observatory_ui_2/app_test.dart b/runtime/observatory_2/tests/observatory_ui_2/app_test.dart
new file mode 100644
index 0000000..5a841ce
--- /dev/null
+++ b/runtime/observatory_2/tests/observatory_ui_2/app_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/elements.dart';
+import 'package:stack_trace/stack_trace.dart';
+
+main() async {
+  Chain.capture(() async {
+    Logger.root.level = Level.INFO;
+    Logger.root.onRecord.listen((LogRecord rec) {
+      print('${rec.level.name}: ${rec.time}: ${rec.message}');
+    });
+    Logger.root.info('Starting Observatory');
+    document.body.children
+        .insert(0, new ObservatoryApplicationElement.created().element);
+  });
+}
diff --git a/runtime/observatory_2/tests/observatory_ui_2/observatory_ui.status b/runtime/observatory_2/tests/observatory_ui_2/observatory_ui.status
new file mode 100644
index 0000000..10260fd
--- /dev/null
+++ b/runtime/observatory_2/tests/observatory_ui_2/observatory_ui.status
@@ -0,0 +1,12 @@
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+[ !$browser ]
+*: SkipByDesign
+
+# custom elements are not supported on old browsers, we don't
+# intend for observatory to work on old browser versions, so
+# skipping.
+[ $runtime == ff || $runtime == ie10 || $runtime == ie11 || $runtime == safari ]
+*: SkipByDesign
diff --git a/runtime/observatory_2/tests/service_2/add_breakpoint_rpc_kernel_test.dart b/runtime/observatory_2/tests/service_2/add_breakpoint_rpc_kernel_test.dart
new file mode 100644
index 0000000..6434d69
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/add_breakpoint_rpc_kernel_test.dart
@@ -0,0 +1,138 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+import 'dart:async';
+
+const int LINE_A = 23;
+const int LINE_B = 25;
+
+int value = 0;
+
+int incValue(int amount) {
+  value += amount;
+  return amount;
+}
+
+Future testMain() async {
+  incValue(incValue(1)); // line A.
+
+  incValue(incValue(1)); // line B.
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+
+  // Test future breakpoints.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    // Future breakpoint.
+    var futureBpt1 = await isolate.addBreakpoint(script, LINE_A);
+    expect(futureBpt1.number, equals(1));
+    expect(futureBpt1.resolved, isFalse);
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
+    expect(await futureBpt1.location.getColumn(), equals(null));
+
+    // Future breakpoint with specific column.
+    var futureBpt2 = await isolate.addBreakpoint(script, LINE_A, 3);
+    expect(futureBpt2.number, equals(2));
+    expect(futureBpt2.resolved, isFalse);
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
+    expect(await futureBpt2.location.getColumn(), equals(3));
+
+    int resolvedCount =
+        await resumeAndCountResolvedBreakpointsUntilPause(isolate);
+
+    // After resolution the breakpoints have assigned line & column.
+    expect(resolvedCount, equals(2));
+    expect(futureBpt1.resolved, isTrue);
+    expect(await futureBpt1.location.getLine(), equals(LINE_A));
+    expect(await futureBpt1.location.getColumn(), equals(12));
+    expect(futureBpt2.resolved, isTrue);
+    expect(await futureBpt2.location.getLine(), equals(LINE_A));
+    expect(await futureBpt2.location.getColumn(), equals(3));
+
+    // The first breakpoint hits before value is modified.
+    Instance result = await rootLib.evaluate('value');
+    expect(result.valueAsString, equals('0'));
+
+    isolate.resume();
+    await hasStoppedAtBreakpoint(isolate);
+
+    // The second breakpoint hits after value has been modified once.
+    result = await rootLib.evaluate('value');
+    expect(result.valueAsString, equals('1'));
+
+    // Remove the breakpoints.
+    expect(
+        (await isolate.removeBreakpoint(futureBpt1)).type, equals('Success'));
+    expect(
+        (await isolate.removeBreakpoint(futureBpt2)).type, equals('Success'));
+  },
+
+  // Test resolution of column breakpoints.
+  (Isolate isolate) async {
+    var script = isolate.rootLibrary.scripts[0];
+    // Try all columns, including some columns that are too big.
+    for (int col = 1; col <= 50; col++) {
+      var bpt = await isolate.addBreakpoint(script, LINE_A, col);
+      expect(bpt.resolved, isTrue);
+      int resolvedLine = await bpt.location.getLine();
+      int resolvedCol = await bpt.location.getColumn();
+      print('$LINE_A:${col} -> ${resolvedLine}:${resolvedCol}');
+      if (col <= 12) {
+        expect(resolvedLine, equals(LINE_A));
+        expect(resolvedCol, equals(3));
+      } else if (col <= 36) {
+        expect(resolvedLine, equals(LINE_A));
+        expect(resolvedCol, equals(12));
+      } else {
+        expect(resolvedLine, equals(LINE_B));
+        expect(resolvedCol, equals(12));
+      }
+      expect((await isolate.removeBreakpoint(bpt)).type, equals('Success'));
+    }
+
+    // Make sure that a zero column is an error.
+    var caughtException = false;
+    try {
+      await isolate.addBreakpoint(script, 20, 0);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "addBreakpoint: invalid 'column' parameter: 0");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+Future<int> resumeAndCountResolvedBreakpointsUntilPause(Isolate isolate) async {
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  Completer completer = new Completer();
+  var subscription;
+  int resolvedCount = 0;
+  subscription = stream.listen((ServiceEvent event) async {
+    if (event.kind == ServiceEvent.kBreakpointResolved) {
+      resolvedCount++;
+    }
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      subscription.cancel();
+      completer.complete();
+    }
+  });
+  await isolate.resume();
+  await completer.future;
+  return resolvedCount;
+}
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory_2/tests/service_2/allocations_test.dart b/runtime/observatory_2/tests/service_2/allocations_test.dart
new file mode 100644
index 0000000..3fb6ce4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/allocations_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library allocations_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Foo {}
+
+// Prevent TFA from removing this static field to ensure the objects are kept
+// alive, so the allocation stats will report them via the service api.
+@pragma('vm:entry-point')
+List<Foo> foos;
+
+void script() {
+  foos = [new Foo(), new Foo(), new Foo()];
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var profile = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', {});
+    var classHeapStats = profile['members'].singleWhere((stats) {
+      return stats['class']['name'] == 'Foo';
+    });
+    expect(classHeapStats['instancesCurrent'], equals(3));
+    expect(classHeapStats['instancesAccumulated'], equals(3));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
new file mode 100644
index 0000000..1abcb9f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_generator_breakpoint_test.dart
@@ -0,0 +1,96 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose-debug
+// VMOptions=--verbose-debug --stacktrace-every=55 --stress-async-stacks
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+printSync() {
+  print('sync'); // Line 13
+}
+
+printAsync() async {
+  await null;
+  print('async'); // Line 18
+}
+
+printAsyncStar() async* {
+  await null;
+  print('async*'); // Line 23
+}
+
+printSyncStar() sync* {
+  print('sync*'); // Line 27
+}
+
+var testerReady = false;
+testeeDo() {
+  // We block here rather than allowing the isolate to enter the
+  // paused-on-exit state before the tester gets a chance to set
+  // the breakpoints because we need the event loop to remain
+  // operational for the async bodies to run.
+  print('testee waiting');
+  while (!testerReady);
+
+  printSync();
+  var future = printAsync();
+  var stream = printAsyncStar();
+  var iterator = printSyncStar();
+
+  print('middle'); // Line 44
+
+  future.then((v) => print(v));
+  stream.toList();
+  iterator.toList();
+}
+
+Future testAsync(Isolate isolate) async {
+  await isolate.rootLibrary.load();
+  var script = isolate.rootLibrary.scripts[0];
+
+  var bp1 = await isolate.addBreakpoint(script, 13);
+  expect(bp1, isNotNull);
+  expect(bp1 is Breakpoint, isTrue);
+  var bp2 = await isolate.addBreakpoint(script, 18);
+  expect(bp2, isNotNull);
+  expect(bp2 is Breakpoint, isTrue);
+  var bp3 = await isolate.addBreakpoint(script, 23);
+  expect(bp3, isNotNull);
+  expect(bp3 is Breakpoint, isTrue);
+  var bp4 = await isolate.addBreakpoint(script, 27);
+  expect(bp4, isNotNull);
+  expect(bp4 is Breakpoint, isTrue);
+  var bp5 = await isolate.addBreakpoint(script, 44);
+  print("BP5 - $bp5");
+  expect(bp5, isNotNull);
+  expect(bp5 is Breakpoint, isTrue);
+
+  var hits = [];
+
+  isolate.rootLibrary.evaluate('testerReady = true').then((result) {
+    print(result);
+    expect((result as Instance).valueAsString, equals('true'));
+  });
+
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  await for (ServiceEvent event in stream) {
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      var bp = event.breakpoint;
+      print('Hit $bp');
+      hits.add(bp);
+      await isolate.resume();
+
+      if (hits.length == 5) break;
+    }
+  }
+
+  expect(hits, equals([bp1, bp5, bp4, bp2, bp3]));
+}
+
+var tests = <IsolateTest>[testAsync];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testeeDo);
diff --git a/runtime/observatory_2/tests/service_2/async_next_regession_18877_test.dart b/runtime/observatory_2/tests/service_2/async_next_regession_18877_test.dart
new file mode 100644
index 0000000..8b56841
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_next_regession_18877_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 23;
+const int LINE_B = 24;
+const int LINE_C = 25;
+
+foo() async {}
+
+doAsync(stop) async {
+  // Flutter issue 18877:
+  // If a closure is defined in the context of an async method, stepping over
+  // an await causes the implicit breakpoint to be set for that closure instead
+  // of the async_op, resulting in the debugger falling through.
+  final baz = () => print('doAsync($stop) done!');
+  if (stop) debugger();
+  await foo(); // Line A.
+  await foo(); // Line B.
+  await foo(); // Line C.
+  baz();
+  return null;
+}
+
+testMain() {
+  // With two runs of doAsync floating around, async step should only cause
+  // us to stop in the run we started in.
+  doAsync(false);
+  doAsync(true);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver, // foo()
+  stoppedAtLine(LINE_A),
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  stepOver, // foo()
+  stoppedAtLine(LINE_B),
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/async_next_test.dart b/runtime/observatory_2/tests/service_2/async_next_test.dart
new file mode 100644
index 0000000..f717e0a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_next_test.dart
@@ -0,0 +1,45 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 18;
+const int LINE_B = 19;
+const int LINE_C = 20;
+
+foo() async {}
+
+doAsync(stop) async {
+  if (stop) debugger();
+  await foo(); // Line A.
+  await foo(); // Line B.
+  await foo(); // Line C.
+  return null;
+}
+
+testMain() {
+  // With two runs of doAsync floating around, async step should only cause
+  // us to stop in the run we started in.
+  doAsync(false);
+  doAsync(true);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver, // foo()
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  stepOver, // foo()
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/async_scope_test.dart b/runtime/observatory_2/tests/service_2/async_scope_test.dart
new file mode 100644
index 0000000..4e6815b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_scope_test.dart
@@ -0,0 +1,72 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 20;
+const int LINE_B = 26;
+
+foo() {}
+
+doAsync(param1) async {
+  var local1 = param1 + 1;
+  foo(); // Line A.
+  await local1;
+}
+
+doAsyncStar(param2) async* {
+  var local2 = param2 + 1;
+  foo(); // Line B.
+  yield local2;
+}
+
+testeeDo() {
+  debugger();
+
+  doAsync(1).then((_) {
+    doAsyncStar(1).listen((_) {});
+  });
+}
+
+Future checkAsyncVarDescriptors(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(1));
+  Frame frame = stack['frames'][0];
+  var vars = frame.variables.map((v) => v['name']).join(' ');
+  expect(vars, equals('param1 local1')); // no :async_op et al
+}
+
+Future checkAsyncStarVarDescriptors(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(1));
+  Frame frame = stack['frames'][0];
+  var vars = frame.variables.map((v) => v['name']).join(' ');
+  expect(vars, equals('param2 local2')); // no :async_op et al
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint, // debugger()
+  setBreakpointAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  checkAsyncVarDescriptors,
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  checkAsyncStarVarDescriptors,
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testeeDo);
diff --git a/runtime/observatory_2/tests/service_2/async_single_step_exception_test.dart b/runtime/observatory_2/tests/service_2/async_single_step_exception_test.dart
new file mode 100644
index 0000000..fdc490e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_single_step_exception_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 20;
+const LINE_B = 21;
+const LINE_C = 27;
+const LINE_D = 29;
+const LINE_E = 32;
+const LINE_F = 35;
+const LINE_G = 37;
+
+helper() async {
+  print('helper'); // LINE_A.
+  throw 'a'; // LINE_B.
+  return null;
+}
+
+testMain() async {
+  debugger();
+  print('mmmmm'); // LINE_C.
+  try {
+    await helper(); // LINE_D.
+  } catch (e) {
+    // arrive here on error.
+    print('error: $e'); // LINE_E.
+  } finally {
+    // arrive here in both cases.
+    print('foo'); // LINE_F.
+  }
+  print('z'); // LINE_G.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C), // print mmmm
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A), // print helper
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // throw a
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(23), // } (weird dispatching)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D), // await helper (weird dispatching)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E), // print(error)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E), // print(error) (weird finally dispatching)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_F), // print(foo)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_G), // print(z)
+  resumeIsolate
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/async_single_step_into_test.dart b/runtime/observatory_2/tests/service_2/async_single_step_into_test.dart
new file mode 100644
index 0000000..8d8417f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_single_step_into_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 17;
+const LINE_B = 18;
+const LINE_C = 23;
+const LINE_D = 24;
+
+helper() async {
+  print('helper'); // LINE_A.
+  print('foobar'); // LINE_B.
+}
+
+testMain() {
+  debugger();
+  print('mmmmm'); // LINE_C.
+  helper(); // LINE_D.
+  print('z');
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/async_single_step_out_test.dart b/runtime/observatory_2/tests/service_2/async_single_step_out_test.dart
new file mode 100644
index 0000000..2b51e24
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_single_step_out_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 18;
+const LINE_B = 19;
+const LINE_C = 24;
+const LINE_D = 25;
+const LINE_E = 26;
+
+helper() async {
+  print('helper'); // LINE_A.
+  return null; // LINE_B.
+}
+
+testMain() async {
+  debugger();
+  print('mmmmm'); // LINE_C.
+  await helper(); // LINE_D.
+  print('z'); // LINE_E.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C), // print mmmm
+  stepOver,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D), // await helper
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A), // print.
+  stepOver,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B), // return null.
+  stepInto, // exit helper via a single step.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(20), // return null (weird dispatching)
+  stepInto, // exit helper via a single step.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(25), // await helper (weird dispatching)
+  smartNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E), // arrive after the await.
+  resumeIsolate
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/async_star_single_step_into_test.dart b/runtime/observatory_2/tests/service_2/async_star_single_step_into_test.dart
new file mode 100644
index 0000000..65a784d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_star_single_step_into_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 19;
+const LINE_B = 20;
+const LINE_C = 24;
+const LINE_D = 27;
+const LINE_E = 33;
+const LINE_F = 34;
+
+foobar() async* {
+  yield 1; // LINE_A.
+  yield 2; // LINE_B.
+}
+
+helper() async {
+  print('helper'); // LINE_C.
+  await for (var i in foobar()) {
+    debugger();
+    print('loop'); // LINE_D.
+  }
+}
+
+testMain() {
+  debugger();
+  print('mmmmm'); // LINE_E.
+  helper(); // LINE_F.
+  print('z');
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_F),
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  // Resume here to exit the generator function.
+  // TODO(johnmccutchan): Implement support for step-out of async functions.
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/async_star_step_out_test.dart b/runtime/observatory_2/tests/service_2/async_star_step_out_test.dart
new file mode 100644
index 0000000..fca9d16
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_star_step_out_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 22;
+const LINE_B = 23;
+const LINE_C = 27;
+const LINE_D = 30;
+const LINE_E = 37;
+const LINE_F = 38;
+const LINE_G = 39;
+const LINE_H = 28;
+const LINE_I = 32;
+
+foobar() async* {
+  yield 1; // LINE_A.
+  yield 2; // LINE_B.
+}
+
+helper() async {
+  print('helper'); // LINE_C.
+  await for (var i in foobar()) /* LINE_H */ {
+    debugger();
+    print('loop'); // LINE_D.
+  }
+  return null; // LINE_I.
+}
+
+testMain() {
+  debugger();
+  print('mmmmm'); // LINE_E.
+  helper(); // LINE_F.
+  print('z'); // LINE_G.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_F),
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOut, // step out of generator.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_H), // await for.
+  stepInto,
+
+  hasStoppedAtBreakpoint, // debugger().
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D), // print.
+  stepInto,
+
+  hasStoppedAtBreakpoint, // await for.
+  stepInto,
+
+  hasStoppedAtBreakpoint, // back in generator.
+  stoppedAtLine(LINE_B),
+  stepOut, // step out of generator.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_H), // await for.
+  stepInto,
+
+  hasStoppedAtBreakpoint, // debugger().
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D), // print.
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_H), // await for.
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stepOut, // step out of generator.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_I), // return null.
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/async_step_out_test.dart b/runtime/observatory_2/tests/service_2/async_step_out_test.dart
new file mode 100644
index 0000000..f22f8d8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/async_step_out_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 19;
+const LINE_B = 20;
+const LINE_C = 21;
+const LINE_D = 26;
+const LINE_E = 27;
+const LINE_F = 28;
+
+helper() async {
+  await null; // LINE_A.
+  print('helper'); // LINE_B.
+  print('foobar'); // LINE_C.
+}
+
+testMain() async {
+  debugger();
+  print('mmmmm'); // LINE_D.
+  await helper(); // LINE_E.
+  print('z'); // LINE_F.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_E),
+  stepInto,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  asyncNext,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  stepOver, // print.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  stepOut, // out of helper to awaiter testMain.
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_F),
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/auth_token_test.dart b/runtime/observatory_2/tests/service_2/auth_token_test.dart
new file mode 100644
index 0000000..12a8836
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/auth_token_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart' as S;
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  Expect.isNotNull(info.serverUri);
+  // Ensure that we have the auth token in the path segments.
+  Expect.isTrue(info.serverUri.pathSegments.length > 1);
+  // Sanity check the length of the auth token.
+  Expect.isTrue(info.serverUri.pathSegments[0].length > 8);
+
+  // Try connecting to the server without the auth token, it should throw
+  // an exception.
+  var port = info.serverUri.port;
+  var url = Uri.parse('http://localhost:$port');
+  var httpClient = new io.HttpClient();
+  try {
+    var request = await httpClient.getUrl(url);
+    fail('expected exception');
+  } catch (e) {
+    // Expected
+  }
+
+  // Try connecting to the server with the auth token, it should succeed.
+  try {
+    var request = await httpClient.getUrl(info.serverUri);
+  } catch (e) {
+    fail('could not connect');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+  }
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeBefore: testeeBefore,
+    // the testee is responsible for starting the
+    // web server.
+    testeeControlsServer: true);
diff --git a/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_2_test.dart b/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_2_test.dart
new file mode 100644
index 0000000..be22e8b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_2_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 28;
+const LINE_B = 34;
+const LINE_C = 38;
+
+notCalled() async {
+  await null;
+  await null;
+  await null;
+  await null;
+}
+
+foobar() async {
+  await null;
+  debugger();
+  print('foobar'); // LINE_A.
+}
+
+helper() async {
+  await null;
+  print('helper');
+  await foobar(); // LINE_B.
+}
+
+testMain() async {
+  helper(); // LINE_C.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    // Verify awaiter stack trace is the current frame + the awaiter.
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    List awaiterFrames = stack['awaiterFrames'];
+    for (final v in awaiterFrames) {
+      print(v);
+    }
+
+    if (useCausalAsyncStacks) {
+      expect(awaiterFrames.length, greaterThanOrEqualTo(4));
+      // Awaiter frame.
+      expect(await awaiterFrames[0].toUserString(),
+          stringContainsInOrder(['foobar', '.dart:${LINE_A}']));
+      // Awaiter frame.
+      expect(await awaiterFrames[1].toUserString(),
+          stringContainsInOrder(['helper', '.dart:${LINE_B}']));
+      // Suspension point.
+      expect(awaiterFrames[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      // Causal frame.
+      expect(await awaiterFrames[3].toUserString(),
+          stringContainsInOrder(['testMain', '.dart:${LINE_C}']));
+    } else {
+      expect(awaiterFrames.length, greaterThanOrEqualTo(2));
+      // Awaiter frame.
+      expect(await awaiterFrames[0].toUserString(),
+          stringContainsInOrder(['foobar', '.dart:${LINE_A}']));
+      // Awaiter frame.
+      expect(await awaiterFrames[1].toUserString(),
+          stringContainsInOrder(['helper', '.dart:${LINE_B}']));
+    }
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_test.dart b/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_test.dart
new file mode 100644
index 0000000..5f18945
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/awaiter_async_stack_contents_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async-debugger --verbose-debug --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async-debugger --verbose-debug --causal-async-stacks --no-lazy-async-stacks
+
+import 'dart:developer';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_C = 22;
+const LINE_A = 28;
+const LINE_B = 34;
+const LINE_D = 29;
+
+foobar() async {
+  await null;
+  debugger();
+  print('foobar'); // LINE_C.
+}
+
+helper() async {
+  await null;
+  debugger();
+  print('helper'); // LINE_A.
+  await foobar(); // LINE_D
+}
+
+testMain() {
+  debugger();
+  helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // No awaiter frames because we are in a completely synchronous stack.
+    expect(stack['awaiterFrames'], isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (Isolate isolate) async {
+    // Verify awaiter stack trace is the current frame + the awaiter.
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    List awaiterFrames = stack['awaiterFrames'];
+    if (useCausalAsyncStacks) {
+      expect(awaiterFrames.length, greaterThanOrEqualTo(4));
+      // Awaiter frame.
+      expect(await awaiterFrames[0].toUserString(),
+          stringContainsInOrder(['foobar', '.dart:$LINE_C']));
+      // Awaiter frame.
+      expect(await awaiterFrames[1].toUserString(),
+          stringContainsInOrder(['helper', '.dart:$LINE_D']));
+      // Suspension point.
+      expect(awaiterFrames[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      // Causal frame.
+      expect(await awaiterFrames[3].toUserString(),
+          stringContainsInOrder(['testMain', '.dart:$LINE_B']));
+    } else {
+      expect(awaiterFrames.length, greaterThanOrEqualTo(2));
+      // Awaiter frame.
+      expect(await awaiterFrames[0].toUserString(),
+          stringContainsInOrder(['foobar', '.dart:$LINE_C']));
+      // Awaiter frame.
+      expect(await awaiterFrames[1].toUserString(),
+          stringContainsInOrder(['helper', '.dart:$LINE_D']));
+      // "helper" is not await'ed.
+    }
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/bad_reload/v1/main.dart b/runtime/observatory_2/tests/service_2/bad_reload/v1/main.dart
new file mode 100644
index 0000000..8b3a14b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/bad_reload/v1/main.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+test() => 'apple';
+
+main() {
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
diff --git a/runtime/observatory_2/tests/service_2/bad_reload/v2/main.dart b/runtime/observatory_2/tests/service_2/bad_reload/v2/main.dart
new file mode 100644
index 0000000..e698487
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/bad_reload/v2/main.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+import 'library_isnt_here_man';
+
+test() => 'apple';
+
+main() {
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
diff --git a/runtime/observatory_2/tests/service_2/bad_reload_test.dart b/runtime/observatory_2/tests/service_2/bad_reload_test.dart
new file mode 100644
index 0000000..1aad2dc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/bad_reload_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory_2/service.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri spawnUri = baseUri.resolveUri(Uri.parse('bad_reload/v1/main.dart'));
+Uri v2Uri = baseUri.resolveUri(Uri.parse('bad_reload/v2/main.dart'));
+
+testMain() async {
+  print(baseUri);
+  debugger(); // Stop here.
+  // Spawn the child isolate.
+  I.Isolate isolate = await I.Isolate.spawnUri(spawnUri, [], null);
+  print(isolate);
+  debugger();
+}
+
+Future<String> invokeTest(Isolate isolate) async {
+  await isolate.reload();
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  Instance result = await lib.evaluate('test()');
+  expect(result.isString, isTrue);
+  return result.valueAsString;
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Stop at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  (Isolate mainIsolate) async {
+    // Grab the VM.
+    VM vm = mainIsolate.vm;
+    await vm.reloadIsolates();
+    expect(vm.isolates.length, 2);
+
+    // Find the spawned isolate.
+    Isolate spawnedIsolate =
+        vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+    expect(spawnedIsolate, isNotNull);
+
+    // Invoke test in v1.
+    String v1 = await invokeTest(spawnedIsolate);
+    expect(v1, 'apple');
+
+    // Reload to v2.
+    var response = await spawnedIsolate.reloadSources(
+      rootLibUri: v2Uri.toString(),
+    );
+    // Observe that it failed.
+    expect(response['success'], isFalse);
+    List notices = response['details']['notices'];
+    expect(notices.length, equals(1));
+    Map<String, dynamic> reasonForCancelling = notices[0];
+    expect(reasonForCancelling['type'], equals('ReasonForCancelling'));
+    expect(reasonForCancelling['message'], contains('library_isnt_here_man'));
+
+    String v2 = await invokeTest(spawnedIsolate);
+    expect(v2, 'apple');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/bad_web_socket_address_test.dart b/runtime/observatory_2/tests/service_2/bad_web_socket_address_test.dart
new file mode 100644
index 0000000..58a6881
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/bad_web_socket_address_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:logging/logging.dart';
+import "package:observatory_2/service_io.dart";
+import 'package:test/test.dart';
+
+void testBadWebSocket() async {
+  var vm = new WebSocketVM(new WebSocketVMTarget('ws://karatekid/ws'));
+
+  dynamic error;
+  try {
+    await vm.load();
+  } catch (e) {
+    error = e;
+  }
+  expect(error, isA<NetworkRpcException>());
+}
+
+main() async {
+  Logger.root.level = Level.INFO;
+  Logger.root.onRecord.listen((LogRecord rec) {
+    print('${rec.level.name}: ${rec.time}: ${rec.message}');
+  });
+
+  await test('bad web socket address', testBadWebSocket);
+}
diff --git a/runtime/observatory_2/tests/service_2/break_on_activation_test.dart b/runtime/observatory_2/tests/service_2/break_on_activation_test.dart
new file mode 100644
index 0000000..6b3dfb0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/break_on_activation_test.dart
@@ -0,0 +1,205 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+genRepeater(value) {
+  return () => print(value);
+}
+
+genRepeaterNamed(value) {
+  return ({x, y}) => print(value);
+}
+
+var r1;
+var r2;
+var r3;
+
+var r1_named;
+var r2_named;
+var r3_named;
+
+void testeeSetup() {
+  // These closures have the same function.
+  r1 = genRepeater('r1');
+  r2 = genRepeater('r2');
+  r3 = genRepeater('r3');
+
+  // These closures have the same function.
+  r1_named = genRepeaterNamed('r1_named');
+  r2_named = genRepeaterNamed('r2_named');
+  r3_named = genRepeaterNamed('r3_named');
+}
+
+void testeeDo() {
+  r1();
+  r2();
+  r3();
+}
+
+void testeeDoNamed() {
+  r1_named(y: 'Not a closure', x: 'Not a closure');
+  r2_named(y: 'Not a closure', x: 'Not a closure');
+  r3_named(y: 'Not a closure', x: 'Not a closure');
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+
+    var breaksHit = 0;
+
+    var subscriptionFuture =
+        isolate.vm.listenEventStream(VM.kDebugStream, (ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print("Hit breakpoint ${event.breakpoint}");
+        breaksHit++;
+        isolate.resume();
+      }
+    });
+
+    valueOfField(String name) async {
+      var field = rootLib.variables.singleWhere((v) => v.name == name);
+      await field.load();
+      return field.staticValue as Instance;
+    }
+
+    var r1Ref = await valueOfField('r1');
+
+    var bpt1 = await isolate.addBreakOnActivation(r1Ref);
+    print("Added breakpoint $bpt1");
+    expect(bpt1 is Breakpoint, isTrue);
+    expect(breaksHit, equals(0));
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(bpt1));
+    print("testeeDo()");
+    var res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(1));
+
+    await isolate.removeBreakpoint(bpt1);
+    print("Removed breakpoint $bpt1");
+    print("testeeDo()");
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(null));
+    res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(1));
+
+    await cancelFutureSubscription(subscriptionFuture);
+  },
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+
+    var breaksHit = 0;
+
+    var subscriptionFuture =
+        isolate.vm.listenEventStream(VM.kDebugStream, (ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print("Hit breakpoint ${event.breakpoint}");
+        breaksHit++;
+        isolate.resume();
+      }
+    });
+
+    valueOfField(String name) async {
+      var field = rootLib.variables.singleWhere((v) => v.name == name);
+      await field.load();
+      return field.staticValue as Instance;
+    }
+
+    var r1Ref = await valueOfField('r1_named');
+
+    var bpt1 = await isolate.addBreakOnActivation(r1Ref);
+    print("Added breakpoint $bpt1");
+    expect(bpt1 is Breakpoint, isTrue);
+    expect(breaksHit, equals(0));
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(bpt1));
+    print("testeeDoNamed()");
+    var res = await rootLib.evaluate("testeeDoNamed()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(1));
+
+    await isolate.removeBreakpoint(bpt1);
+    print("Removed breakpoint $bpt1");
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(null));
+    print("testeeDoNamed()");
+    res = await rootLib.evaluate("testeeDoNamed()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(1));
+
+    await cancelFutureSubscription(subscriptionFuture);
+  },
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+
+    var breaksHit = 0;
+
+    var subscriptionFuture =
+        isolate.vm.listenEventStream(VM.kDebugStream, (ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print("Hit breakpoint ${event.breakpoint}");
+        breaksHit++;
+        isolate.resume();
+      }
+    });
+
+    valueOfField(String name) async {
+      var field = rootLib.variables.singleWhere((v) => v.name == name);
+      await field.load();
+      return field.staticValue as Instance;
+    }
+
+    var r1Ref = await valueOfField('r1');
+    var r2Ref = await valueOfField('r2');
+
+    var bpt1 = await isolate.addBreakOnActivation(r1Ref);
+    print("Added breakpoint $bpt1");
+    expect(bpt1 is Breakpoint, isTrue);
+    expect(breaksHit, equals(0));
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(bpt1));
+    print("testeeDo()");
+    var res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(1));
+
+    var bpt2 = await isolate.addBreakOnActivation(r2Ref);
+    print("Added breakpoint $bpt2");
+    expect(bpt2 is Breakpoint, isTrue);
+    expect(breaksHit, equals(1));
+    await r2Ref.reload();
+    expect(r2Ref.activationBreakpoint, equals(bpt2));
+    print("testeeDo()");
+    res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(3));
+
+    await isolate.removeBreakpoint(bpt1);
+    print("Removed breakpoint $bpt1");
+    await r1Ref.reload();
+    expect(r1Ref.activationBreakpoint, equals(null));
+    print("testeeDo()");
+    res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(4));
+
+    await isolate.removeBreakpoint(bpt2);
+    print("Removed breakpoint $bpt2");
+    await r2Ref.reload();
+    expect(r2Ref.activationBreakpoint, equals(null));
+    print("testeeDo()");
+    res = await rootLib.evaluate("testeeDo()");
+    expect(res is Instance, isTrue); // Not error.
+    expect(breaksHit, equals(4));
+
+    await cancelFutureSubscription(subscriptionFuture);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: testeeSetup);
diff --git a/runtime/observatory_2/tests/service_2/break_on_async_function_test.dart b/runtime/observatory_2/tests/service_2/break_on_async_function_test.dart
new file mode 100644
index 0000000..caa9fd6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/break_on_async_function_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 13;
+
+Future<String> testFunction() async {
+  await new Future.delayed(new Duration(milliseconds: 1));
+  return "Done";
+}
+
+testMain() async {
+  debugger();
+  var str = await testFunction();
+  print(str);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Add breakpoint at the entry of async function
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+    var function =
+        rootLib.functions.singleWhere((f) => f.name == 'testFunction');
+
+    var bpt = await isolate.addBreakpointAtEntry(function);
+    expect(bpt is Breakpoint, isTrue);
+    print(bpt);
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/break_on_default_constructor_test.dart b/runtime/observatory_2/tests/service_2/break_on_default_constructor_test.dart
new file mode 100644
index 0000000..160db2f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/break_on_default_constructor_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/debugger.dart';
+import 'package:observatory_2/service.dart' as S;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+class Foo {}
+
+code() {
+  new Foo();
+}
+
+class TestDebugger extends Debugger {
+  TestDebugger(this.isolate, this.stack);
+
+  VM get vm => isolate.vm;
+  Isolate isolate;
+  ServiceMap stack;
+  int currentFrame = 0;
+}
+
+Future<Debugger> initDebugger(Isolate isolate) {
+  return isolate.getStack().then((stack) {
+    return new TestDebugger(isolate, stack);
+  });
+}
+
+List<String> stops = [];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  // Load the isolate's libraries
+  (Isolate isolate) async {
+    for (var lib in isolate.libraries) {
+      await lib.load();
+    }
+  },
+
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, 'Foo');
+
+    if (loc.valid) {
+      if (loc.function != null) {
+        try {
+          await debugger.isolate.addBreakpointAtEntry(loc.function);
+        } on S.ServerRpcException catch (e) {
+          if (e.code == S.ServerRpcException.kCannotAddBreakpoint) {
+            // Expected
+          } else {
+            fail("Got unexpected error $e");
+          }
+        }
+      } else {
+        fail("Expected to find function");
+      }
+    } else {
+      fail("Expected to find function");
+    }
+
+    await isolate.resume();
+  }
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/break_on_function_test.dart b/runtime/observatory_2/tests/service_2/break_on_function_test.dart
new file mode 100644
index 0000000..a8d148c
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/break_on_function_test.dart
@@ -0,0 +1,55 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 14;
+
+testFunction(flag) {
+  // Line A.
+  if (flag) {
+    print("Yes");
+  } else {
+    print("No");
+  }
+}
+
+testMain() {
+  debugger();
+  testFunction(true);
+  testFunction(false);
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Add breakpoint
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+    var function =
+        rootLib.functions.singleWhere((f) => f.name == 'testFunction');
+
+    var bpt = await isolate.addBreakpointAtEntry(function);
+    expect(bpt is Breakpoint, isTrue);
+    print(bpt);
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_async_break_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_async_break_test.dart
new file mode 100644
index 0000000..a2cc75f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_async_break_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+const int LINE = 17;
+
+// Issue: https://github.com/dart-lang/sdk/issues/36622
+Future<void> testMain() async {
+  for (int i = 0; i < 2; i++) {
+    if (i > 0) {
+      break; // breakpoint here
+    }
+    await Future.delayed(Duration(seconds: 1));
+  }
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+
+  // Test future breakpoints.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    // Future breakpoint.
+    var futureBpt = await isolate.addBreakpoint(script, LINE);
+    expect(futureBpt.number, 1);
+    expect(futureBpt.resolved, isFalse);
+    expect(await futureBpt.location.getLine(), LINE);
+    expect(await futureBpt.location.getColumn(), null);
+
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    Completer completer = new Completer();
+    var subscription;
+    var resolvedCount = 0;
+    subscription = stream.listen((ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kBreakpointResolved) {
+        resolvedCount++;
+      }
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    await isolate.resume();
+    await hasStoppedAtBreakpoint(isolate);
+
+    // After resolution the breakpoints have assigned line & column.
+    expect(resolvedCount, 1);
+    expect(futureBpt.resolved, isTrue);
+    expect(await futureBpt.location.getLine(), LINE);
+    expect(await futureBpt.location.getColumn(), 7);
+
+    // Remove the breakpoints.
+    expect((await isolate.removeBreakpoint(futureBpt)).type, 'Success');
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart
new file mode 100644
index 0000000..03a57f6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_file_uri_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'dart:io' show Platform;
+
+import 'package:observatory_test_package_2/has_part.dart' as hasPart;
+import 'package:path/path.dart' as path;
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri breakpointFile = baseUri.resolve('observatory_test_package/the_part.dart');
+const String shortFile = "the_part.dart";
+
+const int LINE = 87;
+
+code() {
+  hasPart.main();
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:5", // on 'print'
+  "$shortFile:${LINE + 1}:3" // on class ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(breakpointFile.toString(), LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_test.dart
new file mode 100644
index 0000000..8aec1ff
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_in_package_parts_class_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'package:observatory_test_package_2/has_part.dart' as hasPart;
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 87;
+const String breakpointFile = "package:observatory_test_package_2/the_part.dart";
+const String shortFile = "the_part.dart";
+
+code() {
+  hasPart.main();
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:5", // on 'print'
+  "$shortFile:${LINE + 1}:3" // on class ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(breakpointFile, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_part.dart b/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_part.dart
new file mode 100644
index 0000000..4855332
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_part.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of breakpoint_in_parts_class;
+
+void foo() {
+  print("lalala");
+}
+
+class Foo1 {
+  final foo;
+
+  Foo1(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo2 {
+  final foo;
+
+  Foo2(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo3 {
+  final foo;
+
+  Foo3(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo4 {
+  final foo;
+
+  Foo4(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo5 {
+  final foo;
+
+  Foo5(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo6 {
+  final foo;
+
+  Foo6(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo7 {
+  final foo;
+
+  Foo7(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo8 {
+  final foo;
+
+  Foo8(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo9 {
+  final foo;
+
+  Foo9(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo10 {
+  final foo;
+
+  Foo10(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+var foo2 = foo() as dynamic;
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_test.dart
new file mode 100644
index 0000000..77786a2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_in_parts_class_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+part 'breakpoint_in_parts_class_part.dart';
+
+const int LINE = 87;
+const String file = "breakpoint_in_parts_class_part.dart";
+
+code() {
+  Foo10 foo = new Foo10("Foo!");
+  print(foo);
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$file:${LINE+0}:5", // on 'print'
+  "$file:${LINE+1}:3" // on class ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(file, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_non_debuggable_library_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_non_debuggable_library_test.dart
new file mode 100644
index 0000000..c2dde98
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_non_debuggable_library_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_test_package_2/has_part.dart' as test_pkg;
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const String file = 'package:observatory_test_package_2/has_part.dart';
+// print() within fooz()
+const int LINE_A = 15;
+// print() within barz()
+const int LINE_B = 11;
+
+testMain() {
+  test_pkg.fooz();
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    // Mark 'package:observatory_test_package_2/has_part.dart' as not debuggable.
+    await isolate.reload();
+    Library has_part =
+        isolate.libraries.firstWhere((Library library) => library.uri == file);
+    await has_part.load();
+    expect(has_part.debuggable, true);
+    // SetBreakpoint before setting library to non-debuggable.
+    // Breakpoints are allowed to be set (before marking library as
+    // non-debuggable) but are not hit when running (after marking library
+    // as non-debuggable).
+    Script script =
+        has_part.scripts.firstWhere((Script script) => script.uri == file);
+    Breakpoint bpt = await isolate.addBreakpoint(script, LINE_A);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+
+    // Set breakpoint and check later that this breakpoint won't be added if
+    // the library is non-debuggable.
+    bpt = await isolate.addBreakpoint(script, LINE_B);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+    await script.reload();
+    // Remove breakpoint.
+    var res = await isolate.removeBreakpoint(bpt);
+    expect(res.type, 'Success');
+
+    var setDebugParams = {
+      'libraryId': has_part.id,
+      'isDebuggable': false,
+    };
+    Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade(
+        'setLibraryDebuggable', setDebugParams);
+    expect(result['type'], 'Success');
+    await has_part.reload();
+    expect(has_part.debuggable, false);
+    print('$has_part is debuggable: ${has_part.debuggable}');
+
+    // Breakpoints are not allowed to set on non-debuggable libraries.
+    try {
+      await isolate.addBreakpoint(script, LINE_B);
+    } catch (e) {
+      expect(e is ServerRpcException, true);
+      expect(e.code == ServerRpcException.kCannotAddBreakpoint, true);
+      print("Set Breakpoint to non-debuggable library is not allowed");
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtExit,
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true, pause_on_exit: true);
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_1_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_1_test.dart
new file mode 100644
index 0000000..2d28590
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_1_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 18;
+const String file = "breakpoint_on_if_null_1_test.dart";
+
+code() {
+  foo(42);
+}
+
+foo(dynamic args) {
+  if (args == null) {
+    print("was null");
+  }
+  if (args != null) {
+    print("was not null");
+  }
+  if (args == 42) {
+    print("was 42!");
+  }
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$file:${LINE + 0}:12", // on '=='
+  "$file:${LINE + 3}:12", // on '!='
+  "$file:${LINE + 4}:5", // on 'print'
+  "$file:${LINE + 6}:12", // on '=='
+  "$file:${LINE + 7}:5", // on 'print'
+  "$file:${LINE + 9}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(file, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_2_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_2_test.dart
new file mode 100644
index 0000000..5eb37e5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_2_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 21;
+const String file = "breakpoint_on_if_null_2_test.dart";
+
+dynamic compareWithMe = 43;
+
+code() {
+  compareWithMe = null;
+  foo(42);
+}
+
+foo(dynamic args) {
+  if (args == compareWithMe) {
+    print("was null");
+  }
+  if (args != compareWithMe) {
+    print("was not null");
+  }
+  if (args == 42) {
+    print("was 42!");
+  }
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$file:${LINE + 0}:12", // on '=='
+  "$file:${LINE + 3}:12", // on '!='
+  "$file:${LINE + 4}:5", // on 'print'
+  "$file:${LINE + 6}:12", // on '=='
+  "$file:${LINE + 7}:5", // on 'print'
+  "$file:${LINE + 9}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(file, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_3_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_3_test.dart
new file mode 100644
index 0000000..a4c1fde
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_3_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 17;
+const String file = "breakpoint_on_if_null_3_test.dart";
+
+code() {
+  foo(42);
+}
+
+foo(dynamic args) {
+  if (args == null) {
+    print("was null");
+  }
+  if (args != null) {
+    print("was not null");
+  }
+  if (args == 42) {
+    print("was 42!");
+  }
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$file:${LINE + 0}:13", // on 'args'
+  "$file:${LINE + 1}:12", // on '=='
+  "$file:${LINE + 4}:12", // on '!='
+  "$file:${LINE + 5}:5", // on 'print'
+  "$file:${LINE + 7}:12", // on '=='
+  "$file:${LINE + 8}:5", // on 'print'
+  "$file:${LINE + 10}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(file, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_4_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_4_test.dart
new file mode 100644
index 0000000..7b9ffe1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_on_if_null_4_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 20;
+const String file = "breakpoint_on_if_null_4_test.dart";
+
+dynamic compareWithMe = 43;
+
+code() {
+  compareWithMe = null;
+  foo(42);
+}
+
+foo(dynamic args) {
+  if (args == compareWithMe) {
+    print("was null");
+  }
+  if (args != compareWithMe) {
+    print("was not null");
+  }
+  if (args == 42) {
+    print("was 42!");
+  }
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$file:${LINE + 0}:13", // on 'args'
+  "$file:${LINE + 1}:12", // on '=='
+  "$file:${LINE + 4}:12", // on '!='
+  "$file:${LINE + 5}:5", // on 'print'
+  "$file:${LINE + 7}:12", // on '=='
+  "$file:${LINE + 8}:5", // on 'print'
+  "$file:${LINE + 10}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(file, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_partfile_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_partfile_test.dart
new file mode 100644
index 0000000..e0ad0fa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_partfile_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library breakpoint_in_parts_class;
+
+import 'package:observatory_test_package_2/has_part.dart' as hasPart;
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 8;
+const String breakpointFile =
+    "package:observatory_test_package_2/the_part_2.dart";
+const String shortFile = "the_part_2.dart";
+
+code() {
+  hasPart.bar();
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:3", // on 'print'
+  "$shortFile:${LINE + 1}:1" // on class ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(breakpointFile, LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoint_two_args_checked_test.dart b/runtime/observatory_2/tests/service_2/breakpoint_two_args_checked_test.dart
new file mode 100644
index 0000000..b05b736
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoint_two_args_checked_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+// This test was mostly interesting for DBC, which needed to patch two bytecodes
+// to create a breakpoint for fast Smi ops.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 26;
+const int LINE_B = 27;
+const int LINE_C = 28;
+
+class NotGeneric {}
+
+testeeMain() {
+  var x = new List(1);
+  var y = 7;
+  debugger();
+  print("Statement");
+  x[0] = 3; // Line A.
+  x is NotGeneric; // Line B.
+  y & 4; // Line C.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Add breakpoints.
+  (Isolate isolate) async {
+    Library rootLib = await isolate.rootLibrary.load();
+    var script = rootLib.scripts[0];
+
+    var bpt1 = await isolate.addBreakpoint(script, LINE_A);
+    print(bpt1);
+    expect(bpt1.resolved, isTrue);
+    expect(await bpt1.location.getLine(), equals(LINE_A));
+
+    var bpt2 = await isolate.addBreakpoint(script, LINE_B);
+    print(bpt2);
+    expect(bpt2.resolved, isTrue);
+    expect(await bpt2.location.getLine(), equals(LINE_B));
+
+    var bpt3 = await isolate.addBreakpoint(script, LINE_C);
+    print(bpt3);
+    expect(bpt3.resolved, isTrue);
+    expect(await bpt3.location.getLine(), equals(LINE_C));
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib1.dart b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib1.dart
new file mode 100644
index 0000000..3c43715
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "breakpoints_with_mixin_lib3.dart";
+
+class Test1 extends Object with Foo {}
diff --git a/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib2.dart b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib2.dart
new file mode 100644
index 0000000..c054176
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "breakpoints_with_mixin_lib3.dart";
+
+class Test2 extends Object with Foo {}
diff --git a/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib3.dart b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib3.dart
new file mode 100644
index 0000000..a7329de
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_lib3.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  foo() {
+    print("I should be breakable!");
+  }
+}
+
+class Bar {
+  bar() {
+    print("I should be breakable too!");
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_test.dart b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_test.dart
new file mode 100644
index 0000000..05830b3
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/breakpoints_with_mixin_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+import "breakpoints_with_mixin_lib1.dart";
+import "breakpoints_with_mixin_lib2.dart";
+import "breakpoints_with_mixin_lib3.dart";
+
+const String testFilename = "breakpoints_with_mixin_test.dart";
+const int testCodeLineStart = 18;
+const String lib3Filename = "breakpoints_with_mixin_lib3.dart";
+const int lib3Bp1 = 7;
+const int lib3Bp2 = 13;
+
+void code() {
+  Test1 test1 = new Test1();
+  test1.foo();
+  Test2 test2 = new Test2();
+  test2.foo();
+  Foo foo = new Foo();
+  foo.foo();
+  Bar bar = new Bar();
+  bar.bar();
+  test1.foo();
+  test2.foo();
+  foo.foo();
+  bar.bar();
+}
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 2}:9)",
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 4}:9)",
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 6}:7)",
+  "$lib3Filename:$lib3Bp2:5 ($testFilename:${testCodeLineStart + 8}:7)",
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 9}:9)",
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 10}:9)",
+  "$lib3Filename:$lib3Bp1:5 ($testFilename:${testCodeLineStart + 11}:7)",
+  "$lib3Filename:$lib3Bp2:5 ($testFilename:${testCodeLineStart + 12}:7)",
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtUriAndLine(lib3Filename, lib3Bp1),
+  setBreakpointAtUriAndLine(lib3Filename, lib3Bp2),
+  resumeProgramRecordingStops(stops, true),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/caching_test.dart b/runtime/observatory_2/tests/service_2/caching_test.dart
new file mode 100644
index 0000000..f89a2c0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/caching_test.dart
@@ -0,0 +1,24 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// If caching is working properly, the coverage data will go into the same
+// Script object from which we requested coverage data, instead of a new
+// Script object.
+
+library caching_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Script script = await lib.scripts.single.load();
+    Script script2 = await isolate.getObject(script.id);
+    expect(identical(script, script2), isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/capture_stdio_test.dart b/runtime/observatory_2/tests/service_2/capture_stdio_test.dart
new file mode 100644
index 0000000..dc81e5a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/capture_stdio_test.dart
@@ -0,0 +1,80 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:io';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void test() {
+  debugger();
+  stdout.write('stdout');
+
+  debugger();
+  print('print');
+
+  debugger();
+  stderr.write('stderr');
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stdoutSub;
+    stdoutSub = await isolate.vm.listenEventStream(VM.kStdoutStream,
+        (ServiceEvent event) {
+      expect(event.kind, equals('WriteEvent'));
+      expect(event.bytesAsString, equals('stdout'));
+      stdoutSub.cancel().then((_) {
+        completer.complete();
+      });
+    });
+    await isolate.resume();
+    await completer.future;
+  },
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stdoutSub;
+    int eventNumber = 1;
+    stdoutSub = await isolate.vm.listenEventStream(VM.kStdoutStream,
+        (ServiceEvent event) {
+      expect(event.kind, equals('WriteEvent'));
+      if (eventNumber == 1) {
+        expect(event.bytesAsString, equals('print'));
+      } else if (eventNumber == 2) {
+        expect(event.bytesAsString, equals('\n'));
+        stdoutSub.cancel().then((_) {
+          completer.complete();
+        });
+      } else {
+        expect(true, false);
+      }
+      eventNumber++;
+    });
+    await isolate.resume();
+    await completer.future;
+  },
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stderrSub;
+    stderrSub = await isolate.vm.listenEventStream(VM.kStderrStream,
+        (ServiceEvent event) {
+      expect(event.kind, equals('WriteEvent'));
+      expect(event.bytesAsString, equals('stderr'));
+      stderrSub.cancel().then((_) {
+        completer.complete();
+      });
+    });
+    await isolate.resume();
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: test);
diff --git a/runtime/observatory_2/tests/service_2/causal_async_stack_contents_test.dart b/runtime/observatory_2/tests/service_2/causal_async_stack_contents_test.dart
new file mode 100644
index 0000000..067887d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/causal_async_stack_contents_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks --verbose_debug
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_C = 20;
+const LINE_A = 26;
+const LINE_B = 32;
+
+foobar() {
+  debugger();
+  print('foobar'); // LINE_C.
+}
+
+helper() async {
+  await 0; // force async gap
+  debugger();
+  print('helper'); // LINE_A.
+  foobar();
+}
+
+testMain() {
+  debugger();
+  helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack['asyncCausalFrames'], isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    if (useCausalAsyncStacks) {
+      expect(asyncStack[0].toString(), contains('helper'));
+      expect(asyncStack[1].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      expect(asyncStack[2].toString(), contains('testMain'));
+    } else {
+      expect(asyncStack[0].toString(), contains('helper'));
+      // "helper" is not await'ed.
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    if (useCausalAsyncStacks) {
+      expect(asyncStack[0].toString(), contains('foobar'));
+      expect(asyncStack[1].toString(), contains('helper'));
+      expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      expect(asyncStack[3].toString(), contains('testMain'));
+      expect(await asyncStack[0].location.toUserString(), contains('.dart:20'));
+      expect(await asyncStack[1].location.toUserString(), contains('.dart:27'));
+      expect(await asyncStack[3].location.toUserString(), contains('.dart:32'));
+    } else {
+      expect(asyncStack[0].toString(), contains('foobar'));
+      expect(asyncStack[1].toString(), contains('helper'));
+      // "helper" is not await'ed.
+    }
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart b/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart
new file mode 100644
index 0000000..c37359e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/causal_async_stack_presence_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks --verbose_debug
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_C = 19;
+const LINE_A = 24;
+const LINE_B = 30;
+
+foobar() {
+  debugger();
+  print('foobar'); // LINE_C.
+}
+
+helper() async {
+  debugger();
+  print('helper'); // LINE_A.
+  foobar();
+}
+
+testMain() {
+  debugger();
+  helper(); // LINE_B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack['asyncCausalFrames'], isNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/causal_async_star_stack_contents_test.dart b/runtime/observatory_2/tests/service_2/causal_async_star_stack_contents_test.dart
new file mode 100644
index 0000000..4474624
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/causal_async_star_stack_contents_test.dart
@@ -0,0 +1,106 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks --verbose_debug
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 29;
+const LINE_B = 21;
+const LINE_C = 23;
+
+foobar() async* {
+  await 0; // force async gap
+  debugger();
+  yield 1; // LINE_B.
+  debugger();
+  yield 2; // LINE_C.
+}
+
+helper() async {
+  await 0; // force async gap
+  debugger();
+  print('helper'); // LINE_A.
+  await for (var i in foobar()) {
+    print('helper $i');
+  }
+}
+
+testMain() {
+  helper();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    if (useCausalAsyncStacks) {
+      expect(asyncStack.length, greaterThanOrEqualTo(3));
+      expect(asyncStack[0].toString(), contains('helper'));
+      expect(asyncStack[1].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      expect(asyncStack[2].toString(), contains('testMain'));
+    } else {
+      expect(asyncStack.length, greaterThanOrEqualTo(1));
+      expect(asyncStack[0].toString(), contains('helper'));
+      // helper isn't awaited.
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    expect(asyncStack.length, greaterThanOrEqualTo(3));
+    expect(asyncStack[0].toString(), contains('foobar'));
+    expect(asyncStack[1].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    expect(asyncStack[2].toString(), contains('helper'));
+    expect(asyncStack[3].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    if (useCausalAsyncStacks) {
+      // helper isn't awaited.
+      expect(asyncStack[4].toString(), contains('testMain'));
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    print('async:');
+    await printFrames(asyncStack);
+    print('sync:');
+    await printFrames(stack['frames']);
+    expect(asyncStack.length, greaterThanOrEqualTo(4));
+    expect(asyncStack[0].toString(), contains('foobar'));
+    expect(
+        await asyncStack[0].location.toUserString(), contains('.dart:$LINE_C'));
+    expect(asyncStack[1].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    expect(asyncStack[2].toString(), contains('helper'));
+    expect(await asyncStack[2].location.toUserString(), contains('.dart:30'));
+    expect(asyncStack[3].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    if (useCausalAsyncStacks) {
+      // helper isn't awaited.
+      expect(asyncStack.length, greaterThanOrEqualTo(5));
+      expect(asyncStack[4].toString(), contains('testMain'));
+      expect(await asyncStack[4].location.toUserString(), contains('.dart:36'));
+    }
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart b/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart
new file mode 100644
index 0000000..db19b2c
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/causal_async_star_stack_presence_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks --verbose_debug
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks --verbose_debug
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 26;
+const LINE_B = 19;
+const LINE_C = 21;
+
+foobar() async* {
+  debugger();
+  yield 1; // LINE_B.
+  debugger();
+  yield 2; // LINE_C.
+}
+
+helper() async {
+  debugger();
+  print('helper'); // LINE_A.
+  await for (var i in foobar()) {
+    print('helper $i');
+  }
+}
+
+testMain() {
+  helper();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // No causal frames because we are in a completely synchronous stack.
+    expect(stack['asyncCausalFrames'], isNotNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Has causal frames (we are inside a function called by an async function)
+    expect(stack['asyncCausalFrames'], isNotNull);
+  },
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: testMain, extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/client_name_rpc_test.dart b/runtime/observatory_2/tests/service_2/client_name_rpc_test.dart
new file mode 100644
index 0000000..6d0f8e5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_name_rpc_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    final defaultClientName = 'client1';
+    final clientName = 'agent-007';
+    var result = await vm.invokeRpcNoUpgrade('getClientName', {});
+    expect(result['type'], 'ClientName');
+    expect(result['name'], defaultClientName);
+
+    // Set the name for this client.
+    result = await vm.invokeRpcNoUpgrade(
+      'setClientName',
+      {
+        'name': clientName,
+      },
+    );
+    expect(result['type'], 'Success');
+
+    // Check it was set properly.
+    result = await vm.invokeRpcNoUpgrade('getClientName', {});
+    expect(result['type'], 'ClientName');
+    expect(result['name'], clientName);
+
+    // Check clearing works properly.
+    result = await vm.invokeRpcNoUpgrade(
+      'setClientName',
+      {
+        'name': '',
+      },
+    );
+    expect(result['type'], 'Success');
+
+    result = await vm.invokeRpcNoUpgrade('getClientName', {});
+    expect(result['type'], 'ClientName');
+    expect(result['name'], defaultClientName);
+  },
+  // Try to set an invalid agent name for this client.
+  (VM vm) async {
+    try {
+      await vm.invokeRpcNoUpgrade(
+        'setClientName',
+        {
+          'name': 42,
+        },
+      );
+      fail('Successfully set invalid client name');
+    } on ServerRpcException catch (e) {/* expected */}
+  },
+  // Missing parameters.
+  (VM vm) async {
+    try {
+      await vm.invokeRpcNoUpgrade('setClientName', {});
+      fail('Successfully set name with no type');
+    } on ServerRpcException catch (e) {/* expected */}
+  },
+];
+
+main(args) async => runVMTests(
+      args,
+      tests,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_approve_then_disconnect_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_approve_then_disconnect_test.dart
new file mode 100644
index 0000000..b33fc3f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_approve_then_disconnect_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+
+final test = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    client1 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+    client2 = await createClient(
+      isolate.owner,
+      clientName: otherClientName,
+    );
+    await setRequireApprovalForResume(
+      client2,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+
+    // Give resume approval for client1 to ensure approval state is cleaned up
+    // properly when both client1 and client2 have disconnected.
+    await resume(client1, isolate);
+    expect(await isPausedAtStart(isolate), true);
+
+    // Once client1 is disconnected, we should still be paused.
+    client1.disconnect();
+    expect(await isPausedAtStart(isolate), true);
+
+    // Once client2 disconnects, there are no clients which require resume
+    // approval. Since there were no resume requests made by clients which are
+    // still connected, the isolate remains paused.
+    client2.disconnect();
+    expect(await isPausedAtStart(isolate), true);
+
+    await isolate.resume();
+  },
+  hasStoppedAtExit,
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      test,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      pause_on_exit: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_common.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_common.dart
new file mode 100644
index 0000000..fb60217
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_common.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'service_test_common.dart';
+
+const String clientName = 'TestClient';
+const String otherClientName = 'OtherTestClient';
+
+Future<void> setClientName(WebSocketVM client, String name) async =>
+    await client.invokeRpc('setClientName', {'name': name});
+
+Future<WebSocketVM> createClient(WebSocketVM vm,
+    {String clientName: clientName}) async {
+  final client = WebSocketVM(vm.target);
+  await client.load();
+  await setClientName(client, clientName);
+  return client;
+}
+
+Future<void> setRequireApprovalForResume(
+  WebSocketVM vm,
+  Isolate isolate, {
+  bool pauseOnStart: false,
+  bool pauseOnExit: false,
+  bool pauseOnReload: false,
+}) async {
+  int pauseTypeMask = 0;
+  if (pauseOnStart) {
+    pauseTypeMask |= 1;
+  }
+  if (pauseOnReload) {
+    pauseTypeMask |= 2;
+  }
+  if (pauseOnExit) {
+    pauseTypeMask |= 4;
+  }
+  await vm.invokeRpc('requirePermissionToResume', {
+    'isolateId': isolate.id,
+    'pauseTypeMask': pauseTypeMask,
+    'onPauseStart': pauseOnStart,
+    'onPauseReload': pauseOnReload,
+    'onPauseExit': pauseOnExit,
+  });
+}
+
+Future<void> resume(WebSocketVM vm, Isolate isolate) async =>
+    await vm.invokeRpc('resume', {
+      'isolateId': isolate.id,
+    });
+
+Future<bool> isPausedAtStart(Isolate isolate) async {
+  await isolate.reload();
+  return ((isolate.pauseEvent != null) &&
+      isEventOfKind(isolate.pauseEvent, ServiceEvent.kPauseStart));
+}
+
+Future<bool> isPausedAtExit(Isolate isolate) async {
+  await isolate.reload();
+  return ((isolate.pauseEvent != null) &&
+      isEventOfKind(isolate.pauseEvent, ServiceEvent.kPauseExit));
+}
+
+Future<bool> isPausedPostRequest(Isolate isolate) async {
+  await isolate.reload();
+  return ((isolate.pauseEvent != null) &&
+      isEventOfKind(isolate.pauseEvent, ServiceEvent.kPausePostRequest));
+}
+
+Future<void> waitForResume(Isolate isolate) async {
+  final completer = Completer<bool>();
+  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+  });
+  return completer.future;
+}
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_disconnect_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_disconnect_test.dart
new file mode 100644
index 0000000..f59ca97
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_disconnect_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+
+final test = <IsolateTest>[
+  // Multiple clients, disconnect client awaiting approval.
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    client1 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+    client2 = await createClient(
+      isolate.owner,
+      clientName: otherClientName,
+    );
+    await setRequireApprovalForResume(
+      client2,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+
+    // Send a resume request on the test client so we'll resume once the other
+    // clients which require approval disconnect.
+    await isolate.resume();
+    expect(await isPausedAtStart(isolate), true);
+
+    // Once client1 is disconnected, we should still be paused.
+    client1.disconnect();
+    expect(await isPausedAtStart(isolate), true);
+
+    // Once client2 disconnects, there are no clients which require resume
+    // approval. Ensure we resume immediately so we don't deadlock waiting for
+    // approvals from disconnected clients.
+    client2.disconnect();
+  },
+  hasStoppedAtExit,
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      test,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      pause_on_exit: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_identical_names_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_identical_names_test.dart
new file mode 100644
index 0000000..ba4faa4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_identical_names_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+
+final sameClientNamesTest = <IsolateTest>[
+  // Multiple clients, same client names.
+  (Isolate isolate) async {
+    final resumeFuture = waitForResume(isolate);
+
+    client1 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+    client2 = await createClient(isolate.owner);
+
+    expect(await isPausedAtStart(isolate), true);
+    await resume(client2, isolate);
+    await resumeFuture;
+  },
+  hasStoppedAtExit,
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      sameClientNamesTest,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      pause_on_exit: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_multiple_names_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_multiple_names_test.dart
new file mode 100644
index 0000000..818a0a2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_multiple_names_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+WebSocketVM client3;
+
+final multipleClientNamesTest = <IsolateTest>[
+  // Multiple clients, different client names.
+  (Isolate isolate) async {
+    client1 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+    client2 = await createClient(
+      isolate.owner,
+      clientName: otherClientName,
+    );
+    client3 = await createClient(isolate.owner, clientName: 'DummyClient');
+
+    final resumeFuture = waitForResume(isolate);
+    expect(await isPausedAtStart(isolate), true);
+    await resume(client2, isolate);
+    expect(await isPausedAtStart(isolate), true);
+    await resume(client1, isolate);
+    await resumeFuture;
+    expect(await isPausedAtStart(isolate), false);
+  },
+  hasStoppedAtExit,
+  (Isolate isolate) async {
+    await setRequireApprovalForResume(
+      client2,
+      isolate,
+      pauseOnExit: true,
+    );
+    await resume(client1, isolate);
+    expect(await isPausedAtExit(isolate), true);
+    await resume(client2, isolate);
+    await waitForTargetVMExit(isolate.vm);
+  },
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      multipleClientNamesTest,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      pause_on_exit: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_name_change_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_name_change_test.dart
new file mode 100644
index 0000000..bedf87f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_name_change_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+WebSocketVM client3;
+
+final nameChangeTest = <IsolateTest>[
+  // Remove required approvals via name change.
+  (Isolate isolate) async {
+    final resumeFuture = waitForResume(isolate);
+
+    // Create two clients with the same name.
+    client1 = await createClient(isolate.owner);
+    client2 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnStart: true,
+      pauseOnExit: true,
+    );
+    client3 = await createClient(isolate.owner, clientName: otherClientName);
+
+    // Check that client3 can't resume the isolate on its own.
+    expect(await isPausedAtStart(isolate), true);
+    await resume(client3, isolate);
+    expect(await isPausedAtStart(isolate), true);
+
+    // Change the name of client1. Since client2 has the same name that client1
+    // originally had, the service still requires approval to resume the
+    // isolate.
+    await setClientName(client1, 'foobar');
+    expect(await isPausedAtStart(isolate), true);
+    await setClientName(client2, 'baz');
+  },
+  hasStoppedAtExit,
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      nameChangeTest,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      pause_on_exit: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/client_resume_approvals_reload_test.dart b/runtime/observatory_2/tests/service_2/client_resume_approvals_reload_test.dart
new file mode 100644
index 0000000..b77ec16
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/client_resume_approvals_reload_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void fooBar() {
+  int i = 0;
+  while (true) {
+    i++;
+  }
+  print(i);
+}
+
+WebSocketVM client1;
+WebSocketVM client2;
+
+final hotReloadTest = <IsolateTest>[
+  // Multiple clients, hot reload approval.
+  (Isolate isolate) async {
+    final resumeFuture = waitForResume(isolate);
+
+    client1 = await createClient(isolate.owner);
+    await setRequireApprovalForResume(
+      client1,
+      isolate,
+      pauseOnReload: true,
+    );
+    client2 = await createClient(
+      isolate.owner,
+      clientName: otherClientName,
+    );
+    await setRequireApprovalForResume(
+      client2,
+      isolate,
+      pauseOnReload: true,
+    );
+  },
+  // Paused on start, resume.
+  resumeIsolate,
+  // Reload and then pause.
+  reloadSources(true),
+  hasStoppedPostRequest,
+  (Isolate isolate) async {
+    // Check that client2 can't resume the isolate on its own.
+    expect(await isPausedPostRequest(isolate), true);
+    await resume(client2, isolate);
+    expect(await isPausedPostRequest(isolate), true);
+    final resumeFuture = waitForResume(isolate);
+    await resume(client1, isolate);
+    await resumeFuture;
+    expect(await isPausedPostRequest(isolate), false);
+  },
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      hotReloadTest,
+      testeeConcurrent: fooBar,
+      pause_on_start: true,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/code_test.dart b/runtime/observatory_2/tests/service_2/code_test.dart
new file mode 100644
index 0000000..a369d3f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/code_test.dart
@@ -0,0 +1,82 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int counter = 0;
+
+void funcB() {
+  counter++; // line 13
+  if (counter % 100000000 == 0) {
+    print(counter);
+  }
+}
+
+void funcA() {
+  funcB();
+}
+
+void testFunction() {
+  while (true) {
+    funcA();
+  }
+}
+
+var tests = <IsolateTest>[
+// Go to breakpoint at line 13.
+  (Isolate isolate) async {
+    await isolate.rootLibrary.load();
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+      var subscription;
+      subscription = stream.listen((ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseBreakpoint) {
+          print('Breakpoint reached');
+          subscription.cancel();
+          completer.complete();
+        }
+      });
+    });
+
+    // Add the breakpoint.
+    var script = isolate.rootLibrary.scripts[0];
+    var line = 13;
+    isolate.addBreakpoint(script, line);
+    await completer.future; // Wait for breakpoint reached.
+  },
+
+// Inspect code objects for top two frames.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(3));
+    var frame0 = stack['frames'][0];
+    var frame1 = stack['frames'][1];
+    print(frame0);
+    expect(frame0.function.name, equals('funcB'));
+    expect(frame1.function.name, equals('funcA'));
+    var codeId0 = frame0.code.id;
+    var codeId1 = frame1.code.id;
+
+    List tests = <IsolateTest>[];
+    // Load code from frame 0.
+    Code code = await isolate.getObject(codeId0);
+    expect(code.type, equals('Code'));
+    expect(code.function.name, equals('funcB'));
+    expect(code.hasDisassembly, equals(true));
+
+    // Load code from frame 0.
+    code = await isolate.getObject(codeId1);
+    expect(code.type, equals('Code'));
+    expect(code.function.name, equals('funcA'));
+    expect(code.hasDisassembly, equals(true));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/collect_all_garbage_test.dart b/runtime/observatory_2/tests/service_2/collect_all_garbage_test.dart
new file mode 100644
index 0000000..48589e9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/collect_all_garbage_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var result = await isolate.invokeRpcNoUpgrade('_collectAllGarbage', {});
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/column_breakpoint_test.dart b/runtime/observatory_2/tests/service_2/column_breakpoint_test.dart
new file mode 100644
index 0000000..b474d6d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/column_breakpoint_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+code() {
+  var b = [1, 2].map((i) => i == 0).toList();
+  print(b.length);
+}
+
+const int LINE = 9;
+const int COLUMN = 29;
+const String shortFile = "column_breakpoint_test.dart";
+const String breakpointFile =
+    "package:observatory_test_package_2/column_breakpoint_test.dart";
+
+List<String> stops = [];
+
+List<String> expected = [
+  "$shortFile:${LINE + 0}:23", // on 'i == 0'
+  "$shortFile:${LINE + 0}:23", // iterate twice
+  "$shortFile:${LINE + 1}:3" //on 'b.length'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLineColumn(LINE, COLUMN), // on 'i == 0'
+  setBreakpointAtLineColumn(LINE + 1, 9), // on 'b.length'
+  resumeProgramRecordingStops(stops, false),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/command_test.dart b/runtime/observatory_2/tests/service_2/command_test.dart
new file mode 100644
index 0000000..23769c0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/command_test.dart
@@ -0,0 +1,233 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/cli.dart';
+import 'package:test/test.dart';
+
+class TestCommand extends Command {
+  TestCommand(this.out, name, children) : super(name, children);
+  StringBuffer out;
+
+  Future run(List<String> args) {
+    out.write('executing ${name}(${args})\n');
+    return new Future.value(null);
+  }
+}
+
+class TestCompleteCommand extends Command {
+  TestCompleteCommand(this.out, name, children) : super(name, children);
+  StringBuffer out;
+
+  Future<List<String>> complete(List<String> args) {
+    var possibles = ['one ', 'two ', 'three '];
+    return new Future.value(
+        possibles.where((possible) => possible.startsWith(args[0])).toList());
+  }
+
+  Future run(List<String> args) {
+    out.write('executing ${name}(${args})\n');
+    return new Future.value(null);
+  }
+}
+
+void testCommandComplete() {
+  RootCommand cmd = new RootCommand([
+    new TestCommand(null, 'alpha', <Command>[]),
+    new TestCommand(null, 'game', <Command>[
+      new TestCommand(null, 'checkers', <Command>[]),
+      new TestCommand(null, 'chess', <Command>[])
+    ]),
+    new TestCommand(null, 'gamera', <Command>[
+      new TestCommand(null, 'london', <Command>[]),
+      new TestCommand(null, 'tokyo', <Command>[]),
+      new TestCommand(null, 'topeka', <Command>[])
+    ]),
+    new TestCompleteCommand(
+        null, 'count', <Command>[new TestCommand(null, 'chocula', <Command>[])])
+  ]);
+
+  // Show all commands.
+  cmd.completeCommand('').then((result) {
+    expect(result, equals(['alpha ', 'game ', 'gamera ', 'count ']));
+  });
+
+  // Substring completion.
+  cmd.completeCommand('al').then((result) {
+    expect(result, equals(['alpha ']));
+  });
+
+  // Full string completion.
+  cmd.completeCommand('alpha').then((result) {
+    expect(result, equals(['alpha ']));
+  });
+
+  // Extra space, no subcommands.
+  cmd.completeCommand('alpha ').then((result) {
+    expect(result, equals(['alpha ']));
+  });
+
+  // Ambiguous completion.
+  cmd.completeCommand('g').then((result) {
+    expect(result, equals(['game ', 'gamera ']));
+  });
+
+  // Ambiguous completion, exact match not preferred.
+  cmd.completeCommand('game').then((result) {
+    expect(result, equals(['game ', 'gamera ']));
+  });
+
+  // Show all subcommands.
+  cmd.completeCommand('gamera ').then((result) {
+    expect(
+        result, equals(['gamera london ', 'gamera tokyo ', 'gamera topeka ']));
+  });
+
+  // Subcommand completion.
+  cmd.completeCommand('gamera l').then((result) {
+    expect(result, equals(['gamera london ']));
+  });
+
+  // Extra space, with subcommand.
+  cmd.completeCommand('gamera london ').then((result) {
+    expect(result, equals(['gamera london ']));
+  });
+
+  // Ambiguous subcommand completion.
+  cmd.completeCommand('gamera t').then((result) {
+    expect(result, equals(['gamera tokyo ', 'gamera topeka ']));
+  });
+
+  // Ambiguous subcommand completion with substring prefix.
+  // Note that the prefix is left alone.
+  cmd.completeCommand('gamer t').then((result) {
+    expect(result, equals(['gamer tokyo ', 'gamer topeka ']));
+  });
+
+  // Ambiguous but exact prefix is preferred.
+  cmd.completeCommand('game chec').then((result) {
+    expect(result, equals(['game checkers ']));
+  });
+
+  // Ambiguous non-exact prefix means no matches.
+  cmd.completeCommand('gam chec').then((result) {
+    expect(result, equals([]));
+  });
+
+  // Locals + subcommands, show all.
+  cmd.completeCommand('count ').then((result) {
+    expect(result,
+        equals(['count chocula ', 'count one ', 'count two ', 'count three ']));
+  });
+
+  // Locals + subcommands, single local match.
+  cmd.completeCommand('count th').then((result) {
+    expect(result, equals(['count three ']));
+  });
+
+  // Locals + subcommands, ambiguous local match.
+  cmd.completeCommand('count t').then((result) {
+    expect(result, equals(['count two ', 'count three ']));
+  });
+
+  // Locals + subcommands, single command match.
+  cmd.completeCommand('co choc').then((result) {
+    expect(result, equals(['co chocula ']));
+  });
+
+  // We gobble spare spaces in the prefix but not elsewhere.
+  cmd.completeCommand('    game    chec').then((result) {
+    expect(result, equals(['game    checkers ']));
+  });
+}
+
+testCommandRunSimple() async {
+  // Run a simple command.
+  StringBuffer out = new StringBuffer();
+  RootCommand cmd =
+      new RootCommand([new TestCommand(out, 'alpha', <Command>[])]);
+
+  // Full name dispatch works.  Argument passing works.
+  await cmd.runCommand('alpha dog');
+  expect(out.toString(), contains('executing alpha([dog])\n'));
+  out.clear();
+  // Substring dispatch works.
+  await cmd.runCommand('al cat mouse');
+  expect(out.toString(), contains('executing alpha([cat , mouse])\n'));
+}
+
+testCommandRunSubcommand() async {
+  // Run a simple command.
+  StringBuffer out = new StringBuffer();
+  RootCommand cmd = new RootCommand([
+    new TestCommand(out, 'alpha', [
+      new TestCommand(out, 'beta', <Command>[]),
+      new TestCommand(out, 'gamma', <Command>[])
+    ])
+  ]);
+
+  await cmd.runCommand('a b');
+  expect(out.toString(), equals('executing beta([])\n'));
+  out.clear();
+  await cmd.runCommand('alpha g ');
+  expect(out.toString(), equals('executing gamma([])\n'));
+}
+
+testCommandRunNotFound() async {
+  // Run a simple command.
+  StringBuffer out = new StringBuffer();
+  RootCommand cmd =
+      new RootCommand([new TestCommand(out, 'alpha', <Command>[])]);
+
+  dynamic e;
+  try {
+    await cmd.runCommand('goose');
+  } catch (ex) {
+    e = ex;
+  }
+  expect(e.toString(), equals("No such command: 'goose'"));
+}
+
+testCommandRunAmbiguous() async {
+  // Run a simple command.
+  StringBuffer out = new StringBuffer();
+  RootCommand cmd = new RootCommand([
+    new TestCommand(out, 'alpha', <Command>[]),
+    new TestCommand(out, 'ankle', <Command>[])
+  ]);
+
+  dynamic e;
+  try {
+    await cmd.runCommand('a 55');
+  } catch (ex) {
+    e = ex;
+  }
+  expect(e.toString(), equals("Command 'a 55' is ambiguous: [alpha, ankle]"));
+  out.clear();
+
+  await cmd.runCommand('ankl 55');
+  expect(out.toString(), equals('executing ankle([55])\n'));
+}
+
+testCommandRunAlias() async {
+  // Run a simple command.
+  StringBuffer out = new StringBuffer();
+  var aliasCmd = new TestCommand(out, 'alpha', <Command>[]);
+  aliasCmd.alias = 'a';
+  RootCommand cmd =
+      new RootCommand([aliasCmd, new TestCommand(out, 'ankle', <Command>[])]);
+
+  await cmd.runCommand('a 55');
+  expect(out.toString(), equals('executing alpha([55])\n'));
+}
+
+main() {
+  test('command completion test suite', testCommandComplete);
+  test('run a simple command', testCommandRunSimple);
+  test('run a subcommand', testCommandRunSubcommand);
+  test('run a command which is not found', testCommandRunNotFound);
+  test('run a command which is ambiguous', testCommandRunAmbiguous);
+  test('run a command using an alias', testCommandRunAlias);
+}
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v1/main.dart b/runtime/observatory_2/tests/service_2/complex_reload/v1/main.dart
new file mode 100644
index 0000000..043b9b9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v1/main.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+test() => 'apple';
+
+main() {
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v2/.gitignore b/runtime/observatory_2/tests/service_2/complex_reload/v2/.gitignore
new file mode 100644
index 0000000..1d24550
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v2/.gitignore
@@ -0,0 +1 @@
+!packages
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v2/foobar_lib/foo.dart b/runtime/observatory_2/tests/service_2/complex_reload/v2/foobar_lib/foo.dart
new file mode 100644
index 0000000..8981163
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v2/foobar_lib/foo.dart
@@ -0,0 +1 @@
+fooLib() => 'fooLib';
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v2/main.dart b/runtime/observatory_2/tests/service_2/complex_reload/v2/main.dart
new file mode 100644
index 0000000..2088634
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v2/main.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:foobar/foo.dart';
+
+test() => fooLib();
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v2/packages b/runtime/observatory_2/tests/service_2/complex_reload/v2/packages
new file mode 100644
index 0000000..9d477cd
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v2/packages
@@ -0,0 +1 @@
+foobar:foobar_lib/
diff --git a/runtime/observatory_2/tests/service_2/complex_reload/v3/main.dart b/runtime/observatory_2/tests/service_2/complex_reload/v3/main.dart
new file mode 100644
index 0000000..01756a99
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload/v3/main.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+test() => 'cabbage';
diff --git a/runtime/observatory_2/tests/service_2/complex_reload_test.dart b/runtime/observatory_2/tests/service_2/complex_reload_test.dart
new file mode 100644
index 0000000..4e63b8d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/complex_reload_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory_2/service.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri spawnUri = baseUri.resolveUri(Uri.parse('complex_reload/v1/main.dart'));
+Uri v2Uri = baseUri.resolveUri(Uri.parse('complex_reload/v2/main.dart'));
+Uri v3Uri = baseUri.resolveUri(Uri.parse('complex_reload/v3/main.dart'));
+Uri v2PackagesUri = baseUri.resolveUri(Uri.parse('complex_reload/v2/packages'));
+
+testMain() async {
+  print(baseUri);
+  debugger(); // Stop here.
+  // Spawn the child isolate.
+  I.Isolate isolate = await I.Isolate.spawnUri(spawnUri, [], null);
+  print(isolate);
+  debugger();
+}
+
+Future<String> invokeTest(Isolate isolate) async {
+  await isolate.reload();
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  Instance result = await lib.evaluate('test()');
+  expect(result.isString, isTrue);
+  return result.valueAsString;
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Stop at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  (Isolate mainIsolate) async {
+    // Grab the VM.
+    VM vm = mainIsolate.vm;
+    await vm.reloadIsolates();
+    expect(vm.isolates.length, 2);
+
+    // Find the spawned isolate.
+    Isolate spawnedIsolate =
+        vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+    expect(spawnedIsolate, isNotNull);
+
+    // Invoke test in v1.
+    String v1 = await invokeTest(spawnedIsolate);
+    expect(v1, 'apple');
+
+    // Reload to v2.
+    var response = await spawnedIsolate.reloadSources(
+      rootLibUri: v2Uri.toString(),
+      packagesUri: v2PackagesUri.toString(),
+    );
+    print(response);
+    expect(response['success'], isTrue);
+
+    // Invoke test in v2.
+    String v2 = await invokeTest(spawnedIsolate);
+    expect(v2, 'fooLib');
+
+    // Reload to v3.
+    response = await spawnedIsolate.reloadSources(
+      rootLibUri: v3Uri.toString(),
+    );
+    expect(response['success'], isTrue);
+
+    // Invoke test in v3.
+    String v3 = await invokeTest(spawnedIsolate);
+    expect(v3, 'cabbage');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/contexts_test.dart b/runtime/observatory_2/tests/service_2/contexts_test.dart
new file mode 100644
index 0000000..fb40ffa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/contexts_test.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library inbound_references_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
+var cleanBlock;
+@pragma("vm:entry-point")
+var copyingBlock;
+@pragma("vm:entry-point")
+var fullBlock;
+@pragma("vm:entry-point")
+var fullBlockWithChain;
+
+Function genCleanBlock() {
+  block(x) => x;
+  return block;
+}
+
+Function genCopyingBlock() {
+  final x = 'I could be copied into the block';
+  block() => x;
+  return block;
+}
+
+Function genFullBlock() {
+  var x = 42; // I must captured in a context.
+  block() => x;
+  x++;
+  return block;
+}
+
+Function genFullBlockWithChain() {
+  var x = 420; // I must captured in a context.
+  outerBlock() {
+    var y = 4200;
+    innerBlock() => x + y;
+    y++;
+    return innerBlock;
+  }
+
+  x++;
+  return outerBlock();
+}
+
+void script() {
+  cleanBlock = genCleanBlock();
+  copyingBlock = genCopyingBlock();
+  fullBlock = genFullBlock();
+  fullBlockWithChain = genFullBlockWithChain();
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field field = lib.variables.singleWhere((v) => v.name == 'cleanBlock');
+    await field.load();
+    Instance block = await field.staticValue.load();
+    expect(block.isClosure, isTrue);
+    expect(block.closureContext, isNull);
+  },
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field field = lib.variables.singleWhere((v) => v.name == 'copyingBlock');
+    await field.load();
+    Instance block = await field.staticValue.load();
+    expect(block.isClosure, isTrue);
+    expect(block.closureContext.isContext, isTrue);
+    expect(block.closureContext.length, equals(1));
+    Context ctxt = await block.closureContext.load();
+    expect(ctxt.variables.single.value.asValue.isString, isTrue);
+    expect(ctxt.variables.single.value.asValue.valueAsString,
+        equals('I could be copied into the block'));
+    expect(ctxt.parentContext, isNull);
+  },
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field field = lib.variables.singleWhere((v) => v.name == 'fullBlock');
+    await field.load();
+    Instance block = await field.staticValue.load();
+    expect(block.isClosure, isTrue);
+    expect(block.closureContext.isContext, isTrue);
+    expect(block.closureContext.length, equals(1));
+    Context ctxt = await block.closureContext.load();
+    expect(ctxt.variables.single.value.asValue.isInt, isTrue);
+    expect(ctxt.variables.single.value.asValue.valueAsString, equals('43'));
+    expect(ctxt.parentContext, isNull);
+  },
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field field =
+        lib.variables.singleWhere((v) => v.name == 'fullBlockWithChain');
+    await field.load();
+    Instance block = await field.staticValue.load();
+    expect(block.isClosure, isTrue);
+    expect(block.closureContext.isContext, isTrue);
+    expect(block.closureContext.length, equals(1));
+    Context ctxt = await block.closureContext.load();
+    expect(ctxt.variables.single.value.asValue.isInt, isTrue);
+    expect(ctxt.variables.single.value.asValue.valueAsString, equals('4201'));
+    expect(ctxt.parentContext.isContext, isTrue);
+    expect(ctxt.parentContext.length, equals(1));
+    Context outerCtxt = await ctxt.parentContext.load();
+    expect(outerCtxt.variables.single.value.asValue.isInt, isTrue);
+    expect(
+        outerCtxt.variables.single.value.asValue.valueAsString, equals('421'));
+    expect(outerCtxt.parentContext, isNull);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/coverage_const_field_async_closure_test.dart b/runtime/observatory_2/tests/service_2/coverage_const_field_async_closure_test.dart
new file mode 100644
index 0000000..f2c21ce
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/coverage_const_field_async_closure_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 15; // LINE_A - 4
+const int LINE_B = 23; // LINE_A - 3
+
+class Bar {
+  static const String field = "field"; // LINE_A
+}
+
+Future<String> fooAsync(int x) async {
+  if (x == 42) {
+    return '*' * x;
+  }
+  return List.generate(x, (_) => 'xyzzy').join(' ');
+} // LINE_B
+
+void testFunction() async {
+  await new Future.delayed(Duration(milliseconds: 500));
+  fooAsync(42).then((_) {});
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, 'Stack');
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    // Async closure of testFunction
+    expect(stack['frames'][0].function.name, 'async_op');
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    Script script = root.scripts.first;
+    await script.load();
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': script.id,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    List<dynamic> ranges = report['ranges'];
+
+    int match = 0;
+    for (var range in ranges) {
+      for (int i in range["coverage"]["hits"]) {
+        int line = script.tokenToLine(i);
+        if (line == null) {
+          throw FormatException('token ${i} was missing source location');
+        }
+        // Check LINE.
+        if (line == LINE_A || line == LINE_A - 3 || line == LINE_A - 4) {
+          match = match + 1;
+        }
+        // _clearAsyncThreadStackTrace should have an invalid token position.
+        expect(line, isNot(LINE_B));
+      }
+    }
+    // Neither LINE nor Bar.field should be added into coverage.
+    expect(match, 0);
+  },
+  resumeIsolate
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/coverage_leaf_function_test.dart b/runtime/observatory_2/tests/service_2/coverage_leaf_function_test.dart
new file mode 100644
index 0000000..25587aa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/coverage_leaf_function_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+
+String leafFunction() {
+  return "some constant";
+}
+
+void testFunction() {
+  debugger();
+  leafFunction();
+  debugger();
+}
+
+bool allRangesCompiled(coverage) {
+  for (int i = 0; i < coverage['ranges'].length; i++) {
+    if (!coverage['ranges'][i]['compiled']) {
+      return false;
+    }
+  }
+  return true;
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    var func = root.functions.singleWhere((f) => f.name == 'leafFunction');
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 384,
+      'endPos': 434,
+      'compiled': true,
+      'coverage': {
+        'hits': [],
+        'misses': [384]
+      }
+    };
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id,
+      'tokenPos': func.location.tokenPos,
+      'endTokenPos': func.location.endTokenPos,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(report['type'], equals('SourceReport'));
+    expect(report['ranges'].length, 1);
+    expect(report['ranges'][0], equals(expectedRange));
+    expect(report['scripts'].length, 1);
+    expect(report['scripts'][0]['uri'],
+        endsWith('coverage_leaf_function_test.dart'));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    var func = root.functions.singleWhere((f) => f.name == 'leafFunction');
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 384,
+      'endPos': 434,
+      'compiled': true,
+      'coverage': {
+        'hits': [384],
+        'misses': []
+      }
+    };
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id,
+      'tokenPos': func.location.tokenPos,
+      'endTokenPos': func.location.endTokenPos,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(report['type'], equals('SourceReport'));
+    expect(report['ranges'].length, 1);
+    expect(report['ranges'][0], equals(expectedRange));
+    expect(report['scripts'].length, 1);
+    expect(report['scripts'][0]['uri'],
+        endsWith('coverage_leaf_function_test.dart'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/coverage_optimized_function_test.dart b/runtime/observatory_2/tests/service_2/coverage_optimized_function_test.dart
new file mode 100644
index 0000000..d99072d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/coverage_optimized_function_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--no_background_compilation --optimization_counter_threshold=10
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+
+String optimizedFunction() {
+  return 5.toString() + 3.toString();
+}
+
+void testFunction() {
+  for (var i = 0; i < 20; i++) {
+    optimizedFunction();
+  }
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    var func = root.functions.singleWhere((f) => f.name == 'optimizedFunction');
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 461,
+      'endPos': 528,
+      'compiled': true,
+      'coverage': {
+        'hits': [461, 501, 512, 516],
+        'misses': []
+      }
+    };
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id,
+      'tokenPos': func.location.tokenPos,
+      'endTokenPos': func.location.endTokenPos,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(report['type'], equals('SourceReport'));
+    expect(report['ranges'].length, 1);
+    expect(report['ranges'][0], equals(expectedRange));
+    expect(report['scripts'].length, 1);
+    expect(report['scripts'][0]['uri'],
+        endsWith('coverage_optimized_function_test.dart'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/dds_log_history_size_gigantic_test.dart b/runtime/observatory_2/tests/service_2/dds_log_history_size_gigantic_test.dart
new file mode 100644
index 0000000..717cbddec
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dds_log_history_size_gigantic_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+Future testMain() async {
+  // Log a total of 30 messages
+  for (int i = 1; i <= maxLogHistorySize + 10; ++i) {
+    log('All work and no play makes Ben a dull boy ($i)');
+  }
+  debugger();
+}
+
+const maxLogHistorySize = 100000;
+
+Future setLogHistorySize(Isolate isolate, int size) async {
+  return await isolate.invokeRpcNoUpgrade('setLogHistorySize', {
+    'size': size,
+  });
+}
+
+Future<int> getLogHistorySize(Isolate isolate) async {
+  final result = await isolate.invokeRpcNoUpgrade('getLogHistorySize', {});
+  expect(result['type'], 'Size');
+  return result['size'];
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    final initialSize = await getLogHistorySize(isolate);
+    try {
+      await setLogHistorySize(isolate, maxLogHistorySize + 1);
+    } on ServerRpcException catch (e) {
+      expect(e.message, "'size' must be less than $maxLogHistorySize");
+    }
+    expect(await getLogHistorySize(isolate), initialSize);
+  },
+  (Isolate isolate) async {
+    final result = await setLogHistorySize(isolate, maxLogHistorySize);
+    expect(result['type'], 'Success');
+    expect(await getLogHistorySize(isolate), maxLogHistorySize);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    print("Starting step 6");
+    final completer = Completer<void>();
+
+    await Future.delayed(const Duration(seconds: 1));
+
+    int i = 11;
+    await subscribeToStream(isolate.vm, 'Logging', (event) async {
+      expect(
+        event.logRecord['message'].valueAsString,
+        'All work and no play makes Ben a dull boy ($i)',
+      );
+      i++;
+
+      if (i == maxLogHistorySize + 10) {
+        await cancelStreamSubscription('Logging');
+        completer.complete();
+      }
+    });
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      enableService: false, // DDS specific feature
+      testeeConcurrent: testMain,
+      pause_on_start: true,
+      pause_on_exit: true,
+    );
diff --git a/runtime/observatory_2/tests/service_2/dds_log_history_size_simple_test.dart b/runtime/observatory_2/tests/service_2/dds_log_history_size_simple_test.dart
new file mode 100644
index 0000000..6287ffb
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dds_log_history_size_simple_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'client_resume_approvals_common.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+Future testMain() async {
+  // Log a total of 9 messages
+  for (int i = 1; i <= 9; ++i) {
+    log('log$i');
+  }
+  debugger();
+  log('log10');
+}
+
+Future setLogHistorySize(Isolate isolate, int size) async {
+  return await isolate.invokeRpcNoUpgrade('setLogHistorySize', {
+    'size': size,
+  });
+}
+
+Future<int> getLogHistorySize(Isolate isolate) async {
+  final result = await isolate.invokeRpcNoUpgrade('getLogHistorySize', {});
+  expect(result['type'], 'Size');
+  return result['size'];
+}
+
+var tests = <IsolateTest>[
+  isPausedAtStart,
+  resumeIsolate,
+  (Isolate isolate) async {
+    // Check that resizing does the right thing.
+    final result = await setLogHistorySize(isolate, 10);
+    expect(result['type'], 'Success');
+    expect(await getLogHistorySize(isolate), 10);
+
+    final completer = Completer<void>();
+
+    int i = 1;
+    await subscribeToStream(isolate.vm, 'Logging', (event) async {
+      expect(event.logRecord['message'].valueAsString, 'log$i');
+      i++;
+
+      if (i == 10) {
+        await cancelStreamSubscription('Logging');
+        completer.complete();
+      } else if (i > 10) {
+        fail('Too many log messages');
+      }
+    });
+    await completer.future;
+  },
+  (Isolate isolate) async {
+    // Resize to be smaller
+    final result = await setLogHistorySize(isolate, 5);
+    expect(result['type'], 'Success');
+    expect(await getLogHistorySize(isolate), 5);
+  },
+  resumeIsolate,
+  (Isolate isolate) async {
+    final completer = Completer<void>();
+
+    // Create a new client as we want to get log messages from the entire
+    // history buffer.
+    final client = await createClient(isolate.vm);
+
+    int i = 6;
+    await subscribeToStream(client, 'Logging', (event) async {
+      expect(event.logRecord['message'].valueAsString, 'log$i');
+      i++;
+
+      if (i == 11) {
+        await cancelStreamSubscription('Logging');
+        completer.complete();
+      } else if (i > 11) {
+        fail('Too many log messages');
+      }
+    });
+    await completer.future;
+    await client.disconnect();
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      enableService: false, // DDS specific feature
+      testeeConcurrent: testMain,
+      pause_on_start: true,
+      pause_on_exit: true,
+    );
diff --git a/runtime/observatory_2/tests/service_2/dds_log_history_size_test.dart b/runtime/observatory_2/tests/service_2/dds_log_history_size_test.dart
new file mode 100644
index 0000000..ce1a51e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dds_log_history_size_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+Future testMain() async {
+  // Initial logging history should be 0, so these messages won't be buffered.
+  log('log1');
+  log('log2');
+
+  // Setting the log history length does not apply retroactively.
+  debugger();
+
+  // Log a total of 30 messages
+  for (int i = 3; i <= 30; ++i) {
+    log('log$i');
+  }
+}
+
+Future setLogHistorySize(Isolate isolate, int size) async {
+  return await isolate.invokeRpcNoUpgrade('setLogHistorySize', {
+    'size': size,
+  });
+}
+
+Future<int> getLogHistorySize(Isolate isolate) async {
+  final result = await isolate.invokeRpcNoUpgrade('getLogHistorySize', {});
+  expect(result['type'], 'Size');
+  return result['size'];
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    final result = await setLogHistorySize(isolate, 0);
+    expect(result['type'], 'Success');
+    expect(await getLogHistorySize(isolate), 0);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    final result = await setLogHistorySize(isolate, 20);
+    expect(await getLogHistorySize(isolate), 20);
+    expect(result['type'], 'Success');
+  },
+  resumeIsolate,
+  (Isolate isolate) async {
+    final completer = Completer<void>();
+
+    await Future.delayed(const Duration(seconds: 1));
+
+    // With the log history set to 20, the first log message should be 'log11'
+    int i = 11;
+    await subscribeToStream(isolate.vm, 'Logging', (event) async {
+      expect(event.logRecord['message'].valueAsString, 'log$i');
+      i++;
+
+      if (i == 30) {
+        await cancelStreamSubscription('Logging');
+        completer.complete();
+      }
+    });
+    await completer.future;
+  },
+  (Isolate isolate) async {
+    try {
+      // Try to set an invalid history size
+      await setLogHistorySize(isolate, -1);
+      fail('Successfully set invalid size');
+    } on ServerRpcException catch (e) {
+      expect(e.message, "'size' must be greater or equal to zero");
+    }
+    expect(await getLogHistorySize(isolate), 20);
+  }
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      enableService: false, // DDS specific feature
+      testeeConcurrent: testMain,
+      pause_on_start: true,
+      pause_on_exit: true,
+    );
diff --git a/runtime/observatory_2/tests/service_2/debugger_inspect_test.dart b/runtime/observatory_2/tests/service_2/debugger_inspect_test.dart
new file mode 100644
index 0000000..26213fa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/debugger_inspect_test.dart
@@ -0,0 +1,39 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+class Point {
+  int x, y;
+  Point(this.x, this.y);
+}
+
+void testeeDo() {
+  inspect(new Point(3, 4));
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kInspect) {
+        expect(event.inspectee.clazz.name, equals('Point'));
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    // Start listening for events first.
+    await isolate.rootLibrary.evaluate('testeeDo()');
+    return completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/debugger_location_second_test.dart b/runtime/observatory_2/tests/service_2/debugger_location_second_test.dart
new file mode 100644
index 0000000..4f27730
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/debugger_location_second_test.dart
@@ -0,0 +1,208 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/debugger.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+const int LINE_A = 21;
+const int LINE_B = 110;
+const int LINE_C = 11;
+
+void testFunction() {
+  int i = 0;
+  while (i == 0) {
+    debugger();
+    print('loop'); // Line A.
+    print('loop');
+  }
+}
+
+class TestDebugger extends Debugger {
+  TestDebugger(this.isolate, this.stack);
+
+  VM get vm => isolate.vm;
+  Isolate isolate;
+  ServiceMap stack;
+  int currentFrame = 0;
+}
+
+void debugger_location_dummy_function() {}
+
+class DebuggerLocationTestFoo {
+  DebuggerLocationTestFoo(this.field);
+  DebuggerLocationTestFoo.named();
+
+  void method() {}
+  void madness() {}
+
+  int field;
+}
+
+class DebuggerLocationTestBar {}
+
+Future<Debugger> initDebugger(Isolate isolate) {
+  return isolate.getStack().then((stack) {
+    return new TestDebugger(isolate, stack);
+  });
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Load the isolate's libraries
+  (Isolate isolate) async {
+    for (var lib in isolate.libraries) {
+      await lib.load();
+    }
+  },
+
+// Parse method
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(
+        debugger, 'DebuggerLocationTestFoo.method');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('DebuggerLocationTestFoo.method'));
+  },
+
+// Parse method
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(
+        debugger, 'DebuggerLocationTestFoo.field=');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('DebuggerLocationTestFoo.field='));
+  },
+
+// Parse bad method
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(
+        debugger, 'DebuggerLocationTestFoo.missing');
+    expect(loc.valid, isFalse);
+    expect(
+        loc.toString(),
+        equals('invalid source location '
+            '(Function \'DebuggerLocationTestFoo.missing\' not found)'));
+  },
+
+// Complete function + script
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions = await DebuggerLocation.complete(debugger, 'debugger_loc');
+    expect(
+        completions.toString(),
+        equals('[debugger_location_dummy_function,'
+            ' debugger_location.dart:,'
+            ' debugger_location_second_test.dart:]'));
+  },
+
+// Complete class
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions =
+        await DebuggerLocation.complete(debugger, 'DebuggerLocationTe');
+    expect(
+        completions.toString(),
+        equals('[DebuggerLocationTestBar,'
+            ' DebuggerLocationTestFoo]'));
+  },
+
+// No completions: unqualified name
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions =
+        await DebuggerLocation.complete(debugger, 'debugger_locXYZZY');
+    expect(completions.toString(), equals('[]'));
+  },
+
+// Complete method
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions =
+        await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.m');
+    expect(
+        completions.toString(),
+        equals('[DebuggerLocationTestFoo.madness,'
+            ' DebuggerLocationTestFoo.method]'));
+  },
+
+// No completions: qualified name
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions =
+        await DebuggerLocation.complete(debugger, 'DebuggerLocationTestFoo.q');
+    expect(completions.toString(), equals('[]'));
+  },
+
+// Complete script
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions = await DebuggerLocation.complete(
+        debugger, 'debugger_location_second_te');
+    expect(completions.toString(),
+        equals('[debugger_location_second_test.dart:]'));
+  },
+
+// Complete script:line
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions = await DebuggerLocation.complete(
+        debugger, 'debugger_location_second_test.dart:11');
+    expect(
+        completions.toString(),
+        equals('[debugger_location_second_test.dart:${LINE_B + 0} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 0}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 1} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 1}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 2} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 2}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 3} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 3}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 4} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 4}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 5} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 5}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 8} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 8}:,'
+            ' debugger_location_second_test.dart:${LINE_B + 9} ,'
+            ' debugger_location_second_test.dart:${LINE_B + 9}:]'));
+  },
+
+// Complete script:line:col
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions = await DebuggerLocation.complete(
+        debugger, 'debugger_location_second_test.dart:$LINE_C:2');
+    expect(
+        completions.toString(),
+        equals('[debugger_location_second_test.dart:$LINE_C:2 ,'
+            ' debugger_location_second_test.dart:$LINE_C:20 ,'
+            ' debugger_location_second_test.dart:$LINE_C:21 ,'
+            ' debugger_location_second_test.dart:$LINE_C:22 ,'
+            ' debugger_location_second_test.dart:$LINE_C:23 ,'
+            ' debugger_location_second_test.dart:$LINE_C:24 ]'));
+  },
+
+// Complete without the script name.
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var completions = await DebuggerLocation.complete(debugger, '$LINE_C:2');
+    expect(
+        completions.toString(),
+        equals('[debugger_location_second_test.dart:$LINE_C:2 ,'
+            ' debugger_location_second_test.dart:$LINE_C:20 ,'
+            ' debugger_location_second_test.dart:$LINE_C:21 ,'
+            ' debugger_location_second_test.dart:$LINE_C:22 ,'
+            ' debugger_location_second_test.dart:$LINE_C:23 ,'
+            ' debugger_location_second_test.dart:$LINE_C:24 ]'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/debugger_location_test.dart b/runtime/observatory_2/tests/service_2/debugger_location_test.dart
new file mode 100644
index 0000000..4ecadb2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/debugger_location_test.dart
@@ -0,0 +1,154 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/debugger.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+
+const int LINE_A = 21;
+const int LINE_B = 111;
+const int LINE_C = 11;
+
+void testFunction() {
+  int i = 0;
+  while (i == 0) {
+    debugger();
+    print('loop'); // Line A.
+    print('loop');
+  }
+}
+
+class TestDebugger extends Debugger {
+  TestDebugger(this.isolate, this.stack);
+
+  VM get vm => isolate.vm;
+  Isolate isolate;
+  ServiceMap stack;
+  int currentFrame = 0;
+}
+
+void debugger_location_dummy_function() {}
+
+class DebuggerLocationTestFoo {
+  DebuggerLocationTestFoo(this.field);
+  DebuggerLocationTestFoo.named();
+
+  void method() {}
+  void madness() {}
+
+  int field;
+}
+
+class DebuggerLocationTestBar {}
+
+Future<Debugger> initDebugger(Isolate isolate) {
+  return isolate.getStack().then((stack) {
+    return new TestDebugger(isolate, stack);
+  });
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Parse '' => current position
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, '');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('debugger_location_test.dart:$LINE_A:5'));
+  },
+
+// Parse line
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, '18');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('debugger_location_test.dart:18'));
+  },
+
+// Parse line + col
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, '16:11');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('debugger_location_test.dart:16:11'));
+  },
+
+// Parse script + line
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(
+        debugger, 'debugger_location_test.dart:16');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('debugger_location_test.dart:16'));
+  },
+
+// Parse script + line + col
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(
+        debugger, 'debugger_location_test.dart:16:11');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('debugger_location_test.dart:16:11'));
+  },
+
+// Parse bad script
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, 'bad.dart:15');
+    expect(loc.valid, isFalse);
+    expect(loc.toString(),
+        equals('invalid source location (Script \'bad.dart\' not found)'));
+  },
+
+// Parse function
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, 'testFunction');
+    expect(loc.valid, isTrue);
+    expect(loc.toString(), equals('testFunction'));
+  },
+
+// Parse bad function
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, 'doesNotReallyExist');
+    expect(loc.valid, isFalse);
+    expect(
+        loc.toString(),
+        equals(
+            'invalid source location (Function \'doesNotReallyExist\' not found)'));
+  },
+
+// Parse constructor
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc = await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo');
+    expect(loc.valid, isTrue);
+    // TODO(turnidge): Printing a constructor currently adds
+    // another class qualifier at the front.  Do we want to change
+    // this to be more consistent?
+    expect(loc.toString(),
+        equals('DebuggerLocationTestFoo.DebuggerLocationTestFoo'));
+  },
+
+// Parse named constructor
+  (Isolate isolate) async {
+    var debugger = await initDebugger(isolate);
+    var loc =
+        await DebuggerLocation.parse(debugger, 'DebuggerLocationTestFoo.named');
+    expect(loc.valid, isTrue);
+    // TODO(turnidge): Printing a constructor currently adds
+    // another class qualifier at the front.  Do we want to change
+    // this to be more consistent?
+    expect(loc.toString(),
+        equals('DebuggerLocationTestFoo.DebuggerLocationTestFoo.named'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/debugging_inlined_finally_test.dart b/runtime/observatory_2/tests/service_2/debugging_inlined_finally_test.dart
new file mode 100644
index 0000000..149f610
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/debugging_inlined_finally_test.dart
@@ -0,0 +1,133 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 23;
+const int LINE_B = 26;
+const int LINE_C = 29;
+
+testFunction() {
+  debugger();
+  var a;
+  try {
+    var b;
+    try {
+      for (int i = 0; i < 10; i++) {
+        var x = () => i + a + b;
+        return x; // LINE_A
+      }
+    } finally {
+      b = 10; // LINE_B
+    }
+  } finally {
+    a = 1; // LINE_C
+  }
+}
+
+testMain() {
+  var f = testFunction();
+  expect(f(), equals(11));
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Add breakpoint
+  (Isolate isolate) async {
+    await isolate.rootLibrary.load();
+
+    var script = isolate.rootLibrary.scripts[0];
+    await script.load();
+
+    // Add 3 breakpoints.
+    {
+      var result = await isolate.addBreakpoint(script, LINE_A);
+      expect(result is Breakpoint, isTrue);
+      Breakpoint bpt = result;
+      expect(bpt.type, equals('Breakpoint'));
+      expect(bpt.location.script.id, equals(script.id));
+      expect(bpt.location.script.tokenToLine(bpt.location.tokenPos),
+          equals(LINE_A));
+      expect(isolate.breakpoints.length, equals(1));
+    }
+
+    {
+      var result = await isolate.addBreakpoint(script, LINE_B);
+      expect(result is Breakpoint, isTrue);
+      Breakpoint bpt = result;
+      expect(bpt.type, equals('Breakpoint'));
+      expect(bpt.location.script.id, equals(script.id));
+      expect(bpt.location.script.tokenToLine(bpt.location.tokenPos),
+          equals(LINE_B));
+      expect(isolate.breakpoints.length, equals(2));
+    }
+
+    {
+      var result = await isolate.addBreakpoint(script, LINE_C);
+      expect(result is Breakpoint, isTrue);
+      Breakpoint bpt = result;
+      expect(bpt.type, equals('Breakpoint'));
+      expect(bpt.location.script.id, equals(script.id));
+      expect(bpt.location.script.tokenToLine(bpt.location.tokenPos),
+          equals(LINE_C));
+      expect(isolate.breakpoints.length, equals(3));
+    }
+
+    // Wait for breakpoint events.
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line LINE_A.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.tokenToLine(stack['frames'][0].location.tokenPos),
+        equals(LINE_A));
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line LINE_B.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.tokenToLine(stack['frames'][0].location.tokenPos),
+        equals(LINE_B));
+  },
+
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+
+// We are at the breakpoint on line LINE_C.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.tokenToLine(stack['frames'][0].location.tokenPos),
+        equals(LINE_C));
+  },
+
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/debugging_test.dart b/runtime/observatory_2/tests/service_2/debugging_test.dart
new file mode 100644
index 0000000..15daf6b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/debugging_test.dart
@@ -0,0 +1,209 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int counter = 0;
+
+void periodicTask(_) {
+  counter++;
+  counter++; // Line 15.  We set our breakpoint here.
+  counter++;
+  if (counter % 300 == 0) {
+    print('counter = $counter');
+  }
+}
+
+void startTimer() {
+  new Timer.periodic(const Duration(milliseconds: 10), periodicTask);
+}
+
+var tests = <IsolateTest>[
+// Pause
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseInterrupted) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    isolate.pause();
+    await completer.future;
+  },
+
+// Resume
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    await completer.future;
+  },
+
+// Add breakpoint
+  (Isolate isolate) async {
+    await isolate.rootLibrary.load();
+
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print('Breakpoint reached');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    var script = isolate.rootLibrary.scripts[0];
+    await script.load();
+
+    // Add the breakpoint.
+    var result = await isolate.addBreakpoint(script, 15);
+    expect(result is Breakpoint, isTrue);
+    Breakpoint bpt = result;
+    expect(bpt.type, equals('Breakpoint'));
+    expect(bpt.location.script.id, equals(script.id));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(15));
+    expect(isolate.breakpoints.length, equals(1));
+
+    await completer.future; // Wait for breakpoint events.
+  },
+
+// We are at the breakpoint on line 15.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.name, endsWith('debugging_test.dart'));
+    expect(
+        script.tokenToLine(stack['frames'][0].location.tokenPos), equals(15));
+  },
+
+// Stepping
+  (Isolate isolate) async {
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print('Breakpoint reached');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    await isolate.stepOver();
+    await completer.future; // Wait for breakpoint events.
+  },
+
+// We are now at line 16.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.name, endsWith('debugging_test.dart'));
+    expect(
+        script.tokenToLine(stack['frames'][0].location.tokenPos), equals(16));
+  },
+
+// Remove breakpoint
+  (Isolate isolate) async {
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kBreakpointRemoved) {
+        print('Breakpoint removed');
+        expect(isolate.breakpoints.length, equals(0));
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    expect(isolate.breakpoints.length, equals(1));
+    var bpt = isolate.breakpoints.values.first;
+    await isolate.removeBreakpoint(bpt);
+    await completer.future;
+  },
+
+// Resume
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    await completer.future;
+  },
+
+// Add breakpoint at function entry
+  (Isolate isolate) async {
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print('Breakpoint reached');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    // Find a specific function.
+    ServiceFunction function = isolate.rootLibrary.functions
+        .firstWhere((f) => f.name == 'periodicTask');
+    expect(function, isNotNull);
+
+    // Add the breakpoint at function entry
+    var result = await isolate.addBreakpointAtEntry(function);
+    expect(result is Breakpoint, isTrue);
+    Breakpoint bpt = result;
+    expect(bpt.type, equals('Breakpoint'));
+    expect(bpt.location.script.name, equals('debugging_test.dart'));
+    expect(bpt.location.script.tokenToLine(bpt.location.tokenPos), equals(12));
+    expect(isolate.breakpoints.length, equals(1));
+
+    await completer.future; // Wait for breakpoint events.
+  },
+
+// We are now at line 13.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    expect(script.name, endsWith('debugging_test.dart'));
+    expect(
+        script.tokenToLine(stack['frames'][0].location.tokenPos), equals(12));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: startTimer);
diff --git a/runtime/observatory_2/tests/service_2/deferred_library.dart b/runtime/observatory_2/tests/service_2/deferred_library.dart
new file mode 100644
index 0000000..9a40be6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/deferred_library.dart
@@ -0,0 +1,18 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library deferred_library;
+
+int value = 0;
+
+int decValue(int amount) {
+  value -= amount;
+  return amount;
+}
+
+void deferredTest() {
+  decValue(decValue(1)); // line 15
+
+  decValue(decValue(1)); // line 17
+}
diff --git a/runtime/observatory_2/tests/service_2/dev_fs_http_put_test.dart b/runtime/observatory_2/tests/service_2/dev_fs_http_put_test.dart
new file mode 100644
index 0000000..e0f48ec
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dev_fs_http_put_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+  var completer = new Completer<String>();
+  var contents = new StringBuffer();
+  response.cast<List<int>>().transform(utf8.decoder).listen((String data) {
+    contents.write(data);
+  }, onDone: () => completer.complete(contents.toString()));
+  return completer.future;
+}
+
+var tests = <VMTest>[
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    var filePath = '/foo/bar.dat';
+    var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+    var fileContentsBase64 = base64Encode(fileContents);
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {'fsName': fsId});
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], isA<String>());
+
+    // Write the file by issuing an HTTP PUT.
+    HttpClient client = new HttpClient();
+    HttpClientRequest request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path', filePath);
+    request.add(gzip.encode([9]));
+    HttpClientResponse response = await request.close();
+    String responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Trigger an error by issuing an HTTP PUT.
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    // omit the 'dev_fs_path' parameter.
+    request.write(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    Map error = result['error']['data'];
+    expect(error, isNotNull);
+    expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+    // Write the file again but this time with the true file contents.
+    client = new HttpClient();
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path', filePath);
+    request.add(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Close the HTTP client.
+    client.close();
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(1));
+    expect(result['files'][0]['name'], equals(filePath));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/dev_fs_http_put_weird_char_test.dart b/runtime/observatory_2/tests/service_2/dev_fs_http_put_weird_char_test.dart
new file mode 100644
index 0000000..ea9ed44
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dev_fs_http_put_weird_char_test.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+  var completer = new Completer<String>();
+  var contents = new StringBuffer();
+  response.cast<List<int>>().transform(utf8.decoder).listen((String data) {
+    contents.write(data);
+  }, onDone: () => completer.complete(contents.toString()));
+  return completer.future;
+}
+
+var tests = <VMTest>[
+  // Write a file with the \r character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    var filePath = '/foo/b\rar.dart';
+    var filePathBase64 = base64Encode(utf8.encode(filePath));
+    var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+    var fileContentsBase64 = base64Encode(fileContents);
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {'fsName': fsId});
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], isA<String>());
+
+    // Write the file by issuing an HTTP PUT.
+    HttpClient client = new HttpClient();
+    HttpClientRequest request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path_b64', filePathBase64);
+    request.add(gzip.encode([9]));
+    HttpClientResponse response = await request.close();
+    String responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Trigger an error by issuing an HTTP PUT.
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    // omit the 'dev_fs_path' parameter.
+    request.write(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    Map error = result['error']['data'];
+    expect(error, isNotNull);
+    expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+    // Write the file again but this time with the true file contents.
+    client = new HttpClient();
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_path_b64', filePathBase64);
+    request.add(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Close the HTTP client.
+    client.close();
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(1));
+    expect(result['files'][0]['name'], equals(filePath));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/dev_fs_test.dart b/runtime/observatory_2/tests/service_2/dev_fs_test.dart
new file mode 100644
index 0000000..1cab8e5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dev_fs_test.dart
@@ -0,0 +1,151 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FileSystemList'));
+    expect(result['fsNames'].toString(), equals("[]"));
+
+    var params = {'fsName': 'alpha'};
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', params);
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals('alpha'));
+    expect(result['uri'], isA<String>());
+
+    result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FileSystemList'));
+    expect(result['fsNames'].toString(), equals('[alpha]'));
+
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('_createDevFS', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileSystemAlreadyExists));
+      expect(e.message, "_createDevFS: file system 'alpha' already exists");
+    }
+    expect(caughtException, isTrue);
+
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', params);
+    expect(result['type'], equals('Success'));
+
+    result = await vm.invokeRpcNoUpgrade('_listDevFS', {});
+    expect(result['type'], equals('FileSystemList'));
+    expect(result['fsNames'].toString(), equals("[]"));
+
+    caughtException = false;
+    try {
+      await vm.invokeRpcNoUpgrade('_deleteDevFS', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileSystemDoesNotExist));
+      expect(e.message, "_deleteDevFS: file system 'alpha' does not exist");
+    }
+    expect(caughtException, isTrue);
+  },
+  (VM vm) async {
+    var fsId = 'banana';
+    var filePath = '/foo/bar.dat';
+    var fileContents = base64Encode(utf8.encode('fileContents'));
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {'fsName': fsId});
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], isA<String>());
+
+    bool caughtException = false;
+    try {
+      await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': filePath,
+      });
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kFileDoesNotExist));
+      expect(e.message, startsWith("_readDevFSFile: FileSystemException: "));
+    }
+    expect(caughtException, isTrue);
+
+    // Write a file.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile',
+        {'fsName': fsId, 'path': filePath, 'fileContents': fileContents});
+    expect(result['type'], equals('Success'));
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // The leading '/' is optional.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': filePath.substring(1),
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // Read a file outside of the fs.
+    caughtException = false;
+    try {
+      await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+        'fsName': fsId,
+        'path': '../foo',
+      });
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "_readDevFSFile: invalid 'path' parameter: ../foo");
+    }
+    expect(caughtException, isTrue);
+
+    // Write a set of files.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFiles', {
+      'fsName': fsId,
+      'files': [
+        ['/a', base64Encode(utf8.encode('a_contents'))],
+        ['/b', base64Encode(utf8.encode('b_contents'))]
+      ]
+    });
+    expect(result['type'], equals('Success'));
+
+    // Read one of the files back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': '/b',
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'],
+        equals(base64Encode(utf8.encode('b_contents'))));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(3));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/dev_fs_uri_test.dart b/runtime/observatory_2/tests/service_2/dev_fs_uri_test.dart
new file mode 100644
index 0000000..27cc9a4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dev_fs_uri_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+Future<String> readResponse(HttpClientResponse response) {
+  var completer = new Completer<String>();
+  var contents = new StringBuffer();
+  response.cast<List<int>>().transform(utf8.decoder).listen((String data) {
+    contents.write(data);
+  }, onDone: () => completer.complete(contents.toString()));
+  return completer.future;
+}
+
+var tests = <VMTest>[
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    // NOTE: When using the URI encoding scheme, paths cannot be absolute.
+    var filePath = 'foo/bar.dat';
+    var fileUri = Uri.parse(filePath);
+    var fileUriBase64 = base64Encode(utf8.encode(fileUri.toString()));
+    var fileContents = [0, 1, 2, 3, 4, 5, 6, 255];
+    var fileContentsBase64 = base64Encode(fileContents);
+
+    var filePath2 = 'baz/boo.dat';
+    var fileUri2 = Uri.parse(filePath2);
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {'fsName': fsId});
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], isA<String>());
+
+    // Write the file by issuing an HTTP PUT.
+    HttpClient client = new HttpClient();
+    HttpClientRequest request =
+        await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_uri_b64', fileUriBase64);
+    request.add(gzip.encode([9]));
+    HttpClientResponse response = await request.close();
+    String responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    print(result);
+    expect(result['result']['type'], equals('Success'));
+
+    // Trigger an error by issuing an HTTP PUT.
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    // omit the 'dev_fs_path' parameter.
+    request.write(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    Map error = result['error']['data'];
+    expect(error, isNotNull);
+    expect(error['details'].contains("expects the 'path' parameter"), isTrue);
+
+    // Write the file again but this time with the true file contents.
+    client = new HttpClient();
+    request = await client.putUrl(Uri.parse(serviceHttpAddress));
+    request.headers.add('dev_fs_name', fsId);
+    request.headers.add('dev_fs_uri_b64', fileUriBase64);
+    request.add(gzip.encode(fileContents));
+    response = await request.close();
+    responseBody = await readResponse(response);
+    result = jsonDecode(responseBody);
+    expect(result['result']['type'], equals('Success'));
+
+    // Close the HTTP client.
+    client.close();
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'uri': fileUri.toString(),
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // Write a second file via URI.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile', {
+      'fsName': fsId,
+      'uri': fileUri2.toString(),
+      'fileContents': fileContentsBase64
+    });
+
+    // Read the second file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'uri': fileUri2.toString(),
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContentsBase64));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/dev_fs_weird_char_test.dart b/runtime/observatory_2/tests/service_2/dev_fs_weird_char_test.dart
new file mode 100644
index 0000000..999f84a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dev_fs_weird_char_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  // Write a file with the ? character in the filename.
+  (VM vm) async {
+    var fsId = 'test';
+    var filePath = '/foo/bar?dat';
+    var fileContents = base64Encode(utf8.encode('fileContents'));
+
+    var result;
+    // Create DevFS.
+    result = await vm.invokeRpcNoUpgrade('_createDevFS', {'fsName': fsId});
+    expect(result['type'], equals('FileSystem'));
+    expect(result['name'], equals(fsId));
+    expect(result['uri'], isA<String>());
+
+    // Write the file.
+    result = await vm.invokeRpcNoUpgrade('_writeDevFSFile',
+        {'fsName': fsId, 'path': filePath, 'fileContents': fileContents});
+    expect(result['type'], equals('Success'));
+
+    // Read the file back.
+    result = await vm.invokeRpcNoUpgrade('_readDevFSFile', {
+      'fsName': fsId,
+      'path': filePath,
+    });
+    expect(result['type'], equals('FSFile'));
+    expect(result['fileContents'], equals(fileContents));
+
+    // List all the files in the file system.
+    result = await vm.invokeRpcNoUpgrade('_listDevFSFiles', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('FSFileList'));
+    expect(result['files'].length, equals(1));
+    expect(result['files'][0]['name'], equals('/foo/bar?dat'));
+
+    // Delete DevFS.
+    result = await vm.invokeRpcNoUpgrade('_deleteDevFS', {
+      'fsName': fsId,
+    });
+    expect(result['type'], equals('Success'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/developer_extension_test.dart b/runtime/observatory_2/tests/service_2/developer_extension_test.dart
new file mode 100644
index 0000000..61cab8f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/developer_extension_test.dart
@@ -0,0 +1,117 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+Future<ServiceExtensionResponse> Handler(String method, Map paremeters) {
+  print('Invoked extension: $method');
+  switch (method) {
+    case 'ext..delay':
+      Completer c = new Completer<ServiceExtensionResponse>();
+      new Timer(new Duration(seconds: 1), () {
+        c.complete(new ServiceExtensionResponse.result(jsonEncode({
+          'type': '_delayedType',
+          'method': method,
+          'parameters': paremeters,
+        })));
+      });
+      return c.future;
+    case 'ext..error':
+      return new Future<ServiceExtensionResponse>.value(
+          new ServiceExtensionResponse.error(
+              ServiceExtensionResponse.extensionErrorMin, 'My error detail.'));
+    case 'ext..exception':
+      throw "I always throw!";
+    case 'ext..success':
+      return new Future<ServiceExtensionResponse>.value(
+          new ServiceExtensionResponse.result(jsonEncode({
+        'type': '_extensionType',
+        'method': method,
+        'parameters': paremeters,
+      })));
+  }
+}
+
+void test() {
+  registerExtension('ext..delay', Handler);
+  debugger();
+  postEvent('ALPHA', {'cat': 'dog'});
+  debugger();
+  registerExtension('ext..error', Handler);
+  registerExtension('ext..exception', Handler);
+  registerExtension('ext..success', Handler);
+  bool exceptionThrown = false;
+  try {
+    registerExtension('ext..delay', Handler);
+  } catch (e) {
+    exceptionThrown = true;
+  }
+  // This check is running in the target process so we can't used package:test.
+  Expect.isTrue(exceptionThrown);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    await isolate.load();
+    // Note: extensions other than those is this test might already be
+    // registered by core libraries.
+    expect(isolate.extensionRPCs, contains('ext..delay'));
+    expect(isolate.extensionRPCs, isNot(contains('ext..error')));
+    expect(isolate.extensionRPCs, isNot(contains('ext..exception')));
+    expect(isolate.extensionRPCs, isNot(contains('ext..success')));
+  },
+  resumeIsolateAndAwaitEvent(Isolate.kExtensionStream, (ServiceEvent event) {
+    expect(event.kind, equals(ServiceEvent.kExtension));
+    expect(event.extensionKind, equals('ALPHA'));
+    expect(event.extensionData, isA<Map>());
+    expect(event.extensionData['cat'], equals('dog'));
+  }),
+  hasStoppedAtBreakpoint,
+  resumeIsolateAndAwaitEvent(VM.kIsolateStream, (ServiceEvent event) {
+    // Check that we received an event when '__error' was registered.
+    expect(event.kind, equals(ServiceEvent.kServiceExtensionAdded));
+    expect(event.extensionRPC, equals('ext..error'));
+  }),
+  // Initial.
+  (Isolate isolate) async {
+    var result;
+
+    result = await isolate.invokeRpcNoUpgrade('ext..delay', {});
+    expect(result['type'], equals('_delayedType'));
+    expect(result['method'], equals('ext..delay'));
+    expect(result['parameters']['isolateId'], isNotNull);
+
+    try {
+      await isolate.invokeRpcNoUpgrade('ext..error', {});
+    } on ServerRpcException catch (e, st) {
+      expect(e.code, equals(ServiceExtensionResponse.extensionErrorMin));
+      expect(e.message, equals('My error detail.'));
+    }
+
+    try {
+      await isolate.invokeRpcNoUpgrade('ext..exception', {});
+    } on ServerRpcException catch (e, st) {
+      expect(e.code, equals(ServiceExtensionResponse.extensionError));
+      expect(e.message.startsWith('I always throw!\n'), isTrue);
+    }
+
+    result =
+        await isolate.invokeRpcNoUpgrade('ext..success', {'apple': 'banana'});
+    expect(result['type'], equals('_extensionType'));
+    expect(result['method'], equals('ext..success'));
+    expect(result['parameters']['isolateId'], isNotNull);
+    expect(result['parameters']['apple'], equals('banana'));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: test);
diff --git a/runtime/observatory_2/tests/service_2/developer_server_control_test.dart b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
new file mode 100644
index 0000000..62889e4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/developer_server_control_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart' as S;
+import 'test_helper.dart';
+
+int majorVersion;
+int minorVersion;
+Uri serverUri;
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  // First grab the URL where the observatory is listening on and the
+  // service protocol version numbers. We expect the URL to be null as
+  // the server has not been started yet.
+  ServiceProtocolInfo info = await Service.getInfo();
+  majorVersion = info.majorVersion;
+  minorVersion = info.minorVersion;
+  serverUri = info.serverUri;
+  Expect.isNull(info.serverUri);
+  {
+    // Now, start the web server and store the URI which is expected to be
+    // non NULL in the top level variable.
+    ServiceProtocolInfo info =
+        await Service.controlWebServer(enable: true, silenceOutput: true);
+    Expect.equals(info.majorVersion, majorVersion);
+    Expect.equals(info.minorVersion, minorVersion);
+    Expect.isNotNull(info.serverUri);
+    serverUri = info.serverUri;
+  }
+  {
+    // Now try starting the web server again, this should just return the
+    // existing state without any change (port number does not change).
+    ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+    Expect.equals(info.majorVersion, majorVersion);
+    Expect.equals(info.minorVersion, minorVersion);
+    Expect.equals(info.serverUri, serverUri);
+  }
+  {
+    // Try turning off the web server, this should turn off the server and
+    // the Uri returned should be null.
+    ServiceProtocolInfo info = await Service.controlWebServer(enable: false);
+    Expect.equals(info.majorVersion, majorVersion);
+    Expect.equals(info.minorVersion, minorVersion);
+    Expect.isNull(info.serverUri);
+  }
+  {
+    // Try turning off the web server again, this should be a nop
+    // and the Uri returned should be null.
+    ServiceProtocolInfo info = await Service.controlWebServer(enable: false);
+    Expect.equals(info.majorVersion, majorVersion);
+    Expect.equals(info.minorVersion, minorVersion);
+    Expect.isNull(info.serverUri);
+  }
+  {
+    // Start the web server again for the test below.
+    ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+    majorVersion = info.majorVersion;
+    minorVersion = info.minorVersion;
+    serverUri = info.serverUri;
+    Expect.equals(info.majorVersion, majorVersion);
+    Expect.equals(info.minorVersion, minorVersion);
+    Expect.equals(info.serverUri, serverUri);
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    Expect.equals(true, true);
+  }
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeBefore: testeeBefore,
+    // the testee is responsible for starting the
+    // web server.
+    testeeControlsServer: true);
diff --git a/runtime/observatory_2/tests/service_2/developer_service_get_isolate_id_test.dart b/runtime/observatory_2/tests/service_2/developer_service_get_isolate_id_test.dart
new file mode 100644
index 0000000..eb65cdc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/developer_service_get_isolate_id_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer' as dev;
+import 'dart:isolate' as Core;
+
+import 'package:observatory_2/service_io.dart' as Service;
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+// testee state.
+String selfId;
+Core.Isolate childIsolate;
+String childId;
+
+void spawnEntry(int i) {
+  dev.debugger();
+}
+
+Future testeeMain() async {
+  dev.debugger();
+  // Spawn an isolate.
+  childIsolate = await Core.Isolate.spawn(spawnEntry, 0);
+  // Assign the id for this isolate and it's child to strings so they can
+  // be read by the tester.
+  selfId = dev.Service.getIsolateID(Core.Isolate.current);
+  childId = dev.Service.getIsolateID(childIsolate);
+  dev.debugger();
+}
+
+@pragma("vm:entry-point")
+getSelfId() => selfId;
+
+@pragma("vm:entry-point")
+getChildId() => childId;
+
+// tester state:
+Service.Isolate initialIsolate;
+Service.Isolate localChildIsolate;
+
+var tests = <VMTest>[
+  (Service.VM vm) async {
+    // Sanity check.
+    expect(vm.isolates.length, 1);
+    initialIsolate = vm.isolates[0];
+    await hasStoppedAtBreakpoint(initialIsolate);
+    // Resume.
+    await initialIsolate.resume();
+  },
+  (Service.VM vm) async {
+    // Initial isolate has paused at second debugger call.
+    await hasStoppedAtBreakpoint(initialIsolate);
+  },
+  (Service.VM vm) async {
+    // Reload the VM.
+    await vm.reload();
+
+    // Grab the child isolate.
+    localChildIsolate =
+        vm.isolates.firstWhere((Service.Isolate i) => i != initialIsolate);
+    expect(localChildIsolate, isNotNull);
+
+    // Reload the initial isolate.
+    await initialIsolate.reload();
+
+    // Grab the root library.
+    Service.Library rootLbirary = await initialIsolate.rootLibrary.load();
+
+    // Grab self id.
+    Service.Instance localSelfId =
+        await initialIsolate.invoke(rootLbirary, 'getSelfId');
+
+    // Check that the id reported from dart:developer matches the id reported
+    // from the service protocol.
+    expect(localSelfId.isString, true);
+    expect(initialIsolate.id, equals(localSelfId.valueAsString));
+
+    // Grab the child isolate's id.
+    Service.Instance localChildId =
+        await initialIsolate.invoke(rootLbirary, 'getChildId');
+
+    // Check that the id reported from dart:developer matches the id reported
+    // from the service protocol.
+    expect(localChildId.isString, true);
+    expect(localChildIsolate.id, equals(localChildId.valueAsString));
+  }
+];
+
+main(args) async => runVMTests(args, tests, testeeConcurrent: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/dominator_tree_vm_test.dart b/runtime/observatory_2/tests/service_2/dominator_tree_vm_test.dart
new file mode 100644
index 0000000..9cb5ad5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dominator_tree_vm_test.dart
@@ -0,0 +1,164 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+// small example from [Lenguaer & Tarjan 1979]
+class R {
+  // All fields are marked with @pragma("vm:entry-point")
+  // in order to make sure they are not removed by the tree shaker
+  // even though they are never read.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+  @pragma("vm:entry-point")
+  var z;
+}
+
+class A {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class B {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+  @pragma("vm:entry-point")
+  var z;
+}
+
+class C {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class D {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class E {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class F {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class G {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class H {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class I {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class J {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class K {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class L {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+var r;
+
+buildGraph() {
+  r = new R();
+  var a = new A();
+  var b = new B();
+  var c = new C();
+  var d = new D();
+  var e = new E();
+  var f = new F();
+  var g = new G();
+  var h = new H();
+  var i = new I();
+  var j = new J();
+  var k = new K();
+  var l = new L();
+
+  r.x = a;
+  r.y = b;
+  r.z = c;
+  a.x = d;
+  b.x = a;
+  b.y = d;
+  b.z = e;
+  c.x = f;
+  c.y = g;
+  d.x = l;
+  e.x = h;
+  f.x = i;
+  g.x = i;
+  g.y = j;
+  h.x = e;
+  h.y = k;
+  i.x = k;
+  j.x = i;
+  k.x = i;
+  k.y = r;
+  l.x = h;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    final graph = await isolate.fetchHeapSnapshot().done;
+
+    node(String className) {
+      return graph.objects.singleWhere((v) => v.klass.name == className);
+    }
+
+    expect(node('I').parent, equals(node('R')));
+    expect(node('K').parent, equals(node('R')));
+    expect(node('C').parent, equals(node('R')));
+    expect(node('H').parent, equals(node('R')));
+    expect(node('E').parent, equals(node('R')));
+    expect(node('A').parent, equals(node('R')));
+    expect(node('D').parent, equals(node('R')));
+    expect(node('B').parent, equals(node('R')));
+
+    expect(node('F').parent, equals(node('C')));
+    expect(node('G').parent, equals(node('C')));
+    expect(node('J').parent, equals(node('G')));
+    expect(node('L').parent, equals(node('D')));
+
+    expect(node('R'), isNotNull); // The field.
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: buildGraph);
diff --git a/runtime/observatory_2/tests/service_2/dominator_tree_vm_with_double_field_test.dart b/runtime/observatory_2/tests/service_2/dominator_tree_vm_with_double_field_test.dart
new file mode 100644
index 0000000..965d4f0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/dominator_tree_vm_with_double_field_test.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+double getDoubleWithHeapObjectTag() {
+  final bd = ByteData(8);
+  bd.setUint64(0, 0x8000000000000001, Endian.host);
+  final double v = bd.getFloat64(0, Endian.host);
+  return v;
+}
+
+// small example from [Lenguaer & Tarjan 1979]
+class R {
+  final double fld = getDoubleWithHeapObjectTag();
+  // Fields are marked with @pragma("vm:entry-point")
+  // in order to make sure they are not removed by the tree shaker
+  // even though they are never read.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+  @pragma("vm:entry-point")
+  var z;
+}
+
+class A {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class B {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+  @pragma("vm:entry-point")
+  var z;
+}
+
+class C {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class D {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class E {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class F {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class G {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class H {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class I {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class J {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+class K {
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+class L {
+  @pragma("vm:entry-point")
+  var x;
+}
+
+var r;
+
+buildGraph() {
+  r = new R();
+  var a = new A();
+  var b = new B();
+  var c = new C();
+  var d = new D();
+  var e = new E();
+  var f = new F();
+  var g = new G();
+  var h = new H();
+  var i = new I();
+  var j = new J();
+  var k = new K();
+  var l = new L();
+
+  r.x = a;
+  r.y = b;
+  r.z = c;
+  a.x = d;
+  b.x = a;
+  b.y = d;
+  b.z = e;
+  c.x = f;
+  c.y = g;
+  d.x = l;
+  e.x = h;
+  f.x = i;
+  g.x = i;
+  g.y = j;
+  h.x = e;
+  h.y = k;
+  i.x = k;
+  j.x = i;
+  k.x = i;
+  k.y = r;
+  l.x = h;
+
+  Expect.equals(r.fld, getDoubleWithHeapObjectTag());
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    final graph = await isolate.fetchHeapSnapshot().done;
+
+    node(String className) {
+      return graph.objects.singleWhere((v) => v.klass.name == className);
+    }
+
+    expect(node('I').parent, equals(node('R')));
+    expect(node('K').parent, equals(node('R')));
+    expect(node('C').parent, equals(node('R')));
+    expect(node('H').parent, equals(node('R')));
+    expect(node('E').parent, equals(node('R')));
+    expect(node('A').parent, equals(node('R')));
+    expect(node('D').parent, equals(node('R')));
+    expect(node('B').parent, equals(node('R')));
+
+    expect(node('F').parent, equals(node('C')));
+    expect(node('G').parent, equals(node('C')));
+    expect(node('J').parent, equals(node('G')));
+    expect(node('L').parent, equals(node('D')));
+
+    expect(node('R'), isNotNull); // The field.
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: buildGraph);
diff --git a/runtime/observatory_2/tests/service_2/echo_test.dart b/runtime/observatory_2/tests/service_2/echo_test.dart
new file mode 100644
index 0000000..bccb96e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/echo_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) =>
+      isolate.vm.invokeRpcNoUpgrade('_echo', {'text': 'hello'}).then((result) {
+        expect(result['type'], equals('_EchoResponse'));
+        expect(result['text'], equals('hello'));
+      }),
+  (Isolate isolate) =>
+      isolate.invokeRpcNoUpgrade('_echo', {'text': 'hello'}).then((result) {
+        expect(result['type'], equals('_EchoResponse'));
+        expect(result['text'], equals('hello'));
+      }),
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream('_Echo');
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      assert(event.kind == '_Echo');
+      expect(event.data.lengthInBytes, equals(3));
+      expect(event.data[0], equals(0));
+      expect(event.data[1], equals(128));
+      expect(event.data[2], equals(255));
+      subscription.cancel();
+      completer.complete();
+    });
+
+    await isolate.invokeRpc('_triggerEchoEvent', {'text': 'hello'});
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/enable_service_port_fallback_positive_test.dart b/runtime/observatory_2/tests/service_2/enable_service_port_fallback_positive_test.dart
new file mode 100644
index 0000000..e50fc0a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/enable_service_port_fallback_positive_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+// Tests that the --enable-service-port-fallback flag works correctly by trying to bind to
+// a port that is available.
+var tests = <VMTest>[
+  (VM vm) async {
+    // Correctly bound to provided port.
+    expect(Uri.parse(serviceHttpAddress).port == selectedPort, true);
+  }
+];
+
+int selectedPort = 0;
+
+main(args) async {
+  selectedPort = await _getUnusedPort();
+  await runVMTests(
+    args, tests,
+    enable_service_port_fallback: true,
+    // Choose a port number that should always be open.
+    port: selectedPort,
+    extraArgs: [],
+    // TODO(bkonyi): investigate failure.
+    enableDds: false,
+  );
+}
+
+Future<int> _getUnusedPort() async {
+  var socket = await ServerSocket.bind(InternetAddress.anyIPv4, 0);
+  var port = socket.port;
+  await socket.close();
+  return port;
+}
diff --git a/runtime/observatory_2/tests/service_2/enable_service_port_fallback_test.dart b/runtime/observatory_2/tests/service_2/enable_service_port_fallback_test.dart
new file mode 100644
index 0000000..0c89d5c
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/enable_service_port_fallback_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+// Tests that the --enable-service-port-fallback flag works correctly by trying to bind to
+// a port that is unsupported.
+var tests = <VMTest>[
+  (VM vm) async {
+    // Did not bind to provided port.
+    expect(Uri.parse(serviceHttpAddress).port != portNumber, true);
+    await socket.close();
+  }
+];
+
+ServerSocket socket;
+int portNumber = -1;
+
+main(args) async {
+  socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
+  portNumber = socket.port;
+  return runVMTests(args, tests,
+      enable_service_port_fallback: true, port: portNumber, extraArgs: []);
+}
diff --git a/runtime/observatory_2/tests/service_2/eval_internal_class_test.dart b/runtime/observatory_2/tests/service_2/eval_internal_class_test.dart
new file mode 100644
index 0000000..19a83e4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/eval_internal_class_test.dart
@@ -0,0 +1,53 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library root = await isolate.rootLibrary.load();
+
+    Class classLibrary = await root.clazz.load();
+    print(classLibrary);
+    {
+      bool caughtExceptions = false;
+      try {
+        dynamic result = await classLibrary.evaluate('3 + 4');
+        print(result);
+      } on ServerRpcException catch (e) {
+        expect(e.toString(), contains('can be evaluated only'));
+        caughtExceptions = true;
+      }
+      expect(caughtExceptions, isTrue);
+    }
+
+    Class classClass = await classLibrary.clazz.load();
+    print(classClass);
+    {
+      bool caughtExceptions = false;
+      try {
+        dynamic result = await classClass.evaluate('3 + 4');
+        print(result);
+      } on ServerRpcException catch (e) {
+        expect(e.toString(), contains('can be evaluated only'));
+        caughtExceptions = true;
+      }
+      expect(caughtExceptions, isTrue);
+    }
+
+    Instance someArray = await root.evaluate("new List(2)");
+    print(someArray);
+    expect(someArray is Instance, isTrue);
+    Class classArray = await someArray.clazz.load();
+    print(classArray);
+    dynamic result = await classArray.evaluate('3 + 4');
+    print(result);
+    expect(result is Instance, isTrue);
+    expect(result.valueAsString, equals('7'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/eval_regression_flutter20255_test.dart b/runtime/observatory_2/tests/service_2/eval_regression_flutter20255_test.dart
new file mode 100644
index 0000000..0ef9d6a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/eval_regression_flutter20255_test.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+class Base<T> {
+  String field;
+
+  Base(this.field);
+  String foo() => 'Base-$field';
+}
+
+class Sub<T> extends Base<T> {
+  String field;
+
+  Sub(this.field) : super(field);
+  String foo() {
+    debugger();
+    return 'Sub-$field';
+  }
+}
+
+class ISub<T> implements Base<T> {
+  String field;
+
+  ISub(this.field);
+  String foo() => 'ISub-$field';
+}
+
+class Box<T> {
+  T value;
+
+  @pragma('vm:never-inline')
+  void setValue(T value) {
+    this.value = value;
+  }
+}
+
+final objects = <Base>[
+  new Base<int>('b'),
+  new Sub<double>('a'),
+  new ISub<bool>('c')
+];
+
+String triggerTypeTestingStubGeneration() {
+  final Box<Object> box = new Box<Base>();
+  for (int i = 0; i < 1000000; ++i) {
+    box.setValue(objects.last);
+  }
+  return 'tts-generated';
+}
+
+void testFunction() {
+  // Triggers the debugger, which will evaluate an expression in the context of
+  // [Sub<double>], which will make a subclass of [Base<T>].
+  print(objects[1].foo());
+
+  triggerTypeTestingStubGeneration();
+
+  // Triggers the debugger, which will evaluate an expression in the context of
+  // [Sub<double>], which will make a subclass of [Base<T>].
+  print(objects[1].foo());
+}
+
+Future triggerEvaluation(Isolate isolate) async {
+  ServiceMap stack = await isolate.getStack();
+
+  // Make sure we are in the right place.
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'].length, greaterThanOrEqualTo(2));
+  expect(stack['frames'][0].function.name, equals('foo'));
+  expect(stack['frames'][0].function.dartOwner.name, equals('Sub'));
+
+  // Trigger an evaluation, which will create a new subclass of Base<T>.
+  final dynamic result =
+      await isolate.evalFrame(0, 'this.field + " world \$T"');
+  if (result is DartError) {
+    throw 'Got an error "$result", expected result of expression evaluation.';
+  }
+  expect(result.valueAsString, equals('a world double'));
+
+  // Trigger an optimization of a type testing stub (and usage of it).
+  final dynamic result2 =
+      await isolate.evalFrame(0, 'triggerTypeTestingStubGeneration()');
+  if (result2 is DartError) {
+    throw 'Got an error "$result", expected result of expression evaluation.';
+  }
+  expect(result2.valueAsString, equals('tts-generated'));
+}
+
+final testSteps = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  triggerEvaluation,
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  triggerEvaluation,
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, testSteps, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/eval_skip_breakpoint.dart b/runtime/observatory_2/tests/service_2/eval_skip_breakpoint.dart
new file mode 100644
index 0000000..3647689
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/eval_skip_breakpoint.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+  print('bar');
+}
+
+testMain() {
+  debugger();
+  bar();
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+// Add breakpoint
+  setBreakpointAtLine(LINE_B),
+// Evaluate 'bar()'
+  (Isolate isolate) async {
+    final lib = isolate.rootLibrary;
+    await lib.evaluate('bar()', disableBreakpoints: true);
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/eval_test.dart b/runtime/observatory_2/tests/service_2/eval_test.dart
new file mode 100644
index 0000000..15b21be
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/eval_test.dart
@@ -0,0 +1,106 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+int globalVar = 100;
+
+class MyClass {
+  static int staticVar = 1000;
+
+  static void method(int value) {
+    debugger();
+  }
+}
+
+class _MyClass {
+  void foo() {
+    debugger();
+  }
+}
+
+void testFunction() {
+  int i = 0;
+  while (true) {
+    if (++i % 100000000 == 0) {
+      MyClass.method(10000);
+      (new _MyClass()).foo();
+    }
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Evaluate against library, class, and instance.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(2));
+    expect(stack['frames'][0].function.name, equals('method'));
+    expect(stack['frames'][0].function.dartOwner.name, equals('MyClass'));
+
+    var lib = isolate.rootLibrary;
+    var cls = stack['frames'][0].function.dartOwner;
+    var instance = stack['frames'][0].variables[0]['value'];
+
+    dynamic result = await lib.evaluate('globalVar + 5');
+    print(result);
+    expect(result.valueAsString, equals('105'));
+
+    await expectError(() => lib.evaluate('globalVar + staticVar + 5'));
+
+    result = await cls.evaluate('globalVar + staticVar + 5');
+    print(result);
+    expect(result.valueAsString, equals('1105'));
+
+    await expectError(() => cls.evaluate('this + 5'));
+
+    result = await instance.evaluate('this + 5');
+    print(result);
+    expect(result.valueAsString, equals('10005'));
+
+    await expectError(() => instance.evaluate('this + frog'));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(2));
+    expect(stack['frames'][0].function.name, equals('foo'));
+    expect(stack['frames'][0].function.dartOwner.name, equals('_MyClass'));
+
+    var cls = stack['frames'][0].function.dartOwner;
+
+    dynamic result = await cls.evaluate("1+1");
+    print(result);
+    expect(result.valueAsString, equals("2"));
+  }
+];
+
+expectError(func) async {
+  bool gotException = false;
+  dynamic result;
+  try {
+    result = await func();
+    expect(result.type, equals('Error')); // dart1 semantics
+  } on ServerRpcException catch (e) {
+    expect(e.code, equals(ServerRpcException.kExpressionCompilationError));
+    gotException = true;
+  }
+  if (result?.type != 'Error') {
+    expect(gotException, true); // dart2 semantics
+  }
+}
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_other.dart b/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_other.dart
new file mode 100644
index 0000000..bf070a1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_other.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+
+var topLevel = "OtherLibrary";
+
+class Superclass {
+  var _instVar = 'Superclass';
+  var instVar = 'Superclass';
+  method() => 'Superclass';
+  static staticMethod() => 'Superclass';
+  suppress_warning() => _instVar;
+}
+
+class Klass extends Superclass {
+  var _instVar = 'Klass';
+  var instVar = 'Klass';
+  method() => 'Klass';
+  static staticMethod() => 'Klass';
+
+  test() {
+    var _local = 'Klass';
+    debugger();
+    // Suppress unused variable warning.
+    print(_local);
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_test.dart b/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_test.dart
new file mode 100644
index 0000000..6af1450
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_activation_in_method_class_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests that expressions evaluated in a frame see the same scope as the
+// frame's method.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+import 'evaluate_activation_in_method_class_other.dart';
+
+var topLevel = "TestLibrary";
+
+class Subclass extends Superclass with Klass {
+  var _instVar = 'Subclass';
+  var instVar = 'Subclass';
+  method() => 'Subclass';
+  static staticMethod() => 'Subclass';
+  suppress_warning() => _instVar;
+}
+
+testeeDo() {
+  var obj = new Subclass();
+  obj.test();
+}
+
+Future testerDo(Isolate isolate) async {
+  await hasStoppedAtBreakpoint(isolate);
+
+  // Make sure we are in the right place.
+  var stack = await isolate.getStack();
+  var topFrame = 0;
+  expect(stack.type, equals('Stack'));
+  expect(stack['frames'][topFrame].function.name, equals('test'));
+  expect(stack['frames'][topFrame].function.dartOwner.name,
+      equals('Superclass&Klass'));
+
+  Instance result;
+
+  result = await isolate.evalFrame(topFrame, '_local');
+  print(result);
+  expect(result.valueAsString, equals('Klass'));
+
+  result = await isolate.evalFrame(topFrame, '_instVar');
+  print(result);
+  expect(result.valueAsString, equals('Klass'));
+
+  result = await isolate.evalFrame(topFrame, 'instVar');
+  print(result);
+  expect(result.valueAsString, equals('Subclass'));
+
+  result = await isolate.evalFrame(topFrame, 'method()');
+  print(result);
+  expect(result.valueAsString, equals('Subclass'));
+
+  result = await isolate.evalFrame(topFrame, 'super._instVar');
+  print(result);
+  expect(result.valueAsString, equals('Superclass'));
+
+  result = await isolate.evalFrame(topFrame, 'super.instVar');
+  print(result);
+  expect(result.valueAsString, equals('Superclass'));
+
+  result = await isolate.evalFrame(topFrame, 'super.method()');
+  print(result);
+  expect(result.valueAsString, equals('Superclass'));
+
+  result = await isolate.evalFrame(topFrame, 'staticMethod()');
+  print(result);
+  expect(result.valueAsString, equals('Klass'));
+
+  // function.Owner verus function.Origin
+  // The mixin of Superclass is in _other.dart and the mixin
+  // application is in _test.dart.
+  result = await isolate.evalFrame(topFrame, 'topLevel');
+  print(result);
+  expect(result.valueAsString, equals('OtherLibrary'));
+}
+
+main(args) => runIsolateTests(args, [testerDo], testeeConcurrent: testeeDo);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_activation_test.dart b/runtime/observatory_2/tests/service_2/evaluate_activation_test.dart
new file mode 100644
index 0000000..7967aae
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_activation_test.dart
@@ -0,0 +1,269 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+import 'dart:async';
+import 'dart:math' as math;
+
+breakHere() {}
+
+use(dynamic v) => v;
+
+class C {
+  var instVar = 1;
+  static var classVar = 2;
+
+  method(methodParam) {
+    var methodTemp = 4;
+    use(methodTemp);
+    [5].forEach((outerParam) {
+      var outerTemp = 6;
+      use(outerTemp);
+      [7].forEach((innerParam) {
+        var innerTemp = 8;
+        use(innerTemp);
+        breakHere();
+      });
+    });
+  }
+
+  static method2(methodParam) {
+    var methodTemp = 4;
+    use(methodTemp);
+    [5].forEach((outerParam) {
+      var outerTemp = 6;
+      use(outerTemp);
+      [7].forEach((innerParam) {
+        var innerTemp = 8;
+        use(innerTemp);
+        breakHere();
+      });
+    });
+  }
+
+  method3(methodParam) {
+    var methodTemp = 4;
+    use(methodTemp);
+    breakHere();
+  }
+
+  static var closureWithReturnedHome;
+  method4(methodParam) {
+    var methodTemp = 4;
+    use(methodTemp);
+    [5].forEach((outerParam) {
+      var outerTemp = 6;
+      use(outerTemp);
+      closureWithReturnedHome = (innerParam) {
+        var innerTemp = 8;
+        use(innerTemp);
+        breakHere();
+      };
+    });
+  }
+}
+
+Future testMethod(Isolate isolate) async {
+  // silence analyzer.
+  expect(math.sqrt(4), equals(2));
+  Library rootLib = await isolate.rootLibrary.load();
+  ServiceFunction function =
+      rootLib.functions.singleWhere((f) => f.name == 'breakHere');
+  Breakpoint bpt = await isolate.addBreakpointAtEntry(function);
+  print("Breakpoint: $bpt");
+  expect(bpt is Breakpoint, isTrue);  // I.e, not null.
+
+  bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  var sub;
+  sub = stream.listen((ServiceEvent event) async {
+    print("Event $event");
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      var frameNumber = 1, r;
+      r = await isolate.evalFrame(frameNumber, '123');  /// instance: ok
+      expect(r.valueAsString, equals('123'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'this');  /// scope: ok
+      expect(r.clazz.name, equals('C'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'instVar');  /// instance: continued
+      expect(r.valueAsString, equals('1'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'classVar'); /// instance: continued
+      expect(r.valueAsString, equals('2'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'methodParam');  /// scope: continued
+      expect(r.valueAsString, equals('3'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'methodTemp');  /// scope: continued
+      expect(r.valueAsString, equals('4'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerParam');  /// scope: continued
+      expect(r.valueAsString, equals('5'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerTemp');  /// scope: continued
+      expect(r.valueAsString, equals('6'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'innerParam');  /// instance: continued
+      expect(r.valueAsString, equals('7'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'innerTemp');  /// instance: continued
+      expect(r.valueAsString, equals('8'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'math.sqrt');  /// instance: continued
+      expect(r.isClosure, isTrue);  /// instance: continued
+
+      hitBreakpoint = true;
+      sub.cancel();  // Do not handle events for the other tests.
+      isolate.resume();
+    }
+  });
+
+  var result = await rootLib.evaluate('new C().method(3)');
+  print("Result $result");
+  expect(hitBreakpoint, isTrue);
+}
+
+Future testMethod2(Isolate isolate) async {
+  Library rootLib = await isolate.rootLibrary.load();
+  ServiceFunction function =
+      rootLib.functions.singleWhere((f) => f.name == 'breakHere');
+  Breakpoint bpt = await isolate.addBreakpointAtEntry(function);
+  print("Breakpoint: $bpt");
+  expect(bpt is Breakpoint, isTrue);  // I.e, not null.
+
+  bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  var sub;
+  sub = stream.listen((ServiceEvent event) async {
+    print("Event $event");
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      var frameNumber = 1, r;
+      r = await isolate.evalFrame(frameNumber, '123');
+      expect(r.valueAsString, equals('123'));
+      r = await isolate.evalFrame(frameNumber, 'this');
+      expect(r is DartError, isTrue);
+      r = await isolate.evalFrame(frameNumber, 'instVar');
+      expect(r is DartError, isTrue);
+      r = await isolate.evalFrame(frameNumber, 'classVar');
+      expect(r.valueAsString, equals('2'));
+      r = await isolate.evalFrame(frameNumber, 'methodParam');
+      expect(r.valueAsString, equals('3'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'methodTemp');
+      expect(r.valueAsString, equals('4'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerParam');
+      expect(r.valueAsString, equals('5'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerTemp');
+      expect(r.valueAsString, equals('6'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'innerParam');
+      expect(r.valueAsString, equals('7'));
+      r = await isolate.evalFrame(frameNumber, 'innerTemp');
+      expect(r.valueAsString, equals('8'));
+      r = await isolate.evalFrame(frameNumber, 'math.sqrt');
+      expect(r.isClosure, isTrue);
+
+      hitBreakpoint = true;
+      sub.cancel();  // Do not handle events for the other tests.
+      isolate.resume();
+    }
+  });
+
+  var result = await rootLib.evaluate('C.method2(3)');
+  print("Result $result");
+  expect(hitBreakpoint, isTrue);
+}
+
+Future testMethod3(Isolate isolate) async {
+  Library rootLib = await isolate.rootLibrary.load();
+  ServiceFunction function =
+      rootLib.functions.singleWhere((f) => f.name == 'breakHere');
+  Breakpoint bpt = await isolate.addBreakpointAtEntry(function);
+  print("Breakpoint: $bpt");
+  expect(bpt is Breakpoint, isTrue);  // I.e, not null.
+
+  bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  var sub;
+  sub = stream.listen((ServiceEvent event) async {
+    print("Event $event");
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      var frameNumber = 1, r;
+      r = await isolate.evalFrame(frameNumber, '123');
+      expect(r.valueAsString, equals('123'));
+      r = await isolate.evalFrame(frameNumber, 'this');
+      expect(r.clazz.name, equals('C'));
+      r = await isolate.evalFrame(frameNumber, 'instVar');
+      expect(r.valueAsString, equals('1'));
+      r = await isolate.evalFrame(frameNumber, 'classVar');
+      expect(r.valueAsString, equals('2'));
+      r = await isolate.evalFrame(frameNumber, 'methodParam');
+      expect(r.valueAsString, equals('3'));
+      r = await isolate.evalFrame(frameNumber, 'methodTemp');
+      expect(r.valueAsString, equals('4'));
+      r = await isolate.evalFrame(frameNumber, 'math.sqrt');
+      expect(r.isClosure, isTrue);
+
+      hitBreakpoint = true;
+      sub.cancel();  // Do not handle events for the other tests.
+      isolate.resume();
+    }
+  });
+
+  var result = await rootLib.evaluate('new C().method3(3)');
+  print("Result $result");
+  expect(hitBreakpoint, isTrue);
+}
+
+
+Future testMethod4(Isolate isolate) async {
+  Library rootLib = await isolate.rootLibrary.load();
+  ServiceFunction function =
+      rootLib.functions.singleWhere((f) => f.name == 'breakHere');
+  Breakpoint bpt = await isolate.addBreakpointAtEntry(function);
+  print("Breakpoint: $bpt");
+  expect(bpt is Breakpoint, isTrue);  // I.e, not null.
+
+  bool hitBreakpoint = false;
+  var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  var sub;
+  sub = stream.listen((ServiceEvent event) async {
+    print("Event $event");
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      var frameNumber = 1, r;
+      r = await isolate.evalFrame(frameNumber, '123');  /// instance: continued
+      expect(r.valueAsString, equals('123'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'this');  /// scope: continued
+      expect(r.clazz.name, equals('C'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'instVar');  /// instance: continued
+      expect(r.valueAsString, equals('1'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'classVar');  /// instance: continued
+      expect(r.valueAsString, equals('2'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'methodParam');  /// scope: continued
+      expect(r.valueAsString, equals('3'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'methodTemp');  /// scope: continued
+      expect(r.valueAsString, equals('4'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerParam');  /// scope: continued
+      expect(r.valueAsString, equals('5'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'outerTemp');  /// scope: continued
+      expect(r.valueAsString, equals('6'));  /// scope: continued
+      r = await isolate.evalFrame(frameNumber, 'innerParam');  /// instance: continued
+      expect(r.valueAsString, equals('7'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'innerTemp');  /// instance: continued
+      expect(r.valueAsString, equals('8'));  /// instance: continued
+      r = await isolate.evalFrame(frameNumber, 'math.sqrt');  /// instance: continued
+      expect(r.isClosure, isTrue);  /// instance: continued
+
+      hitBreakpoint = true;
+      sub.cancel();  // Do not handle events for the other tests.
+      isolate.resume();
+    }
+  });
+
+  var result = await rootLib.evaluate(
+      '(){ new C().method4(3); C.closureWithReturnedHome(7); }()');
+  print("Result $result");
+  expect(hitBreakpoint, isTrue);
+}
+
+var tests = <IsolateTest>[
+  testMethod,
+  testMethod2,
+  testMethod3,
+  testMethod4,
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_async_closure_test.dart b/runtime/observatory_2/tests/service_2/evaluate_async_closure_test.dart
new file mode 100644
index 0000000..a68c64a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_async_closure_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    // Silence analyzer on 'dart:async' import.
+    expect(new Future.value(0) != null, isTrue);
+    String test = "(){ "
+        "  var k = () { return Future.value(3); }; "
+        "  var w = () async { return await k(); }; "
+        "  return w(); "
+        "}()";
+    Library lib = await isolate.rootLibrary.load();
+
+    var result = await lib.evaluate(test);
+    expect("$result", equals("Instance(a _Future)"));
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_class_type_parameters_test.dart b/runtime/observatory_2/tests/service_2/evaluate_class_type_parameters_test.dart
new file mode 100644
index 0000000..05bf1c4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_class_type_parameters_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+class A<T> {
+  void foo() {
+    debugger();
+  }
+}
+
+class B<S> extends A<int> {
+  void bar() {
+    debugger();
+  }
+}
+
+testFunction() {
+  var v = new B<String>();
+  v.bar();
+  v.foo();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 20);
+
+    Instance result = await isolate.evalFrame(topFrame, '"\$S"');
+    print(result);
+    expect(result.valueAsString, equals("String"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 14);
+
+    Instance result = await isolate.evalFrame(topFrame, '"\$T"');
+    print(result);
+    expect(result.valueAsString, equals("int"));
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_function_type_parameters_test.dart b/runtime/observatory_2/tests/service_2/evaluate_function_type_parameters_test.dart
new file mode 100644
index 0000000..1ee95d1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_function_type_parameters_test.dart
@@ -0,0 +1,137 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+topLevel<S>() {
+  debugger();
+
+  void inner1<TBool, TString, TDouble, TInt>(TInt x) {
+    debugger();
+  }
+
+  inner1<bool, String, double, int>(3);
+
+  void inner2() {
+    debugger();
+  }
+
+  inner2();
+}
+
+class A {
+  foo<T, S>() {
+    debugger();
+  }
+
+  bar<T>(T t) {
+    debugger();
+  }
+}
+
+void testMain() {
+  topLevel<String>();
+  (new A()).foo<int, bool>();
+  (new A()).bar<dynamic>(42);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 14);
+
+    Instance result = await isolate.evalFrame(topFrame, "S.toString()");
+    print(result);
+    expect(result.valueAsString, equals("String"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 16);
+
+    Instance result = await isolate.evalFrame(topFrame, "TBool.toString()");
+    print(result);
+    expect(result.valueAsString, equals("bool"));
+
+    result = await isolate.evalFrame(topFrame, "TString.toString()");
+    print(result);
+    expect(result.valueAsString, equals("String"));
+
+    result = await isolate.evalFrame(topFrame, "TDouble.toString()");
+    print(result);
+    expect(result.valueAsString, equals("double"));
+
+    result = await isolate.evalFrame(topFrame, "TInt.toString()");
+    print(result);
+    expect(result.valueAsString, equals("int"));
+
+    result = await isolate.evalFrame(topFrame, "S.toString()");
+    print(result);
+    expect(result.valueAsString, equals("String"));
+
+    result = await isolate.evalFrame(topFrame, "x");
+    print(result);
+    expect(result.valueAsString, equals("3"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 22);
+
+    Instance result = await isolate.evalFrame(topFrame, "S.toString()");
+    print(result);
+    expect(result.valueAsString, equals("String"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 30);
+
+    Instance result = await isolate.evalFrame(topFrame, "T.toString()");
+    print(result);
+    expect(result.valueAsString, equals("int"));
+
+    result = await isolate.evalFrame(topFrame, "S.toString()");
+    print(result);
+    expect(result.valueAsString, equals("bool"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 34);
+
+    Instance result = await isolate.evalFrame(topFrame, "T.toString()");
+    print(result);
+    expect(result.valueAsString, equals("dynamic"));
+    result = await isolate.evalFrame(topFrame, "t");
+    print(result);
+    expect(result.valueAsString, equals("42"));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_in_async_activation_test.dart b/runtime/observatory_2/tests/service_2/evaluate_in_async_activation_test.dart
new file mode 100644
index 0000000..5dd6681
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_in_async_activation_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+testFunction() async {
+  var x = 3;
+  var y = 4;
+  debugger();
+  var z = await new Future(() => x + y);
+  debugger();
+  return z;
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 16);
+
+    Instance result = await isolate.evalFrame(topFrame, "x");
+    print(result);
+    expect(result.valueAsString, equals("3"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 18);
+
+    Instance result = await isolate.evalFrame(topFrame, "z");
+    print(result);
+    expect(result.valueAsString, equals("7"));
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_in_async_star_activation_test.dart b/runtime/observatory_2/tests/service_2/evaluate_in_async_star_activation_test.dart
new file mode 100644
index 0000000..9d1309a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_in_async_star_activation_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+generator() async* {
+  var x = 3;
+  var y = 4;
+  debugger();
+  yield y;
+  var z = x + y;
+  debugger();
+  yield z;
+}
+
+testFunction() async {
+  await for (var ignored in generator());
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 15);
+
+    Instance result = await isolate.evalFrame(topFrame, "x");
+    print(result);
+    expect(result.valueAsString, equals("3"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 18);
+
+    Instance result = await isolate.evalFrame(topFrame, "z");
+    print(result);
+    expect(result.valueAsString, equals("7"));
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_in_frame_rpc_test.dart b/runtime/observatory_2/tests/service_2/evaluate_in_frame_rpc_test.dart
new file mode 100644
index 0000000..88d6df2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_in_frame_rpc_test.dart
@@ -0,0 +1,44 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void method(int value, _) {
+  debugger();
+}
+
+void testFunction() {
+  int i = 0;
+  while (true) {
+    if (++i % 100000000 == 0) {
+      method(10000, 50);
+    }
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+// Evaluate against library, class, and instance.
+  (Isolate isolate) async {
+    var result;
+    result = await isolate.evalFrame(0, 'value');
+    expect(result.valueAsString, equals('10000'));
+
+    result = await isolate.evalFrame(0, '_');
+    expect(result.valueAsString, equals('50'));
+
+    result = await isolate.evalFrame(0, 'value + _');
+    expect(result.valueAsString, equals('10050'));
+
+    result = await isolate.evalFrame(1, 'i');
+    expect(result.valueAsString, equals('100000000'));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_in_frame_with_scope_test.dart b/runtime/observatory_2/tests/service_2/evaluate_in_frame_with_scope_test.dart
new file mode 100644
index 0000000..0f98b20
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_in_frame_with_scope_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+var thing1;
+var thing2;
+
+testeeMain() {
+  thing1 = 3;
+  thing2 = 4;
+  foo(42, 1984);
+}
+
+foo(x, y) {
+  var local = x + y;
+  debugger();
+  return local;
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('foo'));
+
+    Library lib = await isolate.rootLibrary.load();
+    Field thing1Field =
+        await lib.variables.singleWhere((v) => v.name == "thing1").load();
+    var thing1 = thing1Field.staticValue;
+    print(thing1);
+    Field thing2Field =
+        await lib.variables.singleWhere((v) => v.name == "thing2").load();
+    var thing2 = thing2Field.staticValue;
+    print(thing2);
+
+    ServiceObject result = await isolate.evalFrame(0, "x + y + a + b",
+        scope: <String, ServiceObject>{"a": thing1, "b": thing2});
+    expect(result, isA<Instance>());
+    print(result);
+    expect((result as Instance).valueAsString, equals('2033'));
+
+    result = await isolate.evalFrame(0, "local + a + b",
+        scope: <String, ServiceObject>{"a": thing1, "b": thing2});
+    expect(result, isA<Instance>());
+    print(result);
+    expect((result as Instance).valueAsString, equals('2033'));
+
+    // Note the eval's scope is shadowing the locals' scope.
+    result = await isolate.evalFrame(0, "x + y",
+        scope: <String, ServiceObject>{"x": thing1, "y": thing2});
+    expect(result, isA<Instance>());
+    print(result);
+    expect((result as Instance).valueAsString, equals('7'));
+
+    bool didThrow = false;
+    try {
+      await lib.evaluate("x + y",
+          scope: <String, ServiceObject>{"x": lib, "y": lib});
+    } catch (e) {
+      didThrow = true;
+      expect(e.toString(),
+          contains("Cannot evaluate against a VM-internal object"));
+    }
+    expect(didThrow, isTrue);
+
+    didThrow = false;
+    try {
+      result = await lib.evaluate("x + y",
+          scope: <String, ServiceObject>{"not&an&identifier": thing1});
+      print(result);
+    } catch (e) {
+      didThrow = true;
+      expect(e.toString(), contains("invalid 'scope' parameter"));
+    }
+    expect(didThrow, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_in_sync_star_activation_test.dart b/runtime/observatory_2/tests/service_2/evaluate_in_sync_star_activation_test.dart
new file mode 100644
index 0000000..54bc903
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_in_sync_star_activation_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+generator() sync* {
+  var x = 3;
+  var y = 4;
+  debugger();
+  yield y;
+  var z = x + y;
+  debugger();
+  yield z;
+}
+
+testFunction() {
+  for (var ignored in generator());
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 15);
+
+    Instance result = await isolate.evalFrame(topFrame, "x");
+    print(result);
+    expect(result.valueAsString, equals("3"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Make sure we are in the right place.
+    var stack = await isolate.getStack();
+    var topFrame = 0;
+    expect(stack.type, equals('Stack'));
+    expect(await stack['frames'][topFrame].location.getLine(), 18);
+
+    Instance result = await isolate.evalFrame(topFrame, "z");
+    print(result);
+    expect(result.valueAsString, equals("7"));
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_with_escaping_closure_test.dart b/runtime/observatory_2/tests/service_2/evaluate_with_escaping_closure_test.dart
new file mode 100644
index 0000000..64ecacf
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_with_escaping_closure_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+dynamic escapedClosure;
+
+testeeMain() {}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+
+    Instance result = await lib.evaluate("escapedClosure = (x, y) => x + y");
+    print(result);
+    expect(result.clazz.name, startsWith('_Closure'));
+
+    for (var i = 0; i < 100; i++) {
+      result = await lib.evaluate("escapedClosure(3, 4)");
+      print(result);
+      expect(result.valueAsString, equals('7'));
+    }
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/evaluate_with_scope_test.dart b/runtime/observatory_2/tests/service_2/evaluate_with_scope_test.dart
new file mode 100644
index 0000000..f714823
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/evaluate_with_scope_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var thing1;
+var thing2;
+
+testeeMain() {
+  thing1 = 3;
+  thing2 = 4;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field thing1Field =
+        await lib.variables.singleWhere((v) => v.name == "thing1").load();
+    var thing1 = thing1Field.staticValue;
+    print(thing1);
+    Field thing2Field =
+        await lib.variables.singleWhere((v) => v.name == "thing2").load();
+    var thing2 = thing2Field.staticValue;
+    print(thing2);
+
+    Instance result = await lib.evaluate("x + y",
+        scope: <String, ServiceObject>{"x": thing1, "y": thing2});
+    expect(result.valueAsString, equals('7'));
+
+    bool didThrow = false;
+    try {
+      result = await lib.evaluate("x + y",
+          scope: <String, ServiceObject>{"x": lib, "y": lib});
+      print(result);
+    } catch (e) {
+      didThrow = true;
+      expect(e.toString(),
+          contains("Cannot evaluate against a VM-internal object"));
+    }
+    expect(didThrow, isTrue);
+
+    didThrow = false;
+    try {
+      result = await lib.evaluate("x + y",
+          scope: <String, ServiceObject>{"not&an&identifier": thing1});
+      print(result);
+    } catch (e) {
+      didThrow = true;
+      expect(e.toString(), contains("invalid 'scope' parameter"));
+    }
+    expect(didThrow, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/external_service_asynchronous_invocation_test.dart b/runtime/observatory_2/tests/service_2/external_service_asynchronous_invocation_test.dart
new file mode 100644
index 0000000..5fc82c9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_asynchronous_invocation_test.dart
@@ -0,0 +1,171 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> stream = socket.stream.map(jsonEncode);
+    stream.cast<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+
+    const successServiceName = 'successService';
+    const errorServiceName = 'errorService';
+    const serviceAlias = 'serviceAlias';
+    const paramKey = 'pkey';
+    const paramValue = 'pvalue';
+    const resultKey = 'rkey';
+    const resultValue = 'rvalue';
+    const errorCode = 5000;
+    const errorKey = 'ekey';
+    const errorValue = 'evalue';
+    const repetition = 5;
+
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': successServiceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    // Registering second service
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': errorServiceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    // Testing parallel invocation of service which succeeds
+    {
+      final results = new List<Future<Map>>.generate(repetition, (iteration) {
+        final end = iteration.toString();
+        return vm.invokeRpcRaw(
+            vm.services.first.method, {paramKey + end: paramValue + end});
+      });
+      final requests = await (client.take(repetition).toList());
+
+      final completions = requests.map((final request) {
+        final iteration = requests.indexOf(request);
+        final end = iteration.toString();
+
+        // check requests while they arrive
+        expect(request, contains('id'));
+        expect(request['id'], isNotNull);
+        expect(request['method'], equals(successServiceName));
+        expect(request['params'], isNotNull);
+        expect(request['params'][paramKey + end], equals(paramValue + end));
+
+        // answer later
+        return () => socket.add({
+              'jsonrpc': '2.0',
+              'id': request['id'],
+              'result': {resultKey + end: resultValue + end}
+            });
+      }).toList();
+      // random order
+      completions.shuffle();
+      // answer out of order
+      completions.forEach((complete) => complete());
+
+      final responses = await Future.wait(results);
+      responses.forEach((final response) {
+        final iteration = responses.indexOf(response);
+        final end = iteration.toString();
+
+        expect(response, isNotNull);
+        expect(response[resultKey + end], equals(resultValue + end));
+      });
+    }
+
+    // Testing parallel invocation of service which fails
+    {
+      final results = new List<Future<Map>>.generate(repetition, (iteration) {
+        final end = iteration.toString();
+        return vm.invokeRpcRaw(
+            vm.services[1].method, {paramKey + end: paramValue + end});
+      });
+      final requests = await (client.take(repetition).toList());
+
+      final completions = requests.map((final request) {
+        final iteration = requests.indexOf(request);
+        final end = iteration.toString();
+
+        // check requests while they arrive
+        expect(request, contains('id'));
+        expect(request['id'], isNotNull);
+        expect(request['method'], equals(errorServiceName));
+        expect(request['params'], isNotNull);
+        expect(request['params'][paramKey + end], equals(paramValue + end));
+
+        // answer later
+        return () => socket.add({
+              'jsonrpc': '2.0',
+              'id': request['id'],
+              'error': {
+                'code': errorCode + iteration,
+                'data': {errorKey + end: errorValue + end},
+                'message': 'error message',
+              }
+            });
+      }).toList();
+      // random order
+      completions.shuffle();
+      // answer out of order
+      completions.forEach((complete) => complete());
+
+      final errors = await Future.wait(results.map((future) {
+        return future.then<dynamic>((_) {
+          expect(false, isTrue, reason: 'shouldn\'t get here');
+        }).catchError((e) => e);
+      }));
+      errors.forEach((dynamic error) {
+        final iteration = errors.indexOf(error);
+        final end = iteration.toString();
+
+        expect(error, isNotNull);
+        expect(error.code, equals(errorCode + iteration));
+        expect(error.data, isNotNull);
+        expect(error.data[errorKey + end], equals(errorValue + end));
+      });
+    }
+
+    await socket.close();
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/external_service_disappear_test.dart b/runtime/observatory_2/tests/service_2/external_service_disappear_test.dart
new file mode 100644
index 0000000..d9658ef
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_disappear_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> stream = socket.stream.map(jsonEncode);
+    stream.cast<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+
+    // Note: keep this in sync with sdk/lib/vmservice.dart
+    const kServiceDisappeared = 112;
+    const kServiceDisappeared_Msg = 'Service has disappeared';
+
+    const serviceName = 'disapearService';
+    const serviceAlias = 'serviceAlias';
+    const paramKey = 'pkey';
+    const paramValue = 'pvalue';
+    const repetition = 5;
+
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': serviceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    // Testing invocation of service which disappear
+    {
+      final results = new List<Future<Map>>.generate(repetition, (iteration) {
+        final end = iteration.toString();
+        return vm.invokeRpcRaw(
+            vm.services.first.method, {paramKey + end: paramValue + end});
+      });
+      final requests = await (client.take(repetition).toList());
+
+      requests.forEach((final request) {
+        final iteration = requests.indexOf(request);
+        final end = iteration.toString();
+
+        // check requests while they arrive
+        expect(request, contains('id'));
+        expect(request['id'], isNotNull);
+        expect(request['method'], equals(serviceName));
+        expect(request['params'], isNotNull);
+        expect(request['params'][paramKey + end], equals(paramValue + end));
+      });
+
+      await socket.close();
+
+      await Future.wait(results.map((future) {
+        return future.then((_) {
+          expect(false, isTrue, reason: 'shouldn\'t get here');
+        }).catchError((Object error_object) {
+          ServerRpcException error = error_object as ServerRpcException;
+          expect(error, isNotNull);
+          expect(error.code, equals(kServiceDisappeared));
+          expect(error.message, equals(kServiceDisappeared_Msg));
+        });
+      }));
+    }
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/external_service_notification_invocation_test.dart b/runtime/observatory_2/tests/service_2/external_service_notification_invocation_test.dart
new file mode 100644
index 0000000..47b202e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_notification_invocation_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+    WebSocket _socket_invoker =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController<Map>();
+    final socket_invoker = new StreamController<Map>();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> socket_stream = socket.stream.map(jsonEncode);
+    socket_stream.cast<Object>().pipe(_socket);
+    Stream<String> socket_invoker_stream =
+        socket_invoker.stream.map(jsonEncode);
+    socket_invoker_stream.cast<Object>().pipe(_socket_invoker);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+    final client_invoker = _socket_invoker.map(_decoder).asBroadcastStream();
+
+    const serviceName = 'successService';
+    const serviceAlias = 'serviceAlias';
+    const paramKey = 'pkey';
+    const paramValue = 'pvalue';
+    const repetition = 5;
+
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': serviceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    client_invoker.first.then((_) {
+      expect(false, isTrue, reason: 'shouldn\'t get here');
+    }).catchError((_) => null);
+
+    // Testing serial invocation of service which succedes
+    for (var iteration = 0; iteration < repetition; iteration++) {
+      final end = iteration.toString();
+      socket_invoker.add({
+        'jsonrpc': '2.0',
+        'method': vm.services.first.method,
+        'params': {paramKey + end: paramValue + end}
+      });
+      final request = await client.first;
+
+      expect(request, contains('id'));
+      expect(request['id'], isNotNull);
+      expect(request['method'], equals(serviceName));
+      expect(request['params'], isNotNull);
+      expect(request['params'][paramKey + end], equals(paramValue + end));
+
+      socket.add({'jsonrpc': '2.0', 'id': request['id'], 'result': {}});
+    }
+
+    await socket.close();
+    await socket_invoker.close();
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/external_service_registration_test.dart b/runtime/observatory_2/tests/service_2/external_service_registration_test.dart
new file mode 100644
index 0000000..0356dcb
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_registration_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    expect(vm.services, isEmpty,
+        reason: 'No service should be registered at startup');
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> socket_stream = socket.stream.map(jsonEncode);
+    socket_stream.cast<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+
+    // Note: keep this in sync with sdk/lib/vmservice.dart
+    const kServiceAlreadyRegistered = 111;
+    const kServiceAlreadyRegistered_Msg = 'Service already registered';
+
+    const serviceName = 'serviceName';
+    const serviceAlias = 'serviceAlias';
+
+    {
+      // Registering first service
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': 1,
+        'method': 'registerService',
+        'params': {'service': serviceName, 'alias': serviceAlias}
+      });
+
+      // Avoid flaky test.
+      // We cannot assume the order in which two messages will arrive
+      // from two different sockets
+      final message =
+          (await Future.wait([client.first, serviceEvents.first])).first;
+
+      expect(message['id'], equals(1),
+          reason: 'Should answer with the same id');
+      expect(message['result'], isNotEmpty);
+      expect(message['result']['type'], equals('Success'));
+
+      expect(vm.services, isNotEmpty);
+      expect(vm.services.length, equals(1));
+      expect(vm.services.first.service, equals(serviceName));
+      expect(vm.services.first.method, isNotEmpty);
+      expect(vm.services.first.alias, equals(serviceAlias));
+    }
+
+    {
+      // Registering second service
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': 1,
+        'method': 'registerService',
+        'params': {'service': serviceName + '2', 'alias': serviceAlias + '2'}
+      });
+
+      // Avoid flaky test.
+      // We cannot assume the order in which two messages will arrive
+      // from two different sockets
+      final message =
+          (await Future.wait([client.first, serviceEvents.first])).first;
+
+      expect(message['id'], equals(1),
+          reason: 'Should answer with the same id');
+      expect(message['result'], isNotEmpty);
+      expect(message['result']['type'], equals('Success'));
+
+      expect(vm.services, isNotEmpty);
+      expect(vm.services.length, equals(2));
+      expect(vm.services[1].service, equals(serviceName + '2'));
+      expect(vm.services[1].method, isNotEmpty);
+      expect(vm.services[1].alias, equals(serviceAlias + '2'));
+    }
+
+    {
+      // Double registering first service
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': 1,
+        'method': 'registerService',
+        'params': {'service': serviceName, 'alias': serviceAlias}
+      });
+
+      final message = await client.first;
+
+      expect(message['id'], equals(1),
+          reason: 'Should answer with the same id');
+      expect(message['error'], isNotEmpty);
+      expect(message['error']['code'], equals(kServiceAlreadyRegistered));
+      expect(
+          message['error']['message'], equals(kServiceAlreadyRegistered_Msg));
+    }
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([socket.close(), serviceEvents.take(2).last]);
+
+    expect(vm.services, isEmpty,
+        reason: 'Should unregister services when client disconnects');
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/external_service_registration_via_notification_test.dart b/runtime/observatory_2/tests/service_2/external_service_registration_via_notification_test.dart
new file mode 100644
index 0000000..927d801
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_registration_via_notification_test.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    expect(vm.services, isEmpty,
+        reason: 'No service should be registered at startup');
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> stream = socket.stream.map(jsonEncode);
+    stream.cast<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+
+    // Note: keep this in sync with sdk/lib/vmservice.dart
+    const kServiceAlreadyRegistered = 111;
+    const kServiceAlreadyRegistered_Msg = 'Service already registered';
+
+    const serviceName = 'serviceName';
+    const serviceAlias = 'serviceAlias';
+
+    {
+      // Registering first service
+      socket.add({
+        'jsonrpc': '2.0',
+        'method': 'registerService',
+        'params': {'service': serviceName, 'alias': serviceAlias}
+      });
+
+      await serviceEvents.first;
+
+      expect(vm.services, isNotEmpty);
+      expect(vm.services.length, equals(1));
+      expect(vm.services.first.service, equals(serviceName));
+      expect(vm.services.first.method, isNotEmpty);
+      expect(vm.services.first.alias, equals(serviceAlias));
+    }
+
+    {
+      // Registering second service
+      socket.add({
+        'jsonrpc': '2.0',
+        'method': 'registerService',
+        'params': {'service': serviceName + '2', 'alias': serviceAlias + '2'}
+      });
+
+      await serviceEvents.first;
+
+      expect(vm.services, isNotEmpty);
+      expect(vm.services.length, equals(2));
+      expect(vm.services[1].service, equals(serviceName + '2'));
+      expect(vm.services[1].method, isNotEmpty);
+      expect(vm.services[1].alias, equals(serviceAlias + '2'));
+    }
+
+    {
+      // Double registering first service
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': 1,
+        'method': 'registerService',
+        'params': {'service': serviceName, 'alias': serviceAlias}
+      });
+
+      final message = await client.first;
+
+      expect(message['id'], equals(1),
+          reason: 'Should answer with the same id');
+      expect(message['error'], isNotEmpty);
+      expect(message['error']['code'], equals(kServiceAlreadyRegistered));
+      expect(
+          message['error']['message'], equals(kServiceAlreadyRegistered_Msg));
+    }
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([socket.close(), serviceEvents.take(2).last]);
+
+    expect(vm.services, isEmpty,
+        reason: 'Should unregister services when client disconnects');
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/external_service_synchronous_invocation_test.dart b/runtime/observatory_2/tests/service_2/external_service_synchronous_invocation_test.dart
new file mode 100644
index 0000000..33dffe1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/external_service_synchronous_invocation_test.dart
@@ -0,0 +1,133 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:io' show WebSocket;
+import 'dart:convert' show jsonDecode, jsonEncode;
+import 'dart:async' show Future, Stream, StreamController;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.owner;
+
+    final serviceEvents =
+        (await vm.getEventStream('Service')).asBroadcastStream();
+
+    WebSocket _socket =
+        await WebSocket.connect((vm as WebSocketVM).target.networkAddress);
+
+    final socket = new StreamController();
+
+    // Avoid to manually encode and decode messages from the stream
+    Stream<String> stream = socket.stream.map(jsonEncode);
+    stream.cast<Object>().pipe(_socket);
+    dynamic _decoder(dynamic obj) {
+      return jsonDecode(obj);
+    }
+
+    final client = _socket.map(_decoder).asBroadcastStream();
+
+    const successServiceName = 'successService';
+    const errorServiceName = 'errorService';
+    const serviceAlias = 'serviceAlias';
+    const paramKey = 'pkey';
+    const paramValue = 'pvalue';
+    const resultKey = 'rkey';
+    const resultValue = 'rvalue';
+    const errorCode = 5000;
+    const errorKey = 'ekey';
+    const errorValue = 'evalue';
+    const repetition = 5;
+
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': successServiceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    // Registering second service
+    socket.add({
+      'jsonrpc': '2.0',
+      'id': 1,
+      'method': 'registerService',
+      'params': {'service': errorServiceName, 'alias': serviceAlias}
+    });
+
+    // Avoid flaky test.
+    // We cannot assume the order in which two messages will arrive
+    // from two different sockets
+    await Future.wait([client.first, serviceEvents.first]);
+
+    // Testing serial invocation of service which succeeds
+    for (var iteration = 0; iteration < repetition; iteration++) {
+      final end = iteration.toString();
+      final result = vm.invokeRpcRaw(
+          vm.services.first.method, {paramKey + end: paramValue + end});
+      final request = await client.first;
+
+      expect(request, contains('id'));
+      expect(request['id'], isNotNull);
+      expect(request['method'], equals(successServiceName));
+      expect(request['params'], isNotNull);
+      expect(request['params'][paramKey + end], equals(paramValue + end));
+
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': request['id'],
+        'result': {resultKey + end: resultValue + end}
+      });
+
+      final response = await result;
+
+      expect(response, isNotNull);
+      expect(response[resultKey + end], equals(resultValue + end));
+    }
+
+    // Testing serial invocation of service which fails
+    for (var iteration = 0; iteration < repetition; iteration++) {
+      final end = iteration.toString();
+      final result = vm.invokeRpcRaw(
+          vm.services[1].method, {paramKey + end: paramValue + end});
+      final request = await client.first;
+
+      expect(request, contains('id'));
+      expect(request['id'], isNotNull);
+      expect(request['method'], equals(errorServiceName));
+      expect(request['params'], isNotNull);
+      expect(request['params'][paramKey + end], equals(paramValue + end));
+
+      socket.add({
+        'jsonrpc': '2.0',
+        'id': request['id'],
+        'error': {
+          'code': errorCode + iteration,
+          'data': {errorKey + end: errorValue + end},
+          'message': 'error message',
+        }
+      });
+
+      try {
+        final response = await result;
+        expect(false, isTrue, reason: 'shouldn\'t get here');
+      } on ServerRpcException catch (e) {
+        expect(e.code, equals(errorCode + iteration));
+        expect(e.data, isNotNull);
+        expect(e.data[errorKey + end], equals(errorValue + end));
+      }
+    }
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+    );
diff --git a/runtime/observatory_2/tests/service_2/field_script_other.dart b/runtime/observatory_2/tests/service_2/field_script_other.dart
new file mode 100644
index 0000000..ed9681e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/field_script_other.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of field_script_test;
+
+var otherField = 42;
diff --git a/runtime/observatory_2/tests/service_2/field_script_test.dart b/runtime/observatory_2/tests/service_2/field_script_test.dart
new file mode 100644
index 0000000..e83c57f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/field_script_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library field_script_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+part 'field_script_other.dart';
+
+code() {
+  print(otherField);
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    var fields = lib.variables;
+    expect(fields.length, 2);
+    print(lib.variables);
+    for (Field f in fields) {
+      await f.load();
+      String locationString = await f.location.toUserString();
+      if (f.name == "tests") {
+        expect(locationString, "field_script_test.dart:18:5");
+      } else if (f.name == "otherField") {
+        expect(locationString, "field_script_other.dart:7:5");
+      } else {
+        fail("Unexpected field: ${f.name}");
+      }
+    }
+  }
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/file_service_test.dart b/runtime/observatory_2/tests/service_2/file_service_test.dart
new file mode 100644
index 0000000..be3b3cf
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/file_service_test.dart
@@ -0,0 +1,105 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+Future setupFiles() async {
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
+  var writingFile;
+  var readingFile;
+
+  void closeDown() {
+    if (writingFile != null) {
+      writingFile.closeSync();
+    }
+    if (readingFile != null) {
+      readingFile.closeSync();
+    }
+    dir.deleteSync(recursive: true);
+  }
+
+  Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
+    closeDown();
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+    try {
+      final filePath = dir.path + io.Platform.pathSeparator + "file";
+      final f = io.File(filePath);
+      writingFile = await f.open(mode: io.FileMode.write);
+      await writingFile.writeByte(42);
+      await writingFile.writeByte(42);
+      await writingFile.writeByte(42);
+
+      final file = io.File.fromUri(io.Platform.script);
+      readingFile = await file.open();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+      await readingFile.readByte();
+
+      // The utility functions should close the files after them, so we
+      // don't expect the calls below to result in open files.
+      final writeTemp = dir.path + io.Platform.pathSeparator + "other_file";
+      final utilFile = io.File(writeTemp);
+      await utilFile.writeAsString('foobar');
+      final readTemp = io.File(writeTemp);
+      final result = await readTemp.readAsString();
+      Expect.equals(result, 'foobar');
+    } catch (e) {
+      closeDown();
+      throw e;
+    }
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
+}
+
+var fileTests = <IsolateTest>[
+  (Isolate isolate) async {
+    await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
+    try {
+      final result =
+          await isolate.invokeRpcNoUpgrade('ext.dart.io.getOpenFiles', {});
+      expect(result['type'], equals('OpenFileList'));
+      expect(result['files'].length, equals(2));
+      final writing = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getOpenFileById', {'id': result['files'][0]['id']});
+
+      expect(writing['readBytes'], equals(0));
+      expect(writing['readCount'], equals(0));
+      expect(writing['writeCount'], equals(3));
+      expect(writing['writeBytes'], equals(3));
+      expect(writing['lastWriteTime'], greaterThan(0));
+      expect(writing['lastReadTime'], equals(0));
+
+      final reading = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getOpenFileById', {'id': result['files'][1]['id']});
+
+      expect(reading['readBytes'], equals(5));
+      expect(reading['readCount'], equals(5));
+      expect(reading['writeCount'], equals(0));
+      expect(reading['writeBytes'], equals(0));
+      expect(reading['lastWriteTime'], equals(0));
+      expect(reading['lastReadTime'], greaterThan(0));
+    } finally {
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
+    }
+  },
+];
+
+main(args) async => runIsolateTests(args, fileTests, testeeBefore: setupFiles);
diff --git a/runtime/observatory_2/tests/service_2/gc_test.dart b/runtime/observatory_2/tests/service_2/gc_test.dart
new file mode 100644
index 0000000..014f661
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/gc_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'test_helper.dart';
+
+import 'dart:async';
+
+void script() {
+  var grow;
+  grow = (int iterations, int size, Duration duration) {
+    if (iterations <= 0) {
+      return;
+    }
+    new List<int>.filled(size, 0);
+    new Timer(duration, () => grow(iterations - 1, size, duration));
+  };
+  grow(100, 1 << 24, new Duration(seconds: 1));
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) {
+    Completer completer = new Completer();
+    // Expect at least this many GC events.
+    int gcCountdown = 3;
+    isolate.vm.getEventStream(VM.kGCStream).then((stream) {
+      var subscription;
+      subscription = stream.listen((ServiceEvent event) {
+        assert(event.kind == ServiceEvent.kGC);
+        print('Received GC event');
+        if (--gcCountdown == 0) {
+          subscription.cancel();
+          completer.complete();
+        }
+      });
+    });
+    return completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: script);
diff --git a/runtime/observatory_2/tests/service_2/get_allocation_profile_public_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_allocation_profile_public_rpc_test.dart
new file mode 100644
index 0000000..c63b282
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_allocation_profile_public_rpc_test.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+Future sleep(int milliseconds) {
+  Completer completer = new Completer();
+  Duration duration = new Duration(milliseconds: milliseconds);
+  new Timer(duration, () => completer.complete());
+  return completer.future;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var params = {};
+    var result =
+        await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    expect(result.containsKey('dateLastAccumulatorReset'), isFalse);
+    expect(result.containsKey('dateLastServiceGC'), isFalse);
+    expect(result.containsKey('_heaps'), isFalse);
+    expect(result['members'].length, isPositive);
+
+    var member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isFalse);
+    expect(member.containsKey('_old'), isFalse);
+    expect(member.containsKey('_promotedInstances'), isFalse);
+    expect(member.containsKey('_promotedBytes'), isFalse);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    // reset.
+    params = {
+      'reset': 'true',
+    };
+    result = await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    var firstReset = result['dateLastAccumulatorReset'];
+    expect(firstReset, isA<String>());
+    expect(result.containsKey('dateLastServiceGC'), isFalse);
+    expect(result.containsKey('_heaps'), isFalse);
+    expect(result['members'].length, isPositive);
+
+    member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isFalse);
+    expect(member.containsKey('_old'), isFalse);
+    expect(member.containsKey('_promotedInstances'), isFalse);
+    expect(member.containsKey('_promotedBytes'), isFalse);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    await sleep(1000);
+
+    result = await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+    var secondReset = result['dateLastAccumulatorReset'];
+    expect(secondReset, isNot(equals(firstReset)));
+
+    // gc.
+    params = {
+      'gc': 'true',
+    };
+    result = await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    expect(result['dateLastAccumulatorReset'], equals(secondReset));
+    var firstGC = result['dateLastServiceGC'];
+    expect(firstGC, isA<String>());
+    expect(result.containsKey('_heaps'), isFalse);
+    expect(result['members'].length, isPositive);
+
+    member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isFalse);
+    expect(member.containsKey('_old'), isFalse);
+    expect(member.containsKey('_promotedInstances'), isFalse);
+    expect(member.containsKey('_promotedBytes'), isFalse);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    await sleep(1000);
+
+    result = await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+    var secondGC = result['dateLastAccumulatorReset'];
+    expect(secondGC, isNot(equals(firstGC)));
+  },
+  (Isolate isolate) async {
+    var params = {
+      'reset': 'banana',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.data['details'],
+          "getAllocationProfile: invalid \'reset\' parameter: banana");
+    }
+    expect(caughtException, isTrue);
+  },
+  (Isolate isolate) async {
+    var params = {
+      'gc': 'banana',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getAllocationProfile', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.data['details'],
+          "getAllocationProfile: invalid \'gc\' parameter: banana");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_allocation_profile_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_allocation_profile_rpc_test.dart
new file mode 100644
index 0000000..a589331
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_allocation_profile_rpc_test.dart
@@ -0,0 +1,132 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+Future sleep(int milliseconds) {
+  Completer completer = new Completer();
+  Duration duration = new Duration(milliseconds: milliseconds);
+  new Timer(duration, () => completer.complete());
+  return completer.future;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var params = {};
+    var result =
+        await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    expect(result.containsKey('dateLastAccumulatorReset'), isFalse);
+    expect(result.containsKey('dateLastServiceGC'), isFalse);
+    expect(result['_heaps'].length, isPositive);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+    expect(result['members'].length, isPositive);
+
+    var member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isTrue);
+    expect(member.containsKey('_old'), isTrue);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    // reset.
+    params = {
+      'reset': 'true',
+    };
+    result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    var firstReset = result['dateLastAccumulatorReset'];
+    expect(firstReset, isA<String>());
+    expect(result.containsKey('dateLastServiceGC'), isFalse);
+    expect(result['_heaps'].length, isPositive);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+    expect(result['members'].length, isPositive);
+
+    member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isTrue);
+    expect(member.containsKey('_old'), isTrue);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    await sleep(1000);
+
+    result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+    var secondReset = result['dateLastAccumulatorReset'];
+    expect(secondReset, isNot(equals(firstReset)));
+
+    // gc.
+    params = {
+      'gc': 'true',
+    };
+    result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+    expect(result['type'], equals('AllocationProfile'));
+    expect(result['dateLastAccumulatorReset'], equals(secondReset));
+    var firstGC = result['dateLastServiceGC'];
+    expect(firstGC, isA<String>());
+    expect(result['_heaps'].length, isPositive);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+    expect(result['members'].length, isPositive);
+
+    member = result['members'][0];
+    expect(member['type'], equals('ClassHeapStats'));
+    expect(member.containsKey('_new'), isTrue);
+    expect(member.containsKey('_old'), isTrue);
+    expect(member.containsKey('instancesAccumulated'), isTrue);
+    expect(member.containsKey('instancesCurrent'), isTrue);
+    expect(member.containsKey('bytesCurrent'), isTrue);
+    expect(member.containsKey('accumulatedSize'), isTrue);
+
+    await sleep(1000);
+
+    result = await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+    var secondGC = result['dateLastAccumulatorReset'];
+    expect(secondGC, isNot(equals(firstGC)));
+  },
+  (Isolate isolate) async {
+    var params = {
+      'reset': 'banana',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.data['details'],
+          "_getAllocationProfile: invalid \'reset\' parameter: banana");
+    }
+    expect(caughtException, isTrue);
+  },
+  (Isolate isolate) async {
+    var params = {
+      'gc': 'banana',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('_getAllocationProfile', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.data['details'],
+          "_getAllocationProfile: invalid \'gc\' parameter: banana");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_allocation_samples_test.dart b/runtime/observatory_2/tests/service_2/get_allocation_samples_test.dart
new file mode 100644
index 0000000..87eebfd
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_allocation_samples_test.dart
@@ -0,0 +1,91 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/sample_profile.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+class Foo {
+  Foo() {
+    print('new Foo');
+  }
+}
+
+void test() {
+  debugger();
+  // Toggled on.
+  debugger();
+  debugger();
+  // Allocation.
+  new Foo();
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+
+  // Initial.
+  (Isolate isolate) async {
+    // Verify initial state of 'Foo'.
+    var fooClass = await getClassFromRootLib(isolate, 'Foo');
+    expect(fooClass, isNotNull);
+    expect(fooClass.name, equals('Foo'));
+    print(fooClass.id);
+    expect(fooClass.traceAllocations, isFalse);
+    await fooClass.setTraceAllocations(true);
+    await fooClass.reload();
+    expect(fooClass.traceAllocations, isTrue);
+  },
+
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  // Extra debugger stop, continue to allow the allocation stubs to be switched
+  // over. This is a bug but low priority.
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+
+  // Allocation profile.
+  (Isolate isolate) async {
+    var fooClass = await getClassFromRootLib(isolate, 'Foo');
+    await fooClass.reload();
+    expect(fooClass.traceAllocations, isTrue);
+    dynamic profileResponse = await fooClass.getAllocationSamples();
+    expect(profileResponse, isNotNull);
+    expect(profileResponse['type'], equals('_CpuProfile'));
+    await fooClass.setTraceAllocations(false);
+    await fooClass.reload();
+    expect(fooClass.traceAllocations, isFalse);
+    SampleProfile cpuProfile = new SampleProfile();
+    await cpuProfile.load(isolate, profileResponse);
+    cpuProfile.buildCodeCallerAndCallees();
+    cpuProfile.buildFunctionCallerAndCallees();
+    var tree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
+    var node = tree.root;
+    var expected = [
+      'Root',
+      'DRT_AllocateObject',
+      '[Stub] Allocate Foo',
+      'test',
+      'test',
+      '_Closure.call'
+    ];
+    for (var i = 0; i < expected.length; i++) {
+      expect(node.profileCode.code.name, equals(expected[i]));
+      // Depth first traversal.
+      if (node.children.length == 0) {
+        node = null;
+      } else {
+        node = node.children[0];
+      }
+      expect(node, isNotNull);
+    }
+  },
+  resumeIsolate,
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: test);
diff --git a/runtime/observatory_2/tests/service_2/get_client_name_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_client_name_rpc_test.dart
new file mode 100644
index 0000000..6f29c9c
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_client_name_rpc_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+void fooBar() {}
+
+Future<String> getClientName(Isolate isolate) async {
+  final result = await isolate.vm.invokeRpcNoUpgrade('getClientName', {});
+  return result['name'];
+}
+
+Future<void> setClientName(Isolate isolate, String name) async =>
+    await isolate.vm.invokeRpcNoUpgrade('setClientName', {
+      'name': name,
+    });
+
+final test = <IsolateTest>[
+  (Isolate isolate) async {
+    // Each client has a default name based on the order of connection to the
+    // service.
+    expect(await getClientName(isolate), 'client1');
+
+    // Set a custom client name and check it was set properly.
+    await setClientName(isolate, 'foobar');
+    expect(await getClientName(isolate), 'foobar');
+
+    // Clear the client name and check that we're using the default again.
+    await setClientName(isolate, '');
+    expect(await getClientName(isolate), 'client1');
+  },
+];
+
+Future<void> main(args) => runIsolateTests(
+      args,
+      test,
+      testeeBefore: fooBar,
+      enableService: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/get_cpu_profile_timeline_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_cpu_profile_timeline_rpc_test.dart
new file mode 100644
index 0000000..40db79e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_cpu_profile_timeline_rpc_test.dart
@@ -0,0 +1,62 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/src/repositories/timeline_base.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+fib(n) {
+  if (n < 0) return 0;
+  if (n == 0) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+testeeDo() {
+  print("Testee doing something.");
+  fib(30);
+  print("Testee did something.");
+}
+
+Future checkTimeline(VM vm) async {
+  var result = await TimelineRepositoryBase().getCpuProfileTimeline(vm);
+  var isString = isA<String>();
+  var isInt = isA<int>();
+  Map frames = result['stackFrames'];
+  expect(frames.length, greaterThan(10), reason: "Should have many samples");
+  for (Map frame in frames.values) {
+    expect(frame['category'], isString);
+    expect(frame['name'], isString);
+    if (frame['resolvedUrl'] != null) {
+      expect(frame['resolvedUrl'], isString);
+    }
+    if (frame['parent'] != null) {
+      expect(frames.containsKey(frame['parent']), isTrue);
+    }
+  }
+
+  List events = result['traceEvents'];
+  expect(events.length, greaterThan(10), reason: "Should have many samples");
+  for (Map event in events) {
+    expect(event['ph'], equals('P'));
+    expect(event['pid'], isInt);
+    expect(event['tid'], isInt);
+    expect(event['ts'], isInt);
+    expect(event['cat'], equals("Dart"));
+    expect(frames.containsKey(event['sf']), isTrue);
+  }
+}
+
+var tests = <VMTest>[
+  (VM vm) => checkTimeline(vm),
+];
+
+var vmArgs = [
+  '--profiler=true',
+  '--profile-vm=false', // So this also works with KBC.
+];
+
+main(args) async =>
+    runVMTests(args, tests, testeeBefore: testeeDo, extraArgs: vmArgs);
diff --git a/runtime/observatory_2/tests/service_2/get_cpu_samples_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_cpu_samples_rpc_test.dart
new file mode 100644
index 0000000..d121b2b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_cpu_samples_rpc_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+fib(n) {
+  if (n < 0) return 0;
+  if (n == 0) return 1;
+  return fib(n - 1) + fib(n - 2);
+}
+
+testeeDo() {
+  print("Testee doing something.");
+  fib(30);
+  print("Testee did something.");
+}
+
+Future checkSamples(Isolate isolate) async {
+  final result =
+      await isolate.invokeRpcNoUpgrade('getCpuSamples', {'_code': true});
+  expect(result['type'], equals('CpuSamples'));
+
+  final isString = isA<String>();
+  final isInt = isA<int>();
+  final isList = isA<List>();
+  final functions = result['functions'];
+  expect(functions.length, greaterThan(10),
+      reason: "Should have many functions");
+  final codes = result['_codes'];
+  expect(functions.length, greaterThan(10),
+      reason: "Should have many code objects");
+
+  final samples = result['samples'];
+  expect(samples.length, greaterThan(10), reason: "Should have many samples");
+  final sample = samples.first;
+  expect(sample['tid'], isInt);
+  expect(sample['timestamp'], isInt);
+  if (sample.containsKey('vmTag')) {
+    expect(sample['vmTag'], isString);
+  }
+  if (sample.containsKey('userTag')) {
+    expect(sample['userTag'], isString);
+  }
+  expect(sample['stack'], isList);
+  expect(sample['_codeStack'], isList);
+}
+
+var tests = <IsolateTest>[
+  (Isolate i) => checkSamples(i),
+];
+
+var vmArgs = [
+  '--profiler=true',
+  '--profile-vm=false', // So this also works with KBC.
+];
+
+main(args) async =>
+    runIsolateTests(args, tests, testeeBefore: testeeDo, extraArgs: vmArgs);
diff --git a/runtime/observatory_2/tests/service_2/get_flag_list_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_flag_list_rpc_test.dart
new file mode 100644
index 0000000..b70e4e4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_flag_list_rpc_test.dart
@@ -0,0 +1,140 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+Future getFlagValue(VM vm, String flagName) async {
+  var result = await vm.invokeRpcNoUpgrade('getFlagList', {});
+  expect(result['type'], equals('FlagList'));
+  final flags = result['flags'];
+  for (final flag in flags) {
+    if (flag['name'] == flagName) {
+      return flag['valueAsString'];
+    }
+  }
+}
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('getFlagList', {});
+    expect(result['type'], equals('FlagList'));
+    // TODO(turnidge): Make this test a bit beefier.
+  },
+
+  // Modify a flag which does not exist.
+  (VM vm) async {
+    var params = {
+      'name': 'does_not_really_exist',
+      'value': 'true',
+    };
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Error'));
+    expect(result['message'], equals('Cannot set flag: flag not found'));
+  },
+
+  // Modify a flag with the wrong value type.
+  (VM vm) async {
+    var params = {
+      'name': 'pause_isolates_on_start',
+      'value': 'not-a-boolean',
+    };
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Error'));
+    expect(result['message'], equals('Cannot set flag: invalid value'));
+  },
+
+  // Modify a flag with the right value type.
+  (VM vm) async {
+    var params = {
+      'name': 'pause_isolates_on_start',
+      'value': 'false',
+    };
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+  },
+
+  // Modify a flag which cannot be set at runtime.
+  (VM vm) async {
+    var params = {
+      'name': 'random_seed',
+      'value': '42',
+    };
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Error'));
+    expect(
+        result['message'], equals('Cannot set flag: cannot change at runtime'));
+  },
+
+  // Modify the profile_period at runtime.
+  (VM vm) async {
+    final kProfilePeriod = 'profile_period';
+    final kValue = 100;
+    expect(await getFlagValue(vm, kProfilePeriod), '1000');
+    final params = {
+      'name': '$kProfilePeriod',
+      'value': '$kValue',
+    };
+    final completer = Completer();
+    final stream = await vm.getEventStream(VM.kVMStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kVMFlagUpdate) {
+        expect(event.owner.type, 'VM');
+        expect(event.flag, kProfilePeriod);
+        expect(event.newValue, kValue.toString());
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    final result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+    await completer.future;
+    expect(await getFlagValue(vm, kProfilePeriod), kValue.toString());
+  },
+
+  // Start and stop the profiler at runtime.
+  (VM vm) async {
+    final kProfiler = 'profiler';
+    if (await getFlagValue(vm, kProfiler) == 'false') {
+      // Either in release or product modes and the profiler is disabled.
+      return;
+    }
+    final params = {
+      'name': kProfiler,
+      'value': 'false',
+    };
+
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+    expect(await getFlagValue(vm, kProfiler), 'false');
+    try {
+      // Arbitrary RPC which checks whether or not the profiler is enabled.
+      await vm.isolates.first.invokeRpcNoUpgrade('getCpuSamples', {});
+      fail('Profiler is disabled and request should fail');
+    } on ServerRpcException catch (_) {/* Expected */}
+
+    // Clear CPU samples.
+    result = await vm.isolates.first.invokeRpcNoUpgrade('clearCpuSamples', {});
+    expect(result['type'], equals('Success'));
+
+    params['value'] = 'true';
+    result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+    expect(await getFlagValue(vm, kProfiler), 'true');
+
+    try {
+      // Arbitrary RPC which checks whether or not the profiler is enabled.
+      result = await vm.isolates.first.invokeRpcNoUpgrade('getCpuSamples', {});
+    } on ServerRpcException catch (e) {
+      fail('Profiler is enabled and request should succeed. Error:\n$e');
+    }
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_heap_map_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_heap_map_rpc_test.dart
new file mode 100644
index 0000000..ffb754b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_heap_map_rpc_test.dart
@@ -0,0 +1,65 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var params = {};
+    var result = await isolate.invokeRpcNoUpgrade('_getHeapMap', params);
+    expect(result['type'], equals('HeapMap'));
+    expect(result['freeClassId'], isPositive);
+    expect(result['unitSizeBytes'], isPositive);
+    expect(result['pageSizeBytes'], isPositive);
+    expect(result['classList'], isNotNull);
+    expect(result['pages'].length, isPositive);
+    expect(result['pages'][0]['objectStart'], isA<String>());
+    expect(result['pages'][0]['objects'].length, isPositive);
+    expect(result['pages'][0]['objects'][0], isPositive);
+  },
+  (Isolate isolate) async {
+    var params = {'gc': 'scavenge'};
+    var result = await isolate.invokeRpcNoUpgrade('_getHeapMap', params);
+    expect(result['type'], equals('HeapMap'));
+    expect(result['freeClassId'], isPositive);
+    expect(result['unitSizeBytes'], isPositive);
+    expect(result['pageSizeBytes'], isPositive);
+    expect(result['classList'], isNotNull);
+    expect(result['pages'].length, isPositive);
+    expect(result['pages'][0]['objectStart'], isA<String>());
+    expect(result['pages'][0]['objects'].length, isPositive);
+    expect(result['pages'][0]['objects'][0], isPositive);
+  },
+  (Isolate isolate) async {
+    var params = {'gc': 'mark-sweep'};
+    var result = await isolate.invokeRpcNoUpgrade('_getHeapMap', params);
+    expect(result['type'], equals('HeapMap'));
+    expect(result['freeClassId'], isPositive);
+    expect(result['unitSizeBytes'], isPositive);
+    expect(result['pageSizeBytes'], isPositive);
+    expect(result['classList'], isNotNull);
+    expect(result['pages'].length, isPositive);
+    expect(result['pages'][0]['objectStart'], isA<String>());
+    expect(result['pages'][0]['objects'].length, isPositive);
+    expect(result['pages'][0]['objects'][0], isPositive);
+  },
+  (Isolate isolate) async {
+    var params = {'gc': 'mark-compact'};
+    var result = await isolate.invokeRpcNoUpgrade('_getHeapMap', params);
+    expect(result['type'], equals('HeapMap'));
+    expect(result['freeClassId'], isPositive);
+    expect(result['unitSizeBytes'], isPositive);
+    expect(result['pageSizeBytes'], isPositive);
+    expect(result['classList'], isNotNull);
+    expect(result['pages'].length, isPositive);
+    expect(result['pages'][0]['objectStart'], isA<String>());
+    expect(result['pages'][0]['objects'].length, isPositive);
+    expect(result['pages'][0]['objects'][0], isPositive);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_instances_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_instances_rpc_test.dart
new file mode 100644
index 0000000..7a6047d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_instances_rpc_test.dart
@@ -0,0 +1,76 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+class _TestClass {
+  _TestClass(this.x, this.y);
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+var global;
+
+void warmup() {
+  global = new _TestClass(new _TestClass(1, 2), null);
+}
+
+@pragma("vm:entry-point")
+getGlobal() => global;
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var obj = await invoke(isolate, 'getGlobal');
+    var params = {
+      'objectId': obj['class']['id'],
+      'limit': 4,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getInstances', params);
+    expect(result['type'], equals('InstanceSet'));
+    expect(result['totalCount'], equals(2));
+    expect(result['instances'].length, equals(2));
+    expect(result['instances'][0]['type'], equals('@Instance'));
+
+    // Limit is respected.
+    params = {
+      'objectId': obj['class']['id'],
+      'limit': 1,
+    };
+    result = await isolate.invokeRpcNoUpgrade('getInstances', params);
+    expect(result['type'], equals('InstanceSet'));
+    expect(result['totalCount'], equals(2));
+    expect(result['instances'].length, equals(1));
+    expect(result['instances'][0]['type'], equals('@Instance'));
+
+    // Try an object ID that isn't a class ID
+    params = {
+      'objectId': isolate.rootLibrary.id,
+      'limit': 1,
+    };
+    try {
+      await isolate.invokeRpcNoUpgrade('getInstances', params);
+    } on ServerRpcException catch (_) {
+      // Success.
+    } catch (e) {
+      fail('Failed with exception: $e');
+    }
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_after_async_error_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_after_async_error_test.dart
new file mode 100644
index 0000000..eb79fdf
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_after_async_error_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+doThrow() async {
+  throw "oh no"; // Line 13.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtExit,
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('oh no'), isTrue);
+  }
+];
+
+main(args) async => runIsolateTests(args, tests,
+    pause_on_exit: true, testeeConcurrent: doThrow);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_after_language_error_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_after_language_error_test.dart
new file mode 100644
index 0000000..88a7f89
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_after_language_error_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+var x;
+
+doThrow() {
+  if (x) while {
+  };
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtExit,
+
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains("'(' expected"), isTrue);
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args,
+                                         tests,
+                                         pause_on_exit: true,
+                                         testeeConcurrent: doThrow);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_after_stack_overflow_error_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_after_stack_overflow_error_test.dart
new file mode 100644
index 0000000..6b76c6b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_after_stack_overflow_error_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+// Non tailable recursive function that should trigger a Stack Overflow.
+num factorialGrowth([num n = 1]) {
+  return factorialGrowth(n + 1) * n;
+}
+
+void nonTailableRecursion() {
+  factorialGrowth();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtExit,
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('Stack Overflow'), isTrue);
+  }
+];
+
+main(args) async => runIsolateTests(args, tests,
+    pause_on_exit: true, testeeConcurrent: nonTailableRecursion);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_after_sync_error_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_after_sync_error_test.dart
new file mode 100644
index 0000000..fe72721
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_after_sync_error_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+doThrow() {
+  throw "oh no"; // Line 13.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtExit,
+  (Isolate isolate) async {
+    await isolate.reload();
+    expect(isolate.error, isNotNull);
+    expect(isolate.error.message.contains('oh no'), isTrue);
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    pause_on_exit: true, testeeConcurrent: doThrow);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_group_memory_usage.dart b/runtime/observatory_2/tests/service_2/get_isolate_group_memory_usage.dart
new file mode 100644
index 0000000..b5559ba
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_group_memory_usage.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': vm.isolateGroups.first.id,
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('MemoryUsage'));
+    expect(result['heapUsage'], isPositive);
+    expect(result['heapCapacity'], isPositive);
+    expect(result['externalUsage'], isPositive);
+  },
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "getIsolateGroupMemoryUsage: invalid 'isolateGroupId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate group id, not found.
+  (VM vm) async {
+    final params = {
+      'isolateGroupId': 'isolateGroups/9999999999',
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Expired'));
+    expect(result['valueAsString'], equals('<expired>'));
+  },
+
+  // isolate id was passed instead of isolate group id.
+  (VM vm) async {
+    final params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    final result =
+        await vm.invokeRpcNoUpgrade('getIsolateGroupMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Expired'));
+    expect(result['valueAsString'], equals('<expired>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart
new file mode 100644
index 0000000..f09eb04
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_isolate_rpc_test.dart
@@ -0,0 +1,64 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var params = {
+      'isolateId': vm.isolates.first.id,
+    };
+    var result = await vm.invokeRpcNoUpgrade('getIsolate', params);
+    expect(result['type'], equals('Isolate'));
+    expect(result['id'], startsWith('isolates/'));
+    expect(result['number'], isA<String>());
+    expect(result['isSystemIsolate'], isFalse);
+    expect(result['_originNumber'], equals(result['number']));
+    expect(result['startTime'], isPositive);
+    expect(result['livePorts'], isPositive);
+    expect(result['pauseOnExit'], isFalse);
+    expect(result['pauseEvent']['type'], equals('Event'));
+    expect(result['error'], isNull);
+    expect(result['_numZoneHandles'], isPositive);
+    expect(result['_numScopedHandles'], isPositive);
+    expect(result['rootLib']['type'], equals('@Library'));
+    expect(result['libraries'].length, isPositive);
+    expect(result['libraries'][0]['type'], equals('@Library'));
+    expect(result['breakpoints'].length, isZero);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+  },
+
+  (VM vm) async {
+    var params = {
+      'isolateId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getIsolate', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getIsolate: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VM vm) async {
+    var params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    var result = await vm.invokeRpcNoUpgrade('getIsolate', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Collected'));
+    expect(result['valueAsString'], equals('<collected>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_memory_usage.dart b/runtime/observatory_2/tests/service_2/get_memory_usage.dart
new file mode 100644
index 0000000..9a8eff4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_memory_usage.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var params = {
+      'isolateId': vm.isolates.first.id,
+    };
+    var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+    expect(result['type'], equals('MemoryUsage'));
+    expect(result['heapUsage'], isPositive);
+    expect(result['heapCapacity'], isPositive);
+    expect(result['externalUsage'], isPositive);
+  },
+  (VM vm) async {
+    var params = {
+      'isolateId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getMemoryUsage: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VM vm) async {
+    var params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    var result = await vm.invokeRpcNoUpgrade('getMemoryUsage', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Collected'));
+    expect(result['valueAsString'], equals('<collected>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_native_allocation_samples_test.dart b/runtime/observatory_2/tests/service_2/get_native_allocation_samples_test.dart
new file mode 100644
index 0000000..ad7d7d5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_native_allocation_samples_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--profiler_native_memory
+
+import 'package:observatory_2/sample_profile.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+void verifyHelper(var root, bool exclusive) {
+  if (root.children.length == 0) {
+    return;
+  }
+
+  if (!(root is FunctionCallTreeNode)) {
+    print('${root.profileCode.code.name}');
+  } else {
+    print('${root.profileFunction.function.name}');
+  }
+
+  int inclusiveAllocations = 0;
+  int exclusiveAllocations = 0;
+
+  for (int i = 0; i < root.children.length; i++) {
+    inclusiveAllocations += root.children[i].inclusiveNativeAllocations;
+    exclusiveAllocations += root.children[i].exclusiveNativeAllocations;
+  }
+
+  int rootMemory;
+  if (exclusive) {
+    rootMemory = root.inclusiveNativeAllocations + exclusiveAllocations;
+  } else {
+    rootMemory =
+        root.inclusiveNativeAllocations - root.exclusiveNativeAllocations;
+  }
+
+  expect(inclusiveAllocations == rootMemory, isTrue);
+  for (int i = 0; i < root.children.length; i++) {
+    verifyHelper(root.children[i], exclusive);
+  }
+}
+
+void verify(var tree, bool exclusive) {
+  var node = tree.root;
+  expect(node, isNotNull);
+  expect(node.children.length >= 0, isTrue);
+
+  for (int i = 0; i < node.children.length; i++) {
+    verifyHelper(node.children[i], exclusive);
+  }
+}
+
+var tests = <VMTest>[
+  // Verify inclusive tries.
+  (VM vm) async {
+    var response =
+        await vm.invokeRpc('_getNativeAllocationSamples', {'_code': true});
+    SampleProfile cpuProfile = new SampleProfile();
+    await cpuProfile.load(vm, response);
+    var codeTree = cpuProfile.loadCodeTree(M.ProfileTreeDirection.inclusive);
+    var functionTree =
+        cpuProfile.loadFunctionTree(M.ProfileTreeDirection.inclusive);
+    verify(codeTree, false);
+    verify(functionTree, false);
+  },
+  // Verify exclusive tries.
+  (VM vm) async {
+    var response =
+        await vm.invokeRpc('_getNativeAllocationSamples', {'_code': true});
+    SampleProfile cpuProfile = new SampleProfile();
+    await cpuProfile.load(vm, response);
+    var codeTreeExclusive =
+        cpuProfile.loadCodeTree(M.ProfileTreeDirection.exclusive);
+    var functionTreeExclusive =
+        cpuProfile.loadFunctionTree(M.ProfileTreeDirection.exclusive);
+    verify(codeTreeExclusive, true);
+    verify(functionTreeExclusive, true);
+  }
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
new file mode 100644
index 0000000..36b9c61
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_object_rpc_test.dart
@@ -0,0 +1,1006 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library get_object_rpc_test;
+
+import 'dart:typed_data';
+import 'dart:convert' show base64Decode;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+class _DummyClass {
+  static var dummyVar = 11;
+  final List<String> dummyList = new List<String>.filled(20, null);
+  void dummyFunction() {}
+}
+
+class _DummySubClass extends _DummyClass {}
+
+void warmup() {
+  // Silence analyzer.
+  new _DummySubClass();
+  new _DummyClass().dummyFunction();
+}
+
+@pragma("vm:entry-point")
+getChattanooga() => "Chattanooga";
+
+@pragma("vm:entry-point")
+getList() => [3, 2, 1];
+
+@pragma("vm:entry-point")
+getMap() => {"x": 3, "y": 4, "z": 5};
+
+@pragma("vm:entry-point")
+getUint8List() => uint8List;
+
+@pragma("vm:entry-point")
+getUint64List() => uint64List;
+
+@pragma("vm:entry-point")
+getDummyClass() => new _DummyClass();
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var uint8List = new Uint8List.fromList([3, 2, 1]);
+var uint64List = new Uint64List.fromList([3, 2, 1]);
+
+var tests = <IsolateTest>[
+  // null object.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'objects/null',
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Null'));
+    expect(result['id'], equals('objects/null'));
+    expect(result['valueAsString'], equals('null'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('Null'));
+    expect(result['size'], isPositive);
+  },
+
+  // bool object.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'objects/bool-true',
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Bool'));
+    expect(result['id'], equals('objects/bool-true'));
+    expect(result['valueAsString'], equals('true'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('bool'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+  },
+
+  // int object.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'objects/int-123',
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Int'));
+    expect(result['_vmType'], equals('Smi'));
+    expect(result['id'], equals('objects/int-123'));
+    expect(result['valueAsString'], equals('123'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Smi'));
+    expect(result['size'], isZero);
+    expect(result['fields'], isEmpty);
+  },
+
+  // A string
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getChattanooga');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('String'));
+    expect(result['_vmType'], equals('String'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], equals('Chattanooga'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_OneByteString'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(11));
+    expect(result['offset'], isNull);
+    expect(result['count'], isNull);
+  },
+
+  // String prefix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getChattanooga');
+    var params = {
+      'objectId': evalResult['id'],
+      'count': 4,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('String'));
+    expect(result['_vmType'], equals('String'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], equals('Chat'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_OneByteString'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(11));
+    expect(result['offset'], isNull);
+    expect(result['count'], equals(4));
+  },
+
+  // String subrange.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getChattanooga');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 4,
+      'count': 6,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('String'));
+    expect(result['_vmType'], equals('String'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], equals('tanoog'));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_OneByteString'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(11));
+    expect(result['offset'], equals(4));
+    expect(result['count'], equals(6));
+  },
+
+  // String with wacky offset.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getChattanooga');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 100,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('String'));
+    expect(result['_vmType'], equals('String'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], equals(''));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_OneByteString'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(11));
+    expect(result['offset'], equals(11));
+    expect(result['count'], equals(0));
+  },
+
+  // A built-in List.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getList');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('List'));
+    expect(result['_vmType'], equals('GrowableObjectArray'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_GrowableList'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], isNull);
+    expect(result['elements'].length, equals(3));
+    expect(result['elements'][0]['type'], equals('@Instance'));
+    expect(result['elements'][0]['kind'], equals('Int'));
+    expect(result['elements'][0]['valueAsString'], equals('3'));
+    expect(result['elements'][1]['type'], equals('@Instance'));
+    expect(result['elements'][1]['kind'], equals('Int'));
+    expect(result['elements'][1]['valueAsString'], equals('2'));
+    expect(result['elements'][2]['type'], equals('@Instance'));
+    expect(result['elements'][2]['kind'], equals('Int'));
+    expect(result['elements'][2]['valueAsString'], equals('1'));
+  },
+
+  // List prefix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getList');
+    var params = {
+      'objectId': evalResult['id'],
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('List'));
+    expect(result['_vmType'], equals('GrowableObjectArray'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_GrowableList'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], equals(2));
+    expect(result['elements'].length, equals(2));
+    expect(result['elements'][0]['type'], equals('@Instance'));
+    expect(result['elements'][0]['kind'], equals('Int'));
+    expect(result['elements'][0]['valueAsString'], equals('3'));
+    expect(result['elements'][1]['type'], equals('@Instance'));
+    expect(result['elements'][1]['kind'], equals('Int'));
+    expect(result['elements'][1]['valueAsString'], equals('2'));
+  },
+
+  // List suffix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getList');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 2,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('List'));
+    expect(result['_vmType'], equals('GrowableObjectArray'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_GrowableList'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(2));
+    expect(result['count'], equals(1));
+    expect(result['elements'].length, equals(1));
+    expect(result['elements'][0]['type'], equals('@Instance'));
+    expect(result['elements'][0]['kind'], equals('Int'));
+    expect(result['elements'][0]['valueAsString'], equals('1'));
+  },
+
+  // List with wacky offset.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getList');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 100,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('List'));
+    expect(result['_vmType'], equals('GrowableObjectArray'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_GrowableList'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(3));
+    expect(result['count'], equals(0));
+    expect(result['elements'], isEmpty);
+  },
+
+  // A built-in Map.
+  (Isolate isolate) async {
+    // Call eval to get a Dart map.
+    var evalResult = await invoke(isolate, 'getMap');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Map'));
+    expect(result['_vmType'], equals('LinkedHashMap'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_InternalLinkedHashMap'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], isNull);
+    expect(result['associations'].length, equals(3));
+    expect(result['associations'][0]['key']['type'], equals('@Instance'));
+    expect(result['associations'][0]['key']['kind'], equals('String'));
+    expect(result['associations'][0]['key']['valueAsString'], equals('x'));
+    expect(result['associations'][0]['value']['type'], equals('@Instance'));
+    expect(result['associations'][0]['value']['kind'], equals('Int'));
+    expect(result['associations'][0]['value']['valueAsString'], equals('3'));
+    expect(result['associations'][1]['key']['type'], equals('@Instance'));
+    expect(result['associations'][1]['key']['kind'], equals('String'));
+    expect(result['associations'][1]['key']['valueAsString'], equals('y'));
+    expect(result['associations'][1]['value']['type'], equals('@Instance'));
+    expect(result['associations'][1]['value']['kind'], equals('Int'));
+    expect(result['associations'][1]['value']['valueAsString'], equals('4'));
+    expect(result['associations'][2]['key']['type'], equals('@Instance'));
+    expect(result['associations'][2]['key']['kind'], equals('String'));
+    expect(result['associations'][2]['key']['valueAsString'], equals('z'));
+    expect(result['associations'][2]['value']['type'], equals('@Instance'));
+    expect(result['associations'][2]['value']['kind'], equals('Int'));
+    expect(result['associations'][2]['value']['valueAsString'], equals('5'));
+  },
+
+  // Map prefix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart map.
+    var evalResult = await invoke(isolate, 'getMap');
+    var params = {
+      'objectId': evalResult['id'],
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Map'));
+    expect(result['_vmType'], equals('LinkedHashMap'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_InternalLinkedHashMap'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], equals(2));
+    expect(result['associations'].length, equals(2));
+    expect(result['associations'][0]['key']['type'], equals('@Instance'));
+    expect(result['associations'][0]['key']['kind'], equals('String'));
+    expect(result['associations'][0]['key']['valueAsString'], equals('x'));
+    expect(result['associations'][0]['value']['type'], equals('@Instance'));
+    expect(result['associations'][0]['value']['kind'], equals('Int'));
+    expect(result['associations'][0]['value']['valueAsString'], equals('3'));
+    expect(result['associations'][1]['key']['type'], equals('@Instance'));
+    expect(result['associations'][1]['key']['kind'], equals('String'));
+    expect(result['associations'][1]['key']['valueAsString'], equals('y'));
+    expect(result['associations'][1]['value']['type'], equals('@Instance'));
+    expect(result['associations'][1]['value']['kind'], equals('Int'));
+    expect(result['associations'][1]['value']['valueAsString'], equals('4'));
+  },
+
+  // Map suffix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart map.
+    var evalResult = await invoke(isolate, 'getMap');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 2,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Map'));
+    expect(result['_vmType'], equals('LinkedHashMap'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_InternalLinkedHashMap'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(2));
+    expect(result['count'], equals(1));
+    expect(result['associations'].length, equals(1));
+    expect(result['associations'][0]['key']['type'], equals('@Instance'));
+    expect(result['associations'][0]['key']['kind'], equals('String'));
+    expect(result['associations'][0]['key']['valueAsString'], equals('z'));
+    expect(result['associations'][0]['value']['type'], equals('@Instance'));
+    expect(result['associations'][0]['value']['kind'], equals('Int'));
+    expect(result['associations'][0]['value']['valueAsString'], equals('5'));
+  },
+
+  // Map with wacky offset
+  (Isolate isolate) async {
+    // Call eval to get a Dart map.
+    var evalResult = await invoke(isolate, 'getMap');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 100,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Map'));
+    expect(result['_vmType'], equals('LinkedHashMap'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_InternalLinkedHashMap'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(3));
+    expect(result['count'], equals(0));
+    expect(result['associations'], isEmpty);
+  },
+
+  // Uint8List.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint8List');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint8List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint8List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], isNull);
+    expect(result['bytes'], equals('AwIB'));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint8List().toString(), equals('[3, 2, 1]'));
+  },
+
+  // Uint8List prefix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint8List');
+    var params = {
+      'objectId': evalResult['id'],
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint8List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint8List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], equals(2));
+    expect(result['bytes'], equals('AwI='));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint8List().toString(), equals('[3, 2]'));
+  },
+
+  // Uint8List suffix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint8List');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 2,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint8List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint8List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(2));
+    expect(result['count'], equals(1));
+    expect(result['bytes'], equals('AQ=='));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint8List().toString(), equals('[1]'));
+  },
+
+  // Uint8List with wacky offset.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint8List');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 100,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint8List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint8List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(3));
+    expect(result['count'], equals(0));
+    expect(result['bytes'], equals(''));
+  },
+
+  // Uint64List.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint64List');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint64List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint64List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], isNull);
+    expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAAEAAAAAAAAA'));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint64List().toString(), equals('[3, 2, 1]'));
+  },
+
+  // Uint64List prefix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint64List');
+    var params = {
+      'objectId': evalResult['id'],
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint64List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint64List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], isNull);
+    expect(result['count'], equals(2));
+    expect(result['bytes'], equals('AwAAAAAAAAACAAAAAAAAAA=='));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint64List().toString(), equals('[3, 2]'));
+  },
+
+  // Uint64List suffix.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint64List');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 2,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint64List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint64List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(2));
+    expect(result['count'], equals(1));
+    expect(result['bytes'], equals('AQAAAAAAAAA='));
+    Uint8List bytes = base64Decode(result['bytes']);
+    expect(bytes.buffer.asUint64List().toString(), equals('[1]'));
+  },
+
+  // Uint64List with wacky offset.
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getUint64List');
+    var params = {
+      'objectId': evalResult['id'],
+      'offset': 100,
+      'count': 2,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Uint64List'));
+    expect(result['_vmType'], equals('TypedData'));
+    expect(result['id'], startsWith('objects/'));
+    expect(result['valueAsString'], isNull);
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Uint64List'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['length'], equals(3));
+    expect(result['offset'], equals(3));
+    expect(result['count'], equals(0));
+    expect(result['bytes'], equals(''));
+  },
+
+  // An expired object.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'objects/99999999',
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], startsWith('Expired'));
+    expect(result['valueAsString'], equals('<expired>'));
+    expect(result['class'], isNull);
+    expect(result['size'], isNull);
+  },
+
+  // library.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': isolate.rootLibrary.id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Library'));
+    expect(result['id'], startsWith('libraries/'));
+    expect(result['name'], equals('get_object_rpc_test'));
+    expect(result['uri'], startsWith('file:'));
+    expect(result['uri'], endsWith('get_object_rpc_test.dart'));
+    expect(result['debuggable'], equals(true));
+    expect(result['dependencies'].length, isPositive);
+    expect(result['dependencies'][0]['target']['type'], equals('@Library'));
+    expect(result['scripts'].length, isPositive);
+    expect(result['scripts'][0]['type'], equals('@Script'));
+    expect(result['variables'].length, isPositive);
+    expect(result['variables'][0]['type'], equals('@Field'));
+    expect(result['functions'].length, isPositive);
+    expect(result['functions'][0]['type'], equals('@Function'));
+    expect(result['classes'].length, isPositive);
+    expect(result['classes'][0]['type'], equals('@Class'));
+  },
+
+  // invalid library.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'libraries/9999999',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "getObject: invalid 'objectId' parameter: libraries/9999999");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // script.
+  (Isolate isolate) async {
+    // Get the library first.
+    var params = {
+      'objectId': isolate.rootLibrary.id,
+    };
+    var libResult = await isolate.invokeRpcNoUpgrade('getObject', params);
+    // Get the first script.
+    params = {
+      'objectId': libResult['scripts'][0]['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Script'));
+    expect(result['id'], startsWith('libraries/'));
+    expect(result['uri'], startsWith('file:'));
+    expect(result['uri'], endsWith('get_object_rpc_test.dart'));
+    expect(result['_kind'], equals('kernel'));
+    expect(result['library']['type'], equals('@Library'));
+    expect(result['source'], startsWith('// Copyright (c)'));
+    expect(result['tokenPosTable'].length, isPositive);
+    expect(result['tokenPosTable'][0], isA<List>());
+    expect(result['tokenPosTable'][0].length, isPositive);
+    expect(result['tokenPosTable'][0][0], isA<int>());
+  },
+
+  // invalid script.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'scripts/9999999',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "getObject: invalid 'objectId' parameter: scripts/9999999");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // class
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var params = {
+      'objectId': evalResult['class']['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Class'));
+    expect(result['id'], startsWith('classes/'));
+    expect(result['name'], equals('_DummyClass'));
+    expect(result['_vmName'], startsWith('_DummyClass@'));
+    expect(result['abstract'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['_finalized'], equals(true));
+    expect(result['_implemented'], equals(false));
+    expect(result['_patch'], equals(false));
+    expect(result['library']['type'], equals('@Library'));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['super']['type'], equals('@Class'));
+    expect(result['interfaces'].length, isZero);
+    expect(result['fields'].length, isPositive);
+    expect(result['fields'][0]['type'], equals('@Field'));
+    expect(result['functions'].length, isPositive);
+    expect(result['functions'][0]['type'], equals('@Function'));
+    expect(result['subclasses'].length, isPositive);
+    expect(result['subclasses'][0]['type'], equals('@Class'));
+  },
+
+  // invalid class.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'classes/9999999',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "getObject: invalid 'objectId' parameter: classes/9999999");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // type.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/types/0";
+    var params = {
+      'objectId': id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('Type'));
+    expect(result['id'], equals(id));
+    expect(result['class']['type'], equals('@Class'));
+    expect(result['class']['name'], equals('_Type'));
+    expect(result['size'], isPositive);
+    expect(result['fields'], isEmpty);
+    expect(result['typeClass']['type'], equals('@Class'));
+    expect(result['typeClass']['name'], equals('_DummyClass'));
+  },
+
+  // invalid type.
+  (Isolate isolate) async {
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/types/9999999";
+    var params = {
+      'objectId': id,
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message, startsWith("getObject: invalid 'objectId' parameter: "));
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/functions/dummyFunction";
+    var params = {
+      'objectId': id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Function'));
+    expect(result['id'], equals(id));
+    expect(result['name'], equals('dummyFunction'));
+    expect(result['_kind'], equals('RegularFunction'));
+    expect(result['static'], equals(false));
+    expect(result['const'], equals(false));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['code']['type'], equals('@Code'));
+    expect(result['_optimizable'], equals(true));
+    expect(result['_inlinable'], equals(true));
+    expect(result['_usageCounter'], isPositive);
+    expect(result['_optimizedCallSiteCount'], isZero);
+    expect(result['_deoptimizations'], isZero);
+  },
+
+  // invalid function.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/functions/invalid";
+    var params = {
+      'objectId': id,
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message, startsWith("getObject: invalid 'objectId' parameter: "));
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // field
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/fields/dummyVar";
+    var params = {
+      'objectId': id,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Field'));
+    expect(result['id'], equals(id));
+    expect(result['name'], equals('dummyVar'));
+    expect(result['const'], equals(false));
+    expect(result['static'], equals(true));
+    expect(result['final'], equals(false));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['staticValue']['valueAsString'], equals('11'));
+    expect(result['_guardNullable'], isNotNull);
+    expect(result['_guardClass'], isNotNull);
+    expect(result['_guardLength'], isNotNull);
+  },
+
+  // field with guards
+  (Isolate isolate) async {
+    var result = await isolate.vm.invokeRpcNoUpgrade('getFlagList', {});
+    var use_field_guards = false;
+    for (var flag in result['flags']) {
+      if (flag['name'] == 'use_field_guards') {
+        use_field_guards = flag['valueAsString'] == 'true';
+        break;
+      }
+    }
+    if (!use_field_guards) {
+      return; // skip the test if guards are not enabled
+    }
+
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/fields/dummyList";
+    var params = {
+      'objectId': id,
+    };
+    result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Field'));
+    expect(result['id'], equals(id));
+    expect(result['name'], equals('dummyList'));
+    expect(result['const'], equals(false));
+    expect(result['static'], equals(false));
+    expect(result['final'], equals(true));
+    expect(result['location']['type'], equals('SourceLocation'));
+    expect(result['_guardNullable'], isNotNull);
+    expect(result['_guardClass'], isNotNull);
+    expect(result['_guardLength'], equals('20'));
+  },
+
+  // invalid field.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var id = "${evalResult['class']['id']}/fields/mythicalField";
+    var params = {
+      'objectId': id,
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message, startsWith("getObject: invalid 'objectId' parameter: "));
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // code.
+  (Isolate isolate) async {
+    // Call eval to get a class id.
+    var evalResult = await invoke(isolate, 'getDummyClass');
+    var funcId = "${evalResult['class']['id']}/functions/dummyFunction";
+    var params = {
+      'objectId': funcId,
+    };
+    var funcResult = await isolate.invokeRpcNoUpgrade('getObject', params);
+    params = {
+      'objectId': funcResult['code']['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    expect(result['type'], equals('Code'));
+    expect(result['name'], endsWith('_DummyClass.dummyFunction'));
+    expect(result['_vmName'], endsWith('dummyFunction'));
+    expect(result['kind'], equals('Dart'));
+    expect(result['_optimized'], isA<bool>());
+    expect(result['function']['type'], equals('@Function'));
+    expect(result['_startAddress'], isA<String>());
+    expect(result['_endAddress'], isA<String>());
+    expect(result['_objectPool'], isNotNull);
+    expect(result['_disassembly'], isNotNull);
+    expect(result['_descriptors'], isNotNull);
+    expect(result['_inlinedFunctions'], anyOf([isNull, isA<List>()]));
+    expect(result['_inlinedIntervals'], anyOf([isNull, isA<List>()]));
+  },
+
+  // invalid code.
+  (Isolate isolate) async {
+    var params = {
+      'objectId': 'code/0',
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getObject', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getObject: invalid 'objectId' parameter: code/0");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);
diff --git a/runtime/observatory_2/tests/service_2/get_object_store_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_object_store_rpc_test.dart
new file mode 100644
index 0000000..616c5ab
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_object_store_rpc_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void testeeMain() {}
+
+bool isClosureFunctionsList(NamedField field) {
+  return field.name == 'closure_functions_';
+}
+
+var tests = <IsolateTest>[
+// Get object_store.
+  (Isolate isolate) async {
+    var object_store = await isolate.getObjectStore();
+    expect(object_store.runtimeType, equals(ObjectStore));
+    // Sanity check.
+    expect(object_store.fields.length, greaterThanOrEqualTo(1));
+    // Checking Closures.
+    var single = object_store.fields.singleWhere(isClosureFunctionsList);
+    expect(single, isNotNull);
+    var value = single.value as Instance;
+    expect(value.isList, isTrue);
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests, testeeBefore: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/get_ports_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_ports_rpc_test.dart
new file mode 100644
index 0000000..be65e05
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_ports_rpc_test.dart
@@ -0,0 +1,53 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library get_ports_rpc_test;
+
+import 'dart:isolate' hide Isolate;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var port1;
+var port2;
+
+void warmup() {
+  port1 = new RawReceivePort(null);
+  port2 = new RawReceivePort((_) {});
+}
+
+int countHandlerMatches(ports, matcher) {
+  var matches = 0;
+  for (var port in ports) {
+    if (matcher(port['handler'])) {
+      matches++;
+    }
+  }
+  return matches;
+}
+
+bool nullMatcher(handler) {
+  return handler.isNull;
+}
+
+bool closureMatcher(handler) {
+  return handler.isClosure;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    dynamic result = await isolate.invokeRpc('_getPorts', {});
+    expect(result['type'], equals('_Ports'));
+    expect(result['ports'], isList);
+    var ports = result['ports'];
+    // There are at least two ports: the two created in warm up. Some OSes
+    // will have other ports open but we do not try and test for these.
+    expect(ports.length, greaterThanOrEqualTo(2));
+    expect(countHandlerMatches(ports, nullMatcher), greaterThanOrEqualTo(1));
+    expect(countHandlerMatches(ports, closureMatcher), greaterThanOrEqualTo(1));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);
diff --git a/runtime/observatory_2/tests/service_2/get_process_memory_usage_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_process_memory_usage_rpc_test.dart
new file mode 100644
index 0000000..efd056e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_process_memory_usage_rpc_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade("getProcessMemoryUsage", {});
+    expect(result['type'], equals('ProcessMemoryUsage'));
+    checkProcessMemoryItem(item) {
+      expect(item['name'], isA<String>());
+      expect(item['description'], isA<String>());
+      expect(item['size'], isA<int>());
+      expect(item['size'], greaterThanOrEqualTo(0));
+      for (var child in item['children']) {
+        checkProcessMemoryItem(child);
+      }
+    }
+
+    checkProcessMemoryItem(result['root']);
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_retained_size_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_retained_size_rpc_test.dart
new file mode 100644
index 0000000..edc5c78
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_retained_size_rpc_test.dart
@@ -0,0 +1,77 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+class _TestClass {
+  _TestClass(this.x, this.y);
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+@pragma("vm:entry-point")
+var myVar;
+
+@pragma("vm:entry-point")
+invoke1() => myVar = new _TestClass(null, null);
+
+@pragma("vm:entry-point")
+invoke2() => myVar = new _TestClass(new _TestClass(null, null), null);
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    // One instance of _TestClass retained.
+    var evalResult = await invoke(isolate, 'invoke1');
+    var params = {
+      'targetId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('_getRetainedSize', params);
+    expect(result['type'], equals('@Instance'));
+    expect(result['kind'], equals('Int'));
+    int value1 = int.parse(result['valueAsString']);
+    expect(value1, isPositive);
+
+    // Two instances of _TestClass retained.
+    evalResult = await invoke(isolate, 'invoke2');
+    params = {
+      'targetId': evalResult['id'],
+    };
+    result = await isolate.invokeRpcNoUpgrade('_getRetainedSize', params);
+    expect(result['type'], equals('@Instance'));
+    expect(result['kind'], equals('Int'));
+    int value2 = int.parse(result['valueAsString']);
+    expect(value2, isPositive);
+
+    // Size has doubled.
+    expect(value2, equals(2 * value1));
+
+    // Get the retained size for class _TestClass.
+    params = {
+      'targetId': evalResult['class']['id'],
+    };
+    result = await isolate.invokeRpcNoUpgrade('_getRetainedSize', params);
+    expect(result['type'], equals('@Instance'));
+    expect(result['kind'], equals('Int'));
+    int value3 = int.parse(result['valueAsString']);
+    expect(value3, isPositive);
+    expect(value3, equals(value2));
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_retaining_path_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_retaining_path_rpc_test.dart
new file mode 100644
index 0000000..2bbc008
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_retaining_path_rpc_test.dart
@@ -0,0 +1,211 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+class _TestClass {
+  _TestClass();
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+var target1 = new _TestClass();
+var target2 = new _TestClass();
+var target3 = new _TestClass();
+var target4 = new _TestClass();
+var target5 = new _TestClass();
+@pragma("vm:entry-point") // Prevent obfuscation
+var globalObject = new _TestClass();
+@pragma("vm:entry-point") // Prevent obfuscation
+var globalList = new List(100);
+@pragma("vm:entry-point") // Prevent obfuscation
+var globalMap1 = new Map();
+@pragma("vm:entry-point") // Prevent obfuscation
+var globalMap2 = new Map();
+
+void warmup() {
+  globalObject.x = target1;
+  globalObject.y = target2;
+  globalList[12] = target3;
+  globalMap1['key'] = target4;
+  globalMap2[target5] = 'value';
+}
+
+@pragma("vm:entry-point")
+getGlobalObject() => globalObject;
+
+@pragma("vm:entry-point")
+takeTarget1() {
+  var tmp = target1;
+  target1 = null;
+  return tmp;
+}
+
+@pragma("vm:entry-point")
+takeTarget2() {
+  var tmp = target2;
+  target2 = null;
+  return tmp;
+}
+
+@pragma("vm:entry-point")
+takeTarget3() {
+  var tmp = target3;
+  target3 = null;
+  return tmp;
+}
+
+@pragma("vm:entry-point")
+takeTarget4() {
+  var tmp = target4;
+  target4 = null;
+  return tmp;
+}
+
+@pragma("vm:entry-point")
+takeTarget5() {
+  var tmp = target5;
+  target5 = null;
+  return tmp;
+}
+
+@pragma("vm:entry-point")
+getTrue() => true;
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var tests = <IsolateTest>[
+  // simple path
+  (Isolate isolate) async {
+    var obj = await invoke(isolate, 'getGlobalObject');
+    var params = {
+      'targetId': obj['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(2));
+    expect(result['elements'][1]['value']['name'], equals('globalObject'));
+  },
+
+  // missing limit.
+  (Isolate isolate) async {
+    var obj = await invoke(isolate, 'getGlobalObject');
+    var params = {
+      'targetId': obj['id'],
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.data['details'],
+          "getRetainingPath expects the \'limit\' parameter");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  (Isolate isolate) async {
+    var target1 = await invoke(isolate, 'takeTarget1');
+    var params = {
+      'targetId': target1['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
+    expect(result['elements'][1]['parentField'], equals('x'));
+    expect(result['elements'][2]['value']['name'], equals('globalObject'));
+  },
+
+  (Isolate isolate) async {
+    var target2 = await invoke(isolate, 'takeTarget2');
+    var params = {
+      'targetId': target2['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
+    expect(result['elements'][1]['parentField'], equals('y'));
+    expect(result['elements'][2]['value']['name'], equals('globalObject'));
+  },
+
+  (Isolate isolate) async {
+    var target3 = await invoke(isolate, 'takeTarget3');
+    var params = {
+      'targetId': target3['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
+    expect(result['elements'][1]['parentListIndex'], equals(12));
+    expect(result['elements'][2]['value']['name'], equals('globalList'));
+  },
+
+  (Isolate isolate) async {
+    var target4 = await invoke(isolate, 'takeTarget4');
+    var params = {
+      'targetId': target4['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['gcRootType'], 'user global');
+    expect(result['elements'].length, equals(3));
+    expect(
+        result['elements'][1]['parentMapKey']['valueAsString'], equals('key'));
+    expect(result['elements'][2]['value']['name'], equals('globalMap1'));
+  },
+
+  (Isolate isolate) async {
+    var target5 = await invoke(isolate, 'takeTarget5');
+    var params = {
+      'targetId': target5['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['elements'].length, equals(3));
+    expect(result['elements'][1]['parentMapKey']['class']['name'],
+        equals('_TestClass'));
+    expect(result['elements'][2]['value']['name'], equals('globalMap2'));
+  },
+
+  // object store
+  (Isolate isolate) async {
+    var obj = await invoke(isolate, 'getTrue');
+    var params = {
+      'targetId': obj['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(
+        result['gcRootType'] == 'class table' ||
+            result['gcRootType'] == 'isolate_object store',
+        true);
+    expect(result['elements'].length, 0);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);
diff --git a/runtime/observatory_2/tests/service_2/get_scripts_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_scripts_rpc_test.dart
new file mode 100644
index 0000000..e778135
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_scripts_rpc_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var params = {
+      'isolateId': vm.isolates.first.id,
+    };
+    var result = await vm.invokeRpcNoUpgrade('getScripts', params);
+    expect(result['type'], equals('ScriptList'));
+    expect(result['scripts'].length, isPositive);
+    expect(result['scripts'][0]['type'], equals('@Script'));
+  },
+
+  (VM vm) async {
+    var params = {
+      'isolateId': 'badid',
+    };
+    bool caughtException;
+    try {
+      await vm.invokeRpcNoUpgrade('getScripts', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message, "getScripts: invalid 'isolateId' parameter: badid");
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Plausible isolate id, not found.
+  (VM vm) async {
+    var params = {
+      'isolateId': 'isolates/9999999999',
+    };
+    var result = await vm.invokeRpcNoUpgrade('getScripts', params);
+    expect(result['type'], equals('Sentinel'));
+    expect(result['kind'], equals('Collected'));
+    expect(result['valueAsString'], equals('<collected>'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_source_report_test.dart b/runtime/observatory_2/tests/service_2/get_source_report_test.dart
new file mode 100644
index 0000000..984de51
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_source_report_test.dart
@@ -0,0 +1,199 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+
+int globalVar = 100;
+
+class MyClass {
+  static void myFunction(int value) {
+    if (value < 0) {
+      print("negative");
+    } else {
+      print("positive");
+    }
+    debugger();
+  }
+
+  static void otherFunction(int value) {
+    if (value < 0) {
+      print("otherFunction <");
+    } else {
+      print("otherFunction >=");
+    }
+  }
+}
+
+void testFunction() {
+  MyClass.otherFunction(-100);
+  MyClass.myFunction(10000);
+}
+
+class MyConstClass {
+  const MyConstClass();
+  static const MyConstClass instance = null ?? const MyConstClass();
+
+  void foo() {
+    debugger();
+  }
+}
+
+void testFunction2() {
+  MyConstClass.instance.foo();
+}
+
+bool allRangesCompiled(coverage) {
+  for (int i = 0; i < coverage['ranges'].length; i++) {
+    if (!coverage['ranges'][i]['compiled']) {
+      return false;
+    }
+  }
+  return true;
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(2));
+    expect(stack['frames'][0].function.name, equals('myFunction'));
+    expect(stack['frames'][0].function.dartOwner.name, equals('MyClass'));
+
+    var func = stack['frames'][0].function;
+    expect(func.name, equals('myFunction'));
+    await func.load();
+
+    var expectedRange = {
+      'scriptIndex': 0,
+      'startPos': 432,
+      'endPos': 576,
+      'compiled': true,
+      'coverage': {
+        'hits': [432, 482, 533, 562],
+        'misses': [495],
+      }
+    };
+
+    // Full script
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id
+    };
+    var coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    final numRanges = coverage['ranges'].length;
+    expect(coverage['type'], equals('SourceReport'));
+
+    expect(numRanges, equals(12));
+    expect(coverage['ranges'][0], equals(expectedRange));
+    expect(coverage['scripts'].length, 1);
+    expect(
+        coverage['scripts'][0]['uri'], endsWith('get_source_report_test.dart'));
+    expect(allRangesCompiled(coverage), isFalse);
+
+    // Force compilation.
+    params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id,
+      'forceCompile': true
+    };
+    coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(coverage['type'], equals('SourceReport'));
+    expect(coverage['ranges'].length, numRanges);
+    expect(allRangesCompiled(coverage), isTrue);
+
+    // One function
+    params = {
+      'reports': ['Coverage'],
+      'scriptId': func.location.script.id,
+      'tokenPos': func.location.tokenPos,
+      'endTokenPos': func.location.endTokenPos
+    };
+    coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(coverage['type'], equals('SourceReport'));
+    expect(coverage['ranges'].length, 1);
+    expect(coverage['ranges'][0], equals(expectedRange));
+    expect(coverage['scripts'].length, 1);
+    expect(
+        coverage['scripts'][0]['uri'], endsWith('get_source_report_test.dart'));
+
+    // Full isolate
+    params = {
+      'reports': ['Coverage']
+    };
+    coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(coverage['type'], equals('SourceReport'));
+    expect(coverage['ranges'].length, greaterThan(1));
+    expect(coverage['scripts'].length, greaterThan(1));
+
+    // Full isolate
+    params = {
+      'reports': ['Coverage'],
+      'forceCompile': true
+    };
+    coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(coverage['type'], equals('SourceReport'));
+    expect(coverage['ranges'].length, greaterThan(1));
+    expect(coverage['scripts'].length, greaterThan(1));
+
+    // Multiple reports (make sure enum list parameter parsing works).
+    params = {
+      'reports': ['_CallSites', 'Coverage', 'PossibleBreakpoints'],
+      'scriptId': func.location.script.id,
+      'tokenPos': func.location.tokenPos,
+      'endTokenPos': func.location.endTokenPos
+    };
+    coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    expect(coverage['type'], equals('SourceReport'));
+    expect(coverage['ranges'].length, 1);
+    var range = coverage['ranges'][0];
+    expect(range.containsKey('callSites'), isTrue);
+    expect(range.containsKey('coverage'), isTrue);
+    expect(range.containsKey('possibleBreakpoints'), isTrue);
+
+    // missing scriptId with tokenPos.
+    bool caughtException = false;
+    try {
+      params = {
+        'reports': ['Coverage'],
+        'tokenPos': func.location.tokenPos
+      };
+      coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message,
+          "getSourceReport: the 'tokenPos' parameter requires the "
+          "\'scriptId\' parameter");
+    }
+    expect(caughtException, isTrue);
+
+    // missing scriptId with endTokenPos.
+    caughtException = false;
+    try {
+      params = {
+        'reports': ['Coverage'],
+        'endTokenPos': func.location.endTokenPos
+      };
+      coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message,
+          "getSourceReport: the 'endTokenPos' parameter requires the "
+          "\'scriptId\' parameter");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib1.dart b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib1.dart
new file mode 100644
index 0000000..c9d5a02
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib1.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+mixin A {
+  void foo() {
+    print('foo');
+  }
+}
+
+mixin B {
+  void bar() {
+    print('bar');
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib2.dart b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib2.dart
new file mode 100644
index 0000000..616df73
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "get_source_report_with_mixin_lib1.dart";
+
+class Test1 with A {}
diff --git a/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib3.dart b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib3.dart
new file mode 100644
index 0000000..c9f49a9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_lib3.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "get_source_report_with_mixin_lib1.dart";
+
+class Test2 with B {}
diff --git a/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_test.dart b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_test.dart
new file mode 100644
index 0000000..281b7b7
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_source_report_with_mixin_test.dart
@@ -0,0 +1,98 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+
+import "get_source_report_with_mixin_lib2.dart";
+import "get_source_report_with_mixin_lib3.dart";
+
+const String lib1Filename = "get_source_report_with_mixin_lib1";
+const String lib3Filename = "get_source_report_with_mixin_lib3";
+
+void testFunction() {
+  final Test1 test1 = new Test1();
+  test1.foo();
+  final Test2 test2 = new Test2();
+  test2.bar();
+  debugger();
+  print("done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    final stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    final List<Script> scripts = await isolate.getScripts();
+    Script foundScript;
+    for (Script script in scripts) {
+      if (script.uri.contains(lib1Filename)) {
+        foundScript = script;
+        break;
+      }
+    }
+
+    Set<int> hits;
+    {
+      // Get report for everything; then collect for lib1.
+      final Map<String, Object> params = {
+        'reports': ['Coverage'],
+      };
+      final coverage =
+          await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+      hits = getHitsForLib1(coverage, lib1Filename);
+      expect(hits.length, greaterThanOrEqualTo(2));
+      print(hits);
+    }
+    {
+      // Now get report for the lib1 only.
+      final Map<String, Object> params = {
+        'reports': ['Coverage'],
+        'scriptId': foundScript.id
+      };
+      final coverage =
+          await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+      final Set<int> localHits = getHitsForLib1(coverage, lib1Filename);
+      expect(localHits.length, equals(hits.length));
+      expect(hits.toList()..sort(), equals(localHits.toList()..sort()));
+      print(localHits);
+    }
+  },
+];
+
+Set<int> getHitsForLib1(Map coverage, String uriContains) {
+  final List scripts = coverage["scripts"];
+  final Set<int> scriptIdsWanted = {};
+  for (int i = 0; i < scripts.length; i++) {
+    final Map script = scripts[i];
+    final String scriptUri = script["uri"];
+    if (scriptUri.contains(uriContains)) {
+      scriptIdsWanted.add(i);
+    }
+  }
+  final List ranges = coverage["ranges"];
+  final Set<int> hits = {};
+  for (int i = 0; i < ranges.length; i++) {
+    final Map range = ranges[i];
+    if (scriptIdsWanted.contains(range["scriptIndex"])) {
+      if (range["coverage"] != null) {
+        for (int hit in range["coverage"]["hits"]) {
+          hits.add(hit);
+        }
+      }
+    }
+  }
+  return hits;
+}
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/get_stack_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_stack_rpc_test.dart
new file mode 100644
index 0000000..887cb1b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_stack_rpc_test.dart
@@ -0,0 +1,92 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:isolate' as isolate;
+import 'dart:developer' as developer;
+
+int counter = 0;
+const stoppedAtLine = 24;
+var port = new isolate.RawReceivePort(msgHandler);
+
+// This name is used in a test below.
+void msgHandler(_) {}
+
+void periodicTask(_) {
+  port.sendPort.send(34);
+  developer.debugger(message: "fo", when: true); // We will be at the next line.
+  counter++;
+  if (counter % 300 == 0) {
+    print('counter = $counter');
+  }
+}
+
+void startTimer() {
+  new Timer.periodic(const Duration(milliseconds: 10), periodicTask);
+}
+
+var tests = <IsolateTest>[
+// Initial data fetch and verify we've hit the breakpoint.
+  (Isolate isolate) async {
+    await isolate.rootLibrary.load();
+    var script = isolate.rootLibrary.scripts[0];
+    await script.load();
+    await hasStoppedAtBreakpoint(isolate);
+    // Sanity check.
+    expect(isolate.pauseEvent is M.PauseBreakpointEvent, isTrue);
+  },
+
+// Get stack
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+
+    // Sanity check.
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    Script script = stack['frames'][0].location.script;
+    expect(script.tokenToLine(stack['frames'][0].location.tokenPos),
+        equals(stoppedAtLine));
+
+    // Iterate over frames.
+    var frameDepth = 0;
+    for (var frame in stack['frames']) {
+      print('checking frame $frameDepth');
+      expect(frame.type, equals('Frame'));
+      expect(frame.index, equals(frameDepth++));
+      expect(frame.code.type, equals('Code'));
+      expect(frame.function.type, equals('Function'));
+      expect(frame.location.type, equals('SourceLocation'));
+    }
+
+    // Sanity check.
+    expect(stack['messages'].length, greaterThanOrEqualTo(1));
+
+    // Iterate over messages.
+    var messageDepth = 0;
+    // objectId of message to be handled by msgHandler.
+    var msgHandlerObjectId;
+    for (var message in stack['messages']) {
+      print('checking message $messageDepth');
+      expect(message.index, equals(messageDepth++));
+      expect(message.size, greaterThanOrEqualTo(0));
+      expect(message.handler.type, equals('Function'));
+      expect(message.location.type, equals('SourceLocation'));
+      if (message.handler.name.contains('msgHandler')) {
+        msgHandlerObjectId = message.messageObjectId;
+      }
+    }
+    expect(msgHandlerObjectId, isNotNull);
+
+    // Get object.
+    Instance object = await isolate.getObject(msgHandlerObjectId);
+    expect(object.valueAsString, equals('34'));
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: startTimer);
diff --git a/runtime/observatory_2/tests/service_2/get_supported_protocols_test.dart b/runtime/observatory_2/tests/service_2/get_supported_protocols_test.dart
new file mode 100644
index 0000000..d17583b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_supported_protocols_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <VMTest>[
+  (VM vm) async {
+    final result = await vm.invokeRpcNoUpgrade('getSupportedProtocols', {});
+    expect(result['type'], equals('ProtocolList'));
+    final List<Map> protocols =
+        result['protocols'].cast<Map<String, dynamic>>();
+    expect(protocols.length, useDds ? 2 : 1);
+
+    final expectedProtocols = <String>{
+      'VM Service',
+      if (useDds) 'DDS',
+    };
+
+    for (final protocol in protocols) {
+      final protocolName = protocol['protocolName'];
+      expect(expectedProtocols.contains(protocolName), isTrue);
+      expect(protocol['major'] > 0, isTrue);
+      expect(protocol['minor'] >= 0, isTrue);
+    }
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_user_level_retaining_path_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_user_level_retaining_path_rpc_test.dart
new file mode 100644
index 0000000..45c8941
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_user_level_retaining_path_rpc_test.dart
@@ -0,0 +1,78 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+class _TestClass {
+  _TestClass();
+  var x;
+  var y;
+}
+
+class _TestConst {
+  const _TestConst();
+}
+
+_TopLevelClosure() {}
+
+var x;
+var fn;
+
+void warmup() {
+  x = const _TestConst();
+  fn = _TopLevelClosure;
+}
+
+@pragma("vm:entry-point")
+getX() => x;
+
+@pragma("vm:entry-point")
+getFn() => fn;
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var tests = <IsolateTest>[
+  // Expect a simple path through variable x instead of long path filled
+  // with VM objects
+  (Isolate isolate) async {
+    var target1 = await invoke(isolate, 'getX');
+    var params = {
+      'targetId': target1['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['elements'].length, equals(2));
+    expect(
+        result['elements'][0]['value']['class']['name'], equals('_TestConst'));
+    expect(result['elements'][1]['value']['name'], equals('x'));
+  },
+
+  // Expect a simple path through variable fn instead of long path filled
+  // with VM objects
+  (Isolate isolate) async {
+    var target2 = await invoke(isolate, 'getFn');
+    var params = {
+      'targetId': target2['id'],
+      'limit': 100,
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getRetainingPath', params);
+    expect(result['type'], equals('RetainingPath'));
+    expect(result['elements'].length, equals(2));
+    expect(result['elements'][0]['value']['class']['name'], equals('_Closure'));
+    expect(result['elements'][1]['value']['name'], equals('fn'));
+  }
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: warmup);
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
new file mode 100644
index 0000000..468e979
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -0,0 +1,21 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('getVersion', {});
+    expect(result['type'], equals('Version'));
+    expect(result['major'], equals(3));
+    expect(result['minor'], equals(39));
+    expect(result['_privateMajor'], equals(0));
+    expect(result['_privateMinor'], equals(0));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart
new file mode 100644
index 0000000..6fff547
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_vm_rpc_test.dart
@@ -0,0 +1,32 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--vm-name=Walter
+
+import 'dart:io';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('getVM', {});
+    expect(result['type'], equals('VM'));
+    expect(result['name'], equals('Walter'));
+    expect(result['architectureBits'], isPositive);
+    expect(result['targetCPU'], isA<String>());
+    expect(result['hostCPU'], isA<String>());
+    expect(result['operatingSystem'], Platform.operatingSystem);
+    expect(result['version'], isA<String>());
+    expect(result['pid'], isA<int>());
+    expect(result['startTime'], isPositive);
+    expect(result['isolates'].length, isPositive);
+    expect(result['isolates'][0]['type'], equals('@Isolate'));
+    expect(result['isolateGroups'].length, isPositive);
+    expect(result['isolateGroups'][0]['type'], equals('@IsolateGroup'));
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_vm_timeline_micros_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_vm_timeline_micros_rpc_test.dart
new file mode 100644
index 0000000..7b849e6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_vm_timeline_micros_rpc_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    var result = await vm.invokeRpcNoUpgrade('getVMTimelineMicros', {});
+    expect(result['type'], equals('Timestamp'));
+    expect(result['timestamp'], isPositive);
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart
new file mode 100644
index 0000000..8dc5899
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_vm_timeline_rpc_test.dart
@@ -0,0 +1,193 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'dart:io';
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+primeTimeline() {
+  Timeline.startSync('apple');
+  Timeline.instantSync('ISYNC', arguments: {'fruit': 'banana'});
+  Timeline.finishSync();
+  TimelineTask parentTask = TimelineTask.withTaskId(42);
+  TimelineTask task = TimelineTask(parent: parentTask, filterKey: 'testFilter');
+  task.start('TASK1', arguments: {'task1-start-key': 'task1-start-value'});
+  task.instant('ITASK',
+      arguments: {'task1-instant-key': 'task1-instant-value'});
+  task.finish(arguments: {'task1-finish-key': 'task1-finish-value'});
+
+  Flow flow = Flow.begin(id: 123);
+  Timeline.startSync('peach', flow: flow);
+  Timeline.finishSync();
+  Timeline.startSync('watermelon', flow: Flow.step(flow.id));
+  Timeline.finishSync();
+  Timeline.startSync('pear', flow: Flow.end(flow.id));
+  Timeline.finishSync();
+}
+
+List filterForDartEvents(List events) {
+  return events.where((event) => event['cat'] == 'Dart').toList();
+}
+
+bool mapContains(Map map, Map submap) {
+  for (var key in submap.keys) {
+    if (map[key] != submap[key]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool eventsContains(List events, String phase, String name, [Map arguments]) {
+  for (Map event in events) {
+    if ((event['ph'] == phase) && (event['name'] == name)) {
+      if (arguments == null) {
+        return true;
+      } else if (mapContains(event['args'], arguments)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+int timeOrigin(List events) {
+  if (events.length == 0) {
+    return 0;
+  }
+  int smallest = events[0]['ts'];
+  for (var i = 0; i < events.length; i++) {
+    Map event = events[i];
+    if (event['ts'] < smallest) {
+      smallest = event['ts'];
+    }
+  }
+  return smallest;
+}
+
+int timeDuration(List events, int timeOrigin) {
+  if (events.length == 0) {
+    return 0;
+  }
+  int biggestDuration = events[0]['ts'] - timeOrigin;
+  for (var i = 0; i < events.length; i++) {
+    Map event = events[i];
+    int duration = event['ts'] - timeOrigin;
+    if (duration > biggestDuration) {
+      biggestDuration = duration;
+    }
+  }
+  return biggestDuration;
+}
+
+void allEventsHaveIsolateNumber(List events) {
+  for (Map event in events) {
+    if (event['ph'] == 'M') {
+      // Skip meta-data events.
+      continue;
+    }
+    if (event['name'] == 'Runnable' && event['ph'] == 'i') {
+      // Skip Runnable events which don't have an isolate.
+      continue;
+    }
+    if (event['cat'] == 'VM') {
+      // Skip VM category events which don't have an isolate.
+      continue;
+    }
+    if (event['cat'] == 'API') {
+      // Skip API category events which sometimes don't have an isolate.
+      continue;
+    }
+    if (event['cat'] == 'Embedder' &&
+        (event['name'] == 'DFE::ReadScript' ||
+            event['name'] == 'CreateIsolateGroupAndSetupHelper')) {
+      continue;
+    }
+    Map arguments = event['args'];
+    expect(arguments, isA<Map>());
+    expect(arguments['isolateGroupId'], isA<String>());
+    if (event['cat'] != 'GC') {
+      expect(arguments['isolateId'], isA<String>());
+    }
+  }
+}
+
+var tests = <VMTest>[
+  (VM vm) async {
+    Map result = await vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], equals('Timeline'));
+    expect(result['traceEvents'], isA<List>());
+    final int numEvents = result['traceEvents'].length;
+    List dartEvents = filterForDartEvents(result['traceEvents']);
+    expect(dartEvents.length, greaterThanOrEqualTo(11));
+    allEventsHaveIsolateNumber(dartEvents);
+    allEventsHaveIsolateNumber(result['traceEvents']);
+    expect(
+        eventsContains(dartEvents, 'i', 'ISYNC', {'fruit': 'banana'}), isTrue);
+    expect(eventsContains(dartEvents, 'B', 'apple'), isTrue);
+    expect(eventsContains(dartEvents, 'E', 'apple'), isTrue);
+    expect(
+        eventsContains(dartEvents, 'b', 'TASK1', {
+          'filterKey': 'testFilter',
+          'task1-start-key': 'task1-start-value',
+          'parentId': 42.toRadixString(16)
+        }),
+        isTrue);
+    expect(
+        eventsContains(dartEvents, 'e', 'TASK1', {
+          'filterKey': 'testFilter',
+          'task1-finish-key': 'task1-finish-value',
+        }),
+        isTrue);
+    expect(
+        eventsContains(dartEvents, 'n', 'ITASK', {
+          'filterKey': 'testFilter',
+          'task1-instant-key': 'task1-instant-value',
+        }),
+        isTrue);
+    expect(eventsContains(dartEvents, 'q', 'ITASK'), isFalse);
+    expect(eventsContains(dartEvents, 'B', 'peach'), isTrue);
+    expect(eventsContains(dartEvents, 'E', 'peach'), isTrue);
+    expect(eventsContains(dartEvents, 'B', 'watermelon'), isTrue);
+    expect(eventsContains(dartEvents, 'E', 'watermelon'), isTrue);
+    expect(eventsContains(dartEvents, 'B', 'pear'), isTrue);
+    expect(eventsContains(dartEvents, 'E', 'pear'), isTrue);
+    expect(eventsContains(dartEvents, 's', '123'), isTrue);
+    expect(eventsContains(dartEvents, 't', '123'), isTrue);
+    expect(eventsContains(dartEvents, 'f', '123'), isTrue);
+    // Calculate the time Window of Dart events.
+    int origin = timeOrigin(dartEvents);
+    int extent = timeDuration(dartEvents, origin);
+    // Query for the timeline with the time window for Dart events.
+    result = await vm.invokeRpcNoUpgrade('getVMTimeline',
+        {'timeOriginMicros': origin, 'timeExtentMicros': extent});
+    // Verify that we received fewer events than before.
+    expect(result['traceEvents'].length, lessThan(numEvents));
+    // Verify that we have the same number of Dart events.
+    List dartEvents2 = filterForDartEvents(result['traceEvents']);
+    expect(dartEvents2.length, dartEvents.length);
+  },
+];
+
+main(List<String> args) async {
+  // Running the subprocesses of this particular test in opt counter mode
+  // will cause it to be slow and cause many compilations.
+  //
+  // Together with "--complete-timeline" this will create a huge number of
+  // timeline events which can, on ia32, cause the process to hit OOM.
+  //
+  // So we filter out that particular argument.
+  final executableArgs = Platform.executableArguments
+      .where((String arg) => !arg.contains('optimization-counter-threshold'))
+      .toList();
+
+  await runVMTests(args, tests,
+      testeeBefore: primeTimeline,
+      extraArgs: ['--complete-timeline'],
+      executableArgs: executableArgs);
+}
diff --git a/runtime/observatory_2/tests/service_2/get_zone_memory_info_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_zone_memory_info_rpc_test.dart
new file mode 100644
index 0000000..dd1d671
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_zone_memory_info_rpc_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    // Just iterate over all the isolates to confirm they have
+    // the correct fields needed to examine zone memory usage.
+    for (Isolate isolate in new List.from(vm.isolates)) {
+      await isolate.reload();
+      expect(isolate.zoneHighWatermark, isA<int>());
+      expect(isolate.threads, isNotNull);
+      List<Thread> threads = isolate.threads;
+
+      for (Thread thread in threads) {
+        expect(thread.type, equals('_Thread'));
+        expect(thread.id, isNotNull);
+        expect(thread.kind, isNotNull);
+        expect(thread.zoneHighWatermark, isA<int>());
+        expect(thread.zoneCapacity, isA<int>());
+      }
+    }
+  },
+];
+
+main(args) async => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/http_auth_get_isolate_rpc_test.dart b/runtime/observatory_2/tests/service_2/http_auth_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..261fa26
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_auth_get_isolate_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/http_auth_get_vm_rpc_test.dart b/runtime/observatory_2/tests/service_2/http_auth_get_vm_rpc_test.dart
new file mode 100644
index 0000000..5484c5e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_auth_get_vm_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/http_enable_timeline_logging_service_test.dart b/runtime/observatory_2/tests/service_2/http_enable_timeline_logging_service_test.dart
new file mode 100644
index 0000000..1c1b0b0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_enable_timeline_logging_service_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const String kSetHttpEnableTimelineLogging =
+    'ext.dart.io.setHttpEnableTimelineLogging';
+const String kGetHttpEnableTimelineLogging =
+    'ext.dart.io.getHttpEnableTimelineLogging';
+Future<void> setup() async {}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    await isolate.load();
+    // Ensure all HTTP service extensions are registered.
+    expect(isolate.extensionRPCs.length, greaterThanOrEqualTo(2));
+    expect(
+        isolate.extensionRPCs.contains(kGetHttpEnableTimelineLogging), isTrue);
+    expect(
+        isolate.extensionRPCs.contains(kSetHttpEnableTimelineLogging), isTrue);
+  },
+  (Isolate isolate) async {
+    await isolate.load();
+    var response =
+        await isolate.invokeRpcNoUpgrade(kGetHttpEnableTimelineLogging, {});
+    expect(response['type'], 'HttpTimelineLoggingState');
+    expect(response['enabled'], false);
+
+    response = await isolate
+        .invokeRpcNoUpgrade(kSetHttpEnableTimelineLogging, {'enable': true});
+    expect(response['type'], 'Success');
+
+    response =
+        await isolate.invokeRpcNoUpgrade(kGetHttpEnableTimelineLogging, {});
+    expect(response['type'], 'HttpTimelineLoggingState');
+    expect(response['enabled'], true);
+
+    response = await isolate
+        .invokeRpcNoUpgrade(kSetHttpEnableTimelineLogging, {'enable': false});
+    expect(response['type'], 'Success');
+
+    response =
+        await isolate.invokeRpcNoUpgrade(kGetHttpEnableTimelineLogging, {});
+    expect(response['type'], 'HttpTimelineLoggingState');
+    expect(response['enabled'], false);
+  },
+  (Isolate isolate) async {
+    // Bad argument.
+    try {
+      await isolate
+          .invokeRpcNoUpgrade(kSetHttpEnableTimelineLogging, {'enable': 'foo'});
+    } catch (e) {/* expected */}
+    // Missing argument.
+    try {
+      await isolate.invokeRpcNoUpgrade(kSetHttpEnableTimelineLogging, {});
+    } catch (e) {/* expected */}
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: setup);
diff --git a/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_common.dart b/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_common.dart
new file mode 100644
index 0000000..84418d2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_common.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart' as S;
+import 'test_helper.dart';
+
+Future<String> getIsolateGroupId(
+    io.HttpClient httpClient, Uri serverUri) async {
+  // Build the request.
+  final pathSegments = <String>[]..addAll(serverUri.pathSegments);
+  const method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = serverUri.replace(pathSegments: pathSegments);
+  final request = await httpClient.getUrl(requestUri);
+  final Map response = await (await request.close())
+      .cast<List<int>>()
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+  final result = response['result'];
+  return result['isolateGroups'][0]['id'];
+}
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  Expect.isNotNull(info.serverUri);
+  final httpClient = new io.HttpClient();
+
+  // Build the request.
+  final params = <String, String>{
+    'isolateGroupId': await getIsolateGroupId(httpClient, info.serverUri),
+  };
+
+  const method = 'getIsolateGroup';
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri
+      .replace(pathSegments: pathSegments, queryParameters: params);
+
+  try {
+    final request = await httpClient.getUrl(requestUri);
+    final response = await request.close();
+    final Map jsonResponse = await response
+        .cast<List<int>>()
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    final result = jsonResponse['result'];
+    Expect.equals(result['type'], 'IsolateGroup');
+    Expect.isTrue(result['id'].startsWith('isolateGroups/'));
+    Expect.type<String>(result['number']);
+    Expect.isFalse(result['isSystemIsolateGroup']);
+    Expect.isTrue(result['isolates'].length > 0);
+    Expect.equals(result['isolates'][0]['type'], '@Isolate');
+  } catch (e) {
+    Expect.fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+  }
+];
diff --git a/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_test.dart b/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_test.dart
new file mode 100644
index 0000000..eb382b1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_isolate_group_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_isolate_group_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_common.dart b/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_common.dart
new file mode 100644
index 0000000..7f5c869
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_common.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart' as S;
+import 'test_helper.dart';
+
+Future<String> getIsolateId(io.HttpClient httpClient, Uri serverUri) async {
+  // Build the request.
+  final pathSegments = <String>[]..addAll(serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = serverUri.replace(pathSegments: pathSegments);
+  var request = await httpClient.getUrl(requestUri);
+  Map response = await (await request.close())
+      .cast<List<int>>()
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+  Map result = response['result'];
+  return result['isolates'][0]['id'];
+}
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  Expect.isNotNull(info.serverUri);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final params = <String, String>{
+    'isolateId': await getIsolateId(httpClient, info.serverUri),
+  };
+
+  String method = 'getIsolate';
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri
+      .replace(pathSegments: pathSegments, queryParameters: params);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .cast<List<int>>()
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    Expect.equals(result['type'], 'Isolate');
+    Expect.isTrue(result['id'].startsWith('isolates/'));
+    Expect.type<String>(result['number']);
+    Expect.equals(result['_originNumber'], result['number']);
+    Expect.isTrue(result['startTime'] > 0);
+    Expect.isTrue(result['livePorts'] > 0);
+    Expect.isFalse(result['pauseOnExit']);
+    Expect.equals(result['pauseEvent']['type'], 'Event');
+    Expect.isNull(result['error']);
+    Expect.isTrue(result['_numZoneHandles'] > 0);
+    Expect.isTrue(result['_numScopedHandles'] > 0);
+    Expect.equals(result['rootLib']['type'], '@Library');
+    Expect.isTrue(result['libraries'].length > 0);
+    Expect.equals(result['libraries'][0]['type'], '@Library');
+    Expect.equals(result['breakpoints'].length, 0);
+    Expect.equals(result['_heaps']['new']['type'], 'HeapSpace');
+    Expect.equals(result['_heaps']['old']['type'], 'HeapSpace');
+    Expect.equals(result['isolate_group']['type'], '@IsolateGroup');
+  } catch (e) {
+    Expect.fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+  }
+];
diff --git a/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_test.dart b/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..261fa26
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_isolate_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/http_get_vm_rpc_common.dart b/runtime/observatory_2/tests/service_2/http_get_vm_rpc_common.dart
new file mode 100644
index 0000000..f43b121
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_vm_rpc_common.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart' as S;
+import 'test_helper.dart';
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  Expect.isNotNull(info.serverUri);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri.replace(pathSegments: pathSegments);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .cast<List<int>>()
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    Expect.equals(result['type'], 'VM');
+    Expect.equals(result['name'], 'vm');
+    Expect.isTrue(result['architectureBits'] > 0);
+    Expect.type<String>(result['targetCPU']);
+    Expect.type<String>(result['hostCPU']);
+    Expect.type<String>(result['version']);
+    Expect.type<int>(result['pid']);
+    Expect.isTrue(result['startTime'] > 0);
+    Expect.isTrue(result['isolates'].length > 0);
+    Expect.equals(result['isolates'][0]['type'], '@Isolate');
+    Expect.isTrue(result['isolateGroups'].length > 0);
+    Expect.equals(result['isolateGroups'][0]['type'], '@IsolateGroup');
+  } catch (e) {
+    Expect.fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+  }
+];
diff --git a/runtime/observatory_2/tests/service_2/http_get_vm_rpc_test.dart b/runtime/observatory_2/tests/service_2/http_get_vm_rpc_test.dart
new file mode 100644
index 0000000..5484c5e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/http_get_vm_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/implicit_getter_setter_test.dart b/runtime/observatory_2/tests/service_2/implicit_getter_setter_test.dart
new file mode 100644
index 0000000..39115bc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/implicit_getter_setter_test.dart
@@ -0,0 +1,68 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library implicit_getter_setter_test;
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class A {
+  double field = 0.0;
+}
+
+script() {
+  for (int i = 0; i < 10; i++) {
+    new A();
+  }
+}
+
+Future testGetter(Isolate isolate) async {
+  Library rootLibrary = await isolate.rootLibrary.load();
+  expect(rootLibrary.classes.length, equals(1));
+  Class classA = await rootLibrary.classes[0].load();
+  expect(classA.name, equals('A'));
+  // Find getter.
+  ServiceFunction getterFunc;
+  for (ServiceFunction function in classA.functions) {
+    if (function.name == 'field') {
+      getterFunc = function;
+      break;
+    }
+  }
+  expect(getterFunc, isNotNull);
+  await getterFunc.load();
+  Field field = await getterFunc.field.load();
+  expect(field, isNotNull);
+  expect(field.name, equals('field'));
+  Class classDouble = await field.guardClass.load();
+  expect(classDouble.name, equals('_Double'));
+}
+
+Future testSetter(Isolate isolate) async {
+  Library rootLibrary = await isolate.rootLibrary.load();
+  expect(rootLibrary.classes.length, equals(1));
+  Class classA = await rootLibrary.classes[0].load();
+  expect(classA.name, equals('A'));
+  // Find setter.
+  ServiceFunction setterFunc;
+  for (ServiceFunction function in classA.functions) {
+    if (function.name == 'field=') {
+      setterFunc = function;
+      break;
+    }
+  }
+  expect(setterFunc, isNotNull);
+  await setterFunc.load();
+  Field field = await setterFunc.field.load();
+  expect(field, isNotNull);
+  expect(field.name, equals('field'));
+  Class classDouble = await field.guardClass.load();
+  expect(classDouble.name, equals('_Double'));
+}
+
+var tests = <IsolateTest>[testGetter, testSetter];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/inbound_references_test.dart b/runtime/observatory_2/tests/service_2/inbound_references_test.dart
new file mode 100644
index 0000000..6053042
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/inbound_references_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library inbound_references_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Node {
+  // Make sure this field is not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var edge;
+}
+
+class Edge {}
+
+var n, e, array;
+
+void script() {
+  n = new Node();
+  e = new Edge();
+  n.edge = e;
+  array = new List(2);
+  array[0] = n;
+  array[1] = e;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field field = lib.variables.where((v) => v.name == 'e').single;
+    await field.load();
+    Instance e = field.staticValue;
+    ServiceMap response = await isolate.getInboundReferences(e, 100);
+    List references = response['references'];
+    hasReferenceSuchThat(predicate) {
+      expect(references.any(predicate), isTrue);
+    }
+
+    // Assert e is referenced by at least n, array, and the top-level
+    // field e.
+    hasReferenceSuchThat((r) =>
+        r['parentField'] != null &&
+        r['parentField'].name == 'edge' &&
+        r['source'].isInstance &&
+        r['source'].clazz.name == 'Node');
+    hasReferenceSuchThat(
+        (r) => r['parentListIndex'] == 1 && r['source'].isList);
+    hasReferenceSuchThat(
+        (r) => r['source'] is Field && r['source'].name == 'e');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/instance_field_order_rpc_test.dart b/runtime/observatory_2/tests/service_2/instance_field_order_rpc_test.dart
new file mode 100644
index 0000000..6bc8bdc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/instance_field_order_rpc_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library get_object_rpc_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Super {
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var z = 1;
+  @pragma("vm:entry-point")
+  var y = 2;
+}
+
+class Sub extends Super {
+  @pragma("vm:entry-point")
+  var y = 3;
+  @pragma("vm:entry-point")
+  var x = 4;
+}
+
+@pragma("vm:entry-point")
+getSub() => new Sub();
+
+invoke(Isolate isolate, String selector) async {
+  Map params = {
+    'targetId': isolate.rootLibrary.id,
+    'selector': selector,
+    'argumentIds': <String>[],
+  };
+  return await isolate.invokeRpcNoUpgrade('invoke', params);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    // Call eval to get a Dart list.
+    var evalResult = await invoke(isolate, 'getSub');
+    var params = {
+      'objectId': evalResult['id'],
+    };
+    var result = await isolate.invokeRpcNoUpgrade('getObject', params);
+    print(result);
+    expect(result['type'], equals('Instance'));
+    expect(result['kind'], equals('PlainInstance'));
+    expect(result['class']['name'], equals('Sub'));
+    expect(result['size'], isPositive);
+    expect(result['fields'][0]['decl']['name'], 'z');
+    expect(result['fields'][0]['value']['valueAsString'], '1');
+    expect(result['fields'][1]['decl']['name'], 'y');
+    expect(result['fields'][1]['value']['valueAsString'], '2');
+    expect(result['fields'][2]['decl']['name'], 'y');
+    expect(result['fields'][2]['value']['valueAsString'], '3');
+    expect(result['fields'][3]['decl']['name'], 'x');
+    expect(result['fields'][3]['value']['valueAsString'], '4');
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/invoke_skip_breakpoint.dart b/runtime/observatory_2/tests/service_2/invoke_skip_breakpoint.dart
new file mode 100644
index 0000000..100f9d7
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/invoke_skip_breakpoint.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 21;
+const int LINE_B = 16;
+
+bar() {
+  print('bar');
+  return 'bar';
+}
+
+testMain() {
+  debugger();
+  bar();
+  print("Done");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  setBreakpointAtLine(LINE_B),
+  (Isolate isolate) async {
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    dynamic result = await isolate.invokeRpc("invoke", {
+      "targetId": lib.id,
+      "selector": "bar",
+      "argumentIds": [],
+      "disableBreakpoints": true
+    });
+    print(result);
+    expect(result.valueAsString, equals('bar'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/invoke_test.dart b/runtime/observatory_2/tests/service_2/invoke_test.dart
new file mode 100644
index 0000000..e888a65
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/invoke_test.dart
@@ -0,0 +1,128 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+libraryFunction() => "foobar1";
+
+class Klass {
+  @pragma('vm:entry-point')
+  static classFunction(x) => "foobar2" + x;
+  @pragma('vm:entry-point')
+  instanceFunction(x, y) => "foobar3" + x + y;
+}
+
+var instance;
+
+@pragma('vm:entry-point')
+var apple;
+@pragma('vm:entry-point')
+var banana;
+
+void testFunction() {
+  instance = new Klass();
+  apple = "apple";
+  banana = "banana";
+  debugger();
+}
+
+@pragma('vm:entry-point')
+void foo() {
+  print('foobar');
+}
+
+@pragma('vm:entry-point')
+void invokeFunction(Function func) {
+  func();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+    final fooFunc = lib.functions.singleWhere((func) => func.name == "foo");
+    Class cls = lib.classes.singleWhere((cls) => cls.name == "Klass");
+    Field field =
+        lib.variables.singleWhere((field) => field.name == "instance");
+    await field.load();
+    Instance instance = field.staticValue;
+    field = lib.variables.singleWhere((field) => field.name == "apple");
+    await field.load();
+    Instance apple = field.staticValue;
+    field = lib.variables.singleWhere((field) => field.name == "banana");
+    await field.load();
+    Instance banana = field.staticValue;
+
+    dynamic result = await isolate.invokeRpc("invoke",
+        {"targetId": lib.id, "selector": "libraryFunction", "argumentIds": []});
+    print(result);
+    expect(result.valueAsString, equals('foobar1'));
+
+    result = await isolate.invokeRpc("invoke", {
+      "targetId": cls.id,
+      "selector": "classFunction",
+      "argumentIds": [apple.id]
+    });
+    print(result);
+    expect(result.valueAsString, equals('foobar2apple'));
+
+    result = await isolate.invokeRpc("invoke", {
+      "targetId": instance.id,
+      "selector": "instanceFunction",
+      "argumentIds": [apple.id, banana.id]
+    });
+    print(result);
+    expect(result.valueAsString, equals('foobar3applebanana'));
+
+    // Wrong arity.
+    await expectError(
+        () => isolate.invokeRpc("invoke", {
+              "targetId": instance.id,
+              "selector": "instanceFunction",
+              "argumentIds": [apple.id]
+            }),
+        ServerRpcException.kExpressionCompilationError);
+
+    // Non-instance argument.
+    await expectError(
+        () => isolate.invokeRpc("invoke", {
+              "targetId": lib.id,
+              "selector": "invokeFunction",
+              "argumentIds": [fooFunc.id]
+            }),
+        ServerRpcException.kInvalidParams);
+
+    // No such target.
+    await expectError(
+        () => isolate.invokeRpc("invoke", {
+              "targetId": instance.id,
+              "selector": "functionDoesNotExist",
+              "argumentIds": [apple.id]
+            }),
+        ServerRpcException.kExpressionCompilationError);
+  },
+  resumeIsolate,
+];
+
+expectError(func, code) async {
+  bool gotException = false;
+  dynamic result;
+  try {
+    result = await func();
+    expect(result.type, equals('Error')); // dart1 semantics
+  } on ServerRpcException catch (e) {
+    expect(e.code, code);
+    gotException = true;
+  }
+  if (result?.type != 'Error') {
+    expect(gotException, true); // dart2 semantics
+  }
+}
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/isolate_lifecycle_test.dart b/runtime/observatory_2/tests/service_2/isolate_lifecycle_test.dart
new file mode 100644
index 0000000..7d38631
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/isolate_lifecycle_test.dart
@@ -0,0 +1,132 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+final spawnCount = 4;
+final resumeCount = spawnCount ~/ 2;
+final isolates = [];
+
+void spawnEntry(int i) {}
+
+Future during() async {
+  debugger();
+  // Spawn spawnCount long lived isolates.
+  for (var i = 0; i < spawnCount; i++) {
+    var isolate = await I.Isolate.spawn(spawnEntry, i);
+    isolates.add(isolate);
+  }
+  print('spawned all isolates');
+}
+
+int numPaused(vm) {
+  int paused = 0;
+  for (var isolate in vm.isolates) {
+    if (isolate.paused && isolate.pauseEvent is M.PauseExitEvent) {
+      paused++;
+    }
+  }
+  return paused;
+}
+
+var tests = <VMTest>[
+  (VM vm) async {
+    expect(vm.isolates.length, 1);
+    await hasStoppedAtBreakpoint(vm.isolates[0]);
+  },
+  (VM vm) async {
+    Completer completer = new Completer();
+    var stream = await vm.getEventStream(VM.kIsolateStream);
+    var subscription;
+    int startCount = 0;
+    int runnableCount = 0;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kIsolateStart) {
+        startCount++;
+      }
+      if (event.kind == ServiceEvent.kIsolateRunnable) {
+        runnableCount++;
+      }
+      if (runnableCount == spawnCount) {
+        subscription.cancel();
+        completer.complete(null);
+      }
+    });
+    expect(vm.isolates.length, 1);
+    vm.isolates[0].resume();
+    await completer.future;
+    expect(startCount, spawnCount);
+    expect(runnableCount, spawnCount);
+    expect(vm.isolates.length, spawnCount + 1);
+  },
+  (VM vm) async {
+    // Load each isolate.
+    for (var isolate in vm.isolates) {
+      await isolate.load();
+    }
+  },
+  (VM vm) async {
+    Completer completer = new Completer();
+    var stream = await vm.getEventStream(VM.kDebugStream);
+    if (numPaused(vm) < (spawnCount + 1)) {
+      var subscription;
+      subscription = stream.listen((ServiceEvent event) {
+        if (event.kind == ServiceEvent.kPauseExit) {
+          if (numPaused(vm) == (spawnCount + 1)) {
+            subscription.cancel();
+            completer.complete(null);
+          }
+        }
+      });
+      await completer.future;
+    }
+    expect(numPaused(vm), spawnCount + 1);
+  },
+  (VM vm) async {
+    var resumedReceived = 0;
+    Completer completer = new Completer();
+    var stream = await vm.getEventStream(VM.kIsolateStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kIsolateExit) {
+        resumedReceived++;
+        if (resumedReceived >= resumeCount) {
+          subscription.cancel();
+          completer.complete(null);
+        }
+      }
+    });
+
+    // Resume a subset of the isolates.
+    var resumesIssued = 0;
+    var isolateList = vm.isolates.toList();
+    for (var isolate in isolateList) {
+      if (isolate.name.endsWith('main')) {
+        continue;
+      }
+      try {
+        resumesIssued++;
+        await isolate.resume();
+      } catch (_) {}
+      if (resumesIssued == resumeCount) {
+        break;
+      }
+    }
+    await completer.future;
+  },
+  (VM vm) async {
+    expect(numPaused(vm), spawnCount + 1 - resumeCount);
+  },
+];
+
+main(args) async =>
+    runVMTests(args, tests, testeeConcurrent: during, pause_on_exit: true);
diff --git a/runtime/observatory_2/tests/service_2/issue_25465_test.dart b/runtime/observatory_2/tests/service_2/issue_25465_test.dart
new file mode 100644
index 0000000..87c6986
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/issue_25465_test.dart
@@ -0,0 +1,73 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:async';
+
+const int LINE_A = 16;
+const int LINE_B = 17;
+
+testMain() {
+  var foo; // line A
+  foo = 42; // line B
+  print(foo);
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+
+  // Add breakpoints at line 11 and line 12.
+  (Isolate isolate) async {
+    var rootLib = isolate.rootLibrary;
+    await rootLib.load();
+    var script = rootLib.scripts[0];
+
+    var bpt1 = await isolate.addBreakpoint(script, LINE_A);
+    var bpt2 = await isolate.addBreakpoint(script, LINE_B);
+    expect(await bpt1.location.getLine(), equals(LINE_A));
+    expect(await bpt2.location.getLine(), equals(LINE_B));
+
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    Completer completer = new Completer();
+    var subscription;
+    var breakCount = 0;
+    subscription = stream.listen((ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        breakCount++;
+        print('break count is $breakCount');
+        if (breakCount == 1) {
+          // We are stopped at breakpoint 1.
+          expect(event.breakpoint.number, equals(bpt1.number));
+
+          // Remove both breakpoints
+          var result = await isolate.removeBreakpoint(bpt1);
+          expect(result.type, equals("Success"));
+
+          result = await isolate.removeBreakpoint(bpt2);
+          expect(result.type, equals("Success"));
+
+          isolate.stepOver();
+        } else {
+          // No breakpoint.
+          expect(event.breakpoint, isNull);
+
+          // We expect the next step to take us to line B.
+          var stack = await isolate.getStack();
+          expect(await stack['frames'][0].location.getLine(), equals(LINE_B));
+
+          subscription.cancel();
+          completer.complete(null);
+        }
+      }
+    });
+    isolate.resume();
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain, pause_on_start: true);
diff --git a/runtime/observatory_2/tests/service_2/issue_27238_test.dart b/runtime/observatory_2/tests/service_2/issue_27238_test.dart
new file mode 100644
index 0000000..60c7497
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/issue_27238_test.dart
@@ -0,0 +1,46 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'service_test_common.dart';
+import 'dart:async';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 19;
+const int LINE_B = 22;
+const int LINE_C = 23;
+const int LINE_D = 25;
+const int LINE_E = 26;
+
+testMain() async {
+  debugger();
+  Future future1 = new Future.value(); // LINE_A.
+  Future future2 = new Future.value();
+
+  await future1; // LINE_B.
+  await future2; // LINE_C.
+
+  print('foo1'); // LINE_D.
+  print('foo2'); // LINE_E.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  smartNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+  smartNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/issue_27287_test.dart b/runtime/observatory_2/tests/service_2/issue_27287_test.dart
new file mode 100644
index 0000000..872ad12
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/issue_27287_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+const int LINE_A = 17;
+const int LINE_B = 18;
+
+var libVariable;
+
+testMain() {
+  debugger();
+  print("Before"); // LINE_A
+  libVariable = 0; // LINE_B
+  print("and after");
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver,
+  // Check that debugger stops at assignment to top-level variable.
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/issue_30555_test.dart b/runtime/observatory_2/tests/service_2/issue_30555_test.dart
new file mode 100644
index 0000000..00c34c9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/issue_30555_test.dart
@@ -0,0 +1,141 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+import "dart:isolate" as dart;
+
+void isolate(dart.SendPort port) {
+  dart.RawReceivePort receive = new dart.RawReceivePort((_) {
+    debugger();
+    throw new Exception();
+  });
+  port.send(receive.sendPort);
+}
+
+void test() {
+  dart.RawReceivePort receive = new dart.RawReceivePort((port) {
+    debugger();
+    port.send(null);
+    debugger();
+    port.send(null);
+    debugger();
+  });
+  dart.Isolate.spawn(isolate, receive.sendPort);
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    int step = 0;
+    var completer = new Completer();
+    var sub;
+    final Isolate firstIsolate = isolate;
+    print("First isolate is: ${firstIsolate.id}");
+    Isolate secondIsolate;
+    sub = await isolate.vm.listenEventStream(VM.kDebugStream, (ServiceEvent c) {
+      print("Event ${c.kind} on ${c.isolate.id}");
+      switch (step) {
+        case 0:
+          expect(c.kind, equals(ServiceEvent.kResume),
+              reason: "First isolate should resume");
+          expect(c.isolate.id, equals(firstIsolate.id),
+              reason: "First isolate should resume");
+          break;
+        case 1:
+          expect(c.kind, equals(ServiceEvent.kPauseStart),
+              reason: "Second isolate should pause on start");
+          expect(c.isolate.id, equals(isolate.vm.isolates[1].id),
+              reason: "Second isolate should pause on start");
+          secondIsolate = c.isolate;
+          print("Second isolate is: ${secondIsolate.id}");
+          print("Resuming second isolate");
+          secondIsolate.resume();
+          break;
+        case 2:
+          expect(c.kind, equals(ServiceEvent.kResume),
+              reason: "Second isolate should resume");
+          expect(c.isolate.id, equals(secondIsolate.id),
+              reason: "Second isolate should resume");
+          break;
+        case 3:
+          expect(c.kind, equals(ServiceEvent.kPauseBreakpoint),
+              reason: "First isolate should stop at debugger()");
+          expect(c.isolate.id, equals(firstIsolate.id),
+              reason: "First isolate should stop at debugger()");
+          print("Resuming first isolate");
+          firstIsolate.resume();
+          break;
+        case 4:
+          expect(c.kind, equals(ServiceEvent.kResume),
+              reason: "First isolate should resume (1)");
+          expect(c.isolate.id, equals(firstIsolate.id),
+              reason: "First isolate should resume (1)");
+          break;
+        case 5:
+          expect(c.kind, equals(ServiceEvent.kPauseBreakpoint),
+              reason: "First & Second isolate should stop at debugger()");
+          break;
+        case 6:
+          expect(c.kind, equals(ServiceEvent.kPauseBreakpoint),
+              reason: "First & Second isolate should stop at debugger()");
+          print("Resuming second isolate");
+          secondIsolate.resume();
+          break;
+        case 7:
+          expect(c.kind, equals(ServiceEvent.kResume),
+              reason: "Second isolate should resume before the exception");
+          expect(c.isolate.id, equals(secondIsolate.id),
+              reason: "Second isolate should resume before the exception");
+          break;
+        case 8:
+          expect(c.kind, equals(ServiceEvent.kPauseExit),
+              reason: "Second isolate should exit at the exception");
+          expect(c.isolate.id, equals(secondIsolate.id),
+              reason: "Second isolate should exit at the exception");
+          print("Resuming first isolate");
+          firstIsolate.resume();
+          break;
+        case 9:
+          expect(c.kind, equals(ServiceEvent.kResume),
+              reason: "First isolate should resume after the exception");
+          expect(c.isolate.id, equals(firstIsolate.id),
+              reason: "First isolate should resume after the exception");
+          break;
+        case 10:
+          expect(c.isolate.id, equals(firstIsolate.id),
+              reason: "First "
+                  "isolate should stop at debugger() after exception.\n"
+                  "Probably the second resumed even though it was not expect "
+                  "to do it.");
+          expect(c.kind, equals(ServiceEvent.kPauseBreakpoint),
+              reason: "First isolate should stop at debugger() after "
+                  "exception.");
+          completer.complete();
+          break;
+        default:
+          fail("Shouldn't get here, the second isolate resumed even though it "
+              "was not expect to do it");
+          break;
+      }
+      step++;
+    });
+    print("Resuming first isolate");
+    firstIsolate.resume();
+    await completer.future;
+    // We wait 1 second to account for delays in the service protocol.
+    // A late message can still arrive.
+    await new Future.delayed(const Duration(seconds: 1));
+    // No fails, tear down the stream.
+    sub.cancel();
+  }
+];
+
+main(args) async => runIsolateTests(args, tests,
+    pause_on_start: true, pause_on_exit: true, testeeConcurrent: test);
diff --git a/runtime/observatory_2/tests/service_2/kill_paused_test.dart b/runtime/observatory_2/tests/service_2/kill_paused_test.dart
new file mode 100644
index 0000000..1e9e346
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/kill_paused_test.dart
@@ -0,0 +1,29 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_common.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+import 'dart:developer';
+import 'service_test_common.dart';
+
+testMain() async {
+  debugger(); // Stop here.
+  print('1');
+  while (true) {}
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Kill the app
+  (Isolate isolate) async {
+    Map<String, dynamic> params = <String, dynamic>{};
+    ServiceObject result = await isolate.invokeRpc('kill', params);
+    expect(result.type, equals('Success'));
+  }
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/kill_running_test.dart b/runtime/observatory_2/tests/service_2/kill_running_test.dart
new file mode 100644
index 0000000..5f5846d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/kill_running_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_common.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+testMain() async {
+  print('1');
+  while (true) {}
+}
+
+var tests = <IsolateTest>[
+  // Kill the app
+  (Isolate isolate) async {
+    Map<String, dynamic> params = <String, dynamic>{};
+    ServiceObject result = await isolate.invokeRpc('kill', params);
+    expect(result.type, equals('Success'));
+  }
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/library_dependency_test.dart b/runtime/observatory_2/tests/service_2/library_dependency_test.dart
new file mode 100644
index 0000000..a34a95d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/library_dependency_test.dart
@@ -0,0 +1,46 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+export 'dart:collection';
+import 'dart:mirrors' as mirrors;
+import 'dart:convert' deferred as convert;
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    await isolate.load();
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    // Avoid unused import warning from the analyzer.
+    mirrors.currentMirrorSystem();
+
+    importOf(String uri) {
+      return lib.dependencies.singleWhere((dep) => dep.target.uri == uri);
+    }
+
+    expect(importOf("dart:collection").isImport, isFalse);
+    expect(importOf("dart:collection").isExport, isTrue);
+    expect(importOf("dart:collection").isDeferred, isFalse);
+    expect(importOf("dart:collection").prefix, equals(null));
+
+    expect(importOf("dart:mirrors").isImport, isTrue);
+    expect(importOf("dart:mirrors").isExport, isFalse);
+    expect(importOf("dart:mirrors").isDeferred, isFalse);
+    expect(importOf("dart:mirrors").prefix, equals("mirrors"));
+
+    expect(importOf("dart:convert").isImport, isTrue);
+    expect(importOf("dart:convert").isExport, isFalse);
+    expect(importOf("dart:convert").isDeferred, isTrue);
+    expect(importOf("dart:convert").prefix, equals("convert"));
+  },
+  (Isolate isolate) async {
+    return convert.loadLibrary();
+  }
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/local_variable_declaration_test.dart b/runtime/observatory_2/tests/service_2/local_variable_declaration_test.dart
new file mode 100644
index 0000000..4a05a02
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/local_variable_declaration_test.dart
@@ -0,0 +1,112 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+
+testParameters(int jjjj, int oooo, [int hhhh, int nnnn]) {
+  debugger();
+}
+
+testMain() {
+  int xxx, yyyy, zzzzz;
+  for (int i = 0; i < 1; i++) {
+    var foo = () {};
+    debugger();
+  }
+  var bar = () {
+    print(xxx);
+    print(yyyy);
+    debugger();
+  };
+  bar();
+  testParameters(0, 0);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedInFunction('testMain'),
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    // Grab the top frame.
+    Frame frame = stack['frames'][0];
+    // Grab the script.
+    Script script = frame.location.script;
+    await script.load();
+
+    // Ensure that the token at each declaration position is the name of the
+    // variable.
+    for (var variable in frame.variables) {
+      final int declarationTokenPos = variable['declarationTokenPos'];
+      final String name = variable['name'];
+      final String token = script.getToken(declarationTokenPos);
+      // When running from an appjit snapshot, sources aren't available so the returned token will
+      // be null.
+      if (token != null) {
+        expect(name, token);
+      }
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  // We have stopped in the anonymous closure assigned to bar. Verify that
+  // variables captured in the context have valid declaration positions.
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    // Grab the top frame.
+    Frame frame = stack['frames'][0];
+    // Grab the script.
+    Script script = frame.location.script;
+    await script.load();
+    print(frame);
+    expect(frame.variables.length, greaterThanOrEqualTo(1));
+    for (var variable in frame.variables) {
+      final int declarationTokenPos = variable['declarationTokenPos'];
+      final String name = variable['name'];
+      final String token = script.getToken(declarationTokenPos);
+      // When running from an appjit snapshot, sources aren't available so the returned token will
+      // be null.
+      if (token != null) {
+        expect(name, token);
+      }
+    }
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedInFunction('testParameters'),
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    // Grab the top frame.
+    Frame frame = stack['frames'][0];
+    // Grab the script.
+    Script script = frame.location.script;
+    await script.load();
+
+    // Ensure that the token at each declaration position is the name of the
+    // variable.
+    expect(frame.variables.length, greaterThanOrEqualTo(1));
+    for (var variable in frame.variables) {
+      final int declarationTokenPos = variable['declarationTokenPos'];
+      final String name = variable['name'];
+      final String token = script.getToken(declarationTokenPos);
+      // When running from an appjit snapshot, sources aren't available so the returned token will
+      // be null.
+      if (token != null) {
+        expect(name, token);
+      }
+    }
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/local_variable_in_awaiter_async_frame_test.dart b/runtime/observatory_2/tests/service_2/local_variable_in_awaiter_async_frame_test.dart
new file mode 100644
index 0000000..dd34e63
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/local_variable_in_awaiter_async_frame_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 14;
+
+Future<String> testFunction(String caption) async {
+  await Future.delayed(Duration(milliseconds: 1));
+  return caption;
+}
+
+testMain() async {
+  debugger();
+  var str = await testFunction('The caption');
+  print(str);
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  setBreakpointAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  hasLocalVarInTopAwaiterStackFrame('caption'),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/logging_test.dart b/runtime/observatory_2/tests/service_2/logging_test.dart
new file mode 100644
index 0000000..dac2746
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/logging_test.dart
@@ -0,0 +1,53 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer' as developer;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'package:logging/logging.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void init() {
+  Logger.root.level = Level.ALL;
+  Logger.root.onRecord.listen((logRecord) {
+    developer.log(logRecord.message,
+        time: logRecord.time,
+        sequenceNumber: logRecord.sequenceNumber,
+        level: logRecord.level.value,
+        name: logRecord.loggerName,
+        zone: null,
+        error: logRecord.error,
+        stackTrace: logRecord.stackTrace);
+  });
+}
+
+void run() {
+  developer.debugger();
+  Logger.root.fine('Hey Buddy!');
+  developer.debugger();
+  Logger.root.info('YES');
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  resumeIsolateAndAwaitEvent(Isolate.kLoggingStream, (ServiceEvent event) {
+    expect(event.kind, equals(ServiceEvent.kLogging));
+    expect(event.logRecord['sequenceNumber'], equals(0));
+    expect(event.logRecord['message'].valueAsString, equals('Hey Buddy!'));
+    expect(event.logRecord['level'], equals(Level.FINE));
+    expect(event.logRecord['time'], isA<DateTime>());
+  }),
+  hasStoppedAtBreakpoint,
+  resumeIsolateAndAwaitEvent(Isolate.kLoggingStream, (ServiceEvent event) {
+    expect(event.kind, equals(ServiceEvent.kLogging));
+    expect(event.logRecord['sequenceNumber'], equals(1));
+    expect(event.logRecord['level'], equals(Level.INFO));
+    expect(event.logRecord['message'].valueAsString, equals('YES'));
+    expect(event.logRecord['time'], isA<DateTime>());
+  }),
+];
+
+main(args) =>
+    runIsolateTests(args, tests, testeeBefore: init, testeeConcurrent: run);
diff --git a/runtime/observatory_2/tests/service_2/malformed_test.dart b/runtime/observatory_2/tests/service_2/malformed_test.dart
new file mode 100644
index 0000000..8a3d886
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/malformed_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    bool caughtException;
+    try {
+      await isolate.invokeRpc('_respondWithMalformedObject', {});
+      expect(false, isTrue, reason: 'Unreachable');
+    } on MalformedResponseRpcException catch (e) {
+      caughtException = true;
+      expect(e.message, equals("Response is missing the 'type' field"));
+    }
+    expect(caughtException, isTrue);
+  },
+
+  // Do this test last... it kills the vm connection.
+  (Isolate isolate) async {
+    bool caughtException;
+    try {
+      await isolate.invokeRpc('_respondWithMalformedJson', {});
+      expect(false, isTrue, reason: 'Unreachable');
+    } on NetworkRpcException catch (e) {
+      caughtException = true;
+      expect(
+          e.message,
+          startsWith("Canceling request: "
+              "Connection saw corrupt JSON message: "
+              "FormatException: Unexpected character"));
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      // This test hangs with DDS as package:json_rpc_2 can't parse the JSON
+      // response and is unable to determine the request ID, so the malformed
+      // JSON request will never complete.
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/metrics_test.dart b/runtime/observatory_2/tests/service_2/metrics_test.dart
new file mode 100644
index 0000000..91b57fa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/metrics_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+import 'dart:developer';
+
+void script() {
+  var counter = new Counter('a.b.c', 'description');
+  Metrics.register(counter);
+  counter.value = 1234.5;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Map metrics = await isolate.refreshDartMetrics();
+    expect(metrics.length, equals(1));
+    var counter = metrics['metrics/a.b.c'];
+    expect(counter.name, equals('a.b.c'));
+    expect(counter.value, equals(1234.5));
+  },
+  (Isolate isolate) async {
+    var params = {'metricId': 'metrics/a.b.c'};
+    ServiceMetric counter =
+        await isolate.invokeRpc('_getIsolateMetric', params);
+    expect(counter.name, equals('a.b.c'));
+    expect(counter.value, equals(1234.5));
+  },
+  (Isolate isolate) async {
+    bool caughtException;
+    try {
+      await isolate
+          .invokeRpc('_getIsolateMetric', {'metricId': 'metrics/a.b.d'});
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(e.message,
+          "_getIsolateMetric: invalid 'metricId' parameter: metrics/a.b.d");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/mirror_references_test.dart b/runtime/observatory_2/tests/service_2/mirror_references_test.dart
new file mode 100644
index 0000000..6699130
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/mirror_references_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm_references_test;
+
+import 'dart:mirrors';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Foo {}
+
+Foo foo;
+var /*MirrorReference*/ ref;
+
+void script() {
+  foo = new Foo();
+  ClassMirror fooClassMirror = reflectClass(Foo);
+  InstanceMirror fooClassMirrorMirror = reflect(fooClassMirror);
+  LibraryMirror libmirrors = fooClassMirrorMirror.type.owner;
+  ref = reflect(fooClassMirror)
+      .getField(MirrorSystem.getSymbol('_reflectee', libmirrors))
+      .reflectee;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field fooField = lib.variables.singleWhere((v) => v.name == 'foo');
+    await fooField.load();
+    Instance foo = fooField.staticValue;
+    Field refField = lib.variables.singleWhere((v) => v.name == 'ref');
+    await refField.load();
+    Instance ref = refField.staticValue;
+
+    expect(foo.isMirrorReference, isFalse);
+    expect(ref.isMirrorReference, isTrue);
+    expect(ref.referent, isNull);
+    Instance loadedRef = await ref.load();
+    expect(loadedRef.referent, isNotNull);
+    expect(loadedRef.referent.name, equals('Foo'));
+    expect(loadedRef.referent, equals(foo.clazz));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/mixin_break_class1.dart b/runtime/observatory_2/tests/service_2/mixin_break_class1.dart
new file mode 100644
index 0000000..e490fdd
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/mixin_break_class1.dart
@@ -0,0 +1,10 @@
+library mixin_step_class1;
+
+import 'mixin_break_mixin_class.dart';
+
+class Hello1 extends Object with HelloMixin {
+  void speak() {
+    sayHello();
+    print(" - Hello1");
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/mixin_break_class2.dart b/runtime/observatory_2/tests/service_2/mixin_break_class2.dart
new file mode 100644
index 0000000..cc6a454
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/mixin_break_class2.dart
@@ -0,0 +1,10 @@
+library mixin_step_class2;
+
+import 'mixin_break_mixin_class.dart';
+
+class Hello2 extends Object with HelloMixin {
+  void speak() {
+    sayHello();
+    print(" - Hello2");
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/mixin_break_mixin_class.dart b/runtime/observatory_2/tests/service_2/mixin_break_mixin_class.dart
new file mode 100644
index 0000000..e19a7a8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/mixin_break_mixin_class.dart
@@ -0,0 +1,7 @@
+library mixin_step_mixin_class;
+
+class HelloMixin {
+  void sayHello() {
+    print("Hello!");
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/mixin_break_test.dart b/runtime/observatory_2/tests/service_2/mixin_break_test.dart
new file mode 100644
index 0000000..f32e87a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/mixin_break_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library mixin_step_test;
+
+import 'dart:developer';
+
+import 'mixin_break_class1.dart';
+import 'mixin_break_class2.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const String file = "mixin_break_mixin_class.dart";
+
+int codeRuns = 0;
+
+code() {
+  if (++codeRuns > 1) {
+    print("Calling debugger!");
+    debugger();
+  }
+  Hello1 a = new Hello1();
+  Hello2 b = new Hello2();
+  a.speak();
+  b.speak();
+
+  print("Both now compiled");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:5:5 (mixin_break_class1.dart:7:5)",
+  "$file:5:5 (mixin_break_class2.dart:7:5)",
+];
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  setBreakpointAtUriAndLine(file, 5),
+  resumeProgramRecordingStops(stops, true),
+  checkRecordedStops(stops, expected),
+];
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: code,
+      testeeConcurrent: code,
+      pause_on_start: false,
+      pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/native_metrics_test.dart b/runtime/observatory_2/tests/service_2/native_metrics_test.dart
new file mode 100644
index 0000000..ffc167d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/native_metrics_test.dart
@@ -0,0 +1,51 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+import 'dart:developer';
+
+void script() {
+  var counter = new Counter('a.b.c', 'description');
+  Metrics.register(counter);
+  counter.value = 1234.5;
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Map metrics = await isolate.refreshNativeMetrics();
+    expect(metrics.length, greaterThan(1));
+    expect(metrics.length, greaterThan(1));
+    var foundOldHeapCapacity =
+        metrics.values.any((m) => m.name == 'heap.old.capacity');
+    expect(foundOldHeapCapacity, equals(true));
+  },
+  (Isolate isolate) async {
+    var params = {'metricId': 'metrics/native/heap.old.used'};
+    ServiceMetric counter =
+        await isolate.invokeRpc('_getIsolateMetric', params);
+    expect(counter.type, equals('Counter'));
+    expect(counter.name, equals('heap.old.used'));
+  },
+  (Isolate isolate) async {
+    bool caughtException;
+    try {
+      await isolate.invokeRpc(
+          '_getIsolateMetric', {'metricId': 'metrics/native/doesnotexist'});
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message,
+          "_getIsolateMetric: invalid 'metricId' "
+          "parameter: metrics/native/doesnotexist");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/network_profiling_test.dart b/runtime/observatory_2/tests/service_2/network_profiling_test.dart
new file mode 100644
index 0000000..5c27795
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/network_profiling_test.dart
@@ -0,0 +1,215 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const String content = 'some random content';
+const String udpContent = 'aghfkjdb';
+const String kClearSocketProfileRPC = 'ext.dart.io.clearSocketProfile';
+const String kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
+const String kGetVersionRPC = 'ext.dart.io.getVersion';
+const String kPauseSocketProfilingRPC = 'ext.dart.io.pauseSocketProfiling';
+const String kStartSocketProfilingRPC = 'ext.dart.io.startSocketProfiling';
+const String localhost = '127.0.0.1';
+
+Future<void> setup() async {}
+
+Future<void> socketTest() async {
+  // Socket
+  var serverSocket = await io.ServerSocket.bind(localhost, 0);
+  var socket = await io.Socket.connect(localhost, serverSocket.port);
+  socket.write(content);
+  await socket.flush();
+  await socket.destroy();
+
+  // rawDatagram
+  final doneCompleter = Completer<void>();
+  var server = await io.RawDatagramSocket.bind(localhost, 0);
+  server.listen((io.RawSocketEvent event) {
+    if (event == io.RawSocketEvent.read) {
+      io.Datagram dg = server.receive();
+      if (!doneCompleter.isCompleted) {
+        doneCompleter.complete();
+      }
+    }
+  });
+  var client = await io.RawDatagramSocket.bind(localhost, 0);
+  client.send(utf8.encoder.convert(udpContent), io.InternetAddress(localhost),
+      server.port);
+  client.send([1, 2, 3], io.InternetAddress(localhost), server.port);
+
+  // Wait for datagram to arrive.
+  await doneCompleter.future;
+  // Post finish event
+  postEvent('socketTest', {'socket': 'test'});
+}
+
+Future<void> checkFinishEvent(ServiceEvent event) {
+  expect(event.kind, equals(ServiceEvent.kExtension));
+  expect(event.extensionKind, equals('socketTest'));
+  expect(event.extensionData, isA<Map>());
+  expect(event.extensionData['socket'], equals('test'));
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    await isolate.load();
+    // Ensure all network profiling service extensions are registered.
+    expect(isolate.extensionRPCs.length, greaterThanOrEqualTo(5));
+    expect(isolate.extensionRPCs.contains(kClearSocketProfileRPC), isTrue);
+    expect(isolate.extensionRPCs.contains(kGetVersionRPC), isTrue);
+    expect(isolate.extensionRPCs.contains(kPauseSocketProfilingRPC), isTrue);
+    expect(isolate.extensionRPCs.contains(kStartSocketProfilingRPC), isTrue);
+    expect(isolate.extensionRPCs.contains(kPauseSocketProfilingRPC), isTrue);
+  },
+
+  // Test getSocketProfiler
+  (Isolate isolate) async {
+    await isolate.load();
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    var response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+    // returns an empty list in 'sockets'
+    expect(response['sockets'].length, 0);
+  },
+
+  // Test getSocketProfile and startSocketProfiling
+  (Isolate isolate) async {
+    await isolate.load();
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    var response =
+        await isolate.invokeRpcNoUpgrade(kStartSocketProfilingRPC, {});
+    expect(response['type'], 'Success');
+
+    // Check whether socketTest has finished.
+    Completer completer = Completer();
+    var sub;
+    sub = await isolate.vm.listenEventStream(Isolate.kExtensionStream,
+        (ServiceEvent event) {
+      checkFinishEvent(event);
+      sub.cancel();
+      completer.complete();
+    });
+
+    dynamic result = await isolate.invokeRpc("invoke",
+        {"targetId": lib.id, "selector": "socketTest", "argumentIds": []});
+    await completer.future;
+
+    response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+    var stats = response['sockets'];
+    // 1 tcp socket, 2 udp datagrams
+    expect(stats.length, 3);
+    stats.forEach((socket) {
+      expect(socket['address'], contains(localhost));
+      Expect.type<int>(socket['startTime']);
+      Expect.type<int>(socket['id']);
+      Expect.type<int>(socket['port']);
+      if (socket['socketType'] == 'tcp') {
+        expect(socket['writeBytes'], content.length);
+        expect(socket.containsKey('lastWriteTime'), true);
+        expect(socket['lastWriteTime'] > 0, true);
+      } else {
+        // 2 udp sockets, one of them is writing and the other is listening.
+        expect(socket['socketType'], 'udp');
+        if (socket['readBytes'] == 0) {
+          // [1, 2, 3] was sent.
+          expect(socket['writeBytes'], 3 + udpContent.length);
+          expect(socket.containsKey('lastWriteTime'), true);
+          expect(socket['lastWriteTime'] > 0, true);
+          expect(socket.containsKey('lastReadTime'), false);
+        } else {
+          // [1, 2, 3] was sent.
+          expect(socket['writeBytes'], 0);
+          expect(socket['readBytes'], 3 + udpContent.length);
+          expect(socket.containsKey('lastWriteTime'), false);
+          expect(socket.containsKey('lastReadTime'), true);
+          expect(socket['lastReadTime'] > 0, true);
+        }
+      }
+    });
+
+    // run 99 more times and check we have 100 sockets statistic.
+    for (int i = 0; i < 99; i++) {
+      completer = Completer();
+      sub = await isolate.vm.listenEventStream(Isolate.kExtensionStream,
+          (ServiceEvent event) {
+        checkFinishEvent(event);
+        sub.cancel();
+        completer.complete();
+      });
+      dynamic result = await isolate.invokeRpc("invoke",
+          {"targetId": lib.id, "selector": "socketTest", "argumentIds": []});
+      await completer.future;
+    }
+
+    response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+    // 1 tcp socket, 2 udp datagrams
+    expect(response['sockets'].length, 3 * 100);
+  },
+
+  // Test clearSocketProfiler
+  (Isolate isolate) async {
+    await isolate.load();
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    var response = await isolate.invokeRpcNoUpgrade(kClearSocketProfileRPC, {});
+    expect(response['type'], 'Success');
+
+    response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+    expect(response['sockets'].length, 0);
+  },
+
+  // Test pauseSocketProfiling
+  (Isolate isolate) async {
+    await isolate.load();
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    var response =
+        await isolate.invokeRpcNoUpgrade(kStartSocketProfilingRPC, {});
+    expect(response['type'], 'Success');
+
+    response = await isolate.invokeRpcNoUpgrade(kPauseSocketProfilingRPC, {});
+    expect(response['type'], 'Success');
+
+    // Check whether socketTest has finished.
+    Completer completer = Completer();
+    var sub;
+    sub = await isolate.vm.listenEventStream(Isolate.kExtensionStream,
+        (ServiceEvent event) {
+      checkFinishEvent(event);
+      sub.cancel();
+      completer.complete();
+    });
+
+    dynamic result = await isolate.invokeRpc("invoke",
+        {"targetId": lib.id, "selector": "socketTest", "argumentIds": []});
+    await completer.future;
+
+    response = await isolate.invokeRpcNoUpgrade(kGetSocketProfileRPC, {});
+    expect(response['type'], 'SocketProfile');
+    expect(response['sockets'].length, 0);
+  }
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: setup);
diff --git a/runtime/observatory_2/tests/service_2/next_through_assign_call_test.dart b/runtime/observatory_2/tests/service_2/next_through_assign_call_test.dart
new file mode 100644
index 0000000..3b815d2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_assign_call_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_assign_call_test.dart";
+
+code() {
+  int a;
+  int b;
+  a = b = foo();
+  print(a);
+  print(b);
+  a = foo();
+  print(a);
+  int d = foo();
+  print(d);
+  int e = foo(), f, g = foo();
+  print(e);
+  print(f);
+  print(g);
+}
+
+foo() {
+  return 42;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:7", // on variable 'a'
+  "$file:${LINE_A+1}:7", // on variable 'b'
+  "$file:${LINE_A+2}:11", // on call to 'foo'
+  "$file:${LINE_A+3}:3", // on call to 'print'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:7", // on call to 'foo'
+  "$file:${LINE_A+6}:3", // on call to 'print'
+  "$file:${LINE_A+7}:11", // on call to 'foo'
+  "$file:${LINE_A+8}:3", // on call to 'print'
+  "$file:${LINE_A+9}:11", // on first call to 'foo'
+  "$file:${LINE_A+9}:18", // on variable 'f'
+  "$file:${LINE_A+9}:25", // on second call to 'foo'
+  "$file:${LINE_A+10}:3", // on call to 'print'
+  "$file:${LINE_A+11}:3", // on call to 'print'
+  "$file:${LINE_A+12}:3", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_assign_int_test.dart b/runtime/observatory_2/tests/service_2/next_through_assign_int_test.dart
new file mode 100644
index 0000000..c57fd84
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_assign_int_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_assign_int_test.dart";
+
+code() {
+  int a;
+  int b;
+  a = b = 42;
+  print(a);
+  print(b);
+  a = 42;
+  print(a);
+  int d = 42;
+  print(d);
+  int e = 41, f, g = 42;
+  print(e);
+  print(f);
+  print(g);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:7", // on variable 'a'
+  "$file:${LINE_A+1}:7", // on variable 'b'
+  "$file:${LINE_A+2}:7", // on 'b'
+  "$file:${LINE_A+3}:3", // on call to 'print'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:3", // on 'a'
+  "$file:${LINE_A+6}:3", // on call to 'print'
+  "$file:${LINE_A+7}:9", // on '='
+  "$file:${LINE_A+8}:3", // on call to 'print'
+  "$file:${LINE_A+9}:9", // on first '='
+  "$file:${LINE_A+9}:15", // on 'f'
+  "$file:${LINE_A+9}:20", // on second '='
+  "$file:${LINE_A+10}:3", // on call to 'print'
+  "$file:${LINE_A+11}:3", // on call to 'print'
+  "$file:${LINE_A+12}:3", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_await_for_test.dart b/runtime/observatory_2/tests/service_2/next_through_await_for_test.dart
new file mode 100644
index 0000000..734c1f1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_await_for_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 14;
+const String file = "next_through_await_for_test.dart";
+
+code() async {
+  int count = 0;
+  await for (var num in naturalsTo(2)) {
+    print(num);
+    count++;
+  }
+}
+
+Stream<int> naturalsTo(int n) async* {
+  int k = 0;
+  while (k < n) {
+    k++;
+    yield k;
+  }
+  yield 42;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:13", // on '='
+  "$file:${LINE + 1}:25", // on 'naturalsTo'
+
+  // Iteration #1
+  "$file:${LINE + 1}:3", // on 'await'
+  "$file:${LINE + 1}:40", // on '{'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 3}:10", // on '++'
+
+  // Iteration #2
+  "$file:${LINE + 1}:3", // on 'await'
+  "$file:${LINE + 1}:40", // on '{'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 3}:10", // on '++'
+
+  // Iteration #3
+  "$file:${LINE + 1}:3", // on 'await'
+  "$file:${LINE + 1}:40", // on '{'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 3}:10", // on '++'
+
+  // Done
+  "$file:${LINE + 1}:3", // on 'await'
+  "$file:${LINE + 5}:1"
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_call_on_field_in_class_test.dart b/runtime/observatory_2/tests/service_2/next_through_call_on_field_in_class_test.dart
new file mode 100644
index 0000000..8f5eef8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_call_on_field_in_class_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_call_on_field_in_class_test.dart";
+
+code() {
+  var foo = new Foo();
+  foo.foo = foo.fooMethod;
+  foo.fooMethod();
+  foo.foo();
+}
+
+class Foo {
+  var foo;
+
+  void fooMethod() {
+    print("Hello from fooMethod");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:17", // on "Foo"
+  "$file:${LINE_A+2}:17", // on "fooMethod"
+  "$file:${LINE_A+2}:7", // on "foo"
+  "$file:${LINE_A+3}:7", // on "fooMethod"
+  "$file:${LINE_A+4}:7", // on "foo"
+  "$file:${LINE_A+5}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_call_on_field_test.dart b/runtime/observatory_2/tests/service_2/next_through_call_on_field_test.dart
new file mode 100644
index 0000000..c47cd82
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_call_on_field_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 13;
+const String file = "next_through_call_on_field_test.dart";
+
+var foo;
+
+code() {
+  foo = fooMethod;
+  fooMethod();
+  foo();
+}
+
+void fooMethod() {
+  print("Hello from fooMethod");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:3", // on "foo"
+  "$file:${LINE_A+2}:3", // on "fooMethod"
+  "$file:${LINE_A+3}:6", // after "foo" (on invisible ".call")
+  "$file:${LINE_A+4}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_call_on_static_field_in_class_test.dart b/runtime/observatory_2/tests/service_2/next_through_call_on_static_field_in_class_test.dart
new file mode 100644
index 0000000..d4b351f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_call_on_static_field_in_class_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_call_on_static_field_in_class_test.dart";
+
+code() {
+  Foo.foo = Foo.fooMethod;
+  Foo.fooMethod();
+  Foo.foo();
+}
+
+class Foo {
+  static var foo;
+
+  static void fooMethod() {
+    print("Hello from fooMethod");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // after "code", i.e. on "("
+  "$file:${LINE_A+1}:7", // on "foo"
+  "$file:${LINE_A+2}:7", // on "fooMethod"
+  "$file:${LINE_A+3}:10", // after "foo" (on invisible ".call")
+  "$file:${LINE_A+4}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_catch_test.dart b/runtime/observatory_2/tests/service_2/next_through_catch_test.dart
new file mode 100644
index 0000000..3942e0f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_catch_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_catch_test.dart";
+
+code() {
+  try {
+    var value = "world";
+    throw "Hello, $value";
+  } catch (e, st) {
+    print(e);
+    print(st);
+  }
+  try {
+    throw "Hello, world";
+  } catch (e, st) {
+    print(e);
+    print(st);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+1}:15", // on '='
+  "$file:${LINE_A+2}:26", // after last '"' (i.e. before ';')
+  "$file:${LINE_A+4}:5", // on call to 'print'
+  "$file:${LINE_A+5}:5", // on call to 'print'
+  "$file:${LINE_A+8}:5", // on 'throw'
+  "$file:${LINE_A+10}:5", // on call to 'print'
+  "$file:${LINE_A+11}:5", // on call to 'print'
+  "$file:${LINE_A+13}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_closure_test.dart b/runtime/observatory_2/tests/service_2/next_through_closure_test.dart
new file mode 100644
index 0000000..0c7d8ae
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_closure_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 14;
+const String file = "next_through_closure_test.dart";
+
+codeXYZ(int i) {
+  var x = () =>
+      // some comment here to allow this formatting
+      i * i; // LINE_A
+  return x();
+}
+
+code() {
+  codeXYZ(42);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:9", // on '*'
+  "$file:${LINE_A+0}:7", // on first 'i'
+  "$file:${LINE_A+1}:3", // on 'return'
+  "$file:${LINE_A+6}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_create_list_and_map_test.dart b/runtime/observatory_2/tests/service_2/next_through_create_list_and_map_test.dart
new file mode 100644
index 0000000..523ef13
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_create_list_and_map_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_create_list_and_map_test.dart";
+
+code() {
+  List<int> myList = [
+    1234567890,
+    1234567891,
+    1234567892,
+    1234567893,
+    1234567894
+  ];
+  List<int> myConstList = const [
+    1234567890,
+    1234567891,
+    1234567892,
+    1234567893,
+    1234567894
+  ];
+  Map<int, int> myMap = {
+    1: 42,
+    2: 43,
+    33242344: 432432432,
+    443243232: 543242454
+  };
+  Map<int, int> myConstMap = const {
+    1: 42,
+    2: 43,
+    33242344: 432432432,
+    443243232: 543242454
+  };
+  print(myList);
+  print(myConstList);
+  int lookup = myMap[1];
+  print(lookup);
+  print(myMap);
+  print(myConstMap);
+  print(myMap[2]);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialize list (on '[')
+  "$file:${LINE_A+0}:22",
+
+  // Initialize const list (on '=')
+  "$file:${LINE_A+7}:25",
+
+  // Initialize map (on '{')
+  "$file:${LINE_A+14}:25",
+
+  // Initialize const map (on '=')
+  "$file:${LINE_A+20}:28",
+
+  // Prints (on call to 'print')
+  "$file:${LINE_A+26}:3",
+  "$file:${LINE_A+27}:3",
+
+  // Lookup (on '[')
+  "$file:${LINE_A+28}:21",
+
+  // Prints (on call to 'print')
+  "$file:${LINE_A+29}:3",
+  "$file:${LINE_A+30}:3",
+  "$file:${LINE_A+31}:3",
+
+  // Lookup (on '[') + print (on call to 'print')
+  "$file:${LINE_A+32}:14",
+  "$file:${LINE_A+32}:3",
+
+  // End (on ending '}')
+  "$file:${LINE_A+33}:1"
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_for_each_loop_test.dart b/runtime/observatory_2/tests/service_2/next_through_for_each_loop_test.dart
new file mode 100644
index 0000000..bce2c73
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_for_each_loop_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 12;
+const String file = "next_through_for_each_loop_test.dart";
+
+code() {
+  List<int> data = [1, 2, 3, 4];
+  for (int datapoint in data) {
+    print(datapoint);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialize data (on '[')
+  "$file:${LINE+0}:20",
+
+  // An iteration of the loop is "data", "{", then inside loop
+  // (on call to 'print')
+  "$file:${LINE+1}:25",
+  "$file:${LINE+1}:31",
+  "$file:${LINE+2}:5",
+
+  // Iteration 2
+  "$file:${LINE+1}:25",
+  "$file:${LINE+1}:31",
+  "$file:${LINE+2}:5",
+
+  // Iteration 3
+  "$file:${LINE+1}:25",
+  "$file:${LINE+1}:31",
+  "$file:${LINE+2}:5",
+
+  // Iteration 4
+  "$file:${LINE+1}:25",
+  "$file:${LINE+1}:31",
+  "$file:${LINE+2}:5",
+
+  // End: Apparently we go to data again, then on the final "}"
+  "$file:${LINE+1}:25",
+  "$file:${LINE+4}:1"
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_for_loop_with_break_and_continue_test.dart b/runtime/observatory_2/tests/service_2/next_through_for_loop_with_break_and_continue_test.dart
new file mode 100644
index 0000000..f794803
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_for_loop_with_break_and_continue_test.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_for_loop_with_break_and_continue_test.dart";
+
+code() {
+  int count = 0;
+  for (int i = 0; i < 42; ++i) {
+    if (i == 2) {
+      continue;
+    }
+    if (i == 3) {
+      break;
+    }
+    count++;
+  }
+  print(count);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  // Initialization (on '='), loop start (on '='),
+  // first iteration (on '<', on '==', on '==', on '++')
+  "$file:${LINE_A+0}:13",
+  "$file:${LINE_A+1}:14",
+  "$file:${LINE_A+1}:21",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+8}:10",
+
+  // Second iteration of loop: Full run
+  // (on '++', on '<', on '==', on '==', on '++')
+  "$file:${LINE_A+1}:27",
+  "$file:${LINE_A+1}:21",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+8}:10",
+
+  // Third iteration of loop: continue
+  // (on '++', on '<', on '==', on 'continue')
+  "$file:${LINE_A+1}:27",
+  "$file:${LINE_A+1}:21",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+3}:7",
+
+  // Forth iteration of loop: break
+  // (on '++', on '<', on '==' on '==', on 'break')
+  "$file:${LINE_A+1}:27",
+  "$file:${LINE_A+1}:21",
+  "$file:${LINE_A+2}:11",
+  "$file:${LINE_A+5}:11",
+  "$file:${LINE_A+6}:7",
+
+  // End (on call to 'print' and on ending '}')
+  "$file:${LINE_A+10}:3",
+  "$file:${LINE_A+11}:1"
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_function_expression_test.dart b/runtime/observatory_2/tests/service_2/next_through_function_expression_test.dart
new file mode 100644
index 0000000..ef33331
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_function_expression_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_function_expression_test.dart";
+
+codeXYZ(int i) {
+  innerOne() {
+    return i * i;
+  }
+
+  return innerOne();
+}
+
+code() {
+  codeXYZ(42);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:13", // on 'i' in 'codeXYZ(int i)'
+  "$file:${LINE_A+1}:3", // on 'innerOne'
+  "$file:${LINE_A+5}:18", // on '(', i.e. after 'innerOne' call
+  "$file:${LINE_A+5}:3" // on 'return'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_implicit_call_test.dart b/runtime/observatory_2/tests/service_2/next_through_implicit_call_test.dart
new file mode 100644
index 0000000..35762fa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_implicit_call_test.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 18;
+const String file = "next_through_implicit_call_test.dart";
+
+int _fooCallNumber = 0;
+foo() {
+  ++_fooCallNumber;
+  print("Foo call #$_fooCallNumber!");
+}
+
+code() {
+  foo();
+  (foo)();
+  var a = [foo];
+  a[0]();
+  (a[0])();
+  var b = [
+    [foo, foo]
+  ];
+  b[0][1]();
+  (b[0][1])();
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:3", // on 'foo'
+  "$file:${LINE+1}:8", // on '(' (in '()')
+  "$file:${LINE+2}:11", // on '['
+  "$file:${LINE+3}:4", // on '['
+  "$file:${LINE+3}:7", // on '('
+  "$file:${LINE+4}:5", // on '['
+  "$file:${LINE+4}:9", // on '(' (in '()')
+  "$file:${LINE+6}:5", // on '[' (inner one)
+  "$file:${LINE+5}:11", // on '[' (outer one)
+  "$file:${LINE+8}:4", // on first '['
+  "$file:${LINE+8}:7", // on second '['
+  "$file:${LINE+8}:10", // on '('
+  "$file:${LINE+9}:5", // on first '['
+  "$file:${LINE+9}:8", // on second '['
+  "$file:${LINE+9}:12", // on '(' (in '()')
+  "$file:${LINE+10}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_is_and_as_test.dart b/runtime/observatory_2/tests/service_2/next_through_is_and_as_test.dart
new file mode 100644
index 0000000..886be73
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_is_and_as_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_is_and_as_test.dart";
+
+code() {
+  var i = 42.42;
+  var hex = 0x42;
+  if (i is int) {
+    print("i is int");
+    int x = i as int;
+    if (x.isEven) {
+      print("it's even even!");
+    } else {
+      print("but it's not even even!");
+    }
+  }
+  if (i is! int) {
+    print("i is not int");
+  }
+  if (hex is int) {
+    print("hex is int");
+    int x = hex as dynamic;
+    if (x.isEven) {
+      print("it's even even!");
+    } else {
+      print("but it's not even even!");
+    }
+  }
+  if (hex is! int) {
+    print("hex is not int");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:9", // on '='
+  "$file:${LINE_A+1}:11", // on '"'
+  "$file:${LINE_A+2}:9", // on 'is'
+  "$file:${LINE_A+11}:9", // on 'is!'
+  "$file:${LINE_A+12}:5", // on call to 'print'
+  "$file:${LINE_A+14}:11", // in 'is'
+  "$file:${LINE_A+15}:5", // on call to 'print'
+  "$file:${LINE_A+16}:11", // on 'as'
+  "$file:${LINE_A+17}:11", // on 'isEven'
+  "$file:${LINE_A+18}:7", // on call to 'print'
+  "$file:${LINE_A+23}:11", // on 'is!'
+  "$file:${LINE_A+26}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_multi_catch_test.dart b/runtime/observatory_2/tests/service_2/next_through_multi_catch_test.dart
new file mode 100644
index 0000000..855d6b6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_multi_catch_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 12;
+const String file = "next_through_multi_catch_test.dart";
+
+code() {
+  try {
+    throw "Boom!";
+  } on StateError {
+    print("StateError");
+  } on ArgumentError catch (e) {
+    print("ArgumentError: $e");
+  } catch (e) {
+    print(e);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+1}:5", // on 'throw'
+  "$file:${LINE+2}:5", // on 'on'
+  "$file:${LINE+4}:5", // on 'on'
+  "$file:${LINE+7}:5", // on 'print'
+  "$file:${LINE+9}:1", // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_new_test.dart b/runtime/observatory_2/tests/service_2/next_through_new_test.dart
new file mode 100644
index 0000000..115f707
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_new_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 11;
+const String file = "next_through_new_test.dart";
+
+code() {
+  var x = new Foo();
+  return x;
+}
+
+class Foo {
+  var x;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in 'code()'
+  "$file:${LINE_A+1}:15", // on 'Foo'
+  "$file:${LINE_A+2}:3" // on 'return'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_super_test.dart b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_super_test.dart
new file mode 100644
index 0000000..b67ae51
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_super_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 22;
+const String file = "next_through_operator_bracket_on_super_test.dart";
+
+class Class2 {
+  operator [](index) => index;
+
+  code() {
+    this[42];
+    return this[42];
+  }
+}
+
+class Class3 extends Class2 {
+  code() {
+    super[42];
+    return super[42];
+  }
+}
+
+code() {
+  Class3 c = new Class3();
+  c[42];
+  c.code();
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:10", // on '['
+  "$file:${LINE+1}:17", // on '['
+  "$file:${LINE+1}:5", // on 'return'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_this_test.dart b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_this_test.dart
new file mode 100644
index 0000000..acd3082
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_on_this_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 15;
+const String file = "next_through_operator_bracket_on_this_test.dart";
+
+class Class2 {
+  operator [](index) => index;
+
+  code() {
+    this[42];
+    return this[42];
+  }
+}
+
+code() {
+  Class2 c = new Class2();
+  c[42];
+  c.code();
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:9", // on '['
+  "$file:${LINE+1}:16", // on '['
+  "$file:${LINE+1}:5", // on 'return'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_operator_bracket_test.dart b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_test.dart
new file mode 100644
index 0000000..164479b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_operator_bracket_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 21;
+const String file = "next_through_operator_bracket_test.dart";
+
+class Class2 {
+  operator [](index) => index;
+
+  code() {
+    this[42];
+    return this[42];
+  }
+}
+
+code() {
+  Class2 c = new Class2();
+  c[42];
+  c.code();
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:18", // after 'new', on 'Class2'
+  "$file:${LINE+1}:4", // on '['
+  "$file:${LINE+2}:5", // on 'code'
+  "$file:${LINE+3}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_simple_async_test.dart b/runtime/observatory_2/tests/service_2/next_through_simple_async_test.dart
new file mode 100644
index 0000000..5a3ac87
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_simple_async_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:io';
+
+const int LINE_A = 16;
+const String file = "next_through_simple_async_test.dart";
+
+// line A is at the "code() async" line
+code() async {
+  File f = new File(Platform.script.toFilePath());
+  DateTime modified = await f.lastModified();
+  bool exists = await f.exists();
+  print("Modified: $modified; exists: $exists");
+  foo();
+}
+
+foo() {
+  print("Hello from Foo!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in code()'
+  "$file:${LINE_A+1}:30", // on 'script'
+  "$file:${LINE_A+1}:37", // on 'toFilePath'
+  "$file:${LINE_A+1}:16", // on File
+  "$file:${LINE_A+2}:31", // on 'lastModified'
+  "$file:${LINE_A+2}:23", // on 'await'
+  "$file:${LINE_A+3}:25", // on 'exists'
+  "$file:${LINE_A+3}:17", // on 'await'
+  "$file:${LINE_A+4}:47", // on ')', i.e. before ';'
+  "$file:${LINE_A+4}:3", // on call to 'print'
+  "$file:${LINE_A+5}:3", // on call to 'foo'
+  "$file:${LINE_A+6}:1" // ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_simple_async_with_returns_test.dart b/runtime/observatory_2/tests/service_2/next_through_simple_async_with_returns_test.dart
new file mode 100644
index 0000000..68dca68
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_simple_async_with_returns_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:io';
+
+const int LINE_A = 16;
+const String file = "next_through_simple_async_with_returns_test.dart";
+
+// line A is at the "code() async" line
+code() async {
+  File f = new File(Platform.script.toFilePath());
+  bool exists = await f.exists();
+  if (exists) {
+    return 42;
+  }
+  foo();
+}
+
+foo() {
+  print("Hello from Foo!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:5", // on '(' in 'code()'
+  "$file:${LINE_A+1}:30", // on 'script'
+  "$file:${LINE_A+1}:37", // on 'toFilePath'
+  "$file:${LINE_A+1}:16", // on 'File'
+  "$file:${LINE_A+2}:25", // on 'exists'
+  "$file:${LINE_A+2}:17", // on 'await'
+  "$file:${LINE_A+4}:5" // on 'return'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_simple_linear_2_test.dart b/runtime/observatory_2/tests/service_2/next_through_simple_linear_2_test.dart
new file mode 100644
index 0000000..25bfbd9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_simple_linear_2_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 15;
+const String file = "next_through_simple_linear_2_test.dart";
+
+code() {
+  var a = getA();
+  var b = getB();
+
+  print("Hello, World!"); // LINE_A
+  print("a: $a; b: $b");
+  print("Goodbye, world!");
+}
+
+getA() => true;
+getB() => 42;
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:$LINE_A:3", // on call to 'print'
+  "$file:${LINE_A+1}:23", // on ')', i.e. before ';'
+  "$file:${LINE_A+1}:3", // on call to 'print'
+  "$file:${LINE_A+2}:3", // on call to 'print'
+  "$file:${LINE_A+3}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/next_through_simple_linear_test.dart b/runtime/observatory_2/tests/service_2/next_through_simple_linear_test.dart
new file mode 100644
index 0000000..ae4943e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/next_through_simple_linear_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE_A = 12;
+const String file = "next_through_simple_linear_test.dart";
+
+code() {
+  print("Hello, World!"); // LINE_A
+  print("Stop here too!");
+  print("Goodbye, world!");
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE_A+0}:3", // on call to 'print'
+  "$file:${LINE_A+1}:3", // on call to 'print'
+  "$file:${LINE_A+2}:3", // on call to 'print'
+  "$file:${LINE_A+3}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE_A),
+  runStepThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/object_graph_vm_test.dart b/runtime/observatory_2/tests/service_2/object_graph_vm_test.dart
new file mode 100644
index 0000000..d1cb655
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/object_graph_vm_test.dart
@@ -0,0 +1,150 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/object_graph.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Foo {
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  dynamic left;
+  @pragma("vm:entry-point")
+  dynamic right;
+}
+
+Foo r;
+
+List lst;
+
+void script() {
+  // Create 3 instances of Foo, with out-degrees
+  // 0 (for b), 1 (for a), and 2 (for staticFoo).
+  r = new Foo();
+  var a = new Foo();
+  var b = new Foo();
+  r.left = a;
+  r.right = b;
+  a.left = b;
+
+  lst = new List(2);
+  lst[0] = lst; // Self-loop.
+  // Larger than any other fixed-size list in a fresh heap.
+  lst[1] = new List(1234569);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var graph = await isolate.fetchHeapSnapshot().done;
+
+    Iterable<SnapshotObject> foos =
+        graph.objects.where((SnapshotObject obj) => obj.klass.name == "Foo");
+    expect(foos.length, equals(3));
+
+    SnapshotObject bVertex = foos.singleWhere((SnapshotObject obj) {
+      List<SnapshotObject> successors = obj.successors.toList();
+      return successors[0].klass.name == "Null" &&
+          successors[1].klass.name == "Null";
+    });
+    SnapshotObject aVertex = foos.singleWhere((SnapshotObject obj) {
+      List<SnapshotObject> successors = obj.successors.toList();
+      return successors[0].klass.name == "Foo" &&
+          successors[1].klass.name == "Null";
+    });
+    SnapshotObject rVertex = foos.singleWhere((SnapshotObject obj) {
+      List<SnapshotObject> successors = obj.successors.toList();
+      return successors[0].klass.name == "Foo" &&
+          successors[1].klass.name == "Foo";
+    });
+
+    // TODO(koda): Check actual byte sizes.
+
+    expect(aVertex.retainedSize, equals(aVertex.shallowSize));
+    expect(bVertex.retainedSize, equals(bVertex.shallowSize));
+    expect(
+        rVertex.retainedSize,
+        equals(
+            aVertex.shallowSize + bVertex.shallowSize + rVertex.shallowSize));
+
+    List<SnapshotObject> lists = new List.from(
+        graph.objects.where((SnapshotObject obj) => obj.klass.name == '_List'));
+    expect(lists.length >= 2, isTrue);
+    // Order by decreasing retained size.
+    lists.sort((u, v) => v.retainedSize - u.retainedSize);
+    SnapshotObject first = lists[0];
+    expect(first.successors.length, greaterThanOrEqualTo(2));
+    SnapshotObject second = lists[1];
+    expect(second.successors.length, greaterThanOrEqualTo(1234569));
+    // Check that the short list retains more than the long list inside.
+    // and specifically, that it retains exactly itself + the long one.
+    expect(first.retainedSize, equals(first.shallowSize + second.shallowSize));
+
+    // Verify sizes of classes are the appropriates sums of their instances.
+    // This also verifies that the class instance iterators are visiting the
+    // correct set of objects (e.g., not including dead objects).
+    for (SnapshotClass klass in graph.classes) {
+      int shallowSum = 0;
+      int internalSum = 0;
+      int externalSum = 0;
+      for (SnapshotObject instance in klass.instances) {
+        if (instance == graph.root) {
+          // The root may have 0 self size.
+          expect(instance.internalSize, greaterThanOrEqualTo(0));
+          expect(instance.externalSize, greaterThanOrEqualTo(0));
+          expect(instance.shallowSize, greaterThanOrEqualTo(0));
+        } else {
+          // All other objects are heap objects with positive size.
+          expect(instance.internalSize, greaterThan(0));
+          expect(instance.externalSize, greaterThanOrEqualTo(0));
+          expect(instance.shallowSize, greaterThan(0));
+        }
+        expect(instance.retainedSize, greaterThan(0));
+        expect(instance.shallowSize,
+            equals(instance.internalSize + instance.externalSize));
+        shallowSum += instance.shallowSize;
+        internalSum += instance.internalSize;
+        externalSum += instance.externalSize;
+      }
+      expect(shallowSum, equals(klass.shallowSize));
+      expect(internalSum, equals(klass.internalSize));
+      expect(externalSum, equals(klass.externalSize));
+      expect(
+          klass.shallowSize, equals(klass.internalSize + klass.externalSize));
+    }
+
+    // Verify sizes of the overall graph are the appropriates sums of all
+    // instances. This also verifies that the all instances iterator is visiting
+    // the correct set of objects (e.g., not including dead objects).
+    int shallowSum = 0;
+    int internalSum = 0;
+    int externalSum = 0;
+    for (SnapshotObject instance in graph.objects) {
+      if (instance == graph.root) {
+        // The root may have 0 self size.
+        expect(instance.internalSize, greaterThanOrEqualTo(0));
+        expect(instance.externalSize, greaterThanOrEqualTo(0));
+        expect(instance.shallowSize, greaterThanOrEqualTo(0));
+      } else {
+        // All other objects are heap objects with positive size.
+        expect(instance.internalSize, greaterThan(0));
+        expect(instance.externalSize, greaterThanOrEqualTo(0));
+        expect(instance.shallowSize, greaterThan(0));
+      }
+      expect(instance.retainedSize, greaterThan(0));
+      expect(instance.shallowSize,
+          equals(instance.internalSize + instance.externalSize));
+      shallowSum += instance.shallowSize;
+      internalSum += instance.internalSize;
+      externalSum += instance.externalSize;
+    }
+    expect(shallowSum, equals(graph.size));
+    expect(internalSum, equals(graph.internalSize));
+    expect(externalSum, equals(graph.externalSize));
+    expect(graph.size, equals(graph.internalSize + graph.externalSize));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/observatory_assets_test.dart b/runtime/observatory_2/tests/service_2/observatory_assets_test.dart
new file mode 100644
index 0000000..249acbb
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_assets_test.dart
@@ -0,0 +1,29 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    // Simple heartbeat test to ensure we can fetch Observatory resources.
+    var heartBeatUrl =
+        serviceHttpAddress + '/third_party/trace_viewer_full.html';
+    print('Trying to fetch $heartBeatUrl');
+    HttpClient client = new HttpClient();
+    HttpClientRequest request = await client.getUrl(Uri.parse(heartBeatUrl));
+    HttpClientResponse response = await request.close();
+    expect(response.statusCode, 200);
+    await response.drain();
+  }
+];
+
+main(args) async => runVMTests(
+      args, tests,
+      // TODO(bkonyi): DDS doesn't forward Observatory assets properly yet.
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/observatory_test_package_2/.packages b/runtime/observatory_2/tests/service_2/observatory_test_package_2/.packages
new file mode 100644
index 0000000..684be4e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_test_package_2/.packages
@@ -0,0 +1 @@
+observatory_test_package:.
\ No newline at end of file
diff --git a/runtime/observatory_2/tests/service_2/observatory_test_package_2/has_part.dart b/runtime/observatory_2/tests/service_2/observatory_test_package_2/has_part.dart
new file mode 100644
index 0000000..f59bb93
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_test_package_2/has_part.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library has_part;
+
+part 'the_part.dart';
+part 'the_part_2.dart';
+
+barz() {
+  print('in bar!');
+}
+
+fooz() {
+  print('in foo!');
+  bar();
+}
+
+main() {
+  Foo10 foo = new Foo10("Foo!");
+  print(foo);
+}
diff --git a/runtime/observatory_2/tests/service_2/observatory_test_package_2/pubspec.yaml b/runtime/observatory_2/tests/service_2/observatory_test_package_2/pubspec.yaml
new file mode 100644
index 0000000..db61a01f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_test_package_2/pubspec.yaml
@@ -0,0 +1,4 @@
+name: observatory_test_package
+publish_to: none
+environment:
+  sdk: '^2.7.0'
diff --git a/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part.dart b/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part.dart
new file mode 100644
index 0000000..d8545f8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of has_part;
+
+void foo() {
+  print("lalala");
+}
+
+class Foo1 {
+  final foo;
+
+  Foo1(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo2 {
+  final foo;
+
+  Foo2(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo3 {
+  final foo;
+
+  Foo3(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo4 {
+  final foo;
+
+  Foo4(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo5 {
+  final foo;
+
+  Foo5(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo6 {
+  final foo;
+
+  Foo6(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo7 {
+  final foo;
+
+  Foo7(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo8 {
+  final foo;
+
+  Foo8(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo9 {
+  final foo;
+
+  Foo9(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+class Foo10 {
+  final foo;
+
+  Foo10(this.foo) {
+    print("hello from foo!");
+  }
+}
+
+var foo2 = foo() as dynamic;
diff --git a/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part_2.dart b/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part_2.dart
new file mode 100644
index 0000000..c38df9c
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/observatory_test_package_2/the_part_2.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of has_part;
+
+void bar() {
+  print('Should break here');
+}
diff --git a/runtime/observatory_2/tests/service_2/parameters_in_scope_at_entry_test.dart b/runtime/observatory_2/tests/service_2/parameters_in_scope_at_entry_test.dart
new file mode 100644
index 0000000..d6c2d7b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/parameters_in_scope_at_entry_test.dart
@@ -0,0 +1,72 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:observatory_2/service_io.dart';
+import 'test_helper.dart';
+import 'dart:developer';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+
+const int LINE_A = 30;
+const int LINE_B = 34;
+
+foo(param) {
+  return param;
+}
+
+fooClosure() {
+  theClosureFunction(param) {
+    return param;
+  }
+
+  return theClosureFunction;
+}
+
+testMain() {
+  debugger();
+  foo("in-scope"); // Line A.
+
+  var f = fooClosure();
+  debugger();
+  f("in-scope"); // Line B.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (isolate) => isolate.stepInto(),
+  hasStoppedAtBreakpoint,
+  (isolate) async {
+    var stack = await isolate.getStack();
+    Frame top = stack['frames'][0];
+    print(top);
+    expect(top.function.name, equals("foo"));
+    print(top.variables);
+    expect(top.variables.length, equals(1));
+    var param = top.variables[0];
+    expect(param['name'], equals("param"));
+    expect(param['value'].valueAsString, equals("in-scope"));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (isolate) => isolate.stepInto(),
+  hasStoppedAtBreakpoint,
+  (isolate) async {
+    var stack = await isolate.getStack();
+    Frame top = stack['frames'][0];
+    print(top);
+    expect(top.function.name, equals("theClosureFunction"));
+    print(top.variables);
+    expect(top.variables.length, equals(1));
+    var param = top.variables[0];
+    expect(param['name'], equals("param"));
+    expect(param['value'].valueAsString, equals("in-scope"));
+  },
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/pause_idle_isolate_test.dart b/runtime/observatory_2/tests/service_2/pause_idle_isolate_test.dart
new file mode 100644
index 0000000..06b0689
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_idle_isolate_test.dart
@@ -0,0 +1,52 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'dart:io';
+import 'dart:isolate' show ReceivePort;
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+var receivePort;
+
+void testMain() {
+  receivePort = new ReceivePort();
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    print('Resuming...');
+    await isolate.resume();
+
+    // Wait for the isolate to become idle.  We detect this by querying
+    // the stack until it becomes empty.
+    var frameCount;
+    do {
+      var stack = await isolate.getStack();
+      frameCount = stack['frames'].length;
+      print('Frames: $frameCount');
+      sleep(const Duration(milliseconds: 10));
+    } while (frameCount > 0);
+    print('Isolate is idle.');
+    await isolate.reload();
+    expect(isolate.pauseEvent is M.ResumeEvent, isTrue);
+
+    // Make sure that the isolate receives an interrupt even when it is
+    // idle. (https://github.com/dart-lang/sdk/issues/24349)
+    var interruptFuture = hasPausedFor(isolate, ServiceEvent.kPauseInterrupted);
+    print('Pausing...');
+    await isolate.pause();
+    await interruptFuture;
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain,
+    verbose_vm: true,
+    extraArgs: ['--trace-service', '--trace-service-verbose']);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_exceptions_test.dart b/runtime/observatory_2/tests/service_2/pause_on_exceptions_test.dart
new file mode 100644
index 0000000..fa506c9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_exceptions_test.dart
@@ -0,0 +1,105 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+}
+
+doCaught() {
+  try {
+    doThrow();
+  } catch (e) {}
+  return "end of doCaught";
+}
+
+doUncaught() {
+  doThrow();
+  return "end of doUncaught";
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.reload();
+
+    var onPaused = null;
+    var onResume = null;
+
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      print("Event $event");
+      if (event.kind == ServiceEvent.kPauseException) {
+        if (onPaused == null) throw "Unexpected pause event $event";
+        var t = onPaused;
+        onPaused = null;
+        t.complete(event);
+      }
+      if (event.kind == ServiceEvent.kResume) {
+        if (onResume == null) throw "Unexpected resume event $event";
+        var t = onResume;
+        onResume = null;
+        t.complete(event);
+      }
+    });
+
+    test(String pauseMode, String expression, bool shouldPause,
+        bool shouldBeCaught) async {
+      print("Evaluating $expression with pause on $pauseMode exception");
+
+      expect((await isolate.setExceptionPauseMode(pauseMode)) is DartError,
+          isFalse);
+
+      var t;
+      if (shouldPause) {
+        t = new Completer();
+        onPaused = t;
+      }
+      var fres = lib.evaluate(expression);
+      if (shouldPause) {
+        await t.future;
+
+        var stack = await isolate.getStack();
+        expect(stack['frames'][0].function.name, equals('doThrow'));
+        // Ugh, no .line. expect(stack['frames'][0].location.line, equals(17));
+
+        t = new Completer();
+        onResume = t;
+        isolate.resume();
+        await t.future;
+      }
+
+      dynamic res = await fres;
+      print(res);
+      if (shouldBeCaught) {
+        expect(res.isInstance, isTrue);
+        expect(res.isString, isTrue);
+        expect(res.valueAsString, equals("end of doCaught"));
+      } else {
+        expect(res.isError, isTrue);
+        await res.load(); // Weird?
+        expect(res.exception.isInstance, isTrue);
+        expect(res.exception.isString, isTrue);
+        expect(res.exception.valueAsString, equals("TheException"));
+      }
+    }
+
+    await test("All", "doCaught()", true, true);
+    await test("All", "doUncaught()", true, false);
+
+    await test("Unhandled", "doCaught()", false, true);
+    await test("Unhandled", "doUncaught()", true, false);
+
+    await test("None", "doCaught()", false, true);
+    await test("None", "doUncaught()", false, false);
+
+    subscription.cancel();
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_test.dart b/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_test.dart
new file mode 100644
index 0000000..b4a1dd9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_test.dart
@@ -0,0 +1,86 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+void testMain() {
+  print('Hello');
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    print('Getting stream...');
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    print('Subscribing...');
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseStart) {
+        print('Received $event');
+        subscription.cancel();
+        completer.complete();
+      } else {
+        print('Ignoring event $event');
+      }
+    });
+    print('Subscribed.  Pause event is ${isolate.pauseEvent}');
+
+    if (isolate.pauseEvent != null && isolate.pauseEvent is M.PauseStartEvent) {
+      // Wait for the isolate to hit PauseStart.
+      subscription.cancel();
+      print('Subscription cancelled.');
+    } else {
+      print('Waiting for pause start event.');
+      await completer.future;
+    }
+    print('Done waiting for pause event.');
+
+    // Grab the timestamp.
+    var pausetime1 = isolate.pauseEvent.timestamp;
+    expect(pausetime1, isNotNull);
+    // Reload the isolate.
+    await isolate.reload();
+    // Verify that it is the same.
+    expect(pausetime1.millisecondsSinceEpoch,
+        equals(isolate.pauseEvent.timestamp.millisecondsSinceEpoch));
+
+    completer = new Completer();
+    stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseExit) {
+        print('Received PauseExit');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    print('Resuming...');
+    isolate.resume();
+
+    // Wait for the isolate to hit PauseExit.
+    await completer.future;
+
+    // Grab the timestamp.
+    var pausetime2 = isolate.pauseEvent.timestamp;
+    expect(pausetime2, isNotNull);
+    // Reload the isolate.
+    await isolate.reload();
+    // Verify that it is the same.
+    expect(pausetime2.millisecondsSinceEpoch,
+        equals(isolate.pauseEvent.timestamp.millisecondsSinceEpoch));
+    expect(pausetime2.millisecondsSinceEpoch,
+        greaterThan(pausetime1.millisecondsSinceEpoch));
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain,
+    pause_on_start: true,
+    pause_on_exit: true,
+    verbose_vm: true,
+    extraArgs: ['--trace-service', '--trace-service-verbose']);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_with_child_test.dart b/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_with_child_test.dart
new file mode 100644
index 0000000..c2f9bde
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_start_and_exit_with_child_test.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:isolate' as isolate;
+
+void child(message) {
+  print("Child got initial message");
+  message.send(null);
+}
+
+void testMain() {
+  var port = new isolate.RawReceivePort();
+  port.handler = (message) {
+    print("Parent got response");
+    port.close();
+  };
+
+  isolate.Isolate.spawn(child, port.sendPort);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    VM vm = isolate.vm;
+
+    print('Getting stream...');
+    Completer completer = new Completer();
+    var stream = await vm.getEventStream(VM.kDebugStream);
+    print('Subscribing...');
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.isolate == isolate && event.kind == ServiceEvent.kPauseStart) {
+        print('Received $event');
+        subscription.cancel();
+        completer.complete();
+      } else {
+        print('Ignoring event $event');
+      }
+    });
+    print('Subscribed.  Pause event is ${isolate.pauseEvent}');
+
+    if (isolate.pauseEvent != null && isolate.pauseEvent is M.PauseStartEvent) {
+      // Wait for the isolate to hit PauseStart.
+      subscription.cancel();
+      print('Subscription cancelled.');
+    } else {
+      print('Waiting for pause start event.');
+      await completer.future;
+    }
+    print('Done waiting for pause event.');
+
+    expect(isolate.pauseEvent, isNotNull);
+    expect(isolate.pauseEvent is M.PauseStartEvent, isTrue);
+
+    print("Disabling pause_isolates_on_start");
+    var params = {
+      'name': 'pause_isolates_on_start',
+      'value': 'false',
+    };
+    var result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+
+    print("Disabling pause_isolates_on_exit");
+    params = {
+      'name': 'pause_isolates_on_exit',
+      'value': 'false',
+    };
+    result = await vm.invokeRpcNoUpgrade('setFlag', params);
+    expect(result['type'], equals('Success'));
+
+    completer = new Completer();
+    stream = await vm.getEventStream(VM.kDebugStream);
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.isolate == isolate && event.kind == ServiceEvent.kPauseExit) {
+        print('Received PauseExit');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    print('Resuming at start...');
+    isolate.resume();
+
+    // Wait for the isolate to hit PauseExit.
+    await completer.future;
+
+    expect(isolate.pauseEvent, isNotNull);
+    expect(isolate.pauseEvent is M.PauseExitEvent, isTrue);
+
+    print('Resuming at exit...');
+    isolate.resume();
+
+    // Nothing else keeping the VM around. In particular, the child isolate
+    // won't pause on exit.
+    await vm.onDisconnect;
+  },
+];
+
+main(args) => runIsolateTests(
+      args, tests,
+      testeeConcurrent: testMain,
+      pause_on_start: true,
+      pause_on_exit: true,
+      verbose_vm: true,
+      extraArgs: [
+        '--trace-service',
+        '--trace-service-verbose',
+      ],
+      // TODO(bkonyi): investigate failure.
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/pause_on_start_then_step_test.dart b/runtime/observatory_2/tests/service_2/pause_on_start_then_step_test.dart
new file mode 100644
index 0000000..c80ad79
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_start_then_step_test.dart
@@ -0,0 +1,94 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+void testMain() {
+  print('Hello');
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    print('Getting stream...');
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    print('Subscribing...');
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseStart) {
+        print('Received $event');
+        subscription.cancel();
+        completer.complete();
+      } else {
+        print('Ignoring event $event');
+      }
+    });
+    print('Subscribed.  Pause event is ${isolate.pauseEvent}');
+
+    if (isolate.pauseEvent != null && isolate.pauseEvent is M.PauseStartEvent) {
+      // Wait for the isolate to hit PauseStart.
+      subscription.cancel();
+      print('Subscription cancelled.');
+    } else {
+      print('Waiting for pause start event.');
+      await completer.future;
+    }
+    print('Done waiting for pause event.');
+
+    // Grab the timestamp.
+    var pausetime1 = isolate.pauseEvent.timestamp;
+    expect(pausetime1, isNotNull);
+    // Reload the isolate.
+    await isolate.reload();
+    // Verify that it is the same.
+    expect(pausetime1.millisecondsSinceEpoch,
+        equals(isolate.pauseEvent.timestamp.millisecondsSinceEpoch));
+
+    completer = new Completer();
+    stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print('Received PauseBreakpoint');
+        subscription.cancel();
+        completer.complete();
+      }
+      print('Got ${event.kind}');
+    });
+
+    print('Stepping...');
+    isolate.stepInto();
+
+    // Wait for the isolate to hit PauseBreakpoint.
+    print('Waiting for PauseBreakpoint');
+    await completer.future;
+
+    // Grab the timestamp.
+    print('Getting pausevent timestamp');
+    var pausetime2 = isolate.pauseEvent.timestamp;
+    expect(pausetime2, isNotNull);
+    // Reload the isolate.
+    print('Reloading isolate');
+    await isolate.reload();
+    print('Reload finished');
+    // Verify that it is the same.
+    expect(pausetime2.millisecondsSinceEpoch,
+        equals(isolate.pauseEvent.timestamp.millisecondsSinceEpoch));
+
+    expect(pausetime2.millisecondsSinceEpoch,
+        greaterThan(pausetime1.millisecondsSinceEpoch));
+
+    print('Test finished');
+  },
+];
+
+main(args) => runIsolateTests(args, tests,
+    testeeConcurrent: testMain,
+    pause_on_start: true,
+    pause_on_exit: true,
+    verbose_vm: true,
+    extraArgs: ['--trace-service', '--trace-service-verbose']);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions2_test.dart b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions2_test.dart
new file mode 100644
index 0000000..fa4bf52
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions2_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async_debugger --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async_debugger --causal-async-stacks --no-lazy-async-stacks
+// VMOptions=--async_debugger --no-causal-async-stacks --lazy-async-stacks --optimization-counter-threshold=5
+// VMOptions=--async_debugger --causal-async-stacks --no-lazy-async-stacks --optimization-counter-threshold=5
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const LINE_A = 37;
+
+class Foo {}
+
+doThrow() {
+  throw "TheException"; // Line 13.
+  return "end of doThrow";
+}
+
+asyncThrower() async {
+  await 0; // force async gap
+  doThrow();
+}
+
+testeeMain() async {
+  // Trigger optimization via OSR.
+  var s = 0;
+  for (var i = 0; i < 100; i++) {
+    s += i;
+  }
+  print(s);
+  // No try ... catch.
+  await asyncThrower(); // LINE_A
+}
+
+var tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    print("We stopped!");
+    var stack = await isolate.getStack();
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    expect(asyncStack.length, greaterThanOrEqualTo(4));
+    expect(asyncStack[0].toString(), contains('doThrow'));
+    expect(asyncStack[1].toString(), contains('asyncThrower'));
+    expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+    expect(asyncStack[3].toString(), contains('testeeMain'));
+    expect(
+        await asyncStack[3].location.toUserString(), contains('.dart:$LINE_A'));
+  }
+];
+
+main(args) => runIsolateTests(
+      args,
+      tests,
+      pause_on_unhandled_exceptions: true,
+      testeeConcurrent: testeeMain,
+      extraArgs: extraDebuggingArgs,
+      // TODO(bkonyi): causes ASSERT in debug mode, unrelated to DDS.
+      // See https://github.com/dart-lang/sdk/issues/41379.
+      enableDds: false,
+    );
diff --git a/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions3_test.dart b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions3_test.dart
new file mode 100644
index 0000000..ea5a7cc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions3_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that debugger can stop on an unhandled exception thrown from async
+// function. Regression test for https://dartbug.com/38697.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const LINE_A = 18;
+const LINE_B = 23;
+const LINE_C = 26;
+
+throwException() async {
+  throw 'exception'; // LINE_A
+}
+
+testeeMain() async {
+  try {
+    await throwException(); // LINE_B
+  } finally {
+    try {
+      await throwException(); // LINE_C
+    } finally {}
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    print("Stopped!");
+    var stack = await isolate.getStack();
+    expect(stack['frames'][0].function.toString(), contains('throwException'));
+  },
+  resumeIsolate,
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    print(stack['frames'][0]);
+    // await in testeeMain
+    expect(await stack['frames'][0].location.toUserString(),
+        contains('.dart:${LINE_B}'));
+  },
+  resumeIsolate,
+  hasStoppedWithUnhandledException,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+    print(stack['frames'][0]);
+    expect(await stack['frames'][0].location.toUserString(),
+        contains('.dart:${LINE_C}'));
+  }
+];
+
+main(args) => runIsolateTests(args, tests,
+    pause_on_unhandled_exceptions: true, testeeConcurrent: testeeMain);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions_test.dart b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions_test.dart
new file mode 100644
index 0000000..da16126
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_unhandled_async_exceptions_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--async_debugger --no-causal-async-stacks --lazy-async-stacks
+// VMOptions=--async_debugger --causal-async-stacks --no-lazy-async-stacks
+
+import 'package:observatory_2/service_io.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const LINE_A = 36;
+
+class Foo {}
+
+doThrow() {
+  throw "TheException"; // Line 13.
+  return "end of doThrow";
+}
+
+asyncThrower() async {
+  await 0; // force async gap
+  doThrow();
+}
+
+testeeMain() async {
+  try {
+    // caught.
+    try {
+      await asyncThrower();
+    } catch (e) {}
+
+    // uncaught.
+    try {
+      await asyncThrower(); // LINE_A.
+    } on double catch (e) {}
+  } on Foo catch (e) {}
+}
+
+var tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    print("We stopped!");
+    var stack = await isolate.getStack();
+    expect(stack['asyncCausalFrames'], isNotNull);
+    var asyncStack = stack['asyncCausalFrames'];
+    if (useCausalAsyncStacks) {
+      expect(asyncStack.length, greaterThanOrEqualTo(4));
+      expect(asyncStack[0].toString(), contains('doThrow'));
+      expect(asyncStack[1].toString(), contains('asyncThrower'));
+      expect(asyncStack[2].kind, equals(M.FrameKind.asyncSuspensionMarker));
+      expect(asyncStack[3].toString(), contains('testeeMain'));
+      // We've stopped at LINE_A.
+      expect(await asyncStack[3].location.toUserString(),
+          contains('.dart:$LINE_A'));
+    } else {
+      expect(asyncStack.length, greaterThanOrEqualTo(2));
+      expect(asyncStack[0].toString(), contains('doThrow'));
+      expect(asyncStack[1].toString(), contains('asyncThrower'));
+      // There was no await'er for "doThrow()".
+    }
+  }
+];
+
+main(args) => runIsolateTests(args, tests,
+    pause_on_unhandled_exceptions: true,
+    testeeConcurrent: testeeMain,
+    extraArgs: extraDebuggingArgs);
diff --git a/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_test.dart b/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_test.dart
new file mode 100644
index 0000000..eeb81e6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/pause_on_unhandled_exceptions_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+doThrow() {
+  throw "TheException"; // Line 13.
+  return "end of doThrow";
+}
+
+var tests = <IsolateTest>[
+  hasStoppedWithUnhandledException,
+  (Isolate isolate) async {
+    print("We stopped!");
+    var stack = await isolate.getStack();
+    expect(stack['frames'][0].function.name, equals('doThrow'));
+  }
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    pause_on_unhandled_exceptions: true, testeeConcurrent: doThrow);
diff --git a/runtime/observatory_2/tests/service_2/positive_token_pos_test.dart b/runtime/observatory_2/tests/service_2/positive_token_pos_test.dart
new file mode 100644
index 0000000..ed4d46e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/positive_token_pos_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+helper() async {
+  // Line 12, Col 16 is the open brace.
+}
+
+testMain() {
+  debugger();
+  helper(); // Line 18, Col 3 is the position of the function call.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(18),
+  stepInto,
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['frames'].length, greaterThan(2));
+
+    // We used to return a negative token position for this frame.
+    // See issue #27128.
+    var frame = stack['frames'][0];
+    expect(frame.function.qualifiedName, equals('helper.async_op'));
+    expect(await frame.location.getLine(), equals(14));
+    expect(await frame.location.getColumn(), equals(1));
+
+    frame = stack['frames'][1];
+    expect(frame.function.name, equals('testMain'));
+    expect(await frame.location.getLine(), equals(18));
+    expect(await frame.location.getColumn(), equals(3));
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/process_service_test.dart b/runtime/observatory_2/tests/service_2/process_service_test.dart
new file mode 100644
index 0000000..b008313
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/process_service_test.dart
@@ -0,0 +1,141 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final dartJITBinary = path.join(path.dirname(io.Platform.resolvedExecutable),
+    'dart' + path.extension(io.Platform.resolvedExecutable));
+
+Future setupProcesses() async {
+  final dir = await io.Directory.systemTemp.createTemp('file_service');
+
+  final args = [
+    ...io.Platform.executableArguments,
+    '--pause_isolates_on_start',
+    io.Platform.script.toFilePath(),
+  ];
+  io.Process process1;
+  io.Process process2;
+  io.Process process3;
+
+  void closeDown() {
+    if (process1 != null) {
+      process1.kill();
+    }
+    if (process2 != null) {
+      process2.kill();
+    }
+    if (process3 != null) {
+      process3.kill();
+    }
+    dir.deleteSync(recursive: true);
+  }
+
+  Future<ServiceExtensionResponse> cleanup(ignored_a, ignored_b) {
+    closeDown();
+    final result = jsonEncode({'type': 'foobar'});
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> setup(ignored_a, ignored_b) async {
+    try {
+      process1 = await io.Process.start(io.Platform.executable, args);
+      process2 =
+          await io.Process.start(io.Platform.executable, args..add('foobar'));
+      final codeFilePath = dir.path + io.Platform.pathSeparator + "other_file";
+      final codeFile = io.File(codeFilePath);
+      await codeFile.writeAsString('''
+          import "dart:io";
+
+          void main() async {
+            await stdin.drain();
+          }
+          ''');
+      process3 = await io.Process.start(
+          dartJITBinary, [...io.Platform.executableArguments, codeFilePath]);
+    } catch (_) {
+      closeDown();
+      rethrow;
+    }
+
+    final result = jsonEncode({
+      'type': 'foobar',
+      'pids': [process1.pid, process2.pid, process3.pid]
+    });
+    return Future.value(ServiceExtensionResponse.result(result));
+  }
+
+  Future<ServiceExtensionResponse> closeStdin(ignored_a, ignored_b) {
+    process3.stdin.close();
+    return process3.exitCode.then<ServiceExtensionResponse>((int exit) {
+      final result = jsonEncode({'type': 'foobar'});
+      return ServiceExtensionResponse.result(result);
+    });
+  }
+
+  registerExtension('ext.dart.io.cleanup', cleanup);
+  registerExtension('ext.dart.io.setup', setup);
+  registerExtension('ext.dart.io.closeStdin', closeStdin);
+}
+
+final processTests = <IsolateTest>[
+  // Initial.
+  (Isolate isolate) async {
+    final setup = await isolate.invokeRpcNoUpgrade('ext.dart.io.setup', {});
+    try {
+      var all = await isolate
+          .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {});
+      expect(all['type'], equals('SpawnedProcessList'));
+
+      expect(all['processes'].length, equals(3));
+
+      final first = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][0]['id']});
+      expect(first['name'], io.Platform.executable);
+      expect(first['pid'], equals(setup['pids'][0]));
+      expect(first['arguments'].contains('foobar'), isFalse);
+      expect(first['startedAt'], greaterThan(0));
+
+      final second = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][1]['id']});
+      expect(second['name'], io.Platform.executable);
+      expect(second['pid'], equals(setup['pids'][1]));
+      expect(second['arguments'].contains('foobar'), isTrue);
+      expect(second['pid'] != first['pid'], isTrue);
+      expect(second['startedAt'], greaterThan(0));
+      expect(second['startedAt'], greaterThanOrEqualTo(first['startedAt']));
+
+      final third = await isolate.invokeRpcNoUpgrade(
+          'ext.dart.io.getSpawnedProcessById',
+          {'id': all['processes'][2]['id']});
+      expect(third['name'], dartJITBinary);
+      expect(third['pid'], equals(setup['pids'][2]));
+      expect(third['pid'] != first['pid'], isTrue);
+      expect(third['pid'] != second['pid'], isTrue);
+      expect(third['startedAt'], greaterThanOrEqualTo(second['startedAt']));
+
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.closeStdin', {});
+      all = await isolate
+          .invokeRpcNoUpgrade('ext.dart.io.getSpawnedProcesses', {});
+      expect(all['type'], equals('SpawnedProcessList'));
+      expect(all['processes'].length, equals(2));
+    } finally {
+      await isolate.invokeRpcNoUpgrade('ext.dart.io.cleanup', {});
+    }
+  },
+];
+
+main(args) async =>
+    runIsolateTests(args, processTests, testeeBefore: setupProcesses);
diff --git a/runtime/observatory_2/tests/service_2/reachable_size_test.dart b/runtime/observatory_2/tests/service_2/reachable_size_test.dart
new file mode 100644
index 0000000..f92962d
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/reachable_size_test.dart
@@ -0,0 +1,74 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+class Pair {
+  // Make sure these fields are not removed by the tree shaker.
+  @pragma("vm:entry-point")
+  var x;
+  @pragma("vm:entry-point")
+  var y;
+}
+
+var p1;
+var p2;
+
+buildGraph() {
+  p1 = new Pair();
+  p2 = new Pair();
+
+  // Adds to both reachable and retained size.
+  p1.x = new List();
+  p2.x = new List();
+
+  // Adds to reachable size only.
+  p1.y = p2.y = new List();
+}
+
+Future<int> getReachableSize(ServiceObject obj) async {
+  Instance size = await obj.isolate.getReachableSize(obj);
+  return int.parse(size.valueAsString);
+}
+
+Future<int> getRetainedSize(ServiceObject obj) async {
+  Instance size = await obj.isolate.getRetainedSize(obj);
+  return int.parse(size.valueAsString);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Instance p1 = await rootLibraryFieldValue(isolate, "p1");
+    Instance p2 = await rootLibraryFieldValue(isolate, "p2");
+
+    // In general, shallow <= retained <= reachable. In this program,
+    // 0 < shallow < retained < reachable.
+
+    int p1_shallow = p1.size;
+    int p1_retained = await getRetainedSize(p1);
+    int p1_reachable = await getReachableSize(p1);
+
+    expect(0, lessThan(p1_shallow));
+    expect(p1_shallow, lessThan(p1_retained));
+    expect(p1_retained, lessThan(p1_reachable));
+
+    int p2_shallow = p2.size;
+    int p2_retained = await getRetainedSize(p2);
+    int p2_reachable = await getReachableSize(p2);
+
+    expect(0, lessThan(p2_shallow));
+    expect(p2_shallow, lessThan(p2_retained));
+    expect(p2_retained, lessThan(p2_reachable));
+
+    expect(p1_shallow, equals(p2_shallow));
+    expect(p1_retained, equals(p2_retained));
+    expect(p1_reachable, equals(p2_reachable));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: buildGraph);
diff --git a/runtime/observatory_2/tests/service_2/regexp_function_test.dart b/runtime/observatory_2/tests/service_2/regexp_function_test.dart
new file mode 100644
index 0000000..73f95b9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regexp_function_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=
+// VMOptions=--interpret_irregexp
+
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+// Make sure these variables are not removed by the tree shaker.
+@pragma("vm:entry-point")
+var regex0;
+@pragma("vm:entry-point")
+var regex;
+
+void script() {
+  // Check the internal NUL doesn't trip up the name scrubbing in the vm.
+  regex0 = new RegExp("with internal \u{0} NUL");
+  regex = new RegExp(r"(\w+)");
+  String str = "Parse my string";
+  Iterable<Match> matches = regex.allMatches(str); // Run to generate bytecode.
+  Expect.equals(matches.length, 3);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = isolate.rootLibrary;
+    await lib.load();
+
+    Field field0 = lib.variables.singleWhere((v) => v.name == 'regex0');
+    await field0.load(); // No crash due to embedded NUL.
+
+    Field field = lib.variables.singleWhere((v) => v.name == 'regex');
+    await field.load();
+    Instance regex = field.staticValue;
+    expect(regex.isInstance, isTrue);
+    expect(regex.isRegExp, isTrue);
+    await regex.load();
+
+    if (regex.oneByteFunction == null) {
+      // Running with interpreted regexp.
+      var b1 = await regex.oneByteBytecode.load();
+      expect(b1.isTypedData, isTrue);
+      var b2 = await regex.twoByteBytecode.load();
+      expect(b2.isTypedData, isFalse); // No two-byte string subject was used.
+    } else {
+      // Running with compiled regexp.
+      var f1 = await regex.oneByteFunction.load();
+      expect(f1 is ServiceFunction, isTrue);
+      var f2 = await regex.twoByteFunction.load();
+      expect(f2 is ServiceFunction, isTrue);
+      var f3 = await regex.externalOneByteFunction.load();
+      expect(f3 is ServiceFunction, isTrue);
+      var f4 = await regex.externalTwoByteFunction.load();
+      expect(f4 is ServiceFunction, isTrue);
+    }
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/regress_28443_test.dart b/runtime/observatory_2/tests/service_2/regress_28443_test.dart
new file mode 100644
index 0000000..ddc48fa
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regress_28443_test.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+const int LINE_A = 28, LINE_B = 33;
+
+class VMServiceClient {
+  VMServiceClient(this.x);
+  close() => new Future.microtask(() => print("close"));
+  var x;
+}
+
+collect() async {
+  var uri = "abc";
+  var vmService;
+  await new Future.microtask(() async {
+    try {
+      vmService = new VMServiceClient(uri);
+      await new Future.microtask(() => throw new TimeoutException("here"));
+    } on dynamic {
+      vmService.close();
+      rethrow; // LINE_A
+    }
+  });
+}
+
+test_code() async {
+  try {
+    await collect();
+  } on TimeoutException {
+    print("ok");
+  }
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  markDartColonLibrariesDebuggable,
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  setBreakpointAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stepOut,
+  stoppedAtLine(LINE_B),
+  resumeIsolate
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: test_code, pause_on_start: true, pause_on_exit: false);
diff --git a/runtime/observatory_2/tests/service_2/regress_28980_test.dart b/runtime/observatory_2/tests/service_2/regress_28980_test.dart
new file mode 100644
index 0000000..3bdf993
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regress_28980_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+const int LINE_A = 19, LINE_B = 38;
+
+var _lock;
+var _lockEnabled = true;
+
+String flutterRoot = "abc";
+
+foo(a, b, c, d) {
+  return new A(); // LINE_A
+}
+
+class A {
+  Future lock() => new Future.microtask(() => print("lock"));
+  String path = "path";
+}
+
+class FileSystemException {}
+
+Future<Null> test_code() async {
+  if (!_lockEnabled) return null;
+  assert(_lock == null);
+  _lock = foo(flutterRoot, 'bin', 'cache', 'lockfile');
+  bool locked = false;
+  bool printed = false;
+  while (!locked) {
+    try {
+      await _lock.lock();
+      locked = true; // LINE_B
+    } on FileSystemException {
+      if (!printed) {
+        print('Print path: ${_lock.path}');
+        print('Just another line...');
+        printed = true;
+      }
+      await new Future<Null>.delayed(const Duration(milliseconds: 50));
+    }
+  }
+}
+
+Future stepThroughProgram(Isolate isolate) async {
+  Completer completer = new Completer();
+  int pauseEventsSeen = 0;
+
+  await subscribeToStream(isolate.vm, VM.kDebugStream,
+      (ServiceEvent event) async {
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      // We are paused: Step further.
+      pauseEventsSeen++;
+      isolate.stepInto();
+    } else if (event.kind == ServiceEvent.kPauseExit) {
+      // We are at the exit: The test is done.
+      expect(pauseEventsSeen > 20, true,
+          reason: "Saw only $pauseEventsSeen pause events.");
+      await cancelStreamSubscription(VM.kDebugStream);
+      completer.complete();
+    }
+  });
+  isolate.resume();
+  return completer.future;
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  markDartColonLibrariesDebuggable,
+  setBreakpointAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stepInto,
+  stepInto,
+  stepInto,
+  resumeIsolate,
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: test_code, pause_on_start: true, pause_on_exit: false);
diff --git a/runtime/observatory_2/tests/service_2/regress_34841_lib.dart b/runtime/observatory_2/tests/service_2/regress_34841_lib.dart
new file mode 100644
index 0000000..60eb3e4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regress_34841_lib.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  String baz() => StackTrace.current.toString();
+  final String foo = () {
+    return StackTrace.current.toString();
+  }();
+}
diff --git a/runtime/observatory_2/tests/service_2/regress_34841_test.dart b/runtime/observatory_2/tests/service_2/regress_34841_test.dart
new file mode 100644
index 0000000..d3c208a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/regress_34841_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// While it's not (currently) necessary, add some noise here to push down token
+// positions in this file compared to the file regress_34841_lib.dart.
+// This is to ensure that any possible tokens in that file are just comments
+// (i.e. not actual) positions in this file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+import 'regress_34841_lib.dart';
+
+class Bar extends Object with Foo {}
+
+void testFunction() {
+  Bar bar = new Bar();
+  print(bar.foo);
+  print(bar.baz());
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    Script script = root.scripts.first;
+    await script.load();
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': script.id,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    List<dynamic> ranges = report['ranges'];
+    List<int> coveragePlaces = <int>[];
+    for (var range in ranges) {
+      for (int i in range["coverage"]["hits"]) {
+        coveragePlaces.add(i);
+      }
+      for (int i in range["coverage"]["misses"]) {
+        coveragePlaces.add(i);
+      }
+    }
+
+    // Make sure we can translate it all.
+    for (int place in coveragePlaces) {
+      int line = script.tokenToLine(place);
+      int column = script.tokenToCol(place);
+      if (line == null || column == null) {
+        throw "Token $place translated to $line:$column";
+      }
+    }
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/reload_sources_test.dart b/runtime/observatory_2/tests/service_2/reload_sources_test.dart
new file mode 100644
index 0000000..b2ff5a9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/reload_sources_test.dart
@@ -0,0 +1,40 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'dart:developer';
+import 'service_test_common.dart';
+
+testMain() {
+  debugger(); // Stop here.
+  print('1');
+  while (true) {}
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Reload sources and request to pause post reload. The pause request will be
+  // ignored because we are already paused at a breakpoint.
+  reloadSources(true),
+  // Ensure that we are still stopped at a breakpoint.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Reload sources and request to pause post reload. The pause request will
+  // be respected because we are not already paused.
+  reloadSources(true),
+  // Ensure that we are paused post reload request.
+  hasStoppedPostRequest,
+  // Resume the isolate.
+  resumeIsolate,
+  // Verify that it is running.
+  isolateIsRunning,
+  // Reload sources and do not request to pause post reload.
+  reloadSources(false),
+  // Verify that it is running.
+  isolateIsRunning,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/rewind_optimized_out_test.dart b/runtime/observatory_2/tests/service_2/rewind_optimized_out_test.dart
new file mode 100644
index 0000000..34901ec
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/rewind_optimized_out_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+int LINE_A = 31;
+int LINE_B = 36;
+int LINE_C = 39;
+int LINE_D = 43;
+
+int global = 0;
+
+@pragma('vm:never-inline')
+b3(x) {
+  int sum = 0;
+  try {
+    for (int i = 0; i < x; i++) {
+      sum += x;
+    }
+  } catch (e) {
+    print("caught $e");
+  }
+  if (global >= 100) {
+    debugger();
+  }
+  global = global + 1; // Line A
+  return sum;
+}
+
+@pragma('vm:prefer-inline')
+b2(x) => b3(x); // Line B
+
+@pragma('vm:prefer-inline')
+b1(x) => b2(x); // Line C
+
+test() {
+  while (true) {
+    b1(10000); // Line D
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    // We are at our breakpoint with global=100.
+    Instance result = await isolate.rootLibrary.evaluate('global');
+    print('global is $result');
+    expect(result.type, equals('Instance'));
+    expect(result.valueAsString, equals('100'));
+
+    // Rewind the top stack frame.
+    bool caughtException;
+    try {
+      result = await isolate.rewind(1);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kCannotResume));
+      expect(
+          e.message,
+          startsWith('Cannot rewind to frame 1 due to conflicting compiler '
+              'optimizations. Run the vm with --no-prune-dead-locals '
+              'to disallow these optimizations. Next valid rewind '
+              'frame is '));
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: test, extraArgs: [
+      '--trace-rewind',
+      '--prune-dead-locals',
+      '--no-background-compilation',
+      '--optimization-counter-threshold=10'
+    ]);
diff --git a/runtime/observatory_2/tests/service_2/rewind_test.dart b/runtime/observatory_2/tests/service_2/rewind_test.dart
new file mode 100644
index 0000000..06b6f50
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/rewind_test.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+int LINE_A = 31;
+int LINE_B = 36;
+int LINE_C = 39;
+int LINE_D = 43;
+
+int global = 0;
+
+@pragma('vm:never-inline')
+b3(x) {
+  int sum = 0;
+  try {
+    for (int i = 0; i < x; i++) {
+      sum += x;
+    }
+  } catch (e) {
+    print("caught $e");
+  }
+  if (global >= 100) {
+    debugger();
+  }
+  global = global + 1; // Line A
+  return sum;
+}
+
+@pragma('vm:prefer-inline')
+b2(x) => b3(x); // Line B
+
+@pragma('vm:prefer-inline')
+b1(x) => b2(x); // Line C
+
+test() {
+  while (true) {
+    b1(10000); // Line D
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    // We are not able to rewind frame 0.
+    bool caughtException;
+    try {
+      await isolate.rewind(0);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kCannotResume));
+      expect(e.message, 'Frame must be in bounds [1..8]: saw 0');
+    }
+    expect(caughtException, isTrue);
+  },
+  (Isolate isolate) async {
+    // We are not able to rewind frame 13.
+    bool caughtException;
+    try {
+      await isolate.rewind(13);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kCannotResume));
+      expect(e.message, 'Frame must be in bounds [1..8]: saw 13');
+    }
+    expect(caughtException, isTrue);
+  },
+  (Isolate isolate) async {
+    // We are at our breakpoint with global=100.
+    Instance result = await isolate.rootLibrary.evaluate('global');
+    print('global is $result');
+    expect(result.type, equals('Instance'));
+    expect(result.valueAsString, equals('100'));
+
+    // Rewind the top stack frame.
+    var result2 = await isolate.rewind(1);
+    expect(result2['type'], equals('Success'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    var result = await isolate.resume();
+    expect(result['type'], equals('Success'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    // global still is equal to 100.  We did not execute "global++".
+    Instance result = await isolate.rootLibrary.evaluate('global');
+    print('global is $result');
+    expect(result.type, equals('Instance'));
+    expect(result.valueAsString, equals('100'));
+
+    // Rewind up to 'test'/
+    var result2 = await isolate.rewind(3);
+    expect(result2['type'], equals('Success'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_D),
+  (Isolate isolate) async {
+    // Reset global to 0 and start again.
+    Instance result = await isolate.rootLibrary.evaluate('global=0');
+    print('set global to $result');
+    expect(result.type, equals('Instance'));
+    expect(result.valueAsString, equals('0'));
+
+    var result2 = await isolate.resume();
+    expect(result2['type'], equals('Success'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (Isolate isolate) async {
+    // We are at our breakpoint with global=100.
+    Instance result = await isolate.rootLibrary.evaluate('global');
+    print('global is $result');
+    expect(result.type, equals('Instance'));
+    expect(result.valueAsString, equals('100'));
+
+    // Rewind the top 2 stack frames.
+    var result2 = await isolate.rewind(2);
+    expect(result2['type'], equals('Success'));
+  },
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_C),
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: test, extraArgs: [
+      '--trace-rewind',
+      '--no-prune-dead-locals',
+      '--no-background-compilation',
+      '--optimization-counter-threshold=10'
+    ]);
diff --git a/runtime/observatory_2/tests/service_2/service_2.status b/runtime/observatory_2/tests/service_2/service_2.status
new file mode 100644
index 0000000..c16feab
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/service_2.status
@@ -0,0 +1,73 @@
+# Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+# Flaky failures
+dds_log_history_size_gigantic_test: Pass, Slow # Involves processing lots of logs
+field_script_test: Pass, RuntimeError
+get_allocation_samples_test: Pass, RuntimeError # Inconsistent stack trace
+get_isolate_rpc_test: Pass, RuntimeError # Issue 29324
+isolate_lifecycle_test: Pass, RuntimeError # Issue 24174
+pause_on_exceptions_test: Pass, RuntimeError # Issue 33049
+pause_on_start_and_exit_with_child_test: Pass, RuntimeError # Issue 33049
+reload_sources_test: Pass, Slow # Reload is slow on the bots
+valid_source_locations_test: Pass, Slow # Generally slow, even in release-x64.
+
+[ $arch == arm ]
+process_service_test: Pass, Fail # Issue 24344
+
+# Test uses service API and relies on correct class names
+[ $builder_tag == obfuscated ]
+dominator_tree_vm_test: SkipByDesign
+dominator_tree_vm_with_double_field_test: SkipByDesign
+
+# Tests with known analyzer issues
+[ $compiler == dart2analyzer ]
+developer_extension_test: SkipByDesign
+get_isolate_after_language_error_test: SkipByDesign
+
+# Service protocol is not supported in product mode.
+[ $mode == product ]
+*: SkipByDesign
+
+[ $system == android ]
+string_escaping_test: Skip # Issue http://dartbug.com/42094
+
+[ $system == windows ]
+*: Slow
+async_generator_breakpoint_test: Skip # Issue 29145
+dev_fs_http_put_weird_char_test: Skip # Windows disallows carriage returns in paths
+dev_fs_weird_char_test: Skip # Windows disallows question mark in paths
+
+[ $compiler == none && $runtime == vm ]
+evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
+evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
+
+[ $compiler == none && $runtime == vm && $system == fuchsia ]
+*: Skip # Not yet triaged.
+
+[ $mode == debug && $system == windows ]
+dds_log_history_size_gigantic_test: Skip # Too slow: dartbug.com/41825
+
+[ $mode == debug && $system == windows && $checked ]
+async_scope_test: Pass, Slow
+
+[ $mode == debug && ($arch == simarm || $arch == simarm64) ]
+*: SkipSlow
+
+# These tests are slow on simulators.
+[ $arch == simarm || $arch == simarm64 ]
+*: Pass, Slow
+
+# All tests use dart:io
+[ $compiler == dart2js || $browser ]
+*: SkipByDesign
+
+[ $compiler == dartk || $compiler == dartkp ]
+rewind_test: Pass, Slow
+
+[ $system != linux || $arch != ia32 && $arch != x64 ]
+get_native_allocation_samples_test: Skip # Unsupported.
+
+# Skip all service tests because random reloads interfere.
+[ $hot_reload || $hot_reload_rollback ]
+*: SkipByDesign # The service tests should run without being reloaded.
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
new file mode 100644
index 0000000..9e721f2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -0,0 +1,301 @@
+# Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+[ $compiler == app_jitk ]
+add_breakpoint_rpc_kernel_test: SkipByDesign # No incremental compiler available.
+async_generator_breakpoint_test: SkipByDesign # No incremental compiler available.
+bad_reload_test: RuntimeError
+break_on_activation_test: SkipByDesign # No incremental compiler available.
+complex_reload_test: RuntimeError
+debugger_inspect_test: SkipByDesign # No incremental compiler available.
+debugger_location_second_test: RuntimeError
+eval_internal_class_test: SkipByDesign # No incremental compiler available.
+eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
+eval_test: SkipByDesign # No incremental compiler available.
+evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
+evaluate_activation_test: SkipByDesign # No incremental compiler available.
+evaluate_async_closure_test: SkipByDesign # No incremental compiler available.
+evaluate_class_type_parameters_test: SkipByDesign # No incremental compiler available.
+evaluate_function_type_parameters_test: SkipByDesign # No incremental compiler available.
+evaluate_in_async_activation_test: SkipByDesign # No incremental compiler available.
+evaluate_in_async_star_activation_test: SkipByDesign # No incremental compiler available.
+evaluate_in_frame_rpc_test: SkipByDesign # No incremental compiler available.
+evaluate_in_frame_with_scope_test: SkipByDesign # No incremental compiler available.
+evaluate_in_sync_star_activation_test: SkipByDesign # No incremental compiler available.
+evaluate_with_escaping_closure_test: SkipByDesign # No incremental compiler available.
+evaluate_with_scope_test: SkipByDesign # No incremental compiler available.
+pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
+rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
+rewind_test: SkipByDesign # No incremental compiler available.
+
+[ $compiler == dartk ]
+bad_reload_test: RuntimeError # Issue 34025
+coverage_optimized_function_test: Pass, Slow
+evaluate_activation_in_method_class_test: RuntimeError # Issue 35505
+evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
+evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
+get_source_report_test: RuntimeError # Should pass again when constant evaluation is relanded, see http://dartbug.com/36600
+pause_on_unhandled_async_exceptions2_test: Pass, Slow
+
+[ $compiler == dartkp ]
+add_breakpoint_rpc_kernel_test: SkipByDesign
+async_generator_breakpoint_test: SkipByDesign
+async_next_regession_18877_test: Skip, Timeout
+async_next_test: Skip, Timeout
+async_scope_test: Skip, Timeout
+async_single_step_exception_test: Skip, Timeout
+async_single_step_into_test: Skip, Timeout
+async_single_step_out_test: Skip, Timeout
+async_star_single_step_into_test: Skip, Timeout
+async_star_step_out_test: Skip, Timeout
+async_step_out_test: Skip, Timeout
+awaiter_async_stack_contents_2_test: Skip, Timeout
+awaiter_async_stack_contents_test: Skip, Timeout
+bad_reload_test: SkipByDesign
+break_on_activation_test: SkipByDesign
+break_on_async_function_test: Skip, Timeout
+break_on_default_constructor_test: SkipByDesign
+break_on_function_test: Skip, Timeout
+breakpoint_async_break_test: SkipByDesign
+breakpoint_in_package_parts_class_file_uri_test: SkipByDesign
+breakpoint_in_package_parts_class_test: SkipByDesign
+breakpoint_in_parts_class_test: SkipByDesign
+breakpoint_non_debuggable_library_test: SkipByDesign
+breakpoint_on_if_null_1_test: SkipByDesign
+breakpoint_on_if_null_2_test: SkipByDesign
+breakpoint_on_if_null_3_test: SkipByDesign
+breakpoint_on_if_null_4_test: SkipByDesign
+breakpoint_partfile_test: SkipByDesign
+breakpoint_two_args_checked_test: Skip, Timeout
+breakpoints_with_mixin_test: SkipByDesign # Debugger is disabled in AOT mode.
+capture_stdio_test: Skip, Timeout
+causal_async_stack_contents_test: Skip, Timeout
+causal_async_stack_presence_test: Skip, Timeout
+causal_async_star_stack_contents_test: Skip, Timeout
+causal_async_star_stack_presence_test: Skip, Timeout
+client_resume_approvals_reload_test: SkipByDesign # Compiler is disabled in AOT mode.
+code_test: SkipByDesign
+column_breakpoint_test: SkipByDesign
+complex_reload_test: SkipByDesign
+coverage_const_field_async_closure_test: Skip, Timeout
+coverage_leaf_function_test: Skip, Timeout
+coverage_optimized_function_test: Skip, Timeout
+dds_log_history_size_*: Skip, Timeout
+debugger_inspect_test: SkipByDesign
+debugger_location_second_test: Skip, Timeout
+debugger_location_test: Skip, Timeout
+debugging_inlined_finally_test: Skip, Timeout
+debugging_test: SkipByDesign
+dev_fs_spawn_test: SkipByDesign
+developer_extension_test: Skip, Timeout
+developer_service_get_isolate_id_test: Skip, Timeout
+eval_internal_class_test: SkipByDesign
+eval_regression_flutter20255_test: Skip, Timeout
+eval_test: Skip, Timeout
+evaluate_activation_in_method_class_test: Skip, Timeout
+evaluate_activation_test: SkipByDesign
+evaluate_async_closure_test: SkipByDesign
+evaluate_class_type_parameters_test: Skip, Timeout
+evaluate_function_type_parameters_test: Skip, Timeout
+evaluate_in_async_activation_test: Skip, Timeout
+evaluate_in_async_star_activation_test: Skip, Timeout
+evaluate_in_frame_rpc_test: Skip, Timeout
+evaluate_in_frame_with_scope_test: Skip, Timeout
+evaluate_in_sync_star_activation_test: Skip, Timeout
+evaluate_with_escaping_closure_test: SkipByDesign
+evaluate_with_scope_test: SkipByDesign
+field_script_test: SkipByDesign
+get_allocation_samples_test: Skip, Timeout
+get_isolate_after_language_error_test: CompileTimeError
+get_object_rpc_test: SkipByDesign
+get_source_report_test: Skip, Timeout
+get_source_report_with_mixin_test: Skip, Timeout
+get_stack_rpc_test: Skip, Timeout
+implicit_getter_setter_test: SkipByDesign
+invoke_test: Skip, Timeout
+isolate_lifecycle_test: SkipByDesign
+issue_25465_test: SkipByDesign
+issue_27238_test: Skip, Timeout
+issue_27287_test: Skip, Timeout
+issue_30555_test: SkipByDesign
+kill_paused_test: Skip, Timeout
+library_dependency_test: CompileTimeError
+local_variable_declaration_test: Skip, Timeout
+local_variable_in_awaiter_async_frame_test: Skip, Timeout
+logging_test: Skip, Timeout
+mirror_references_test: CompileTimeError
+mixin_break_test: Skip, Timeout
+network_profiling_test: Skip, Timeout
+next_through_assign_call_test: SkipByDesign
+next_through_assign_int_test: SkipByDesign
+next_through_await_for_test: SkipByDesign
+next_through_call_on_field_in_class_test: SkipByDesign
+next_through_call_on_field_test: SkipByDesign
+next_through_call_on_static_field_in_class_test: SkipByDesign
+next_through_catch_test: SkipByDesign
+next_through_closure_test: SkipByDesign
+next_through_create_list_and_map_test: SkipByDesign
+next_through_for_each_loop_test: SkipByDesign
+next_through_for_loop_with_break_and_continue_test: SkipByDesign
+next_through_function_expression_test: SkipByDesign
+next_through_implicit_call_test: SkipByDesign
+next_through_is_and_as_test: SkipByDesign
+next_through_multi_catch_test: SkipByDesign
+next_through_new_test: SkipByDesign
+next_through_operator_bracket_on_super_test: SkipByDesign
+next_through_operator_bracket_on_this_test: SkipByDesign
+next_through_operator_bracket_test: SkipByDesign
+next_through_simple_async_test: SkipByDesign
+next_through_simple_async_with_returns_test: SkipByDesign
+next_through_simple_linear_2_test: SkipByDesign
+next_through_simple_linear_test: SkipByDesign
+parameters_in_scope_at_entry_test: Skip, Timeout
+pause_idle_isolate_test: Skip, Timeout
+pause_on_exceptions_test: SkipByDesign
+pause_on_start_then_step_test: SkipByDesign
+pause_on_unhandled_async_exceptions2_test: SkipByDesign
+pause_on_unhandled_async_exceptions3_test: SkipByDesign
+pause_on_unhandled_async_exceptions_test: SkipByDesign
+pause_on_unhandled_exceptions_test: SkipByDesign
+positive_token_pos_test: Skip, Timeout
+regress_28443_test: SkipByDesign
+regress_28980_test: SkipByDesign
+regress_34841_test: Skip, Timeout
+reload_sources_test: Skip, Timeout
+rewind_optimized_out_test: Skip, Timeout
+rewind_test: Skip, Timeout
+set_library_debuggable_test: Skip, Timeout
+simple_reload_test: SkipByDesign
+steal_breakpoint_test: SkipByDesign
+step_into_async_no_await_test: Skip, Timeout
+step_over_await_test: Skip, Timeout
+step_test: SkipByDesign
+step_through_arithmetic_test: SkipByDesign
+step_through_constructor_calls_test: SkipByDesign
+step_through_constructor_test: SkipByDesign
+step_through_for_each_sync_star_2_test: SkipByDesign
+step_through_for_each_sync_star_test: SkipByDesign
+step_through_function_2_test: SkipByDesign
+step_through_function_test: SkipByDesign
+step_through_getter_test: SkipByDesign
+step_through_mixin_from_sdk_test: SkipByDesign
+step_through_property_get_test: SkipByDesign
+step_through_property_set_test: SkipByDesign
+step_through_setter_test: SkipByDesign
+step_through_switch_test: SkipByDesign
+step_through_switch_with_continue_test: SkipByDesign
+valid_source_locations_test: Skip, Timeout
+vm_timeline_flags_test: Skip, Timeout
+weak_properties_test: CompileTimeError
+yield_positions_with_finally_test: SkipByDesign
+
+[ $fasta ]
+get_isolate_after_language_error_test: CompileTimeError
+
+[ $arch == arm64 && $compiler == dartk ]
+coverage_optimized_function_test: Pass, Slow
+
+[ $arch == arm64 && $compiler == dartk && $mode == release ]
+get_object_rpc_test: Pass, RuntimeError # Please triage / issue #27806
+
+[ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
+eval_regression_flutter20255_test: SkipSlow # Timeout
+get_vm_timeline_rpc_test: Pass, Slow
+rewind_optimized_out_test: SkipSlow # Timeout
+
+[ $arch == ia32 && $compiler == dartk ]
+valid_source_locations_test: Skip # Issue 34736, too slow.
+
+[ $arch != simarm && $arch != simarm64 && $compiler == dartk ]
+complex_reload_test: RuntimeError
+
+[ $compiler == dartk && $mode == debug ]
+isolate_lifecycle_test: Skip # Flaky.
+pause_idle_isolate_test: Skip # Flaky
+rewind_optimized_out_test: Pass, Slow
+
+[ $compiler == dartk && $system == windows ]
+add_breakpoint_rpc_kernel_test: Skip # Timeout
+break_on_default_constructor_test: Skip # Issues 32137 and 32138.
+breakpoint_in_parts_class_test: Skip # Timeout
+coverage_optimized_function_test: Skip # Timeout
+field_script_test: Skip # Timeout
+get_vm_timeline_rpc_test: Skip # Issue 32137.
+issue_25465_test: Skip # Issues 32137 and 32138.
+issue_30555_test: Skip # Issues 32137 and 32138.
+next_through_assign_call_test: Skip # Issues 32137 and 32138.
+next_through_assign_int_test: Skip # Issues 32137 and 32138.
+next_through_call_on_field_in_class_test: Skip # Issues 32137 and 32138.
+next_through_call_on_field_test: Skip # Issues 32137 and 32138.
+next_through_call_on_static_field_in_class_test: Skip # Timeout
+next_through_catch_test: Skip # Issues 32137 and 32138.
+next_through_closure_test: Skip # Timeout
+next_through_create_list_and_map_test: Skip # Issues 32137 and 32138.
+next_through_for_each_loop_test: Skip # Timeout
+next_through_for_loop_with_break_and_continue_test: Skip # Timeout
+next_through_function_expression_test: Skip # Issues 32137 and 32138.
+next_through_implicit_call_test: Skip # Timeout
+next_through_is_and_as_test: Skip # Issues 32137 and 32138.
+next_through_multi_catch_test: Skip # Issues 32137 and 32138.
+next_through_new_test: Skip # Timeout
+next_through_operator_bracket_on_super_test: Skip # Timeout
+next_through_operator_bracket_on_this_test: Skip # Timeout
+next_through_operator_bracket_test: Skip # Timeout
+next_through_simple_async_test: Skip # Timeout
+next_through_simple_async_with_returns_test: Skip # Issues 32137 and 32138.
+next_through_simple_linear_2_test: Skip # Issues 32137 and 32138.
+next_through_simple_linear_test: Skip # Issues 32137 and 32138.
+pause_idle_isolate_test: Skip # Issues 32137 and 32138.
+pause_on_start_and_exit_test: Skip # Issues 32225, 32138.
+pause_on_start_and_exit_with_child_test: Skip # Timeout
+pause_on_start_then_step_test: Skip # Issue 32225, 32138.
+regress_28443_test: Skip # Times out.
+regress_28980_test: Skip # Issues 32137 and 32138.
+reload_sources_test: RuntimeError
+set_vm_name_rpc_test: Skip # Times out. Issue 32137.
+step_test: Skip # Issues 32137 and 32138.
+step_through_constructor_calls_test: Skip # Timeout
+step_through_constructor_test: Skip # Timeout
+step_through_function_2_test: Skip # Issues 32137 and 32138.
+step_through_function_test: Skip # Issues 32137 and 32138.
+step_through_getter_test: Skip # Timeout
+step_through_property_get_test: Skip # Times out. Issue 32137.
+step_through_property_set_test: Skip # Timeout
+step_through_setter_test: Skip # Issues 32137 and 32138.
+step_through_switch_test: Skip # Times out. Issue 32137.
+step_through_switch_with_continue_test: Skip # Times out. Issue 32137.
+
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
+add_breakpoint_rpc_kernel_test: RuntimeError # Issue #34736
+async_generator_breakpoint_test: SkipByDesign # No incremental compiler available.
+bad_reload_test: Skip # Times out on sim architectures, also RuntimeError.
+break_on_activation_test: RuntimeError # Issue #34736
+breakpoint_in_package_parts_class_file_uri_test: RuntimeError # Issue #34736
+complex_reload_test: Skip # Times out on sim architectures, also RuntimeError.
+dds_log_history_size_gigantic_test: SkipSlow # Involves hundreds of thousands of log messages
+debugger_inspect_test: RuntimeError, Timeout # Issue #34736
+eval_internal_class_test: RuntimeError # Issue #34736
+eval_regression_flutter20255_test: SkipByDesign # No incremental compiler available.
+eval_test: RuntimeError # Issue #34736
+evaluate_activation_test/none: RuntimeError # Issue #34736
+evaluate_async_closure_test: RuntimeError # Issue #34736
+evaluate_class_type_parameters_test: RuntimeError # Issue 34736
+evaluate_function_type_parameters_test: RuntimeError # Issue 34736
+evaluate_in_async_activation_test: RuntimeError # Issue #34736
+evaluate_in_async_star_activation_test: RuntimeError # Issue #34736
+evaluate_in_frame_rpc_test: RuntimeError # Issue #34736
+evaluate_in_frame_with_scope_test: RuntimeError # Issue #34736
+evaluate_in_sync_star_activation_test: SkipByDesign # No incremental compiler available.
+evaluate_with_scope_test: RuntimeError # Issue #34736
+pause_on_exceptions_test: RuntimeError, Timeout # Issue #34736
+reload_sources_test: Skip # Times out.
+rewind_optimized_out_test: RuntimeError # Issue #34736
+rewind_test: Pass, RuntimeError
+set_name_rpc_test: RuntimeError # Please triage.
+simple_reload_test: RuntimeError, Timeout
+valid_source_locations_test: Skip # Issue 34736, too slow.
+
+[ $mode == debug && $system == windows ]
+debugger_location_second_test: Skip, Timeout
+debugger_location_test: Skip, Timeout
diff --git a/runtime/observatory_2/tests/service_2/service_test_common.dart b/runtime/observatory_2/tests/service_2/service_test_common.dart
new file mode 100644
index 0000000..4373982
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/service_test_common.dart
@@ -0,0 +1,620 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library service_test_common;
+
+import 'dart:async';
+import 'dart:io' show Platform;
+import 'package:dds/dds.dart';
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_common.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+typedef Future IsolateTest(Isolate isolate);
+typedef Future VMTest(VM vm);
+typedef Future DDSTest(VM vm, DartDevelopmentService dds);
+typedef void ServiceEventHandler(ServiceEvent event);
+
+Map<String, StreamSubscription> streamSubscriptions = {};
+
+Future subscribeToStream(
+    VM vm, String streamName, ServiceEventHandler onEvent) async {
+  assert(streamSubscriptions[streamName] == null);
+
+  Stream<ServiceEvent> stream = await vm.getEventStream(streamName);
+  StreamSubscription subscription = stream.listen(onEvent);
+  streamSubscriptions[streamName] = subscription;
+}
+
+Future cancelStreamSubscription(String streamName) async {
+  StreamSubscription subscription = streamSubscriptions[streamName];
+  subscription.cancel();
+  streamSubscriptions.remove(streamName);
+}
+
+Future smartNext(Isolate isolate) async {
+  print('smartNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    dynamic event = isolate.pauseEvent;
+    if (event.atAsyncSuspension) {
+      return asyncNext(isolate);
+    } else {
+      return syncNext(isolate);
+    }
+  } else {
+    throw 'The program is already running';
+  }
+}
+
+Future asyncNext(Isolate isolate) async {
+  print('asyncNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    dynamic event = isolate.pauseEvent;
+    if (!event.atAsyncSuspension) {
+      throw 'No async continuation at this location';
+    } else {
+      return isolate.stepOverAsyncSuspension();
+    }
+  } else {
+    throw 'The program is already running';
+  }
+}
+
+Future syncNext(Isolate isolate) async {
+  print('syncNext');
+  if (isolate.status == M.IsolateStatus.paused) {
+    return isolate.stepOver();
+  } else {
+    throw 'The program is already running';
+  }
+}
+
+Future asyncStepOver(Isolate isolate) async {
+  final Completer pausedAtSyntheticBreakpoint = new Completer();
+  StreamSubscription subscription;
+
+  // Cancel the subscription.
+  cancelSubscription() {
+    if (subscription != null) {
+      subscription.cancel();
+      subscription = null;
+    }
+  }
+
+  // Complete futures with with error.
+  completeError(error) {
+    if (!pausedAtSyntheticBreakpoint.isCompleted) {
+      pausedAtSyntheticBreakpoint.completeError(error);
+    }
+  }
+
+  // Subscribe to the debugger event stream.
+  Stream<ServiceEvent> stream;
+  try {
+    stream = await isolate.vm.getEventStream(VM.kDebugStream);
+  } catch (e) {
+    completeError(e);
+    return pausedAtSyntheticBreakpoint.future;
+  }
+
+  Breakpoint syntheticBreakpoint;
+
+  subscription = stream.listen((ServiceEvent event) async {
+    // Synthetic breakpoint add event. This is the first event we will
+    // receive.
+    bool isAdd = (event.kind == ServiceEvent.kBreakpointAdded) &&
+        (event.breakpoint.isSyntheticAsyncContinuation) &&
+        (event.owner == isolate);
+    // Resume after synthetic breakpoint added. This is the second event
+    // we will receive.
+    bool isResume = (event.kind == ServiceEvent.kResume) &&
+        (syntheticBreakpoint != null) &&
+        (event.owner == isolate);
+    // Paused at synthetic breakpoint. This is the third event we will
+    // receive.
+    bool isPaused = (event.kind == ServiceEvent.kPauseBreakpoint) &&
+        (syntheticBreakpoint != null) &&
+        (event.breakpoint == syntheticBreakpoint);
+    if (isAdd) {
+      syntheticBreakpoint = event.breakpoint;
+    } else if (isResume) {
+    } else if (isPaused) {
+      pausedAtSyntheticBreakpoint.complete(isolate);
+      syntheticBreakpoint = null;
+      cancelSubscription();
+    }
+  });
+
+  // Issue the step OverAwait command.
+  try {
+    await isolate.stepOverAsyncSuspension();
+  } catch (e) {
+    // This can fail when another client issued the same resume command
+    // or another client has moved the isolate forward.
+    cancelSubscription();
+    completeError(e);
+  }
+
+  return pausedAtSyntheticBreakpoint.future;
+}
+
+bool isEventOfKind(M.Event event, String kind) {
+  switch (kind) {
+    case ServiceEvent.kPauseBreakpoint:
+      return event is M.PauseBreakpointEvent;
+    case ServiceEvent.kPauseException:
+      return event is M.PauseExceptionEvent;
+    case ServiceEvent.kPauseExit:
+      return event is M.PauseExitEvent;
+    case ServiceEvent.kPauseStart:
+      return event is M.PauseStartEvent;
+    case ServiceEvent.kPausePostRequest:
+      return event is M.PausePostRequestEvent;
+    default:
+      return false;
+  }
+}
+
+Future hasPausedFor(Isolate isolate, String kind) {
+  // Set up a listener to wait for breakpoint events.
+  Completer completer = new Completer();
+  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if ((isolate == event.isolate) && (event.kind == kind)) {
+        if (completer != null) {
+          // Reload to update isolate.pauseEvent.
+          print('Paused with $kind');
+          subscription.cancel();
+          completer.complete(isolate.reload());
+          completer = null;
+        }
+      }
+    });
+
+    // Pause may have happened before we subscribed.
+    isolate.reload().then((_) {
+      if ((isolate.pauseEvent != null) &&
+          isEventOfKind(isolate.pauseEvent, kind)) {
+        // Already waiting at a breakpoint.
+        if (completer != null) {
+          print('Paused with $kind');
+          subscription.cancel();
+          completer.complete(isolate);
+          completer = null;
+        }
+      }
+    });
+  });
+
+  return completer.future; // Will complete when breakpoint hit.
+}
+
+Future hasStoppedAtBreakpoint(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseBreakpoint);
+}
+
+Future hasStoppedPostRequest(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPausePostRequest);
+}
+
+Future hasStoppedWithUnhandledException(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseException);
+}
+
+Future hasStoppedAtExit(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseExit);
+}
+
+Future hasPausedAtStart(Isolate isolate) {
+  return hasPausedFor(isolate, ServiceEvent.kPauseStart);
+}
+
+Future markDartColonLibrariesDebuggable(Isolate isolate) async {
+  await isolate.reload();
+  for (Library lib in isolate.libraries) {
+    await lib.load();
+    if (lib.uri.startsWith('dart:') && !lib.uri.startsWith('dart:_')) {
+      var setDebugParams = {
+        'libraryId': lib.id,
+        'isDebuggable': true,
+      };
+      Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade(
+          'setLibraryDebuggable', setDebugParams);
+    }
+  }
+  return isolate;
+}
+
+IsolateTest reloadSources([bool pause = false]) {
+  return (Isolate isolate) async {
+    Map<String, dynamic> params = <String, dynamic>{};
+    if (pause) {
+      params['pause'] = pause;
+    }
+    return isolate.invokeRpc('reloadSources', params);
+  };
+}
+
+// Currying is your friend.
+IsolateTest setBreakpointAtLine(int line) {
+  return (Isolate isolate) async {
+    print("Setting breakpoint for line $line");
+    Library lib = await isolate.rootLibrary.load();
+    Script script = lib.scripts.firstWhere((s) => s.uri == lib.uri);
+
+    Breakpoint bpt = await isolate.addBreakpoint(script, line);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+  };
+}
+
+IsolateTest setBreakpointAtLineColumn(int line, int column) {
+  return (Isolate isolate) async {
+    print("Setting breakpoint for line $line column $column");
+    Library lib = await isolate.rootLibrary.load();
+    Script script = lib.scripts.firstWhere((s) => s.uri == lib.uri);
+
+    Breakpoint bpt = await isolate.addBreakpoint(script, line, column);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+  };
+}
+
+IsolateTest setBreakpointAtUriAndLine(String uri, int line) {
+  return (Isolate isolate) async {
+    print("Setting breakpoint for line $line in $uri");
+    Breakpoint bpt = await isolate.addBreakpointByScriptUri(uri, line);
+    print("Breakpoint is $bpt");
+    expect(bpt, isNotNull);
+    expect(bpt is Breakpoint, isTrue);
+  };
+}
+
+IsolateTest stoppedAtLine(int line) {
+  return (Isolate isolate) async {
+    print("Checking we are at line $line");
+
+    // Make sure that the isolate has stopped.
+    await isolate.reload();
+    expect(isolate.pauseEvent is! M.ResumeEvent, isTrue);
+
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+
+    List frames = stack['frames'];
+    expect(frames.length, greaterThanOrEqualTo(1));
+
+    Frame top = frames[0];
+    Script script = await top.location.script.load();
+    int actualLine = script.tokenToLine(top.location.tokenPos);
+    if (actualLine != line) {
+      StringBuffer sb = new StringBuffer();
+      sb.write("Expected to be at line $line but actually at line $actualLine");
+      sb.write("\nFull stack trace:\n");
+      for (Frame f in stack['frames']) {
+        sb.write(" $f [${await f.location.getLine()}]\n");
+      }
+      throw sb.toString();
+    } else {
+      print('Program is stopped at line: $line');
+    }
+  };
+}
+
+IsolateTest stoppedInFunction(String functionName,
+    {bool contains: false, bool includeOwner: false}) {
+  return (Isolate isolate) async {
+    print("Checking we are in function: $functionName");
+
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+
+    List frames = stack['frames'];
+    expect(frames.length, greaterThanOrEqualTo(1));
+
+    Frame topFrame = frames[0];
+    ServiceFunction function = await topFrame.function.load();
+    String name = function.name;
+    if (includeOwner) {
+      ServiceFunction owner =
+          await (function.dartOwner as ServiceObject).load();
+      name = '${owner.name}.$name';
+    }
+    final bool matches =
+        contains ? name.contains(functionName) : name == functionName;
+    if (!matches) {
+      StringBuffer sb = new StringBuffer();
+      sb.write("Expected to be in function $functionName but "
+          "actually in function $name");
+      sb.write("\nFull stack trace:\n");
+      for (Frame f in frames) {
+        await f.function.load();
+        await (f.function.dartOwner as ServiceObject).load();
+        String name = f.function.name;
+        String ownerName = (f.function.dartOwner as ServiceObject).name;
+        sb.write(" $f [$name] [$ownerName]\n");
+      }
+      throw sb.toString();
+    } else {
+      print('Program is stopped in function: $functionName');
+    }
+  };
+}
+
+IsolateTest hasLocalVarInTopAwaiterStackFrame(String varName) {
+  return (Isolate isolate) async {
+    print("Checking we have variable '$varName' in the top frame");
+
+    // Make sure that the isolate has stopped.
+    await isolate.reload();
+    expect(isolate.pauseEvent is! M.ResumeEvent, isTrue);
+
+    final ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+
+    final List frames = stack['awaiterFrames'];
+    expect(frames.length, greaterThanOrEqualTo(1));
+
+    final Frame top = frames[0];
+    for (final variable in top.variables) {
+      if (variable.name == varName) {
+        return;
+      }
+    }
+    final sb = StringBuffer();
+    sb.write("Expected to find $varName in top awaiter stack frame, found ");
+    if (top.variables.isEmpty) {
+      sb.write("no variables\n");
+    } else {
+      sb.write("these instead:\n");
+      for (var variable in top.variables) {
+        sb.write("\t${variable.name}\n");
+      }
+    }
+    throw sb.toString();
+  };
+}
+
+Future resumeIsolate(Isolate isolate) {
+  Completer completer = new Completer();
+  isolate.vm.getEventStream(VM.kDebugStream).then((stream) {
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+  });
+  isolate.resume();
+  return completer.future;
+}
+
+Future resumeAndAwaitEvent(Isolate isolate, stream, onEvent) async {
+  Completer completer = new Completer();
+  var sub;
+  sub = await isolate.vm.listenEventStream(stream, (ServiceEvent event) {
+    var r = onEvent(event);
+    if (r is! Future) {
+      r = new Future.value(r);
+    }
+    r.then((x) => sub.cancel().then((_) {
+          completer.complete();
+        }));
+  });
+  await isolate.resume();
+  return completer.future;
+}
+
+IsolateTest resumeIsolateAndAwaitEvent(stream, onEvent) {
+  return (Isolate isolate) async =>
+      resumeAndAwaitEvent(isolate, stream, onEvent);
+}
+
+Future stepOver(Isolate isolate) async {
+  await isolate.stepOver();
+  return hasStoppedAtBreakpoint(isolate);
+}
+
+Future stepInto(Isolate isolate) async {
+  await isolate.stepInto();
+  return hasStoppedAtBreakpoint(isolate);
+}
+
+Future stepOut(Isolate isolate) async {
+  await isolate.stepOut();
+  return hasStoppedAtBreakpoint(isolate);
+}
+
+Future isolateIsRunning(Isolate isolate) async {
+  await isolate.reload();
+  expect(isolate.running, true);
+}
+
+Future<Class> getClassFromRootLib(Isolate isolate, String className) async {
+  Library rootLib = await isolate.rootLibrary.load();
+  for (Class cls in rootLib.classes) {
+    if (cls.name == className) {
+      return cls;
+    }
+  }
+  return null;
+}
+
+Future<Instance> rootLibraryFieldValue(
+    Isolate isolate, String fieldName) async {
+  Library rootLib = await isolate.rootLibrary.load();
+  Field field = rootLib.variables.singleWhere((v) => v.name == fieldName);
+  await field.load();
+  Instance value = field.staticValue;
+  await value.load();
+  return value;
+}
+
+IsolateTest runStepThroughProgramRecordingStops(List<String> recordStops) {
+  return (Isolate isolate) async {
+    Completer completer = new Completer();
+
+    await subscribeToStream(isolate.vm, VM.kDebugStream,
+        (ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        await isolate.reload();
+        // We are paused: Step further.
+        Frame frame = isolate.topFrame;
+        recordStops.add(await frame.location.toUserString());
+        if (event.atAsyncSuspension) {
+          isolate.stepOverAsyncSuspension();
+        } else {
+          isolate.stepOver();
+        }
+      } else if (event.kind == ServiceEvent.kPauseExit) {
+        // We are at the exit: The test is done.
+        await cancelStreamSubscription(VM.kDebugStream);
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    return completer.future;
+  };
+}
+
+IsolateTest resumeProgramRecordingStops(
+    List<String> recordStops, bool includeCaller) {
+  return (Isolate isolate) async {
+    Completer completer = new Completer();
+
+    await subscribeToStream(isolate.vm, VM.kDebugStream,
+        (ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        await isolate.reload();
+        // We are paused: Resume after recording.
+        ServiceMap stack = await isolate.getStack();
+        expect(stack.type, equals('Stack'));
+        List frames = stack['frames'];
+        expect(frames.length, greaterThanOrEqualTo(2));
+        Frame frame = frames[0];
+        String brokeAt = await frame.location.toUserString();
+        if (includeCaller) {
+          frame = frames[1];
+          String calledFrom = await frame.location.toUserString();
+          recordStops.add("$brokeAt ($calledFrom)");
+        } else {
+          recordStops.add(brokeAt);
+        }
+
+        isolate.resume();
+      } else if (event.kind == ServiceEvent.kPauseExit) {
+        // We are at the exit: The test is done.
+        await cancelStreamSubscription(VM.kDebugStream);
+        completer.complete();
+      }
+    });
+    print("Resuming!");
+    isolate.resume();
+    return completer.future;
+  };
+}
+
+IsolateTest runStepIntoThroughProgramRecordingStops(List<String> recordStops) {
+  return (Isolate isolate) async {
+    Completer completer = new Completer();
+
+    await subscribeToStream(isolate.vm, VM.kDebugStream,
+        (ServiceEvent event) async {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        await isolate.reload();
+        // We are paused: Step into further.
+        Frame frame = isolate.topFrame;
+        recordStops.add(await frame.location.toUserString());
+        isolate.stepInto();
+      } else if (event.kind == ServiceEvent.kPauseExit) {
+        // We are at the exit: The test is done.
+        await cancelStreamSubscription(VM.kDebugStream);
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    return completer.future;
+  };
+}
+
+IsolateTest checkRecordedStops(
+    List<String> recordStops, List<String> expectedStops,
+    {bool removeDuplicates = false,
+    bool debugPrint = false,
+    String debugPrintFile,
+    int debugPrintLine}) {
+  return (Isolate isolate) async {
+    if (debugPrint) {
+      for (int i = 0; i < recordStops.length; i++) {
+        String line = recordStops[i];
+        String output = line;
+        int firstColon = line.indexOf(":");
+        int lastColon = line.lastIndexOf(":");
+        if (debugPrintFile != null &&
+            debugPrintLine != null &&
+            firstColon > 0 &&
+            lastColon > 0) {
+          int lineNumber = int.parse(line.substring(firstColon + 1, lastColon));
+          int relativeLineNumber = lineNumber - debugPrintLine;
+          var columnNumber = line.substring(lastColon + 1);
+          var file = line.substring(0, firstColon);
+          if (file == debugPrintFile) {
+            output = '\$file:\${LINE+$relativeLineNumber}:$columnNumber';
+          }
+        }
+        String comma = i == recordStops.length - 1 ? "" : ",";
+        print('"$output"$comma');
+      }
+    }
+    if (removeDuplicates) {
+      recordStops = removeAdjacentDuplicates(recordStops);
+      expectedStops = removeAdjacentDuplicates(expectedStops);
+    }
+
+    // Single stepping in interpreted bytecode may record extra stops.
+    // Allow the extra ones as long as the expected ones are recorded.
+    int i = 0;
+    int j = 0;
+    while (i < recordStops.length && j < expectedStops.length) {
+      if (recordStops[i] != expectedStops[j]) {
+        // Check if recordStops[i] is an extra stop.
+        int k = i + 1;
+        while (k < recordStops.length && recordStops[k] != expectedStops[j]) {
+          k++;
+        }
+        if (k < recordStops.length) {
+          // Allow and ignore extra recorded stops from i to k-1.
+          i = k;
+        } else {
+          // This will report an error.
+          expect(recordStops[i], expectedStops[j]);
+        }
+      }
+      i++;
+      j++;
+    }
+
+    expect(recordStops.length >= expectedStops.length, true,
+        reason: "Expects at least ${expectedStops.length} breaks, "
+            "got ${recordStops.length}.");
+  };
+}
+
+List<String> removeAdjacentDuplicates(List<String> fromList) {
+  List<String> result = <String>[];
+  String latestLine;
+  for (String s in fromList) {
+    if (s == latestLine) continue;
+    latestLine = s;
+    result.add(s);
+  }
+  return result;
+}
+
+Future<void> waitForTargetVMExit(VM vm) async => await vm.onDisconnect;
diff --git a/runtime/observatory_2/tests/service_2/set_library_debuggable_rpc_test.dart b/runtime/observatory_2/tests/service_2/set_library_debuggable_rpc_test.dart
new file mode 100644
index 0000000..8059cf9a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/set_library_debuggable_rpc_test.dart
@@ -0,0 +1,59 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library set_library_debuggable_rpc_test;
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    var result;
+
+    // debuggable defaults to true.
+    var getObjectParams = {
+      'objectId': isolate.rootLibrary.id,
+    };
+    result = await isolate.invokeRpcNoUpgrade('getObject', getObjectParams);
+    expect(result['debuggable'], equals(true));
+
+    // Change debuggable to false.
+    var setDebugParams = {
+      'libraryId': isolate.rootLibrary.id,
+      'isDebuggable': false,
+    };
+    result = await isolate.invokeRpcNoUpgrade(
+        'setLibraryDebuggable', setDebugParams);
+    expect(result['type'], equals('Success'));
+
+    // Verify.
+    result = await isolate.invokeRpcNoUpgrade('getObject', getObjectParams);
+    expect(result['debuggable'], equals(false));
+  },
+
+  // invalid library.
+  (Isolate isolate) async {
+    var params = {
+      'libraryId': 'libraries/9999999',
+      'isDebuggable': false,
+    };
+    bool caughtException;
+    try {
+      await isolate.invokeRpcNoUpgrade('setLibraryDebuggable', params);
+      expect(false, isTrue, reason: 'Unreachable');
+    } on ServerRpcException catch (e) {
+      caughtException = true;
+      expect(e.code, equals(ServerRpcException.kInvalidParams));
+      expect(
+          e.message,
+          "setLibraryDebuggable: "
+          "invalid 'libraryId' parameter: libraries/9999999");
+    }
+    expect(caughtException, isTrue);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/set_library_debuggable_test.dart b/runtime/observatory_2/tests/service_2/set_library_debuggable_test.dart
new file mode 100644
index 0000000..89a8b52
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/set_library_debuggable_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library set_library_debuggable_test;
+
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const LINE_A = 19;
+const LINE_B = 20;
+const LINE_C = 21;
+
+testMain() async {
+  debugger();
+  print('hi'); // LINE_A.
+  print('yep'); // LINE_B.
+  print('zoo'); // LINE_C.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  markDartColonLibrariesDebuggable,
+  (Isolate isolate) async {
+    await isolate.reload();
+    Library dartCore = isolate.libraries
+        .firstWhere((Library library) => library.uri == 'dart:core');
+    await dartCore.reload();
+    expect(dartCore.debuggable, equals(true));
+  },
+  stoppedInFunction('testMain', contains: true, includeOwner: true),
+  stoppedAtLine(LINE_A),
+  stepInto,
+  stoppedInFunction('print'),
+  stepOut,
+  stoppedInFunction('testMain', contains: true, includeOwner: true),
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    // Mark 'dart:core' as not debuggable.
+    await isolate.reload();
+    Library dartCore = isolate.libraries
+        .firstWhere((Library library) => library.uri == 'dart:core');
+    await dartCore.load();
+    expect(dartCore.debuggable, equals(true));
+    var setDebugParams = {
+      'libraryId': dartCore.id,
+      'isDebuggable': false,
+    };
+    Map<String, dynamic> result = await isolate.invokeRpcNoUpgrade(
+        'setLibraryDebuggable', setDebugParams);
+    expect(result['type'], equals('Success'));
+    await dartCore.reload();
+    expect(dartCore.debuggable, equals(false));
+  },
+  stoppedInFunction('testMain', contains: true, includeOwner: true),
+  stoppedAtLine(LINE_B),
+  stepInto,
+  stoppedInFunction('testMain', contains: true, includeOwner: true),
+  stoppedAtLine(LINE_C),
+];
+
+main(args) async => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/set_name_rpc_test.dart b/runtime/observatory_2/tests/service_2/set_name_rpc_test.dart
new file mode 100644
index 0000000..f6ffc4e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/set_name_rpc_test.dart
@@ -0,0 +1,34 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--vm-name=Walter
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    expect(isolate.name == 'main', isTrue);
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kIsolateStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kIsolateUpdate) {
+        expect(event.owner.type, equals('Isolate'));
+        expect(event.owner.name, equals('Barbara'));
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    var result = await isolate.setName('Barbara');
+    expect(result.type, equals('Success'));
+
+    await completer.future;
+    expect(isolate.name, equals('Barbara'));
+  }
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/set_vm_name_rpc_test.dart b/runtime/observatory_2/tests/service_2/set_vm_name_rpc_test.dart
new file mode 100644
index 0000000..e15b005
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/set_vm_name_rpc_test.dart
@@ -0,0 +1,36 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--vm-name=Walter
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <VMTest>[
+  (VM vm) async {
+    expect(vm.name, equals('Walter'));
+
+    Completer completer = new Completer();
+    var stream = await vm.getEventStream(VM.kVMStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kVMUpdate) {
+        expect(event.owner.type, equals('VM'));
+        expect(event.owner.name, equals('Barbara'));
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    var result = await vm.setName('Barbara');
+    expect(result.type, equals('Success'));
+
+    await completer.future;
+    expect(vm.name, equals('Barbara'));
+  },
+];
+
+main(args) async => runVMTests(args, tests,
+    extraArgs: ['--trace-service', '--trace-service-verbose']);
diff --git a/runtime/observatory_2/tests/service_2/simple_reload/v1/main.dart b/runtime/observatory_2/tests/service_2/simple_reload/v1/main.dart
new file mode 100644
index 0000000..887ded3
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/simple_reload/v1/main.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+test() => 'apple';
+
+class Foo<T> {}
+
+main() {
+  RawReceivePort keepAlive = new RawReceivePort();
+  new Foo<String>();
+  print('spawned isolate running');
+}
diff --git a/runtime/observatory_2/tests/service_2/simple_reload/v2/main.dart b/runtime/observatory_2/tests/service_2/simple_reload/v2/main.dart
new file mode 100644
index 0000000..0be97ce
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/simple_reload/v2/main.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+test() => 'orange';
+
+class Foo<T> {}
+
+main() {
+  RawReceivePort keepAlive = new RawReceivePort();
+  print('spawned isolate running');
+}
diff --git a/runtime/observatory_2/tests/service_2/simple_reload_test.dart b/runtime/observatory_2/tests/service_2/simple_reload_test.dart
new file mode 100644
index 0000000..9fbfebc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/simple_reload_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// OtherResources=simple_reload/v1/main.dart simple_reload/v2/main.dart
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory_2/service.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+// Chop off the file name.
+String baseDirectory = path.dirname(Platform.script.path) + '/';
+
+Uri baseUri = Platform.script.replace(path: baseDirectory);
+Uri spawnUri = baseUri.resolveUri(Uri.parse('simple_reload/v1/main.dart'));
+Uri v2Uri = baseUri.resolveUri(Uri.parse('simple_reload/v2/main.dart'));
+
+testMain() async {
+  print(baseUri);
+  debugger(); // Stop here.
+  // Spawn the child isolate.
+  I.Isolate isolate = await I.Isolate.spawnUri(spawnUri, [], null);
+  print(isolate);
+  debugger();
+}
+
+Future<String> invokeTest(Isolate isolate) async {
+  await isolate.reload();
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  Instance result = await lib.evaluate('test()');
+  expect(result.isString, isTrue);
+  return result.valueAsString;
+}
+
+var tests = <IsolateTest>[
+  // Stopped at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  // Resume the isolate into the while loop.
+  resumeIsolate,
+  // Stop at 'debugger' statement.
+  hasStoppedAtBreakpoint,
+  (Isolate mainIsolate) async {
+    // Grab the VM.
+    VM vm = mainIsolate.vm;
+    await vm.reloadIsolates();
+    expect(vm.isolates.length, 2);
+
+    // Find the spawned isolate.
+    Isolate spawnedIsolate =
+        vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+    expect(spawnedIsolate, isNotNull);
+
+    // Invoke test in v1.
+    String v1 = await invokeTest(spawnedIsolate);
+    expect(v1, 'apple');
+
+    // Reload to v2.
+    var response = await spawnedIsolate.reloadSources(
+      rootLibUri: v2Uri.toString(),
+    );
+    // Observe that it succeed.
+    expect(response['success'], isTrue);
+
+    String v2 = await invokeTest(spawnedIsolate);
+    expect(v2, 'orange');
+  }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/steal_breakpoint_test.dart b/runtime/observatory_2/tests/service_2/steal_breakpoint_test.dart
new file mode 100644
index 0000000..9da34e8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/steal_breakpoint_test.dart
@@ -0,0 +1,79 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--steal-breakpoints
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+import 'dart:async';
+
+int counter = 0;
+
+void periodicTask(_) {
+  counter++; // Line 14.  We set our breakpoint here.
+  if (counter % 1000 == 0) {
+    print('counter = $counter');
+  }
+}
+
+void startTimer() {
+  new Timer.periodic(const Duration(milliseconds: 10), periodicTask);
+}
+
+var tests = <IsolateTest>[
+// Add a breakpoint and wait for it to be reached.
+  (Isolate isolate) async {
+    await isolate.rootLibrary.load();
+
+    // Set up a listener to wait for breakpoint events.
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kPauseBreakpoint) {
+        print('Isolate paused at breakpoint');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+
+    // Add the breakpoint.
+    var script = isolate.rootLibrary.scripts[0];
+    var result = await isolate.addBreakpoint(script, 14);
+    expect(result is Breakpoint, isTrue);
+
+    await completer.future; // Wait for breakpoint event to fire.
+  },
+
+// We are at the breakpoint on line 14.
+  (Isolate isolate) async {
+    ServiceMap stack = await isolate.getStack();
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+
+    Script script = stack['frames'][0].location.script;
+    await script.load();
+    expect(script.name, endsWith('steal_breakpoint_test.dart'));
+    expect(
+        script.tokenToLine(stack['frames'][0].location.tokenPos), equals(14));
+  },
+
+// Resume
+  (Isolate isolate) async {
+    Completer completer = new Completer();
+    var stream = await isolate.vm.getEventStream(VM.kDebugStream);
+    var subscription;
+    subscription = stream.listen((ServiceEvent event) {
+      if (event.kind == ServiceEvent.kResume) {
+        print('Isolate resumed');
+        subscription.cancel();
+        completer.complete();
+      }
+    });
+    isolate.resume();
+    await completer.future;
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: startTimer);
diff --git a/runtime/observatory_2/tests/service_2/step_into_async_no_await_test.dart b/runtime/observatory_2/tests/service_2/step_into_async_no_await_test.dart
new file mode 100644
index 0000000..23cf4df
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_into_async_no_await_test.dart
@@ -0,0 +1,35 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'test_helper.dart';
+import 'dart:developer';
+import 'service_test_common.dart';
+
+const int LINE_A = 20;
+
+// :async_op will not be captured in this function because it never needs to
+// reschedule it.
+asyncWithoutAwait() async {
+  print("asyncWithoutAwait");
+}
+
+testMain() {
+  debugger();
+  asyncWithoutAwait(); // Line A.
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  (isolate) => isolate.stepInto(),
+  hasStoppedAtBreakpoint,
+  (isolate) => isolate.getStack(), // Should not crash.
+  // TODO(rmacnak): stoppedAtLine(12)
+  // This doesn't happen because asyncWithoutAwait is marked undebuggable.
+  // Probably needs to change to support async-step-into.
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/step_over_await_test.dart b/runtime/observatory_2/tests/service_2/step_over_await_test.dart
new file mode 100644
index 0000000..8cdf1b5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_over_await_test.dart
@@ -0,0 +1,47 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+import 'package:observatory_2/models.dart' as M;
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+const int LINE_A = 22;
+const int LINE_B = 24;
+
+// This tests the asyncNext command.
+asyncFunction() async {
+  debugger();
+  print('a'); // LINE_A
+  await new Future.delayed(new Duration(seconds: 2));
+  print('b'); // LINE_B
+}
+
+testMain() {
+  asyncFunction();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  stepOver, // At new Duration().
+  stepOver, // At new Future.delayed().
+  stepOver, // At async.
+  // Check that we are at the async statement
+  (Isolate isolate) async {
+    expect(M.isAtAsyncSuspension(isolate.pauseEvent), isTrue);
+  },
+  asyncNext,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  resumeIsolate,
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory_2/tests/service_2/step_test.dart b/runtime/observatory_2/tests/service_2/step_test.dart
new file mode 100644
index 0000000..94903f6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_test.dart
@@ -0,0 +1,47 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+const int LINE_A = 14;
+
+code() {
+  var x = {}; // LINE_A
+}
+
+Future stepThroughProgram(Isolate isolate) async {
+  Completer completer = new Completer();
+  int pauseEventsSeen = 0;
+
+  await subscribeToStream(isolate.vm, VM.kDebugStream,
+      (ServiceEvent event) async {
+    if (event.kind == ServiceEvent.kPauseBreakpoint) {
+      // We are paused: Step further.
+      pauseEventsSeen++;
+      isolate.stepInto();
+    } else if (event.kind == ServiceEvent.kPauseExit) {
+      // We are at the exit: The test is done.
+      expect(pauseEventsSeen > 20, true,
+          reason: "Saw only $pauseEventsSeen pause events.");
+      await cancelStreamSubscription(VM.kDebugStream);
+      completer.complete();
+    }
+  });
+  isolate.resume();
+  return completer.future;
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  markDartColonLibrariesDebuggable,
+  setBreakpointAtLine(LINE_A),
+  stepThroughProgram
+];
+
+main(args) => runIsolateTestsSynchronous(args, tests,
+    testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
diff --git a/runtime/observatory_2/tests/service_2/step_through_arithmetic_test.dart b/runtime/observatory_2/tests/service_2/step_through_arithmetic_test.dart
new file mode 100644
index 0000000..6c2c1d8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_arithmetic_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_arithmetic_test.dart";
+
+code() {
+  print(1 + 2);
+  print((1 + 2) / 2);
+  print(1 + 2 * 3);
+  print((1 + 2) * 3);
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // after 'code'
+
+  "$file:${LINE+1}:11", // on '+'
+  "$file:${LINE+1}:3", // on 'print'
+
+  "$file:${LINE+2}:12", // on '+'
+  "$file:${LINE+2}:17", // on '/'
+  "$file:${LINE+2}:3", // on 'print'
+
+  "$file:${LINE+3}:15", // on '*'
+  "$file:${LINE+3}:11", // on '+'
+  "$file:${LINE+3}:3", // on 'print'
+
+  "$file:${LINE+4}:12", // on '+'
+  "$file:${LINE+4}:17", // on '*'
+  "$file:${LINE+4}:3", // on 'print'
+
+  "$file:${LINE+5}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_constructor_calls_test.dart b/runtime/observatory_2/tests/service_2/step_through_constructor_calls_test.dart
new file mode 100644
index 0000000..a78fb57
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_constructor_calls_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 12;
+const String file = "step_through_constructor_calls_test.dart";
+
+code() {
+  Foo foo1 = new Foo();
+  print(foo1.x);
+  Foo foo2 = new Foo.named();
+  print(foo2.x);
+  Foo foo3 = const Foo();
+  print(foo3.x);
+  Foo foo4 = const Foo.named();
+  print(foo4.x);
+  Foo foo5 = new Foo.named2(1, 2, 3);
+  print(foo5.x);
+}
+
+class Foo {
+  final int x;
+
+  const Foo() : x = 1;
+
+  const Foo.named() : x = 2;
+
+  const Foo.named2(int aaaaaaaa, int bbbbbbbbbb, int ccccccccccccc)
+      : x = aaaaaaaa + bbbbbbbbbb + ccccccccccccc;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:18", // on 'Foo'
+  "$file:${LINE+15}:12", // on '(' in 'const Foo() : x = 1;'
+  "$file:${LINE+15}:22", // on ';' in same line
+  "$file:${LINE+1}:14", // on 'x'
+  "$file:${LINE+1}:3", // on print
+  "$file:${LINE+2}:18", // on 'Foo'
+  "$file:${LINE+17}:18", // on '(' in 'const Foo.named() : x = 2;'
+  "$file:${LINE+17}:28", // on ';' in same line
+  "$file:${LINE+3}:14", // on 'x'
+  "$file:${LINE+3}:3", // on print
+  "$file:${LINE+4}:12", // on '='
+  "$file:${LINE+5}:14", // on 'x'
+  "$file:${LINE+5}:3", // on print
+  "$file:${LINE+6}:12", // on '='
+  "$file:${LINE+7}:14", // on 'x'
+  "$file:${LINE+7}:3", // on print
+  "$file:${LINE+8}:18", // on 'Foo'
+  "$file:${LINE+19}:54", // on 'ccccccccccccc'
+  "$file:${LINE+20}:22", // on first '+'
+  "$file:${LINE+20}:35", // on second '+'
+  "$file:${LINE+20}:50", // on ';'
+  "$file:${LINE+9}:14", // on 'x'
+  "$file:${LINE+9}:3", // on print
+  "$file:${LINE+10}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  // removeDuplicates: Source-based debugging stops on the ';'
+  // in the constructors twice. Kernel does not. For now we'll accept that.
+  checkRecordedStops(stops, expected, removeDuplicates: true)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_constructor_test.dart b/runtime/observatory_2/tests/service_2/step_through_constructor_test.dart
new file mode 100644
index 0000000..42fc5d6
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_constructor_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 17;
+const String file = "step_through_constructor_test.dart";
+
+code() {
+  new Foo();
+}
+
+class Foo {
+  Foo() {
+    print("Hello from Foo!");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // on 'print'
+  "$file:${LINE+1}:3", // on ending '}'
+];
+
+var tests = [
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_2_test.dart b/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_2_test.dart
new file mode 100644
index 0000000..16ee4c9
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_2_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_for_each_sync_star_2_test.dart";
+
+code() {
+  for (int datapoint in generator()) {
+    print(datapoint);
+  }
+}
+
+generator() sync* {
+  var x = 3;
+  var y = 4;
+  yield x;
+  yield x + y;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 7}:9", // on '=' in 'x = 3'
+  "$file:${LINE + 8}:9", // on '=' in 'y = 4'
+  "$file:${LINE + 9}:3", // on yield
+
+  "$file:${LINE + 1}:38", // on '{' in 'for' line
+  "$file:${LINE + 1}:12", // on 'datapoint'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 10}:11", // on '+' in 'x + y'
+  "$file:${LINE + 10}:3", // on yield
+
+  "$file:${LINE + 1}:38", // on '{' in 'for' line
+  "$file:${LINE + 1}:12", // on 'datapoint'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 11}:1", // on ending '}' of 'generator'
+
+  "$file:${LINE + 4}:1", // on ending '}' of 'code''
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_test.dart b/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_test.dart
new file mode 100644
index 0000000..676c5e0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_for_each_sync_star_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_for_each_sync_star_test.dart";
+
+code() {
+  for (int datapoint in generator()) {
+    print(datapoint);
+  }
+}
+
+generator() sync* {
+  var x = 3;
+  var y = 4;
+  yield y;
+  var z = x + y;
+  yield z;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 7}:9", // on '=' in 'x = 3'
+  "$file:${LINE + 8}:9", // on '=' in 'y = 4'
+  "$file:${LINE + 9}:3", // on yield
+
+  "$file:${LINE + 1}:38", // on '{' in 'for' line
+  "$file:${LINE + 1}:12", // on 'datapoint'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 10}:13", // on '+' in 'z = x + y'
+  "$file:${LINE + 11}:3", // on yield
+
+  "$file:${LINE + 1}:38", // on '{' in 'for' line
+  "$file:${LINE + 1}:12", // on 'datapoint'
+  "$file:${LINE + 2}:5", // on 'print'
+  "$file:${LINE + 1}:25", // on 'generator' (in 'for' line)
+
+  "$file:${LINE + 6}:10", // after 'generator' (definition line)
+  "$file:${LINE + 12}:1", // on ending '}' of 'generator'
+
+  "$file:${LINE + 4}:1", // on ending '}' of 'code''
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_function_2_test.dart b/runtime/observatory_2/tests/service_2/step_through_function_2_test.dart
new file mode 100644
index 0000000..b6b6ff5
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_function_2_test.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE = 11;
+const String file = "step_through_function_2_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  bar.barXYZ1(42);
+  bar.barXYZ2(42);
+  fooXYZ1(42);
+  fooXYZ2(42);
+}
+
+// ignore: unused_element
+int _xyz = -1;
+
+fooXYZ1(int i) {
+  _xyz = i - 1;
+}
+
+fooXYZ2(int i) {
+  _xyz = i;
+}
+
+class Bar {
+  int _xyz = -1;
+
+  barXYZ1(int i) {
+    _xyz = i - 1;
+  }
+
+  barXYZ2(int i) {
+    _xyz = i;
+  }
+
+  get barXYZ => _xyz + 1;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:17", // on 'Bar'
+
+  "$file:${LINE + 2}:7", // on 'barXYZ1'
+  "$file:${LINE + 22}:15", // on 'i'
+  "$file:${LINE + 23}:14", // on '-'
+  "$file:${LINE + 23}:5", // on '_xyz'
+  "$file:${LINE + 24}:3", // on '}'
+
+  "$file:${LINE + 3}:7", // on 'barXYZ2'
+  "$file:${LINE + 26}:15", // on 'i'
+  "$file:${LINE + 27}:5", // on '_xyz'
+  "$file:${LINE + 28}:3", // on '}'
+
+  "$file:${LINE + 4}:3", // on 'fooXYZ1'
+  "$file:${LINE + 11}:13", // on 'i'
+  "$file:${LINE + 12}:12", // on '-'
+  "$file:${LINE + 13}:1", // on '}'
+
+  "$file:${LINE + 5}:3", // on 'fooXYZ2'
+  "$file:${LINE + 15}:13", // on 'i'
+  "$file:${LINE + 16}:3", // on '_xyz'
+  "$file:${LINE + 17}:1", // on '}'
+
+  "$file:${LINE + 6}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_function_test.dart b/runtime/observatory_2/tests/service_2/step_through_function_test.dart
new file mode 100644
index 0000000..d206c3a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_function_test.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_function_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  print(bar.barXYZ1());
+  print(bar.barXYZ2(4, 2));
+  print(bar.barXYZ3());
+  print(bar.barXYZ4(4, 2));
+  print(fooXYZ1());
+  print(fooXYZ2(4, 2));
+  print(fooXYZ3());
+  print(fooXYZ4(4, 2));
+}
+
+fooXYZ1 /**/ () => "fooXYZ";
+fooXYZ2 /**/ (int i, int j) => "fooXYZ${i}${j}";
+fooXYZ3 /**/ () {
+  return "fooXYZ";
+}
+
+fooXYZ4 /**/ (int i, int j) {
+  return "fooXYZ${i}${j}";
+}
+
+class Bar {
+  barXYZ1 /**/ () => "barXYZ";
+  barXYZ2 /**/ (int i, int j) => "barXYZ${i}${j}";
+  barXYZ3 /**/ () {
+    return "barXYZ";
+  }
+
+  barXYZ4 /**/ (int i, int j) {
+    return "barXYZ${i}${j}";
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // after 'code'
+  "$file:${LINE+1}:17", // on 'Bar'
+
+  "$file:${LINE+2}:13", // on 'barXYZ1'
+  "$file:${LINE+23}:16", // after 'barXYZ1', i.e. on '('
+  "$file:${LINE+23}:22", // on first '"'
+  "$file:${LINE+2}:3", // on 'print'
+
+  "$file:${LINE+3}:13", // on 'barXYZ2'
+  "$file:${LINE+24}:28", // on 'j'
+  "$file:${LINE+24}:50", // after last '"', i.e. on ';'
+  "$file:${LINE+24}:34", // on first '"'
+  "$file:${LINE+3}:3", // on 'print'
+
+  "$file:${LINE+4}:13", // on 'barXYZ3'
+  "$file:${LINE+25}:16", // after 'barXYZ3', i.e. on '('
+  "$file:${LINE+26}:5", // on 'return'
+  "$file:${LINE+4}:3", // on 'print'
+
+  "$file:${LINE+5}:13", // on 'barXYZ4'
+  "$file:${LINE+29}:28", // on 'j'
+  "$file:${LINE+30}:28", // after last '"', i.e. on ';'
+  "$file:${LINE+30}:5", // on 'return'
+  "$file:${LINE+5}:3", // on 'print'
+
+  "$file:${LINE+6}:9", // on 'fooXYZ1'
+  "$file:${LINE+12}:14", // after 'fooXYZ1', i.e. on '('
+  "$file:${LINE+12}:20", // on first '"'
+  "$file:${LINE+6}:3", // on 'print'
+
+  "$file:${LINE+7}:9", // on 'fooXYZ2'
+  "$file:${LINE+13}:26", // on 'j'
+  "$file:${LINE+13}:48", // after last '"', i.e. on ';'
+  "$file:${LINE+13}:32", // on first '"'
+  "$file:${LINE+7}:3", // on 'print'
+
+  "$file:${LINE+8}:9", // on 'fooXYZ3'
+  "$file:${LINE+14}:14", // after 'fooXYZ3', i.e. on '('
+  "$file:${LINE+15}:3", // on 'return'
+  "$file:${LINE+8}:3", // on 'print'
+
+  "$file:${LINE+9}:9", // on 'fooXYZ4'
+  "$file:${LINE+18}:26", // on 'j'
+  "$file:${LINE+19}:26", // after last '"', i.e. on ';'
+  "$file:${LINE+19}:3", // on 'return'
+  "$file:${LINE+9}:3", // on 'print'
+
+  "$file:${LINE+10}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_getter_test.dart b/runtime/observatory_2/tests/service_2/step_through_getter_test.dart
new file mode 100644
index 0000000..f0160c2
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_getter_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_getter_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  print(bar.barXYZ);
+  print(bar.barXYZ2);
+  print(fooXYZ);
+  print(fooXYZ2);
+}
+
+get fooXYZ => "fooXYZ";
+
+get fooXYZ2 {
+  int i = 42;
+  return "Hello, $i!";
+}
+
+class Bar {
+  get barXYZ => "barXYZ";
+
+  get barXYZ2 {
+    int i = 42;
+    return "Hello, $i!";
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // after 'code'
+  "$file:${LINE+1}:17", // on 'Bar'
+
+  "$file:${LINE+2}:13", // on 'barXYZ'
+  "$file:${LINE+16}:14", // on '=>' in 'get barXYZ => "barXYZ";'
+  "$file:${LINE+16}:17", // on first '"'
+  "$file:${LINE+2}:3", // on 'print'
+
+  "$file:${LINE+3}:13", // on 'barXYZ2'
+  "$file:${LINE+18}:15", // on '{' in 'get barXYZ2 {'
+  "$file:${LINE+19}:11", // on '='
+  "$file:${LINE+20}:24", // after '"', i.e. on ';'
+  "$file:${LINE+20}:5", // on 'return'
+  "$file:${LINE+3}:3", // on 'print'
+
+  "$file:${LINE+4}:9", // on 'fooXYZ'
+  "$file:${LINE+8}:12", // on '=>' in 'get fooXYZ => "fooXYZ";'
+  "$file:${LINE+8}:15", // on first '"'
+  "$file:${LINE+4}:3", // on 'print'
+
+  "$file:${LINE+5}:9", // on 'fooXYZ2'
+  "$file:${LINE+10}:13", // on '{'
+  "$file:${LINE+11}:9", // on '='
+  "$file:${LINE+12}:22", // after '"', i.e. on ';'
+  "$file:${LINE+12}:3", // on 'return'
+  "$file:${LINE+5}:3", // on 'print'
+
+  "$file:${LINE+6}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_mixin_from_sdk_test.dart b/runtime/observatory_2/tests/service_2/step_through_mixin_from_sdk_test.dart
new file mode 100644
index 0000000..fc075a0
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_mixin_from_sdk_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:collection';
+
+const int LINE = 13;
+const String file = "step_through_mixin_from_sdk_test.dart";
+
+code() {
+  Foo foo = new Foo();
+  if (foo.contains(43)) {
+    print("Contains 43!");
+  } else {
+    print("Doesn't contain 43!");
+  }
+}
+
+class Foo extends Object with ListMixin<int> {
+  @override
+  int length = 1;
+
+  @override
+  int operator [](int index) {
+    return 42;
+  }
+
+  @override
+  void operator []=(int index, int value) {}
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:17", // on "Foo" (in "new Foo()")
+  "$file:${LINE + 1}:11", // on "="
+  "list.dart:124:25", // on parameter to "contains"
+  "list.dart:125:23", // on "length" in "this.length"
+  "list.dart:126:16", // on "=" in "i = 0"
+  "list.dart:126:23", // on "<" in "i < length"
+  "list.dart:127:15", // on "[" in "this[i]"
+  "$file:${LINE + 13}:23", // on parameter in "operator []"
+  "$file:${LINE + 14}:5", // on "return"
+  "list.dart:127:19", // on "=="
+  "list.dart:128:26", // on "length" in "this.length"
+  "list.dart:128:18", // on "!="
+  "list.dart:126:34", // on "++" in "i++"
+  "list.dart:126:23", // on "<" in "i < length"
+  "list.dart:132:5", // on "return"
+  "$file:${LINE + 4}:5", // on "print"
+  "$file:${LINE + 6}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected, removeDuplicates: true)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_property_get_test.dart b/runtime/observatory_2/tests/service_2/step_through_property_get_test.dart
new file mode 100644
index 0000000..e312723
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_property_get_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 33;
+const String file = "step_through_property_get_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  bar.doStuff();
+}
+
+class Foo {
+  final List<String> data1;
+
+  Foo() : data1 = ["a", "b", "c"];
+
+  void doStuff() {
+    print(data1);
+    print(data1[1]);
+  }
+}
+
+class Bar extends Foo {
+  final List<String> data2;
+
+  Bar() : data2 = ["d", "e", "f"];
+
+  void doStuff() {
+    print(data2);
+    print(data2[1]);
+
+    print(data1);
+    print(data1[1]);
+
+    print(super.data1);
+    print(super.data1[1]);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:11", // on 'data2'
+  "$file:${LINE+0}:5", // on 'print'
+  "$file:${LINE+1}:11", // on 'data2'
+  "$file:${LINE+1}:16", // on '['
+  "$file:${LINE+1}:5", // on 'print'
+
+  "$file:${LINE+3}:11", // on 'data1'
+  "$file:${LINE+3}:5", // on 'print'
+  "$file:${LINE+4}:11", // on 'data1'
+  "$file:${LINE+4}:16", // on '['
+  "$file:${LINE+4}:5", // on 'print'
+
+  "$file:${LINE+6}:17", // on 'data1'
+  "$file:${LINE+6}:5", // on 'print'
+  "$file:${LINE+7}:17", // on 'data1'
+  "$file:${LINE+7}:22", // on '['
+  "$file:${LINE+7}:5", // on 'print'
+
+  "$file:${LINE+8}:3" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_property_set_test.dart b/runtime/observatory_2/tests/service_2/step_through_property_set_test.dart
new file mode 100644
index 0000000..fab872b
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_property_set_test.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 33;
+const String file = "step_through_property_set_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  bar.doStuff();
+}
+
+class Foo {
+  final List<String> data1;
+
+  Foo() : data1 = ["a", "b", "c"];
+
+  void doStuff() {
+    data1[1] = 'x';
+    print(data1[1]);
+  }
+}
+
+class Bar extends Foo {
+  final List<String> data2;
+
+  Bar() : data2 = ["d", "e", "f"];
+
+  void doStuff() {
+    data2[1] = '1';
+    print(data2[1]);
+
+    data1[1] = '2';
+    print(data1[1]);
+
+    super.data1[1] = '42';
+    print(super.data1[1]);
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // on 'data2'
+  "$file:${LINE+0}:10", // on '['
+  "$file:${LINE+1}:11", // on 'data2'
+  "$file:${LINE+1}:16", // on '['
+  "$file:${LINE+1}:5", // on 'print'
+
+  "$file:${LINE+3}:5", // on 'data1'
+  "$file:${LINE+3}:10", // on '['
+  "$file:${LINE+4}:11", // on 'data1'
+  "$file:${LINE+4}:16", // on '['
+  "$file:${LINE+4}:5", // on 'print'
+
+  "$file:${LINE+6}:11", // on 'data1'
+  "$file:${LINE+6}:16", // on '['
+  "$file:${LINE+7}:17", // on 'data1'
+  "$file:${LINE+7}:22", // on '['
+  "$file:${LINE+7}:5", // on 'print'
+
+  "$file:${LINE+8}:3" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_setter_test.dart b/runtime/observatory_2/tests/service_2/step_through_setter_test.dart
new file mode 100644
index 0000000..aa40fb1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_setter_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE = 11;
+const String file = "step_through_setter_test.dart";
+
+code() {
+  Bar bar = new Bar();
+  bar.barXYZ = 42;
+  fooXYZ = 42;
+}
+
+// ignore: unused_element
+int _xyz = -1;
+
+set fooXYZ(int i) {
+  _xyz = i - 1;
+}
+
+class Bar {
+  int _xyz = -1;
+
+  set barXYZ(int i) {
+    _xyz = i - 1;
+  }
+
+  get barXYZ => _xyz + 1;
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE + 0}:5", // after 'code'
+  "$file:${LINE + 1}:17", // on 'Bar'
+
+  "$file:${LINE + 2}:7", // on 'barXYZ'
+  "$file:${LINE + 16}:18", // on 'i'
+  "$file:${LINE + 17}:14", // on '-'
+  "$file:${LINE + 17}:5", // on '_xyz'
+  "$file:${LINE + 18}:3", // on '}'
+
+  "$file:${LINE + 3}:3", // on 'fooXYZ'
+  "$file:${LINE + 9}:16", // on 'i'
+  "$file:${LINE + 10}:12", // on '-'
+  "$file:${LINE + 11}:1", // on '}'
+
+  "$file:${LINE + 4}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_switch_test.dart b/runtime/observatory_2/tests/service_2/step_through_switch_test.dart
new file mode 100644
index 0000000..bd65fe7
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_switch_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_switch_test.dart";
+
+code() {
+  code2('a');
+  code2('b');
+  code2('c');
+  code2('d');
+}
+
+code2(String key) {
+  switch (key) {
+    case "a":
+      print("a!");
+      break;
+    case "b":
+    case "c":
+      print("b or c!");
+      break;
+    default:
+      print("neither a, b or c...");
+  }
+}
+
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // after 'code'
+
+  "$file:${LINE+1}:3", // on 'code2'
+  "$file:${LINE+7}:14", // on 'key'
+  "$file:${LINE+9}:10", // on first '"' on 'case "a"' line
+  "$file:${LINE+10}:7", // on 'print'
+  "$file:${LINE+11}:7", // on 'break'
+  "$file:${LINE+19}:1", // on '}'
+
+  "$file:${LINE+2}:3", // on 'code2'
+  "$file:${LINE+7}:14", // on 'key'
+  "$file:${LINE+9}:10", // on first '"' on 'case "a"' line
+  "$file:${LINE+12}:10", // on first '"' on 'case "b"' line
+  "$file:${LINE+14}:7", // on 'print'
+  "$file:${LINE+15}:7", // on 'break'
+  "$file:${LINE+19}:1", // on '}'
+
+  "$file:${LINE+3}:3", // on 'code2'
+  "$file:${LINE+7}:14", // on 'key'
+  "$file:${LINE+9}:10", // on first '"' on 'case "a"' line
+  "$file:${LINE+12}:10", // on first '"' on 'case "b"' line
+  "$file:${LINE+13}:10", // on first '"' on 'case "c"' line
+  "$file:${LINE+14}:7", // on 'print'
+  "$file:${LINE+15}:7", // on 'break'
+  "$file:${LINE+19}:1", // on '}'
+
+  "$file:${LINE+4}:3", // on 'code2'
+  "$file:${LINE+7}:14", // on 'key'
+  "$file:${LINE+9}:10", // on first '"' on 'case "a"' line
+  "$file:${LINE+12}:10", // on first '"' on 'case "b"' line
+  "$file:${LINE+13}:10", // on first '"' on 'case "c"' line
+  "$file:${LINE+17}:7", // on 'print'
+  "$file:${LINE+19}:1", // on '}'
+
+  "$file:${LINE+5}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/step_through_switch_with_continue_test.dart b/runtime/observatory_2/tests/service_2/step_through_switch_with_continue_test.dart
new file mode 100644
index 0000000..d9afbb4
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/step_through_switch_with_continue_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'test_helper.dart';
+import 'service_test_common.dart';
+
+const int LINE = 11;
+const String file = "step_through_switch_with_continue_test.dart";
+
+code() {
+  switch (switchOnMe.length) {
+    case 0:
+      print("(got 0!");
+      continue label;
+    label:
+    case 1:
+      print("Got 0 or 1!");
+      break;
+    case 2:
+      print("Got 2!");
+      break;
+    default:
+      print("Got lost!");
+  }
+}
+
+List<String> switchOnMe = [];
+List<String> stops = [];
+List<String> expected = [
+  "$file:${LINE+0}:5", // after 'code'
+
+  "$file:${LINE+1}:11", // on switchOnMe
+  "$file:${LINE+17}:27", // on switchOnMe initializer starting '['
+  "$file:${LINE+1}:22", // on length
+
+  "$file:${LINE+2}:10", // on 0
+  "$file:${LINE+3}:7", // on print
+  "$file:${LINE+4}:7", // on continue
+
+  "$file:${LINE+7}:7", // on print
+  "$file:${LINE+8}:7", // on break
+
+  "$file:${LINE+15}:1" // on ending '}'
+];
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  runStepIntoThroughProgramRecordingStops(stops),
+  checkRecordedStops(stops, expected,
+      debugPrint: true, debugPrintFile: file, debugPrintLine: LINE)
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/service_2/stream_subscription_test.dart b/runtime/observatory_2/tests/service_2/stream_subscription_test.dart
new file mode 100644
index 0000000..145827f
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/stream_subscription_test.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+Future streamListen(VM vm, String streamId) async =>
+    await vm.invokeRpcNoUpgrade(
+      'streamListen',
+      {
+        'streamId': streamId,
+      },
+    );
+
+Future streamCancel(VM vm, String streamId) async =>
+    await vm.invokeRpcNoUpgrade(
+      'streamCancel',
+      {
+        'streamId': streamId,
+      },
+    );
+
+var tests = <VMTest>[
+  // Check double subscription fails.
+  (VM vm) async {
+    await streamListen(vm, '_Echo');
+    try {
+      await streamListen(vm, '_Echo');
+      fail('Subscribed to stream twice');
+    } on ServerRpcException catch (e) {
+      expect(e.message, 'Stream already subscribed');
+    }
+  },
+  // Check double cancellation fails.
+  (VM vm) async {
+    await streamCancel(vm, '_Echo');
+    try {
+      await streamCancel(vm, '_Echo');
+      fail('Double cancellation of stream successful');
+    } on ServerRpcException catch (e) {
+      expect(e.message, 'Stream not subscribed');
+    }
+  },
+  // Check subscription to invalid stream fails.
+  (VM vm) async {
+    try {
+      await streamListen(vm, 'Foo');
+      fail('Subscribed to invalid stream');
+    } on ServerRpcException catch (e) {
+      expect(e.message, "streamListen: invalid 'streamId' parameter: Foo");
+    }
+  }
+];
+
+main(args) => runVMTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/string_escaping_test.dart b/runtime/observatory_2/tests/service_2/string_escaping_test.dart
new file mode 100644
index 0000000..6a9c829
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/string_escaping_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library string_escaping_test;
+
+import 'dart:async';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var ascii;
+var latin1;
+var unicode;
+var hebrew;
+var singleQuotes;
+var doubleQuotes;
+var newLines;
+var tabs;
+var suggrogatePairs;
+var nullInTheMiddle;
+var escapedUnicodeEscape;
+var longStringEven;
+var longStringOdd;
+var malformedWithLeadSurrogate;
+var malformedWithTrailSurrogate;
+
+void script() {
+  ascii = "Hello, World!";
+  latin1 = "blåbærgrød";
+  unicode = "Îñţérñåţîöñåļîžåţîờñ";
+  hebrew = "שלום רב שובך צפורה נחמדת"; // Right-to-left text.
+  singleQuotes = "'One,' he said.";
+  doubleQuotes = '"Two," he said.';
+  newLines = "Windows\r\nSmalltalk\rUnix\n";
+  tabs = "One\tTwo\tThree";
+  suggrogatePairs = "1𝄞2𝄞𝄞3𝄞𝄞𝄞";
+  nullInTheMiddle = "There are four\u0000 words.";
+  escapedUnicodeEscape = "Should not be A: \\u0041";
+
+  // A surrogate pair will cross the preferred truncation boundry.
+  longStringEven = "..";
+  for (int i = 0; i < 512; i++) longStringEven += "𝄞";
+  longStringOdd = ".";
+  for (int i = 0; i < 512; i++) longStringOdd += "𝄞";
+
+  malformedWithLeadSurrogate = "before" + "𝄞"[0] + "after";
+  malformedWithTrailSurrogate = "before" + "𝄞"[1] + "after";
+}
+
+Future testStrings(Isolate isolate) async {
+  Library lib = isolate.rootLibrary;
+  await lib.load();
+  for (var variable in lib.variables) {
+    await variable.load();
+  }
+
+  expectFullString(String varName, String varValueAsString) {
+    Field field = lib.variables.singleWhere((v) => v.name == varName);
+    Instance value = field.staticValue;
+    expect(value.valueAsString, equals(varValueAsString));
+    expect(value.valueAsStringIsTruncated, isFalse);
+  }
+
+  expectTruncatedString(String varName, String varValueAsString) {
+    Field field = lib.variables.singleWhere((v) => v.name == varName);
+    Instance value = field.staticValue;
+    expect(varValueAsString, startsWith(value.valueAsString));
+    expect(value.valueAsStringIsTruncated, isTrue);
+  }
+
+  script(); // Need to initialize variables in the testing isolate.
+  expectFullString('ascii', ascii);
+  expectFullString('latin1', latin1);
+  expectFullString('unicode', unicode);
+  expectFullString('hebrew', hebrew);
+  expectFullString('singleQuotes', singleQuotes);
+  expectFullString('doubleQuotes', doubleQuotes);
+  expectFullString('newLines', newLines);
+  expectFullString('tabs', tabs);
+  expectFullString('suggrogatePairs', suggrogatePairs);
+  expectFullString('nullInTheMiddle', nullInTheMiddle);
+  expectTruncatedString('longStringEven', longStringEven);
+  expectTruncatedString('longStringOdd', longStringOdd);
+  expectFullString('malformedWithLeadSurrogate', malformedWithLeadSurrogate);
+  expectFullString('malformedWithTrailSurrogate', malformedWithTrailSurrogate);
+}
+
+var tests = <IsolateTest>[
+  testStrings,
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/test_helper.dart b/runtime/observatory_2/tests/service_2/test_helper.dart
new file mode 100644
index 0000000..18f345e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/test_helper.dart
@@ -0,0 +1,681 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library test_helper;
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'package:dds/dds.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+export 'service_test_common.dart' show DDSTest, IsolateTest, VMTest;
+
+/// Whether to use causal async stacks (if not we use lazy async stacks).
+const bool useCausalAsyncStacks =
+    const bool.fromEnvironment('dart.developer.causal_async_stacks');
+
+/// Determines whether DDS is enabled for this test run.
+const bool useDds = const bool.fromEnvironment('USE_DDS');
+
+/// The extra arguments to use
+const List<String> extraDebuggingArgs = useCausalAsyncStacks
+    ? const ['--causal-async-stacks', '--no-lazy-async-stacks']
+    : const ['--no-causal-async-stacks', '--lazy-async-stacks'];
+
+/// Will be set to the http address of the VM's service protocol before
+/// any tests are invoked.
+String serviceHttpAddress;
+String serviceWebsocketAddress;
+
+const String _TESTEE_ENV_KEY = 'SERVICE_TEST_TESTEE';
+const Map<String, String> _TESTEE_SPAWN_ENV = const {_TESTEE_ENV_KEY: 'true'};
+bool _isTestee() {
+  return Platform.environment.containsKey(_TESTEE_ENV_KEY);
+}
+
+const String _SKY_SHELL_ENV_KEY = 'SERVICE_TEST_SKY_SHELL';
+bool _shouldLaunchSkyShell() {
+  return Platform.environment.containsKey(_SKY_SHELL_ENV_KEY);
+}
+
+String _skyShellPath() {
+  return Platform.environment[_SKY_SHELL_ENV_KEY];
+}
+
+class _ServiceTesteeRunner {
+  Future run(
+      {testeeBefore(): null,
+      testeeConcurrent(): null,
+      bool pause_on_start: false,
+      bool pause_on_exit: false}) async {
+    if (!pause_on_start) {
+      if (testeeBefore != null) {
+        final result = testeeBefore();
+        if (result is Future) {
+          await result;
+        }
+      }
+      print(''); // Print blank line to signal that testeeBefore has run.
+    }
+    if (testeeConcurrent != null) {
+      final result = testeeConcurrent();
+      if (result is Future) {
+        await result;
+      }
+    }
+    if (!pause_on_exit) {
+      // Wait around for the process to be killed.
+      stdin.first.then((_) => exit(0));
+    }
+  }
+
+  void runSync(
+      {void testeeBeforeSync(): null,
+      void testeeConcurrentSync(): null,
+      bool pause_on_start: false,
+      bool pause_on_exit: false}) {
+    if (!pause_on_start) {
+      if (testeeBeforeSync != null) {
+        testeeBeforeSync();
+      }
+      print(''); // Print blank line to signal that testeeBefore has run.
+    }
+    if (testeeConcurrentSync != null) {
+      testeeConcurrentSync();
+    }
+    if (!pause_on_exit) {
+      // Wait around for the process to be killed.
+      stdin.first.then((_) => exit(0));
+    }
+  }
+}
+
+class _ServiceTesteeLauncher {
+  Process process;
+  final List<String> args;
+  Future<void> get exited => _processCompleter.future;
+  final _processCompleter = Completer<void>();
+  bool killedByTester = false;
+
+  _ServiceTesteeLauncher() : args = [Platform.script.toFilePath()] {}
+
+  // Spawn the testee process.
+  Future<Process> _spawnProcess(
+      bool pause_on_start,
+      bool pause_on_exit,
+      bool pause_on_unhandled_exceptions,
+      bool enable_service_port_fallback,
+      bool testeeControlsServer,
+      Uri serviceInfoUri,
+      int port,
+      List<String> extraArgs,
+      List<String> executableArgs) {
+    assert(pause_on_start != null);
+    assert(pause_on_exit != null);
+    assert(pause_on_unhandled_exceptions != null);
+    assert(testeeControlsServer != null);
+
+    if (_shouldLaunchSkyShell()) {
+      return _spawnSkyProcess(
+          pause_on_start,
+          pause_on_exit,
+          pause_on_unhandled_exceptions,
+          testeeControlsServer,
+          extraArgs,
+          executableArgs);
+    } else {
+      return _spawnDartProcess(
+          pause_on_start,
+          pause_on_exit,
+          pause_on_unhandled_exceptions,
+          enable_service_port_fallback,
+          testeeControlsServer,
+          serviceInfoUri,
+          port,
+          extraArgs,
+          executableArgs);
+    }
+  }
+
+  Future<Process> _spawnDartProcess(
+      bool pause_on_start,
+      bool pause_on_exit,
+      bool pause_on_unhandled_exceptions,
+      bool enable_service_port_fallback,
+      bool testeeControlsServer,
+      Uri serviceInfoUri,
+      int port,
+      List<String> extraArgs,
+      List<String> executableArgs) {
+    assert(!_shouldLaunchSkyShell());
+
+    final String dartExecutable = Platform.executable;
+
+    final fullArgs = <String>[
+      '--disable-dart-dev',
+    ];
+    if (pause_on_start) {
+      fullArgs.add('--pause-isolates-on-start');
+    }
+    if (pause_on_exit) {
+      fullArgs.add('--pause-isolates-on-exit');
+    }
+    if (enable_service_port_fallback) {
+      fullArgs.add('--enable_service_port_fallback');
+    }
+    fullArgs.add('--write-service-info=$serviceInfoUri');
+
+    if (pause_on_unhandled_exceptions) {
+      fullArgs.add('--pause-isolates-on-unhandled-exceptions');
+    }
+    fullArgs.add('--profiler');
+    if (extraArgs != null) {
+      fullArgs.addAll(extraArgs);
+    }
+    fullArgs.addAll(executableArgs);
+    if (!testeeControlsServer) {
+      fullArgs.add('--enable-vm-service:$port');
+    }
+    fullArgs.addAll(args);
+
+    return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
+  }
+
+  Future<Process> _spawnSkyProcess(
+      bool pause_on_start,
+      bool pause_on_exit,
+      bool pause_on_unhandled_exceptions,
+      bool testeeControlsServer,
+      List<String> extraArgs,
+      List<String> executableArgs) {
+    assert(_shouldLaunchSkyShell());
+
+    final String dartExecutable = _skyShellPath();
+
+    final dartFlags = <String>[];
+    final fullArgs = <String>[];
+    if (pause_on_start) {
+      dartFlags.add('--pause_isolates_on_start');
+      fullArgs.add('--start-paused');
+    }
+    if (pause_on_exit) {
+      dartFlags.add('--pause_isolates_on_exit');
+    }
+    if (pause_on_unhandled_exceptions) {
+      dartFlags.add('--pause_isolates_on_unhandled_exceptions');
+    }
+    dartFlags.add('--profiler');
+    // Override mirrors.
+    dartFlags.add('--enable_mirrors=true');
+    if (extraArgs != null) {
+      fullArgs.addAll(extraArgs);
+    }
+    fullArgs.addAll(executableArgs);
+    if (!testeeControlsServer) {
+      fullArgs.add('--observatory-port=0');
+    }
+    fullArgs.add('--dart-flags=${dartFlags.join(' ')}');
+    fullArgs.addAll(args);
+
+    return _spawnCommon(dartExecutable, fullArgs, <String, String>{});
+  }
+
+  Future<Process> _spawnCommon(String executable, List<String> arguments,
+      Map<String, String> dartEnvironment) {
+    final environment = _TESTEE_SPAWN_ENV;
+    final bashEnvironment = new StringBuffer();
+    environment.forEach((k, v) => bashEnvironment.write("$k=$v "));
+    if (dartEnvironment != null) {
+      dartEnvironment.forEach((k, v) {
+        arguments.insert(0, '-D$k=$v');
+      });
+    }
+    print('** Launching $bashEnvironment$executable ${arguments.join(' ')}');
+    return Process.start(executable, arguments, environment: environment);
+  }
+
+  Future<Uri> launch(
+      bool pause_on_start,
+      bool pause_on_exit,
+      bool pause_on_unhandled_exceptions,
+      bool enable_service_port_fallback,
+      bool testeeControlsServer,
+      int port,
+      List<String> extraArgs,
+      List<String> executableArgs) async {
+    final completer = new Completer<Uri>();
+    final serviceInfoDir =
+        await Directory.systemTemp.createTemp('dart_service');
+    final serviceInfoUri = serviceInfoDir.uri.resolve('service_info.json');
+    final serviceInfoFile = await File.fromUri(serviceInfoUri).create();
+    _spawnProcess(
+            pause_on_start,
+            pause_on_exit,
+            pause_on_unhandled_exceptions,
+            enable_service_port_fallback,
+            testeeControlsServer,
+            serviceInfoUri,
+            port,
+            extraArgs,
+            executableArgs)
+        .then((p) async {
+      process = p;
+      Uri uri;
+      final blankCompleter = Completer();
+      bool blankLineReceived = false;
+      process.stdout
+          .transform(utf8.decoder)
+          .transform(new LineSplitter())
+          .listen((line) {
+        if (!blankLineReceived && (pause_on_start || line == '')) {
+          // Received blank line.
+          blankLineReceived = true;
+          blankCompleter.complete();
+        }
+        print('>testee>out> $line');
+      });
+      process.stderr
+          .transform(utf8.decoder)
+          .transform(new LineSplitter())
+          .listen((line) {
+        print('>testee>err> ${line.trim()}');
+      });
+      process.exitCode.then((exitCode) async {
+        await serviceInfoDir.delete(recursive: true);
+        if ((exitCode != 0) && !killedByTester) {
+          throw "Testee exited with $exitCode";
+        }
+        print("** Process exited");
+        _processCompleter.complete();
+      });
+
+      // Wait for the blank line which signals that we're ready to run.
+      await blankCompleter.future;
+      while ((await serviceInfoFile.length()) <= 5) {
+        await Future.delayed(Duration(milliseconds: 50));
+      }
+      final content = await serviceInfoFile.readAsString();
+      final infoJson = json.decode(content);
+      String rawUri = infoJson['uri'];
+
+      // If rawUri ends with a /, Uri.parse will include an empty string as the
+      // last path segment. Make sure it's not there to ensure we have a
+      // consistent Uri.
+      if (rawUri.endsWith('/')) {
+        rawUri = rawUri.substring(0, rawUri.length - 1);
+      }
+      uri = Uri.parse(rawUri);
+      completer.complete(uri);
+    });
+    return completer.future;
+  }
+
+  void requestExit() {
+    if (process != null) {
+      print('** Killing script');
+      if (process.kill()) {
+        killedByTester = true;
+      }
+    }
+  }
+}
+
+void setupAddresses(Uri serverAddress) {
+  serviceWebsocketAddress =
+      'ws://${serverAddress.authority}${serverAddress.path}/ws';
+  serviceHttpAddress = 'http://${serverAddress.authority}${serverAddress.path}';
+}
+
+class _ServiceTesterRunner {
+  void run({
+    List<String> mainArgs,
+    List<String> extraArgs,
+    List<String> executableArgs,
+    List<DDSTest> ddsTests,
+    List<IsolateTest> isolateTests,
+    List<VMTest> vmTests,
+    bool pause_on_start: false,
+    bool pause_on_exit: false,
+    bool verbose_vm: false,
+    bool pause_on_unhandled_exceptions: false,
+    bool enable_service_port_fallback: false,
+    bool testeeControlsServer: false,
+    bool enableDds: true,
+    bool enableService: true,
+    int port = 0,
+  }) {
+    if (executableArgs == null) {
+      executableArgs = Platform.executableArguments;
+    }
+    DartDevelopmentService dds;
+    WebSocketVM vm;
+    _ServiceTesteeLauncher process;
+    bool testsDone = false;
+
+    ignoreLateException(Function f) async {
+      try {
+        await f();
+      } catch (error, stackTrace) {
+        if (testsDone) {
+          print('Ignoring late exception during process exit:\n'
+              '$error\n$stackTrace');
+        } else {
+          rethrow;
+        }
+      }
+    }
+
+    setUp(
+      () => ignoreLateException(
+        () async {
+          process = _ServiceTesteeLauncher();
+          await process
+              .launch(
+                  pause_on_start,
+                  pause_on_exit,
+                  pause_on_unhandled_exceptions,
+                  enable_service_port_fallback,
+                  testeeControlsServer,
+                  port,
+                  extraArgs,
+                  executableArgs)
+              .then((Uri serverAddress) async {
+            if (mainArgs.contains("--gdb")) {
+              final pid = process.process.pid;
+              final wait = new Duration(seconds: 10);
+              print("Testee has pid $pid, waiting $wait before continuing");
+              sleep(wait);
+            }
+            if (useDds) {
+              dds = await DartDevelopmentService.startDartDevelopmentService(
+                  serverAddress);
+              setupAddresses(dds.uri);
+            } else {
+              setupAddresses(serverAddress);
+            }
+            print('** Signaled to run test queries on $serviceHttpAddress'
+                ' (${useDds ? "DDS" : "VM Service"})');
+            vm =
+                new WebSocketVM(new WebSocketVMTarget(serviceWebsocketAddress));
+            print('Loading VM...');
+            await vm.load();
+            print('Done loading VM');
+          });
+        },
+      ),
+    );
+
+    tearDown(
+      () => ignoreLateException(
+        () async {
+          if (useDds) {
+            await dds?.shutdown();
+          }
+          process.requestExit();
+        },
+      ),
+    );
+
+    final name = Platform.script.pathSegments.last;
+    runTest(String name) {
+      test(
+        '$name (${useDds ? 'DDS' : 'VM Service'})',
+        () => ignoreLateException(
+          () async {
+            // Run vm tests.
+            if (vmTests != null) {
+              int testIndex = 1;
+              final totalTests = vmTests.length;
+              for (var test in vmTests) {
+                vm.verbose = verbose_vm;
+                print('Running $name [$testIndex/$totalTests]');
+                testIndex++;
+                await test(vm);
+              }
+            }
+
+            // Run dds tests.
+            if (ddsTests != null) {
+              int testIndex = 1;
+              final totalTests = ddsTests.length;
+              for (var test in ddsTests) {
+                vm.verbose = verbose_vm;
+                print('Running $name [$testIndex/$totalTests]');
+                testIndex++;
+                await test(vm, dds);
+              }
+            }
+
+            // Run isolate tests.
+            if (isolateTests != null) {
+              final isolate = await getFirstIsolate(vm);
+              int testIndex = 1;
+              final totalTests = isolateTests.length;
+              for (var test in isolateTests) {
+                vm.verbose = verbose_vm;
+                print('Running $name [$testIndex/$totalTests]');
+                testIndex++;
+                await test(isolate);
+              }
+            }
+
+            print('All service tests completed successfully.');
+            testsDone = true;
+          },
+        ),
+        // Some service tests run fairly long (e.g., valid_source_locations_test).
+        timeout: Timeout.none,
+      );
+    }
+
+    if ((useDds && !enableDds) || (!useDds && ddsTests != null)) {
+      print('Skipping DDS run for $name');
+      return;
+    }
+    if (!useDds && !enableService) {
+      print('Skipping VM Service run for $name');
+      return;
+    }
+    runTest(name);
+  }
+
+  Future<Isolate> getFirstIsolate(WebSocketVM vm) async {
+    if (vm.isolates.isNotEmpty) {
+      final isolate = await vm.isolates.first.load();
+      if (isolate is Isolate) {
+        return isolate;
+      }
+    }
+
+    Completer completer = new Completer();
+    vm.getEventStream(VM.kIsolateStream).then((stream) {
+      var subscription;
+      subscription = stream.listen((ServiceEvent event) async {
+        if (completer == null) {
+          subscription.cancel();
+          return;
+        }
+        if (event.kind == ServiceEvent.kIsolateRunnable) {
+          if (vm.isolates.isNotEmpty) {
+            vm.isolates.first.load().then((result) {
+              if (result is Isolate) {
+                subscription.cancel();
+                completer.complete(result);
+                completer = null;
+              }
+            });
+          }
+        }
+      });
+    });
+
+    // The isolate may have started before we subscribed.
+    if (vm.isolates.isNotEmpty) {
+      vm.isolates.first.reload().then((result) async {
+        if (completer != null && result is Isolate) {
+          completer.complete(result);
+          completer = null;
+        }
+      });
+    }
+    return await completer.future;
+  }
+}
+
+/// Runs [tests] in sequence, each of which should take an [Isolate] and
+/// return a [Future]. Code for setting up state can run before and/or
+/// concurrently with the tests. Uses [mainArgs] to determine whether
+/// to run tests or testee in this invocation of the script.
+Future runIsolateTests(List<String> mainArgs, List<IsolateTest> tests,
+    {testeeBefore(),
+    testeeConcurrent(),
+    bool pause_on_start: false,
+    bool pause_on_exit: false,
+    bool verbose_vm: false,
+    bool pause_on_unhandled_exceptions: false,
+    bool testeeControlsServer: false,
+    bool enableDds: true,
+    bool enableService: true,
+    List<String> extraArgs}) async {
+  assert(!pause_on_start || testeeBefore == null);
+  if (_isTestee()) {
+    new _ServiceTesteeRunner().run(
+        testeeBefore: testeeBefore,
+        testeeConcurrent: testeeConcurrent,
+        pause_on_start: pause_on_start,
+        pause_on_exit: pause_on_exit);
+  } else {
+    new _ServiceTesterRunner().run(
+      mainArgs: mainArgs,
+      extraArgs: extraArgs,
+      isolateTests: tests,
+      pause_on_start: pause_on_start,
+      pause_on_exit: pause_on_exit,
+      verbose_vm: verbose_vm,
+      pause_on_unhandled_exceptions: pause_on_unhandled_exceptions,
+      testeeControlsServer: testeeControlsServer,
+      enableDds: enableDds,
+      enableService: enableService,
+    );
+  }
+}
+
+/// Runs [tests] in sequence, each of which should take an [Isolate] and
+/// return a [Future]. Code for setting up state can run before and/or
+/// concurrently with the tests. Uses [mainArgs] to determine whether
+/// to run tests or testee in this invocation of the script.
+///
+/// This is a special version of this test harness specifically for the
+/// pause_on_unhandled_exceptions_test, which cannot properly function
+/// in an async context (because exceptions are *always* handled in async
+/// functions).
+void runIsolateTestsSynchronous(List<String> mainArgs, List<IsolateTest> tests,
+    {void testeeBefore(),
+    void testeeConcurrent(),
+    bool pause_on_start: false,
+    bool pause_on_exit: false,
+    bool verbose_vm: false,
+    bool pause_on_unhandled_exceptions: false,
+    List<String> extraArgs}) {
+  assert(!pause_on_start || testeeBefore == null);
+  if (_isTestee()) {
+    new _ServiceTesteeRunner().runSync(
+        testeeBeforeSync: testeeBefore,
+        testeeConcurrentSync: testeeConcurrent,
+        pause_on_start: pause_on_start,
+        pause_on_exit: pause_on_exit);
+  } else {
+    new _ServiceTesterRunner().run(
+        mainArgs: mainArgs,
+        extraArgs: extraArgs,
+        isolateTests: tests,
+        pause_on_start: pause_on_start,
+        pause_on_exit: pause_on_exit,
+        verbose_vm: verbose_vm,
+        pause_on_unhandled_exceptions: pause_on_unhandled_exceptions);
+  }
+}
+
+/// Runs [tests] in sequence, each of which should take a [VM] and
+/// return a [Future]. Code for setting up state can run before and/or
+/// concurrently with the tests. Uses [mainArgs] to determine whether
+/// to run tests or testee in this invocation of the script.
+Future runVMTests(List<String> mainArgs, List<VMTest> tests,
+    {testeeBefore(),
+    testeeConcurrent(),
+    bool pause_on_start: false,
+    bool pause_on_exit: false,
+    bool verbose_vm: false,
+    bool pause_on_unhandled_exceptions: false,
+    bool enable_service_port_fallback: false,
+    bool enableDds: true,
+    bool enableService: true,
+    int port = 0,
+    List<String> extraArgs,
+    List<String> executableArgs}) async {
+  if (_isTestee()) {
+    new _ServiceTesteeRunner().run(
+        testeeBefore: testeeBefore,
+        testeeConcurrent: testeeConcurrent,
+        pause_on_start: pause_on_start,
+        pause_on_exit: pause_on_exit);
+  } else {
+    new _ServiceTesterRunner().run(
+      mainArgs: mainArgs,
+      extraArgs: extraArgs,
+      executableArgs: executableArgs,
+      vmTests: tests,
+      pause_on_start: pause_on_start,
+      pause_on_exit: pause_on_exit,
+      verbose_vm: verbose_vm,
+      pause_on_unhandled_exceptions: pause_on_unhandled_exceptions,
+      enable_service_port_fallback: enable_service_port_fallback,
+      enableDds: enableDds,
+      enableService: enableService,
+      port: port,
+    );
+  }
+}
+
+/// Runs [tests] in sequence, each of which should take a [VM] and
+/// [DartDevelopmentService] and return a [Future]. Code for setting up state
+/// can run before and/or concurrently with the tests. Uses [mainArgs] to
+/// determine whether to run tests or testee in this invocation of the
+/// script.
+Future runDDSTests(List<String> mainArgs, List<DDSTest> tests,
+    {testeeBefore(),
+    testeeConcurrent(),
+    bool pause_on_start: false,
+    bool pause_on_exit: false,
+    bool verbose_vm: false,
+    bool pause_on_unhandled_exceptions: false,
+    bool enable_service_port_fallback: false,
+    int port = 0,
+    List<String> extraArgs,
+    List<String> executableArgs}) async {
+  if (_isTestee()) {
+    new _ServiceTesteeRunner().run(
+        testeeBefore: testeeBefore,
+        testeeConcurrent: testeeConcurrent,
+        pause_on_start: pause_on_start,
+        pause_on_exit: pause_on_exit);
+  } else {
+    new _ServiceTesterRunner().run(
+      mainArgs: mainArgs,
+      extraArgs: extraArgs,
+      executableArgs: executableArgs,
+      ddsTests: tests,
+      pause_on_start: pause_on_start,
+      pause_on_exit: pause_on_exit,
+      verbose_vm: verbose_vm,
+      pause_on_unhandled_exceptions: pause_on_unhandled_exceptions,
+      enable_service_port_fallback: enable_service_port_fallback,
+      enableDds: true,
+      enableService: false,
+      port: port,
+    );
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/timeline_leak_test.dart b/runtime/observatory_2/tests/service_2/timeline_leak_test.dart
new file mode 100644
index 0000000..03f848e
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/timeline_leak_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--timeline-recorder=ring --timeline-streams=Dart
+
+import 'dart:developer';
+
+main() {
+  for (var i = 0; i < 100000; i++) {
+    // OneByteString, ASCII
+    Timeline.startSync('ASCII', arguments: {'arg': 'ASCII'});
+    Timeline.finishSync();
+
+    // OneByteString, Latin1
+    Timeline.startSync('blåbærgrød', arguments: {'arg': 'blåbærgrød'});
+    Timeline.finishSync();
+
+    // TwoByteString
+    Timeline.startSync('Îñţérñåţîöñåļîžåţîờñ',
+        arguments: {'arg': 'Îñţérñåţîöñåļîžåţîờñ'});
+    Timeline.finishSync();
+  }
+}
diff --git a/runtime/observatory_2/tests/service_2/type_arguments_test.dart b/runtime/observatory_2/tests/service_2/type_arguments_test.dart
new file mode 100644
index 0000000..91c97e1
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/type_arguments_test.dart
@@ -0,0 +1,46 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) =>
+      isolate.getTypeArgumentsList(false).then((dynamic allTypeArgs) {
+        var allTypeArgsTableSize =
+            allTypeArgs['canonicalTypeArgumentsTableSize'];
+        var allTypeArgsTableUsed =
+            allTypeArgs['canonicalTypeArgumentsTableUsed'];
+        var allTypeArgsList = allTypeArgs['typeArguments'];
+        expect(allTypeArgsList, isNotNull);
+        // Check size >= used.
+        expect(
+            allTypeArgsTableSize, greaterThanOrEqualTo(allTypeArgsTableUsed));
+        return isolate
+            .getTypeArgumentsList(true)
+            .then((dynamic instantiatedTypeArgs) {
+          var instantiatedTypeArgsTableSize =
+              instantiatedTypeArgs['canonicalTypeArgumentsTableSize'];
+          var instantiatedTypeArgsTableUsed =
+              instantiatedTypeArgs['canonicalTypeArgumentsTableUsed'];
+          // Check size >= used.
+          expect(instantiatedTypeArgsTableSize,
+              greaterThanOrEqualTo(instantiatedTypeArgsTableUsed));
+          // Check that |instantiated| <= |all|
+          var instantiatedTypeArgsList = instantiatedTypeArgs['typeArguments'];
+          expect(instantiatedTypeArgsList, isNotNull);
+          expect(allTypeArgsList.length,
+              greaterThanOrEqualTo(instantiatedTypeArgsList.length));
+          // Check that we can 'get' this object again.
+          var firstType = allTypeArgsList[0];
+          return isolate.getObject(firstType.id).then((ServiceObject object) {
+            TypeArguments type = object;
+            expect(firstType.name, type.name);
+          });
+        });
+      }),
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/typed_data_test.dart b/runtime/observatory_2/tests/service_2/typed_data_test.dart
new file mode 100644
index 0000000..3de01a8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/typed_data_test.dart
@@ -0,0 +1,137 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+library typed_data_test;
+
+import 'dart:typed_data';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var int8List;
+var int16List;
+var int32List;
+var int64List;
+
+var uint8List;
+var uint16List;
+var uint32List;
+var uint64List;
+var uint8ClampedList;
+
+var float32List;
+var float64List;
+
+var int32x4;
+var float32x4;
+var float64x2;
+var int32x4List;
+var float32x4List;
+var float64x2List;
+
+void script() {
+  int8List = new Int8List(2);
+  int8List[0] = -1;
+  int8List[1] = -2;
+  int16List = new Int16List(2);
+  int16List[0] = -3;
+  int16List[1] = -4;
+  int32List = new Int32List(2);
+  int32List[0] = -5;
+  int32List[1] = -6;
+  int64List = new Int64List(2);
+  int64List[0] = -7;
+  int64List[1] = -8;
+
+  uint8List = new Uint8List(2);
+  uint8List[0] = 1;
+  uint8List[1] = 2;
+  uint16List = new Uint16List(2);
+  uint16List[0] = 3;
+  uint16List[1] = 4;
+  uint32List = new Uint32List(2);
+  uint32List[0] = 5;
+  uint32List[1] = 6;
+  uint64List = new Uint64List(2);
+  uint64List[0] = 7;
+  uint64List[1] = 8;
+  uint8ClampedList = new Uint8ClampedList(2);
+  uint8ClampedList[0] = 9;
+  uint8ClampedList[1] = 10;
+
+  float32List = new Float32List(2);
+  float32List[0] = 4.25;
+  float32List[1] = 8.50;
+  float64List = new Float64List(2);
+  float64List[0] = 16.25;
+  float64List[1] = 32.50;
+
+  int32x4 = new Int32x4(1, 2, 3, 4);
+  float32x4 = new Float32x4(1.0, 2.0, 4.0, 8.0);
+  float64x2 = new Float64x2(16.0, 32.0);
+  int32x4List = new Int32x4List(2);
+  float32x4List = new Float32x4List(2);
+  float64x2List = new Float64x2List(2);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    script();
+    Library lib = await isolate.rootLibrary.load();
+
+    // Pre-load all the fields so we don't use await below and get better
+    // stacktraces.
+    for (var v in lib.variables) {
+      await v.load();
+      await v.staticValue.load();
+    }
+
+    expectTypedData(name, expectedValue) {
+      var variable = lib.variables.singleWhere((v) => v.name == name);
+      var actualValue = (variable.staticValue as Instance).typedElements;
+      if (expectedValue is Int32x4List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+          expect(actualValue[i].z, equals(expectedValue[i].z));
+          expect(actualValue[i].w, equals(expectedValue[i].w));
+        }
+      } else if (expectedValue is Float32x4List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+          expect(actualValue[i].z, equals(expectedValue[i].z));
+          expect(actualValue[i].w, equals(expectedValue[i].w));
+        }
+      } else if (expectedValue is Float64x2List) {
+        expect(actualValue.length, equals(expectedValue.length));
+        for (var i = 0; i < actualValue.length; i++) {
+          expect(actualValue[i].x, equals(expectedValue[i].x));
+          expect(actualValue[i].y, equals(expectedValue[i].y));
+        }
+      } else {
+        expect(actualValue, equals(expectedValue));
+      }
+    }
+
+    expectTypedData("int8List", int8List);
+    expectTypedData("int16List", int16List);
+    expectTypedData("int32List", int32List);
+    expectTypedData("int64List", int64List);
+    expectTypedData("uint8List", uint8List);
+    expectTypedData("uint16List", uint16List);
+    expectTypedData("uint32List", uint32List);
+    expectTypedData("uint64List", uint64List);
+    expectTypedData("uint8ClampedList", uint8ClampedList);
+    expectTypedData("float32List", float32List);
+    expectTypedData("float64List", float64List);
+    expectTypedData("int32x4List", int32x4List);
+    expectTypedData("float32x4List", float32x4List);
+    expectTypedData("float64x2List", float64x2List);
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/valid_source_locations_test.dart b/runtime/observatory_2/tests/service_2/valid_source_locations_test.dart
new file mode 100644
index 0000000..79f20cc
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/valid_source_locations_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+
+import 'package:observatory_2/service_io.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+void testFunction() {
+  debugger();
+}
+
+Future validateLocation(Location location, Object object) async {
+  if (location == null) return;
+  if (location.tokenPos < 0) return;
+  if (location.script.uri == 'dart:_internal-patch/class_id_fasta.dart') {
+    // Injected fields from this script cannot be reloaded.
+    return;
+  }
+
+  // Ensure the script is loaded.
+  final Script script = await location.script.load();
+
+  // Use the more low-level functions.
+  final line = script.tokenToLine(location.tokenPos);
+  if (line == null) {
+    throw 'missing location for $object in script ${script.uri}';
+  }
+  script.getLine(line);
+  script.tokenToCol(location.tokenPos);
+
+  // Use the helper functions.
+  await location.getLine();
+  await location.getColumn();
+}
+
+Future validateFieldLocation(Field field) async {
+  field = await field.load();
+  await validateLocation(field.location, field);
+}
+
+Future validateFunctionLocation(ServiceFunction fun) async {
+  fun = await fun.load();
+  await validateLocation(fun.location, fun);
+}
+
+Future validateClassLocation(Class klass) async {
+  klass = await klass.load();
+  await validateLocation(klass.location, klass);
+
+  for (Field field in klass.fields) {
+    await validateFieldLocation(field);
+  }
+  for (ServiceFunction fun in klass.functions) {
+    await validateFunctionLocation(fun);
+  }
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Force everything to be compiled.
+    final params = {
+      'reports': ['Coverage'],
+      'forceCompile': true
+    };
+    await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+
+    // Loop over all libraries, classes, functions and fields to ensure .
+    for (Library lib in isolate.libraries) {
+      lib = await lib.load();
+
+      for (Field field in lib.variables) {
+        await validateFieldLocation(field);
+      }
+      for (ServiceFunction fun in lib.functions) {
+        await validateFunctionLocation(fun);
+      }
+      for (Class klass in lib.classes) {
+        await validateClassLocation(klass);
+      }
+    }
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory_2/tests/service_2/verify_http_timeline_test.dart b/runtime/observatory_2/tests/service_2/verify_http_timeline_test.dart
new file mode 100644
index 0000000..a4ca036
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/verify_http_timeline_test.dart
@@ -0,0 +1,330 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--timeline_streams=Dart
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+import 'dart:math';
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final rng = Random();
+
+// Enable to test redirects.
+const shouldTestRedirects = false;
+
+const maxRequestDelayMs = 3000;
+const maxResponseDelayMs = 500;
+const serverShutdownDelayMs = 2000;
+
+void randomlyAddCookie(HttpResponse response) {
+  if (rng.nextInt(3) == 0) {
+    response.cookies.add(Cookie('Cookie-Monster', 'Me-want-cookie!'));
+  }
+}
+
+Future<bool> randomlyRedirect(HttpServer server, HttpResponse response) async {
+  if (shouldTestRedirects && rng.nextInt(5) == 0) {
+    final redirectUri = Uri(host: 'www.google.com', port: 80);
+    response.redirect(redirectUri);
+    return true;
+  }
+  return false;
+}
+
+// Execute HTTP requests with random delays so requests have some overlap. This
+// way we can be certain that timeline events are matching up properly even when
+// connections are interrupted or can't be established.
+Future<void> executeWithRandomDelay(Function f) =>
+    Future<void>.delayed(Duration(milliseconds: rng.nextInt(maxRequestDelayMs)))
+        .then((_) async {
+      try {
+        await f();
+      } on HttpException catch (_) {} on SocketException catch (_) {} on StateError catch (_) {} on OSError catch (_) {}
+    });
+
+Uri randomlyAddRequestParams(Uri uri) {
+  const possiblePathSegments = <String>['foo', 'bar', 'baz', 'foobar'];
+  final segmentSubset =
+      possiblePathSegments.sublist(0, rng.nextInt(possiblePathSegments.length));
+  uri = uri.replace(pathSegments: segmentSubset);
+  if (rng.nextInt(3) == 0) {
+    uri = uri.replace(queryParameters: {
+      'foo': 'bar',
+      'year': '2019',
+    });
+  }
+  return uri;
+}
+
+Future<HttpServer> startServer() async {
+  final server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
+  server.listen((request) async {
+    final response = request.response;
+    response.write(request.method);
+    randomlyAddCookie(response);
+    if (await randomlyRedirect(server, response)) {
+      // Redirect calls close() on the response.
+      return;
+    }
+    // Randomly delay response.
+    await Future.delayed(
+        Duration(milliseconds: rng.nextInt(maxResponseDelayMs)));
+    response.close();
+  });
+  return server;
+}
+
+Future<void> testMain() async {
+  // Ensure there's a chance some requests will be interrupted.
+  Expect.isTrue(maxRequestDelayMs > serverShutdownDelayMs);
+  Expect.isTrue(maxResponseDelayMs < serverShutdownDelayMs);
+
+  final server = await startServer();
+  HttpClient.enableTimelineLogging = true;
+  final client = HttpClient();
+  final requests = <Future>[];
+  final address =
+      Uri(scheme: 'http', host: server.address.host, port: server.port);
+
+  // HTTP DELETE
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.deleteUrl(randomlyAddRequestParams(address));
+      final string = 'DELETE $address';
+      r.headers.add(HttpHeaders.contentLengthHeader, string.length);
+      r.write(string);
+      final response = await r.close();
+      response.listen((_) {});
+    });
+    requests.add(future);
+  }
+
+  // HTTP GET
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.getUrl(randomlyAddRequestParams(address));
+      final response = await r.close();
+      await response.drain();
+    });
+    requests.add(future);
+  }
+  // HTTP HEAD
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.headUrl(randomlyAddRequestParams(address));
+      await r.close();
+    });
+    requests.add(future);
+  }
+
+  // HTTP CONNECT
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r =
+          await client.openUrl('connect', randomlyAddRequestParams(address));
+      await r.close();
+    });
+    requests.add(future);
+  }
+
+  // HTTP PATCH
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.patchUrl(randomlyAddRequestParams(address));
+      final response = await r.close();
+      response.listen(null);
+    });
+    requests.add(future);
+  }
+
+  // HTTP POST
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.postUrl(randomlyAddRequestParams(address));
+      r.add(Uint8List.fromList([0, 1, 2]));
+      await r.close();
+    });
+    requests.add(future);
+  }
+
+  // HTTP PUT
+  for (int i = 0; i < 10; ++i) {
+    final future = executeWithRandomDelay(() async {
+      final r = await client.putUrl(randomlyAddRequestParams(address));
+      await r.close();
+    });
+    requests.add(future);
+  }
+
+  // Purposefully close server before some connections can be made to ensure
+  // that refused / interrupted connections correctly create finish timeline
+  // events.
+  await Future.delayed(Duration(milliseconds: serverShutdownDelayMs));
+  await server.close();
+
+  // Ensure all requests complete before finishing.
+  await Future.wait(requests);
+}
+
+bool isStartEvent(Map event) => (event['ph'] == 'b');
+bool isFinishEvent(Map event) => (event['ph'] == 'e');
+
+bool hasCompletedEvents(List traceEvents) {
+  final events = <String, int>{};
+  for (final event in traceEvents) {
+    final id = event['id'];
+    events.putIfAbsent(id, () => 0);
+    if (isStartEvent(event)) {
+      events[id]++;
+    } else if (isFinishEvent(event)) {
+      events[id]--;
+    }
+  }
+  bool valid = true;
+  events.forEach((id, count) {
+    if (count != 0) {
+      valid = false;
+    }
+  });
+  return valid;
+}
+
+List filterEventsByName(List traceEvents, String name) =>
+    traceEvents.where((e) => e['name'].contains(name)).toList();
+
+List filterEventsByIdAndName(List traceEvents, String id, String name) =>
+    traceEvents
+        .where((e) => e['id'] == id && e['name'].contains(name))
+        .toList();
+
+void hasValidHttpConnections(List traceEvents) {
+  final events = filterEventsByName(traceEvents, 'HTTP Connection');
+  expect(hasCompletedEvents(events), isTrue);
+}
+
+void validateHttpStartEvent(Map event, String method) {
+  expect(event.containsKey('args'), isTrue);
+  final args = event['args'];
+  expect(args.containsKey('method'), isTrue);
+  expect(args['method'], method);
+  expect(args['filterKey'], 'HTTP/client');
+  expect(args.containsKey('uri'), isTrue);
+}
+
+void validateHttpFinishEvent(Map event) {
+  expect(event.containsKey('args'), isTrue);
+  final args = event['args'];
+  expect(args['filterKey'], 'HTTP/client');
+  if (!args.containsKey('error')) {
+    expect(args.containsKey('requestHeaders'), isTrue);
+    expect(args['requestHeaders'] != null, isTrue);
+    expect(args.containsKey('compressionState'), isTrue);
+    expect(args.containsKey('connectionInfo'), isTrue);
+    expect(args.containsKey('contentLength'), isTrue);
+    expect(args.containsKey('cookies'), isTrue);
+    expect(args.containsKey('responseHeaders'), isTrue);
+    expect(args.containsKey('isRedirect'), isTrue);
+    expect(args.containsKey('persistentConnection'), isTrue);
+    expect(args.containsKey('reasonPhrase'), isTrue);
+    expect(args.containsKey('redirects'), isTrue);
+    expect(args.containsKey('statusCode'), isTrue);
+    // If proxyInfo is non-null, uri and port _must_ be non-null.
+    if (args.containsKey('proxyInfo')) {
+      final proxyInfo = args['proxyInfo'];
+      expect(proxyInfo.containsKey('uri'), isTrue);
+      expect(proxyInfo.containsKey('port'), isTrue);
+    }
+  }
+}
+
+void hasValidHttpRequests(List traceEvents, String method) {
+  var events = filterEventsByName(traceEvents, 'HTTP CLIENT $method');
+  for (final event in events) {
+    if (isStartEvent(event)) {
+      validateHttpStartEvent(event, method);
+      // Check body of request has been sent and recorded correctly.
+      if (method == 'DELETE' || method == 'POST') {
+        final id = event['id'];
+        final bodyEvent =
+            filterEventsByIdAndName(traceEvents, id, 'Request body');
+        // Due to randomness, it doesn't guarantee to have the timeline events.
+        if (bodyEvent.length == 1) {
+          if (method == 'POST') {
+            // add() was used
+            Expect.listEquals(
+                <int>[0, 1, 2], bodyEvent[0]['args']['encodedData']);
+          } else {
+            // write() was used.
+            Expect.isTrue(
+                bodyEvent[0]['args']['data'].startsWith('$method http'));
+          }
+        }
+      }
+    } else if (isFinishEvent(event)) {
+      validateHttpFinishEvent(event);
+    } else {
+      fail('unexpected event type: ${event["ph"]}');
+    }
+  }
+
+  // Check response body matches string stored in the map.
+  events = filterEventsByName(traceEvents, 'HTTP CLIENT response of $method');
+  if (method == 'DELETE') {
+    // It called listen().
+    expect(hasCompletedEvents(events), isTrue);
+  }
+  for (final event in events) {
+    // Each response will be associated with a request.
+    if (isFinishEvent(event)) {
+      continue;
+    }
+    final id = event['id'];
+    final data = filterEventsByIdAndName(traceEvents, id, 'Response body');
+    if (data.length != 0) {
+      Expect.equals(1, data.length);
+      Expect.listEquals(utf8.encode(method), data[0]['args']['data']);
+    }
+  }
+}
+
+void hasValidHttpCONNECTs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'CONNECT');
+void hasValidHttpDELETEs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'DELETE');
+void hasValidHttpGETs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'GET');
+void hasValidHttpHEADs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'HEAD');
+void hasValidHttpPATCHs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'PATCH');
+void hasValidHttpPOSTs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'POST');
+void hasValidHttpPUTs(List traceEvents) =>
+    hasValidHttpRequests(traceEvents, 'PUT');
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    final result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], 'Timeline');
+    expect(result.containsKey('traceEvents'), isTrue);
+    final traceEvents = result['traceEvents'];
+    expect(traceEvents.length > 0, isTrue);
+    hasValidHttpConnections(traceEvents);
+    hasValidHttpCONNECTs(traceEvents);
+    hasValidHttpDELETEs(traceEvents);
+    hasValidHttpGETs(traceEvents);
+    hasValidHttpHEADs(traceEvents);
+    hasValidHttpPATCHs(traceEvents);
+    hasValidHttpPOSTs(traceEvents);
+    hasValidHttpPUTs(traceEvents);
+  },
+];
+
+main(args) async => runIsolateTests(args, tests, testeeBefore: testMain);
diff --git a/runtime/observatory_2/tests/service_2/vm_service_dds_test.dart b/runtime/observatory_2/tests/service_2/vm_service_dds_test.dart
new file mode 100644
index 0000000..d309fd8
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/vm_service_dds_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:dds/dds.dart';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'test_helper.dart';
+
+final tests = <DDSTest>[
+  (VM vm, DartDevelopmentService dds) async {
+    final client = WebSocketVM(
+      WebSocketVMTarget(
+        dds.wsUri.toString(),
+      ),
+    );
+    final result = await client.invokeRpcNoUpgrade('getSupportedProtocols', {});
+    final protocols = result['protocols'];
+    expect(protocols.length, 2);
+    bool supportsVmProtocol = false;
+    bool supportsDdsProtocol = false;
+    for (final protocol in protocols) {
+      if (protocol['protocolName'] == 'VM Service') {
+        supportsVmProtocol = true;
+      } else if (protocol['protocolName'] == 'DDS') {
+        supportsDdsProtocol = true;
+      }
+    }
+    expect(supportsVmProtocol, true);
+    expect(supportsDdsProtocol, true);
+  }
+];
+
+main(args) async => runDDSTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/vm_test.dart b/runtime/observatory_2/tests/service_2/vm_test.dart
new file mode 100644
index 0000000..ef69f35
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/vm_test.dart
@@ -0,0 +1,25 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+var tests = <IsolateTest>[
+  (Isolate isolate) {
+    VM vm = isolate.owner;
+    expect(vm.targetCPU, isNotNull);
+    expect(vm.architectureBits == 32 || vm.architectureBits == 64, isTrue);
+    expect(vm.embedder, equals("Dart VM"));
+    expect(vm.currentMemory, isNotNull);
+    expect(vm.currentMemory, greaterThan(0));
+    expect(vm.currentRSS, isNotNull);
+    expect(vm.currentRSS, greaterThan(0));
+    expect(vm.maxRSS, isNotNull);
+    expect(vm.maxRSS, greaterThan(0));
+    expect(vm.maxRSS, greaterThanOrEqualTo(vm.currentRSS));
+  },
+];
+
+main(args) => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/tests/service_2/vm_timeline_events_test.dart b/runtime/observatory_2/tests/service_2/vm_timeline_events_test.dart
new file mode 100644
index 0000000..bd6a9ed
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/vm_timeline_events_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+primeDartTimeline() async {
+  while (true) {
+    Timeline.startSync('apple');
+    Timeline.finishSync();
+    // Give the VM a chance to send the timeline events. This test is
+    // significantly slower if we loop without yielding control after each
+    // iteration.
+    await Future.delayed(const Duration(milliseconds: 1));
+  }
+}
+
+bool isDart(event) => event['cat'] == 'Dart';
+
+List filterEvents(List events, filter) {
+  return events.where(filter).toList();
+}
+
+Completer completer;
+int eventCount;
+
+onTimelineEvent(ServiceEvent event) {
+  if (event.kind != ServiceEvent.kTimelineEvents) {
+    return;
+  }
+  eventCount++;
+  expect(filterEvents(event.timelineEvents, isDart).length, greaterThan(0));
+  if (eventCount == 5) {
+    completer.complete(eventCount);
+  }
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    // Clear global state.
+    eventCount = 0;
+    completer = Completer<void>();
+  },
+  (Isolate isolate) async {
+    // Subscribe to the Timeline stream.
+    await subscribeToStream(isolate.vm, VM.kTimelineStream, onTimelineEvent);
+  },
+  (Isolate isolate) async {
+    // Ensure we don't get any events before enabling Dart.
+    await new Future.delayed(new Duration(seconds: 5));
+    expect(eventCount, 0);
+  },
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that 'Dart' is available.
+    expect(flags['availableStreams'].contains('Dart'), isTrue);
+    // Confirm that nothing is being recorded.
+    expect(flags['recordedStreams'].length, equals(0));
+  },
+  (Isolate isolate) async {
+    // Enable the Dart category.
+    await isolate.vm.invokeRpcNoUpgrade('setVMTimelineFlags', {
+      "recordedStreams": ["Dart"]
+    });
+  },
+  (Isolate isolate) async {
+    // Wait to receive events.
+    await completer.future;
+    cancelStreamSubscription(VM.kTimelineStream);
+  },
+];
+
+main(args) async =>
+    runIsolateTests(args, tests, testeeConcurrent: primeDartTimeline);
diff --git a/runtime/observatory_2/tests/service_2/vm_timeline_flags_test.dart b/runtime/observatory_2/tests/service_2/vm_timeline_flags_test.dart
new file mode 100644
index 0000000..71a5534
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/vm_timeline_flags_test.dart
@@ -0,0 +1,131 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+primeDartTimeline() {
+  while (true) {
+    Timeline.startSync('apple');
+    Timeline.finishSync();
+    debugger();
+  }
+}
+
+bool isDart(event) => event['cat'] == 'Dart';
+bool isMetaData(event) => event['ph'] == 'M';
+bool isNotMetaData(event) => !isMetaData(event);
+bool isNotDartAndMetaData(event) => !isDart(event) && !isMetaData(event);
+
+List filterEvents(List events, filter) {
+  return events.where(filter).toList();
+}
+
+int dartEventCount;
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that 'Dart' is available.
+    expect(flags['availableStreams'].contains('Dart'), isTrue);
+    // Confirm that nothing is being recorded.
+    expect(flags['recordedStreams'].length, equals(0));
+  },
+  (Isolate isolate) async {
+    // Get the timeline.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], equals('Timeline'));
+    expect(result['traceEvents'], isA<List>());
+    // Confirm that it as no non-meta data events.
+    expect(filterEvents(result['traceEvents'], isNotMetaData).length, 0);
+  },
+  (Isolate isolate) async {
+    final completer = Completer<void>();
+    await subscribeToStream(isolate.vm, 'Timeline', (event) async {
+      expect(event.kind, ServiceEvent.kTimelineStreamSubscriptionsUpdate);
+      expect(event.updatedStreams.length, 1);
+      expect(event.updatedStreams.first, 'Dart');
+      await cancelStreamSubscription('Timeline');
+      completer.complete();
+    });
+    // Enable the Dart category.
+    await isolate.vm.invokeRpcNoUpgrade('setVMTimelineFlags', {
+      "recordedStreams": ["Dart"]
+    });
+    await completer.future;
+  },
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that only Dart is being recorded.
+    expect(flags['recordedStreams'].length, equals(1));
+    expect(flags['recordedStreams'].contains('Dart'), isTrue);
+    print(flags);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Get the timeline.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], equals('Timeline'));
+    expect(result['traceEvents'], isA<List>());
+    print(result['traceEvents']);
+    // Confirm that Dart events are added.
+    expect(filterEvents(result['traceEvents'], isDart).length, greaterThan(0));
+    // Confirm that zero non-Dart events are added.
+    expect(filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+        equals(0));
+  },
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    final completer = Completer<void>();
+    await subscribeToStream(isolate.vm, 'Timeline', (event) async {
+      expect(event.kind, ServiceEvent.kTimelineStreamSubscriptionsUpdate);
+      expect(event.updatedStreams.length, 0);
+      await cancelStreamSubscription('Timeline');
+      completer.complete();
+    });
+
+    // Disable the Dart category.
+    await isolate.vm
+        .invokeRpcNoUpgrade('setVMTimelineFlags', {"recordedStreams": []});
+    // Grab the timeline and remember the number of Dart events.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], equals('Timeline'));
+    expect(result['traceEvents'], isA<List>());
+    dartEventCount = filterEvents(result['traceEvents'], isDart).length;
+
+    await completer.future;
+  },
+  (Isolate isolate) async {
+    // Get the flags.
+    Map flags = await isolate.vm.invokeRpcNoUpgrade('getVMTimelineFlags', {});
+    expect(flags['type'], 'TimelineFlags');
+    // Confirm that 'Dart' is not being recorded.
+    expect(flags['recordedStreams'].length, equals(0));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    // Grab the timeline and verify that we haven't added any new Dart events.
+    Map result = await isolate.vm.invokeRpcNoUpgrade('getVMTimeline', {});
+    expect(result['type'], equals('Timeline'));
+    expect(result['traceEvents'], isA<List>());
+    expect(filterEvents(result['traceEvents'], isDart).length, dartEventCount);
+    // Confirm that zero non-Dart events are added.
+    expect(filterEvents(result['traceEvents'], isNotDartAndMetaData).length,
+        equals(0));
+  },
+];
+
+main(args) async =>
+    runIsolateTests(args, tests, testeeConcurrent: primeDartTimeline);
diff --git a/runtime/observatory_2/tests/service_2/weak_properties_test.dart b/runtime/observatory_2/tests/service_2/weak_properties_test.dart
new file mode 100644
index 0000000..f12387a
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/weak_properties_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm_references_test;
+
+import 'dart:mirrors';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'test_helper.dart';
+
+class Foo {}
+
+class Bar {}
+
+var expando;
+var key;
+var value;
+var weak_property;
+
+void script() {
+  expando = new Expando('some debug name');
+  key = new Foo();
+  value = new Bar();
+  expando[key] = value;
+
+  InstanceMirror expandoMirror = reflect(expando);
+  LibraryMirror libcore = expandoMirror.type.owner;
+
+  var entries = expandoMirror
+      .getField(MirrorSystem.getSymbol('_data', libcore))
+      .reflectee;
+  weak_property = entries.singleWhere((e) => e != null);
+  print(weak_property);
+}
+
+var tests = <IsolateTest>[
+  (Isolate isolate) async {
+    Library lib = await isolate.rootLibrary.load();
+    Field keyField = lib.variables.singleWhere((v) => v.name == 'key');
+    await keyField.load();
+    Instance key = keyField.staticValue;
+    Field valueField = lib.variables.singleWhere((v) => v.name == 'value');
+    await valueField.load();
+    Instance value = valueField.staticValue;
+    Field propField =
+        lib.variables.singleWhere((v) => v.name == 'weak_property');
+    await propField.load();
+    Instance prop = propField.staticValue;
+
+    expect(key.isWeakProperty, isFalse);
+    expect(value.isWeakProperty, isFalse);
+    expect(prop.isWeakProperty, isTrue);
+    expect(prop.key, isNull);
+    expect(prop.value, isNull);
+    Instance loadedProp = await prop.load();
+    // Object ids are not canonicalized, so we rely on the key and value
+    // being the sole instances of their classes to test we got the objects
+    // we expect.
+    expect(loadedProp.key, isNotNull);
+    expect(loadedProp.key.clazz, equals(key.clazz));
+    expect(loadedProp.value, isNotNull);
+    expect(loadedProp.value.clazz, equals(value.clazz));
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeBefore: script);
diff --git a/runtime/observatory_2/tests/service_2/yield_positions_with_finally_test.dart b/runtime/observatory_2/tests/service_2/yield_positions_with_finally_test.dart
new file mode 100644
index 0000000..47d4c38
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/yield_positions_with_finally_test.dart
@@ -0,0 +1,212 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+import 'dart:developer';
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE = 106;
+const int LINE_A = 23;
+const int LINE_B = 36;
+const int LINE_C = 47;
+const int LINE_D = 61;
+const int LINE_E = 78;
+const int LINE_F = 93;
+
+// break statement
+Stream<int> testBreak() async* {
+  for (int t = 0; t < 10; t++) {
+    try {
+      if (t == 1) break;
+      await throwException(); // LINE_A
+    } catch (e) {} finally {
+      yield t;
+    }
+  }
+}
+
+// return statement
+Stream<int> testReturn() async* {
+  for (int t = 0; t < 10; t++) {
+    try {
+      yield t;
+      if (t == 1) return;
+      await throwException(); // LINE_B
+    } catch (e) {} finally {
+      yield t;
+    }
+  }
+}
+
+// Multiple functions
+Stream<int> testMultipleFunctions() async* {
+  try {
+    yield 0;
+    await throwException(); // LINE_C
+  } catch (e) {} finally {
+    yield 1;
+  }
+}
+
+// continue statement
+Stream<int> testContinueSwitch() async* {
+  int currentState = 0;
+  switch (currentState) {
+    case 0:
+      {
+        try {
+          if (currentState == 1) continue label;
+          await throwException(); // LINE_D
+        } catch (e) {} finally {
+          yield 0;
+        }
+        yield 1;
+        break;
+      }
+    label:
+    case 1:
+      break;
+  }
+}
+
+Stream<int> testNestFinally() async* {
+  int i = 0;
+  try {
+    if (i == 1) return;
+    await throwException(); //LINE_E
+  } catch (e) {} finally {
+    try {
+      yield i;
+    } finally {
+      yield 1;
+    }
+    yield 1;
+  }
+}
+
+Stream<int> testAsyncClosureInFinally() async* {
+  int i = 0;
+  try {
+    if (i == 1) return;
+    await throwException(); //LINE_F
+  } catch (e) {} finally {
+    inner() async {
+      await Future.delayed(Duration(milliseconds: 10));
+    }
+
+    await inner;
+    yield 1;
+  }
+}
+
+Future<void> throwException() async {
+  await Future.delayed(Duration(milliseconds: 10));
+  throw new Exception(""); // LINE
+}
+
+code() async {
+  await for (var x in testBreak()) {}
+  await for (var x in testReturn()) {}
+  await for (var x in testMultipleFunctions()) {}
+  await for (var x in testContinueSwitch()) {}
+  await for (var x in testNestFinally()) {}
+  await for (var x in testAsyncClosureInFinally()) {}
+}
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  setBreakpointAtLine(LINE),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_A));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test return statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_B));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_C));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test break statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_D));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test nested finally statement
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_E));
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE),
+  (Isolate isolate) async {
+    // test async closure within finally block
+    ServiceMap stack = await isolate.getStack();
+    expect(stack['awaiterFrames'], isNotNull);
+    expect(stack['awaiterFrames'].length, greaterThanOrEqualTo(2));
+
+    // Check second top frame contains correct line number
+    Script script = stack['awaiterFrames'][1].location.script;
+    expect(script.tokenToLine(stack['awaiterFrames'][1].location.tokenPos),
+        equals(LINE_F));
+  },
+  resumeIsolate,
+  hasStoppedAtExit
+];
+
+main(args) {
+  runIsolateTestsSynchronous(args, tests,
+      testeeConcurrent: code, pause_on_start: true, pause_on_exit: true);
+}
diff --git a/runtime/observatory_2/tests/ui/inspector.dart b/runtime/observatory_2/tests/ui/inspector.dart
new file mode 100644
index 0000000..7849381
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/inspector.dart
@@ -0,0 +1,272 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See inspector.txt for expected behavior.
+
+library manual_inspector_test;
+
+import 'dart:isolate';
+import 'dart:mirrors';
+import 'dart:developer';
+import 'dart:typed_data';
+
+part 'inspector_part.dart';
+
+var libraryField;
+var node;
+var uninitialized = new Object();
+
+extractPrivateField(obj, name) {
+  return reflect(obj)
+      .getField(MirrorSystem.getSymbol(name, reflect(obj).type.owner))
+      .reflectee;
+}
+
+class A<T> {}
+
+class B<S extends num> {}
+
+class S {}
+
+class M {}
+
+class MA extends S with M {}
+
+class Node {
+  static var classField;
+
+  var nullable;
+  var mixedType;
+  var array;
+  var bigint;
+  var blockClean;
+  var blockCopying;
+  var blockFull;
+  var blockFullWithChain;
+  var boundedType;
+  var capability;
+  var counter;
+  var expando;
+  var float32x4;
+  var float64;
+  var float64x2;
+  var gauge;
+  var growableList;
+  var int32x4;
+  var isolate;
+  var map;
+  var mint;
+  var mirrorClass;
+  var mirrorClosure;
+  var mirrorInstance;
+  var mirrorReference;
+  var portReceive;
+  var portSend;
+  var regex;
+  var smi;
+  var stacktrace;
+  var string;
+  var stringLatin1;
+  var stringSnowflake;
+  var stringUnicode;
+  var stringHebrew;
+  var stringTrebleClef;
+  var theFalse;
+  var theNull;
+  var theTrue;
+  var type;
+  var typeParameter;
+  var typedData;
+  var userTag;
+  var weakProperty;
+
+  genStackTrace() {
+    try {
+      num.parse(',');
+    } catch (e, s) {
+      return s;
+    }
+  }
+
+  genCleanBlock() {
+    block(x) => x;
+    return block;
+  }
+
+  genCopyingBlock() {
+    final x = 'I could be copied down';
+    block() => x;
+    return block;
+  }
+
+  genFullBlock() {
+    var x = 0;
+    block() => x++;
+    return block;
+  }
+
+  genFullBlockWithChain() {
+    var x = 0;
+    outer() {
+      var y = 0;
+      block() => x++ + y++;
+      return block;
+    }
+
+    return outer;
+  }
+
+  f(int x) {
+    ++x;
+    return x;
+  }
+
+  static staticMain() {
+    node.main();
+  }
+
+  main() {
+    print("Started main");
+
+    f(9);
+
+    nullable = 1;
+    nullable = null;
+    nullable = 1;
+    mixedType = 1;
+    mixedType = "2";
+    mixedType = false;
+
+    array = new List(3);
+    array[0] = 1;
+    array[1] = 2;
+    array[2] = 3;
+    bigint = 1 << 65;
+    blockClean = genCleanBlock();
+    blockCopying = genCopyingBlock();
+    blockFull = genFullBlock();
+    blockFullWithChain = genFullBlockWithChain();
+    boundedType = extractPrivateField(
+        reflect(new B<int>()).type.typeVariables.single, '_reflectee');
+    counter = new Counter("CounterName", "Counter description");
+    expando = new Expando("expando-name");
+    expando[array] = 'The weakly associated value';
+    float32x4 = new Float32x4(0.0, -1.0, 3.14, 2e28);
+    float64 = 3.14;
+    float64x2 = new Float64x2(0.0, 3.14);
+    gauge = new Gauge("GaugeName", "Gauge description", 0.0, 100.0);
+    growableList = new List();
+    int32x4 = new Int32x4(0, 1, 10, 11);
+    map = {
+      "x-key": "x-value",
+      "y-key": "y-value",
+      "removed-key": "removed-value"
+    };
+    map.remove("removed-key");
+    mint = 1 << 32;
+    mirrorClass = reflectClass(Object);
+    mirrorClosure = reflect(blockFull);
+    mirrorInstance = reflect("a reflectee");
+    mirrorReference = extractPrivateField(mirrorClass, '_reflectee');
+    portReceive = new RawReceivePort();
+    portSend = portReceive.sendPort;
+    regex = new RegExp("a*b+c");
+    smi = 7;
+    stacktrace = genStackTrace();
+    string = "Hello $smi ${smi.runtimeType}";
+    stringLatin1 = "blåbærgrød";
+    stringSnowflake = "❄";
+    stringUnicode = "Îñţérñåţîöñåļîžåţîờñ";
+    stringHebrew = "שלום רב שובך צפורה נחמדת"; // An example of Right-to-Left.
+    stringTrebleClef = "𝄞"; // An example of a surrogate pair.
+    theFalse = false;
+    theNull = null;
+    theTrue = true;
+    type = String;
+    typeParameter =
+        extractPrivateField(reflectClass(A).typeVariables.single, '_reflectee');
+    typedData = extractPrivateField(new ByteData(64), '_typedData');
+    userTag = new UserTag("Example tag name");
+    weakProperty =
+        extractPrivateField(expando, '_data').firstWhere((e) => e != null);
+
+    Isolate.spawn(secondMain, "Hello2").then((otherIsolate) {
+      isolate = otherIsolate;
+      portSend = otherIsolate.controlPort;
+      capability = otherIsolate.terminateCapability;
+    });
+    Isolate.spawn(secondMain, "Hello3").then((otherIsolate) {
+      isolate = otherIsolate;
+      portSend = otherIsolate.controlPort;
+      capability = otherIsolate.terminateCapability;
+    });
+
+    print("Finished main");
+    busy();
+  }
+
+  busy() {
+    var localVar = 0;
+    while (true) {
+      localVar = (localVar + 1) & 0xFFFF;
+    }
+  }
+}
+
+secondMain(msg) {
+  print("Hello from second isolate");
+}
+
+var typed;
+
+class Typed {
+  var float32List = new Float32List(16);
+  var float64List = new Float64List(16);
+
+  var int32x4 = new Int32x4(1, 2, 3, 4);
+  var float32x4 = new Float32x4.zero();
+  var float64x2 = new Float64x2.zero();
+  var int32x4List = new Int32x4List(16);
+  var float32x4List = new Float32x4List(16);
+  var float64x2List = new Float64x2List(16);
+
+  var int8List = new Int8List(8);
+  var int16List = new Int16List(8);
+  var int32List = new Int32List(8);
+  var int64List = new Int64List(8);
+  var uint8List = new Uint8List(8);
+  var uint16List = new Uint16List(8);
+  var uint32List = new Uint32List(8);
+  var uint64List = new Uint64List(8);
+  var uint8ClampedList = new Uint8ClampedList(8);
+
+  var byteBuffer = new Uint8List(8).buffer;
+  var byteBuffer2 = new Float32List(8).buffer;
+
+  var byteData = new ByteData(8);
+
+  Typed() {
+    float32List[0] = 3.14;
+    int8List[0] = 5;
+  }
+
+  Typed._named() {
+    float32List[0] = 3.14;
+    int8List[0] = 5;
+  }
+}
+
+main() {
+  libraryField = 'Library field value';
+  Node.classField = 'Class field value';
+  typed = new Typed();
+  node = new Node();
+  Node.staticMain();
+}
+
+class C {
+  static doPrint() {
+    print("Original");
+  }
+}
diff --git a/runtime/observatory_2/tests/ui/inspector.txt b/runtime/observatory_2/tests/ui/inspector.txt
new file mode 100644
index 0000000..0f99c300
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/inspector.txt
@@ -0,0 +1,5 @@
+0. Run dart --observe inspector.dart
+1. Visit isolate 'root'
+2. Visit library manual_inspector_test
+3. Expand 'variables'
+4. Each should display a reasonable value, not a blank nor an 'Unknown service ref'
diff --git a/runtime/observatory_2/tests/ui/inspector_part.dart b/runtime/observatory_2/tests/ui/inspector_part.dart
new file mode 100644
index 0000000..06589e3
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/inspector_part.dart
@@ -0,0 +1,17 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+part of manual_inspector_test;
+
+functionInPart() {}
+
+set explicitSetter(x) {}
+
+get explicitGetter {}
+
+class D {
+  set explicitSetter(x) {}
+
+  get explicitGetter {}
+}
diff --git a/runtime/observatory_2/tests/ui/log.dart b/runtime/observatory_2/tests/ui/log.dart
new file mode 100644
index 0000000..aaebbe2
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/log.dart
@@ -0,0 +1,27 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:developer' as developer;
+import 'package:logging/logging.dart';
+
+main() {
+  Logger.root.level = Level.ALL;
+  Logger.root.onRecord.listen((logRecord) {
+    developer.log(logRecord.message,
+        time: logRecord.time,
+        sequenceNumber: logRecord.sequenceNumber,
+        level: logRecord.level.value,
+        name: logRecord.loggerName,
+        zone: null,
+        error: logRecord.error,
+        stackTrace: logRecord.stackTrace);
+  });
+  new Timer.periodic(new Duration(seconds: 1), (t) {
+    Logger.root.info('INFO MESSAGE');
+  });
+  new Timer.periodic(new Duration(seconds: 1), (t) {
+    Logger.root.fine('FINE MESSAGE');
+  });
+}
diff --git a/runtime/observatory_2/tests/ui/log.txt b/runtime/observatory_2/tests/ui/log.txt
new file mode 100644
index 0000000..0f64917
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/log.txt
@@ -0,0 +1,6 @@
+0. Run dart --observe log.dart
+1. Visit main isolate's logging page.
+2. You should see 'INFO MESSAGE' and 'FINE MESSAGE'.
+3. Adjust the level to be 'INFO' and see that 'FINE' messages are hidden.
+4. Adjust the level to be 'FINE' and see that all messages are displayed.
+5. Adjust the level to be 'SHOUT' and see that no messages are displayed.
diff --git a/runtime/observatory_2/tests/ui/retainingPath.dart b/runtime/observatory_2/tests/ui/retainingPath.dart
new file mode 100644
index 0000000..0a2c30f
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/retainingPath.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// See reatiningPath.txt for expected behavior.
+
+class Foo {
+  var a;
+  var b;
+  Foo(this.a, this.b);
+}
+
+main() {
+  var list = new List<Foo>.filled(10, null);
+  list[5] = new Foo(42.toString(), new Foo(87.toString(), 17.toString()));
+  while (true) {}
+}
diff --git a/runtime/observatory_2/tests/ui/retainingPath.txt b/runtime/observatory_2/tests/ui/retainingPath.txt
new file mode 100644
index 0000000..e4666a8
--- /dev/null
+++ b/runtime/observatory_2/tests/ui/retainingPath.txt
@@ -0,0 +1,18 @@
+0.
+dart --observe retainingPath.dart
+1.
+isolate 'root'
+2.
+library 'retainingPath.dart'
+3.
+class 'Foo'
+4.
+under 'instances', find 'strongly reachable' list; it should contain 2 elements, one of which should have a field containing "87"
+5.
+instance "87"
+6.
+find 'retaining path'; it should have length 4, and be annotated as follows:
+ "87" in var a
+ Foo in var b
+ Foo at list index 5 of
+ _List(10)
diff --git a/runtime/observatory_2/tool/ensure_dartfmt.sh b/runtime/observatory_2/tool/ensure_dartfmt.sh
new file mode 100755
index 0000000..6aa50e9
--- /dev/null
+++ b/runtime/observatory_2/tool/ensure_dartfmt.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+dart_files=$(find lib web -name "*.dart")
+[ -z "$dart_files" ] && exit 0
+
+unformatted=$(dartfmt -n $dart_files)
+[ -z "$unformatted" ] && exit 0
+
+# Some files are not dartfmt'd. Print message and fail.
+echo >&2 "dart files must be formatted with dartfmt. Please run:"
+for fn in $unformatted; do
+  echo >&2 "  dartfmt -w $PWD/$fn"
+done
+
+exit 1
diff --git a/runtime/observatory_2/update_sources.py b/runtime/observatory_2/update_sources.py
new file mode 100755
index 0000000..39f6ad3
--- /dev/null
+++ b/runtime/observatory_2/update_sources.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Updates the list of Observatory source files.
+
+import os
+import sys
+from datetime import date
+
+
+def getDir(rootdir, target):
+    sources = []
+    for root, subdirs, files in os.walk(rootdir):
+        subdirs.sort()
+        files.sort()
+        for f in files:
+            sources.append(root + '/' + f)
+    return sources
+
+
+HEADER = """# Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# DO NOT EDIT. This file is generated by update_sources.py in this directory.
+
+# This file contains all dart, css, and html sources for Observatory.
+"""
+
+
+def main():
+    with open('observatory_sources.gni', 'w') as target:
+        target.write(HEADER)
+        target.write('observatory_sources = [\n')
+        sources = []
+        for rootdir in ['lib', 'web']:
+            sources.extend(getDir(rootdir, target))
+        sources.sort()
+        for s in sources:
+            if (s[-9:] != 'README.md'):
+                target.write('  "' + s + '",\n')
+        target.write(']\n')
+
+
+if __name__ == "__main__":
+    main()
diff --git a/runtime/observatory_2/web/favicon.ico b/runtime/observatory_2/web/favicon.ico
new file mode 100644
index 0000000..c861395
--- /dev/null
+++ b/runtime/observatory_2/web/favicon.ico
Binary files differ
diff --git a/runtime/observatory_2/web/index.html b/runtime/observatory_2/web/index.html
new file mode 100644
index 0000000..161e866
--- /dev/null
+++ b/runtime/observatory_2/web/index.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html style="height: 100%">
+<head>
+  <meta charset="utf-8">
+  <title>Dart VM Observatory</title>
+  <link rel="stylesheet" href="packages/observatory/src/elements/css/shared.css">
+  <script defer src="main.dart.js"></script>
+</head>
+<body style="height: 100%">
+</body>
+</html>
diff --git a/runtime/observatory_2/web/main.dart b/runtime/observatory_2/web/main.dart
new file mode 100644
index 0000000..72e2190
--- /dev/null
+++ b/runtime/observatory_2/web/main.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:html';
+import 'package:logging/logging.dart';
+import 'package:observatory_2/elements.dart';
+import 'package:stack_trace/stack_trace.dart';
+
+main() async {
+  Chain.capture(() async {
+    Logger.root.level = Level.INFO;
+    Logger.root.onRecord.listen((LogRecord rec) {
+      print('${rec.level.name}: ${rec.time}: ${rec.message}');
+    });
+    Logger.root.info('Starting Observatory');
+    document.body.children
+        .insert(0, new ObservatoryApplicationElement.created().element);
+  });
+}
diff --git a/runtime/observatory_2/web/third_party/README.md b/runtime/observatory_2/web/third_party/README.md
new file mode 100644
index 0000000..ba94574
--- /dev/null
+++ b/runtime/observatory_2/web/third_party/README.md
@@ -0,0 +1,4 @@
+This directory contains a vulcanized version of trace-viewer:
+
+https://github.com/catapult-project/catapult/wiki/Embedding-Trace-Viewer
+
diff --git a/runtime/observatory_2/web/third_party/trace_viewer_full.html b/runtime/observatory_2/web/third_party/trace_viewer_full.html
new file mode 100644
index 0000000..d815ec5
--- /dev/null
+++ b/runtime/observatory_2/web/third_party/trace_viewer_full.html
@@ -0,0 +1,10442 @@
+<!DOCTYPE html>
+<html>
+  <head i18n-values="dir:textdirection;">
+  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+  <meta http-equiv="origin-trial" content="AnYuQDtUf6OrWCmR9Okd67JhWVTbmnRedvPi1TEvAxac8+1p6o9q08FoDO6oCbLD0xEqev+SkZFiIhFSzlY9HgUAAABxeyJvcmlnaW4iOiJodHRwczovL2dvb2dsZXVzZXJjb250ZW50LmNvbTo0NDMiLCJmZWF0dXJlIjoiV2ViQ29tcG9uZW50c1YwIiwiZXhwaXJ5IjoxNjA0NjE0NTM4LCJpc1N1YmRvbWFpbiI6dHJ1ZX0=">
+  <meta http-equiv="origin-trial" content="AkFXw3wHnOs/XXYqFXpc3diDLrRFd9PTgGs/gs43haZmngI/u1g8L4bDnSKLZkB6fecjmjTwcAMQFCpWMAoHSQEAAAB8eyJvcmlnaW4iOiJodHRwczovL2Nocm9taXVtLWJ1aWxkLXN0YXRzLmFwcHNwb3QuY29tOjQ0MyIsImZlYXR1cmUiOiJXZWJDb21wb25lbnRzVjAiLCJleHBpcnkiOjE2MTIyMjM5OTksImlzU3ViZG9tYWluIjp0cnVlfQ==">
+  <meta http-equiv="origin-trial" content="AtQY4wpX9+nj+Vn27cTgygzIPbtB2WoAoMQR5jK9mCm/H2gRIDH6MmGVAaziv9XnYTDKjhBnQYtecbTiIHCQiAIAAACEeyJvcmlnaW4iOiJodHRwczovL2Nocm9taXVtLWJ1aWxkLXN0YXRzLXN0YWdpbmcuYXBwc3BvdC5jb206NDQzIiwiZmVhdHVyZSI6IldlYkNvbXBvbmVudHNWMCIsImV4cGlyeSI6MTYxMjIyMzk5OSwiaXNTdWJkb21haW4iOnRydWV9">
+<template id="overlay-template">
+  <style>
+    overlay-mask {
+      left: 0;
+      padding: 8px;
+      position: absolute;
+      top: 0;
+      z-index: 1000;
+      font-family: sans-serif;
+      -webkit-justify-content: center;
+      background: rgba(0, 0, 0, 0.8);
+      display: flex;
+      height: 100%;
+      left: 0;
+      position: fixed;
+      top: 0;
+      width: 100%;
+    }
+    overlay-mask:focus {
+      outline: none;
+    }
+    overlay-vertical-centering-container {
+      -webkit-justify-content: center;
+      flex-direction: column;
+      display: flex;
+    }
+    overlay-frame {
+      z-index: 1100;
+      background: rgb(255, 255, 255);
+      border: 1px solid #ccc;
+      margin: 75px;
+      display: flex;
+      flex-direction: column;
+      min-height: 0;
+    }
+    title-bar {
+      -webkit-align-items: center;
+      flex-direction: row;
+      border-bottom: 1px solid #ccc;
+      background-color: #ddd;
+      display: flex;
+      padding: 5px;
+      flex: 0 0 auto;
+    }
+    title {
+      display: inline;
+      font-weight: bold;
+      flex: 1 1 auto;
+    }
+    close-button {
+      -webkit-align-self: flex-end;
+      border: 1px solid #eee;
+      background-color: #999;
+      font-size: 10pt;
+      font-weight: bold;
+      padding: 2px;
+      text-align: center;
+      width: 16px;
+    }
+    close-button:hover {
+      background-color: #ddd;
+      border-color: black;
+      cursor: pointer;
+    }
+    overlay-content {
+      display: flex;
+      flex: 1 1 auto;
+      flex-direction: column;
+      overflow-y: auto;
+      padding: 10px;
+      min-width: 300px;
+      min-height: 0;
+    }
+    button-bar {
+      -webkit-align-items: baseline;
+      border-top: 1px solid #ccc;
+      display: flex;
+      flex: 0 0 auto;
+      flex-direction: row-reverse;
+      padding: 4px;
+    }
+  </style>
+
+  <overlay-mask>
+    <overlay-vertical-centering-container>
+      <overlay-frame>
+        <title-bar>
+          <title></title>
+          <close-button>✕</close-button>
+        </title-bar>
+        <overlay-content>
+          <content></content>
+        </overlay-content>
+        <button-bar></button-bar>
+      </overlay-frame>
+    </overlay-vertical-centering-container>
+  </overlay-mask>
+</template><dom-module id="tr-ui-a-analysis-link">
+  <template>
+    <style>
+    :host {
+      display: inline;
+      cursor: pointer;
+      cursor: pointer;
+      white-space: nowrap;
+    }
+    a {
+      text-decoration: underline;
+    }
+    </style>
+    <a href="{{href}}" on-click="onClicked_" on-mouseenter="onMouseEnter_" on-mouseleave="onMouseLeave_"><slot></slot></a>
+
+  </template>
+</dom-module><dom-module id="tr-ui-b-table">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      table {
+        flex: 1 1 auto;
+        align-self: stretch;
+        border-collapse: separate;
+        border-spacing: 0;
+        border-width: 0;
+        -webkit-user-select: initial;
+      }
+
+      tr > td {
+        padding: 2px 4px 2px 4px;
+        vertical-align: top;
+      }
+
+      table > tbody:focus {
+        outline: none;
+      }
+      table > tbody:focus[selection-mode="row"] > tr[selected],
+      table > tbody:focus[selection-mode="cell"] > tr > td[selected],
+      table > tbody:focus > tr.empty-row > td {
+        outline: 1px dotted #666666;
+        outline-offset: -1px;
+      }
+
+      button.toggle-button {
+        height: 15px;
+        line-height: 60%;
+        vertical-align: middle;
+        width: 100%;
+      }
+
+      button > * {
+        height: 15px;
+        vertical-align: middle;
+      }
+
+      td.button-column {
+        width: 30px;
+      }
+
+      table > thead > tr > td.sensitive:hover {
+        background-color: #fcfcfc;
+      }
+
+      table > thead > tr > td {
+        font-weight: bold;
+        text-align: left;
+
+        background-color: #eee;
+        white-space: nowrap;
+        overflow: hidden;
+        text-overflow: ellipsis;
+
+        border-top: 1px solid #ffffff;
+        border-bottom: 1px solid #aaa;
+      }
+
+      table > tfoot {
+        background-color: #eee;
+        font-weight: bold;
+      }
+
+      /* Light row and cell highlight. */
+      table > tbody[row-highlight-style="light"] > tr[selected],
+      table > tbody[cell-highlight-style="light"] > tr > td[selected] {
+        background-color: rgb(213, 236, 229);  /* light turquoise */
+      }
+      table > tbody[row-highlight-style="light"] >
+          tr:not(.empty-row):not([selected]):hover,
+      table > tbody[cell-highlight-style="light"] >
+          tr:not(.empty-row):not([selected]) > td:hover {
+        background-color: #f6f6f6;  /* light grey */
+      }
+
+      /* Dark row and cell highlight. */
+      table > tbody[row-highlight-style="dark"] > tr[selected],
+      table > tbody[cell-highlight-style="dark"] > tr > td[selected] {
+        background-color: rgb(103, 199, 165);  /* turquoise */
+      }
+      table > tbody[row-highlight-style="dark"] >
+          tr:not(.empty-row):not([selected]):hover,
+      table > tbody[cell-highlight-style="dark"] >
+          tr:not(.empty-row):not([selected]) > td:hover {
+        background-color: #e6e6e6;  /* grey */
+      }
+      table > tbody[row-highlight-style="dark"] > tr:hover[selected],
+      table > tbody[cell-highlight-style="dark"] > tr[selected] > td:hover {
+        background-color: rgb(171, 217, 202);  /* semi-light turquoise */
+      }
+
+      table > colgroup > col[selected] {
+        background-color: #e6e6e6;  /* grey */
+      }
+
+      table > tbody > tr.empty-row > td {
+        color: #666;
+        font-style: italic;
+        text-align: center;
+      }
+
+      table > tbody.has-footer > tr:last-child > td {
+        border-bottom: 1px solid #aaa;
+      }
+
+      table > tfoot > tr:first-child > td {
+        border-top: 1px solid #ffffff;
+      }
+
+      :host([zebra]) table tbody tr:nth-child(even) {
+        background-color: #f4f4f4;
+      }
+
+      expand-button {
+        -webkit-user-select: none;
+        cursor: pointer;
+        margin-right: 3px;
+        font-size: smaller;
+        height: 1rem;
+      }
+
+      expand-button.button-expanded {
+        transform: rotate(90deg);
+      }
+    </style>
+    <table>
+      <colgroup id="cols">
+      </colgroup>
+      <thead id="head">
+      </thead>
+      <tbody id="body">
+      </tbody>
+      <tfoot id="foot">
+      </tfoot>
+    </table>
+  </template>
+</dom-module><dom-module id="tr-ui-b-table-header-cell">
+  <template>
+  <style>
+    :host {
+      -webkit-user-select: none;
+      display: flex;
+    }
+
+    span {
+      flex: 0 1 auto;
+    }
+
+    #side {
+      -webkit-user-select: none;
+      flex: 0 0 auto;
+      padding-left: 2px;
+      padding-right: 2px;
+      vertical-align: top;
+      font-size: 15px;
+      font-family: sans-serif;
+      line-height: 85%;
+      margin-left: 5px;
+    }
+
+    #side.disabled {
+      color: rgb(140, 140, 140);
+    }
+
+    #title:empty, #side:empty {
+      display: none;
+    }
+  </style>
+
+    <span id="title"></span>
+    <span id="side"></span>
+  </template>
+</dom-module><dom-module id="tr-v-ui-scalar-context-controller">
+  <template></template>
+</dom-module><dom-module id="tr-v-ui-scalar-span">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+      justify-content: flex-end;
+      position: relative;
+      /* Limit the sparkline's negative z-index to the span only. */
+      isolation: isolate;
+    }
+
+    :host(.left-align) {
+      justify-content: flex-start;
+    }
+
+    :host(.inline) {
+      display: inline-flex;
+    }
+
+    #sparkline {
+      width: 0%;
+      position: absolute;
+      bottom: 0;
+      display: none;
+      height: 100%;
+      background-color: hsla(216, 100%, 94.5%, .75);
+      border-color: hsl(216, 100%, 89%);
+      box-sizing: border-box;
+      z-index: -1;
+    }
+    #sparkline.positive {
+      border-right-style: solid;
+      /* The border width must be kept in sync with buildSparklineStyle_(). */
+      border-right-width: 1px;
+    }
+    #sparkline:not(.positive) {
+      border-left-style: solid;
+      /* The border width must be kept in sync with buildSparklineStyle_(). */
+      border-left-width: 1px;
+    }
+    #sparkline.better {
+      background-color: hsla(115, 100%, 93%, .75);
+      border-color: hsl(118, 60%, 80%);
+    }
+    #sparkline.worse {
+      background-color: hsla(0, 100%, 88%, .75);
+      border-color: hsl(0, 100%, 80%);
+    }
+
+    #content {
+      white-space: nowrap;
+    }
+    #content, #significance, #warning {
+      flex-grow: 0;
+    }
+    #content.better {
+      color: green;
+    }
+    #content.worse {
+      color: red;
+    }
+
+    #significance svg {
+      margin-left: 4px;
+      display: none;
+      height: 1em;
+      vertical-align: text-top;
+      stroke-width: 4;
+      fill: rgba(0, 0, 0, 0);
+    }
+    #significance #insignificant {
+      stroke: black;
+    }
+    #significance #significantly_better {
+      stroke: green;
+    }
+    #significance #significantly_worse {
+      stroke: red;
+    }
+
+    #warning {
+      display: none;
+      margin-left: 4px;
+      height: 1em;
+      vertical-align: text-top;
+      stroke-width: 0;
+    }
+    #warning path {
+      fill: rgb(255, 185, 185);
+    }
+    #warning rect {
+      fill: red;
+    }
+    </style>
+
+    <span id="sparkline"></span>
+
+    <span id="content"></span>
+
+    <span id="significance">
+      
+      <svg id="insignificant" viewBox="0 0 128 128">
+        <circle cx="64" cy="64" r="60"></circle>
+        <circle cx="44" cy="44" r="4"></circle>
+        <circle cx="84" cy="44" r="4"></circle>
+        <line x1="36" x2="92" y1="80" y2="80"></line>
+      </svg>
+
+      
+      <svg id="significantly_better" viewBox="0 0 128 128">
+        <circle cx="64" cy="64" r="60"></circle>
+        <circle cx="44" cy="44" r="4"></circle>
+        <circle cx="84" cy="44" r="4"></circle>
+        <path d="M 28 64 Q 64 128 100 64"></path>
+      </svg>
+
+      
+      <svg id="significantly_worse" viewBox="0 0 128 128">
+        <circle cx="64" cy="64" r="60"></circle>
+        <circle cx="44" cy="44" r="4"></circle>
+        <circle cx="84" cy="44" r="4"></circle>
+        <path d="M 36 96 Q 64 48 92 96"></path>
+      </svg>
+    </span>
+
+    <svg id="warning" viewBox="0 0 128 128">
+      <path d="M 64 0 L 128 128 L 0 128 L 64 0"></path>
+      <rect height="84" width="8" x="60" y="0"></rect>
+      <rect height="24" width="8" x="60" y="100"></rect>
+    </svg>
+  </template>
+</dom-module><dom-module id="tr-ui-a-generic-object-view">
+  <template>
+    <style>
+    :host {
+      display: block;
+      font-family: monospace;
+    }
+    </style>
+    <div id="content">
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-generic-object-view-with-label">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+    </style>
+  </template>
+</dom-module><dom-module id="tr-ui-b-drag-handle">
+  <template>
+    <style>
+    :host {
+      -webkit-user-select: none;
+      box-sizing: border-box;
+      display: block;
+    }
+
+    :host(.horizontal-drag-handle) {
+      background-image: -webkit-gradient(linear,
+                                         0 0, 0 100%,
+                                         from(#E5E5E5),
+                                         to(#D1D1D1));
+      border-bottom: 1px solid #8e8e8e;
+      border-top: 1px solid white;
+      cursor: ns-resize;
+      flex: 0 0 auto;
+      height: 7px;
+      position: relative;
+    }
+
+    :host(.vertical-drag-handle) {
+      background-image: -webkit-gradient(linear,
+                                         0 0, 100% 0,
+                                         from(#E5E5E5),
+                                         to(#D1D1D1));
+      border-left: 1px solid white;
+      border-right: 1px solid #8e8e8e;
+      cursor: ew-resize;
+      flex: 0 0 auto;
+      position: relative;
+      width: 7px;
+    }
+    </style>
+    <div></div>
+  </template>
+</dom-module><dom-module id="tv-ui-b-hotkey-controller">
+  <template>
+    <div></div>
+  </template>
+</dom-module><dom-module id="tr-ui-b-info-bar">
+  <template>
+    <style>
+    :host {
+      align-items: center;
+      flex: 0 0 auto;
+      background-color: rgb(252, 235, 162);
+      border-bottom: 1px solid #A3A3A3;
+      border-left: 1px solid white;
+      border-right: 1px solid #A3A3A3;
+      border-top: 1px solid white;
+      display: flex;
+      min-height: 26px;
+      padding: 0 3px 0 3px;
+    }
+
+    :host([hidden]) {
+      display: none !important;
+    }
+
+    #message { flex: 1 1 auto; }
+    </style>
+
+    <span id="message"></span>
+    <span id="buttons"></span>
+  </template>
+</dom-module><dom-module id="tr-ui-b-mouse-mode-icon">
+  <template>
+    <style>
+    :host {
+      display: block;
+      background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAChCAYAAACbBNzvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABV0RVh0Q3JlYXRpb24gVGltZQA3LzE2LzEzRNEKUwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAA9aSURBVHic7V1rTFvl//+UrgUmZWMpbLa6cLErwpYxkqLGkjAG88WSbmumGUllvlmAJctMRtybvlHrLXiJUekMIZuYSCL5gS+EuLIXGEGjqCsllCEW6xQECgzWG7S05/+C/zkp9LTn0gsL6ych9JzznOdzPj19Luf5PN/nCN59913ixRdfRFdXFxLx/2GDgCAIYmpqCoWFhUjE/4cNae+99x4AIFH/Hzak7nDqDu+wOyyw2WzEdl9EMpG23ReQbKQE73Q8coJ3bfcFWK1W/Pbbb/D7/UhLi/37DwaDEIvFKC8vR0lJSdjxbRVstVoxPDyMxx9/HAUFBcjMzIRAIOCdXzAYhNvtht1ux/DwMACEid5WwSMjI3jyySdRXFwMsVgMoVAYk2CCIJCZmYns7GyMjo5iZGQkPoKXl5exd+9e3hdGIhgMIj8/H5mZmRCJRIyCyQ5NJBAEgUAgAKFQiIKCAiwsLISl4VxoHA4H+vv74Xa7uZ4aBqFQiOzsbIhEIojFYojFYohEItq/8fFxXLlyBUtLSxHThOaxZ88eCIXC2AWPj48DAH799deYBaelpUEoFLL6++qrrwAAH3zwAav0YrGYthLkJHh6ehpzc3MAgPn5eUxPT8csWiAQMJbboaEhmM1mAIDFYsHQ0BDvPDkJtlgsYdt+v59LFrxw/fr1sG2Xy8UrL06C6+vrw7bFYjEvYi747rvvwrYlEgmvvDjV0g6HI+p2ohBP3qh32OFwoLe3l1VGvb29sNvtvC8kFCMjI9DpdKzS6nQ6mEwm1nnTPg/7/X6MjY1hcnKS/VX+P/bu3YuysjLk5uYypv36669x8uRJZGRkQCQSwev1oqOjAz09PZx5CwsLcenSJRw+fBh+vx+rq6swmUx46aWXNqWjvcMDAwO8xAIbnZKBgQFeNXhzczMvscBGp6S5uRk//vhj1HS0grVaLYqLi3kRy+Vy1NXVRe0RRcKNGzeg0Wh48apUKnR1daG6ujpqOtpKy+VyQa1Wo6SkBLdv38aFCxeoY5988gn1+fLly9TnL774ApWVlXjiiSfgdDqxtrbG+aJ9Ph/0ej3OnDkDvV6PW7duUceOHDlCfR4dHaU+v/DCC7h27RrUajWcTidWV1ejctAKJggCKysryMzMhE6nw+zsLO3Joft1Oh0ePHiApaUlduqi8BYVFaGvr48Vb19fHyfeqM2Sz+dj3QTEs4lKJC+njsfWJoptkxUrtjZRbJssOnASXFtbG3U7UXjrrbeibnMBJ8FZWVkoKysDABQUFCArK4s3MRcoFArqrlZXV0OhUPDOi5Ngn8+Hw4cPQyqV4tlnn4XP5+NNTIIgmH0An8+HV155BUqlEq+++ior3kAgQLuf84jH2toajh8/jvX1da6n0sLj8SAjI4MxHUEQ+PTTT1nlSRAEHjx4QHtsW8e0RCIR7HY79uzZE/GOcEUgEEAgEMDff/8NkUgUdnxbBR85cgRmsxkCgQD5+fkRh2XYIhAI4P79+5iamoLD4cCxY8fC0myr4KeeegoCgQBWqxVzc3NIS0uLedQyGAxi165dKC8vR1FRUVialHu405ESvNPxyAlOuYfJRMo9fFjdw3iBq3vIBDbu4bYK3uoextKtJEH2yWNyD8nyEG8wuYcffvgha3cxru6h3W5Hf39/QoyzaE6fyWRCQ0MDZ+MsLu7h8vIyent7sby8zIk8VkxNTUGn08Fms8UlP04Nn9/vR39/f9w8JLZwu91obGzk5CFFAq+Wfnh4mDKok4mWlha0trbGlAfvrs3k5CQGBgaSYoiHoqenB1evXk2OIb4VDocDJpMp6eXaYrGgsbGRV7mOufPq8XgwMDCQ9HI9NzeHq1evci7XvDseUqkUWq0W6enpCAaDcDqd8Hq9fLNjDaVSiRs3bkAikfDi5XSHxWIxampqAAALCwsYGhrC7Ows5ufnEypWIpHAYDAAACYmJnD9+nXevJwEnzp1CjKZDBUVFQCAsbGxpJTfjz76CFVVVWhqagIAdHR08G6XWQuuqanB7t274fV6UVpaiuzsbAAbTzyJhMFggEKhgNfrRX19PWQyGQDAaDTyyo+V4JqaGshkMsricLlcOH78OICNCWp8p0cwwWAwoKqqahPvG2+8AWDji+7u7uacJyvBMpksrKxkZWVR0yLGxsY4E7NBVVVVGK9CoaCmRXR0dHDOk5VguorB5/OhoqICYrE4YZ2PSLxXrlyBRCLhNcE1pufh1dVVXLx4EWlpaRGnJzCBjXtId87g4GBU3ri5h1uJ5+fnY8mCtXvIhTflHoYg5R4mEyn3MAl45KyWlOCdjkdOcMo9TCZS7mHKPeSGhLmH5LBOrAGXXN1DcliHrgdFgsk95CzYbrfDbDbD7/ejrKwstpmtNO5hJJhMJrS2tsLtdqOpqQlarTZi2mjuIWvBfr8fZrN50/iz2WzG9PQ0nn/+edonEzZgij10uVwwGo2bxp+NRiOGhobw+uuv005hjtk9JENz6AbbyWCuRESp2Ww2NDc30w62WywW6HQ6zoOIrO5wbm4uzp8/j5WVFXR2dm46VldXh3379mF5eTku86dDUVxcjK6uLthstrClqrq6unDo0CHOvKwE+/1+LC4uUqG0oZiYmIhaicQCkvfu3bthxwYGBnhVmpy6NnSD7kxxQvEA3Zo+fIsQJ8F040j379/nRcwFdF4037FwToLphkUXFxd5EXMB3chkUgQ7nc6wfT6fL+Gm+H///Re2z+Vy8TLFGSut/v5+RsPsm2++AbDR84pXLFNDQwPjelxnz54FsBFK+/nnn7PKl/EOa7VaVmHvYrE4au+HK27evMkq7F0ikeDmzZus82UU7HK5qG8yGs6ePct73gUdfD4f2tvbGdO1t7dzaocZBRMEAaFQSBnhdKipqYFQKORlm0TjzcvLo4xwOhgMBuTl5XHiZVVp+f1+yGQy2iDq4uJiyGSyhFRcfr8fVVVVtEHUGo0GVVVVnHlZ19JerxdqtRpSqZTaJ5VKoVarEzrdwev1Qq/XQ6lUUvuUSiX0ej0vXk7N0srKCjQaDbXmjUajwcrKCmfSULD5Oa6srKCtrQ0SiQQSiQRtbW2MvHFzD0MrsXhUUmzdw9BKjKmSiqt7SBBE3Conru4hOa8kWqBnyj3cgl0EQcQ0cMYWW3kIgkiKe7iVV2C1Won09PSYxLCB1+tFZmYmtb22tobt4E1LBimATaQAkiKWjveR85ZSgnc6Uu5hMpFyD1PuITekYg/ZxB52dXXFTMo2n1D38NSpU7zjDEP/yHzisnJpIsBm5dJ45rntgpONuITTJirctqWlJabjdGAUvNUEp0NouxcvtLa2MgZhmUwmzqKjCrbb7aw9HC5pmWAymVivb2kymTgFe0RslrbeNTa1rtlshkgkQn5+PusL2Iqtd42NdWM0GpGVlYWTJ08ypo14h/nGI8Uax8Q3XJbteREFV1ZW8iLmex6Ja9euJfS8iD9puVyOmpoa3L59G8DmVUq3glzNlAzoimVgvrq6GmlpadDr9QA2r1K6FeRqpmRAFxveiIK9Xi8VZ/jLL78whulUVFTELJbkJeMMjUYjI29TUxNrsQBDX5qMM4w0qE2iuLgYpaWlcXMPyThDphWMNRoN6uvrOfGyskvVanXUNGq1Oq5WKclL/qwjQa/Xc+Zl1dNi8nFi9ZeSyZvqS0erjbmAbT6kT7X1lQp8QeYTyasKE8w3aJJvPh6PBwRBYGZmJi68MzMzqdjDUDx67mEsFxwrUrGHSUCqWdrpSAne6dix7uFzzz1HW0s/FO7h/v37UVBQgMceeyxm99DlcsFut2NwcBACgSDsnTHb7h4ePHgQxcXFcTPTMjIyIJFIcOfOHfz+++8Pl2DSPSTftxQv93DXrl0oKirCnTt3wtIwFhq62aputxtms5maCR8pHROEQiEkEgntew/X1tbC3mu4tLSE9vZ2nD9/njZd6Pn79u3jHoo3OTmJsbExnDlzBsDGWLXdbqcNoent7YVCocChQ4dYh+VFij3s7u5GR0cH9YWaTCbcunVr0yMkmfbChQvQarXQarVUWF4wGER6ejp7wdPT0zCbzfB4PJv2R7NT/H4/rFYrJicnUVZWxnowPtTpGxoagtFoDAsIi2anuN1ufPnll+ju7salS5dw4sQJKk+64hH2FTgcDgwPD4eJZQu/3w+bzcZ5JSSLxYL333+fNvqNDdxuN3p6ehjPDxMsl8tjjkw5ceIENfOVLVQqFd58882YeA0GA7WiWiSECfb5fPjpp58AbKyBx/bCpVIp6urqAADff/895wf6tbU1fPbZZwCAjz/+mPHCSSiVSsr3eueddxh5aWtpMrwuJyeH9cuczp07R5UZvktO/fnnnwCAY8eOoa+vj9U5nZ2d1CsH2fhaUZulwcFB1kGNi4uLjK/gYwuDwcCJ9+2332add9RmyW63w+12Q6FQIC8vD5cvX8bCwgI19VcqlcJms8HhcGBycjJuSz6aTCbMzs5Cq9Xi6NGjGB0dxcTEBJxOJyQSCZRKJUZGRjAyMoL//e9/jBFsoaAVLJfLKZvD4XBQ37ZEItlUph0OB238gVwu5ySQhEqlopo+i8VCtbsymWxTmb579y6t46BSqRg5aAXX1tbi22+/DZvY5XQ6aQMuQyGVSlFbW8trgb6WlhY0NDRgYmJi0/6ZmRnGYVylUomWlhbGeGbaMuzxeKDRaKhVDdkgOzsblZWVOHfuHO82fH19HW1tbWhqamL9ul2ZTIbXXnsNnZ2drN7yFfFFjy6XC6WlpVCpVFhaWsK///5LVfnz8/PIy8sDAOzevRu5ubnIycmBx+OJKZ6YIAj4fD7U19ejsbERf/zxB4aHhykrdHx8HE8//TQAYP/+/VAqlVAoFJx4I1ZapGiyrBw4cAD37t2DXC7HgQMHAGx0QXNycrC+vh63VR5Cecnw3J6eHqhUKpSXlwPY6OI+88wzALiHxnN6PPz555/D9h08eJATIR/Qzd9gE/FKh9SYFlvI5XKqPMUCrlFuKpUKp0+fZkwXDAZp93MSLBaLUVJSgqNHjyIjIwNerzfmOR0ul4sx9lAikeD06dN4+eWXIZVKGXnj5h5evHgRXq8XHo+Hd9MTCpFIhHv37iEnJydqp/+HH36A1+uFy+VirKTi6h7Gug7tVpDuIUEQKCwsjOge/vPPP6zyCwQCWF5exl9//YX5+Xla93DbzTSbzQar1Yr19fW4uoclJSUp9xB4BJullOCdjkdO8P8BGCQ0hnF1DxUAAAAASUVORK5CYII=);
+      width: 27px;
+      height: 30px;
+    }
+    :host.active {
+      cursor: auto;
+    }
+    </style>
+  </template>
+</dom-module><dom-module id="tr-ui-b-mouse-mode-selector">
+  <template>
+    <style>
+    :host {
+
+      -webkit-user-drag: element;
+      -webkit-user-select: none;
+
+      background: #DDD;
+      border: 1px solid #BBB;
+      border-radius: 4px;
+      box-shadow: 0 1px 2px rgba(0,0,0,0.2);
+      left: calc(100% - 120px);
+      position: absolute;
+      top: 100px;
+      user-select: none;
+      width: 29px;
+      z-index: 20;
+    }
+
+    .drag-handle {
+      background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAChCAYAAACbBNzvAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABV0RVh0Q3JlYXRpb24gVGltZQA3LzE2LzEzRNEKUwAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAA9aSURBVHic7V1rTFvl//+UrgUmZWMpbLa6cLErwpYxkqLGkjAG88WSbmumGUllvlmAJctMRtybvlHrLXiJUekMIZuYSCL5gS+EuLIXGEGjqCsllCEW6xQECgzWG7S05/+C/zkp9LTn0gsL6ych9JzznOdzPj19Luf5PN/nCN59913ixRdfRFdXFxLx/2GDgCAIYmpqCoWFhUjE/4cNae+99x4AIFH/Hzak7nDqDu+wOyyw2WzEdl9EMpG23ReQbKQE73Q8coJ3bfcFWK1W/Pbbb/D7/UhLi/37DwaDEIvFKC8vR0lJSdjxbRVstVoxPDyMxx9/HAUFBcjMzIRAIOCdXzAYhNvtht1ux/DwMACEid5WwSMjI3jyySdRXFwMsVgMoVAYk2CCIJCZmYns7GyMjo5iZGQkPoKXl5exd+9e3hdGIhgMIj8/H5mZmRCJRIyCyQ5NJBAEgUAgAKFQiIKCAiwsLISl4VxoHA4H+vv74Xa7uZ4aBqFQiOzsbIhEIojFYojFYohEItq/8fFxXLlyBUtLSxHThOaxZ88eCIXC2AWPj48DAH799deYBaelpUEoFLL6++qrrwAAH3zwAav0YrGYthLkJHh6ehpzc3MAgPn5eUxPT8csWiAQMJbboaEhmM1mAIDFYsHQ0BDvPDkJtlgsYdt+v59LFrxw/fr1sG2Xy8UrL06C6+vrw7bFYjEvYi747rvvwrYlEgmvvDjV0g6HI+p2ohBP3qh32OFwoLe3l1VGvb29sNvtvC8kFCMjI9DpdKzS6nQ6mEwm1nnTPg/7/X6MjY1hcnKS/VX+P/bu3YuysjLk5uYypv36669x8uRJZGRkQCQSwev1oqOjAz09PZx5CwsLcenSJRw+fBh+vx+rq6swmUx46aWXNqWjvcMDAwO8xAIbnZKBgQFeNXhzczMvscBGp6S5uRk//vhj1HS0grVaLYqLi3kRy+Vy1NXVRe0RRcKNGzeg0Wh48apUKnR1daG6ujpqOtpKy+VyQa1Wo6SkBLdv38aFCxeoY5988gn1+fLly9TnL774ApWVlXjiiSfgdDqxtrbG+aJ9Ph/0ej3OnDkDvV6PW7duUceOHDlCfR4dHaU+v/DCC7h27RrUajWcTidWV1ejctAKJggCKysryMzMhE6nw+zsLO3Joft1Oh0ePHiApaUlduqi8BYVFaGvr48Vb19fHyfeqM2Sz+dj3QTEs4lKJC+njsfWJoptkxUrtjZRbJssOnASXFtbG3U7UXjrrbeibnMBJ8FZWVkoKysDABQUFCArK4s3MRcoFArqrlZXV0OhUPDOi5Ngn8+Hw4cPQyqV4tlnn4XP5+NNTIIgmH0An8+HV155BUqlEq+++ior3kAgQLuf84jH2toajh8/jvX1da6n0sLj8SAjI4MxHUEQ+PTTT1nlSRAEHjx4QHtsW8e0RCIR7HY79uzZE/GOcEUgEEAgEMDff/8NkUgUdnxbBR85cgRmsxkCgQD5+fkRh2XYIhAI4P79+5iamoLD4cCxY8fC0myr4KeeegoCgQBWqxVzc3NIS0uLedQyGAxi165dKC8vR1FRUVialHu405ESvNPxyAlOuYfJRMo9fFjdw3iBq3vIBDbu4bYK3uoextKtJEH2yWNyD8nyEG8wuYcffvgha3cxru6h3W5Hf39/QoyzaE6fyWRCQ0MDZ+MsLu7h8vIyent7sby8zIk8VkxNTUGn08Fms8UlP04Nn9/vR39/f9w8JLZwu91obGzk5CFFAq+Wfnh4mDKok4mWlha0trbGlAfvrs3k5CQGBgaSYoiHoqenB1evXk2OIb4VDocDJpMp6eXaYrGgsbGRV7mOufPq8XgwMDCQ9HI9NzeHq1evci7XvDseUqkUWq0W6enpCAaDcDqd8Hq9fLNjDaVSiRs3bkAikfDi5XSHxWIxampqAAALCwsYGhrC7Ows5ufnEypWIpHAYDAAACYmJnD9+nXevJwEnzp1CjKZDBUVFQCAsbGxpJTfjz76CFVVVWhqagIAdHR08G6XWQuuqanB7t274fV6UVpaiuzsbAAbTzyJhMFggEKhgNfrRX19PWQyGQDAaDTyyo+V4JqaGshkMsricLlcOH78OICNCWp8p0cwwWAwoKqqahPvG2+8AWDji+7u7uacJyvBMpksrKxkZWVR0yLGxsY4E7NBVVVVGK9CoaCmRXR0dHDOk5VguorB5/OhoqICYrE4YZ2PSLxXrlyBRCLhNcE1pufh1dVVXLx4EWlpaRGnJzCBjXtId87g4GBU3ri5h1uJ5+fnY8mCtXvIhTflHoYg5R4mEyn3MAl45KyWlOCdjkdOcMo9TCZS7mHKPeSGhLmH5LBOrAGXXN1DcliHrgdFgsk95CzYbrfDbDbD7/ejrKwstpmtNO5hJJhMJrS2tsLtdqOpqQlarTZi2mjuIWvBfr8fZrN50/iz2WzG9PQ0nn/+edonEzZgij10uVwwGo2bxp+NRiOGhobw+uuv005hjtk9JENz6AbbyWCuRESp2Ww2NDc30w62WywW6HQ6zoOIrO5wbm4uzp8/j5WVFXR2dm46VldXh3379mF5eTku86dDUVxcjK6uLthstrClqrq6unDo0CHOvKwE+/1+LC4uUqG0oZiYmIhaicQCkvfu3bthxwYGBnhVmpy6NnSD7kxxQvEA3Zo+fIsQJ8F040j379/nRcwFdF4037FwToLphkUXFxd5EXMB3chkUgQ7nc6wfT6fL+Gm+H///Re2z+Vy8TLFGSut/v5+RsPsm2++AbDR84pXLFNDQwPjelxnz54FsBFK+/nnn7PKl/EOa7VaVmHvYrE4au+HK27evMkq7F0ikeDmzZus82UU7HK5qG8yGs6ePct73gUdfD4f2tvbGdO1t7dzaocZBRMEAaFQSBnhdKipqYFQKORlm0TjzcvLo4xwOhgMBuTl5XHiZVVp+f1+yGQy2iDq4uJiyGSyhFRcfr8fVVVVtEHUGo0GVVVVnHlZ19JerxdqtRpSqZTaJ5VKoVarEzrdwev1Qq/XQ6lUUvuUSiX0ej0vXk7N0srKCjQaDbXmjUajwcrKCmfSULD5Oa6srKCtrQ0SiQQSiQRtbW2MvHFzD0MrsXhUUmzdw9BKjKmSiqt7SBBE3Conru4hOa8kWqBnyj3cgl0EQcQ0cMYWW3kIgkiKe7iVV2C1Won09PSYxLCB1+tFZmYmtb22tobt4E1LBimATaQAkiKWjveR85ZSgnc6Uu5hMpFyD1PuITekYg/ZxB52dXXFTMo2n1D38NSpU7zjDEP/yHzisnJpIsBm5dJ45rntgpONuITTJirctqWlJabjdGAUvNUEp0NouxcvtLa2MgZhmUwmzqKjCrbb7aw9HC5pmWAymVivb2kymTgFe0RslrbeNTa1rtlshkgkQn5+PusL2Iqtd42NdWM0GpGVlYWTJ08ypo14h/nGI8Uax8Q3XJbteREFV1ZW8iLmex6Ja9euJfS8iD9puVyOmpoa3L59G8DmVUq3glzNlAzoimVgvrq6GmlpadDr9QA2r1K6FeRqpmRAFxveiIK9Xi8VZ/jLL78whulUVFTELJbkJeMMjUYjI29TUxNrsQBDX5qMM4w0qE2iuLgYpaWlcXMPyThDphWMNRoN6uvrOfGyskvVanXUNGq1Oq5WKclL/qwjQa/Xc+Zl1dNi8nFi9ZeSyZvqS0erjbmAbT6kT7X1lQp8QeYTyasKE8w3aJJvPh6PBwRBYGZmJi68MzMzqdjDUDx67mEsFxwrUrGHSUCqWdrpSAne6dix7uFzzz1HW0s/FO7h/v37UVBQgMceeyxm99DlcsFut2NwcBACgSDsnTHb7h4ePHgQxcXFcTPTMjIyIJFIcOfOHfz+++8Pl2DSPSTftxQv93DXrl0oKirCnTt3wtIwFhq62aputxtms5maCR8pHROEQiEkEgntew/X1tbC3mu4tLSE9vZ2nD9/njZd6Pn79u3jHoo3OTmJsbExnDlzBsDGWLXdbqcNoent7YVCocChQ4dYh+VFij3s7u5GR0cH9YWaTCbcunVr0yMkmfbChQvQarXQarVUWF4wGER6ejp7wdPT0zCbzfB4PJv2R7NT/H4/rFYrJicnUVZWxnowPtTpGxoagtFoDAsIi2anuN1ufPnll+ju7salS5dw4sQJKk+64hH2FTgcDgwPD4eJZQu/3w+bzcZ5JSSLxYL333+fNvqNDdxuN3p6ehjPDxMsl8tjjkw5ceIENfOVLVQqFd58882YeA0GA7WiWiSECfb5fPjpp58AbKyBx/bCpVIp6urqAADff/895wf6tbU1fPbZZwCAjz/+mPHCSSiVSsr3eueddxh5aWtpMrwuJyeH9cuczp07R5UZvktO/fnnnwCAY8eOoa+vj9U5nZ2d1CsH2fhaUZulwcFB1kGNi4uLjK/gYwuDwcCJ9+2332add9RmyW63w+12Q6FQIC8vD5cvX8bCwgI19VcqlcJms8HhcGBycjJuSz6aTCbMzs5Cq9Xi6NGjGB0dxcTEBJxOJyQSCZRKJUZGRjAyMoL//e9/jBFsoaAVLJfLKZvD4XBQ37ZEItlUph0OB238gVwu5ySQhEqlopo+i8VCtbsymWxTmb579y6t46BSqRg5aAXX1tbi22+/DZvY5XQ6aQMuQyGVSlFbW8trgb6WlhY0NDRgYmJi0/6ZmRnGYVylUomWlhbGeGbaMuzxeKDRaKhVDdkgOzsblZWVOHfuHO82fH19HW1tbWhqamL9ul2ZTIbXXnsNnZ2drN7yFfFFjy6XC6WlpVCpVFhaWsK///5LVfnz8/PIy8sDAOzevRu5ubnIycmBx+OJKZ6YIAj4fD7U19ejsbERf/zxB4aHhykrdHx8HE8//TQAYP/+/VAqlVAoFJx4I1ZapGiyrBw4cAD37t2DXC7HgQMHAGx0QXNycrC+vh63VR5Cecnw3J6eHqhUKpSXlwPY6OI+88wzALiHxnN6PPz555/D9h08eJATIR/Qzd9gE/FKh9SYFlvI5XKqPMUCrlFuKpUKp0+fZkwXDAZp93MSLBaLUVJSgqNHjyIjIwNerzfmOR0ul4sx9lAikeD06dN4+eWXIZVKGXnj5h5evHgRXq8XHo+Hd9MTCpFIhHv37iEnJydqp/+HH36A1+uFy+VirKTi6h7Gug7tVpDuIUEQKCwsjOge/vPPP6zyCwQCWF5exl9//YX5+Xla93DbzTSbzQar1Yr19fW4uoclJSUp9xB4BJullOCdjkdO8P8BGCQ0hnF1DxUAAAAASUVORK5CYII=) 2px 3px no-repeat;
+      background-repeat: no-repeat;
+      border-bottom: 1px solid #BCBCBC;
+      cursor: move;
+      display: block;
+      height: 13px;
+      width: 27px;
+    }
+
+    .tool-button {
+      background-position: center center;
+      background-repeat: no-repeat;
+      border-bottom: 1px solid #BCBCBC;
+      border-top: 1px solid #F1F1F1;
+      cursor: pointer;
+    }
+
+    .buttons > .tool-button:last-child {
+      border-bottom: none;
+    }
+
+    </style>
+    <div class="drag-handle"></div>
+    <div class="buttons">
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-e-chrome-cc-display-item-list-item">
+  <template>
+    <style>
+      :host {
+        border-bottom: 1px solid #555;
+        display: block;
+        font-size: 12px;
+        padding: 3px 5px;
+      }
+
+      :host(:hover) {
+        background-color: #f0f0f0;
+        cursor: pointer;
+      }
+
+      .header {
+        font-weight: bold;
+        margin: 2px 0;
+      }
+
+      .header > .extra {
+        background-color: #777;
+        border-radius: 4px;
+        color: white;
+        margin: 0 6px;
+        text-decoration: none;
+        padding: 2px 4px;
+      }
+
+      .raw-details {
+        white-space: pre-wrap;
+      }
+
+      .details > dl {
+        margin: 0;
+      }
+
+      :host(:not([selected])) .details {
+        display: none;
+      }
+    </style>
+    <div class="header">
+      {{name}}
+      <template if="{{_computeIfSKP(richDetails)}}" is="dom-if">
+        <a class="extra" download="drawing.skp" href$="{{_computeHref(richDetails)}}" on-click="{{stopPropagation}}">SKP</a>
+      </template>
+    </div>
+    <div class="details">
+      <template if="{{rawDetails}}" is="dom-if">
+        <div class="raw-details">{{rawDetails}}</div>
+      </template>
+      <template if="{{richDetails}}" is="dom-if">
+        <dl>
+          <template if="{{richDetails.visualRect}}" is="dom-if">
+            <dt>Visual rect</dt>
+            <dd>{{richDetails.visualRect.x}},{{richDetails.visualRect.y}}
+                {{richDetails.visualRect.width}}×{{richDetails.visualRect.height}}
+            </dd>
+          </template>
+        </dl>
+      </template>
+    </div>
+  </template>
+
+</dom-module><template id="tr-ui-e-chrome-cc-display-item-debugger-template">
+  <left-panel>
+    <display-item-info>
+      <header>
+        <span class="title">Display Item List</span>
+        <span class="size"></span>
+        <div class="export">
+          <input class="dlfilename" type="text" value="displayitemlist.json"/>
+          <button class="dlexport">Export display item list</button>
+        </div>
+        <div class="export">
+          <input class="skpfilename" type="text" value="skpicture.skp"/>
+          <button class="skpexport">Export list as SkPicture</button>
+        </div>
+      </header>
+    </display-item-info>
+  </left-panel>
+  <right-panel>
+    <raster-area>
+      <canvas-scroller>
+        <canvas></canvas>
+      </canvas-scroller>
+    </raster-area>
+  </right-panel>
+</template><template id="quad-stack-view-template">
+  <style>
+  #chrome-left {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMcAAABICAYAAABC4+HLAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAB3RJTUUH3QcNFyMmV/Pm9QAAIABJREFUeNrtvXmwXdd13vlbe9/7BgzEQAIcQAIEQYKjSAokLVlOW5Fk2nLKmqx0J2Wp0k652h13uiy5XYqdwU7sSnckpZ1yV3U75apU4kos27Elu9NlyRXZjiiRomSTIiWZs0hwHsABJIY33rPX6j/W2ueed3DvAyDKKoGFW0UCeO/ec/fZZ+29v7XWt74lAIuLi7tXV1f/raq+zcy2AogIZsbpvrqfMzNE5IS/1/fVn5sZKaUTrtX9/v7nT+fn9e/1e052X/3r1THWa3R/37+miKCq7c+mjW/a+F/P57vj6/45bayn+wzXs4n+794Q9nP8+PHdS0tL31LVmfpGVQU4YSInGUb/YfZvpn+zp/LQu4Y27X31d933nurkq+qaa08yotO55npG0v2O+r1/XZ9fb2FMWoD9Oe5+pju//e+fdP3u83+j2I+89NJLn11dXf1bdSCTJnnSSpz2+/VWZ/8m+w+g/zD616yT2P9733BOZ5f4dhbCevPQHet63zVtV3y9n1/v/k9nZ562SNY7Gd5o9iPPP//8qxVKrQdL+hOy3qqdNEnTjv1JA+vuRpMGvd7kn8oCqded9B2THuJ6u/Kk7+vuiNOgQH8OX+/np813/376O/CkU2EavDwVWPiGsp9nn33WJt3ItF2ne2xOe2jTHuTJMOS0He1UcG33791JmWQYkzB6dyfp7tynsktPG8/Jdv2TGcLpfH7Sc5m0EKZBsPV+tp4PMe39bwj7efrpp229G5u2O3WPplN1cE/XQZsENybtnNN2pv4x3N1Fpu2S/SO6j6fXgz6n4gRPGmMfR7/ez/cXd/1798Tsfr4PMU52Oq4Hp95I9jPor7ZJ+G7STlEnvN7gesfXpB2tH5lZzynrO07Txtb92aQTY9rv+3i1v4jqv5umOSEq0r9O3/iqEUx6MPXnqjpxrk73812oMQmP968zyUj68zPp+U1bxG80+5GnnnrKpkVxTiWUuN4q7+96/YFXp6pvANN8hD7MmRbF6O7200KR9ed9CDbpSF4v6jIJtnQjQdPGOylK9p34/HowaFL0Z73IUNex7Z5Gk3bkN6L9yBNPPGHdY3fayu3uSP0dqH62uyP0w4XrDWo957gPEfqf78e4p4U8+0Y86R6711pvAUyL3vTvd9ou238Q/Xn4dj4/Cd6d7BlMC532534S9OnO8xvVfuTxxx+39RJlk/DtpAGc6k6hquScp+7EkyIn0+LV60Ufpu2q05zN/sOYFIfvP8CT5VEmGWN/h5w0zm/38+sl7/r3drLntt58rzdXbyT7kccee8z6O2b3JnLO6zpjk47nkyVg1pu07muas9b3CaZh4f5uPMn4Sikn7Jj9RTEJMnQfVHdck4x3Wt5i0qL6dj8/6WQ5GcSYBiEn+STrhT/fqPYzmJYxrRcopax5eH18Oi38WI2ulLImYTPNMavv716z/93rRXUmOZXVgZ5kePX7+hPeN5xJTmx3MdXf9zHyM888w8LCwgn30IUQ0xzWSYvhVD4/LarTzpWBpOl+zqRQ9lqjE2DCtbH2x9MW3XA45JxzzmHnzp0njYp9r9jPoH75Gkekc8SZ2ZpjrH/Ez8wMSSmHMY4YjZp2MDnniVGT/sPvRhxmZ2fJOWHmxj0ajU7AtvV6k4727gSklMg5M4jdq6iyuro69bv799fNptYF0X3vJKjz8MMPMz+/gWuvuYatW7eScgIEwTADEwEUAZDkBgtuYONlCCJgAuZ/N5QkCcP8avFzUH8fsZgNEoJJLAakc+2TjENi90RQjGSCJm1/hwlmgmRFFIwEYoiNxyPxvYZ07gVKUzh8+DD333cfRZXLLrvsBLxfjbl76pyO/ZRS1thq325O137k4YcftvUSOf1Ufdco/uwLX+LOv7ibZ194EYBdF+zkB956C+98+99ARE64ue6XqyqDwaDdGZqm4Qtf/DK3f+UveO7QS2uu944f/IH2WpNwdp2U/oT8+W23c8dX7+K5GN9FF+zkb7zlZt71jh9cswNPw8uTsPU0h19VeeSRR7j55lvYumUzK6MCpqTs9p2AAiRLmChWBBIIiqZEMkVUMAQTJZtQSCCKkDE0/h+7twkKpCSYxrhVMTGyCYogohRLCGvHoYD0xyGKScIUpC5AVSQl/0ACaxeCkJJhakDCTJEEiKAmDMx8XSdAY6lZQjHmZoa89NLL3Pv1r3PVVVeesDH3T+FTtZ/uguhu8v3o36naj4ggjzzyiPXhwtRjOf6+tLjEP//4r3HOuRfw5psPsOeSXQA8+dQz3Pu1ezl2+BC//I9+jvn5uXWjDfW1uLjIr37y19m8/fzJ13vlBf75L/48c3Oza3aWadSP5eUVfuUT/2bd6/3yL/xvbNgwv2Y3qbtOF0J2MfN6ka7nnnuOvZfuZcfO8xitKnloFBXEBHGLc4MTQwVEDeIkyAqa/Pdh9z5vaqgkUuz8akYGVATEHOYYiCSUQtJqkCDJsJJIvXFYNRIzLGWQQqqLEiOhqKS6gnzhqJ9cJplsiiXBSnfBJF957TEoJBKYYskwFUSgWCKnBkmZp59+mpdfepmdO3eu2USn+V/r2c/JWAX9CN/J7KdNiD744IO2nqM0Cff+01/9P7js6gP8d29/C5detJNtmzYC8OrxBZ547kVu/+JfcPDBe/iXv/xPkCnkvHalm/HPTvV6v/SP25vs3mB3fKurI37pX36cfdesf73HHriH//2X/3Fr/NOSTZMyzn0n0sx47LHH+JEf+REWFhd8pzcliRtyBVbFYlcTN0bfpoWEYiaxENTtjOQwByOZ7+r+b/zacY5YICvH/iDmBurjmzQOKMlIWkPThpohkuN0iwWI+YrNGkdeQswwcbhlWEAzw8wXazZDJfsYMP84ghXzxSHip5rB/IY5/sv/+0dc96Y3rdmA2uz0YDA1EHIqDNv1KDAVvk2yn64vOujHlqdlJ+vv/+wLX2JuywVcfOkeXj2ywGtHn0C1Hov+uUsu3cNzzz/Hf7vtdm5959snRknq6wtfvOOUr/fnX7yDH37n29fccBdG5Zy57fYvs2HrqV7vdm59x9vXJeqtx6WqD+T555/nyiv3s7y8TMLhSgLMElkURx+KENi+7uzi0EgtIUCi+OmSwIpjmYTSAIN6uiSDkkAKQgp/IgON+yaGnxIBz/rjcPckj30LU5I5rCsJsiYsafgjCbXEUIwiiqq4e1J9FjVfNCioYMlPC/eJIFuisTiN0oBkhllBcmJlaYnL9+/n0KFD7Nixg5xza6hPP/00S0tLzM7Mho/lfpGicW/hyyCQAv75Nuw+UOwi/o7WmXLfClhYOMaWLVvZtWtXG7TpRibrMx/0V1j34XcdT4DBYMA933yQnRdeymhUOHZsCZFEqrurORRZHRV2XrCLr33jft596zsZjUbtiuzGqQeDAXd//T52Xrj3lK53zzce4G/d+k6WlpfXOF5jSAhf+8YD7DjF8d3zjQf50VvfRdM0LYzqv/pHcH9napqGF154gb/59rdz7PhxTPCdNSliisYuK5rjIRsWPyeJQyGhWhyNCEn9sbrPIGRJmBRfeCb+kEXQwDZG49AFIYmh4kvmhHGYISTEGl9YBimPoZypvx8VJA3R5IurMcdrSTrjLuGjGJCNpJnGlCwWp6CRMLIoMCBhFJPYIAxNxjVXX83v//7vs337dnLONE1DzpmXX36Zt73tB1g8fhwzh3OIObyrp60IWp9XNlBfRtkCPqWIM9T5x+GhDIQN8/O88srLfPWrX+WWW245IeLVPvvubt49biZRMTDj6MISGzdt9i81YTjIzM/OMjc7w3AwANwp27hpM0cWln0iOt9RowruSAlHFpZP43pLJxAB68lnZuSUOXJa41tCIuQ7jYBWf9fnP5kZo9GIlZUVLrzwQpaXVzxihGHJEE1ucdlIkgOwKMncj5Ds0SjfZd2R9re7AeWkGOFUhuOrrd+jFDPMEkJ1XGPhxdY+cRzZARPJfR9Jiqm/P2wONKHJwJRs6jt0Su5nWHJfQj2IYBQIp14xBkI47OE/BVyUFI6/KCk5zJOSGY1W2bFjB03TrOGtzQyHNKNRnTGQghWjWInxGI0phvtyNOZg0GAU86hmlMYw9c9qMYyCjgpHjx9ndmYD3//Wt3LPPfdM9FtUlYGqUko5IbzVdUi7WHw4M8vc3CxzczNsmnejq6HSphSWVlYBWF2ZY2Z2tt2tuwuw/ruUwszs6V2vuxi6TlYd48zM6V+vC8/qYqgnZT861Y+dP/bYo/zoj/4Yo3o8u1PgoVRJiPqJBRkRo6C+oxchSaGIxC5uJHEfwDdqN3xTg+wRKXd2EyRIBppjy/fLY02CWCzTxuHX91MAEfdPNJESqBopFcwyJurAqg3jWpx6DqkExVIiNwIDQa1BAWRAQiE5XExJ/URCyQgFIZlB9rk8cOAAt912G/v3728jiMOZGVQDEShoSUhuEM2U5CecFHWIGbAzlwZJghRDs0AJ2FVdu2wUMxI+XyqFpjF27drF0aNH2bRpU7txt455fcjVuCrE6Ds6DkdW2bF9C1lg49wsG+ZmOWfjHNu3bGL7lk1s2TjPpvlZNszOkMTYsW0LWvSEHbhraDu2nfr1ztu6haa3uLqn0qhpOO+0rncOTWcy+vmMesLVxVgXdimFpmligWbmZgZtLN8vFmFZbbBGHfdSwo9whxot8ZAdMydzTG9aUDGKGlZ8QaiGU6wGVtDSUChIY6j6gqOBTHPScZj5qVHUoAg0DaYlIIWhlj2qFUhBDUwLNH4tMCgKZqRSGMwO+PM//VOGgznPe2jDYGbIvfd8g5mZAapCMcEEv6cK8RpFLLFp06Z2Lqvt7dmzh4cfeRBTQ1E04GXBEG187pLSqNKYbyBm0IQda6MoDUbB1DwQUvyE1tJgKFqM1dJw6Z5Lefzxx1vb7B4EqbtSJjmmXYjVNIXrr7mCI68dZmaQmJ8dsu2cTezYtpkd2zaz9ZyNzM8OmRlkjr52mBuu2c/qaHRCZGcMSxpuuGb/qV/v2isYxfW6GdFqtE3TcMNpjq8mGbs+xyRSX520GhMvpfDC889z7XXXsdKsYMV8t7fA3ChYJmWgGKkIlh3SWeQEwJDkp0UJKKIioGNXW9R3PnKKEK+E32BYDlxvUMTQzEnHIREQSCQaMSRn9+dlvKOmMUr3aFRKcco43JIUicWU+G+3fYHf/c+/x6c+9R+ZGQ6ZmZ3jtz/1Kf7PX/vX3HPvvTHaQsYgKUnFo9C5oBirKytcdeVVvPjii+1zEBGOHTvGxk0bfXGabyxGQ1GHmaYB4YqRLDYIIXyw4vDQ/HoJQ61BTHyPKeZ3aMbxhQXm5+dPSDCaGamPt7pQZRJL8qYbrmP56KscPnwYEZgZJAbZ/5sZZMA4fPgVlo++yoEbrqXCtq4Bdv2bm9/8JpaPvXZq17v+2hNgTXcxN03DzQeuP+Xx3XLg+hNoGN1Togsxu4umnijPv/AC+6/YTxlZZIo1YJIf5yLmBpeFMhCwEg67J8QkVacyRe66eLg1aRtcUVFSgmzFsx3uWSKSkWIUibiSpcD1648DMU/ggTvP6r5PskhrmEMfRFEJKBcZfJPkjq4nQTA13vk338mHfuJDfOXOr/J7v/t7/M7v/A53fvlOfuqnfoqbbjhA8di1/2nZr5kU0YQlhz7XvukannrqqTW2snXrVpYXFrBmBH5+OBnA/CRxP0NJVjySZoo2DrLcbhu0eDTORONnxde3FUQLqoVmtMreS/fwzDPPnOBe5J/+6Z/+F/1dvZ9V7BqHiHDDtVdy51f/ktVRw9ZzNpMkMRo1HD16jAce/hbPPv0k/+N//941Wcr1CoNuvO4q7vjKetd7gr/3t98zkXJ8QpTJjBuuu5IvTxnf/Q9/i+effpIPf/DHJiqO9EPX/Yhd9UuWl5fZMD/ProsupJhDBEniOzaCWMakuNMsjp0znhzTSv0wRbL4yYCQyWgliJhTMzKZRty3cNhDJNgMY0ACz66H333ScRSHVSnCrZbdfzFpc4okFLHsvkEkBE0E6YSPfXxQrHDF/suZnZ3jttu+wHPPPcv73vdefuiHfpiVZrlNbLYJy4Hfm9uSn4jaFF47coScUuvnbd26lccOPsa27eehxXd/JO7LQAZgJRZ84+epZM8JeYwtIaKIRZpGxXNFLTvMIuye2LRxE48++ig7d+5c48/KPffcY5O4+11nvOsj1N/Pz2/ggYe/xaNPPUcTGHc4GLBvz0Vcc8U+VlZXpkrgTCrPrNf71pPPnnC9a6+8gqWlxTUOUx1T/VmfGbphw0buf+gRHn3yudavaMe3/3JWVpZPYOXW+6vX7CYcu9GUpmm47777+OAHP+h4NxYlSdr8gOGOY45TwCpIsRQwxkjqxi7iECCJY3MBj91L8viXKSlFrN7iG6SyrOp1OaVxEAlB1EPFyTzSVCkjmgSp2XGNPALBO2kMy0JW8YhW8VNpODvLp//g03zjG/diCDfeeAN/+8c/yOrqClgOLpZgA8NGKU6vOI0QhMzK8iL/9fOf58orr2QwGJBz5v777+etb/l+jh096rAzCNApbhMqRItTRVKHGBmcF6CYkSUjWlr+pNNrIodiwlNPP8WuXbvWJKoHXew+GAwYjUYnxPS78d9q3EtLi+zfdym3HLiBuVlP1qyurPLakSMsryxPrNfuhnL7hLKFhePs33cpN9/4Jubm58BgeWWFI0eOsLBwfM3i7BrytLrlhYXjXL1/H993043MzsyAwMrKKseOHWNxcWEq6a3PzO0nSFWV0WjE7OwsMzOzLC8teagTQ5w8FVljZ8B6bD/Ig2YkUaz4I1Tx06Sh+E4cxuIZcHdAU8Ak0+T2ihtWzYSj1NThScfhYM4dbne6fVcV8bCx5zpicanvvO2qix+bepSrFMgizM7O8h8/9Z/46p1f4f0f+HEA/ugP/5CVpRU+/KEPsTxa8XAxhpRUM6C+IFViDgqbNp3Tnso153HhhRfyyuGXyGmGOjtJxfliqYbFPX+hpiQKWIoNB1CFQYrTsqGIRLTKT+xk0ChA4Yr9+3ng/vvZu3dvaw+D7mmxsrLCYDBY44TWf3eNsJsPeeWVV9aVdekvvm7Uql88tLq6yksvvzy1sH+aSkh9NU3T+k0iwuLiIouLi+0J2K8zmERP7+Z2qvPdz3EcOnSI6667jtXVZTQZ0pgf81KZrNWgAuNWrlJSSolEWPL9WqWGOt2eJSlaguJhvusnEc/yV0ygRkkpiH+QRSnCScfhnCl1smM44BVIdVnBnnFOEfpMiBVUnMxYeWFZ3FP6/z77x9x5x528//0f4F3vfAdigpbCZ/7wM1yyezdveetbnL8lCbNC5cAUJ7d4SFoSS6Nlrrnmap555ll27tzJcDjk3HPP5eDBg1x2+RU0qytgQol5dNaDopactoLFCVyQLKhCSua+hQTzWD33YwKpcUaA/8ztbBRRs/bk6OPsLkTRoHj3C/Yn1Rv0/ZJJBSarq6troEr3c/XPmvnuQ7FJmfu+sMAkI+/WpPQTndMURGqCr8/6rD8/dOgQ73nPezh27HhEYzzk6Md6pX8bFbAIhonDJKhoxWLXTwFp1NdPY8EgFzT8Dv+AOwbOrjWPgKXKbfLo1CmNo15HPHFmUhgTVQh+lOOWLM641aCFWEtbj+cgyo/+yLvZtnUb3//Wt7G6OkIwfviHb2Xnzgu48c3Xs7K86idNzTGUoLlLxUdOiMwI1159NX/5l3exbdu29jkuLi4yPzvL8dUVSoNDtDjJLKBRI0YmkqXOcEQSFI2cShKkLowSSUlLkU+CZMbi4iLnbt/O8vIyMzMzbkt33nmnTaqK6lZx1aOuX7vcx+yTanq7MKpbfNR1quvu3F8wfQp5d7ev4+v6Al3o0/eX1hMHm1aLPEl8YWFhgZWVZd7+gz/IatOEPzDwya8bdXLoQwnqglR6OBFNcqhDOLbq22dEIiM513iUR8woyZ32XJ3sFDukuPtSKhnxFMbRJgZjx0ymIIM2CWkBO6xS4FNk7cVQC1jia6UNh1rOfgKotgnLFGOWDkFRTZyuUmodSaX1BNoYCF+548vMDGeYn59nZmYGVeXwK4fZef4FqFkEH2owISElnil+X77Ak/PQLBYzYNKQbNDys2rEziJQkFDO2bKVu+6+i71797q9dxNp/d247yfUnMC00Gw3kdNNltXPTitb7VZ91YRQn6zY/96+L1TDq30nvY6l+2fNldSxdU/Mfji3C+1WVlZ45JFHeOtb3sZodTWIbL4raTAKa8UFxTlOTlfxZJRU34DkcXuLRG6p4VdAszu+QZZTBSkOY6zu/MUJWaYRTTuNcfhxlaIOQ+Ik8ARhqZBNPOyMJFLkFDTGX0wpJUCYiI+ztaHY7ASsGRuemS+iZCCqEbiKMKv6ovRxKbccuIWDBw+2lBIR4YVDLzAzHJLQCF1bhzZSPKnZEjiDvqLmi5sCyfMeJpU640466uPT5Pe4PFohDTLD4dARQ3e3rYbdzRB3F0mfqj0pD9CFL12sXiM+1ZDrd9WfdSejv+C6pMWukXezmv3/uhCpe63uoqvjrYuq6WHOetp1v3N+fp65+TnMMpTShjOt3QE9ROvYPI5/83oKlRL1FIrzNSRyAJXFamBNLexzjJ78mqq+YFJxACZ4dvB0xqFBFycpUMhmlBw0k6CxWnJDdlqKnwR+gezcrmD+WkR+tN1/jUJARRM/tSg+1mSU8K80KCGkgiEeoFAfkqkyt2kD8/PzLVlVVbn22mu57YtfYLUUNm7cgBYfmgUb2BduHJfFKBRnAqRIXBZnKIuCNMWTirFo0eKUEwEdGcuLy2MbuP32260LfU6m0zRNm3Q9XdZazDIajRgOh+2C6Auk9X2e9dQpJtU+96HSYDA4IYk5TVh4Te1w+Br9U+PFF1/kyquuYu/eS50KkiQoHtLmCHJEhGosnRrPD6IgOaIl5rAJ8YSYJoWSUSnk5Bwqq5gjJUyLR4tybhm8vkA4rXFIMmiEkqSlswseyclSTxL3XzyRCGLF5QaiZLZSw2t+JuHObaJuAuo8KLF6i/V/Dgu1pk+C1hEOcRLP8D/1zFM89NBDnH/++QyHQy91Hgx44IEHKKUwPz9PaZq4txpVq5WINZIXLoJGwZa4RyZtrNzvQVGSed3LzOwsKQm7du0aEw+7jmyfaDiJRtENuU2Td+z/vMvd6i6++u8uhOpHlyoEqousr3LXvYd+sq7eU9c3miSjWRdJ9WO6i7DuYIcOHeLHP/B+ji0skSWyA6kWKKU2x13LUn3HcuydUoSjgk6NJqwUkNziYMtK1hTwSONKvggk+WJJgbFNGswyScopj6MN+yZjkEAbQwYNlMwwfKKSPN8S9u9JNcmIRj1HkByliEfGRoKm5KzxONMkxpCjTEDw7L1FWUESpWgIX2SLkoKoGMzC/iuu4Mtf/jI7duxobWJ5eZnLLrusjXh2Swb69tO3iYpQuqWw1fftRkyHw+GaIM2gL0ZQv7juntN0nLoZ9a5D3GXdttTfyHr2F0QdcH8xdk+P6kt0F0w3RNyv0OtH37rXn8TA7YsorK6unlBPXEphYWGByy+7jMWlZa+YK8kd5sDqKejfRkNmgBaPubvwgNKUQYxRIZnvxil2VC3+WREnFOILysSDrKoCNAgShU/J687l9MeRygCNYqriTA7PyquzcX0z953fiIRMtnEJbQ7elnrQQHMhaaIBp8cHLPOKkUqV0VYvQsy8ZiVqQ8Tpu2OonmBlZYX9+/dz5MgRtmzZsqaMtm8bw+FwzabaZ23X1+zs7Bok008kT5JYSl0j74ZtR6PRGojV3fFreLOLxfs+S5f+XXfe6mtMKputi6DrVPfpIX1fon5n15/o+g2T9GHrOJaXl9fkbUoprTJJHWddwE3T8MQTT/COH3oXpSmRqnP6tyexvKRUUMQG7luY1GgqiSF5UDynkSzwdZSamkQxj4dXsyWyQE7uvFrUwWrKEIVPOqgV36c/Do3TS6VGsiLWr2PlkAxYKo5zaiYcozHncGlAGEsgJUUdObhn4ZAmp2Acx2JHpBO50tZvMrE2ny1RHKXA277/bRw8eHCNXX237Sd1C4e6cKceMd2sdI3ydJ31SYXsdYDd1djdyfuwqgt3BoPBCSJjNRFZrzccDtes+vWUUvqJwvr+4XC4Jsxcd4+6+6SUGI1GHD16lAcffJD/4e/8HZaPL3nVWXCSPLTpLB1LbqopZGsQT4aliB5pyaTAtwWQQfAhtJCDqaqRlCtBabBhwnKJIiOLTDfQSOQrTn8czsNIHhUL6J0HOGwzJxUWEZJKsDIEy4ZJ9ipDrUojGg67JwuCKxwejuc1LIfJB8YXEY9WRZGXImQN1i+GpuSnWTGWV5b48Ic/zNfvvZejR4+uQTffLfuR27/0pdhCiAL6MUmM4J7Uyq5WmiU0kmqEo2oj1Z9JyLVU3GqRFfU5Cp+ge52uDx+7UJ3kVgFJWPO++pska+Vqqq+FdcbT+S4i4tJqRdXQUCSU3JeTljM1HA64+qorWS4N2VJ8jQYBLpMoQUWHAUKDix9U+ptj/cBI4nymAEvxQBwe+XXjHlJBtdIQ05hwh6JZSPo6xtFm68f3i4IFnZycQhBhnJF3H1yD4hIlsCpjxq6M6+NpqTIhAySKFKfiD5K11A93xI0qFlRTqV42HLkhEyQJDz74wASxD9pn1SGutQteqM+acRBhLBI2wZ7Hw2+t6/lDh2woQhG8drkaazUUBI00ewpqDClR1EXGqiZRq2IR0jE5HM+avZWITzsTMqInEb2oC0BDoCxJ8IoiopCCy+OsS6c1iPiR7xFFI6dQvqhiCjHlLfwQN6Lx/Xssp5iQrBpK5JJbdqrXSYiF1kegDM8ZBDkvplIl5igHLSMoH9XZFIOSa2WdeXVbZGpdWMfxuVRHH39fLFvPVai87nH4JsDaZ6WG5SBFVl6X1PmHsV5QhEQcCZcsAAAWiUlEQVTN/3S+VfIipBosE0FLzWRnf1Z4Vtp9J/WAXcpRvBVUrprIi/vGxpG2yOWf5FkJRdx+Bh6DeN32nCRKFyV2No1Yd12ViguMpZRiB/AEVor4u0VM2+LYN/Hj2LO6cXhGFVjoVDjetnqsBMUnDuVURS1IpOw7TqP12K8Lw5Nm7vA5dUDVs8MSnl8hwpKhzKfqIgWu3RScHgtjSw4l6s6SgtWKuhqHU9OkzbYWMyx1ggPm7FZJyZ1UBIsyToschguG+HcXxZN+kdmuQVdNJRJw1jlVtS2W+k6MQ8W8bDcMMhWjSfgmY8Vza6o+P8Hd0wjFWlQG1mNc8OfqGWev2WgipKzqBuf+T4kyFB9f0TzOktdEqLoWlpl4HQaN86LsVJ+VeaTvO2jPg6B6erRDIIdR13oD/02s+uQTSJvrdfwpUTBjA2sTR9IINlCkyWiuzM/sD0DMSS0mTkqzhKbiANpo2aClEXLc2LhYP7Kfgb/rSSvWtMk2y7G7hbSHVUigtcjIKMUX60iEQQOWa/DU0BIs2ahRdqLOd2aOihZee+UwRYsbQ3a2qmbIxb1hC1U3oQ1ZjRm7GnkFEXKLIYmEn4zRRYp6kXofFYIEydHLB4OK0RmHf5eChOYVY2q81edWhdrCc3B4GBC3as3Fs0rFoaDXllQYowEVfcMiiJh10Yt2TqzkTGE/GeS7OkeDFD5CSfFnOFxSAjRKwKIUxklGvC4TGRSk8aIXk8bLO1NyxuQgao6roYaRWlSEWZhiIlFaAw+tpMANKeHx8Ip5Ww5NPDj1YnpPPDmFuoqMWRz1VfAMgvgnhpVwxIrn5Er2IqEkvjMnySjFT6SUnX/0HZij44tHWVkdccnu3Zx9fe+/Btr4DuvUBW1hjiTfL1IpNAKDyNiqFefN+Kbv8Wp1LaVKoSdi89Iq7/lRlc0jKJqsfW9JNi7cJ3mMPRwlrUzTtoYldokorjZxcKniO4e6DIWvfMVLSXODufU7wcE8yVZq2FDHO3xj1SeSVr0jWUE1ofL65shILC6tsG/fZW3M/ezre/uVkBJVZo5HCacxyDruuJkTzqzSHrK4WFqFKWLkyOWk6kTWLHllZhYP3UXZekRliFj4uHorBSFMzOPdFllaB8w4F0Y8sqJVXdzEaxnCaTXxMkpxBVn/uqSh9FcimuEOutQQRUrOdkU8vBo+kNcCvP45SiI0zejswjiTFodLODaUCJ21YbzgpKSICnn9rbSliCYRprOE5OTOoLg2kJHIUQYq2aMKOVVpRtpoeKoymVLpy0FbSA66UjinxRLJ7RfLGUWcyyMOzCLC6pg4uUaTmKDZa4fropFU2miNk3BaXgdSwqlLige1amVdcvr2654j9zfOvs4gWEVxVW2rNc2iHg7P7qiJiDujppTqtBSw1CDmcXRWidqA8LOtuAYTTlOQKOUZkwIrv8ZFugbqWqzSOulxZBQNOU+HLSkcNi3GAEHzyIPDGkxRF0cKCqpiKaT7i7rwWBX6ipNINbtoQHJGJjmFbEsVFNOWkWq8zjkadRzDs68zBVa5wQ2DgpAkObOsRFSiCsdJxdgZyKHm4OFbBhG4SZW373FzHUR7lKBGWIT2UieLOtTIaUQtmvsblT7txDUlkzRXIqUnk5LnHyQWBknIqDvFklxVQ2sCLBYdCcmGWnJJTvFQoRYhDYKBKhGxyQRPKLVhz29njlxMwDVaObs2zjBYFUmdxqzF3yI1l5DaTKSiaEkgrhhHEmaGmc2bNjM7mHF4o5HOi2qvXEJu3/DC/uAQEU53FokkWxDGUtVX9TLHpDkUx+tWPBYTm8kDl6jJngjy/GotAfUQclRTen11VMah47BdUUgpBJ6DFaCUEAwzJGVmN8yxYdM8m+Y3QM7Vg4kkkTE7nJ06R5VHZHEAnV0bZxysiqysefioiDCIWmQstbyYZMllKkMndX5mA//3b/w//MnnPsett97K//qz/wuriwbZd+IaXUo11m8pdFIjc12MJJGbiOIUzFzvtR1P01bOEUS9lDOPPPQQr7z6Kju2n8cVV1zuSStxaUxyiCfXa5iHgEuQ5VxCMORhUE/IVapQUGFTSqwsL/E7v/uf+eY3v86RI0eYGQ65/PLLee973su1N1xPWVnh2OICn/+jz/P+D3wgAgedOTJXRS8mDCIjXSkjZ19nCqyKrKMUT+J5mt4CK9MamAZRKhnMzczyG//2N3jowQe56aab+PrX7yUxJCWLCJLDnMoZwlwNIqc4naQySR1Mlcp5CQl8SSn8F2lT+W5YnpRqSmHvnktJOfHoY4+ShkFYyzkSSNYqjbcyXuKEEq1Z+6iuz4RAcpw6szNz/Pmf/lf+3k/+JN969GG2bd/Gvn37uPiSSzh+fIGPf/IT/Itf+iWOHDvGRz/yc+Q8OHGOYuJUPNTbWGkTY2dfZ9DiKADFG5aIppYe4KJi2qrsIQ2iwuzcLP/+t/4D9993H9u2bUO1cPPNN6Ml5F5qWNZLgl260Wruo6qMp7arllrxgFHtHyFgxeVUUggwN5W8KL7INm3eiKJs2LQRBQ5+63FyErSx4PxUiFfpGR4CdqFwRTUFT6j4Yo6SycEg8cd//F/49Gf+kBuuvx5B2LZ1G9deey2X7N5N0YZ9+/axuLTEz/7sz7Jnz+4WgnbnyKNmrhiokS23s7DqzINViaalbZQcNGXR0AbKThxIgllhbm6WT/32b3P3XXezY8cOzIwtW7byD3/mH7K4shzdiYxG8IRfKzwfLMiiYeAaxfnFI0ollMilbY4HRaNqLXnmXDJWCkVgzyWX8sSTjzOcmWPzhs0cOX6EJ558kt2790TysJCCJtBUVTypQoBGyRp98ELmrHgTl8OHD/MHf/Bp9u3bx2g04qMf/Qh7du9meWWZLENKafh3/+Hf8/xzz3HFFVcE6zeoJDFHLvDhVBlVF1FGcoSlzxrcmeVz2ABSoYTSRAlYoCl7D4eggc8Mh3zmM3/A7bffwfnnnw/Azp07+djHPkajDefMDUNhI1rwBllNVVlcWvRdNFid3quCwP7aGo5ZioYr3gekcnA8cqWklMMHSly+7woee+IgOQ3YumULh189zLPPPsPFF+9qWxRr66iH6oc60SxriBCrO82ShJQGfPozf8TevXs5duwYv/iLv8imTedw7PhxhEQjixxfXOa+b/4V5+04b1xGGwVHqXK7teZSSnTZqnUTejaSe+YtDu82mkU6HYEyYh5gFVNSHvC5P/kTPv/5P+Oiiy5sDeOhhx7i3e9+d0igyLgntYybtm/cuJFf/79+nXM2nxPKEwnJ2tJKUu0BIerZZIWmKdx11x1ITuOWXLjgGSHfLyS2bN3Cls3nUFTZunUbrx0+zPPPvsCFF1zoY8rR6kqcqGgaogiR6fYwrUfWBnOzPPLwg2zffi6X7buM7du2szJaDSq28OLLr/LRj3yEiy++mKNHj3p8S4RmtQkWLeHZV3GxqvAXGFNbZvnZ15myOEwsIq+1j0EmpdKqSKDG7Pw8n/7MZ9izZ8+a6r9zzz2X8847b90vKKXhi1/8Eu99z4+5+28lEhgS7EpXscgpuzyKKK+8dIiLd+9hkMQ1YtMIs2FIygS1pOo6hR9hZLZu386hFw6x6+JdjJrGe3lHEZEnxx37ayTzarPHJmU2JGNpyWVZLrrgQlaa1SBOehRr1wUX8NnPfg60RPbeN4Dl0QrLxxfbXuKo530oNm4qGYIHdhZXnWGLwxVhnJEq4lDDosREjZShrK5y1VVXsbS0dNpfsLo6YveuXWhxDySJdy8ySSRV1LIr1WlpT565jZs5fuwIaWbW9Y0sk5JGHsPFYES974KKMDDH+0X9NGmaEs0nvejHlFbqsu19h4euNdiBRYW5uVnX2F1aIqsXz2jxSpOl0SrLr7ziaRJlXAVnRm6VA6tgW/FkYuuE51pOefZ1Ri0OCrkMKGmsnySB2ZNAo0JZXuEjH/kon/zkJ9bUY59//vlcffVV3tpM2sLTtrZPzNiydQs33ngTy6tLkSj0uolkng/IOHFPa2mjGlu3biJnf2+tx0gdSYFg/XPs+AJZ1DsUkVhZXuDSSy9DKYg5M9ijYt4FqaiQcnFNpWxYyd5ZVYSiDeeffz5NU7j77rv50E98iIWlBVqhm5JdtsYysxtmKKPG+wCKK3VX9JSTM38tNFqrOksKn+fs68x5ydPPPF116sPochSF+C5emyFIRGQ+8YmPt7W8zz77HH//7/8kb37zAe+akw1TbwxZBbUV7yCkVW81HOycDG0kmh5KW8stVVM1VUHxCO9aFMvgnKnXXn2Nlw4dYtu554IVFldX2Lt7D6Vx/ydngvIuURIqQYyM8leSJzsju52ScMcdt/OlL93O4uIiBw68mb/7d3+C5ZXlqGly3+uVl17iV37lV7nxxhv4n/7B/8xoZTWKZizyi937SO6UR4vjFw49z00HbjprdWdKnsOakFUxjQ6exYnehdDmHtdooIWPfexjlJDc2bXrIn7zN3+Tv/rmN5zuPYrrFHXcrRaG6Ht+MYNSEFXKyHMSpp4LMNShkXmyT83afm+VKFi1/I6+eoRnn3uGrdu3oRiLSyvsufgSmlGlo9decNCkWn9hjKJGo4QAcqNOFUmmFFPe8a53ISJs3ryZ2277Iv/q4/+Kl156iY0bNoHC5z77x/yjX/gFzr/gfP7irr9kNg+pnQHaA7VoKwEKhjVB3bez2fEz7uR48qknLJNbdQ9LtaC4qkDUckZvmSXJM9Sf/OQnWxmUgwcP8lu/9VssLi4g5CASWtCVkq+TWmgURfFAiHpVXaZg9YpHtCza9bbyjeIwaSYP+NrXv8auCy6ClFg8vsieS/d4F9bIp2RxkWLNtLXX0Zpi3M8uKPBaO8DEybi0uMSv/ZtfY252luXlZR5//HEWFhYYDAZccsklbN++nYWFBd73vvdx0803U7Q5YY6INsaVGZ+Sy8+8+PwhDhw4cNbqzqSTo2BRqFOiFtuL8FMIFFA0+jQ03p8tZX7+536e5RWP7uw4b4d/Pqjpg2gmoqqIGk2IhlkqFINGjSZOBFXvEJpKQa2BQqhIBPtcFGu8GaIUb86+aX4TBeP48aPs3rMbbUY0USCF+omgRKticzHjohpL1JeHJqUpTl+36HmtpmyY38A/+6f/hAsvuojRaMT+/fu5+aabuf6GG5ifn2eQB/zMz/wDvu+W76OUZuIcWaijazFUCqWRXlHX2dcZcXI88eTjZpJoJYTa5iJjwYFKwo7MhwscZKGMCnd/7S7edMONbJyb94hTkii2DwVwAaxBZNCWt0rkARSviZBilARZw1hTLcgfh4UsKvEkpPEXFo6zcdNm12K1VjmrrfKr2lOefmg1WECdS+b6JjZuqFgpLHhgYn7DPMeOH+eRRx7m6NGjzM7NcsnFl7D3sr0cO7rg2XCxqXOU1JuqJFwsLQ0yh154nptuOutznDmL44knDPHqORt4Ew/VHPUXIeyg4pSLUK3TkHMPcaiqTeFwJVH14d2g1ZyqHmL1Xq0aelUaurBZooVCrdgLmJNrfTmtTlGKL9boA6HiDUwkh8SPiod9XUCD1EQ31VSbqsQCiSYsYhJtvdplBGY0SRhaFc2JTqbqQoGCYqc4RzUhmtOAF188C6vOLFhFzYr7jq5BIdeooZBUQg3PXD+1lOiyGBhe3dFurGqQatvpE6JKLjXeQ6HVEKoOdpwQxXMY3qXHG40UDGk80lTEe+URkvtaqScWPSrCnyBgVJXsMUtobtqGj973O8iUNCGr0zj3KciNqr7gBhqkkLZ3hYXBW0uzP5U5MhOn47SaT2dfZ8zi0Ej21cahRLzes9niESh1yEEJdZCIHCW1tr2UiF+H6Nmg0RWxrbQTV6zTKmxEkPQ6X1xlHNUKAwnZzuR1TqUEEz3V0m9DdeCD01Atz3jVYTSalOLYvwRd3YoLOlSVESxakdnIGzhqRJWiM5IFrUXR1z1HVb3x7OsMSgIGEhmTG6L/AsGXkoznMGosn+QVdC01PYWyRwqZ+mjxS9u1xHddBMvFdYdLaRuyCDky8jXWFO1QrLiUTklRo+Rqikkt1MktZEejM1UIK9RbkFQV1r1iRC17UZVEaxcpURUYcEqhiPsz0nj0rKr6IfK650gH5ezaONNODqnE1xAIIKIsVVXDosmIR1b94edsnUIoGxtRLm1OoVXwVWtVDnNTF03VeM1eUpqsbdjYRKKvsg0zDmUkKSKlI1Zcuw+NW+VWX8ePIRdSbheLjFwNBD8NBiWa1BOOe/gG5rMShUoBM78Dc+Slv+msxZ1RPkfoQbmYQY3qgI4E1QYzx+Zq3uAU9SyzVawfjd2LetMUxXtEW/SK8B50OT4T6iMaHY5QShVIEPH6h+TizVWlRIMoWFTRIjTi/kkJyCYWbFtTirijXlXNVUucHrX/t2vrWiNOlykuueNhZ1opTO/zEi20NNqhvc450qawYX4Df3XffWsoOGdf38PRqscOPmYpFG1ShlSyc5kyUQvurXSlNBGFicBU1F20WlPquk2VLlLFvzUUsVPrRIdvUCKqU6nudY83acNg1tK9MySvIHRIpeTk6iWErGfkMaM/orcPQ1rdbvdtShrXkVeyjCilqrkXVzqR6NtXhcorn+t1z1HxnNIrr77KyspS9LUIXtkayFUZPbV1g7WdWaPXfCsKYViwVySawXTeYIzJjq3av7Tq7bWPNxEKr+OQWrIs2p6I1umjN+011oSvrSfCyOrvpBaGhSp7R4e3+px0tXbbga+9le/WHMljjx70pHg4qSqCyMhLSU1c87XqzVpoCIbUjSuXgKYQcDbI4vKZskauvmrcgmhGJSRzglflSt/RtsBcMsc0t4TDksbibN4ZKSrwxJCiHnatRVFt96DIrkdttySX1K+ZE4v0dTXmFCdUFonmMcEOiJyMiLbq79+xOZJOo4ToAe6+j7WLX6r5mDe7SUGt8QaQHgk0Fd94skb9irR+XKp6KTIOr0t0lR1InKhrxkGba5LiRNRstZeGz1OTooePpjVtjMfPKuar6kNXKqq6ovugfVZEi4BoU2AaWsUhB0vQ1uJ5EJWX3605annVIkKREp1Ds3cBjRZZIeCHiIuU1V3FzBscinn72kQJ/K2RSIwFIJVHFUVNRNutCN820SvDdbAij5E1yIdGrhQMIWTjSyvCTU7MRqjUhZ4tdi6NZF9oZsVNSLZxf47sLYNTZMyl+hrRMyKpRueMyHN8p+coKqBU1GnuGCWVttNq7R8jql6LbnGaRu9AojamCm1HcUtUZDZutBqSQeoVj2hBtbgGcJETx4GXAljxZ+bs6WjtXIxRSLYq6gvDAqKGwkpSIoEM0gQnwSo1SZgp3tO8RBsJgnemMVduG+NnpbUeJ/Fdn6OBVme0hmKJTp9tljlk4iWq8qLfRirxuTJuQqPRJqgemVrPqugYlELbqf62WHSASuIdf1o2cNDMq9+SQqbexp2anKBo0fsiGMSR3EvW0ERfDRkYTSPef1oEHakLrJVEoYE09Aw+CVd/tKCwZ3IqSBn4Qygh+fnXNEeSBt8T4zj7rMZzNPjKV75KbbLT9idogVhIeNZjrdvaqsrsmESuo9Mjq6NCMq61DvwvXdzr35GihUBtKmNRm60hNh05OMfHMZQkqdN2rYtvg9LRJiSqhm0kO10BoZUBSiYtDBtLhNSuFFVwOnlo+K9xjhLfG+M4+6zGc/T/A8/G/snZpSWJAAAAAElFTkSuQmCC);
+    display: none;
+  }
+  #chrome-mid {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAABICAYAAADRa1RpAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAB3RJTUUH3QcNFycE5v9iFQAAAQtJREFUOMvtkjGSWzEMQx/0eYrM3v8k3vgqycalSwlI8Ufyl3OBFMtGIgUCIEd6PB6RBEASqvfONSrJXrDNbNkQ8ywA2y/SmayW+ZIESTsiyQsxo40xmMS2aUmYbheHpCVd0+UqJGGMsey3mUyldoUvlY3D9rIN0K7Wbe/WbZ+y1yWtaVtrp3VJzAEX6ZVjc2p7b2mtnYhNdl6m05rwtfV/ltx7XypJTpXeO7Y5juOlchzHaWxyrJmuhLapqgIJONv05+srThBgiQpBTSRwGOr3rwccgWHUhJ7P5/YNlbd/2XiL78L/WajP240AQUihfnx84EDJjCHKHjTAbkimQDgBjAJ1/3kHAgEk/gL71AHEWVXPGQAAAABJRU5ErkJggg==);
+    display: none;
+  }
+  #chrome-right {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAABICAYAAACaw4eEAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAB3RJTUUH3QcNFyghKmOqnQAADE1JREFUaN6dmsuyZsdRhb/M2uf07bREYDykPeIleAMibNx92i9BgEPBgyB5xlvgtgI8VDNBI41xhGkpQowERgqw3H0ue1cuBlm1T/3Vu4XNiWj9l12XrMyVK1fWL/v6668lCXdHEt/1Z2YnnyUhCTPbX8dn45pmRkR81z7/XUr59Pz8/K8ePnz47/bVV19pnDhu0t+Pmx0Z+Pv8zWv1/eZnZ2dntw8ePPizZXw4bj5/P3vq6G/eePZiX9fd9/Xng6/reg78/dInzxPG9+/auH83GjEbPUahj6m1Hoa6v1/X9c+XPrlP7INqrfuru7+10WzUkUHvOtTojPF1mPdHSzdqPPXo5vm046bdq0fhGr+bvXZk6OgAM2OZBx7hZD7hnCzbtp149Wid0YOjx+eE6t8tMzb659Ebkg5PPY8ZvXpEQWNCzck2M4H3BWeM1Fr31/6+GziPmTefM3tcYzQoIt4a3+cso2EzhsYTzAAdw9M9M3rviPv683dl/Oi9pdZKKeVk4piVRyDu1NI3mCtARFBKeWeGbtt2yHV9HXdnGUMyGjSfZq4K42ajYbPXx836XjO+jsj3rawcFx5dPgK8bzJ6eGbzI8yO3j4yaMToiWF98fl0c4bNSXBEJ/Ozd1HSEY8BLGOIxlONeCqlnHyWtGNoxteRMX38uP44fkyyPnfpp58zqy/s7jsGj0rOEcvPVaMD/sj4I/zWWllmMB/VviOwHumv+dkRGc9EOtOUu6fHZteOGBtDN/+NeJwPNRsxl54RU3PIO4x827a3wNwfdr45kib92WhAf9+fHem1I7FZa31rr+WIr45kzrjZsixvZWHHYcfqXFHGctM9ta7ridcigmVZWNf1DvyllN2wkatmHIxCby7kYzbPOD2qFCN39efrut55rE8YM3I+8VENHPFVa2VZlkOSdXe2bTuhmHdl+W5ox8T8YCbD/l2t9YQqRiNGjx8l1JEamVXKri56doyTuzfGhWd+OyLJjsNRlo+eHaX63Iy8ldnjQn3hbmA/yagGusfG7JwrxZytcxMyjpnH77VyPEEP65iVs5tntp4ldp8zlrG+x8z2Y9L1f91Jy+zeccGZn0Zv9nFHTH500BGbM6HOojMiWEZQf1cN7Aut68qyLCdeGFN+xuRYJ7tXu5fetU9EZCiPOp8xm8bTzLqpe2jkoDnzxjCOa8/VZByzzG7t8gQ4eT+GdO4Be0kZDTgq5kea/0g0RgS+rushNkbg93o6aqeejUeNR/fcUWmaqWLbtn39MdGWGcRHUrcb17E1jhszq3tvxNCsJuaE6VGZMbeMKTrL6LGelVL2k41jx6zuRbknSS9BI7WMdDRTxLi3z+VkDl3/7vb29oS3xhoZESdZOm4whrW/7/NHT83UtNze3u6c1I06Ozs7wdjc7PaQzsV8JNSOp7k97IDvtDPDYTdsvts6Pz8/MXCsm2PD2g/Tm+Vx0bHZHTNvjMyRyh2pajk/P0cIZEAHLLgXQLg5ckDCAFsKCwtIeHHAQGAmSnEkMAyZMBkin4lc3jBEM4a7MZgo7mBGhLD/+M1/qiCqDJflIjICYbknjlEtQEl81cBDYIaUi3aDwoEQ7mABuFMjcHOMQHLMRLSDhhlFQk4+k9IhLggZBREeVLN+NNwNCAhRwjGMimGyPJlA3owyIwiKEltWjTBHNchIGpLleIS5ITNKQHVDYRiBGUQI/83X/0XUyorhm2EKAsvT1IqFgwusgglCWARV3SuGmdNchwgiRHWQagcHIqCNJ7whJ6AI20AeUJ3A0ilP/vQJ33zzDdvNDbWkO91oAwphrah7wVGG1cHMqSHkggiwDJthmAcgjIIVg5rfWc1h2AZ7AgBLpMElMpQCUyOSX/3rr/j+9/+EGoEQTgKxKnDADRROmCiWySJBeILbMCxENVhwBISCnldm4EBEeiQRk1AJs/Y5ER2q7BX03v17SQnumDeXRqXgDaSA1cSdIExQDM+UgtoArTyMIjABJUPt4S2hRHEIgbdstV5LI4OusDvDMgMNqw3sHqi0HPcMotyRNqp5ArnmRrkLuBm4kHmjDAeEDMICk2PFMwomqjI2xYSHsJIUUnxoeBO7rdQUJ2qeJk8SLfdLGtgWCouEVzFUG7NXMAXVG1YqyDdMhSDgFuTpabUEiUguUw3AiAafbhoR4EtmpJknKArgytMaBHBmIozEIQ41M1dK7ySGEvxQ8NoI1w2WFh0XlsUaFYilJ5zhpuGKwBxXeygIqxlrE6Ih1wKPgi8L799/QGcJo4M5o9oYDfcKUZJmEFdX12zrikh2xwwrQA2KOeqETRlCGaKaUFXLpjQwy5Elu4dzflb4uw8/5MXP/wEsE6ORVX8hbVRzTVcN4ic/ec4HH3zA7XaTC1sQtZUXAm98Z7I7uvjii8+5ePw4pUiwu7TXuogM3cX7j/jhX/yIJz948gf/NPjll1/yy1/+E//z299RCGrL+AxI8krQfhk5Ab+6LmrGyDA1dvfkqOvXNzy7fMonn7w8umjafabmsDuowPPnz3nz5joLiN9VCwIqJDGHweixV59/weNHF4itZSMJbGq61kg3h3N2fs7D9x7jIdTwIzw3tCxrZo560U5U8frNFdu6URWJS8RmRukto3smv07uxwJrMa9uLDJCG1ZKI87AWJBvhEOsG9WEhSVcWBtu1A615da2kboiPaRW4hSRcBGEClhg0cTDycWdJR1XgUdkrN2hRqslGapydo+fffgRL37+Ir1opzrrJHZDAiB49vySv/3gp9zcRiqLCpsrjSLrnpQ27KH8/ItXPHz4PtRbRMoTajrBw6Hk4o8vLvjhj/6SH/w/wf/xx//I629/u9fPjkxLIZfVwmLwWBhQqUqgU1NZlCrkQVRwGW9urrl89pRPXr78gw27vHzO9dVVI2cIOYVIGHkrYXVDUQaPvXrFo4tHbFV7dnkjzGT+5BjXwnK/cPHovcRLI9hME3ZeM2+HtRwQAVdXb1ivr6ldzfYC3sSnPFAUZHW+HE7WtqamZL07avrcnYgKKtR6m/VKQTR9n0JQjZj7KqD2LCLY2h4quqsKNUWA5BQPatjAY1hTpuAO2iqlGLV1EQJ8C87vnfOzjz7ixS8+5vf93y+sFeZnl5f89K//htttw1bAW5d05rAK90awjOD//BUPHtynblmInXStyUHJR3jw3sV7/PjpU548eXJArvZ/gv/Fx7/g9bfftug4NfVKa7byd8pN9ZT5I9rFSM/wSPFXrOn5Tby5vubp0x/z8uU/t1Jx5/H9v3b3/q4YGJfPLrl+c0Pde8lgEWxN0znG1jG6e+zfXnHvwQNETdmMINqlSEeZJ1Dvn93j4uJiL+6jv8TQO9L6lya9f/fta26228wodVwZboFU2gLbqbqglZLarzTbdpvBEhWxNJI1bq5uuV6/SRCHt35AyAwPo5aKZzlIHRb5SqTR1nRSnitQtC4phNlyqvlTppRUlmZEQJizhCErbYSa57J8SNkLRm3s7RV54AHymjK9cYjUyg+wqV8XRCtfdzea+IZiFIoSsFKBEm1SE26SpXZCeDh7g9P64R4SrU2ZkC1btea5TMDsqCJ5UfUuZwO1BlnZ6tkgrWWWqjOgqhJmsLWa2dowsKZK0nuKlMWokWWBoBIeiJpZF6CqhtnMdHSHW6PdZLfijjISu2HX11dEjURrTza3BtymzaLV5NZwEGQYW4ekaLdCkXSDRCkidr2n/XKGUlOKjxc6oXZN0H4ZefXrVxQ3atTsjD1lkJpIDNEwlSCRZ53rp4zViNiQtqwEStHT1YoUOaclSY1MmmjXCelNz2Q1T5L/7LPPYDEePXqYNa0ENHnd7xeKKUFiAO2HBM97DZMoS1prMmQLrqCE8uZHIgVDNAFpFEW7BnGKWQtnYJ6GOmL54+99D0JEzfT1alRzikHtda+1/4nsxk/VqQZmlXXzJMUiqFu7nrJMe8v2LhteteuAvEcrVqk1m+Owdn9h7ZYSE6WAIrkjPCVIFua8s0jhWHfhZ5YZZ6rZNxoplZp3clg2uUSKAcmwYpgqUs1iFI5Z4rr3mliq3IVqVDbwM9CGkao1rN1IR6F4xepCEFht1wAhIKjRNH0Dv6ym5lHrEQw8JSlUtapghHJ+qiK13OyZ6yyf/sunSYqyVuPavVVq3bvSgrKxcKVGU7/s1U5ovXz1W5v9ftPVet68cbSehRo65ZNfUuB/AWHLchVUWJtFAAAAAElFTkSuQmCC);
+    display: none;
+  }
+  </style>
+
+  <div id="header"></div>
+  <input id="stacking-distance-slider" max="400" min="1" step="1" type="range"/>
+  
+  <div id="canvas-scroller">
+    <canvas id="canvas"></canvas>
+  </div>
+  <img id="chrome-left"/>
+  <img id="chrome-mid"/>
+  <img id="chrome-right"/>
+</template><template id="tr-ui-e-chrome-cc-layer-tree-quad-stack-view-template">
+  <style>
+  #input-event {
+    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAMnwAADJ8BPja39wAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAyNSURBVHic7Z1PTCPXHcc/4wWWVbJN2cJSLVqiQJuGpoIGEVWReoBNIlIF5RCRSysOK9EbksUeOHLIIQcULbLEEYk7oqduD6gSRoqUEyK7dCOabOHghCiAE/JntQtesHt4fuM3z2+MZzy2x8ZfaTTjN+Px4/fh9/7Pb6xMJkND4VGk2hloyKkGkJCpASRkagAJmRpAQqYGkJCpASRkaqp2BvzKsizf3w1z38sKc+ZUaQCuAFeB57P7q4AF/Kxsj4GnLrfL+6PDYofQAskCaAJ6gJeB6+QAFOvZpwgwPwOHwCNgN5uu/+H252raJHRALMu6ggDwCtALNAf8E88QUL5AAHqSTVcNUTU4oQBiWVYzMIiA0E3lGhtp4CsEnPtACgFDGqXiYKoKxLKsCPAaMIwojlzV1tZGV1cXHR0ddHR00N7ebh93dHQAcHh4aG/JZNI+3tvb4+jo6LzsPAY+QYA5Ix9KBsoPpmpALMt6BXgTaHe7pre3l5GREUZGRujv7/fdsspkMmxtbRGPx4nH4+zs7BS6/HtgHfgvOW9xeE05bVZxIJZldQNvATf1c5FIhMHBQYaHh7l16xbd3d1lyUMikWBtbY319XU2NzdJp9Omy74B1oAEAoa8yIZTDttVDIhlWZeB94Dfm86Pjo4SjUbLBsFNiUSCWCzG6uqq2yVfAv9CNKHTlNlbKgLEsqxrwF+BX+nnhoaGuHPnDv39/WXPRyFtbW1x9+5dNjY2TKePgBXgOwQUFUyg3lJ2IJZl9QAfAK1qek9PD9PT04yMjJT1970qHo8zPz/P7u6ufuoE+CewQw6Kw2OCsGVZgViW9SdgFNGLBqC1tZWZmRnGx8eJRMI5lJZOp1lZWWFubo7j42P1VAZR4W8gWmJn5KBAAEVYWYBkm7PvIvoWtjo7O1lYWKCvry/w3yyHtre3mZqaYn9/Xz/1EPg3ot+iQslQIpTAgWRh/A0x5GFrYGCAWCxGe7trKzeUSiaTRKNRHjx4oJ/6CvgHoigLDEo5yox30WCMjY2xtLRUczAA2tvbWVpaYmxsTD91E3gbMbTTBFxCFM0WYPntMwXqIdk64x3lM9FolMnJycB+o5paXFwkFovplfcniDrlNLvJXr4vTwnMQ7KtqVE1rZ5gAExOThKNRvXkPyMGQaWXlOQpgQDJ9jM+QGlNjY2N1RUMqcnJSb34shClwnVE8aVCAY9QSi6ysj3wv6N0+gYGBlhaWqKlpaWke4dVqVSK27dv6xX9j8AyYpDyGaL4svsqxdo5CA95DwVGZ2cnsVisbmEAtLS0EIvF6OzsVJNfQIzRlVTJlwQkO1Boj021traysLBQk60pr2pvb2dhYYHWVscAxEuI1pcKJYIHKKV6yFvqh5mZmZrp9AWhvr4+ZmZm9OQ3MAMpSr6BZOcz7CH0np4exsfH/d6uZjU+Pk5Pj6PbdR34LT69xBeQbG/8TTVteno6tGNT5VQkEmF6elpPfh24TK7VFaFIKH4t+BrKTN/Q0FDoRm0rqZGREYaGhtSkXyDqVs9Fl2cg2QUJw2ranTt3vN6m7mSwwR8R68dULzm31eXHQwZRFiSMjo5WfXIpDOrv72d01DFQcQXoQ3hI0V7iB8gr9pcjEdNQwoVVNBrV69EXcanccfEST0Cyi9jsSe/BwcGKz4GHWd3d3QwOOqaAOoDnMFfuRnn1kJfV7wwPD3v8ev1Ls4mF+Ac2FVsW5C8aLxpI9ou/U9Nu3brlOcP1LoNNbuJej+R5ihcPaQJ+Iz/09vY2iiuDuru76e3tVZN+jeiTyFHggsWWFyA9KAufL3K/4zxptrkE3MClYkcDUxQQU3HVAOIug226yHlIXvNXrUe8eEiHPGhra2v0PQqov7+ftrY2NekFzEVWSXWI3Rns6uoq6ZGyepdlWXR1dalJrRTwEFVegFyVB3L5f0Pu0mzUirC1CsPoJcUCuYLyGFkDyPnSbBQhB8VUZNm99nOBZC+8qqZdhBnBUmWw0RXMQHx5iOPpprB5yMbGBp999lm1s+GQwUZXKFBUSRULxOEhYQNy//59Hj58WO1sOOQCpGAfBOoESBhVwENMm61in/cOXRt3f3+f09NTAH766SdaWlrY29sDoLm5mevXr1cze25y9QypYoH8rH44PDwsIU/B6KOPPrLzcXBwQCQS4dNPPwXgxo0bfPzxx9XMnslGJ7h7hkX2GZOaBRKLxezjxcVFLl++zMTERBVz5JTBRseGy3zXIaEDEna5eAgENIX7WP2QTCaL/NrFlcFG0kMKLvIttsh6ilg83ATh85D3338/dGNrmo3SiAXYuvLgeImX9Rj4peHHqq5r165VOwt50mx0gjkqhJT92cvgol2P7O3thSa+VBiVyWTsJnhWsv4wBrZR5QWIjfzo6IitrS0vebxQ2tra0oPdPCbfQ4ze4gXII/VDPB73k9cLIYNtDnACUJ9td8gLkF2UiqkBxF2abc6AJOboD3lQzgWi1BWnCCgA7OzskEgk/Oa5bpVIJPTwT9+RCymoe4jvIkt+8Qs1cW1tzVem61kGm8jiKk1+gIE8eV25+Ihc3CjW19c9fr3+pdkkgwCiwsiL+oDyUKhXIE8QISUA2NzcbBRbihKJBJubm2rSD4h4KLLuOMMQRUiVn9XvdrGVTqcdg3wXXbFYTI9Op3qHuqlQHCoKSNadJNH7KGNbq6urjT4Jou+hRaVLIUoTE4zA6hD5Q5+oCXfv3vVxm/qSwQY7iG6C9BAZByWv6auOevgBIr3ke5mwsbFxofsl8XhcDw34BPgaYXg1KI0p6JlDRQPRiq0zRGQ1W/Pz827RPeta6XSa+fl5Pfl/5LxC3QrCAP9P4WYQcW2/kQm7u7usrKz4vF3tamVlRY/P+CPwLTlvcANiDN/kCYjiJXLv6AXNzc2xvb3t5ZY1re3tbebm5vRk2Vc7JReExgTDqFI8JIMIMvylTDw+PmZqaupCzCgmk0mmpqb0IJkHiLpV9Ypn5MA4oJimMDwD0eqSDCLIsD3WvL+/TzQaJZVKeb11zSiVShGNRvXgmE+Az8kVU8+UrSjvgNKCz8jxmaeIIMNyEoYHDx4wOztbwq3DrdnZWT1W1imi5XmCE0YKlyLLbYLPFxDlZhLKd4ggw/aJe/fusbi46Of2odbi4iL37t1TkzLAfxAzqmc4PcPkIQVVqofIfRrREVpXL4jFYnUFRQbB1PQIMZsqYaSUraiWlaqSQvxlV3rIFd2XEIsm/gL8Qb1ubGyMDz/8sGajzKVSKWZnZ3XPANHs/xxh+BSiyDrObifkirCiiisIDogK5TIwjvY6ijoMpHwEbCJAPCMHQIWhxl4sKmxsEEEwwQmlCQHlbeBV9do6CjX+DbBNDobqHSYYRQfCLDnimKEZfJbN0CpiENLOxf7+PhMTEywvL4d6mCWdTrO8vMzExIQOI4Pod31OPowTzHWHpz80kMjWyqpB6SXSU5oRQYbfARwVSA2+ruIU0ZrSK/ATnEBky8oxqlusnQMLNa4VXRa5Sr4JEYdwDPG8tkM18kKXJ+TmgWQ/Q3qDDsNTJa4r6NjvkA/lEsJTnkdEMX3J9N0Qv/LoAFFEyRaTbFFJGPK4ZBhQntdVgDuUZkTr6w2E1zgUspeC/YjoY3yPczgkZdhk568kGFC+F7qAE4qsU2S90owIpfo6ImCkUVV6bd4TxHzGtzgnmNThEN0rHK0pSngFUtleeeQCRa1XmhHN41eBAcRDka6qwIslU4jRhq/Jn8tQh0HUitttWtb3YvRyv4MKck8MyUeCZRGmeosMGPkiIshNpR72yCCW6hwgFiTI1pE0tDS6abDQ87BIMarEW9rAGUFNNot1MHL/HCIs3k1E8K9LAWfpDDEYepDd5Lopdc5b9Qx9r14nx/EgABhQASCQ109RizAdjApH9vhvIOJNvYCIFyJjhhSjNLlm6WMEgCS5tbbqAjbTlKsKwwTCHmCtmfcY2j/khCL3auwPNXyRGqOwifzQRq2IYk7dwDl8cYwwpjoqrRrSDYYKpdCaqpLrC5Oq8S5c+xCzx+hwTJtbEBdT3aMbUBpVXWvrtsnz+op1CNArVFXlbdEu3mICowJS9+cBsR/Exx2IaQG0af1tHggI1itUVft96vahsi/kOabPxQCRe93IaW3TAVQMhFRVgdiZMIORexOgQiDkXv3DdAObPMYIgAqBkAoFECmtJ+4Gp9Ax2rEORe51w+sQ7OOK17FhAqLKBY567AbBTSY4rsfVsktogagqACfvUpd0tz/SkR4GW9QEEFVBhtAI499ec0DqXf8H8f4X10jf2YAAAAAASUVORK5CYII=);
+    display: none;
+  }
+  </style>
+  <img id="input-event"/>
+</template><template id="tr-ui-e-chrome-cc-picture-debugger-template">
+  <left-panel>
+    <picture-info>
+      <div>
+        <span class="title">Skia Picture</span>
+        <span class="size"></span>
+      </div>
+      <div>
+        <input class="filename" type="text" value="skpicture.skp"/>
+        <button class="export">Export</button>
+      </div>
+    </picture-info>
+  </left-panel>
+  <right-panel>
+    <tr-ui-e-chrome-cc-picture-ops-chart-view>
+    </tr-ui-e-chrome-cc-picture-ops-chart-view>
+    <raster-area><canvas></canvas></raster-area>
+  </right-panel>
+</template><dom-module id="tr-ui-a-stack-frame">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+      align-items: center;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex: 0 1;
+      flex-direction: column;
+    }
+    #table {
+      flex: 0 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table">
+    </tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-chrome-cc-raster-task-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #heading {
+      flex: 0 0 auto;
+    }
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+
+    <div id="heading">
+      Rasterization costs in
+      <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
+    </div>
+    <tr-ui-b-table id="content"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-chrome-codesearch">
+  <template>
+    <style>
+      :host {
+        white-space: nowrap;
+      }
+      #codesearchLink {
+        font-size: x-small;
+        margin-left: 20px;
+        text-decoration: none;
+      }
+    </style>
+    <a id="codesearchLink" on-click="onClick" target="_blank">🔍</a>
+  </template>
+</dom-module><style>
+.tr-ui-e-chrome-gpu-state-snapshot-view{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAZiS0dEAEwATABMYqp3KAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90JCQsBMCH7ZqYAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAUElEQVRYw+3WwQkAIAiF4Vc0hTO5/wiuURvYIcQOv1cRPhDlDXffSsrMsrYiQi/zU80FAACAVX3nt3lWAABA/x+ovnPyAAAA5AHyAAAA3wMOd34Xd+lsglgAAAAASUVORK5CYII=);display:flex;overflow:auto}.tr-ui-e-chrome-gpu-state-snapshot-view img{display:block;margin:16px auto 16px auto}
+</style><dom-module id="tr-ui-a-layout-tree-sub-view">
+  <template>
+    <style>
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><template id="tr-ui-e-img-image-snapshot-view-template">
+  <style>
+    .image-info {
+      margin-bottom: 5px;
+    }
+
+    .image-info .title {
+      font-weight: bold;
+      margin-left: 5px;
+      margin-right: 5px;
+    }
+
+    .image-info .size {
+      margin-right: 5px;
+    }
+
+    .image-container {
+      min-height: 100px;
+      min-width: 200px;
+      overflow: auto;
+    }
+  </style>
+
+  <div class="image-info">
+    <span class="title">Image</span>
+    <span class="size">(unknown)</span>
+    <span class="instructions">
+      [ Drag with mouse to zoom in and out ]
+    </span>
+  </div>
+  <div class="image-container">
+    <img alt="Image snapshot"/>
+  </div>
+</template><dom-module id="tr-ui-e-s-frame-data-side-panel">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      width: 600px;
+      flex-direction: column;
+    }
+    table-container {
+      display: flex;
+      overflow: auto;
+      font-size: 12px;
+    }
+    </style>
+    <div>
+      Organize by:
+      <select id="select">
+        <option value="none">None</option>
+        <option value="tree">Frame Tree</option>
+      </select>
+    </div>
+    <table-container>
+      <tr-ui-b-table id="table"></tr-ui-b-table>
+    </table-container>
+  </template>
+</dom-module><dom-module id="tr-ui-b-chart-legend-key">
+  <template>
+    <style>
+      #checkbox {
+        margin: 0;
+        visibility: hidden;
+        vertical-align: text-top;
+      }
+      #label, #link {
+        white-space: nowrap;
+        text-overflow: ellipsis;
+        overflow: hidden;
+        display: inline-block;
+      }
+    </style>
+
+    <input checked="" id="checkbox" type="checkbox"/>
+    <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
+    <label id="label"></label>
+  </template>
+</dom-module><template id="chart-base-template">
+  <svg> 
+    <g id="chart-area" xmlns="http://www.w3.org/2000/svg">
+      <g class="x axis"></g>
+      <g class="y axis"></g>
+      <text id="title"></text>
+    </g>
+  </svg>
+</template><dom-module id="tr-ui-e-s-input-latency-side-panel">
+  <template>
+    <style>
+    :host {
+      flex-direction: column;
+      display: flex;
+    }
+    toolbar {
+      flex: 0 0 auto;
+      border-bottom: 1px solid black;
+      display: flex;
+    }
+    result-area {
+      flex: 1 1 auto;
+      display: block;
+      min-height: 0;
+      overflow-y: auto;
+    }
+    </style>
+
+    <toolbar id="toolbar"></toolbar>
+    <result-area id="result_area"></result-area>
+  </template>
+</dom-module><dom-module id="tr-ui-b-heading">
+  <template>
+    <style>
+    :host {
+      background-color: rgb(243, 245, 247);
+      border-right: 1px solid #8e8e8e;
+      display: block;
+      height: 100%;
+      margin: 0;
+      padding: 0 5px 0 0;
+    }
+
+    heading {
+      display: block;
+      overflow-x: hidden;
+      text-align: left;
+      white-space: nowrap;
+    }
+
+    #arrow {
+      flex: 0 0 auto;
+      font-family: sans-serif;
+      margin-left: 5px;
+      margin-right: 5px;
+      width: 8px;
+    }
+
+    #link, #heading_content {
+      display: none;
+    }
+    </style>
+    <heading id="heading" on-click="onHeadingDivClicked_">
+      <span id="arrow"></span>
+      <span id="heading_content"></span>
+      <tr-ui-a-analysis-link id="link"></tr-ui-a-analysis-link>
+    </heading>
+  </template>
+</dom-module><style>
+.track-button{background-color:rgba(255,255,255,0.5);border:1px solid rgba(0,0,0,0.1);color:rgba(0,0,0,0.2);font-size:10px;height:12px;text-align:center;width:12px}.track-button:hover{background-color:rgba(255,255,255,1.0);border:1px solid rgba(0,0,0,0.5);box-shadow:0 0 .05em rgba(0,0,0,0.4);color:rgba(0,0,0,1)}.track-close-button{left:2px;position:absolute;top:2px}.track-collapse-button{left:3px;position:absolute;top:2px}
+</style><style>
+.object-instance-track{height:18px}
+</style><style>
+.tr-ui-e-system-stats-instance-track{height:500px}.tr-ui-e-system-stats-instance-track ul{list-style:none;list-style-position:outside;margin:0;overflow:hidden}
+</style><style>
+.tr-ui-e-system-stats-snapshot-view .subhead{font-size:small;padding-bottom:10px}.tr-ui-e-system-stats-snapshot-view ul{background-position:0 5px;background-repeat:no-repeat;cursor:pointer;font-family:monospace;list-style:none;margin:0;padding-left:15px}.tr-ui-e-system-stats-snapshot-view li{background-position:0 5px;background-repeat:no-repeat;cursor:pointer;list-style:none;margin:0;padding-left:15px}
+</style><dom-module id="tr-ui-e-v8-gc-objects-stats-table">
+  <template>
+    <style>
+    tr-ui-b-table {
+      flex: 0 0 auto;
+      align-self: stretch;
+      margin-top: 1em;
+      font-size: 12px;
+    }
+    .diff {
+      display: inline-block;
+      margin-top: 1em;
+      margin-left: 0.8em;
+    }
+    </style>
+    <div class="diff" id="diffOption">
+      Diff
+    </div>
+    <tr-ui-b-table id="diffTable"></tr-ui-b-table>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view">
+  <template>
+    <style>
+    </style>
+    <tr-ui-e-v8-gc-objects-stats-table id="gcObjectsStats">
+    </tr-ui-e-v8-gc-objects-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-v8-ic-stats-table">
+  <template>
+    <style>
+    tr-ui-b-table {
+      flex: 0 0 auto;
+      align-self: stretch;
+      margin-top: 1em;
+      font-size: 12px;
+    }
+    #total {
+      margin-top: 1em;
+      margin-left: 0.8em;
+    }
+    #groupOption {
+      display: inline-block;
+      margin-top: 1em;
+      margin-left: 0.8em;
+    }
+    </style>
+    <div style="padding-right: 200px">
+      <div style="float:right;  border-style: solid; border-width: 1px; padding:20px">
+        X no feedback<br/>
+        0 uninitialized<br/>
+        . premonomorphic<br/>
+        1 monomorphic<br/>
+        ^ recompute handler<br/>
+        P polymorphic<br/>
+        N megamorphic<br/>
+        G generic
+      </div>
+    </div>
+    <div id="total">
+    </div>
+    <div id="groupOption">
+      Group Key
+    </div>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view">
+  <template>
+    <tr-ui-e-v8-ic-stats-table id="table">
+    </tr-ui-e-v8-ic-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-v8-runtime-call-stats-table">
+  <template>
+    <style>
+    #table, #blink_rcs_table {
+      flex: 0 0 auto;
+      align-self: stretch;
+      margin-top: 1em;
+      font-size: 12px;
+    }
+
+    #v8_rcs_heading, #blink_rcs_heading {
+        padding-top: 1em;
+        font-size: 18px;
+    }
+    </style>
+    <h1 id="v8_rcs_heading"></h1>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+    <h1 id="blink_rcs_heading"></h1>
+    <tr-ui-b-table id="blink_rcs_table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-multi-v8-thread-slice-sub-view">
+  <template>
+    <tr-ui-a-multi-thread-slice-sub-view id="content"></tr-ui-a-multi-thread-slice-sub-view>
+    <tr-ui-e-v8-runtime-call-stats-table id="runtimeCallStats"></tr-ui-e-v8-runtime-call-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-single-v8-gc-stats-thread-slice-sub-view">
+  <template>
+    <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+    <tr-ui-e-v8-gc-objects-stats-table id="gcObjectsStats"></tr-ui-e-v8-gc-objects-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-single-v8-ic-stats-thread-slice-sub-view">
+  <template>
+    <tr-ui-e-v8-ic-stats-table id="table">
+    </tr-ui-e-v8-ic-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-e-single-v8-thread-slice-sub-view">
+  <template>
+    <tr-ui-a-single-thread-slice-sub-view id="content"></tr-ui-a-single-thread-slice-sub-view>
+    <tr-ui-e-v8-runtime-call-stats-table id="runtimeCallStats"></tr-ui-e-v8-runtime-call-stats-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-alert-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table">
+    </tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-b-tab-view">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      #selection_description, #tabs {
+        font-size: 12px;
+      }
+
+      #selection_description {
+        display: inline-block;
+        font-weight: bold;
+        margin: 9px 0px 4px 20px;
+      }
+
+      #tabs {
+        flex: 0 0 auto;
+        border-top: 1px solid #8e8e8e;
+        border-bottom: 1px solid #8e8e8e;
+        background-color: #ececec;
+        overflow: hidden;
+        margin: 0;
+      }
+
+      #tabs input[type=radio] {
+        display: none;
+      }
+
+      #tabs tab label {
+        cursor: pointer;
+        display: inline-block;
+        border: 1px solid #ececec;
+        margin: 5px 0px 0px 15px;
+        padding: 3px 10px 3px 10px;
+      }
+
+      #tabs tab label span {
+        font-weight: bold;
+      }
+
+      #tabs:focus input[type=radio]:checked ~ label {
+        outline: dotted 1px #8e8e8e;
+        outline-offset: -2px;
+      }
+
+      #tabs input[type=radio]:checked ~ label {
+        background-color: white;
+        border: 1px solid #8e8e8e;
+        border-bottom: 1px solid white;
+      }
+
+      #subView {
+        flex: 1 1 auto;
+        min-width: 0;
+        display: flex;
+      }
+
+      #subView > * {
+        flex: 1 1 auto;
+        min-width: 0;
+      }
+    </style>
+    <div hidden="[[tabsHidden]]" id="tabs">
+      <label id="selection_description">[[label_]]</label>
+      <template is="dom-repeat" items="[[subViews_]]">
+        <tab>
+          <input checked="[[isChecked_(item)]]" id$="[[computeRadioId_(item)]]" name="tabs" on-change="onTabChanged_" type="radio"/>
+          <label for$="[[computeRadioId_(item)]]">
+            <template if="[[item.tabIcon]]" is="dom-if">
+              <span style$="[[item.tabIcon.style]]">[[item.tabIcon.text]]</span>
+            </template>
+            [[item.tabLabel]]
+          </label>
+        </tab>
+      </template>
+    </div>
+    <div id="subView"></div>
+    <slot>
+    </slot>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-heap-details-breakdown-view">
+  <template>
+    <tr-ui-b-tab-view id="tabs"></tr-ui-b-tab-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-heap-details-breakdown-view-tab">
+  <template>
+    <tr-v-ui-scalar-context-controller></tr-v-ui-scalar-context-controller>
+    <tr-ui-b-info-bar hidden="" id="info"></tr-ui-b-info-bar>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-heap-details-path-view">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+    </style>
+    <tr-v-ui-scalar-context-controller></tr-v-ui-scalar-context-controller>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-heap-details-pane">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      #header {
+        flex: 0 0 auto;
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+
+        background-color: #eee;
+        border-bottom: 1px solid #8e8e8e;
+        border-top: 1px solid white;
+      }
+
+      #label {
+        flex: 1 1 auto;
+        padding: 8px;
+        font-size: 15px;
+        font-weight: bold;
+      }
+
+      #view_mode_container {
+        display: none;
+        flex: 0 0 auto;
+        padding: 5px;
+        font-size: 15px;
+      }
+
+      #contents {
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+
+      #info_text {
+        padding: 8px;
+        color: #666;
+        font-style: italic;
+        text-align: center;
+      }
+
+      #split_view {
+        display: none;  /* Hide until memory allocator dumps are set. */
+        flex: 1 0 auto;
+        align-self: stretch;
+        flex-direction: row;
+      }
+
+      #path_view {
+        width: 50%;
+      }
+
+      #breakdown_view {
+        flex: 1 1 auto;
+        width: 0;
+      }
+
+      #path_view, #breakdown_view {
+        overflow-x: auto;  /* Show scrollbar if necessary. */
+      }
+    </style>
+    <div id="header">
+      <div id="label">Heap details</div>
+      <div id="view_mode_container">
+        <span>View mode:</span>
+        
+      </div>
+    </div>
+    <div id="contents">
+      <tr-ui-b-info-bar hidden="" id="info_bar">
+      </tr-ui-b-info-bar>
+
+      <div id="info_text">No heap dump selected</div>
+
+      <div id="split_view">
+        <tr-ui-a-memory-dump-heap-details-path-view id="path_view">
+        </tr-ui-a-memory-dump-heap-details-path-view>
+        <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+        <tr-ui-a-memory-dump-heap-details-breakdown-view id="breakdown_view">
+        </tr-ui-a-memory-dump-heap-details-breakdown-view>
+      </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-allocator-details-pane">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      #label {
+        flex: 0 0 auto;
+        padding: 8px;
+
+        background-color: #eee;
+        border-bottom: 1px solid #8e8e8e;
+        border-top: 1px solid white;
+
+        font-size:  15px;
+        font-weight: bold;
+      }
+
+      #contents {
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+
+      #info_text {
+        padding: 8px;
+        color: #666;
+        font-style: italic;
+        text-align: center;
+      }
+
+      #table {
+        display: none;  /* Hide until memory allocator dumps are set. */
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+    </style>
+    <div id="label">Component details</div>
+    <div id="contents">
+      <div id="info_text">No memory allocator dump selected</div>
+      <tr-ui-b-table id="table"></tr-ui-b-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-vm-regions-details-pane">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      #label {
+        flex: 0 0 auto;
+        padding: 8px;
+
+        background-color: #eee;
+        border-bottom: 1px solid #8e8e8e;
+        border-top: 1px solid white;
+
+        font-size:  15px;
+        font-weight: bold;
+      }
+
+      #contents {
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+
+      #info_text {
+        padding: 8px;
+        color: #666;
+        font-style: italic;
+        text-align: center;
+      }
+
+      #table {
+        display: none;  /* Hide until memory dumps are set. */
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+    </style>
+    <div id="label">Memory maps</div>
+    <div id="contents">
+      <div id="info_text">No memory maps selected</div>
+      <tr-ui-b-table id="table"></tr-ui-b-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-b-color-legend">
+  <template>
+    <style>
+    :host {
+      display: inline-block;
+    }
+
+    #square {
+      font-size: 150%;  /* Make the square bigger. */
+      line-height: 0%;  /* Prevent the square from increasing legend height. */
+    }
+    </style>
+    <span id="square"></span>
+    <span id="label"></span>
+  </template>
+</dom-module><dom-module id="tr-ui-b-view-specific-brushing-state">
+  <template></template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-overview-pane">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      #label {
+        flex: 0 0 auto;
+        padding: 8px;
+
+        background-color: #eee;
+        border-bottom: 1px solid #8e8e8e;
+        border-top: 1px solid white;
+
+        font-size:  15px;
+        font-weight: bold;
+      }
+
+      #label a {
+        font-weight: normal;
+        float: right;
+      }
+
+      #contents {
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+        overflow: auto;
+      }
+
+      #info_text {
+        padding: 8px;
+        color: #666;
+        font-style: italic;
+        text-align: center;
+      }
+
+      #table {
+        display: none;  /* Hide until memory dumps are set. */
+        flex: 1 0 auto;
+        align-self: stretch;
+        font-size: 12px;
+      }
+    </style>
+    <tr-ui-b-view-specific-brushing-state id="state" view-id="analysis.memory_dump_overview_pane">
+    </tr-ui-b-view-specific-brushing-state>
+    <div id="label">Overview <a href="https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra">Help</a></div>
+    <div id="contents">
+      <div id="info_text">No memory memory dumps selected</div>
+      <tr-ui-b-table id="table"></tr-ui-b-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-memory-dump-header-pane">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: row;
+        align-items: center;
+
+        background-color: #d0d0d0;
+        border-bottom: 1px solid #8e8e8e;
+        border-top: 1px solid white;
+      }
+
+      #label {
+        flex: 1 1 auto;
+        padding: 6px;
+        font-size: 15px;
+      }
+
+      #aggregation_mode_container {
+        display: none;
+        flex: 0 0 auto;
+        padding: 5px;
+        font-size: 15px;
+      }
+    </style>
+    
+    <div id="label"></div>
+    <div id="aggregation_mode_container">
+      <span>Metric aggregation:</span>
+      
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-stacked-pane-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+
+    #pane_container > * {
+      flex: 0 0 auto;
+    }
+    </style>
+    <div id="pane_container">
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-container-memory-dump-sub-view">
+  <template>
+    <style>
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-counter-sample-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-event-summary-table">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table">
+    </tr-ui-b-table>
+    
+  </template>
+</dom-module><dom-module id="tr-ui-a-selection-summary-table">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table">
+    </tr-ui-b-table>
+    
+  </template>
+</dom-module><dom-module id="tr-ui-b-radio-picker">
+  <template>
+    <style>
+    :host([vertical]) #container {
+      flex-direction: column;
+    }
+    :host(:not[vertical]) #container {
+      flex-direction: row;
+    }
+    #container {
+      display: flex;
+    }
+    #container > div {
+      padding-left: 1em;
+      padding-bottom: 0.5em;
+    }
+    </style>
+    <div id="container"></div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-breakdown-span">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #table_container {
+      display: flex;
+      flex: 0 0 auto;
+    }
+    #table {
+      max-height: 150px;
+      overflow-y: auto;
+    }
+    </style>
+
+    <div id="empty">(empty)</div>
+    <div id="table_container">
+      <div id="container"></div>
+      <span>
+        <tr-ui-b-table id="table"></tr-ui-b-table>
+      </span>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-collected-related-event-set-span">
+</dom-module><dom-module id="tr-v-ui-date-range-span">
+  <template>
+    <content></content>
+  </template>
+</dom-module><dom-module id="tr-v-ui-generic-set-span">
+  <template>
+    <style>
+      a {
+        display: block;
+      }
+    </style>
+
+    <tr-ui-a-generic-object-view id="generic"></tr-ui-a-generic-object-view>
+
+    <div id="links"></div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-related-event-set-span">
+</dom-module><dom-module id="tr-v-ui-scalar-diagnostic-span">
+  <template>
+    <tr-v-ui-scalar-span id="scalar"></tr-v-ui-scalar-span>
+  </template>
+</dom-module><dom-module id="tr-v-ui-unmergeable-diagnostic-set-span">
+</dom-module><dom-module id="tr-v-ui-diagnostic-map-table">
+  <template>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-v-ui-scalar-map-table">
+  <template>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-span">
+  <template>
+    <style>
+    #container {
+      display: flex;
+      flex-direction: row;
+      justify-content: space-between;
+    }
+    #chart {
+      flex-grow: 1;
+      display: none;
+    }
+    #drag_handle, #diagnostics_tab_templates {
+      display: none;
+    }
+    #chart svg {
+      display: block;
+    }
+    #stats_container {
+      overflow-y: auto;
+    }
+    </style>
+
+    <div id="container">
+      <div id="chart"></div>
+      <div id="stats_container">
+        <tr-v-ui-scalar-map-table id="stats"></tr-v-ui-scalar-map-table>
+      </div>
+    </div>
+    <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+
+    <tr-ui-b-tab-view id="diagnostics"></tr-ui-b-tab-view>
+
+    <div id="diagnostics_tab_templates">
+      <tr-v-ui-diagnostic-map-table id="metric_diagnostics"></tr-v-ui-diagnostic-map-table>
+
+      <tr-v-ui-diagnostic-map-table id="metadata_diagnostics"></tr-v-ui-diagnostic-map-table>
+
+      <div id="sample_diagnostics_container">
+        <div id="merge_sample_diagnostics_container">
+          <input checked="" id="merge_sample_diagnostics" on-change="updateDiagnostics_" type="checkbox"/>
+          <label for="merge_sample_diagnostics">Merge Sample Diagnostics</label>
+        </div>
+        <tr-v-ui-diagnostic-map-table id="sample_diagnostics"></tr-v-ui-diagnostic-map-table>
+      </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      overflow: auto;
+    }
+    #content {
+      display: flex;
+      flex-direction: column;
+      flex: 0 1 auto;
+      align-self: stretch;
+    }
+    #content > * {
+      flex: 0 0 auto;
+      align-self: stretch;
+    }
+    #histogramContainer {
+      display: flex;
+    }
+
+    tr-ui-a-multi-event-summary-table {
+      border-bottom: 1px solid #aaa;
+    }
+
+    tr-ui-a-selection-summary-table  {
+      margin-top: 1.25em;
+      border-top: 1px solid #aaa;
+      background-color: #eee;
+      font-weight: bold;
+      margin-bottom: 1.25em;
+      border-bottom: 1px solid #aaa;
+    }
+    </style>
+    <div id="content">
+      <tr-ui-a-multi-event-summary-table id="eventSummaryTable">
+      </tr-ui-a-multi-event-summary-table>
+      <tr-ui-a-selection-summary-table id="selectionSummaryTable">
+      </tr-ui-a-selection-summary-table>
+      <tr-ui-b-radio-picker id="radioPicker">
+      </tr-ui-b-radio-picker>
+      <div id="histogramContainer">
+        <tr-v-ui-histogram-span id="histogramSpan">
+        </tr-v-ui-histogram-span>
+      </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-related-events">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-async-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #container {
+      display: flex;
+      flex: 1 1 auto;
+    }
+    #events {
+      margin-left: 8px;
+      flex: 0 1 200px;
+    }
+    </style>
+    <div id="container">
+      <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+      <div id="events">
+        <tr-ui-a-related-events id="relatedEvents"></tr-ui-a-related-events>
+      </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-cpu-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #content {
+      flex: 1 1 auto;
+    }
+    </style>
+    <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-flow-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    </style>
+    <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-instant-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-object-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="content"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-frame-power-usage-chart">
+  <template>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-power-sample-summary-table">
+  <template>
+    <style>
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-power-sample-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+    }
+    #tables {
+      display: flex;
+      flex-direction: column;
+      width: 50%;
+    }
+    #chart {
+      width: 50%;
+    }
+    </style>
+    <div id="tables">
+      <tr-ui-a-power-sample-summary-table id="summaryTable">
+      </tr-ui-a-power-sample-summary-table>
+    </div>
+    <tr-ui-a-frame-power-usage-chart id="chart">
+    </tr-ui-a-frame-power-usage-chart>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-sample-sub-view">
+  <template>
+    <style>
+    :host { display: block; }
+    #control {
+      background-color: #e6e6e6;
+      background-image: -webkit-gradient(linear, 0 0, 0 100%,
+                                         from(#E5E5E5), to(#D1D1D1));
+      flex: 0 0 auto;
+      overflow-x: auto;
+    }
+    #control::-webkit-scrollbar { height: 0px; }
+    #control {
+      font-size: 12px;
+      display: flex;
+      flex-direction: row;
+      align-items: stretch;
+      margin: 1px;
+      margin-right: 2px;
+    }
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+    <div id="control">
+      Sample View Option
+    </div>
+    <tr-ui-b-table id="table">
+    </tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-thread-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #content {
+      display: flex;
+      flex: 1 1 auto;
+      min-width: 0;
+    }
+    #content > tr-ui-a-related-events {
+      margin-left: 8px;
+      flex: 0 1 200px;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-thread-time-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #content {
+      flex: 1 1 auto;
+      min-width: 0;
+    }
+    </style>
+    <tr-ui-a-multi-event-sub-view id="content"></tr-ui-a-multi-event-sub-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-user-expectation-related-samples-table">
+  <template>
+    <style>
+    #table {
+      flex: 1 1 auto;
+      align-self: stretch;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-multi-user-expectation-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex: 1 1 auto;
+    }
+    #events {
+      margin-left: 8px;
+      flex: 0 1 200px;
+    }
+    </style>
+    <tr-ui-a-multi-event-sub-view id="realView"></tr-ui-a-multi-event-sub-view>
+    <div id="events">
+      <tr-ui-a-user-expectation-related-samples-table id="relatedSamples"></tr-ui-a-user-expectation-related-samples-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-async-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+    }
+    #events {
+      display:flex;
+      flex-direction: column;
+    }
+    </style>
+    <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+    <div id="events">
+      <tr-ui-a-related-events id="relatedEvents"></tr-ui-a-related-events>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-cpu-slice-sub-view">
+  <template>
+    <style>
+    table {
+      border-collapse: collapse;
+      border-width: 0;
+      margin-bottom: 25px;
+      width: 100%;
+    }
+
+    table tr > td:first-child {
+      padding-left: 2px;
+    }
+
+    table tr > td {
+      padding: 2px 4px 2px 4px;
+      vertical-align: text-top;
+      width: 150px;
+    }
+
+    table td td {
+      padding: 0 0 0 0;
+      width: auto;
+    }
+    tr {
+      vertical-align: top;
+    }
+
+    tr:nth-child(2n+0) {
+      background-color: #e2e2e2;
+    }
+    </style>
+    <table>
+      <tbody><tr>
+        <td>Running process:</td><td id="process-name"></td>
+      </tr>
+      <tr>
+        <td>Running thread:</td><td id="thread-name"></td>
+      </tr>
+      <tr>
+        <td>Start:</td>
+        <td>
+          <tr-v-ui-scalar-span id="start">
+          </tr-v-ui-scalar-span>
+        </td>
+      </tr>
+      <tr>
+        <td>Duration:</td>
+        <td>
+          <tr-v-ui-scalar-span id="duration">
+          </tr-v-ui-scalar-span>
+        </td>
+      </tr>
+      <tr>
+        <td>Active slices:</td><td id="running-thread"></td>
+      </tr>
+      <tr>
+        <td>Args:</td>
+        <td>
+          <tr-ui-a-generic-object-view id="args">
+          </tr-ui-a-generic-object-view>
+        </td>
+      </tr>
+    </tbody></table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-flow-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+    </style>
+    <tr-ui-a-single-event-sub-view id="singleEventSubView">
+    </tr-ui-a-single-event-sub-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-frame-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    #asv {
+      flex: 0 0 auto;
+      align-self: stretch;
+    }
+    </style>
+    <tr-ui-a-alert-sub-view id="asv">
+    </tr-ui-a-alert-sub-view>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-instant-event-sub-view">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-object-instance-sub-view">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+
+    #snapshots > * {
+      display: block;
+    }
+
+    :host {
+      overflow: auto;
+      display: block;
+    }
+
+    * {
+      -webkit-user-select: text;
+    }
+
+    .title {
+      border-bottom: 1px solid rgb(128, 128, 128);
+      font-size: 110%;
+      font-weight: bold;
+    }
+
+    td, th {
+      font-family: monospace;
+      vertical-align: top;
+    }
+    </style>
+    <div id="content"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-object-snapshot-sub-view">
+  <template>
+    <style>
+    #args {
+      white-space: pre;
+    }
+
+    :host {
+      overflow: auto;
+      display: flex;
+    }
+
+    ::content * {
+      -webkit-user-select: text;
+    }
+
+    ::content .title {
+      border-bottom: 1px solid rgb(128, 128, 128);
+      font-size: 110%;
+      font-weight: bold;
+    }
+
+    ::content td, th {
+      font-family: monospace;
+      vertical-align: top;
+    }
+    </style>
+    <slot></slot>
+  </template>
+</dom-module><dom-module id="tr-ui-a-power-sample-table">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-power-sample-sub-view">
+  <template>
+    <style>
+    :host { display: block; }
+    </style>
+    <tr-ui-a-power-sample-table id="samplesTable">
+    </tr-ui-a-power-sample-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-sample-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="content"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-thread-slice-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+    }
+    #events {
+      display: flex;
+      flex-direction: column;
+    }
+
+    </style>
+    <tr-ui-a-single-event-sub-view id="content"></tr-ui-a-single-event-sub-view>
+    <div id="events">
+      <tr-ui-a-related-events id="relatedEvents">
+      </tr-ui-a-related-events>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-thread-time-slice-sub-view">
+  <template>
+    <style>
+    table {
+      border-collapse: collapse;
+      border-width: 0;
+      margin-bottom: 25px;
+      width: 100%;
+    }
+
+    table tr > td:first-child {
+      padding-left: 2px;
+    }
+
+    table tr > td {
+      padding: 2px 4px 2px 4px;
+      vertical-align: text-top;
+      width: 150px;
+    }
+
+    table td td {
+      padding: 0 0 0 0;
+      width: auto;
+    }
+    tr {
+      vertical-align: top;
+    }
+
+    tr:nth-child(2n+0) {
+      background-color: #e2e2e2;
+    }
+    </style>
+    <table>
+      <tbody><tr>
+        <td>Running process:</td><td id="process-name"></td>
+      </tr>
+      <tr>
+        <td>Running thread:</td><td id="thread-name"></td>
+      </tr>
+      <tr>
+        <td>State:</td>
+        <td><b><span id="state"></span></b></td>
+      </tr>
+      <tr>
+        <td>Start:</td>
+        <td>
+          <tr-v-ui-scalar-span id="start">
+          </tr-v-ui-scalar-span>
+        </td>
+      </tr>
+      <tr>
+        <td>Duration:</td>
+        <td>
+          <tr-v-ui-scalar-span id="duration">
+          </tr-v-ui-scalar-span>
+        </td>
+      </tr>
+
+      <tr>
+        <td>On CPU:</td><td id="on-cpu"></td>
+      </tr>
+
+      <tr>
+        <td>Running instead:</td><td id="running-instead"></td>
+      </tr>
+
+      <tr>
+        <td>Args:</td><td id="args"></td>
+      </tr>
+    </tbody></table>
+  </template>
+</dom-module><dom-module id="tr-ui-a-single-user-expectation-sub-view">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: row;
+    }
+    #events {
+      display: flex;
+      flex-direction: column;
+    }
+    </style>
+    <tr-ui-a-single-event-sub-view id="realView"></tr-ui-a-single-event-sub-view>
+    <div id="events">
+      <tr-ui-a-user-expectation-related-samples-table id="relatedSamples"></tr-ui-a-user-expectation-related-samples-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-a-analysis-view">
+  <template>
+    <style>
+      :host {
+        background-color: white;
+        display: flex;
+        flex-direction: column;
+        height: 275px;
+        overflow: auto;
+      }
+
+      :host(.tall-mode) {
+        height: 525px;
+      }
+    </style>
+    <slot></slot>
+  </template>
+</dom-module><dom-module id="tr-ui-b-dropdown">
+  <template>
+    <style>
+    button {
+      @apply --dropdown-button;
+    }
+    button.open {
+      @apply --dropdown-button-open;
+    }
+    dialog {
+      position: absolute;
+      margin: 0;
+      padding: 1em;
+      border: 1px solid darkgrey;
+      @apply --dropdown-dialog;
+    }
+    </style>
+
+    <button id="button" on-tap="open">[[label]]</button>
+
+    <dialog id="dialog" on-cancel="close" on-tap="onDialogTap_">
+      <slot></slot>
+    </dialog>
+  </template>
+</dom-module><dom-module id="tr-ui-b-info-bar-group">
+  <template>
+    <style>
+    :host {
+      flex: 0 0 auto;
+      flex-direction: column;
+      display: flex;
+    }
+    </style>
+    <div id="messages"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-b-toolbar-button">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      background-color: #f8f8f8;
+      border: 1px solid rgba(0, 0, 0, 0.5);
+      color: rgba(0,0,0,0.8);
+      justify-content: center;
+      align-self: stretch;
+      min-width: 23px;
+    }
+
+    :host(:hover) {
+      background-color: rgba(255, 255, 255, 1.0);
+      border-color: rgba(0, 0, 0, 0.8);
+      box-shadow: 0 0 .05em rgba(0, 0, 0, 0.4);
+      color: rgba(0, 0, 0, 1);
+    }
+
+    #aligner {
+      display: flex;
+      flex: 0 0 auto;
+      align-self: center;
+    }
+    </style>
+    <div id="aligner">
+      <slot></slot>
+    </div>
+  </template>
+</dom-module><style>
+.drawing-container{display:inline;overflow:auto;overflow-x:hidden;position:relative}.drawing-container-canvas{display:block;pointer-events:none;position:absolute;top:0}
+</style><style>
+.letter-dot-track {
+  height: 18px;
+}
+</style><style>
+.chart-track {
+  height: 30px;
+  position: relative;
+}
+</style><style>
+.cpu-usage-track {
+  height: 90px;
+}
+</style><style>
+.power-series-track {
+  height: 90px;
+}
+</style><style>
+.spacing-track{height:4px}
+</style><style>
+.rect-track{height:18px}
+</style><style>
+.thread-track{flex-direction:column;display:flex;position:relative}
+</style><style>
+.process-track-header{display:flex;flex:0 0 auto;background-image:-webkit-gradient(linear,0 0,100% 0,from(#E5E5E5),to(#D1D1D1));border-bottom:1px solid #8e8e8e;border-top:1px solid white;font-size:75%}.process-track-name{flex-grow:1}.process-track-name:before{content:'\25B8';padding:0 5px}.process-track-base.expanded .process-track-name:before{content:'\25BE'}.process-track-close{color:black;border:1px solid transparent;padding:0px 2px}.process-track-close:hover{border:1px solid grey}
+</style><style>
+.model-track {
+  flex-grow: 1;
+}
+</style><style>
+.x-axis-track {
+  height: 12px;
+}
+
+.x-axis-track.tall-mode {
+  height: 30px;
+}
+</style><dom-module id="tr-ui-timeline-track-view">
+  <template>
+    <style>
+    :host {
+      flex-direction: column;
+      display: flex;
+      position: relative;
+    }
+
+    :host ::content * {
+      -webkit-user-select: none;
+      cursor: default;
+    }
+
+    #drag_box {
+      background-color: rgba(0, 0, 255, 0.25);
+      border: 1px solid rgb(0, 0, 96);
+      font-size: 75%;
+      position: fixed;
+    }
+
+    #hint_text {
+      position: absolute;
+      bottom: 6px;
+      right: 6px;
+      font-size: 8pt;
+    }
+    </style>
+    <slot></slot>
+
+    <div id="drag_box"></div>
+    <div id="hint_text"></div>
+
+    <tv-ui-b-hotkey-controller id="hotkey_controller">
+    </tv-ui-b-hotkey-controller>
+  </template>
+</dom-module><dom-module id="tr-ui-find-control">
+  <template>
+    <style>
+      :host {
+        -webkit-user-select: none;
+        display: flex;
+        position: relative;
+      }
+      input {
+        -webkit-user-select: auto;
+        background-color: #f8f8f8;
+        border: 1px solid rgba(0, 0, 0, 0.5);
+        box-sizing: border-box;
+        margin: 0;
+        padding: 0;
+        width: 170px;
+      }
+      input:focus {
+        background-color: white;
+      }
+      tr-ui-b-toolbar-button {
+        border-left: none;
+        margin: 0;
+      }
+      #hitCount {
+        left: 0;
+        opacity: 0.25;
+        pointer-events: none;
+        position: absolute;
+        text-align: right;
+        top: 2px;
+        width: 167px;
+        z-index: 1;
+      }
+      #spinner {
+        visibility: hidden;
+        width: 8px;
+        height: 8px;
+        left: 154px;
+        pointer-events: none;
+        position: absolute;
+        top: 4px;
+        z-index: 1;
+
+        border: 2px solid transparent;
+        border-bottom: 2px solid rgba(0, 0, 0, 0.5);
+        border-right: 2px solid rgba(0, 0, 0, 0.5);
+        border-radius: 50%;
+      }
+      @keyframes spin { 100% { transform: rotate(360deg); } }
+    </style>
+
+    <input id="filter" on-blur="filterBlur" on-focus="filterFocus" on-input="filterTextChanged" on-keydown="filterKeyDown" on-mouseup="filterMouseUp" type="text"/>
+    <div id="spinner"></div>
+    <tr-ui-b-toolbar-button on-click="findPrevious">
+      ←
+    </tr-ui-b-toolbar-button>
+    <tr-ui-b-toolbar-button on-click="findNext">
+      →
+    </tr-ui-b-toolbar-button>
+    <div id="hitCount">0 of 0</div>
+  </template>
+</dom-module><dom-module id="tr-ui-scripting-control">
+  <template>
+    <style>
+      :host {
+        flex: 1 1 auto;
+      }
+      .root {
+        font-family: monospace;
+        cursor: text;
+
+        padding: 2px;
+        margin: 2px;
+        border: 1px solid rgba(0, 0, 0, 0.5);
+        background: white;
+
+        height: 100px;
+        overflow-y: auto;
+
+        transition-property: opacity, height, padding, margin;
+        transition-duration: .2s;
+        transition-timing-function: ease-out;
+      }
+      .hidden {
+        margin-top: 0px;
+        margin-bottom: 0px;
+        padding-top: 0px;
+        padding-bottom: 0px;
+        height: 0px;
+        opacity: 0;
+      }
+      .focused {
+        outline: auto 5px -webkit-focus-ring-color;
+      }
+      #history {
+        -webkit-user-select: text;
+        color: #777;
+      }
+      #promptContainer {
+        display: flex;
+      }
+      #promptMark {
+        width: 1em;
+        color: #468;
+      }
+      #prompt {
+        flex: 1;
+        width: 100%;
+        border: none !important;
+        background-color: inherit !important;
+        font: inherit !important;
+        text-overflow: clip !important;
+        text-decoration: none !important;
+      }
+      #prompt:focus {
+        outline: none;
+      }
+    </style>
+
+    <div class="root hidden" id="root" on-focus="onConsoleFocus" tabindex="0">
+      <div id="history"></div>
+      <div id="promptContainer">
+        <span id="promptMark">&gt;</span>
+        <input id="prompt" on-blur="onConsoleBlur" on-keydown="promptKeyDown" on-keypress="promptKeyPress" type="text"/>
+       </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-side-panel-container">
+  <template>
+    <style>
+    :host {
+      align-items: stretch;
+      display: flex;
+      background-color: white;
+    }
+
+    :host([expanded]) > #side_panel_drag_handle,
+    :host([expanded]) > active-panel-container {
+      flex: 1 1 auto;
+      border-left: 1px solid black;
+      display: flex;
+    }
+
+    :host(:not([expanded])) > #side_panel_drag_handle,
+    :host(:not([expanded])) > active-panel-container {
+      display: none;
+    }
+
+    active-panel-container {
+      display: flex;
+    }
+
+    tab-strip {
+      flex: 0 0 auto;
+      flex-direction: column;
+      -webkit-user-select: none;
+      background-color: rgb(236, 236, 236);
+      border-left: 1px solid black;
+      cursor: default;
+      display: flex;
+      min-width: 18px; /* workaround for flexbox and writing-mode mixing bug */
+      padding: 10px 0 10px 0;
+      font-size: 12px;
+    }
+
+    tab-strip > tab-strip-label {
+      flex-shrink: 0;
+      -webkit-writing-mode: vertical-rl;
+      white-space: nowrap;
+      display: inline;
+      margin-right: 1px;
+      min-height: 20px;
+      padding: 15px 3px 15px 1px;
+    }
+
+    tab-strip >
+        tab-strip-label:not([enabled]) {
+      color: rgb(128, 128, 128);
+    }
+
+    tab-strip > tab-strip-label[selected] {
+      background-color: white;
+      border: 1px solid rgb(163, 163, 163);
+      border-left: none;
+      padding: 14px 2px 14px 1px;
+    }
+
+    #active_panel_container {
+      overflow: auto;
+    }
+    </style>
+
+    <tr-ui-b-drag-handle id="side_panel_drag_handle"></tr-ui-b-drag-handle>
+    <active-panel-container id="active_panel_container">
+    </active-panel-container>
+    <tab-strip id="tab_strip"></tab-strip>
+  </template>
+</dom-module><dom-module id="tr-ui-timeline-view-help-overlay">
+  <template>
+    <style>
+    :host {
+      flex: 1 1 auto;
+      flex-direction: row;
+      display: flex;
+      width: 700px;
+    }
+    .column {
+      width: 50%;
+    }
+    h2 {
+      font-size: 1.2em;
+      margin: 0;
+      margin-top: 5px;
+      text-align: center;
+    }
+    h3 {
+      margin: 0;
+      margin-left: 126px;
+      margin-top: 10px;
+    }
+    .pair {
+      flex: 1 1 auto;
+      flex-direction: row;
+      display: flex;
+    }
+    .command {
+      font-family: monospace;
+      margin-right: 5px;
+      text-align: right;
+      width: 150px;
+    }
+    .action {
+      font-size: 0.9em;
+      text-align: left;
+      width: 200px;
+    }
+    tr-ui-b-mouse-mode-icon {
+      border: 1px solid #888;
+      border-radius: 3px;
+      box-shadow: inset 0 0 2px rgba(0,0,0,0.3);
+      display: inline-block;
+      margin-right: 1px;
+      position: relative;
+      top: 4px;
+    }
+    .mouse-mode-icon.pan-mode {
+      background-position: -1px -11px;
+    }
+    .mouse-mode-icon.select-mode {
+      background-position: -1px -41px;
+    }
+    .mouse-mode-icon.zoom-mode {
+      background-position: -1px -71px;
+    }
+    .mouse-mode-icon.timing-mode {
+      background-position: -1px -101px;
+    }
+    </style>
+    <div class="column left">
+      <h2>Navigation</h2>
+      <div class="pair">
+        <div class="command">w/s</div>
+        <div class="action">Zoom in/out (+shift: faster)</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">a/d</div>
+        <div class="action">Pan left/right (+shift: faster)</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">→/shift-TAB</div>
+        <div class="action">Select previous event</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">←/TAB</div>
+        <div class="action">Select next event</div>
+      </div>
+
+      <h2>Mouse Controls</h2>
+      <div class="pair">
+        <div class="command">click</div>
+        <div class="action">Select event</div>
+      </div>
+      <div class="pair">
+        <div class="command">alt-mousewheel</div>
+        <div class="action">Zoom in/out</div>
+      </div>
+
+      <h3>
+        <tr-ui-b-mouse-mode-icon mode-name="SELECTION"></tr-ui-b-mouse-mode-icon>
+        Select mode
+      </h3>
+      <div class="pair">
+        <div class="command">drag</div>
+        <div class="action">Box select</div>
+      </div>
+
+      <div class="pair">
+        <div class="command"><span class="mod"></span>-click/drag</div>
+        <div class="action">Add events to the current selection</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">double click</div>
+        <div class="action">Select all events with same title</div>
+      </div>
+
+      <h3>
+        <tr-ui-b-mouse-mode-icon mode-name="PANSCAN"></tr-ui-b-mouse-mode-icon>
+        Pan mode
+      </h3>
+      <div class="pair">
+        <div class="command">drag</div>
+        <div class="action">Pan the view</div>
+      </div>
+
+      <h3>
+        <tr-ui-b-mouse-mode-icon mode-name="ZOOM"></tr-ui-b-mouse-mode-icon>
+        Zoom mode
+      </h3>
+      <div class="pair">
+        <div class="command">drag</div>
+        <div class="action">Zoom in/out by dragging up/down</div>
+      </div>
+
+      <h3>
+        <tr-ui-b-mouse-mode-icon mode-name="TIMING"></tr-ui-b-mouse-mode-icon>
+        Timing mode
+      </h3>
+      <div class="pair">
+        <div class="command">drag</div>
+        <div class="action">Create or move markers</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">double click</div>
+        <div class="action">Set marker range to slice</div>
+      </div>
+    </div>
+
+    <div class="column right">
+      <h2>General</h2>
+      <div class="pair">
+        <div class="command">1-4</div>
+        <div class="action">Switch mouse mode</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">shift</div>
+        <div class="action">Hold for temporary select</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">space</div>
+        <div class="action">Hold for temporary pan</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">/</div>
+        <div class="action">Search</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">enter</div>
+        <div class="action">Step through search results</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">f</div>
+        <div class="action">Zoom into selection</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">z/0</div>
+        <div class="action">Reset zoom and pan</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">g/G</div>
+        <div class="action">Toggle 60hz grid</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">v</div>
+        <div class="action">Highlight VSync</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">h</div>
+        <div class="action">Toggle low/high details</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">m</div>
+        <div class="action">Mark current selection</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">p</div>
+        <div class="action">Select power samples over current selection interval</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">`</div>
+        <div class="action">Show or hide the scripting console</div>
+      </div>
+
+      <div class="pair">
+        <div class="command">?</div>
+        <div class="action">Show help</div>
+      </div>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-timeline-view-metadata-overlay">
+  <template>
+    <style>
+    :host {
+      width: 700px;
+
+      overflow: auto;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-timeline-view">
+  <template>
+    <style>
+    :host {
+      flex-direction: column;
+      cursor: default;
+      display: flex;
+      font-family: sans-serif;
+      padding: 0;
+    }
+
+    #control {
+      background-color: #e6e6e6;
+      background-image: -webkit-gradient(linear, 0 0, 0 100%,
+          from(#E5E5E5), to(#D1D1D1));
+      flex: 0 0 auto;
+      overflow-x: auto;
+    }
+
+    #control::-webkit-scrollbar { height: 0px; }
+
+    #control > #bar {
+      font-size: 12px;
+      display: flex;
+      flex-direction: row;
+      margin: 1px;
+    }
+
+    #control > #bar > #title {
+      display: flex;
+      align-items: center;
+      padding-left: 8px;
+      padding-right: 8px;
+      flex: 1 1 auto;
+      overflow: hidden;
+      white-space: nowrap;
+    }
+
+    #control > #bar > #left_controls,
+    #control > #bar > #right_controls {
+      display: flex;
+      flex-direction: row;
+      align-items: stretch;
+      flex-shrink: 0;
+    }
+
+    #control > #bar > #left_controls > * { margin-right: 2px; }
+    #control > #bar > #right_controls > * { margin-left: 2px; }
+    #control > #collapsing_controls { display: flex; }
+
+    middle-container {
+      flex: 1 1 auto;
+      flex-direction: row;
+      border-bottom: 1px solid #8e8e8e;
+      display: flex;
+      min-height: 0;
+    }
+
+    middle-container ::content track-view-container {
+      flex: 1 1 auto;
+      display: flex;
+      min-height: 0;
+      min-width: 0;
+      overflow-x: hidden;
+    }
+
+    middle-container ::content track-view-container > * { flex: 1 1 auto; }
+    middle-container > x-timeline-view-side-panel-container { flex: 0 0 auto; }
+    tr-ui-b-drag-handle { flex: 0 0 auto; }
+    tr-ui-a-analysis-view { flex: 0 0 auto; }
+
+    tr-ui-b-dropdown {
+      --dropdown-button: {
+        -webkit-appearance: none;
+        align-items: normal;
+        background-color: rgb(248, 248, 248);
+        border: 1px solid rgba(0, 0, 0, 0.5);
+        box-sizing: content-box;
+        color: rgba(0, 0, 0, 0.8);
+        font-family: sans-serif;
+        font-size: 12px;
+        padding: 2px 5px;
+      }
+    }
+    </style>
+
+    <tv-ui-b-hotkey-controller id="hkc"></tv-ui-b-hotkey-controller>
+    <div id="control">
+      <div id="bar">
+        <div id="left_controls"></div>
+        <div id="title">^_^</div>
+        <div id="right_controls">
+          <tr-ui-b-dropdown id="flow_event_filter_dropdown" label="Flow events"></tr-ui-b-dropdown>
+          <tr-ui-b-dropdown id="process_filter_dropdown" label="Processes"></tr-ui-b-dropdown>
+          <tr-ui-b-toolbar-button id="view_metadata_button">
+            M
+          </tr-ui-b-toolbar-button>
+          <tr-ui-b-dropdown id="view_options_dropdown" label="View Options"></tr-ui-b-dropdown>
+          <tr-ui-find-control id="view_find_control"></tr-ui-find-control>
+          <tr-ui-b-toolbar-button id="view_console_button">
+            »
+          </tr-ui-b-toolbar-button>
+          <tr-ui-b-toolbar-button id="view_help_button">
+            ?
+          </tr-ui-b-toolbar-button>
+        </div>
+      </div>
+      <div id="collapsing_controls"></div>
+      <tr-ui-b-info-bar-group id="import-warnings">
+      </tr-ui-b-info-bar-group>
+      <tr-ui-b-info-bar-group id="polyfill-warning">
+      </tr-ui-b-info-bar-group>
+    </div>
+    <middle-container>
+      <slot></slot>
+
+      <tr-ui-side-panel-container id="side_panel_container">
+      </tr-ui-side-panel-container>
+    </middle-container>
+    <tr-ui-b-drag-handle id="drag_handle"></tr-ui-b-drag-handle>
+    <tr-ui-a-analysis-view id="analysis"></tr-ui-a-analysis-view>
+
+    <tr-v-ui-preferred-display-unit id="display_unit">
+    </tr-v-ui-preferred-display-unit>
+  </template>
+</dom-module><dom-module id="tr-ui-b-grouping-table">
+  <template>
+    <style>
+    :host {
+      display: flex;
+    }
+    #table {
+      flex: 1 1 auto;
+      font-size: 12px;
+    }
+    </style>
+    <tr-ui-b-table id="table"></tr-ui-b-table>
+  </template>
+</dom-module><dom-module id="tr-ui-b-grouping-table-groupby-picker">
+  <template>
+    <style>
+    #container {
+      display: flex;
+    }
+    #container *:not(:first-child) {
+      padding-left: 3px;
+      border-left: 1px solid black;
+      margin-left: 3px;
+    }
+    </style>
+
+    <div id="container"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-b-grouping-table-groupby-picker-group">
+  <template>
+    <style>
+    :host {
+      white-space: nowrap;
+    }
+    #left, #right {
+      user-select: none;
+      cursor: pointer;
+    }
+    </style>
+
+    <span id="left" on-click="moveLeft_">◀</span>
+    <input id="enabled" on-change="onEnableChanged_" type="checkbox"/>
+    <label for="enabled" id="label"></label>
+    <span id="right" on-click="moveRight_">▶</span>
+  </template>
+</dom-module><dom-module id="tr-ui-sp-file-size-stats-side-panel">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    toolbar {
+      align-items: center;
+      background-color: rgb(236, 236, 236);
+      border-bottom: 1px solid #8e8e8e;
+      display: flex;
+      flex-direction: row;
+      flex-direction: row;
+      flex: 0 0 auto;
+      font-size: 12px;
+      padding: 0 10px 0 10px;
+    }
+    table-container {
+      display: flex;
+      min-height: 0px;
+      overflow-y: auto;
+    }
+    </style>
+
+    <toolbar>
+      <span><b>Group by:</b></span>
+      <tr-ui-b-grouping-table-groupby-picker id="picker">
+      </tr-ui-b-grouping-table-groupby-picker>
+    </toolbar>
+    <table-container>
+      <tr-ui-b-grouping-table id="table"></tr-ui-b-grouping-table>
+    </table-container>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-controls-export">
+  <template>
+    <style>
+    :host {
+      display: grid;
+      grid-gap: 1em;
+      grid-template-rows: auto auto;
+      grid-template-columns: auto auto;
+    }
+    button {
+      -webkit-appearance: none;
+      border: 0;
+      font-size: initial;
+      padding: 5px;
+    }
+    </style>
+
+    <button on-tap="exportRawCsv_">raw CSV</button>
+    <button on-tap="exportRawJson_">raw JSON</button>
+    <button on-tap="exportMergedCsv_">merged CSV</button>
+    <button on-tap="exportMergedJson_">merged JSON</button>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-controls">
+  <template>
+    <style>
+    :host {
+      display: block;
+    }
+
+    #help, #feedback {
+      display: none;
+      margin-left: 20px;
+    }
+
+    #search_container {
+      display: inline-flex;
+      margin-right: 20px;
+      padding-bottom: 1px;
+      border-bottom: 1px solid darkgrey;
+    }
+
+    #search {
+      border: 0;
+      max-width: 20em;
+      outline: none;
+    }
+
+    #clear_search {
+      visibility: hidden;
+      height: 1em;
+      stroke: black;
+      stroke-width: 16;
+    }
+
+    #controls {
+      white-space: nowrap;
+    }
+
+    #show_overview, #hide_overview {
+      height: 1em;
+      margin-right: 20px;
+    }
+
+    #show_overview {
+      stroke: blue;
+      stroke-width: 16;
+    }
+
+    #show_overview:hover {
+      background: blue;
+      stroke: white;
+    }
+
+    #hide_overview {
+      display: none;
+      stroke-width: 18;
+      stroke: black;
+    }
+
+    #hide_overview:hover {
+      background: black;
+      stroke: white;
+    }
+
+    #reference_display_label {
+      display: none;
+      margin-right: 20px;
+    }
+
+    #alpha, #alpha_slider_container {
+      display: none;
+    }
+
+    #alpha {
+      margin-right: 20px;
+    }
+
+    #alpha_slider_container {
+      background: white;
+      border: 1px solid black;
+      flex-direction: column;
+      padding: 0.5em;
+      position: absolute;
+      z-index: 10; /* scalar-span uses z-index :-( */
+    }
+
+    #alpha_slider {
+      -webkit-appearance: slider-vertical;
+      align-self: center;
+      height: 200px;
+      width: 30px;
+    }
+
+    #statistic {
+      display: none;
+      margin-right: 20px;
+    }
+
+    #show_visualization {
+      margin-right: 20px;
+    }
+
+    #export {
+      margin-right: 20px;
+    }
+    </style>
+
+    <div id="controls">
+      <span id="search_container">
+        <input id="search" placeholder="Find Histogram name" value="{{searchQuery::keyup}}"/>
+        <svg id="clear_search" on-tap="clearSearch_" viewBox="0 0 128 128">
+          <g>
+          <title>Clear search</title>
+          <line x1="28" x2="100" y1="28" y2="100"></line>
+          <line x1="28" x2="100" y1="100" y2="28"></line>
+          </g>
+        </svg>
+      </span>
+
+      <svg id="show_overview" on-tap="toggleOverviewLineCharts_" viewBox="0 0 128 128">
+        <g>
+        <title>Show overview charts</title>
+        <line x1="19" x2="49" y1="109" y2="49"></line>
+        <line x1="49" x2="79" y1="49" y2="79"></line>
+        <line x1="79" x2="109" y1="79" y2="19"></line>
+        </g>
+      </svg>
+      <svg id="hide_overview" on-tap="toggleOverviewLineCharts_" viewBox="0 0 128 128">
+        <g>
+        <title>Hide overview charts</title>
+        <line x1="28" x2="100" y1="28" y2="100"></line>
+        <line x1="28" x2="100" y1="100" y2="28"></line>
+        </g>
+      </svg>
+
+      <select id="reference_display_label" value="{{referenceDisplayLabel::change}}">
+        <option value="">Select a reference column</option>
+      </select>
+
+      <button id="alpha" on-tap="openAlphaSlider_">α=[[alphaString]]</button>
+      <div id="alpha_slider_container">
+        <input id="alpha_slider" max="18" min="0" on-blur="closeAlphaSlider_" on-input="updateAlpha_" type="range" value="{{alphaIndex::change}}"/>
+      </div>
+
+      <select id="statistic" value="{{displayStatisticName::change}}">
+      </select>
+
+      <button id="show_visualization" on-tap="loadVisualization_">Visualize</button>
+
+      <tr-ui-b-dropdown label="Export">
+        <tr-v-ui-histogram-set-controls-export>
+        </tr-v-ui-histogram-set-controls-export>
+      </tr-ui-b-dropdown>
+
+      <input checked="{{showAll::change}}" id="show_all" title="When unchecked, less important histograms are hidden." type="checkbox"/>
+      <label for="show_all" title="When unchecked, less important histograms are hidden.">Show all</label>
+
+      <a id="help">Help</a>
+      <a id="feedback">Feedback</a>
+    </div>
+
+    <tr-ui-b-grouping-table-groupby-picker id="picker">
+    </tr-ui-b-grouping-table-groupby-picker>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-table-cell">
+  <template>
+    <style>
+    #histogram_container {
+      display: flex;
+      flex-direction: row;
+    }
+
+    #missing, #empty, #unmergeable, #scalar {
+      flex-grow: 1;
+    }
+
+    #open_histogram, #close_histogram, #open_histogram svg, #close_histogram svg {
+      height: 1em;
+    }
+
+    #open_histogram svg {
+      margin-left: 4px;
+      stroke-width: 0;
+      stroke: blue;
+      fill: blue;
+    }
+    :host(:hover) #open_histogram svg {
+      background: blue;
+      stroke: white;
+      fill: white;
+    }
+
+    #scalar {
+      flex-grow: 1;
+      white-space: nowrap;
+    }
+
+    #histogram {
+      flex-grow: 1;
+    }
+
+    #close_histogram svg line {
+      stroke-width: 18;
+      stroke: black;
+    }
+    #close_histogram:hover svg {
+      background: black;
+    }
+    #close_histogram:hover svg line {
+      stroke: white;
+    }
+
+    #overview_container {
+      display: none;
+    }
+    </style>
+
+    <div id="histogram_container">
+      <span id="missing">(missing)</span>
+      <span id="empty">(empty)</span>
+      <span id="unmergeable">(unmergeable)</span>
+
+      <tr-v-ui-scalar-span id="scalar" on-click="openHistogram_"></tr-v-ui-scalar-span>
+
+      <span id="open_histogram" on-click="openHistogram_">
+        <svg viewBox="0 0 128 128">
+          <rect height="16" width="32" x="16" y="24"></rect>
+          <rect height="16" width="96" x="16" y="56"></rect>
+          <rect height="16" width="64" x="16" y="88"></rect>
+        </svg>
+      </span>
+
+      <span id="histogram"></span>
+
+      <span id="close_histogram" on-click="closeHistogram_">
+        <svg viewBox="0 0 128 128">
+          <line x1="28" x2="100" y1="28" y2="100"></line>
+          <line x1="28" x2="100" y1="100" y2="28"></line>
+        </svg>
+      </span>
+    </div>
+
+    <div id="overview_container">
+    </div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-table-name-cell">
+  <template>
+    <style>
+    #name_container {
+      display: flex;
+    }
+
+    #name {
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
+
+    #show_overview, #hide_overview, #show_overview svg, #hide_overview svg {
+      height: 1em;
+      margin-left: 5px;
+    }
+
+    #show_overview svg {
+      stroke: blue;
+      stroke-width: 16;
+    }
+
+    #show_overview:hover svg {
+      background: blue;
+      stroke: white;
+    }
+
+    #hide_overview {
+      display: none;
+    }
+
+    #hide_overview svg {
+      stroke-width: 18;
+      stroke: black;
+    }
+
+    #hide_overview:hover svg {
+      background: black;
+      stroke: white;
+    }
+
+    #open_histograms, #close_histograms, #open_histograms svg, #close_histograms svg {
+      height: 1em;
+    }
+
+    #close_histograms {
+      display: none;
+    }
+
+    #open_histograms svg {
+      margin-left: 4px;
+      stroke-width: 0;
+      stroke: blue;
+      fill: blue;
+    }
+    #open_histograms:hover svg {
+      background: blue;
+      stroke: white;
+      fill: white;
+    }
+
+    #close_histograms line {
+      stroke-width: 18;
+      stroke: black;
+    }
+    #close_histograms:hover {
+      background: black;
+    }
+    #close_histograms:hover line {
+      stroke: white;
+    }
+
+    #overview_container {
+      display: none;
+    }
+    </style>
+
+    <div id="name_container">
+      <span id="name"></span>
+
+      <span id="show_overview" on-click="showOverview_">
+        <svg viewBox="0 0 128 128">
+          <line x1="19" x2="49" y1="109" y2="49"></line>
+          <line x1="49" x2="79" y1="49" y2="79"></line>
+          <line x1="79" x2="109" y1="79" y2="19"></line>
+        </svg>
+      </span>
+
+      <span id="hide_overview" on-click="hideOverview_">
+        <svg viewBox="0 0 128 128">
+          <line x1="28" x2="100" y1="28" y2="100"></line>
+          <line x1="28" x2="100" y1="100" y2="28"></line>
+        </svg>
+      </span>
+
+      <span id="open_histograms" on-click="openHistograms_">
+        <svg viewBox="0 0 128 128">
+          <rect height="16" width="32" x="16" y="24"></rect>
+          <rect height="16" width="96" x="16" y="56"></rect>
+          <rect height="16" width="64" x="16" y="88"></rect>
+        </svg>
+      </span>
+
+      <span id="close_histograms" on-click="closeHistograms_">
+        <svg viewBox="0 0 128 128">
+          <line x1="28" x2="100" y1="28" y2="100"></line>
+          <line x1="28" x2="100" y1="100" y2="28"></line>
+        </svg>
+      </span>
+    </div>
+
+    <div id="overview_container">
+    </div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-table">
+  <template>
+    <style>
+    :host {
+      min-height: 0px;
+      overflow: auto;
+    }
+    #table {
+      margin-top: 5px;
+    }
+    </style>
+
+    <tr-ui-b-table id="table">
+  </tr-ui-b-table></template>
+</dom-module><dom-module id="tr-v-ui-metrics-visualization">
+  <template>
+    <style>
+      button {
+        padding: 5px;
+        font-size: 14px;
+      }
+
+      .text_input {
+        width: 50px;
+        padding: 4px;
+        font-size: 14px;
+      }
+
+      .error {
+        color: red;
+        display: none;
+      }
+
+      .container {
+        position: relative;
+        display: inline-block;
+        margin-left: 15px;
+      }
+
+      #title {
+        font-size: 20px;
+        font-weight: bold;
+        padding-bottom: 5px;
+      }
+
+      #selectors {
+        display: block;
+        padding-bottom: 10px;
+      }
+
+      #search_page {
+        width: 200px;
+        margin-left: 30px;
+      }
+
+      #close {
+        display: none;
+        vertical-align: top;
+      }
+
+      #close svg{
+        height: 1em;
+      }
+
+      #close svg line {
+        stroke-width: 18;
+        stroke: black;
+      }
+
+      #close:hover svg {
+        background: black;
+      }
+
+      #close:hover svg line {
+        stroke: white;
+      }
+    </style>
+      <span class="container" id="aggregateContainer">
+      </span>
+      <span class="container" id="pageByPageContainer">
+        <span id="selectors">
+          <span id="percentile_label">Percentile Range:</span>
+          <input class="text_input" id="start" placeholder="0"/>
+          <input class="text_input" id="end" placeholder="100"/>
+          <button id="filter" on-tap="filterByPercentile_">Filter</button>
+          <input class="text_input" id="search_page" placeholder="Page Name"/>
+          <button id="search" on-tap="searchByPage_">Search</button>
+          <span class="error" id="search_error">Sorry, could not find that page!</span>
+        </span>
+      </span>
+      <div display="block" id="submetricsContainer">
+        <span id="close">
+          <svg viewBox="0 0 128 128">
+            <line x1="28" x2="100" y1="28" y2="100"></line>
+            <line x1="28" x2="100" y1="100" y2="28"></line>
+          </svg>
+        </span>
+      </div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-raster-visualization">
+  <template>
+    <style>
+      button {
+        padding: 5px;
+        font-size: 14px;
+      }
+      .error {
+        color: red;
+        display: none;
+      }
+
+      .text_input {
+        width: 200px;
+        padding: 4px;
+        font-size: 14px;
+      }
+
+      .selector_container{
+        padding: 5px;
+      }
+
+      #search {
+        display: inline-block;
+        padding-bottom: 10px;
+      }
+
+      #search_page {
+        width: 200px;
+      }
+
+      #pageSelector {
+        display: inline-block;
+        font-size: 12pt;
+      }
+
+      #close {
+        display: none;
+        vertical-align: top;
+      }
+
+      #close svg{
+        height: 1em;
+      }
+
+      #close svg line {
+        stroke-width: 18;
+        stroke: black;
+      }
+
+      #close:hover svg {
+        background: black;
+      }
+
+      #close:hover svg line {
+        stroke: white;
+      }
+    </style>
+    <span id="aggregateContainer">
+      <div>
+        <div class="selector_container">
+          <span id="select_page_label">Individual Page Results:</span>
+          <select id="pageSelector">
+            <option id="select_page" value="">Select a page</option>
+          </select>
+        </div>
+        <div class="selector_container">
+          <div id="search_page_label">Search for a page:</div>
+          <input class="text_input" id="search_page" placeholder="Page Name"/>
+          <button id="search_button">Search</button>
+          <div class="error" id="search_error">Sorry, could not find that page!</div>
+        </div>
+      </div>
+    </span>
+    <span id="pageContainer">
+      <span id="close">
+          <svg viewBox="0 0 128 128">
+            <line x1="28" x2="100" y1="28" y2="100"></line>
+            <line x1="28" x2="100" y1="100" y2="28"></line>
+          </svg>
+        </span>
+      </span>
+  </template>
+</dom-module><meta charset="utf-8"/><dom-module id="tr-v-ui-visualizations-data-container">
+  <template>
+    <style>
+      .error {
+        color: red;
+        display: none;
+      }
+
+      .sample{
+        display: none;
+      }
+
+      .subtitle{
+        font-size: 20px;
+        font-weight: bold;
+        padding-bottom: 5px;
+      }
+
+      .description{
+        font-size: 15px;
+        padding-bottom: 5px;
+      }
+
+      #title {
+        font-size: 30px;
+        font-weight: bold;
+        padding-bottom: 5px;
+      }
+    </style>
+    <div id="title">Visualizations</div>
+    <div class="error" id="data_error">Invalid data provided.</div>
+    <div id="pipeline_per_frame_container">
+      <div class="subtitle">Graphics Pipeline and Raster Tasks</div>
+      <div class="description">
+        When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
+        Only pages where raster tasks are completed after beginFrame is issued are included.
+      </div>
+      <tr-v-ui-raster-visualization id="rasterVisualization">
+      </tr-v-ui-raster-visualization>
+    </div>
+    <div id="metrics_container">
+      <div class="subtitle">Metrics</div>
+      <div class="description">Total amount of time taken for the indicated metrics.</div>
+      <tr-v-ui-metrics-visualization class="sample" id="metricsVisualization">
+      </tr-v-ui-metrics-visualization>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-v-ui-histogram-set-view">
+  <template>
+    <style>
+    :host {
+      font-family: sans-serif;
+    }
+
+    #zero {
+      color: red;
+      /* histogram-set-table is used by both metrics-side-panel and results.html.
+       * This font-size rule has no effect in results.html, but improves
+       * legibility in the metrics-side-panel, which sets font-size in order to
+       * make this table denser.
+       */
+      font-size: initial;
+    }
+
+    #container {
+      display: none;
+    }
+
+    #visualizations{
+      display: none;
+    }
+    </style>
+
+    <div id="zero">zero Histograms</div>
+
+    <div id="container">
+      <tr-v-ui-histogram-set-controls id="controls">
+      </tr-v-ui-histogram-set-controls>
+
+      <tr-v-ui-visualizations-data-container id="visualizations">
+      </tr-v-ui-visualizations-data-container>
+
+      <tr-v-ui-histogram-set-table id="table"></tr-v-ui-histogram-set-table>
+    </div>
+  </template>
+</dom-module><dom-module id="tr-ui-sp-metrics-side-panel">
+  <template>
+    <style>
+    :host {
+      display: flex;
+      flex-direction: column;
+    }
+    div#error {
+      color: red;
+    }
+    #results {
+      font-size: 12px;
+    }
+    </style>
+
+    <top-left-controls id="top_left_controls"></top-left-controls>
+
+    <tr-v-ui-histogram-set-view id="results"></tr-v-ui-histogram-set-view>
+
+    <div id="error"></div>
+  </template>
+</dom-module><dom-module id="tr-ui-e-s-alerts-side-panel">
+  <template>
+    <style>
+    :host {
+      display: block;
+      width: 250px;
+    }
+    #content {
+      flex-direction: column;
+      display: flex;
+    }
+    tr-ui-b-table {
+      font-size: 12px;
+    }
+    </style>
+
+    <div id="content">
+      <toolbar id="toolbar"></toolbar>
+      <result-area id="result_area"></result-area>
+    </div>
+  </template>
+</dom-module><script>
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/* WARNING: This file is auto generated.
+ *
+ * Do not edit directly.
+ */
+
+'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(window.Polymer){throw new Error('Cannot proceed. Polymer already present.');}
+window.Polymer={};window.Polymer.dom='shadow';}
+(function(){function resolve(){document.body.removeAttribute('unresolved');}
+if(window.WebComponents){addEventListener('WebComponentsReady',resolve);}else{if(document.readyState==='interactive'||document.readyState==='complete'){resolve();}else{addEventListener('DOMContentLoaded',resolve);}}}());window.Polymer={Settings:function(){var settings=window.Polymer||{};if(!settings.noUrlSettings){var parts=location.search.slice(1).split('&');for(var i=0,o;i<parts.length&&(o=parts[i]);i++){o=o.split('=');o[0]&&(settings[o[0]]=o[1]||true);}}
+settings.wantShadow=settings.dom==='shadow';settings.hasShadow=Boolean(Element.prototype.createShadowRoot);settings.nativeShadow=settings.hasShadow&&!window.ShadowDOMPolyfill;settings.useShadow=settings.wantShadow&&settings.hasShadow;settings.hasNativeImports=Boolean('import'in document.createElement('link'));settings.useNativeImports=settings.hasNativeImports;settings.useNativeCustomElements=!window.CustomElements||window.CustomElements.useNative;settings.useNativeShadow=settings.useShadow&&settings.nativeShadow;settings.usePolyfillProto=!settings.useNativeCustomElements&&!Object.__proto__;settings.hasNativeCSSProperties=!navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)&&window.CSS&&CSS.supports&&CSS.supports('box-shadow','0 0 0 var(--foo)');settings.useNativeCSSProperties=settings.hasNativeCSSProperties&&settings.lazyRegister&&settings.useNativeCSSProperties;settings.isIE=navigator.userAgent.match('Trident');settings.passiveTouchGestures=settings.passiveTouchGestures||false;return settings;}()};(function(){var userPolymer=window.Polymer;window.Polymer=function(prototype){if(typeof prototype==='function'){prototype=prototype.prototype;}
+if(!prototype){prototype={};}
+prototype=desugar(prototype);var customCtor=prototype===prototype.constructor.prototype?prototype.constructor:null;var options={prototype:prototype};if(prototype.extends){options.extends=prototype.extends;}
+Polymer.telemetry._registrate(prototype);var ctor=document.registerElement(prototype.is,options);return customCtor||ctor;};var desugar=function(prototype){var base=Polymer.Base;if(prototype.extends){base=Polymer.Base._getExtendedPrototype(prototype.extends);}
+prototype=Polymer.Base.chainObject(prototype,base);prototype.registerCallback();return prototype;};if(userPolymer){for(var i in userPolymer){Polymer[i]=userPolymer[i];}}
+Polymer.Class=function(prototype){if(!prototype.factoryImpl){prototype.factoryImpl=function(){};}
+return desugar(prototype).constructor;};}());Polymer.telemetry={registrations:[],_regLog:function(prototype){console.log('['+prototype.is+']: registered');},_registrate:function(prototype){this.registrations.push(prototype);Polymer.log&&this._regLog(prototype);},dumpRegistrations:function(){this.registrations.forEach(this._regLog);}};Object.defineProperty(window,'currentImport',{enumerable:true,configurable:true,get:function(){return(document._currentScript||document.currentScript||{}).ownerDocument;}});Polymer.RenderStatus={_ready:false,_callbacks:[],whenReady:function(cb){if(this._ready){cb();}else{this._callbacks.push(cb);}},_makeReady:function(){this._ready=true;for(var i=0;i<this._callbacks.length;i++){this._callbacks[i]();}
+this._callbacks=[];},_catchFirstRender:function(){requestAnimationFrame(function(){Polymer.RenderStatus._makeReady();});},_afterNextRenderQueue:[],_waitingNextRender:false,afterNextRender:function(element,fn,args){this._watchNextRender();this._afterNextRenderQueue.push([element,fn,args]);},hasRendered:function(){return this._ready;},_watchNextRender:function(){if(!this._waitingNextRender){this._waitingNextRender=true;var fn=function(){Polymer.RenderStatus._flushNextRender();};if(!this._ready){this.whenReady(fn);}else{requestAnimationFrame(fn);}}},_flushNextRender:function(){var self=this;setTimeout(function(){self._flushRenderCallbacks(self._afterNextRenderQueue);self._afterNextRenderQueue=[];self._waitingNextRender=false;});},_flushRenderCallbacks:function(callbacks){for(var i=0,h;i<callbacks.length;i++){h=callbacks[i];h[1].apply(h[0],h[2]||Polymer.nar);}}};if(window.HTMLImports){HTMLImports.whenReady(function(){Polymer.RenderStatus._catchFirstRender();});}else{Polymer.RenderStatus._catchFirstRender();}
+Polymer.ImportStatus=Polymer.RenderStatus;Polymer.ImportStatus.whenLoaded=Polymer.ImportStatus.whenReady;(function(){'use strict';var settings=Polymer.Settings;Polymer.Base={__isPolymerInstance__:true,_addFeature:function(feature){this.mixin(this,feature);},registerCallback:function(){if(settings.lazyRegister==='max'){if(this.beforeRegister){this.beforeRegister();}}else{this._desugarBehaviors();for(var i=0,b;i<this.behaviors.length;i++){b=this.behaviors[i];if(b.beforeRegister){b.beforeRegister.call(this);}}
+if(this.beforeRegister){this.beforeRegister();}}
+this._registerFeatures();if(!settings.lazyRegister){this.ensureRegisterFinished();}},createdCallback:function(){if(settings.disableUpgradeEnabled){if(this.hasAttribute('disable-upgrade')){this._propertySetter=disableUpgradePropertySetter;this._configValue=null;this.__data__={};return;}else{this.__hasInitialized=true;}}
+this.__initialize();},__initialize:function(){if(!this.__hasRegisterFinished){this._ensureRegisterFinished(this.__proto__);}
+Polymer.telemetry.instanceCount++;this.root=this;for(var i=0,b;i<this.behaviors.length;i++){b=this.behaviors[i];if(b.created){b.created.call(this);}}
+if(this.created){this.created();}
+this._initFeatures();},ensureRegisterFinished:function(){this._ensureRegisterFinished(this);},_ensureRegisterFinished:function(proto){if(proto.__hasRegisterFinished!==proto.is||!proto.is){if(settings.lazyRegister==='max'){proto._desugarBehaviors();for(var i=0,b;i<proto.behaviors.length;i++){b=proto.behaviors[i];if(b.beforeRegister){b.beforeRegister.call(proto);}}}
+proto.__hasRegisterFinished=proto.is;if(proto._finishRegisterFeatures){proto._finishRegisterFeatures();}
+for(var j=0,pb;j<proto.behaviors.length;j++){pb=proto.behaviors[j];if(pb.registered){pb.registered.call(proto);}}
+if(proto.registered){proto.registered();}
+if(settings.usePolyfillProto&&proto!==this){proto.extend(this,proto);}}},attachedCallback:function(){var self=this;Polymer.RenderStatus.whenReady(function(){self.isAttached=true;for(var i=0,b;i<self.behaviors.length;i++){b=self.behaviors[i];if(b.attached){b.attached.call(self);}}
+if(self.attached){self.attached();}});},detachedCallback:function(){var self=this;Polymer.RenderStatus.whenReady(function(){self.isAttached=false;for(var i=0,b;i<self.behaviors.length;i++){b=self.behaviors[i];if(b.detached){b.detached.call(self);}}
+if(self.detached){self.detached();}});},attributeChangedCallback:function(name,oldValue,newValue){this._attributeChangedImpl(name);for(var i=0,b;i<this.behaviors.length;i++){b=this.behaviors[i];if(b.attributeChanged){b.attributeChanged.call(this,name,oldValue,newValue);}}
+if(this.attributeChanged){this.attributeChanged(name,oldValue,newValue);}},_attributeChangedImpl:function(name){this._setAttributeToProperty(this,name);},extend:function(target,source){if(target&&source){var n$=Object.getOwnPropertyNames(source);for(var i=0,n;i<n$.length&&(n=n$[i]);i++){this.copyOwnProperty(n,source,target);}}
+return target||source;},mixin:function(target,source){for(var i in source){target[i]=source[i];}
+return target;},copyOwnProperty:function(name,source,target){var pd=Object.getOwnPropertyDescriptor(source,name);if(pd){Object.defineProperty(target,name,pd);}},_logger:function(level,args){if(args.length===1&&Array.isArray(args[0])){args=args[0];}
+switch(level){case'log':case'warn':case'error':console[level].apply(console,args);break;}},_log:function(){var args=Array.prototype.slice.call(arguments,0);this._logger('log',args);},_warn:function(){var args=Array.prototype.slice.call(arguments,0);this._logger('warn',args);},_error:function(){var args=Array.prototype.slice.call(arguments,0);this._logger('error',args);},_logf:function(){return this._logPrefix.concat(this.is).concat(Array.prototype.slice.call(arguments,0));}};Polymer.Base._logPrefix=function(){var color=window.chrome&&!/edge/i.test(navigator.userAgent)||/firefox/i.test(navigator.userAgent);return color?['%c[%s::%s]:','font-weight: bold; background-color:#EEEE00;']:['[%s::%s]:'];}();Polymer.Base.chainObject=function(object,inherited){if(object&&inherited&&object!==inherited){if(!Object.__proto__){object=Polymer.Base.extend(Object.create(inherited),object);}
+object.__proto__=inherited;}
+return object;};Polymer.Base=Polymer.Base.chainObject(Polymer.Base,HTMLElement.prototype);Polymer.BaseDescriptors={};var disableUpgradePropertySetter;if(settings.disableUpgradeEnabled){disableUpgradePropertySetter=function(property,value){this.__data__[property]=value;};var origAttributeChangedCallback=Polymer.Base.attributeChangedCallback;Polymer.Base.attributeChangedCallback=function(name,oldValue,newValue){if(!this.__hasInitialized&&name==='disable-upgrade'){this.__hasInitialized=true;this._propertySetter=Polymer.Bind._modelApi._propertySetter;this._configValue=Polymer.Base._configValue;this.__initialize();}
+origAttributeChangedCallback.call(this,name,oldValue,newValue);};}
+if(window.CustomElements){Polymer.instanceof=CustomElements.instanceof;}else{Polymer.instanceof=function(obj,ctor){return obj instanceof ctor;};}
+Polymer.isInstance=function(obj){return Boolean(obj&&obj.__isPolymerInstance__);};Polymer.telemetry.instanceCount=0;}());(function(){var modules={};var lcModules={};var findModule=function(id){return modules[id]||lcModules[id.toLowerCase()];};var DomModule=function(){return document.createElement('dom-module');};DomModule.prototype=Object.create(HTMLElement.prototype);Polymer.Base.mixin(DomModule.prototype,{createdCallback:function(){this.register();},register:function(id){id=id||this.id||this.getAttribute('name')||this.getAttribute('is');if(id){this.id=id;modules[id]=this;lcModules[id.toLowerCase()]=this;}},import:function(id,selector){if(id){var m=findModule(id);if(!m){forceDomModulesUpgrade();m=findModule(id);}
+if(m&&selector){m=m.querySelector(selector);}
+return m;}}});Object.defineProperty(DomModule.prototype,'constructor',{value:DomModule,configurable:true,writable:true});var cePolyfill=window.CustomElements&&!CustomElements.useNative;document.registerElement('dom-module',DomModule);function forceDomModulesUpgrade(){if(cePolyfill){var script=document._currentScript||document.currentScript;var doc=script&&script.ownerDocument||document;var modules=doc.querySelectorAll('dom-module');for(var i=modules.length-1,m;i>=0&&(m=modules[i]);i--){if(m.__upgraded__){return;}else{CustomElements.upgrade(m);}}}}}());Polymer.Base._addFeature({_prepIs:function(){if(!this.is){var module=(document._currentScript||document.currentScript).parentNode;if(module.localName==='dom-module'){var id=module.id||module.getAttribute('name')||module.getAttribute('is');this.is=id;}}
+if(this.is){this.is=this.is.toLowerCase();}}});Polymer.Base._addFeature({behaviors:[],_desugarBehaviors:function(){if(this.behaviors.length){this.behaviors=this._desugarSomeBehaviors(this.behaviors);}},_desugarSomeBehaviors:function(behaviors){var behaviorSet=[];behaviors=this._flattenBehaviorsList(behaviors);for(var i=behaviors.length-1;i>=0;i--){var b=behaviors[i];if(behaviorSet.indexOf(b)===-1){this._mixinBehavior(b);behaviorSet.unshift(b);}}
+return behaviorSet;},_flattenBehaviorsList:function(behaviors){var flat=[];for(var i=0;i<behaviors.length;i++){var b=behaviors[i];if(b instanceof Array){flat=flat.concat(this._flattenBehaviorsList(b));}else if(b){flat.push(b);}else{this._warn(this._logf('_flattenBehaviorsList','behavior is null, check for missing or 404 import'));}}
+return flat;},_mixinBehavior:function(b){var n$=Object.getOwnPropertyNames(b);var useAssignment=b._noAccessors;for(var i=0,n;i<n$.length&&(n=n$[i]);i++){if(!Polymer.Base._behaviorProperties[n]&&!this.hasOwnProperty(n)){if(useAssignment){this[n]=b[n];}else{this.copyOwnProperty(n,b,this);}}}},_prepBehaviors:function(){this._prepFlattenedBehaviors(this.behaviors);},_prepFlattenedBehaviors:function(behaviors){for(var i=0,l=behaviors.length;i<l;i++){this._prepBehavior(behaviors[i]);}
+this._prepBehavior(this);},_marshalBehaviors:function(){for(var i=0;i<this.behaviors.length;i++){this._marshalBehavior(this.behaviors[i]);}
+this._marshalBehavior(this);}});Polymer.Base._behaviorProperties={hostAttributes:true,beforeRegister:true,registered:true,properties:true,observers:true,listeners:true,created:true,attached:true,detached:true,attributeChanged:true,ready:true,_noAccessors:true};Polymer.Base._addFeature({_getExtendedPrototype:function(tag){return this._getExtendedNativePrototype(tag);},_nativePrototypes:{},_getExtendedNativePrototype:function(tag){var p=this._nativePrototypes[tag];if(!p){p=Object.create(this.getNativePrototype(tag));var p$=Object.getOwnPropertyNames(Polymer.Base);for(var i=0,n;i<p$.length&&(n=p$[i]);i++){if(!Polymer.BaseDescriptors[n]){p[n]=Polymer.Base[n];}}
+Object.defineProperties(p,Polymer.BaseDescriptors);this._nativePrototypes[tag]=p;}
+return p;},getNativePrototype:function(tag){return Object.getPrototypeOf(document.createElement(tag));}});Polymer.Base._addFeature({_prepConstructor:function(){this._factoryArgs=this.extends?[this.extends,this.is]:[this.is];var ctor=function(){return this._factory(arguments);};if(this.hasOwnProperty('extends')){ctor.extends=this.extends;}
+Object.defineProperty(this,'constructor',{value:ctor,writable:true,configurable:true});ctor.prototype=this;},_factory:function(args){var elt=document.createElement.apply(document,this._factoryArgs);if(this.factoryImpl){this.factoryImpl.apply(elt,args);}
+return elt;}});Polymer.nob=Object.create(null);Polymer.Base._addFeature({getPropertyInfo:function(property){var info=this._getPropertyInfo(property,this.properties);if(!info){for(var i=0;i<this.behaviors.length;i++){info=this._getPropertyInfo(property,this.behaviors[i].properties);if(info){return info;}}}
+return info||Polymer.nob;},_getPropertyInfo:function(property,properties){var p=properties&&properties[property];if(typeof p==='function'){p=properties[property]={type:p};}
+if(p){p.defined=true;}
+return p;},_prepPropertyInfo:function(){this._propertyInfo={};for(var i=0;i<this.behaviors.length;i++){this._addPropertyInfo(this._propertyInfo,this.behaviors[i].properties);}
+this._addPropertyInfo(this._propertyInfo,this.properties);this._addPropertyInfo(this._propertyInfo,this._propertyEffects);},_addPropertyInfo:function(target,source){if(source){var t,s;for(var i in source){t=target[i];s=source[i];if(i[0]==='_'&&!s.readOnly){continue;}
+if(!target[i]){target[i]={type:typeof s==='function'?s:s.type,readOnly:s.readOnly,attribute:Polymer.CaseMap.camelToDashCase(i)};}else{if(!t.type){t.type=s.type;}
+if(!t.readOnly){t.readOnly=s.readOnly;}}}}}});(function(){var propertiesDesc={configurable:true,writable:true,enumerable:true,value:{}};Polymer.BaseDescriptors.properties=propertiesDesc;Object.defineProperty(Polymer.Base,'properties',propertiesDesc);}());Polymer.CaseMap={_caseMap:{},_rx:{dashToCamel:/-[a-z]/g,camelToDash:/([A-Z])/g},dashToCamelCase:function(dash){return this._caseMap[dash]||(this._caseMap[dash]=dash.indexOf('-')<0?dash:dash.replace(this._rx.dashToCamel,function(m){return m[1].toUpperCase();}));},camelToDashCase:function(camel){return this._caseMap[camel]||(this._caseMap[camel]=camel.replace(this._rx.camelToDash,'-$1').toLowerCase());}};Polymer.Base._addFeature({_addHostAttributes:function(attributes){if(!this._aggregatedAttributes){this._aggregatedAttributes={};}
+if(attributes){this.mixin(this._aggregatedAttributes,attributes);}},_marshalHostAttributes:function(){if(this._aggregatedAttributes){this._applyAttributes(this,this._aggregatedAttributes);}},_applyAttributes:function(node,attr$){for(var n in attr$){if(!this.hasAttribute(n)&&n!=='class'){var v=attr$[n];this.serializeValueToAttribute(v,n,this);}}},_marshalAttributes:function(){this._takeAttributesToModel(this);},_takeAttributesToModel:function(model){if(this.hasAttributes()){for(var i in this._propertyInfo){var info=this._propertyInfo[i];if(this.hasAttribute(info.attribute)){this._setAttributeToProperty(model,info.attribute,i,info);}}}},_setAttributeToProperty:function(model,attribute,property,info){if(!this._serializing){property=property||Polymer.CaseMap.dashToCamelCase(attribute);info=info||this._propertyInfo&&this._propertyInfo[property];if(info&&!info.readOnly){var v=this.getAttribute(attribute);model[property]=this.deserialize(v,info.type);}}},_serializing:false,reflectPropertyToAttribute:function(property,attribute,value){this._serializing=true;value=value===undefined?this[property]:value;this.serializeValueToAttribute(value,attribute||Polymer.CaseMap.camelToDashCase(property));this._serializing=false;},serializeValueToAttribute:function(value,attribute,node){var str=this.serialize(value);node=node||this;if(str===undefined){node.removeAttribute(attribute);}else{node.setAttribute(attribute,str);}},deserialize:function(value,type){switch(type){case Number:value=Number(value);break;case Boolean:value=value!=null;break;case Object:try{value=JSON.parse(value);}catch(x){}
+break;case Array:try{value=JSON.parse(value);}catch(x){value=null;console.warn('Polymer::Attributes: couldn`t decode Array as JSON');}
+break;case Date:value=new Date(value);break;case String:default:break;}
+return value;},serialize:function(value){switch(typeof value){case'boolean':return value?'':undefined;case'object':if(value instanceof Date){return value.toString();}else if(value){try{return JSON.stringify(value);}catch(x){return'';}}
+default:return value!=null?value:undefined;}}});Polymer.version="1.11.3";Polymer.Base._addFeature({_registerFeatures:function(){this._prepIs();this._prepBehaviors();this._prepConstructor();this._prepPropertyInfo();},_prepBehavior:function(b){this._addHostAttributes(b.hostAttributes);},_marshalBehavior:function(b){},_initFeatures:function(){this._marshalHostAttributes();this._marshalBehaviors();}});(function(){function resolveCss(cssText,ownerDocument){return cssText.replace(CSS_URL_RX,function(m,pre,url,post){return pre+'\''+resolve(url.replace(/["']/g,''),ownerDocument)+'\''+post;});}
+function resolveAttrs(element,ownerDocument){for(var name in URL_ATTRS){var a$=URL_ATTRS[name];for(var i=0,l=a$.length,a,at,v;i<l&&(a=a$[i]);i++){if(name==='*'||element.localName===name){at=element.attributes[a];v=at&&at.value;if(v&&v.search(BINDING_RX)<0){at.value=a==='style'?resolveCss(v,ownerDocument):resolve(v,ownerDocument);}}}}}
+function resolve(url,ownerDocument){if(url&&ABS_URL.test(url)){return url;}
+var resolver=getUrlResolver(ownerDocument);resolver.href=url;return resolver.href||url;}
+var tempDoc;var tempDocBase;function resolveUrl(url,baseUri){if(!tempDoc){tempDoc=document.implementation.createHTMLDocument('temp');tempDocBase=tempDoc.createElement('base');tempDoc.head.appendChild(tempDocBase);}
+tempDocBase.href=baseUri;return resolve(url,tempDoc);}
+function getUrlResolver(ownerDocument){return ownerDocument.body.__urlResolver||(ownerDocument.body.__urlResolver=ownerDocument.createElement('a'));}
+function pathFromUrl(url){return url.substring(0,url.lastIndexOf('/')+1);}
+var CSS_URL_RX=/(url\()([^)]*)(\))/g;var URL_ATTRS={'*':['href','src','style','url'],form:['action']};var ABS_URL=/(^\/)|(^#)|(^[\w-\d]*:)/;var BINDING_RX=/\{\{|\[\[/;Polymer.ResolveUrl={resolveCss:resolveCss,resolveAttrs:resolveAttrs,resolveUrl:resolveUrl,pathFromUrl:pathFromUrl};Polymer.rootPath=Polymer.Settings.rootPath||pathFromUrl(document.baseURI||window.location.href);}());Polymer.Base._addFeature({_prepTemplate:function(){var module;if(this._template===undefined){module=Polymer.DomModule.import(this.is);this._template=module&&module.querySelector('template');}
+if(module){var assetPath=module.getAttribute('assetpath')||'';var importURL=Polymer.ResolveUrl.resolveUrl(assetPath,module.ownerDocument.baseURI);this._importPath=Polymer.ResolveUrl.pathFromUrl(importURL);}else{this._importPath='';}
+if(this._template&&this._template.hasAttribute('is')){this._warn(this._logf('_prepTemplate','top-level Polymer template '+'must not be a type-extension, found',this._template,'Move inside simple <template>.'));}
+if(this._template&&!this._template.content&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate){HTMLTemplateElement.decorate(this._template);}},_stampTemplate:function(){if(this._template){this.root=this.instanceTemplate(this._template);}},instanceTemplate:function(template){var dom=document.importNode(template._content||template.content,true);return dom;}});(function(){var baseAttachedCallback=Polymer.Base.attachedCallback;var baseDetachedCallback=Polymer.Base.detachedCallback;Polymer.Base._addFeature({_hostStack:[],ready:function(){},_registerHost:function(host){this.dataHost=host=host||Polymer.Base._hostStack[Polymer.Base._hostStack.length-1];if(host&&host._clients){host._clients.push(this);}
+this._clients=null;this._clientsReadied=false;},_beginHosting:function(){Polymer.Base._hostStack.push(this);if(!this._clients){this._clients=[];}},_endHosting:function(){Polymer.Base._hostStack.pop();},_tryReady:function(){this._readied=false;if(this._canReady()){this._ready();}},_canReady:function(){return!this.dataHost||this.dataHost._clientsReadied;},_ready:function(){this._beforeClientsReady();if(this._template){this._setupRoot();this._readyClients();}
+this._clientsReadied=true;this._clients=null;this._afterClientsReady();this._readySelf();},_readyClients:function(){this._beginDistribute();var c$=this._clients;if(c$){for(var i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){c._ready();}}
+this._finishDistribute();},_readySelf:function(){for(var i=0,b;i<this.behaviors.length;i++){b=this.behaviors[i];if(b.ready){b.ready.call(this);}}
+if(this.ready){this.ready();}
+this._readied=true;if(this._attachedPending){this._attachedPending=false;this.attachedCallback();}},_beforeClientsReady:function(){},_afterClientsReady:function(){},_beforeAttached:function(){},attachedCallback:function(){if(this._readied){this._beforeAttached();baseAttachedCallback.call(this);}else{this._attachedPending=true;}},detachedCallback:function(){if(this._readied){baseDetachedCallback.call(this);}else{this._attachedPending=false;}}});}());Polymer.ArraySplice=function(){function newSplice(index,removed,addedCount){return{index:index,removed:removed,addedCount:addedCount};}
+var EDIT_LEAVE=0;var EDIT_UPDATE=1;var EDIT_ADD=2;var EDIT_DELETE=3;function ArraySplice(){}
+ArraySplice.prototype={calcEditDistances:function(current,currentStart,currentEnd,old,oldStart,oldEnd){var rowCount=oldEnd-oldStart+1;var columnCount=currentEnd-currentStart+1;var distances=new Array(rowCount);for(var i=0;i<rowCount;i++){distances[i]=new Array(columnCount);distances[i][0]=i;}
+for(var j=0;j<columnCount;j++)
+distances[0][j]=j;for(i=1;i<rowCount;i++){for(j=1;j<columnCount;j++){if(this.equals(current[currentStart+j-1],old[oldStart+i-1]))
+distances[i][j]=distances[i-1][j-1];else{var north=distances[i-1][j]+1;var west=distances[i][j-1]+1;distances[i][j]=north<west?north:west;}}}
+return distances;},spliceOperationsFromEditDistances:function(distances){var i=distances.length-1;var j=distances[0].length-1;var current=distances[i][j];var edits=[];while(i>0||j>0){if(i==0){edits.push(EDIT_ADD);j--;continue;}
+if(j==0){edits.push(EDIT_DELETE);i--;continue;}
+var northWest=distances[i-1][j-1];var west=distances[i-1][j];var north=distances[i][j-1];var min;if(west<north)
+min=west<northWest?west:northWest;else
+min=north<northWest?north:northWest;if(min==northWest){if(northWest==current){edits.push(EDIT_LEAVE);}else{edits.push(EDIT_UPDATE);current=northWest;}
+i--;j--;}else if(min==west){edits.push(EDIT_DELETE);i--;current=west;}else{edits.push(EDIT_ADD);j--;current=north;}}
+edits.reverse();return edits;},calcSplices:function(current,currentStart,currentEnd,old,oldStart,oldEnd){var prefixCount=0;var suffixCount=0;var minLength=Math.min(currentEnd-currentStart,oldEnd-oldStart);if(currentStart==0&&oldStart==0)
+prefixCount=this.sharedPrefix(current,old,minLength);if(currentEnd==current.length&&oldEnd==old.length)
+suffixCount=this.sharedSuffix(current,old,minLength-prefixCount);currentStart+=prefixCount;oldStart+=prefixCount;currentEnd-=suffixCount;oldEnd-=suffixCount;if(currentEnd-currentStart==0&&oldEnd-oldStart==0)
+return[];if(currentStart==currentEnd){var splice=newSplice(currentStart,[],0);while(oldStart<oldEnd)
+splice.removed.push(old[oldStart++]);return[splice];}else if(oldStart==oldEnd)
+return[newSplice(currentStart,[],currentEnd-currentStart)];var ops=this.spliceOperationsFromEditDistances(this.calcEditDistances(current,currentStart,currentEnd,old,oldStart,oldEnd));splice=undefined;var splices=[];var index=currentStart;var oldIndex=oldStart;for(var i=0;i<ops.length;i++){switch(ops[i]){case EDIT_LEAVE:if(splice){splices.push(splice);splice=undefined;}
+index++;oldIndex++;break;case EDIT_UPDATE:if(!splice)
+splice=newSplice(index,[],0);splice.addedCount++;index++;splice.removed.push(old[oldIndex]);oldIndex++;break;case EDIT_ADD:if(!splice)
+splice=newSplice(index,[],0);splice.addedCount++;index++;break;case EDIT_DELETE:if(!splice)
+splice=newSplice(index,[],0);splice.removed.push(old[oldIndex]);oldIndex++;break;}}
+if(splice){splices.push(splice);}
+return splices;},sharedPrefix:function(current,old,searchLength){for(var i=0;i<searchLength;i++)
+if(!this.equals(current[i],old[i]))
+return i;return searchLength;},sharedSuffix:function(current,old,searchLength){var index1=current.length;var index2=old.length;var count=0;while(count<searchLength&&this.equals(current[--index1],old[--index2]))
+count++;return count;},calculateSplices:function(current,previous){return this.calcSplices(current,0,current.length,previous,0,previous.length);},equals:function(currentValue,previousValue){return currentValue===previousValue;}};return new ArraySplice();}();Polymer.domInnerHTML=function(){var escapeAttrRegExp=/[&\u00A0"]/g;var escapeDataRegExp=/[&\u00A0<>]/g;function escapeReplace(c){switch(c){case'&':return'&amp;';case'<':return'&lt;';case'>':return'&gt;';case'"':return'&quot;';case'\xA0':return'&nbsp;';}}
+function escapeAttr(s){return s.replace(escapeAttrRegExp,escapeReplace);}
+function escapeData(s){return s.replace(escapeDataRegExp,escapeReplace);}
+function makeSet(arr){var set={};for(var i=0;i<arr.length;i++){set[arr[i]]=true;}
+return set;}
+var voidElements=makeSet(['area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr']);var plaintextParents=makeSet(['style','script','xmp','iframe','noembed','noframes','plaintext','noscript']);function getOuterHTML(node,parentNode,composed){switch(node.nodeType){case Node.ELEMENT_NODE:var tagName=node.localName;var s='<'+tagName;var attrs=node.attributes;for(var i=0,attr;attr=attrs[i];i++){s+=' '+attr.name+'="'+escapeAttr(attr.value)+'"';}
+s+='>';if(voidElements[tagName]){return s;}
+return s+getInnerHTML(node,composed)+'</'+tagName+'>';case Node.TEXT_NODE:var data=node.data;if(parentNode&&plaintextParents[parentNode.localName]){return data;}
+return escapeData(data);case Node.COMMENT_NODE:return'<!--'+node.data+'-->';default:console.error(node);throw new Error('not implemented');}}
+function getInnerHTML(node,composed){if(node instanceof HTMLTemplateElement)
+node=node.content;var s='';var c$=Polymer.dom(node).childNodes;for(var i=0,l=c$.length,child;i<l&&(child=c$[i]);i++){s+=getOuterHTML(child,node,composed);}
+return s;}
+return{getInnerHTML:getInnerHTML};}();(function(){'use strict';var nativeInsertBefore=Element.prototype.insertBefore;var nativeAppendChild=Element.prototype.appendChild;var nativeRemoveChild=Element.prototype.removeChild;Polymer.TreeApi={arrayCopyChildNodes:function(parent){var copy=[],i=0;for(var n=parent.firstChild;n;n=n.nextSibling){copy[i++]=n;}
+return copy;},arrayCopyChildren:function(parent){var copy=[],i=0;for(var n=parent.firstElementChild;n;n=n.nextElementSibling){copy[i++]=n;}
+return copy;},arrayCopy:function(a$){var l=a$.length;var copy=new Array(l);for(var i=0;i<l;i++){copy[i]=a$[i];}
+return copy;}};Polymer.TreeApi.Logical={hasParentNode:function(node){return Boolean(node.__dom&&node.__dom.parentNode);},hasChildNodes:function(node){return Boolean(node.__dom&&node.__dom.childNodes!==undefined);},getChildNodes:function(node){return this.hasChildNodes(node)?this._getChildNodes(node):node.childNodes;},_getChildNodes:function(node){if(!node.__dom.childNodes){node.__dom.childNodes=[];for(var n=node.__dom.firstChild;n;n=n.__dom.nextSibling){node.__dom.childNodes.push(n);}}
+return node.__dom.childNodes;},getParentNode:function(node){return node.__dom&&node.__dom.parentNode!==undefined?node.__dom.parentNode:node.parentNode;},getFirstChild:function(node){return node.__dom&&node.__dom.firstChild!==undefined?node.__dom.firstChild:node.firstChild;},getLastChild:function(node){return node.__dom&&node.__dom.lastChild!==undefined?node.__dom.lastChild:node.lastChild;},getNextSibling:function(node){return node.__dom&&node.__dom.nextSibling!==undefined?node.__dom.nextSibling:node.nextSibling;},getPreviousSibling:function(node){return node.__dom&&node.__dom.previousSibling!==undefined?node.__dom.previousSibling:node.previousSibling;},getFirstElementChild:function(node){return node.__dom&&node.__dom.firstChild!==undefined?this._getFirstElementChild(node):node.firstElementChild;},_getFirstElementChild:function(node){var n=node.__dom.firstChild;while(n&&n.nodeType!==Node.ELEMENT_NODE){n=n.__dom.nextSibling;}
+return n;},getLastElementChild:function(node){return node.__dom&&node.__dom.lastChild!==undefined?this._getLastElementChild(node):node.lastElementChild;},_getLastElementChild:function(node){var n=node.__dom.lastChild;while(n&&n.nodeType!==Node.ELEMENT_NODE){n=n.__dom.previousSibling;}
+return n;},getNextElementSibling:function(node){return node.__dom&&node.__dom.nextSibling!==undefined?this._getNextElementSibling(node):node.nextElementSibling;},_getNextElementSibling:function(node){var n=node.__dom.nextSibling;while(n&&n.nodeType!==Node.ELEMENT_NODE){n=n.__dom.nextSibling;}
+return n;},getPreviousElementSibling:function(node){return node.__dom&&node.__dom.previousSibling!==undefined?this._getPreviousElementSibling(node):node.previousElementSibling;},_getPreviousElementSibling:function(node){var n=node.__dom.previousSibling;while(n&&n.nodeType!==Node.ELEMENT_NODE){n=n.__dom.previousSibling;}
+return n;},saveChildNodes:function(node){if(!this.hasChildNodes(node)){node.__dom=node.__dom||{};node.__dom.firstChild=node.firstChild;node.__dom.lastChild=node.lastChild;node.__dom.childNodes=[];for(var n=node.firstChild;n;n=n.nextSibling){n.__dom=n.__dom||{};n.__dom.parentNode=node;node.__dom.childNodes.push(n);n.__dom.nextSibling=n.nextSibling;n.__dom.previousSibling=n.previousSibling;}}},recordInsertBefore:function(node,container,ref_node){container.__dom.childNodes=null;if(node.nodeType===Node.DOCUMENT_FRAGMENT_NODE){for(var n=node.firstChild;n;n=n.nextSibling){this._linkNode(n,container,ref_node);}}else{this._linkNode(node,container,ref_node);}},_linkNode:function(node,container,ref_node){node.__dom=node.__dom||{};container.__dom=container.__dom||{};if(ref_node){ref_node.__dom=ref_node.__dom||{};}
+node.__dom.previousSibling=ref_node?ref_node.__dom.previousSibling:container.__dom.lastChild;if(node.__dom.previousSibling){node.__dom.previousSibling.__dom.nextSibling=node;}
+node.__dom.nextSibling=ref_node||null;if(node.__dom.nextSibling){node.__dom.nextSibling.__dom.previousSibling=node;}
+node.__dom.parentNode=container;if(ref_node){if(ref_node===container.__dom.firstChild){container.__dom.firstChild=node;}}else{container.__dom.lastChild=node;if(!container.__dom.firstChild){container.__dom.firstChild=node;}}
+container.__dom.childNodes=null;},recordRemoveChild:function(node,container){node.__dom=node.__dom||{};container.__dom=container.__dom||{};if(node===container.__dom.firstChild){container.__dom.firstChild=node.__dom.nextSibling;}
+if(node===container.__dom.lastChild){container.__dom.lastChild=node.__dom.previousSibling;}
+var p=node.__dom.previousSibling;var n=node.__dom.nextSibling;if(p){p.__dom.nextSibling=n;}
+if(n){n.__dom.previousSibling=p;}
+node.__dom.parentNode=node.__dom.previousSibling=node.__dom.nextSibling=undefined;container.__dom.childNodes=null;}};Polymer.TreeApi.Composed={getChildNodes:function(node){return Polymer.TreeApi.arrayCopyChildNodes(node);},getParentNode:function(node){return node.parentNode;},clearChildNodes:function(node){node.textContent='';},insertBefore:function(parentNode,newChild,refChild){return nativeInsertBefore.call(parentNode,newChild,refChild||null);},appendChild:function(parentNode,newChild){return nativeAppendChild.call(parentNode,newChild);},removeChild:function(parentNode,node){return nativeRemoveChild.call(parentNode,node);}};}());Polymer.DomApi=function(){'use strict';var Settings=Polymer.Settings;var TreeApi=Polymer.TreeApi;var DomApi=function(node){this.node=needsToWrap?DomApi.wrap(node):node;};var needsToWrap=Settings.hasShadow&&!Settings.nativeShadow;DomApi.wrap=window.wrap?window.wrap:function(node){return node;};DomApi.prototype={flush:function(){Polymer.dom.flush();},deepContains:function(node){if(this.node.contains(node)){return true;}
+var n=node;var doc=node.ownerDocument;while(n&&n!==doc&&n!==this.node){n=Polymer.dom(n).parentNode||n.host;}
+return n===this.node;},queryDistributedElements:function(selector){var c$=this.getEffectiveChildNodes();var list=[];for(var i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){if(c.nodeType===Node.ELEMENT_NODE&&DomApi.matchesSelector.call(c,selector)){list.push(c);}}
+return list;},getEffectiveChildNodes:function(){var list=[];var c$=this.childNodes;for(var i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){if(c.localName===CONTENT){var d$=dom(c).getDistributedNodes();for(var j=0;j<d$.length;j++){list.push(d$[j]);}}else{list.push(c);}}
+return list;},observeNodes:function(callback){if(callback){if(!this.observer){this.observer=this.node.localName===CONTENT?new DomApi.DistributedNodesObserver(this):new DomApi.EffectiveNodesObserver(this);}
+return this.observer.addListener(callback);}},unobserveNodes:function(handle){if(this.observer){this.observer.removeListener(handle);}},notifyObserver:function(){if(this.observer){this.observer.notify();}},_query:function(matcher,node,halter){node=node||this.node;var list=[];this._queryElements(TreeApi.Logical.getChildNodes(node),matcher,halter,list);return list;},_queryElements:function(elements,matcher,halter,list){for(var i=0,l=elements.length,c;i<l&&(c=elements[i]);i++){if(c.nodeType===Node.ELEMENT_NODE){if(this._queryElement(c,matcher,halter,list)){return true;}}}},_queryElement:function(node,matcher,halter,list){var result=matcher(node);if(result){list.push(node);}
+if(halter&&halter(result)){return result;}
+this._queryElements(TreeApi.Logical.getChildNodes(node),matcher,halter,list);}};var CONTENT=DomApi.CONTENT='content';var dom=DomApi.factory=function(node){node=node||document;if(!node.__domApi){node.__domApi=new DomApi.ctor(node);}
+return node.__domApi;};DomApi.hasApi=function(node){return Boolean(node.__domApi);};DomApi.ctor=DomApi;Polymer.dom=function(obj,patch){if(obj instanceof Event){return Polymer.EventApi.factory(obj);}else{return DomApi.factory(obj,patch);}};var p=Element.prototype;DomApi.matchesSelector=p.matches||p.matchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;return DomApi;}();(function(){'use strict';var Settings=Polymer.Settings;var DomApi=Polymer.DomApi;var dom=DomApi.factory;var TreeApi=Polymer.TreeApi;var getInnerHTML=Polymer.domInnerHTML.getInnerHTML;var CONTENT=DomApi.CONTENT;if(Settings.useShadow){return;}
+var nativeCloneNode=Element.prototype.cloneNode;var nativeImportNode=Document.prototype.importNode;Polymer.Base.mixin(DomApi.prototype,{_lazyDistribute:function(host){if(host.shadyRoot&&host.shadyRoot._distributionClean){host.shadyRoot._distributionClean=false;Polymer.dom.addDebouncer(host.debounce('_distribute',host._distributeContent));}},appendChild:function(node){return this.insertBefore(node);},insertBefore:function(node,ref_node){if(ref_node&&TreeApi.Logical.getParentNode(ref_node)!==this.node){throw Error('The ref_node to be inserted before is not a child '+'of this node');}
+if(node.nodeType!==Node.DOCUMENT_FRAGMENT_NODE){var parent=TreeApi.Logical.getParentNode(node);if(parent){if(DomApi.hasApi(parent)){dom(parent).notifyObserver();}
+this._removeNode(node);}else{this._removeOwnerShadyRoot(node);}}
+if(!this._addNode(node,ref_node)){if(ref_node){ref_node=ref_node.localName===CONTENT?this._firstComposedNode(ref_node):ref_node;}
+var container=this.node._isShadyRoot?this.node.host:this.node;if(ref_node){TreeApi.Composed.insertBefore(container,node,ref_node);}else{TreeApi.Composed.appendChild(container,node);}}
+this.notifyObserver();return node;},_addNode:function(node,ref_node){var root=this.getOwnerRoot();if(root){var ipAdded=this._maybeAddInsertionPoint(node,this.node);if(!root._invalidInsertionPoints){root._invalidInsertionPoints=ipAdded;}
+this._addNodeToHost(root.host,node);}
+if(TreeApi.Logical.hasChildNodes(this.node)){TreeApi.Logical.recordInsertBefore(node,this.node,ref_node);}
+var handled=this._maybeDistribute(node)||this.node.shadyRoot;if(handled){if(node.nodeType===Node.DOCUMENT_FRAGMENT_NODE){while(node.firstChild){TreeApi.Composed.removeChild(node,node.firstChild);}}else{var parent=TreeApi.Composed.getParentNode(node);if(parent){TreeApi.Composed.removeChild(parent,node);}}}
+return handled;},removeChild:function(node){if(TreeApi.Logical.getParentNode(node)!==this.node){throw Error('The node to be removed is not a child of this node: '+node);}
+if(!this._removeNode(node)){var container=this.node._isShadyRoot?this.node.host:this.node;var parent=TreeApi.Composed.getParentNode(node);if(container===parent){TreeApi.Composed.removeChild(container,node);}}
+this.notifyObserver();return node;},_removeNode:function(node){var logicalParent=TreeApi.Logical.hasParentNode(node)&&TreeApi.Logical.getParentNode(node);var distributed;var root=this._ownerShadyRootForNode(node);if(logicalParent){distributed=dom(node)._maybeDistributeParent();TreeApi.Logical.recordRemoveChild(node,logicalParent);if(root&&this._removeDistributedChildren(root,node)){root._invalidInsertionPoints=true;this._lazyDistribute(root.host);}}
+this._removeOwnerShadyRoot(node);if(root){this._removeNodeFromHost(root.host,node);}
+return distributed;},replaceChild:function(node,ref_node){this.insertBefore(node,ref_node);this.removeChild(ref_node);return node;},_hasCachedOwnerRoot:function(node){return Boolean(node._ownerShadyRoot!==undefined);},getOwnerRoot:function(){return this._ownerShadyRootForNode(this.node);},_ownerShadyRootForNode:function(node){if(!node){return;}
+var root=node._ownerShadyRoot;if(root===undefined){if(node._isShadyRoot){root=node;}else{var parent=TreeApi.Logical.getParentNode(node);if(parent){root=parent._isShadyRoot?parent:this._ownerShadyRootForNode(parent);}else{root=null;}}
+if(root||document.documentElement.contains(node)){node._ownerShadyRoot=root;}}
+return root;},_maybeDistribute:function(node){var fragContent=node.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&!node.__noContent&&dom(node).querySelector(CONTENT);var wrappedContent=fragContent&&TreeApi.Logical.getParentNode(fragContent).nodeType!==Node.DOCUMENT_FRAGMENT_NODE;var hasContent=fragContent||node.localName===CONTENT;if(hasContent){var root=this.getOwnerRoot();if(root){this._lazyDistribute(root.host);}}
+var needsDist=this._nodeNeedsDistribution(this.node);if(needsDist){this._lazyDistribute(this.node);}
+return needsDist||hasContent&&!wrappedContent;},_maybeAddInsertionPoint:function(node,parent){var added;if(node.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&!node.__noContent){var c$=dom(node).querySelectorAll(CONTENT);for(var i=0,n,np,na;i<c$.length&&(n=c$[i]);i++){np=TreeApi.Logical.getParentNode(n);if(np===node){np=parent;}
+na=this._maybeAddInsertionPoint(n,np);added=added||na;}}else if(node.localName===CONTENT){TreeApi.Logical.saveChildNodes(parent);TreeApi.Logical.saveChildNodes(node);added=true;}
+return added;},_updateInsertionPoints:function(host){var i$=host.shadyRoot._insertionPoints=dom(host.shadyRoot).querySelectorAll(CONTENT);for(var i=0,c;i<i$.length;i++){c=i$[i];TreeApi.Logical.saveChildNodes(c);TreeApi.Logical.saveChildNodes(TreeApi.Logical.getParentNode(c));}},_nodeNeedsDistribution:function(node){return node&&node.shadyRoot&&DomApi.hasInsertionPoint(node.shadyRoot);},_addNodeToHost:function(host,node){if(host._elementAdd){host._elementAdd(node);}},_removeNodeFromHost:function(host,node){if(host._elementRemove){host._elementRemove(node);}},_removeDistributedChildren:function(root,container){var hostNeedsDist;var ip$=root._insertionPoints;for(var i=0;i<ip$.length;i++){var content=ip$[i];if(this._contains(container,content)){var dc$=dom(content).getDistributedNodes();for(var j=0;j<dc$.length;j++){hostNeedsDist=true;var node=dc$[j];var parent=TreeApi.Composed.getParentNode(node);if(parent){TreeApi.Composed.removeChild(parent,node);}}}}
+return hostNeedsDist;},_contains:function(container,node){while(node){if(node==container){return true;}
+node=TreeApi.Logical.getParentNode(node);}},_removeOwnerShadyRoot:function(node){if(this._hasCachedOwnerRoot(node)){var c$=TreeApi.Logical.getChildNodes(node);for(var i=0,l=c$.length,n;i<l&&(n=c$[i]);i++){this._removeOwnerShadyRoot(n);}}
+node._ownerShadyRoot=undefined;},_firstComposedNode:function(content){var n$=dom(content).getDistributedNodes();for(var i=0,l=n$.length,n,p$;i<l&&(n=n$[i]);i++){p$=dom(n).getDestinationInsertionPoints();if(p$[p$.length-1]===content){return n;}}},querySelector:function(selector){var result=this._query(function(n){return DomApi.matchesSelector.call(n,selector);},this.node,function(n){return Boolean(n);})[0];return result||null;},querySelectorAll:function(selector){return this._query(function(n){return DomApi.matchesSelector.call(n,selector);},this.node);},getDestinationInsertionPoints:function(){return this.node._destinationInsertionPoints||[];},getDistributedNodes:function(){return this.node._distributedNodes||[];},_clear:function(){while(this.childNodes.length){this.removeChild(this.childNodes[0]);}},setAttribute:function(name,value){this.node.setAttribute(name,value);this._maybeDistributeParent();},removeAttribute:function(name){this.node.removeAttribute(name);this._maybeDistributeParent();},_maybeDistributeParent:function(){if(this._nodeNeedsDistribution(this.parentNode)){this._lazyDistribute(this.parentNode);return true;}},cloneNode:function(deep){var n=nativeCloneNode.call(this.node,false);if(deep){var c$=this.childNodes;var d=dom(n);for(var i=0,nc;i<c$.length;i++){nc=dom(c$[i]).cloneNode(true);d.appendChild(nc);}}
+return n;},importNode:function(externalNode,deep){var doc=this.node instanceof Document?this.node:this.node.ownerDocument;var n=nativeImportNode.call(doc,externalNode,false);if(deep){var c$=TreeApi.Logical.getChildNodes(externalNode);var d=dom(n);for(var i=0,nc;i<c$.length;i++){nc=dom(doc).importNode(c$[i],true);d.appendChild(nc);}}
+return n;},_getComposedInnerHTML:function(){return getInnerHTML(this.node,true);}});Object.defineProperties(DomApi.prototype,{activeElement:{get:function(){var active=document.activeElement;if(!active){return null;}
+var isShadyRoot=!!this.node._isShadyRoot;if(this.node!==document){if(!isShadyRoot){return null;}
+if(this.node.host===active||!this.node.host.contains(active)){return null;}}
+var activeRoot=dom(active).getOwnerRoot();while(activeRoot&&activeRoot!==this.node){active=activeRoot.host;activeRoot=dom(active).getOwnerRoot();}
+if(this.node===document){return activeRoot?null:active;}else{return activeRoot===this.node?active:null;}},configurable:true},childNodes:{get:function(){var c$=TreeApi.Logical.getChildNodes(this.node);return Array.isArray(c$)?c$:TreeApi.arrayCopyChildNodes(this.node);},configurable:true},children:{get:function(){if(TreeApi.Logical.hasChildNodes(this.node)){return Array.prototype.filter.call(this.childNodes,function(n){return n.nodeType===Node.ELEMENT_NODE;});}else{return TreeApi.arrayCopyChildren(this.node);}},configurable:true},parentNode:{get:function(){return TreeApi.Logical.getParentNode(this.node);},configurable:true},firstChild:{get:function(){return TreeApi.Logical.getFirstChild(this.node);},configurable:true},lastChild:{get:function(){return TreeApi.Logical.getLastChild(this.node);},configurable:true},nextSibling:{get:function(){return TreeApi.Logical.getNextSibling(this.node);},configurable:true},previousSibling:{get:function(){return TreeApi.Logical.getPreviousSibling(this.node);},configurable:true},firstElementChild:{get:function(){return TreeApi.Logical.getFirstElementChild(this.node);},configurable:true},lastElementChild:{get:function(){return TreeApi.Logical.getLastElementChild(this.node);},configurable:true},nextElementSibling:{get:function(){return TreeApi.Logical.getNextElementSibling(this.node);},configurable:true},previousElementSibling:{get:function(){return TreeApi.Logical.getPreviousElementSibling(this.node);},configurable:true},textContent:{get:function(){var nt=this.node.nodeType;if(nt===Node.TEXT_NODE||nt===Node.COMMENT_NODE){return this.node.textContent;}else{var tc=[];for(var i=0,cn=this.childNodes,c;c=cn[i];i++){if(c.nodeType!==Node.COMMENT_NODE){tc.push(c.textContent);}}
+return tc.join('');}},set:function(text){var nt=this.node.nodeType;if(nt===Node.TEXT_NODE||nt===Node.COMMENT_NODE){this.node.textContent=text;}else{this._clear();if(text){this.appendChild(document.createTextNode(text));}}},configurable:true},innerHTML:{get:function(){var nt=this.node.nodeType;if(nt===Node.TEXT_NODE||nt===Node.COMMENT_NODE){return null;}else{return getInnerHTML(this.node);}},set:function(text){var nt=this.node.nodeType;if(nt!==Node.TEXT_NODE||nt!==Node.COMMENT_NODE){this._clear();var d=document.createElement('div');d.innerHTML=text;var c$=TreeApi.arrayCopyChildNodes(d);for(var i=0;i<c$.length;i++){this.appendChild(c$[i]);}}},configurable:true}});DomApi.hasInsertionPoint=function(root){return Boolean(root&&root._insertionPoints.length);};}());(function(){'use strict';var Settings=Polymer.Settings;var TreeApi=Polymer.TreeApi;var DomApi=Polymer.DomApi;if(!Settings.useShadow){return;}
+Polymer.Base.mixin(DomApi.prototype,{querySelectorAll:function(selector){return TreeApi.arrayCopy(this.node.querySelectorAll(selector));},getOwnerRoot:function(){var n=this.node;while(n){if(n.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&n.host){return n;}
+n=n.parentNode;}},importNode:function(externalNode,deep){var doc=this.node instanceof Document?this.node:this.node.ownerDocument;return doc.importNode(externalNode,deep);},getDestinationInsertionPoints:function(){var n$=this.node.getDestinationInsertionPoints&&this.node.getDestinationInsertionPoints();return n$?TreeApi.arrayCopy(n$):[];},getDistributedNodes:function(){var n$=this.node.getDistributedNodes&&this.node.getDistributedNodes();return n$?TreeApi.arrayCopy(n$):[];}});Object.defineProperties(DomApi.prototype,{activeElement:{get:function(){var node=DomApi.wrap(this.node);var activeElement=node.activeElement;return node.contains(activeElement)?activeElement:null;},configurable:true},childNodes:{get:function(){return TreeApi.arrayCopyChildNodes(this.node);},configurable:true},children:{get:function(){return TreeApi.arrayCopyChildren(this.node);},configurable:true},textContent:{get:function(){return this.node.textContent;},set:function(value){return this.node.textContent=value;},configurable:true},innerHTML:{get:function(){return this.node.innerHTML;},set:function(value){return this.node.innerHTML=value;},configurable:true}});var forwardMethods=function(m$){for(var i=0;i<m$.length;i++){forwardMethod(m$[i]);}};var forwardMethod=function(method){DomApi.prototype[method]=function(){return this.node[method].apply(this.node,arguments);};};forwardMethods(['cloneNode','appendChild','insertBefore','removeChild','replaceChild','setAttribute','removeAttribute','querySelector']);var forwardProperties=function(f$){for(var i=0;i<f$.length;i++){forwardProperty(f$[i]);}};var forwardProperty=function(name){Object.defineProperty(DomApi.prototype,name,{get:function(){return this.node[name];},configurable:true});};forwardProperties(['parentNode','firstChild','lastChild','nextSibling','previousSibling','firstElementChild','lastElementChild','nextElementSibling','previousElementSibling']);}());Polymer.Base.mixin(Polymer.dom,{_flushGuard:0,_FLUSH_MAX:100,_needsTakeRecords:!Polymer.Settings.useNativeCustomElements,_debouncers:[],_staticFlushList:[],_finishDebouncer:null,flush:function(){this._flushGuard=0;this._prepareFlush();while(this._debouncers.length&&this._flushGuard<this._FLUSH_MAX){while(this._debouncers.length){this._debouncers.shift().complete();}
+if(this._finishDebouncer){this._finishDebouncer.complete();}
+this._prepareFlush();this._flushGuard++;}
+if(this._flushGuard>=this._FLUSH_MAX){console.warn('Polymer.dom.flush aborted. Flush may not be complete.');}},_prepareFlush:function(){if(this._needsTakeRecords){CustomElements.takeRecords();}
+for(var i=0;i<this._staticFlushList.length;i++){this._staticFlushList[i]();}},addStaticFlush:function(fn){this._staticFlushList.push(fn);},removeStaticFlush:function(fn){var i=this._staticFlushList.indexOf(fn);if(i>=0){this._staticFlushList.splice(i,1);}},addDebouncer:function(debouncer){this._debouncers.push(debouncer);this._finishDebouncer=Polymer.Debounce(this._finishDebouncer,this._finishFlush);},_finishFlush:function(){Polymer.dom._debouncers=[];}});Polymer.EventApi=function(){'use strict';var DomApi=Polymer.DomApi.ctor;var Settings=Polymer.Settings;DomApi.Event=function(event){this.event=event;};if(Settings.useShadow){DomApi.Event.prototype={get rootTarget(){return this.event.path[0];},get localTarget(){return this.event.target;},get path(){var path=this.event.path;if(!Array.isArray(path)){path=Array.prototype.slice.call(path);}
+return path;}};}else{DomApi.Event.prototype={get rootTarget(){return this.event.target;},get localTarget(){var current=this.event.currentTarget;var currentRoot=current&&Polymer.dom(current).getOwnerRoot();var p$=this.path;for(var i=0;i<p$.length;i++){if(Polymer.dom(p$[i]).getOwnerRoot()===currentRoot){return p$[i];}}},get path(){if(!this.event._path){var path=[];var current=this.rootTarget;while(current){path.push(current);var insertionPoints=Polymer.dom(current).getDestinationInsertionPoints();if(insertionPoints.length){for(var i=0;i<insertionPoints.length-1;i++){path.push(insertionPoints[i]);}
+current=insertionPoints[insertionPoints.length-1];}else{current=Polymer.dom(current).parentNode||current.host;}}
+path.push(window);this.event._path=path;}
+return this.event._path;}};}
+var factory=function(event){if(!event.__eventApi){event.__eventApi=new DomApi.Event(event);}
+return event.__eventApi;};return{factory:factory};}();(function(){'use strict';var DomApi=Polymer.DomApi.ctor;var useShadow=Polymer.Settings.useShadow;Object.defineProperty(DomApi.prototype,'classList',{get:function(){if(!this._classList){this._classList=new DomApi.ClassList(this);}
+return this._classList;},configurable:true});DomApi.ClassList=function(host){this.domApi=host;this.node=host.node;};DomApi.ClassList.prototype={add:function(){this.node.classList.add.apply(this.node.classList,arguments);this._distributeParent();},remove:function(){this.node.classList.remove.apply(this.node.classList,arguments);this._distributeParent();},toggle:function(){this.node.classList.toggle.apply(this.node.classList,arguments);this._distributeParent();},_distributeParent:function(){if(!useShadow){this.domApi._maybeDistributeParent();}},contains:function(){return this.node.classList.contains.apply(this.node.classList,arguments);}};}());(function(){'use strict';var DomApi=Polymer.DomApi.ctor;var Settings=Polymer.Settings;DomApi.EffectiveNodesObserver=function(domApi){this.domApi=domApi;this.node=this.domApi.node;this._listeners=[];};DomApi.EffectiveNodesObserver.prototype={addListener:function(callback){if(!this._isSetup){this._setup();this._isSetup=true;}
+var listener={fn:callback,_nodes:[]};this._listeners.push(listener);this._scheduleNotify();return listener;},removeListener:function(handle){var i=this._listeners.indexOf(handle);if(i>=0){this._listeners.splice(i,1);handle._nodes=[];}
+if(!this._hasListeners()){this._cleanup();this._isSetup=false;}},_setup:function(){this._observeContentElements(this.domApi.childNodes);},_cleanup:function(){this._unobserveContentElements(this.domApi.childNodes);},_hasListeners:function(){return Boolean(this._listeners.length);},_scheduleNotify:function(){if(this._debouncer){this._debouncer.stop();}
+this._debouncer=Polymer.Debounce(this._debouncer,this._notify);this._debouncer.context=this;Polymer.dom.addDebouncer(this._debouncer);},notify:function(){if(this._hasListeners()){this._scheduleNotify();}},_notify:function(){this._beforeCallListeners();this._callListeners();},_beforeCallListeners:function(){this._updateContentElements();},_updateContentElements:function(){this._observeContentElements(this.domApi.childNodes);},_observeContentElements:function(elements){for(var i=0,n;i<elements.length&&(n=elements[i]);i++){if(this._isContent(n)){n.__observeNodesMap=n.__observeNodesMap||new WeakMap();if(!n.__observeNodesMap.has(this)){n.__observeNodesMap.set(this,this._observeContent(n));}}}},_observeContent:function(content){var self=this;var h=Polymer.dom(content).observeNodes(function(){self._scheduleNotify();});h._avoidChangeCalculation=true;return h;},_unobserveContentElements:function(elements){for(var i=0,n,h;i<elements.length&&(n=elements[i]);i++){if(this._isContent(n)){h=n.__observeNodesMap.get(this);if(h){Polymer.dom(n).unobserveNodes(h);n.__observeNodesMap.delete(this);}}}},_isContent:function(node){return node.localName==='content';},_callListeners:function(){var o$=this._listeners;var nodes=this._getEffectiveNodes();for(var i=0,o;i<o$.length&&(o=o$[i]);i++){var info=this._generateListenerInfo(o,nodes);if(info||o._alwaysNotify){this._callListener(o,info);}}},_getEffectiveNodes:function(){return this.domApi.getEffectiveChildNodes();},_generateListenerInfo:function(listener,newNodes){if(listener._avoidChangeCalculation){return true;}
+var oldNodes=listener._nodes;var info={target:this.node,addedNodes:[],removedNodes:[]};var splices=Polymer.ArraySplice.calculateSplices(newNodes,oldNodes);for(var i=0,s;i<splices.length&&(s=splices[i]);i++){for(var j=0,n;j<s.removed.length&&(n=s.removed[j]);j++){info.removedNodes.push(n);}}
+for(i=0,s;i<splices.length&&(s=splices[i]);i++){for(j=s.index;j<s.index+s.addedCount;j++){info.addedNodes.push(newNodes[j]);}}
+listener._nodes=newNodes;if(info.addedNodes.length||info.removedNodes.length){return info;}},_callListener:function(listener,info){return listener.fn.call(this.node,info);},enableShadowAttributeTracking:function(){}};if(Settings.useShadow){var baseSetup=DomApi.EffectiveNodesObserver.prototype._setup;var baseCleanup=DomApi.EffectiveNodesObserver.prototype._cleanup;Polymer.Base.mixin(DomApi.EffectiveNodesObserver.prototype,{_setup:function(){if(!this._observer){var self=this;this._mutationHandler=function(mxns){if(mxns&&mxns.length){self._scheduleNotify();}};this._observer=new MutationObserver(this._mutationHandler);this._boundFlush=function(){self._flush();};Polymer.dom.addStaticFlush(this._boundFlush);this._observer.observe(this.node,{childList:true});}
+baseSetup.call(this);},_cleanup:function(){this._observer.disconnect();this._observer=null;this._mutationHandler=null;Polymer.dom.removeStaticFlush(this._boundFlush);baseCleanup.call(this);},_flush:function(){if(this._observer){this._mutationHandler(this._observer.takeRecords());}},enableShadowAttributeTracking:function(){if(this._observer){this._makeContentListenersAlwaysNotify();this._observer.disconnect();this._observer.observe(this.node,{childList:true,attributes:true,subtree:true});var root=this.domApi.getOwnerRoot();var host=root&&root.host;if(host&&Polymer.dom(host).observer){Polymer.dom(host).observer.enableShadowAttributeTracking();}}},_makeContentListenersAlwaysNotify:function(){for(var i=0,h;i<this._listeners.length;i++){h=this._listeners[i];h._alwaysNotify=h._isContentListener;}}});}}());(function(){'use strict';var DomApi=Polymer.DomApi.ctor;var Settings=Polymer.Settings;DomApi.DistributedNodesObserver=function(domApi){DomApi.EffectiveNodesObserver.call(this,domApi);};DomApi.DistributedNodesObserver.prototype=Object.create(DomApi.EffectiveNodesObserver.prototype);Polymer.Base.mixin(DomApi.DistributedNodesObserver.prototype,{_setup:function(){},_cleanup:function(){},_beforeCallListeners:function(){},_getEffectiveNodes:function(){return this.domApi.getDistributedNodes();}});if(Settings.useShadow){Polymer.Base.mixin(DomApi.DistributedNodesObserver.prototype,{_setup:function(){if(!this._observer){var root=this.domApi.getOwnerRoot();var host=root&&root.host;if(host){var self=this;this._observer=Polymer.dom(host).observeNodes(function(){self._scheduleNotify();});this._observer._isContentListener=true;if(this._hasAttrSelect()){Polymer.dom(host).observer.enableShadowAttributeTracking();}}}},_hasAttrSelect:function(){var select=this.node.getAttribute('select');return select&&select.match(/[[.]+/);},_cleanup:function(){var root=this.domApi.getOwnerRoot();var host=root&&root.host;if(host){Polymer.dom(host).unobserveNodes(this._observer);}
+this._observer=null;}});}}());(function(){var DomApi=Polymer.DomApi;var TreeApi=Polymer.TreeApi;Polymer.Base._addFeature({_prepShady:function(){this._useContent=this._useContent||Boolean(this._template);},_setupShady:function(){this.shadyRoot=null;if(!this.__domApi){this.__domApi=null;}
+if(!this.__dom){this.__dom=null;}
+if(!this._ownerShadyRoot){this._ownerShadyRoot=undefined;}},_poolContent:function(){if(this._useContent){TreeApi.Logical.saveChildNodes(this);}},_setupRoot:function(){if(this._useContent){this._createLocalRoot();if(!this.dataHost){upgradeLogicalChildren(TreeApi.Logical.getChildNodes(this));}}},_createLocalRoot:function(){this.shadyRoot=this.root;this.shadyRoot._distributionClean=false;this.shadyRoot._hasDistributed=false;this.shadyRoot._isShadyRoot=true;this.shadyRoot._dirtyRoots=[];var i$=this.shadyRoot._insertionPoints=!this._notes||this._notes._hasContent?this.shadyRoot.querySelectorAll('content'):[];TreeApi.Logical.saveChildNodes(this.shadyRoot);for(var i=0,c;i<i$.length;i++){c=i$[i];TreeApi.Logical.saveChildNodes(c);TreeApi.Logical.saveChildNodes(c.parentNode);}
+this.shadyRoot.host=this;},distributeContent:function(updateInsertionPoints){if(this.shadyRoot){this.shadyRoot._invalidInsertionPoints=this.shadyRoot._invalidInsertionPoints||updateInsertionPoints;var host=getTopDistributingHost(this);Polymer.dom(this)._lazyDistribute(host);}},_distributeContent:function(){if(this._useContent&&!this.shadyRoot._distributionClean){if(this.shadyRoot._invalidInsertionPoints){Polymer.dom(this)._updateInsertionPoints(this);this.shadyRoot._invalidInsertionPoints=false;}
+this._beginDistribute();this._distributeDirtyRoots();this._finishDistribute();}},_beginDistribute:function(){if(this._useContent&&DomApi.hasInsertionPoint(this.shadyRoot)){this._resetDistribution();this._distributePool(this.shadyRoot,this._collectPool());}},_distributeDirtyRoots:function(){var c$=this.shadyRoot._dirtyRoots;for(var i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){c._distributeContent();}
+this.shadyRoot._dirtyRoots=[];},_finishDistribute:function(){if(this._useContent){this.shadyRoot._distributionClean=true;if(DomApi.hasInsertionPoint(this.shadyRoot)){this._composeTree();notifyContentObservers(this.shadyRoot);}else{if(!this.shadyRoot._hasDistributed){TreeApi.Composed.clearChildNodes(this);this.appendChild(this.shadyRoot);}else{var children=this._composeNode(this);this._updateChildNodes(this,children);}}
+if(!this.shadyRoot._hasDistributed){notifyInitialDistribution(this);}
+this.shadyRoot._hasDistributed=true;}},elementMatches:function(selector,node){node=node||this;return DomApi.matchesSelector.call(node,selector);},_resetDistribution:function(){var children=TreeApi.Logical.getChildNodes(this);for(var i=0;i<children.length;i++){var child=children[i];if(child._destinationInsertionPoints){child._destinationInsertionPoints=undefined;}
+if(isInsertionPoint(child)){clearDistributedDestinationInsertionPoints(child);}}
+var root=this.shadyRoot;var p$=root._insertionPoints;for(var j=0;j<p$.length;j++){p$[j]._distributedNodes=[];}},_collectPool:function(){var pool=[];var children=TreeApi.Logical.getChildNodes(this);for(var i=0;i<children.length;i++){var child=children[i];if(isInsertionPoint(child)){pool.push.apply(pool,child._distributedNodes);}else{pool.push(child);}}
+return pool;},_distributePool:function(node,pool){var p$=node._insertionPoints;for(var i=0,l=p$.length,p;i<l&&(p=p$[i]);i++){this._distributeInsertionPoint(p,pool);maybeRedistributeParent(p,this);}},_distributeInsertionPoint:function(content,pool){var anyDistributed=false;for(var i=0,l=pool.length,node;i<l;i++){node=pool[i];if(!node){continue;}
+if(this._matchesContentSelect(node,content)){distributeNodeInto(node,content);pool[i]=undefined;anyDistributed=true;}}
+if(!anyDistributed){var children=TreeApi.Logical.getChildNodes(content);for(var j=0;j<children.length;j++){distributeNodeInto(children[j],content);}}},_composeTree:function(){this._updateChildNodes(this,this._composeNode(this));var p$=this.shadyRoot._insertionPoints;for(var i=0,l=p$.length,p,parent;i<l&&(p=p$[i]);i++){parent=TreeApi.Logical.getParentNode(p);if(!parent._useContent&&parent!==this&&parent!==this.shadyRoot){this._updateChildNodes(parent,this._composeNode(parent));}}},_composeNode:function(node){var children=[];var c$=TreeApi.Logical.getChildNodes(node.shadyRoot||node);for(var i=0;i<c$.length;i++){var child=c$[i];if(isInsertionPoint(child)){var distributedNodes=child._distributedNodes;for(var j=0;j<distributedNodes.length;j++){var distributedNode=distributedNodes[j];if(isFinalDestination(child,distributedNode)){children.push(distributedNode);}}}else{children.push(child);}}
+return children;},_updateChildNodes:function(container,children){var composed=TreeApi.Composed.getChildNodes(container);var splices=Polymer.ArraySplice.calculateSplices(children,composed);for(var i=0,d=0,s;i<splices.length&&(s=splices[i]);i++){for(var j=0,n;j<s.removed.length&&(n=s.removed[j]);j++){if(TreeApi.Composed.getParentNode(n)===container){TreeApi.Composed.removeChild(container,n);}
+composed.splice(s.index+d,1);}
+d-=s.addedCount;}
+for(var i=0,s,next;i<splices.length&&(s=splices[i]);i++){next=composed[s.index];for(j=s.index,n;j<s.index+s.addedCount;j++){n=children[j];TreeApi.Composed.insertBefore(container,n,next);composed.splice(j,0,n);}}},_matchesContentSelect:function(node,contentElement){var select=contentElement.getAttribute('select');if(!select){return true;}
+select=select.trim();if(!select){return true;}
+if(!(node instanceof Element)){return false;}
+var validSelectors=/^(:not\()?[*.#[a-zA-Z_|]/;if(!validSelectors.test(select)){return false;}
+return this.elementMatches(select,node);},_elementAdd:function(){},_elementRemove:function(){}});var domHostDesc={get:function(){var root=Polymer.dom(this).getOwnerRoot();return root&&root.host;},configurable:true};Object.defineProperty(Polymer.Base,'domHost',domHostDesc);Polymer.BaseDescriptors.domHost=domHostDesc;function distributeNodeInto(child,insertionPoint){insertionPoint._distributedNodes.push(child);var points=child._destinationInsertionPoints;if(!points){child._destinationInsertionPoints=[insertionPoint];}else{points.push(insertionPoint);}}
+function clearDistributedDestinationInsertionPoints(content){var e$=content._distributedNodes;if(e$){for(var i=0;i<e$.length;i++){var d=e$[i]._destinationInsertionPoints;if(d){d.splice(d.indexOf(content)+1,d.length);}}}}
+function maybeRedistributeParent(content,host){var parent=TreeApi.Logical.getParentNode(content);if(parent&&parent.shadyRoot&&DomApi.hasInsertionPoint(parent.shadyRoot)&&parent.shadyRoot._distributionClean){parent.shadyRoot._distributionClean=false;host.shadyRoot._dirtyRoots.push(parent);}}
+function isFinalDestination(insertionPoint,node){var points=node._destinationInsertionPoints;return points&&points[points.length-1]===insertionPoint;}
+function isInsertionPoint(node){return node.localName=='content';}
+function getTopDistributingHost(host){while(host&&hostNeedsRedistribution(host)){host=host.domHost;}
+return host;}
+function hostNeedsRedistribution(host){var c$=TreeApi.Logical.getChildNodes(host);for(var i=0,c;i<c$.length;i++){c=c$[i];if(c.localName&&c.localName==='content'){return host.domHost;}}}
+function notifyContentObservers(root){for(var i=0,c;i<root._insertionPoints.length;i++){c=root._insertionPoints[i];if(DomApi.hasApi(c)){Polymer.dom(c).notifyObserver();}}}
+function notifyInitialDistribution(host){if(DomApi.hasApi(host)){Polymer.dom(host).notifyObserver();}}
+var needsUpgrade=window.CustomElements&&!CustomElements.useNative;function upgradeLogicalChildren(children){if(needsUpgrade&&children){for(var i=0;i<children.length;i++){CustomElements.upgrade(children[i]);}}}}());if(Polymer.Settings.useShadow){Polymer.Base._addFeature({_poolContent:function(){},_beginDistribute:function(){},distributeContent:function(){},_distributeContent:function(){},_finishDistribute:function(){},_createLocalRoot:function(){this.createShadowRoot();this.shadowRoot.appendChild(this.root);this.root=this.shadowRoot;}});}Polymer.Async={_currVal:0,_lastVal:0,_callbacks:[],_twiddleContent:0,_twiddle:document.createTextNode(''),run:function(callback,waitTime){if(waitTime>0){return~setTimeout(callback,waitTime);}else{this._twiddle.textContent=this._twiddleContent++;this._callbacks.push(callback);return this._currVal++;}},cancel:function(handle){if(handle<0){clearTimeout(~handle);}else{var idx=handle-this._lastVal;if(idx>=0){if(!this._callbacks[idx]){throw'invalid async handle: '+handle;}
+this._callbacks[idx]=null;}}},_atEndOfMicrotask:function(){var len=this._callbacks.length;for(var i=0;i<len;i++){var cb=this._callbacks[i];if(cb){try{cb();}catch(e){i++;this._callbacks.splice(0,i);this._lastVal+=i;this._twiddle.textContent=this._twiddleContent++;throw e;}}}
+this._callbacks.splice(0,len);this._lastVal+=len;}};new window.MutationObserver(function(){Polymer.Async._atEndOfMicrotask();}).observe(Polymer.Async._twiddle,{characterData:true});Polymer.Debounce=function(){var Async=Polymer.Async;var Debouncer=function(context){this.context=context;var self=this;this.boundComplete=function(){self.complete();};};Debouncer.prototype={go:function(callback,wait){var h;this.finish=function(){Async.cancel(h);};h=Async.run(this.boundComplete,wait);this.callback=callback;},stop:function(){if(this.finish){this.finish();this.finish=null;this.callback=null;}},complete:function(){if(this.finish){var callback=this.callback;this.stop();callback.call(this.context);}}};function debounce(debouncer,callback,wait){if(debouncer){debouncer.stop();}else{debouncer=new Debouncer(this);}
+debouncer.go(callback,wait);return debouncer;}
+return debounce;}();Polymer.Base._addFeature({_setupDebouncers:function(){this._debouncers={};},debounce:function(jobName,callback,wait){return this._debouncers[jobName]=Polymer.Debounce.call(this,this._debouncers[jobName],callback,wait);},isDebouncerActive:function(jobName){var debouncer=this._debouncers[jobName];return!!(debouncer&&debouncer.finish);},flushDebouncer:function(jobName){var debouncer=this._debouncers[jobName];if(debouncer){debouncer.complete();}},cancelDebouncer:function(jobName){var debouncer=this._debouncers[jobName];if(debouncer){debouncer.stop();}}});Polymer.DomModule=document.createElement('dom-module');Polymer.Base._addFeature({_registerFeatures:function(){this._prepIs();this._prepBehaviors();this._prepConstructor();this._prepTemplate();this._prepShady();this._prepPropertyInfo();},_prepBehavior:function(b){this._addHostAttributes(b.hostAttributes);},_initFeatures:function(){this._registerHost();if(this._template){this._poolContent();this._beginHosting();this._stampTemplate();this._endHosting();}
+this._marshalHostAttributes();this._setupDebouncers();this._marshalBehaviors();this._tryReady();},_marshalBehavior:function(b){}});(function(){Polymer.nar=[];var disableUpgradeEnabled=Polymer.Settings.disableUpgradeEnabled;Polymer.Annotations={parseAnnotations:function(template,stripWhiteSpace){var list=[];var content=template._content||template.content;this._parseNodeAnnotations(content,list,stripWhiteSpace||template.hasAttribute('strip-whitespace'));return list;},_parseNodeAnnotations:function(node,list,stripWhiteSpace){return node.nodeType===Node.TEXT_NODE?this._parseTextNodeAnnotation(node,list):this._parseElementAnnotations(node,list,stripWhiteSpace);},_bindingRegex:function(){var IDENT='(?:'+'[a-zA-Z_$][\\w.:$\\-*]*'+')';var NUMBER='(?:'+'[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?'+')';var SQUOTE_STRING='(?:'+'\'(?:[^\'\\\\]|\\\\.)*\''+')';var DQUOTE_STRING='(?:'+'"(?:[^"\\\\]|\\\\.)*"'+')';var STRING='(?:'+SQUOTE_STRING+'|'+DQUOTE_STRING+')';var ARGUMENT='(?:'+IDENT+'|'+NUMBER+'|'+STRING+'\\s*'+')';var ARGUMENTS='(?:'+ARGUMENT+'(?:,\\s*'+ARGUMENT+')*'+')';var ARGUMENT_LIST='(?:'+'\\(\\s*'+'(?:'+ARGUMENTS+'?'+')'+'\\)\\s*'+')';var BINDING='('+IDENT+'\\s*'+ARGUMENT_LIST+'?'+')';var OPEN_BRACKET='(\\[\\[|{{)'+'\\s*';var CLOSE_BRACKET='(?:]]|}})';var NEGATE='(?:(!)\\s*)?';var EXPRESSION=OPEN_BRACKET+NEGATE+BINDING+CLOSE_BRACKET;return new RegExp(EXPRESSION,'g');}(),_parseBindings:function(text){var re=this._bindingRegex;var parts=[];var lastIndex=0;var m;while((m=re.exec(text))!==null){if(m.index>lastIndex){parts.push({literal:text.slice(lastIndex,m.index)});}
+var mode=m[1][0];var negate=Boolean(m[2]);var value=m[3].trim();var customEvent,notifyEvent,colon;if(mode=='{'&&(colon=value.indexOf('::'))>0){notifyEvent=value.substring(colon+2);value=value.substring(0,colon);customEvent=true;}
+parts.push({compoundIndex:parts.length,value:value,mode:mode,negate:negate,event:notifyEvent,customEvent:customEvent});lastIndex=re.lastIndex;}
+if(lastIndex&&lastIndex<text.length){var literal=text.substring(lastIndex);if(literal){parts.push({literal:literal});}}
+if(parts.length){return parts;}},_literalFromParts:function(parts){var s='';for(var i=0;i<parts.length;i++){var literal=parts[i].literal;s+=literal||'';}
+return s;},_parseTextNodeAnnotation:function(node,list){var parts=this._parseBindings(node.textContent);if(parts){node.textContent=this._literalFromParts(parts)||' ';var annote={bindings:[{kind:'text',name:'textContent',parts:parts,isCompound:parts.length!==1}]};list.push(annote);return annote;}},_parseElementAnnotations:function(element,list,stripWhiteSpace){var annote={bindings:[],events:[]};if(element.localName==='content'){list._hasContent=true;}
+this._parseChildNodesAnnotations(element,annote,list,stripWhiteSpace);if(element.attributes){this._parseNodeAttributeAnnotations(element,annote,list);if(this.prepElement){this.prepElement(element);}}
+if(annote.bindings.length||annote.events.length||annote.id){list.push(annote);}
+return annote;},_parseChildNodesAnnotations:function(root,annote,list,stripWhiteSpace){if(root.firstChild){var node=root.firstChild;var i=0;while(node){var next=node.nextSibling;if(node.localName==='template'&&!node.hasAttribute('preserve-content')){this._parseTemplate(node,i,list,annote,stripWhiteSpace);}
+if(node.localName=='slot'){node=this._replaceSlotWithContent(node);}
+if(node.nodeType===Node.TEXT_NODE){var n=next;while(n&&n.nodeType===Node.TEXT_NODE){node.textContent+=n.textContent;next=n.nextSibling;root.removeChild(n);n=next;}
+if(stripWhiteSpace&&!node.textContent.trim()){root.removeChild(node);i--;}}
+if(node.parentNode){var childAnnotation=this._parseNodeAnnotations(node,list,stripWhiteSpace);if(childAnnotation){childAnnotation.parent=annote;childAnnotation.index=i;}}
+node=next;i++;}}},_replaceSlotWithContent:function(slot){var content=slot.ownerDocument.createElement('content');while(slot.firstChild){content.appendChild(slot.firstChild);}
+var attrs=slot.attributes;for(var i=0;i<attrs.length;i++){var attr=attrs[i];content.setAttribute(attr.name,attr.value);}
+var name=slot.getAttribute('name');if(name){content.setAttribute('select','[slot=\''+name+'\']');}
+slot.parentNode.replaceChild(content,slot);return content;},_parseTemplate:function(node,index,list,parent,stripWhiteSpace){var content=document.createDocumentFragment();content._notes=this.parseAnnotations(node,stripWhiteSpace);content.appendChild(node.content);list.push({bindings:Polymer.nar,events:Polymer.nar,templateContent:content,parent:parent,index:index});},_parseNodeAttributeAnnotations:function(node,annotation){var attrs=Array.prototype.slice.call(node.attributes);for(var i=attrs.length-1,a;a=attrs[i];i--){var n=a.name;var v=a.value;var b;if(n.slice(0,3)==='on-'){node.removeAttribute(n);annotation.events.push({name:n.slice(3),value:v});}else if(b=this._parseNodeAttributeAnnotation(node,n,v)){annotation.bindings.push(b);}else if(n==='id'){annotation.id=v;}}},_parseNodeAttributeAnnotation:function(node,name,value){var parts=this._parseBindings(value);if(parts){var origName=name;var kind='property';if(name[name.length-1]=='$'){name=name.slice(0,-1);kind='attribute';}
+var literal=this._literalFromParts(parts);if(literal&&kind=='attribute'){node.setAttribute(name,literal);}
+if(node.localName==='input'&&origName==='value'){node.setAttribute(origName,'');}
+if(disableUpgradeEnabled&&origName==='disable-upgrade$'){node.setAttribute(name,'');}
+node.removeAttribute(origName);var propertyName=Polymer.CaseMap.dashToCamelCase(name);if(kind==='property'){name=propertyName;}
+return{kind:kind,name:name,propertyName:propertyName,parts:parts,literal:literal,isCompound:parts.length!==1};}},findAnnotatedNode:function(root,annote){var parent=annote.parent&&Polymer.Annotations.findAnnotatedNode(root,annote.parent);if(parent){for(var n=parent.firstChild,i=0;n;n=n.nextSibling){if(annote.index===i++){return n;}}}else{return root;}}};}());Polymer.Path={root:function(path){var dotIndex=path.indexOf('.');if(dotIndex===-1){return path;}
+return path.slice(0,dotIndex);},isDeep:function(path){return path.indexOf('.')!==-1;},isAncestor:function(base,path){return base.indexOf(path+'.')===0;},isDescendant:function(base,path){return path.indexOf(base+'.')===0;},translate:function(base,newBase,path){return newBase+path.slice(base.length);},matches:function(base,wildcard,path){return base===path||this.isAncestor(base,path)||Boolean(wildcard)&&this.isDescendant(base,path);}};Polymer.Base._addFeature({_prepAnnotations:function(){if(!this._template){this._notes=[];}else{var self=this;Polymer.Annotations.prepElement=function(element){self._prepElement(element);};if(this._template._content&&this._template._content._notes){this._notes=this._template._content._notes;}else{this._notes=Polymer.Annotations.parseAnnotations(this._template);this._processAnnotations(this._notes);}
+Polymer.Annotations.prepElement=null;}},_processAnnotations:function(notes){for(var i=0;i<notes.length;i++){var note=notes[i];for(var j=0;j<note.bindings.length;j++){var b=note.bindings[j];for(var k=0;k<b.parts.length;k++){var p=b.parts[k];if(!p.literal){var signature=this._parseMethod(p.value);if(signature){p.signature=signature;}else{p.model=Polymer.Path.root(p.value);}}}}
+if(note.templateContent){this._processAnnotations(note.templateContent._notes);var pp=note.templateContent._parentProps=this._discoverTemplateParentProps(note.templateContent._notes);var bindings=[];for(var prop in pp){var name='_parent_'+prop;bindings.push({index:note.index,kind:'property',name:name,propertyName:name,parts:[{mode:'{',model:prop,value:prop}]});}
+note.bindings=note.bindings.concat(bindings);}}},_discoverTemplateParentProps:function(notes){var pp={};for(var i=0,n;i<notes.length&&(n=notes[i]);i++){for(var j=0,b$=n.bindings,b;j<b$.length&&(b=b$[j]);j++){for(var k=0,p$=b.parts,p;k<p$.length&&(p=p$[k]);k++){if(p.signature){var args=p.signature.args;for(var kk=0;kk<args.length;kk++){var model=args[kk].model;if(model){pp[model]=true;}}
+if(p.signature.dynamicFn){pp[p.signature.method]=true;}}else{if(p.model){pp[p.model]=true;}}}}
+if(n.templateContent){var tpp=n.templateContent._parentProps;Polymer.Base.mixin(pp,tpp);}}
+return pp;},_prepElement:function(element){Polymer.ResolveUrl.resolveAttrs(element,this._template.ownerDocument);},_findAnnotatedNode:Polymer.Annotations.findAnnotatedNode,_marshalAnnotationReferences:function(){if(this._template){this._marshalIdNodes();this._marshalAnnotatedNodes();this._marshalAnnotatedListeners();}},_configureAnnotationReferences:function(){var notes=this._notes;var nodes=this._nodes;for(var i=0;i<notes.length;i++){var note=notes[i];var node=nodes[i];this._configureTemplateContent(note,node);this._configureCompoundBindings(note,node);}},_configureTemplateContent:function(note,node){if(note.templateContent){node._content=note.templateContent;}},_configureCompoundBindings:function(note,node){var bindings=note.bindings;for(var i=0;i<bindings.length;i++){var binding=bindings[i];if(binding.isCompound){var storage=node.__compoundStorage__||(node.__compoundStorage__={});var parts=binding.parts;var literals=new Array(parts.length);for(var j=0;j<parts.length;j++){literals[j]=parts[j].literal;}
+var name=binding.name;storage[name]=literals;if(binding.literal&&binding.kind=='property'){if(node._configValue){node._configValue(name,binding.literal);}else{node[name]=binding.literal;}}}}},_marshalIdNodes:function(){this.$={};for(var i=0,l=this._notes.length,a;i<l&&(a=this._notes[i]);i++){if(a.id){this.$[a.id]=this._findAnnotatedNode(this.root,a);}}},_marshalAnnotatedNodes:function(){if(this._notes&&this._notes.length){var r=new Array(this._notes.length);for(var i=0;i<this._notes.length;i++){r[i]=this._findAnnotatedNode(this.root,this._notes[i]);}
+this._nodes=r;}},_marshalAnnotatedListeners:function(){for(var i=0,l=this._notes.length,a;i<l&&(a=this._notes[i]);i++){if(a.events&&a.events.length){var node=this._findAnnotatedNode(this.root,a);for(var j=0,e$=a.events,e;j<e$.length&&(e=e$[j]);j++){this.listen(node,e.name,e.value);}}}}});Polymer.Base._addFeature({listeners:{},_listenListeners:function(listeners){var node,name,eventName;for(eventName in listeners){if(eventName.indexOf('.')<0){node=this;name=eventName;}else{name=eventName.split('.');node=this.$[name[0]];name=name[1];}
+this.listen(node,name,listeners[eventName]);}},listen:function(node,eventName,methodName){var handler=this._recallEventHandler(this,eventName,node,methodName);if(!handler){handler=this._createEventHandler(node,eventName,methodName);}
+if(handler._listening){return;}
+this._listen(node,eventName,handler);handler._listening=true;},_boundListenerKey:function(eventName,methodName){return eventName+':'+methodName;},_recordEventHandler:function(host,eventName,target,methodName,handler){var hbl=host.__boundListeners;if(!hbl){hbl=host.__boundListeners=new WeakMap();}
+var bl=hbl.get(target);if(!bl){bl={};if(!Polymer.Settings.isIE||target!=window){hbl.set(target,bl);}}
+var key=this._boundListenerKey(eventName,methodName);bl[key]=handler;},_recallEventHandler:function(host,eventName,target,methodName){var hbl=host.__boundListeners;if(!hbl){return;}
+var bl=hbl.get(target);if(!bl){return;}
+var key=this._boundListenerKey(eventName,methodName);return bl[key];},_createEventHandler:function(node,eventName,methodName){var host=this;var handler=function(e){if(host[methodName]){host[methodName](e,e.detail);}else{host._warn(host._logf('_createEventHandler','listener method `'+methodName+'` not defined'));}};handler._listening=false;this._recordEventHandler(host,eventName,node,methodName,handler);return handler;},unlisten:function(node,eventName,methodName){var handler=this._recallEventHandler(this,eventName,node,methodName);if(handler){this._unlisten(node,eventName,handler);handler._listening=false;}},_listen:function(node,eventName,handler){node.addEventListener(eventName,handler);},_unlisten:function(node,eventName,handler){node.removeEventListener(eventName,handler);}});(function(){'use strict';var wrap=Polymer.DomApi.wrap;var HAS_NATIVE_TA=typeof document.head.style.touchAction==='string';var GESTURE_KEY='__polymerGestures';var HANDLED_OBJ='__polymerGesturesHandled';var TOUCH_ACTION='__polymerGesturesTouchAction';var TAP_DISTANCE=25;var TRACK_DISTANCE=5;var TRACK_LENGTH=2;var MOUSE_TIMEOUT=2500;var MOUSE_EVENTS=['mousedown','mousemove','mouseup','click'];var MOUSE_WHICH_TO_BUTTONS=[0,1,4,2];var MOUSE_HAS_BUTTONS=function(){try{return new MouseEvent('test',{buttons:1}).buttons===1;}catch(e){return false;}}();function isMouseEvent(name){return MOUSE_EVENTS.indexOf(name)>-1;}
+var SUPPORTS_PASSIVE=false;(function(){try{var opts=Object.defineProperty({},'passive',{get:function(){SUPPORTS_PASSIVE=true;}});window.addEventListener('test',null,opts);window.removeEventListener('test',null,opts);}catch(e){}}());function PASSIVE_TOUCH(eventName){if(isMouseEvent(eventName)||eventName==='touchend'){return;}
+if(HAS_NATIVE_TA&&SUPPORTS_PASSIVE&&Polymer.Settings.passiveTouchGestures){return{passive:true};}}
+var IS_TOUCH_ONLY=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);var mouseCanceller=function(mouseEvent){var sc=mouseEvent.sourceCapabilities;if(sc&&!sc.firesTouchEvents){return;}
+mouseEvent[HANDLED_OBJ]={skip:true};if(mouseEvent.type==='click'){var path=Polymer.dom(mouseEvent).path;if(path){for(var i=0;i<path.length;i++){if(path[i]===POINTERSTATE.mouse.target){return;}}}
+mouseEvent.preventDefault();mouseEvent.stopPropagation();}};function setupTeardownMouseCanceller(setup){var events=IS_TOUCH_ONLY?['click']:MOUSE_EVENTS;for(var i=0,en;i<events.length;i++){en=events[i];if(setup){document.addEventListener(en,mouseCanceller,true);}else{document.removeEventListener(en,mouseCanceller,true);}}}
+function ignoreMouse(ev){if(!POINTERSTATE.mouse.mouseIgnoreJob){setupTeardownMouseCanceller(true);}
+var unset=function(){setupTeardownMouseCanceller();POINTERSTATE.mouse.target=null;POINTERSTATE.mouse.mouseIgnoreJob=null;};POINTERSTATE.mouse.target=Polymer.dom(ev).rootTarget;POINTERSTATE.mouse.mouseIgnoreJob=Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob,unset,MOUSE_TIMEOUT);}
+function hasLeftMouseButton(ev){var type=ev.type;if(!isMouseEvent(type)){return false;}
+if(type==='mousemove'){var buttons=ev.buttons===undefined?1:ev.buttons;if(ev instanceof window.MouseEvent&&!MOUSE_HAS_BUTTONS){buttons=MOUSE_WHICH_TO_BUTTONS[ev.which]||0;}
+return Boolean(buttons&1);}else{var button=ev.button===undefined?0:ev.button;return button===0;}}
+function isSyntheticClick(ev){if(ev.type==='click'){if(ev.detail===0){return true;}
+var t=Gestures.findOriginalTarget(ev);var bcr=t.getBoundingClientRect();var x=ev.pageX,y=ev.pageY;return!(x>=bcr.left&&x<=bcr.right&&(y>=bcr.top&&y<=bcr.bottom));}
+return false;}
+var POINTERSTATE={mouse:{target:null,mouseIgnoreJob:null},touch:{x:0,y:0,id:-1,scrollDecided:false}};function firstTouchAction(ev){var path=Polymer.dom(ev).path;var ta='auto';for(var i=0,n;i<path.length;i++){n=path[i];if(n[TOUCH_ACTION]){ta=n[TOUCH_ACTION];break;}}
+return ta;}
+function trackDocument(stateObj,movefn,upfn){stateObj.movefn=movefn;stateObj.upfn=upfn;document.addEventListener('mousemove',movefn);document.addEventListener('mouseup',upfn);}
+function untrackDocument(stateObj){document.removeEventListener('mousemove',stateObj.movefn);document.removeEventListener('mouseup',stateObj.upfn);stateObj.movefn=null;stateObj.upfn=null;}
+document.addEventListener('touchend',ignoreMouse,SUPPORTS_PASSIVE?{passive:true}:false);var Gestures={gestures:{},recognizers:[],deepTargetFind:function(x,y){var node=document.elementFromPoint(x,y);var next=node;while(next&&next.shadowRoot){next=next.shadowRoot.elementFromPoint(x,y);if(next){node=next;}}
+return node;},findOriginalTarget:function(ev){if(ev.path){return ev.path[0];}
+return ev.target;},handleNative:function(ev){var handled;var type=ev.type;var node=wrap(ev.currentTarget);var gobj=node[GESTURE_KEY];if(!gobj){return;}
+var gs=gobj[type];if(!gs){return;}
+if(!ev[HANDLED_OBJ]){ev[HANDLED_OBJ]={};if(type.slice(0,5)==='touch'){var t=ev.changedTouches[0];if(type==='touchstart'){if(ev.touches.length===1){POINTERSTATE.touch.id=t.identifier;}}
+if(POINTERSTATE.touch.id!==t.identifier){return;}
+if(!HAS_NATIVE_TA){if(type==='touchstart'||type==='touchmove'){Gestures.handleTouchAction(ev);}}}}
+handled=ev[HANDLED_OBJ];if(handled.skip){return;}
+var recognizers=Gestures.recognizers;for(var i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){if(r.flow&&r.flow.start.indexOf(ev.type)>-1&&r.reset){r.reset();}}}
+for(i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){handled[r.name]=true;r[type](ev);}}},handleTouchAction:function(ev){var t=ev.changedTouches[0];var type=ev.type;if(type==='touchstart'){POINTERSTATE.touch.x=t.clientX;POINTERSTATE.touch.y=t.clientY;POINTERSTATE.touch.scrollDecided=false;}else if(type==='touchmove'){if(POINTERSTATE.touch.scrollDecided){return;}
+POINTERSTATE.touch.scrollDecided=true;var ta=firstTouchAction(ev);var prevent=false;var dx=Math.abs(POINTERSTATE.touch.x-t.clientX);var dy=Math.abs(POINTERSTATE.touch.y-t.clientY);if(!ev.cancelable){}else if(ta==='none'){prevent=true;}else if(ta==='pan-x'){prevent=dy>dx;}else if(ta==='pan-y'){prevent=dx>dy;}
+if(prevent){ev.preventDefault();}else{Gestures.prevent('track');}}},add:function(node,evType,handler){node=wrap(node);var recognizer=this.gestures[evType];var deps=recognizer.deps;var name=recognizer.name;var gobj=node[GESTURE_KEY];if(!gobj){node[GESTURE_KEY]=gobj={};}
+for(var i=0,dep,gd;i<deps.length;i++){dep=deps[i];if(IS_TOUCH_ONLY&&isMouseEvent(dep)&&dep!=='click'){continue;}
+gd=gobj[dep];if(!gd){gobj[dep]=gd={_count:0};}
+if(gd._count===0){node.addEventListener(dep,this.handleNative,PASSIVE_TOUCH(dep));}
+gd[name]=(gd[name]||0)+1;gd._count=(gd._count||0)+1;}
+node.addEventListener(evType,handler);if(recognizer.touchAction){this.setTouchAction(node,recognizer.touchAction);}},remove:function(node,evType,handler){node=wrap(node);var recognizer=this.gestures[evType];var deps=recognizer.deps;var name=recognizer.name;var gobj=node[GESTURE_KEY];if(gobj){for(var i=0,dep,gd;i<deps.length;i++){dep=deps[i];gd=gobj[dep];if(gd&&gd[name]){gd[name]=(gd[name]||1)-1;gd._count=(gd._count||1)-1;if(gd._count===0){node.removeEventListener(dep,this.handleNative,PASSIVE_TOUCH(dep));}}}}
+node.removeEventListener(evType,handler);},register:function(recog){this.recognizers.push(recog);for(var i=0;i<recog.emits.length;i++){this.gestures[recog.emits[i]]=recog;}},findRecognizerByEvent:function(evName){for(var i=0,r;i<this.recognizers.length;i++){r=this.recognizers[i];for(var j=0,n;j<r.emits.length;j++){n=r.emits[j];if(n===evName){return r;}}}
+return null;},setTouchAction:function(node,value){if(HAS_NATIVE_TA){node.style.touchAction=value;}
+node[TOUCH_ACTION]=value;},fire:function(target,type,detail){var ev=Polymer.Base.fire(type,detail,{node:target,bubbles:true,cancelable:true});if(ev.defaultPrevented){var preventer=detail.preventer||detail.sourceEvent;if(preventer&&preventer.preventDefault){preventer.preventDefault();}}},prevent:function(evName){var recognizer=this.findRecognizerByEvent(evName);if(recognizer.info){recognizer.info.prevent=true;}},resetMouseCanceller:function(){if(POINTERSTATE.mouse.mouseIgnoreJob){POINTERSTATE.mouse.mouseIgnoreJob.complete();}}};Gestures.register({name:'downup',deps:['mousedown','touchstart','touchend'],flow:{start:['mousedown','touchstart'],end:['mouseup','touchend']},emits:['down','up'],info:{movefn:null,upfn:null},reset:function(){untrackDocument(this.info);},mousedown:function(e){if(!hasLeftMouseButton(e)){return;}
+var t=Gestures.findOriginalTarget(e);var self=this;var movefn=function movefn(e){if(!hasLeftMouseButton(e)){self.fire('up',t,e);untrackDocument(self.info);}};var upfn=function upfn(e){if(hasLeftMouseButton(e)){self.fire('up',t,e);}
+untrackDocument(self.info);};trackDocument(this.info,movefn,upfn);this.fire('down',t,e);},touchstart:function(e){this.fire('down',Gestures.findOriginalTarget(e),e.changedTouches[0],e);},touchend:function(e){this.fire('up',Gestures.findOriginalTarget(e),e.changedTouches[0],e);},fire:function(type,target,event,preventer){Gestures.fire(target,type,{x:event.clientX,y:event.clientY,sourceEvent:event,preventer:preventer,prevent:function(e){return Gestures.prevent(e);}});}});Gestures.register({name:'track',touchAction:'none',deps:['mousedown','touchstart','touchmove','touchend'],flow:{start:['mousedown','touchstart'],end:['mouseup','touchend']},emits:['track'],info:{x:0,y:0,state:'start',started:false,moves:[],addMove:function(move){if(this.moves.length>TRACK_LENGTH){this.moves.shift();}
+this.moves.push(move);},movefn:null,upfn:null,prevent:false},reset:function(){this.info.state='start';this.info.started=false;this.info.moves=[];this.info.x=0;this.info.y=0;this.info.prevent=false;untrackDocument(this.info);},hasMovedEnough:function(x,y){if(this.info.prevent){return false;}
+if(this.info.started){return true;}
+var dx=Math.abs(this.info.x-x);var dy=Math.abs(this.info.y-y);return dx>=TRACK_DISTANCE||dy>=TRACK_DISTANCE;},mousedown:function(e){if(!hasLeftMouseButton(e)){return;}
+var t=Gestures.findOriginalTarget(e);var self=this;var movefn=function movefn(e){var x=e.clientX,y=e.clientY;if(self.hasMovedEnough(x,y)){self.info.state=self.info.started?e.type==='mouseup'?'end':'track':'start';if(self.info.state==='start'){Gestures.prevent('tap');}
+self.info.addMove({x:x,y:y});if(!hasLeftMouseButton(e)){self.info.state='end';untrackDocument(self.info);}
+self.fire(t,e);self.info.started=true;}};var upfn=function upfn(e){if(self.info.started){movefn(e);}
+untrackDocument(self.info);};trackDocument(this.info,movefn,upfn);this.info.x=e.clientX;this.info.y=e.clientY;},touchstart:function(e){var ct=e.changedTouches[0];this.info.x=ct.clientX;this.info.y=ct.clientY;},touchmove:function(e){var t=Gestures.findOriginalTarget(e);var ct=e.changedTouches[0];var x=ct.clientX,y=ct.clientY;if(this.hasMovedEnough(x,y)){if(this.info.state==='start'){Gestures.prevent('tap');}
+this.info.addMove({x:x,y:y});this.fire(t,ct);this.info.state='track';this.info.started=true;}},touchend:function(e){var t=Gestures.findOriginalTarget(e);var ct=e.changedTouches[0];if(this.info.started){this.info.state='end';this.info.addMove({x:ct.clientX,y:ct.clientY});this.fire(t,ct,e);}},fire:function(target,touch,preventer){var secondlast=this.info.moves[this.info.moves.length-2];var lastmove=this.info.moves[this.info.moves.length-1];var dx=lastmove.x-this.info.x;var dy=lastmove.y-this.info.y;var ddx,ddy=0;if(secondlast){ddx=lastmove.x-secondlast.x;ddy=lastmove.y-secondlast.y;}
+return Gestures.fire(target,'track',{state:this.info.state,x:touch.clientX,y:touch.clientY,dx:dx,dy:dy,ddx:ddx,ddy:ddy,sourceEvent:touch,preventer:preventer,hover:function(){return Gestures.deepTargetFind(touch.clientX,touch.clientY);}});}});Gestures.register({name:'tap',deps:['mousedown','click','touchstart','touchend'],flow:{start:['mousedown','touchstart'],end:['click','touchend']},emits:['tap'],info:{x:NaN,y:NaN,prevent:false},reset:function(){this.info.x=NaN;this.info.y=NaN;this.info.prevent=false;},save:function(e){this.info.x=e.clientX;this.info.y=e.clientY;},mousedown:function(e){if(hasLeftMouseButton(e)){this.save(e);}},click:function(e){if(hasLeftMouseButton(e)){this.forward(e);}},touchstart:function(e){this.save(e.changedTouches[0],e);},touchend:function(e){this.forward(e.changedTouches[0],e);},forward:function(e,preventer){var dx=Math.abs(e.clientX-this.info.x);var dy=Math.abs(e.clientY-this.info.y);var t=Gestures.findOriginalTarget(e);if(isNaN(dx)||isNaN(dy)||dx<=TAP_DISTANCE&&dy<=TAP_DISTANCE||isSyntheticClick(e)){if(!this.info.prevent){Gestures.fire(t,'tap',{x:e.clientX,y:e.clientY,sourceEvent:e,preventer:preventer});}}}});var DIRECTION_MAP={x:'pan-x',y:'pan-y',none:'none',all:'auto'};Polymer.Base._addFeature({_setupGestures:function(){this.__polymerGestures=null;},_listen:function(node,eventName,handler){if(Gestures.gestures[eventName]){Gestures.add(node,eventName,handler);}else{node.addEventListener(eventName,handler);}},_unlisten:function(node,eventName,handler){if(Gestures.gestures[eventName]){Gestures.remove(node,eventName,handler);}else{node.removeEventListener(eventName,handler);}},setScrollDirection:function(direction,node){node=node||this;Gestures.setTouchAction(node,DIRECTION_MAP[direction]||'auto');}});Polymer.Gestures=Gestures;}());(function(){'use strict';Polymer.Base._addFeature({$$:function(slctr){return Polymer.dom(this.root).querySelector(slctr);},toggleClass:function(name,bool,node){node=node||this;if(arguments.length==1){bool=!node.classList.contains(name);}
+if(bool){Polymer.dom(node).classList.add(name);}else{Polymer.dom(node).classList.remove(name);}},toggleAttribute:function(name,bool,node){node=node||this;if(arguments.length==1){bool=!node.hasAttribute(name);}
+if(bool){Polymer.dom(node).setAttribute(name,'');}else{Polymer.dom(node).removeAttribute(name);}},classFollows:function(name,toElement,fromElement){if(fromElement){Polymer.dom(fromElement).classList.remove(name);}
+if(toElement){Polymer.dom(toElement).classList.add(name);}},attributeFollows:function(name,toElement,fromElement){if(fromElement){Polymer.dom(fromElement).removeAttribute(name);}
+if(toElement){Polymer.dom(toElement).setAttribute(name,'');}},getEffectiveChildNodes:function(){return Polymer.dom(this).getEffectiveChildNodes();},getEffectiveChildren:function(){var list=Polymer.dom(this).getEffectiveChildNodes();return list.filter(function(n){return n.nodeType===Node.ELEMENT_NODE;});},getEffectiveTextContent:function(){var cn=this.getEffectiveChildNodes();var tc=[];for(var i=0,c;c=cn[i];i++){if(c.nodeType!==Node.COMMENT_NODE){tc.push(Polymer.dom(c).textContent);}}
+return tc.join('');},queryEffectiveChildren:function(slctr){var e$=Polymer.dom(this).queryDistributedElements(slctr);return e$&&e$[0];},queryAllEffectiveChildren:function(slctr){return Polymer.dom(this).queryDistributedElements(slctr);},getContentChildNodes:function(slctr){var content=Polymer.dom(this.root).querySelector(slctr||'content');return content?Polymer.dom(content).getDistributedNodes():[];},getContentChildren:function(slctr){return this.getContentChildNodes(slctr).filter(function(n){return n.nodeType===Node.ELEMENT_NODE;});},fire:function(type,detail,options){options=options||Polymer.nob;var node=options.node||this;detail=detail===null||detail===undefined?{}:detail;var bubbles=options.bubbles===undefined?true:options.bubbles;var cancelable=Boolean(options.cancelable);var useCache=options._useCache;var event=this._getEvent(type,bubbles,cancelable,useCache);event.detail=detail;if(useCache){this.__eventCache[type]=null;}
+node.dispatchEvent(event);if(useCache){this.__eventCache[type]=event;}
+return event;},__eventCache:{},_getEvent:function(type,bubbles,cancelable,useCache){var event=useCache&&this.__eventCache[type];if(!event||(event.bubbles!=bubbles||event.cancelable!=cancelable)){event=new Event(type,{bubbles:Boolean(bubbles),cancelable:cancelable});}
+return event;},async:function(callback,waitTime){var self=this;return Polymer.Async.run(function(){callback.call(self);},waitTime);},cancelAsync:function(handle){Polymer.Async.cancel(handle);},arrayDelete:function(path,item){var index;if(Array.isArray(path)){index=path.indexOf(item);if(index>=0){return path.splice(index,1);}}else{var arr=this._get(path);index=arr.indexOf(item);if(index>=0){return this.splice(path,index,1);}}},transform:function(transform,node){node=node||this;node.style.webkitTransform=transform;node.style.transform=transform;},translate3d:function(x,y,z,node){node=node||this;this.transform('translate3d('+x+','+y+','+z+')',node);},importHref:function(href,onload,onerror,optAsync){var link=document.createElement('link');link.rel='import';link.href=href;var list=Polymer.Base.importHref.imported=Polymer.Base.importHref.imported||{};var cached=list[link.href];var imprt=cached||link;var self=this;var loadListener=function(e){e.target.__firedLoad=true;e.target.removeEventListener('load',loadListener);e.target.removeEventListener('error',errorListener);return onload.call(self,e);};var errorListener=function(e){e.target.__firedError=true;e.target.removeEventListener('load',loadListener);e.target.removeEventListener('error',errorListener);return onerror.call(self,e);};if(onload){imprt.addEventListener('load',loadListener);}
+if(onerror){imprt.addEventListener('error',errorListener);}
+if(cached){if(cached.__firedLoad){cached.dispatchEvent(new Event('load'));}
+if(cached.__firedError){cached.dispatchEvent(new Event('error'));}}else{list[link.href]=link;optAsync=Boolean(optAsync);if(optAsync){link.setAttribute('async','');}
+document.head.appendChild(link);}
+return imprt;},create:function(tag,props){var elt=document.createElement(tag);if(props){for(var n in props){elt[n]=props[n];}}
+return elt;},isLightDescendant:function(node){return this!==node&&this.contains(node)&&Polymer.dom(this).getOwnerRoot()===Polymer.dom(node).getOwnerRoot();},isLocalDescendant:function(node){return this.root===Polymer.dom(node).getOwnerRoot();}});if(!Polymer.Settings.useNativeCustomElements){var importHref=Polymer.Base.importHref;Polymer.Base.importHref=function(href,onload,onerror,optAsync){CustomElements.ready=false;var loadFn=function(e){CustomElements.upgradeDocumentTree(document);CustomElements.ready=true;if(onload){return onload.call(this,e);}};return importHref.call(this,href,loadFn,onerror,optAsync);};}}());Polymer.Bind={prepareModel:function(model){Polymer.Base.mixin(model,this._modelApi);},_modelApi:{_notifyChange:function(source,event,value){value=value===undefined?this[source]:value;event=event||Polymer.CaseMap.camelToDashCase(source)+'-changed';this.fire(event,{value:value},{bubbles:false,cancelable:false,_useCache:Polymer.Settings.eventDataCache||!Polymer.Settings.isIE});},_propertySetter:function(property,value,effects,fromAbove){var old=this.__data__[property];if(old!==value&&(old===old||value===value)){this.__data__[property]=value;if(typeof value=='object'){this._clearPath(property);}
+if(this._propertyChanged){this._propertyChanged(property,value,old);}
+if(effects){this._effectEffects(property,value,effects,old,fromAbove);}}
+return old;},__setProperty:function(property,value,quiet,node){node=node||this;var effects=node._propertyEffects&&node._propertyEffects[property];if(effects){node._propertySetter(property,value,effects,quiet);}else if(node[property]!==value){node[property]=value;}},_effectEffects:function(property,value,effects,old,fromAbove){for(var i=0,l=effects.length,fx;i<l&&(fx=effects[i]);i++){fx.fn.call(this,property,this[property],fx.effect,old,fromAbove);}},_clearPath:function(path){for(var prop in this.__data__){if(Polymer.Path.isDescendant(path,prop)){this.__data__[prop]=undefined;}}}},ensurePropertyEffects:function(model,property){if(!model._propertyEffects){model._propertyEffects={};}
+var fx=model._propertyEffects[property];if(!fx){fx=model._propertyEffects[property]=[];}
+return fx;},addPropertyEffect:function(model,property,kind,effect){var fx=this.ensurePropertyEffects(model,property);var propEffect={kind:kind,effect:effect,fn:Polymer.Bind['_'+kind+'Effect']};fx.push(propEffect);return propEffect;},createBindings:function(model){var fx$=model._propertyEffects;if(fx$){for(var n in fx$){var fx=fx$[n];fx.sort(this._sortPropertyEffects);this._createAccessors(model,n,fx);}}},_sortPropertyEffects:function(){var EFFECT_ORDER={'compute':0,'annotation':1,'annotatedComputation':2,'reflect':3,'notify':4,'observer':5,'complexObserver':6,'function':7};return function(a,b){return EFFECT_ORDER[a.kind]-EFFECT_ORDER[b.kind];};}(),_createAccessors:function(model,property,effects){var defun={get:function(){return this.__data__[property];}};var setter=function(value){this._propertySetter(property,value,effects);};var info=model.getPropertyInfo&&model.getPropertyInfo(property);if(info&&info.readOnly){if(!info.computed){model['_set'+this.upper(property)]=setter;}}else{defun.set=setter;}
+Object.defineProperty(model,property,defun);},upper:function(name){return name[0].toUpperCase()+name.substring(1);},_addAnnotatedListener:function(model,index,property,path,event,negated){if(!model._bindListeners){model._bindListeners=[];}
+var fn=this._notedListenerFactory(property,path,Polymer.Path.isDeep(path),negated);var eventName=event||Polymer.CaseMap.camelToDashCase(property)+'-changed';model._bindListeners.push({index:index,property:property,path:path,changedFn:fn,event:eventName});},_isEventBogus:function(e,target){return e.path&&e.path[0]!==target;},_notedListenerFactory:function(property,path,isStructured,negated){return function(target,value,targetPath){if(targetPath){var newPath=Polymer.Path.translate(property,path,targetPath);this._notifyPath(newPath,value);}else{value=target[property];if(negated){value=!value;}
+if(!isStructured){this[path]=value;}else{if(this.__data__[path]!=value){this.set(path,value);}}}};},prepareInstance:function(inst){inst.__data__=Object.create(null);},setupBindListeners:function(inst){var b$=inst._bindListeners;for(var i=0,l=b$.length,info;i<l&&(info=b$[i]);i++){var node=inst._nodes[info.index];this._addNotifyListener(node,inst,info.event,info.changedFn);}},_addNotifyListener:function(element,context,event,changedFn){element.addEventListener(event,function(e){return context._notifyListener(changedFn,e);});}};Polymer.Base.mixin(Polymer.Bind,{_shouldAddListener:function(effect){return effect.name&&effect.kind!='attribute'&&effect.kind!='text'&&!effect.isCompound&&effect.parts[0].mode==='{';},_annotationEffect:function(source,value,effect){if(source!=effect.value){value=this._get(effect.value);this.__data__[effect.value]=value;}
+this._applyEffectValue(effect,value);},_reflectEffect:function(source,value,effect){this.reflectPropertyToAttribute(source,effect.attribute,value);},_notifyEffect:function(source,value,effect,old,fromAbove){if(!fromAbove){this._notifyChange(source,effect.event,value);}},_functionEffect:function(source,value,fn,old,fromAbove){fn.call(this,source,value,old,fromAbove);},_observerEffect:function(source,value,effect,old){var fn=this[effect.method];if(fn){fn.call(this,value,old);}else{this._warn(this._logf('_observerEffect','observer method `'+effect.method+'` not defined'));}},_complexObserverEffect:function(source,value,effect){var fn=this[effect.method];if(fn){var args=Polymer.Bind._marshalArgs(this.__data__,effect,source,value);if(args){fn.apply(this,args);}}else if(effect.dynamicFn){}else{this._warn(this._logf('_complexObserverEffect','observer method `'+effect.method+'` not defined'));}},_computeEffect:function(source,value,effect){var fn=this[effect.method];if(fn){var args=Polymer.Bind._marshalArgs(this.__data__,effect,source,value);if(args){var computedvalue=fn.apply(this,args);this.__setProperty(effect.name,computedvalue);}}else if(effect.dynamicFn){}else{this._warn(this._logf('_computeEffect','compute method `'+effect.method+'` not defined'));}},_annotatedComputationEffect:function(source,value,effect){var computedHost=this._rootDataHost||this;var fn=computedHost[effect.method];if(fn){var args=Polymer.Bind._marshalArgs(this.__data__,effect,source,value);if(args){var computedvalue=fn.apply(computedHost,args);this._applyEffectValue(effect,computedvalue);}}else if(effect.dynamicFn){}else{computedHost._warn(computedHost._logf('_annotatedComputationEffect','compute method `'+effect.method+'` not defined'));}},_marshalArgs:function(model,effect,path,value){var values=[];var args=effect.args;var bailoutEarly=args.length>1||effect.dynamicFn;for(var i=0,l=args.length;i<l;i++){var arg=args[i];var name=arg.name;var v;if(arg.literal){v=arg.value;}else if(path===name){v=value;}else{v=model[name];if(v===undefined&&arg.structured){v=Polymer.Base._get(name,model);}}
+if(bailoutEarly&&v===undefined){return;}
+if(arg.wildcard){var matches=Polymer.Path.isAncestor(path,name);values[i]={path:matches?path:name,value:matches?value:v,base:v};}else{values[i]=v;}}
+return values;}});Polymer.Base._addFeature({_addPropertyEffect:function(property,kind,effect){var prop=Polymer.Bind.addPropertyEffect(this,property,kind,effect);prop.pathFn=this['_'+prop.kind+'PathEffect'];},_prepEffects:function(){Polymer.Bind.prepareModel(this);this._addAnnotationEffects(this._notes);},_prepBindings:function(){Polymer.Bind.createBindings(this);},_addPropertyEffects:function(properties){if(properties){for(var p in properties){var prop=properties[p];if(prop.observer){this._addObserverEffect(p,prop.observer);}
+if(prop.computed){prop.readOnly=true;this._addComputedEffect(p,prop.computed);}
+if(prop.notify){this._addPropertyEffect(p,'notify',{event:Polymer.CaseMap.camelToDashCase(p)+'-changed'});}
+if(prop.reflectToAttribute){var attr=Polymer.CaseMap.camelToDashCase(p);if(attr[0]==='-'){this._warn(this._logf('_addPropertyEffects','Property '+p+' cannot be reflected to attribute '+attr+' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.'));}else{this._addPropertyEffect(p,'reflect',{attribute:attr});}}
+if(prop.readOnly){Polymer.Bind.ensurePropertyEffects(this,p);}}}},_addComputedEffect:function(name,expression){var sig=this._parseMethod(expression);var dynamicFn=sig.dynamicFn;for(var i=0,arg;i<sig.args.length&&(arg=sig.args[i]);i++){this._addPropertyEffect(arg.model,'compute',{method:sig.method,args:sig.args,trigger:arg,name:name,dynamicFn:dynamicFn});}
+if(dynamicFn){this._addPropertyEffect(sig.method,'compute',{method:sig.method,args:sig.args,trigger:null,name:name,dynamicFn:dynamicFn});}},_addObserverEffect:function(property,observer){this._addPropertyEffect(property,'observer',{method:observer,property:property});},_addComplexObserverEffects:function(observers){if(observers){for(var i=0,o;i<observers.length&&(o=observers[i]);i++){this._addComplexObserverEffect(o);}}},_addComplexObserverEffect:function(observer){var sig=this._parseMethod(observer);if(!sig){throw new Error('Malformed observer expression \''+observer+'\'');}
+var dynamicFn=sig.dynamicFn;for(var i=0,arg;i<sig.args.length&&(arg=sig.args[i]);i++){this._addPropertyEffect(arg.model,'complexObserver',{method:sig.method,args:sig.args,trigger:arg,dynamicFn:dynamicFn});}
+if(dynamicFn){this._addPropertyEffect(sig.method,'complexObserver',{method:sig.method,args:sig.args,trigger:null,dynamicFn:dynamicFn});}},_addAnnotationEffects:function(notes){for(var i=0,note;i<notes.length&&(note=notes[i]);i++){var b$=note.bindings;for(var j=0,binding;j<b$.length&&(binding=b$[j]);j++){this._addAnnotationEffect(binding,i);}}},_addAnnotationEffect:function(note,index){if(Polymer.Bind._shouldAddListener(note)){Polymer.Bind._addAnnotatedListener(this,index,note.name,note.parts[0].value,note.parts[0].event,note.parts[0].negate);}
+for(var i=0;i<note.parts.length;i++){var part=note.parts[i];if(part.signature){this._addAnnotatedComputationEffect(note,part,index);}else if(!part.literal){if(note.kind==='attribute'&&note.name[0]==='-'){this._warn(this._logf('_addAnnotationEffect','Cannot set attribute '+note.name+' because "-" is not a valid attribute starting character'));}else{this._addPropertyEffect(part.model,'annotation',{kind:note.kind,index:index,name:note.name,propertyName:note.propertyName,value:part.value,isCompound:note.isCompound,compoundIndex:part.compoundIndex,event:part.event,customEvent:part.customEvent,negate:part.negate});}}}},_addAnnotatedComputationEffect:function(note,part,index){var sig=part.signature;if(sig.static){this.__addAnnotatedComputationEffect('__static__',index,note,part,null);}else{for(var i=0,arg;i<sig.args.length&&(arg=sig.args[i]);i++){if(!arg.literal){this.__addAnnotatedComputationEffect(arg.model,index,note,part,arg);}}
+if(sig.dynamicFn){this.__addAnnotatedComputationEffect(sig.method,index,note,part,null);}}},__addAnnotatedComputationEffect:function(property,index,note,part,trigger){this._addPropertyEffect(property,'annotatedComputation',{index:index,isCompound:note.isCompound,compoundIndex:part.compoundIndex,kind:note.kind,name:note.name,negate:part.negate,method:part.signature.method,args:part.signature.args,trigger:trigger,dynamicFn:part.signature.dynamicFn});},_parseMethod:function(expression){var m=expression.match(/([^\s]+?)\(([\s\S]*)\)/);if(m){var sig={method:m[1],static:true};if(this.getPropertyInfo(sig.method)!==Polymer.nob){sig.static=false;sig.dynamicFn=true;}
+if(m[2].trim()){var args=m[2].replace(/\\,/g,'&comma;').split(',');return this._parseArgs(args,sig);}else{sig.args=Polymer.nar;return sig;}}},_parseArgs:function(argList,sig){sig.args=argList.map(function(rawArg){var arg=this._parseArg(rawArg);if(!arg.literal){sig.static=false;}
+return arg;},this);return sig;},_parseArg:function(rawArg){var arg=rawArg.trim().replace(/&comma;/g,',').replace(/\\(.)/g,'$1');var a={name:arg};var fc=arg[0];if(fc==='-'){fc=arg[1];}
+if(fc>='0'&&fc<='9'){fc='#';}
+switch(fc){case'\'':case'"':a.value=arg.slice(1,-1);a.literal=true;break;case'#':a.value=Number(arg);a.literal=true;break;}
+if(!a.literal){a.model=Polymer.Path.root(arg);a.structured=Polymer.Path.isDeep(arg);if(a.structured){a.wildcard=arg.slice(-2)=='.*';if(a.wildcard){a.name=arg.slice(0,-2);}}}
+return a;},_marshalInstanceEffects:function(){Polymer.Bind.prepareInstance(this);if(this._bindListeners){Polymer.Bind.setupBindListeners(this);}},_applyEffectValue:function(info,value){var node=this._nodes[info.index];var property=info.name;value=this._computeFinalAnnotationValue(node,property,value,info);if(info.kind=='attribute'){this.serializeValueToAttribute(value,property,node);}else{var pinfo=node._propertyInfo&&node._propertyInfo[property];if(pinfo&&pinfo.readOnly){return;}
+this.__setProperty(property,value,Polymer.Settings.suppressBindingNotifications,node);}},_computeFinalAnnotationValue:function(node,property,value,info){if(info.negate){value=!value;}
+if(info.isCompound){var storage=node.__compoundStorage__[property];storage[info.compoundIndex]=value;value=storage.join('');}
+if(info.kind!=='attribute'){if(property==='className'){value=this._scopeElementClass(node,value);}
+if(property==='textContent'||node.localName=='input'&&property=='value'){value=value==undefined?'':value;}}
+return value;},_executeStaticEffects:function(){if(this._propertyEffects&&this._propertyEffects.__static__){this._effectEffects('__static__',null,this._propertyEffects.__static__);}}});(function(){var usePolyfillProto=Polymer.Settings.usePolyfillProto;var avoidInstanceProperties=Boolean(Object.getOwnPropertyDescriptor(document.documentElement,'properties'));Polymer.Base._addFeature({_setupConfigure:function(initialConfig){this._config={};this._handlers=[];this._aboveConfig=null;if(initialConfig){for(var i in initialConfig){if(initialConfig[i]!==undefined){this._config[i]=initialConfig[i];}}}},_marshalAttributes:function(){this._takeAttributesToModel(this._config);},_attributeChangedImpl:function(name){var model=this._clientsReadied?this:this._config;this._setAttributeToProperty(model,name);},_configValue:function(name,value){var info=this._propertyInfo[name];if(!info||!info.readOnly){this._config[name]=value;}},_beforeClientsReady:function(){this._configure();},_configure:function(){this._configureAnnotationReferences();this._configureInstanceProperties();this._aboveConfig=this.mixin({},this._config);var config={};for(var i=0;i<this.behaviors.length;i++){this._configureProperties(this.behaviors[i].properties,config);}
+this._configureProperties(avoidInstanceProperties?this.__proto__.properties:this.properties,config);this.mixin(config,this._aboveConfig);this._config=config;if(this._clients&&this._clients.length){this._distributeConfig(this._config);}},_configureInstanceProperties:function(){for(var i in this._propertyEffects){if(!usePolyfillProto&&this.hasOwnProperty(i)){this._configValue(i,this[i]);delete this[i];}}},_configureProperties:function(properties,config){for(var i in properties){var c=properties[i];if(c.value!==undefined){var value=c.value;if(typeof value=='function'){value=value.call(this,this._config);}
+config[i]=value;}}},_distributeConfig:function(config){var fx$=this._propertyEffects;if(fx$){for(var p in config){var fx=fx$[p];if(fx){for(var i=0,l=fx.length,x;i<l&&(x=fx[i]);i++){if(x.kind==='annotation'){var node=this._nodes[x.effect.index];var name=x.effect.propertyName;var isAttr=x.effect.kind=='attribute';var hasEffect=node._propertyEffects&&node._propertyEffects[name];if(node._configValue&&(hasEffect||!isAttr)){var value=p===x.effect.value?config[p]:this._get(x.effect.value,config);value=this._computeFinalAnnotationValue(node,name,value,x.effect);if(isAttr){value=node.deserialize(this.serialize(value),node._propertyInfo[name].type);}
+node._configValue(name,value);}}}}}}},_afterClientsReady:function(){this.importPath=this._importPath;this.rootPath=Polymer.rootPath;this._executeStaticEffects();this._applyConfig(this._config,this._aboveConfig);this._flushHandlers();},_applyConfig:function(config,aboveConfig){for(var n in config){if(this[n]===undefined){this.__setProperty(n,config[n],n in aboveConfig);}}},_notifyListener:function(fn,e){if(!Polymer.Bind._isEventBogus(e,e.target)){var value,path;if(e.detail){value=e.detail.value;path=e.detail.path;}
+if(!this._clientsReadied){this._queueHandler([fn,e.target,value,path]);}else{return fn.call(this,e.target,value,path);}}},_queueHandler:function(args){this._handlers.push(args);},_flushHandlers:function(){var h$=this._handlers;for(var i=0,l=h$.length,h;i<l&&(h=h$[i]);i++){h[0].call(this,h[1],h[2],h[3]);}
+this._handlers=[];}});}());(function(){'use strict';var Path=Polymer.Path;Polymer.Base._addFeature({notifyPath:function(path,value,fromAbove){var info={};var v=this._get(path,this,info);if(arguments.length===1){value=v;}
+if(info.path){this._notifyPath(info.path,value,fromAbove);}},_notifyPath:function(path,value,fromAbove){var old=this._propertySetter(path,value);if(old!==value&&(old===old||value===value)){this._pathEffector(path,value);if(!fromAbove){this._notifyPathUp(path,value);}
+return true;}},_getPathParts:function(path){if(Array.isArray(path)){var parts=[];for(var i=0;i<path.length;i++){var args=path[i].toString().split('.');for(var j=0;j<args.length;j++){parts.push(args[j]);}}
+return parts;}else{return path.toString().split('.');}},set:function(path,value,root){var prop=root||this;var parts=this._getPathParts(path);var array;var last=parts[parts.length-1];if(parts.length>1){for(var i=0;i<parts.length-1;i++){var part=parts[i];if(array&&part[0]=='#'){prop=Polymer.Collection.get(array).getItem(part);}else{prop=prop[part];if(array&&parseInt(part,10)==part){parts[i]=Polymer.Collection.get(array).getKey(prop);}}
+if(!prop){return;}
+array=Array.isArray(prop)?prop:null;}
+if(array){var coll=Polymer.Collection.get(array);var old,key;if(last[0]=='#'){key=last;old=coll.getItem(key);last=array.indexOf(old);coll.setItem(key,value);}else if(parseInt(last,10)==last){old=prop[last];key=coll.getKey(old);parts[i]=key;coll.setItem(key,value);}}
+prop[last]=value;if(!root){this._notifyPath(parts.join('.'),value);}}else{prop[path]=value;}},get:function(path,root){return this._get(path,root);},_get:function(path,root,info){var prop=root||this;var parts=this._getPathParts(path);var array;for(var i=0;i<parts.length;i++){if(!prop){return;}
+var part=parts[i];if(array&&part[0]=='#'){prop=Polymer.Collection.get(array).getItem(part);}else{prop=prop[part];if(info&&array&&parseInt(part,10)==part){parts[i]=Polymer.Collection.get(array).getKey(prop);}}
+array=Array.isArray(prop)?prop:null;}
+if(info){info.path=parts.join('.');}
+return prop;},_pathEffector:function(path,value){var model=Path.root(path);var fx$=this._propertyEffects&&this._propertyEffects[model];if(fx$){for(var i=0,fx;i<fx$.length&&(fx=fx$[i]);i++){var fxFn=fx.pathFn;if(fxFn){fxFn.call(this,path,value,fx.effect);}}}
+if(this._boundPaths){this._notifyBoundPaths(path,value);}},_annotationPathEffect:function(path,value,effect){if(Path.matches(effect.value,false,path)){Polymer.Bind._annotationEffect.call(this,path,value,effect);}else if(!effect.negate&&Path.isDescendant(effect.value,path)){var node=this._nodes[effect.index];if(node&&node._notifyPath){var newPath=Path.translate(effect.value,effect.name,path);node._notifyPath(newPath,value,true);}}},_complexObserverPathEffect:function(path,value,effect){if(Path.matches(effect.trigger.name,effect.trigger.wildcard,path)){Polymer.Bind._complexObserverEffect.call(this,path,value,effect);}},_computePathEffect:function(path,value,effect){if(Path.matches(effect.trigger.name,effect.trigger.wildcard,path)){Polymer.Bind._computeEffect.call(this,path,value,effect);}},_annotatedComputationPathEffect:function(path,value,effect){if(Path.matches(effect.trigger.name,effect.trigger.wildcard,path)){Polymer.Bind._annotatedComputationEffect.call(this,path,value,effect);}},linkPaths:function(to,from){this._boundPaths=this._boundPaths||{};if(from){this._boundPaths[to]=from;}else{this.unlinkPaths(to);}},unlinkPaths:function(path){if(this._boundPaths){delete this._boundPaths[path];}},_notifyBoundPaths:function(path,value){for(var a in this._boundPaths){var b=this._boundPaths[a];if(Path.isDescendant(a,path)){this._notifyPath(Path.translate(a,b,path),value);}else if(Path.isDescendant(b,path)){this._notifyPath(Path.translate(b,a,path),value);}}},_notifyPathUp:function(path,value){var rootName=Path.root(path);var dashCaseName=Polymer.CaseMap.camelToDashCase(rootName);var eventName=dashCaseName+this._EVENT_CHANGED;this.fire(eventName,{path:path,value:value},{bubbles:false,_useCache:Polymer.Settings.eventDataCache||!Polymer.Settings.isIE});},_EVENT_CHANGED:'-changed',notifySplices:function(path,splices){var info={};var array=this._get(path,this,info);this._notifySplices(array,info.path,splices);},_notifySplices:function(array,path,splices){var change={keySplices:Polymer.Collection.applySplices(array,splices),indexSplices:splices};var splicesPath=path+'.splices';this._notifyPath(splicesPath,change);this._notifyPath(path+'.length',array.length);this.__data__[splicesPath]={keySplices:null,indexSplices:null};},_notifySplice:function(array,path,index,added,removed){this._notifySplices(array,path,[{index:index,addedCount:added,removed:removed,object:array,type:'splice'}]);},push:function(path){var info={};var array=this._get(path,this,info);var args=Array.prototype.slice.call(arguments,1);var len=array.length;var ret=array.push.apply(array,args);if(args.length){this._notifySplice(array,info.path,len,args.length,[]);}
+return ret;},pop:function(path){var info={};var array=this._get(path,this,info);var hadLength=Boolean(array.length);var args=Array.prototype.slice.call(arguments,1);var ret=array.pop.apply(array,args);if(hadLength){this._notifySplice(array,info.path,array.length,0,[ret]);}
+return ret;},splice:function(path,start){var info={};var array=this._get(path,this,info);if(start<0){start=array.length-Math.floor(-start);}else{start=Math.floor(start);}
+if(!start){start=0;}
+var args=Array.prototype.slice.call(arguments,1);var ret=array.splice.apply(array,args);var addedCount=Math.max(args.length-2,0);if(addedCount||ret.length){this._notifySplice(array,info.path,start,addedCount,ret);}
+return ret;},shift:function(path){var info={};var array=this._get(path,this,info);var hadLength=Boolean(array.length);var args=Array.prototype.slice.call(arguments,1);var ret=array.shift.apply(array,args);if(hadLength){this._notifySplice(array,info.path,0,0,[ret]);}
+return ret;},unshift:function(path){var info={};var array=this._get(path,this,info);var args=Array.prototype.slice.call(arguments,1);var ret=array.unshift.apply(array,args);if(args.length){this._notifySplice(array,info.path,0,args.length,[]);}
+return ret;},prepareModelNotifyPath:function(model){this.mixin(model,{fire:Polymer.Base.fire,_getEvent:Polymer.Base._getEvent,__eventCache:Polymer.Base.__eventCache,notifyPath:Polymer.Base.notifyPath,_get:Polymer.Base._get,_EVENT_CHANGED:Polymer.Base._EVENT_CHANGED,_notifyPath:Polymer.Base._notifyPath,_notifyPathUp:Polymer.Base._notifyPathUp,_pathEffector:Polymer.Base._pathEffector,_annotationPathEffect:Polymer.Base._annotationPathEffect,_complexObserverPathEffect:Polymer.Base._complexObserverPathEffect,_annotatedComputationPathEffect:Polymer.Base._annotatedComputationPathEffect,_computePathEffect:Polymer.Base._computePathEffect,_notifyBoundPaths:Polymer.Base._notifyBoundPaths,_getPathParts:Polymer.Base._getPathParts});}});}());Polymer.Base._addFeature({resolveUrl:function(url){return Polymer.ResolveUrl.resolveUrl(url,this._importPath);}});Polymer.CssParse=function(){return{parse:function(text){text=this._clean(text);return this._parseCss(this._lex(text),text);},_clean:function(cssText){return cssText.replace(this._rx.comments,'').replace(this._rx.port,'');},_lex:function(text){var root={start:0,end:text.length};var n=root;for(var i=0,l=text.length;i<l;i++){switch(text[i]){case this.OPEN_BRACE:if(!n.rules){n.rules=[];}
+var p=n;var previous=p.rules[p.rules.length-1];n={start:i+1,parent:p,previous:previous};p.rules.push(n);break;case this.CLOSE_BRACE:n.end=i+1;n=n.parent||root;break;}}
+return root;},_parseCss:function(node,text){var t=text.substring(node.start,node.end-1);node.parsedCssText=node.cssText=t.trim();if(node.parent){var ss=node.previous?node.previous.end:node.parent.start;t=text.substring(ss,node.start-1);t=this._expandUnicodeEscapes(t);t=t.replace(this._rx.multipleSpaces,' ');t=t.substring(t.lastIndexOf(';')+1);var s=node.parsedSelector=node.selector=t.trim();node.atRule=s.indexOf(this.AT_START)===0;if(node.atRule){if(s.indexOf(this.MEDIA_START)===0){node.type=this.types.MEDIA_RULE;}else if(s.match(this._rx.keyframesRule)){node.type=this.types.KEYFRAMES_RULE;node.keyframesName=node.selector.split(this._rx.multipleSpaces).pop();}}else{if(s.indexOf(this.VAR_START)===0){node.type=this.types.MIXIN_RULE;}else{node.type=this.types.STYLE_RULE;}}}
+var r$=node.rules;if(r$){for(var i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){this._parseCss(r,text);}}
+return node;},_expandUnicodeEscapes:function(s){return s.replace(/\\([0-9a-f]{1,6})\s/gi,function(){var code=arguments[1],repeat=6-code.length;while(repeat--){code='0'+code;}
+return'\\'+code;});},stringify:function(node,preserveProperties,text){text=text||'';var cssText='';if(node.cssText||node.rules){var r$=node.rules;if(r$&&!this._hasMixinRules(r$)){for(var i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){cssText=this.stringify(r,preserveProperties,cssText);}}else{cssText=preserveProperties?node.cssText:this.removeCustomProps(node.cssText);cssText=cssText.trim();if(cssText){cssText='  '+cssText+'\n';}}}
+if(cssText){if(node.selector){text+=node.selector+' '+this.OPEN_BRACE+'\n';}
+text+=cssText;if(node.selector){text+=this.CLOSE_BRACE+'\n\n';}}
+return text;},_hasMixinRules:function(rules){return rules[0].selector.indexOf(this.VAR_START)===0;},removeCustomProps:function(cssText){cssText=this.removeCustomPropAssignment(cssText);return this.removeCustomPropApply(cssText);},removeCustomPropAssignment:function(cssText){return cssText.replace(this._rx.customProp,'').replace(this._rx.mixinProp,'');},removeCustomPropApply:function(cssText){return cssText.replace(this._rx.mixinApply,'').replace(this._rx.varApply,'');},types:{STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1000},OPEN_BRACE:'{',CLOSE_BRACE:'}',_rx:{comments:/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g},VAR_START:'--',MEDIA_START:'@media',AT_START:'@'};}();Polymer.StyleUtil=function(){var settings=Polymer.Settings;return{unscopedStyleImports:new WeakMap(),SHADY_UNSCOPED_ATTR:'shady-unscoped',NATIVE_VARIABLES:Polymer.Settings.useNativeCSSProperties,MODULE_STYLES_SELECTOR:'style, link[rel=import][type~=css], template',INCLUDE_ATTR:'include',toCssText:function(rules,callback){if(typeof rules==='string'){rules=this.parser.parse(rules);}
+if(callback){this.forEachRule(rules,callback);}
+return this.parser.stringify(rules,this.NATIVE_VARIABLES);},forRulesInStyles:function(styles,styleRuleCallback,keyframesRuleCallback){if(styles){for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){this.forEachRuleInStyle(s,styleRuleCallback,keyframesRuleCallback);}}},forActiveRulesInStyles:function(styles,styleRuleCallback,keyframesRuleCallback){if(styles){for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){this.forEachRuleInStyle(s,styleRuleCallback,keyframesRuleCallback,true);}}},rulesForStyle:function(style){if(!style.__cssRules&&style.textContent){style.__cssRules=this.parser.parse(style.textContent);}
+return style.__cssRules;},isKeyframesSelector:function(rule){return rule.parent&&rule.parent.type===this.ruleTypes.KEYFRAMES_RULE;},forEachRuleInStyle:function(style,styleRuleCallback,keyframesRuleCallback,onlyActiveRules){var rules=this.rulesForStyle(style);var styleCallback,keyframeCallback;if(styleRuleCallback){styleCallback=function(rule){styleRuleCallback(rule,style);};}
+if(keyframesRuleCallback){keyframeCallback=function(rule){keyframesRuleCallback(rule,style);};}
+this.forEachRule(rules,styleCallback,keyframeCallback,onlyActiveRules);},forEachRule:function(node,styleRuleCallback,keyframesRuleCallback,onlyActiveRules){if(!node){return;}
+var skipRules=false;if(onlyActiveRules){if(node.type===this.ruleTypes.MEDIA_RULE){var matchMedia=node.selector.match(this.rx.MEDIA_MATCH);if(matchMedia){if(!window.matchMedia(matchMedia[1]).matches){skipRules=true;}}}}
+if(node.type===this.ruleTypes.STYLE_RULE){styleRuleCallback(node);}else if(keyframesRuleCallback&&node.type===this.ruleTypes.KEYFRAMES_RULE){keyframesRuleCallback(node);}else if(node.type===this.ruleTypes.MIXIN_RULE){skipRules=true;}
+var r$=node.rules;if(r$&&!skipRules){for(var i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){this.forEachRule(r,styleRuleCallback,keyframesRuleCallback,onlyActiveRules);}}},applyCss:function(cssText,moniker,target,contextNode){var style=this.createScopeStyle(cssText,moniker);return this.applyStyle(style,target,contextNode);},applyStyle:function(style,target,contextNode){target=target||document.head;var after=contextNode&&contextNode.nextSibling||target.firstChild;this.__lastHeadApplyNode=style;return target.insertBefore(style,after);},createScopeStyle:function(cssText,moniker){var style=document.createElement('style');if(moniker){style.setAttribute('scope',moniker);}
+style.textContent=cssText;return style;},__lastHeadApplyNode:null,applyStylePlaceHolder:function(moniker){var placeHolder=document.createComment(' Shady DOM styles for '+moniker+' ');var after=this.__lastHeadApplyNode?this.__lastHeadApplyNode.nextSibling:null;var scope=document.head;scope.insertBefore(placeHolder,after||scope.firstChild);this.__lastHeadApplyNode=placeHolder;return placeHolder;},cssFromModules:function(moduleIds,warnIfNotFound){var modules=moduleIds.trim().split(/\s+/);var cssText='';for(var i=0;i<modules.length;i++){cssText+=this.cssFromModule(modules[i],warnIfNotFound);}
+return cssText;},cssFromModule:function(moduleId,warnIfNotFound){var m=Polymer.DomModule.import(moduleId);if(m&&!m._cssText){m._cssText=this.cssFromElement(m);}
+if(!m&&warnIfNotFound){console.warn('Could not find style data in module named',moduleId);}
+return m&&m._cssText||'';},cssFromElement:function(element){var cssText='';var content=element.content||element;var e$=Polymer.TreeApi.arrayCopy(content.querySelectorAll(this.MODULE_STYLES_SELECTOR));for(var i=0,e;i<e$.length;i++){e=e$[i];if(e.localName==='template'){if(!e.hasAttribute('preserve-content')){cssText+=this.cssFromElement(e);}}else{if(e.localName==='style'){var include=e.getAttribute(this.INCLUDE_ATTR);if(include){cssText+=this.cssFromModules(include,true);}
+e=e.__appliedElement||e;e.parentNode.removeChild(e);var css=this.resolveCss(e.textContent,element.ownerDocument);if(!settings.useNativeShadow&&e.hasAttribute(this.SHADY_UNSCOPED_ATTR)){e.textContent=css;document.head.insertBefore(e,document.head.firstChild);}else{cssText+=css;}}else if(e.import&&e.import.body){var importCss=this.resolveCss(e.import.body.textContent,e.import);if(!settings.useNativeShadow&&e.hasAttribute(this.SHADY_UNSCOPED_ATTR)){if(!this.unscopedStyleImports.has(e.import)){this.unscopedStyleImports.set(e.import,true);var importStyle=document.createElement('style');importStyle.setAttribute(this.SHADY_UNSCOPED_ATTR,'');importStyle.textContent=importCss;document.head.insertBefore(importStyle,document.head.firstChild);}}else{cssText+=importCss;}}}}
+return cssText;},styleIncludesToTemplate:function(targetTemplate){var styles=targetTemplate.content.querySelectorAll('style[include]');for(var i=0,s;i<styles.length;i++){s=styles[i];s.parentNode.insertBefore(this._includesToFragment(s.getAttribute('include')),s);}},_includesToFragment:function(styleIncludes){var includeArray=styleIncludes.trim().split(' ');var frag=document.createDocumentFragment();for(var i=0;i<includeArray.length;i++){var t=Polymer.DomModule.import(includeArray[i],'template');if(t){this._addStylesToFragment(frag,t.content);}}
+return frag;},_addStylesToFragment:function(frag,source){var s$=source.querySelectorAll('style');for(var i=0,s;i<s$.length;i++){s=s$[i];var include=s.getAttribute('include');if(include){frag.appendChild(this._includesToFragment(include));}
+if(s.textContent){frag.appendChild(s.cloneNode(true));}}},isTargetedBuild:function(buildType){return settings.useNativeShadow?buildType==='shadow':buildType==='shady';},cssBuildTypeForModule:function(module){var dm=Polymer.DomModule.import(module);if(dm){return this.getCssBuildType(dm);}},getCssBuildType:function(element){return element.getAttribute('css-build');},_findMatchingParen:function(text,start){var level=0;for(var i=start,l=text.length;i<l;i++){switch(text[i]){case'(':level++;break;case')':if(--level===0){return i;}
+break;}}
+return-1;},processVariableAndFallback:function(str,callback){var start=str.indexOf('var(');if(start===-1){return callback(str,'','','');}
+var end=this._findMatchingParen(str,start+3);var inner=str.substring(start+4,end);var prefix=str.substring(0,start);var suffix=this.processVariableAndFallback(str.substring(end+1),callback);var comma=inner.indexOf(',');if(comma===-1){return callback(prefix,inner.trim(),'',suffix);}
+var value=inner.substring(0,comma).trim();var fallback=inner.substring(comma+1).trim();return callback(prefix,value,fallback,suffix);},rx:{VAR_ASSIGN:/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:([^;{]*)|{([^}]*)})(?:(?=[;\s}])|$)/gi,MIXIN_MATCH:/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,VAR_CONSUMED:/(--[\w-]+)\s*([:,;)]|$)/gi,ANIMATION_MATCH:/(animation\s*:)|(animation-name\s*:)/,MEDIA_MATCH:/@media[^(]*(\([^)]*\))/,IS_VAR:/^--/,BRACKETED:/\{[^}]*\}/g,HOST_PREFIX:'(?:^|[^.#[:])',HOST_SUFFIX:'($|[.:[\\s>+~])'},resolveCss:Polymer.ResolveUrl.resolveCss,parser:Polymer.CssParse,ruleTypes:Polymer.CssParse.types};}();Polymer.StyleTransformer=function(){var styleUtil=Polymer.StyleUtil;var settings=Polymer.Settings;var api={dom:function(node,scope,useAttr,shouldRemoveScope){this._transformDom(node,scope||'',useAttr,shouldRemoveScope);},_transformDom:function(node,selector,useAttr,shouldRemoveScope){if(node.setAttribute){this.element(node,selector,useAttr,shouldRemoveScope);}
+var c$=Polymer.dom(node).childNodes;for(var i=0;i<c$.length;i++){this._transformDom(c$[i],selector,useAttr,shouldRemoveScope);}},element:function(element,scope,useAttr,shouldRemoveScope){if(useAttr){if(shouldRemoveScope){element.removeAttribute(SCOPE_NAME);}else{element.setAttribute(SCOPE_NAME,scope);}}else{if(scope){if(element.classList){if(shouldRemoveScope){element.classList.remove(SCOPE_NAME);element.classList.remove(scope);}else{element.classList.add(SCOPE_NAME);element.classList.add(scope);}}else if(element.getAttribute){var c=element.getAttribute(CLASS);if(shouldRemoveScope){if(c){element.setAttribute(CLASS,c.replace(SCOPE_NAME,'').replace(scope,''));}}else{element.setAttribute(CLASS,(c?c+' ':'')+SCOPE_NAME+' '+scope);}}}}},elementStyles:function(element,callback){var styles=element._styles;var cssText='';var cssBuildType=element.__cssBuild;var passthrough=settings.useNativeShadow||cssBuildType==='shady';var cb;if(passthrough){var self=this;cb=function(rule){rule.selector=self._slottedToContent(rule.selector);rule.selector=rule.selector.replace(ROOT,':host > *');rule.selector=self._dirShadowTransform(rule.selector);if(callback){callback(rule);}};}
+for(var i=0,l=styles.length,s;i<l&&(s=styles[i]);i++){var rules=styleUtil.rulesForStyle(s);cssText+=passthrough?styleUtil.toCssText(rules,cb):this.css(rules,element.is,element.extends,callback,element._scopeCssViaAttr)+'\n\n';}
+return cssText.trim();},css:function(rules,scope,ext,callback,useAttr){var hostScope=this._calcHostScope(scope,ext);scope=this._calcElementScope(scope,useAttr);var self=this;return styleUtil.toCssText(rules,function(rule){if(!rule.isScoped){self.rule(rule,scope,hostScope);rule.isScoped=true;}
+if(callback){callback(rule,scope,hostScope);}});},_calcElementScope:function(scope,useAttr){if(scope){return useAttr?CSS_ATTR_PREFIX+scope+CSS_ATTR_SUFFIX:CSS_CLASS_PREFIX+scope;}else{return'';}},_calcHostScope:function(scope,ext){return ext?'[is='+scope+']':scope;},rule:function(rule,scope,hostScope){this._transformRule(rule,this._transformComplexSelector,scope,hostScope);},_transformRule:function(rule,transformer,scope,hostScope){rule.selector=rule.transformedSelector=this._transformRuleCss(rule,transformer,scope,hostScope);},_splitSelectorList:function(selector){var parts=[];var part='';for(var i=0;i>=0&&i<selector.length;i++){if(selector[i]==='('){var end=styleUtil._findMatchingParen(selector,i);part+=selector.slice(i,end+1);i=end;}else if(selector[i]===COMPLEX_SELECTOR_SEP){parts.push(part);part='';}else{part+=selector[i];}}
+if(part){parts.push(part);}
+if(parts.length===0){parts.push(selector);}
+return parts;},_transformRuleCss:function(rule,transformer,scope,hostScope){var p$=this._splitSelectorList(rule.selector);if(!styleUtil.isKeyframesSelector(rule)){for(var i=0,l=p$.length,p;i<l&&(p=p$[i]);i++){p$[i]=transformer.call(this,p,scope,hostScope);}}
+return p$.join(COMPLEX_SELECTOR_SEP);},_ensureScopedDir:function(s){var m=s.match(DIR_PAREN);if(m&&m[1]===''&&m[0].length===s.length){s='*'+s;}
+return s;},_additionalDirSelectors:function(dir,after,prefix){if(!dir||!after){return'';}
+prefix=prefix||'';return COMPLEX_SELECTOR_SEP+prefix+' '+dir+' '+after;},_transformComplexSelector:function(selector,scope,hostScope){var stop=false;var hostContext=false;var dir=false;var self=this;selector=selector.trim();selector=this._slottedToContent(selector);selector=selector.replace(ROOT,':host > *');selector=selector.replace(CONTENT_START,HOST+' $1');selector=this._ensureScopedDir(selector);selector=selector.replace(SIMPLE_SELECTOR_SEP,function(m,c,s){if(!stop){var info=self._transformCompoundSelector(s,c,scope,hostScope);stop=stop||info.stop;hostContext=hostContext||info.hostContext;dir=dir||info.dir;c=info.combinator;s=info.value;}else{s=s.replace(SCOPE_JUMP,' ');}
+return c+s;});if(hostContext){selector=selector.replace(HOST_CONTEXT_PAREN,function(m,pre,paren,post){var replacement=pre+paren+' '+hostScope+post+COMPLEX_SELECTOR_SEP+' '+pre+hostScope+paren+post;if(dir){replacement+=self._additionalDirSelectors(paren,post,hostScope);}
+return replacement;});}
+return selector;},_transformDir:function(s){s=s.replace(HOST_DIR,HOST_DIR_REPLACE);s=s.replace(DIR_PAREN,DIR_REPLACE);return s;},_transformCompoundSelector:function(selector,combinator,scope,hostScope){var jumpIndex=selector.search(SCOPE_JUMP);var hostContext=false;var dir=false;if(selector.match(DIR_PAREN)){selector=this._transformDir(selector);dir=true;}
+if(selector.indexOf(HOST_CONTEXT)>=0){hostContext=true;}else if(selector.indexOf(HOST)>=0){selector=this._transformHostSelector(selector,hostScope);}else if(jumpIndex!==0){selector=scope?this._transformSimpleSelector(selector,scope):selector;}
+if(selector.indexOf(CONTENT)>=0){combinator='';}
+var stop;if(jumpIndex>=0){selector=selector.replace(SCOPE_JUMP,' ');stop=true;}
+return{value:selector,combinator:combinator,stop:stop,hostContext:hostContext,dir:dir};},_transformSimpleSelector:function(selector,scope){var p$=selector.split(PSEUDO_PREFIX);p$[0]+=scope;return p$.join(PSEUDO_PREFIX);},_transformHostSelector:function(selector,hostScope){var m=selector.match(HOST_PAREN);var paren=m&&m[2].trim()||'';if(paren){if(!paren[0].match(SIMPLE_SELECTOR_PREFIX)){var typeSelector=paren.split(SIMPLE_SELECTOR_PREFIX)[0];if(typeSelector===hostScope){return paren;}else{return SELECTOR_NO_MATCH;}}else{return selector.replace(HOST_PAREN,function(m,host,paren){return hostScope+paren;});}}else{return selector.replace(HOST,hostScope);}},documentRule:function(rule){rule.selector=rule.parsedSelector;this.normalizeRootSelector(rule);if(!settings.useNativeShadow){this._transformRule(rule,this._transformDocumentSelector);}},normalizeRootSelector:function(rule){rule.selector=rule.selector.replace(ROOT,'html');var parts=this._splitSelectorList(rule.selector);parts=parts.filter(function(part){return!part.match(HOST_OR_HOST_GT_STAR);});rule.selector=parts.join(COMPLEX_SELECTOR_SEP);},_transformDocumentSelector:function(selector){return this._transformComplexSelector(selector,SCOPE_DOC_SELECTOR);},_slottedToContent:function(cssText){return cssText.replace(SLOTTED_PAREN,CONTENT+'> $1');},_dirShadowTransform:function(selector){if(!selector.match(/:dir\(/)){return selector;}
+return this._splitSelectorList(selector).map(function(s){s=this._ensureScopedDir(s);s=this._transformDir(s);var m=HOST_CONTEXT_PAREN.exec(s);if(m){s+=this._additionalDirSelectors(m[2],m[3],'');}
+return s;},this).join(COMPLEX_SELECTOR_SEP);},SCOPE_NAME:'style-scope'};var SCOPE_NAME=api.SCOPE_NAME;var SCOPE_DOC_SELECTOR=':not(['+SCOPE_NAME+'])'+':not(.'+SCOPE_NAME+')';var COMPLEX_SELECTOR_SEP=',';var SIMPLE_SELECTOR_SEP=/(^|[\s>+~]+)((?:\[.+?\]|[^\s>+~=\[])+)/g;var SIMPLE_SELECTOR_PREFIX=/[[.:#*]/;var HOST=':host';var ROOT=':root';var HOST_PAREN=/(:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/;var HOST_CONTEXT=':host-context';var HOST_CONTEXT_PAREN=/(.*)(?::host-context)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))(.*)/;var CONTENT='::content';var SCOPE_JUMP=/::content|::shadow|\/deep\//;var CSS_CLASS_PREFIX='.';var CSS_ATTR_PREFIX='['+SCOPE_NAME+'~=';var CSS_ATTR_SUFFIX=']';var PSEUDO_PREFIX=':';var CLASS='class';var CONTENT_START=new RegExp('^('+CONTENT+')');var SELECTOR_NO_MATCH='should_not_match';var SLOTTED_PAREN=/(?:::slotted)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g;var HOST_OR_HOST_GT_STAR=/:host(?:\s*>\s*\*)?/;var DIR_PAREN=/(.*):dir\((ltr|rtl)\)/;var DIR_REPLACE=':host-context([dir="$2"]) $1';var HOST_DIR=/:host\(:dir\((rtl|ltr)\)\)/g;var HOST_DIR_REPLACE=':host-context([dir="$1"])';return api;}();Polymer.StyleExtends=function(){var styleUtil=Polymer.StyleUtil;return{hasExtends:function(cssText){return Boolean(cssText.match(this.rx.EXTEND));},transform:function(style){var rules=styleUtil.rulesForStyle(style);var self=this;styleUtil.forEachRule(rules,function(rule){self._mapRuleOntoParent(rule);if(rule.parent){var m;while(m=self.rx.EXTEND.exec(rule.cssText)){var extend=m[1];var extendor=self._findExtendor(extend,rule);if(extendor){self._extendRule(rule,extendor);}}}
+rule.cssText=rule.cssText.replace(self.rx.EXTEND,'');});return styleUtil.toCssText(rules,function(rule){if(rule.selector.match(self.rx.STRIP)){rule.cssText='';}},true);},_mapRuleOntoParent:function(rule){if(rule.parent){var map=rule.parent.map||(rule.parent.map={});var parts=rule.selector.split(',');for(var i=0,p;i<parts.length;i++){p=parts[i];map[p.trim()]=rule;}
+return map;}},_findExtendor:function(extend,rule){return rule.parent&&rule.parent.map&&rule.parent.map[extend]||this._findExtendor(extend,rule.parent);},_extendRule:function(target,source){if(target.parent!==source.parent){this._cloneAndAddRuleToParent(source,target.parent);}
+target.extends=target.extends||[];target.extends.push(source);source.selector=source.selector.replace(this.rx.STRIP,'');source.selector=(source.selector&&source.selector+',\n')+target.selector;if(source.extends){source.extends.forEach(function(e){this._extendRule(target,e);},this);}},_cloneAndAddRuleToParent:function(rule,parent){rule=Object.create(rule);rule.parent=parent;if(rule.extends){rule.extends=rule.extends.slice();}
+parent.rules.push(rule);},rx:{EXTEND:/@extends\(([^)]*)\)\s*?;/gim,STRIP:/%[^,]*$/}};}();Polymer.ApplyShim=function(){'use strict';var styleUtil=Polymer.StyleUtil;var MIXIN_MATCH=styleUtil.rx.MIXIN_MATCH;var VAR_ASSIGN=styleUtil.rx.VAR_ASSIGN;var BAD_VAR=/var\(\s*(--[^,]*),\s*(--[^)]*)\)/g;var APPLY_NAME_CLEAN=/;\s*/m;var INITIAL_INHERIT=/^\s*(initial)|(inherit)\s*$/;var MIXIN_VAR_SEP='_-_';var mixinMap={};function mapSet(name,props){name=name.trim();mixinMap[name]={properties:props,dependants:{}};}
+function mapGet(name){name=name.trim();return mixinMap[name];}
+function replaceInitialOrInherit(property,value){var match=INITIAL_INHERIT.exec(value);if(match){if(match[1]){value=ApplyShim._getInitialValueForProperty(property);}else{value='apply-shim-inherit';}}
+return value;}
+function cssTextToMap(text){var props=text.split(';');var property,value;var out={};for(var i=0,p,sp;i<props.length;i++){p=props[i];if(p){sp=p.split(':');if(sp.length>1){property=sp[0].trim();value=replaceInitialOrInherit(property,sp.slice(1).join(':'));out[property]=value;}}}
+return out;}
+function invalidateMixinEntry(mixinEntry){var currentProto=ApplyShim.__currentElementProto;var currentElementName=currentProto&&currentProto.is;for(var elementName in mixinEntry.dependants){if(elementName!==currentElementName){mixinEntry.dependants[elementName].__applyShimInvalid=true;}}}
+function produceCssProperties(matchText,propertyName,valueProperty,valueMixin){if(valueProperty){styleUtil.processVariableAndFallback(valueProperty,function(prefix,value){if(value&&mapGet(value)){valueMixin='@apply '+value+';';}});}
+if(!valueMixin){return matchText;}
+var mixinAsProperties=consumeCssProperties(valueMixin);var prefix=matchText.slice(0,matchText.indexOf('--'));var mixinValues=cssTextToMap(mixinAsProperties);var combinedProps=mixinValues;var mixinEntry=mapGet(propertyName);var oldProps=mixinEntry&&mixinEntry.properties;if(oldProps){combinedProps=Object.create(oldProps);combinedProps=Polymer.Base.mixin(combinedProps,mixinValues);}else{mapSet(propertyName,combinedProps);}
+var out=[];var p,v;var needToInvalidate=false;for(p in combinedProps){v=mixinValues[p];if(v===undefined){v='initial';}
+if(oldProps&&!(p in oldProps)){needToInvalidate=true;}
+out.push(propertyName+MIXIN_VAR_SEP+p+': '+v);}
+if(needToInvalidate){invalidateMixinEntry(mixinEntry);}
+if(mixinEntry){mixinEntry.properties=combinedProps;}
+if(valueProperty){prefix=matchText+';'+prefix;}
+return prefix+out.join('; ')+';';}
+function fixVars(matchText,varA,varB){return'var('+varA+','+'var('+varB+'))';}
+function atApplyToCssProperties(mixinName,fallbacks){mixinName=mixinName.replace(APPLY_NAME_CLEAN,'');var vars=[];var mixinEntry=mapGet(mixinName);if(!mixinEntry){mapSet(mixinName,{});mixinEntry=mapGet(mixinName);}
+if(mixinEntry){var currentProto=ApplyShim.__currentElementProto;if(currentProto){mixinEntry.dependants[currentProto.is]=currentProto;}
+var p,parts,f;for(p in mixinEntry.properties){f=fallbacks&&fallbacks[p];parts=[p,': var(',mixinName,MIXIN_VAR_SEP,p];if(f){parts.push(',',f);}
+parts.push(')');vars.push(parts.join(''));}}
+return vars.join('; ');}
+function consumeCssProperties(text){var m;while(m=MIXIN_MATCH.exec(text)){var matchText=m[0];var mixinName=m[1];var idx=m.index;var applyPos=idx+matchText.indexOf('@apply');var afterApplyPos=idx+matchText.length;var textBeforeApply=text.slice(0,applyPos);var textAfterApply=text.slice(afterApplyPos);var defaults=cssTextToMap(textBeforeApply);var replacement=atApplyToCssProperties(mixinName,defaults);text=[textBeforeApply,replacement,textAfterApply].join('');MIXIN_MATCH.lastIndex=idx+replacement.length;}
+return text;}
+var ApplyShim={_measureElement:null,_map:mixinMap,_separator:MIXIN_VAR_SEP,transform:function(styles,elementProto){this.__currentElementProto=elementProto;styleUtil.forRulesInStyles(styles,this._boundFindDefinitions);styleUtil.forRulesInStyles(styles,this._boundFindApplications);if(elementProto){elementProto.__applyShimInvalid=false;}
+this.__currentElementProto=null;},_findDefinitions:function(rule){var cssText=rule.parsedCssText;cssText=cssText.replace(BAD_VAR,fixVars);cssText=cssText.replace(VAR_ASSIGN,produceCssProperties);rule.cssText=cssText;if(rule.selector===':root'){rule.selector=':host > *';}},_findApplications:function(rule){rule.cssText=consumeCssProperties(rule.cssText);},transformRule:function(rule){this._findDefinitions(rule);this._findApplications(rule);},_getInitialValueForProperty:function(property){if(!this._measureElement){this._measureElement=document.createElement('meta');this._measureElement.style.all='initial';document.head.appendChild(this._measureElement);}
+return window.getComputedStyle(this._measureElement).getPropertyValue(property);}};ApplyShim._boundTransformRule=ApplyShim.transformRule.bind(ApplyShim);ApplyShim._boundFindDefinitions=ApplyShim._findDefinitions.bind(ApplyShim);ApplyShim._boundFindApplications=ApplyShim._findApplications.bind(ApplyShim);return ApplyShim;}();(function(){var prepElement=Polymer.Base._prepElement;var nativeShadow=Polymer.Settings.useNativeShadow;var styleUtil=Polymer.StyleUtil;var styleTransformer=Polymer.StyleTransformer;var styleExtends=Polymer.StyleExtends;var applyShim=Polymer.ApplyShim;var settings=Polymer.Settings;Polymer.Base._addFeature({_prepElement:function(element){if(this._encapsulateStyle&&this.__cssBuild!=='shady'){styleTransformer.element(element,this.is,this._scopeCssViaAttr);}
+prepElement.call(this,element);},_prepStyles:function(){if(this._encapsulateStyle===undefined){this._encapsulateStyle=!nativeShadow;}
+if(!nativeShadow){this._scopeStyle=styleUtil.applyStylePlaceHolder(this.is);}
+this.__cssBuild=styleUtil.cssBuildTypeForModule(this.is);},_prepShimStyles:function(){if(this._template){var hasTargetedCssBuild=styleUtil.isTargetedBuild(this.__cssBuild);if(settings.useNativeCSSProperties&&this.__cssBuild==='shadow'&&hasTargetedCssBuild){if(settings.preserveStyleIncludes){styleUtil.styleIncludesToTemplate(this._template);}
+return;}
+this._styles=this._styles||this._collectStyles();if(settings.useNativeCSSProperties&&!this.__cssBuild){applyShim.transform(this._styles,this);}
+var cssText=settings.useNativeCSSProperties&&hasTargetedCssBuild?this._styles.length&&this._styles[0].textContent.trim():styleTransformer.elementStyles(this);this._prepStyleProperties();if(!this._needsStyleProperties()&&cssText){styleUtil.applyCss(cssText,this.is,nativeShadow?this._template.content:null,this._scopeStyle);}}else{this._styles=[];}},_collectStyles:function(){var styles=[];var cssText='',m$=this.styleModules;if(m$){for(var i=0,l=m$.length,m;i<l&&(m=m$[i]);i++){cssText+=styleUtil.cssFromModule(m);}}
+cssText+=styleUtil.cssFromModule(this.is);var p=this._template&&this._template.parentNode;if(this._template&&(!p||p.id.toLowerCase()!==this.is)){cssText+=styleUtil.cssFromElement(this._template);}
+if(cssText){var style=document.createElement('style');style.textContent=cssText;if(styleExtends.hasExtends(style.textContent)){cssText=styleExtends.transform(style);}
+styles.push(style);}
+return styles;},_elementAdd:function(node){if(this._encapsulateStyle){if(node.__styleScoped){node.__styleScoped=false;}else{styleTransformer.dom(node,this.is,this._scopeCssViaAttr);}}},_elementRemove:function(node){if(this._encapsulateStyle){styleTransformer.dom(node,this.is,this._scopeCssViaAttr,true);}},scopeSubtree:function(container,shouldObserve){if(nativeShadow){return;}
+var self=this;var scopify=function(node){if(node.nodeType===Node.ELEMENT_NODE){var className=node.getAttribute('class');node.setAttribute('class',self._scopeElementClass(node,className));var n$=node.querySelectorAll('*');for(var i=0,n;i<n$.length&&(n=n$[i]);i++){className=n.getAttribute('class');n.setAttribute('class',self._scopeElementClass(n,className));}}};scopify(container);if(shouldObserve){var mo=new MutationObserver(function(mxns){for(var i=0,m;i<mxns.length&&(m=mxns[i]);i++){if(m.addedNodes){for(var j=0;j<m.addedNodes.length;j++){scopify(m.addedNodes[j]);}}}});mo.observe(container,{childList:true,subtree:true});return mo;}}});}());Polymer.StyleProperties=function(){'use strict';var matchesSelector=Polymer.DomApi.matchesSelector;var styleUtil=Polymer.StyleUtil;var styleTransformer=Polymer.StyleTransformer;var IS_IE=navigator.userAgent.match('Trident');var settings=Polymer.Settings;return{decorateStyles:function(styles,scope){var self=this,props={},keyframes=[],ruleIndex=0;var scopeSelector=styleTransformer._calcHostScope(scope.is,scope.extends);styleUtil.forRulesInStyles(styles,function(rule,style){self.decorateRule(rule);rule.index=ruleIndex++;self.whenHostOrRootRule(scope,rule,style,function(info){if(rule.parent.type===styleUtil.ruleTypes.MEDIA_RULE){scope.__notStyleScopeCacheable=true;}
+if(info.isHost){var hostContextOrFunction=info.selector.split(' ').some(function(s){return s.indexOf(scopeSelector)===0&&s.length!==scopeSelector.length;});scope.__notStyleScopeCacheable=scope.__notStyleScopeCacheable||hostContextOrFunction;}});self.collectPropertiesInCssText(rule.propertyInfo.cssText,props);},function onKeyframesRule(rule){keyframes.push(rule);});styles._keyframes=keyframes;var names=[];for(var i in props){names.push(i);}
+return names;},decorateRule:function(rule){if(rule.propertyInfo){return rule.propertyInfo;}
+var info={},properties={};var hasProperties=this.collectProperties(rule,properties);if(hasProperties){info.properties=properties;rule.rules=null;}
+info.cssText=this.collectCssText(rule);rule.propertyInfo=info;return info;},collectProperties:function(rule,properties){var info=rule.propertyInfo;if(info){if(info.properties){Polymer.Base.mixin(properties,info.properties);return true;}}else{var m,rx=this.rx.VAR_ASSIGN;var cssText=rule.parsedCssText;var value;var any;while(m=rx.exec(cssText)){value=(m[2]||m[3]).trim();if(value!=='inherit'){properties[m[1].trim()]=value;}
+any=true;}
+return any;}},collectCssText:function(rule){return this.collectConsumingCssText(rule.parsedCssText);},collectConsumingCssText:function(cssText){return cssText.replace(this.rx.BRACKETED,'').replace(this.rx.VAR_ASSIGN,'');},collectPropertiesInCssText:function(cssText,props){var m;while(m=this.rx.VAR_CONSUMED.exec(cssText)){var name=m[1];if(m[2]!==':'){props[name]=true;}}},reify:function(props){var names=Object.getOwnPropertyNames(props);for(var i=0,n;i<names.length;i++){n=names[i];props[n]=this.valueForProperty(props[n],props);}},valueForProperty:function(property,props){if(property){if(property.indexOf(';')>=0){property=this.valueForProperties(property,props);}else{var self=this;var fn=function(prefix,value,fallback,suffix){var propertyValue=self.valueForProperty(props[value],props);if(!propertyValue||propertyValue==='initial'){propertyValue=self.valueForProperty(props[fallback]||fallback,props)||fallback;}else if(propertyValue==='apply-shim-inherit'){propertyValue='inherit';}
+return prefix+(propertyValue||'')+suffix;};property=styleUtil.processVariableAndFallback(property,fn);}}
+return property&&property.trim()||'';},valueForProperties:function(property,props){var parts=property.split(';');for(var i=0,p,m;i<parts.length;i++){if(p=parts[i]){this.rx.MIXIN_MATCH.lastIndex=0;m=this.rx.MIXIN_MATCH.exec(p);if(m){p=this.valueForProperty(props[m[1]],props);}else{var colon=p.indexOf(':');if(colon!==-1){var pp=p.substring(colon);pp=pp.trim();pp=this.valueForProperty(pp,props)||pp;p=p.substring(0,colon)+pp;}}
+parts[i]=p&&p.lastIndexOf(';')===p.length-1?p.slice(0,-1):p||'';}}
+return parts.join(';');},applyProperties:function(rule,props){var output='';if(!rule.propertyInfo){this.decorateRule(rule);}
+if(rule.propertyInfo.cssText){output=this.valueForProperties(rule.propertyInfo.cssText,props);}
+rule.cssText=output;},applyKeyframeTransforms:function(rule,keyframeTransforms){var input=rule.cssText;var output=rule.cssText;if(rule.hasAnimations==null){rule.hasAnimations=this.rx.ANIMATION_MATCH.test(input);}
+if(rule.hasAnimations){var transform;if(rule.keyframeNamesToTransform==null){rule.keyframeNamesToTransform=[];for(var keyframe in keyframeTransforms){transform=keyframeTransforms[keyframe];output=transform(input);if(input!==output){input=output;rule.keyframeNamesToTransform.push(keyframe);}}}else{for(var i=0;i<rule.keyframeNamesToTransform.length;++i){transform=keyframeTransforms[rule.keyframeNamesToTransform[i]];input=transform(input);}
+output=input;}}
+rule.cssText=output;},propertyDataFromStyles:function(styles,element){var props={},self=this;var o=[];styleUtil.forActiveRulesInStyles(styles,function(rule){if(!rule.propertyInfo){self.decorateRule(rule);}
+var selectorToMatch=rule.transformedSelector||rule.parsedSelector;if(element&&rule.propertyInfo.properties&&selectorToMatch){if(matchesSelector.call(element,selectorToMatch)){self.collectProperties(rule,props);addToBitMask(rule.index,o);}}});return{properties:props,key:o};},_rootSelector:/:root|:host\s*>\s*\*/,_checkRoot:function(hostScope,selector){return Boolean(selector.match(this._rootSelector))||hostScope==='html'&&selector.indexOf('html')>-1;},whenHostOrRootRule:function(scope,rule,style,callback){if(!rule.propertyInfo){self.decorateRule(rule);}
+if(!rule.propertyInfo.properties){return;}
+var hostScope=scope.is?styleTransformer._calcHostScope(scope.is,scope.extends):'html';var parsedSelector=rule.parsedSelector;var isRoot=this._checkRoot(hostScope,parsedSelector);var isHost=!isRoot&&parsedSelector.indexOf(':host')===0;var cssBuild=scope.__cssBuild||style.__cssBuild;if(cssBuild==='shady'){isRoot=parsedSelector===hostScope+' > *.'+hostScope||parsedSelector.indexOf('html')>-1;isHost=!isRoot&&parsedSelector.indexOf(hostScope)===0;}
+if(!isRoot&&!isHost){return;}
+var selectorToMatch=hostScope;if(isHost){if(settings.useNativeShadow&&!rule.transformedSelector){rule.transformedSelector=styleTransformer._transformRuleCss(rule,styleTransformer._transformComplexSelector,scope.is,hostScope);}
+selectorToMatch=rule.transformedSelector||rule.parsedSelector;}
+if(isRoot&&hostScope==='html'){selectorToMatch=rule.transformedSelector||rule.parsedSelector;}
+callback({selector:selectorToMatch,isHost:isHost,isRoot:isRoot});},hostAndRootPropertiesForScope:function(scope){var hostProps={},rootProps={},self=this;styleUtil.forActiveRulesInStyles(scope._styles,function(rule,style){self.whenHostOrRootRule(scope,rule,style,function(info){var element=scope._element||scope;if(matchesSelector.call(element,info.selector)){if(info.isHost){self.collectProperties(rule,hostProps);}else{self.collectProperties(rule,rootProps);}}});});return{rootProps:rootProps,hostProps:hostProps};},transformStyles:function(element,properties,scopeSelector){var self=this;var hostSelector=styleTransformer._calcHostScope(element.is,element.extends);var rxHostSelector=element.extends?'\\'+hostSelector.slice(0,-1)+'\\]':hostSelector;var hostRx=new RegExp(this.rx.HOST_PREFIX+rxHostSelector+this.rx.HOST_SUFFIX);var keyframeTransforms=this._elementKeyframeTransforms(element,scopeSelector);return styleTransformer.elementStyles(element,function(rule){self.applyProperties(rule,properties);if(!settings.useNativeShadow&&!Polymer.StyleUtil.isKeyframesSelector(rule)&&rule.cssText){self.applyKeyframeTransforms(rule,keyframeTransforms);self._scopeSelector(rule,hostRx,hostSelector,element._scopeCssViaAttr,scopeSelector);}});},_elementKeyframeTransforms:function(element,scopeSelector){var keyframesRules=element._styles._keyframes;var keyframeTransforms={};if(!settings.useNativeShadow&&keyframesRules){for(var i=0,keyframesRule=keyframesRules[i];i<keyframesRules.length;keyframesRule=keyframesRules[++i]){this._scopeKeyframes(keyframesRule,scopeSelector);keyframeTransforms[keyframesRule.keyframesName]=this._keyframesRuleTransformer(keyframesRule);}}
+return keyframeTransforms;},_keyframesRuleTransformer:function(keyframesRule){return function(cssText){return cssText.replace(keyframesRule.keyframesNameRx,keyframesRule.transformedKeyframesName);};},_scopeKeyframes:function(rule,scopeId){rule.keyframesNameRx=new RegExp('\\b'+rule.keyframesName+'(?!\\B|-)','g');rule.transformedKeyframesName=rule.keyframesName+'-'+scopeId;rule.transformedSelector=rule.transformedSelector||rule.selector;rule.selector=rule.transformedSelector.replace(rule.keyframesName,rule.transformedKeyframesName);},_hasDirOrHostContext:function(parsedSelector){return/:host-context|:dir/.test(parsedSelector);},_scopeSelector:function(rule,hostRx,hostSelector,viaAttr,scopeId){rule.transformedSelector=rule.transformedSelector||rule.selector;var selector=rule.transformedSelector;var scope=styleTransformer._calcElementScope(scopeId,viaAttr);var hostScope=styleTransformer._calcElementScope(hostSelector,viaAttr);var parts=selector.split(',');var isDirOrHostContextSelector=this._hasDirOrHostContext(rule.parsedSelector);for(var i=0,l=parts.length,p;i<l&&(p=parts[i]);i++){parts[i]=p.match(hostRx)?p.replace(hostSelector,scope):isDirOrHostContextSelector?p.replace(hostScope,scope+' '+hostScope):scope+' '+p;}
+rule.selector=parts.join(',');},applyElementScopeSelector:function(element,selector,old,viaAttr){var c=viaAttr?element.getAttribute(styleTransformer.SCOPE_NAME):element.getAttribute('class')||'';var v=old?c.replace(old,selector):(c?c+' ':'')+this.XSCOPE_NAME+' '+selector;if(c!==v){if(viaAttr){element.setAttribute(styleTransformer.SCOPE_NAME,v);}else{element.setAttribute('class',v);}}},applyElementStyle:function(element,properties,selector,style){var cssText=style?style.textContent||'':this.transformStyles(element,properties,selector);var s=element._customStyle;if(s&&!settings.useNativeShadow&&s!==style){s._useCount--;if(s._useCount<=0&&s.parentNode){s.parentNode.removeChild(s);}}
+if(settings.useNativeShadow){if(element._customStyle){element._customStyle.textContent=cssText;style=element._customStyle;}else if(cssText){style=styleUtil.applyCss(cssText,selector,element.root,element._scopeStyle);}}else{if(!style){if(cssText){style=styleUtil.applyCss(cssText,selector,null,element._scopeStyle);}}else if(!style.parentNode){if(IS_IE&&cssText.indexOf('@media')>-1){style.textContent=cssText;}
+styleUtil.applyStyle(style,null,element._scopeStyle);}}
+if(style){style._useCount=style._useCount||0;if(element._customStyle!=style){style._useCount++;}
+element._customStyle=style;}
+return style;},mixinCustomStyle:function(props,customStyle){var v;for(var i in customStyle){v=customStyle[i];if(v||v===0){props[i]=v;}}},updateNativeStyleProperties:function(element,properties){var oldPropertyNames=element.__customStyleProperties;if(oldPropertyNames){for(var i=0;i<oldPropertyNames.length;i++){element.style.removeProperty(oldPropertyNames[i]);}}
+var propertyNames=[];for(var p in properties){if(properties[p]!==null){element.style.setProperty(p,properties[p]);propertyNames.push(p);}}
+element.__customStyleProperties=propertyNames;},rx:styleUtil.rx,XSCOPE_NAME:'x-scope'};function addToBitMask(n,bits){var o=parseInt(n/32);var v=1<<n%32;bits[o]=(bits[o]||0)|v;}}();(function(){Polymer.StyleCache=function(){this.cache={};};Polymer.StyleCache.prototype={MAX:100,store:function(is,data,keyValues,keyStyles){data.keyValues=keyValues;data.styles=keyStyles;var s$=this.cache[is]=this.cache[is]||[];s$.push(data);if(s$.length>this.MAX){s$.shift();}},retrieve:function(is,keyValues,keyStyles){var cache=this.cache[is];if(cache){for(var i=cache.length-1,data;i>=0;i--){data=cache[i];if(keyStyles===data.styles&&this._objectsEqual(keyValues,data.keyValues)){return data;}}}},clear:function(){this.cache={};},_objectsEqual:function(target,source){var t,s;for(var i in target){t=target[i],s=source[i];if(!(typeof t==='object'&&t?this._objectsStrictlyEqual(t,s):t===s)){return false;}}
+if(Array.isArray(target)){return target.length===source.length;}
+return true;},_objectsStrictlyEqual:function(target,source){return this._objectsEqual(target,source)&&this._objectsEqual(source,target);}};}());Polymer.StyleDefaults=function(){var styleProperties=Polymer.StyleProperties;var StyleCache=Polymer.StyleCache;var nativeVariables=Polymer.Settings.useNativeCSSProperties;var api={_styles:[],_properties:null,customStyle:{},_styleCache:new StyleCache(),_element:Polymer.DomApi.wrap(document.documentElement),addStyle:function(style){this._styles.push(style);this._properties=null;},get _styleProperties(){if(!this._properties){styleProperties.decorateStyles(this._styles,this);this._styles._scopeStyleProperties=null;this._properties=styleProperties.hostAndRootPropertiesForScope(this).rootProps;styleProperties.mixinCustomStyle(this._properties,this.customStyle);styleProperties.reify(this._properties);}
+return this._properties;},hasStyleProperties:function(){return Boolean(this._properties);},_needsStyleProperties:function(){},_computeStyleProperties:function(){return this._styleProperties;},updateStyles:function(properties){this._properties=null;if(properties){Polymer.Base.mixin(this.customStyle,properties);}
+this._styleCache.clear();for(var i=0,s;i<this._styles.length;i++){s=this._styles[i];s=s.__importElement||s;s._apply();}
+if(nativeVariables){styleProperties.updateNativeStyleProperties(document.documentElement,this.customStyle);}}};return api;}();(function(){'use strict';var serializeValueToAttribute=Polymer.Base.serializeValueToAttribute;var propertyUtils=Polymer.StyleProperties;var styleTransformer=Polymer.StyleTransformer;var styleDefaults=Polymer.StyleDefaults;var nativeShadow=Polymer.Settings.useNativeShadow;var nativeVariables=Polymer.Settings.useNativeCSSProperties;Polymer.Base._addFeature({_prepStyleProperties:function(){if(!nativeVariables){this._ownStylePropertyNames=this._styles&&this._styles.length?propertyUtils.decorateStyles(this._styles,this):null;}},customStyle:null,getComputedStyleValue:function(property){if(!nativeVariables&&!this._styleProperties){this._computeStyleProperties();}
+return!nativeVariables&&this._styleProperties&&this._styleProperties[property]||getComputedStyle(this).getPropertyValue(property);},_setupStyleProperties:function(){this.customStyle={};this._styleCache=null;this._styleProperties=null;this._scopeSelector=null;this._ownStyleProperties=null;this._customStyle=null;},_needsStyleProperties:function(){return Boolean(!nativeVariables&&this._ownStylePropertyNames&&this._ownStylePropertyNames.length);},_validateApplyShim:function(){if(this.__applyShimInvalid){Polymer.ApplyShim.transform(this._styles,this.__proto__);var cssText=styleTransformer.elementStyles(this);if(nativeShadow){var templateStyle=this._template.content.querySelector('style');if(templateStyle){templateStyle.textContent=cssText;}}else{var shadyStyle=this._scopeStyle&&this._scopeStyle.nextSibling;if(shadyStyle){shadyStyle.textContent=cssText;}}}},_beforeAttached:function(){if((!this._scopeSelector||this.__stylePropertiesInvalid)&&this._needsStyleProperties()){this.__stylePropertiesInvalid=false;this._updateStyleProperties();}},_findStyleHost:function(){var e=this,root;while(root=Polymer.dom(e).getOwnerRoot()){if(Polymer.isInstance(root.host)){return root.host;}
+e=root.host;}
+return styleDefaults;},_updateStyleProperties:function(){var info,scope=this._findStyleHost();if(!scope._styleProperties){scope._computeStyleProperties();}
+if(!scope._styleCache){scope._styleCache=new Polymer.StyleCache();}
+var scopeData=propertyUtils.propertyDataFromStyles(scope._styles,this);var scopeCacheable=!this.__notStyleScopeCacheable;if(scopeCacheable){scopeData.key.customStyle=this.customStyle;info=scope._styleCache.retrieve(this.is,scopeData.key,this._styles);}
+var scopeCached=Boolean(info);if(scopeCached){this._styleProperties=info._styleProperties;}else{this._computeStyleProperties(scopeData.properties);}
+this._computeOwnStyleProperties();if(!scopeCached){info=styleCache.retrieve(this.is,this._ownStyleProperties,this._styles);}
+var globalCached=Boolean(info)&&!scopeCached;var style=this._applyStyleProperties(info);if(!scopeCached){style=style&&nativeShadow?style.cloneNode(true):style;info={style:style,_scopeSelector:this._scopeSelector,_styleProperties:this._styleProperties};if(scopeCacheable){scopeData.key.customStyle={};this.mixin(scopeData.key.customStyle,this.customStyle);scope._styleCache.store(this.is,info,scopeData.key,this._styles);}
+if(!globalCached){styleCache.store(this.is,Object.create(info),this._ownStyleProperties,this._styles);}}},_computeStyleProperties:function(scopeProps){var scope=this._findStyleHost();if(!scope._styleProperties){scope._computeStyleProperties();}
+var props=Object.create(scope._styleProperties);var hostAndRootProps=propertyUtils.hostAndRootPropertiesForScope(this);this.mixin(props,hostAndRootProps.hostProps);scopeProps=scopeProps||propertyUtils.propertyDataFromStyles(scope._styles,this).properties;this.mixin(props,scopeProps);this.mixin(props,hostAndRootProps.rootProps);propertyUtils.mixinCustomStyle(props,this.customStyle);propertyUtils.reify(props);this._styleProperties=props;},_computeOwnStyleProperties:function(){var props={};for(var i=0,n;i<this._ownStylePropertyNames.length;i++){n=this._ownStylePropertyNames[i];props[n]=this._styleProperties[n];}
+this._ownStyleProperties=props;},_scopeCount:0,_applyStyleProperties:function(info){var oldScopeSelector=this._scopeSelector;this._scopeSelector=info?info._scopeSelector:this.is+'-'+this.__proto__._scopeCount++;var style=propertyUtils.applyElementStyle(this,this._styleProperties,this._scopeSelector,info&&info.style);if(!nativeShadow){propertyUtils.applyElementScopeSelector(this,this._scopeSelector,oldScopeSelector,this._scopeCssViaAttr);}
+return style;},serializeValueToAttribute:function(value,attribute,node){node=node||this;if(attribute==='class'&&!nativeShadow){var host=node===this?this.domHost||this.dataHost:this;if(host){value=host._scopeElementClass(node,value);}}
+node=this.shadyRoot&&this.shadyRoot._hasDistributed?Polymer.dom(node):node;serializeValueToAttribute.call(this,value,attribute,node);},_scopeElementClass:function(element,selector){if(!nativeShadow&&!this._scopeCssViaAttr){selector=(selector?selector+' ':'')+SCOPE_NAME+' '+this.is+(element._scopeSelector?' '+XSCOPE_NAME+' '+element._scopeSelector:'');}
+return selector;},updateStyles:function(properties){if(properties){this.mixin(this.customStyle,properties);}
+if(nativeVariables){propertyUtils.updateNativeStyleProperties(this,this.customStyle);}else{if(this.isAttached){if(this._needsStyleProperties()){this._updateStyleProperties();}else{this._styleProperties=null;}}else{this.__stylePropertiesInvalid=true;}
+if(this._styleCache){this._styleCache.clear();}
+this._updateRootStyles();}},_updateRootStyles:function(root){root=root||this.root;var c$=Polymer.dom(root)._query(function(e){return e.shadyRoot||e.shadowRoot;});for(var i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){if(c.updateStyles){c.updateStyles();}}}});Polymer.updateStyles=function(properties){styleDefaults.updateStyles(properties);Polymer.Base._updateRootStyles(document);};var styleCache=new Polymer.StyleCache();Polymer.customStyleCache=styleCache;var SCOPE_NAME=styleTransformer.SCOPE_NAME;var XSCOPE_NAME=propertyUtils.XSCOPE_NAME;}());Polymer.Base._addFeature({_registerFeatures:function(){this._prepIs();if(this.factoryImpl){this._prepConstructor();}
+this._prepStyles();},_finishRegisterFeatures:function(){this._prepTemplate();this._prepShimStyles();this._prepAnnotations();this._prepEffects();this._prepBehaviors();this._prepPropertyInfo();this._prepBindings();this._prepShady();},_prepBehavior:function(b){this._addPropertyEffects(b.properties);this._addComplexObserverEffects(b.observers);this._addHostAttributes(b.hostAttributes);},_initFeatures:function(){this._setupGestures();this._setupConfigure(this.__data__);this._setupStyleProperties();this._setupDebouncers();this._setupShady();this._registerHost();if(this._template){this._validateApplyShim();this._poolContent();this._beginHosting();this._stampTemplate();this._endHosting();this._marshalAnnotationReferences();}
+this._marshalInstanceEffects();this._marshalBehaviors();this._marshalHostAttributes();this._marshalAttributes();this._tryReady();},_marshalBehavior:function(b){if(b.listeners){this._listenListeners(b.listeners);}}});(function(){var propertyUtils=Polymer.StyleProperties;var styleUtil=Polymer.StyleUtil;var cssParse=Polymer.CssParse;var styleDefaults=Polymer.StyleDefaults;var styleTransformer=Polymer.StyleTransformer;var applyShim=Polymer.ApplyShim;var debounce=Polymer.Debounce;var settings=Polymer.Settings;var updateDebouncer;Polymer({is:'custom-style',extends:'style',_template:null,properties:{include:String},ready:function(){this.__appliedElement=this.__appliedElement||this;this.__cssBuild=styleUtil.getCssBuildType(this);if(this.__appliedElement!==this){this.__appliedElement.__cssBuild=this.__cssBuild;}
+if(this.ownerDocument!==window.document&&this.__appliedElement===this){document.head.appendChild(this);}
+this._tryApply();},attached:function(){this._tryApply();},_tryApply:function(){if(!this._appliesToDocument){if(this.parentNode&&this.parentNode.localName!=='dom-module'){this._appliesToDocument=true;var e=this.__appliedElement;if(!settings.useNativeCSSProperties){this.__needsUpdateStyles=styleDefaults.hasStyleProperties();styleDefaults.addStyle(e);}
+if(e.textContent||this.include){this._apply(true);}else{var self=this;var observer=new MutationObserver(function(){observer.disconnect();self._apply(true);});observer.observe(e,{childList:true});}}}},_updateStyles:function(){Polymer.updateStyles();},_apply:function(initialApply){var e=this.__appliedElement;if(this.include){e.textContent=styleUtil.cssFromModules(this.include,true)+e.textContent;}
+if(!e.textContent){return;}
+var buildType=this.__cssBuild;var targetedBuild=styleUtil.isTargetedBuild(buildType);if(settings.useNativeCSSProperties&&targetedBuild){return;}
+var styleRules=styleUtil.rulesForStyle(e);if(!targetedBuild){styleUtil.forEachRule(styleRules,function(rule){styleTransformer.documentRule(rule);});if(settings.useNativeCSSProperties&&!buildType){applyShim.transform([e]);}}
+if(settings.useNativeCSSProperties){e.textContent=styleUtil.toCssText(styleRules);}else{var self=this;var fn=function fn(){self._flushCustomProperties();};if(initialApply){Polymer.RenderStatus.whenReady(fn);}else{fn();}}},_flushCustomProperties:function(){if(this.__needsUpdateStyles){this.__needsUpdateStyles=false;updateDebouncer=debounce(updateDebouncer,this._updateStyles);}else{this._applyCustomProperties();}},_applyCustomProperties:function(){var element=this.__appliedElement;this._computeStyleProperties();var props=this._styleProperties;var rules=styleUtil.rulesForStyle(element);if(!rules){return;}
+element.textContent=styleUtil.toCssText(rules,function(rule){var css=rule.cssText=rule.parsedCssText;if(rule.propertyInfo&&rule.propertyInfo.cssText){css=cssParse.removeCustomPropAssignment(css);rule.cssText=propertyUtils.valueForProperties(css,props);}});}});}());Polymer.Templatizer={properties:{__hideTemplateChildren__:{observer:'_showHideChildren'}},_instanceProps:Polymer.nob,_parentPropPrefix:'_parent_',templatize:function(template){this._templatized=template;if(!template._content){template._content=template.content;}
+if(template._content._ctor){this.ctor=template._content._ctor;this._prepParentProperties(this.ctor.prototype,template);return;}
+var archetype=Object.create(Polymer.Base);this._customPrepAnnotations(archetype,template);this._prepParentProperties(archetype,template);archetype._prepEffects();this._customPrepEffects(archetype);archetype._prepBehaviors();archetype._prepPropertyInfo();archetype._prepBindings();archetype._notifyPathUp=this._notifyPathUpImpl;archetype._scopeElementClass=this._scopeElementClassImpl;archetype.listen=this._listenImpl;archetype._showHideChildren=this._showHideChildrenImpl;archetype.__setPropertyOrig=this.__setProperty;archetype.__setProperty=this.__setPropertyImpl;var _constructor=this._constructorImpl;var ctor=function TemplateInstance(model,host){_constructor.call(this,model,host);};ctor.prototype=archetype;archetype.constructor=ctor;template._content._ctor=ctor;this.ctor=ctor;},_getRootDataHost:function(){return this.dataHost&&this.dataHost._rootDataHost||this.dataHost;},_showHideChildrenImpl:function(hide){var c=this._children;for(var i=0;i<c.length;i++){var n=c[i];if(Boolean(hide)!=Boolean(n.__hideTemplateChildren__)){if(n.nodeType===Node.TEXT_NODE){if(hide){n.__polymerTextContent__=n.textContent;n.textContent='';}else{n.textContent=n.__polymerTextContent__;}}else if(n.style){if(hide){n.__polymerDisplay__=n.style.display;n.style.display='none';}else{n.style.display=n.__polymerDisplay__;}}}
+n.__hideTemplateChildren__=hide;}},__setPropertyImpl:function(property,value,fromAbove,node){if(node&&node.__hideTemplateChildren__&&property=='textContent'){property='__polymerTextContent__';}
+this.__setPropertyOrig(property,value,fromAbove,node);},_debounceTemplate:function(fn){Polymer.dom.addDebouncer(this.debounce('_debounceTemplate',fn));},_flushTemplates:function(){Polymer.dom.flush();},_customPrepEffects:function(archetype){var parentProps=archetype._parentProps;for(var prop in parentProps){archetype._addPropertyEffect(prop,'function',this._createHostPropEffector(prop));}
+for(prop in this._instanceProps){archetype._addPropertyEffect(prop,'function',this._createInstancePropEffector(prop));}},_customPrepAnnotations:function(archetype,template){var t=archetype._template=document.createElement('template');var c=t._content=template._content;if(!c._notes){var rootDataHost=archetype._rootDataHost;if(rootDataHost){Polymer.Annotations.prepElement=function(){rootDataHost._prepElement();};}
+c._notes=Polymer.Annotations.parseAnnotations(template);Polymer.Annotations.prepElement=null;this._processAnnotations(c._notes);}
+archetype._notes=c._notes;archetype._parentProps=c._parentProps;},_prepParentProperties:function(archetype,template){var parentProps=this._parentProps=archetype._parentProps;if(this._forwardParentProp&&parentProps){var proto=archetype._parentPropProto;var prop;if(!proto){for(prop in this._instanceProps){delete parentProps[prop];}
+proto=archetype._parentPropProto=Object.create(null);if(template!=this){Polymer.Bind.prepareModel(proto);Polymer.Base.prepareModelNotifyPath(proto);}
+for(prop in parentProps){var parentProp=this._parentPropPrefix+prop;var effects=[{kind:'function',effect:this._createForwardPropEffector(prop),fn:Polymer.Bind._functionEffect},{kind:'notify',fn:Polymer.Bind._notifyEffect,effect:{event:Polymer.CaseMap.camelToDashCase(parentProp)+'-changed'}}];proto._propertyEffects=proto._propertyEffects||{};proto._propertyEffects[parentProp]=effects;Polymer.Bind._createAccessors(proto,parentProp,effects);}}
+var self=this;if(template!=this){Polymer.Bind.prepareInstance(template);template._forwardParentProp=function(source,value){self._forwardParentProp(source,value);};}
+this._extendTemplate(template,proto);template._pathEffector=function(path,value,fromAbove){return self._pathEffectorImpl(path,value,fromAbove);};}},_createForwardPropEffector:function(prop){return function(source,value){this._forwardParentProp(prop,value);};},_createHostPropEffector:function(prop){var prefix=this._parentPropPrefix;return function(source,value){this.dataHost._templatized[prefix+prop]=value;};},_createInstancePropEffector:function(prop){return function(source,value,old,fromAbove){if(!fromAbove){this.dataHost._forwardInstanceProp(this,prop,value);}};},_extendTemplate:function(template,proto){var n$=Object.getOwnPropertyNames(proto);if(proto._propertySetter){template._propertySetter=proto._propertySetter;}
+for(var i=0,n;i<n$.length&&(n=n$[i]);i++){var val=template[n];if(val&&n=='_propertyEffects'){var pe=Polymer.Base.mixin({},val);template._propertyEffects=Polymer.Base.mixin(pe,proto._propertyEffects);}else{var pd=Object.getOwnPropertyDescriptor(proto,n);Object.defineProperty(template,n,pd);if(val!==undefined){template._propertySetter(n,val);}}}},_showHideChildren:function(hidden){},_forwardInstancePath:function(inst,path,value){},_forwardInstanceProp:function(inst,prop,value){},_notifyPathUpImpl:function(path,value){var dataHost=this.dataHost;var root=Polymer.Path.root(path);dataHost._forwardInstancePath.call(dataHost,this,path,value);if(root in dataHost._parentProps){dataHost._templatized._notifyPath(dataHost._parentPropPrefix+path,value);}},_pathEffectorImpl:function(path,value,fromAbove){if(this._forwardParentPath){if(path.indexOf(this._parentPropPrefix)===0){var subPath=path.substring(this._parentPropPrefix.length);var model=Polymer.Path.root(subPath);if(model in this._parentProps){this._forwardParentPath(subPath,value);}}}
+Polymer.Base._pathEffector.call(this._templatized,path,value,fromAbove);},_constructorImpl:function(model,host){this._rootDataHost=host._getRootDataHost();this._setupConfigure(model);this._registerHost(host);this._beginHosting();this.root=this.instanceTemplate(this._template);this.root.__noContent=!this._notes._hasContent;this.root.__styleScoped=true;this._endHosting();this._marshalAnnotatedNodes();this._marshalInstanceEffects();this._marshalAnnotatedListeners();var children=[];for(var n=this.root.firstChild;n;n=n.nextSibling){children.push(n);n._templateInstance=this;}
+this._children=children;if(host.__hideTemplateChildren__){this._showHideChildren(true);}
+this._tryReady();},_listenImpl:function(node,eventName,methodName){var model=this;var host=this._rootDataHost;var handler=host._createEventHandler(node,eventName,methodName);var decorated=function(e){e.model=model;handler(e);};host._listen(node,eventName,decorated);},_scopeElementClassImpl:function(node,value){var host=this._rootDataHost;if(host){return host._scopeElementClass(node,value);}
+return value;},stamp:function(model){model=model||{};if(this._parentProps){var templatized=this._templatized;for(var prop in this._parentProps){if(model[prop]===undefined){model[prop]=templatized[this._parentPropPrefix+prop];}}}
+return new this.ctor(model,this);},modelForElement:function(el){var model;while(el){if(model=el._templateInstance){if(model.dataHost!=this){el=model.dataHost;}else{return model;}}else{el=el.parentNode;}}}};Polymer({is:'dom-template',extends:'template',_template:null,behaviors:[Polymer.Templatizer],ready:function(){this.templatize(this);}});Polymer._collections=new WeakMap();Polymer.Collection=function(userArray){Polymer._collections.set(userArray,this);this.userArray=userArray;this.store=userArray.slice();this.initMap();};Polymer.Collection.prototype={constructor:Polymer.Collection,initMap:function(){var omap=this.omap=new WeakMap();var pmap=this.pmap={};var s=this.store;for(var i=0;i<s.length;i++){var item=s[i];if(item&&typeof item=='object'){omap.set(item,i);}else{pmap[item]=i;}}},add:function(item){var key=this.store.push(item)-1;if(item&&typeof item=='object'){this.omap.set(item,key);}else{this.pmap[item]=key;}
+return'#'+key;},removeKey:function(key){if(key=this._parseKey(key)){this._removeFromMap(this.store[key]);delete this.store[key];}},_removeFromMap:function(item){if(item&&typeof item=='object'){this.omap.delete(item);}else{delete this.pmap[item];}},remove:function(item){var key=this.getKey(item);this.removeKey(key);return key;},getKey:function(item){var key;if(item&&typeof item=='object'){key=this.omap.get(item);}else{key=this.pmap[item];}
+if(key!=undefined){return'#'+key;}},getKeys:function(){return Object.keys(this.store).map(function(key){return'#'+key;});},_parseKey:function(key){if(key&&key[0]=='#'){return key.slice(1);}},setItem:function(key,item){if(key=this._parseKey(key)){var old=this.store[key];if(old){this._removeFromMap(old);}
+if(item&&typeof item=='object'){this.omap.set(item,key);}else{this.pmap[item]=key;}
+this.store[key]=item;}},getItem:function(key){if(key=this._parseKey(key)){return this.store[key];}},getItems:function(){var items=[],store=this.store;for(var key in store){items.push(store[key]);}
+return items;},_applySplices:function(splices){var keyMap={},key;for(var i=0,s;i<splices.length&&(s=splices[i]);i++){s.addedKeys=[];for(var j=0;j<s.removed.length;j++){key=this.getKey(s.removed[j]);keyMap[key]=keyMap[key]?null:-1;}
+for(j=0;j<s.addedCount;j++){var item=this.userArray[s.index+j];key=this.getKey(item);key=key===undefined?this.add(item):key;keyMap[key]=keyMap[key]?null:1;s.addedKeys.push(key);}}
+var removed=[];var added=[];for(key in keyMap){if(keyMap[key]<0){this.removeKey(key);removed.push(key);}
+if(keyMap[key]>0){added.push(key);}}
+return[{removed:removed,added:added}];}};Polymer.Collection.get=function(userArray){return Polymer._collections.get(userArray)||new Polymer.Collection(userArray);};Polymer.Collection.applySplices=function(userArray,splices){var coll=Polymer._collections.get(userArray);return coll?coll._applySplices(splices):null;};Polymer({is:'dom-repeat',extends:'template',_template:null,properties:{items:{type:Array},as:{type:String,value:'item'},indexAs:{type:String,value:'index'},sort:{type:Function,observer:'_sortChanged'},filter:{type:Function,observer:'_filterChanged'},observe:{type:String,observer:'_observeChanged'},delay:Number,renderedItemCount:{type:Number,notify:!Polymer.Settings.suppressTemplateNotifications,readOnly:true},initialCount:{type:Number,observer:'_initializeChunking'},targetFramerate:{type:Number,value:20},notifyDomChange:{type:Boolean},_targetFrameTime:{type:Number,computed:'_computeFrameTime(targetFramerate)'}},behaviors:[Polymer.Templatizer],observers:['_itemsChanged(items.*)'],created:function(){this._instances=[];this._pool=[];this._limit=Infinity;var self=this;this._boundRenderChunk=function(){self._renderChunk();};},detached:function(){this.__isDetached=true;for(var i=0;i<this._instances.length;i++){this._detachInstance(i);}},attached:function(){if(this.__isDetached){this.__isDetached=false;var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;}
+var parent=Polymer.dom(parentNode);for(var i=0;i<this._instances.length;i++){this._attachInstance(i,parent,refNode);}}},ready:function(){this._instanceProps={__key__:true};this._instanceProps[this.as]=true;this._instanceProps[this.indexAs]=true;if(!this.ctor){this.templatize(this);}},_sortChanged:function(sort){var dataHost=this._getRootDataHost();this._sortFn=sort&&(typeof sort=='function'?sort:function(){return dataHost[sort].apply(dataHost,arguments);});this._needFullRefresh=true;if(this.items){this._debounceTemplate(this._render);}},_filterChanged:function(filter){var dataHost=this._getRootDataHost();this._filterFn=filter&&(typeof filter=='function'?filter:function(){return dataHost[filter].apply(dataHost,arguments);});this._needFullRefresh=true;if(this.items){this._debounceTemplate(this._render);}},_computeFrameTime:function(rate){return Math.ceil(1000/rate);},_initializeChunking:function(){if(this.initialCount){this._limit=this.initialCount;this._chunkCount=this.initialCount;this._lastChunkTime=performance.now();}},_tryRenderChunk:function(){if(this.items&&this._limit<this.items.length){this.debounce('renderChunk',this._requestRenderChunk);}},_requestRenderChunk:function(){requestAnimationFrame(this._boundRenderChunk);},_renderChunk:function(){var currChunkTime=performance.now();var ratio=this._targetFrameTime/(currChunkTime-this._lastChunkTime);this._chunkCount=Math.round(this._chunkCount*ratio)||1;this._limit+=this._chunkCount;this._lastChunkTime=currChunkTime;this._debounceTemplate(this._render);},_observeChanged:function(){this._observePaths=this.observe&&this.observe.replace('.*','.').split(' ');},_itemsChanged:function(change){if(change.path=='items'){if(Array.isArray(this.items)){this.collection=Polymer.Collection.get(this.items);}else if(!this.items){this.collection=null;}else{this._error(this._logf('dom-repeat','expected array for `items`,'+' found',this.items));}
+this._keySplices=[];this._indexSplices=[];this._needFullRefresh=true;this._initializeChunking();this._debounceTemplate(this._render);}else if(change.path=='items.splices'){this._keySplices=this._keySplices.concat(change.value.keySplices);this._indexSplices=this._indexSplices.concat(change.value.indexSplices);this._debounceTemplate(this._render);}else{var subpath=change.path.slice(6);this._forwardItemPath(subpath,change.value);this._checkObservedPaths(subpath);}},_checkObservedPaths:function(path){if(this._observePaths){path=path.substring(path.indexOf('.')+1);var paths=this._observePaths;for(var i=0;i<paths.length;i++){if(path.indexOf(paths[i])===0){this._needFullRefresh=true;if(this.delay){this.debounce('render',this._render,this.delay);}else{this._debounceTemplate(this._render);}
+return;}}}},render:function(){this._needFullRefresh=true;this._debounceTemplate(this._render);this._flushTemplates();},_render:function(){if(this._needFullRefresh){this._applyFullRefresh();this._needFullRefresh=false;}else if(this._keySplices.length){if(this._sortFn){this._applySplicesUserSort(this._keySplices);}else{if(this._filterFn){this._applyFullRefresh();}else{this._applySplicesArrayOrder(this._indexSplices);}}}else{}
+this._keySplices=[];this._indexSplices=[];var keyToIdx=this._keyToInstIdx={};for(var i=this._instances.length-1;i>=0;i--){var inst=this._instances[i];if(inst.isPlaceholder&&i<this._limit){inst=this._insertInstance(i,inst.__key__);}else if(!inst.isPlaceholder&&i>=this._limit){inst=this._downgradeInstance(i,inst.__key__);}
+keyToIdx[inst.__key__]=i;if(!inst.isPlaceholder){inst.__setProperty(this.indexAs,i,true);}}
+this._pool.length=0;this._setRenderedItemCount(this._instances.length);if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}
+this._tryRenderChunk();},_applyFullRefresh:function(){var c=this.collection;var keys;if(this._sortFn){keys=c?c.getKeys():[];}else{keys=[];var items=this.items;if(items){for(var i=0;i<items.length;i++){keys.push(c.getKey(items[i]));}}}
+var self=this;if(this._filterFn){keys=keys.filter(function(a){return self._filterFn(c.getItem(a));});}
+if(this._sortFn){keys.sort(function(a,b){return self._sortFn(c.getItem(a),c.getItem(b));});}
+for(i=0;i<keys.length;i++){var key=keys[i];var inst=this._instances[i];if(inst){inst.__key__=key;if(!inst.isPlaceholder&&i<this._limit){inst.__setProperty(this.as,c.getItem(key),true);}}else if(i<this._limit){this._insertInstance(i,key);}else{this._insertPlaceholder(i,key);}}
+for(var j=this._instances.length-1;j>=i;j--){this._detachAndRemoveInstance(j);}},_numericSort:function(a,b){return a-b;},_applySplicesUserSort:function(splices){var c=this.collection;var keyMap={};var key;for(var i=0,s;i<splices.length&&(s=splices[i]);i++){for(var j=0;j<s.removed.length;j++){key=s.removed[j];keyMap[key]=keyMap[key]?null:-1;}
+for(j=0;j<s.added.length;j++){key=s.added[j];keyMap[key]=keyMap[key]?null:1;}}
+var removedIdxs=[];var addedKeys=[];for(key in keyMap){if(keyMap[key]===-1){removedIdxs.push(this._keyToInstIdx[key]);}
+if(keyMap[key]===1){addedKeys.push(key);}}
+if(removedIdxs.length){removedIdxs.sort(this._numericSort);for(i=removedIdxs.length-1;i>=0;i--){var idx=removedIdxs[i];if(idx!==undefined){this._detachAndRemoveInstance(idx);}}}
+var self=this;if(addedKeys.length){if(this._filterFn){addedKeys=addedKeys.filter(function(a){return self._filterFn(c.getItem(a));});}
+addedKeys.sort(function(a,b){return self._sortFn(c.getItem(a),c.getItem(b));});var start=0;for(i=0;i<addedKeys.length;i++){start=this._insertRowUserSort(start,addedKeys[i]);}}},_insertRowUserSort:function(start,key){var c=this.collection;var item=c.getItem(key);var end=this._instances.length-1;var idx=-1;while(start<=end){var mid=start+end>>1;var midKey=this._instances[mid].__key__;var cmp=this._sortFn(c.getItem(midKey),item);if(cmp<0){start=mid+1;}else if(cmp>0){end=mid-1;}else{idx=mid;break;}}
+if(idx<0){idx=end+1;}
+this._insertPlaceholder(idx,key);return idx;},_applySplicesArrayOrder:function(splices){for(var i=0,s;i<splices.length&&(s=splices[i]);i++){for(var j=0;j<s.removed.length;j++){this._detachAndRemoveInstance(s.index);}
+for(j=0;j<s.addedKeys.length;j++){this._insertPlaceholder(s.index+j,s.addedKeys[j]);}}},_detachInstance:function(idx){var inst=this._instances[idx];if(!inst.isPlaceholder){for(var i=0;i<inst._children.length;i++){var el=inst._children[i];Polymer.dom(inst.root).appendChild(el);}
+return inst;}},_attachInstance:function(idx,parent,refNode){var inst=this._instances[idx];if(!inst.isPlaceholder){parent.insertBefore(inst.root,refNode);}},_detachAndRemoveInstance:function(idx){var inst=this._detachInstance(idx);if(inst){this._pool.push(inst);}
+this._instances.splice(idx,1);},_insertPlaceholder:function(idx,key){this._instances.splice(idx,0,{isPlaceholder:true,__key__:key});},_stampInstance:function(idx,key){var model={__key__:key};model[this.as]=this.collection.getItem(key);model[this.indexAs]=idx;return this.stamp(model);},_insertInstance:function(idx,key){var inst=this._pool.pop();if(inst){inst.__setProperty(this.as,this.collection.getItem(key),true);inst.__setProperty('__key__',key,true);}else{inst=this._stampInstance(idx,key);}
+var beforeRow=this._instances[idx+1];var beforeNode=beforeRow&&!beforeRow.isPlaceholder?beforeRow._children[0]:this;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){if(beforeNode==this){beforeNode=parentNode;}
+parentNode=Polymer.dom(parentNode).parentNode;}
+Polymer.dom(parentNode).insertBefore(inst.root,beforeNode);this._instances[idx]=inst;return inst;},_downgradeInstance:function(idx,key){var inst=this._detachInstance(idx);if(inst){this._pool.push(inst);}
+inst={isPlaceholder:true,__key__:key};this._instances[idx]=inst;return inst;},_showHideChildren:function(hidden){for(var i=0;i<this._instances.length;i++){if(!this._instances[i].isPlaceholder)
+this._instances[i]._showHideChildren(hidden);}},_forwardInstanceProp:function(inst,prop,value){if(prop==this.as){var idx;if(this._sortFn||this._filterFn){idx=this.items.indexOf(this.collection.getItem(inst.__key__));}else{idx=inst[this.indexAs];}
+this.set('items.'+idx,value);}},_forwardInstancePath:function(inst,path,value){if(path.indexOf(this.as+'.')===0){this._notifyPath('items.'+inst.__key__+'.'+path.slice(this.as.length+1),value);}},_forwardParentProp:function(prop,value){var i$=this._instances;for(var i=0,inst;i<i$.length&&(inst=i$[i]);i++){if(!inst.isPlaceholder){inst.__setProperty(prop,value,true);}}},_forwardParentPath:function(path,value){var i$=this._instances;for(var i=0,inst;i<i$.length&&(inst=i$[i]);i++){if(!inst.isPlaceholder){inst._notifyPath(path,value,true);}}},_forwardItemPath:function(path,value){if(this._keyToInstIdx){var dot=path.indexOf('.');var key=path.substring(0,dot<0?path.length:dot);var idx=this._keyToInstIdx[key];var inst=this._instances[idx];if(inst&&!inst.isPlaceholder){if(dot>=0){path=this.as+'.'+path.substring(dot+1);inst._notifyPath(path,value,true);}else{inst.__setProperty(this.as,value,true);}}}},itemForElement:function(el){var instance=this.modelForElement(el);return instance&&instance[this.as];},keyForElement:function(el){var instance=this.modelForElement(el);return instance&&instance.__key__;},indexForElement:function(el){var instance=this.modelForElement(el);return instance&&instance[this.indexAs];}});Polymer({is:'array-selector',_template:null,properties:{items:{type:Array,observer:'clearSelection'},multi:{type:Boolean,value:false,observer:'clearSelection'},selected:{type:Object,notify:true},selectedItem:{type:Object,notify:true},toggle:{type:Boolean,value:false}},clearSelection:function(){if(Array.isArray(this.selected)){for(var i=0;i<this.selected.length;i++){this.unlinkPaths('selected.'+i);}}else{this.unlinkPaths('selected');this.unlinkPaths('selectedItem');}
+if(this.multi){if(!this.selected||this.selected.length){this.selected=[];this._selectedColl=Polymer.Collection.get(this.selected);}}else{this.selected=null;this._selectedColl=null;}
+this.selectedItem=null;},isSelected:function(item){if(this.multi){return this._selectedColl.getKey(item)!==undefined;}else{return this.selected==item;}},deselect:function(item){if(this.multi){if(this.isSelected(item)){var skey=this._selectedColl.getKey(item);this.arrayDelete('selected',item);this.unlinkPaths('selected.'+skey);}}else{this.selected=null;this.selectedItem=null;this.unlinkPaths('selected');this.unlinkPaths('selectedItem');}},select:function(item){var icol=Polymer.Collection.get(this.items);var key=icol.getKey(item);if(this.multi){if(this.isSelected(item)){if(this.toggle){this.deselect(item);}}else{this.push('selected',item);var skey=this._selectedColl.getKey(item);this.linkPaths('selected.'+skey,'items.'+key);}}else{if(this.toggle&&item==this.selected){this.deselect();}else{this.selected=item;this.selectedItem=item;this.linkPaths('selected','items.'+key);this.linkPaths('selectedItem','items.'+key);}}}});Polymer({is:'dom-if',extends:'template',_template:null,properties:{'if':{type:Boolean,value:false,observer:'_queueRender'},restamp:{type:Boolean,value:false,observer:'_queueRender'},notifyDomChange:{type:Boolean}},behaviors:[Polymer.Templatizer],_queueRender:function(){this._debounceTemplate(this._render);},detached:function(){var parentNode=this.parentNode;if(parentNode&&parentNode.localName==this.is){parentNode=Polymer.dom(parentNode).parentNode;}
+if(!parentNode||parentNode.nodeType==Node.DOCUMENT_FRAGMENT_NODE&&(!Polymer.Settings.hasShadow||!(parentNode instanceof ShadowRoot))){this._teardownInstance();}},attached:function(){if(this.if&&this.ctor){this.async(this._ensureInstance);}},render:function(){this._flushTemplates();},_render:function(){if(this.if){if(!this.ctor){this.templatize(this);}
+this._ensureInstance();this._showHideChildren();}else if(this.restamp){this._teardownInstance();}
+if(!this.restamp&&this._instance){this._showHideChildren();}
+if(this.if!=this._lastIf){if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}
+this._lastIf=this.if;}},_ensureInstance:function(){var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode&&parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;}
+if(parentNode){if(!this._instance){this._instance=this.stamp();var root=this._instance.root;Polymer.dom(parentNode).insertBefore(root,refNode);}else{var c$=this._instance._children;if(c$&&c$.length){var lastChild=Polymer.dom(refNode).previousSibling;if(lastChild!==c$[c$.length-1]){for(var i=0,n;i<c$.length&&(n=c$[i]);i++){Polymer.dom(parentNode).insertBefore(n,refNode);}}}}}},_teardownInstance:function(){if(this._instance){var c$=this._instance._children;if(c$&&c$.length){var parent=Polymer.dom(Polymer.dom(c$[0]).parentNode);for(var i=0,n;i<c$.length&&(n=c$[i]);i++){parent.removeChild(n);}}
+this._instance=null;}},_showHideChildren:function(){var hidden=this.__hideTemplateChildren__||!this.if;if(this._instance){this._instance._showHideChildren(hidden);}},_forwardParentProp:function(prop,value){if(this._instance){this._instance.__setProperty(prop,value,true);}},_forwardParentPath:function(path,value){if(this._instance){this._instance._notifyPath(path,value,true);}}});Polymer({is:'dom-bind',properties:{notifyDomChange:{type:Boolean}},extends:'template',_template:null,created:function(){var self=this;Polymer.RenderStatus.whenReady(function(){if(document.readyState=='loading'){document.addEventListener('DOMContentLoaded',function(){self._markImportsReady();});}else{self._markImportsReady();}});},_ensureReady:function(){if(!this._readied){this._readySelf();}},_markImportsReady:function(){this._importsReady=true;this._ensureReady();},_registerFeatures:function(){this._prepConstructor();},_insertChildren:function(){var refNode;var parentNode=Polymer.dom(this).parentNode;if(parentNode.localName==this.is){refNode=parentNode;parentNode=Polymer.dom(parentNode).parentNode;}else{refNode=this;}
+Polymer.dom(parentNode).insertBefore(this.root,refNode);},_removeChildren:function(){if(this._children){for(var i=0;i<this._children.length;i++){this.root.appendChild(this._children[i]);}}},_initFeatures:function(){},_scopeElementClass:function(element,selector){if(this.dataHost){return this.dataHost._scopeElementClass(element,selector);}else{return selector;}},_configureInstanceProperties:function(){},_prepConfigure:function(){var config={};for(var prop in this._propertyEffects){config[prop]=this[prop];}
+var setupConfigure=this._setupConfigure;this._setupConfigure=function(){setupConfigure.call(this,config);};},attached:function(){if(this._importsReady){this.render();}},detached:function(){this._removeChildren();},render:function(){this._ensureReady();if(!this._children){this._template=this;this._prepAnnotations();this._prepEffects();this._prepBehaviors();this._prepConfigure();this._prepBindings();this._prepPropertyInfo();Polymer.Base._initFeatures.call(this);this._children=Polymer.TreeApi.arrayCopyChildNodes(this.root);}
+this._insertChildren();if(!Polymer.Settings.suppressTemplateNotifications||this.notifyDomChange){this.fire('dom-change');}}});'use strict';if(!window.CustomElements||window.CustomElements.hasNative){if(!Polymer.Settings.useNativeShadow){tr.showPanic('Polymer error','base should use native shadow when possible.');}}'use strict';const global=this.window||this.global;this.tr=(function(){if(global.tr)return global.tr;function exportPath(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{cur=cur[part]={};}}
+return cur;}
+function isExported(name){const parts=name.split('.');let cur=global;for(let part;parts.length&&(part=parts.shift());){if(part in cur){cur=cur[part];}else{return false;}}
+return true;}
+function isDefined(name){const parts=name.split('.');let curObject=global;for(let i=0;i<parts.length;i++){const partName=parts[i];const nextObject=curObject[partName];if(nextObject===undefined)return false;curObject=nextObject;}
+return true;}
+let panicElement=undefined;const rawPanicMessages=[];function showPanicElementIfNeeded(){if(panicElement)return;const panicOverlay=document.createElement('div');panicOverlay.style.backgroundColor='white';panicOverlay.style.border='3px solid red';panicOverlay.style.boxSizing='border-box';panicOverlay.style.color='black';panicOverlay.style.display='flex';panicOverlay.style.height='100%';panicOverlay.style.left=0;panicOverlay.style.padding='8px';panicOverlay.style.position='fixed';panicOverlay.style.top=0;panicOverlay.style.webkitFlexDirection='column';panicOverlay.style.width='100%';panicElement=document.createElement('div');panicElement.style.webkitFlex='1 1 auto';panicElement.style.overflow='auto';panicOverlay.appendChild(panicElement);if(!document.body){setTimeout(function(){document.body.appendChild(panicOverlay);},150);}else{document.body.appendChild(panicOverlay);}}
+function showPanic(panicTitle,panicDetails){if(tr.isHeadless){if(panicDetails instanceof Error)throw panicDetails;throw new Error('Panic: '+panicTitle+':\n'+panicDetails);}
+if(panicDetails instanceof Error){panicDetails=panicDetails.stack;}
+showPanicElementIfNeeded();const panicMessageEl=document.createElement('div');panicMessageEl.innerHTML='<h2 id="message"></h2>'+'<pre id="details"></pre>';panicMessageEl.querySelector('#message').textContent=panicTitle;panicMessageEl.querySelector('#details').textContent=panicDetails;panicElement.appendChild(panicMessageEl);rawPanicMessages.push({title:panicTitle,details:panicDetails});}
+function hasPanic(){return rawPanicMessages.length!==0;}
+function getPanicText(){return rawPanicMessages.map(function(msg){return msg.title;}).join(', ');}
+function exportTo(namespace,fn){const obj=exportPath(namespace);const exports=fn();for(const propertyName in exports){const propertyDescriptor=Object.getOwnPropertyDescriptor(exports,propertyName);if(propertyDescriptor){Object.defineProperty(obj,propertyName,propertyDescriptor);}}}
+function initialize(){if(global.isVinn){tr.isVinn=true;}else if(global.process&&global.process.versions.node){tr.isNode=true;}else{tr.isVinn=false;tr.isNode=false;tr.doc=document;tr.isMac=/Mac/.test(navigator.platform);tr.isWindows=/Win/.test(navigator.platform);tr.isChromeOS=/CrOS/.test(navigator.userAgent);tr.isLinux=/Linux/.test(navigator.userAgent);}
+tr.isHeadless=tr.isVinn||tr.isNode;}
+return{initialize,exportTo,isExported,isDefined,showPanic,hasPanic,getPanicText,};})();tr.initialize();'use strict';tr.exportTo('tr.b',function(){function EventTarget(){}
+EventTarget.decorate=function(target){for(const k in EventTarget.prototype){if(k==='decorate')continue;const v=EventTarget.prototype[k];if(typeof v!=='function')continue;target[k]=v;}};EventTarget.prototype={addEventListener(type,handler){if(!this.listeners_){this.listeners_=Object.create(null);}
+if(!(type in this.listeners_)){this.listeners_[type]=[handler];}else{const handlers=this.listeners_[type];if(handlers.indexOf(handler)<0){handlers.push(handler);}}},removeEventListener(type,handler){if(!this.listeners_)return;if(type in this.listeners_){const handlers=this.listeners_[type];const index=handlers.indexOf(handler);if(index>=0){if(handlers.length===1){delete this.listeners_[type];}else{handlers.splice(index,1);}}}},dispatchEvent(event){if(!this.listeners_)return true;event.__defineGetter__('target',()=>this);const realPreventDefault=event.preventDefault;event.preventDefault=function(){realPreventDefault.call(this);this.rawReturnValue=false;};const type=event.type;let prevented=0;if(type in this.listeners_){const handlers=this.listeners_[type].concat();for(let i=0,handler;handler=handlers[i];i++){if(handler.handleEvent){prevented|=handler.handleEvent.call(handler,event)===false;}else{prevented|=handler.call(this,event)===false;}}}
+return!prevented&&event.rawReturnValue;},async dispatchAsync(event){if(!this.listeners_)return true;const listeners=this.listeners_[event.type];if(listeners===undefined)return;await Promise.all(listeners.slice().map(listener=>{if(listener.handleEvent){return listener.handleEvent.call(listener,event);}
+return listener.call(this,event);}));},hasEventListener(type){return(this.listeners_!==undefined&&this.listeners_[type]!==undefined);}};return{EventTarget,};});'use strict';tr.exportTo('tr.b',function(){function RegisteredTypeInfo(constructor,metadata){this.constructor=constructor;this.metadata=metadata;}
+const BASIC_REGISTRY_MODE='BASIC_REGISTRY_MODE';const TYPE_BASED_REGISTRY_MODE='TYPE_BASED_REGISTRY_MODE';const ALL_MODES={BASIC_REGISTRY_MODE:true,TYPE_BASED_REGISTRY_MODE:true};function ExtensionRegistryOptions(mode){if(mode===undefined){throw new Error('Mode is required');}
+if(!ALL_MODES[mode]){throw new Error('Not a mode.');}
+this.mode_=mode;this.defaultMetadata_={};this.defaultConstructor_=undefined;this.defaultTypeInfo_=undefined;this.frozen_=false;}
+ExtensionRegistryOptions.prototype={freeze(){if(this.frozen_){throw new Error('Frozen');}
+this.frozen_=true;},get mode(){return this.mode_;},get defaultMetadata(){return this.defaultMetadata_;},set defaultMetadata(defaultMetadata){if(this.frozen_){throw new Error('Frozen');}
+this.defaultMetadata_=defaultMetadata;this.defaultTypeInfo_=undefined;},get defaultConstructor(){return this.defaultConstructor_;},set defaultConstructor(defaultConstructor){if(this.frozen_){throw new Error('Frozen');}
+this.defaultConstructor_=defaultConstructor;this.defaultTypeInfo_=undefined;},get defaultTypeInfo(){if(this.defaultTypeInfo_===undefined&&this.defaultConstructor_){this.defaultTypeInfo_=new RegisteredTypeInfo(this.defaultConstructor,this.defaultMetadata);}
+return this.defaultTypeInfo_;},validateConstructor(constructor){if(!this.mandatoryBaseClass)return;let curProto=constructor.prototype.__proto__;let ok=false;while(curProto){if(curProto===this.mandatoryBaseClass.prototype){ok=true;break;}
+curProto=curProto.__proto__;}
+if(!ok){throw new Error(constructor+'must be subclass of '+registry);}}};return{BASIC_REGISTRY_MODE,TYPE_BASED_REGISTRY_MODE,ExtensionRegistryOptions,RegisteredTypeInfo,};});'use strict';tr.exportTo('tr.b',function(){let Event;if(tr.isHeadless){function HeadlessEvent(type,opt_bubbles,opt_preventable){this.type=type;this.bubbles=(opt_bubbles!==undefined?!!opt_bubbles:false);this.cancelable=(opt_preventable!==undefined?!!opt_preventable:false);this.defaultPrevented=false;this.cancelBubble=false;}
+HeadlessEvent.prototype={preventDefault(){this.defaultPrevented=true;},stopPropagation(){this.cancelBubble=true;}};Event=HeadlessEvent;}else{function TrEvent(type,opt_bubbles,opt_preventable){const e=tr.doc.createEvent('Event');e.initEvent(type,!!opt_bubbles,!!opt_preventable);e.__proto__=global.Event.prototype;return e;}
+TrEvent.prototype={__proto__:global.Event.prototype};Event=TrEvent;}
+function dispatchSimpleEvent(target,type,opt_bubbles,opt_cancelable,opt_fields){const e=new tr.b.Event(type,opt_bubbles,opt_cancelable);Object.assign(e,opt_fields);return target.dispatchEvent(e);}
+async function dispatchSimpleEventAsync(target,type,opt_fields){const e=new tr.b.Event(type,false,false);Object.assign(e,opt_fields);return await target.dispatchAsync(e);}
+return{Event,dispatchSimpleEvent,dispatchSimpleEventAsync,};});'use strict';tr.exportTo('tr.b',function(){const RegisteredTypeInfo=tr.b.RegisteredTypeInfo;const ExtensionRegistryOptions=tr.b.ExtensionRegistryOptions;function decorateBasicExtensionRegistry(registry,extensionRegistryOptions){const savedStateStack=[];registry.registeredTypeInfos_=[];registry.register=function(constructor,opt_metadata){if(registry.findIndexOfRegisteredConstructor(constructor)!==undefined){throw new Error('Handler already registered for '+constructor);}
+extensionRegistryOptions.validateConstructor(constructor);const metadata={};for(const k in extensionRegistryOptions.defaultMetadata){metadata[k]=extensionRegistryOptions.defaultMetadata[k];}
+if(opt_metadata){for(const k in opt_metadata){metadata[k]=opt_metadata[k];}}
+const typeInfo=new RegisteredTypeInfo(constructor,metadata);let e=new tr.b.Event('will-register');e.typeInfo=typeInfo;registry.dispatchEvent(e);registry.registeredTypeInfos_.push(typeInfo);e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.pushCleanStateBeforeTest=function(){savedStateStack.push(registry.registeredTypeInfos_);registry.registeredTypeInfos_=[];const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.popCleanStateAfterTest=function(){registry.registeredTypeInfos_=savedStateStack[0];savedStateStack.splice(0,1);const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.findIndexOfRegisteredConstructor=function(constructor){for(let i=0;i<registry.registeredTypeInfos_.length;i++){if(registry.registeredTypeInfos_[i].constructor===constructor){return i;}}
+return undefined;};registry.unregister=function(constructor){const foundIndex=registry.findIndexOfRegisteredConstructor(constructor);if(foundIndex===undefined){throw new Error(constructor+' not registered');}
+registry.registeredTypeInfos_.splice(foundIndex,1);const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.getAllRegisteredTypeInfos=function(){return registry.registeredTypeInfos_;};registry.findTypeInfo=function(constructor){const foundIndex=this.findIndexOfRegisteredConstructor(constructor);if(foundIndex!==undefined){return this.registeredTypeInfos_[foundIndex];}
+return undefined;};registry.findTypeInfoMatching=function(predicate,opt_this){opt_this=opt_this?opt_this:undefined;for(let i=0;i<registry.registeredTypeInfos_.length;++i){const typeInfo=registry.registeredTypeInfos_[i];if(predicate.call(opt_this,typeInfo)){return typeInfo;}}
+return extensionRegistryOptions.defaultTypeInfo;};registry.findTypeInfoWithName=function(name){if(typeof(name)!=='string'){throw new Error('Name is not a string.');}
+const typeInfo=registry.findTypeInfoMatching(function(ti){return ti.constructor.name===name;});if(typeInfo)return typeInfo;return undefined;};}
+return{_decorateBasicExtensionRegistry:decorateBasicExtensionRegistry};});'use strict';tr.exportTo('tr.b',function(){const categoryPartsFor={};function getCategoryParts(category){let parts=categoryPartsFor[category];if(parts!==undefined)return parts;parts=category.split(',');categoryPartsFor[category]=parts;return parts;}
+return{getCategoryParts,};});'use strict';tr.exportTo('tr.b',function(){const getCategoryParts=tr.b.getCategoryParts;const RegisteredTypeInfo=tr.b.RegisteredTypeInfo;const ExtensionRegistryOptions=tr.b.ExtensionRegistryOptions;function decorateTypeBasedExtensionRegistry(registry,extensionRegistryOptions){const savedStateStack=[];registry.registeredTypeInfos_=[];registry.categoryPartToTypeInfoMap_=new Map();registry.typeNameToTypeInfoMap_=new Map();registry.register=function(constructor,metadata){extensionRegistryOptions.validateConstructor(constructor);const typeInfo=new RegisteredTypeInfo(constructor,metadata||extensionRegistryOptions.defaultMetadata);typeInfo.typeNames=[];typeInfo.categoryParts=[];if(metadata&&metadata.typeName){typeInfo.typeNames.push(metadata.typeName);}
+if(metadata&&metadata.typeNames){typeInfo.typeNames.push.apply(typeInfo.typeNames,metadata.typeNames);}
+if(metadata&&metadata.categoryParts){typeInfo.categoryParts.push.apply(typeInfo.categoryParts,metadata.categoryParts);}
+if(typeInfo.typeNames.length===0&&typeInfo.categoryParts.length===0){throw new Error('typeName or typeNames must be provided');}
+typeInfo.typeNames.forEach(function(typeName){if(registry.typeNameToTypeInfoMap_.has(typeName)){throw new Error('typeName '+typeName+' already registered');}});typeInfo.categoryParts.forEach(function(categoryPart){if(registry.categoryPartToTypeInfoMap_.has(categoryPart)){throw new Error('categoryPart '+categoryPart+' already registered');}});let e=new tr.b.Event('will-register');e.typeInfo=typeInfo;registry.dispatchEvent(e);typeInfo.typeNames.forEach(function(typeName){registry.typeNameToTypeInfoMap_.set(typeName,typeInfo);});typeInfo.categoryParts.forEach(function(categoryPart){registry.categoryPartToTypeInfoMap_.set(categoryPart,typeInfo);});registry.registeredTypeInfos_.push(typeInfo);e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.pushCleanStateBeforeTest=function(){savedStateStack.push({registeredTypeInfos:registry.registeredTypeInfos_,typeNameToTypeInfoMap:registry.typeNameToTypeInfoMap_,categoryPartToTypeInfoMap:registry.categoryPartToTypeInfoMap_});registry.registeredTypeInfos_=[];registry.typeNameToTypeInfoMap_=new Map();registry.categoryPartToTypeInfoMap_=new Map();const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.popCleanStateAfterTest=function(){const state=savedStateStack[0];savedStateStack.splice(0,1);registry.registeredTypeInfos_=state.registeredTypeInfos;registry.typeNameToTypeInfoMap_=state.typeNameToTypeInfoMap;registry.categoryPartToTypeInfoMap_=state.categoryPartToTypeInfoMap;const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.unregister=function(constructor){let typeInfoIndex=-1;for(let i=0;i<registry.registeredTypeInfos_.length;i++){if(registry.registeredTypeInfos_[i].constructor===constructor){typeInfoIndex=i;break;}}
+if(typeInfoIndex===-1){throw new Error(constructor+' not registered');}
+const typeInfo=registry.registeredTypeInfos_[typeInfoIndex];registry.registeredTypeInfos_.splice(typeInfoIndex,1);typeInfo.typeNames.forEach(function(typeName){registry.typeNameToTypeInfoMap_.delete(typeName);});typeInfo.categoryParts.forEach(function(categoryPart){registry.categoryPartToTypeInfoMap_.delete(categoryPart);});const e=new tr.b.Event('registry-changed');registry.dispatchEvent(e);};registry.getTypeInfo=function(category,typeName){if(category){const categoryParts=getCategoryParts(category);for(let i=0;i<categoryParts.length;i++){const categoryPart=categoryParts[i];const typeInfo=registry.categoryPartToTypeInfoMap_.get(categoryPart);if(typeInfo!==undefined)return typeInfo;}}
+const typeInfo=registry.typeNameToTypeInfoMap_.get(typeName);if(typeInfo!==undefined)return typeInfo;return extensionRegistryOptions.defaultTypeInfo;};registry.getConstructor=function(category,typeName){const typeInfo=registry.getTypeInfo(category,typeName);if(typeInfo)return typeInfo.constructor;return undefined;};}
+return{_decorateTypeBasedExtensionRegistry:decorateTypeBasedExtensionRegistry};});'use strict';tr.exportTo('tr.b',function(){const URL_REGEX=/^(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b|file:\/\/)([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;function deepCopy(value){if(!(value instanceof Object)){if(value===undefined||value===null)return value;if(typeof value==='string')return value.substring();if(typeof value==='boolean')return value;if(typeof value==='number')return value;throw new Error('Unrecognized: '+typeof value);}
+const object=value;if(object instanceof Array){const res=new Array(object.length);for(let i=0;i<object.length;i++){res[i]=deepCopy(object[i]);}
+return res;}
+if(object.__proto__!==Object.prototype){throw new Error('Can only clone simple types');}
+const res={};for(const key in object){res[key]=deepCopy(object[key]);}
+return res;}
+function normalizeException(e){if(e===undefined||e===null){return{typeName:'UndefinedError',message:'Unknown: null or undefined exception',stack:'Unknown'};}
+if(typeof(e)==='string'){return{typeName:'StringError',message:e,stack:[e]};}
+let typeName;if(e.name){typeName=e.name;}else if(e.constructor){if(e.constructor.name){typeName=e.constructor.name;}else{typeName='AnonymousError';}}else{typeName='ErrorWithNoConstructor';}
+const msg=e.message?e.message:'Unknown';return{typeName,message:msg,stack:e.stack?e.stack:[msg]};}
+function stackTraceAsString(){return new Error().stack+'';}
+function stackTrace(){let stack=stackTraceAsString();stack=stack.split('\n');return stack.slice(2);}
+function getUsingPath(path,fromDict){const parts=path.split('.');let cur=fromDict;for(let part;parts.length&&(part=parts.shift());){if(!parts.length){return cur[part];}else if(part in cur){cur=cur[part];}else{return undefined;}}
+return undefined;}
+function formatDate(date){return date.toISOString().replace('T',' ').slice(0,19);}
+function numberToJson(n){if(isNaN(n))return'NaN';if(n===Infinity)return'Infinity';if(n===-Infinity)return'-Infinity';return n;}
+function numberFromJson(n){if(n==='NaN'||n===null)return NaN;if(n==='Infinity')return Infinity;if(n==='-Infinity')return-Infinity;return n;}
+function runLengthEncoding(ary){const encodedArray=[];for(const element of ary){if(encodedArray.length===0||encodedArray[encodedArray.length-1].value!==element){encodedArray.push({value:element,count:1,});}else{encodedArray[encodedArray.length-1].count+=1;}}
+return encodedArray;}
+function isUrl(s){return typeof(s)==='string'&&s.match(URL_REGEX)!==null;}
+function getOnlyElement(iterable){const iterator=iterable[Symbol.iterator]();const firstIteration=iterator.next();if(firstIteration.done){throw new Error('getOnlyElement was passed an empty iterable.');}
+const secondIteration=iterator.next();if(!secondIteration.done){throw new Error('getOnlyElement was passed an iterable with multiple elements.');}
+return firstIteration.value;}
+function getFirstElement(iterable){const iterator=iterable[Symbol.iterator]();const result=iterator.next();if(result.done){throw new Error('getFirstElement was passed an empty iterable.');}
+return result.value;}
+function compareArrays(x,y,elementCmp){const minLength=Math.min(x.length,y.length);let i;for(i=0;i<minLength;i++){const tmp=elementCmp(x[i],y[i]);if(tmp)return tmp;}
+if(x.length===y.length)return 0;if(x[i]===undefined)return-1;return 1;}
+function groupIntoMap(ary,callback,opt_this,opt_arrayConstructor){const arrayConstructor=opt_arrayConstructor||Array;const results=new Map();for(const element of ary){const key=callback.call(opt_this,element);let items=results.get(key);if(items===undefined){items=new arrayConstructor();results.set(key,items);}
+items.push(element);}
+return results;}
+function inPlaceFilter(array,predicate,opt_this){opt_this=opt_this||this;let nextPosition=0;for(let i=0;i<array.length;i++){if(!predicate.call(opt_this,array[i],i))continue;if(nextPosition<i){array[nextPosition]=array[i];}
+nextPosition++;}
+if(nextPosition<array.length){array.length=nextPosition;}}
+function invertArrayOfDicts(array,opt_dictGetter,opt_this){opt_this=opt_this||this;const result={};for(let i=0;i<array.length;i++){const item=array[i];if(item===undefined)continue;const dict=opt_dictGetter?opt_dictGetter.call(opt_this,item):item;if(dict===undefined)continue;for(const key in dict){let valueList=result[key];if(valueList===undefined){result[key]=valueList=new Array(array.length);}
+valueList[i]=dict[key];}}
+return result;}
+function setsEqual(a,b){if(!(a instanceof Set)||!(b instanceof Set))return false;if(a.size!==b.size)return false;for(const x of a){if(!b.has(x))return false;}
+return true;}
+function findLowIndexInSortedArray(ary,mapFn,loVal){if(ary.length===0)return 1;let low=0;let high=ary.length-1;let i;let comparison;let hitPos=-1;while(low<=high){i=Math.floor((low+high)/2);comparison=mapFn(ary[i])-loVal;if(comparison<0){low=i+1;continue;}else if(comparison>0){high=i-1;continue;}else{hitPos=i;high=i-1;}}
+return hitPos!==-1?hitPos:low;}
+function findIndexInSortedIntervals(ary,mapLoFn,mapWidthFn,loVal){const first=findLowIndexInSortedArray(ary,mapLoFn,loVal);if(first===0){if(loVal>=mapLoFn(ary[0])&&loVal<mapLoFn(ary[0])+mapWidthFn(ary[0],0)){return 0;}
+return-1;}
+if(first<ary.length){if(loVal>=mapLoFn(ary[first])&&loVal<mapLoFn(ary[first])+mapWidthFn(ary[first],first)){return first;}
+if(loVal>=mapLoFn(ary[first-1])&&loVal<mapLoFn(ary[first-1])+
+mapWidthFn(ary[first-1],first-1)){return first-1;}
+return ary.length;}
+if(first===ary.length){if(loVal>=mapLoFn(ary[first-1])&&loVal<mapLoFn(ary[first-1])+
+mapWidthFn(ary[first-1],first-1)){return first-1;}
+return ary.length;}
+return ary.length;}
+function findIndexInSortedClosedIntervals(ary,mapLoFn,mapHiFn,val){const i=findLowIndexInSortedArray(ary,mapLoFn,val);if(i===0){if(val>=mapLoFn(ary[0],0)&&val<=mapHiFn(ary[0],0)){return 0;}
+return-1;}
+if(i<ary.length){if(val>=mapLoFn(ary[i-1],i-1)&&val<=mapHiFn(ary[i-1],i-1)){return i-1;}
+if(val>=mapLoFn(ary[i],i)&&val<=mapHiFn(ary[i],i)){return i;}
+return ary.length;}
+if(i===ary.length){if(val>=mapLoFn(ary[i-1],i-1)&&val<=mapHiFn(ary[i-1],i-1)){return i-1;}
+return ary.length;}
+return ary.length;}
+function iterateOverIntersectingIntervals(ary,mapLoFn,mapWidthFn,loVal,hiVal,cb){if(ary.length===0)return;if(loVal>hiVal)return;let i=findLowIndexInSortedArray(ary,mapLoFn,loVal);if(i===-1){return;}
+if(i>0){const hi=mapLoFn(ary[i-1])+mapWidthFn(ary[i-1],i-1);if(hi>=loVal){cb(ary[i-1],i-1);}}
+if(i===ary.length){return;}
+for(let n=ary.length;i<n;i++){const lo=mapLoFn(ary[i]);if(lo>=hiVal)break;cb(ary[i],i);}}
+function findClosestElementInSortedArray(ary,mapFn,val,maxDiff){if(ary.length===0)return null;let aftIdx=findLowIndexInSortedArray(ary,mapFn,val);const befIdx=aftIdx>0?aftIdx-1:0;if(aftIdx===ary.length)aftIdx-=1;const befDiff=Math.abs(val-mapFn(ary[befIdx]));const aftDiff=Math.abs(val-mapFn(ary[aftIdx]));if(befDiff>maxDiff&&aftDiff>maxDiff)return null;const idx=befDiff<aftDiff?befIdx:aftIdx;return ary[idx];}
+function findClosestIntervalInSortedIntervals(ary,mapLoFn,mapHiFn,val,maxDiff){if(ary.length===0)return null;let idx=findLowIndexInSortedArray(ary,mapLoFn,val);if(idx>0)idx-=1;const hiInt=ary[idx];let loInt=hiInt;if(val>mapHiFn(hiInt)&&idx+1<ary.length){loInt=ary[idx+1];}
+const loDiff=Math.abs(val-mapLoFn(loInt));const hiDiff=Math.abs(val-mapHiFn(hiInt));if(loDiff>maxDiff&&hiDiff>maxDiff)return null;if(loDiff<hiDiff)return loInt;return hiInt;}
+function findFirstTrueIndexInSortedArray(array,test){let i0=0;let i1=array.length;while(i0<i1){const i=Math.trunc((i0+i1)/2);if(test(array[i])){i1=i;}else{i0=i+1;}}
+return i1;}
+return{compareArrays,deepCopy,findClosestElementInSortedArray,findClosestIntervalInSortedIntervals,findFirstTrueIndexInSortedArray,findIndexInSortedClosedIntervals,findIndexInSortedIntervals,findLowIndexInSortedArray,formatDate,getFirstElement,getOnlyElement,getUsingPath,groupIntoMap,inPlaceFilter,invertArrayOfDicts,isUrl,iterateOverIntersectingIntervals,normalizeException,numberFromJson,numberToJson,runLengthEncoding,setsEqual,stackTrace,stackTraceAsString,};});'use strict';tr.exportTo('tr.b',function(){function decorateExtensionRegistry(registry,registryOptions){if(registry.register){throw new Error('Already has registry');}
+registryOptions.freeze();if(registryOptions.mode===tr.b.BASIC_REGISTRY_MODE){tr.b._decorateBasicExtensionRegistry(registry,registryOptions);}else if(registryOptions.mode===tr.b.TYPE_BASED_REGISTRY_MODE){tr.b._decorateTypeBasedExtensionRegistry(registry,registryOptions);}else{throw new Error('Unrecognized mode');}
+if(registry.addEventListener===undefined){tr.b.EventTarget.decorate(registry);}}
+return{decorateExtensionRegistry,};});'use strict';tr.exportTo('tr.importer',function(){function Importer(){}
+Importer.prototype={__proto__:Object.prototype,get importerName(){return'Importer';},isTraceDataContainer(){return false;},extractSubtraces(){return[];},importClockSyncMarkers(){},importEvents(){},importSampleData(){},finalizeImport(){}};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Importer;tr.b.decorateExtensionRegistry(Importer,options);Importer.findImporterFor=function(eventData){const typeInfo=Importer.findTypeInfoMatching(function(ti){return ti.constructor.canImport(eventData);});if(typeInfo){return typeInfo.constructor;}
+return undefined;};return{Importer,};});'use strict';tr.exportTo('tr.e.importer.gcloud_trace',function(){function GcloudTraceImporter(model,eventData){this.importPriority=2;this.eventData_=eventData;}
+GcloudTraceImporter.canImport=function(eventData){if(typeof(eventData)!=='string'&&!(eventData instanceof String)){return false;}
+const normalizedEventData=eventData.slice(0,20).replace(/\s/g,'');if(normalizedEventData.length<14)return false;return normalizedEventData.slice(0,14)==='{"projectId":"';};GcloudTraceImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'GcloudTraceImporter';},extractSubtraces(){const traceEvents=this.createEventsForTrace();return traceEvents?[traceEvents]:[];},createEventsForTrace(){const events=[];const trace=JSON.parse(this.eventData_);const spanLength=trace.spans.length;for(let i=0;i<spanLength;i++){events.push(this.createEventForSpan(trace.traceId,trace.spans[i]));}
+return{'traceEvents':events};},createEventForSpan(traceId,span){let newArgs={};if(span.labels){newArgs=JSON.parse(JSON.stringify(span.labels));}
+newArgs['Span ID']=span.spanId;newArgs['Start Time']=span.startTime;newArgs['End Time']=span.endTime;if(span.parentSpanId){newArgs['Parent Span ID']=span.parentSpanId;}
+return{name:span.name,args:newArgs,pid:traceId,ts:Date.parse(span.startTime)*1000,dur:(Date.parse(span.endTime)-Date.parse(span.startTime))*1000,cat:'tracespan',tid:traceId,ph:'X'};}};tr.importer.Importer.register(GcloudTraceImporter);return{GcloudTraceImporter,};});'use strict';tr.exportTo('tr.b.math',function(){function convertEventsToRanges(events){return events.map(function(event){return tr.b.math.Range.fromExplicitRange(event.start,event.end);});}
+function mergeRanges(inRanges,mergeThreshold,mergeFunction){const remainingEvents=inRanges.slice();remainingEvents.sort(function(x,y){return x.min-y.min;});if(remainingEvents.length<=1){const merged=[];if(remainingEvents.length===1){merged.push(mergeFunction(remainingEvents));}
+return merged;}
+const mergedEvents=[];let currentMergeBuffer=[];let rightEdge;function beginMerging(){currentMergeBuffer.push(remainingEvents[0]);remainingEvents.splice(0,1);rightEdge=currentMergeBuffer[0].max;}
+function flushCurrentMergeBuffer(){if(currentMergeBuffer.length===0)return;mergedEvents.push(mergeFunction(currentMergeBuffer));currentMergeBuffer=[];if(remainingEvents.length!==0)beginMerging();}
+beginMerging();while(remainingEvents.length){const currentEvent=remainingEvents[0];const distanceFromRightEdge=currentEvent.min-rightEdge;if(distanceFromRightEdge<mergeThreshold){rightEdge=Math.max(rightEdge,currentEvent.max);remainingEvents.splice(0,1);currentMergeBuffer.push(currentEvent);continue;}
+flushCurrentMergeBuffer();}
+flushCurrentMergeBuffer();return mergedEvents;}
+function findEmptyRangesBetweenRanges(inRanges,opt_totalRange){if(opt_totalRange&&opt_totalRange.isEmpty)opt_totalRange=undefined;const emptyRanges=[];if(!inRanges.length){if(opt_totalRange)emptyRanges.push(opt_totalRange);return emptyRanges;}
+inRanges=inRanges.slice();inRanges.sort(function(x,y){return x.min-y.min;});if(opt_totalRange&&(opt_totalRange.min<inRanges[0].min)){emptyRanges.push(tr.b.math.Range.fromExplicitRange(opt_totalRange.min,inRanges[0].min));}
+inRanges.forEach(function(range,index){for(let otherIndex=0;otherIndex<inRanges.length;++otherIndex){if(index===otherIndex)continue;const other=inRanges[otherIndex];if(other.min>range.max){emptyRanges.push(tr.b.math.Range.fromExplicitRange(range.max,other.min));return;}
+if(other.max>range.max){return;}}
+if(opt_totalRange&&(range.max<opt_totalRange.max)){emptyRanges.push(tr.b.math.Range.fromExplicitRange(range.max,opt_totalRange.max));}});return emptyRanges;}
+return{convertEventsToRanges,findEmptyRangesBetweenRanges,mergeRanges,};});!function(t,n){if("object"==typeof exports&&"object"==typeof module)module.exports=n();else if("function"==typeof define&&define.amd)define(n);else{var r=n();for(var a in r)("object"==typeof exports?exports:t)[a]=r[a]}}(this,function(){return function(t){function n(a){if(r[a])return r[a].exports;var e=r[a]={exports:{},id:a,loaded:!1};return t[a].call(e.exports,e,e.exports,n),e.loaded=!0,e.exports}var r={};return n.m=t,n.c=r,n.p="",n(0)}([function(t,n,r){n.glMatrix=r(1),n.mat2=r(2),n.mat2d=r(3),n.mat3=r(4),n.mat4=r(5),n.quat=r(6),n.vec2=r(9),n.vec3=r(7),n.vec4=r(8)},function(t,n,r){var a={};a.EPSILON=1e-6,a.ARRAY_TYPE="undefined"!=typeof Float32Array?Float32Array:Array,a.RANDOM=Math.random,a.setMatrixArrayType=function(t){GLMAT_ARRAY_TYPE=t};var e=Math.PI/180;a.toRadian=function(t){return t*e},t.exports=a},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},e.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1];t[1]=n[2],t[2]=r}else t[0]=n[0],t[1]=n[2],t[2]=n[1],t[3]=n[3];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*u-e*a;return o?(o=1/o,t[0]=u*o,t[1]=-a*o,t[2]=-e*o,t[3]=r*o,t):null},e.adjoint=function(t,n){var r=n[0];return t[0]=n[3],t[1]=-n[1],t[2]=-n[2],t[3]=r,t},e.determinant=function(t){return t[0]*t[3]-t[2]*t[1]},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1],f=r[2],s=r[3];return t[0]=a*i+u*c,t[1]=e*i+o*c,t[2]=a*f+u*s,t[3]=e*f+o*s,t},e.mul=e.multiply,e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+u*i,t[1]=e*c+o*i,t[2]=a*-i+u*c,t[3]=e*-i+o*c,t},e.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1];return t[0]=a*i,t[1]=e*i,t[2]=u*c,t[3]=o*c,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t},e.str=function(t){return"mat2("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2))},e.LDU=function(t,n,r,a){return t[2]=a[2]/a[0],r[0]=a[0],r[1]=a[1],r[3]=a[3]-t[2]*r[1],[t,n,r]},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(6);return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(6);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=0,t[5]=0,t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=r*u-a*e;return c?(c=1/c,t[0]=u*c,t[1]=-a*c,t[2]=-e*c,t[3]=r*c,t[4]=(e*i-u*o)*c,t[5]=(a*o-r*i)*c,t):null},e.determinant=function(t){return t[0]*t[3]-t[1]*t[2]},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1],h=r[2],M=r[3],l=r[4],v=r[5];return t[0]=a*f+u*s,t[1]=e*f+o*s,t[2]=a*h+u*M,t[3]=e*h+o*M,t[4]=a*l+u*v+i,t[5]=e*l+o*v+c,t},e.mul=e.multiply,e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=Math.sin(r),s=Math.cos(r);return t[0]=a*s+u*f,t[1]=e*s+o*f,t[2]=a*-f+u*s,t[3]=e*-f+o*s,t[4]=i,t[5]=c,t},e.scale=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1];return t[0]=a*f,t[1]=e*f,t[2]=u*s,t[3]=o*s,t[4]=i,t[5]=c,t},e.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=r[0],s=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=a*f+u*s+i,t[5]=e*f+o*s+c,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=-r,t[3]=a,t[4]=0,t[5]=0,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=n[1],t[4]=0,t[5]=0,t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=1,t[4]=n[0],t[5]=n[1],t},e.str=function(t){return"mat2d("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+1)},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(9);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat4=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[4],t[4]=n[5],t[5]=n[6],t[6]=n[8],t[7]=n[9],t[8]=n[10],t},e.clone=function(t){var n=new a.ARRAY_TYPE(9);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[5];t[1]=n[3],t[2]=n[6],t[3]=r,t[5]=n[7],t[6]=a,t[7]=e}else t[0]=n[0],t[1]=n[3],t[2]=n[6],t[3]=n[1],t[4]=n[4],t[5]=n[7],t[6]=n[2],t[7]=n[5],t[8]=n[8];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=s*o-i*f,M=-s*u+i*c,l=f*u-o*c,v=r*h+a*M+e*l;return v?(v=1/v,t[0]=h*v,t[1]=(-s*a+e*f)*v,t[2]=(i*a-e*o)*v,t[3]=M*v,t[4]=(s*r-e*c)*v,t[5]=(-i*r+e*u)*v,t[6]=l*v,t[7]=(-f*r+a*c)*v,t[8]=(o*r-a*u)*v,t):null},e.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8];return t[0]=o*s-i*f,t[1]=e*f-a*s,t[2]=a*i-e*o,t[3]=i*c-u*s,t[4]=r*s-e*c,t[5]=e*u-r*i,t[6]=u*f-o*c,t[7]=a*c-r*f,t[8]=r*o-a*u,t},e.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],c=t[7],f=t[8];return n*(f*u-o*c)+r*(-f*e+o*i)+a*(c*e-u*i)},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=r[0],l=r[1],v=r[2],m=r[3],p=r[4],d=r[5],A=r[6],R=r[7],w=r[8];return t[0]=M*a+l*o+v*f,t[1]=M*e+l*i+v*s,t[2]=M*u+l*c+v*h,t[3]=m*a+p*o+d*f,t[4]=m*e+p*i+d*s,t[5]=m*u+p*c+d*h,t[6]=A*a+R*o+w*f,t[7]=A*e+R*i+w*s,t[8]=A*u+R*c+w*h,t},e.mul=e.multiply,e.translate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=r[0],l=r[1];return t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=c,t[6]=M*a+l*o+f,t[7]=M*e+l*i+s,t[8]=M*u+l*c+h,t},e.rotate=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=Math.sin(r),l=Math.cos(r);return t[0]=l*a+M*o,t[1]=l*e+M*i,t[2]=l*u+M*c,t[3]=l*o-M*a,t[4]=l*i-M*e,t[5]=l*c-M*u,t[6]=f,t[7]=s,t[8]=h,t},e.scale=function(t,n,r){var a=r[0],e=r[1];return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=e*n[3],t[4]=e*n[4],t[5]=e*n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=1,t[5]=0,t[6]=n[0],t[7]=n[1],t[8]=1,t},e.fromRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=-r,t[4]=a,t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=n[1],t[5]=0,t[6]=0,t[7]=0,t[8]=1,t},e.fromMat2d=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=0,t[3]=n[2],t[4]=n[3],t[5]=0,t[6]=n[4],t[7]=n[5],t[8]=1,t},e.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,c=e+e,f=r*o,s=a*o,h=a*i,M=e*o,l=e*i,v=e*c,m=u*o,p=u*i,d=u*c;return t[0]=1-h-v,t[3]=s-d,t[6]=M+p,t[1]=s+d,t[4]=1-f-v,t[7]=l-m,t[2]=M-p,t[5]=l+m,t[8]=1-f-h,t},e.normalFromMat4=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15],A=r*i-a*o,R=r*c-e*o,w=r*f-u*o,q=a*c-e*i,Y=a*f-u*i,g=e*f-u*c,y=s*m-h*v,x=s*p-M*v,P=s*d-l*v,E=h*p-M*m,T=h*d-l*m,b=M*d-l*p,D=A*b-R*T+w*E+q*P-Y*x+g*y;return D?(D=1/D,t[0]=(i*b-c*T+f*E)*D,t[1]=(c*P-o*b-f*x)*D,t[2]=(o*T-i*P+f*y)*D,t[3]=(e*T-a*b-u*E)*D,t[4]=(r*b-e*P+u*x)*D,t[5]=(a*P-r*T-u*y)*D,t[6]=(m*g-p*Y+d*q)*D,t[7]=(p*w-v*g-d*R)*D,t[8]=(v*Y-m*w+d*A)*D,t):null},e.str=function(t){return"mat3("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2))},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(16);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.clone=function(t){var n=new a.ARRAY_TYPE(16);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n[4]=t[4],n[5]=t[5],n[6]=t[6],n[7]=t[7],n[8]=t[8],n[9]=t[9],n[10]=t[10],n[11]=t[11],n[12]=t[12],n[13]=t[13],n[14]=t[14],n[15]=t[15],n},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},e.identity=function(t){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.transpose=function(t,n){if(t===n){var r=n[1],a=n[2],e=n[3],u=n[6],o=n[7],i=n[11];t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=r,t[6]=n[9],t[7]=n[13],t[8]=a,t[9]=u,t[11]=n[14],t[12]=e,t[13]=o,t[14]=i}else t[0]=n[0],t[1]=n[4],t[2]=n[8],t[3]=n[12],t[4]=n[1],t[5]=n[5],t[6]=n[9],t[7]=n[13],t[8]=n[2],t[9]=n[6],t[10]=n[10],t[11]=n[14],t[12]=n[3],t[13]=n[7],t[14]=n[11],t[15]=n[15];return t},e.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15],A=r*i-a*o,R=r*c-e*o,w=r*f-u*o,q=a*c-e*i,Y=a*f-u*i,g=e*f-u*c,y=s*m-h*v,x=s*p-M*v,P=s*d-l*v,E=h*p-M*m,T=h*d-l*m,b=M*d-l*p,D=A*b-R*T+w*E+q*P-Y*x+g*y;return D?(D=1/D,t[0]=(i*b-c*T+f*E)*D,t[1]=(e*T-a*b-u*E)*D,t[2]=(m*g-p*Y+d*q)*D,t[3]=(M*Y-h*g-l*q)*D,t[4]=(c*P-o*b-f*x)*D,t[5]=(r*b-e*P+u*x)*D,t[6]=(p*w-v*g-d*R)*D,t[7]=(s*g-M*w+l*R)*D,t[8]=(o*T-i*P+f*y)*D,t[9]=(a*P-r*T-u*y)*D,t[10]=(v*Y-m*w+d*A)*D,t[11]=(h*w-s*Y-l*A)*D,t[12]=(i*x-o*E-c*y)*D,t[13]=(r*E-a*x+e*y)*D,t[14]=(m*R-v*q-p*A)*D,t[15]=(s*q-h*R+M*A)*D,t):null},e.adjoint=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=n[4],i=n[5],c=n[6],f=n[7],s=n[8],h=n[9],M=n[10],l=n[11],v=n[12],m=n[13],p=n[14],d=n[15];return t[0]=i*(M*d-l*p)-h*(c*d-f*p)+m*(c*l-f*M),t[1]=-(a*(M*d-l*p)-h*(e*d-u*p)+m*(e*l-u*M)),t[2]=a*(c*d-f*p)-i*(e*d-u*p)+m*(e*f-u*c),t[3]=-(a*(c*l-f*M)-i*(e*l-u*M)+h*(e*f-u*c)),t[4]=-(o*(M*d-l*p)-s*(c*d-f*p)+v*(c*l-f*M)),t[5]=r*(M*d-l*p)-s*(e*d-u*p)+v*(e*l-u*M),t[6]=-(r*(c*d-f*p)-o*(e*d-u*p)+v*(e*f-u*c)),t[7]=r*(c*l-f*M)-o*(e*l-u*M)+s*(e*f-u*c),t[8]=o*(h*d-l*m)-s*(i*d-f*m)+v*(i*l-f*h),t[9]=-(r*(h*d-l*m)-s*(a*d-u*m)+v*(a*l-u*h)),t[10]=r*(i*d-f*m)-o*(a*d-u*m)+v*(a*f-u*i),t[11]=-(r*(i*l-f*h)-o*(a*l-u*h)+s*(a*f-u*i)),t[12]=-(o*(h*p-M*m)-s*(i*p-c*m)+v*(i*M-c*h)),t[13]=r*(h*p-M*m)-s*(a*p-e*m)+v*(a*M-e*h),t[14]=-(r*(i*p-c*m)-o*(a*p-e*m)+v*(a*c-e*i)),t[15]=r*(i*M-c*h)-o*(a*M-e*h)+s*(a*c-e*i),t},e.determinant=function(t){var n=t[0],r=t[1],a=t[2],e=t[3],u=t[4],o=t[5],i=t[6],c=t[7],f=t[8],s=t[9],h=t[10],M=t[11],l=t[12],v=t[13],m=t[14],p=t[15],d=n*o-r*u,A=n*i-a*u,R=n*c-e*u,w=r*i-a*o,q=r*c-e*o,Y=a*c-e*i,g=f*v-s*l,y=f*m-h*l,x=f*p-M*l,P=s*m-h*v,E=s*p-M*v,T=h*p-M*m;return d*T-A*E+R*P+w*x-q*y+Y*g},e.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=n[9],l=n[10],v=n[11],m=n[12],p=n[13],d=n[14],A=n[15],R=r[0],w=r[1],q=r[2],Y=r[3];return t[0]=R*a+w*i+q*h+Y*m,t[1]=R*e+w*c+q*M+Y*p,t[2]=R*u+w*f+q*l+Y*d,t[3]=R*o+w*s+q*v+Y*A,R=r[4],w=r[5],q=r[6],Y=r[7],t[4]=R*a+w*i+q*h+Y*m,t[5]=R*e+w*c+q*M+Y*p,t[6]=R*u+w*f+q*l+Y*d,t[7]=R*o+w*s+q*v+Y*A,R=r[8],w=r[9],q=r[10],Y=r[11],t[8]=R*a+w*i+q*h+Y*m,t[9]=R*e+w*c+q*M+Y*p,t[10]=R*u+w*f+q*l+Y*d,t[11]=R*o+w*s+q*v+Y*A,R=r[12],w=r[13],q=r[14],Y=r[15],t[12]=R*a+w*i+q*h+Y*m,t[13]=R*e+w*c+q*M+Y*p,t[14]=R*u+w*f+q*l+Y*d,t[15]=R*o+w*s+q*v+Y*A,t},e.mul=e.multiply,e.translate=function(t,n,r){var a,e,u,o,i,c,f,s,h,M,l,v,m=r[0],p=r[1],d=r[2];return n===t?(t[12]=n[0]*m+n[4]*p+n[8]*d+n[12],t[13]=n[1]*m+n[5]*p+n[9]*d+n[13],t[14]=n[2]*m+n[6]*p+n[10]*d+n[14],t[15]=n[3]*m+n[7]*p+n[11]*d+n[15]):(a=n[0],e=n[1],u=n[2],o=n[3],i=n[4],c=n[5],f=n[6],s=n[7],h=n[8],M=n[9],l=n[10],v=n[11],t[0]=a,t[1]=e,t[2]=u,t[3]=o,t[4]=i,t[5]=c,t[6]=f,t[7]=s,t[8]=h,t[9]=M,t[10]=l,t[11]=v,t[12]=a*m+i*p+h*d+n[12],t[13]=e*m+c*p+M*d+n[13],t[14]=u*m+f*p+l*d+n[14],t[15]=o*m+s*p+v*d+n[15]),t},e.scale=function(t,n,r){var a=r[0],e=r[1],u=r[2];return t[0]=n[0]*a,t[1]=n[1]*a,t[2]=n[2]*a,t[3]=n[3]*a,t[4]=n[4]*e,t[5]=n[5]*e,t[6]=n[6]*e,t[7]=n[7]*e,t[8]=n[8]*u,t[9]=n[9]*u,t[10]=n[10]*u,t[11]=n[11]*u,t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],t},e.rotate=function(t,n,r,e){var u,o,i,c,f,s,h,M,l,v,m,p,d,A,R,w,q,Y,g,y,x,P,E,T,b=e[0],D=e[1],L=e[2],_=Math.sqrt(b*b+D*D+L*L);return Math.abs(_)<a.EPSILON?null:(_=1/_,b*=_,D*=_,L*=_,u=Math.sin(r),o=Math.cos(r),i=1-o,c=n[0],f=n[1],s=n[2],h=n[3],M=n[4],l=n[5],v=n[6],m=n[7],p=n[8],d=n[9],A=n[10],R=n[11],w=b*b*i+o,q=D*b*i+L*u,Y=L*b*i-D*u,g=b*D*i-L*u,y=D*D*i+o,x=L*D*i+b*u,P=b*L*i+D*u,E=D*L*i-b*u,T=L*L*i+o,t[0]=c*w+M*q+p*Y,t[1]=f*w+l*q+d*Y,t[2]=s*w+v*q+A*Y,t[3]=h*w+m*q+R*Y,t[4]=c*g+M*y+p*x,t[5]=f*g+l*y+d*x,t[6]=s*g+v*y+A*x,t[7]=h*g+m*y+R*x,t[8]=c*P+M*E+p*T,t[9]=f*P+l*E+d*T,t[10]=s*P+v*E+A*T,t[11]=h*P+m*E+R*T,n!==t&&(t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t)},e.rotateX=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[4],o=n[5],i=n[6],c=n[7],f=n[8],s=n[9],h=n[10],M=n[11];return n!==t&&(t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[4]=u*e+f*a,t[5]=o*e+s*a,t[6]=i*e+h*a,t[7]=c*e+M*a,t[8]=f*e-u*a,t[9]=s*e-o*a,t[10]=h*e-i*a,t[11]=M*e-c*a,t},e.rotateY=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[0],o=n[1],i=n[2],c=n[3],f=n[8],s=n[9],h=n[10],M=n[11];return n!==t&&(t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=u*e-f*a,t[1]=o*e-s*a,t[2]=i*e-h*a,t[3]=c*e-M*a,t[8]=u*a+f*e,t[9]=o*a+s*e,t[10]=i*a+h*e,t[11]=c*a+M*e,t},e.rotateZ=function(t,n,r){var a=Math.sin(r),e=Math.cos(r),u=n[0],o=n[1],i=n[2],c=n[3],f=n[4],s=n[5],h=n[6],M=n[7];return n!==t&&(t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15]),t[0]=u*e+f*a,t[1]=o*e+s*a,t[2]=i*e+h*a,t[3]=c*e+M*a,t[4]=f*e-u*a,t[5]=s*e-o*a,t[6]=h*e-i*a,t[7]=M*e-c*a,t},e.fromTranslation=function(t,n){return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=n[0],t[13]=n[1],t[14]=n[2],t[15]=1,t},e.fromScaling=function(t,n){return t[0]=n[0],t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=n[1],t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=n[2],t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromRotation=function(t,n,r){var e,u,o,i=r[0],c=r[1],f=r[2],s=Math.sqrt(i*i+c*c+f*f);return Math.abs(s)<a.EPSILON?null:(s=1/s,i*=s,c*=s,f*=s,e=Math.sin(n),u=Math.cos(n),o=1-u,t[0]=i*i*o+u,t[1]=c*i*o+f*e,t[2]=f*i*o-c*e,t[3]=0,t[4]=i*c*o-f*e,t[5]=c*c*o+u,t[6]=f*c*o+i*e,t[7]=0,t[8]=i*f*o+c*e,t[9]=c*f*o-i*e,t[10]=f*f*o+u,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t)},e.fromXRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=1,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=a,t[6]=r,t[7]=0,t[8]=0,t[9]=-r,t[10]=a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromYRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=0,t[2]=-r,t[3]=0,t[4]=0,t[5]=1,t[6]=0,t[7]=0,t[8]=r,t[9]=0,t[10]=a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromZRotation=function(t,n){var r=Math.sin(n),a=Math.cos(n);return t[0]=a,t[1]=r,t[2]=0,t[3]=0,t[4]=-r,t[5]=a,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=1,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.fromRotationTranslation=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=a+a,c=e+e,f=u+u,s=a*i,h=a*c,M=a*f,l=e*c,v=e*f,m=u*f,p=o*i,d=o*c,A=o*f;return t[0]=1-(l+m),t[1]=h+A,t[2]=M-d,t[3]=0,t[4]=h-A,t[5]=1-(s+m),t[6]=v+p,t[7]=0,t[8]=M+d,t[9]=v-p,t[10]=1-(s+l),t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t},e.fromRotationTranslationScale=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3],c=e+e,f=u+u,s=o+o,h=e*c,M=e*f,l=e*s,v=u*f,m=u*s,p=o*s,d=i*c,A=i*f,R=i*s,w=a[0],q=a[1],Y=a[2];return t[0]=(1-(v+p))*w,t[1]=(M+R)*w,t[2]=(l-A)*w,t[3]=0,t[4]=(M-R)*q,t[5]=(1-(h+p))*q,t[6]=(m+d)*q,t[7]=0,t[8]=(l+A)*Y,t[9]=(m-d)*Y,t[10]=(1-(h+v))*Y,t[11]=0,t[12]=r[0],t[13]=r[1],t[14]=r[2],t[15]=1,t},e.fromRotationTranslationScaleOrigin=function(t,n,r,a,e){var u=n[0],o=n[1],i=n[2],c=n[3],f=u+u,s=o+o,h=i+i,M=u*f,l=u*s,v=u*h,m=o*s,p=o*h,d=i*h,A=c*f,R=c*s,w=c*h,q=a[0],Y=a[1],g=a[2],y=e[0],x=e[1],P=e[2];return t[0]=(1-(m+d))*q,t[1]=(l+w)*q,t[2]=(v-R)*q,t[3]=0,t[4]=(l-w)*Y,t[5]=(1-(M+d))*Y,t[6]=(p+A)*Y,t[7]=0,t[8]=(v+R)*g,t[9]=(p-A)*g,t[10]=(1-(M+m))*g,t[11]=0,t[12]=r[0]+y-(t[0]*y+t[4]*x+t[8]*P),t[13]=r[1]+x-(t[1]*y+t[5]*x+t[9]*P),t[14]=r[2]+P-(t[2]*y+t[6]*x+t[10]*P),t[15]=1,t},e.fromQuat=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r+r,i=a+a,c=e+e,f=r*o,s=a*o,h=a*i,M=e*o,l=e*i,v=e*c,m=u*o,p=u*i,d=u*c;return t[0]=1-h-v,t[1]=s+d,t[2]=M-p,t[3]=0,t[4]=s-d,t[5]=1-f-v,t[6]=l+m,t[7]=0,t[8]=M+p,t[9]=l-m,t[10]=1-f-h,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,t},e.frustum=function(t,n,r,a,e,u,o){var i=1/(r-n),c=1/(e-a),f=1/(u-o);return t[0]=2*u*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=2*u*c,t[6]=0,t[7]=0,t[8]=(r+n)*i,t[9]=(e+a)*c,t[10]=(o+u)*f,t[11]=-1,t[12]=0,t[13]=0,t[14]=o*u*2*f,t[15]=0,t},e.perspective=function(t,n,r,a,e){var u=1/Math.tan(n/2),o=1/(a-e);return t[0]=u/r,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=u,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=(e+a)*o,t[11]=-1,t[12]=0,t[13]=0,t[14]=2*e*a*o,t[15]=0,t},e.perspectiveFromFieldOfView=function(t,n,r,a){var e=Math.tan(n.upDegrees*Math.PI/180),u=Math.tan(n.downDegrees*Math.PI/180),o=Math.tan(n.leftDegrees*Math.PI/180),i=Math.tan(n.rightDegrees*Math.PI/180),c=2/(o+i),f=2/(e+u);return t[0]=c,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=f,t[6]=0,t[7]=0,t[8]=-((o-i)*c*.5),t[9]=(e-u)*f*.5,t[10]=a/(r-a),t[11]=-1,t[12]=0,t[13]=0,t[14]=a*r/(r-a),t[15]=0,t},e.ortho=function(t,n,r,a,e,u,o){var i=1/(n-r),c=1/(a-e),f=1/(u-o);return t[0]=-2*i,t[1]=0,t[2]=0,t[3]=0,t[4]=0,t[5]=-2*c,t[6]=0,t[7]=0,t[8]=0,t[9]=0,t[10]=2*f,t[11]=0,t[12]=(n+r)*i,t[13]=(e+a)*c,t[14]=(o+u)*f,t[15]=1,t},e.lookAt=function(t,n,r,u){var o,i,c,f,s,h,M,l,v,m,p=n[0],d=n[1],A=n[2],R=u[0],w=u[1],q=u[2],Y=r[0],g=r[1],y=r[2];return Math.abs(p-Y)<a.EPSILON&&Math.abs(d-g)<a.EPSILON&&Math.abs(A-y)<a.EPSILON?e.identity(t):(M=p-Y,l=d-g,v=A-y,m=1/Math.sqrt(M*M+l*l+v*v),M*=m,l*=m,v*=m,o=w*v-q*l,i=q*M-R*v,c=R*l-w*M,m=Math.sqrt(o*o+i*i+c*c),m?(m=1/m,o*=m,i*=m,c*=m):(o=0,i=0,c=0),f=l*c-v*i,s=v*o-M*c,h=M*i-l*o,m=Math.sqrt(f*f+s*s+h*h),m?(m=1/m,f*=m,s*=m,h*=m):(f=0,s=0,h=0),t[0]=o,t[1]=f,t[2]=M,t[3]=0,t[4]=i,t[5]=s,t[6]=l,t[7]=0,t[8]=c,t[9]=h,t[10]=v,t[11]=0,t[12]=-(o*p+i*d+c*A),t[13]=-(f*p+s*d+h*A),t[14]=-(M*p+l*d+v*A),t[15]=1,t)},e.str=function(t){return"mat4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+", "+t[4]+", "+t[5]+", "+t[6]+", "+t[7]+", "+t[8]+", "+t[9]+", "+t[10]+", "+t[11]+", "+t[12]+", "+t[13]+", "+t[14]+", "+t[15]+")"},e.frob=function(t){return Math.sqrt(Math.pow(t[0],2)+Math.pow(t[1],2)+Math.pow(t[2],2)+Math.pow(t[3],2)+Math.pow(t[4],2)+Math.pow(t[5],2)+Math.pow(t[6],2)+Math.pow(t[7],2)+Math.pow(t[8],2)+Math.pow(t[9],2)+Math.pow(t[10],2)+Math.pow(t[11],2)+Math.pow(t[12],2)+Math.pow(t[13],2)+Math.pow(t[14],2)+Math.pow(t[15],2))},t.exports=e},function(t,n,r){var a=r(1),e=r(4),u=r(7),o=r(8),i={};i.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},i.rotationTo=function(){var t=u.create(),n=u.fromValues(1,0,0),r=u.fromValues(0,1,0);return function(a,e,o){var c=u.dot(e,o);return-.999999>c?(u.cross(t,n,e),u.length(t)<1e-6&&u.cross(t,r,e),u.normalize(t,t),i.setAxisAngle(a,t,Math.PI),a):c>.999999?(a[0]=0,a[1]=0,a[2]=0,a[3]=1,a):(u.cross(t,e,o),a[0]=t[0],a[1]=t[1],a[2]=t[2],a[3]=1+c,i.normalize(a,a))}}(),i.setAxes=function(){var t=e.create();return function(n,r,a,e){return t[0]=a[0],t[3]=a[1],t[6]=a[2],t[1]=e[0],t[4]=e[1],t[7]=e[2],t[2]=-r[0],t[5]=-r[1],t[8]=-r[2],i.normalize(n,i.fromMat3(n,t))}}(),i.clone=o.clone,i.fromValues=o.fromValues,i.copy=o.copy,i.set=o.set,i.identity=function(t){return t[0]=0,t[1]=0,t[2]=0,t[3]=1,t},i.setAxisAngle=function(t,n,r){r=.5*r;var a=Math.sin(r);return t[0]=a*n[0],t[1]=a*n[1],t[2]=a*n[2],t[3]=Math.cos(r),t},i.add=o.add,i.multiply=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3],i=r[0],c=r[1],f=r[2],s=r[3];return t[0]=a*s+o*i+e*f-u*c,t[1]=e*s+o*c+u*i-a*f,t[2]=u*s+o*f+a*c-e*i,t[3]=o*s-a*i-e*c-u*f,t},i.mul=i.multiply,i.scale=o.scale,i.rotateX=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+o*i,t[1]=e*c+u*i,t[2]=u*c-e*i,t[3]=o*c-a*i,t},i.rotateY=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c-u*i,t[1]=e*c+o*i,t[2]=u*c+a*i,t[3]=o*c-e*i,t},i.rotateZ=function(t,n,r){r*=.5;var a=n[0],e=n[1],u=n[2],o=n[3],i=Math.sin(r),c=Math.cos(r);return t[0]=a*c+e*i,t[1]=e*c-a*i,t[2]=u*c+o*i,t[3]=o*c-u*i,t},i.calculateW=function(t,n){var r=n[0],a=n[1],e=n[2];return t[0]=r,t[1]=a,t[2]=e,t[3]=Math.sqrt(Math.abs(1-r*r-a*a-e*e)),t},i.dot=o.dot,i.lerp=o.lerp,i.slerp=function(t,n,r,a){var e,u,o,i,c,f=n[0],s=n[1],h=n[2],M=n[3],l=r[0],v=r[1],m=r[2],p=r[3];return u=f*l+s*v+h*m+M*p,0>u&&(u=-u,l=-l,v=-v,m=-m,p=-p),1-u>1e-6?(e=Math.acos(u),o=Math.sin(e),i=Math.sin((1-a)*e)/o,c=Math.sin(a*e)/o):(i=1-a,c=a),t[0]=i*f+c*l,t[1]=i*s+c*v,t[2]=i*h+c*m,t[3]=i*M+c*p,t},i.sqlerp=function(){var t=i.create(),n=i.create();return function(r,a,e,u,o,c){return i.slerp(t,a,o,c),i.slerp(n,e,u,c),i.slerp(r,t,n,2*c*(1-c)),r}}(),i.invert=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u,i=o?1/o:0;return t[0]=-r*i,t[1]=-a*i,t[2]=-e*i,t[3]=u*i,t},i.conjugate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=n[3],t},i.length=o.length,i.len=i.length,i.squaredLength=o.squaredLength,i.sqrLen=i.squaredLength,i.normalize=o.normalize,i.fromMat3=function(t,n){var r,a=n[0]+n[4]+n[8];if(a>0)r=Math.sqrt(a+1),t[3]=.5*r,r=.5/r,t[0]=(n[5]-n[7])*r,t[1]=(n[6]-n[2])*r,t[2]=(n[1]-n[3])*r;else{var e=0;n[4]>n[0]&&(e=1),n[8]>n[3*e+e]&&(e=2);var u=(e+1)%3,o=(e+2)%3;r=Math.sqrt(n[3*e+e]-n[3*u+u]-n[3*o+o]+1),t[e]=.5*r,r=.5/r,t[3]=(n[3*u+o]-n[3*o+u])*r,t[u]=(n[3*u+e]+n[3*e+u])*r,t[o]=(n[3*o+e]+n[3*e+o])*r}return t},i.str=function(t){return"quat("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=i},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(3);return t[0]=0,t[1]=0,t[2]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(3);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n},e.fromValues=function(t,n,r){var e=new a.ARRAY_TYPE(3);return e[0]=t,e[1]=n,e[2]=r,e},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t},e.set=function(t,n,r,a){return t[0]=n,t[1]=r,t[2]=a,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return Math.sqrt(r*r+a*a+e*e)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2];return r*r+a*a+e*e},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1],a=t[2];return Math.sqrt(n*n+r*r+a*a)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1],a=t[2];return n*n+r*r+a*a},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=n[2],u=r*r+a*a+e*e;return u>0&&(u=1/Math.sqrt(u),t[0]=n[0]*u,t[1]=n[1]*u,t[2]=n[2]*u),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]},e.cross=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2];return t[0]=e*c-u*i,t[1]=u*o-a*c,t[2]=a*i-e*o,t},e.lerp=function(t,n,r,a){var e=n[0],u=n[1],o=n[2];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t},e.hermite=function(t,n,r,a,e,u){var o=u*u,i=o*(2*u-3)+1,c=o*(u-2)+u,f=o*(u-1),s=o*(3-2*u);return t[0]=n[0]*i+r[0]*c+a[0]*f+e[0]*s,t[1]=n[1]*i+r[1]*c+a[1]*f+e[1]*s,t[2]=n[2]*i+r[2]*c+a[2]*f+e[2]*s,t},e.bezier=function(t,n,r,a,e,u){var o=1-u,i=o*o,c=u*u,f=i*o,s=3*u*i,h=3*c*o,M=c*u;return t[0]=n[0]*f+r[0]*s+a[0]*h+e[0]*M,t[1]=n[1]*f+r[1]*s+a[1]*h+e[1]*M,t[2]=n[2]*f+r[2]*s+a[2]*h+e[2]*M,t},e.random=function(t,n){n=n||1;var r=2*a.RANDOM()*Math.PI,e=2*a.RANDOM()-1,u=Math.sqrt(1-e*e)*n;return t[0]=Math.cos(r)*u,t[1]=Math.sin(r)*u,t[2]=e*n,t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[3]*a+r[7]*e+r[11]*u+r[15];return o=o||1,t[0]=(r[0]*a+r[4]*e+r[8]*u+r[12])/o,t[1]=(r[1]*a+r[5]*e+r[9]*u+r[13])/o,t[2]=(r[2]*a+r[6]*e+r[10]*u+r[14])/o,t},e.transformMat3=function(t,n,r){var a=n[0],e=n[1],u=n[2];return t[0]=a*r[0]+e*r[3]+u*r[6],t[1]=a*r[1]+e*r[4]+u*r[7],t[2]=a*r[2]+e*r[5]+u*r[8],t},e.transformQuat=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2],f=r[3],s=f*a+i*u-c*e,h=f*e+c*a-o*u,M=f*u+o*e-i*a,l=-o*a-i*e-c*u;return t[0]=s*f+l*-o+h*-c-M*-i,t[1]=h*f+l*-i+M*-o-s*-c,t[2]=M*f+l*-c+s*-i-h*-o,t},e.rotateX=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0],u[1]=e[1]*Math.cos(a)-e[2]*Math.sin(a),u[2]=e[1]*Math.sin(a)+e[2]*Math.cos(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.rotateY=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[2]*Math.sin(a)+e[0]*Math.cos(a),u[1]=e[1],u[2]=e[2]*Math.cos(a)-e[0]*Math.sin(a),t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.rotateZ=function(t,n,r,a){var e=[],u=[];return e[0]=n[0]-r[0],e[1]=n[1]-r[1],e[2]=n[2]-r[2],u[0]=e[0]*Math.cos(a)-e[1]*Math.sin(a),u[1]=e[0]*Math.sin(a)+e[1]*Math.cos(a),u[2]=e[2],t[0]=u[0]+r[0],t[1]=u[1]+r[1],t[2]=u[2]+r[2],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=3),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],t[2]=n[i+2],u(t,t,o),n[i]=t[0],n[i+1]=t[1],n[i+2]=t[2];return n}}(),e.angle=function(t,n){var r=e.fromValues(t[0],t[1],t[2]),a=e.fromValues(n[0],n[1],n[2]);e.normalize(r,r),e.normalize(a,a);var u=e.dot(r,a);return u>1?0:Math.acos(u)},e.str=function(t){return"vec3("+t[0]+", "+t[1]+", "+t[2]+")"},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(4);return t[0]=0,t[1]=0,t[2]=0,t[3]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(4);return n[0]=t[0],n[1]=t[1],n[2]=t[2],n[3]=t[3],n},e.fromValues=function(t,n,r,e){var u=new a.ARRAY_TYPE(4);return u[0]=t,u[1]=n,u[2]=r,u[3]=e,u},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t},e.set=function(t,n,r,a,e){return t[0]=n,t[1]=r,t[2]=a,t[3]=e,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t[2]=n[2]+r[2],t[3]=n[3]+r[3],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t[2]=n[2]-r[2],t[3]=n[3]-r[3],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t[2]=n[2]*r[2],t[3]=n[3]*r[3],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t[2]=n[2]/r[2],t[3]=n[3]/r[3],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t[2]=Math.min(n[2],r[2]),t[3]=Math.min(n[3],r[3]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t[2]=Math.max(n[2],r[2]),t[3]=Math.max(n[3],r[3]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t[2]=n[2]*r,t[3]=n[3]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t[2]=n[2]+r[2]*a,t[3]=n[3]+r[3]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return Math.sqrt(r*r+a*a+e*e+u*u)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1],e=n[2]-t[2],u=n[3]-t[3];return r*r+a*a+e*e+u*u},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1],a=t[2],e=t[3];return Math.sqrt(n*n+r*r+a*a+e*e)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1],a=t[2],e=t[3];return n*n+r*r+a*a+e*e},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t[2]=-n[2],t[3]=-n[3],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t[2]=1/n[2],t[3]=1/n[3],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=n[2],u=n[3],o=r*r+a*a+e*e+u*u;return o>0&&(o=1/Math.sqrt(o),t[0]=r*o,t[1]=a*o,t[2]=e*o,t[3]=u*o),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]},e.lerp=function(t,n,r,a){var e=n[0],u=n[1],o=n[2],i=n[3];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t[2]=o+a*(r[2]-o),t[3]=i+a*(r[3]-i),t},e.random=function(t,n){return n=n||1,t[0]=a.RANDOM(),t[1]=a.RANDOM(),t[2]=a.RANDOM(),t[3]=a.RANDOM(),e.normalize(t,t),e.scale(t,t,n),t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=n[3];return t[0]=r[0]*a+r[4]*e+r[8]*u+r[12]*o,t[1]=r[1]*a+r[5]*e+r[9]*u+r[13]*o,t[2]=r[2]*a+r[6]*e+r[10]*u+r[14]*o,t[3]=r[3]*a+r[7]*e+r[11]*u+r[15]*o,t},e.transformQuat=function(t,n,r){var a=n[0],e=n[1],u=n[2],o=r[0],i=r[1],c=r[2],f=r[3],s=f*a+i*u-c*e,h=f*e+c*a-o*u,M=f*u+o*e-i*a,l=-o*a-i*e-c*u;return t[0]=s*f+l*-o+h*-c-M*-i,t[1]=h*f+l*-i+M*-o-s*-c,t[2]=M*f+l*-c+s*-i-h*-o,t[3]=n[3],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=4),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],t[2]=n[i+2],t[3]=n[i+3],u(t,t,o),n[i]=t[0],n[i+1]=t[1],n[i+2]=t[2],n[i+3]=t[3];return n}}(),e.str=function(t){return"vec4("+t[0]+", "+t[1]+", "+t[2]+", "+t[3]+")"},t.exports=e},function(t,n,r){var a=r(1),e={};e.create=function(){var t=new a.ARRAY_TYPE(2);return t[0]=0,t[1]=0,t},e.clone=function(t){var n=new a.ARRAY_TYPE(2);return n[0]=t[0],n[1]=t[1],n},e.fromValues=function(t,n){var r=new a.ARRAY_TYPE(2);return r[0]=t,r[1]=n,r},e.copy=function(t,n){return t[0]=n[0],t[1]=n[1],t},e.set=function(t,n,r){return t[0]=n,t[1]=r,t},e.add=function(t,n,r){return t[0]=n[0]+r[0],t[1]=n[1]+r[1],t},e.subtract=function(t,n,r){return t[0]=n[0]-r[0],t[1]=n[1]-r[1],t},e.sub=e.subtract,e.multiply=function(t,n,r){return t[0]=n[0]*r[0],t[1]=n[1]*r[1],t},e.mul=e.multiply,e.divide=function(t,n,r){return t[0]=n[0]/r[0],t[1]=n[1]/r[1],t},e.div=e.divide,e.min=function(t,n,r){return t[0]=Math.min(n[0],r[0]),t[1]=Math.min(n[1],r[1]),t},e.max=function(t,n,r){return t[0]=Math.max(n[0],r[0]),t[1]=Math.max(n[1],r[1]),t},e.scale=function(t,n,r){return t[0]=n[0]*r,t[1]=n[1]*r,t},e.scaleAndAdd=function(t,n,r,a){return t[0]=n[0]+r[0]*a,t[1]=n[1]+r[1]*a,t},e.distance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1];return Math.sqrt(r*r+a*a)},e.dist=e.distance,e.squaredDistance=function(t,n){var r=n[0]-t[0],a=n[1]-t[1];return r*r+a*a},e.sqrDist=e.squaredDistance,e.length=function(t){var n=t[0],r=t[1];return Math.sqrt(n*n+r*r)},e.len=e.length,e.squaredLength=function(t){var n=t[0],r=t[1];return n*n+r*r},e.sqrLen=e.squaredLength,e.negate=function(t,n){return t[0]=-n[0],t[1]=-n[1],t},e.inverse=function(t,n){return t[0]=1/n[0],t[1]=1/n[1],t},e.normalize=function(t,n){var r=n[0],a=n[1],e=r*r+a*a;return e>0&&(e=1/Math.sqrt(e),t[0]=n[0]*e,t[1]=n[1]*e),t},e.dot=function(t,n){return t[0]*n[0]+t[1]*n[1]},e.cross=function(t,n,r){var a=n[0]*r[1]-n[1]*r[0];return t[0]=t[1]=0,t[2]=a,t},e.lerp=function(t,n,r,a){var e=n[0],u=n[1];return t[0]=e+a*(r[0]-e),t[1]=u+a*(r[1]-u),t},e.random=function(t,n){n=n||1;var r=2*a.RANDOM()*Math.PI;return t[0]=Math.cos(r)*n,t[1]=Math.sin(r)*n,t},e.transformMat2=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e,t[1]=r[1]*a+r[3]*e,t},e.transformMat2d=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[2]*e+r[4],t[1]=r[1]*a+r[3]*e+r[5],t},e.transformMat3=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[3]*e+r[6],t[1]=r[1]*a+r[4]*e+r[7],t},e.transformMat4=function(t,n,r){var a=n[0],e=n[1];return t[0]=r[0]*a+r[4]*e+r[12],t[1]=r[1]*a+r[5]*e+r[13],t},e.forEach=function(){var t=e.create();return function(n,r,a,e,u,o){var i,c;for(r||(r=2),a||(a=0),c=e?Math.min(e*r+a,n.length):n.length,i=a;c>i;i+=r)t[0]=n[i],t[1]=n[i+1],u(t,t,o),n[i]=t[0],n[i+1]=t[1];return n}}(),e.str=function(t){return"vec2("+t[0]+", "+t[1]+")"},t.exports=e}])});'use strict';(function(global){if(tr.isNode){const glMatrixAbsPath=HTMLImportsLoader.hrefToAbsolutePath('/gl-matrix-min.js');const glMatrixModule=require(glMatrixAbsPath);for(const exportName in glMatrixModule){global[exportName]=glMatrixModule[exportName];}}})(this);'use strict';tr.exportTo('tr.b.math',function(){const PREFERRED_NUMBER_SERIES_MULTIPLIERS=[1,2,5,10];function approximately(x,y,delta){if(delta===undefined)delta=1e-9;return Math.abs(x-y)<delta;}
+function clamp(x,lo,hi){return Math.min(Math.max(x,lo),hi);}
+function lerp(percentage,lo,hi){const range=hi-lo;return lo+percentage*range;}
+function normalize(value,lo,hi){return(value-lo)/(hi-lo);}
+function deg2rad(deg){return(Math.PI*deg)/180.0;}
+function erf(x){const sign=(x>=0)?1:-1;x=Math.abs(x);const a1=0.254829592;const a2=-0.284496736;const a3=1.421413741;const a4=-1.453152027;const a5=1.061405429;const p=0.3275911;const t=1.0/(1.0+p*x);const y=1.0-(((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*Math.exp(-x*x);return sign*y;}
+const tmpVec2=vec2.create();const tmpVec2b=vec2.create();const tmpVec4=vec4.create();const tmpMat2d=mat2d.create();vec2.createFromArray=function(arr){if(arr.length!==2)throw new Error('Should be length 2');const v=vec2.create();vec2.set(v,arr[0],arr[1]);return v;};vec2.createXY=function(x,y){const v=vec2.create();vec2.set(v,x,y);return v;};vec2.toString=function(a){return'['+a[0]+', '+a[1]+']';};vec2.addTwoScaledUnitVectors=function(out,u1,scale1,u2,scale2){vec2.scale(tmpVec2,u1,scale1);vec2.scale(tmpVec2b,u2,scale2);vec2.add(out,tmpVec2,tmpVec2b);};vec2.interpolatePiecewiseFunction=function(points,x){if(x<points[0][0])return points[0][1];for(let i=1;i<points.length;++i){if(x<points[i][0]){const percent=normalize(x,points[i-1][0],points[i][0]);return lerp(percent,points[i-1][1],points[i][1]);}}
+return points[points.length-1][1];};vec3.createXYZ=function(x,y,z){const v=vec3.create();vec3.set(v,x,y,z);return v;};vec3.toString=function(a){return'vec3('+a[0]+', '+a[1]+', '+a[2]+')';};mat2d.translateXY=function(out,x,y){vec2.set(tmpVec2,x,y);mat2d.translate(out,out,tmpVec2);};mat2d.scaleXY=function(out,x,y){vec2.set(tmpVec2,x,y);mat2d.scale(out,out,tmpVec2);};vec4.unitize=function(out,a){out[0]=a[0]/a[3];out[1]=a[1]/a[3];out[2]=a[2]/a[3];out[3]=1;return out;};vec2.copyFromVec4=function(out,a){vec4.unitize(tmpVec4,a);vec2.copy(out,tmpVec4);};function logOrLog10(x,base){if(base===10)return Math.log10(x);return Math.log(x)/Math.log(base);}
+function lesserPower(x,opt_base){const base=opt_base||10;return Math.pow(base,Math.floor(logOrLog10(x,base)));}
+function greaterPower(x,opt_base){const base=opt_base||10;return Math.pow(base,Math.ceil(logOrLog10(x,base)));}
+function lesserWholeNumber(x){if(x===0)return 0;const pow10=(x<0)?-lesserPower(-x):lesserPower(x);return pow10*Math.floor(x/pow10);}
+function greaterWholeNumber(x){if(x===0)return 0;const pow10=(x<0)?-lesserPower(-x):lesserPower(x);return pow10*Math.ceil(x/pow10);}
+function truncate(value,digits){const pow10=Math.pow(10,digits);return Math.round(value*pow10)/pow10;}
+function preferredNumberLargerThanMin(min){const absMin=Math.abs(min);const conservativeGuess=tr.b.math.lesserPower(absMin);let minPreferedNumber=undefined;for(const multiplier of PREFERRED_NUMBER_SERIES_MULTIPLIERS){const tightenedGuess=conservativeGuess*multiplier;if(tightenedGuess>=absMin){minPreferedNumber=tightenedGuess;break;}}
+if(minPreferedNumber===undefined){throw new Error('Could not compute preferred number for '+min);}
+if(min<0)minPreferedNumber*=-1;return minPreferedNumber;}
+return{approximately,clamp,lerp,normalize,deg2rad,erf,lesserPower,greaterPower,lesserWholeNumber,greaterWholeNumber,preferredNumberLargerThanMin,truncate,};});'use strict';tr.exportTo('tr.b.math',function(){function Range(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;}
+Range.prototype={__proto__:Object.prototype,clone(){if(this.isEmpty)return new Range();return Range.fromExplicitRange(this.min_,this.max_);},reset(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addRange(range){if(range.isEmpty)return;this.addValue(range.min);this.addValue(range.max);},addValue(value){if(this.isEmpty_){this.max_=value;this.min_=value;this.isEmpty_=false;return;}
+this.max_=Math.max(this.max_,value);this.min_=Math.min(this.min_,value);},set min(min){this.isEmpty_=false;this.min_=min;},get min(){if(this.isEmpty_)return undefined;return this.min_;},get max(){if(this.isEmpty_)return undefined;return this.max_;},set max(max){this.isEmpty_=false;this.max_=max;},get range(){if(this.isEmpty_)return undefined;return this.max_-this.min_;},get center(){return(this.min_+this.max_)*0.5;},get duration(){if(this.isEmpty_)return 0;return this.max_-this.min_;},enclosingPowers(opt_base){if(this.isEmpty)return new Range();return Range.fromExplicitRange(tr.b.math.lesserPower(this.min_,opt_base),tr.b.math.greaterPower(this.max_,opt_base));},normalize(x){return tr.b.math.normalize(x,this.min,this.max);},lerp(x){return tr.b.math.lerp(x,this.min,this.max);},clamp(x){return tr.b.math.clamp(x,this.min,this.max);},equals(that){if(this.isEmpty&&that.isEmpty)return true;if(this.isEmpty!==that.isEmpty)return false;return(tr.b.math.approximately(this.min,that.min)&&tr.b.math.approximately(this.max,that.max));},containsExplicitRangeInclusive(min,max){if(this.isEmpty)return false;return this.min_<=min&&max<=this.max_;},containsExplicitRangeExclusive(min,max){if(this.isEmpty)return false;return this.min_<min&&max<this.max_;},intersectsExplicitRangeInclusive(min,max){if(this.isEmpty)return false;return this.min_<=max&&min<=this.max_;},intersectsExplicitRangeExclusive(min,max){if(this.isEmpty)return false;return this.min_<max&&min<this.max_;},containsRangeInclusive(range){if(range.isEmpty)return false;return this.containsExplicitRangeInclusive(range.min_,range.max_);},containsRangeExclusive(range){if(range.isEmpty)return false;return this.containsExplicitRangeExclusive(range.min_,range.max_);},intersectsRangeInclusive(range){if(range.isEmpty)return false;return this.intersectsExplicitRangeInclusive(range.min_,range.max_);},intersectsRangeExclusive(range){if(range.isEmpty)return false;return this.intersectsExplicitRangeExclusive(range.min_,range.max_);},findExplicitIntersectionDuration(min,max){min=Math.max(this.min,min);max=Math.min(this.max,max);if(max<min)return 0;return max-min;},findIntersection(range){if(this.isEmpty||range.isEmpty)return new Range();const min=Math.max(this.min,range.min);const max=Math.min(this.max,range.max);if(max<min)return new Range();return Range.fromExplicitRange(min,max);},toJSON(){if(this.isEmpty_)return{isEmpty:true};return{isEmpty:false,max:this.max,min:this.min};},filterArray(sortedArray,opt_keyFunc,opt_this){if(this.isEmpty_)return[];const keyFunc=opt_keyFunc||(x=>x);function getValue(obj){return keyFunc.call(opt_this,obj);}
+const first=tr.b.findFirstTrueIndexInSortedArray(sortedArray,obj=>this.min_===undefined||this.min_<=getValue(obj));const last=tr.b.findFirstTrueIndexInSortedArray(sortedArray,obj=>this.max_!==undefined&&this.max_<getValue(obj));return sortedArray.slice(first,last);}};Range.fromDict=function(d){if(d.isEmpty===true)return new Range();if(d.isEmpty===false){const range=new Range();range.min=d.min;range.max=d.max;return range;}
+throw new Error('Not a range');};Range.fromExplicitRange=function(min,max){const range=new Range();range.min=min;range.max=max;return range;};Range.compareByMinTimes=function(a,b){if(!a.isEmpty&&!b.isEmpty)return a.min_-b.min_;if(a.isEmpty&&!b.isEmpty)return-1;if(!a.isEmpty&&b.isEmpty)return 1;return 0;};Range.findDifference=function(rangeA,rangeB){if(!rangeA||rangeA.duration<0||!rangeB||rangeB.duration<0){throw new Error(`Couldn't subtract ranges`);}
+const resultRanges=[];if(rangeA.isEmpty)return resultRanges;if(rangeB.isEmpty)return[rangeA.clone()];const intersection=rangeA.findIntersection(rangeB);if(intersection.isEmpty){return[rangeA.clone()];}
+if(rangeA.duration===0&&rangeB.duration===0){if(intersection.empty)return[rangeA.clone()];else if(intersection.duration===0)return resultRanges;throw new Error(`Two points' intersection can only be a point or empty`);}
+const leftRange=tr.b.math.Range.fromExplicitRange(rangeA.min,intersection.min);if(leftRange.duration>0){resultRanges.push(leftRange);}
+const rightRange=tr.b.math.Range.fromExplicitRange(intersection.max,rangeA.max);if(rightRange.duration>0){resultRanges.push(rightRange);}
+return resultRanges;};Range.PERCENT_RANGE=Range.fromExplicitRange(0,1);Object.freeze(Range.PERCENT_RANGE);return{Range,};});'use strict';(function(exports){var rank={standard:function(array,key){array=array.sort(function(a,b){var x=a[key];var y=b[key];return((x<y)?-1:((x>y)?1:0));});for(var i=1;i<array.length+1;i++){array[i-1]['rank']=i;}
+return array;},fractional:function(array,key){array=this.standard(array,key);var pos=0;while(pos<array.length){var sum=0;var i=0;for(i=0;array[pos+i+1]&&(array[pos+i][key]===array[pos+i+1][key]);i++){sum+=array[pos+i]['rank'];}
+sum+=array[pos+i]['rank'];var endPos=pos+i+1;for(pos;pos<endPos;pos++){array[pos]['rank']=sum/(i+1);}
+pos=endPos;}
+return array;},rank:function(x,y){var nx=x.length,ny=y.length,combined=[],ranked;while(nx--){combined.push({set:'x',val:x[nx]});}
+while(ny--){combined.push({set:'y',val:y[ny]});}
+ranked=this.fractional(combined,'val');return ranked}};var erf=function erf(x){var cof=[-1.3026537197817094,6.4196979235649026e-1,1.9476473204185836e-2,-9.561514786808631e-3,-9.46595344482036e-4,3.66839497852761e-4,4.2523324806907e-5,-2.0278578112534e-5,-1.624290004647e-6,1.303655835580e-6,1.5626441722e-8,-8.5238095915e-8,6.529054439e-9,5.059343495e-9,-9.91364156e-10,-2.27365122e-10,9.6467911e-11,2.394038e-12,-6.886027e-12,8.94487e-13,3.13092e-13,-1.12708e-13,3.81e-16,7.106e-15,-1.523e-15,-9.4e-17,1.21e-16,-2.8e-17];var j=cof.length-1;var isneg=false;var d=0;var dd=0;var t,ty,tmp,res;if(x<0){x=-x;isneg=true;}
+t=2/(2+x);ty=4*t-2;for(;j>0;j--){tmp=d;d=ty*d-dd+cof[j];dd=tmp;}
+res=t*Math.exp(-x*x+0.5*(cof[0]+ty*d)-dd);return isneg?res-1:1-res;};var dnorm=function(x,mean,std){return 0.5*(1+erf((x-mean)/Math.sqrt(2*std*std)));}
+var statistic=function(x,y){var ranked=rank.rank(x,y),nr=ranked.length,nx=x.length,ny=y.length,ranksums={x:0,y:0},i=0,t=0,nt=1,tcf,ux,uy;while(i<nr){if(i>0){if(ranked[i].val==ranked[i-1].val){nt++;}else{if(nt>1){t+=Math.pow(nt,3)-nt
+nt=1;}}}
+ranksums[ranked[i].set]+=ranked[i].rank
+i++;}
+tcf=1-(t/(Math.pow(nr,3)-nr))
+ux=nx*ny+(nx*(nx+1)/2)-ranksums.x;uy=nx*ny-ux;return{tcf:tcf,ux:ux,uy:uy,big:Math.max(ux,uy),small:Math.min(ux,uy)}}
+exports.test=function(x,y,alt,corr){alt=typeof alt!=='undefined'?alt:'two-sided';corr=typeof corr!=='undefined'?corr:true;var nx=x.length,ny=y.length,f=1,u,mu,std,z,p;u=statistic(x,y);if(corr){mu=(nx*ny/2)+0.5;}else{mu=nx*ny/2;}
+std=Math.sqrt(u.tcf*nx*ny*(nx+ny+1)/12);if(alt=='less'){z=(u.ux-mu)/std;}else if(alt=='greater'){z=(u.uy-mu)/std;}else if(alt=='two-sided'){z=Math.abs((u.big-mu)/std);}else{console.log('Unknown alternative argument');}
+if(alt=='two-sided'){f=2;}
+p=dnorm(-z,0,1)*f;return{U:u.small,p:p};}})(typeof exports==='undefined'?this['mannwhitneyu']={}:exports);'use strict';(function(global){if(tr.isNode){const mwuAbsPath=HTMLImportsLoader.hrefToAbsolutePath('/mannwhitneyu.js');const mwuModule=require(mwuAbsPath);for(const exportName in mwuModule){global[exportName]=mwuModule[exportName];}}})(this);'use strict';tr.exportTo('tr.b.math',function(){const Statistics={};Statistics.divideIfPossibleOrZero=function(numerator,denominator){if(denominator===0)return 0;return numerator/denominator;};Statistics.sum=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);let ret=0;let i=0;for(const elt of ary){ret+=func.call(opt_this,elt,i++);}
+return ret;};Statistics.mean=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);let sum=0;let i=0;for(const elt of ary){sum+=func.call(opt_this,elt,i++);}
+if(i===0)return undefined;return sum/i;};Statistics.geometricMean=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);let i=0;let logsum=0;for(const elt of ary){const x=func.call(opt_this,elt,i++);if(x<=0)return 0;logsum+=Math.log(Math.abs(x));}
+if(i===0)return 1;return Math.exp(logsum/i);};Statistics.weightedMean=function(ary,weightCallback,opt_valueCallback,opt_this){const valueCallback=opt_valueCallback||(x=>x);let numerator=0;let denominator=0;let i=-1;for(const elt of ary){i++;const value=valueCallback.call(opt_this,elt,i);if(value===undefined)continue;const weight=weightCallback.call(opt_this,elt,i,value);numerator+=weight*value;denominator+=weight;}
+if(denominator===0)return undefined;return numerator/denominator;};Statistics.variance=function(ary,opt_func,opt_this){if(ary.length===0)return undefined;if(ary.length===1)return 0;const func=opt_func||(x=>x);const mean=Statistics.mean(ary,func,opt_this);const sumOfSquaredDistances=Statistics.sum(ary,function(d,i){const v=func.call(this,d,i)-mean;return v*v;},opt_this);return sumOfSquaredDistances/(ary.length-1);};Statistics.stddev=function(ary,opt_func,opt_this){if(ary.length===0)return undefined;return Math.sqrt(Statistics.variance(ary,opt_func,opt_this));};Statistics.max=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);let ret=-Infinity;let i=0;for(const elt of ary){ret=Math.max(ret,func.call(opt_this,elt,i++));}
+return ret;};Statistics.min=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);let ret=Infinity;let i=0;for(const elt of ary){ret=Math.min(ret,func.call(opt_this,elt,i++));}
+return ret;};Statistics.range=function(ary,opt_func,opt_this){const func=opt_func||(x=>x);const ret=new tr.b.math.Range();let i=0;for(const elt of ary){ret.addValue(func.call(opt_this,elt,i++));}
+return ret;};Statistics.percentile=function(ary,percent,opt_func,opt_this){if(!(percent>=0&&percent<=1)){throw new Error('percent must be [0,1]');}
+const func=opt_func||(x=>x);const tmp=new Array(ary.length);let i=0;for(const elt of ary){tmp[i]=func.call(opt_this,elt,i++);}
+tmp.sort((a,b)=>a-b);const idx=Math.floor((ary.length-1)*percent);return tmp[idx];};Statistics.normalizeSamples=function(samples){if(samples.length===0){return{normalized_samples:samples,scale:1.0};}
+samples=samples.slice().sort(function(a,b){return a-b;});const low=Math.min.apply(null,samples);const high=Math.max.apply(null,samples);const newLow=0.5/samples.length;const newHigh=(samples.length-0.5)/samples.length;if(high-low===0.0){samples=Array.apply(null,new Array(samples.length)).map(function(){return 0.5;});return{normalized_samples:samples,scale:1.0};}
+const scale=(newHigh-newLow)/(high-low);for(let i=0;i<samples.length;i++){samples[i]=(samples[i]-low)*scale+newLow;}
+return{normalized_samples:samples,scale};};Statistics.discrepancy=function(samples,opt_locationCount){if(samples.length===0)return 0.0;let maxLocalDiscrepancy=0;const invSampleCount=1.0/samples.length;const locations=[];const countLess=[];const countLessEqual=[];if(opt_locationCount!==undefined){let sampleIndex=0;for(let i=0;i<opt_locationCount;i++){const location=i/(opt_locationCount-1);locations.push(location);while(sampleIndex<samples.length&&samples[sampleIndex]<location){sampleIndex+=1;}
+countLess.push(sampleIndex);while(sampleIndex<samples.length&&samples[sampleIndex]<=location){sampleIndex+=1;}
+countLessEqual.push(sampleIndex);}}else{if(samples[0]>0.0){locations.push(0.0);countLess.push(0);countLessEqual.push(0);}
+for(let i=0;i<samples.length;i++){locations.push(samples[i]);countLess.push(i);countLessEqual.push(i+1);}
+if(samples[-1]<1.0){locations.push(1.0);countLess.push(samples.length);countLessEqual.push(samples.length);}}
+let maxDiff=0;let minDiff=0;for(let i=1;i<locations.length;i++){const length=locations[i]-locations[i-1];const countClosed=countLessEqual[i]-countLess[i-1];const countOpen=countLess[i]-countLessEqual[i-1];const countClosedIncrement=countLessEqual[i]-countLessEqual[i-1];const countOpenIncrement=countLess[i]-countLess[i-1];maxDiff=Math.max(countClosedIncrement*invSampleCount-length+maxDiff,countClosed*invSampleCount-length);minDiff=Math.min(countOpenIncrement*invSampleCount-length+minDiff,countOpen*invSampleCount-length);maxLocalDiscrepancy=Math.max(maxDiff,-minDiff,maxLocalDiscrepancy);}
+return maxLocalDiscrepancy;};Statistics.timestampsDiscrepancy=function(timestamps,opt_absolute,opt_locationCount){if(timestamps.length===0)return 0.0;if(opt_absolute===undefined)opt_absolute=true;if(Array.isArray(timestamps[0])){const rangeDiscrepancies=timestamps.map(function(r){return Statistics.timestampsDiscrepancy(r);});return Math.max.apply(null,rangeDiscrepancies);}
+const s=Statistics.normalizeSamples(timestamps);const samples=s.normalized_samples;const sampleScale=s.scale;let discrepancy=Statistics.discrepancy(samples,opt_locationCount);const invSampleCount=1.0/samples.length;if(opt_absolute===true){discrepancy/=sampleScale;}else{discrepancy=tr.b.math.clamp((discrepancy-invSampleCount)/(1.0-invSampleCount),0.0,1.0);}
+return discrepancy;};Statistics.uniformlySampleArray=function(samples,count){if(samples.length<=count){return samples;}
+while(samples.length>count){const i=parseInt(Math.random()*samples.length);samples.splice(i,1);}
+return samples;};Statistics.uniformlySampleStream=function(samples,streamLength,newElement,numSamples){if(streamLength<=numSamples){if(samples.length>=streamLength){samples[streamLength-1]=newElement;}else{samples.push(newElement);}
+return;}
+const probToKeep=numSamples/streamLength;if(Math.random()>probToKeep)return;const index=Math.floor(Math.random()*numSamples);samples[index]=newElement;};Statistics.mergeSampledStreams=function(samplesA,streamLengthA,samplesB,streamLengthB,numSamples){if(streamLengthB<numSamples){const nbElements=Math.min(streamLengthB,samplesB.length);for(let i=0;i<nbElements;++i){Statistics.uniformlySampleStream(samplesA,streamLengthA+i+1,samplesB[i],numSamples);}
+return;}
+if(streamLengthA<numSamples){const nbElements=Math.min(streamLengthA,samplesA.length);const tempSamples=samplesB.slice();for(let i=0;i<nbElements;++i){Statistics.uniformlySampleStream(tempSamples,streamLengthB+i+1,samplesA[i],numSamples);}
+for(let i=0;i<tempSamples.length;++i){samplesA[i]=tempSamples[i];}
+return;}
+const nbElements=Math.min(numSamples,samplesB.length);const probOfSwapping=streamLengthB/(streamLengthA+streamLengthB);for(let i=0;i<nbElements;++i){if(Math.random()<probOfSwapping){samplesA[i]=samplesB[i];}}};function Distribution(){}
+Distribution.prototype={computeDensity(x){throw Error('Not implemented');},computePercentile(x){throw Error('Not implemented');},computeComplementaryPercentile(x){return 1-this.computePercentile(x);},get mean(){throw Error('Not implemented');},get mode(){throw Error('Not implemented');},get median(){throw Error('Not implemented');},get standardDeviation(){throw Error('Not implemented');},get variance(){throw Error('Not implemented');}};Statistics.UniformDistribution=function(opt_range){if(!opt_range)opt_range=tr.b.math.Range.fromExplicitRange(0,1);this.range=opt_range;};Statistics.UniformDistribution.prototype={__proto__:Distribution.prototype,computeDensity(x){return 1/this.range.range;},computePercentile(x){return tr.b.math.normalize(x,this.range.min,this.range.max);},get mean(){return this.range.center;},get mode(){return undefined;},get median(){return this.mean;},get standardDeviation(){return Math.sqrt(this.variance);},get variance(){return Math.pow(this.range.range,2)/12;}};Statistics.NormalDistribution=function(opt_mean,opt_variance){this.mean_=opt_mean||0;this.variance_=opt_variance||1;this.standardDeviation_=Math.sqrt(this.variance_);};Statistics.NormalDistribution.prototype={__proto__:Distribution.prototype,computeDensity(x){const scale=(1.0/(this.standardDeviation*Math.sqrt(2.0*Math.PI)));const exponent=-Math.pow(x-this.mean,2)/(2.0*this.variance);return scale*Math.exp(exponent);},computePercentile(x){const standardizedX=((x-this.mean)/Math.sqrt(2.0*this.variance));return(1.0+tr.b.math.erf(standardizedX))/2.0;},get mean(){return this.mean_;},get median(){return this.mean;},get mode(){return this.mean;},get standardDeviation(){return this.standardDeviation_;},get variance(){return this.variance_;}};Statistics.LogNormalDistribution=function(opt_location,opt_shape){this.normalDistribution_=new Statistics.NormalDistribution(opt_location,Math.pow(opt_shape||1,2));};Statistics.LogNormalDistribution.prototype={__proto__:Statistics.NormalDistribution.prototype,computeDensity(x){return this.normalDistribution_.computeDensity(Math.log(x))/x;},computePercentile(x){return this.normalDistribution_.computePercentile(Math.log(x));},get mean(){return Math.exp(this.normalDistribution_.mean+
+(this.normalDistribution_.variance/2));},get variance(){const nm=this.normalDistribution_.mean;const nv=this.normalDistribution_.variance;return(Math.exp(2*(nm+nv))-
+Math.exp(2*nm+nv));},get standardDeviation(){return Math.sqrt(this.variance);},get median(){return Math.exp(this.normalDistribution_.mean);},get mode(){return Math.exp(this.normalDistribution_.mean-
+this.normalDistribution_.variance);}};Statistics.LogNormalDistribution.fromMedianAndDiminishingReturns=function(median,diminishingReturns){diminishingReturns=Math.log(diminishingReturns/median);const shape=Math.sqrt(1-3*diminishingReturns-
+Math.sqrt(Math.pow(diminishingReturns-3,2)-8))/2;const location=Math.log(median);return new Statistics.LogNormalDistribution(location,shape);};Statistics.DEFAULT_ALPHA=0.01;Statistics.MAX_SUGGESTED_SAMPLE_SIZE=20;Statistics.Significance={SIGNIFICANT:'REJECT',INSIGNIFICANT:'FAIL_TO_REJECT',NEED_MORE_DATA:'NEED_MORE_DATA',DONT_CARE:'DONT_CARE',};class HypothesisTestResult{constructor(p,u,needMoreData,opt_alpha){this.p_=p;this.u_=u;this.needMoreData_=needMoreData;this.compare(opt_alpha);}
+get p(){return this.p_;}
+get U(){return this.u_;}
+get significance(){return this.significance_;}
+compare(opt_alpha){const alpha=opt_alpha||Statistics.DEFAULT_ALPHA;if(this.p<alpha){this.significance_=Statistics.Significance.SIGNIFICANT;}else if(this.needMoreData_){this.significance_=Statistics.Significance.NEED_MORE_DATA;}else{this.significance_=Statistics.Significance.INSIGNIFICANT;}
+return this.significance_;}
+asDict(){return{p:this.p,U:this.U,significance:this.significance,};}}
+Statistics.mwu=function(a,b,opt_alpha,opt_reqSampleSize){const result=mannwhitneyu.test(a,b);const needMoreData=opt_reqSampleSize&&Math.min(a.length,b.length)<opt_reqSampleSize;return new HypothesisTestResult(result.p,result.U,needMoreData,opt_alpha);};return{Statistics,};});'use strict';tr.exportTo('tr.b',function(){const GREEK_SMALL_LETTER_MU=String.fromCharCode(956);const SECONDS_IN_A_MINUTE=60;const SECONDS_IN_AN_HOUR=SECONDS_IN_A_MINUTE*60;const SECONDS_IN_A_DAY=SECONDS_IN_AN_HOUR*24;const SECONDS_IN_A_WEEK=SECONDS_IN_A_DAY*7;const SECONDS_IN_A_YEAR=SECONDS_IN_A_DAY*365.2422;const SECONDS_IN_A_MONTH=SECONDS_IN_A_YEAR/12;const UnitPrefixScale={};const UnitScale={};function defineUnitPrefixScale(name,prefixes){if(UnitPrefixScale[name]!==undefined){throw new Error('Unit prefix scale \''+name+'\' already exists');}
+if(prefixes.AUTO!==undefined){throw new Error('The \'AUTO\' unit prefix is not supported for unit'+'prefix scales and cannot be added to scale \''+name+'\'');}
+UnitPrefixScale[name]=prefixes;}
+UnitScale.defineUnitScale=function(name,unitScale){if(UnitScale[name]!==undefined){throw new Error('Unit scale \''+name+'\' already exists');}
+if(unitScale.AUTO!==undefined){throw new Error('\'AUTO\' unit scale will be added automatically '+'for unit scale \''+name+'\'');}
+unitScale.AUTO=Object.values(unitScale);unitScale.AUTO.sort((a,b)=>a.value-b.value);if(name)UnitScale[name]=unitScale;return unitScale;};function definePrefixScaleFromUnitScale(prefixName,unitScale){if(!unitScale){throw new Error('Cannot create PrefixScale without a unit scale.');}
+const prefixScale={};for(const[curPrefix,curScale]of Object.entries(unitScale)){if(curPrefix==='AUTO'){continue;}
+if(curScale.symbol===undefined||!curScale.value){throw new Error(`Cannot create PrefixScale from malformed unit ${curScale}.`);}
+prefixScale[curPrefix]={value:curScale.value,symbol:curScale.symbol};}
+return defineUnitPrefixScale(prefixName,prefixScale);}
+UnitScale.defineUnitScaleFromPrefixScale=function(baseSymbol,baseName,prefixScale,opt_scaleName){if(baseSymbol===undefined){throw new Error('Cannot create UnitScale with undefined baseSymbol.');}
+if(!baseName){throw new Error('Cannot create UnitScale without a baseName.');}
+if(!prefixScale){throw new Error('Cannot create UnitScale without a prefix scale.');}
+const unitScale={};for(const curPrefix of Object.keys(prefixScale)){const curScale=prefixScale[curPrefix];if(curScale.symbol===undefined||!curScale.value){throw new Error(`Cannot convert PrefixScale with malformed prefix ${curScale}.`);}
+const name=curPrefix==='NONE'?baseName:`${curPrefix}_${baseName}`;unitScale[name]={value:curScale.value,symbol:curScale.symbol+baseSymbol,baseSymbol};}
+return UnitScale.defineUnitScale(opt_scaleName,unitScale);};function convertUnit(value,fromScale,toScale){if(value===undefined)return undefined;const fromScaleBase=fromScale.baseSymbol;const toScaleBase=toScale.baseSymbol;if(fromScaleBase!==undefined&&toScaleBase!==undefined&&fromScaleBase!==toScaleBase){throw new Error('Cannot convert between units with different base symbols.');}
+return value*(fromScale.value/toScale.value);}
+defineUnitPrefixScale('BINARY',{NONE:{value:Math.pow(1024,0),symbol:''},KIBI:{value:Math.pow(1024,1),symbol:'Ki'},MEBI:{value:Math.pow(1024,2),symbol:'Mi'},GIBI:{value:Math.pow(1024,3),symbol:'Gi'},TEBI:{value:Math.pow(1024,4),symbol:'Ti'}});defineUnitPrefixScale('METRIC',{NANO:{value:1e-9,symbol:'n'},MICRO:{value:1e-6,symbol:GREEK_SMALL_LETTER_MU},MILLI:{value:1e-3,symbol:'m'},NONE:{value:1,symbol:''},KILO:{value:1e3,symbol:'k'},MEGA:{value:1e6,symbol:'M'},GIGA:{value:1e9,symbol:'G'}});UnitScale.defineUnitScale('TIME',{NANO_SEC:{value:1e-9,symbol:'ns',baseSymbol:'s'},MICRO_SEC:{value:1e-6,symbol:GREEK_SMALL_LETTER_MU+'s',baseSymbol:'s'},MILLI_SEC:{value:1e-3,symbol:'ms',baseSymbol:'s'},SEC:{value:1,symbol:'s',baseSymbol:'s'},MINUTE:{value:SECONDS_IN_A_MINUTE,symbol:'min',baseSymbol:'s'},HOUR:{value:SECONDS_IN_AN_HOUR,symbol:'hr',baseSymbol:'s'},DAY:{value:SECONDS_IN_A_DAY,symbol:'days',baseSymbol:'s'},WEEK:{value:SECONDS_IN_A_WEEK,symbol:'weeks',baseSymbol:'s'},MONTH:{value:SECONDS_IN_A_MONTH,symbol:'months',baseSymbol:'s'},YEAR:{value:SECONDS_IN_A_YEAR,symbol:'years',baseSymbol:'s'}});UnitScale.defineUnitScaleFromPrefixScale('B','BYTE',UnitPrefixScale.BINARY,'MEMORY');definePrefixScaleFromUnitScale('DATA_SIZE',UnitScale.MEMORY);UnitScale.defineUnitScaleFromPrefixScale('/s','SECONDS',UnitPrefixScale.DATA_SIZE,'BANDWIDTH_BYTES');return{UnitPrefixScale,UnitScale,convertUnit,GREEK_SMALL_LETTER_MU,};});'use strict';tr.exportTo('tr.b',function(){const msDisplayMode={scale:1e-3,suffix:'ms',roundedLess(a,b){return Math.round(a*1000)<Math.round(b*1000);},formatSpec:{unitScale:[tr.b.UnitScale.TIME.MILLI_SEC],minimumFractionDigits:3,}};const nsDisplayMode={scale:1e-9,suffix:'ns',roundedLess(a,b){return Math.round(a*1000000)<Math.round(b*1000000);},formatSpec:{unitScale:[tr.b.UnitScale.TIME.NANO_SEC],maximumFractionDigits:0}};const TimeDisplayModes={ns:nsDisplayMode,ms:msDisplayMode};return{TimeDisplayModes,};});'use strict';tr.exportTo('tr.ui.b',function(){function iterateElementDeeplyImpl(element,cb,thisArg,includeElement){if(includeElement&&cb.call(thisArg,element))return true;if(element.root&&element.root!==element&&iterateElementDeeplyImpl(element.root,cb,thisArg,false)){return true;}
+const children=Polymer.dom(element).children;for(let i=0;i<children.length;i++){if(iterateElementDeeplyImpl(children[i],cb,thisArg,true)){return true;}}
+return false;}
+function iterateElementDeeply(element,cb,thisArg){iterateElementDeeplyImpl(element,cb,thisArg,false);}
+function findDeepElementMatchingPredicate(element,predicate){let foundElement=undefined;function matches(element){const match=predicate(element);if(!match){return false;}
+foundElement=element;return true;}
+iterateElementDeeply(element,matches);return foundElement;}
+function findDeepElementsMatchingPredicate(element,predicate){const foundElements=[];function matches(element){const match=predicate(element);if(match){foundElements.push(element);}
+return false;}
+iterateElementDeeply(element,matches);return foundElements;}
+function findDeepElementMatching(element,selector){return findDeepElementMatchingPredicate(element,function(element){return element.matches(selector);});}
+function findDeepElementsMatching(element,selector){return findDeepElementsMatchingPredicate(element,function(element){return element.matches(selector);});}
+function findDeepElementWithTextContent(element,re){return findDeepElementMatchingPredicate(element,function(element){if(element.children.length!==0)return false;return re.test(Polymer.dom(element).textContent);});}
+return{findDeepElementMatching,findDeepElementsMatching,findDeepElementMatchingPredicate,findDeepElementsMatchingPredicate,findDeepElementWithTextContent,};});'use strict';tr.exportTo('tr.b',function(){const TimeDisplayModes=tr.b.TimeDisplayModes;const PLUS_MINUS_SIGN=String.fromCharCode(177);const CACHED_FORMATTERS={};function getNumberFormatter(minSpec,maxSpec,minCtx,maxCtx){const key=minSpec+'-'+maxSpec+'-'+minCtx+'-'+maxCtx;let formatter=CACHED_FORMATTERS[key];if(formatter===undefined){let minimumFractionDigits=minCtx!==undefined?minCtx:minSpec;let maximumFractionDigits=maxCtx!==undefined?maxCtx:maxSpec;if(minimumFractionDigits>maximumFractionDigits){if(minCtx!==undefined&&maxCtx===undefined){maximumFractionDigits=minimumFractionDigits;}else if(minCtx===undefined&&maxCtx!==undefined){minimumFractionDigits=maximumFractionDigits;}}
+formatter=new Intl.NumberFormat(undefined,{minimumFractionDigits,maximumFractionDigits,});CACHED_FORMATTERS[key]=formatter;}
+return formatter;}
+function max(a,b){if(a===undefined)return b;if(b===undefined)return a;return a.scale>b.scale?a:b;}
+const ImprovementDirection={DONT_CARE:0,BIGGER_IS_BETTER:1,SMALLER_IS_BETTER:2};function Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,formatSpec){this.unitName=unitName;this.jsonName=jsonName;this.scaleBaseUnit=scaleBaseUnit;this.isDelta=isDelta;this.improvementDirection=improvementDirection;this.formatSpec_=formatSpec;this.baseUnit=undefined;this.correspondingDeltaUnit=undefined;}
+Unit.prototype={asJSON(){return this.jsonName;},asJSON2(){return this.asJSON().replace('_smallerIsBetter','-').replace('_biggerIsBetter','+');},truncate(value){if(typeof value!=='number')return value;if(0===(value%1))return value;if(typeof this.formatSpec_!=='function'&&(!this.formatSpec_.unitScale||((this.formatSpec_.unitScale.length===1)&&(this.formatSpec_.unitScale[0].value===1)))){const digits=this.formatSpec_.maximumFractionDigits||this.formatSpec_.minimumFractionDigits;return tr.b.math.truncate(value,digits+1);}
+const formatted=this.format(value);let test=Math.round(value);if(formatted===this.format(test))return test;let lo=1;let hi=16;while(lo<hi-1){const digits=parseInt((lo+hi)/2);test=tr.b.math.truncate(value,digits);if(formatted===this.format(test)){hi=digits;}else{lo=digits;}}
+test=tr.b.math.truncate(value,lo);if(formatted===this.format(test))return test;return tr.b.math.truncate(value,hi);},getUnitScale_(opt_context){let formatSpec=this.formatSpec_;let formatSpecWasFunction=false;if(typeof formatSpec==='function'){formatSpecWasFunction=true;formatSpec=formatSpec();}
+const context=opt_context||{};let scale=undefined;if(context.unitScale){scale=context.unitScale;}else if(context.unitPrefix){const symbol=formatSpec.baseSymbol?formatSpec.baseSymbol:this.scaleBaseUnit.baseSymbol;scale=tr.b.UnitScale.defineUnitScaleFromPrefixScale(symbol,symbol,[context.unitPrefix]).AUTO;}else{scale=formatSpec.unitScale;if(!scale){scale=[{value:1,symbol:formatSpec.baseSymbol||'',baseSymbol:formatSpec.baseSymbol||''}];if(!formatSpecWasFunction)formatSpec.unitScale=scale;}}
+if(!(scale instanceof Array)){throw new Error('Unit has a malformed unit scale.');}
+return scale;},get unitString(){const scale=this.getUnitScale_();if(!scale){throw new Error('A UnitScale could not be found for Unit '+this.unitName);}
+return scale[0].symbol;},format(value,opt_context){let signString='';if(value<0){signString='-';value=-value;}else if(this.isDelta){signString=value===0?PLUS_MINUS_SIGN:'+';}
+const context=opt_context||{};const scale=this.getUnitScale_(context);let deltaValue=context.deltaValue===undefined?value:context.deltaValue;deltaValue=Math.abs(deltaValue)*this.scaleBaseUnit.value;if(deltaValue===0){deltaValue=1;}
+let i=0;while(i<scale.length-1&&deltaValue/scale[i+1].value>=1){i++;}
+const selectedSubUnit=scale[i];let formatSpec=this.formatSpec_;if(typeof formatSpec==='function')formatSpec=formatSpec();let unitString='';if(selectedSubUnit.symbol){if(!formatSpec.avoidSpacePrecedingUnit)unitString=' ';unitString+=selectedSubUnit.symbol;}
+value=tr.b.convertUnit(value,this.scaleBaseUnit,selectedSubUnit);const numberString=getNumberFormatter(formatSpec.minimumFractionDigits,formatSpec.maximumFractionDigits,context.minimumFractionDigits,context.maximumFractionDigits).format(value);return signString+numberString+unitString;}};Unit.reset=function(){Unit.currentTimeDisplayMode=TimeDisplayModes.ms;};Unit.timestampFromUs=function(us){return tr.b.convertUnit(us,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);};Object.defineProperty(Unit,'currentTimeDisplayMode',{get(){return Unit.currentTimeDisplayMode_;},set(value){if(Unit.currentTimeDisplayMode_===value)return;Unit.currentTimeDisplayMode_=value;Unit.dispatchEvent(new tr.b.Event('display-mode-changed'));}});Unit.didPreferredTimeDisplayUnitChange=function(){let largest=undefined;const els=tr.ui.b.findDeepElementsMatching(document.body,'tr-v-ui-preferred-display-unit');els.forEach(function(el){largest=max(largest,el.preferredTimeDisplayMode);});Unit.currentTimeDisplayMode=largest===undefined?TimeDisplayModes.ms:largest;};Unit.byName={};Unit.byJSONName={};Unit.fromJSON=function(object){if(typeof(object)==='string'){if(object.endsWith('+')){object=object.slice(0,object.length-1)+'_biggerIsBetter';}else if(object.endsWith('-')){object=object.slice(0,object.length-1)+'_smallerIsBetter';}
+const u=Unit.byJSONName[object];if(u)return u;}
+throw new Error(`Unrecognized unit "${object}"`);};Unit.define=function(params){const definedUnits=[];for(const improvementDirection of Object.values(ImprovementDirection)){const regularUnit=Unit.defineUnitVariant_(params,false,improvementDirection);const deltaUnit=Unit.defineUnitVariant_(params,true,improvementDirection);regularUnit.correspondingDeltaUnit=deltaUnit;deltaUnit.correspondingDeltaUnit=deltaUnit;definedUnits.push(regularUnit,deltaUnit);}
+const baseUnit=Unit.byName[params.baseUnitName];definedUnits.forEach(u=>u.baseUnit=baseUnit);};Unit.nameSuffixForImprovementDirection=function(improvementDirection){switch(improvementDirection){case ImprovementDirection.DONT_CARE:return'';case ImprovementDirection.BIGGER_IS_BETTER:return'_biggerIsBetter';case ImprovementDirection.SMALLER_IS_BETTER:return'_smallerIsBetter';default:throw new Error('Unknown improvement direction: '+improvementDirection);}};Unit.defineUnitVariant_=function(params,isDelta,improvementDirection){let nameSuffix=isDelta?'Delta':'';nameSuffix+=Unit.nameSuffixForImprovementDirection(improvementDirection);const unitName=params.baseUnitName+nameSuffix;const jsonName=params.baseJsonName+nameSuffix;if(Unit.byName[unitName]!==undefined){throw new Error('Unit \''+unitName+'\' already exists');}
+if(Unit.byJSONName[jsonName]!==undefined){throw new Error('JSON unit \''+jsonName+'\' alread exists');}
+let scaleBaseUnit=params.scaleBaseUnit;if(!scaleBaseUnit){let formatSpec=params.formatSpec;if(typeof formatSpec==='function')formatSpec=formatSpec();const baseSymbol=formatSpec.unitScale?formatSpec.unitScale[0].baseSymbol:(formatSpec.baseSymbol||'');scaleBaseUnit={value:1,symbol:baseSymbol,baseSymbol};}
+const unit=new Unit(unitName,jsonName,scaleBaseUnit,isDelta,improvementDirection,params.formatSpec);Unit.byName[unitName]=unit;Unit.byJSONName[jsonName]=unit;return unit;};tr.b.EventTarget.decorate(Unit);Unit.reset();Unit.define({baseUnitName:'timeInMsAutoFormat',baseJsonName:'msBestFitFormat',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec:{unitScale:tr.b.UnitScale.TIME.AUTO,minimumFractionDigits:0,maximumFractionDigits:3}});Unit.define({baseUnitName:'timeDurationInMs',baseJsonName:'ms',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'timeStampInMs',baseJsonName:'tsMs',scaleBaseUnit:tr.b.UnitScale.TIME.MILLI_SEC,formatSpec(){return Unit.currentTimeDisplayMode_.formatSpec;}});Unit.define({baseUnitName:'normalizedPercentage',baseJsonName:'n%',formatSpec:{unitScale:[{value:0.01,symbol:'%'}],avoidSpacePrecedingUnit:true,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'sizeInBytes',baseJsonName:'sizeInBytes',formatSpec:{unitScale:tr.b.UnitScale.MEMORY.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'bandwidthInBytesPerSecond',baseJsonName:'bytesPerSecond',formatSpec:{unitScale:tr.b.UnitScale.BANDWIDTH_BYTES.AUTO,minimumFractionDigits:1,maximumFractionDigits:1}});Unit.define({baseUnitName:'energyInJoules',baseJsonName:'J',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('J','JOULE',tr.b.UnitPrefixScale.METRIC,'JOULE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'powerInWatts',baseJsonName:'W',formatSpec:{unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('W','WATT',tr.b.UnitPrefixScale.METRIC,'WATT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricCurrentInAmperes',baseJsonName:'A',formatSpec:{baseSymbol:'A',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('A','AMPERE',tr.b.UnitPrefixScale.METRIC,'AMPERE').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'electricPotentialInVolts',baseJsonName:'V',formatSpec:{baseSymbol:'V',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('V','VOLT',tr.b.UnitPrefixScale.METRIC,'VOLT').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'frequencyInHertz',baseJsonName:'Hz',formatSpec:{baseSymbol:'Hz',unitScale:tr.b.UnitScale.defineUnitScaleFromPrefixScale('Hz','HERTZ',tr.b.UnitPrefixScale.METRIC,'HERTZ').AUTO,minimumFractionDigits:3}});Unit.define({baseUnitName:'unitlessNumber',baseJsonName:'unitless',formatSpec:{minimumFractionDigits:3,maximumFractionDigits:3}});Unit.define({baseUnitName:'count',baseJsonName:'count',formatSpec:{minimumFractionDigits:0,maximumFractionDigits:0}});Unit.define({baseUnitName:'sigma',baseJsonName:'sigma',formatSpec:{baseSymbol:String.fromCharCode(963),minimumFractionDigits:1,maximumFractionDigits:1}});return{ImprovementDirection,Unit,};});'use strict';tr.exportTo('tr.b',function(){class Scalar{constructor(unit,value){if(!(unit instanceof tr.b.Unit)){throw new Error('Expected Unit');}
+if(!(typeof(value)==='number')){throw new Error('Expected value to be number');}
+this.unit=unit;this.value=value;}
+asDict(){return{unit:this.unit.asJSON(),value:tr.b.numberToJson(this.value),};}
+toString(){return this.unit.format(this.value);}
+static fromDict(d){return new Scalar(tr.b.Unit.fromJSON(d.unit),tr.b.numberFromJson(d.value));}}
+return{Scalar,};});'use strict';tr.exportTo('tr.c',function(){function Auditor(model){this.model_=model;}
+Auditor.prototype={__proto__:Object.prototype,get model(){return this.model_;},runAnnotate(){},installUserFriendlyCategoryDriverIfNeeded(){},runAudit(){}};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Auditor;tr.b.decorateExtensionRegistry(Auditor,options);return{Auditor,};});'use strict';tr.exportTo('tr.b',function(){function clamp01(value){return Math.max(0,Math.min(1,value));}
+function Color(opt_r,opt_g,opt_b,opt_a){this.r=Math.floor(opt_r)||0;this.g=Math.floor(opt_g)||0;this.b=Math.floor(opt_b)||0;this.a=opt_a;}
+Color.fromString=function(str){let tmp;let values;if(str.substr(0,4)==='rgb('){tmp=str.substr(4,str.length-5);values=tmp.split(',').map(function(v){return v.replace(/^\s+/,'','g');});if(values.length!==3){throw new Error('Malformatted rgb-expression');}
+return new Color(parseInt(values[0]),parseInt(values[1]),parseInt(values[2]));}
+if(str.substr(0,5)==='rgba('){tmp=str.substr(5,str.length-6);values=tmp.split(',').map(function(v){return v.replace(/^\s+/,'','g');});if(values.length!==4){throw new Error('Malformatted rgb-expression');}
+return new Color(parseInt(values[0]),parseInt(values[1]),parseInt(values[2]),parseFloat(values[3]));}
+if(str[0]==='#'&&str.length===7){return new Color(parseInt(str.substr(1,2),16),parseInt(str.substr(3,2),16),parseInt(str.substr(5,2),16));}
+throw new Error('Unrecognized string format.');};Color.lerp=function(a,b,percent){if(a.a!==undefined&&b.a!==undefined){return Color.lerpRGBA(a,b,percent);}
+return Color.lerpRGB(a,b,percent);};Color.lerpRGB=function(a,b,percent){return new Color(((b.r-a.r)*percent)+a.r,((b.g-a.g)*percent)+a.g,((b.b-a.b)*percent)+a.b);};Color.lerpRGBA=function(a,b,percent){return new Color(((b.r-a.r)*percent)+a.r,((b.g-a.g)*percent)+a.g,((b.b-a.b)*percent)+a.b,((b.a-a.a)*percent)+a.a);};Color.fromDict=function(dict){return new Color(dict.r,dict.g,dict.b,dict.a);};Color.fromHSLExplicit=function(h,s,l,a){let r;let g;let b;function hue2rgb(p,q,t){if(t<0)t+=1;if(t>1)t-=1;if(t<1/6)return p+(q-p)*6*t;if(t<1/2)return q;if(t<2/3)return p+(q-p)*(2/3-t)*6;return p;}
+if(s===0){r=g=b=l;}else{const q=l<0.5?l*(1+s):l+s-l*s;const p=2*l-q;r=hue2rgb(p,q,h+1/3);g=hue2rgb(p,q,h);b=hue2rgb(p,q,h-1/3);}
+return new Color(Math.floor(r*255),Math.floor(g*255),Math.floor(b*255),a);};Color.fromHSL=function(hsl){return Color.fromHSLExplicit(hsl.h,hsl.s,hsl.l,hsl.a);};Color.prototype={clone(){const c=new Color();c.r=this.r;c.g=this.g;c.b=this.b;c.a=this.a;return c;},blendOver(bgColor){const oneMinusThisAlpha=1-this.a;const outA=this.a+bgColor.a*oneMinusThisAlpha;const bgBlend=(bgColor.a*oneMinusThisAlpha)/bgColor.a;return new Color(this.r*this.a+bgColor.r*bgBlend,this.g*this.a+bgColor.g*bgBlend,this.b*this.a+bgColor.b*bgBlend,outA);},brighten(opt_k){const k=opt_k||0.45;return new Color(Math.min(255,this.r+Math.floor(this.r*k)),Math.min(255,this.g+Math.floor(this.g*k)),Math.min(255,this.b+Math.floor(this.b*k)),this.a);},lighten(k,opt_maxL){const maxL=opt_maxL!==undefined?opt_maxL:1.0;const hsl=this.toHSL();hsl.l=Math.min(hsl.l+k,maxL);return Color.fromHSL(hsl);},darken(opt_k){let k;if(opt_k!==undefined){k=opt_k;}else{k=0.45;}
+return new Color(Math.min(255,this.r-Math.floor(this.r*k)),Math.min(255,this.g-Math.floor(this.g*k)),Math.min(255,this.b-Math.floor(this.b*k)),this.a);},desaturate(opt_desaturateFactor){let desaturateFactor;if(opt_desaturateFactor!==undefined){desaturateFactor=opt_desaturateFactor;}else{desaturateFactor=1;}
+const hsl=this.toHSL();hsl.s=clamp01(hsl.s*(1-desaturateFactor));return Color.fromHSL(hsl);},withAlpha(a){return new Color(this.r,this.g,this.b,a);},toString(){if(this.a!==undefined){return'rgba('+
+this.r+','+this.g+','+
+this.b+','+this.a+')';}
+return'rgb('+this.r+','+this.g+','+this.b+')';},toHSL(){const r=this.r/255;const g=this.g/255;const b=this.b/255;const max=Math.max(r,g,b);const min=Math.min(r,g,b);let h;let s;const l=(max+min)/2;if(min===max){h=0;s=0;}else{const delta=max-min;if(l>0.5){s=delta/(2-max-min);}else{s=delta/(max+min);}
+if(r===max){h=(g-b)/delta;if(g<b)h+=6;}else if(g===max){h=2+((b-r)/delta);}else{h=4+((r-g)/delta);}
+h/=6;}
+return{h,s,l,a:this.a};},toStringWithAlphaOverride(alpha){return'rgba('+
+this.r+','+this.g+','+
+this.b+','+alpha+')';}};return{Color,};});'use strict';tr.exportTo('tr.b',function(){function SinebowColorGenerator(opt_a,opt_brightness){this.a_=(opt_a===undefined)?1:opt_a;this.brightness_=(opt_brightness===undefined)?1:opt_brightness;this.colorIndex_=0;this.keyToColor={};}
+SinebowColorGenerator.prototype={colorForKey(key){if(!this.keyToColor[key]){this.keyToColor[key]=this.nextColor();}
+return this.keyToColor[key];},nextColor(){const components=SinebowColorGenerator.nthColor(this.colorIndex_++);return tr.b.Color.fromString(SinebowColorGenerator.calculateColor(components[0],components[1],components[2],this.a_,this.brightness_));}};SinebowColorGenerator.PHI=(1+Math.sqrt(5))/2;SinebowColorGenerator.sinebow=function(h){h+=0.5;h=-h;let r=Math.sin(Math.PI*h);let g=Math.sin(Math.PI*(h+1/3));let b=Math.sin(Math.PI*(h+2/3));r*=r;g*=g;b*=b;const y=2*(0.2989*r+0.5870*g+0.1140*b);r/=y;g/=y;b/=y;return[256*r,256*g,256*b];};SinebowColorGenerator.nthColor=function(n){return SinebowColorGenerator.sinebow(n*this.PHI);};SinebowColorGenerator.calculateColor=function(r,g,b,a,brightness){if(brightness<=1){r*=brightness;g*=brightness;b*=brightness;}else{r=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),r,255);g=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),g,255);b=tr.b.math.lerp(tr.b.math.normalize(brightness,1,2),b,255);}
+r=Math.round(r);g=Math.round(g);b=Math.round(b);return'rgba('+r+','+g+','+b+', '+a+')';};return{SinebowColorGenerator,};});'use strict';tr.exportTo('tr.b',function(){const numGeneralPurposeColorIds=23;const generalPurposeColors=new Array(numGeneralPurposeColorIds);const sinebowAlpha=1.0;const sinebowBrightness=1.5;const sinebowColorGenerator=new tr.b.SinebowColorGenerator(sinebowAlpha,sinebowBrightness);for(let i=0;i<numGeneralPurposeColorIds;i++){generalPurposeColors[i]=sinebowColorGenerator.nextColor();}
+const reservedColorsByName={thread_state_uninterruptible:new tr.b.Color(182,125,143),thread_state_iowait:new tr.b.Color(255,140,0),thread_state_running:new tr.b.Color(126,200,148),thread_state_runnable:new tr.b.Color(133,160,210),thread_state_sleeping:new tr.b.Color(240,240,240),thread_state_unknown:new tr.b.Color(199,155,125),background_memory_dump:new tr.b.Color(0,180,180),light_memory_dump:new tr.b.Color(0,0,180),detailed_memory_dump:new tr.b.Color(180,0,180),vsync_highlight_color:new tr.b.Color(0,0,255),generic_work:new tr.b.Color(125,125,125),good:new tr.b.Color(0,125,0),bad:new tr.b.Color(180,125,0),terrible:new tr.b.Color(180,0,0),black:new tr.b.Color(0,0,0),grey:new tr.b.Color(221,221,221),white:new tr.b.Color(255,255,255),yellow:new tr.b.Color(255,255,0),olive:new tr.b.Color(100,100,0),rail_response:new tr.b.Color(67,135,253),rail_animation:new tr.b.Color(244,74,63),rail_idle:new tr.b.Color(238,142,0),rail_load:new tr.b.Color(13,168,97),startup:new tr.b.Color(230,230,0),heap_dump_stack_frame:new tr.b.Color(128,128,128),heap_dump_object_type:new tr.b.Color(0,0,255),heap_dump_child_node_arrow:new tr.b.Color(204,102,0),cq_build_running:new tr.b.Color(255,255,119),cq_build_passed:new tr.b.Color(153,238,102),cq_build_failed:new tr.b.Color(238,136,136),cq_build_abandoned:new tr.b.Color(187,187,187),cq_build_attempt_runnig:new tr.b.Color(222,222,75),cq_build_attempt_passed:new tr.b.Color(103,218,35),cq_build_attempt_failed:new tr.b.Color(197,81,81)};const numReservedColorIds=Object.keys(reservedColorsByName).length;const numColorsPerVariant=numGeneralPurposeColorIds+numReservedColorIds;function ColorScheme(){}
+const paletteBase=[];paletteBase.push.apply(paletteBase,generalPurposeColors);paletteBase.push.apply(paletteBase,Object.values(reservedColorsByName));ColorScheme.colors=[];ColorScheme.properties={};ColorScheme.properties={numColorsPerVariant,};function pushVariant(func){const variantColors=paletteBase.map(func);ColorScheme.colors.push.apply(ColorScheme.colors,variantColors);}
+pushVariant(function(c){return c;});ColorScheme.properties.brightenedOffsets=[];ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.lighten(0.3,0.8);});ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.lighten(0.48,0.85);});ColorScheme.properties.brightenedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.lighten(0.65,0.9);});ColorScheme.properties.dimmedOffsets=[];ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.desaturate();});ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.desaturate(0.5);});ColorScheme.properties.dimmedOffsets.push(ColorScheme.colors.length);pushVariant(function(c){return c.desaturate(0.3);});ColorScheme.colorsAsStrings=ColorScheme.colors.map(function(c){return c.toString();});const reservedColorNameToIdMap=(function(){const m=new Map();let i=generalPurposeColors.length;for(const key of Object.keys(reservedColorsByName)){m.set(key,i++);}
+return m;})();ColorScheme.getColorIdForReservedName=function(name){const id=reservedColorNameToIdMap.get(name);if(id===undefined){throw new Error('Unrecognized color '+name);}
+return id;};ColorScheme.getColorForReservedNameAsString=function(reservedName){const id=ColorScheme.getColorIdForReservedName(reservedName);return ColorScheme.colorsAsStrings[id];};ColorScheme.getStringHash=function(name){let hash=0;for(let i=0;i<name.length;++i){hash=(hash+37*hash+11*name.charCodeAt(i))%0xFFFFFFFF;}
+return hash;};const stringColorIdCache=new Map();ColorScheme.getColorIdForGeneralPurposeString=function(string){if(stringColorIdCache.get(string)===undefined){const hash=ColorScheme.getStringHash(string);stringColorIdCache.set(string,hash%numGeneralPurposeColorIds);}
+return stringColorIdCache.get(string);};ColorScheme.getAnotherColorId=function(colorId,n){return(colorId+n)%numColorsPerVariant;};ColorScheme.getVariantColorId=function(colorId,offset){return colorId+offset;};return{ColorScheme,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;function EventInfo(title,description,docLinks){this.title=title;this.description=description;this.docLinks=docLinks;this.colorId=ColorScheme.getColorIdForGeneralPurposeString(title);}
+return{EventInfo,};});'use strict';tr.exportTo('tr.b',function(){let nextGUID=1;const UUID4_PATTERN='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx';const GUID={allocateSimple(){return nextGUID++;},getLastSimpleGuid(){return nextGUID-1;},allocateUUID4(){return UUID4_PATTERN.replace(/[xy]/g,function(c){let r=parseInt(Math.random()*16);if(c==='y')r=(r&3)+8;return r.toString(16);});}};return{GUID,};});'use strict';tr.exportTo('tr.model',function(){function EventRegistry(){}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(EventRegistry,options);EventRegistry.addEventListener('will-register',function(e){const metadata=e.typeInfo.metadata;if(metadata.name===undefined){throw new Error('Registered events must provide name metadata');}
+if(metadata.pluralName===undefined){throw new Error('Registered events must provide pluralName metadata');}
+if(metadata.subTypes===undefined){metadata.subTypes={};const options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=e.typeInfo.constructor;options.defaultConstructor=e.typeInfo.constructor;tr.b.decorateExtensionRegistry(metadata.subTypes,options);}else{if(!metadata.subTypes.register){throw new Error('metadata.subTypes must be an extension registry.');}}
+e.typeInfo.constructor.subTypes=metadata.subTypes;});let eventsByTypeName=undefined;EventRegistry.getEventTypeInfoByTypeName=function(typeName){if(eventsByTypeName===undefined){eventsByTypeName={};EventRegistry.getAllRegisteredTypeInfos().forEach(function(typeInfo){eventsByTypeName[typeInfo.metadata.name]=typeInfo;});}
+return eventsByTypeName[typeName];};EventRegistry.addEventListener('registry-changed',function(){eventsByTypeName=undefined;});function convertCamelCaseToTitleCase(name){let result=name.replace(/[A-Z]/g,' $&');result=result.charAt(0).toUpperCase()+result.slice(1);return result;}
+EventRegistry.getUserFriendlySingularName=function(typeName){const typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);const str=typeInfo.metadata.name;return convertCamelCaseToTitleCase(str);};EventRegistry.getUserFriendlyPluralName=function(typeName){const typeInfo=EventRegistry.getEventTypeInfoByTypeName(typeName);const str=typeInfo.metadata.pluralName;return convertCamelCaseToTitleCase(str);};return{EventRegistry,};});'use strict';tr.exportTo('tr.model',function(){const EventRegistry=tr.model.EventRegistry;const RequestSelectionChangeEvent=tr.b.Event.bind(undefined,'requestSelectionChange',true,false);function EventSet(opt_events){this.bounds_=new tr.b.math.Range();this.events_=new Set();this.guid_=tr.b.GUID.allocateSimple();if(opt_events){if(opt_events instanceof Array){for(const event of opt_events){this.push(event);}}else if(opt_events instanceof EventSet){this.addEventSet(opt_events);}else{this.push(opt_events);}}}
+EventSet.prototype={__proto__:Object.prototype,get bounds(){return this.bounds_;},get duration(){if(this.bounds_.isEmpty)return 0;return this.bounds_.max-this.bounds_.min;},get length(){return this.events_.size;},get guid(){return this.guid_;},*[Symbol.iterator](){for(const event of this.events_){yield event;}},clear(){this.bounds_=new tr.b.math.Range();this.events_.clear();},push(...events){let numPushed;for(const event of events){if(event.guid===undefined){throw new Error('Event must have a GUID');}
+if(!this.events_.has(event)){this.events_.add(event);if(event.addBoundsToRange){if(this.bounds_!==undefined){event.addBoundsToRange(this.bounds_);}}}
+numPushed++;}
+return numPushed;},contains(event){if(this.events_.has(event))return event;return undefined;},addEventSet(eventSet){for(const event of eventSet){this.push(event);}},intersectionIsEmpty(otherEventSet){return!this.some(event=>otherEventSet.contains(event));},equals(that){if(this.length!==that.length)return false;return this.every(event=>that.contains(event));},sortEvents(compare){const ary=this.toArray();ary.sort(compare);this.clear();for(const event of ary){this.push(event);}},getEventsOrganizedByBaseType(opt_pruneEmpty){const allTypeInfos=EventRegistry.getAllRegisteredTypeInfos();const events=this.getEventsOrganizedByCallback(function(event){let maxEventIndex=-1;let maxEventTypeInfo=undefined;allTypeInfos.forEach(function(eventTypeInfo,eventIndex){if(!(event instanceof eventTypeInfo.constructor))return;if(eventIndex>maxEventIndex){maxEventIndex=eventIndex;maxEventTypeInfo=eventTypeInfo;}});if(maxEventIndex===-1){throw new Error(`Unrecognized event type: ${event.constructor.name}`);}
+return maxEventTypeInfo.metadata.name;});if(!opt_pruneEmpty){allTypeInfos.forEach(function(eventTypeInfo){if(events[eventTypeInfo.metadata.name]===undefined){events[eventTypeInfo.metadata.name]=new EventSet();}});}
+return events;},getEventsOrganizedByTitle(){return this.getEventsOrganizedByCallback(function(event){if(event.title===undefined){throw new Error('An event didn\'t have a title!');}
+return event.title;});},getEventsOrganizedByCallback(cb,opt_this){const groupedEvents=tr.b.groupIntoMap(this,cb,opt_this||this);const groupedEventsDict={};for(const[k,events]of groupedEvents){groupedEventsDict[k]=new EventSet(events);}
+return groupedEventsDict;},enumEventsOfType(type,func){for(const event of this){if(event instanceof type){func(event);}}},get userFriendlyName(){if(this.length===0){throw new Error('Empty event set');}
+const eventsByBaseType=this.getEventsOrganizedByBaseType(true);const eventTypeName=Object.keys(eventsByBaseType)[0];if(this.length===1){const tmp=EventRegistry.getUserFriendlySingularName(eventTypeName);return tr.b.getOnlyElement(this.events_).userFriendlyName;}
+const numEventTypes=Object.keys(eventsByBaseType).length;if(numEventTypes!==1){return this.length+' events of various types';}
+const tmp=EventRegistry.getUserFriendlyPluralName(eventTypeName);return this.length+' '+tmp;},filter(fn,opt_this){const res=new EventSet();for(const event of this){if(fn.call(opt_this,event)){res.push(event);}}
+return res;},toArray(){const ary=[];for(const event of this){ary.push(event);}
+return ary;},forEach(fn,opt_this){for(const event of this){fn.call(opt_this,event);}},map(fn,opt_this){const res=[];for(const event of this){res.push(fn.call(opt_this,event));}
+return res;},every(fn,opt_this){for(const event of this){if(!fn.call(opt_this,event)){return false;}}
+return true;},some(fn,opt_this){for(const event of this){if(fn.call(opt_this,event)){return true;}}
+return false;},asDict(){const stableIds=[];for(const event of this){stableIds.push(event.stableId);}
+return{'events':stableIds};},asSet(){return this.events_;}};EventSet.IMMUTABLE_EMPTY_SET=(function(){const s=new EventSet();s.push=function(){throw new Error('Cannot push to an immutable event set');};s.addEventSet=function(){throw new Error('Cannot add to an immutable event set');};Object.freeze(s);return s;})();return{EventSet,RequestSelectionChangeEvent,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;const SelectionState={NONE:0,SELECTED:ColorScheme.properties.brightenedOffsets[0],HIGHLIGHTED:ColorScheme.properties.brightenedOffsets[1],DIMMED:ColorScheme.properties.dimmedOffsets[0],BRIGHTENED0:ColorScheme.properties.brightenedOffsets[0],BRIGHTENED1:ColorScheme.properties.brightenedOffsets[1],BRIGHTENED2:ColorScheme.properties.brightenedOffsets[2],DIMMED0:ColorScheme.properties.dimmedOffsets[0],DIMMED1:ColorScheme.properties.dimmedOffsets[1],DIMMED2:ColorScheme.properties.dimmedOffsets[2]};const brighteningLevels=[SelectionState.NONE,SelectionState.BRIGHTENED0,SelectionState.BRIGHTENED1,SelectionState.BRIGHTENED2];SelectionState.getFromBrighteningLevel=function(level){return brighteningLevels[level];};const dimmingLevels=[SelectionState.DIMMED0,SelectionState.DIMMED1,SelectionState.DIMMED2];SelectionState.getFromDimmingLevel=function(level){return dimmingLevels[level];};return{SelectionState,};});'use strict';tr.exportTo('tr.model',function(){const SelectionState=tr.model.SelectionState;function SelectableItem(modelItem){this.modelItem_=modelItem;}
+SelectableItem.prototype={get modelItem(){return this.modelItem_;},get selected(){return this.selectionState===SelectionState.SELECTED;},addToSelection(selection){const modelItem=this.modelItem_;if(!modelItem)return;selection.push(modelItem);},addToTrackMap(eventToTrackMap,track){const modelItem=this.modelItem_;if(!modelItem)return;eventToTrackMap.addEvent(modelItem,track);}};return{SelectableItem,};});'use strict';tr.exportTo('tr.model',function(){const SelectableItem=tr.model.SelectableItem;const SelectionState=tr.model.SelectionState;const IMMUTABLE_EMPTY_SET=tr.model.EventSet.IMMUTABLE_EMPTY_SET;function Event(){SelectableItem.call(this,this);this.guid_=tr.b.GUID.allocateSimple();this.selectionState=SelectionState.NONE;this.info=undefined;}
+Event.prototype={__proto__:SelectableItem.prototype,get guid(){return this.guid_;},get stableId(){return undefined;},get range(){const range=new tr.b.math.Range();this.addBoundsToRange(range);return range;},associatedAlerts:IMMUTABLE_EMPTY_SET,addAssociatedAlert(alert){if(this.associatedAlerts===IMMUTABLE_EMPTY_SET){this.associatedAlerts=new tr.model.EventSet();}
+this.associatedAlerts.push(alert);},addBoundsToRange(range){}};return{Event,};});'use strict';tr.exportTo('tr.model',function(){function TimedEvent(start){tr.model.Event.call(this);this.start=start;this.duration=0;this.cpuStart=undefined;this.cpuDuration=undefined;this.contexts=Object.freeze([]);}
+TimedEvent.prototype={__proto__:tr.model.Event.prototype,get end(){return this.start+this.duration;},get boundsRange(){return tr.b.math.Range.fromExplicitRange(this.start,this.end);},addBoundsToRange(range){range.addValue(this.start);range.addValue(this.end);},bounds(that,opt_precisionUnit){if(opt_precisionUnit===undefined){opt_precisionUnit=tr.b.TimeDisplayModes.ms;}
+const startsBefore=opt_precisionUnit.roundedLess(that.start,this.start);const endsAfter=opt_precisionUnit.roundedLess(this.end,that.end);return!startsBefore&&!endsAfter;}};return{TimedEvent,};});'use strict';tr.exportTo('tr.model',function(){function Alert(info,start,opt_associatedEvents,opt_args){tr.model.TimedEvent.call(this,start);this.info=info;this.args=opt_args||{};this.associatedEvents=new tr.model.EventSet(opt_associatedEvents);this.associatedEvents.forEach(function(event){event.addAssociatedAlert(this);},this);}
+Alert.prototype={__proto__:tr.model.TimedEvent.prototype,get title(){return this.info.title;},get colorId(){return this.info.colorId;},get userFriendlyName(){return'Alert '+this.title+' at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);}};tr.model.EventRegistry.register(Alert,{name:'alert',pluralName:'alerts'});return{Alert,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;const Statistics=tr.b.math.Statistics;const FRAME_PERF_CLASS={GOOD:'good',BAD:'bad',TERRIBLE:'terrible',NEUTRAL:'generic_work'};function Frame(associatedEvents,threadTimeRanges,opt_args){tr.model.Event.call(this);this.threadTimeRanges=threadTimeRanges;this.associatedEvents=new tr.model.EventSet(associatedEvents);this.args=opt_args||{};this.title='Frame';this.start=Statistics.min(threadTimeRanges,function(x){return x.start;});this.end=Statistics.max(threadTimeRanges,function(x){return x.end;});this.totalDuration=Statistics.sum(threadTimeRanges,function(x){return x.end-x.start;});this.perfClass=FRAME_PERF_CLASS.NEUTRAL;}
+Frame.prototype={__proto__:tr.model.Event.prototype,set perfClass(perfClass){this.colorId=ColorScheme.getColorIdForReservedName(perfClass);this.perfClass_=perfClass;},get perfClass(){return this.perfClass_;},shiftTimestampsForward(amount){this.start+=amount;this.end+=amount;for(let i=0;i<this.threadTimeRanges.length;i++){this.threadTimeRanges[i].start+=amount;this.threadTimeRanges[i].end+=amount;}},addBoundsToRange(range){range.addValue(this.start);range.addValue(this.end);}};tr.model.EventRegistry.register(Frame,{name:'frame',pluralName:'frames'});return{Frame,FRAME_PERF_CLASS,};});'use strict';tr.exportTo('tr.model.helpers',function(){const Frame=tr.model.Frame;const Statistics=tr.b.math.Statistics;const UI_DRAW_TYPE={NONE:'none',LEGACY:'legacy',MARSHMALLOW:'marshmallow'};const UI_THREAD_DRAW_NAMES={'performTraversals':UI_DRAW_TYPE.LEGACY,'Choreographer#doFrame':UI_DRAW_TYPE.MARSHMALLOW};const RENDER_THREAD_DRAW_NAME='DrawFrame';const RENDER_THREAD_INDEP_DRAW_NAME='doFrame';const RENDER_THREAD_QUEUE_NAME='queueBuffer';const RENDER_THREAD_SWAP_NAME='eglSwapBuffers';const THREAD_SYNC_NAME='syncFrameState';function getSlicesForThreadTimeRanges(threadTimeRanges){const ret=[];threadTimeRanges.forEach(function(threadTimeRange){const slices=[];threadTimeRange.thread.sliceGroup.iterSlicesInTimeRange(function(slice){slices.push(slice);},threadTimeRange.start,threadTimeRange.end);ret.push.apply(ret,slices);});return ret;}
+function makeFrame(threadTimeRanges,surfaceFlinger){const args={};if(surfaceFlinger&&surfaceFlinger.hasVsyncs){const start=Statistics.min(threadTimeRanges,function(threadTimeRanges){return threadTimeRanges.start;});args.deadline=surfaceFlinger.getFrameDeadline(start);args.frameKickoff=surfaceFlinger.getFrameKickoff(start);}
+const events=getSlicesForThreadTimeRanges(threadTimeRanges);return new Frame(events,threadTimeRanges,args);}
+function findOverlappingDrawFrame(renderThread,uiDrawSlice){if(!renderThread)return undefined;let overlappingDrawFrame;const slices=tr.b.iterateOverIntersectingIntervals(renderThread.sliceGroup.slices,function(range){return range.start;},function(range){return range.end;},uiDrawSlice.start,uiDrawSlice.end,function(rtDrawSlice){if(rtDrawSlice.title===RENDER_THREAD_DRAW_NAME){const rtSyncSlice=rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);if(rtSyncSlice&&rtSyncSlice.start>=uiDrawSlice.start&&rtSyncSlice.end<=uiDrawSlice.end){overlappingDrawFrame=rtDrawSlice;}}});return overlappingDrawFrame;}
+function getPreTraversalWorkRanges(uiThread){if(!uiThread)return[];const preFrameEvents=[];uiThread.sliceGroup.slices.forEach(function(slice){if(slice.title==='obtainView'||slice.title==='setupListItem'||slice.title==='deliverInputEvent'||slice.title==='RV Scroll'){preFrameEvents.push(slice);}});uiThread.asyncSliceGroup.slices.forEach(function(slice){if(slice.title==='deliverInputEvent'){preFrameEvents.push(slice);}});return tr.b.math.mergeRanges(tr.b.math.convertEventsToRanges(preFrameEvents),3,function(events){return{start:events[0].min,end:events[events.length-1].max};});}
+function getFrameStartTime(traversalStart,preTraversalWorkRanges){const preTraversalWorkRange=tr.b.findClosestIntervalInSortedIntervals(preTraversalWorkRanges,function(range){return range.start;},function(range){return range.end;},traversalStart,3);if(preTraversalWorkRange){return preTraversalWorkRange.start;}
+return traversalStart;}
+function getRtFrameEndTime(rtDrawSlice){const rtQueueSlice=rtDrawSlice.findDescendentSlice(RENDER_THREAD_QUEUE_NAME);if(rtQueueSlice){return rtQueueSlice.end;}
+const rtSwapSlice=rtDrawSlice.findDescendentSlice(RENDER_THREAD_SWAP_NAME);if(rtSwapSlice){return rtSwapSlice.end;}
+return rtDrawSlice.end;}
+function getUiThreadDrivenFrames(app){if(!app.uiThread)return[];let preTraversalWorkRanges=[];if(app.uiDrawType===UI_DRAW_TYPE.LEGACY){preTraversalWorkRanges=getPreTraversalWorkRanges(app.uiThread);}
+const frames=[];app.uiThread.sliceGroup.slices.forEach(function(slice){if(!(slice.title in UI_THREAD_DRAW_NAMES)){return;}
+const threadTimeRanges=[];const uiThreadTimeRange={thread:app.uiThread,start:getFrameStartTime(slice.start,preTraversalWorkRanges),end:slice.end};threadTimeRanges.push(uiThreadTimeRange);const rtDrawSlice=findOverlappingDrawFrame(app.renderThread,slice);if(rtDrawSlice){const rtSyncSlice=rtDrawSlice.findDescendentSlice(THREAD_SYNC_NAME);if(rtSyncSlice){uiThreadTimeRange.end=Math.min(uiThreadTimeRange.end,rtSyncSlice.start);}
+threadTimeRanges.push({thread:app.renderThread,start:rtDrawSlice.start,end:getRtFrameEndTime(rtDrawSlice)});}
+frames.push(makeFrame(threadTimeRanges,app.surfaceFlinger));});return frames;}
+function getRenderThreadDrivenFrames(app){if(!app.renderThread)return[];const frames=[];app.renderThread.sliceGroup.getSlicesOfName(RENDER_THREAD_INDEP_DRAW_NAME).forEach(function(slice){const threadTimeRanges=[{thread:app.renderThread,start:slice.start,end:slice.end}];frames.push(makeFrame(threadTimeRanges,app.surfaceFlinger));});return frames;}
+function getUiDrawType(uiThread){if(!uiThread){return UI_DRAW_TYPE.NONE;}
+const slices=uiThread.sliceGroup.slices;for(let i=0;i<slices.length;i++){if(slices[i].title in UI_THREAD_DRAW_NAMES){return UI_THREAD_DRAW_NAMES[slices[i].title];}}
+return UI_DRAW_TYPE.NONE;}
+function getInputSamples(process){let samples=undefined;for(const counterName in process.counters){if(/^android\.aq\:pending/.test(counterName)&&process.counters[counterName].numSeries===1){samples=process.counters[counterName].series[0].samples;break;}}
+if(!samples)return[];const inputSamples=[];let lastValue=0;samples.forEach(function(sample){if(sample.value>lastValue){inputSamples.push(sample);}
+lastValue=sample.value;});return inputSamples;}
+function getAnimationAsyncSlices(uiThread){if(!uiThread)return[];const slices=[];for(const slice of uiThread.asyncSliceGroup.getDescendantEvents()){if(/^animator\:/.test(slice.title)){slices.push(slice);}}
+return slices;}
+function AndroidApp(process,uiThread,renderThread,surfaceFlinger,uiDrawType){this.process=process;this.uiThread=uiThread;this.renderThread=renderThread;this.surfaceFlinger=surfaceFlinger;this.uiDrawType=uiDrawType;this.frames_=undefined;this.inputs_=undefined;}
+AndroidApp.createForProcessIfPossible=function(process,surfaceFlinger){let uiThread=process.getThread(process.pid);const uiDrawType=getUiDrawType(uiThread);if(uiDrawType===UI_DRAW_TYPE.NONE){uiThread=undefined;}
+const renderThreads=process.findAllThreadsNamed('RenderThread');const renderThread=(renderThreads.length===1?renderThreads[0]:undefined);if(uiThread||renderThread){return new AndroidApp(process,uiThread,renderThread,surfaceFlinger,uiDrawType);}};AndroidApp.prototype={getFrames(){if(!this.frames_){const uiFrames=getUiThreadDrivenFrames(this);const rtFrames=getRenderThreadDrivenFrames(this);this.frames_=uiFrames.concat(rtFrames);this.frames_.sort(function(a,b){a.end-b.end;});}
+return this.frames_;},getInputSamples(){if(!this.inputs_){this.inputs_=getInputSamples(this.process);}
+return this.inputs_;},getAnimationAsyncSlices(){if(!this.animations_){this.animations_=getAnimationAsyncSlices(this.uiThread);}
+return this.animations_;}};return{AndroidApp,};});'use strict';tr.exportTo('tr.model.helpers',function(){const findLowIndexInSortedArray=tr.b.findLowIndexInSortedArray;const VSYNC_SF_NAME='android.VSYNC-sf';const VSYNC_APP_NAME='android.VSYNC-app';const VSYNC_FALLBACK_NAME='android.VSYNC';const TIMESTAMP_FUDGE_MS=0.01;function getVsyncTimestamps(process,counterName){let vsync=process.counters[counterName];if(!vsync){vsync=process.counters[VSYNC_FALLBACK_NAME];}
+if(vsync&&vsync.numSeries===1&&vsync.numSamples>1){return vsync.series[0].timestamps;}
+return undefined;}
+function AndroidSurfaceFlinger(process,thread){this.process=process;this.thread=thread;this.appVsync_=undefined;this.sfVsync_=undefined;this.appVsyncTimestamps_=getVsyncTimestamps(process,VSYNC_APP_NAME);this.sfVsyncTimestamps_=getVsyncTimestamps(process,VSYNC_SF_NAME);this.deadlineDelayMs_=this.appVsyncTimestamps_!==this.sfVsyncTimestamps_?5:TIMESTAMP_FUDGE_MS;}
+AndroidSurfaceFlinger.createForProcessIfPossible=function(process){const mainThread=process.getThread(process.pid);if(mainThread&&mainThread.name&&/surfaceflinger/.test(mainThread.name)){return new AndroidSurfaceFlinger(process,mainThread);}
+const primaryThreads=process.findAllThreadsNamed('SurfaceFlinger');if(primaryThreads.length===1){return new AndroidSurfaceFlinger(process,primaryThreads[0]);}
+return undefined;};AndroidSurfaceFlinger.prototype={get hasVsyncs(){return!!this.appVsyncTimestamps_&&!!this.sfVsyncTimestamps_;},getFrameKickoff(timestamp){if(!this.hasVsyncs){throw new Error('cannot query vsync info without vsyncs');}
+const firstGreaterIndex=findLowIndexInSortedArray(this.appVsyncTimestamps_,function(x){return x;},timestamp+TIMESTAMP_FUDGE_MS);if(firstGreaterIndex<1)return undefined;return this.appVsyncTimestamps_[firstGreaterIndex-1];},getFrameDeadline(timestamp){if(!this.hasVsyncs){throw new Error('cannot query vsync info without vsyncs');}
+const firstGreaterIndex=findLowIndexInSortedArray(this.sfVsyncTimestamps_,function(x){return x;},timestamp+this.deadlineDelayMs_);if(firstGreaterIndex>=this.sfVsyncTimestamps_.length){return undefined;}
+return this.sfVsyncTimestamps_[firstGreaterIndex];}};return{AndroidSurfaceFlinger,};});'use strict';tr.exportTo('tr.model.helpers',function(){const AndroidApp=tr.model.helpers.AndroidApp;const AndroidSurfaceFlinger=tr.model.helpers.AndroidSurfaceFlinger;const IMPORTANT_SURFACE_FLINGER_SLICES={'doComposition':true,'updateTexImage':true,'postFramebuffer':true};const IMPORTANT_UI_THREAD_SLICES={'Choreographer#doFrame':true,'performTraversals':true,'deliverInputEvent':true};const IMPORTANT_RENDER_THREAD_SLICES={'doFrame':true};function iterateImportantThreadSlices(thread,important,callback){if(!thread)return;thread.sliceGroup.slices.forEach(function(slice){if(slice.title in important){callback(slice);}});}
+function AndroidModelHelper(model){this.model=model;this.apps=[];this.surfaceFlinger=undefined;const processes=model.getAllProcesses();for(let i=0;i<processes.length&&!this.surfaceFlinger;i++){this.surfaceFlinger=AndroidSurfaceFlinger.createForProcessIfPossible(processes[i]);}
+model.getAllProcesses().forEach(function(process){const app=AndroidApp.createForProcessIfPossible(process,this.surfaceFlinger);if(app){this.apps.push(app);}},this);}
+AndroidModelHelper.guid=tr.b.GUID.allocateSimple();AndroidModelHelper.supportsModel=function(model){return true;};AndroidModelHelper.prototype={iterateImportantSlices(callback){if(this.surfaceFlinger){iterateImportantThreadSlices(this.surfaceFlinger.thread,IMPORTANT_SURFACE_FLINGER_SLICES,callback);}
+this.apps.forEach(function(app){iterateImportantThreadSlices(app.uiThread,IMPORTANT_UI_THREAD_SLICES,callback);iterateImportantThreadSlices(app.renderThread,IMPORTANT_RENDER_THREAD_SLICES,callback);});}};return{AndroidModelHelper,};});'use strict';tr.exportTo('tr.model',function(){function Slice(category,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration,opt_argsStripped,opt_bindId){if(new.target){throw new Error('Can\'t instantiate pure virtual class Slice');}
+tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.inFlowEvents=[];this.outFlowEvents=[];this.subSlices=[];this.selfTime=undefined;this.cpuSelfTime=undefined;this.important=false;this.parentContainer=undefined;this.argsStripped=false;this.bind_id_=opt_bindId;this.parentSlice=undefined;this.isTopLevel=false;if(opt_duration!==undefined){this.duration=opt_duration;}
+if(opt_cpuStart!==undefined){this.cpuStart=opt_cpuStart;}
+if(opt_cpuDuration!==undefined){this.cpuDuration=opt_cpuDuration;}
+if(opt_argsStripped!==undefined){this.argsStripped=true;}}
+Slice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get userFriendlyName(){return'Slice '+this.title+' at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get stableId(){const parentSliceGroup=this.parentContainer.sliceGroup;return parentSliceGroup.stableId+'.'+
+parentSliceGroup.slices.indexOf(this);},get bindId(){return this.bind_id_;},findDescendentSlice(targetTitle){if(!this.subSlices){return undefined;}
+for(let i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title===targetTitle){return this.subSlices[i];}
+const slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;}
+return undefined;},get mostTopLevelSlice(){if(!this.parentSlice)return this;return this.parentSlice.mostTopLevelSlice;},getProcess(){const thread=this.parentContainer;if(thread&&thread.getProcess){return thread.getProcess();}
+return undefined;},get model(){const process=this.getProcess();if(process!==undefined){return this.getProcess().model;}
+return undefined;},*findTopmostSlicesRelativeToThisSlice(eventPredicate){if(eventPredicate(this)){yield this;return;}
+for(const s of this.subSlices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate);}},iterateAllSubsequentSlices(callback,opt_this){const parentStack=[];let started=false;const topmostSlice=this.mostTopLevelSlice;parentStack.push(topmostSlice);while(parentStack.length!==0){const curSlice=parentStack.pop();if(started){callback.call(opt_this,curSlice);}else{started=(curSlice.guid===this.guid);}
+for(let i=curSlice.subSlices.length-1;i>=0;i--){parentStack.push(curSlice.subSlices[i]);}}},get subsequentSlices(){const res=[];this.iterateAllSubsequentSlices(function(subseqSlice){res.push(subseqSlice);});return res;},*enumerateAllAncestors(){let curSlice=this.parentSlice;while(curSlice){yield curSlice;curSlice=curSlice.parentSlice;}},get ancestorSlices(){return Array.from(this.enumerateAllAncestors());},iterateEntireHierarchy(callback,opt_this){const mostTopLevelSlice=this.mostTopLevelSlice;callback.call(opt_this,mostTopLevelSlice);mostTopLevelSlice.iterateAllSubsequentSlices(callback,opt_this);},get entireHierarchy(){const res=[];this.iterateEntireHierarchy(function(slice){res.push(slice);});return res;},get ancestorAndSubsequentSlices(){const res=[];res.push(this);for(const aSlice of this.enumerateAllAncestors()){res.push(aSlice);}
+this.iterateAllSubsequentSlices(function(sSlice){res.push(sSlice);});return res;},*enumerateAllDescendents(){for(const slice of this.subSlices){yield slice;}
+for(const slice of this.subSlices){yield*slice.enumerateAllDescendents();}},get descendentSlices(){const res=[];for(const slice of this.enumerateAllDescendents()){res.push(slice);}
+return res;}};return{Slice,};});'use strict';tr.exportTo('tr.model',function(){const Slice=tr.model.Slice;const SCHEDULING_STATE={DEBUG:'Debug',EXIT_DEAD:'Exit Dead',RUNNABLE:'Runnable',RUNNING:'Running',SLEEPING:'Sleeping',STOPPED:'Stopped',TASK_DEAD:'Task Dead',UNINTR_SLEEP:'Uninterruptible Sleep',UNINTR_SLEEP_WAKE_KILL:'Uninterruptible Sleep | WakeKill',UNINTR_SLEEP_WAKING:'Uninterruptible Sleep | Waking',UNINTR_SLEEP_IO:'Uninterruptible Sleep - Block I/O',UNINTR_SLEEP_WAKE_KILL_IO:'Uninterruptible Sleep | WakeKill - Block I/O',UNINTR_SLEEP_WAKING_IO:'Uninterruptible Sleep | Waking - Block I/O',UNKNOWN:'UNKNOWN',WAKE_KILL:'Wakekill',WAKING:'Waking',ZOMBIE:'Zombie'};function ThreadTimeSlice(thread,schedulingState,cat,start,args,opt_duration){Slice.call(this,cat,schedulingState,this.getColorForState_(schedulingState),start,args,opt_duration);this.thread=thread;this.schedulingState=schedulingState;this.cpuOnWhichThreadWasRunning=undefined;}
+ThreadTimeSlice.prototype={__proto__:Slice.prototype,getColorForState_(state){const getColorIdForReservedName=tr.b.ColorScheme.getColorIdForReservedName;switch(state){case SCHEDULING_STATE.RUNNABLE:return getColorIdForReservedName('thread_state_runnable');case SCHEDULING_STATE.RUNNING:return getColorIdForReservedName('thread_state_running');case SCHEDULING_STATE.SLEEPING:return getColorIdForReservedName('thread_state_sleeping');case SCHEDULING_STATE.DEBUG:case SCHEDULING_STATE.EXIT_DEAD:case SCHEDULING_STATE.STOPPED:case SCHEDULING_STATE.TASK_DEAD:case SCHEDULING_STATE.UNINTR_SLEEP:case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:case SCHEDULING_STATE.UNKNOWN:case SCHEDULING_STATE.WAKE_KILL:case SCHEDULING_STATE.WAKING:case SCHEDULING_STATE.ZOMBIE:return getColorIdForReservedName('thread_state_uninterruptible');case SCHEDULING_STATE.UNINTR_SLEEP_IO:case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO:case SCHEDULING_STATE.UNINTR_SLEEP_WAKING_IO:return getColorIdForReservedName('thread_state_iowait');default:return getColorIdForReservedName('thread_state_unknown');}},get analysisTypeName(){return'tr.ui.analysis.ThreadTimeSlice';},getAssociatedCpuSlice(){if(!this.cpuOnWhichThreadWasRunning)return undefined;const cpuSlices=this.cpuOnWhichThreadWasRunning.slices;for(let i=0;i<cpuSlices.length;i++){const cpuSlice=cpuSlices[i];if(cpuSlice.start!==this.start)continue;if(cpuSlice.duration!==this.duration)continue;return cpuSlice;}
+return undefined;},getCpuSliceThatTookCpu(){if(this.cpuOnWhichThreadWasRunning)return undefined;let curIndex=this.thread.indexOfTimeSlice(this);let cpuSliceWhenLastRunning;while(curIndex>=0){const curSlice=this.thread.timeSlices[curIndex];if(!curSlice.cpuOnWhichThreadWasRunning){curIndex--;continue;}
+cpuSliceWhenLastRunning=curSlice.getAssociatedCpuSlice();break;}
+if(!cpuSliceWhenLastRunning)return undefined;const cpu=cpuSliceWhenLastRunning.cpu;const indexOfSliceOnCpuWhenLastRunning=cpu.indexOf(cpuSliceWhenLastRunning);const nextRunningSlice=cpu.slices[indexOfSliceOnCpuWhenLastRunning+1];if(!nextRunningSlice)return undefined;if(Math.abs(nextRunningSlice.start-cpuSliceWhenLastRunning.end)<0.00001){return nextRunningSlice;}
+return undefined;}};tr.model.EventRegistry.register(ThreadTimeSlice,{name:'threadTimeSlice',pluralName:'threadTimeSlices'});return{ThreadTimeSlice,SCHEDULING_STATE,};});'use strict';tr.exportTo('tr.model',function(){const CompoundEventSelectionState={NOT_SELECTED:0,EVENT_SELECTED:0x1,SOME_ASSOCIATED_EVENTS_SELECTED:0x2,ALL_ASSOCIATED_EVENTS_SELECTED:0x4,EVENT_AND_SOME_ASSOCIATED_SELECTED:0x1|0x2,EVENT_AND_ALL_ASSOCIATED_SELECTED:0x1|0x4};return{CompoundEventSelectionState,};});'use strict';tr.exportTo('tr.model.um',function(){const CompoundEventSelectionState=tr.model.CompoundEventSelectionState;function UserExpectation(parentModel,initiatorType,start,duration){tr.model.TimedEvent.call(this,start);this.associatedEvents=new tr.model.EventSet();this.duration=duration;this.initiatorType_=initiatorType;this.parentModel=parentModel;this.typeInfo_=undefined;this.sourceEvents=new tr.model.EventSet();}
+const INITIATOR_TYPE={KEYBOARD:'Keyboard',MOUSE:'Mouse',MOUSE_WHEEL:'MouseWheel',TAP:'Tap',PINCH:'Pinch',FLING:'Fling',TOUCH:'Touch',SCROLL:'Scroll',CSS:'CSS',WEBGL:'WebGL',VIDEO:'Video',VR:'VR',};UserExpectation.prototype={__proto__:tr.model.TimedEvent.prototype,computeCompoundEvenSelectionState(selection){let cess=CompoundEventSelectionState.NOT_SELECTED;if(selection.contains(this)){cess|=CompoundEventSelectionState.EVENT_SELECTED;}
+if(this.associatedEvents.intersectionIsEmpty(selection)){return cess;}
+const allContained=this.associatedEvents.every(function(event){return selection.contains(event);});if(allContained){cess|=CompoundEventSelectionState.ALL_ASSOCIATED_EVENTS_SELECTED;}else{cess|=CompoundEventSelectionState.SOME_ASSOCIATED_EVENTS_SELECTED;}
+return cess;},get associatedSamples(){const samples=new tr.model.EventSet();this.associatedEvents.forEach(function(event){if(event instanceof tr.model.ThreadSlice){samples.addEventSet(event.overlappingSamples);}});return samples;},get userFriendlyName(){return this.title+' User Expectation at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get stableId(){return('UserExpectation.'+this.guid);},get typeInfo(){if(!this.typeInfo_){this.typeInfo_=UserExpectation.subTypes.findTypeInfo(this.constructor);}
+if(!this.typeInfo_){throw new Error('Unregistered UserExpectation');}
+return this.typeInfo_;},get colorId(){return this.typeInfo.metadata.colorId;},get stageTitle(){return this.typeInfo.metadata.stageTitle;},get initiatorType(){return this.initiatorType_;},get title(){if(!this.initiatorType){return this.stageTitle;}
+return this.initiatorType+' '+this.stageTitle;},get totalCpuMs(){let cpuMs=0;this.associatedEvents.forEach(function(event){if(event.cpuSelfTime){cpuMs+=event.cpuSelfTime;}});return cpuMs;}};const subTypes={};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(subTypes,options);subTypes.addEventListener('will-register',function(e){const metadata=e.typeInfo.metadata;if(metadata.stageTitle===undefined){throw new Error('Registered UserExpectations must provide '+'stageTitle');}
+if(metadata.colorId===undefined){throw new Error('Registered UserExpectations must provide '+'colorId');}});tr.model.EventRegistry.register(UserExpectation,{name:'userExpectation',pluralName:'userExpectations',subTypes});return{UserExpectation,INITIATOR_TYPE,};});'use strict';tr.exportTo('tr.model.um',function(){function ResponseExpectation(parentModel,initiatorTitle,start,duration,opt_isAnimationBegin){tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.isAnimationBegin=opt_isAnimationBegin||false;}
+ResponseExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:ResponseExpectation};tr.model.um.UserExpectation.subTypes.register(ResponseExpectation,{stageTitle:'Response',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_response')});return{ResponseExpectation,};});'use strict';tr.exportTo('tr.e.audits',function(){const SCHEDULING_STATE=tr.model.SCHEDULING_STATE;const Auditor=tr.c.Auditor;const AndroidModelHelper=tr.model.helpers.AndroidModelHelper;const ColorScheme=tr.b.ColorScheme;const Statistics=tr.b.math.Statistics;const FRAME_PERF_CLASS=tr.model.FRAME_PERF_CLASS;const Alert=tr.model.Alert;const EventInfo=tr.model.EventInfo;const Scalar=tr.b.Scalar;const timeDurationInMs=tr.b.Unit.byName.timeDurationInMs;const EXPECTED_FRAME_TIME_MS=16.67;function getStart(e){return e.start;}
+function getDuration(e){return e.duration;}
+function getCpuDuration(e){return(e.cpuDuration!==undefined)?e.cpuDuration:e.duration;}
+function frameIsActivityStart(frame){return frame.associatedEvents.any(x=>x.title==='activityStart');}
+function frameMissedDeadline(frame){return frame.args.deadline&&frame.args.deadline<frame.end;}
+function DocLinkBuilder(){this.docLinks=[];}
+DocLinkBuilder.prototype={addAppVideo(name,videoId){this.docLinks.push({label:'Video Link',textContent:('Android Performance Patterns: '+name),href:'https://www.youtube.com/watch?list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE&v='+videoId});return this;},addDacRef(name,link){this.docLinks.push({label:'Doc Link',textContent:(name+' documentation'),href:'https://developer.android.com/reference/'+link});return this;},build(){return this.docLinks;}};function AndroidAuditor(model){Auditor.call(this,model);const helper=model.getOrCreateHelper(AndroidModelHelper);if(helper.apps.length||helper.surfaceFlinger){this.helper=helper;}}
+AndroidAuditor.viewAlphaAlertInfo_=new EventInfo('Inefficient View alpha usage','Setting an alpha between 0 and 1 has significant performance costs, if one of the fast alpha paths is not used.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('View#setAlpha()','android/view/View.html#setAlpha(float)').build());AndroidAuditor.saveLayerAlertInfo_=new EventInfo('Expensive rendering with Canvas#saveLayer()','Canvas#saveLayer() incurs extremely high rendering cost. They disrupt the rendering pipeline when drawn, forcing a flush of drawing content. Instead use View hardware layers, or static Bitmaps. This enables the offscreen buffers to be reused in between frames, and avoids the disruptive render target switch.',new DocLinkBuilder().addAppVideo('Hidden Cost of Transparency','wIy8g8yNhNk').addDacRef('Canvas#saveLayerAlpha()','android/graphics/Canvas.html#saveLayerAlpha(android.graphics.RectF, int, int)').build());AndroidAuditor.getSaveLayerAlerts_=function(frame){const badAlphaRegEx=/^(.+) alpha caused (unclipped )?saveLayer (\d+)x(\d+)$/;const saveLayerRegEx=/^(unclipped )?saveLayer (\d+)x(\d+)$/;const ret=[];const events=[];frame.associatedEvents.forEach(function(slice){const match=badAlphaRegEx.exec(slice.title);if(match){const args={'view name':match[1],'width':parseInt(match[3]),'height':parseInt(match[4])};ret.push(new Alert(AndroidAuditor.viewAlphaAlertInfo_,slice.start,[slice],args));}else if(saveLayerRegEx.test(slice.title)){events.push(slice);}},this);if(events.length>ret.length){const unclippedSeen=Statistics.sum(events,function(slice){return saveLayerRegEx.exec(slice.title)[1]?1:0;});const clippedSeen=events.length-unclippedSeen;const earliestStart=Statistics.min(events,function(slice){return slice.start;});const args={'Unclipped saveLayer count (especially bad!)':unclippedSeen,'Clipped saveLayer count':clippedSeen};events.push(frame);ret.push(new Alert(AndroidAuditor.saveLayerAlertInfo_,earliestStart,events,args));}
+return ret;};AndroidAuditor.pathAlertInfo_=new EventInfo('Path texture churn','Paths are drawn with a mask texture, so when a path is modified / newly drawn, that texture must be generated and uploaded to the GPU. Ensure that you cache paths between frames and do not unnecessarily call Path#reset(). You can cut down on this cost by sharing Path object instances between drawables/views.');AndroidAuditor.getPathAlert_=function(frame){const uploadRegEx=/^Generate Path Texture$/;const events=frame.associatedEvents.filter(function(event){return event.title==='Generate Path Texture';});const start=Statistics.min(events,getStart);const duration=Statistics.sum(events,getDuration);if(duration<3)return undefined;events.push(frame);return new Alert(AndroidAuditor.pathAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.uploadAlertInfo_=new EventInfo('Expensive Bitmap uploads','Bitmaps that have been modified / newly drawn must be uploaded to the GPU. Since this is expensive if the total number of pixels uploaded is large, reduce the amount of Bitmap churn in this animation/context, per frame.');AndroidAuditor.getUploadAlert_=function(frame){const uploadRegEx=/^Upload (\d+)x(\d+) Texture$/;const events=[];let start=Number.POSITIVE_INFINITY;let duration=0;let pixelsUploaded=0;frame.associatedEvents.forEach(function(event){const match=uploadRegEx.exec(event.title);if(match){events.push(event);start=Math.min(start,event.start);duration+=event.duration;pixelsUploaded+=parseInt(match[1])*parseInt(match[2]);}});if(events.length===0||duration<3)return undefined;const mPixels=(pixelsUploaded/1000000).toFixed(2)+' million';const args={'Pixels uploaded':mPixels,'Time spent':new Scalar(timeDurationInMs,duration)};events.push(frame);return new Alert(AndroidAuditor.uploadAlertInfo_,start,events,args);};AndroidAuditor.ListViewInflateAlertInfo_=new EventInfo('Inflation during ListView recycling','ListView item recycling involved inflating views. Ensure your Adapter#getView() recycles the incoming View, instead of constructing a new one.');AndroidAuditor.ListViewBindAlertInfo_=new EventInfo('Inefficient ListView recycling/rebinding','ListView recycling taking too much time per frame. Ensure your Adapter#getView() binds data efficiently.');AndroidAuditor.getListViewAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='obtainView'||event.title==='setupListItem';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;let hasInflation=false;for(const event of events){if(event.findDescendentSlice('inflate')){hasInflation=true;}}
+const start=Statistics.min(events,getStart);const args={'Time spent':new Scalar(timeDurationInMs,duration)};args['ListView items '+(hasInflation?'inflated':'rebound')]=events.length/2;const eventInfo=hasInflation?AndroidAuditor.ListViewInflateAlertInfo_:AndroidAuditor.ListViewBindAlertInfo_;events.push(frame);return new Alert(eventInfo,start,events,args);};AndroidAuditor.measureLayoutAlertInfo_=new EventInfo('Expensive measure/layout pass','Measure/Layout took a significant time, contributing to jank. Avoid triggering layout during animations.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').build());AndroidAuditor.getMeasureLayoutAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='measure'||event.title==='layout';});const duration=Statistics.sum(events,getCpuDuration);if(events.length===0||duration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.measureLayoutAlertInfo_,start,events,{'Time spent':new Scalar(timeDurationInMs,duration)});};AndroidAuditor.viewDrawAlertInfo_=new EventInfo('Long View#draw()','Recording the drawing commands of invalidated Views took a long time. Avoid significant work in View or Drawable custom drawing, especially allocations or drawing to Bitmaps.',new DocLinkBuilder().addAppVideo('Invalidations, Layouts, and Performance','we6poP0kw6E').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getViewDrawAlert_=function(frame){let slice=undefined;for(const event of frame.associatedEvents){if(event.title==='getDisplayList'||event.title==='Record View#draw()'){slice=event;break;}}
+if(!slice||getCpuDuration(slice)<3)return undefined;return new Alert(AndroidAuditor.viewDrawAlertInfo_,slice.start,[slice,frame],{'Time spent':new Scalar(timeDurationInMs,getCpuDuration(slice))});};AndroidAuditor.blockingGcAlertInfo_=new EventInfo('Blocking Garbage Collection','Blocking GCs are caused by object churn, and made worse by having large numbers of objects in the heap. Avoid allocating objects during animations/scrolling, and recycle Bitmaps to avoid triggering garbage collection.',new DocLinkBuilder().addAppVideo('Garbage Collection in Android','pzfzz50W5Uo').addAppVideo('Avoiding Allocations in onDraw()','HAK5acHQ53E').build());AndroidAuditor.getBlockingGcAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return event.title==='DVM Suspend'||event.title==='GC: Wait For Concurrent';});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<3)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.blockingGcAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.lockContentionAlertInfo_=new EventInfo('Lock contention','UI thread lock contention is caused when another thread holds a lock that the UI thread is trying to use. UI thread progress is blocked until the lock is released. Inspect locking done within the UI thread, and ensure critical sections are short.');AndroidAuditor.getLockContentionAlert_=function(frame){const events=frame.associatedEvents.filter(function(event){return/^Lock Contention on /.test(event.title);});const blockedDuration=Statistics.sum(events,getDuration);if(blockedDuration<1)return undefined;const start=Statistics.min(events,getStart);events.push(frame);return new Alert(AndroidAuditor.lockContentionAlertInfo_,start,events,{'Blocked duration':new Scalar(timeDurationInMs,blockedDuration)});};AndroidAuditor.schedulingAlertInfo_=new EventInfo('Scheduling delay','Work to produce this frame was descheduled for several milliseconds, contributing to jank. Ensure that code on the UI thread doesn\'t block on work being done on other threads, and that background threads (doing e.g. network or bitmap loading) are running at android.os.Process#THREAD_PRIORITY_BACKGROUND or lower so they are less likely to interrupt the UI thread. These background threads should show up with a priority number of 130 or higher in the scheduling section under the Kernel process.');AndroidAuditor.getSchedulingAlert_=function(frame){let totalDuration=0;const totalStats={};for(const ttr of frame.threadTimeRanges){const stats=ttr.thread.getSchedulingStatsForRange(ttr.start,ttr.end);for(const[key,value]of Object.entries(stats)){if(!(key in totalStats)){totalStats[key]=0;}
+totalStats[key]+=value;totalDuration+=value;}}
+if(!(SCHEDULING_STATE.RUNNING in totalStats)||totalDuration===0||totalDuration-totalStats[SCHEDULING_STATE.RUNNING]<3){return;}
+const args={};for(const[key,value]of Object.entries(totalStats)){let newKey=key;if(key===SCHEDULING_STATE.RUNNABLE){newKey='Not scheduled, but runnable';}else if(key===SCHEDULING_STATE.UNINTR_SLEEP){newKey='Blocking I/O delay';}
+args[newKey]=new Scalar(timeDurationInMs,value);}
+return new Alert(AndroidAuditor.schedulingAlertInfo_,frame.start,[frame],args);};AndroidAuditor.prototype={__proto__:Auditor.prototype,renameAndSort_(){this.model.kernel.important=false;this.model.getAllProcesses().forEach(function(process){if(this.helper.surfaceFlinger&&process===this.helper.surfaceFlinger.process){if(!process.name){process.name='SurfaceFlinger';}
+process.sortIndex=Number.NEGATIVE_INFINITY;process.important=false;return;}
+const uiThread=process.getThread(process.pid);if(!process.name&&uiThread&&uiThread.name){if(/^ndroid\./.test(uiThread.name)){uiThread.name='a'+uiThread.name;}
+process.name=uiThread.name;uiThread.name='UI Thread';}
+process.sortIndex=0;for(const tid in process.threads){process.sortIndex-=process.threads[tid].sliceGroup.slices.length;}},this);this.model.getAllThreads().forEach(function(thread){if(thread.tid===thread.parent.pid){thread.sortIndex=-3;}
+if(thread.name==='RenderThread'){thread.sortIndex=-2;}
+if(/^hwuiTask/.test(thread.name)){thread.sortIndex=-1;}});},pushFramesAndJudgeJank_(){let badFramesObserved=0;let framesObserved=0;const surfaceFlinger=this.helper.surfaceFlinger;this.helper.apps.forEach(function(app){app.process.frames=app.getFrames();app.process.frames.forEach(function(frame){if(frame.totalDuration>EXPECTED_FRAME_TIME_MS*2){badFramesObserved+=2;frame.perfClass=FRAME_PERF_CLASS.TERRIBLE;}else if(frame.totalDuration>EXPECTED_FRAME_TIME_MS||frameMissedDeadline(frame)){badFramesObserved++;frame.perfClass=FRAME_PERF_CLASS.BAD;}else{frame.perfClass=FRAME_PERF_CLASS.GOOD;}});framesObserved+=app.process.frames.length;});if(framesObserved){const portionBad=badFramesObserved/framesObserved;if(portionBad>0.3){this.model.faviconHue='red';}else if(portionBad>0.05){this.model.faviconHue='yellow';}else{this.model.faviconHue='green';}}},pushEventInfo_(){const appAnnotator=new AppAnnotator();this.helper.apps.forEach(function(app){if(app.uiThread){appAnnotator.applyEventInfos(app.uiThread.sliceGroup);}
+if(app.renderThread){appAnnotator.applyEventInfos(app.renderThread.sliceGroup);}});},runAnnotate(){if(!this.helper)return;this.renameAndSort_();this.pushFramesAndJudgeJank_();this.pushEventInfo_();this.helper.iterateImportantSlices(function(slice){slice.important=true;});},runAudit(){if(!this.helper)return;const alerts=this.model.alerts;this.helper.apps.forEach(function(app){app.getFrames().forEach(function(frame){alerts.push.apply(alerts,AndroidAuditor.getSaveLayerAlerts_(frame));if(frame.perfClass===FRAME_PERF_CLASS.NEUTRAL||frame.perfClass===FRAME_PERF_CLASS.GOOD){return;}
+let alert=AndroidAuditor.getPathAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getUploadAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getListViewAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getMeasureLayoutAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getViewDrawAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getBlockingGcAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getLockContentionAlert_(frame);if(alert)alerts.push(alert);alert=AndroidAuditor.getSchedulingAlert_(frame);if(alert)alerts.push(alert);});},this);this.addRenderingInteractionRecords();this.addInputInteractionRecords();},addRenderingInteractionRecords(){const events=[];this.helper.apps.forEach(function(app){events.push.apply(events,app.getAnimationAsyncSlices());events.push.apply(events,app.getFrames());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Rendering',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);tr.b.math.mergeRanges(tr.b.math.convertEventsToRanges(events),30,mergerFunction);},addInputInteractionRecords(){const inputSamples=[];this.helper.apps.forEach(function(app){inputSamples.push.apply(inputSamples,app.getInputSamples());});const mergerFunction=function(events){const ir=new tr.model.um.ResponseExpectation(this.model,'Input',events[0].min,events[events.length-1].max-events[0].min);this.model.userModel.expectations.push(ir);}.bind(this);const inputRanges=inputSamples.map(function(sample){return tr.b.math.Range.fromExplicitRange(sample.timestamp,sample.timestamp);});tr.b.math.mergeRanges(inputRanges,30,mergerFunction);}};Auditor.register(AndroidAuditor);function AppAnnotator(){this.titleInfoLookup=new Map();this.titleParentLookup=new Map();this.build_();}
+AppAnnotator.prototype={build_(){const registerEventInfo=function(dict){this.titleInfoLookup.set(dict.title,new EventInfo(dict.title,dict.description,dict.docLinks));if(dict.parents){this.titleParentLookup.set(dict.title,dict.parents);}}.bind(this);registerEventInfo({title:'inflate',description:'Constructing a View hierarchy from pre-processed XML via LayoutInflater#layout. This includes constructing all of the View objects in the hierarchy, and applying styled attributes.'});registerEventInfo({title:'obtainView',description:'Adapter#getView() called to bind content to a recycled View that is being presented.'});registerEventInfo({title:'setupListItem',description:'Attached a newly-bound, recycled View to its parent ListView.'});registerEventInfo({title:'setupGridItem',description:'Attached a newly-bound, recycled View to its parent GridView.'});const choreographerLinks=new DocLinkBuilder().addDacRef('Choreographer','android/view/Choreographer.html').build();registerEventInfo({title:'Choreographer#doFrame',docLinks:choreographerLinks,description:'Choreographer executes frame callbacks for inputs, animations, and rendering traversals. When this work is done, a frame will be presented to the user.'});registerEventInfo({title:'input',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Input callbacks are processed. This generally encompasses dispatching input to Views, as well as any work the Views do to process this input/gesture.'});registerEventInfo({title:'animation',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Animation callbacks are processed. This is generally minimal work, as animations determine progress for the frame, and push new state to animated objects (such as setting View properties).'});registerEventInfo({title:'traversals',parents:['Choreographer#doFrame'],docLinks:choreographerLinks,description:'Primary draw traversals. This is the primary traversal of the View hierarchy, including layout and draw passes.'});const traversalParents=['Choreographer#doFrame','performTraversals'];const layoutLinks=new DocLinkBuilder().addDacRef('View#Layout','android/view/View.html#Layout').build();registerEventInfo({title:'performTraversals',description:'A drawing traversal of the View hierarchy, comprised of all layout and drawing needed to produce the frame.'});registerEventInfo({title:'measure',parents:traversalParents,docLinks:layoutLinks,description:'First of two phases in view hierarchy layout. Views are asked to size themselves according to constraints supplied by their parent. Some ViewGroups may measure a child more than once to help satisfy their own constraints. Nesting ViewGroups that measure children more than once can lead to excessive and repeated work.'});registerEventInfo({title:'layout',parents:traversalParents,docLinks:layoutLinks,description:'Second of two phases in view hierarchy layout, repositioning content and child Views into their new locations.'});const drawString='Draw pass over the View hierarchy. Every invalidated View will have its drawing commands recorded. On Android versions prior to Lollipop, this would also include the issuing of draw commands to the GPU. Starting with Lollipop, it only includes the recording of commands, and syncing that information to the RenderThread.';registerEventInfo({title:'draw',parents:traversalParents,description:drawString});const recordString='Every invalidated View\'s drawing commands are recorded. Each will have View#draw() called, and is passed a Canvas that will record and store its drawing commands until it is next invalidated/rerecorded.';registerEventInfo({title:'getDisplayList',parents:['draw'],description:recordString});registerEventInfo({title:'Record View#draw()',parents:['draw'],description:recordString});registerEventInfo({title:'drawDisplayList',parents:['draw'],description:'Execution of recorded draw commands to generate a frame. This represents the actual formation and issuing of drawing commands to the GPU. On Android L and higher devices, this work is done on a dedicated RenderThread, instead of on the UI Thread.'});registerEventInfo({title:'DrawFrame',description:'RenderThread portion of the standard UI/RenderThread split frame. This represents the actual formation and issuing of drawing commands to the GPU.'});registerEventInfo({title:'doFrame',description:'RenderThread animation frame. Represents drawing work done by the RenderThread on a frame where the UI thread did not produce new drawing content.'});registerEventInfo({title:'syncFrameState',description:'Sync stage between the UI thread and the RenderThread, where the UI thread hands off a frame (including information about modified Views). Time in this method primarily consists of uploading modified Bitmaps to the GPU. After this sync is completed, the UI thread is unblocked, and the RenderThread starts to render the frame.'});registerEventInfo({title:'flush drawing commands',description:'Issuing the now complete drawing commands to the GPU.'});registerEventInfo({title:'eglSwapBuffers',description:'Complete GPU rendering of the frame.'});registerEventInfo({title:'RV Scroll',description:'RecyclerView is calculating a scroll. If there are too many of these in Systrace, some Views inside RecyclerView might be causing it. Try to avoid using EditText, focusable views or handle them with care.'});registerEventInfo({title:'RV OnLayout',description:'OnLayout has been called by the View system. If this shows up too many times in Systrace, make sure the children of RecyclerView do not update themselves directly. This will cause a full re-layout but when it happens via the Adapter notifyItemChanged, RecyclerView can avoid full layout calculation.'});registerEventInfo({title:'RV FullInvalidate',description:'NotifyDataSetChanged or equal has been called. If this is taking a long time, try sending granular notify adapter changes instead of just calling notifyDataSetChanged or setAdapter / swapAdapter. Adding stable ids to your adapter might help.'});registerEventInfo({title:'RV PartialInvalidate',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV OnBindView',description:'RecyclerView is rebinding a View. If this is taking a lot of time, consider optimizing your layout or make sure you are not doing extra operations in onBindViewHolder call.'});registerEventInfo({title:'RV CreateView',description:'RecyclerView is creating a new View. If too many of these are present: 1) There might be a problem in Recycling (e.g. custom Animations that set transient state and prevent recycling or ItemAnimator not implementing the contract properly. See Adapter#onFailedToRecycleView(ViewHolder). 2) There may be too many item view types. Try merging them. 3) There might be too many itemChange animations and not enough space in RecyclerPool. Try increasing your pool size and item cache size.'});registerEventInfo({title:'eglSwapBuffers',description:'The CPU has finished producing drawing commands, and is flushing drawing work to the GPU, and posting that buffer to the consumer (which is often SurfaceFlinger window composition). Once this is completed, the GPU can produce the frame content without any involvement from the CPU.'});},applyEventInfosRecursive_(parentNames,slice){const checkExpectedParentNames=function(expectedParentNames){if(!expectedParentNames)return true;return expectedParentNames.some(function(name){return parentNames.has(name);});};if(this.titleInfoLookup.has(slice.title)){if(checkExpectedParentNames(this.titleParentLookup.get(slice.title))){slice.info=this.titleInfoLookup.get(slice.title);}}
+if(slice.subSlices.length>0){if(!parentNames.has(slice.title)){parentNames.set(slice.title,0);}
+parentNames.set(slice.title,parentNames.get(slice.title)+1);slice.subSlices.forEach(function(subSlice){this.applyEventInfosRecursive_(parentNames,subSlice);},this);parentNames.set(slice.title,parentNames.get(slice.title)-1);if(parentNames.get(slice.title)===0){delete parentNames[slice.title];}}},applyEventInfos(sliceGroup){sliceGroup.topLevelSlices.forEach(function(slice){this.applyEventInfosRecursive_(new Map(),slice);},this);}};return{AndroidAuditor,};});'use strict';tr.exportTo('tr.model',function(){function ObjectSnapshot(objectInstance,ts,args){tr.model.Event.call(this);this.objectInstance=objectInstance;this.ts=ts;this.args=args;}
+ObjectSnapshot.prototype={__proto__:tr.model.Event.prototype,preInitialize(){},initialize(){},referencedAt(item,object,field){},addBoundsToRange(range){range.addValue(this.ts);},get userFriendlyName(){return'Snapshot of '+this.objectInstance.userFriendlyName+' @ '+
+tr.b.Unit.byName.timeStampInMs.format(this.ts);}};tr.model.EventRegistry.register(ObjectSnapshot,{name:'objectSnapshot',pluralName:'objectSnapshots'});return{ObjectSnapshot,};});'use strict';tr.exportTo('tr.model',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectInstance(parent,scopedId,category,name,creationTs,opt_baseTypeName){tr.model.Event.call(this);this.parent=parent;this.scopedId=scopedId;this.category=category;this.baseTypeName=opt_baseTypeName?opt_baseTypeName:name;this.name=name;this.creationTs=creationTs;this.creationTsWasExplicit=false;this.deletionTs=Number.MAX_VALUE;this.deletionTsWasExplicit=false;this.colorId=0;this.bounds=new tr.b.math.Range();this.snapshots=[];this.hasImplicitSnapshots=false;}
+ObjectInstance.prototype={__proto__:tr.model.Event.prototype,get typeName(){return this.name;},addBoundsToRange(range){range.addRange(this.bounds);},addSnapshot(ts,args,opt_name,opt_baseTypeName){if(ts<this.creationTs){throw new Error('Snapshots must be >= instance.creationTs');}
+if(ts>=this.deletionTs){throw new Error('Snapshots cannot be added after '+'an objects deletion timestamp.');}
+let lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts===ts){throw new Error('Snapshots already exists at this time!');}
+if(ts<lastSnapshot.ts){throw new Error('Snapshots must be added in increasing timestamp order');}}
+if(opt_name&&(this.name!==opt_name)){if(!opt_baseTypeName){throw new Error('Must provide base type name for name update');}
+if(this.baseTypeName!==opt_baseTypeName){throw new Error('Cannot update type name: base types dont match');}
+this.name=opt_name;}
+const snapshotConstructor=tr.model.ObjectSnapshot.subTypes.getConstructor(this.category,this.name);const snapshot=new snapshotConstructor(this,ts,args);this.snapshots.push(snapshot);return snapshot;},wasDeleted(ts){let lastSnapshot;if(this.snapshots.length>0){lastSnapshot=this.snapshots[this.snapshots.length-1];if(lastSnapshot.ts>ts){throw new Error('Instance cannot be deleted at ts='+
+ts+'. A snapshot exists that is older.');}}
+this.deletionTs=ts;this.deletionTsWasExplicit=true;},preInitialize(){for(let i=0;i<this.snapshots.length;i++){this.snapshots[i].preInitialize();}},initialize(){for(let i=0;i<this.snapshots.length;i++){this.snapshots[i].initialize();}},isAliveAt(ts){if(ts<this.creationTs&&this.creationTsWasExplicit){return false;}
+if(ts>this.deletionTs){return false;}
+return true;},getSnapshotAt(ts){if(ts<this.creationTs){if(this.creationTsWasExplicit){throw new Error('ts must be within lifetime of this instance');}
+return this.snapshots[0];}
+if(ts>this.deletionTs){throw new Error('ts must be within lifetime of this instance');}
+const snapshots=this.snapshots;const i=tr.b.findIndexInSortedIntervals(snapshots,function(snapshot){return snapshot.ts;},function(snapshot,i){if(i===snapshots.length-1){return snapshots[i].objectInstance.deletionTs;}
+return snapshots[i+1].ts-snapshots[i].ts;},ts);if(i<0){return this.snapshots[0];}
+if(i>=this.snapshots.length){return this.snapshots[this.snapshots.length-1];}
+return this.snapshots[i];},updateBounds(){this.bounds.reset();this.bounds.addValue(this.creationTs);if(this.deletionTs!==Number.MAX_VALUE){this.bounds.addValue(this.deletionTs);}else if(this.snapshots.length>0){this.bounds.addValue(this.snapshots[this.snapshots.length-1].ts);}},shiftTimestampsForward(amount){this.creationTs+=amount;if(this.deletionTs!==Number.MAX_VALUE){this.deletionTs+=amount;}
+this.snapshots.forEach(function(snapshot){snapshot.ts+=amount;});},get userFriendlyName(){return this.typeName+' object '+this.scopedId;}};tr.model.EventRegistry.register(ObjectInstance,{name:'objectInstance',pluralName:'objectInstances'});return{ObjectInstance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;const ObjectInstance=tr.model.ObjectInstance;function BlameContextSnapshot(){ObjectSnapshot.apply(this,arguments);}
+BlameContextSnapshot.prototype={__proto__:ObjectSnapshot.prototype,get parentContext(){if(this.args.parent instanceof BlameContextSnapshot){return this.args.parent;}
+return undefined;},get userFriendlyName(){return'BlameContext';}};function BlameContextInstance(){ObjectInstance.apply(this,arguments);}
+BlameContextInstance.prototype={__proto__:ObjectInstance.prototype,get blameContextType(){throw new Error('Not implemented');}};return{BlameContextSnapshot,BlameContextInstance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const BlameContextSnapshot=tr.e.chrome.BlameContextSnapshot;const BlameContextInstance=tr.e.chrome.BlameContextInstance;function FrameTreeNodeSnapshot(){BlameContextSnapshot.apply(this,arguments);}
+FrameTreeNodeSnapshot.prototype={__proto__:BlameContextSnapshot.prototype,get renderFrame(){if(this.args.renderFrame instanceof tr.e.chrome.RenderFrameSnapshot){return this.args.renderFrame;}
+return undefined;},get url(){return this.args.url;},get userFriendlyName(){return'FrameTreeNode';}};tr.model.ObjectSnapshot.subTypes.register(FrameTreeNodeSnapshot,{typeName:'FrameTreeNode'});function FrameTreeNodeInstance(){BlameContextInstance.apply(this,arguments);}
+FrameTreeNodeInstance.prototype={__proto__:BlameContextInstance.prototype,get blameContextType(){return'Frame';}};tr.model.ObjectInstance.subTypes.register(FrameTreeNodeInstance,{typeName:'FrameTreeNode'});return{FrameTreeNodeSnapshot,FrameTreeNodeInstance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const BlameContextSnapshot=tr.e.chrome.BlameContextSnapshot;const BlameContextInstance=tr.e.chrome.BlameContextInstance;function RenderFrameSnapshot(){BlameContextSnapshot.apply(this,arguments);}
+RenderFrameSnapshot.prototype={__proto__:BlameContextSnapshot.prototype,referencedAt(item,object,field){if(item instanceof tr.e.chrome.FrameTreeNodeSnapshot&&object===item.args&&field==='renderFrame'){this.args.frameTreeNode=item;}},get frameTreeNode(){if(this.args.frameTreeNode instanceof
+tr.e.chrome.FrameTreeNodeSnapshot){return this.args.frameTreeNode;}
+return undefined;},get url(){if(this.frameTreeNode){return this.frameTreeNode.url;}
+return undefined;},get userFriendlyName(){return'RenderFrame';}};tr.model.ObjectSnapshot.subTypes.register(RenderFrameSnapshot,{typeName:'RenderFrame'});function RenderFrameInstance(){BlameContextInstance.apply(this,arguments);}
+RenderFrameInstance.prototype={__proto__:BlameContextInstance.prototype,get blameContextType(){return'Frame';}};tr.model.ObjectInstance.subTypes.register(RenderFrameInstance,{typeName:'RenderFrame'});return{RenderFrameSnapshot,RenderFrameInstance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const BlameContextSnapshot=tr.e.chrome.BlameContextSnapshot;const BlameContextInstance=tr.e.chrome.BlameContextInstance;function TopLevelSnapshot(){BlameContextSnapshot.apply(this,arguments);}
+TopLevelSnapshot.prototype={__proto__:BlameContextSnapshot.prototype,get userFriendlyName(){return'TopLevel';}};tr.model.ObjectSnapshot.subTypes.register(TopLevelSnapshot,{typeName:'TopLevel'});function TopLevelInstance(){BlameContextInstance.apply(this,arguments);}
+TopLevelInstance.prototype={__proto__:BlameContextInstance.prototype,get blameContextType(){return'TopLevel';}};tr.model.ObjectInstance.subTypes.register(TopLevelInstance,{typeName:'TopLevel'});return{TopLevelSnapshot,TopLevelInstance,};});'use strict';tr.exportTo('tr.model',function(){function AsyncSlice(category,title,colorId,start,args,duration,opt_isTopLevel,opt_cpuStart,opt_cpuDuration,opt_argsStripped){tr.model.TimedEvent.call(this,start);this.category=category||'';this.originalTitle=title;this.title=title;this.colorId=colorId;this.args=args;this.startStackFrame=undefined;this.endStackFrame=undefined;this.didNotFinish=false;this.important=false;this.subSlices=[];this.parentContainer_=undefined;this.id=undefined;this.startThread=undefined;this.endThread=undefined;this.cpuStart=undefined;this.cpuDuration=undefined;this.argsStripped=false;this.startStackFrame=undefined;this.endStackFrame=undefined;this.duration=duration;this.isTopLevel=(opt_isTopLevel===true);if(opt_cpuStart!==undefined){this.cpuStart=opt_cpuStart;}
+if(opt_cpuDuration!==undefined){this.cpuDuration=opt_cpuDuration;}
+if(opt_argsStripped!==undefined){this.argsStripped=opt_argsStripped;}}
+AsyncSlice.prototype={__proto__:tr.model.TimedEvent.prototype,get analysisTypeName(){return this.title;},get parentContainer(){return this.parentContainer_;},set parentContainer(parentContainer){this.parentContainer_=parentContainer;for(let i=0;i<this.subSlices.length;i++){const subSlice=this.subSlices[i];if(subSlice.parentContainer===undefined){subSlice.parentContainer=parentContainer;}}},get viewSubGroupTitle(){return this.title;},get viewSubGroupGroupingKey(){return undefined;},get userFriendlyName(){return'Async slice '+this.title+' at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get stableId(){const parentAsyncSliceGroup=this.parentContainer.asyncSliceGroup;return parentAsyncSliceGroup.stableId+'.'+
+parentAsyncSliceGroup.slices.indexOf(this);},*findTopmostSlicesRelativeToThisSlice(eventPredicate,opt_this){if(eventPredicate(this)){yield this;return;}
+for(const s of this.subSlices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate);}},findDescendentSlice(targetTitle){if(!this.subSlices)return undefined;for(let i=0;i<this.subSlices.length;i++){if(this.subSlices[i].title===targetTitle){return this.subSlices[i];}
+const slice=this.subSlices[i].findDescendentSlice(targetTitle);if(slice)return slice;}
+return undefined;},*enumerateAllDescendents(){for(const slice of this.subSlices){yield slice;}
+for(const slice of this.subSlices){if(slice.enumerateAllDescendents!==undefined){yield*slice.enumerateAllDescendents();}}},compareTo(that){return this.title.localeCompare(that.title);}};tr.model.EventRegistry.register(AsyncSlice,{name:'asyncSlice',pluralName:'asyncSlices'});return{AsyncSlice,};});'use strict';tr.exportTo('tr.e.blink',function(){class BlinkSchedulerAsyncSlice extends tr.model.AsyncSlice{get viewSubGroupGroupingKey(){if(this.title.startsWith('FrameScheduler.')){return'Frame'+this.id;}
+if(this.title.startsWith('Scheduler.')){return'Renderer Scheduler';}
+return undefined;}
+get viewSubGroupTitle(){if(this.title.startsWith('FrameScheduler.')){return this.title.substring(15);}
+if(this.title.startsWith('Scheduler.')){return this.title.substring(10);}
+return this.title;}}
+tr.model.AsyncSlice.subTypes.register(BlinkSchedulerAsyncSlice,{categoryParts:['renderer.scheduler','disabled-by-default-renderer.scheduler','disabled-by-default-renderer.scheduler.debug',]});return{BlinkSchedulerAsyncSlice,};});'use strict';tr.exportTo('tr.model.helpers',function(){const MAIN_FRAMETIME_TYPE='main_frametime_type';const IMPL_FRAMETIME_TYPE='impl_frametime_type';const MAIN_RENDERING_STATS='BenchmarkInstrumentation::MainThreadRenderingStats';const IMPL_RENDERING_STATS='BenchmarkInstrumentation::ImplThreadRenderingStats';function getSlicesIntersectingRange(rangeOfInterest,slices){const slicesInFilterRange=[];for(let i=0;i<slices.length;i++){const slice=slices[i];if(rangeOfInterest.intersectsExplicitRangeInclusive(slice.start,slice.end)){slicesInFilterRange.push(slice);}}
+return slicesInFilterRange;}
+function ChromeProcessHelper(modelHelper,process){this.modelHelper=modelHelper;this.process=process;this.telemetryInternalRanges_=undefined;}
+ChromeProcessHelper.prototype={get pid(){return this.process.pid;},isTelemetryInternalEvent(slice){if(this.telemetryInternalRanges_===undefined){this.findTelemetryInternalRanges_();}
+for(const range of this.telemetryInternalRanges_){if(range.containsExplicitRangeInclusive(slice.start,slice.end)){return true;}}
+return false;},findTelemetryInternalRanges_(){this.telemetryInternalRanges_=[];let start=0;for(const thread of Object.values(this.process.threads)){for(const slice of thread.asyncSliceGroup.getDescendantEvents()){if(/^telemetry\.internal\..*\.start$/.test(slice.title)){start=slice.start;}else if(/^telemetry\.internal\..*\.end$/.test(slice.title)&&start!==undefined){this.telemetryInternalRanges_.push(tr.b.math.Range.fromExplicitRange(start,slice.end));start=undefined;}}}},getFrameEventsInRange(frametimeType,range){const titleToGet=(frametimeType===MAIN_FRAMETIME_TYPE?MAIN_RENDERING_STATS:IMPL_RENDERING_STATS);const frameEvents=[];for(const event of this.process.getDescendantEvents()){if(event.title===titleToGet){if(range.intersectsExplicitRangeInclusive(event.start,event.end)){frameEvents.push(event);}}}
+frameEvents.sort(function(a,b){return a.start-b.start;});return frameEvents;}};function getFrametimeDataFromEvents(frameEvents){const frametimeData=[];for(let i=1;i<frameEvents.length;i++){const diff=frameEvents[i].start-frameEvents[i-1].start;frametimeData.push({'x':frameEvents[i].start,'frametime':diff});}
+return frametimeData;}
+return{ChromeProcessHelper,MAIN_FRAMETIME_TYPE,IMPL_FRAMETIME_TYPE,MAIN_RENDERING_STATS,IMPL_RENDERING_STATS,getSlicesIntersectingRange,getFrametimeDataFromEvents,};});'use strict';tr.exportTo('tr.model.helpers',function(){function ChromeBrowserHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrBrowserMain');if(!process.name){process.name=ChromeBrowserHelper.PROCESS_NAME;}}
+ChromeBrowserHelper.PROCESS_NAME='Browser';ChromeBrowserHelper.isBrowserProcess=function(process){return!!process.findAtMostOneThreadNamed('CrBrowserMain');};ChromeBrowserHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get browserName(){const hasInProcessRendererThread=this.process.findAllThreadsNamed('Chrome_InProcRendererThread').length>0;return hasInProcessRendererThread?'webview':'chrome';},get mainThread(){return this.mainThread_;},get rendererHelpers(){return this.modelHelper.rendererHelpers;},getLoadingEventsInRange(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title.indexOf('WebContentsImpl Loading')===0&&rangeOfInterest.intersectsExplicitRangeInclusive(slice.start,slice.end);});},getCommitProvisionalLoadEventsInRange(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return slice.title==='RenderFrameImpl::didCommitProvisionalLoad'&&rangeOfInterest.intersectsExplicitRangeInclusive(slice.start,slice.end);});},get hasLatencyEvents(){let hasLatency=false;for(const thread of this.modelHelper.model.getAllThreads()){for(const event of thread.getDescendantEvents()){if(!event.isTopLevel)continue;if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice)){continue;}
+hasLatency=true;}}
+return hasLatency;},getLatencyEventsInRange(rangeOfInterest){return this.getAllAsyncSlicesMatching(function(slice){return(slice.title.indexOf('InputLatency')===0)&&rangeOfInterest.intersectsExplicitRangeInclusive(slice.start,slice.end);});},getAllAsyncSlicesMatching(pred,opt_this){const events=[];this.iterAllThreads(function(thread){for(const slice of thread.getDescendantEvents()){if(pred.call(opt_this,slice)){events.push(slice);}}});return events;},iterAllThreads(func,opt_this){for(const thread of Object.values(this.process.threads)){func.call(opt_this,thread);}
+for(const rendererHelper of Object.values(this.rendererHelpers)){const rendererProcess=rendererHelper.process;for(const thread of Object.values(rendererProcess.threads)){func.call(opt_this,thread);}}}};return{ChromeBrowserHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){function ChromeGpuHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);if(!process.name){process.name=ChromeGpuHelper.PROCESS_NAME;}}
+ChromeGpuHelper.PROCESS_NAME='GPU Process';ChromeGpuHelper.isGpuProcess=function(process){if(process.findAtMostOneThreadNamed('CrBrowserMain')||process.findAtMostOneThreadNamed('CrRendererMain')){return false;}
+return process.findAllThreadsNamed('CrGpuMain').length>0;};ChromeGpuHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype};return{ChromeGpuHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const NET_CATEGORIES=new Set(['net','netlog','disabled-by-default-netlog','disabled-by-default-network']);class ChromeThreadHelper{constructor(thread){this.thread=thread;}
+getNetworkEvents(){const networkEvents=[];for(const slice of this.thread.asyncSliceGroup.slices){const categories=tr.b.getCategoryParts(slice.category);const isNetEvent=category=>NET_CATEGORIES.has(category);if(categories.filter(isNetEvent).length===0)continue;networkEvents.push(slice);}
+return networkEvents;}}
+return{ChromeThreadHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){const ChromeThreadHelper=tr.model.helpers.ChromeThreadHelper;function ChromeRendererHelper(modelHelper,process){tr.model.helpers.ChromeProcessHelper.call(this,modelHelper,process);this.mainThread_=process.findAtMostOneThreadNamed('CrRendererMain')||process.findAtMostOneThreadNamed('Chrome_InProcRendererThread');this.compositorThread_=process.findAtMostOneThreadNamed('Compositor');this.rasterWorkerThreads_=process.findAllThreadsMatching(function(t){if(t.name===undefined)return false;if(t.name.startsWith('CompositorTileWorker'))return true;if(t.name.startsWith('CompositorRasterWorker'))return true;return false;});this.dedicatedWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('DedicatedWorker');});this.foregroundWorkerThreads_=process.findAllThreadsMatching(function(t){return t.name&&t.name.startsWith('ThreadPoolForegroundWorker');});if(!process.name){process.name=ChromeRendererHelper.PROCESS_NAME;}}
+ChromeRendererHelper.PROCESS_NAME='Renderer';ChromeRendererHelper.isRenderProcess=function(process){if(process.findAtMostOneThreadNamed('CrRendererMain'))return true;if(process.findAtMostOneThreadNamed('Compositor'))return true;return false;};ChromeRendererHelper.isTracingProcess=function(process){return process.labels!==undefined&&process.labels.length===1&&process.labels[0]==='chrome://tracing';};ChromeRendererHelper.prototype={__proto__:tr.model.helpers.ChromeProcessHelper.prototype,get mainThread(){return this.mainThread_;},get compositorThread(){return this.compositorThread_;},get rasterWorkerThreads(){return this.rasterWorkerThreads_;},get dedicatedWorkerThreads(){return this.dedicatedWorkerThreads_;},get foregroundWorkerThreads(){return this.foregroundWorkerThreads_;},get isChromeTracingUI(){return ChromeRendererHelper.isTracingProcess(this.process);},};return{ChromeRendererHelper,};});'use strict';tr.exportTo('tr.model.um',function(){class Segment extends tr.model.TimedEvent{constructor(start,duration){super(start);this.duration=duration;this.expectations_=[];}
+get expectations(){return this.expectations_;}
+clone(){const clone=new Segment(this.start,this.duration);clone.expectations.push(...this.expectations);return clone;}
+addSegment(other){this.duration+=other.duration;this.expectations.push(...other.expectations);}}
+return{Segment,};});'use strict';tr.exportTo('tr.model.helpers',function(){const GESTURE_EVENT='SyntheticGestureController::running';const IR_REG_EXP=/Interaction\.([^/]+)(\/[^/]*)?$/;const ChromeRendererHelper=tr.model.helpers.ChromeRendererHelper;class TelemetryHelper{constructor(modelHelper){this.modelHelper=modelHelper;this.renderersWithIR_=undefined;this.irSegments_=undefined;this.uiSegments_=undefined;this.animationSegments_=undefined;}
+get renderersWithIR(){this.findIRs_();return this.renderersWithIR_;}
+get irSegments(){this.findIRs_();return this.irSegments_;}
+get uiSegments(){this.findIRs_();return this.uiSegments_;}
+get animationSegments(){if(this.animationSegments_===undefined){const model=this.modelHelper.model;this.animationSegments_=model.userModel.segments.filter(segment=>segment.expectations.find(ue=>ue instanceof tr.model.um.AnimationExpectation));this.animationSegments_.sort((x,y)=>x.start-y.start);}
+return this.animationSegments_;}
+findIRs_(){if(this.irSegments_!==undefined)return;this.renderersWithIR_=[];const gestureEvents=[];const interactionRecords=[];const processes=Object.values(this.modelHelper.rendererHelpers).concat(this.modelHelper.browserHelpers).map(processHelper=>processHelper.process);for(const process of processes){let foundIR=false;for(const thread of Object.values(process.threads)){for(const slice of thread.asyncSliceGroup.slices){if(slice.title===GESTURE_EVENT){gestureEvents.push(slice);}else if(IR_REG_EXP.test(slice.title)){interactionRecords.push(slice);foundIR=true;}}}
+if(foundIR&&ChromeRendererHelper.isRenderProcess(process)&&!ChromeRendererHelper.isTracingProcess(process)){this.renderersWithIR_.push(new ChromeRendererHelper(this.modelHelper,process));}}
+this.irSegments_=[];this.uiSegments_=[];for(const ir of interactionRecords){const parts=IR_REG_EXP.exec(ir.title);let gestureEventFound=false;if(parts[1].startsWith('Gesture_')){for(const gestureEvent of gestureEvents){if(ir.boundsRange.intersectsRangeInclusive(gestureEvent.boundsRange)){this.irSegments_.push(new tr.model.um.Segment(gestureEvent.start,gestureEvent.duration));gestureEventFound=true;break;}}}else if(parts[1].startsWith('ui_')){this.uiSegments_.push(new tr.model.um.Segment(ir.start,ir.duration));}
+if(!gestureEventFound){this.irSegments_.push(new tr.model.um.Segment(ir.start,ir.duration));}}
+this.irSegments_.sort((x,y)=>x.start-y.start);this.uiSegments_.sort((x,y)=>x.start-y.start);}}
+return{TelemetryHelper,};});'use strict';tr.exportTo('tr.model.helpers',function(){function findChromeBrowserProcesses(model){return model.getAllProcesses(tr.model.helpers.ChromeBrowserHelper.isBrowserProcess);}
+function findChromeRenderProcesses(model){return model.getAllProcesses(tr.model.helpers.ChromeRendererHelper.isRenderProcess);}
+function findChromeGpuProcess(model){const gpuProcesses=model.getAllProcesses(tr.model.helpers.ChromeGpuHelper.isGpuProcess);if(gpuProcesses.length!==1)return undefined;return gpuProcesses[0];}
+function findTelemetrySurfaceFlingerProcess(model){const surfaceFlingerProcesses=model.getAllProcesses(process=>(process.name==='SurfaceFlinger'));if(surfaceFlingerProcesses.length!==1)return undefined;return surfaceFlingerProcesses[0];}
+function ChromeModelHelper(model){this.model_=model;const browserProcesses=findChromeBrowserProcesses(model);this.browserHelpers_=browserProcesses.map(p=>new tr.model.helpers.ChromeBrowserHelper(this,p));const gpuProcess=findChromeGpuProcess(model);if(gpuProcess){this.gpuHelper_=new tr.model.helpers.ChromeGpuHelper(this,gpuProcess);}else{this.gpuHelper_=undefined;}
+const rendererProcesses_=findChromeRenderProcesses(model);this.rendererHelpers_={};rendererProcesses_.forEach(function(renderProcess){const rendererHelper=new tr.model.helpers.ChromeRendererHelper(this,renderProcess);this.rendererHelpers_[rendererHelper.pid]=rendererHelper;},this);this.surfaceFlingerProcess_=findTelemetrySurfaceFlingerProcess(model);this.chromeBounds_=undefined;this.telemetryHelper_=new tr.model.helpers.TelemetryHelper(this);}
+ChromeModelHelper.guid=tr.b.GUID.allocateSimple();ChromeModelHelper.supportsModel=function(model){if(findChromeBrowserProcesses(model).length)return true;if(findChromeRenderProcesses(model).length)return true;return false;};ChromeModelHelper.prototype={get pid(){throw new Error('woah');},get process(){throw new Error('woah');},get model(){return this.model_;},get browserProcess(){if(this.browserHelper===undefined)return undefined;return this.browserHelper.process;},get browserHelper(){return this.browserHelpers_[0];},get browserHelpers(){return this.browserHelpers_;},get gpuHelper(){return this.gpuHelper_;},get rendererHelpers(){return this.rendererHelpers_;},get surfaceFlingerProcess(){return this.surfaceFlingerProcess_;},get chromeBounds(){if(!this.chromeBounds_){this.chromeBounds_=new tr.b.math.Range();for(const browserHelper of Object.values(this.browserHelpers)){this.chromeBounds_.addRange(browserHelper.process.bounds);}
+for(const rendererHelper of Object.values(this.rendererHelpers)){this.chromeBounds_.addRange(rendererHelper.process.bounds);}
+if(this.gpuHelper){this.chromeBounds_.addRange(this.gpuHelper.process.bounds);}}
+if(this.chromeBounds_.isEmpty){return undefined;}
+return this.chromeBounds_;},get telemetryHelper(){return this.telemetryHelper_;}};return{ChromeModelHelper,};});'use strict';tr.exportTo('tr.e.cc',function(){const AsyncSlice=tr.model.AsyncSlice;const EventSet=tr.model.EventSet;const UI_COMP_NAME='INPUT_EVENT_LATENCY_UI_COMPONENT';const ORIGINAL_COMP_NAME='INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT';const BEGIN_COMP_NAME='INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT';const END_COMP_NAME='INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT';const LEGACY_END_COMP_NAME='INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT';const MAIN_RENDERER_THREAD_NAME='CrRendererMain';const COMPOSITOR_THREAD_NAME='Compositor';const OLD_IPC_FLOW_EVENT='disabled-by-default-ipc.flow';const OLD_POSTTASK_FLOW_EVENT='disabled-by-default-toplevel.flow';const NEW_POSTTASK_FLOW_EVENT='toplevel.flow';const INPUT_EVENT_TYPE_NAMES={CHAR:'Char',CLICK:'GestureClick',CONTEXT_MENU:'ContextMenu',FLING_CANCEL:'GestureFlingCancel',FLING_START:'GestureFlingStart',KEY_DOWN:'KeyDown',KEY_DOWN_RAW:'RawKeyDown',KEY_UP:'KeyUp',LATENCY_SCROLL_UPDATE:'ScrollUpdate',MOUSE_DOWN:'MouseDown',MOUSE_ENTER:'MouseEnter',MOUSE_LEAVE:'MouseLeave',MOUSE_MOVE:'MouseMove',MOUSE_UP:'MouseUp',MOUSE_WHEEL:'MouseWheel',PINCH_BEGIN:'GesturePinchBegin',PINCH_END:'GesturePinchEnd',PINCH_UPDATE:'GesturePinchUpdate',SCROLL_BEGIN:'GestureScrollBegin',SCROLL_END:'GestureScrollEnd',SCROLL_UPDATE:'GestureScrollUpdate',SCROLL_UPDATE_RENDERER:'ScrollUpdate',SHOW_PRESS:'GestureShowPress',TAP:'GestureTap',TAP_CANCEL:'GestureTapCancel',TAP_DOWN:'GestureTapDown',TOUCH_CANCEL:'TouchCancel',TOUCH_END:'TouchEnd',TOUCH_MOVE:'TouchMove',TOUCH_START:'TouchStart',UNKNOWN:'UNKNOWN'};function InputLatencyAsyncSlice(){AsyncSlice.apply(this,arguments);this.associatedEvents_=new EventSet();this.typeName_=undefined;if(!this.isLegacyEvent){this.determineModernTypeName_();}}
+InputLatencyAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get isLegacyEvent(){return this.title==='InputLatency';},get typeName(){if(!this.typeName_){this.determineLegacyTypeName_();}
+return this.typeName_;},checkTypeName_(){if(!this.typeName_){throw new Error('Unable to determine typeName');}
+let found=false;for(const typeName in INPUT_EVENT_TYPE_NAMES){if(this.typeName===INPUT_EVENT_TYPE_NAMES[typeName]){found=true;break;}}
+if(!found){this.typeName_=INPUT_EVENT_TYPE_NAMES.UNKNOWN;}},determineModernTypeName_(){const lastColonIndex=this.title.lastIndexOf(':');if(lastColonIndex<0)return;const characterAfterLastColonIndex=lastColonIndex+1;this.typeName_=this.title.slice(characterAfterLastColonIndex);this.checkTypeName_();},determineLegacyTypeName_(){for(const subSlice of this.enumerateAllDescendents()){const subSliceIsAInputLatencyAsyncSlice=(subSlice instanceof InputLatencyAsyncSlice);if(!subSliceIsAInputLatencyAsyncSlice)continue;if(!subSlice.typeName)continue;if(this.typeName_&&subSlice.typeName_){const subSliceHasDifferentTypeName=(this.typeName_!==subSlice.typeName_);if(subSliceHasDifferentTypeName){throw new Error('InputLatencyAsyncSlice.determineLegacyTypeName_() '+' found multiple typeNames');}}
+this.typeName_=subSlice.typeName_;}
+if(!this.typeName_){throw new Error('InputLatencyAsyncSlice.determineLegacyTypeName_() failed');}
+this.checkTypeName_();},getRendererHelper(sourceSlices){const traceModel=this.startThread.parent.model;const modelHelper=traceModel.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper)return undefined;let mainThread=undefined;let compositorThread=undefined;for(const i in sourceSlices){if(sourceSlices[i].parentContainer.name===MAIN_RENDERER_THREAD_NAME){mainThread=sourceSlices[i].parentContainer;}else if(sourceSlices[i].parentContainer.name===COMPOSITOR_THREAD_NAME){compositorThread=sourceSlices[i].parentContainer;}
+if(mainThread&&compositorThread)break;}
+const rendererHelpers=modelHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(let i=0;i<pids.length;i++){const pid=pids[i];const rendererHelper=rendererHelpers[pid];if(rendererHelper.mainThread===mainThread||rendererHelper.compositorThread===compositorThread){return rendererHelper;}}
+return undefined;},addEntireSliceHierarchy(slice){this.associatedEvents_.push(slice);slice.iterateAllSubsequentSlices(function(subsequentSlice){this.associatedEvents_.push(subsequentSlice);},this);},addDirectlyAssociatedEvents(flowEvents){const slices=[];flowEvents.forEach(function(flowEvent){this.associatedEvents_.push(flowEvent);const newSource=flowEvent.startSlice.mostTopLevelSlice;if(slices.indexOf(newSource)===-1){slices.push(newSource);}},this);const lastFlowEvent=flowEvents[flowEvents.length-1];const lastSource=lastFlowEvent.endSlice.mostTopLevelSlice;if(slices.indexOf(lastSource)===-1){slices.push(lastSource);}
+return slices;},belongToOtherInputs(slice,flowEvents){let fromOtherInputs=false;slice.iterateEntireHierarchy(function(subsequentSlice){if(fromOtherInputs)return;subsequentSlice.inFlowEvents.forEach(function(inflow){if(fromOtherInputs)return;if(inflow.category.indexOf('input')>-1){if(flowEvents.indexOf(inflow)===-1){fromOtherInputs=true;}}},this);},this);return fromOtherInputs;},triggerOtherInputs(event,flowEvents){if(event.outFlowEvents===undefined||event.outFlowEvents.length===0){return false;}
+const flow=event.outFlowEvents[0];const isPostTask=flow.category===NEW_POSTTASK_FLOW_EVENT||flow.category===OLD_POSTTASK_FLOW_EVENT;if(!isPostTask||!flow.endSlice){return false;}
+const endSlice=flow.endSlice;if(this.belongToOtherInputs(endSlice.mostTopLevelSlice,flowEvents)){return true;}
+return false;},followSubsequentSlices(event,queue,visited,flowEvents){let stopFollowing=false;let inputAck=false;event.iterateAllSubsequentSlices(function(slice){if(stopFollowing)return;if(slice.title==='TaskQueueManager::RunTask')return;if(slice.title==='ThreadProxy::ScheduledActionSendBeginMainFrame'){return;}
+if(slice.title==='Scheduler::ScheduleBeginImplFrameDeadline'){if(this.triggerOtherInputs(slice,flowEvents))return;}
+if(slice.title==='CompositorImpl::PostComposite'){if(this.triggerOtherInputs(slice,flowEvents))return;}
+if(slice.title==='InputRouterImpl::ProcessInputEventAck'){inputAck=true;}
+if(inputAck&&slice.title==='InputRouterImpl::FilterAndSendWebInputEvent'){stopFollowing=true;}
+this.followCurrentSlice(slice,queue,visited);},this);},followCurrentSlice(event,queue,visited){event.outFlowEvents.forEach(function(outflow){if((outflow.category===NEW_POSTTASK_FLOW_EVENT||outflow.category===OLD_POSTTASK_FLOW_EVENT||outflow.category===OLD_IPC_FLOW_EVENT)&&outflow.endSlice){this.associatedEvents_.push(outflow);const nextEvent=outflow.endSlice.mostTopLevelSlice;if(!visited.contains(nextEvent)){visited.push(nextEvent);queue.push(nextEvent);}}},this);},backtraceFromDraw(beginImplFrame,visited){const pendingEventQueue=[];pendingEventQueue.push(beginImplFrame.mostTopLevelSlice);while(pendingEventQueue.length!==0){const event=pendingEventQueue.pop();this.addEntireSliceHierarchy(event);event.inFlowEvents.forEach(function(inflow){if(inflow.category===POSTTASK_FLOW_EVENT&&inflow.startSlice){const nextEvent=inflow.startSlice.mostTopLevelSlice;if(!visited.contains(nextEvent)){visited.push(nextEvent);pendingEventQueue.push(nextEvent);}}},this);}},sortRasterizerSlices(rasterWorkerThreads,sortedRasterizerSlices){rasterWorkerThreads.forEach(function(rasterizer){Array.prototype.push.apply(sortedRasterizerSlices,rasterizer.sliceGroup.slices);},this);sortedRasterizerSlices.sort(function(a,b){if(a.start!==b.start){return a.start-b.start;}
+return a.guid-b.guid;});},addRasterizationEvents(prepareTiles,rendererHelper,visited,flowEvents,sortedRasterizerSlices){if(!prepareTiles.args.prepare_tiles_id)return;if(!rendererHelper||!rendererHelper.rasterWorkerThreads){return;}
+const rasterWorkerThreads=rendererHelper.rasterWorkerThreads;const prepareTileId=prepareTiles.args.prepare_tiles_id;const pendingEventQueue=[];if(sortedRasterizerSlices.length===0){this.sortRasterizerSlices(rasterWorkerThreads,sortedRasterizerSlices);}
+let numFinishedTasks=0;const RASTER_TASK_TITLE='RasterizerTaskImpl::RunOnWorkerThread';const IMAGEDECODE_TASK_TITLE='ImageDecodeTaskImpl::RunOnWorkerThread';const FINISHED_TASK_TITLE='TaskSetFinishedTaskImpl::RunOnWorkerThread';for(let i=0;i<sortedRasterizerSlices.length;i++){const task=sortedRasterizerSlices[i];if(task.title===RASTER_TASK_TITLE||task.title===IMAGEDECODE_TASK_TITLE){if(task.args.source_prepare_tiles_id===prepareTileId){this.addEntireSliceHierarchy(task.mostTopLevelSlice);}}else if(task.title===FINISHED_TASK_TITLE){if(task.start>prepareTiles.start){pendingEventQueue.push(task.mostTopLevelSlice);if(++numFinishedTasks===3)break;}}}
+while(pendingEventQueue.length!==0){const event=pendingEventQueue.pop();this.addEntireSliceHierarchy(event);this.followSubsequentSlices(event,pendingEventQueue,visited,flowEvents);}},addOtherCausallyRelatedEvents(rendererHelper,sourceSlices,flowEvents,sortedRasterizerSlices){const pendingEventQueue=[];const visitedEvents=new EventSet();let beginImplFrame=undefined;let prepareTiles=undefined;sortedRasterizerSlices=[];sourceSlices.forEach(function(sourceSlice){if(!visitedEvents.contains(sourceSlice)){visitedEvents.push(sourceSlice);pendingEventQueue.push(sourceSlice);}},this);while(pendingEventQueue.length!==0){const event=pendingEventQueue.pop();this.addEntireSliceHierarchy(event);this.followCurrentSlice(event,pendingEventQueue,visitedEvents);this.followSubsequentSlices(event,pendingEventQueue,visitedEvents,flowEvents);const COMPOSITOR_PREPARE_TILES='TileManager::PrepareTiles';prepareTiles=event.findDescendentSlice(COMPOSITOR_PREPARE_TILES);if(prepareTiles){this.addRasterizationEvents(prepareTiles,rendererHelper,visitedEvents,flowEvents,sortedRasterizerSlices);}
+const COMPOSITOR_ON_BIFD='Scheduler::OnBeginImplFrameDeadline';beginImplFrame=event.findDescendentSlice(COMPOSITOR_ON_BIFD);if(beginImplFrame){this.backtraceFromDraw(beginImplFrame,visitedEvents);}}},get associatedEvents(){if(this.associatedEvents_.length!==0){return this.associatedEvents_;}
+const modelIndices=this.startThread.parent.model.modelIndices;const flowEvents=modelIndices.getFlowEventsWithId(this.id);if(flowEvents.length===0){return this.associatedEvents_;}
+const sourceSlices=this.addDirectlyAssociatedEvents(flowEvents);const rendererHelper=this.getRendererHelper(sourceSlices);this.addOtherCausallyRelatedEvents(rendererHelper,sourceSlices,flowEvents);return this.associatedEvents_;},get inputLatency(){if(!('data'in this.args))return undefined;const data=this.args.data;const endTimeComp=data[END_COMP_NAME]||data[LEGACY_END_COMP_NAME];if(endTimeComp===undefined)return undefined;let latency=0;const endTime=endTimeComp.time;if(ORIGINAL_COMP_NAME in data){latency=endTime-data[ORIGINAL_COMP_NAME].time;}else if(UI_COMP_NAME in data){latency=endTime-data[UI_COMP_NAME].time;}else if(BEGIN_COMP_NAME in data){latency=endTime-data[BEGIN_COMP_NAME].time;}else{throw new Error('No valid begin latency component');}
+return latency;}};const eventTypeNames=['Char','ContextMenu','GestureClick','GestureFlingCancel','GestureFlingStart','GestureScrollBegin','GestureScrollEnd','GestureScrollUpdate','GestureShowPress','GestureTap','GestureTapCancel','GestureTapDown','GesturePinchBegin','GesturePinchEnd','GesturePinchUpdate','KeyDown','KeyUp','MouseDown','MouseEnter','MouseLeave','MouseMove','MouseUp','MouseWheel','RawKeyDown','ScrollUpdate','TouchCancel','TouchEnd','TouchMove','TouchStart'];const allTypeNames=['InputLatency'];eventTypeNames.forEach(function(eventTypeName){allTypeNames.push('InputLatency:'+eventTypeName);allTypeNames.push('InputLatency::'+eventTypeName);});AsyncSlice.subTypes.register(InputLatencyAsyncSlice,{typeNames:allTypeNames,categoryParts:['latencyInfo']});return{InputLatencyAsyncSlice,INPUT_EVENT_TYPE_NAMES,};});'use strict';tr.exportTo('tr.e.chrome',function(){const SAME_AS_PARENT='same-as-parent';const TITLES_FOR_USER_FRIENDLY_CATEGORY={composite:['CompositingInputsUpdater::update','ThreadProxy::SetNeedsUpdateLayers','LayerTreeHost::DoUpdateLayers','LayerTreeHost::UpdateLayers::BuildPropertyTrees','LocalFrameView::pushPaintArtifactToCompositor','LocalFrameView::updateCompositedSelectionIfNeeded','LocalFrameView::RunCompositingLifecyclePhase','UpdateLayerTree',],gc:['minorGC','majorGC','MajorGC','MinorGC','V8.GCScavenger','V8.GCIncrementalMarking','V8.GCIdleNotification','V8.GCContext','V8.GCCompactor','V8GCController::traceDOMWrappers',],iframe_creation:['WebLocalFrameImpl::createChildframe',],imageDecode:['Decode Image','ImageFrameGenerator::decode','ImageFrameGenerator::decodeAndScale','ImageFrameGenerator::decodeToYUV','ImageResourceContent::updateImage',],input:['HitTest','ScrollableArea::scrollPositionChanged','EventHandler::handleMouseMoveEvent',],layout:['IntersectionObserverController::computeTrackedIntersectionObservations','LocalFrameView::invalidateTree','LocalFrameView::layout','LocalFrameView::performLayout','LocalFrameView::performPostLayoutTasks','LocalFrameView::performPreLayoutTasks','LocalFrameView::RunStyleAndLayoutCompositingPhases','Layout','PaintLayer::updateLayerPositionsAfterLayout','ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities','WebViewImpl::updateAllLifecyclePhases','WebViewImpl::beginFrame',],parseHTML:['BackgroundHTMLParser::pumpTokenizer','BackgroundHTMLParser::sendTokensToMainThread','HTMLDocumentParser::didReceiveParsedChunkFromBackgroundParser','HTMLDocumentParser::documentElementAvailable','HTMLDocumentParser::notifyPendingTokenizedChunks','HTMLDocumentParser::processParsedChunkFromBackgroundParser','HTMLDocumentParser::processTokenizedChunkFromBackgroundParser','ParseHTML',],raster:['DisplayListRasterSource::PerformSolidColorAnalysis','Picture::Raster','RasterBufferImpl::Playback','RasterTask','RasterizerTaskImpl::RunOnWorkerThread','SkCanvas::drawImageRect()','SkCanvas::drawPicture()','SkCanvas::drawTextBlob()','TileTaskWorkerPool::PlaybackToMemory',],record:['Canvas2DLayerBridge::flushRecordingOnly','CompositingInputsUpdater::update','CompositingRequirementsUpdater::updateRecursive','ContentLayerDelegate::paintContents','DisplayItemList::Finalize','LocalFrameView::RunPaintLifecyclePhase','LocalFrameView::RunPrePaintLifecyclePhase','Paint','PaintController::commitNewDisplayItems','PaintLayerCompositor::updateIfNeededRecursive','Picture::Record','PictureLayer::Update',],style:['CSSParserImpl::parseStyleSheet.parse','CSSParserImpl::parseStyleSheet.tokenize','Document::rebuildLayoutTree','Document::recalcStyle','Document::updateActiveStyle','Document::updateStyle','Document::updateStyleInvalidationIfNeeded','LocalFrameView::updateStyleAndLayoutIfNeededRecursive','ParseAuthorStyleSheet','RuleSet::addRulesFromSheet','StyleElement::processStyleSheet','StyleEngine::createResolver','StyleEngine::updateActiveStyleSheets','StyleSheetContents::parseAuthorStyleSheet','UpdateLayoutTree',],script_parse_and_compile:['V8.CompileFullCode','V8.NewContext','V8.Parse','V8.ParseLazy','V8.RecompileSynchronous','V8.ScriptCompiler','v8.compile','v8.parseOnBackground',],script_execute:['EvaluateScript','FunctionCall','HTMLParserScriptRunner ExecuteScript','V8.Execute','V8.RunMicrotasks','V8.Task','WindowProxy::initialize','v8.callFunction','v8.run',],resource_loading:['RenderFrameImpl::didFinishDocumentLoad','RenderFrameImpl::didFinishLoad','Resource::appendData','ResourceDispatcher::OnReceivedData','ResourceDispatcher::OnReceivedResponse','ResourceDispatcher::OnRequestComplete','ResourceFetcher::requestResource','WebURLLoaderImpl::Context::Cancel','WebURLLoaderImpl::Context::OnCompletedRequest','WebURLLoaderImpl::Context::OnReceivedData','WebURLLoaderImpl::Context::OnReceivedRedirect','WebURLLoaderImpl::Context::OnReceivedResponse','WebURLLoaderImpl::Context::Start','WebURLLoaderImpl::loadAsynchronously','WebURLLoaderImpl::loadSynchronously','content::mojom::URLLoaderClient',],renderer_misc:['DecodeFont','ThreadState::completeSweep',],v8_runtime:[],[SAME_AS_PARENT]:['SyncChannel::Send',]};const COLOR_FOR_USER_FRIENDLY_CATEGORY=new tr.b.SinebowColorGenerator();const USER_FRIENDLY_CATEGORY_FOR_TITLE=new Map();for(const category in TITLES_FOR_USER_FRIENDLY_CATEGORY){TITLES_FOR_USER_FRIENDLY_CATEGORY[category].forEach(function(title){USER_FRIENDLY_CATEGORY_FOR_TITLE.set(title,category);});}
+const USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY={netlog:'net',overhead:'overhead',startup:'startup',gpu:'gpu',};function ChromeUserFriendlyCategoryDriver(){}
+ChromeUserFriendlyCategoryDriver.fromEvent=function(event){let userFriendlyCategory=USER_FRIENDLY_CATEGORY_FOR_TITLE.get(event.title);if(userFriendlyCategory){if(userFriendlyCategory===SAME_AS_PARENT){if(event.parentSlice){return ChromeUserFriendlyCategoryDriver.fromEvent(event.parentSlice);}}else{return userFriendlyCategory;}}
+const eventCategoryParts=tr.b.getCategoryParts(event.category);for(let i=0;i<eventCategoryParts.length;++i){const eventCategory=eventCategoryParts[i];userFriendlyCategory=USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY[eventCategory];if(userFriendlyCategory){return userFriendlyCategory;}}
+return'other';};ChromeUserFriendlyCategoryDriver.getColor=function(ufc){return COLOR_FOR_USER_FRIENDLY_CATEGORY.colorForKey(ufc);};ChromeUserFriendlyCategoryDriver.ALL_TITLES=['other'];for(const category in TITLES_FOR_USER_FRIENDLY_CATEGORY){if(category===SAME_AS_PARENT)continue;ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
+for(const category of Object.values(USER_FRIENDLY_CATEGORY_FOR_EVENT_CATEGORY)){ChromeUserFriendlyCategoryDriver.ALL_TITLES.push(category);}
+ChromeUserFriendlyCategoryDriver.ALL_TITLES.sort();for(const category of ChromeUserFriendlyCategoryDriver.ALL_TITLES){ChromeUserFriendlyCategoryDriver.getColor(category);}
+return{ChromeUserFriendlyCategoryDriver,};});'use strict';tr.exportTo('tr.model',function(){return{BROWSER_PROCESS_PID_REF:-1,OBJECT_DEFAULT_SCOPE:'ptr',LOCAL_ID_PHASES:new Set(['N','D','O','(',')'])};});'use strict';tr.exportTo('tr.e.audits',function(){const Auditor=tr.c.Auditor;const Alert=tr.model.Alert;const EventInfo=tr.model.EventInfo;function ChromeAuditor(model){Auditor.call(this,model);const modelHelper=this.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper&&modelHelper.browserHelper){this.modelHelper=modelHelper;}else{this.modelHelper=undefined;}}
+function getMissedFrameAlerts(rendererHelpers){const alerts=[];for(const rendererHelper of rendererHelpers){if(!rendererHelper.compositorThread)continue;const thread=rendererHelper.compositorThread;const asyncSlices=Object.values(thread.asyncSliceGroup.slices);for(const slice of asyncSlices){if(slice.title!=='PipelineReporter'||!slice.args.termination_status||slice.args.termination_status!=='missed_frame')continue;const alertSlices=[slice].concat(slice.subSlices);alerts.push(new Alert(new EventInfo('Missed Frame','Frame was not submitted before deadline.'),slice.start,alertSlices));}}
+return alerts;}
+ChromeAuditor.prototype={__proto__:Auditor.prototype,runAnnotate(){if(!this.modelHelper)return;for(const pid in this.modelHelper.rendererHelpers){const rendererHelper=this.modelHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI){rendererHelper.process.important=false;}}},installUserFriendlyCategoryDriverIfNeeded(){this.model.addUserFriendlyCategoryDriver(tr.e.chrome.ChromeUserFriendlyCategoryDriver);},runAudit(){if(!this.modelHelper)return;this.model.replacePIDRefsInPatchups(tr.model.BROWSER_PROCESS_PID_REF,this.modelHelper.browserProcess.pid);this.model.applyObjectRefPatchups();const alerts=getMissedFrameAlerts(Object.values(this.modelHelper.rendererHelpers));this.model.alerts=this.model.alerts.concat(alerts);}};Auditor.register(ChromeAuditor);return{ChromeAuditor,};});'use strict';tr.exportTo('tr.e.chrome',function(){const KNOWN_PROPERTIES={absX:1,absY:1,address:1,anonymous:1,childNeeds:1,children:1,classNames:1,col:1,colSpan:1,float:1,height:1,htmlId:1,name:1,posChildNeeds:1,positioned:1,positionedMovement:1,relX:1,relY:1,relativePositioned:1,row:1,rowSpan:1,selfNeeds:1,stickyPositioned:1,tag:1,width:1};function LayoutObject(snapshot,args){this.snapshot_=snapshot;this.id_=args.address;this.name_=args.name;this.childLayoutObjects_=[];this.otherProperties_={};this.tag_=args.tag;this.relativeRect_=tr.b.math.Rect.fromXYWH(args.relX,args.relY,args.width,args.height);this.absoluteRect_=tr.b.math.Rect.fromXYWH(args.absX,args.absY,args.width,args.height);this.isFloat_=args.float;this.isStickyPositioned_=args.stickyPositioned;this.isPositioned_=args.positioned;this.isRelativePositioned_=args.relativePositioned;this.isAnonymous_=args.anonymous;this.htmlId_=args.htmlId;this.classNames_=args.classNames;this.needsLayoutReasons_=[];if(args.selfNeeds){this.needsLayoutReasons_.push('self');}
+if(args.childNeeds){this.needsLayoutReasons_.push('child');}
+if(args.posChildNeeds){this.needsLayoutReasons_.push('positionedChild');}
+if(args.positionedMovement){this.needsLayoutReasons_.push('positionedMovement');}
+this.tableRow_=args.row;this.tableCol_=args.col;this.tableRowSpan_=args.rowSpan;this.tableColSpan_=args.colSpan;if(args.children){args.children.forEach(function(child){this.childLayoutObjects_.push(new LayoutObject(snapshot,child));}.bind(this));}
+for(const property in args){if(!KNOWN_PROPERTIES[property]){this.otherProperties_[property]=args[property];}}}
+LayoutObject.prototype={get snapshot(){return this.snapshot_;},get id(){return this.id_;},get name(){return this.name_;},get tag(){return this.tag_;},get relativeRect(){return this.relativeRect_;},get absoluteRect(){return this.absoluteRect_;},get isPositioned(){return this.isPositioned_;},get isFloat(){return this.isFloat_;},get isStickyPositioned(){return this.isStickyPositioned_;},get isRelativePositioned(){return this.isRelativePositioned_;},get isAnonymous(){return this.isAnonymous_;},get tableRow(){return this.tableRow_;},get tableCol(){return this.tableCol_;},get tableRowSpan(){return this.tableRowSpan_;},get tableColSpan(){return this.tableColSpan_;},get htmlId(){return this.htmlId_;},get classNames(){return this.classNames_;},get needsLayoutReasons(){return this.needsLayoutReasons_;},get hasChildLayoutObjects(){return this.childLayoutObjects_.length>0;},get childLayoutObjects(){return this.childLayoutObjects_;},traverseTree(cb,opt_this){cb.call(opt_this,this);if(!this.hasChildLayoutObjects)return;this.childLayoutObjects.forEach(function(child){child.traverseTree(cb,opt_this);});},get otherPropertyNames(){const names=[];for(const name in this.otherProperties_){names.push(name);}
+return names;},getProperty(name){return this.otherProperties_[name];},get previousSnapshotLayoutObject(){if(!this.snapshot.previousSnapshot)return undefined;return this.snapshot.previousSnapshot.getLayoutObjectById(this.id);},get nextSnapshotLayoutObject(){if(!this.snapshot.nextSnapshot)return undefined;return this.snapshot.nextSnapshot.getLayoutObjectById(this.id);}};return{LayoutObject,};});'use strict';tr.exportTo('tr.e.chrome',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;const ObjectInstance=tr.model.ObjectInstance;function LayoutTreeInstance(){ObjectInstance.apply(this,arguments);}
+LayoutTreeInstance.prototype={__proto__:ObjectInstance.prototype,};ObjectInstance.subTypes.register(LayoutTreeInstance,{typeName:'LayoutTree'});function LayoutTreeSnapshot(){ObjectSnapshot.apply(this,arguments);this.rootLayoutObject=new tr.e.chrome.LayoutObject(this,this.args);}
+LayoutTreeSnapshot.prototype={__proto__:ObjectSnapshot.prototype,};ObjectSnapshot.subTypes.register(LayoutTreeSnapshot,{typeName:'LayoutTree'});return{LayoutTreeInstance,LayoutTreeSnapshot,};});'use strict';tr.exportTo('tr.model',function(){function EventContainer(){this.guid_=tr.b.GUID.allocateSimple();this.important=true;this.bounds_=new tr.b.math.Range();}
+EventContainer.prototype={get guid(){return this.guid_;},get stableId(){throw new Error('Not implemented');},get bounds(){return this.bounds_;},updateBounds(){throw new Error('Not implemented');},shiftTimestampsForward(amount){throw new Error('Not implemented');},*childEvents(){},*getDescendantEvents(){yield*this.childEvents();for(const container of this.childEventContainers()){yield*container.getDescendantEvents();}},*childEventContainers(){},*getDescendantEventContainers(){yield this;for(const container of this.childEventContainers()){yield*container.getDescendantEventContainers();}},*getDescendantEventsInSortedRanges(ranges,opt_containerPredicate){if(opt_containerPredicate===undefined||opt_containerPredicate(this)){for(const event of this.childEvents()){const i=tr.b.findFirstTrueIndexInSortedArray(ranges,range=>event.start<=range.max);if(i<ranges.length&&event.end>=ranges[i].min)yield event;}}
+for(const container of this.childEventContainers()){yield*container.getDescendantEventsInSortedRanges(ranges,opt_containerPredicate);}},*findTopmostSlicesInThisContainer(eventPredicate,opt_this){},*findTopmostSlices(eventPredicate){for(const ec of this.getDescendantEventContainers()){yield*ec.findTopmostSlicesInThisContainer(eventPredicate);}},*findTopmostSlicesNamed(name){yield*this.findTopmostSlices(e=>e.title===name);}};return{EventContainer,};});'use strict';tr.exportTo('tr.model',function(){const Event=tr.model.Event;const EventRegistry=tr.model.EventRegistry;class ResourceUsageSample extends Event{constructor(series,start,usage){super();this.series_=series;this.start_=start;this.usage_=usage;}
+get series(){return this.series_;}
+get start(){return this.start_;}
+set start(value){this.start_=value;}
+get usage(){return this.usage_;}
+set usage(value){this.usage_=value;}
+addBoundsToRange(range){range.addValue(this.start);}}
+EventRegistry.register(ResourceUsageSample,{name:'resourceUsageSample',pluralName:'resourceUsageSamples'});return{ResourceUsageSample,};});'use strict';tr.exportTo('tr.model',function(){const ResourceUsageSample=tr.model.ResourceUsageSample;class ResourceUsageSeries extends tr.model.EventContainer{constructor(device){super();this.device_=device;this.samples_=[];}
+get device(){return this.device_;}
+get samples(){return this.samples_;}
+get stableId(){return this.device_.stableId+'.ResourceUsageSeries';}
+addUsageSample(ts,val){const sample=new ResourceUsageSample(this,ts,val);this.samples_.push(sample);return sample;}
+computeResourceTimeConsumedInMs(start,end){const measurementRange=tr.b.math.Range.fromExplicitRange(start,end);let resourceTimeInMs=0;let startIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,start)-1;const endIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,end);if(startIndex<0)startIndex=0;for(let i=startIndex;i<endIndex;i++){const sample=this.samples[i];const nextSample=this.samples[i+1];const sampleRange=new tr.b.math.Range();sampleRange.addValue(sample.start);sampleRange.addValue(nextSample?nextSample.start:sample.start);const intersectionRangeInMs=measurementRange.findIntersection(sampleRange);resourceTimeInMs+=intersectionRangeInMs.duration*sample.usage;}
+return resourceTimeInMs;}
+getSamplesWithinRange(start,end){const startIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,start);const endIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,end);return this.samples.slice(startIndex,endIndex);}
+shiftTimestampsForward(amount){for(let i=0;i<this.samples_.length;++i){this.samples_[i].start+=amount;}}
+updateBounds(){this.bounds.reset();if(this.samples_.length===0)return;this.bounds.addValue(this.samples_[0].start);this.bounds.addValue(this.samples_[this.samples_.length-1].start);}*childEvents(){yield*this.samples_;}}
+return{ResourceUsageSeries,};});'use strict';tr.exportTo('tr.e.audits',function(){class CpuUsageAuditor extends tr.c.Auditor{constructor(model){super();this.model_=model;}
+runAnnotate(){this.model_.device.cpuUsageSeries=this.computeCpuUsageSeries_(this.model_.bounds.min,this.model_.bounds.max,this.computeCpuUsage_());}
+computeBinSize_(start,end){const MIN_BIN_SIZE_MS=1.0;const MAX_NUM_BINS=100000;const interval=end-start;let binSize=MIN_BIN_SIZE_MS;while(binSize*MAX_NUM_BINS<interval)binSize*=2;return binSize;}
+computeCpuUsageSeries_(start,end,usageRecords){const series=new tr.model.ResourceUsageSeries();if(start===undefined||usageRecords.length===0)return series;const binSize=this.computeBinSize_(start,end);const numBins=Math.ceil((end-start)/binSize);const arr=new Array(numBins).fill(0);for(const record of usageRecords){const firstIndex=Math.ceil((record.start-start)/binSize);const lastIndex=Math.floor((record.end-start)/binSize);for(let i=firstIndex;i<=lastIndex;i++)arr[i]+=record.usage;}
+for(let i=0;i<numBins;i++){series.addUsageSample(start+(i*binSize),arr[i]);}
+return series;}
+computeCpuUsage_(){const model=this.model_;const result=[];for(const pid in model.processes){for(const e of model.processes[pid].getDescendantEvents()){if(!(e instanceof tr.model.ThreadSlice)||e.duration===0||e.cpuDuration===undefined){continue;}
+if(e.selfTime===0||e.selfTime===undefined||e.cpuSelfTime===undefined){continue;}
+const usage=tr.b.math.clamp(e.cpuSelfTime/e.selfTime,0,1);let lastTime=e.start;for(const subslice of e.subSlices){result.push({usage,start:lastTime,end:subslice.start});lastTime=subslice.end;}
+result.push({usage,start:lastTime,end:e.end});}}
+return result;}}
+tr.c.Auditor.register(CpuUsageAuditor);return{CpuUsageAuditor};});'use strict';tr.exportTo('tr.e.img',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function ImageSnapshot(){ObjectSnapshot.apply(this,arguments);}
+ImageSnapshot.prototype={__proto__:ObjectSnapshot.prototype,initialize(){this.data_=this.args.data;this.type_=this.args.params.type;},get data(){return this.data_;},get type(){return this.type_;},};ObjectSnapshot.subTypes.register(ImageSnapshot,{typeNames:['gfx::Image']});return{ImageSnapshot,};});'use strict';tr.exportTo('tr.b',function(){function Base64(){}
+function b64ToUint6(nChr){if(nChr>64&&nChr<91)return nChr-65;if(nChr>96&&nChr<123)return nChr-71;if(nChr>47&&nChr<58)return nChr+4;if(nChr===43)return 62;if(nChr===47)return 63;return 0;}
+Base64.getDecodedBufferLength=function(input){let pad=0;if(input.substr(-2)==='=='){pad=2;}else if(input.substr(-1)==='='){pad=1;}
+return((input.length*3+1)>>2)-pad;};Base64.EncodeArrayBufferToString=function(input){let binary='';const bytes=new Uint8Array(input);const len=bytes.byteLength;for(let i=0;i<len;i++){binary+=String.fromCharCode(bytes[i]);}
+return btoa(binary);};Base64.DecodeToTypedArray=function(input,output){const nInLen=input.length;const nOutLen=Base64.getDecodedBufferLength(input);let nMod3=0;let nMod4=0;let nUint24=0;let nOutIdx=0;if(nOutLen>output.byteLength){throw new Error('Output buffer too small to decode.');}
+for(let nInIdx=0;nInIdx<nInLen;nInIdx++){nMod4=nInIdx&3;nUint24|=b64ToUint6(input.charCodeAt(nInIdx))<<18-6*nMod4;if(nMod4===3||nInLen-nInIdx===1){for(nMod3=0;nMod3<3&&nOutIdx<nOutLen;nMod3++,nOutIdx++){output.setUint8(nOutIdx,nUint24>>>(16>>>nMod3&24)&255);}
+nUint24=0;}}
+return nOutLen;};Base64.btoa=function(input){return btoa(input);};Base64.atob=function(input){return atob(input);};return{Base64,};});'use strict';tr.exportTo('tr.e.importer.etw',function(){function Parser(importer){this.importer=importer;this.model=importer.model;}
+Parser.prototype={__proto__:Object.prototype};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseClass=Parser;tr.b.decorateExtensionRegistry(Parser,options);return{Parser,};});'use strict';tr.exportTo('tr.e.importer.etw',function(){const Parser=tr.e.importer.etw.Parser;const guid='68FDD900-4A3E-11D1-84F4-0000F80464E3';const kEventTraceHeaderOpcode=0;function EventTraceParser(importer){Parser.call(this,importer);importer.registerEventHandler(guid,kEventTraceHeaderOpcode,EventTraceParser.prototype.decodeHeader.bind(this));}
+EventTraceParser.prototype={__proto__:Parser.prototype,decodeFields(header,decoder){if(header.version!==2){throw new Error('Incompatible EventTrace event version.');}
+const bufferSize=decoder.decodeUInt32();const version=decoder.decodeUInt32();const providerVersion=decoder.decodeUInt32();const numberOfProcessors=decoder.decodeUInt32();const endTime=decoder.decodeUInt64ToString();const timerResolution=decoder.decodeUInt32();const maxFileSize=decoder.decodeUInt32();const logFileMode=decoder.decodeUInt32();const buffersWritten=decoder.decodeUInt32();const startBuffers=decoder.decodeUInt32();const pointerSize=decoder.decodeUInt32();const eventsLost=decoder.decodeUInt32();const cpuSpeed=decoder.decodeUInt32();const loggerName=decoder.decodeUInteger(header.is64);const logFileName=decoder.decodeUInteger(header.is64);const timeZoneInformation=decoder.decodeTimeZoneInformation();const padding=decoder.decodeUInt32();const bootTime=decoder.decodeUInt64ToString();const perfFreq=decoder.decodeUInt64ToString();const startTime=decoder.decodeUInt64ToString();const reservedFlags=decoder.decodeUInt32();const buffersLost=decoder.decodeUInt32();const sessionNameString=decoder.decodeW16String();const logFileNameString=decoder.decodeW16String();return{bufferSize,version,providerVersion,numberOfProcessors,endTime,timerResolution,maxFileSize,logFileMode,buffersWritten,startBuffers,pointerSize,eventsLost,cpuSpeed,loggerName,logFileName,timeZoneInformation,bootTime,perfFreq,startTime,reservedFlags,buffersLost,sessionNameString,logFileNameString};},decodeHeader(header,decoder){const fields=this.decodeFields(header,decoder);return true;}};Parser.register(EventTraceParser);return{EventTraceParser,};});'use strict';tr.exportTo('tr.e.importer.etw',function(){const Parser=tr.e.importer.etw.Parser;const guid='3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C';const kProcessStartOpcode=1;const kProcessEndOpcode=2;const kProcessDCStartOpcode=3;const kProcessDCEndOpcode=4;const kProcessDefunctOpcode=39;function ProcessParser(importer){Parser.call(this,importer);importer.registerEventHandler(guid,kProcessStartOpcode,ProcessParser.prototype.decodeStart.bind(this));importer.registerEventHandler(guid,kProcessEndOpcode,ProcessParser.prototype.decodeEnd.bind(this));importer.registerEventHandler(guid,kProcessDCStartOpcode,ProcessParser.prototype.decodeDCStart.bind(this));importer.registerEventHandler(guid,kProcessDCEndOpcode,ProcessParser.prototype.decodeDCEnd.bind(this));importer.registerEventHandler(guid,kProcessDefunctOpcode,ProcessParser.prototype.decodeDefunct.bind(this));}
+ProcessParser.prototype={__proto__:Parser.prototype,decodeFields(header,decoder){if(header.version>5){throw new Error('Incompatible Process event version.');}
+let pageDirectoryBase;if(header.version===1){pageDirectoryBase=decoder.decodeUInteger(header.is64);}
+let uniqueProcessKey;if(header.version>=2){uniqueProcessKey=decoder.decodeUInteger(header.is64);}
+const processId=decoder.decodeUInt32();const parentId=decoder.decodeUInt32();let sessionId;let exitStatus;if(header.version>=1){sessionId=decoder.decodeUInt32();exitStatus=decoder.decodeInt32();}
+let directoryTableBase;if(header.version>=3){directoryTableBase=decoder.decodeUInteger(header.is64);}
+let flags;if(header.version>=4){flags=decoder.decodeUInt32();}
+const userSID=decoder.decodeSID(header.is64);let imageFileName;if(header.version>=1){imageFileName=decoder.decodeString();}
+let commandLine;if(header.version>=2){commandLine=decoder.decodeW16String();}
+let packageFullName;let applicationId;if(header.version>=4){packageFullName=decoder.decodeW16String();applicationId=decoder.decodeW16String();}
+let exitTime;if(header.version===5&&header.opcode===kProcessDefunctOpcode){exitTime=decoder.decodeUInt64ToString();}
+return{pageDirectoryBase,uniqueProcessKey,processId,parentId,sessionId,exitStatus,directoryTableBase,flags,userSID,imageFileName,commandLine,packageFullName,applicationId,exitTime};},decodeStart(header,decoder){const fields=this.decodeFields(header,decoder);const process=this.model.getOrCreateProcess(fields.processId);if(process.hasOwnProperty('has_ended')){throw new Error('Process clash detected.');}
+process.name=fields.imageFileName;return true;},decodeEnd(header,decoder){const fields=this.decodeFields(header,decoder);const process=this.model.getOrCreateProcess(fields.processId);process.has_ended=true;return true;},decodeDCStart(header,decoder){const fields=this.decodeFields(header,decoder);const process=this.model.getOrCreateProcess(fields.processId);if(process.hasOwnProperty('has_ended')){throw new Error('Process clash detected.');}
+process.name=fields.imageFileName;return true;},decodeDCEnd(header,decoder){const fields=this.decodeFields(header,decoder);const process=this.model.getOrCreateProcess(fields.processId);process.has_ended=true;return true;},decodeDefunct(header,decoder){const fields=this.decodeFields(header,decoder);return true;}};Parser.register(ProcessParser);return{ProcessParser,};});'use strict';tr.exportTo('tr.e.importer.etw',function(){const Parser=tr.e.importer.etw.Parser;const guid='3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';const kThreadStartOpcode=1;const kThreadEndOpcode=2;const kThreadDCStartOpcode=3;const kThreadDCEndOpcode=4;const kThreadCSwitchOpcode=36;function ThreadParser(importer){Parser.call(this,importer);importer.registerEventHandler(guid,kThreadStartOpcode,ThreadParser.prototype.decodeStart.bind(this));importer.registerEventHandler(guid,kThreadEndOpcode,ThreadParser.prototype.decodeEnd.bind(this));importer.registerEventHandler(guid,kThreadDCStartOpcode,ThreadParser.prototype.decodeDCStart.bind(this));importer.registerEventHandler(guid,kThreadDCEndOpcode,ThreadParser.prototype.decodeDCEnd.bind(this));importer.registerEventHandler(guid,kThreadCSwitchOpcode,ThreadParser.prototype.decodeCSwitch.bind(this));}
+ThreadParser.prototype={__proto__:Parser.prototype,decodeFields(header,decoder){if(header.version>3){throw new Error('Incompatible Thread event version '+
+header.version+'.');}
+const processId=decoder.decodeUInt32();const threadId=decoder.decodeUInt32();let stackBase;let stackLimit;let userStackBase;let userStackLimit;let affinity;let startAddr;let win32StartAddr;let tebBase;let subProcessTag;let basePriority;let pagePriority;let ioPriority;let threadFlags;let waitMode;if(header.version===1){if(header.opcode===kThreadStartOpcode||header.opcode===kThreadDCStartOpcode){stackBase=decoder.decodeUInteger(header.is64);stackLimit=decoder.decodeUInteger(header.is64);userStackBase=decoder.decodeUInteger(header.is64);userStackLimit=decoder.decodeUInteger(header.is64);startAddr=decoder.decodeUInteger(header.is64);win32StartAddr=decoder.decodeUInteger(header.is64);waitMode=decoder.decodeInt8();decoder.skip(3);}}else{stackBase=decoder.decodeUInteger(header.is64);stackLimit=decoder.decodeUInteger(header.is64);userStackBase=decoder.decodeUInteger(header.is64);userStackLimit=decoder.decodeUInteger(header.is64);if(header.version===2){startAddr=decoder.decodeUInteger(header.is64);}else{affinity=decoder.decodeUInteger(header.is64);}
+win32StartAddr=decoder.decodeUInteger(header.is64);tebBase=decoder.decodeUInteger(header.is64);subProcessTag=decoder.decodeUInt32();if(header.version===3){basePriority=decoder.decodeUInt8();pagePriority=decoder.decodeUInt8();ioPriority=decoder.decodeUInt8();threadFlags=decoder.decodeUInt8();}}
+return{processId,threadId,stackBase,stackLimit,userStackBase,userStackLimit,affinity,startAddr,win32StartAddr,tebBase,subProcessTag,waitMode,basePriority,pagePriority,ioPriority,threadFlags};},decodeCSwitchFields(header,decoder){if(header.version<2||header.version>4){throw new Error('Incompatible cswitch event version '+
+header.version+'.');}
+const newThreadId=decoder.decodeUInt32();const oldThreadId=decoder.decodeUInt32();const newThreadPriority=decoder.decodeInt8();const oldThreadPriority=decoder.decodeInt8();const previousCState=decoder.decodeUInt8();const spareByte=decoder.decodeInt8();const oldThreadWaitReason=decoder.decodeInt8();const oldThreadWaitMode=decoder.decodeInt8();const oldThreadState=decoder.decodeInt8();const oldThreadWaitIdealProcessor=decoder.decodeInt8();const newThreadWaitTime=decoder.decodeUInt32();const reserved=decoder.decodeUInt32();return{newThreadId,oldThreadId,newThreadPriority,oldThreadPriority,previousCState,spareByte,oldThreadWaitReason,oldThreadWaitMode,oldThreadState,oldThreadWaitIdealProcessor,newThreadWaitTime,reserved};},decodeStart(header,decoder){const fields=this.decodeFields(header,decoder);this.importer.createThreadIfNeeded(fields.processId,fields.threadId);return true;},decodeEnd(header,decoder){const fields=this.decodeFields(header,decoder);this.importer.removeThreadIfPresent(fields.threadId);return true;},decodeDCStart(header,decoder){const fields=this.decodeFields(header,decoder);this.importer.createThreadIfNeeded(fields.processId,fields.threadId);return true;},decodeDCEnd(header,decoder){const fields=this.decodeFields(header,decoder);this.importer.removeThreadIfPresent(fields.threadId);return true;},decodeCSwitch(header,decoder){const fields=this.decodeCSwitchFields(header,decoder);const cpu=this.importer.getOrCreateCpu(header.cpu);const newThread=this.importer.getThreadFromWindowsTid(fields.newThreadId);let newThreadName;if(newThread&&newThread.userFriendlyName){newThreadName=newThread.userFriendlyName;}else{const newProcessId=this.importer.getPidFromWindowsTid(fields.newThreadId);const newProcess=this.model.getProcess(newProcessId);let newProcessName;if(newProcess){newProcessName=newProcess.name;}else{newProcessName='Unknown process';}
+newThreadName=newProcessName+' (tid '+fields.newThreadId+')';}
+cpu.switchActiveThread(header.timestamp,{},fields.newThreadId,newThreadName,fields);return true;}};Parser.register(ThreadParser);return{ThreadParser,};});'use strict';tr.exportTo('tr.b',function(){function max(a,b){if(a===undefined)return b;if(b===undefined)return a;return Math.max(a,b);}
+function IntervalTree(beginPositionCb,endPositionCb){this.beginPositionCb_=beginPositionCb;this.endPositionCb_=endPositionCb;this.root_=undefined;this.size_=0;}
+IntervalTree.prototype={insert(datum){const startPosition=this.beginPositionCb_(datum);const endPosition=this.endPositionCb_(datum);const node=new IntervalTreeNode(datum,startPosition,endPosition);this.size_++;this.root_=this.insertNode_(this.root_,node);this.root_.colour=Colour.BLACK;return datum;},insertNode_(root,node){if(root===undefined)return node;if(root.leftNode&&root.leftNode.isRed&&root.rightNode&&root.rightNode.isRed){this.flipNodeColour_(root);}
+if(node.key<root.key){root.leftNode=this.insertNode_(root.leftNode,node);}else if(node.key===root.key){root.merge(node);}else{root.rightNode=this.insertNode_(root.rightNode,node);}
+if(root.rightNode&&root.rightNode.isRed&&(root.leftNode===undefined||!root.leftNode.isRed)){root=this.rotateLeft_(root);}
+if(root.leftNode&&root.leftNode.isRed&&root.leftNode.leftNode&&root.leftNode.leftNode.isRed){root=this.rotateRight_(root);}
+return root;},rotateRight_(node){const sibling=node.leftNode;node.leftNode=sibling.rightNode;sibling.rightNode=node;sibling.colour=node.colour;node.colour=Colour.RED;return sibling;},rotateLeft_(node){const sibling=node.rightNode;node.rightNode=sibling.leftNode;sibling.leftNode=node;sibling.colour=node.colour;node.colour=Colour.RED;return sibling;},flipNodeColour_(node){node.colour=this.flipColour_(node.colour);node.leftNode.colour=this.flipColour_(node.leftNode.colour);node.rightNode.colour=this.flipColour_(node.rightNode.colour);},flipColour_(colour){return colour===Colour.RED?Colour.BLACK:Colour.RED;},updateHighValues(){this.updateHighValues_(this.root_);},updateHighValues_(node){if(node===undefined)return undefined;node.maxHighLeft=this.updateHighValues_(node.leftNode);node.maxHighRight=this.updateHighValues_(node.rightNode);return max(max(node.maxHighLeft,node.highValue),node.maxHighRight);},validateFindArguments_(queryLow,queryHigh){if(queryLow===undefined||queryHigh===undefined){throw new Error('queryLow and queryHigh must be defined');}
+if((typeof queryLow!=='number')||(typeof queryHigh!=='number')){throw new Error('queryLow and queryHigh must be numbers');}},findIntersection(queryLow,queryHigh){this.validateFindArguments_(queryLow,queryHigh);if(this.root_===undefined)return[];const ret=[];this.root_.appendIntersectionsInto_(ret,queryLow,queryHigh);return ret;},get size(){return this.size_;},get root(){return this.root_;},dump_(){if(this.root_===undefined)return[];return this.root_.dump();}};const Colour={RED:'red',BLACK:'black'};function IntervalTreeNode(datum,lowValue,highValue){this.lowValue_=lowValue;this.data_=[{datum,high:highValue,low:lowValue}];this.colour_=Colour.RED;this.parentNode_=undefined;this.leftNode_=undefined;this.rightNode_=undefined;this.maxHighLeft_=undefined;this.maxHighRight_=undefined;}
+IntervalTreeNode.prototype={appendIntersectionsInto_(ret,queryLow,queryHigh){if(this.lowValue_>=queryHigh){if(!this.leftNode_)return;return this.leftNode_.appendIntersectionsInto_(ret,queryLow,queryHigh);}
+if(this.maxHighLeft_>queryLow){this.leftNode_.appendIntersectionsInto_(ret,queryLow,queryHigh);}
+if(this.highValue>queryLow){for(let i=(this.data.length-1);i>=0;--i){if(this.data[i].high<queryLow)break;ret.push(this.data[i].datum);}}
+if(this.rightNode_){this.rightNode_.appendIntersectionsInto_(ret,queryLow,queryHigh);}},get colour(){return this.colour_;},set colour(colour){this.colour_=colour;},get key(){return this.lowValue_;},get lowValue(){return this.lowValue_;},get highValue(){return this.data_[this.data_.length-1].high;},set leftNode(left){this.leftNode_=left;},get leftNode(){return this.leftNode_;},get hasLeftNode(){return this.leftNode_!==undefined;},set rightNode(right){this.rightNode_=right;},get rightNode(){return this.rightNode_;},get hasRightNode(){return this.rightNode_!==undefined;},set parentNode(parent){this.parentNode_=parent;},get parentNode(){return this.parentNode_;},get isRootNode(){return this.parentNode_===undefined;},set maxHighLeft(high){this.maxHighLeft_=high;},get maxHighLeft(){return this.maxHighLeft_;},set maxHighRight(high){this.maxHighRight_=high;},get maxHighRight(){return this.maxHighRight_;},get data(){return this.data_;},get isRed(){return this.colour_===Colour.RED;},merge(node){for(let i=0;i<node.data.length;i++){this.data_.push(node.data[i]);}
+this.data_.sort(function(a,b){return a.high-b.high;});},dump(){const ret={};if(this.leftNode_){ret.left=this.leftNode_.dump();}
+ret.data=this.data_.map(function(d){return[d.low,d.high];});if(this.rightNode_){ret.right=this.rightNode_.dump();}
+return ret;}};return{IntervalTree,};});'use strict';tr.exportTo('tr.b.math',function(){const tmpVec2s=[];for(let i=0;i<8;i++){tmpVec2s[i]=vec2.create();}
+const tmpVec2a=vec4.create();const tmpVec4a=vec4.create();const tmpVec4b=vec4.create();const tmpMat4=mat4.create();const tmpMat4b=mat4.create();const p00=vec2.createXY(0,0);const p10=vec2.createXY(1,0);const p01=vec2.createXY(0,1);const p11=vec2.createXY(1,1);const lerpingVecA=vec2.create();const lerpingVecB=vec2.create();function lerpVec2(out,a,b,amt){vec2.scale(lerpingVecA,a,amt);vec2.scale(lerpingVecB,b,1-amt);vec2.add(out,lerpingVecA,lerpingVecB);vec2.normalize(out,out);return out;}
+function Quad(){this.p1=vec2.create();this.p2=vec2.create();this.p3=vec2.create();this.p4=vec2.create();}
+Quad.fromXYWH=function(x,y,w,h){const q=new Quad();vec2.set(q.p1,x,y);vec2.set(q.p2,x+w,y);vec2.set(q.p3,x+w,y+h);vec2.set(q.p4,x,y+h);return q;};Quad.fromRect=function(r){return new Quad.fromXYWH(r.x,r.y,r.width,r.height);};Quad.from4Vecs=function(p1,p2,p3,p4){const q=new Quad();vec2.set(q.p1,p1[0],p1[1]);vec2.set(q.p2,p2[0],p2[1]);vec2.set(q.p3,p3[0],p3[1]);vec2.set(q.p4,p4[0],p4[1]);return q;};Quad.from8Array=function(arr){if(arr.length!==8){throw new Error('Array must be 8 long');}
+const q=new Quad();q.p1[0]=arr[0];q.p1[1]=arr[1];q.p2[0]=arr[2];q.p2[1]=arr[3];q.p3[0]=arr[4];q.p3[1]=arr[5];q.p4[0]=arr[6];q.p4[1]=arr[7];return q;};Quad.prototype={pointInside(point){return pointInImplicitQuad(point,this.p1,this.p2,this.p3,this.p4);},boundingRect(){const x0=Math.min(this.p1[0],this.p2[0],this.p3[0],this.p4[0]);const y0=Math.min(this.p1[1],this.p2[1],this.p3[1],this.p4[1]);const x1=Math.max(this.p1[0],this.p2[0],this.p3[0],this.p4[0]);const y1=Math.max(this.p1[1],this.p2[1],this.p3[1],this.p4[1]);return new tr.b.math.Rect.fromXYWH(x0,y0,x1-x0,y1-y0);},clone(){const q=new Quad();vec2.copy(q.p1,this.p1);vec2.copy(q.p2,this.p2);vec2.copy(q.p3,this.p3);vec2.copy(q.p4,this.p4);return q;},scale(s){const q=new Quad();this.scaleFast(q,s);return q;},scaleFast(dstQuad,s){vec2.copy(dstQuad.p1,this.p1,s);vec2.copy(dstQuad.p2,this.p2,s);vec2.copy(dstQuad.p3,this.p3,s);vec2.copy(dstQuad.p3,this.p3,s);},isRectangle(){const bounds=this.boundingRect();return(bounds.x===this.p1[0]&&bounds.y===this.p1[1]&&bounds.width===this.p2[0]-this.p1[0]&&bounds.y===this.p2[1]&&bounds.width===this.p3[0]-this.p1[0]&&bounds.height===this.p3[1]-this.p2[1]&&bounds.x===this.p4[0]&&bounds.height===this.p4[1]-this.p2[1]);},projectUnitRect(rect){const q=new Quad();this.projectUnitRectFast(q,rect);return q;},projectUnitRectFast(dstQuad,rect){const v12=tmpVec2s[0];const v14=tmpVec2s[1];const v23=tmpVec2s[2];const v43=tmpVec2s[3];vec2.sub(v12,this.p2,this.p1);const l12=vec2.length(v12);vec2.scale(v12,v12,1/l12);vec2.sub(v14,this.p4,this.p1);const l14=vec2.length(v14);vec2.scale(v14,v14,1/l14);vec2.sub(v23,this.p3,this.p2);const l23=vec2.length(v23);vec2.scale(v23,v23,1/l23);vec2.sub(v43,this.p3,this.p4);const l43=vec2.length(v43);vec2.scale(v43,v43,1/l43);const b12=tmpVec2s[0];const b14=tmpVec2s[1];const b23=tmpVec2s[2];const b43=tmpVec2s[3];lerpVec2(b12,v12,v43,rect.y);lerpVec2(b43,v12,v43,1-rect.bottom);lerpVec2(b14,v14,v23,rect.x);lerpVec2(b23,v14,v23,1-rect.right);vec2.addTwoScaledUnitVectors(tmpVec2a,b12,l12*rect.x,b14,l14*rect.y);vec2.add(dstQuad.p1,this.p1,tmpVec2a);vec2.addTwoScaledUnitVectors(tmpVec2a,b12,l12*-(1.0-rect.right),b23,l23*rect.y);vec2.add(dstQuad.p2,this.p2,tmpVec2a);vec2.addTwoScaledUnitVectors(tmpVec2a,b43,l43*-(1.0-rect.right),b23,l23*-(1.0-rect.bottom));vec2.add(dstQuad.p3,this.p3,tmpVec2a);vec2.addTwoScaledUnitVectors(tmpVec2a,b43,l43*rect.left,b14,l14*-(1.0-rect.bottom));vec2.add(dstQuad.p4,this.p4,tmpVec2a);},toString(){return'Quad('+
+vec2.toString(this.p1)+', '+
+vec2.toString(this.p2)+', '+
+vec2.toString(this.p3)+', '+
+vec2.toString(this.p4)+')';}};function sign(p1,p2,p3){return(p1[0]-p3[0])*(p2[1]-p3[1])-
+(p2[0]-p3[0])*(p1[1]-p3[1]);}
+function pointInTriangle2(pt,p1,p2,p3){const b1=sign(pt,p1,p2)<0.0;const b2=sign(pt,p2,p3)<0.0;const b3=sign(pt,p3,p1)<0.0;return((b1===b2)&&(b2===b3));}
+function pointInImplicitQuad(point,p1,p2,p3,p4){return pointInTriangle2(point,p1,p2,p3)||pointInTriangle2(point,p1,p3,p4);}
+return{pointInTriangle2,pointInImplicitQuad,Quad,};});'use strict';tr.exportTo('tr.b',function(){const ESTIMATED_IDLE_PERIOD_LENGTH_MILLISECONDS=10;const REQUEST_IDLE_CALLBACK_TIMEOUT_MILLISECONDS=100;const recordRAFStacks=false;let pendingPreAFs=[];let pendingRAFs=[];const pendingIdleCallbacks=[];let currentRAFDispatchList=undefined;let rafScheduled=false;let idleWorkScheduled=false;function scheduleRAF(){if(rafScheduled)return;rafScheduled=true;if(tr.isHeadless){Promise.resolve().then(function(){processRequests(false,0);},function(e){throw e;});}else{if(window.requestAnimationFrame){window.requestAnimationFrame(processRequests.bind(this,false));}else{const delta=Date.now()-window.performance.now();window.webkitRequestAnimationFrame(function(domTimeStamp){processRequests(false,domTimeStamp-delta);});}}}
+function nativeRequestIdleCallbackSupported(){return!tr.isHeadless&&window.requestIdleCallback;}
+function scheduleIdleWork(){if(idleWorkScheduled)return;if(!nativeRequestIdleCallbackSupported()){scheduleRAF();return;}
+idleWorkScheduled=true;window.requestIdleCallback(function(deadline,didTimeout){processIdleWork(false,deadline);},{timeout:REQUEST_IDLE_CALLBACK_TIMEOUT_MILLISECONDS});}
+function onAnimationFrameError(e,opt_stack){console.log(e.stack);if(tr.isHeadless)throw e;if(opt_stack)console.log(opt_stack);if(e.message){console.error(e.message,e.stack);}else{console.error(e);}}
+function runTask(task,frameBeginTime){try{task.callback.call(task.context,frameBeginTime);}catch(e){tr.b.onAnimationFrameError(e,task.stack);}}
+function processRequests(forceAllTasksToRun,frameBeginTime){rafScheduled=false;const currentPreAFs=pendingPreAFs;currentRAFDispatchList=pendingRAFs;pendingPreAFs=[];pendingRAFs=[];const hasRAFTasks=currentPreAFs.length||currentRAFDispatchList.length;for(let i=0;i<currentPreAFs.length;i++){runTask(currentPreAFs[i],frameBeginTime);}
+while(currentRAFDispatchList.length>0){runTask(currentRAFDispatchList.shift(),frameBeginTime);}
+currentRAFDispatchList=undefined;if((!hasRAFTasks&&!nativeRequestIdleCallbackSupported())||forceAllTasksToRun){const rafCompletionDeadline=frameBeginTime+ESTIMATED_IDLE_PERIOD_LENGTH_MILLISECONDS;processIdleWork(forceAllTasksToRun,{timeRemaining(){return rafCompletionDeadline-window.performance.now();}});}
+if(pendingIdleCallbacks.length>0)scheduleIdleWork();}
+function processIdleWork(forceAllTasksToRun,deadline){idleWorkScheduled=false;while(pendingIdleCallbacks.length>0){runTask(pendingIdleCallbacks.shift());if(!forceAllTasksToRun&&(tr.isHeadless||deadline.timeRemaining()<=0)){break;}}
+if(pendingIdleCallbacks.length>0)scheduleIdleWork();}
+function getStack_(){if(!recordRAFStacks)return'';const stackLines=tr.b.stackTrace();stackLines.shift();return stackLines.join('\n');}
+function requestPreAnimationFrame(callback,opt_this){pendingPreAFs.push({callback,context:opt_this||global,stack:getStack_()});scheduleRAF();}
+function requestAnimationFrameInThisFrameIfPossible(callback,opt_this){if(!currentRAFDispatchList){requestAnimationFrame(callback,opt_this);return;}
+currentRAFDispatchList.push({callback,context:opt_this||global,stack:getStack_()});return;}
+function requestAnimationFrame(callback,opt_this){pendingRAFs.push({callback,context:opt_this||global,stack:getStack_()});scheduleRAF();}
+function animationFrame(){return new Promise(resolve=>requestAnimationFrame(resolve));}
+function requestIdleCallback(callback,opt_this){pendingIdleCallbacks.push({callback,context:opt_this||global,stack:getStack_()});scheduleIdleWork();}
+function forcePendingRAFTasksToRun(frameBeginTime){if(!rafScheduled)return;processRequests(false,frameBeginTime);}
+function forceAllPendingTasksToRunForTest(){if(!rafScheduled&&!idleWorkScheduled)return;processRequests(true,0);}
+function timeout(ms){return new Promise(resolve=>window.setTimeout(resolve,ms));}
+function idle(){return new Promise(resolve=>requestIdleCallback(resolve));}
+return{animationFrame,forceAllPendingTasksToRunForTest,forcePendingRAFTasksToRun,idle,onAnimationFrameError,requestAnimationFrame,requestAnimationFrameInThisFrameIfPossible,requestIdleCallback,requestPreAnimationFrame,timeout,};});'use strict';tr.exportTo('tr.b',function(){class Mark{constructor(groupName,functionName,opt_timestamp){if(tr.isHeadless)return;this.groupName_=groupName;this.functionName_=functionName;const guid=tr.b.GUID.allocateSimple();this.measureName_=`${groupName} ${functionName}`;if(opt_timestamp){this.startMark_={startTime:opt_timestamp};}else{this.startMarkName_=`${this.measureName} ${guid} start`;}
+this.endMark_=undefined;this.endMarkName_=`${this.measureName} ${guid} end`;window.performance.mark(this.startMarkName_);}
+get groupName(){return this.groupName_;}
+get functionName(){return this.functionName_;}
+get measureName(){return this.measureName_;}
+get startMark(){return this.startMark_||tr.b.getOnlyElement(window.performance.getEntriesByName(this.startMarkName_));}
+get endMark(){return this.endMark_||tr.b.getOnlyElement(window.performance.getEntriesByName(this.endMarkName_));}
+get durationMs(){return this.endMark.startTime-this.startMark.startTime;}
+end(opt_timestamp){if(tr.isHeadless)return;if(opt_timestamp){this.endMark_={startTime:opt_timestamp};}else{window.performance.mark(this.endMarkName_);}
+if(!this.startMark_&&!this.endMark_){window.performance.measure(this.measureName_,this.startMarkName_,this.endMarkName_);}else if(Timing.logVoidMarks&&!(window.ga instanceof Function)){console.log('void mark',this.groupName,this.functionName,this.durationMs);}
+if(!(window.ga instanceof Function))return;ga('send',{hitType:'event',eventCategory:this.groupName,eventAction:this.functionName,eventValue:this.durationMs,});}}
+class Timing{static mark(groupName,functionName,opt_timestamp){return new Mark(groupName,functionName,opt_timestamp);}
+static instant(groupName,functionName,opt_value){const valueString=opt_value===undefined?'':' '+opt_value;if(console&&console.timeStamp){console.timeStamp(`${groupName} ${functionName}${valueString}`);}
+if(window&&window.ga instanceof Function){ga('send',{hitType:'event',eventCategory:groupName,eventAction:functionName,eventValue:opt_value,});}}
+static getCurrentTimeMs(){try{return performance.now();}catch(error){}
+return 0;}}
+Timing.logVoidMarks=false;return{Timing,};});'use strict';tr.exportTo('tr.b',function(){const Timing=tr.b.Timing;function Task(runCb,thisArg){if(runCb!==undefined&&thisArg===undefined&&runCb.prototype!==undefined){throw new Error('Almost certainly you meant to pass a bound callback '+'or thisArg.');}
+this.runCb_=runCb;this.thisArg_=thisArg;this.afterTask_=undefined;this.subTasks_=[];this.updatesUi_=false;}
+Task.prototype={get name(){return this.runCb_.name;},set updatesUi(value){this.updatesUi_=value;},subTask(cb,thisArg){if(cb instanceof Task){this.subTasks_.push(cb);}else{this.subTasks_.push(new Task(cb,thisArg));}
+return this.subTasks_[this.subTasks_.length-1];},run(){if(this.runCb_!==undefined)this.runCb_.call(this.thisArg_,this);const subTasks=this.subTasks_;this.subTasks_=undefined;if(!subTasks.length)return this.afterTask_;for(let i=1;i<subTasks.length;i++){subTasks[i-1].afterTask_=subTasks[i];}
+subTasks[subTasks.length-1].afterTask_=this.afterTask_;return subTasks[0];},after(cb,thisArg){if(this.afterTask_){throw new Error('Has an after task already');}
+if(cb instanceof Task){this.afterTask_=cb;}else{this.afterTask_=new Task(cb,thisArg);}
+return this.afterTask_;},enqueue(cb,thisArg){if(!this.afterTask_)return this.after(cb,thisArg);return this.afterTask_.enqueue(cb,thisArg);}};Task.RunSynchronously=function(task){let curTask=task;while(curTask){curTask=curTask.run();}};Task.RunWhenIdle=function(task){return new Promise(function(resolve,reject){let curTask=task;function runAnother(){try{curTask=curTask.run();}catch(e){reject(e);return;}
+if(curTask){if(curTask.updatesUi_){tr.b.requestAnimationFrameInThisFrameIfPossible(runAnother);}else{tr.b.requestIdleCallback(runAnother);}
+return;}
+resolve();}
+tr.b.requestIdleCallback(runAnother);});};return{Task,};});'use strict';tr.exportTo('tr.c',function(){function makeCaseInsensitiveRegex(pattern){pattern=pattern.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');return new RegExp(pattern,'i');}
+function Filter(){}
+Filter.prototype={__proto__:Object.prototype,matchCounter(counter){return true;},matchCpu(cpu){return true;},matchProcess(process){return true;},matchSlice(slice){return true;},matchThread(thread){return true;}};function TitleOrCategoryFilter(text){Filter.call(this);this.regex_=makeCaseInsensitiveRegex(text);if(!text.length){throw new Error('Filter text is empty.');}}
+TitleOrCategoryFilter.prototype={__proto__:Filter.prototype,matchSlice(slice){if(slice.title===undefined&&slice.category===undefined){return false;}
+return this.regex_.test(slice.title)||(!!slice.category&&this.regex_.test(slice.category));}};function ExactTitleFilter(text){Filter.call(this);this.text_=text;if(!text.length){throw new Error('Filter text is empty.');}}
+ExactTitleFilter.prototype={__proto__:Filter.prototype,matchSlice(slice){return slice.title===this.text_;}};function FullTextFilter(text){Filter.call(this);this.regex_=makeCaseInsensitiveRegex(text);this.titleOrCategoryFilter_=new TitleOrCategoryFilter(text);}
+FullTextFilter.prototype={__proto__:Filter.prototype,matchObject_(obj){for(const key in obj){if(!obj.hasOwnProperty(key))continue;if(this.regex_.test(key))return true;if(this.regex_.test(obj[key]))return true;}
+return false;},matchSlice(slice){if(this.titleOrCategoryFilter_.matchSlice(slice))return true;return this.matchObject_(slice.args);}};return{Filter,TitleOrCategoryFilter,ExactTitleFilter,FullTextFilter,};});'use strict';tr.exportTo('tr.model',function(){const ClockDomainId={BATTOR:'BATTOR',UNKNOWN_CHROME_LEGACY:'UNKNOWN_CHROME_LEGACY',LINUX_CLOCK_MONOTONIC:'LINUX_CLOCK_MONOTONIC',LINUX_FTRACE_GLOBAL:'LINUX_FTRACE_GLOBAL',MAC_MACH_ABSOLUTE_TIME:'MAC_MACH_ABSOLUTE_TIME',WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:'WIN_ROLLOVER_PROTECTED_TIME_GET_TIME',WIN_QPC:'WIN_QPC',SYSTRACE:'SYSTRACE',TELEMETRY:'TELEMETRY'};const POSSIBLE_CHROME_CLOCK_DOMAINS=new Set([ClockDomainId.UNKNOWN_CHROME_LEGACY,ClockDomainId.LINUX_CLOCK_MONOTONIC,ClockDomainId.MAC_MACH_ABSOLUTE_TIME,ClockDomainId.WIN_ROLLOVER_PROTECTED_TIME_GET_TIME,ClockDomainId.WIN_QPC]);const BATTOR_FAST_SYNC_THRESHOLD_MS=3;function ClockSyncManager(){this.domainsSeen_=new Set();this.markersBySyncId_=new Map();this.transformerMapByDomainId_={};}
+ClockSyncManager.prototype={addClockSyncMarker(domainId,syncId,startTs,opt_endTs){this.onDomainSeen_(domainId);if(Object.values(ClockDomainId).indexOf(domainId)<0){throw new Error('"'+domainId+'" is not in the list of known '+'clock domain IDs.');}
+if(this.modelDomainId_){throw new Error('Cannot add new clock sync markers after getting '+'a model time transformer.');}
+const marker=new ClockSyncMarker(domainId,startTs,opt_endTs);if(!this.markersBySyncId_.has(syncId)){this.markersBySyncId_.set(syncId,[marker]);return;}
+const markers=this.markersBySyncId_.get(syncId);if(markers.length===2){throw new Error('Clock sync with ID "'+syncId+'" is already '+'complete - cannot add a third clock sync marker to it.');}
+if(markers[0].domainId===domainId){throw new Error('A clock domain cannot sync with itself.');}
+markers.push(marker);this.onSyncCompleted_(markers[0],marker);},get completeSyncIds(){const completeSyncIds=[];for(const[syncId,markers]of this.markersBySyncId){if(markers.length===2)completeSyncIds.push(syncId);}
+return completeSyncIds;},get markersBySyncId(){return this.markersBySyncId_;},get domainsSeen(){return this.domainsSeen_;},getModelTimeTransformer(domainId){this.onDomainSeen_(domainId);if(!this.modelDomainId_){this.selectModelDomainId_();}
+return this.getTimeTransformerRaw_(domainId,this.modelDomainId_).fn;},getTimeTransformerError(fromDomainId,toDomainId){this.onDomainSeen_(fromDomainId);this.onDomainSeen_(toDomainId);return this.getTimeTransformerRaw_(fromDomainId,toDomainId).error;},getTimeTransformerRaw_(fromDomainId,toDomainId){const transformer=this.getTransformerBetween_(fromDomainId,toDomainId);if(!transformer){throw new Error('No clock sync markers exist pairing clock domain "'+
+fromDomainId+'" '+'with target clock domain "'+
+toDomainId+'".');}
+return transformer;},getTransformerBetween_(fromDomainId,toDomainId){const visitedDomainIds=new Set();const queue=[{domainId:fromDomainId,transformer:Transformer.IDENTITY}];while(queue.length>0){queue.sort((domain1,domain2)=>domain1.transformer.error-domain2.transformer.error);const current=queue.shift();if(current.domainId===toDomainId){return current.transformer;}
+if(visitedDomainIds.has(current.domainId)){continue;}
+visitedDomainIds.add(current.domainId);const outgoingTransformers=this.transformerMapByDomainId_[current.domainId];if(!outgoingTransformers)continue;for(const outgoingDomainId in outgoingTransformers){const toNextDomainTransformer=outgoingTransformers[outgoingDomainId];const toCurrentDomainTransformer=current.transformer;queue.push({domainId:outgoingDomainId,transformer:Transformer.compose(toNextDomainTransformer,toCurrentDomainTransformer)});}}
+return undefined;},selectModelDomainId_(){this.ensureAllDomainsAreConnected_();for(const chromeDomainId of POSSIBLE_CHROME_CLOCK_DOMAINS){if(this.domainsSeen_.has(chromeDomainId)){this.modelDomainId_=chromeDomainId;return;}}
+const domainsSeenArray=Array.from(this.domainsSeen_);domainsSeenArray.sort();this.modelDomainId_=domainsSeenArray[0];},ensureAllDomainsAreConnected_(){let firstDomainId=undefined;for(const domainId of this.domainsSeen_){if(!firstDomainId){firstDomainId=domainId;continue;}
+if(!this.getTransformerBetween_(firstDomainId,domainId)){throw new Error('Unable to select a master clock domain because no '+'path can be found from "'+firstDomainId+'" to "'+domainId+'".');}}
+return true;},onDomainSeen_(domainId){if(domainId===ClockDomainId.UNKNOWN_CHROME_LEGACY&&!this.domainsSeen_.has(ClockDomainId.UNKNOWN_CHROME_LEGACY)){for(const chromeDomainId of POSSIBLE_CHROME_CLOCK_DOMAINS){if(chromeDomainId===ClockDomainId.UNKNOWN_CHROME_LEGACY){continue;}
+this.collapseDomains_(ClockDomainId.UNKNOWN_CHROME_LEGACY,chromeDomainId);}}
+this.domainsSeen_.add(domainId);},onSyncCompleted_(marker1,marker2){const forwardTransformer=Transformer.fromMarkers(marker1,marker2);const backwardTransformer=Transformer.fromMarkers(marker2,marker1);const existingTransformer=this.getOrCreateTransformerMap_(marker1.domainId)[marker2.domainId];if(!existingTransformer||forwardTransformer.error<existingTransformer.error){this.getOrCreateTransformerMap_(marker1.domainId)[marker2.domainId]=forwardTransformer;this.getOrCreateTransformerMap_(marker2.domainId)[marker1.domainId]=backwardTransformer;}},collapseDomains_(domain1Id,domain2Id){this.getOrCreateTransformerMap_(domain1Id)[domain2Id]=this.getOrCreateTransformerMap_(domain2Id)[domain1Id]=Transformer.IDENTITY;},getOrCreateTransformerMap_(domainId){if(!this.transformerMapByDomainId_[domainId]){this.transformerMapByDomainId_[domainId]={};}
+return this.transformerMapByDomainId_[domainId];},computeDotGraph(){let dotString='graph {\n';const domainsSeen=[...this.domainsSeen_].sort();for(const domainId of domainsSeen){dotString+=`  ${domainId}[shape=box]\n`;}
+const markersBySyncIdEntries=[...this.markersBySyncId_.entries()].sort(([syncId1,markers1],[syncId2,markers2])=>syncId1.localeCompare(syncId2));for(const[syncId,markers]of markersBySyncIdEntries){const sortedMarkers=markers.sort((a,b)=>a.domainId.localeCompare(b.domainId));for(const m of markers){dotString+=`  "${syncId}" -- ${m.domainId} `;dotString+=`[label="[${m.startTs}, ${m.endTs}]"]\n`;}}
+dotString+='}';return dotString;}};function ClockSyncMarker(domainId,startTs,opt_endTs){this.domainId=domainId;this.startTs=startTs;this.endTs=opt_endTs===undefined?startTs:opt_endTs;}
+ClockSyncMarker.prototype={get duration(){return this.endTs-this.startTs;},get ts(){return this.startTs+this.duration/2;}};function Transformer(fn,error){this.fn=fn;this.error=error;}
+Transformer.IDENTITY=new Transformer((x=>x),0);Transformer.compose=function(aToB,bToC){return new Transformer((ts)=>bToC.fn(aToB.fn(ts)),aToB.error+bToC.error);};Transformer.fromMarkers=function(fromMarker,toMarker){let fromTs=fromMarker.ts;let toTs=toMarker.ts;if(fromMarker.domainId===ClockDomainId.BATTOR&&toMarker.duration>BATTOR_FAST_SYNC_THRESHOLD_MS){toTs=toMarker.startTs;}else if(toMarker.domainId===ClockDomainId.BATTOR&&fromMarker.duration>BATTOR_FAST_SYNC_THRESHOLD_MS){fromTs=fromMarker.startTs;}
+const tsShift=toTs-fromTs;return new Transformer((ts)=>ts+tsShift,fromMarker.duration+toMarker.duration);};return{ClockDomainId,ClockSyncManager,};});'use strict';tr.exportTo('tr.model',function(){function CounterSample(series,timestamp,value){tr.model.Event.call(this);this.series_=series;this.timestamp_=timestamp;this.value_=value;}
+CounterSample.groupByTimestamp=function(samples){const samplesByTimestamp=tr.b.groupIntoMap(samples,s=>s.timestamp);const timestamps=Array.from(samplesByTimestamp.keys());timestamps.sort();const groups=[];for(const ts of timestamps){const group=samplesByTimestamp.get(ts);group.sort((x,y)=>x.series.seriesIndex-y.series.seriesIndex);groups.push(group);}
+return groups;};CounterSample.prototype={__proto__:tr.model.Event.prototype,get series(){return this.series_;},get timestamp(){return this.timestamp_;},get value(){return this.value_;},set timestamp(timestamp){this.timestamp_=timestamp;},addBoundsToRange(range){range.addValue(this.timestamp);},getSampleIndex(){return tr.b.findLowIndexInSortedArray(this.series.timestamps,function(x){return x;},this.timestamp_);},get userFriendlyName(){return'Counter sample from '+this.series_.title+' at '+
+tr.b.Unit.byName.timeStampInMs.format(this.timestamp);}};tr.model.EventRegistry.register(CounterSample,{name:'counterSample',pluralName:'counterSamples'});return{CounterSample,};});'use strict';tr.exportTo('tr.model',function(){const CounterSample=tr.model.CounterSample;function CounterSeries(name,color){tr.model.EventContainer.call(this);this.name_=name;this.color_=color;this.timestamps_=[];this.samples_=[];this.counter=undefined;this.seriesIndex=undefined;}
+CounterSeries.prototype={__proto__:tr.model.EventContainer.prototype,get length(){return this.timestamps_.length;},get name(){return this.name_;},get color(){return this.color_;},get samples(){return this.samples_;},get timestamps(){return this.timestamps_;},getSample(idx){return this.samples_[idx];},getTimestamp(idx){return this.timestamps_[idx];},addCounterSample(ts,val){const sample=new CounterSample(this,ts,val);this.addSample(sample);return sample;},addSample(sample){this.timestamps_.push(sample.timestamp);this.samples_.push(sample);},getStatistics(sampleIndices){let sum=0;let min=Number.MAX_VALUE;let max=-Number.MAX_VALUE;for(let i=0;i<sampleIndices.length;++i){const sample=this.getSample(sampleIndices[i]).value;sum+=sample;min=Math.min(sample,min);max=Math.max(sample,max);}
+return{min,max,avg:(sum/sampleIndices.length),start:this.getSample(sampleIndices[0]).value,end:this.getSample(sampleIndices.length-1).value};},shiftTimestampsForward(amount){for(let i=0;i<this.timestamps_.length;++i){this.timestamps_[i]+=amount;this.samples_[i].timestamp=this.timestamps_[i];}},*childEvents(){yield*this.samples_;},*childEventContainers(){}};return{CounterSeries,};});'use strict';tr.exportTo('tr.model',function(){function Counter(parent,id,category,name){tr.model.EventContainer.call(this);this.parent_=parent;this.id_=id;this.category_=category||'';this.name_=name;this.series_=[];this.totals=[];}
+Counter.prototype={__proto__:tr.model.EventContainer.prototype,get parent(){return this.parent_;},get id(){return this.id_;},get category(){return this.category_;},get name(){return this.name_;},*childEvents(){},*childEventContainers(){yield*this.series;},set timestamps(arg){throw new Error('Bad counter API. No cookie.');},set seriesNames(arg){throw new Error('Bad counter API. No cookie.');},set seriesColors(arg){throw new Error('Bad counter API. No cookie.');},set samples(arg){throw new Error('Bad counter API. No cookie.');},addSeries(series){series.counter=this;series.seriesIndex=this.series_.length;this.series_.push(series);return series;},getSeries(idx){return this.series_[idx];},get series(){return this.series_;},get numSeries(){return this.series_.length;},get numSamples(){if(this.series_.length===0)return 0;return this.series_[0].length;},get timestamps(){if(this.series_.length===0)return[];return this.series_[0].timestamps;},getSampleStatistics(sampleIndices){sampleIndices.sort();const ret=[];this.series_.forEach(function(series){ret.push(series.getStatistics(sampleIndices));});return ret;},shiftTimestampsForward(amount){for(let i=0;i<this.series_.length;++i){this.series_[i].shiftTimestampsForward(amount);}},updateBounds(){this.totals=[];this.maxTotal=0;this.bounds.reset();if(this.series_.length===0)return;const firstSeries=this.series_[0];const lastSeries=this.series_[this.series_.length-1];this.bounds.addValue(firstSeries.getTimestamp(0));this.bounds.addValue(lastSeries.getTimestamp(lastSeries.length-1));const numSeries=this.numSeries;this.maxTotal=-Infinity;for(let i=0;i<firstSeries.length;++i){let total=0;this.series_.forEach(function(series){total+=series.getSample(i).value;this.totals.push(total);}.bind(this));this.maxTotal=Math.max(total,this.maxTotal);}}};Counter.compare=function(x,y){let tmp=x.parent.compareTo(y.parent);if(tmp!==0)return tmp;tmp=x.name.localeCompare(y.name);if(tmp===0)return x.tid-y.tid;return tmp;};return{Counter,};});'use strict';tr.exportTo('tr.model',function(){const Slice=tr.model.Slice;function CpuSlice(cat,title,colorId,start,args,opt_duration){Slice.apply(this,arguments);this.threadThatWasRunning=undefined;this.cpu=undefined;}
+CpuSlice.prototype={__proto__:Slice.prototype,get analysisTypeName(){return'tr.ui.analysis.CpuSlice';},getAssociatedTimeslice(){if(!this.threadThatWasRunning){return undefined;}
+const timeSlices=this.threadThatWasRunning.timeSlices;for(let i=0;i<timeSlices.length;i++){const timeSlice=timeSlices[i];if(timeSlice.start!==this.start){continue;}
+if(timeSlice.duration!==this.duration){continue;}
+return timeSlice;}
+return undefined;}};tr.model.EventRegistry.register(CpuSlice,{name:'cpuSlice',pluralName:'cpuSlices'});return{CpuSlice,};});'use strict';tr.exportTo('tr.model',function(){function TimeToObjectInstanceMap(createObjectInstanceFunction,parent,scopedId){this.createObjectInstanceFunction_=createObjectInstanceFunction;this.parent=parent;this.scopedId=scopedId;this.instances=[];}
+TimeToObjectInstanceMap.prototype={idWasCreated(category,name,ts){if(this.instances.length===0){this.instances.push(this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts));this.instances[0].creationTsWasExplicit=true;return this.instances[0];}
+let lastInstance=this.instances[this.instances.length-1];if(ts<lastInstance.deletionTs){throw new Error('Mutation of the TimeToObjectInstanceMap must be '+'done in ascending timestamp order.');}
+lastInstance=this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts);lastInstance.creationTsWasExplicit=true;this.instances.push(lastInstance);return lastInstance;},addSnapshot(category,name,ts,args,opt_baseTypeName){if(this.instances.length===0){this.instances.push(this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts,opt_baseTypeName));}
+const i=tr.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);let instance;if(i<0){instance=this.instances[0];if(ts>instance.deletionTs||instance.creationTsWasExplicit){throw new Error('At the provided timestamp, no instance was still alive');}
+if(instance.snapshots.length!==0){throw new Error('Cannot shift creationTs forward, '+'snapshots have been added. First snap was at ts='+
+instance.snapshots[0].ts+' and creationTs was '+
+instance.creationTs);}
+instance.creationTs=ts;}else if(i>=this.instances.length){instance=this.instances[this.instances.length-1];if(ts>=instance.deletionTs){instance=this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts,opt_baseTypeName);this.instances.push(instance);}else{let lastValidIndex;for(let i=this.instances.length-1;i>=0;i--){const tmp=this.instances[i];if(ts>=tmp.deletionTs)break;if(tmp.creationTsWasExplicit===false&&tmp.snapshots.length===0){lastValidIndex=i;}}
+if(lastValidIndex===undefined){throw new Error('Cannot add snapshot. No instance was alive that was mutable.');}
+instance=this.instances[lastValidIndex];instance.creationTs=ts;}}else{instance=this.instances[i];}
+return instance.addSnapshot(ts,args,name,opt_baseTypeName);},get lastInstance(){if(this.instances.length===0)return undefined;return this.instances[this.instances.length-1];},idWasDeleted(category,name,ts){if(this.instances.length===0){this.instances.push(this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts));}
+let lastInstance=this.instances[this.instances.length-1];if(ts<lastInstance.creationTs){throw new Error('Cannot delete an id before it was created');}
+if(lastInstance.deletionTs===Number.MAX_VALUE){lastInstance.wasDeleted(ts);return lastInstance;}
+if(ts<lastInstance.deletionTs){throw new Error('id was already deleted earlier.');}
+lastInstance=this.createObjectInstanceFunction_(this.parent,this.scopedId,category,name,ts);this.instances.push(lastInstance);lastInstance.wasDeleted(ts);return lastInstance;},getInstanceAt(ts){const i=tr.b.findIndexInSortedIntervals(this.instances,function(inst){return inst.creationTs;},function(inst){return inst.deletionTs-inst.creationTs;},ts);if(i<0){if(this.instances[0].creationTsWasExplicit){return undefined;}
+return this.instances[0];}else if(i>=this.instances.length){return undefined;}
+return this.instances[i];}};return{TimeToObjectInstanceMap,};});'use strict';tr.exportTo('tr.model',function(){const ObjectInstance=tr.model.ObjectInstance;const ObjectSnapshot=tr.model.ObjectSnapshot;function ObjectCollection(parent){tr.model.EventContainer.call(this);this.parent=parent;this.instanceMapsByScopedId_={};this.instancesByTypeName_={};this.createObjectInstance_=this.createObjectInstance_.bind(this);}
+ObjectCollection.prototype={__proto__:tr.model.EventContainer.prototype,*childEvents(){for(const instance of this.getAllObjectInstances()){yield instance;yield*instance.snapshots;}},createObjectInstance_(parent,scopedId,category,name,creationTs,opt_baseTypeName){const constructor=tr.model.ObjectInstance.subTypes.getConstructor(category,name);const instance=new constructor(parent,scopedId,category,name,creationTs,opt_baseTypeName);const typeName=instance.typeName;let instancesOfTypeName=this.instancesByTypeName_[typeName];if(!instancesOfTypeName){instancesOfTypeName=[];this.instancesByTypeName_[typeName]=instancesOfTypeName;}
+instancesOfTypeName.push(instance);return instance;},getOrCreateInstanceMap_(scopedId){let dict;if(scopedId.scope in this.instanceMapsByScopedId_){dict=this.instanceMapsByScopedId_[scopedId.scope];}else{dict={};this.instanceMapsByScopedId_[scopedId.scope]=dict;}
+let instanceMap=dict[scopedId.id];if(instanceMap)return instanceMap;instanceMap=new tr.model.TimeToObjectInstanceMap(this.createObjectInstance_,this.parent,scopedId);dict[scopedId.id]=instanceMap;return instanceMap;},idWasCreated(scopedId,category,name,ts){const instanceMap=this.getOrCreateInstanceMap_(scopedId);return instanceMap.idWasCreated(category,name,ts);},addSnapshot(scopedId,category,name,ts,args,opt_baseTypeName){const instanceMap=this.getOrCreateInstanceMap_(scopedId);const snapshot=instanceMap.addSnapshot(category,name,ts,args,opt_baseTypeName);if(snapshot.objectInstance.category!==category){const msg='Added snapshot name='+name+' with cat='+category+' impossible. It instance was created/snapshotted with cat='+
+snapshot.objectInstance.category+' name='+
+snapshot.objectInstance.name;throw new Error(msg);}
+if(opt_baseTypeName&&snapshot.objectInstance.baseTypeName!==opt_baseTypeName){throw new Error('Could not add snapshot with baseTypeName='+
+opt_baseTypeName+'. It '+'was previously created with name='+
+snapshot.objectInstance.baseTypeName);}
+if(snapshot.objectInstance.name!==name){throw new Error('Could not add snapshot with name='+name+'. It '+'was previously created with name='+
+snapshot.objectInstance.name);}
+return snapshot;},idWasDeleted(scopedId,category,name,ts){const instanceMap=this.getOrCreateInstanceMap_(scopedId);const deletedInstance=instanceMap.idWasDeleted(category,name,ts);if(!deletedInstance)return;if(deletedInstance.category!==category){const msg='Deleting object '+deletedInstance.name+' with a different category '+'than when it was created. It previous had cat='+
+deletedInstance.category+' but the delete command '+'had cat='+category;throw new Error(msg);}
+if(deletedInstance.baseTypeName!==name){throw new Error('Deletion requested for name='+
+name+' could not proceed: '+'An existing object with baseTypeName='+
+deletedInstance.baseTypeName+' existed.');}},autoDeleteObjects(maxTimestamp){for(const imapById of Object.values(this.instanceMapsByScopedId_)){for(const i2imap of Object.values(imapById)){const lastInstance=i2imap.lastInstance;if(lastInstance.deletionTs!==Number.MAX_VALUE)continue;i2imap.idWasDeleted(lastInstance.category,lastInstance.name,maxTimestamp);lastInstance.deletionTsWasExplicit=false;}}},getObjectInstanceAt(scopedId,ts){let instanceMap;if(scopedId.scope in this.instanceMapsByScopedId_){instanceMap=this.instanceMapsByScopedId_[scopedId.scope][scopedId.id];}
+if(!instanceMap)return undefined;return instanceMap.getInstanceAt(ts);},getSnapshotAt(scopedId,ts){const instance=this.getObjectInstanceAt(scopedId,ts);if(!instance)return undefined;return instance.getSnapshotAt(ts);},iterObjectInstances(iter,opt_this){opt_this=opt_this||this;for(const imapById of Object.values(this.instanceMapsByScopedId_)){for(const i2imap of Object.values(imapById)){i2imap.instances.forEach(iter,opt_this);}}},getAllObjectInstances(){const instances=[];this.iterObjectInstances(function(i){instances.push(i);});return instances;},getAllInstancesNamed(name){return this.instancesByTypeName_[name];},getAllInstancesByTypeName(){return this.instancesByTypeName_;},preInitializeAllObjects(){this.iterObjectInstances(function(instance){instance.preInitialize();});},initializeAllObjects(){this.iterObjectInstances(function(instance){instance.initialize();});},initializeInstances(){this.iterObjectInstances(function(instance){instance.initialize();});},updateBounds(){this.bounds.reset();this.iterObjectInstances(function(instance){instance.updateBounds();this.bounds.addRange(instance.bounds);},this);},shiftTimestampsForward(amount){this.iterObjectInstances(function(instance){instance.shiftTimestampsForward(amount);});},addCategoriesToDict(categoriesDict){this.iterObjectInstances(function(instance){categoriesDict[instance.category]=true;});}};return{ObjectCollection,};});'use strict';tr.exportTo('tr.model',function(){class AsyncSliceGroup extends tr.model.EventContainer{constructor(parentContainer,opt_name){super();this.parentContainer_=parentContainer;this.name_=opt_name;this.slices=[];this.viewSubGroups_=undefined;this.nestedLevel_=0;this.hasNestedSubGroups_=true;this.title_=undefined;}
+get parentContainer(){return this.parentContainer_;}
+get model(){return this.parentContainer_.parent.model;}
+get stableId(){return this.parentContainer_.stableId+'.AsyncSliceGroup';}
+get title(){if(this.nested_level_===0){return'<root>';}
+return this.title_;}
+getSettingsKey(){if(this.name_===undefined){return undefined;}
+const parentKey=this.parentContainer_.getSettingsKey();if(parentKey===undefined){return undefined;}
+return parentKey+'.'+this.name_;}
+push(slice){if(this.viewSubGroups_!==undefined){throw new Error('No new slices are allowed when view sub-groups already formed.');}
+slice.parentContainer=this.parentContainer;this.slices.push(slice);return slice;}
+get length(){return this.slices.length;}
+shiftTimestampsForward(amount){for(const slice of this.childEvents()){slice.start+=amount;}}
+updateBounds(){this.bounds.reset();for(let i=0;i<this.slices.length;i++){this.bounds.addValue(this.slices[i].start);this.bounds.addValue(this.slices[i].end);}}
+autoCloseOpenSlices(){const maxTimestamp=this.parentContainer_.parent.model.bounds.max;for(const slice of this.childEvents()){if(slice.didNotFinish){slice.duration=maxTimestamp-slice.start;}}}
+get viewSubGroups(){if(!this.hasNestedSubGroups_||this.nestedLevel_===2){return[];}
+if(this.viewSubGroups_!==undefined){return this.viewSubGroups_;}
+const subGroupsByTitle=new Map();for(const slice of this.slices){let subGroupTitle=slice.viewSubGroupTitle;let hasNestedSubGroups=false;if(this.nestedLevel_===0&&slice.viewSubGroupGroupingKey!==undefined){subGroupTitle=slice.viewSubGroupGroupingKey;hasNestedSubGroups=true;}
+let subGroup=subGroupsByTitle.get(subGroupTitle);if(subGroup===undefined){let name;if(this.name_!==undefined){name=this.name_+'.'+subGroupTitle;}else{name=subGroupTitle;}
+subGroup=new AsyncSliceGroup(this.parentContainer_,name);subGroup.title_=subGroupTitle;subGroup.hasNestedSubGroups_=hasNestedSubGroups;subGroup.nestedLevel_=this.nestedLevel_+1;subGroupsByTitle.set(subGroupTitle,subGroup);}
+subGroup.push(slice);}
+this.viewSubGroups_=Array.from(subGroupsByTitle.values());this.viewSubGroups_.sort((a,b)=>a.title.localeCompare(b.title));return this.viewSubGroups_;}*findTopmostSlicesInThisContainer(eventPredicate,opt_this){for(const slice of this.slices){if(slice.isTopLevel){yield*slice.findTopmostSlicesRelativeToThisSlice(eventPredicate,opt_this);}}}*childEvents(){for(const slice of this.slices){yield slice;yield*slice.enumerateAllDescendents();}}*childEventContainers(){}}
+return{AsyncSliceGroup,};});'use strict';tr.exportTo('tr.model',function(){const Slice=tr.model.Slice;function ThreadSlice(cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration,opt_argsStripped,opt_bindId){Slice.call(this,cat,title,colorId,start,args,opt_duration,opt_cpuStart,opt_cpuDuration,opt_argsStripped,opt_bindId);this.subSlices=[];}
+ThreadSlice.prototype={__proto__:Slice.prototype,get overlappingSamples(){const samples=new tr.model.EventSet();if(!this.parentContainer||!this.parentContainer.samples){return samples;}
+this.parentContainer.samples.forEach(function(sample){if(this.start<=sample.start&&sample.start<=this.end){samples.push(sample);}},this);return samples;}};tr.model.EventRegistry.register(ThreadSlice,{name:'slice',pluralName:'slices'});return{ThreadSlice,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;const ThreadSlice=tr.model.ThreadSlice;function getSliceLo(s){return s.start;}
+function getSliceHi(s){return s.end;}
+function SliceGroup(parentContainer,opt_sliceConstructor,opt_name){tr.model.EventContainer.call(this);this.parentContainer_=parentContainer;const sliceConstructor=opt_sliceConstructor||ThreadSlice;this.sliceConstructor=sliceConstructor;this.sliceConstructorSubTypes=this.sliceConstructor.subTypes;if(!this.sliceConstructorSubTypes){throw new Error('opt_sliceConstructor must have a subtype registry.');}
+this.openPartialSlices_=[];this.slices=[];this.topLevelSlices=[];this.haveTopLevelSlicesBeenBuilt=false;this.name_=opt_name;if(this.model===undefined){throw new Error('SliceGroup must have model defined.');}}
+SliceGroup.prototype={__proto__:tr.model.EventContainer.prototype,get parentContainer(){return this.parentContainer_;},get model(){return this.parentContainer_.model;},get stableId(){return this.parentContainer_.stableId+'.SliceGroup';},getSettingsKey(){if(!this.name_)return undefined;const parentKey=this.parentContainer_.getSettingsKey();if(!parentKey)return undefined;return parentKey+'.'+this.name;},get length(){return this.slices.length;},pushSlice(slice){this.haveTopLevelSlicesBeenBuilt=false;slice.parentContainer=this.parentContainer_;this.slices.push(slice);return slice;},pushSlices(slices){this.haveTopLevelSlicesBeenBuilt=false;slices.forEach(function(slice){slice.parentContainer=this.parentContainer_;this.slices.push(slice);},this);},beginSlice(category,title,ts,opt_args,opt_tts,opt_argsStripped,opt_colorId,opt_bindId){const colorId=opt_colorId||ColorScheme.getColorIdForGeneralPurposeString(title);const sliceConstructorSubTypes=this.sliceConstructorSubTypes;const sliceType=sliceConstructorSubTypes.getConstructor(category,title);const slice=new sliceType(category,title,colorId,ts,opt_args?opt_args:{},null,opt_tts,undefined,opt_argsStripped,opt_bindId);this.openPartialSlices_.push(slice);slice.didNotFinish=true;this.pushSlice(slice);return slice;},isTimestampValidForBeginOrEnd(ts){if(!this.openPartialSlices_.length)return true;const top=this.openPartialSlices_[this.openPartialSlices_.length-1];return ts>=top.start;},get openSliceCount(){return this.openPartialSlices_.length;},get mostRecentlyOpenedPartialSlice(){if(!this.openPartialSlices_.length)return undefined;return this.openPartialSlices_[this.openPartialSlices_.length-1];},endSlice(ts,opt_tts,opt_colorId){if(!this.openSliceCount){throw new Error('endSlice called without an open slice');}
+const slice=this.openPartialSlices_[this.openSliceCount-1];this.openPartialSlices_.splice(this.openSliceCount-1,1);if(ts<slice.start){throw new Error('Slice '+slice.title+' end time is before its start.');}
+slice.duration=ts-slice.start;slice.didNotFinish=false;slice.colorId=opt_colorId||slice.colorId;if(opt_tts&&slice.cpuStart!==undefined){slice.cpuDuration=opt_tts-slice.cpuStart;}
+return slice;},pushCompleteSlice(category,title,ts,duration,tts,cpuDuration,opt_args,opt_argsStripped,opt_colorId,opt_bindId){const colorId=opt_colorId||ColorScheme.getColorIdForGeneralPurposeString(title);const sliceConstructorSubTypes=this.sliceConstructorSubTypes;const sliceType=sliceConstructorSubTypes.getConstructor(category,title);const slice=new sliceType(category,title,colorId,ts,opt_args?opt_args:{},duration,tts,cpuDuration,opt_argsStripped,opt_bindId);if(duration===undefined){slice.didNotFinish=true;}
+this.pushSlice(slice);return slice;},autoCloseOpenSlices(){this.updateBounds();const maxTimestamp=this.bounds.max;for(let sI=0;sI<this.slices.length;sI++){const slice=this.slices[sI];if(slice.didNotFinish){slice.duration=maxTimestamp-slice.start;}}
+this.openPartialSlices_=[];},shiftTimestampsForward(amount){for(let sI=0;sI<this.slices.length;sI++){const slice=this.slices[sI];slice.start=(slice.start+amount);}},updateBounds(){this.bounds.reset();for(let i=0;i<this.slices.length;i++){this.bounds.addValue(this.slices[i].start);this.bounds.addValue(this.slices[i].end);}},copySlice(slice){const sliceConstructorSubTypes=this.sliceConstructorSubTypes;const sliceType=sliceConstructorSubTypes.getConstructor(slice.category,slice.title);const newSlice=new sliceType(slice.category,slice.title,slice.colorId,slice.start,slice.args,slice.duration,slice.cpuStart,slice.cpuDuration);newSlice.didNotFinish=slice.didNotFinish;return newSlice;},*findTopmostSlicesInThisContainer(eventPredicate,opt_this){if(!this.haveTopLevelSlicesBeenBuilt){throw new Error('Nope');}
+for(const s of this.topLevelSlices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate);}},*childEvents(){yield*this.slices;},*childEventContainers(){},*getDescendantEventsInSortedRanges(ranges,opt_containerPredicate){if(ranges.length===0||(opt_containerPredicate!==undefined&&!opt_containerPredicate(this))){return;}
+let rangeIndex=0;let range=ranges[rangeIndex];for(const event of this.childEvents()){while(event.start>range.max){rangeIndex++;if(rangeIndex>=ranges.length)return;range=ranges[rangeIndex];}
+if(event.end>=range.min)yield event;}},getSlicesOfName(title){const slices=[];for(let i=0;i<this.slices.length;i++){if(this.slices[i].title===title){slices.push(this.slices[i]);}}
+return slices;},iterSlicesInTimeRange(callback,start,end){const ret=[];tr.b.iterateOverIntersectingIntervals(this.topLevelSlices,function(s){return s.start;},function(s){return s.duration;},start,end,function(topLevelSlice){callback(topLevelSlice);for(const slice of topLevelSlice.enumerateAllDescendents()){callback(slice);}});return ret;},findFirstSlice(){if(!this.haveTopLevelSlicesBeenBuilt){throw new Error('Nope');}
+if(0===this.slices.length)return undefined;return this.slices[0];},findSliceAtTs(ts){if(!this.haveTopLevelSlicesBeenBuilt)throw new Error('Nope');let i=tr.b.findIndexInSortedClosedIntervals(this.topLevelSlices,getSliceLo,getSliceHi,ts);if(i===-1||i===this.topLevelSlices.length){return undefined;}
+let curSlice=this.topLevelSlices[i];while(true){i=tr.b.findIndexInSortedClosedIntervals(curSlice.subSlices,getSliceLo,getSliceHi,ts);if(i===-1||i===curSlice.subSlices.length){return curSlice;}
+curSlice=curSlice.subSlices[i];}},findNextSliceAfter(ts,refGuid){let i=tr.b.findLowIndexInSortedArray(this.slices,getSliceLo,ts);if(i===this.slices.length){return undefined;}
+for(;i<this.slices.length;i++){const slice=this.slices[i];if(slice.start>ts)return slice;if(slice.guid<=refGuid)continue;return slice;}
+return undefined;},hasCpuDuration_(){if(this.slices.some(function(slice){return slice.cpuDuration!==undefined;}))return true;return false;},createSubSlices(){this.haveTopLevelSlicesBeenBuilt=true;this.createSubSlicesImpl_();if(!this.hasCpuDuration_()&&this.parentContainer.timeSlices){this.addCpuTimeToSubslices_(this.parentContainer.timeSlices);}
+this.slices.forEach(function(slice){let selfTime=slice.duration;for(let i=0;i<slice.subSlices.length;i++){selfTime-=slice.subSlices[i].duration;}
+slice.selfTime=selfTime;if(slice.cpuDuration===undefined)return;let cpuSelfTime=slice.cpuDuration;for(let i=0;i<slice.subSlices.length;i++){if(slice.subSlices[i].cpuDuration!==undefined){cpuSelfTime-=slice.subSlices[i].cpuDuration;}}
+slice.cpuSelfTime=cpuSelfTime;});},createSubSlicesImpl_(){const precisionUnit=this.model.intrinsicTimeUnit;function addSliceIfBounds(parent,child){if(parent.bounds(child,precisionUnit)){child.parentSlice=parent;if(parent.subSlices===undefined){parent.subSlices=[];}
+parent.subSlices.push(child);return true;}
+return false;}
+if(!this.slices.length)return;const ops=[];for(let i=0;i<this.slices.length;i++){if(this.slices[i].subSlices){this.slices[i].subSlices.splice(0,this.slices[i].subSlices.length);}
+ops.push(i);}
+const originalSlices=this.slices;ops.sort(function(ix,iy){const x=originalSlices[ix];const y=originalSlices[iy];if(x.start!==y.start){return x.start-y.start;}
+return ix-iy;});const slices=new Array(this.slices.length);for(let i=0;i<ops.length;i++){slices[i]=originalSlices[ops[i]];}
+let rootSlice=slices[0];this.topLevelSlices=[];this.topLevelSlices.push(rootSlice);rootSlice.isTopLevel=true;for(let i=1;i<slices.length;i++){const slice=slices[i];while(rootSlice!==undefined&&(!addSliceIfBounds(rootSlice,slice))){rootSlice=rootSlice.parentSlice;}
+if(rootSlice===undefined){this.topLevelSlices.push(slice);slice.isTopLevel=true;}
+rootSlice=slice;}
+this.slices=slices;},addCpuTimeToSubslices_(timeSlices){const SCHEDULING_STATE=tr.model.SCHEDULING_STATE;let sliceIdx=0;timeSlices.forEach(function(timeSlice){if(timeSlice.schedulingState===SCHEDULING_STATE.RUNNING){while(sliceIdx<this.topLevelSlices.length){if(this.addCpuTimeToSubslice_(this.topLevelSlices[sliceIdx],timeSlice)){sliceIdx++;}else{break;}}}},this);},addCpuTimeToSubslice_(slice,timeSlice){if(slice.start>timeSlice.end||slice.end<timeSlice.start){return slice.end<=timeSlice.end;}
+let duration=timeSlice.duration;if(slice.start>timeSlice.start){duration-=slice.start-timeSlice.start;}
+if(timeSlice.end>slice.end){duration-=timeSlice.end-slice.end;}
+if(slice.cpuDuration){slice.cpuDuration+=duration;}else{slice.cpuDuration=duration;}
+for(let i=0;i<slice.subSlices.length;i++){this.addCpuTimeToSubslice_(slice.subSlices[i],timeSlice);}
+return slice.end<=timeSlice.end;}};SliceGroup.merge=function(groupA,groupB){if(groupA.openPartialSlices_.length>0){throw new Error('groupA has open partial slices');}
+if(groupB.openPartialSlices_.length>0){throw new Error('groupB has open partial slices');}
+if(groupA.parentContainer!==groupB.parentContainer){throw new Error('Different parent threads. Cannot merge');}
+if(groupA.sliceConstructor!==groupB.sliceConstructor){throw new Error('Different slice constructors. Cannot merge');}
+const result=new SliceGroup(groupA.parentContainer,groupA.sliceConstructor,groupA.name_);const slicesA=groupA.slices;const slicesB=groupB.slices;let idxA=0;let idxB=0;const openA=[];const openB=[];const splitOpenSlices=function(when){for(let i=0;i<openB.length;i++){const oldSlice=openB[i];const oldEnd=oldSlice.end;if(when<oldSlice.start||oldEnd<when){throw new Error('slice should not be split');}
+const newSlice=result.copySlice(oldSlice);newSlice.start=when;newSlice.duration=oldEnd-when;if(newSlice.title.indexOf(' (cont.)')===-1){newSlice.title+=' (cont.)';}
+oldSlice.duration=when-oldSlice.start;openB[i]=newSlice;result.pushSlice(newSlice);}};const closeOpenSlices=function(upTo){while(openA.length>0||openB.length>0){const nextA=openA[openA.length-1];const nextB=openB[openB.length-1];const endA=nextA&&nextA.end;const endB=nextB&&nextB.end;if((endA===undefined||endA>upTo)&&(endB===undefined||endB>upTo)){return;}
+if(endB===undefined||endA<endB){splitOpenSlices(endA);openA.pop();}else{openB.pop();}}};while(idxA<slicesA.length||idxB<slicesB.length){const sA=slicesA[idxA];const sB=slicesB[idxB];let nextSlice;let isFromB;if(sA===undefined||(sB!==undefined&&sA.start>sB.start)){nextSlice=result.copySlice(sB);isFromB=true;idxB++;}else{nextSlice=result.copySlice(sA);isFromB=false;idxA++;}
+closeOpenSlices(nextSlice.start);result.pushSlice(nextSlice);if(isFromB){openB.push(nextSlice);}else{splitOpenSlices(nextSlice.start);openA.push(nextSlice);}}
+closeOpenSlices();return result;};return{SliceGroup,};});'use strict';tr.exportTo('tr.model',function(){const AsyncSlice=tr.model.AsyncSlice;const AsyncSliceGroup=tr.model.AsyncSliceGroup;const SliceGroup=tr.model.SliceGroup;const ThreadSlice=tr.model.ThreadSlice;const ThreadTimeSlice=tr.model.ThreadTimeSlice;function Thread(parent,tid){if(!parent){throw new Error('Parent must be provided.');}
+tr.model.EventContainer.call(this);this.parent=parent;this.sortIndex=0;this.tid=tid;this.name=undefined;this.samples_=undefined;this.sliceGroup=new SliceGroup(this,ThreadSlice,'slices');this.timeSlices=undefined;this.kernelSliceGroup=new SliceGroup(this,ThreadSlice,'kernel-slices');this.asyncSliceGroup=new AsyncSliceGroup(this,'async-slices');}
+Thread.prototype={__proto__:tr.model.EventContainer.prototype,get model(){return this.parent.model;},get stableId(){return this.parent.stableId+'.'+this.tid;},compareTo(that){return Thread.compare(this,that);},*childEventContainers(){if(this.sliceGroup.length){yield this.sliceGroup;}
+if(this.kernelSliceGroup.length){yield this.kernelSliceGroup;}
+if(this.asyncSliceGroup.length){yield this.asyncSliceGroup;}},*childEvents(){if(this.timeSlices){yield*this.timeSlices;}},iterateAllPersistableObjects(cb){cb(this);if(this.sliceGroup.length){cb(this.sliceGroup);}
+this.asyncSliceGroup.viewSubGroups.forEach(cb);},shiftTimestampsForward(amount){this.sliceGroup.shiftTimestampsForward(amount);if(this.timeSlices){for(let i=0;i<this.timeSlices.length;i++){const slice=this.timeSlices[i];slice.start+=amount;}}
+this.kernelSliceGroup.shiftTimestampsForward(amount);this.asyncSliceGroup.shiftTimestampsForward(amount);},get isEmpty(){if(this.sliceGroup.length)return false;if(this.sliceGroup.openSliceCount)return false;if(this.timeSlices&&this.timeSlices.length)return false;if(this.kernelSliceGroup.length)return false;if(this.asyncSliceGroup.length)return false;if(this.samples_.length)return false;return true;},updateBounds(){this.bounds.reset();this.sliceGroup.updateBounds();this.bounds.addRange(this.sliceGroup.bounds);this.kernelSliceGroup.updateBounds();this.bounds.addRange(this.kernelSliceGroup.bounds);this.asyncSliceGroup.updateBounds();this.bounds.addRange(this.asyncSliceGroup.bounds);if(this.timeSlices&&this.timeSlices.length){this.bounds.addValue(this.timeSlices[0].start);this.bounds.addValue(this.timeSlices[this.timeSlices.length-1].end);}
+if(this.samples_&&this.samples_.length){this.bounds.addValue(this.samples_[0].start);this.bounds.addValue(this.samples_[this.samples_.length-1].end);}},addCategoriesToDict(categoriesDict){for(let i=0;i<this.sliceGroup.length;i++){categoriesDict[this.sliceGroup.slices[i].category]=true;}
+for(let i=0;i<this.kernelSliceGroup.length;i++){categoriesDict[this.kernelSliceGroup.slices[i].category]=true;}
+for(let i=0;i<this.asyncSliceGroup.length;i++){categoriesDict[this.asyncSliceGroup.slices[i].category]=true;}
+if(this.samples_){for(let i=0;i<this.samples_.length;i++){categoriesDict[this.samples_[i].category]=true;}}},autoCloseOpenSlices(){this.sliceGroup.autoCloseOpenSlices();this.asyncSliceGroup.autoCloseOpenSlices();this.kernelSliceGroup.autoCloseOpenSlices();},mergeKernelWithUserland(){if(this.kernelSliceGroup.length>0){const newSlices=SliceGroup.merge(this.sliceGroup,this.kernelSliceGroup);this.sliceGroup.slices=newSlices.slices;this.kernelSliceGroup=new SliceGroup(this);this.updateBounds();}},createSubSlices(){this.sliceGroup.createSubSlices();this.samples_=this.parent.model.samples.filter(sample=>sample.thread===this);},get userFriendlyName(){return this.name||this.tid;},get userFriendlyDetails(){return'tid: '+this.tid+
+(this.name?', name: '+this.name:'');},getSettingsKey(){if(!this.name)return undefined;const parentKey=this.parent.getSettingsKey();if(!parentKey)return undefined;return parentKey+'.'+this.name;},getProcess(){return this.parent;},indexOfTimeSlice(timeSlice){const i=tr.b.findLowIndexInSortedArray(this.timeSlices,function(slice){return slice.start;},timeSlice.start);if(this.timeSlices[i]!==timeSlice)return undefined;return i;},sumOverToplevelSlicesInRange(range,func){let sum=0;tr.b.iterateOverIntersectingIntervals(this.sliceGroup.topLevelSlices,slice=>slice.start,slice=>slice.end,range.min,range.max,slice=>{let fractionOfSliceInsideRangeOfInterest=1;if(slice.duration>0){const intersection=range.findIntersection(slice.range);fractionOfSliceInsideRangeOfInterest=intersection.duration/slice.duration;}
+sum+=func(slice)*fractionOfSliceInsideRangeOfInterest;});return sum;},getCpuTimeForRange(range){return this.sumOverToplevelSlicesInRange(range,slice=>slice.cpuDuration||0);},getNumToplevelSlicesForRange(range){return this.sumOverToplevelSlicesInRange(range,slice=>1);},getWallTimeForRange(range){return this.sumOverToplevelSlicesInRange(range,slice=>slice.duration||0);},getSchedulingStatsForRange(start,end){const stats={};if(!this.timeSlices)return stats;function addStatsForSlice(threadTimeSlice){const overlapStart=Math.max(threadTimeSlice.start,start);const overlapEnd=Math.min(threadTimeSlice.end,end);const schedulingState=threadTimeSlice.schedulingState;if(!(schedulingState in stats))stats[schedulingState]=0;stats[schedulingState]+=overlapEnd-overlapStart;}
+tr.b.iterateOverIntersectingIntervals(this.timeSlices,function(x){return x.start;},function(x){return x.end;},start,end,addStatsForSlice);return stats;},get samples(){return this.samples_;},get type(){const re=/^[^0-9|\/]+/;const matches=re.exec(this.name);if(matches&&matches[0])return matches[0];throw new Error('Could not determine thread type for thread name '+
+this.name);}};Thread.compare=function(x,y){let tmp=x.parent.compareTo(y.parent);if(tmp)return tmp;tmp=x.sortIndex-y.sortIndex;if(tmp)return tmp;if(x.name!==undefined){if(y.name!==undefined){tmp=x.name.localeCompare(y.name);}else{tmp=-1;}}else if(y.name!==undefined){tmp=1;}
+if(tmp)return tmp;return x.tid-y.tid;};return{Thread,};});'use strict';tr.exportTo('tr.model',function(){const Thread=tr.model.Thread;const Counter=tr.model.Counter;function ProcessBase(model){if(!model){throw new Error('Must provide a model');}
+tr.model.EventContainer.call(this);this.model=model;this.threads={};this.counters={};this.objects=new tr.model.ObjectCollection(this);this.sortIndex=0;}
+ProcessBase.compare=function(x,y){return x.sortIndex-y.sortIndex;};ProcessBase.prototype={__proto__:tr.model.EventContainer.prototype,get stableId(){throw new Error('Not implemented');},*childEventContainers(){yield*Object.values(this.threads);yield*Object.values(this.counters);yield this.objects;},iterateAllPersistableObjects(cb){cb(this);for(const tid in this.threads){this.threads[tid].iterateAllPersistableObjects(cb);}},get numThreads(){let n=0;for(const p in this.threads){n++;}
+return n;},shiftTimestampsForward(amount){for(const child of this.childEventContainers()){child.shiftTimestampsForward(amount);}},autoCloseOpenSlices(){for(const tid in this.threads){const thread=this.threads[tid];thread.autoCloseOpenSlices();}},autoDeleteObjects(maxTimestamp){this.objects.autoDeleteObjects(maxTimestamp);},preInitializeObjects(){this.objects.preInitializeAllObjects();},initializeObjects(){this.objects.initializeAllObjects();},mergeKernelWithUserland(){for(const tid in this.threads){const thread=this.threads[tid];thread.mergeKernelWithUserland();}},updateBounds(){this.bounds.reset();for(const tid in this.threads){this.threads[tid].updateBounds();this.bounds.addRange(this.threads[tid].bounds);}
+for(const id in this.counters){this.counters[id].updateBounds();this.bounds.addRange(this.counters[id].bounds);}
+this.objects.updateBounds();this.bounds.addRange(this.objects.bounds);},addCategoriesToDict(categoriesDict){for(const tid in this.threads){this.threads[tid].addCategoriesToDict(categoriesDict);}
+for(const id in this.counters){categoriesDict[this.counters[id].category]=true;}
+this.objects.addCategoriesToDict(categoriesDict);},findAllThreadsMatching(predicate,opt_this){const threads=[];for(const tid in this.threads){const thread=this.threads[tid];if(predicate.call(opt_this,thread)){threads.push(thread);}}
+return threads;},findAllThreadsNamed(name){const threads=this.findAllThreadsMatching(function(thread){if(!thread.name)return false;return thread.name===name;});return threads;},findAtMostOneThreadNamed(name){const threads=this.findAllThreadsNamed(name);if(threads.length===0)return undefined;if(threads.length>1){throw new Error('Expected no more than one '+name);}
+return threads[0];},pruneEmptyContainers(){const threadsToKeep={};for(const tid in this.threads){const thread=this.threads[tid];if(!thread.isEmpty){threadsToKeep[tid]=thread;}}
+this.threads=threadsToKeep;},getThread(tid){return this.threads[tid];},getOrCreateThread(tid){if(!this.threads[tid]){this.threads[tid]=new Thread(this,tid);}
+return this.threads[tid];},getOrCreateCounter(cat,name){const id=cat+'.'+name;if(!this.counters[id]){this.counters[id]=new Counter(this,id,cat,name);}
+return this.counters[id];},getSettingsKey(){throw new Error('Not implemented');},createSubSlices(){for(const tid in this.threads){this.threads[tid].createSubSlices();}}};return{ProcessBase,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;const Counter=tr.model.Counter;const CpuSlice=tr.model.CpuSlice;function Cpu(kernel,number){if(kernel===undefined||number===undefined){throw new Error('Missing arguments');}
+this.kernel=kernel;this.cpuNumber=number;this.slices=[];this.counters={};this.bounds_=new tr.b.math.Range();this.samples_=undefined;this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;}
+Cpu.prototype={__proto__:tr.model.EventContainer.prototype,get samples(){return this.samples_;},get userFriendlyName(){return'CPU '+this.cpuNumber;},*findTopmostSlicesInThisContainer(eventPredicate,opt_this){for(const s of this.slices){yield*s.findTopmostSlicesRelativeToThisSlice(eventPredicate,opt_this);}},*childEvents(){yield*this.slices;if(this.samples_){yield*this.samples_;}},*childEventContainers(){yield*Object.values(this.counters);},getOrCreateCounter(cat,name){const id=cat+'.'+name;if(!this.counters[id]){this.counters[id]=new Counter(this,id,cat,name);}
+return this.counters[id];},getCounter(cat,name){const id=cat+'.'+name;if(!this.counters[id]){return undefined;}
+return this.counters[id];},shiftTimestampsForward(amount){for(let sI=0;sI<this.slices.length;sI++){this.slices[sI].start=(this.slices[sI].start+amount);}
+for(const id in this.counters){this.counters[id].shiftTimestampsForward(amount);}},updateBounds(){this.bounds_.reset();if(this.slices.length){this.bounds_.addValue(this.slices[0].start);this.bounds_.addValue(this.slices[this.slices.length-1].end);}
+for(const id in this.counters){this.counters[id].updateBounds();this.bounds_.addRange(this.counters[id].bounds);}
+if(this.samples_&&this.samples_.length){this.bounds_.addValue(this.samples_[0].start);this.bounds_.addValue(this.samples_[this.samples_.length-1].end);}},createSubSlices(){this.samples_=this.kernel.model.samples.filter(function(sample){return sample.cpu===this;},this);},addCategoriesToDict(categoriesDict){for(let i=0;i<this.slices.length;i++){categoriesDict[this.slices[i].category]=true;}
+for(const id in this.counters){categoriesDict[this.counters[id].category]=true;}
+for(let i=0;i<this.samples_.length;i++){categoriesDict[this.samples_[i].category]=true;}},indexOf(cpuSlice){const i=tr.b.findLowIndexInSortedArray(this.slices,function(slice){return slice.start;},cpuSlice.start);if(this.slices[i]!==cpuSlice)return undefined;return i;},closeActiveThread(endTimestamp,args){if(this.lastActiveThread_===undefined||this.lastActiveThread_===0){return;}
+if(endTimestamp<this.lastActiveTimestamp_){throw new Error('The end timestamp of a thread running on CPU '+
+this.cpuNumber+' is before its start timestamp.');}
+for(const key in args){this.lastActiveArgs_[key]=args[key];}
+const duration=endTimestamp-this.lastActiveTimestamp_;const slice=new tr.model.CpuSlice('',this.lastActiveName_,ColorScheme.getColorIdForGeneralPurposeString(this.lastActiveName_),this.lastActiveTimestamp_,this.lastActiveArgs_,duration);slice.cpu=this;this.slices.push(slice);this.lastActiveTimestamp_=undefined;this.lastActiveThread_=undefined;this.lastActiveName_=undefined;this.lastActiveArgs_=undefined;},switchActiveThread(timestamp,oldThreadArgs,newThreadId,newThreadName,newThreadArgs){this.closeActiveThread(timestamp,oldThreadArgs);this.lastActiveTimestamp_=timestamp;this.lastActiveThread_=newThreadId;this.lastActiveName_=newThreadName;this.lastActiveArgs_=newThreadArgs;},getFreqStatsForRange(range){const stats={};function addStatsForFreq(freqSample,index){const freqEnd=(index<freqSample.series_.length-1)?freqSample.series_.samples_[index+1].timestamp:range.max;const freqRange=tr.b.math.Range.fromExplicitRange(freqSample.timestamp,freqEnd);const intersection=freqRange.findIntersection(range);if(!(freqSample.value in stats)){stats[freqSample.value]=0;}
+stats[freqSample.value]+=intersection.duration;}
+const freqCounter=this.getCounter('','Clock Frequency');if(freqCounter!==undefined){const freqSeries=freqCounter.getSeries(0);if(!freqSeries)return;tr.b.iterateOverIntersectingIntervals(freqSeries.samples_,function(x){return x.timestamp;},function(x,index){if(index<freqSeries.length-1){return freqSeries.samples_[index+1].timestamp;}
+return range.max;},range.min,range.max,addStatsForFreq);}
+return stats;}};Cpu.compare=function(x,y){return x.cpuNumber-y.cpuNumber;};return{Cpu,};});'use strict';tr.exportTo('tr.model',function(){const Event=tr.model.Event;const EventRegistry=tr.model.EventRegistry;function PowerSample(series,start,powerInW){Event.call(this);this.series_=series;this.start_=parseFloat(start);this.powerInW_=parseFloat(powerInW);}
+PowerSample.prototype={__proto__:Event.prototype,get series(){return this.series_;},get start(){return this.start_;},set start(value){this.start_=value;},get powerInW(){return this.powerInW_;},set powerInW(value){this.powerInW_=value;},addBoundsToRange(range){range.addValue(this.start);}};EventRegistry.register(PowerSample,{name:'powerSample',pluralName:'powerSamples'});return{PowerSample,};});'use strict';tr.exportTo('tr.model',function(){const PowerSample=tr.model.PowerSample;function PowerSeries(device){tr.model.EventContainer.call(this);this.device_=device;this.samples_=[];}
+PowerSeries.prototype={__proto__:tr.model.EventContainer.prototype,get device(){return this.device_;},get samples(){return this.samples_;},get stableId(){return this.device_.stableId+'.PowerSeries';},addPowerSample(ts,val){const sample=new PowerSample(this,ts,val);this.samples_.push(sample);return sample;},getEnergyConsumedInJ(start,end){const measurementRange=tr.b.math.Range.fromExplicitRange(start,end);let energyConsumedInJ=0;let startIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,start)-1;const endIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,end);if(startIndex<0){startIndex=0;}
+for(let i=startIndex;i<endIndex;i++){const sample=this.samples[i];const nextSample=this.samples[i+1];const sampleRange=new tr.b.math.Range();sampleRange.addValue(sample.start);sampleRange.addValue(nextSample?nextSample.start:sample.start);const intersectionRangeInMs=measurementRange.findIntersection(sampleRange);const durationInS=tr.b.convertUnit(intersectionRangeInMs.duration,tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);energyConsumedInJ+=durationInS*sample.powerInW;}
+return energyConsumedInJ;},getSamplesWithinRange(start,end){const startIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,start);const endIndex=tr.b.findLowIndexInSortedArray(this.samples,x=>x.start,end);return this.samples.slice(startIndex,endIndex);},shiftTimestampsForward(amount){for(let i=0;i<this.samples_.length;++i){this.samples_[i].start+=amount;}},updateBounds(){this.bounds.reset();if(this.samples_.length===0)return;this.bounds.addValue(this.samples_[0].start);this.bounds.addValue(this.samples_[this.samples_.length-1].start);},*childEvents(){yield*this.samples_;},};return{PowerSeries,};});'use strict';tr.exportTo('tr.model',function(){function Device(model){if(!model){throw new Error('Must provide a model.');}
+tr.model.EventContainer.call(this);this.powerSeries_=undefined;this.cpuUsageSeries_=undefined;this.vSyncTimestamps_=[];}
+Device.compare=function(x,y){return x.guid-y.guid;};Device.prototype={__proto__:tr.model.EventContainer.prototype,compareTo(that){return Device.compare(this,that);},get userFriendlyName(){return'Device';},get userFriendlyDetails(){return'Device';},get stableId(){return'Device';},getSettingsKey(){return'device';},get powerSeries(){return this.powerSeries_;},set powerSeries(powerSeries){this.powerSeries_=powerSeries;},get cpuUsageSeries(){return this.cpuUsageSeries_;},set cpuUsageSeries(cpuUsageSeries){this.cpuUsageSeries_=cpuUsageSeries;},get vSyncTimestamps(){return this.vSyncTimestamps_;},set vSyncTimestamps(value){this.vSyncTimestamps_=value;},updateBounds(){this.bounds.reset();for(const child of this.childEventContainers()){child.updateBounds();this.bounds.addRange(child.bounds);}},shiftTimestampsForward(amount){for(const child of this.childEventContainers()){child.shiftTimestampsForward(amount);}
+for(let i=0;i<this.vSyncTimestamps_.length;i++){this.vSyncTimestamps_[i]+=amount;}},addCategoriesToDict(categoriesDict){},*childEventContainers(){if(this.powerSeries_){yield this.powerSeries_;}
+if(this.cpuUsageSeries_){yield this.cpuUsageSeries_;}}};return{Device,};});'use strict';tr.exportTo('tr.model',function(){function FlowEvent(category,id,title,colorId,start,args,opt_duration){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.start=start;this.args=args;this.id=id;this.startSlice=undefined;this.endSlice=undefined;this.startStackFrame=undefined;this.endStackFrame=undefined;if(opt_duration!==undefined){this.duration=opt_duration;}}
+FlowEvent.prototype={__proto__:tr.model.TimedEvent.prototype,get userFriendlyName(){return'Flow event named '+this.title+' at '+
+tr.b.Unit.byName.timeStampInMs.format(this.timestamp);}};tr.model.EventRegistry.register(FlowEvent,{name:'flowEvent',pluralName:'flowEvents'});return{FlowEvent,};});'use strict';tr.exportTo('tr.model',function(){function ContainerMemoryDump(start){tr.model.TimedEvent.call(this,start);this.levelOfDetail=undefined;this.memoryAllocatorDumps_=undefined;this.memoryAllocatorDumpsByFullName_=undefined;}
+ContainerMemoryDump.LevelOfDetail={BACKGROUND:0,LIGHT:1,DETAILED:2};ContainerMemoryDump.prototype={__proto__:tr.model.TimedEvent.prototype,shiftTimestampsForward(amount){this.start+=amount;},get memoryAllocatorDumps(){return this.memoryAllocatorDumps_;},set memoryAllocatorDumps(memoryAllocatorDumps){this.memoryAllocatorDumps_=memoryAllocatorDumps;this.forceRebuildingMemoryAllocatorDumpByFullNameIndex();},getMemoryAllocatorDumpByFullName(fullName){if(this.memoryAllocatorDumps_===undefined)return undefined;if(this.memoryAllocatorDumpsByFullName_===undefined){const index={};function addDumpsToIndex(dumps){dumps.forEach(function(dump){index[dump.fullName]=dump;addDumpsToIndex(dump.children);});}
+addDumpsToIndex(this.memoryAllocatorDumps_);this.memoryAllocatorDumpsByFullName_=index;}
+return this.memoryAllocatorDumpsByFullName_[fullName];},forceRebuildingMemoryAllocatorDumpByFullNameIndex(){this.memoryAllocatorDumpsByFullName_=undefined;},iterateRootAllocatorDumps(fn,opt_this){if(this.memoryAllocatorDumps===undefined)return;this.memoryAllocatorDumps.forEach(fn,opt_this||this);}};return{ContainerMemoryDump,};});'use strict';tr.exportTo('tr.model',function(){function MemoryAllocatorDump(containerMemoryDump,fullName,opt_guid){this.fullName=fullName;this.parent=undefined;this.children=[];this.numerics={};this.diagnostics={};this.containerMemoryDump=containerMemoryDump;this.owns=undefined;this.ownedBy=[];this.ownedBySiblingSizes=new Map();this.retains=[];this.retainedBy=[];this.weak=false;this.infos=[];this.guid=opt_guid;}
+MemoryAllocatorDump.SIZE_NUMERIC_NAME='size';MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME='effective_size';MemoryAllocatorDump.RESIDENT_SIZE_NUMERIC_NAME='resident_size';MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME=MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;MemoryAllocatorDump.prototype={get name(){return this.fullName.substring(this.fullName.lastIndexOf('/')+1);},get quantifiedName(){return'\''+this.fullName+'\' in '+
+this.containerMemoryDump.containerName;},getDescendantDumpByFullName(fullName){return this.containerMemoryDump.getMemoryAllocatorDumpByFullName(this.fullName+'/'+fullName);},isDescendantOf(otherDump){if(this===otherDump)return true;if(this.parent===undefined)return false;return this.parent.isDescendantOf(otherDump);},addNumeric(name,numeric){if(!(numeric instanceof tr.b.Scalar)){throw new Error('Numeric value must be an instance of Scalar.');}
+if(name in this.numerics){throw new Error('Duplicate numeric name: '+name+'.');}
+this.numerics[name]=numeric;},addDiagnostic(name,text){if(typeof text!=='string'){throw new Error('Diagnostic text must be a string.');}
+if(name in this.diagnostics){throw new Error('Duplicate diagnostic name: '+name+'.');}
+this.diagnostics[name]=text;},aggregateNumericsRecursively(opt_model){const numericNames=new Set();this.children.forEach(function(child){child.aggregateNumericsRecursively(opt_model);for(const[item,value]of Object.entries(child.numerics)){numericNames.add(item,value);}},this);numericNames.forEach(function(numericName){if(numericName===MemoryAllocatorDump.SIZE_NUMERIC_NAME||numericName===MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME||this.numerics[numericName]!==undefined){return;}
+this.numerics[numericName]=MemoryAllocatorDump.aggregateNumerics(this.children.map(function(child){return child.numerics[numericName];}),opt_model);},this);}};MemoryAllocatorDump.aggregateNumerics=function(numerics,opt_model){let shouldLogWarning=!!opt_model;let aggregatedUnit=undefined;let aggregatedValue=0;numerics.forEach(function(numeric){if(numeric===undefined)return;const unit=numeric.unit;if(aggregatedUnit===undefined){aggregatedUnit=unit;}else if(aggregatedUnit!==unit){if(shouldLogWarning){opt_model.importWarning({type:'numeric_parse_error',message:'Multiple units provided for numeric: \''+
+aggregatedUnit.unitName+'\' and \''+unit.unitName+'\'.'});shouldLogWarning=false;}
+aggregatedUnit=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;}
+aggregatedValue+=numeric.value;},this);if(aggregatedUnit===undefined)return undefined;return new tr.b.Scalar(aggregatedUnit,aggregatedValue);};function MemoryAllocatorDumpLink(source,target,opt_importance){this.source=source;this.target=target;this.importance=opt_importance;this.size=undefined;}
+const MemoryAllocatorDumpInfoType={PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN:0,PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER:1};return{MemoryAllocatorDump,MemoryAllocatorDumpLink,MemoryAllocatorDumpInfoType,};});'use strict';tr.exportTo('tr.model',function(){function GlobalMemoryDump(model,start){tr.model.ContainerMemoryDump.call(this,start);this.model=model;this.processMemoryDumps={};}
+const SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;const EFFECTIVE_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME;const MemoryAllocatorDumpInfoType=tr.model.MemoryAllocatorDumpInfoType;const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;function getSize(dump){const numeric=dump.numerics[SIZE_NUMERIC_NAME];if(numeric===undefined)return 0;return numeric.value;}
+function hasSize(dump){return dump.numerics[SIZE_NUMERIC_NAME]!==undefined;}
+function optional(value,defaultValue){if(value===undefined)return defaultValue;return value;}
+GlobalMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get stableId(){return'memory.'+this.model.globalMemoryDumps.indexOf(this);},get userFriendlyName(){return'Global memory dump at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get containerName(){return'global space';},finalizeGraph(){this.removeWeakDumps();this.setUpTracingOverheadOwnership();this.aggregateNumerics();this.calculateSizes();this.calculateEffectiveSizes();this.discountTracingOverheadFromVmRegions();this.forceRebuildingMemoryAllocatorDumpByFullNameIndices();},removeWeakDumps(){this.traverseAllocatorDumpsInDepthFirstPreOrder(function(dump){if(dump.weak)return;if((dump.owns!==undefined&&dump.owns.target.weak)||(dump.parent!==undefined&&dump.parent.weak)){dump.weak=true;}});function removeWeakDumpsFromListRecursively(dumps){tr.b.inPlaceFilter(dumps,function(dump){if(dump.weak){return false;}
+removeWeakDumpsFromListRecursively(dump.children);tr.b.inPlaceFilter(dump.ownedBy,function(ownershipLink){return!ownershipLink.source.weak;});return true;});}
+this.iterateContainerDumps(function(containerDump){const memoryAllocatorDumps=containerDump.memoryAllocatorDumps;if(memoryAllocatorDumps!==undefined){removeWeakDumpsFromListRecursively(memoryAllocatorDumps);}});},calculateSizes(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateMemoryAllocatorDumpSize_.bind(this));},calculateMemoryAllocatorDumpSize_(dump){let shouldDefineSize=false;function getDependencySize(dependencyDump){const numeric=dependencyDump.numerics[SIZE_NUMERIC_NAME];if(numeric===undefined)return 0;shouldDefineSize=true;return numeric.value;}
+const sizeNumeric=dump.numerics[SIZE_NUMERIC_NAME];let size=0;let checkDependencySizeIsConsistent=function(){};if(sizeNumeric!==undefined){size=sizeNumeric.value;shouldDefineSize=true;if(sizeNumeric.unit!==tr.b.Unit.byName.sizeInBytes_smallerIsBetter){this.model.importWarning({type:'memory_dump_parse_error',message:'Invalid unit of \'size\' numeric of memory allocator '+'dump '+dump.quantifiedName+': '+
+sizeNumeric.unit.unitName+'.'});}
+checkDependencySizeIsConsistent=function(dependencySize,dependencyInfoType,dependencyName){if(size>=dependencySize)return;this.model.importWarning({type:'memory_dump_parse_error',message:'Size provided by memory allocator dump \''+
+dump.fullName+'\''+
+tr.b.Unit.byName.sizeInBytes.format(size)+') is less than '+dependencyName+' ('+
+tr.b.Unit.byName.sizeInBytes.format(dependencySize)+').'});dump.infos.push({type:dependencyInfoType,providedSize:size,dependencySize});}.bind(this);}
+let aggregatedChildrenSize=0;const allOverlaps={};dump.children.forEach(function(childDump){function aggregateDescendantDump(descendantDump){const ownedDumpLink=descendantDump.owns;if(ownedDumpLink!==undefined&&ownedDumpLink.target.isDescendantOf(dump)){let ownedChildDump=ownedDumpLink.target;while(ownedChildDump.parent!==dump){ownedChildDump=ownedChildDump.parent;}
+if(childDump!==ownedChildDump){const ownedBySiblingSize=getDependencySize(descendantDump);if(ownedBySiblingSize>0){const previousTotalOwnedBySiblingSize=ownedChildDump.ownedBySiblingSizes.get(childDump)||0;const updatedTotalOwnedBySiblingSize=previousTotalOwnedBySiblingSize+ownedBySiblingSize;ownedChildDump.ownedBySiblingSizes.set(childDump,updatedTotalOwnedBySiblingSize);}}
+return;}
+if(descendantDump.children.length===0){aggregatedChildrenSize+=getDependencySize(descendantDump);return;}
+descendantDump.children.forEach(aggregateDescendantDump);}
+aggregateDescendantDump(childDump);});checkDependencySizeIsConsistent(aggregatedChildrenSize,PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN,'the aggregated size of its children');let largestOwnerSize=0;dump.ownedBy.forEach(function(ownershipLink){const owner=ownershipLink.source;const ownerSize=getDependencySize(owner);largestOwnerSize=Math.max(largestOwnerSize,ownerSize);});checkDependencySizeIsConsistent(largestOwnerSize,PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER,'the size of its largest owner');if(!shouldDefineSize){delete dump.numerics[SIZE_NUMERIC_NAME];return;}
+size=Math.max(size,aggregatedChildrenSize,largestOwnerSize);dump.numerics[SIZE_NUMERIC_NAME]=new tr.b.Scalar(tr.b.Unit.byName.sizeInBytes_smallerIsBetter,size);if(aggregatedChildrenSize<size&&dump.children!==undefined&&dump.children.length>0){const virtualChild=new tr.model.MemoryAllocatorDump(dump.containerMemoryDump,dump.fullName+'/<unspecified>');virtualChild.parent=dump;dump.children.unshift(virtualChild);virtualChild.numerics[SIZE_NUMERIC_NAME]=new tr.b.Scalar(tr.b.Unit.byName.sizeInBytes_smallerIsBetter,size-aggregatedChildrenSize);}},calculateEffectiveSizes(){this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpSubSizes_.bind(this));this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpOwnershipCoefficient_.bind(this));this.traverseAllocatorDumpsInDepthFirstPreOrder(this.calculateDumpCumulativeOwnershipCoefficient_.bind(this));this.traverseAllocatorDumpsInDepthFirstPostOrder(this.calculateDumpEffectiveSize_.bind(this));},calculateDumpSubSizes_(dump){if(!hasSize(dump))return;if(dump.children===undefined||dump.children.length===0){const size=getSize(dump);dump.notOwningSubSize_=size;dump.notOwnedSubSize_=size;return;}
+let notOwningSubSize=0;dump.children.forEach(function(childDump){if(childDump.owns!==undefined)return;notOwningSubSize+=optional(childDump.notOwningSubSize_,0);});dump.notOwningSubSize_=notOwningSubSize;let notOwnedSubSize=0;dump.children.forEach(function(childDump){if(childDump.ownedBy.length===0){notOwnedSubSize+=optional(childDump.notOwnedSubSize_,0);return;}
+let largestChildOwnerSize=0;childDump.ownedBy.forEach(function(ownershipLink){largestChildOwnerSize=Math.max(largestChildOwnerSize,getSize(ownershipLink.source));});notOwnedSubSize+=getSize(childDump)-largestChildOwnerSize;});dump.notOwnedSubSize_=notOwnedSubSize;},calculateDumpOwnershipCoefficient_(dump){if(!hasSize(dump))return;if(dump.ownedBy.length===0)return;const owners=dump.ownedBy.map(function(ownershipLink){return{dump:ownershipLink.source,importance:optional(ownershipLink.importance,0),notOwningSubSize:optional(ownershipLink.source.notOwningSubSize_,0)};});owners.sort(function(a,b){if(a.importance===b.importance){return a.notOwningSubSize-b.notOwningSubSize;}
+return b.importance-a.importance;});let currentImportanceStartPos=0;let alreadyAttributedSubSize=0;while(currentImportanceStartPos<owners.length){const currentImportance=owners[currentImportanceStartPos].importance;let nextImportanceStartPos=currentImportanceStartPos+1;while(nextImportanceStartPos<owners.length&&owners[nextImportanceStartPos].importance===currentImportance){nextImportanceStartPos++;}
+let attributedNotOwningSubSize=0;for(let pos=currentImportanceStartPos;pos<nextImportanceStartPos;pos++){const owner=owners[pos];const notOwningSubSize=owner.notOwningSubSize;if(notOwningSubSize>alreadyAttributedSubSize){attributedNotOwningSubSize+=(notOwningSubSize-alreadyAttributedSubSize)/(nextImportanceStartPos-pos);alreadyAttributedSubSize=notOwningSubSize;}
+let owningCoefficient=0;if(notOwningSubSize!==0){owningCoefficient=attributedNotOwningSubSize/notOwningSubSize;}
+owner.dump.owningCoefficient_=owningCoefficient;}
+currentImportanceStartPos=nextImportanceStartPos;}
+const notOwnedSubSize=optional(dump.notOwnedSubSize_,0);const remainderSubSize=notOwnedSubSize-alreadyAttributedSubSize;let ownedCoefficient=0;if(notOwnedSubSize!==0){ownedCoefficient=remainderSubSize/notOwnedSubSize;}
+dump.ownedCoefficient_=ownedCoefficient;},calculateDumpCumulativeOwnershipCoefficient_(dump){if(!hasSize(dump))return;let cumulativeOwnedCoefficient=optional(dump.ownedCoefficient_,1);const parent=dump.parent;if(dump.parent!==undefined){cumulativeOwnedCoefficient*=dump.parent.cumulativeOwnedCoefficient_;}
+dump.cumulativeOwnedCoefficient_=cumulativeOwnedCoefficient;let cumulativeOwningCoefficient;if(dump.owns!==undefined){cumulativeOwningCoefficient=dump.owningCoefficient_*dump.owns.target.cumulativeOwningCoefficient_;}else if(dump.parent!==undefined){cumulativeOwningCoefficient=dump.parent.cumulativeOwningCoefficient_;}else{cumulativeOwningCoefficient=1;}
+dump.cumulativeOwningCoefficient_=cumulativeOwningCoefficient;},calculateDumpEffectiveSize_(dump){if(!hasSize(dump)){delete dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME];return;}
+let effectiveSize;if(dump.children===undefined||dump.children.length===0){effectiveSize=getSize(dump)*dump.cumulativeOwningCoefficient_*dump.cumulativeOwnedCoefficient_;}else{effectiveSize=0;dump.children.forEach(function(childDump){if(!hasSize(childDump))return;effectiveSize+=childDump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME].value;});}
+dump.numerics[EFFECTIVE_SIZE_NUMERIC_NAME]=new tr.b.Scalar(tr.b.Unit.byName.sizeInBytes_smallerIsBetter,effectiveSize);},aggregateNumerics(){this.iterateRootAllocatorDumps(function(dump){dump.aggregateNumericsRecursively(this.model);});this.iterateRootAllocatorDumps(this.propagateNumericsAndDiagnosticsRecursively);for(const processMemoryDump of Object.values(this.processMemoryDumps)){processMemoryDump.iterateRootAllocatorDumps(function(dump){dump.aggregateNumericsRecursively(this.model);},this);}},propagateNumericsAndDiagnosticsRecursively(globalAllocatorDump){['numerics','diagnostics'].forEach(function(field){for(const[name,value]of
+Object.entries(globalAllocatorDump[field])){globalAllocatorDump.ownedBy.forEach(function(ownershipLink){const processAllocatorDump=ownershipLink.source;if(processAllocatorDump[field][name]!==undefined){return;}
+processAllocatorDump[field][name]=value;});}});globalAllocatorDump.children.forEach(this.propagateNumericsAndDiagnosticsRecursively,this);},setUpTracingOverheadOwnership(){for(const dump of Object.values(this.processMemoryDumps)){dump.setUpTracingOverheadOwnership(this.model);}},discountTracingOverheadFromVmRegions(){for(const dump of Object.values(this.processMemoryDumps)){dump.discountTracingOverheadFromVmRegions(this.model);}},forceRebuildingMemoryAllocatorDumpByFullNameIndices(){this.iterateContainerDumps(function(containerDump){containerDump.forceRebuildingMemoryAllocatorDumpByFullNameIndex();});},iterateContainerDumps(fn){fn.call(this,this);for(const processDump of Object.values(this.processMemoryDumps)){fn.call(this,processDump);}},iterateAllRootAllocatorDumps(fn){this.iterateContainerDumps(function(containerDump){containerDump.iterateRootAllocatorDumps(fn,this);});},traverseAllocatorDumpsInDepthFirstPostOrder(fn){const visitedDumps=new WeakSet();const openDumps=new WeakSet();function visit(dump){if(visitedDumps.has(dump))return;if(openDumps.has(dump)){throw new Error(dump.userFriendlyName+' contains a cycle');}
+openDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this,ownershipLink.source);},this);dump.children.forEach(visit,this);fn.call(this,dump);visitedDumps.add(dump);openDumps.delete(dump);}
+this.iterateAllRootAllocatorDumps(visit);},traverseAllocatorDumpsInDepthFirstPreOrder(fn){const visitedDumps=new WeakSet();function visit(dump){if(visitedDumps.has(dump))return;if(dump.owns!==undefined&&!visitedDumps.has(dump.owns.target)){return;}
+if(dump.parent!==undefined&&!visitedDumps.has(dump.parent)){return;}
+fn.call(this,dump);visitedDumps.add(dump);dump.ownedBy.forEach(function(ownershipLink){visit.call(this,ownershipLink.source);},this);dump.children.forEach(visit,this);}
+this.iterateAllRootAllocatorDumps(visit);}};tr.model.EventRegistry.register(GlobalMemoryDump,{name:'globalMemoryDump',pluralName:'globalMemoryDumps'});return{GlobalMemoryDump,};});'use strict';tr.exportTo('tr.model',function(){const InstantEventType={GLOBAL:1,PROCESS:2};function InstantEvent(category,title,colorId,start,args,parent){tr.model.TimedEvent.call(this,start);this.category=category||'';this.title=title;this.colorId=colorId;this.args=args;this.parent_=parent;this.type=undefined;}
+InstantEvent.prototype={__proto__:tr.model.TimedEvent.prototype,};function GlobalInstantEvent(category,title,colorId,start,args,parent){InstantEvent.apply(this,arguments);this.type=InstantEventType.GLOBAL;}
+GlobalInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Global instant event '+this.title+' @ '+
+tr.b.Unit.byName.timeStampInMs.format(start);},get stableId(){return'instant.'+this.parent_.instantEvents.indexOf(this);},};function ProcessInstantEvent(category,title,colorId,start,args,parent){InstantEvent.apply(this,arguments);this.type=InstantEventType.PROCESS;}
+ProcessInstantEvent.prototype={__proto__:InstantEvent.prototype,get userFriendlyName(){return'Process-level instant event '+this.title+' @ '+
+tr.b.Unit.byName.timeStampInMs.format(start);},get stableId(){return this.parent_.stableId+'.instant.'+
+this.parent_.instantEvents.indexOf(this);},};tr.model.EventRegistry.register(InstantEvent,{name:'instantEvent',pluralName:'instantEvents'});return{GlobalInstantEvent,ProcessInstantEvent,InstantEventType,InstantEvent,};});'use strict';tr.exportTo('tr.model',function(){const Cpu=tr.model.Cpu;const ProcessBase=tr.model.ProcessBase;function Kernel(model){ProcessBase.call(this,model);this.cpus={};this.softwareMeasuredCpuCount_=undefined;}
+Kernel.compare=function(x,y){return 0;};Kernel.prototype={__proto__:ProcessBase.prototype,compareTo(that){return Kernel.compare(this,that);},get userFriendlyName(){return'Kernel';},get userFriendlyDetails(){return'Kernel';},get stableId(){return'Kernel';},getOrCreateCpu(cpuNumber){if(!this.cpus[cpuNumber]){this.cpus[cpuNumber]=new Cpu(this,cpuNumber);}
+return this.cpus[cpuNumber];},get softwareMeasuredCpuCount(){return this.softwareMeasuredCpuCount_;},set softwareMeasuredCpuCount(softwareMeasuredCpuCount){if(this.softwareMeasuredCpuCount_!==undefined&&this.softwareMeasuredCpuCount_!==softwareMeasuredCpuCount){throw new Error('Cannot change the softwareMeasuredCpuCount once it is set');}
+this.softwareMeasuredCpuCount_=softwareMeasuredCpuCount;},get bestGuessAtCpuCount(){const realCpuCount=Object.keys(this.cpus).length;if(realCpuCount!==0){return realCpuCount;}
+return this.softwareMeasuredCpuCount;},updateBounds(){ProcessBase.prototype.updateBounds.call(this);for(const cpuNumber in this.cpus){const cpu=this.cpus[cpuNumber];cpu.updateBounds();this.bounds.addRange(cpu.bounds);}},createSubSlices(){ProcessBase.prototype.createSubSlices.call(this);for(const cpuNumber in this.cpus){const cpu=this.cpus[cpuNumber];cpu.createSubSlices();}},addCategoriesToDict(categoriesDict){ProcessBase.prototype.addCategoriesToDict.call(this,categoriesDict);for(const cpuNumber in this.cpus){this.cpus[cpuNumber].addCategoriesToDict(categoriesDict);}},getSettingsKey(){return'kernel';},*childEventContainers(){yield*ProcessBase.prototype.childEventContainers.call(this);yield*Object.values(this.cpus);},};return{Kernel,};});'use strict';tr.exportTo('tr.model',function(){function ModelIndices(model){this.flowEventsById_={};model.flowEvents.forEach(function(fe){if(fe.id!==undefined){if(!this.flowEventsById_.hasOwnProperty(fe.id)){this.flowEventsById_[fe.id]=[];}
+this.flowEventsById_[fe.id].push(fe);}},this);}
+ModelIndices.prototype={addEventWithId(id,event){if(!this.flowEventsById_.hasOwnProperty(id)){this.flowEventsById_[id]=[];}
+this.flowEventsById_[id].push(event);},getFlowEventsWithId(id){if(!this.flowEventsById_.hasOwnProperty(id)){return[];}
+return this.flowEventsById_[id];}};return{ModelIndices,};});'use strict';tr.exportTo('tr.model',function(){function ModelStats(){this.traceEventCountsByKey_=new Map();this.allTraceEventStats_=[];this.traceEventStatsInTimeIntervals_=new Map();this.allTraceEventStatsInTimeIntervals_=[];this.hasEventSizesinBytes_=false;this.traceImportDurationMs_=undefined;}
+ModelStats.prototype={TIME_INTERVAL_SIZE_IN_MS:100,willProcessBasicTraceEvent(phase,category,title,ts,opt_eventSizeinBytes){const key=phase+'/'+category+'/'+title;let eventStats=this.traceEventCountsByKey_.get(key);if(eventStats===undefined){eventStats={phase,category,title,numEvents:0,totalEventSizeinBytes:0};this.traceEventCountsByKey_.set(key,eventStats);this.allTraceEventStats_.push(eventStats);}
+eventStats.numEvents++;const timeIntervalKey=Math.floor(tr.b.Unit.timestampFromUs(ts)/this.TIME_INTERVAL_SIZE_IN_MS);let eventStatsByTimeInverval=this.traceEventStatsInTimeIntervals_.get(timeIntervalKey);if(eventStatsByTimeInverval===undefined){eventStatsByTimeInverval={timeInterval:timeIntervalKey,numEvents:0,totalEventSizeinBytes:0};this.traceEventStatsInTimeIntervals_.set(timeIntervalKey,eventStatsByTimeInverval);this.allTraceEventStatsInTimeIntervals_.push(eventStatsByTimeInverval);}
+eventStatsByTimeInverval.numEvents++;if(opt_eventSizeinBytes!==undefined){this.hasEventSizesinBytes_=true;eventStats.totalEventSizeinBytes+=opt_eventSizeinBytes;eventStatsByTimeInverval.totalEventSizeinBytes+=opt_eventSizeinBytes;}},get allTraceEventStats(){return this.allTraceEventStats_;},get allTraceEventStatsInTimeIntervals(){return this.allTraceEventStatsInTimeIntervals_;},get hasEventSizesinBytes(){return this.hasEventSizesinBytes_;},get traceImportDurationMs(){return this.traceImportDurationMs_;},set traceImportDurationMs(traceImportDurationMs){this.traceImportDurationMs_=traceImportDurationMs;}};return{ModelStats,};});'use strict';tr.exportTo('tr.model',function(){function VMRegion(startAddress,sizeInBytes,protectionFlags,mappedFile,byteStats){this.startAddress=startAddress;this.sizeInBytes=sizeInBytes;this.protectionFlags=protectionFlags;this.mappedFile=mappedFile||'';this.byteStats=byteStats||{};}
+VMRegion.PROTECTION_FLAG_READ=4;VMRegion.PROTECTION_FLAG_WRITE=2;VMRegion.PROTECTION_FLAG_EXECUTE=1;VMRegion.PROTECTION_FLAG_MAYSHARE=128;VMRegion.prototype={get uniqueIdWithinProcess(){return this.mappedFile+'#'+this.startAddress;},get protectionFlagsToString(){if(this.protectionFlags===undefined)return undefined;return((this.protectionFlags&VMRegion.PROTECTION_FLAG_READ?'r':'-')+
+(this.protectionFlags&VMRegion.PROTECTION_FLAG_WRITE?'w':'-')+
+(this.protectionFlags&VMRegion.PROTECTION_FLAG_EXECUTE?'x':'-')+
+(this.protectionFlags&VMRegion.PROTECTION_FLAG_MAYSHARE?'s':'p'));}};VMRegion.fromDict=function(dict){return new VMRegion(dict.startAddress,dict.sizeInBytes,dict.protectionFlags,dict.mappedFile,dict.byteStats);};function VMRegionClassificationNode(opt_rule){this.rule_=opt_rule||VMRegionClassificationNode.CLASSIFICATION_RULES;this.hasRegions=false;this.sizeInBytes=undefined;this.byteStats={};this.children_=undefined;this.regions_=[];}
+VMRegionClassificationNode.CLASSIFICATION_RULES={name:'Total',children:[{name:'Android',file:/^\/dev\/ashmem(?!\/libc malloc)/,children:[{name:'Java runtime',file:/^\/dev\/ashmem\/dalvik-/,children:[{name:'Spaces',file:/\/dalvik-(alloc|main|large object|non moving|zygote) space/,children:[{name:'Normal',file:/\/dalvik-(alloc|main)/},{name:'Large',file:/\/dalvik-large object/},{name:'Zygote',file:/\/dalvik-zygote/},{name:'Non-moving',file:/\/dalvik-non moving/}]},{name:'Linear Alloc',file:/\/dalvik-LinearAlloc/},{name:'Indirect Reference Table',file:/\/dalvik-indirect.ref/},{name:'Cache',file:/\/dalvik-jit-code-cache/},{name:'Accounting'}]},{name:'Cursor',file:/\/CursorWindow/},{name:'Ashmem'}]},{name:'Native heap',file:/^((\[heap\])|(\[anon:)|(\/dev\/ashmem\/libc malloc)|(\[discounted tracing overhead\])|$)/},{name:'Stack',file:/^\[stack/},{name:'Files',file:/\.((((jar)|(apk)|(ttf)|(odex)|(oat)|(art))$)|(dex)|(so))/,children:[{name:'so',file:/\.so/},{name:'jar',file:/\.jar$/},{name:'apk',file:/\.apk$/},{name:'ttf',file:/\.ttf$/},{name:'dex',file:/\.((dex)|(odex$))/},{name:'oat',file:/\.oat$/},{name:'art',file:/\.art$/}]},{name:'Devices',file:/(^\/dev\/)|(anon_inode:dmabuf)/,children:[{name:'GPU',file:/\/((nv)|(mali)|(kgsl))/},{name:'DMA',file:/anon_inode:dmabuf/}]}]};VMRegionClassificationNode.OTHER_RULE={name:'Other'};VMRegionClassificationNode.fromRegions=function(regions,opt_rules){const tree=new VMRegionClassificationNode(opt_rules);tree.regions_=regions;for(let i=0;i<regions.length;i++){tree.addStatsFromRegion_(regions[i]);}
+return tree;};VMRegionClassificationNode.prototype={get title(){return this.rule_.name;},get children(){if(this.isLeafNode){return undefined;}
+if(this.children_===undefined){this.buildTree_();}
+return this.children_;},get regions(){if(!this.isLeafNode){return undefined;}
+return this.regions_;},get allRegionsForTesting(){if(this.regions_!==undefined){if(this.children_!==undefined){throw new Error('Internal error: a VM region classification node '+'cannot have both regions and children');}
+return this.regions_;}
+let regions=[];this.children_.forEach(function(childNode){regions=regions.concat(childNode.allRegionsForTesting);});return regions;},get isLeafNode(){const children=this.rule_.children;return children===undefined||children.length===0;},addRegion(region){this.addRegionRecursively_(region,true);},someRegion(fn,opt_this){if(this.regions_!==undefined){return this.regions_.some(fn,opt_this);}
+return this.children_.some(function(childNode){return childNode.someRegion(fn,opt_this);});},addRegionRecursively_(region,addStatsToThisNode){if(addStatsToThisNode){this.addStatsFromRegion_(region);}
+if(this.regions_!==undefined){if(this.children_!==undefined){throw new Error('Internal error: a VM region classification node '+'cannot have both regions and children');}
+this.regions_.push(region);return;}
+function regionRowMatchesChildNide(child){const fileRegExp=child.rule_.file;if(fileRegExp===undefined)return true;return fileRegExp.test(region.mappedFile);}
+let matchedChild=this.children_.find(regionRowMatchesChildNide);if(matchedChild===undefined){if(this.children_.length!==this.rule_.children.length){throw new Error('Internal error');}
+matchedChild=new VMRegionClassificationNode(VMRegionClassificationNode.OTHER_RULE);this.children_.push(matchedChild);}
+matchedChild.addRegionRecursively_(region,true);},buildTree_(){const cachedRegions=this.regions_;this.regions_=undefined;this.buildChildNodesRecursively_();for(let i=0;i<cachedRegions.length;i++){this.addRegionRecursively_(cachedRegions[i],false);}},buildChildNodesRecursively_(){if(this.children_!==undefined){throw new Error('Internal error: Classification node already has children');}
+if(this.regions_!==undefined&&this.regions_.length!==0){throw new Error('Internal error: Classification node should have no regions');}
+if(this.isLeafNode){return;}
+this.regions_=undefined;this.children_=this.rule_.children.map(function(childRule){const child=new VMRegionClassificationNode(childRule);child.buildChildNodesRecursively_();return child;});},addStatsFromRegion_(region){this.hasRegions=true;const regionSizeInBytes=region.sizeInBytes;if(regionSizeInBytes!==undefined){this.sizeInBytes=(this.sizeInBytes||0)+regionSizeInBytes;}
+const thisByteStats=this.byteStats;const regionByteStats=region.byteStats;for(const byteStatName in regionByteStats){const regionByteStatValue=regionByteStats[byteStatName];if(regionByteStatValue===undefined)continue;thisByteStats[byteStatName]=(thisByteStats[byteStatName]||0)+regionByteStatValue;}
+if(region.mappedFile.includes('/base.odex')||region.mappedFile.includes('/base.vdex')){if(region.byteStats.proportionalResident!==undefined){thisByteStats.javaBasePss=(thisByteStats.javaBasePss||0)+
+region.byteStats.proportionalResident;}
+if(region.byteStats.privateCleanResident!==undefined){thisByteStats.javaBaseCleanResident=(thisByteStats.javaBaseCleanResident||0)+
+region.byteStats.privateCleanResident;}
+if(region.byteStats.sharedCleanResident!==undefined){thisByteStats.javaBaseCleanResident=(thisByteStats.javaBaseCleanResident||0)+
+region.byteStats.sharedCleanResident;}}
+const textProtectionFlags=(VMRegion.PROTECTION_FLAG_READ|VMRegion.PROTECTION_FLAG_EXECUTE);if((region.protectionFlags===textProtectionFlags)&&(region.mappedFile.includes('/base.apk')||region.mappedFile.includes('/libchrome.so'))){if(regionSizeInBytes!==undefined){this.nativeLibrarySizeInBytes=(this.nativeLibrarySizeInBytes||0)+regionSizeInBytes;}
+if(region.byteStats.privateCleanResident!==undefined){thisByteStats.nativeLibraryPrivateCleanResident=(thisByteStats.nativeLibraryPrivateCleanResident||0)+
+region.byteStats.privateCleanResident;}
+if(region.byteStats.sharedCleanResident!==undefined){thisByteStats.nativeLibrarySharedCleanResident=(thisByteStats.nativeLibrarySharedCleanResident||0)+
+region.byteStats.sharedCleanResident;}
+if(region.byteStats.proportionalResident!==undefined){thisByteStats.nativeLibraryProportionalResident=(thisByteStats.nativeLibraryProportionalResident||0)+
+region.byteStats.proportionalResident;}}}};return{VMRegion,VMRegionClassificationNode,};});'use strict';tr.exportTo('tr.model',function(){const DISCOUNTED_ALLOCATOR_NAMES=['winheap','malloc'];const TRACING_OVERHEAD_PATH=['allocated_objects','tracing_overhead'];const SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME;const RESIDENT_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.RESIDENT_SIZE_NUMERIC_NAME;function getSizeNumericValue(dump,sizeNumericName){const sizeNumeric=dump.numerics[sizeNumericName];if(sizeNumeric===undefined)return 0;return sizeNumeric.value;}
+function ProcessMemoryDump(globalMemoryDump,process,start){tr.model.ContainerMemoryDump.call(this,start);this.process=process;this.globalMemoryDump=globalMemoryDump;this.totals=undefined;this.vmRegions=undefined;this.heapDumps=undefined;this.tracingOverheadOwnershipSetUp_=false;this.tracingOverheadDiscountedFromVmRegions_=false;}
+ProcessMemoryDump.prototype={__proto__:tr.model.ContainerMemoryDump.prototype,get stableId(){return this.process.stableId+'.memory.'+
+this.process.memoryDumps.indexOf(this);},get userFriendlyName(){return'Process memory dump at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get containerName(){return this.process.userFriendlyName;},get processMemoryDumps(){const dumps={};dumps[this.process.pid]=this;return dumps;},get hasOwnVmRegions(){return this.vmRegions!==undefined;},setUpTracingOverheadOwnership(opt_model){if(this.tracingOverheadOwnershipSetUp_)return;this.tracingOverheadOwnershipSetUp_=true;const tracingDump=this.getMemoryAllocatorDumpByFullName('tracing');if(tracingDump===undefined||tracingDump.owns!==undefined){return;}
+if(tracingDump.owns!==undefined)return;const hasDiscountedFromAllocatorDumps=DISCOUNTED_ALLOCATOR_NAMES.some(function(allocatorName){const allocatorDump=this.getMemoryAllocatorDumpByFullName(allocatorName);if(allocatorDump===undefined){return false;}
+let nextPathIndex=0;let currentDump=allocatorDump;let currentFullName=allocatorName;for(;nextPathIndex<TRACING_OVERHEAD_PATH.length;nextPathIndex++){const childFullName=currentFullName+'/'+
+TRACING_OVERHEAD_PATH[nextPathIndex];const childDump=this.getMemoryAllocatorDumpByFullName(childFullName);if(childDump===undefined)break;currentDump=childDump;currentFullName=childFullName;}
+for(;nextPathIndex<TRACING_OVERHEAD_PATH.length;nextPathIndex++){const childFullName=currentFullName+'/'+
+TRACING_OVERHEAD_PATH[nextPathIndex];const childDump=new tr.model.MemoryAllocatorDump(currentDump.containerMemoryDump,childFullName);childDump.parent=currentDump;currentDump.children.push(childDump);currentFullName=childFullName;currentDump=childDump;}
+const ownershipLink=new tr.model.MemoryAllocatorDumpLink(tracingDump,currentDump);tracingDump.owns=ownershipLink;currentDump.ownedBy.push(ownershipLink);return true;},this);if(hasDiscountedFromAllocatorDumps){this.forceRebuildingMemoryAllocatorDumpByFullNameIndex();}},discountTracingOverheadFromVmRegions(opt_model){if(this.tracingOverheadDiscountedFromVmRegions_)return;this.tracingOverheadDiscountedFromVmRegions_=true;const tracingDump=this.getMemoryAllocatorDumpByFullName('tracing');if(tracingDump===undefined)return;const discountedSize=getSizeNumericValue(tracingDump,SIZE_NUMERIC_NAME);const discountedResidentSize=getSizeNumericValue(tracingDump,RESIDENT_SIZE_NUMERIC_NAME);if(discountedSize<=0&&discountedResidentSize<=0)return;if(this.totals!==undefined){if(this.totals.residentBytes!==undefined){this.totals.residentBytes-=discountedResidentSize;}
+if(this.totals.peakResidentBytes!==undefined){this.totals.peakResidentBytes-=discountedResidentSize;}}
+if(this.vmRegions!==undefined){const hasSizeInBytes=this.vmRegions.sizeInBytes!==undefined;const hasPrivateDirtyResident=this.vmRegions.byteStats.privateDirtyResident!==undefined;const hasProportionalResident=this.vmRegions.byteStats.proportionalResident!==undefined;if((hasSizeInBytes&&discountedSize>0)||((hasPrivateDirtyResident||hasProportionalResident)&&discountedResidentSize>0)){const byteStats={};if(hasPrivateDirtyResident){byteStats.privateDirtyResident=-discountedResidentSize;}
+if(hasProportionalResident){byteStats.proportionalResident=-discountedResidentSize;}
+this.vmRegions.addRegion(tr.model.VMRegion.fromDict({mappedFile:'[discounted tracing overhead]',sizeInBytes:hasSizeInBytes?-discountedSize:undefined,byteStats}));}}}};ProcessMemoryDump.hookUpMostRecentVmRegionsLinks=function(processDumps){let mostRecentVmRegions=undefined;processDumps.forEach(function(processDump){if(processDump.vmRegions!==undefined){mostRecentVmRegions=processDump.vmRegions;}
+processDump.mostRecentVmRegions=mostRecentVmRegions;});};tr.model.EventRegistry.register(ProcessMemoryDump,{name:'processMemoryDump',pluralName:'processMemoryDumps'});return{ProcessMemoryDump,};});'use strict';tr.exportTo('tr.model',function(){const ProcessBase=tr.model.ProcessBase;const ProcessInstantEvent=tr.model.ProcessInstantEvent;const Frame=tr.model.Frame;const ProcessMemoryDump=tr.model.ProcessMemoryDump;function Process(model,pid){if(model===undefined){throw new Error('model must be provided');}
+if(pid===undefined){throw new Error('pid must be provided');}
+tr.model.ProcessBase.call(this,model);this.pid=pid;this.name=undefined;this.labels=[];this.uptime_seconds=0;this.instantEvents=[];this.memoryDumps=[];this.frames=[];this.activities=[];}
+Process.compare=function(x,y){let tmp=tr.model.ProcessBase.compare(x,y);if(tmp)return tmp;if(x.name!==undefined){if(y.name!==undefined){tmp=x.name.localeCompare(y.name);}else{tmp=-1;}}else if(y.name!==undefined){tmp=1;}
+if(tmp)return tmp;tmp=tr.b.compareArrays(x.labels,y.labels,function(x,y){return x.localeCompare(y);});if(tmp)return tmp;return x.pid-y.pid;};Process.prototype={__proto__:tr.model.ProcessBase.prototype,get stableId(){return this.pid;},compareTo(that){return Process.compare(this,that);},*childEvents(){yield*ProcessBase.prototype.childEvents.call(this);yield*this.instantEvents;yield*this.frames;yield*this.memoryDumps;},addLabelIfNeeded(labelName){for(let i=0;i<this.labels.length;i++){if(this.labels[i]===labelName)return;}
+this.labels.push(labelName);},get userFriendlyName(){let res;if(this.name){res=this.name+' (pid '+this.pid+')';}else{res='Process '+this.pid;}
+if(this.labels.length){res+=': '+this.labels.join(', ');}
+if(this.uptime_seconds){res+=', uptime:'+this.uptime_seconds+'s';}
+return res;},get userFriendlyDetails(){if(this.name){return this.name+' (pid '+this.pid+')';}
+return'pid: '+this.pid;},getSettingsKey(){if(!this.name)return undefined;if(!this.labels.length)return'processes.'+this.name;return'processes.'+this.name+'.'+this.labels.join('.');},shiftTimestampsForward(amount){for(let i=0;i<this.instantEvents.length;i++){this.instantEvents[i].start+=amount;}
+for(let i=0;i<this.frames.length;i++){this.frames[i].shiftTimestampsForward(amount);}
+for(let i=0;i<this.memoryDumps.length;i++){this.memoryDumps[i].shiftTimestampsForward(amount);}
+for(let i=0;i<this.activities.length;i++){this.activities[i].shiftTimestampsForward(amount);}
+tr.model.ProcessBase.prototype.shiftTimestampsForward.apply(this,arguments);},updateBounds(){tr.model.ProcessBase.prototype.updateBounds.apply(this);for(let i=0;i<this.frames.length;i++){this.frames[i].addBoundsToRange(this.bounds);}
+for(let i=0;i<this.memoryDumps.length;i++){this.memoryDumps[i].addBoundsToRange(this.bounds);}
+for(let i=0;i<this.activities.length;i++){this.activities[i].addBoundsToRange(this.bounds);}},sortMemoryDumps(){this.memoryDumps.sort(function(x,y){return x.start-y.start;});tr.model.ProcessMemoryDump.hookUpMostRecentVmRegionsLinks(this.memoryDumps);}};return{Process,};});'use strict';tr.exportTo('tr.model',function(){function Sample(start,title,leafNode,thread,opt_cpu,opt_weight,opt_args){tr.model.TimedEvent.call(this,start);this.start_=start;this.title_=title;this.leafNode_=leafNode;this.thread_=thread;this.colorId_=leafNode.colorId;this.cpu_=opt_cpu;this.weight_=opt_weight;this.args=opt_args||{};}
+Sample.prototype={__proto__:tr.model.TimedEvent.prototype,get title(){return this.title_;},get colorId(){return this.colorId_;},get thread(){return this.thread_;},get leafNode(){return this.leafNode_;},get userFriendlyName(){return'Sample at '+
+tr.b.Unit.byName.timeStampInMs.format(this.start);},get userFriendlyStack(){return this.leafNode_.userFriendlyStack;},getNodesAsArray(){const nodes=[];let node=this.leafNode_;while(node!==undefined){nodes.push(node);node=node.parentNode;}
+return nodes;},get cpu(){return this.cpu_;},get weight(){return this.weight_;},};tr.model.EventRegistry.register(Sample,{name:'Sample',pluralName:'Samples'});return{Sample,};});'use strict';tr.exportTo('tr.model',function(){function StackFrame(parentFrame,id,title,colorId,opt_sourceInfo){if(id===undefined){throw new Error('id must be given');}
+this.parentFrame_=parentFrame;this.id=id;this.title_=title;this.colorId=colorId;this.children=[];this.sourceInfo_=opt_sourceInfo;if(this.parentFrame_){this.parentFrame_.addChild(this);}}
+StackFrame.prototype={get parentFrame(){return this.parentFrame_;},get title(){if(this.sourceInfo_){const src=this.sourceInfo_.toString();return this.title_+(src===''?'':' '+src);}
+return this.title_;},get domain(){let result='unknown';if(this.sourceInfo_&&this.sourceInfo_.domain){result=this.sourceInfo_.domain;}
+if(result==='unknown'&&this.parentFrame){result=this.parentFrame.domain;}
+return result;},get sourceInfo(){return this.sourceInfo_;},set parentFrame(parentFrame){if(this.parentFrame_){Polymer.dom(this.parentFrame_).removeChild(this);}
+this.parentFrame_=parentFrame;if(this.parentFrame_){this.parentFrame_.addChild(this);}},addChild(child){this.children.push(child);},removeChild(child){const i=this.children.indexOf(child.id);if(i===-1){throw new Error('omg');}
+this.children.splice(i,1);},removeAllChildren(){for(let i=0;i<this.children.length;i++){this.children[i].parentFrame_=undefined;}
+this.children.splice(0,this.children.length);},get stackTrace(){const stack=[this];let cur=this.parentFrame;while(cur){stack.push(cur);cur=cur.parentFrame;}
+return stack;},getUserFriendlyStackTrace(){return this.stackTrace.map(function(x){return x.title;});}};return{StackFrame,};});'use strict';tr.exportTo('tr.model.um',function(){class UserModel extends tr.model.EventContainer{constructor(parentModel){super();this.parentModel_=parentModel;this.expectations_=new tr.model.EventSet();this.segments_=[];}
+get stableId(){return'UserModel';}
+get parentModel(){return this.parentModel_;}
+sortExpectations(){this.expectations_.sortEvents((x,y)=>(x.start-y.start));}
+get expectations(){return this.expectations_;}
+shiftTimestampsForward(amount){}
+addCategoriesToDict(categoriesDict){}
+get segments(){return this.segments_;}*childEvents(){yield*this.expectations;}*childEventContainers(){}
+updateBounds(){this.bounds.reset();for(const expectation of this.expectations){expectation.addBoundsToRange(this.bounds);}}
+resegment(getKeyForSegment){const newSegments=[];let prevKey=undefined;let prevSegment=undefined;for(let i=0;i<this.segments.length;++i){const segment=this.segments[i];const key=getKeyForSegment(segment,i);if(prevSegment!==undefined&&key===prevKey){prevSegment.addSegment(segment);}else{prevSegment=segment.clone();newSegments.push(prevSegment);}
+prevKey=key;}
+return newSegments;}}
+return{UserModel,};});'use strict';tr.exportTo('tr',function(){const Process=tr.model.Process;const Device=tr.model.Device;const Kernel=tr.model.Kernel;const GlobalMemoryDump=tr.model.GlobalMemoryDump;const GlobalInstantEvent=tr.model.GlobalInstantEvent;const FlowEvent=tr.model.FlowEvent;const Alert=tr.model.Alert;const Sample=tr.model.Sample;function Model(){tr.model.EventContainer.call(this);tr.b.EventTarget.decorate(this);this.timestampShiftToZeroAmount_=0;this.faviconHue='blue';this.device=new Device(this);this.kernel=new Kernel(this);this.processes={};this.metadata=[];this.categories=[];this.instantEvents=[];this.flowEvents=[];this.clockSyncManager=new tr.model.ClockSyncManager();this.intrinsicTimeUnit_=undefined;this.stackFrames={};this.samples=[];this.alerts=[];this.userModel=new tr.model.um.UserModel(this);this.flowIntervalTree=new tr.b.IntervalTree((f)=>f.start,(f)=>f.end);this.globalMemoryDumps=[];this.userFriendlyCategoryDrivers_=[];this.annotationsByGuid_={};this.modelIndices=undefined;this.stats=new tr.model.ModelStats();this.importWarnings_=[];this.reportedImportWarnings_={};this.isTimeHighResolution_=true;this.patchupsToApply_=[];this.doesHelperGUIDSupportThisModel_={};this.helpersByConstructorGUID_={};this.eventsByStableId_=undefined;}
+Model.prototype={__proto__:tr.model.EventContainer.prototype,getEventByStableId(stableId){if(this.eventsByStableId_===undefined){this.eventsByStableId_={};for(const event of this.getDescendantEvents()){this.eventsByStableId_[event.stableId]=event;}}
+return this.eventsByStableId_[stableId];},getOrCreateHelper(constructor){if(!constructor.guid){throw new Error('Helper constructors must have GUIDs');}
+if(this.helpersByConstructorGUID_[constructor.guid]===undefined){if(this.doesHelperGUIDSupportThisModel_[constructor.guid]===undefined){this.doesHelperGUIDSupportThisModel_[constructor.guid]=constructor.supportsModel(this);}
+if(!this.doesHelperGUIDSupportThisModel_[constructor.guid]){return undefined;}
+this.helpersByConstructorGUID_[constructor.guid]=new constructor(this);}
+return this.helpersByConstructorGUID_[constructor.guid];},*childEvents(){yield*this.globalMemoryDumps;yield*this.instantEvents;yield*this.flowEvents;yield*this.alerts;yield*this.samples;},*childEventContainers(){yield this.userModel;yield this.device;yield this.kernel;yield*Object.values(this.processes);},iterateAllPersistableObjects(callback){this.kernel.iterateAllPersistableObjects(callback);for(const pid in this.processes){this.processes[pid].iterateAllPersistableObjects(callback);}},updateBounds(){this.bounds.reset();const bounds=this.bounds;for(const ec of this.childEventContainers()){ec.updateBounds();bounds.addRange(ec.bounds);}
+for(const event of this.childEvents()){event.addBoundsToRange(bounds);}},shiftWorldToZero(){const shiftAmount=-this.bounds.min;this.timestampShiftToZeroAmount_=shiftAmount;for(const ec of this.childEventContainers()){ec.shiftTimestampsForward(shiftAmount);}
+for(const event of this.childEvents()){event.start+=shiftAmount;}
+this.updateBounds();},convertTimestampToModelTime(sourceClockDomainName,ts){if(sourceClockDomainName!=='traceEventClock'){throw new Error('Only traceEventClock is supported.');}
+return tr.b.Unit.timestampFromUs(ts)+
+this.timestampShiftToZeroAmount_;},get numProcesses(){let n=0;for(const p in this.processes){n++;}
+return n;},getProcess(pid){return this.processes[pid];},getOrCreateProcess(pid){if(!this.processes[pid]){this.processes[pid]=new Process(this,pid);}
+return this.processes[pid];},addStackFrame(stackFrame){if(this.stackFrames[stackFrame.id]){throw new Error('Stack frame already exists');}
+this.stackFrames[stackFrame.id]=stackFrame;return stackFrame;},updateCategories_(){const categoriesDict={};this.userModel.addCategoriesToDict(categoriesDict);this.device.addCategoriesToDict(categoriesDict);this.kernel.addCategoriesToDict(categoriesDict);for(const pid in this.processes){this.processes[pid].addCategoriesToDict(categoriesDict);}
+this.categories=[];for(const category in categoriesDict){if(category!==''){this.categories.push(category);}}},getAllThreads(){const threads=[];for(const tid in this.kernel.threads){threads.push(process.threads[tid]);}
+for(const pid in this.processes){const process=this.processes[pid];for(const tid in process.threads){threads.push(process.threads[tid]);}}
+return threads;},getAllProcesses(opt_predicate){const processes=[];for(const pid in this.processes){const process=this.processes[pid];if(opt_predicate===undefined||opt_predicate(process)){processes.push(process);}}
+return processes;},getAllCounters(){const counters=[];counters.push.apply(counters,Object.values(this.device.counters||{}));counters.push.apply(counters,Object.values(this.kernel.counters||{}));for(const pid in this.processes){const process=this.processes[pid];for(const tid in process.counters){counters.push(process.counters[tid]);}}
+return counters;},getAnnotationByGUID(guid){return this.annotationsByGuid_[guid];},addAnnotation(annotation){if(!annotation.guid){throw new Error('Annotation with undefined guid given');}
+this.annotationsByGuid_[annotation.guid]=annotation;tr.b.dispatchSimpleEvent(this,'annotationChange');},removeAnnotation(annotation){this.annotationsByGuid_[annotation.guid].onRemove();delete this.annotationsByGuid_[annotation.guid];tr.b.dispatchSimpleEvent(this,'annotationChange');},getAllAnnotations(){return Object.values(this.annotationsByGuid_);},addUserFriendlyCategoryDriver(ufcd){this.userFriendlyCategoryDrivers_.push(ufcd);},getUserFriendlyCategoryFromEvent(event){for(let i=0;i<this.userFriendlyCategoryDrivers_.length;i++){const ufc=this.userFriendlyCategoryDrivers_[i].fromEvent(event);if(ufc!==undefined)return ufc;}
+return undefined;},findAllThreadsNamed(name){const namedThreads=[];namedThreads.push.apply(namedThreads,this.kernel.findAllThreadsNamed(name));for(const pid in this.processes){namedThreads.push.apply(namedThreads,this.processes[pid].findAllThreadsNamed(name));}
+return namedThreads;},get importOptions(){return this.importOptions_;},set importOptions(options){this.importOptions_=options;},get intrinsicTimeUnit(){if(this.intrinsicTimeUnit_===undefined){return tr.b.TimeDisplayModes.ms;}
+return this.intrinsicTimeUnit_;},set intrinsicTimeUnit(value){if(this.intrinsicTimeUnit_===value)return;if(this.intrinsicTimeUnit_!==undefined){throw new Error('Intrinsic time unit already set');}
+this.intrinsicTimeUnit_=value;},get isTimeHighResolution(){return this.isTimeHighResolution_;},set isTimeHighResolution(value){this.isTimeHighResolution_=value;},get canonicalUrl(){return this.canonicalUrl_;},set canonicalUrl(value){if(this.canonicalUrl_===value)return;if(this.canonicalUrl_!==undefined){throw new Error('canonicalUrl already set');}
+this.canonicalUrl_=value;},importWarning(data){data.showToUser=!!data.showToUser;this.importWarnings_.push(data);if(this.reportedImportWarnings_[data.type]===true)return;this.reportedImportWarnings_[data.type]=true;},get hasImportWarnings(){return(this.importWarnings_.length>0);},get importWarnings(){return this.importWarnings_;},get importWarningsThatShouldBeShownToUser(){return this.importWarnings_.filter(function(warning){return warning.showToUser;});},autoCloseOpenSlices(){this.samples.sort(function(x,y){return x.start-y.start;});this.updateBounds();this.kernel.autoCloseOpenSlices();for(const pid in this.processes){this.processes[pid].autoCloseOpenSlices();}},createSubSlices(){this.kernel.createSubSlices();for(const pid in this.processes){this.processes[pid].createSubSlices();}},preInitializeObjects(){for(const pid in this.processes){this.processes[pid].preInitializeObjects();}},initializeObjects(){for(const pid in this.processes){this.processes[pid].initializeObjects();}},pruneEmptyContainers(){this.kernel.pruneEmptyContainers();for(const pid in this.processes){this.processes[pid].pruneEmptyContainers();}},mergeKernelWithUserland(){for(const pid in this.processes){this.processes[pid].mergeKernelWithUserland();}},computeWorldBounds(shiftWorldToZero){this.updateBounds();this.updateCategories_();if(shiftWorldToZero){this.shiftWorldToZero();}},buildFlowEventIntervalTree(){for(let i=0;i<this.flowEvents.length;++i){const flowEvent=this.flowEvents[i];this.flowIntervalTree.insert(flowEvent);}
+this.flowIntervalTree.updateHighValues();},cleanupUndeletedObjects(){for(const pid in this.processes){this.processes[pid].autoDeleteObjects(this.bounds.max);}},sortMemoryDumps(){this.globalMemoryDumps.sort(function(x,y){return x.start-y.start;});for(const pid in this.processes){this.processes[pid].sortMemoryDumps();}},finalizeMemoryGraphs(){this.globalMemoryDumps.forEach(function(dump){dump.finalizeGraph();});},buildEventIndices(){this.modelIndices=new tr.model.ModelIndices(this);},sortAlerts(){this.alerts.sort(function(x,y){return x.start-y.start;});},applyObjectRefPatchups(){const unresolved=[];this.patchupsToApply_.forEach(function(patchup){if(patchup.pidRef in this.processes){const snapshot=this.processes[patchup.pidRef].objects.getSnapshotAt(patchup.scopedId,patchup.ts);if(snapshot){patchup.object[patchup.field]=snapshot;snapshot.referencedAt(patchup.item,patchup.object,patchup.field);return;}}
+unresolved.push(patchup);},this);this.patchupsToApply_=unresolved;},replacePIDRefsInPatchups(oldPidRef,newPidRef){this.patchupsToApply_.forEach(function(patchup){if(patchup.pidRef===oldPidRef){patchup.pidRef=newPidRef;}});},joinRefs(){this.joinObjectRefs_();this.applyObjectRefPatchups();},joinObjectRefs_(){for(const[pid,process]of Object.entries(this.processes)){this.joinObjectRefsForProcess_(pid,process);}},joinObjectRefsForProcess_(pid,process){for(const thread of Object.values(process.threads)){thread.asyncSliceGroup.slices.forEach(function(item){this.searchItemForIDRefs_(pid,'start',item);},this);thread.sliceGroup.slices.forEach(function(item){this.searchItemForIDRefs_(pid,'start',item);},this);}
+process.objects.iterObjectInstances(function(instance){instance.snapshots.forEach(function(item){this.searchItemForIDRefs_(pid,'ts',item);},this);},this);},searchItemForIDRefs_(pid,itemTimestampField,item){if(!item.args&&!item.contexts)return;const patchupsToApply=this.patchupsToApply_;function handleField(object,fieldName,fieldValue){if(!fieldValue||(!fieldValue.id_ref&&!fieldValue.idRef)){return;}
+const scope=fieldValue.scope||tr.model.OBJECT_DEFAULT_SCOPE;const idRef=fieldValue.id_ref||fieldValue.idRef;const scopedId=new tr.model.ScopedId(scope,idRef);const pidRef=fieldValue.pid_ref||fieldValue.pidRef||pid;const ts=item[itemTimestampField];patchupsToApply.push({item,object,field:fieldName,pidRef,scopedId,ts});}
+function iterObjectFieldsRecursively(object){if(!(object instanceof Object))return;if((object instanceof tr.model.ObjectSnapshot)||(object instanceof Float32Array)||(object instanceof tr.b.math.Quad)){return;}
+if(object instanceof Array){for(let i=0;i<object.length;i++){handleField(object,i,object[i]);iterObjectFieldsRecursively(object[i]);}
+return;}
+for(const key in object){const value=object[key];handleField(object,key,value);iterObjectFieldsRecursively(value);}}
+iterObjectFieldsRecursively(item.args);iterObjectFieldsRecursively(item.contexts);}};return{Model,};});'use strict';tr.exportTo('tr.e.importer.etw',function(){const kThreadGuid='3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C';const kThreadDCStartOpcode=3;function Decoder(){this.payload_=new DataView(new ArrayBuffer(256));}
+Decoder.prototype={__proto__:Object.prototype,reset(base64Payload){const decodedSize=tr.b.Base64.getDecodedBufferLength(base64Payload);if(decodedSize>this.payload_.byteLength){this.payload_=new DataView(new ArrayBuffer(decodedSize));}
+tr.b.Base64.DecodeToTypedArray(base64Payload,this.payload_);this.position_=0;},skip(length){this.position_+=length;},decodeUInt8(){const result=this.payload_.getUint8(this.position_,true);this.position_+=1;return result;},decodeUInt16(){const result=this.payload_.getUint16(this.position_,true);this.position_+=2;return result;},decodeUInt32(){const result=this.payload_.getUint32(this.position_,true);this.position_+=4;return result;},decodeUInt64ToString(){const low=this.decodeUInt32();const high=this.decodeUInt32();const lowStr=('0000000'+low.toString(16)).substr(-8);const highStr=('0000000'+high.toString(16)).substr(-8);const result=highStr+lowStr;return result;},decodeInt8(){const result=this.payload_.getInt8(this.position_,true);this.position_+=1;return result;},decodeInt16(){const result=this.payload_.getInt16(this.position_,true);this.position_+=2;return result;},decodeInt32(){const result=this.payload_.getInt32(this.position_,true);this.position_+=4;return result;},decodeInt64ToString(){return this.decodeUInt64ToString();},decodeUInteger(is64){if(is64){return this.decodeUInt64ToString();}
+return this.decodeUInt32();},decodeString(){let str='';while(true){const c=this.decodeUInt8();if(!c)return str;str=str+String.fromCharCode(c);}},decodeW16String(){let str='';while(true){const c=this.decodeUInt16();if(!c)return str;str=str+String.fromCharCode(c);}},decodeFixedW16String(length){const oldPosition=this.position_;let str='';for(let i=0;i<length;i++){const c=this.decodeUInt16();if(!c)break;str=str+String.fromCharCode(c);}
+this.position_=oldPosition+2*length;return str;},decodeBytes(length){const bytes=[];for(let i=0;i<length;++i){const c=this.decodeUInt8();bytes.push(c);}
+return bytes;},decodeSID(is64){const pSid=this.decodeUInteger(is64);const attributes=this.decodeUInt32();if(is64){this.decodeUInt32();}
+const revision=this.decodeUInt8();const subAuthorityCount=this.decodeUInt8();this.decodeUInt16();this.decodeUInt32();if(revision!==1){throw new Error('Invalid SID revision: could not decode the SID structure.');}
+const sid=this.decodeBytes(4*subAuthorityCount);return{pSid,attributes,sid};},decodeSystemTime(){const wYear=this.decodeInt16();const wMonth=this.decodeInt16();const wDayOfWeek=this.decodeInt16();const wDay=this.decodeInt16();const wHour=this.decodeInt16();const wMinute=this.decodeInt16();const wSecond=this.decodeInt16();const wMilliseconds=this.decodeInt16();return{wYear,wMonth,wDayOfWeek,wDay,wHour,wMinute,wSecond,wMilliseconds};},decodeTimeZoneInformation(){const bias=this.decodeUInt32();const standardName=this.decodeFixedW16String(32);const standardDate=this.decodeSystemTime();const standardBias=this.decodeUInt32();const daylightName=this.decodeFixedW16String(32);const daylightDate=this.decodeSystemTime();const daylightBias=this.decodeUInt32();return{bias,standardName,standardDate,standardBias,daylightName,daylightDate,daylightBias};}};function EtwImporter(model,events){this.importPriority=3;this.model_=model;this.events_=events;this.handlers_={};this.decoder_=new Decoder();this.walltime_=undefined;this.ticks_=undefined;this.is64bit_=undefined;this.tidsToPid_={};const allTypeInfos=tr.e.importer.etw.Parser.getAllRegisteredTypeInfos();this.parsers_=allTypeInfos.map(function(typeInfo){return new typeInfo.constructor(this);},this);}
+EtwImporter.canImport=function(events){if(!events.hasOwnProperty('name')||!events.hasOwnProperty('content')||events.name!=='ETW'){return false;}
+return true;};EtwImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'EtwImporter';},get model(){return this.model_;},createThreadIfNeeded(pid,tid){this.tidsToPid_[tid]=pid;},removeThreadIfPresent(tid){this.tidsToPid_[tid]=undefined;},getPidFromWindowsTid(tid){if(tid===0)return 0;const pid=this.tidsToPid_[tid];if(pid===undefined){return 0;}
+return pid;},getThreadFromWindowsTid(tid){const pid=this.getPidFromWindowsTid(tid);const process=this.model_.getProcess(pid);if(!process)return undefined;return process.getThread(tid);},getOrCreateCpu(cpuNumber){const cpu=this.model_.kernel.getOrCreateCpu(cpuNumber);return cpu;},importEvents(){this.events_.content.forEach(this.parseInfo.bind(this));if(this.walltime_===undefined||this.ticks_===undefined){throw Error('Cannot find clock sync information in the system trace.');}
+if(this.is64bit_===undefined){throw Error('Cannot determine pointer size of the system trace.'+'Consider deselecting "System tracing" or disabling the "Paging '+'Executive" feature of Windows');}
+this.events_.content.forEach(this.parseEvent.bind(this));},importTimestamp(timestamp){const ts=parseInt(timestamp,16);return(ts-this.walltime_+this.ticks_)/1000.;},parseInfo(event){if(event.hasOwnProperty('guid')&&event.hasOwnProperty('walltime')&&event.hasOwnProperty('tick')&&event.guid==='ClockSync'){this.walltime_=parseInt(event.walltime,16);this.ticks_=parseInt(event.tick,16);}
+if(this.is64bit_===undefined&&event.hasOwnProperty('guid')&&event.hasOwnProperty('op')&&event.hasOwnProperty('ver')&&event.hasOwnProperty('payload')&&event.guid===kThreadGuid&&event.op===kThreadDCStartOpcode){const decodedSize=tr.b.Base64.getDecodedBufferLength(event.payload);if(event.ver===1){if(decodedSize>=52){this.is64bit_=true;}else{this.is64bit_=false;}}else if(event.ver===2){if(decodedSize>=64){this.is64bit_=true;}else{this.is64bit_=false;}}else if(event.ver===3){if(decodedSize>=60){this.is64bit_=true;}else{this.is64bit_=false;}}}
+return true;},parseEvent(event){if(!event.hasOwnProperty('guid')||!event.hasOwnProperty('op')||!event.hasOwnProperty('ver')||!event.hasOwnProperty('cpu')||!event.hasOwnProperty('ts')||!event.hasOwnProperty('payload')){return false;}
+const timestamp=this.importTimestamp(event.ts);const header={guid:event.guid,opcode:event.op,version:event.ver,cpu:event.cpu,timestamp,is64:this.is64bit_};const decoder=this.decoder_;decoder.reset(event.payload);const handler=this.getEventHandler(header.guid,header.opcode);if(!handler)return false;if(!handler(header,decoder)){this.model_.importWarning({type:'parse_error',message:'Malformed '+header.guid+' event ('+event.payload+')'});return false;}
+return true;},registerEventHandler(guid,opcode,handler){if(this.handlers_[guid]===undefined){this.handlers_[guid]=[];}
+this.handlers_[guid][opcode]=handler;},getEventHandler(guid,opcode){if(this.handlers_[guid]===undefined){return undefined;}
+return this.handlers_[guid][opcode];}};tr.importer.Importer.register(EtwImporter);return{EtwImporter,};});'use strict';tr.exportTo('tr.b',function(){class TraceStream{static get HEADER_SIZE(){return Math.pow(2,10);}
+static get CHUNK_SIZE(){return Math.pow(2,20);}
+get isBinary(){throw new Error('Not implemented');}
+get hasData(){throw new Error('Not implemented');}
+get header(){throw new Error('Not implemented');}
+readUntilDelimiter(delim){throw new Error('Not implemented');}
+readNumBytes(opt_size){throw new Error('Not implemented');}
+rewind(){throw new Error('Not implemented');}
+substream(offset,opt_length,opt_headerSize){throw new Error('Not implemented');}}
+return{TraceStream,};});'use strict';tr.exportTo('tr.e.importer.fuchsia',function(){const IMPORT_PRIORITY=0;const IDLE_THREAD_THRESHOLD=6444000000;const ZX_THREAD_STATE_NEW=0;const ZX_THREAD_STATE_RUNNING=1;const ZX_THREAD_STATE_SUSPENDED=2;const ZX_THREAD_STATE_BLOCKED=3;const ZX_THREAD_STATE_DYING=4;const ZX_THREAD_STATE_DEAD=5;class FuchsiaImporter extends tr.importer.Importer{constructor(model,eventData){super(model,eventData);this.importPriority=IMPORT_PRIORITY;this.model_=model;this.events_=eventData.events;this.parsers_=[];this.threadInfo_=new Map();this.processNames_=new Map();this.threadStates_=new Map();}
+static canImport(eventData){if(eventData instanceof tr.b.TraceStream){if(eventData.isBinary)return false;eventData=eventData.header;}
+if(eventData instanceof Object&&eventData.type==='fuchsia'){return true;}
+return false;}
+get importerName(){return'FuchsiaImporter';}
+get model(){return this.model_;}
+importClockSyncMarkers(){}
+finalizeImport(){}
+isIdleThread(prio,tid){if(prio===undefined){return tid>IDLE_THREAD_THRESHOLD;}
+return prio===0;}
+recordThreadState_(tid,timestamp,state,prio){if(this.isIdleThread(prio,tid)){return;}
+const states=this.threadStates_.has(tid)?this.threadStates_.get(tid):[];states.push({'ts':timestamp,state});this.threadStates_.set(tid,states);}
+processContextSwitchEvent_(event){let tid=event.in.tid;let threadName=tid.toString();let procName='';const prio=event.in.prio;if(this.threadInfo_.has(tid)){const threadInfo=this.threadInfo_.get(tid);threadName=threadInfo.name;const pid=threadInfo.pid;if(this.processNames_.has(pid)){procName=this.processNames_.get(pid)+':';}}
+const name=procName+threadName;if(this.isIdleThread(prio,tid)){tid=undefined;}
+const cpu=this.model_.kernel.getOrCreateCpu(event.cpu);const timestamp=tr.b.Unit.timestampFromUs(event.ts);cpu.switchActiveThread(timestamp,{},tid,name,tid);const SCHEDULING_STATE=tr.model.SCHEDULING_STATE;this.recordThreadState_(tid,timestamp,SCHEDULING_STATE.RUNNING,prio);let outState=SCHEDULING_STATE.UNKNOWN;switch(event.out.state){case ZX_THREAD_STATE_NEW:outState=SCHEDULING_STATE.RUNNABLE;break;case ZX_THREAD_STATE_RUNNING:outState=SCHEDULING_STATE.RUNNABLE;break;case ZX_THREAD_STATE_BLOCKED:outState=SCHEDULING_STATE.SLEEPING;break;case ZX_THREAD_STATE_SUSPENDED:outState=SCHEDULING_STATE.STOPPED;break;case ZX_THREAD_STATE_DEAD:outState=SCHEDULING_STATE.TASK_DEAD;break;}
+this.recordThreadState_(event.out.tid,timestamp,outState,event.out.prio);}
+processProcessInfoEvent_(event){const process=this.model_.getOrCreateProcess(event.pid);process.name=event.name;this.processNames_.set(event.pid,event.name);if('sort_index'in event){process.sortIndex=event.sort_index;}}
+processThreadInfoEvent_(event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);thread.name=event.name;this.threadInfo_.set(event.tid,{'name':event.name,'pid':event.pid});if('sort_index'in event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);thread.sortIndex=event.sort_index;}}
+processEvent_(event){switch(event.ph){case'k':this.processContextSwitchEvent_(event);break;case'p':this.processProcessInfoEvent_(event);break;case't':this.processThreadInfoEvent_(event);break;}}
+postProcessStates_(){for(const[tid,states]of this.threadStates_){if(!this.threadInfo_.has(tid)){continue;}
+const pid=this.threadInfo_.get(tid).pid;const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);const slices=[];for(let i=0;i<states.length-1;i++){slices.push(new tr.model.ThreadTimeSlice(thread,states[i].state,'',states[i].ts,{},states[i+1].ts-states[i].ts));}
+thread.timeSlices=slices;}}
+importEvents(){for(const event of this.events_){this.processEvent_(event);}
+this.postProcessStates_();}}
+tr.importer.Importer.register(FuchsiaImporter);return{FuchsiaImporter,IMPORT_PRIORITY,};});'use strict';tr.exportTo('tr.b',function(){const MAX_FUNCTION_ARGS_COUNT=Math.pow(2,15)-1;class InMemoryTraceStream extends tr.b.TraceStream{constructor(buffer,isBinary,opt_headerSize){super();if(!buffer instanceof Uint8Array){throw new Error('buffer should be a Uint8Array');}
+const headerSize=opt_headerSize||tr.b.TraceStream.HEADER_SIZE;this.data_=buffer;this.isBinary_=isBinary;this.header_=InMemoryTraceStream.uint8ArrayToString_(this.data_.subarray(0,headerSize));this.cursor_=0;}
+get isBinary(){return this.isBinary_;}
+get hasData(){return this.cursor_<this.data_.length;}
+get header(){return this.header_;}
+get data(){return this.data_;}
+toString(){this.rewind();return this.readNumBytes(Number.MAX_VALUE);}
+readUntilDelimiter(delim){if(delim.length!==1){throw new Error('delim must be exactly one character');}
+const offset=this.data_.indexOf(delim.charCodeAt(0),this.cursor_)+1;return this.readToOffset_(offset>0?Math.min(offset,this.data_.length):this.data_.length);}
+readNumBytes(opt_size){if(opt_size!==undefined&&opt_size<=0){throw new Error(`readNumBytes expects a positive size (${opt_size} given)`);}
+const size=opt_size||tr.b.TraceStream.CHUNK_SIZE;const offset=Math.min(this.cursor_+size,this.data_.length);return this.readToOffset_(offset);}
+rewind(){this.cursor_=0;}
+substream(startOffset,opt_endOffset,opt_headerSize){return new InMemoryTraceStream(this.data_.subarray(startOffset,opt_endOffset),this.isBinary_,opt_headerSize);}
+readToOffset_(offset){const out=InMemoryTraceStream.uint8ArrayToString_(this.data_.subarray(this.cursor_,offset));this.cursor_=offset;return out;}
+static uint8ArrayToString_(arr){if(typeof TextDecoder!=='undefined'){const decoder=new TextDecoder('utf-8');return decoder.decode(arr);}
+const c=[];for(let i=0;i<arr.length;i+=MAX_FUNCTION_ARGS_COUNT){c.push(String.fromCharCode(...arr.subarray(i,i+MAX_FUNCTION_ARGS_COUNT)));}
+return c.join('');}}
+return{InMemoryTraceStream,};});!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).pako=t()}}(function(){return function t(e,a,i){function n(s,o){if(!a[s]){if(!e[s]){var l="function"==typeof require&&require;if(!o&&l)return l(s,!0);if(r)return r(s,!0);var h=new Error("Cannot find module '"+s+"'");throw h.code="MODULE_NOT_FOUND",h}var d=a[s]={exports:{}};e[s][0].call(d.exports,function(t){var a=e[s][1][t];return n(a||t)},d,d.exports,t,e,a,i)}return a[s].exports}for(var r="function"==typeof require&&require,s=0;s<i.length;s++)n(i[s]);return n}({1:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({level:_,method:c,chunkSize:16384,windowBits:15,memLevel:8,strategy:u,to:""},t||{});var e=this.options;e.raw&&e.windowBits>0?e.windowBits=-e.windowBits:e.gzip&&e.windowBits>0&&e.windowBits<16&&(e.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new h,this.strm.avail_out=0;var a=r.deflateInit2(this.strm,e.level,e.method,e.windowBits,e.memLevel,e.strategy);if(a!==f)throw new Error(l[a]);if(e.header&&r.deflateSetHeader(this.strm,e.header),e.dictionary){var n;if(n="string"==typeof e.dictionary?o.string2buf(e.dictionary):"[object ArrayBuffer]"===d.call(e.dictionary)?new Uint8Array(e.dictionary):e.dictionary,(a=r.deflateSetDictionary(this.strm,n))!==f)throw new Error(l[a]);this._dict_set=!0}}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||l[a.err];return a.result}var r=t("./zlib/deflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/messages"),h=t("./zlib/zstream"),d=Object.prototype.toString,f=0,_=-1,u=0,c=8;i.prototype.push=function(t,e){var a,i,n=this.strm,l=this.options.chunkSize;if(this.ended)return!1;i=e===~~e?e:!0===e?4:0,"string"==typeof t?n.input=o.string2buf(t):"[object ArrayBuffer]"===d.call(t)?n.input=new Uint8Array(t):n.input=t,n.next_in=0,n.avail_in=n.input.length;do{if(0===n.avail_out&&(n.output=new s.Buf8(l),n.next_out=0,n.avail_out=l),1!==(a=r.deflate(n,i))&&a!==f)return this.onEnd(a),this.ended=!0,!1;0!==n.avail_out&&(0!==n.avail_in||4!==i&&2!==i)||("string"===this.options.to?this.onData(o.buf2binstring(s.shrinkBuf(n.output,n.next_out))):this.onData(s.shrinkBuf(n.output,n.next_out)))}while((n.avail_in>0||0===n.avail_out)&&1!==a);return 4===i?(a=r.deflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===f):2!==i||(this.onEnd(f),n.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===f&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Deflate=i,a.deflate=n,a.deflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.gzip=function(t,e){return e=e||{},e.gzip=!0,n(t,e)}},{"./utils/common":3,"./utils/strings":4,"./zlib/deflate":8,"./zlib/messages":13,"./zlib/zstream":15}],2:[function(t,e,a){"use strict";function i(t){if(!(this instanceof i))return new i(t);this.options=s.assign({chunkSize:16384,windowBits:0,to:""},t||{});var e=this.options;e.raw&&e.windowBits>=0&&e.windowBits<16&&(e.windowBits=-e.windowBits,0===e.windowBits&&(e.windowBits=-15)),!(e.windowBits>=0&&e.windowBits<16)||t&&t.windowBits||(e.windowBits+=32),e.windowBits>15&&e.windowBits<48&&0==(15&e.windowBits)&&(e.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new d,this.strm.avail_out=0;var a=r.inflateInit2(this.strm,e.windowBits);if(a!==l.Z_OK)throw new Error(h[a]);this.header=new f,r.inflateGetHeader(this.strm,this.header)}function n(t,e){var a=new i(e);if(a.push(t,!0),a.err)throw a.msg||h[a.err];return a.result}var r=t("./zlib/inflate"),s=t("./utils/common"),o=t("./utils/strings"),l=t("./zlib/constants"),h=t("./zlib/messages"),d=t("./zlib/zstream"),f=t("./zlib/gzheader"),_=Object.prototype.toString;i.prototype.push=function(t,e){var a,i,n,h,d,f,u=this.strm,c=this.options.chunkSize,b=this.options.dictionary,g=!1;if(this.ended)return!1;i=e===~~e?e:!0===e?l.Z_FINISH:l.Z_NO_FLUSH,"string"==typeof t?u.input=o.binstring2buf(t):"[object ArrayBuffer]"===_.call(t)?u.input=new Uint8Array(t):u.input=t,u.next_in=0,u.avail_in=u.input.length;do{if(0===u.avail_out&&(u.output=new s.Buf8(c),u.next_out=0,u.avail_out=c),(a=r.inflate(u,l.Z_NO_FLUSH))===l.Z_NEED_DICT&&b&&(f="string"==typeof b?o.string2buf(b):"[object ArrayBuffer]"===_.call(b)?new Uint8Array(b):b,a=r.inflateSetDictionary(this.strm,f)),a===l.Z_BUF_ERROR&&!0===g&&(a=l.Z_OK,g=!1),a!==l.Z_STREAM_END&&a!==l.Z_OK)return this.onEnd(a),this.ended=!0,!1;u.next_out&&(0!==u.avail_out&&a!==l.Z_STREAM_END&&(0!==u.avail_in||i!==l.Z_FINISH&&i!==l.Z_SYNC_FLUSH)||("string"===this.options.to?(n=o.utf8border(u.output,u.next_out),h=u.next_out-n,d=o.buf2string(u.output,n),u.next_out=h,u.avail_out=c-h,h&&s.arraySet(u.output,u.output,n,h,0),this.onData(d)):this.onData(s.shrinkBuf(u.output,u.next_out)))),0===u.avail_in&&0===u.avail_out&&(g=!0)}while((u.avail_in>0||0===u.avail_out)&&a!==l.Z_STREAM_END);return a===l.Z_STREAM_END&&(i=l.Z_FINISH),i===l.Z_FINISH?(a=r.inflateEnd(this.strm),this.onEnd(a),this.ended=!0,a===l.Z_OK):i!==l.Z_SYNC_FLUSH||(this.onEnd(l.Z_OK),u.avail_out=0,!0)},i.prototype.onData=function(t){this.chunks.push(t)},i.prototype.onEnd=function(t){t===l.Z_OK&&("string"===this.options.to?this.result=this.chunks.join(""):this.result=s.flattenChunks(this.chunks)),this.chunks=[],this.err=t,this.msg=this.strm.msg},a.Inflate=i,a.inflate=n,a.inflateRaw=function(t,e){return e=e||{},e.raw=!0,n(t,e)},a.ungzip=n},{"./utils/common":3,"./utils/strings":4,"./zlib/constants":6,"./zlib/gzheader":9,"./zlib/inflate":11,"./zlib/messages":13,"./zlib/zstream":15}],3:[function(t,e,a){"use strict";function i(t,e){return Object.prototype.hasOwnProperty.call(t,e)}var n="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;a.assign=function(t){for(var e=Array.prototype.slice.call(arguments,1);e.length;){var a=e.shift();if(a){if("object"!=typeof a)throw new TypeError(a+"must be non-object");for(var n in a)i(a,n)&&(t[n]=a[n])}}return t},a.shrinkBuf=function(t,e){return t.length===e?t:t.subarray?t.subarray(0,e):(t.length=e,t)};var r={arraySet:function(t,e,a,i,n){if(e.subarray&&t.subarray)t.set(e.subarray(a,a+i),n);else for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){var e,a,i,n,r,s;for(i=0,e=0,a=t.length;e<a;e++)i+=t[e].length;for(s=new Uint8Array(i),n=0,e=0,a=t.length;e<a;e++)r=t[e],s.set(r,n),n+=r.length;return s}},s={arraySet:function(t,e,a,i,n){for(var r=0;r<i;r++)t[n+r]=e[a+r]},flattenChunks:function(t){return[].concat.apply([],t)}};a.setTyped=function(t){t?(a.Buf8=Uint8Array,a.Buf16=Uint16Array,a.Buf32=Int32Array,a.assign(a,r)):(a.Buf8=Array,a.Buf16=Array,a.Buf32=Array,a.assign(a,s))},a.setTyped(n)},{}],4:[function(t,e,a){"use strict";function i(t,e){if(e<65537&&(t.subarray&&s||!t.subarray&&r))return String.fromCharCode.apply(null,n.shrinkBuf(t,e));for(var a="",i=0;i<e;i++)a+=String.fromCharCode(t[i]);return a}var n=t("./common"),r=!0,s=!0;try{String.fromCharCode.apply(null,[0])}catch(t){r=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(t){s=!1}for(var o=new n.Buf8(256),l=0;l<256;l++)o[l]=l>=252?6:l>=248?5:l>=240?4:l>=224?3:l>=192?2:1;o[254]=o[254]=1,a.string2buf=function(t){var e,a,i,r,s,o=t.length,l=0;for(r=0;r<o;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),l+=a<128?1:a<2048?2:a<65536?3:4;for(e=new n.Buf8(l),s=0,r=0;s<l;r++)55296==(64512&(a=t.charCodeAt(r)))&&r+1<o&&56320==(64512&(i=t.charCodeAt(r+1)))&&(a=65536+(a-55296<<10)+(i-56320),r++),a<128?e[s++]=a:a<2048?(e[s++]=192|a>>>6,e[s++]=128|63&a):a<65536?(e[s++]=224|a>>>12,e[s++]=128|a>>>6&63,e[s++]=128|63&a):(e[s++]=240|a>>>18,e[s++]=128|a>>>12&63,e[s++]=128|a>>>6&63,e[s++]=128|63&a);return e},a.buf2binstring=function(t){return i(t,t.length)},a.binstring2buf=function(t){for(var e=new n.Buf8(t.length),a=0,i=e.length;a<i;a++)e[a]=t.charCodeAt(a);return e},a.buf2string=function(t,e){var a,n,r,s,l=e||t.length,h=new Array(2*l);for(n=0,a=0;a<l;)if((r=t[a++])<128)h[n++]=r;else if((s=o[r])>4)h[n++]=65533,a+=s-1;else{for(r&=2===s?31:3===s?15:7;s>1&&a<l;)r=r<<6|63&t[a++],s--;s>1?h[n++]=65533:r<65536?h[n++]=r:(r-=65536,h[n++]=55296|r>>10&1023,h[n++]=56320|1023&r)}return i(h,n)},a.utf8border=function(t,e){var a;for((e=e||t.length)>t.length&&(e=t.length),a=e-1;a>=0&&128==(192&t[a]);)a--;return a<0?e:0===a?e:a+o[t[a]]>e?a:e}},{"./common":3}],5:[function(t,e,a){"use strict";e.exports=function(t,e,a,i){for(var n=65535&t|0,r=t>>>16&65535|0,s=0;0!==a;){a-=s=a>2e3?2e3:a;do{r=r+(n=n+e[i++]|0)|0}while(--s);n%=65521,r%=65521}return n|r<<16|0}},{}],6:[function(t,e,a){"use strict";e.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],7:[function(t,e,a){"use strict";var i=function(){for(var t,e=[],a=0;a<256;a++){t=a;for(var i=0;i<8;i++)t=1&t?3988292384^t>>>1:t>>>1;e[a]=t}return e}();e.exports=function(t,e,a,n){var r=i,s=n+a;t^=-1;for(var o=n;o<s;o++)t=t>>>8^r[255&(t^e[o])];return-1^t}},{}],8:[function(t,e,a){"use strict";function i(t,e){return t.msg=A[e],e}function n(t){return(t<<1)-(t>4?9:0)}function r(t){for(var e=t.length;--e>=0;)t[e]=0}function s(t){var e=t.state,a=e.pending;a>t.avail_out&&(a=t.avail_out),0!==a&&(z.arraySet(t.output,e.pending_buf,e.pending_out,a,t.next_out),t.next_out+=a,e.pending_out+=a,t.total_out+=a,t.avail_out-=a,e.pending-=a,0===e.pending&&(e.pending_out=0))}function o(t,e){B._tr_flush_block(t,t.block_start>=0?t.block_start:-1,t.strstart-t.block_start,e),t.block_start=t.strstart,s(t.strm)}function l(t,e){t.pending_buf[t.pending++]=e}function h(t,e){t.pending_buf[t.pending++]=e>>>8&255,t.pending_buf[t.pending++]=255&e}function d(t,e,a,i){var n=t.avail_in;return n>i&&(n=i),0===n?0:(t.avail_in-=n,z.arraySet(e,t.input,t.next_in,n,a),1===t.state.wrap?t.adler=S(t.adler,e,n,a):2===t.state.wrap&&(t.adler=E(t.adler,e,n,a)),t.next_in+=n,t.total_in+=n,n)}function f(t,e){var a,i,n=t.max_chain_length,r=t.strstart,s=t.prev_length,o=t.nice_match,l=t.strstart>t.w_size-it?t.strstart-(t.w_size-it):0,h=t.window,d=t.w_mask,f=t.prev,_=t.strstart+at,u=h[r+s-1],c=h[r+s];t.prev_length>=t.good_match&&(n>>=2),o>t.lookahead&&(o=t.lookahead);do{if(a=e,h[a+s]===c&&h[a+s-1]===u&&h[a]===h[r]&&h[++a]===h[r+1]){r+=2,a++;do{}while(h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&h[++r]===h[++a]&&r<_);if(i=at-(_-r),r=_-at,i>s){if(t.match_start=e,s=i,i>=o)break;u=h[r+s-1],c=h[r+s]}}}while((e=f[e&d])>l&&0!=--n);return s<=t.lookahead?s:t.lookahead}function _(t){var e,a,i,n,r,s=t.w_size;do{if(n=t.window_size-t.lookahead-t.strstart,t.strstart>=s+(s-it)){z.arraySet(t.window,t.window,s,s,0),t.match_start-=s,t.strstart-=s,t.block_start-=s,e=a=t.hash_size;do{i=t.head[--e],t.head[e]=i>=s?i-s:0}while(--a);e=a=s;do{i=t.prev[--e],t.prev[e]=i>=s?i-s:0}while(--a);n+=s}if(0===t.strm.avail_in)break;if(a=d(t.strm,t.window,t.strstart+t.lookahead,n),t.lookahead+=a,t.lookahead+t.insert>=et)for(r=t.strstart-t.insert,t.ins_h=t.window[r],t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+1])&t.hash_mask;t.insert&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[r+et-1])&t.hash_mask,t.prev[r&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=r,r++,t.insert--,!(t.lookahead+t.insert<et)););}while(t.lookahead<it&&0!==t.strm.avail_in)}function u(t,e){for(var a,i;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),0!==a&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a)),t.match_length>=et)if(i=B._tr_tally(t,t.strstart-t.match_start,t.match_length-et),t.lookahead-=t.match_length,t.match_length<=t.max_lazy_match&&t.lookahead>=et){t.match_length--;do{t.strstart++,t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart}while(0!=--t.match_length);t.strstart++}else t.strstart+=t.match_length,t.match_length=0,t.ins_h=t.window[t.strstart],t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+1])&t.hash_mask;else i=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++;if(i&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function c(t,e){for(var a,i,n;;){if(t.lookahead<it){if(_(t),t.lookahead<it&&e===Z)return _t;if(0===t.lookahead)break}if(a=0,t.lookahead>=et&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart),t.prev_length=t.match_length,t.prev_match=t.match_start,t.match_length=et-1,0!==a&&t.prev_length<t.max_lazy_match&&t.strstart-a<=t.w_size-it&&(t.match_length=f(t,a),t.match_length<=5&&(t.strategy===H||t.match_length===et&&t.strstart-t.match_start>4096)&&(t.match_length=et-1)),t.prev_length>=et&&t.match_length<=t.prev_length){n=t.strstart+t.lookahead-et,i=B._tr_tally(t,t.strstart-1-t.prev_match,t.prev_length-et),t.lookahead-=t.prev_length-1,t.prev_length-=2;do{++t.strstart<=n&&(t.ins_h=(t.ins_h<<t.hash_shift^t.window[t.strstart+et-1])&t.hash_mask,a=t.prev[t.strstart&t.w_mask]=t.head[t.ins_h],t.head[t.ins_h]=t.strstart)}while(0!=--t.prev_length);if(t.match_available=0,t.match_length=et-1,t.strstart++,i&&(o(t,!1),0===t.strm.avail_out))return _t}else if(t.match_available){if((i=B._tr_tally(t,0,t.window[t.strstart-1]))&&o(t,!1),t.strstart++,t.lookahead--,0===t.strm.avail_out)return _t}else t.match_available=1,t.strstart++,t.lookahead--}return t.match_available&&(i=B._tr_tally(t,0,t.window[t.strstart-1]),t.match_available=0),t.insert=t.strstart<et-1?t.strstart:et-1,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function b(t,e){for(var a,i,n,r,s=t.window;;){if(t.lookahead<=at){if(_(t),t.lookahead<=at&&e===Z)return _t;if(0===t.lookahead)break}if(t.match_length=0,t.lookahead>=et&&t.strstart>0&&(n=t.strstart-1,(i=s[n])===s[++n]&&i===s[++n]&&i===s[++n])){r=t.strstart+at;do{}while(i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&i===s[++n]&&n<r);t.match_length=at-(r-n),t.match_length>t.lookahead&&(t.match_length=t.lookahead)}if(t.match_length>=et?(a=B._tr_tally(t,1,t.match_length-et),t.lookahead-=t.match_length,t.strstart+=t.match_length,t.match_length=0):(a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++),a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function g(t,e){for(var a;;){if(0===t.lookahead&&(_(t),0===t.lookahead)){if(e===Z)return _t;break}if(t.match_length=0,a=B._tr_tally(t,0,t.window[t.strstart]),t.lookahead--,t.strstart++,a&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):t.last_lit&&(o(t,!1),0===t.strm.avail_out)?_t:ut}function m(t,e,a,i,n){this.good_length=t,this.max_lazy=e,this.nice_length=a,this.max_chain=i,this.func=n}function w(t){t.window_size=2*t.w_size,r(t.head),t.max_lazy_match=x[t.level].max_lazy,t.good_match=x[t.level].good_length,t.nice_match=x[t.level].nice_length,t.max_chain_length=x[t.level].max_chain,t.strstart=0,t.block_start=0,t.lookahead=0,t.insert=0,t.match_length=t.prev_length=et-1,t.match_available=0,t.ins_h=0}function p(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=q,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new z.Buf16(2*$),this.dyn_dtree=new z.Buf16(2*(2*Q+1)),this.bl_tree=new z.Buf16(2*(2*V+1)),r(this.dyn_ltree),r(this.dyn_dtree),r(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new z.Buf16(tt+1),this.heap=new z.Buf16(2*J+1),r(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new z.Buf16(2*J+1),r(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function v(t){var e;return t&&t.state?(t.total_in=t.total_out=0,t.data_type=Y,e=t.state,e.pending=0,e.pending_out=0,e.wrap<0&&(e.wrap=-e.wrap),e.status=e.wrap?rt:dt,t.adler=2===e.wrap?0:1,e.last_flush=Z,B._tr_init(e),D):i(t,U)}function k(t){var e=v(t);return e===D&&w(t.state),e}function y(t,e,a,n,r,s){if(!t)return U;var o=1;if(e===L&&(e=6),n<0?(o=0,n=-n):n>15&&(o=2,n-=16),r<1||r>G||a!==q||n<8||n>15||e<0||e>9||s<0||s>M)return i(t,U);8===n&&(n=9);var l=new p;return t.state=l,l.strm=t,l.wrap=o,l.gzhead=null,l.w_bits=n,l.w_size=1<<l.w_bits,l.w_mask=l.w_size-1,l.hash_bits=r+7,l.hash_size=1<<l.hash_bits,l.hash_mask=l.hash_size-1,l.hash_shift=~~((l.hash_bits+et-1)/et),l.window=new z.Buf8(2*l.w_size),l.head=new z.Buf16(l.hash_size),l.prev=new z.Buf16(l.w_size),l.lit_bufsize=1<<r+6,l.pending_buf_size=4*l.lit_bufsize,l.pending_buf=new z.Buf8(l.pending_buf_size),l.d_buf=1*l.lit_bufsize,l.l_buf=3*l.lit_bufsize,l.level=e,l.strategy=s,l.method=a,k(t)}var x,z=t("../utils/common"),B=t("./trees"),S=t("./adler32"),E=t("./crc32"),A=t("./messages"),Z=0,R=1,C=3,N=4,O=5,D=0,I=1,U=-2,T=-3,F=-5,L=-1,H=1,j=2,K=3,M=4,P=0,Y=2,q=8,G=9,X=15,W=8,J=286,Q=30,V=19,$=2*J+1,tt=15,et=3,at=258,it=at+et+1,nt=32,rt=42,st=69,ot=73,lt=91,ht=103,dt=113,ft=666,_t=1,ut=2,ct=3,bt=4,gt=3;x=[new m(0,0,0,0,function(t,e){var a=65535;for(a>t.pending_buf_size-5&&(a=t.pending_buf_size-5);;){if(t.lookahead<=1){if(_(t),0===t.lookahead&&e===Z)return _t;if(0===t.lookahead)break}t.strstart+=t.lookahead,t.lookahead=0;var i=t.block_start+a;if((0===t.strstart||t.strstart>=i)&&(t.lookahead=t.strstart-i,t.strstart=i,o(t,!1),0===t.strm.avail_out))return _t;if(t.strstart-t.block_start>=t.w_size-it&&(o(t,!1),0===t.strm.avail_out))return _t}return t.insert=0,e===N?(o(t,!0),0===t.strm.avail_out?ct:bt):(t.strstart>t.block_start&&(o(t,!1),t.strm.avail_out),_t)}),new m(4,4,8,4,u),new m(4,5,16,8,u),new m(4,6,32,32,u),new m(4,4,16,16,c),new m(8,16,32,32,c),new m(8,16,128,128,c),new m(8,32,128,256,c),new m(32,128,258,1024,c),new m(32,258,258,4096,c)],a.deflateInit=function(t,e){return y(t,e,q,X,W,P)},a.deflateInit2=y,a.deflateReset=k,a.deflateResetKeep=v,a.deflateSetHeader=function(t,e){return t&&t.state?2!==t.state.wrap?U:(t.state.gzhead=e,D):U},a.deflate=function(t,e){var a,o,d,f;if(!t||!t.state||e>O||e<0)return t?i(t,U):U;if(o=t.state,!t.output||!t.input&&0!==t.avail_in||o.status===ft&&e!==N)return i(t,0===t.avail_out?F:U);if(o.strm=t,a=o.last_flush,o.last_flush=e,o.status===rt)if(2===o.wrap)t.adler=0,l(o,31),l(o,139),l(o,8),o.gzhead?(l(o,(o.gzhead.text?1:0)+(o.gzhead.hcrc?2:0)+(o.gzhead.extra?4:0)+(o.gzhead.name?8:0)+(o.gzhead.comment?16:0)),l(o,255&o.gzhead.time),l(o,o.gzhead.time>>8&255),l(o,o.gzhead.time>>16&255),l(o,o.gzhead.time>>24&255),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,255&o.gzhead.os),o.gzhead.extra&&o.gzhead.extra.length&&(l(o,255&o.gzhead.extra.length),l(o,o.gzhead.extra.length>>8&255)),o.gzhead.hcrc&&(t.adler=E(t.adler,o.pending_buf,o.pending,0)),o.gzindex=0,o.status=st):(l(o,0),l(o,0),l(o,0),l(o,0),l(o,0),l(o,9===o.level?2:o.strategy>=j||o.level<2?4:0),l(o,gt),o.status=dt);else{var _=q+(o.w_bits-8<<4)<<8;_|=(o.strategy>=j||o.level<2?0:o.level<6?1:6===o.level?2:3)<<6,0!==o.strstart&&(_|=nt),_+=31-_%31,o.status=dt,h(o,_),0!==o.strstart&&(h(o,t.adler>>>16),h(o,65535&t.adler)),t.adler=1}if(o.status===st)if(o.gzhead.extra){for(d=o.pending;o.gzindex<(65535&o.gzhead.extra.length)&&(o.pending!==o.pending_buf_size||(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending!==o.pending_buf_size));)l(o,255&o.gzhead.extra[o.gzindex]),o.gzindex++;o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),o.gzindex===o.gzhead.extra.length&&(o.gzindex=0,o.status=ot)}else o.status=ot;if(o.status===ot)if(o.gzhead.name){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.name.length?255&o.gzhead.name.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.gzindex=0,o.status=lt)}else o.status=lt;if(o.status===lt)if(o.gzhead.comment){d=o.pending;do{if(o.pending===o.pending_buf_size&&(o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),s(t),d=o.pending,o.pending===o.pending_buf_size)){f=1;break}f=o.gzindex<o.gzhead.comment.length?255&o.gzhead.comment.charCodeAt(o.gzindex++):0,l(o,f)}while(0!==f);o.gzhead.hcrc&&o.pending>d&&(t.adler=E(t.adler,o.pending_buf,o.pending-d,d)),0===f&&(o.status=ht)}else o.status=ht;if(o.status===ht&&(o.gzhead.hcrc?(o.pending+2>o.pending_buf_size&&s(t),o.pending+2<=o.pending_buf_size&&(l(o,255&t.adler),l(o,t.adler>>8&255),t.adler=0,o.status=dt)):o.status=dt),0!==o.pending){if(s(t),0===t.avail_out)return o.last_flush=-1,D}else if(0===t.avail_in&&n(e)<=n(a)&&e!==N)return i(t,F);if(o.status===ft&&0!==t.avail_in)return i(t,F);if(0!==t.avail_in||0!==o.lookahead||e!==Z&&o.status!==ft){var u=o.strategy===j?g(o,e):o.strategy===K?b(o,e):x[o.level].func(o,e);if(u!==ct&&u!==bt||(o.status=ft),u===_t||u===ct)return 0===t.avail_out&&(o.last_flush=-1),D;if(u===ut&&(e===R?B._tr_align(o):e!==O&&(B._tr_stored_block(o,0,0,!1),e===C&&(r(o.head),0===o.lookahead&&(o.strstart=0,o.block_start=0,o.insert=0))),s(t),0===t.avail_out))return o.last_flush=-1,D}return e!==N?D:o.wrap<=0?I:(2===o.wrap?(l(o,255&t.adler),l(o,t.adler>>8&255),l(o,t.adler>>16&255),l(o,t.adler>>24&255),l(o,255&t.total_in),l(o,t.total_in>>8&255),l(o,t.total_in>>16&255),l(o,t.total_in>>24&255)):(h(o,t.adler>>>16),h(o,65535&t.adler)),s(t),o.wrap>0&&(o.wrap=-o.wrap),0!==o.pending?D:I)},a.deflateEnd=function(t){var e;return t&&t.state?(e=t.state.status)!==rt&&e!==st&&e!==ot&&e!==lt&&e!==ht&&e!==dt&&e!==ft?i(t,U):(t.state=null,e===dt?i(t,T):D):U},a.deflateSetDictionary=function(t,e){var a,i,n,s,o,l,h,d,f=e.length;if(!t||!t.state)return U;if(a=t.state,2===(s=a.wrap)||1===s&&a.status!==rt||a.lookahead)return U;for(1===s&&(t.adler=S(t.adler,e,f,0)),a.wrap=0,f>=a.w_size&&(0===s&&(r(a.head),a.strstart=0,a.block_start=0,a.insert=0),d=new z.Buf8(a.w_size),z.arraySet(d,e,f-a.w_size,a.w_size,0),e=d,f=a.w_size),o=t.avail_in,l=t.next_in,h=t.input,t.avail_in=f,t.next_in=0,t.input=e,_(a);a.lookahead>=et;){i=a.strstart,n=a.lookahead-(et-1);do{a.ins_h=(a.ins_h<<a.hash_shift^a.window[i+et-1])&a.hash_mask,a.prev[i&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=i,i++}while(--n);a.strstart=i,a.lookahead=et-1,_(a)}return a.strstart+=a.lookahead,a.block_start=a.strstart,a.insert=a.lookahead,a.lookahead=0,a.match_length=a.prev_length=et-1,a.match_available=0,t.next_in=l,t.input=h,t.avail_in=o,a.wrap=s,D},a.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./messages":13,"./trees":14}],9:[function(t,e,a){"use strict";e.exports=function(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}},{}],10:[function(t,e,a){"use strict";e.exports=function(t,e){var a,i,n,r,s,o,l,h,d,f,_,u,c,b,g,m,w,p,v,k,y,x,z,B,S;a=t.state,i=t.next_in,B=t.input,n=i+(t.avail_in-5),r=t.next_out,S=t.output,s=r-(e-t.avail_out),o=r+(t.avail_out-257),l=a.dmax,h=a.wsize,d=a.whave,f=a.wnext,_=a.window,u=a.hold,c=a.bits,b=a.lencode,g=a.distcode,m=(1<<a.lenbits)-1,w=(1<<a.distbits)-1;t:do{c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=b[u&m];e:for(;;){if(v=p>>>24,u>>>=v,c-=v,0===(v=p>>>16&255))S[r++]=65535&p;else{if(!(16&v)){if(0==(64&v)){p=b[(65535&p)+(u&(1<<v)-1)];continue e}if(32&v){a.mode=12;break t}t.msg="invalid literal/length code",a.mode=30;break t}k=65535&p,(v&=15)&&(c<v&&(u+=B[i++]<<c,c+=8),k+=u&(1<<v)-1,u>>>=v,c-=v),c<15&&(u+=B[i++]<<c,c+=8,u+=B[i++]<<c,c+=8),p=g[u&w];a:for(;;){if(v=p>>>24,u>>>=v,c-=v,!(16&(v=p>>>16&255))){if(0==(64&v)){p=g[(65535&p)+(u&(1<<v)-1)];continue a}t.msg="invalid distance code",a.mode=30;break t}if(y=65535&p,v&=15,c<v&&(u+=B[i++]<<c,(c+=8)<v&&(u+=B[i++]<<c,c+=8)),(y+=u&(1<<v)-1)>l){t.msg="invalid distance too far back",a.mode=30;break t}if(u>>>=v,c-=v,v=r-s,y>v){if((v=y-v)>d&&a.sane){t.msg="invalid distance too far back",a.mode=30;break t}if(x=0,z=_,0===f){if(x+=h-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}else if(f<v){if(x+=h+f-v,(v-=f)<k){k-=v;do{S[r++]=_[x++]}while(--v);if(x=0,f<k){k-=v=f;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}}}else if(x+=f-v,v<k){k-=v;do{S[r++]=_[x++]}while(--v);x=r-y,z=S}for(;k>2;)S[r++]=z[x++],S[r++]=z[x++],S[r++]=z[x++],k-=3;k&&(S[r++]=z[x++],k>1&&(S[r++]=z[x++]))}else{x=r-y;do{S[r++]=S[x++],S[r++]=S[x++],S[r++]=S[x++],k-=3}while(k>2);k&&(S[r++]=S[x++],k>1&&(S[r++]=S[x++]))}break}}break}}while(i<n&&r<o);i-=k=c>>3,u&=(1<<(c-=k<<3))-1,t.next_in=i,t.next_out=r,t.avail_in=i<n?n-i+5:5-(i-n),t.avail_out=r<o?o-r+257:257-(r-o),a.hold=u,a.bits=c}},{}],11:[function(t,e,a){"use strict";function i(t){return(t>>>24&255)+(t>>>8&65280)+((65280&t)<<8)+((255&t)<<24)}function n(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new u.Buf16(320),this.work=new u.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function r(t){var e;return t&&t.state?(e=t.state,t.total_in=t.total_out=e.total=0,t.msg="",e.wrap&&(t.adler=1&e.wrap),e.mode=N,e.last=0,e.havedict=0,e.dmax=32768,e.head=null,e.hold=0,e.bits=0,e.lencode=e.lendyn=new u.Buf32(dt),e.distcode=e.distdyn=new u.Buf32(ft),e.sane=1,e.back=-1,z):E}function s(t){var e;return t&&t.state?(e=t.state,e.wsize=0,e.whave=0,e.wnext=0,r(t)):E}function o(t,e){var a,i;return t&&t.state?(i=t.state,e<0?(a=0,e=-e):(a=1+(e>>4),e<48&&(e&=15)),e&&(e<8||e>15)?E:(null!==i.window&&i.wbits!==e&&(i.window=null),i.wrap=a,i.wbits=e,s(t))):E}function l(t,e){var a,i;return t?(i=new n,t.state=i,i.window=null,(a=o(t,e))!==z&&(t.state=null),a):E}function h(t){if(ut){var e;for(f=new u.Buf32(512),_=new u.Buf32(32),e=0;e<144;)t.lens[e++]=8;for(;e<256;)t.lens[e++]=9;for(;e<280;)t.lens[e++]=7;for(;e<288;)t.lens[e++]=8;for(m(p,t.lens,0,288,f,0,t.work,{bits:9}),e=0;e<32;)t.lens[e++]=5;m(v,t.lens,0,32,_,0,t.work,{bits:5}),ut=!1}t.lencode=f,t.lenbits=9,t.distcode=_,t.distbits=5}function d(t,e,a,i){var n,r=t.state;return null===r.window&&(r.wsize=1<<r.wbits,r.wnext=0,r.whave=0,r.window=new u.Buf8(r.wsize)),i>=r.wsize?(u.arraySet(r.window,e,a-r.wsize,r.wsize,0),r.wnext=0,r.whave=r.wsize):((n=r.wsize-r.wnext)>i&&(n=i),u.arraySet(r.window,e,a-i,n,r.wnext),(i-=n)?(u.arraySet(r.window,e,a-i,i,0),r.wnext=i,r.whave=r.wsize):(r.wnext+=n,r.wnext===r.wsize&&(r.wnext=0),r.whave<r.wsize&&(r.whave+=n))),0}var f,_,u=t("../utils/common"),c=t("./adler32"),b=t("./crc32"),g=t("./inffast"),m=t("./inftrees"),w=0,p=1,v=2,k=4,y=5,x=6,z=0,B=1,S=2,E=-2,A=-3,Z=-4,R=-5,C=8,N=1,O=2,D=3,I=4,U=5,T=6,F=7,L=8,H=9,j=10,K=11,M=12,P=13,Y=14,q=15,G=16,X=17,W=18,J=19,Q=20,V=21,$=22,tt=23,et=24,at=25,it=26,nt=27,rt=28,st=29,ot=30,lt=31,ht=32,dt=852,ft=592,_t=15,ut=!0;a.inflateReset=s,a.inflateReset2=o,a.inflateResetKeep=r,a.inflateInit=function(t){return l(t,_t)},a.inflateInit2=l,a.inflate=function(t,e){var a,n,r,s,o,l,f,_,dt,ft,_t,ut,ct,bt,gt,mt,wt,pt,vt,kt,yt,xt,zt,Bt,St=0,Et=new u.Buf8(4),At=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!t||!t.state||!t.output||!t.input&&0!==t.avail_in)return E;(a=t.state).mode===M&&(a.mode=P),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,ft=l,_t=f,xt=z;t:for(;;)switch(a.mode){case N:if(0===a.wrap){a.mode=P;break}for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(2&a.wrap&&35615===_){a.check=0,Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0),_=0,dt=0,a.mode=O;break}if(a.flags=0,a.head&&(a.head.done=!1),!(1&a.wrap)||(((255&_)<<8)+(_>>8))%31){t.msg="incorrect header check",a.mode=ot;break}if((15&_)!==C){t.msg="unknown compression method",a.mode=ot;break}if(_>>>=4,dt-=4,yt=8+(15&_),0===a.wbits)a.wbits=yt;else if(yt>a.wbits){t.msg="invalid window size",a.mode=ot;break}a.dmax=1<<yt,t.adler=a.check=1,a.mode=512&_?j:M,_=0,dt=0;break;case O:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.flags=_,(255&a.flags)!==C){t.msg="unknown compression method",a.mode=ot;break}if(57344&a.flags){t.msg="unknown header flags set",a.mode=ot;break}a.head&&(a.head.text=_>>8&1),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=D;case D:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.time=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,Et[2]=_>>>16&255,Et[3]=_>>>24&255,a.check=b(a.check,Et,4,0)),_=0,dt=0,a.mode=I;case I:for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.head&&(a.head.xflags=255&_,a.head.os=_>>8),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0,a.mode=U;case U:if(1024&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length=_,a.head&&(a.head.extra_len=_),512&a.flags&&(Et[0]=255&_,Et[1]=_>>>8&255,a.check=b(a.check,Et,2,0)),_=0,dt=0}else a.head&&(a.head.extra=null);a.mode=T;case T:if(1024&a.flags&&((ut=a.length)>l&&(ut=l),ut&&(a.head&&(yt=a.head.extra_len-a.length,a.head.extra||(a.head.extra=new Array(a.head.extra_len)),u.arraySet(a.head.extra,n,s,ut,yt)),512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,a.length-=ut),a.length))break t;a.length=0,a.mode=F;case F:if(2048&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.name+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.name=null);a.length=0,a.mode=L;case L:if(4096&a.flags){if(0===l)break t;ut=0;do{yt=n[s+ut++],a.head&&yt&&a.length<65536&&(a.head.comment+=String.fromCharCode(yt))}while(yt&&ut<l);if(512&a.flags&&(a.check=b(a.check,n,ut,s)),l-=ut,s+=ut,yt)break t}else a.head&&(a.head.comment=null);a.mode=H;case H:if(512&a.flags){for(;dt<16;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(65535&a.check)){t.msg="header crc mismatch",a.mode=ot;break}_=0,dt=0}a.head&&(a.head.hcrc=a.flags>>9&1,a.head.done=!0),t.adler=a.check=0,a.mode=M;break;case j:for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}t.adler=a.check=i(_),_=0,dt=0,a.mode=K;case K:if(0===a.havedict)return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,S;t.adler=a.check=1,a.mode=M;case M:if(e===y||e===x)break t;case P:if(a.last){_>>>=7&dt,dt-=7&dt,a.mode=nt;break}for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}switch(a.last=1&_,_>>>=1,dt-=1,3&_){case 0:a.mode=Y;break;case 1:if(h(a),a.mode=Q,e===x){_>>>=2,dt-=2;break t}break;case 2:a.mode=X;break;case 3:t.msg="invalid block type",a.mode=ot}_>>>=2,dt-=2;break;case Y:for(_>>>=7&dt,dt-=7&dt;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if((65535&_)!=(_>>>16^65535)){t.msg="invalid stored block lengths",a.mode=ot;break}if(a.length=65535&_,_=0,dt=0,a.mode=q,e===x)break t;case q:a.mode=G;case G:if(ut=a.length){if(ut>l&&(ut=l),ut>f&&(ut=f),0===ut)break t;u.arraySet(r,n,s,ut,o),l-=ut,s+=ut,f-=ut,o+=ut,a.length-=ut;break}a.mode=M;break;case X:for(;dt<14;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(a.nlen=257+(31&_),_>>>=5,dt-=5,a.ndist=1+(31&_),_>>>=5,dt-=5,a.ncode=4+(15&_),_>>>=4,dt-=4,a.nlen>286||a.ndist>30){t.msg="too many length or distance symbols",a.mode=ot;break}a.have=0,a.mode=W;case W:for(;a.have<a.ncode;){for(;dt<3;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.lens[At[a.have++]]=7&_,_>>>=3,dt-=3}for(;a.have<19;)a.lens[At[a.have++]]=0;if(a.lencode=a.lendyn,a.lenbits=7,zt={bits:a.lenbits},xt=m(w,a.lens,0,19,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid code lengths set",a.mode=ot;break}a.have=0,a.mode=J;case J:for(;a.have<a.nlen+a.ndist;){for(;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(wt<16)_>>>=gt,dt-=gt,a.lens[a.have++]=wt;else{if(16===wt){for(Bt=gt+2;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_>>>=gt,dt-=gt,0===a.have){t.msg="invalid bit length repeat",a.mode=ot;break}yt=a.lens[a.have-1],ut=3+(3&_),_>>>=2,dt-=2}else if(17===wt){for(Bt=gt+3;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=3+(7&(_>>>=gt)),_>>>=3,dt-=3}else{for(Bt=gt+7;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}dt-=gt,yt=0,ut=11+(127&(_>>>=gt)),_>>>=7,dt-=7}if(a.have+ut>a.nlen+a.ndist){t.msg="invalid bit length repeat",a.mode=ot;break}for(;ut--;)a.lens[a.have++]=yt}}if(a.mode===ot)break;if(0===a.lens[256]){t.msg="invalid code -- missing end-of-block",a.mode=ot;break}if(a.lenbits=9,zt={bits:a.lenbits},xt=m(p,a.lens,0,a.nlen,a.lencode,0,a.work,zt),a.lenbits=zt.bits,xt){t.msg="invalid literal/lengths set",a.mode=ot;break}if(a.distbits=6,a.distcode=a.distdyn,zt={bits:a.distbits},xt=m(v,a.lens,a.nlen,a.ndist,a.distcode,0,a.work,zt),a.distbits=zt.bits,xt){t.msg="invalid distances set",a.mode=ot;break}if(a.mode=Q,e===x)break t;case Q:a.mode=V;case V:if(l>=6&&f>=258){t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,g(t,_t),o=t.next_out,r=t.output,f=t.avail_out,s=t.next_in,n=t.input,l=t.avail_in,_=a.hold,dt=a.bits,a.mode===M&&(a.back=-1);break}for(a.back=0;St=a.lencode[_&(1<<a.lenbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(mt&&0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.lencode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,a.length=wt,0===mt){a.mode=it;break}if(32&mt){a.back=-1,a.mode=M;break}if(64&mt){t.msg="invalid literal/length code",a.mode=ot;break}a.extra=15&mt,a.mode=$;case $:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.length+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}a.was=a.length,a.mode=tt;case tt:for(;St=a.distcode[_&(1<<a.distbits)-1],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(0==(240&mt)){for(pt=gt,vt=mt,kt=wt;St=a.distcode[kt+((_&(1<<pt+vt)-1)>>pt)],gt=St>>>24,mt=St>>>16&255,wt=65535&St,!(pt+gt<=dt);){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}_>>>=pt,dt-=pt,a.back+=pt}if(_>>>=gt,dt-=gt,a.back+=gt,64&mt){t.msg="invalid distance code",a.mode=ot;break}a.offset=wt,a.extra=15&mt,a.mode=et;case et:if(a.extra){for(Bt=a.extra;dt<Bt;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}a.offset+=_&(1<<a.extra)-1,_>>>=a.extra,dt-=a.extra,a.back+=a.extra}if(a.offset>a.dmax){t.msg="invalid distance too far back",a.mode=ot;break}a.mode=at;case at:if(0===f)break t;if(ut=_t-f,a.offset>ut){if((ut=a.offset-ut)>a.whave&&a.sane){t.msg="invalid distance too far back",a.mode=ot;break}ut>a.wnext?(ut-=a.wnext,ct=a.wsize-ut):ct=a.wnext-ut,ut>a.length&&(ut=a.length),bt=a.window}else bt=r,ct=o-a.offset,ut=a.length;ut>f&&(ut=f),f-=ut,a.length-=ut;do{r[o++]=bt[ct++]}while(--ut);0===a.length&&(a.mode=V);break;case it:if(0===f)break t;r[o++]=a.length,f--,a.mode=V;break;case nt:if(a.wrap){for(;dt<32;){if(0===l)break t;l--,_|=n[s++]<<dt,dt+=8}if(_t-=f,t.total_out+=_t,a.total+=_t,_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,o-_t):c(a.check,r,_t,o-_t)),_t=f,(a.flags?_:i(_))!==a.check){t.msg="incorrect data check",a.mode=ot;break}_=0,dt=0}a.mode=rt;case rt:if(a.wrap&&a.flags){for(;dt<32;){if(0===l)break t;l--,_+=n[s++]<<dt,dt+=8}if(_!==(4294967295&a.total)){t.msg="incorrect length check",a.mode=ot;break}_=0,dt=0}a.mode=st;case st:xt=B;break t;case ot:xt=A;break t;case lt:return Z;case ht:default:return E}return t.next_out=o,t.avail_out=f,t.next_in=s,t.avail_in=l,a.hold=_,a.bits=dt,(a.wsize||_t!==t.avail_out&&a.mode<ot&&(a.mode<nt||e!==k))&&d(t,t.output,t.next_out,_t-t.avail_out)?(a.mode=lt,Z):(ft-=t.avail_in,_t-=t.avail_out,t.total_in+=ft,t.total_out+=_t,a.total+=_t,a.wrap&&_t&&(t.adler=a.check=a.flags?b(a.check,r,_t,t.next_out-_t):c(a.check,r,_t,t.next_out-_t)),t.data_type=a.bits+(a.last?64:0)+(a.mode===M?128:0)+(a.mode===Q||a.mode===q?256:0),(0===ft&&0===_t||e===k)&&xt===z&&(xt=R),xt)},a.inflateEnd=function(t){if(!t||!t.state)return E;var e=t.state;return e.window&&(e.window=null),t.state=null,z},a.inflateGetHeader=function(t,e){var a;return t&&t.state?0==(2&(a=t.state).wrap)?E:(a.head=e,e.done=!1,z):E},a.inflateSetDictionary=function(t,e){var a,i,n=e.length;return t&&t.state?0!==(a=t.state).wrap&&a.mode!==K?E:a.mode===K&&(i=1,(i=c(i,e,n,0))!==a.check)?A:d(t,e,n,n)?(a.mode=lt,Z):(a.havedict=1,z):E},a.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":3,"./adler32":5,"./crc32":7,"./inffast":10,"./inftrees":12}],12:[function(t,e,a){"use strict";var i=t("../utils/common"),n=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],r=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],s=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],o=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];e.exports=function(t,e,a,l,h,d,f,_){var u,c,b,g,m,w,p,v,k,y=_.bits,x=0,z=0,B=0,S=0,E=0,A=0,Z=0,R=0,C=0,N=0,O=null,D=0,I=new i.Buf16(16),U=new i.Buf16(16),T=null,F=0;for(x=0;x<=15;x++)I[x]=0;for(z=0;z<l;z++)I[e[a+z]]++;for(E=y,S=15;S>=1&&0===I[S];S--);if(E>S&&(E=S),0===S)return h[d++]=20971520,h[d++]=20971520,_.bits=1,0;for(B=1;B<S&&0===I[B];B++);for(E<B&&(E=B),R=1,x=1;x<=15;x++)if(R<<=1,(R-=I[x])<0)return-1;if(R>0&&(0===t||1!==S))return-1;for(U[1]=0,x=1;x<15;x++)U[x+1]=U[x]+I[x];for(z=0;z<l;z++)0!==e[a+z]&&(f[U[e[a+z]]++]=z);if(0===t?(O=T=f,w=19):1===t?(O=n,D-=257,T=r,F-=257,w=256):(O=s,T=o,w=-1),N=0,z=0,x=B,m=d,A=E,Z=0,b=-1,C=1<<E,g=C-1,1===t&&C>852||2===t&&C>592)return 1;for(;;){p=x-Z,f[z]<w?(v=0,k=f[z]):f[z]>w?(v=T[F+f[z]],k=O[D+f[z]]):(v=96,k=0),u=1<<x-Z,B=c=1<<A;do{h[m+(N>>Z)+(c-=u)]=p<<24|v<<16|k|0}while(0!==c);for(u=1<<x-1;N&u;)u>>=1;if(0!==u?(N&=u-1,N+=u):N=0,z++,0==--I[x]){if(x===S)break;x=e[a+f[z]]}if(x>E&&(N&g)!==b){for(0===Z&&(Z=E),m+=B,R=1<<(A=x-Z);A+Z<S&&!((R-=I[A+Z])<=0);)A++,R<<=1;if(C+=1<<A,1===t&&C>852||2===t&&C>592)return 1;h[b=N&g]=E<<24|A<<16|m-d|0}}return 0!==N&&(h[m+N]=x-Z<<24|64<<16|0),_.bits=E,0}},{"../utils/common":3}],13:[function(t,e,a){"use strict";e.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],14:[function(t,e,a){"use strict";function i(t){for(var e=t.length;--e>=0;)t[e]=0}function n(t,e,a,i,n){this.static_tree=t,this.extra_bits=e,this.extra_base=a,this.elems=i,this.max_length=n,this.has_stree=t&&t.length}function r(t,e){this.dyn_tree=t,this.max_code=0,this.stat_desc=e}function s(t){return t<256?et[t]:et[256+(t>>>7)]}function o(t,e){t.pending_buf[t.pending++]=255&e,t.pending_buf[t.pending++]=e>>>8&255}function l(t,e,a){t.bi_valid>M-a?(t.bi_buf|=e<<t.bi_valid&65535,o(t,t.bi_buf),t.bi_buf=e>>M-t.bi_valid,t.bi_valid+=a-M):(t.bi_buf|=e<<t.bi_valid&65535,t.bi_valid+=a)}function h(t,e,a){l(t,a[2*e],a[2*e+1])}function d(t,e){var a=0;do{a|=1&t,t>>>=1,a<<=1}while(--e>0);return a>>>1}function f(t){16===t.bi_valid?(o(t,t.bi_buf),t.bi_buf=0,t.bi_valid=0):t.bi_valid>=8&&(t.pending_buf[t.pending++]=255&t.bi_buf,t.bi_buf>>=8,t.bi_valid-=8)}function _(t,e){var a,i,n,r,s,o,l=e.dyn_tree,h=e.max_code,d=e.stat_desc.static_tree,f=e.stat_desc.has_stree,_=e.stat_desc.extra_bits,u=e.stat_desc.extra_base,c=e.stat_desc.max_length,b=0;for(r=0;r<=K;r++)t.bl_count[r]=0;for(l[2*t.heap[t.heap_max]+1]=0,a=t.heap_max+1;a<j;a++)(r=l[2*l[2*(i=t.heap[a])+1]+1]+1)>c&&(r=c,b++),l[2*i+1]=r,i>h||(t.bl_count[r]++,s=0,i>=u&&(s=_[i-u]),o=l[2*i],t.opt_len+=o*(r+s),f&&(t.static_len+=o*(d[2*i+1]+s)));if(0!==b){do{for(r=c-1;0===t.bl_count[r];)r--;t.bl_count[r]--,t.bl_count[r+1]+=2,t.bl_count[c]--,b-=2}while(b>0);for(r=c;0!==r;r--)for(i=t.bl_count[r];0!==i;)(n=t.heap[--a])>h||(l[2*n+1]!==r&&(t.opt_len+=(r-l[2*n+1])*l[2*n],l[2*n+1]=r),i--)}}function u(t,e,a){var i,n,r=new Array(K+1),s=0;for(i=1;i<=K;i++)r[i]=s=s+a[i-1]<<1;for(n=0;n<=e;n++){var o=t[2*n+1];0!==o&&(t[2*n]=d(r[o]++,o))}}function c(){var t,e,a,i,r,s=new Array(K+1);for(a=0,i=0;i<U-1;i++)for(it[i]=a,t=0;t<1<<W[i];t++)at[a++]=i;for(at[a-1]=i,r=0,i=0;i<16;i++)for(nt[i]=r,t=0;t<1<<J[i];t++)et[r++]=i;for(r>>=7;i<L;i++)for(nt[i]=r<<7,t=0;t<1<<J[i]-7;t++)et[256+r++]=i;for(e=0;e<=K;e++)s[e]=0;for(t=0;t<=143;)$[2*t+1]=8,t++,s[8]++;for(;t<=255;)$[2*t+1]=9,t++,s[9]++;for(;t<=279;)$[2*t+1]=7,t++,s[7]++;for(;t<=287;)$[2*t+1]=8,t++,s[8]++;for(u($,F+1,s),t=0;t<L;t++)tt[2*t+1]=5,tt[2*t]=d(t,5);rt=new n($,W,T+1,F,K),st=new n(tt,J,0,L,K),ot=new n(new Array(0),Q,0,H,P)}function b(t){var e;for(e=0;e<F;e++)t.dyn_ltree[2*e]=0;for(e=0;e<L;e++)t.dyn_dtree[2*e]=0;for(e=0;e<H;e++)t.bl_tree[2*e]=0;t.dyn_ltree[2*Y]=1,t.opt_len=t.static_len=0,t.last_lit=t.matches=0}function g(t){t.bi_valid>8?o(t,t.bi_buf):t.bi_valid>0&&(t.pending_buf[t.pending++]=t.bi_buf),t.bi_buf=0,t.bi_valid=0}function m(t,e,a,i){g(t),i&&(o(t,a),o(t,~a)),A.arraySet(t.pending_buf,t.window,e,a,t.pending),t.pending+=a}function w(t,e,a,i){var n=2*e,r=2*a;return t[n]<t[r]||t[n]===t[r]&&i[e]<=i[a]}function p(t,e,a){for(var i=t.heap[a],n=a<<1;n<=t.heap_len&&(n<t.heap_len&&w(e,t.heap[n+1],t.heap[n],t.depth)&&n++,!w(e,i,t.heap[n],t.depth));)t.heap[a]=t.heap[n],a=n,n<<=1;t.heap[a]=i}function v(t,e,a){var i,n,r,o,d=0;if(0!==t.last_lit)do{i=t.pending_buf[t.d_buf+2*d]<<8|t.pending_buf[t.d_buf+2*d+1],n=t.pending_buf[t.l_buf+d],d++,0===i?h(t,n,e):(h(t,(r=at[n])+T+1,e),0!==(o=W[r])&&l(t,n-=it[r],o),h(t,r=s(--i),a),0!==(o=J[r])&&l(t,i-=nt[r],o))}while(d<t.last_lit);h(t,Y,e)}function k(t,e){var a,i,n,r=e.dyn_tree,s=e.stat_desc.static_tree,o=e.stat_desc.has_stree,l=e.stat_desc.elems,h=-1;for(t.heap_len=0,t.heap_max=j,a=0;a<l;a++)0!==r[2*a]?(t.heap[++t.heap_len]=h=a,t.depth[a]=0):r[2*a+1]=0;for(;t.heap_len<2;)r[2*(n=t.heap[++t.heap_len]=h<2?++h:0)]=1,t.depth[n]=0,t.opt_len--,o&&(t.static_len-=s[2*n+1]);for(e.max_code=h,a=t.heap_len>>1;a>=1;a--)p(t,r,a);n=l;do{a=t.heap[1],t.heap[1]=t.heap[t.heap_len--],p(t,r,1),i=t.heap[1],t.heap[--t.heap_max]=a,t.heap[--t.heap_max]=i,r[2*n]=r[2*a]+r[2*i],t.depth[n]=(t.depth[a]>=t.depth[i]?t.depth[a]:t.depth[i])+1,r[2*a+1]=r[2*i+1]=n,t.heap[1]=n++,p(t,r,1)}while(t.heap_len>=2);t.heap[--t.heap_max]=t.heap[1],_(t,e),u(r,h,t.bl_count)}function y(t,e,a){var i,n,r=-1,s=e[1],o=0,l=7,h=4;for(0===s&&(l=138,h=3),e[2*(a+1)+1]=65535,i=0;i<=a;i++)n=s,s=e[2*(i+1)+1],++o<l&&n===s||(o<h?t.bl_tree[2*n]+=o:0!==n?(n!==r&&t.bl_tree[2*n]++,t.bl_tree[2*q]++):o<=10?t.bl_tree[2*G]++:t.bl_tree[2*X]++,o=0,r=n,0===s?(l=138,h=3):n===s?(l=6,h=3):(l=7,h=4))}function x(t,e,a){var i,n,r=-1,s=e[1],o=0,d=7,f=4;for(0===s&&(d=138,f=3),i=0;i<=a;i++)if(n=s,s=e[2*(i+1)+1],!(++o<d&&n===s)){if(o<f)do{h(t,n,t.bl_tree)}while(0!=--o);else 0!==n?(n!==r&&(h(t,n,t.bl_tree),o--),h(t,q,t.bl_tree),l(t,o-3,2)):o<=10?(h(t,G,t.bl_tree),l(t,o-3,3)):(h(t,X,t.bl_tree),l(t,o-11,7));o=0,r=n,0===s?(d=138,f=3):n===s?(d=6,f=3):(d=7,f=4)}}function z(t){var e;for(y(t,t.dyn_ltree,t.l_desc.max_code),y(t,t.dyn_dtree,t.d_desc.max_code),k(t,t.bl_desc),e=H-1;e>=3&&0===t.bl_tree[2*V[e]+1];e--);return t.opt_len+=3*(e+1)+5+5+4,e}function B(t,e,a,i){var n;for(l(t,e-257,5),l(t,a-1,5),l(t,i-4,4),n=0;n<i;n++)l(t,t.bl_tree[2*V[n]+1],3);x(t,t.dyn_ltree,e-1),x(t,t.dyn_dtree,a-1)}function S(t){var e,a=4093624447;for(e=0;e<=31;e++,a>>>=1)if(1&a&&0!==t.dyn_ltree[2*e])return R;if(0!==t.dyn_ltree[18]||0!==t.dyn_ltree[20]||0!==t.dyn_ltree[26])return C;for(e=32;e<T;e++)if(0!==t.dyn_ltree[2*e])return C;return R}function E(t,e,a,i){l(t,(O<<1)+(i?1:0),3),m(t,e,a,!0)}var A=t("../utils/common"),Z=4,R=0,C=1,N=2,O=0,D=1,I=2,U=29,T=256,F=T+1+U,L=30,H=19,j=2*F+1,K=15,M=16,P=7,Y=256,q=16,G=17,X=18,W=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],J=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],Q=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],V=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],$=new Array(2*(F+2));i($);var tt=new Array(2*L);i(tt);var et=new Array(512);i(et);var at=new Array(256);i(at);var it=new Array(U);i(it);var nt=new Array(L);i(nt);var rt,st,ot,lt=!1;a._tr_init=function(t){lt||(c(),lt=!0),t.l_desc=new r(t.dyn_ltree,rt),t.d_desc=new r(t.dyn_dtree,st),t.bl_desc=new r(t.bl_tree,ot),t.bi_buf=0,t.bi_valid=0,b(t)},a._tr_stored_block=E,a._tr_flush_block=function(t,e,a,i){var n,r,s=0;t.level>0?(t.strm.data_type===N&&(t.strm.data_type=S(t)),k(t,t.l_desc),k(t,t.d_desc),s=z(t),n=t.opt_len+3+7>>>3,(r=t.static_len+3+7>>>3)<=n&&(n=r)):n=r=a+5,a+4<=n&&-1!==e?E(t,e,a,i):t.strategy===Z||r===n?(l(t,(D<<1)+(i?1:0),3),v(t,$,tt)):(l(t,(I<<1)+(i?1:0),3),B(t,t.l_desc.max_code+1,t.d_desc.max_code+1,s+1),v(t,t.dyn_ltree,t.dyn_dtree)),b(t),i&&g(t)},a._tr_tally=function(t,e,a){return t.pending_buf[t.d_buf+2*t.last_lit]=e>>>8&255,t.pending_buf[t.d_buf+2*t.last_lit+1]=255&e,t.pending_buf[t.l_buf+t.last_lit]=255&a,t.last_lit++,0===e?t.dyn_ltree[2*a]++:(t.matches++,e--,t.dyn_ltree[2*(at[a]+T+1)]++,t.dyn_dtree[2*s(e)]++),t.last_lit===t.lit_bufsize-1},a._tr_align=function(t){l(t,D<<1,3),h(t,Y,$),f(t)}},{"../utils/common":3}],15:[function(t,e,a){"use strict";e.exports=function(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}},{}],"/":[function(t,e,a){"use strict";var i={};(0,t("./lib/utils/common").assign)(i,t("./lib/deflate"),t("./lib/inflate"),t("./lib/zlib/constants")),e.exports=i},{"./lib/deflate":1,"./lib/inflate":2,"./lib/utils/common":3,"./lib/zlib/constants":6}]},{},[])("/")});'use strict';tr.exportTo('tr.e.importer',function(){const GZIP_MEMBER_HEADER_ID_SIZE=3;const GZIP_HEADER_ID1=0x1f;const GZIP_HEADER_ID2=0x8b;const GZIP_DEFLATE_COMPRESSION=8;function _stringToUInt8Array(str){const array=new Uint8Array(str.length);for(let i=0;i<str.length;++i){array[i]=str.charCodeAt(i);}
+return array;}
+function GzipImporter(model,eventData){this.inflateAsTraceStream=false;if(typeof(eventData)==='string'||eventData instanceof String){eventData=_stringToUInt8Array(eventData);}else if(eventData instanceof ArrayBuffer){eventData=new Uint8Array(eventData);}else if(eventData instanceof tr.b.InMemoryTraceStream){eventData=eventData.data;this.inflateAsTraceStream_=true;}else{throw new Error('Unknown gzip data format');}
+this.model_=model;this.gzipData_=eventData;}
+GzipImporter.canImport=function(eventData){if(eventData instanceof tr.b.InMemoryTraceStream){eventData=eventData.header;}
+let header;if(eventData instanceof ArrayBuffer){header=new Uint8Array(eventData.slice(0,GZIP_MEMBER_HEADER_ID_SIZE));}else if(typeof(eventData)==='string'||eventData instanceof String){header=eventData.substring(0,GZIP_MEMBER_HEADER_ID_SIZE);header=_stringToUInt8Array(header);}else{return false;}
+return header[0]===GZIP_HEADER_ID1&&header[1]===GZIP_HEADER_ID2&&header[2]===GZIP_DEFLATE_COMPRESSION;};GzipImporter.inflateGzipData_=function(data){let position=0;function getByte(){if(position>=data.length){throw new Error('Unexpected end of gzip data');}
+return data[position++];}
+function getWord(){const low=getByte();const high=getByte();return(high<<8)+low;}
+function skipBytes(amount){position+=amount;}
+function skipZeroTerminatedString(){while(getByte()!==0){}}
+const id1=getByte();const id2=getByte();if(id1!==GZIP_HEADER_ID1||id2!==GZIP_HEADER_ID2){throw new Error('Not gzip data');}
+const compressionMethod=getByte();if(compressionMethod!==GZIP_DEFLATE_COMPRESSION){throw new Error('Unsupported compression method: '+compressionMethod);}
+const flags=getByte();const haveHeaderCrc=flags&(1<<1);const haveExtraFields=flags&(1<<2);const haveFileName=flags&(1<<3);const haveComment=flags&(1<<4);skipBytes(4+1+1);if(haveExtraFields){const bytesToSkip=getWord();skipBytes(bytesToSkip);}
+if(haveFileName)skipZeroTerminatedString();if(haveComment)skipZeroTerminatedString();if(haveHeaderCrc)getWord();const inflatedData=pako.inflateRaw(data.subarray(position));if(this.inflateAsTraceStream_){return GzipImporter.transformToStream(inflatedData);}
+let string;try{string=GzipImporter.transformToString(inflatedData);}catch(err){return GzipImporter.transformToStream(inflatedData);}
+if(inflatedData.length>0&&string.length===0){return GzipImporter.transformToStream(inflatedData);}
+return string;};GzipImporter.transformToStream=function(data){if(data instanceof Uint8Array){return new tr.b.InMemoryTraceStream(data,false);}
+throw new Error(`Cannot transform ${type} to TraceStream.`);};GzipImporter.transformToString=function(data){if(typeof(data)==='string')return data;if(typeof TextDecoder==='undefined'){if(data instanceof ArrayBuffer){data=new Uint8Array(data);}
+const result=[];let chunk=65536;let k=0;const len=data.length;while(k<len&&chunk>1){try{const chunklen=Math.min(k+chunk,len);let dataslice;if(data instanceof Array){dataslice=data.slice(k,chunklen);}else{dataslice=data.subarray(k,chunklen);}
+result.push(String.fromCharCode.apply(null,dataslice));k+=chunk;}catch(e){chunk=Math.floor(chunk/2);}}
+return result.join('');}
+if(data instanceof Array){data=new Uint8Array(data);}
+return new TextDecoder('utf-8').decode(data);};GzipImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'GzipImporter';},isTraceDataContainer(){return true;},extractSubtraces(){const eventData=GzipImporter.inflateGzipData_(this.gzipData_);return eventData?[eventData]:[];}};tr.importer.Importer.register(GzipImporter);return{GzipImporter,};});'use strict';tr.exportTo('tr.importer',function(){class SimpleLineReader{constructor(text){this.data_=text instanceof tr.b.TraceStream?text:text.split(new RegExp('\r?\n'));this.curLine_=0;this.readLastLine_=false;this.savedLines_=undefined;}*[Symbol.iterator](){let lastLine=undefined;while(this.hasData_){if(this.readLastLine_){this.curLine_++;this.readLastLine_=false;}else if(this.data_ instanceof tr.b.TraceStream){this.curLine_++;const line=this.data_.readUntilDelimiter('\n');if(line.endsWith('\r\n')){lastLine=line.slice(0,-2);}else if(line.endsWith('\n')){lastLine=line.slice(0,-1);}else{lastLine=line;}}else{this.curLine_++;lastLine=this.data_[this.curLine_-1];}
+yield lastLine;}}
+get curLineNumber(){return this.curLine_;}
+get hasData_(){if(this.data_ instanceof tr.b.TraceStream)return this.data_.hasData;return this.curLine_<this.data_.length;}
+advanceToLineMatching(regex){for(const line of this){if(this.savedLines_!==undefined)this.savedLines_.push(line);if(regex.test(line)){this.goBack_();return true;}}
+return false;}
+goBack_(){if(this.readLastLine_){throw new Error('There should be at least one nextLine call between '+'any two goBack calls.');}
+if(this.curLine_===0){throw new Error('There should be at least one nextLine call before '+'the first goBack call.');}
+this.readLastLine_=true;this.curLine_--;}
+beginSavingLines(){this.savedLines_=[];}
+endSavingLinesAndGetResult(){const tmp=this.savedLines_;this.savedLines_=undefined;return tmp;}}
+return{SimpleLineReader,};});'use strict';tr.exportTo('tr.e.importer',function(){function Trace2HTMLImporter(model,events){this.importPriority=0;}
+Trace2HTMLImporter.subtraces_=[];function _extractEventsFromHTML(text){Trace2HTMLImporter.subtraces_=[];const r=new tr.importer.SimpleLineReader(text);while(true){if(!r.advanceToLineMatching(new RegExp('^<\s*script id="viewer-data" '+'type="(application\/json|text\/plain)">\r?$'))){break;}
+r.beginSavingLines();if(!r.advanceToLineMatching(/^<\/\s*script>\r?$/))return;let rawEvents=r.endSavingLinesAndGetResult();rawEvents=rawEvents.slice(1,rawEvents.length-1);const data64=rawEvents.join('\n');const buffer=new ArrayBuffer(tr.b.Base64.getDecodedBufferLength(data64));const len=tr.b.Base64.DecodeToTypedArray(data64,new DataView(buffer));Trace2HTMLImporter.subtraces_.push(buffer.slice(0,len));}}
+function _canImportFromHTML(text){if(!/^<!DOCTYPE html>/.test(text))return false;_extractEventsFromHTML(text);if(Trace2HTMLImporter.subtraces_.length===0)return false;return true;}
+Trace2HTMLImporter.canImport=function(events){if(events instanceof tr.b.TraceStream)return false;return _canImportFromHTML(events);};Trace2HTMLImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'Trace2HTMLImporter';},isTraceDataContainer(){return true;},extractSubtraces(){return Trace2HTMLImporter.subtraces_;},importEvents(){}};tr.importer.Importer.register(Trace2HTMLImporter);return{Trace2HTMLImporter,};});'use strict';tr.exportTo('tr.e.importer.v8',function(){function SplayTree(){}
+SplayTree.prototype.root_=null;SplayTree.prototype.isEmpty=function(){return!this.root_;};SplayTree.prototype.insert=function(key,value){if(this.isEmpty()){this.root_=new SplayTree.Node(key,value);return;}
+this.splay_(key);if(this.root_.key===key){return;}
+const node=new SplayTree.Node(key,value);if(key>this.root_.key){node.left=this.root_;node.right=this.root_.right;this.root_.right=null;}else{node.right=this.root_;node.left=this.root_.left;this.root_.left=null;}
+this.root_=node;};SplayTree.prototype.remove=function(key){if(this.isEmpty()){throw Error('Key not found: '+key);}
+this.splay_(key);if(this.root_.key!==key){throw Error('Key not found: '+key);}
+const removed=this.root_;if(!this.root_.left){this.root_=this.root_.right;}else{const right=this.root_.right;this.root_=this.root_.left;this.splay_(key);this.root_.right=right;}
+return removed;};SplayTree.prototype.find=function(key){if(this.isEmpty())return null;this.splay_(key);return this.root_.key===key?this.root_:null;};SplayTree.prototype.findMin=function(){if(this.isEmpty())return null;let current=this.root_;while(current.left){current=current.left;}
+return current;};SplayTree.prototype.findMax=function(opt_startNode){if(this.isEmpty())return null;let current=opt_startNode||this.root_;while(current.right){current=current.right;}
+return current;};SplayTree.prototype.findGreatestLessThan=function(key){if(this.isEmpty())return null;this.splay_(key);if(this.root_.key<=key){return this.root_;}
+if(this.root_.left){return this.findMax(this.root_.left);}
+return null;};SplayTree.prototype.exportKeysAndValues=function(){const result=[];this.traverse_(function(node){result.push([node.key,node.value]);});return result;};SplayTree.prototype.exportValues=function(){const result=[];this.traverse_(function(node){result.push(node.value);});return result;};SplayTree.prototype.splay_=function(key){if(this.isEmpty())return;const dummy=new SplayTree.Node(null,null);let left=dummy;let right=dummy;let current=this.root_;while(true){if(key<current.key){if(!current.left){break;}
+if(key<current.left.key){const tmp=current.left;current.left=tmp.right;tmp.right=current;current=tmp;if(!current.left){break;}}
+right.left=current;right=current;current=current.left;}else if(key>current.key){if(!current.right){break;}
+if(key>current.right.key){const tmp=current.right;current.right=tmp.left;tmp.left=current;current=tmp;if(!current.right){break;}}
+left.right=current;left=current;current=current.right;}else{break;}}
+left.right=current.left;right.left=current.right;current.left=dummy.right;current.right=dummy.left;this.root_=current;};SplayTree.prototype.traverse_=function(f){const nodesToVisit=[this.root_];while(nodesToVisit.length>0){const node=nodesToVisit.shift();if(node===null)continue;f(node);nodesToVisit.push(node.left);nodesToVisit.push(node.right);}};SplayTree.Node=function(key,value){this.key=key;this.value=value;};SplayTree.Node.prototype.left=null;SplayTree.Node.prototype.right=null;return{SplayTree,};});'use strict';tr.exportTo('tr.e.importer.v8',function(){function CodeMap(){this.dynamics_=new tr.e.importer.v8.SplayTree();this.dynamicsNameGen_=new tr.e.importer.v8.CodeMap.NameGenerator();this.statics_=new tr.e.importer.v8.SplayTree();this.libraries_=new tr.e.importer.v8.SplayTree();this.pages_=[];}
+CodeMap.PAGE_ALIGNMENT=12;CodeMap.PAGE_SIZE=1<<CodeMap.PAGE_ALIGNMENT;CodeMap.prototype.addCode=function(start,codeEntry){this.deleteAllCoveredNodes_(this.dynamics_,start,start+codeEntry.size);this.dynamics_.insert(start,codeEntry);};CodeMap.prototype.moveCode=function(from,to){const removedNode=this.dynamics_.remove(from);this.deleteAllCoveredNodes_(this.dynamics_,to,to+removedNode.value.size);this.dynamics_.insert(to,removedNode.value);};CodeMap.prototype.deleteCode=function(start){const removedNode=this.dynamics_.remove(start);};CodeMap.prototype.addLibrary=function(start,codeEntry){this.markPages_(start,start+codeEntry.size);this.libraries_.insert(start,codeEntry);};CodeMap.prototype.addStaticCode=function(start,codeEntry){this.statics_.insert(start,codeEntry);};CodeMap.prototype.markPages_=function(start,end){for(let addr=start;addr<=end;addr+=CodeMap.PAGE_SIZE){this.pages_[addr>>>CodeMap.PAGE_ALIGNMENT]=1;}};CodeMap.prototype.deleteAllCoveredNodes_=function(tree,start,end){const toDelete=[];let addr=end-1;while(addr>=start){const node=tree.findGreatestLessThan(addr);if(!node)break;const start2=node.key;const end2=start2+node.value.size;if(start2<end&&start<end2)toDelete.push(start2);addr=start2-1;}
+for(let i=0,l=toDelete.length;i<l;++i)tree.remove(toDelete[i]);};CodeMap.prototype.isAddressBelongsTo_=function(addr,node){return addr>=node.key&&addr<(node.key+node.value.size);};CodeMap.prototype.findInTree_=function(tree,addr){const node=tree.findGreatestLessThan(addr);return node&&this.isAddressBelongsTo_(addr,node)?node.value:null;};CodeMap.prototype.findEntryInLibraries=function(addr){const pageAddr=addr>>>CodeMap.PAGE_ALIGNMENT;if(pageAddr in this.pages_){return this.findInTree_(this.libraries_,addr);}
+return undefined;};CodeMap.prototype.findEntry=function(addr){const pageAddr=addr>>>CodeMap.PAGE_ALIGNMENT;if(pageAddr in this.pages_){return this.findInTree_(this.statics_,addr)||this.findInTree_(this.libraries_,addr);}
+const min=this.dynamics_.findMin();const max=this.dynamics_.findMax();if(max!==null&&addr<(max.key+max.value.size)&&addr>=min.key){const dynaEntry=this.findInTree_(this.dynamics_,addr);if(dynaEntry===null)return null;if(!dynaEntry.nameUpdated_){dynaEntry.name=this.dynamicsNameGen_.getName(dynaEntry.name);dynaEntry.nameUpdated_=true;}
+return dynaEntry;}
+return null;};CodeMap.prototype.findDynamicEntryByStartAddress=function(addr){const node=this.dynamics_.find(addr);return node?node.value:null;};CodeMap.prototype.getAllDynamicEntries=function(){return this.dynamics_.exportValues();};CodeMap.prototype.getAllDynamicEntriesWithAddresses=function(){return this.dynamics_.exportKeysAndValues();};CodeMap.prototype.getAllStaticEntries=function(){return this.statics_.exportValues();};CodeMap.prototype.getAllLibrariesEntries=function(){return this.libraries_.exportValues();};CodeMap.CodeState={COMPILED:0,OPTIMIZABLE:1,OPTIMIZED:2};CodeMap.CodeEntry=function(size,opt_name,opt_type){this.id=tr.b.GUID.allocateSimple();this.size=size;this.name_=opt_name||'';this.type=opt_type||'';this.nameUpdated_=false;};CodeMap.CodeEntry.prototype={__proto__:Object.prototype,get name(){return this.name_;},set name(value){this.name_=value;},toString(){this.name_+': '+this.size.toString(16);}};CodeMap.CodeEntry.TYPE={SHARED_LIB:'SHARED_LIB',CPP:'CPP'};CodeMap.DynamicFuncCodeEntry=function(size,type,func,state){CodeMap.CodeEntry.call(this,size,'',type);this.func=func;this.state=state;};CodeMap.DynamicFuncCodeEntry.STATE_PREFIX=['','~','*'];CodeMap.DynamicFuncCodeEntry.prototype={__proto__:CodeMap.CodeEntry.prototype,get name(){return CodeMap.DynamicFuncCodeEntry.STATE_PREFIX[this.state]+
+this.func.name;},set name(value){this.name_=value;},getRawName(){return this.func.getName();},isJSFunction(){return true;},toString(){return this.type+': '+this.name+': '+this.size.toString(16);}};CodeMap.FunctionEntry=function(name){CodeMap.CodeEntry.call(this,0,name);};CodeMap.FunctionEntry.prototype={__proto__:CodeMap.CodeEntry.prototype,get name(){let name=this.name_;if(name.length===0){name='<anonymous>';}else if(name.charAt(0)===' '){name='<anonymous>'+name;}
+return name;},set name(value){this.name_=value;}};CodeMap.NameGenerator=function(){this.knownNames_={};};CodeMap.NameGenerator.prototype.getName=function(name){if(!(name in this.knownNames_)){this.knownNames_[name]=0;return name;}
+const count=++this.knownNames_[name];return name+' {'+count+'}';};return{CodeMap,};});'use strict';tr.exportTo('tr.e.importer.v8',function(){function CsvParser(){}
+CsvParser.CSV_FIELD_RE_=/^"((?:[^"]|"")*)"|([^,]*)/;CsvParser.DOUBLE_QUOTE_RE_=/""/g;CsvParser.prototype.parseLine=function(line){const fieldRe=CsvParser.CSV_FIELD_RE_;const doubleQuoteRe=CsvParser.DOUBLE_QUOTE_RE_;let pos=0;const endPos=line.length;const fields=[];if(endPos>0){do{const fieldMatch=fieldRe.exec(line.substr(pos));if(typeof fieldMatch[1]==='string'){const field=fieldMatch[1];pos+=field.length+3;fields.push(field.replace(doubleQuoteRe,'"'));}else{const field=fieldMatch[2];pos+=field.length+1;fields.push(field);}}while(pos<=endPos);}
+return fields;};function LogReader(dispatchTable){this.dispatchTable_=dispatchTable;this.lineNum_=0;this.csvParser_=new CsvParser();}
+LogReader.prototype.printError=function(str){};LogReader.prototype.processLogChunk=function(chunk){this.processLog_(chunk.split('\n'));};LogReader.prototype.processLogLine=function(line){this.processLog_([line]);};LogReader.prototype.processStack=function(pc,func,stack){const fullStack=func?[pc,func]:[pc];let prevFrame=pc;for(let i=0,n=stack.length;i<n;++i){const frame=stack[i];const firstChar=frame.charAt(0);if(firstChar==='+'||firstChar==='-'){prevFrame+=parseInt(frame,16);fullStack.push(prevFrame);}else if(firstChar!=='o'){fullStack.push(parseInt(frame,16));}}
+return fullStack;};LogReader.prototype.skipDispatch=function(dispatch){return false;};LogReader.prototype.dispatchLogRow_=function(fields){const command=fields[0];if(!(command in this.dispatchTable_))return;const dispatch=this.dispatchTable_[command];if(dispatch===null||this.skipDispatch(dispatch)){return;}
+const parsedFields=[];for(let i=0;i<dispatch.parsers.length;++i){const parser=dispatch.parsers[i];if(parser===null){parsedFields.push(fields[1+i]);}else if(typeof parser==='function'){parsedFields.push(parser(fields[1+i]));}else{parsedFields.push(fields.slice(1+i));break;}}
+dispatch.processor.apply(this,parsedFields);};LogReader.prototype.processLog_=function(lines){for(let i=0,n=lines.length;i<n;++i,++this.lineNum_){const line=lines[i];if(!line){continue;}
+try{const fields=this.csvParser_.parseLine(line);this.dispatchLogRow_(fields);}catch(e){this.printError('line '+(this.lineNum_+1)+': '+
+(e.message||e));}}};return{LogReader,};});'use strict';tr.exportTo('tr.model',function(){function ProfileNode(id,title,parentNode){this.id_=id;this.title_=title;this.parentNode_=parentNode;this.colorId_=-1;this.userFriendlyStack_=[];}
+ProfileNode.prototype={__proto__:Object.prototype,get title(){return this.title_;},get parentNode(){return this.parentNode_;},set parentNode(value){this.parentNode_=value;},get id(){return this.id_;},get colorId(){return this.colorId_;},set colorId(value){this.colorId_=value;},get userFriendlyName(){return this.title_;},get userFriendlyStack(){if(this.userFriendlyStack_.length===0){this.userFriendlyStack_=[this.userFriendlyName];if(this.parentNode_!==undefined){this.userFriendlyStack_=this.userFriendlyStack_.concat(this.parentNode_.userFriendlyStack);}}
+return this.userFriendlyStack_;},get sampleTitle(){throw new Error('Not implemented.');}};tr.model.EventRegistry.register(ProfileNode,{name:'Node',pluralName:'Nodes'});return{ProfileNode,};});'use strict';tr.exportTo('tr.e.v8',function(){const ProfileNode=tr.model.ProfileNode;function V8CpuProfileNode(id,callFrame,parentNode){ProfileNode.call(this,id,callFrame.functionName,parentNode);this.callFrame_=tr.b.deepCopy(callFrame);this.deoptReason_='';this.colorId_=tr.b.ColorScheme.getColorIdForGeneralPurposeString(callFrame.functionName);}
+V8CpuProfileNode.prototype={__proto__:ProfileNode.prototype,get functionName(){return this.callFrame_.functionName;},get scriptId(){return this.callFrame_.scriptId;},get url(){if(!this.callFrame_.url){return'unknown';}
+let url=this.callFrame_.url;if(this.callFrame_.lineNumber===undefined){return url;}
+url=url+':'+this.callFrame_.lineNumber;if(this.callFrame_.columnNumber===undefined){return url;}
+url=url+':'+this.callFrame_.columnNumber;return url;},get deoptReason(){return this.deoptReason_;},set deoptReason(value){this.deoptReason_=value;},get userFriendlyName(){const name=this.functionName+' url: '+this.url;return!this.deoptReason_?name:name+' Deoptimized reason: '+this.deoptReason_;},get sampleTitle(){return'V8 Sample';}};V8CpuProfileNode.constructFromObject=function(profileTree,node){const nodeId=node.id;if(nodeId===1){return undefined;}
+const parentNode=profileTree.getNode(node.parent);const profileNode=new V8CpuProfileNode(nodeId,node.callFrame,parentNode);if(node.deoptReason!==undefined){profileNode.deoptReason=node.deoptReason;}
+return profileNode;};ProfileNode.subTypes.register(V8CpuProfileNode,{typeName:'cpuProfile',name:'v8 cpu profile node',pluralName:'v8 cpu profile nodes'});ProfileNode.subTypes.register(V8CpuProfileNode,{typeName:'legacySample',name:'v8 cpu profile node',pluralName:'v8 cpu profile nodes'});return{ProfileNode,};});'use strict';tr.exportTo('tr.model',function(){function ProfileTree(){this.startTime_=undefined;this.endTime_=undefined;this.tree_=new Map();this.pid_=-1;this.tid_=-1;}
+ProfileTree.prototype={__proto__:Object.prototype,get pid(){return this.pid_;},set pid(value){this.pid_=value;},get tid(){return this.tid_;},set tid(value){this.tid_=value;},get tree(){return this.tree_;},get startTime(){return this.startTime_;},set startTime(value){this.startTime_=value;this.endTime_=value;},get endTime(){return this.endTime_;},set endTime(value){this.endTime_=value;},add(node){if(this.tree_.has(node.id)){throw new Error('Conflict id in the profile tree.');}
+this.tree_.set(node.id,node);return node;},getNode(nodeId){return this.tree_.get(nodeId);}};return{ProfileTree,};});'use strict';tr.exportTo('tr.e.importer.v8',function(){const CodeEntry=tr.e.importer.v8.CodeMap.CodeEntry;const CodeMap=tr.e.importer.v8.CodeMap;const ColorScheme=tr.b.ColorScheme;const DynamicFuncCodeEntry=tr.e.importer.v8.CodeMap.DynamicFuncCodeEntry;const FunctionEntry=tr.e.importer.v8.CodeMap.FunctionEntry;const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,'legacySample');function V8LogImporter(model,eventData){this.importPriority=3;this.model_=model;this.logData_=eventData;this.code_map_=new CodeMap();this.v8_timer_thread_=undefined;this.v8_thread_=undefined;this.profileTree_=new tr.model.ProfileTree();this.profileTree_.add(new ProfileNodeType(-1,{url:'',functionName:'unknown'}));this.v8_stack_timeline_=[];}
+const kV8BinarySuffixes=['/d8','/libv8.so'];const TimerEventDefaultArgs={'V8.Execute':{pause:false,no_execution:false},'V8.External':{pause:false,no_execution:true},'V8.CompileFullCode':{pause:true,no_execution:true},'V8.RecompileSynchronous':{pause:true,no_execution:true},'V8.RecompileParallel':{pause:false,no_execution:false},'V8.CompileEval':{pause:true,no_execution:true},'V8.Parse':{pause:true,no_execution:true},'V8.PreParse':{pause:true,no_execution:true},'V8.ParseLazy':{pause:true,no_execution:true},'V8.GCScavenger':{pause:true,no_execution:true},'V8.GCCompactor':{pause:true,no_execution:true},'V8.GCContext':{pause:true,no_execution:true}};V8LogImporter.canImport=function(eventData){if(typeof(eventData)!=='string'&&!(eventData instanceof String)){return false;}
+return eventData.substring(0,11)==='v8-version,'||eventData.substring(0,12)==='timer-event,'||eventData.substring(0,5)==='tick,'||eventData.substring(0,15)==='shared-library,'||eventData.substring(0,9)==='profiler,'||eventData.substring(0,14)==='code-creation,';};V8LogImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'V8LogImporter';},processTimerEvent_(name,startInUs,lengthInUs){const args=TimerEventDefaultArgs[name];if(args===undefined)return;const startInMs=tr.b.convertUnit(startInUs,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);const lengthInMs=tr.b.convertUnit(lengthInUs,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);const colorId=ColorScheme.getColorIdForGeneralPurposeString(name);const slice=new tr.model.ThreadSlice('v8',name,colorId,startInMs,args,lengthInMs);this.v8_timer_thread_.sliceGroup.pushSlice(slice);},processTimerEventStart_(name,startInUs){const args=TimerEventDefaultArgs[name];if(args===undefined)return;const startInMs=tr.b.convertUnit(startInUs,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);this.v8_timer_thread_.sliceGroup.beginSlice('v8',name,startInMs,args);},processTimerEventEnd_(name,endInUs){const endInMs=tr.b.convertUnit(endInUs,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);this.v8_timer_thread_.sliceGroup.endSlice(endInMs);},processCodeCreateEvent_(type,kind,address,size,name,maybeFunc){function parseState(s){switch(s){case'':return CodeMap.CodeState.COMPILED;case'~':return CodeMap.CodeState.OPTIMIZABLE;case'*':return CodeMap.CodeState.OPTIMIZED;}
+throw new Error('unknown code state: '+s);}
+if(maybeFunc.length){const funcAddr=parseInt(maybeFunc[0]);const state=parseState(maybeFunc[1]);let func=this.code_map_.findDynamicEntryByStartAddress(funcAddr);if(!func){func=new FunctionEntry(name);func.kind=kind;this.code_map_.addCode(funcAddr,func);}else if(func.name!==name){func.name=name;}
+let entry=this.code_map_.findDynamicEntryByStartAddress(address);if(entry){if(entry.size===size&&entry.func===func){entry.state=state;}}else{entry=new DynamicFuncCodeEntry(size,type,func,state);entry.kind=kind;this.code_map_.addCode(address,entry);}}else{const codeEntry=new CodeEntry(size,name);codeEntry.kind=kind;this.code_map_.addCode(address,codeEntry);}},processCodeMoveEvent_(from,to){this.code_map_.moveCode(from,to);},processCodeDeleteEvent_(address){this.code_map_.deleteCode(address);},processSharedLibrary_(name,start,end){const codeEntry=new CodeEntry(end-start,name,CodeEntry.TYPE.SHARED_LIB);codeEntry.kind=-3;for(let i=0;i<kV8BinarySuffixes.length;i++){const suffix=kV8BinarySuffixes[i];if(name.indexOf(suffix,name.length-suffix.length)>=0){codeEntry.kind=-1;break;}}
+this.code_map_.addLibrary(start,codeEntry);},processCppSymbol_(address,size,name){const codeEntry=new CodeEntry(size,name,CodeEntry.TYPE.CPP);codeEntry.kind=-1;this.code_map_.addStaticCode(address,codeEntry);},processTickEvent_(pc,startInUs,isExternalCallback,tosOrExternalCallback,vmstate,stack){const startInMs=tr.b.convertUnit(startInUs,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);function findChildWithEntryID(stackFrame,entryID){for(let i=0;i<stackFrame.children.length;i++){if(stackFrame.children[i].entryID===entryID){return stackFrame.children[i];}}
+return undefined;}
+function processStack(pc,func,stack){const fullStack=func?[pc,func]:[pc];let prevFrame=pc;for(let i=0,n=stack.length;i<n;++i){const frame=stack[i];const firstChar=frame.charAt(0);if(firstChar==='+'||firstChar==='-'){prevFrame+=parseInt(frame,16);fullStack.push(prevFrame);}else if(firstChar!=='o'){fullStack.push(parseInt(frame,16));}}
+return fullStack;}
+if(isExternalCallback){pc=tosOrExternalCallback;tosOrExternalCallback=0;}else if(tosOrExternalCallback){const funcEntry=this.code_map_.findEntry(tosOrExternalCallback);if(!funcEntry||!funcEntry.isJSFunction||!funcEntry.isJSFunction()){tosOrExternalCallback=0;}}
+let processedStack=processStack(pc,tosOrExternalCallback,stack);let node=undefined;let lastNode=undefined;processedStack=processedStack.reverse();for(let i=0,n=processedStack.length;i<n;i++){const frame=processedStack[i];if(!frame)break;const entry=this.code_map_.findEntry(frame);if(!entry&&i!==0){continue;}
+let sourceInfo=undefined;if(entry&&entry.type===CodeEntry.TYPE.CPP){const libEntry=this.code_map_.findEntryInLibraries(frame);if(libEntry){sourceInfo={file:libEntry.name};}}
+const entryId=entry?entry.id:-1;node=this.profileTree_.getNode(entryId);if(node===undefined){node=this.profileTree_.add(new ProfileNodeType(entryId,{functionName:entry.name,url:sourceInfo?sourceInfo.file:'',lineNumber:sourceInfo?sourceInfo.line:undefined,columnNumber:sourceInfo?sourceInfo.column:undefined,scriptId:sourceInfo?sourceInfo.scriptId:undefined},lastNode));}
+lastNode=node;}
+this.model_.samples.push(new tr.model.Sample(startInMs,'V8 PC',node,this.v8_thread_,undefined,1));},processDistortion_(distortionInPicoseconds){},processPlotRange_(start,end){},processV8Version_(major,minor,build,patch,candidate){},importEvents(){const logreader=new tr.e.importer.v8.LogReader({'timer-event':{parsers:[null,parseInt,parseInt],processor:this.processTimerEvent_.bind(this)},'shared-library':{parsers:[null,parseInt,parseInt],processor:this.processSharedLibrary_.bind(this)},'timer-event-start':{parsers:[null,parseInt],processor:this.processTimerEventStart_.bind(this)},'timer-event-end':{parsers:[null,parseInt],processor:this.processTimerEventEnd_.bind(this)},'code-creation':{parsers:[null,parseInt,parseInt,parseInt,null,'var-args'],processor:this.processCodeCreateEvent_.bind(this)},'code-move':{parsers:[parseInt,parseInt],processor:this.processCodeMoveEvent_.bind(this)},'code-delete':{parsers:[parseInt],processor:this.processCodeDeleteEvent_.bind(this)},'cpp':{parsers:[parseInt,parseInt,null],processor:this.processCppSymbol_.bind(this)},'tick':{parsers:[parseInt,parseInt,parseInt,parseInt,parseInt,'var-args'],processor:this.processTickEvent_.bind(this)},'distortion':{parsers:[parseInt],processor:this.processDistortion_.bind(this)},'plot-range':{parsers:[parseInt,parseInt],processor:this.processPlotRange_.bind(this)},'v8-version':{parsers:[parseInt,parseInt,parseInt,parseInt,parseInt],processor:this.processV8Version_.bind(this)}});this.v8_timer_thread_=this.model_.getOrCreateProcess(-32).getOrCreateThread(1);this.v8_timer_thread_.name='V8 Timers';this.v8_thread_=this.model_.getOrCreateProcess(-32).getOrCreateThread(2);this.v8_thread_.name='V8';const lines=this.logData_.split('\n');for(let i=0;i<lines.length;i++){logreader.processLogLine(lines[i]);}
+function addSlices(slices,thread){for(let i=0;i<slices.length;i++){const duration=slices[i].end-slices[i].start;const slice=new tr.model.ThreadSlice('v8',slices[i].name,ColorScheme.getColorIdForGeneralPurposeString(slices[i].name),slices[i].start,{},duration);thread.sliceGroup.pushSlice(slice);addSlices(slices[i].children,thread);}}
+addSlices(this.v8_stack_timeline_,this.v8_thread_);}};tr.importer.Importer.register(V8LogImporter);return{V8LogImporter,};});'use strict';if(tr.isVinn){global.window={};}
+!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;"undefined"!=typeof window?b=window:"undefined"!=typeof global?b=global:"undefined"!=typeof self&&(b=self),b.JSZip=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);throw new Error("Cannot find module '"+g+"'")}var j=c[g]={exports:{}};b[g][0].call(j.exports,function(a){var c=b[g][1][a];return e(c?c:a)},j,j.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b,c){"use strict";var d="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";c.encode=function(a){for(var b,c,e,f,g,h,i,j="",k=0;k<a.length;)b=a.charCodeAt(k++),c=a.charCodeAt(k++),e=a.charCodeAt(k++),f=b>>2,g=(3&b)<<4|c>>4,h=(15&c)<<2|e>>6,i=63&e,isNaN(c)?h=i=64:isNaN(e)&&(i=64),j=j+d.charAt(f)+d.charAt(g)+d.charAt(h)+d.charAt(i);return j},c.decode=function(a){var b,c,e,f,g,h,i,j="",k=0;for(a=a.replace(/[^A-Za-z0-9\+\/\=]/g,"");k<a.length;)f=d.indexOf(a.charAt(k++)),g=d.indexOf(a.charAt(k++)),h=d.indexOf(a.charAt(k++)),i=d.indexOf(a.charAt(k++)),b=f<<2|g>>4,c=(15&g)<<4|h>>2,e=(3&h)<<6|i,j+=String.fromCharCode(b),64!=h&&(j+=String.fromCharCode(c)),64!=i&&(j+=String.fromCharCode(e));return j}},{}],2:[function(a,b){"use strict";function c(){this.compressedSize=0,this.uncompressedSize=0,this.crc32=0,this.compressionMethod=null,this.compressedContent=null}c.prototype={getContent:function(){return null},getCompressedContent:function(){return null}},b.exports=c},{}],3:[function(a,b,c){"use strict";c.STORE={magic:"\x00\x00",compress:function(a){return a},uncompress:function(a){return a},compressInputType:null,uncompressInputType:null},c.DEFLATE=a("./flate")},{"./flate":8}],4:[function(a,b){"use strict";var c=a("./utils"),d=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,936918e3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117];b.exports=function(a,b){if("undefined"==typeof a||!a.length)return 0;var e="string"!==c.getTypeOf(a);"undefined"==typeof b&&(b=0);var f=0,g=0,h=0;b=-1^b;for(var i=0,j=a.length;j>i;i++)h=e?a[i]:a.charCodeAt(i),g=255&(b^h),f=d[g],b=b>>>8^f;return-1^b}},{"./utils":21}],5:[function(a,b){"use strict";function c(){this.data=null,this.length=0,this.index=0}var d=a("./utils");c.prototype={checkOffset:function(a){this.checkIndex(this.index+a)},checkIndex:function(a){if(this.length<a||0>a)throw new Error("End of data reached (data length = "+this.length+", asked index = "+a+"). Corrupted zip ?")},setIndex:function(a){this.checkIndex(a),this.index=a},skip:function(a){this.setIndex(this.index+a)},byteAt:function(){},readInt:function(a){var b,c=0;for(this.checkOffset(a),b=this.index+a-1;b>=this.index;b--)c=(c<<8)+this.byteAt(b);return this.index+=a,c},readString:function(a){return d.transformTo("string",this.readData(a))},readData:function(){},lastIndexOfSignature:function(){},readDate:function(){var a=this.readInt(4);return new Date((a>>25&127)+1980,(a>>21&15)-1,a>>16&31,a>>11&31,a>>5&63,(31&a)<<1)}},b.exports=c},{"./utils":21}],6:[function(a,b,c){"use strict";c.base64=!1,c.binary=!1,c.dir=!1,c.createFolders=!1,c.date=null,c.compression=null,c.comment=null},{}],7:[function(a,b,c){"use strict";var d=a("./utils");c.string2binary=function(a){return d.string2binary(a)},c.string2Uint8Array=function(a){return d.transformTo("uint8array",a)},c.uint8Array2String=function(a){return d.transformTo("string",a)},c.string2Blob=function(a){var b=d.transformTo("arraybuffer",a);return d.arrayBuffer2Blob(b)},c.arrayBuffer2Blob=function(a){return d.arrayBuffer2Blob(a)},c.transformTo=function(a,b){return d.transformTo(a,b)},c.getTypeOf=function(a){return d.getTypeOf(a)},c.checkSupport=function(a){return d.checkSupport(a)},c.MAX_VALUE_16BITS=d.MAX_VALUE_16BITS,c.MAX_VALUE_32BITS=d.MAX_VALUE_32BITS,c.pretty=function(a){return d.pretty(a)},c.findCompression=function(a){return d.findCompression(a)},c.isRegExp=function(a){return d.isRegExp(a)}},{"./utils":21}],8:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,e=a("pako");c.uncompressInputType=d?"uint8array":"array",c.compressInputType=d?"uint8array":"array",c.magic="\b\x00",c.compress=function(a){return e.deflateRaw(a)},c.uncompress=function(a){return e.inflateRaw(a)}},{pako:24}],9:[function(a,b){"use strict";function c(a,b){return this instanceof c?(this.files={},this.comment=null,this.root="",a&&this.load(a,b),void(this.clone=function(){var a=new c;for(var b in this)"function"!=typeof this[b]&&(a[b]=this[b]);return a})):new c(a,b)}var d=a("./base64");c.prototype=a("./object"),c.prototype.load=a("./load"),c.support=a("./support"),c.defaults=a("./defaults"),c.utils=a("./deprecatedPublicUtils"),c.base64={encode:function(a){return d.encode(a)},decode:function(a){return d.decode(a)}},c.compressions=a("./compressions"),b.exports=c},{"./base64":1,"./compressions":3,"./defaults":6,"./deprecatedPublicUtils":7,"./load":10,"./object":13,"./support":17}],10:[function(a,b){"use strict";var c=a("./base64"),d=a("./zipEntries");b.exports=function(a,b){var e,f,g,h;for(b=b||{},b.base64&&(a=c.decode(a)),f=new d(a,b),e=f.files,g=0;g<e.length;g++)h=e[g],this.file(h.fileName,h.decompressed,{binary:!0,optimizedBinaryString:!0,date:h.date,dir:h.dir,comment:h.fileComment.length?h.fileComment:null,createFolders:b.createFolders});return f.zipComment.length&&(this.comment=f.zipComment),this}},{"./base64":1,"./zipEntries":22}],11:[function(a,b){(function(a){"use strict";b.exports=function(b,c){return new a(b,c)},b.exports.test=function(b){return a.isBuffer(b)}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],12:[function(a,b){"use strict";function c(a){this.data=a,this.length=this.data.length,this.index=0}var d=a("./uint8ArrayReader");c.prototype=new d,c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./uint8ArrayReader":18}],13:[function(a,b){"use strict";var c=a("./support"),d=a("./utils"),e=a("./crc32"),f=a("./signature"),g=a("./defaults"),h=a("./base64"),i=a("./compressions"),j=a("./compressedObject"),k=a("./nodeBuffer"),l=a("./utf8"),m=a("./stringWriter"),n=a("./uint8ArrayWriter"),o=function(a){if(a._data instanceof j&&(a._data=a._data.getContent(),a.options.binary=!0,a.options.base64=!1,"uint8array"===d.getTypeOf(a._data))){var b=a._data;a._data=new Uint8Array(b.length),0!==b.length&&a._data.set(b,0)}return a._data},p=function(a){var b=o(a),e=d.getTypeOf(b);return"string"===e?!a.options.binary&&c.nodebuffer?k(b,"utf-8"):a.asBinary():b},q=function(a){var b=o(this);return null===b||"undefined"==typeof b?"":(this.options.base64&&(b=h.decode(b)),b=a&&this.options.binary?A.utf8decode(b):d.transformTo("string",b),a||this.options.binary||(b=d.transformTo("string",A.utf8encode(b))),b)},r=function(a,b,c){this.name=a,this.dir=c.dir,this.date=c.date,this.comment=c.comment,this._data=b,this.options=c,this._initialMetadata={dir:c.dir,date:c.date}};r.prototype={asText:function(){return q.call(this,!0)},asBinary:function(){return q.call(this,!1)},asNodeBuffer:function(){var a=p(this);return d.transformTo("nodebuffer",a)},asUint8Array:function(){var a=p(this);return d.transformTo("uint8array",a)},asArrayBuffer:function(){return this.asUint8Array().buffer}};var s=function(a,b){var c,d="";for(c=0;b>c;c++)d+=String.fromCharCode(255&a),a>>>=8;return d},t=function(){var a,b,c={};for(a=0;a<arguments.length;a++)for(b in arguments[a])arguments[a].hasOwnProperty(b)&&"undefined"==typeof c[b]&&(c[b]=arguments[a][b]);return c},u=function(a){return a=a||{},a.base64!==!0||null!==a.binary&&void 0!==a.binary||(a.binary=!0),a=t(a,g),a.date=a.date||new Date,null!==a.compression&&(a.compression=a.compression.toUpperCase()),a},v=function(a,b,c){var e,f=d.getTypeOf(b);if(c=u(c),c.createFolders&&(e=w(a))&&x.call(this,e,!0),c.dir||null===b||"undefined"==typeof b)c.base64=!1,c.binary=!1,b=null;else if("string"===f)c.binary&&!c.base64&&c.optimizedBinaryString!==!0&&(b=d.string2binary(b));else{if(c.base64=!1,c.binary=!0,!(f||b instanceof j))throw new Error("The data of '"+a+"' is in an unsupported format !");"arraybuffer"===f&&(b=d.transformTo("uint8array",b))}var g=new r(a,b,c);return this.files[a]=g,g},w=function(a){"/"==a.slice(-1)&&(a=a.substring(0,a.length-1));var b=a.lastIndexOf("/");return b>0?a.substring(0,b):""},x=function(a,b){return"/"!=a.slice(-1)&&(a+="/"),b="undefined"!=typeof b?b:!1,this.files[a]||v.call(this,a,null,{dir:!0,createFolders:b}),this.files[a]},y=function(a,b){var c,f=new j;return a._data instanceof j?(f.uncompressedSize=a._data.uncompressedSize,f.crc32=a._data.crc32,0===f.uncompressedSize||a.dir?(b=i.STORE,f.compressedContent="",f.crc32=0):a._data.compressionMethod===b.magic?f.compressedContent=a._data.getCompressedContent():(c=a._data.getContent(),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c)))):(c=p(a),(!c||0===c.length||a.dir)&&(b=i.STORE,c=""),f.uncompressedSize=c.length,f.crc32=e(c),f.compressedContent=b.compress(d.transformTo(b.compressInputType,c))),f.compressedSize=f.compressedContent.length,f.compressionMethod=b.magic,f},z=function(a,b,c,g){var h,i,j,k,m=(c.compressedContent,d.transformTo("string",l.utf8encode(b.name))),n=b.comment||"",o=d.transformTo("string",l.utf8encode(n)),p=m.length!==b.name.length,q=o.length!==n.length,r=b.options,t="",u="",v="";j=b._initialMetadata.dir!==b.dir?b.dir:r.dir,k=b._initialMetadata.date!==b.date?b.date:r.date,h=k.getHours(),h<<=6,h|=k.getMinutes(),h<<=5,h|=k.getSeconds()/2,i=k.getFullYear()-1980,i<<=4,i|=k.getMonth()+1,i<<=5,i|=k.getDate(),p&&(u=s(1,1)+s(e(m),4)+m,t+="up"+s(u.length,2)+u),q&&(v=s(1,1)+s(this.crc32(o),4)+o,t+="uc"+s(v.length,2)+v);var w="";w+="\n\x00",w+=p||q?"\x00\b":"\x00\x00",w+=c.compressionMethod,w+=s(h,2),w+=s(i,2),w+=s(c.crc32,4),w+=s(c.compressedSize,4),w+=s(c.uncompressedSize,4),w+=s(m.length,2),w+=s(t.length,2);var x=f.LOCAL_FILE_HEADER+w+m+t,y=f.CENTRAL_FILE_HEADER+"\x00"+w+s(o.length,2)+"\x00\x00\x00\x00"+(j===!0?"\x00\x00\x00":"\x00\x00\x00\x00")+s(g,4)+m+t+o;return{fileRecord:x,dirRecord:y,compressedObject:c}},A={load:function(){throw new Error("Load method is not defined. Is the file jszip-load.js included ?")},filter:function(a){var b,c,d,e,f=[];for(b in this.files)this.files.hasOwnProperty(b)&&(d=this.files[b],e=new r(d.name,d._data,t(d.options)),c=b.slice(this.root.length,b.length),b.slice(0,this.root.length)===this.root&&a(c,e)&&f.push(e));return f},file:function(a,b,c){if(1===arguments.length){if(d.isRegExp(a)){var e=a;return this.filter(function(a,b){return!b.dir&&e.test(a)})}return this.filter(function(b,c){return!c.dir&&b===a})[0]||null}return a=this.root+a,v.call(this,a,b,c),this},folder:function(a){if(!a)return this;if(d.isRegExp(a))return this.filter(function(b,c){return c.dir&&a.test(b)});var b=this.root+a,c=x.call(this,b),e=this.clone();return e.root=c.name,e},remove:function(a){a=this.root+a;var b=this.files[a];if(b||("/"!=a.slice(-1)&&(a+="/"),b=this.files[a]),b&&!b.dir)delete this.files[a];else for(var c=this.filter(function(b,c){return c.name.slice(0,a.length)===a}),d=0;d<c.length;d++)delete this.files[c[d].name];return this},generate:function(a){a=t(a||{},{base64:!0,compression:"STORE",type:"base64",comment:null}),d.checkSupport(a.type);var b,c,e=[],g=0,j=0,k=d.transformTo("string",this.utf8encode(a.comment||this.comment||""));for(var l in this.files)if(this.files.hasOwnProperty(l)){var o=this.files[l],p=o.options.compression||a.compression.toUpperCase(),q=i[p];if(!q)throw new Error(p+" is not a valid compression method !");var r=y.call(this,o,q),u=z.call(this,l,o,r,g);g+=u.fileRecord.length+r.compressedSize,j+=u.dirRecord.length,e.push(u)}var v="";v=f.CENTRAL_DIRECTORY_END+"\x00\x00\x00\x00"+s(e.length,2)+s(e.length,2)+s(j,4)+s(g,4)+s(k.length,2)+k;var w=a.type.toLowerCase();for(b="uint8array"===w||"arraybuffer"===w||"blob"===w||"nodebuffer"===w?new n(g+j+v.length):new m(g+j+v.length),c=0;c<e.length;c++)b.append(e[c].fileRecord),b.append(e[c].compressedObject.compressedContent);for(c=0;c<e.length;c++)b.append(e[c].dirRecord);b.append(v);var x=b.finalize();switch(a.type.toLowerCase()){case"uint8array":case"arraybuffer":case"nodebuffer":return d.transformTo(a.type.toLowerCase(),x);case"blob":return d.arrayBuffer2Blob(d.transformTo("arraybuffer",x));case"base64":return a.base64?h.encode(x):x;default:return x}},crc32:function(a,b){return e(a,b)},utf8encode:function(a){return d.transformTo("string",l.utf8encode(a))},utf8decode:function(a){return l.utf8decode(a)}};b.exports=A},{"./base64":1,"./compressedObject":2,"./compressions":3,"./crc32":4,"./defaults":6,"./nodeBuffer":11,"./signature":14,"./stringWriter":16,"./support":17,"./uint8ArrayWriter":19,"./utf8":20,"./utils":21}],14:[function(a,b,c){"use strict";c.LOCAL_FILE_HEADER="PK",c.CENTRAL_FILE_HEADER="PK",c.CENTRAL_DIRECTORY_END="PK",c.ZIP64_CENTRAL_DIRECTORY_LOCATOR="PK",c.ZIP64_CENTRAL_DIRECTORY_END="PK",c.DATA_DESCRIPTOR="PK\b"},{}],15:[function(a,b){"use strict";function c(a,b){this.data=a,b||(this.data=e.string2binary(this.data)),this.length=this.data.length,this.index=0}var d=a("./dataReader"),e=a("./utils");c.prototype=new d,c.prototype.byteAt=function(a){return this.data.charCodeAt(a)},c.prototype.lastIndexOfSignature=function(a){return this.data.lastIndexOf(a)},c.prototype.readData=function(a){this.checkOffset(a);var b=this.data.slice(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5,"./utils":21}],16:[function(a,b){"use strict";var c=a("./utils"),d=function(){this.data=[]};d.prototype={append:function(a){a=c.transformTo("string",a),this.data.push(a)},finalize:function(){return this.data.join("")}},b.exports=d},{"./utils":21}],17:[function(a,b,c){(function(a){"use strict";if(c.base64=!0,c.array=!0,c.string=!0,c.arraybuffer="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof Uint8Array,c.nodebuffer="undefined"!=typeof a,c.uint8array="undefined"!=typeof Uint8Array,"undefined"==typeof ArrayBuffer)c.blob=!1;else{var b=new ArrayBuffer(0);try{c.blob=0===new Blob([b],{type:"application/zip"}).size}catch(d){try{var e=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,f=new e;f.append(b),c.blob=0===f.getBlob("application/zip").size}catch(d){c.blob=!1}}}}).call(this,"undefined"!=typeof Buffer?Buffer:void 0)},{}],18:[function(a,b){"use strict";function c(a){a&&(this.data=a,this.length=this.data.length,this.index=0)}var d=a("./dataReader");c.prototype=new d,c.prototype.byteAt=function(a){return this.data[a]},c.prototype.lastIndexOfSignature=function(a){for(var b=a.charCodeAt(0),c=a.charCodeAt(1),d=a.charCodeAt(2),e=a.charCodeAt(3),f=this.length-4;f>=0;--f)if(this.data[f]===b&&this.data[f+1]===c&&this.data[f+2]===d&&this.data[f+3]===e)return f;return-1},c.prototype.readData=function(a){if(this.checkOffset(a),0===a)return new Uint8Array(0);var b=this.data.subarray(this.index,this.index+a);return this.index+=a,b},b.exports=c},{"./dataReader":5}],19:[function(a,b){"use strict";var c=a("./utils"),d=function(a){this.data=new Uint8Array(a),this.index=0};d.prototype={append:function(a){0!==a.length&&(a=c.transformTo("uint8array",a),this.data.set(a,this.index),this.index+=a.length)},finalize:function(){return this.data}},b.exports=d},{"./utils":21}],20:[function(a,b,c){"use strict";for(var d=a("./utils"),e=a("./support"),f=a("./nodeBuffer"),g=new Array(256),h=0;256>h;h++)g[h]=h>=252?6:h>=248?5:h>=240?4:h>=224?3:h>=192?2:1;g[254]=g[254]=1;var i=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=e.uint8array?new Uint8Array(i):new Array(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},j=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+g[a[c]]>b?c:b},k=function(a){var b,c,e,f,h=a.length,i=new Array(2*h);for(c=0,b=0;h>b;)if(e=a[b++],128>e)i[c++]=e;else if(f=g[e],f>4)i[c++]=65533,b+=f-1;else{for(e&=2===f?31:3===f?15:7;f>1&&h>b;)e=e<<6|63&a[b++],f--;f>1?i[c++]=65533:65536>e?i[c++]=e:(e-=65536,i[c++]=55296|e>>10&1023,i[c++]=56320|1023&e)}return i.length!==c&&(i.subarray?i=i.subarray(0,c):i.length=c),d.applyFromCharCode(i)};c.utf8encode=function(a){return e.nodebuffer?f(a,"utf-8"):i(a)},c.utf8decode=function(a){if(e.nodebuffer)return d.transformTo("nodebuffer",a).toString("utf-8");a=d.transformTo(e.uint8array?"uint8array":"array",a);for(var b=[],c=0,f=a.length,g=65536;f>c;){var h=j(a,Math.min(c+g,f));b.push(e.uint8array?k(a.subarray(c,h)):k(a.slice(c,h))),c=h}return b.join("")}},{"./nodeBuffer":11,"./support":17,"./utils":21}],21:[function(a,b,c){"use strict";function d(a){return a}function e(a,b){for(var c=0;c<a.length;++c)b[c]=255&a.charCodeAt(c);return b}function f(a){var b=65536,d=[],e=a.length,f=c.getTypeOf(a),g=0,h=!0;try{switch(f){case"uint8array":String.fromCharCode.apply(null,new Uint8Array(0));break;case"nodebuffer":String.fromCharCode.apply(null,j(0))}}catch(i){h=!1}if(!h){for(var k="",l=0;l<a.length;l++)k+=String.fromCharCode(a[l]);return k}for(;e>g&&b>1;)try{d.push("array"===f||"nodebuffer"===f?String.fromCharCode.apply(null,a.slice(g,Math.min(g+b,e))):String.fromCharCode.apply(null,a.subarray(g,Math.min(g+b,e)))),g+=b}catch(i){b=Math.floor(b/2)}return d.join("")}function g(a,b){for(var c=0;c<a.length;c++)b[c]=a[c];return b}var h=a("./support"),i=a("./compressions"),j=a("./nodeBuffer");c.string2binary=function(a){for(var b="",c=0;c<a.length;c++)b+=String.fromCharCode(255&a.charCodeAt(c));return b},c.arrayBuffer2Blob=function(a){c.checkSupport("blob");try{return new Blob([a],{type:"application/zip"})}catch(b){try{var d=window.BlobBuilder||window.WebKitBlobBuilder||window.MozBlobBuilder||window.MSBlobBuilder,e=new d;return e.append(a),e.getBlob("application/zip")}catch(b){throw new Error("Bug : can't construct the Blob.")}}},c.applyFromCharCode=f;var k={};k.string={string:d,array:function(a){return e(a,new Array(a.length))},arraybuffer:function(a){return k.string.uint8array(a).buffer},uint8array:function(a){return e(a,new Uint8Array(a.length))},nodebuffer:function(a){return e(a,j(a.length))}},k.array={string:f,array:d,arraybuffer:function(a){return new Uint8Array(a).buffer},uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(a)}},k.arraybuffer={string:function(a){return f(new Uint8Array(a))},array:function(a){return g(new Uint8Array(a),new Array(a.byteLength))},arraybuffer:d,uint8array:function(a){return new Uint8Array(a)},nodebuffer:function(a){return j(new Uint8Array(a))}},k.uint8array={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return a.buffer},uint8array:d,nodebuffer:function(a){return j(a)}},k.nodebuffer={string:f,array:function(a){return g(a,new Array(a.length))},arraybuffer:function(a){return k.nodebuffer.uint8array(a).buffer},uint8array:function(a){return g(a,new Uint8Array(a.length))},nodebuffer:d},c.transformTo=function(a,b){if(b||(b=""),!a)return b;c.checkSupport(a);var d=c.getTypeOf(b),e=k[d][a](b);return e},c.getTypeOf=function(a){return"string"==typeof a?"string":"[object Array]"===Object.prototype.toString.call(a)?"array":h.nodebuffer&&j.test(a)?"nodebuffer":h.uint8array&&a instanceof Uint8Array?"uint8array":h.arraybuffer&&a instanceof ArrayBuffer?"arraybuffer":void 0},c.checkSupport=function(a){var b=h[a.toLowerCase()];if(!b)throw new Error(a+" is not supported by this browser")},c.MAX_VALUE_16BITS=65535,c.MAX_VALUE_32BITS=-1,c.pretty=function(a){var b,c,d="";for(c=0;c<(a||"").length;c++)b=a.charCodeAt(c),d+="\\x"+(16>b?"0":"")+b.toString(16).toUpperCase();return d},c.findCompression=function(a){for(var b in i)if(i.hasOwnProperty(b)&&i[b].magic===a)return i[b];return null},c.isRegExp=function(a){return"[object RegExp]"===Object.prototype.toString.call(a)}},{"./compressions":3,"./nodeBuffer":11,"./support":17}],22:[function(a,b){"use strict";function c(a,b){this.files=[],this.loadOptions=b,a&&this.load(a)}var d=a("./stringReader"),e=a("./nodeBufferReader"),f=a("./uint8ArrayReader"),g=a("./utils"),h=a("./signature"),i=a("./zipEntry"),j=a("./support"),k=a("./object");c.prototype={checkSignature:function(a){var b=this.reader.readString(4);if(b!==a)throw new Error("Corrupted zip or bug : unexpected signature ("+g.pretty(b)+", expected "+g.pretty(a)+")")},readBlockEndOfCentral:function(){this.diskNumber=this.reader.readInt(2),this.diskWithCentralDirStart=this.reader.readInt(2),this.centralDirRecordsOnThisDisk=this.reader.readInt(2),this.centralDirRecords=this.reader.readInt(2),this.centralDirSize=this.reader.readInt(4),this.centralDirOffset=this.reader.readInt(4),this.zipCommentLength=this.reader.readInt(2),this.zipComment=this.reader.readString(this.zipCommentLength),this.zipComment=k.utf8decode(this.zipComment)},readBlockZip64EndOfCentral:function(){this.zip64EndOfCentralSize=this.reader.readInt(8),this.versionMadeBy=this.reader.readString(2),this.versionNeeded=this.reader.readInt(2),this.diskNumber=this.reader.readInt(4),this.diskWithCentralDirStart=this.reader.readInt(4),this.centralDirRecordsOnThisDisk=this.reader.readInt(8),this.centralDirRecords=this.reader.readInt(8),this.centralDirSize=this.reader.readInt(8),this.centralDirOffset=this.reader.readInt(8),this.zip64ExtensibleData={};for(var a,b,c,d=this.zip64EndOfCentralSize-44,e=0;d>e;)a=this.reader.readInt(2),b=this.reader.readInt(4),c=this.reader.readString(b),this.zip64ExtensibleData[a]={id:a,length:b,value:c}},readBlockZip64EndOfCentralLocator:function(){if(this.diskWithZip64CentralDirStart=this.reader.readInt(4),this.relativeOffsetEndOfZip64CentralDir=this.reader.readInt(8),this.disksCount=this.reader.readInt(4),this.disksCount>1)throw new Error("Multi-volumes zip are not supported")},readLocalFiles:function(){var a,b;for(a=0;a<this.files.length;a++)b=this.files[a],this.reader.setIndex(b.localHeaderOffset),this.checkSignature(h.LOCAL_FILE_HEADER),b.readLocalPart(this.reader),b.handleUTF8()},readCentralDir:function(){var a;for(this.reader.setIndex(this.centralDirOffset);this.reader.readString(4)===h.CENTRAL_FILE_HEADER;)a=new i({zip64:this.zip64},this.loadOptions),a.readCentralPart(this.reader),this.files.push(a)},readEndOfCentral:function(){var a=this.reader.lastIndexOfSignature(h.CENTRAL_DIRECTORY_END);if(-1===a)throw new Error("Corrupted zip : can't find end of central directory");if(this.reader.setIndex(a),this.checkSignature(h.CENTRAL_DIRECTORY_END),this.readBlockEndOfCentral(),this.diskNumber===g.MAX_VALUE_16BITS||this.diskWithCentralDirStart===g.MAX_VALUE_16BITS||this.centralDirRecordsOnThisDisk===g.MAX_VALUE_16BITS||this.centralDirRecords===g.MAX_VALUE_16BITS||this.centralDirSize===g.MAX_VALUE_32BITS||this.centralDirOffset===g.MAX_VALUE_32BITS){if(this.zip64=!0,a=this.reader.lastIndexOfSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),-1===a)throw new Error("Corrupted zip : can't find the ZIP64 end of central directory locator");this.reader.setIndex(a),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_LOCATOR),this.readBlockZip64EndOfCentralLocator(),this.reader.setIndex(this.relativeOffsetEndOfZip64CentralDir),this.checkSignature(h.ZIP64_CENTRAL_DIRECTORY_END),this.readBlockZip64EndOfCentral()}},prepareReader:function(a){var b=g.getTypeOf(a);this.reader="string"!==b||j.uint8array?"nodebuffer"===b?new e(a):new f(g.transformTo("uint8array",a)):new d(a,this.loadOptions.optimizedBinaryString)},load:function(a){this.prepareReader(a),this.readEndOfCentral(),this.readCentralDir(),this.readLocalFiles()}},b.exports=c},{"./nodeBufferReader":12,"./object":13,"./signature":14,"./stringReader":15,"./support":17,"./uint8ArrayReader":18,"./utils":21,"./zipEntry":23}],23:[function(a,b){"use strict";function c(a,b){this.options=a,this.loadOptions=b}var d=a("./stringReader"),e=a("./utils"),f=a("./compressedObject"),g=a("./object");c.prototype={isEncrypted:function(){return 1===(1&this.bitFlag)},useUTF8:function(){return 2048===(2048&this.bitFlag)},prepareCompressedContent:function(a,b,c){return function(){var d=a.index;a.setIndex(b);var e=a.readData(c);return a.setIndex(d),e}},prepareContent:function(a,b,c,d,f){return function(){var a=e.transformTo(d.uncompressInputType,this.getCompressedContent()),b=d.uncompress(a);if(b.length!==f)throw new Error("Bug : uncompressed data size mismatch");return b}},readLocalPart:function(a){var b,c;if(a.skip(22),this.fileNameLength=a.readInt(2),c=a.readInt(2),this.fileName=a.readString(this.fileNameLength),a.skip(c),-1==this.compressedSize||-1==this.uncompressedSize)throw new Error("Bug or corrupted zip : didn't get enough informations from the central directory (compressedSize == -1 || uncompressedSize == -1)");if(b=e.findCompression(this.compressionMethod),null===b)throw new Error("Corrupted zip : compression "+e.pretty(this.compressionMethod)+" unknown (inner file : "+this.fileName+")");if(this.decompressed=new f,this.decompressed.compressedSize=this.compressedSize,this.decompressed.uncompressedSize=this.uncompressedSize,this.decompressed.crc32=this.crc32,this.decompressed.compressionMethod=this.compressionMethod,this.decompressed.getCompressedContent=this.prepareCompressedContent(a,a.index,this.compressedSize,b),this.decompressed.getContent=this.prepareContent(a,a.index,this.compressedSize,b,this.uncompressedSize),this.loadOptions.checkCRC32&&(this.decompressed=e.transformTo("string",this.decompressed.getContent()),g.crc32(this.decompressed)!==this.crc32))throw new Error("Corrupted zip : CRC32 mismatch")},readCentralPart:function(a){if(this.versionMadeBy=a.readString(2),this.versionNeeded=a.readInt(2),this.bitFlag=a.readInt(2),this.compressionMethod=a.readString(2),this.date=a.readDate(),this.crc32=a.readInt(4),this.compressedSize=a.readInt(4),this.uncompressedSize=a.readInt(4),this.fileNameLength=a.readInt(2),this.extraFieldsLength=a.readInt(2),this.fileCommentLength=a.readInt(2),this.diskNumberStart=a.readInt(2),this.internalFileAttributes=a.readInt(2),this.externalFileAttributes=a.readInt(4),this.localHeaderOffset=a.readInt(4),this.isEncrypted())throw new Error("Encrypted zip are not supported");this.fileName=a.readString(this.fileNameLength),this.readExtraFields(a),this.parseZIP64ExtraField(a),this.fileComment=a.readString(this.fileCommentLength),this.dir=16&this.externalFileAttributes?!0:!1},parseZIP64ExtraField:function(){if(this.extraFields[1]){var a=new d(this.extraFields[1].value);this.uncompressedSize===e.MAX_VALUE_32BITS&&(this.uncompressedSize=a.readInt(8)),this.compressedSize===e.MAX_VALUE_32BITS&&(this.compressedSize=a.readInt(8)),this.localHeaderOffset===e.MAX_VALUE_32BITS&&(this.localHeaderOffset=a.readInt(8)),this.diskNumberStart===e.MAX_VALUE_32BITS&&(this.diskNumberStart=a.readInt(4))}},readExtraFields:function(a){var b,c,d,e=a.index;for(this.extraFields=this.extraFields||{};a.index<e+this.extraFieldsLength;)b=a.readInt(2),c=a.readInt(2),d=a.readString(c),this.extraFields[b]={id:b,length:c,value:d}},handleUTF8:function(){if(this.useUTF8())this.fileName=g.utf8decode(this.fileName),this.fileComment=g.utf8decode(this.fileComment);else{var a=this.findExtraFieldUnicodePath();null!==a&&(this.fileName=a);var b=this.findExtraFieldUnicodeComment();null!==b&&(this.fileComment=b)}},findExtraFieldUnicodePath:function(){var a=this.extraFields[28789];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileName)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null},findExtraFieldUnicodeComment:function(){var a=this.extraFields[25461];if(a){var b=new d(a.value);return 1!==b.readInt(1)?null:g.crc32(this.fileComment)!==b.readInt(4)?null:g.utf8decode(b.readString(a.length-5))}return null}},b.exports=c},{"./compressedObject":2,"./object":13,"./stringReader":15,"./utils":21}],24:[function(a,b){"use strict";var c=a("./lib/utils/common").assign,d=a("./lib/deflate"),e=a("./lib/inflate"),f=a("./lib/zlib/constants"),g={};c(g,d,e,f),b.exports=g},{"./lib/deflate":25,"./lib/inflate":26,"./lib/utils/common":27,"./lib/zlib/constants":30}],25:[function(a,b,c){"use strict";function d(a,b){var c=new s(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}function f(a,b){return b=b||{},b.gzip=!0,d(a,b)}var g=a("./zlib/deflate.js"),h=a("./utils/common"),i=a("./utils/strings"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=0,m=4,n=0,o=1,p=-1,q=0,r=8,s=function(a){this.options=h.assign({level:p,method:r,chunkSize:16384,windowBits:15,memLevel:8,strategy:q,to:""},a||{});var b=this.options;b.raw&&b.windowBits>0?b.windowBits=-b.windowBits:b.gzip&&b.windowBits>0&&b.windowBits<16&&(b.windowBits+=16),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=g.deflateInit2(this.strm,b.level,b.method,b.windowBits,b.memLevel,b.strategy);if(c!==n)throw new Error(j[c]);b.header&&g.deflateSetHeader(this.strm,b.header)};s.prototype.push=function(a,b){var c,d,e=this.strm,f=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?m:l,e.input="string"==typeof a?i.string2buf(a):a,e.next_in=0,e.avail_in=e.input.length;do{if(0===e.avail_out&&(e.output=new h.Buf8(f),e.next_out=0,e.avail_out=f),c=g.deflate(e,d),c!==o&&c!==n)return this.onEnd(c),this.ended=!0,!1;(0===e.avail_out||0===e.avail_in&&d===m)&&this.onData("string"===this.options.to?i.buf2binstring(h.shrinkBuf(e.output,e.next_out)):h.shrinkBuf(e.output,e.next_out))}while((e.avail_in>0||0===e.avail_out)&&c!==o);return d===m?(c=g.deflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===n):!0},s.prototype.onData=function(a){this.chunks.push(a)},s.prototype.onEnd=function(a){a===n&&(this.result="string"===this.options.to?this.chunks.join(""):h.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Deflate=s,c.deflate=d,c.deflateRaw=e,c.gzip=f},{"./utils/common":27,"./utils/strings":28,"./zlib/deflate.js":32,"./zlib/messages":37,"./zlib/zstream":39}],26:[function(a,b,c){"use strict";function d(a,b){var c=new m(b);if(c.push(a,!0),c.err)throw c.msg;return c.result}function e(a,b){return b=b||{},b.raw=!0,d(a,b)}var f=a("./zlib/inflate.js"),g=a("./utils/common"),h=a("./utils/strings"),i=a("./zlib/constants"),j=a("./zlib/messages"),k=a("./zlib/zstream"),l=a("./zlib/gzheader"),m=function(a){this.options=g.assign({chunkSize:16384,windowBits:0,to:""},a||{});var b=this.options;b.raw&&b.windowBits>=0&&b.windowBits<16&&(b.windowBits=-b.windowBits,0===b.windowBits&&(b.windowBits=-15)),!(b.windowBits>=0&&b.windowBits<16)||a&&a.windowBits||(b.windowBits+=32),b.windowBits>15&&b.windowBits<48&&0===(15&b.windowBits)&&(b.windowBits|=15),this.err=0,this.msg="",this.ended=!1,this.chunks=[],this.strm=new k,this.strm.avail_out=0;var c=f.inflateInit2(this.strm,b.windowBits);if(c!==i.Z_OK)throw new Error(j[c]);this.header=new l,f.inflateGetHeader(this.strm,this.header)};m.prototype.push=function(a,b){var c,d,e,j,k,l=this.strm,m=this.options.chunkSize;if(this.ended)return!1;d=b===~~b?b:b===!0?i.Z_FINISH:i.Z_NO_FLUSH,l.input="string"==typeof a?h.binstring2buf(a):a,l.next_in=0,l.avail_in=l.input.length;do{if(0===l.avail_out&&(l.output=new g.Buf8(m),l.next_out=0,l.avail_out=m),c=f.inflate(l,i.Z_NO_FLUSH),c!==i.Z_STREAM_END&&c!==i.Z_OK)return this.onEnd(c),this.ended=!0,!1;l.next_out&&(0===l.avail_out||c===i.Z_STREAM_END||0===l.avail_in&&d===i.Z_FINISH)&&("string"===this.options.to?(e=h.utf8border(l.output,l.next_out),j=l.next_out-e,k=h.buf2string(l.output,e),l.next_out=j,l.avail_out=m-j,j&&g.arraySet(l.output,l.output,e,j,0),this.onData(k)):this.onData(g.shrinkBuf(l.output,l.next_out)))}while(l.avail_in>0&&c!==i.Z_STREAM_END);return c===i.Z_STREAM_END&&(d=i.Z_FINISH),d===i.Z_FINISH?(c=f.inflateEnd(this.strm),this.onEnd(c),this.ended=!0,c===i.Z_OK):!0},m.prototype.onData=function(a){this.chunks.push(a)},m.prototype.onEnd=function(a){a===i.Z_OK&&(this.result="string"===this.options.to?this.chunks.join(""):g.flattenChunks(this.chunks)),this.chunks=[],this.err=a,this.msg=this.strm.msg},c.Inflate=m,c.inflate=d,c.inflateRaw=e,c.ungzip=d},{"./utils/common":27,"./utils/strings":28,"./zlib/constants":30,"./zlib/gzheader":33,"./zlib/inflate.js":35,"./zlib/messages":37,"./zlib/zstream":39}],27:[function(a,b,c){"use strict";var d="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Int32Array;c.assign=function(a){for(var b=Array.prototype.slice.call(arguments,1);b.length;){var c=b.shift();if(c){if("object"!=typeof c)throw new TypeError(c+"must be non-object");for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d])}}return a},c.shrinkBuf=function(a,b){return a.length===b?a:a.subarray?a.subarray(0,b):(a.length=b,a)};var e={arraySet:function(a,b,c,d,e){if(b.subarray&&a.subarray)return void a.set(b.subarray(c,c+d),e);for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){var b,c,d,e,f,g;for(d=0,b=0,c=a.length;c>b;b++)d+=a[b].length;for(g=new Uint8Array(d),e=0,b=0,c=a.length;c>b;b++)f=a[b],g.set(f,e),e+=f.length;return g}},f={arraySet:function(a,b,c,d,e){for(var f=0;d>f;f++)a[e+f]=b[c+f]},flattenChunks:function(a){return[].concat.apply([],a)}};c.setTyped=function(a){a?(c.Buf8=Uint8Array,c.Buf16=Uint16Array,c.Buf32=Int32Array,c.assign(c,e)):(c.Buf8=Array,c.Buf16=Array,c.Buf32=Array,c.assign(c,f))},c.setTyped(d)},{}],28:[function(a,b,c){"use strict";function d(a,b){if(65537>b&&(a.subarray&&g||!a.subarray&&f))return String.fromCharCode.apply(null,e.shrinkBuf(a,b));for(var c="",d=0;b>d;d++)c+=String.fromCharCode(a[d]);return c}var e=a("./common"),f=!0,g=!0;try{String.fromCharCode.apply(null,[0])}catch(h){f=!1}try{String.fromCharCode.apply(null,new Uint8Array(1))}catch(h){g=!1}for(var i=new e.Buf8(256),j=0;256>j;j++)i[j]=j>=252?6:j>=248?5:j>=240?4:j>=224?3:j>=192?2:1;i[254]=i[254]=1,c.string2buf=function(a){var b,c,d,f,g,h=a.length,i=0;for(f=0;h>f;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),i+=128>c?1:2048>c?2:65536>c?3:4;for(b=new e.Buf8(i),g=0,f=0;i>g;f++)c=a.charCodeAt(f),55296===(64512&c)&&h>f+1&&(d=a.charCodeAt(f+1),56320===(64512&d)&&(c=65536+(c-55296<<10)+(d-56320),f++)),128>c?b[g++]=c:2048>c?(b[g++]=192|c>>>6,b[g++]=128|63&c):65536>c?(b[g++]=224|c>>>12,b[g++]=128|c>>>6&63,b[g++]=128|63&c):(b[g++]=240|c>>>18,b[g++]=128|c>>>12&63,b[g++]=128|c>>>6&63,b[g++]=128|63&c);return b},c.buf2binstring=function(a){return d(a,a.length)},c.binstring2buf=function(a){for(var b=new e.Buf8(a.length),c=0,d=b.length;d>c;c++)b[c]=a.charCodeAt(c);return b},c.buf2string=function(a,b){var c,e,f,g,h=b||a.length,j=new Array(2*h);for(e=0,c=0;h>c;)if(f=a[c++],128>f)j[e++]=f;else if(g=i[f],g>4)j[e++]=65533,c+=g-1;else{for(f&=2===g?31:3===g?15:7;g>1&&h>c;)f=f<<6|63&a[c++],g--;g>1?j[e++]=65533:65536>f?j[e++]=f:(f-=65536,j[e++]=55296|f>>10&1023,j[e++]=56320|1023&f)}return d(j,e)},c.utf8border=function(a,b){var c;for(b=b||a.length,b>a.length&&(b=a.length),c=b-1;c>=0&&128===(192&a[c]);)c--;return 0>c?b:0===c?b:c+i[a[c]]>b?c:b}},{"./common":27}],29:[function(a,b){"use strict";function c(a,b,c,d){for(var e=65535&a|0,f=a>>>16&65535|0,g=0;0!==c;){g=c>2e3?2e3:c,c-=g;do e=e+b[d++]|0,f=f+e|0;while(--g);e%=65521,f%=65521}return e|f<<16|0}b.exports=c},{}],30:[function(a,b){b.exports={Z_NO_FLUSH:0,Z_PARTIAL_FLUSH:1,Z_SYNC_FLUSH:2,Z_FULL_FLUSH:3,Z_FINISH:4,Z_BLOCK:5,Z_TREES:6,Z_OK:0,Z_STREAM_END:1,Z_NEED_DICT:2,Z_ERRNO:-1,Z_STREAM_ERROR:-2,Z_DATA_ERROR:-3,Z_BUF_ERROR:-5,Z_NO_COMPRESSION:0,Z_BEST_SPEED:1,Z_BEST_COMPRESSION:9,Z_DEFAULT_COMPRESSION:-1,Z_FILTERED:1,Z_HUFFMAN_ONLY:2,Z_RLE:3,Z_FIXED:4,Z_DEFAULT_STRATEGY:0,Z_BINARY:0,Z_TEXT:1,Z_UNKNOWN:2,Z_DEFLATED:8}},{}],31:[function(a,b){"use strict";function c(){for(var a,b=[],c=0;256>c;c++){a=c;for(var d=0;8>d;d++)a=1&a?3988292384^a>>>1:a>>>1;b[c]=a}return b}function d(a,b,c,d){var f=e,g=d+c;a=-1^a;for(var h=d;g>h;h++)a=a>>>8^f[255&(a^b[h])];return-1^a}var e=c();b.exports=d},{}],32:[function(a,b,c){"use strict";function d(a,b){return a.msg=G[b],b}function e(a){return(a<<1)-(a>4?9:0)}function f(a){for(var b=a.length;--b>=0;)a[b]=0}function g(a){var b=a.state,c=b.pending;c>a.avail_out&&(c=a.avail_out),0!==c&&(C.arraySet(a.output,b.pending_buf,b.pending_out,c,a.next_out),a.next_out+=c,b.pending_out+=c,a.total_out+=c,a.avail_out-=c,b.pending-=c,0===b.pending&&(b.pending_out=0))}function h(a,b){D._tr_flush_block(a,a.block_start>=0?a.block_start:-1,a.strstart-a.block_start,b),a.block_start=a.strstart,g(a.strm)}function i(a,b){a.pending_buf[a.pending++]=b}function j(a,b){a.pending_buf[a.pending++]=b>>>8&255,a.pending_buf[a.pending++]=255&b}function k(a,b,c,d){var e=a.avail_in;return e>d&&(e=d),0===e?0:(a.avail_in-=e,C.arraySet(b,a.input,a.next_in,e,c),1===a.state.wrap?a.adler=E(a.adler,b,e,c):2===a.state.wrap&&(a.adler=F(a.adler,b,e,c)),a.next_in+=e,a.total_in+=e,e)}function l(a,b){var c,d,e=a.max_chain_length,f=a.strstart,g=a.prev_length,h=a.nice_match,i=a.strstart>a.w_size-jb?a.strstart-(a.w_size-jb):0,j=a.window,k=a.w_mask,l=a.prev,m=a.strstart+ib,n=j[f+g-1],o=j[f+g];a.prev_length>=a.good_match&&(e>>=2),h>a.lookahead&&(h=a.lookahead);do if(c=b,j[c+g]===o&&j[c+g-1]===n&&j[c]===j[f]&&j[++c]===j[f+1]){f+=2,c++;do;while(j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&j[++f]===j[++c]&&m>f);if(d=ib-(m-f),f=m-ib,d>g){if(a.match_start=b,g=d,d>=h)break;n=j[f+g-1],o=j[f+g]}}while((b=l[b&k])>i&&0!==--e);return g<=a.lookahead?g:a.lookahead}function m(a){var b,c,d,e,f,g=a.w_size;do{if(e=a.window_size-a.lookahead-a.strstart,a.strstart>=g+(g-jb)){C.arraySet(a.window,a.window,g,g,0),a.match_start-=g,a.strstart-=g,a.block_start-=g,c=a.hash_size,b=c;do d=a.head[--b],a.head[b]=d>=g?d-g:0;while(--c);c=g,b=c;do d=a.prev[--b],a.prev[b]=d>=g?d-g:0;while(--c);e+=g}if(0===a.strm.avail_in)break;if(c=k(a.strm,a.window,a.strstart+a.lookahead,e),a.lookahead+=c,a.lookahead+a.insert>=hb)for(f=a.strstart-a.insert,a.ins_h=a.window[f],a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+1])&a.hash_mask;a.insert&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[f+hb-1])&a.hash_mask,a.prev[f&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=f,f++,a.insert--,!(a.lookahead+a.insert<hb)););}while(a.lookahead<jb&&0!==a.strm.avail_in)}function n(a,b){var c=65535;for(c>a.pending_buf_size-5&&(c=a.pending_buf_size-5);;){if(a.lookahead<=1){if(m(a),0===a.lookahead&&b===H)return sb;if(0===a.lookahead)break}a.strstart+=a.lookahead,a.lookahead=0;var d=a.block_start+c;if((0===a.strstart||a.strstart>=d)&&(a.lookahead=a.strstart-d,a.strstart=d,h(a,!1),0===a.strm.avail_out))return sb;if(a.strstart-a.block_start>=a.w_size-jb&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.strstart>a.block_start&&(h(a,!1),0===a.strm.avail_out)?sb:sb}function o(a,b){for(var c,d;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),0!==c&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c)),a.match_length>=hb)if(d=D._tr_tally(a,a.strstart-a.match_start,a.match_length-hb),a.lookahead-=a.match_length,a.match_length<=a.max_lazy_match&&a.lookahead>=hb){a.match_length--;do a.strstart++,a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart;while(0!==--a.match_length);a.strstart++}else a.strstart+=a.match_length,a.match_length=0,a.ins_h=a.window[a.strstart],a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+1])&a.hash_mask;else d=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++;if(d&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function p(a,b){for(var c,d,e;;){if(a.lookahead<jb){if(m(a),a.lookahead<jb&&b===H)return sb;if(0===a.lookahead)break}if(c=0,a.lookahead>=hb&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart),a.prev_length=a.match_length,a.prev_match=a.match_start,a.match_length=hb-1,0!==c&&a.prev_length<a.max_lazy_match&&a.strstart-c<=a.w_size-jb&&(a.match_length=l(a,c),a.match_length<=5&&(a.strategy===S||a.match_length===hb&&a.strstart-a.match_start>4096)&&(a.match_length=hb-1)),a.prev_length>=hb&&a.match_length<=a.prev_length){e=a.strstart+a.lookahead-hb,d=D._tr_tally(a,a.strstart-1-a.prev_match,a.prev_length-hb),a.lookahead-=a.prev_length-1,a.prev_length-=2;do++a.strstart<=e&&(a.ins_h=(a.ins_h<<a.hash_shift^a.window[a.strstart+hb-1])&a.hash_mask,c=a.prev[a.strstart&a.w_mask]=a.head[a.ins_h],a.head[a.ins_h]=a.strstart);while(0!==--a.prev_length);if(a.match_available=0,a.match_length=hb-1,a.strstart++,d&&(h(a,!1),0===a.strm.avail_out))return sb}else if(a.match_available){if(d=D._tr_tally(a,0,a.window[a.strstart-1]),d&&h(a,!1),a.strstart++,a.lookahead--,0===a.strm.avail_out)return sb}else a.match_available=1,a.strstart++,a.lookahead--}return a.match_available&&(d=D._tr_tally(a,0,a.window[a.strstart-1]),a.match_available=0),a.insert=a.strstart<hb-1?a.strstart:hb-1,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function q(a,b){for(var c,d,e,f,g=a.window;;){if(a.lookahead<=ib){if(m(a),a.lookahead<=ib&&b===H)return sb;if(0===a.lookahead)break}if(a.match_length=0,a.lookahead>=hb&&a.strstart>0&&(e=a.strstart-1,d=g[e],d===g[++e]&&d===g[++e]&&d===g[++e])){f=a.strstart+ib;do;while(d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&d===g[++e]&&f>e);a.match_length=ib-(f-e),a.match_length>a.lookahead&&(a.match_length=a.lookahead)}if(a.match_length>=hb?(c=D._tr_tally(a,1,a.match_length-hb),a.lookahead-=a.match_length,a.strstart+=a.match_length,a.match_length=0):(c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++),c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function r(a,b){for(var c;;){if(0===a.lookahead&&(m(a),0===a.lookahead)){if(b===H)return sb;break}if(a.match_length=0,c=D._tr_tally(a,0,a.window[a.strstart]),a.lookahead--,a.strstart++,c&&(h(a,!1),0===a.strm.avail_out))return sb}return a.insert=0,b===K?(h(a,!0),0===a.strm.avail_out?ub:vb):a.last_lit&&(h(a,!1),0===a.strm.avail_out)?sb:tb}function s(a){a.window_size=2*a.w_size,f(a.head),a.max_lazy_match=B[a.level].max_lazy,a.good_match=B[a.level].good_length,a.nice_match=B[a.level].nice_length,a.max_chain_length=B[a.level].max_chain,a.strstart=0,a.block_start=0,a.lookahead=0,a.insert=0,a.match_length=a.prev_length=hb-1,a.match_available=0,a.ins_h=0}function t(){this.strm=null,this.status=0,this.pending_buf=null,this.pending_buf_size=0,this.pending_out=0,this.pending=0,this.wrap=0,this.gzhead=null,this.gzindex=0,this.method=Y,this.last_flush=-1,this.w_size=0,this.w_bits=0,this.w_mask=0,this.window=null,this.window_size=0,this.prev=null,this.head=null,this.ins_h=0,this.hash_size=0,this.hash_bits=0,this.hash_mask=0,this.hash_shift=0,this.block_start=0,this.match_length=0,this.prev_match=0,this.match_available=0,this.strstart=0,this.match_start=0,this.lookahead=0,this.prev_length=0,this.max_chain_length=0,this.max_lazy_match=0,this.level=0,this.strategy=0,this.good_match=0,this.nice_match=0,this.dyn_ltree=new C.Buf16(2*fb),this.dyn_dtree=new C.Buf16(2*(2*db+1)),this.bl_tree=new C.Buf16(2*(2*eb+1)),f(this.dyn_ltree),f(this.dyn_dtree),f(this.bl_tree),this.l_desc=null,this.d_desc=null,this.bl_desc=null,this.bl_count=new C.Buf16(gb+1),this.heap=new C.Buf16(2*cb+1),f(this.heap),this.heap_len=0,this.heap_max=0,this.depth=new C.Buf16(2*cb+1),f(this.depth),this.l_buf=0,this.lit_bufsize=0,this.last_lit=0,this.d_buf=0,this.opt_len=0,this.static_len=0,this.matches=0,this.insert=0,this.bi_buf=0,this.bi_valid=0}function u(a){var b;return a&&a.state?(a.total_in=a.total_out=0,a.data_type=X,b=a.state,b.pending=0,b.pending_out=0,b.wrap<0&&(b.wrap=-b.wrap),b.status=b.wrap?lb:qb,a.adler=2===b.wrap?0:1,b.last_flush=H,D._tr_init(b),M):d(a,O)}function v(a){var b=u(a);return b===M&&s(a.state),b}function w(a,b){return a&&a.state?2!==a.state.wrap?O:(a.state.gzhead=b,M):O}function x(a,b,c,e,f,g){if(!a)return O;var h=1;if(b===R&&(b=6),0>e?(h=0,e=-e):e>15&&(h=2,e-=16),1>f||f>Z||c!==Y||8>e||e>15||0>b||b>9||0>g||g>V)return d(a,O);8===e&&(e=9);var i=new t;return a.state=i,i.strm=a,i.wrap=h,i.gzhead=null,i.w_bits=e,i.w_size=1<<i.w_bits,i.w_mask=i.w_size-1,i.hash_bits=f+7,i.hash_size=1<<i.hash_bits,i.hash_mask=i.hash_size-1,i.hash_shift=~~((i.hash_bits+hb-1)/hb),i.window=new C.Buf8(2*i.w_size),i.head=new C.Buf16(i.hash_size),i.prev=new C.Buf16(i.w_size),i.lit_bufsize=1<<f+6,i.pending_buf_size=4*i.lit_bufsize,i.pending_buf=new C.Buf8(i.pending_buf_size),i.d_buf=i.lit_bufsize>>1,i.l_buf=3*i.lit_bufsize,i.level=b,i.strategy=g,i.method=c,v(a)}function y(a,b){return x(a,b,Y,$,_,W)}function z(a,b){var c,h,k,l;if(!a||!a.state||b>L||0>b)return a?d(a,O):O;if(h=a.state,!a.output||!a.input&&0!==a.avail_in||h.status===rb&&b!==K)return d(a,0===a.avail_out?Q:O);if(h.strm=a,c=h.last_flush,h.last_flush=b,h.status===lb)if(2===h.wrap)a.adler=0,i(h,31),i(h,139),i(h,8),h.gzhead?(i(h,(h.gzhead.text?1:0)+(h.gzhead.hcrc?2:0)+(h.gzhead.extra?4:0)+(h.gzhead.name?8:0)+(h.gzhead.comment?16:0)),i(h,255&h.gzhead.time),i(h,h.gzhead.time>>8&255),i(h,h.gzhead.time>>16&255),i(h,h.gzhead.time>>24&255),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,255&h.gzhead.os),h.gzhead.extra&&h.gzhead.extra.length&&(i(h,255&h.gzhead.extra.length),i(h,h.gzhead.extra.length>>8&255)),h.gzhead.hcrc&&(a.adler=F(a.adler,h.pending_buf,h.pending,0)),h.gzindex=0,h.status=mb):(i(h,0),i(h,0),i(h,0),i(h,0),i(h,0),i(h,9===h.level?2:h.strategy>=T||h.level<2?4:0),i(h,wb),h.status=qb);else{var m=Y+(h.w_bits-8<<4)<<8,n=-1;n=h.strategy>=T||h.level<2?0:h.level<6?1:6===h.level?2:3,m|=n<<6,0!==h.strstart&&(m|=kb),m+=31-m%31,h.status=qb,j(h,m),0!==h.strstart&&(j(h,a.adler>>>16),j(h,65535&a.adler)),a.adler=1}if(h.status===mb)if(h.gzhead.extra){for(k=h.pending;h.gzindex<(65535&h.gzhead.extra.length)&&(h.pending!==h.pending_buf_size||(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending!==h.pending_buf_size));)i(h,255&h.gzhead.extra[h.gzindex]),h.gzindex++;h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),h.gzindex===h.gzhead.extra.length&&(h.gzindex=0,h.status=nb)}else h.status=nb;if(h.status===nb)if(h.gzhead.name){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.name.length?255&h.gzhead.name.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.gzindex=0,h.status=ob)}else h.status=ob;if(h.status===ob)if(h.gzhead.comment){k=h.pending;do{if(h.pending===h.pending_buf_size&&(h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),g(a),k=h.pending,h.pending===h.pending_buf_size)){l=1;break}l=h.gzindex<h.gzhead.comment.length?255&h.gzhead.comment.charCodeAt(h.gzindex++):0,i(h,l)}while(0!==l);h.gzhead.hcrc&&h.pending>k&&(a.adler=F(a.adler,h.pending_buf,h.pending-k,k)),0===l&&(h.status=pb)}else h.status=pb;if(h.status===pb&&(h.gzhead.hcrc?(h.pending+2>h.pending_buf_size&&g(a),h.pending+2<=h.pending_buf_size&&(i(h,255&a.adler),i(h,a.adler>>8&255),a.adler=0,h.status=qb)):h.status=qb),0!==h.pending){if(g(a),0===a.avail_out)return h.last_flush=-1,M}else if(0===a.avail_in&&e(b)<=e(c)&&b!==K)return d(a,Q);if(h.status===rb&&0!==a.avail_in)return d(a,Q);if(0!==a.avail_in||0!==h.lookahead||b!==H&&h.status!==rb){var o=h.strategy===T?r(h,b):h.strategy===U?q(h,b):B[h.level].func(h,b);if((o===ub||o===vb)&&(h.status=rb),o===sb||o===ub)return 0===a.avail_out&&(h.last_flush=-1),M;if(o===tb&&(b===I?D._tr_align(h):b!==L&&(D._tr_stored_block(h,0,0,!1),b===J&&(f(h.head),0===h.lookahead&&(h.strstart=0,h.block_start=0,h.insert=0))),g(a),0===a.avail_out))return h.last_flush=-1,M}return b!==K?M:h.wrap<=0?N:(2===h.wrap?(i(h,255&a.adler),i(h,a.adler>>8&255),i(h,a.adler>>16&255),i(h,a.adler>>24&255),i(h,255&a.total_in),i(h,a.total_in>>8&255),i(h,a.total_in>>16&255),i(h,a.total_in>>24&255)):(j(h,a.adler>>>16),j(h,65535&a.adler)),g(a),h.wrap>0&&(h.wrap=-h.wrap),0!==h.pending?M:N)}function A(a){var b;return a&&a.state?(b=a.state.status,b!==lb&&b!==mb&&b!==nb&&b!==ob&&b!==pb&&b!==qb&&b!==rb?d(a,O):(a.state=null,b===qb?d(a,P):M)):O}var B,C=a("../utils/common"),D=a("./trees"),E=a("./adler32"),F=a("./crc32"),G=a("./messages"),H=0,I=1,J=3,K=4,L=5,M=0,N=1,O=-2,P=-3,Q=-5,R=-1,S=1,T=2,U=3,V=4,W=0,X=2,Y=8,Z=9,$=15,_=8,ab=29,bb=256,cb=bb+1+ab,db=30,eb=19,fb=2*cb+1,gb=15,hb=3,ib=258,jb=ib+hb+1,kb=32,lb=42,mb=69,nb=73,ob=91,pb=103,qb=113,rb=666,sb=1,tb=2,ub=3,vb=4,wb=3,xb=function(a,b,c,d,e){this.good_length=a,this.max_lazy=b,this.nice_length=c,this.max_chain=d,this.func=e};B=[new xb(0,0,0,0,n),new xb(4,4,8,4,o),new xb(4,5,16,8,o),new xb(4,6,32,32,o),new xb(4,4,16,16,p),new xb(8,16,32,32,p),new xb(8,16,128,128,p),new xb(8,32,128,256,p),new xb(32,128,258,1024,p),new xb(32,258,258,4096,p)],c.deflateInit=y,c.deflateInit2=x,c.deflateReset=v,c.deflateResetKeep=u,c.deflateSetHeader=w,c.deflate=z,c.deflateEnd=A,c.deflateInfo="pako deflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./messages":37,"./trees":38}],33:[function(a,b){"use strict";function c(){this.text=0,this.time=0,this.xflags=0,this.os=0,this.extra=null,this.extra_len=0,this.name="",this.comment="",this.hcrc=0,this.done=!1}b.exports=c},{}],34:[function(a,b){"use strict";var c=30,d=12;b.exports=function(a,b){var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C;e=a.state,f=a.next_in,B=a.input,g=f+(a.avail_in-5),h=a.next_out,C=a.output,i=h-(b-a.avail_out),j=h+(a.avail_out-257),k=e.dmax,l=e.wsize,m=e.whave,n=e.wnext,o=e.window,p=e.hold,q=e.bits,r=e.lencode,s=e.distcode,t=(1<<e.lenbits)-1,u=(1<<e.distbits)-1;a:do{15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=r[p&t];b:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,0===w)C[h++]=65535&v;else{if(!(16&w)){if(0===(64&w)){v=r[(65535&v)+(p&(1<<w)-1)];continue b}if(32&w){e.mode=d;break a}a.msg="invalid literal/length code",e.mode=c;break a}x=65535&v,w&=15,w&&(w>q&&(p+=B[f++]<<q,q+=8),x+=p&(1<<w)-1,p>>>=w,q-=w),15>q&&(p+=B[f++]<<q,q+=8,p+=B[f++]<<q,q+=8),v=s[p&u];c:for(;;){if(w=v>>>24,p>>>=w,q-=w,w=v>>>16&255,!(16&w)){if(0===(64&w)){v=s[(65535&v)+(p&(1<<w)-1)];continue c}a.msg="invalid distance code",e.mode=c;break a}if(y=65535&v,w&=15,w>q&&(p+=B[f++]<<q,q+=8,w>q&&(p+=B[f++]<<q,q+=8)),y+=p&(1<<w)-1,y>k){a.msg="invalid distance too far back",e.mode=c;break a}if(p>>>=w,q-=w,w=h-i,y>w){if(w=y-w,w>m&&e.sane){a.msg="invalid distance too far back",e.mode=c;break a}if(z=0,A=o,0===n){if(z+=l-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}else if(w>n){if(z+=l+n-w,w-=n,x>w){x-=w;do C[h++]=o[z++];while(--w);if(z=0,x>n){w=n,x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}}}else if(z+=n-w,x>w){x-=w;do C[h++]=o[z++];while(--w);z=h-y,A=C}for(;x>2;)C[h++]=A[z++],C[h++]=A[z++],C[h++]=A[z++],x-=3;x&&(C[h++]=A[z++],x>1&&(C[h++]=A[z++]))}else{z=h-y;do C[h++]=C[z++],C[h++]=C[z++],C[h++]=C[z++],x-=3;while(x>2);x&&(C[h++]=C[z++],x>1&&(C[h++]=C[z++]))}break}}break}}while(g>f&&j>h);x=q>>3,f-=x,q-=x<<3,p&=(1<<q)-1,a.next_in=f,a.next_out=h,a.avail_in=g>f?5+(g-f):5-(f-g),a.avail_out=j>h?257+(j-h):257-(h-j),e.hold=p,e.bits=q}},{}],35:[function(a,b,c){"use strict";function d(a){return(a>>>24&255)+(a>>>8&65280)+((65280&a)<<8)+((255&a)<<24)}function e(){this.mode=0,this.last=!1,this.wrap=0,this.havedict=!1,this.flags=0,this.dmax=0,this.check=0,this.total=0,this.head=null,this.wbits=0,this.wsize=0,this.whave=0,this.wnext=0,this.window=null,this.hold=0,this.bits=0,this.length=0,this.offset=0,this.extra=0,this.lencode=null,this.distcode=null,this.lenbits=0,this.distbits=0,this.ncode=0,this.nlen=0,this.ndist=0,this.have=0,this.next=null,this.lens=new r.Buf16(320),this.work=new r.Buf16(288),this.lendyn=null,this.distdyn=null,this.sane=0,this.back=0,this.was=0}function f(a){var b;return a&&a.state?(b=a.state,a.total_in=a.total_out=b.total=0,a.msg="",b.wrap&&(a.adler=1&b.wrap),b.mode=K,b.last=0,b.havedict=0,b.dmax=32768,b.head=null,b.hold=0,b.bits=0,b.lencode=b.lendyn=new r.Buf32(ob),b.distcode=b.distdyn=new r.Buf32(pb),b.sane=1,b.back=-1,C):F}function g(a){var b;return a&&a.state?(b=a.state,b.wsize=0,b.whave=0,b.wnext=0,f(a)):F}function h(a,b){var c,d;return a&&a.state?(d=a.state,0>b?(c=0,b=-b):(c=(b>>4)+1,48>b&&(b&=15)),b&&(8>b||b>15)?F:(null!==d.window&&d.wbits!==b&&(d.window=null),d.wrap=c,d.wbits=b,g(a))):F}function i(a,b){var c,d;return a?(d=new e,a.state=d,d.window=null,c=h(a,b),c!==C&&(a.state=null),c):F}function j(a){return i(a,rb)}function k(a){if(sb){var b;for(p=new r.Buf32(512),q=new r.Buf32(32),b=0;144>b;)a.lens[b++]=8;for(;256>b;)a.lens[b++]=9;for(;280>b;)a.lens[b++]=7;for(;288>b;)a.lens[b++]=8;for(v(x,a.lens,0,288,p,0,a.work,{bits:9}),b=0;32>b;)a.lens[b++]=5;v(y,a.lens,0,32,q,0,a.work,{bits:5}),sb=!1}a.lencode=p,a.lenbits=9,a.distcode=q,a.distbits=5}function l(a,b,c,d){var e,f=a.state;return null===f.window&&(f.wsize=1<<f.wbits,f.wnext=0,f.whave=0,f.window=new r.Buf8(f.wsize)),d>=f.wsize?(r.arraySet(f.window,b,c-f.wsize,f.wsize,0),f.wnext=0,f.whave=f.wsize):(e=f.wsize-f.wnext,e>d&&(e=d),r.arraySet(f.window,b,c-d,e,f.wnext),d-=e,d?(r.arraySet(f.window,b,c-d,d,0),f.wnext=d,f.whave=f.wsize):(f.wnext+=e,f.wnext===f.wsize&&(f.wnext=0),f.whave<f.wsize&&(f.whave+=e))),0}function m(a,b){var c,e,f,g,h,i,j,m,n,o,p,q,ob,pb,qb,rb,sb,tb,ub,vb,wb,xb,yb,zb,Ab=0,Bb=new r.Buf8(4),Cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];if(!a||!a.state||!a.output||!a.input&&0!==a.avail_in)return F;c=a.state,c.mode===V&&(c.mode=W),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,o=i,p=j,xb=C;a:for(;;)switch(c.mode){case K:if(0===c.wrap){c.mode=W;break}for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(2&c.wrap&&35615===m){c.check=0,Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0),m=0,n=0,c.mode=L;break}if(c.flags=0,c.head&&(c.head.done=!1),!(1&c.wrap)||(((255&m)<<8)+(m>>8))%31){a.msg="incorrect header check",c.mode=lb;break}if((15&m)!==J){a.msg="unknown compression method",c.mode=lb;break}if(m>>>=4,n-=4,wb=(15&m)+8,0===c.wbits)c.wbits=wb;else if(wb>c.wbits){a.msg="invalid window size",c.mode=lb;break}c.dmax=1<<wb,a.adler=c.check=1,c.mode=512&m?T:V,m=0,n=0;break;case L:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.flags=m,(255&c.flags)!==J){a.msg="unknown compression method",c.mode=lb;break}if(57344&c.flags){a.msg="unknown header flags set",c.mode=lb;break}c.head&&(c.head.text=m>>8&1),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=M;case M:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.time=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,Bb[2]=m>>>16&255,Bb[3]=m>>>24&255,c.check=t(c.check,Bb,4,0)),m=0,n=0,c.mode=N;case N:for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.head&&(c.head.xflags=255&m,c.head.os=m>>8),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0,c.mode=O;case O:if(1024&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length=m,c.head&&(c.head.extra_len=m),512&c.flags&&(Bb[0]=255&m,Bb[1]=m>>>8&255,c.check=t(c.check,Bb,2,0)),m=0,n=0}else c.head&&(c.head.extra=null);c.mode=P;case P:if(1024&c.flags&&(q=c.length,q>i&&(q=i),q&&(c.head&&(wb=c.head.extra_len-c.length,c.head.extra||(c.head.extra=new Array(c.head.extra_len)),r.arraySet(c.head.extra,e,g,q,wb)),512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,c.length-=q),c.length))break a;c.length=0,c.mode=Q;case Q:if(2048&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.name+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.name=null);c.length=0,c.mode=R;case R:if(4096&c.flags){if(0===i)break a;q=0;do wb=e[g+q++],c.head&&wb&&c.length<65536&&(c.head.comment+=String.fromCharCode(wb));while(wb&&i>q);if(512&c.flags&&(c.check=t(c.check,e,q,g)),i-=q,g+=q,wb)break a}else c.head&&(c.head.comment=null);c.mode=S;case S:if(512&c.flags){for(;16>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(65535&c.check)){a.msg="header crc mismatch",c.mode=lb;break}m=0,n=0}c.head&&(c.head.hcrc=c.flags>>9&1,c.head.done=!0),a.adler=c.check=0,c.mode=V;break;case T:for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}a.adler=c.check=d(m),m=0,n=0,c.mode=U;case U:if(0===c.havedict)return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,E;a.adler=c.check=1,c.mode=V;case V:if(b===A||b===B)break a;case W:if(c.last){m>>>=7&n,n-=7&n,c.mode=ib;break}for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}switch(c.last=1&m,m>>>=1,n-=1,3&m){case 0:c.mode=X;break;case 1:if(k(c),c.mode=bb,b===B){m>>>=2,n-=2;break a}break;case 2:c.mode=$;break;case 3:a.msg="invalid block type",c.mode=lb}m>>>=2,n-=2;break;case X:for(m>>>=7&n,n-=7&n;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if((65535&m)!==(m>>>16^65535)){a.msg="invalid stored block lengths",c.mode=lb;break}if(c.length=65535&m,m=0,n=0,c.mode=Y,b===B)break a;case Y:c.mode=Z;case Z:if(q=c.length){if(q>i&&(q=i),q>j&&(q=j),0===q)break a;r.arraySet(f,e,g,q,h),i-=q,g+=q,j-=q,h+=q,c.length-=q;break}c.mode=V;break;case $:for(;14>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(c.nlen=(31&m)+257,m>>>=5,n-=5,c.ndist=(31&m)+1,m>>>=5,n-=5,c.ncode=(15&m)+4,m>>>=4,n-=4,c.nlen>286||c.ndist>30){a.msg="too many length or distance symbols",c.mode=lb;break}c.have=0,c.mode=_;case _:for(;c.have<c.ncode;){for(;3>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.lens[Cb[c.have++]]=7&m,m>>>=3,n-=3}for(;c.have<19;)c.lens[Cb[c.have++]]=0;if(c.lencode=c.lendyn,c.lenbits=7,yb={bits:c.lenbits},xb=v(w,c.lens,0,19,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid code lengths set",c.mode=lb;break}c.have=0,c.mode=ab;case ab:for(;c.have<c.nlen+c.ndist;){for(;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(16>sb)m>>>=qb,n-=qb,c.lens[c.have++]=sb;else{if(16===sb){for(zb=qb+2;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m>>>=qb,n-=qb,0===c.have){a.msg="invalid bit length repeat",c.mode=lb;break}wb=c.lens[c.have-1],q=3+(3&m),m>>>=2,n-=2}else if(17===sb){for(zb=qb+3;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=3+(7&m),m>>>=3,n-=3}else{for(zb=qb+7;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=qb,n-=qb,wb=0,q=11+(127&m),m>>>=7,n-=7}if(c.have+q>c.nlen+c.ndist){a.msg="invalid bit length repeat",c.mode=lb;break}for(;q--;)c.lens[c.have++]=wb}}if(c.mode===lb)break;if(0===c.lens[256]){a.msg="invalid code -- missing end-of-block",c.mode=lb;break}if(c.lenbits=9,yb={bits:c.lenbits},xb=v(x,c.lens,0,c.nlen,c.lencode,0,c.work,yb),c.lenbits=yb.bits,xb){a.msg="invalid literal/lengths set",c.mode=lb;break}if(c.distbits=6,c.distcode=c.distdyn,yb={bits:c.distbits},xb=v(y,c.lens,c.nlen,c.ndist,c.distcode,0,c.work,yb),c.distbits=yb.bits,xb){a.msg="invalid distances set",c.mode=lb;break}if(c.mode=bb,b===B)break a;case bb:c.mode=cb;case cb:if(i>=6&&j>=258){a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,u(a,p),h=a.next_out,f=a.output,j=a.avail_out,g=a.next_in,e=a.input,i=a.avail_in,m=c.hold,n=c.bits,c.mode===V&&(c.back=-1);break}for(c.back=0;Ab=c.lencode[m&(1<<c.lenbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(rb&&0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.lencode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,c.length=sb,0===rb){c.mode=hb;break}if(32&rb){c.back=-1,c.mode=V;break}if(64&rb){a.msg="invalid literal/length code",c.mode=lb;break}c.extra=15&rb,c.mode=db;case db:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.length+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}c.was=c.length,c.mode=eb;case eb:for(;Ab=c.distcode[m&(1<<c.distbits)-1],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(0===(240&rb)){for(tb=qb,ub=rb,vb=sb;Ab=c.distcode[vb+((m&(1<<tb+ub)-1)>>tb)],qb=Ab>>>24,rb=Ab>>>16&255,sb=65535&Ab,!(n>=tb+qb);){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}m>>>=tb,n-=tb,c.back+=tb}if(m>>>=qb,n-=qb,c.back+=qb,64&rb){a.msg="invalid distance code",c.mode=lb;break}c.offset=sb,c.extra=15&rb,c.mode=fb;case fb:if(c.extra){for(zb=c.extra;zb>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}c.offset+=m&(1<<c.extra)-1,m>>>=c.extra,n-=c.extra,c.back+=c.extra}if(c.offset>c.dmax){a.msg="invalid distance too far back",c.mode=lb;break}c.mode=gb;case gb:if(0===j)break a;if(q=p-j,c.offset>q){if(q=c.offset-q,q>c.whave&&c.sane){a.msg="invalid distance too far back",c.mode=lb;break}q>c.wnext?(q-=c.wnext,ob=c.wsize-q):ob=c.wnext-q,q>c.length&&(q=c.length),pb=c.window}else pb=f,ob=h-c.offset,q=c.length;q>j&&(q=j),j-=q,c.length-=q;do f[h++]=pb[ob++];while(--q);0===c.length&&(c.mode=cb);break;case hb:if(0===j)break a;f[h++]=c.length,j--,c.mode=cb;break;case ib:if(c.wrap){for(;32>n;){if(0===i)break a;i--,m|=e[g++]<<n,n+=8}if(p-=j,a.total_out+=p,c.total+=p,p&&(a.adler=c.check=c.flags?t(c.check,f,p,h-p):s(c.check,f,p,h-p)),p=j,(c.flags?m:d(m))!==c.check){a.msg="incorrect data check",c.mode=lb;break}m=0,n=0}c.mode=jb;case jb:if(c.wrap&&c.flags){for(;32>n;){if(0===i)break a;i--,m+=e[g++]<<n,n+=8}if(m!==(4294967295&c.total)){a.msg="incorrect length check",c.mode=lb;break}m=0,n=0}c.mode=kb;case kb:xb=D;break a;case lb:xb=G;break a;case mb:return H;case nb:default:return F}return a.next_out=h,a.avail_out=j,a.next_in=g,a.avail_in=i,c.hold=m,c.bits=n,(c.wsize||p!==a.avail_out&&c.mode<lb&&(c.mode<ib||b!==z))&&l(a,a.output,a.next_out,p-a.avail_out)?(c.mode=mb,H):(o-=a.avail_in,p-=a.avail_out,a.total_in+=o,a.total_out+=p,c.total+=p,c.wrap&&p&&(a.adler=c.check=c.flags?t(c.check,f,p,a.next_out-p):s(c.check,f,p,a.next_out-p)),a.data_type=c.bits+(c.last?64:0)+(c.mode===V?128:0)+(c.mode===bb||c.mode===Y?256:0),(0===o&&0===p||b===z)&&xb===C&&(xb=I),xb)}function n(a){if(!a||!a.state)return F;var b=a.state;return b.window&&(b.window=null),a.state=null,C}function o(a,b){var c;return a&&a.state?(c=a.state,0===(2&c.wrap)?F:(c.head=b,b.done=!1,C)):F}var p,q,r=a("../utils/common"),s=a("./adler32"),t=a("./crc32"),u=a("./inffast"),v=a("./inftrees"),w=0,x=1,y=2,z=4,A=5,B=6,C=0,D=1,E=2,F=-2,G=-3,H=-4,I=-5,J=8,K=1,L=2,M=3,N=4,O=5,P=6,Q=7,R=8,S=9,T=10,U=11,V=12,W=13,X=14,Y=15,Z=16,$=17,_=18,ab=19,bb=20,cb=21,db=22,eb=23,fb=24,gb=25,hb=26,ib=27,jb=28,kb=29,lb=30,mb=31,nb=32,ob=852,pb=592,qb=15,rb=qb,sb=!0;c.inflateReset=g,c.inflateReset2=h,c.inflateResetKeep=f,c.inflateInit=j,c.inflateInit2=i,c.inflate=m,c.inflateEnd=n,c.inflateGetHeader=o,c.inflateInfo="pako inflate (from Nodeca project)"},{"../utils/common":27,"./adler32":29,"./crc32":31,"./inffast":34,"./inftrees":36}],36:[function(a,b){"use strict";var c=a("../utils/common"),d=15,e=852,f=592,g=0,h=1,i=2,j=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,0,0],k=[16,16,16,16,16,16,16,16,17,17,17,17,18,18,18,18,19,19,19,19,20,20,20,20,21,21,21,21,16,72,78],l=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0],m=[16,16,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,64,64];b.exports=function(a,b,n,o,p,q,r,s){var t,u,v,w,x,y,z,A,B,C=s.bits,D=0,E=0,F=0,G=0,H=0,I=0,J=0,K=0,L=0,M=0,N=null,O=0,P=new c.Buf16(d+1),Q=new c.Buf16(d+1),R=null,S=0;for(D=0;d>=D;D++)P[D]=0;for(E=0;o>E;E++)P[b[n+E]]++;for(H=C,G=d;G>=1&&0===P[G];G--);if(H>G&&(H=G),0===G)return p[q++]=20971520,p[q++]=20971520,s.bits=1,0;for(F=1;G>F&&0===P[F];F++);for(F>H&&(H=F),K=1,D=1;d>=D;D++)if(K<<=1,K-=P[D],0>K)return-1;if(K>0&&(a===g||1!==G))return-1;for(Q[1]=0,D=1;d>D;D++)Q[D+1]=Q[D]+P[D];for(E=0;o>E;E++)0!==b[n+E]&&(r[Q[b[n+E]]++]=E);if(a===g?(N=R=r,y=19):a===h?(N=j,O-=257,R=k,S-=257,y=256):(N=l,R=m,y=-1),M=0,E=0,D=F,x=q,I=H,J=0,v=-1,L=1<<H,w=L-1,a===h&&L>e||a===i&&L>f)return 1;for(var T=0;;){T++,z=D-J,r[E]<y?(A=0,B=r[E]):r[E]>y?(A=R[S+r[E]],B=N[O+r[E]]):(A=96,B=0),t=1<<D-J,u=1<<I,F=u;do u-=t,p[x+(M>>J)+u]=z<<24|A<<16|B|0;while(0!==u);for(t=1<<D-1;M&t;)t>>=1;if(0!==t?(M&=t-1,M+=t):M=0,E++,0===--P[D]){if(D===G)break;D=b[n+r[E]]}if(D>H&&(M&w)!==v){for(0===J&&(J=H),x+=F,I=D-J,K=1<<I;G>I+J&&(K-=P[I+J],!(0>=K));)I++,K<<=1;if(L+=1<<I,a===h&&L>e||a===i&&L>f)return 1;v=M&w,p[v]=H<<24|I<<16|x-q|0}}return 0!==M&&(p[x+M]=D-J<<24|64<<16|0),s.bits=H,0}},{"../utils/common":27}],37:[function(a,b){"use strict";b.exports={2:"need dictionary",1:"stream end",0:"","-1":"file error","-2":"stream error","-3":"data error","-4":"insufficient memory","-5":"buffer error","-6":"incompatible version"}},{}],38:[function(a,b,c){"use strict";function d(a){for(var b=a.length;--b>=0;)a[b]=0}function e(a){return 256>a?gb[a]:gb[256+(a>>>7)]}function f(a,b){a.pending_buf[a.pending++]=255&b,a.pending_buf[a.pending++]=b>>>8&255}function g(a,b,c){a.bi_valid>V-c?(a.bi_buf|=b<<a.bi_valid&65535,f(a,a.bi_buf),a.bi_buf=b>>V-a.bi_valid,a.bi_valid+=c-V):(a.bi_buf|=b<<a.bi_valid&65535,a.bi_valid+=c)}function h(a,b,c){g(a,c[2*b],c[2*b+1])}function i(a,b){var c=0;do c|=1&a,a>>>=1,c<<=1;while(--b>0);return c>>>1}function j(a){16===a.bi_valid?(f(a,a.bi_buf),a.bi_buf=0,a.bi_valid=0):a.bi_valid>=8&&(a.pending_buf[a.pending++]=255&a.bi_buf,a.bi_buf>>=8,a.bi_valid-=8)}function k(a,b){var c,d,e,f,g,h,i=b.dyn_tree,j=b.max_code,k=b.stat_desc.static_tree,l=b.stat_desc.has_stree,m=b.stat_desc.extra_bits,n=b.stat_desc.extra_base,o=b.stat_desc.max_length,p=0;for(f=0;U>=f;f++)a.bl_count[f]=0;for(i[2*a.heap[a.heap_max]+1]=0,c=a.heap_max+1;T>c;c++)d=a.heap[c],f=i[2*i[2*d+1]+1]+1,f>o&&(f=o,p++),i[2*d+1]=f,d>j||(a.bl_count[f]++,g=0,d>=n&&(g=m[d-n]),h=i[2*d],a.opt_len+=h*(f+g),l&&(a.static_len+=h*(k[2*d+1]+g)));if(0!==p){do{for(f=o-1;0===a.bl_count[f];)f--;a.bl_count[f]--,a.bl_count[f+1]+=2,a.bl_count[o]--,p-=2}while(p>0);for(f=o;0!==f;f--)for(d=a.bl_count[f];0!==d;)e=a.heap[--c],e>j||(i[2*e+1]!==f&&(a.opt_len+=(f-i[2*e+1])*i[2*e],i[2*e+1]=f),d--)}}function l(a,b,c){var d,e,f=new Array(U+1),g=0;for(d=1;U>=d;d++)f[d]=g=g+c[d-1]<<1;for(e=0;b>=e;e++){var h=a[2*e+1];0!==h&&(a[2*e]=i(f[h]++,h))}}function m(){var a,b,c,d,e,f=new Array(U+1);for(c=0,d=0;O-1>d;d++)for(ib[d]=c,a=0;a<1<<_[d];a++)hb[c++]=d;for(hb[c-1]=d,e=0,d=0;16>d;d++)for(jb[d]=e,a=0;a<1<<ab[d];a++)gb[e++]=d;for(e>>=7;R>d;d++)for(jb[d]=e<<7,a=0;a<1<<ab[d]-7;a++)gb[256+e++]=d;for(b=0;U>=b;b++)f[b]=0;for(a=0;143>=a;)eb[2*a+1]=8,a++,f[8]++;for(;255>=a;)eb[2*a+1]=9,a++,f[9]++;for(;279>=a;)eb[2*a+1]=7,a++,f[7]++;for(;287>=a;)eb[2*a+1]=8,a++,f[8]++;for(l(eb,Q+1,f),a=0;R>a;a++)fb[2*a+1]=5,fb[2*a]=i(a,5);kb=new nb(eb,_,P+1,Q,U),lb=new nb(fb,ab,0,R,U),mb=new nb(new Array(0),bb,0,S,W)}function n(a){var b;for(b=0;Q>b;b++)a.dyn_ltree[2*b]=0;for(b=0;R>b;b++)a.dyn_dtree[2*b]=0;for(b=0;S>b;b++)a.bl_tree[2*b]=0;a.dyn_ltree[2*X]=1,a.opt_len=a.static_len=0,a.last_lit=a.matches=0}function o(a){a.bi_valid>8?f(a,a.bi_buf):a.bi_valid>0&&(a.pending_buf[a.pending++]=a.bi_buf),a.bi_buf=0,a.bi_valid=0}function p(a,b,c,d){o(a),d&&(f(a,c),f(a,~c)),E.arraySet(a.pending_buf,a.window,b,c,a.pending),a.pending+=c}function q(a,b,c,d){var e=2*b,f=2*c;return a[e]<a[f]||a[e]===a[f]&&d[b]<=d[c]}function r(a,b,c){for(var d=a.heap[c],e=c<<1;e<=a.heap_len&&(e<a.heap_len&&q(b,a.heap[e+1],a.heap[e],a.depth)&&e++,!q(b,d,a.heap[e],a.depth));)a.heap[c]=a.heap[e],c=e,e<<=1;a.heap[c]=d}function s(a,b,c){var d,f,i,j,k=0;if(0!==a.last_lit)do d=a.pending_buf[a.d_buf+2*k]<<8|a.pending_buf[a.d_buf+2*k+1],f=a.pending_buf[a.l_buf+k],k++,0===d?h(a,f,b):(i=hb[f],h(a,i+P+1,b),j=_[i],0!==j&&(f-=ib[i],g(a,f,j)),d--,i=e(d),h(a,i,c),j=ab[i],0!==j&&(d-=jb[i],g(a,d,j)));while(k<a.last_lit);h(a,X,b)}function t(a,b){var c,d,e,f=b.dyn_tree,g=b.stat_desc.static_tree,h=b.stat_desc.has_stree,i=b.stat_desc.elems,j=-1;for(a.heap_len=0,a.heap_max=T,c=0;i>c;c++)0!==f[2*c]?(a.heap[++a.heap_len]=j=c,a.depth[c]=0):f[2*c+1]=0;for(;a.heap_len<2;)e=a.heap[++a.heap_len]=2>j?++j:0,f[2*e]=1,a.depth[e]=0,a.opt_len--,h&&(a.static_len-=g[2*e+1]);for(b.max_code=j,c=a.heap_len>>1;c>=1;c--)r(a,f,c);e=i;do c=a.heap[1],a.heap[1]=a.heap[a.heap_len--],r(a,f,1),d=a.heap[1],a.heap[--a.heap_max]=c,a.heap[--a.heap_max]=d,f[2*e]=f[2*c]+f[2*d],a.depth[e]=(a.depth[c]>=a.depth[d]?a.depth[c]:a.depth[d])+1,f[2*c+1]=f[2*d+1]=e,a.heap[1]=e++,r(a,f,1);while(a.heap_len>=2);a.heap[--a.heap_max]=a.heap[1],k(a,b),l(f,j,a.bl_count)}function u(a,b,c){var d,e,f=-1,g=b[1],h=0,i=7,j=4;for(0===g&&(i=138,j=3),b[2*(c+1)+1]=65535,d=0;c>=d;d++)e=g,g=b[2*(d+1)+1],++h<i&&e===g||(j>h?a.bl_tree[2*e]+=h:0!==e?(e!==f&&a.bl_tree[2*e]++,a.bl_tree[2*Y]++):10>=h?a.bl_tree[2*Z]++:a.bl_tree[2*$]++,h=0,f=e,0===g?(i=138,j=3):e===g?(i=6,j=3):(i=7,j=4))}function v(a,b,c){var d,e,f=-1,i=b[1],j=0,k=7,l=4;for(0===i&&(k=138,l=3),d=0;c>=d;d++)if(e=i,i=b[2*(d+1)+1],!(++j<k&&e===i)){if(l>j){do h(a,e,a.bl_tree);while(0!==--j)}else 0!==e?(e!==f&&(h(a,e,a.bl_tree),j--),h(a,Y,a.bl_tree),g(a,j-3,2)):10>=j?(h(a,Z,a.bl_tree),g(a,j-3,3)):(h(a,$,a.bl_tree),g(a,j-11,7));j=0,f=e,0===i?(k=138,l=3):e===i?(k=6,l=3):(k=7,l=4)}}function w(a){var b;for(u(a,a.dyn_ltree,a.l_desc.max_code),u(a,a.dyn_dtree,a.d_desc.max_code),t(a,a.bl_desc),b=S-1;b>=3&&0===a.bl_tree[2*cb[b]+1];b--);return a.opt_len+=3*(b+1)+5+5+4,b}function x(a,b,c,d){var e;for(g(a,b-257,5),g(a,c-1,5),g(a,d-4,4),e=0;d>e;e++)g(a,a.bl_tree[2*cb[e]+1],3);v(a,a.dyn_ltree,b-1),v(a,a.dyn_dtree,c-1)}function y(a){var b,c=4093624447;for(b=0;31>=b;b++,c>>>=1)if(1&c&&0!==a.dyn_ltree[2*b])return G;if(0!==a.dyn_ltree[18]||0!==a.dyn_ltree[20]||0!==a.dyn_ltree[26])return H;for(b=32;P>b;b++)if(0!==a.dyn_ltree[2*b])return H;return G}function z(a){pb||(m(),pb=!0),a.l_desc=new ob(a.dyn_ltree,kb),a.d_desc=new ob(a.dyn_dtree,lb),a.bl_desc=new ob(a.bl_tree,mb),a.bi_buf=0,a.bi_valid=0,n(a)}function A(a,b,c,d){g(a,(J<<1)+(d?1:0),3),p(a,b,c,!0)}function B(a){g(a,K<<1,3),h(a,X,eb),j(a)}function C(a,b,c,d){var e,f,h=0;a.level>0?(a.strm.data_type===I&&(a.strm.data_type=y(a)),t(a,a.l_desc),t(a,a.d_desc),h=w(a),e=a.opt_len+3+7>>>3,f=a.static_len+3+7>>>3,e>=f&&(e=f)):e=f=c+5,e>=c+4&&-1!==b?A(a,b,c,d):a.strategy===F||f===e?(g(a,(K<<1)+(d?1:0),3),s(a,eb,fb)):(g(a,(L<<1)+(d?1:0),3),x(a,a.l_desc.max_code+1,a.d_desc.max_code+1,h+1),s(a,a.dyn_ltree,a.dyn_dtree)),n(a),d&&o(a)}function D(a,b,c){return a.pending_buf[a.d_buf+2*a.last_lit]=b>>>8&255,a.pending_buf[a.d_buf+2*a.last_lit+1]=255&b,a.pending_buf[a.l_buf+a.last_lit]=255&c,a.last_lit++,0===b?a.dyn_ltree[2*c]++:(a.matches++,b--,a.dyn_ltree[2*(hb[c]+P+1)]++,a.dyn_dtree[2*e(b)]++),a.last_lit===a.lit_bufsize-1}var E=a("../utils/common"),F=4,G=0,H=1,I=2,J=0,K=1,L=2,M=3,N=258,O=29,P=256,Q=P+1+O,R=30,S=19,T=2*Q+1,U=15,V=16,W=7,X=256,Y=16,Z=17,$=18,_=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],bb=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7],cb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],db=512,eb=new Array(2*(Q+2));d(eb);var fb=new Array(2*R);d(fb);var gb=new Array(db);d(gb);var hb=new Array(N-M+1);d(hb);var ib=new Array(O);d(ib);var jb=new Array(R);d(jb);var kb,lb,mb,nb=function(a,b,c,d,e){this.static_tree=a,this.extra_bits=b,this.extra_base=c,this.elems=d,this.max_length=e,this.has_stree=a&&a.length},ob=function(a,b){this.dyn_tree=a,this.max_code=0,this.stat_desc=b},pb=!1;c._tr_init=z,c._tr_stored_block=A,c._tr_flush_block=C,c._tr_tally=D,c._tr_align=B},{"../utils/common":27}],39:[function(a,b){"use strict";function c(){this.input=null,this.next_in=0,this.avail_in=0,this.total_in=0,this.output=null,this.next_out=0,this.avail_out=0,this.total_out=0,this.msg="",this.state=null,this.data_type=2,this.adler=0}b.exports=c},{}]},{},[9])(9)});'use strict';if(tr.isVinn){global.JSZip=global.window.JSZip;global.window=undefined;}else if(tr.isNode){const jsZipAbsPath=HTMLImportsLoader.hrefToAbsolutePath('/jszip.min.js');const jsZipModule=require(jsZipAbsPath);global.JSZip=jsZipModule;}'use strict';tr.exportTo('tr.e.importer',function(){function ZipImporter(model,eventData){if(eventData instanceof ArrayBuffer){eventData=new Uint8Array(eventData);}
+this.model_=model;this.eventData_=eventData;}
+ZipImporter.canImport=function(eventData){let header;if(eventData instanceof ArrayBuffer){header=new Uint8Array(eventData.slice(0,2));}else if(typeof(eventData)==='string'||eventData instanceof String){header=[eventData.charCodeAt(0),eventData.charCodeAt(1)];}else{return false;}
+return header[0]==='P'.charCodeAt(0)&&header[1]==='K'.charCodeAt(0);};ZipImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'ZipImporter';},isTraceDataContainer(){return true;},extractSubtraces(){const zip=new JSZip(this.eventData_);const subtraces=[];for(const idx in zip.files){subtraces.push(zip.files[idx].asBinary());}
+return subtraces;}};tr.importer.Importer.register(ZipImporter);return{ZipImporter,};});'use strict';tr.exportTo('tr.model',function(){function HeapEntry(heapDump,leafStackFrame,objectTypeName,size,count,valuesAreTotals){this.heapDump=heapDump;this.leafStackFrame=leafStackFrame;this.objectTypeName=objectTypeName;this.size=size;this.count=count;this.valuesAreTotals=valuesAreTotals;}
+function HeapDump(processMemoryDump,allocatorName,isComplete){this.processMemoryDump=processMemoryDump;this.allocatorName=allocatorName;this.isComplete=isComplete;this.entries=[];}
+HeapDump.prototype={addEntry(leafStackFrame,objectTypeName,size,count,opt_valuesAreTotals){if(opt_valuesAreTotals===undefined)opt_valuesAreTotals=true;const valuesAreTotals=opt_valuesAreTotals;const entry=new HeapEntry(this,leafStackFrame,objectTypeName,size,count,valuesAreTotals);this.entries.push(entry);return entry;}};return{HeapEntry,HeapDump,};});'use strict';tr.exportTo('tr.e.importer',function(){function HeapDumpTraceEventImporter(heapProfileExpander,stackFrames,processMemoryDump,idPrefix,model){this.expander=heapProfileExpander;this.stackFrames=stackFrames;this.processMemoryDump=processMemoryDump;this.idPrefix=idPrefix;this.model=model;}
+HeapDumpTraceEventImporter.prototype={getLeafStackFrame(stackFrameId){if(stackFrameId==='')return undefined;const parentId=this.idPrefix+stackFrameId;const id=parentId+':self';if(!this.stackFrames[id]){const parentStackFrame=this.stackFrames[parentId];const stackFrame=new tr.model.StackFrame(parentStackFrame,id,'<self>',undefined);this.model.addStackFrame(stackFrame);}
+return this.stackFrames[id];},parseEntry(entry,heapDump){const size=entry.size;const count=entry.count;const leafStackFrame=this.getLeafStackFrame(entry.node.id);const objectTypeName=entry.type.name;const valuesAreTotals=false;if(objectTypeName===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing object type name (ID '+typeId+')',});}
+heapDump.addEntry(leafStackFrame,objectTypeName,size,count,valuesAreTotals);},parse(){const heapDumps={};const inflated=this.expander.inflated;for(const[allocatorName,entries]of Object.entries(inflated)){const heapDump=new tr.model.HeapDump(this.processMemoryDump,allocatorName);for(const entry of entries){this.parseEntry(entry,heapDump);}
+heapDump.isComplete=true;heapDumps[allocatorName]=heapDump;}
+return heapDumps;},};return{HeapDumpTraceEventImporter,};});'use strict';tr.exportTo('tr.e.importer',function(){function LegacyHeapDumpTraceEventImporter(model,processMemoryDump,processObjectTypeNameMap,idPrefix,dumpId,rawHeapDumps){this.model_=model;this.processObjectTypeNameMap_=processObjectTypeNameMap;this.idPrefix_=idPrefix;this.processMemoryDump_=processMemoryDump;this.pid_=this.processMemoryDump_.process.pid;this.dumpId_=dumpId;this.rawHeapDumps_=rawHeapDumps;}
+LegacyHeapDumpTraceEventImporter.prototype={parseRawHeapDump(rawHeapDump,allocatorName){const model=this.model_;const processMemoryDump=this.processMemoryDump_;const heapDump=new tr.model.HeapDump(processMemoryDump,allocatorName);const entries=rawHeapDump.entries;if(entries===undefined||entries.length===0){this.model_.importWarning({type:'memory_dump_parse_error',message:'No heap entries in a '+allocatorName+' heap dump for PID='+this.pid_+' and dump ID='+this.dumpId_+'.'});return undefined;}
+const isOldFormat=entries[0].bt===undefined;if(!isOldFormat&&this.processObjectTypeNameMap_===undefined){return undefined;}
+for(let i=0;i<entries.length;i++){const entry=entries[i];const size=parseInt(entry.size,16);const leafStackFrameIndex=entry.bt;let leafStackFrame;if(isOldFormat){if(leafStackFrameIndex===undefined){leafStackFrame=undefined;}else{let leafStackFrameId=this.idPrefix_+leafStackFrameIndex;if(leafStackFrameIndex===''){leafStackFrame=undefined;}else{leafStackFrame=model.stackFrames[leafStackFrameId];if(leafStackFrame===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing leaf stack frame (ID '+
+leafStackFrameId+') of heap entry '+i+' (size '+
+size+') in a '+allocatorName+' heap dump for PID='+this.pid_+'.'});continue;}}
+leafStackFrameId+=':self';if(model.stackFrames[leafStackFrameId]!==undefined){leafStackFrame=model.stackFrames[leafStackFrameId];}else{leafStackFrame=new tr.model.StackFrame(leafStackFrame,leafStackFrameId,'<self>',undefined);model.addStackFrame(leafStackFrame);}}}else{if(leafStackFrameIndex===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing stack frame ID of heap entry '+i+' (size '+size+') in a '+allocatorName+' heap dump for PID='+this.pid_+'.'});continue;}
+const leafStackFrameId=this.idPrefix_+leafStackFrameIndex;if(leafStackFrameIndex===''){leafStackFrame=undefined;}else{leafStackFrame=model.stackFrames[leafStackFrameId];if(leafStackFrame===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing leaf stack frame (ID '+leafStackFrameId+') of heap entry '+i+' (size '+size+') in a '+
+allocatorName+' heap dump for PID='+this.pid_+'.'});continue;}}}
+const objectTypeId=entry.type;let objectTypeName;if(objectTypeId===undefined){objectTypeName=undefined;}else if(this.processObjectTypeNameMap_===undefined){continue;}else{objectTypeName=this.processObjectTypeNameMap_[objectTypeId];if(objectTypeName===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing object type name (ID '+objectTypeId+') of heap entry '+i+' (size '+size+') in a '+
+allocatorName+' heap dump for PID='+this.pid_+'.'});continue;}}
+const count=entry.count===undefined?undefined:parseInt(entry.count,16);heapDump.addEntry(leafStackFrame,objectTypeName,size,count);}
+return heapDump;},parse(){const heapDumps={};for(const allocatorName in this.rawHeapDumps_){const rawHeapDump=this.rawHeapDumps_[allocatorName];const heapDump=this.parseRawHeapDump(rawHeapDump,allocatorName);if(heapDump!==undefined&&heapDump.entries.length>0){heapDumps[allocatorName]=heapDump;}}
+return heapDumps;},};return{LegacyHeapDumpTraceEventImporter,};});'use strict';if(tr.isHeadless){global.window={};}
+(function(window,Object,Array,Error,JSON,undefined){var partialComplete=varArgs(function(fn,args){var numBoundArgs=args.length;return varArgs(function(callArgs){for(var i=0;i<callArgs.length;i++){args[numBoundArgs+i]=callArgs[i];}
+args.length=numBoundArgs+callArgs.length;return fn.apply(this,args);});}),compose=varArgs(function(fns){var fnsList=arrayAsList(fns);function next(params,curFn){return[apply(params,curFn)];}
+return varArgs(function(startParams){return foldR(next,startParams,fnsList)[0];});});function compose2(f1,f2){return function(){return f1.call(this,f2.apply(this,arguments));}}
+function attr(key){return function(o){return o[key];};}
+var lazyUnion=varArgs(function(fns){return varArgs(function(params){var maybeValue;for(var i=0;i<len(fns);i++){maybeValue=apply(params,fns[i]);if(maybeValue){return maybeValue;}}});});function apply(args,fn){return fn.apply(undefined,args);}
+function varArgs(fn){var numberOfFixedArguments=fn.length-1,slice=Array.prototype.slice;if(numberOfFixedArguments==0){return function(){return fn.call(this,slice.call(arguments));}}else if(numberOfFixedArguments==1){return function(){return fn.call(this,arguments[0],slice.call(arguments,1));}}
+var argsHolder=Array(fn.length);return function(){for(var i=0;i<numberOfFixedArguments;i++){argsHolder[i]=arguments[i];}
+argsHolder[numberOfFixedArguments]=slice.call(arguments,numberOfFixedArguments);return fn.apply(this,argsHolder);}}
+function flip(fn){return function(a,b){return fn(b,a);}}
+function lazyIntersection(fn1,fn2){return function(param){return fn1(param)&&fn2(param);};}
+function noop(){}
+function always(){return true}
+function functor(val){return function(){return val;}}
+function isOfType(T,maybeSomething){return maybeSomething&&maybeSomething.constructor===T;}
+var len=attr('length'),isString=partialComplete(isOfType,String);function defined(value){return value!==undefined;}
+function hasAllProperties(fieldList,o){return(o instanceof Object)&&all(function(field){return(field in o);},fieldList);}
+function cons(x,xs){return[x,xs];}
+var emptyList=null,head=attr(0),tail=attr(1);function arrayAsList(inputArray){return reverseList(inputArray.reduce(flip(cons),emptyList));}
+var list=varArgs(arrayAsList);function listAsArray(list){return foldR(function(arraySoFar,listItem){arraySoFar.unshift(listItem);return arraySoFar;},[],list);}
+function map(fn,list){return list?cons(fn(head(list)),map(fn,tail(list))):emptyList;}
+function foldR(fn,startValue,list){return list?fn(foldR(fn,startValue,tail(list)),head(list)):startValue;}
+function foldR1(fn,list){return tail(list)?fn(foldR1(fn,tail(list)),head(list)):head(list);}
+function without(list,test,removedFn){return withoutInner(list,removedFn||noop);function withoutInner(subList,removedFn){return subList?(test(head(subList))?(removedFn(head(subList)),tail(subList)):cons(head(subList),withoutInner(tail(subList),removedFn))):emptyList;}}
+function all(fn,list){return!list||(fn(head(list))&&all(fn,tail(list)));}
+function applyEach(fnList,args){if(fnList){head(fnList).apply(null,args);applyEach(tail(fnList),args);}}
+function reverseList(list){function reverseInner(list,reversedAlready){if(!list){return reversedAlready;}
+return reverseInner(tail(list),cons(head(list),reversedAlready))}
+return reverseInner(list,emptyList);}
+function first(test,list){return list&&(test(head(list))?head(list):first(test,tail(list)));}
+function clarinet(eventBus){"use strict";var
+emitSaxKey=eventBus(SAX_KEY).emit,emitValueOpen=eventBus(SAX_VALUE_OPEN).emit,emitValueClose=eventBus(SAX_VALUE_CLOSE).emit,emitFail=eventBus(FAIL_EVENT).emit,MAX_BUFFER_LENGTH=64*1024,stringTokenPattern=/[\\"\n]/g,_n=0,BEGIN=_n++,VALUE=_n++,OPEN_OBJECT=_n++,CLOSE_OBJECT=_n++,OPEN_ARRAY=_n++,CLOSE_ARRAY=_n++,STRING=_n++,OPEN_KEY=_n++,CLOSE_KEY=_n++,TRUE=_n++,TRUE2=_n++,TRUE3=_n++,FALSE=_n++,FALSE2=_n++,FALSE3=_n++,FALSE4=_n++,NULL=_n++,NULL2=_n++,NULL3=_n++,NUMBER_DECIMAL_POINT=_n++,NUMBER_DIGIT=_n,bufferCheckPosition=MAX_BUFFER_LENGTH,latestError,c,p,textNode=undefined,numberNode="",slashed=false,closed=false,state=BEGIN,stack=[],unicodeS=null,unicodeI=0,depth=0,position=0,column=0,line=1;function checkBufferLength(){var maxActual=0;if(textNode!==undefined&&textNode.length>MAX_BUFFER_LENGTH){emitError("Max buffer length exceeded: textNode");maxActual=Math.max(maxActual,textNode.length);}
+if(numberNode.length>MAX_BUFFER_LENGTH){emitError("Max buffer length exceeded: numberNode");maxActual=Math.max(maxActual,numberNode.length);}
+bufferCheckPosition=(MAX_BUFFER_LENGTH-maxActual)
++position;}
+eventBus(STREAM_DATA).on(handleData);eventBus(STREAM_END).on(handleStreamEnd);function emitError(errorString){if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+latestError=Error(errorString+"\nLn: "+line+"\nCol: "+column+"\nChr: "+c);emitFail(errorReport(undefined,undefined,latestError));}
+function handleStreamEnd(){if(state==BEGIN){emitValueOpen({});emitValueClose();closed=true;return;}
+if(state!==VALUE||depth!==0)
+emitError("Unexpected end");if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+closed=true;}
+function whitespace(c){return c=='\r'||c=='\n'||c==' '||c=='\t';}
+function handleData(chunk){if(latestError)
+return;if(closed){return emitError("Cannot write after close");}
+var i=0;c=chunk[0];while(c){p=c;c=chunk[i++];if(!c)break;position++;if(c=="\n"){line++;column=0;}else column++;switch(state){case BEGIN:if(c==="{")state=OPEN_OBJECT;else if(c==="[")state=OPEN_ARRAY;else if(!whitespace(c))
+return emitError("Non-whitespace before {[.");continue;case OPEN_KEY:case OPEN_OBJECT:if(whitespace(c))continue;if(state===OPEN_KEY)stack.push(CLOSE_KEY);else{if(c==='}'){emitValueOpen({});emitValueClose();state=stack.pop()||VALUE;continue;}else stack.push(CLOSE_OBJECT);}
+if(c==='"')
+state=STRING;else
+return emitError("Malformed object key should start with \" ");continue;case CLOSE_KEY:case CLOSE_OBJECT:if(whitespace(c))continue;if(c===':'){if(state===CLOSE_OBJECT){stack.push(CLOSE_OBJECT);if(textNode!==undefined){emitValueOpen({});emitSaxKey(textNode);textNode=undefined;}
+depth++;}else{if(textNode!==undefined){emitSaxKey(textNode);textNode=undefined;}}
+state=VALUE;}else if(c==='}'){if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+emitValueClose();depth--;state=stack.pop()||VALUE;}else if(c===','){if(state===CLOSE_OBJECT)
+stack.push(CLOSE_OBJECT);if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+state=OPEN_KEY;}else
+return emitError('Bad object');continue;case OPEN_ARRAY:case VALUE:if(whitespace(c))continue;if(state===OPEN_ARRAY){emitValueOpen([]);depth++;state=VALUE;if(c===']'){emitValueClose();depth--;state=stack.pop()||VALUE;continue;}else{stack.push(CLOSE_ARRAY);}}
+if(c==='"')state=STRING;else if(c==='{')state=OPEN_OBJECT;else if(c==='[')state=OPEN_ARRAY;else if(c==='t')state=TRUE;else if(c==='f')state=FALSE;else if(c==='n')state=NULL;else if(c==='-'){numberNode+=c;}else if(c==='0'){numberNode+=c;state=NUMBER_DIGIT;}else if('123456789'.indexOf(c)!==-1){numberNode+=c;state=NUMBER_DIGIT;}else
+return emitError("Bad value");continue;case CLOSE_ARRAY:if(c===','){stack.push(CLOSE_ARRAY);if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+state=VALUE;}else if(c===']'){if(textNode!==undefined){emitValueOpen(textNode);emitValueClose();textNode=undefined;}
+emitValueClose();depth--;state=stack.pop()||VALUE;}else if(whitespace(c))
+continue;else
+return emitError('Bad array');continue;case STRING:if(textNode===undefined){textNode="";}
+var starti=i-1;STRING_BIGLOOP:while(true){while(unicodeI>0){unicodeS+=c;c=chunk.charAt(i++);if(unicodeI===4){textNode+=String.fromCharCode(parseInt(unicodeS,16));unicodeI=0;starti=i-1;}else{unicodeI++;}
+if(!c)break STRING_BIGLOOP;}
+if(c==='"'&&!slashed){state=stack.pop()||VALUE;textNode+=chunk.substring(starti,i-1);break;}
+if(c==='\\'&&!slashed){slashed=true;textNode+=chunk.substring(starti,i-1);c=chunk.charAt(i++);if(!c)break;}
+if(slashed){slashed=false;if(c==='n'){textNode+='\n';}
+else if(c==='r'){textNode+='\r';}
+else if(c==='t'){textNode+='\t';}
+else if(c==='f'){textNode+='\f';}
+else if(c==='b'){textNode+='\b';}
+else if(c==='u'){unicodeI=1;unicodeS='';}else{textNode+=c;}
+c=chunk.charAt(i++);starti=i-1;if(!c)break;else continue;}
+stringTokenPattern.lastIndex=i;var reResult=stringTokenPattern.exec(chunk);if(!reResult){i=chunk.length+1;textNode+=chunk.substring(starti,i-1);break;}
+i=reResult.index+1;c=chunk.charAt(reResult.index);if(!c){textNode+=chunk.substring(starti,i-1);break;}}
+continue;case TRUE:if(!c)continue;if(c==='r')state=TRUE2;else
+return emitError('Invalid true started with t'+c);continue;case TRUE2:if(!c)continue;if(c==='u')state=TRUE3;else
+return emitError('Invalid true started with tr'+c);continue;case TRUE3:if(!c)continue;if(c==='e'){emitValueOpen(true);emitValueClose();state=stack.pop()||VALUE;}else
+return emitError('Invalid true started with tru'+c);continue;case FALSE:if(!c)continue;if(c==='a')state=FALSE2;else
+return emitError('Invalid false started with f'+c);continue;case FALSE2:if(!c)continue;if(c==='l')state=FALSE3;else
+return emitError('Invalid false started with fa'+c);continue;case FALSE3:if(!c)continue;if(c==='s')state=FALSE4;else
+return emitError('Invalid false started with fal'+c);continue;case FALSE4:if(!c)continue;if(c==='e'){emitValueOpen(false);emitValueClose();state=stack.pop()||VALUE;}else
+return emitError('Invalid false started with fals'+c);continue;case NULL:if(!c)continue;if(c==='u')state=NULL2;else
+return emitError('Invalid null started with n'+c);continue;case NULL2:if(!c)continue;if(c==='l')state=NULL3;else
+return emitError('Invalid null started with nu'+c);continue;case NULL3:if(!c)continue;if(c==='l'){emitValueOpen(null);emitValueClose();state=stack.pop()||VALUE;}else
+return emitError('Invalid null started with nul'+c);continue;case NUMBER_DECIMAL_POINT:if(c==='.'){numberNode+=c;state=NUMBER_DIGIT;}else
+return emitError('Leading zero not followed by .');continue;case NUMBER_DIGIT:if('0123456789'.indexOf(c)!==-1)numberNode+=c;else if(c==='.'){if(numberNode.indexOf('.')!==-1)
+return emitError('Invalid number has two dots');numberNode+=c;}else if(c==='e'||c==='E'){if(numberNode.indexOf('e')!==-1||numberNode.indexOf('E')!==-1)
+return emitError('Invalid number has two exponential');numberNode+=c;}else if(c==="+"||c==="-"){if(!(p==='e'||p==='E'))
+return emitError('Invalid symbol in number');numberNode+=c;}else{if(numberNode){emitValueOpen(parseFloat(numberNode));emitValueClose();numberNode="";}
+i--;state=stack.pop()||VALUE;}
+continue;default:return emitError("Unknown state: "+state);}}
+if(position>=bufferCheckPosition)
+checkBufferLength();}}
+function ascentManager(oboeBus,handlers){"use strict";var listenerId={},ascent;function stateAfter(handler){return function(param){ascent=handler(ascent,param);}}
+for(var eventName in handlers){oboeBus(eventName).on(stateAfter(handlers[eventName]),listenerId);}
+oboeBus(NODE_SWAP).on(function(newNode){var oldHead=head(ascent),key=keyOf(oldHead),ancestors=tail(ascent),parentNode;if(ancestors){parentNode=nodeOf(head(ancestors));parentNode[key]=newNode;}});oboeBus(NODE_DROP).on(function(){var oldHead=head(ascent),key=keyOf(oldHead),ancestors=tail(ascent),parentNode;if(ancestors){parentNode=nodeOf(head(ancestors));delete parentNode[key];}});oboeBus(ABORTING).on(function(){for(var eventName in handlers){oboeBus(eventName).un(listenerId);}});}
+function parseResponseHeaders(headerStr){var headers={};headerStr&&headerStr.split('\u000d\u000a').forEach(function(headerPair){var index=headerPair.indexOf('\u003a\u0020');headers[headerPair.substring(0,index)]=headerPair.substring(index+2);});return headers;}
+function isCrossOrigin(pageLocation,ajaxHost){function defaultPort(protocol){return{'http:':80,'https:':443}[protocol];}
+function portOf(location){return location.port||defaultPort(location.protocol||pageLocation.protocol);}
+return!!((ajaxHost.protocol&&(ajaxHost.protocol!=pageLocation.protocol))||(ajaxHost.host&&(ajaxHost.host!=pageLocation.host))||(ajaxHost.host&&(portOf(ajaxHost)!=portOf(pageLocation))));}
+function parseUrlOrigin(url){var URL_HOST_PATTERN=/(\w+:)?(?:\/\/)([\w.-]+)?(?::(\d+))?\/?/,urlHostMatch=URL_HOST_PATTERN.exec(url)||[];return{protocol:urlHostMatch[1]||'',host:urlHostMatch[2]||'',port:urlHostMatch[3]||''};}
+function httpTransport(){return new XMLHttpRequest();}
+function streamingHttp(oboeBus,xhr,method,url,data,headers,withCredentials){"use strict";var emitStreamData=oboeBus(STREAM_DATA).emit,emitFail=oboeBus(FAIL_EVENT).emit,numberOfCharsAlreadyGivenToCallback=0,stillToSendStartEvent=true;oboeBus(ABORTING).on(function(){xhr.onreadystatechange=null;xhr.abort();});function handleProgress(){var textSoFar=xhr.responseText,newText=textSoFar.substr(numberOfCharsAlreadyGivenToCallback);if(newText){emitStreamData(newText);}
+numberOfCharsAlreadyGivenToCallback=len(textSoFar);}
+if('onprogress'in xhr){xhr.onprogress=handleProgress;}
+xhr.onreadystatechange=function(){function sendStartIfNotAlready(){try{stillToSendStartEvent&&oboeBus(HTTP_START).emit(xhr.status,parseResponseHeaders(xhr.getAllResponseHeaders()));stillToSendStartEvent=false;}catch(e){}}
+switch(xhr.readyState){case 2:case 3:return sendStartIfNotAlready();case 4:sendStartIfNotAlready();var successful=String(xhr.status)[0]==2;if(successful){handleProgress();oboeBus(STREAM_END).emit();}else{emitFail(errorReport(xhr.status,xhr.responseText));}}};try{xhr.open(method,url,true);for(var headerName in headers){xhr.setRequestHeader(headerName,headers[headerName]);}
+if(!isCrossOrigin(window.location,parseUrlOrigin(url))){xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');}
+xhr.withCredentials=withCredentials;xhr.send(data);}catch(e){window.setTimeout(partialComplete(emitFail,errorReport(undefined,undefined,e)),0);}}
+var jsonPathSyntax=(function(){var
+regexDescriptor=function regexDescriptor(regex){return regex.exec.bind(regex);},jsonPathClause=varArgs(function(componentRegexes){componentRegexes.unshift(/^/);return regexDescriptor(RegExp(componentRegexes.map(attr('source')).join('')));}),possiblyCapturing=/(\$?)/,namedNode=/([\w-_]+|\*)/,namePlaceholder=/()/,nodeInArrayNotation=/\["([^"]+)"\]/,numberedNodeInArrayNotation=/\[(\d+|\*)\]/,fieldList=/{([\w ]*?)}/,optionalFieldList=/(?:{([\w ]*?)})?/
+,jsonPathNamedNodeInObjectNotation=jsonPathClause(possiblyCapturing,namedNode,optionalFieldList),jsonPathNamedNodeInArrayNotation=jsonPathClause(possiblyCapturing,nodeInArrayNotation,optionalFieldList),jsonPathNumberedNodeInArrayNotation=jsonPathClause(possiblyCapturing,numberedNodeInArrayNotation,optionalFieldList),jsonPathPureDuckTyping=jsonPathClause(possiblyCapturing,namePlaceholder,fieldList),jsonPathDoubleDot=jsonPathClause(/\.\./),jsonPathDot=jsonPathClause(/\./),jsonPathBang=jsonPathClause(possiblyCapturing,/!/),emptyString=jsonPathClause(/$/);return function(fn){return fn(lazyUnion(jsonPathNamedNodeInObjectNotation,jsonPathNamedNodeInArrayNotation,jsonPathNumberedNodeInArrayNotation,jsonPathPureDuckTyping),jsonPathDoubleDot,jsonPathDot,jsonPathBang,emptyString);};}());function namedNode(key,node){return{key:key,node:node};}
+var keyOf=attr('key');var nodeOf=attr('node');var ROOT_PATH={};function incrementalContentBuilder(oboeBus){var emitNodeOpened=oboeBus(NODE_OPENED).emit,emitNodeClosed=oboeBus(NODE_CLOSED).emit,emitRootOpened=oboeBus(ROOT_PATH_FOUND).emit,emitRootClosed=oboeBus(ROOT_NODE_FOUND).emit;function arrayIndicesAreKeys(possiblyInconsistentAscent,newDeepestNode){var parentNode=nodeOf(head(possiblyInconsistentAscent));return isOfType(Array,parentNode)?keyFound(possiblyInconsistentAscent,len(parentNode),newDeepestNode):possiblyInconsistentAscent;}
+function nodeOpened(ascent,newDeepestNode){if(!ascent){emitRootOpened(newDeepestNode);return keyFound(ascent,ROOT_PATH,newDeepestNode);}
+var arrayConsistentAscent=arrayIndicesAreKeys(ascent,newDeepestNode),ancestorBranches=tail(arrayConsistentAscent),previouslyUnmappedName=keyOf(head(arrayConsistentAscent));appendBuiltContent(ancestorBranches,previouslyUnmappedName,newDeepestNode);return cons(namedNode(previouslyUnmappedName,newDeepestNode),ancestorBranches);}
+function appendBuiltContent(ancestorBranches,key,node){nodeOf(head(ancestorBranches))[key]=node;}
+function keyFound(ascent,newDeepestName,maybeNewDeepestNode){if(ascent){appendBuiltContent(ascent,newDeepestName,maybeNewDeepestNode);}
+var ascentWithNewPath=cons(namedNode(newDeepestName,maybeNewDeepestNode),ascent);emitNodeOpened(ascentWithNewPath);return ascentWithNewPath;}
+function nodeClosed(ascent){emitNodeClosed(ascent);return tail(ascent)||emitRootClosed(nodeOf(head(ascent)));}
+var contentBuilderHandlers={};contentBuilderHandlers[SAX_VALUE_OPEN]=nodeOpened;contentBuilderHandlers[SAX_VALUE_CLOSE]=nodeClosed;contentBuilderHandlers[SAX_KEY]=keyFound;return contentBuilderHandlers;}
+var jsonPathCompiler=jsonPathSyntax(function(pathNodeSyntax,doubleDotSyntax,dotSyntax,bangSyntax,emptySyntax){var CAPTURING_INDEX=1;var NAME_INDEX=2;var FIELD_LIST_INDEX=3;var headKey=compose2(keyOf,head),headNode=compose2(nodeOf,head);function nameClause(previousExpr,detection){var name=detection[NAME_INDEX],matchesName=(!name||name=='*')?always:function(ascent){return headKey(ascent)==name};return lazyIntersection(matchesName,previousExpr);}
+function duckTypeClause(previousExpr,detection){var fieldListStr=detection[FIELD_LIST_INDEX];if(!fieldListStr)
+return previousExpr;var hasAllrequiredFields=partialComplete(hasAllProperties,arrayAsList(fieldListStr.split(/\W+/))),isMatch=compose2(hasAllrequiredFields,headNode);return lazyIntersection(isMatch,previousExpr);}
+function capture(previousExpr,detection){var capturing=!!detection[CAPTURING_INDEX];if(!capturing)
+return previousExpr;return lazyIntersection(previousExpr,head);}
+function skip1(previousExpr){if(previousExpr==always){return always;}
+function notAtRoot(ascent){return headKey(ascent)!=ROOT_PATH;}
+return lazyIntersection(notAtRoot,compose2(previousExpr,tail));}
+function skipMany(previousExpr){if(previousExpr==always){return always;}
+var
+terminalCaseWhenArrivingAtRoot=rootExpr(),terminalCaseWhenPreviousExpressionIsSatisfied=previousExpr,recursiveCase=skip1(function(ascent){return cases(ascent);}),cases=lazyUnion(terminalCaseWhenArrivingAtRoot,terminalCaseWhenPreviousExpressionIsSatisfied,recursiveCase);return cases;}
+function rootExpr(){return function(ascent){return headKey(ascent)==ROOT_PATH;};}
+function statementExpr(lastClause){return function(ascent){var exprMatch=lastClause(ascent);return exprMatch===true?head(ascent):exprMatch;};}
+function expressionsReader(exprs,parserGeneratedSoFar,detection){return foldR(function(parserGeneratedSoFar,expr){return expr(parserGeneratedSoFar,detection);},parserGeneratedSoFar,exprs);}
+function generateClauseReaderIfTokenFound(tokenDetector,clauseEvaluatorGenerators,jsonPath,parserGeneratedSoFar,onSuccess){var detected=tokenDetector(jsonPath);if(detected){var compiledParser=expressionsReader(clauseEvaluatorGenerators,parserGeneratedSoFar,detected),remainingUnparsedJsonPath=jsonPath.substr(len(detected[0]));return onSuccess(remainingUnparsedJsonPath,compiledParser);}}
+function clauseMatcher(tokenDetector,exprs){return partialComplete(generateClauseReaderIfTokenFound,tokenDetector,exprs);}
+var clauseForJsonPath=lazyUnion(clauseMatcher(pathNodeSyntax,list(capture,duckTypeClause,nameClause,skip1)),clauseMatcher(doubleDotSyntax,list(skipMany)),clauseMatcher(dotSyntax,list()),clauseMatcher(bangSyntax,list(capture,rootExpr)),clauseMatcher(emptySyntax,list(statementExpr)),function(jsonPath){throw Error('"'+jsonPath+'" could not be tokenised')});function returnFoundParser(_remainingJsonPath,compiledParser){return compiledParser}
+function compileJsonPathToFunction(uncompiledJsonPath,parserGeneratedSoFar){var onFind=uncompiledJsonPath?compileJsonPathToFunction:returnFoundParser;return clauseForJsonPath(uncompiledJsonPath,parserGeneratedSoFar,onFind);}
+return function(jsonPath){try{return compileJsonPathToFunction(jsonPath,always);}catch(e){throw Error('Could not compile "'+jsonPath+'" because '+e.message);}}});function singleEventPubSub(eventType,newListener,removeListener){var listenerTupleList,listenerList;function hasId(id){return function(tuple){return tuple.id==id;};}
+return{on:function(listener,listenerId){var tuple={listener:listener,id:listenerId||listener};if(newListener){newListener.emit(eventType,listener,tuple.id);}
+listenerTupleList=cons(tuple,listenerTupleList);listenerList=cons(listener,listenerList);return this;},emit:function(){applyEach(listenerList,arguments);},un:function(listenerId){var removed;listenerTupleList=without(listenerTupleList,hasId(listenerId),function(tuple){removed=tuple;});if(removed){listenerList=without(listenerList,function(listener){return listener==removed.listener;});if(removeListener){removeListener.emit(eventType,removed.listener,removed.id);}}},listeners:function(){return listenerList;},hasListener:function(listenerId){var test=listenerId?hasId(listenerId):always;return defined(first(test,listenerTupleList));}};}
+function pubSub(){var singles={},newListener=newSingle('newListener'),removeListener=newSingle('removeListener');function newSingle(eventName){return singles[eventName]=singleEventPubSub(eventName,newListener,removeListener);}
+function pubSubInstance(eventName){return singles[eventName]||newSingle(eventName);}
+['emit','on','un'].forEach(function(methodName){pubSubInstance[methodName]=varArgs(function(eventName,parameters){apply(parameters,pubSubInstance(eventName)[methodName]);});});return pubSubInstance;}
+var
+_S=1,NODE_OPENED=_S++,NODE_CLOSED=_S++,NODE_SWAP=_S++,NODE_DROP=_S++,FAIL_EVENT='fail',ROOT_NODE_FOUND=_S++,ROOT_PATH_FOUND=_S++,HTTP_START='start',STREAM_DATA='data',STREAM_END='end',ABORTING=_S++,SAX_KEY=_S++,SAX_VALUE_OPEN=_S++,SAX_VALUE_CLOSE=_S++;function errorReport(statusCode,body,error){try{var jsonBody=JSON.parse(body);}catch(e){}
+return{statusCode:statusCode,body:body,jsonBody:jsonBody,thrown:error};}
+function patternAdapter(oboeBus,jsonPathCompiler){var predicateEventMap={node:oboeBus(NODE_CLOSED),path:oboeBus(NODE_OPENED)};function emitMatchingNode(emitMatch,node,ascent){var descent=reverseList(ascent);emitMatch(node,listAsArray(tail(map(keyOf,descent))),listAsArray(map(nodeOf,descent)));}
+function addUnderlyingListener(fullEventName,predicateEvent,compiledJsonPath){var emitMatch=oboeBus(fullEventName).emit;predicateEvent.on(function(ascent){var maybeMatchingMapping=compiledJsonPath(ascent);if(maybeMatchingMapping!==false){emitMatchingNode(emitMatch,nodeOf(maybeMatchingMapping),ascent);}},fullEventName);oboeBus('removeListener').on(function(removedEventName){if(removedEventName==fullEventName){if(!oboeBus(removedEventName).listeners()){predicateEvent.un(fullEventName);}}});}
+oboeBus('newListener').on(function(fullEventName){var match=/(node|path):(.*)/.exec(fullEventName);if(match){var predicateEvent=predicateEventMap[match[1]];if(!predicateEvent.hasListener(fullEventName)){addUnderlyingListener(fullEventName,predicateEvent,jsonPathCompiler(match[2]));}}})}
+function instanceApi(oboeBus,contentSource){var oboeApi,fullyQualifiedNamePattern=/^(node|path):./,rootNodeFinishedEvent=oboeBus(ROOT_NODE_FOUND),emitNodeDrop=oboeBus(NODE_DROP).emit,emitNodeSwap=oboeBus(NODE_SWAP).emit,addListener=varArgs(function(eventId,parameters){if(oboeApi[eventId]){apply(parameters,oboeApi[eventId]);}else{var event=oboeBus(eventId),listener=parameters[0];if(fullyQualifiedNamePattern.test(eventId)){addForgettableCallback(event,listener);}else{event.on(listener);}}
+return oboeApi;}),removeListener=function(eventId,p2,p3){if(eventId=='done'){rootNodeFinishedEvent.un(p2);}else if(eventId=='node'||eventId=='path'){oboeBus.un(eventId+':'+p2,p3);}else{var listener=p2;oboeBus(eventId).un(listener);}
+return oboeApi;};function addProtectedCallback(eventName,callback){oboeBus(eventName).on(protectedCallback(callback),callback);return oboeApi;}
+function addForgettableCallback(event,callback,listenerId){listenerId=listenerId||callback;var safeCallback=protectedCallback(callback);event.on(function(){var discard=false;oboeApi.forget=function(){discard=true;};apply(arguments,safeCallback);delete oboeApi.forget;if(discard){event.un(listenerId);}},listenerId);return oboeApi;}
+function protectedCallback(callback){return function(){try{return callback.apply(oboeApi,arguments);}catch(e){setTimeout(function(){throw new Error(e.message);});}}}
+function fullyQualifiedPatternMatchEvent(type,pattern){return oboeBus(type+':'+pattern);}
+function wrapCallbackToSwapNodeIfSomethingReturned(callback){return function(){var returnValueFromCallback=callback.apply(this,arguments);if(defined(returnValueFromCallback)){if(returnValueFromCallback==oboe.drop){emitNodeDrop();}else{emitNodeSwap(returnValueFromCallback);}}}}
+function addSingleNodeOrPathListener(eventId,pattern,callback){var effectiveCallback;if(eventId=='node'){effectiveCallback=wrapCallbackToSwapNodeIfSomethingReturned(callback);}else{effectiveCallback=callback;}
+addForgettableCallback(fullyQualifiedPatternMatchEvent(eventId,pattern),effectiveCallback,callback);}
+function addMultipleNodeOrPathListeners(eventId,listenerMap){for(var pattern in listenerMap){addSingleNodeOrPathListener(eventId,pattern,listenerMap[pattern]);}}
+function addNodeOrPathListenerApi(eventId,jsonPathOrListenerMap,callback){if(isString(jsonPathOrListenerMap)){addSingleNodeOrPathListener(eventId,jsonPathOrListenerMap,callback);}else{addMultipleNodeOrPathListeners(eventId,jsonPathOrListenerMap);}
+return oboeApi;}
+oboeBus(ROOT_PATH_FOUND).on(function(rootNode){oboeApi.root=functor(rootNode);});oboeBus(HTTP_START).on(function(_statusCode,headers){oboeApi.header=function(name){return name?headers[name]:headers;}});return oboeApi={on:addListener,addListener:addListener,removeListener:removeListener,emit:oboeBus.emit,node:partialComplete(addNodeOrPathListenerApi,'node'),path:partialComplete(addNodeOrPathListenerApi,'path'),done:partialComplete(addForgettableCallback,rootNodeFinishedEvent),start:partialComplete(addProtectedCallback,HTTP_START),fail:oboeBus(FAIL_EVENT).on,abort:oboeBus(ABORTING).emit,write:oboeBus(STREAM_DATA).emit,finish:oboeBus(STREAM_END).emit,header:noop,root:noop,source:contentSource};}
+function wire(httpMethodName,contentSource,body,headers,withCredentials){var oboeBus=pubSub();if(contentSource){streamingHttp(oboeBus,httpTransport(),httpMethodName,contentSource,body,headers,withCredentials);}
+clarinet(oboeBus);ascentManager(oboeBus,incrementalContentBuilder(oboeBus));patternAdapter(oboeBus,jsonPathCompiler);return instanceApi(oboeBus,contentSource);}
+function applyDefaults(passthrough,url,httpMethodName,body,headers,withCredentials,cached){headers=headers?JSON.parse(JSON.stringify(headers)):{};if(body){if(!isString(body)){body=JSON.stringify(body);headers['Content-Type']=headers['Content-Type']||'application/json';}}else{body=null;}
+function modifiedUrl(baseUrl,cached){if(cached===false){if(baseUrl.indexOf('?')==-1){baseUrl+='?';}else{baseUrl+='&';}
+baseUrl+='_='+new Date().getTime();}
+return baseUrl;}
+return passthrough(httpMethodName||'GET',modifiedUrl(url,cached),body,headers,withCredentials||false);}
+function oboe(arg1){var nodeStreamMethodNames=list('resume','pause','pipe'),isStream=partialComplete(hasAllProperties,nodeStreamMethodNames);if(arg1){if(isStream(arg1)||isString(arg1)){return applyDefaults(wire,arg1);}else{return applyDefaults(wire,arg1.url,arg1.method,arg1.body,arg1.headers,arg1.withCredentials,arg1.cached);}}else{return wire();}}
+oboe.drop=function(){return oboe.drop;};if(typeof define==="function"&&define.amd){define("oboe",[],function(){return oboe;});}else if(typeof exports==='object'){module.exports=oboe;}else{window.oboe=oboe;}})((function(){try{return window;}catch(e){return self;}}()),Object,Array,Error,JSON);'use strict';if(tr.isVinn){global.oboe=global.window.oboe;global.window=undefined;}else if(tr.isNode){global.window=undefined;const path=HTMLImportsLoader.hrefToAbsolutePath('/oboe/dist/oboe-node.js');global.oboe=require(path);}'use strict';tr.exportTo('tr.e.importer',function(){const STRING_ID_SUFFIX='_sid';const PLURAL_STRING_ID_SUFFIX='_sids';function isStringReference(s){return s.endsWith(STRING_ID_SUFFIX)||s.endsWith(PLURAL_STRING_ID_SUFFIX);}
+function getStringReferenceName(name){if(name.endsWith(PLURAL_STRING_ID_SUFFIX)){return name.slice(0,-PLURAL_STRING_ID_SUFFIX.length);}
+return name.slice(0,-STRING_ID_SUFFIX.length);}
+function deferenceStrings(idToString,o){const clone=Object.assign({},o);for(const[key,value]of Object.entries(clone)){if(isStringReference(key)){const name=getStringReferenceName(key);clone[name]=idToString(value);}}
+return clone;}
+function singularize(word){if(word.endsWith('s')){return word.slice(0,-1);}
+return word;}
+function getMetadataPairs(dataJson){const isMetadata=v=>typeof v!=='object'||Array.isArray(v);const pairs=Object.entries(dataJson);const metadataPairs=pairs.filter(([_,v])=>isMetadata(v));return metadataPairs;}
+function getGroupPairs(dataJson){const pairs=Object.entries(dataJson);const nonMapPairs=pairs.filter(([k,_])=>k!=='maps');const groupPairs=nonMapPairs.filter(([_,v])=>typeof v==='object');return groupPairs;}
+function createMap(mapJson){const map=new Map();for(const entry of mapJson){if(entry.id===undefined){throw new Error('Missing required key "id" in streaming event.');}
+map.set(entry.id,entry);}
+return map;}
+function createMaps(mapsJson){const maps=new Map();for(const[name,mapJson]of Object.entries(mapsJson)){maps.set(name,createMap(mapJson));}
+return maps;}
+function createGroup(groupJson,opt_startTime){const entries=[];const n=Object.values(groupJson)[0].length;for(let i=0;i<n;i++){const entry={};for(const name in groupJson){entry[name]=groupJson[name][i];}
+entries.push(entry);}
+const timeDelta=groupJson.timeDelta;if(opt_startTime===undefined&&timeDelta!==undefined){throw new Error('Missing required key "startTime" in streaming event.');}
+if(opt_startTime){let delta=0;for(const entry of entries){delta+=entry.timeDelta?entry.timeDelta:0;entry.time=opt_startTime+delta;}}
+return entries;}
+function createGroups(groupsJson,opt_startTime){const groups=new Map();for(const[name,groupJson]of Object.entries(groupsJson)){groups.set(name,createGroup(groupJson,opt_startTime));}
+return groups;}
+function createMetadata(metadataPairs){const metadata=new Map();for(const[name,value]of metadataPairs){metadata.set(name,value);}
+if(metadata.get('version')===undefined){throw new Error('Missing required key "version" in streaming event.');}
+return metadata;}
+class ProfilingDictionaryReader{constructor(opt_metadata,opt_maps,opt_groups,opt_parent){this.metadata=opt_metadata||new Map();this.maps=opt_maps||new Map();this.groups=opt_groups||new Map();this.parent_=opt_parent||undefined;this.inflated_=undefined;this.raw_=undefined;this.boundGetString_=this.getString.bind(this);this.deferenceStrings_=o=>deferenceStrings(this.boundGetString_,o);}
+static empty(){return new ProfilingDictionaryReader();}
+get parent(){return this.parent_;}
+get raw(){if(this.raw_)return this.raw_;this.raw_={};for(const[name,group]of this.groups.entries()){this.raw_[name]=group;}
+return this.raw_;}
+get inflated(){if(this.inflated_)return this.inflated_;this.inflated_={};for(const[name,group]of this.groups.entries()){this.inflated_[name]=this.inflateGroup(group);}
+return this.inflated_;}
+getNewMap(name){return this.maps.get(name)||new Map();}
+getMapValue(mapName,id){let value=this.getNewMap(mapName).get(id);if(value===undefined&&this.parent){value=this.parent.getMapValue(mapName,id);}
+return value;}
+getString(id){const value=this.getMapValue('strings',id);if(value===undefined)return undefined;return value.string;}
+hasMap(name){if(this.maps.has(name))return true;if(this.parent===undefined)return false;return this.parent.hasMap(name);}
+inflateGroup(group){return group.map(this.inflateEntry.bind(this));}
+inflateEntry(entry){const inflatedEntry={};for(const[name,value]of Object.entries(entry)){let inflatedValue;if(this.hasMap(name)){const id=value;inflatedValue=this.deferenceStrings_(this.getMapValue(name,id));}else{inflatedValue=value;}
+inflatedEntry[singularize(name)]=inflatedValue;}
+return this.deferenceStrings_(inflatedEntry);}
+expandData(data){const mapsJson=data.maps||{};const groupsJson=data.allocators||{};const metadataPairs=getMetadataPairs(data);const metadata=createMetadata(metadataPairs);const opt_startTime=metadata.get('startTime');const maps=createMaps(mapsJson);const groups=createGroups(groupsJson,opt_startTime);return new ProfilingDictionaryReader(metadata,maps,groups,this);}
+expandEvent(event){return this.expandData(event.args.data);}}
+return{ProfilingDictionaryReader,singularize,deferenceStringsForTest:deferenceStrings,};});'use strict';tr.exportTo('tr.model.source_info',function(){function SourceInfo(file,opt_line,opt_column){this.file_=file;this.line_=opt_line||-1;this.column_=opt_column||-1;}
+SourceInfo.prototype={get file(){return this.file_;},get line(){return this.line_;},get column(){return this.column_;},get domain(){if(!this.file_)return undefined;const domain=this.file_.match(/(.*:\/\/[^:\/]*)/i);return domain?domain[1]:undefined;},toString(){let str='';if(this.file_){str+=this.file_;}
+if(this.line_>0){str+=':'+this.line_;}
+if(this.column_>0){str+=':'+this.column_;}
+return str;}};return{SourceInfo,};});'use strict';tr.exportTo('tr.model.source_info',function(){function JSSourceInfo(file,line,column,isNative,scriptId,state){tr.model.source_info.SourceInfo.call(this,file,line,column);this.isNative_=isNative;this.scriptId_=scriptId;this.state_=state;}
+JSSourceInfo.prototype={__proto__:tr.model.source_info.SourceInfo.prototype,get state(){return this.state_;},get isNative(){return this.isNative_;},get scriptId(){return this.scriptId_;},toString(){const str=this.isNative_?'[native v8] ':'';return str+
+tr.model.source_info.SourceInfo.prototype.toString.call(this);}};const JSSourceState={COMPILED:'compiled',OPTIMIZABLE:'optimizable',OPTIMIZED:'optimized',UNKNOWN:'unknown',};return{JSSourceInfo,JSSourceState,};});'use strict';tr.exportTo('tr.e.importer',function(){function TraceCodeEntry(address,size,name,scriptId){this.id_=tr.b.GUID.allocateSimple();this.address_=address;this.size_=size;const rePrefix=/^(\w*:)?([*~]?)(.*)$/m;const tokens=rePrefix.exec(name);const prefix=tokens[1];let state=tokens[2];const body=tokens[3];if(state==='*'){state=tr.model.source_info.JSSourceState.OPTIMIZED;}else if(state==='~'){state=tr.model.source_info.JSSourceState.OPTIMIZABLE;}else if(state===''){state=tr.model.source_info.JSSourceState.COMPILED;}else{state=tr.model.source_info.JSSourceState.UNKNOWN;}
+let rawName;let rawUrl;if(prefix==='Script:'){rawName='';rawUrl=body;}else{const spacePos=body.lastIndexOf(' ');rawName=spacePos!==-1?body.substr(0,spacePos):body;rawUrl=spacePos!==-1?body.substr(spacePos+1):'';}
+function splitLineAndColumn(url){const lineColumnRegEx=/(?::(\d+))?(?::(\d+))?$/;const lineColumnMatch=lineColumnRegEx.exec(url);let lineNumber;let columnNumber;if(typeof(lineColumnMatch[1])==='string'){lineNumber=parseInt(lineColumnMatch[1],10);lineNumber=isNaN(lineNumber)?undefined:lineNumber-1;}
+if(typeof(lineColumnMatch[2])==='string'){columnNumber=parseInt(lineColumnMatch[2],10);columnNumber=isNaN(columnNumber)?undefined:columnNumber-1;}
+return{url:url.substring(0,url.length-lineColumnMatch[0].length),lineNumber,columnNumber};}
+const nativeSuffix=' native';const isNative=rawName.endsWith(nativeSuffix);this.name_=isNative?rawName.slice(0,-nativeSuffix.length):rawName;const urlData=splitLineAndColumn(rawUrl);const url=urlData.url||'';const line=urlData.lineNumber||0;const column=urlData.columnNumber||0;this.sourceInfo_=new tr.model.source_info.JSSourceInfo(url,line,column,isNative,scriptId,state);}
+TraceCodeEntry.prototype={get id(){return this.id_;},get sourceInfo(){return this.sourceInfo_;},get name(){return this.name_;},set address(address){this.address_=address;},get address(){return this.address_;},set size(size){this.size_=size;},get size(){return this.size_;}};return{TraceCodeEntry,};});'use strict';tr.exportTo('tr.e.importer',function(){function TraceCodeMap(){this.banks_=new Map();}
+TraceCodeMap.prototype={addEntry(addressHex,size,name,scriptId){const entry=new tr.e.importer.TraceCodeEntry(this.getAddress_(addressHex),size,name,scriptId);this.addEntry_(addressHex,entry);},moveEntry(oldAddressHex,newAddressHex,size){const entry=this.getBank_(oldAddressHex).removeEntry(this.getAddress_(oldAddressHex));if(!entry)return;entry.address=this.getAddress_(newAddressHex);entry.size=size;this.addEntry_(newAddressHex,entry);},lookupEntry(addressHex){return this.getBank_(addressHex).lookupEntry(this.getAddress_(addressHex));},addEntry_(addressHex,entry){this.getBank_(addressHex).addEntry(entry);},getAddress_(addressHex){const bankSizeHexDigits=13;addressHex=addressHex.slice(2);return parseInt(addressHex.slice(-bankSizeHexDigits),16);},getBank_(addressHex){addressHex=addressHex.slice(2);const bankSizeHexDigits=13;const maxHexDigits=16;const bankName=addressHex.slice(-maxHexDigits,-bankSizeHexDigits);let bank=this.banks_.get(bankName);if(!bank){bank=new TraceCodeBank();this.banks_.set(bankName,bank);}
+return bank;}};function TraceCodeBank(){this.entries_=[];}
+TraceCodeBank.prototype={removeEntry(address){if(this.entries_.length===0)return undefined;const index=tr.b.findLowIndexInSortedArray(this.entries_,function(entry){return entry.address;},address);const entry=this.entries_[index];if(!entry||entry.address!==address)return undefined;this.entries_.splice(index,1);return entry;},lookupEntry(address){const index=tr.b.findFirstTrueIndexInSortedArray(this.entries_,e=>(address<e.address))-1;const entry=this.entries_[index];return entry&&address<entry.address+entry.size?entry:undefined;},addEntry(newEntry){if(this.entries_.length===0){this.entries_.push(newEntry);}
+const endAddress=newEntry.address+newEntry.size;const lastIndex=tr.b.findLowIndexInSortedArray(this.entries_,function(entry){return entry.address;},endAddress);let index;for(index=lastIndex-1;index>=0;--index){const entry=this.entries_[index];const entryEndAddress=entry.address+entry.size;if(entryEndAddress<=newEntry.address)break;}
+++index;this.entries_.splice(index,lastIndex-index,newEntry);}};return{TraceCodeMap,};});'use strict';tr.exportTo('tr.e.measure',function(){const AsyncSlice=tr.model.AsyncSlice;const MEASURE_NAME_REGEX=/([^\/:]+):(.*?)(?:\/([A-Za-z0-9+/]+=?=?))?$/;function MeasureAsyncSlice(){this.groupTitle_='Ungrouped Measure';const matched=MEASURE_NAME_REGEX.exec(arguments[1]);if(matched!==null){arguments[1]=matched[2];this.groupTitle_=matched[1];}
+AsyncSlice.apply(this,arguments);}
+MeasureAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){return this.groupTitle_;},get title(){return this.title_;},set title(title){this.title_=title;}};AsyncSlice.subTypes.register(MeasureAsyncSlice,{categoryParts:['blink.user_timing']});return{MEASURE_NAME_REGEX,MeasureAsyncSlice,};});'use strict';tr.exportTo('tr.importer',function(){function ContextProcessor(model){this.model_=model;this.activeContexts_=[];this.stackPerType_={};this.contextCache_={};this.contextSetCache_={};this.cachedEntryForActiveContexts_=undefined;this.seenSnapshots_={};}
+ContextProcessor.prototype={enterContext(contextType,scopedId){const newActiveContexts=[this.getOrCreateContext_(contextType,scopedId),];for(const oldContext of this.activeContexts_){if(oldContext.type===contextType){this.pushContext_(oldContext);}else{newActiveContexts.push(oldContext);}}
+this.activeContexts_=newActiveContexts;this.cachedEntryForActiveContexts_=undefined;},leaveContext(contextType,scopedId){this.leaveContextImpl_(context=>context.type===contextType&&context.snapshot.scope===scopedId.scope&&context.snapshot.idRef===scopedId.id);},destroyContext(scopedId){for(const stack of Object.values(this.stackPerType_)){let newLength=0;for(let i=0;i<stack.length;++i){if(stack[i].snapshot.scope!==scopedId.scope||stack[i].snapshot.idRef!==scopedId.id){stack[newLength++]=stack[i];}}
+stack.length=newLength;}
+this.leaveContextImpl_(context=>context.snapshot.scope===scopedId.scope&&context.snapshot.idRef===scopedId.id);},leaveContextImpl_(predicate){const newActiveContexts=[];for(const oldContext of this.activeContexts_){if(predicate(oldContext)){const previousContext=this.popContext_(oldContext.type);if(previousContext){newActiveContexts.push(previousContext);}}else{newActiveContexts.push(oldContext);}}
+this.activeContexts_=newActiveContexts;this.cachedEntryForActiveContexts_=undefined;},getOrCreateContext_(contextType,scopedId){const context={type:contextType,snapshot:{scope:scopedId.scope,idRef:scopedId.id}};const key=this.getContextKey_(context);if(key in this.contextCache_){return this.contextCache_[key];}
+this.contextCache_[key]=context;const snapshotKey=this.getSnapshotKey_(scopedId);this.seenSnapshots_[snapshotKey]=true;return context;},pushContext_(context){if(!(context.type in this.stackPerType_)){this.stackPerType_[context.type]=[];}
+this.stackPerType_[context.type].push(context);},popContext_(contextType){if(!(contextType in this.stackPerType_)){return undefined;}
+return this.stackPerType_[contextType].pop();},getContextKey_(context){return[context.type,context.snapshot.scope,context.snapshot.idRef].join('\x00');},getSnapshotKey_(scopedId){return[scopedId.scope,scopedId.idRef].join('\x00');},get activeContexts(){if(this.cachedEntryForActiveContexts_===undefined){let key=[];for(const context of this.activeContexts_){key.push(this.getContextKey_(context));}
+key.sort();key=key.join('\x00');if(key in this.contextSetCache_){this.cachedEntryForActiveContexts_=this.contextSetCache_[key];}else{this.activeContexts_.sort(function(a,b){const keyA=this.getContextKey_(a);const keyB=this.getContextKey_(b);if(keyA<keyB){return-1;}
+if(keyA>keyB){return 1;}
+return 0;}.bind(this));this.contextSetCache_[key]=Object.freeze(this.activeContexts_);this.cachedEntryForActiveContexts_=this.contextSetCache_[key];}}
+return this.cachedEntryForActiveContexts_;},invalidateContextCacheForSnapshot(scopedId){const snapshotKey=this.getSnapshotKey_(scopedId);if(!(snapshotKey in this.seenSnapshots_))return;this.contextCache_={};this.contextSetCache_={};this.cachedEntryForActiveContexts_=undefined;this.activeContexts_=this.activeContexts_.map(function(context){if(context.snapshot.scope!==scopedId.scope||context.snapshot.idRef!==scopedId.id){return context;}
+return{type:context.type,snapshot:{scope:context.snapshot.scope,idRef:context.snapshot.idRef}};});this.seenSnapshots_={};},};return{ContextProcessor,};});'use strict';tr.exportTo('tr.model',function(){function Annotation(){this.guid_=tr.b.GUID.allocateSimple();this.view_=undefined;}
+Annotation.fromDictIfPossible=function(args){if(args.typeName===undefined){throw new Error('Missing typeName argument');}
+const typeInfo=Annotation.findTypeInfoMatching(function(typeInfo){return typeInfo.metadata.typeName===args.typeName;});if(typeInfo===undefined)return undefined;return typeInfo.constructor.fromDict(args);};Annotation.fromDict=function(){throw new Error('Not implemented');};Annotation.prototype={get guid(){return this.guid_;},onRemove(){},toDict(){throw new Error('Not implemented');},getOrCreateView(viewport){if(!this.view_){this.view_=this.createView_(viewport);}
+return this.view_;},createView_(){throw new Error('Not implemented');}};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(Annotation,options);Annotation.addEventListener('will-register',function(e){if(!e.typeInfo.constructor.hasOwnProperty('fromDict')){throw new Error('Must have fromDict method');}
+if(!e.typeInfo.metadata.typeName){throw new Error('Registered Annotations must provide typeName');}});return{Annotation,};});'use strict';tr.exportTo('tr.model',function(){function YComponent(stableId,yPercentOffset){this.stableId=stableId;this.yPercentOffset=yPercentOffset;}
+YComponent.prototype={toDict(){return{stableId:this.stableId,yPercentOffset:this.yPercentOffset};}};function Location(xWorld,yComponents){this.xWorld_=xWorld;this.yComponents_=yComponents;}
+Location.fromViewCoordinates=function(viewport,viewX,viewY){const dt=viewport.currentDisplayTransform;const xWorld=dt.xViewToWorld(viewX);const yComponents=[];let elem=document.elementFromPoint(viewX+viewport.modelTrackContainer.canvas.offsetLeft,viewY+viewport.modelTrackContainer.canvas.offsetTop);while(elem instanceof tr.ui.tracks.Track){if(elem.eventContainer){const boundRect=elem.getBoundingClientRect();const yPercentOffset=(viewY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
+elem=elem.parentElement;}
+if(yComponents.length===0)return;return new Location(xWorld,yComponents);};Location.fromStableIdAndTimestamp=function(viewport,stableId,ts){const xWorld=ts;const yComponents=[];const containerToTrack=viewport.containerToTrackMap;let elem=containerToTrack.getTrackByStableId(stableId);if(!elem)return;const firstY=elem.getBoundingClientRect().top;while(elem instanceof tr.ui.tracks.Track){if(elem.eventContainer){const boundRect=elem.getBoundingClientRect();const yPercentOffset=(firstY-boundRect.top)/boundRect.height;yComponents.push(new YComponent(elem.eventContainer.stableId,yPercentOffset));}
+elem=elem.parentElement;}
+if(yComponents.length===0)return;return new Location(xWorld,yComponents);};Location.prototype={get xWorld(){return this.xWorld_;},getContainingTrack(viewport){const containerToTrack=viewport.containerToTrackMap;for(const i in this.yComponents_){const yComponent=this.yComponents_[i];const track=containerToTrack.getTrackByStableId(yComponent.stableId);if(track!==undefined)return track;}},toViewCoordinates(viewport){const dt=viewport.currentDisplayTransform;const containerToTrack=viewport.containerToTrackMap;const viewX=dt.xWorldToView(this.xWorld_);let viewY=-1;for(const index in this.yComponents_){const yComponent=this.yComponents_[index];const track=containerToTrack.getTrackByStableId(yComponent.stableId);if(track!==undefined){const boundRect=track.getBoundingClientRect();viewY=yComponent.yPercentOffset*boundRect.height+boundRect.top;break;}}
+return{viewX,viewY};},toDict(){return{xWorld:this.xWorld_,yComponents:this.yComponents_};}};return{Location,};});'use strict';tr.exportTo('tr.ui.annotations',function(){function AnnotationView(viewport,annotation){}
+AnnotationView.prototype={draw(ctx){throw new Error('Not implemented');}};return{AnnotationView,};});'use strict';tr.exportTo('tr.ui.annotations',function(){function RectAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;}
+RectAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,draw(ctx){const dt=this.viewport_.currentDisplayTransform;const startCoords=this.annotation_.startLocation.toViewCoordinates(this.viewport_);const endCoords=this.annotation_.endLocation.toViewCoordinates(this.viewport_);let startY=startCoords.viewY-ctx.canvas.getBoundingClientRect().top;const sizeY=endCoords.viewY-startCoords.viewY;if(startY+sizeY<0){startY=sizeY;}else if(startY<0){startY=0;}
+ctx.fillStyle=this.annotation_.fillStyle;ctx.fillRect(startCoords.viewX,startY,endCoords.viewX-startCoords.viewX,sizeY);}};return{RectAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function RectAnnotation(start,end){tr.model.Annotation.apply(this,arguments);this.startLocation_=start;this.endLocation_=end;this.fillStyle='rgba(255, 180, 0, 0.3)';}
+RectAnnotation.fromDict=function(dict){const args=dict.args;const startLoc=new tr.model.Location(args.start.xWorld,args.start.yComponents);const endLoc=new tr.model.Location(args.end.xWorld,args.end.yComponents);return new tr.model.RectAnnotation(startLoc,endLoc);};RectAnnotation.prototype={__proto__:tr.model.Annotation.prototype,get startLocation(){return this.startLocation_;},get endLocation(){return this.endLocation_;},toDict(){return{typeName:'rect',args:{start:this.startLocation.toDict(),end:this.endLocation.toDict()}};},createView_(viewport){return new tr.ui.annotations.RectAnnotationView(viewport,this);}};tr.model.Annotation.register(RectAnnotation,{typeName:'rect'});return{RectAnnotation,};});'use strict';tr.exportTo('tr.ui.annotations',function(){function CommentBoxAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;this.textArea_=undefined;this.styleWidth=250;this.styleHeight=50;this.fontSize=10;this.rightOffset=50;this.topOffset=25;}
+CommentBoxAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,removeTextArea(){Polymer.dom(Polymer.dom(this.textArea_).parentNode).removeChild(this.textArea_);},draw(ctx){const coords=this.annotation_.location.toViewCoordinates(this.viewport_);if(coords.viewX<0){if(this.textArea_){this.textArea_.style.visibility='hidden';}
+return;}
+if(!this.textArea_){this.textArea_=document.createElement('textarea');this.textArea_.style.position='absolute';this.textArea_.readOnly=true;this.textArea_.value=this.annotation_.text;this.textArea_.style.zIndex=1;Polymer.dom(Polymer.dom(ctx.canvas).parentNode).appendChild(this.textArea_);}
+this.textArea_.style.width=this.styleWidth+'px';this.textArea_.style.height=this.styleHeight+'px';this.textArea_.style.fontSize=this.fontSize+'px';this.textArea_.style.visibility='visible';this.textArea_.style.left=coords.viewX+ctx.canvas.getBoundingClientRect().left+
+this.rightOffset+'px';this.textArea_.style.top=coords.viewY-ctx.canvas.getBoundingClientRect().top-
+this.topOffset+'px';ctx.strokeStyle='rgb(0, 0, 0)';ctx.lineWidth=2;ctx.beginPath();tr.ui.b.drawLine(ctx,coords.viewX,coords.viewY-ctx.canvas.getBoundingClientRect().top,coords.viewX+this.rightOffset,coords.viewY-this.topOffset-
+ctx.canvas.getBoundingClientRect().top);ctx.stroke();}};return{CommentBoxAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function CommentBoxAnnotation(location,text){tr.model.Annotation.apply(this,arguments);this.location=location;this.text=text;}
+CommentBoxAnnotation.fromDict=function(dict){const args=dict.args;const location=new tr.model.Location(args.location.xWorld,args.location.yComponents);return new tr.model.CommentBoxAnnotation(location,args.text);};CommentBoxAnnotation.prototype={__proto__:tr.model.Annotation.prototype,onRemove(){this.view_.removeTextArea();},toDict(){return{typeName:'comment_box',args:{text:this.text,location:this.location.toDict()}};},createView_(viewport){return new tr.ui.annotations.CommentBoxAnnotationView(viewport,this);}};tr.model.Annotation.register(CommentBoxAnnotation,{typeName:'comment_box'});return{CommentBoxAnnotation,};});'use strict';tr.exportTo('tr.model',function(){function ScopedId(scope,id,pid){if(scope===undefined){throw new Error('Scope should be defined. Use \''+
+tr.model.OBJECT_DEFAULT_SCOPE+'\' as the default scope.');}
+this.scope=scope;this.id=id;this.pid=pid;}
+ScopedId.prototype={toString(){const pidStr=this.pid===undefined?'':'pid: '+this.pid+', ';return'{'+pidStr+'scope: '+this.scope+', id: '+this.id+'}';},toStringWithDelimiter(delim){return(this.pid===undefined?'':this.pid)+delim+
+this.scope+delim+this.id;}};return{ScopedId,};});'use strict';tr.exportTo('tr.ui.annotations',function(){function XMarkerAnnotationView(viewport,annotation){this.viewport_=viewport;this.annotation_=annotation;}
+XMarkerAnnotationView.prototype={__proto__:tr.ui.annotations.AnnotationView.prototype,draw(ctx){const dt=this.viewport_.currentDisplayTransform;const viewX=dt.xWorldToView(this.annotation_.timestamp);ctx.beginPath();tr.ui.b.drawLine(ctx,viewX,0,viewX,ctx.canvas.height);ctx.strokeStyle=this.annotation_.strokeStyle;ctx.stroke();}};return{XMarkerAnnotationView,};});'use strict';tr.exportTo('tr.model',function(){function XMarkerAnnotation(timestamp){tr.model.Annotation.apply(this,arguments);this.timestamp=timestamp;this.strokeStyle='rgba(0, 0, 255, 0.5)';}
+XMarkerAnnotation.fromDict=function(dict){return new XMarkerAnnotation(dict.args.timestamp);};XMarkerAnnotation.prototype={__proto__:tr.model.Annotation.prototype,toDict(){return{typeName:'xmarker',args:{timestamp:this.timestamp}};},createView_(viewport){return new tr.ui.annotations.XMarkerAnnotationView(viewport,this);}};tr.model.Annotation.register(XMarkerAnnotation,{typeName:'xmarker'});return{XMarkerAnnotation,};});'use strict';tr.exportTo('tr.e.importer',function(){const Base64=tr.b.Base64;const deepCopy=tr.b.deepCopy;const ColorScheme=tr.b.ColorScheme;const HeapDumpTraceEventImporter=tr.e.importer.HeapDumpTraceEventImporter;const LegacyHeapDumpTraceEventImporter=tr.e.importer.LegacyHeapDumpTraceEventImporter;const StreamingEventExpander=tr.e.importer.StreamingEventExpander;const ProfilingDictionaryReader=tr.e.importer.ProfilingDictionaryReader;const MEASURE_NAME_REGEX=tr.e.measure.MEASURE_NAME_REGEX;function getEventColor(event,opt_customName){if(event.cname){return ColorScheme.getColorIdForReservedName(event.cname);}else if(opt_customName||event.name){return ColorScheme.getColorIdForGeneralPurposeString(opt_customName||event.name);}}
+function isLegacyChromeClockSyncEvent(event){return event.name!==undefined&&event.name.startsWith(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX)&&((event.ph==='S')||(event.ph==='F'));}
+const PRODUCER='producer';const CONSUMER='consumer';const STEP='step';const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER=[undefined,BACKGROUND,LIGHT,DETAILED];const GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX='global/';const LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX='ClockSyncEvent.';const BYTE_STAT_NAME_MAP={'pc':'privateCleanResident','pd':'privateDirtyResident','sc':'sharedCleanResident','sd':'sharedDirtyResident','pss':'proportionalResident','sw':'swapped'};const WEAK_MEMORY_ALLOCATOR_DUMP_FLAG=1<<0;const OBJECT_TYPE_NAME_PATTERNS=[{prefix:'const char *WTF::getStringWithTypeName() [T = ',suffix:']'},{prefix:'const char* WTF::getStringWithTypeName() [with T = ',suffix:']'},{prefix:'const char *__cdecl WTF::getStringWithTypeName<',suffix:'>(void)'}];const SUBTRACE_FIELDS=new Set(['powerTraceAsString','systemTraceEvents','androidProcessDump',]);const NON_METADATA_FIELDS=new Set(['displayTimeUnit','samples','stackFrames','traceAnnotations','traceEvents',...SUBTRACE_FIELDS]);function TraceEventImporter(model,eventData){this.hasEvents_=undefined;this.importPriority=1;this.model_=model;this.events_=undefined;this.sampleEvents_=undefined;this.stackFrameEvents_=undefined;this.stackFrameTree_=new tr.model.ProfileTree();this.subtraces_=[];this.eventsWereFromString_=false;this.softwareMeasuredCpuCount_=undefined;this.allAsyncEvents_=[];this.allFlowEvents_=[];this.allObjectEvents_=[];this.contextProcessorPerThread={};this.traceEventSampleStackFramesByName_={};this.v8ProcessCodeMaps_={};this.v8ProcessRootStackFrame_={};this.v8SamplingData_=[];this.profileTrees_=new Map();this.profileInfo_=new Map();this.legacyChromeClockSyncStartEvent_=undefined;this.legacyChromeClockSyncFinishEvent_=undefined;this.allMemoryDumpEvents_={};this.heapProfileExpander=new ProfilingDictionaryReader();this.objectTypeNameMap_={};this.clockDomainId_=tr.model.ClockDomainId.UNKNOWN_CHROME_LEGACY;this.toModelTime_=undefined;if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();if(eventData[0]==='['){eventData=eventData.replace(/\s*,\s*$/,'');if(eventData[eventData.length-1]!==']'){eventData=eventData+']';}}
+this.events_=JSON.parse(eventData);this.eventsWereFromString_=true;}else{this.events_=eventData;}
+if(this.events_.traceEvents){const container=this.events_;this.events_=this.events_.traceEvents;for(const subtraceField of SUBTRACE_FIELDS){if(container[subtraceField]){this.storeSubtrace_(container[subtraceField]);}}
+this.storeSamples_(container.samples);this.storeStackFrames_(container.stackFrames);this.storeDisplayTimeUnit_(container.displayTimeUnit);this.storeTraceAnnotations_(container.traceAnnotations);this.storeMetadata_(container);}else if(this.events_ instanceof tr.b.TraceStream){const parser=oboe().node('{cat ph}',function(e){return oboe.drop;}).node('!.powerTraceAsString',this.storeSubtrace_.bind(this)).node('!.systemTraceEvents',this.storeSubtrace_.bind(this)).node('!.samples',this.storeSamples_.bind(this)).node('!.stackFrames',this.storeStackFrames_.bind(this)).node('!.displayTimeUnit',this.storeDisplayTimeUnit_.bind(this)).node('!.traceAnnotations',this.storeTraceAnnotations_.bind(this)).done(this.storeMetadata_.bind(this));this.events_.rewind();while(this.events_.hasData){parser.write(this.events_.readNumBytes());}
+parser.finish();}}
+TraceEventImporter.canImport=function(eventData){if(eventData instanceof tr.b.TraceStream){if(eventData.isBinary)return false;eventData=eventData.header;}
+if(typeof(eventData)==='string'||eventData instanceof String){eventData=eventData.trim();return eventData[0]==='{'||eventData[0]==='[';}
+if(eventData instanceof Array&&eventData.length&&eventData[0].ph){return true;}
+if(eventData.traceEvents){if(eventData.traceEvents instanceof Array){if(eventData.traceEvents.length&&eventData.traceEvents[0].ph){return true;}
+if(eventData.samples&&eventData.samples.length&&eventData.stackFrames!==undefined){return true;}}}
+return false;};TraceEventImporter.scopedIdForEvent_=function(event){const scope=event.scope||tr.model.OBJECT_DEFAULT_SCOPE;let pid=undefined;if(event.id!==undefined){if(event.id2!==undefined){throw new Error('Event has both id and id2');}
+pid=tr.model.LOCAL_ID_PHASES.has(event.ph)?event.pid:undefined;return new tr.model.ScopedId(scope,event.id,pid);}else if(event.id2!==undefined){if(event.id2.global!==undefined){return new tr.model.ScopedId(scope,event.id2.global);}else if(event.id2.local!==undefined){return new tr.model.ScopedId(scope,event.id2.local,event.pid);}
+throw new Error('Event that uses id2 must have either a global or local ID');}
+return undefined;};TraceEventImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'TraceEventImporter';},extractSubtraces(){const subtraces=this.subtraces_;this.subtraces_=[];return subtraces;},deepCopyIfNeeded_(obj){if(obj===undefined)obj={};if(this.eventsWereFromString_)return obj;return deepCopy(obj);},deepCopyAlways_(obj){if(obj===undefined)obj={};return deepCopy(obj);},processAsyncEvent(event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);this.allAsyncEvents_.push({sequenceNumber:this.allAsyncEvents_.length,event,thread});},processFlowEvent(event,opt_slice){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);this.allFlowEvents_.push({refGuid:tr.b.GUID.getLastSimpleGuid(),sequenceNumber:this.allFlowEvents_.length,event,slice:opt_slice,thread});},processCounterEvent(event){let ctrName;if(event.id!==undefined){ctrName=event.name+'['+event.id+']';}else{ctrName=event.name;}
+const ctr=this.model_.getOrCreateProcess(event.pid).getOrCreateCounter(event.cat,ctrName);const reservedColorId=event.cname?getEventColor(event):undefined;if(ctr.numSeries===0){for(const seriesName in event.args){const colorId=reservedColorId||getEventColor(event,ctr.name+'.'+seriesName);ctr.addSeries(new tr.model.CounterSeries(seriesName,colorId));}
+if(ctr.numSeries===0){this.model_.importWarning({type:'counter_parse_error',message:'Expected counter '+event.name+' to have at least one argument to use as a value.'});delete ctr.parent.counters[ctr.name];return;}}
+const ts=this.toModelTimeFromUs_(event.ts);ctr.series.forEach(function(series){const val=event.args[series.name]?event.args[series.name]:0;series.addCounterSample(ts,val);});},processObjectEvent(event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);this.allObjectEvents_.push({sequenceNumber:this.allObjectEvents_.length,event,thread});if(thread.guid in this.contextProcessorPerThread){const processor=this.contextProcessorPerThread[thread.guid];const scopedId=TraceEventImporter.scopedIdForEvent_(event);if(event.ph==='D'){processor.destroyContext(scopedId);}
+processor.invalidateContextCacheForSnapshot(scopedId);}},processContextEvent(event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);if(!(thread.guid in this.contextProcessorPerThread)){this.contextProcessorPerThread[thread.guid]=new tr.importer.ContextProcessor(this.model_);}
+const scopedId=TraceEventImporter.scopedIdForEvent_(event);const contextType=event.name;const processor=this.contextProcessorPerThread[thread.guid];if(event.ph==='('){processor.enterContext(contextType,scopedId);}else if(event.ph===')'){processor.leaveContext(contextType,scopedId);}else{this.model_.importWarning({type:'unknown_context_phase',message:'Unknown context event phase: '+event.ph+'.'});}},setContextsFromThread_(thread,slice){if(thread.guid in this.contextProcessorPerThread){slice.contexts=this.contextProcessorPerThread[thread.guid].activeContexts;}},processDurationEvent(event){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);const ts=this.toModelTimeFromUs_(event.ts);if(event.dur===0&&!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'duration_parse_error',message:'Timestamps are moving backward.'});return;}
+if(event.ph==='B'){const slice=thread.sliceGroup.beginSlice(event.cat,event.name,this.toModelTimeFromUs_(event.ts),this.deepCopyIfNeeded_(event.args),this.toModelTimeFromUs_(event.tts),event.argsStripped,getEventColor(event),event.bind_id);slice.startStackFrame=this.getStackFrameForEvent_(event);this.setContextsFromThread_(thread,slice);}else if(event.ph==='I'||event.ph==='i'||event.ph==='R'){if(event.s!==undefined&&event.s!=='t'){throw new Error('This should never happen');}
+thread.sliceGroup.beginSlice(event.cat,event.name,this.toModelTimeFromUs_(event.ts),this.deepCopyIfNeeded_(event.args),this.toModelTimeFromUs_(event.tts),event.argsStripped,getEventColor(event),event.bind_id);const slice=thread.sliceGroup.endSlice(this.toModelTimeFromUs_(event.ts),this.toModelTimeFromUs_(event.tts));slice.startStackFrame=this.getStackFrameForEvent_(event);slice.endStackFrame=undefined;}else{if(!thread.sliceGroup.openSliceCount){this.model_.importWarning({type:'duration_parse_error',message:'E phase event without a matching B phase event.'});return;}
+const slice=thread.sliceGroup.endSlice(this.toModelTimeFromUs_(event.ts),this.toModelTimeFromUs_(event.tts),getEventColor(event));if(event.name&&slice.title!==event.name){this.model_.importWarning({type:'title_match_error',message:'Titles do not match. Title is '+
+slice.title+' in openSlice, and is '+
+event.name+' in endSlice'});}
+slice.endStackFrame=this.getStackFrameForEvent_(event);this.mergeArgsInto_(slice.args,event.args,slice.title);}},mergeArgsInto_(dstArgs,srcArgs,eventName){for(const arg in srcArgs){if(dstArgs[arg]!==undefined){this.model_.importWarning({type:'arg_merge_error',message:'Different phases of '+eventName+' provided values for argument '+arg+'.'+' The last provided value will be used.'});}
+dstArgs[arg]=this.deepCopyIfNeeded_(srcArgs[arg]);}},processCompleteEvent(event){if(event.cat!==undefined&&event.cat.indexOf('trace_event_overhead')>-1){return undefined;}
+const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);if(event.flow_out){if(event.flow_in){event.flowPhase=STEP;}else{event.flowPhase=PRODUCER;}}else if(event.flow_in){event.flowPhase=CONSUMER;}
+const slice=thread.sliceGroup.pushCompleteSlice(event.cat,event.name,this.toModelTimeFromUs_(event.ts),this.durationFromUs_(event.dur),this.maybeToModelTimeFromUs_(event.tts),this.durationFromUs_(event.tdur),this.deepCopyIfNeeded_(event.args),event.argsStripped,getEventColor(event),event.bind_id);slice.startStackFrame=this.getStackFrameForEvent_(event);slice.endStackFrame=this.getStackFrameForEvent_(event,true);this.setContextsFromThread_(thread,slice);return slice;},processJitCodeEvent(event){if(this.v8ProcessCodeMaps_[event.pid]===undefined){this.v8ProcessCodeMaps_[event.pid]=new tr.e.importer.TraceCodeMap();}
+const map=this.v8ProcessCodeMaps_[event.pid];const data=event.args.data;if(event.name==='JitCodeMoved'){map.moveEntry(data.code_start,data.new_code_start,data.code_len);}else{map.addEntry(data.code_start,data.code_len,data.name,data.script_id);}},processMetadataEvent(event){if(event.name==='JitCodeAdded'||event.name==='JitCodeMoved'){this.v8SamplingData_.push(event);return;}
+if(event.argsStripped)return;if(event.name==='process_name'){const process=this.model_.getOrCreateProcess(event.pid);process.name=event.args.name;}else if(event.name==='process_labels'){const process=this.model_.getOrCreateProcess(event.pid);const stackFrames=event.args.stackFrames;if(event.args.labels===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'No labels found in a \''+event.name+'\' metadata event'});}else{const labels=event.args.labels.split(',');for(let i=0;i<labels.length;i++){process.addLabelIfNeeded(labels[i]);}}}else if(event.name==='process_uptime_seconds'){const process=this.model_.getOrCreateProcess(event.pid);process.uptime_seconds=event.args.uptime;}else if(event.name==='process_sort_index'){const process=this.model_.getOrCreateProcess(event.pid);process.sortIndex=event.args.sort_index;}else if(event.name==='thread_name'){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);thread.name=event.args.name;}else if(event.name==='thread_sort_index'){const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);thread.sortIndex=event.args.sort_index;}else if(event.name==='num_cpus'){let n=event.args.number;if(this.softwareMeasuredCpuCount_!==undefined){n=Math.max(n,this.softwareMeasuredCpuCount_);}
+this.softwareMeasuredCpuCount_=n;}else if(event.name==='stackFrames'){const stackFrames=event.args.stackFrames;if(stackFrames===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'No stack frames found in a \''+event.name+'\' metadata event'});}else{this.importStackFrames_(stackFrames,'p'+event.pid+':');}}else if(event.name==='typeNames'){const objectTypeNameMap=event.args.typeNames;if(objectTypeNameMap===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'No mapping from object type IDs to names found in a \''+
+event.name+'\' metadata event'});}else{this.importObjectTypeNameMap_(objectTypeNameMap,event.pid);}}else if(event.name==='TraceConfig'){this.model_.metadata.push({name:'TraceConfig',value:event.args.value});}else{this.model_.importWarning({type:'metadata_parse_error',message:'Unrecognized metadata name: '+event.name});}},processInstantEvent(event){if(event.name==='JitCodeAdded'||event.name==='JitCodeMoved'){this.v8SamplingData_.push(event);return;}
+if(event.s==='t'||event.s===undefined){this.processDurationEvent(event);return;}
+let constructor;let parent;switch(event.s){case'g':constructor=tr.model.GlobalInstantEvent;parent=this.model_;break;case'p':constructor=tr.model.ProcessInstantEvent;parent=this.model_.getOrCreateProcess(event.pid);break;default:this.model_.importWarning({type:'instant_parse_error',message:'I phase event with unknown "s" field value.'});return;}
+const instantEvent=new constructor(event.cat,event.name,getEventColor(event),this.toModelTimeFromUs_(event.ts),this.deepCopyIfNeeded_(event.args),parent);parent.instantEvents.push(instantEvent);},getOrCreateProfileTree_(sampleType,id){if(!this.profileTrees_.has(sampleType)){this.profileTrees_.set(sampleType,new Map());}
+const profileTreeMap=this.profileTrees_.get(sampleType);if(profileTreeMap.has(id)){return profileTreeMap.get(id);}
+const profileTree=new tr.model.ProfileTree();profileTreeMap.set(id,profileTree);const info=this.profileInfo_.get(id);if(info!==undefined){profileTree.startTime=info.startTime;profileTree.pid=info.pid;profileTree.tid=info.tid;}
+return profileTree;},processSample(event){if(event.args===undefined||event.args.data===undefined){return;}
+if(event.id===undefined){throw new Error('No event ID in sample');}
+const data=event.args.data;if(data.startTime!==undefined){this.profileInfo_.set(event.id,{startTime:data.startTime,pid:event.pid,tid:event.tid});}
+const timeDeltas=data.timeDeltas;for(const sampleType in data){if(sampleType==='timeDeltas'||sampleType==='startTime'){continue;}
+if(data[sampleType].samples&&timeDeltas&&data[sampleType].samples.length!==timeDeltas.length){throw new Error('samples and timeDeltas array should have same length');}
+const profileTree=this.getOrCreateProfileTree_(sampleType,event.id);const nodes=data[sampleType].nodes;const samples=data[sampleType].samples;if(nodes!==undefined){for(const node of nodes){const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);const profileNode=ProfileNodeType.constructFromObject(profileTree,node);if(profileNode===undefined){continue;}
+profileTree.add(profileNode);}}
+if(samples!==undefined){const thread=this.model_.getOrCreateProcess(profileTree.pid).getOrCreateThread(profileTree.tid);for(let i=0,len=samples.length;i<len;++i){const node=profileTree.getNode(samples[i]);profileTree.endTime+=timeDeltas[i];if(node===undefined)continue;const start=this.toModelTimeFromUs_(profileTree.endTime);this.model_.samples.push(new tr.model.Sample(start,node.sampleTitle,node,thread));}}}},processLegacyV8Sample(event){const data=event.args.data;const sampleType='legacySample';const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,sampleType);if(data.vm_state==='js'&&!data.stack.length)return;const profileTree=this.getOrCreateProfileTree_(sampleType,event.pid);if(profileTree.getNode(-1)===undefined){profileTree.add(new ProfileNodeType(-1,{url:'',scriptId:-1,functionName:'unknown'},undefined));}
+let node=undefined;if(data.stack.length>0&&this.v8ProcessCodeMaps_[event.pid]){const map=this.v8ProcessCodeMaps_[event.pid];data.stack.reverse();let parentNode=undefined;for(let i=0;i<data.stack.length;i++){const entry=map.lookupEntry(data.stack[i]);if(entry===undefined){node=profileTree.getNode(-1);}else{node=profileTree.getNode(entry.id);if(node===undefined){const sourceInfo=entry.sourceInfo;node=new ProfileNodeType(entry.id,{functionName:entry.name,url:entry.sourceInfo.file,lineNumber:sourceInfo.line!==-1?sourceInfo.line:undefined,columnNumber:sourceInfo.column!==-1?sourceInfo.column:undefined,scriptid:entry.sourceInfo.scriptId},parentNode);profileTree.add(node);}}
+parentNode=node;}}else{node=profileTree.getNode(data.vm_state);if(node===undefined){node=new ProfileNodeType(data.vm_state,{url:'',functionName:data.vm_state},undefined);profileTree.add(node);}}
+const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);this.model_.samples.push(new tr.model.Sample(this.toModelTimeFromUs_(event.ts),node.sampleTitle,node,thread));},processTraceSampleEvent(event){if(event.name==='V8Sample'||event.name.startsWith('Profile')){this.v8SamplingData_.push(event);return;}
+let node=this.stackFrameTree_.getNode(event.name);if(node===undefined&&event.sf!==undefined){node=this.stackFrameTree_.getNode('g'+event.sf);}
+if(node===undefined){let id=event.name;if(event.sf){id='g'+event.sf;}
+const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,'legacySample');node=this.stackFrameTree_.add(new ProfileNodeType(id,{functionName:event.name},undefined));}
+const thread=this.model_.getOrCreateProcess(event.pid).getOrCreateThread(event.tid);const sample=new tr.model.Sample(this.toModelTimeFromUs_(event.ts),'Trace Event Sample',node,thread,undefined,1,this.deepCopyIfNeeded_(event.args));this.setContextsFromThread_(thread,sample);this.model_.samples.push(sample);},processMemoryDumpEvent(event){if(event.ph!=='v'){throw new Error('Invalid memory dump event phase "'+event.ph+'".');}
+const dumpId=event.id;if(dumpId===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory dump event (phase \''+event.ph+'\') without a dump ID.'});return;}
+const pid=event.pid;if(pid===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory dump event (phase\''+event.ph+'\', dump ID \''+
+dumpId+'\') without a PID.'});return;}
+const allEvents=this.allMemoryDumpEvents_;let dumpIdEvents=allEvents[dumpId];if(dumpIdEvents===undefined){allEvents[dumpId]=dumpIdEvents={};}
+let processEvents=dumpIdEvents[pid];if(processEvents===undefined){dumpIdEvents[pid]=processEvents=[];}
+processEvents.push(event);},processClockSyncEvent(event){if(event.ph!=='c'){throw new Error('Invalid clock sync event phase "'+event.ph+'".');}
+const syncId=event.args.sync_id;if(syncId===undefined){this.model_.importWarning({type:'clock_sync_parse_error',message:'Clock sync at time '+event.ts+' without an ID.'});return;}
+if(event.args&&event.args.issue_ts!==undefined){this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,syncId,tr.b.Unit.timestampFromUs(event.args.issue_ts),tr.b.Unit.timestampFromUs(event.ts));}else{this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,syncId,tr.b.Unit.timestampFromUs(event.ts));}},processLegacyChromeClockSyncEvent(event){if(event.ph==='S'){this.legacyChromeClockSyncStartEvent_=event;}else if(event.ph==='F'){this.legacyChromeClockSyncFinishEvent_=event;}
+if(this.legacyChromeClockSyncStartEvent_===undefined||this.legacyChromeClockSyncFinishEvent_===undefined){return;}
+const startSyncId=this.legacyChromeClockSyncStartEvent_.name.substring(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX.length);const finishSyncId=this.legacyChromeClockSyncFinishEvent_.name.substring(LEGACY_CHROME_CLOCK_SYNC_EVENT_NAME_PREFIX.length);if(startSyncId!==finishSyncId){throw new Error('Inconsistent clock sync ID of legacy Chrome clock sync events');}
+this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,startSyncId,tr.b.Unit.timestampFromUs(this.legacyChromeClockSyncStartEvent_.ts),tr.b.Unit.timestampFromUs(this.legacyChromeClockSyncFinishEvent_.ts));},processV8Events(){this.v8SamplingData_.sort(function(a,b){if(a.ts!==b.ts)return a.ts-b.ts;if(a.ph==='M'||a.ph==='I'){return-1;}else if(b.ph==='M'||b.ph==='I'){return 1;}
+return 0;});const length=this.v8SamplingData_.length;for(let i=0;i<length;++i){const event=this.v8SamplingData_[i];if(event.ph==='M'||event.ph==='I'){this.processJitCodeEvent(event);}else if(event.ph==='P'){if(event.name.startsWith('Profile')){this.processSample(event);}else{this.processLegacyV8Sample(event);}}}},importClockSyncMarkers(){if(this.events_ instanceof tr.b.TraceStream){const parser=oboe().node('{cat ph}',this.importClockSyncMarker_.bind(this));this.events_.rewind();while(this.events_.hasData){parser.write(this.events_.readNumBytes());}
+parser.finish();}else{for(let i=0;i<this.events_.length;i++){this.importClockSyncMarker_(this.events_[i]);}}},importClockSyncMarker_(event){const isLegacyChromeClockSync=isLegacyChromeClockSyncEvent(event);if(event.ph!=='c'&&!isLegacyChromeClockSync)return;const eventSizeInBytes=this.model_.importOptions.trackDetailedModelStats?JSON.stringify(event).length:undefined;this.model_.stats.willProcessBasicTraceEvent('clock_sync',event.cat,event.name,event.ts,eventSizeInBytes);if(isLegacyChromeClockSync){this.processLegacyChromeClockSyncEvent(event);}else{this.processClockSyncEvent(event);}},importEvents(){this.hasEvents_=false;if(this.stackFrameEvents_){this.importStackFrames_(this.stackFrameEvents_,'g');}
+if(this.traceAnnotations_)this.importAnnotations_();if(this.events_ instanceof tr.b.TraceStream){const parser=oboe().node('{cat ph}',this.processEvent_.bind(this));this.events_.rewind();while(this.events_.hasData){parser.write(this.events_.readNumBytes());}
+parser.finish();}else{for(let eI=0;eI<this.events_.length;eI++){this.processEvent_(this.events_[eI]);}}
+this.createAsyncSlices_();this.processV8Events();for(const frame of Object.values(this.v8ProcessRootStackFrame_)){frame.removeAllChildren();}},storeSubtrace_(subtrace){this.subtraces_.push(subtrace);return oboe.drop;},storeSamples_(samples){this.sampleEvents_=samples;return oboe.drop;},storeStackFrames_(stackFrames){this.stackFrameEvents_=stackFrames;return oboe.drop;},storeDisplayTimeUnit_(unitName){if(!unitName)return;const unit=tr.b.TimeDisplayModes[unitName];if(unit===undefined){throw new Error('Unit '+unitName+' is not supported.');}
+this.model_.intrinsicTimeUnit=unit;return oboe.drop;},storeTraceAnnotations_(traceAnnotations){this.traceAnnotations_=traceAnnotations;return oboe.drop;},storeMetadata_(container){for(const fieldName of Object.keys(container)){if(NON_METADATA_FIELDS.has(fieldName))continue;this.model_.metadata.push({name:fieldName,value:container[fieldName]});if(fieldName!=='metadata')continue;const metadata=container[fieldName];if(metadata['highres-ticks']){this.model_.isTimeHighResolution=metadata['highres-ticks'];}
+if(metadata['clock-domain']){this.clockDomainId_=metadata['clock-domain'];}}
+return oboe.drop;},processEvent_(event){this.hasEvents_=true;const importOptions=this.model_.importOptions;const trackDetailedModelStats=importOptions.trackDetailedModelStats;const modelStats=this.model_.stats;if(event.args==='__stripped__'){event.argsStripped=true;event.args=undefined;}
+let eventSizeInBytes=undefined;if(trackDetailedModelStats){eventSizeInBytes=JSON.stringify(event).length;}
+switch(event.ph){case'B':case'E':modelStats.willProcessBasicTraceEvent('begin_end (non-compact)',event.cat,event.name,event.ts,eventSizeInBytes);this.processDurationEvent(event);break;case'X':{modelStats.willProcessBasicTraceEvent('begin_end (compact)',event.cat,event.name,event.ts,eventSizeInBytes);const slice=this.processCompleteEvent(event);if(slice!==undefined&&event.bind_id!==undefined){this.processFlowEvent(event,slice);}
+break;}
+case'b':case'e':case'n':case'S':case'F':case'T':case'p':modelStats.willProcessBasicTraceEvent('async',event.cat,event.name,event.ts,eventSizeInBytes);this.processAsyncEvent(event);break;case'I':case'i':case'R':modelStats.willProcessBasicTraceEvent('instant',event.cat,event.name,event.ts,eventSizeInBytes);this.processInstantEvent(event);break;case'P':modelStats.willProcessBasicTraceEvent('samples',event.cat,event.name,event.ts,eventSizeInBytes);this.processTraceSampleEvent(event);break;case'C':modelStats.willProcessBasicTraceEvent('counters',event.cat,event.name,event.ts,eventSizeInBytes);this.processCounterEvent(event);break;case'M':modelStats.willProcessBasicTraceEvent('metadata',event.cat,event.name,event.ts,eventSizeInBytes);this.processMetadataEvent(event);break;case'N':case'D':case'O':modelStats.willProcessBasicTraceEvent('objects',event.cat,event.name,event.ts,eventSizeInBytes);this.processObjectEvent(event);break;case's':case't':case'f':modelStats.willProcessBasicTraceEvent('flows',event.cat,event.name,event.ts,eventSizeInBytes);this.processFlowEvent(event);break;case'v':modelStats.willProcessBasicTraceEvent('memory_dumps',event.cat,event.name,event.ts,eventSizeInBytes);this.processMemoryDumpEvent(event);break;case'(':case')':this.processContextEvent(event);break;case'c':break;default:modelStats.willProcessBasicTraceEvent('unknown',event.cat,event.name,event.ts,eventSizeInBytes);this.model_.importWarning({type:'parse_error',message:'Unrecognized event phase: '+
+event.ph+' ('+event.name+')'});}
+return oboe.drop;},importStackFrames_(rawStackFrames,idPrefix){const model=this.model_;for(const id in rawStackFrames){const rawStackFrame=rawStackFrames[id];const fullId=idPrefix+id;const textForColor=rawStackFrame.category?rawStackFrame.category:rawStackFrame.name;const stackFrame=new tr.model.StackFrame(undefined,fullId,rawStackFrame.name,ColorScheme.getColorIdForGeneralPurposeString(textForColor));model.addStackFrame(stackFrame);}
+for(const id in rawStackFrames){const fullId=idPrefix+id;const stackFrame=model.stackFrames[fullId];if(stackFrame===undefined){throw new Error('Internal error');}
+const rawStackFrame=rawStackFrames[id];const parentId=rawStackFrame.parent;let parentStackFrame;if(parentId===undefined){parentStackFrame=undefined;}else{const parentFullId=idPrefix+parentId;parentStackFrame=model.stackFrames[parentFullId];if(parentStackFrame===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'Missing parent frame with ID '+parentFullId+' for stack frame \''+stackFrame.name+'\' (ID '+fullId+').'});}}
+stackFrame.parentFrame=parentStackFrame;}
+const ProfileNodeType=tr.model.ProfileNode.subTypes.getConstructor(undefined,'legacySample');if(idPrefix==='g'){for(const id in rawStackFrames){const rawStackFrame=rawStackFrames[id];const textForColor=rawStackFrame.category?rawStackFrame.category:rawStackFrame.name;const node=this.stackFrameTree_.add(new ProfileNodeType('g'+id,{functionName:rawStackFrame.name},undefined));node.colorId=ColorScheme.getColorIdForGeneralPurposeString(textForColor);node.parentId=rawStackFrame.parent;}
+for(const id in rawStackFrames){const node=this.stackFrameTree_.getNode('g'+id);const parentId=node.parentId;let parentNode=undefined;if(parentId!==undefined){parentNode=this.stackFrameTree_.getNode('g'+parentId);if(parentNode===undefined){this.model_.importWarning({type:'metadata_parse_error',message:'Missing parent frame with ID '+parentId+' for stack frame \''+node.name+'\' (ID '+node.id+').'});}
+node.parentNode=parentNode;}}}},importObjectTypeNameMap_(rawObjectTypeNameMap,pid){if(pid in this.objectTypeNameMap_){this.model_.importWarning({type:'metadata_parse_error',message:'Mapping from object type IDs to names provided for pid='+
+pid+' multiple times.'});return;}
+let objectTypeNamePrefix=undefined;let objectTypeNameSuffix=undefined;const objectTypeNameMap={};for(const objectTypeId in rawObjectTypeNameMap){const rawObjectTypeName=rawObjectTypeNameMap[objectTypeId];if(objectTypeNamePrefix===undefined){for(let i=0;i<OBJECT_TYPE_NAME_PATTERNS.length;i++){const pattern=OBJECT_TYPE_NAME_PATTERNS[i];if(rawObjectTypeName.startsWith(pattern.prefix)&&rawObjectTypeName.endsWith(pattern.suffix)){objectTypeNamePrefix=pattern.prefix;objectTypeNameSuffix=pattern.suffix;break;}}}
+if(objectTypeNamePrefix!==undefined&&rawObjectTypeName.startsWith(objectTypeNamePrefix)&&rawObjectTypeName.endsWith(objectTypeNameSuffix)){objectTypeNameMap[objectTypeId]=rawObjectTypeName.substring(objectTypeNamePrefix.length,rawObjectTypeName.length-objectTypeNameSuffix.length);}else{objectTypeNameMap[objectTypeId]=rawObjectTypeName;}}
+this.objectTypeNameMap_[pid]=objectTypeNameMap;},importAnnotations_(){for(const id in this.traceAnnotations_){const annotation=tr.model.Annotation.fromDictIfPossible(this.traceAnnotations_[id]);if(!annotation){this.model_.importWarning({type:'annotation_warning',message:'Unrecognized traceAnnotation typeName \"'+
+this.traceAnnotations_[id].typeName+'\"'});continue;}
+this.model_.addAnnotation(annotation);}},finalizeImport(){if(this.softwareMeasuredCpuCount_!==undefined){this.model_.kernel.softwareMeasuredCpuCount=this.softwareMeasuredCpuCount_;}
+this.createFlowSlices_();this.createExplicitObjects_();this.createImplicitObjects_();this.createMemoryDumps_();},getStackFrameForEvent_(event,opt_lookForEndEvent){let sf;let stack;if(opt_lookForEndEvent){sf=event.esf;stack=event.estack;}else{sf=event.sf;stack=event.stack;}
+if(stack!==undefined&&sf!==undefined){this.model_.importWarning({type:'stack_frame_and_stack_error',message:'Event at '+event.ts+' cannot have both a stack and a stackframe.'});return undefined;}
+if(stack!==undefined){return this.model_.resolveStackToStackFrame_(event.pid,stack);}
+if(sf===undefined)return undefined;const stackFrame=this.model_.stackFrames['g'+sf];if(stackFrame===undefined){this.model_.importWarning({type:'sample_import_error',message:'No frame for '+sf});return;}
+return stackFrame;},resolveStackToStackFrame_(pid,stack){return undefined;},importSampleData(){if(!this.sampleEvents_)return;const m=this.model_;const events=this.sampleEvents_;if(this.hasEvents_===undefined){throw new Error('importEvents is not run before importSampleData');}else if(!this.hasEvents_){for(let i=0;i<events.length;i++){const event=events[i];m.getOrCreateProcess(event.tid).getOrCreateThread(event.tid);}}
+const threadsByTid={};m.getAllThreads().forEach(function(t){threadsByTid[t.tid]=t;});for(let i=0;i<events.length;i++){const event=events[i];const thread=threadsByTid[event.tid];if(thread===undefined){m.importWarning({type:'sample_import_error',message:'Thread '+events.tid+'not found'});continue;}
+let cpu;if(event.cpu!==undefined){cpu=m.kernel.getOrCreateCpu(event.cpu);}
+const leafNode=this.stackFrameTree_.getNode('g'+event.sf);const sample=new tr.model.Sample(this.toModelTimeFromUs_(event.ts),event.name,leafNode,thread,cpu,event.weight);m.samples.push(sample);}},createAsyncSlices_(){if(this.allAsyncEvents_.length===0)return;this.allAsyncEvents_.sort(function(x,y){const d=x.event.ts-y.event.ts;if(d!==0)return d;return x.sequenceNumber-y.sequenceNumber;});const legacyEvents=[];const nestableAsyncEventsByKey={};const nestableMeasureAsyncEventsByKey={};for(let i=0;i<this.allAsyncEvents_.length;i++){const asyncEventState=this.allAsyncEvents_[i];const event=asyncEventState.event;if(event.ph==='S'||event.ph==='F'||event.ph==='T'||event.ph==='p'){legacyEvents.push(asyncEventState);continue;}
+if(event.cat===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require a '+'cat parameter.'});continue;}
+if(event.name===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require a '+'name parameter.'});continue;}
+const id=TraceEventImporter.scopedIdForEvent_(event);if(id===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async events (ph: b, e, or n) require an '+'id parameter.'});continue;}
+if(event.cat==='blink.user_timing'){const matched=MEASURE_NAME_REGEX.exec(event.name);if(matched!==null){const key=matched[1]+':'+event.cat;try{event.args=JSON.parse(Base64.atob(matched[3])||'{}');}catch(e){}
+if(nestableMeasureAsyncEventsByKey[key]===undefined){nestableMeasureAsyncEventsByKey[key]=[];}
+nestableMeasureAsyncEventsByKey[key].push(asyncEventState);continue;}}
+const key=event.cat+':'+id.toStringWithDelimiter(':');if(nestableAsyncEventsByKey[key]===undefined){nestableAsyncEventsByKey[key]=[];}
+nestableAsyncEventsByKey[key].push(asyncEventState);}
+this.createLegacyAsyncSlices_(legacyEvents);this.createNestableAsyncSlices_(nestableMeasureAsyncEventsByKey);this.createNestableAsyncSlices_(nestableAsyncEventsByKey);},createLegacyAsyncSlice_(events){const asyncEventState=events[events.length-1];const event=asyncEventState.event;const name=event.name;const id=TraceEventImporter.scopedIdForEvent_(event);const key=id.toStringWithDelimiter(':');const asyncSliceConstructor=tr.model.AsyncSlice.subTypes.getConstructor(events[0].event.cat,name);let duration;if(event.ts!==undefined){duration=this.toModelTimeFromUs_(event.ts-events[0].event.ts);}
+const slice=new asyncSliceConstructor(events[0].event.cat,name,getEventColor(events[0].event),this.toModelTimeFromUs_(events[0].event.ts),Object.assign({},events[0].event.args,event.args),duration||0,true,undefined,undefined,events[0].event.argsStripped);if(duration===undefined){slice.didNotFinish=true;slice.error='Slice has no matching END. End time has been adjusted.';this.model_.importWarning({type:'async_slice_parse_error',message:'Legacy async BEGIN event at '+
+events[0].event.ts+' with name="'+
+name+'" and id='+key+' was unmatched.'});}
+slice.startThread=events[0].thread;slice.endThread=asyncEventState.thread;slice.id=key;const stepType=events[1].event.ph;let isValid=true;for(let j=1;j<events.length-1;++j){if(events[j].event.ph==='T'||events[j].event.ph==='p'){isValid=this.assertStepTypeMatches_(stepType,events[j]);if(!isValid)break;}
+if(events[j].event.ph==='S'){this.model_.importWarning({type:'async_slice_parse_error',message:'At '+events[j].event.ts+', a slice named "'+
+name+'" with id='+id+' had a step before the start event.'});continue;}
+if(events[j].event.ph==='F'){this.model_.importWarning({type:'async_slice_parse_error',message:'At '+events[j].event.ts+', a slice named '+
+name+' with id='+id+' had a step after the finish event.'});continue;}
+const startIndex=j+(stepType==='T'?0:-1);const endIndex=startIndex+1;let subName=name;if(!events[j].event.argsStripped&&(events[j].event.ph==='T'||events[j].event.ph==='p')){subName=events[j].event.args.step;}
+const asyncSliceConstructor=tr.model.AsyncSlice.subTypes.getConstructor(events[0].event.cat,subName);let duration;if(events[endIndex].event.ts!==undefined){duration=this.toModelTimeFromUs_(events[endIndex].event.ts-events[startIndex].event.ts);}
+const subSlice=new asyncSliceConstructor(events[0].event.cat,subName,getEventColor(events[0].event,subName+j),this.toModelTimeFromUs_(events[startIndex].event.ts),this.deepCopyIfNeeded_(events[j].event.args),duration||0,undefined,undefined,events[startIndex].event.argsStripped);if(duration===undefined){subSlice.didNotFinish=true;subSlice.error='Slice has no matching END. End time has been adjusted.';}
+subSlice.startThread=events[startIndex].thread;subSlice.endThread=events[endIndex].thread;subSlice.id=key;slice.subSlices.push(subSlice);}
+if(isValid){slice.startThread.asyncSliceGroup.push(slice);}},createLegacyAsyncSlices_(legacyEvents){if(legacyEvents.length===0)return;legacyEvents.sort(function(x,y){const d=x.event.ts-y.event.ts;if(d!==0)return d;return x.sequenceNumber-y.sequenceNumber;});const asyncEventStatesByNameThenID={};for(let i=0;i<legacyEvents.length;i++){const asyncEventState=legacyEvents[i];const event=asyncEventState.event;const name=event.name;if(name===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Async events (ph: S, T, p, or F) require a name '+' parameter.'});continue;}
+const id=TraceEventImporter.scopedIdForEvent_(event);if(id===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:'Async events (ph: S, T, p, or F) require an id parameter.'});continue;}
+const key=id.toStringWithDelimiter(':');if(event.ph==='S'){if(asyncEventStatesByNameThenID[name]===undefined){asyncEventStatesByNameThenID[name]={};}
+if(asyncEventStatesByNameThenID[name][key]){this.model_.importWarning({type:'async_slice_parse_error',message:'At '+event.ts+', a slice of the same id '+id+' was alrady open.'});continue;}
+asyncEventStatesByNameThenID[name][key]=[];asyncEventStatesByNameThenID[name][key].push(asyncEventState);}else{if(asyncEventStatesByNameThenID[name]===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:`At ${event.ts}, no slice named "${name}" was open.`,});continue;}
+if(asyncEventStatesByNameThenID[name][key]===undefined){this.model_.importWarning({type:'async_slice_parse_error',message:`At ${event.ts}, no slice named "${name}" with id=${id} was `+'open.',});continue;}
+const events=asyncEventStatesByNameThenID[name][key];events.push(asyncEventState);if(event.ph==='F'){this.createLegacyAsyncSlice_(events);delete asyncEventStatesByNameThenID[name][key];}}}
+for(const[name,statesByID]of
+Object.entries(asyncEventStatesByNameThenID)){for(const[id,states]of Object.entries(statesByID)){const startEvent=states[0].event;states.push({sequenceNumber:1+states[states.length-1].sequenceNumber,event:{ph:'F',name,id:startEvent.id,id2:startEvent.id2,scope:startEvent.scope,pid:startEvent.pid,tid:startEvent.tid,cat:startEvent.cat,args:{},},thread:this.model_.getOrCreateProcess(startEvent.pid).getOrCreateThread(startEvent.tid),});this.createLegacyAsyncSlice_(states);}}},createNestableAsyncSlices_(nestableEventsByKey){for(const key in nestableEventsByKey){const eventStateEntries=nestableEventsByKey[key];const parentStack=[];for(let i=0;i<eventStateEntries.length;++i){const eventStateEntry=eventStateEntries[i];if(eventStateEntry.event.ph==='e'){let parentIndex=-1;for(let k=parentStack.length-1;k>=0;--k){if(parentStack[k].event.name===eventStateEntry.event.name){parentIndex=k;break;}}
+if(parentIndex===-1){eventStateEntry.finished=false;}else{parentStack[parentIndex].end=eventStateEntry;while(parentIndex<parentStack.length){parentStack.pop();}}}
+if(parentStack.length>0){eventStateEntry.parentEntry=parentStack[parentStack.length-1];}
+if(eventStateEntry.event.ph==='b'){parentStack.push(eventStateEntry);}}
+const topLevelSlices=[];for(let i=0;i<eventStateEntries.length;++i){const eventStateEntry=eventStateEntries[i];if(eventStateEntry.event.ph==='e'&&eventStateEntry.finished===undefined){continue;}
+let startState=undefined;let endState=undefined;let sliceArgs=eventStateEntry.event.args||{};let sliceError=undefined;const id=TraceEventImporter.scopedIdForEvent_(eventStateEntry.event);if(eventStateEntry.event.ph==='n'){startState=eventStateEntry;endState=eventStateEntry;}else if(eventStateEntry.event.ph==='b'){if(eventStateEntry.end===undefined){eventStateEntry.end=eventStateEntries[eventStateEntries.length-1];sliceError='Slice has no matching END. End time has been adjusted.';this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async BEGIN event at '+
+eventStateEntry.event.ts+' with name="'+
+eventStateEntry.event.name+'" and id='+id+' was unmatched.'});}else{function concatenateArguments(args1,args2){if(args1.params===undefined||args2.params===undefined){return Object.assign({},args1,args2);}
+const args3={};args3.params=Object.assign({},args1.params,args2.params);return Object.assign({},args1,args2,args3);}
+const endArgs=eventStateEntry.end.event.args||{};sliceArgs=concatenateArguments(sliceArgs,endArgs);}
+startState=eventStateEntry;endState=eventStateEntry.end;}else{sliceError='Slice has no matching BEGIN. Start time has been adjusted.';this.model_.importWarning({type:'async_slice_parse_error',message:'Nestable async END event at '+
+eventStateEntry.event.ts+' with name='+
+eventStateEntry.event.name+' and id='+id+' was unmatched.'});startState=eventStateEntries[0];endState=eventStateEntry;}
+const isTopLevel=(eventStateEntry.parentEntry===undefined);const asyncSliceConstructor=tr.model.AsyncSlice.subTypes.getConstructor(eventStateEntry.event.cat,eventStateEntry.event.name);let threadStart=undefined;let threadDuration=undefined;if(startState.event.tts&&startState.event.use_async_tts){threadStart=this.toModelTimeFromUs_(startState.event.tts);if(endState.event.tts){const threadEnd=this.toModelTimeFromUs_(endState.event.tts);threadDuration=threadEnd-threadStart;}}
+const slice=new asyncSliceConstructor(eventStateEntry.event.cat,eventStateEntry.event.name,getEventColor(endState.event),this.toModelTimeFromUs_(startState.event.ts),sliceArgs,this.toModelTimeFromUs_(endState.event.ts-startState.event.ts),isTopLevel,threadStart,threadDuration,startState.event.argsStripped);slice.startThread=startState.thread;slice.endThread=endState.thread;slice.startStackFrame=this.getStackFrameForEvent_(startState.event);slice.endStackFrame=this.getStackFrameForEvent_(endState.event);slice.id=key;if(sliceError!==undefined){slice.error=sliceError;}
+eventStateEntry.slice=slice;if(isTopLevel){topLevelSlices.push(slice);}else if(eventStateEntry.parentEntry.slice!==undefined){eventStateEntry.parentEntry.slice.subSlices.push(slice);}}
+for(let si=0;si<topLevelSlices.length;si++){topLevelSlices[si].startThread.asyncSliceGroup.push(topLevelSlices[si]);}}},assertStepTypeMatches_(stepType,event){if(stepType!==event.event.ph){this.model_.importWarning({type:'async_slice_parse_error',message:'At '+event.event.ts+', a slice named '+
+event.event.name+' with id='+
+TraceEventImporter.scopedIdForEvent_(event.event)+' had both begin and end steps, which is not allowed.'});return false;}
+return true;},validateFlowEvent_(event){if(event.name===undefined){this.model_.importWarning({type:'flow_slice_parse_error',message:'Flow events (ph: s, t or f) require a name parameter.'});return false;}
+if(event.ph==='s'||event.ph==='f'||event.ph==='t'){if(event.id===undefined){this.model_.importWarning({type:'flow_slice_parse_error',message:'Flow events (ph: s, t or f) require an id parameter.'});return false;}
+return true;}
+if(event.bind_id){if(event.flow_in===undefined&&event.flow_out===undefined){this.model_.importWarning({type:'flow_slice_parse_error',message:'Flow producer or consumer require flow_in or flow_out.'});return false;}
+return true;}
+return false;},createFlowSlices_(){if(this.allFlowEvents_.length===0)return;const createFlowEvent=function(thread,event,opt_slice){let startSlice;let flowId;let flowStartTs;if(event.bind_id){startSlice=opt_slice;flowId=event.bind_id;flowStartTs=this.toModelTimeFromUs_(event.ts+event.dur);}else{const ts=this.toModelTimeFromUs_(event.ts);startSlice=thread.sliceGroup.findSliceAtTs(ts);if(startSlice===undefined)return undefined;flowId=event.id;flowStartTs=ts;}
+const flowEvent=new tr.model.FlowEvent(event.cat,flowId,event.name,getEventColor(event),flowStartTs,this.deepCopyAlways_(event.args));flowEvent.startSlice=startSlice;flowEvent.startStackFrame=this.getStackFrameForEvent_(event);flowEvent.endStackFrame=undefined;startSlice.outFlowEvents.push(flowEvent);return flowEvent;}.bind(this);const finishFlowEventWith=function(flowEvent,thread,event,refGuid,bindToParent,opt_slice){let endSlice;if(event.bind_id){endSlice=opt_slice;}else{const ts=this.toModelTimeFromUs_(event.ts);if(bindToParent){endSlice=thread.sliceGroup.findSliceAtTs(ts);}else{endSlice=thread.sliceGroup.findNextSliceAfter(ts,refGuid);}
+if(endSlice===undefined)return false;}
+endSlice.inFlowEvents.push(flowEvent);flowEvent.endSlice=endSlice;flowEvent.duration=this.toModelTimeFromUs_(event.ts)-flowEvent.start;flowEvent.endStackFrame=this.getStackFrameForEvent_(event);this.mergeArgsInto_(flowEvent.args,event.args,flowEvent.title);return true;}.bind(this);const processFlowConsumer=function(flowIdToEvent,sliceGuidToEvent,event,slice){let flowEvent=flowIdToEvent[event.bind_id];if(flowEvent===undefined){this.model_.importWarning({type:'flow_slice_ordering_error',message:'Flow consumer '+event.bind_id+' does not have '+'a flow producer'});return false;}else if(flowEvent.endSlice){const flowProducer=flowEvent.startSlice;flowEvent=createFlowEvent(undefined,sliceGuidToEvent[flowProducer.guid],flowProducer);}
+const refGuid=undefined;const ok=finishFlowEventWith(flowEvent,undefined,event,refGuid,undefined,slice);if(ok){this.model_.flowEvents.push(flowEvent);}else{this.model_.importWarning({type:'flow_slice_end_error',message:'Flow consumer '+event.bind_id+' does not end '+'at an actual slice, so cannot be created.'});return false;}
+return true;}.bind(this);const processFlowProducer=function(flowIdToEvent,flowStatus,event,slice){if(flowIdToEvent[event.bind_id]&&flowStatus[event.bind_id]){this.model_.importWarning({type:'flow_slice_start_error',message:'Flow producer '+event.bind_id+' already seen'});return false;}
+const flowEvent=createFlowEvent(undefined,event,slice);if(!flowEvent){this.model_.importWarning({type:'flow_slice_start_error',message:'Flow producer '+event.bind_id+' does not start'+'a flow'});return false;}
+flowIdToEvent[event.bind_id]=flowEvent;}.bind(this);this.allFlowEvents_.sort(function(x,y){const d=x.event.ts-y.event.ts;if(d!==0)return d;return x.sequenceNumber-y.sequenceNumber;});const flowIdToEvent={};const sliceGuidToEvent={};const flowStatus={};for(let i=0;i<this.allFlowEvents_.length;++i){const data=this.allFlowEvents_[i];const refGuid=data.refGuid;const event=data.event;const thread=data.thread;if(!this.validateFlowEvent_(event))continue;if(event.bind_id){const slice=data.slice;sliceGuidToEvent[slice.guid]=event;if(event.flowPhase===PRODUCER){if(!processFlowProducer(flowIdToEvent,flowStatus,event,slice)){continue;}
+flowStatus[event.bind_id]=true;}else{if(!processFlowConsumer(flowIdToEvent,sliceGuidToEvent,event,slice)){continue;}
+flowStatus[event.bind_id]=false;if(event.flowPhase===STEP){if(!processFlowProducer(flowIdToEvent,flowStatus,event,slice)){continue;}
+flowStatus[event.bind_id]=true;}}
+continue;}
+const fullFlowId=JSON.stringify({id:event.id,cat:event.cat,name:event.name});let flowEvent;if(event.ph==='s'){if(flowIdToEvent[fullFlowId]){this.model_.importWarning({type:'flow_slice_start_error',message:'event id '+event.id+' already seen when '+'encountering start of flow event.'});continue;}
+flowEvent=createFlowEvent(thread,event);if(!flowEvent){this.model_.importWarning({type:'flow_slice_start_error',message:'event id '+event.id+' does not start '+'at an actual slice, so cannot be created.'});continue;}
+flowIdToEvent[fullFlowId]=flowEvent;}else if(event.ph==='t'||event.ph==='f'){flowEvent=flowIdToEvent[fullFlowId];if(flowEvent===undefined){this.model_.importWarning({type:'flow_slice_ordering_error',message:'Found flow phase '+event.ph+' for id: '+event.id+' but no flow start found.'});continue;}
+let bindToParent=event.ph==='t';if(event.ph==='f'){if(event.bp===undefined){if(event.cat.indexOf('input')>-1){bindToParent=true;}else if(event.cat.indexOf('ipc.flow')>-1){bindToParent=true;}}else{if(event.bp!=='e'){this.model_.importWarning({type:'flow_slice_bind_point_error',message:'Flow event with invalid binding point (event.bp).'});continue;}
+bindToParent=true;}}
+const ok=finishFlowEventWith(flowEvent,thread,event,refGuid,bindToParent);if(ok){this.model_.flowEvents.push(flowEvent);}else{this.model_.importWarning({type:'flow_slice_end_error',message:'event id '+event.id+' does not end '+'at an actual slice, so cannot be created.'});}
+flowIdToEvent[fullFlowId]=undefined;if(ok&&event.ph==='t'){flowEvent=createFlowEvent(thread,event);flowIdToEvent[fullFlowId]=flowEvent;}}}},createExplicitObjects_(){if(this.allObjectEvents_.length===0)return;const processEvent=function(objectEventState){const event=objectEventState.event;const scopedId=TraceEventImporter.scopedIdForEvent_(event);const thread=objectEventState.thread;if(event.name===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+JSON.stringify(event)+': '+'Object events require an name parameter.'});}
+if(scopedId===undefined||scopedId.id===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+JSON.stringify(event)+': '+'Object events require an id parameter.'});}
+const process=thread.parent;const ts=this.toModelTimeFromUs_(event.ts);let instance;if(event.ph==='N'){try{instance=process.objects.idWasCreated(scopedId,event.cat,event.name,ts);}catch(e){this.model_.importWarning({type:'object_parse_error',message:'While processing create of '+
+scopedId+' at ts='+ts+': '+e});return;}}else if(event.ph==='O'){if(event.args.snapshot===undefined){this.model_.importWarning({type:'object_parse_error',message:'While processing '+scopedId+' at ts='+ts+': '+'Snapshots must have args: {snapshot: ...}'});return;}
+let snapshot;try{const args=this.deepCopyIfNeeded_(event.args.snapshot);let cat;if(args.cat){cat=args.cat;delete args.cat;}else{cat=event.cat;}
+let baseTypename;if(args.base_type){baseTypename=args.base_type;delete args.base_type;}else{baseTypename=undefined;}
+snapshot=process.objects.addSnapshot(scopedId,cat,event.name,ts,args,baseTypename);snapshot.snapshottedOnThread=thread;}catch(e){this.model_.importWarning({type:'object_parse_error',message:'While processing snapshot of '+
+scopedId+' at ts='+ts+': '+e});return;}
+instance=snapshot.objectInstance;}else if(event.ph==='D'){try{process.objects.idWasDeleted(scopedId,event.cat,event.name,ts);const instanceMap=process.objects.getOrCreateInstanceMap_(scopedId);instance=instanceMap.lastInstance;}catch(e){this.model_.importWarning({type:'object_parse_error',message:'While processing delete of '+
+scopedId+' at ts='+ts+': '+e});return;}}
+if(instance){instance.colorId=getEventColor(event,instance.typeName);}}.bind(this);this.allObjectEvents_.sort(function(x,y){const d=x.event.ts-y.event.ts;if(d!==0)return d;return x.sequenceNumber-y.sequenceNumber;});const allObjectEvents=this.allObjectEvents_;for(let i=0;i<allObjectEvents.length;i++){const objectEventState=allObjectEvents[i];try{processEvent.call(this,objectEventState);}catch(e){this.model_.importWarning({type:'object_parse_error',message:e.message});}}},createImplicitObjects_(){for(const proc of Object.values(this.model_.processes)){this.createImplicitObjectsForProcess_(proc);}},createImplicitObjectsForProcess_(process){function processField(referencingObject,referencingObjectFieldName,referencingObjectFieldValue,containingSnapshot){if(!referencingObjectFieldValue)return;if(referencingObjectFieldValue instanceof
+tr.model.ObjectSnapshot){return null;}
+if(referencingObjectFieldValue.id===undefined)return;const implicitSnapshot=referencingObjectFieldValue;const rawId=implicitSnapshot.id;const m=/(.+)\/(.+)/.exec(rawId);if(!m){throw new Error('Implicit snapshots must have names.');}
+delete implicitSnapshot.id;const name=m[1];const id=m[2];let res;let cat;if(implicitSnapshot.cat!==undefined){cat=implicitSnapshot.cat;}else{cat=containingSnapshot.objectInstance.category;}
+let baseTypename;if(implicitSnapshot.base_type){baseTypename=implicitSnapshot.base_type;}else{baseTypename=undefined;}
+const scope=containingSnapshot.objectInstance.scopedId.scope;try{res=process.objects.addSnapshot(new tr.model.ScopedId(scope,id),cat,name,containingSnapshot.ts,implicitSnapshot,baseTypename);}catch(e){this.model_.importWarning({type:'object_snapshot_parse_error',message:'While processing implicit snapshot of '+
+rawId+' at ts='+containingSnapshot.ts+': '+e});return;}
+res.objectInstance.hasImplicitSnapshots=true;res.containingSnapshot=containingSnapshot;res.snapshottedOnThread=containingSnapshot.snapshottedOnThread;referencingObject[referencingObjectFieldName]=res;if(!(res instanceof tr.model.ObjectSnapshot)){throw new Error('Created object must be instanceof snapshot');}
+return res.args;}
+function iterObject(object,func,containingSnapshot,thisArg){if(!(object instanceof Object))return;if(object instanceof Array){for(let i=0;i<object.length;i++){const res=func.call(thisArg,object,i,object[i],containingSnapshot);if(res===null)continue;if(res){iterObject(res,func,containingSnapshot,thisArg);}else{iterObject(object[i],func,containingSnapshot,thisArg);}}
+return;}
+for(const key in object){const res=func.call(thisArg,object,key,object[key],containingSnapshot);if(res===null)continue;if(res){iterObject(res,func,containingSnapshot,thisArg);}else{iterObject(object[key],func,containingSnapshot,thisArg);}}}
+process.objects.iterObjectInstances(function(instance){instance.snapshots.forEach(function(snapshot){if(snapshot.args.id!==undefined){throw new Error('args cannot have an id field inside it');}
+iterObject(snapshot.args,processField,snapshot,this);},this);},this);},minimalTimestampInPidToEvents_(pidToEvents){let smallestTs=Infinity;for(const events of Object.values(pidToEvents)){for(const event of events){if(event.ts<smallestTs){smallestTs=event.ts;}}}
+return smallestTs;},createMemoryDumps_(){const pairs=Object.entries(this.allMemoryDumpEvents_);const key=x=>this.minimalTimestampInPidToEvents_(x);pairs.sort((x,y)=>key(x[1])-key(y[1]));for(const[dumpId,pidToEvents]of pairs){this.createGlobalMemoryDump_(pidToEvents,dumpId);}},createGlobalMemoryDump_(dumpIdEvents,dumpId){const globalRange=new tr.b.math.Range();for(const pid in dumpIdEvents){const processEvents=dumpIdEvents[pid];for(let i=0;i<processEvents.length;i++){globalRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));}}
+if(globalRange.isEmpty){throw new Error('Internal error: Global memory dump without events');}
+const globalMemoryDump=new tr.model.GlobalMemoryDump(this.model_,globalRange.min);globalMemoryDump.duration=globalRange.range;this.model_.globalMemoryDumps.push(globalMemoryDump);const globalMemoryAllocatorDumpsByFullName={};const levelsOfDetail={};const allMemoryAllocatorDumpsByGuid={};for(const pid in dumpIdEvents){this.createProcessMemoryDump_(globalMemoryDump,globalMemoryAllocatorDumpsByFullName,levelsOfDetail,allMemoryAllocatorDumpsByGuid,dumpIdEvents[pid],pid,dumpId);}
+globalMemoryDump.levelOfDetail=levelsOfDetail.global;globalMemoryDump.memoryAllocatorDumps=this.inferMemoryAllocatorDumpTree_(globalMemoryAllocatorDumpsByFullName);this.parseMemoryDumpAllocatorEdges_(allMemoryAllocatorDumpsByGuid,dumpIdEvents,dumpId);},createProcessMemoryDump_(globalMemoryDump,globalMemoryAllocatorDumpsByFullName,levelsOfDetail,allMemoryAllocatorDumpsByGuid,processEvents,pid,dumpId){const processRange=new tr.b.math.Range();for(let i=0;i<processEvents.length;i++){processRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));}
+if(processRange.isEmpty){throw new Error('Internal error: Process memory dump without events');}
+const process=this.model_.getOrCreateProcess(pid);const processMemoryDump=new tr.model.ProcessMemoryDump(globalMemoryDump,process,processRange.min);processMemoryDump.duration=processRange.range;process.memoryDumps.push(processMemoryDump);globalMemoryDump.processMemoryDumps[pid]=processMemoryDump;const processMemoryAllocatorDumpsByFullName={};for(let i=0;i<processEvents.length;i++){const processEvent=processEvents[i];const dumps=processEvent.args.dumps;if(dumps===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'\'dumps\' field not found in a process memory dump'+' event for PID='+pid+' and dump ID='+dumpId+'.'});continue;}
+this.parseMemoryDumpTotals_(processMemoryDump,dumps,pid,dumpId);this.parseMemoryDumpVmRegions_(processMemoryDump,dumps,pid,dumpId);this.parseMemoryDumpHeapDumps_(processMemoryDump,dumps,pid,dumpId);this.parseMemoryDumpLevelOfDetail_(levelsOfDetail,dumps,pid,dumpId);this.parseMemoryDumpAllocatorDumps_(processMemoryDump,globalMemoryDump,processMemoryAllocatorDumpsByFullName,globalMemoryAllocatorDumpsByFullName,allMemoryAllocatorDumpsByGuid,dumps,pid,dumpId);}
+if(levelsOfDetail.process===undefined){levelsOfDetail.process=processMemoryDump.vmRegions?DETAILED:LIGHT;}
+if(!this.updateMemoryDumpLevelOfDetail_(levelsOfDetail,'global',levelsOfDetail.process)){this.model_.importWarning({type:'memory_dump_parse_error',message:'diffent levels of detail provided for global memory'+' dump (dump ID='+dumpId+').'});}
+processMemoryDump.levelOfDetail=levelsOfDetail.process;delete levelsOfDetail.process;processMemoryDump.memoryAllocatorDumps=this.inferMemoryAllocatorDumpTree_(processMemoryAllocatorDumpsByFullName);},parseMemoryDumpTotals_(processMemoryDump,dumps,pid,dumpId){const rawTotals=dumps.process_totals;if(rawTotals===undefined)return;if(processMemoryDump.totals!==undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Process totals provided multiple times for'+' process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});return;}
+const totals={};let platformSpecificTotals=undefined;for(const rawTotalName in rawTotals){const rawTotalValue=rawTotals[rawTotalName];if(rawTotalValue===undefined)continue;if(rawTotalName==='resident_set_bytes'){totals.residentBytes=parseInt(rawTotalValue,16);continue;}
+if(rawTotalName==='peak_resident_set_bytes'){totals.peakResidentBytes=parseInt(rawTotalValue,16);continue;}
+if(rawTotalName==='is_peak_rss_resetable'){totals.arePeakResidentBytesResettable=!!rawTotalValue;continue;}
+if(rawTotalName==='private_footprint_bytes'){totals.privateFootprintBytes=parseInt(rawTotalValue,16);continue;}
+if(platformSpecificTotals===undefined){platformSpecificTotals={};totals.platformSpecific=platformSpecificTotals;}
+platformSpecificTotals[rawTotalName]=parseInt(rawTotalValue,16);}
+if(totals.peakResidentBytes===undefined&&totals.arePeakResidentBytesResettable!==undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Optional field peak_resident_set_bytes found'+' but is_peak_rss_resetable not found in'+' process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});}
+if(totals.arePeakResidentBytesResettable!==undefined&&totals.peakResidentBytes===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Optional field is_peak_rss_resetable found'+' but peak_resident_set_bytes not found in'+' process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});}
+processMemoryDump.totals=totals;},parseMemoryDumpVmRegions_(processMemoryDump,dumps,pid,dumpId){const rawProcessMmaps=dumps.process_mmaps;if(rawProcessMmaps===undefined)return;const rawVmRegions=rawProcessMmaps.vm_regions;if(rawVmRegions===undefined)return;if(processMemoryDump.vmRegions!==undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'VM regions provided multiple times for'+' process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});return;}
+const vmRegions=new Array(rawVmRegions.length);for(let i=0;i<rawVmRegions.length;i++){const rawVmRegion=rawVmRegions[i];const byteStats={};const rawByteStats=rawVmRegion.bs;for(const rawByteStatName in rawByteStats){const rawByteStatValue=rawByteStats[rawByteStatName];if(rawByteStatValue===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Byte stat \''+rawByteStatName+'\' of VM region '+
+i+' ('+rawVmRegion.mf+') in process memory dump for '+'PID='+pid+' and dump ID='+dumpId+' does not have a value.'});continue;}
+const byteStatName=BYTE_STAT_NAME_MAP[rawByteStatName];if(byteStatName===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Unknown byte stat name \''+rawByteStatName+'\' ('+
+rawByteStatValue+') of VM region '+i+' ('+
+rawVmRegion.mf+') in process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});continue;}
+byteStats[byteStatName]=parseInt(rawByteStatValue,16);if(byteStatName==='proportionalResident'&&byteStats[byteStatName]===0){byteStats[byteStatName]=undefined;}}
+vmRegions[i]=new tr.model.VMRegion(parseInt(rawVmRegion.sa,16),parseInt(rawVmRegion.sz,16),rawVmRegion.pf,rawVmRegion.mf,byteStats);}
+processMemoryDump.vmRegions=tr.model.VMRegionClassificationNode.fromRegions(vmRegions);},parseMemoryDumpHeapDumps_(processMemoryDump,dumps,pid,dumpId){const idPrefix='p'+pid+':';let importer;if(dumps.heaps){const processTypeMap=this.objectTypeNameMap_[pid];if(processTypeMap===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Missing mapping from object type IDs to names.'});}
+importer=new LegacyHeapDumpTraceEventImporter(this.model_,processMemoryDump,processTypeMap,idPrefix,dumpId,dumps.heaps);}else if(dumps.heaps_v2){const data=dumps.heaps_v2;this.heapProfileExpander=this.heapProfileExpander.expandData(data);this.addNewStackFramesFromExpander_(this.heapProfileExpander,idPrefix);importer=new HeapDumpTraceEventImporter(this.heapProfileExpander,this.model_.stackFrames,processMemoryDump,idPrefix,this.model_);}
+if(!importer)return;const heapDumps=importer.parse();if(!heapDumps)return;if(processMemoryDump.heapDumps!==undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Heap dumps provided multiple times for'+' process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});return;}
+if(Object.keys(heapDumps).length>0){processMemoryDump.heapDumps=heapDumps;}},addNewStackFramesFromExpander_(expander,idPrefix){const nodeMap=expander.getNewMap('nodes');const newStackFrames={};for(const[id,stackFrame]of nodeMap.entries()){if(!this.model_.stackFrames[idPrefix+id]){newStackFrames[id]={id,name:expander.getString(stackFrame.name_sid),};if(stackFrame.parent)newStackFrames[id].parent=stackFrame.parent;}}
+this.importStackFrames_(newStackFrames,idPrefix);},parseMemoryDumpLevelOfDetail_(levelsOfDetail,dumps,pid,dumpId){const rawLevelOfDetail=dumps.level_of_detail;let level;switch(rawLevelOfDetail){case'background':level=BACKGROUND;break;case'light':level=LIGHT;break;case'detailed':level=DETAILED;break;case undefined:level=undefined;break;default:this.model_.importWarning({type:'memory_dump_parse_error',message:'unknown raw level of detail \''+rawLevelOfDetail+'\' of process memory dump for PID='+pid+' and dump ID='+dumpId+'.'});return;}
+if(!this.updateMemoryDumpLevelOfDetail_(levelsOfDetail,'process',level)){this.model_.importWarning({type:'memory_dump_parse_error',message:'diffent levels of detail provided for process memory'+' dump for PID='+pid+' (dump ID='+dumpId+').'});}},updateMemoryDumpLevelOfDetail_(levelsOfDetail,scope,level){if(!(scope in levelsOfDetail)||level===levelsOfDetail[scope]){levelsOfDetail[scope]=level;return true;}
+if(MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(level)>MEMORY_DUMP_LEVEL_OF_DETAIL_ORDER.indexOf(levelsOfDetail[scope])){levelsOfDetail[scope]=level;}
+return false;},parseMemoryDumpAllocatorDumps_(processMemoryDump,globalMemoryDump,processMemoryAllocatorDumpsByFullName,globalMemoryAllocatorDumpsByFullName,allMemoryAllocatorDumpsByGuid,dumps,pid,dumpId){const rawAllocatorDumps=dumps.allocators;if(rawAllocatorDumps===undefined)return;for(let fullName in rawAllocatorDumps){const rawAllocatorDump=rawAllocatorDumps[fullName];const guid=rawAllocatorDump.guid;if(guid===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory allocator dump '+fullName+' for PID='+pid+' and dump ID='+dumpId+' does not have a GUID.'});}
+const flags=rawAllocatorDump.flags||0;const isWeakDump=!!(flags&WEAK_MEMORY_ALLOCATOR_DUMP_FLAG);let containerMemoryDump;let dstIndex;if(fullName.startsWith(GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX)){fullName=fullName.substring(GLOBAL_MEMORY_ALLOCATOR_DUMP_PREFIX.length);containerMemoryDump=globalMemoryDump;dstIndex=globalMemoryAllocatorDumpsByFullName;}else{containerMemoryDump=processMemoryDump;dstIndex=processMemoryAllocatorDumpsByFullName;}
+let allocatorDump=allMemoryAllocatorDumpsByGuid[guid];if(allocatorDump===undefined){if(fullName in dstIndex){this.model_.importWarning({type:'memory_dump_parse_error',message:'Multiple GUIDs provided for'+' memory allocator dump '+fullName+': '+
+dstIndex[fullName].guid+', '+guid+' (ignored) for'+' PID='+pid+' and dump ID='+dumpId+'.'});continue;}
+allocatorDump=new tr.model.MemoryAllocatorDump(containerMemoryDump,fullName,guid);allocatorDump.weak=isWeakDump;dstIndex[fullName]=allocatorDump;if(guid!==undefined){allMemoryAllocatorDumpsByGuid[guid]=allocatorDump;}}else{if(allocatorDump.containerMemoryDump!==containerMemoryDump){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory allocator dump '+fullName+' (GUID='+guid+') for PID='+pid+' and dump ID='+
+dumpId+' dumped in different contexts.'});continue;}
+if(allocatorDump.fullName!==fullName){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory allocator dump with GUID='+guid+' for PID='+
+pid+' and dump ID='+dumpId+' has multiple names: '+
+allocatorDump.fullName+', '+fullName+' (ignored).'});continue;}
+if(!isWeakDump){allocatorDump.weak=false;}}
+let attributes=rawAllocatorDump.attrs;if(attributes===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory allocator dump '+fullName+' (GUID='+guid+') for PID='+pid+' and dump ID='+dumpId+' does not have attributes.'});attributes={};}
+for(const attrName in attributes){const attrArgs=attributes[attrName];const attrType=attrArgs.type;const attrValue=attrArgs.value;switch(attrType){case'scalar':{if(attrName in allocatorDump.numerics){this.model_.importWarning({type:'memory_dump_parse_error',message:'Multiple values provided for scalar attribute '+
+attrName+' of memory allocator dump '+fullName+' (GUID='+guid+') for PID='+pid+' and dump ID='+
+dumpId+'.'});break;}
+const unit=attrArgs.units==='bytes'?tr.b.Unit.byName.sizeInBytes_smallerIsBetter:tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const value=parseInt(attrValue,16);allocatorDump.addNumeric(attrName,new tr.b.Scalar(unit,value));break;}
+case'string':if(attrName in allocatorDump.diagnostics){this.model_.importWarning({type:'memory_dump_parse_error',message:'Multiple values provided for string attribute '+
+attrName+' of memory allocator dump '+fullName+' (GUID='+guid+') for PID='+pid+' and dump ID='+
+dumpId+'.'});break;}
+allocatorDump.addDiagnostic(attrName,attrValue);break;default:this.model_.importWarning({type:'memory_dump_parse_error',message:'Unknown type provided for attribute '+attrName+' of memory allocator dump '+fullName+' (GUID='+guid+') for PID='+pid+' and dump ID='+dumpId+': '+
+attrType});break;}}}},inferMemoryAllocatorDumpTree_(memoryAllocatorDumpsByFullName){const rootAllocatorDumps=[];const fullNames=Object.keys(memoryAllocatorDumpsByFullName);fullNames.sort();for(let i=0;i<fullNames.length;i++){let fullName=fullNames[i];let allocatorDump=memoryAllocatorDumpsByFullName[fullName];while(true){const lastSlashIndex=fullName.lastIndexOf('/');if(lastSlashIndex===-1){rootAllocatorDumps.push(allocatorDump);break;}
+const parentFullName=fullName.substring(0,lastSlashIndex);let parentAllocatorDump=memoryAllocatorDumpsByFullName[parentFullName];let parentAlreadyExisted=true;if(parentAllocatorDump===undefined){parentAlreadyExisted=false;parentAllocatorDump=new tr.model.MemoryAllocatorDump(allocatorDump.containerMemoryDump,parentFullName);if(allocatorDump.weak!==false){parentAllocatorDump.weak=undefined;}
+memoryAllocatorDumpsByFullName[parentFullName]=parentAllocatorDump;}
+allocatorDump.parent=parentAllocatorDump;parentAllocatorDump.children.push(allocatorDump);if(parentAlreadyExisted){if(!allocatorDump.weak){while(parentAllocatorDump!==undefined&&parentAllocatorDump.weak===undefined){parentAllocatorDump.weak=false;parentAllocatorDump=parentAllocatorDump.parent;}}
+break;}
+fullName=parentFullName;allocatorDump=parentAllocatorDump;}}
+for(const fullName in memoryAllocatorDumpsByFullName){const allocatorDump=memoryAllocatorDumpsByFullName[fullName];if(allocatorDump.weak===undefined){allocatorDump.weak=true;}}
+return rootAllocatorDumps;},parseMemoryDumpAllocatorEdges_(allMemoryAllocatorDumpsByGuid,dumpIdEvents,dumpId){for(const pid in dumpIdEvents){const processEvents=dumpIdEvents[pid];for(let i=0;i<processEvents.length;i++){const processEvent=processEvents[i];const dumps=processEvent.args.dumps;if(dumps===undefined)continue;const rawEdges=dumps.allocators_graph;if(rawEdges===undefined)continue;for(let j=0;j<rawEdges.length;j++){const rawEdge=rawEdges[j];const sourceGuid=rawEdge.source;const sourceDump=allMemoryAllocatorDumpsByGuid[sourceGuid];if(sourceDump===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Edge for PID='+pid+' and dump ID='+dumpId+' is missing source memory allocator dump (GUID='+
+sourceGuid+').'});continue;}
+const targetGuid=rawEdge.target;const targetDump=allMemoryAllocatorDumpsByGuid[targetGuid];if(targetDump===undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Edge for PID='+pid+' and dump ID='+dumpId+' is missing target memory allocator dump (GUID='+
+targetGuid+').'});continue;}
+const importance=rawEdge.importance;const edge=new tr.model.MemoryAllocatorDumpLink(sourceDump,targetDump,importance);switch(rawEdge.type){case'ownership':if(sourceDump.owns!==undefined){this.model_.importWarning({type:'memory_dump_parse_error',message:'Memory allocator dump '+sourceDump.fullName+' (GUID='+sourceGuid+') already owns a memory'+' allocator dump ('+
+sourceDump.owns.target.fullName+').'});}else{sourceDump.owns=edge;targetDump.ownedBy.push(edge);}
+break;case'retention':sourceDump.retains.push(edge);targetDump.retainedBy.push(edge);break;default:this.model_.importWarning({type:'memory_dump_parse_error',message:'Invalid edge type: '+rawEdge.type+' (PID='+pid+', dump ID='+dumpId+', source='+sourceGuid+', target='+targetGuid+', importance='+importance+').'});}}}}},toModelTimeFromUs_(ts){if(!this.toModelTime_){this.toModelTime_=this.model_.clockSyncManager.getModelTimeTransformer(this.clockDomainId_);}
+return this.toModelTime_(tr.b.Unit.timestampFromUs(ts));},maybeToModelTimeFromUs_(ts){if(ts===undefined){return undefined;}
+return this.toModelTimeFromUs_(ts);},durationFromUs_(dur){if(dur===undefined){return undefined;}
+return tr.b.Unit.timestampFromUs(dur);}};tr.importer.Importer.register(TraceEventImporter);return{TraceEventImporter,};});'use strict';tr.exportTo('tr.e.net',function(){const AsyncSlice=tr.model.AsyncSlice;function NetAsyncSlice(){AsyncSlice.apply(this,arguments);this.url_=undefined;this.byteCount_=undefined;this.isTitleComputed_=false;this.isUrlComputed_=false;}
+NetAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){return'NetLog';},get title(){if(this.isTitleComputed_||!this.isTopLevel){return this.title_;}
+if(this.url!==undefined&&this.url.length>0){this.title_=this.url;}else if(this.args!==undefined&&this.args.source_type!==undefined){this.title_=this.args.source_type;}
+this.isTitleComputed_=true;return this.title_;},set title(title){this.title_=title;},get url(){if(this.isUrlComputed_){return this.url_;}
+if(this.args!==undefined&&this.args.params!==undefined&&this.args.params.url!==undefined){this.url_=this.args.params.url;}else if(this.subSlices!==undefined&&this.subSlices.length>0){for(let i=0;i<this.subSlices.length&&!this.url_;i++){if(this.subSlices[i].url!==undefined){this.url_=this.subSlices[i].url;}}}
+this.isUrlComputed_=true;return this.url_;},get byteCount(){if(this.byteCount_!==undefined){return this.byteCount_;}
+this.byteCount_=0;if((this.originalTitle==='URL_REQUEST_JOB_FILTERED_BYTES_READ'||this.originalTitle==='URL_REQUEST_JOB_BYTES_READ')&&this.args!==undefined&&this.args.params!==undefined&&this.args.params.byte_count!==undefined){this.byteCount_=this.args.params.byte_count;}
+for(let i=0;i<this.subSlices.length;i++){this.byteCount_+=this.subSlices[i].byteCount;}
+return this.byteCount_;}};AsyncSlice.subTypes.register(NetAsyncSlice,{categoryParts:['netlog','disabled-by-default-netlog']});return{NetAsyncSlice,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){function Parser(importer){this.importer=importer;this.model=importer.model;}
+Parser.prototype={__proto__:Object.prototype};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.mandatoryBaseClass=Parser;tr.b.decorateExtensionRegistry(Parser,options);return{Parser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function AndroidParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));importer.registerEventHandler('0:android',AndroidParser.prototype.traceMarkWriteAndroidEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+function parseArgs(argsString){const args={};if(argsString){const argsArray=argsString.split(';');for(let i=0;i<argsArray.length;++i){const parts=argsArray[i].split('=');if(parts[0]){args[parts.shift()]=parts.join('=');}}}
+return args;}
+AndroidParser.prototype={__proto__:Parser.prototype,openAsyncSlice(thread,category,name,cookie,ts,args){const asyncSliceConstructor=tr.model.AsyncSlice.subTypes.getConstructor(category,name);const slice=new asyncSliceConstructor(category,name,ColorScheme.getColorIdForGeneralPurposeString(name),ts,args);const key=category+':'+name+':'+cookie;slice.id=cookie;slice.startThread=thread;if(!this.openAsyncSlices){this.openAsyncSlices={};}
+this.openAsyncSlices[key]=slice;},closeAsyncSlice(thread,category,name,cookie,ts,args){if(!this.openAsyncSlices){return;}
+const key=category+':'+name+':'+cookie;const slice=this.openAsyncSlices[key];if(!slice){return;}
+for(const arg in args){if(slice.args[arg]!==undefined){this.model_.importWarning({type:'parse_error',message:'Both the S and F events of '+slice.title+' provided values for argument '+arg+'.'+' The value of the F event will be used.'});}
+slice.args[arg]=args[arg];}
+slice.endThread=thread;slice.duration=ts-slice.start;slice.startThread.asyncSliceGroup.push(slice);delete this.openAsyncSlices[key];},traceMarkWriteAndroidEvent(eventName,cpuNumber,pid,ts,eventBase){const eventData=eventBase.details.split('|');switch(eventData[0]){case'B':{const ppid=parseInt(eventData[1]);const title=eventData[2];const args=parseArgs(eventData[3]);let category=eventData[4];if(category===undefined)category='android';const thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;if(!thread.sliceGroup.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+this.ppids_[pid]=ppid;thread.sliceGroup.beginSlice(category,title,ts,args);break;}
+case'E':{const ppid=this.ppids_[pid];if(ppid===undefined){break;}
+const thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);if(!thread.sliceGroup.openSliceCount){break;}
+const slice=thread.sliceGroup.endSlice(ts);const args=parseArgs(eventData[3]);for(const arg in args){if(slice.args[arg]!==undefined){this.model_.importWarning({type:'parse_error',message:'Both the B and E events of '+slice.title+' provided values for argument '+arg+'.'+' The value of the E event will be used.'});}
+slice.args[arg]=args[arg];}
+break;}
+case'C':{const ppid=parseInt(eventData[1]);const name=eventData[2];const value=parseInt(eventData[3]);let category=eventData[4];if(category===undefined)category='android';const ctr=this.model_.getOrCreateProcess(ppid).getOrCreateCounter(category,name);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries(value,ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,value);});break;}
+case'S':{const ppid=parseInt(eventData[1]);const name=eventData[2];const cookie=parseInt(eventData[3]);const args=parseArgs(eventData[4]);let category=eventData[5];if(category===undefined)category='android';const thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;this.ppids_[pid]=ppid;this.openAsyncSlice(thread,category,name,cookie,ts,args);break;}
+case'F':{const ppid=parseInt(eventData[1]);const name=eventData[2];const cookie=parseInt(eventData[3]);const args=parseArgs(eventData[4]);let category=eventData[5];if(category===undefined)category='android';const thread=this.model_.getOrCreateProcess(ppid).getOrCreateThread(pid);thread.name=eventBase.threadName;this.ppids_[pid]=ppid;this.closeAsyncSlice(thread,category,name,cookie,ts,args);break;}
+default:return false;}
+return true;}};Parser.register(AndroidParser);return{AndroidParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;const binderTransRE=new RegExp('transaction=(\\d+) dest_node=(\\d+) '+'dest_proc=(\\d+) dest_thread=(\\d+) '+'reply=(\\d+) flags=(0x[0-9a-fA-F]+) '+'code=(0x[0-9a-fA-F]+)');const binderAllocRE=new RegExp('transaction=(\\d+) data_size=(\\d+) '+'offsets_size=(\\d+)');const binderTransReceivedRE=/transaction=(\d+)/;function isBinderThread(name){return(name.indexOf('Binder')>-1);}
+const TF_ONE_WAY=0x01;const TF_ROOT_OBJECT=0x04;const TF_STATUS_CODE=0x08;const TF_ACCEPT_FDS=0x10;const NO_FLAGS=0;function binderFlagsToHuman(num){const flag=parseInt(num,16);let str='';if(flag&TF_ONE_WAY){str+='this is a one-way call: async, no return; ';}
+if(flag&TF_ROOT_OBJECT){str+='contents are the components root object; ';}
+if(flag&TF_STATUS_CODE){str+='contents are a 32-bit status code; ';}
+if(flag&TF_ACCEPT_FDS){str+='allow replies with file descriptors; ';}
+if(flag===NO_FLAGS){str+='No Flags Set';}
+return str;}
+function isReplyToOrigin(calling,called){return(called.dest_proc===calling.calling_pid||called.dest_thread===calling.calling_pid);}
+function binderCodeToHuman(code){return'Java Layer Dependent';}
+function doInternalSlice(trans,slice,ts){if(slice.subSlices.length!==0){slice.subSlices[0].start=ts;return slice.subSlices[0];}
+const kthread=trans.calling_kthread.thread;const internalSlice=kthread.sliceGroup.pushCompleteSlice('binder',slice.title,ts,.001,0,0,slice.args);internalSlice.title=slice.title;internalSlice.id=slice.id;internalSlice.colorId=slice.colorId;slice.subSlices.push(internalSlice);return internalSlice;}
+function generateBinderArgsForSlice(trans,cThreadName){return{'Transaction Id':trans.transaction_key,'Destination Node':trans.dest_node,'Destination Process':trans.dest_proc,'Destination Thread':trans.dest_thread,'Destination Name':cThreadName,'Reply transaction?':trans.is_reply_transaction,'Flags':trans.flags+' '+
+binderFlagsToHuman(trans.flags),'Code':trans.code+' '+
+binderCodeToHuman(trans.code),'Calling PID':trans.calling_pid,'Calling tgid':trans.calling_kthread.thread.parent.pid};}
+function BinderTransaction(events,callingPid,callingTs,callingKthread){this.transaction_key=parseInt(events[1]);this.dest_node=parseInt(events[2]);this.dest_proc=parseInt(events[3]);this.dest_thread=parseInt(events[4]);this.is_reply_transaction=parseInt(events[5])===1?true:false;this.expect_reply=((this.is_reply_transaction===false)&&(parseInt(events[6],16)&TF_ONE_WAY)===0);this.flags=events[6];this.code=events[7];this.calling_pid=callingPid;this.calling_ts=callingTs;this.calling_kthread=callingKthread;}
+function BinderParser(importer){Parser.call(this,importer);importer.registerEventHandler('binder_locked',BinderParser.prototype.binderLocked.bind(this));importer.registerEventHandler('binder_unlock',BinderParser.prototype.binderUnlock.bind(this));importer.registerEventHandler('binder_lock',BinderParser.prototype.binderLock.bind(this));importer.registerEventHandler('binder_transaction',BinderParser.prototype.binderTransaction.bind(this));importer.registerEventHandler('binder_transaction_received',BinderParser.prototype.binderTransactionReceived.bind(this));importer.registerEventHandler('binder_transaction_alloc_buf',BinderParser.prototype.binderTransactionAllocBuf.bind(this));this.model_=importer.model;this.kthreadlookup={};this.importer_=importer;this.transWaitingRecv={};this.syncTransWaitingCompletion={};this.recursiveSyncTransWaitingCompletion_ByPID={};this.receivedTransWaitingConversion={};}
+BinderParser.prototype={__proto__:Parser.prototype,binderLock(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;this.doNameMappings(pid,tgid,eventName.threadName);const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);kthread.binderAttemptLockTS=ts;kthread.binderOpenTsA=ts;return true;},binderLocked(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;const binderThread=isBinderThread(eventBase.threadName);const name=eventBase.threadName;const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);this.doNameMappings(pid,tgid,name);const rthread=kthread.thread;kthread.binderLockAquiredTS=ts;if(kthread.binderAttemptLockTS===undefined)return false;const args=this.generateArgsForSlice(tgid,pid,name,kthread);rthread.sliceGroup.pushCompleteSlice('binder','binder lock waiting',kthread.binderAttemptLockTS,ts-kthread.binderAttemptLockTS,0,0,args);kthread.binderAttemptLockTS=undefined;return true;},binderUnlock(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);if(kthread.binderLockAquiredTS===undefined)return false;const args=this.generateArgsForSlice(tgid,pid,eventBase.threadName,kthread);kthread.thread.sliceGroup.pushCompleteSlice('binder','binder lock held',kthread.binderLockAquiredTS,ts-kthread.binderLockAquiredTS,0,0,args);kthread.binderLockAquiredTS=undefined;return true;},binderTransaction(eventName,cpuNumber,pid,ts,eventBase){const event=binderTransRE.exec(eventBase.details);if(event===undefined)return false;const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;this.doNameMappings(pid,tgid,eventBase.threadName);const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);const trans=new BinderTransaction(event,pid,ts,kthread);const args=generateBinderArgsForSlice(trans,eventBase.threadName);const priorReceive=this.getPriorReceiveOnPID(pid);if(priorReceive!==false){return this.modelPriorReceive(priorReceive,ts,pid,tgid,kthread,trans,args,event);}
+const recursiveTrans=this.getRecursiveTransactionNeedingCompletion(pid);if(recursiveTrans!==false){return this.modelRecursiveTransactions(recursiveTrans,ts,pid,kthread,trans,args);}
+const slice=kthread.thread.sliceGroup.pushCompleteSlice('binder','',ts,.03,0,0,args);slice.colorId=ColorScheme.getColorIdForGeneralPurposeString(ts.toString());trans.slice=slice;if(trans.expect_reply){slice.title='binder transaction';}else{slice.title='binder transaction async';}
+this.addTransactionWaitingForRecv(trans.transaction_key,trans);return true;},binderTransactionReceived(eventName,cpuNumber,pid,ts,eventBase){const event=binderTransReceivedRE.exec(eventBase.details);if(event===undefined)return false;const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;const transactionkey=parseInt(event[1]);const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);const syncComplete=this.getSyncTransNeedsCompletion(transactionkey);if(syncComplete!==false){const syncTrans=syncComplete[0];const syncSlice=syncTrans.slice;const responseTrans=syncComplete[1];const responseSlice=responseTrans.slice;syncSlice.duration=ts-syncSlice.start;const syncInternal=doInternalSlice(syncTrans,syncSlice,ts);const responseTs=responseSlice.start+responseSlice.duration;const responseInternal=doInternalSlice(responseTrans,responseSlice,responseTs);if(responseSlice.outFlowEvents.length===0||syncSlice.inFlowEvents.length===0){const flow=this.generateFlow(responseInternal,syncInternal,responseTrans,syncTrans);syncSlice.inFlowEvents.push(flow);responseSlice.outFlowEvents.push(flow);this.model_.flowEvents.push(flow);}
+for(let i=1;i<syncSlice.inFlowEvents.length;i++){syncSlice.inFlowEvents[i].duration=ts-syncSlice.inFlowEvents[i].start;}
+return true;}
+const trForRecv=this.getTransactionWaitingForRecv(transactionkey);if(trForRecv!==false){if(!trForRecv.expect_reply){const args=generateBinderArgsForSlice(trForRecv,eventBase.threadName);const slice=kthread.thread.sliceGroup.pushCompleteSlice('binder','binder Async recv',ts,.03,0,0,args);const fakeEvent=[0,0,0,0,0,0,0];const fakeTrans=new BinderTransaction(fakeEvent,pid,ts,kthread);const flow=this.generateFlow(trForRecv.slice,slice,trForRecv,fakeTrans);this.model_.flowEvents.push(flow);trForRecv.slice.title='binder transaction async';trForRecv.slice.duration=.03;return true;}
+trForRecv.slice.title='binder transaction';this.setCurrentReceiveOnPID(pid,[ts,trForRecv]);return true;}
+return false;},binderTransactionAllocBuf(eventName,cpuNumber,pid,ts,eventBase){const event=binderAllocRE.exec(eventBase.details);if(event===null)return false;const tgid=parseInt(eventBase.tgid);if(isNaN(tgid))return false;const transactionkey=parseInt(event[1]);const kthread=this.importer_.getOrCreateBinderKernelThread(eventBase.threadName,tgid,pid);const trans=this.peekTransactionWaitingForRecv(transactionkey);if(trans&&trans.slice){trans.slice.args['Data Size']=parseInt(event[2]);trans.slice.args['Offsets Size']=parseInt(event[3]);return true;}
+return false;},modelRecursiveTransactions(recursiveTrans,ts,pid,kthread,trans,args){const recursiveSlice=recursiveTrans[1].slice;const origSlice=recursiveTrans[0].slice;recursiveSlice.duration=ts-recursiveSlice.start;recursiveSlice.args=args;trans.slice=recursiveSlice;if(trans.is_reply_transaction){origSlice.duration=ts-origSlice.start;this.addSyncTransNeedingCompletion(trans.transaction_key,recursiveTrans);if(isReplyToOrigin(recursiveTrans[0],trans)){this.removeRecursiveTransaction(pid);}}else{const slice=kthread.thread.sliceGroup.pushCompleteSlice('binder','',ts,.03,0,0,args);trans.slice=slice;this.addTransactionWaitingForRecv(trans.transaction_key,trans);}
+return true;},modelPriorReceive(priorReceive,ts,pid,tgid,kthread,trans,args,event){const calleeSlice=priorReceive[1].slice;const calleeTrans=priorReceive[1];const recvTs=priorReceive[0];let slice=kthread.thread.sliceGroup.pushCompleteSlice('binder','',recvTs,ts-recvTs,0,0);const flow=this.generateFlow(calleeSlice,slice,calleeTrans,trans);this.model_.flowEvents.push(flow);trans.slice=slice;if(trans.is_reply_transaction){slice.title='binder reply';slice.args=args;this.addSyncTransNeedingCompletion(trans.transaction_key,[calleeTrans,trans]);}else{slice.title='binder reply';const trans1=new BinderTransaction(event,pid,ts,kthread);slice=kthread.thread.sliceGroup.pushCompleteSlice('binder','binder transaction',recvTs,(ts-recvTs),0,0,args);if(!trans.expect_reply){slice.title='binder transaction async';slice.duration=.03;}else{}
+trans1.slice=slice;this.addRecursiveSyncTransNeedingCompletion(pid,[calleeTrans,trans]);this.addTransactionWaitingForRecv(trans.transaction_key,trans1);}
+return true;},getRecursiveTransactionNeedingCompletion(pid){if(this.recursiveSyncTransWaitingCompletion_ByPID[pid]===undefined){return false;}
+const len=this.recursiveSyncTransWaitingCompletion_ByPID[pid].length;if(len===0)return false;return this.recursiveSyncTransWaitingCompletion_ByPID[pid][len-1];},addRecursiveSyncTransNeedingCompletion(pid,tuple){if(this.recursiveSyncTransWaitingCompletion_ByPID[pid]===undefined){this.recursiveSyncTransWaitingCompletion_ByPID[pid]=[];}
+this.recursiveSyncTransWaitingCompletion_ByPID[pid].push(tuple);},removeRecursiveTransaction(pid){const len=this.recursiveSyncTransWaitingCompletion_ByPID[pid].length;if(len===0){delete this.recursiveSyncTransWaitingCompletion_ByPID[pid];return;}
+this.recursiveSyncTransWaitingCompletion_ByPID[pid].splice(len-1,1);},setCurrentReceiveOnPID(pid,tuple){if(this.receivedTransWaitingConversion[pid]===undefined){this.receivedTransWaitingConversion[pid]=[];}
+this.receivedTransWaitingConversion[pid].push(tuple);},getPriorReceiveOnPID(pid){if(this.receivedTransWaitingConversion[pid]===undefined){return false;}
+const len=this.receivedTransWaitingConversion[pid].length;if(len===0)return false;return this.receivedTransWaitingConversion[pid].splice(len-1,1)[0];},addSyncTransNeedingCompletion(transactionkey,tuple){const dict=this.syncTransWaitingCompletion;dict[transactionkey]=tuple;},getSyncTransNeedsCompletion(transactionkey){const ret=this.syncTransWaitingCompletion[transactionkey];if(ret===undefined)return false;delete this.syncTransWaitingCompletion[transactionkey];return ret;},getTransactionWaitingForRecv(transactionkey){const ret=this.transWaitingRecv[transactionkey];if(ret===undefined)return false;delete this.transWaitingRecv[transactionkey];return ret;},peekTransactionWaitingForRecv(transactionkey){const ret=this.transWaitingRecv[transactionkey];if(ret===undefined)return false;return ret;},addTransactionWaitingForRecv(transactionkey,transaction){this.transWaitingRecv[transactionkey]=transaction;},generateFlow(from,to,fromTrans,toTrans){const title='Transaction from : '+
+this.pid2name(fromTrans.calling_pid)+' From PID: '+fromTrans.calling_pid+' to pid: '+
+toTrans.calling_pid+' Thread Name: '+this.pid2name(toTrans.calling_pid);const ts=from.start;const flow=new tr.model.FlowEvent('binder','binder',title,1,ts,[]);flow.startSlice=from;flow.endSlice=to;flow.start=from.start;flow.duration=to.start-ts;from.outFlowEvents.push(flow);to.inFlowEvents.push(flow);return flow;},generateArgsForSlice(tgid,pid,name,kthread){return{'Thread Name':name,pid,'gid':tgid};},pid2name(pid){return this.kthreadlookup[pid];},doNameMappings(pid,tgid,name){this.registerPidName(pid,name);this.registerPidName(tgid,name);},registerPidName(pid,name){if(this.pid2name(pid)===undefined){this.kthreadlookup[pid]=name;}}};Parser.register(BinderParser);return{BinderParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function BusParser(importer){Parser.call(this,importer);importer.registerEventHandler('memory_bus_usage',BusParser.prototype.traceMarkWriteBusEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+BusParser.prototype={__proto__:Parser.prototype,traceMarkWriteBusEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const re=new RegExp('bus=(\\S+) rw_bytes=(\\d+) r_bytes=(\\d+) '+'w_bytes=(\\d+) cycles=(\\d+) ns=(\\d+)');const event=re.exec(eventBase.details);const name=event[1];const rwBytes=parseInt(event[2]);const rBytes=parseInt(event[3]);const wBytes=parseInt(event[4]);const cycles=parseInt(event[5]);const ns=parseInt(event[6]);const sec=tr.b.convertUnit(ns,tr.b.UnitPrefixScale.METRIC.NANO,tr.b.UnitPrefixScale.METRIC.NONE);const readBandwidthInBps=rBytes/sec;const readBandwidthInMiBps=tr.b.convertUnit(readBandwidthInBps,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI);const writeBandwidthInBps=wBytes/sec;const writeBandwidthInMiBps=tr.b.convertUnit(writeBandwidthInBps,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI);let ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' read');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,readBandwidthInMiBps);});ctr=this.model_.kernel.getOrCreateCounter(null,'bus '+name+' write');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,writeBandwidthInMiBps);});return true;}};Parser.register(BusParser);return{BusParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ClockParser(importer){Parser.call(this,importer);importer.registerEventHandler('clock_set_rate',ClockParser.prototype.traceMarkWriteClockEvent.bind(this));importer.registerEventHandler('clk_set_rate',ClockParser.prototype.traceMarkWriteClkEvent.bind(this));importer.registerEventHandler('clock_enable',ClockParser.prototype.traceMarkWriteClockOnOffEvent.bind(this));importer.registerEventHandler('clock_disable',ClockParser.prototype.traceMarkWriteClockOnOffEvent.bind(this));importer.registerEventHandler('clk_enable',ClockParser.prototype.traceMarkWriteClkOnEvent.bind(this));importer.registerEventHandler('clk_disable',ClockParser.prototype.traceMarkWriteClkOffEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+ClockParser.prototype={__proto__:Parser.prototype,clockMark(name,subName,value,ts){const ctr=this.model_.kernel.getOrCreateCounter(null,name+' '+subName);if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,value);});},traceMarkWriteClockEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/(\S+) state=(\d+)/.exec(eventBase.details);const name=event[1];const rate=parseInt(event[2]);this.clockMark(name,'Frequency',rate,ts);return true;},traceMarkWriteClkEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/(\S+) (\d+)/.exec(eventBase.details);const name=event[1];const rate=parseInt(event[2]);this.clockMark(name,'Frequency',rate,ts);return true;},traceMarkWriteClockOnOffEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/(\S+) state=(\d+)/.exec(eventBase.details);const name=event[1];const state=parseInt(event[2]);this.clockMark(name,'State',state,ts);return true;},traceMarkWriteClkOnEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/\S+/.exec(eventBase.details);const name=event[0];this.clockMark(name,'State',1,ts);return true;},traceMarkWriteClkOffEvent(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=/\S+/.exec(eventBase.details);const name=event[0];this.clockMark(name,'State',0,ts);return true;}};Parser.register(ClockParser);return{ClockParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function CpufreqParser(importer){Parser.call(this,importer);importer.registerEventHandler('cpufreq_interactive_up',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_down',CpufreqParser.prototype.cpufreqUpDownEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_already',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_notyet',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_setspeed',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_target',CpufreqParser.prototype.cpufreqTargetEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_boost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));importer.registerEventHandler('cpufreq_interactive_unboost',CpufreqParser.prototype.cpufreqBoostUnboostEvent.bind(this));}
+function splitData(input){const data={};const args=input.split(/\s+/);const len=args.length;for(let i=0;i<len;i++){const item=args[i].split('=');data[item[0]]=parseInt(item[1]);}
+return data;}
+CpufreqParser.prototype={__proto__:Parser.prototype,cpufreqSlice(ts,eventName,cpu,args){const kthread=this.importer.getOrCreatePseudoThread('cpufreq');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqBoostSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('cpufreq_boost');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},cpufreqUpDownEvent(eventName,cpuNumber,pid,ts,eventBase){const data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqTargetEvent(eventName,cpuNumber,pid,ts,eventBase){const data=splitData(eventBase.details);this.cpufreqSlice(ts,eventName,data.cpu,data);return true;},cpufreqBoostUnboostEvent(eventName,cpuNumber,pid,ts,eventBase){this.cpufreqBoostSlice(ts,eventName,{type:eventBase.details});return true;}};Parser.register(CpufreqParser);return{CpufreqParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DiskParser(importer){Parser.call(this,importer);importer.registerEventHandler('f2fs_write_begin',DiskParser.prototype.f2fsWriteBeginEvent.bind(this));importer.registerEventHandler('f2fs_write_end',DiskParser.prototype.f2fsWriteEndEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_enter',DiskParser.prototype.f2fsSyncFileEnterEvent.bind(this));importer.registerEventHandler('f2fs_sync_file_exit',DiskParser.prototype.f2fsSyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_sync_file_enter',DiskParser.prototype.ext4SyncFileEnterEvent.bind(this));importer.registerEventHandler('ext4_sync_file_exit',DiskParser.prototype.ext4SyncFileExitEvent.bind(this));importer.registerEventHandler('ext4_da_write_begin',DiskParser.prototype.ext4WriteBeginEvent.bind(this));importer.registerEventHandler('ext4_da_write_end',DiskParser.prototype.ext4WriteEndEvent.bind(this));importer.registerEventHandler('block_rq_issue',DiskParser.prototype.blockRqIssueEvent.bind(this));importer.registerEventHandler('block_rq_complete',DiskParser.prototype.blockRqCompleteEvent.bind(this));}
+DiskParser.prototype={__proto__:Parser.prototype,openAsyncSlice(ts,category,threadName,pid,key,name){const kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);const asyncSliceConstructor=tr.model.AsyncSlice.subTypes.getConstructor(category,name);const slice=new asyncSliceConstructor(category,name,ColorScheme.getColorIdForGeneralPurposeString(name),ts);slice.startThread=kthread.thread;if(!kthread.openAsyncSlices){kthread.openAsyncSlices={};}
+kthread.openAsyncSlices[key]=slice;},closeAsyncSlice(ts,category,threadName,pid,key,args){const kthread=this.importer.getOrCreateKernelThread(category+':'+threadName,pid);if(kthread.openAsyncSlices){const slice=kthread.openAsyncSlices[key];if(slice){slice.duration=ts-slice.start;slice.args=args;slice.endThread=kthread.thread;slice.subSlices=[new tr.model.AsyncSlice(category,slice.title,slice.colorId,slice.start,slice.args,slice.duration)];kthread.thread.asyncSliceGroup.push(slice);delete kthread.openAsyncSlices[key];}}},f2fsWriteBeginEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), flags = (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const pos=parseInt(event[3]);const len=parseInt(event[4]);const key=device+'-'+inode+'-'+pos+'-'+len;this.openAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,'f2fs_write');return true;},f2fsWriteEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev = \((\d+,\d+)\), ino = (\d+), pos = (\d+), len = (\d+), copied = (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const pos=parseInt(event[3]);const len=parseInt(event[4]);const error=parseInt(event[5])!==len;const key=device+'-'+inode+'-'+pos+'-'+len;this.closeAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,{device,inode,error});return true;},ext4WriteBeginEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) flags (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const pos=parseInt(event[3]);const len=parseInt(event[4]);const key=device+'-'+inode+'-'+pos+'-'+len;this.openAsyncSlice(ts,'ext4',eventBase.threadName,eventBase.pid,key,'ext4_write');return true;},ext4WriteEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev (\d+,\d+) ino (\d+) pos (\d+) len (\d+) copied (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const pos=parseInt(event[3]);const len=parseInt(event[4]);const error=parseInt(event[5])!==len;const key=device+'-'+inode+'-'+pos+'-'+len;this.closeAsyncSlice(ts,'ext4',eventBase.threadName,eventBase.pid,key,{device,inode,error});return true;},f2fsSyncFileEnterEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('dev = \\((\\d+,\\d+)\\), ino = (\\d+), pino = (\\d+), i_mode = (\\S+), '+'i_size = (\\d+), i_nlink = (\\d+), i_blocks = (\\d+), i_advise = (\\d+)').exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const key=device+'-'+inode;this.openAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,'fsync');return true;},f2fsSyncFileExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('dev = \\((\\d+,\\d+)\\), ino = (\\d+), checkpoint is (\\S+), '+'datasync = (\\d+), ret = (\\d+)').exec(eventBase.details.replace('not needed','not_needed'));if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const error=parseInt(event[5]);const key=device+'-'+inode;this.closeAsyncSlice(ts,'f2fs',eventBase.threadName,eventBase.pid,key,{device,inode,error});return true;},ext4SyncFileEnterEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev (\d+,\d+) ino (\d+) parent (\d+) datasync (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const datasync=(event[4]==='1')||(event[4]===1);const key=device+'-'+inode;const action=datasync?'fdatasync':'fsync';this.openAsyncSlice(ts,'ext4',eventBase.threadName,eventBase.pid,key,action);return true;},ext4SyncFileExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev (\d+,\d+) ino (\d+) ret (\d+)/.exec(eventBase.details);if(!event)return false;const device=event[1];const inode=parseInt(event[2]);const error=parseInt(event[3]);const key=device+'-'+inode;this.closeAsyncSlice(ts,'ext4',eventBase.threadName,eventBase.pid,key,{device,inode,error});return true;},blockRqIssueEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? '+'\\d+ \\(.*\\) (\\d+) \\+ (\\d+) \\[.*\\]').exec(eventBase.details);if(!event)return false;let action;switch(event[3]){case'D':action='discard';break;case'W':action='write';break;case'R':action='read';break;case'N':action='none';break;default:action='unknown';break;}
+if(event[2]){action+=' flush';}
+if(event[4]==='F'){action+=' fua';}
+if(event[5]==='A'){action+=' ahead';}
+if(event[6]==='S'){action+=' sync';}
+if(event[7]==='M'){action+=' meta';}
+const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const key=device+'-'+sector+'-'+numSectors;this.openAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,action);return true;},blockRqCompleteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=new RegExp('(\\d+,\\d+) (F)?([DWRN])(F)?(A)?(S)?(M)? '+'\\(.*\\) (\\d+) \\+ (\\d+) \\[(.*)\\]').exec(eventBase.details);if(!event)return false;const device=event[1];const sector=parseInt(event[8]);const numSectors=parseInt(event[9]);const error=parseInt(event[10]);const key=device+'-'+sector+'-'+numSectors;this.closeAsyncSlice(ts,'block',eventBase.threadName,eventBase.pid,key,{device,sector,numSectors,error});return true;}};Parser.register(DiskParser);return{DiskParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DmaFenceParser(importer){Parser.call(this,importer);this.model_=importer.model_;importer.registerEventHandler('dma_fence_init',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('dma_fence_emit',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('dma_fence_destroy',DmaFenceParser.prototype.fenceDestroyEvent.bind(this));importer.registerEventHandler('dma_fence_enable_signal',DmaFenceParser.prototype.fenceEnableSignalEvent.bind(this));importer.registerEventHandler('dma_fence_signaled',DmaFenceParser.prototype.fenceSignaledEvent.bind(this));importer.registerEventHandler('dma_fence_wait_start',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('dma_fence_wait_end',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('fence_init',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('fence_emit',DmaFenceParser.prototype.initEvent.bind(this));importer.registerEventHandler('fence_destroy',DmaFenceParser.prototype.fenceDestroyEvent.bind(this));importer.registerEventHandler('fence_enable_signal',DmaFenceParser.prototype.fenceEnableSignalEvent.bind(this));importer.registerEventHandler('fence_signaled',DmaFenceParser.prototype.fenceSignaledEvent.bind(this));importer.registerEventHandler('fence_wait_start',DmaFenceParser.prototype.fenceWaitEvent.bind(this));importer.registerEventHandler('fence_wait_end',DmaFenceParser.prototype.fenceWaitEvent.bind(this));this.model_=importer.model_;}
+const fenceRE=/driver=(\S+) timeline=(\S+) context=(\d+) seqno=(\d+)/;DmaFenceParser.prototype={__proto__:Parser.prototype,initEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);thread.lastActiveTs=ts;return true;},fenceDestroyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_destroy('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
+thread.lastActiveTs=ts;},fenceEnableSignalEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_enable('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
+thread.lastActiveTs=ts;},fenceSignaledEvent(eventName,cpuNumber,pid,ts,eventBase){const event=fenceRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const thread=this.importer.getOrCreatePseudoThread(event[2]);const name='fence_signal('+event[4]+')';const colorName='fence('+event[4]+')';if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;const slice=new tr.model.ThreadSlice('',name,ColorScheme.getColorIdForGeneralPurposeString(colorName),thread.lastActiveTs,{driver:event[1],context:event[3]},duration);thread.thread.sliceGroup.pushSlice(slice);}
+if(thread.thread.sliceGroup.openSliceCount>0){thread.thread.sliceGroup.endSlice(ts);}
+thread.lastActiveTs=ts;return true;},fenceWaitEvent(eventName,cpuNumber,pid,ts,eventBase){if(eventBase.tgid===undefined)return false;const event=fenceRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+const name='dma_fence_wait("'+event[2]+'")';if(eventName.endsWith('start')){const slice=slices.beginSlice(null,name,ts,{driver:event[1],context:event[3],seqno:event[4],});}else{if(slices.openSliceCount>0){slices.endSlice(ts);}}
+return true;},};Parser.register(DmaFenceParser);return{DmaFenceParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function DrmParser(importer){Parser.call(this,importer);importer.registerEventHandler('drm_vblank_event',DrmParser.prototype.vblankEvent.bind(this));}
+DrmParser.prototype={__proto__:Parser.prototype,drmVblankSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('drm_vblank');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},vblankEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/crtc=(\d+), seq=(\d+)/.exec(eventBase.details);if(!event)return false;const crtc=parseInt(event[1]);const seq=parseInt(event[2]);this.drmVblankSlice(ts,'vblank:'+crtc,{crtc,seq});return true;}};Parser.register(DrmParser);return{DrmParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function ExynosParser(importer){Parser.call(this,importer);importer.registerEventHandler('exynos_busfreq_target_int',ExynosParser.prototype.busfreqTargetIntEvent.bind(this));importer.registerEventHandler('exynos_busfreq_target_mif',ExynosParser.prototype.busfreqTargetMifEvent.bind(this));importer.registerEventHandler('exynos_page_flip_state',ExynosParser.prototype.pageFlipStateEvent.bind(this));}
+ExynosParser.prototype={__proto__:Parser.prototype,exynosBusfreqSample(name,ts,frequency){const targetCpu=this.importer.getOrCreateCpu(0);const counter=targetCpu.getOrCreateCounter('',name);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries('frequency',ColorScheme.getColorIdForGeneralPurposeString(counter.name+'.'+'frequency')));}
+counter.series.forEach(function(series){series.addCounterSample(ts,frequency);});},busfreqTargetIntEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('INT Frequency',ts,parseInt(event[1]));return true;},busfreqTargetMifEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.exynosBusfreqSample('MIF Frequency',ts,parseInt(event[1]));return true;},exynosPageFlipStateOpenSlice(ts,pipe,fb,state){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');kthread.openSliceTS=ts;kthread.openSlice=state;},exynosPageFlipStateCloseSlice(ts,pipe,fb,args){const kthread=this.importer.getOrCreatePseudoThread('exynos_flip_state (pipe:'+pipe+', fb:'+fb+')');if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;},pageFlipStateEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/pipe=(\d+), fb=(\d+), state=(.*)/.exec(eventBase.details);if(!event)return false;const pipe=parseInt(event[1]);const fb=parseInt(event[2]);const state=event[3];this.exynosPageFlipStateCloseSlice(ts,pipe,fb,{pipe,fb});if(state!=='flipped'){this.exynosPageFlipStateOpenSlice(ts,pipe,fb,state);}
+return true;}};Parser.register(ExynosParser);return{ExynosParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function GestureParser(importer){Parser.call(this,importer);importer.registerEventHandler('tracing_mark_write:log',GestureParser.prototype.logEvent.bind(this));importer.registerEventHandler('tracing_mark_write:SyncInterpret',GestureParser.prototype.syncEvent.bind(this));importer.registerEventHandler('tracing_mark_write:HandleTimer',GestureParser.prototype.timerEvent.bind(this));}
+GestureParser.prototype={__proto__:Parser.prototype,gestureOpenSlice(title,ts,opt_args){const thread=this.importer.getOrCreatePseudoThread('gesture').thread;thread.sliceGroup.beginSlice('touchpad_gesture',title,ts,opt_args);},gestureCloseSlice(title,ts){const thread=this.importer.getOrCreatePseudoThread('gesture').thread;if(thread.sliceGroup.openSliceCount){const slice=thread.sliceGroup.mostRecentlyOpenedPartialSlice;if(slice.title!==title){this.importer.model.importWarning({type:'title_match_error',message:'Titles do not match. Title is '+
+slice.title+' in openSlice, and is '+
+title+' in endSlice'});}else{thread.sliceGroup.endSlice(ts);}}},logEvent(eventName,cpuNumber,pid,ts,eventBase){const innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('GestureLog',ts,{name:innerEvent[2]});break;case'end':this.gestureCloseSlice('GestureLog',ts);}
+return true;},syncEvent(eventName,cpuNumber,pid,ts,eventBase){const innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('SyncInterpret',ts,{interpreter:innerEvent[2]});break;case'end':this.gestureCloseSlice('SyncInterpret',ts);}
+return true;},timerEvent(eventName,cpuNumber,pid,ts,eventBase){const innerEvent=/^\s*(\w+):\s*(\w+)$/.exec(eventBase.details);switch(innerEvent[1]){case'start':this.gestureOpenSlice('HandleTimer',ts,{interpreter:innerEvent[2]});break;case'end':this.gestureCloseSlice('HandleTimer',ts);}
+return true;}};Parser.register(GestureParser);return{GestureParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function I2cParser(importer){Parser.call(this,importer);importer.registerEventHandler('i2c_write',I2cParser.prototype.i2cWriteEvent.bind(this));importer.registerEventHandler('i2c_read',I2cParser.prototype.i2cReadEvent.bind(this));importer.registerEventHandler('i2c_reply',I2cParser.prototype.i2cReplyEvent.bind(this));importer.registerEventHandler('i2c_result',I2cParser.prototype.i2cResultEvent.bind(this));}
+const i2cWriteReplyRE=new RegExp('i2c-(\\d+) #(\\d+) a=([\\da-fA-F]+) f=([\\da-fA-F]+) l=(\\d+) '+'(\\[[\\da-fA-F\\-]+\\])');const i2cReadRE=/i2c-(\d+) #(\d+) a=([\da-fA-F]+) f=([\da-fA-F]+) l=(\d+)/;const i2cResultRE=/i2c-(\d+) n=(\d+) ret=(\d+)/;I2cParser.prototype={__proto__:Parser.prototype,i2cWriteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=i2cWriteReplyRE.exec(eventBase.details);if(!event)return false;const adapterNumber=parseInt(event[1]);const messageNumber=event[2];const address=event[3];const flags=event[4];const dataLength=event[5];const data=event[6];const thread=this.importer.getOrCreatePseudoThread('i2c adapter '+adapterNumber);pushLastSliceIfNeeded(thread,event[1],ts);thread.lastEntryTitle='i2c write';thread.lastEntryTs=ts;thread.lastEntryArgs={'Message number':messageNumber,'Address':address,'Flags':flags,'Data Length':dataLength,'Data':data};return true;},i2cReadEvent(eventName,cpuNumber,pid,ts,eventBase){const event=i2cReadRE.exec(eventBase.details);if(!event)return false;const adapterNumber=parseInt(event[1]);const messageNumber=event[2];const address=event[3];const flags=event[4];const dataLength=event[5];const thread=this.importer.getOrCreatePseudoThread('i2c adapter '+adapterNumber);pushLastSliceIfNeeded(thread,event[1],ts);thread.lastEntryTitle='i2c read';thread.lastEntryTs=ts;thread.lastEntryArgs={'Message number':messageNumber,'Address':address,'Flags':flags,'Data Length':dataLength};return true;},i2cReplyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=i2cWriteReplyRE.exec(eventBase.details);if(!event)return false;const adapterNumber=parseInt(event[1]);const messageNumber=event[2];const address=event[3];const flags=event[4];const dataLength=event[5];const data=event[6];const thread=this.importer.getOrCreatePseudoThread('i2c adapter '+adapterNumber);pushLastSliceIfNeeded(thread,event[1],ts);thread.lastEntryTitle='i2c reply';thread.lastEntryTs=ts;thread.lastEntryArgs={'Message number':messageNumber,'Address':address,'Flags':flags,'Data Length':dataLength,'Data':data};return true;},i2cResultEvent(eventName,cpuNumber,pid,ts,eventBase){const event=i2cResultRE.exec(eventBase.details);if(!event)return false;const adapterNumber=parseInt(event[1]);const numMessages=event[2];const ret=event[3];const thread=this.importer.getOrCreatePseudoThread('i2c adapter '+adapterNumber);const args=thread.lastEntryArgs;if(args!==undefined){args['Number of messages']=numMessages;args.Return=ret;}
+pushLastSliceIfNeeded(thread,event[1],ts);thread.lastEntryTitle=undefined;thread.lastEntryTs=undefined;thread.lastEntryArgs=undefined;return true;},};function pushLastSliceIfNeeded(thread,id,currentTs){if(thread.lastEntryTs!==undefined){const duration=currentTs-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('',thread.lastEntryTitle,ColorScheme.getColorIdForGeneralPurposeString(id),thread.lastEntryTs,thread.lastEntryArgs,duration);thread.thread.sliceGroup.pushSlice(slice);}}
+Parser.register(I2cParser);return{I2cParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function I915Parser(importer){Parser.call(this,importer);importer.registerEventHandler('i915_gem_object_create',I915Parser.prototype.gemObjectCreateEvent.bind(this));importer.registerEventHandler('i915_gem_object_bind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_unbind',I915Parser.prototype.gemObjectBindEvent.bind(this));importer.registerEventHandler('i915_gem_object_change_domain',I915Parser.prototype.gemObjectChangeDomainEvent.bind(this));importer.registerEventHandler('i915_gem_object_pread',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_pwrite',I915Parser.prototype.gemObjectPreadWriteEvent.bind(this));importer.registerEventHandler('i915_gem_object_fault',I915Parser.prototype.gemObjectFaultEvent.bind(this));importer.registerEventHandler('i915_gem_object_clflush',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_object_destroy',I915Parser.prototype.gemObjectDestroyEvent.bind(this));importer.registerEventHandler('i915_gem_ring_dispatch',I915Parser.prototype.gemRingDispatchEvent.bind(this));importer.registerEventHandler('i915_gem_ring_flush',I915Parser.prototype.gemRingFlushEvent.bind(this));importer.registerEventHandler('i915_gem_request',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_add',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_complete',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_retire',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_begin',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_request_wait_end',I915Parser.prototype.gemRequestEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_begin',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_gem_ring_wait_end',I915Parser.prototype.gemRingWaitEvent.bind(this));importer.registerEventHandler('i915_reg_rw',I915Parser.prototype.regRWEvent.bind(this));importer.registerEventHandler('i915_flip_request',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('i915_flip_complete',I915Parser.prototype.flipEvent.bind(this));importer.registerEventHandler('intel_gpu_freq_change',I915Parser.prototype.gpuFrequency.bind(this));}
+I915Parser.prototype={__proto__:Parser.prototype,i915FlipOpenSlice(ts,obj,plane){const kthread=this.importer.getOrCreatePseudoThread('i915_flip');kthread.openSliceTS=ts;kthread.openSlice='flip:'+obj+'/'+plane;},i915FlipCloseSlice(ts,args){const kthread=this.importer.getOrCreatePseudoThread('i915_flip');if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,args,ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;},i915GemObjectSlice(ts,eventName,obj,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gem');kthread.openSlice=eventName+':'+obj;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915GemRingSlice(ts,eventName,dev,ring,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gem_ring');kthread.openSlice=eventName+':'+dev+'.'+ring;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915RegSlice(ts,eventName,reg,args){const kthread=this.importer.getOrCreatePseudoThread('i915_reg');kthread.openSlice=eventName+':'+reg;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},i915FreqChangeSlice(ts,eventName,args){const kthread=this.importer.getOrCreatePseudoThread('i915_gpu_freq');kthread.openSlice=eventName;const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),ts,args,0);kthread.thread.sliceGroup.pushSlice(slice);},gemObjectCreateEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const size=parseInt(event[2]);this.i915GemObjectSlice(ts,eventName,obj,{obj,size});return true;},gemObjectBindEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), offset=(\w+), size=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const offset=event[2];const size=parseInt(event[3]);this.i915ObjectGemSlice(ts,eventName+':'+obj,{obj,offset,size});return true;},gemObjectChangeDomainEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), read=(\w+=>\w+), write=(\w+=>\w+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const read=event[2];const write=event[3];this.i915GemObjectSlice(ts,eventName,obj,{obj,read,write});return true;},gemObjectPreadWriteEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), offset=(\d+), len=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const offset=parseInt(event[2]);const len=parseInt(event[3]);this.i915GemObjectSlice(ts,eventName,obj,{obj,offset,len});return true;},gemObjectFaultEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+), (\w+) index=(\d+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];const type=event[2];const index=parseInt(event[3]);this.i915GemObjectSlice(ts,eventName,obj,{obj,type,index});return true;},gemObjectDestroyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/obj=(\w+)/.exec(eventBase.details);if(!event)return false;const obj=event[1];this.i915GemObjectSlice(ts,eventName,obj,{obj});return true;},gemRingDispatchEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const seqno=parseInt(event[3]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,seqno});return true;},gemRingFlushEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\w+), invalidate=(\w+), flush=(\w+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const invalidate=event[3];const flush=event[4];this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,invalidate,flush});return true;},gemRequestEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+), seqno=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);const seqno=parseInt(event[3]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring,seqno});return true;},gemRingWaitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/dev=(\d+), ring=(\d+)/.exec(eventBase.details);if(!event)return false;const dev=parseInt(event[1]);const ring=parseInt(event[2]);this.i915GemRingSlice(ts,eventName,dev,ring,{dev,ring});return true;},regRWEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/(\w+) reg=(\w+), len=(\d+), val=(\(\w+, \w+\))/.exec(eventBase.details);if(!event)return false;const rw=event[1];const reg=event[2];const len=event[3];const data=event[3];this.i915RegSlice(ts,rw,reg,{rw,reg,len,data});return true;},flipEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/plane=(\d+), obj=(\w+)/.exec(eventBase.details);if(!event)return false;const plane=parseInt(event[1]);const obj=event[2];if(eventName==='i915_flip_request'){this.i915FlipOpenSlice(ts,obj,plane);}else{this.i915FlipCloseSlice(ts,{obj,plane});}
+return true;},gpuFrequency(eventName,cpuNumver,pid,ts,eventBase){const event=/new_freq=(\d+)/.exec(eventBase.details);if(!event)return false;const freq=parseInt(event[1]);this.i915FreqChangeSlice(ts,eventName,{freq});return true;}};Parser.register(I915Parser);return{I915Parser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function IonHeapParser(importer){Parser.call(this,importer);importer.registerEventHandler('ion_heap_shrink',IonHeapParser.prototype.traceIonHeapShrink.bind(this));importer.registerEventHandler('ion_heap_grow',IonHeapParser.prototype.traceIonHeapGrow.bind(this));this.model_=importer.model_;}
+const TestExports={};const ionHeapRE=new RegExp('heap_name=(\\S+), len=(\\d+), total_allocated=(\\d+)');TestExports.ionHeapRE=ionHeapRE;IonHeapParser.prototype={__proto__:Parser.prototype,traceIonHeapShrink(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=ionHeapRE.exec(eventBase.details);if(!event)return false;const name=event[1];const len=parseInt(event[2]);const totalAllocated=parseInt(event[3]);const ionHeap=totalAllocated+len;const ctr=this.model_.kernel.getOrCreateCounter(null,name+' ion heap');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,ionHeap);});return true;},traceIonHeapGrow(eventName,cpuNumber,pid,ts,eventBase,threadName){const event=ionHeapRE.exec(eventBase.details);if(!event)return false;const name=event[1];const len=parseInt(event[2]);const totalAllocated=parseInt(event[3]);const ionHeap=totalAllocated+len;const ctr=this.model_.kernel.getOrCreateCounter(null,name+' ion heap');if(ctr.numSeries===0){ctr.addSeries(new tr.model.CounterSeries('value',ColorScheme.getColorIdForGeneralPurposeString(ctr.name+'.'+'value')));}
+ctr.series.forEach(function(series){series.addCounterSample(ts,ionHeap);});return true;}};Parser.register(IonHeapParser);return{IonHeapParser,_IonHeapParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function IrqParser(importer){Parser.call(this,importer);importer.registerEventHandler('irq_handler_entry',IrqParser.prototype.irqHandlerEntryEvent.bind(this));importer.registerEventHandler('irq_handler_exit',IrqParser.prototype.irqHandlerExitEvent.bind(this));importer.registerEventHandler('softirq_raise',IrqParser.prototype.softirqRaiseEvent.bind(this));importer.registerEventHandler('softirq_entry',IrqParser.prototype.softirqEntryEvent.bind(this));importer.registerEventHandler('softirq_exit',IrqParser.prototype.softirqExitEvent.bind(this));importer.registerEventHandler('ipi_entry',IrqParser.prototype.ipiEntryEvent.bind(this));importer.registerEventHandler('ipi_exit',IrqParser.prototype.ipiExitEvent.bind(this));importer.registerEventHandler('preempt_disable',IrqParser.prototype.preemptStartEvent.bind(this));importer.registerEventHandler('preempt_enable',IrqParser.prototype.preemptEndEvent.bind(this));importer.registerEventHandler('irq_disable',IrqParser.prototype.irqoffStartEvent.bind(this));importer.registerEventHandler('irq_enable',IrqParser.prototype.irqoffEndEvent.bind(this));}
+const irqHandlerEntryRE=/irq=(\d+) name=(.+)/;const irqHandlerExitRE=/irq=(\d+) ret=(.+)/;const softirqRE=/vec=(\d+) \[action=(.+)\]/;const ipiHandlerExitRE=/\((.+)\)/;const preemptirqRE=/caller=(.+) parent=(.+)/;IrqParser.prototype={__proto__:Parser.prototype,irqHandlerEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const event=irqHandlerEntryRE.exec(eventBase.details);if(!event)return false;const irq=parseInt(event[1]);const name=event[2];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);thread.lastEntryTs=ts;thread.irqName=name;return true;},irqHandlerExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=irqHandlerExitRE.exec(eventBase.details);if(!event)return false;const irq=parseInt(event[1]);const ret=event[2];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('','IRQ ('+thread.irqName+')',ColorScheme.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{ret},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;thread.irqName=undefined;return true;},softirqRaiseEvent(eventName,cpuNumber,pid,ts,eventBase){return true;},softirqEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const event=softirqRE.exec(eventBase.details);if(!event)return false;const action=event[2];const thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);thread.lastEntryTs=ts;return true;},softirqExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=softirqRE.exec(eventBase.details);if(!event)return false;const vec=parseInt(event[1]);const action=event[2];const thread=this.importer.getOrCreatePseudoThread('softirq cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('',action,ColorScheme.getColorIdForGeneralPurposeString(event[1]),thread.lastEntryTs,{vec},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;return true;},ipiEntryEvent(eventName,cpuNumber,pid,ts,eventBase){const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);thread.lastEntryTs=ts;return true;},ipiExitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=ipiHandlerExitRE.exec(eventBase.details);if(!event)return false;const ipiName=event[1];const thread=this.importer.getOrCreatePseudoThread('irqs cpu '+cpuNumber);if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('','IPI ('+ipiName+')',ColorScheme.getColorIdForGeneralPurposeString(ipiName),thread.lastEntryTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;return true;},preemptStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=preemptirqRE.exec(eventBase.details);if(!event)return false;const thread=this.importer.getOrCreatePseudoThread('preempt cpu '+cpuNumber);thread.lastEntryTs=ts;thread.preemptStartCaller=event[1];thread.preemptStartParent=event[2];return true;},preemptEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=preemptirqRE.exec(eventBase.details);if(!event)return false;const thread=this.importer.getOrCreatePseudoThread('preempt cpu '+cpuNumber);thread.preemptEndCaller=event[1];thread.preemptEndParent=event[2];if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('',thread.preemptStartParent+': '+thread.preemptStartCaller,ColorScheme.getColorIdForGeneralPurposeString(thread.preemptEndCaller),thread.lastEntryTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;return true;},irqoffStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=preemptirqRE.exec(eventBase.details);if(!event)return false;const thread=this.importer.getOrCreatePseudoThread('irqoff cpu '+cpuNumber);thread.lastEntryTs=ts;thread.irqoffStartCaller=event[1];thread.irqoffStartParent=event[2];return true;},irqoffEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=preemptirqRE.exec(eventBase.details);if(!event)return false;const thread=this.importer.getOrCreatePseudoThread('irqoff cpu '+cpuNumber);thread.irqoffEndCaller=event[1];thread.irqoffEndParent=event[2];if(thread.lastEntryTs!==undefined){const duration=ts-thread.lastEntryTs;const slice=new tr.model.ThreadSlice('',thread.irqoffStartParent+': '+thread.irqoffStartCaller,ColorScheme.getColorIdForGeneralPurposeString(thread.irqoffEndCaller),thread.lastEntryTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastEntryTs=undefined;return true;}};Parser.register(IrqParser);return{IrqParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const LinuxPerfParser=tr.e.importer.linux_perf.Parser;function KernelFuncParser(importer){LinuxPerfParser.call(this,importer);importer.registerEventHandler('graph_ent',KernelFuncParser.prototype.traceKernelFuncEnterEvent.bind(this));importer.registerEventHandler('graph_ret',KernelFuncParser.prototype.traceKernelFuncReturnEvent.bind(this));this.model_=importer.model_;this.ppids_={};}
+const TestExports={};const funcEnterRE=new RegExp('func=(.+)');TestExports.funcEnterRE=funcEnterRE;KernelFuncParser.prototype={__proto__:LinuxPerfParser.prototype,traceKernelFuncEnterEvent(eventName,cpuNumber,pid,ts,eventBase){const eventData=funcEnterRE.exec(eventBase.details);if(!eventData)return false;if(eventBase.tgid===undefined){return false;}
+const tgid=parseInt(eventBase.tgid);const name=eventData[1];const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+const slice=slices.beginSlice(null,name,ts,{});return true;},traceKernelFuncReturnEvent(eventName,cpuNumber,pid,ts,eventBase){if(eventBase.tgid===undefined){return false;}
+const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+if(slices.openSliceCount>0){slices.endSlice(ts);}
+return true;}};LinuxPerfParser.register(KernelFuncParser);return{KernelFuncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function MaliParser(importer){Parser.call(this,importer);importer.registerEventHandler('mali_dvfs_event',MaliParser.prototype.dvfsEventEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_clock',MaliParser.prototype.dvfsSetClockEvent.bind(this));importer.registerEventHandler('mali_dvfs_set_voltage',MaliParser.prototype.dvfsSetVoltageEvent.bind(this));this.addJMCounter('mali_hwc_MESSAGES_SENT','Messages Sent');this.addJMCounter('mali_hwc_MESSAGES_RECEIVED','Messages Received');this.addJMCycles('mali_hwc_GPU_ACTIVE','GPU Active');this.addJMCycles('mali_hwc_IRQ_ACTIVE','IRQ Active');for(let i=0;i<7;i++){const jobStr='JS'+i;const jobHWCStr='mali_hwc_'+jobStr;this.addJMCounter(jobHWCStr+'_JOBS',jobStr+' Jobs');this.addJMCounter(jobHWCStr+'_TASKS',jobStr+' Tasks');this.addJMCycles(jobHWCStr+'_ACTIVE',jobStr+' Active');this.addJMCycles(jobHWCStr+'_WAIT_READ',jobStr+' Wait Read');this.addJMCycles(jobHWCStr+'_WAIT_ISSUE',jobStr+' Wait Issue');this.addJMCycles(jobHWCStr+'_WAIT_DEPEND',jobStr+' Wait Depend');this.addJMCycles(jobHWCStr+'_WAIT_FINISH',jobStr+' Wait Finish');}
+this.addTilerCounter('mali_hwc_TRIANGLES','Triangles');this.addTilerCounter('mali_hwc_QUADS','Quads');this.addTilerCounter('mali_hwc_POLYGONS','Polygons');this.addTilerCounter('mali_hwc_POINTS','Points');this.addTilerCounter('mali_hwc_LINES','Lines');this.addTilerCounter('mali_hwc_VCACHE_HIT','VCache Hit');this.addTilerCounter('mali_hwc_VCACHE_MISS','VCache Miss');this.addTilerCounter('mali_hwc_FRONT_FACING','Front Facing');this.addTilerCounter('mali_hwc_BACK_FACING','Back Facing');this.addTilerCounter('mali_hwc_PRIM_VISIBLE','Prim Visible');this.addTilerCounter('mali_hwc_PRIM_CULLED','Prim Culled');this.addTilerCounter('mali_hwc_PRIM_CLIPPED','Prim Clipped');this.addTilerCounter('mali_hwc_WRBUF_HIT','Wrbuf Hit');this.addTilerCounter('mali_hwc_WRBUF_MISS','Wrbuf Miss');this.addTilerCounter('mali_hwc_WRBUF_LINE','Wrbuf Line');this.addTilerCounter('mali_hwc_WRBUF_PARTIAL','Wrbuf Partial');this.addTilerCounter('mali_hwc_WRBUF_STALL','Wrbuf Stall');this.addTilerCycles('mali_hwc_ACTIVE','Tiler Active');this.addTilerCycles('mali_hwc_INDEX_WAIT','Index Wait');this.addTilerCycles('mali_hwc_INDEX_RANGE_WAIT','Index Range Wait');this.addTilerCycles('mali_hwc_VERTEX_WAIT','Vertex Wait');this.addTilerCycles('mali_hwc_PCACHE_WAIT','Pcache Wait');this.addTilerCycles('mali_hwc_WRBUF_WAIT','Wrbuf Wait');this.addTilerCycles('mali_hwc_BUS_READ','Bus Read');this.addTilerCycles('mali_hwc_BUS_WRITE','Bus Write');this.addTilerCycles('mali_hwc_TILER_UTLB_STALL','Tiler UTLB Stall');this.addTilerCycles('mali_hwc_TILER_UTLB_HIT','Tiler UTLB Hit');this.addFragCycles('mali_hwc_FRAG_ACTIVE','Active');this.addFragCounter('mali_hwc_FRAG_PRIMATIVES','Primitives');this.addFragCounter('mali_hwc_FRAG_PRIMATIVES_DROPPED','Primitives Dropped');this.addFragCycles('mali_hwc_FRAG_CYCLE_DESC','Descriptor Processing');this.addFragCycles('mali_hwc_FRAG_CYCLES_PLR','PLR Processing??');this.addFragCycles('mali_hwc_FRAG_CYCLES_VERT','Vertex Processing');this.addFragCycles('mali_hwc_FRAG_CYCLES_TRISETUP','Triangle Setup');this.addFragCycles('mali_hwc_FRAG_CYCLES_RAST','Rasterization???');this.addFragCounter('mali_hwc_FRAG_THREADS','Threads');this.addFragCounter('mali_hwc_FRAG_DUMMY_THREADS','Dummy Threads');this.addFragCounter('mali_hwc_FRAG_QUADS_RAST','Quads Rast');this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_TEST','Quads EZS Test');this.addFragCounter('mali_hwc_FRAG_QUADS_EZS_KILLED','Quads EZS Killed');this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_TEST','Quads LZS Test');this.addFragCounter('mali_hwc_FRAG_QUADS_LZS_KILLED','Quads LZS Killed');this.addFragCycles('mali_hwc_FRAG_CYCLE_NO_TILE','No Tiles');this.addFragCounter('mali_hwc_FRAG_NUM_TILES','Tiles');this.addFragCounter('mali_hwc_FRAG_TRANS_ELIM','Transactions Eliminated');this.addComputeCycles('mali_hwc_COMPUTE_ACTIVE','Active');this.addComputeCounter('mali_hwc_COMPUTE_TASKS','Tasks');this.addComputeCounter('mali_hwc_COMPUTE_THREADS','Threads Started');this.addComputeCycles('mali_hwc_COMPUTE_CYCLES_DESC','Waiting for Descriptors');this.addTripipeCycles('mali_hwc_TRIPIPE_ACTIVE','Active');this.addArithCounter('mali_hwc_ARITH_WORDS','Instructions (/Pipes)');this.addArithCycles('mali_hwc_ARITH_CYCLES_REG','Reg scheduling stalls (/Pipes)');this.addArithCycles('mali_hwc_ARITH_CYCLES_L0','L0 cache miss stalls (/Pipes)');this.addArithCounter('mali_hwc_ARITH_FRAG_DEPEND','Frag dep check failures (/Pipes)');this.addLSCounter('mali_hwc_LS_WORDS','Instruction Words Completed');this.addLSCounter('mali_hwc_LS_ISSUES','Full Pipeline Issues');this.addLSCounter('mali_hwc_LS_RESTARTS','Restarts (unpairable insts)');this.addLSCounter('mali_hwc_LS_REISSUES_MISS','Pipeline reissue (cache miss/uTLB)');this.addLSCounter('mali_hwc_LS_REISSUES_VD','Pipeline reissue (varying data)');this.addLSCounter('mali_hwc_LS_REISSUE_ATTRIB_MISS','Pipeline reissue (attribute cache miss)');this.addLSCounter('mali_hwc_LS_REISSUE_NO_WB','Writeback not used');this.addTexCounter('mali_hwc_TEX_WORDS','Words');this.addTexCounter('mali_hwc_TEX_BUBBLES','Bubbles');this.addTexCounter('mali_hwc_TEX_WORDS_L0','Words L0');this.addTexCounter('mali_hwc_TEX_WORDS_DESC','Words Desc');this.addTexCounter('mali_hwc_TEX_THREADS','Threads');this.addTexCounter('mali_hwc_TEX_RECIRC_FMISS','Recirc due to Full Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_DESC','Recirc due to Desc Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_MULTI','Recirc due to Multipass');this.addTexCounter('mali_hwc_TEX_RECIRC_PMISS','Recirc due to Partial Cache Miss');this.addTexCounter('mali_hwc_TEX_RECIRC_CONF','Recirc due to Cache Conflict');this.addLSCCounter('mali_hwc_LSC_READ_HITS','Read Hits');this.addLSCCounter('mali_hwc_LSC_READ_MISSES','Read Misses');this.addLSCCounter('mali_hwc_LSC_WRITE_HITS','Write Hits');this.addLSCCounter('mali_hwc_LSC_WRITE_MISSES','Write Misses');this.addLSCCounter('mali_hwc_LSC_ATOMIC_HITS','Atomic Hits');this.addLSCCounter('mali_hwc_LSC_ATOMIC_MISSES','Atomic Misses');this.addLSCCounter('mali_hwc_LSC_LINE_FETCHES','Line Fetches');this.addLSCCounter('mali_hwc_LSC_DIRTY_LINE','Dirty Lines');this.addLSCCounter('mali_hwc_LSC_SNOOPS','Snoops');this.addAXICounter('mali_hwc_AXI_TLB_STALL','Address channel stall');this.addAXICounter('mali_hwc_AXI_TLB_MISS','Cache Miss');this.addAXICounter('mali_hwc_AXI_TLB_TRANSACTION','Transactions');this.addAXICounter('mali_hwc_LS_TLB_MISS','LS Cache Miss');this.addAXICounter('mali_hwc_LS_TLB_HIT','LS Cache Hit');this.addAXICounter('mali_hwc_AXI_BEATS_READ','Read Beats');this.addAXICounter('mali_hwc_AXI_BEATS_WRITE','Write Beats');this.addMMUCounter('mali_hwc_MMU_TABLE_WALK','Page Table Walks');this.addMMUCounter('mali_hwc_MMU_REPLAY_MISS','Cache Miss from Replay Buffer');this.addMMUCounter('mali_hwc_MMU_REPLAY_FULL','Replay Buffer Full');this.addMMUCounter('mali_hwc_MMU_NEW_MISS','Cache Miss on New Request');this.addMMUCounter('mali_hwc_MMU_HIT','Cache Hit');this.addMMUCycles('mali_hwc_UTLB_STALL','UTLB Stalled');this.addMMUCycles('mali_hwc_UTLB_REPLAY_MISS','UTLB Replay Miss');this.addMMUCycles('mali_hwc_UTLB_REPLAY_FULL','UTLB Replay Full');this.addMMUCycles('mali_hwc_UTLB_NEW_MISS','UTLB New Miss');this.addMMUCycles('mali_hwc_UTLB_HIT','UTLB Hit');this.addL2Counter('mali_hwc_L2_READ_BEATS','Read Beats');this.addL2Counter('mali_hwc_L2_WRITE_BEATS','Write Beats');this.addL2Counter('mali_hwc_L2_ANY_LOOKUP','Any Lookup');this.addL2Counter('mali_hwc_L2_READ_LOOKUP','Read Lookup');this.addL2Counter('mali_hwc_L2_SREAD_LOOKUP','Shareable Read Lookup');this.addL2Counter('mali_hwc_L2_READ_REPLAY','Read Replayed');this.addL2Counter('mali_hwc_L2_READ_SNOOP','Read Snoop');this.addL2Counter('mali_hwc_L2_READ_HIT','Read Cache Hit');this.addL2Counter('mali_hwc_L2_CLEAN_MISS','CleanUnique Miss');this.addL2Counter('mali_hwc_L2_WRITE_LOOKUP','Write Lookup');this.addL2Counter('mali_hwc_L2_SWRITE_LOOKUP','Shareable Write Lookup');this.addL2Counter('mali_hwc_L2_WRITE_REPLAY','Write Replayed');this.addL2Counter('mali_hwc_L2_WRITE_SNOOP','Write Snoop');this.addL2Counter('mali_hwc_L2_WRITE_HIT','Write Cache Hit');this.addL2Counter('mali_hwc_L2_EXT_READ_FULL','ExtRD with BIU Full');this.addL2Counter('mali_hwc_L2_EXT_READ_HALF','ExtRD with BIU >1/2 Full');this.addL2Counter('mali_hwc_L2_EXT_WRITE_FULL','ExtWR with BIU Full');this.addL2Counter('mali_hwc_L2_EXT_WRITE_HALF','ExtWR with BIU >1/2 Full');this.addL2Counter('mali_hwc_L2_EXT_READ','External Read (ExtRD)');this.addL2Counter('mali_hwc_L2_EXT_READ_LINE','ExtRD (linefill)');this.addL2Counter('mali_hwc_L2_EXT_WRITE','External Write (ExtWR)');this.addL2Counter('mali_hwc_L2_EXT_WRITE_LINE','ExtWR (linefill)');this.addL2Counter('mali_hwc_L2_EXT_WRITE_SMALL','ExtWR (burst size <64B)');this.addL2Counter('mali_hwc_L2_EXT_BARRIER','External Barrier');this.addL2Counter('mali_hwc_L2_EXT_AR_STALL','Address Read stalls');this.addL2Counter('mali_hwc_L2_EXT_R_BUF_FULL','Response Buffer full stalls');this.addL2Counter('mali_hwc_L2_EXT_RD_BUF_FULL','Read Data Buffer full stalls');this.addL2Counter('mali_hwc_L2_EXT_R_RAW','RAW hazard stalls');this.addL2Counter('mali_hwc_L2_EXT_W_STALL','Write Data stalls');this.addL2Counter('mali_hwc_L2_EXT_W_BUF_FULL','Write Data Buffer full');this.addL2Counter('mali_hwc_L2_EXT_R_W_HAZARD','WAW or WAR hazard stalls');this.addL2Counter('mali_hwc_L2_TAG_HAZARD','Tag hazard replays');this.addL2Cycles('mali_hwc_L2_SNOOP_FULL','Snoop buffer full');this.addL2Cycles('mali_hwc_L2_REPLAY_FULL','Replay buffer full');importer.registerEventHandler('tracing_mark_write:mali_driver',MaliParser.prototype.maliDDKEvent.bind(this));importer.registerEventHandler('mali_job_systrace_event_start',MaliParser.prototype.maliJobEvent.bind(this));importer.registerEventHandler('mali_job_systrace_event_stop',MaliParser.prototype.maliJobEvent.bind(this));this.model_=importer.model_;this.deferredJobs_={};}
+MaliParser.prototype={__proto__:Parser.prototype,maliDDKOpenSlice(pid,tid,ts,func,blockinfo){const thread=this.importer.model_.getOrCreateProcess(pid).getOrCreateThread(tid);const funcArgs=/^([\w\d_]*)(?:\(\))?:?\s*(.*)$/.exec(func);thread.sliceGroup.beginSlice('gpu-driver',funcArgs[1],ts,{'args':funcArgs[2],blockinfo});},maliDDKCloseSlice(pid,tid,ts,args,blockinfo){const thread=this.importer.model_.getOrCreateProcess(pid).getOrCreateThread(tid);if(!thread.sliceGroup.openSliceCount){return;}
+thread.sliceGroup.endSlice(ts);},autoDetectLineRE(line){const lineREWithThread=/^\s*\(([\w\-]*)\)\s*(\w+):\s*([\w\\\/\.\-]*@\d*):?\s*(.*)$/;if(lineREWithThread.test(line)){return lineREWithThread;}
+const lineRENoThread=/^s*()(\w+):\s*([\w\\\/.\-]*):?\s*(.*)$/;if(lineRENoThread.test(line)){return lineRENoThread;}
+return null;},lineRE:null,maliDDKEvent(eventName,cpuNumber,pid,ts,eventBase){if(this.lineRE===null){this.lineRE=this.autoDetectLineRE(eventBase.details);if(this.lineRE===null)return false;}
+const maliEvent=this.lineRE.exec(eventBase.details);const tid=(maliEvent[1]===''?'mali':maliEvent[1]);switch(maliEvent[2]){case'cros_trace_print_enter':this.maliDDKOpenSlice(pid,tid,ts,maliEvent[4],maliEvent[3]);break;case'cros_trace_print_exit':this.maliDDKCloseSlice(pid,tid,ts,[],maliEvent[3]);}
+return true;},maliJobEvent(eventName,cpuNumber,pid,ts,eventBase){const jobEventRE=/^.*tracing_mark_write: (S|F)\|(\d+)\|(\w+)-job\|(\d+)\|(\d+)\|(\d+)\|(\d+)\|(\d+)\|([a-z0-9]+)\|(\d+)$/;const jobEvent=jobEventRE.exec(eventBase.details);if(!jobEvent){this.model_.importWarning({type:'parse_error',args:'unexpected mali_job_systrace_event_* event syntax'});return;}
+const jobType=jobEvent[3];const jobId=jobEvent[4];const thread=this.importer.model_.getOrCreateProcess(0).getOrCreateThread('mali:'+jobType);switch(jobEvent[1]){case'S':{const args={ctx:jobEvent[9],pid:parseInt(jobEvent[2],10),dep0:parseInt(jobEvent[5],10),dep1:parseInt(jobEvent[7],10)};if(thread.sliceGroup.openSliceCount){if(!(jobType in this.deferredJobs_)){this.deferredJobs_[jobType]=[];}
+this.deferredJobs_[jobType].push({id:jobId,args});}else{thread.sliceGroup.beginSlice(null,jobId,ts,args);}}break;case'F':{if(!thread.sliceGroup.openSliceCount){return;}
+if(thread.sliceGroup.mostRecentlyOpenedPartialSlice.title!==jobId){this.model_.importWarning({type:'invalid event nesting',message:'non-sequential jobs in same mali job slot'});}
+thread.sliceGroup.endSlice(ts);const deferredJobs=this.deferredJobs_[jobType];if(deferredJobs&&deferredJobs.length){const job=deferredJobs.shift();thread.sliceGroup.beginSlice(null,job.id,ts,job.args);}}break;}
+return true;},dvfsSample(counterName,seriesName,ts,s){const value=parseInt(s);const counter=this.model_.kernel.getOrCreateCounter('DVFS',counterName);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries(seriesName,ColorScheme.getColorIdForGeneralPurposeString(counter.name)));}
+counter.series.forEach(function(series){series.addCounterSample(ts,value);});},dvfsEventEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/utilization=(\d+)/.exec(eventBase.details);if(!event)return false;this.dvfsSample('DVFS Utilization','utilization',ts,event[1]);return true;},dvfsSetClockEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/frequency=(\d+)/.exec(eventBase.details);if(!event)return false;this.dvfsSample('DVFS Frequency','frequency',ts,event[1]);return true;},dvfsSetVoltageEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/voltage=(\d+)/.exec(eventBase.details);if(!event)return false;this.dvfsSample('DVFS Voltage','voltage',ts,event[1]);return true;},hwcSample(cat,counterName,seriesName,ts,eventBase){const event=/val=(\d+)/.exec(eventBase.details);if(!event)return false;const value=parseInt(event[1]);const counter=this.model_.kernel.getOrCreateCounter(cat,counterName);if(counter.numSeries===0){counter.addSeries(new tr.model.CounterSeries(seriesName,ColorScheme.getColorIdForGeneralPurposeString(counter.name)));}
+counter.series.forEach(function(series){series.addCounterSample(ts,value);});return true;},jmSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:jm','JM: '+ctrName,seriesName,ts,eventBase);},addJMCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.jmSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addJMCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.jmSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},tilerSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:tiler','Tiler: '+ctrName,seriesName,ts,eventBase);},addTilerCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.tilerSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addTilerCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.tilerSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},fragSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:fragment','Fragment: '+ctrName,seriesName,ts,eventBase);},addFragCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.fragSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addFragCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.fragSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},computeSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:compute','Compute: '+ctrName,seriesName,ts,eventBase);},addComputeCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.computeSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addComputeCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.computeSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addTripipeCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.hwcSample('mali:shader','Tripipe: '+hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},arithSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:arith','Arith: '+ctrName,seriesName,ts,eventBase);},addArithCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.arithSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addArithCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.arithSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addLSCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.hwcSample('mali:ls','LS: '+hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},textureSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:texture','Texture: '+ctrName,seriesName,ts,eventBase);},addTexCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.textureSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addLSCCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.hwcSample('mali:lsc','LSC: '+hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addAXICounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.hwcSample('mali:axi','AXI: '+hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},mmuSample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:mmu','MMU: '+ctrName,seriesName,ts,eventBase);},addMMUCounter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.mmuSample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addMMUCycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.mmuSample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},l2Sample(ctrName,seriesName,ts,eventBase){return this.hwcSample('mali:l2','L2: '+ctrName,seriesName,ts,eventBase);},addL2Counter(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'count',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));},addL2Cycles(hwcEventName,hwcTitle){function handler(eventName,cpuNumber,pid,ts,eventBase){return this.l2Sample(hwcTitle,'cycles',ts,eventBase);}
+this.importer.registerEventHandler(hwcEventName,handler.bind(this));}};Parser.register(MaliParser);return{MaliParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function MemReclaimParser(importer){Parser.call(this,importer);importer.registerEventHandler('mm_vmscan_kswapd_wake',MemReclaimParser.prototype.kswapdWake.bind(this));importer.registerEventHandler('mm_vmscan_kswapd_sleep',MemReclaimParser.prototype.kswapdSleep.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_begin',MemReclaimParser.prototype.reclaimBegin.bind(this));importer.registerEventHandler('mm_vmscan_direct_reclaim_end',MemReclaimParser.prototype.reclaimEnd.bind(this));importer.registerEventHandler('lowmemory_kill',MemReclaimParser.prototype.lowmemoryKill.bind(this));}
+const kswapdWakeRE=/nid=(\d+) order=(\d+)/;const kswapdSleepRE=/nid=(\d+)/;const reclaimBeginRE=/order=(\d+) may_writepage=\d+ gfp_flags=(.+)/;const reclaimEndRE=/nr_reclaimed=(\d+)/;const lowmemoryRE=/([^ ]+) \((\d+)\), page cache (\d+)kB \(limit (\d+)kB\), free (-?\d+)Kb/;MemReclaimParser.prototype={__proto__:Parser.prototype,kswapdWake(eventName,cpuNumber,pid,ts,eventBase){const event=kswapdWakeRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const nid=parseInt(event[1]);const order=parseInt(event[2]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){if(order>kthread.order){kthread.order=order;}}else{kthread.openSliceTS=ts;kthread.order=order;}
+return true;},kswapdSleep(eventName,cpuNumber,pid,ts,eventBase){const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim',eventBase.threadName,kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order});}
+kthread.openSliceTS=undefined;kthread.order=undefined;return true;},reclaimBegin(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimBeginRE.exec(eventBase.details);if(!event)return false;const order=parseInt(event[1]);const gfp=event[2];const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.openSliceTS=ts;kthread.order=order;kthread.gfp=gfp;return true;},reclaimEnd(eventName,cpuNumber,pid,ts,eventBase){const event=reclaimEndRE.exec(eventBase.details);if(!event)return false;const nrReclaimed=parseInt(event[1]);const tgid=parseInt(eventBase.tgid);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);if(kthread.openSliceTS!==undefined){kthread.thread.sliceGroup.pushCompleteSlice('memreclaim','direct reclaim',kthread.openSliceTS,ts-kthread.openSliceTS,0,0,{order:kthread.order,gfp:kthread.gfp,nr_reclaimed:nrReclaimed});}
+kthread.openSliceTS=undefined;kthread.order=undefined;kthread.gfp=undefined;return true;},lowmemoryKill(eventName,cpuNumber,pid,ts,eventBase){const event=lowmemoryRE.exec(eventBase.details);if(!event)return false;const tgid=parseInt(eventBase.tgid);const killedName=event[1];const killedPid=parseInt(event[2]);const cache=parseInt(event[3]);const free=parseInt(event[5]);const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,tgid,pid);kthread.thread.sliceGroup.pushCompleteSlice('lowmemory','low memory kill',ts,0,0,0,{killed_name:killedName,killed_pid:killedPid,cache,free});return true;}};Parser.register(MemReclaimParser);return{MemReclaimParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function PowerParser(importer){Parser.call(this,importer);importer.registerEventHandler('power_start',PowerParser.prototype.powerStartEvent.bind(this));importer.registerEventHandler('power_frequency',PowerParser.prototype.powerFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency',PowerParser.prototype.cpuFrequencyEvent.bind(this));importer.registerEventHandler('cpu_frequency_limits',PowerParser.prototype.cpuFrequencyLimitsEvent.bind(this));importer.registerEventHandler('cpu_idle',PowerParser.prototype.cpuIdleEvent.bind(this));}
+PowerParser.prototype={__proto__:Parser.prototype,cpuStateSlice(ts,targetCpuNumber,eventType,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);if(eventType!=='1'){this.importer.model.importWarning({type:'parse_error',message:'Don\'t understand power_start events of '+'type '+eventType});return;}
+const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
+powerCounter.series.forEach(function(series){series.addCounterSample(ts,cpuState);});},cpuIdleSlice(ts,targetCpuNumber,cpuState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','C-State');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name)));}
+const val=(cpuState!==4294967295?cpuState+1:0);powerCounter.series.forEach(function(series){series.addCounterSample(ts,val);});},cpuFrequencySlice(ts,targetCpuNumber,powerState){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','Clock Frequency');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('state',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'state')));}
+powerCounter.series.forEach(function(series){series.addCounterSample(ts,powerState);});},cpuFrequencyLimitsSlice(ts,targetCpuNumber,minFreq,maxFreq){const targetCpu=this.importer.getOrCreateCpu(targetCpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','Clock Frequency Limits');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('Min Frequency',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'Min Frequency')));powerCounter.addSeries(new tr.model.CounterSeries('Max Frequency',ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'Max Frequency')));}
+powerCounter.series.forEach(function(series){if(series.name==='Min Frequency'){series.addCounterSample(ts,minFreq);}
+if(series.name==='Max Frequency'){series.addCounterSample(ts,maxFreq);}});},powerStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/type=(\d+) state=(\d) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const cpuState=parseInt(event[2]);this.cpuStateSlice(ts,targetCpuNumber,event[1],cpuState);return true;},powerFrequencyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/type=(\d+) state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const powerState=parseInt(event[2]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuFrequencyEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[2]);const powerState=parseInt(event[1]);this.cpuFrequencySlice(ts,targetCpuNumber,powerState);return true;},cpuFrequencyLimitsEvent(eventName,cpu,pid,ts,eventBase){const event=/min=(\d+) max=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[3]);const minFreq=parseInt(event[1]);const maxFreq=parseInt(event[2]);this.cpuFrequencyLimitsSlice(ts,targetCpuNumber,minFreq,maxFreq);return true;},cpuIdleEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/state=(\d+) cpu_id=(\d+)/.exec(eventBase.details);if(!event)return false;const targetCpuNumber=parseInt(event[2]);const cpuState=parseInt(event[1]);this.cpuIdleSlice(ts,targetCpuNumber,cpuState);return true;}};Parser.register(PowerParser);return{PowerParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function RegulatorParser(importer){Parser.call(this,importer);importer.registerEventHandler('regulator_enable',RegulatorParser.prototype.regulatorEnableEvent.bind(this));importer.registerEventHandler('regulator_enable_delay',RegulatorParser.prototype.regulatorEnableDelayEvent.bind(this));importer.registerEventHandler('regulator_enable_complete',RegulatorParser.prototype.regulatorEnableCompleteEvent.bind(this));importer.registerEventHandler('regulator_disable',RegulatorParser.prototype.regulatorDisableEvent.bind(this));importer.registerEventHandler('regulator_disable_complete',RegulatorParser.prototype.regulatorDisableCompleteEvent.bind(this));importer.registerEventHandler('regulator_set_voltage',RegulatorParser.prototype.regulatorSetVoltageEvent.bind(this));importer.registerEventHandler('regulator_set_voltage_complete',RegulatorParser.prototype.regulatorSetVoltageCompleteEvent.bind(this));this.model_=importer.model_;}
+const regulatorEnableRE=/name=(.+)/;const regulatorDisableRE=/name=(.+)/;const regulatorSetVoltageCompleteRE=/name=(\S+), val=(\d+)/;RegulatorParser.prototype={__proto__:Parser.prototype,getCtr_(ctrName,valueName){const ctr=this.model_.kernel.getOrCreateCounter(null,'vreg '+ctrName+' '+valueName);if(ctr.series[0]===undefined){ctr.addSeries(new tr.model.CounterSeries(valueName,ColorScheme.getColorIdForGeneralPurposeString(ctrName+'.'+valueName)));}
+return ctr;},regulatorEnableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorEnableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,1);return true;},regulatorEnableDelayEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorEnableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorDisableEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorDisableRE.exec(eventBase.details);if(!event)return false;const name=event[1];const ctr=this.getCtr_(name,'enabled');ctr.series[0].addCounterSample(ts,0);return true;},regulatorDisableCompleteEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageEvent(eventName,cpuNum,pid,ts,eventBase){return true;},regulatorSetVoltageCompleteEvent(eventName,cpuNum,pid,ts,eventBase){const event=regulatorSetVoltageCompleteRE.exec(eventBase.details);if(!event)return false;const name=event[1];const voltage=parseInt(event[2]);const ctr=this.getCtr_(name,'voltage');ctr.series[0].addCounterSample(ts,voltage);return true;}};Parser.register(RegulatorParser);return{RegulatorParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function RssParser(importer){Parser.call(this,importer);importer.registerEventHandler('rss_stat',RssParser.prototype.rssStat.bind(this));}
+const TestExports={};const rssStatRE=new RegExp('member=(\\d+) size=(\\d+)');TestExports.rssStatRE=rssStatRE;const unknownThreadName='<...>';RssParser.prototype={__proto__:Parser.prototype,rssStat(eventName,cpuNumber,pid,ts,eventBase){const event=rssStatRE.exec(eventBase.details);if(!event)return false;const member=parseInt(event[1]);const size=parseInt(event[2]);if(eventBase.tgid===undefined){return false;}
+const tgid=parseInt(eventBase.tgid);const process=this.importer.model_.getOrCreateProcess(tgid);let subTitle='';if(member===0){subTitle=' (file pages)';}else if(member===1){subTitle=' (anon)';}
+const rssCounter=process.getOrCreateCounter('RSS','RSS '+member+subTitle);if(rssCounter.numSeries===0){rssCounter.addSeries(new tr.model.CounterSeries('RSS',tr.b.ColorScheme.getColorIdForGeneralPurposeString(rssCounter.name)));}
+rssCounter.series.forEach(function(series){series.addCounterSample(ts,size);});return true;},};Parser.register(RssParser);return{RssParser,_RssParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const Parser=tr.e.importer.linux_perf.Parser;function SchedParser(importer){Parser.call(this,importer);importer.registerEventHandler('sched_switch',SchedParser.prototype.schedSwitchEvent.bind(this));importer.registerEventHandler('sched_wakeup',SchedParser.prototype.schedWakeupEvent.bind(this));importer.registerEventHandler('sched_blocked_reason',SchedParser.prototype.schedBlockedEvent.bind(this));importer.registerEventHandler('sched_cpu_hotplug',SchedParser.prototype.schedCpuHotplugEvent.bind(this));}
+const TestExports={};const schedSwitchRE=new RegExp('prev_comm=(.+) prev_pid=(\\d+) prev_prio=(\\d+) '+'prev_state=(\\S\\+?|\\S\\|\\S) ==> '+'next_comm=(.+) next_pid=(\\d+) next_prio=(\\d+)');const schedBlockedRE=new RegExp('pid=(\\d+) iowait=(\\d) caller=(.+)');TestExports.schedSwitchRE=schedSwitchRE;const schedWakeupRE=/comm=(.+) pid=(\d+) prio=(\d+)(?: success=\d+)? target_cpu=(\d+)/;TestExports.schedWakeupRE=schedWakeupRE;const unknownThreadName='<...>';SchedParser.prototype={__proto__:Parser.prototype,schedSwitchEvent(eventName,cpuNumber,pid,ts,eventBase){const event=schedSwitchRE.exec(eventBase.details);if(!event)return false;const prevState=event[4];const nextComm=event[5];const nextPid=parseInt(event[6]);const nextPrio=parseInt(event[7]);if(eventBase.tgid!==undefined){const tgid=parseInt(eventBase.tgid);const process=this.importer.model_.getOrCreateProcess(tgid);const storedThread=process.getThread(pid);if(!storedThread){const thread=process.getOrCreateThread(pid);thread.name=eventBase.threadName;}else if(storedThread.name===unknownThreadName){storedThread.name=eventBase.threadName;}}
+const nextThread=this.importer.threadsByLinuxPid[nextPid];let nextName;if(nextThread){nextName=nextThread.userFriendlyName;}else{nextName=nextComm;}
+const cpu=this.importer.getOrCreateCpu(cpuNumber);cpu.switchActiveThread(ts,{stateWhenDescheduled:prevState},nextPid,nextName,{comm:nextComm,tid:nextPid,prio:nextPrio});return true;},schedWakeupEvent(eventName,cpuNumber,pid,ts,eventBase){const event=schedWakeupRE.exec(eventBase.details);if(!event)return false;const fromPid=pid;const comm=event[1];pid=parseInt(event[2]);const prio=parseInt(event[3]);this.importer.markPidRunnable(ts,pid,comm,prio,fromPid);return true;},schedCpuHotplugEvent(eventName,cpuNumber,pid,ts,eventBase){const event=/cpu (\d+) (.+) error=(\d+)/.exec(eventBase.details);if(!event)return false;cpuNumber=event[1];const state=event[2];const targetCpu=this.importer.getOrCreateCpu(cpuNumber);const powerCounter=targetCpu.getOrCreateCounter('','Cpu Hotplug');if(powerCounter.numSeries===0){powerCounter.addSeries(new tr.model.CounterSeries('State',tr.b.ColorScheme.getColorIdForGeneralPurposeString(powerCounter.name+'.'+'State')));}
+powerCounter.series.forEach(function(series){if(series.name==='State'){series.addCounterSample(ts,state.localeCompare('offline')?0:1);}});return true;},schedBlockedEvent(eventName,cpuNumber,pid,ts,eventBase){const event=schedBlockedRE.exec(eventBase.details);if(!event)return false;pid=parseInt(event[1]);const iowait=parseInt(event[2]);const caller=event[3];this.importer.addPidBlockedReason(ts,pid,iowait,caller);return true;}};Parser.register(SchedParser);return{SchedParser,_SchedParserTestExports:TestExports};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function SyncParser(importer){Parser.call(this,importer);importer.registerEventHandler('sync_timeline',SyncParser.prototype.timelineEvent.bind(this));importer.registerEventHandler('sync_wait',SyncParser.prototype.syncWaitEvent.bind(this));importer.registerEventHandler('sync_pt',SyncParser.prototype.syncPtEvent.bind(this));this.model_=importer.model_;}
+const syncTimelineRE=/name=(\S+) value=(\S*)/;const syncWaitRE=/(\S+) name=(\S+) state=(\d+)/;const syncPtRE=/name=(\S+) value=(\S*)/;SyncParser.prototype={__proto__:Parser.prototype,timelineEvent(eventName,cpuNumber,pid,ts,eventBase){const event=syncTimelineRE.exec(eventBase.details);if(!event)return false;const thread=this.importer.getOrCreatePseudoThread(event[1]);if(thread.lastActiveTs!==undefined){const duration=ts-thread.lastActiveTs;let value=thread.lastActiveValue;if(value===undefined)value=' ';const slice=new tr.model.ThreadSlice('',value,ColorScheme.getColorIdForGeneralPurposeString(value),thread.lastActiveTs,{},duration);thread.thread.sliceGroup.pushSlice(slice);}
+thread.lastActiveTs=ts;thread.lastActiveValue=event[2];return true;},syncWaitEvent(eventName,cpuNumber,pid,ts,eventBase){const event=syncWaitRE.exec(eventBase.details);if(!event)return false;if(eventBase.tgid===undefined){return false;}
+const tgid=parseInt(eventBase.tgid);const thread=this.model_.getOrCreateProcess(tgid).getOrCreateThread(pid);thread.name=eventBase.threadName;const slices=thread.kernelSliceGroup;if(!slices.isTimestampValidForBeginOrEnd(ts)){this.model_.importWarning({type:'parse_error',message:'Timestamps are moving backward.'});return false;}
+const name='fence_wait("'+event[2]+'")';if(event[1]==='begin'){const slice=slices.beginSlice(null,name,ts,{'Start state':event[3]});}else if(event[1]==='end'){if(slices.openSliceCount>0){slices.endSlice(ts);}}else{return false;}
+return true;},syncPtEvent(eventName,cpuNumber,pid,ts,eventBase){return!!syncPtRE.exec(eventBase.details);}};Parser.register(SyncParser);return{SyncParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const ColorScheme=tr.b.ColorScheme;const Parser=tr.e.importer.linux_perf.Parser;function WorkqueueParser(importer){Parser.call(this,importer);importer.registerEventHandler('workqueue_execute_start',WorkqueueParser.prototype.executeStartEvent.bind(this));importer.registerEventHandler('workqueue_execute_end',WorkqueueParser.prototype.executeEndEvent.bind(this));importer.registerEventHandler('workqueue_queue_work',WorkqueueParser.prototype.executeQueueWork.bind(this));importer.registerEventHandler('workqueue_activate_work',WorkqueueParser.prototype.executeActivateWork.bind(this));}
+const workqueueExecuteStartRE=/work struct (.+): function (\S+)/;const workqueueExecuteEndRE=/work struct (.+)/;WorkqueueParser.prototype={__proto__:Parser.prototype,executeStartEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteStartRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);kthread.openSliceTS=ts;kthread.openSlice=event[2];return true;},executeEndEvent(eventName,cpuNumber,pid,ts,eventBase){const event=workqueueExecuteEndRE.exec(eventBase.details);if(!event)return false;const kthread=this.importer.getOrCreateKernelThread(eventBase.threadName,pid,pid);if(kthread.openSlice){const slice=new tr.model.ThreadSlice('',kthread.openSlice,ColorScheme.getColorIdForGeneralPurposeString(kthread.openSlice),kthread.openSliceTS,{},ts-kthread.openSliceTS);kthread.thread.sliceGroup.pushSlice(slice);}
+kthread.openSlice=undefined;return true;},executeQueueWork(eventName,cpuNumber,pid,ts,eventBase){return true;},executeActivateWork(eventName,cpuNumber,pid,ts,eventBase){return true;}};Parser.register(WorkqueueParser);return{WorkqueueParser,};});'use strict';tr.exportTo('tr.e.importer.linux_perf',function(){const MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID='linux_clock_monotonic_to_ftrace_global';const IMPORT_PRIORITY=2;function FTraceImporter(model,events){this.importPriority=IMPORT_PRIORITY;this.model_=model;this.events_=events;this.wakeups_=[];this.blockedReasons_=[];this.kernelThreadStates_={};this.buildMapFromLinuxPidsToThreads_();this.lines_=[];this.pseudoThreadCounter=1;this.parsers_=[];this.eventHandlers_={};this.haveClockSyncedMonotonicToGlobal_=false;this.clockDomainId_=tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL;}
+const TestExports={};const lineREWithTGID=new RegExp('^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithTGID=function(line){const groups=lineREWithTGID.exec(line);if(!groups)return groups;let tgid=groups[3];if(tgid[0]==='-')tgid=undefined;return{threadName:groups[1],pid:groups[2],tgid,cpuNumber:groups[4],timestamp:groups[5],eventName:groups[6],details:groups[7]};};TestExports.lineParserWithTGID=lineParserWithTGID;const lineREWithIRQInfo=new RegExp('^\\s*(.+)-(\\d+)\\s+\\[(\\d+)\\]'+'\\s+[dX.][Nnp.][Hhs.][0-9a-f.]'+'\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$');const lineParserWithIRQInfo=function(line){const groups=lineREWithIRQInfo.exec(line);if(!groups)return groups;return{threadName:groups[1],pid:groups[2],cpuNumber:groups[3],timestamp:groups[4],eventName:groups[5],details:groups[6]};};TestExports.lineParserWithIRQInfo=lineParserWithIRQInfo;const lineREWithLegacyFmt=/^\s*(.+)-(\d+)\s+\[(\d+)\]\s*(\d+\.\d+):\s+(\S+):\s(.*)$/;const lineParserWithLegacyFmt=function(line){const groups=lineREWithLegacyFmt.exec(line);if(!groups){return groups;}
+return{threadName:groups[1],pid:groups[2],cpuNumber:groups[3],timestamp:groups[4],eventName:groups[5],details:groups[6]};};TestExports.lineParserWithLegacyFmt=lineParserWithLegacyFmt;const traceEventClockSyncRE=/trace_event_clock_sync: parent_ts=(\d+\.?\d*)/;TestExports.traceEventClockSyncRE=traceEventClockSyncRE;const realTimeClockSyncRE=/trace_event_clock_sync: realtime_ts=(\d+)/;const genericClockSyncRE=/trace_event_clock_sync: name=([\w\-]+)/;const pseudoKernelPID=0;function autoDetectLineParser(line){if(line[0]==='{')return false;if(lineREWithTGID.test(line))return lineParserWithTGID;if(lineREWithIRQInfo.test(line))return lineParserWithIRQInfo;if(lineREWithLegacyFmt.test(line))return lineParserWithLegacyFmt;return undefined;}
+TestExports.autoDetectLineParser=autoDetectLineParser;FTraceImporter.canImport=function(events){if(events instanceof tr.b.TraceStream)events=events.header;if(!(typeof(events)==='string'||events instanceof String)){return false;}
+if(FTraceImporter._extractEventsFromSystraceHTML(events,false).ok){return true;}
+if(FTraceImporter._extractEventsFromSystraceMultiHTML(events,false).ok){return true;}
+if(/^# tracer:/.test(events))return true;const lineBreakIndex=events.indexOf('\n');if(lineBreakIndex>-1)events=events.substring(0,lineBreakIndex);if(autoDetectLineParser(events))return true;return false;};FTraceImporter._extractEventsFromSystraceHTML=function(incomingEvents,produceResult){const failure={ok:false};if(produceResult===undefined)produceResult=true;const header=incomingEvents instanceof tr.b.TraceStream?incomingEvents.header:incomingEvents;if(!/^<!DOCTYPE html>/.test(header))return failure;const r=new tr.importer.SimpleLineReader(incomingEvents);if(!r.advanceToLineMatching(/^  <script>$/))return failure;if(!r.advanceToLineMatching(/^  var linuxPerfData = "\\$/))return failure;const eventsBeginAtLine=r.curLineNumber+1;r.beginSavingLines();if(!r.advanceToLineMatching(/^  <\/script>$/))return failure;let rawEvents=r.endSavingLinesAndGetResult();rawEvents=rawEvents.slice(1,rawEvents.length-1);if(!r.advanceToLineMatching(/^<\/body>$/))return failure;if(!r.advanceToLineMatching(/^<\/html>$/))return failure;function endsWith(str,suffix){return str.indexOf(suffix,str.length-suffix.length)!==-1;}
+function stripSuffix(str,suffix){if(!endsWith(str,suffix))return str;return str.substring(str,str.length-suffix.length);}
+let events=[];if(produceResult){for(let i=0;i<rawEvents.length;i++){let event=rawEvents[i];event=stripSuffix(event,'\\n\\');events.push(event);}}else{events=[rawEvents[rawEvents.length-1]];}
+const oldLastEvent=events[events.length-1];const newLastEvent=stripSuffix(oldLastEvent,'\\n";');if(newLastEvent===oldLastEvent)return failure;events[events.length-1]=newLastEvent;return{ok:true,lines:produceResult?events:undefined,eventsBeginAtLine};};FTraceImporter._extractEventsFromSystraceMultiHTML=function(incomingEvents,produceResult){const failure={ok:false};if(produceResult===undefined)produceResult=true;const header=incomingEvents instanceof tr.b.TraceStream?incomingEvents.header:incomingEvents;if(!(new RegExp('^<!DOCTYPE HTML>','i').test(header)))return failure;const r=new tr.importer.SimpleLineReader(incomingEvents);let events=[];let eventsBeginAtLine;while(!/^# tracer:/.test(events)){if(!r.advanceToLineMatching(/^  <script class="trace-data" type="application\/text">$/)){return failure;}
+eventsBeginAtLine=r.curLineNumber+1;r.beginSavingLines();if(!r.advanceToLineMatching(/^  <\/script>$/))return failure;events=r.endSavingLinesAndGetResult();events=events.slice(1,events.length-1);}
+if(!r.advanceToLineMatching(/^<\/body>$/))return failure;if(!r.advanceToLineMatching(/^<\/html>$/))return failure;return{ok:true,lines:produceResult?events:undefined,eventsBeginAtLine,};};FTraceImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'FTraceImporter';},get model(){return this.model_;},importClockSyncMarkers(){this.lazyInit_();this.forEachLine_(function(text,eventBase,cpuNumber,pid,ts){const eventName=eventBase.eventName;if(eventName!=='tracing_mark_write'&&eventName!=='0')return;if(traceEventClockSyncRE.exec(eventBase.details)||genericClockSyncRE.exec(eventBase.details)){this.traceClockSyncEvent_(eventName,cpuNumber,pid,ts,eventBase);}else if(realTimeClockSyncRE.exec(eventBase.details)){const match=realTimeClockSyncRE.exec(eventBase.details);this.model_.realtime_to_monotonic_offset_ms=ts-match[1];}}.bind(this));},importEvents(){if(this.lines_.length===0)return;const modelTimeTransformer=this.model_.clockSyncManager.getModelTimeTransformer(this.clockDomainId_);this.importCpuData_(modelTimeTransformer);this.buildMapFromLinuxPidsToThreads_();this.buildPerThreadCpuSlicesFromCpuState_();},registerEventHandler(eventName,handler){this.eventHandlers_[eventName]=handler;},getOrCreateCpu(cpuNumber){return this.model_.kernel.getOrCreateCpu(cpuNumber);},getOrCreateKernelThread(kernelThreadName,pid,tid){if(!this.kernelThreadStates_[kernelThreadName]){const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[kernelThreadName]={pid,thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[tid]=thread;}
+return this.kernelThreadStates_[kernelThreadName];},getOrCreateBinderKernelThread(kernelThreadName,pid,tid){const key=kernelThreadName+pid+tid;if(!this.kernelThreadStates_[key]){const thread=this.model_.getOrCreateProcess(pid).getOrCreateThread(tid);thread.name=kernelThreadName;this.kernelThreadStates_[key]={pid,thread,openSlice:undefined,openSliceTS:undefined};this.threadsByLinuxPid[tid]=thread;}
+return this.kernelThreadStates_[key];},getOrCreatePseudoThread(threadName){let thread=this.kernelThreadStates_[threadName];if(!thread){thread=this.getOrCreateKernelThread(threadName,pseudoKernelPID,this.pseudoThreadCounter);this.pseudoThreadCounter++;}
+return thread;},markPidRunnable(ts,pid,comm,prio,fromPid){this.wakeups_.push({ts,tid:pid,fromTid:fromPid});},addPidBlockedReason(ts,pid,iowait,caller){this.blockedReasons_.push({ts,tid:pid,iowait,caller});},buildMapFromLinuxPidsToThreads_(){this.threadsByLinuxPid={};this.model_.getAllThreads().forEach(function(thread){this.threadsByLinuxPid[thread.tid]=thread;}.bind(this));},buildPerThreadCpuSlicesFromCpuState_(){const SCHEDULING_STATE=tr.model.SCHEDULING_STATE;for(const cpuNumber in this.model_.kernel.cpus){const cpu=this.model_.kernel.cpus[cpuNumber];for(let i=0;i<cpu.slices.length;i++){const cpuSlice=cpu.slices[i];const thread=this.threadsByLinuxPid[cpuSlice.args.tid];if(!thread)continue;cpuSlice.threadThatWasRunning=thread;if(!thread.tempCpuSlices){thread.tempCpuSlices=[];}
+thread.tempCpuSlices.push(cpuSlice);}}
+for(const i in this.wakeups_){const wakeup=this.wakeups_[i];const thread=this.threadsByLinuxPid[wakeup.tid];if(!thread)continue;thread.tempWakeups=thread.tempWakeups||[];thread.tempWakeups.push(wakeup);}
+for(const i in this.blockedReasons_){const reason=this.blockedReasons_[i];const thread=this.threadsByLinuxPid[reason.tid];if(!thread)continue;thread.tempBlockedReasons=thread.tempBlockedReasons||[];thread.tempBlockedReasons.push(reason);}
+this.model_.getAllThreads().forEach(function(thread){if(thread.tempCpuSlices===undefined)return;const origSlices=thread.tempCpuSlices;delete thread.tempCpuSlices;origSlices.sort(function(x,y){return x.start-y.start;});const wakeups=thread.tempWakeups||[];delete thread.tempWakeups;wakeups.sort(function(x,y){return x.ts-y.ts;});const reasons=thread.tempBlockedReasons||[];delete thread.tempBlockedReasons;reasons.sort(function(x,y){return x.ts-y.ts;});const slices=[];if(origSlices.length){const slice=origSlices[0];if(wakeups.length&&wakeups[0].ts<slice.start){const wakeup=wakeups.shift();const wakeupDuration=slice.start-wakeup.ts;const args={'wakeup from tid':wakeup.fromTid};slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));}
+const runningSlice=new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',slice.start,{},slice.duration);runningSlice.cpuOnWhichThreadWasRunning=slice.cpu;slices.push(runningSlice);}
+for(let i=1;i<origSlices.length;i++){let wakeup=undefined;const prevSlice=origSlices[i-1];const nextSlice=origSlices[i];let midDuration=nextSlice.start-prevSlice.end;while(wakeups.length&&wakeups[0].ts<nextSlice.start){const w=wakeups.shift();if(wakeup===undefined&&w.ts>prevSlice.end){wakeup=w;}}
+let blockedReason=undefined;while(reasons.length&&reasons[0].ts<prevSlice.end){const r=reasons.shift();}
+if(wakeup!==undefined&&reasons.length&&reasons[0].ts<wakeup.ts){blockedReason=reasons.shift();}
+const pushSleep=function(state){if(wakeup!==undefined){midDuration=wakeup.ts-prevSlice.end;}
+if(blockedReason!==undefined){const args={'kernel callsite when blocked:':blockedReason.caller};if(blockedReason.iowait){switch(state){case SCHEDULING_STATE.UNINTR_SLEEP:state=SCHEDULING_STATE.UNINTR_SLEEP_IO;break;case SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL:state=SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;break;case SCHEDULING_STATE.UNINTR_SLEEP_WAKING:state=SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL_IO;break;default:}}
+slices.push(new tr.model.ThreadTimeSlice(thread,state,'',prevSlice.end,args,midDuration));}else{slices.push(new tr.model.ThreadTimeSlice(thread,state,'',prevSlice.end,{},midDuration));}
+if(wakeup!==undefined){const wakeupDuration=nextSlice.start-wakeup.ts;const args={'wakeup from tid':wakeup.fromTid};slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',wakeup.ts,args,wakeupDuration));wakeup=undefined;}};if(prevSlice.args.stateWhenDescheduled==='S'){pushSleep(SCHEDULING_STATE.SLEEPING);}else if(prevSlice.args.stateWhenDescheduled==='R'||prevSlice.args.stateWhenDescheduled==='R+'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNABLE,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='D'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP);}else if(prevSlice.args.stateWhenDescheduled==='T'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.STOPPED,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='t'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.DEBUG,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='Z'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.ZOMBIE,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='X'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.EXIT_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='x'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.TASK_DEAD,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='K'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKE_KILL,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='W'){slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.WAKING,'',prevSlice.end,{},midDuration));}else if(prevSlice.args.stateWhenDescheduled==='D|K'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKE_KILL);}else if(prevSlice.args.stateWhenDescheduled==='D|W'){pushSleep(SCHEDULING_STATE.UNINTR_SLEEP_WAKING);}else{slices.push(new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.UNKNOWN,'',prevSlice.end,{},midDuration));this.model_.importWarning({type:'parse_error',message:'Unrecognized sleep state: '+
+prevSlice.args.stateWhenDescheduled});}
+const runningSlice=new tr.model.ThreadTimeSlice(thread,SCHEDULING_STATE.RUNNING,'',nextSlice.start,{},nextSlice.duration);runningSlice.cpuOnWhichThreadWasRunning=prevSlice.cpu;slices.push(runningSlice);}
+thread.timeSlices=slices;},this);},createParsers_(){const allTypeInfos=tr.e.importer.linux_perf.Parser.getAllRegisteredTypeInfos();const parsers=allTypeInfos.map(function(typeInfo){return new typeInfo.constructor(this);},this);return parsers;},registerDefaultHandlers_(){this.registerEventHandler('tracing_mark_write',FTraceImporter.prototype.traceMarkingWriteEvent_.bind(this));this.registerEventHandler('0',FTraceImporter.prototype.traceMarkingWriteEvent_.bind(this));this.registerEventHandler('tracing_mark_write:trace_event_clock_sync',function(){return true;});this.registerEventHandler('0:trace_event_clock_sync',function(){return true;});},traceClockSyncEvent_(eventName,cpuNumber,pid,ts,eventBase){let event=/name=(\w+?)\s(.+)/.exec(eventBase.details);if(event){const name=event[1];const pieces=event[2].split(' ');const args={perfTs:ts};for(let i=0;i<pieces.length;i++){const parts=pieces[i].split('=');if(parts.length!==2){throw new Error('omgbbq');}
+args[parts[0]]=parts[1];}
+this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,name,ts);return true;}
+event=/name=([\w\-]+)/.exec(eventBase.details);if(event){this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,event[1],ts);return true;}
+event=/parent_ts=(\d+\.?\d*)/.exec(eventBase.details);if(!event)return false;let monotonicTs=event[1]*1000;if(monotonicTs===0)monotonicTs=ts;if(this.haveClockSyncedMonotonicToGlobal_){return true;}
+this.model_.clockSyncManager.addClockSyncMarker(this.clockDomainId_,MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID,ts);this.model_.clockSyncManager.addClockSyncMarker(tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC,MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID,monotonicTs);this.haveClockSyncedMonotonicToGlobal_=true;return true;},traceMarkingWriteEvent_(eventName,cpuNumber,pid,ts,eventBase,threadName){eventBase.details=eventBase.details.replace(/\\n.*$/,'');const event=/^\s*(\w+):\s*(.*)$/.exec(eventBase.details);if(!event){const tag=eventBase.details.substring(0,2);if(tag==='B|'||tag==='E'||tag==='E|'||tag==='X|'||tag==='C|'||tag==='S|'||tag==='F|'){eventBase.subEventName='android';}else{return false;}}else{eventBase.subEventName=event[1];eventBase.details=event[2];}
+const writeEventName=eventName+':'+eventBase.subEventName;const handler=this.eventHandlers_[writeEventName];if(!handler){this.model_.importWarning({type:'parse_error',message:'Unknown trace_marking_write event '+writeEventName});return true;}
+return handler(writeEventName,cpuNumber,pid,ts,eventBase,threadName);},importCpuData_(modelTimeTransformer){this.forEachLine_(function(text,eventBase,cpuNumber,pid,ts){const eventName=eventBase.eventName;const handler=this.eventHandlers_[eventName];if(!handler){this.model_.importWarning({type:'parse_error',message:'Unknown event '+eventName+' ('+text+')'});return;}
+ts=modelTimeTransformer(ts);if(!handler(eventName,cpuNumber,pid,ts,eventBase)){this.model_.importWarning({type:'parse_error',message:'Malformed '+eventName+' event ('+text+')'});}}.bind(this));},parseLines_(){let extractResult=FTraceImporter._extractEventsFromSystraceHTML(this.events_,true);if(!extractResult.ok){extractResult=FTraceImporter._extractEventsFromSystraceMultiHTML(this.events_,true);}
+let lineParser=undefined;if(extractResult.ok){for(const line of extractResult.lines){lineParser=this.parseLine_(line,lineParser);}}else{const r=new tr.importer.SimpleLineReader(this.events_);for(const line of r){lineParser=this.parseLine_(line,lineParser);}}},parseLine_(line,lineParser){line=line.trim();if(line.length===0)return lineParser;if(/^#/.test(line)){const clockType=/^# clock_type=([A-Z_]+)$/.exec(line);if(clockType){this.clockDomainId_=clockType[1];}
+return lineParser;}
+if(!lineParser){lineParser=autoDetectLineParser(line);if(!lineParser){this.model_.importWarning({type:'parse_error',message:'Cannot parse line: '+line});return lineParser;}}
+const eventBase=lineParser(line);if(!eventBase){this.model_.importWarning({type:'parse_error',message:'Unrecognized line: '+line});return lineParser;}
+this.lines_.push([line,eventBase,parseInt(eventBase.cpuNumber),parseInt(eventBase.pid),parseFloat(eventBase.timestamp)*1000]);return lineParser;},forEachLine_(handler){for(let i=0;i<this.lines_.length;++i){const line=this.lines_[i];handler.apply(this,line);}},lazyInit_(){this.parsers_=this.createParsers_();this.registerDefaultHandlers_();this.parseLines_();}};tr.importer.Importer.register(FTraceImporter);return{FTraceImporter,_FTraceImporterTestExports:TestExports,IMPORT_PRIORITY,};});'use strict';tr.exportTo('tr.e.importer.android.atrace_process_dump',function(){const IMPORT_PRIORITY=tr.e.importer.linux_perf.IMPORT_PRIORITY+1;const HEADER='ATRACE_PROCESS_DUMP';const PROTECTION_FLAG_LETTERS={'-':0,'r':tr.model.VMRegion.PROTECTION_FLAG_READ,'w':tr.model.VMRegion.PROTECTION_FLAG_WRITE,'x':tr.model.VMRegion.PROTECTION_FLAG_EXECUTE,'s':tr.model.VMRegion.PROTECTION_FLAG_MAYSHARE,};class AtraceProcessDumpImporter extends tr.importer.Importer{constructor(model,data){super(model,data);this.importPriority=IMPORT_PRIORITY;this.model_=model;this.raw_data_=data;this.clock_sync_markers_={};this.snapshots_=[];this.processes_={};}
+static canImport(events){if(!(typeof(events)==='string'||events instanceof String)){return false;}
+return events.startsWith(HEADER);}
+get importerName(){return'AtraceProcessDumpImporter';}
+get model(){return this.model_;}
+lazyParseData(){if(this.raw_data_===undefined){return;}
+const dump=JSON.parse(this.raw_data_.slice(HEADER.length+1));this.clock_sync_markers_=dump.clock_sync_markers;this.snapshots_=dump.dump.snapshots;this.processes_=dump.dump.processes;this.raw_data_=undefined;}
+importClockSyncMarkers(){this.lazyParseData();for(const syncId in this.clock_sync_markers_){const ts=parseInt(this.clock_sync_markers_[syncId]);this.model_.clockSyncManager.addClockSyncMarker(tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC,syncId,ts);}}
+setProcessMemoryDumpTotals_(pmd,processInfo){pmd.totals={'residentBytes':processInfo.rss*1024,'platformSpecific':{'vm':processInfo.vm*1024}};const totals=pmd.totals.platformSpecific;function importGpuMetric(name){if(processInfo[name]!==undefined&&processInfo[name]>0){totals[name]=processInfo[name]*1024;totals[name+'_pss']=processInfo[name+'_pss']*1024;}}
+importGpuMetric('gpu_egl');importGpuMetric('gpu_gl');importGpuMetric('gpu_etc');if(processInfo.pss!==undefined){totals.pss=processInfo.pss*1024;totals.swp=processInfo.swp*1024;totals.pc=processInfo.pc*1024;totals.pd=processInfo.pd*1024;totals.sc=processInfo.sc*1024;totals.sd=processInfo.sd*1024;}}
+setProcessMemoryDumpVmRegions_(pmd,processInfo){if(processInfo.mmaps===undefined){return;}
+const vmRegions=[];for(const memoryMap of processInfo.mmaps){const addr=memoryMap.vm.split('-').map(x=>parseInt(x,16));let flags=0;for(const letter of memoryMap.flags){flags|=PROTECTION_FLAG_LETTERS[letter];}
+const totals={'proportionalResident':memoryMap.pss*1024,'privateCleanResident':memoryMap.pc*1024,'privateDirtyResident':memoryMap.pd*1024,'sharedCleanResident':memoryMap.sc*1024,'sharedDirtyResident':memoryMap.sd*1024,'swapped':memoryMap.swp*1024,};vmRegions.push(new tr.model.VMRegion(addr[0],addr[1]-addr[0],flags,memoryMap.file,totals));}
+pmd.vmRegions=tr.model.VMRegionClassificationNode.fromRegions(vmRegions);}
+importEvents(){this.lazyParseData();for(const[pid,process]of Object.entries(this.processes_)){const modelProcess=this.model_.getProcess(pid);if(modelProcess===undefined){continue;}
+modelProcess.name=process.name;const threads=process.threads;if(threads===undefined){continue;}
+for(const[tid,thread]of Object.entries(threads)){const modelThread=modelProcess.threads[tid];if(modelThread===undefined){continue;}
+modelThread.name=thread.name;}}
+const memCounter=this.model_.kernel.getOrCreateCounter('global','SystemMemory');const memUsedSeries=new tr.model.CounterSeries('Used (KB)',0);const memSwappedSeries=new tr.model.CounterSeries('Swapped (KB)',0);memCounter.addSeries(memUsedSeries);memCounter.addSeries(memSwappedSeries);for(const snapshot of this.snapshots_){const ts=parseInt(snapshot.ts);const memoryDump=snapshot.memdump;if(memoryDump===undefined){const memInfo=snapshot.meminfo;if(memInfo===undefined){continue;}
+const memCaches=memInfo.Buffers+memInfo.Cached-memInfo.Mapped;const memUsed=memInfo.MemTotal-memInfo.MemFree-memCaches;const memSwapped=memInfo.SwapTotal-memInfo.SwapFree;memUsedSeries.addCounterSample(ts,memUsed);memSwappedSeries.addCounterSample(ts,memSwapped);continue;}
+const gmd=new tr.model.GlobalMemoryDump(this.model_,ts);this.model_.globalMemoryDumps.push(gmd);for(const[pid,processInfo]of Object.entries(memoryDump)){if(processInfo.rss===undefined){continue;}
+const modelProcess=this.model_.getProcess(pid);if(modelProcess===undefined){continue;}
+const pmd=new tr.model.ProcessMemoryDump(gmd,modelProcess,ts);gmd.processMemoryDumps[pid]=pmd;modelProcess.memoryDumps.push(pmd);this.setProcessMemoryDumpTotals_(pmd,processInfo);this.setProcessMemoryDumpVmRegions_(pmd,processInfo);}}}}
+tr.importer.Importer.register(AtraceProcessDumpImporter);return{AtraceProcessDumpImporter,};});'use strict';tr.exportTo('tr.model',function(){const ColorScheme=tr.b.ColorScheme;function Activity(name,category,range,args){tr.model.TimedEvent.call(this,range.min);this.title=name;this.category=category;this.colorId=ColorScheme.getColorIdForGeneralPurposeString(name);this.duration=range.duration;this.args=args;this.name=name;}
+Activity.prototype={__proto__:tr.model.TimedEvent.prototype,shiftTimestampsForward(amount){this.start+=amount;},addBoundsToRange(range){range.addValue(this.start);range.addValue(this.end);}};return{Activity,};});'use strict';tr.exportTo('tr.e.importer.android',function(){const Importer=tr.importer.Importer;const ACTIVITY_STATE={NONE:'none',CREATED:'created',STARTED:'started',RESUMED:'resumed',PAUSED:'paused',STOPPED:'stopped',DESTROYED:'destroyed'};const activityMap={};function EventLogImporter(model,events){this.model_=model;this.events_=events;this.importPriority=3;}
+const eventLogActivityRE=new RegExp('(\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}.\\d+)'+'\\s+(\\d+)\\s+(\\d+)\\s+([A-Z])\\s*'+'(am_\\w+)\\s*:(.*)');const amCreateRE=new RegExp('\s*\\[.*,.*,.*,(.*),.*,.*,.*,.*\\]');const amFocusedRE=new RegExp('\s*\\[\\d+,(.*)\\]');const amProcStartRE=new RegExp('\s*\\[\\d+,\\d+,\\d+,.*,activity,(.*)\\]');const amOnResumeRE=new RegExp('\s*\\[\\d+,(.*)\\]');const amOnPauseRE=new RegExp('\s*\\[\\d+,(.*)\\]');const amLaunchTimeRE=new RegExp('\s*\\[\\d+,\\d+,(.*),(\\d+),(\\d+)');const amDestroyRE=new RegExp('\s*\\[\\d+,\\d+,\\d+,(.*)\\]');EventLogImporter.canImport=function(events){if(!(typeof(events)==='string'||events instanceof String)){return false;}
+if(/^<!DOCTYPE html>/.test(events))return false;return eventLogActivityRE.test(events);};EventLogImporter.prototype={__proto__:Importer.prototype,get importerName(){return'EventLogImporter';},get model(){return this.model_;},getFullActivityName(component){const componentSplit=component.split('/');if(componentSplit[1].startsWith('.')){return componentSplit[0]+componentSplit[1];}
+return componentSplit[1];},getProcName(component){const componentSplit=component.split('/');return componentSplit[0];},findOrCreateActivity(activityName){if(activityName in activityMap){return activityMap[activityName];}
+const activity={state:ACTIVITY_STATE.NONE,name:activityName};activityMap[activityName]=activity;return activity;},deleteActivity(activityName){delete activityMap[activityName];},handleCreateActivity(ts,activityName){const activity=this.findOrCreateActivity(activityName);activity.state=ACTIVITY_STATE.CREATED;activity.createdTs=ts;},handleFocusActivity(ts,procName,activityName){const activity=this.findOrCreateActivity(activityName);activity.lastFocusedTs=ts;},handleProcStartForActivity(ts,activityName){const activity=this.findOrCreateActivity(activityName);activity.procStartTs=ts;},handleOnResumeCalled(ts,pid,activityName){const activity=this.findOrCreateActivity(activityName);activity.state=ACTIVITY_STATE.RESUMED;activity.lastResumeTs=ts;activity.pid=pid;},handleOnPauseCalled(ts,activityName){const activity=this.findOrCreateActivity(activityName);activity.state=ACTIVITY_STATE.PAUSED;activity.lastPauseTs=ts;if(ts>this.model_.bounds.min&&ts<this.model_.bounds.max){this.addActivityToProcess(activity);}},handleLaunchTime(ts,activityName,launchTime){const activity=this.findOrCreateActivity(activityName);activity.launchTime=launchTime;},handleDestroyActivity(ts,activityName){this.deleteActivity(activityName);},addActivityToProcess(activity){if(activity.pid===undefined)return;const process=this.model_.getOrCreateProcess(activity.pid);const range=tr.b.math.Range.fromExplicitRange(Math.max(this.model_.bounds.min,activity.lastResumeTs),activity.lastPauseTs);const newActivity=new tr.model.Activity(activity.name,'Android Activity',range,{created:activity.createdTs,procstart:activity.procStartTs,lastfocus:activity.lastFocusedTs});process.activities.push(newActivity);},parseAmLine_(line){let match=eventLogActivityRE.exec(line);if(!match)return;const firstRealtimeTs=this.model_.bounds.min-
+this.model_.realtime_to_monotonic_offset_ms;const year=new Date(firstRealtimeTs).getFullYear();const ts=match[1].substring(0,5)+'-'+year+' '+
+match[1].substring(5,match[1].length);const monotonicTs=Date.parse(ts)+
+this.model_.realtime_to_monotonic_offset_ms;const pid=match[2];const action=match[5];const data=match[6];if(action==='am_create_activity'){match=amCreateRE.exec(data);if(match&&match.length>=2){this.handleCreateActivity(monotonicTs,this.getFullActivityName(match[1]));}}else if(action==='am_focused_activity'){match=amFocusedRE.exec(data);if(match&&match.length>=2){this.handleFocusActivity(monotonicTs,this.getProcName(match[1]),this.getFullActivityName(match[1]));}}else if(action==='am_proc_start'){match=amProcStartRE.exec(data);if(match&&match.length>=2){this.handleProcStartForActivity(monotonicTs,this.getFullActivityName(match[1]));}}else if(action==='am_on_resume_called'){match=amOnResumeRE.exec(data);if(match&&match.length>=2){this.handleOnResumeCalled(monotonicTs,pid,match[1]);}}else if(action==='am_on_paused_called'){match=amOnPauseRE.exec(data);if(match&&match.length>=2){this.handleOnPauseCalled(monotonicTs,match[1]);}}else if(action==='am_activity_launch_time'){match=amLaunchTimeRE.exec(data);this.handleLaunchTime(monotonicTs,this.getFullActivityName(match[1]),match[2]);}else if(action==='am_destroy_activity'){match=amDestroyRE.exec(data);if(match&&match.length===2){this.handleDestroyActivity(monotonicTs,this.getFullActivityName(match[1]));}}},importEvents(){if(isNaN(this.model_.realtime_to_monotonic_offset_ms)){this.model_.importWarning({type:'eveng_log_clock_sync',message:'Need a trace_event_clock_sync to map realtime to import.'});return;}
+this.model_.updateBounds();const lines=this.events_.split('\n');lines.forEach(this.parseAmLine_,this);for(const activityName in activityMap){const activity=activityMap[activityName];if(activity.state===ACTIVITY_STATE.RESUMED){activity.lastPauseTs=this.model_.bounds.max;this.addActivityToProcess(activity);}}}};Importer.register(EventLogImporter);return{EventLogImporter,};});'use strict';tr.exportTo('tr.e.importer.android.process_data',function(){const Importer=tr.importer.Importer;const PROCESS_DUMP_HEADER='PROCESS DUMP';function ProcessDataImporter(model,processData){this.model_=model;this.processDataLines=processData.split('\n');this.importPriority=3;}
+ProcessDataImporter.canImport=function(events){if(!(typeof(events)==='string'||events instanceof String)){return false;}
+if(events.split('\n')[0]===PROCESS_DUMP_HEADER){return true;}
+return false;};ProcessDataImporter.prototype={__proto__:Importer.prototype,get importerName(){return'ProcessDataImporter';},get model(){return this.model_;},parseEventData(data){const allDumpedProcesses={};let parseProcesses=false;let parseThreads=false;let legacy=false;for(let i=1;i<data.length;i++){const cols=data[i].split(/\s+/);if(cols[0].startsWith('USER')){if(parseProcesses){parseProcesses=false;parseThreads=true;}else{parseThreads=false;parseProcesses=true;}
+const colCount=cols.length;if(parseProcesses&&colCount===9){legacy=false;}else if(parseProcesses&&colCount===8){legacy=true;}
+continue;}
+if(parseProcesses){const pid=Number(cols[1]);if(allDumpedProcesses[pid]===undefined){allDumpedProcesses[pid]={};}
+allDumpedProcesses[pid]={'name':cols[8],pid,'comm':cols[9]};continue;}
+if(parseThreads){let pid;let tid;let name;if(legacy){pid=Number(cols[1]);if(allDumpedProcesses[pid]!==undefined){tid=pid;}else{tid=pid;pid=Number(cols[2]);}
+name=cols.slice(8).join(' ');}else{pid=Number(cols[1]);tid=Number(cols[2]);name=cols.slice(3).join(' ');}
+if(allDumpedProcesses[pid]===undefined)continue;if(allDumpedProcesses[pid].threads===undefined){allDumpedProcesses[pid].threads={};}
+allDumpedProcesses[pid].threads[tid]={tid,name};continue;}}
+return allDumpedProcesses;},importEvents(){const allDumpedProcesses=this.parseEventData(this.processDataLines);const modelProcesses=this.model_.getAllProcesses();for(let i=0;i<modelProcesses.length;i++){const modelProcess=modelProcesses[i];const pid=modelProcess.pid;const dumpedProcess=allDumpedProcesses[pid];if(dumpedProcess===undefined){continue;}
+modelProcess.name=dumpedProcess.name;const processDumpThreads=dumpedProcess.threads;if(processDumpThreads!==undefined){for(const tid in modelProcess.threads){const modelThread=modelProcess.threads[tid];if(Number(pid)===Number(tid)){modelThread.name='UI thread';}else if(modelThread.name==='<...>'){if(processDumpThreads[tid]!==undefined){modelThread.name=processDumpThreads[tid].name;}}}}}}};Importer.register(ProcessDataImporter);return{ProcessDataImporter,};});'use strict';tr.exportTo('tr.e.importer.battor',function(){function BattorImporter(model,events){this.importPriority=3;this.model_=model;this.samples_=[];this.syncTimestampsById_=new Map();this.parseTrace_(events);}
+const battorDataLineRE=new RegExp('^(-?\\d+\\.\\d+)\\s+(-?\\d+\\.\\d+)\\s+(-?\\d+\\.\\d+)'+'(?:\\s+<(\\S+)>)?$');const battorHeaderLineRE=/^# BattOr/;BattorImporter.canImport=function(events){if(!(typeof(events)==='string'||events instanceof String)){return false;}
+return battorHeaderLineRE.test(events);};BattorImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'BattorImporter';},get model(){return this.model_;},importClockSyncMarkers(){for(const[syncId,ts]of this.syncTimestampsById_){this.model_.clockSyncManager.addClockSyncMarker(tr.model.ClockDomainId.BATTOR,syncId,ts);}},importEvents(){if(this.model_.device.powerSeries){this.model_.importWarning({type:'import_error',message:'Power counter exists, can not import BattOr power trace.'});return;}
+const modelTimeTransformer=this.model_.clockSyncManager.getModelTimeTransformer(tr.model.ClockDomainId.BATTOR);const powerSeries=this.model_.device.powerSeries=new tr.model.PowerSeries(this.model_.device);for(let i=0;i<this.samples_.length;i++){const sample=this.samples_[i];powerSeries.addPowerSample(modelTimeTransformer(sample.ts),sample.powerInW);}},parseTrace_(trace){const lines=trace.split('\n');for(let line of lines){line=line.trim();if(line.length===0)continue;if(line.startsWith('#'))continue;const groups=battorDataLineRE.exec(line);if(!groups){this.model_.importWarning({type:'parse_error',message:'Unrecognized line in BattOr trace: '+line});continue;}
+const ts=parseFloat(groups[1]);const voltageInV=tr.b.convertUnit(parseFloat(groups[2]),tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);const currentInA=tr.b.convertUnit(parseFloat(groups[3]),tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);const syncId=groups[4];if(syncId){this.syncTimestampsById_.set(syncId,ts);}
+if(voltageInV<0||currentInA<0){this.model_.importWarning({type:'parse_error',message:'The following line in the BattOr trace has a negative '+'voltage or current, neither of which are allowed: '+line+'. A common cause of this is that the device is charging '+'while the trace is being recorded.'});continue;}
+this.samples_.push(new Sample(ts,voltageInV,currentInA));}}};function Sample(ts,voltageInV,currentInA){this.ts=ts;this.voltageInV=voltageInV;this.currentInA=currentInA;}
+Sample.prototype={get powerInW(){return this.voltageInV*this.currentInA;}};tr.importer.Importer.register(BattorImporter);return{BattorImporter,};});'use strict';tr.exportTo('tr.e.importer.ddms',function(){const kPid=0;const kCategory='java';const kMethodLutEndMarker='\n*end\n';const kThreadsStart='\n*threads\n';const kMethodsStart='\n*methods\n';const kTraceMethodEnter=0x00;const kTraceMethodExit=0x01;const kTraceUnroll=0x02;const kTraceMethodActionMask=0x03;const kTraceHeaderLength=32;const kTraceMagicValue=0x574f4c53;const kTraceVersionSingleClock=2;const kTraceVersionDualClock=3;const kTraceRecordSizeSingleClock=10;const kTraceRecordSizeDualClock=14;function Reader(stringPayload){this.position_=0;this.data_=new Uint8Array(stringPayload.length);for(let i=0;i<stringPayload.length;++i){this.data_[i]=stringPayload.charCodeAt(i);}}
+Reader.prototype={__proto__:Object.prototype,uint8(){const result=this.data_[this.position_];this.position_+=1;return result;},uint16(){let result=0;result+=this.uint8();result+=this.uint8()<<8;return result;},uint32(){let result=0;result+=this.uint8();result+=this.uint8()<<8;result+=this.uint8()<<16;result+=this.uint8()<<24;return result;},uint64(){const low=this.uint32();const high=this.uint32();const lowStr=('0000000'+low.toString(16)).substr(-8);const highStr=('0000000'+high.toString(16)).substr(-8);const result=highStr+lowStr;return result;},seekTo(position){this.position_=position;},hasMore(){return this.position_<this.data_.length;}};function DdmsImporter(model,data){this.importPriority=3;this.model_=model;this.data_=data;}
+DdmsImporter.canImport=function(data){if(typeof(data)==='string'||data instanceof String){const header=data.slice(0,1000);return header.startsWith('*version\n')&&header.indexOf('\nvm=')>=0&&header.indexOf(kThreadsStart)>=0;}
+return false;};DdmsImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'DdmsImporter';},get model(){return this.model_;},importEvents(){const divider=this.data_.indexOf(kMethodLutEndMarker)+
+kMethodLutEndMarker.length;this.metadata_=this.data_.slice(0,divider);this.methods_={};this.parseThreads();this.parseMethods();const traceReader=new Reader(this.data_.slice(divider));const magic=traceReader.uint32();if(magic!==kTraceMagicValue){throw Error('Failed to match magic value');}
+this.version_=traceReader.uint16();if(this.version_!==kTraceVersionDualClock){throw Error('Unknown version');}
+const dataOffest=traceReader.uint16();const startDateTime=traceReader.uint64();const recordSize=traceReader.uint16();traceReader.seekTo(dataOffest);while(traceReader.hasMore()){this.parseTraceEntry(traceReader);}},parseTraceEntry(reader){const tid=reader.uint16();const methodPacked=reader.uint32();const cpuSinceStart=reader.uint32();const wallClockSinceStart=reader.uint32();let method=methodPacked&~kTraceMethodActionMask;const action=methodPacked&kTraceMethodActionMask;const thread=this.getTid(tid);method=this.getMethodName(method);if(action===kTraceMethodEnter){thread.sliceGroup.beginSlice(kCategory,method,wallClockSinceStart,undefined,cpuSinceStart);}else if(thread.sliceGroup.openSliceCount){thread.sliceGroup.endSlice(wallClockSinceStart,cpuSinceStart);}},parseThreads(){let threads=this.metadata_.slice(this.metadata_.indexOf(kThreadsStart)+
+kThreadsStart.length);threads=threads.slice(0,threads.indexOf('\n*'));threads=threads.split('\n');threads.forEach(this.parseThread.bind(this));},parseThread(threadLine){const tid=threadLine.slice(0,threadLine.indexOf('\t'));const thread=this.getTid(parseInt(tid));thread.name=threadLine.slice(threadLine.indexOf('\t')+1);},getTid(tid){return this.model_.getOrCreateProcess(kPid).getOrCreateThread(tid);},parseMethods(){let methods=this.metadata_.slice(this.metadata_.indexOf(kMethodsStart)+
+kMethodsStart.length);methods=methods.slice(0,methods.indexOf('\n*'));methods=methods.split('\n');methods.forEach(this.parseMethod.bind(this));},parseMethod(methodLine){const data=methodLine.split('\t');const methodId=parseInt(data[0]);const methodName=data[1]+'.'+data[2]+data[3];this.addMethod(methodId,methodName);},addMethod(methodId,methodName){this.methods_[methodId]=methodName;},getMethodName(methodId){return this.methods_[methodId];}};tr.importer.Importer.register(DdmsImporter);return{DdmsImporter,};});'use strict';tr.exportTo('tr.e.audits',function(){class LowMemoryAuditor extends tr.c.Auditor{constructor(model){super();this.model_=model;}
+runAnnotate(){this.model_.device.lowMemoryEvents=this.getLowMemoryEvents_();}
+getLowMemoryEvents_(){const model=this.model_;const result=[];for(const process of model.getAllProcesses()){for(const e of process.getDescendantEvents()){if(!(e instanceof tr.model.ThreadSlice)||e.duration!==0){continue;}
+if(e.category!=='lowmemory'){continue;}
+result.push(e);}}
+return result;}}
+tr.c.Auditor.register(LowMemoryAuditor);return{LowMemoryAuditor};});'use strict';function filterDuplicateTimestamps(timestamps){const dedupedTimestamps=[];let lastTs=0;for(const ts of timestamps){if(ts-lastTs>=1){dedupedTimestamps.push(ts);lastTs=ts;}}
+return dedupedTimestamps;}
+tr.exportTo('tr.e.audits',function(){const VSYNC_COUNTER_PRECISIONS={'android.VSYNC-app':15,'android.VSYNC':15};const VSYNC_SLICE_PRECISIONS={'RenderWidgetHostViewAndroid::OnVSync':5,'VSYNC':10,'vblank':10,'DisplayLinkMac::GetVSyncParameters':5};const BEGIN_FRAME_SLICE_PRECISION={'DisplayScheduler::BeginFrame':10};function VSyncAuditor(model){tr.c.Auditor.call(this,model);}
+VSyncAuditor.prototype={__proto__:tr.c.Auditor.prototype,runAnnotate(){this.model.device.vSyncTimestamps=this.findVSyncTimestamps(this.model);},findVSyncTimestamps(model){let times=[];let maxPrecision=Number.NEGATIVE_INFINITY;let maxTitle=undefined;function useInstead(title,precisions){const precision=precisions[title];if(precision===undefined)return false;if(title===maxTitle)return true;if(precision<=maxPrecision){if(precision===maxPrecision){model.importWarning({type:'VSyncAuditor',message:'Encountered two different VSync events ('+
+maxTitle+', '+title+') with the same precision, '+'ignoring the newer one ('+title+')',showToUser:false,});}
+return false;}
+maxPrecision=precision;maxTitle=title;times=[];return true;}
+for(const pid in model.processes){const process=model.processes[pid];for(const cid in process.counters){if(useInstead(cid,VSYNC_COUNTER_PRECISIONS)){const counter=process.counters[cid];for(let i=0;i<counter.series.length;i++){const series=counter.series[i];Array.prototype.push.apply(times,series.timestamps);}}}
+for(const tid in process.threads){const thread=process.threads[tid];for(let i=0;i<thread.sliceGroup.slices.length;i++){const slice=thread.sliceGroup.slices[i];if(useInstead(slice.title,VSYNC_SLICE_PRECISIONS)){times.push(slice.start);}else if(useInstead(slice.title,BEGIN_FRAME_SLICE_PRECISION)&&slice.args.args&&slice.args.args.frame_time_us){times.push(slice.args.args.frame_time_us/1000.0);}}}}
+times.sort(function(x,y){return x-y;});return filterDuplicateTimestamps(times);}};tr.c.Auditor.register(VSyncAuditor);return{VSyncAuditor,};});'use strict';tr.exportTo('tr.importer',function(){function EmptyImporter(events){this.importPriority=0;}
+EmptyImporter.canImport=function(eventData){if(eventData instanceof Array&&eventData.length===0){return true;}
+if(typeof(eventData)==='string'||eventData instanceof String){return eventData.length===0;}
+return false;};EmptyImporter.prototype={__proto__:tr.importer.Importer.prototype,get importerName(){return'EmptyImporter';}};tr.importer.Importer.register(EmptyImporter);return{EmptyImporter,};});'use strict';tr.exportTo('tr.model.um',function(){function AnimationExpectation(parentModel,initiatorTitle,start,duration){tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.frameEvents_=undefined;}
+AnimationExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:AnimationExpectation,get frameEvents(){if(this.frameEvents_){return this.frameEvents_;}
+this.frameEvents_=new tr.model.EventSet();this.associatedEvents.forEach(function(event){if(event.title===tr.model.helpers.IMPL_RENDERING_STATS){this.frameEvents_.push(event);}},this);return this.frameEvents_;}};tr.model.um.UserExpectation.subTypes.register(AnimationExpectation,{stageTitle:'Animation',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_animation')});return{AnimationExpectation,};});'use strict';tr.exportTo('tr.importer',function(){function ProtoExpectation(type,initiatorType){this.type=type;this.initiatorType=initiatorType;this.start=Infinity;this.end=-Infinity;this.associatedEvents=new tr.model.EventSet();this.isAnimationBegin=false;}
+ProtoExpectation.RESPONSE_TYPE='r';ProtoExpectation.ANIMATION_TYPE='a';ProtoExpectation.IGNORED_TYPE='ignored';const INITIATOR_HIERARCHY=[tr.model.um.INITIATOR_TYPE.PINCH,tr.model.um.INITIATOR_TYPE.FLING,tr.model.um.INITIATOR_TYPE.MOUSE_WHEEL,tr.model.um.INITIATOR_TYPE.SCROLL,tr.model.um.INITIATOR_TYPE.VR,tr.model.um.INITIATOR_TYPE.VIDEO,tr.model.um.INITIATOR_TYPE.WEBGL,tr.model.um.INITIATOR_TYPE.CSS,tr.model.um.INITIATOR_TYPE.MOUSE,tr.model.um.INITIATOR_TYPE.KEYBOARD,tr.model.um.INITIATOR_TYPE.TAP,tr.model.um.INITIATOR_TYPE.TOUCH];function combineInitiatorTypes(title1,title2){for(const item of INITIATOR_HIERARCHY){if(title1===item||title2===item)return item;}
+throw new Error('Invalid titles in combineInitiatorTypes');}
+ProtoExpectation.prototype={get isValid(){return this.end>this.start;},containsTypeNames(typeNames){return this.associatedEvents.some(x=>typeNames.indexOf(x.typeName)>=0);},containsSliceTitle(title){return this.associatedEvents.some(x=>title===x.title);},createInteractionRecord(model){if(this.type!==ProtoExpectation.IGNORED_TYPE&&!this.isValid){model.importWarning({type:'ProtoExpectation',message:'Please file a bug with this trace. '+this.debug(),showToUser:true});return undefined;}
+const duration=this.end-this.start;let ir=undefined;switch(this.type){case ProtoExpectation.RESPONSE_TYPE:ir=new tr.model.um.ResponseExpectation(model,this.initiatorType,this.start,duration,this.isAnimationBegin);break;case ProtoExpectation.ANIMATION_TYPE:ir=new tr.model.um.AnimationExpectation(model,this.initiatorType,this.start,duration);break;}
+if(!ir)return undefined;ir.sourceEvents.addEventSet(this.associatedEvents);function pushAssociatedEvents(event){ir.associatedEvents.push(event);if(event.associatedEvents){ir.associatedEvents.addEventSet(event.associatedEvents);}}
+this.associatedEvents.forEach(function(event){pushAssociatedEvents(event);if(event.subSlices){event.subSlices.forEach(pushAssociatedEvents);}});return ir;},merge(other){this.initiatorType=combineInitiatorTypes(this.initiatorType,other.initiatorType);this.associatedEvents.addEventSet(other.associatedEvents);this.start=Math.min(this.start,other.start);this.end=Math.max(this.end,other.end);if(other.isAnimationBegin){this.isAnimationBegin=true;}},pushEvent(event){this.start=Math.min(this.start,event.start);this.end=Math.max(this.end,event.end);this.associatedEvents.push(event);},pushSample(sample){this.start=Math.min(this.start,sample.timestamp);this.end=Math.max(this.end,sample.timestamp);this.associatedEvents.push(sample);},containsTimestampInclusive(timestamp){return(this.start<=timestamp)&&(timestamp<=this.end);},intersects(other){return(other.start<this.end)&&(other.end>this.start);},isNear(event,threshold){return(this.end+threshold)>event.start;},debug(){let debugString=this.type+'(';debugString+=parseInt(this.start)+' ';debugString+=parseInt(this.end);this.associatedEvents.forEach(function(event){debugString+=' '+event.typeName;});return debugString+')';}};return{ProtoExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const ProtoExpectation=tr.importer.ProtoExpectation;const INITIATOR_TYPE=tr.model.um.INITIATOR_TYPE;const INPUT_TYPE=tr.e.cc.INPUT_EVENT_TYPE_NAMES;const KEYBOARD_TYPE_NAMES=[INPUT_TYPE.CHAR,INPUT_TYPE.KEY_DOWN_RAW,INPUT_TYPE.KEY_DOWN,INPUT_TYPE.KEY_UP];const MOUSE_RESPONSE_TYPE_NAMES=[INPUT_TYPE.CLICK,INPUT_TYPE.CONTEXT_MENU];const MOUSE_WHEEL_TYPE_NAMES=[INPUT_TYPE.MOUSE_WHEEL];const MOUSE_DRAG_TYPE_NAMES=[INPUT_TYPE.MOUSE_DOWN,INPUT_TYPE.MOUSE_MOVE,INPUT_TYPE.MOUSE_UP];const TAP_TYPE_NAMES=[INPUT_TYPE.TAP,INPUT_TYPE.TAP_CANCEL,INPUT_TYPE.TAP_DOWN];const PINCH_TYPE_NAMES=[INPUT_TYPE.PINCH_BEGIN,INPUT_TYPE.PINCH_END,INPUT_TYPE.PINCH_UPDATE];const FLING_TYPE_NAMES=[INPUT_TYPE.FLING_CANCEL,INPUT_TYPE.FLING_START];const TOUCH_TYPE_NAMES=[INPUT_TYPE.TOUCH_END,INPUT_TYPE.TOUCH_MOVE,INPUT_TYPE.TOUCH_START];const SCROLL_TYPE_NAMES=[INPUT_TYPE.SCROLL_BEGIN,INPUT_TYPE.SCROLL_END,INPUT_TYPE.SCROLL_UPDATE];const ALL_HANDLED_TYPE_NAMES=[].concat(KEYBOARD_TYPE_NAMES,MOUSE_RESPONSE_TYPE_NAMES,MOUSE_WHEEL_TYPE_NAMES,MOUSE_DRAG_TYPE_NAMES,PINCH_TYPE_NAMES,TAP_TYPE_NAMES,FLING_TYPE_NAMES,TOUCH_TYPE_NAMES,SCROLL_TYPE_NAMES);const RENDERER_FLING_TITLE='InputHandlerProxy::HandleGestureFling::started';const PLAYBACK_EVENT_TITLE='VideoPlayback';const CSS_ANIMATION_TITLE='Animation';const VR_COUNTER_NAMES=['gpu.WebVR FPS','gpu.WebVR frame time (ms)','gpu.WebVR pose prediction (ms)','gpu.WebXR FPS',];const VR_EXPECTATION_EVENTS={'Vr.AcquireGvrFrame':{'histogramName':'acquire_frame','description':'Duration acquire a frame from GVR','hasCpuTime':true,},'Vr.DrawFrame':{'histogramName':'draw_frame','description':'Duration to render one frame','hasCpuTime':true,},'Vr.PostSubmitDrawOnGpu':{'histogramName':'post_submit_draw_on_gpu','description':'Duration to draw a frame on GPU post submit to '+'GVR. Note this duration may include time spent on '+'reprojection','hasCpuTime':false,},'Vr.ProcessControllerInput':{'histogramName':'update_controller','description':'Duration to query input from the controller','hasCpuTime':true,},'Vr.ProcessControllerInputForWebXr':{'histogramName':'update_controller_webxr','description':'Duration to query input from the controller for WebXR','hasCpuTime':true,},'Vr.SubmitFrameNow':{'histogramName':'submit_frame','description':'Duration to submit a frame to GVR','hasCpuTime':true,}};const WEBXR_INSTANT_EVENTS={'WebXR frame time (ms)':{'javascript':{'histogramName':'webxr_frame_time_javascript','description':'WebXR frame time spent on JavaScript',},'rendering':{'histogramName':'webxr_frame_time_rendering','description':'WebXR frame time spent on rendering'}},'WebXR pose prediction':{'milliseconds':{'histogramName':'webxr_pose_prediction','description':'WebXR pose prediction in ms',},},};const XR_DEVICE_SERVICE_PROCESS='Service: xr_device_service';function isXrDeviceServiceProcess(process){if(process.name===XR_DEVICE_SERVICE_PROCESS)return true;return false;}
+const VR_RESPONSE_MS=1000;const INPUT_MERGE_THRESHOLD_MS=200;const ANIMATION_MERGE_THRESHOLD_MS=32;const MOUSE_WHEEL_THRESHOLD_MS=40;const MOUSE_MOVE_THRESHOLD_MS=40;function compareEvents(x,y){if(x.start!==y.start){return x.start-y.start;}
+if(x.end!==y.end){return x.end-y.end;}
+if(x.guid&&y.guid){return x.guid-y.guid;}
+return 0;}
+function forEventTypesIn(events,typeNames,cb,opt_this){events.forEach(function(event){if(typeNames.indexOf(event.typeName)>=0){cb.call(opt_this,event);}});}
+function causedFrame(event){return event.associatedEvents.some(isImplFrameEvent);}
+function getSortedFrameEventsByProcess(modelHelper){const frameEventsByPid={};for(const[pid,rendererHelper]of
+Object.entries(modelHelper.rendererHelpers)){frameEventsByPid[pid]=rendererHelper.getFrameEventsInRange(tr.model.helpers.IMPL_FRAMETIME_TYPE,modelHelper.model.bounds);}
+return frameEventsByPid;}
+function getSortedInputEvents(modelHelper){const inputEvents=[];const browserProcess=modelHelper.browserHelper.process;const mainThread=browserProcess.findAtMostOneThreadNamed('CrBrowserMain');for(const slice of mainThread.asyncSliceGroup.getDescendantEvents()){if(!slice.isTopLevel)continue;if(!(slice instanceof tr.e.cc.InputLatencyAsyncSlice))continue;if(isNaN(slice.start)||isNaN(slice.duration)||isNaN(slice.end)){continue;}
+inputEvents.push(slice);}
+return inputEvents.sort(compareEvents);}
+function findProtoExpectations(modelHelper,sortedInputEvents,warn){const protoExpectations=[];const handlers=[handleKeyboardEvents,handleMouseResponseEvents,handleMouseWheelEvents,handleMouseDragEvents,handleTapResponseEvents,handlePinchEvents,handleFlingEvents,handleTouchEvents,handleScrollEvents,handleCSSAnimations,handleWebGLAnimations,handleVideoAnimations,handleVrAnimations,];handlers.forEach(function(handler){protoExpectations.push.apply(protoExpectations,handler(modelHelper,sortedInputEvents,warn));});protoExpectations.sort(compareEvents);return protoExpectations;}
+function handleKeyboardEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];forEventTypesIn(sortedInputEvents,KEYBOARD_TYPE_NAMES,function(event){const pe=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.KEYBOARD);pe.pushEvent(event);protoExpectations.push(pe);});return protoExpectations;}
+function handleMouseResponseEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];forEventTypesIn(sortedInputEvents,MOUSE_RESPONSE_TYPE_NAMES,function(event){const pe=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.MOUSE);pe.pushEvent(event);protoExpectations.push(pe);});return protoExpectations;}
+function handleMouseWheelEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;let prevEvent_=undefined;forEventTypesIn(sortedInputEvents,MOUSE_WHEEL_TYPE_NAMES,function(event){const prevEvent=prevEvent_;prevEvent_=event;if(currentPE&&(prevEvent.start+MOUSE_WHEEL_THRESHOLD_MS)>=event.start){if(currentPE.type===ProtoExpectation.ANIMATION_TYPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.MOUSE_WHEEL);currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+return;}
+currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.MOUSE_WHEEL);currentPE.pushEvent(event);protoExpectations.push(currentPE);});return protoExpectations;}
+function handleMouseDragEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;let mouseDownEvent=undefined;forEventTypesIn(sortedInputEvents,MOUSE_DRAG_TYPE_NAMES,function(event){switch(event.typeName){case INPUT_TYPE.MOUSE_DOWN:if(causedFrame(event)){const pe=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.MOUSE);pe.pushEvent(event);protoExpectations.push(pe);}else{mouseDownEvent=event;}
+break;case INPUT_TYPE.MOUSE_MOVE:if(!causedFrame(event)){const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);}else if(!currentPE||!currentPE.isNear(event,MOUSE_MOVE_THRESHOLD_MS)){currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.MOUSE);currentPE.pushEvent(event);if(mouseDownEvent){currentPE.associatedEvents.push(mouseDownEvent);mouseDownEvent=undefined;}
+protoExpectations.push(currentPE);}else{if(currentPE.type===ProtoExpectation.ANIMATION_TYPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.MOUSE);currentPE.pushEvent(event);protoExpectations.push(currentPE);}}
+break;case INPUT_TYPE.MOUSE_UP:if(!mouseDownEvent){const pe=new ProtoExpectation(causedFrame(event)?ProtoExpectation.RESPONSE_TYPE:ProtoExpectation.IGNORED_TYPE,INITIATOR_TYPE.MOUSE);pe.pushEvent(event);protoExpectations.push(pe);break;}
+if(currentPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.MOUSE);if(mouseDownEvent){currentPE.associatedEvents.push(mouseDownEvent);}
+currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+mouseDownEvent=undefined;currentPE=undefined;break;}});if(mouseDownEvent){currentPE=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);currentPE.pushEvent(mouseDownEvent);protoExpectations.push(currentPE);}
+return protoExpectations;}
+function handleTapResponseEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;forEventTypesIn(sortedInputEvents,TAP_TYPE_NAMES,function(event){switch(event.typeName){case INPUT_TYPE.TAP_DOWN:currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.TAP);currentPE.pushEvent(event);protoExpectations.push(currentPE);break;case INPUT_TYPE.TAP:if(currentPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.TAP);currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+currentPE=undefined;break;case INPUT_TYPE.TAP_CANCEL:if(!currentPE){const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);break;}
+if(currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.TAP);currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+currentPE=undefined;break;}});return protoExpectations;}
+function handlePinchEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;let sawFirstUpdate=false;const modelBounds=modelHelper.model.bounds;forEventTypesIn(sortedInputEvents,PINCH_TYPE_NAMES,function(event){switch(event.typeName){case INPUT_TYPE.PINCH_BEGIN:if(currentPE&&currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)){currentPE.pushEvent(event);break;}
+currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.PINCH);currentPE.pushEvent(event);currentPE.isAnimationBegin=true;protoExpectations.push(currentPE);sawFirstUpdate=false;break;case INPUT_TYPE.PINCH_UPDATE:if(!currentPE||((currentPE.type===ProtoExpectation.RESPONSE_TYPE)&&sawFirstUpdate)||!currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)){currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.PINCH);currentPE.pushEvent(event);protoExpectations.push(currentPE);}else{currentPE.pushEvent(event);sawFirstUpdate=true;}
+break;case INPUT_TYPE.PINCH_END:if(currentPE){currentPE.pushEvent(event);}else{const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);}
+currentPE=undefined;break;}});return protoExpectations;}
+function handleFlingEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;function isRendererFling(event){return event.title===RENDERER_FLING_TITLE;}
+const browserHelper=modelHelper.browserHelper;const flingEvents=browserHelper.getAllAsyncSlicesMatching(isRendererFling);forEventTypesIn(sortedInputEvents,FLING_TYPE_NAMES,function(event){flingEvents.push(event);});flingEvents.sort(compareEvents);flingEvents.forEach(function(event){if(event.title===RENDERER_FLING_TITLE){if(currentPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.FLING);currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+return;}
+switch(event.typeName){case INPUT_TYPE.FLING_START:if(currentPE){warn({type:'UserModelBuilder',message:'Unexpected FlingStart',showToUser:false,});currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.FLING);currentPE.pushEvent(event);currentPE.end=0;protoExpectations.push(currentPE);}
+break;case INPUT_TYPE.FLING_CANCEL:if(currentPE){currentPE.pushEvent(event);currentPE.end=event.start;currentPE=undefined;}else{const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);}
+break;}});if(currentPE&&!currentPE.end){currentPE.end=modelHelper.model.bounds.max;}
+return protoExpectations;}
+function handleTouchEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;let sawFirstMove=false;forEventTypesIn(sortedInputEvents,TOUCH_TYPE_NAMES,function(event){switch(event.typeName){case INPUT_TYPE.TOUCH_START:if(currentPE){currentPE.pushEvent(event);}else{currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.TOUCH);currentPE.pushEvent(event);currentPE.isAnimationBegin=true;protoExpectations.push(currentPE);sawFirstMove=false;}
+break;case INPUT_TYPE.TOUCH_MOVE:if(!currentPE){currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.TOUCH);currentPE.pushEvent(event);protoExpectations.push(currentPE);break;}
+if((sawFirstMove&&(currentPE.type===ProtoExpectation.RESPONSE_TYPE))||!currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)){const prevEnd=currentPE.end;currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.TOUCH);currentPE.pushEvent(event);currentPE.start=prevEnd;protoExpectations.push(currentPE);}else{currentPE.pushEvent(event);sawFirstMove=true;}
+break;case INPUT_TYPE.TOUCH_END:if(!currentPE){const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);break;}
+if(currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)){currentPE.pushEvent(event);}else{const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);}
+currentPE=undefined;break;}});return protoExpectations;}
+function handleScrollEvents(modelHelper,sortedInputEvents,warn){const protoExpectations=[];let currentPE=undefined;let sawFirstUpdate=false;forEventTypesIn(sortedInputEvents,SCROLL_TYPE_NAMES,function(event){switch(event.typeName){case INPUT_TYPE.SCROLL_BEGIN:currentPE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.SCROLL);currentPE.pushEvent(event);currentPE.isAnimationBegin=true;protoExpectations.push(currentPE);sawFirstUpdate=false;break;case INPUT_TYPE.SCROLL_UPDATE:if(currentPE){if(currentPE.isNear(event,INPUT_MERGE_THRESHOLD_MS)&&((currentPE.type===ProtoExpectation.ANIMATION_TYPE)||!sawFirstUpdate)){currentPE.pushEvent(event);sawFirstUpdate=true;}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.SCROLL);currentPE.pushEvent(event);protoExpectations.push(currentPE);}}else{currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.SCROLL);currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+break;case INPUT_TYPE.SCROLL_END:if(!currentPE){warn({type:'UserModelBuilder',message:'Unexpected ScrollEnd',showToUser:false,});const pe=new ProtoExpectation(ProtoExpectation.IGNORED_TYPE);pe.pushEvent(event);protoExpectations.push(pe);break;}
+currentPE.pushEvent(event);break;}});return protoExpectations;}
+function handleVideoAnimations(modelHelper,sortedInputEvents,warn){const events=[];for(const pid in modelHelper.rendererHelpers){for(const tid in modelHelper.rendererHelpers[pid].process.threads){for(const asyncSlice of
+modelHelper.rendererHelpers[pid].process.threads[tid].asyncSliceGroup.slices){if(asyncSlice.title===PLAYBACK_EVENT_TITLE){events.push(asyncSlice);}}}}
+events.sort(tr.importer.compareEvents);const protoExpectations=[];for(const event of events){const currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.VIDEO);currentPE.start=event.start;currentPE.end=event.end;currentPE.pushEvent(event);protoExpectations.push(currentPE);}
+return protoExpectations;}
+function handleVrAnimations(modelHelper,sortedInputEvents,warn){const events=[];const processes=[];if(typeof modelHelper.gpuHelper!=='undefined'){processes.push(modelHelper.gpuHelper.process);}
+for(const helper of Object.values(modelHelper.rendererHelpers)){processes.push(helper.process);}
+for(const helper of Object.values(modelHelper.browserHelpers)){processes.push(helper.process);}
+for(const service of modelHelper.model.getAllProcesses(isXrDeviceServiceProcess)){processes.push(service);}
+let vrCounterStart=Number.MAX_SAFE_INTEGER;let vrEventStart=Number.MAX_SAFE_INTEGER;for(const proc of processes){for(const[counterName,counterSeries]of
+Object.entries(proc.counters)){if(VR_COUNTER_NAMES.includes(counterName)){for(const series of counterSeries.series){for(const sample of series.samples){events.push(sample);vrCounterStart=Math.min(vrCounterStart,sample.timestamp);}}}}
+for(const thread of Object.values(proc.threads)){for(const container of thread.childEventContainers()){for(const slice of container.slices){if(slice.title in VR_EXPECTATION_EVENTS||slice.title in WEBXR_INSTANT_EVENTS){events.push(slice);vrEventStart=Math.min(vrEventStart,slice.start);}}}}}
+if(events.length===0){return[];}
+events.sort(function(x,y){if(x.range.min!==y.range.min){return x.range.min-y.range.min;}
+return x.guid-y.guid;});vrCounterStart=(vrCounterStart===Number.MAX_SAFE_INTEGER)?0:vrCounterStart;vrEventStart=(vrEventStart===Number.MAX_SAFE_INTEGER)?0:vrEventStart;const vrAnimationStart=Math.max(vrCounterStart,vrEventStart)+
+VR_RESPONSE_MS;const responsePE=new ProtoExpectation(ProtoExpectation.RESPONSE_TYPE,INITIATOR_TYPE.VR);const animationPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.VR);let lastResponseEvent;for(const event of events){if(event.range.min<vrAnimationStart){if(event instanceof tr.model.CounterSample){responsePE.pushSample(event);}else{responsePE.pushEvent(event);}
+lastResponseEvent=event;}else{if(event instanceof tr.model.CounterSample){animationPE.pushSample(event);}else{animationPE.pushEvent(event);}}}
+if(lastResponseEvent instanceof tr.model.CounterSample){animationPE.pushSample(lastResponseEvent);}else{animationPE.pushEvent(lastResponseEvent);}
+return[responsePE,animationPE];}
+function handleCSSAnimations(modelHelper,sortedInputEvents,warn){const animationEvents=modelHelper.browserHelper.getAllAsyncSlicesMatching(function(event){return((event.title===CSS_ANIMATION_TITLE)&&event.isTopLevel&&(event.duration>0));});const animationRanges=[];function pushAnimationRange(start,end,animation){const range=tr.b.math.Range.fromExplicitRange(start,end);range.animation=animation;animationRanges.push(range);}
+animationEvents.forEach(function(animation){if(animation.subSlices.length===0){pushAnimationRange(animation.start,animation.end,animation);}else{let start=undefined;animation.subSlices.forEach(function(sub){if((sub.args.data.state==='running')&&(start===undefined)){start=sub.start;}else if((sub.args.data.state==='paused')||(sub.args.data.state==='idle')||(sub.args.data.state==='finished')){if(start===undefined){start=modelHelper.model.bounds.min;}
+pushAnimationRange(start,sub.start,animation);start=undefined;}});if(start!==undefined){pushAnimationRange(start,animation.end,animation);}}});return animationRanges.map(function(range){const protoExpectation=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.CSS);protoExpectation.start=range.min;protoExpectation.end=range.max;protoExpectation.associatedEvents.push(range.animation);return protoExpectation;});}
+function findWebGLEvents(modelHelper,mailboxEvents,animationEvents){for(const event of modelHelper.model.getDescendantEvents()){if(event.title==='DrawingBuffer::prepareMailbox'){mailboxEvents.push(event);}else if(event.title==='PageAnimator::serviceScriptedAnimations'){animationEvents.push(event);}}}
+function findMailboxEventsNearAnimationEvents(mailboxEvents,animationEvents){if(animationEvents.length===0)return[];mailboxEvents.sort(compareEvents);animationEvents.sort(compareEvents);const animationIterator=animationEvents[Symbol.iterator]();let animationEvent=animationIterator.next().value;const filteredEvents=[];for(const event of mailboxEvents){while(animationEvent&&(animationEvent.start<(event.start-ANIMATION_MERGE_THRESHOLD_MS))){animationEvent=animationIterator.next().value;}
+if(!animationEvent)break;if(animationEvent.start<(event.start+ANIMATION_MERGE_THRESHOLD_MS)){filteredEvents.push(event);}}
+return filteredEvents;}
+function createProtoExpectationsFromMailboxEvents(mailboxEvents){const protoExpectations=[];let currentPE=undefined;for(const event of mailboxEvents){if(currentPE===undefined||!currentPE.isNear(event,ANIMATION_MERGE_THRESHOLD_MS)){currentPE=new ProtoExpectation(ProtoExpectation.ANIMATION_TYPE,INITIATOR_TYPE.WEBGL);currentPE.pushEvent(event);protoExpectations.push(currentPE);}else{currentPE.pushEvent(event);}}
+return protoExpectations;}
+function handleWebGLAnimations(modelHelper,sortedInputEvents,warn){const prepareMailboxEvents=[];const scriptedAnimationEvents=[];findWebGLEvents(modelHelper,prepareMailboxEvents,scriptedAnimationEvents);const webGLMailboxEvents=findMailboxEventsNearAnimationEvents(prepareMailboxEvents,scriptedAnimationEvents);return createProtoExpectationsFromMailboxEvents(webGLMailboxEvents);}
+function postProcessProtoExpectations(modelHelper,protoExpectations){protoExpectations=findFrameEventsForAnimations(modelHelper,protoExpectations);protoExpectations=mergeIntersectingResponses(protoExpectations);protoExpectations=mergeIntersectingAnimations(protoExpectations);protoExpectations=fixResponseAnimationStarts(protoExpectations);protoExpectations=fixTapResponseTouchAnimations(protoExpectations);return protoExpectations;}
+function mergeIntersectingResponses(protoExpectations){const newPEs=[];while(protoExpectations.length){const pe=protoExpectations.shift();newPEs.push(pe);if(pe.type!==ProtoExpectation.RESPONSE_TYPE)continue;for(let i=0;i<protoExpectations.length;++i){const otherPE=protoExpectations[i];if(otherPE.type!==pe.type)continue;if(!otherPE.intersects(pe))continue;const typeNames=pe.associatedEvents.map(function(event){return event.typeName;});if(otherPE.containsTypeNames(typeNames))continue;pe.merge(otherPE);protoExpectations.splice(i,1);--i;}}
+return newPEs;}
+function mergeIntersectingAnimations(protoExpectations){const newPEs=[];while(protoExpectations.length){const pe=protoExpectations.shift();newPEs.push(pe);if(pe.type!==ProtoExpectation.ANIMATION_TYPE)continue;const isCSS=pe.initiatorType===INITIATOR_TYPE.CSS;const isFling=pe.containsTypeNames([INPUT_TYPE.FLING_START]);const isVideo=pe.initiatorType===INITIATOR_TYPE.VIDEO;for(let i=0;i<protoExpectations.length;++i){const otherPE=protoExpectations[i];if(otherPE.type!==pe.type)continue;if((isCSS&&otherPE.initiatorType!==INITIATOR_TYPE.CSS)||isFling!==otherPE.containsTypeNames([INPUT_TYPE.FLING_START])||isVideo&&otherPE.initiatorType!==INITIATOR_TYPE.VIDEO||otherPE.initiatorType===INITIATOR_TYPE.VR){continue;}
+if(isCSS){if(!pe.isNear(otherPE,ANIMATION_MERGE_THRESHOLD_MS)){continue;}}else if(!otherPE.intersects(pe)){continue;}
+pe.merge(otherPE);protoExpectations.splice(i,1);--i;}}
+return newPEs;}
+function fixResponseAnimationStarts(protoExpectations){protoExpectations.forEach(function(ape){if(ape.type!==ProtoExpectation.ANIMATION_TYPE){return;}
+protoExpectations.forEach(function(rpe){if(rpe.type!==ProtoExpectation.RESPONSE_TYPE){return;}
+if(!ape.containsTimestampInclusive(rpe.end)){return;}
+if(ape.containsTimestampInclusive(rpe.start)){return;}
+ape.start=rpe.end;if(ape.associatedEvents!==undefined){ape.associatedEvents=ape.associatedEvents.filter(e=>(!isImplFrameEvent(e)||e.start>=ape.start));}});});return protoExpectations;}
+function isImplFrameEvent(event){return event.title===tr.model.helpers.IMPL_RENDERING_STATS;}
+function fixTapResponseTouchAnimations(protoExpectations){function isTapResponse(pe){return(pe.type===ProtoExpectation.RESPONSE_TYPE)&&pe.containsTypeNames([INPUT_TYPE.TAP]);}
+function isTouchAnimation(pe){return(pe.type===ProtoExpectation.ANIMATION_TYPE)&&pe.containsTypeNames([INPUT_TYPE.TOUCH_MOVE])&&!pe.containsTypeNames([INPUT_TYPE.SCROLL_UPDATE,INPUT_TYPE.PINCH_UPDATE]);}
+const newPEs=[];while(protoExpectations.length){const pe=protoExpectations.shift();newPEs.push(pe);const peIsTapResponse=isTapResponse(pe);const peIsTouchAnimation=isTouchAnimation(pe);if(!peIsTapResponse&&!peIsTouchAnimation){continue;}
+for(let i=0;i<protoExpectations.length;++i){const otherPE=protoExpectations[i];if(!otherPE.intersects(pe))continue;if(peIsTapResponse&&!isTouchAnimation(otherPE))continue;if(peIsTouchAnimation&&!isTapResponse(otherPE))continue;pe.type=ProtoExpectation.RESPONSE_TYPE;pe.merge(otherPE);protoExpectations.splice(i,1);--i;}}
+return newPEs;}
+function findFrameEventsForAnimations(modelHelper,protoExpectations){const newPEs=[];const frameEventsByPid=getSortedFrameEventsByProcess(modelHelper);for(const pe of protoExpectations){if(pe.type!==ProtoExpectation.ANIMATION_TYPE){newPEs.push(pe);continue;}
+const frameEvents=[];for(const pid of Object.keys(modelHelper.rendererHelpers)){const range=tr.b.math.Range.fromExplicitRange(pe.start,pe.end);frameEvents.push.apply(frameEvents,range.filterArray(frameEventsByPid[pid],e=>e.start));}
+if(frameEvents.length===0&&!(pe.initiatorType===INITIATOR_TYPE.WEBGL||pe.initiatorType===INITIATOR_TYPE.VR)){pe.type=ProtoExpectation.IGNORED_TYPE;newPEs.push(pe);continue;}
+pe.associatedEvents.addEventSet(frameEvents);newPEs.push(pe);}
+return newPEs;}
+function checkAllInputEventsHandled(modelHelper,sortedInputEvents,protoExpectations,warn){const handledEvents=[];protoExpectations.forEach(function(protoExpectation){protoExpectation.associatedEvents.forEach(function(event){if((event.title===CSS_ANIMATION_TITLE)&&(event.subSlices.length>0)){return;}
+if((handledEvents.indexOf(event)>=0)&&(!isImplFrameEvent(event))){warn({type:'UserModelBuilder',message:`double-handled event: ${event.typeName} @ ${event.start}`,showToUser:false,});return;}
+handledEvents.push(event);});});sortedInputEvents.forEach(function(event){if(handledEvents.indexOf(event)<0){warn({type:'UserModelBuilder',message:`double-handled event: ${event.typeName} @ ${event.start}`,showToUser:false,});}});}
+function findInputExpectations(modelHelper){let warning;function warn(w){if(warning)return;warning=w;}
+const sortedInputEvents=getSortedInputEvents(modelHelper);let protoExpectations=findProtoExpectations(modelHelper,sortedInputEvents,warn);protoExpectations=postProcessProtoExpectations(modelHelper,protoExpectations);checkAllInputEventsHandled(modelHelper,sortedInputEvents,protoExpectations,warn);if(warning)modelHelper.model.importWarning(warning);const expectations=[];protoExpectations.forEach(function(protoExpectation){const ir=protoExpectation.createInteractionRecord(modelHelper.model);if(ir){expectations.push(ir);}});return expectations;}
+return{findInputExpectations,compareEvents,CSS_ANIMATION_TITLE,VR_EXPECTATION_EVENTS,WEBXR_INSTANT_EVENTS,};});'use strict';tr.exportTo('tr.b',function(){class FixedColorScheme{constructor(namesToColors){this.namesToColors_=namesToColors;}
+static fromNames(names){const namesToColors=new Map();const generator=new tr.b.SinebowColorGenerator();for(const name of names){namesToColors.set(name,generator.colorForKey(name));}
+return new FixedColorScheme(namesToColors);}
+getColor(name){const color=this.namesToColors_.get(name);if(color===undefined)throw new Error('Unknown color: '+name);return color;}}
+const MemoryColumnColorScheme=new FixedColorScheme(new Map([['used_memory_column',new tr.b.Color(0,0,255)],['older_used_memory_column',new tr.b.Color(153,204,255)],['tracing_memory_column',new tr.b.Color(153,153,153)]]));function FixedColorSchemeRegistry(){}
+FixedColorSchemeRegistry.lookUp=function(name){const info=this.findTypeInfoMatching(info=>info.metadata.name===name);if(!info)return undefined;return info.constructor();};const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(FixedColorSchemeRegistry,options);return{MemoryColumnColorScheme,FixedColorScheme,FixedColorSchemeRegistry,};});'use strict';tr.exportTo('tr.e.chrome.chrome_processes',function(){const CHROME_PROCESS_NAMES={BROWSER:'browser_process',RENDERER:'renderer_processes',ALL:'all_processes',GPU:'gpu_process',PPAPI:'ppapi_process',UNKNOWN:'unknown_processes',};const PROCESS_COLOR_SCHEME_NAME='ChromeProcessNames';const PROCESS_COLOR_SCHEME=tr.b.FixedColorScheme.fromNames(Object.values(CHROME_PROCESS_NAMES));tr.b.FixedColorSchemeRegistry.register(()=>PROCESS_COLOR_SCHEME,{name:PROCESS_COLOR_SCHEME_NAME,});function canonicalizeName(name){return name.toLowerCase().replace(' ','_');}
+function canonicalizeProcessName(rawProcessName){if(!rawProcessName)return CHROME_PROCESS_NAMES.UNKNOWN;const baseCanonicalName=canonicalizeName(rawProcessName);switch(baseCanonicalName){case'renderer':return CHROME_PROCESS_NAMES.RENDERER;case'browser':return CHROME_PROCESS_NAMES.BROWSER;}
+if(Object.values(CHROME_PROCESS_NAMES).includes(baseCanonicalName)){return baseCanonicalName;}
+return CHROME_PROCESS_NAMES.UNKNOWN;}
+return{CHROME_PROCESS_NAMES,PROCESS_COLOR_SCHEME,PROCESS_COLOR_SCHEME_NAME,canonicalizeName,canonicalizeProcessName,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function perceptualBlend(ir,index,score){return Math.exp(1-score);}
+function filterExpectationsByRange(irs,opt_range){const filteredExpectations=[];irs.forEach(function(ir){if(!(ir instanceof tr.model.um.UserExpectation))return;if(!opt_range||opt_range.intersectsExplicitRangeInclusive(ir.start,ir.end)){filteredExpectations.push(ir);}});return filteredExpectations;}
+function splitGlobalDumpsByBrowserName(model,opt_rangeOfInterest){const chromeModelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const browserNameToGlobalDumps=new Map();const globalDumpToBrowserHelper=new WeakMap();if(chromeModelHelper){chromeModelHelper.browserHelpers.forEach(function(helper){const globalDumps=skipDumpsThatDoNotIntersectRange(helper.process.memoryDumps.map(d=>d.globalMemoryDump),opt_rangeOfInterest);globalDumps.forEach(function(globalDump){const existingHelper=globalDumpToBrowserHelper.get(globalDump);if(existingHelper!==undefined){throw new Error('Memory dump ID clash across multiple browsers '+'with PIDs: '+existingHelper.pid+' and '+helper.pid);}
+globalDumpToBrowserHelper.set(globalDump,helper);});makeKeyUniqueAndSet(browserNameToGlobalDumps,tr.e.chrome.chrome_processes.canonicalizeName(helper.browserName),globalDumps);});}
+const unclassifiedGlobalDumps=skipDumpsThatDoNotIntersectRange(model.globalMemoryDumps.filter(g=>!globalDumpToBrowserHelper.has(g)),opt_rangeOfInterest);if(unclassifiedGlobalDumps.length>0){makeKeyUniqueAndSet(browserNameToGlobalDumps,'unknown_browser',unclassifiedGlobalDumps);}
+return browserNameToGlobalDumps;}
+function makeKeyUniqueAndSet(map,key,value){let uniqueKey=key;let nextIndex=2;while(map.has(uniqueKey)){uniqueKey=key+nextIndex;nextIndex++;}
+map.set(uniqueKey,value);}
+function skipDumpsThatDoNotIntersectRange(dumps,opt_range){if(!opt_range)return dumps;return dumps.filter(d=>opt_range.intersectsExplicitRangeInclusive(d.start,d.end));}
+function hasCategoryAndName(event,category,title){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
+return{hasCategoryAndName,filterExpectationsByRange,perceptualBlend,splitGlobalDumpsByBrowserName};});'use strict';tr.exportTo('tr.e.chrome',function(){const CHROME_INTERNAL_URLS=['','about:blank','data:text/html,pluginplaceholderdata','chrome-error://chromewebdata/'];const SCHEDULER_TOP_LEVEL_TASK_TITLE='ThreadControllerImpl::RunTask';const SCHEDULER_TOP_LEVEL_TASKS=new Set([SCHEDULER_TOP_LEVEL_TASK_TITLE,'ThreadControllerImpl::DoWork','TaskQueueManager::ProcessTaskFromWorkQueue']);class EventFinderUtils{static hasCategoryAndName(event,category,title){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
+static*getMainThreadEvents(rendererHelper,eventTitle,eventCategory){if(!rendererHelper.mainThread)return;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(rendererHelper.isTelemetryInternalEvent(ev))continue;if(!this.hasCategoryAndName(ev,eventCategory,eventTitle)){continue;}
+yield ev;}}
+static getNetworkEventsInRange(process,range){const networkEvents=[];for(const thread of Object.values(process.threads)){const threadHelper=new tr.model.helpers.ChromeThreadHelper(thread);const events=threadHelper.getNetworkEvents();for(const event of events){if(range.intersectsExplicitRangeInclusive(event.start,event.end)){networkEvents.push(event);}}}
+return networkEvents;}
+static getSortedMainThreadEventsByFrame(rendererHelper,eventTitle,eventCategory){const eventsByFrame=new Map();const events=this.getMainThreadEvents(rendererHelper,eventTitle,eventCategory);for(const ev of events){const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;if(!eventsByFrame.has(frameIdRef)){eventsByFrame.set(frameIdRef,[]);}
+eventsByFrame.get(frameIdRef).push(ev);}
+return eventsByFrame;}
+static getSortedMainThreadEventsByNavId(rendererHelper,eventTitle,eventCategory){const eventsByNavId=new Map();const events=this.getMainThreadEvents(rendererHelper,eventTitle,eventCategory);for(const ev of events){if(ev.args.data===undefined)continue;const navIdRef=ev.args.data.navigationId;if(navIdRef===undefined)continue;eventsByNavId.set(navIdRef,ev);}
+return eventsByNavId;}
+static findLastEventStartingOnOrBeforeTimestamp(sortedEvents,timestamp){const firstIndexAfterTimestamp=tr.b.findFirstTrueIndexInSortedArray(sortedEvents,e=>e.start>timestamp);if(firstIndexAfterTimestamp===0)return undefined;return sortedEvents[firstIndexAfterTimestamp-1];}
+static findLastEventStartingBeforeTimestamp(sortedEvents,timestamp){const firstIndexAfterTimestamp=tr.b.findFirstTrueIndexInSortedArray(sortedEvents,e=>e.start>=timestamp);if(firstIndexAfterTimestamp===0)return undefined;return sortedEvents[firstIndexAfterTimestamp-1];}
+static findNextEventStartingOnOrAfterTimestamp(sortedEvents,timestamp){const firstIndexOnOrAfterTimestamp=tr.b.findFirstTrueIndexInSortedArray(sortedEvents,e=>e.start>=timestamp);if(firstIndexOnOrAfterTimestamp===sortedEvents.length){return undefined;}
+return sortedEvents[firstIndexOnOrAfterTimestamp];}
+static findNextEventStartingAfterTimestamp(sortedEvents,timestamp){const firstIndexOnOrAfterTimestamp=tr.b.findFirstTrueIndexInSortedArray(sortedEvents,e=>e.start>timestamp);if(firstIndexOnOrAfterTimestamp===sortedEvents.length){return undefined;}
+return sortedEvents[firstIndexOnOrAfterTimestamp];}
+static findToplevelSchedulerTasks(mainThread){const tasks=[];for(const task of mainThread.findTopmostSlices(slice=>slice.category==='toplevel'&&SCHEDULER_TOP_LEVEL_TASKS.has(slice.title))){tasks.push(task);}
+return tasks;}}
+return{EventFinderUtils,CHROME_INTERNAL_URLS,SCHEDULER_TOP_LEVEL_TASK_TITLE,};});'use strict';tr.exportTo('tr.e.chrome',function(){const TIME_TO_INTERACTIVE_WINDOW_SIZE_MS=5000;const ACTIVE_REQUEST_TOLERANCE=2;const FCI_MIN_CLUSTER_SEPARATION_MS=1000;const TASK_CLUSTER_HEAVINESS_THRESHOLD_MS=250;const ENDPOINT_TYPES={LONG_TASK_START:'LONG_TASK_START',LONG_TASK_END:'LONG_TASK_END',REQUEST_START:'REQUEST_START',REQUEST_END:'REQUEST_END'};function getEndpoints_(events,startType,endType){const endpoints=[];for(const event of events){endpoints.push({time:event.start,type:startType});endpoints.push({time:event.end,type:endType});}
+return endpoints;}
+function reachedTTIQuiscence_(timestamp,networkQuietWindowStart,mainThreadQuietWindowStart){if(networkQuietWindowStart===undefined||mainThreadQuietWindowStart===undefined){return false;}
+const mainThreadQuietForLongEnough=timestamp-mainThreadQuietWindowStart>=TIME_TO_INTERACTIVE_WINDOW_SIZE_MS;const networkQuietForLongEnough=timestamp-networkQuietWindowStart>=TIME_TO_INTERACTIVE_WINDOW_SIZE_MS;return mainThreadQuietForLongEnough&&networkQuietForLongEnough;}
+function findInteractiveTime(searchBegin,searchEnd,domContentLoadedEnd,longTasksInWindow,networkRequests){const longTaskEndpoints=getEndpoints_(longTasksInWindow,ENDPOINT_TYPES.LONG_TASK_START,ENDPOINT_TYPES.LONG_TASK_END);const networkRequestEndpoints=getEndpoints_(networkRequests,ENDPOINT_TYPES.REQUEST_START,ENDPOINT_TYPES.REQUEST_END);const endpoints=longTaskEndpoints.concat(networkRequestEndpoints);endpoints.sort((a,b)=>a.time-b.time);let networkQuietWindowStart=searchBegin;let mainThreadQuietWindowStart=searchBegin;let interactiveCandidate=undefined;let activeRequests=0;for(const endpoint of endpoints){if(reachedTTIQuiscence_(endpoint.time,networkQuietWindowStart,mainThreadQuietWindowStart)){interactiveCandidate=mainThreadQuietWindowStart;break;}
+switch(endpoint.type){case ENDPOINT_TYPES.LONG_TASK_START:mainThreadQuietWindowStart=undefined;break;case ENDPOINT_TYPES.LONG_TASK_END:mainThreadQuietWindowStart=endpoint.time;break;case ENDPOINT_TYPES.REQUEST_START:activeRequests++;if(activeRequests>ACTIVE_REQUEST_TOLERANCE){networkQuietWindowStart=undefined;}
+break;case ENDPOINT_TYPES.REQUEST_END:activeRequests--;if(activeRequests===ACTIVE_REQUEST_TOLERANCE){networkQuietWindowStart=endpoint.time;}
+break;default:throw new Error('Internal Error: Unhandled endpoint type.');}}
+if(interactiveCandidate===undefined&&reachedTTIQuiscence_(searchEnd,networkQuietWindowStart,mainThreadQuietWindowStart)){interactiveCandidate=mainThreadQuietWindowStart;}
+if(interactiveCandidate===undefined)return undefined;return Math.max(interactiveCandidate,domContentLoadedEnd);}
+function requiredFCIWindowSizeMs(timeSinceSearchBeginMs){const timeCoefficient=1/15*Math.log(2);const timeSinceSearchBeginSeconds=tr.b.convertUnit(timeSinceSearchBeginMs,tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);const windowSizeSeconds=4*Math.exp(-timeCoefficient*timeSinceSearchBeginSeconds)+1;return tr.b.convertUnit(windowSizeSeconds,tr.b.UnitPrefixScale.METRIC.NONE,tr.b.UnitPrefixScale.METRIC.MILLI);}
+class TaskCluster{constructor(tasksInClusterSorted){if(tasksInClusterSorted.length===0){throw new Error('Internal Error: TaskCluster must have non zero tasks');}
+for(let i=0;i<tasksInClusterSorted.length-1;i++){const durationBetweenTasks=tasksInClusterSorted[i+1].start-
+tasksInClusterSorted[i].end;if(durationBetweenTasks>=FCI_MIN_CLUSTER_SEPARATION_MS){throw new Error('Internal Error: Tasks in a TaskCluster cannot be '+'more than '+FCI_MIN_CLUSTER_SEPARATION_MS+' miliseconds apart');}
+if(durationBetweenTasks<-1e7){throw new Error('Internal Error: List of tasks used to construct '+'TaskCluster must be sorted.');}}
+this._clusterTasks=tasksInClusterSorted;}
+get start(){return this._clusterTasks[0].start;}
+get end(){return this._clusterTasks[this._clusterTasks.length-1].end;}
+isHeavy(){return this.end-this.start>TASK_CLUSTER_HEAVINESS_THRESHOLD_MS;}}
+function findFCITaskClusters(sortedLongTasks){const clusters=[];if(sortedLongTasks.length===0)return clusters;const firstTask=sortedLongTasks[0];const restOfTasks=sortedLongTasks.slice(1);let currentClusterTasks=[firstTask];for(const currTask of restOfTasks){const prevTask=currentClusterTasks[currentClusterTasks.length-1];if(currTask.start-prevTask.end<FCI_MIN_CLUSTER_SEPARATION_MS){currentClusterTasks.push(currTask);}else{clusters.push(new TaskCluster(currentClusterTasks));currentClusterTasks=[currTask];}}
+clusters.push(new TaskCluster(currentClusterTasks));return clusters;}
+function reachedFCIQuiescence_(timestamp,mainThreadQuietWindowStart,searchBegin){const quietWindowSize=timestamp-mainThreadQuietWindowStart;const timeSinceSearchBegin=mainThreadQuietWindowStart-searchBegin;const requiredWindowSize=requiredFCIWindowSizeMs(timeSinceSearchBegin);return quietWindowSize>requiredWindowSize;}
+function findFirstCpuIdleTime(searchBegin,searchEnd,domContentLoadedEnd,longTasksInWindow){const sortedLongTasks=longTasksInWindow.sort((a,b)=>a.start-b.start);const taskClusters=findFCITaskClusters(sortedLongTasks);const heavyTaskClusters=taskClusters.filter(cluster=>cluster.isHeavy());let quietWindowBegin=searchBegin;let fiCandidate=undefined;for(const cluster of heavyTaskClusters){if(reachedFCIQuiescence_(cluster.start,quietWindowBegin,searchBegin)){fiCandidate=quietWindowBegin;break;}
+quietWindowBegin=cluster.end;}
+if(fiCandidate===undefined){if(reachedFCIQuiescence_(searchEnd,quietWindowBegin,searchBegin)){fiCandidate=quietWindowBegin;}else{return undefined;}}
+return Math.max(fiCandidate,domContentLoadedEnd);}
+return{findInteractiveTime,findFirstCpuIdleTime,requiredFCIWindowSizeMs,findFCITaskClusters,};});'use strict';tr.exportTo('tr.model.um',function(){const LOAD_SUBTYPE_NAMES={SUCCESSFUL:'Successful',FAILED:'Failed',};const DOES_LOAD_SUBTYPE_NAME_EXIST={};for(const key in LOAD_SUBTYPE_NAMES){DOES_LOAD_SUBTYPE_NAME_EXIST[LOAD_SUBTYPE_NAMES[key]]=true;}
+function LoadExpectation(parentModel,initiatorTitle,start,duration,renderer,navigationStart,fmpEvent,dclEndEvent,cpuIdleTime,timeToInteractive,url,frameId){if(!DOES_LOAD_SUBTYPE_NAME_EXIST[initiatorTitle]){throw new Error(initiatorTitle+' is not in LOAD_SUBTYPE_NAMES');}
+tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);this.renderProcess=renderer;this.renderMainThread=undefined;this.routingId=undefined;this.parentRoutingId=undefined;this.loadFinishedEvent=undefined;this.navigationStart=navigationStart;this.fmpEvent=fmpEvent;this.domContentLoadedEndEvent=dclEndEvent;this.firstCpuIdleTime=cpuIdleTime;this.timeToInteractive=timeToInteractive;this.url=url;this.frameId=frameId;}
+LoadExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:LoadExpectation};tr.model.um.UserExpectation.subTypes.register(LoadExpectation,{stageTitle:'Load',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_load')});return{LOAD_SUBTYPE_NAMES,LoadExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const LONG_TASK_THRESHOLD_MS=50;const IGNORE_URLS=['','about:blank',];function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
+return snapshot;}
+function findFirstMeaningfulPaintCandidates(rendererHelper){const candidatesForFrameId={};for(const ev of rendererHelper.process.getDescendantEvents()){if(!tr.e.chrome.EventFinderUtils.hasCategoryAndName(ev,'loading','firstMeaningfulPaintCandidate')){continue;}
+if(rendererHelper.isTelemetryInternalEvent(ev))continue;const frameIdRef=ev.args.frame;if(frameIdRef===undefined)continue;let list=candidatesForFrameId[frameIdRef];if(list===undefined){candidatesForFrameId[frameIdRef]=list=[];}
+list.push(ev);}
+return candidatesForFrameId;}
+function computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd){if(domContentLoadedEndEvent===undefined||fmpEvent===undefined){return{interactiveTime:undefined,firstCpuIdleTime:undefined};}
+const firstMeaningfulPaintTime=fmpEvent.start;const mainThreadTasks=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const longTasks=mainThreadTasks.filter(task=>task.duration>=LONG_TASK_THRESHOLD_MS);const longTasksInWindow=longTasks.filter(task=>task.range.intersectsExplicitRangeInclusive(firstMeaningfulPaintTime,searchWindowEnd));const resourceLoadEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd));const firstCpuIdleTime=tr.e.chrome.findFirstCpuIdleTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow);const interactiveTime=resourceLoadEvents.length>0?tr.e.chrome.findInteractiveTime(firstMeaningfulPaintTime,searchWindowEnd,domContentLoadedEndEvent.start,longTasksInWindow,resourceLoadEvents):undefined;return{interactiveTime,firstCpuIdleTime};}
+function constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpEvent,searchWindowEnd,url,frameId){const dclTimesForFrame=frameToDomContentLoadedEndEvents.get(frameId)||[];const dclSearchRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,searchWindowEnd);const dclTimesInWindow=dclSearchRange.filterArray(dclTimesForFrame,event=>event.start);let domContentLoadedEndEvent=undefined;if(dclTimesInWindow.length!==0){domContentLoadedEndEvent=dclTimesInWindow[dclTimesInWindow.length-1];}
+const{interactiveTime,firstCpuIdleTime}=computeInteractivityMetricSample_(rendererHelper,navigationStart,fmpEvent,domContentLoadedEndEvent,searchWindowEnd);const duration=(interactiveTime===undefined)?searchWindowEnd-navigationStart.start:interactiveTime-navigationStart.start;return new tr.model.um.LoadExpectation(rendererHelper.modelHelper.model,tr.model.um.LOAD_SUBTYPE_NAMES.SUCCESSFUL,navigationStart.start,duration,rendererHelper.process,navigationStart,fmpEvent,domContentLoadedEndEvent,firstCpuIdleTime,interactiveTime,url,frameId);}
+function collectLoadExpectationsForRenderer(rendererHelper){const samples=[];const frameToNavStartEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const frameToDomContentLoadedEndEvents=tr.e.chrome.EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'domContentLoadedEventEnd','blink.user_timing');function addSamples(frameIdRef,navigationStart,fmpCandidateEvents,searchWindowEnd,url){let fmpMarkerEvent=tr.e.chrome.EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(fmpCandidateEvents,searchWindowEnd);if(fmpMarkerEvent!==undefined&&navigationStart.start>fmpMarkerEvent.start){fmpMarkerEvent=undefined;}
+samples.push(constructLoadingExpectation_(rendererHelper,frameToDomContentLoadedEndEvents,navigationStart,fmpMarkerEvent,searchWindowEnd,url,frameIdRef));}
+const candidatesForFrameId=findFirstMeaningfulPaintCandidates(rendererHelper);for(const[frameIdRef,navStartEvents]of frameToNavStartEvents){const fmpCandidateEvents=candidatesForFrameId[frameIdRef]||[];let prevNavigation={navigationEvent:undefined,url:undefined};for(let index=0;index<navStartEvents.length;index++){const currNavigation=navStartEvents[index];let url;let isLoadingMainFrame=false;if(currNavigation.args.data){url=currNavigation.args.data.documentLoaderURL;isLoadingMainFrame=currNavigation.args.data.isLoadingMainFrame;}else{const snapshot=findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,currNavigation.start);if(snapshot){url=snapshot.args.documentLoaderURL;isLoadingMainFrame=snapshot.args.isLoadingMainFrame;}}
+if(!isLoadingMainFrame)continue;if(url===undefined||IGNORE_URLS.includes(url))continue;if(prevNavigation.navigationEvent!==undefined){addSamples(frameIdRef,prevNavigation.navigationEvent,fmpCandidateEvents,currNavigation.start,prevNavigation.url);}
+prevNavigation={navigationEvent:currNavigation,url};}
+if(prevNavigation.navigationEvent!==undefined){addSamples(frameIdRef,prevNavigation.navigationEvent,fmpCandidateEvents,rendererHelper.modelHelper.chromeBounds.max,prevNavigation.url);}}
+return samples;}
+function findLoadExpectations(modelHelper){const loads=[];const chromeHelper=modelHelper.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;loads.push.apply(loads,collectLoadExpectationsForRenderer(rendererHelper));}
+return loads;}
+return{findLoadExpectations,};});'use strict';tr.exportTo('tr.model.um',function(){function StartupExpectation(parentModel,start,duration){tr.model.um.UserExpectation.call(this,parentModel,'',start,duration);}
+StartupExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:StartupExpectation};tr.model.um.UserExpectation.subTypes.register(StartupExpectation,{stageTitle:'Startup',colorId:tr.b.ColorScheme.getColorIdForReservedName('startup')});return{StartupExpectation,};});'use strict';tr.exportTo('tr.importer',function(){function getAllFrameEvents(modelHelper){const frameEvents=[];frameEvents.push.apply(frameEvents,modelHelper.browserHelper.getFrameEventsInRange(tr.model.helpers.IMPL_FRAMETIME_TYPE,modelHelper.model.bounds));for(const renderer of Object.values(modelHelper.rendererHelpers)){frameEvents.push.apply(frameEvents,renderer.getFrameEventsInRange(tr.model.helpers.IMPL_FRAMETIME_TYPE,modelHelper.model.bounds));}
+return frameEvents.sort(tr.importer.compareEvents);}
+function getStartupEvents(modelHelper){function isStartupSlice(slice){return slice.title==='BrowserMainLoop::CreateThreads';}
+const events=modelHelper.browserHelper.getAllAsyncSlicesMatching(isStartupSlice);const deduper=new tr.model.EventSet();events.forEach(function(event){const sliceGroup=event.parentContainer.sliceGroup;const slice=sliceGroup&&sliceGroup.findFirstSlice();if(slice){deduper.push(slice);}});return deduper.toArray();}
+function findStartupExpectations(modelHelper){const openingEvents=getStartupEvents(modelHelper);const closingEvents=getAllFrameEvents(modelHelper);const startups=[];openingEvents.forEach(function(openingEvent){closingEvents.forEach(function(closingEvent){if(openingEvent.closingEvent)return;if(closingEvent.openingEvent)return;if(closingEvent.start<=openingEvent.start)return;if(openingEvent.parentContainer.parent.pid!==closingEvent.parentContainer.parent.pid){return;}
+openingEvent.closingEvent=closingEvent;closingEvent.openingEvent=openingEvent;const se=new tr.model.um.StartupExpectation(modelHelper.model,openingEvent.start,closingEvent.end-openingEvent.start);se.associatedEvents.push(openingEvent);se.associatedEvents.push(closingEvent);startups.push(se);});});return startups;}
+return{findStartupExpectations,};});'use strict';tr.exportTo('tr.model',function(){function getAssociatedEvents(irs){const allAssociatedEvents=new tr.model.EventSet();irs.forEach(function(ir){ir.associatedEvents.forEach(function(event){if(event instanceof tr.model.FlowEvent)return;allAssociatedEvents.push(event);});});return allAssociatedEvents;}
+function getUnassociatedEvents(model,associatedEvents){const unassociatedEvents=new tr.model.EventSet();for(const proc of model.getAllProcesses()){for(const thread of Object.values(proc.threads)){for(const event of thread.sliceGroup.getDescendantEvents()){if(!associatedEvents.contains(event)){unassociatedEvents.push(event);}}}}
+return unassociatedEvents;}
+function getTotalCpuDuration(events){let cpuMs=0;events.forEach(function(event){if(event.cpuSelfTime){cpuMs+=event.cpuSelfTime;}});return cpuMs;}
+function getIRCoverageFromModel(model){const associatedEvents=getAssociatedEvents(model.userModel.expectations);if(!associatedEvents.length)return undefined;const unassociatedEvents=getUnassociatedEvents(model,associatedEvents);const associatedCpuMs=getTotalCpuDuration(associatedEvents);const unassociatedCpuMs=getTotalCpuDuration(unassociatedEvents);const totalEventCount=associatedEvents.length+unassociatedEvents.length;const totalCpuMs=associatedCpuMs+unassociatedCpuMs;let coveredEventsCpuTimeRatio=undefined;if(totalCpuMs!==0){coveredEventsCpuTimeRatio=associatedCpuMs/totalCpuMs;}
+return{associatedEventsCount:associatedEvents.length,unassociatedEventsCount:unassociatedEvents.length,associatedEventsCpuTimeMs:associatedCpuMs,unassociatedEventsCpuTimeMs:unassociatedCpuMs,coveredEventsCountRatio:associatedEvents.length/totalEventCount,coveredEventsCpuTimeRatio};}
+return{getIRCoverageFromModel,getAssociatedEvents,getUnassociatedEvents,};});'use strict';tr.exportTo('tr.model.um',function(){function IdleExpectation(parentModel,start,duration){const initiatorTitle='';tr.model.um.UserExpectation.call(this,parentModel,initiatorTitle,start,duration);}
+IdleExpectation.prototype={__proto__:tr.model.um.UserExpectation.prototype,constructor:IdleExpectation};tr.model.um.UserExpectation.subTypes.register(IdleExpectation,{stageTitle:'Idle',colorId:tr.b.ColorScheme.getColorIdForReservedName('rail_idle')});return{IdleExpectation,};});'use strict';tr.exportTo('tr.importer',function(){const INSIGNIFICANT_MS=1;class UserModelBuilder{constructor(model){this.model=model;this.modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);}
+static supportsModelHelper(modelHelper){return modelHelper.browserHelper!==undefined;}
+buildUserModel(){if(!this.modelHelper||!this.modelHelper.browserHelper)return;try{for(const ue of this.findUserExpectations()){this.model.userModel.expectations.push(ue);}
+this.model.userModel.segments.push(...this.findSegments());}catch(error){this.model.importWarning({type:'UserModelBuilder',message:error,showToUser:true});}}
+findSegments(){let timestamps=new Set();for(const expectation of this.model.userModel.expectations){timestamps.add(expectation.start);timestamps.add(expectation.end);}
+timestamps=[...timestamps];timestamps.sort((x,y)=>x-y);const segments=[];for(let i=0;i<timestamps.length-1;++i){const segment=new tr.model.um.Segment(timestamps[i],timestamps[i+1]-timestamps[i]);segments.push(segment);const segmentRange=tr.b.math.Range.fromExplicitRange(segment.start,segment.end);for(const expectation of this.model.userModel.expectations){const expectationRange=tr.b.math.Range.fromExplicitRange(expectation.start,expectation.end);if(segmentRange.intersectsRangeExclusive(expectationRange)){segment.expectations.push(expectation);}}}
+return segments;}
+findUserExpectations(){const expectations=[];expectations.push.apply(expectations,tr.importer.findStartupExpectations(this.modelHelper));expectations.push.apply(expectations,tr.importer.findLoadExpectations(this.modelHelper));expectations.push.apply(expectations,tr.importer.findInputExpectations(this.modelHelper));expectations.push.apply(expectations,this.findIdleExpectations(expectations));this.collectUnassociatedEvents_(expectations);return expectations;}
+collectUnassociatedEvents_(expectations){const vacuumUEs=[];for(const expectation of expectations){if(expectation instanceof tr.model.um.IdleExpectation||expectation instanceof tr.model.um.LoadExpectation||expectation instanceof tr.model.um.StartupExpectation){vacuumUEs.push(expectation);}}
+if(vacuumUEs.length===0)return;const allAssociatedEvents=tr.model.getAssociatedEvents(expectations);const unassociatedEvents=tr.model.getUnassociatedEvents(this.model,allAssociatedEvents);for(const event of unassociatedEvents){if(!(event instanceof tr.model.ThreadSlice))continue;if(!event.isTopLevel)continue;for(let index=0;index<vacuumUEs.length;++index){const expectation=vacuumUEs[index];if((event.start>=expectation.start)&&(event.start<expectation.end)){expectation.associatedEvents.addEventSet(event.entireHierarchy);break;}}}}
+findIdleExpectations(otherUEs){if(this.model.bounds.isEmpty)return;const emptyRanges=tr.b.math.findEmptyRangesBetweenRanges(tr.b.math.convertEventsToRanges(otherUEs),this.model.bounds);const expectations=[];const model=this.model;for(const range of emptyRanges){if(range.max<(range.min+INSIGNIFICANT_MS))continue;expectations.push(new tr.model.um.IdleExpectation(model,range.min,range.max-range.min));}
+return expectations;}}
+function createCustomizeModelLinesFromModel(model){const modelLines=[];modelLines.push('      audits.addEvent(model.browserMain,');modelLines.push('          {title: \'model start\', start: 0, end: 1});');const typeNames={};for(const typeName in tr.e.cc.INPUT_EVENT_TYPE_NAMES){typeNames[tr.e.cc.INPUT_EVENT_TYPE_NAMES[typeName]]=typeName;}
+let modelEvents=new tr.model.EventSet();for(const ue of model.userModel.expectations){modelEvents.addEventSet(ue.sourceEvents);}
+modelEvents=modelEvents.toArray();modelEvents.sort(tr.importer.compareEvents);for(const event of modelEvents){const startAndEnd='start: '+parseInt(event.start)+', '+'end: '+parseInt(event.end)+'});';if(event instanceof tr.e.cc.InputLatencyAsyncSlice){modelLines.push('      audits.addInputEvent(model, INPUT_TYPE.'+
+typeNames[event.typeName]+',');}else if(event.title==='RenderFrameImpl::didCommitProvisionalLoad'){modelLines.push('      audits.addCommitLoadEvent(model,');}else if(event.title==='InputHandlerProxy::HandleGestureFling::started'){modelLines.push('      audits.addFlingAnimationEvent(model,');}else if(event.title===tr.model.helpers.IMPL_RENDERING_STATS){modelLines.push('      audits.addFrameEvent(model,');}else if(event.title===tr.importer.CSS_ANIMATION_TITLE){modelLines.push('      audits.addEvent(model.rendererMain, {');modelLines.push('        title: \'Animation\', '+startAndEnd);return;}else{throw new Error('You must extend createCustomizeModelLinesFromModel()'+'to support this event:\n'+event.title+'\n');}
+modelLines.push('          {'+startAndEnd);}
+modelLines.push('      audits.addEvent(model.browserMain,');modelLines.push('          {'+'title: \'model end\', '+'start: '+(parseInt(model.bounds.max)-1)+', '+'end: '+parseInt(model.bounds.max)+'});');return modelLines;}
+function createExpectedUELinesFromModel(model){const expectedLines=[];const ueCount=model.userModel.expectations.length;for(let index=0;index<ueCount;++index){const expectation=model.userModel.expectations[index];let ueString='      {';ueString+='title: \''+expectation.title+'\', ';ueString+='start: '+parseInt(expectation.start)+', ';ueString+='end: '+parseInt(expectation.end)+', ';ueString+='eventCount: '+expectation.sourceEvents.length;ueString+='}';if(index<(ueCount-1))ueString+=',';expectedLines.push(ueString);}
+return expectedLines;}
+function createUEFinderTestCaseStringFromModel(model){const filename=window.location.hash.substr(1);let testName=filename.substr(filename.lastIndexOf('/')+1);testName=testName.substr(0,testName.indexOf('.'));try{const testLines=[];testLines.push('  /*');testLines.push('    This test was generated from');testLines.push('    '+filename+'');testLines.push('   */');testLines.push('  test(\''+testName+'\', function() {');testLines.push('    const verifier = new UserExpectationVerifier();');testLines.push('    verifier.customizeModelCallback = function(model) {');testLines.push.apply(testLines,createCustomizeModelLinesFromModel(model));testLines.push('    };');testLines.push('    verifier.expectedUEs = [');testLines.push.apply(testLines,createExpectedUELinesFromModel(model));testLines.push('    ];');testLines.push('    verifier.verify();');testLines.push('  });');return testLines.join('\n');}catch(error){return error;}}
+return{UserModelBuilder,createUEFinderTestCaseStringFromModel,};});'use strict';tr.exportTo('tr.ui.b',function(){function decorate(source,constr){let elements;if(typeof source==='string'){elements=Polymer.dom(tr.doc).querySelectorAll(source);}else{elements=[source];}
+for(let i=0,el;el=elements[i];i++){if(!(el instanceof constr)){constr.decorate(el);}}}
+function define(className,opt_parentConstructor,opt_tagNS){if(typeof className==='function'){throw new Error('Passing functions as className is deprecated. Please '+'use (className, opt_parentConstructor) to subclass');}
+className=className.toLowerCase();if(opt_parentConstructor&&!opt_parentConstructor.tagName){throw new Error('opt_parentConstructor was not '+'created by tr.ui.b.define');}
+let tagName=className;let tagNS=undefined;if(opt_parentConstructor){if(opt_tagNS){throw new Error('Must not specify tagNS if parentConstructor is given');}
+let parent=opt_parentConstructor;while(parent&&parent.tagName){tagName=parent.tagName;tagNS=parent.tagNS;parent=parent.parentConstructor;}}else{tagNS=opt_tagNS;}
+function f(){if(opt_parentConstructor&&f.prototype.__proto__!==opt_parentConstructor.prototype){throw new Error(className+' prototye\'s __proto__ field is messed up. '+'It MUST be the prototype of '+opt_parentConstructor.tagName);}
+let el;if(tagNS===undefined){el=tr.doc.createElement(tagName);}else{el=tr.doc.createElementNS(tagNS,tagName);}
+f.decorate.call(this,el,arguments);return el;}
+f.decorate=function(el){el.__proto__=f.prototype;el.decorate.apply(el,arguments[1]);el.constructor=f;};f.className=className;f.tagName=tagName;f.tagNS=tagNS;f.parentConstructor=(opt_parentConstructor?opt_parentConstructor:undefined);f.toString=function(){if(!f.parentConstructor){return f.tagName;}
+return f.parentConstructor.toString()+'::'+f.className;};return f;}
+function elementIsChildOf(el,potentialParent){if(el===potentialParent)return false;let cur=el;while(Polymer.dom(cur).parentNode){if(cur===potentialParent)return true;cur=Polymer.dom(cur).parentNode;}
+return false;}
+return{decorate,define,elementIsChildOf,};});'use strict';tr.exportTo('tr.b.math',function(){function Rect(){this.x=0;this.y=0;this.width=0;this.height=0;}
+Rect.fromXYWH=function(x,y,w,h){const rect=new Rect();rect.x=x;rect.y=y;rect.width=w;rect.height=h;return rect;};Rect.fromArray=function(ary){if(ary.length!==4){throw new Error('ary.length must be 4');}
+const rect=new Rect();rect.x=ary[0];rect.y=ary[1];rect.width=ary[2];rect.height=ary[3];return rect;};Rect.prototype={__proto__:Object.prototype,get left(){return this.x;},get top(){return this.y;},get right(){return this.x+this.width;},get bottom(){return this.y+this.height;},toString(){return'Rect('+this.x+', '+this.y+', '+
+this.width+', '+this.height+')';},toArray(){return[this.x,this.y,this.width,this.height];},clone(){const rect=new Rect();rect.x=this.x;rect.y=this.y;rect.width=this.width;rect.height=this.height;return rect;},enlarge(pad){const rect=new Rect();this.enlargeFast(rect,pad);return rect;},enlargeFast(out,pad){out.x=this.x-pad;out.y=this.y-pad;out.width=this.width+2*pad;out.height=this.height+2*pad;return out;},size(){return{width:this.width,height:this.height};},scale(s){const rect=new Rect();this.scaleFast(rect,s);return rect;},scaleSize(s){return Rect.fromXYWH(this.x,this.y,this.width*s,this.height*s);},scaleFast(out,s){out.x=this.x*s;out.y=this.y*s;out.width=this.width*s;out.height=this.height*s;return out;},translate(v){const rect=new Rect();this.translateFast(rect,v);return rect;},translateFast(out,v){out.x=this.x+v[0];out.y=this.x+v[1];out.width=this.width;out.height=this.height;return out;},asUVRectInside(containingRect){const rect=new Rect();rect.x=(this.x-containingRect.x)/containingRect.width;rect.y=(this.y-containingRect.y)/containingRect.height;rect.width=this.width/containingRect.width;rect.height=this.height/containingRect.height;return rect;},intersects(that){let ok=true;ok&=this.x<that.right;ok&=this.right>that.x;ok&=this.y<that.bottom;ok&=this.bottom>that.y;return ok;},equalTo(rect){return rect&&(this.x===rect.x)&&(this.y===rect.y)&&(this.width===rect.width)&&(this.height===rect.height);}};return{Rect,};});'use strict';tr.exportTo('tr.ui.b',function(){function instantiateTemplate(selector,doc){doc=doc||document;const el=Polymer.dom(doc).querySelector(selector);if(!el){throw new Error('Element not found: '+selector);}
+return doc.importNode(el.content,true);}
+function windowRectForElement(element){const position=[element.offsetLeft,element.offsetTop];const size=[element.offsetWidth,element.offsetHeight];let node=element.offsetParent;while(node){position[0]+=node.offsetLeft;position[1]+=node.offsetTop;node=node.offsetParent;}
+return tr.b.math.Rect.fromXYWH(position[0],position[1],size[0],size[1]);}
+function scrollIntoViewIfNeeded(el){const pr=el.parentElement.getBoundingClientRect();const cr=el.getBoundingClientRect();if(cr.top<pr.top){el.scrollIntoView(true);}else if(cr.bottom>pr.bottom){el.scrollIntoView(false);}}
+function extractUrlString(url){let extracted=url.replace(/url\((.*)\)/,'$1');extracted=extracted.replace(/\"(.*)\"/,'$1');return extracted;}
+function toThreeDigitLocaleString(value){return value.toLocaleString(undefined,{minimumFractionDigits:3,maximumFractionDigits:3});}
+function isUnknownElementName(name){return document.createElement(name)instanceof HTMLUnknownElement;}
+return{isUnknownElementName,toThreeDigitLocaleString,instantiateTemplate,windowRectForElement,scrollIntoViewIfNeeded,extractUrlString,};});'use strict';tr.exportTo('tr.ui.b',function(){if(tr.isHeadless)return{};const THIS_DOC=document._currentScript.ownerDocument;const Overlay=tr.ui.b.define('overlay');Overlay.prototype={__proto__:HTMLDivElement.prototype,decorate(){Polymer.dom(this).classList.add('overlay');this.parentEl_=this.ownerDocument.body;this.visible_=false;this.userCanClose_=true;this.onKeyDown_=this.onKeyDown_.bind(this);this.onClick_=this.onClick_.bind(this);this.onFocusIn_=this.onFocusIn_.bind(this);this.onDocumentClick_=this.onDocumentClick_.bind(this);this.onClose_=this.onClose_.bind(this);this.addEventListener('visible-change',tr.ui.b.Overlay.prototype.onVisibleChange_.bind(this),true);const createShadowRoot=this.createShadowRoot||this.webkitCreateShadowRoot;this.shadow_=createShadowRoot.call(this);Polymer.dom(this.shadow_).appendChild(tr.ui.b.instantiateTemplate('#overlay-template',THIS_DOC));this.closeBtn_=Polymer.dom(this.shadow_).querySelector('close-button');this.closeBtn_.addEventListener('click',this.onClose_);Polymer.dom(this.shadow_).querySelector('overlay-frame').addEventListener('click',this.onClick_);this.observer_=new MutationObserver(this.didButtonBarMutate_.bind(this));this.observer_.observe(Polymer.dom(this.shadow_).querySelector('button-bar'),{childList:true});Object.defineProperty(this,'title',{get(){return Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent;},set(title){Polymer.dom(Polymer.dom(this.shadow_).querySelector('title')).textContent=title;}});},set userCanClose(userCanClose){this.userCanClose_=userCanClose;this.closeBtn_.style.display=userCanClose?'block':'none';},get buttons(){return Polymer.dom(this.shadow_).querySelector('button-bar');},get visible(){return this.visible_;},set visible(newValue){if(this.visible_===newValue)return;this.visible_=newValue;const e=new tr.b.Event('visible-change');this.dispatchEvent(e);},onVisibleChange_(){this.visible_?this.show_():this.hide_();},show_(){Polymer.dom(this.parentEl_).appendChild(this);if(this.userCanClose_){this.addEventListener('keydown',this.onKeyDown_.bind(this));this.addEventListener('click',this.onDocumentClick_.bind(this));this.closeBtn_.addEventListener('click',this.onClose_);}
+this.parentEl_.addEventListener('focusin',this.onFocusIn_);this.tabIndex=0;const elList=Polymer.dom(this).querySelectorAll('button, input, list, select, a');if(elList.length>0){if(elList[0]===this.closeBtn_){if(elList.length>1)return elList[1].focus();}else{return elList[0].focus();}}
+this.focus();},hide_(){Polymer.dom(this.parentEl_).removeChild(this);this.parentEl_.removeEventListener('focusin',this.onFocusIn_);if(this.closeBtn_){this.closeBtn_.removeEventListener('click',this.onClose_);}
+document.removeEventListener('keydown',this.onKeyDown_);document.removeEventListener('click',this.onDocumentClick_);},onClose_(e){this.visible=false;if((e.type!=='keydown')||(e.type==='keydown'&&e.keyCode===27)){e.stopPropagation();}
+e.preventDefault();tr.b.dispatchSimpleEvent(this,'closeclick');},onFocusIn_(e){let node=e.target;while(node){if(node===this){return;}
+node=node.parentNode;}
+tr.b.timeout(0).then(()=>this.focus());e.preventDefault();e.stopPropagation();},didButtonBarMutate_(e){const hasButtons=this.buttons.children.length>0;if(hasButtons){Polymer.dom(this.shadow_).querySelector('button-bar').style.display=undefined;}else{Polymer.dom(this.shadow_).querySelector('button-bar').style.display='none';}},onKeyDown_(e){if(e.keyCode===9&&e.shiftKey&&e.target===this){e.preventDefault();return;}
+if(e.keyCode!==27)return;this.onClose_(e);},onClick_(e){e.stopPropagation();},onDocumentClick_(e){if(!this.userCanClose_)return;this.onClose_(e);}};Overlay.showError=function(msg,opt_err){const o=new Overlay();o.title='Error';Polymer.dom(o).textContent=msg;if(opt_err){const e=tr.b.normalizeException(opt_err);const stackDiv=document.createElement('pre');Polymer.dom(stackDiv).textContent=e.stack;stackDiv.style.paddingLeft='8px';stackDiv.style.margin=0;Polymer.dom(o).appendChild(stackDiv);}
+const b=document.createElement('button');Polymer.dom(b).textContent='OK';b.addEventListener('click',function(){o.visible=false;});Polymer.dom(o.buttons).appendChild(b);o.visible=true;return o;};return{Overlay,};});'use strict';tr.exportTo('tr.importer',function(){const Timing=tr.b.Timing;function ImportOptions(){this.shiftWorldToZero=true;this.pruneEmptyContainers=true;this.showImportWarnings=true;this.trackDetailedModelStats=false;this.customizeModelCallback=undefined;const auditorTypes=tr.c.Auditor.getAllRegisteredTypeInfos();this.auditorConstructors=auditorTypes.map(function(typeInfo){return typeInfo.constructor;});}
+function Import(model,opt_options){if(model===undefined){throw new Error('Must provide model to import into.');}
+this.importing_=false;this.importOptions_=opt_options||new ImportOptions();this.model_=model;this.model_.importOptions=this.importOptions_;}
+Import.prototype={__proto__:Object.prototype,importTraces(traces){const progressMeter={update(msg){}};tr.b.Task.RunSynchronously(this.createImportTracesTask(progressMeter,traces));},importTracesWithProgressDialog(traces){if(tr.isHeadless){throw new Error('Cannot use this method in headless mode.');}
+const overlay=tr.ui.b.Overlay();overlay.title='Importing...';overlay.userCanClose=false;overlay.msgEl=document.createElement('div');Polymer.dom(overlay).appendChild(overlay.msgEl);overlay.msgEl.style.margin='20px';overlay.update=function(msg){Polymer.dom(this.msgEl).textContent=msg;};overlay.visible=true;const promise=tr.b.Task.RunWhenIdle(this.createImportTracesTask(overlay,traces));promise.then(function(){overlay.visible=false;},function(err){overlay.visible=false;});return promise;},createImportTracesTask(progressMeter,traces){const importStartTimeMs=tr.b.Timing.getCurrentTimeMs();if(this.importing_){throw new Error('Already importing.');}
+this.importing_=true;const importTask=new tr.b.Task(function prepareImport(){progressMeter.update('I will now import your traces for you...');},this);let lastTask=importTask;const importers=[];function addImportStage(title,callback){lastTask=lastTask.after(()=>progressMeter.update(title));lastTask.updatesUi=true;lastTask=lastTask.after(callback);}
+function addStageForEachImporter(title,callback){lastTask=lastTask.after((task)=>{importers.forEach((importer,index)=>{const uiSubTask=task.subTask(()=>{progressMeter.update(`${title} ${index + 1} of ${importers.length}`);});uiSubTask.updatesUi=true;task.subTask(()=>callback(importer));});});}
+addImportStage('Creating importers...',()=>{traces=traces.slice(0);progressMeter.update('Creating importers...');for(let i=0;i<traces.length;++i){importers.push(this.createImporter_(traces[i]));}
+for(let i=0;i<importers.length;i++){const subtraces=importers[i].extractSubtraces();for(let j=0;j<subtraces.length;j++){try{traces.push(subtraces[j]);importers.push(this.createImporter_(subtraces[j]));}catch(error){this.model_.importWarning({type:error.name,message:error.message,showToUser:true,});continue;}}}
+if(traces.length&&!this.hasEventDataDecoder_(importers)){throw new Error('Could not find an importer for the provided eventData.');}
+importers.sort(function(x,y){return x.importPriority-y.importPriority;});});addStageForEachImporter('Importing clock sync markers',importer=>importer.importClockSyncMarkers());addStageForEachImporter('Importing',importer=>importer.importEvents());if(this.importOptions_.customizeModelCallback){addImportStage('Customizing',()=>{this.importOptions_.customizeModelCallback(this.model_);});}
+addStageForEachImporter('Importing sample data',importer=>importer.importSampleData());addImportStage('Autoclosing open slices...',()=>{this.model_.autoCloseOpenSlices();this.model_.createSubSlices();});addStageForEachImporter('Finalizing import',importer=>importer.finalizeImport());addImportStage('Initializing objects (step 1/2)...',()=>this.model_.preInitializeObjects());if(this.importOptions_.pruneEmptyContainers){addImportStage('Pruning empty containers...',()=>this.model_.pruneEmptyContainers());}
+addImportStage('Merging kernel with userland...',()=>this.model_.mergeKernelWithUserland());let auditors=[];addImportStage('Adding arbitrary data to model...',()=>{auditors=this.importOptions_.auditorConstructors.map(auditorConstructor=>new auditorConstructor(this.model_));auditors.forEach((auditor)=>{auditor.runAnnotate();auditor.installUserFriendlyCategoryDriverIfNeeded();});});addImportStage('Computing final world bounds...',()=>{this.model_.computeWorldBounds(this.importOptions_.shiftWorldToZero);});addImportStage('Building flow event map...',()=>this.model_.buildFlowEventIntervalTree());addImportStage('Joining object refs...',()=>this.model_.joinRefs());addImportStage('Cleaning up undeleted objects...',()=>this.model_.cleanupUndeletedObjects());addImportStage('Sorting memory dumps...',()=>this.model_.sortMemoryDumps());addImportStage('Finalizing memory dump graphs...',()=>this.model_.finalizeMemoryGraphs());addImportStage('Initializing objects (step 2/2)...',()=>this.model_.initializeObjects());addImportStage('Building event indices...',()=>this.model_.buildEventIndices());addImportStage('Building UserModel...',()=>{const userModelBuilder=new tr.importer.UserModelBuilder(this.model_);userModelBuilder.buildUserModel();});addImportStage('Sorting user expectations...',()=>this.model_.userModel.sortExpectations());addImportStage('Running auditors...',()=>{auditors.forEach(auditor=>auditor.runAudit());});addImportStage('Updating alerts...',()=>this.model_.sortAlerts());addImportStage('Update bounds...',()=>this.model_.updateBounds());addImportStage('Looking for warnings...',()=>{if(!this.model_.isTimeHighResolution){this.model_.importWarning({type:'low_resolution_timer',message:'Trace time is low resolution, trace may be unusable.',showToUser:true});}});lastTask.after(()=>{this.importing_=false;this.model_.stats.traceImportDurationMs=tr.b.Timing.getCurrentTimeMs()-importStartTimeMs;});return importTask;},createImporter_(eventData){const importerConstructor=tr.importer.Importer.findImporterFor(eventData);if(!importerConstructor){throw new Error('Couldn\'t create an importer for the provided '+'eventData.');}
+return new importerConstructor(this.model_,eventData);},hasEventDataDecoder_(importers){for(let i=0;i<importers.length;++i){if(!importers[i].isTraceDataContainer())return true;}
+return false;}};return{ImportOptions,Import,};});'use strict';tr.exportTo('tr.e.v8',function(){const ThreadSlice=tr.model.ThreadSlice;function V8GCStatsThreadSlice(){ThreadSlice.apply(this,arguments);this.liveObjects_=JSON.parse(this.args.live);delete this.args.live;this.deadObjects_=JSON.parse(this.args.dead);delete this.args.dead;}
+V8GCStatsThreadSlice.prototype={__proto__:ThreadSlice.prototype,get liveObjects(){return this.liveObjects_;},get deadObjects(){return this.deadObjects_;}};ThreadSlice.subTypes.register(V8GCStatsThreadSlice,{categoryParts:['disabled-by-default-v8.gc_stats'],name:'v8 gc stats slice',pluralName:'v8 gc stats slices'});return{V8GCStatsThreadSlice,};});'use strict';tr.exportTo('tr.e.v8',function(){const ThreadSlice=tr.model.ThreadSlice;function V8ICStatsThreadSlice(){ThreadSlice.apply(this,arguments);this.icStats_=undefined;if(this.args['ic-stats']){this.icStats_=this.args['ic-stats'].data;delete this.args['ic-stats'];}}
+V8ICStatsThreadSlice.prototype={__proto__:ThreadSlice.prototype,get icStats(){return this.icStats_;}};ThreadSlice.subTypes.register(V8ICStatsThreadSlice,{categoryParts:['disabled-by-default-v8.ic_stats'],name:'v8 ic stats slice',pluralName:'v8 ic stats slices'});return{V8ICStatsThreadSlice,};});'use strict';tr.exportTo('tr.e.v8',function(){const ThreadSlice=tr.model.ThreadSlice;function V8ThreadSlice(){ThreadSlice.apply(this,arguments);this.runtimeCallStats_=undefined;}
+V8ThreadSlice.prototype={__proto__:ThreadSlice.prototype,get runtimeCallStats(){if('runtime-call-stats'in this.args){this.runtimeCallStats_=this.args['runtime-call-stats'];delete this.args['runtime-call-stats'];}
+return this.runtimeCallStats_;}};ThreadSlice.subTypes.register(V8ThreadSlice,{categoryParts:['v8','disabled-by-default-v8.runtime_stats'],name:'v8 slice',pluralName:'v8 slices'});return{V8ThreadSlice,};});'use strict';tr.exportTo('tr.e.cc',function(){function PictureAsImageData(picture,errorOrImageData){this.picture_=picture;if(errorOrImageData instanceof ImageData){this.error_=undefined;this.imageData_=errorOrImageData;}else{this.error_=errorOrImageData;this.imageData_=undefined;}}
+PictureAsImageData.Pending=function(picture){return new PictureAsImageData(picture,undefined);};PictureAsImageData.prototype={get picture(){return this.picture_;},get error(){return this.error_;},get imageData(){return this.imageData_;},isPending(){return this.error_===undefined&&this.imageData_===undefined;},asCanvas(){if(!this.imageData_)return;const canvas=document.createElement('canvas');const ctx=canvas.getContext('2d');canvas.width=this.imageData_.width;canvas.height=this.imageData_.height;ctx.putImageData(this.imageData_,0,0);return canvas;}};return{PictureAsImageData,};});'use strict';tr.exportTo('tr.e.cc',function(){const convertedNameCache={};function convertNameToJSConvention(name){if(name in convertedNameCache){return convertedNameCache[name];}
+if(name[0]==='_'||name[name.length-1]==='_'){convertedNameCache[name]=name;return name;}
+const words=name.split('_');if(words.length===1){convertedNameCache[name]=words[0];return words[0];}
+for(let i=1;i<words.length;i++){words[i]=words[i][0].toUpperCase()+words[i].substring(1);}
+convertedNameCache[name]=words.join('');return convertedNameCache[name];}
+function moveRequiredFieldsFromArgsToToplevel(object,fields){for(let i=0;i<fields.length;i++){const key=fields[i];if(object.args[key]===undefined){throw Error('Expected field '+key+' not found in args');}
+if(object[key]!==undefined){throw Error('Field '+key+' already in object');}
+object[key]=object.args[key];delete object.args[key];}}
+function moveOptionalFieldsFromArgsToToplevel(object,fields){for(let i=0;i<fields.length;i++){const key=fields[i];if(object.args[key]===undefined)continue;if(object[key]!==undefined){throw Error('Field '+key+' already in object');}
+object[key]=object.args[key];delete object.args[key];}}
+function preInitializeObject(object){preInitializeObjectInner(object.args,false);}
+function preInitializeObjectInner(object,hasRecursed){if(!(object instanceof Object))return;if(object instanceof Array){for(let i=0;i<object.length;i++){preInitializeObjectInner(object[i],true);}
+return;}
+if(hasRecursed&&(object instanceof tr.model.ObjectSnapshot||object instanceof tr.model.ObjectInstance)){return;}
+for(let key in object){const newKey=convertNameToJSConvention(key);if(newKey!==key){const value=object[key];delete object[key];object[newKey]=value;key=newKey;}
+if(/Quad$/.test(key)&&!(object[key]instanceof tr.b.math.Quad)){let q;try{q=tr.b.math.Quad.from8Array(object[key]);}catch(e){}
+object[key]=q;continue;}
+if(/Rect$/.test(key)&&!(object[key]instanceof tr.b.math.Rect)){let r;try{r=tr.b.math.Rect.fromArray(object[key]);}catch(e){}
+object[key]=r;}
+preInitializeObjectInner(object[key],true);}}
+return{preInitializeObject,convertNameToJSConvention,moveRequiredFieldsFromArgsToToplevel,moveOptionalFieldsFromArgsToToplevel,};});'use strict';tr.exportTo('tr.e.cc',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;const PictureCount=0;const OPS_TIMING_ITERATIONS=3;function Picture(skp64,layerRect){this.skp64_=skp64;this.layerRect_=layerRect;this.guid_=tr.b.GUID.allocateSimple();}
+Picture.prototype={get canSave(){return true;},get layerRect(){return this.layerRect_;},get guid(){return this.guid_;},getBase64SkpData(){return this.skp64_;},getOps(){if(!PictureSnapshot.CanGetOps()){console.error(PictureSnapshot.HowToEnablePictureDebugging());return undefined;}
+const ops=window.chrome.skiaBenchmarking.getOps({skp64:this.skp64_,params:{layer_rect:this.layerRect_.toArray()}});if(!ops){console.error('Failed to get picture ops.');}
+return ops;},getOpTimings(){if(!PictureSnapshot.CanGetOpTimings()){console.error(PictureSnapshot.HowToEnablePictureDebugging());return undefined;}
+const opTimings=window.chrome.skiaBenchmarking.getOpTimings({skp64:this.skp64_,params:{layer_rect:this.layerRect_.toArray()}});if(!opTimings){console.error('Failed to get picture op timings.');}
+return opTimings;},tagOpsWithTimings(ops){const opTimings=[];for(let iteration=0;iteration<OPS_TIMING_ITERATIONS;iteration++){opTimings[iteration]=this.getOpTimings();if(!opTimings[iteration]||!opTimings[iteration].cmd_times){return ops;}
+if(opTimings[iteration].cmd_times.length!==ops.length){return ops;}}
+for(let opIndex=0;opIndex<ops.length;opIndex++){let min=Number.MAX_VALUE;for(let i=0;i<OPS_TIMING_ITERATIONS;i++){min=Math.min(min,opTimings[i].cmd_times[opIndex]);}
+ops[opIndex].cmd_time=min;}
+return ops;},rasterize(params,rasterCompleteCallback){if(!PictureSnapshot.CanRasterize()||!PictureSnapshot.CanGetOps()){rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,tr.e.cc.PictureSnapshot.HowToEnablePictureDebugging()));return;}
+if(!this.layerRect_.width||!this.layerRect_.height){rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,null));return;}
+const raster=window.chrome.skiaBenchmarking.rasterize({skp64:this.skp64_,params:{layer_rect:this.layerRect_.toArray()}},{stop:params.stopIndex===undefined?-1:params.stopIndex,overdraw:!!params.showOverdraw,params:{}});if(raster){const canvas=document.createElement('canvas');const ctx=canvas.getContext('2d');canvas.width=raster.width;canvas.height=raster.height;const imageData=ctx.createImageData(raster.width,raster.height);imageData.data.set(new Uint8ClampedArray(raster.data));rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,imageData));}else{const error='Failed to rasterize picture. '+'Your recording may be from an old Chrome version. '+'The SkPicture format is not backward compatible.';rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,error));}}};function LayeredPicture(pictures){this.guid_=tr.b.GUID.allocateSimple();this.pictures_=pictures;this.layerRect_=undefined;}
+LayeredPicture.prototype={__proto__:Picture.prototype,get canSave(){return false;},get typeName(){return'cc::LayeredPicture';},get layerRect(){if(this.layerRect_!==undefined){return this.layerRect_;}
+this.layerRect_={x:0,y:0,width:0,height:0};for(let i=0;i<this.pictures_.length;++i){const rect=this.pictures_[i].layerRect;this.layerRect_.x=Math.min(this.layerRect_.x,rect.x);this.layerRect_.y=Math.min(this.layerRect_.y,rect.y);this.layerRect_.width=Math.max(this.layerRect_.width,rect.x+rect.width);this.layerRect_.height=Math.max(this.layerRect_.height,rect.y+rect.height);}
+return this.layerRect_;},get guid(){return this.guid_;},getBase64SkpData(){throw new Error('Not available with a LayeredPicture.');},getOps(){let ops=[];for(let i=0;i<this.pictures_.length;++i){ops=ops.concat(this.pictures_[i].getOps());}
+return ops;},getOpTimings(){const opTimings=this.pictures_[0].getOpTimings();for(let i=1;i<this.pictures_.length;++i){const timings=this.pictures_[i].getOpTimings();opTimings.cmd_times=opTimings.cmd_times.concat(timings.cmd_times);opTimings.total_time+=timings.total_time;}
+return opTimings;},tagOpsWithTimings(ops){const opTimings=[];for(let iteration=0;iteration<OPS_TIMING_ITERATIONS;iteration++){opTimings[iteration]=this.getOpTimings();if(!opTimings[iteration]||!opTimings[iteration].cmd_times){return ops;}}
+for(let opIndex=0;opIndex<ops.length;opIndex++){let min=Number.MAX_VALUE;for(let i=0;i<OPS_TIMING_ITERATIONS;i++){min=Math.min(min,opTimings[i].cmd_times[opIndex]);}
+ops[opIndex].cmd_time=min;}
+return ops;},rasterize(params,rasterCompleteCallback){this.picturesAsImageData_=[];const rasterCallback=function(pictureAsImageData){this.picturesAsImageData_.push(pictureAsImageData);if(this.picturesAsImageData_.length!==this.pictures_.length){return;}
+const canvas=document.createElement('canvas');const ctx=canvas.getContext('2d');canvas.width=this.layerRect.width;canvas.height=this.layerRect.height;for(let i=0;i<this.picturesAsImageData_.length;++i){ctx.putImageData(this.picturesAsImageData_[i].imageData,this.pictures_[i].layerRect.x,this.pictures_[i].layerRect.y);}
+this.picturesAsImageData_=[];rasterCompleteCallback(new tr.e.cc.PictureAsImageData(this,ctx.getImageData(this.layerRect.x,this.layerRect.y,this.layerRect.width,this.layerRect.height)));}.bind(this);for(let i=0;i<this.pictures_.length;++i){this.pictures_[i].rasterize(params,rasterCallback);}}};function PictureSnapshot(){ObjectSnapshot.apply(this,arguments);}
+PictureSnapshot.HasSkiaBenchmarking=function(){return tr.isExported('chrome.skiaBenchmarking');};PictureSnapshot.CanRasterize=function(){if(!PictureSnapshot.HasSkiaBenchmarking()){return false;}
+if(!window.chrome.skiaBenchmarking.rasterize){return false;}
+return true;};PictureSnapshot.CanGetOps=function(){if(!PictureSnapshot.HasSkiaBenchmarking()){return false;}
+if(!window.chrome.skiaBenchmarking.getOps){return false;}
+return true;};PictureSnapshot.CanGetOpTimings=function(){if(!PictureSnapshot.HasSkiaBenchmarking()){return false;}
+if(!window.chrome.skiaBenchmarking.getOpTimings){return false;}
+return true;};PictureSnapshot.CanGetInfo=function(){if(!PictureSnapshot.HasSkiaBenchmarking()){return false;}
+if(!window.chrome.skiaBenchmarking.getInfo){return false;}
+return true;};PictureSnapshot.HowToEnablePictureDebugging=function(){if(tr.isHeadless){return'Pictures only work in chrome';}
+const usualReason=['For pictures to show up, the Chrome browser displaying the trace ','needs to be running with --enable-skia-benchmarking. Please restart ','chrome with this flag and try loading the trace again.'].join('');if(!PictureSnapshot.HasSkiaBenchmarking()){return usualReason;}
+if(!PictureSnapshot.CanRasterize()){return'Your chrome is old: chrome.skipBenchmarking.rasterize not found';}
+if(!PictureSnapshot.CanGetOps()){return'Your chrome is old: chrome.skiaBenchmarking.getOps not found';}
+if(!PictureSnapshot.CanGetOpTimings()){return'Your chrome is old: '+'chrome.skiaBenchmarking.getOpTimings not found';}
+if(!PictureSnapshot.CanGetInfo()){return'Your chrome is old: chrome.skiaBenchmarking.getInfo not found';}
+return undefined;};PictureSnapshot.CanDebugPicture=function(){return PictureSnapshot.HowToEnablePictureDebugging()===undefined;};PictureSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);this.rasterResult_=undefined;},initialize(){if(this.args.alias){this.args=this.args.alias.args;}
+if(!this.args.params.layerRect){throw new Error('Missing layer rect');}
+this.layerRect_=this.args.params.layerRect;this.picture_=new Picture(this.args.skp64,this.args.params.layerRect);},set picture(picture){this.picture_=picture;},get canSave(){return this.picture_.canSave;},get layerRect(){return this.layerRect_?this.layerRect_:this.picture_.layerRect;},get guid(){return this.picture_.guid;},getBase64SkpData(){return this.picture_.getBase64SkpData();},getOps(){return this.picture_.getOps();},getOpTimings(){return this.picture_.getOpTimings();},tagOpsWithTimings(ops){return this.picture_.tagOpsWithTimings(ops);},rasterize(params,rasterCompleteCallback){this.picture_.rasterize(params,rasterCompleteCallback);}};ObjectSnapshot.subTypes.register(PictureSnapshot,{typeNames:['cc::Picture']});return{PictureSnapshot,Picture,LayeredPicture,};});'use strict';tr.exportTo('tr.e.cc',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function DisplayItemList(skp64,layerRect){tr.e.cc.Picture.apply(this,arguments);}
+DisplayItemList.prototype={__proto__:tr.e.cc.Picture.prototype};function DisplayItemListSnapshot(){tr.e.cc.PictureSnapshot.apply(this,arguments);}
+DisplayItemListSnapshot.prototype={__proto__:tr.e.cc.PictureSnapshot.prototype,initialize(){tr.e.cc.PictureSnapshot.prototype.initialize.call(this);this.displayItems_=this.args.params.items;},get items(){return this.displayItems_;}};ObjectSnapshot.subTypes.register(DisplayItemListSnapshot,{typeNames:['cc::DisplayItemList']});return{DisplayItemListSnapshot,DisplayItemList,};});'use strict';tr.exportTo('tr.b.math',function(){function BBox2(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;}
+BBox2.prototype={__proto__:Object.prototype,reset(){this.isEmpty_=true;this.min_=undefined;this.max_=undefined;},get isEmpty(){return this.isEmpty_;},addBBox2(bbox2){if(bbox2.isEmpty)return;this.addVec2(bbox2.min_);this.addVec2(bbox2.max_);},clone(){const bbox=new BBox2();bbox.addBBox2(this);return bbox;},addXY(x,y){if(this.isEmpty_){this.max_=vec2.create();this.min_=vec2.create();vec2.set(this.max_,x,y);vec2.set(this.min_,x,y);this.isEmpty_=false;return;}
+this.max_[0]=Math.max(this.max_[0],x);this.max_[1]=Math.max(this.max_[1],y);this.min_[0]=Math.min(this.min_[0],x);this.min_[1]=Math.min(this.min_[1],y);},addVec2(value){if(this.isEmpty_){this.max_=vec2.create();this.min_=vec2.create();vec2.set(this.max_,value[0],value[1]);vec2.set(this.min_,value[0],value[1]);this.isEmpty_=false;return;}
+this.max_[0]=Math.max(this.max_[0],value[0]);this.max_[1]=Math.max(this.max_[1],value[1]);this.min_[0]=Math.min(this.min_[0],value[0]);this.min_[1]=Math.min(this.min_[1],value[1]);},addQuad(quad){this.addVec2(quad.p1);this.addVec2(quad.p2);this.addVec2(quad.p3);this.addVec2(quad.p4);},get minVec2(){if(this.isEmpty_)return undefined;return this.min_;},get maxVec2(){if(this.isEmpty_)return undefined;return this.max_;},get sizeAsVec2(){if(this.isEmpty_){throw new Error('Empty BBox2 has no size');}
+const size=vec2.create();vec2.subtract(size,this.max_,this.min_);return size;},get size(){if(this.isEmpty_){throw new Error('Empty BBox2 has no size');}
+return{width:this.max_[0]-this.min_[0],height:this.max_[1]-this.min_[1]};},get width(){if(this.isEmpty_){throw new Error('Empty BBox2 has no width');}
+return this.max_[0]-this.min_[0];},get height(){if(this.isEmpty_){throw new Error('Empty BBox2 has no width');}
+return this.max_[1]-this.min_[1];},toString(){if(this.isEmpty_)return'empty';return'min=('+this.min_[0]+','+this.min_[1]+') '+'max=('+this.max_[0]+','+this.max_[1]+')';},asRect(){return tr.b.math.Rect.fromXYWH(this.min_[0],this.min_[1],this.max_[0]-this.min_[0],this.max_[1]-this.min_[1]);}};return{BBox2,};});'use strict';tr.exportTo('tr.e.cc',function(){const constants={};constants.ACTIVE_TREE=0;constants.PENDING_TREE=1;constants.HIGH_PRIORITY_BIN=0;constants.LOW_PRIORITY_BIN=1;constants.SEND_BEGIN_FRAME_EVENT='ThreadProxy::ScheduledActionSendBeginMainFrame';constants.BEGIN_MAIN_FRAME_EVENT='ThreadProxy::BeginMainFrame';return{constants};});'use strict';tr.exportTo('tr.e.cc',function(){function Region(){this.rects=[];}
+Region.fromArray=function(array){if(array.length%4!==0){throw new Error('Array must consist be a multiple of 4 in length');}
+const r=new Region();for(let i=0;i<array.length;i+=4){r.rects.push(tr.b.math.Rect.fromXYWH(array[i],array[i+1],array[i+2],array[i+3]));}
+return r;};Region.fromArrayOrUndefined=function(array){if(array===undefined)return new Region();return Region.fromArray(array);};Region.prototype={__proto__:Region.prototype,rectIntersects(r){for(let i=0;i<this.rects.length;i++){if(this.rects[i].intersects(r))return true;}
+return false;},addRect(r){this.rects.push(r);}};return{Region,};});'use strict';tr.exportTo('tr.e.cc',function(){function TileCoverageRect(rect,tile){this.geometryRect=rect;this.tile=tile;}
+return{TileCoverageRect,};});'use strict';tr.exportTo('tr.e.cc',function(){const constants=tr.e.cc.constants;const ObjectSnapshot=tr.model.ObjectSnapshot;function LayerImplSnapshot(){ObjectSnapshot.apply(this,arguments);}
+LayerImplSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);this.layerTreeImpl_=undefined;this.parentLayer=undefined;},initialize(){this.invalidation=new tr.e.cc.Region();this.unrecordedRegion=new tr.e.cc.Region();this.pictures=[];tr.e.cc.moveRequiredFieldsFromArgsToToplevel(this,['layerId','layerQuad']);tr.e.cc.moveOptionalFieldsFromArgsToToplevel(this,['children','maskLayer','replicaLayer','idealContentsScale','geometryContentsScale','layoutRects','usingGpuRasterization']);this.gpuMemoryUsageInBytes=this.args.gpuMemoryUsage;this.bounds=tr.b.math.Rect.fromXYWH(0,0,this.args.bounds.width,this.args.bounds.height);if(this.args.animationBounds){this.animationBoundsRect=tr.b.math.Rect.fromXYWH(this.args.animationBounds[0],this.args.animationBounds[1],this.args.animationBounds[3],this.args.animationBounds[4]);}
+if(this.children){for(let i=0;i<this.children.length;i++){this.children[i].parentLayer=this;}}
+if(this.maskLayer){this.maskLayer.parentLayer=this;}
+if(this.replicaLayer){this.replicaLayer.parentLayer=this;}
+if(!this.geometryContentsScale){this.geometryContentsScale=1.0;}
+if(!this.idealContentsScale){this.idealContentsScale=1.0;}
+this.touchEventHandlerRegion=tr.e.cc.Region.fromArrayOrUndefined(this.args.touchEventHandlerRegion);this.wheelEventHandlerRegion=tr.e.cc.Region.fromArrayOrUndefined(this.args.wheelEventHandlerRegion);this.nonFastScrollableRegion=tr.e.cc.Region.fromArrayOrUndefined(this.args.nonFastScrollableRegion);},get layerTreeImpl(){if(this.layerTreeImpl_){return this.layerTreeImpl_;}
+if(this.parentLayer){return this.parentLayer.layerTreeImpl;}
+return undefined;},set layerTreeImpl(layerTreeImpl){this.layerTreeImpl_=layerTreeImpl;},get activeLayer(){if(this.layerTreeImpl.whichTree===constants.ACTIVE_TREE){return this;}
+const activeTree=this.layerTreeImpl.layerTreeHostImpl.activeTree;return activeTree.findLayerWithId(this.layerId);},get pendingLayer(){if(this.layerTreeImpl.whichTree===constants.PENDING_TREE){return this;}
+const pendingTree=this.layerTreeImpl.layerTreeHostImpl.pendingTree;return pendingTree.findLayerWithId(this.layerId);}};function PictureLayerImplSnapshot(){LayerImplSnapshot.apply(this,arguments);}
+PictureLayerImplSnapshot.prototype={__proto__:LayerImplSnapshot.prototype,initialize(){LayerImplSnapshot.prototype.initialize.call(this);if(this.args.debugInfo){for(const i in this.args.debugInfo){this.args[i]=this.args.debugInfo[i];}
+delete this.args.debugInfo;}
+if(this.args.annotatedInvalidationRects){this.invalidation=new tr.e.cc.Region();for(const annotatedRect of this.args.annotatedInvalidationRects){const rect=annotatedRect.geometryRect;rect.reason=annotatedRect.reason;rect.client=annotatedRect.client;this.invalidation.addRect(rect);}
+delete this.args.annotatedInvalidationRects;}else if(this.args.invalidation){this.invalidation=tr.e.cc.Region.fromArray(this.args.invalidation);}
+delete this.args.invalidation;if(this.args.unrecordedRegion){this.unrecordedRegion=tr.e.cc.Region.fromArray(this.args.unrecordedRegion);delete this.args.unrecordedRegion;}
+if(this.args.pictures){this.pictures=this.args.pictures;this.pictures.sort(function(a,b){return a.ts-b.ts;});}
+this.tileCoverageRects=[];if(this.args.coverageTiles){for(let i=0;i<this.args.coverageTiles.length;++i){const rect=this.args.coverageTiles[i].geometryRect.scale(this.idealContentsScale);const tile=this.args.coverageTiles[i].tile;this.tileCoverageRects.push(new tr.e.cc.TileCoverageRect(rect,tile));}
+delete this.args.coverageTiles;}}};ObjectSnapshot.subTypes.register(PictureLayerImplSnapshot,{typeName:'cc::PictureLayerImpl'});ObjectSnapshot.subTypes.register(LayerImplSnapshot,{typeNames:['cc::LayerImpl','cc::DelegatedRendererLayerImpl','cc::HeadsUpDisplayLayerImpl','cc::IOSurfaceLayerImpl','cc::NinePatchLayerImpl','cc::PictureImageLayerImpl','cc::ScrollbarLayerImpl','cc::SolidColorLayerImpl','cc::SolidColorScrollbarLayerImpl','cc::SurfaceLayerImpl','cc::TextureLayerImpl','cc::TiledLayerImpl','cc::VideoLayerImpl','cc::PaintedScrollbarLayerImpl','ClankPatchLayer','TabBorderLayer','CounterLayer']});return{LayerImplSnapshot,PictureLayerImplSnapshot,};});'use strict';tr.exportTo('tr.e.cc',function(){const constants=tr.e.cc.constants;const ObjectSnapshot=tr.model.ObjectSnapshot;function LayerTreeImplSnapshot(){ObjectSnapshot.apply(this,arguments);}
+LayerTreeImplSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);this.layerTreeHostImpl=undefined;this.whichTree=undefined;this.sourceFrameNumber=undefined;},initialize(){tr.e.cc.moveRequiredFieldsFromArgsToToplevel(this,['renderSurfaceLayerList']);tr.e.cc.moveOptionalFieldsFromArgsToToplevel(this,['rootLayer','layers']);if(this.args.sourceFrameNumber){this.sourceFrameNumber=this.args.sourceFrameNumber;}
+if(this.rootLayer){this.rootLayer.layerTreeImpl=this;}else{for(let i=0;i<this.layers.length;i++){this.layers[i].layerTreeImpl=this;}}
+if(this.args.swapPromiseTraceIds&&this.args.swapPromiseTraceIds.length){this.tracedInputLatencies=[];const ownProcess=this.objectInstance.parent;const modelHelper=ownProcess.model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper){this._initializeTracedInputLatencies(modelHelper);}}},_initializeTracedInputLatencies(modelHelper){const latencyEvents=modelHelper.browserHelper.getLatencyEventsInRange(modelHelper.model.bounds);latencyEvents.forEach(function(event){for(let i=0;i<this.args.swapPromiseTraceIds.length;i++){if(!event.args.data||!event.args.data.trace_id){continue;}
+if(parseInt(event.args.data.trace_id)===this.args.swapPromiseTraceIds[i]){this.tracedInputLatencies.push(event);}}},this);},get hasSourceFrameBeenDrawnBefore(){if(this.whichTree===tr.e.cc.constants.PENDING_TREE){return false;}
+if(this.sourceFrameNumber===undefined)return;const thisLTHI=this.layerTreeHostImpl;const thisLTHIIndex=thisLTHI.objectInstance.snapshots.indexOf(thisLTHI);const prevLTHIIndex=thisLTHIIndex-1;if(prevLTHIIndex<0||prevLTHIIndex>=thisLTHI.objectInstance.snapshots.length){return false;}
+const prevLTHI=thisLTHI.objectInstance.snapshots[prevLTHIIndex];if(!prevLTHI.activeTree)return false;if(prevLTHI.activeTree.sourceFrameNumber===undefined)return;return prevLTHI.activeTree.sourceFrameNumber===this.sourceFrameNumber;},get otherTree(){const other=this.whichTree===constants.ACTIVE_TREE?constants.PENDING_TREE:constants.ACTIVE_TREE;return this.layerTreeHostImpl.getTree(other);},get gpuMemoryUsageInBytes(){let totalBytes=0;this.iterLayers(function(layer){if(layer.gpuMemoryUsageInBytes!==undefined){totalBytes+=layer.gpuMemoryUsageInBytes;}});return totalBytes;},iterLayers(func,thisArg){const visitedLayers={};function visitLayer(layer,depth,isMask,isReplica){if(visitedLayers[layer.layerId])return;visitedLayers[layer.layerId]=true;func.call(thisArg,layer,depth,isMask,isReplica);if(layer.children){for(let i=0;i<layer.children.length;i++){visitLayer(layer.children[i],depth+1);}}
+if(layer.maskLayer){visitLayer(layer.maskLayer,depth+1,true,false);}
+if(layer.replicaLayer){visitLayer(layer.replicaLayer,depth+1,false,true);}}
+if(this.rootLayer){visitLayer(this.rootLayer,0,false,false);}else{for(let i=0;i<this.layers.length;i++){visitLayer(this.layers[i],0,false,false);}}},findLayerWithId(id){let foundLayer=undefined;function visitLayer(layer){if(layer.layerId===id){foundLayer=layer;}}
+this.iterLayers(visitLayer);return foundLayer;}};ObjectSnapshot.subTypes.register(LayerTreeImplSnapshot,{typeName:'cc::LayerTreeImpl'});return{LayerTreeImplSnapshot,};});'use strict';tr.exportTo('tr.e.cc',function(){const constants=tr.e.cc.constants;const ObjectSnapshot=tr.model.ObjectSnapshot;const ObjectInstance=tr.model.ObjectInstance;function LayerTreeHostImplSnapshot(){ObjectSnapshot.apply(this,arguments);}
+LayerTreeHostImplSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);},initialize(){tr.e.cc.moveRequiredFieldsFromArgsToToplevel(this,['deviceViewportSize','activeTree']);tr.e.cc.moveOptionalFieldsFromArgsToToplevel(this,['pendingTree']);if(this.args.activeTiles!==undefined){this.activeTiles=this.args.activeTiles;delete this.args.activeTiles;}else if(this.args.tiles!==undefined){this.activeTiles=this.args.tiles;delete this.args.tiles;}
+if(!this.activeTiles){this.activeTiles=[];}
+this.activeTree.layerTreeHostImpl=this;this.activeTree.whichTree=constants.ACTIVE_TREE;if(this.pendingTree){this.pendingTree.layerTreeHostImpl=this;this.pendingTree.whichTree=constants.PENDING_TREE;}},getContentsScaleNames(){const scales={};for(let i=0;i<this.activeTiles.length;++i){const tile=this.activeTiles[i];scales[tile.contentsScale]=tile.resolution;}
+return scales;},getTree(whichTree){if(whichTree===constants.ACTIVE_TREE){return this.activeTree;}
+if(whichTree===constants.PENDING_TREE){return this.pendingTree;}
+throw new Exception('Unknown tree type + '+whichTree);},get tilesHaveGpuMemoryUsageInfo(){if(this.tilesHaveGpuMemoryUsageInfo_!==undefined){return this.tilesHaveGpuMemoryUsageInfo_;}
+for(let i=0;i<this.activeTiles.length;i++){if(this.activeTiles[i].gpuMemoryUsageInBytes===undefined){continue;}
+this.tilesHaveGpuMemoryUsageInfo_=true;return true;}
+this.tilesHaveGpuMemoryUsageInfo_=false;return false;},get gpuMemoryUsageInBytes(){if(!this.tilesHaveGpuMemoryUsageInfo)return;let usage=0;for(let i=0;i<this.activeTiles.length;i++){const u=this.activeTiles[i].gpuMemoryUsageInBytes;if(u!==undefined)usage+=u;}
+return usage;},get userFriendlyName(){let frameNumber;if(!this.activeTree){frameNumber=this.objectInstance.snapshots.indexOf(this);}else{if(this.activeTree.sourceFrameNumber===undefined){frameNumber=this.objectInstance.snapshots.indexOf(this);}else{frameNumber=this.activeTree.sourceFrameNumber;}}
+return'cc::LayerTreeHostImpl frame '+frameNumber;}};ObjectSnapshot.subTypes.register(LayerTreeHostImplSnapshot,{typeName:'cc::LayerTreeHostImpl'});function LayerTreeHostImplInstance(){ObjectInstance.apply(this,arguments);this.allLayersBBox_=undefined;}
+LayerTreeHostImplInstance.prototype={__proto__:ObjectInstance.prototype,get allContentsScales(){if(this.allContentsScales_){return this.allContentsScales_;}
+const scales={};for(const tileID in this.allTileHistories_){const tileHistory=this.allTileHistories_[tileID];scales[tileHistory.contentsScale]=true;}
+this.allContentsScales_=Object.keys(scales);return this.allContentsScales_;},get allLayersBBox(){if(this.allLayersBBox_){return this.allLayersBBox_;}
+const bbox=new tr.b.math.BBox2();function handleTree(tree){tree.renderSurfaceLayerList.forEach(function(layer){bbox.addQuad(layer.layerQuad);});}
+this.snapshots.forEach(function(lthi){handleTree(lthi.activeTree);if(lthi.pendingTree){handleTree(lthi.pendingTree);}});this.allLayersBBox_=bbox;return this.allLayersBBox_;}};ObjectInstance.subTypes.register(LayerTreeHostImplInstance,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshot,LayerTreeHostImplInstance,};});'use strict';tr.exportTo('tr.e.cc',function(){const tileTypes={highRes:'highRes',lowRes:'lowRes',extraHighRes:'extraHighRes',extraLowRes:'extraLowRes',missing:'missing',culled:'culled',solidColor:'solidColor',picture:'picture',directPicture:'directPicture',unknown:'unknown'};const tileBorder={highRes:{color:'rgba(80, 200, 200, 0.7)',width:1},lowRes:{color:'rgba(212, 83, 192, 0.7)',width:2},extraHighRes:{color:'rgba(239, 231, 20, 0.7)',width:2},extraLowRes:{color:'rgba(93, 186, 18, 0.7)',width:2},missing:{color:'rgba(255, 0, 0, 0.7)',width:1},culled:{color:'rgba(160, 100, 0, 0.8)',width:1},solidColor:{color:'rgba(128, 128, 128, 0.7)',width:1},picture:{color:'rgba(64, 64, 64, 0.7)',width:1},directPicture:{color:'rgba(127, 255, 0, 1.0)',width:1},unknown:{color:'rgba(0, 0, 0, 1.0)',width:2}};return{tileTypes,tileBorder};});'use strict';tr.exportTo('tr.e.cc',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function TileSnapshot(){ObjectSnapshot.apply(this,arguments);}
+TileSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);},initialize(){tr.e.cc.moveOptionalFieldsFromArgsToToplevel(this,['layerId','contentsScale','contentRect']);if(this.args.managedState){this.resolution=this.args.managedState.resolution;this.isSolidColor=this.args.managedState.isSolidColor;this.isUsingGpuMemory=this.args.managedState.isUsingGpuMemory;this.hasResource=this.args.managedState.hasResource;this.scheduledPriority=this.args.scheduledPriority;this.gpuMemoryUsageInBytes=this.args.gpuMemoryUsage;}else{this.resolution=this.args.resolution;this.isSolidColor=this.args.drawInfo.isSolidColor;this.isUsingGpuMemory=this.args.isUsingGpuMemory;this.hasResource=this.args.hasResource;this.scheduledPriority=this.args.scheduledPriority;this.gpuMemoryUsageInBytes=this.args.gpuMemoryUsage;}
+if(this.contentRect){this.layerRect=this.contentRect.scale(1.0/this.contentsScale);}
+if(this.isSolidColor){this.type_=tr.e.cc.tileTypes.solidColor;}else if(!this.hasResource){this.type_=tr.e.cc.tileTypes.missing;}else if(this.resolution==='HIGH_RESOLUTION'){this.type_=tr.e.cc.tileTypes.highRes;}else if(this.resolution==='LOW_RESOLUTION'){this.type_=tr.e.cc.tileTypes.lowRes;}else{this.type_=tr.e.cc.tileTypes.unknown;}},getTypeForLayer(layer){let type=this.type_;if(type===tr.e.cc.tileTypes.unknown){if(this.contentsScale<layer.idealContentsScale){type=tr.e.cc.tileTypes.extraLowRes;}else if(this.contentsScale>layer.idealContentsScale){type=tr.e.cc.tileTypes.extraHighRes;}}
+return type;}};ObjectSnapshot.subTypes.register(TileSnapshot,{typeName:'cc::Tile'});return{TileSnapshot,};});'use strict';tr.exportTo('tr.ui.b',function(){const Location=tr.model.Location;function UIState(location,scaleX){this.location_=location;this.scaleX_=scaleX;}
+UIState.fromUserFriendlyString=function(model,viewport,stateString){const navByFinderPattern=/^(-?\d+(\.\d+)?)@(.+)x(\d+(\.\d+)?)$/g;const match=navByFinderPattern.exec(stateString);if(!match)return;const timestamp=parseFloat(match[1]);const stableId=match[3];const scaleX=parseFloat(match[4]);if(scaleX<=0){throw new Error('Invalid ScaleX value in UI State string.');}
+if(!viewport.containerToTrackMap.getTrackByStableId(stableId)){throw new Error('Invalid StableID given in UI State String.');}
+const loc=tr.model.Location.fromStableIdAndTimestamp(viewport,stableId,timestamp);return new UIState(loc,scaleX);};UIState.prototype={get location(){return this.location_;},get scaleX(){return this.scaleX_;},toUserFriendlyString(viewport){const timestamp=this.location_.xWorld;const stableId=this.location_.getContainingTrack(viewport).eventContainer.stableId;const scaleX=this.scaleX_;return timestamp.toFixed(5)+'@'+stableId+'x'+scaleX.toFixed(5);},toDict(){return{location:this.location_.toDict(),scaleX:this.scaleX_};}};return{UIState,};});'use strict';tr.exportTo('tr.ui.b',function(){const EventSet=tr.model.EventSet;const SelectionState=tr.model.SelectionState;function BrushingState(){this.guid_=tr.b.GUID.allocateSimple();this.selection_=new EventSet();this.findMatches_=new EventSet();this.analysisViewRelatedEvents_=new EventSet();this.analysisLinkHoveredEvents_=new EventSet();this.appliedToModel_=undefined;this.viewSpecificBrushingStates_={};}
+BrushingState.prototype={get guid(){return this.guid_;},clone(){const that=new BrushingState();that.selection_=this.selection_;that.findMatches_=this.findMatches_;that.analysisViewRelatedEvents_=this.analysisViewRelatedEvents_;that.analysisLinkHoveredEvents_=this.analysisLinkHoveredEvents_;that.viewSpecificBrushingStates_=this.viewSpecificBrushingStates_;return that;},equals(that){if(!this.selection_.equals(that.selection_)){return false;}
+if(!this.findMatches_.equals(that.findMatches_)){return false;}
+if(!this.analysisViewRelatedEvents_.equals(that.analysisViewRelatedEvents_)){return false;}
+if(!this.analysisLinkHoveredEvents_.equals(that.analysisLinkHoveredEvents_)){return false;}
+return true;},get selectionOfInterest(){if(this.selection_.length){return this.selection_;}
+if(this.highlight_.length){return this.highlight_;}
+if(this.analysisViewRelatedEvents_.length){return this.analysisViewRelatedEvents_;}
+if(this.analysisLinkHoveredEvents_.length){return this.analysisLinkHoveredEvents_;}
+return this.selection_;},get selection(){return this.selection_;},set selection(selection){if(this.appliedToModel_){throw new Error('Cannot mutate this state right now');}
+if(selection===undefined){selection=new EventSet();}
+this.selection_=selection;},get findMatches(){return this.findMatches_;},set findMatches(findMatches){if(this.appliedToModel_){throw new Error('Cannot mutate this state right now');}
+if(findMatches===undefined){findMatches=new EventSet();}
+this.findMatches_=findMatches;},get analysisViewRelatedEvents(){return this.analysisViewRelatedEvents_;},set analysisViewRelatedEvents(analysisViewRelatedEvents){if(this.appliedToModel_){throw new Error('Cannot mutate this state right now');}
+if(!(analysisViewRelatedEvents instanceof EventSet)){analysisViewRelatedEvents=new EventSet();}
+this.analysisViewRelatedEvents_=analysisViewRelatedEvents;},get analysisLinkHoveredEvents(){return this.analysisLinkHoveredEvents_;},set analysisLinkHoveredEvents(analysisLinkHoveredEvents){if(this.appliedToModel_){throw new Error('Cannot mutate this state right now');}
+if(!(analysisLinkHoveredEvents instanceof EventSet)){analysisLinkHoveredEvents=new EventSet();}
+this.analysisLinkHoveredEvents_=analysisLinkHoveredEvents;},get isAppliedToModel(){return this.appliedToModel_!==undefined;},get viewSpecificBrushingStates(){return this.viewSpecificBrushingStates_;},set viewSpecificBrushingStates(viewSpecificBrushingStates){this.viewSpecificBrushingStates_=viewSpecificBrushingStates;},get defaultState_(){const standoutEventExists=(this.analysisLinkHoveredEvents_.length>0||this.analysisViewRelatedEvents_.length>0||this.findMatches_.length>0);return(standoutEventExists?SelectionState.DIMMED0:SelectionState.NONE);},get brightenedEvents_(){const brightenedEvents=new EventSet();brightenedEvents.addEventSet(this.findMatches);brightenedEvents.addEventSet(this.analysisViewRelatedEvents_);brightenedEvents.addEventSet(this.selection_);brightenedEvents.addEventSet(this.analysisLinkHoveredEvents_);return brightenedEvents;},applyToEventSelectionStates(model){this.appliedToModel_=model;if(model){const newDefaultState=this.defaultState_;const currentDefaultState=tr.b.getFirstElement(model.getDescendantEvents()).selectionState;if(currentDefaultState!==newDefaultState){for(const e of model.getDescendantEvents()){e.selectionState=newDefaultState;}}}
+let level;for(const e of this.brightenedEvents_){level=0;if(this.analysisViewRelatedEvents_.contains(e)||this.findMatches_.contains(e)){level++;}
+if(this.analysisLinkHoveredEvents_.contains(e)){level++;}
+if(this.selection_.contains(e)){level++;}
+e.selectionState=SelectionState.getFromBrighteningLevel(level);}},transferModelOwnershipToClone(that){if(!this.appliedToModel_){throw new Error('Not applied');}
+that.appliedToModel_=this.appliedToModel_;this.appliedToModel_=undefined;},unapplyFromEventSelectionStates(){if(!this.appliedToModel_){throw new Error('Not applied');}
+const model=this.appliedToModel_;this.appliedToModel_=undefined;const defaultState=this.defaultState_;for(const e of this.brightenedEvents_){e.selectionState=defaultState;}
+return defaultState;}};return{BrushingState,};});'use strict';tr.exportTo('tr.ui.b',function(){function Animation(){}
+Animation.prototype={canTakeOverFor(existingAnimation){throw new Error('Not implemented');},takeOverFor(existingAnimation,newStartTimestamp,target){throw new Error('Not implemented');},start(timestamp,target){throw new Error('Not implemented');},didStopEarly(timestamp,target,willBeTakenOverByAnotherAnimation){},tick(timestamp,target){throw new Error('Not implemented');}};return{Animation,};});'use strict';tr.exportTo('tr.ui.b',function(){function AnimationController(){tr.b.EventTarget.call(this);this.target_=undefined;this.activeAnimation_=undefined;this.tickScheduled_=false;}
+AnimationController.prototype={__proto__:tr.b.EventTarget.prototype,get target(){return this.target_;},set target(target){if(this.activeAnimation_){throw new Error('Cannot change target while animation is running.');}
+if(target.cloneAnimationState===undefined||typeof target.cloneAnimationState!=='function'){throw new Error('target must have a cloneAnimationState function');}
+this.target_=target;},get activeAnimation(){return this.activeAnimation_;},get hasActiveAnimation(){return!!this.activeAnimation_;},queueAnimation(animation,opt_now){if(this.target_===undefined){throw new Error('Cannot queue animations without a target');}
+let now;if(opt_now!==undefined){now=opt_now;}else{now=window.performance.now();}
+if(this.activeAnimation_){const done=this.activeAnimation_.tick(now,this.target_);if(done){this.activeAnimation_=undefined;}}
+if(this.activeAnimation_){if(animation.canTakeOverFor(this.activeAnimation_)){this.activeAnimation_.didStopEarly(now,this.target_,true);animation.takeOverFor(this.activeAnimation_,now,this.target_);}else{this.activeAnimation_.didStopEarly(now,this.target_,false);}}
+this.activeAnimation_=animation;this.activeAnimation_.start(now,this.target_);if(this.tickScheduled_)return;this.tickScheduled_=true;tr.b.requestAnimationFrame(this.tickActiveAnimation_,this);},cancelActiveAnimation(opt_now){if(!this.activeAnimation_)return;let now;if(opt_now!==undefined){now=opt_now;}else{now=window.performance.now();}
+this.activeAnimation_.didStopEarly(now,this.target_,false);this.activeAnimation_=undefined;},tickActiveAnimation_(frameBeginTime){this.tickScheduled_=false;if(!this.activeAnimation_)return;if(this.target_===undefined){this.activeAnimation_.didStopEarly(frameBeginTime,this.target_,false);return;}
+const oldTargetState=this.target_.cloneAnimationState();const done=this.activeAnimation_.tick(frameBeginTime,this.target_);if(done){this.activeAnimation_=undefined;}
+if(this.activeAnimation_){this.tickScheduled_=true;tr.b.requestAnimationFrame(this.tickActiveAnimation_,this);}
+if(oldTargetState){const e=new tr.b.Event('didtick');e.oldTargetState=oldTargetState;this.dispatchEvent(e,false,false);}}};return{AnimationController,};});'use strict';tr.exportTo('tr.b',function(){function Settings(){return Settings;}
+if(tr.b.unittest&&tr.b.unittest.TestRunner){tr.b.unittest.TestRunner.addEventListener('tr-unittest-will-run',function(){if(tr.isHeadless){Settings.setAlternativeStorageInstance(new HeadlessStorage());}else{Settings.setAlternativeStorageInstance(global.sessionStorage);global.sessionStorage.clear();}});}
+function SessionSettings(){return SessionSettings;}
+function AddStaticStorageFunctionsToClass_(inputClass,storage){inputClass.storage_=storage;inputClass.get=function(key,opt_default,opt_namespace){key=inputClass.namespace_(key,opt_namespace);const rawVal=inputClass.storage_.getItem(key);if(rawVal===null||rawVal===undefined){return opt_default;}
+try{return JSON.parse(rawVal).value;}catch(e){inputClass.storage_.removeItem(key);return opt_default;}};inputClass.set=function(key,value,opt_namespace){if(value===undefined){throw new Error('Settings.set: value must not be undefined');}
+const v=JSON.stringify({value});inputClass.storage_.setItem(inputClass.namespace_(key,opt_namespace),v);};inputClass.keys=function(opt_namespace){const result=[];opt_namespace=opt_namespace||'';for(let i=0;i<inputClass.storage_.length;i++){const key=inputClass.storage_.key(i);if(inputClass.isnamespaced_(key,opt_namespace)){result.push(inputClass.unnamespace_(key,opt_namespace));}}
+return result;};inputClass.isnamespaced_=function(key,opt_namespace){return key.indexOf(inputClass.normalize_(opt_namespace))===0;};inputClass.namespace_=function(key,opt_namespace){return inputClass.normalize_(opt_namespace)+key;};inputClass.unnamespace_=function(key,opt_namespace){return key.replace(inputClass.normalize_(opt_namespace),'');};inputClass.normalize_=function(opt_namespace){return inputClass.NAMESPACE+(opt_namespace?opt_namespace+'.':'');};inputClass.setAlternativeStorageInstance=function(instance){inputClass.storage_=instance;};inputClass.getAlternativeStorageInstance=function(){if(!tr.isHeadless&&inputClass.storage_===localStorage){return undefined;}
+return inputClass.storage_;};inputClass.NAMESPACE='trace-viewer';}
+function HeadlessStorage(){this.length=0;this.hasItem_={};this.items_={};this.itemsAsArray_=undefined;}
+HeadlessStorage.prototype={key(index){return this.itemsAsArray[index];},get itemsAsArray(){if(this.itemsAsArray_!==undefined){return this.itemsAsArray_;}
+const itemsAsArray=[];for(const k in this.items_){itemsAsArray.push(k);}
+this.itemsAsArray_=itemsAsArray;return this.itemsAsArray_;},getItem(key){if(!this.hasItem_[key]){return null;}
+return this.items_[key];},removeItem(key){if(!this.hasItem_[key]){return;}
+const value=this.items_[key];delete this.hasItem_[key];delete this.items_[key];this.length--;this.itemsAsArray_=undefined;return value;},setItem(key,value){if(this.hasItem_[key]){this.items_[key]=value;return;}
+this.items_[key]=value;this.hasItem_[key]=true;this.length++;this.itemsAsArray_=undefined;return value;}};if(tr.isHeadless){AddStaticStorageFunctionsToClass_(Settings,new HeadlessStorage());AddStaticStorageFunctionsToClass_(SessionSettings,new HeadlessStorage());}else{AddStaticStorageFunctionsToClass_(Settings,localStorage);AddStaticStorageFunctionsToClass_(SessionSettings,sessionStorage);}
+return{Settings,SessionSettings,};});'use strict';tr.exportTo('tr.ui.b',function(){function createSpan(opt_dictionary){let ownerDocument=document;if(opt_dictionary&&opt_dictionary.ownerDocument){ownerDocument=opt_dictionary.ownerDocument;}
+const spanEl=ownerDocument.createElement('span');if(opt_dictionary){if(opt_dictionary.className){spanEl.className=opt_dictionary.className;}
+if(opt_dictionary.textContent){Polymer.dom(spanEl).textContent=opt_dictionary.textContent;}
+if(opt_dictionary.tooltip){spanEl.title=opt_dictionary.tooltip;}
+if(opt_dictionary.parent){Polymer.dom(opt_dictionary.parent).appendChild(spanEl);}
+if(opt_dictionary.bold){spanEl.style.fontWeight='bold';}
+if(opt_dictionary.italic){spanEl.style.fontStyle='italic';}
+if(opt_dictionary.marginLeft){spanEl.style.marginLeft=opt_dictionary.marginLeft;}
+if(opt_dictionary.marginRight){spanEl.style.marginRight=opt_dictionary.marginRight;}
+if(opt_dictionary.backgroundColor){spanEl.style.backgroundColor=opt_dictionary.backgroundColor;}
+if(opt_dictionary.color){spanEl.style.color=opt_dictionary.color;}}
+return spanEl;}
+function createLink(opt_args){let ownerDocument=document;if(opt_args&&opt_args.ownerDocument){ownerDocument=opt_args.ownerDocument;}
+const linkEl=ownerDocument.createElement('a');if(opt_args){if(opt_args.href)linkEl.href=opt_args.href;if(opt_args.tooltip)linkEl.title=opt_args.tooltip;if(opt_args.color)linkEl.style.color=opt_args.color;if(opt_args.bold)linkEl.style.fontWeight='bold';if(opt_args.italic)linkEl.style.fontStyle='italic';if(opt_args.className)linkEl.className=opt_args.className;if(opt_args.parent)Polymer.dom(opt_args.parent).appendChild(linkEl);if(opt_args.marginLeft)linkEl.style.marginLeft=opt_args.marginLeft;if(opt_args.marginRight)linkEl.style.marginRight=opt_args.marginRight;if(opt_args.backgroundColor){linkEl.style.backgroundColor=opt_args.backgroundColor;}
+if(opt_args.textContent){Polymer.dom(linkEl).textContent=opt_args.textContent;}}
+return linkEl;}
+function createDiv(opt_dictionary){const divEl=document.createElement('div');if(opt_dictionary){if(opt_dictionary.className){divEl.className=opt_dictionary.className;}
+if(opt_dictionary.parent){Polymer.dom(opt_dictionary.parent).appendChild(divEl);}
+if(opt_dictionary.textContent){Polymer.dom(divEl).textContent=opt_dictionary.textContent;}
+if(opt_dictionary.maxWidth){divEl.style.maxWidth=opt_dictionary.maxWidth;}}
+return divEl;}
+function createScopedStyle(styleContent){const styleEl=document.createElement('style');styleEl.scoped=true;Polymer.dom(styleEl).innerHTML=styleContent;return styleEl;}
+function valuesEqual(a,b){if(a instanceof Array&&b instanceof Array){return a.length===b.length&&JSON.stringify(a)===JSON.stringify(b);}
+return a===b;}
+function createSelector(targetEl,targetElProperty,settingsKey,defaultValue,items,opt_namespace){let defaultValueIndex;for(let i=0;i<items.length;i++){const item=items[i];if(valuesEqual(item.value,defaultValue)){defaultValueIndex=i;break;}}
+if(defaultValueIndex===undefined){throw new Error('defaultValue must be in the items list');}
+const selectorEl=document.createElement('select');selectorEl.addEventListener('change',onChange);for(let i=0;i<items.length;i++){const item=items[i];const optionEl=document.createElement('option');Polymer.dom(optionEl).textContent=item.label;optionEl.targetPropertyValue=item.value;optionEl.item=item;Polymer.dom(selectorEl).appendChild(optionEl);}
+function onChange(e){const value=selectorEl.selectedValue;tr.b.Settings.set(settingsKey,value,opt_namespace);targetEl[targetElProperty]=value;}
+const oldSetter=targetEl.__lookupSetter__('selectedIndex');selectorEl.__defineGetter__('selectedValue',function(v){return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue;});selectorEl.__defineGetter__('selectedItem',function(v){return selectorEl.children[selectorEl.selectedIndex].item;});selectorEl.__defineSetter__('selectedValue',function(v){for(let i=0;i<selectorEl.children.length;i++){const value=selectorEl.children[i].targetPropertyValue;if(valuesEqual(value,v)){const changed=selectorEl.selectedIndex!==i;if(changed){selectorEl.selectedIndex=i;onChange();}
+return;}}
+throw new Error('Not a valid value');});const initialValue=tr.b.Settings.get(settingsKey,defaultValue,opt_namespace);let didSet=false;for(let i=0;i<selectorEl.children.length;i++){if(valuesEqual(selectorEl.children[i].targetPropertyValue,initialValue)){didSet=true;targetEl[targetElProperty]=initialValue;selectorEl.selectedIndex=i;break;}}
+if(!didSet){selectorEl.selectedIndex=defaultValueIndex;targetEl[targetElProperty]=defaultValue;}
+return selectorEl;}
+function createEditCategorySpan(optionGroupEl,targetEl){const spanEl=createSpan({className:'edit-categories'});Polymer.dom(spanEl).textContent='Edit categories';Polymer.dom(spanEl).classList.add('labeled-option');spanEl.addEventListener('click',function(){targetEl.onClickEditCategories();});return spanEl;}
+function createOptionGroup(targetEl,targetElProperty,settingsKey,defaultValue,items){function onChange(){let value=[];if(this.value.length){value=this.value.split(',');}
+tr.b.Settings.set(settingsKey,value);targetEl[targetElProperty]=value;}
+const optionGroupEl=createSpan({className:'labeled-option-group'});const initialValue=tr.b.Settings.get(settingsKey,defaultValue);for(let i=0;i<items.length;++i){const item=items[i];const id='category-preset-'+item.label.replace(/ /g,'-');const radioEl=document.createElement('input');radioEl.type='radio';Polymer.dom(radioEl).setAttribute('id',id);Polymer.dom(radioEl).setAttribute('name','category-presets-group');Polymer.dom(radioEl).setAttribute('value',item.value);radioEl.addEventListener('change',onChange.bind(radioEl,targetEl,targetElProperty,settingsKey));if(valuesEqual(initialValue,item.value)){radioEl.checked=true;}
+const labelEl=document.createElement('label');Polymer.dom(labelEl).textContent=item.label;Polymer.dom(labelEl).setAttribute('for',id);const spanEl=createSpan({className:'labeled-option'});Polymer.dom(spanEl).appendChild(radioEl);Polymer.dom(spanEl).appendChild(labelEl);spanEl.__defineSetter__('checked',function(opt_bool){const changed=radioEl.checked!==(!!opt_bool);if(!changed)return;radioEl.checked=!!opt_bool;onChange();});spanEl.__defineGetter__('checked',function(){return radioEl.checked;});Polymer.dom(optionGroupEl).appendChild(spanEl);}
+Polymer.dom(optionGroupEl).appendChild(createEditCategorySpan(optionGroupEl,targetEl));if(!initialValue.length){Polymer.dom(optionGroupEl).classList.add('categories-expanded');}
+targetEl[targetElProperty]=initialValue;return optionGroupEl;}
+let nextCheckboxId=1;function createCheckBox(targetEl,targetElProperty,settingsKey,defaultValue,label,opt_changeCb){const buttonEl=document.createElement('input');buttonEl.type='checkbox';let initialValue=defaultValue;if(settingsKey!==undefined){initialValue=tr.b.Settings.get(settingsKey,defaultValue);buttonEl.checked=!!initialValue;}
+if(targetEl){targetEl[targetElProperty]=initialValue;}
+function onChange(){if(settingsKey!==undefined){tr.b.Settings.set(settingsKey,buttonEl.checked);}
+if(targetEl){targetEl[targetElProperty]=buttonEl.checked;}
+if(opt_changeCb){opt_changeCb.call();}}
+buttonEl.addEventListener('change',onChange);const id='#checkbox-'+nextCheckboxId++;const spanEl=createSpan();spanEl.style.display='flex';spanEl.style.whiteSpace='nowrap';Polymer.dom(buttonEl).setAttribute('id',id);const labelEl=document.createElement('label');Polymer.dom(labelEl).textContent=label;Polymer.dom(labelEl).setAttribute('for',id);Polymer.dom(spanEl).appendChild(buttonEl);Polymer.dom(spanEl).appendChild(labelEl);spanEl.__defineSetter__('checked',function(opt_bool){const changed=buttonEl.checked!==(!!opt_bool);if(!changed)return;buttonEl.checked=!!opt_bool;onChange();});spanEl.__defineGetter__('checked',function(){return buttonEl.checked;});return spanEl;}
+function createButton(label,opt_callback,opt_this){const buttonEl=document.createElement('input');buttonEl.type='button';buttonEl.value=label;function onClick(){opt_callback.call(opt_this||buttonEl);}
+if(opt_callback){buttonEl.addEventListener('click',onClick);}
+return buttonEl;}
+function createTextInput(targetEl,targetElProperty,settingsKey,defaultValue){const initialValue=tr.b.Settings.get(settingsKey,defaultValue);const el=document.createElement('input');el.type='text';function onChange(e){tr.b.Settings.set(settingsKey,el.value);targetEl[targetElProperty]=el.value;}
+el.addEventListener('input',onChange);el.value=initialValue;targetEl[targetElProperty]=initialValue;return el;}
+function isElementAttachedToDocument(el){let cur=el;while(Polymer.dom(cur).parentNode){cur=Polymer.dom(cur).parentNode;}
+return(cur===el.ownerDocument||cur.nodeName==='#document-fragment');}
+function asHTMLOrTextNode(value,opt_ownerDocument){if(value instanceof Node){return value;}
+const ownerDocument=opt_ownerDocument||document;return ownerDocument.createTextNode(value);}
+return{createSpan,createLink,createDiv,createScopedStyle,createSelector,createOptionGroup,createCheckBox,createButton,createTextInput,isElementAttachedToDocument,asHTMLOrTextNode,};});'use strict';tr.exportTo('tr.ui.b',function(){const elidedTitleCacheDict=new Map();const elidedTitleCache=new ElidedTitleCache();function ElidedTitleCache(){this.textWidthMap=new Map();}
+ElidedTitleCache.prototype={get(ctx,pixWidth,title,width,sliceDuration){let elidedDict=elidedTitleCacheDict.get(title);if(!elidedDict){elidedDict=new Map();elidedTitleCacheDict.set(title,elidedDict);}
+let elidedDictForPixWidth=elidedDict.get(pixWidth);if(!elidedDictForPixWidth){elidedDict.set(pixWidth,new Map());elidedDictForPixWidth=elidedDict.get(pixWidth);}
+let stringWidthPair=elidedDictForPixWidth.get(sliceDuration);if(stringWidthPair===undefined){let newtitle=title;let elided=false;while(this.labelWidthWorld(ctx,newtitle,pixWidth)>sliceDuration){if(newtitle.length*0.75<1)break;newtitle=newtitle.substring(0,newtitle.length*0.75);elided=true;}
+if(elided&&newtitle.length>3){newtitle=newtitle.substring(0,newtitle.length-3)+'...';}
+stringWidthPair=new ElidedStringWidthPair(newtitle,this.labelWidth(ctx,newtitle));elidedDictForPixWidth.set(sliceDuration,stringWidthPair);}
+return stringWidthPair;},quickMeasureText_(ctx,text){let w=this.textWidthMap.get(text);if(!w){w=ctx.measureText(text).width;this.textWidthMap.set(text,w);}
+return w;},labelWidth(ctx,title){return this.quickMeasureText_(ctx,title)+2;},labelWidthWorld(ctx,title,pixWidth){return this.labelWidth(ctx,title)*pixWidth;}};function ElidedStringWidthPair(string,width){this.string=string;this.width=width;}
+return{ElidedTitleCache,};});'use strict';tr.exportTo('tr.ui.b',function(){const ColorScheme=tr.b.ColorScheme;const colors=ColorScheme.colors;const colorsAsStrings=ColorScheme.colorsAsStrings;const SelectionState=tr.model.SelectionState;const EventPresenter={getSelectableItemColorAsString(item){const offset=this.getColorIdOffset_(item);const colorId=ColorScheme.getVariantColorId(item.colorId,offset);return colorsAsStrings[colorId];},getColorIdOffset_(event){return event.selectionState;},getTextColor(event){if(event.selectionState===SelectionState.DIMMED){return'rgb(60,60,60)';}
+return'rgb(0,0,0)';},getSliceColorId(slice){const offset=this.getColorIdOffset_(slice);return ColorScheme.getVariantColorId(slice.colorId,offset);},getSliceAlpha(slice,async){let alpha=1;if(async){alpha*=0.3;}
+return alpha;},getInstantSliceColor(instant){const offset=this.getColorIdOffset_(instant);const colorId=ColorScheme.getVariantColorId(instant.colorId,offset);return colors[colorId].toStringWithAlphaOverride(1.0);},getObjectInstanceColor(instance){const offset=this.getColorIdOffset_(instance);const colorId=ColorScheme.getVariantColorId(instance.colorId,offset);return colors[colorId].toStringWithAlphaOverride(0.25);},getObjectSnapshotColor(snapshot){const offset=this.getColorIdOffset_(snapshot);let colorId=snapshot.objectInstance.colorId;colorId=ColorScheme.getVariantColorId(colorId,offset);return colors[colorId];},getCounterSeriesColor(colorId,selectionState,opt_alphaMultiplier){const event={selectionState};const offset=this.getColorIdOffset_(event);const c=colors[ColorScheme.getVariantColorId(colorId,offset)];return c.toStringWithAlphaOverride(opt_alphaMultiplier!==undefined?opt_alphaMultiplier:1.0);},getBarSnapshotColor(snapshot,offset){const snapshotOffset=this.getColorIdOffset_(snapshot);let colorId=snapshot.objectInstance.colorId;colorId=ColorScheme.getAnotherColorId(colorId,offset);colorId=ColorScheme.getVariantColorId(colorId,snapshotOffset);return colors[colorId].toStringWithAlphaOverride(1.0);}};return{EventPresenter,};});'use strict';tr.exportTo('tr.ui.b',function(){const elidedTitleCache=new tr.ui.b.ElidedTitleCache();const ColorScheme=tr.b.ColorScheme;const colorsAsStrings=ColorScheme.colorsAsStrings;const EventPresenter=tr.ui.b.EventPresenter;const blackColorId=ColorScheme.getColorIdForReservedName('black');const THIN_SLICE_HEIGHT=4;const SLICE_WAITING_WIDTH_DRAW_THRESHOLD=3;const SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD=1;const SHOULD_ELIDE_TEXT=true;function drawLine(ctx,x1,y1,x2,y2){ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);}
+function drawTriangle(ctx,x1,y1,x2,y2,x3,y3){ctx.beginPath();ctx.moveTo(x1,y1);ctx.lineTo(x2,y2);ctx.lineTo(x3,y3);ctx.closePath();}
+function drawArrow(ctx,x1,y1,x2,y2,arrowLength,arrowWidth){const dx=x2-x1;const dy=y2-y1;const len=Math.sqrt(dx*dx+dy*dy);const perc=(len-arrowLength)/len;const bx=x1+perc*dx;const by=y1+perc*dy;const ux=dx/len;const uy=dy/len;const ax=uy*arrowWidth;const ay=-ux*arrowWidth;ctx.beginPath();drawLine(ctx,x1,y1,x2,y2);ctx.stroke();drawTriangle(ctx,bx+ax,by+ay,x2,y2,bx-ax,by-ay);ctx.fill();}
+function drawSlices(ctx,dt,viewLWorld,viewRWorld,viewHeight,slices,async){const pixelRatio=window.devicePixelRatio||1;const height=viewHeight*pixelRatio;const viewL=dt.xWorldToView(viewLWorld);const viewR=dt.xWorldToView(viewRWorld);let darkRectHeight=THIN_SLICE_HEIGHT*pixelRatio;if(height<darkRectHeight){darkRectHeight=0;}
+const lightRectHeight=height-darkRectHeight;ctx.save();const rect=new tr.ui.b.FastRectRenderer(ctx,viewL,viewR,2,2,colorsAsStrings);rect.setYandH(0,height);const lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);let hadTopLevel=false;for(let i=lowSlice;i<slices.length;++i){const slice=slices[i];const x=slice.start;if(x>viewRWorld)break;const xView=dt.xWorldToView(x);let wView=1;if(slice.duration>0){const w=Math.max(slice.duration,0.000001);wView=Math.max(dt.xWorldVectorToView(w),1);}
+const colorId=EventPresenter.getSliceColorId(slice);const alpha=EventPresenter.getSliceAlpha(slice,async);const lightAlpha=alpha*0.70;if(async&&slice.isTopLevel){rect.setYandH(3,height-3);hadTopLevel=true;}else{rect.setYandH(0,height);}
+if(!slice.cpuDuration){rect.fillRect(xView,wView,colorId,alpha);continue;}
+let activeWidth=wView*(slice.cpuDuration/slice.duration);let waitingWidth=wView-activeWidth;if(activeWidth<SLICE_ACTIVE_WIDTH_DRAW_THRESHOLD){activeWidth=0;waitingWidth=wView;}
+if(waitingWidth<SLICE_WAITING_WIDTH_DRAW_THRESHOLD){activeWidth=wView;waitingWidth=0;}
+if(activeWidth>0){rect.fillRect(xView,activeWidth,colorId,alpha);}
+if(waitingWidth>0){rect.setYandH(0,lightRectHeight);rect.fillRect(xView+activeWidth-1,waitingWidth+1,colorId,lightAlpha);rect.setYandH(lightRectHeight,darkRectHeight);rect.fillRect(xView+activeWidth-1,waitingWidth+1,colorId,alpha);rect.setYandH(0,height);}}
+rect.flush();if(async&&hadTopLevel){rect.setYandH(2,1);for(let i=lowSlice;i<slices.length;++i){const slice=slices[i];const x=slice.start;if(x>viewRWorld)break;if(!slice.isTopLevel)continue;const xView=dt.xWorldToView(x);let wView=1;if(slice.duration>0){const w=Math.max(slice.duration,0.000001);wView=Math.max(dt.xWorldVectorToView(w),1);}
+rect.fillRect(xView,wView,blackColorId,0.7);}
+rect.flush();}
+ctx.restore();}
+function drawInstantSlicesAsLines(ctx,dt,viewLWorld,viewRWorld,viewHeight,slices,lineWidthInPixels){const pixelRatio=window.devicePixelRatio||1;const height=viewHeight*pixelRatio;ctx.save();ctx.lineWidth=lineWidthInPixels*pixelRatio;const lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start;},viewLWorld);for(let i=lowSlice;i<slices.length;++i){const slice=slices[i];const x=slice.start;if(x>viewRWorld)break;ctx.strokeStyle=EventPresenter.getInstantSliceColor(slice);const xView=dt.xWorldToView(x);ctx.beginPath();ctx.moveTo(xView,0);ctx.lineTo(xView,height);ctx.stroke();}
+ctx.restore();}
+function drawLabels(ctx,dt,viewLWorld,viewRWorld,slices,async,fontSize,yOffset){const pixelRatio=window.devicePixelRatio||1;const pixWidth=dt.xViewVectorToWorld(1);ctx.save();ctx.textAlign='center';ctx.textBaseline='top';ctx.font=(fontSize*pixelRatio)+'px sans-serif';if(async){ctx.font='italic '+ctx.font;}
+const cY=yOffset*pixelRatio;const lowSlice=tr.b.findLowIndexInSortedArray(slices,function(slice){return slice.start+slice.duration;},viewLWorld);const quickDiscardThreshold=pixWidth*20;for(let i=lowSlice;i<slices.length;++i){const slice=slices[i];if(slice.start>viewRWorld)break;if(slice.duration<=quickDiscardThreshold)continue;const xLeftClipped=Math.max(slice.start,viewLWorld);const xRightClipped=Math.min(slice.start+slice.duration,viewRWorld);const visibleWidth=xRightClipped-xLeftClipped;const title=slice.title+
+(slice.didNotFinish?' (Did Not Finish)':'');let drawnTitle=title;let drawnWidth=elidedTitleCache.labelWidth(ctx,drawnTitle);const fullLabelWidth=elidedTitleCache.labelWidthWorld(ctx,drawnTitle,pixWidth);if(SHOULD_ELIDE_TEXT&&fullLabelWidth>visibleWidth){const elidedValues=elidedTitleCache.get(ctx,pixWidth,drawnTitle,drawnWidth,visibleWidth);drawnTitle=elidedValues.string;drawnWidth=elidedValues.width;}
+if(drawnWidth*pixWidth<visibleWidth){ctx.fillStyle=EventPresenter.getTextColor(slice);const cX=dt.xWorldToView((xLeftClipped+xRightClipped)/2);ctx.fillText(drawnTitle,cX,cY,drawnWidth);}}
+ctx.restore();}
+return{drawSlices,drawInstantSlicesAsLines,drawLabels,drawLine,drawTriangle,drawArrow,elidedTitleCache_:elidedTitleCache,THIN_SLICE_HEIGHT,};});'use strict';tr.exportTo('tr.ui',function(){function TimelineDisplayTransform(opt_that){if(opt_that){this.set(opt_that);return;}
+this.scaleX=1;this.panX=0;this.panY=0;}
+TimelineDisplayTransform.prototype={set(that){this.scaleX=that.scaleX;this.panX=that.panX;this.panY=that.panY;},clone(){return new TimelineDisplayTransform(this);},equals(that){let eq=true;if(that===undefined||that===null){return false;}
+eq&=this.panX===that.panX;eq&=this.panY===that.panY;eq&=this.scaleX===that.scaleX;return!!eq;},almostEquals(that){let eq=true;if(that===undefined||that===null){return false;}
+eq&=Math.abs(this.panX-that.panX)<0.001;eq&=Math.abs(this.panY-that.panY)<0.001;eq&=Math.abs(this.scaleX-that.scaleX)<0.001;return!!eq;},incrementPanXInViewUnits(xDeltaView){this.panX+=this.xViewVectorToWorld(xDeltaView);},xPanWorldPosToViewPos(worldX,viewX,viewWidth){if(typeof viewX==='string'){if(viewX==='left'){viewX=0;}else if(viewX==='center'){viewX=viewWidth/2;}else if(viewX==='right'){viewX=viewWidth-1;}else{throw new Error('viewX must be left|center|right or number.');}}
+this.panX=(viewX/this.scaleX)-worldX;},xPanWorldBoundsIntoView(worldMin,worldMax,viewWidth){if(this.xWorldToView(worldMin)<0){this.xPanWorldPosToViewPos(worldMin,'left',viewWidth);}else if(this.xWorldToView(worldMax)>viewWidth){this.xPanWorldPosToViewPos(worldMax,'right',viewWidth);}},xSetWorldBounds(worldMin,worldMax,viewWidth){const worldWidth=worldMax-worldMin;const scaleX=viewWidth/worldWidth;const panX=-worldMin;this.setPanAndScale(panX,scaleX);},setPanAndScale(p,s){this.scaleX=s;this.panX=p;},xWorldToView(x){return(x+this.panX)*this.scaleX;},xWorldVectorToView(x){return x*this.scaleX;},xViewToWorld(x){return(x/this.scaleX)-this.panX;},xViewVectorToWorld(x){return x/this.scaleX;}};return{TimelineDisplayTransform,};});'use strict';tr.exportTo('tr.ui',function(){function SnapIndicator(y,height){this.y=y;this.height=height;}
+function TimelineInterestRange(vp){this.viewport_=vp;this.range_=new tr.b.math.Range();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;}
+TimelineInterestRange.prototype={get isEmpty(){return this.range_.isEmpty;},reset(){this.range_.reset();this.leftSelected_=false;this.rightSelected_=false;this.leftSnapIndicator_=undefined;this.rightSnapIndicator_=undefined;this.viewport_.dispatchChangeEvent();},get min(){return this.range_.min;},set min(min){this.range_.min=min;this.viewport_.dispatchChangeEvent();},get max(){return this.range_.max;},set max(max){this.range_.max=max;this.viewport_.dispatchChangeEvent();},set(range){this.range_.reset();this.range_.addRange(range);this.viewport_.dispatchChangeEvent();},setMinAndMax(min,max){this.range_.min=min;this.range_.max=max;this.viewport_.dispatchChangeEvent();},get range(){return this.range_.range;},asRangeObject(){const range=new tr.b.math.Range();range.addRange(this.range_);return range;},get leftSelected(){return this.leftSelected_;},set leftSelected(leftSelected){if(this.leftSelected_===leftSelected)return;this.leftSelected_=leftSelected;this.viewport_.dispatchChangeEvent();},get rightSelected(){return this.rightSelected_;},set rightSelected(rightSelected){if(this.rightSelected_===rightSelected)return;this.rightSelected_=rightSelected;this.viewport_.dispatchChangeEvent();},get leftSnapIndicator(){return this.leftSnapIndicator_;},set leftSnapIndicator(leftSnapIndicator){this.leftSnapIndicator_=leftSnapIndicator;this.viewport_.dispatchChangeEvent();},get rightSnapIndicator(){return this.rightSnapIndicator_;},set rightSnapIndicator(rightSnapIndicator){this.rightSnapIndicator_=rightSnapIndicator;this.viewport_.dispatchChangeEvent();},draw(ctx,viewLWorld,viewRWorld,viewHeight){if(this.range_.isEmpty)return;const dt=this.viewport_.currentDisplayTransform;const markerLWorld=this.min;const markerRWorld=this.max;const markerLView=Math.round(dt.xWorldToView(markerLWorld));const markerRView=Math.round(dt.xWorldToView(markerRWorld));ctx.fillStyle='rgba(0, 0, 0, 0.2)';if(markerLWorld>viewLWorld){ctx.fillRect(dt.xWorldToView(viewLWorld),0,markerLView,viewHeight);}
+if(markerRWorld<viewRWorld){ctx.fillRect(markerRView,0,dt.xWorldToView(viewRWorld),viewHeight);}
+const pixelRatio=window.devicePixelRatio||1;ctx.lineWidth=Math.round(pixelRatio);if(this.range_.range>0){this.drawLine_(ctx,viewLWorld,viewRWorld,viewHeight,this.min,this.leftSelected_);this.drawLine_(ctx,viewLWorld,viewRWorld,viewHeight,this.max,this.rightSelected_);}else{this.drawLine_(ctx,viewLWorld,viewRWorld,viewHeight,this.min,this.leftSelected_||this.rightSelected_);}
+ctx.lineWidth=1;},drawLine_(ctx,viewLWorld,viewRWorld,height,ts,selected){if(ts<viewLWorld||ts>=viewRWorld)return;const dt=this.viewport_.currentDisplayTransform;const viewX=Math.round(dt.xWorldToView(ts));ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();tr.ui.b.drawLine(ctx,viewX,0,viewX,height);if(selected){ctx.strokeStyle='rgb(255, 0, 0)';}else{ctx.strokeStyle='rgb(0, 0, 0)';}
+ctx.stroke();ctx.restore();},drawIndicators(ctx,viewLWorld,viewRWorld){if(this.leftSnapIndicator_){this.drawIndicator_(ctx,viewLWorld,viewRWorld,this.range_.min,this.leftSnapIndicator_,this.leftSelected_);}
+if(this.rightSnapIndicator_){this.drawIndicator_(ctx,viewLWorld,viewRWorld,this.range_.max,this.rightSnapIndicator_,this.rightSelected_);}},drawIndicator_(ctx,viewLWorld,viewRWorld,xWorld,si,selected){const dt=this.viewport_.currentDisplayTransform;const viewX=Math.round(dt.xWorldToView(xWorld));ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);const pixelRatio=window.devicePixelRatio||1;const viewY=si.y*devicePixelRatio;const viewHeight=si.height*devicePixelRatio;const arrowSize=4*pixelRatio;if(selected){ctx.fillStyle='rgb(255, 0, 0)';}else{ctx.fillStyle='rgb(0, 0, 0)';}
+tr.ui.b.drawTriangle(ctx,viewX-arrowSize*0.75,viewY,viewX+arrowSize*0.75,viewY,viewX,viewY+arrowSize);ctx.fill();tr.ui.b.drawTriangle(ctx,viewX-arrowSize*0.75,viewY+viewHeight,viewX+arrowSize*0.75,viewY+viewHeight,viewX,viewY+viewHeight-arrowSize);ctx.fill();ctx.restore();}};return{SnapIndicator,TimelineInterestRange,};});'use strict';tr.exportTo('tr.ui.tracks',function(){function ContainerToTrackMap(){this.stableIdToTrackMap_={};}
+ContainerToTrackMap.prototype={addContainer(container,track){if(!track){throw new Error('Must provide a track.');}
+this.stableIdToTrackMap_[container.stableId]=track;},clear(){this.stableIdToTrackMap_={};},getTrackByStableId(stableId){return this.stableIdToTrackMap_[stableId];}};return{ContainerToTrackMap,};});'use strict';tr.exportTo('tr.ui.tracks',function(){function EventToTrackMap(){}
+EventToTrackMap.prototype={addEvent(event,track){if(!track){throw new Error('Must provide a track.');}
+this[event.guid]=track;}};return{EventToTrackMap,};});'use strict';tr.exportTo('tr.ui',function(){const TimelineDisplayTransform=tr.ui.TimelineDisplayTransform;const TimelineInterestRange=tr.ui.TimelineInterestRange;const IDEAL_MAJOR_MARK_DISTANCE_PX=150;const MAJOR_MARK_ROUNDING_FACTOR=100000;class AnimationControllerProxy{constructor(target){this.target_=target;}
+get panX(){return this.target_.currentDisplayTransform_.panX;}
+set panX(panX){this.target_.currentDisplayTransform_.panX=panX;}
+get panY(){return this.target_.currentDisplayTransform_.panY;}
+set panY(panY){this.target_.currentDisplayTransform_.panY=panY;}
+get scaleX(){return this.target_.currentDisplayTransform_.scaleX;}
+set scaleX(scaleX){this.target_.currentDisplayTransform_.scaleX=scaleX;}
+cloneAnimationState(){return this.target_.currentDisplayTransform_.clone();}
+xPanWorldPosToViewPos(xWorld,xView){this.target_.currentDisplayTransform_.xPanWorldPosToViewPos(xWorld,xView,this.target_.modelTrackContainer_.canvas.clientWidth);}}
+function TimelineViewport(parentEl){this.parentEl_=parentEl;this.modelTrackContainer_=undefined;this.currentDisplayTransform_=new TimelineDisplayTransform();this.initAnimationController_();this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highDetails_=false;this.gridTimebase_=0;this.gridStep_=1000/60;this.gridEnabled_=false;this.hasCalledSetupFunction_=false;this.onResize_=this.onResize_.bind(this);this.onModelTrackControllerScroll_=this.onModelTrackControllerScroll_.bind(this);this.timeMode_=TimelineViewport.TimeMode.TIME_IN_MS;this.majorMarkWorldPositions_=[];this.majorMarkUnit_=undefined;this.interestRange_=new TimelineInterestRange(this);this.eventToTrackMap_=new tr.ui.tracks.EventToTrackMap();this.containerToTrackMap=new tr.ui.tracks.ContainerToTrackMap();this.dispatchChangeEvent=this.dispatchChangeEvent.bind(this);}
+TimelineViewport.TimeMode={TIME_IN_MS:0,REVISIONS:1};TimelineViewport.prototype={__proto__:tr.b.EventTarget.prototype,get isAttachedToDocumentOrInTestMode(){if(this.parentEl_===undefined)return;return tr.ui.b.isElementAttachedToDocument(this.parentEl_);},onResize_(){this.dispatchChangeEvent();},dispatchChangeEvent(){tr.b.dispatchSimpleEvent(this,'change');},detach(){window.removeEventListener('resize',this.dispatchChangeEvent);},initAnimationController_(){this.dtAnimationController_=new tr.ui.b.AnimationController();this.dtAnimationController_.addEventListener('didtick',function(e){this.onCurentDisplayTransformChange_(e.oldTargetState);}.bind(this));this.dtAnimationController_.target=new AnimationControllerProxy(this);},get currentDisplayTransform(){return this.currentDisplayTransform_;},setDisplayTransformImmediately(displayTransform){this.dtAnimationController_.cancelActiveAnimation();const oldDisplayTransform=this.dtAnimationController_.target.cloneAnimationState();this.currentDisplayTransform_.set(displayTransform);this.onCurentDisplayTransformChange_(oldDisplayTransform);},queueDisplayTransformAnimation(animation){if(!(animation instanceof tr.ui.b.Animation)){throw new Error('animation must be instanceof tr.ui.b.Animation');}
+this.dtAnimationController_.queueAnimation(animation);},onCurentDisplayTransformChange_(oldDisplayTransform){if(this.modelTrackContainer_){this.currentDisplayTransform.panY=tr.b.math.clamp(this.currentDisplayTransform.panY,0,this.modelTrackContainer_.scrollHeight-
+this.modelTrackContainer_.clientHeight);}
+const changed=!this.currentDisplayTransform.equals(oldDisplayTransform);const yChanged=this.currentDisplayTransform.panY!==oldDisplayTransform.panY;if(yChanged){this.modelTrackContainer_.scrollTop=this.currentDisplayTransform.panY;}
+if(changed){this.dispatchChangeEvent();}},onModelTrackControllerScroll_(e){if(this.dtAnimationController_.activeAnimation&&this.dtAnimationController_.activeAnimation.affectsPanY){this.dtAnimationController_.cancelActiveAnimation();}
+const panY=this.modelTrackContainer_.scrollTop;this.currentDisplayTransform_.panY=panY;},get modelTrackContainer(){return this.modelTrackContainer_;},set modelTrackContainer(m){if(this.modelTrackContainer_){this.modelTrackContainer_.removeEventListener('scroll',this.onModelTrackControllerScroll_);}
+this.modelTrackContainer_=m;this.modelTrackContainer_.addEventListener('scroll',this.onModelTrackControllerScroll_);},get selectedFlowEvents(){return this.selectedFlowEvents_;},set selectedFlowEvents(selectedFlowEvents){this.selectedFlowEvents_=selectedFlowEvents;this.dispatchChangeEvent();},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;this.dispatchChangeEvent();},get highDetails(){return this.highDetails_;},set highDetails(highDetails){this.highDetails_=highDetails;this.dispatchChangeEvent();},get gridEnabled(){return this.gridEnabled_;},set gridEnabled(enabled){if(this.gridEnabled_===enabled)return;this.gridEnabled_=enabled&&true;this.dispatchChangeEvent();},get gridTimebase(){return this.gridTimebase_;},set gridTimebase(timebase){if(this.gridTimebase_===timebase)return;this.gridTimebase_=timebase;this.dispatchChangeEvent();},get gridStep(){return this.gridStep_;},get interestRange(){return this.interestRange_;},get majorMarkWorldPositions(){return this.majorMarkWorldPositions_;},get majorMarkUnit(){switch(this.timeMode_){case TimelineViewport.TimeMode.TIME_IN_MS:return tr.b.Unit.byName.timeInMsAutoFormat;case TimelineViewport.TimeMode.REVISIONS:return tr.b.Unit.byName.count;default:throw new Error('Cannot get Unit for unsupported time mode '+this.timeMode_);}},get timeMode(){return this.timeMode_;},set timeMode(mode){this.timeMode_=mode;this.dispatchChangeEvent();},updateMajorMarkData(viewLWorld,viewRWorld){const pixelRatio=window.devicePixelRatio||1;const dt=this.currentDisplayTransform;const idealMajorMarkDistancePix=IDEAL_MAJOR_MARK_DISTANCE_PX*pixelRatio;const idealMajorMarkDistanceWorld=dt.xViewVectorToWorld(idealMajorMarkDistancePix);const majorMarkDistanceWorld=tr.b.math.preferredNumberLargerThanMin(idealMajorMarkDistanceWorld);const firstMajorMark=Math.floor(viewLWorld/majorMarkDistanceWorld)*majorMarkDistanceWorld;this.majorMarkWorldPositions_=[];if(firstMajorMark/majorMarkDistanceWorld>1e15)return;for(let curX=firstMajorMark;curX<viewRWorld;curX+=majorMarkDistanceWorld){this.majorMarkWorldPositions_.push(Math.floor(MAJOR_MARK_ROUNDING_FACTOR*curX)/MAJOR_MARK_ROUNDING_FACTOR);}},drawMajorMarkLines(ctx,viewHeight){ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();for(const majorMark of this.majorMarkWorldPositions_){const x=this.currentDisplayTransform.xWorldToView(majorMark);tr.ui.b.drawLine(ctx,x,0,x,viewHeight);}
+ctx.strokeStyle='#ddd';ctx.stroke();ctx.restore();},drawGridLines(ctx,viewLWorld,viewRWorld,viewHeight){if(!this.gridEnabled)return;const dt=this.currentDisplayTransform;let x=this.gridTimebase;ctx.save();ctx.translate((Math.round(ctx.lineWidth)%2)/2,0);ctx.beginPath();while(x<viewRWorld){if(x>=viewLWorld){const vx=Math.floor(dt.xWorldToView(x));tr.ui.b.drawLine(ctx,vx,0,vx,viewHeight);}
+x+=this.gridStep;}
+ctx.strokeStyle='rgba(255, 0, 0, 0.25)';ctx.stroke();ctx.restore();},getShiftedSelection(selection,offset){const newSelection=new tr.model.EventSet();for(const event of selection){if(event instanceof tr.model.FlowEvent){if(offset>0){newSelection.push(event.endSlice);}else if(offset<0){newSelection.push(event.startSlice);}else{}
+continue;}
+const track=this.trackForEvent(event);track.addEventNearToProvidedEventToSelection(event,offset,newSelection);}
+if(newSelection.length===0)return undefined;return newSelection;},rebuildEventToTrackMap(){this.eventToTrackMap_=new tr.ui.tracks.EventToTrackMap();this.modelTrackContainer_.addEventsToTrackMap(this.eventToTrackMap_);},rebuildContainerToTrackMap(){this.containerToTrackMap.clear();this.modelTrackContainer_.addContainersToTrackMap(this.containerToTrackMap);},trackForEvent(event){return this.eventToTrackMap_[event.guid];}};return{TimelineViewport,};});'use strict';tr.exportTo('tr.c',function(){const BrushingState=tr.ui.b.BrushingState;const EventSet=tr.model.EventSet;const SelectionState=tr.model.SelectionState;const Viewport=tr.ui.TimelineViewport;function BrushingStateController(timelineView){tr.b.EventTarget.call(this);this.timelineView_=timelineView;this.currentBrushingState_=new BrushingState();this.onPopState_=this.onPopState_.bind(this);this.historyEnabled_=false;this.selections_={};}
+BrushingStateController.prototype={__proto__:tr.b.EventTarget.prototype,dispatchChangeEvent_(){const e=new tr.b.Event('change',false,false);this.dispatchEvent(e);},get model(){if(!this.timelineView_){return undefined;}
+return this.timelineView_.model;},get trackView(){if(!this.timelineView_){return undefined;}
+return this.timelineView_.trackView;},get viewport(){if(!this.timelineView_){return undefined;}
+if(!this.timelineView_.trackView){return undefined;}
+return this.timelineView_.trackView.viewport;},get historyEnabled(){return this.historyEnabled_;},set historyEnabled(historyEnabled){this.historyEnabled_=!!historyEnabled;if(historyEnabled){window.addEventListener('popstate',this.onPopState_);}else{window.removeEventListener('popstate',this.onPopState_);}},modelWillChange(){if(this.currentBrushingState_.isAppliedToModel){this.currentBrushingState_.unapplyFromEventSelectionStates();}},modelDidChange(){this.selections_={};this.currentBrushingState_=new BrushingState();this.currentBrushingState_.applyToEventSelectionStates(this.model);const e=new tr.b.Event('model-changed',false,false);this.dispatchEvent(e);this.dispatchChangeEvent_();},onUserInitiatedSelectionChange_(){const selection=this.selection;if(this.historyEnabled){this.selections_[selection.guid]=selection;const state={selection_guid:selection.guid};window.history.pushState(state,document.title);}},onPopState_(e){if(e.state===null)return;const selection=this.selections_[e.state.selection_guid];if(selection){const newState=this.currentBrushingState_.clone();newState.selection=selection;this.currentBrushingState=newState;}
+e.stopPropagation();},get selection(){return this.currentBrushingState_.selection;},get findMatches(){return this.currentBrushingState_.findMatches;},get selectionOfInterest(){return this.currentBrushingState_.selectionOfInterest;},get currentBrushingState(){return this.currentBrushingState_;},set currentBrushingState(newBrushingState){if(newBrushingState.isAppliedToModel){throw new Error('Cannot apply this state, it is applied');}
+const hasValueChanged=!this.currentBrushingState_.equals(newBrushingState);if(newBrushingState!==this.currentBrushingState_&&!hasValueChanged){if(this.currentBrushingState_.isAppliedToModel){this.currentBrushingState_.transferModelOwnershipToClone(newBrushingState);}
+this.currentBrushingState_=newBrushingState;return;}
+if(this.currentBrushingState_.isAppliedToModel){this.currentBrushingState_.unapplyFromEventSelectionStates();}
+this.currentBrushingState_=newBrushingState;this.currentBrushingState_.applyToEventSelectionStates(this.model);this.dispatchChangeEvent_();},addAllEventsMatchingFilterToSelectionAsTask(filter,selection){const timelineView=this.timelineView_.trackView;if(!timelineView){return new tr.b.Task();}
+return timelineView.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);},findTextChangedTo(allPossibleMatches){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.findMatches=allPossibleMatches;this.currentBrushingState=newBrushingState;},findFocusChangedTo(currentFocus){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=currentFocus;this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},findTextCleared(){if(this.xNavStringMarker_!==undefined){this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=undefined;}
+if(this.guideLineAnnotation_!==undefined){this.model.removeAnnotation(this.guideLineAnnotation_);this.guideLineAnnotation_=undefined;}
+const newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=new EventSet();newBrushingState.findMatches=new EventSet();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},uiStateFromString(string){return tr.ui.b.UIState.fromUserFriendlyString(this.model,this.viewport,string);},navToPosition(uiState,showNavLine){this.trackView.navToPosition(uiState,showNavLine);},changeSelectionFromTimeline(selection){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new EventSet();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},showScriptControlSelection(selection){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new EventSet();this.currentBrushingState=newBrushingState;},changeSelectionFromRequestSelectionChangeEvent(selection){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.selection=selection;newBrushingState.findMatches=new EventSet();this.currentBrushingState=newBrushingState;this.onUserInitiatedSelectionChange_();},changeAnalysisViewRelatedEvents(eventSet){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.analysisViewRelatedEvents=eventSet;this.currentBrushingState=newBrushingState;},changeAnalysisLinkHoveredEvents(eventSet){const newBrushingState=this.currentBrushingState_.clone();newBrushingState.analysisLinkHoveredEvents=eventSet;this.currentBrushingState=newBrushingState;},getViewSpecificBrushingState(viewId){return this.currentBrushingState.viewSpecificBrushingStates[viewId];},changeViewSpecificBrushingState(viewId,newState){const oldStates=this.currentBrushingState_.viewSpecificBrushingStates;const newStates={};for(const id in oldStates){newStates[id]=oldStates[id];}
+if(newState===undefined){delete newStates[viewId];}else{newStates[viewId]=newState;}
+const newBrushingState=this.currentBrushingState_.clone();newBrushingState.viewSpecificBrushingStates=newStates;this.currentBrushingState=newBrushingState;}};BrushingStateController.getControllerForElement=function(element){if(tr.isHeadless){throw new Error('Unsupported');}
+let currentElement=element;while(currentElement){if(currentElement.brushingStateController){return currentElement.brushingStateController;}
+if(currentElement.parentElement){currentElement=currentElement.parentElement;continue;}
+let currentNode=currentElement;while(Polymer.dom(currentNode).parentNode){currentNode=Polymer.dom(currentNode).parentNode;}
+currentElement=currentNode.host;}
+return undefined;};return{BrushingStateController,};});'use strict';Polymer({is:'tr-ui-a-analysis-link',properties:{href:{type:String}},listeners:{'click':'onClicked_','mouseenter':'onMouseEnter_','mouseleave':'onMouseLeave_'},ready(){this.selection_=undefined;},attached(){this.controller_=tr.c.BrushingStateController.getControllerForElement(this);},detached(){this.clearHighlight_();this.controller_=undefined;},set color(c){this.style.color=c;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;Polymer.dom(this).textContent=selection.userFriendlyName;},setSelectionAndContent(selection,opt_textContent){this.selection_=selection;if(opt_textContent){Polymer.dom(this).textContent=opt_textContent;}},getCurrentSelection_(){if(typeof this.selection_==='function'){return this.selection_();}
+return this.selection_;},setHighlight_(opt_eventSet){if(this.controller_){this.controller_.changeAnalysisLinkHoveredEvents(opt_eventSet);}},clearHighlight_(opt_eventSet){this.setHighlight_();},onClicked_(clickEvent){if(!this.selection_)return;clickEvent.stopPropagation();const event=new tr.model.RequestSelectionChangeEvent();event.selection=this.getCurrentSelection_();this.dispatchEvent(event);},onMouseEnter_(){this.setHighlight_(this.getCurrentSelection_());},onMouseLeave_(){this.clearHighlight_();}});'use strict';tr.exportTo('tr.ui.b',function(){const TableFormat={};TableFormat.SelectionMode={NONE:0,ROW:1,CELL:2};TableFormat.HighlightStyle={DEFAULT:0,NONE:1,LIGHT:2,DARK:3};TableFormat.ColumnAlignment={LEFT:0,RIGHT:1};return{TableFormat,};});'use strict';(function(){const RIGHT_ARROW=String.fromCharCode(0x25b6);const UNSORTED_ARROW=String.fromCharCode(0x25BF);const ASCENDING_ARROW=String.fromCharCode(0x25B4);const DESCENDING_ARROW=String.fromCharCode(0x25BE);const SelectionMode=tr.ui.b.TableFormat.SelectionMode;const SelectionModeValues=new Set(Object.values(SelectionMode));const HighlightStyle=tr.ui.b.TableFormat.HighlightStyle;const HighlightStyleValues=new Set(Object.values(HighlightStyle));const ColumnAlignment=tr.ui.b.TableFormat.ColumnAlignment;const ColumnAlignmentValues=new Set(Object.values(ColumnAlignment));Polymer({is:'tr-ui-b-table',created(){this.selectionMode_=SelectionMode.NONE;this.rowHighlightStyle_=HighlightStyle.DEFAULT;this.cellHighlightStyle_=HighlightStyle.DEFAULT;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=new WeakMap();this.tableFooterRows_=[];this.tableFooterRowsInfo_=new WeakMap();this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];this.showHeader_=true;this.emptyValue_=undefined;this.subRowsPropertyName_='subRows';this.customizeTableRowCallback_=undefined;this.defaultExpansionStateCallback_=undefined;this.userCanModifySortOrder_=true;this.computedFontSizePx_=undefined;},ready(){this.$.body.addEventListener('keydown',this.onKeyDown_.bind(this),true);this.$.body.addEventListener('focus',this.onFocus_.bind(this),true);},clear(){this.selectionMode_=SelectionMode.NONE;this.rowHighlightStyle_=HighlightStyle.DEFAULT;this.cellHighlightStyle_=HighlightStyle.DEFAULT;this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;Polymer.dom(this).textContent='';this.tableColumns_=[];this.tableRows_=[];this.tableRowsInfo_=new WeakMap();this.tableFooterRows_=[];this.tableFooterRowsInfo_=new WeakMap();this.sortColumnIndex_=undefined;this.sortDescending_=false;this.columnsWithExpandButtons_=[];this.headerCells_=[];this.showHeader_=true;this.emptyValue_=undefined;this.subRowsPropertyName_='subRows';this.defaultExpansionStateCallback_=undefined;this.userCanModifySortOrder_=true;},set zebra(zebra){if(zebra){this.setAttribute('zebra',true);}else{this.removeAttribute('zebra');}},get zebra(){return this.getAttribute('zebra');},get showHeader(){return this.showHeader_;},set showHeader(showHeader){this.showHeader_=showHeader;this.scheduleRebuildHeaders_();},set subRowsPropertyName(name){this.subRowsPropertyName_=name;},set defaultExpansionStateCallback(cb){this.defaultExpansionStateCallback_=cb;this.scheduleRebuildBody_();},set customizeTableRowCallback(cb){this.customizeTableRowCallback_=cb;this.scheduleRebuildBody_();},get emptyValue(){return this.emptyValue_;},set emptyValue(emptyValue){const previousEmptyValue=this.emptyValue_;this.emptyValue_=emptyValue;if(this.tableRows_.length===0&&emptyValue!==previousEmptyValue){this.scheduleRebuildBody_();}},set tableColumns(columns){let columnsWithExpandButtons=[];for(let i=0;i<columns.length;i++){if(columns[i].showExpandButtons){columnsWithExpandButtons.push(i);}}
+if(columnsWithExpandButtons.length===0){columnsWithExpandButtons=[0];}
+for(let i=0;i<columns.length;i++){const colInfo=columns[i];if(colInfo.width===undefined)continue;const hasExpandButton=columnsWithExpandButtons.includes(i);const w=colInfo.width;if(w){if(/\d+px/.test(w)){continue;}else if(/\d+%/.test(w)){if(hasExpandButton){throw new Error('Columns cannot be %-sized and host '+' an expand button');}}else{throw new Error('Unrecognized width string');}}}
+let sortIndex=undefined;const currentSortColumn=this.tableColumns[this.sortColumnIndex_];if(currentSortColumn){for(const[i,column]of columns.entries()){if(currentSortColumn.title===column.title){sortIndex=i;break;}}}
+this.tableColumns_=columns;this.headerCells_=[];this.columnsWithExpandButtons_=columnsWithExpandButtons;this.scheduleRebuildHeaders_();this.sortColumnIndex=sortIndex;this.tableRows=this.tableRows_;},get tableColumns(){return this.tableColumns_;},set tableRows(rows){this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;this.tableRows_=rows;this.tableRowsInfo_=new WeakMap();this.scheduleRebuildBody_();},get tableRows(){return this.tableRows_;},set footerRows(rows){this.tableFooterRows_=rows;this.tableFooterRowsInfo_=new WeakMap();this.scheduleRebuildFooter_();},get footerRows(){return this.tableFooterRows_;},get userCanModifySortOrder(){return this.userCanModifySortOrder_;},set userCanModifySortOrder(userCanModifySortOrder){const newUserCanModifySortOrder=!!userCanModifySortOrder;if(newUserCanModifySortOrder===this.userCanModifySortOrder_){return;}
+this.userCanModifySortOrder_=newUserCanModifySortOrder;this.scheduleRebuildHeaders_();},set sortColumnIndex(number){if(number===this.sortColumnIndex_)return;if(number!==undefined){if(this.tableColumns_.length<=number){throw new Error('Column number '+number+' is out of bounds.');}
+if(!this.tableColumns_[number].cmp){throw new Error('Column '+number+' does not have a comparator.');}}
+this.sortColumnIndex_=number;this.updateHeaderArrows_();this.scheduleRebuildBody_();this.dispatchSortingChangedEvent_();},get sortColumnIndex(){return this.sortColumnIndex_;},set sortDescending(value){const newValue=!!value;if(newValue!==this.sortDescending_){this.sortDescending_=newValue;this.updateHeaderArrows_();this.scheduleRebuildBody_();this.dispatchSortingChangedEvent_();}},get sortDescending(){return this.sortDescending_;},updateHeaderArrows_(){for(let i=0;i<this.headerCells_.length;i++){const headerCell=this.headerCells_[i];const isColumnCurrentlySorted=i===this.sortColumnIndex_;if(!this.tableColumns_[i].cmp||(!this.userCanModifySortOrder_&&!isColumnCurrentlySorted)){headerCell.sideContent='';continue;}
+if(!isColumnCurrentlySorted){headerCell.sideContent=UNSORTED_ARROW;headerCell.sideContentDisabled=false;continue;}
+headerCell.sideContent=this.sortDescending_?DESCENDING_ARROW:ASCENDING_ARROW;headerCell.sideContentDisabled=!this.userCanModifySortOrder_;}},generateHeaderColumns_(){const selectedTableColumnIndex=this.selectedTableColumnIndex;Polymer.dom(this.$.cols).textContent='';for(let i=0;i<this.tableColumns_.length;++i){const colElement=document.createElement('col');if(i===selectedTableColumnIndex){colElement.setAttribute('selected',true);}
+Polymer.dom(this.$.cols).appendChild(colElement);}
+this.headerCells_=[];Polymer.dom(this.$.head).textContent='';if(!this.showHeader_)return;const tr=this.appendNewElement_(this.$.head,'tr');for(let i=0;i<this.tableColumns_.length;i++){const td=this.appendNewElement_(tr,'td');const headerCell=document.createElement('tr-ui-b-table-header-cell');headerCell.column=this.tableColumns_[i];if(this.tableColumns_[i].cmp){const isColumnCurrentlySorted=i===this.sortColumnIndex_;if(isColumnCurrentlySorted){headerCell.sideContent=this.sortDescending_?DESCENDING_ARROW:ASCENDING_ARROW;if(!this.userCanModifySortOrder_){headerCell.sideContentDisabled=true;}}
+if(this.userCanModifySortOrder_){Polymer.dom(td).classList.add('sensitive');if(!isColumnCurrentlySorted){headerCell.sideContent=UNSORTED_ARROW;}
+headerCell.tapCallback=this.createSortCallback_(i);}}
+Polymer.dom(td).appendChild(headerCell);this.headerCells_.push(headerCell);}},applySizes_(){if(this.tableRows_.length===0&&!this.showHeader)return;let rowToRemoveSizing;let rowToSize;if(this.showHeader){rowToSize=Polymer.dom(this.$.head).children[0];rowToRemoveSizing=Polymer.dom(this.$.body).children[0];}else{rowToSize=Polymer.dom(this.$.body).children[0];rowToRemoveSizing=Polymer.dom(this.$.head).children[0];}
+for(let i=0;i<this.tableColumns_.length;i++){if(rowToRemoveSizing&&Polymer.dom(rowToRemoveSizing).children[i]){const tdToRemoveSizing=Polymer.dom(rowToRemoveSizing).children[i];tdToRemoveSizing.style.minWidth='';tdToRemoveSizing.style.width='';}
+const td=Polymer.dom(rowToSize).children[i];let delta;if(this.columnsWithExpandButtons_.includes(i)){td.style.paddingLeft=this.basicIndentation_+'px';delta=this.basicIndentation_+'px';}else{delta=undefined;}
+function calc(base,delta){if(delta){return'calc('+base+' - '+delta+')';}
+return base;}
+const w=this.tableColumns_[i].width;if(w){if(/\d+px/.test(w)){td.style.minWidth=calc(w,delta);}else if(/\d+%/.test(w)){td.style.width=w;}else{throw new Error('Unrecognized width string: '+w);}}}},createSortCallback_(columnNumber){return function(){if(!this.userCanModifySortOrder_)return;const previousIndex=this.sortColumnIndex;this.sortColumnIndex=columnNumber;if(previousIndex!==columnNumber){this.sortDescending=false;}else{this.sortDescending=!this.sortDescending;}}.bind(this);},generateTableRowNodes_(tableSection,userRows,rowInfoMap,indentation,lastAddedRow,parentRowInfo){if(this.sortColumnIndex_!==undefined&&tableSection===this.$.body){userRows=userRows.slice();userRows.sort(function(rowA,rowB){let c=this.tableColumns_[this.sortColumnIndex_].cmp(rowA,rowB);if(this.sortDescending_){c=-c;}
+return c;}.bind(this));}
+for(let i=0;i<userRows.length;i++){const userRow=userRows[i];const rowInfo=this.getOrCreateRowInfoFor_(rowInfoMap,userRow,parentRowInfo);const htmlNode=this.getHTMLNodeForRowInfo_(tableSection,rowInfo,rowInfoMap,indentation);if(lastAddedRow===undefined){Polymer.dom(tableSection).insertBefore(htmlNode,Polymer.dom(tableSection).firstChild);}else{const nextSiblingOfLastAdded=Polymer.dom(lastAddedRow).nextSibling;Polymer.dom(tableSection).insertBefore(htmlNode,nextSiblingOfLastAdded);}
+lastAddedRow=htmlNode;if(!rowInfo.isExpanded)continue;lastAddedRow=this.generateTableRowNodes_(tableSection,userRow[this.subRowsPropertyName_],rowInfoMap,indentation+1,lastAddedRow,rowInfo);}
+return lastAddedRow;},getOrCreateRowInfoFor_(rowInfoMap,userRow,parentRowInfo){let rowInfo=undefined;if(rowInfoMap.has(userRow)){rowInfo=rowInfoMap.get(userRow);}else{rowInfo={userRow,htmlNode:undefined,parentRowInfo};rowInfoMap.set(userRow,rowInfo);}
+rowInfo.isExpanded=this.getExpandedForUserRow_(userRow);return rowInfo;},customizeTableRow_(userRow,trElement){if(!this.customizeTableRowCallback_)return;this.customizeTableRowCallback_(userRow,trElement);},get basicIndentation_(){if(this.computedFontSizePx_===undefined){this.computedFontSizePx_=parseInt(getComputedStyle(this).fontSize)||16;}
+return this.computedFontSizePx_-2;},getHTMLNodeForRowInfo_(tableSection,rowInfo,rowInfoMap,indentation){if(rowInfo.htmlNode){this.customizeTableRow_(rowInfo.userRow,rowInfo.htmlNode);return rowInfo.htmlNode;}
+const INDENT_SPACE=indentation*16;const INDENT_SPACE_NO_BUTTON=indentation*16+this.basicIndentation_;const trElement=this.ownerDocument.createElement('tr');rowInfo.htmlNode=trElement;rowInfo.indentation=indentation;trElement.rowInfo=rowInfo;this.customizeTableRow_(rowInfo.userRow,trElement);const isBodyRow=tableSection===this.$.body;const isExpandableRow=rowInfo.userRow[this.subRowsPropertyName_]&&rowInfo.userRow[this.subRowsPropertyName_].length;for(let i=0;i<this.tableColumns_.length;){const td=this.appendNewElement_(trElement,'td');td.columnIndex=i;const column=this.tableColumns_[i];const value=column.value(rowInfo.userRow);const colSpan=column.colSpan?column.colSpan:1;td.style.colSpan=colSpan;switch(column.align){case undefined:case ColumnAlignment.LEFT:break;case ColumnAlignment.RIGHT:td.style.textAlign='right';break;default:throw new Error('Invalid alignment of column at index='+i+': '+column.align);}
+if(this.doesColumnIndexSupportSelection(i)){Polymer.dom(td).classList.add('supports-selection');}
+if(this.columnsWithExpandButtons_.includes(i)){if(rowInfo.userRow[this.subRowsPropertyName_]&&rowInfo.userRow[this.subRowsPropertyName_].length>0){td.style.paddingLeft=INDENT_SPACE+'px';td.style.display='flex';const expandButton=this.appendNewElement_(td,'expand-button');Polymer.dom(expandButton).textContent=RIGHT_ARROW;if(rowInfo.isExpanded){Polymer.dom(expandButton).classList.add('button-expanded');}}else{td.style.paddingLeft=INDENT_SPACE_NO_BUTTON+'px';}}
+if(value!==undefined){Polymer.dom(td).appendChild(tr.ui.b.asHTMLOrTextNode(value,this.ownerDocument));}
+td.addEventListener('click',function(i,clickEvent){clickEvent.preventDefault();if(!isBodyRow&&!isExpandableRow)return;clickEvent.stopPropagation();if(clickEvent.target.tagName==='EXPAND-BUTTON'){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);return;}
+if(isBodyRow&&this.selectionMode_!==SelectionMode.NONE){let shouldSelect=false;let shouldFocus=false;switch(this.selectionMode_){case SelectionMode.ROW:shouldSelect=this.selectedTableRowInfo_!==rowInfo;shouldFocus=true;break;case SelectionMode.CELL:if(this.doesColumnIndexSupportSelection(i)){shouldSelect=this.selectedTableRowInfo_!==rowInfo||this.selectedColumnIndex_!==i;shouldFocus=true;}
+break;default:throw new Error('Invalid selection mode '+
+this.selectionMode_);}
+if(shouldFocus){this.focus();}
+if(shouldSelect){this.didTableRowInfoGetClicked_(rowInfo,i);return;}}
+if(isExpandableRow){this.setExpandedForUserRow_(tableSection,rowInfoMap,rowInfo.userRow,!rowInfo.isExpanded);}}.bind(this,i));if(isBodyRow){td.addEventListener('dblclick',function(i,e){e.stopPropagation();this.dispatchStepIntoEvent_(rowInfo,i);}.bind(this,i));}
+i+=colSpan;}
+return rowInfo.htmlNode;},removeSubNodes_(tableSection,rowInfo,rowInfoMap){if(rowInfo.userRow[this.subRowsPropertyName_]===undefined)return;for(let i=0;i<rowInfo.userRow[this.subRowsPropertyName_].length;i++){const subRow=rowInfo.userRow[this.subRowsPropertyName_][i];const subRowInfo=rowInfoMap.get(subRow);if(!subRowInfo)continue;const subNode=subRowInfo.htmlNode;if(subNode&&Polymer.dom(subNode).parentNode===tableSection){Polymer.dom(tableSection).removeChild(subNode);this.removeSubNodes_(tableSection,subRowInfo,rowInfoMap);}}},scheduleRebuildHeaders_(){this.headerDirty_=true;this.scheduleRebuild_();},scheduleRebuildBody_(){this.bodyDirty_=true;this.scheduleRebuild_();},scheduleRebuildFooter_(){this.footerDirty_=true;this.scheduleRebuild_();},scheduleRebuild_(){if(this.rebuildPending_)return;this.rebuildPending_=true;setTimeout(function(){this.rebuildPending_=false;this.rebuild();}.bind(this),0);},rebuildIfNeeded_(){this.rebuild();},rebuild(){const wasBodyOrHeaderDirty=this.headerDirty_||this.bodyDirty_;if(this.headerDirty_){this.generateHeaderColumns_();this.headerDirty_=false;}
+if(this.bodyDirty_){Polymer.dom(this.$.body).textContent='';this.generateTableRowNodes_(this.$.body,this.tableRows_,this.tableRowsInfo_,0,undefined,undefined);if(this.tableRows_.length===0&&this.emptyValue_!==undefined){const trElement=this.ownerDocument.createElement('tr');Polymer.dom(this.$.body).appendChild(trElement);Polymer.dom(trElement).classList.add('empty-row');const td=this.ownerDocument.createElement('td');Polymer.dom(trElement).appendChild(td);td.colSpan=this.tableColumns_.length;const emptyValue=this.emptyValue_;Polymer.dom(td).appendChild(tr.ui.b.asHTMLOrTextNode(emptyValue,this.ownerDocument));}
+this.bodyDirty_=false;}
+if(wasBodyOrHeaderDirty)this.applySizes_();if(this.footerDirty_){Polymer.dom(this.$.foot).textContent='';this.generateTableRowNodes_(this.$.foot,this.tableFooterRows_,this.tableFooterRowsInfo_,0,undefined,undefined);if(this.tableFooterRowsInfo_.length){Polymer.dom(this.$.body).classList.add('has-footer');}else{Polymer.dom(this.$.body).classList.remove('has-footer');}
+this.footerDirty_=false;}},appendNewElement_(parent,tagName){const element=parent.ownerDocument.createElement(tagName);Polymer.dom(parent).appendChild(element);return element;},getExpandedForTableRow(userRow){this.rebuildIfNeeded_();const rowInfo=this.tableRowsInfo_.get(userRow);if(rowInfo===undefined){throw new Error('Row has not been seen, must expand its parents');}
+return rowInfo.isExpanded;},getExpandedForUserRow_(userRow){if(userRow[this.subRowsPropertyName_]===undefined){return false;}
+if(userRow[this.subRowsPropertyName_].length===0){return false;}
+if(userRow.isExpanded){return true;}
+if((userRow.isExpanded!==undefined)&&(userRow.isExpanded===false)){return false;}
+const rowInfo=this.tableRowsInfo_.get(userRow);if(rowInfo&&rowInfo.isExpanded){return true;}
+if(this.defaultExpansionStateCallback_===undefined){return false;}
+let parentUserRow=undefined;if(rowInfo&&rowInfo.parentRowInfo){parentUserRow=rowInfo.parentRowInfo.userRow;}
+return this.defaultExpansionStateCallback_(userRow,parentUserRow);},setExpandedForTableRow(userRow,expanded){this.rebuildIfNeeded_();const rowInfo=this.tableRowsInfo_.get(userRow);if(rowInfo===undefined){throw new Error('Row has not been seen, must expand its parents');}
+return this.setExpandedForUserRow_(this.$.body,this.tableRowsInfo_,userRow,expanded);},setExpandedForUserRow_(tableSection,rowInfoMap,userRow,expanded){this.rebuildIfNeeded_();const rowInfo=rowInfoMap.get(userRow);if(rowInfo===undefined){throw new Error('Row has not been seen, must expand its parents');}
+const wasExpanded=rowInfo.isExpanded;rowInfo.isExpanded=!!expanded;if(rowInfo.htmlNode===undefined)return;if(rowInfo.htmlNode.parentElement!==tableSection){return;}
+const expandButton=Polymer.dom(rowInfo.htmlNode).querySelector('expand-button');if(rowInfo.isExpanded){Polymer.dom(expandButton).classList.add('button-expanded');const lastAddedRow=rowInfo.htmlNode;if(rowInfo.userRow[this.subRowsPropertyName_]){this.generateTableRowNodes_(tableSection,rowInfo.userRow[this.subRowsPropertyName_],rowInfoMap,rowInfo.indentation+1,lastAddedRow,rowInfo);}}else{Polymer.dom(expandButton).classList.remove('button-expanded');this.removeSubNodes_(tableSection,rowInfo,rowInfoMap);}
+if(wasExpanded!==rowInfo.isExpanded){const e=new tr.b.Event('row-expanded-changed');e.row=rowInfo.userRow;this.dispatchEvent(e);}
+this.maybeUpdateSelectedRow_();},get selectionMode(){return this.selectionMode_;},set selectionMode(selectionMode){if(!SelectionModeValues.has(selectionMode)){throw new Error('Invalid selection mode '+selectionMode);}
+this.rebuildIfNeeded_();this.selectionMode_=selectionMode;this.didSelectionStateChange_();},get rowHighlightStyle(){return this.rowHighlightStyle_;},set rowHighlightStyle(rowHighlightStyle){if(!HighlightStyleValues.has(rowHighlightStyle)){throw new Error('Invalid row highlight style '+rowHighlightStyle);}
+this.rebuildIfNeeded_();this.rowHighlightStyle_=rowHighlightStyle;this.didSelectionStateChange_();},get resolvedRowHighlightStyle(){if(this.rowHighlightStyle_!==HighlightStyle.DEFAULT){return this.rowHighlightStyle_;}
+switch(this.selectionMode_){case SelectionMode.NONE:return HighlightStyle.NONE;case SelectionMode.ROW:return HighlightStyle.DARK;case SelectionMode.CELL:return HighlightStyle.LIGHT;default:throw new Error('Invalid selection mode '+selectionMode);}},get cellHighlightStyle(){return this.cellHighlightStyle_;},set cellHighlightStyle(cellHighlightStyle){if(!HighlightStyleValues.has(cellHighlightStyle)){throw new Error('Invalid cell highlight style '+cellHighlightStyle);}
+this.rebuildIfNeeded_();this.cellHighlightStyle_=cellHighlightStyle;this.didSelectionStateChange_();},get resolvedCellHighlightStyle(){if(this.cellHighlightStyle_!==HighlightStyle.DEFAULT){return this.cellHighlightStyle_;}
+switch(this.selectionMode_){case SelectionMode.NONE:case SelectionMode.ROW:return HighlightStyle.NONE;case SelectionMode.CELL:return HighlightStyle.DARK;default:throw new Error('Invalid selection mode '+selectionMode);}},setHighlightStyle_(highlightAttribute,resolvedHighlightStyle){switch(resolvedHighlightStyle){case HighlightStyle.NONE:Polymer.dom(this.$.body).removeAttribute(highlightAttribute);break;case HighlightStyle.LIGHT:Polymer.dom(this.$.body).setAttribute(highlightAttribute,'light');break;case HighlightStyle.DARK:Polymer.dom(this.$.body).setAttribute(highlightAttribute,'dark');break;default:throw new Error('Invalid resolved highlight style '+
+resolvedHighlightStyle);}},didSelectionStateChange_(){this.setHighlightStyle_('row-highlight-style',this.resolvedRowHighlightStyle);this.setHighlightStyle_('cell-highlight-style',this.resolvedCellHighlightStyle);this.removeSelectedState_();switch(this.selectionMode_){case SelectionMode.ROW:Polymer.dom(this.$.body).setAttribute('selection-mode','row');Polymer.dom(this.$.body).setAttribute('tabindex',0);this.selectedColumnIndex_=undefined;break;case SelectionMode.CELL:Polymer.dom(this.$.body).setAttribute('selection-mode','cell');Polymer.dom(this.$.body).setAttribute('tabindex',0);if(this.selectedTableRowInfo_&&this.selectedColumnIndex_===undefined){const i=this.getFirstSelectableColumnIndex_();if(i===-1){this.selectedTableRowInfo_=undefined;}else{this.selectedColumnIndex_=i;}}
+break;case SelectionMode.NONE:Polymer.dom(this.$.body).removeAttribute('selection-mode');Polymer.dom(this.$.body).removeAttribute('tabindex');this.$.body.blur();this.selectedTableRowInfo_=undefined;this.selectedColumnIndex_=undefined;break;default:throw new Error('Invalid selection mode '+this.selectionMode_);}
+this.maybeUpdateSelectedRow_();},maybeUpdateSelectedRow_(){if(this.selectedTableRowInfo_===undefined)return;function isVisible(rowInfo){if(!rowInfo.htmlNode)return false;return!!rowInfo.htmlNode.parentElement;}
+if(isVisible(this.selectedTableRowInfo_)){this.updateSelectedState_();return;}
+this.removeSelectedState_();let curRowInfo=this.selectedTableRowInfo_;while(curRowInfo&&!isVisible(curRowInfo)){curRowInfo=curRowInfo.parentRowInfo;}
+this.selectedTableRowInfo_=curRowInfo;if(this.selectedTableRowInfo_){this.updateSelectedState_();}else{this.selectedColumnIndex_=undefined;}},didTableRowInfoGetClicked_(rowInfo,columnIndex){switch(this.selectionMode_){case SelectionMode.NONE:return;case SelectionMode.CELL:if(!this.doesColumnIndexSupportSelection(columnIndex)){return;}
+if(this.selectedColumnIndex!==columnIndex){this.selectedColumnIndex=columnIndex;}
+case SelectionMode.ROW:if(this.selectedTableRowInfo_!==rowInfo){this.selectedTableRow=rowInfo.userRow;}}},dispatchStepIntoEvent_(rowInfo,columnIndex){const e=new tr.b.Event('step-into');e.tableRow=rowInfo.userRow;e.tableColumn=this.tableColumns_[columnIndex];e.columnIndex=columnIndex;this.dispatchEvent(e);},get selectedCell(){const row=this.selectedTableRow;const columnIndex=this.selectedColumnIndex;if(row===undefined||columnIndex===undefined||this.tableColumns_.length<=columnIndex){return undefined;}
+const column=this.tableColumns_[columnIndex];return{row,column,value:column.value(row)};},get selectedTableColumnIndex(){const cols=Polymer.dom(this.$.cols).children;for(let i=0;i<cols.length;++i){if(cols[i].getAttribute('selected')){return i;}}
+return undefined;},set selectedTableColumnIndex(selectedIndex){const cols=Polymer.dom(this.$.cols).children;for(let i=0;i<cols.length;++i){if(i===selectedIndex){cols[i].setAttribute('selected',true);}else{cols[i].removeAttribute('selected');}}},get selectedTableRow(){if(!this.selectedTableRowInfo_)return undefined;return this.selectedTableRowInfo_.userRow;},set selectedTableRow(userRow){this.rebuildIfNeeded_();if(this.selectionMode_===SelectionMode.NONE){throw new Error('Selection is off.');}
+let rowInfo;if(userRow===undefined){rowInfo=undefined;}else{rowInfo=this.tableRowsInfo_.get(userRow);if(!rowInfo){throw new Error('Row has not been seen, must expand its parents.');}}
+const e=this.prepareToChangeSelection_();if(!rowInfo){this.selectedColumnIndex_=undefined;}else{switch(this.selectionMode_){case SelectionMode.ROW:this.selectedColumnIndex_=undefined;break;case SelectionMode.CELL:if(this.selectedColumnIndex_===undefined){const i=this.getFirstSelectableColumnIndex_();if(i===-1){throw new Error('Cannot find a selectable column.');}
+this.selectedColumnIndex_=i;}
+break;default:throw new Error('Invalid selection mode '+this.selectionMode_);}}
+this.selectedTableRowInfo_=rowInfo;this.updateSelectedState_();this.dispatchEvent(e);},prepareToChangeSelection_(){const e=new tr.b.Event('selection-changed');const previousSelectedRowInfo=this.selectedTableRowInfo_;if(previousSelectedRowInfo){e.previousSelectedTableRow=previousSelectedRowInfo.userRow;}else{e.previousSelectedTableRow=undefined;}
+this.removeSelectedState_();return e;},removeSelectedState_(){this.setSelectedState_(false);},updateSelectedState_(){this.setSelectedState_(true);},setSelectedState_(select){if(this.selectedTableRowInfo_===undefined)return;const rowNode=this.selectedTableRowInfo_.htmlNode;if(select){Polymer.dom(rowNode).setAttribute('selected',true);}else{Polymer.dom(rowNode).removeAttribute('selected');}
+const cellNode=Polymer.dom(rowNode).children[this.selectedColumnIndex_];if(!cellNode)return;if(select){Polymer.dom(cellNode).setAttribute('selected',true);}else{Polymer.dom(cellNode).removeAttribute('selected');}},doesColumnIndexSupportSelection(columnIndex){const columnInfo=this.tableColumns_[columnIndex];const scs=columnInfo.supportsCellSelection;if(scs===false)return false;return true;},getFirstSelectableColumnIndex_(){for(let i=0;i<this.tableColumns_.length;i++){if(this.doesColumnIndexSupportSelection(i)){return i;}}
+return-1;},getSelectableNodeGivenTableRowNode_(htmlNode){switch(this.selectionMode_){case SelectionMode.ROW:return htmlNode;case SelectionMode.CELL:return Polymer.dom(htmlNode).children[this.selectedColumnIndex_];default:throw new Error('Invalid selection mode '+this.selectionMode_);}},get selectedColumnIndex(){if(this.selectionMode_!==SelectionMode.CELL){return undefined;}
+return this.selectedColumnIndex_;},set selectedColumnIndex(selectedColumnIndex){this.rebuildIfNeeded_();if(this.selectionMode_===SelectionMode.NONE){throw new Error('Selection is off.');}
+if(selectedColumnIndex<0||selectedColumnIndex>=this.tableColumns_.length){throw new Error('Invalid index');}
+if(!this.doesColumnIndexSupportSelection(selectedColumnIndex)){throw new Error('Selection is not supported on this column');}
+const e=this.prepareToChangeSelection_();if(this.selectedColumnIndex_===undefined){this.selectedTableRowInfo_=undefined;}else if(!this.selectedTableRowInfo_){if(this.tableRows_.length===0){throw new Error('No available row to be selected');}
+this.selectedTableRowInfo_=this.tableRowsInfo_.get(this.tableRows_[0]);}
+this.selectedColumnIndex_=selectedColumnIndex;this.updateSelectedState_();this.dispatchEvent(e);},onKeyDown_(e){if(this.selectionMode_===SelectionMode.NONE)return;const CODE_TO_COMMAND_NAMES={13:'ENTER',32:'SPACE',37:'ARROW_LEFT',38:'ARROW_UP',39:'ARROW_RIGHT',40:'ARROW_DOWN'};const cmdName=CODE_TO_COMMAND_NAMES[e.keyCode];if(cmdName===undefined)return;e.stopPropagation();e.preventDefault();this.performKeyCommand_(cmdName);},onFocus_(e){if(this.selectionMode_===SelectionMode.NONE||this.selectedTableRow||this.tableRows_.length===0){return;}
+if(this.selectionMode_===SelectionMode.CELL&&this.getFirstSelectableColumnIndex_()===-1){return;}
+this.selectedTableRow=this.tableRows_[0];},focus(){this.$.body.focus();this.onFocus_();},blur(){this.$.body.blur();},get isFocused(){return this.root.activeElement===this.$.body;},performKeyCommand_(cmdName){this.rebuildIfNeeded_();switch(cmdName){case'ARROW_UP':this.selectPreviousOrFirstRowIfPossible_();return;case'ARROW_DOWN':this.selectNextOrFirstRowIfPossible_();return;case'ARROW_RIGHT':switch(this.selectionMode_){case SelectionMode.NONE:return;case SelectionMode.ROW:this.expandRowAndSelectChildRowIfPossible_();return;case SelectionMode.CELL:this.selectNextSelectableCellToTheRightIfPossible_();return;default:throw new Error('Invalid selection mode '+this.selectionMode_);}
+case'ARROW_LEFT':switch(this.selectionMode_){case SelectionMode.NONE:return;case SelectionMode.ROW:this.collapseRowOrSelectParentRowIfPossible_();return;case SelectionMode.CELL:this.selectNextSelectableCellToTheLeftIfPossible_();return;default:throw new Error('Invalid selection mode '+this.selectionMode_);}
+case'SPACE':this.toggleRowExpansionStateIfPossible_();return;case'ENTER':this.stepIntoSelectionIfPossible_();return;default:throw new Error('Unrecognized command '+cmdName);}},selectPreviousOrFirstRowIfPossible_(){const prev=this.selectedTableRowInfo_?this.selectedTableRowInfo_.htmlNode.previousElementSibling:this.$.body.firstChild;if(!prev)return;if(this.selectionMode_===SelectionMode.CELL&&this.getFirstSelectableColumnIndex_()===-1){return;}
+tr.ui.b.scrollIntoViewIfNeeded(prev);this.selectedTableRow=prev.rowInfo.userRow;},selectNextOrFirstRowIfPossible_(){this.getFirstSelectableColumnIndex_;const next=this.selectedTableRowInfo_?this.selectedTableRowInfo_.htmlNode.nextElementSibling:this.$.body.firstChild;if(!next)return;if(this.selectionMode_===SelectionMode.CELL&&this.getFirstSelectableColumnIndex_()===-1){return;}
+tr.ui.b.scrollIntoViewIfNeeded(next);this.selectedTableRow=next.rowInfo.userRow;},expandRowAndSelectChildRowIfPossible_(){const selectedRowInfo=this.selectedTableRowInfo_;if(!selectedRowInfo||selectedRowInfo.userRow[this.subRowsPropertyName_]===undefined||selectedRowInfo.userRow[this.subRowsPropertyName_].length===0){return;}
+if(!selectedRowInfo.isExpanded){this.setExpandedForTableRow(selectedRowInfo.userRow,true);}
+this.selectedTableRow=selectedRowInfo.htmlNode.nextElementSibling.rowInfo.userRow;},collapseRowOrSelectParentRowIfPossible_(){const selectedRowInfo=this.selectedTableRowInfo_;if(!selectedRowInfo)return;if(selectedRowInfo.isExpanded){this.setExpandedForTableRow(selectedRowInfo.userRow,false);}else{const parentRowInfo=selectedRowInfo.parentRowInfo;if(parentRowInfo){this.selectedTableRow=parentRowInfo.userRow;}}},selectNextSelectableCellToTheRightIfPossible_(){if(!this.selectedTableRowInfo_||this.selectedColumnIndex_===undefined){return;}
+for(let i=this.selectedColumnIndex_+1;i<this.tableColumns_.length;i++){if(this.doesColumnIndexSupportSelection(i)){this.selectedColumnIndex=i;return;}}},selectNextSelectableCellToTheLeftIfPossible_(){if(!this.selectedTableRowInfo_||this.selectedColumnIndex_===undefined){return;}
+for(let i=this.selectedColumnIndex_-1;i>=0;i--){if(this.doesColumnIndexSupportSelection(i)){this.selectedColumnIndex=i;return;}}},toggleRowExpansionStateIfPossible_(){const selectedRowInfo=this.selectedTableRowInfo_;if(!selectedRowInfo||selectedRowInfo.userRow[this.subRowsPropertyName_]===undefined||selectedRowInfo.userRow[this.subRowsPropertyName_].length===0){return;}
+this.setExpandedForTableRow(selectedRowInfo.userRow,!selectedRowInfo.isExpanded);},stepIntoSelectionIfPossible_(){if(!this.selectedTableRowInfo_)return;this.dispatchStepIntoEvent_(this.selectedTableRowInfo_,this.selectedColumnIndex_);},dispatchSortingChangedEvent_(){const e=new tr.b.Event('sort-column-changed');e.sortColumnIndex=this.sortColumnIndex_;e.sortDescending=this.sortDescending_;this.dispatchEvent(e);}});})();'use strict';const ColumnAlignment=tr.ui.b.TableFormat.ColumnAlignment;Polymer({is:'tr-ui-b-table-header-cell',created(){this.tapCallback_=undefined;this.cellTitle_='';this.align_=undefined;this.selectable_=false;this.column_=undefined;},ready(){this.addEventListener('click',this.onTap_.bind(this));},set column(column){this.column_=column;this.align=column.align;this.cellTitle=column.title;},get column(){return this.column_;},set cellTitle(value){this.cellTitle_=value;const titleNode=tr.ui.b.asHTMLOrTextNode(this.cellTitle_,this.ownerDocument);this.$.title.innerText='';Polymer.dom(this.$.title).appendChild(titleNode);},get cellTitle(){return this.cellTitle_;},set align(align){switch(align){case undefined:case ColumnAlignment.LEFT:this.style.justifyContent='';break;case ColumnAlignment.RIGHT:this.style.justifyContent='flex-end';break;default:throw new Error('Invalid alignment of column (title=\''+
+this.cellTitle_+'\'): '+align);}
+this.align_=align;},get align(){return this.align_;},clearSideContent(){Polymer.dom(this.$.side).textContent='';},set sideContent(content){Polymer.dom(this.$.side).textContent=content;this.$.side.style.display=content?'inline':'none';},get sideContent(){return Polymer.dom(this.$.side).textContent;},set sideContentDisabled(sideContentDisabled){this.$.side.classList.toggle('disabled',sideContentDisabled);},get sideContentDisabled(){return this.$.side.classList.contains('disabled');},set tapCallback(callback){this.style.cursor='pointer';this.tapCallback_=callback;},get tapCallback(){return this.tapCallback_;},onTap_(){if(this.tapCallback_){this.tapCallback_();}}});'use strict';tr.exportTo('tr.b.math',function(){class RunningStatistics{constructor(){this.mean_=0;this.count_=0;this.max_=-Infinity;this.min_=Infinity;this.sum_=0;this.variance_=0;this.meanlogs_=0;}
+get count(){return this.count_;}
+get geometricMean(){if(this.meanlogs_===undefined)return 0;return Math.exp(this.meanlogs_);}
+get mean(){if(this.count_===0)return undefined;return this.mean_;}
+get max(){return this.max_;}
+get min(){return this.min_;}
+get sum(){return this.sum_;}
+get variance(){if(this.count_===0)return undefined;if(this.count_===1)return 0;return this.variance_/(this.count_-1);}
+get stddev(){if(this.count_===0)return undefined;return Math.sqrt(this.variance);}
+add(x){this.count_++;this.max_=Math.max(this.max_,x);this.min_=Math.min(this.min_,x);this.sum_+=x;if(x<=0){this.meanlogs_=undefined;}else if(this.meanlogs_!==undefined){this.meanlogs_+=(Math.log(Math.abs(x))-this.meanlogs_)/this.count;}
+if(this.count_===1){this.mean_=x;this.variance_=0;}else{const oldMean=this.mean_;const oldVariance=this.variance_;if(oldMean===Infinity||oldMean===-Infinity){this.mean_=this.sum_/this.count_;}else{this.mean_=oldMean+(x-oldMean)/this.count_;}
+this.variance_=oldVariance+(x-oldMean)*(x-this.mean_);}}
+merge(other){const result=new RunningStatistics();result.count_=this.count_+other.count_;result.sum_=this.sum_+other.sum_;result.min_=Math.min(this.min_,other.min_);result.max_=Math.max(this.max_,other.max_);if(result.count===0){result.mean_=0;result.variance_=0;result.meanlogs_=0;}else{result.mean_=result.sum/result.count;const deltaMean=(this.mean||0)-(other.mean||0);result.variance_=this.variance_+other.variance_+
+(this.count*other.count*deltaMean*deltaMean/result.count);if(this.meanlogs_===undefined||other.meanlogs_===undefined){result.meanlogs_=undefined;}else{result.meanlogs_=(this.count*this.meanlogs_+
+other.count*other.meanlogs_)/result.count;}}
+return result;}
+truncate(unit){this.max_=unit.truncate(this.max_);if(this.meanlogs_!==undefined){const formatted=unit.format(this.geometricMean);let lo=1;let hi=16;while(lo<hi-1){const digits=parseInt((lo+hi)/2);const test=tr.b.math.truncate(this.meanlogs_,digits);if(formatted===unit.format(Math.exp(test))){hi=digits;}else{lo=digits;}}
+const test=tr.b.math.truncate(this.meanlogs_,lo);if(formatted===unit.format(Math.exp(test))){this.meanlogs_=test;}else{this.meanlogs_=tr.b.math.truncate(this.meanlogs_,hi);}}
+this.mean_=unit.truncate(this.mean_);this.min_=unit.truncate(this.min_);this.sum_=unit.truncate(this.sum_);this.variance_=unit.truncate(this.variance_);}
+asDict(){if(!this.count){return[];}
+return[this.count_,this.max_,this.meanlogs_,this.mean_,this.min_,this.sum_,this.variance_,];}
+static fromDict(dict){const result=new RunningStatistics();if(dict.length!==7){return result;}
+[result.count_,result.max_,result.meanlogs_,result.mean_,result.min_,result.sum_,result.variance_,]=dict;return result;}}
+return{RunningStatistics,};});'use strict';tr.exportTo('tr.v.d',function(){class Diagnostic{constructor(){this.guid_=undefined;}
+clone(){return new this.constructor();}
+canAddDiagnostic(otherDiagnostic){return false;}
+addDiagnostic(otherDiagnostic){throw new Error('Abstract virtual method: subclasses must override '+'this method if they override canAddDiagnostic');}
+get guid(){if(this.guid_===undefined){this.guid_=tr.b.GUID.allocateUUID4();}
+return this.guid_;}
+set guid(guid){if(this.guid_!==undefined){throw new Error('Cannot reset guid');}
+this.guid_=guid;}
+get hasGuid(){return this.guid_!==undefined;}
+asDictOrReference(){if(this.guid_!==undefined){return this.guid_;}
+return this.asDict();}
+asDict(){const result={type:this.constructor.name};if(this.guid_!==undefined){result.guid=this.guid_;}
+this.asDictInto_(result);return result;}
+asDictInto_(d){throw new Error('Abstract virtual method: subclasses must override '+'this method if they override canAddDiagnostic');}
+static fromDict(d){const typeInfo=Diagnostic.findTypeInfoWithName(d.type);if(!typeInfo){throw new Error('Unrecognized diagnostic type: '+d.type);}
+const diagnostic=typeInfo.constructor.fromDict(d);if(d.guid!==undefined)diagnostic.guid=d.guid;return diagnostic;}
+static deserialize(type,d,deserializer){const typeInfo=Diagnostic.findTypeInfoWithName(type);if(!typeInfo){throw new Error('Unrecognized diagnostic type: '+type);}
+return typeInfo.constructor.deserialize(d,deserializer);}}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Diagnostic;tr.b.decorateExtensionRegistry(Diagnostic,options);Diagnostic.addEventListener('will-register',function(e){const constructor=e.typeInfo.constructor;if(!(constructor.deserialize instanceof Function)||(constructor.deserialize===Diagnostic.deserialize)||(constructor.deserialize.length!==2)){throw new Error(`Please define ${constructor.name}.deserialize(data, deserializer)`);}
+if(!(constructor.fromDict instanceof Function)||(constructor.fromDict===Diagnostic.fromDict)||(constructor.fromDict.length!==1)){throw new Error(`Please define ${constructor.name}.fromDict(d)`);}
+if(!(constructor.prototype.serialize instanceof Function)||(constructor.prototype.serialize===Diagnostic.prototype.serialize)||(constructor.prototype.serialize.length!==1)){throw new Error(`Please define ${constructor.name}.serialize(serializer)`);}});return{Diagnostic,};});'use strict';tr.exportTo('tr.v.d',function(){class Breakdown extends tr.v.d.Diagnostic{constructor(){super();this.values_=new Map();this.colorScheme='';}
+truncate(unit){for(const[name,value]of this){this.values_.set(name,unit.truncate(value));}}
+clone(){const clone=new Breakdown();clone.colorScheme=this.colorScheme;clone.addDiagnostic(this);return clone;}
+equals(other){if(this.colorScheme!==other.colorScheme)return false;if(this.values_.size!==other.values_.size)return false;for(const[k,v]of this){if(v!==other.get(k))return false;}
+return true;}
+canAddDiagnostic(otherDiagnostic){return((otherDiagnostic instanceof Breakdown)&&(otherDiagnostic.colorScheme===this.colorScheme));}
+addDiagnostic(otherDiagnostic){for(const[name,value]of otherDiagnostic){this.set(name,this.get(name)+value);}
+return this;}
+set(name,value){if(typeof name!=='string'||typeof value!=='number'){throw new Error('Breakdown maps from strings to numbers');}
+this.values_.set(name,value);}
+get(name){return this.values_.get(name)||0;}*[Symbol.iterator](){for(const pair of this.values_){yield pair;}}
+get size(){return this.values_.size;}
+serialize(serializer){const keys=[...this.values_.keys()];keys.sort();return[serializer.getOrAllocateId(this.colorScheme),serializer.getOrAllocateId(keys.map(k=>serializer.getOrAllocateId(k))),...keys.map(k=>this.get(k)),];}
+asDictInto_(d){d.values={};for(const[name,value]of this){d.values[name]=tr.b.numberToJson(value);}
+if(this.colorScheme){d.colorScheme=this.colorScheme;}}
+static fromEntries(entries){const breakdown=new Breakdown();for(const[name,value]of entries){breakdown.set(name,value);}
+return breakdown;}
+static deserialize(data,deserializer){const breakdown=new Breakdown();breakdown.colorScheme=deserializer.getObject(data[0]);const keys=deserializer.getObject(data[1]);for(let i=0;i<keys.length;++i){breakdown.set(deserializer.getObject(keys[i]),tr.b.numberFromJson(data[i+2]));}
+return breakdown;}
+static fromDict(d){const breakdown=new Breakdown();for(const[name,value]of Object.entries(d.values)){breakdown.set(name,tr.b.numberFromJson(value));}
+if(d.colorScheme){breakdown.colorScheme=d.colorScheme;}
+return breakdown;}}
+tr.v.d.Diagnostic.register(Breakdown,{elementName:'tr-v-ui-breakdown-span'});return{Breakdown,};});'use strict';tr.exportTo('tr.v.d',function(){class CollectedRelatedEventSet extends tr.v.d.Diagnostic{constructor(){super();this.eventSetsByCanonicalUrl_=new Map();}
+asDictInto_(d){d.events={};for(const[canonicalUrl,eventSet]of this){d.events[canonicalUrl]=[];for(const event of eventSet){d.events[canonicalUrl].push({stableId:event.stableId,title:event.title,start:event.start,duration:event.duration});}}}
+static deserialize(events,deserializer){return CollectedRelatedEventSet.fromDict({events});}
+serialize(serializer){const d={};this.asDictInto(d);return d.events;}
+static fromDict(d){const result=new CollectedRelatedEventSet();for(const[canonicalUrl,events]of Object.entries(d.events)){result.eventSetsByCanonicalUrl_.set(canonicalUrl,events.map(e=>new tr.v.d.EventRef(e)));}
+return result;}
+get size(){return this.eventSetsByCanonicalUrl_.size;}
+get(canonicalUrl){return this.eventSetsByCanonicalUrl_.get(canonicalUrl);}*[Symbol.iterator](){for(const[canonicalUrl,eventSet]of this.eventSetsByCanonicalUrl_){yield[canonicalUrl,eventSet];}}
+canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof tr.v.d.RelatedEventSet||otherDiagnostic instanceof tr.v.d.CollectedRelatedEventSet;}
+addEventSetForCanonicalUrl(canonicalUrl,events){let myEventSet=this.eventSetsByCanonicalUrl_.get(canonicalUrl);if(myEventSet===undefined){myEventSet=new Set();this.eventSetsByCanonicalUrl_.set(canonicalUrl,myEventSet);}
+for(const event of events){myEventSet.add(event);}}
+addDiagnostic(otherDiagnostic){if(otherDiagnostic instanceof tr.v.d.CollectedRelatedEventSet){for(const[canonicalUrl,otherEventSet]of otherDiagnostic){this.addEventSetForCanonicalUrl(canonicalUrl,otherEventSet);}
+return;}
+if(!otherDiagnostic.canonicalUrl)return;this.addEventSetForCanonicalUrl(otherDiagnostic.canonicalUrl,otherDiagnostic);}}
+tr.v.d.Diagnostic.register(CollectedRelatedEventSet,{elementName:'tr-v-ui-collected-related-event-set-span'});return{CollectedRelatedEventSet,};});'use strict';tr.exportTo('tr.v.d',function(){class DateRange extends tr.v.d.Diagnostic{constructor(ms){super();this.range_=new tr.b.math.Range();this.range_.addValue(ms);}
+get minTimestamp(){return this.range_.min;}
+get maxTimestamp(){return this.range_.max;}
+get minDate(){return new Date(this.range_.min);}
+get maxDate(){return new Date(this.range_.max);}
+get durationMs(){return this.range_.duration;}
+clone(){const clone=new tr.v.d.DateRange(this.range_.min);clone.addDiagnostic(this);return clone;}
+equals(other){if(!(other instanceof DateRange))return false;return this.range_.equals(other.range_);}
+canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof DateRange;}
+addDiagnostic(other){this.range_.addRange(other.range_);}
+toString(){const minDate=tr.b.formatDate(this.minDate);if(this.durationMs===0)return minDate;const maxDate=tr.b.formatDate(this.maxDate);return`${minDate} - ${maxDate}`;}
+serialize(serializer){if(this.durationMs===0)return this.range_.min;return[this.range_.min,this.range_.max];}
+asDictInto_(d){d.min=this.range_.min;if(this.durationMs===0)return;d.max=this.range_.max;}
+static deserialize(data,deserializer){if(data instanceof Array){const dr=new DateRange(data[0]);dr.range_.addValue(data[1]);return dr;}
+return new DateRange(data);}
+static fromDict(d){const dateRange=new DateRange(d.min);if(d.max!==undefined)dateRange.range_.addValue(d.max);return dateRange;}}
+tr.v.d.Diagnostic.register(DateRange,{elementName:'tr-v-ui-date-range-span'});return{DateRange,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticRef{constructor(guid){this.guid=guid;}
+asDict(){return this.guid;}
+asDictOrReference(){return this.asDict();}}
+return{DiagnosticRef,};});'use strict';tr.exportTo('tr.v.d',function(){function stableStringify(obj){let replacer;if(!(obj instanceof Array)&&obj!==null){replacer=Object.keys(obj).sort();}
+return JSON.stringify(obj,replacer);}
+class GenericSet extends tr.v.d.Diagnostic{constructor(values){super();if(typeof values[Symbol.iterator]!=='function'){throw new Error('GenericSet must be constructed from an interable.');}
+this.values_=new Set(values);this.has_objects_=false;for(const value of values){if(typeof value==='object'){this.has_objects_=true;}}}
+get size(){return this.values_.size;}
+get length(){return this.values_.size;}*[Symbol.iterator](){for(const value of this.values_){yield value;}}
+has(value){if(typeof value!=='object')return this.values_.has(value);const json=JSON.stringify(value);for(const x of this){if(typeof x!=='object')continue;if(json===JSON.stringify(x))return true;}
+return false;}
+equals(other){if(!(other instanceof GenericSet))return false;if(this.size!==other.size)return false;for(const value of this){if(!other.has(value))return false;}
+return true;}
+get hashKey(){if(this.has_objects_)return undefined;if(this.hash_key_!==undefined){return this.hash_key_;}
+let key='';for(const value of Array.from(this.values_.values()).sort()){key+=value;}
+this.hash_key_=key;return key;}
+serialize(serializer){const i=[...this].map(x=>serializer.getOrAllocateId(x));return(i.length===1)?i[0]:i;}
+asDictInto_(d){d.values=Array.from(this);}
+static deserialize(data,deserializer){if(!(data instanceof Array)){data=[data];}
+return new GenericSet(data.map(datum=>deserializer.getObject(datum)));}
+static fromDict(d){return new GenericSet(d.values);}
+clone(){return new GenericSet(this.values_);}
+canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof GenericSet;}
+addDiagnostic(otherDiagnostic){const jsons=new Set();for(const value of this){if(typeof value!=='object')continue;jsons.add(stableStringify(value));}
+for(const value of otherDiagnostic){if(typeof value==='object'){if(jsons.has(stableStringify(value))){continue;}
+this.has_objects_=true;}
+this.values_.add(value);}}}
+tr.v.d.Diagnostic.register(GenericSet,{elementName:'tr-v-ui-generic-set-span'});return{GenericSet,};});'use strict';tr.exportTo('tr.v.d',function(){class EventRef{constructor(event){this.stableId=event.stableId;this.title=event.title;this.start=event.start;this.duration=event.duration;this.end=this.start+this.duration;this.guid=tr.b.GUID.allocateSimple();}}
+return{EventRef,};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedEventSet extends tr.v.d.Diagnostic{constructor(opt_events){super();this.eventsByStableId_=new Map();this.canonicalUrl_=undefined;if(opt_events){if(opt_events instanceof tr.model.EventSet||opt_events instanceof Array){for(const event of opt_events){this.add(event);}}else{this.add(opt_events);}}}
+clone(){const clone=new tr.v.d.CollectedRelatedEventSet();clone.addDiagnostic(this);return clone;}
+equals(other){if(this.length!==other.length)return false;for(const event of this){if(!other.has(event))return false;}
+return true;}
+add(event){this.eventsByStableId_.set(event.stableId,event);}
+has(event){return this.eventsByStableId_.has(event.stableId);}
+get length(){return this.eventsByStableId_.size;}*[Symbol.iterator](){for(const event of this.eventsByStableId_.values()){yield event;}}
+get canonicalUrl(){return this.canonicalUrl_;}
+resolve(model,opt_required){for(const[stableId,value]of this.eventsByStableId_){if(!(value instanceof tr.v.d.EventRef))continue;const event=model.getEventByStableId(stableId);if(event instanceof tr.model.Event){this.eventsByStableId_.set(stableId,event);}else if(opt_required){throw new Error('Unable to find Event '+stableId);}}}
+serialize(serializer){return[...this].map(event=>[event.stableId,serializer.getOrAllocateId(event.title),event.start,event.duration,]);}
+asDictInto_(d){d.events=[];for(const event of this){d.events.push({stableId:event.stableId,title:event.title,start:tr.b.Unit.byName.timeStampInMs.truncate(event.start),duration:tr.b.Unit.byName.timeDurationInMs.truncate(event.duration),});}}
+static deserialize(data,deserializer){return new RelatedEventSet(data.map(event=>new tr.v.d.EventRef({stableId:event[0],title:deserializer.getObject(event[1]),start:event[2],duration:event[3],})));}
+static fromDict(d){return new RelatedEventSet(d.events.map(event=>new tr.v.d.EventRef(event)));}}
+tr.v.d.Diagnostic.register(RelatedEventSet,{elementName:'tr-v-ui-related-event-set-span'});return{RelatedEventSet,};});'use strict';tr.exportTo('tr.v.d',function(){class RelatedNameMap extends tr.v.d.Diagnostic{constructor(opt_info){super();this.map_=new Map();if(opt_info){for(const[key,name]of Object.entries(opt_info)){this.set(key,name);}}}
+clone(){const clone=new RelatedNameMap();clone.addDiagnostic(this);return clone;}
+equals(other){if(!(other instanceof RelatedNameMap))return false;const keys1=new Set(this.map_.keys());const keys2=new Set(other.map_.keys());if(!tr.b.setsEqual(keys1,keys2))return false;for(const[key,name]of this){if(name!==other.get(key))return false;}
+return true;}
+canAddDiagnostic(otherDiagnostic){return otherDiagnostic instanceof RelatedNameMap;}
+addDiagnostic(otherDiagnostic){for(const[key,name]of otherDiagnostic){const existing=this.get(key);if(existing===undefined){this.set(key,name);}else if(existing!==name){throw new Error('Histogram names differ: '+`"${existing}" != "${name}"`);}}}
+serialize(serializer){const keys=[...this.map_.keys()];keys.sort();const names=keys.map(k=>serializer.getOrAllocateId(this.get(k)));const keysId=serializer.getOrAllocateId(keys.map(k=>serializer.getOrAllocateId(k)));return[keysId,...names];}
+asDictInto_(d){d.names={};for(const[key,name]of this)d.names[key]=name;}
+set(key,name){this.map_.set(key,name);}
+get(key){return this.map_.get(key);}*[Symbol.iterator](){for(const pair of this.map_)yield pair;}*values(){for(const value of this.map_.values())yield value;}
+static fromEntries(entries){const names=new RelatedNameMap();for(const[key,name]of entries){names.set(key,name);}
+return names;}
+static deserialize(data,deserializer){const names=new RelatedNameMap();const keys=deserializer.getObject(data[0]);for(let i=0;i<keys.length;++i){names.set(deserializer.getObject(keys[i]),deserializer.getObject(data[i+1]));}
+return names;}
+static fromDict(d){return RelatedNameMap.fromEntries(Object.entries(d.names||{}));}}
+tr.v.d.Diagnostic.register(RelatedNameMap,{elementName:'tr-v-ui-related-name-map-span',});return{RelatedNameMap,};});'use strict';tr.exportTo('tr.v.d',function(){class Scalar extends tr.v.d.Diagnostic{constructor(value){super();if(!(value instanceof tr.b.Scalar)){throw new Error('expected Scalar');}
+this.value=value;}
+clone(){return new Scalar(this.value);}
+serialize(serializer){return this.value.asDict();}
+asDictInto_(d){d.value=this.value.asDict();}
+static deserialize(value,deserializer){return Scalar.fromDict({value});}
+static fromDict(d){return new Scalar(tr.b.Scalar.fromDict(d.value));}}
+tr.v.d.Diagnostic.register(Scalar,{elementName:'tr-v-ui-scalar-diagnostic-span'});return{Scalar,};});'use strict';tr.exportTo('tr.v.d',function(){class UnmergeableDiagnosticSet extends tr.v.d.Diagnostic{constructor(diagnostics){super();this._diagnostics=diagnostics;}
+clone(){const clone=new tr.v.d.UnmergeableDiagnosticSet();clone.addDiagnostic(this);return clone;}
+canAddDiagnostic(otherDiagnostic){return true;}
+addDiagnostic(otherDiagnostic){if(otherDiagnostic instanceof UnmergeableDiagnosticSet){for(const subOtherDiagnostic of otherDiagnostic){const clone=subOtherDiagnostic.clone();this.addDiagnostic(clone);}
+return;}
+for(let i=0;i<this._diagnostics.length;++i){if(this._diagnostics[i].canAddDiagnostic(otherDiagnostic)){this._diagnostics[i].addDiagnostic(otherDiagnostic);return;}}
+const clone=otherDiagnostic.clone();this._diagnostics.push(clone);}
+get length(){return this._diagnostics.length;}*[Symbol.iterator](){for(const diagnostic of this._diagnostics)yield diagnostic;}
+asDictInto_(d){d.diagnostics=this._diagnostics.map(d=>d.asDictOrReference());}
+static deserialize(data,deserializer){return new UnmergeableDiagnosticSet(d.map(i=>deserializer.getDiagnostic(i).diagnostic));}
+serialize(serializer){return this._diagnostics.map(d=>serializer.getOrAllocateDiagnosticId('',d));}
+static fromDict(d){return new UnmergeableDiagnosticSet(d.diagnostics.map(d=>((typeof d==='string')?new tr.v.d.DiagnosticRef(d):tr.v.d.Diagnostic.fromDict(d))));}}
+tr.v.d.Diagnostic.register(UnmergeableDiagnosticSet,{elementName:'tr-v-ui-unmergeable-diagnostic-set-span'});return{UnmergeableDiagnosticSet,};});'use strict';tr.exportTo('tr.v.d',function(){const RESERVED_INFOS={ANGLE_REVISIONS:{name:'angleRevisions',type:tr.v.d.GenericSet},ARCHITECTURES:{name:'architectures',type:tr.v.d.GenericSet},BENCHMARKS:{name:'benchmarks',type:tr.v.d.GenericSet},BENCHMARK_START:{name:'benchmarkStart',type:tr.v.d.DateRange},BENCHMARK_DESCRIPTIONS:{name:'benchmarkDescriptions',type:tr.v.d.GenericSet},BOTS:{name:'bots',type:tr.v.d.GenericSet},BUG_COMPONENTS:{name:'bugComponents',type:tr.v.d.GenericSet},BUILDS:{name:'builds',type:tr.v.d.GenericSet},CATAPULT_REVISIONS:{name:'catapultRevisions',type:tr.v.d.GenericSet},CHROMIUM_COMMIT_POSITIONS:{name:'chromiumCommitPositions',type:tr.v.d.GenericSet},CHROMIUM_REVISIONS:{name:'chromiumRevisions',type:tr.v.d.GenericSet},DESCRIPTION:{name:'description',type:tr.v.d.GenericSet},DEVICE_IDS:{name:'deviceIds',type:tr.v.d.GenericSet},DOCUMENTATION_URLS:{name:'documentationUrls',type:tr.v.d.GenericSet},FUCHSIA_GARNET_REVISIONS:{name:'fuchsiaGarnetRevisions',type:tr.v.d.GenericSet},FUCHSIA_PERIDOT_REVISIONS:{name:'fuchsiaPeridotRevisions',type:tr.v.d.GenericSet},FUCHSIA_TOPAZ_REVISIONS:{name:'fuchsiaTopazRevisions',type:tr.v.d.GenericSet},FUCHSIA_ZIRCON_REVISIONS:{name:'fuchsiaZirconRevisions',type:tr.v.d.GenericSet},GPUS:{name:'gpus',type:tr.v.d.GenericSet},IS_REFERENCE_BUILD:{name:'isReferenceBuild',type:tr.v.d.GenericSet},LABELS:{name:'labels',type:tr.v.d.GenericSet},LOG_URLS:{name:'logUrls',type:tr.v.d.GenericSet},MASTERS:{name:'masters',type:tr.v.d.GenericSet},MEMORY_AMOUNTS:{name:'memoryAmounts',type:tr.v.d.GenericSet},OS_NAMES:{name:'osNames',type:tr.v.d.GenericSet},OS_VERSIONS:{name:'osVersions',type:tr.v.d.GenericSet},OWNERS:{name:'owners',type:tr.v.d.GenericSet},POINT_ID:{name:'pointId',type:tr.v.d.GenericSet},PRODUCT_VERSIONS:{name:'productVersions',type:tr.v.d.GenericSet},REVISION_TIMESTAMPS:{name:'revisionTimestamps',type:tr.v.d.DateRange},SKIA_REVISIONS:{name:'skiaRevisions',type:tr.v.d.GenericSet},STATISTICS_NAMES:{name:'statisticsNames',type:tr.v.d.GenericSet},STORIES:{name:'stories',type:tr.v.d.GenericSet},STORYSET_REPEATS:{name:'storysetRepeats',type:tr.v.d.GenericSet},STORY_TAGS:{name:'storyTags',type:tr.v.d.GenericSet},SUMMARY_KEYS:{name:'summaryKeys',type:tr.v.d.GenericSet},TEST_PATH:{name:'testPath',type:tr.v.d.GenericSet},TRACE_START:{name:'traceStart',type:tr.v.d.DateRange},TRACE_URLS:{name:'traceUrls',type:tr.v.d.GenericSet},V8_COMMIT_POSITIONS:{name:'v8CommitPositions',type:tr.v.d.DateRange},V8_REVISIONS:{name:'v8Revisions',type:tr.v.d.GenericSet},WEBRTC_REVISIONS:{name:'webrtcRevisions',type:tr.v.d.GenericSet},WEBRTC_INTERNAL_REVISIONS:{name:'webrtcInternalRevisions',type:tr.v.d.GenericSet},};const RESERVED_NAMES={};const RESERVED_NAMES_TO_TYPES=new Map();for(const[codename,info]of Object.entries(RESERVED_INFOS)){RESERVED_NAMES[codename]=info.name;if(RESERVED_NAMES_TO_TYPES.has(info.name)){throw new Error(`Duplicate reserved name "${info.name}"`);}
+RESERVED_NAMES_TO_TYPES.set(info.name,info.type);}
+const RESERVED_NAMES_SET=new Set(Object.values(RESERVED_NAMES));return{RESERVED_INFOS,RESERVED_NAMES,RESERVED_NAMES_SET,RESERVED_NAMES_TO_TYPES,};});'use strict';tr.exportTo('tr.v.d',function(){class DiagnosticMap extends Map{constructor(opt_allowReservedNames){super();if(opt_allowReservedNames===undefined){opt_allowReservedNames=true;}
+this.allowReservedNames_=opt_allowReservedNames;}
+set(name,diagnostic){if(typeof(name)!=='string'){throw new Error(`name must be string, not ${name}`);}
+if(!(diagnostic instanceof tr.v.d.Diagnostic)&&!(diagnostic instanceof tr.v.d.DiagnosticRef)){throw new Error(`Must be instanceof Diagnostic: ${diagnostic}`);}
+if(!this.allowReservedNames_&&tr.v.d.RESERVED_NAMES_SET.has(name)&&!(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)&&!(diagnostic instanceof tr.v.d.DiagnosticRef)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type&&!(diagnostic instanceof type)){throw new Error(`Diagnostics named "${name}" must be ${type.name}, `+`not ${diagnostic.constructor.name}`);}}
+Map.prototype.set.call(this,name,diagnostic);}
+delete(name){if(name===undefined)throw new Error('missing name');Map.prototype.delete.call(this,name);}
+deserializeAdd(data,deserializer){for(const id of data){const{name,diagnostic}=deserializer.getDiagnostic(id);this.set(name,diagnostic);}}
+addDicts(dict){for(const[name,diagnosticDict]of Object.entries(dict)){if(name==='tagmap')continue;if(typeof diagnosticDict==='string'){this.set(name,new tr.v.d.DiagnosticRef(diagnosticDict));}else if(diagnosticDict.type!=='RelatedHistogramMap'&&diagnosticDict.type!=='RelatedHistogramBreakdown'&&diagnosticDict.type!=='TagMap'){this.set(name,tr.v.d.Diagnostic.fromDict(diagnosticDict));}}}
+resolveSharedDiagnostics(histograms,opt_required){for(const[name,value]of this){if(!(value instanceof tr.v.d.DiagnosticRef)){continue;}
+const guid=value.guid;const diagnostic=histograms.lookupDiagnostic(guid);if(diagnostic instanceof tr.v.d.Diagnostic){this.set(name,diagnostic);}else if(opt_required){throw new Error('Unable to find shared Diagnostic '+guid);}}}
+serialize(serializer){const data=[];for(const[name,diagnostic]of this){data.push(serializer.getOrAllocateDiagnosticId(name,diagnostic));}
+return data;}
+asDict(){const dict={};for(const[name,diagnostic]of this){dict[name]=diagnostic.asDictOrReference();}
+return dict;}
+static deserialize(data,deserializer){const diagnostics=new DiagnosticMap();diagnostics.deserializeAdd(data,deserializer);return diagnostics;}
+static fromDict(d){const diagnostics=new DiagnosticMap();diagnostics.addDicts(d);return diagnostics;}
+static fromObject(obj){const diagnostics=new DiagnosticMap();if(!(obj instanceof Map))obj=Object.entries(obj);for(const[name,diagnostic]of obj){if(!diagnostic)continue;diagnostics.set(name,diagnostic);}
+return diagnostics;}
+addDiagnostics(other){for(const[name,otherDiagnostic]of other){const myDiagnostic=this.get(name);if(myDiagnostic!==undefined&&myDiagnostic.canAddDiagnostic(otherDiagnostic)){myDiagnostic.addDiagnostic(otherDiagnostic);continue;}
+const clone=otherDiagnostic.clone();if(myDiagnostic===undefined){this.set(name,clone);continue;}
+this.set(name,new tr.v.d.UnmergeableDiagnosticSet([myDiagnostic,clone]));}}}
+return{DiagnosticMap};});'use strict';tr.exportTo('tr.v',function(){const MAX_DIAGNOSTIC_MAPS=16;const DEFAULT_SAMPLE_VALUES_PER_BIN=10;const DEFAULT_REBINNED_COUNT=40;const DEFAULT_BOUNDARIES_FOR_UNIT=new Map();const DEFAULT_ITERATION_FOR_BOOTSTRAP_RESAMPLING=500;const DELTA=String.fromCharCode(916);const Z_SCORE_NAME='z-score';const P_VALUE_NAME='p-value';const U_STATISTIC_NAME='U';function percentToString(percent,opt_force3){if(percent<0||percent>1){throw new Error('percent must be in [0,1]');}
+if(percent===0)return'000';if(percent===1)return'100';let str=percent.toString();if(str[1]!=='.'){throw new Error('Unexpected percent');}
+str=str+'0'.repeat(Math.max(4-str.length,0));if(str.length>4){if(opt_force3){str=str.slice(0,4);}else{str=str.slice(0,4)+'_'+str.slice(4);}}
+return'0'+str.slice(2);}
+function percentFromString(s){return parseFloat(s[0]+'.'+s.substr(1).replace(/_/g,''));}
+class HistogramBin{constructor(range){this.range=range;this.count=0;this.diagnosticMaps=[];}
+addSample(value){this.count+=1;}
+addDiagnosticMap(diagnostics){tr.b.math.Statistics.uniformlySampleStream(this.diagnosticMaps,this.count,diagnostics,MAX_DIAGNOSTIC_MAPS);}
+addBin(other){if(!this.range.equals(other.range)){throw new Error('Merging incompatible Histogram bins.');}
+tr.b.math.Statistics.mergeSampledStreams(this.diagnosticMaps,this.count,other.diagnosticMaps,other.count,MAX_DIAGNOSTIC_MAPS);this.count+=other.count;}
+deserialize(data,deserializer){if(!(data instanceof Array)){this.count=data;return;}
+this.count=data[0];for(const sample of data.slice(1)){if(!(sample instanceof Array))continue;this.diagnosticMaps.push(tr.v.d.DiagnosticMap.deserialize(sample.slice(1),deserializer));}}
+fromDict(dict){this.count=dict[0];if(dict.length>1){for(const map of dict[1]){this.diagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map));}}}
+serialize(serializer){if(!this.diagnosticMaps.length){return this.count;}
+return[this.count,...this.diagnosticMaps.map(d=>[undefined,...d.serialize(serializer)])];}
+asDict(){if(!this.diagnosticMaps.length){return[this.count];}
+return[this.count,this.diagnosticMaps.map(d=>d.asDict())];}}
+const DEFAULT_SUMMARY_OPTIONS=new Map([['avg',true],['count',true],['geometricMean',false],['max',true],['min',true],['nans',false],['std',true],['sum',true],]);class Histogram{constructor(name,unit,opt_binBoundaries){if(!(unit instanceof tr.b.Unit)){throw new Error('unit must be a Unit: '+unit);}
+let binBoundaries=opt_binBoundaries;if(!binBoundaries){const baseUnit=unit.baseUnit?unit.baseUnit:unit;binBoundaries=DEFAULT_BOUNDARIES_FOR_UNIT.get(baseUnit.unitName);}
+this.binBoundariesDict_=binBoundaries.asDict();this.allBins=binBoundaries.bins.slice();this.description='';const allowReservedNames=false;this.diagnostics_=new tr.v.d.DiagnosticMap(allowReservedNames);this.maxNumSampleValues_=this.defaultMaxNumSampleValues_;this.name_=name;this.nanDiagnosticMaps=[];this.numNans=0;this.running_=undefined;this.sampleValues_=[];this.sampleMeans_=[];this.summaryOptions=new Map(DEFAULT_SUMMARY_OPTIONS);this.summaryOptions.set('percentile',[]);this.summaryOptions.set('iprs',[]);this.summaryOptions.set('ci',[]);this.unit=unit;}
+static create(name,unit,samples,opt_options){const options=opt_options||{};const hist=new Histogram(name,unit,options.binBoundaries);if(options.description)hist.description=options.description;if(options.summaryOptions){let summaryOptions=options.summaryOptions;if(!(summaryOptions instanceof Map)){summaryOptions=Object.entries(summaryOptions);}
+for(const[name,value]of summaryOptions){hist.summaryOptions.set(name,value);}}
+if(options.diagnostics!==undefined){let diagnostics=options.diagnostics;if(!(diagnostics instanceof Map)){diagnostics=Object.entries(diagnostics);}
+for(const[name,diagnostic]of diagnostics){if(!diagnostic)continue;hist.diagnostics.set(name,diagnostic);}}
+if(!(samples instanceof Array))samples=[samples];for(const sample of samples){if(typeof sample==='object'){hist.addSample(sample.value,sample.diagnostics);}else{hist.addSample(sample);}}
+return hist;}
+get diagnostics(){return this.diagnostics_;}
+get running(){return this.running_;}
+get maxNumSampleValues(){return this.maxNumSampleValues_;}
+set maxNumSampleValues(n){this.maxNumSampleValues_=n;tr.b.math.Statistics.uniformlySampleArray(this.sampleValues_,this.maxNumSampleValues_);}
+get name(){return this.name_;}
+deserializeStatistics_(){const statisticsNames=this.diagnostics.get(tr.v.d.RESERVED_NAMES.STATISTICS_NAMES);if(!statisticsNames)return;for(const statName of statisticsNames){if(statName.startsWith('pct_')){const percent=percentFromString(statName.substr(4));this.summaryOptions.get('percentile').push(percent);}else if(statName.startsWith('ipr_')){const lower=percentFromString(statName.substr(4,3));const upper=percentFromString(statName.substr(8));this.summaryOptions.get('iprs').push(tr.b.math.Range.fromExplicitRange(lower,upper));}else if(statName.startsWith('ci_')){const percent=percentFromString(statName.replace('_lower','').replace('_upper','').substr(3));if(!this.summaryOptions.get('ci').includes(percent)){this.summaryOptions.get('ci').push(percent);}}}
+for(const statName of this.summaryOptions.keys()){if(statName==='percentile'||statName==='iprs'||statName==='ci'){continue;}
+this.summaryOptions.set(statName,statisticsNames.has(statName));}}
+deserializeBin_(i,bin,deserializer){this.allBins[i]=new HistogramBin(this.allBins[i].range);this.allBins[i].deserialize(bin,deserializer);if(!(bin instanceof Array))return;for(let sample of bin.slice(1)){if(sample instanceof Array){sample=sample[0];}
+this.sampleValues_.push(sample);}}
+deserializeBins_(bins,deserializer){if(bins instanceof Array){for(let i=0;i<bins.length;++i){this.deserializeBin_(i,bins[i],deserializer);}}else{for(const[i,binData]of Object.entries(bins)){this.deserializeBin_(i,binData,deserializer);}}}
+static deserialize(data,deserializer){const[name,unit,boundaries,diagnostics,running,bins,nanBin]=data;const hist=new Histogram(deserializer.getObject(name),tr.b.Unit.fromJSON(unit),HistogramBinBoundaries.fromDict(deserializer.getObject(boundaries)));hist.diagnostics.deserializeAdd(diagnostics,deserializer);const description=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.DESCRIPTION);if(description&&description.length){hist.description=[...description][0];}
+hist.deserializeStatistics_();if(running){hist.running_=tr.b.math.RunningStatistics.fromDict(running);}
+if(bins){hist.deserializeBins_(bins,deserializer);}
+if(nanBin){if(!(nanBin instanceof Array)){hist.numNans=nanBin;}else{hist.numNans=nanBin[0];for(const sample of nanBin.slice(1)){if(!(sample instanceof Array))continue;hist.nanDiagnosticMaps.push(tr.v.d.DiagnosticMap.deserialize(sample.slice(1),deserializer));}}}
+return hist;}
+static fromDict(dict){const hist=new Histogram(dict.name,tr.b.Unit.fromJSON(dict.unit),HistogramBinBoundaries.fromDict(dict.binBoundaries));if(dict.description){hist.description=dict.description;}
+if(dict.diagnostics){hist.diagnostics.addDicts(dict.diagnostics);}
+if(dict.allBins){if(dict.allBins.length!==undefined){for(let i=0;i<dict.allBins.length;++i){hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(dict.allBins[i]);}}else{for(const[i,binDict]of Object.entries(dict.allBins)){if(i>=hist.allBins.length||i<0){throw new Error('Invalid index "'+i+'" out of bounds of [0..'+hist.allBins.length+')');}
+hist.allBins[i]=new HistogramBin(hist.allBins[i].range);hist.allBins[i].fromDict(binDict);}}}
+if(dict.running){hist.running_=tr.b.math.RunningStatistics.fromDict(dict.running);}
+if(dict.summaryOptions){if(dict.summaryOptions.iprs){dict.summaryOptions.iprs=dict.summaryOptions.iprs.map(r=>tr.b.math.Range.fromExplicitRange(r[0],r[1]));}
+hist.customizeSummaryOptions(dict.summaryOptions);}
+if(dict.maxNumSampleValues!==undefined){hist.maxNumSampleValues=dict.maxNumSampleValues;}
+if(dict.sampleValues){hist.sampleValues_=dict.sampleValues;}
+if(dict.numNans){hist.numNans=dict.numNans;}
+if(dict.nanDiagnostics){for(const map of dict.nanDiagnostics){hist.nanDiagnosticMaps.push(tr.v.d.DiagnosticMap.fromDict(map));}}
+return hist;}
+get numValues(){return this.running_?this.running_.count:0;}
+get average(){return this.running_?this.running_.mean:undefined;}
+get standardDeviation(){return this.running_?this.running_.stddev:undefined;}
+get geometricMean(){return this.running_?this.running_.geometricMean:0;}
+get sum(){return this.running_?this.running_.sum:0;}
+get min(){return this.running_?this.running_.min:Infinity;}
+get max(){return this.running_?this.running_.max:-Infinity;}
+getDifferenceSignificance(other,opt_alpha){if(this.unit!==other.unit){throw new Error('Cannot compare Histograms with different units');}
+if(this.unit.improvementDirection===tr.b.ImprovementDirection.DONT_CARE){return tr.b.math.Statistics.Significance.DONT_CARE;}
+if(!(other instanceof Histogram)){throw new Error('Unable to compute a p-value');}
+const testResult=tr.b.math.Statistics.mwu(this.sampleValues,other.sampleValues,opt_alpha);return testResult.significance;}
+getApproximatePercentile(percent){if(percent<0||percent>1){throw new Error('percent must be in [0,1]');}
+if(this.numValues===0)return undefined;if(this.allBins.length===1){const sortedSampleValues=this.sampleValues.slice().sort((x,y)=>x-y);return sortedSampleValues[Math.floor((sortedSampleValues.length-1)*percent)];}
+let valuesToSkip=Math.floor((this.numValues-1)*percent);for(const bin of this.allBins){valuesToSkip-=bin.count;if(valuesToSkip>=0)continue;if(bin.range.min===-Number.MAX_VALUE){return bin.range.max;}
+if(bin.range.max===Number.MAX_VALUE){return bin.range.min;}
+return bin.range.center;}
+return this.allBins[this.allBins.length-1].range.min;}
+getBinIndexForValue(value){const i=tr.b.findFirstTrueIndexInSortedArray(this.allBins,b=>value<b.range.max);if(0<=i&&i<this.allBins.length)return i;return this.allBins.length-1;}
+getBinForValue(value){return this.allBins[this.getBinIndexForValue(value)];}
+addSample(value,opt_diagnostics){if(opt_diagnostics){if(!(opt_diagnostics instanceof tr.v.d.DiagnosticMap)){opt_diagnostics=tr.v.d.DiagnosticMap.fromObject(opt_diagnostics);}
+for(const[name,diag]of opt_diagnostics){if(diag instanceof tr.v.d.Breakdown){diag.truncate(this.unit);}}}
+if(typeof(value)!=='number'||isNaN(value)){this.numNans++;if(opt_diagnostics){tr.b.math.Statistics.uniformlySampleStream(this.nanDiagnosticMaps,this.numNans,opt_diagnostics,MAX_DIAGNOSTIC_MAPS);}}else{if(this.running_===undefined){this.running_=new tr.b.math.RunningStatistics();}
+this.sampleMeans_=[];this.running_.add(value);value=this.unit.truncate(value);const binIndex=this.getBinIndexForValue(value);let bin=this.allBins[binIndex];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[binIndex]=bin;}
+bin.addSample(value);if(opt_diagnostics){bin.addDiagnosticMap(opt_diagnostics);}}
+tr.b.math.Statistics.uniformlySampleStream(this.sampleValues_,this.numValues+this.numNans,value,this.maxNumSampleValues);}
+resampleMean_(percent){const filteredSamples=this.sampleValues_.filter(value=>typeof(value)==='number'&&!isNaN(value));const sampleCount=filteredSamples.length;if(sampleCount===0||percent<=0.0||percent>=1.0){return[undefined,undefined];}else if(sampleCount===1){return[filteredSamples[0],filteredSamples[0]];}
+const iterations=DEFAULT_ITERATION_FOR_BOOTSTRAP_RESAMPLING;if(this.sampleMeans_.length!==iterations){this.sampleMeans_=[];for(let i=0;i<iterations;i++){let tempSum=0.0;for(let j=0;j<sampleCount;j++){tempSum+=filteredSamples[Math.floor(Math.random()*sampleCount)];}
+this.sampleMeans_.push(tempSum/sampleCount);}
+this.sampleMeans_.sort((a,b)=>a-b);}
+return[this.sampleMeans_[Math.floor((iterations-1)*(0.5-percent/2))],this.sampleMeans_[Math.ceil((iterations-1)*(0.5+percent/2))],];}
+sampleValuesInto(samples){for(const sampleValue of this.sampleValues){samples.push(sampleValue);}}
+canAddHistogram(other){if(this.unit!==other.unit){return false;}
+if(this.binBoundariesDict_===other.binBoundariesDict_){return true;}
+if(!this.binBoundariesDict_||!other.binBoundariesDict_){return true;}
+if(this.binBoundariesDict_.length!==other.binBoundariesDict_.length){return false;}
+for(let i=0;i<this.binBoundariesDict_.length;++i){const slice=this.binBoundariesDict_[i];const otherSlice=other.binBoundariesDict_[i];if(slice instanceof Array){if(!(otherSlice instanceof Array)){return false;}
+if(slice[0]!==otherSlice[0]||!tr.b.math.approximately(slice[1],otherSlice[1])||slice[2]!==otherSlice[2]){return false;}}else{if(otherSlice instanceof Array){return false;}
+if(!tr.b.math.approximately(slice,otherSlice)){return false;}}}
+return true;}
+addHistogram(other){if(!this.canAddHistogram(other)){throw new Error('Merging incompatible Histograms');}
+if(!!this.binBoundariesDict_===!!other.binBoundariesDict_){for(let i=0;i<this.allBins.length;++i){let bin=this.allBins[i];if(bin.count===0){bin=new HistogramBin(bin.range);this.allBins[i]=bin;}
+bin.addBin(other.allBins[i]);}}else{const[multiBin,singleBin]=this.binBoundariesDict_?[this,other]:[other,this];for(const value of singleBin.sampleValues){if(typeof(value)!=='number'||isNaN(value)){continue;}
+const binIndex=multiBin.getBinIndexForValue(value);let bin=multiBin.allBins[binIndex];if(bin.count===0){bin=new HistogramBin(bin.range);multiBin.allBins[binIndex]=bin;}
+bin.addSample(value);}}
+tr.b.math.Statistics.mergeSampledStreams(this.nanDiagnosticMaps,this.numNans,other.nanDiagnosticMaps,other.numNans,MAX_DIAGNOSTIC_MAPS);tr.b.math.Statistics.mergeSampledStreams(this.sampleValues,this.numValues+this.numNans,other.sampleValues,other.numValues+other.numNans,(this.maxNumSampleValues+other.maxNumSampleValues)/2);this.numNans+=other.numNans;if(other.running_!==undefined){if(this.running_===undefined){this.running_=new tr.b.math.RunningStatistics();}
+this.running_=this.running_.merge(other.running_);}
+this.sampleMeans_=[];this.diagnostics.addDiagnostics(other.diagnostics);for(const[stat,option]of other.summaryOptions){if(stat==='percentile'){const percentiles=this.summaryOptions.get(stat);for(const percent of option){if(!percentiles.includes(percent))percentiles.push(percent);}}else if(stat==='iprs'){const thisIprs=this.summaryOptions.get(stat);for(const ipr of option){let found=false;for(const thisIpr of thisIprs){found=ipr.equals(thisIpr);if(found)break;}
+if(!found)thisIprs.push(ipr);}}else if(stat==='ci'){const CIs=this.summaryOptions.get(stat);for(const CI of option){if(!CIs.includes(CI))CIs.push(CI);}}else if(option&&!this.summaryOptions.get(stat)){this.summaryOptions.set(stat,true);}}}
+customizeSummaryOptions(summaryOptions){for(const[key,value]of Object.entries(summaryOptions)){this.summaryOptions.set(key,value);}}
+getStatisticScalar(statName,opt_referenceHistogram,opt_mwu){if(statName==='avg'){if(typeof(this.average)!=='number')return undefined;return new tr.b.Scalar(this.unit,this.average);}
+if(statName==='std'){if(typeof(this.standardDeviation)!=='number')return undefined;return new tr.b.Scalar(this.unit,this.standardDeviation);}
+if(statName==='geometricMean'){if(typeof(this.geometricMean)!=='number')return undefined;return new tr.b.Scalar(this.unit,this.geometricMean);}
+if(statName==='min'||statName==='max'||statName==='sum'){if(this.running_===undefined){this.running_=new tr.b.math.RunningStatistics();}
+if(typeof(this.running_[statName])!=='number')return undefined;return new tr.b.Scalar(this.unit,this.running_[statName]);}
+if(statName==='nans'){return new tr.b.Scalar(tr.b.Unit.byName.count_smallerIsBetter,this.numNans);}
+if(statName==='count'){return new tr.b.Scalar(tr.b.Unit.byName.count_smallerIsBetter,this.numValues);}
+if(statName.substr(0,4)==='pct_'){if(this.numValues===0)return undefined;const percent=percentFromString(statName.substr(4));const percentile=this.getApproximatePercentile(percent);if(typeof(percentile)!=='number')return undefined;return new tr.b.Scalar(this.unit,percentile);}
+if(statName.substr(0,3)==='ci_'){const percent=percentFromString(statName.substr(3,3));const[lowCI,highCI]=this.resampleMean_(percent);if(statName.substr(7)==='lower'){if(typeof(lowCI)!=='number')return undefined;return new tr.b.Scalar(this.unit,lowCI);}else if(statName.substr(7)==='upper'){if(typeof(highCI)!=='number')return undefined;return new tr.b.Scalar(this.unit,highCI);}
+if(typeof(highCI)!=='number'||typeof(lowCI)!=='number'){return undefined;}
+return new tr.b.Scalar(this.unit,highCI-lowCI);}
+if(statName.substr(0,4)==='ipr_'){let lower=percentFromString(statName.substr(4,3));let upper=percentFromString(statName.substr(8));if(lower>=upper){throw new Error('Invalid inter-percentile range: '+statName);}
+lower=this.getApproximatePercentile(lower);upper=this.getApproximatePercentile(upper);const ipr=upper-lower;if(typeof(ipr)!=='number')return undefined;return new tr.b.Scalar(this.unit,ipr);}
+if(!this.canCompare(opt_referenceHistogram)){throw new Error('Cannot compute '+statName+' when histograms are not comparable');}
+const suffix=tr.b.Unit.nameSuffixForImprovementDirection(this.unit.improvementDirection);const deltaIndex=statName.indexOf(DELTA);if(deltaIndex>=0){const baseStatName=statName.substr(deltaIndex+1);const thisStat=this.getStatisticScalar(baseStatName);const otherStat=opt_referenceHistogram.getStatisticScalar(baseStatName);const deltaValue=thisStat.value-otherStat.value;if(statName[0]==='%'){return new tr.b.Scalar(tr.b.Unit.byName['normalizedPercentageDelta'+suffix],deltaValue/otherStat.value);}
+return new tr.b.Scalar(thisStat.unit.correspondingDeltaUnit,deltaValue);}
+if(statName===Z_SCORE_NAME){return new tr.b.Scalar(tr.b.Unit.byName['sigmaDelta'+suffix],(this.average-opt_referenceHistogram.average)/opt_referenceHistogram.standardDeviation);}
+const mwu=opt_mwu||tr.b.math.Statistics.mwu(this.sampleValues,opt_referenceHistogram.sampleValues);if(statName===P_VALUE_NAME){return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber,mwu.p);}
+if(statName===U_STATISTIC_NAME){return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber,mwu.U);}
+throw new Error('Unrecognized statistic name: '+statName);}
+get statisticsNames(){const statisticsNames=new Set();for(const[statName,option]of this.summaryOptions){if(statName==='percentile'){for(const pctile of option){statisticsNames.add('pct_'+tr.v.percentToString(pctile));}}else if(statName==='iprs'){for(const range of option){statisticsNames.add('ipr_'+tr.v.percentToString(range.min,true)+'_'+tr.v.percentToString(range.max,true));}}else if(statName==='ci'){for(const CIpctile of option){const CIpctStr=tr.v.percentToString(CIpctile);statisticsNames.add('ci_'+CIpctStr+'_lower');statisticsNames.add('ci_'+CIpctStr+'_upper');statisticsNames.add('ci_'+CIpctStr);}}else if(option){statisticsNames.add(statName);}}
+return statisticsNames;}
+canCompare(other){return other instanceof Histogram&&this.unit===other.unit&&this.numValues>0&&other.numValues>0;}
+getAvailableStatisticName(statName,opt_referenceHist){if(this.canCompare(opt_referenceHist))return statName;if(statName===Z_SCORE_NAME||statName===P_VALUE_NAME||statName===U_STATISTIC_NAME){return'avg';}
+const deltaIndex=statName.indexOf(DELTA);if(deltaIndex<0)return statName;return statName.substr(deltaIndex+1);}
+static getDeltaStatisticsNames(statNames){const deltaNames=[];for(const statName of statNames){deltaNames.push(`${DELTA}${statName}`);deltaNames.push(`%${DELTA}${statName}`);}
+return deltaNames.concat([Z_SCORE_NAME,P_VALUE_NAME,U_STATISTIC_NAME]);}
+get statisticsScalars(){const results=new Map();for(const statName of this.statisticsNames){const scalar=this.getStatisticScalar(statName);if(scalar===undefined)continue;results.set(statName,scalar);}
+return results;}
+get sampleValues(){return this.sampleValues_;}
+clone(){const binBoundaries=HistogramBinBoundaries.fromDict(this.binBoundariesDict_);const hist=new Histogram(this.name,this.unit,binBoundaries);for(const[stat,option]of this.summaryOptions){if(stat==='percentile'||stat==='iprs'||stat==='ci'){hist.summaryOptions.set(stat,Array.from(option));}else{hist.summaryOptions.set(stat,option);}}
+hist.addHistogram(this);return hist;}
+rebin(newBoundaries){const rebinned=new tr.v.Histogram(this.name,this.unit,newBoundaries);rebinned.description=this.description;for(const sample of this.sampleValues){rebinned.addSample(sample);}
+rebinned.running_=this.running_;for(const[name,diagnostic]of this.diagnostics){rebinned.diagnostics.set(name,diagnostic);}
+for(const[stat,option]of this.summaryOptions){if(stat==='percentile'||stat==='ci'){rebinned.summaryOptions.set(stat,Array.from(option));}else{rebinned.summaryOptions.set(stat,option);}}
+return rebinned;}
+serialize(serializer){let nanBin=this.numNans;if(this.nanDiagnosticMaps.length){nanBin=[nanBin,...this.nanDiagnosticMaps.map(dm=>[undefined,...dm.serialize(serializer)])];}
+this.diagnostics.set(tr.v.d.RESERVED_NAMES.STATISTICS_NAMES,new tr.v.d.GenericSet([...this.statisticsNames].sort()));this.diagnostics.set(tr.v.d.RESERVED_NAMES.DESCRIPTION,new tr.v.d.GenericSet([this.description].sort()));return[serializer.getOrAllocateId(this.name),this.unit.asJSON2(),serializer.getOrAllocateId(this.binBoundariesDict_),this.diagnostics.serialize(serializer),this.running_?this.running_.asDict():0,this.serializeBins_(serializer),nanBin,];}
+asDict(){const dict={};dict.name=this.name;dict.unit=this.unit.asJSON();if(this.binBoundariesDict_!==undefined){dict.binBoundaries=this.binBoundariesDict_;}
+if(this.description){dict.description=this.description;}
+if(this.diagnostics.size){dict.diagnostics=this.diagnostics.asDict();}
+if(this.maxNumSampleValues!==this.defaultMaxNumSampleValues_){dict.maxNumSampleValues=this.maxNumSampleValues;}
+if(this.numNans){dict.numNans=this.numNans;}
+if(this.nanDiagnosticMaps.length){dict.nanDiagnostics=this.nanDiagnosticMaps.map(dm=>dm.asDict());}
+if(this.numValues){dict.sampleValues=this.sampleValues.slice();this.running.truncate(this.unit);dict.running=this.running_.asDict();dict.allBins=this.allBinsAsDict_();}
+const summaryOptions={};let anyOverriddenSummaryOptions=false;for(const[name,value]of this.summaryOptions){let option;if(name==='percentile'){if(value.length===0)continue;option=Array.from(value);}else if(name==='iprs'){if(value.length===0)continue;option=value.map(r=>[r.min,r.max]);}else if(name==='ci'){if(value.length===0)continue;option=Array.from(value);}else if(value===DEFAULT_SUMMARY_OPTIONS.get(name)){continue;}else{option=value;}
+summaryOptions[name]=option;anyOverriddenSummaryOptions=true;}
+if(anyOverriddenSummaryOptions){dict.summaryOptions=summaryOptions;}
+return dict;}
+serializeBins_(serializer){const numBins=this.allBins.length;let emptyBins=0;for(let i=0;i<numBins;++i){if(this.allBins[i].count===0){++emptyBins;}}
+if(emptyBins===numBins){return 0;}
+if(emptyBins>(numBins/2)){const allBinsDict={};for(let i=0;i<numBins;++i){const bin=this.allBins[i];if(bin.count>0){allBinsDict[i]=bin.serialize(serializer);}}
+return allBinsDict;}
+const allBinsArray=[];for(let i=0;i<numBins;++i){allBinsArray.push(this.allBins[i].serialize(serializer));}
+return allBinsArray;}
+allBinsAsDict_(){const numBins=this.allBins.length;let emptyBins=0;for(let i=0;i<numBins;++i){if(this.allBins[i].count===0){++emptyBins;}}
+if(emptyBins===numBins){return undefined;}
+if(emptyBins>(numBins/2)){const allBinsDict={};for(let i=0;i<numBins;++i){const bin=this.allBins[i];if(bin.count>0){allBinsDict[i]=bin.asDict();}}
+return allBinsDict;}
+const allBinsArray=[];for(let i=0;i<numBins;++i){allBinsArray.push(this.allBins[i].asDict());}
+return allBinsArray;}
+get defaultMaxNumSampleValues_(){return DEFAULT_SAMPLE_VALUES_PER_BIN*Math.max(this.allBins.length,DEFAULT_REBINNED_COUNT);}}
+Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS={count:false,max:false,min:false,std:false,sum:false,};const HISTOGRAM_BIN_BOUNDARIES_CACHE=new Map();class HistogramBinBoundaries{static createLinear(min,max,numBins){return new HistogramBinBoundaries(min).addLinearBins(max,numBins);}
+static createExponential(min,max,numBins){return new HistogramBinBoundaries(min).addExponentialBins(max,numBins);}
+static createWithBoundaries(binBoundaries){const builder=new HistogramBinBoundaries(binBoundaries[0]);for(const boundary of binBoundaries.slice(1)){builder.addBinBoundary(boundary);}
+return builder;}
+constructor(minBinBoundary){this.builder_=[minBinBoundary];this.range_=new tr.b.math.Range();this.range_.addValue(minBinBoundary);this.binRanges_=undefined;this.bins_=undefined;}
+get range(){return this.range_;}
+asDict(){if(this.builder_.length===1&&this.builder_[0]===Number.MAX_VALUE){return undefined;}
+return this.builder_;}
+pushBuilderSlice_(slice){this.builder_.push(slice);this.builder_=this.builder_.slice();}
+static fromDict(dict){if(dict===undefined){return HistogramBinBoundaries.SINGULAR;}
+const cacheKey=JSON.stringify(dict);if(HISTOGRAM_BIN_BOUNDARIES_CACHE.has(cacheKey)){return HISTOGRAM_BIN_BOUNDARIES_CACHE.get(cacheKey);}
+const binBoundaries=new HistogramBinBoundaries(dict[0]);for(const slice of dict.slice(1)){if(!(slice instanceof Array)){binBoundaries.addBinBoundary(slice);continue;}
+switch(slice[0]){case HistogramBinBoundaries.SLICE_TYPE.LINEAR:binBoundaries.addLinearBins(slice[1],slice[2]);break;case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL:binBoundaries.addExponentialBins(slice[1],slice[2]);break;default:throw new Error('Unrecognized HistogramBinBoundaries slice type');}}
+HISTOGRAM_BIN_BOUNDARIES_CACHE.set(cacheKey,binBoundaries);return binBoundaries;}
+get bins(){if(this.bins_===undefined){this.buildBins_();}
+return this.bins_;}
+buildBins_(){this.bins_=this.binRanges.map(r=>new HistogramBin(r));}
+get binRanges(){if(this.binRanges_===undefined){this.buildBinRanges_();}
+return this.binRanges_;}
+buildBinRanges_(){if(typeof this.builder_[0]!=='number'){throw new Error('Invalid start of builder_');}
+this.binRanges_=[];let prevBoundary=this.builder_[0];if(prevBoundary>-Number.MAX_VALUE){this.binRanges_.push(tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE,prevBoundary));}
+for(const slice of this.builder_.slice(1)){if(!(slice instanceof Array)){this.binRanges_.push(tr.b.math.Range.fromExplicitRange(prevBoundary,slice));prevBoundary=slice;continue;}
+const nextMaxBinBoundary=slice[1];const binCount=slice[2];const sliceMinBinBoundary=prevBoundary;switch(slice[0]){case HistogramBinBoundaries.SLICE_TYPE.LINEAR:{const binWidth=(nextMaxBinBoundary-prevBoundary)/binCount;for(let i=1;i<binCount;i++){const boundary=sliceMinBinBoundary+i*binWidth;this.binRanges_.push(tr.b.math.Range.fromExplicitRange(prevBoundary,boundary));prevBoundary=boundary;}
+break;}
+case HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL:{const binExponentWidth=Math.log(nextMaxBinBoundary/prevBoundary)/binCount;for(let i=1;i<binCount;i++){const boundary=sliceMinBinBoundary*Math.exp(i*binExponentWidth);this.binRanges_.push(tr.b.math.Range.fromExplicitRange(prevBoundary,boundary));prevBoundary=boundary;}
+break;}
+default:throw new Error('Unrecognized HistogramBinBoundaries slice type');}
+this.binRanges_.push(tr.b.math.Range.fromExplicitRange(prevBoundary,nextMaxBinBoundary));prevBoundary=nextMaxBinBoundary;}
+if(prevBoundary<Number.MAX_VALUE){this.binRanges_.push(tr.b.math.Range.fromExplicitRange(prevBoundary,Number.MAX_VALUE));}}
+addBinBoundary(nextMaxBinBoundary){if(nextMaxBinBoundary<=this.range.max){throw new Error('The added max bin boundary must be larger than '+'the current max boundary');}
+this.binRanges_=undefined;this.bins_=undefined;this.pushBuilderSlice_(nextMaxBinBoundary);this.range.addValue(nextMaxBinBoundary);return this;}
+addLinearBins(nextMaxBinBoundary,binCount){if(binCount<=0){throw new Error('Bin count must be positive');}
+if(nextMaxBinBoundary<=this.range.max){throw new Error('The new max bin boundary must be greater than '+'the previous max bin boundary');}
+this.binRanges_=undefined;this.bins_=undefined;this.pushBuilderSlice_([HistogramBinBoundaries.SLICE_TYPE.LINEAR,nextMaxBinBoundary,binCount]);this.range.addValue(nextMaxBinBoundary);return this;}
+addExponentialBins(nextMaxBinBoundary,binCount){if(binCount<=0){throw new Error('Bin count must be positive');}
+if(this.range.max<=0){throw new Error('Current max bin boundary must be positive');}
+if(this.range.max>=nextMaxBinBoundary){throw new Error('The last added max boundary must be greater than '+'the current max boundary boundary');}
+this.binRanges_=undefined;this.bins_=undefined;this.pushBuilderSlice_([HistogramBinBoundaries.SLICE_TYPE.EXPONENTIAL,nextMaxBinBoundary,binCount]);this.range.addValue(nextMaxBinBoundary);return this;}}
+HistogramBinBoundaries.SLICE_TYPE={LINEAR:0,EXPONENTIAL:1,};HistogramBinBoundaries.SINGULAR=new HistogramBinBoundaries(Number.MAX_VALUE);DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.timeDurationInMs.unitName,HistogramBinBoundaries.createExponential(1e-3,1e6,1e2));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.timeInMsAutoFormat.unitName,new HistogramBinBoundaries(0).addBinBoundary(1).addExponentialBins(1e3,3).addBinBoundary(tr.b.convertUnit(2,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(5,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(10,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(30,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.MINUTE.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(2*tr.b.convertUnit(tr.b.UnitScale.TIME.MINUTE.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(5*tr.b.convertUnit(tr.b.UnitScale.TIME.MINUTE.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(10*tr.b.convertUnit(tr.b.UnitScale.TIME.MINUTE.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(30*tr.b.convertUnit(tr.b.UnitScale.TIME.MINUTE.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.HOUR.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(2*tr.b.convertUnit(tr.b.UnitScale.TIME.HOUR.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(6*tr.b.convertUnit(tr.b.UnitScale.TIME.HOUR.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(12*tr.b.convertUnit(tr.b.UnitScale.TIME.HOUR.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.DAY.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.WEEK.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.MONTH.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)).addBinBoundary(tr.b.convertUnit(tr.b.UnitScale.TIME.YEAR.value,tr.b.UnitScale.TIME.SEC,tr.b.UnitScale.TIME.MILLI_SEC)));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.timeStampInMs.unitName,HistogramBinBoundaries.createLinear(0,1e10,1e3));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.normalizedPercentage.unitName,HistogramBinBoundaries.createLinear(0,1.0,20));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.sizeInBytes.unitName,HistogramBinBoundaries.createExponential(1,1e12,1e2));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.energyInJoules.unitName,HistogramBinBoundaries.createExponential(1e-3,1e3,50));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.powerInWatts.unitName,HistogramBinBoundaries.createExponential(1e-3,1,50));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.unitlessNumber.unitName,HistogramBinBoundaries.createExponential(1e-3,1e3,50));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.count.unitName,HistogramBinBoundaries.createExponential(1,1e3,20));DEFAULT_BOUNDARIES_FOR_UNIT.set(tr.b.Unit.byName.sigma.unitName,HistogramBinBoundaries.createLinear(-5,5,50));return{DEFAULT_REBINNED_COUNT,DELTA,Histogram,HistogramBinBoundaries,P_VALUE_NAME,U_STATISTIC_NAME,Z_SCORE_NAME,percentFromString,percentToString,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-scalar-context-controller',created(){this.host_=undefined;this.groupToContext_=new Map();this.dirtyGroups_=new Set();},attached(){if(this.host_){throw new Error('Scalar context controller is already attached to a host');}
+const host=findParentOrHost(this);if(host.__scalarContextController){throw new Error('Multiple scalar context controllers attached to this host');}
+host.__scalarContextController=this;this.host_=host;},detached(){if(!this.host_){throw new Error('Scalar context controller is not attached to a host');}
+if(this.host_.__scalarContextController!==this){throw new Error('Scalar context controller is not attached to its host');}
+delete this.host_.__scalarContextController;this.host_=undefined;},getContext(group){return this.groupToContext_.get(group);},onScalarSpanAdded(group,span){let context=this.groupToContext_.get(group);if(context===undefined){context={spans:new Set(),range:new tr.b.math.Range()};this.groupToContext_.set(group,context);}
+if(context.spans.has(span)){throw new Error('Scalar span already registered with group: '+group);}
+context.spans.add(span);this.markGroupDirtyAndScheduleUpdate_(group);},onScalarSpanRemoved(group,span){const context=this.groupToContext_.get(group);if(!context.spans.has(span)){throw new Error('Scalar span not registered with group: '+group);}
+context.spans.delete(span);this.markGroupDirtyAndScheduleUpdate_(group);},onScalarSpanUpdated(group,span){const context=this.groupToContext_.get(group);if(!context.spans.has(span)){throw new Error('Scalar span not registered with group: '+group);}
+this.markGroupDirtyAndScheduleUpdate_(group);},markGroupDirtyAndScheduleUpdate_(group){const alreadyDirty=this.dirtyGroups_.size>0;this.dirtyGroups_.add(group);if(!alreadyDirty){tr.b.requestAnimationFrameInThisFrameIfPossible(this.updateContext,this);}},updateContext(){const groups=this.dirtyGroups_;if(groups.size===0)return;this.dirtyGroups_=new Set();for(const group of groups){this.updateGroup_(group);}
+const event=new tr.b.Event('context-updated');event.groups=groups;this.dispatchEvent(event);},updateGroup_(group){const context=this.groupToContext_.get(group);if(context.spans.size===0){this.groupToContext_.delete(group);return;}
+context.range.reset();for(const span of context.spans){context.range.addValue(span.value);}}});function getScalarContextControllerForElement(element){while(element){if(element.__scalarContextController){return element.__scalarContextController;}
+element=findParentOrHost(element);}
+return undefined;}
+function findParentOrHost(node){if(node.parentElement){return node.parentElement;}
+while(Polymer.dom(node).parentNode){node=Polymer.dom(node).parentNode;}
+return node.host;}
+return{getScalarContextControllerForElement,};});'use strict';tr.exportTo('tr.v.ui',function(){function createScalarSpan(value,opt_config){if(value===undefined)return'';const config=opt_config||{};const ownerDocument=config.ownerDocument||document;const span=unwrap(ownerDocument).createElement('tr-v-ui-scalar-span');let numericValue;if(value instanceof tr.b.Scalar){span.value=value;numericValue=value.value;}else if(value instanceof tr.v.Histogram){numericValue=value.average;if(numericValue===undefined)return'';span.setValueAndUnit(numericValue,value.unit);}else{const unit=config.unit;if(unit===undefined){throw new Error('Unit must be provided in config when value is a number');}
+span.setValueAndUnit(value,unit);numericValue=value;}
+if(config.context){span.context=config.context;}
+if(config.customContextRange){span.customContextRange=config.customContextRange;}
+if(config.leftAlign){span.leftAlign=true;}
+if(config.inline){span.inline=true;}
+if(config.significance!==undefined){span.significance=config.significance;}
+if(config.contextGroup!==undefined){span.contextGroup=config.contextGroup;}
+return span;}
+return{createScalarSpan,};});'use strict';Polymer({is:'tr-v-ui-scalar-span',properties:{contextGroup:{type:String,reflectToAttribute:true,observer:'contextGroupChanged_'}},created(){this.value_=undefined;this.unit_=undefined;this.context_=undefined;this.warning_=undefined;this.significance_=tr.b.math.Statistics.Significance.DONT_CARE;this.shouldSearchForContextController_=false;this.lazyContextController_=undefined;this.onContextUpdated_=this.onContextUpdated_.bind(this);this.updateContents_=this.updateContents_.bind(this);this.customContextRange_=undefined;},get significance(){return this.significance_;},set significance(s){this.significance_=s;this.updateContents_();},set contentTextDecoration(deco){this.$.content.style.textDecoration=deco;},get value(){return this.value_;},set value(value){if(value instanceof tr.b.Scalar){this.value_=value.value;this.unit_=value.unit;}else{this.value_=value;}
+this.updateContents_();if(this.hasContext_(this.contextGroup)){this.contextController_.onScalarSpanUpdated(this.contextGroup,this);}else{this.updateSparkline_();}},get contextController_(){if(this.shouldSearchForContextController_){this.lazyContextController_=tr.v.ui.getScalarContextControllerForElement(this);this.shouldSearchForContextController_=false;}
+return this.lazyContextController_;},hasContext_(contextGroup){return!!(contextGroup&&this.contextController_);},contextGroupChanged_(newContextGroup,oldContextGroup){this.detachFromContextControllerIfPossible_(oldContextGroup);if(!this.attachToContextControllerIfPossible_(newContextGroup)){this.onContextUpdated_();}},attachToContextControllerIfPossible_(contextGroup){if(!this.hasContext_(contextGroup))return false;this.contextController_.addEventListener('context-updated',this.onContextUpdated_);this.contextController_.onScalarSpanAdded(contextGroup,this);return true;},detachFromContextControllerIfPossible_(contextGroup){if(!this.hasContext_(contextGroup))return;this.contextController_.removeEventListener('context-updated',this.onContextUpdated_);this.contextController_.onScalarSpanRemoved(contextGroup,this);},attached(){tr.b.Unit.addEventListener('display-mode-changed',this.updateContents_);this.shouldSearchForContextController_=true;this.attachToContextControllerIfPossible_(this.contextGroup);},detached(){tr.b.Unit.removeEventListener('display-mode-changed',this.updateContents_);this.detachFromContextControllerIfPossible_(this.contextGroup);this.shouldSearchForContextController_=false;this.lazyContextController_=undefined;},onContextUpdated_(){this.updateSparkline_();},get context(){return this.context_;},set context(context){this.context_=context;this.updateContents_();},get unit(){return this.unit_;},set unit(unit){this.unit_=unit;this.updateContents_();this.updateSparkline_();},setValueAndUnit(value,unit){this.value_=value;this.unit_=unit;this.updateContents_();},get customContextRange(){return this.customContextRange_;},set customContextRange(customContextRange){this.customContextRange_=customContextRange;this.updateSparkline_();},get inline(){return Polymer.dom(this).classList.contains('inline');},set inline(inline){if(inline){Polymer.dom(this).classList.add('inline');}else{Polymer.dom(this).classList.remove('inline');}},get leftAlign(){return Polymer.dom(this).classList.contains('left-align');},set leftAlign(leftAlign){if(leftAlign){Polymer.dom(this).classList.add('left-align');}else{Polymer.dom(this).classList.remove('left-align');}},updateSparkline_(){Polymer.dom(this.$.sparkline).classList.remove('positive');Polymer.dom(this.$.sparkline).classList.remove('better');Polymer.dom(this.$.sparkline).classList.remove('worse');Polymer.dom(this.$.sparkline).classList.remove('same');this.$.sparkline.style.display='none';this.$.sparkline.style.left='0';this.$.sparkline.style.width='0';let range=this.customContextRange_;if(!range&&this.hasContext_(this.contextGroup)){const context=this.contextController_.getContext(this.contextGroup);if(context){range=context.range;}}
+if(!range||range.isEmpty)return;const leftPoint=Math.min(range.min,0);const rightPoint=Math.max(range.max,0);const pointDistance=rightPoint-leftPoint;if(pointDistance===0){return;}
+this.$.sparkline.style.display='block';let left;let width;if(this.value>0){width=Math.min(this.value,rightPoint);left=-leftPoint;Polymer.dom(this.$.sparkline).classList.add('positive');}else if(this.value<=0){width=-Math.max(this.value,leftPoint);left=(-leftPoint)-width;}
+this.$.sparkline.style.left=this.buildSparklineStyle_(left/pointDistance,false);this.$.sparkline.style.width=this.buildSparklineStyle_(width/pointDistance,true);const changeClass=this.changeClassName_;if(changeClass){Polymer.dom(this.$.sparkline).classList.add(changeClass);}},buildSparklineStyle_(ratio,isWidth){let position='calc('+ratio+' * (100% - 1px)';if(isWidth){position+=' + 1px';}
+position+=')';return position;},updateContents_(){Polymer.dom(this.$.content).textContent='';Polymer.dom(this.$.content).classList.remove('better');Polymer.dom(this.$.content).classList.remove('worse');Polymer.dom(this.$.content).classList.remove('same');this.$.insignificant.style.display='';this.$.significantly_better.style.display='';this.$.significantly_worse.style.display='';if(this.unit_===undefined)return;this.$.content.title='';Polymer.dom(this.$.content).textContent=this.unit_.format(this.value,this.context);this.updateDelta_();},updateDelta_(){let changeClass=this.changeClassName_;if(!changeClass){this.$.significance.style.display='none';return;}
+this.$.significance.style.display='inline';let title;switch(changeClass){case'better':title='improvement';break;case'worse':title='regression';break;case'same':title='no change';break;default:throw new Error('Unknown change class: '+changeClass);}
+Polymer.dom(this.$.content).classList.add(changeClass);switch(this.significance){case tr.b.math.Statistics.Significance.DONT_CARE:break;case tr.b.math.Statistics.Significance.INSIGNIFICANT:if(changeClass!=='same')title='insignificant '+title;this.$.insignificant.style.display='inline';changeClass='same';break;case tr.b.math.Statistics.Significance.SIGNIFICANT:if(changeClass==='same'){throw new Error('How can no change be significant?');}
+this.$['significantly_'+changeClass].style.display='inline';title='significant '+title;break;default:throw new Error('Unknown significance '+this.significance);}
+this.$.significance.title=title;this.$.content.title=title;},get changeClassName_(){if(!this.unit_||!this.unit_.isDelta)return undefined;switch(this.unit_.improvementDirection){case tr.b.ImprovementDirection.DONT_CARE:return undefined;case tr.b.ImprovementDirection.BIGGER_IS_BETTER:if(this.value===0)return'same';return this.value>0?'better':'worse';case tr.b.ImprovementDirection.SMALLER_IS_BETTER:if(this.value===0)return'same';return this.value<0?'better':'worse';default:throw new Error('Unknown improvement direction: '+
+this.unit_.improvementDirection);}},get warning(){return this.warning_;},set warning(warning){this.warning_=warning;const warningEl=this.$.warning;if(this.warning_){warningEl.title=warning;warningEl.style.display='inline';}else{warningEl.title='';warningEl.style.display='';}},get timestamp(){return this.value;},set timestamp(timestamp){if(timestamp instanceof tr.b.u.TimeStamp){this.value=timestamp;return;}
+this.setValueAndUnit(timestamp,tr.b.u.Units.timeStampInMs);},get duration(){return this.value;},set duration(duration){if(duration instanceof tr.b.u.TimeDuration){this.value=duration;return;}
+this.setValueAndUnit(duration,tr.b.u.Units.timeDurationInMs);}});'use strict';function isTable(object){if(!(object instanceof Array)||(object.length<2))return false;for(const colName in object[0]){if(typeof colName!=='string')return false;}
+for(let i=0;i<object.length;++i){if(!(object[i]instanceof Object))return false;for(const colName in object[i]){if(i&&(object[0][colName]===undefined))return false;const cellType=typeof object[i][colName];if(cellType!=='string'&&cellType!=='number')return false;}
+if(i){for(const colName in object[0]){if(object[i][colName]===undefined)return false;}}}
+return true;}
+Polymer({is:'tr-ui-a-generic-object-view',ready(){this.object_=undefined;},get object(){return this.object_;},set object(object){this.object_=object;this.updateContents_();},updateContents_(){Polymer.dom(this.$.content).textContent='';this.appendElementsForType_('',this.object_,0,0,5,'');},appendElementsForType_(label,object,indent,depth,maxDepth,suffix){if(depth>maxDepth){this.appendSimpleText_(label,indent,'<recursion limit reached>',suffix);return;}
+if(object===undefined){this.appendSimpleText_(label,indent,'undefined',suffix);return;}
+if(object===null){this.appendSimpleText_(label,indent,'null',suffix);return;}
+if(!(object instanceof Object)){const type=typeof object;if(type!=='string'){return this.appendSimpleText_(label,indent,object,suffix);}
+let objectReplaced=false;if((object[0]==='{'&&object[object.length-1]==='}')||(object[0]==='['&&object[object.length-1]===']')){try{object=JSON.parse(object);objectReplaced=true;}catch(e){}}
+if(!objectReplaced){if(object.includes('\n')){const lines=object.split('\n');lines.forEach(function(line,i){let text;let ioff;let ll;let ss;if(i===0){text='"'+line;ioff=0;ll=label;ss='';}else if(i<lines.length-1){text=line;ioff=1;ll='';ss='';}else{text=line+'"';ioff=1;ll='';ss=suffix;}
+const el=this.appendSimpleText_(ll,indent+ioff*label.length+ioff,text,ss);el.style.whiteSpace='pre';return el;},this);return;}
+if(tr.b.isUrl(object)){const link=document.createElement('a');link.href=object;link.textContent=object;this.appendElementWithLabel_(label,indent,link,suffix);return;}
+this.appendSimpleText_(label,indent,'"'+object+'"',suffix);return;}}
+if(object instanceof tr.model.ObjectSnapshot){const link=document.createElement('tr-ui-a-analysis-link');link.selection=new tr.model.EventSet(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
+if(object instanceof tr.model.ObjectInstance){const link=document.createElement('tr-ui-a-analysis-link');link.selection=new tr.model.EventSet(object);this.appendElementWithLabel_(label,indent,link,suffix);return;}
+if(object instanceof tr.b.math.Rect){this.appendSimpleText_(label,indent,object.toString(),suffix);return;}
+if(object instanceof tr.b.Scalar){const el=this.ownerDocument.createElement('tr-v-ui-scalar-span');el.value=object;el.inline=true;this.appendElementWithLabel_(label,indent,el,suffix);return;}
+if(object instanceof Array){this.appendElementsForArray_(label,object,indent,depth,maxDepth,suffix);return;}
+this.appendElementsForObject_(label,object,indent,depth,maxDepth,suffix);},appendElementsForArray_(label,object,indent,depth,maxDepth,suffix){if(object.length===0){this.appendSimpleText_(label,indent,'[]',suffix);return;}
+if(isTable(object)){const table=document.createElement('tr-ui-b-table');const columns=[];for(const colName of Object.keys(object[0])){let allStrings=true;let allNumbers=true;for(let i=0;i<object.length;++i){if(typeof(object[i][colName])!=='string'){allStrings=false;}
+if(typeof(object[i][colName])!=='number'){allNumbers=false;}
+if(!allStrings&&!allNumbers)break;}
+const column={title:colName};column.value=function(row){return row[colName];};if(allStrings){column.cmp=function(x,y){return x[colName].localeCompare(y[colName]);};}else if(allNumbers){column.cmp=function(x,y){return x[colName]-y[colName];};}
+columns.push(column);}
+table.tableColumns=columns;table.tableRows=object;this.appendElementWithLabel_(label,indent,table,suffix);table.rebuild();return;}
+this.appendElementsForType_(label+'[',object[0],indent,depth+1,maxDepth,object.length>1?',':']'+suffix);for(let i=1;i<object.length;i++){this.appendElementsForType_('',object[i],indent+label.length+1,depth+1,maxDepth,i<object.length-1?',':']'+suffix);}
+return;},appendElementsForObject_(label,object,indent,depth,maxDepth,suffix){const keys=Object.keys(object);if(keys.length===0){this.appendSimpleText_(label,indent,'{}',suffix);return;}
+this.appendElementsForType_(label+'{'+keys[0]+': ',object[keys[0]],indent,depth,maxDepth,keys.length>1?',':'}'+suffix);for(let i=1;i<keys.length;i++){this.appendElementsForType_(keys[i]+': ',object[keys[i]],indent+label.length+1,depth+1,maxDepth,i<keys.length-1?',':'}'+suffix);}},appendElementWithLabel_(label,indent,dataElement,suffix){const row=document.createElement('div');const indentSpan=document.createElement('span');indentSpan.style.whiteSpace='pre';for(let i=0;i<indent;i++){Polymer.dom(indentSpan).textContent+=' ';}
+Polymer.dom(row).appendChild(indentSpan);const labelSpan=document.createElement('span');Polymer.dom(labelSpan).textContent=label;Polymer.dom(row).appendChild(labelSpan);Polymer.dom(row).appendChild(dataElement);const suffixSpan=document.createElement('span');Polymer.dom(suffixSpan).textContent=suffix;Polymer.dom(row).appendChild(suffixSpan);row.dataElement=dataElement;Polymer.dom(this.$.content).appendChild(row);},appendSimpleText_(label,indent,text,suffix){const el=this.ownerDocument.createElement('span');Polymer.dom(el).textContent=text;this.appendElementWithLabel_(label,indent,el,suffix);return el;}});'use strict';Polymer({is:'tr-ui-a-generic-object-view-with-label',ready(){this.labelEl_=document.createElement('div');this.genericObjectView_=document.createElement('tr-ui-a-generic-object-view');Polymer.dom(this.root).appendChild(this.labelEl_);Polymer.dom(this.root).appendChild(this.genericObjectView_);},get label(){return Polymer.dom(this.labelEl_).textContent;},set label(label){Polymer.dom(this.labelEl_).textContent=label;},get object(){return this.genericObjectView_.object;},set object(object){this.genericObjectView_.object=object;}});'use strict';tr.exportTo('tr.ui.analysis',function(){const ObjectSnapshotView=tr.ui.b.define('object-snapshot-view');ObjectSnapshotView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.objectSnapshot_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectSnapshot=obj;},get modelEvent(){return this.objectSnapshot;},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(i){this.objectSnapshot_=i;this.updateContents();},updateContents(){throw new Error('Not implemented');}};const options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectSnapshotView;options.defaultMetadata={showInstances:true,showInTrackView:true};tr.b.decorateExtensionRegistry(ObjectSnapshotView,options);return{ObjectSnapshotView,};});'use strict';Polymer({is:'tr-ui-b-drag-handle',created(){this.lastMousePos_=0;this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.addEventListener('mousedown',this.onMouseDown_);this.target_=undefined;this.horizontal=true;this.observer_=new MutationObserver(this.didTargetMutate_.bind(this));this.targetSizesByModeKey_={};this.currentDraggingSize_=undefined;},get modeKey_(){return this.target_.className===''?'.':this.target_.className;},get target(){return this.target_;},set target(target){this.observer_.disconnect();this.target_=target;if(!this.target_)return;this.observer_.observe(this.target_,{attributes:true,attributeFilter:['class']});},get horizontal(){return this.horizontal_;},set horizontal(h){this.horizontal_=h;if(this.horizontal_){this.className='horizontal-drag-handle';}else{this.className='vertical-drag-handle';}},get vertical(){return!this.horizontal_;},set vertical(v){this.horizontal=!v;},forceMutationObserverFlush_(){const records=this.observer_.takeRecords();if(records.length){this.didTargetMutate_(records);}},didTargetMutate_(e){const modeSize=this.targetSizesByModeKey_[this.modeKey_];if(modeSize!==undefined){this.setTargetSize_(modeSize);return;}
+this.target_.style[this.targetStyleKey_]='';},get targetStyleKey_(){return this.horizontal_?'height':'width';},getTargetSize_(){const size=parseInt(window.getComputedStyle(this.target_)[this.targetStyleKey_]);this.targetSizesByModeKey_[this.modeKey_]=size;return size;},setTargetSize_(s){this.target_.style[this.targetStyleKey_]=s+'px';this.targetSizesByModeKey_[this.modeKey_]=this.getTargetSize_();tr.b.dispatchSimpleEvent(this,'drag-handle-resize',true,false);},applyDelta_(delta){if(this.target_===this.nextElementSibling){this.currentDraggingSize_+=delta;}else{this.currentDraggingSize_-=delta;}
+this.setTargetSize_(this.currentDraggingSize_);},onMouseMove_(e){const curMousePos=this.horizontal_?e.clientY:e.clientX;const delta=this.lastMousePos_-curMousePos;this.applyDelta_(delta);this.lastMousePos_=curMousePos;e.preventDefault();return true;},onMouseDown_(e){if(!this.target_)return;this.forceMutationObserverFlush_();this.currentDraggingSize_=this.getTargetSize_();this.lastMousePos_=this.horizontal_?e.clientY:e.clientX;document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);e.preventDefault();return true;},onMouseUp_(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);e.preventDefault();this.currentDraggingSize_=undefined;}});'use strict';tr.exportTo('tr.ui.b',function(){function HotKey(dict){if(dict.eventType===undefined){throw new Error('eventType must be given');}
+if(dict.keyCode===undefined&&dict.keyCodes===undefined){throw new Error('keyCode or keyCodes must be given');}
+if(dict.keyCode!==undefined&&dict.keyCodes!==undefined){throw new Error('Only keyCode or keyCodes can be given');}
+if(dict.callback===undefined){throw new Error('callback must be given');}
+this.eventType_=dict.eventType;this.keyCodes_=[];if(dict.keyCode){this.pushKeyCode_(dict.keyCode);}else if(dict.keyCodes){dict.keyCodes.forEach(this.pushKeyCode_,this);}
+this.useCapture_=!!dict.useCapture;this.callback_=dict.callback;this.thisArg_=dict.thisArg!==undefined?dict.thisArg:undefined;this.helpText_=dict.helpText!==undefined?dict.helpText:undefined;}
+HotKey.prototype={get eventType(){return this.eventType_;},get keyCodes(){return this.keyCodes_;},get helpText(){return this.helpText_;},call(e){this.callback_.call(this.thisArg_,e);},pushKeyCode_(keyCode){this.keyCodes_.push(keyCode);}};return{HotKey,};});'use strict';Polymer({is:'tv-ui-b-hotkey-controller',created(){this.isAttached_=false;this.globalMode_=false;this.slavedToParentController_=undefined;this.curHost_=undefined;this.childControllers_=[];this.bubblingKeyDownHotKeys_={};this.capturingKeyDownHotKeys_={};this.bubblingKeyPressHotKeys_={};this.capturingKeyPressHotKeys_={};this.onBubblingKeyDown_=this.onKey_.bind(this,false);this.onCapturingKeyDown_=this.onKey_.bind(this,true);this.onBubblingKeyPress_=this.onKey_.bind(this,false);this.onCapturingKeyPress_=this.onKey_.bind(this,true);},attached(){this.isAttached_=true;const host=this.findHost_();if(host.__hotkeyController){throw new Error('Multiple hotkey controllers attached to this host');}
+host.__hotkeyController=this;this.curHost_=host;let parentElement;if(host.parentElement){parentElement=host.parentElement;}else{parentElement=Polymer.dom(host).parentNode.host;}
+const parentController=tr.b.getHotkeyControllerForElement(parentElement);if(parentController){this.slavedToParentController_=parentController;parentController.addChildController_(this);return;}
+host.addEventListener('keydown',this.onBubblingKeyDown_,false);host.addEventListener('keydown',this.onCapturingKeyDown_,true);host.addEventListener('keypress',this.onBubblingKeyPress_,false);host.addEventListener('keypress',this.onCapturingKeyPress_,true);},detached(){this.isAttached_=false;const host=this.curHost_;if(!host)return;delete host.__hotkeyController;this.curHost_=undefined;if(this.slavedToParentController_){this.slavedToParentController_.removeChildController_(this);this.slavedToParentController_=undefined;return;}
+host.removeEventListener('keydown',this.onBubblingKeyDown_,false);host.removeEventListener('keydown',this.onCapturingKeyDown_,true);host.removeEventListener('keypress',this.onBubblingKeyPress_,false);host.removeEventListener('keypress',this.onCapturingKeyPress_,true);},addChildController_(controller){const i=this.childControllers_.indexOf(controller);if(i!==-1){throw new Error('Controller already registered');}
+this.childControllers_.push(controller);},removeChildController_(controller){const i=this.childControllers_.indexOf(controller);if(i===-1){throw new Error('Controller not registered');}
+this.childControllers_.splice(i,1);return controller;},getKeyMapForEventType_(eventType,useCapture){if(eventType==='keydown'){if(!useCapture){return this.bubblingKeyDownHotKeys_;}
+return this.capturingKeyDownHotKeys_;}
+if(eventType==='keypress'){if(!useCapture){return this.bubblingKeyPressHotKeys_;}
+return this.capturingKeyPressHotKeys_;}
+throw new Error('Unsupported key event');},addHotKey(hotKey){if(!(hotKey instanceof tr.ui.b.HotKey)){throw new Error('hotKey must be a tr.ui.b.HotKey');}
+const keyMap=this.getKeyMapForEventType_(hotKey.eventType,hotKey.useCapture);for(let i=0;i<hotKey.keyCodes.length;i++){const keyCode=hotKey.keyCodes[i];if(keyMap[keyCode]){throw new Error('Key is already bound for keyCode='+keyCode);}}
+for(let i=0;i<hotKey.keyCodes.length;i++){const keyCode=hotKey.keyCodes[i];keyMap[keyCode]=hotKey;}
+return hotKey;},removeHotKey(hotKey){if(!(hotKey instanceof tr.ui.b.HotKey)){throw new Error('hotKey must be a tr.ui.b.HotKey');}
+const keyMap=this.getKeyMapForEventType_(hotKey.eventType,hotKey.useCapture);for(let i=0;i<hotKey.keyCodes.length;i++){const keyCode=hotKey.keyCodes[i];if(!keyMap[keyCode]){throw new Error('Key is not bound for keyCode='+keyCode);}
+keyMap[keyCode]=hotKey;}
+for(let i=0;i<hotKey.keyCodes.length;i++){const keyCode=hotKey.keyCodes[i];delete keyMap[keyCode];}
+return hotKey;},get globalMode(){return this.globalMode_;},set globalMode(globalMode){const wasAttached=this.isAttached_;if(wasAttached){this.detached();}
+this.globalMode_=!!globalMode;if(wasAttached){this.attached();}},get topmostConroller_(){if(this.slavedToParentController_){return this.slavedToParentController_.topmostConroller_;}
+return this;},childRequestsGeneralFocus(child){const topmost=this.topmostConroller_;if(topmost.curHost_){if(topmost.curHost_.hasAttribute('tabIndex')){topmost.curHost_.focus();}else{if(document.activeElement){document.activeElement.blur();}}}else{if(document.activeElement){document.activeElement.blur();}}},childRequestsBlur(child){child.blur();const topmost=this.topmostConroller_;if(topmost.curHost_){topmost.curHost_.focus();}},findHost_(){if(this.globalMode_)return wrap(document.body);if(this.parentElement)return this.parentElement;if(!Polymer.dom(this).parentNode)return this.host;let node=this.parentNode;while(Polymer.dom(node).parentNode)node=Polymer.dom(node).parentNode;return node.host;},appendMatchingHotKeysTo_(matchedHotKeys,useCapture,e){const localKeyMap=this.getKeyMapForEventType_(e.type,useCapture);const localHotKey=localKeyMap[e.keyCode];if(localHotKey){matchedHotKeys.push(localHotKey);}
+for(let i=0;i<this.childControllers_.length;i++){const controller=this.childControllers_[i];controller.appendMatchingHotKeysTo_(matchedHotKeys,useCapture,e);}},onKey_(useCapture,e){if(!useCapture&&e.path[0].tagName==='INPUT')return;let sortedControllers;const matchedHotKeys=[];this.appendMatchingHotKeysTo_(matchedHotKeys,useCapture,e);if(matchedHotKeys.length===0)return false;if(matchedHotKeys.length>1){throw new Error('More than one hotKey is currently unsupported');}
+const hotKey=matchedHotKeys[0];let prevented=0;prevented|=hotKey.call(e);return!prevented&&e.defaultPrevented;}});'use strict';tr.exportTo('tr.b',function(){function getHotkeyControllerForElement(refElement){let curElement=refElement;while(curElement){if(curElement.tagName==='tv-ui-b-hotkey-controller'){return curElement;}
+if(curElement.__hotkeyController){return curElement.__hotkeyController;}
+if(curElement.parentElement){curElement=curElement.parentElement;continue;}
+curElement=findHost(curElement);}
+return undefined;}
+function findHost(initialNode){let node=initialNode;while(Polymer.dom(node).parentNode){node=Polymer.dom(node).parentNode;}
+return node.host;}
+return{getHotkeyControllerForElement,};});'use strict';Polymer({is:'tr-ui-b-info-bar',ready(){this.messageEl_=this.$.message;this.buttonsEl_=this.$.buttons;this.message='';},get message(){return Polymer.dom(this.messageEl_).textContent;},set message(message){Polymer.dom(this.messageEl_).textContent=message;},get visible(){return!this.hidden;},set visible(visible){this.hidden=!visible;},removeAllButtons(){Polymer.dom(this.buttonsEl_).textContent='';},addButton(text,clickCallback){const button=document.createElement('button');Polymer.dom(button).textContent=text;button.addEventListener('click',event=>clickCallback(event,this));Polymer.dom(this.buttonsEl_).appendChild(button);return button;}});'use strict';tr.exportTo('tr.ui.b',function(){const ContainerThatDecoratesItsChildren=tr.ui.b.define('div');ContainerThatDecoratesItsChildren.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.observer_=new MutationObserver(this.didMutate_.bind(this));this.observer_.observe(this,{childList:true});Object.defineProperty(this,'textContent',{get:undefined,set:this.onSetTextContent_});},appendChild(x){HTMLDivElement.prototype.appendChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},insertBefore(x,y){HTMLDivElement.prototype.insertBefore.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},removeChild(x){HTMLDivElement.prototype.removeChild.call(this,x);this.didMutate_(this.observer_.takeRecords());},replaceChild(x,y){HTMLDivElement.prototype.replaceChild.call(this,x,y);this.didMutate_(this.observer_.takeRecords());},onSetTextContent_(textContent){if(textContent!==''){throw new Error('textContent can only be set to \'\'.');}
+this.clear();},clear(){while(Polymer.dom(this).lastChild){HTMLDivElement.prototype.removeChild.call(this,Polymer.dom(this).lastChild);}
+this.didMutate_(this.observer_.takeRecords());},didMutate_(records){this.beginDecorating_();for(let i=0;i<records.length;i++){const addedNodes=records[i].addedNodes;if(addedNodes){for(let j=0;j<addedNodes.length;j++){this.decorateChild_(addedNodes[j]);}}
+const removedNodes=records[i].removedNodes;if(removedNodes){for(let j=0;j<removedNodes.length;j++){this.undecorateChild_(removedNodes[j]);}}}
+this.doneDecoratingForNow_();},decorateChild_(child){throw new Error('Not implemented');},undecorateChild_(child){throw new Error('Not implemented');},beginDecorating_(){},doneDecoratingForNow_(){}};return{ContainerThatDecoratesItsChildren,};});'use strict';tr.exportTo('tr.ui.b',function(){const ListView=tr.ui.b.define('x-list-view',tr.ui.b.ContainerThatDecoratesItsChildren);ListView.prototype={__proto__:tr.ui.b.ContainerThatDecoratesItsChildren.prototype,decorate(){tr.ui.b.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);Polymer.dom(this).classList.add('x-list-view');this.style.display='block';this.style.userSelect='none';this.style.outline='none';this.onItemClicked_=this.onItemClicked_.bind(this);this.onKeyDown_=this.onKeyDown_.bind(this);this.tabIndex=0;this.addEventListener('keydown',this.onKeyDown_);this.selectionChanged_=false;},decorateChild_(item){Polymer.dom(item).classList.add('list-item');item.style.paddingTop='2px';item.style.paddingRight='4px';item.style.paddingBottom='2px';item.style.paddingLeft='4px';item.addEventListener('click',this.onItemClicked_,true);Object.defineProperty(item,'selected',{configurable:true,get:()=>item.hasAttribute('selected'),set:value=>{const oldSelection=this.selectedElement;if(oldSelection&&oldSelection!==item&&value){Polymer.dom(this.selectedElement).removeAttribute('selected');}
+if(value){Polymer.dom(item).setAttribute('selected','selected');item.style.backgroundColor='rgb(171, 217, 202)';item.style.outline='1px dotted rgba(0,0,0,0.1)';item.style.outlineOffset=0;}else{Polymer.dom(item).removeAttribute('selected');item.style.backgroundColor='';}
+const newSelection=this.selectedElement;if(newSelection!==oldSelection){tr.b.dispatchSimpleEvent(this,'selection-changed',false);}},});},undecorateChild_(item){this.selectionChanged_|=item.selected;Polymer.dom(item).classList.remove('list-item');item.removeEventListener('click',this.onItemClicked_);delete item.selected;},beginDecorating_(){this.selectionChanged_=false;},doneDecoratingForNow_(){if(this.selectionChanged_){tr.b.dispatchSimpleEvent(this,'selection-changed',false);}},get selectedElement(){const el=Polymer.dom(this).querySelector('.list-item[selected]');if(!el)return undefined;return el;},set selectedElement(el){if(!el){if(this.selectedElement){this.selectedElement.selected=false;}
+return;}
+if(el.parentElement!==this){throw new Error('Can only select elements that are children of this list view');}
+el.selected=true;},getElementByIndex(index){return Polymer.dom(this).querySelector('.list-item:nth-child('+index+')');},clear(){const changed=this.selectedElement!==undefined;tr.ui.b.ContainerThatDecoratesItsChildren.prototype.clear.call(this);if(changed){tr.b.dispatchSimpleEvent(this,'selection-changed',false);}},onItemClicked_(e){const currentSelectedElement=this.selectedElement;if(currentSelectedElement){Polymer.dom(currentSelectedElement).removeAttribute('selected');}
+let element=e.target;while(element.parentElement!==this){element=element.parentElement;}
+if(element!==currentSelectedElement){Polymer.dom(element).setAttribute('selected','selected');}
+tr.b.dispatchSimpleEvent(this,'selection-changed',false);},onKeyDown_(e){if(this.selectedElement===undefined)return;if(e.keyCode===38){const prev=Polymer.dom(this.selectedElement).previousSibling;if(prev){prev.selected=true;tr.ui.b.scrollIntoViewIfNeeded(prev);e.preventDefault();return true;}}else if(e.keyCode===40){const next=Polymer.dom(this.selectedElement).nextSibling;if(next){next.selected=true;tr.ui.b.scrollIntoViewIfNeeded(next);e.preventDefault();return true;}}},addItem(textContent){const item=document.createElement('div');Polymer.dom(item).textContent=textContent;Polymer.dom(this).appendChild(item);item.style.userSelect='none';return item;}};return{ListView,};});'use strict';tr.exportTo('tr.ui.b',function(){const MOUSE_SELECTOR_MODE={};MOUSE_SELECTOR_MODE.SELECTION=0x1;MOUSE_SELECTOR_MODE.PANSCAN=0x2;MOUSE_SELECTOR_MODE.ZOOM=0x4;MOUSE_SELECTOR_MODE.TIMING=0x8;MOUSE_SELECTOR_MODE.ROTATE=0x10;MOUSE_SELECTOR_MODE.ALL_MODES=0x1F;const MOUSE_SELECTOR_MODE_INFOS={};MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.PANSCAN]={name:'PANSCAN',mode:MOUSE_SELECTOR_MODE.PANSCAN,title:'pan',eventNames:{enter:'enterpan',begin:'beginpan',update:'updatepan',end:'endpan',exit:'exitpan'},activeBackgroundPosition:'-30px -10px',defaultBackgroundPosition:'0 -10px'};MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.SELECTION]={name:'SELECTION',mode:MOUSE_SELECTOR_MODE.SELECTION,title:'selection',eventNames:{enter:'enterselection',begin:'beginselection',update:'updateselection',end:'endselection',exit:'exitselection'},activeBackgroundPosition:'-30px -40px',defaultBackgroundPosition:'0 -40px'};MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.ZOOM]={name:'ZOOM',mode:MOUSE_SELECTOR_MODE.ZOOM,title:'zoom',eventNames:{enter:'enterzoom',begin:'beginzoom',update:'updatezoom',end:'endzoom',exit:'exitzoom'},activeBackgroundPosition:'-30px -70px',defaultBackgroundPosition:'0 -70px'};MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.TIMING]={name:'TIMING',mode:MOUSE_SELECTOR_MODE.TIMING,title:'timing',eventNames:{enter:'entertiming',begin:'begintiming',update:'updatetiming',end:'endtiming',exit:'exittiming'},activeBackgroundPosition:'-30px -100px',defaultBackgroundPosition:'0 -100px'};MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.ROTATE]={name:'ROTATE',mode:MOUSE_SELECTOR_MODE.ROTATE,title:'rotate',eventNames:{enter:'enterrotate',begin:'beginrotate',update:'updaterotate',end:'endrotate',exit:'exitrotate'},activeBackgroundPosition:'-30px -130px',defaultBackgroundPosition:'0 -130px'};return{MOUSE_SELECTOR_MODE_INFOS,MOUSE_SELECTOR_MODE,};});'use strict';Polymer({is:'tr-ui-b-mouse-mode-icon',properties:{modeName:{type:String,reflectToAttribute:true,observer:'modeNameChanged'},},created(){this.active_=false;this.acceleratorKey_=undefined;},ready(){this.updateContents_();},get mode(){return tr.ui.b.MOUSE_SELECTOR_MODE[this.modeName];},set mode(mode){const modeInfo=tr.ui.b.MOUSE_SELECTOR_MODE_INFOS[mode];if(modeInfo===undefined){throw new Error('Unknown mode');}
+this.modeName=modeInfo.name;},modeNameChanged(){this.updateContents_();},get active(){return this.active_;},set active(active){this.active_=!!active;if(this.active_){Polymer.dom(this).classList.add('active');}else{Polymer.dom(this).classList.remove('active');}
+this.updateContents_();},get acceleratorKey(){return this.acceleratorKey_;},set acceleratorKey(acceleratorKey){this.acceleratorKey_=acceleratorKey;this.updateContents_();},updateContents_(){if(this.modeName===undefined)return;const mode=this.mode;if(mode===undefined){throw new Error('Invalid mode');}
+const modeInfo=tr.ui.b.MOUSE_SELECTOR_MODE_INFOS[mode];if(!modeInfo){throw new Error('Invalid mode');}
+let title=modeInfo.title;if(this.acceleratorKey_){title=title+' ('+this.acceleratorKey_+')';}
+this.title=title;let bp;if(this.active_){bp=modeInfo.activeBackgroundPosition;}else{bp=modeInfo.defaultBackgroundPosition;}
+this.style.backgroundPosition=bp;}});'use strict';tr.exportTo('tr.ui.b',function(){function MouseTracker(opt_targetElement){this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.targetElement=opt_targetElement;}
+MouseTracker.prototype={get targetElement(){return this.targetElement_;},set targetElement(targetElement){if(this.targetElement_){this.targetElement_.removeEventListener('mousedown',this.onMouseDown_);}
+this.targetElement_=targetElement;if(this.targetElement_){this.targetElement_.addEventListener('mousedown',this.onMouseDown_);}},onMouseDown_(e){if(e.button!==0)return true;e=this.remakeEvent_(e,'mouse-tracker-start');this.targetElement_.dispatchEvent(e);document.addEventListener('mousemove',this.onMouseMove_);document.addEventListener('mouseup',this.onMouseUp_);this.targetElement_.addEventListener('blur',this.onMouseUp_);this.savePreviousUserSelect_=document.body.style['-webkit-user-select'];document.body.style['-webkit-user-select']='none';e.preventDefault();return true;},onMouseMove_(e){e=this.remakeEvent_(e,'mouse-tracker-move');this.targetElement_.dispatchEvent(e);},onMouseUp_(e){document.removeEventListener('mousemove',this.onMouseMove_);document.removeEventListener('mouseup',this.onMouseUp_);this.targetElement_.removeEventListener('blur',this.onMouseUp_);document.body.style['-webkit-user-select']=this.savePreviousUserSelect_;e=this.remakeEvent_(e,'mouse-tracker-end');this.targetElement_.dispatchEvent(e);},remakeEvent_(e,newType){const remade=new tr.b.Event(newType,true,true);remade.x=e.x;remade.y=e.y;remade.offsetX=e.offsetX;remade.offsetY=e.offsetY;remade.clientX=e.clientX;remade.clientY=e.clientY;return remade;}};function trackMouseMovesUntilMouseUp(mouseMoveHandler,opt_mouseUpHandler,opt_keyUpHandler){function cleanupAndDispatchToMouseUp(e){document.removeEventListener('mousemove',mouseMoveHandler);if(opt_keyUpHandler){document.removeEventListener('keyup',opt_keyUpHandler);}
+document.removeEventListener('mouseup',cleanupAndDispatchToMouseUp);if(opt_mouseUpHandler){opt_mouseUpHandler(e);}}
+document.addEventListener('mousemove',mouseMoveHandler);if(opt_keyUpHandler){document.addEventListener('keyup',opt_keyUpHandler);}
+document.addEventListener('mouseup',cleanupAndDispatchToMouseUp);}
+return{MouseTracker,trackMouseMovesUntilMouseUp,};});'use strict';tr.exportTo('tr.ui.b',function(){const MOUSE_SELECTOR_MODE=tr.ui.b.MOUSE_SELECTOR_MODE;const MOUSE_SELECTOR_MODE_INFOS=tr.ui.b.MOUSE_SELECTOR_MODE_INFOS;const MIN_MOUSE_SELECTION_DISTANCE=4;const MODIFIER={SHIFT:0x1,SPACE:0x2,CMD_OR_CTRL:0x4};function isCmdOrCtrlPressed(event){if(tr.isMac)return event.metaKey;return event.ctrlKey;}
+Polymer({is:'tr-ui-b-mouse-mode-selector',created(){this.supportedModeMask_=MOUSE_SELECTOR_MODE.ALL_MODES;this.initialRelativeMouseDownPos_={x:0,y:0};this.defaultMode_=MOUSE_SELECTOR_MODE.PANSCAN;this.settingsKey_=undefined;this.mousePos_={x:0,y:0};this.mouseDownPos_={x:0,y:0};this.onMouseDown_=this.onMouseDown_.bind(this);this.onMouseMove_=this.onMouseMove_.bind(this);this.onMouseUp_=this.onMouseUp_.bind(this);this.onKeyDown_=this.onKeyDown_.bind(this);this.onKeyUp_=this.onKeyUp_.bind(this);this.mode_=undefined;this.modeToKeyCodeMap_={};this.modifierToModeMap_={};this.targetElement_=undefined;this.modeBeforeAlternativeModeActivated_=null;this.isInteracting_=false;this.isClick_=false;},ready(){this.buttonsEl_=Polymer.dom(this.root).querySelector('.buttons');this.dragHandleEl_=Polymer.dom(this.root).querySelector('.drag-handle');this.supportedModeMask=MOUSE_SELECTOR_MODE.ALL_MODES;this.dragHandleEl_.addEventListener('mousedown',this.onDragHandleMouseDown_.bind(this));this.buttonsEl_.addEventListener('mouseup',this.onButtonMouseUp_);this.buttonsEl_.addEventListener('mousedown',this.onButtonMouseDown_);this.buttonsEl_.addEventListener('click',this.onButtonPress_.bind(this));},attached(){document.addEventListener('keydown',this.onKeyDown_);document.addEventListener('keyup',this.onKeyUp_);},detached(){document.removeEventListener('keydown',this.onKeyDown_);document.removeEventListener('keyup',this.onKeyUp_);},get targetElement(){return this.targetElement_;},set targetElement(target){if(this.targetElement_){this.targetElement_.removeEventListener('mousedown',this.onMouseDown_);}
+this.targetElement_=target;if(this.targetElement_){this.targetElement_.addEventListener('mousedown',this.onMouseDown_);}},get defaultMode(){return this.defaultMode_;},set defaultMode(defaultMode){this.defaultMode_=defaultMode;},get settingsKey(){return this.settingsKey_;},set settingsKey(settingsKey){this.settingsKey_=settingsKey;if(!this.settingsKey_)return;let mode=tr.b.Settings.get(this.settingsKey_+'.mode',undefined);if(MOUSE_SELECTOR_MODE_INFOS[mode]===undefined){mode=undefined;}
+if((mode&this.supportedModeMask_)===0){mode=undefined;}
+if(!mode)mode=this.defaultMode_;this.mode=mode;const pos=tr.b.Settings.get(this.settingsKey_+'.pos',undefined);if(pos)this.pos=pos;},get supportedModeMask(){return this.supportedModeMask_;},set supportedModeMask(supportedModeMask){if(this.mode&&(supportedModeMask&this.mode)===0){throw new Error('supportedModeMask must include current mode.');}
+function createButtonForMode(mode){return button;}
+this.supportedModeMask_=supportedModeMask;Polymer.dom(this.buttonsEl_).textContent='';for(const modeName in MOUSE_SELECTOR_MODE){if(modeName==='ALL_MODES')continue;const mode=MOUSE_SELECTOR_MODE[modeName];if((this.supportedModeMask_&mode)===0)continue;const button=document.createElement('tr-ui-b-mouse-mode-icon');button.mode=mode;Polymer.dom(button).classList.add('tool-button');Polymer.dom(this.buttonsEl_).appendChild(button);}},getButtonForMode_(mode){for(let i=0;i<this.buttonsEl_.children.length;i++){const buttonEl=this.buttonsEl_.children[i];if(buttonEl.mode===mode){return buttonEl;}}
+return undefined;},get mode(){return this.currentMode_;},set mode(newMode){if(newMode!==undefined){if(typeof newMode!=='number'){throw new Error('Mode must be a number');}
+if((newMode&this.supportedModeMask_)===0){throw new Error('Cannot switch to this mode, it is not supported');}
+if(MOUSE_SELECTOR_MODE_INFOS[newMode]===undefined){throw new Error('Unrecognized mode');}}
+let modeInfo;if(this.currentMode_===newMode)return;if(this.currentMode_){const buttonEl=this.getButtonForMode_(this.currentMode_);if(buttonEl)buttonEl.active=false;if(this.isInteracting_){const mouseEvent=this.createEvent_(MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.end);this.dispatchEvent(mouseEvent);}
+modeInfo=MOUSE_SELECTOR_MODE_INFOS[this.currentMode_];tr.b.dispatchSimpleEvent(this,modeInfo.eventNames.exit,true);}
+this.currentMode_=newMode;if(this.currentMode_){const buttonEl=this.getButtonForMode_(this.currentMode_);if(buttonEl)buttonEl.active=true;this.mouseDownPos_.x=this.mousePos_.x;this.mouseDownPos_.y=this.mousePos_.y;modeInfo=MOUSE_SELECTOR_MODE_INFOS[this.currentMode_];if(!this.isInAlternativeMode_){tr.b.dispatchSimpleEvent(this,modeInfo.eventNames.enter,true);}
+if(this.isInteracting_){const mouseEvent=this.createEvent_(MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.begin);this.dispatchEvent(mouseEvent);}}
+if(this.settingsKey_&&!this.isInAlternativeMode_){tr.b.Settings.set(this.settingsKey_+'.mode',this.mode);}},setKeyCodeForMode(mode,keyCode){if((mode&this.supportedModeMask_)===0){throw new Error('Mode not supported');}
+this.modeToKeyCodeMap_[mode]=keyCode;if(!this.buttonsEl_)return;const buttonEl=this.getButtonForMode_(mode);if(buttonEl){buttonEl.acceleratorKey=String.fromCharCode(keyCode);}},setCurrentMousePosFromEvent_(e){this.mousePos_.x=e.clientX;this.mousePos_.y=e.clientY;},createEvent_(eventName,sourceEvent){const event=new tr.b.Event(eventName,true);event.clientX=this.mousePos_.x;event.clientY=this.mousePos_.y;event.deltaX=this.mousePos_.x-this.mouseDownPos_.x;event.deltaY=this.mousePos_.y-this.mouseDownPos_.y;event.mouseDownX=this.mouseDownPos_.x;event.mouseDownY=this.mouseDownPos_.y;event.didPreventDefault=false;event.preventDefault=function(){event.didPreventDefault=true;if(sourceEvent){sourceEvent.preventDefault();}};event.stopPropagation=function(){sourceEvent.stopPropagation();};event.stopImmediatePropagation=function(){throw new Error('Not implemented');};return event;},onMouseDown_(e){if(e.button!==0)return;this.setCurrentMousePosFromEvent_(e);const mouseEvent=this.createEvent_(MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.begin,e);if(this.mode===MOUSE_SELECTOR_MODE.SELECTION){mouseEvent.appendSelection=isCmdOrCtrlPressed(e);}
+this.dispatchEvent(mouseEvent);this.isInteracting_=true;this.isClick_=true;tr.ui.b.trackMouseMovesUntilMouseUp(this.onMouseMove_,this.onMouseUp_);},onMouseMove_(e){this.setCurrentMousePosFromEvent_(e);const mouseEvent=this.createEvent_(MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.update,e);this.dispatchEvent(mouseEvent);if(this.isInteracting_){this.checkIsClick_(e);}},onMouseUp_(e){if(e.button!==0)return;const mouseEvent=this.createEvent_(MOUSE_SELECTOR_MODE_INFOS[this.mode].eventNames.end,e);mouseEvent.isClick=this.isClick_;this.dispatchEvent(mouseEvent);if(this.isClick_&&!mouseEvent.didPreventDefault){this.dispatchClickEvents_(e);}
+this.isInteracting_=false;this.updateAlternativeModeState_(e);},onButtonMouseDown_(e){e.preventDefault();e.stopImmediatePropagation();},onButtonMouseUp_(e){e.preventDefault();e.stopImmediatePropagation();},onButtonPress_(e){this.modeBeforeAlternativeModeActivated_=undefined;this.mode=e.target.mode;e.preventDefault();},onKeyDown_(e){if(e.path[0].tagName==='INPUT')return;if(e.keyCode===' '.charCodeAt(0)){this.spacePressed_=true;}
+this.updateAlternativeModeState_(e);},onKeyUp_(e){if(e.path[0].tagName==='INPUT')return;if(e.keyCode===' '.charCodeAt(0)){this.spacePressed_=false;}
+let didHandleKey=false;for(const[modeStr,keyCode]of Object.entries(this.modeToKeyCodeMap_)){if(e.keyCode===keyCode){this.modeBeforeAlternativeModeActivated_=undefined;const mode=parseInt(modeStr);this.mode=mode;didHandleKey=true;}}
+if(didHandleKey){e.preventDefault();e.stopPropagation();return;}
+this.updateAlternativeModeState_(e);},updateAlternativeModeState_(e){const shiftPressed=e.shiftKey;const spacePressed=this.spacePressed_;const cmdOrCtrlPressed=isCmdOrCtrlPressed(e);const smm=this.supportedModeMask_;let newMode;let isNewModeAnAlternativeMode=false;if(shiftPressed&&(this.modifierToModeMap_[MODIFIER.SHIFT]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SHIFT];isNewModeAnAlternativeMode=true;}else if(spacePressed&&(this.modifierToModeMap_[MODIFIER.SPACE]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.SPACE];isNewModeAnAlternativeMode=true;}else if(cmdOrCtrlPressed&&(this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL]&smm)!==0){newMode=this.modifierToModeMap_[MODIFIER.CMD_OR_CTRL];isNewModeAnAlternativeMode=true;}else{if(this.isInAlternativeMode_){newMode=this.modeBeforeAlternativeModeActivated_;isNewModeAnAlternativeMode=false;}else{newMode=undefined;}}
+if(this.mode===newMode||newMode===undefined)return;if(isNewModeAnAlternativeMode){this.modeBeforeAlternativeModeActivated_=this.mode;}
+this.mode=newMode;},get isInAlternativeMode_(){return!!this.modeBeforeAlternativeModeActivated_;},setModifierForAlternateMode(mode,modifier){this.modifierToModeMap_[modifier]=mode;},get pos(){return{x:parseInt(this.style.left),y:parseInt(this.style.top)};},set pos(pos){pos=this.constrainPositionToBounds_(pos);this.style.left=pos.x+'px';this.style.top=pos.y+'px';if(this.settingsKey_){tr.b.Settings.set(this.settingsKey_+'.pos',this.pos);}},constrainPositionToBounds_(pos){const parent=this.offsetParent||document.body;const parentRect=tr.ui.b.windowRectForElement(parent);const top=0;const bottom=parentRect.height-this.offsetHeight;const left=0;const right=parentRect.width-this.offsetWidth;const res={};res.x=Math.max(pos.x,left);res.x=Math.min(res.x,right);res.y=Math.max(pos.y,top);res.y=Math.min(res.y,bottom);return res;},onDragHandleMouseDown_(e){e.preventDefault();e.stopImmediatePropagation();const mouseDownPos={x:e.clientX-this.offsetLeft,y:e.clientY-this.offsetTop};tr.ui.b.trackMouseMovesUntilMouseUp(function(e){const pos={};pos.x=e.clientX-mouseDownPos.x;pos.y=e.clientY-mouseDownPos.y;this.pos=pos;}.bind(this));},checkIsClick_(e){if(!this.isInteracting_||!this.isClick_)return;const deltaX=this.mousePos_.x-this.mouseDownPos_.x;const deltaY=this.mousePos_.y-this.mouseDownPos_.y;const minDist=MIN_MOUSE_SELECTION_DISTANCE;if(deltaX*deltaX+deltaY*deltaY>minDist*minDist){this.isClick_=false;}},dispatchClickEvents_(e){if(!this.isClick_)return;const modeInfo=MOUSE_SELECTOR_MODE_INFOS[MOUSE_SELECTOR_MODE.SELECTION];const eventNames=modeInfo.eventNames;let mouseEvent=this.createEvent_(eventNames.begin);mouseEvent.appendSelection=isCmdOrCtrlPressed(e);this.dispatchEvent(mouseEvent);mouseEvent=this.createEvent_(eventNames.end);this.dispatchEvent(mouseEvent);}});return{MIN_MOUSE_SELECTION_DISTANCE,MODIFIER,};});'use strict';(function(){const DETAILS_SPLIT_REGEX=/^(\S*)\s*([\S\s]*)$/;Polymer({is:'tr-ui-e-chrome-cc-display-item-list-item',created(){Polymer.dom(this).setAttribute('name','');Polymer.dom(this).setAttribute('rawDetails','');Polymer.dom(this).setAttribute('richDetails',undefined);Polymer.dom(this).setAttribute('data_',undefined);},get data(){return this.data_;},set data(data){this.data_=data;if(!data){this.name='DATA MISSING';this.rawDetails='';this.richDetails=undefined;}else if(typeof data==='string'){const match=data.match(DETAILS_SPLIT_REGEX);this.name=match[1];this.rawDetails=match[2];this.richDetails=undefined;}else{this.name=data.name;this.rawDetails='';this.richDetails=data;}},stopPropagation(e){e.stopPropagation();},_computeIfSKP(richDetails){return richDetails&&richDetails.skp64;},_computeHref(richDetails){return'data:application/octet-stream;base64,'+richDetails.skp64;}});})();'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){function Selection(){this.selectionToSetIfClicked=undefined;}
+Selection.prototype={get specicifity(){throw new Error('Not implemented');},get associatedLayerId(){throw new Error('Not implemented');},get associatedRenderPassId(){throw new Error('Not implemented');},get highlightsByLayerId(){return{};},createAnalysis(){throw new Error('Not implemented');},findEquivalent(lthi){throw new Error('Not implemented');}};function RenderPassSelection(renderPass,renderPassId){if(!renderPass||(renderPassId===undefined)){throw new Error('Render pass (with id) is required');}
+this.renderPass_=renderPass;this.renderPassId_=renderPassId;}
+RenderPassSelection.prototype={__proto__:Selection.prototype,get specicifity(){return 1;},get associatedLayerId(){return undefined;},get associatedRenderPassId(){return this.renderPassId_;},get renderPass(){return this.renderPass_;},createAnalysis(){const dataView=document.createElement('tr-ui-a-generic-object-view-with-label');dataView.label='RenderPass '+this.renderPassId_;dataView.object=this.renderPass_.args;return dataView;},get title(){return this.renderPass_.objectInstance.typeName;}};function LayerSelection(layer){if(!layer){throw new Error('Layer is required');}
+this.layer_=layer;}
+LayerSelection.prototype={__proto__:Selection.prototype,get specicifity(){return 1;},get associatedLayerId(){return this.layer_.layerId;},get associatedRenderPassId(){return undefined;},get layer(){return this.layer_;},createAnalysis(){const dataView=document.createElement('tr-ui-a-generic-object-view-with-label');dataView.label='Layer '+this.layer_.layerId;if(this.layer_.usingGpuRasterization){dataView.label+=' (GPU-rasterized)';}
+dataView.object=this.layer_.args;return dataView;},get title(){return this.layer_.objectInstance.typeName;},findEquivalent(lthi){const layer=lthi.activeTree.findLayerWithId(this.layer_.layerId)||lthi.pendingTree.findLayerWithId(this.layer_.layerId);if(!layer)return undefined;return new LayerSelection(layer);}};function TileSelection(tile,opt_data){this.tile_=tile;this.data_=opt_data||{};}
+TileSelection.prototype={__proto__:Selection.prototype,get specicifity(){return 2;},get associatedLayerId(){return this.tile_.layerId;},get highlightsByLayerId(){const highlights={};highlights[this.tile_.layerId]=[{colorKey:this.tile_.objectInstance.typeName,rect:this.tile_.layerRect}];return highlights;},createAnalysis(){const analysis=document.createElement('tr-ui-a-generic-object-view-with-label');analysis.label='Tile '+this.tile_.objectInstance.id+' on layer '+
+this.tile_.layerId;if(this.data_){analysis.object={moreInfo:this.data_,tileArgs:this.tile_.args};}else{analysis.object=this.tile_.args;}
+return analysis;},findEquivalent(lthi){const tileInstance=this.tile_.tileInstance;if(lthi.ts<tileInstance.creationTs||lthi.ts>=tileInstance.deletionTs){return undefined;}
+const tileSnapshot=tileInstance.getSnapshotAt(lthi.ts);if(!tileSnapshot)return undefined;return new TileSelection(tileSnapshot);}};function LayerRectSelection(layer,rectType,rect,opt_data){this.layer_=layer;this.rectType_=rectType;this.rect_=rect;this.data_=opt_data!==undefined?opt_data:rect;}
+LayerRectSelection.prototype={__proto__:Selection.prototype,get specicifity(){return 2;},get associatedLayerId(){return this.layer_.layerId;},get highlightsByLayerId(){const highlights={};highlights[this.layer_.layerId]=[{colorKey:this.rectType_,rect:this.rect_}];return highlights;},createAnalysis(){const analysis=document.createElement('tr-ui-a-generic-object-view-with-label');analysis.label=this.rectType_+' on layer '+this.layer_.layerId;analysis.object=this.data_;return analysis;},findEquivalent(lthi){return undefined;}};function AnimationRectSelection(layer,rect){this.layer_=layer;this.rect_=rect;}
+AnimationRectSelection.prototype={__proto__:Selection.prototype,get specicifity(){return 0;},get associatedLayerId(){return this.layer_.layerId;},createAnalysis(){const analysis=document.createElement('tr-ui-a-generic-object-view-with-label');analysis.label='Animation Bounds of layer '+this.layer_.layerId;analysis.object=this.rect_;return analysis;}};return{Selection,RenderPassSelection,LayerSelection,TileSelection,LayerRectSelection,AnimationRectSelection,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const ANNOTATION='Comment';const BEGIN_ANNOTATION='BeginCommentGroup';const END_ANNOTATION='EndCommentGroup';const ANNOTATION_ID='ID: ';const ANNOTATION_CLASS='CLASS: ';const ANNOTATION_TAG='TAG: ';const constants=tr.e.cc.constants;const PictureOpsListView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-list-view');PictureOpsListView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.borderTop='1px solid grey';this.style.overflow='auto';this.opsList_=new tr.ui.b.ListView();Polymer.dom(this).appendChild(this.opsList_);this.selectedOp_=undefined;this.selectedOpIndex_=undefined;this.opsList_.addEventListener('selection-changed',this.onSelectionChanged_.bind(this));this.picture_=undefined;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.updateContents_();},updateContents_(){this.opsList_.clear();if(!this.picture_)return;let ops=this.picture_.getOps();if(!ops)return;ops=this.picture_.tagOpsWithTimings(ops);ops=this.opsTaggedWithAnnotations_(ops);for(let i=0;i<ops.length;i++){const op=ops[i];const item=document.createElement('div');item.opIndex=op.opIndex;Polymer.dom(item).textContent=i+') '+op.cmd_string;if(op.elementInfo.tag||op.elementInfo.id||op.elementInfo.class){const elementInfo=document.createElement('span');Polymer.dom(elementInfo).classList.add('elementInfo');elementInfo.style.color='purple';elementInfo.style.fontSize='small';elementInfo.style.fontWeight='bold';elementInfo.style.color='#777';const tag=op.elementInfo.tag?op.elementInfo.tag:'unknown';const id=op.elementInfo.id?'id='+op.elementInfo.id:undefined;const className=op.elementInfo.class?'class='+
+op.elementInfo.class:undefined;Polymer.dom(elementInfo).textContent='<'+tag+(id?' ':'')+
+(id?id:'')+(className?' ':'')+
+(className?className:'')+'>';Polymer.dom(item).appendChild(elementInfo);}
+if(op.info.length>0){const infoItem=document.createElement('div');Polymer.dom(infoItem).textContent=JSON.stringify(op.info);infoItem.style.fontSize='x-small';infoItem.style.color='#777';Polymer.dom(item).appendChild(infoItem);}
+if(op.cmd_time&&op.cmd_time>=0.0001){const time=document.createElement('span');Polymer.dom(time).classList.add('time');const rounded=op.cmd_time.toFixed(4);Polymer.dom(time).textContent='('+rounded+'ms)';time.style.fontSize='x-small';time.style.color='rgb(136, 0, 0)';Polymer.dom(item).appendChild(time);}
+item.style.borderBottom='1px solid #555';item.style.fontSize='small';item.style.fontWeight='bold';item.style.paddingBottom='5px';item.style.paddingLeft='5px';item.style.cursor='pointer';for(const child of item.children){child.style.fontWeight='normal';child.style.marginLeft='1em';child.style.maxWidth='300px';}
+Polymer.dom(this.opsList_).appendChild(item);}},onSelectionChanged_(e){let beforeSelectedOp=true;if(this.opsList_.selectedElement===this.selectedOp_){this.opsList_.selectedElement=undefined;beforeSelectedOp=false;this.selectedOpIndex_=undefined;}
+this.selectedOp_=this.opsList_.selectedElement;const ops=this.opsList_.children;for(let i=0;i<ops.length;i++){const op=ops[i];if(op===this.selectedOp_){beforeSelectedOp=false;this.selectedOpIndex_=op.opIndex;}else if(beforeSelectedOp){Polymer.dom(op).setAttribute('beforeSelection','beforeSelection');op.style.backgroundColor='rgb(103, 199, 165)';}else{Polymer.dom(op).removeAttribute('beforeSelection');op.style.backgroundColor='';}}
+tr.b.dispatchSimpleEvent(this,'selection-changed',false);},get numOps(){return this.opsList_.children.length;},get selectedOpIndex(){return this.selectedOpIndex_;},set selectedOpIndex(s){this.selectedOpIndex_=s;if(s===undefined){this.opsList_.selectedElement=this.selectedOp_;this.onSelectionChanged_();}else{if(s<0)throw new Error('Invalid index');if(s>=this.numOps)throw new Error('Invalid index');this.opsList_.selectedElement=this.opsList_.getElementByIndex(s+1);tr.ui.b.scrollIntoViewIfNeeded(this.opsList_.selectedElement);}},opsTaggedWithAnnotations_(ops){const annotationGroups=[];const opsWithoutAnnotations=[];for(let opIndex=0;opIndex<ops.length;opIndex++){const op=ops[opIndex];op.opIndex=opIndex;switch(op.cmd_string){case BEGIN_ANNOTATION:annotationGroups.push([]);break;case END_ANNOTATION:annotationGroups.pop();break;case ANNOTATION:annotationGroups[annotationGroups.length-1].push(op);break;default:{const annotations=[];let elementInfo={};annotationGroups.forEach(function(annotationGroup){elementInfo={};annotationGroup.forEach(function(annotation){annotation.info.forEach(function(info){if(info.includes(ANNOTATION_TAG)){elementInfo.tag=info.substring(info.indexOf(ANNOTATION_TAG)+
+ANNOTATION_TAG.length).toLowerCase();}else if(info.includes(ANNOTATION_ID)){elementInfo.id=info.substring(info.indexOf(ANNOTATION_ID)+
+ANNOTATION_ID.length);}else if(info.includes(ANNOTATION_CLASS)){elementInfo.class=info.substring(info.indexOf(ANNOTATION_CLASS)+
+ANNOTATION_CLASS.length);}
+annotations.push(info);});});});op.annotations=annotations;op.elementInfo=elementInfo;opsWithoutAnnotations.push(op);}}}
+return opsWithoutAnnotations;}};return{PictureOpsListView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const THIS_DOC=document.currentScript.ownerDocument;const DisplayItemDebugger=tr.ui.b.define('tr-ui-e-chrome-cc-display-item-debugger');DisplayItemDebugger.prototype={__proto__:HTMLDivElement.prototype,decorate(){const node=tr.ui.b.instantiateTemplate('#tr-ui-e-chrome-cc-display-item-debugger-template',THIS_DOC);Polymer.dom(this).appendChild(node);this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.display='flex';this.style.minWidth=0;this.pictureAsImageData_=undefined;this.zoomScaleValue_=1;this.sizeInfo_=Polymer.dom(this).querySelector('.size');this.rasterArea_=Polymer.dom(this).querySelector('raster-area');this.rasterArea_.style.flexGrow=1;this.rasterArea_.style.flexShrink=1;this.rasterArea_.style.flexBasis='auto';this.rasterArea_.style.backgroundColor='#ddd';this.rasterArea_.style.minHeight='200px';this.rasterArea_.style.minWidth='200px';this.rasterArea_.style.paddingLeft='5px';this.rasterArea_.style.display='flex';this.rasterArea_.style.flexDirection='column';this.rasterCanvas_=Polymer.dom(this.rasterArea_).querySelector('canvas');this.rasterCtx_=this.rasterCanvas_.getContext('2d');const canvasScroller=Polymer.dom(this).querySelector('canvas-scroller');canvasScroller.style.flexGrow=1;canvasScroller.style.flexShrink=1;canvasScroller.style.flexBasis='auto';canvasScroller.style.minWidth=0;canvasScroller.style.minHeight=0;canvasScroller.style.overflow='auto';this.trackMouse_();this.displayItemInfo_=Polymer.dom(this).querySelector('display-item-info');this.displayItemInfo_.addEventListener('click',this.onDisplayItemInfoClick_.bind(this),false);this.displayItemListView_=new tr.ui.b.ListView();this.displayItemListView_.addEventListener('selection-changed',this.onDisplayItemListSelection_.bind(this));Polymer.dom(this.displayItemInfo_).appendChild(this.displayItemListView_);this.displayListFilename_=Polymer.dom(this).querySelector('.dlfilename');this.displayListExportButton_=Polymer.dom(this).querySelector('.dlexport');this.displayListExportButton_.addEventListener('click',this.onExportDisplayListClicked_.bind(this));this.skpFilename_=Polymer.dom(this).querySelector('.skpfilename');this.skpExportButton_=Polymer.dom(this).querySelector('.skpexport');this.skpExportButton_.addEventListener('click',this.onExportSkPictureClicked_.bind(this));const leftPanel=Polymer.dom(this).querySelector('left-panel');leftPanel.style.flexGrow=0;leftPanel.style.flexShrink=0;leftPanel.style.flexBasis='auto';leftPanel.style.minWidth='200px';leftPanel.style.overflow='auto';leftPanel.children[0].paddingTop='2px';leftPanel.children[0].children[0].style.borderBottom='1px solid #555';const leftPanelTitle=leftPanel.querySelector('.title');leftPanelTitle.style.fontWeight='bold';leftPanelTitle.style.marginLeft='5px';leftPanelTitle.style.marginright='5px';for(const div of leftPanel.querySelectorAll('.export')){div.style.margin='5px';}
+const middleDragHandle=document.createElement('tr-ui-b-drag-handle');middleDragHandle.style.flexGrow=0;middleDragHandle.style.flexShrink=0;middleDragHandle.style.flexBasis='auto';middleDragHandle.horizontal=false;middleDragHandle.target=leftPanel;const rightPanel=Polymer.dom(this).querySelector('right-panel');rightPanel.style.display='flex';rightPanel.style.flexGrow=1;rightPanel.style.flexShrink=1;rightPanel.style.flexBasis='auto';rightPanel.style.minWidth=0;this.infoBar_=document.createElement('tr-ui-b-info-bar');Polymer.dom(this.rasterArea_).insertBefore(this.infoBar_,canvasScroller);Polymer.dom(this).insertBefore(middleDragHandle,rightPanel);this.picture_=undefined;this.pictureOpsListView_=new tr.ui.e.chrome.cc.PictureOpsListView();this.pictureOpsListView_.style.flexGrow=0;this.pictureOpsListView_.style.flexShrink=0;this.pictureOpsListView_.style.flexBasis='auto';this.pictureOpsListView_.style.overflow='auto';this.pictureOpsListView_.style.minWidth='100px';Polymer.dom(rightPanel).insertBefore(this.pictureOpsListView_,this.rasterArea_);this.pictureOpsListDragHandle_=document.createElement('tr-ui-b-drag-handle');this.pictureOpsListDragHandle_.horizontal=false;this.pictureOpsListDragHandle_.target=this.pictureOpsListView_;Polymer.dom(rightPanel).insertBefore(this.pictureOpsListDragHandle_,this.rasterArea_);},get picture(){return this.picture_;},set displayItemList(displayItemList){this.displayItemList_=displayItemList;this.picture=this.displayItemList_;this.displayItemListView_.clear();this.displayItemList_.items.forEach(function(item){const listItem=document.createElement('tr-ui-e-chrome-cc-display-item-list-item');listItem.data=item;Polymer.dom(this.displayItemListView_).appendChild(listItem);}.bind(this));},set picture(picture){this.picture_=picture;const showOpsList=picture&&picture!==this.displayItemList_;this.updateDrawOpsList_(showOpsList);if(picture){const size=this.getRasterCanvasSize_();this.rasterCanvas_.width=size.width;this.rasterCanvas_.height=size.height;}
+const bounds=this.rasterArea_.getBoundingClientRect();const selectorBounds=this.mouseModeSelector_.getBoundingClientRect();this.mouseModeSelector_.pos={x:(bounds.right-selectorBounds.width-10),y:bounds.top};this.rasterize_();this.scheduleUpdateContents_();},getRasterCanvasSize_(){const style=window.getComputedStyle(this.rasterArea_);let width=parseInt(style.width);let height=parseInt(style.height);if(this.picture_){width=Math.max(width,this.picture_.layerRect.width);height=Math.max(height,this.picture_.layerRect.height);}
+return{width,height};},scheduleUpdateContents_(){if(this.updateContentsPending_)return;this.updateContentsPending_=true;tr.b.requestAnimationFrameInThisFrameIfPossible(this.updateContents_.bind(this));},updateContents_(){this.updateContentsPending_=false;if(this.picture_){Polymer.dom(this.sizeInfo_).textContent='('+
+this.picture_.layerRect.width+' x '+
+this.picture_.layerRect.height+')';}
+if(!this.pictureAsImageData_)return;this.infoBar_.visible=false;this.infoBar_.removeAllButtons();if(this.pictureAsImageData_.error){this.infoBar_.message='Cannot rasterize...';this.infoBar_.addButton('More info...',function(e){const overlay=new tr.ui.b.Overlay();Polymer.dom(overlay).textContent=this.pictureAsImageData_.error;overlay.visible=true;e.stopPropagation();return false;}.bind(this));this.infoBar_.visible=true;}
+this.drawPicture_();},drawPicture_(){const size=this.getRasterCanvasSize_();if(size.width!==this.rasterCanvas_.width){this.rasterCanvas_.width=size.width;}
+if(size.height!==this.rasterCanvas_.height){this.rasterCanvas_.height=size.height;}
+this.rasterCtx_.clearRect(0,0,size.width,size.height);if(!this.picture_||!this.pictureAsImageData_.imageData)return;const imgCanvas=this.pictureAsImageData_.asCanvas();const w=imgCanvas.width;const h=imgCanvas.height;this.rasterCtx_.drawImage(imgCanvas,0,0,w,h,0,0,w*this.zoomScaleValue_,h*this.zoomScaleValue_);},rasterize_(){if(this.picture_){this.picture_.rasterize({showOverdraw:false},this.onRasterComplete_.bind(this));}},onRasterComplete_(pictureAsImageData){this.pictureAsImageData_=pictureAsImageData;this.scheduleUpdateContents_();},onDisplayItemListSelection_(e){const selected=this.displayItemListView_.selectedElement;if(!selected){this.picture=this.displayItemList_;return;}
+const index=Array.prototype.indexOf.call(this.displayItemListView_.children,selected);const displayItem=this.displayItemList_.items[index];if(displayItem&&displayItem.skp64){this.picture=new tr.e.cc.Picture(displayItem.skp64,this.displayItemList_.layerRect);}else{this.picture=undefined;}},onDisplayItemInfoClick_(e){if(e&&e.target===this.displayItemInfo_){this.displayItemListView_.selectedElement=undefined;}},updateDrawOpsList_(showOpsList){if(showOpsList){this.pictureOpsListView_.picture=this.picture_;if(this.pictureOpsListView_.numOps>0){this.pictureOpsListView_.style.display='block';this.pictureOpsListDragHandle_.style.display='block';}}else{this.pictureOpsListView_.style.display='none';this.pictureOpsListDragHandle_.style.display='none';}},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.rasterArea_;Polymer.dom(this.rasterArea_).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.defaultMode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.settingsKey='pictureDebugger.mouseModeSelector';this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));},onBeginZoom_(e){this.isZooming_=true;this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);e.preventDefault();},onUpdateZoom_(e){if(!this.isZooming_)return;const currentMouseViewPos=this.extractRelativeMousePosition_(e);this.zoomScaleValue_+=((this.lastMouseViewPos_.y-currentMouseViewPos.y)*0.001);this.zoomScaleValue_=Math.max(this.zoomScaleValue_,0.1);this.drawPicture_();this.lastMouseViewPos_=currentMouseViewPos;},onEndZoom_(e){this.lastMouseViewPos_=undefined;this.isZooming_=false;e.preventDefault();},extractRelativeMousePosition_(e){return{x:e.clientX-this.rasterArea_.offsetLeft,y:e.clientY-this.rasterArea_.offsetTop};},saveFile_(filename,rawData){if(!rawData)return;const length=rawData.length;const arrayBuffer=new ArrayBuffer(length);const uint8Array=new Uint8Array(arrayBuffer);for(let c=0;c<length;c++){uint8Array[c]=rawData.charCodeAt(c);}
+const blob=new Blob([uint8Array],{type:'application/octet-binary'});const blobUrl=window.URL.createObjectURL(blob);const link=document.createElementNS('http://www.w3.org/1999/xhtml','a');link.href=blobUrl;link.download=filename;const event=document.createEvent('MouseEvents');event.initMouseEvent('click',true,false,window,0,0,0,0,0,false,false,false,false,0,null);link.dispatchEvent(event);},onExportDisplayListClicked_(){const rawData=JSON.stringify(this.displayItemList_.items);this.saveFile_(this.displayListFilename_.value,rawData);},onExportSkPictureClicked_(){const rawData=tr.b.Base64.atob(this.picture_.getBase64SkpData());this.saveFile_(this.skpFilename_.value,rawData);}};return{DisplayItemDebugger,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const DisplayItemSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-display-item-list-view',tr.ui.analysis.ObjectSnapshotView);DisplayItemSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){this.style.display='flex';this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.minWidth=0;this.displayItemDebugger_=new tr.ui.e.chrome.cc.DisplayItemDebugger();this.displayItemDebugger_.style.flexGrow=1;this.displayItemDebugger_.style.flexShrink=1;this.displayItemDebugger_.style.flexBasis='auto';this.displayItemDebugger_.style.minWidth=0;Polymer.dom(this).appendChild(this.displayItemDebugger_);},updateContents(){if(this.objectSnapshot_&&this.displayItemDebugger_){this.displayItemDebugger_.displayItemList=this.objectSnapshot_;}}};tr.ui.analysis.ObjectSnapshotView.register(DisplayItemSnapshotView,{typeNames:['cc::DisplayItemList'],showInstances:false});return{DisplayItemSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const constants=tr.e.cc.constants;const RENDER_PASS_QUADS=Math.max(constants.ACTIVE_TREE,constants.PENDING_TREE)+1;const LayerPicker=tr.ui.b.define('tr-ui-e-chrome-cc-layer-picker');LayerPicker.prototype={__proto__:HTMLUnknownElement.prototype,decorate(){this.lthi_=undefined;this.controls_=document.createElement('top-controls');this.renderPassQuads_=false;this.style.display='flex';this.style.flexDirection='column';this.controls_.style.flexGrow=0;this.controls_.style.flexShrink=0;this.controls_.style.flexBasis='auto';this.controls_.style.backgroundImage='-webkit-gradient(linear, 0 0, 100% 0, from(#E5E5E5), to(#D1D1D1))';this.controls_.style.borderBottom='1px solid #8e8e8e';this.controls_.style.borderTop='1px solid white';this.controls_.style.display='inline';this.controls_.style.fontSize='14px';this.controls_.style.paddingLeft='2px';this.itemList_=new tr.ui.b.ListView();this.itemList_.style.flexGrow=1;this.itemList_.style.flexShrink=1;this.itemList_.style.flexBasis='auto';this.itemList_.style.fontFamily='monospace';this.itemList_.style.overflow='auto';Polymer.dom(this).appendChild(this.controls_);Polymer.dom(this).appendChild(this.itemList_);this.itemList_.addEventListener('selection-changed',this.onItemSelectionChanged_.bind(this));Polymer.dom(this.controls_).appendChild(tr.ui.b.createSelector(this,'whichTree','layerPicker.whichTree',constants.ACTIVE_TREE,[{label:'Active tree',value:constants.ACTIVE_TREE},{label:'Pending tree',value:constants.PENDING_TREE},{label:'Render pass quads',value:RENDER_PASS_QUADS}]));this.showPureTransformLayers_=false;const showPureTransformLayers=tr.ui.b.createCheckBox(this,'showPureTransformLayers','layerPicker.showPureTransformLayers',false,'Transform layers');Polymer.dom(showPureTransformLayers).classList.add('show-transform-layers');showPureTransformLayers.title='When checked, pure transform layers are shown';Polymer.dom(this.controls_).appendChild(showPureTransformLayers);},get lthiSnapshot(){return this.lthiSnapshot_;},set lthiSnapshot(lthiSnapshot){this.lthiSnapshot_=lthiSnapshot;this.updateContents_();},get whichTree(){return this.renderPassQuads_?constants.ACTIVE_TREE:this.whichTree_;},set whichTree(whichTree){this.whichTree_=whichTree;this.renderPassQuads_=(whichTree===RENDER_PASS_QUADS);this.updateContents_();tr.b.dispatchSimpleEvent(this,'selection-change',false);},get layerTreeImpl(){if(this.lthiSnapshot===undefined)return undefined;return this.lthiSnapshot.getTree(this.whichTree);},get isRenderPassQuads(){return this.renderPassQuads_;},get showPureTransformLayers(){return this.showPureTransformLayers_;},set showPureTransformLayers(show){if(this.showPureTransformLayers_===show)return;this.showPureTransformLayers_=show;this.updateContents_();},getRenderPassInfos_(){if(!this.lthiSnapshot_)return[];const renderPassInfo=[];if(!this.lthiSnapshot_.args.frame||!this.lthiSnapshot_.args.frame.renderPasses){return renderPassInfo;}
+const renderPasses=this.lthiSnapshot_.args.frame.renderPasses;for(let i=0;i<renderPasses.length;++i){const info={renderPass:renderPasses[i],depth:0,id:i,name:'cc::RenderPass'};renderPassInfo.push(info);}
+return renderPassInfo;},getLayerInfos_(){if(!this.lthiSnapshot_)return[];const tree=this.lthiSnapshot_.getTree(this.whichTree_);if(!tree)return[];const layerInfos=[];const showPureTransformLayers=this.showPureTransformLayers_;const visitedLayers={};function visitLayer(layer,depth,isMask,isReplica){if(visitedLayers[layer.layerId])return;visitedLayers[layer.layerId]=true;const info={layer,depth};if(layer.args.drawsContent){info.name=layer.objectInstance.name;}else{info.name='cc::LayerImpl';}
+if(layer.usingGpuRasterization){info.name+=' (G)';}
+info.isMaskLayer=isMask;info.replicaLayer=isReplica;if(showPureTransformLayers||layer.args.drawsContent){layerInfos.push(info);}}
+tree.iterLayers(visitLayer);return layerInfos;},updateContents_(){if(this.renderPassQuads_){this.updateRenderPassContents_();}else{this.updateLayerContents_();}},updateRenderPassContents_(){this.itemList_.clear();let selectedRenderPassId;if(this.selection_&&this.selection_.associatedRenderPassId){selectedRenderPassId=this.selection_.associatedRenderPassId;}
+const renderPassInfos=this.getRenderPassInfos_();renderPassInfos.forEach(function(renderPassInfo){const renderPass=renderPassInfo.renderPass;const id=renderPassInfo.id;const item=this.createElementWithDepth_(renderPassInfo.depth);const labelEl=Polymer.dom(item).appendChild(tr.ui.b.createSpan());Polymer.dom(labelEl).textContent=renderPassInfo.name+' '+id;item.renderPass=renderPass;item.renderPassId=id;Polymer.dom(this.itemList_).appendChild(item);if(id===selectedRenderPassId){renderPass.selectionState=tr.model.SelectionState.SELECTED;}},this);},updateLayerContents_(){this.changingItemSelection_=true;try{this.itemList_.clear();let selectedLayerId;if(this.selection_&&this.selection_.associatedLayerId){selectedLayerId=this.selection_.associatedLayerId;}
+const layerInfos=this.getLayerInfos_();layerInfos.forEach(function(layerInfo){const layer=layerInfo.layer;const id=layer.layerId;const item=this.createElementWithDepth_(layerInfo.depth);const labelEl=Polymer.dom(item).appendChild(tr.ui.b.createSpan());Polymer.dom(labelEl).textContent=layerInfo.name+' '+id;const notesEl=Polymer.dom(item).appendChild(tr.ui.b.createSpan());if(layerInfo.isMaskLayer){Polymer.dom(notesEl).textContent+='(mask)';}
+if(layerInfo.isReplicaLayer){Polymer.dom(notesEl).textContent+='(replica)';}
+if((layer.gpuMemoryUsageInBytes!==undefined)&&(layer.gpuMemoryUsageInBytes>0)){const gpuUsageStr=tr.b.Unit.byName.sizeInBytes.format(layer.gpuMemoryUsageInBytes);Polymer.dom(notesEl).textContent+=' ('+gpuUsageStr+' MiB)';}
+item.layer=layer;Polymer.dom(this.itemList_).appendChild(item);if(layer.layerId===selectedLayerId){layer.selectionState=tr.model.SelectionState.SELECTED;item.selected=true;}},this);}finally{this.changingItemSelection_=false;}},createElementWithDepth_(depth){const item=document.createElement('div');const indentEl=Polymer.dom(item).appendChild(tr.ui.b.createSpan());indentEl.style.whiteSpace='pre';for(let i=0;i<depth;i++){Polymer.dom(indentEl).textContent=Polymer.dom(indentEl).textContent+' ';}
+return item;},onItemSelectionChanged_(e){if(this.changingItemSelection_)return;if(this.renderPassQuads_){this.onRenderPassSelected_(e);}else{this.onLayerSelected_(e);}
+tr.b.dispatchSimpleEvent(this,'selection-change',false);},onRenderPassSelected_(e){let selectedRenderPass;let selectedRenderPassId;if(this.itemList_.selectedElement){selectedRenderPass=this.itemList_.selectedElement.renderPass;selectedRenderPassId=this.itemList_.selectedElement.renderPassId;}
+if(selectedRenderPass){this.selection_=new tr.ui.e.chrome.cc.RenderPassSelection(selectedRenderPass,selectedRenderPassId);}else{this.selection_=undefined;}},onLayerSelected_(e){let selectedLayer;if(this.itemList_.selectedElement){selectedLayer=this.itemList_.selectedElement.layer;}
+if(selectedLayer){this.selection_=new tr.ui.e.chrome.cc.LayerSelection(selectedLayer);}else{this.selection_=undefined;}},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.updateContents_();}};return{LayerPicker,};});'use strict';tr.exportTo('tr.e.cc',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function RenderPassSnapshot(){ObjectSnapshot.apply(this,arguments);}
+RenderPassSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){tr.e.cc.preInitializeObject(this);},initialize(){tr.e.cc.moveRequiredFieldsFromArgsToToplevel(this,['quadList']);}};ObjectSnapshot.subTypes.register(RenderPassSnapshot,{typeName:'cc::RenderPass'});return{RenderPassSnapshot,};});'use strict';tr.exportTo('tr.ui.b',function(){const deg2rad=tr.b.math.deg2rad;const constants={DEFAULT_SCALE:0.5,DEFAULT_EYE_DISTANCE:10000,MINIMUM_DISTANCE:1000,MAXIMUM_DISTANCE:100000,FOV:15,RESCALE_TIMEOUT_MS:200,MAXIMUM_TILT:80,SETTINGS_NAMESPACE:'tr.ui_camera'};const Camera=tr.ui.b.define('camera');Camera.prototype={__proto__:HTMLUnknownElement.prototype,decorate(eventSource){this.eventSource_=eventSource;this.eventSource_.addEventListener('beginpan',this.onPanBegin_.bind(this));this.eventSource_.addEventListener('updatepan',this.onPanUpdate_.bind(this));this.eventSource_.addEventListener('endpan',this.onPanEnd_.bind(this));this.eventSource_.addEventListener('beginzoom',this.onZoomBegin_.bind(this));this.eventSource_.addEventListener('updatezoom',this.onZoomUpdate_.bind(this));this.eventSource_.addEventListener('endzoom',this.onZoomEnd_.bind(this));this.eventSource_.addEventListener('beginrotate',this.onRotateBegin_.bind(this));this.eventSource_.addEventListener('updaterotate',this.onRotateUpdate_.bind(this));this.eventSource_.addEventListener('endrotate',this.onRotateEnd_.bind(this));this.eye_=[0,0,constants.DEFAULT_EYE_DISTANCE];this.gazeTarget_=[0,0,0];this.rotation_=[0,0];this.pixelRatio_=window.devicePixelRatio||1;},get modelViewMatrix(){const mvMatrix=mat4.create();mat4.lookAt(mvMatrix,this.eye_,this.gazeTarget_,[0,1,0]);return mvMatrix;},get projectionMatrix(){const rect=tr.ui.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);const aspectRatio=rect.width/rect.height;const matrix=mat4.create();mat4.perspective(matrix,deg2rad(constants.FOV),aspectRatio,1,100000);return matrix;},set canvas(c){this.canvas_=c;},set deviceRect(rect){this.deviceRect_=rect;},get stackingDistanceDampening(){const gazeVector=[this.gazeTarget_[0]-this.eye_[0],this.gazeTarget_[1]-this.eye_[1],this.gazeTarget_[2]-this.eye_[2]];vec3.normalize(gazeVector,gazeVector);return 1+gazeVector[2];},loadCameraFromSettings(settings){this.eye_=settings.get('eye',this.eye_,constants.SETTINGS_NAMESPACE);this.gazeTarget_=settings.get('gaze_target',this.gazeTarget_,constants.SETTINGS_NAMESPACE);this.rotation_=settings.get('rotation',this.rotation_,constants.SETTINGS_NAMESPACE);this.dispatchRenderEvent_();},saveCameraToSettings(settings){settings.set('eye',this.eye_,constants.SETTINGS_NAMESPACE);settings.set('gaze_target',this.gazeTarget_,constants.SETTINGS_NAMESPACE);settings.set('rotation',this.rotation_,constants.SETTINGS_NAMESPACE);},resetCamera(){this.eye_=[0,0,constants.DEFAULT_EYE_DISTANCE];this.gazeTarget_=[0,0,0];this.rotation_=[0,0];const settings=tr.b.SessionSettings();const keys=settings.keys(constants.SETTINGS_NAMESPACE);if(keys.length!==0){this.loadCameraFromSettings(settings);return;}
+if(this.deviceRect_){const rect=tr.ui.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);this.eye_[0]=this.deviceRect_.width/2;this.eye_[1]=this.deviceRect_.height/2;this.gazeTarget_[0]=this.deviceRect_.width/2;this.gazeTarget_[1]=this.deviceRect_.height/2;}
+this.saveCameraToSettings(settings);this.dispatchRenderEvent_();},updatePanByDelta(delta){const rect=tr.ui.b.windowRectForElement(this.canvas_).scaleSize(this.pixelRatio_);const eyeVector=[this.eye_[0]-this.gazeTarget_[0],this.eye_[1]-this.gazeTarget_[1],this.eye_[2]-this.gazeTarget_[2]];const length=vec3.length(eyeVector);vec3.normalize(eyeVector,eyeVector);const halfFov=constants.FOV/2;const multiplier=2.0*length*Math.tan(deg2rad(halfFov))/rect.height;const up=[0,1,0];const rotMatrix=mat4.create();mat4.rotate(rotMatrix,rotMatrix,deg2rad(this.rotation_[1]),[0,1,0]);mat4.rotate(rotMatrix,rotMatrix,deg2rad(this.rotation_[0]),[1,0,0]);vec3.transformMat4(up,up,rotMatrix);const right=[0,0,0];vec3.cross(right,eyeVector,up);vec3.normalize(right,right);for(let i=0;i<3;++i){this.gazeTarget_[i]+=delta[0]*multiplier*right[i]-delta[1]*multiplier*up[i];this.eye_[i]=this.gazeTarget_[i]+length*eyeVector[i];}
+if(Math.abs(this.gazeTarget_[2])>1e-6){const gazeVector=[-eyeVector[0],-eyeVector[1],-eyeVector[2]];const newLength=tr.b.math.clamp(-this.eye_[2]/gazeVector[2],constants.MINIMUM_DISTANCE,constants.MAXIMUM_DISTANCE);for(let i=0;i<3;++i){this.gazeTarget_[i]=this.eye_[i]+newLength*gazeVector[i];}}
+this.saveCameraToSettings(tr.b.SessionSettings());this.dispatchRenderEvent_();},updateZoomByDelta(delta){let deltaY=delta[1];deltaY=tr.b.math.clamp(deltaY,-50,50);let scale=1.0-deltaY/100.0;const eyeVector=[0,0,0];vec3.subtract(eyeVector,this.eye_,this.gazeTarget_);const length=vec3.length(eyeVector);if(length*scale<constants.MINIMUM_DISTANCE){scale=constants.MINIMUM_DISTANCE/length;}else if(length*scale>constants.MAXIMUM_DISTANCE){scale=constants.MAXIMUM_DISTANCE/length;}
+vec3.scale(eyeVector,eyeVector,scale);vec3.add(this.eye_,this.gazeTarget_,eyeVector);this.saveCameraToSettings(tr.b.SessionSettings());this.dispatchRenderEvent_();},updateRotateByDelta(delta){delta[0]*=0.5;delta[1]*=0.5;if(Math.abs(this.rotation_[0]+delta[1])>constants.MAXIMUM_TILT){return;}
+if(Math.abs(this.rotation_[1]-delta[0])>constants.MAXIMUM_TILT){return;}
+const eyeVector=[0,0,0,0];vec3.subtract(eyeVector,this.eye_,this.gazeTarget_);const rotMatrix=mat4.create();mat4.rotate(rotMatrix,rotMatrix,-deg2rad(this.rotation_[0]),[1,0,0]);mat4.rotate(rotMatrix,rotMatrix,-deg2rad(this.rotation_[1]),[0,1,0]);vec4.transformMat4(eyeVector,eyeVector,rotMatrix);this.rotation_[0]+=delta[1];this.rotation_[1]-=delta[0];mat4.identity(rotMatrix);mat4.rotate(rotMatrix,rotMatrix,deg2rad(this.rotation_[1]),[0,1,0]);mat4.rotate(rotMatrix,rotMatrix,deg2rad(this.rotation_[0]),[1,0,0]);vec4.transformMat4(eyeVector,eyeVector,rotMatrix);vec3.add(this.eye_,this.gazeTarget_,eyeVector);this.saveCameraToSettings(tr.b.SessionSettings());this.dispatchRenderEvent_();},onPanBegin_(e){this.panning_=true;this.lastMousePosition_=this.getMousePosition_(e);},onPanUpdate_(e){if(!this.panning_)return;const delta=this.getMouseDelta_(e,this.lastMousePosition_);this.lastMousePosition_=this.getMousePosition_(e);this.updatePanByDelta(delta);},onPanEnd_(e){this.panning_=false;},onZoomBegin_(e){this.zooming_=true;const p=this.getMousePosition_(e);this.lastMousePosition_=p;this.zoomPoint_=p;},onZoomUpdate_(e){if(!this.zooming_)return;const delta=this.getMouseDelta_(e,this.lastMousePosition_);this.lastMousePosition_=this.getMousePosition_(e);this.updateZoomByDelta(delta);},onZoomEnd_(e){this.zooming_=false;this.zoomPoint_=undefined;},onRotateBegin_(e){this.rotating_=true;this.lastMousePosition_=this.getMousePosition_(e);},onRotateUpdate_(e){if(!this.rotating_)return;const delta=this.getMouseDelta_(e,this.lastMousePosition_);this.lastMousePosition_=this.getMousePosition_(e);this.updateRotateByDelta(delta);},onRotateEnd_(e){this.rotating_=false;},getMousePosition_(e){const rect=tr.ui.b.windowRectForElement(this.canvas_);return[(e.clientX-rect.x)*this.pixelRatio_,(e.clientY-rect.y)*this.pixelRatio_];},getMouseDelta_(e,p){const newP=this.getMousePosition_(e);return[newP[0]-p[0],newP[1]-p[1]];},dispatchRenderEvent_(){tr.b.dispatchSimpleEvent(this,'renderrequired',false,false);}};return{Camera,};});'use strict';tr.exportTo('tr.ui.b',function(){const THIS_DOC=document.currentScript.ownerDocument;const constants={};constants.IMAGE_LOAD_RETRY_TIME_MS=500;constants.SUBDIVISION_MINIMUM=1;constants.SUBDIVISION_RECURSION_DEPTH=3;constants.SUBDIVISION_DEPTH_THRESHOLD=100;constants.FAR_PLANE_DISTANCE=10000;function drawTexturedTriangle(ctx,img,p0,p1,p2,t0,t1,t2){const tmpP0=[p0[0],p0[1]];const tmpP1=[p1[0],p1[1]];const tmpP2=[p2[0],p2[1]];const tmpT0=[t0[0],t0[1]];const tmpT1=[t1[0],t1[1]];const tmpT2=[t2[0],t2[1]];ctx.beginPath();ctx.moveTo(tmpP0[0],tmpP0[1]);ctx.lineTo(tmpP1[0],tmpP1[1]);ctx.lineTo(tmpP2[0],tmpP2[1]);ctx.closePath();tmpP1[0]-=tmpP0[0];tmpP1[1]-=tmpP0[1];tmpP2[0]-=tmpP0[0];tmpP2[1]-=tmpP0[1];tmpT1[0]-=tmpT0[0];tmpT1[1]-=tmpT0[1];tmpT2[0]-=tmpT0[0];tmpT2[1]-=tmpT0[1];const det=1/(tmpT1[0]*tmpT2[1]-tmpT2[0]*tmpT1[1]);const a=(tmpT2[1]*tmpP1[0]-tmpT1[1]*tmpP2[0])*det;const b=(tmpT2[1]*tmpP1[1]-tmpT1[1]*tmpP2[1])*det;const c=(tmpT1[0]*tmpP2[0]-tmpT2[0]*tmpP1[0])*det;const d=(tmpT1[0]*tmpP2[1]-tmpT2[0]*tmpP1[1])*det;const e=tmpP0[0]-a*tmpT0[0]-c*tmpT0[1];const f=tmpP0[1]-b*tmpT0[0]-d*tmpT0[1];ctx.save();ctx.transform(a,b,c,d,e,f);ctx.clip();ctx.drawImage(img,0,0);ctx.restore();}
+function drawTriangleSub(ctx,img,p0,p1,p2,t0,t1,t2,opt_recursionDepth){const depth=opt_recursionDepth||0;let subdivisionIndex=0;if(depth<constants.SUBDIVISION_MINIMUM){subdivisionIndex=7;}else if(depth<constants.SUBDIVISION_RECURSION_DEPTH){if(Math.abs(p0[2]-p1[2])>constants.SUBDIVISION_DEPTH_THRESHOLD){subdivisionIndex+=1;}
+if(Math.abs(p0[2]-p2[2])>constants.SUBDIVISION_DEPTH_THRESHOLD){subdivisionIndex+=2;}
+if(Math.abs(p1[2]-p2[2])>constants.SUBDIVISION_DEPTH_THRESHOLD){subdivisionIndex+=4;}}
+const p01=vec4.create();const p02=vec4.create();const p12=vec4.create();const t01=vec2.create();const t02=vec2.create();const t12=vec2.create();for(let i=0;i<2;++i){p0[i]*=p0[2];p1[i]*=p1[2];p2[i]*=p2[2];}
+for(let i=0;i<4;++i){p01[i]=(p0[i]+p1[i])/2;p02[i]=(p0[i]+p2[i])/2;p12[i]=(p1[i]+p2[i])/2;}
+for(let i=0;i<2;++i){p0[i]/=p0[2];p1[i]/=p1[2];p2[i]/=p2[2];p01[i]/=p01[2];p02[i]/=p02[2];p12[i]/=p12[2];}
+for(let i=0;i<2;++i){t01[i]=(t0[i]+t1[i])/2;t02[i]=(t0[i]+t2[i])/2;t12[i]=(t1[i]+t2[i])/2;}
+switch(subdivisionIndex){case 1:drawTriangleSub(ctx,img,p0,p01,p2,t0,t01,t2,depth+1);drawTriangleSub(ctx,img,p01,p1,p2,t01,t1,t2,depth+1);break;case 2:drawTriangleSub(ctx,img,p0,p1,p02,t0,t1,t02,depth+1);drawTriangleSub(ctx,img,p1,p02,p2,t1,t02,t2,depth+1);break;case 3:drawTriangleSub(ctx,img,p0,p01,p02,t0,t01,t02,depth+1);drawTriangleSub(ctx,img,p02,p01,p2,t02,t01,t2,depth+1);drawTriangleSub(ctx,img,p01,p1,p2,t01,t1,t2,depth+1);break;case 4:drawTriangleSub(ctx,img,p0,p12,p2,t0,t12,t2,depth+1);drawTriangleSub(ctx,img,p0,p1,p12,t0,t1,t12,depth+1);break;case 5:drawTriangleSub(ctx,img,p0,p01,p2,t0,t01,t2,depth+1);drawTriangleSub(ctx,img,p2,p01,p12,t2,t01,t12,depth+1);drawTriangleSub(ctx,img,p01,p1,p12,t01,t1,t12,depth+1);break;case 6:drawTriangleSub(ctx,img,p0,p12,p02,t0,t12,t02,depth+1);drawTriangleSub(ctx,img,p0,p1,p12,t0,t1,t12,depth+1);drawTriangleSub(ctx,img,p02,p12,p2,t02,t12,t2,depth+1);break;case 7:drawTriangleSub(ctx,img,p0,p01,p02,t0,t01,t02,depth+1);drawTriangleSub(ctx,img,p01,p12,p02,t01,t12,t02,depth+1);drawTriangleSub(ctx,img,p01,p1,p12,t01,t1,t12,depth+1);drawTriangleSub(ctx,img,p02,p12,p2,t02,t12,t2,depth+1);break;default:drawTexturedTriangle(ctx,img,p0,p1,p2,t0,t1,t2);break;}}
+const tmpVec4=vec4.create();function transform(transformed,point,matrix,viewport){vec4.set(tmpVec4,point[0],point[1],0,1);vec4.transformMat4(tmpVec4,tmpVec4,matrix);let w=tmpVec4[3];if(w<1e-6)w=1e-6;transformed[0]=((tmpVec4[0]/w)+1)*viewport.width/2;transformed[1]=((tmpVec4[1]/w)+1)*viewport.height/2;transformed[2]=w;}
+function drawProjectedQuadBackgroundToContext(quad,p1,p2,p3,p4,ctx,quadCanvas){if(quad.imageData){quadCanvas.width=quad.imageData.width;quadCanvas.height=quad.imageData.height;quadCanvas.getContext('2d').putImageData(quad.imageData,0,0);const quadBBox=new tr.b.math.BBox2();quadBBox.addQuad(quad);const iw=quadCanvas.width;const ih=quadCanvas.height;drawTriangleSub(ctx,quadCanvas,p1,p2,p4,[0,0],[iw,0],[0,ih]);drawTriangleSub(ctx,quadCanvas,p2,p3,p4,[iw,0],[iw,ih],[0,ih]);}
+if(quad.backgroundColor){ctx.fillStyle=quad.backgroundColor;ctx.beginPath();ctx.moveTo(p1[0],p1[1]);ctx.lineTo(p2[0],p2[1]);ctx.lineTo(p3[0],p3[1]);ctx.lineTo(p4[0],p4[1]);ctx.closePath();ctx.fill();}}
+function drawProjectedQuadOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas){ctx.beginPath();ctx.moveTo(p1[0],p1[1]);ctx.lineTo(p2[0],p2[1]);ctx.lineTo(p3[0],p3[1]);ctx.lineTo(p4[0],p4[1]);ctx.closePath();ctx.save();if(quad.borderColor){ctx.strokeStyle=quad.borderColor;}else{ctx.strokeStyle='rgb(128,128,128)';}
+if(quad.shadowOffset){ctx.shadowColor='rgb(0, 0, 0)';ctx.shadowOffsetX=quad.shadowOffset[0];ctx.shadowOffsetY=quad.shadowOffset[1];if(quad.shadowBlur){ctx.shadowBlur=quad.shadowBlur;}}
+if(quad.borderWidth){ctx.lineWidth=quad.borderWidth;}else{ctx.lineWidth=1;}
+ctx.stroke();ctx.restore();}
+function drawProjectedQuadSelectionOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas){if(!quad.upperBorderColor)return;ctx.lineWidth=8;ctx.strokeStyle=quad.upperBorderColor;ctx.beginPath();ctx.moveTo(p1[0],p1[1]);ctx.lineTo(p2[0],p2[1]);ctx.lineTo(p3[0],p3[1]);ctx.lineTo(p4[0],p4[1]);ctx.closePath();ctx.stroke();}
+function drawProjectedQuadToContext(passNumber,quad,p1,p2,p3,p4,ctx,quadCanvas){if(passNumber===0){drawProjectedQuadBackgroundToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===1){drawProjectedQuadOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else if(passNumber===2){drawProjectedQuadSelectionOutlineToContext(quad,p1,p2,p3,p4,ctx,quadCanvas);}else{throw new Error('Invalid pass number');}}
+const tmpP1=vec3.create();const tmpP2=vec3.create();const tmpP3=vec3.create();const tmpP4=vec3.create();function transformAndProcessQuads(matrix,viewport,quads,numPasses,handleQuadFunc,opt_arg1,opt_arg2){for(let passNumber=0;passNumber<numPasses;passNumber++){for(let i=0;i<quads.length;i++){const quad=quads[i];transform(tmpP1,quad.p1,matrix,viewport);transform(tmpP2,quad.p2,matrix,viewport);transform(tmpP3,quad.p3,matrix,viewport);transform(tmpP4,quad.p4,matrix,viewport);handleQuadFunc(passNumber,quad,tmpP1,tmpP2,tmpP3,tmpP4,opt_arg1,opt_arg2);}}}
+const QuadStackView=tr.ui.b.define('quad-stack-view');QuadStackView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.className='quad-stack-view';this.style.display='flex';this.style.position='relative';const node=tr.ui.b.instantiateTemplate('#quad-stack-view-template',THIS_DOC);Polymer.dom(this).appendChild(node);this.updateHeaderVisibility_();const header=Polymer.dom(this).querySelector('#header');header.style.position='absolute';header.style.fontSize='70%';header.style.top='10px';header.style.left='10px';header.style.right='150px';const scroller=Polymer.dom(this).querySelector('#canvas-scroller');scroller.style.flexGrow=1;scroller.style.flexShrink=1;scroller.style.flexBasis='auto';scroller.style.minWidth=0;scroller.style.minHeight=0;scroller.style.overflow='auto';this.canvas_=Polymer.dom(this).querySelector('#canvas');this.chromeImages_={left:Polymer.dom(this).querySelector('#chrome-left'),mid:Polymer.dom(this).querySelector('#chrome-mid'),right:Polymer.dom(this).querySelector('#chrome-right')};const stackingDistanceSlider=Polymer.dom(this).querySelector('#stacking-distance-slider');stackingDistanceSlider.style.position='absolute';stackingDistanceSlider.style.fontSize='70%';stackingDistanceSlider.style.top='10px';stackingDistanceSlider.style.right='10px';stackingDistanceSlider.value=tr.b.Settings.get('quadStackView.stackingDistance',45);stackingDistanceSlider.addEventListener('change',this.onStackingDistanceChange_.bind(this));stackingDistanceSlider.addEventListener('input',this.onStackingDistanceChange_.bind(this));this.trackMouse_();this.camera_=new tr.ui.b.Camera(this.mouseModeSelector_);this.camera_.addEventListener('renderrequired',this.onRenderRequired_.bind(this));this.cameraWasReset_=false;this.camera_.canvas=this.canvas_;this.viewportRect_=tr.b.math.Rect.fromXYWH(0,0,0,0);this.pixelRatio_=window.devicePixelRatio||1;},updateHeaderVisibility_(){if(this.headerText){Polymer.dom(this).querySelector('#header').style.display='';}else{Polymer.dom(this).querySelector('#header').style.display='none';}},get headerText(){return Polymer.dom(this).querySelector('#header').textContent;},set headerText(headerText){Polymer.dom(this).querySelector('#header').textContent=headerText;this.updateHeaderVisibility_();},onStackingDistanceChange_(e){tr.b.Settings.set('quadStackView.stackingDistance',this.stackingDistance);this.scheduleRender();e.stopPropagation();},get stackingDistance(){return Polymer.dom(this).querySelector('#stacking-distance-slider').value;},get mouseModeSelector(){return this.mouseModeSelector_;},get camera(){return this.camera_;},set quads(q){this.quads_=q;this.scheduleRender();},set deviceRect(rect){if(!rect||rect.equalTo(this.deviceRect_))return;this.deviceRect_=rect;this.camera_.deviceRect=rect;this.chromeQuad_=undefined;},resize(){if(!this.offsetParent)return true;const width=parseInt(window.getComputedStyle(this.offsetParent).width);const height=parseInt(window.getComputedStyle(this.offsetParent).height);const rect=tr.b.math.Rect.fromXYWH(0,0,width,height);if(rect.equalTo(this.viewportRect_))return false;this.viewportRect_=rect;this.canvas_.style.width=width+'px';this.canvas_.style.height=height+'px';this.canvas_.width=this.pixelRatio_*width;this.canvas_.height=this.pixelRatio_*height;if(!this.cameraWasReset_){this.camera_.resetCamera();this.cameraWasReset_=true;}
+return true;},readyToDraw(){if(!this.chromeImages_.left.src){let leftContent=window.getComputedStyle(this.chromeImages_.left).backgroundImage;leftContent=tr.ui.b.extractUrlString(leftContent);let midContent=window.getComputedStyle(this.chromeImages_.mid).backgroundImage;midContent=tr.ui.b.extractUrlString(midContent);let rightContent=window.getComputedStyle(this.chromeImages_.right).backgroundImage;rightContent=tr.ui.b.extractUrlString(rightContent);this.chromeImages_.left.src=leftContent;this.chromeImages_.mid.src=midContent;this.chromeImages_.right.src=rightContent;}
+return(this.chromeImages_.left.height>0)&&(this.chromeImages_.mid.height>0)&&(this.chromeImages_.right.height>0);},get chromeQuad(){if(this.chromeQuad_)return this.chromeQuad_;const chromeCanvas=document.createElement('canvas');const offsetY=this.chromeImages_.left.height;chromeCanvas.width=this.deviceRect_.width;chromeCanvas.height=this.deviceRect_.height+offsetY;const leftWidth=this.chromeImages_.left.width;const midWidth=this.chromeImages_.mid.width;const rightWidth=this.chromeImages_.right.width;const chromeCtx=chromeCanvas.getContext('2d');chromeCtx.drawImage(this.chromeImages_.left,0,0);chromeCtx.save();chromeCtx.translate(leftWidth,0);const s=(this.deviceRect_.width-leftWidth-rightWidth)/midWidth;chromeCtx.scale(s,1);chromeCtx.drawImage(this.chromeImages_.mid,0,0);chromeCtx.restore();chromeCtx.drawImage(this.chromeImages_.right,leftWidth+s*midWidth,0);const chromeRect=tr.b.math.Rect.fromXYWH(this.deviceRect_.x,this.deviceRect_.y-offsetY,this.deviceRect_.width,this.deviceRect_.height+offsetY);const chromeQuad=tr.b.math.Quad.fromRect(chromeRect);chromeQuad.stackingGroupId=this.maxStackingGroupId_+1;chromeQuad.imageData=chromeCtx.getImageData(0,0,chromeCanvas.width,chromeCanvas.height);chromeQuad.shadowOffset=[0,0];chromeQuad.shadowBlur=5;chromeQuad.borderWidth=3;this.chromeQuad_=chromeQuad;return this.chromeQuad_;},scheduleRender(){if(this.redrawScheduled_)return false;this.redrawScheduled_=true;tr.b.requestAnimationFrame(this.render,this);},onRenderRequired_(e){this.scheduleRender();},stackTransformAndProcessQuads_(numPasses,handleQuadFunc,includeChromeQuad,opt_arg1,opt_arg2){const mv=this.camera_.modelViewMatrix;const p=this.camera_.projectionMatrix;const viewport=tr.b.math.Rect.fromXYWH(0,0,this.canvas_.width,this.canvas_.height);const quadStacks=[];for(let i=0;i<this.quads_.length;++i){const quad=this.quads_[i];const stackingId=quad.stackingGroupId||0;while(stackingId>=quadStacks.length){quadStacks.push([]);}
+quadStacks[stackingId].push(quad);}
+const mvp=mat4.create();this.maxStackingGroupId_=quadStacks.length;const effectiveStackingDistance=this.stackingDistance*this.camera_.stackingDistanceDampening;mat4.multiply(mvp,p,mv);for(let i=0;i<quadStacks.length;++i){transformAndProcessQuads(mvp,viewport,quadStacks[i],numPasses,handleQuadFunc,opt_arg1,opt_arg2);mat4.translate(mv,mv,[0,0,effectiveStackingDistance]);mat4.multiply(mvp,p,mv);}
+if(includeChromeQuad&&this.deviceRect_){transformAndProcessQuads(mvp,viewport,[this.chromeQuad],numPasses,drawProjectedQuadToContext,opt_arg1,opt_arg2);}},render(){this.redrawScheduled_=false;if(!this.readyToDraw()){setTimeout(this.scheduleRender.bind(this),constants.IMAGE_LOAD_RETRY_TIME_MS);return;}
+if(!this.quads_)return;const canvasCtx=this.canvas_.getContext('2d');if(!this.resize()){canvasCtx.clearRect(0,0,this.canvas_.width,this.canvas_.height);}
+const quadCanvas=document.createElement('canvas');this.stackTransformAndProcessQuads_(3,drawProjectedQuadToContext,true,canvasCtx,quadCanvas);quadCanvas.width=0;},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.canvas_;this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION|tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN|tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM|tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN;this.mouseModeSelector_.pos={x:0,y:100};Polymer.dom(this).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.settingsKey='quadStackView.mouseModeSelector';this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ROTATE,tr.ui.b.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.PANSCAN,tr.ui.b.MODIFIER.SPACE);this.mouseModeSelector_.setModifierForAlternateMode(tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM,tr.ui.b.MODIFIER.CMD_OR_CTRL);this.mouseModeSelector_.addEventListener('updateselection',this.onSelectionUpdate_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onSelectionUpdate_.bind(this));},extractRelativeMousePosition_(e){const br=this.canvas_.getBoundingClientRect();return[this.pixelRatio_*(e.clientX-this.canvas_.offsetLeft-br.left),this.pixelRatio_*(e.clientY-this.canvas_.offsetTop-br.top)];},onSelectionUpdate_(e){const mousePos=this.extractRelativeMousePosition_(e);const res=[];function handleQuad(passNumber,quad,p1,p2,p3,p4){if(tr.b.math.pointInImplicitQuad(mousePos,p1,p2,p3,p4)){res.push(quad);}}
+this.stackTransformAndProcessQuads_(1,handleQuad,false);e=new tr.b.Event('selectionchange');e.quads=res;this.dispatchEvent(e);}};return{QuadStackView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const ColorScheme=tr.b.ColorScheme;const THIS_DOC=document.currentScript.ownerDocument;const TILE_HEATMAP_TYPE={};TILE_HEATMAP_TYPE.NONE='none';TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY='scheduledPriority';TILE_HEATMAP_TYPE.USING_GPU_MEMORY='usingGpuMemory';const cc=tr.ui.e.chrome.cc;function createTileRectsSelectorBaseOptions(){return[{label:'None',value:'none'},{label:'Coverage Rects',value:'coverage'}];}
+const LayerTreeQuadStackView=tr.ui.b.define('tr-ui-e-chrome-cc-layer-tree-quad-stack-view');LayerTreeQuadStackView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.flexDirection='column';this.style.minHeight=0;this.style.display='flex';this.isRenderPassQuads_=false;this.pictureAsImageData_={};this.messages_=[];this.controls_=document.createElement('top-controls');this.controls_.style.flexGrow=0;this.controls_.style.flexShrink=0;this.controls_.style.flexBasis='auto';this.controls_.style.backgroundImage='-webkit-gradient(linear, 0 0, 100% 0, from(#E5E5E5), to(#D1D1D1))';this.controls_.style.borderBottom='1px solid #8e8e8e';this.controls_.style.borderTop='1px solid white';this.controls_.style.display='flex';this.controls_.style.flexDirection='row';this.controls_.style.flexWrap='wrap';this.controls_.style.fontSize='14px';this.controls_.style.paddingLeft='2px';this.controls_.style.overflow='hidden';this.infoBar_=document.createElement('tr-ui-b-info-bar');this.quadStackView_=new tr.ui.b.QuadStackView();this.quadStackView_.addEventListener('selectionchange',this.onQuadStackViewSelectionChange_.bind(this));this.quadStackView_.style.flexGrow=1;this.quadStackView_.style.flexShrink=1;this.quadStackView_.style.flexBasis='auto';this.quadStackView_.style.minWidth='200px';this.extraHighlightsByLayerId_=undefined;this.inputEventImageData_=undefined;const m=tr.ui.b.MOUSE_SELECTOR_MODE;const mms=this.quadStackView_.mouseModeSelector;mms.settingsKey='tr.e.cc.layerTreeQuadStackView.mouseModeSelector';mms.setKeyCodeForMode(m.SELECTION,'Z'.charCodeAt(0));mms.setKeyCodeForMode(m.PANSCAN,'X'.charCodeAt(0));mms.setKeyCodeForMode(m.ZOOM,'C'.charCodeAt(0));mms.setKeyCodeForMode(m.ROTATE,'V'.charCodeAt(0));const node=tr.ui.b.instantiateTemplate('#tr-ui-e-chrome-cc-layer-tree-quad-stack-view-template',THIS_DOC);Polymer.dom(this).appendChild(node);Polymer.dom(this).appendChild(this.controls_);Polymer.dom(this).appendChild(this.infoBar_);Polymer.dom(this).appendChild(this.quadStackView_);this.tileRectsSelector_=tr.ui.b.createSelector(this,'howToShowTiles','layerView.howToShowTiles','none',createTileRectsSelectorBaseOptions());Polymer.dom(this.controls_).appendChild(this.tileRectsSelector_);const tileHeatmapText=tr.ui.b.createSpan({textContent:'Tile heatmap:'});Polymer.dom(this.controls_).appendChild(tileHeatmapText);const tileHeatmapSelector=tr.ui.b.createSelector(this,'tileHeatmapType','layerView.tileHeatmapType',TILE_HEATMAP_TYPE.NONE,[{label:'None',value:TILE_HEATMAP_TYPE.NONE},{label:'Scheduled Priority',value:TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY},{label:'Is using GPU memory',value:TILE_HEATMAP_TYPE.USING_GPU_MEMORY}]);Polymer.dom(this.controls_).appendChild(tileHeatmapSelector);const showOtherLayersCheckbox=tr.ui.b.createCheckBox(this,'showOtherLayers','layerView.showOtherLayers',true,'Other layers/passes');showOtherLayersCheckbox.title='When checked, show all layers, selected or not.';Polymer.dom(this.controls_).appendChild(showOtherLayersCheckbox);const showInvalidationsCheckbox=tr.ui.b.createCheckBox(this,'showInvalidations','layerView.showInvalidations',true,'Invalidations');showInvalidationsCheckbox.title='When checked, compositing invalidations are highlighted in red';Polymer.dom(this.controls_).appendChild(showInvalidationsCheckbox);const showUnrecordedRegionCheckbox=tr.ui.b.createCheckBox(this,'showUnrecordedRegion','layerView.showUnrecordedRegion',true,'Unrecorded area');showUnrecordedRegionCheckbox.title='When checked, unrecorded areas are highlighted in yellow';Polymer.dom(this.controls_).appendChild(showUnrecordedRegionCheckbox);const showBottlenecksCheckbox=tr.ui.b.createCheckBox(this,'showBottlenecks','layerView.showBottlenecks',true,'Bottlenecks');showBottlenecksCheckbox.title='When checked, scroll bottlenecks are highlighted';Polymer.dom(this.controls_).appendChild(showBottlenecksCheckbox);const showLayoutRectsCheckbox=tr.ui.b.createCheckBox(this,'showLayoutRects','layerView.showLayoutRects',false,'Layout rects');showLayoutRectsCheckbox.title='When checked, shows rects for regions where layout happened';Polymer.dom(this.controls_).appendChild(showLayoutRectsCheckbox);const showContentsCheckbox=tr.ui.b.createCheckBox(this,'showContents','layerView.showContents',true,'Contents');showContentsCheckbox.title='When checked, show the rendered contents inside the layer outlines';Polymer.dom(this.controls_).appendChild(showContentsCheckbox);const showAnimationBoundsCheckbox=tr.ui.b.createCheckBox(this,'showAnimationBounds','layerView.showAnimationBounds',false,'Animation Bounds');showAnimationBoundsCheckbox.title='When checked, show a border around'+' a layer showing the extent of its animation.';Polymer.dom(this.controls_).appendChild(showAnimationBoundsCheckbox);const showInputEventsCheckbox=tr.ui.b.createCheckBox(this,'showInputEvents','layerView.showInputEvents',true,'Input events');showInputEventsCheckbox.title='When checked, input events are '+'displayed as circles.';Polymer.dom(this.controls_).appendChild(showInputEventsCheckbox);this.whatRasterizedLink_=document.createElement('tr-ui-a-analysis-link');this.whatRasterizedLink_.style.position='absolute';this.whatRasterizedLink_.style.bottom='15px';this.whatRasterizedLink_.style.left='10px';this.whatRasterizedLink_.selection=this.getWhatRasterizedEventSet_.bind(this);Polymer.dom(this.quadStackView_).appendChild(this.whatRasterizedLink_);},get layerTreeImpl(){return this.layerTreeImpl_;},set isRenderPassQuads(newValue){this.isRenderPassQuads_=newValue;},set layerTreeImpl(layerTreeImpl){if(this.layerTreeImpl_===layerTreeImpl)return;this.layerTreeImpl_=layerTreeImpl;this.selection=undefined;},get extraHighlightsByLayerId(){return this.extraHighlightsByLayerId_;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.extraHighlightsByLayerId_=extraHighlightsByLayerId;this.scheduleUpdateContents_();},get showOtherLayers(){return this.showOtherLayers_;},set showOtherLayers(show){this.showOtherLayers_=show;this.updateContents_();},get showAnimationBounds(){return this.showAnimationBounds_;},set showAnimationBounds(show){this.showAnimationBounds_=show;this.updateContents_();},get showInputEvents(){return this.showInputEvents_;},set showInputEvents(show){this.showInputEvents_=show;this.updateContents_();},get showContents(){return this.showContents_;},set showContents(show){this.showContents_=show;this.updateContents_();},get showInvalidations(){return this.showInvalidations_;},set showInvalidations(show){this.showInvalidations_=show;this.updateContents_();},get showUnrecordedRegion(){return this.showUnrecordedRegion_;},set showUnrecordedRegion(show){this.showUnrecordedRegion_=show;this.updateContents_();},get showBottlenecks(){return this.showBottlenecks_;},set showBottlenecks(show){this.showBottlenecks_=show;this.updateContents_();},get showLayoutRects(){return this.showLayoutRects_;},set showLayoutRects(show){this.showLayoutRects_=show;this.updateContents_();},get howToShowTiles(){return this.howToShowTiles_;},set howToShowTiles(val){if(val!=='none'&&val!=='coverage'&&isNaN(parseFloat(val))){throw new Error('howToShowTiles requires "none" or "coverage" or a number');}
+this.howToShowTiles_=val;this.updateContents_();},get tileHeatmapType(){return this.tileHeatmapType_;},set tileHeatmapType(val){this.tileHeatmapType_=val;this.updateContents_();},get selection(){return this.selection_;},set selection(selection){if(this.selection===selection)return;this.selection_=selection;tr.b.dispatchSimpleEvent(this,'selection-change');this.updateContents_();},regenerateContent(){this.updateTilesSelector_();this.updateContents_();},loadDataForImageElement_(image,callback){const imageContent=window.getComputedStyle(image).backgroundImage;if(!imageContent){this.scheduleUpdateContents_();return;}
+image.src=tr.ui.b.extractUrlString(imageContent);image.onload=function(){const canvas=document.createElement('canvas');const ctx=canvas.getContext('2d');canvas.width=image.width;canvas.height=image.height;ctx.drawImage(image,0,0);const imageData=ctx.getImageData(0,0,canvas.width,canvas.height);callback(imageData);};},onQuadStackViewSelectionChange_(e){const selectableQuads=e.quads.filter(function(q){return q.selectionToSetIfClicked!==undefined;});if(selectableQuads.length===0){this.selection=undefined;return;}
+selectableQuads.sort(function(x,y){const z=x.stackingGroupId-y.stackingGroupId;if(z!==0)return z;return x.selectionToSetIfClicked.specicifity-
+y.selectionToSetIfClicked.specicifity;});const quadToSelect=selectableQuads[selectableQuads.length-1];this.selection=quadToSelect.selectionToSetIfClicked;},scheduleUpdateContents_(){if(this.updateContentsPending_)return;this.updateContentsPending_=true;tr.b.requestAnimationFrameInThisFrameIfPossible(this.updateContents_,this);},updateContents_(){if(!this.layerTreeImpl_){this.quadStackView_.headerText='No tree';this.quadStackView_.quads=[];return;}
+const status=this.computePictureLoadingStatus_();if(!status.picturesComplete)return;const lthi=this.layerTreeImpl_.layerTreeHostImpl;const lthiInstance=lthi.objectInstance;const worldViewportRect=tr.b.math.Rect.fromXYWH(0,0,lthi.deviceViewportSize.width,lthi.deviceViewportSize.height);this.quadStackView_.deviceRect=worldViewportRect;if(this.isRenderPassQuads_){this.quadStackView_.quads=this.generateRenderPassQuads();}else{this.quadStackView_.quads=this.generateLayerQuads();}
+this.updateWhatRasterizedLinkState_();let message='';if(lthi.tilesHaveGpuMemoryUsageInfo){const thisTreeUsageInBytes=this.layerTreeImpl_.gpuMemoryUsageInBytes;const otherTreeUsageInBytes=lthi.gpuMemoryUsageInBytes-
+thisTreeUsageInBytes;message+=tr.b.convertUnit(thisTreeUsageInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB on this tree';if(otherTreeUsageInBytes){message+=', '+
+tr.b.convertUnit(otherTreeUsageInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB on the other tree';}}else{if(this.layerTreeImpl_){const thisTreeUsageInBytes=this.layerTreeImpl_.gpuMemoryUsageInBytes;message+=tr.b.convertUnit(thisTreeUsageInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB on this tree';if(this.layerTreeImpl_.otherTree){message+=', ??? MiB on other tree. ';}}}
+if(lthi.args.tileManagerBasicState){const tmgs=lthi.args.tileManagerBasicState.globalState;message+=' (softMax='+
+tr.b.convertUnit(tmgs.softMemoryLimitInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB, hardMax='+
+tr.b.convertUnit(tmgs.hardMemoryLimitInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB, '+
+tmgs.memoryLimitPolicy+')';}else{const thread=lthi.snapshottedOnThread;const didManageTilesSlices=thread.sliceGroup.slices.filter(s=>{if(s.category!=='tr.e.cc')return false;if(s.title!=='DidManage')return false;if(s.end>lthi.ts)return false;return true;});didManageTilesSlices.sort(function(x,y){return x.end-y.end;});if(didManageTilesSlices.length>0){const newest=didManageTilesSlices[didManageTilesSlices.length-1];const tmgs=newest.args.state.global_state;message+=' (softMax='+
+tr.b.convertUnit(tmgs.softMemoryLimitInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB, hardMax='+
+tr.b.convertUnit(tmgs.hardMemoryLimitInBytes,tr.b.UnitPrefixScale.BINARY.NONE,tr.b.UnitPrefixScale.BINARY.MEBI).toFixed(1)+' MiB, '+
+tmgs.memoryLimitPolicy+')';}}
+if(this.layerTreeImpl_.otherTree){message+=' (Another tree exists)';}
+if(message.length){this.quadStackView_.headerText=message;}else{this.quadStackView_.headerText=undefined;}
+this.updateInfoBar_(status.messages);},updateTilesSelector_(){const data=createTileRectsSelectorBaseOptions();if(this.layerTreeImpl_){const lthi=this.layerTreeImpl_.layerTreeHostImpl;const scaleNames=lthi.getContentsScaleNames();for(const scale in scaleNames){data.push({label:'Scale '+scale+' ('+scaleNames[scale]+')',value:scale});}}
+const newSelector=tr.ui.b.createSelector(this,'howToShowTiles','layerView.howToShowTiles','none',data);this.controls_.replaceChild(newSelector,this.tileRectsSelector_);this.tileRectsSelector_=newSelector;},computePictureLoadingStatus_(){const layers=this.layers;const status={messages:[],picturesComplete:true};if(this.showContents){let hasPendingRasterizeImage=false;let firstPictureError=undefined;let hasMissingLayerRect=false;let hasUnresolvedPictureRef=false;for(let i=0;i<layers.length;i++){const layer=layers[i];for(let ir=0;ir<layer.pictures.length;++ir){const picture=layer.pictures[ir];if(picture.idRef){hasUnresolvedPictureRef=true;continue;}
+if(!picture.layerRect){hasMissingLayerRect=true;continue;}
+const pictureAsImageData=this.pictureAsImageData_[picture.guid];if(!pictureAsImageData){hasPendingRasterizeImage=true;this.pictureAsImageData_[picture.guid]=tr.e.cc.PictureAsImageData.Pending(this);picture.rasterize({stopIndex:undefined},function(pictureImageData){const picture_=pictureImageData.picture;this.pictureAsImageData_[picture_.guid]=pictureImageData;this.scheduleUpdateContents_();}.bind(this));continue;}
+if(pictureAsImageData.isPending()){hasPendingRasterizeImage=true;continue;}
+if(pictureAsImageData.error){if(!firstPictureError){firstPictureError=pictureAsImageData.error;}
+break;}}}
+if(hasPendingRasterizeImage){status.picturesComplete=false;}else{if(hasUnresolvedPictureRef){status.messages.push({header:'Missing picture',details:'Your trace didn\'t have pictures for every layer. '+'Old chrome versions had this problem'});}
+if(hasMissingLayerRect){status.messages.push({header:'Missing layer rect',details:'Your trace may be corrupt or from a very old '+'Chrome revision.'});}
+if(firstPictureError){status.messages.push({header:'Cannot rasterize',details:firstPictureError});}}}
+if(this.showInputEvents&&this.layerTreeImpl.tracedInputLatencies&&this.inputEventImageData_===undefined){const image=Polymer.dom(this).querySelector('#input-event');if(!image.src){this.loadDataForImageElement_(image,function(imageData){this.inputEventImageData_=imageData;this.updateContentsPending_=false;this.scheduleUpdateContents_();}.bind(this));}
+status.picturesComplete=false;}
+return status;},get selectedRenderPass(){if(this.selection){return this.selection.renderPass_;}},get selectedLayer(){if(this.selection){const selectedLayerId=this.selection.associatedLayerId;return this.layerTreeImpl_.findLayerWithId(selectedLayerId);}},get renderPasses(){let renderPasses=this.layerTreeImpl.layerTreeHostImpl.args.frame.renderPasses;if(!this.showOtherLayers){const selectedRenderPass=this.selectedRenderPass;if(selectedRenderPass){renderPasses=[selectedRenderPass];}}
+return renderPasses;},get layers(){let layers=this.layerTreeImpl.renderSurfaceLayerList;if(!this.showOtherLayers){const selectedLayer=this.selectedLayer;if(selectedLayer){layers=[selectedLayer];}}
+return layers;},appendImageQuads_(quads,layer,layerQuad){for(let ir=0;ir<layer.pictures.length;++ir){const picture=layer.pictures[ir];if(!picture.layerRect)continue;const unitRect=picture.layerRect.asUVRectInside(layer.bounds);const iq=layerQuad.projectUnitRect(unitRect);const pictureData=this.pictureAsImageData_[picture.guid];if(this.showContents&&pictureData&&pictureData.imageData){iq.imageData=pictureData.imageData;iq.borderColor='rgba(0,0,0,0)';}else{iq.imageData=undefined;}
+iq.stackingGroupId=layerQuad.stackingGroupId;quads.push(iq);}},appendAnimationQuads_(quads,layer,layerQuad){if(!layer.animationBoundsRect)return;const rect=layer.animationBoundsRect;const abq=tr.b.math.Quad.fromRect(rect);abq.backgroundColor='rgba(164,191,48,0.5)';abq.borderColor='rgba(205,255,0,0.75)';abq.borderWidth=3.0;abq.stackingGroupId=layerQuad.stackingGroupId;abq.selectionToSetIfClicked=new cc.AnimationRectSelection(layer,rect);quads.push(abq);},appendInvalidationQuads_(quads,layer,layerQuad){if(layer.layerTreeImpl.hasSourceFrameBeenDrawnBefore)return;for(const rect of layer.invalidation.rects){const unitRect=rect.asUVRectInside(layer.bounds);const iq=layerQuad.projectUnitRect(unitRect);iq.backgroundColor='rgba(0, 255, 0, 0.1)';if(rect.reason==='appeared'){iq.backgroundColor='rgba(0, 255, 128, 0.1)';}
+iq.borderColor='rgba(0, 255, 0, 1)';iq.stackingGroupId=layerQuad.stackingGroupId;let message='Invalidation rect';if(rect.reason){message+=' ('+rect.reason+')';}
+if(rect.client){message+=' for '+rect.client;}
+iq.selectionToSetIfClicked=new cc.LayerRectSelection(layer,message,rect,rect);quads.push(iq);}},appendUnrecordedRegionQuads_(quads,layer,layerQuad){for(let ir=0;ir<layer.unrecordedRegion.rects.length;ir++){const rect=layer.unrecordedRegion.rects[ir];const unitRect=rect.asUVRectInside(layer.bounds);const iq=layerQuad.projectUnitRect(unitRect);iq.backgroundColor='rgba(240, 230, 140, 0.3)';iq.borderColor='rgba(240, 230, 140, 1)';iq.stackingGroupId=layerQuad.stackingGroupId;iq.selectionToSetIfClicked=new cc.LayerRectSelection(layer,'Unrecorded area',rect,rect);quads.push(iq);}},appendBottleneckQuads_(quads,layer,layerQuad,stackingGroupId){function processRegion(region,label,borderColor){const backgroundColor=borderColor.clone();backgroundColor.a=0.4*(borderColor.a||1.0);if(!region||!region.rects)return;for(let ir=0;ir<region.rects.length;ir++){const rect=region.rects[ir];const unitRect=rect.asUVRectInside(layer.bounds);const iq=layerQuad.projectUnitRect(unitRect);iq.backgroundColor=backgroundColor.toString();iq.borderColor=borderColor.toString();iq.borderWidth=4.0;iq.stackingGroupId=stackingGroupId;iq.selectionToSetIfClicked=new cc.LayerRectSelection(layer,label,rect,rect);quads.push(iq);}}
+processRegion(layer.touchEventHandlerRegion,'Touch listener',tr.b.Color.fromString('rgb(228, 226, 27)'));processRegion(layer.wheelEventHandlerRegion,'Wheel listener',tr.b.Color.fromString('rgb(176, 205, 29)'));processRegion(layer.nonFastScrollableRegion,'Repaints on scroll',tr.b.Color.fromString('rgb(213, 134, 32)'));},appendTileCoverageRectQuads_(quads,layer,layerQuad,heatmapType){if(!layer.tileCoverageRects)return;const tiles=[];for(let ct=0;ct<layer.tileCoverageRects.length;++ct){const tile=layer.tileCoverageRects[ct].tile;if(tile!==undefined)tiles.push(tile);}
+const lthi=this.layerTreeImpl_.layerTreeHostImpl;const minMax=this.getMinMaxForHeatmap_(lthi.activeTiles,heatmapType);const heatmapResult=this.computeHeatmapColors_(tiles,minMax,heatmapType);let heatIndex=0;for(let ct=0;ct<layer.tileCoverageRects.length;++ct){let rect=layer.tileCoverageRects[ct].geometryRect;rect=rect.scale(1.0/layer.geometryContentsScale);const tile=layer.tileCoverageRects[ct].tile;const unitRect=rect.asUVRectInside(layer.bounds);const quad=layerQuad.projectUnitRect(unitRect);quad.backgroundColor='rgba(0, 0, 0, 0)';quad.stackingGroupId=layerQuad.stackingGroupId;let type=tr.e.cc.tileTypes.missing;if(tile){type=tile.getTypeForLayer(layer);quad.backgroundColor=heatmapResult[heatIndex].color;++heatIndex;}
+quad.borderColor=tr.e.cc.tileBorder[type].color;quad.borderWidth=tr.e.cc.tileBorder[type].width;let label;if(tile){label='coverageRect';}else{label='checkerboard coverageRect';}
+quad.selectionToSetIfClicked=new cc.LayerRectSelection(layer,label,rect,layer.tileCoverageRects[ct]);quads.push(quad);}},appendLayoutRectQuads_(quads,layer,layerQuad){if(!layer.layoutRects){return;}
+for(let ct=0;ct<layer.layoutRects.length;++ct){let rect=layer.layoutRects[ct].geometryRect;rect=rect.scale(1.0/layer.geometryContentsScale);const unitRect=rect.asUVRectInside(layer.bounds);const quad=layerQuad.projectUnitRect(unitRect);quad.backgroundColor='rgba(0, 0, 0, 0)';quad.stackingGroupId=layerQuad.stackingGroupId;quad.borderColor='rgba(0, 0, 200, 0.7)';quad.borderWidth=2;const label='Layout rect';quad.selectionToSetIfClicked=new cc.LayerRectSelection(layer,label,rect);quads.push(quad);}},getValueForHeatmap_(tile,heatmapType){if(heatmapType===TILE_HEATMAP_TYPE.SCHEDULED_PRIORITY){return tile.scheduledPriority===0?undefined:tile.scheduledPriority;}else if(heatmapType===TILE_HEATMAP_TYPE.USING_GPU_MEMORY){if(tile.isSolidColor)return 0.5;return tile.isUsingGpuMemory?0:1;}},getMinMaxForHeatmap_(tiles,heatmapType){const range=new tr.b.math.Range();if(heatmapType===TILE_HEATMAP_TYPE.USING_GPU_MEMORY){range.addValue(0);range.addValue(1);return range;}
+for(let i=0;i<tiles.length;++i){const value=this.getValueForHeatmap_(tiles[i],heatmapType);if(value===undefined)continue;range.addValue(value);}
+if(range.range===0){range.addValue(1);}
+return range;},computeHeatmapColors_(tiles,minMax,heatmapType){const min=minMax.min;const max=minMax.max;const color=function(value){let hue=120*(1-(value-min)/(max-min));if(hue<0)hue=0;return'hsla('+hue+', 100%, 50%, 0.5)';};const values=[];for(let i=0;i<tiles.length;++i){const tile=tiles[i];const value=this.getValueForHeatmap_(tile,heatmapType);const res={value,color:value!==undefined?color(value):undefined};values.push(res);}
+return values;},appendTilesWithScaleQuads_(quads,layer,layerQuad,scale,heatmapType){const lthi=this.layerTreeImpl_.layerTreeHostImpl;const tiles=[];for(let i=0;i<lthi.activeTiles.length;++i){const tile=lthi.activeTiles[i];if(Math.abs(tile.contentsScale-scale)>1e-6){continue;}
+if(layer.layerId!==tile.layerId)continue;tiles.push(tile);}
+const minMax=this.getMinMaxForHeatmap_(lthi.activeTiles,heatmapType);const heatmapResult=this.computeHeatmapColors_(tiles,minMax,heatmapType);for(let i=0;i<tiles.length;++i){const tile=tiles[i];const rect=tile.layerRect;if(!tile.layerRect)continue;const unitRect=rect.asUVRectInside(layer.bounds);const quad=layerQuad.projectUnitRect(unitRect);quad.backgroundColor='rgba(0, 0, 0, 0)';quad.stackingGroupId=layerQuad.stackingGroupId;const type=tile.getTypeForLayer(layer);quad.borderColor=tr.e.cc.tileBorder[type].color;quad.borderWidth=tr.e.cc.tileBorder[type].width;quad.backgroundColor=heatmapResult[i].color;const data={tileType:type};if(heatmapType!==TILE_HEATMAP_TYPE.NONE){data[heatmapType]=heatmapResult[i].value;}
+quad.selectionToSetIfClicked=new cc.TileSelection(tile,data);quads.push(quad);}},appendHighlightQuadsForLayer_(quads,layer,layerQuad,highlights){highlights.forEach(function(highlight){const rect=highlight.rect;const unitRect=rect.asUVRectInside(layer.bounds);const quad=layerQuad.projectUnitRect(unitRect);let colorId=ColorScheme.getColorIdForGeneralPurposeString(highlight.colorKey);const offset=ColorScheme.properties.brightenedOffsets[0];colorId=ColorScheme.getVariantColorId(colorId,offset);const color=ColorScheme.colors[colorId];const quadForDrawing=quad.clone();quadForDrawing.backgroundColor=color.withAlpha(0.5).toString();quadForDrawing.borderColor=color.withAlpha(1.0).darken().toString();quadForDrawing.stackingGroupId=layerQuad.stackingGroupId;quads.push(quadForDrawing);},this);},generateRenderPassQuads(){if(!this.layerTreeImpl.layerTreeHostImpl.args.frame)return[];const renderPasses=this.renderPasses;if(!renderPasses)return[];const quads=[];for(let i=0;i<renderPasses.length;++i){const quadList=renderPasses[i].quadList;for(let j=0;j<quadList.length;++j){const drawQuad=quadList[j];const quad=drawQuad.rectAsTargetSpaceQuad.clone();quad.borderColor='rgb(170, 204, 238)';quad.borderWidth=2;quad.stackingGroupId=i;quads.push(quad);}}
+return quads;},generateLayerQuads(){this.updateContentsPending_=false;const layers=this.layers;const quads=[];let nextStackingGroupId=0;const alreadyVisitedLayerIds={};let selectionHighlightsByLayerId;if(this.selection){selectionHighlightsByLayerId=this.selection.highlightsByLayerId;}else{selectionHighlightsByLayerId={};}
+const extraHighlightsByLayerId=this.extraHighlightsByLayerId||{};for(let i=1;i<=layers.length;i++){const layer=layers[layers.length-i];alreadyVisitedLayerIds[layer.layerId]=true;if(layer.objectInstance.name==='cc::NinePatchLayerImpl'){continue;}
+const layerQuad=layer.layerQuad.clone();if(layer.usingGpuRasterization){const pixelRatio=window.devicePixelRatio||1;layerQuad.borderWidth=2.0*pixelRatio;layerQuad.borderColor='rgba(154,205,50,0.75)';}else{layerQuad.borderColor='rgba(0,0,0,0.75)';}
+layerQuad.stackingGroupId=nextStackingGroupId++;layerQuad.selectionToSetIfClicked=new cc.LayerSelection(layer);layerQuad.layer=layer;if(this.showOtherLayers&&this.selectedLayer===layer){layerQuad.upperBorderColor='rgb(156,189,45)';}
+if(this.showAnimationBounds){this.appendAnimationQuads_(quads,layer,layerQuad);}
+this.appendImageQuads_(quads,layer,layerQuad);quads.push(layerQuad);if(this.showInvalidations){this.appendInvalidationQuads_(quads,layer,layerQuad);}
+if(this.showUnrecordedRegion){this.appendUnrecordedRegionQuads_(quads,layer,layerQuad);}
+if(this.showBottlenecks){this.appendBottleneckQuads_(quads,layer,layerQuad,layerQuad.stackingGroupId);}
+if(this.showLayoutRects){this.appendLayoutRectQuads_(quads,layer,layerQuad);}
+if(this.howToShowTiles==='coverage'){this.appendTileCoverageRectQuads_(quads,layer,layerQuad,this.tileHeatmapType);}else if(this.howToShowTiles!=='none'){this.appendTilesWithScaleQuads_(quads,layer,layerQuad,this.howToShowTiles,this.tileHeatmapType);}
+let highlights;highlights=extraHighlightsByLayerId[layer.layerId];if(highlights){this.appendHighlightQuadsForLayer_(quads,layer,layerQuad,highlights);}
+highlights=selectionHighlightsByLayerId[layer.layerId];if(highlights){this.appendHighlightQuadsForLayer_(quads,layer,layerQuad,highlights);}}
+this.layerTreeImpl.iterLayers(function(layer,depth,isMask,isReplica){if(!this.showOtherLayers&&this.selectedLayer!==layer)return;if(alreadyVisitedLayerIds[layer.layerId])return;const layerQuad=layer.layerQuad;const stackingGroupId=nextStackingGroupId++;if(this.showBottlenecks){this.appendBottleneckQuads_(quads,layer,layerQuad,stackingGroupId);}},this);const tracedInputLatencies=this.layerTreeImpl.tracedInputLatencies;if(this.showInputEvents&&tracedInputLatencies){for(let i=0;i<tracedInputLatencies.length;i++){const coordinatesArray=tracedInputLatencies[i].args.data.coordinates;for(let j=0;j<coordinatesArray.length;j++){const inputQuad=tr.b.math.Quad.fromXYWH(coordinatesArray[j].x-25,coordinatesArray[j].y-25,50,50);inputQuad.borderColor='rgba(0, 0, 0, 0)';inputQuad.imageData=this.inputEventImageData_;quads.push(inputQuad);}}}
+return quads;},updateInfoBar_(infoBarMessages){if(infoBarMessages.length){this.infoBar_.removeAllButtons();this.infoBar_.message='Some problems were encountered...';this.infoBar_.addButton('More info...',function(e){const overlay=new tr.ui.b.Overlay();Polymer.dom(overlay).textContent='';infoBarMessages.forEach(function(message){const title=document.createElement('h3');Polymer.dom(title).textContent=message.header;const details=document.createElement('div');Polymer.dom(details).textContent=message.details;Polymer.dom(overlay).appendChild(title);Polymer.dom(overlay).appendChild(details);});overlay.visible=true;e.stopPropagation();return false;});this.infoBar_.visible=true;}else{this.infoBar_.removeAllButtons();this.infoBar_.message='';this.infoBar_.visible=false;}},getWhatRasterized_(){const lthi=this.layerTreeImpl_.layerTreeHostImpl;const renderProcess=lthi.objectInstance.parent;const tasks=[];for(const event of renderProcess.getDescendantEvents()){if(!(event instanceof tr.model.Slice))continue;const tile=tr.e.cc.getTileFromRasterTaskSlice(event);if(tile===undefined)continue;if(tile.containingSnapshot===lthi){tasks.push(event);}}
+return tasks;},updateWhatRasterizedLinkState_(){const tasks=this.getWhatRasterized_();if(tasks.length){Polymer.dom(this.whatRasterizedLink_).textContent=tasks.length+' raster tasks';this.whatRasterizedLink_.style.display='';}else{Polymer.dom(this.whatRasterizedLink_).textContent='';this.whatRasterizedLink_.style.display='none';}},getWhatRasterizedEventSet_(){return new tr.model.EventSet(this.getWhatRasterized_());}};return{LayerTreeQuadStackView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const constants=tr.e.cc.constants;const LayerView=tr.ui.b.define('tr-ui-e-chrome-cc-layer-view');LayerView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexDirection='column';this.style.display='flex';this.layerTreeQuadStackView_=new tr.ui.e.chrome.cc.LayerTreeQuadStackView();this.dragBar_=document.createElement('tr-ui-b-drag-handle');this.analysisEl_=document.createElement('tr-ui-e-chrome-cc-layer-view-analysis');this.analysisEl_.style.flexGrow=0;this.analysisEl_.style.flexShrink=0;this.analysisEl_.style.flexBasis='auto';this.analysisEl_.style.height='150px';this.analysisEl_.style.overflow='auto';this.analysisEl_.addEventListener('requestSelectionChange',this.onRequestSelectionChangeFromAnalysisEl_.bind(this));this.dragBar_.target=this.analysisEl_;Polymer.dom(this).appendChild(this.layerTreeQuadStackView_);Polymer.dom(this).appendChild(this.dragBar_);Polymer.dom(this).appendChild(this.analysisEl_);this.layerTreeQuadStackView_.addEventListener('selection-change',function(){this.layerTreeQuadStackViewSelectionChanged_();}.bind(this));this.layerTreeQuadStackViewSelectionChanged_();},get layerTreeImpl(){return this.layerTreeQuadStackView_.layerTreeImpl;},set layerTreeImpl(newValue){return this.layerTreeQuadStackView_.layerTreeImpl=newValue;},set isRenderPassQuads(newValue){return this.layerTreeQuadStackView_.isRenderPassQuads=newValue;},get selection(){return this.layerTreeQuadStackView_.selection;},set selection(newValue){this.layerTreeQuadStackView_.selection=newValue;},regenerateContent(){this.layerTreeQuadStackView_.regenerateContent();},layerTreeQuadStackViewSelectionChanged_(){const selection=this.layerTreeQuadStackView_.selection;if(selection){this.dragBar_.style.display='';this.analysisEl_.style.display='';Polymer.dom(this.analysisEl_).textContent='';const layer=selection.layer;if(tr.e.cc.PictureSnapshot.CanDebugPicture()&&layer&&layer.args&&layer.args.pictures&&layer.args.pictures.length){Polymer.dom(this.analysisEl_).appendChild(this.createPictureBtn_(layer.args.pictures));}
+const analysis=selection.createAnalysis();Polymer.dom(this.analysisEl_).appendChild(analysis);for(const child of this.analysisEl_.children){child.style.userSelect='text';}}else{this.dragBar_.style.display='none';this.analysisEl_.style.display='none';const analysis=Polymer.dom(this.analysisEl_).firstChild;if(analysis){Polymer.dom(this.analysisEl_).removeChild(analysis);}
+this.layerTreeQuadStackView_.style.height=window.getComputedStyle(this).height;}
+tr.b.dispatchSimpleEvent(this,'selection-change');},createPictureBtn_(pictures){if(!(pictures instanceof Array)){pictures=[pictures];}
+const link=document.createElement('tr-ui-a-analysis-link');link.selection=function(){const layeredPicture=new tr.e.cc.LayeredPicture(pictures);const snapshot=new tr.e.cc.PictureSnapshot(layeredPicture);snapshot.picture=layeredPicture;const selection=new tr.model.EventSet();selection.push(snapshot);return selection;};Polymer.dom(link).textContent='View in Picture Debugger';return link;},onRequestSelectionChangeFromAnalysisEl_(e){if(!(e.selection instanceof tr.ui.e.chrome.cc.Selection)){return;}
+e.stopPropagation();this.selection=e.selection;},get extraHighlightsByLayerId(){return this.layerTreeQuadStackView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerTreeQuadStackView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};return{LayerView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const LayerTreeHostImplSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-layer-tree-host-impl-snapshot-view',tr.ui.analysis.ObjectSnapshotView);LayerTreeHostImplSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-lthi-s-view');this.style.display='flex';this.style.flexDirection='row';this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.minWidth=0;this.selection_=undefined;this.layerPicker_=new tr.ui.e.chrome.cc.LayerPicker();this.layerPicker_.style.flexGrow=0;this.layerPicker_.style.flexShrink=0;this.layerPicker_.style.flexBasis='auto';this.layerPicker_.style.minWidth='200px';this.layerPicker_.addEventListener('selection-change',this.onLayerPickerSelectionChanged_.bind(this));this.layerView_=new tr.ui.e.chrome.cc.LayerView();this.layerView_.addEventListener('selection-change',this.onLayerViewSelectionChanged_.bind(this));this.layerView_.style.flexGrow=1;this.layerView_.style.flexShrink=1;this.layerView_.style.flexBasis='auto';this.layerView_.style.minWidth=0;this.dragHandle_=document.createElement('tr-ui-b-drag-handle');this.dragHandle_.style.flexGrow=0;this.dragHandle_.style.flexShrink=0;this.dragHandle_.style.flexBasis='auto';this.dragHandle_.horizontal=false;this.dragHandle_.target=this.layerPicker_;Polymer.dom(this).appendChild(this.layerPicker_);Polymer.dom(this).appendChild(this.dragHandle_);Polymer.dom(this).appendChild(this.layerView_);this.onLayerViewSelectionChanged_();this.onLayerPickerSelectionChanged_();},get objectSnapshot(){return this.objectSnapshot_;},set objectSnapshot(objectSnapshot){this.objectSnapshot_=objectSnapshot;const lthi=this.objectSnapshot;let layerTreeImpl;if(lthi){layerTreeImpl=lthi.getTree(this.layerPicker_.whichTree);}
+this.layerPicker_.lthiSnapshot=lthi;this.layerView_.layerTreeImpl=layerTreeImpl;this.layerView_.regenerateContent();if(!this.selection_)return;this.selection=this.selection_.findEquivalent(lthi);},get selection(){return this.selection_;},set selection(selection){if(this.selection_===selection)return;this.selection_=selection;this.layerPicker_.selection=selection;this.layerView_.selection=selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerPickerSelectionChanged_(){this.selection_=this.layerPicker_.selection;this.layerView_.selection=this.selection;this.layerView_.layerTreeImpl=this.layerPicker_.layerTreeImpl;this.layerView_.isRenderPassQuads=this.layerPicker_.isRenderPassQuads;this.layerView_.regenerateContent();tr.b.dispatchSimpleEvent(this,'cc-selection-change');},onLayerViewSelectionChanged_(){this.selection_=this.layerView_.selection;this.layerPicker_.selection=this.selection;tr.b.dispatchSimpleEvent(this,'cc-selection-change');},get extraHighlightsByLayerId(){return this.layerView_.extraHighlightsByLayerId;},set extraHighlightsByLayerId(extraHighlightsByLayerId){this.layerView_.extraHighlightsByLayerId=extraHighlightsByLayerId;}};tr.ui.analysis.ObjectSnapshotView.register(LayerTreeHostImplSnapshotView,{typeName:'cc::LayerTreeHostImpl'});return{LayerTreeHostImplSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const OPS_TIMING_ITERATIONS=3;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=40;const AXIS_PADDING_LEFT=60;const AXIS_PADDING_RIGHT=35;const AXIS_PADDING_TOP=25;const AXIS_PADDING_BOTTOM=45;const AXIS_LABEL_PADDING=5;const AXIS_TICK_SIZE=10;const LABEL_PADDING=5;const LABEL_INTERLEAVE_OFFSET=15;const BAR_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartSummaryView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-summary-view');PictureOpsChartSummaryView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.flexGrow=0;this.style.flexShrink=0;this.style.flexBasis='auto';this.style.fontSize=0;this.style.margin=0;this.style.minHeight='200px';this.style.minWidth='200px';this.style.overflow='hidden';this.style.padding=0;this.picture_=undefined;this.pictureDataProcessed_=false;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.opsTimingData_=[];this.chartWidth_=0;this.chartHeight_=0;this.requiresRedraw_=true;this.currentBarMouseOverTarget_=null;this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}},get requiresRedraw(){return this.requiresRedraw_;},set requiresRedraw(requiresRedraw){this.requiresRedraw_=requiresRedraw;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureDataProcessed_=false;if(Polymer.dom(this).classList.contains('hidden'))return;this.processPictureData_();this.requiresRedraw=true;this.updateChartContents();},hide(){Polymer.dom(this).classList.add('hidden');this.style.display='none';},show(){Polymer.dom(this).classList.remove('hidden');this.style.display='';if(!this.pictureDataProcessed_){this.processPictureData_();}
+this.requiresRedraw=true;this.updateChartContents();},onMouseMove_(e){const lastBarMouseOverTarget=this.currentBarMouseOverTarget_;this.currentBarMouseOverTarget_=null;const x=e.offsetX;const y=e.offsetY;const chartLeft=CHART_PADDING_LEFT;const chartRight=this.chartWidth_-CHART_PADDING_RIGHT;const chartTop=AXIS_PADDING_TOP;const chartBottom=this.chartHeight_-AXIS_PADDING_BOTTOM;const chartInnerWidth=chartRight-chartLeft;if(x>chartLeft&&x<chartRight&&y>chartTop&&y<chartBottom){this.currentBarMouseOverTarget_=Math.floor((x-chartLeft)/chartInnerWidth*this.opsTimingData_.length);this.currentBarMouseOverTarget_=tr.b.math.clamp(this.currentBarMouseOverTarget_,0,this.opsTimingData_.length-1);}
+if(this.currentBarMouseOverTarget_===lastBarMouseOverTarget)return;this.drawChartContents_();},onResize_(){this.requiresRedraw=true;this.updateChartContents();},updateChartContents(){if(this.requiresRedraw){this.updateChartDimensions_();}
+this.drawChartContents_();},updateChartDimensions_(){this.chartWidth_=this.offsetWidth;this.chartHeight_=this.offsetHeight;this.chart_.width=this.chartWidth_*this.chartScale_;this.chart_.height=this.chartHeight_*this.chartScale_;this.chart_.style.width=this.chartWidth_+'px';this.chart_.style.height=this.chartHeight_+'px';this.chartCtx_.scale(this.chartScale_,this.chartScale_);},processPictureData_(){this.resetOpsTimingData_();this.pictureDataProcessed_=true;if(!this.picture_)return;let ops=this.picture_.getOps();if(!ops)return;ops=this.picture_.tagOpsWithTimings(ops);if(ops[0].cmd_time===undefined)return;this.collapseOpsToTimingBuckets_(ops);},drawChartContents_(){this.clearChartContents_();if(this.opsTimingData_.length===0){this.showNoTimingDataMessage_();return;}
+this.drawChartAxes_();this.drawBars_();this.drawLineAtBottomOfChart_();if(this.currentBarMouseOverTarget_===null)return;this.drawTooltip_();},drawLineAtBottomOfChart_(){this.chartCtx_.strokeStyle='#AAA';this.chartCtx_.moveTo(0,this.chartHeight_-0.5);this.chartCtx_.lineTo(this.chartWidth_,this.chartHeight_-0.5);this.chartCtx_.stroke();},drawTooltip_(){const tooltipData=this.opsTimingData_[this.currentBarMouseOverTarget_];const tooltipTitle=tooltipData.cmd_string;const tooltipTime=tooltipData.cmd_time.toFixed(4);const tooltipWidth=110;const tooltipHeight=40;const chartInnerWidth=this.chartWidth_-CHART_PADDING_RIGHT-
+CHART_PADDING_LEFT;const barWidth=chartInnerWidth/this.opsTimingData_.length;const tooltipOffset=Math.round((tooltipWidth-barWidth)*0.5);const left=CHART_PADDING_LEFT+this.currentBarMouseOverTarget_*barWidth-tooltipOffset;const top=Math.round((this.chartHeight_-tooltipHeight)*0.5);this.chartCtx_.save();this.chartCtx_.shadowOffsetX=0;this.chartCtx_.shadowOffsetY=5;this.chartCtx_.shadowBlur=4;this.chartCtx_.shadowColor='rgba(0,0,0,0.4)';this.chartCtx_.strokeStyle='#888';this.chartCtx_.fillStyle='#EEE';this.chartCtx_.fillRect(left,top,tooltipWidth,tooltipHeight);this.chartCtx_.shadowColor='transparent';this.chartCtx_.translate(0.5,0.5);this.chartCtx_.strokeRect(left,top,tooltipWidth,tooltipHeight);this.chartCtx_.restore();this.chartCtx_.fillStyle='#222';this.chartCtx_.textBaseline='top';this.chartCtx_.font='800 12px Arial';this.chartCtx_.fillText(tooltipTitle,left+8,top+8);this.chartCtx_.fillStyle='#555';this.chartCtx_.textBaseline='top';this.chartCtx_.font='400 italic 10px Arial';this.chartCtx_.fillText('Total: '+tooltipTime+'ms',left+8,top+22);},drawBars_(){const len=this.opsTimingData_.length;const max=this.opsTimingData_[0].cmd_time;const min=this.opsTimingData_[len-1].cmd_time;const width=this.chartWidth_-CHART_PADDING_LEFT-CHART_PADDING_RIGHT;const height=this.chartHeight_-AXIS_PADDING_TOP-AXIS_PADDING_BOTTOM;const barWidth=Math.floor(width/len);let opData;let opTiming;let opHeight;let opLabel;let barLeft;for(let b=0;b<len;b++){opData=this.opsTimingData_[b];opTiming=opData.cmd_time/max;opHeight=Math.round(Math.max(1,opTiming*height));opLabel=opData.cmd_string;barLeft=CHART_PADDING_LEFT+b*barWidth;this.chartCtx_.fillStyle=this.getOpColor_(opLabel);this.chartCtx_.fillRect(barLeft+BAR_PADDING,AXIS_PADDING_TOP+
+height-opHeight,barWidth-2*BAR_PADDING,opHeight);}},getOpColor_(opName){const characters=opName.split('');const hue=characters.reduce(this.reduceNameToHue,0)%360;return'hsl('+hue+', 30%, 50%)';},reduceNameToHue(previousValue,currentValue,index,array){return Math.round(previousValue+currentValue.charCodeAt(0)*HUE_CHAR_CODE_ADJUSTMENT);},drawChartAxes_(){const len=this.opsTimingData_.length;const max=this.opsTimingData_[0].cmd_time;const min=this.opsTimingData_[len-1].cmd_time;const width=this.chartWidth_-AXIS_PADDING_LEFT-AXIS_PADDING_RIGHT;const height=this.chartHeight_-AXIS_PADDING_TOP-AXIS_PADDING_BOTTOM;const totalBarWidth=this.chartWidth_-CHART_PADDING_LEFT-
+CHART_PADDING_RIGHT;const barWidth=Math.floor(totalBarWidth/len);const tickYInterval=height/(VERTICAL_TICKS-1);let tickYPosition=0;const tickValInterval=(max-min)/(VERTICAL_TICKS-1);let tickVal=0;this.chartCtx_.fillStyle='#333';this.chartCtx_.strokeStyle='#777';this.chartCtx_.save();this.chartCtx_.translate(0.5,0.5);this.chartCtx_.save();this.chartCtx_.translate(AXIS_PADDING_LEFT,AXIS_PADDING_TOP);this.chartCtx_.moveTo(0,0);this.chartCtx_.lineTo(0,height);this.chartCtx_.lineTo(width,height);this.chartCtx_.font='10px Arial';this.chartCtx_.textAlign='right';this.chartCtx_.textBaseline='middle';for(let t=0;t<VERTICAL_TICKS;t++){tickYPosition=Math.round(t*tickYInterval);tickVal=(max-t*tickValInterval).toFixed(4);this.chartCtx_.moveTo(0,tickYPosition);this.chartCtx_.lineTo(-AXIS_TICK_SIZE,tickYPosition);this.chartCtx_.fillText(tickVal,-AXIS_TICK_SIZE-AXIS_LABEL_PADDING,tickYPosition);}
+this.chartCtx_.stroke();this.chartCtx_.restore();this.chartCtx_.save();this.chartCtx_.translate(CHART_PADDING_LEFT+Math.round(barWidth*0.5),AXIS_PADDING_TOP+height+LABEL_PADDING);this.chartCtx_.font='10px Arial';this.chartCtx_.textAlign='center';this.chartCtx_.textBaseline='top';let labelTickLeft;let labelTickBottom;for(let l=0;l<len;l++){labelTickLeft=Math.round(l*barWidth);labelTickBottom=l%2*LABEL_INTERLEAVE_OFFSET;this.chartCtx_.save();this.chartCtx_.moveTo(labelTickLeft,-LABEL_PADDING);this.chartCtx_.lineTo(labelTickLeft,labelTickBottom);this.chartCtx_.stroke();this.chartCtx_.restore();this.chartCtx_.fillText(this.opsTimingData_[l].cmd_string,labelTickLeft,labelTickBottom);}
+this.chartCtx_.restore();this.chartCtx_.restore();},clearChartContents_(){this.chartCtx_.clearRect(0,0,this.chartWidth_,this.chartHeight_);},showNoTimingDataMessage_(){this.chartCtx_.font='800 italic 14px Arial';this.chartCtx_.fillStyle='#333';this.chartCtx_.textAlign='center';this.chartCtx_.textBaseline='middle';this.chartCtx_.fillText('No timing data available.',this.chartWidth_*0.5,this.chartHeight_*0.5);},collapseOpsToTimingBuckets_(ops){const opsTimingDataIndexHash_={};const timingData=this.opsTimingData_;let op;let opIndex;for(let i=0;i<ops.length;i++){op=ops[i];if(op.cmd_time===undefined)continue;opIndex=opsTimingDataIndexHash_[op.cmd_string]||null;if(opIndex===null){timingData.push({cmd_time:0,cmd_string:op.cmd_string});opIndex=timingData.length-1;opsTimingDataIndexHash_[op.cmd_string]=opIndex;}
+timingData[opIndex].cmd_time+=op.cmd_time;}
+timingData.sort(this.sortTimingBucketsByOpTimeDescending_);this.collapseTimingBucketsToOther_(4);},collapseTimingBucketsToOther_(count){const timingData=this.opsTimingData_;const otherSource=timingData.splice(count,timingData.length-count);let otherDestination=null;if(!otherSource.length)return;timingData.push({cmd_time:0,cmd_string:'Other'});otherDestination=timingData[timingData.length-1];for(let i=0;i<otherSource.length;i++){otherDestination.cmd_time+=otherSource[i].cmd_time;}},sortTimingBucketsByOpTimeDescending_(a,b){return b.cmd_time-a.cmd_time;},resetOpsTimingData_(){this.opsTimingData_.length=0;}};return{PictureOpsChartSummaryView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const BAR_PADDING=1;const BAR_WIDTH=5;const CHART_PADDING_LEFT=65;const CHART_PADDING_RIGHT=30;const CHART_PADDING_BOTTOM=35;const CHART_PADDING_TOP=20;const AXIS_PADDING_LEFT=55;const AXIS_PADDING_RIGHT=30;const AXIS_PADDING_BOTTOM=35;const AXIS_PADDING_TOP=20;const AXIS_TICK_SIZE=5;const AXIS_LABEL_PADDING=5;const VERTICAL_TICKS=5;const HUE_CHAR_CODE_ADJUSTMENT=5.7;const PictureOpsChartView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-ops-chart-view');PictureOpsChartView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.style.display='block';this.style.height='180px';this.style.margin=0;this.style.padding=0;this.style.position='relative';this.picture_=undefined;this.pictureOps_=undefined;this.opCosts_=undefined;this.chartScale_=window.devicePixelRatio;this.chart_=document.createElement('canvas');this.chartCtx_=this.chart_.getContext('2d');Polymer.dom(this).appendChild(this.chart_);this.selectedOpIndex_=undefined;this.chartWidth_=0;this.chartHeight_=0;this.dimensionsHaveChanged_=true;this.currentBarMouseOverTarget_=undefined;this.ninetyFifthPercentileCost_=0;this.totalOpCost_=0;this.chart_.addEventListener('click',this.onClick_.bind(this));this.chart_.addEventListener('mousemove',this.onMouseMove_.bind(this));try{new ResizeObserver(this.onResize_.bind(this)).observe(this);}catch(e){}
+this.usePercentileScale_=false;this.usePercentileScaleCheckbox_=tr.ui.b.createCheckBox(this,'usePercentileScale','PictureOpsChartView.usePercentileScale',false,'Limit to 95%-ile');Polymer.dom(this.usePercentileScaleCheckbox_).classList.add('use-percentile-scale');this.usePercentileScaleCheckbox_.style.position='absolute';this.usePercentileScaleCheckbox_.style.left=0;this.usePercentileScaleCheckbox_.style.top=0;Polymer.dom(this).appendChild(this.usePercentileScaleCheckbox_);},get dimensionsHaveChanged(){return this.dimensionsHaveChanged_;},set dimensionsHaveChanged(dimensionsHaveChanged){this.dimensionsHaveChanged_=dimensionsHaveChanged;},get usePercentileScale(){return this.usePercentileScale_;},set usePercentileScale(usePercentileScale){this.usePercentileScale_=usePercentileScale;this.drawChartContents_();},get numOps(){return this.opCosts_.length;},get selectedOpIndex(){return this.selectedOpIndex_;},set selectedOpIndex(selectedOpIndex){if(selectedOpIndex<0)throw new Error('Invalid index');if(selectedOpIndex>=this.numOps)throw new Error('Invalid index');this.selectedOpIndex_=selectedOpIndex;},get picture(){return this.picture_;},set picture(picture){this.picture_=picture;this.pictureOps_=picture.tagOpsWithTimings(picture.getOps());this.currentBarMouseOverTarget_=undefined;this.processPictureData_();this.dimensionsHaveChanged=true;},processPictureData_(){if(this.pictureOps_===undefined)return;let totalOpCost=0;this.opCosts_=this.pictureOps_.map(function(op){totalOpCost+=op.cmd_time;return op.cmd_time;});this.opCosts_.sort();const ninetyFifthPercentileCostIndex=Math.floor(this.opCosts_.length*0.95);this.ninetyFifthPercentileCost_=this.opCosts_[ninetyFifthPercentileCostIndex];this.maxCost_=this.opCosts_[this.opCosts_.length-1];this.totalOpCost_=totalOpCost;},extractBarIndex_(e){let index=undefined;if(this.pictureOps_===undefined||this.pictureOps_.length===0){return index;}
+const x=e.offsetX;const y=e.offsetY;const totalBarWidth=(BAR_WIDTH+BAR_PADDING)*this.pictureOps_.length;const chartLeft=CHART_PADDING_LEFT;const chartTop=0;const chartBottom=this.chartHeight_-CHART_PADDING_BOTTOM;const chartRight=chartLeft+totalBarWidth;if(x<chartLeft||x>chartRight||y<chartTop||y>chartBottom){return index;}
+index=Math.floor((x-chartLeft)/totalBarWidth*this.pictureOps_.length);index=tr.b.math.clamp(index,0,this.pictureOps_.length-1);return index;},onClick_(e){const barClicked=this.extractBarIndex_(e);if(barClicked===undefined)return;if(barClicked===this.selectedOpIndex){this.selectedOpIndex=undefined;}else{this.selectedOpIndex=barClicked;}
+e.preventDefault();tr.b.dispatchSimpleEvent(this,'selection-changed',false);},onMouseMove_(e){const lastBarMouseOverTarget=this.currentBarMouseOverTarget_;this.currentBarMouseOverTarget_=this.extractBarIndex_(e);if(this.currentBarMouseOverTarget_===lastBarMouseOverTarget){return;}
+this.drawChartContents_();},onResize_(){this.dimensionsHaveChanged=true;this.updateChartContents();},scrollSelectedItemIntoViewIfNecessary(){if(this.selectedOpIndex===undefined){return;}
+const width=this.offsetWidth;const left=this.scrollLeft;const right=left+width;const targetLeft=CHART_PADDING_LEFT+
+(BAR_WIDTH+BAR_PADDING)*this.selectedOpIndex;if(targetLeft>left&&targetLeft<right){return;}
+this.scrollLeft=(targetLeft-width*0.5);},updateChartContents(){if(this.dimensionsHaveChanged){this.updateChartDimensions_();}
+this.drawChartContents_();},updateChartDimensions_(){if(!this.pictureOps_)return;let width=CHART_PADDING_LEFT+CHART_PADDING_RIGHT+
+((BAR_WIDTH+BAR_PADDING)*this.pictureOps_.length);if(width<this.offsetWidth){width=this.offsetWidth;}
+this.chartWidth_=width;this.chartHeight_=this.getBoundingClientRect().height;this.chart_.width=this.chartWidth_*this.chartScale_;this.chart_.height=this.chartHeight_*this.chartScale_;this.chart_.style.width=this.chartWidth_+'px';this.chart_.style.height=this.chartHeight_+'px';this.chartCtx_.scale(this.chartScale_,this.chartScale_);this.dimensionsHaveChanged=false;},drawChartContents_(){this.clearChartContents_();if(this.pictureOps_===undefined||this.pictureOps_.length===0||this.pictureOps_[0].cmd_time===undefined){this.showNoTimingDataMessage_();return;}
+this.drawSelection_();this.drawBars_();this.drawChartAxes_();this.drawLinesAtTickMarks_();this.drawLineAtBottomOfChart_();if(this.currentBarMouseOverTarget_===undefined){return;}
+this.drawTooltip_();},drawSelection_(){if(this.selectedOpIndex===undefined){return;}
+const width=(BAR_WIDTH+BAR_PADDING)*this.selectedOpIndex;this.chartCtx_.fillStyle='rgb(223, 235, 230)';this.chartCtx_.fillRect(CHART_PADDING_LEFT,CHART_PADDING_TOP,width,this.chartHeight_-CHART_PADDING_TOP-CHART_PADDING_BOTTOM);},drawChartAxes_(){const min=this.opCosts_[0];const max=this.opCosts_[this.opCosts_.length-1];const height=this.chartHeight_-AXIS_PADDING_TOP-AXIS_PADDING_BOTTOM;const tickYInterval=height/(VERTICAL_TICKS-1);let tickYPosition=0;const tickValInterval=(max-min)/(VERTICAL_TICKS-1);let tickVal=0;this.chartCtx_.fillStyle='#333';this.chartCtx_.strokeStyle='#777';this.chartCtx_.save();this.chartCtx_.translate(0.5,0.5);this.chartCtx_.beginPath();this.chartCtx_.moveTo(AXIS_PADDING_LEFT,AXIS_PADDING_TOP);this.chartCtx_.lineTo(AXIS_PADDING_LEFT,this.chartHeight_-
+AXIS_PADDING_BOTTOM);this.chartCtx_.lineTo(this.chartWidth_-AXIS_PADDING_RIGHT,this.chartHeight_-AXIS_PADDING_BOTTOM);this.chartCtx_.stroke();this.chartCtx_.closePath();this.chartCtx_.translate(AXIS_PADDING_LEFT,AXIS_PADDING_TOP);this.chartCtx_.font='10px Arial';this.chartCtx_.textAlign='right';this.chartCtx_.textBaseline='middle';this.chartCtx_.beginPath();for(let t=0;t<VERTICAL_TICKS;t++){tickYPosition=Math.round(t*tickYInterval);tickVal=(max-t*tickValInterval).toFixed(4);this.chartCtx_.moveTo(0,tickYPosition);this.chartCtx_.lineTo(-AXIS_TICK_SIZE,tickYPosition);this.chartCtx_.fillText(tickVal,-AXIS_TICK_SIZE-AXIS_LABEL_PADDING,tickYPosition);}
+this.chartCtx_.stroke();this.chartCtx_.closePath();this.chartCtx_.restore();},drawLinesAtTickMarks_(){const height=this.chartHeight_-AXIS_PADDING_TOP-AXIS_PADDING_BOTTOM;const width=this.chartWidth_-AXIS_PADDING_LEFT-AXIS_PADDING_RIGHT;const tickYInterval=height/(VERTICAL_TICKS-1);let tickYPosition=0;this.chartCtx_.save();this.chartCtx_.translate(AXIS_PADDING_LEFT+0.5,AXIS_PADDING_TOP+0.5);this.chartCtx_.beginPath();this.chartCtx_.strokeStyle='rgba(0,0,0,0.05)';for(let t=0;t<VERTICAL_TICKS;t++){tickYPosition=Math.round(t*tickYInterval);this.chartCtx_.moveTo(0,tickYPosition);this.chartCtx_.lineTo(width,tickYPosition);this.chartCtx_.stroke();}
+this.chartCtx_.restore();this.chartCtx_.closePath();},drawLineAtBottomOfChart_(){this.chartCtx_.strokeStyle='#AAA';this.chartCtx_.beginPath();this.chartCtx_.moveTo(0,this.chartHeight_-0.5);this.chartCtx_.lineTo(this.chartWidth_,this.chartHeight_-0.5);this.chartCtx_.stroke();this.chartCtx_.closePath();},drawTooltip_(){const tooltipData=this.pictureOps_[this.currentBarMouseOverTarget_];const tooltipTitle=tooltipData.cmd_string;const tooltipTime=tooltipData.cmd_time.toFixed(4);const toolTipTimePercentage=((tooltipData.cmd_time/this.totalOpCost_)*100).toFixed(2);const tooltipWidth=120;const tooltipHeight=40;const chartInnerWidth=this.chartWidth_-CHART_PADDING_RIGHT-
+CHART_PADDING_LEFT;const barWidth=BAR_WIDTH+BAR_PADDING;const tooltipOffset=Math.round((tooltipWidth-barWidth)*0.5);const left=CHART_PADDING_LEFT+this.currentBarMouseOverTarget_*barWidth-tooltipOffset;const top=Math.round((this.chartHeight_-tooltipHeight)*0.5);this.chartCtx_.save();this.chartCtx_.shadowOffsetX=0;this.chartCtx_.shadowOffsetY=5;this.chartCtx_.shadowBlur=4;this.chartCtx_.shadowColor='rgba(0,0,0,0.4)';this.chartCtx_.strokeStyle='#888';this.chartCtx_.fillStyle='#EEE';this.chartCtx_.fillRect(left,top,tooltipWidth,tooltipHeight);this.chartCtx_.shadowColor='transparent';this.chartCtx_.translate(0.5,0.5);this.chartCtx_.strokeRect(left,top,tooltipWidth,tooltipHeight);this.chartCtx_.restore();this.chartCtx_.fillStyle='#222';this.chartCtx_.textAlign='left';this.chartCtx_.textBaseline='top';this.chartCtx_.font='800 12px Arial';this.chartCtx_.fillText(tooltipTitle,left+8,top+8);this.chartCtx_.fillStyle='#555';this.chartCtx_.font='400 italic 10px Arial';this.chartCtx_.fillText(tooltipTime+'ms ('+
+toolTipTimePercentage+'%)',left+8,top+22);},drawBars_(){let op;let opColor=0;let opHeight=0;const opWidth=BAR_WIDTH+BAR_PADDING;let opHover=false;const bottom=this.chartHeight_-CHART_PADDING_BOTTOM;const maxHeight=this.chartHeight_-CHART_PADDING_BOTTOM-
+CHART_PADDING_TOP;let maxValue;if(this.usePercentileScale){maxValue=this.ninetyFifthPercentileCost_;}else{maxValue=this.maxCost_;}
+for(let b=0;b<this.pictureOps_.length;b++){op=this.pictureOps_[b];opHeight=Math.round((op.cmd_time/maxValue)*maxHeight);opHeight=Math.max(opHeight,1);opHover=(b===this.currentBarMouseOverTarget_);opColor=this.getOpColor_(op.cmd_string,opHover);if(b===this.selectedOpIndex){this.chartCtx_.fillStyle='#FFFF00';}else{this.chartCtx_.fillStyle=opColor;}
+this.chartCtx_.fillRect(CHART_PADDING_LEFT+b*opWidth,bottom-opHeight,BAR_WIDTH,opHeight);}},getOpColor_(opName,hover){const characters=opName.split('');const hue=characters.reduce(this.reduceNameToHue,0)%360;const saturation=30;const lightness=hover?'75%':'50%';return'hsl('+hue+', '+saturation+'%, '+lightness+'%)';},reduceNameToHue(previousValue,currentValue,index,array){return Math.round(previousValue+currentValue.charCodeAt(0)*HUE_CHAR_CODE_ADJUSTMENT);},clearChartContents_(){this.chartCtx_.clearRect(0,0,this.chartWidth_,this.chartHeight_);},showNoTimingDataMessage_(){this.chartCtx_.font='800 italic 14px Arial';this.chartCtx_.fillStyle='#333';this.chartCtx_.textAlign='center';this.chartCtx_.textBaseline='middle';this.chartCtx_.fillText('No timing data available.',this.chartWidth_*0.5,this.chartHeight_*0.5);}};return{PictureOpsChartView,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const THIS_DOC=document._currentScript.ownerDocument;const PictureDebugger=tr.ui.b.define('tr-ui-e-chrome-cc-picture-debugger');PictureDebugger.prototype={__proto__:HTMLDivElement.prototype,decorate(){const node=tr.ui.b.instantiateTemplate('#tr-ui-e-chrome-cc-picture-debugger-template',THIS_DOC);Polymer.dom(this).appendChild(node);this.style.display='flex';this.style.flexDirection='row';const title=this.querySelector('.title');title.style.fontWeight='bold';title.style.marginLeft='5px';title.style.marginRight='5px';this.pictureAsImageData_=undefined;this.showOverdraw_=false;this.zoomScaleValue_=1;this.sizeInfo_=Polymer.dom(this).querySelector('.size');this.rasterArea_=Polymer.dom(this).querySelector('raster-area');this.rasterArea_.style.backgroundColor='#ddd';this.rasterArea_.style.minHeight='100px';this.rasterArea_.style.minWidth='200px';this.rasterArea_.style.overflow='auto';this.rasterArea_.style.paddingLeft='5px';this.rasterCanvas_=Polymer.dom(this.rasterArea_).querySelector('canvas');this.rasterCtx_=this.rasterCanvas_.getContext('2d');this.filename_=Polymer.dom(this).querySelector('.filename');this.filename_.style.userSelect='text';this.filename_.style.marginLeft='5px';this.drawOpsChartSummaryView_=new tr.ui.e.chrome.cc.PictureOpsChartSummaryView();this.drawOpsChartView_=new tr.ui.e.chrome.cc.PictureOpsChartView();this.drawOpsChartView_.addEventListener('selection-changed',this.onChartBarClicked_.bind(this));this.exportButton_=Polymer.dom(this).querySelector('.export');this.exportButton_.addEventListener('click',this.onSaveAsSkPictureClicked_.bind(this));this.trackMouse_();const overdrawCheckbox=tr.ui.b.createCheckBox(this,'showOverdraw','pictureView.showOverdraw',false,'Show overdraw');const chartCheckbox=tr.ui.b.createCheckBox(this,'showSummaryChart','pictureView.showSummaryChart',false,'Show timing summary');const pictureInfo=Polymer.dom(this).querySelector('picture-info');pictureInfo.style.flexGrow=0;pictureInfo.style.flexShrink=0;pictureInfo.style.flexBasis='auto';pictureInfo.style.paddingTop='2px';Polymer.dom(pictureInfo).appendChild(overdrawCheckbox);Polymer.dom(pictureInfo).appendChild(chartCheckbox);this.drawOpsView_=new tr.ui.e.chrome.cc.PictureOpsListView();this.drawOpsView_.flexGrow=1;this.drawOpsView_.flexShrink=1;this.drawOpsView_.flexBasis='auto';this.drawOpsView_.addEventListener('selection-changed',this.onChangeDrawOps_.bind(this));const leftPanel=Polymer.dom(this).querySelector('left-panel');leftPanel.style.flexDirection='column';leftPanel.style.display='flex';leftPanel.style.flexGrow=0;leftPanel.style.flexShrink=0;leftPanel.style.flexBasis='auto';leftPanel.style.minWidth='200px';leftPanel.style.overflow='auto';Polymer.dom(leftPanel).appendChild(this.drawOpsChartSummaryView_);Polymer.dom(leftPanel).appendChild(this.drawOpsView_);const middleDragHandle=document.createElement('tr-ui-b-drag-handle');middleDragHandle.style.flexGrow=0;middleDragHandle.style.flexShrink=0;middleDragHandle.style.flexBasis='auto';middleDragHandle.horizontal=false;middleDragHandle.target=leftPanel;const rightPanel=Polymer.dom(this).querySelector('right-panel');rightPanel.style.flexGrow=1;rightPanel.style.flexShrink=1;rightPanel.style.flexBasis='auto';rightPanel.style.minWidth=0;rightPanel.style.flexDirection='column';rightPanel.style.display='flex';const chartView=Polymer.dom(rightPanel).querySelector('tr-ui-e-chrome-cc-picture-ops-chart-view');this.drawOpsChartView_.style.flexGrow=0;this.drawOpsChartView_.style.flexShrink=0;this.drawOpsChartView_.style.flexBasis='auto';this.drawOpsChartView_.style.minWidth=0;this.drawOpsChartView_.style.overflowX='auto';this.drawOpsChartView_.style.overflowY='hidden';rightPanel.replaceChild(this.drawOpsChartView_,chartView);this.infoBar_=document.createElement('tr-ui-b-info-bar');Polymer.dom(this.rasterArea_).appendChild(this.infoBar_);Polymer.dom(this).insertBefore(middleDragHandle,rightPanel);this.picture_=undefined;const hkc=document.createElement('tv-ui-b-hotkey-controller');hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',thisArg:this,keyCode:'h'.charCodeAt(0),callback(e){this.moveSelectedOpBy(-1);e.stopPropagation();}}));hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',thisArg:this,keyCode:'l'.charCodeAt(0),callback(e){this.moveSelectedOpBy(1);e.stopPropagation();}}));Polymer.dom(this).appendChild(hkc);},onSaveAsSkPictureClicked_(){const rawData=tr.b.Base64.atob(this.picture_.getBase64SkpData());const length=rawData.length;const arrayBuffer=new ArrayBuffer(length);const uint8Array=new Uint8Array(arrayBuffer);for(let c=0;c<length;c++){uint8Array[c]=rawData.charCodeAt(c);}
+const blob=new Blob([uint8Array],{type:'application/octet-binary'});const blobUrl=window.webkitURL.createObjectURL(blob);const link=document.createElementNS('http://www.w3.org/1999/xhtml','a');link.href=blobUrl;link.download=this.filename_.value;const event=document.createEvent('MouseEvents');event.initMouseEvent('click',true,false,window,0,0,0,0,0,false,false,false,false,0,null);link.dispatchEvent(event);},get picture(){return this.picture_;},set picture(picture){this.drawOpsView_.picture=picture;this.drawOpsChartView_.picture=picture;this.drawOpsChartSummaryView_.picture=picture;this.picture_=picture;this.exportButton_.disabled=!this.picture_.canSave;if(picture){const size=this.getRasterCanvasSize_();this.rasterCanvas_.width=size.width;this.rasterCanvas_.height=size.height;}
+const bounds=this.rasterArea_.getBoundingClientRect();const selectorBounds=this.mouseModeSelector_.getBoundingClientRect();this.mouseModeSelector_.pos={x:(bounds.right-selectorBounds.width-10),y:bounds.top};this.rasterize_();this.scheduleUpdateContents_();},getRasterCanvasSize_(){const style=window.getComputedStyle(this.rasterArea_);const width=Math.max(parseInt(style.width),this.picture_.layerRect.width);const height=Math.max(parseInt(style.height),this.picture_.layerRect.height);return{width,height};},scheduleUpdateContents_(){if(this.updateContentsPending_)return;this.updateContentsPending_=true;tr.b.requestAnimationFrameInThisFrameIfPossible(this.updateContents_.bind(this));},updateContents_(){this.updateContentsPending_=false;if(this.picture_){Polymer.dom(this.sizeInfo_).textContent='('+
+this.picture_.layerRect.width+' x '+
+this.picture_.layerRect.height+')';}
+this.drawOpsChartView_.updateChartContents();this.drawOpsChartView_.scrollSelectedItemIntoViewIfNecessary();if(!this.pictureAsImageData_)return;this.infoBar_.visible=false;this.infoBar_.removeAllButtons();if(this.pictureAsImageData_.error){this.infoBar_.message='Cannot rasterize...';this.infoBar_.addButton('More info...',function(e){const overlay=new tr.ui.b.Overlay();Polymer.dom(overlay).textContent=this.pictureAsImageData_.error;overlay.visible=true;e.stopPropagation();return false;}.bind(this));this.infoBar_.visible=true;}
+this.drawPicture_();},drawPicture_(){const size=this.getRasterCanvasSize_();if(size.width!==this.rasterCanvas_.width){this.rasterCanvas_.width=size.width;}
+if(size.height!==this.rasterCanvas_.height){this.rasterCanvas_.height=size.height;}
+this.rasterCtx_.clearRect(0,0,size.width,size.height);if(!this.pictureAsImageData_.imageData)return;const imgCanvas=this.pictureAsImageData_.asCanvas();const w=imgCanvas.width;const h=imgCanvas.height;this.rasterCtx_.drawImage(imgCanvas,0,0,w,h,0,0,w*this.zoomScaleValue_,h*this.zoomScaleValue_);},rasterize_(){if(this.picture_){this.picture_.rasterize({stopIndex:this.drawOpsView_.selectedOpIndex,showOverdraw:this.showOverdraw_},this.onRasterComplete_.bind(this));}},onRasterComplete_(pictureAsImageData){this.pictureAsImageData_=pictureAsImageData;this.scheduleUpdateContents_();},moveSelectedOpBy(increment){if(this.selectedOpIndex===undefined){this.selectedOpIndex=0;return;}
+this.selectedOpIndex=tr.b.math.clamp(this.selectedOpIndex+increment,0,this.numOps);},get numOps(){return this.drawOpsView_.numOps;},get selectedOpIndex(){return this.drawOpsView_.selectedOpIndex;},set selectedOpIndex(index){this.drawOpsView_.selectedOpIndex=index;this.drawOpsChartView_.selectedOpIndex=index;},onChartBarClicked_(e){this.drawOpsView_.selectedOpIndex=this.drawOpsChartView_.selectedOpIndex;},onChangeDrawOps_(e){this.rasterize_();this.scheduleUpdateContents_();this.drawOpsChartView_.selectedOpIndex=this.drawOpsView_.selectedOpIndex;},set showOverdraw(v){this.showOverdraw_=v;this.rasterize_();},set showSummaryChart(chartShouldBeVisible){if(chartShouldBeVisible){this.drawOpsChartSummaryView_.show();}else{this.drawOpsChartSummaryView_.hide();}},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.rasterArea_;Polymer.dom(this.rasterArea_).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.defaultMode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.settingsKey='pictureDebugger.mouseModeSelector';this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));},onBeginZoom_(e){this.isZooming_=true;this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);e.preventDefault();},onUpdateZoom_(e){if(!this.isZooming_)return;const currentMouseViewPos=this.extractRelativeMousePosition_(e);this.zoomScaleValue_+=((this.lastMouseViewPos_.y-currentMouseViewPos.y)*0.001);this.zoomScaleValue_=Math.max(this.zoomScaleValue_,0.1);this.drawPicture_();this.lastMouseViewPos_=currentMouseViewPos;},onEndZoom_(e){this.lastMouseViewPos_=undefined;this.isZooming_=false;e.preventDefault();},extractRelativeMousePosition_(e){return{x:e.clientX-this.rasterArea_.offsetLeft,y:e.clientY-this.rasterArea_.offsetTop};}};return{PictureDebugger,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const PictureSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-picture-snapshot-view',tr.ui.analysis.ObjectSnapshotView);PictureSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-picture-snapshot-view');this.style.display='flex';this.style.flexGrow=1;this.style.flexShrink=1;this.style.flexBasis='auto';this.style.minWidth=0;this.pictureDebugger_=new tr.ui.e.chrome.cc.PictureDebugger();this.pictureDebugger_.style.flexGrow=1;this.pictureDebugger_.style.flexShrink=1;this.pictureDebugger_.style.flexBasis='auto';this.pictureDebugger_.style.minWidth=0;Polymer.dom(this).appendChild(this.pictureDebugger_);},updateContents(){if(this.objectSnapshot_&&this.pictureDebugger_){this.pictureDebugger_.picture=this.objectSnapshot_;}}};tr.ui.analysis.ObjectSnapshotView.register(PictureSnapshotView,{typeNames:['cc::Picture','cc::LayeredPicture'],showInstances:false});return{PictureSnapshotView,};});'use strict';tr.exportTo('tr.e.cc',function(){const knownRasterTaskNames=['TileManager::RunRasterTask','RasterWorkerPoolTaskImpl::RunRasterOnThread','RasterWorkerPoolTaskImpl::Raster','RasterTaskImpl::Raster','cc::RasterTask','RasterTask'];const knownAnalysisTaskNames=['TileManager::RunAnalyzeTask','RasterWorkerPoolTaskImpl::RunAnalysisOnThread','RasterWorkerPoolTaskImpl::Analyze','RasterTaskImpl::Analyze','cc::AnalyzeTask','AnalyzeTask'];function getTileFromRasterTaskSlice(slice){if(!(isSliceDoingRasterization(slice)||isSliceDoingAnalysis(slice))){return undefined;}
+let tileData;if(slice.args.data){tileData=slice.args.data;}else{tileData=slice.args.tileData;}
+if(tileData===undefined)return undefined;if(tileData.tile_id)return tileData.tile_id;const tile=tileData.tileId;if(!(tile instanceof tr.e.cc.TileSnapshot)){return undefined;}
+return tileData.tileId;}
+function isSliceDoingRasterization(slice){return knownRasterTaskNames.includes(slice.title);}
+function isSliceDoingAnalysis(slice){return knownAnalysisTaskNames.includes(slice.title);}
+return{getTileFromRasterTaskSlice,isSliceDoingRasterization,isSliceDoingAnalysis};});'use strict';tr.exportTo('tr.ui.analysis',function(){const AnalysisSubView={set tabLabel(label){Polymer.dom(this).setAttribute('tab-label',label);},get tabLabel(){return this.getAttribute('tab-label');},get requiresTallView(){return false;},get relatedEventsToHighlight(){return undefined;},set selection(selection){throw new Error('Not implemented!');},get selection(){throw new Error('Not implemented!');}};const allTypeInfosByEventProto=new Map();let onlyRootTypeInfosByEventProto=undefined;let eventProtoToRootTypeInfoMap=undefined;function AnalysisSubViewTypeInfo(eventConstructor,options){if(options.multi===undefined){throw new Error('missing field: multi');}
+if(options.title===undefined){throw new Error('missing field: title');}
+this.eventConstructor=eventConstructor;this.singleTagName=undefined;this.singleTitle=undefined;this.multiTagName=undefined;this.multiTitle=undefined;this.childrenTypeInfos_=undefined;}
+AnalysisSubViewTypeInfo.prototype={get childrenTypeInfos(){return this.childrenTypeInfos_;},resetchildrenTypeInfos(){this.childrenTypeInfos_=[];}};AnalysisSubView.register=function(tagName,eventConstructor,options){let typeInfo=allTypeInfosByEventProto.get(eventConstructor.prototype);if(typeInfo===undefined){typeInfo=new AnalysisSubViewTypeInfo(eventConstructor,options);allTypeInfosByEventProto.set(typeInfo.eventConstructor.prototype,typeInfo);onlyRootTypeInfosByEventProto=undefined;}
+if(!options.multi){if(typeInfo.singleTagName!==undefined){throw new Error('SingleTagName already set');}
+typeInfo.singleTagName=tagName;typeInfo.singleTitle=options.title;}else{if(typeInfo.multiTagName!==undefined){throw new Error('MultiTagName already set');}
+typeInfo.multiTagName=tagName;typeInfo.multiTitle=options.title;}
+return typeInfo;};function rebuildRootSubViewTypeInfos(){onlyRootTypeInfosByEventProto=new Map();allTypeInfosByEventProto.forEach(function(typeInfo){typeInfo.resetchildrenTypeInfos();});allTypeInfosByEventProto.forEach(function(typeInfo,eventProto){const eventPrototype=typeInfo.eventConstructor.prototype;let lastEventProto=eventPrototype;let curEventProto=eventPrototype.__proto__;while(true){if(!allTypeInfosByEventProto.has(curEventProto)){const rootTypeInfo=allTypeInfosByEventProto.get(lastEventProto);const rootEventProto=lastEventProto;const isNew=onlyRootTypeInfosByEventProto.has(rootEventProto);onlyRootTypeInfosByEventProto.set(rootEventProto,rootTypeInfo);break;}
+lastEventProto=curEventProto;curEventProto=curEventProto.__proto__;}});allTypeInfosByEventProto.forEach(function(typeInfo,eventProto){const eventPrototype=typeInfo.eventConstructor.prototype;const parentEventProto=eventPrototype.__proto__;const parentTypeInfo=allTypeInfosByEventProto.get(parentEventProto);if(!parentTypeInfo)return;parentTypeInfo.childrenTypeInfos.push(typeInfo);});eventProtoToRootTypeInfoMap=new Map();allTypeInfosByEventProto.forEach(function(typeInfo,eventProto){const eventPrototype=typeInfo.eventConstructor.prototype;let curEventProto=eventPrototype;while(true){if(onlyRootTypeInfosByEventProto.has(curEventProto)){const rootTypeInfo=onlyRootTypeInfosByEventProto.get(curEventProto);eventProtoToRootTypeInfoMap.set(eventPrototype,rootTypeInfo);break;}
+curEventProto=curEventProto.__proto__;}});}
+function findLowestTypeInfoForEvents(thisTypeInfo,events){if(events.length===0)return thisTypeInfo;const event0=tr.b.getFirstElement(events);let candidateSubTypeInfo;for(let i=0;i<thisTypeInfo.childrenTypeInfos.length;i++){const childTypeInfo=thisTypeInfo.childrenTypeInfos[i];if(event0 instanceof childTypeInfo.eventConstructor){candidateSubTypeInfo=childTypeInfo;break;}}
+if(!candidateSubTypeInfo)return thisTypeInfo;let allMatch=true;for(const event of events){if(event instanceof candidateSubTypeInfo.eventConstructor)continue;allMatch=false;break;}
+if(!allMatch){return thisTypeInfo;}
+return findLowestTypeInfoForEvents(candidateSubTypeInfo,events);}
+const primaryEventProtoToTypeInfoMap=new Map();function getRootTypeInfoForEvent(event){const curProto=event.__proto__;const typeInfo=primaryEventProtoToTypeInfoMap.get(curProto);if(typeInfo)return typeInfo;return getRootTypeInfoForEventSlow(event);}
+function getRootTypeInfoForEventSlow(event){let typeInfo;let curProto=event.__proto__;while(true){if(curProto===Object.prototype){throw new Error('No view registered for '+event.toString());}
+typeInfo=onlyRootTypeInfosByEventProto.get(curProto);if(typeInfo){primaryEventProtoToTypeInfoMap.set(event.__proto__,typeInfo);return typeInfo;}
+curProto=curProto.__proto__;}}
+AnalysisSubView.getEventsOrganizedByTypeInfo=function(selection){if(onlyRootTypeInfosByEventProto===undefined){rebuildRootSubViewTypeInfos();}
+const eventsByRootTypeInfo=tr.b.groupIntoMap(selection,function(event){return getRootTypeInfoForEvent(event);},this,tr.model.EventSet);const eventsByLowestTypeInfo=new Map();eventsByRootTypeInfo.forEach(function(events,typeInfo){const lowestTypeInfo=findLowestTypeInfoForEvents(typeInfo,events);eventsByLowestTypeInfo.set(lowestTypeInfo,events);});return eventsByLowestTypeInfo;};return{AnalysisSubView,AnalysisSubViewTypeInfo,};});Polymer({is:'tr-ui-a-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView]});'use strict';Polymer({is:'tr-ui-a-stack-frame',ready(){this.stackFrame_=undefined;this.$.table.tableColumns=[];this.$.table.showHeader=true;},get stackFrame(){return this.stackFrame_;},set stackFrame(stackFrame){const table=this.$.table;this.stackFrame_=stackFrame;if(stackFrame===undefined){table.tableColumns=[];table.tableRows=[];table.rebuild();return;}
+let hasName=false;let hasTitle=false;table.tableRows=stackFrame.stackTrace;table.tableRows.forEach(function(row){hasName|=row.name!==undefined;hasTitle|=row.title!==undefined;});const cols=[];if(hasName){cols.push({title:'Name',value(row){return row.name;}});}
+if(hasTitle){cols.push({title:'Title',value(row){return row.title;}});}
+table.tableColumns=cols;table.rebuild();},tableForTesting(){return this.$.table;}});'use strict';Polymer({is:'tr-ui-a-single-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],properties:{isFlow:{type:Boolean,value:false}},ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){if(selection.length!==1){throw new Error('Only supports single slices');}
+this.setSelectionWithoutErrorChecks(selection);},setSelectionWithoutErrorChecks(selection){this.currentSelection_=selection;this.updateContents_();},getFlowEventRows_(event){const rows=this.getEventRowsHelper_(event);rows.splice(0,0,{name:'ID',value:event.id});function createLinkTo(slice){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.model.EventSet(slice);});Polymer.dom(linkEl).textContent=slice.userFriendlyName;return linkEl;}
+rows.push({name:'From',value:createLinkTo(event.startSlice)});rows.push({name:'To',value:createLinkTo(event.endSlice)});return rows;},getEventRowsHelper_(event){const rows=[];if(event.error){rows.push({name:'Error',value:event.error});}
+if(event.title){let title=event.title;if(tr.isExported('tr-ui-e-chrome-codesearch')){const container=document.createElement('div');container.appendChild(document.createTextNode(title));const link=document.createElement('tr-ui-e-chrome-codesearch');link.searchPhrase=title;container.appendChild(link);title=container;}
+rows.push({name:'Title',value:title});}
+if(event.category){rows.push({name:'Category',value:event.category});}
+if(event.model!==undefined){const ufc=event.model.getUserFriendlyCategoryFromEvent(event);if(ufc!==undefined){rows.push({name:'User Friendly Category',value:ufc});}}
+if(event.name){rows.push({name:'Name',value:event.name});}
+rows.push({name:'Start',value:tr.v.ui.createScalarSpan(event.start,{unit:tr.b.Unit.byName.timeStampInMs})});if(event.duration){rows.push({name:'Wall Duration',value:tr.v.ui.createScalarSpan(event.duration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+if(event.cpuDuration){rows.push({name:'CPU Duration',value:tr.v.ui.createScalarSpan(event.cpuDuration,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+if(event.subSlices!==undefined&&event.subSlices.length!==0){if(event.selfTime){rows.push({name:'Self Time',value:tr.v.ui.createScalarSpan(event.selfTime,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+if(event.cpuSelfTime){const cpuSelfTimeEl=tr.v.ui.createScalarSpan(event.cpuSelfTime,{unit:tr.b.Unit.byName.timeDurationInMs});if(event.cpuSelfTime>event.selfTime){cpuSelfTimeEl.warning=' Note that CPU Self Time is larger than Self Time. '+'This is a known limitation of this system, which occurs '+'due to several subslices, rounding issues, and imprecise '+'time at which we get cpu- and real-time.';}
+rows.push({name:'CPU Self Time',value:cpuSelfTimeEl});}}
+if(event.durationInUserTime){rows.push({name:'Duration (U)',value:tr.v.ui.createScalarSpan(event.durationInUserTime,{unit:tr.b.Unit.byName.timeDurationInMs})});}
+function createStackFrameEl(sf){const sfEl=document.createElement('tr-ui-a-stack-frame');sfEl.stackFrame=sf;return sfEl;}
+if(event.startStackFrame&&event.endStackFrame){if(event.startStackFrame===event.endStackFrame){rows.push({name:'Start+End Stack Trace',value:createStackFrameEl(event.startStackFrame)});}else{rows.push({name:'Start Stack Trace',value:createStackFrameEl(event.startStackFrame)});rows.push({name:'End Stack Trace',value:createStackFrameEl(event.endStackFrame)});}}else if(event.startStackFrame){rows.push({name:'Start Stack Trace',value:createStackFrameEl(event.startStackFrame)});}else if(event.endStackFrame){rows.push({name:'End Stack Trace',value:createStackFrameEl(event.endStackFrame)});}
+if(event.info){const descriptionEl=tr.ui.b.createDiv({textContent:event.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(event.info.docLinks){event.info.docLinks.forEach(function(linkObject){const linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;Polymer.dom(linkEl).textContent=Polymer.dom(linkObject).textContent;rows.push({name:linkObject.label,value:linkEl});});}}
+if(event.associatedAlerts.length){const alertSubRows=[];event.associatedAlerts.forEach(function(alert){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.model.EventSet(alert);},alert.info.description);alertSubRows.push({name:alert.title,value:linkEl});});rows.push({name:'Alerts',value:'',isExpanded:true,subRows:alertSubRows});}
+return rows;},getEventRows_(event){if(this.isFlow){return this.getFlowEventRows_(event);}
+return this.getEventRowsHelper_(event);},addArgsToRows_(rows,args){let n=0;for(const argName in args){n+=1;}
+if(n>0){const subRows=[];for(const argName in args){n+=1;}
+if(n>0){const subRows=[];for(const argName in args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=args[argName];subRows.push({name:argName,value:argView});}
+rows.push({name:'Args',value:'',isExpanded:true,subRows});}}},addContextsToRows_(rows,contexts){if(contexts.length){const subRows=contexts.map(function(context){const contextView=document.createElement('tr-ui-a-generic-object-view');contextView.object=context;return{name:'Context',value:contextView};});rows.push({name:'Contexts',value:'',isExpanded:true,subRows});}},updateContents_(){if(this.currentSelection_===undefined){this.$.table.rows=[];this.$.table.rebuild();return;}
+const event=tr.b.getOnlyElement(this.currentSelection_);const rows=this.getEventRows_(event);if(event.argsStripped){rows.push({name:'Args',value:'Stripped'});}else{this.addArgsToRows_(rows,event.args);}
+this.addContextsToRows_(rows,event.contexts);const customizeRowsEvent=new tr.b.Event('customize-rows');customizeRowsEvent.rows=rows;this.dispatchEvent(customizeRowsEvent);this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-ui-e-chrome-cc-raster-task-view',created(){this.selection_=undefined;},set selection(selection){this.selection_=selection;this.updateContents_();},updateColumns_(hadCpuDurations){const timeSpanConfig={unit:tr.b.Unit.byName.timeDurationInMs,ownerDocument:this.ownerDocument};const columns=[{title:'Layer',value(row){if(row.isTotals)return'Totals';if(row.layer){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.ui.e.chrome.cc.LayerSelection(row.layer);},'Layer '+row.layerId);return linkEl;}
+return'Layer '+row.layerId;},width:'250px'},{title:'Num Tiles',value(row){return row.numTiles;},cmp(a,b){return a.numTiles-b.numTiles;}},{title:'Num Analysis Tasks',value(row){return row.numAnalysisTasks;},cmp(a,b){return a.numAnalysisTasks-b.numAnalysisTasks;}},{title:'Num Raster Tasks',value(row){return row.numRasterTasks;},cmp(a,b){return a.numRasterTasks-b.numRasterTasks;}},{title:'Wall Duration (ms)',value(row){return tr.v.ui.createScalarSpan(row.duration,timeSpanConfig);},cmp(a,b){return a.duration-b.duration;}}];if(hadCpuDurations){columns.push({title:'CPU Duration (ms)',value(row){return tr.v.ui.createScalarSpan(row.cpuDuration,timeSpanConfig);},cmp(a,b){return a.cpuDuration-b.cpuDuration;}});}
+let colWidthPercentage;if(columns.length===1){colWidthPercentage='100%';}else{colWidthPercentage=(100/(columns.length-1)).toFixed(3)+'%';}
+for(let i=1;i<columns.length;i++){columns[i].width=colWidthPercentage;}
+this.$.content.tableColumns=columns;this.$.content.sortColumnIndex=columns.length-1;},updateContents_(){const table=this.$.content;if(this.selection_.length===0){this.$.link.setSelectionAndContent(undefined,'');table.tableRows=[];table.footerRows=[];table.rebuild();return;}
+const lthi=tr.e.cc.getTileFromRasterTaskSlice(tr.b.getFirstElement(this.selection_)).containingSnapshot;this.$.link.setSelectionAndContent(function(){return new tr.model.EventSet(lthi);},lthi.userFriendlyName);const costsByLayerId={};function getCurrentCostsForLayerId(tile){const layerId=tile.layerId;const lthi=tile.containingSnapshot;let layer;if(lthi.activeTree){layer=lthi.activeTree.findLayerWithId(layerId);}
+if(layer===undefined&&lthi.pendingTree){layer=lthi.pendingTree.findLayerWithId(layerId);}
+if(costsByLayerId[layerId]===undefined){costsByLayerId[layerId]={layerId,layer,numTiles:0,numAnalysisTasks:0,numRasterTasks:0,duration:0,cpuDuration:0};}
+return costsByLayerId[layerId];}
+let totalDuration=0;let totalCpuDuration=0;let totalNumAnalyzeTasks=0;let totalNumRasterizeTasks=0;let hadCpuDurations=false;const tilesThatWeHaveSeen={};this.selection_.forEach(function(slice){const tile=tr.e.cc.getTileFromRasterTaskSlice(slice);const curCosts=getCurrentCostsForLayerId(tile);if(!tilesThatWeHaveSeen[tile.objectInstance.id]){tilesThatWeHaveSeen[tile.objectInstance.id]=true;curCosts.numTiles+=1;}
+if(tr.e.cc.isSliceDoingAnalysis(slice)){curCosts.numAnalysisTasks+=1;totalNumAnalyzeTasks+=1;}else{curCosts.numRasterTasks+=1;totalNumRasterizeTasks+=1;}
+curCosts.duration+=slice.duration;totalDuration+=slice.duration;if(slice.cpuDuration!==undefined){curCosts.cpuDuration+=slice.cpuDuration;totalCpuDuration+=slice.cpuDuration;hadCpuDurations=true;}});this.updateColumns_(hadCpuDurations);table.tableRows=Object.values(costsByLayerId);table.rebuild();table.footerRows=[{isTotals:true,numTiles:Object.keys(tilesThatWeHaveSeen).length,numAnalysisTasks:totalNumAnalyzeTasks,numRasterTasks:totalNumRasterizeTasks,duration:totalDuration,cpuDuration:totalCpuDuration}];}});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){function RasterTaskSelection(selection){tr.ui.e.chrome.cc.Selection.call(this);const whySupported=RasterTaskSelection.whySuported(selection);if(!whySupported.ok){throw new Error('Fail: '+whySupported.why);}
+this.slices_=Array.from(selection);this.tiles_=this.slices_.map(function(slice){const tile=tr.e.cc.getTileFromRasterTaskSlice(slice);if(tile===undefined){throw new Error('This should never happen due to .supports check.');}
+return tile;});}
+RasterTaskSelection.whySuported=function(selection){if(!(selection instanceof tr.model.EventSet)){return{ok:false,why:'Must be selection'};}
+if(selection.length===0){return{ok:false,why:'Selection must be non empty'};}
+let referenceSnapshot=undefined;for(const event of selection){if(!(event instanceof tr.model.Slice)){return{ok:false,why:'Not a slice'};}
+const tile=tr.e.cc.getTileFromRasterTaskSlice(event);if(tile===undefined){return{ok:false,why:'No tile found'};}
+if(!referenceSnapshot){referenceSnapshot=tile.containingSnapshot;}else{if(tile.containingSnapshot!==referenceSnapshot){return{ok:false,why:'Raster tasks are from different compositor instances'};}}}
+return{ok:true};};RasterTaskSelection.supports=function(selection){return RasterTaskSelection.whySuported(selection).ok;};RasterTaskSelection.prototype={__proto__:tr.ui.e.chrome.cc.Selection.prototype,get specicifity(){return 3;},get associatedLayerId(){const tile0=this.tiles_[0];const allSameLayer=this.tiles_.every(function(tile){tile.layerId===tile0.layerId;});if(allSameLayer){return tile0.layerId;}
+return undefined;},get extraHighlightsByLayerId(){const highlights={};this.tiles_.forEach(function(tile,i){if(highlights[tile.layerId]===undefined){highlights[tile.layerId]=[];}
+const slice=this.slices_[i];highlights[tile.layerId].push({colorKey:slice.title,rect:tile.layerRect});},this);return highlights;},createAnalysis(){const sel=new tr.model.EventSet();this.slices_.forEach(function(slice){sel.push(slice);});let analysis;if(sel.length===1){analysis=document.createElement('tr-ui-a-single-event-sub-view');}else{analysis=document.createElement('tr-ui-e-chrome-cc-raster-task-view');}
+analysis.selection=sel;return analysis;},findEquivalent(lthi){return undefined;},get containingSnapshot(){return this.tiles_[0].containingSnapshot;}};return{RasterTaskSelection,};});'use strict';tr.exportTo('tr.ui.e.chrome.cc',function(){const TileSnapshotView=tr.ui.b.define('tr-ui-e-chrome-cc-tile-snapshot-view',tr.ui.analysis.ObjectSnapshotView);TileSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-cc-tile-snapshot-view');this.layerTreeView_=new tr.ui.e.chrome.cc.LayerTreeHostImplSnapshotView();Polymer.dom(this).appendChild(this.layerTreeView_);},updateContents(){const tile=this.objectSnapshot_;const layerTreeHostImpl=tile.containingSnapshot;if(!layerTreeHostImpl)return;this.layerTreeView_.objectSnapshot=layerTreeHostImpl;this.layerTreeView_.selection=new tr.ui.e.chrome.cc.TileSelection(tile);}};tr.ui.analysis.ObjectSnapshotView.register(TileSnapshotView,{typeName:'cc::Tile',showInTrackView:false});return{TileSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.chrome',function(){Polymer({is:'tr-ui-e-chrome-codesearch',set searchPhrase(phrase){const link=Polymer.dom(this.$.codesearchLink);const codeSearchURL='https://cs.chromium.org/search/?sq=package:chromium&type=cs&q=';link.setAttribute('href',codeSearchURL+encodeURIComponent(phrase));},onClick(clickEvent){clickEvent.stopPropagation();}});return{};});'use strict';tr.exportTo('tr.e.gpu',function(){const AsyncSlice=tr.model.AsyncSlice;function GpuAsyncSlice(){AsyncSlice.apply(this,arguments);}
+GpuAsyncSlice.prototype={__proto__:AsyncSlice.prototype,get viewSubGroupTitle(){if(this.args.channel){if(this.category==='disabled-by-default-gpu.device'){return'Device.'+this.args.channel;}
+return'Service.'+this.args.channel;}
+return this.title;}};AsyncSlice.subTypes.register(GpuAsyncSlice,{categoryParts:['disabled-by-default-gpu.device','disabled-by-default-gpu.service']});return{GpuAsyncSlice,};});'use strict';tr.exportTo('tr.e.gpu',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function StateSnapshot(){ObjectSnapshot.apply(this,arguments);}
+StateSnapshot.prototype={__proto__:ObjectSnapshot.prototype,preInitialize(){this.screenshot_=undefined;},initialize(){if(this.args.screenshot){this.screenshot_=this.args.screenshot;}},get screenshot(){return this.screenshot_;}};ObjectSnapshot.subTypes.register(StateSnapshot,{typeName:'gpu::State'});return{StateSnapshot,};});'use strict';tr.exportTo('tr.ui.e.chrome.gpu',function(){const StateSnapshotView=tr.ui.b.define('tr-ui-e-chrome-gpu-state-snapshot-view',tr.ui.analysis.ObjectSnapshotView);StateSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-chrome-gpu-state-snapshot-view');this.screenshotImage_=document.createElement('img');Polymer.dom(this).appendChild(this.screenshotImage_);},updateContents(){if(this.objectSnapshot_&&this.objectSnapshot_.screenshot){this.screenshotImage_.src='data:image/png;base64,'+
+this.objectSnapshot_.screenshot;}}};tr.ui.analysis.ObjectSnapshotView.register(StateSnapshotView,{typeName:'gpu::State'});return{StateSnapshotView,};});'use strict';tr.exportTo('tr.ui.analysis',function(){Polymer({is:'tr-ui-a-layout-tree-sub-view',behaviors:['tr-ui-a-sub-view'],set selection(selection){this.currentSelection_=selection;this.updateContents_();},get selection(){return this.currentSelection_;},updateContents_(){this.set('$.content.textContent','');if(!this.currentSelection_)return;const columns=[{title:'Tag/Name',value(layoutObject){return layoutObject.tag||':'+layoutObject.name;}},{title:'htmlId',value(layoutObject){return layoutObject.htmlId||'';}},{title:'classNames',value(layoutObject){return layoutObject.classNames||'';}},{title:'reasons',value(layoutObject){return layoutObject.needsLayoutReasons.join(', ');}},{title:'width',value(layoutObject){return layoutObject.absoluteRect.width;}},{title:'height',value(layoutObject){return layoutObject.absoluteRect.height;}},{title:'absX',value(layoutObject){return layoutObject.absoluteRect.left;}},{title:'absY',value(layoutObject){return layoutObject.absoluteRect.top;}},{title:'relX',value(layoutObject){return layoutObject.relativeRect.left;}},{title:'relY',value(layoutObject){return layoutObject.relativeRect.top;}},{title:'float',value(layoutObject){return layoutObject.isFloat?'float':'';}},{title:'positioned',value(layoutObject){return layoutObject.isPositioned?'positioned':'';}},{title:'relative',value(layoutObject){return layoutObject.isRelativePositioned?'relative':'';}},{title:'sticky',value(layoutObject){return layoutObject.isStickyPositioned?'sticky':'';}},{title:'anonymous',value(layoutObject){return layoutObject.isAnonymous?'anonymous':'';}},{title:'row',value(layoutObject){if(layoutObject.tableRow===undefined){return'';}
+return layoutObject.tableRow;}},{title:'col',value(layoutObject){if(layoutObject.tableCol===undefined){return'';}
+return layoutObject.tableCol;}},{title:'rowSpan',value(layoutObject){if(layoutObject.tableRowSpan===undefined){return'';}
+return layoutObject.tableRowSpan;}},{title:'colSpan',value(layoutObject){if(layoutObject.tableColSpan===undefined){return'';}
+return layoutObject.tableColSpan;}},{title:'address',value(layoutObject){return layoutObject.id.toString(16);}}];const table=this.ownerDocument.createElement('tr-ui-b-table');table.defaultExpansionStateCallback=function(layoutObject,parentLayoutObject){return true;};table.subRowsPropertyName='childLayoutObjects';table.tableColumns=columns;table.tableRows=this.currentSelection_.map(function(snapshot){return snapshot.rootLayoutObject;});table.rebuild();Polymer.dom(this.$.content).appendChild(table);},});return{};});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-layout-tree-sub-view',tr.e.chrome.LayoutTreeSnapshot,{multi:false,title:'Layout Tree',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-layout-tree-sub-view',tr.e.chrome.LayoutTreeSnapshot,{multi:true,title:'Layout Trees',});'use strict';tr.exportTo('tr.ui.e.img',function(){const THIS_DOC=document.currentScript.ownerDocument;const ImageSnapshotView=tr.ui.b.define('tr-ui-e-img-image-snapshot-view',tr.ui.analysis.ObjectSnapshotView);ImageSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){const node=tr.ui.b.instantiateTemplate('#tr-ui-e-img-image-snapshot-view-template',THIS_DOC);Polymer.dom(this).appendChild(node);const info=Polymer.dom(this).querySelector('.image-info');this.sizeInfo_=Polymer.dom(info).querySelector('.size');this.imageContainer_=Polymer.dom(this).querySelector('.image-container');this.image_=Polymer.dom(this.imageContainer_).querySelector('img');this.zoomScaleValue_=1;this.trackMouse_();},updateContents(){if(this.objectSnapshot_&&this.objectSnapshot_.data&&this.objectSnapshot_.type){this.image_.onload=this.drawPicture_.bind(this);this.image_.src=`data:image/${this.objectSnapshot_.type};`+`base64,${this.objectSnapshot_.data}`;}
+this.drawPicture_();},drawPicture_(){if(!this.image_.complete)return;const naturalWidth=this.image_.naturalWidth;const naturalHeight=this.image_.naturalHeight;this.sizeInfo_.textContent=`(${naturalWidth} x ${naturalHeight})`;this.image_.width=naturalWidth*this.zoomScaleValue_;this.image_.height=naturalHeight*this.zoomScaleValue_;},trackMouse_(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this.imageContainer_;Polymer.dom(this.imageContainer_).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.supportedModeMask=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.mode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.defaultMode=tr.ui.b.MOUSE_SELECTOR_MODE.ZOOM;this.mouseModeSelector_.settingsKey='pictureDebugger.mouseModeSelector';this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));},onBeginZoom_(e){this.isZooming_=true;this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);e.preventDefault();},onUpdateZoom_(e){if(!this.isZooming_)return;const currentMouseViewPos=this.extractRelativeMousePosition_(e);this.zoomScaleValue_+=((this.lastMouseViewPos_.y-currentMouseViewPos.y)*0.001);this.zoomScaleValue_=Math.max(this.zoomScaleValue_,0.1);this.drawPicture_();this.lastMouseViewPos_=currentMouseViewPos;},onEndZoom_(e){this.lastMouseViewPos_=undefined;this.isZooming_=false;e.preventDefault();},extractRelativeMousePosition_(e){return{x:e.clientX-this.imageContainer_.offsetLeft,y:e.clientY-this.imageContainer_.offsetTop};},};tr.ui.analysis.ObjectSnapshotView.register(ImageSnapshotView,{typeName:'gfx::Image'});return{ImageSnapshotView,};});'use strict';tr.exportTo('tr.ui.behaviors',function(){const SidePanel={get rangeOfInterest(){throw new Error('Not implemented');},set rangeOfInterest(rangeOfInterest){throw new Error('Not implemented');},get selection(){throw new Error('Not implemented');},set selection(selection){throw new Error('Not implemented');},get model(){throw new Error('Not implemented');},set model(model){throw new Error('Not implemented');},supportsModel(m){throw new Error('Not implemented');}};return{SidePanel,};});'use strict';tr.exportTo('tr.ui.side_panel',function(){function SidePanelRegistry(){}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(SidePanelRegistry,options);return{SidePanelRegistry,};});'use strict';tr.exportTo('tr.ui.e.s',function(){const BlameContextSnapshot=tr.e.chrome.BlameContextSnapshot;const FrameTreeNodeSnapshot=tr.e.chrome.FrameTreeNodeSnapshot;const RenderFrameSnapshot=tr.e.chrome.RenderFrameSnapshot;const TopLevelSnapshot=tr.e.chrome.TopLevelSnapshot;const BlameContextInstance=tr.e.chrome.BlameContextInstance;const FrameTreeNodeInstance=tr.e.chrome.FrameTreeNodeInstance;const RenderFrameInstance=tr.e.chrome.RenderFrameInstance;const TopLevelInstance=tr.e.chrome.TopLevelInstance;function Row(context){this.subRows=undefined;this.contexts=[];this.type=undefined;this.renderer='N/A';this.url=undefined;this.time=0;this.eventsOfInterest=new tr.model.EventSet();if(context===undefined)return;this.type=context.objectInstance.blameContextType;this.contexts.push(context);if(context instanceof FrameTreeNodeSnapshot){if(context.renderFrame){this.contexts.push(context.renderFrame);this.renderer=context.renderFrame.objectInstance.parent.pid;}}else if(context instanceof RenderFrameSnapshot){if(context.frameTreeNode){this.contexts.push(context.frameTreeNode);}
+this.renderer=context.objectInstance.parent.pid;}else if(context instanceof TopLevelSnapshot){this.renderer=context.objectInstance.parent.pid;}else{throw new Error('Unknown context type');}
+this.eventsOfInterest.addEventSet(this.contexts);this.url=context.url;}
+const groupFunctions={none:rows=>rows,tree(rows,rowMap){const getParentRow=function(row){let pivot;row.contexts.forEach(function(context){if(context instanceof tr.e.chrome.FrameTreeNodeSnapshot){pivot=context;}});if(pivot&&pivot.parentContext){return rowMap[pivot.parentContext.guid];}
+return undefined;};const rootRows=[];rows.forEach(function(row){const parentRow=getParentRow(row);if(parentRow===undefined){rootRows.push(row);return;}
+if(parentRow.subRows===undefined){parentRow.subRows=[];}
+parentRow.subRows.push(row);});const aggregateAllDescendants=function(row){if(!row.subRows){if(getParentRow(row)){row.type='Subframe';}
+return row;}
+const result=new Row();result.type='Frame Tree';result.renderer=row.renderer;result.url=row.url;result.subRows=[row];row.subRows.forEach(subRow=>result.subRows.push(aggregateAllDescendants(subRow)));result.subRows.forEach(function(subRow){result.time+=subRow.time;result.eventsOfInterest.addEventSet(subRow.eventsOfInterest);});row.subRows=undefined;return result;};return rootRows.map(rootRow=>aggregateAllDescendants(rootRow));}};Polymer({is:'tr-ui-e-s-frame-data-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=new tr.b.math.Range();this.$.table.showHeader=true;this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;this.$.table.tableColumns=this.createFrameDataTableColumns_();this.$.table.addEventListener('selection-changed',function(e){this.selectEventSet_(this.$.table.selectedTableRow.eventsOfInterest);}.bind(this));this.$.select.addEventListener('change',function(e){this.updateContents_();}.bind(this));},selectEventSet_(eventSet){const event=new tr.model.RequestSelectionChangeEvent();event.selection=eventSet;this.dispatchEvent(event);},createFrameDataTableColumns_(){return[{title:'Renderer',value:row=>row.renderer,cmp:(a,b)=>a.renderer-b.renderer},{title:'Type',value:row=>row.type},{title:'Time',value:row=>tr.v.ui.createScalarSpan(row.time,{unit:tr.b.Unit.byName.timeStampInMs,ownerDocument:this.ownerDocument}),cmp:(a,b)=>a.time-b.time},{title:'URL',value:row=>row.url,cmp:(a,b)=>(a.url||'').localeCompare(b.url||'')}];},createFrameDataTableRows_(){if(!this.model_)return[];const rows=[];const rowMap={};for(const proc of Object.values(this.model_.processes)){proc.objects.iterObjectInstances(function(objectInstance){if(!(objectInstance instanceof BlameContextInstance)){return;}
+objectInstance.snapshots.forEach(function(snapshot){if(rowMap[snapshot.guid])return;const row=new Row(snapshot);row.contexts.forEach(context=>rowMap[context.guid]=row);rows.push(row);},this);},this);}
+for(const proc of Object.values(this.model_.processes)){for(const thread of Object.values(proc.threads)){thread.sliceGroup.iterSlicesInTimeRange(function(topLevelSlice){topLevelSlice.contexts.forEach(function(context){if(!context.snapshot.guid||!rowMap[context.snapshot.guid]){return;}
+const row=rowMap[context.snapshot.guid];row.eventsOfInterest.push(topLevelSlice);row.time+=topLevelSlice.selfTime||0;});},this.currentRangeOfInterest.min,this.currentRangeOfInterest.max);}}
+const select=this.$.select;const groupOption=select.options[select.selectedIndex].value;const groupFunction=groupFunctions[groupOption];return groupFunction(rows,rowMap);},updateContents_(){this.$.table.tableRows=this.createFrameDataTableRows_();this.$.table.rebuild();},supportsModel(m){if(!m){return{supported:false,reason:'No model available.'};}
+const ans={supported:false};for(const proc of Object.values(m.processes)){proc.objects.iterObjectInstances(function(instance){if(instance instanceof BlameContextInstance){ans.supported=true;}});}
+if(!ans.supported){ans.reason='No frame data available';}
+return ans;},get currentRangeOfInterest(){if(this.rangeOfInterest_.isEmpty){return this.model_.bounds;}
+return this.rangeOfInterest_;},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(rangeOfInterest){this.rangeOfInterest_=rangeOfInterest;this.updateContents_();},get selection(){},set selection(_){},get textLabel(){return'Frame Data';},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();}});tr.ui.side_panel.SidePanelRegistry.register(function(){return document.createElement('tr-ui-e-s-frame-data-side-panel');});});'use strict';Polymer({is:'tr-ui-b-chart-legend-key',ready(){this.$.checkbox.addEventListener('change',this.onCheckboxChange_.bind(this));},onCheckboxChange_(){tr.b.dispatchSimpleEvent(this,tr.ui.b.DataSeriesEnableChangeEventType,true,false,{key:Polymer.dom(this).textContent,enabled:this.enabled});},set textContent(t){Polymer.dom(this.$.label).textContent=t;Polymer.dom(this.$.link).textContent=t;this.updateContents_();},set width(w){w-=20;this.$.link.style.width=w+'px';this.$.label.style.width=w+'px';},get textContent(){return Polymer.dom(this.$.label).textContent;},set optional(optional){this.$.checkbox.style.visibility=optional?'visible':'hidden';},get optional(){return this.$.checkbox.style.visibility==='visible';},set enabled(enabled){this.$.checkbox.checked=enabled?'checked':'';},get enabled(){return this.$.checkbox.checked;},set color(c){this.$.label.style.color=c;this.$.link.color=c;},set target(target){this.$.link.setSelectionAndContent(target,Polymer.dom(this.$.label).textContent);this.updateContents_();},get target(){return this.$.link.selection;},set title(title){this.$.link.title=title;},updateContents_(){this.$.link.style.display=this.target?'':'none';this.$.label.style.display=this.target?'none':'';this.$.label.htmlFor=this.optional?'checkbox':'';}});'use strict';(function(window){window.define=function(x){window.d3=x;};window.define.amd=true;})(this);!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function T(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function z(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o,a=0,c=0,s=0;if(u=/([a-z]+)\((.*)\)/i.exec(n))switch(i=u[2].split(","),u[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Mt(i[0]),Mt(i[1]),Mt(i[2]))}return(o=Va.get(n))?t(o.r,o.g,o.b):(null!=n&&"#"===n.charAt(0)&&(r=parseInt(n.substring(1),16),isNaN(r)||(4===n.length?(a=(3840&r)>>4,a=a>>4|a,c=240&r,c=c>>4|c,s=15&r,s=s<<4|s):7===n.length&&(a=(16711680&r)>>16,c=(65280&r)>>8,s=255&r))),t(a,c,s))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Xo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function zt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=zt;var r=new zt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=zt;var r=new zt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==zt,o=new(i?zt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=zt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=zt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);hc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>Sa,k=p*x;if(hc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*ka:_,S^h>=e^m>=e){var E=fe(se(f),se(n));pe(E);var A=fe(u,E);pe(A);var C=(S^_>=0?-1:1)*X(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function ze(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),Tc>t&&(Tc=t),t>zc&&(zc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,T=N-e,q=x*L-y*T;(q*q/M>i||oa((y*L+x*T)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function Tr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function zr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),zr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(zu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function zu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function Ti(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function zi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():zi(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=zi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=zi(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return zi(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function To(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function zo(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=zi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=zi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.3"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=Sizzle,va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=T(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=T(o);for(;f>r;++r)p[r]=T(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=z.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,Ta=Math.SQRT2,qa=2,za=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(Ta*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(Ta*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+za*f)/(2*i*qa*h),p=(c*c-i*i-za*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ta;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=T.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=T.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=T.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=T.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",T=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=T.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,T,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv("	","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;zt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,Te,ze,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,Tc,qc,zc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=zc=-(Lc=Tc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,Tc],[qc,zc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ti,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ti(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ti:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(To(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=zo,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=Ts,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":Ts,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Ts="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return zs[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),T.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),T=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?T.on("touchmove.brush",v).on("touchend.brush",y):T.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),z=+/^n/.test(k);M=[l[1-q]-L[0],f[1-z]-L[1]],L[0]=l[q],L[1]=f[z]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var zs={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(Math.ceil(n/e)*e,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();'use strict';(function(window){window.define=undefined;}).call(this,this);'use strict';tr.exportTo('tr.ui.b',function(){const DataSeriesEnableChangeEventType='data-series-enabled-change';const THIS_DOC=document._currentScript.ownerDocument;const svgNS='http://www.w3.org/2000/svg';const ColorScheme=tr.b.ColorScheme;function getColorOfKey(key,selected){let id=ColorScheme.getColorIdForGeneralPurposeString(key);if(selected){id+=ColorScheme.properties.brightenedOffsets[0];}
+return ColorScheme.colorsAsStrings[id];}
+function getSVGTextSize(parentNode,text,opt_callback,opt_this){const textNode=document.createElementNS('http://www.w3.org/2000/svg','text');textNode.setAttributeNS(null,'x',0);textNode.setAttributeNS(null,'y',0);textNode.setAttributeNS(null,'fill','black');textNode.appendChild(document.createTextNode(text));parentNode.appendChild(textNode);if(opt_callback){opt_callback.call(opt_this||parentNode,textNode);}
+const width=textNode.getComputedTextLength();const height=textNode.getBBox().height;parentNode.removeChild(textNode);return{width,height};}
+function DataSeries(key){this.key_=key;this.target_=undefined;this.title_='';this.optional_=false;this.enabled_=true;this.color_=getColorOfKey(key,false);this.highlightedColor_=getColorOfKey(key,true);}
+DataSeries.prototype={get key(){return this.key_;},get title(){return this.title_;},set title(t){this.title_=t;},get color(){return this.color_;},set color(c){this.color_=c;},get highlightedColor(){return this.highlightedColor_;},set highlightedColor(c){this.highlightedColor_=c;},get optional(){return this.optional_;},set optional(optional){this.optional_=optional;},get enabled(){return this.enabled_;},set enabled(enabled){if(!this.optional&&!enabled){this.optional=true;}
+this.enabled_=enabled;},get target(){return this.target_;},set target(t){this.target_=t;}};const ChartBase=tr.ui.b.define('svg',undefined,svgNS);ChartBase.prototype={__proto__:HTMLUnknownElement.prototype,getDataSeries(key){if(!this.seriesByKey_.has(key)){this.seriesByKey_.set(key,new DataSeries(key));}
+return this.seriesByKey_.get(key);},decorate(){Polymer.dom(this).classList.add('chart-base');this.setAttribute('style','cursor: default; user-select: none;');this.chartTitle_=undefined;this.seriesByKey_=new Map();this.graphWidth_=undefined;this.graphHeight_=undefined;this.margin={top:0,right:0,bottom:0,left:0,};this.hideLegend_=false;this.showTitleInLegend_=false;this.titleHeight_='16pt';const template=Polymer.dom(THIS_DOC).querySelector('#chart-base-template');const svgEl=Polymer.dom(template.content).querySelector('svg');for(let i=0;i<Polymer.dom(svgEl).children.length;i++){Polymer.dom(this).appendChild(Polymer.dom(svgEl.children[i]).cloneNode(true));}
+this.addEventListener(DataSeriesEnableChangeEventType,this.onDataSeriesEnableChange_.bind(this));},get hideLegend(){return this.hideLegend_;},set hideLegend(h){this.hideLegend_=h;this.updateContents_();},get showTitleInLegend(){return this.showTitleInLegend_;},set showTitleInLegend(s){this.showTitleInLegend_=s;this.updateContents_();},isSeriesEnabled(key){return this.getDataSeries(key).enabled;},onDataSeriesEnableChange_(event){this.getDataSeries(event.key).enabled=event.enabled;this.updateContents_();},get chartTitle(){return this.chartTitle_;},set chartTitle(chartTitle){this.chartTitle_=chartTitle;this.updateContents_();},get chartAreaElement(){return Polymer.dom(this).querySelector('#chart-area');},get graphWidth(){if(this.graphWidth_===undefined)return this.defaultGraphWidth;return this.graphWidth_;},set graphWidth(width){this.graphWidth_=width;this.updateContents_();},get defaultGraphWidth(){return 0;},get graphHeight(){if(this.graphHeight_===undefined)return this.defaultGraphHeight;return this.graphHeight_;},set graphHeight(height){this.graphHeight_=height;this.updateContents_();},get titleHeight(){return this.titleHeight_;},set titleHeight(height){this.titleHeight_=height;this.updateContents_();},get defaultGraphHeight(){return 0;},get totalWidth(){return this.margin.left+this.graphWidth+this.margin.right;},get totalHeight(){return this.margin.top+this.graphHeight+this.margin.bottom;},updateMargins_(){const legendSize=this.computeLegendSize_();this.margin.right=Math.max(this.margin.right,legendSize.width);this.margin.bottom=Math.max(this.margin.bottom,legendSize.height-this.graphHeight);if(this.chartTitle_){const titleSize=getSVGTextSize(this,this.chartTitle_,textNode=>{textNode.style.fontSize='16pt';});this.margin.top=Math.max(this.margin.top,titleSize.height+15);const horizontalOverhangPx=(titleSize.width-this.graphWidth)/2;this.margin.left=Math.max(this.margin.left,horizontalOverhangPx);this.margin.right=Math.max(this.margin.right,horizontalOverhangPx);}},computeLegendSize_(){let width=0;let height=0;if(this.hideLegend)return{width,height};let series=[...this.seriesByKey_.values()];if(this.showTitleInLegend){series=series.filter(series=>series.title!=='');}
+for(const seriesEntry of series){const legendText=this.showTitleInLegend?seriesEntry.title:seriesEntry.key;const textSize=getSVGTextSize(this,legendText);width=Math.max(width,textSize.width+30);height+=textSize.height;}
+return{width,height};},updateDimensions_(){const thisSel=d3.select(this);thisSel.attr('width',this.totalWidth);thisSel.attr('height',this.totalHeight);d3.select(this.chartAreaElement).attr('transform','translate('+this.margin.left+', '+this.margin.top+')');},updateContents_(){this.updateMargins_();this.updateDimensions_();this.updateTitle_();this.updateLegend_();},updateTitle_(){const titleSel=d3.select(this.chartAreaElement).select('#title');if(!this.chartTitle_){titleSel.style('display','none');return;}
+titleSel.attr('transform','translate('+this.graphWidth*0.5+',-15)').style('display',undefined).style('text-anchor','middle').style('font-size',this.titleHeight).attr('class','title').attr('width',this.graphWidth).text(this.chartTitle_);},updateLegend_(){const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.legend').remove();if(this.hideLegend)return;let series;let seriesText;if(this.showTitleInLegend){series=[...this.seriesByKey_.values()].filter(series=>series.title!=='').filter(series=>series.color!=='transparent').reverse();seriesText=series=>series.title;}else{series=[...this.seriesByKey_.values()].filter(series=>series.color!=='transparent').reverse();seriesText=series=>series.key;}
+const legendEntriesSel=chartAreaSel.selectAll('.legend').data(series);legendEntriesSel.enter().append('foreignObject').attr('class','legend').attr('x',this.graphWidth+2).attr('width',this.margin.right).attr('height',18).attr('transform',(series,i)=>'translate(0,'+i*18+')').append('xhtml:body').style('margin',0).append('tr-ui-b-chart-legend-key').property('color',series=>((this.currentHighlightedLegendKey===series.key)?series.highlightedColor:series.color)).property('width',this.margin.right).property('target',series=>series.target).property('title',series=>series.title).property('optional',series=>series.optional).property('enabled',series=>series.enabled).text(seriesText);legendEntriesSel.exit().remove();},get highlightedLegendKey(){return this.highlightedLegendKey_;},set highlightedLegendKey(highlightedLegendKey){this.highlightedLegendKey_=highlightedLegendKey;this.updateHighlight_();},get currentHighlightedLegendKey(){if(this.tempHighlightedLegendKey_){return this.tempHighlightedLegendKey_;}
+return this.highlightedLegendKey_;},pushTempHighlightedLegendKey(key){if(this.tempHighlightedLegendKey_){throw new Error('push cannot nest');}
+this.tempHighlightedLegendKey_=key;this.updateHighlight_();},popTempHighlightedLegendKey(key){if(this.tempHighlightedLegendKey_!==key){throw new Error('pop cannot happen');}
+this.tempHighlightedLegendKey_=undefined;this.updateHighlight_();},updateHighlight_(){const chartAreaSel=d3.select(this.chartAreaElement);const legendEntriesSel=chartAreaSel.selectAll('.legend');const getDataSeries=chart.getDataSeries.bind(chart);const currentHighlightedLegendKey=chart.currentHighlightedLegendKey;legendEntriesSel.each(function(key){const dataSeries=getDataSeries(key);if(key===currentHighlightedLegendKey){this.style.fill=dataSeries.highlightedColor;this.style.fontWeight='bold';}else{this.style.fill=dataSeries.color;this.style.fontWeight='';}});}};return{ChartBase,DataSeriesEnableChangeEventType,getColorOfKey,getSVGTextSize,};});'use strict';tr.exportTo('tr.ui.b',function(){const D3_Y_AXIS_WIDTH_PX=9;const D3_X_AXIS_HEIGHT_PX=23;function sanitizePower(x,defaultValue){if(!isNaN(x)&&isFinite(x)&&(x!==0))return x;return defaultValue;}
+const ChartBase2D=tr.ui.b.define('chart-base-2d',tr.ui.b.ChartBase);ChartBase2D.prototype={__proto__:tr.ui.b.ChartBase.prototype,decorate(){super.decorate();Polymer.dom(this).classList.add('chart-base-2d');this.xScale_=d3.scale.linear();this.yScale_=d3.scale.linear();this.isYLogScale_=false;this.yLogScaleBase_=10;this.yLogScaleMin_=undefined;this.autoDataRange_=new tr.b.math.Range();this.overrideDataRange_=undefined;this.hideXAxis_=false;this.hideYAxis_=false;this.data_=[];this.xAxisLabel_='';this.yAxisLabel_='';this.textHeightPx_=0;this.unit_=undefined;d3.select(this.chartAreaElement).append('g').attr('id','brushes');d3.select(this.chartAreaElement).append('g').attr('id','series');this.addEventListener('mousedown',this.onMouseDown_.bind(this));},get yLogScaleBase(){return this.yLogScaleBase_;},set yLogScaleBase(b){this.yLogScaleBase_=b;},get unit(){return this.unit_;},set unit(unit){this.unit_=unit;this.updateContents_();},get xAxisLabel(){return this.xAxisLabel_;},set xAxisLabel(label){this.xAxisLabel_=label;},get yAxisLabel(){return this.yAxisLabel_;},set yAxisLabel(label){this.yAxisLabel_=label;},get hideXAxis(){return this.hideXAxis_;},set hideXAxis(h){this.hideXAxis_=h;this.updateContents_();},get hideYAxis(){return this.hideYAxis_;},set hideYAxis(h){this.hideYAxis_=h;this.updateContents_();},get data(){return this.data_;},set data(data){if(data===undefined){throw new Error('data must be an Array');}
+this.data_=data;this.updateSeriesKeys_();this.updateDataRange_();this.updateContents_();},set isYLogScale(logScale){if(logScale){this.yScale_=d3.scale.log().base(this.yLogScaleBase);}else{this.yScale_=d3.scale.linear();}
+this.isYLogScale_=logScale;},getYScaleMin_(){return this.isYLogScale_?this.yLogScaleMin_:0;},getYScaleDomain_(minValue,maxValue){if(this.overrideDataRange_!==undefined){return[this.dataRange.min,this.dataRange.max];}
+if(this.isYLogScale_){return[this.getYScaleMin_(),maxValue];}
+return[Math.min(minValue,this.getYScaleMin_()),maxValue];},getSampleWidth_(data,index,leftSide){let leftIndex;let rightIndex;if(leftSide){leftIndex=Math.max(index-1,0);rightIndex=index;}else{leftIndex=index;rightIndex=Math.min(index+1,data.length-1);}
+const leftWidth=this.getXForDatum_(data[index],index)-
+this.getXForDatum_(data[leftIndex],leftIndex);const rightWidth=this.getXForDatum_(data[rightIndex],rightIndex)-
+this.getXForDatum_(data[index],index);return tr.b.math.Statistics.mean([leftWidth,rightWidth]);},updateSeriesKeys_(){this.data_.forEach(function(datum){Object.keys(datum).forEach(function(key){if(this.isDatumFieldSeries_(key)){this.getDataSeries(key);}},this);},this);},isDatumFieldSeries_(fieldName){return fieldName!=='x';},getXForDatum_(datum,index){return datum.x;},updateMargins_(){this.margin.left=this.hideYAxis?0:this.yAxisWidth;this.margin.bottom=this.hideXAxis?0:this.xAxisHeight;if(this.hideXAxis&&!this.hideYAxis){this.margin.bottom=10;}
+if(this.hideYAxis&&!this.hideXAxis){this.margin.left=10;}
+this.margin.top=this.hideYAxis?0:10;if(this.yAxisLabel){this.margin.top+=this.textHeightPx_;}
+if(this.xAxisLabel){this.margin.right=Math.max(this.margin.right,16+tr.ui.b.getSVGTextSize(this,this.xAxisLabel).width);}
+super.updateMargins_();},get xAxisHeight(){return D3_X_AXIS_HEIGHT_PX;},computeScaleTickWidth_(scale){if(this.data.length===0)return 0;let tickValues=scale.ticks();let tickFormat=scale.tickFormat();if(this.isYLogScale_){const enclosingPowers=this.dataRange.enclosingPowers();tickValues=[];const maxPower=sanitizePower(enclosingPowers.max,this.yLogScaleBase);for(let power=sanitizePower(enclosingPowers.min,1);power<=maxPower;power*=this.yLogScaleBase){tickValues.push(power);}
+tickFormat=v=>v.toString();}
+if(this.unit){tickFormat=v=>this.unit.format(v);}
+let maxTickWidth=0;for(const tickValue of tickValues){maxTickWidth=Math.max(maxTickWidth,tr.ui.b.getSVGTextSize(this,tickFormat(tickValue)).width);}
+return D3_Y_AXIS_WIDTH_PX+maxTickWidth;},get yAxisWidth(){return this.computeScaleTickWidth_(this.yScale_);},updateScales_(){if(this.data_.length===0)return;this.xScale_.range([0,this.graphWidth]);this.xScale_.domain(d3.extent(this.data_,this.getXForDatum_.bind(this)));this.yScale_.range([this.graphHeight,0]);this.yScale_.domain([this.dataRange.min,this.dataRange.max]);},updateBrushContents_(brushSel){brushSel.selectAll('*').remove();},updateXAxis_(xAxis){xAxis.selectAll('*').remove();xAxis[0][0].style.opacity=0;if(this.hideXAxis)return;this.drawXAxis_(xAxis);const label=xAxis.append('text').attr('class','label');this.drawXAxisTicks_(xAxis);this.drawXAxisLabel_(label);xAxis[0][0].style.opacity=1;},drawXAxis_(xAxis){xAxis.attr('transform','translate(0,'+this.graphHeight+')').call(d3.svg.axis().scale(this.xScale_).orient('bottom'));},drawXAxisLabel_(label){label.attr('x',this.graphWidth+16).attr('y',8).text(this.xAxisLabel);},drawXAxisTicks_(xAxis){let previousRight=undefined;xAxis.selectAll('.tick')[0].forEach(function(tick){const currentLeft=tick.transform.baseVal[0].matrix.e;if((previousRight===undefined)||(currentLeft>(previousRight+3))){const currentWidth=tick.getBBox().width;previousRight=currentLeft+currentWidth;}else{tick.style.opacity=0;}});},set overrideDataRange(range){this.overrideDataRange_=range;},get dataRange(){if(this.overrideDataRange_!==undefined){return this.overrideDataRange_;}
+return this.autoDataRange_;},updateDataRange_(){if(this.overrideDataRange_!==undefined)return;const dataBySeriesKey=this.getDataBySeriesKey_();this.autoDataRange_.reset();for(const[series,values]of Object.entries(dataBySeriesKey)){for(let i=0;i<values.length;i++){this.autoDataRange_.addValue(values[i][series]);}}
+this.yLogScaleMin_=undefined;if(this.autoDataRange_.min!==undefined){let minValue=this.autoDataRange_.min;if(minValue===0){minValue=1;}
+const onePowerLess=tr.b.math.lesserPower(minValue/this.yLogScaleBase);this.yLogScaleMin_=onePowerLess;}},updateYAxis_(yAxis){yAxis.selectAll('*').remove();yAxis[0][0].style.opacity=0;if(this.hideYAxis)return;this.drawYAxis_(yAxis);this.drawYAxisTicks_(yAxis);const label=yAxis.append('text').attr('class','label');this.drawYAxisLabel_(label);},drawYAxis_(yAxis){let axisModifier=d3.svg.axis().scale(this.yScale_).orient('left');let tickFormat;if(this.isYLogScale_){if(this.yLogScaleMin_===undefined)return;const tickValues=[];const enclosingPowers=this.dataRange.enclosingPowers();const maxPower=sanitizePower(enclosingPowers.max,this.yLogScaleBase);for(let power=sanitizePower(enclosingPowers.min,1);power<=maxPower;power*=this.yLogScaleBase){tickValues.push(power);}
+axisModifier=axisModifier.tickValues(tickValues);tickFormat=v=>v.toString();}
+if(this.unit){tickFormat=v=>this.unit.format(v);}
+if(tickFormat){axisModifier=axisModifier.tickFormat(tickFormat);}
+yAxis.call(axisModifier);},drawYAxisLabel_(label){const labelWidthPx=Math.ceil(tr.ui.b.getSVGTextSize(this.chartAreaElement,this.yAxisLabel).width);label.attr('x',-labelWidthPx).attr('y',-8).text(this.yAxisLabel);},drawYAxisTicks_(yAxis){let previousTop=undefined;yAxis.selectAll('.tick')[0].forEach(function(tick){const bbox=tick.getBBox();const currentTop=tick.transform.baseVal[0].matrix.f;const currentBottom=currentTop+bbox.height;if((previousTop===undefined)||(previousTop>(currentBottom+3))){previousTop=currentTop;}else{tick.style.opacity=0;}});yAxis[0][0].style.opacity=1;},updateContents_(){if(this.textHeightPx_===0){this.textHeightPx_=tr.ui.b.getSVGTextSize(this,'Ay').height;}
+this.updateScales_();super.updateContents_();const chartAreaSel=d3.select(this.chartAreaElement);this.updateXAxis_(chartAreaSel.select('.x.axis'));this.updateYAxis_(chartAreaSel.select('.y.axis'));for(const child of Array.from(this.querySelectorAll('.axis path, .axis line'))){child.style.fill='none';child.style.shapeRendering='crispEdges';child.style.stroke='black';}
+this.updateBrushContents_(chartAreaSel.select('#brushes'));this.updateDataContents_(chartAreaSel.select('#series'));},updateDataContents_(seriesSel){throw new Error('Not implemented');},getDataBySeriesKey_(){const dataBySeriesKey={};for(const[key,series]of this.seriesByKey_){dataBySeriesKey[key]=[];}
+this.data_.forEach(function(multiSeriesDatum,index){const x=this.getXForDatum_(multiSeriesDatum,index);d3.keys(multiSeriesDatum).forEach(function(seriesKey){if(seriesKey==='x')return;if(multiSeriesDatum[seriesKey]===undefined)return;if(!this.isDatumFieldSeries_(seriesKey))return;const singleSeriesDatum={x};singleSeriesDatum[seriesKey]=multiSeriesDatum[seriesKey];dataBySeriesKey[seriesKey].push(singleSeriesDatum);},this);},this);return dataBySeriesKey;},getChartPointAtClientPoint_(clientPoint){const rect=this.getBoundingClientRect();return{x:clientPoint.x-rect.left-this.margin.left,y:clientPoint.y-rect.top-this.margin.top};},getDataPointAtChartPoint_(chartPoint){return{x:tr.b.math.clamp(this.xScale_.invert(chartPoint.x),this.xScale_.domain()[0],this.xScale_.domain()[1]),y:tr.b.math.clamp(this.yScale_.invert(chartPoint.y),this.yScale_.domain()[0],this.yScale_.domain()[1])};},getDataPointAtClientPoint_(clientX,clientY){const chartPoint=this.getChartPointAtClientPoint_({x:clientX,y:clientY});return this.getDataPointAtChartPoint_(chartPoint);},prepareDataEvent_(mouseEvent,dataEvent){const dataPoint=this.getDataPointAtClientPoint_(mouseEvent.clientX,mouseEvent.clientY);dataEvent.x=dataPoint.x;dataEvent.y=dataPoint.y;},onMouseDown_(mouseEvent){tr.ui.b.trackMouseMovesUntilMouseUp(this.onMouseMove_.bind(this,mouseEvent.button),this.onMouseUp_.bind(this,mouseEvent.button));mouseEvent.preventDefault();mouseEvent.stopPropagation();const dataEvent=new tr.b.Event('item-mousedown');dataEvent.button=mouseEvent.button;this.prepareDataEvent_(mouseEvent,dataEvent);this.dispatchEvent(dataEvent);for(const child of Array.from(this.querySelector('#brushes').children)){child.setAttribute('fill','rgb(103, 199, 165)');}},onMouseMove_(button,mouseEvent){if(mouseEvent.buttons!==undefined){mouseEvent.preventDefault();mouseEvent.stopPropagation();}
+const dataEvent=new tr.b.Event('item-mousemove');dataEvent.button=button;this.prepareDataEvent_(mouseEvent,dataEvent);this.dispatchEvent(dataEvent);for(const child of Array.from(this.querySelector('#brushes').children)){child.setAttribute('fill','rgb(103, 199, 165)');}},onMouseUp_(button,mouseEvent){mouseEvent.preventDefault();mouseEvent.stopPropagation();const dataEvent=new tr.b.Event('item-mouseup');dataEvent.button=button;this.prepareDataEvent_(mouseEvent,dataEvent);this.dispatchEvent(dataEvent);for(const child of Array.from(this.querySelector('#brushes').children)){child.setAttribute('fill','rgb(213, 236, 229)');}}};return{ChartBase2D,};});'use strict';tr.exportTo('tr.ui.b',function(){const ChartBase2D=tr.ui.b.ChartBase2D;const ChartBase2DBrushX=tr.ui.b.define('chart-base-2d-brush-1d',ChartBase2D);ChartBase2DBrushX.prototype={__proto__:ChartBase2D.prototype,decorate(){super.decorate();this.brushedRange_=new tr.b.math.Range();},set brushedRange(range){this.brushedRange_.reset();this.brushedRange_.addRange(range);this.updateContents_();},get brushedRange(){return tr.b.math.Range.fromDict(this.brushedRange_.toJSON());},computeBrushRangeFromIndices(indexA,indexB){indexA=tr.b.math.clamp(indexA,0,this.data_.length-1);indexB=tr.b.math.clamp(indexB,0,this.data_.length-1);const leftIndex=Math.min(indexA,indexB);const rightIndex=Math.max(indexA,indexB);const brushRange=new tr.b.math.Range();brushRange.addValue(this.getXForDatum_(this.data_[leftIndex],leftIndex)-
+this.getSampleWidth_(this.data_,leftIndex,true));brushRange.addValue(this.getXForDatum_(this.data_[rightIndex],rightIndex)+
+this.getSampleWidth_(this.data_,rightIndex,false));return brushRange;},getDataIndex_(dataX){if(this.data.length===0)return undefined;const bisect=d3.bisector(this.getXForDatum_.bind(this)).right;return bisect(this.data_,dataX)-1;},prepareDataEvent_(mouseEvent,dataEvent){ChartBase2D.prototype.prepareDataEvent_.call(this,mouseEvent,dataEvent);dataEvent.index=this.getDataIndex_(dataEvent.x);if(dataEvent.index!==undefined){dataEvent.data=this.data_[dataEvent.index];}},updateBrushContents_(brushSel){brushSel.selectAll('*').remove();const brushes=this.brushedRange_.isEmpty?[]:[this.brushedRange_];const brushRectsSel=brushSel.selectAll('rect').data(brushes);brushRectsSel.enter().append('rect');brushRectsSel.exit().remove();this.drawBrush_(brushRectsSel);},drawBrush_(brushRectsSel){brushRectsSel.attr('x',d=>this.xScale_(d.min)).attr('y',0).attr('width',d=>this.xScale_(d.max)-this.xScale_(d.min)).attr('height',this.graphHeight).attr('fill','rgb(213, 236, 229)');}};return{ChartBase2DBrushX,};});'use strict';tr.exportTo('tr.ui.b',function(){const ColumnChart=tr.ui.b.define('column-chart',tr.ui.b.ChartBase2DBrushX);ColumnChart.prototype={__proto__:tr.ui.b.ChartBase2DBrushX.prototype,decorate(){super.decorate();this.xCushion_=1;this.isStacked_=false;this.isGrouped_=false;this.enableHoverBox=true;this.displayXInHover=false;this.enableToolTip=false;this.toolTipCallBack_=()=>{};},set toolTipCallBack(callback){this.toolTipCallBack_=callback;},get toolTipCallBack(){return this.toolTipCallBack_;},set isGrouped(grouped){this.isGrouped_=grouped;if(grouped){this.getDataSeries('group').color='transparent';}
+this.updateContents_();},get isGrouped(){return this.isGrouped_;},set isStacked(stacked){this.isStacked_=true;this.updateContents_();},get isStacked(){return this.isStacked_;},get defaultGraphHeight(){return 100;},get defaultGraphWidth(){return 10*this.data_.length;},updateScales_(){if(this.data_.length===0)return;let xDifferences=0;let currentX=undefined;let previousX=undefined;this.data_.forEach(function(datum,index){previousX=currentX;currentX=this.getXForDatum_(datum,index);if(previousX!==undefined){xDifferences+=currentX-previousX;}},this);this.xScale_.range([0,this.graphWidth]);const domain=d3.extent(this.data_,this.getXForDatum_.bind(this));if(this.data_.length>1){this.xCushion_=xDifferences/(this.data_.length-1);}
+this.xScale_.domain([domain[0],domain[1]+this.xCushion_]);this.yScale_.range([this.graphHeight,0]);this.yScale_.domain(this.getYScaleDomain_(this.dataRange.min,this.dataRange.max));},updateDataRange_(){if(!this.isStacked){super.updateDataRange_();return;}
+this.autoDataRange_.reset();this.autoDataRange_.addValue(0);for(const datum of this.data_){let sum=0;for(const[key,series]of this.seriesByKey_){if(datum[key]===undefined){continue;}else if(this.isGrouped&&key==='group'){continue;}
+sum+=datum[key];}
+this.autoDataRange_.addValue(sum);}},getStackedRectsForDatum_(datum,index){const stacks=[];let bottom=this.yScale_.range()[0];let sum=0;for(const[key,series]of this.seriesByKey_){if(datum[key]===undefined||!this.isSeriesEnabled(key)){continue;}else if(this.isGrouped&&key==='group'){continue;}
+sum+=this.dataRange.clamp(datum[key]);const heightPx=bottom-this.yScale_(sum);bottom-=heightPx;stacks.push({key,value:datum[key],color:this.getDataSeries(key).color,heightPx,topPx:bottom,underflow:sum<this.dataRange.min,overflow:sum>this.dataRange.max,});}
+return stacks;},getRectsForDatum_(datum,index){if(this.isStacked){return this.getStackedRectsForDatum_(datum,index);}
+const stacks=[];for(const[key,series]of this.seriesByKey_){if(datum[key]===undefined||!this.isSeriesEnabled(key)){continue;}
+const clampedValue=this.dataRange.clamp(datum[key]);const topPx=this.yScale_(Math.max(clampedValue,this.getYScaleMin_()));stacks.push({key,value:datum[key],topPx,heightPx:this.yScale_.range()[0]-topPx,color:this.getDataSeries(key).color,underflow:datum[key]<this.dataRange.min,overflow:datum[key]>this.dataRange.max,});}
+stacks.sort(function(a,b){return b.topPx-a.topPx;});return stacks;},drawToolTip_(rect){if(!this.enableToolTip)return;const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.tooltip').remove();const labelText='View Breakdown';const labelWidth=tr.ui.b.getSVGTextSize(this.chartAreaElement,labelText).width+5;const labelHeight=this.textHeightPx_;const toolTipLeftPx=rect.leftPx+(rect.widthPx/2);const toolTipTopPx=rect.topPx;chartAreaSel.append('rect').attr('class','tooltip').attr('fill','white').attr('opacity',0.8).attr('stroke','black').attr('x',toolTipLeftPx).attr('y',toolTipTopPx).attr('width',labelWidth+5).attr('height',labelHeight+10);chartAreaSel.append('text').style('cursor','pointer').attr('class','tooltip').on('mousedown',()=>this.toolTipCallBack_(rect)).attr('fill','blue').attr('x',toolTipLeftPx+4).attr('y',toolTipTopPx+labelHeight).attr('text-decoration','underline').text(labelText);},drawHoverValueBox_(rect){const rectHoverEvent=new tr.b.Event('rect-mouseenter');rectHoverEvent.rect=rect;this.dispatchEvent(rectHoverEvent);if(!this.enableHoverBox)return;const seriesKeys=[...this.seriesByKey_.keys()];const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.hover').remove();let keyWidthPx=0;let keyHeightPx=0;if(seriesKeys.length>1&&!this.isGrouped){keyWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.key).width+5;keyHeightPx=this.textHeightPx_;}
+let xLabelWidthPx=0;let xLabelHeightPx=0;if(this.displayXInHover){xLabelWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.datum.x).width+5;xLabelHeightPx=this.textHeightPx_;}
+let groupWidthPx=0;let groupHeightPx=0;if(this.isGrouped&&rect.datum.group!==undefined){groupWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.datum.group).width+5;groupHeightPx=this.textHeightPx_;}
+let value=rect.value;if(this.unit)value=this.unit.format(value);const valueWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,value).width+5;const valueHeightPx=this.textHeightPx_;const hoverWidthPx=Math.max(keyWidthPx,valueWidthPx,xLabelWidthPx,groupWidthPx);let hoverLeftPx=rect.leftPx+(rect.widthPx/2);hoverLeftPx=Math.max(hoverLeftPx-hoverWidthPx,-this.margin.left);const hoverHeightPx=keyHeightPx+valueHeightPx+
+xLabelHeightPx+groupHeightPx+2;const topOffSetPx=this.isGrouped?36:12;let hoverTopPx=rect.topPx;hoverTopPx=Math.min(hoverTopPx,this.getBoundingClientRect().height-
+hoverHeightPx-topOffSetPx);chartAreaSel.append('rect').attr('class','hover').on('mouseleave',()=>this.clearHoverValueBox_(rect)).on('mousedown',this.drawToolTip_.bind(this,rect)).attr('fill','white').attr('stroke','black').attr('x',hoverLeftPx).attr('y',hoverTopPx).attr('width',hoverWidthPx).attr('height',hoverHeightPx);if(seriesKeys.length>1&&!this.isGrouped){chartAreaSel.append('text').attr('class','hover').on('mouseleave',()=>this.clearHoverValueBox_(rect)).on('mousedown',this.drawToolTip_.bind(this,rect)).attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx-2).text(rect.key);}
+if(this.displayXInHover){chartAreaSel.append('text').attr('class','hover').on('mouseleave',()=>this.clearHoverValueBox_(rect)).on('mousedown',this.drawToolTip_.bind(this,rect)).attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+xLabelHeightPx-2).text(rect.datum.x);}
+if(this.isGrouped&&rect.datum.group!==undefined){chartAreaSel.append('text').attr('class','hover').on('mouseleave',()=>this.clearHoverValueBox_(rect)).on('mousedown',this.drawToolTip_.bind(this,rect)).attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+
+xLabelHeightPx+groupHeightPx-2).text(rect.datum.group);}
+chartAreaSel.append('text').attr('class','hover').on('mouseleave',()=>this.clearHoverValueBox_(rect)).on('mousedown',this.drawToolTip_.bind(this,rect)).attr('fill',rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+hoverHeightPx-2).text(value);},clearHoverValueBox_(rect){const event=window.event;if(event.relatedTarget&&Array.from(event.relatedTarget.classList).includes('hover')){return;}
+const rectHoverEvent=new tr.b.Event('rect-mouseleave');rectHoverEvent.rect=rect;this.dispatchEvent(rectHoverEvent);d3.select(this.chartAreaElement).selectAll('.hover').remove();},drawRect_(rect,sel){sel=sel.data([rect]);sel.enter().append('rect').attr('fill',rect.color).attr('x',rect.leftPx).attr('y',rect.topPx).attr('width',rect.widthPx).attr('height',rect.heightPx).on('mousedown',this.drawToolTip_.bind(this,rect)).on('mouseenter',this.drawHoverValueBox_.bind(this,rect)).on('mouseleave',this.clearHoverValueBox_.bind(this,rect));sel.exit().remove();},drawUnderflow_(rect,sel){sel=sel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',rect.leftPx+(rect.widthPx/2)).attr('y',this.graphHeight).on('mousedown',this.drawToolTip_.bind(this,rect)).on('mouseenter',this.drawHoverValueBox_.bind(this,rect)).on('mouseleave',this.clearHoverValueBox_.bind(this,rect));sel.exit().remove();},drawOverflow_(rect,sel){sel=sel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',rect.leftPx+(rect.widthPx/2)).attr('y',0);sel.exit().remove();},updateDataContents_(dataSel){dataSel.selectAll('*').remove();const chartAreaSel=d3.select(this.chartAreaElement);const seriesKeys=[...this.seriesByKey_.keys()];const rectsSel=dataSel.selectAll('path');this.data_.forEach(function(datum,index){const currentX=this.getXForDatum_(datum,index);let width=undefined;if(index<(this.data_.length-1)){const nextX=this.getXForDatum_(this.data_[index+1],index+1);width=nextX-currentX;}else{width=this.xCushion_;}
+for(const rect of this.getRectsForDatum_(datum,index)){rect.datum=datum;rect.index=index;rect.leftPx=this.xScale_(currentX);rect.rightPx=this.xScale_(currentX+width);rect.widthPx=rect.rightPx-rect.leftPx;this.drawRect_(rect,rectsSel);if(rect.underflow){this.drawUnderflow_(rect,rectsSel);}
+if(rect.overflow){this.drawOverflow_(rect,rectsSel);}}},this);}};return{ColumnChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const LineChart=tr.ui.b.define('line-chart',tr.ui.b.ChartBase2DBrushX);LineChart.prototype={__proto__:tr.ui.b.ChartBase2DBrushX.prototype,decorate(){super.decorate();this.enableHoverBox=true;this.displayXInHover=false;},get defaultGraphWidth(){return 20*this.data_.length;},get defaultGraphHeight(){return 100;},drawHoverValueBox_(circle){tr.ui.b.ColumnChart.prototype.drawHoverValueBox_.call(this,circle);},clearHoverValueBox_(circle){tr.ui.b.ColumnChart.prototype.clearHoverValueBox_.call(this,circle);},updateDataContents_(dataSel){dataSel.selectAll('*').remove();const dataBySeriesKey=this.getDataBySeriesKey_();const seriesKeys=[...this.seriesByKey_.keys()];const pathsSel=dataSel.selectAll('path').data(seriesKeys);pathsSel.enter().append('path').style('fill','none').style('stroke-width','1.5px').style('stroke',key=>this.getDataSeries(key).color).attr('d',key=>{const line=d3.svg.line().x(d=>this.xScale_(d.x)).y(d=>this.yScale_(this.dataRange.clamp(d[key])));return line(dataBySeriesKey[key]);});pathsSel.exit().remove();if(this.enableHoverBox){for(let index=0;index<this.data_.length;++index){const datum=this.data_[index];const x=this.getXForDatum_(datum,index);for(const[key,value]of Object.entries(datum)){if(key==='x')continue;if(value===undefined)continue;const color=this.getDataSeries(key).color;const circle=document.createElementNS('http://www.w3.org/2000/svg','circle');circle.setAttribute('cx',this.xScale_(x));circle.setAttribute('cy',this.yScale_(this.dataRange.clamp(value)));circle.setAttribute('r',5);circle.style.fill=color;circle.datum=datum;circle.key=key;circle.value=datum[key];circle.leftPx=this.xScale_(x);circle.widthPx=0;circle.color=color;circle.topPx=this.yScale_(this.dataRange.clamp(value));circle.heightPx=0;circle.addEventListener('mouseenter',()=>this.drawHoverValueBox_(circle));circle.addEventListener('mouseleave',()=>this.clearHoverValueBox_(circle));dataSel[0][0].appendChild(circle);}}}}};return{LineChart,};});'use strict';Polymer({is:'tr-ui-e-s-input-latency-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.rangeOfInterest_=new tr.b.math.Range();this.frametimeType_=tr.model.helpers.IMPL_FRAMETIME_TYPE;this.latencyChart_=undefined;this.frametimeChart_=undefined;this.selectedProcessId_=undefined;this.mouseDownIndex_=undefined;this.curMouseIndex_=undefined;},get model(){return this.model_;},set model(model){this.model_=model;if(this.model_){this.modelHelper_=this.model_.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);}else{this.modelHelper_=undefined;}
+this.updateToolbar_();this.updateContents_();},get frametimeType(){return this.frametimeType_;},set frametimeType(type){if(this.frametimeType_===type)return;this.frametimeType_=type;this.updateContents_();},get selectedProcessId(){return this.selectedProcessId_;},set selectedProcessId(process){if(this.selectedProcessId_===process)return;this.selectedProcessId_=process;this.updateContents_();},set selection(selection){if(this.latencyChart_===undefined)return;this.latencyChart_.brushedRange=selection.bounds;},setBrushedIndices(mouseDownIndex,curIndex){this.mouseDownIndex_=mouseDownIndex;this.curMouseIndex_=curIndex;this.updateBrushedRange_();},updateBrushedRange_(){if(this.latencyChart_===undefined)return;let r=new tr.b.math.Range();if(this.mouseDownIndex_===undefined){this.latencyChart_.brushedRange=r;return;}
+r=this.latencyChart_.computeBrushRangeFromIndices(this.mouseDownIndex_,this.curMouseIndex_);this.latencyChart_.brushedRange=r;let latencySlices=[];for(const thread of this.model_.getAllThreads()){for(const event of thread.getDescendantEvents()){if(event.title.indexOf('InputLatency:')===0){latencySlices.push(event);}}}
+latencySlices=tr.model.helpers.getSlicesIntersectingRange(r,latencySlices);const event=new tr.model.RequestSelectionChangeEvent();event.selection=new tr.model.EventSet(latencySlices);this.latencyChart_.dispatchEvent(event);},registerMouseEventForLatencyChart_(){this.latencyChart_.addEventListener('item-mousedown',function(e){this.mouseDownIndex_=e.index;this.curMouseIndex_=e.index;this.updateBrushedRange_();}.bind(this));this.latencyChart_.addEventListener('item-mousemove',function(e){if(e.button===undefined)return;this.curMouseIndex_=e.index;this.updateBrushedRange_();}.bind(this));this.latencyChart_.addEventListener('item-mouseup',function(e){this.curMouseIndex=e.index;this.updateBrushedRange_();}.bind(this));},updateToolbar_(){const browserProcess=this.modelHelper_.browserProcess;const labels=[];if(browserProcess!==undefined){const labelStr='Browser: '+browserProcess.pid;labels.push({label:labelStr,value:browserProcess.pid});}
+for(const rendererHelper of
+Object.values(this.modelHelper_.rendererHelpers)){const rendererProcess=rendererHelper.process;const labelStr='Renderer: '+rendererProcess.userFriendlyName;labels.push({label:labelStr,value:rendererProcess.userFriendlyName});}
+if(labels.length===0)return;this.selectedProcessId_=labels[0].value;const toolbarEl=this.$.toolbar;Polymer.dom(toolbarEl).appendChild(tr.ui.b.createSelector(this,'frametimeType','inputLatencySidePanel.frametimeType',this.frametimeType_,[{label:'Main Thread Frame Times',value:tr.model.helpers.MAIN_FRAMETIME_TYPE},{label:'Impl Thread Frame Times',value:tr.model.helpers.IMPL_FRAMETIME_TYPE}]));Polymer.dom(toolbarEl).appendChild(tr.ui.b.createSelector(this,'selectedProcessId','inputLatencySidePanel.selectedProcessId',this.selectedProcessId_,labels));},get currentRangeOfInterest(){if(this.rangeOfInterest_.isEmpty){return this.model_.bounds;}
+return this.rangeOfInterest_;},createLatencyLineChart(data,title,parentNode){const chart=new tr.ui.b.LineChart();Polymer.dom(parentNode).appendChild(chart);let width=600;if(document.body.clientWidth!==undefined){width=document.body.clientWidth*0.5;}
+chart.graphWidth=width;chart.chartTitle=title;chart.data=data;return chart;},updateContents_(){const resultArea=this.$.result_area;this.latencyChart_=undefined;this.frametimeChart_=undefined;Polymer.dom(resultArea).textContent='';if(this.modelHelper_===undefined)return;const rangeOfInterest=this.currentRangeOfInterest;let chromeProcess;if(this.modelHelper_.rendererHelpers[this.selectedProcessId_]){chromeProcess=this.modelHelper_.rendererHelpers[this.selectedProcessId_];}else{chromeProcess=this.modelHelper_.browserHelper;}
+const frameEvents=chromeProcess.getFrameEventsInRange(this.frametimeType,rangeOfInterest);const frametimeData=tr.model.helpers.getFrametimeDataFromEvents(frameEvents);const averageFrametime=tr.b.math.Statistics.mean(frametimeData,d=>d.frametime);const latencyEvents=this.modelHelper_.browserHelper.getLatencyEventsInRange(rangeOfInterest);const latencyData=[];latencyEvents.forEach(function(event){if(event.inputLatency===undefined)return;latencyData.push({x:event.start,latency:event.inputLatency/1000});});const averageLatency=tr.b.math.Statistics.mean(latencyData,function(d){return d.latency;});const latencySummaryText=document.createElement('div');Polymer.dom(latencySummaryText).appendChild(tr.ui.b.createSpan({textContent:'Average Latency '+averageLatency+' ms',bold:true}));Polymer.dom(resultArea).appendChild(latencySummaryText);const frametimeSummaryText=document.createElement('div');Polymer.dom(frametimeSummaryText).appendChild(tr.ui.b.createSpan({textContent:'Average Frame Time '+averageFrametime+' ms',bold:true}));Polymer.dom(resultArea).appendChild(frametimeSummaryText);if(latencyData.length!==0){this.latencyChart_=this.createLatencyLineChart(latencyData,'Latency Over Time',resultArea);this.registerMouseEventForLatencyChart_();}
+if(frametimeData.length!==0){this.frametimeChart_=this.createLatencyLineChart(frametimeData,'Frame Times',resultArea);}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(rangeOfInterest){this.rangeOfInterest_=rangeOfInterest;this.updateContents_();},supportsModel(m){if(m===undefined){return{supported:false,reason:'Unknown tracing model'};}
+if(!tr.model.helpers.ChromeModelHelper.supportsModel(m)){return{supported:false,reason:'No Chrome browser or renderer process found'};}
+const modelHelper=m.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper.browserHelper&&modelHelper.browserHelper.hasLatencyEvents){return{supported:true};}
+return{supported:false,reason:'No InputLatency events trace. Consider enabling '+'benchmark" and "input" category when recording the trace'};},get textLabel(){return'Input Latency';}});tr.ui.side_panel.SidePanelRegistry.register(function(){return document.createElement('tr-ui-e-s-input-latency-side-panel');});'use strict';tr.exportTo('tr.e.system_stats',function(){const ObjectSnapshot=tr.model.ObjectSnapshot;function SystemStatsSnapshot(objectInstance,ts,args){ObjectSnapshot.apply(this,arguments);this.objectInstance=objectInstance;this.ts=ts;this.args=args;this.stats_=args;}
+SystemStatsSnapshot.prototype={__proto__:ObjectSnapshot.prototype,initialize(){if(this.args.length===0){throw new Error('No system stats snapshot data.');}
+this.stats_=this.args;},getStats(){return this.stats_;},setStats(stats){this.stats_=stats;}};ObjectSnapshot.subTypes.register(SystemStatsSnapshot,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsSnapshot,};});'use strict';tr.exportTo('tr.ui.b',function(){const constants={HEADING_WIDTH:250};return{constants,};});'use strict';Polymer({is:'tr-ui-b-heading',DOWN_ARROW:String.fromCharCode(0x25BE),RIGHT_ARROW:String.fromCharCode(0x25B8),ready(viewport){this.style.width=(tr.ui.b.constants.HEADING_WIDTH-6)+'px';this.heading_='';this.expanded_=true;this.arrowVisible_=false;this.selectionGenerator_=undefined;this.updateContents_();},get heading(){return this.heading_;},set heading(text){if(this.heading_===text)return;this.heading_=text;this.updateContents_();},set arrowVisible(val){if(this.arrowVisible_===val)return;this.arrowVisible_=!!val;this.updateContents_();},set tooltip(text){this.$.heading.title=text;},set selectionGenerator(generator){if(this.selectionGenerator_===generator)return;this.selectionGenerator_=generator;this.updateContents_();},get expanded(){return this.expanded_;},set expanded(expanded){if(this.expanded_===expanded)return;this.expanded_=!!expanded;this.updateContents_();},onHeadingDivClicked_(){this.dispatchEvent(new tr.b.Event('heading-clicked',true));},updateContents_(){if(this.arrowVisible_){this.$.arrow.style.display='';}else{this.$.arrow.style.display='none';this.$.heading.style.display=this.expanded_?'':'none';}
+if(this.arrowVisible_){Polymer.dom(this.$.arrow).textContent=this.expanded_?this.DOWN_ARROW:this.RIGHT_ARROW;}
+this.$.link.style.display='none';this.$.heading_content.style.display='none';if(this.selectionGenerator_){this.$.link.style.display='inline-block';this.$.link.selection=this.selectionGenerator_;Polymer.dom(this.$.link).textContent=this.heading_;}else{this.$.heading_content.style.display='inline-block';Polymer.dom(this.$.heading_content).textContent=this.heading_;}}});'use strict';tr.exportTo('tr.ui.tracks',function(){const Track=tr.ui.b.define('track',tr.ui.b.ContainerThatDecoratesItsChildren);Track.prototype={__proto__:tr.ui.b.ContainerThatDecoratesItsChildren.prototype,decorate(viewport){tr.ui.b.ContainerThatDecoratesItsChildren.prototype.decorate.call(this);if(viewport===undefined){throw new Error('viewport is required when creating a Track.');}
+this.viewport_=viewport;Polymer.dom(this).classList.add('track');},get viewport(){return this.viewport_;},get drawingContainer(){if(this instanceof tr.ui.tracks.DrawingContainer)return this;let cur=this.parentElement;while(cur){if(cur instanceof tr.ui.tracks.DrawingContainer)return cur;cur=cur.parentElement;}
+return undefined;},get eventContainer(){},invalidateDrawingContainer(){const dc=this.drawingContainer;if(dc)dc.invalidate();},context(){if(!Polymer.dom(this).parentNode)return undefined;if(!Polymer.dom(this).parentNode.context){throw new Error('Parent container does not support context() method.');}
+return Polymer.dom(this).parentNode.context();},decorateChild_(childTrack){},undecorateChild_(childTrack){if(childTrack.detach){childTrack.detach();}},updateContents_(){},drawTrack(type){const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));const dt=this.viewport.currentDisplayTransform;const viewLWorld=dt.xViewToWorld(0);const viewRWorld=dt.xViewToWorld(canvasBounds.width*pixelRatio);const viewHeight=bounds.height*pixelRatio;this.draw(type,viewLWorld,viewRWorld,viewHeight);ctx.restore();},draw(type,viewLWorld,viewRWorld,viewHeight){},addEventsToTrackMap(eventToTrackMap){},addContainersToTrackMap(containerToTrackMap){},addIntersectingEventsInRangeToSelection(loVX,hiVX,loVY,hiVY,selection){const pixelRatio=window.devicePixelRatio||1;const dt=this.viewport.currentDisplayTransform;const viewPixWidthWorld=dt.xViewVectorToWorld(1);const loWX=dt.xViewToWorld(loVX*pixelRatio);const hiWX=dt.xViewToWorld(hiVX*pixelRatio);const clientRect=this.getBoundingClientRect();const a=Math.max(loVY,clientRect.top);const b=Math.min(hiVY,clientRect.bottom);if(a>b)return;this.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){},addClosestInstantEventToSelection(instantEvents,worldX,worldMaxDist,selection){const instantEvent=tr.b.findClosestElementInSortedArray(instantEvents,function(x){return x.start;},worldX,worldMaxDist);if(!instantEvent)return;selection.push(instantEvent);}};return{Track,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SelectionState=tr.model.SelectionState;const EventPresenter=tr.ui.b.EventPresenter;const ObjectInstanceTrack=tr.ui.b.define('object-instance-track',tr.ui.tracks.Track);ObjectInstanceTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('object-instance-track');this.objectInstances_=[];this.objectSnapshots_=[];this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},set heading(heading){this.heading_.heading=heading;},get heading(){return this.heading_.heading;},set tooltip(tooltip){this.heading_.tooltip=tooltip;},get objectInstances(){return this.objectInstances_;},set objectInstances(objectInstances){if(!objectInstances||objectInstances.length===0){this.heading='';this.objectInstances_=[];this.objectSnapshots_=[];return;}
+this.heading=objectInstances[0].baseTypeName;this.objectInstances_=objectInstances;this.objectSnapshots_=[];this.objectInstances_.forEach(function(instance){this.objectSnapshots_.push.apply(this.objectSnapshots_,instance.snapshots);},this);this.objectSnapshots_.sort(function(a,b){return a.ts-b.ts;});},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get snapshotRadiusView(){return 7*(window.devicePixelRatio||1);},draw(type,viewLWorld,viewRWorld,viewHeight){switch(type){case tr.ui.tracks.DrawType.GENERAL_EVENT:this.drawObjectInstances_(viewLWorld,viewRWorld);break;}},drawObjectInstances_(viewLWorld,viewRWorld){const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const height=bounds.height*pixelRatio;const halfHeight=height*0.5;const twoPi=Math.PI*2;const dt=this.viewport.currentDisplayTransform;const snapshotRadiusView=this.snapshotRadiusView;const snapshotRadiusWorld=dt.xViewVectorToWorld(height);const objectInstances=this.objectInstances_;let loI=tr.b.findLowIndexInSortedArray(objectInstances,function(instance){return instance.deletionTs;},viewLWorld);ctx.save();ctx.strokeStyle='rgb(0,0,0)';for(let i=loI;i<objectInstances.length;++i){const instance=objectInstances[i];const x=instance.creationTs;if(x>viewRWorld)break;const right=instance.deletionTs===Number.MAX_VALUE?viewRWorld:instance.deletionTs;const xView=dt.xWorldToView(x);const widthView=dt.xWorldVectorToView(right-x);ctx.fillStyle=EventPresenter.getObjectInstanceColor(instance);ctx.fillRect(xView,pixelRatio,widthView,height-2*pixelRatio);}
+ctx.restore();const objectSnapshots=this.objectSnapshots_;loI=tr.b.findLowIndexInSortedArray(objectSnapshots,function(snapshot){return snapshot.ts+snapshotRadiusWorld;},viewLWorld);for(let i=loI;i<objectSnapshots.length;++i){const snapshot=objectSnapshots[i];const x=snapshot.ts;if(x-snapshotRadiusWorld>viewRWorld)break;const xView=dt.xWorldToView(x);ctx.fillStyle=EventPresenter.getObjectSnapshotColor(snapshot);ctx.beginPath();ctx.arc(xView,halfHeight,snapshotRadiusView,0,twoPi);ctx.fill();if(snapshot.selected){ctx.lineWidth=5;ctx.strokeStyle='rgb(100,100,0)';ctx.stroke();ctx.beginPath();ctx.arc(xView,halfHeight,snapshotRadiusView-1,0,twoPi);ctx.lineWidth=2;ctx.strokeStyle='rgb(255,255,0)';ctx.stroke();}else{ctx.lineWidth=1;ctx.strokeStyle='rgb(0,0,0)';ctx.stroke();}}
+ctx.lineWidth=1;let selectionState=SelectionState.NONE;if(objectInstances.length&&objectInstances[0].selectionState===SelectionState.DIMMED){selectionState=SelectionState.DIMMED;}
+if(selectionState===SelectionState.DIMMED){const width=bounds.width*pixelRatio;ctx.fillStyle='rgba(255,255,255,0.5)';ctx.fillRect(0,0,width,height);ctx.restore();}},addEventsToTrackMap(eventToTrackMap){if(this.objectInstance_!==undefined){this.objectInstance_.forEach(function(obj){eventToTrackMap.addEvent(obj,this);},this);}
+if(this.objectSnapshots_!==undefined){this.objectSnapshots_.forEach(function(obj){eventToTrackMap.addEvent(obj,this);},this);}},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){let foundSnapshot=false;function onSnapshot(snapshot){selection.push(snapshot);foundSnapshot=true;}
+const snapshotRadiusView=this.snapshotRadiusView;const snapshotRadiusWorld=viewPixWidthWorld*snapshotRadiusView;tr.b.iterateOverIntersectingIntervals(this.objectSnapshots_,function(x){return x.ts-snapshotRadiusWorld;},function(x){return 2*snapshotRadiusWorld;},loWX,hiWX,onSnapshot);if(foundSnapshot)return;tr.b.iterateOverIntersectingIntervals(this.objectInstances_,function(x){return x.creationTs;},function(x){return x.deletionTs-x.creationTs;},loWX,hiWX,(value)=>{selection.push(value);});},addEventNearToProvidedEventToSelection(event,offset,selection){let events;if(event instanceof tr.model.ObjectSnapshot){events=this.objectSnapshots_;}else if(event instanceof tr.model.ObjectInstance){events=this.objectInstances_;}else{throw new Error('Unrecognized event');}
+const index=events.indexOf(event);const newIndex=index+offset;if(newIndex>=0&&newIndex<events.length){selection.push(events[newIndex]);return true;}
+return false;},addAllEventsMatchingFilterToSelection(filter,selection){},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){const snapshot=tr.b.findClosestElementInSortedArray(this.objectSnapshots_,function(x){return x.ts;},worldX,worldMaxDist);if(!snapshot)return;selection.push(snapshot);}};const options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);tr.b.decorateExtensionRegistry(ObjectInstanceTrack,options);return{ObjectInstanceTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const StackedBarsTrack=tr.ui.b.define('stacked-bars-track',tr.ui.tracks.Track);StackedBarsTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('stacked-bars-track');this.objectInstance_=null;this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},set heading(heading){this.heading_.heading=heading;},get heading(){return this.heading_.heading;},set tooltip(tooltip){this.heading_.tooltip=tooltip;},addEventsToTrackMap(eventToTrackMap){const objectSnapshots=this.objectInstance_.snapshots;objectSnapshots.forEach(function(obj){eventToTrackMap.addEvent(obj,this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){function onSnapshot(snapshot){selection.push(snapshot);}
+const snapshots=this.objectInstance_.snapshots;const maxBounds=this.objectInstance_.parent.model.bounds.max;tr.b.iterateOverIntersectingIntervals(snapshots,function(x){return x.ts;},function(x,i){if(i===snapshots.length-1){if(snapshots.length===1){return maxBounds;}
+return snapshots[i].ts-snapshots[i-1].ts;}
+return snapshots[i+1].ts-snapshots[i].ts;},loWX,hiWX,onSnapshot);},addEventNearToProvidedEventToSelection(event,offset,selection){if(!(event instanceof tr.model.ObjectSnapshot)){throw new Error('Unrecognized event');}
+const objectSnapshots=this.objectInstance_.snapshots;const index=objectSnapshots.indexOf(event);const newIndex=index+offset;if(newIndex>=0&&newIndex<objectSnapshots.length){selection.push(objectSnapshots[newIndex]);return true;}
+return false;},addAllEventsMatchingFilterToSelection(filter,selection){},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){const snapshot=tr.b.findClosestElementInSortedArray(this.objectInstance_.snapshots,function(x){return x.ts;},worldX,worldMaxDist);if(!snapshot)return;selection.push(snapshot);}};return{StackedBarsTrack,};});'use strict';tr.exportTo('tr.ui.e.system_stats',function(){const EventPresenter=tr.ui.b.EventPresenter;let statCount;const excludedStats={'meminfo':{'pswpin':0,'pswpout':0,'pgmajfault':0},'diskinfo':{'io':0,'io_time':0,'read_time':0,'reads':0,'reads_merged':0,'sectors_read':0,'sectors_written':0,'weighted_io_time':0,'write_time':0,'writes':0,'writes_merged':0},'swapinfo':{},'perfinfo':{'idle_time':0,'read_transfer_count':0,'write_transfer_count':0,'other_transfer_count':0,'read_operation_count':0,'write_operation_count':0,'other_operation_count':0,'pagefile_pages_written':0,'pagefile_pages_write_ios':0,'available_pages':0,'pages_read':0,'page_read_ios':0}};const SystemStatsInstanceTrack=tr.ui.b.define('tr-ui-e-system-stats-instance-track',tr.ui.tracks.StackedBarsTrack);const kPageSizeWindows=4096;SystemStatsInstanceTrack.prototype={__proto__:tr.ui.tracks.StackedBarsTrack.prototype,decorate(viewport){tr.ui.tracks.StackedBarsTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('tr-ui-e-system-stats-instance-track');this.objectInstance_=null;},set objectInstances(objectInstances){if(!objectInstances){this.objectInstance_=[];return;}
+if(objectInstances.length!==1){throw new Error('Bad object instance count.');}
+this.objectInstance_=objectInstances[0];if(this.objectInstance_!==null){this.computeRates_(this.objectInstance_.snapshots);this.maxStats_=this.computeMaxStats_(this.objectInstance_.snapshots);}},computeRates_(snapshots){for(let i=0;i<snapshots.length;i++){const snapshot=snapshots[i];const stats=snapshot.getStats();let prevSnapshot;if(i===0){prevSnapshot=snapshots[0];}else{prevSnapshot=snapshots[i-1];}
+const prevStats=prevSnapshot.getStats();let timeIntervalSeconds=(snapshot.ts-prevSnapshot.ts)/1000;if(timeIntervalSeconds===0){timeIntervalSeconds=1;}
+this.computeRatesRecursive_(prevStats,stats,timeIntervalSeconds);}},computeRatesRecursive_(prevStats,stats,timeIntervalSeconds){for(const statName in stats){if(stats[statName]instanceof Object){this.computeRatesRecursive_(prevStats[statName],stats[statName],timeIntervalSeconds);}else{if(statName==='sectors_read'){stats.bytes_read_per_sec=(stats.sectors_read-
+prevStats.sectors_read)*512/timeIntervalSeconds;}
+if(statName==='sectors_written'){stats.bytes_written_per_sec=(stats.sectors_written-
+prevStats.sectors_written)*512/timeIntervalSeconds;}
+if(statName==='pgmajfault'){stats.pgmajfault_per_sec=(stats.pgmajfault-
+prevStats.pgmajfault)/timeIntervalSeconds;}
+if(statName==='pswpin'){stats.bytes_swpin_per_sec=(stats.pswpin-
+prevStats.pswpin)*1000/timeIntervalSeconds;}
+if(statName==='pswpout'){stats.bytes_swpout_per_sec=(stats.pswpout-
+prevStats.pswpout)*1000/timeIntervalSeconds;}
+if(statName==='idle_time'){const units=tr.b.convertUnit(100.,tr.b.UnitScale.TIME.NANO_SEC,tr.b.UnitScale.TIME.SEC);const idleTile=(stats.idle_time-prevStats.idle_time)*units;stats.idle_time_per_sec=idleTile/timeIntervalSeconds;}
+if(statName==='read_transfer_count'){const bytesRead=stats.read_transfer_count-
+prevStats.read_transfer_count;stats.bytes_read_per_sec=bytesRead/timeIntervalSeconds;}
+if(statName==='write_transfer_count'){const bytesWritten=stats.write_transfer_count-
+prevStats.write_transfer_count;stats.bytes_written_per_sec=bytesWritten/timeIntervalSeconds;}
+if(statName==='other_transfer_count'){const bytesTransfer=stats.other_transfer_count-
+prevStats.other_transfer_count;stats.bytes_other_per_sec=bytesTransfer/timeIntervalSeconds;}
+if(statName==='read_operation_count'){const readOperation=stats.read_operation_count-
+prevStats.read_operation_count;stats.read_operation_per_sec=readOperation/timeIntervalSeconds;}
+if(statName==='write_operation_count'){const writeOperation=stats.write_operation_count-
+prevStats.write_operation_count;stats.write_operation_per_sec=writeOperation/timeIntervalSeconds;}
+if(statName==='other_operation_count'){const otherOperation=stats.other_operation_count-
+prevStats.other_operation_count;stats.other_operation_per_sec=otherOperation/timeIntervalSeconds;}
+if(statName==='pagefile_pages_written'){const pageFileBytesWritten=(stats.pagefile_pages_written-
+prevStats.pagefile_pages_written)*kPageSizeWindows;stats.pagefile_bytes_written_per_sec=pageFileBytesWritten/timeIntervalSeconds;}
+if(statName==='pagefile_pages_write_ios'){const pagefileWriteOperation=stats.pagefile_pages_write_ios-
+prevStats.pagefile_pages_write_ios;stats.pagefile_write_operation_per_sec=pagefileWriteOperation/timeIntervalSeconds;}
+if(statName==='available_pages'){stats.available_pages_in_bytes=stats.available_pages*kPageSizeWindows;}
+if(statName==='pages_read'){const pagesBytesRead=(stats.pages_read-prevStats.pages_read)*kPageSizeWindows;stats.bytes_read_per_sec=pagesBytesRead/timeIntervalSeconds;}
+if(statName==='page_read_ios'){const pagesBytesReadOperations=stats.page_read_ios-prevStats.page_read_ios;stats.pagefile_write_operation_per_sec=pagesBytesReadOperations/timeIntervalSeconds;}}}},computeMaxStats_(snapshots){const maxStats={};statCount=0;for(let i=0;i<snapshots.length;i++){const snapshot=snapshots[i];const stats=snapshot.getStats();this.computeMaxStatsRecursive_(stats,maxStats,excludedStats);}
+return maxStats;},computeMaxStatsRecursive_(stats,maxStats,excludedStats){for(const statName in stats){if(stats[statName]instanceof Object){if(!(statName in maxStats)){maxStats[statName]={};}
+let excludedNested;if(excludedStats&&statName in excludedStats){excludedNested=excludedStats[statName];}else{excludedNested=null;}
+this.computeMaxStatsRecursive_(stats[statName],maxStats[statName],excludedNested);}else{if(excludedStats&&statName in excludedStats){continue;}
+if(!(statName in maxStats)){maxStats[statName]=0;statCount++;}
+if(stats[statName]>maxStats[statName]){maxStats[statName]=stats[statName];}}}},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},draw(type,viewLWorld,viewRWorld,viewHeight){switch(type){case tr.ui.tracks.DrawType.GENERAL_EVENT:this.drawStatBars_(viewLWorld,viewRWorld);break;}},drawStatBars_(viewLWorld,viewRWorld){const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const width=bounds.width*pixelRatio;const height=(bounds.height*pixelRatio)/statCount;const vp=this.viewport.currentDisplayTransform;const maxStats=this.maxStats_;const objectSnapshots=this.objectInstance_.snapshots;let lowIndex=tr.b.findLowIndexInSortedArray(objectSnapshots,function(snapshot){return snapshot.ts;},viewLWorld);if(lowIndex>0)lowIndex-=1;for(let i=lowIndex;i<objectSnapshots.length;++i){const snapshot=objectSnapshots[i];const trace=snapshot.getStats();const currentY=height;const left=snapshot.ts;if(left>viewRWorld)break;let leftView=vp.xWorldToView(left);if(leftView<0)leftView=0;let right;if(i!==objectSnapshots.length-1){right=objectSnapshots[i+1].ts;}else{if(objectSnapshots.length>1){right=objectSnapshots[i].ts+(objectSnapshots[i].ts-
+objectSnapshots[i-1].ts);}else{right=this.objectInstance_.parent.model.bounds.max;}}
+let rightView=vp.xWorldToView(right);if(rightView>width){rightView=width;}
+leftView=Math.floor(leftView);rightView=Math.floor(rightView);this.drawStatBarsRecursive_(snapshot,leftView,rightView,height,trace,maxStats,currentY);if(i===lowIndex){this.drawStatNames_(leftView,height,currentY,'',maxStats);}}
+ctx.lineWidth=1;},drawStatBarsRecursive_(snapshot,leftView,rightView,height,stats,maxStats,currentY){const ctx=this.context();for(const statName in maxStats){if(stats[statName]instanceof Object){currentY=this.drawStatBarsRecursive_(snapshot,leftView,rightView,height,stats[statName],maxStats[statName],currentY);}else{const maxStat=maxStats[statName];ctx.fillStyle=EventPresenter.getBarSnapshotColor(snapshot,Math.round(currentY/height));let barHeight;if(maxStat>0){barHeight=height*Math.max(stats[statName],0)/maxStat;}else{barHeight=0;}
+ctx.fillRect(leftView,currentY-barHeight,Math.max(rightView-leftView,1),barHeight);currentY+=height;}}
+return currentY;},drawStatNames_(leftView,height,currentY,prefix,maxStats){const ctx=this.context();ctx.textAlign='end';ctx.font='12px Arial';ctx.fillStyle='#000000';for(const statName in maxStats){if(maxStats[statName]instanceof Object){currentY=this.drawStatNames_(leftView,height,currentY,statName,maxStats[statName]);}else{let fullname=statName;if(prefix!==''){fullname=prefix+' :: '+statName;}
+ctx.fillText(fullname,leftView-10,currentY-height/4);currentY+=height;}}
+return currentY;}};tr.ui.tracks.ObjectInstanceTrack.register(SystemStatsInstanceTrack,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsInstanceTrack,};});'use strict';tr.exportTo('tr.ui.e.system_stats',function(){const SystemStatsSnapshotView=tr.ui.b.define('tr-ui-e-system-stats-snapshot-view',tr.ui.analysis.ObjectSnapshotView);SystemStatsSnapshotView.prototype={__proto__:tr.ui.analysis.ObjectSnapshotView.prototype,decorate(){Polymer.dom(this).classList.add('tr-ui-e-system-stats-snapshot-view');},updateContents(){const snapshot=this.objectSnapshot_;if(!snapshot||!snapshot.getStats()){Polymer.dom(this).textContent='No system stats snapshot found.';return;}
+Polymer.dom(this).textContent='';const stats=snapshot.getStats();Polymer.dom(this).appendChild(this.buildList_(stats));},isFloat(n){return typeof n==='number'&&n%1!==0;},buildList_(stats){const statList=document.createElement('ul');for(const statName in stats){const statText=document.createElement('li');Polymer.dom(statText).textContent=''+statName+': ';Polymer.dom(statList).appendChild(statText);if(stats[statName]instanceof Object){Polymer.dom(statList).appendChild(this.buildList_(stats[statName]));}else{if(this.isFloat(stats[statName])){Polymer.dom(statText).textContent+=stats[statName].toFixed(2);}else{Polymer.dom(statText).textContent+=stats[statName];}}}
+return statList;}};tr.ui.analysis.ObjectSnapshotView.register(SystemStatsSnapshotView,{typeName:'base::TraceEventSystemStatsMonitor::SystemStats'});return{SystemStatsSnapshotView,};});'use strict';tr.exportTo('tr.ui.e.v8',function(){const IGNORED_ENTRIES={match:full=>full.startsWith('*CODE_AGE_')};const INSTANCE_TYPE_GROUPS={FIXED_ARRAY_TYPE:{match:full=>full.startsWith('*FIXED_ARRAY_'),realEntry:'FIXED_ARRAY_TYPE',keyToName:key=>key.slice('*FIXED_ARRAY_'.length).slice(0,-('_SUB_TYPE'.length)),nameToKey:name=>'*FIXED_ARRAY_'+name+'_SUB_TYPE'},CODE_TYPE:{match:full=>full.startsWith('*CODE_'),realEntry:'CODE_TYPE',keyToName:key=>key.slice('*CODE_'.length),nameToKey:name=>'*CODE_'+name},JS_OBJECTS:{match:full=>full.startsWith('JS_'),keyToName:key=>key,nameToKey:name=>name},Strings:{match:full=>full.endsWith('STRING_TYPE'),keyToName:key=>key,nameToKey:name=>name},Maps:{match:full=>full.startsWith('MAP_')&&full.endsWith('_TYPE'),keyToName:key=>key,nameToKey:name=>name},DescriptorArrays:{match:full=>full.endsWith('DESCRIPTOR_ARRAY_TYPE'),keyToName:key=>key,nameToKey:name=>name}};const DIFF_COLOR={GREEN:'#64DD17',RED:'#D50000'};function computePercentage(valueA,valueB){if(valueA===0)return 0;return valueA/valueB*100;}
+class DiffEntry{constructor(originalEntry,diffEntry){this.originalEntry_=originalEntry;this.diffEntry_=diffEntry;}
+get title(){return this.diffEntry_.title;}
+get overall(){return this.diffEntry_.overall;}
+get overAllocated(){return this.diffEntry_.overAllocated;}
+get count(){return this.diffEntry_.count;}
+get overallPercent(){return this.diffEntry_.overallPercent;}
+get overAllocatedPercent(){return this.diffEntry_.overAllocatedPercent;}
+get origin(){return this.originalEntry_;}
+get diff(){return this.diffEntry_;}
+get subRows(){return this.diffEntry_.subRows;}}
+class Entry{constructor(title,count,overall,overAllocated,histogram,overAllocatedHistogram){this.title_=title;this.overall_=overall;this.count_=count;this.overAllocated_=overAllocated;this.histogram_=histogram;this.overAllocatedHistogram_=overAllocatedHistogram;this.bucketSize_=this.histogram_.length;this.overallPercent_=100;this.overAllocatedPercent_=100;}
+get title(){return this.title_;}
+get overall(){return this.overall_;}
+get count(){return this.count_;}
+get overAllocated(){return this.overAllocated_;}
+get histogram(){return this.histogram_;}
+get overAllocatedHistogram(){return this.overAllocatedHistogram_;}
+get bucketSize(){return this.bucketSize_;}
+get overallPercent(){return this.overallPercent_;}
+set overallPercent(value){this.overallPercent_=value;}
+get overAllocatedPercent(){return this.overAllocatedPercent_;}
+set overAllocatedPercent(value){this.overAllocatedPercent_=value;}
+setFromObject(obj){this.count_=obj.count;this.overall_=obj.overall/1024;this.overAllocated_=obj.over_allocated/1024;this.histogram_=obj.histogram;this.overAllocatedHistogram_=obj.over_allocated_histogram;}
+diff(other){const entry=new Entry(this.title_,other.count_-this.count,other.overall_-this.overall,other.overAllocated_-this.overAllocated,[],[]);entry.overallPercent=computePercentage(entry.overall,this.overall);entry.overAllocatedPercent=computePercentage(entry.overAllocated,this.overAllocated);return new DiffEntry(this,entry);}}
+class GroupedEntry extends Entry{constructor(title,count,overall,overAllocated,histogram,overAllocatedHistogram){super(title,count,overall,overAllocated,histogram,overAllocatedHistogram);this.histogram_.fill(0);this.overAllocatedHistogram_.fill(0);this.entries_=new Map();}
+get title(){return this.title_;}
+set title(value){this.title_=value;}
+get subRows(){return Array.from(this.entries_.values());}
+getEntryFromTitle(title){return this.entries_.get(title);}
+add(entry){this.count_+=entry.count;this.overall_+=entry.overall;this.overAllocated_+=entry.overAllocated;if(this.bucketSize_===entry.bucketSize){for(let i=0;i<this.bucketSize_;++i){this.histogram_[i]+=entry.histogram[i];this.overAllocatedHistogram_[i]+=entry.overAllocatedHistogram[i];}}
+this.entries_.set(entry.title,entry);}
+accumulateUnknown(title){let unknownCount=this.count_;let unknownOverall=this.overall_;let unknownOverAllocated=this.overAllocated_;const unknownHistogram=tr.b.deepCopy(this.histogram_);const unknownOverAllocatedHistogram=tr.b.deepCopy(this.overAllocatedHistogram_);for(const entry of this.entries_.values()){unknownCount-=entry.count;unknownOverall-=entry.overall;unknownOverAllocated-=entry.overAllocated;for(let i=0;i<this.bucketSize_;++i){unknownHistogram[i]-=entry.histogram[i];unknownOverAllocatedHistogram[i]-=entry.overAllocatedHistogram[i];}}
+unknownOverAllocated=unknownOverAllocated<0?0:unknownOverAllocated;this.entries_.set(title,new Entry(title,unknownCount,unknownOverall,unknownOverAllocated,unknownHistogram,unknownOverAllocatedHistogram));}
+calculatePercentage(){for(const entry of this.entries_.values()){entry.overallPercent=computePercentage(entry.overall,this.overall_);entry.overAllocatedPercent=computePercentage(entry.overAllocated,this.overAllocated_);if(entry instanceof GroupedEntry)entry.calculatePercentage();}}
+diff(other){let newTitle='';if(this.title_.startsWith('Isolate')){newTitle='Total';}else{newTitle=this.title_;}
+const result=new GroupedEntry(newTitle,0,0,0,[],[]);for(const entry of this.entries_){const otherEntry=other.getEntryFromTitle(entry[0]);if(otherEntry===undefined)continue;result.add(entry[1].diff(otherEntry));}
+result.overallPercent=computePercentage(result.overall,this.overall);result.overAllocatedPercent=computePercentage(result.overAllocated,this.overAllocated);return new DiffEntry(this,result);}}
+function createSelector(targetEl,defaultValue,items,callback){const selectorEl=document.createElement('select');selectorEl.addEventListener('change',callback.bind(targetEl));const defaultOptionEl=document.createElement('option');for(let i=0;i<items.length;i++){const item=items[i];const optionEl=document.createElement('option');Polymer.dom(optionEl).textContent=item.label;optionEl.targetPropertyValue=item.value;optionEl.item=item;Polymer.dom(selectorEl).appendChild(optionEl);}
+selectorEl.__defineGetter__('selectedValue',function(v){if(selectorEl.children[selectorEl.selectedIndex]===undefined){return undefined;}
+return selectorEl.children[selectorEl.selectedIndex].targetPropertyValue;});selectorEl.__defineGetter__('selectedItem',function(v){if(selectorEl.children[selectorEl.selectedIndex]===undefined){return undefined;}
+return selectorEl.children[selectorEl.selectedIndex].item;});selectorEl.__defineSetter__('selectedValue',function(v){for(let i=0;i<selectorEl.children.length;i++){const value=selectorEl.children[i].targetPropertyValue;if(value===v){const changed=selectorEl.selectedIndex!==i;if(changed){selectorEl.selectedIndex=i;callback();}
+return;}}
+throw new Error('Not a valid value');});selectorEl.selectedIndex=-1;return selectorEl;}
+function plusMinus(value,toFixed=3){return(value>0?'+':'')+value.toFixed(toFixed);}
+function addArrow(value){if(value===0)return value;if(value===Number.NEGATIVE_INFINITY)return'\u2193\u221E';if(value===Number.POSITIVE_INFINITY)return'\u2191\u221E';return(value>0?'\u2191':'\u2193')+Math.abs(value.toFixed(3));}
+Polymer({is:'tr-ui-e-v8-gc-objects-stats-table',ready(){this.$.diffOption.style.display='none';this.isolateEntries_=[];this.selector1_=undefined;this.selector2_=undefined;},constructDiffTable_(table){this.$.diffTable.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;this.$.diffTable.tableColumns=[{title:'Component',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.title;return typeEl;},showExpandButtons:true},{title:'Overall Memory(KB)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=row.origin.overall.toFixed(3);return spanEl;},cmp(a,b){return a.origin.overall-b.origin.overall;}},{title:'diff(KB)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=plusMinus(row.overall);if(row.overall>0){spanEl.style.color=DIFF_COLOR.RED;}else if(row.overall<0){spanEl.style.color=DIFF_COLOR.GREEN;}
+return spanEl;},cmp(a,b){return a.overall-b.overall;}},{title:'diff(%)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=addArrow(row.overallPercent);if(row.overall>0){spanEl.style.color=DIFF_COLOR.RED;}else if(row.overall<0){spanEl.style.color=DIFF_COLOR.GREEN;}
+return spanEl;},cmp(a,b){return a.overall-b.overall;}},{title:'Over Allocated Memory(KB)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=row.origin.overAllocated.toFixed(3);return spanEl;},cmp(a,b){return a.origin.overAllocated-b.origin.overAllocated;}},{title:'diff(KB)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=plusMinus(row.overAllocated);if(row.overAllocated>0){spanEl.style.color=DIFF_COLOR.RED;}else if(row.overAllocated<0){spanEl.style.color=DIFF_COLOR.GREEN;}
+return spanEl;},cmp(a,b){return a.overAllocated-b.overAllocated;}},{title:'diff(%)',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=addArrow(row.overAllocatedPercent);if(row.overAllocated>0){spanEl.style.color=DIFF_COLOR.RED;}else if(row.overAllocated<0){spanEl.style.color=DIFF_COLOR.GREEN;}
+return spanEl;},cmp(a,b){return a.overAllocated-b.overAllocated;}},{title:'Count',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=row.origin.count;return spanEl;},cmp(a,b){return a.origin.count-b.origin.count;}},{title:'diff',value(row){const spanEl=tr.ui.b.createSpan();spanEl.innerText=plusMinus(row.count,0);if(row.count>0){spanEl.style.color=DIFF_COLOR.RED;}else if(row.count<0){spanEl.style.color=DIFF_COLOR.GREEN;}
+return spanEl;},cmp(a,b){return a.count-b.count;}},];},buildOptions_(){const items=[];for(const isolateEntry of this.isolateEntries_){items.push({label:isolateEntry.title,value:isolateEntry});}
+this.$.diffOption.style.display='inline-block';this.selector1_=createSelector(this,'',items,this.diffOptionChanged_);Polymer.dom(this.$.diffOption).appendChild(this.selector1_);const spanEl=tr.ui.b.createSpan();spanEl.innerText=' VS ';Polymer.dom(this.$.diffOption).appendChild(spanEl);this.selector2_=createSelector(this,'',items,this.diffOptionChanged_);Polymer.dom(this.$.diffOption).appendChild(this.selector2_);},diffOptionChanged_(){const isolateEntry1=this.selector1_.selectedValue;const isolateEntry2=this.selector2_.selectedValue;if(isolateEntry1===undefined||isolateEntry2===undefined){return;}
+if(isolateEntry1===isolateEntry2){this.$.diffTable.tableRows=[];this.$.diffTable.rebuild();return;}
+this.$.diffTable.tableRows=[isolateEntry1.diff(isolateEntry2)];this.$.diffTable.rebuild();},constructTable_(){this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;this.$.table.tableColumns=[{title:'Component',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.title;return typeEl;},showExpandButtons:true},{title:'Overall Memory (KB)',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.overall.toFixed(3);return typeEl;},cmp(a,b){return a.overall-b.overall;}},{title:'Over Allocated Memory (KB)',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.overAllocated.toFixed(3);return typeEl;},cmp(a,b){return a.overAllocated-b.overAllocated;}},{title:'Overall Count',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.count;return typeEl;},cmp(a,b){return a.count-b.count;}},{title:'Overall Memory Percent',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.overallPercent.toFixed(3)+'%';return typeEl;},cmp(a,b){return a.overall-b.overall;}},{title:'Overall Allocated Memory Percent',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.overAllocatedPercent.toFixed(3)+'%';return typeEl;},cmp(a,b){return a.overAllocated-b.overAllocated;}}];this.$.table.sortColumnIndex=1;this.$.table.sortDescending=true;},buildSubEntry_(objects,groupEntry,keyToName){const typeGroup=INSTANCE_TYPE_GROUPS[groupEntry.title];for(const instanceType of typeGroup){const e=objects[instanceType];if(e===undefined)continue;delete objects[instanceType];let title=instanceType;if(keyToName!==undefined)title=keyToName(title);groupEntry.add(new Entry(title,e.count,e.overall/1024,e.over_allocated/1024,e.histogram,e.over_allocated_histogram));}},buildUnGroupedEntries_(objects,objectEntry,bucketSize){for(const title of Object.getOwnPropertyNames(objects)){const obj=objects[title];const groupedEntry=new GroupedEntry(title,0,0,0,new Array(bucketSize),new Array(bucketSize));groupedEntry.setFromObject(obj);objectEntry.add(groupedEntry);}},createGroupEntries_(groupEntries,objects,bucketSize){for(const groupName of Object.getOwnPropertyNames(INSTANCE_TYPE_GROUPS)){const groupEntry=new GroupedEntry(groupName,0,0,0,new Array(bucketSize),new Array(bucketSize));if(INSTANCE_TYPE_GROUPS[groupName].realEntry!==undefined){groupEntry.savedRealEntry=objects[INSTANCE_TYPE_GROUPS[groupName].realEntry];delete objects[INSTANCE_TYPE_GROUPS[groupName].realEntry];}
+groupEntries[groupName]=groupEntry;}},buildGroupEntries_(groupEntries,objectEntry){for(const groupName of Object.getOwnPropertyNames(groupEntries)){const groupEntry=groupEntries[groupName];if(groupEntry.savedRealEntry!==undefined){groupEntry.setFromObject(groupEntry.savedRealEntry);groupEntry.accumulateUnknown('UNKNOWN');delete groupEntry.savedRealEntry;}
+objectEntry.add(groupEntry);}},buildSubEntriesForGroups_(groupEntries,objects){for(const instanceType of Object.getOwnPropertyNames(objects)){if(IGNORED_ENTRIES.match(instanceType)){delete objects[instanceType];continue;}
+const e=objects[instanceType];for(const name of Object.getOwnPropertyNames(INSTANCE_TYPE_GROUPS)){const group=INSTANCE_TYPE_GROUPS[name];if(group.match(instanceType)){groupEntries[name].add(new Entry(group.keyToName(instanceType),e.count,e.overall/1024,e.over_allocated/1024,e.histogram,e.over_allocated_histogram));delete objects[instanceType];}}}},build_(objects,objectEntry,bucketSize){delete objects.END;const groupEntries={};this.createGroupEntries_(groupEntries,objects,bucketSize);this.buildSubEntriesForGroups_(groupEntries,objects);this.buildGroupEntries_(groupEntries,objectEntry);this.buildUnGroupedEntries_(objects,objectEntry,bucketSize);},set selection(slices){slices.sortEvents(function(a,b){return b.start-a.start;});const previous=undefined;for(const slice of slices){if(!slice instanceof tr.e.v8.V8GCStatsThreadSlice)continue;const liveObjects=slice.liveObjects;const deadObjects=slice.deadObjects;const isolate=liveObjects.isolate;const isolateEntry=new GroupedEntry('Isolate_'+isolate+' at '+slice.start.toFixed(3)+' ms',0,0,0,[],[]);const liveEntry=new GroupedEntry('live objects',0,0,0,[],[]);const deadEntry=new GroupedEntry('dead objects',0,0,0,[],[]);const liveBucketSize=liveObjects.bucket_sizes.length;const deadBucketSize=deadObjects.bucket_sizes.length;this.build_(tr.b.deepCopy(liveObjects.type_data),liveEntry,liveBucketSize);isolateEntry.add(liveEntry);this.build_(tr.b.deepCopy(deadObjects.type_data),deadEntry,deadBucketSize);isolateEntry.add(deadEntry);isolateEntry.calculatePercentage();this.isolateEntries_.push(isolateEntry);}
+this.updateTable_();if(slices.length>1){this.buildOptions_();this.constructDiffTable_();}},updateTable_(){this.constructTable_();this.$.table.tableRows=this.isolateEntries_;this.$.table.rebuild();},});return{};});'use strict';Polymer({is:'tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.gcObjectsStats.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-multi-v8-gc-stats-thread-slice-sub-view',tr.e.v8.V8GCStatsThreadSlice,{multi:true,title:'V8 GC Stats slices'});'use strict';tr.exportTo('tr.e.v8',function(){const IC_STATS_PROPERTIES=['type','category','scriptName','filePosition','state','isNative','map','propertiesMode','numberOfOwnProperties','instanceType'];class ICStatsEntry{constructor(obj){this.type_=obj.type;if(this.type_.includes('Store')){this.category_='Store';}else if(this.type_.includes('Load')){this.category_='Load';}
+this.state_=obj.state;if(obj.functionName){this.functionName_=obj.optimized?'*':'~';this.functionName_+=obj.functionName.length===0?'(anonymous function)':obj.functionName;}
+this.offset_=obj.offset;this.scriptName_=obj.scriptName?obj.scriptName:'unknown';this.isNative_=obj.scriptName&&obj.scriptName.includes('native');this.lineNum_=obj.lineNum?obj.lineNum:'unknown';this.filePosition_=this.scriptName_+':'+this.lineNum_;if(this.functionName_){this.filePosition_+=' '+this.functionName_+'+'+this.offset_;}
+this.constructor_=obj.constructor?false:true;this.map_=obj.map;if(this.map_){this.propertiesMode_=obj.dict===1?'slow':'fast';}else{this.propertiesMode_='unknown';}
+this.numberOfOwnProperties_=obj.own;this.instanceType_=obj.instanceType;this.key_=obj.key;}
+get type(){return this.type_;}
+get category(){return this.category_;}
+get state(){return this.state_;}
+get functionName(){return this.functionName_;}
+get offset(){return this.offset_;}
+get scriptName(){return this.scriptName_;}
+get isNative(){return this.isNative_;}
+get lineNumber(){return this.lineNum_;}
+get isConstructor(){return this.constructor_;}
+get map(){return this.map_;}
+get propertiesMode(){return this.propertiesMode_;}
+get numberOfOwnProperties(){return this.numberOfOwnProperties_;}
+get instanceType(){return this.instanceType_;}
+get filePosition(){return this.filePosition_;}}
+class ICStatsEntryGroup{constructor(property,key){this.property_=property;this.key_=key;this.percentage_=0;this.entries_=[];this.subGroup_=undefined;}
+static groupBy(groups,entries,property){for(const entry of entries){const key=entry[property];let group=groups.get(key);if(!group){group=new ICStatsEntryGroup(property,key);groups.set(key,group);}
+group.add(entry);}
+for(const group of groups.values()){group.percentage=group.length/entries.length;}}
+add(entry){this.entries_.push(entry);}
+createSubGroup(){if(this.subGroup_)return this.subGroup_;this.subGroup_=new Map();for(const property of IC_STATS_PROPERTIES){if(property===this.property_)continue;const groups=new Map();this.subGroup_.set(property,groups);ICStatsEntryGroup.groupBy(groups,this.entries_,property);}
+return this.subGroup_;}
+get entries(){return this.entries_;}
+get key(){return this.key_;}
+get length(){return this.entries_.length;}
+get percentage(){return this.percentage_;}
+set percentage(value){this.percentage_=value;}}
+class ICStatsCollection{constructor(){this.entries_=[];this.groupedEntries_=new Map();}
+add(entry){this.entries_.push(entry);}
+groupBy(property){if(this.groupedEntries_.has(property)){return Array.from(this.groupedEntries_.get(property).values());}
+const groups=new Map();this.groupedEntries_.set(property,groups);ICStatsEntryGroup.groupBy(groups,this.entries_,property);return Array.from(groups.values());}
+get entries(){return this.entries_;}
+get length(){return this.entries_.length;}}
+return{IC_STATS_PROPERTIES,ICStatsEntry,ICStatsEntryGroup,ICStatsCollection,};});'use strict';tr.exportTo('tr.ui.e.v8',function(){const PROPERTIES=tr.e.v8.IC_STATS_PROPERTIES.map(x=>{return{label:x,value:x};});const ICStatsEntry=tr.e.v8.ICStatsEntry;const ICStatsEntryGroup=tr.e.v8.ICStatsEntryGroup;const ICStatsCollection=tr.e.v8.ICStatsCollection;Polymer({is:'tr-ui-e-v8-ic-stats-table',ready(){this.icStatsCollection_=new ICStatsCollection();this.groupKey_=PROPERTIES[0].value;this.selector_=tr.ui.b.createSelector(this,'groupKey','v8ICStatsGroupKey',this.groupKey_,PROPERTIES);Polymer.dom(this.$.groupOption).appendChild(this.selector_);},get groupKey(){return this.groupKey_;},set groupKey(key){this.groupKey_=key;if(this.icStatsCollection_.length===0)return;this.updateTable_(this.groupKey_);},constructTable_(table,groupKey){table.tableColumns=[{title:'',value:row=>{let expanded=false;const buttonEl=tr.ui.b.createButton('details',function(){const previousSibling=Polymer.dom(this).parentNode.parentNode;const parentNode=previousSibling.parentNode;if(expanded){const trEls=parentNode.getElementsByClassName('subTable');Array.from(trEls).map(x=>x.parentNode.removeChild(x));expanded=false;return;}
+expanded=true;const subGroups=row.createSubGroup();const tr=document.createElement('tr');tr.classList.add('subTable');tr.appendChild(document.createElement('td'));const td=document.createElement('td');td.colSpan=3;for(const subGroup of subGroups){const property=subGroup[0];const all=Array.from(subGroup[1].values());const group=all.slice(0,20);const divEl=document.createElement('div');const spanEl=document.createElement('span');const subTableEl=document.createElement('tr-ui-b-table');spanEl.innerText=`Top 20 out of ${all.length}`;spanEl.style.fontWeight='bold';spanEl.style.fontSize='14px';divEl.appendChild(spanEl);this.constructTable_(subTableEl,property);subTableEl.tableRows=group;subTableEl.rebuild();divEl.appendChild(subTableEl);td.appendChild(divEl);}
+tr.appendChild(td);parentNode.insertBefore(tr,previousSibling.nextSibling);});return buttonEl;}},{title:'Percentage',value(row){const spanEl=document.createElement('span');spanEl.innerText=(row.percentage*100).toFixed(3)+'%';return spanEl;},cmp:(a,b)=>a.percentage-b.percentage},{title:'Count',value(row){const spanEl=document.createElement('span');spanEl.innerText=row.length;return spanEl;},cmp:(a,b)=>a.length-b.length},{title:groupKey,value(row){const spanEl=document.createElement('span');spanEl.innerText=row.key?row.key:'';return spanEl;}}];table.sortColumnIndex=1;table.sortDescending=true;},updateTable_(groupKey){this.constructTable_(this.$.table,groupKey);this.$.table.tableRows=this.icStatsCollection_.groupBy(groupKey);this.$.table.rebuild();},set selection(slices){for(const slice of slices){for(const icStatsObj of slice.icStats){const entry=new ICStatsEntry(icStatsObj);this.icStatsCollection_.add(entry);}}
+this.$.total.innerText='Total items: '+this.icStatsCollection_.length;this.updateTable_(this.selector_.selectedValue);}});return{};});'use strict';Polymer({is:'tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.table.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-multi-v8-ic-stats-thread-slice-sub-view',tr.e.v8.V8ICStatsThreadSlice,{multi:true,title:'V8 IC stats slices'});'use strict';tr.exportTo('tr.e.v8',function(){class RuntimeStatsEntry{constructor(name,count,time){this.name_=name;this.count_=count;this.time_=time;}
+get name(){return this.name_;}
+get count(){return this.count_;}
+get time(){return this.time_;}
+addSample(count,time){this.count_+=count;this.time_+=time;}}
+class RuntimeStatsGroup extends RuntimeStatsEntry{constructor(name,matchRegex){super(name,0,0);this.regex_=matchRegex;this.entries_=new Map();}
+match(name){return this.regex_&&name.match(this.regex_);}
+add(entry){const value=this.entries_.get(entry.name);if(value!==undefined){value.addSample(entry.count,entry.time);}else{this.entries_.set(entry.name,entry);}
+this.count_+=entry.count;this.time_+=entry.time;}
+get values(){return Array.from(this.entries_.values());}}
+class RuntimeStatsGroupCollection{constructor(){this.blink_cpp_group_=new RuntimeStatsGroup('Blink C++',/.*Callback.*/);this.api_group_=new RuntimeStatsGroup('API',/.*API.*/);this.groups_=[new RuntimeStatsGroup('Total'),new RuntimeStatsGroup('IC',/.*IC_.*/),new RuntimeStatsGroup('Optimize-Background',/(.*OptimizeBackground.*)|RecompileConcurrent.*/),new RuntimeStatsGroup('Optimize',/StackGuard|.*Optimize.*|.*Deoptimize.*|Recompile.*/),new RuntimeStatsGroup('Compile-Background',/(.*CompileBackground.*)/),new RuntimeStatsGroup('Compile',/(^Compile.*)|(.*_Compile.*)/),new RuntimeStatsGroup('Parse-Background',/.*ParseBackground.*/),new RuntimeStatsGroup('Parse',/.*Parse.*/),this.blink_cpp_group_,this.api_group_,new RuntimeStatsGroup('GC-Background-Marking',/.*GC.MC.BACKGROUND.*MARKING.*/),new RuntimeStatsGroup('GC-Background-Sweeping',/.*GC.MC.BACKGROUND.*SWEEPING.*/),new RuntimeStatsGroup('GC-Background-Scavenger',/.*GC.SCAVENGER.BACKGROUND.*/),new RuntimeStatsGroup('GC-Background-MinorMC',/.*GC.MINOR_MC.BACKGROUND.*/),new RuntimeStatsGroup('GC-Background-MajorMC',/.*GC.MC.BACKGROUND.*/),new RuntimeStatsGroup('GC-Background-Other',/.*GC.*BACKGROUND.*/),new RuntimeStatsGroup('GC',/GC|AllocateInTargetSpace/),new RuntimeStatsGroup('JavaScript',/JS_Execution/),new RuntimeStatsGroup('V8 C++',/.*/)];this.blink_group_collection_=null;}
+addSlices(slices){const blinkEntries=[];for(const slice of slices){if(!(slice instanceof tr.e.v8.V8ThreadSlice))return;let runtimeCallStats;try{runtimeCallStats=JSON.parse(slice.runtimeCallStats);}catch(e){runtimeCallStats=slice.runtimeCallStats;}
+if(runtimeCallStats===undefined)continue;for(const[name,stat]of Object.entries(runtimeCallStats)){if(name.match(/Blink_.*/)){if(name==='Blink_V8')continue;const entry=new RuntimeStatsEntry(name,stat[0],stat[1]);blinkEntries.push(entry);continue;}
+for(let i=1;i<this.groups_.length;++i){if(this.groups_[i].match(name)){if(stat.length!==2)break;const entry=new RuntimeStatsEntry(name,stat[0],stat[1]);this.groups_[0].addSample(stat[0],stat[1]);this.groups_[i].add(entry);break;}}}}
+this.blink_group_collection_=new BlinkRuntimeStatsGroupCollection(blinkEntries);}
+get totalTime(){return this.groups_[0].time;}
+get totalCount(){return this.groups_[0].count;}
+get runtimeGroups(){return this.groups_;}
+get blinkRCSGroupCollection(){return this.blink_group_collection_;}
+get blinkCppTotalTime(){return this.blink_cpp_group_.time+this.api_group_.time;}}
+class BlinkRuntimeStatsGroupCollection{constructor(entries){this.groups_=[new RuntimeStatsGroup('Blink_Bindings',/^Blink_Bindings_(.*)/),new RuntimeStatsGroup('Blink_GC',/^Blink_GC_(.*)/),new RuntimeStatsGroup('Blink_Layout',/^Blink_Layout_(.*)/),new RuntimeStatsGroup('Blink_Parsing',/^Blink_Parsing_(.*)/),new RuntimeStatsGroup('Blink_Style',/^Blink_Style_(.*)/),new RuntimeStatsGroup('Blink_Callbacks',/^Blink_(.*)/)];this.total_group_=new RuntimeStatsGroup('Blink_Total',/.*/);for(const entry of entries){for(const group of this.groups_){if(group.match(entry.name)){const newEntry=new RuntimeStatsEntry('Blink_'+group.match(entry.name)[1],entry.count,entry.time);group.add(newEntry);this.total_group_.addSample(entry.count,entry.time);break;}}}}
+get runtimeGroups(){return this.groups_.concat(this.total_group_);}
+get values(){return this.groups_.reduce((values,group)=>values.concat(group.values),[]);}
+get totalTime(){return this.total_group_.time;}
+get totalCount(){return this.total_group_.count;}}
+return{BlinkRuntimeStatsGroupCollection,RuntimeStatsEntry,RuntimeStatsGroup,RuntimeStatsGroupCollection,};});'use strict';tr.exportTo('tr.ui.e.v8',function(){const codeSearchURL_='https://cs.chromium.org/search/?sq=package:chromium&type=cs&q=';function removeBlinkPrefix_(name){if(name.startsWith('Blink_'))name=name.substring(6);return name;}
+function handleCodeSearchForV8_(event){if(event.target.parentNode===undefined)return;let name=event.target.parentNode.entryName;if(name.startsWith('API_'))name=name.substring(4);const url=codeSearchURL_+encodeURIComponent(name)+'+file:src/v8/src';window.open(url,'_blank');}
+function handleCodeSearchForBlink_(event){if(event.target.parentNode===undefined)return;const name=event.target.parentNode.entryName;const url=codeSearchURL_+
+encodeURIComponent('RuntimeCallStats::CounterId::k'+name)+'+file:src/third_party/WebKit/|src/out/Debug/';window.open(url,'_blank');}
+function createCodeSearchEl_(handleCodeSearch){const codeSearchEl=document.createElement('span');codeSearchEl.innerText='?';codeSearchEl.style.float='right';codeSearchEl.style.borderRadius='5px';codeSearchEl.style.backgroundColor='#EEE';codeSearchEl.addEventListener('click',handleCodeSearch.bind(this));return codeSearchEl;}
+const timeColumn_={title:'Time',value(row){const typeEl=document.createElement('span');typeEl.innerText=(row.time/1000.0).toFixed(3)+' ms';return typeEl;},width:'100px',cmp(a,b){return a.time-b.time;}};const countColumn_={title:'Count',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.count;return typeEl;},width:'100px',cmp(a,b){return a.count-b.count;}};function percentColumn_(title,totalTime){return{title,value(row){const typeEl=document.createElement('span');typeEl.innerText=(row.time/totalTime*100).toFixed(3)+'%';return typeEl;},width:'100px',cmp(a,b){return a.time-b.time;}};}
+function nameColumn_(handleCodeSearch,modifyName){return{title:'Name',value(row){const typeEl=document.createElement('span');let name=row.name;if(modifyName)name=modifyName(name);typeEl.innerText=name;if(!(row instanceof tr.e.v8.RuntimeStatsGroup)){typeEl.title='click ? for code search';typeEl.entryName=name;const codeSearchEl=createCodeSearchEl_(handleCodeSearch);typeEl.appendChild(codeSearchEl);}
+return typeEl;},width:'200px',showExpandButtons:true};}
+function initializeCommonOptions_(table){table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;table.sortColumnIndex=1;table.sortDescending=true;table.subRowsPropertyName='values';}
+Polymer({is:'tr-ui-e-v8-runtime-call-stats-table',ready(){this.table_=this.$.table;this.blink_rcs_table_=this.$.blink_rcs_table;this.totalTime_=0;},constructV8RCSTable_(totalTime){this.table_.tableColumns=[nameColumn_(handleCodeSearchForV8_),timeColumn_,countColumn_,percentColumn_('Percent',totalTime)];initializeCommonOptions_(this.table_);},constructBlinkRCSTable_(blinkCppTotalTime){this.blink_rcs_table_.tableColumns=[nameColumn_(handleCodeSearchForBlink_,removeBlinkPrefix_),timeColumn_,countColumn_,percentColumn_('Percent (of \'Blink C++\' + \'API\')',blinkCppTotalTime)];initializeCommonOptions_(this.blink_rcs_table_);},set slices(slices){const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(slices);if(runtimeGroupCollection.totalTime>0){this.$.v8_rcs_heading.textContent='V8 Runtime Call Stats';this.constructV8RCSTable_(runtimeGroupCollection.totalTime);this.table_.tableRows=runtimeGroupCollection.runtimeGroups;this.table_.rebuild();}
+const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;if(runtimeGroupCollection.blinkCppTotalTime>0&&blinkRCSGroupCollection.totalTime>0){this.$.blink_rcs_heading.textContent='Blink Runtime Call Stats';this.constructBlinkRCSTable_(runtimeGroupCollection.blinkCppTotalTime);this.blink_rcs_table_.tableRows=blinkRCSGroupCollection.runtimeGroups;this.blink_rcs_table_.rebuild();}}});return{};});'use strict';Polymer({is:'tr-ui-e-multi-v8-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.runtimeCallStats.slices=selection;this.$.content.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-multi-v8-thread-slice-sub-view',tr.e.v8.V8ThreadSlice,{multi:true,title:'V8 slices'});'use strict';Polymer({is:'tr-ui-e-single-v8-gc-stats-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;this.$.gcObjectsStats.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-single-v8-gc-stats-thread-slice-sub-view',tr.e.v8.V8GCStatsThreadSlice,{multi:false,title:'V8 GC stats slice'});'use strict';Polymer({is:'tr-ui-e-single-v8-ic-stats-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.table.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-single-v8-ic-stats-thread-slice-sub-view',tr.e.v8.V8ICStatsThreadSlice,{multi:false,title:'V8 IC stats slice'});'use strict';Polymer({is:'tr-ui-e-single-v8-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.runtimeCallStats.slices=selection;this.$.content.selection=selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-e-single-v8-thread-slice-sub-view',tr.e.v8.V8ThreadSlice,{multi:false,title:'V8 slice'});'use strict';tr.exportTo('tr.c',function(){function ScriptingObject(){}
+ScriptingObject.prototype={onModelChanged(model){}};return{ScriptingObject,};});'use strict';tr.exportTo('tr.c',function(){function ScriptingController(brushingStateController){this.brushingStateController_=brushingStateController;this.scriptObjectNames_=[];this.scriptObjectValues_=[];this.brushingStateController.addEventListener('model-changed',this.onModelChanged_.bind(this));const typeInfos=ScriptingObjectRegistry.getAllRegisteredTypeInfos();typeInfos.forEach(function(typeInfo){this.addScriptObject(typeInfo.metadata.name,typeInfo.constructor);global[typeInfo.metadata.name]=typeInfo.constructor;},this);}
+function ScriptingObjectRegistry(){}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);tr.b.decorateExtensionRegistry(ScriptingObjectRegistry,options);ScriptingController.prototype={get brushingStateController(){return this.brushingStateController_;},onModelChanged_(){this.scriptObjectValues_.forEach(function(v){if(v.onModelChanged){v.onModelChanged(this.brushingStateController.model);}},this);},addScriptObject(name,value){this.scriptObjectNames_.push(name);this.scriptObjectValues_.push(value);},executeCommand(command){const f=new Function(this.scriptObjectNames_,'return eval('+command+')');return f.apply(null,this.scriptObjectValues_);}};return{ScriptingController,ScriptingObjectRegistry,};});'use strict';tr.exportTo('tr.metrics',function(){function MetricRegistry(){}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};tr.b.decorateExtensionRegistry(MetricRegistry,options);function camelCaseToHackerString(camelCase){let hackerString='';for(const c of camelCase){const lowered=c.toLocaleLowerCase();if(lowered===c){hackerString+=c;}else{hackerString+='_'+lowered;}}
+return hackerString;}
+function getCallStack(){try{throw new Error();}catch(error){return error.stack;}}
+function getPathsFromStack(stack){return stack.split('\n').map(line=>{line=line.replace(/^ */,'').split(':');if(line.length<4)return'';return line[line.length-3].split('/');}).filter(x=>x);}
+MetricRegistry.checkFilename=function(metricName,opt_metricPathForTest){if(metricName==='runtimeStatsTotalMetric'||metricName==='v8AndMemoryMetrics'){return;}
+const expectedFilename=camelCaseToHackerString(metricName)+'.html';const stack=getCallStack();let metricPath=opt_metricPathForTest;if(metricPath===undefined){const paths=getPathsFromStack(stack);const METRIC_STACK_INDEX=5;if(paths.length<=METRIC_STACK_INDEX||paths[METRIC_STACK_INDEX].join('/')===paths[0].join('/')){return;}
+metricPath=paths[METRIC_STACK_INDEX].slice(paths[METRIC_STACK_INDEX].length-2);}
+if(!metricPath[1].endsWith('_test.html')&&!metricPath[1].endsWith('_test.html.js')&&metricPath[1]!==expectedFilename&&metricPath[1]!==expectedFilename+'.js'&&metricPath.join('_')!==expectedFilename&&metricPath.join('_')!==expectedFilename+'.js'){throw new Error('Expected '+metricName+' to be in a file named '+
+expectedFilename+'; actual: '+metricPath.join('/')+'; stack: '+stack.replace(/\n/g,'\n  '));}};MetricRegistry.addEventListener('will-register',function(e){const metric=e.typeInfo.constructor;if(!(metric instanceof Function)){throw new Error('Metrics must be functions.');}
+if(!metric.name.endsWith('Metric')&&!metric.name.endsWith('Metrics')){throw new Error('Metric names must end with "Metric" or "Metrics".');}
+if(metric.length<2){throw new Error('Metrics take a HistogramSet and a Model and '+'optionally an options dictionary.');}
+MetricRegistry.checkFilename(metric.name);});return{MetricRegistry,};});'use strict';tr.exportTo('tr.metrics',function(){function accessibilityMetric(histograms,model){const browserAccessibilityEventsHist=new tr.v.Histogram('browser_accessibility_events',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);browserAccessibilityEventsHist.description='Browser accessibility events time';const renderAccessibilityEventsHist=new tr.v.Histogram('render_accessibility_events',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);renderAccessibilityEventsHist.description='Render accessibility events time';const renderAccessibilityLocationsHist=new tr.v.Histogram('render_accessibility_locations',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);renderAccessibilityLocationsHist.description='Render accessibility locations time';const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;for(const slice of mainThread.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='RenderAccessibilityImpl::SendPendingAccessibilityEvents'){renderAccessibilityEventsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}
+if(slice.title==='RenderAccessibilityImpl::SendLocationChanges'){renderAccessibilityLocationsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
+for(const browserHelper of Object.values(chromeHelper.browserHelpers)){const mainThread=browserHelper.mainThread;if(mainThread===undefined)continue;for(const slice of mainThread.getDescendantEvents()){if(slice.title==='BrowserAccessibilityManager::OnAccessibilityEvents'){browserAccessibilityEventsHist.addSample(slice.duration,{event:new tr.v.d.RelatedEventSet(slice)});}}}
+histograms.addHistogram(browserAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityEventsHist);histograms.addHistogram(renderAccessibilityLocationsHist);}
+tr.metrics.MetricRegistry.register(accessibilityMetric);return{accessibilityMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MESSAGE_LOOP_EVENT_NAME='Startup.BrowserMessageLoopStartTime';const CONTENT_START_EVENT_NAME='content::Start';const NAVIGATION_EVENT_NAME='Navigation StartToCommit';const FIRST_CONTENTFUL_PAINT_EVENT_NAME='firstContentfulPaint';function androidStartupMetric(histograms,model){let messageLoopStartEvents=[];let navigationEvents=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;for(const helper of chromeHelper.browserHelpers){for(const ev of helper.mainThread.asyncSliceGroup.childEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}}}
+let contentStartEvents=[];let firstContentfulPaintEvents=[];const rendererHelpers=chromeHelper.rendererHelpers;const pids=Object.keys(rendererHelpers);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(!rendererHelper.mainThread)continue;for(const ev of rendererHelper.mainThread.sliceGroup.childEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}}
+let totalBrowserStarts=messageLoopStartEvents.length;let totalContentStartEvents=contentStartEvents.length;let totalFcpEvents=firstContentfulPaintEvents.length;let totalNavigations=navigationEvents.length;if(totalFcpEvents!==totalBrowserStarts||totalNavigations!==totalBrowserStarts||totalContentStartEvents!==totalBrowserStarts||totalBrowserStarts===0){messageLoopStartEvents=[];contentStartEvents=[];navigationEvents=[];firstContentfulPaintEvents=[];for(const proc of Object.values(model.processes)){for(const ev of proc.getDescendantEvents()){if(ev.title===MESSAGE_LOOP_EVENT_NAME){messageLoopStartEvents.push(ev);}else if(ev.title===NAVIGATION_EVENT_NAME){navigationEvents.push(ev);}else if(ev.title===CONTENT_START_EVENT_NAME){contentStartEvents.push(ev);}}
+for(const ev of proc.getDescendantEvents()){if(ev.title===FIRST_CONTENTFUL_PAINT_EVENT_NAME){firstContentfulPaintEvents.push(ev);break;}}}
+totalBrowserStarts=messageLoopStartEvents.length;totalContentStartEvents=contentStartEvents.length;totalNavigations=navigationEvents.length;totalFcpEvents=firstContentfulPaintEvents.length;}
+function orderEvents(event1,event2){return event1.start-event2.start;}
+messageLoopStartEvents.sort(orderEvents);contentStartEvents.sort(orderEvents);navigationEvents.sort(orderEvents);firstContentfulPaintEvents.sort(orderEvents);if(totalFcpEvents<totalBrowserStarts){throw new Error('Found fewer FCP events ('+totalFcpEvents+') than browser starts ('+totalBrowserStarts+')');}
+const messageLoopStartHistogram=histograms.createHistogram('messageloop_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const contentStartHistogram=histograms.createHistogram('experimental_content_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationStartHistogram=histograms.createHistogram('experimental_navigation_start_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const navigationCommitHistogram=histograms.createHistogram('navigation_commit_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);const firstContentfulPaintHistogram=histograms.createHistogram('first_contentful_paint_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[]);let contentIndex=0;let navIndex=0;let fcpIndex=0;for(let loopStartIndex=0;loopStartIndex<totalBrowserStarts;){const startEvent=messageLoopStartEvents[loopStartIndex];if(fcpIndex===totalFcpEvents){break;}
+const contentStartEvent=contentIndex<contentStartEvents.length?contentStartEvents[contentIndex]:null;if(contentStartEvent&&contentStartEvent.start<startEvent.start){contentIndex++;continue;}
+const navEvent=navIndex<navigationEvents.length?navigationEvents[navIndex]:null;if(navEvent&&navEvent.start<startEvent.start){navIndex++;continue;}
+const fcpEvent=firstContentfulPaintEvents[fcpIndex];if(fcpEvent.start<startEvent.start){fcpIndex++;continue;}
+loopStartIndex++;if(fcpIndex<2){continue;}
+messageLoopStartHistogram.addSample(startEvent.duration,{events:new tr.v.d.RelatedEventSet([startEvent])});if(contentStartEvent){contentStartHistogram.addSample(contentStartEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,contentStartEvent])});}
+if(navEvent){navigationStartHistogram.addSample(navEvent.start-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});navigationCommitHistogram.addSample(navEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,navEvent])});}
+firstContentfulPaintHistogram.addSample(fcpEvent.end-startEvent.start,{events:new tr.v.d.RelatedEventSet([startEvent,fcpEvent])});}}
+tr.metrics.MetricRegistry.register(androidStartupMetric);return{androidStartupMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS=2000;const MIN_DRAW_DELAY_IN_MS=80;const MAX_DRAW_DELAY_IN_MS=2000;function findProcess(processName,model){for(const pid in model.processes){const process=model.processes[pid];if(process.name===processName){return process;}}
+return undefined;}
+function findThreads(process,threadPrefix){if(process===undefined)return undefined;const threads=[];for(const tid in process.threads){const thread=process.threads[tid];if(thread.name.startsWith(threadPrefix)){threads.push(thread);}}
+return threads;}
+function findUIThread(process){if(process===undefined)return undefined;const threads=findThreads(process,'UI Thread');if(threads!==undefined&&threads.length===1){return threads[0];}
+return process.threads[process.pid];}
+function findLaunchSlices(model){const launches=[];const binders=findThreads(findProcess('system_server',model),'Binder');for(const binderId in binders){const binder=binders[binderId];for(const sliceId in binder.asyncSliceGroup.slices){const slice=binder.asyncSliceGroup.slices[sliceId];if(slice.title.startsWith('launching:')){launches.push(slice);}}}
+return launches;}
+function findDrawSlice(appName,startNotBefore,model){let drawSlice=undefined;const thread=findUIThread(findProcess(appName,model));if(thread===undefined)return undefined;for(const sliceId in thread.sliceGroup.slices){const slice=thread.sliceGroup.slices[sliceId];if(slice.start<startNotBefore+MIN_DRAW_DELAY_IN_MS||slice.start>startNotBefore+MAX_DRAW_DELAY_IN_MS)continue;if(slice.title!=='draw')continue;if(drawSlice===undefined||slice.start<drawSlice.start){drawSlice=slice;}}
+return drawSlice;}
+function findInputEventSlice(endNotAfter,model){const endNotBefore=endNotAfter-MAX_INPUT_EVENT_TO_STARTUP_DELAY_IN_MS;let inputSlice=undefined;const systemUi=findUIThread(findProcess('com.android.systemui',model));if(systemUi===undefined)return undefined;for(const sliceId in systemUi.asyncSliceGroup.slices){const slice=systemUi.asyncSliceGroup.slices[sliceId];if(slice.end>endNotAfter||slice.end<endNotBefore)continue;if(slice.title!=='deliverInputEvent')continue;if(inputSlice===undefined||slice.end>inputSlice.end){inputSlice=slice;}}
+return inputSlice;}
+function computeStartupTimeInMs(appName,launchSlice,model){let startupStart=launchSlice.start;let startupEnd=launchSlice.end;const drawSlice=findDrawSlice(appName,launchSlice.end,model);if(drawSlice!==undefined){startupEnd=drawSlice.end;}
+const inputSlice=findInputEventSlice(launchSlice.start,model);if(inputSlice!==undefined){startupStart=inputSlice.start;}
+return startupEnd-startupStart;}
+function measureStartup(histograms,model){const launches=findLaunchSlices(model);for(const sliceId in launches){const launchSlice=launches[sliceId];const appName=launchSlice.title.split(': ')[1];const startupMs=computeStartupTimeInMs(appName,launchSlice,model);histograms.createHistogram(`android:systrace:startup:${appName}`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,startupMs);}}
+function measureThreadStates(histograms,model,rangeOfInterest){for(const pid in model.processes){const process=model.processes[pid];if(process.name===undefined)continue;let hasSlices=false;let timeRunning=0;let timeRunnable=0;let timeSleeping=0;let timeUninterruptible=0;let timeBlockIO=0;let timeUnknown=0;for(const tid in process.threads){const thread=process.threads[tid];if(thread.timeSlices===undefined)continue;for(const sliceId in thread.timeSlices){const slice=thread.timeSlices[sliceId];const sliceRange=tr.b.math.Range.fromExplicitRange(slice.start,slice.end);const intersection=rangeOfInterest.findIntersection(sliceRange);const duration=intersection.duration;if(duration===0)continue;hasSlices=true;if(slice.title==='Running'){timeRunning+=duration;}else if(slice.title==='Runnable'){timeRunnable+=duration;}else if(slice.title==='Sleeping'){timeSleeping+=duration;}else if(slice.title.startsWith('Uninterruptible')){timeUninterruptible+=duration;if(slice.title.includes('Block I/O'))timeBlockIO+=duration;}else{timeUnknown+=duration;}}}
+if(hasSlices){const wall=rangeOfInterest.max-rangeOfInterest.min;histograms.createHistogram(`android:systrace:threadtime:${process.name}:running`,tr.b.Unit.byName.normalizedPercentage,timeRunning/wall);histograms.createHistogram(`android:systrace:threadtime:${process.name}:runnable`,tr.b.Unit.byName.normalizedPercentage,timeRunnable/wall);histograms.createHistogram(`android:systrace:threadtime:${process.name}:sleeping`,tr.b.Unit.byName.normalizedPercentage,timeSleeping/wall);histograms.createHistogram(`android:systrace:threadtime:${process.name}:blockio`,tr.b.Unit.byName.normalizedPercentage,timeBlockIO/wall);histograms.createHistogram(`android:systrace:threadtime:${process.name}:uninterruptible`,tr.b.Unit.byName.normalizedPercentage,timeUninterruptible/wall);if(timeUnknown>0){histograms.createHistogram(`android:systrace:threadtime:${process.name}:unknown`,tr.b.Unit.byName.normalizedPercentage,timeUnknown/wall);}}}}
+function androidSystraceMetric(histograms,model,options){let rangeOfInterest=model.bounds;if(options!==undefined&&options.rangeOfInterest!==undefined){rangeOfInterest=options.rangeOfInterest;}
+measureStartup(histograms,model);measureThreadStates(histograms,model,rangeOfInterest);}
+tr.metrics.MetricRegistry.register(androidSystraceMetric,{supportsRangeOfInterest:true});return{androidSystraceMetric,};});'use strict';tr.exportTo('tr.b.math',function(){const PERCENTILE_PRECISION=1e-7;function PiecewiseLinearFunction(){this.pieces=[];}
+PiecewiseLinearFunction.prototype={push(x1,y1,x2,y2){if(x1>=x2){throw new Error('Invalid segment');}
+if(this.pieces.length>0&&this.pieces[this.pieces.length-1].x2>x1){throw new Error('Potentially overlapping segments');}
+if(x1<x2){this.pieces.push(new Piece(x1,y1,x2,y2));}},partBelow(y){return this.pieces.reduce((acc,p)=>(acc+p.partBelow(y)),0);},get min(){return this.pieces.reduce((acc,p)=>Math.min(acc,p.min),Infinity);},get max(){return this.pieces.reduce((acc,p)=>Math.max(acc,p.max),-Infinity);},get average(){let weightedSum=0;let totalWeight=0;this.pieces.forEach(function(piece){weightedSum+=piece.width*piece.average;totalWeight+=piece.width;});if(totalWeight===0)return 0;return weightedSum/totalWeight;},percentile(percent){if(!(percent>=0&&percent<=1)){throw new Error('percent must be [0,1]');}
+let lower=this.min;let upper=this.max;const total=this.partBelow(upper);if(total===0)return 0;while(upper-lower>PERCENTILE_PRECISION){const middle=(lower+upper)/2;const below=this.partBelow(middle);if(below/total<percent){lower=middle;}else{upper=middle;}}
+return(lower+upper)/2;}};function Piece(x1,y1,x2,y2){this.x1=x1;this.y1=y1;this.x2=x2;this.y2=y2;}
+Piece.prototype={partBelow(y){const width=this.width;if(width===0)return 0;const minY=this.min;const maxY=this.max;if(y>=maxY)return width;if(y<minY)return 0;return(y-minY)/(maxY-minY)*width;},get min(){return Math.min(this.y1,this.y2);},get max(){return Math.max(this.y1,this.y2);},get average(){return(this.y1+this.y2)/2;},get width(){return this.x2-this.x1;}};return{PiecewiseLinearFunction,};});'use strict';tr.exportTo('tr.metrics.v8.utils',function(){const IDLE_TASK_EVENT='SingleThreadIdleTaskRunner::RunTask';const V8_EXECUTE='V8.Execute';const GC_EVENT_PREFIX='V8.GC';const FULL_GC_EVENT='V8.GCCompactor';const LOW_MEMORY_EVENT='V8.GCLowMemoryNotification';const MAJOR_GC_EVENT='MajorGC';const MINOR_GC_EVENT='MinorGC';const TOP_GC_EVENTS={'V8.GCCompactor':'v8-gc-full-mark-compactor','V8.GCFinalizeMC':'v8-gc-latency-mark-compactor','V8.GCFinalizeMCReduceMemory':'v8-gc-memory-mark-compactor','V8.GCIncrementalMarking':'v8-gc-incremental-step','V8.GCIncrementalMarkingFinalize':'v8-gc-incremental-finalize','V8.GCIncrementalMarkingStart':'v8-gc-incremental-start','V8.GCPhantomHandleProcessingCallback':'v8-gc-phantom-handle-callback','V8.GCScavenger':'v8-gc-scavenger'};const MARK_COMPACTOR_EVENTS=new Set(['V8.GCCompactor','V8.GCFinalizeMC','V8.GCFinalizeMCReduceMemory','V8.GCIncrementalMarking','V8.GCIncrementalMarkingFinalize','V8.GCIncrementalMarkingStart','V8.GCPhantomHandleProcessingCallback']);const LOW_MEMORY_MARK_COMPACTOR='v8-gc-low-memory-mark-compactor';function findParent(event,predicate){let parent=event.parentSlice;while(parent){if(predicate(parent)){return parent;}
+parent=parent.parentSlice;}
+return null;}
+function isIdleTask(event){return event.title===IDLE_TASK_EVENT;}
+function isLowMemoryEvent(event){return event.title===LOW_MEMORY_EVENT;}
+function isV8Event(event){return event.title.startsWith('V8.');}
+function isV8ExecuteEvent(event){return event.title===V8_EXECUTE;}
+function isTopV8ExecuteEvent(event){return isV8ExecuteEvent(event)&&findParent(isV8ExecuteEvent)===null;}
+function isGarbageCollectionEvent(event){return event.title&&event.title.startsWith(GC_EVENT_PREFIX)&&event.title!==LOW_MEMORY_EVENT;}
+function isTopGarbageCollectionEvent(event){return event.title in TOP_GC_EVENTS;}
+function isForcedGarbageCollectionEvent(event){return findParent(event,isLowMemoryEvent)!==null;}
+function isSubGarbageCollectionEvent(event){return isGarbageCollectionEvent(event)&&event.parentSlice&&(isTopGarbageCollectionEvent(event.parentSlice)||event.parentSlice.title===MAJOR_GC_EVENT||event.parentSlice.title===MINOR_GC_EVENT);}
+function isNotForcedTopGarbageCollectionEvent(event){return tr.metrics.v8.utils.isTopGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
+function isNotForcedSubGarbageCollectionEvent(event){return tr.metrics.v8.utils.isSubGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
+function isFullMarkCompactorEvent(event){return event.title==='V8.GCCompactor';}
+function isMarkCompactorSummaryEvent(event){return event.title==='V8.GCMarkCompactorSummary';}
+function isMarkCompactorMarkingSummaryEvent(event){return event.title==='V8.GCMarkCompactorMarkingSummary';}
+function isIncrementalMarkingEvent(event){return event.title.startsWith('V8.GCIncrementalMarking');}
+function isLatencyMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMC';}
+function isMemoryMarkCompactorEvent(event){return event.title==='V8.GCFinalizeMCReduceMemory';}
+function isScavengerEvent(event){return event.title==='V8.GCScavenger';}
+function isCompileOptimizeRCSCategory(name){return name==='Optimize';}
+function isCompileUnoptimizeRCSCategory(name){return name==='Compile';}
+function isCompileParseRCSCategory(name){return name==='Parse';}
+function isCompileRCSCategory(name){return name==='Compile'||name==='Optimize'||name==='Parse';}
+function isV8RCSEvent(event){return event instanceof tr.e.v8.V8ThreadSlice;}
+function isMarkCompactorEvent(event){return MARK_COMPACTOR_EVENTS.has(event.title);}
+function isNotForcedMarkCompactorEvent(event){return!isForcedGarbageCollectionEvent(event)&&isMarkCompactorEvent(event);}
+function forcedGCEventName(){return LOW_MEMORY_EVENT;}
+function topGarbageCollectionEventName(event){if(event.title===FULL_GC_EVENT){if(findParent(event,isLowMemoryEvent)){return LOW_MEMORY_MARK_COMPACTOR;}}
+return TOP_GC_EVENTS[event.title];}
+function topGarbageCollectionEventNames(){return Object.values(TOP_GC_EVENTS);}
+function subGarbageCollectionEventName(event){const topEvent=findParent(event,isTopGarbageCollectionEvent);const prefix=topEvent?topGarbageCollectionEventName(topEvent):'unknown';const name=event.title.replace('V8.GC_MC_','').replace('V8.GC_SCAVENGER_','').replace('V8.GC_','').replace(/_/g,'-').toLowerCase();return prefix+'-'+name;}
+function jsExecutionThreads(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let threads=[];for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.isChromeTracingUI)continue;threads.push(rendererHelper.mainThread);threads=threads.concat(rendererHelper.dedicatedWorkerThreads);threads=threads.concat(rendererHelper.foregroundWorkerThreads);}
+return threads;}
+function groupAndProcessEvents(model,filterCallback,groupCallback,processCallback,groups){const groupToEvents={};if(groups){for(const group of groups){groupToEvents[group]=[];}}
+const threads=jsExecutionThreads(model);for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;const group=groupCallback(event);if(groups&&!(group in groupToEvents)){continue;}
+groupToEvents[group]=groupToEvents[group]||[];groupToEvents[group].push(event);}}
+for(const[group,events]of Object.entries(groupToEvents)){processCallback(group,events);}}
+function filterEvents(model,filterCallback){const threads=jsExecutionThreads(model);const events=[];for(const thread of threads){for(const event of thread.sliceGroup.childEvents()){if(!filterCallback(event))continue;events.push(event);}}
+return events;}
+function unionOfIntervals(intervals){if(intervals.length===0)return[];return tr.b.math.mergeRanges(intervals.map(x=>{return{min:x.start,max:x.end};}),1e-6,function(ranges){return{start:ranges.reduce((acc,x)=>Math.min(acc,x.min),ranges[0].min),end:ranges.reduce((acc,x)=>Math.max(acc,x.max),ranges[0].max)};});}
+function hasV8Stats(globalMemoryDump){let v8stats=undefined;globalMemoryDump.iterateContainerDumps(function(dump){v8stats=v8stats||dump.getMemoryAllocatorDumpByFullName('v8');});return!!v8stats;}
+function rangeForMemoryDumps(model){const startOfFirstDumpWithV8=model.globalMemoryDumps.filter(hasV8Stats).reduce((start,dump)=>Math.min(start,dump.start),Infinity);if(startOfFirstDumpWithV8===Infinity)return new tr.b.math.Range();return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8,Infinity);}
+class WindowEndpoint{constructor(start,points){this.points=points;this.lastIndex=-1;this.position=start;this.distanceUntilNextPoint=points[0].position-start;this.cummulativePause=0;this.stackDepth=0;}
+advance(delta){if(delta<this.distanceUntilNextPoint){this.position+=delta;this.cummulativePause+=this.stackDepth>0?delta:0;this.distanceUntilNextPoint=this.points[this.lastIndex+1].position-this.position;}else{this.position+=this.distanceUntilNextPoint;this.cummulativePause+=this.stackDepth>0?this.distanceUntilNextPoint:0;this.distanceUntilNextPoint=0;this.lastIndex++;if(this.lastIndex<this.points.length){this.stackDepth+=this.points[this.lastIndex].delta;if(this.lastIndex+1<this.points.length){this.distanceUntilNextPoint=this.points[this.lastIndex+1].position-this.position;}}}}}
+function mutatorUtilization(start,end,timeWindow,intervals){const mu=new tr.b.math.PiecewiseLinearFunction();if(end-start<=timeWindow){return mu;}
+if(intervals.length===0){mu.push(start,1.0,end-timeWindow,1.0);return mu;}
+intervals=unionOfIntervals(intervals);const points=[];for(const interval of intervals){points.push({position:interval.start,delta:1});points.push({position:interval.end,delta:-1});}
+points.sort((a,b)=>a.position-b.position);points.push({position:end,delta:0});const left=new WindowEndpoint(start,points);const right=new WindowEndpoint(start,points);const EPSILON=1e-6;while(right.position-left.position<timeWindow-EPSILON){right.advance(timeWindow-(right.position-left.position));}
+while(right.lastIndex<points.length){const distanceUntilNextPoint=Math.min(left.distanceUntilNextPoint,right.distanceUntilNextPoint);const position1=left.position;const value1=right.cummulativePause-left.cummulativePause;left.advance(distanceUntilNextPoint);right.advance(distanceUntilNextPoint);if(distanceUntilNextPoint>0){const position2=left.position;const value2=right.cummulativePause-left.cummulativePause;mu.push(position1,1.0-value1/timeWindow,position2,1.0-value2/timeWindow);}}
+return mu;}
+function addMutatorUtilization(metricName,eventFilter,timeWindows,rendererHelpers,histograms){const histogramMap=new Map();for(const timeWindow of timeWindows){const summaryOptions={avg:false,count:false,max:false,min:true,std:false,sum:false};const description=`The minimum mutator utilization in ${timeWindow}ms time window`;const histogram=histograms.createHistogram(`${metricName}-${timeWindow}ms_window`,tr.b.Unit.byName.normalizedPercentage_biggerIsBetter,[],{summaryOptions,description});histogramMap.set(timeWindow,histogram);}
+for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;const pauses=[];for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){if(eventFilter(event)&&event.end>event.start){pauses.push({start:event.start,end:event.end});}}
+pauses.sort((a,b)=>a.start-b.start);const start=rendererHelper.mainThread.bounds.min;const end=rendererHelper.mainThread.bounds.max;for(const timeWindow of timeWindows){const mu=mutatorUtilization(start,end,timeWindow,pauses);histogramMap.get(timeWindow).addSample(mu.min);}}}
+return{addMutatorUtilization,findParent,forcedGCEventName,filterEvents,groupAndProcessEvents,isForcedGarbageCollectionEvent,isFullMarkCompactorEvent,isGarbageCollectionEvent,isIdleTask,isIncrementalMarkingEvent,isLatencyMarkCompactorEvent,isLowMemoryEvent,isMarkCompactorSummaryEvent,isMarkCompactorMarkingSummaryEvent,isMemoryMarkCompactorEvent,isNotForcedMarkCompactorEvent,isNotForcedTopGarbageCollectionEvent,isNotForcedSubGarbageCollectionEvent,isScavengerEvent,isSubGarbageCollectionEvent,isTopGarbageCollectionEvent,isTopV8ExecuteEvent,isV8Event,isV8ExecuteEvent,isV8RCSEvent,isCompileRCSCategory,isCompileOptimizeRCSCategory,isCompileUnoptimizeRCSCategory,isCompileParseRCSCategory,mutatorUtilization,rangeForMemoryDumps,subGarbageCollectionEventName,topGarbageCollectionEventName,topGarbageCollectionEventNames,unionOfIntervals,};});'use strict';tr.exportTo('tr.metrics.blink',function(){const BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP={'BlinkGC.AtomicPauseMarkEpilogue':'blink-gc-atomic-pause-mark-epilogue','BlinkGC.AtomicPauseMarkPrologue':'blink-gc-atomic-pause-mark-prologue','BlinkGC.AtomicPauseMarkRoots':'blink-gc-atomic-pause-mark-roots','BlinkGC.IncrementalMarkingStartMarking':'blink-gc-incremental-start','BlinkGC.IncrementalMarkingStep':'blink-gc-incremental-step','BlinkGC.UnifiedMarkingStep':'blink-gc-unified-marking-by-v8','BlinkGC.CompleteSweep':'blink-gc-complete-sweep','BlinkGC.LazySweepInIdle':'blink-gc-sweep-task-foreground','BlinkGC.LazySweepOnAllocation':'blink-gc-sweep-allocation','BlinkGC.AtomicPauseSweepAndCompact':'blink-gc-atomic-pause-sweep-and-compact'};const BLINK_TOP_GC_ROOTS_MARKING_EVENTS=['BlinkGC.VisitRoots'];const BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure'];const BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS=['BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.IncrementalMarkingStep','BlinkGC.UnifiedMarkingStep'];const BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.IncrementalMarkingStartMarking',].concat(BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS);const BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS=['BlinkGC.ConcurrentMarkingStep'];const BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS=['BlinkGC.CompleteSweep','BlinkGC.LazySweepInIdle','BlinkGC.LazySweepOnAllocation'];const BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS=['BlinkGC.ConcurrentSweepingStep'];const BLINK_TOP_GC_EVENTS=Object.keys(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP).concat(BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS);const ATOMIC_PAUSE_EVENTS=['BlinkGC.AtomicPauseMarkEpilogue','BlinkGC.AtomicPauseMarkPrologue','BlinkGC.AtomicPauseMarkRoots','BlinkGC.AtomicPauseMarkTransitiveClosure','BlinkGC.AtomicPauseSweepAndCompact'];function blinkGarbageCollectionEventName(event){return BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP[event.title];}
+function blinkGarbageCollectionEventNames(){return Object.values(BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP);}
+function isNonForcedEvent(event){return(!event.args||!event.args.forced)&&!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event);}
+function isNonForcedBlinkGarbageCollectionEvent(event){return BLINK_TOP_GC_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedNonAggregatedBlinkGarbageCollectionEvent(event){return event.title in BLINK_NON_AGGREGATED_GC_EVENTS_NAMES_MAP&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionAtomicPauseEvent(event){return ATOMIC_PAUSE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionRootsMarkingEvent(event){return BLINK_TOP_GC_ROOTS_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function
+isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent(event){return BLINK_GC_FOREGROUND_MARKING_TRANSITIVE_CLOSURE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function
+isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent(event){return BLINK_GC_ATOMIC_PAUSE_TRANSITIVE_CLOSURE_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionForegroundMarkingEvent(event){return BLINK_TOP_GC_FOREGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent(event){return BLINK_TOP_GC_BACKGROUND_MARKING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionForegroundSweepingEvent(event){return BLINK_TOP_GC_FOREGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent(event){return BLINK_TOP_GC_BACKGROUND_SWEEPING_EVENTS.includes(event.title)&&isNonForcedEvent(event);}
+function isNonNestedNonForcedBlinkGarbageCollectionEvent(event){return isNonForcedBlinkGarbageCollectionEvent(event)&&!tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isGarbageCollectionEvent);}
+function blinkGcMetric(histograms,model){addDurationOfTopEvents(histograms,model);addDurationOfAtomicPause(histograms,model);addDurationOfAtomicPauseTransitiveClosure(histograms,model);addTotalDurationOfTopEvents(histograms,model);addTotalDurationOfBlinkAndV8TopEvents(histograms,model);addTotalDurationOfRootsMarking(histograms,model);addTotalDurationOfMarkingTransitiveClosure(histograms,model);addTotalDurationOfForegroundMarking(histograms,model);addTotalDurationOfBackgroundMarking(histograms,model);addTotalDurationOfForegroundSweeping(histograms,model);addTotalDurationOfBackgroundSweeping(histograms,model);}
+tr.metrics.MetricRegistry.register(blinkGcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
+function createNumericForTotalEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:false,min:false,std:false,sum:true,percentile:[0.90]});return n;}
+function createNumericForUnifiedEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:false,count:true,max:true,min:false,std:false,sum:true,percentile:[0.90]});return n;}
+function addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedNonAggregatedBlinkGarbageCollectionEvent,blinkGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},blinkGarbageCollectionEventNames());}
+function addDurationOfAtomicPause(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
+function addDurationOfAtomicPauseTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionAtomicPauseTransitiveColsureEvent,event=>event.args.epoch,function(group,events){const cpuDuration=createNumericForTopEventTime('blink-gc-atomic-pause-mark-transitive-closure');cpuDuration.addSample(events.reduce((acc,current)=>acc+current.cpuDuration,0));histograms.addHistogram(cpuDuration);});}
+function addTotalDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionEvent,event=>'blink-gc-total',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-total']);}
+function addTotalDurationOfRootsMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionRootsMarkingEvent,event=>'blink-gc-mark-roots',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-mark-roots']);}
+function addTotalDurationOfMarkingTransitiveClosure(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionMarkingTransitiveColsureEvent,event=>'blink-gc-mark-transitive-closure',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-mark-transitive-closure']);}
+function addTotalDurationOfForegroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundMarkingEvent,event=>'blink-gc-mark-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-mark-foreground']);}
+function addTotalDurationOfBackgroundMarking(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundMarkingEvent,event=>'blink-gc-mark-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-mark-background']);}
+function addTotalDurationOfForegroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionForegroundSweepingEvent,event=>'blink-gc-sweep-foreground',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-sweep-foreground']);}
+function addTotalDurationOfBackgroundSweeping(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isNonForcedBlinkGarbageCollectionBackgroundSweepingEvent,event=>'blink-gc-sweep-background',function(name,events){const cpuDuration=createNumericForTotalEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['blink-gc-sweep-background']);}
+function isV8OrBlinkTopLevelGarbageCollectionEvent(event){return tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent(event)||isNonNestedNonForcedBlinkGarbageCollectionEvent(event);}
+function addTotalDurationOfBlinkAndV8TopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8OrBlinkTopLevelGarbageCollectionEvent,event=>'unified-gc-total',function(name,events){const cpuDuration=createNumericForUnifiedEventTime(name);for(const event of events){cpuDuration.addSample(event.cpuDuration);}
+histograms.addHistogram(cpuDuration);},['unified-gc-total']);}
+return{blinkGcMetric,};});'use strict';tr.exportTo('tr.metrics.blink',function(){function leakDetectionMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper===undefined){throw new Error('Chrome is not present.');}
+const rendererHelpers=modelHelper.rendererHelpers;if(Object.keys(rendererHelpers).length===0){throw new Error('Renderer process is not present.');}
+const pids=Object.keys(rendererHelpers);const chromeDumps=tr.metrics.sh.splitGlobalDumpsByBrowserName(model,undefined).get('chrome');const sumCounter=new Map();for(const pid of pids){for(const[key,count]of countLeakedBlinkObjects(chromeDumps,pid)){sumCounter.set(key,(sumCounter.get(key)||0)+count);}}
+for(const[key,count]of sumCounter){histograms.createHistogram('Leaked '+key,tr.b.Unit.byName.count_smallerIsBetter,count);}
+for(const[key,count]of sumCounter){if(count>0){throw new Error('Memory leak is found.');}}}
+tr.metrics.MetricRegistry.register(leakDetectionMetric);function countLeakedBlinkObjects(dumps,pid){if(dumps===undefined||dumps.length<2){throw new Error('Expected at least two memory dumps.');}
+const firstCounter=countBlinkObjects(dumps[0],pid);const lastCounter=countBlinkObjects(dumps[dumps.length-1],pid);const diffCounter=new Map();for(const[key,lastCount]of lastCounter){diffCounter.set(key,lastCount-firstCounter.get(key));}
+return diffCounter;}
+function countBlinkObjects(dump,pid){const counter=new Map();const processesMemoryDumps=dump.processMemoryDumps;if(processesMemoryDumps[pid]===undefined)return counter;const blinkObjectsDump=processesMemoryDumps[pid].memoryAllocatorDumps.find(dump=>dump.fullName==='blink_objects');for(const v of blinkObjectsDump.children){counter.set(v.name,v.numerics.object_count.value);}
+return counter;}
+return{leakDetectionMetric,};});'use strict';tr.exportTo('tr.metrics.console',function(){const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e4,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const SOURCES=['all','js','network'];function consoleErrorMetric(histograms,model){const counts={};for(const source of SOURCES){counts[source]=0;}
+for(const slice of model.getDescendantEvents()){if(slice.category==='blink.console'&&slice.title==='ConsoleMessage::Error'){const source=slice.args.source.toLowerCase();counts.all++;if(source in counts){counts[source]++;}}
+if(slice.category==='v8.console'&&(slice.title==='V8ConsoleMessage::Exception'||slice.title==='V8ConsoleMessage::Error'||slice.title==='V8ConsoleMessage::Assert')){counts.all++;counts.js++;}}
+for(const source of SOURCES){histograms.createHistogram(`console:error:${source}`,tr.b.Unit.byName.count_smallerIsBetter,counts[source],{description:`Number of ${source} console error messages`,summaryOptions:SUMMARY_OPTIONS});}}
+tr.metrics.MetricRegistry.register(consoleErrorMetric);return{consoleErrorMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function getCpuSnapshotsFromModel(model){const snapshots=[];for(const pid in model.processes){const snapshotInstances=model.processes[pid].objects.getAllInstancesNamed('CPUSnapshots');if(!snapshotInstances)continue;for(const object of snapshotInstances[0].snapshots){snapshots.push(object.args.processes);}}
+return snapshots;}
+function getProcessSumsFromSnapshot(snapshot){const processSums=new Map();for(const processData of snapshot){const processName=processData.name;if(!(processSums.has(processName))){processSums.set(processName,{sum:0.0,paths:new Set()});}
+processSums.get(processName).sum+=parseFloat(processData.pCpu);if(processData.path){processSums.get(processName).paths.add(processData.path);}}
+return processSums;}
+function buildNumericsFromSnapshots(snapshots){const processNumerics=new Map();for(const snapshot of snapshots){const processSums=getProcessSumsFromSnapshot(snapshot);for(const[processName,processData]of processSums.entries()){if(!(processNumerics.has(processName))){processNumerics.set(processName,{numeric:new tr.v.Histogram('cpu:percent:'+processName,tr.b.Unit.byName.normalizedPercentage_smallerIsBetter),paths:new Set()});}
+processNumerics.get(processName).numeric.addSample(processData.sum/100.0);for(const path of processData.paths){processNumerics.get(processName).paths.add(path);}}}
+return processNumerics;}
+function cpuProcessMetric(histograms,model){const snapshots=getCpuSnapshotsFromModel(model);const processNumerics=buildNumericsFromSnapshots(snapshots);for(const[processName,processData]of processNumerics){const numeric=processData.numeric;const missingSnapshotCount=snapshots.length-numeric.numValues;for(let i=0;i<missingSnapshotCount;i++){numeric.addSample(0);}
+numeric.diagnostics.set('paths',new
+tr.v.d.GenericSet([...processData.paths]));histograms.addHistogram(numeric);}}
+tr.metrics.MetricRegistry.register(cpuProcessMetric);return{cpuProcessMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function mediaMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return;for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const mainThread=rendererHelper.mainThread;if(mainThread===undefined)continue;const videoThreads=rendererHelper.process.findAllThreadsMatching(thread=>(thread.name?thread.name.startsWith('ThreadPoolSingleThreadSharedForegroundBlocking'):false));const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){videoThreads.push(compositorThread);}
+const audioThreads=rendererHelper.process.findAllThreadsNamed('AudioOutputDevice');if(audioThreads.length===0&&videoThreads.length===0)continue;const processData=new PerProcessData();processData.recordPlayStarts(mainThread);if(!processData.hasPlaybacks)continue;if(videoThreads.length!==0){processData.calculateTimeToVideoPlays(videoThreads);processData.calculateDroppedFrameCounts(videoThreads);}
+if(audioThreads.length!==0){processData.calculateTimeToAudioPlays(audioThreads);}
+processData.calculateSeekTimes(mainThread);processData.calculateBufferingTimes(mainThread);processData.addMetricToHistograms(histograms);}}
+class PerProcessData{constructor(){this.playbackIdToDataMap_=new Map();}
+recordPlayStarts(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoLoad'){const id=event.args.id;if(this.playbackIdToDataMap_.has(id)){throw new Error('Unexpected multiple initialization of a media playback');}
+this.playbackIdToDataMap_.set(id,new PerPlaybackData(event.start));}}}
+get hasPlaybacks(){return this.playbackIdToDataMap_.size>0;}
+calculateTimeToVideoPlays(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoRendererImpl::Render'){this.getPerPlaybackObject_(event.args.id).processVideoRenderTime(event.start);}}}}
+calculateTimeToAudioPlays(audioThreads){for(const audioThread of audioThreads){for(const event of audioThread.sliceGroup.getDescendantEvents()){if(event.title==='AudioRendererImpl::Render'){this.getPerPlaybackObject_(event.args.id).processAudioRenderTime(event.start);}}}}
+calculateSeekTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::DoSeek'){this.getPerPlaybackObject_(event.args.id).processDoSeek(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::OnPipelineSeeked'){this.getPerPlaybackObject_(event.args.id).processOnPipelineSeeked(event.args.target,event.start);}else if(event.title==='WebMediaPlayerImpl::BufferingHaveEnough'){this.getPerPlaybackObject_(event.args.id).processBufferingHaveEnough(event.start);}}}
+calculateBufferingTimes(mainThread){for(const event of mainThread.sliceGroup.getDescendantEvents()){if(event.title==='WebMediaPlayerImpl::OnEnded'){this.getPerPlaybackObject_(event.args.id).processOnEnded(event.start,event.args.duration);}}}
+calculateDroppedFrameCounts(videoThreads){for(const thread of videoThreads){for(const event of thread.sliceGroup.getDescendantEvents()){if(event.title==='VideoFramesDropped'){this.getPerPlaybackObject_(event.args.id).processVideoFramesDropped(event.args.count);}}}}
+addMetricToHistograms(histograms){for(const[id,playbackData]of this.playbackIdToDataMap_){playbackData.addMetricToHistograms(histograms);}}
+getPerPlaybackObject_(playbackId){let perPlaybackObject=this.playbackIdToDataMap_.get(playbackId);if(perPlaybackObject===undefined){perPlaybackObject=new PerPlaybackData(undefined);this.playbackIdToDataMap_.set(playbackId,perPlaybackObject);}
+return perPlaybackObject;}}
+class PerPlaybackData{constructor(playStartTime){this.playStart_=playStartTime;this.timeToVideoPlay_=undefined;this.timeToAudioPlay_=undefined;this.bufferingTime_=undefined;this.droppedFrameCount_=0;this.seekError_=false;this.seekTimes_=new Map();this.currentSeek_=undefined;}
+get timeToVideoPlay(){return this.timeToVideoPlay_;}
+get timeToAudioPlay(){return this.timeToAudioPlay_;}
+get bufferingTime(){return this.bufferingTime_;}
+get droppedFrameCount(){return(this.timeToVideoPlay_!==undefined)?this.droppedFrameCount_:undefined;}
+get seekTimes(){if(this.seekError_||this.currentSeek_!==undefined)return new Map();return this.seekTimes_;}
+processVideoRenderTime(videoRenderTime){if(this.playStart_!==undefined&&this.timeToVideoPlay_===undefined){this.timeToVideoPlay_=videoRenderTime-this.playStart_;}}
+processAudioRenderTime(audioRenderTime){if(this.playStart_!==undefined&&this.timeToAudioPlay_===undefined){this.timeToAudioPlay_=audioRenderTime-this.playStart_;}}
+processVideoFramesDropped(count){this.droppedFrameCount_+=count;}
+processDoSeek(target,startTime){if(this.currentSeek_!==undefined){this.seekError_=true;return;}
+this.currentSeek_={target,startTime};this.seekTimes_.set(target,this.currentSeek_);}
+processOnPipelineSeeked(target,time){if(this.seekError_)return;const currentSeek=this.currentSeek_;if(currentSeek===undefined){return;}
+if(currentSeek.target!==target){this.seekError_=true;return;}
+if(currentSeek.pipelineSeekTime!==undefined){this.seekError_=true;return;}
+currentSeek.pipelineSeekTime=time-currentSeek.startTime;}
+processBufferingHaveEnough(time){if(this.seekError_)return;const currentSeek=this.currentSeek_;if(currentSeek===undefined){return;}
+if(currentSeek.pipelineSeekTime===undefined){return;}
+currentSeek.seekTime=time-currentSeek.startTime;this.currentSeek_=undefined;}
+processOnEnded(playEndTime,duration){if(this.playStart_===undefined)return;if(this.seekTimes_.size!==0||this.seekError_)return;if(this.bufferingTime_!==undefined)return;duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.NONE,tr.b.UnitPrefixScale.METRIC.MILLI);const playTime=playEndTime-this.playStart_;if(this.timeToVideoPlay_!==undefined){this.bufferingTime_=playTime-duration-this.timeToVideoPlay_;}else if(this.timeToAudioPlay!==undefined){this.bufferingTime_=playTime-duration-this.timeToAudioPlay_;}}
+addMetricToHistograms(histograms){this.addSample_(histograms,'time_to_video_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToVideoPlay);this.addSample_(histograms,'time_to_audio_play',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.timeToAudioPlay);this.addSample_(histograms,'dropped_frame_count',tr.b.Unit.byName.count_smallerIsBetter,this.droppedFrameCount);for(const[key,value]of this.seekTimes.entries()){const keyString=key.toString().replace('.','_');this.addSample_(histograms,'pipeline_seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.pipelineSeekTime);this.addSample_(histograms,'seek_time_'+keyString,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,value.seekTime);}
+this.addSample_(histograms,'buffering_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,this.bufferingTime);}
+addSample_(histograms,name,unit,sample){if(sample===undefined)return;const histogram=histograms.getHistogramNamed(name);if(histogram===undefined){histograms.createHistogram(name,unit,sample);}else{histogram.addSample(sample);}}}
+tr.metrics.MetricRegistry.register(mediaMetric);return{mediaMetric,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const UNKNOWN_THREAD_NAME='Unknown';const CATEGORY_THREAD_MAP=new Map();CATEGORY_THREAD_MAP.set('total_all',[/.*/]);CATEGORY_THREAD_MAP.set('browser',[/^Browser Compositor$/,/^CrBrowserMain$/]);CATEGORY_THREAD_MAP.set('display_compositor',[/^VizCompositorThread$/]);CATEGORY_THREAD_MAP.set('GPU',[/^Chrome_InProcGpuThread$/,/^CrGpuMain$/]);CATEGORY_THREAD_MAP.set('IO',[/IOThread/]);CATEGORY_THREAD_MAP.set('raster',[/CompositorTileWorker/]);CATEGORY_THREAD_MAP.set('renderer_compositor',[/^Compositor$/]);CATEGORY_THREAD_MAP.set('renderer_main',[/^CrRendererMain$/]);CATEGORY_THREAD_MAP.set('total_rendering',[/^Browser Compositor$/,/^Chrome_InProcGpuThread$/,/^Compositor$/,/CompositorTileWorker/,/^CrBrowserMain$/,/^CrGpuMain$/,/^CrRendererMain$/,/IOThread/,/^VizCompositorThread$/]);const ALL_CATEGORIES=[...CATEGORY_THREAD_MAP.keys(),'other'];function addValueToMap_(map,key,value){const oldValue=map.get(key)||0;map.set(key,oldValue+value);}
+function categoryShouldHaveBreakdown(category){return category==='total_all'||category==='total_rendering';}
+function*getCategories_(threadName){let isOther=true;for(const[category,regexps]of CATEGORY_THREAD_MAP){for(const regexp of regexps){if(regexp.test(threadName)){if(category!=='total_all')isOther=false;yield category;break;}}}
+if(isOther)yield'other';}
+function isSubset_(regexps1,regexps2){for(const r1 of regexps1){if(regexps2.find(r2=>r2.toString()===r1.toString())===undefined){return false;}}
+return true;}
+function addCpuUtilizationHistograms(histograms,model,segments,segmentCostFunc,histogramNameFunc,description,unit){if(!unit)unit=tr.b.Unit.byName.unitlessNumber;const histogramMap=new Map();for(const category of ALL_CATEGORIES){const histogram=histograms.createHistogram(histogramNameFunc(category),unit,[],{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1,50,20),description,summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histogramMap.set(category,histogram);}
+for(const[category,regexps]of CATEGORY_THREAD_MAP){const relatedCategories=new tr.v.d.RelatedNameMap();const histogram=histogramMap.get(category);for(const[otherCategory,otherRegexps]of CATEGORY_THREAD_MAP){if(otherCategory===category)continue;if(category!=='all'&&!isSubset_(otherRegexps,regexps))continue;const otherHistogram=histogramMap.get(otherCategory);relatedCategories.set(otherCategory,otherHistogram.name);}
+if([...relatedCategories.values()].length>0){histogram.diagnostics.set('breakdown',relatedCategories);}}
+for(const segment of segments){const threadValues=new Map();for(const thread of model.getAllThreads()){addValueToMap_(threadValues,thread.name||UNKNOWN_THREAD_NAME,segmentCostFunc(thread,segment));}
+const categoryValues=new Map();const breakdowns=new Map();for(const[threadName,coresPerSec]of threadValues){for(const category of getCategories_(threadName)){addValueToMap_(categoryValues,category,coresPerSec);if(!categoryShouldHaveBreakdown(category))continue;if(!breakdowns.has(category)){breakdowns.set(category,new tr.v.d.Breakdown());}
+breakdowns.get(category).set(threadName,coresPerSec);}}
+for(const category of ALL_CATEGORIES){const value=categoryValues.get(category)||0;const diagnostics=new tr.v.d.DiagnosticMap();const breakdown=breakdowns.get(category);if(breakdown)diagnostics.set('breakdown',breakdown);const histogram=histogramMap.get(category);histogram.addSample(value,diagnostics);}}}
+const SUMMARY_OPTIONS={percentile:[0.90,0.95],ci:[0.95],};return{addCpuUtilizationHistograms,SUMMARY_OPTIONS,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const PRESENT_EVENT='Display::FrameDisplayed';const DISPLAY_EVENT='BenchmarkInstrumentation::DisplayRenderingStats';const DRM_EVENT='DrmEventFlipComplete';const SURFACE_FLINGER_EVENT='vsync_before';const COMPOSITOR_FRAME_PRESENTED_EVENT='FramePresented';const MIN_FRAME_LENGTH=0.5;const MIN_FRAME_COUNT=10;const PAUSE_THRESHOLD=20;const ASH_ENVIRONMENT='ash';const BROWSER_ENVIRONMENT='browser';class FrameEvent{constructor(event){this.event_=event;}
+get eventStart(){return this.event_.start;}
+get frameStart(){if(this.event_.title!==DRM_EVENT)return this.event_.start;const data=this.event_.args.data;const TIME=tr.b.UnitScale.TIME;return tr.b.convertUnit(data['vblank.tv_sec'],TIME.SEC,TIME.MILLI_SEC)+
+tr.b.convertUnit(data['vblank.tv_usec'],TIME.MICRO_SEC,TIME.MILLI_SEC);}
+get event(){return this.event_;}}
+class FrameSegment{constructor(frameEvent,duration){this.frameEvent_=frameEvent;this.duration_=duration;this.segment_=new tr.model.um.Segment(frameEvent.eventStart,duration);this.length_=undefined;}
+updateLength(refreshPeriod){this.length_=this.duration_/refreshPeriod;}
+get segment(){return this.segment_;}
+get boundsRange(){return this.segment_.boundsRange;}
+get length(){return this.length_;}
+get duration(){return this.duration_;}
+get event(){return this.frameEvent_.event;}}
+function getDisplayCompositorPresentationEventsExp_(modelHelper){if(!modelHelper)return[];function findEventsFromProcess(process){const events=[];for(const event of process.findTopmostSlicesNamed(PRESENT_EVENT)){events.push(event);}
+return events;}
+if(modelHelper.gpuHelper){const events=findEventsFromProcess(modelHelper.gpuHelper.process);if(events.length>0)return events;}
+if(!modelHelper.browserProcess)return[];return findEventsFromProcess(modelHelper.browserProcess);}
+function getDisplayCompositorPresentationEvents_(modelHelper){if(!modelHelper||!modelHelper.browserProcess)return[];let events=[];if(modelHelper.surfaceFlingerProcess){events=[...modelHelper.surfaceFlingerProcess.findTopmostSlicesNamed(SURFACE_FLINGER_EVENT)];if(events.length>0)return events;}
+if(modelHelper.gpuHelper){const gpuProcess=modelHelper.gpuHelper.process;events=[...gpuProcess.findTopmostSlicesNamed(DRM_EVENT)];if(events.length>0)return events;events=[...gpuProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];if(events.length>0)return events;}
+return[...modelHelper.browserProcess.findTopmostSlicesNamed(DISPLAY_EVENT)];}
+function getUIPresentationEvents_(modelHelper){if(!modelHelper||!modelHelper.browserProcess)return[];const legacyEvents=[];const eventsByEnvironment={};eventsByEnvironment[ASH_ENVIRONMENT]=[];eventsByEnvironment[BROWSER_ENVIRONMENT]=[];for(const event of modelHelper.browserProcess.findTopmostSlicesNamed(COMPOSITOR_FRAME_PRESENTED_EVENT)){if(!('environment'in event.args)){legacyEvents.push(event);}else{eventsByEnvironment[event.args.environment].push(event);}}
+if(eventsByEnvironment[ASH_ENVIRONMENT].length>0){return eventsByEnvironment[ASH_ENVIRONMENT];}
+if(eventsByEnvironment[BROWSER_ENVIRONMENT].length>0){return eventsByEnvironment[BROWSER_ENVIRONMENT];}
+return legacyEvents;}
+function computeFrameSegments_(events,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const frameEvents=events.map(e=>new FrameEvent(e));const frameSegments=[];for(const segment of segments){const filtered=segment.boundsRange.filterArray(frameEvents,x=>x.eventStart);if(filtered.length<minFrameCount)continue;for(let i=1;i<filtered.length;i++){const duration=filtered[i].frameStart-filtered[i-1].frameStart;frameSegments.push(new FrameSegment(filtered[i-1],duration));}}
+return frameSegments;}
+function addBasicFrameTimeHistograms_(histograms,frameSegments,prefix){const frameTimes=(frameSegments.length===0)?[0]:frameSegments.map(x=>x.duration);histograms.createHistogram(`${prefix}frame_times`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,frameTimes,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,50,20),description:'Raw frame times.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram(`${prefix}percentage_smooth`,tr.b.Unit.byName.unitlessNumber_biggerIsBetter,100*tr.b.math.Statistics.sum(frameTimes,(x=>(x<17?1:0)))/frameTimes.length,{description:'Percentage of frames that were hitting 60 FPS.',summaryOptions:{},});}
+function addFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const events=getDisplayCompositorPresentationEvents_(modelHelper);if(!events)return;addFrameTimeHistogramsHelper(histograms,model,segments,events,'',true,minFrameCount);const eventsExp=getDisplayCompositorPresentationEventsExp_(modelHelper);if(eventsExp&&eventsExp.length>0){addFrameTimeHistogramsHelper(histograms,model,segments,eventsExp,'exp_',false,minFrameCount);}}
+function addFrameTimeHistogramsHelper(histograms,model,segments,events,prefix,addCpuMetrics,minFrameCount){const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,prefix+'');if(addCpuMetrics){tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getCpuTimeForRange(segment.boundsRange),category=>`thread_${category}_cpu_time_per_frame`,'CPU cores of a thread group per frame',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);tr.metrics.rendering.addCpuUtilizationHistograms(histograms,model,frameSegments,(thread,segment)=>thread.getNumToplevelSlicesForRange(segment.boundsRange),category=>`tasks_per_frame_${category}`,'Number of tasks of a thread group per frame',tr.b.Unit.byName.unitlessNumber_smallerIsBetter);let totalWallTime=0;let totalCpuTime=0;for(const segment of frameSegments){for(const thread of model.getAllThreads()){totalCpuTime+=thread.getCpuTimeForRange(segment.boundsRange);totalWallTime+=thread.getWallTimeForRange(segment.boundsRange);}}
+histograms.createHistogram('cpu_wall_time_ratio',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,totalCpuTime/totalWallTime,{description:'Ratio of total cpu-time vs. wall-time.',summaryOptions:{},});}
+const refreshPeriod=getRefreshPeriod(model,frameSegments.map(fs=>fs.boundsRange));frameSegments.forEach(fs=>fs.updateLength(refreshPeriod));const validFrames=frameSegments.filter(fs=>fs.length>=MIN_FRAME_LENGTH);const totalFrameDuration=tr.b.math.Statistics.sum(frameSegments,fs=>fs.duration);addJankCountHistograms(histograms,validFrames,prefix);const frameLengths=validFrames.map(frame=>frame.length);histograms.createHistogram(prefix+'frame_lengths',tr.b.Unit.byName.unitlessNumber_smallerIsBetter,frameLengths,{binBoundaries:tr.v.HistogramBinBoundaries.createLinear(0,5,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Frame times in vsyncs.'});histograms.createHistogram(prefix+'avg_surface_fps',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,frameLengths.length/tr.b.convertUnit(totalFrameDuration,tr.b.UnitScale.TIME.MILLI_SEC,tr.b.UnitScale.TIME.SEC),{description:'Average frames per second.',summaryOptions:{},});}
+function addUIFrameTimeHistograms(histograms,model,segments,opt_minFrameCount){const minFrameCount=opt_minFrameCount||MIN_FRAME_COUNT;const events=getUIPresentationEvents_(model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper));if(events.length===0)return;const frameSegments=computeFrameSegments_(events,segments,minFrameCount);addBasicFrameTimeHistograms_(histograms,frameSegments,'ui_');}
+function addJankCountHistograms(histograms,validFrames,prefix){const jankEvents=[];for(let i=1;i<validFrames.length;i++){const change=Math.round((validFrames[i].length-validFrames[i-1].length));if(change>0&&change<PAUSE_THRESHOLD){jankEvents.push(validFrames[i].event);}}
+const jankCount=jankEvents.length;const diagnostics=new tr.v.d.DiagnosticMap();diagnostics.set('events',new tr.v.d.RelatedEventSet(jankEvents));diagnostics.set('timestamps',new tr.v.d.GenericSet(jankEvents.map(e=>e.start)));const histogram=histograms.createHistogram(prefix+'jank_count',tr.b.Unit.byName.count_smallerIsBetter,{value:jankCount,diagnostics},{description:'Number of changes in frame rate.',summaryOptions:{},});}
+function getRefreshPeriod(model,ranges){for(const metadata of model.metadata){if(metadata.value&&metadata.value.surface_flinger){return metadata.value.surface_flinger.refresh_period;}}
+const FRAME_LENGTH=1000.0/60;const BEGIN_FRAME_ARGS='Scheduler::BeginFrame';const FRAME_INTERVAL='interval_us';const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==BEGIN_FRAME_ARGS)continue;const data=slice.args.args;if(!(FRAME_INTERVAL in data)){throw new Error(`${FRAME_INTERVAL} is missing`);}
+return tr.b.convertUnit(data[FRAME_INTERVAL],tr.b.UnitScale.TIME.MICRO_SEC,tr.b.UnitScale.TIME.MILLI_SEC);}}
+return FRAME_LENGTH;}
+return{addFrameTimeHistograms,addUIFrameTimeHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const RGB_DECODE_EVENT='ImageFrameGenerator::decode';const YUV_DECODE_EVENT='ImageFrameGenerator::decodeToYUV';const BLINK_GPU_RASTER_DECODE_EVENT='GpuImageDecodeCache::DecodeImage';const BLINK_SOFTWARE_RASTER_DECODE_EVENT='SoftwareImageDecodeCache::'+'DecodeImageInTask';function getImageDecodingEvents_(modelHelper,ranges){if(!modelHelper||!modelHelper.rendererHelpers)return[];const events=[];for(const renderer of Object.values(modelHelper.rendererHelpers)){for(const thread of renderer.rasterWorkerThreads){const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title===RGB_DECODE_EVENT||slice.title===YUV_DECODE_EVENT||slice.title===BLINK_GPU_RASTER_DECODE_EVENT||slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT){events.push(slice);}}}}
+return events;}
+function addImageDecodeTimeHistograms(histograms,model,segments){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const decodeEvents=getImageDecodingEvents_(modelHelper,segments.map(s=>s.boundsRange));if(!decodeEvents)return;histograms.createHistogram('rgb_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===RGB_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink RGB decoding path for a chunk '+'of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('yuv_decode_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===YUV_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of the Blink YUV decoding path for a '+'chunk of image data (possibly the whole image).',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_gpu_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_GPU_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'GpuImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});histograms.createHistogram('blink_decode_time_software_rasterization',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,decodeEvents.filter(slice=>slice.title===BLINK_SOFTWARE_RASTER_DECODE_EVENT).map(slice=>slice.cpuDuration),{description:'Duration of decoding and scaling within the '+'SoftwareImageDecodeCache for a chunk of image data '+'(possibly the whole image)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});}
+return{addImageDecodeTimeHistograms};});'use strict';tr.exportTo('tr.metrics.rendering',function(){function eventIsValidGraphicsEvent_(event,eventMap){if(event.title!=='Graphics.Pipeline'||!event.bindId||!event.args||!event.args.step){return false;}
+const bindId=event.bindId;if(eventMap.has(bindId)&&event.args.step in eventMap.get(bindId)){if(event.args.step==='IssueBeginFrame'||event.args.step==='ReceiveBeginFrame'){throw new Error('Unexpected duplicate step: '+event.args.step);}
+return false;}
+return true;}
+function generateBreakdownForCompositorPipelineInClient_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('time before GenerateRenderPass',flow.GenerateRenderPass.start-flow.ReceiveBeginFrame.start);breakdown.set('GenerateRenderPass duration',flow.GenerateRenderPass.duration);breakdown.set('GenerateCompositorFrame duration',flow.GenerateCompositorFrame.duration);breakdown.set('SubmitCompositorFrame duration',flow.SubmitCompositorFrame.duration);return breakdown;}
+function generateBreakdownForCompositorPipelineInService_(flow){const breakdown=new tr.v.d.Breakdown();breakdown.set('Processing CompositorFrame on reception',flow.ReceiveCompositorFrame.duration);breakdown.set('Delay before SurfaceAggregation',flow.SurfaceAggregation.start-flow.ReceiveCompositorFrame.end);breakdown.set('SurfaceAggregation duration',flow.SurfaceAggregation.duration);return breakdown;}
+function generateBreakdownForDraw_(drawEvent){const breakdown=new tr.v.d.Breakdown();for(const slice of drawEvent.subSlices){breakdown.set(slice.title,slice.duration);}
+return breakdown;}
+function getDisplayCompositorThread_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const gpuHelper=chromeHelper.gpuHelper;if(gpuHelper){const thread=gpuHelper.process.findAtMostOneThreadNamed('VizCompositorThread');if(thread){return thread;}}
+if(!chromeHelper.browserProcess)return null;return chromeHelper.browserProcess.findAtMostOneThreadNamed('CrBrowserMain');}
+function getRasterTaskTimes(sourceFrameNumber,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const renderers=modelHelper.telemetryHelper.renderersWithIR;if(renderers.length===0)return;const rasterThreads=renderers[0].rasterWorkerThreads;let earliestStart=undefined;let lastEnd=undefined;for(const rasterThread of rasterThreads){for(const slice of[...rasterThread.findTopmostSlicesNamed('TaskGraphRunner::RunTask')]){if(slice.args&&slice.args.source_frame_number_&&slice.args.source_frame_number_===sourceFrameNumber){if(earliestStart===undefined||slice.start<earliestStart){earliestStart=slice.start;}
+if(lastEnd===undefined||slice.end>lastEnd){lastEnd=slice.end;}}}}
+return{start:earliestStart,end:lastEnd};}
+function addPipelineHistograms(histograms,model,segments){const ranges=segments.map(s=>s.boundsRange);const bindEvents=new Map();for(const thread of model.getAllThreads()){for(const event of thread.sliceGroup.childEvents()){if(!eventIsValidGraphicsEvent_(event,bindEvents))continue;for(const range of ranges){if(range.containsExplicitRangeInclusive(event.start,event.end)){if(!bindEvents.has(event.bindId))bindEvents.set(event.bindId,{});break;}}
+if(bindEvents.has(event.bindId)){bindEvents.get(event.bindId)[event.args.step]=event;}}}
+const dcThread=getDisplayCompositorThread_(model);const drawEvents={};if(dcThread){const events=[...dcThread.findTopmostSlicesNamed('Graphics.Pipeline.DrawAndSwap')];for(const segment of segments){const filteredEvents=segment.boundsRange.filterArray(events,evt=>evt.start);for(const event of filteredEvents){if((event.args&&event.args.status==='canceled')||!event.id.startsWith(':ptr:')){continue;}
+const id=parseInt(event.id.substring(5),16);if(id in drawEvents){throw new Error('Duplicate draw events: '+id);}
+drawEvents[id]=event;}}}
+const issueToReceipt=histograms.createHistogram('pipeline:begin_frame_transport',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency of begin-frame message from the display '+'compositor to the client, including the IPC latency and task-'+'queue time in the client.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterStart=histograms.createHistogram('pipeline:begin_frame_to_raster_start',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the beginning of the first CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const issueToRasterEnd=histograms.createHistogram('pipeline:begin_frame_to_raster_end',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame message and '+'the end of the last CompositorTask run in the compositor.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const receiptToSubmit=histograms.createHistogram('pipeline:begin_frame_to_frame_submission',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between begin-frame reception and '+'CompositorFrame submission in the renderer.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const submitToAggregate=histograms.createHistogram('pipeline:frame_submission_to_display',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'Latency between CompositorFrame submission in the '+'renderer to display in the display-compositor, including IPC '+'latency, task-queue time in the display-compositor, and '+'additional processing (e.g. surface-sync etc.)',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});const aggregateToDraw=histograms.createHistogram('pipeline:draw',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:'How long it takes for the gpu-swap step.',summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,});for(const flow of bindEvents.values()){if(!flow.IssueBeginFrame||!flow.ReceiveBeginFrame||!flow.SubmitCompositorFrame||!flow.SurfaceAggregation){continue;}
+issueToReceipt.addSample(flow.ReceiveBeginFrame.start-
+flow.IssueBeginFrame.start);receiptToSubmit.addSample(flow.SubmitCompositorFrame.end-flow.ReceiveBeginFrame.start,{breakdown:generateBreakdownForCompositorPipelineInClient_(flow)});submitToAggregate.addSample(flow.SurfaceAggregation.end-flow.SubmitCompositorFrame.end,{breakdown:generateBreakdownForCompositorPipelineInService_(flow)});if(flow.SubmitCompositorFrame.parentSlice){const sourceFrameNumber=flow.SubmitCompositorFrame.parentSlice.args.source_frame_number_;const rasterDuration=getRasterTaskTimes(sourceFrameNumber,model);if(rasterDuration&&rasterDuration.start&&rasterDuration.end){const receiveToStart=rasterDuration.start-
+flow.ReceiveBeginFrame.start;const receiveToEnd=rasterDuration.end-flow.ReceiveBeginFrame.end;if(receiveToEnd>0){issueToRasterStart.addSample(receiveToStart>0?receiveToStart:0);issueToRasterEnd.addSample(receiveToEnd);}}}
+if(flow.SurfaceAggregation.args&&flow.SurfaceAggregation.args.display_trace){const displayTrace=flow.SurfaceAggregation.args.display_trace;if(!(displayTrace in drawEvents))continue;const drawEvent=drawEvents[displayTrace];aggregateToDraw.addSample(drawEvent.duration,{breakdown:generateBreakdownForDraw_(drawEvent)});}}}
+return{addPipelineHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const IMPL_THREAD_RENDERING_STATS_EVENT='BenchmarkInstrumentation::ImplThreadRenderingStats';const VISIBLE_CONTENT_DATA='visible_content_area';const APPROXIMATED_VISIBLE_CONTENT_DATA='approximated_visible_content_area';const CHECKERBOARDED_VISIBLE_CONTENT_DATA='checkerboarded_visible_content_area';function addPixelsHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;const approximatedPixelPercentages=[];const checkerboardedPixelPercentages=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){if(rendererHelper.compositorThread===undefined)continue;const slices=rendererHelper.compositorThread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==IMPL_THREAD_RENDERING_STATS_EVENT)continue;const data=slice.args.data;if(!(VISIBLE_CONTENT_DATA in data)){throw new Error(`${VISIBLE_CONTENT_DATA} is missing`);}
+const visibleContentArea=data[VISIBLE_CONTENT_DATA];if(visibleContentArea===0){continue;}
+if(APPROXIMATED_VISIBLE_CONTENT_DATA in data){approximatedPixelPercentages.push(data[APPROXIMATED_VISIBLE_CONTENT_DATA]/visibleContentArea);}
+if(CHECKERBOARDED_VISIBLE_CONTENT_DATA in data){checkerboardedPixelPercentages.push(data[CHECKERBOARDED_VISIBLE_CONTENT_DATA]/visibleContentArea);}}}
+histograms.createHistogram('mean_pixels_approximated',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(approximatedPixelPercentages),{description:'Percentage of pixels that were approximated '+'(checkerboarding, low-resolution tiles, etc.).',summaryOptions:{},});histograms.createHistogram('mean_pixels_checkerboarded',tr.b.Unit.byName.normalizedPercentage_smallerIsBetter,100*tr.b.math.Statistics.mean(checkerboardedPixelPercentages),{description:'Percentage of pixels that were checkerboarded.',summaryOptions:{},});}
+return{addPixelsHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const BEGIN_MAIN_FRAME_EVENT='ThreadProxy::BeginMainFrame';const SEND_BEGIN_FRAME_EVENT='ThreadProxy::ScheduledActionSendBeginMainFrame';function getEventTimesByBeginFrameId_(thread,title,ranges){const out=new Map();const slices=thread.sliceGroup;for(const slice of slices.getDescendantEventsInSortedRanges(ranges)){if(slice.title!==title)continue;const id=slice.args.begin_frame_id;if(id===undefined)throw new Error('Event is missing begin_frame_id');if(out.has(id))throw new Error(`There must be exactly one ${title}`);out.set(id,slice.start);}
+return out;}
+function addQueueingDurationHistograms(histograms,model,segments){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let targetRenderers=chromeHelper.telemetryHelper.renderersWithIR;if(targetRenderers.length===0){targetRenderers=Object.values(chromeHelper.rendererHelpers);}
+const queueingDurations=[];const ranges=segments.map(s=>s.boundsRange);for(const rendererHelper of targetRenderers){const mainThread=rendererHelper.mainThread;const compositorThread=rendererHelper.compositorThread;if(mainThread===undefined||compositorThread===undefined)continue;const beginMainFrameTimes=getEventTimesByBeginFrameId_(mainThread,BEGIN_MAIN_FRAME_EVENT,ranges);const sendBeginFrameTimes=getEventTimesByBeginFrameId_(compositorThread,SEND_BEGIN_FRAME_EVENT,ranges);for(const[id,time]of sendBeginFrameTimes){queueingDurations.push(beginMainFrameTimes.get(id)-time);}}
+histograms.createHistogram('queueing_durations',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,queueingDurations,{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(0.01,2,20),summaryOptions:tr.metrics.rendering.SUMMARY_OPTIONS,description:'Time between ScheduledActionSendBeginMainFrame in '+'the compositor thread and the corresponding '+'BeginMainFrame in the main thread.'});}
+return{addQueueingDurationHistograms,};});'use strict';tr.exportTo('tr.metrics.rendering',function(){const GESTURE_EVENT='SyntheticGestureController::running';function renderingMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper)return;let segments=chromeHelper.telemetryHelper.irSegments;if(segments.length===0){segments=chromeHelper.telemetryHelper.animationSegments;}
+if(segments.length>0){tr.metrics.rendering.addFrameTimeHistograms(histograms,model,segments);tr.metrics.rendering.addImageDecodeTimeHistograms(histograms,model,segments);tr.metrics.rendering.addPipelineHistograms(histograms,model,segments);tr.metrics.rendering.addPixelsHistograms(histograms,model,segments);tr.metrics.rendering.addQueueingDurationHistograms(histograms,model,segments);}
+const uiSegments=chromeHelper.telemetryHelper.uiSegments;if(uiSegments.length>0){tr.metrics.rendering.addUIFrameTimeHistograms(histograms,model,chromeHelper.telemetryHelper.uiSegments);}}
+tr.metrics.MetricRegistry.register(renderingMetric,{requiredCategories:['benchmark','toplevel'],});return{renderingMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(80e3,30);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function reportedByPageMetric(histograms,model){const timeToViewable=histograms.createHistogram('reported_by_page:time_to_viewable',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start'+'to telemetry:reported_by_page:viewable',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractive=histograms.createHistogram('reported_by_page:time_to_interactive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from navigation start '+'to telemetry:reported_by_page:interactive',summaryOptions:SUMMARY_OPTIONS,});const benchmarkTime=histograms.createHistogram('reported_by_page:benchmark_time',timeDurationInMs_smallerIsBetter,[],{binBoundaries:METRIC_BOUNDARIES,description:'Time from telemetry:reported_by_page:benchmark_begin '+'to telemetry:reported_by_page:benchmark_end',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:viewable',timeToViewable);measureUserTime(rendererHelper,'navigationStart','telemetry:reported_by_page:interactive',timeToInteractive);measureUserTime(rendererHelper,'telemetry:reported_by_page:benchmark_begin','telemetry:reported_by_page:benchmark_end',benchmarkTime);}}
+function measureUserTime(rendererHelper,startName,endName,histogram){const startEventByNavId=new Map();for(const event of rendererHelper.mainThread.sliceGroup.childEvents()){const navId=getNavigationId(event);if(!navId)continue;if(EventFinderUtils.hasCategoryAndName(event,'blink.user_timing',startName)){startEventByNavId.set(navId,event);}
+if(EventFinderUtils.hasCategoryAndName(event,'blink.user_timing',endName)){if(!startEventByNavId.has(navId)){throw Error(`Missing ${startName} for ${endName} at {event.start}`);}
+const range=tr.b.math.Range.fromExplicitRange(startEventByNavId.get(navId).start,event.start);histogram.addSample(range.duration);startEventByNavId.delete(navId);}}}
+function getNavigationId(event){return event.args.data&&event.args.data.navigationId;}
+tr.metrics.MetricRegistry.register(reportedByPageMetric);return{reportedByPageMetric};});'use strict';tr.exportTo('tr.metrics',function(){function sampleExceptionMetric(histograms,model){const hist=new tr.v.Histogram('foo',tr.b.Unit.byName.sizeInBytes_smallerIsBetter);hist.addSample(9);hist.addSample(91,{bar:new tr.v.d.GenericSet([{hello:42}])});for(const expectation of model.userModel.expectations){if(expectation instanceof tr.model.um.ResponseExpectation){}else if(expectation instanceof tr.model.um.AnimationExpectation){}else if(expectation instanceof tr.model.um.IdleExpectation){}else if(expectation instanceof tr.model.um.LoadExpectation){}}
+const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const[pid,process]of Object.entries(model.processes)){}
+histograms.addHistogram(hist);throw new Error('There was an error');}
+tr.metrics.MetricRegistry.register(sampleExceptionMetric);return{sampleExceptionMetric,};});'use strict';tr.exportTo('tr.metrics',function(){function sampleMetric(histograms,model){const hist=new tr.v.Histogram('foo',tr.b.Unit.byName.sizeInBytes_smallerIsBetter);hist.addSample(9);hist.addSample(91,{bar:new tr.v.d.GenericSet([{hello:42}])});for(const expectation of model.userModel.expectations){if(expectation instanceof tr.model.um.ResponseExpectation){}else if(expectation instanceof tr.model.um.AnimationExpectation){}else if(expectation instanceof tr.model.um.IdleExpectation){}else if(expectation instanceof tr.model.um.LoadExpectation){}}
+const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const[pid,process]of Object.entries(model.processes)){}
+histograms.addHistogram(hist);}
+tr.metrics.MetricRegistry.register(sampleMetric);return{sampleMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const HANDLE_INPUT_EVENT_TITLE='WebViewImpl::handleInputEvent';function findPrecedingEvents_(eventsA,eventsB){const events=new Map();let eventsBIndex=0;for(const eventA of eventsA){for(;eventsBIndex<eventsB.length;eventsBIndex++){if(eventsB[eventsBIndex].start>eventA.start)break;}
+if(eventsBIndex>0){events.set(eventA,eventsB[eventsBIndex-1]);}}
+return events;}
+function findFollowingEvents_(eventsA,eventsB){const events=new Map();let eventsBIndex=0;for(const eventA of eventsA){for(;eventsBIndex<eventsB.length;eventsBIndex++){if(eventsB[eventsBIndex].start>=eventA.start)break;}
+if(eventsBIndex>=0&&eventsBIndex<eventsB.length){events.set(eventA,eventsB[eventsBIndex]);}}
+return events;}
+function getSpaNavigationStartCandidates_(rendererHelper,browserHelper){const isNavStartEvent=e=>{if(e.title===HANDLE_INPUT_EVENT_TITLE&&e.args.type==='MouseUp'){return true;}
+return e.title==='NavigationControllerImpl::GoToIndex';};return[...rendererHelper.mainThread.sliceGroup.getDescendantEvents(),...browserHelper.mainThread.sliceGroup.getDescendantEvents()].filter(isNavStartEvent);}
+function getSpaNavigationEvents_(rendererHelper){const isNavEvent=e=>e.category==='blink'&&e.title==='FrameLoader::updateForSameDocumentNavigation';return[...rendererHelper.mainThread.sliceGroup.getDescendantEvents()].filter(isNavEvent);}
+function getInputLatencyEvents_(browserHelper){const isInputLatencyEvent=e=>e.title==='InputLatency::MouseUp';return browserHelper.getAllAsyncSlicesMatching(isInputLatencyEvent);}
+function getInputLatencyEventByBindIdMap_(browserHelper){const inputLatencyEventByBindIdMap=new Map();for(const event of getInputLatencyEvents_(browserHelper)){inputLatencyEventByBindIdMap.set(event.args.data.trace_id,event);}
+return inputLatencyEventByBindIdMap;}
+function getSpaNavigationEventToNavigationStartMap_(rendererHelper,browserHelper){const mainThread=rendererHelper.mainThread;const spaNavEvents=getSpaNavigationEvents_(rendererHelper);const navStartCandidates=getSpaNavigationStartCandidates_(rendererHelper,browserHelper).sort(tr.importer.compareEvents);const spaNavEventToNavStartCandidateMap=findPrecedingEvents_(spaNavEvents,navStartCandidates);const inputLatencyEventByBindIdMap=getInputLatencyEventByBindIdMap_(browserHelper);const spaNavEventToNavStartEventMap=new Map();for(const[spaNavEvent,navStartCandidate]of
+spaNavEventToNavStartCandidateMap){if(navStartCandidate.title===HANDLE_INPUT_EVENT_TITLE){const inputLatencySlice=inputLatencyEventByBindIdMap.get(Number(navStartCandidate.parentSlice.bindId));if(inputLatencySlice){spaNavEventToNavStartEventMap.set(spaNavEvent,inputLatencySlice);}}else{spaNavEventToNavStartEventMap.set(spaNavEvent,navStartCandidate);}}
+return spaNavEventToNavStartEventMap;}
+function getFirstPaintEvents_(rendererHelper){const isFirstPaintEvent=e=>e.category==='blink'&&e.title==='PaintLayerCompositor::updateIfNeededRecursive';return[...rendererHelper.mainThread.sliceGroup.getDescendantEvents()].filter(isFirstPaintEvent);}
+function getSpaNavigationEventToFirstPaintEventMap_(rendererHelper){const spaNavEvents=getSpaNavigationEvents_(rendererHelper).sort(tr.importer.compareEvents);const firstPaintEvents=getFirstPaintEvents_(rendererHelper).sort(tr.importer.compareEvents);return findFollowingEvents_(spaNavEvents,firstPaintEvents);}
+function findSpaNavigationsOnRenderer(rendererHelper,browserHelper){const spaNavEventToNavStartMap=getSpaNavigationEventToNavigationStartMap_(rendererHelper,browserHelper);const spaNavEventToFirstPaintEventMap=getSpaNavigationEventToFirstPaintEventMap_(rendererHelper);const spaNavigations=[];for(const[spaNavEvent,navStartEvent]of
+spaNavEventToNavStartMap){if(spaNavEventToFirstPaintEventMap.has(spaNavEvent)){const firstPaintEvent=spaNavEventToFirstPaintEventMap.get(spaNavEvent);const isNavStartAsyncSlice=navStartEvent instanceof tr.model.AsyncSlice;spaNavigations.push({navStartCandidates:{inputLatencyAsyncSlice:isNavStartAsyncSlice?navStartEvent:undefined,goToIndexSlice:isNavStartAsyncSlice?undefined:navStartEvent},firstPaintEvent,url:spaNavEvent.args.url});}}
+return spaNavigations;}
+return{findSpaNavigationsOnRenderer,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function getWallClockSelfTime_(event,rangeOfInterest){if(event.duration===0)return 0;const selfTimeRanges=[rangeOfInterest.findIntersection(event.range)];for(const subSlice of event.subSlices){if(selfTimeRanges.length===0)return 0;const lastRange=selfTimeRanges.pop();selfTimeRanges.push(...tr.b.math.Range.findDifference(lastRange,subSlice.range));}
+return tr.b.math.Statistics.sum(selfTimeRanges,r=>r.duration);}
+function getCPUSelfTime_(event,rangeOfInterest){if(event.duration===0||event.selfTime===0)return 0;if(event.cpuSelfTime===undefined)return 0;const cpuTimeDensity=event.cpuSelfTime/event.selfTime;return getWallClockSelfTime_(event,rangeOfInterest)*cpuTimeDensity;}
+function generateTimeBreakdownTree(mainThread,rangeOfInterest,getEventSelfTime){if(mainThread===null)return;const breakdownTree={};for(const title of
+tr.e.chrome.ChromeUserFriendlyCategoryDriver.ALL_TITLES){breakdownTree[title]={total:0,events:{}};}
+for(const event of mainThread.sliceGroup.childEvents()){if(!rangeOfInterest.intersectsRangeExclusive(event.range))continue;const eventSelfTime=getEventSelfTime(event,rangeOfInterest);const title=tr.e.chrome.ChromeUserFriendlyCategoryDriver.fromEvent(event);breakdownTree[title].total+=eventSelfTime;if(breakdownTree[title].events[event.title]===undefined){breakdownTree[title].events[event.title]=0;}
+breakdownTree[title].events[event.title]+=eventSelfTime;let timeIntersectionRatio=0;if(event.duration>0){timeIntersectionRatio=rangeOfInterest.findExplicitIntersectionDuration(event.start,event.end)/event.duration;}
+const v8Runtime=event.args['runtime-call-stat'];if(v8Runtime!==undefined){const v8RuntimeObject=JSON.parse(v8Runtime);for(const runtimeCall in v8RuntimeObject){if(v8RuntimeObject[runtimeCall].length===2){if(breakdownTree.v8_runtime.events[runtimeCall]===undefined){breakdownTree.v8_runtime.events[runtimeCall]=0;}
+const runtimeTime=tr.b.Unit.timestampFromUs(v8RuntimeObject[runtimeCall][1]*timeIntersectionRatio);breakdownTree.v8_runtime.total+=runtimeTime;breakdownTree.v8_runtime.events[runtimeCall]+=runtimeTime;}}}}
+return breakdownTree;}
+function addIdleAndBlockByNetworkBreakdown_(breakdownTree,mainThreadEvents,networkEvents,rangeOfInterest){const mainThreadEventRanges=tr.b.math.convertEventsToRanges(mainThreadEvents);const networkEventRanges=tr.b.math.convertEventsToRanges(networkEvents);const eventRanges=mainThreadEventRanges.concat(networkEventRanges);const idleRanges=tr.b.math.findEmptyRangesBetweenRanges(eventRanges,rangeOfInterest);const totalFreeDuration=tr.b.math.Statistics.sum(idleRanges,range=>range.duration);breakdownTree.idle={total:totalFreeDuration,events:{}};let totalBlockedDuration=rangeOfInterest.duration;for(const[title,component]of Object.entries(breakdownTree)){if(title==='v8_runtime')continue;totalBlockedDuration-=component.total;}
+breakdownTree.blocked_on_network={total:Math.max(totalBlockedDuration,0),events:{}};}
+function generateWallClockTimeBreakdownTree(mainThread,networkEvents,rangeOfInterest){const breakdownTree=generateTimeBreakdownTree(mainThread,rangeOfInterest,getWallClockSelfTime_);const mainThreadEventsInRange=tr.model.helpers.getSlicesIntersectingRange(rangeOfInterest,mainThread.sliceGroup.topLevelSlices);addIdleAndBlockByNetworkBreakdown_(breakdownTree,mainThreadEventsInRange,networkEvents,rangeOfInterest);return breakdownTree;}
+function generateCpuTimeBreakdownTree(mainThread,rangeOfInterest){return generateTimeBreakdownTree(mainThread,rangeOfInterest,getCPUSelfTime_);}
+return{generateTimeBreakdownTree,generateWallClockTimeBreakdownTree,generateCpuTimeBreakdownTree,};});'use strict';tr.exportTo('tr.e.chrome',function(){const LCP_CANDIDATE_EVENT_TITLE='NavStartToLargestContentfulPaint::Candidate::AllFrames::UKM';const LCP_INVALIDATE_EVENT_TITLE='NavStartToLargestContentfulPaint::Invalidate::AllFrames::UKM';class LcpEvent{constructor(event){if(!LcpInvalidateEvent.isLcpInvalidateEvent(event)&&!LcpCandidateEvent.isLcpCandidateEvent(event)){throw new Error('The LCP event should be either a candidate event or'+'an invalidate event.');}
+if(event.start===undefined||event.args.main_frame_tree_node_id===undefined){throw new Error('The LCP event is in unexpected format.');}
+this.start=event.start;this.mainFrameTreeNodeId=event.args.main_frame_tree_node_id;}}
+class LcpCandidateEvent extends LcpEvent{constructor(event){super(event);const{durationInMilliseconds,size,type,inMainFrame}=event.args.data;if(durationInMilliseconds===undefined||size===undefined||type===undefined||inMainFrame===undefined||event.args.main_frame_tree_node_id===undefined||!LcpCandidateEvent.isLcpCandidateEvent(event)){throw new Error('The LCP candidate event is in unexpected format.');}
+this.durationInMilliseconds=durationInMilliseconds;this.size=size;this.type=type;this.inMainFrame=inMainFrame;}
+static isLcpCandidateEvent(event){return event.title===LCP_CANDIDATE_EVENT_TITLE;}}
+class LcpInvalidateEvent extends LcpEvent{constructor(event){super(event);if(!LcpInvalidateEvent.isLcpInvalidateEvent(event)){throw new Error('The LCP invalidate event is in unexpected format.');}}
+static isLcpInvalidateEvent(event){return event.title===LCP_INVALIDATE_EVENT_TITLE;}}
+class LargestContentfulPaint{constructor(allBrowserEvents){this.allBrowserEvents=allBrowserEvents;}
+findCandidates(){const finalLcpEvents=this.findFinalLcpEventOfEachNavigation(this.allBrowserEvents);const finalCandidates=finalLcpEvents.filter(finalLcpEvent=>!LcpInvalidateEvent.isLcpInvalidateEvent(finalLcpEvent));return finalCandidates;}
+findFinalLcpEventOfEachNavigation(allBrowserEvents){const lcpEvents=[];for(const lcpEvent of allBrowserEvents){if(LcpCandidateEvent.isLcpCandidateEvent(lcpEvent)){lcpEvents.push(new LcpCandidateEvent(lcpEvent));}else if(LcpInvalidateEvent.isLcpInvalidateEvent(lcpEvent)){lcpEvents.push(new LcpInvalidateEvent(lcpEvent));}}
+const lcpEventsGroupedByNavigation=new Map();for(const e of lcpEvents){const key=e.mainFrameTreeNodeId;if(!lcpEventsGroupedByNavigation.has(key)){lcpEventsGroupedByNavigation.set(key,[]);}
+lcpEventsGroupedByNavigation.get(key).push(e);}
+const finalLcpEventOfEachNavigation=[];for(const lcpEventList of lcpEventsGroupedByNavigation.values()){lcpEventList.sort((a,b)=>a.start-b.start);finalLcpEventOfEachNavigation.push(lcpEventList[lcpEventList.length-1]);}
+return finalLcpEventOfEachNavigation;}}
+return{LCP_CANDIDATE_EVENT_TITLE,LCP_INVALIDATE_EVENT_TITLE,LargestContentfulPaint,};});'use strict';tr.exportTo('tr.b.math',function(){function earthMoversDistance(firstHistogram,secondHistogram){const buckets=firstHistogram.length;if(secondHistogram.length!==buckets){throw new Error('Histograms have a different number of bins.');}
+const arrSum=arr=>arr.reduce((a,b)=>a+b,0);if(arrSum(firstHistogram)!==arrSum(secondHistogram)){throw new Error('The histograms\' sizes don\'t match.');}
+let total=0;let remainder=0;for(let bucket=0;bucket<buckets;bucket++){remainder+=secondHistogram[bucket]-
+firstHistogram[bucket];total+=Math.abs(remainder);}
+return total;}
+return{earthMoversDistance,};});'use strict';tr.exportTo('tr.e.chrome',function(){const earthMoversDistance=tr.b.math.earthMoversDistance;class SpeedIndex{static getSnapshotsProgress_(timestampedColorHistograms){const numberOfScreenshots=timestampedColorHistograms.length;const firstHistogram=timestampedColorHistograms[0].colorHistogram;const lastHistogram=timestampedColorHistograms[numberOfScreenshots-1].colorHistogram;const totalDistance=earthMoversDistance(firstHistogram[0],lastHistogram[0])+
+earthMoversDistance(firstHistogram[1],lastHistogram[1])+
+earthMoversDistance(firstHistogram[2],lastHistogram[2]);if(totalDistance===0){return[{value:1,ts:timestampedColorHistograms[0].ts}];}
+const snapshotsProgress=new Array(numberOfScreenshots);for(let i=0;i<numberOfScreenshots;i++){const histogram=timestampedColorHistograms[i].colorHistogram;const distance=earthMoversDistance(histogram[0],lastHistogram[0])+
+earthMoversDistance(histogram[1],lastHistogram[1])+
+earthMoversDistance(histogram[2],lastHistogram[2]);const moved=Math.max(totalDistance-distance,0);snapshotsProgress[i]={value:(moved/totalDistance),ts:timestampedColorHistograms[i].ts};}
+return snapshotsProgress;}
+static speedIndexFromSnapshotsProgress_(snapshotsProgress){if(snapshotsProgress.length===0){throw new Error('No snapshots were provided.');}
+let prevSnapshotTimeTaken=0;let prevSnapshotProgress=0;let speedIndex=0;const numberOfScreenshots=snapshotsProgress.length;for(let i=0;i<numberOfScreenshots;i++){const elapsed=snapshotsProgress[i].ts-prevSnapshotTimeTaken;speedIndex+=elapsed*(1.0-prevSnapshotProgress);prevSnapshotTimeTaken=snapshotsProgress[i].ts;prevSnapshotProgress=snapshotsProgress[i].value;}
+return Math.round(speedIndex);}
+static createColorHistogram(imagePixelValues){const n=imagePixelValues.length;const histogram=new Array(3);for(let j=0;j<3;j++){histogram[j]=new Array(256).fill(0);}
+for(let i=0;i<n;i+=4){const r=imagePixelValues[i];const g=imagePixelValues[i+1];const b=imagePixelValues[i+2];histogram[0][r]++;histogram[1][g]++;histogram[2][b]++;}
+return histogram;}
+static calculateSpeedIndex(timestampedColorHistograms){const snapshotsProgress=SpeedIndex.getSnapshotsProgress_(timestampedColorHistograms);return SpeedIndex.speedIndexFromSnapshotsProgress_(snapshotsProgress);}
+static lineSweep(lineSweepRects,viewport){const verticalSweepEdges=[];const horizontalSweepEdges=[];for(let i=0;i<lineSweepRects.length;i++){const rect=lineSweepRects[i];let left=rect.left;let right=rect.right;let top=rect.top;let bottom=rect.bottom;if(left>viewport.x+viewport.width)continue;if(right<viewport.x)continue;if(top>viewport.y+viewport.height)continue;if(bottom<viewport.y)continue;left=Math.max(left,viewport.y);right=Math.min(right,viewport.y+viewport.width);top=Math.max(top,viewport.y);bottom=Math.min(bottom,viewport.y+viewport.height);verticalSweepEdges.push({id:i,value:left,type:'left'},{id:i,value:right,type:'right'});horizontalSweepEdges.push({id:i,value:top,type:'top'},{id:i,value:bottom,type:'bottom'});}
+if(verticalSweepEdges.length===0||horizontalSweepEdges.length===0){return 0;}
+verticalSweepEdges.sort((a,b)=>a.value-b.value);horizontalSweepEdges.sort((a,b)=>a.value-b.value);const active=new Array(lineSweepRects.length).fill(false);let area=0;active[verticalSweepEdges[0].id]=true;for(let i=1;i<verticalSweepEdges.length;i++){const currentLine=verticalSweepEdges[i];const previousLine=verticalSweepEdges[i-1];const deltaX=currentLine.value-previousLine.value;if(deltaX===0)continue;let count=0;let firstRect;for(let j=0;j<horizontalSweepEdges.length;j++){if(active[horizontalSweepEdges[j].id]===true){if(horizontalSweepEdges[j].type==='top'){if(count===0){firstRect=j;}
+count++;}else{if(count===1){const deltaY=horizontalSweepEdges[j].value-
+horizontalSweepEdges[firstRect].value;area+=deltaX*deltaY;}
+count--;}}}
+active[currentLine.id]=(currentLine.type==='left');}
+return area;}
+static quadToRect(quad){const left=Math.min(quad[0],quad[2],quad[4]);const right=Math.max(quad[0],quad[2],quad[4]);const top=Math.min(quad[1],quad[3],quad[5]);const bottom=Math.max(quad[1],quad[3],quad[5]);return{left,right,top,bottom};}
+static calculateRectsBasedSpeedIndex(timestampedPaintRects,viewport){const numberOfRects=timestampedPaintRects.length;if(numberOfRects===0){throw new Error('Can\'t calculate speed index without any paint '+'rectangles.');}
+const areaAddedAtTimestamp=new Array(numberOfRects);const rects=[];let previousAreaOfUnion=0;let totalAreaOfUnion=0;for(let i=numberOfRects-1;i>=0;i--){rects.push(timestampedPaintRects[i].rect);const currentAreaOfUnion=SpeedIndex.lineSweep(rects,viewport);areaAddedAtTimestamp[i]={value:currentAreaOfUnion-previousAreaOfUnion,ts:timestampedPaintRects[i].ts};totalAreaOfUnion+=areaAddedAtTimestamp[i].value;previousAreaOfUnion=currentAreaOfUnion;}
+const paintProgressAtTimestamp=new Array(numberOfRects);let lastProgressRecorded=0;for(let i=0;i<numberOfRects;i++){paintProgressAtTimestamp[i]={value:areaAddedAtTimestamp[i].value/totalAreaOfUnion+
+lastProgressRecorded,ts:areaAddedAtTimestamp[i].ts};lastProgressRecorded=paintProgressAtTimestamp[i].value;}
+return SpeedIndex.speedIndexFromSnapshotsProgress_(paintProgressAtTimestamp);}}
+return{SpeedIndex,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const SpeedIndex=tr.e.chrome.SpeedIndex;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function addRectsBasedSpeedIndexSample(samples,rendererHelper,navigationStart,loadDuration,frameID){let viewport;for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'viewport','loading')){if(event.args.data.frameID===frameID&&event.start<(navigationStart+loadDuration)){viewport=event.args.data;}}
+if(!viewport)return;const timestampedPaintRects=[];for(const event of EventFinderUtils.getMainThreadEvents(rendererHelper,'PaintTimingVisualizer::LayoutObjectPainted','loading')){if(event.start>=navigationStart&&event.start<navigationStart+loadDuration){const paintRect=event.args.data.rect;if(!paintRect)continue;timestampedPaintRects.push({rect:SpeedIndex.quadToRect(paintRect),ts:event.start});}}
+const numberOfRects=timestampedPaintRects.length;if(numberOfRects===0)return;samples.push({value:SpeedIndex.calculateRectsBasedSpeedIndex(timestampedPaintRects,viewport)-navigationStart});}
+function collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper){const rectsBasedSpeedIndexSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addRectsBasedSpeedIndexSample(rectsBasedSpeedIndexSamples,rendererHelper,expectation.navigationStart.start,expectation.duration,expectation.navigationStart.args.frame);}
+return rectsBasedSpeedIndexSamples;}
+function rectsBasedSpeedIndexMetric(histograms,model){const rectsBasedSpeedIndexHistogram=histograms.createHistogram('rectsBasedSpeedIndex',timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,description:' the average time at which visible parts of the'+' page are displayed (in ms).',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectRectsBasedSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){rectsBasedSpeedIndexHistogram.addSample(sample.value);}}
+tr.metrics.MetricRegistry.register(rectsBasedSpeedIndexMetric);return{rectsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_THRESHOLD_MS=50;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_smallerIsBetter=tr.b.Unit.byName.unitlessNumber_smallerIsBetter;const RelatedEventSet=tr.v.d.RelatedEventSet;const hasCategoryAndName=tr.metrics.sh.hasCategoryAndName;const EventFinderUtils=tr.e.chrome.EventFinderUtils;function createBreakdownDiagnostic(breakdownTree){const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownTree){breakdownDiagnostic.set(label,breakdownTree[label].total);}
+return breakdownDiagnostic;}
+const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const TIME_TO_INTERACTIVE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,40e3,35).addExponentialBins(80e3,15);const LAYOUT_SHIFT_SCORE_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,50,25);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,ts){const objects=rendererHelper.process.objects;const frameLoaderInstances=objects.instancesByTypeName_.FrameLoader;if(frameLoaderInstances===undefined)return undefined;let snapshot;for(const instance of frameLoaderInstances){if(!instance.isAliveAt(ts))continue;const maybeSnapshot=instance.getSnapshotAt(ts);if(frameIdRef!==maybeSnapshot.args.frame.id_ref)continue;snapshot=maybeSnapshot;}
+return snapshot;}
+function findAllEvents(rendererHelper,category,title){const targetEvents=[];for(const ev of rendererHelper.process.getDescendantEvents()){if(!hasCategoryAndName(ev,category,title))continue;targetEvents.push(ev);}
+return targetEvents;}
+function getMostRecentValidEvent(rendererHelper,category,title){const targetEvents=findAllEvents(rendererHelper,category,title);let validEvent;for(const targetEvent of targetEvents){if(rendererHelper.isTelemetryInternalEvent(targetEvent))continue;if(validEvent===undefined){validEvent=targetEvent;}else{if(validEvent.start<targetEvent.start){validEvent=targetEvent;}}}
+return validEvent;}
+function getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents){const samples=[];const pcEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','pc');if(pcEvent===undefined)return samples;if(rendererHelper.isTelemetryInternalEvent(pcEvent))return samples;const navigationStartEvent=navIdToNavStartEvents.get(pcEvent.args.data.navigationId);if(navigationStartEvent===undefined)return samples;const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,pcEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventRange);if(rendererHelper.mainThread===undefined)return samples;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventRange);samples.push({value:navStartToEventRange.duration,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),Start:new RelatedEventSet(navigationStartEvent),End:new RelatedEventSet(pcEvent)}});return samples;}
+function getAboveTheFoldLoadedToVisibleSamples(rendererHelper){const samples=[];const pcEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','pc');const visibleEvent=getMostRecentValidEvent(rendererHelper,'blink.user_timing','visible');if(pcEvent!==undefined&&visibleEvent!==undefined){samples.push({value:Math.max(0.0,pcEvent.start-visibleEvent.start),diagnostics:{Start:new RelatedEventSet(visibleEvent),End:new RelatedEventSet(pcEvent)}});}
+return samples;}
+function findTimeToXEntries(category,eventName,rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const targetEvents=findAllEvents(rendererHelper,category,eventName);const entries=[];for(const targetEvent of targetEvents){if(rendererHelper.isTelemetryInternalEvent(targetEvent))continue;const frameIdRef=targetEvent.args.frame;const snapshot=findFrameLoaderSnapshotAt(rendererHelper,frameIdRef,targetEvent.start);if(snapshot===undefined||!snapshot.args.isLoadingMainFrame)continue;const url=snapshot.args.documentLoaderURL;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(url))continue;let navigationStartEvent;if(targetEvent.args.data===undefined||targetEvent.args.data.navigationId===undefined){navigationStartEvent=EventFinderUtils.findLastEventStartingOnOrBeforeTimestamp(frameToNavStartEvents.get(frameIdRef)||[],targetEvent.start);}else{navigationStartEvent=navIdToNavStartEvents.get(targetEvent.args.data.navigationId);}
+if(navigationStartEvent===undefined)continue;entries.push({navigationStartEvent,targetEvent,url,});}
+return entries;}
+function collectTimeToEvent(rendererHelper,timeToXEntries){const samples=[];for(const{targetEvent,navigationStartEvent,url}of timeToXEntries){const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,targetEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventRange);samples.push({value:navStartToEventRange.duration,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),url:new tr.v.d.GenericSet([url]),Start:new RelatedEventSet(navigationStartEvent),End:new RelatedEventSet(targetEvent)}});}
+return samples;}
+function collectTimeToEventInCpuTime(rendererHelper,timeToXEntries){const samples=[];for(const{targetEvent,navigationStartEvent,url}of timeToXEntries){const navStartToEventRange=tr.b.math.Range.fromExplicitRange(navigationStartEvent.start,targetEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToEventRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToEventRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStartEvent),end:new RelatedEventSet(targetEvent),infos:new tr.v.d.GenericSet([{pid:rendererHelper.pid,start:navigationStartEvent.start,event:targetEvent.start,}]),}});}
+return samples;}
+function findLayoutShiftSamples(rendererHelper){let sample;EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'LayoutShift','loading').forEach((events)=>{const evData=events.pop().args.data;if(evData.is_main_frame){sample={value:evData.cumulative_score};}});return sample?[sample]:[];}
+function addFirstMeaningfulPaintSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToFMPRange);const timeToFirstMeaningfulPaint=navStartToFMPRange.duration;const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToFMPRange);samples.push({value:timeToFirstMeaningfulPaint,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
+function addFirstMeaningfulPaintCpuTimeSample(samples,rendererHelper,navigationStart,fmpMarkerEvent,url){const navStartToFMPRange=tr.b.math.Range.fromExplicitRange(navigationStart.start,fmpMarkerEvent.start);const mainThreadCpuTime=rendererHelper.mainThread.getCpuTimeForRange(navStartToFMPRange);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,navStartToFMPRange);samples.push({value:mainThreadCpuTime,breakdownTree,diagnostics:{breakdown:createBreakdownDiagnostic(breakdownTree),start:new RelatedEventSet(navigationStart),end:new RelatedEventSet(fmpMarkerEvent),infos:new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,start:navigationStart.start,fmp:fmpMarkerEvent.start,}]),}});}
+function decorateInteractivitySampleWithDiagnostics_(rendererHelper,eventTimestamp,navigationStartEvent,firstMeaningfulPaintTime,domContentLoadedEndTime,url){if(eventTimestamp===undefined)return undefined;const navigationStartTime=navigationStartEvent.start;const navStartToEventTimeRange=tr.b.math.Range.fromExplicitRange(navigationStartTime,eventTimestamp);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,navStartToEventTimeRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,navStartToEventTimeRange);const breakdownDiagnostic=createBreakdownDiagnostic(breakdownTree);return{value:navStartToEventTimeRange.duration,diagnostics:tr.v.d.DiagnosticMap.fromObject({'Start':new RelatedEventSet(navigationStartEvent),'Navigation infos':new tr.v.d.GenericSet([{url,pid:rendererHelper.pid,navigationStartTime,firstMeaningfulPaintTime,domContentLoadedEndTime,eventTimestamp,}]),'Breakdown of [navStart, eventTimestamp]':breakdownDiagnostic,}),};}
+function getCandidateIndex(entry){return entry.targetEvent.args.data.candidateIndex;}
+function findLastCandidateForEachNavigation(timeToXEntries){const entryMap=new Map();for(const e of timeToXEntries){const navStartEvent=e.navigationStartEvent;if(!entryMap.has(navStartEvent)){entryMap.set(navStartEvent,[]);}
+entryMap.get(navStartEvent).push(e);}
+const lastCandidates=[];for(const timeToXEntriesByNavigation of entryMap.values()){let lastCandidate=timeToXEntriesByNavigation.shift();for(const entry of timeToXEntriesByNavigation){if(getCandidateIndex(entry)>getCandidateIndex(lastCandidate)){lastCandidate=entry;}}
+lastCandidates.push(lastCandidate);}
+return lastCandidates;}
+function findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestTextPaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestTextPaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestTextPaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
+function findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents){const timeToPaintEntries=findTimeToXEntries('loading','LargestImagePaint::Candidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const timeToPaintBlockingEntries=findTimeToXEntries('loading','LargestImagePaint::NoCandidate',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const lastCandidateEvents=findLastCandidateForEachNavigation(timeToPaintEntries.concat(timeToPaintBlockingEntries)).filter(event=>event.targetEvent.title!=='LargestImagePaint::NoCandidate');return collectTimeToEvent(rendererHelper,lastCandidateEvents);}
+function findLargestContentfulPaintHistogramSamples(allBrowserEvents){const lcp=new tr.e.chrome.LargestContentfulPaint(allBrowserEvents);const lcpSamples=lcp.findCandidates().map(candidate=>{const{durationInMilliseconds,size,type,inMainFrame,mainFrameTreeNodeId}=candidate;return{value:durationInMilliseconds,diagnostics:{size:new tr.v.d.GenericSet([size]),type:new tr.v.d.GenericSet([type]),inMainFrame:new tr.v.d.GenericSet([inMainFrame]),mainFrameTreeNodeId:new tr.v.d.GenericSet([mainFrameTreeNodeId]),},};});return lcpSamples;}
+function collectLoadingMetricsForRenderer(rendererHelper){const frameToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByFrame(rendererHelper,'navigationStart','blink.user_timing');const navIdToNavStartEvents=EventFinderUtils.getSortedMainThreadEventsByNavId(rendererHelper,'navigationStart','blink.user_timing');const firstPaintSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('loading','firstPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const timeToFCPEntries=findTimeToXEntries('loading','firstContentfulPaint',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const firstContentfulPaintSamples=collectTimeToEvent(rendererHelper,timeToFCPEntries);const firstContentfulPaintCpuTimeSamples=collectTimeToEventInCpuTime(rendererHelper,timeToFCPEntries);const onLoadSamples=collectTimeToEvent(rendererHelper,findTimeToXEntries('blink.user_timing','loadEventStart',rendererHelper,frameToNavStartEvents,navIdToNavStartEvents));const aboveTheFoldLoadedToVisibleSamples=getAboveTheFoldLoadedToVisibleSamples(rendererHelper);const firstViewportReadySamples=getFirstViewportReadySamples(rendererHelper,navIdToNavStartEvents);const largestImagePaintSamples=findLargestImagePaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const largestTextPaintSamples=findLargestTextPaintSamples(rendererHelper,frameToNavStartEvents,navIdToNavStartEvents);const layoutShiftSamples=findLayoutShiftSamples(rendererHelper);const navigationStartSamples=timeToFCPEntries.map(entry=>{return{value:entry.navigationStartEvent.start};});return{frameToNavStartEvents,firstPaintSamples,firstContentfulPaintSamples,firstContentfulPaintCpuTimeSamples,onLoadSamples,aboveTheFoldLoadedToVisibleSamples,firstViewportReadySamples,largestImagePaintSamples,largestTextPaintSamples,layoutShiftSamples,navigationStartSamples,};}
+function collectMetricsFromLoadExpectations(model,chromeHelper){const interactiveSamples=[];const firstCpuIdleSamples=[];const firstMeaningfulPaintSamples=[];const firstMeaningfulPaintCpuTimeSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];if(expectation.fmpEvent!==undefined){addFirstMeaningfulPaintSample(firstMeaningfulPaintSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);addFirstMeaningfulPaintCpuTimeSample(firstMeaningfulPaintCpuTimeSamples,rendererHelper,expectation.navigationStart,expectation.fmpEvent,expectation.url);}
+if(expectation.firstCpuIdleTime!==undefined){firstCpuIdleSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.firstCpuIdleTime,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}
+if(expectation.timeToInteractive!==undefined){interactiveSamples.push(decorateInteractivitySampleWithDiagnostics_(rendererHelper,expectation.timeToInteractive,expectation.navigationStart,expectation.fmpEvent.start,expectation.domContentLoadedEndEvent.start,expectation.url));}}
+return{firstMeaningfulPaintSamples,firstMeaningfulPaintCpuTimeSamples,firstCpuIdleSamples,interactiveSamples,};}
+function addSamplesToHistogram(samples,histogram,histograms){for(const sample of samples){histogram.addSample(sample.value,sample.diagnostics);if(histogram.name!=='timeToFirstContentfulPaint')continue;if(!sample.breakdownTree)continue;for(const[category,breakdown]of Object.entries(sample.breakdownTree)){const relatedName=`${histogram.name}:${category}`;let relatedHist=histograms.getHistogramsNamed(relatedName)[0];if(!relatedHist){relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
+relatedNames.set(category,relatedName);}
+relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}}
+function loadingMetric(histograms,model){const firstPaintHistogram=histograms.createHistogram('timeToFirstPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintHistogram=histograms.createHistogram('timeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const firstContentfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first contentful paint',summaryOptions:SUMMARY_OPTIONS,});const onLoadHistogram=histograms.createHistogram('timeToOnload',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to onload. '+'This is temporary metric used for PCv1/v2 sanity checking',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintHistogram=histograms.createHistogram('timeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const firstMeaningfulPaintCpuTimeHistogram=histograms.createHistogram('cpuTimeToFirstMeaningfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'CPU time to first meaningful paint',summaryOptions:SUMMARY_OPTIONS,});const timeToInteractiveHistogram=histograms.createHistogram('timeToInteractive',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to Interactive',summaryOptions:SUMMARY_OPTIONS,});const timeToFirstCpuIdleHistogram=histograms.createHistogram('timeToFirstCpuIdle',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time to First CPU Idle',summaryOptions:SUMMARY_OPTIONS,});const aboveTheFoldLoadedToVisibleHistogram=histograms.createHistogram('aboveTheFoldLoadedToVisible',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from first visible to load for AMP pages only.',summaryOptions:SUMMARY_OPTIONS,});const firstViewportReadyHistogram=histograms.createHistogram('timeToFirstViewportReady',timeDurationInMs_smallerIsBetter,[],{binBoundaries:TIME_TO_INTERACTIVE_BOUNDARIES,description:'Time from navigation to load for AMP pages only. ',summaryOptions:SUMMARY_OPTIONS,});const largestImagePaintHistogram=histograms.createHistogram('largestImagePaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Image Paint',summaryOptions:SUMMARY_OPTIONS,});const largestTextPaintHistogram=histograms.createHistogram('largestTextPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Text Paint',summaryOptions:SUMMARY_OPTIONS,});const largestContentfulPaintHistogram=histograms.createHistogram('largestContentfulPaint',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'Time to Largest Contentful Paint',summaryOptions:SUMMARY_OPTIONS,});const layoutShiftHistogram=histograms.createHistogram('mainFrameCumulativeLayoutShift',unitlessNumber_smallerIsBetter,[],{binBoundaries:LAYOUT_SHIFT_SCORE_BOUNDARIES,description:'Main Frame Document Cumulative Layout Shift Score',summaryOptions:SUMMARY_OPTIONS,});const navigationStartHistogram=histograms.createHistogram('navigationStart',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'navigationStart',summaryOptions:SUMMARY_OPTIONS,});tr.metrics.sh.rectsBasedSpeedIndexMetric(histograms,model);const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const pid in chromeHelper.rendererHelpers){const rendererHelper=chromeHelper.rendererHelpers[pid];if(rendererHelper.isChromeTracingUI)continue;const samplesSet=collectLoadingMetricsForRenderer(rendererHelper);const lcpSamples=findLargestContentfulPaintHistogramSamples(chromeHelper.browserHelper.mainThread.sliceGroup.slices);addSamplesToHistogram(lcpSamples,largestContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstPaintSamples,firstPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintSamples,firstContentfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstContentfulPaintCpuTimeSamples,firstContentfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.onLoadSamples,onLoadHistogram,histograms);addSamplesToHistogram(samplesSet.aboveTheFoldLoadedToVisibleSamples,aboveTheFoldLoadedToVisibleHistogram,histograms);addSamplesToHistogram(samplesSet.firstViewportReadySamples,firstViewportReadyHistogram,histograms);addSamplesToHistogram(samplesSet.largestImagePaintSamples,largestImagePaintHistogram,histograms);addSamplesToHistogram(samplesSet.largestTextPaintSamples,largestTextPaintHistogram,histograms);addSamplesToHistogram(samplesSet.layoutShiftSamples,layoutShiftHistogram,histograms);addSamplesToHistogram(samplesSet.navigationStartSamples,navigationStartHistogram,histograms);}
+const samplesSet=collectMetricsFromLoadExpectations(model,chromeHelper);addSamplesToHistogram(samplesSet.firstMeaningfulPaintSamples,firstMeaningfulPaintHistogram,histograms);addSamplesToHistogram(samplesSet.firstMeaningfulPaintCpuTimeSamples,firstMeaningfulPaintCpuTimeHistogram,histograms);addSamplesToHistogram(samplesSet.interactiveSamples,timeToInteractiveHistogram,histograms);addSamplesToHistogram(samplesSet.firstCpuIdleSamples,timeToFirstCpuIdleHistogram,histograms);}
+tr.metrics.MetricRegistry.register(loadingMetric);return{loadingMetric,createBreakdownDiagnostic};});'use strict';tr.exportTo('tr.metrics',function(){const SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY=tr.v.HistogramBinBoundaries.createExponential(1,1000,50);function spaNavigationMetric(histograms,model){const histogram=new tr.v.Histogram('spaNavigationStartToFpDuration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,SPA_NAVIGATION_START_TO_FIRST_PAINT_DURATION_BIN_BOUNDARY);histogram.description='Latency between the input event causing'+' a SPA navigation and the first paint event after it';histogram.customizeSummaryOptions({count:false,sum:false,});const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!modelHelper){return;}
+const rendererHelpers=modelHelper.rendererHelpers;if(!rendererHelpers){return;}
+const browserHelper=modelHelper.browserHelper;for(const rendererHelper of Object.values(rendererHelpers)){const spaNavigations=tr.metrics.findSpaNavigationsOnRenderer(rendererHelper,browserHelper);for(const spaNav of spaNavigations){let beginTs=0;if(spaNav.navStartCandidates.inputLatencyAsyncSlice){const beginData=spaNav.navStartCandidates.inputLatencyAsyncSlice.args.data;beginTs=model.convertTimestampToModelTime('traceEventClock',beginData.INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT.time);}else{beginTs=spaNav.navStartCandidates.goToIndexSlice.start;}
+const rangeOfInterest=tr.b.math.Range.fromExplicitRange(beginTs,spaNav.firstPaintEvent.start);const networkEvents=tr.e.chrome.EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,rangeOfInterest);const breakdownDict=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,rangeOfInterest);const breakdownDiagnostic=new tr.v.d.Breakdown();breakdownDiagnostic.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const label in breakdownDict){breakdownDiagnostic.set(label,parseInt(breakdownDict[label].total*1e3)/1e3);}
+histogram.addSample(rangeOfInterest.duration,{'Breakdown of [navStart, firstPaint]':breakdownDiagnostic,'Start':new tr.v.d.RelatedEventSet(spaNav.navigationStart),'End':new tr.v.d.RelatedEventSet(spaNav.firstPaintEvent),'Navigation infos':new tr.v.d.GenericSet([{url:spaNav.url,pid:rendererHelper.pid,navStart:beginTs,firstPaint:spaNav.firstPaintEvent.start}]),});}}
+histograms.addHistogram(histogram);}
+tr.metrics.MetricRegistry.register(spaNavigationMetric);return{spaNavigationMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LATENCY_BOUNDS=tr.v.HistogramBinBoundaries.createLinear(0,20,100);function clockSyncLatencyMetric(values,model){const domains=Array.from(model.clockSyncManager.domainsSeen).sort();for(let i=0;i<domains.length;i++){for(let j=i+1;j<domains.length;j++){const latency=model.clockSyncManager.getTimeTransformerError(domains[i],domains[j]);const hist=new tr.v.Histogram('clock_sync_latency_'+
+domains[i].toLowerCase()+'_to_'+domains[j].toLowerCase(),tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,LATENCY_BOUNDS);hist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false,});hist.description='Clock sync latency for domain '+domains[i]+' to domain '+domains[j];hist.addSample(latency);values.addHistogram(hist);}}}
+tr.metrics.MetricRegistry.register(clockSyncLatencyMetric);return{clockSyncLatencyMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const CPU_TIME_PERCENTAGE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.01,50,200);function cpuTimeMetric(histograms,model,opt_options){let rangeOfInterest=model.bounds;if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;}else{const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper){const chromeBounds=chromeHelper.chromeBounds;if(chromeBounds){rangeOfInterest=chromeBounds;}}}
+let allProcessCpuTime=0;for(const pid in model.processes){const process=model.processes[pid];if(tr.model.helpers.ChromeRendererHelper.isTracingProcess(process)){continue;}
+let processCpuTime=0;for(const tid in process.threads){const thread=process.threads[tid];processCpuTime+=thread.getCpuTimeForRange(rangeOfInterest);}
+allProcessCpuTime+=processCpuTime;}
+let normalizedAllProcessCpuTime=0;if(rangeOfInterest.duration>0){normalizedAllProcessCpuTime=allProcessCpuTime/rangeOfInterest.duration;}
+const unit=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const cpuTimeHist=new tr.v.Histogram('cpu_time_percentage',unit,CPU_TIME_PERCENTAGE_BOUNDARIES);cpuTimeHist.description='Percent CPU utilization, normalized against a single core. Can be '+'greater than 100% if machine has multiple cores.';cpuTimeHist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false});cpuTimeHist.addSample(normalizedAllProcessCpuTime);histograms.addHistogram(cpuTimeHist);}
+tr.metrics.MetricRegistry.register(cpuTimeMetric,{supportsRangeOfInterest:true});return{cpuTimeMetric,};});'use strict';tr.exportTo('tr.v',function(){class HistogramDeserializer{static deserialize(data){const deserializer=new HistogramDeserializer(data[0],data[1]);return data.slice(2).map(datum=>tr.v.Histogram.deserialize(datum,deserializer));}
+constructor(objects,diagnostics){this.objects_=objects;this.diagnostics_=[];for(const[type,diagnosticsByName]of Object.entries(diagnostics||{})){for(const[name,diagnosticsById]of Object.entries(diagnosticsByName)){for(const[id,data]of Object.entries(diagnosticsById)){const diagnostic=tr.v.d.Diagnostic.deserialize(type,data,this);this.diagnostics_[parseInt(id)]={name,diagnostic};}}}}
+getObject(id){return this.objects_[id];}
+getDiagnostic(id){return this.diagnostics_[parseInt(id)];}}
+return{HistogramDeserializer};});'use strict';tr.exportTo('tr.v',function(){class HistogramGrouping{constructor(key,callback){this.key_=key;this.callback_=callback;HistogramGrouping.BY_KEY.set(key,this);}
+get key(){return this.key_;}
+get callback(){return this.callback_;}
+get label(){return this.key;}
+static buildFromTags(tags,diagnosticName){const booleanTags=new Set();const keyValueTags=new Set();for(const tag of tags){if(tag.includes(':')){const key=tag.split(':')[0];if(booleanTags.has(key)){throw new Error(`Tag "${key}" cannot be both boolean and key-value`);}
+keyValueTags.add(key);}else{if(keyValueTags.has(tag)){throw new Error(`Tag "${tag}" cannot be both boolean and key-value`);}
+booleanTags.add(tag);}}
+const groupings=[];for(const tag of booleanTags){groupings.push(HistogramGrouping.buildBooleanTagGrouping_(tag,diagnosticName));}
+for(const tag of keyValueTags){groupings.push(HistogramGrouping.buildKeyValueTagGrouping_(tag,diagnosticName));}
+return groupings;}
+static buildBooleanTagGrouping_(tag,diagnosticName){return new HistogramGrouping(`${tag}Tag`,h=>{const tags=h.diagnostics.get(diagnosticName);if(tags===undefined||!tags.has(tag))return`~${tag}`;return tag;});}
+static buildKeyValueTagGrouping_(tag,diagnosticName){return new HistogramGrouping(`${tag}Tag`,h=>{const tags=h.diagnostics.get(diagnosticName);if(tags===undefined)return`~${tag}`;const values=new Set();for(const value of tags){const kvp=value.split(':');if(kvp.length<2||kvp[0]!==tag)continue;values.add(kvp[1]);}
+if(values.size===0)return`~${tag}`;const sortedValues=Array.from(values);sortedValues.sort();return sortedValues.join(',');},`${tag} tag`);}}
+HistogramGrouping.BY_KEY=new Map();HistogramGrouping.HISTOGRAM_NAME=new HistogramGrouping('name',h=>h.name);HistogramGrouping.DISPLAY_LABEL=new HistogramGrouping('displayLabel',hist=>{const labels=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.LABELS);if(labels!==undefined&&labels.size>0){return Array.from(labels).join(',');}
+const benchmarks=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);const start=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);if(benchmarks===undefined){if(start===undefined)return'Value';return start.toString();}
+const benchmarksStr=Array.from(benchmarks).join('\n');if(start===undefined)return benchmarksStr;return benchmarksStr+'\n'+start.toString();});class GenericSetGrouping extends HistogramGrouping{constructor(name){super(name,undefined);this.callback_=this.compute_.bind(this);}
+compute_(hist){const diag=hist.diagnostics.get(this.key);if(diag===undefined)return'';const parts=Array.from(diag);parts.sort();return parts.join(',');}}
+GenericSetGrouping.NAMES=[tr.v.d.RESERVED_NAMES.ARCHITECTURES,tr.v.d.RESERVED_NAMES.BENCHMARKS,tr.v.d.RESERVED_NAMES.BOTS,tr.v.d.RESERVED_NAMES.BUILDS,tr.v.d.RESERVED_NAMES.DEVICE_IDS,tr.v.d.RESERVED_NAMES.MASTERS,tr.v.d.RESERVED_NAMES.MEMORY_AMOUNTS,tr.v.d.RESERVED_NAMES.OS_NAMES,tr.v.d.RESERVED_NAMES.OS_VERSIONS,tr.v.d.RESERVED_NAMES.PRODUCT_VERSIONS,tr.v.d.RESERVED_NAMES.STORIES,tr.v.d.RESERVED_NAMES.STORYSET_REPEATS,tr.v.d.RESERVED_NAMES.STORY_TAGS,tr.v.d.RESERVED_NAMES.TEST_PATH,];for(const name of GenericSetGrouping.NAMES){new GenericSetGrouping(name);}
+class DateRangeGrouping extends HistogramGrouping{constructor(name){super(name,undefined);this.callback_=this.compute_.bind(this);}
+compute_(hist){const diag=hist.diagnostics.get(this.key);if(diag===undefined)return'';return diag.toString();}}
+DateRangeGrouping.NAMES=[tr.v.d.RESERVED_NAMES.BENCHMARK_START,tr.v.d.RESERVED_NAMES.TRACE_START,];for(const name of DateRangeGrouping.NAMES){new DateRangeGrouping(name);}
+return{HistogramGrouping,GenericSetGrouping,DateRangeGrouping,};});'use strict';tr.exportTo('tr.v',function(){class HistogramSet{constructor(opt_histograms){this.histograms_=new Set();this.sharedDiagnosticsByGuid_=new Map();if(opt_histograms!==undefined){for(const hist of opt_histograms){this.addHistogram(hist);}}}
+has(hist){return this.histograms_.has(hist);}
+createHistogram(name,unit,samples,opt_options){const hist=tr.v.Histogram.create(name,unit,samples,opt_options);this.addHistogram(hist);return hist;}
+addHistogram(hist,opt_diagnostics){if(this.has(hist)){throw new Error('Cannot add same Histogram twice');}
+if(opt_diagnostics!==undefined){if(!(opt_diagnostics instanceof Map)){opt_diagnostics=Object.entries(opt_diagnostics);}
+for(const[name,diagnostic]of opt_diagnostics){hist.diagnostics.set(name,diagnostic);}}
+this.histograms_.add(hist);}
+addSharedDiagnosticToAllHistograms(name,diagnostic){this.addSharedDiagnostic(diagnostic);for(const hist of this){hist.diagnostics.set(name,diagnostic);}}
+addSharedDiagnostic(diagnostic){this.sharedDiagnosticsByGuid_.set(diagnostic.guid,diagnostic);}
+get length(){return this.histograms_.size;}*[Symbol.iterator](){for(const hist of this.histograms_){yield hist;}}
+getHistogramsNamed(name){return[...this].filter(h=>h.name===name);}
+getHistogramNamed(name){const histograms=this.getHistogramsNamed(name);if(histograms.length===0)return undefined;if(histograms.length>1){throw new Error(`Unexpectedly found multiple histograms named "${name}"`);}
+return histograms[0];}
+lookupDiagnostic(guid){return this.sharedDiagnosticsByGuid_.get(guid);}
+deserialize(data){for(const hist of tr.v.HistogramDeserializer.deserialize(data)){this.addHistogram(hist);}}
+importDicts(dicts){if((dicts instanceof Array)&&(dicts.length>2)&&(dicts[0]instanceof Array)){this.deserialize(dicts);return;}
+for(const dict of dicts){this.importLegacyDict(dict);}}
+importLegacyDict(dict){if(dict.type!==undefined){if(dict.type==='TagMap')return;if(!tr.v.d.Diagnostic.findTypeInfoWithName(dict.type)){throw new Error('Unrecognized shared diagnostic type '+dict.type);}
+this.sharedDiagnosticsByGuid_.set(dict.guid,tr.v.d.Diagnostic.fromDict(dict));}else{const hist=tr.v.Histogram.fromDict(dict);this.addHistogram(hist);hist.diagnostics.resolveSharedDiagnostics(this,true);}}
+asDicts(){const dicts=[];for(const diagnostic of this.sharedDiagnosticsByGuid_.values()){dicts.push(diagnostic.asDict());}
+for(const hist of this){dicts.push(hist.asDict());}
+return dicts;}
+get sourceHistograms(){const diagnosticNames=new Set();for(const hist of this){for(const diagnostic of hist.diagnostics.values()){if(!(diagnostic instanceof tr.v.d.RelatedNameMap))continue;for(const name of diagnostic.values()){diagnosticNames.add(name);}}}
+const sourceHistograms=new HistogramSet;for(const hist of this){if(!diagnosticNames.has(hist.name)){sourceHistograms.addHistogram(hist);}}
+return sourceHistograms;}
+groupHistogramsRecursively(groupings,opt_skipGroupingCallback){function recurse(histograms,level){if(level===groupings.length){return histograms;}
+const grouping=groupings[level];const groupedHistograms=tr.b.groupIntoMap(histograms,grouping.callback);if(opt_skipGroupingCallback&&opt_skipGroupingCallback(grouping,groupedHistograms)){return recurse(histograms,level+1);}
+for(const[key,group]of groupedHistograms){groupedHistograms.set(key,recurse(group,level+1));}
+return groupedHistograms;}
+return recurse([...this],0);}
+deduplicateDiagnostics(){const namesToCandidates=new Map();const diagnosticsToHistograms=new Map();const keysToDiagnostics=new Map();for(const hist of this){for(const[name,candidate]of hist.diagnostics){if(candidate.equals===undefined){this.sharedDiagnosticsByGuid_.set(candidate.guid,candidate);continue;}
+const hashKey=candidate.hashKey;if(candidate.hashKey!==undefined){if(keysToDiagnostics.has(hashKey)){hist.diagnostics.set(name,keysToDiagnostics.get(hashKey));}else{keysToDiagnostics.set(hashKey,candidate);this.sharedDiagnosticsByGuid_.set(candidate.guid,candidate);}
+continue;}
+if(diagnosticsToHistograms.get(candidate)===undefined){diagnosticsToHistograms.set(candidate,[hist]);}else{diagnosticsToHistograms.get(candidate).push(hist);}
+if(!namesToCandidates.has(name)){namesToCandidates.set(name,new Set());}
+namesToCandidates.get(name).add(candidate);}}
+for(const[name,candidates]of namesToCandidates){const deduplicatedDiagnostics=new Set();for(const candidate of candidates){let found=false;for(const test of deduplicatedDiagnostics){if(candidate.equals(test)){const hists=diagnosticsToHistograms.get(candidate);for(const hist of hists){hist.diagnostics.set(name,test);}
+found=true;break;}}
+if(!found){deduplicatedDiagnostics.add(candidate);}
+for(const diagnostic of deduplicatedDiagnostics){this.sharedDiagnosticsByGuid_.set(diagnostic.guid,diagnostic);}}}}
+buildGroupingsFromTags(names){const tags=new Map();for(const hist of this){for(const name of names){if(!hist.diagnostics.has(name))continue;if(!tags.has(name))tags.set(name,new Set());for(const tag of hist.diagnostics.get(name)){tags.get(name).add(tag);}}}
+const groupings=[];for(const[name,values]of tags){const built=tr.v.HistogramGrouping.buildFromTags(values,name);for(const grouping of built){groupings.push(grouping);}}
+return groupings;}}
+return{HistogramSet};});'use strict';tr.exportTo('tr.e.chrome',function(){function hasTitleAndCategory(event,title,category){return event.title===title&&event.category&&tr.b.getCategoryParts(event.category).includes(category);}
+function getNavStartTimestamps(rendererHelper){const navStartTimestamps=[];for(const e of rendererHelper.mainThread.sliceGroup.childEvents()){if(hasTitleAndCategory(e,'navigationStart','blink.user_timing')){navStartTimestamps.push(e.start);}}
+return navStartTimestamps;}
+function getInteractiveTimestamps(model){const interactiveTimestampsMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const rendererHelper of Object.values(chromeHelper.rendererHelpers)){const timestamps=[];interactiveTimestampsMap.set(rendererHelper.pid,timestamps);}
+for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+if(expectation.timeToInteractive===undefined)continue;if(interactiveTimestampsMap.get(expectation.renderProcess.pid)===undefined){interactiveTimestampsMap.set(expectation.renderProcess.pid,[]);}
+interactiveTimestampsMap.get(expectation.renderProcess.pid).push(expectation.timeToInteractive);}
+return interactiveTimestampsMap;}
+function getPostInteractiveTaskWindows(interactiveTimestamps,navStartTimestamps,traceEndTimestamp){let navStartTsIndex=0;let lastTaskWindowEndTs=undefined;const taskWindows=[];for(const currTTI of interactiveTimestamps){while(navStartTsIndex<navStartTimestamps.length&&navStartTimestamps[navStartTsIndex]<currTTI){navStartTsIndex++;}
+const taskWindowEndTs=navStartTsIndex<navStartTimestamps.length?navStartTimestamps[navStartTsIndex]:traceEndTimestamp;if(taskWindowEndTs===lastTaskWindowEndTs){throw Error('Encountered two consecutive interactive timestamps '+'with no navigationStart between them. '+'PostInteractiveTaskWindow is not well defined in this case.');}
+taskWindows.push(tr.b.math.Range.fromExplicitRange(currTTI,taskWindowEndTs));lastTaskWindowEndTs=taskWindowEndTs;}
+return taskWindows;}
+function contributionToEQT(window,task){const startInWindow=Math.max(window.min,task.start);const endInWindow=Math.min(window.max,task.end);const durationInWindow=endInWindow-startInWindow;if(durationInWindow<=0)return 0;const probabilityOfTask=durationInWindow/(window.max-window.min);const minQueueingTime=task.end-endInWindow;const maxQueueingTime=task.end-startInWindow;const expectedQueueingTimeDueToTask=(maxQueueingTime+minQueueingTime)/2;return probabilityOfTask*expectedQueueingTimeDueToTask;}
+function weightedExpectedQueueingTime(window,weightedTasks){let result=0;for(const task of weightedTasks){result+=contributionToEQT(window,task)*task.weight;}
+return result;}
+function expectedQueueingTime(window,tasks){return weightedExpectedQueueingTime(window,tasks.map(function(task){return{start:task.start,end:task.end,weight:1};}));}
+class SlidingWindow{constructor(startTime,windowSize,sortedTasks){this.windowSize_=windowSize;this.sortedTasks_=sortedTasks;this.range_=tr.b.math.Range.fromExplicitRange(startTime,startTime+windowSize);this.firstTaskIndex_=sortedTasks.findIndex(task=>startTime<task.end);if(this.firstTaskIndex_===-1){this.firstTaskIndex_=sortedTasks.length;}
+this.lastTaskIndex_=-1;while(this.lastTaskIndex_+1<sortedTasks.length&&sortedTasks[this.lastTaskIndex_+1].start<startTime+windowSize){this.lastTaskIndex_++;}
+this.innerEQT_=0;for(let i=this.firstTaskIndex_+1;i<this.lastTaskIndex_;i++){this.innerEQT_+=contributionToEQT(this.range_,sortedTasks[i]);}}
+get getEQT(){let firstTaskEQT=0;if(this.firstTaskIndex_<this.sortedTasks_.length){firstTaskEQT=contributionToEQT(this.range_,this.sortedTasks_[this.firstTaskIndex_]);}
+let lastTaskEQT=0;if(this.firstTaskIndex_<this.lastTaskIndex_){lastTaskEQT=contributionToEQT(this.range_,this.sortedTasks_[this.lastTaskIndex_]);}
+return firstTaskEQT+this.innerEQT_+lastTaskEQT;}
+slide(t){this.range_=tr.b.math.Range.fromExplicitRange(t,t+this.windowSize_);if(this.firstTaskIndex_<this.sortedTasks_.length&&this.sortedTasks_[this.firstTaskIndex_].end<=t){this.firstTaskIndex_++;if(this.firstTaskIndex_<this.lastTaskIndex_){this.innerEQT_-=contributionToEQT(this.range_,this.sortedTasks_[this.firstTaskIndex_]);}}
+if(this.lastTaskIndex_+1<this.sortedTasks_.length&&this.sortedTasks_[this.lastTaskIndex_+1].start<t+this.windowSize_){if(this.firstTaskIndex_<this.lastTaskIndex_){this.innerEQT_+=contributionToEQT(this.range_,this.sortedTasks_[this.lastTaskIndex_]);}
+this.lastTaskIndex_++;}}}
+function maxExpectedQueueingTimeInSlidingWindow(startTime,endTime,windowSize,tasks){if(windowSize<=0){throw Error('The window size must be positive number');}
+if(startTime+windowSize>endTime){throw Error('The sliding window must fit in the specified time range');}
+const sortedTasks=tasks.slice().sort((a,b)=>a.start-b.start);for(let i=1;i<sortedTasks.length;i++){if(sortedTasks[i-1].end>sortedTasks[i].start){const midpoint=(sortedTasks[i-1].end+sortedTasks[i].start)/2;sortedTasks[i-1].end=midpoint;sortedTasks[i].start=midpoint;}}
+let endpoints=[];endpoints.push(startTime);endpoints.push(endTime-windowSize);for(const task of tasks){endpoints.push(task.start-windowSize);endpoints.push(task.start);endpoints.push(task.end-windowSize);endpoints.push(task.end);}
+endpoints=endpoints.filter(x=>(startTime<=x&&x+windowSize<=endTime));endpoints.sort((a,b)=>a-b);const slidingWindow=new SlidingWindow(endpoints[0],windowSize,sortedTasks);let maxEQT=0;for(const t of endpoints){slidingWindow.slide(t);maxEQT=Math.max(maxEQT,slidingWindow.getEQT);}
+return maxEQT;}
+return{getPostInteractiveTaskWindows,getNavStartTimestamps,getInteractiveTimestamps,expectedQueueingTime,maxExpectedQueueingTimeInSlidingWindow,weightedExpectedQueueingTime};});'use strict';tr.exportTo('tr.metrics.sh',function(){const WINDOW_SIZE_MS=500;const EQT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.01,WINDOW_SIZE_MS,50);function containsForcedGC_(slice){return slice.findTopmostSlicesRelativeToThisSlice(tr.metrics.v8.utils.isForcedGarbageCollectionEvent).length>0;}
+function getOrCreateHistogram_(histograms,name,description){return histograms.getHistogramNamed(name)||histograms.createHistogram(name,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:EQT_BOUNDARIES,description,summaryOptions:{avg:false,count:false,max:true,min:false,std:false,sum:false,},});}
+function expectedQueueingTimeMetric(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);addExpectedQueueingTimeMetric_('renderer_eqt',event=>{return{start:event.start,duration:event.duration};},false,rendererHelpers,histograms,model);}
+function addExpectedQueueingTimeMetric_(eqtName,getEventTimes,isCpuTime,rendererHelpers,histograms,model){function getTasks(rendererHelper){const tasks=[];for(const slice of
+tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread)){const times=getEventTimes(slice);if(times.duration>0&&!containsForcedGC_(slice)){tasks.push({start:times.start,end:times.start+times.duration});}}
+return tasks;}
+const totalHistogram=getOrCreateHistogram_(histograms,`total:${WINDOW_SIZE_MS}ms_window:${eqtName}`,`The maximum EQT in a ${WINDOW_SIZE_MS}ms sliding window`+' for a given renderer');for(const rendererHelper of rendererHelpers){if(rendererHelper.isChromeTracingUI)continue;if(rendererHelper.mainThread===undefined)continue;if(rendererHelper.mainThread.bounds.duration<WINDOW_SIZE_MS)continue;const tasks=getTasks(rendererHelper);const totalBreakdown=getV8Contribution_(eqtName,getEventTimes,isCpuTime,totalHistogram,histograms,rendererHelper,model);totalHistogram.addSample(tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks),{v8:totalBreakdown});}}
+function getV8Contribution_(eqtName,getEventTimes,isCpuTime,totalEqtHistogram,histograms,rendererHelper,model){if(!model.categories.includes('v8'))return null;const totalBreakdown=new tr.v.d.Breakdown();const eventNamesWithTaskExtractors=getV8EventNamesWithTaskExtractors_(getEventTimes);if(!isCpuTime){const taskExtractorsUsingRCS=getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes);for(const[eventName,getTasks]of taskExtractorsUsingRCS){eventNamesWithTaskExtractors.set(eventName,getTasks);}}
+let totalNames=totalEqtHistogram.diagnostics.get('v8');if(!totalNames){totalNames=new tr.v.d.RelatedNameMap();totalEqtHistogram.diagnostics.set('v8',totalNames);}
+for(const[eventName,getTasks]of eventNamesWithTaskExtractors){const totalHistogram=getOrCreateHistogram_(histograms,`total:${WINDOW_SIZE_MS}ms_window:${eqtName}:${eventName}`,`Contribution to the expected queueing time by ${eventName}`+' for a given renderer. It is computed as the maximum EQT in'+` a ${WINDOW_SIZE_MS}ms sliding window after shrinking top-level`+` tasks to contain only ${eventName} subevents`);const tasks=getTasks(rendererHelper);const totalSample=tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(rendererHelper.mainThread.bounds.min,rendererHelper.mainThread.bounds.max,WINDOW_SIZE_MS,tasks);totalHistogram.addSample(totalSample);totalBreakdown.set(eventName,totalSample);totalNames.set(eventName,totalHistogram.name);}
+return totalBreakdown;}
+function getV8EventNamesWithTaskExtractors_(getEventTimes,cpuMetrics){function durationOfTopmostSubSlices(slice,predicate,excludePredicate){let duration=0;for(const sub of slice.findTopmostSlicesRelativeToThisSlice(predicate)){duration+=getEventTimes(sub).duration;if(excludePredicate!==null&&excludePredicate!==undefined){duration-=durationOfTopmostSubSlices(sub,excludePredicate);}}
+return duration;}
+function taskExtractor(predicate,excludePredicate){return function(rendererHelper){const slices=tr.e.chrome.EventFinderUtils.findToplevelSchedulerTasks(rendererHelper.mainThread);const result=[];for(const slice of slices){const times=getEventTimes(slice);if(times.duration>0&&!containsForcedGC_(slice)){const duration=durationOfTopmostSubSlices(slice,predicate,excludePredicate);result.push({start:times.start,end:times.start+duration});}}
+return result;};}
+return new Map([['v8',taskExtractor(tr.metrics.v8.utils.isV8Event)],['v8:execute',taskExtractor(tr.metrics.v8.utils.isV8ExecuteEvent)],['v8:gc',taskExtractor(tr.metrics.v8.utils.isGarbageCollectionEvent)]]);}
+function extractTaskRCS(getEventTimes,predicate,rendererHelper){const result=[];for(const topSlice of
+rendererHelper.mainThread.sliceGroup.topLevelSlices){const times=getEventTimes(topSlice);if(times.duration<=0||containsForcedGC_(topSlice)){continue;}
+const v8ThreadSlices=[];for(const slice of topSlice.descendentSlices){if(tr.metrics.v8.utils.isV8RCSEvent(slice)){v8ThreadSlices.push(slice);}}
+const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8ThreadSlices);let duration=0;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){if(predicate(runtimeGroup.name)){duration+=runtimeGroup.time;}}
+duration=tr.b.convertUnit(duration,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);result.push({start:times.start,end:times.start+duration});}
+return result;}
+function getV8EventNamesWithTaskExtractorsUsingRCS_(getEventTimes){const extractors=new Map();extractors.set('v8:compile_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileRCSCategory,rendererHelper));extractors.set('v8:compile:optimize_rcs',rendererHelper=>extractTaskRCS(getEventTimes,tr.metrics.v8.utils.isCompileOptimizeRCSCategory,rendererHelper));return extractors;}
+tr.metrics.MetricRegistry.register(expectedQueueingTimeMetric);return{expectedQueueingTimeMetric,};});'use strict';tr.exportTo('tr.b',function(){function MultiDimensionalViewNode(title,valueCount){this.title=title;const dimensions=title.length;this.children=new Array(dimensions);for(let i=0;i<dimensions;i++){this.children[i]=new Map();}
+this.values=new Array(valueCount);for(let v=0;v<valueCount;v++){this.values[v]={self:0,total:0,totalState:NOT_PROVIDED};}}
+MultiDimensionalViewNode.TotalState={NOT_PROVIDED:0,LOWER_BOUND:1,EXACT:2};const NOT_PROVIDED=MultiDimensionalViewNode.TotalState.NOT_PROVIDED;const LOWER_BOUND=MultiDimensionalViewNode.TotalState.LOWER_BOUND;const EXACT=MultiDimensionalViewNode.TotalState.EXACT;MultiDimensionalViewNode.prototype={get subRows(){return Array.from(this.children[0].values());}};function MultiDimensionalViewBuilder(dimensions,valueCount){if(typeof(dimensions)!=='number'||dimensions<0){throw new Error('Dimensions must be a non-negative number');}
+this.dimensions_=dimensions;if(typeof(valueCount)!=='number'||valueCount<0){throw new Error('Number of values must be a non-negative number');}
+this.valueCount_=valueCount;this.buildRoot_=this.createRootNode_();this.topDownTreeViewRoot_=undefined;this.topDownHeavyViewRoot_=undefined;this.bottomUpHeavyViewNode_=undefined;this.complete_=false;this.maxDimensionDepths_=new Array(dimensions);for(let d=0;d<dimensions;d++){this.maxDimensionDepths_[d]=0;}}
+MultiDimensionalViewBuilder.ValueKind={SELF:0,TOTAL:1};MultiDimensionalViewBuilder.ViewType={TOP_DOWN_TREE_VIEW:0,TOP_DOWN_HEAVY_VIEW:1,BOTTOM_UP_HEAVY_VIEW:2};MultiDimensionalViewBuilder.prototype={addPath(path,values,valueKind){if(this.buildRoot_===undefined){throw new Error('Paths cannot be added after either view has been built');}
+if(path.length!==this.dimensions_){throw new Error('Path must be '+this.dimensions_+'-dimensional');}
+if(values.length!==this.valueCount_){throw new Error('Must provide '+this.valueCount_+' values');}
+let isTotal;switch(valueKind){case MultiDimensionalViewBuilder.ValueKind.SELF:isTotal=false;break;case MultiDimensionalViewBuilder.ValueKind.TOTAL:isTotal=true;break;default:throw new Error('Invalid value kind: '+valueKind);}
+let node=this.buildRoot_;for(let d=0;d<path.length;d++){const singleDimensionPath=path[d];const singleDimensionPathLength=singleDimensionPath.length;this.maxDimensionDepths_[d]=Math.max(this.maxDimensionDepths_[d],singleDimensionPathLength);for(let i=0;i<singleDimensionPathLength;i++){node=this.getOrCreateChildNode_(node,d,singleDimensionPath[i]);}}
+for(let v=0;v<this.valueCount_;v++){const addedValue=values[v];if(addedValue===undefined)continue;const nodeValue=node.values[v];if(isTotal){nodeValue.total+=addedValue;nodeValue.totalState=EXACT;}else{nodeValue.self+=addedValue;nodeValue.totalState=Math.max(nodeValue.totalState,LOWER_BOUND);}}},get complete(){return this.complete_;},set complete(isComplete){if(this.buildRoot_===undefined){throw new Error('Can\'t set complete after any view has been built.');}
+this.complete_=isComplete;},buildView(viewType){switch(viewType){case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW:return this.buildTopDownTreeView();case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW:return this.buildTopDownHeavyView();case MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW:return this.buildBottomUpHeavyView();default:throw new Error('Unknown multi-dimensional view type: '+viewType);}},buildTopDownTreeView(){if(this.topDownTreeViewRoot_===undefined){const treeViewRoot=this.buildRoot_;this.buildRoot_=undefined;this.setUpMissingChildRelationships_(treeViewRoot,0);this.finalizeTotalValues_(treeViewRoot,0,new WeakMap());this.topDownTreeViewRoot_=treeViewRoot;}
+return this.topDownTreeViewRoot_;},buildTopDownHeavyView(){if(this.topDownHeavyViewRoot_===undefined){this.topDownHeavyViewRoot_=this.buildGenericHeavyView_(this.addDimensionToTopDownHeavyViewNode_.bind(this));}
+return this.topDownHeavyViewRoot_;},buildBottomUpHeavyView(){if(this.bottomUpHeavyViewNode_===undefined){this.bottomUpHeavyViewNode_=this.buildGenericHeavyView_(this.addDimensionToBottomUpHeavyViewNode_.bind(this));}
+return this.bottomUpHeavyViewNode_;},createRootNode_(){return new MultiDimensionalViewNode(new Array(this.dimensions_),this.valueCount_);},getOrCreateChildNode_(parentNode,dimension,childDimensionTitle){if(dimension<0||dimension>=this.dimensions_){throw new Error('Invalid dimension');}
+const dimensionChildren=parentNode.children[dimension];let childNode=dimensionChildren.get(childDimensionTitle);if(childNode!==undefined){return childNode;}
+const childTitle=parentNode.title.slice();childTitle[dimension]=childDimensionTitle;childNode=new MultiDimensionalViewNode(childTitle,this.valueCount_);dimensionChildren.set(childDimensionTitle,childNode);return childNode;},setUpMissingChildRelationships_(node,firstDimensionToSetUp){for(let d=firstDimensionToSetUp;d<this.dimensions_;d++){const currentDimensionChildTitles=new Set(node.children[d].keys());for(let i=0;i<d;i++){for(const previousDimensionChildNode of node.children[i].values()){for(const previousDimensionGrandChildTitle of
+previousDimensionChildNode.children[d].keys()){currentDimensionChildTitles.add(previousDimensionGrandChildTitle);}}}
+for(const currentDimensionChildTitle of currentDimensionChildTitles){const currentDimensionChildNode=this.getOrCreateChildNode_(node,d,currentDimensionChildTitle);for(let i=0;i<d;i++){for(const previousDimensionChildNode of
+node.children[i].values()){const previousDimensionGrandChildNode=previousDimensionChildNode.children[d].get(currentDimensionChildTitle);if(previousDimensionGrandChildNode!==undefined){currentDimensionChildNode.children[i].set(previousDimensionChildNode.title[i],previousDimensionGrandChildNode);}}}
+this.setUpMissingChildRelationships_(currentDimensionChildNode,d);}}},finalizeTotalValues_(node,firstDimensionToFinalize,dimensionalSelfSumsMap){const dimensionalSelfSums=new Array(this.dimensions_);const minResidual=new Array(this.valueCount_);for(let v=0;v<this.valueCount_;v++)minResidual[v]=0;const nodeValues=node.values;const nodeSelfSums=new Array(this.valueCount_);for(let v=0;v<this.valueCount_;v++){nodeSelfSums[v]=nodeValues[v].self;}
+for(let d=0;d<this.dimensions_;d++){const childResidualSums=new Array(this.valueCount_);for(let v=0;v<this.valueCount_;v++){childResidualSums[v]=0;}
+for(const childNode of node.children[d].values()){if(d>=firstDimensionToFinalize){this.finalizeTotalValues_(childNode,d,dimensionalSelfSumsMap);}
+const childNodeSelfSums=dimensionalSelfSumsMap.get(childNode);const childNodeValues=childNode.values;for(let v=0;v<this.valueCount_;v++){nodeSelfSums[v]+=childNodeSelfSums[d][v];const residual=childNodeValues[v].total-
+childNodeSelfSums[this.dimensions_-1][v];childResidualSums[v]+=residual;if(this.complete){nodeValues[v].totalState=EXACT;}else if(childNodeValues[v].totalState>NOT_PROVIDED){nodeValues[v].totalState=Math.max(nodeValues[v].totalState,LOWER_BOUND);}}}
+dimensionalSelfSums[d]=nodeSelfSums.slice();for(let v=0;v<this.valueCount_;v++){minResidual[v]=Math.max(minResidual[v],childResidualSums[v]);}}
+for(let v=0;v<this.valueCount_;v++){nodeValues[v].total=Math.max(nodeValues[v].total,nodeSelfSums[v]+minResidual[v]);}
+if(dimensionalSelfSumsMap.has(node)){throw new Error('Internal error: Node finalized more than once');}
+dimensionalSelfSumsMap.set(node,dimensionalSelfSums);},buildGenericHeavyView_(treeViewNodeHandler){const treeViewRoot=this.buildTopDownTreeView();const heavyViewRoot=this.createRootNode_();heavyViewRoot.values=treeViewRoot.values;const recursionDepthTrackers=new Array(this.dimensions_);for(let d=0;d<this.dimensions_;d++){recursionDepthTrackers[d]=new RecursionDepthTracker(this.maxDimensionDepths_[d],d);}
+this.addDimensionsToGenericHeavyViewNode_(treeViewRoot,heavyViewRoot,0,recursionDepthTrackers,false,treeViewNodeHandler);this.setUpMissingChildRelationships_(heavyViewRoot,0);return heavyViewRoot;},addDimensionsToGenericHeavyViewNode_(treeViewParentNode,heavyViewParentNode,startDimension,recursionDepthTrackers,previousDimensionsRecursive,treeViewNodeHandler){for(let d=startDimension;d<this.dimensions_;d++){this.addDimensionDescendantsToGenericHeavyViewNode_(treeViewParentNode,heavyViewParentNode,d,recursionDepthTrackers,previousDimensionsRecursive,treeViewNodeHandler);}},addDimensionDescendantsToGenericHeavyViewNode_(treeViewParentNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive,treeViewNodeHandler){const treeViewChildren=treeViewParentNode.children[currentDimension];const recursionDepthTracker=recursionDepthTrackers[currentDimension];for(const treeViewChildNode of treeViewChildren.values()){recursionDepthTracker.push(treeViewChildNode);treeViewNodeHandler(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive);this.addDimensionDescendantsToGenericHeavyViewNode_(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive,treeViewNodeHandler);recursionDepthTracker.pop();}},addDimensionToTopDownHeavyViewNode_(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive){this.addDimensionToTopDownHeavyViewNodeRecursively_(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive,1);},addDimensionToTopDownHeavyViewNodeRecursively_(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive,subTreeDepth){const recursionDepthTracker=recursionDepthTrackers[currentDimension];const currentDimensionRecursive=subTreeDepth<=recursionDepthTracker.recursionDepth;const currentOrPreviousDimensionsRecursive=currentDimensionRecursive||previousDimensionsRecursive;const dimensionTitle=treeViewChildNode.title[currentDimension];const heavyViewChildNode=this.getOrCreateChildNode_(heavyViewParentNode,currentDimension,dimensionTitle);this.addNodeValues_(treeViewChildNode,heavyViewChildNode,!currentOrPreviousDimensionsRecursive);this.addDimensionsToGenericHeavyViewNode_(treeViewChildNode,heavyViewChildNode,currentDimension+1,recursionDepthTrackers,currentOrPreviousDimensionsRecursive,this.addDimensionToTopDownHeavyViewNode_.bind(this));for(const treeViewGrandChildNode of
+treeViewChildNode.children[currentDimension].values()){recursionDepthTracker.push(treeViewGrandChildNode);this.addDimensionToTopDownHeavyViewNodeRecursively_(treeViewGrandChildNode,heavyViewChildNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive,subTreeDepth+1);recursionDepthTracker.pop();}},addDimensionToBottomUpHeavyViewNode_(treeViewChildNode,heavyViewParentNode,currentDimension,recursionDepthTrackers,previousDimensionsRecursive){const recursionDepthTracker=recursionDepthTrackers[currentDimension];const bottomIndex=recursionDepthTracker.bottomIndex;const topIndex=recursionDepthTracker.topIndex;const firstNonRecursiveIndex=bottomIndex+recursionDepthTracker.recursionDepth;const viewNodePath=recursionDepthTracker.viewNodePath;const trackerAncestorNode=recursionDepthTracker.trackerAncestorNode;let heavyViewDescendantNode=heavyViewParentNode;for(let i=bottomIndex;i<topIndex;i++){const treeViewAncestorNode=viewNodePath[i];const dimensionTitle=treeViewAncestorNode.title[currentDimension];heavyViewDescendantNode=this.getOrCreateChildNode_(heavyViewDescendantNode,currentDimension,dimensionTitle);const currentDimensionRecursive=i<firstNonRecursiveIndex;const currentOrPreviousDimensionsRecursive=currentDimensionRecursive||previousDimensionsRecursive;this.addNodeValues_(treeViewChildNode,heavyViewDescendantNode,!currentOrPreviousDimensionsRecursive);this.addDimensionsToGenericHeavyViewNode_(treeViewChildNode,heavyViewDescendantNode,currentDimension+1,recursionDepthTrackers,currentOrPreviousDimensionsRecursive,this.addDimensionToBottomUpHeavyViewNode_.bind(this));}},addNodeValues_(sourceNode,targetNode,addTotal){const targetNodeValues=targetNode.values;const sourceNodeValues=sourceNode.values;for(let v=0;v<this.valueCount_;v++){const targetNodeValue=targetNodeValues[v];const sourceNodeValue=sourceNodeValues[v];targetNodeValue.self+=sourceNodeValue.self;if(addTotal){targetNodeValue.total+=sourceNodeValue.total;if(this.complete){targetNodeValue.totalState=EXACT;}else if(sourceNodeValue.totalState>NOT_PROVIDED){targetNodeValue.totalState=Math.max(targetNodeValue.totalState,LOWER_BOUND);}}}}};function RecursionDepthTracker(maxDepth,dimension){this.titlePath=new Array(maxDepth);this.viewNodePath=new Array(maxDepth);this.bottomIndex=this.topIndex=maxDepth;this.dimension_=dimension;this.currentTrackerNode_=this.createNode_(0,undefined);}
+RecursionDepthTracker.prototype={push(viewNode){if(this.bottomIndex===0){throw new Error('Cannot push to a full tracker');}
+const title=viewNode.title[this.dimension_];this.bottomIndex--;this.titlePath[this.bottomIndex]=title;this.viewNodePath[this.bottomIndex]=viewNode;let childTrackerNode=this.currentTrackerNode_.children.get(title);if(childTrackerNode!==undefined){this.currentTrackerNode_=childTrackerNode;return;}
+const maxLengths=zFunction(this.titlePath,this.bottomIndex);let recursionDepth=0;for(let i=0;i<maxLengths.length;i++){recursionDepth=Math.max(recursionDepth,maxLengths[i]);}
+childTrackerNode=this.createNode_(recursionDepth,this.currentTrackerNode_);this.currentTrackerNode_.children.set(title,childTrackerNode);this.currentTrackerNode_=childTrackerNode;},pop(){if(this.bottomIndex===this.topIndex){throw new Error('Cannot pop from an empty tracker');}
+this.titlePath[this.bottomIndex]=undefined;this.viewNodePath[this.bottomIndex]=undefined;this.bottomIndex++;this.currentTrackerNode_=this.currentTrackerNode_.parent;},get recursionDepth(){return this.currentTrackerNode_.recursionDepth;},createNode_(recursionDepth,parent){return{recursionDepth,parent,children:new Map()};}};function zFunction(list,startIndex){const n=list.length-startIndex;if(n===0)return[];const z=new Array(n);z[0]=0;for(let i=1,left=0,right=0;i<n;++i){let maxLength;if(i<=right){maxLength=Math.min(right-i+1,z[i-left]);}else{maxLength=0;}
+while(i+maxLength<n&&list[startIndex+maxLength]===list[startIndex+i+maxLength]){++maxLength;}
+if(i+maxLength-1>right){left=i;right=i+maxLength-1;}
+z[i]=maxLength;}
+return z;}
+return{MultiDimensionalViewBuilder,MultiDimensionalViewNode,RecursionDepthTracker,zFunction,};});'use strict';tr.exportTo('tr.e.chrome',function(){class CpuTime{static getStageToInitiatorToSegmentBounds(segments,rangeOfInterest){const stageToInitiatorToRanges=new Map();stageToInitiatorToRanges.set('all_stages',new Map([['all_initiators',new Set()]]));const allRanges=stageToInitiatorToRanges.get('all_stages').get('all_initiators');for(const segment of segments){if(!rangeOfInterest.intersectsRangeInclusive(segment.range))continue;const intersectingRange=rangeOfInterest.findIntersection(segment.range);allRanges.add(intersectingRange);for(const expectation of segment.expectations){const stageTitle=expectation.stageTitle;if(!stageToInitiatorToRanges.has(stageTitle)){stageToInitiatorToRanges.set(stageTitle,new Map([['all_initiators',new Set()]]));}
+const initiatorToRanges=stageToInitiatorToRanges.get(stageTitle);initiatorToRanges.get('all_initiators').add(intersectingRange);const initiatorType=expectation.initiatorType;if(initiatorType){if(!initiatorToRanges.has(initiatorType)){initiatorToRanges.set(initiatorType,new Set());}
+initiatorToRanges.get(initiatorType).add(intersectingRange);}}}
+return stageToInitiatorToRanges;}
+static constructMultiDimensionalView(model,rangeOfInterest){const mdvBuilder=new tr.b.MultiDimensionalViewBuilder(3,2);const stageToInitiatorToRanges=CpuTime.getStageToInitiatorToSegmentBounds(model.userModel.segments,rangeOfInterest);const allSegmentBoundsInRange=stageToInitiatorToRanges.get('all_stages').get('all_initiators');for(const[pid,process]of Object.entries(model.processes)){const processType=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);for(const[tid,thread]of Object.entries(process.threads)){const rangeToCpuTime=new Map();for(const range of allSegmentBoundsInRange){rangeToCpuTime.set(range,thread.getCpuTimeForRange(range));}
+for(const[stage,initiatorToRanges]of stageToInitiatorToRanges){for(const[initiator,ranges]of initiatorToRanges){const cpuTime=tr.b.math.Statistics.sum(ranges,range=>rangeToCpuTime.get(range));const duration=tr.b.math.Statistics.sum(ranges,range=>range.duration);const cpuTimePerSecond=cpuTime/duration;mdvBuilder.addPath([[processType],[thread.type],[stage,initiator]],[cpuTimePerSecond,cpuTime],tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);}}}}
+return mdvBuilder.buildTopDownTreeView();}}
+return{CpuTime,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const CPU_PERCENTAGE_UNIT=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const CPU_TIME_UNIT=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;function clonePath_(previousPath){return previousPath.map(subPath=>subPath.map(x=>x));}
+function decodePath_(path){return{processType:path[0][0],threadType:path[1][0],railStage:path[2][0],initiatorType:path[2][1]};}
+function stringifyPathName_(path){const decodedPath=decodePath_(path);return[decodedPath.processType,decodedPath.threadType,decodedPath.railStage,decodedPath.initiatorType].join(':');}
+class CpuTimeTreeDataReporter{constructor(){this.visitedSet_=new Set();}
+reportValuesFromNode_(node,path){const decodedPath=decodePath_(path);const processType=decodedPath.processType||'all_processes';const threadType=decodedPath.threadType||'all_threads';if(!decodedPath.railStage||!decodedPath.initiatorType)return;const{railStage,initiatorType}=decodedPath;const serializedPathName=[processType,threadType,railStage,initiatorType].join(':');const cpuPercentageValue=node.values[0].total;const cpuTimeValue=node.values[1].total;this.histogramSet_.createHistogram(`cpuPercentage:${serializedPathName}`,CPU_PERCENTAGE_UNIT,cpuPercentageValue);this.histogramSet_.createHistogram(`cpuTime:${serializedPathName}`,CPU_TIME_UNIT,cpuTimeValue);}
+reportDataFromTree_(root,rootPath){const rootPathString=stringifyPathName_(rootPath);if(this.visitedSet_.has(rootPathString))return;this.visitedSet_.add(rootPathString);this.reportValuesFromNode_(root,rootPath);for(let dimension=0;dimension<root.children.length;dimension++){const children=root.children[dimension];for(const[name,node]of children){const childPath=clonePath_(rootPath);childPath[dimension].push(name);this.reportDataFromTree_(node,childPath);}}}
+addTreeValuesToHistogramSet(rootNode,histogramSet){const rootPath=[[],[],[]];this.rootNode_=rootNode;this.histogramSet_=histogramSet;this.reportDataFromTree_(this.rootNode_,rootPath);}
+static reportToHistogramSet(rootNode,histogramSet){const reporter=new CpuTimeTreeDataReporter();reporter.addTreeValuesToHistogramSet(rootNode,histogramSet);}}
+return{CpuTimeTreeDataReporter,};});'use strict';tr.exportTo('tr.metrics.sh',function(){function newCpuTimeMetric(histograms,model,opt_options){const rangeOfInterest=opt_options&&opt_options.rangeOfInterest?opt_options.rangeOfInterest:model.bounds;const rootNode=tr.e.chrome.CpuTime.constructMultiDimensionalView(model,rangeOfInterest);tr.metrics.sh.CpuTimeTreeDataReporter.reportToHistogramSet(rootNode,histograms);}
+tr.metrics.MetricRegistry.register(newCpuTimeMetric,{supportsRangeOfInterest:true});return{newCpuTimeMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const includeHistogramNames=['cpuTime:all_processes:all_threads:all_stages:all_initiators','cpuPercentage:all_processes:all_threads:all_stages:all_initiators','cpuTime:browser_process:all_threads:all_stages:all_initiators','cpuPercentage:browser_process:all_threads:all_stages:all_initiators','cpuTime:renderer_processes:all_threads:all_stages:all_initiators','cpuPercentage:renderer_processes:all_threads:all_stages:all_initiators','cpuTime:gpu_process:all_threads:all_stages:all_initiators','cpuPercentage:gpu_process:all_threads:all_stages:all_initiators','cpuTime:renderer_processes:CrRendererMain:all_stages:all_initiators','cpuPercentage:renderer_processes:CrRendererMain:all_stages:all_initiators','cpuTime:browser_process:CrBrowserMain:all_stages:all_initiators','cpuPercentage:browser_process:CrBrowserMain:all_stages:all_initiators','cpuTime:all_processes:all_threads:Load:Successful','cpuPercentage:all_processes:all_threads:Load:Successful',];function limitedCpuTimeMetric(histograms,model,opt_options){const allCpuHistograms=new tr.v.HistogramSet();tr.metrics.sh.newCpuTimeMetric(allCpuHistograms,model,opt_options);for(const histogramName of includeHistogramNames){const histogram=allCpuHistograms.getHistogramNamed(histogramName);if(histogram)histograms.addHistogram(histogram);}}
+tr.metrics.MetricRegistry.register(limitedCpuTimeMetric,{supportsRangeOfInterest:true});return{limitedCpuTimeMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const LONG_TASK_MS=50;const LONGEST_TASK_MS=1000;function iterateLongTopLevelTasksOnThreadInRange(thread,opt_range,cb,opt_this){thread.sliceGroup.topLevelSlices.forEach(function(slice){if(opt_range&&!opt_range.intersectsExplicitRangeInclusive(slice.start,slice.end)){return;}
+if(slice.duration<LONG_TASK_MS)return;cb.call(opt_this,slice);});}
+function iterateRendererMainThreads(model,cb,opt_this){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(modelHelper!==undefined){Object.values(modelHelper.rendererHelpers).forEach(function(rendererHelper){if(!rendererHelper.mainThread)return;cb.call(opt_this,rendererHelper.mainThread);});}}
+const BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(LONG_TASK_MS,LONGEST_TASK_MS,40);function longTasksMetric(histograms,model,opt_options){const rangeOfInterest=opt_options?opt_options.rangeOfInterest:undefined;const longTaskHist=histograms.createHistogram('longTasks',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,description:'durations of long tasks',});const relatedNames=new tr.v.d.RelatedNameMap();longTaskHist.diagnostics.set('categories',relatedNames);iterateRendererMainThreads(model,function(thread){iterateLongTopLevelTasksOnThreadInRange(thread,rangeOfInterest,function(task){const breakdown=new tr.v.d.Breakdown();breakdown.colorScheme=tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER;for(const slice of task.descendentSlices){const sample=slice.cpuSelfTime;if(sample===undefined)continue;const category=model.getUserFriendlyCategoryFromEvent(slice);const histName='longTasks:'+category;let hist=histograms.getHistogramNamed(histName);if(hist===undefined){hist=histograms.createHistogram(histName,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{binBoundaries:BIN_BOUNDARIES,});relatedNames.set(category,hist.name);}
+hist.addSample(sample,{events:new tr.v.d.RelatedEventSet([slice]),});breakdown.set(category,sample+breakdown.get(category));}
+longTaskHist.addSample(task.duration,{events:new tr.v.d.RelatedEventSet([task]),categories:breakdown,});});});}
+tr.metrics.MetricRegistry.register(longTasksMetric,{supportsRangeOfInterest:true,requiredCategories:['toplevel'],});return{longTasksMetric,iterateLongTopLevelTasksOnThreadInRange,iterateRendererMainThreads,LONG_TASK_MS,LONGEST_TASK_MS,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const sizeInBytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const count_smallerIsBetter=tr.b.Unit.byName.count_smallerIsBetter;const DISPLAYED_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;const LEVEL_OF_DETAIL_NAMES=new Map();LEVEL_OF_DETAIL_NAMES.set(BACKGROUND,'background');LEVEL_OF_DETAIL_NAMES.set(LIGHT,'light');LEVEL_OF_DETAIL_NAMES.set(DETAILED,'detailed');const HEAP_PROFILER_DETAIL_NAME='heap_profiler';const BOUNDARIES_FOR_UNIT_MAP=new WeakMap();BOUNDARIES_FOR_UNIT_MAP.set(count_smallerIsBetter,tr.v.HistogramBinBoundaries.createLinear(0,20,20));BOUNDARIES_FOR_UNIT_MAP.set(sizeInBytes_smallerIsBetter,new tr.v.HistogramBinBoundaries(0).addBinBoundary(1024).addExponentialBins(16*1024*1024*1024,4*24));const CHROME_PROCESS_NAMES=tr.e.chrome.chrome_processes.CHROME_PROCESS_NAMES;function memoryMetric(values,model,opt_options){const rangeOfInterest=opt_options?opt_options.rangeOfInterest:undefined;const browserNameToGlobalDumps=tr.metrics.sh.splitGlobalDumpsByBrowserName(model,rangeOfInterest);addGeneralMemoryDumpValues(browserNameToGlobalDumps,values);addDetailedMemoryDumpValues(browserNameToGlobalDumps,values);addMemoryDumpCountValues(browserNameToGlobalDumps,values);}
+const USER_FRIENDLY_BROWSER_NAMES={'chrome':'Chrome','webview':'WebView','unknown_browser':'an unknown browser'};function convertBrowserNameToUserFriendlyName(browserName){for(const baseName in USER_FRIENDLY_BROWSER_NAMES){if(!browserName.startsWith(baseName))continue;const userFriendlyBaseName=USER_FRIENDLY_BROWSER_NAMES[baseName];const suffix=browserName.substring(baseName.length);if(suffix.length===0){return userFriendlyBaseName;}else if(/^\d+$/.test(suffix)){return userFriendlyBaseName+'('+suffix+')';}}
+return'\''+browserName+'\' browser';}
+function convertProcessNameToUserFriendlyName(processName,opt_requirePlural){switch(processName){case CHROME_PROCESS_NAMES.BROWSER:return opt_requirePlural?'browser processes':'the browser process';case CHROME_PROCESS_NAMES.RENDERER:return'renderer processes';case CHROME_PROCESS_NAMES.GPU:return opt_requirePlural?'GPU processes':'the GPU process';case CHROME_PROCESS_NAMES.PPAPI:return opt_requirePlural?'PPAPI processes':'the PPAPI process';case CHROME_PROCESS_NAMES.ALL:return'all processes';case CHROME_PROCESS_NAMES.UNKNOWN:return'unknown processes';default:return'\''+processName+'\' processes';}}
+function addGeneralMemoryDumpValues(browserNameToGlobalDumps,values){addMemoryDumpValues(browserNameToGlobalDumps,gmd=>true,function(processDump,addProcessScalar){addProcessScalar({source:'process_count',property:PROCESS_COUNT,value:1});if(processDump.totals!==undefined){addProcessScalar({source:'reported_by_os',property:RESIDENT_SIZE,component:['system_memory'],value:processDump.totals.residentBytes});addProcessScalar({source:'reported_by_os',property:PEAK_RESIDENT_SIZE,component:['system_memory'],value:processDump.totals.peakResidentBytes});addProcessScalar({source:'reported_by_os',property:PRIVATE_FOOTPRINT_SIZE,component:['system_memory'],value:processDump.totals.privateFootprintBytes,});}
+if(processDump.memoryAllocatorDumps===undefined)return;processDump.memoryAllocatorDumps.forEach(function(rootAllocatorDump){CHROME_VALUE_PROPERTIES.forEach(function(property){addProcessScalar({source:'reported_by_chrome',component:[rootAllocatorDump.name],property,value:rootAllocatorDump.numerics[property.name]});});if(rootAllocatorDump.numerics.allocated_objects_size===undefined){const allocatedObjectsDump=rootAllocatorDump.getDescendantDumpByFullName('allocated_objects');if(allocatedObjectsDump!==undefined){addProcessScalar({source:'reported_by_chrome',component:[rootAllocatorDump.name],property:ALLOCATED_OBJECTS_SIZE,value:allocatedObjectsDump.numerics.size});}}});addTopHeapDumpCategoryValue(processDump,addProcessScalar);addV8MemoryDumpValues(processDump,addProcessScalar);},function(componentTree){const tracingNode=componentTree.children[1].get('tracing');if(tracingNode===undefined)return;for(let i=0;i<componentTree.values.length;i++){componentTree.values[i].total-=tracingNode.values[i].total;}},values);}
+function addTopHeapDumpCategoryValue(processDump,addProcessScalar){if(!processDump.heapDumps){return;}
+for(const allocatorName in processDump.heapDumps){const heapDump=processDump.heapDumps[allocatorName];if(heapDump.entries===undefined||heapDump.entries.length===0){return;}
+const typeToSize={};for(let i=0;i<heapDump.entries.length;i+=1){const entry=heapDump.entries[i];if(!entry.objectTypeName||entry.leafStackFrame){continue;}
+if(!typeToSize[entry.objectTypeName]){typeToSize[entry.objectTypeName]=0;}
+typeToSize[entry.objectTypeName]+=entry.size;}
+let largestValue=0;let largestType='';for(const key in typeToSize){if(largestValue<typeToSize[key]){largestValue=typeToSize[key];largestType=key;}}
+addProcessScalar({source:'reported_by_chrome',component:[allocatorName,largestType],property:HEAP_CATEGORY_SIZE,value:largestValue});}}
+function addV8MemoryDumpValues(processDump,addProcessScalar){const v8Dump=processDump.getMemoryAllocatorDumpByFullName('v8');if(v8Dump===undefined)return;const sharedDump=v8Dump.getDescendantDumpByFullName('shared');if(sharedDump!==undefined){addV8ComponentValues(sharedDump,['v8','shared'],addProcessScalar);sharedDump.children.forEach(function(subDump){addV8ComponentValues(subDump,['v8','shared',subDump.name],addProcessScalar);});}
+v8Dump.children.forEach(function(isolateDump){const mallocDump=isolateDump.getDescendantDumpByFullName('malloc');if(mallocDump!==undefined){addV8ComponentValues(mallocDump,['v8','allocated_by_malloc'],addProcessScalar);}
+let heapDump=isolateDump.getDescendantDumpByFullName('heap');if(heapDump===undefined){heapDump=isolateDump.getDescendantDumpByFullName('heap_spaces');}
+if(heapDump!==undefined){addV8ComponentValues(heapDump,['v8','heap'],addProcessScalar);heapDump.children.forEach(function(spaceDump){if(spaceDump.name==='other_spaces')return;addV8ComponentValues(spaceDump,['v8','heap',spaceDump.name],addProcessScalar);});}});addProcessScalar({source:'reported_by_chrome',component:['v8'],property:CODE_AND_METADATA_SIZE,value:v8Dump.numerics.code_and_metadata_size});addProcessScalar({source:'reported_by_chrome',component:['v8'],property:CODE_AND_METADATA_SIZE,value:v8Dump.numerics.bytecode_and_metadata_size});}
+function addV8ComponentValues(componentDump,componentPath,addProcessScalar){CHROME_VALUE_PROPERTIES.forEach(function(property){addProcessScalar({source:'reported_by_chrome',component:componentPath,property,value:componentDump.numerics[property.name]});});}
+const PROCESS_COUNT={unit:count_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){if(componentPath.length>0){throw new Error('Unexpected process count non-empty component path: '+
+componentPath.join(':'));}
+return'total number of '+convertProcessNameToUserFriendlyName(processName,true);}};const EFFECTIVE_SIZE={name:'effective_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'effective size',componentPreposition:'of'});}};const ALLOCATED_OBJECTS_SIZE={name:'allocated_objects_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'size of all objects allocated',totalUserFriendlyPropertyName:'size of all allocated objects',componentPreposition:'by'});}};const SHIM_ALLOCATED_OBJECTS_SIZE={name:'shim_allocated_objects_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'size of all objects allocated through shim',totalUserFriendlyPropertyName:'size of all allocated objects through shim',componentPreposition:'by'});}};const LOCKED_SIZE={name:'locked_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'locked (pinned) size',componentPreposition:'of'});}};const PEAK_SIZE={name:'peak_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'peak size',componentPreposition:'of'});}};const HEAP_CATEGORY_SIZE={name:'heap_category_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyName:'heap profiler category size',componentPreposition:'for'});}};const CODE_AND_METADATA_SIZE={name:'code_and_metadata_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildChromeValueDescriptionPrefix(componentPath,processName,{userFriendlyPropertyNamePrefix:'size of',userFriendlyPropertyName:'code and metadata'});}};const CHROME_VALUE_PROPERTIES=[EFFECTIVE_SIZE,ALLOCATED_OBJECTS_SIZE,SHIM_ALLOCATED_OBJECTS_SIZE,LOCKED_SIZE,PEAK_SIZE];function buildChromeValueDescriptionPrefix(componentPath,processName,formatSpec){const nameParts=[];if(componentPath.length===0){nameParts.push('total');if(formatSpec.totalUserFriendlyPropertyName){nameParts.push(formatSpec.totalUserFriendlyPropertyName);}else{if(formatSpec.userFriendlyPropertyNamePrefix){nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);}
+nameParts.push(formatSpec.userFriendlyPropertyName);}
+nameParts.push('reported by Chrome for');}else{if(formatSpec.componentPreposition===undefined){if(formatSpec.userFriendlyPropertyNamePrefix){nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);}
+nameParts.push(componentPath.join(':'));nameParts.push(formatSpec.userFriendlyPropertyName);}else{if(formatSpec.userFriendlyPropertyNamePrefix){nameParts.push(formatSpec.userFriendlyPropertyNamePrefix);}
+nameParts.push(formatSpec.userFriendlyPropertyName);nameParts.push(formatSpec.componentPreposition);if(componentPath[componentPath.length-1]==='allocated_by_malloc'){nameParts.push('objects allocated by malloc for');nameParts.push(componentPath.slice(0,componentPath.length-1).join(':'));}else{nameParts.push(componentPath.join(':'));}}
+nameParts.push('in');}
+nameParts.push(convertProcessNameToUserFriendlyName(processName));return nameParts.join(' ');}
+const RESIDENT_SIZE={name:'resident_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'resident set size (RSS)');}};const PEAK_RESIDENT_SIZE={name:'peak_resident_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'peak resident set size');}};const PROPORTIONAL_RESIDENT_SIZE={name:'proportional_resident_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'proportional resident size (PSS)');}};const PRIVATE_DIRTY_SIZE={name:'private_dirty_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'private dirty size');}};const PRIVATE_FOOTPRINT_SIZE={name:'private_footprint_size',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'private footprint size');}};const JAVA_BASE_CLEAN_RESIDENT={name:'java_base_clean_resident',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'java base odex and vdex total clean resident size');}};const JAVA_BASE_PSS={name:'java_base_pss',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'java base odex and vdex proportional resident size');}};const NATIVE_LIBRARY_PRIVATE_CLEAN_RESIDENT={name:'native_library_private_clean_resident',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'native library private clean resident size');}};const NATIVE_LIBRARY_SHARED_CLEAN_RESIDENT={name:'native_library_shared_clean_resident',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'native library shared clean resident size');}};const NATIVE_LIBRARY_PROPORTIONAL_RESIDENT={name:'native_library_proportional_resident',unit:sizeInBytes_smallerIsBetter,buildDescriptionPrefix(componentPath,processName){return buildOsValueDescriptionPrefix(componentPath,processName,'native library proportional resident size');}};function buildOsValueDescriptionPrefix(componentPath,processName,userFriendlyPropertyName){if(componentPath.length>2){throw new Error('OS value component path for \''+
+userFriendlyPropertyName+'\' too long: '+componentPath.join(':'));}
+const nameParts=[];if(componentPath.length<2){nameParts.push('total');}
+nameParts.push(userFriendlyPropertyName);if(componentPath.length>0){switch(componentPath[0]){case'system_memory':if(componentPath.length>1){const userFriendlyComponentName=SYSTEM_VALUE_COMPONENTS[componentPath[1]].userFriendlyName;if(userFriendlyComponentName===undefined){throw new Error('System value sub-component for \''+
+userFriendlyPropertyName+'\' unknown: '+
+componentPath.join(':'));}
+nameParts.push('of',userFriendlyComponentName,'in');}else{nameParts.push('of system memory (RAM) used by');}
+break;case'gpu_memory':if(componentPath.length>1){nameParts.push('of the',componentPath[1]);nameParts.push('Android memtrack component in');}else{nameParts.push('of GPU memory (Android memtrack) used by');}
+break;default:throw new Error('OS value component for \''+
+userFriendlyPropertyName+'\' unknown: '+
+componentPath.join(':'));}}else{nameParts.push('reported by the OS for');}
+nameParts.push(convertProcessNameToUserFriendlyName(processName));return nameParts.join(' ');}
+function addDetailedMemoryDumpValues(browserNameToGlobalDumps,values){addMemoryDumpValues(browserNameToGlobalDumps,g=>g.levelOfDetail===DETAILED,function(processDump,addProcessScalar){for(const[componentName,componentSpec]of
+Object.entries(SYSTEM_VALUE_COMPONENTS)){const node=getDescendantVmRegionClassificationNode(processDump.vmRegions,componentSpec.classificationPath);const componentPath=['system_memory'];if(componentName)componentPath.push(componentName);addProcessScalar({source:'reported_by_os',component:componentPath,property:PROPORTIONAL_RESIDENT_SIZE,value:node===undefined?0:(node.byteStats.proportionalResident||0)});addProcessScalar({source:'reported_by_os',component:componentPath,property:PRIVATE_DIRTY_SIZE,value:node===undefined?0:(node.byteStats.privateDirtyResident||0)});if(node){if(node.byteStats.javaBasePss){addProcessScalar({source:'reported_by_os',component:componentPath,property:JAVA_BASE_PSS,value:node.byteStats.javaBasePss});}
+if(node.byteStats.javaBaseCleanResident){addProcessScalar({source:'reported_by_os',component:componentPath,property:JAVA_BASE_CLEAN_RESIDENT,value:node.byteStats.javaBaseCleanResident});}}
+if(node){if(node.byteStats.nativeLibraryPrivateCleanResident){addProcessScalar({source:'reported_by_os',component:componentPath,property:NATIVE_LIBRARY_PRIVATE_CLEAN_RESIDENT,value:node.byteStats.nativeLibraryPrivateCleanResident});}
+if(node.byteStats.nativeLibrarySharedCleanResident){addProcessScalar({source:'reported_by_os',component:componentPath,property:NATIVE_LIBRARY_SHARED_CLEAN_RESIDENT,value:node.byteStats.nativeLibrarySharedCleanResident});}
+if(node.byteStats.nativeLibraryProportionalResident){addProcessScalar({source:'reported_by_os',component:componentPath,property:NATIVE_LIBRARY_PROPORTIONAL_RESIDENT,value:node.byteStats.nativeLibraryProportionalResident});}}}
+const memtrackDump=processDump.getMemoryAllocatorDumpByFullName('gpu/android_memtrack');if(memtrackDump!==undefined){memtrackDump.children.forEach(function(memtrackChildDump){addProcessScalar({source:'reported_by_os',component:['gpu_memory',memtrackChildDump.name],property:PROPORTIONAL_RESIDENT_SIZE,value:memtrackChildDump.numerics.memtrack_pss});});}},function(componentTree){},values);}
+const SYSTEM_VALUE_COMPONENTS={'':{classificationPath:[],},'java_heap':{classificationPath:['Android','Java runtime','Spaces'],userFriendlyName:'the Java heap'},'ashmem':{classificationPath:['Android','Ashmem'],userFriendlyName:'ashmem'},'native_heap':{classificationPath:['Native heap'],userFriendlyName:'the native heap'},'stack':{classificationPath:['Stack'],userFriendlyName:'the thread stacks'}};function getDescendantVmRegionClassificationNode(node,path){for(let i=0;i<path.length;i++){if(node===undefined)break;node=node.children.find(c=>c.title===path[i]);}
+return node;}
+function addMemoryDumpCountValues(browserNameToGlobalDumps,values){browserNameToGlobalDumps.forEach(function(globalDumps,browserName){let totalDumpCount=0;const levelOfDetailNameToDumpCount={};LEVEL_OF_DETAIL_NAMES.forEach(function(levelOfDetailName){levelOfDetailNameToDumpCount[levelOfDetailName]=0;});levelOfDetailNameToDumpCount[HEAP_PROFILER_DETAIL_NAME]=0;globalDumps.forEach(function(globalDump){totalDumpCount++;const levelOfDetailName=LEVEL_OF_DETAIL_NAMES.get(globalDump.levelOfDetail);if(levelOfDetailName===undefined){return;}
+levelOfDetailNameToDumpCount[levelOfDetailName]++;if(globalDump.levelOfDetail===DETAILED){if(detectHeapProfilerInMemoryDump(globalDump)){levelOfDetailNameToDumpCount[HEAP_PROFILER_DETAIL_NAME]++;}}});reportMemoryDumpCountAsValue(browserName,undefined,totalDumpCount,values);for(const[levelOfDetailName,levelOfDetailDumpCount]of
+Object.entries(levelOfDetailNameToDumpCount)){reportMemoryDumpCountAsValue(browserName,levelOfDetailName,levelOfDetailDumpCount,values);}});}
+function detectHeapProfilerInMemoryDump(globalDump){for(const processDump of Object.values(globalDump.processMemoryDumps)){if(processDump.heapDumps&&processDump.heapDumps.malloc){const mallocDump=processDump.heapDumps.malloc;if(mallocDump.entries&&mallocDump.entries.length>0){return true;}}}
+return false;}
+function reportMemoryDumpCountAsValue(browserName,levelOfDetailName,levelOfDetailDumpCount,values){const nameParts=['memory',browserName,'all_processes','dump_count'];if(levelOfDetailName!==undefined){nameParts.push(levelOfDetailName);}
+const name=nameParts.join(':');const histogram=new tr.v.Histogram(name,count_smallerIsBetter,BOUNDARIES_FOR_UNIT_MAP.get(count_smallerIsBetter));histogram.addSample(levelOfDetailDumpCount);const userFriendlyLevelOfDetail=(levelOfDetailName||'all').replace('_',' ');histogram.description=['total number of',userFriendlyLevelOfDetail,'memory dumps added by',convertBrowserNameToUserFriendlyName(browserName),'to the trace'].join(' ');values.addHistogram(histogram);}
+function addMemoryDumpValues(browserNameToGlobalDumps,customGlobalDumpFilter,customProcessDumpValueExtractor,customComponentTreeModifier,values){browserNameToGlobalDumps.forEach(function(globalDumps,browserName){const filteredGlobalDumps=globalDumps.filter(customGlobalDumpFilter);const sourceToPropertyToBuilder=extractDataFromGlobalDumps(filteredGlobalDumps,customProcessDumpValueExtractor);reportDataAsValues(sourceToPropertyToBuilder,browserName,customComponentTreeModifier,values);});}
+function extractDataFromGlobalDumps(globalDumps,customProcessDumpValueExtractor){const sourceToPropertyToBuilder=new Map();const dumpCount=globalDumps.length;globalDumps.forEach(function(globalDump,dumpIndex){for(const processDump of Object.values(globalDump.processMemoryDumps)){extractDataFromProcessDump(processDump,sourceToPropertyToBuilder,dumpIndex,dumpCount,customProcessDumpValueExtractor);}});return sourceToPropertyToBuilder;}
+function extractDataFromProcessDump(processDump,sourceToPropertyToBuilder,dumpIndex,dumpCount,customProcessDumpValueExtractor){const rawProcessName=processDump.process.name;const processNamePath=[tr.e.chrome.chrome_processes.canonicalizeProcessName(rawProcessName)];customProcessDumpValueExtractor(processDump,function addProcessScalar(spec){if(spec.value===undefined)return;const component=spec.component||[];function createDetailsForErrorMessage(){return['source=',spec.source,', property=',spec.property.name||'(undefined)',', component=',component.length===0?'(empty)':component.join(':'),' in ',processDump.process.userFriendlyName].join('');}
+let value;if(spec.value instanceof tr.b.Scalar){value=spec.value.value;if(spec.value.unit!==spec.property.unit){throw new Error('Scalar unit for '+
+createDetailsForErrorMessage()+' ('+
+spec.value.unit.unitName+') doesn\'t match the unit of the property ('+
+spec.property.unit.unitName+')');}}else{value=spec.value;}
+let propertyToBuilder=sourceToPropertyToBuilder.get(spec.source);if(propertyToBuilder===undefined){propertyToBuilder=new Map();sourceToPropertyToBuilder.set(spec.source,propertyToBuilder);}
+let builder=propertyToBuilder.get(spec.property);if(builder===undefined){builder=new tr.b.MultiDimensionalViewBuilder(2,dumpCount),propertyToBuilder.set(spec.property,builder);}
+const values=new Array(dumpCount);values[dumpIndex]=value;builder.addPath([processNamePath,component],values,tr.b.MultiDimensionalViewBuilder.ValueKind.TOTAL);});}
+function reportDataAsValues(sourceToPropertyToBuilder,browserName,customComponentTreeModifier,values){sourceToPropertyToBuilder.forEach(function(propertyToBuilder,sourceName){propertyToBuilder.forEach(function(builders,property){const tree=builders.buildTopDownTreeView();reportComponentDataAsValues(browserName,sourceName,property,[],[],tree,values,customComponentTreeModifier);});});}
+function reportComponentDataAsValues(browserName,sourceName,property,processPath,componentPath,tree,values,customComponentTreeModifier,opt_cachedHistograms){const cachedHistograms=opt_cachedHistograms||new Map();function recurse(processPath,componentPath,node){return reportComponentDataAsValues(browserName,sourceName,property,processPath,componentPath,node,values,customComponentTreeModifier,cachedHistograms);}
+function buildHistogram(processPath,componentPath,node){return buildNamedMemoryNumericFromNode(browserName,sourceName,property,processPath.length===0?'all_processes':processPath[0],componentPath,node);}
+customComponentTreeModifier(tree);const histogram=buildHistogram(processPath,componentPath,tree);if(cachedHistograms.has(histogram.name)){return cachedHistograms.get(histogram.name);}
+cachedHistograms.set(histogram.name,histogram);const processNames=new tr.v.d.RelatedNameMap();for(const[childProcessName,childProcessNode]of tree.children[0]){processPath.push(childProcessName);const childProcessHistogram=recurse(processPath,componentPath,childProcessNode);processNames.set(childProcessName,childProcessHistogram.name);processPath.pop();}
+const componentNames=new tr.v.d.RelatedNameMap();for(const[childComponentName,childComponentNode]of tree.children[1]){componentPath.push(childComponentName);const childComponentHistogram=recurse(processPath,componentPath,childComponentNode);componentNames.set(childComponentName,childComponentHistogram.name);componentPath.pop();}
+values.addHistogram(histogram);if(tree.children[0].size>0){histogram.diagnostics.set('processes',processNames);}
+if(tree.children[1].size>0){histogram.diagnostics.set('components',componentNames);}
+return histogram;}
+function getNumericName(browserName,sourceName,propertyName,processName,componentPath){const nameParts=['memory',browserName,processName,sourceName].concat(componentPath);if(propertyName!==undefined)nameParts.push(propertyName);return nameParts.join(':');}
+function getNumericDescription(property,browserName,processName,componentPath){return[property.buildDescriptionPrefix(componentPath,processName),'in',convertBrowserNameToUserFriendlyName(browserName)].join(' ');}
+function buildNamedMemoryNumericFromNode(browserName,sourceName,property,processName,componentPath,node){const name=getNumericName(browserName,sourceName,property.name,processName,componentPath);const description=getNumericDescription(property,browserName,processName,componentPath);const numeric=buildMemoryNumericFromNode(name,node,property.unit);numeric.description=description;return numeric;}
+function buildSampleDiagnostics(value,node){if(node.children.length<2)return undefined;const diagnostics=new Map();const i=node.values.indexOf(value);const processBreakdown=new tr.v.d.Breakdown();processBreakdown.colorScheme=tr.e.chrome.chrome_processes.PROCESS_COLOR_SCHEME_NAME;for(const[name,subNode]of node.children[0]){processBreakdown.set(name,subNode.values[i].total);}
+if(processBreakdown.size>0){diagnostics.set('processes',processBreakdown);}
+const componentBreakdown=new tr.v.d.Breakdown();for(const[name,subNode]of node.children[1]){componentBreakdown.set(name,subNode.values[i].total);}
+if(componentBreakdown.size>0){diagnostics.set('components',componentBreakdown);}
+if(diagnostics.size===0)return undefined;return diagnostics;}
+function buildMemoryNumericFromNode(name,node,unit){const histogram=new tr.v.Histogram(name,unit,BOUNDARIES_FOR_UNIT_MAP.get(unit));node.values.forEach(v=>histogram.addSample(v.total,buildSampleDiagnostics(v,node)));return histogram;}
+tr.metrics.MetricRegistry.register(memoryMetric,{supportsRangeOfInterest:true});return{memoryMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,1e2);function nativeCodeResidentMemoryMetric(histograms,model){const histogram=new tr.v.Histogram('NativeCodeResidentMemory',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);for(const slice of model.getDescendantEvents()){if(slice.category==='disabled-by-default-memory-infra'&&slice.title==='ReportGlobalNativeCodeResidentMemoryKb'&&slice.args.NativeCodeResidentMemory){histogram.addSample(slice.args.NativeCodeResidentMemory);}}
+histograms.addHistogram(histogram);}
+tr.metrics.MetricRegistry.register(nativeCodeResidentMemoryMetric);return{nativeCodeResidentMemoryMetric,};});'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const EventFinderUtils=tr.e.chrome.EventFinderUtils;const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:false,min:false,std:false,sum:false,};function addSamplesToHistogram(pairInfo,breakdownTree,histogram,histograms,diagnostics){histogram.addSample(pairInfo.end-pairInfo.start,diagnostics);if(!breakdownTree){return;}
+for(const[category,breakdown]of Object.entries(breakdownTree)){const relatedName=`${histogram.name}:${category}`;if(!histograms.getHistogramNamed(relatedName)){const relatedHist=histograms.createHistogram(relatedName,histogram.unit,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,summaryOptions:{count:false,max:false,min:false,sum:false,},});}
+const relatedHist=histograms.getHistogramNamed(relatedName);let relatedNames=histogram.diagnostics.get('breakdown');if(!relatedNames){relatedNames=new tr.v.d.RelatedNameMap();histogram.diagnostics.set('breakdown',relatedNames);}
+relatedNames.set(category,relatedName);relatedHist.addSample(breakdown.total,{breakdown:tr.v.d.Breakdown.fromEntries(Object.entries(breakdown.events)),});}}
+function splitOneRangeIntoPerSecondRanges(startTime,endTime){const results=[];for(let i=0;startTime+(i+1)*1000<=endTime;i+=1){const start=i*1000;const end=(i+1)*1000;results.push({start,end,});}
+return results;}
+function getNavigationInfos(model){const navigationInfos=[];const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];if(rendererHelper.mainThread===undefined)continue;navigationInfos.push({navigationStart:expectation.navigationStart,rendererHelper,url:expectation.url});}
+navigationInfos.forEach((navInfo,i)=>{if(i===navigationInfos.length-1){navInfo.navigationEndTime=model.bounds.max;}else{navInfo.navigationEndTime=navigationInfos[i+1].navigationStart.start;}});return navigationInfos;}
+function getWallTimeBreakdownTree(rendererHelper,start,end){const startEndRange=tr.b.math.Range.fromExplicitRange(start,end);const networkEvents=EventFinderUtils.getNetworkEventsInRange(rendererHelper.process,startEndRange);const breakdownTree=tr.metrics.sh.generateWallClockTimeBreakdownTree(rendererHelper.mainThread,networkEvents,startEndRange);return breakdownTree;}
+function getCpuTimeBreakdownTree(rendererHelper,start,end){const startEndRange=tr.b.math.Range.fromExplicitRange(start,end);const breakdownTree=tr.metrics.sh.generateCpuTimeBreakdownTree(rendererHelper.mainThread,startEndRange);return breakdownTree;}
+function persecondMetric(histograms,model){const navigationInfos=getNavigationInfos(model);if(navigationInfos.length===0){return;}
+navigationInfos.forEach(navInfo=>{const navigationStart=navInfo.navigationStart.start;const navigationEnd=navInfo.navigationEndTime;const startEndPairs=splitOneRangeIntoPerSecondRanges(navigationStart,navigationEnd);const breakdownList=startEndPairs.map(p=>{const wallHistogramName=`wall_${p.start}_to_${p.end}`;const wallHistogramDescription=`Wall-clock time ${p.start} to ${p.end} breakdown`;const cpuHistogramName=`cpu_${p.start}_to_${p.end}`;const cpuHistogramDescription=`CPU time ${p.start} to ${p.end} breakdown`;const pid=navInfo.rendererHelper.pid;const breakdownTree=getWallTimeBreakdownTree(navInfo.rendererHelper,navigationStart+p.start,navigationStart+p.end);const cpuBreakdownTree=getCpuTimeBreakdownTree(navInfo.rendererHelper,navigationStart+p.start,navigationStart+p.end);const diagnostics={'Navigation infos':new tr.v.d.GenericSet([{url:navInfo.url,pid:navInfo.rendererHelper.pid,navStart:navigationStart,frameIdRef:navInfo.navigationStart.args.frame}]),'breakdown':tr.metrics.sh.createBreakdownDiagnostic(breakdownTree),};return Object.assign(p,{breakdownTree,cpuBreakdownTree,wallHistogramName,wallHistogramDescription,cpuHistogramName,cpuHistogramDescription,diagnostics,});});breakdownList.forEach(p=>{if(!histograms.getHistogramNamed(p.wallHistogramName)){histograms.createHistogram(p.wallHistogramName,timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:p.wallHistogramDescription,summaryOptions:SUMMARY_OPTIONS,});}
+const wallHistogram=histograms.getHistogramNamed(p.wallHistogramName);addSamplesToHistogram(p,p.breakdownTree,wallHistogram,histograms,p.diagnostics);if(!histograms.getHistogramNamed(p.cpuHistogramName)){histograms.createHistogram(p.cpuHistogramName,timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:p.cpuHistogramDescription,summaryOptions:SUMMARY_OPTIONS,});}
+const cpuHistogram=histograms.getHistogramNamed(p.cpuHistogramName);addSamplesToHistogram(p,p.cpuBreakdownTree,cpuHistogram,histograms,p.diagnostics);});});}
+tr.metrics.MetricRegistry.register(persecondMetric);return{persecondMetric,splitOneRangeIntoPerSecondRanges};});'use strict';tr.exportTo('tr.metrics.sh',function(){const CHROME_POWER_GRACE_PERIOD_MS=1;function createEmptyHistogram_(interval,histograms){if(interval.perSecond){return{perSecond:true,energy:histograms.createHistogram(`${interval.name}:power`,tr.b.Unit.byName.powerInWatts_smallerIsBetter,[],{description:`Energy consumption rate for ${interval.description}`,summaryOptions:{avg:true,count:false,max:true,min:true,std:false,sum:false,},}),};}
+return{perSecond:false,energy:histograms.createHistogram(`${interval.name}:energy`,tr.b.Unit.byName.energyInJoules_smallerIsBetter,[],{description:`Energy consumed in ${interval.description}`,summaryOptions:{avg:false,count:false,max:true,min:true,std:false,sum:true,},}),};}
+function createHistograms_(data,interval,histograms){if(data.histograms[interval.name]===undefined){data.histograms[interval.name]=createEmptyHistogram_(interval,histograms);}
+if(data.histograms[interval.name].perSecond){for(const sample of data.model.device.powerSeries.getSamplesWithinRange(interval.bounds.min,interval.bounds.max)){data.histograms[interval.name].energy.addSample(sample.powerInW);}}else{const energyInJ=data.model.device.powerSeries.getEnergyConsumedInJ(interval.bounds.min,interval.bounds.max);data.histograms[interval.name].energy.addSample(energyInJ);}}
+function getNavigationTTIIntervals_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const intervals=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+if(expectation.timeToInteractive!==undefined){intervals.push(tr.b.math.Range.fromExplicitRange(expectation.navigationStart.start,expectation.timeToInteractive));}}
+return intervals.sort((x,y)=>x.min-y.min);}
+function*computeTimeIntervals_(model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const powerSeries=model.device.powerSeries;if(powerSeries===undefined||powerSeries.samples.length===0){return;}
+yield{bounds:model.bounds,name:'story',description:'user story',perSecond:true};const chromeBounds=computeChromeBounds_(model);if(chromeBounds.isEmpty)return;const powerSeriesBoundsWithGracePeriod=tr.b.math.Range.fromExplicitRange(powerSeries.bounds.min-CHROME_POWER_GRACE_PERIOD_MS,powerSeries.bounds.max+CHROME_POWER_GRACE_PERIOD_MS);if(!powerSeriesBoundsWithGracePeriod.containsRangeExclusive(chromeBounds)){return;}
+for(const interval of getRailStageIntervals_(model)){yield{bounds:interval.bounds.findIntersection(chromeBounds),name:interval.name,description:interval.description,perSecond:interval.perSecond};}
+for(const interval of getLoadingIntervals_(model,chromeBounds)){yield{bounds:interval.bounds.findIntersection(chromeBounds),name:interval.name,description:interval.description,perSecond:interval.perSecond};}}
+function*getRailStageIntervals_(model){for(const exp of model.userModel.expectations){const histogramName=exp.title.toLowerCase().replace(' ','_');const energyHist=undefined;if(histogramName.includes('response')){yield{bounds:tr.b.math.Range.fromExplicitRange(exp.start,exp.end),name:histogramName,description:'RAIL stage '+histogramName,perSecond:false};}else if(histogramName.includes('animation')||histogramName.includes('idle')){yield{bounds:tr.b.math.Range.fromExplicitRange(exp.start,exp.end),name:histogramName,description:'RAIL stage '+histogramName,perSecond:true};}}}
+function*getLoadingIntervals_(model,chromeBounds){const ttiIntervals=getNavigationTTIIntervals_(model);for(const ttiInterval of ttiIntervals){yield{bounds:ttiInterval,name:'load',description:'page loads',perSecond:false};}}
+function computeChromeBounds_(model){const chromeBounds=new tr.b.math.Range();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(chromeHelper===undefined)return chromeBounds;for(const helper of chromeHelper.browserHelpers){if(helper.mainThread){chromeBounds.addRange(helper.mainThread.bounds);}}
+for(const pid in chromeHelper.rendererHelpers){if(chromeHelper.rendererHelpers[pid].mainThread){chromeBounds.addRange(chromeHelper.rendererHelpers[pid].mainThread.bounds);}}
+return chromeBounds;}
+function powerMetric(histograms,model){const data={model,histograms:{}};for(const interval of computeTimeIntervals_(model)){createHistograms_(data,interval,histograms);}}
+tr.metrics.MetricRegistry.register(powerMetric);return{powerMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function computeAnimationThroughput(animationExpectation){if(animationExpectation.frameEvents===undefined||animationExpectation.frameEvents.length===0){throw new Error('Animation missing frameEvents '+
+animationExpectation.stableId);}
+const durationInS=tr.b.convertUnit(animationExpectation.duration,tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);return animationExpectation.frameEvents.length/durationInS;}
+function computeAnimationframeTimeDiscrepancy(animationExpectation){if(animationExpectation.frameEvents===undefined||animationExpectation.frameEvents.length===0){throw new Error('Animation missing frameEvents '+
+animationExpectation.stableId);}
+let frameTimestamps=animationExpectation.frameEvents;frameTimestamps=frameTimestamps.toArray().map(function(event){return event.start;});const absolute=true;return tr.b.math.Statistics.timestampsDiscrepancy(frameTimestamps,absolute);}
+function responsivenessMetric(histograms,model,opt_options){const responseNumeric=new tr.v.Histogram('response latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tr.v.HistogramBinBoundaries.createLinear(100,1e3,50));const throughputNumeric=new tr.v.Histogram('animation throughput',tr.b.Unit.byName.unitlessNumber_biggerIsBetter,tr.v.HistogramBinBoundaries.createLinear(10,60,10));const frameTimeDiscrepancyNumeric=new tr.v.Histogram('animation frameTimeDiscrepancy',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tr.v.HistogramBinBoundaries.createLinear(0,1e3,50).addExponentialBins(1e4,10));const latencyNumeric=new tr.v.Histogram('animation latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tr.v.HistogramBinBoundaries.createLinear(0,300,60));model.userModel.expectations.forEach(function(ue){if(opt_options&&opt_options.rangeOfInterest&&!opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){return;}
+const sampleDiagnosticMap=tr.v.d.DiagnosticMap.fromObject({relatedEvents:new tr.v.d.RelatedEventSet([ue])});if(ue instanceof tr.model.um.IdleExpectation){return;}else if(ue instanceof tr.model.um.StartupExpectation){return;}else if(ue instanceof tr.model.um.LoadExpectation){}else if(ue instanceof tr.model.um.ResponseExpectation){responseNumeric.addSample(ue.duration,sampleDiagnosticMap);}else if(ue instanceof tr.model.um.AnimationExpectation){if(ue.frameEvents===undefined||ue.frameEvents.length===0){return;}
+const throughput=computeAnimationThroughput(ue);if(throughput===undefined){throw new Error('Missing throughput for '+
+ue.stableId);}
+throughputNumeric.addSample(throughput,sampleDiagnosticMap);const frameTimeDiscrepancy=computeAnimationframeTimeDiscrepancy(ue);if(frameTimeDiscrepancy===undefined){throw new Error('Missing frameTimeDiscrepancy for '+
+ue.stableId);}
+frameTimeDiscrepancyNumeric.addSample(frameTimeDiscrepancy,sampleDiagnosticMap);ue.associatedEvents.forEach(function(event){if(!(event instanceof tr.e.cc.InputLatencyAsyncSlice)){return;}
+latencyNumeric.addSample(event.duration,sampleDiagnosticMap);});}else{throw new Error('Unrecognized stage for '+ue.stableId);}});[responseNumeric,throughputNumeric,frameTimeDiscrepancyNumeric,latencyNumeric].forEach(function(numeric){numeric.customizeSummaryOptions({avg:true,max:true,min:true,std:true});});histograms.addHistogram(responseNumeric);histograms.addHistogram(throughputNumeric);histograms.addHistogram(frameTimeDiscrepancyNumeric);histograms.addHistogram(latencyNumeric);}
+tr.metrics.MetricRegistry.register(responsivenessMetric,{supportsRangeOfInterest:true,requiredCategories:['rail'],});return{responsivenessMetric,};});var JpegImage=(function jpegImage(){"use strict";var dctZigZag=new Int32Array([0,1,8,16,9,2,3,10,17,24,32,25,18,11,4,5,12,19,26,33,40,48,41,34,27,20,13,6,7,14,21,28,35,42,49,56,57,50,43,36,29,22,15,23,30,37,44,51,58,59,52,45,38,31,39,46,53,60,61,54,47,55,62,63]);var dctCos1=4017
+var dctSin1=799
+var dctCos3=3406
+var dctSin3=2276
+var dctCos6=1567
+var dctSin6=3784
+var dctSqrt2=5793
+var dctSqrt1d2=2896
+function constructor(){}
+function buildHuffmanTable(codeLengths,values){var k=0,code=[],i,j,length=16;while(length>0&&!codeLengths[length-1])
+length--;code.push({children:[],index:0});var p=code[0],q;for(i=0;i<length;i++){for(j=0;j<codeLengths[i];j++){p=code.pop();p.children[p.index]=values[k];while(p.index>0){p=code.pop();}
+p.index++;code.push(p);while(code.length<=i){code.push(q={children:[],index:0});p.children[p.index]=q.children;p=q;}
+k++;}
+if(i+1<length){code.push(q={children:[],index:0});p.children[p.index]=q.children;p=q;}}
+return code[0].children;}
+function decodeScan(data,offset,frame,components,resetInterval,spectralStart,spectralEnd,successivePrev,successive){var precision=frame.precision;var samplesPerLine=frame.samplesPerLine;var scanLines=frame.scanLines;var mcusPerLine=frame.mcusPerLine;var progressive=frame.progressive;var maxH=frame.maxH,maxV=frame.maxV;var startOffset=offset,bitsData=0,bitsCount=0;function readBit(){if(bitsCount>0){bitsCount--;return(bitsData>>bitsCount)&1;}
+bitsData=data[offset++];if(bitsData==0xFF){var nextByte=data[offset++];if(nextByte){throw new Error("unexpected marker: "+((bitsData<<8)|nextByte).toString(16));}}
+bitsCount=7;return bitsData>>>7;}
+function decodeHuffman(tree){var node=tree,bit;while((bit=readBit())!==null){node=node[bit];if(typeof node==='number')
+return node;if(typeof node!=='object')
+throw new Error("invalid huffman sequence");}
+return null;}
+function receive(length){var n=0;while(length>0){var bit=readBit();if(bit===null)return;n=(n<<1)|bit;length--;}
+return n;}
+function receiveAndExtend(length){var n=receive(length);if(n>=1<<(length-1))
+return n;return n+(-1<<length)+1;}
+function decodeBaseline(component,zz){var t=decodeHuffman(component.huffmanTableDC);var diff=t===0?0:receiveAndExtend(t);zz[0]=(component.pred+=diff);var k=1;while(k<64){var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15)
+break;k+=16;continue;}
+k+=r;var z=dctZigZag[k];zz[z]=receiveAndExtend(s);k++;}}
+function decodeDCFirst(component,zz){var t=decodeHuffman(component.huffmanTableDC);var diff=t===0?0:(receiveAndExtend(t)<<successive);zz[0]=(component.pred+=diff);}
+function decodeDCSuccessive(component,zz){zz[0]|=readBit()<<successive;}
+var eobrun=0;function decodeACFirst(component,zz){if(eobrun>0){eobrun--;return;}
+var k=spectralStart,e=spectralEnd;while(k<=e){var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15){eobrun=receive(r)+(1<<r)-1;break;}
+k+=16;continue;}
+k+=r;var z=dctZigZag[k];zz[z]=receiveAndExtend(s)*(1<<successive);k++;}}
+var successiveACState=0,successiveACNextValue;function decodeACSuccessive(component,zz){var k=spectralStart,e=spectralEnd,r=0;while(k<=e){var z=dctZigZag[k];var direction=zz[z]<0?-1:1;switch(successiveACState){case 0:var rs=decodeHuffman(component.huffmanTableAC);var s=rs&15,r=rs>>4;if(s===0){if(r<15){eobrun=receive(r)+(1<<r);successiveACState=4;}else{r=16;successiveACState=1;}}else{if(s!==1)
+throw new Error("invalid ACn encoding");successiveACNextValue=receiveAndExtend(s);successiveACState=r?2:3;}
+continue;case 1:case 2:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;else{r--;if(r===0)
+successiveACState=successiveACState==2?3:0;}
+break;case 3:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;else{zz[z]=successiveACNextValue<<successive;successiveACState=0;}
+break;case 4:if(zz[z])
+zz[z]+=(readBit()<<successive)*direction;break;}
+k++;}
+if(successiveACState===4){eobrun--;if(eobrun===0)
+successiveACState=0;}}
+function decodeMcu(component,decode,mcu,row,col){var mcuRow=(mcu/mcusPerLine)|0;var mcuCol=mcu%mcusPerLine;var blockRow=mcuRow*component.v+row;var blockCol=mcuCol*component.h+col;decode(component,component.blocks[blockRow][blockCol]);}
+function decodeBlock(component,decode,mcu){var blockRow=(mcu/component.blocksPerLine)|0;var blockCol=mcu%component.blocksPerLine;decode(component,component.blocks[blockRow][blockCol]);}
+var componentsLength=components.length;var component,i,j,k,n;var decodeFn;if(progressive){if(spectralStart===0)
+decodeFn=successivePrev===0?decodeDCFirst:decodeDCSuccessive;else
+decodeFn=successivePrev===0?decodeACFirst:decodeACSuccessive;}else{decodeFn=decodeBaseline;}
+var mcu=0,marker;var mcuExpected;if(componentsLength==1){mcuExpected=components[0].blocksPerLine*components[0].blocksPerColumn;}else{mcuExpected=mcusPerLine*frame.mcusPerColumn;}
+if(!resetInterval)resetInterval=mcuExpected;var h,v;while(mcu<mcuExpected){for(i=0;i<componentsLength;i++)
+components[i].pred=0;eobrun=0;if(componentsLength==1){component=components[0];for(n=0;n<resetInterval;n++){decodeBlock(component,decodeFn,mcu);mcu++;}}else{for(n=0;n<resetInterval;n++){for(i=0;i<componentsLength;i++){component=components[i];h=component.h;v=component.v;for(j=0;j<v;j++){for(k=0;k<h;k++){decodeMcu(component,decodeFn,mcu,j,k);}}}
+mcu++;if(mcu===mcuExpected)break;}}
+bitsCount=0;marker=(data[offset]<<8)|data[offset+1];if(marker<0xFF00){throw new Error("marker was not found");}
+if(marker>=0xFFD0&&marker<=0xFFD7){offset+=2;}
+else
+break;}
+return offset-startOffset;}
+function buildComponentData(frame,component){var lines=[];var blocksPerLine=component.blocksPerLine;var blocksPerColumn=component.blocksPerColumn;var samplesPerLine=blocksPerLine<<3;var R=new Int32Array(64),r=new Uint8Array(64);function quantizeAndInverse(zz,dataOut,dataIn){var qt=component.quantizationTable;var v0,v1,v2,v3,v4,v5,v6,v7,t;var p=dataIn;var i;for(i=0;i<64;i++)
+p[i]=zz[i]*qt[i];for(i=0;i<8;++i){var row=8*i;if(p[1+row]==0&&p[2+row]==0&&p[3+row]==0&&p[4+row]==0&&p[5+row]==0&&p[6+row]==0&&p[7+row]==0){t=(dctSqrt2*p[0+row]+512)>>10;p[0+row]=t;p[1+row]=t;p[2+row]=t;p[3+row]=t;p[4+row]=t;p[5+row]=t;p[6+row]=t;p[7+row]=t;continue;}
+v0=(dctSqrt2*p[0+row]+128)>>8;v1=(dctSqrt2*p[4+row]+128)>>8;v2=p[2+row];v3=p[6+row];v4=(dctSqrt1d2*(p[1+row]-p[7+row])+128)>>8;v7=(dctSqrt1d2*(p[1+row]+p[7+row])+128)>>8;v5=p[3+row]<<4;v6=p[5+row]<<4;t=(v0-v1+1)>>1;v0=(v0+v1+1)>>1;v1=t;t=(v2*dctSin6+v3*dctCos6+128)>>8;v2=(v2*dctCos6-v3*dctSin6+128)>>8;v3=t;t=(v4-v6+1)>>1;v4=(v4+v6+1)>>1;v6=t;t=(v7+v5+1)>>1;v5=(v7-v5+1)>>1;v7=t;t=(v0-v3+1)>>1;v0=(v0+v3+1)>>1;v3=t;t=(v1-v2+1)>>1;v1=(v1+v2+1)>>1;v2=t;t=(v4*dctSin3+v7*dctCos3+2048)>>12;v4=(v4*dctCos3-v7*dctSin3+2048)>>12;v7=t;t=(v5*dctSin1+v6*dctCos1+2048)>>12;v5=(v5*dctCos1-v6*dctSin1+2048)>>12;v6=t;p[0+row]=v0+v7;p[7+row]=v0-v7;p[1+row]=v1+v6;p[6+row]=v1-v6;p[2+row]=v2+v5;p[5+row]=v2-v5;p[3+row]=v3+v4;p[4+row]=v3-v4;}
+for(i=0;i<8;++i){var col=i;if(p[1*8+col]==0&&p[2*8+col]==0&&p[3*8+col]==0&&p[4*8+col]==0&&p[5*8+col]==0&&p[6*8+col]==0&&p[7*8+col]==0){t=(dctSqrt2*dataIn[i+0]+8192)>>14;p[0*8+col]=t;p[1*8+col]=t;p[2*8+col]=t;p[3*8+col]=t;p[4*8+col]=t;p[5*8+col]=t;p[6*8+col]=t;p[7*8+col]=t;continue;}
+v0=(dctSqrt2*p[0*8+col]+2048)>>12;v1=(dctSqrt2*p[4*8+col]+2048)>>12;v2=p[2*8+col];v3=p[6*8+col];v4=(dctSqrt1d2*(p[1*8+col]-p[7*8+col])+2048)>>12;v7=(dctSqrt1d2*(p[1*8+col]+p[7*8+col])+2048)>>12;v5=p[3*8+col];v6=p[5*8+col];t=(v0-v1+1)>>1;v0=(v0+v1+1)>>1;v1=t;t=(v2*dctSin6+v3*dctCos6+2048)>>12;v2=(v2*dctCos6-v3*dctSin6+2048)>>12;v3=t;t=(v4-v6+1)>>1;v4=(v4+v6+1)>>1;v6=t;t=(v7+v5+1)>>1;v5=(v7-v5+1)>>1;v7=t;t=(v0-v3+1)>>1;v0=(v0+v3+1)>>1;v3=t;t=(v1-v2+1)>>1;v1=(v1+v2+1)>>1;v2=t;t=(v4*dctSin3+v7*dctCos3+2048)>>12;v4=(v4*dctCos3-v7*dctSin3+2048)>>12;v7=t;t=(v5*dctSin1+v6*dctCos1+2048)>>12;v5=(v5*dctCos1-v6*dctSin1+2048)>>12;v6=t;p[0*8+col]=v0+v7;p[7*8+col]=v0-v7;p[1*8+col]=v1+v6;p[6*8+col]=v1-v6;p[2*8+col]=v2+v5;p[5*8+col]=v2-v5;p[3*8+col]=v3+v4;p[4*8+col]=v3-v4;}
+for(i=0;i<64;++i){var sample=128+((p[i]+8)>>4);dataOut[i]=sample<0?0:sample>0xFF?0xFF:sample;}}
+var i,j;for(var blockRow=0;blockRow<blocksPerColumn;blockRow++){var scanLine=blockRow<<3;for(i=0;i<8;i++)
+lines.push(new Uint8Array(samplesPerLine));for(var blockCol=0;blockCol<blocksPerLine;blockCol++){quantizeAndInverse(component.blocks[blockRow][blockCol],r,R);var offset=0,sample=blockCol<<3;for(j=0;j<8;j++){var line=lines[scanLine+j];for(i=0;i<8;i++)
+line[sample+i]=r[offset++];}}}
+return lines;}
+function clampTo8bit(a){return a<0?0:a>255?255:a;}
+constructor.prototype={load:function load(path){var xhr=new XMLHttpRequest();xhr.open("GET",path,true);xhr.responseType="arraybuffer";xhr.onload=(function(){var data=new Uint8Array(xhr.response||xhr.mozResponseArrayBuffer);this.parse(data);if(this.onload)
+this.onload();}).bind(this);xhr.send(null);},parse:function parse(data){var offset=0,length=data.length;function readUint16(){var value=(data[offset]<<8)|data[offset+1];offset+=2;return value;}
+function readDataBlock(){var length=readUint16();var array=data.subarray(offset,offset+length-2);offset+=array.length;return array;}
+function prepareComponents(frame){var maxH=0,maxV=0;var component,componentId;for(componentId in frame.components){if(frame.components.hasOwnProperty(componentId)){component=frame.components[componentId];if(maxH<component.h)maxH=component.h;if(maxV<component.v)maxV=component.v;}}
+var mcusPerLine=Math.ceil(frame.samplesPerLine/8/maxH);var mcusPerColumn=Math.ceil(frame.scanLines/8/maxV);for(componentId in frame.components){if(frame.components.hasOwnProperty(componentId)){component=frame.components[componentId];var blocksPerLine=Math.ceil(Math.ceil(frame.samplesPerLine/8)*component.h/maxH);var blocksPerColumn=Math.ceil(Math.ceil(frame.scanLines/8)*component.v/maxV);var blocksPerLineForMcu=mcusPerLine*component.h;var blocksPerColumnForMcu=mcusPerColumn*component.v;var blocks=[];for(var i=0;i<blocksPerColumnForMcu;i++){var row=[];for(var j=0;j<blocksPerLineForMcu;j++)
+row.push(new Int32Array(64));blocks.push(row);}
+component.blocksPerLine=blocksPerLine;component.blocksPerColumn=blocksPerColumn;component.blocks=blocks;}}
+frame.maxH=maxH;frame.maxV=maxV;frame.mcusPerLine=mcusPerLine;frame.mcusPerColumn=mcusPerColumn;}
+var jfif=null;var adobe=null;var pixels=null;var frame,resetInterval;var quantizationTables=[],frames=[];var huffmanTablesAC=[],huffmanTablesDC=[];var fileMarker=readUint16();if(fileMarker!=0xFFD8){throw new Error("SOI not found");}
+fileMarker=readUint16();while(fileMarker!=0xFFD9){var i,j,l;switch(fileMarker){case 0xFF00:break;case 0xFFE0:case 0xFFE1:case 0xFFE2:case 0xFFE3:case 0xFFE4:case 0xFFE5:case 0xFFE6:case 0xFFE7:case 0xFFE8:case 0xFFE9:case 0xFFEA:case 0xFFEB:case 0xFFEC:case 0xFFED:case 0xFFEE:case 0xFFEF:case 0xFFFE:var appData=readDataBlock();if(fileMarker===0xFFE0){if(appData[0]===0x4A&&appData[1]===0x46&&appData[2]===0x49&&appData[3]===0x46&&appData[4]===0){jfif={version:{major:appData[5],minor:appData[6]},densityUnits:appData[7],xDensity:(appData[8]<<8)|appData[9],yDensity:(appData[10]<<8)|appData[11],thumbWidth:appData[12],thumbHeight:appData[13],thumbData:appData.subarray(14,14+3*appData[12]*appData[13])};}}
+if(fileMarker===0xFFEE){if(appData[0]===0x41&&appData[1]===0x64&&appData[2]===0x6F&&appData[3]===0x62&&appData[4]===0x65&&appData[5]===0){adobe={version:appData[6],flags0:(appData[7]<<8)|appData[8],flags1:(appData[9]<<8)|appData[10],transformCode:appData[11]};}}
+break;case 0xFFDB:var quantizationTablesLength=readUint16();var quantizationTablesEnd=quantizationTablesLength+offset-2;while(offset<quantizationTablesEnd){var quantizationTableSpec=data[offset++];var tableData=new Int32Array(64);if((quantizationTableSpec>>4)===0){for(j=0;j<64;j++){var z=dctZigZag[j];tableData[z]=data[offset++];}}else if((quantizationTableSpec>>4)===1){for(j=0;j<64;j++){var z=dctZigZag[j];tableData[z]=readUint16();}}else
+throw new Error("DQT: invalid table spec");quantizationTables[quantizationTableSpec&15]=tableData;}
+break;case 0xFFC0:case 0xFFC1:case 0xFFC2:readUint16();frame={};frame.extended=(fileMarker===0xFFC1);frame.progressive=(fileMarker===0xFFC2);frame.precision=data[offset++];frame.scanLines=readUint16();frame.samplesPerLine=readUint16();frame.components={};frame.componentsOrder=[];var componentsCount=data[offset++],componentId;var maxH=0,maxV=0;for(i=0;i<componentsCount;i++){componentId=data[offset];var h=data[offset+1]>>4;var v=data[offset+1]&15;var qId=data[offset+2];frame.componentsOrder.push(componentId);frame.components[componentId]={h:h,v:v,quantizationIdx:qId};offset+=3;}
+prepareComponents(frame);frames.push(frame);break;case 0xFFC4:var huffmanLength=readUint16();for(i=2;i<huffmanLength;){var huffmanTableSpec=data[offset++];var codeLengths=new Uint8Array(16);var codeLengthSum=0;for(j=0;j<16;j++,offset++)
+codeLengthSum+=(codeLengths[j]=data[offset]);var huffmanValues=new Uint8Array(codeLengthSum);for(j=0;j<codeLengthSum;j++,offset++)
+huffmanValues[j]=data[offset];i+=17+codeLengthSum;((huffmanTableSpec>>4)===0?huffmanTablesDC:huffmanTablesAC)[huffmanTableSpec&15]=buildHuffmanTable(codeLengths,huffmanValues);}
+break;case 0xFFDD:readUint16();resetInterval=readUint16();break;case 0xFFDA:var scanLength=readUint16();var selectorsCount=data[offset++];var components=[],component;for(i=0;i<selectorsCount;i++){component=frame.components[data[offset++]];var tableSpec=data[offset++];component.huffmanTableDC=huffmanTablesDC[tableSpec>>4];component.huffmanTableAC=huffmanTablesAC[tableSpec&15];components.push(component);}
+var spectralStart=data[offset++];var spectralEnd=data[offset++];var successiveApproximation=data[offset++];var processed=decodeScan(data,offset,frame,components,resetInterval,spectralStart,spectralEnd,successiveApproximation>>4,successiveApproximation&15);offset+=processed;break;case 0xFFFF:if(data[offset]!==0xFF){offset--;}
+break;default:if(data[offset-3]==0xFF&&data[offset-2]>=0xC0&&data[offset-2]<=0xFE){offset-=3;break;}
+throw new Error("unknown JPEG marker "+fileMarker.toString(16));}
+fileMarker=readUint16();}
+if(frames.length!=1)
+throw new Error("only single frame JPEGs supported");for(var i=0;i<frames.length;i++){var cp=frames[i].components;for(var j in cp){cp[j].quantizationTable=quantizationTables[cp[j].quantizationIdx];delete cp[j].quantizationIdx;}}
+this.width=frame.samplesPerLine;this.height=frame.scanLines;this.jfif=jfif;this.adobe=adobe;this.components=[];for(var i=0;i<frame.componentsOrder.length;i++){var component=frame.components[frame.componentsOrder[i]];this.components.push({lines:buildComponentData(frame,component),scaleX:component.h/frame.maxH,scaleY:component.v/frame.maxV});}},getData:function getData(width,height){var scaleX=this.width/width,scaleY=this.height/height;var component1,component2,component3,component4;var component1Line,component2Line,component3Line,component4Line;var x,y;var offset=0;var Y,Cb,Cr,K,C,M,Ye,R,G,B;var colorTransform;var dataLength=width*height*this.components.length;var data=new Uint8Array(dataLength);switch(this.components.length){case 1:component1=this.components[0];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];for(x=0;x<width;x++){Y=component1Line[0|(x*component1.scaleX*scaleX)];data[offset++]=Y;}}
+break;case 2:component1=this.components[0];component2=this.components[1];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];for(x=0;x<width;x++){Y=component1Line[0|(x*component1.scaleX*scaleX)];data[offset++]=Y;Y=component2Line[0|(x*component2.scaleX*scaleX)];data[offset++]=Y;}}
+break;case 3:colorTransform=true;if(this.adobe&&this.adobe.transformCode)
+colorTransform=true;else if(typeof this.colorTransform!=='undefined')
+colorTransform=!!this.colorTransform;component1=this.components[0];component2=this.components[1];component3=this.components[2];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];component3Line=component3.lines[0|(y*component3.scaleY*scaleY)];for(x=0;x<width;x++){if(!colorTransform){R=component1Line[0|(x*component1.scaleX*scaleX)];G=component2Line[0|(x*component2.scaleX*scaleX)];B=component3Line[0|(x*component3.scaleX*scaleX)];}else{Y=component1Line[0|(x*component1.scaleX*scaleX)];Cb=component2Line[0|(x*component2.scaleX*scaleX)];Cr=component3Line[0|(x*component3.scaleX*scaleX)];R=clampTo8bit(Y+1.402*(Cr-128));G=clampTo8bit(Y-0.3441363*(Cb-128)-0.71413636*(Cr-128));B=clampTo8bit(Y+1.772*(Cb-128));}
+data[offset++]=R;data[offset++]=G;data[offset++]=B;}}
+break;case 4:if(!this.adobe)
+throw new Error('Unsupported color mode (4 components)');colorTransform=false;if(this.adobe&&this.adobe.transformCode)
+colorTransform=true;else if(typeof this.colorTransform!=='undefined')
+colorTransform=!!this.colorTransform;component1=this.components[0];component2=this.components[1];component3=this.components[2];component4=this.components[3];for(y=0;y<height;y++){component1Line=component1.lines[0|(y*component1.scaleY*scaleY)];component2Line=component2.lines[0|(y*component2.scaleY*scaleY)];component3Line=component3.lines[0|(y*component3.scaleY*scaleY)];component4Line=component4.lines[0|(y*component4.scaleY*scaleY)];for(x=0;x<width;x++){if(!colorTransform){C=component1Line[0|(x*component1.scaleX*scaleX)];M=component2Line[0|(x*component2.scaleX*scaleX)];Ye=component3Line[0|(x*component3.scaleX*scaleX)];K=component4Line[0|(x*component4.scaleX*scaleX)];}else{Y=component1Line[0|(x*component1.scaleX*scaleX)];Cb=component2Line[0|(x*component2.scaleX*scaleX)];Cr=component3Line[0|(x*component3.scaleX*scaleX)];K=component4Line[0|(x*component4.scaleX*scaleX)];C=255-clampTo8bit(Y+1.402*(Cr-128));M=255-clampTo8bit(Y-0.3441363*(Cb-128)-0.71413636*(Cr-128));Ye=255-clampTo8bit(Y+1.772*(Cb-128));}
+data[offset++]=255-C;data[offset++]=255-M;data[offset++]=255-Ye;data[offset++]=255-K;}}
+break;default:throw new Error('Unsupported color mode');}
+return data;},copyToImageData:function copyToImageData(imageData){var width=imageData.width,height=imageData.height;var imageDataArray=imageData.data;var data=this.getData(width,height);var i=0,j=0,x,y;var Y,K,C,M,R,G,B;switch(this.components.length){case 1:for(y=0;y<height;y++){for(x=0;x<width;x++){Y=data[i++];imageDataArray[j++]=Y;imageDataArray[j++]=Y;imageDataArray[j++]=Y;imageDataArray[j++]=255;}}
+break;case 3:for(y=0;y<height;y++){for(x=0;x<width;x++){R=data[i++];G=data[i++];B=data[i++];imageDataArray[j++]=R;imageDataArray[j++]=G;imageDataArray[j++]=B;imageDataArray[j++]=255;}}
+break;case 4:for(y=0;y<height;y++){for(x=0;x<width;x++){C=data[i++];M=data[i++];Y=data[i++];K=data[i++];R=255-clampTo8bit(C*(1-K/255)+K);G=255-clampTo8bit(M*(1-K/255)+K);B=255-clampTo8bit(Y*(1-K/255)+K);imageDataArray[j++]=R;imageDataArray[j++]=G;imageDataArray[j++]=B;imageDataArray[j++]=255;}}
+break;default:throw new Error('Unsupported color mode');}}};return constructor;})();global.jpegDecode=decode;function decode(jpegData,opts){var defaultOpts={useTArray:false,colorTransform:true};if(opts){if(typeof opts==='object'){opts={useTArray:(typeof opts.useTArray==='undefined'?defaultOpts.useTArray:opts.useTArray),colorTransform:(typeof opts.colorTransform==='undefined'?defaultOpts.colorTransform:opts.colorTransform)};}else{opts=defaultOpts;opts.useTArray=true;}}else{opts=defaultOpts;}
+var arr=new Uint8Array(jpegData);var decoder=new JpegImage();decoder.parse(arr);decoder.colorTransform=opts.colorTransform;var image={width:decoder.width,height:decoder.height,data:opts.useTArray?new Uint8Array(decoder.width*decoder.height*4):new Buffer(decoder.width*decoder.height*4)};decoder.copyToImageData(image);return image;}'use strict';tr.exportTo('tr.metrics.sh',function(){const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const SpeedIndex=tr.e.chrome.SpeedIndex;const LOADING_METRIC_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,1e3,20).addLinearBins(3e3,20).addExponentialBins(20e3,20);const SUMMARY_OPTIONS={avg:true,count:false,max:true,min:true,std:true,sum:false,};function addSpeedIndexScreenshotsBasedSample(samples,navigationStart,loadDuration,browserHelper){const screenshotObjects=browserHelper.process.objects.getAllInstancesNamed('Screenshot');if(!screenshotObjects)return;for(let i=0;i<screenshotObjects.length;i++){const snapshots=screenshotObjects[i].snapshots;const timestampedColorHistograms=[];snapshots.map(snapshot=>{if(snapshot.ts>=navigationStart.start&&snapshot.ts<navigationStart.start+loadDuration){timestampedColorHistograms.push({colorHistogram:SpeedIndex.createColorHistogram(getPixelData(snapshot.args)),ts:snapshot.ts});}});samples.push({value:SpeedIndex.calculateSpeedIndex(timestampedColorHistograms)-
+navigationStart.start});}}
+function getPixelData(base64JpegImage){const binaryString=atob(base64JpegImage);const bytes=new DataView(new ArrayBuffer(base64JpegImage.length));tr.b.Base64.DecodeToTypedArray(base64JpegImage,bytes);const rawImageData=jpegDecode(bytes.buffer,{useTArray:true});return rawImageData.data;}
+function collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper){const speedIndexScreenshotsBasedSamples=[];for(const expectation of model.userModel.expectations){if(!(expectation instanceof tr.model.um.LoadExpectation))continue;if(tr.e.chrome.CHROME_INTERNAL_URLS.includes(expectation.url)){continue;}
+const rendererHelper=chromeHelper.rendererHelpers[expectation.renderProcess.pid];addSpeedIndexScreenshotsBasedSample(speedIndexScreenshotsBasedSamples,expectation.navigationStart,expectation.duration,chromeHelper.browserHelper);}
+return speedIndexScreenshotsBasedSamples;}
+function screenshotsBasedSpeedIndexMetric(histograms,model){const speedIndexScreenshotsBasedHistogram=histograms.createHistogram('speedIndexScreenshotsBased',timeDurationInMs_smallerIsBetter,[],{binBoundaries:LOADING_METRIC_BOUNDARIES,description:'The average time at which visible parts of the'+' page are displayed.',summaryOptions:SUMMARY_OPTIONS,});const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const samples=collectSpeedIndexSamplesFromLoadExpectations(model,chromeHelper);for(const sample of samples){speedIndexScreenshotsBasedHistogram.addSample(sample.value);}}
+tr.metrics.MetricRegistry.register(screenshotsBasedSpeedIndexMetric);return{screenshotsBasedSpeedIndexMetric};});'use strict';tr.exportTo('tr.metrics.sh',function(){function webviewStartupMetric(histograms,model){const startupWallHist=new tr.v.Histogram('webview_startup_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupWallHist.description='WebView startup wall time';const startupCPUHist=new tr.v.Histogram('webview_startup_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);startupCPUHist.description='WebView startup CPU time';const loadWallHist=new tr.v.Histogram('webview_url_load_wall_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadWallHist.description='WebView blank URL load wall time';const loadCPUHist=new tr.v.Histogram('webview_url_load_cpu_time',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter);loadCPUHist.description='WebView blank URL load CPU time';for(const slice of model.getDescendantEvents()){if(!(slice instanceof tr.model.ThreadSlice))continue;if(slice.title==='WebViewStartupInterval'){startupWallHist.addSample(slice.duration);startupCPUHist.addSample(slice.cpuDuration);}
+if(slice.title==='WebViewBlankUrlLoadInterval'){loadWallHist.addSample(slice.duration);loadCPUHist.addSample(slice.cpuDuration);}}
+histograms.addHistogram(startupWallHist);histograms.addHistogram(startupCPUHist);histograms.addHistogram(loadWallHist);histograms.addHistogram(loadCPUHist);}
+tr.metrics.MetricRegistry.register(webviewStartupMetric);return{webviewStartupMetric,};});'use strict';tr.exportTo('tr.metrics.tabs',function(){function tabsMetric(histograms,model,opt_options){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);if(!chromeHelper){return;}
+const tabSwitchRequestDelays=[];const TAB_SWITCHING_REQUEST_TITLE='TabSwitchVisibilityRequest';let startTabSwitchVisibilityRequest=Number.MAX_SAFE_INTEGER;for(const helper of chromeHelper.browserHelpers){if(!helper.mainThread)continue;for(const slice of helper.mainThread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_REQUEST_TITLE&&!slice.error){tabSwitchRequestDelays.push(slice.duration);if(slice.start<startTabSwitchVisibilityRequest){startTabSwitchVisibilityRequest=slice.start;}}}}
+histograms.createHistogram('tab_switching_request_delay',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchRequestDelays,{description:'Delay before tab-request is made',summaryOptions:{sum:false}});const tabSwitchLatencies=[];const TAB_SWITCHING_SLICE_TITLE='TabSwitching::Latency';function extractLatencyFromHelpers(helpers,legacy){for(const helper of helpers){if(!helper.mainThread){continue;}
+const thread=helper.mainThread;for(const slice of thread.asyncSliceGroup.slices){if(slice.title===TAB_SWITCHING_SLICE_TITLE&&(legacy||slice.args.latency)&&slice.start>startTabSwitchVisibilityRequest){tabSwitchLatencies.push(legacy?slice.duration:slice.args.latency);}}}}
+extractLatencyFromHelpers(chromeHelper.browserHelpers);extractLatencyFromHelpers(Object.values(chromeHelper.rendererHelpers));if(tabSwitchLatencies.length===0){extractLatencyFromHelpers(chromeHelper.browserHelpers,true);}
+histograms.createHistogram('tab_switching_latency',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,tabSwitchLatencies,{description:'Tab switching time in ms',summaryOptions:{sum:false}});}
+tr.metrics.MetricRegistry.register(tabsMetric,{supportsRangeOfInterest:false,});return{tabsMetric,};});'use strict';tr.exportTo('tr.metrics',function(){const MEMORY_INFRA_TRACING_CATEGORY='disabled-by-default-memory-infra';const TIME_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1e-3,1e5,30);const BYTE_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e9,30);const COUNT_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1e5,30);const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;function addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes){const memoryDumpCount=model.globalMemoryDumps.length;if(memoryDumpCount===0)return;let totalOverhead=0;let nonMemoryInfraThreadOverhead=0;const overheadByProvider={};for(const process of Object.values(model.processes)){for(const thread of Object.values(process.threads)){for(const slice of Object.values(thread.sliceGroup.slices)){if(slice.category!==MEMORY_INFRA_TRACING_CATEGORY)continue;totalOverhead+=slice.duration;if(thread.name!=='MemoryInfra'){nonMemoryInfraThreadOverhead+=slice.duration;}
+if(slice.args&&slice.args['dump_provider.name']){const providerName=slice.args['dump_provider.name'];let durationAndCount=overheadByProvider[providerName];if(durationAndCount===undefined){overheadByProvider[providerName]=durationAndCount={duration:0,count:0};}
+durationAndCount.duration+=slice.duration;durationAndCount.count++;}}}}
+histograms.createHistogram('memory_dump_cpu_overhead',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,totalOverhead/memoryDumpCount,{binBoundaries:TIME_BOUNDARIES,description:'Average CPU overhead on all threads per memory-infra dump',summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('nonmemory_thread_memory_dump_cpu_overhead',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,nonMemoryInfraThreadOverhead/memoryDumpCount,{binBoundaries:TIME_BOUNDARIES,description:'Average CPU overhead on non-memory-infra threads '+'per memory-infra dump',summaryOptions:SUMMARY_OPTIONS,});for(const[providerName,overhead]of Object.entries(overheadByProvider)){histograms.createHistogram(`${providerName}_memory_dump_cpu_overhead`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,overhead.duration/overhead.count,{binBoundaries:TIME_BOUNDARIES,description:`Average CPU overhead of ${providerName} per OnMemoryDump call`,summaryOptions:SUMMARY_OPTIONS,});}
+const memoryInfraEventsSize=categoryNamesToTotalEventSizes.get(MEMORY_INFRA_TRACING_CATEGORY);const memoryInfraTraceBytesValue=new tr.v.Histogram('total_memory_dump_size',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);memoryInfraTraceBytesValue.description='Total trace size of memory-infra dumps in bytes';memoryInfraTraceBytesValue.customizeSummaryOptions(SUMMARY_OPTIONS);memoryInfraTraceBytesValue.addSample(memoryInfraEventsSize);histograms.addHistogram(memoryInfraTraceBytesValue);const traceBytesPerDumpValue=new tr.v.Histogram('memory_dump_size',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);traceBytesPerDumpValue.description='Average trace size of memory-infra dumps in bytes';traceBytesPerDumpValue.customizeSummaryOptions(SUMMARY_OPTIONS);traceBytesPerDumpValue.addSample(memoryInfraEventsSize/memoryDumpCount);histograms.addHistogram(traceBytesPerDumpValue);}
+function tracingMetric(histograms,model){if(!model.stats.hasEventSizesinBytes)return;const eventStats=model.stats.allTraceEventStatsInTimeIntervals;eventStats.sort((a,b)=>a.timeInterval-b.timeInterval);const totalTraceBytes=eventStats.reduce((a,b)=>a+b.totalEventSizeinBytes,0);let maxEventCountPerSec=0;let maxEventBytesPerSec=0;const INTERVALS_PER_SEC=Math.floor(1000/model.stats.TIME_INTERVAL_SIZE_IN_MS);let runningEventNumPerSec=0;let runningEventBytesPerSec=0;let start=0;let end=0;while(end<eventStats.length){runningEventNumPerSec+=eventStats[end].numEvents;runningEventBytesPerSec+=eventStats[end].totalEventSizeinBytes;end++;while((eventStats[end-1].timeInterval-
+eventStats[start].timeInterval)>=INTERVALS_PER_SEC){runningEventNumPerSec-=eventStats[start].numEvents;runningEventBytesPerSec-=eventStats[start].totalEventSizeinBytes;start++;}
+maxEventCountPerSec=Math.max(maxEventCountPerSec,runningEventNumPerSec);maxEventBytesPerSec=Math.max(maxEventBytesPerSec,runningEventBytesPerSec);}
+const stats=model.stats.allTraceEventStats;const categoryNamesToTotalEventSizes=(stats.reduce((map,stat)=>(map.set(stat.category,((map.get(stat.category)||0)+
+stat.totalEventSizeinBytes))),new Map()));const maxCatNameAndBytes=Array.from(categoryNamesToTotalEventSizes.entries()).reduce((a,b)=>((b[1]>=a[1])?b:a));const maxEventBytesPerCategory=maxCatNameAndBytes[1];const categoryWithMaxEventBytes=maxCatNameAndBytes[0];const maxEventCountPerSecValue=new tr.v.Histogram('peak_event_rate',tr.b.Unit.byName.count_smallerIsBetter,COUNT_BOUNDARIES);maxEventCountPerSecValue.description='Max number of events per second';maxEventCountPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);maxEventCountPerSecValue.addSample(maxEventCountPerSec);const maxEventBytesPerSecValue=new tr.v.Histogram('peak_event_size_rate',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);maxEventBytesPerSecValue.description='Max event size in bytes per second';maxEventBytesPerSecValue.customizeSummaryOptions(SUMMARY_OPTIONS);maxEventBytesPerSecValue.addSample(maxEventBytesPerSec);const totalTraceBytesValue=new tr.v.Histogram('trace_size',tr.b.Unit.byName.sizeInBytes_smallerIsBetter,BYTE_BOUNDARIES);totalTraceBytesValue.customizeSummaryOptions(SUMMARY_OPTIONS);totalTraceBytesValue.addSample(totalTraceBytes);const biggestCategory={name:categoryWithMaxEventBytes,size_in_bytes:maxEventBytesPerCategory};totalTraceBytesValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(totalTraceBytesValue);maxEventCountPerSecValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(maxEventCountPerSecValue);maxEventBytesPerSecValue.diagnostics.set('category_with_max_event_size',new tr.v.d.GenericSet([biggestCategory]));histograms.addHistogram(maxEventBytesPerSecValue);addMemoryInfraHistograms(histograms,model,categoryNamesToTotalEventSizes);}
+tr.metrics.MetricRegistry.register(tracingMetric);return{tracingMetric,MEMORY_INFRA_TRACING_CATEGORY,};});'use strict';tr.exportTo('tr.metrics',function(){function parseBuckets_(event,processName){const len=tr.b.Base64.getDecodedBufferLength(event.args.buckets);const buffer=new ArrayBuffer(len);const dataView=new DataView(buffer);tr.b.Base64.DecodeToTypedArray(event.args.buckets,dataView);const decoded=new Uint32Array(buffer);const sum=decoded[1]+decoded[2]*0x100000000;const bins=[];let position=4;while(position<=decoded.length-4){const min=decoded[position++];const max=decoded[position++]+decoded[position++]*0x100000000;const count=decoded[position++];const processes=new tr.v.d.Breakdown();processes.set(processName,count);const events=new tr.v.d.RelatedEventSet([event]);bins.push({min,max,count,processes,events});}
+return{sum,bins};}
+function mergeBins_(x,y){x.sum+=y.sum;const allBins=[...x.bins,...y.bins];allBins.sort((a,b)=>a.min-b.min);x.bins=[];let last=undefined;for(const bin of allBins){if(last!==undefined&&bin.min===last.min){if(last.max!==bin.max)throw new Error('Incompatible bins');if(bin.count===0)continue;last.count+=bin.count;for(const event of bin.events){last.events.add(event);}
+last.processes.addDiagnostic(bin.processes);}else{if(last!==undefined&&bin.min<last.max){throw new Error('Incompatible bins');}
+x.bins.push(bin);last=bin;}}}
+function subtractBins_(x,y){x.sum-=y.sum;let p1=0;let p2=0;while(p2<y.bins.length){while(p1<x.bins.length&&x.bins[p1].min!==y.bins[p2].min){p1++;}
+if(p1===x.bins.length)throw new Error('Cannot subtract');if(x.bins[p1].max!==y.bins[p2].max){throw new Error('Incompatible bins');}
+if(x.bins[p1].count<y.bins[p2].count){throw new Error('Cannot subtract');}
+x.bins[p1].count-=y.bins[p2].count;for(const event of y.bins[p2].events){x.bins[p1].events.add(event);}
+const processName=tr.b.getOnlyElement(x.bins[p1].processes)[0];x.bins[p1].processes.set(processName,x.bins[p1].count);p2++;}}
+function getHistogramUnit_(name){return tr.b.Unit.byName.unitlessNumber_smallerIsBetter;}
+function getHistogramBoundaries_(name){if(name.startsWith('Event.Latency.Scroll')){return tr.v.HistogramBinBoundaries.createExponential(1e3,1e5,50);}
+if(name.startsWith('Graphics.Smoothness.Throughput')){return tr.v.HistogramBinBoundaries.createLinear(0,100,101);}
+if(name.startsWith('Memory.Memory.GPU.PeakMemoryUsage')){return tr.v.HistogramBinBoundaries.createLinear(0,1e6,100);}
+return tr.v.HistogramBinBoundaries.createExponential(1e-3,1e3,50);}
+function umaMetric(histograms,model){const histogramValues=new Map();const nameCounts=new Map();for(const process of model.getAllProcesses()){const histogramEvents=new Map();for(const event of process.instantEvents){if(event.title!=='UMAHistogramSamples')continue;const name=event.args.name;const events=histogramEvents.get(name)||[];if(!histogramEvents.has(name))histogramEvents.set(name,events);events.push(event);}
+let processName=tr.e.chrome.chrome_processes.canonicalizeProcessName(process.name);nameCounts.set(processName,(nameCounts.get(processName)||0)+1);processName=`${processName}_${nameCounts.get(processName)}`;for(const[name,events]of histogramEvents){const values=histogramValues.get(name)||{sum:0,bins:[]};if(!histogramValues.has(name))histogramValues.set(name,values);const endValues=parseBuckets_(events[events.length-1],processName);if(events.length===1){mergeBins_(values,endValues);}else if(events.length===2){subtractBins_(endValues,parseBuckets_(events[0],processName));mergeBins_(values,endValues);}else{throw new Error('There should be at most two snapshots of an UMA '+'histogram in each process');}}}
+for(const[name,values]of histogramValues){const histogram=new tr.v.Histogram(name,getHistogramUnit_(name),getHistogramBoundaries_(name));let sumOfMiddles=0;let sumOfBinLengths=0;for(const bin of values.bins){sumOfMiddles+=bin.count*(bin.min+bin.max)/2;sumOfBinLengths+=bin.count*(bin.max-bin.min);}
+const shift=(values.sum-sumOfMiddles)/sumOfBinLengths;if(Math.abs(shift)>0.5)throw new Error('Samples sum is wrong');for(const bin of values.bins){if(bin.count===0)continue;const shiftedValue=(bin.min+bin.max)/2+shift*(bin.max-bin.min);for(const[processName,count]of bin.processes){bin.processes.set(processName,shiftedValue*count/bin.count);}
+for(let i=0;i<bin.count;i++){histogram.addSample(shiftedValue,{processes:bin.processes,events:bin.events});}}
+histograms.addHistogram(histogram);}}
+tr.metrics.MetricRegistry.register(umaMetric,{requiredCategories:['benchmark'],});return{umaMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(4,200,100);function computeExecuteMetrics(histograms,model){const cpuTotalExecution=new tr.v.Histogram('v8_execution_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalExecution.description='cpu total time spent in script execution';const wallTotalExecution=new tr.v.Histogram('v8_execution_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalExecution.description='wall total time spent in script execution';const cpuSelfExecution=new tr.v.Histogram('v8_execution_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfExecution.description='cpu self time spent in script execution';const wallSelfExecution=new tr.v.Histogram('v8_execution_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfExecution.description='wall self time spent in script execution';for(const e of model.findTopmostSlicesNamed('V8.Execute')){cpuTotalExecution.addSample(e.cpuDuration);wallTotalExecution.addSample(e.duration);cpuSelfExecution.addSample(e.cpuSelfTime);wallSelfExecution.addSample(e.selfTime);}
+histograms.addHistogram(cpuTotalExecution);histograms.addHistogram(wallTotalExecution);histograms.addHistogram(cpuSelfExecution);histograms.addHistogram(wallSelfExecution);}
+function computeParseLazyMetrics(histograms,model){const cpuSelfParseLazy=new tr.v.Histogram('v8_parse_lazy_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfParseLazy.description='cpu self time spent performing lazy parsing';const wallSelfParseLazy=new tr.v.Histogram('v8_parse_lazy_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfParseLazy.description='wall self time spent performing lazy parsing';for(const e of model.findTopmostSlicesNamed('V8.ParseLazyMicroSeconds')){cpuSelfParseLazy.addSample(e.cpuSelfTime);wallSelfParseLazy.addSample(e.selfTime);}
+for(const e of model.findTopmostSlicesNamed('V8.ParseLazy')){cpuSelfParseLazy.addSample(e.cpuSelfTime);wallSelfParseLazy.addSample(e.selfTime);}
+histograms.addHistogram(cpuSelfParseLazy);histograms.addHistogram(wallSelfParseLazy);}
+function computeCompileFullCodeMetrics(histograms,model){const cpuSelfCompileFullCode=new tr.v.Histogram('v8_compile_full_code_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfCompileFullCode.description='cpu self time spent performing compiling full code';const wallSelfCompileFullCode=new tr.v.Histogram('v8_compile_full_code_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfCompileFullCode.description='wall self time spent performing compiling full code';for(const e of model.findTopmostSlicesNamed('V8.CompileFullCode')){cpuSelfCompileFullCode.addSample(e.cpuSelfTime);wallSelfCompileFullCode.addSample(e.selfTime);}
+histograms.addHistogram(cpuSelfCompileFullCode);histograms.addHistogram(wallSelfCompileFullCode);}
+function computeCompileIgnitionMetrics(histograms,model){const cpuSelfCompileIgnition=new tr.v.Histogram('v8_compile_ignition_cpu_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuSelfCompileIgnition.description='cpu self time spent in compile ignition';const wallSelfCompileIgnition=new tr.v.Histogram('v8_compile_ignition_wall_self',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallSelfCompileIgnition.description='wall self time spent in compile ignition';for(const e of model.findTopmostSlicesNamed('V8.CompileIgnition')){cpuSelfCompileIgnition.addSample(e.cpuSelfTime);wallSelfCompileIgnition.addSample(e.selfTime);}
+histograms.addHistogram(cpuSelfCompileIgnition);histograms.addHistogram(wallSelfCompileIgnition);}
+function computeRecompileMetrics(histograms,model){const cpuTotalRecompileSynchronous=new tr.v.Histogram('v8_recompile_synchronous_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalRecompileSynchronous.description='cpu total time spent in synchronous recompilation';const wallTotalRecompileSynchronous=new tr.v.Histogram('v8_recompile_synchronous_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalRecompileSynchronous.description='wall total time spent in synchronous recompilation';const cpuTotalRecompileConcurrent=new tr.v.Histogram('v8_recompile_concurrent_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalRecompileConcurrent.description='cpu total time spent in concurrent recompilation';const wallTotalRecompileConcurrent=new tr.v.Histogram('v8_recompile_concurrent_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalRecompileConcurrent.description='wall total time spent in concurrent recompilation';const cpuTotalRecompileOverall=new tr.v.Histogram('v8_recompile_overall_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalRecompileOverall.description='cpu total time spent in synchronous or concurrent recompilation';const wallTotalRecompileOverall=new tr.v.Histogram('v8_recompile_overall_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalRecompileOverall.description='wall total time spent in synchronous or concurrent recompilation';for(const e of model.findTopmostSlicesNamed('V8.RecompileSynchronous')){cpuTotalRecompileSynchronous.addSample(e.cpuDuration);wallTotalRecompileSynchronous.addSample(e.duration);cpuTotalRecompileOverall.addSample(e.cpuDuration);wallTotalRecompileOverall.addSample(e.duration);}
+histograms.addHistogram(cpuTotalRecompileSynchronous);histograms.addHistogram(wallTotalRecompileSynchronous);for(const e of model.findTopmostSlicesNamed('V8.RecompileConcurrent')){cpuTotalRecompileConcurrent.addSample(e.cpuDuration);wallTotalRecompileConcurrent.addSample(e.duration);cpuTotalRecompileOverall.addSample(e.cpuDuration);wallTotalRecompileOverall.addSample(e.duration);}
+histograms.addHistogram(cpuTotalRecompileConcurrent);histograms.addHistogram(wallTotalRecompileConcurrent);histograms.addHistogram(cpuTotalRecompileOverall);histograms.addHistogram(wallTotalRecompileOverall);}
+function computeOptimizeCodeMetrics(histograms,model){const cpuTotalOptimizeCode=new tr.v.Histogram('v8_optimize_code_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalOptimizeCode.description='cpu total time spent in code optimization';const wallTotalOptimizeCode=new tr.v.Histogram('v8_optimize_code_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalOptimizeCode.description='wall total time spent in code optimization';for(const e of model.findTopmostSlicesNamed('V8.OptimizeCode')){cpuTotalOptimizeCode.addSample(e.cpuDuration);wallTotalOptimizeCode.addSample(e.duration);}
+histograms.addHistogram(cpuTotalOptimizeCode);histograms.addHistogram(wallTotalOptimizeCode);}
+function computeDeoptimizeCodeMetrics(histograms,model){const cpuTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_cpu_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);cpuTotalDeoptimizeCode.description='cpu total time spent in code deoptimization';const wallTotalDeoptimizeCode=new tr.v.Histogram('v8_deoptimize_code_wall_total',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);wallTotalDeoptimizeCode.description='wall total time spent in code deoptimization';for(const e of model.findTopmostSlicesNamed('V8.DeoptimizeCode')){cpuTotalDeoptimizeCode.addSample(e.cpuDuration);wallTotalDeoptimizeCode.addSample(e.duration);}
+histograms.addHistogram(cpuTotalDeoptimizeCode);histograms.addHistogram(wallTotalDeoptimizeCode);}
+function executionMetric(histograms,model){computeExecuteMetrics(histograms,model);computeParseLazyMetrics(histograms,model);computeCompileIgnitionMetrics(histograms,model);computeCompileFullCodeMetrics(histograms,model);computeRecompileMetrics(histograms,model);computeOptimizeCodeMetrics(histograms,model);computeDeoptimizeCodeMetrics(histograms,model);}
+tr.metrics.MetricRegistry.register(executionMetric);return{executionMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const TARGET_FPS=60;const MS_PER_SECOND=1000;const WINDOW_SIZE_MS=MS_PER_SECOND/TARGET_FPS;function gcMetric(histograms,model,options){options=options||{};addDurationOfTopEvents(histograms,model);addTotalDurationOfTopEvents(histograms,model);if(options.include_sub_events){addDurationOfSubEvents(histograms,model);}
+addPercentageInV8ExecuteOfTopEvents(histograms,model);addTotalPercentageInV8Execute(histograms,model);addMarkCompactorMutatorUtilization(histograms,model);addTotalMarkCompactorTime(histograms,model);addTotalMarkCompactorMarkingTime(histograms,model);}
+tr.metrics.MetricRegistry.register(gcMetric);const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(0,20,200).addExponentialBins(200,100);function createNumericForTopEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:true,max:true,min:false,std:true,sum:true,percentile:[0.90]});return n;}
+function createNumericForSubEventTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:false,percentile:[0.90]});return n;}
+function createNumericForIdleTime(name){const n=new tr.v.Histogram(name,timeDurationInMs_smallerIsBetter,CUSTOM_BOUNDARIES);n.customizeSummaryOptions({avg:true,count:false,max:true,min:false,std:false,sum:true,percentile:[]});return n;}
+function createPercentage(name,numerator,denominator,unit){const hist=new tr.v.Histogram(name,unit);if(denominator===0){hist.addSample(0);}else{hist.addSample(numerator/denominator);}
+hist.customizeSummaryOptions({avg:true,count:false,max:false,min:false,std:false,sum:false,percentile:[]});return hist;}
+function addDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,tr.metrics.v8.utils.topGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForTopEventTime(name);events.forEach(function(event){cpuDuration.addSample(event.cpuDuration);});histograms.addHistogram(cpuDuration);},tr.metrics.v8.utils.topGarbageCollectionEventNames());}
+function addTotalDurationOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,event=>'v8-gc-total',function(name,events){const cpuDuration=createNumericForTopEventTime(name);events.forEach(function(event){cpuDuration.addSample(event.cpuDuration);});histograms.addHistogram(cpuDuration);},['v8-gc-total']);}
+function isV8MarkCompactorSummary(event){return!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event)&&tr.metrics.v8.utils.isMarkCompactorSummaryEvent(event);}
+function isV8MarkCompactorMarkingSummary(event){return!tr.metrics.v8.utils.isForcedGarbageCollectionEvent(event)&&tr.metrics.v8.utils.isMarkCompactorMarkingSummaryEvent(event);}
+function createHistogramFromSummary(histograms,name,events){const foregroundDuration=createNumericForTopEventTime(name+'-foreground');const backgroundDuration=createNumericForTopEventTime(name+'-background');const totalDuration=createNumericForTopEventTime(name+'-total');const relatedNames=new tr.v.d.RelatedNameMap();relatedNames.set('foreground',foregroundDuration.name);relatedNames.set('background',backgroundDuration.name);for(const event of events){foregroundDuration.addSample(event.args.duration);backgroundDuration.addSample(event.args.background_duration);const breakdownForTotal=new tr.v.d.Breakdown();breakdownForTotal.set('foreground',event.args.duration);breakdownForTotal.set('background',event.args.background_duration);totalDuration.addSample(event.args.duration+event.args.background_duration,{breakdown:breakdownForTotal});}
+histograms.addHistogram(foregroundDuration);histograms.addHistogram(backgroundDuration);histograms.addHistogram(totalDuration,{breakdown:relatedNames});}
+function addTotalMarkCompactorTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorSummary,event=>'v8-gc-mark-compactor',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor']);}
+function addTotalMarkCompactorMarkingTime(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,isV8MarkCompactorMarkingSummary,event=>'v8-gc-mark-compactor-marking',(name,events)=>createHistogramFromSummary(histograms,name,events),['v8-gc-mark-compactor-marking']);}
+function addDurationOfSubEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedSubGarbageCollectionEvent,tr.metrics.v8.utils.subGarbageCollectionEventName,function(name,events){const cpuDuration=createNumericForSubEventTime(name);events.forEach(function(event){cpuDuration.addSample(event.cpuDuration);});histograms.addHistogram(cpuDuration);});}
+function addPercentageInV8ExecuteOfTopEvents(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,tr.metrics.v8.utils.topGarbageCollectionEventName,function(name,events){addPercentageInV8Execute(histograms,model,name,events);},tr.metrics.v8.utils.topGarbageCollectionEventNames());}
+function addTotalPercentageInV8Execute(histograms,model){tr.metrics.v8.utils.groupAndProcessEvents(model,tr.metrics.v8.utils.isNotForcedTopGarbageCollectionEvent,event=>'v8-gc-total',function(name,events){addPercentageInV8Execute(histograms,model,name,events);},['v8-gc-total']);}
+function addPercentageInV8Execute(histograms,model,name,events){let cpuDurationInV8Execute=0;let cpuDurationTotal=0;events.forEach(function(event){const v8Execute=tr.metrics.v8.utils.findParent(event,tr.metrics.v8.utils.isV8ExecuteEvent);if(v8Execute){cpuDurationInV8Execute+=event.cpuDuration;}
+cpuDurationTotal+=event.cpuDuration;});const percentage=createPercentage(name+'_percentage_in_v8_execute',cpuDurationInV8Execute,cpuDurationTotal,percentage_smallerIsBetter);histograms.addHistogram(percentage);}
+function addMarkCompactorMutatorUtilization(histograms,model){const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);const rendererHelpers=Object.values(chromeHelper.rendererHelpers);tr.metrics.v8.utils.addMutatorUtilization('v8-gc-mark-compactor-mmu',tr.metrics.v8.utils.isNotForcedMarkCompactorEvent,[100],rendererHelpers,histograms);}
+return{gcMetric,WINDOW_SIZE_MS,};});'use strict';tr.exportTo('tr.metrics.v8',function(){const COUNT_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(1,1000000,50);const DURATION_CUSTOM_BOUNDARIES=tr.v.HistogramBinBoundaries.createExponential(0.1,10000,50);const SUMMARY_OPTIONS={std:false,count:false,sum:false,min:false,max:false,};function convertMicroToMilli_(time){return tr.b.convertUnit(time,tr.b.UnitPrefixScale.METRIC.MICRO,tr.b.UnitPrefixScale.METRIC.MILLI);}
+function addDurationHistogram(histogramName,time,histograms){const value=convertMicroToMilli_(time);histograms.createHistogram(`${histogramName}:duration`,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,{value},{binBoundaries:DURATION_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS,});}
+function addCountHistogram(histogramName,value,histograms){histograms.createHistogram(`${histogramName}:count`,tr.b.Unit.byName.count_smallerIsBetter,{value},{binBoundaries:COUNT_CUSTOM_BOUNDARIES,summaryOptions:SUMMARY_OPTIONS});}
+function runtimeStatsTotalMetric(histograms,model){const v8Slices=tr.metrics.v8.utils.filterEvents(model,ev=>ev instanceof tr.e.v8.V8ThreadSlice);const runtimeGroupCollection=new tr.e.v8.RuntimeStatsGroupCollection();runtimeGroupCollection.addSlices(v8Slices);let overallV8Time=runtimeGroupCollection.totalTime;let overallV8Count=runtimeGroupCollection.totalCount;let mainThreadTime=runtimeGroupCollection.totalTime;let mainThreadCount=runtimeGroupCollection.totalCount;let mainThreadV8Time=runtimeGroupCollection.totalTime;let mainThreadV8Count=runtimeGroupCollection.totalCount;for(const runtimeGroup of runtimeGroupCollection.runtimeGroups){addDurationHistogram(runtimeGroup.name,runtimeGroup.time,histograms);if(runtimeGroup.name==='Blink C++'){overallV8Time-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}else if(runtimeGroup.name.includes('Background')){mainThreadTime-=runtimeGroup.time;mainThreadV8Time-=runtimeGroup.time;}
+addCountHistogram(runtimeGroup.name,runtimeGroup.count,histograms);if(runtimeGroup.name==='Blink C++'){overallV8Count-=runtimeGroup.count;mainThreadV8Count-=runtimeGroup.count;}else if(runtimeGroup.name.includes('Background')){mainThreadCount-=runtimeGroup.count;mainThreadV8Count-=runtimeGroup.count;}}
+if(runtimeGroupCollection.blinkRCSGroupCollection.totalTime>0){const blinkRCSGroupCollection=runtimeGroupCollection.blinkRCSGroupCollection;for(const group of blinkRCSGroupCollection.runtimeGroups){addDurationHistogram(group.name,group.time,histograms);addCountHistogram(group.name,group.count,histograms);}}
+addDurationHistogram('V8-Only',overallV8Time,histograms);addCountHistogram('V8-Only',overallV8Count,histograms);addDurationHistogram('Total-Main-Thread',mainThreadTime,histograms);addCountHistogram('Total-Main-Thread',mainThreadCount,histograms);addDurationHistogram('V8-Only-Main-Thread',mainThreadV8Time,histograms);addCountHistogram('V8-Only-Main-Thread',mainThreadV8Count,histograms);}
+tr.metrics.MetricRegistry.register(runtimeStatsTotalMetric);return{runtimeStatsTotalMetric,};});'use strict';tr.exportTo('tr.metrics.v8',function(){function v8AndMemoryMetrics(histograms,model){tr.metrics.v8.executionMetric(histograms,model);tr.metrics.v8.gcMetric(histograms,model);tr.metrics.sh.memoryMetric(histograms,model,{rangeOfInterest:tr.metrics.v8.utils.rangeForMemoryDumps(model)});}
+tr.metrics.MetricRegistry.register(v8AndMemoryMetrics);return{v8AndMemoryMetrics,};});'use strict';tr.exportTo('tr.metrics.vr',function(){const VR_GL_THREAD_NAME='VrShellGL';function createHistograms(histograms,name,options,hasCpuTime){const createdHistograms={wall:histograms.createHistogram(name+'_wall',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options)};if(hasCpuTime){createdHistograms.cpu=histograms.createHistogram(name+'_cpu',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],options);}
+return createdHistograms;}
+function frameCycleDurationMetric(histograms,model,opt_options){const histogramsByEventTitle=new Map();const expectationEvents=tr.importer.VR_EXPECTATION_EVENTS;for(const eventName in expectationEvents){const extraInfo=expectationEvents[eventName];histogramsByEventTitle.set(eventName,createHistograms(histograms,extraInfo.histogramName,{description:extraInfo.description},extraInfo.hasCpuTime));}
+histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateAnimationsAndOpacity',createHistograms(histograms,'update_animations_and_opacity',{description:'Duration to apply animation and opacity changes'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateBindings',createHistograms(histograms,'update_bindings',{description:'Duration to push binding values'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateLayout',createHistograms(histograms,'update_layout',{description:'Duration to compute element sizes, layout and textures'},true));histogramsByEventTitle.set('UiScene::OnBeginFrame.UpdateWorldSpaceTransform',createHistograms(histograms,'update_world_space_transforms',{description:'Duration to calculate element transforms in world space'},true));histogramsByEventTitle.set('UiRenderer::DrawUiView',createHistograms(histograms,'draw_ui',{description:'Duration to draw the UI'},true));histogramsByEventTitle.set('UiElementRenderer::DrawTexturedQuad',createHistograms(histograms,'draw_textured_quad',{description:'Duration to draw a textured element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientQuad',createHistograms(histograms,'draw_gradient_quad',{description:'Duration to draw a gradient element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawGradientGridQuad',createHistograms(histograms,'draw_gradient_grid_quad',{description:'Duration to draw a gradient grid element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawController',createHistograms(histograms,'draw_controller',{description:'Duration to draw the controller'},true));histogramsByEventTitle.set('UiElementRenderer::DrawLaser',createHistograms(histograms,'draw_laser',{description:'Duration to draw the laser'},true));histogramsByEventTitle.set('UiElementRenderer::DrawReticle',createHistograms(histograms,'draw_reticle',{description:'Duration to draw the reticle'},true));histogramsByEventTitle.set('UiElementRenderer::DrawShadow',createHistograms(histograms,'draw_shadow',{description:'Duration to draw a shadow element'},true));histogramsByEventTitle.set('UiElementRenderer::DrawStars',createHistograms(histograms,'draw_stars',{description:'Duration to draw the stars'},true));histogramsByEventTitle.set('UiElementRenderer::DrawBackground',createHistograms(histograms,'draw_background',{description:'Duration to draw the textured background'},true));histogramsByEventTitle.set('UiElementRenderer::DrawKeyboard',createHistograms(histograms,'draw_keyboard',{description:'Duration to draw the keyboard'},true));const drawUiSubSlicesMap=new Map();const chromeHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let rangeOfInterest=model.bounds;const userExpectationsOfInterest=[tr.model.um.AnimationExpectation];if(opt_options&&opt_options.rangeOfInterest){rangeOfInterest=opt_options.rangeOfInterest;userExpectationsOfInterest.push(tr.model.um.ResponseExpectation);}
+for(const ue of model.userModel.expectations){if(ue.initiatorType!==tr.model.um.INITIATOR_TYPE.VR){continue;}
+if(!userExpectationsOfInterest.some(function(ueOfInterest){return ue instanceof ueOfInterest;})){continue;}
+if(!rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){continue;}
+for(const helper of chromeHelper.browserHelpers){const glThreads=helper.process.findAllThreadsNamed(VR_GL_THREAD_NAME);for(const glThread of glThreads){for(const event of glThread.getDescendantEvents()){if(!(histogramsByEventTitle.has(event.title))){continue;}
+if(event.start<ue.start||event.end>ue.end){continue;}
+if(event.start<rangeOfInterest.min||event.end>rangeOfInterest.max){continue;}
+if(event.parentSlice&&event.parentSlice.title==='UiRenderer::DrawUiView'){const guid=event.parentSlice.guid;if(!drawUiSubSlicesMap.has(guid)){drawUiSubSlicesMap.set(guid,[]);}
+drawUiSubSlicesMap.get(guid).push(event);continue;}
+const{wall:wallHist,cpu:cpuHist}=histogramsByEventTitle.get(event.title);wallHist.addSample(event.duration);if(cpuHist!==undefined){cpuHist.addSample(event.cpuDuration);}}}}}
+for(const subSlices of drawUiSubSlicesMap.values()){const eventMap=new Map();for(const event of subSlices){if(!eventMap.has(event.title)){eventMap.set(event.title,{wall:0,cpu:0});}
+eventMap.get(event.title).wall+=event.duration;eventMap.get(event.title).cpu+=event.cpuDuration;}
+for(const[title,values]of eventMap.entries()){const{wall:wallHist,cpu:cpuHist}=histogramsByEventTitle.get(title);wallHist.addSample(values.wall);if(cpuHist!==undefined){cpuHist.addSample(values.cpu);}}}}
+tr.metrics.MetricRegistry.register(frameCycleDurationMetric,{supportsRangeOfInterest:true,});return{frameCycleDurationMetric,};});'use strict';tr.exportTo('tr.metrics.vr',function(){function webvrMetric(histograms,model,opt_options){const WEBVR_COUNTERS=new Map([['gpu.WebVR FPS',{name:'webvr_fps',unit:tr.b.Unit.byName.count_biggerIsBetter,samples:{},options:{description:'WebVR frame per second',binBoundaries:tr.v.HistogramBinBoundaries.createLinear(20,120,25),},}],['gpu.WebVR frame time (ms)',{name:'webvr_frame_time',unit:tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,samples:{},options:{description:'WebVR frame time in ms',binBoundaries:tr.v.HistogramBinBoundaries.createLinear(20,120,25),},}],['gpu.WebVR pose prediction (ms)',{name:'webvr_pose_prediction',unit:tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,samples:{},options:{description:'WebVR pose prediction in ms',binBoundaries:tr.v.HistogramBinBoundaries.createLinear(20,120,25),},}],]);for(const ue of model.userModel.expectations){const rangeOfInterestEnabled=opt_options&&opt_options.rangeOfInterest;if(rangeOfInterestEnabled&&!opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){continue;}
+if(ue.initiatorType!==tr.model.um.INITIATOR_TYPE.VR)continue;if(!rangeOfInterestEnabled){if(!(ue instanceof tr.model.um.AnimationExpectation))continue;}else{if(!(ue instanceof tr.model.um.AnimationExpectation||ue instanceof tr.model.um.ResponseExpectation))continue;}
+for(const counter of model.getAllCounters()){if(!(WEBVR_COUNTERS.has(counter.id)))continue;for(const series of counter.series){if(!(series.name in WEBVR_COUNTERS.get(counter.id).samples)){WEBVR_COUNTERS.get(counter.id).samples[series.name]=[];}
+for(const sample of series.samples){if(sample.timestamp<ue.start||sample.timestamp>=ue.end){continue;}
+if(rangeOfInterestEnabled&&!opt_options.rangeOfInterest.intersectsExplicitRangeInclusive(sample.timestamp,sample.timestamp)){continue;}
+WEBVR_COUNTERS.get(counter.id).samples[series.name].push(sample.value);}}}}
+if(!('value'in WEBVR_COUNTERS.get('gpu.WebVR FPS').samples)){WEBVR_COUNTERS.get('gpu.WebVR FPS').samples.value=[0];}
+for(const[key,value]of WEBVR_COUNTERS){for(const[seriesName,samples]of Object.entries(value.samples)){let histogramName=value.name;if(seriesName!=='value'){histogramName=`${histogramName}_${seriesName}`;}
+histograms.createHistogram(histogramName,value.unit,samples,value.options);}}}
+tr.metrics.MetricRegistry.register(webvrMetric,{supportsRangeOfInterest:true,});return{webvrMetric,};});'use strict';tr.exportTo('tr.metrics.vr',function(){function webxrMetric(histograms,model,opt_options){const DEFAULT_BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(20,120,25);const counterHistogramsByTitle=new Map();counterHistogramsByTitle.set('gpu.WebXR FPS',histograms.createHistogram('webxr_fps',tr.b.Unit.byName.count_biggerIsBetter,[],{description:'WebXR frames per second',binBoundaries:DEFAULT_BIN_BOUNDARIES,}));const instantHistogramsByTitle=new Map();const expectationEvents=tr.importer.WEBXR_INSTANT_EVENTS;for(const[eventName,eventData]of Object.entries(expectationEvents)){const argsToHistograms={};for(const[argName,argData]of Object.entries(eventData)){argsToHistograms[argName]=histograms.createHistogram(argData.histogramName,tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[],{description:argData.description,binBoundaries:DEFAULT_BIN_BOUNDARIES,});}
+instantHistogramsByTitle.set(eventName,argsToHistograms);}
+const rangeOfInterestEnabled=opt_options&&opt_options.rangeOfInterest;const rangeOfInterest=(rangeOfInterestEnabled?opt_options.rangeOfInterest:tr.b.math.Range.fromExplicitRange(-Infinity,Infinity));for(const ue of model.userModel.expectations){if(!rangeOfInterest.intersectsExplicitRangeInclusive(ue.start,ue.end)){continue;}
+if(ue.initiatorType!==tr.model.um.INITIATOR_TYPE.VR)continue;if(!rangeOfInterestEnabled){if(!(ue instanceof tr.model.um.AnimationExpectation))continue;}else{if(!(ue instanceof tr.model.um.AnimationExpectation||ue instanceof tr.model.um.ResponseExpectation))continue;}
+for(const counter of model.getAllCounters()){if(!(counterHistogramsByTitle.has(counter.id)))continue;for(const series of counter.series){for(const sample of series.samples){if(sample.timestamp<ue.start||sample.timestamp>=ue.end){continue;}
+if(!rangeOfInterest.intersectsExplicitRangeInclusive(sample.timestamp,sample.timestamp)){continue;}
+counterHistogramsByTitle.get(counter.id).addSample(sample.value);}}}
+for(const event of ue.associatedEvents.asSet()){if(!(instantHistogramsByTitle.has(event.title))){continue;}
+if(!rangeOfInterest.intersectsExplicitRangeInclusive(event.start,event.start)){continue;}
+const eventHistograms=instantHistogramsByTitle.get(event.title);for(const[key,value]of Object.entries(event.args)){if(key in eventHistograms){eventHistograms[key].addSample(value,{event:new tr.v.d.RelatedEventSet(event)});}}}}
+if(counterHistogramsByTitle.get('gpu.WebXR FPS').numValues===0){counterHistogramsByTitle.get('gpu.WebXR FPS').addSample(0);}}
+tr.metrics.MetricRegistry.register(webxrMetric,{supportsRangeOfInterest:true,});return{webxrMetric,};});'use strict';tr.exportTo('tr.metrics.webrtc',function(){const DISPLAY_HERTZ=60.0;const VSYNC_DURATION_US=1e6/DISPLAY_HERTZ;const SEVERITY=3;const FROZEN_FRAME_VSYNC_COUNT_THRESHOLD=6;const WEB_MEDIA_PLAYER_UPDATE_TITLE='UpdateCurrentFrame';const IDEAL_RENDER_INSTANT_NAME='Ideal Render Instant';const ACTUAL_RENDER_BEGIN_NAME='Actual Render Begin';const ACTUAL_RENDER_END_NAME='Actual Render End';const STREAM_ID_NAME='Serial';const REQUIRED_EVENT_ARGS_NAMES=[IDEAL_RENDER_INSTANT_NAME,ACTUAL_RENDER_BEGIN_NAME,ACTUAL_RENDER_END_NAME,STREAM_ID_NAME];const SUMMARY_OPTIONS=tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS;const count_smallerIsBetter=tr.b.Unit.byName.count_smallerIsBetter;const percentage_biggerIsBetter=tr.b.Unit.byName.normalizedPercentage_biggerIsBetter;const percentage_smallerIsBetter=tr.b.Unit.byName.normalizedPercentage_smallerIsBetter;const timeDurationInMs_smallerIsBetter=tr.b.Unit.byName.timeDurationInMs_smallerIsBetter;const unitlessNumber_biggerIsBetter=tr.b.Unit.byName.unitlessNumber_biggerIsBetter;function isValidEvent(event){if(event.title!==WEB_MEDIA_PLAYER_UPDATE_TITLE||!event.args){return false;}
+for(const parameter of REQUIRED_EVENT_ARGS_NAMES){if(!(parameter in event.args)){return false;}}
+return true;}
+function webrtcRenderingMetric(histograms,model){const modelHelper=model.getOrCreateHelper(tr.model.helpers.ChromeModelHelper);let webMediaPlayerMSEvents=[];for(const rendererPid in modelHelper.rendererHelpers){const rendererHelper=modelHelper.rendererHelpers[rendererPid];const compositorThread=rendererHelper.compositorThread;if(compositorThread!==undefined){webMediaPlayerMSEvents=webMediaPlayerMSEvents.concat(compositorThread.sliceGroup.slices.filter(isValidEvent));}}
+const eventsByStreamName=tr.b.groupIntoMap(webMediaPlayerMSEvents,event=>event.args[STREAM_ID_NAME]);for(const[streamName,events]of eventsByStreamName){getTimeStats(histograms,streamName,events);}}
+tr.metrics.MetricRegistry.register(webrtcRenderingMetric);function getTimeStats(histograms,streamName,events){const frameHist=getFrameDistribution(histograms,events);addFpsFromFrameDistribution(histograms,frameHist);addFreezingScore(histograms,frameHist);const driftTimeStats=getDriftStats(events);histograms.createHistogram('WebRTCRendering_drift_time',timeDurationInMs_smallerIsBetter,driftTimeStats.driftTime,{summaryOptions:{count:false,min:false,percentile:[0.75,0.9],},});histograms.createHistogram('WebRTCRendering_rendering_length_error',percentage_smallerIsBetter,driftTimeStats.renderingLengthError,{summaryOptions:SUMMARY_OPTIONS,});const smoothnessStats=getSmoothnessStats(driftTimeStats.driftTime);histograms.createHistogram('WebRTCRendering_percent_badly_out_of_sync',percentage_smallerIsBetter,smoothnessStats.percentBadlyOutOfSync,{summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('WebRTCRendering_percent_out_of_sync',percentage_smallerIsBetter,smoothnessStats.percentOutOfSync,{summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('WebRTCRendering_smoothness_score',percentage_biggerIsBetter,smoothnessStats.smoothnessScore,{summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('WebRTCRendering_frames_out_of_sync',count_smallerIsBetter,smoothnessStats.framesOutOfSync,{summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('WebRTCRendering_frames_badly_out_of_sync',count_smallerIsBetter,smoothnessStats.framesSeverelyOutOfSync,{summaryOptions:SUMMARY_OPTIONS,});}
+const FRAME_DISTRIBUTION_BIN_BOUNDARIES=tr.v.HistogramBinBoundaries.createLinear(1,50,49);function getFrameDistribution(histograms,events){const cadence=tr.b.runLengthEncoding(events.map(e=>e.args[IDEAL_RENDER_INSTANT_NAME]));return histograms.createHistogram('WebRTCRendering_frame_distribution',count_smallerIsBetter,cadence.map(ticks=>ticks.count),{binBoundaries:FRAME_DISTRIBUTION_BIN_BOUNDARIES,summaryOptions:{percentile:[0.75,0.9],},});}
+function addFpsFromFrameDistribution(histograms,frameHist){let numberFrames=0;let numberVsyncs=0;for(let ticks=1;ticks<frameHist.allBins.length;++ticks){const count=frameHist.allBins[ticks].count;numberFrames+=count;numberVsyncs+=ticks*count;}
+const meanRatio=numberVsyncs/numberFrames;histograms.createHistogram('WebRTCRendering_fps',unitlessNumber_biggerIsBetter,DISPLAY_HERTZ/meanRatio,{summaryOptions:SUMMARY_OPTIONS,});}
+function frozenPenaltyWeight(numberFrozenFrames){const penalty={5:1,6:5,7:15,8:25};return penalty[numberFrozenFrames]||(8*(numberFrozenFrames-4));}
+function addFreezingScore(histograms,frameHist){let numberVsyncs=0;let freezingScore=0;let frozenFramesCount=0;for(let ticks=1;ticks<frameHist.allBins.length;++ticks){const count=frameHist.allBins[ticks].count;numberVsyncs+=ticks*count;if(ticks>=FROZEN_FRAME_VSYNC_COUNT_THRESHOLD){frozenFramesCount+=count*(ticks-1);freezingScore+=count*frozenPenaltyWeight(ticks-1);}}
+freezingScore=1-freezingScore/numberVsyncs;if(freezingScore<0){freezingScore=0;}
+histograms.createHistogram('WebRTCRendering_frozen_frames_count',count_smallerIsBetter,frozenFramesCount,{summaryOptions:SUMMARY_OPTIONS,});histograms.createHistogram('WebRTCRendering_freezing_score',percentage_biggerIsBetter,freezingScore,{summaryOptions:SUMMARY_OPTIONS,});}
+function getDriftStats(events){const driftTime=[];const discrepancy=[];let oldIdealRender=0;let expectedIdealRender=0;for(const event of events){const currentIdealRender=event.args[IDEAL_RENDER_INSTANT_NAME];expectedIdealRender+=VSYNC_DURATION_US;if(currentIdealRender===oldIdealRender){continue;}
+const actualRenderBegin=event.args[ACTUAL_RENDER_BEGIN_NAME];driftTime.push(actualRenderBegin-currentIdealRender);discrepancy.push(Math.abs(currentIdealRender-expectedIdealRender));expectedIdealRender=currentIdealRender;oldIdealRender=currentIdealRender;}
+const discrepancySum=tr.b.math.Statistics.sum(discrepancy)-
+discrepancy[0];const lastIdealRender=events[events.length-1].args[IDEAL_RENDER_INSTANT_NAME];const firstIdealRender=events[0].args[IDEAL_RENDER_INSTANT_NAME];const idealRenderSpan=lastIdealRender-firstIdealRender;const renderingLengthError=discrepancySum/idealRenderSpan;return{driftTime,renderingLengthError};}
+function getSmoothnessStats(driftTimes){const meanDriftTime=tr.b.math.Statistics.mean(driftTimes);const normDriftTimes=driftTimes.map(driftTime=>Math.abs(driftTime-meanDriftTime));const framesSeverelyOutOfSync=normDriftTimes.filter(driftTime=>driftTime>2*VSYNC_DURATION_US).length;const framesOutOfSync=normDriftTimes.filter(driftTime=>driftTime>VSYNC_DURATION_US).length;const percentBadlyOutOfSync=framesSeverelyOutOfSync/driftTimes.length;const percentOutOfSync=framesOutOfSync/driftTimes.length;const framesOutOfSyncOnlyOnce=framesOutOfSync-framesSeverelyOutOfSync;let smoothnessScore=1-(framesOutOfSyncOnlyOnce+
+SEVERITY*framesSeverelyOutOfSync)/driftTimes.length;if(smoothnessScore<0){smoothnessScore=0;}
+return{framesOutOfSync,framesSeverelyOutOfSync,percentBadlyOutOfSync,percentOutOfSync,smoothnessScore};}
+return{webrtcRenderingMetric,};});'use strict';Polymer({is:'tr-ui-a-alert-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=[{title:'Label',value(row){return row.name;},width:'150px'},{title:'Value',width:'100%',value(row){return row.value;}}];this.$.table.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},getRowsForSingleAlert_(alert){const rows=[];for(const argName in alert.args){const argView=document.createElement('tr-ui-a-generic-object-view');argView.object=alert.args[argName];rows.push({name:argName,value:argView});}
+if(alert.associatedEvents.length){alert.associatedEvents.forEach(function(event,i){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet(event),event.title);let valueString='';if(event instanceof tr.model.TimedEvent){valueString='took '+event.duration.toFixed(2)+'ms';}
+rows.push({name:linkEl,value:valueString});});}
+const descriptionEl=tr.ui.b.createDiv({textContent:alert.info.description,maxWidth:'300px'});rows.push({name:'Description',value:descriptionEl});if(alert.info.docLinks){alert.info.docLinks.forEach(function(linkObject){const linkEl=document.createElement('a');linkEl.target='_blank';linkEl.href=linkObject.href;Polymer.dom(linkEl).textContent=Polymer.dom(linkObject).textContent;rows.push({name:linkObject.label,value:linkEl});});}
+return rows;},getRowsForAlerts_(alerts){if(alerts.length===1){const rows=[{name:'Alert',value:tr.b.getOnlyElement(alerts).title}];const detailRows=this.getRowsForSingleAlert_(tr.b.getOnlyElement(alerts));rows.push.apply(rows,detailRows);return rows;}
+return alerts.map(function(alert){return{name:'Alert',value:alert.title,isExpanded:alerts.size<10,subRows:this.getRowsForSingleAlert_(alert)};},this);},updateContents_(){if(this.currentSelection_===undefined){this.$.table.rows=[];this.$.table.rebuild();return;}
+const alerts=this.currentSelection_;this.$.table.tableRows=this.getRowsForAlerts_(alerts);this.$.table.rebuild();},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;const result=new tr.model.EventSet();for(const event of this.currentSelection_){result.addEventSet(event.associatedEvents);}
+return result;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-alert-sub-view',tr.model.Alert,{multi:false,title:'Alert',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-alert-sub-view',tr.model.Alert,{multi:true,title:'Alerts',});'use strict';tr.exportTo('tr.ui.analysis',function(){const NO_BREAK_SPACE=String.fromCharCode(160);const RIGHTWARDS_ARROW=String.fromCharCode(8594);const COLLATOR=new Intl.Collator(undefined,{numeric:true});function TitleColumn(title){this.title=title;}
+TitleColumn.prototype={supportsCellSelection:false,value(row){const formattedTitle=this.formatTitle(row);const contexts=row.contexts;if(contexts===undefined||contexts.length===0){return formattedTitle;}
+const firstContext=contexts[0];const lastContext=contexts[contexts.length-1];let changeDefinedContextCount=0;for(let i=1;i<contexts.length;i++){if((contexts[i]===undefined)!==(contexts[i-1]===undefined)){changeDefinedContextCount++;}}
+let color=undefined;let prefix=undefined;if(!firstContext&&lastContext){color='red';prefix='+++';}else if(firstContext&&!lastContext){color='green';prefix='---';}
+if(changeDefinedContextCount>1){color='purple';}
+if(color===undefined&&prefix===undefined){return formattedTitle;}
+const titleEl=document.createElement('span');if(prefix!==undefined){const prefixEl=tr.ui.b.createSpan({textContent:prefix});prefixEl.style.fontFamily='monospace';Polymer.dom(titleEl).appendChild(prefixEl);Polymer.dom(titleEl).appendChild(tr.ui.b.asHTMLOrTextNode(NO_BREAK_SPACE));}
+if(color!==undefined){titleEl.style.color=color;}
+Polymer.dom(titleEl).appendChild(tr.ui.b.asHTMLOrTextNode(formattedTitle));return titleEl;},formatTitle(row){return row.title;},cmp(rowA,rowB){return COLLATOR.compare(rowA.title,rowB.title);}};function MemoryColumn(name,cellPath,aggregationMode){this.name=name;this.cellPath=cellPath;this.shouldSetContextGroup=false;this.aggregationMode=aggregationMode;}
+MemoryColumn.fromRows=function(rows,config){const cellNames=new Set();function gatherCellNames(rows){rows.forEach(function(row){if(row===undefined)return;const fieldCells=row[config.cellKey];if(fieldCells!==undefined){for(const[fieldName,fieldCell]of Object.entries(fieldCells)){if(fieldCell===undefined||fieldCell.fields===undefined){continue;}
+cellNames.add(fieldName);}}
+const subRows=row.subRows;if(subRows!==undefined){gatherCellNames(subRows);}});}
+gatherCellNames(rows);const positions=[];cellNames.forEach(function(cellName){const cellPath=[config.cellKey,cellName];const matchingRule=MemoryColumn.findMatchingRule(cellName,config.rules);const constructor=matchingRule.columnConstructor;const column=new constructor(cellName,cellPath,config.aggregationMode);column.shouldSetContextGroup=!!config.shouldSetContextGroup;positions.push({importance:matchingRule.importance,column});});positions.sort(function(a,b){if(a.importance===b.importance){return COLLATOR.compare(a.column.name,b.column.name);}
+return b.importance-a.importance;});return positions.map(function(position){return position.column;});};MemoryColumn.spaceEqually=function(columns){const columnWidth=(100/columns.length).toFixed(3)+'%';columns.forEach(function(column){column.width=columnWidth;});};MemoryColumn.findMatchingRule=function(name,rules){for(let i=0;i<rules.length;i++){const rule=rules[i];if(MemoryColumn.nameMatchesCondition(name,rule.condition)){return rule;}}
+return undefined;};MemoryColumn.nameMatchesCondition=function(name,condition){if(condition===undefined)return true;if(typeof(condition)==='string')return name===condition;return condition.test(name);};MemoryColumn.AggregationMode={DIFF:0,MAX:1};MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER='at some selected timestamps';MemoryColumn.prototype={get title(){return this.name;},cell(row){let cell=row;const cellPath=this.cellPath;for(let i=0;i<cellPath.length;i++){if(cell===undefined)return undefined;cell=cell[cellPath[i]];}
+return cell;},aggregateCells(row,subRows){},fields(row){const cell=this.cell(row);if(cell===undefined)return undefined;return cell.fields;},value(row){const fields=this.fields(row);if(this.hasAllRelevantFieldsUndefined(fields))return'';const contexts=row.contexts;const color=this.color(fields,contexts);const infos=[];this.addInfos(fields,contexts,infos);const formattedFields=this.formatFields(fields);if((color===undefined||formattedFields==='')&&infos.length===0){return formattedFields;}
+const fieldEl=document.createElement('span');fieldEl.style.display='flex';fieldEl.style.alignItems='center';fieldEl.style.justifyContent='flex-end';Polymer.dom(fieldEl).appendChild(tr.ui.b.asHTMLOrTextNode(formattedFields));infos.forEach(function(info){const infoEl=document.createElement('span');infoEl.style.paddingLeft='4px';infoEl.style.cursor='help';infoEl.style.fontWeight='bold';Polymer.dom(infoEl).textContent=info.icon;if(info.color!==undefined){infoEl.style.color=info.color;}
+infoEl.title=info.message;Polymer.dom(fieldEl).appendChild(infoEl);},this);if(color!==undefined){fieldEl.style.color=color;}
+return fieldEl;},hasAllRelevantFieldsUndefined(fields){if(fields===undefined)return true;switch(this.aggregationMode){case MemoryColumn.AggregationMode.DIFF:return fields[0]===undefined&&fields[fields.length-1]===undefined;case MemoryColumn.AggregationMode.MAX:default:return fields.every(function(field){return field===undefined;});}},color(fields,contexts){return undefined;},formatFields(fields){if(fields.length===1){return this.formatSingleField(fields[0]);}
+return this.formatMultipleFields(fields);},formatSingleField(field){throw new Error('Not implemented');},formatMultipleFields(fields){switch(this.aggregationMode){case MemoryColumn.AggregationMode.DIFF:return this.formatMultipleFieldsDiff(fields[0],fields[fields.length-1]);case MemoryColumn.AggregationMode.MAX:return this.formatMultipleFieldsMax(fields);default:return tr.ui.b.createSpan({textContent:'(unsupported aggregation mode)',italic:true});}},formatMultipleFieldsDiff(firstField,lastField){throw new Error('Not implemented');},formatMultipleFieldsMax(fields){return this.formatSingleField(this.getMaxField(fields));},cmp(rowA,rowB){const fieldsA=this.fields(rowA);const fieldsB=this.fields(rowB);if(fieldsA!==undefined&&fieldsB!==undefined&&fieldsA.length!==fieldsB.length){throw new Error('Different number of fields');}
+const undefinedA=this.hasAllRelevantFieldsUndefined(fieldsA);const undefinedB=this.hasAllRelevantFieldsUndefined(fieldsB);if(undefinedA&&undefinedB)return 0;if(undefinedA)return-1;if(undefinedB)return 1;return this.compareFields(fieldsA,fieldsB);},compareFields(fieldsA,fieldsB){if(fieldsA.length===1){return this.compareSingleFields(fieldsA[0],fieldsB[0]);}
+return this.compareMultipleFields(fieldsA,fieldsB);},compareSingleFields(fieldA,fieldB){throw new Error('Not implemented');},compareMultipleFields(fieldsA,fieldsB){switch(this.aggregationMode){case MemoryColumn.AggregationMode.DIFF:return this.compareMultipleFieldsDiff(fieldsA[0],fieldsA[fieldsA.length-1],fieldsB[0],fieldsB[fieldsB.length-1]);case MemoryColumn.AggregationMode.MAX:return this.compareMultipleFieldsMax(fieldsA,fieldsB);default:return 0;}},compareMultipleFieldsDiff(firstFieldA,lastFieldA,firstFieldB,lastFieldB){throw new Error('Not implemented');},compareMultipleFieldsMax(fieldsA,fieldsB){return this.compareSingleFields(this.getMaxField(fieldsA),this.getMaxField(fieldsB));},getMaxField(fields){return fields.reduce(function(accumulator,field){if(field===undefined){return accumulator;}
+if(accumulator===undefined||this.compareSingleFields(field,accumulator)>0){return field;}
+return accumulator;}.bind(this),undefined);},addInfos(fields,contexts,infos){},getImportance(importanceRules){if(importanceRules.length===0)return 0;const matchingRule=MemoryColumn.findMatchingRule(this.name,importanceRules);if(matchingRule!==undefined){return matchingRule.importance;}
+let minImportance=importanceRules[0].importance;for(let i=1;i<importanceRules.length;i++){minImportance=Math.min(minImportance,importanceRules[i].importance);}
+return minImportance-1;}};function StringMemoryColumn(name,cellPath,aggregationMode){MemoryColumn.call(this,name,cellPath,aggregationMode);}
+StringMemoryColumn.prototype={__proto__:MemoryColumn.prototype,formatSingleField(string){return string;},formatMultipleFieldsDiff(firstString,lastString){if(firstString===undefined){const spanEl=tr.ui.b.createSpan({color:'red'});Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode('+'));Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(this.formatSingleField(lastString)));return spanEl;}else if(lastString===undefined){const spanEl=tr.ui.b.createSpan({color:'green'});Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode('-'));Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(this.formatSingleField(firstString)));return spanEl;}else if(firstString===lastString){return this.formatSingleField(firstString);}
+const spanEl=tr.ui.b.createSpan({color:'DarkOrange'});Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(this.formatSingleField(firstString)));Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(' '+RIGHTWARDS_ARROW+' '));Polymer.dom(spanEl).appendChild(tr.ui.b.asHTMLOrTextNode(this.formatSingleField(lastString)));return spanEl;},compareSingleFields(stringA,stringB){return COLLATOR.compare(stringA,stringB);},compareMultipleFieldsDiff(firstStringA,lastStringA,firstStringB,lastStringB){if(firstStringA===undefined&&firstStringB!==undefined){return 1;}
+if(firstStringA!==undefined&&firstStringB===undefined){return-1;}
+if(firstStringA===undefined&&firstStringB===undefined){return this.compareSingleFields(lastStringA,lastStringB);}
+if(lastStringA===undefined&&lastStringB!==undefined){return-1;}
+if(lastStringA!==undefined&&lastStringB===undefined){return 1;}
+if(lastStringA===undefined&&lastStringB===undefined){return this.compareSingleFields(firstStringB,firstStringA);}
+const areStringsAEqual=firstStringA===lastStringA;const areStringsBEqual=firstStringB===lastStringB;if(areStringsAEqual&&areStringsBEqual)return 0;if(areStringsAEqual)return-1;if(areStringsBEqual)return 1;return 0;}};function NumericMemoryColumn(name,cellPath,aggregationMode){MemoryColumn.call(this,name,cellPath,aggregationMode);}
+NumericMemoryColumn.DIFF_EPSILON=0.0001;NumericMemoryColumn.prototype={__proto__:MemoryColumn.prototype,align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,aggregateCells(row,subRows){const subRowCells=subRows.map(this.cell,this);let hasDefinedSubRowNumeric=false;let timestampCount=undefined;subRowCells.forEach(function(subRowCell){if(subRowCell===undefined)return;const subRowNumerics=subRowCell.fields;if(subRowNumerics===undefined)return;if(timestampCount===undefined){timestampCount=subRowNumerics.length;}else if(timestampCount!==subRowNumerics.length){throw new Error('Sub-rows have different numbers of timestamps');}
+if(hasDefinedSubRowNumeric){return;}
+hasDefinedSubRowNumeric=subRowNumerics.some(function(numeric){return numeric!==undefined;});});if(!hasDefinedSubRowNumeric){return;}
+const cellPath=this.cellPath;let rowCell=row;for(let i=0;i<cellPath.length;i++){const nextStepName=cellPath[i];let nextStep=rowCell[nextStepName];if(nextStep===undefined){if(i<cellPath.length-1){nextStep={};}else{nextStep=new MemoryCell(undefined);}
+rowCell[nextStepName]=nextStep;}
+rowCell=nextStep;}
+if(rowCell.fields===undefined){rowCell.fields=new Array(timestampCount);}else if(rowCell.fields.length!==timestampCount){throw new Error('Row has a different number of timestamps than sub-rows');}
+for(let i=0;i<timestampCount;i++){if(rowCell.fields[i]!==undefined)continue;rowCell.fields[i]=tr.model.MemoryAllocatorDump.aggregateNumerics(subRowCells.map(function(subRowCell){if(subRowCell===undefined||subRowCell.fields===undefined){return undefined;}
+return subRowCell.fields[i];}));}},formatSingleField(numeric){return tr.v.ui.createScalarSpan(numeric,{context:this.getFormattingContext(numeric.unit),contextGroup:this.shouldSetContextGroup?this.name:undefined,inline:true,});},getFormattingContext(unit){return undefined;},formatMultipleFieldsDiff(firstNumeric,lastNumeric){return this.formatSingleField(this.getDiffField_(firstNumeric,lastNumeric));},compareSingleFields(numericA,numericB){return numericA.value-numericB.value;},compareMultipleFieldsDiff(firstNumericA,lastNumericA,firstNumericB,lastNumericB){return this.getDiffFieldValue_(firstNumericA,lastNumericA)-
+this.getDiffFieldValue_(firstNumericB,lastNumericB);},getDiffField_(firstNumeric,lastNumeric){const definedNumeric=firstNumeric||lastNumeric;return new tr.b.Scalar(definedNumeric.unit.correspondingDeltaUnit,this.getDiffFieldValue_(firstNumeric,lastNumeric));},getDiffFieldValue_(firstNumeric,lastNumeric){const firstValue=firstNumeric===undefined?0:firstNumeric.value;const lastValue=lastNumeric===undefined?0:lastNumeric.value;const diff=lastValue-firstValue;return Math.abs(diff)<NumericMemoryColumn.DIFF_EPSILON?0:diff;}};function MemoryCell(fields){this.fields=fields;}
+MemoryCell.extractFields=function(cell){if(cell===undefined)return undefined;return cell.fields;};const RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT=10;function expandTableRowsRecursively(table){let currentLevelRows=table.tableRows;let totalVisibleRowCount=currentLevelRows.length;while(currentLevelRows.length>0){let nextLevelRowCount=0;currentLevelRows.forEach(function(currentLevelRow){const subRows=currentLevelRow.subRows;if(subRows===undefined||subRows.length===0)return;nextLevelRowCount+=subRows.length;});if(totalVisibleRowCount+nextLevelRowCount>RECURSIVE_EXPANSION_MAX_VISIBLE_ROW_COUNT){break;}
+const nextLevelRows=new Array(nextLevelRowCount);let nextLevelRowIndex=0;currentLevelRows.forEach(function(currentLevelRow){const subRows=currentLevelRow.subRows;if(subRows===undefined||subRows.length===0)return;table.setExpandedForTableRow(currentLevelRow,true);subRows.forEach(function(subRow){nextLevelRows[nextLevelRowIndex++]=subRow;});});totalVisibleRowCount+=nextLevelRowCount;currentLevelRows=nextLevelRows;}}
+function aggregateTableRowCellsRecursively(row,columns,opt_predicate){const subRows=row.subRows;if(subRows===undefined||subRows.length===0)return;subRows.forEach(function(subRow){aggregateTableRowCellsRecursively(subRow,columns,opt_predicate);});if(opt_predicate===undefined||opt_predicate(row.contexts)){aggregateTableRowCells(row,subRows,columns);}}
+function aggregateTableRowCells(row,subRows,columns){columns.forEach(function(column){if(!(column instanceof MemoryColumn))return;column.aggregateCells(row,subRows);});}
+function createCells(timeToValues,valueFieldsGetter,opt_this){opt_this=opt_this||this;const fieldNameToFields=tr.b.invertArrayOfDicts(timeToValues,valueFieldsGetter,opt_this);const result={};for(const[fieldName,fields]of Object.entries(fieldNameToFields)){result[fieldName]=new tr.ui.analysis.MemoryCell(fields);}
+return result;}
+function createWarningInfo(message){return{message,icon:String.fromCharCode(9888),color:'red'};}
+function DetailsNumericMemoryColumn(name,cellPath,aggregationMode){NumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+DetailsNumericMemoryColumn.prototype={__proto__:NumericMemoryColumn.prototype,getFormattingContext(unit){if(unit.baseUnit===tr.b.Unit.byName.sizeInBytes){return{unitPrefix:tr.b.UnitPrefixScale.BINARY.KIBI};}
+return undefined;}};return{TitleColumn,MemoryColumn,StringMemoryColumn,NumericMemoryColumn,MemoryCell,expandTableRowsRecursively,aggregateTableRowCellsRecursively,aggregateTableRowCells,createCells,createWarningInfo,DetailsNumericMemoryColumn,};});'use strict';tr.exportTo('tr.ui.analysis',function(){const LATIN_SMALL_LETTER_F_WITH_HOOK=String.fromCharCode(0x0192);const CIRCLED_LATIN_CAPITAL_LETTER_T=String.fromCharCode(0x24C9);const HeapDetailsRowDimension={ROOT:{},STACK_FRAME:{label:'Stack frame',symbol:LATIN_SMALL_LETTER_F_WITH_HOOK,color:'heap_dump_stack_frame'},OBJECT_TYPE:{label:'Object type',symbol:CIRCLED_LATIN_CAPITAL_LETTER_T,color:'heap_dump_object_type'}};function HeapDetailsTitleColumn(title){tr.ui.analysis.TitleColumn.call(this,title);}
+HeapDetailsTitleColumn.prototype={__proto__:tr.ui.analysis.TitleColumn.prototype,formatTitle(row){if(row.dimension===HeapDetailsRowDimension.ROOT){return row.title;}
+const symbolEl=document.createElement('span');Polymer.dom(symbolEl).textContent=row.dimension.symbol;symbolEl.title=row.dimension.label;symbolEl.style.color=tr.b.ColorScheme.getColorForReservedNameAsString(row.dimension.color);symbolEl.style.paddingRight='4px';symbolEl.style.cursor='help';symbolEl.style.fontWeight='bold';const titleEl=document.createElement('span');Polymer.dom(titleEl).appendChild(symbolEl);Polymer.dom(titleEl).appendChild(document.createTextNode(row.title));return titleEl;}};function AllocationCountColumn(name,cellPath,aggregationMode){tr.ui.analysis.DetailsNumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+AllocationCountColumn.prototype={__proto__:tr.ui.analysis.DetailsNumericMemoryColumn.prototype,getFormattingContext(unit){return{minimumFractionDigits:0};}};const HEAP_DETAILS_COLUMN_RULES=[{condition:'Size',importance:2,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Count',importance:1,columnConstructor:AllocationCountColumn},{importance:0,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn}];return{HeapDetailsRowDimension,HeapDetailsTitleColumn,AllocationCountColumn,HEAP_DETAILS_COLUMN_RULES,};});'use strict';tr.exportTo('tr.ui.analysis',function(){const RebuildableBehavior={rebuild(){if(!this.paneDirty_){return;}
+this.paneDirty_=false;this.onRebuild_();},scheduleRebuild_(){if(this.paneDirty_)return;this.paneDirty_=true;tr.b.requestAnimationFrame(this.rebuild.bind(this));},onRebuild_(){}};return{RebuildableBehavior,};});'use strict';Polymer({is:'tr-ui-b-tab-view',properties:{label_:{type:String,value:()=>''},selectedSubView_:Object,subViews_:{type:Array,value:()=>[]},tabsHidden:{type:Boolean,value:false,observer:'tabsHiddenChanged_'}},ready(){this.$.tabs.addEventListener('keydown',this.onKeyDown_.bind(this),true);this.updateFocusability_();},set label(newLabel){this.set('label_',newLabel);},get tabs(){return this.get('subViews_');},get selectedSubView(){return this.selectedSubView_;},set selectedSubView(subView){if(subView===this.selectedSubView_)return;if(this.selectedSubView_){Polymer.dom(this.$.subView).removeChild(this.selectedSubView_);const oldInput=this.root.getElementById(this.computeRadioId_(this.selectedSubView_));if(oldInput){oldInput.checked=false;}}
+this.set('selectedSubView_',subView);if(subView){Polymer.dom(this.$.subView).appendChild(subView);const newInput=this.root.getElementById(this.computeRadioId_(subView));if(newInput){newInput.checked=true;}}
+this.fire('selected-tab-change');},clearSubViews(){this.splice('subViews_',0,this.subViews_.length);this.selectedSubView=undefined;this.updateFocusability_();},addSubView(subView){this.push('subViews_',subView);if(!this.selectedSubView_)this.selectedSubView=subView;this.updateFocusability_();},get subViews(){return this.subViews_;},resetSubViews(subViews){this.splice('subViews_',0,this.subViews_.length);if(subViews.length){for(const subView of subViews){this.push('subViews_',subView);}
+this.selectedSubView=subViews[0];}else{this.selectedSubView=undefined;}
+this.updateFocusability_();},onTabChanged_(event){this.selectedSubView=event.model.item;},isChecked_(subView){return this.selectedSubView_===subView;},tabsHiddenChanged_(){this.updateFocusability_();},onKeyDown_(e){if(this.tabsHidden)return;let keyHandled=false;switch(e.keyCode){case 37:keyHandled=this.selectPreviousTabIfPossible();break;case 39:keyHandled=this.selectNextTabIfPossible();break;}
+if(!keyHandled)return;e.stopPropagation();e.preventDefault();},selectNextTabIfPossible(){return this.selectTabByOffsetIfPossible_(1);},selectPreviousTabIfPossible(){return this.selectTabByOffsetIfPossible_(-1);},selectTabByOffsetIfPossible_(offset){if(!this.selectedSubView_)return false;const currentIndex=this.subViews_.indexOf(this.selectedSubView_);const newSubView=this.tabs[currentIndex+offset];if(!newSubView)return false;this.selectedSubView=newSubView;return true;},shouldBeFocusable_(){return!this.tabsHidden&&this.subViews_.length>0;},updateFocusability_(){if(this.shouldBeFocusable_()){Polymer.dom(this.$.tabs).setAttribute('tabindex',0);}else{Polymer.dom(this.$.tabs).removeAttribute('tabindex');}},computeRadioId_(subView){return subView.tagName+'-'+subView.tabLabel.replace(/ /g,'-');}});'use strict';tr.exportTo('tr.ui.analysis',function(){const RESONABLE_NUMBER_OF_ROWS=200;const TabUiState={NO_LONG_TAIL:0,HIDING_LONG_TAIL:1,SHOWING_LONG_TAIL:2,};function EmptyFillerColumn(){}
+EmptyFillerColumn.prototype={title:'',value(){return'';},};Polymer({is:'tr-ui-a-memory-dump-heap-details-breakdown-view',behaviors:[tr.ui.analysis.RebuildableBehavior],created(){this.displayedNode_=undefined;this.dimensionToTab_=new Map();},ready(){this.scheduleRebuild_();this.root.addEventListener('keydown',this.onKeyDown_.bind(this),true);},get displayedNode(){return this.displayedNode_;},set displayedNode(node){this.displayedNode_=node;this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;for(const tab of this.$.tabs.tabs){tab.aggregationMode=aggregationMode;}},onRebuild_(){const previouslySelectedTab=this.$.tabs.selectedSubView;let previouslySelectedTabFocused=false;let previouslySelectedDimension=undefined;if(previouslySelectedTab){previouslySelectedTabFocused=previouslySelectedTab.isFocused;previouslySelectedDimension=previouslySelectedTab.dimension;}
+for(const tab of this.$.tabs.tabs){tab.nodes=undefined;}
+this.$.tabs.clearSubViews();if(this.displayedNode_===undefined){this.$.tabs.label='No heap node provided.';return;}
+for(const[dimension,children]of this.displayedNode_.childNodes){if(!this.dimensionToTab_.has(dimension)){this.dimensionToTab_.set(dimension,document.createElement('tr-ui-a-memory-dump-heap-details-breakdown-view-tab'));}
+const tab=this.dimensionToTab_.get(dimension);tab.aggregationMode=this.aggregationMode_;tab.dimension=dimension;tab.nodes=children;this.$.tabs.addSubView(tab);tab.rebuild();if(dimension===previouslySelectedDimension){this.$.tabs.selectedSubView=tab;if(previouslySelectedTabFocused){tab.focus();}}}
+if(this.$.tabs.tabs.length>0){this.$.tabs.label='Break selected node further by:';}else{this.$.tabs.label='Selected node cannot be broken down any further.';}},onKeyDown_(keyEvent){if(!this.displayedNode_)return;let keyHandled=false;switch(keyEvent.keyCode){case 8:{if(!this.displayedNode_.parentNode)break;const viewEvent=new tr.b.Event('enter-node');viewEvent.node=this.displayedNode_.parentNode;this.dispatchEvent(viewEvent);keyHandled=true;break;}
+case 37:case 39:{const wasFocused=this.$.tabs.selectedSubView.isFocused;keyHandled=keyEvent.keyCode===37?this.$.tabs.selectPreviousTabIfPossible():this.$.tabs.selectNextTabIfPossible();if(wasFocused&&keyHandled){this.$.tabs.selectedSubView.focus();}}}
+if(!keyHandled)return;keyEvent.stopPropagation();keyEvent.preventDefault();}});Polymer({is:'tr-ui-a-memory-dump-heap-details-breakdown-view-tab',behaviors:[tr.ui.analysis.RebuildableBehavior],created(){this.dimension_=undefined;this.nodes_=undefined;this.aggregationMode_=undefined;this.displayLongTail_=false;},ready(){this.$.table.addEventListener('step-into',function(tableEvent){const viewEvent=new tr.b.Event('enter-node');viewEvent.node=tableEvent.tableRow;this.dispatchEvent(viewEvent);}.bind(this));},get displayLongTail(){return this.displayLongTail_;},set displayLongTail(newValue){if(this.displayLongTail===newValue)return;this.displayLongTail_=newValue;this.scheduleRebuild_();},get dimension(){return this.dimension_;},set dimension(dimension){this.dimension_=dimension;this.scheduleRebuild_();},get nodes(){return this.nodes_;},set nodes(nodes){this.nodes_=nodes;this.scheduleRebuild_();},get nodes(){return this.nodes_||[];},get dimensionLabel_(){if(this.dimension_===undefined)return'(undefined)';return this.dimension_.label;},get tabLabel(){let nodeCount=0;if(this.nodes_){nodeCount=this.nodes_.length;}
+return this.dimensionLabel_+' ('+nodeCount+')';},get tabIcon(){if(this.dimension_===undefined||this.dimension_===tr.ui.analysis.HeapDetailsRowDimension.ROOT){return undefined;}
+return{text:this.dimension_.symbol,style:'color: '+tr.b.ColorScheme.getColorForReservedNameAsString(this.dimension_.color)+';'};},get aggregationMode(){return this.aggregationMode_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},focus(){this.$.table.focus();},blur(){this.$.table.blur();},get isFocused(){return this.$.table.isFocused;},onRebuild_(){this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;this.$.table.emptyValue='Cannot break down by '+
+this.dimensionLabel_.toLowerCase()+' any further.';const[state,rows]=this.getRows_();const total=this.nodes.length;const displayed=rows.length;const hidden=total-displayed;this.updateInfoBar_(state,[total,displayed,hidden]);this.$.table.tableRows=rows;this.$.table.tableColumns=this.createColumns_(rows);if(this.$.table.sortColumnIndex===undefined){this.$.table.sortColumnIndex=0;this.$.table.sortDescending=false;}
+this.$.table.rebuild();},createColumns_(rows){const titleColumn=new tr.ui.analysis.HeapDetailsTitleColumn(this.dimensionLabel_);titleColumn.width='400px';const numericColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'cells',aggregationMode:this.aggregationMode_,rules:tr.ui.analysis.HEAP_DETAILS_COLUMN_RULES,shouldSetContextGroup:true});if(numericColumns.length===0){numericColumns.push(new EmptyFillerColumn());}
+tr.ui.analysis.MemoryColumn.spaceEqually(numericColumns);const columns=[titleColumn].concat(numericColumns);return columns;},getRows_(){let rows=this.nodes;if(rows.length<=RESONABLE_NUMBER_OF_ROWS){return[TabUiState.NO_LONG_TAIL,rows];}else if(this.displayLongTail){return[TabUiState.SHOWING_LONG_TAIL,rows];}
+const absSize=row=>Math.max(row.cells.Size.fields[0].value);rows.sort((a,b)=>absSize(b)-absSize(a));rows=rows.slice(0,RESONABLE_NUMBER_OF_ROWS);return[TabUiState.HIDING_LONG_TAIL,rows];},updateInfoBar_(state,rowStats){if(state===TabUiState.SHOWING_LONG_TAIL){this.longTailVisibleInfoBar_(rowStats);}else if(state===TabUiState.HIDING_LONG_TAIL){this.longTailHiddenInfoBar_(rowStats);}else{this.hideInfoBar_();}},longTailVisibleInfoBar_(rowStats){const[total,visible,hidden]=rowStats;const couldHide=total-RESONABLE_NUMBER_OF_ROWS;this.$.info.message='Showing '+total+' rows. This may be slow.';this.$.info.removeAllButtons();const buttonText='Hide '+couldHide+' rows.';this.$.info.addButton(buttonText,()=>this.displayLongTail=false);this.$.info.visible=true;},longTailHiddenInfoBar_(rowStats){const[total,visible,hidden]=rowStats;this.$.info.message='Hiding the smallest '+hidden+' rows.';this.$.info.removeAllButtons();this.$.info.addButton('Show all.',()=>this.displayLongTail=true);this.$.info.visible=true;},hideInfoBar_(){this.$.info.visible=false;},});return{};});'use strict';tr.exportTo('tr.ui.analysis',function(){const DOWNWARDS_ARROW_WITH_TIP_RIGHTWARDS=String.fromCharCode(0x21B3);function HeapDetailsPathColumn(title){tr.ui.analysis.HeapDetailsTitleColumn.call(this,title);}
+HeapDetailsPathColumn.prototype={__proto__:tr.ui.analysis.HeapDetailsTitleColumn.prototype,formatTitle(row){const title=tr.ui.analysis.HeapDetailsTitleColumn.prototype.formatTitle.call(this,row);if(row.dimension===tr.ui.analysis.HeapDetailsRowDimension.ROOT){return title;}
+const arrowEl=document.createElement('span');Polymer.dom(arrowEl).textContent=DOWNWARDS_ARROW_WITH_TIP_RIGHTWARDS;arrowEl.style.paddingRight='2px';arrowEl.style.fontWeight='bold';arrowEl.style.color=tr.b.ColorScheme.getColorForReservedNameAsString('heap_dump_child_node_arrow');const rowEl=document.createElement('span');Polymer.dom(rowEl).appendChild(arrowEl);Polymer.dom(rowEl).appendChild(tr.ui.b.asHTMLOrTextNode(title));return rowEl;}};Polymer({is:'tr-ui-a-memory-dump-heap-details-path-view',behaviors:[tr.ui.analysis.RebuildableBehavior],created(){this.selectedNode_=undefined;this.aggregationMode_=undefined;},ready(){this.$.table.addEventListener('selection-changed',function(event){this.selectedNode_=this.$.table.selectedTableRow;this.didSelectedNodeChange_();}.bind(this));},didSelectedNodeChange_(){this.dispatchEvent(new tr.b.Event('selected-node-changed'));},get selectedNode(){return this.selectedNode_;},set selectedNode(node){this.selectedNode_=node;this.didSelectedNodeChange_();this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},onRebuild_(){if(this.selectedNode_===undefined){this.$.table.clear();return;}
+if(this.$.table.tableRows.includes(this.selectedNode_)){this.$.table.selectedTableRow=this.selectedNode_;return;}
+this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;this.$.table.userCanModifySortOrder=false;const rows=this.createRows_(this.selectedNode_);this.$.table.tableRows=rows;this.$.table.tableColumns=this.createColumns_(rows);this.$.table.selectedTableRow=rows[rows.length-1];},createRows_(node){const rows=[];while(node){rows.push(node);node=node.parentNode;}
+rows.reverse();return rows;},createColumns_(rows){const titleColumn=new HeapDetailsPathColumn('Current path');titleColumn.width='200px';const numericColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'cells',aggregationMode:this.aggregationMode_,rules:tr.ui.analysis.HEAP_DETAILS_COLUMN_RULES,shouldSetContextGroup:true});tr.ui.analysis.MemoryColumn.spaceEqually(numericColumns);return[titleColumn].concat(numericColumns);}});return{};});'use strict';tr.exportTo('tr.ui.analysis',function(){const StackedPaneImpl={set childPaneBuilder(childPaneBuilder){this.childPaneBuilder_=childPaneBuilder;this.dispatchEvent(new tr.b.Event('request-child-pane-change'));},get childPaneBuilder(){return this.childPaneBuilder_;},appended(){this.rebuild();}};const StackedPane=[tr.ui.analysis.RebuildableBehavior,StackedPaneImpl];return{StackedPane,};});Polymer({is:'tr-ui-a-stacked-pane',behaviors:[tr.ui.analysis.StackedPane]});'use strict';tr.exportTo('tr.ui.analysis',function(){const Scalar=tr.b.Scalar;const sizeInBytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const count_smallerIsBetter=tr.b.Unit.byName.count_smallerIsBetter;const MultiDimensionalViewBuilder=tr.b.MultiDimensionalViewBuilder;const TotalState=tr.b.MultiDimensionalViewNode.TotalState;function HeapDumpTreeNode(stackFrameNodes,dimension,title,heavyView,parentNode){this.dimension=dimension;this.title=title;this.parentNode=parentNode;this.heavyView_=heavyView;this.stackFrameNodes_=stackFrameNodes;this.lazyCells_=undefined;this.lazyChildNodes_=undefined;}
+HeapDumpTreeNode.prototype={get minDisplayedTotalState_(){if(this.heavyView_){return TotalState.LOWER_BOUND;}
+return TotalState.EXACT;},get childNodes(){if(!this.lazyChildNodes_){this.lazyChildNodes_=new Map();this.addDimensionChildNodes_(tr.ui.analysis.HeapDetailsRowDimension.STACK_FRAME,0);this.addDimensionChildNodes_(tr.ui.analysis.HeapDetailsRowDimension.OBJECT_TYPE,1);this.releaseStackFrameNodesIfPossible_();}
+return this.lazyChildNodes_;},get cells(){if(!this.lazyCells_){this.addCells_();this.releaseStackFrameNodesIfPossible_();}
+return this.lazyCells_;},releaseStackFrameNodesIfPossible_(){if(this.lazyCells_&&this.lazyChildNodes_){this.stackFrameNodes_=undefined;}},addDimensionChildNodes_(dimension,dimensionIndex){const dimensionChildTitleToStackFrameNodes=tr.b.invertArrayOfDicts(this.stackFrameNodes_,node=>this.convertStackFrameNodeDimensionToChildDict_(node,dimensionIndex));const dimensionChildNodes=[];for(const[childTitle,childStackFrameNodes]of
+Object.entries(dimensionChildTitleToStackFrameNodes)){dimensionChildNodes.push(new HeapDumpTreeNode(childStackFrameNodes,dimension,childTitle,this.heavyView_,this));}
+this.lazyChildNodes_.set(dimension,dimensionChildNodes);},convertStackFrameNodeDimensionToChildDict_(stackFrameNode,dimensionIndex){const childDict={};let displayedChildrenTotalSize=0;let displayedChildrenTotalCount=0;let hasDisplayedChildren=false;let allDisplayedChildrenHaveDisplayedCounts=true;for(const child of stackFrameNode.children[dimensionIndex].values()){if(child.values[0].totalState<this.minDisplayedTotalState_){continue;}
+if(child.values[1].totalState<this.minDisplayedTotalState_){allDisplayedChildrenHaveDisplayedCounts=false;}
+childDict[child.title[dimensionIndex]]=child;displayedChildrenTotalSize+=child.values[0].total;displayedChildrenTotalCount+=child.values[1].total;hasDisplayedChildren=true;}
+const nodeTotalSize=stackFrameNode.values[0].total;const nodeTotalCount=stackFrameNode.values[1].total;const hasUnclassifiedSizeOrCount=displayedChildrenTotalSize<nodeTotalSize||displayedChildrenTotalCount<nodeTotalCount;if(!this.heavyView_&&hasUnclassifiedSizeOrCount&&hasDisplayedChildren){const otherTitle=stackFrameNode.title.slice();otherTitle[dimensionIndex]='<other>';const otherNode=new tr.b.MultiDimensionalViewNode(otherTitle,2);childDict[otherTitle[dimensionIndex]]=otherNode;otherNode.values[0].total=nodeTotalSize-displayedChildrenTotalSize;otherNode.values[0].totalState=this.minDisplayedTotalState_;otherNode.values[1].total=nodeTotalCount-displayedChildrenTotalCount;otherNode.values[1].totalState=allDisplayedChildrenHaveDisplayedCounts?this.minDisplayedTotalState_:TotalState.NOT_PROVIDED;}
+return childDict;},addCells_(){this.lazyCells_=tr.ui.analysis.createCells(this.stackFrameNodes_,function(stackFrameNode){const size=stackFrameNode.values[0].total;const numerics={'Size':new Scalar(sizeInBytes_smallerIsBetter,size)};const countValue=stackFrameNode.values[1];if(countValue.totalState>=this.minDisplayedTotalState_){const count=countValue.total;numerics.Count=new Scalar(count_smallerIsBetter,count);}
+return numerics;},this);}};Polymer({is:'tr-ui-a-memory-dump-heap-details-pane',behaviors:[tr.ui.analysis.StackedPane],created(){this.heapDumps_=undefined;this.viewMode_=undefined;this.aggregationMode_=undefined;this.cachedBuilders_=new Map();},ready(){this.$.info_bar.message='Note: Values displayed in the heavy view '+'are lower bounds (except for the root).';Polymer.dom(this.$.view_mode_container).appendChild(tr.ui.b.createSelector(this,'viewMode','memoryDumpHeapDetailsPane.viewMode',MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW,[{label:'Top-down (Tree)',value:MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW},{label:'Top-down (Heavy)',value:MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW},{label:'Bottom-up (Heavy)',value:MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW}]));this.$.drag_handle.target=this.$.path_view;this.$.drag_handle.horizontal=false;this.$.path_view.addEventListener('selected-node-changed',(function(e){this.$.breakdown_view.displayedNode=this.$.path_view.selectedNode;}).bind(this));this.$.breakdown_view.addEventListener('enter-node',(function(e){this.$.path_view.selectedNode=e.node;}).bind(this));},set heapDumps(heapDumps){this.heapDumps_=heapDumps;this.scheduleRebuild_();},get heapDumps(){return this.heapDumps_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.$.path_view.aggregationMode=aggregationMode;this.$.breakdown_view.aggregationMode=aggregationMode;},get aggregationMode(){return this.aggregationMode_;},set viewMode(viewMode){this.viewMode_=viewMode;this.scheduleRebuild_();},get viewMode(){return this.viewMode_;},get heavyView(){switch(this.viewMode){case MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW:case MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW:return true;default:return false;}},onRebuild_(){if(this.heapDumps_===undefined||this.heapDumps_.length===0){this.$.info_text.style.display='block';this.$.split_view.style.display='none';this.$.view_mode_container.style.display='none';this.$.info_bar.hidden=true;this.$.path_view.selectedNode=undefined;return;}
+this.$.info_text.style.display='none';this.$.split_view.style.display='flex';this.$.view_mode_container.style.display='block';this.$.info_bar.hidden=!this.heavyView;this.$.path_view.selectedNode=this.createHeapTree_();this.$.path_view.rebuild();this.$.breakdown_view.rebuild();},createHeapTree_(){const definedHeapDump=this.heapDumps_.find(x=>x);if(definedHeapDump===undefined)return undefined;const rootRowTitle=definedHeapDump.allocatorName;const stackFrameTrees=this.createStackFrameTrees_(this.heapDumps_);return new HeapDumpTreeNode(stackFrameTrees,tr.ui.analysis.HeapDetailsRowDimension.ROOT,rootRowTitle,this.heavyView);},createStackFrameTrees_(heapDumps){const builders=heapDumps.map(heapDump=>this.createBuilder_(heapDump));const views=builders.map(builder=>{if(builder===undefined)return undefined;return builder.buildView(this.viewMode);});return views;},createBuilder_(heapDump){if(heapDump===undefined)return undefined;if(this.cachedBuilders_.has(heapDump)){return this.cachedBuilders_.get(heapDump);}
+const dimensions=2;const valueCount=2;const builder=new MultiDimensionalViewBuilder(dimensions,valueCount);for(const entry of heapDump.entries){const leafStackFrame=entry.leafStackFrame;const stackTracePath=leafStackFrame===undefined?[]:leafStackFrame.getUserFriendlyStackTrace().reverse();const objectTypeName=entry.objectTypeName;const objectTypeNamePath=objectTypeName===undefined?[]:[objectTypeName];const valueKind=entry.valuesAreTotals?MultiDimensionalViewBuilder.ValueKind.TOTAL:MultiDimensionalViewBuilder.ValueKind.SELF;builder.addPath([stackTracePath,objectTypeNamePath],[entry.size,entry.count],valueKind);}
+builder.complete=heapDump.isComplete;this.cachedBuilders_.set(heapDump,builder);return builder;},});return{};});'use strict';tr.exportTo('tr.ui.analysis',function(){const URL_TO_SIZE_VS_EFFECTIVE_SIZE='https://chromium.googlesource.com/chromium/src/+/master/docs/memory-infra/README.md#effective_size-vs_size';const SUBALLOCATION_CONTEXT=true;const MemoryAllocatorDumpInfoType=tr.model.MemoryAllocatorDumpInfoType;const PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN;const PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER=MemoryAllocatorDumpInfoType.PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER;const LEFTWARDS_OPEN_HEADED_ARROW=String.fromCharCode(0x21FD);const RIGHTWARDS_OPEN_HEADED_ARROW=String.fromCharCode(0x21FE);const EN_DASH=String.fromCharCode(0x2013);const CIRCLED_LATIN_SMALL_LETTER_I=String.fromCharCode(0x24D8);function AllocatorDumpNameColumn(){tr.ui.analysis.TitleColumn.call(this,'Component');}
+AllocatorDumpNameColumn.prototype={__proto__:tr.ui.analysis.TitleColumn.prototype,formatTitle(row){if(!row.suballocation){return row.title;}
+return tr.ui.b.createSpan({textContent:row.title,italic:true,tooltip:row.fullNames===undefined?undefined:row.fullNames.join(', ')});}};function getAndUpdateEntry(map,name,createdCallback){let entry=map.get(name);if(entry===undefined){entry={count:0};createdCallback(entry);map.set(name,entry);}
+entry.count++;return entry;}
+function SizeInfoMessageBuilder(){this.parts_=[];this.indent_=0;}
+SizeInfoMessageBuilder.prototype={append(){this.parts_.push.apply(this.parts_,Array.prototype.slice.apply(arguments));},appendMap(map,hasPluralSuffix,emptyText,itemCallback,opt_this){opt_this=opt_this||this;if(map.size===0){if(emptyText){this.append(emptyText);}}else if(map.size===1){this.parts_.push(' ');const key=map.keys().next().value;itemCallback.call(opt_this,key,map.get(key));}else{if(hasPluralSuffix){this.parts_.push('s');}
+this.parts_.push(':');this.indent_++;for(const key of map.keys()){this.parts_.push('\n',' '.repeat(3*(this.indent_-1)),' - ');itemCallback.call(opt_this,key,map.get(key));}
+this.indent_--;}},appendImportanceRange(range){this.append(' (importance: ');if(range.min===range.max){this.append(range.min);}else{this.append(range.min,EN_DASH,range.max);}
+this.append(')');},appendSizeIfDefined(size){if(size!==undefined){this.append(' (',tr.b.Unit.byName.sizeInBytes.format(size),')');}},appendSomeTimestampsQuantifier(){this.append(' ',tr.ui.analysis.MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER);},build(){return this.parts_.join('');}};function EffectiveSizeColumn(name,cellPath,aggregationMode){tr.ui.analysis.DetailsNumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+EffectiveSizeColumn.prototype={__proto__:tr.ui.analysis.DetailsNumericMemoryColumn.prototype,get title(){return tr.ui.b.createLink({textContent:this.name,tooltip:'Memory used by this component',href:URL_TO_SIZE_VS_EFFECTIVE_SIZE});},addInfos(numerics,memoryAllocatorDumps,infos){if(memoryAllocatorDumps===undefined)return;const ownerNameToEntry=new Map();const ownedNameToEntry=new Map();for(let i=0;i<numerics.length;i++){if(numerics[i]===undefined)continue;const dump=memoryAllocatorDumps[i];if(dump===SUBALLOCATION_CONTEXT){return;}
+dump.ownedBy.forEach(function(ownerLink){const ownerDump=ownerLink.source;this.getAndUpdateOwnershipEntry_(ownerNameToEntry,ownerDump,ownerLink);},this);const ownedLink=dump.owns;if(ownedLink!==undefined){const ownedDump=ownedLink.target;const ownedEntry=this.getAndUpdateOwnershipEntry_(ownedNameToEntry,ownedDump,ownedLink,true);const sharerNameToEntry=ownedEntry.sharerNameToEntry;ownedDump.ownedBy.forEach(function(sharerLink){const sharerDump=sharerLink.source;if(sharerDump===dump)return;this.getAndUpdateOwnershipEntry_(sharerNameToEntry,sharerDump,sharerLink);},this);}}
+if(ownerNameToEntry.size>0){const messageBuilder=new SizeInfoMessageBuilder();messageBuilder.append('shared by');messageBuilder.appendMap(ownerNameToEntry,false,undefined,function(ownerName,ownerEntry){messageBuilder.append(ownerName);if(ownerEntry.count<numerics.length){messageBuilder.appendSomeTimestampsQuantifier();}
+messageBuilder.appendImportanceRange(ownerEntry.importanceRange);},this);infos.push({message:messageBuilder.build(),icon:LEFTWARDS_OPEN_HEADED_ARROW,color:'green'});}
+if(ownedNameToEntry.size>0){const messageBuilder=new SizeInfoMessageBuilder();messageBuilder.append('shares');messageBuilder.appendMap(ownedNameToEntry,false,undefined,function(ownedName,ownedEntry){messageBuilder.append(ownedName);const ownedCount=ownedEntry.count;if(ownedCount<numerics.length){messageBuilder.appendSomeTimestampsQuantifier();}
+messageBuilder.appendImportanceRange(ownedEntry.importanceRange);messageBuilder.append(' with');messageBuilder.appendMap(ownedEntry.sharerNameToEntry,false,' no other dumps',function(sharerName,sharerEntry){messageBuilder.append(sharerName);if(sharerEntry.count<ownedCount){messageBuilder.appendSomeTimestampsQuantifier();}
+messageBuilder.appendImportanceRange(sharerEntry.importanceRange);},this);},this);infos.push({message:messageBuilder.build(),icon:RIGHTWARDS_OPEN_HEADED_ARROW,color:'green'});}},getAndUpdateOwnershipEntry_(map,dump,link,opt_withSharerNameToEntry){const entry=getAndUpdateEntry(map,dump.quantifiedName,function(newEntry){newEntry.importanceRange=new tr.b.math.Range();if(opt_withSharerNameToEntry){newEntry.sharerNameToEntry=new Map();}});entry.importanceRange.addValue(link.importance||0);return entry;}};function SizeColumn(name,cellPath,aggregationMode){tr.ui.analysis.DetailsNumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+SizeColumn.prototype={__proto__:tr.ui.analysis.DetailsNumericMemoryColumn.prototype,get title(){return tr.ui.b.createLink({textContent:this.name,tooltip:'Memory requested by this component',href:URL_TO_SIZE_VS_EFFECTIVE_SIZE});},addInfos(numerics,memoryAllocatorDumps,infos){if(memoryAllocatorDumps===undefined)return;this.addOverlapInfo_(numerics,memoryAllocatorDumps,infos);this.addProvidedSizeWarningInfos_(numerics,memoryAllocatorDumps,infos);},addOverlapInfo_(numerics,memoryAllocatorDumps,infos){const siblingNameToEntry=new Map();for(let i=0;i<numerics.length;i++){if(numerics[i]===undefined)continue;const dump=memoryAllocatorDumps[i];if(dump===SUBALLOCATION_CONTEXT){return;}
+const ownedBySiblingSizes=dump.ownedBySiblingSizes;for(const siblingDump of ownedBySiblingSizes.keys()){const siblingName=siblingDump.name;getAndUpdateEntry(siblingNameToEntry,siblingName,function(newEntry){if(numerics.length===1){newEntry.size=ownedBySiblingSizes.get(siblingDump);}});}}
+if(siblingNameToEntry.size>0){const messageBuilder=new SizeInfoMessageBuilder();messageBuilder.append('overlaps with its sibling');messageBuilder.appendMap(siblingNameToEntry,true,undefined,function(siblingName,siblingEntry){messageBuilder.append('\'',siblingName,'\'');messageBuilder.appendSizeIfDefined(siblingEntry.size);if(siblingEntry.count<numerics.length){messageBuilder.appendSomeTimestampsQuantifier();}},this);infos.push({message:messageBuilder.build(),icon:CIRCLED_LATIN_SMALL_LETTER_I,color:'blue'});}},addProvidedSizeWarningInfos_(numerics,memoryAllocatorDumps,infos){const infoTypeToEntry=new Map();for(let i=0;i<numerics.length;i++){if(numerics[i]===undefined)continue;const dump=memoryAllocatorDumps[i];if(dump===SUBALLOCATION_CONTEXT){return;}
+dump.infos.forEach(function(dumpInfo){getAndUpdateEntry(infoTypeToEntry,dumpInfo.type,function(newEntry){if(numerics.length===1){newEntry.providedSize=dumpInfo.providedSize;newEntry.dependencySize=dumpInfo.dependencySize;}});});}
+for(const infoType of infoTypeToEntry.keys()){const entry=infoTypeToEntry.get(infoType);const messageBuilder=new SizeInfoMessageBuilder();messageBuilder.append('provided size');messageBuilder.appendSizeIfDefined(entry.providedSize);let dependencyName;switch(infoType){case PROVIDED_SIZE_LESS_THAN_AGGREGATED_CHILDREN:dependencyName='the aggregated size of the children';break;case PROVIDED_SIZE_LESS_THAN_LARGEST_OWNER:dependencyName='the size of the largest owner';break;default:dependencyName='an unknown dependency';break;}
+messageBuilder.append(' was less than ',dependencyName);messageBuilder.appendSizeIfDefined(entry.dependencySize);if(entry.count<numerics.length){messageBuilder.appendSomeTimestampsQuantifier();}
+infos.push(tr.ui.analysis.createWarningInfo(messageBuilder.build()));}}};const NUMERIC_COLUMN_RULES=[{condition:tr.model.MemoryAllocatorDump.EFFECTIVE_SIZE_NUMERIC_NAME,importance:10,columnConstructor:EffectiveSizeColumn},{condition:tr.model.MemoryAllocatorDump.SIZE_NUMERIC_NAME,importance:9,columnConstructor:SizeColumn},{condition:'page_size',importance:0,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:/size/,importance:5,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{importance:0,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn}];const DIAGNOSTIC_COLUMN_RULES=[{importance:0,columnConstructor:tr.ui.analysis.StringMemoryColumn}];Polymer({is:'tr-ui-a-memory-dump-allocator-details-pane',behaviors:[tr.ui.analysis.StackedPane],created(){this.memoryAllocatorDumps_=undefined;this.heapDumps_=undefined;this.aggregationMode_=undefined;},ready(){this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;},set memoryAllocatorDumps(memoryAllocatorDumps){this.memoryAllocatorDumps_=memoryAllocatorDumps;this.scheduleRebuild_();},get memoryAllocatorDumps(){return this.memoryAllocatorDumps_;},set heapDumps(heapDumps){this.heapDumps_=heapDumps;this.scheduleRebuild_();},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},onRebuild_(){if(this.memoryAllocatorDumps_===undefined||this.memoryAllocatorDumps_.length===0){this.$.info_text.style.display='block';this.$.table.style.display='none';this.$.table.clear();this.$.table.rebuild();this.childPaneBuilder=undefined;return;}
+this.$.info_text.style.display='none';this.$.table.style.display='block';const rows=this.createRows_();const columns=this.createColumns_(rows);rows.forEach(function(rootRow){tr.ui.analysis.aggregateTableRowCellsRecursively(rootRow,columns,function(contexts){return contexts!==undefined&&contexts.some(function(context){return context===SUBALLOCATION_CONTEXT;});});});this.$.table.tableRows=rows;this.$.table.tableColumns=columns;this.$.table.rebuild();tr.ui.analysis.expandTableRowsRecursively(this.$.table);if(this.heapDumps_===undefined){this.childPaneBuilder=undefined;}else{this.childPaneBuilder=function(){const pane=document.createElement('tr-ui-a-memory-dump-heap-details-pane');pane.heapDumps=this.heapDumps_;pane.aggregationMode=this.aggregationMode_;return pane;}.bind(this);}},createRows_(){return[this.createAllocatorRowRecursively_(this.memoryAllocatorDumps_)];},createAllocatorRowRecursively_(dumps){const definedDump=dumps.find(x=>x);const title=definedDump.name;const fullName=definedDump.fullName;const numericCells=tr.ui.analysis.createCells(dumps,function(dump){return dump.numerics;});const diagnosticCells=tr.ui.analysis.createCells(dumps,function(dump){return dump.diagnostics;});let suballocatedBy=undefined;if(title.startsWith('__')){for(let i=0;i<dumps.length;i++){const dump=dumps[i];if(dump===undefined||dump.ownedBy.length===0){continue;}
+const ownerDump=dump.ownedBy[0].source;if(dump.ownedBy.length>1||dump.children.length>0||ownerDump.containerMemoryDump!==dump.containerMemoryDump){suballocatedBy=undefined;break;}
+if(suballocatedBy===undefined){suballocatedBy=ownerDump.fullName;}else if(suballocatedBy!==ownerDump.fullName){suballocatedBy=undefined;break;}}}
+const row={title,fullNames:[fullName],contexts:dumps,numericCells,diagnosticCells,suballocatedBy};const childDumpNameToDumps=tr.b.invertArrayOfDicts(dumps,function(dump){const results={};for(const child of dump.children){results[child.name]=child;}
+return results;});const subRows=[];let suballocationClassificationRootNode=undefined;for(const childDumps of Object.values(childDumpNameToDumps)){const childRow=this.createAllocatorRowRecursively_(childDumps);if(childRow.suballocatedBy===undefined){subRows.push(childRow);}else{suballocationClassificationRootNode=this.classifySuballocationRow_(childRow,suballocationClassificationRootNode);}}
+if(suballocationClassificationRootNode!==undefined){const suballocationRow=this.createSuballocationRowRecursively_('suballocations',suballocationClassificationRootNode);subRows.push(suballocationRow);}
+if(subRows.length>0){row.subRows=subRows;}
+return row;},classifySuballocationRow_(suballocationRow,rootNode){if(rootNode===undefined){rootNode={children:{},row:undefined};}
+const suballocationLevels=suballocationRow.suballocatedBy.split('/');let currentNode=rootNode;for(let i=0;i<suballocationLevels.length;i++){const suballocationLevel=suballocationLevels[i];let nextNode=currentNode.children[suballocationLevel];if(nextNode===undefined){currentNode.children[suballocationLevel]=nextNode={children:{},row:undefined};}
+currentNode=nextNode;}
+const existingRow=currentNode.row;if(existingRow!==undefined){for(let i=0;i<suballocationRow.contexts.length;i++){const newContext=suballocationRow.contexts[i];if(newContext===undefined)continue;if(existingRow.contexts[i]!==undefined){throw new Error('Multiple suballocations with the same owner name');}
+existingRow.contexts[i]=newContext;['numericCells','diagnosticCells'].forEach(function(cellKey){const suballocationCells=suballocationRow[cellKey];if(suballocationCells===undefined)return;for(const[cellName,cell]of Object.entries(suballocationCells)){if(cell===undefined)continue;const fields=cell.fields;if(fields===undefined)continue;const field=fields[i];if(field===undefined)continue;let existingCells=existingRow[cellKey];if(existingCells===undefined){existingCells={};existingRow[cellKey]=existingCells;}
+let existingCell=existingCells[cellName];if(existingCell===undefined){existingCell=new tr.ui.analysis.MemoryCell(new Array(fields.length));existingCells[cellName]=existingCell;}
+existingCell.fields[i]=field;}});}
+existingRow.fullNames.push.apply(existingRow.fullNames,suballocationRow.fullNames);}else{currentNode.row=suballocationRow;}
+return rootNode;},createSuballocationRowRecursively_(name,node){const childCount=Object.keys(node.children).length;if(childCount===0){if(node.row===undefined){throw new Error('Suballocation node must have a row or children');}
+const row=node.row;row.title=name;row.suballocation=true;return row;}
+const subRows=[];for(const[subName,subNode]of Object.entries(node.children)){subRows.push(this.createSuballocationRowRecursively_(subName,subNode));}
+if(node.row!==undefined){const row=node.row;row.title='<unspecified>';row.suballocation=true;subRows.unshift(row);}
+const contexts=new Array(subRows[0].contexts.length);for(let i=0;i<subRows.length;i++){subRows[i].contexts.forEach(function(subContext,index){if(subContext!==undefined){contexts[index]=SUBALLOCATION_CONTEXT;}});}
+return{title:name,suballocation:true,contexts,subRows};},createColumns_(rows){const titleColumn=new AllocatorDumpNameColumn();titleColumn.width='200px';const numericColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'numericCells',aggregationMode:this.aggregationMode_,rules:NUMERIC_COLUMN_RULES});const diagnosticColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'diagnosticCells',aggregationMode:this.aggregationMode_,rules:DIAGNOSTIC_COLUMN_RULES});const fieldColumns=numericColumns.concat(diagnosticColumns);tr.ui.analysis.MemoryColumn.spaceEqually(fieldColumns);const columns=[titleColumn].concat(fieldColumns);return columns;}});return{SUBALLOCATION_CONTEXT,AllocatorDumpNameColumn,EffectiveSizeColumn,SizeColumn,};});'use strict';tr.exportTo('tr.ui.analysis',function(){const Scalar=tr.b.Scalar;const sizeInBytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const CONSTANT_COLUMN_RULES=[{condition:'Start address',importance:0,columnConstructor:tr.ui.analysis.StringMemoryColumn}];const VARIABLE_COLUMN_RULES=[{condition:'Virtual size',importance:7,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Protection flags',importance:6,columnConstructor:tr.ui.analysis.StringMemoryColumn},{condition:'PSS',importance:5,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Private dirty',importance:4,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Private clean',importance:3,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Shared dirty',importance:2,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Shared clean',importance:1,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn},{condition:'Swapped',importance:0,columnConstructor:tr.ui.analysis.DetailsNumericMemoryColumn}];const BYTE_STAT_COLUMN_MAP={'proportionalResident':'PSS','privateDirtyResident':'Private dirty','privateCleanResident':'Private clean','sharedDirtyResident':'Shared dirty','sharedCleanResident':'Shared clean','swapped':'Swapped'};function hexString(address,is64BitAddress){if(address===undefined)return undefined;const hexPadding=is64BitAddress?'0000000000000000':'00000000';return(hexPadding+address.toString(16)).substr(-hexPadding.length);}
+function pruneEmptyRuleRows(row){if(row.subRows===undefined||row.subRows.length===0)return;if(row.subRows[0].rule===undefined){return;}
+row.subRows.forEach(pruneEmptyRuleRows);row.subRows=row.subRows.filter(function(subRow){return subRow.subRows.length>0;});}
+Polymer({is:'tr-ui-a-memory-dump-vm-regions-details-pane',behaviors:[tr.ui.analysis.StackedPane],created(){this.vmRegions_=undefined;this.aggregationMode_=undefined;},ready(){this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;},set vmRegions(vmRegions){this.vmRegions_=vmRegions;this.scheduleRebuild_();},get vmRegions(){return this.vmRegions_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},onRebuild_(){if(this.vmRegions_===undefined||this.vmRegions_.length===0){this.$.info_text.style.display='block';this.$.table.style.display='none';this.$.table.clear();this.$.table.rebuild();return;}
+this.$.info_text.style.display='none';this.$.table.style.display='block';const rows=this.createRows_(this.vmRegions_);const columns=this.createColumns_(rows);this.$.table.tableRows=rows;this.$.table.tableColumns=columns;this.$.table.rebuild();tr.ui.analysis.expandTableRowsRecursively(this.$.table);},createRows_(timeToVmRegionTree){const is64BitAddress=timeToVmRegionTree.some(function(vmRegionTree){if(vmRegionTree===undefined)return false;return vmRegionTree.someRegion(function(region){if(region.startAddress===undefined)return false;return region.startAddress>=4294967296;});});return[this.createClassificationNodeRow(timeToVmRegionTree,is64BitAddress)];},createClassificationNodeRow(timeToNode,is64BitAddress){const definedNode=timeToNode.find(x=>x);const childNodeIdToTimeToNode=Object.values(tr.b.invertArrayOfDicts(timeToNode,function(node){const children=node.children;if(children===undefined)return undefined;const childMap={};children.forEach(function(childNode){if(!childNode.hasRegions)return;childMap[childNode.title]=childNode;});return childMap;}));const childNodeSubRows=childNodeIdToTimeToNode.map(function(timeToChildNode){return this.createClassificationNodeRow(timeToChildNode,is64BitAddress);},this);const regionIdToTimeToRegion=Object.values(tr.b.invertArrayOfDicts(timeToNode,function(node){const regions=node.regions;if(regions===undefined)return undefined;const results={};for(const region of regions){results[region.uniqueIdWithinProcess]=region;}
+return results;}));const regionSubRows=regionIdToTimeToRegion.map(function(timeToRegion){return this.createRegionRow_(timeToRegion,is64BitAddress);},this);const subRows=childNodeSubRows.concat(regionSubRows);return{title:definedNode.title,contexts:timeToNode,variableCells:this.createVariableCells_(timeToNode),subRows};},createRegionRow_(timeToRegion,is64BitAddress){const definedRegion=timeToRegion.find(x=>x);return{title:definedRegion.mappedFile,contexts:timeToRegion,constantCells:this.createConstantCells_(definedRegion,is64BitAddress),variableCells:this.createVariableCells_(timeToRegion)};},createConstantCells_(definedRegion,is64BitAddress){return tr.ui.analysis.createCells([definedRegion],function(region){const startAddress=region.startAddress;if(startAddress===undefined)return undefined;return{'Start address':hexString(startAddress,is64BitAddress)};});},createVariableCells_(timeToRegion){return tr.ui.analysis.createCells(timeToRegion,function(region){const fields={};const sizeInBytes=region.sizeInBytes;if(sizeInBytes!==undefined){fields['Virtual size']=new Scalar(sizeInBytes_smallerIsBetter,sizeInBytes);}
+const protectionFlags=region.protectionFlagsToString;if(protectionFlags!==undefined){fields['Protection flags']=protectionFlags;}
+for(const[byteStatName,columnName]of
+Object.entries(BYTE_STAT_COLUMN_MAP)){const byteStat=region.byteStats[byteStatName];if(byteStat===undefined)continue;fields[columnName]=new Scalar(sizeInBytes_smallerIsBetter,byteStat);}
+return fields;});},createColumns_(rows){const titleColumn=new tr.ui.analysis.TitleColumn('Mapped file');titleColumn.width='200px';const constantColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'constantCells',aggregationMode:undefined,rules:CONSTANT_COLUMN_RULES});const variableColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'variableCells',aggregationMode:this.aggregationMode_,rules:VARIABLE_COLUMN_RULES});const fieldColumns=constantColumns.concat(variableColumns);tr.ui.analysis.MemoryColumn.spaceEqually(fieldColumns);const columns=[titleColumn].concat(fieldColumns);return columns;}});return{};});'use strict';Polymer({is:'tr-ui-b-color-legend',ready(){const blackSquareCharCode=9632;this.$.square.innerText=String.fromCharCode(blackSquareCharCode);this.label_=undefined;this.compoundEventSelectionState_=tr.model.CompoundEventSelectionState.NOT_SELECTED;},set compoundEventSelectionState(compoundEventSelectionState){this.compoundEventSelectionState_=compoundEventSelectionState;},get label(){return this.label_;},set label(label){if(label===undefined){this.setLabelAndColorId(undefined,undefined);return;}
+const colorId=tr.b.ColorScheme.getColorIdForGeneralPurposeString(label);this.setLabelAndColorId(label,colorId);},setLabelAndColorId(label,colorId){this.label_=label;Polymer.dom(this.$.label).textContent='';Polymer.dom(this.$.label).appendChild(tr.ui.b.asHTMLOrTextNode(label));if(colorId===undefined){this.$.square.style.color='initial';}else{this.$.square.style.color=tr.b.ColorScheme.colorsAsStrings[colorId];}}});'use strict';Polymer({is:'tr-ui-b-view-specific-brushing-state',get viewId(){return this.getAttribute('view-id');},set viewId(viewId){Polymer.dom(this).setAttribute('view-id',viewId);},get(){const viewId=this.viewId;if(!viewId){throw new Error('Element must have a view-id attribute!');}
+const brushingStateController=tr.c.BrushingStateController.getControllerForElement(this);if(!brushingStateController)return undefined;return brushingStateController.getViewSpecificBrushingState(viewId);},set(state){const viewId=this.viewId;if(!viewId){throw new Error('Element must have a view-id attribute!');}
+const brushingStateController=tr.c.BrushingStateController.getControllerForElement(this);if(!brushingStateController)return;brushingStateController.changeViewSpecificBrushingState(viewId,state);}});'use strict';tr.exportTo('tr.ui.analysis',function(){const MemoryColumnColorScheme=tr.b.MemoryColumnColorScheme;const Scalar=tr.b.Scalar;const sizeInBytes_smallerIsBetter=tr.b.Unit.byName.sizeInBytes_smallerIsBetter;const PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX='_bytes';const DISPLAYED_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;const SOME_TIMESTAMPS_INFO_QUANTIFIER=tr.ui.analysis.MemoryColumn.SOME_TIMESTAMPS_INFO_QUANTIFIER;const RIGHTWARDS_ARROW_WITH_HOOK=String.fromCharCode(0x21AA);const RIGHTWARDS_ARROW_FROM_BAR=String.fromCharCode(0x21A6);const GREATER_THAN_OR_EQUAL_TO=String.fromCharCode(0x2265);const UNMARRIED_PARTNERSHIP_SYMBOL=String.fromCharCode(0x26AF);const TRIGRAM_FOR_HEAVEN=String.fromCharCode(0x2630);function lazyMap(list,fn,opt_this){opt_this=opt_this||this;let result=undefined;list.forEach(function(item,index){const value=fn.call(opt_this,item,index);if(value===undefined)return;if(result===undefined){result=new Array(list.length);}
+result[index]=value;});return result;}
+function ProcessNameColumn(){tr.ui.analysis.TitleColumn.call(this,'Process');}
+ProcessNameColumn.prototype={__proto__:tr.ui.analysis.TitleColumn.prototype,formatTitle(row){if(row.contexts===undefined){return row.title;}
+const titleEl=document.createElement('tr-ui-b-color-legend');titleEl.label=row.title;return titleEl;}};function UsedMemoryColumn(name,cellPath,aggregationMode){tr.ui.analysis.NumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+UsedMemoryColumn.COLOR=MemoryColumnColorScheme.getColor('used_memory_column').toString();UsedMemoryColumn.OLDER_COLOR=MemoryColumnColorScheme.getColor('older_used_memory_column').toString();UsedMemoryColumn.prototype={__proto__:tr.ui.analysis.NumericMemoryColumn.prototype,get title(){return tr.ui.b.createSpan({textContent:this.name,color:UsedMemoryColumn.COLOR});},getFormattingContext(unit){return{unitPrefix:tr.b.UnitPrefixScale.BINARY.MEBI};},color(numerics,processMemoryDumps){return UsedMemoryColumn.COLOR;},getChildPaneBuilder(processMemoryDumps){if(processMemoryDumps===undefined)return undefined;const vmRegions=lazyMap(processMemoryDumps,function(pmd){if(pmd===undefined)return undefined;return pmd.mostRecentVmRegions;});if(vmRegions===undefined)return undefined;return function(){const pane=document.createElement('tr-ui-a-memory-dump-vm-regions-details-pane');pane.vmRegions=vmRegions;pane.aggregationMode=this.aggregationMode;return pane;}.bind(this);}};function PeakMemoryColumn(name,cellPath,aggregationMode){UsedMemoryColumn.call(this,name,cellPath,aggregationMode);}
+PeakMemoryColumn.prototype={__proto__:UsedMemoryColumn.prototype,addInfos(numerics,processMemoryDumps,infos){if(processMemoryDumps===undefined)return;let resettableValueCount=0;let nonResettableValueCount=0;for(let i=0;i<numerics.length;i++){if(numerics[i]===undefined)continue;if(processMemoryDumps[i].arePeakResidentBytesResettable){resettableValueCount++;}else{nonResettableValueCount++;}}
+if(resettableValueCount>0&&nonResettableValueCount>0){infos.push(tr.ui.analysis.createWarningInfo('Both resettable and '+'non-resettable peak RSS values were provided by the process'));}else if(resettableValueCount>0){infos.push({icon:RIGHTWARDS_ARROW_WITH_HOOK,message:'Peak RSS since previous memory dump.'});}else{infos.push({icon:RIGHTWARDS_ARROW_FROM_BAR,message:'Peak RSS since process startup. Finer grained '+'peaks require a Linux kernel version '+
+GREATER_THAN_OR_EQUAL_TO+' 4.0.'});}}};function ByteStatColumn(name,cellPath,aggregationMode){UsedMemoryColumn.call(this,name,cellPath,aggregationMode);}
+ByteStatColumn.prototype={__proto__:UsedMemoryColumn.prototype,color(numerics,processMemoryDumps){if(processMemoryDumps===undefined){return UsedMemoryColumn.COLOR;}
+const allOlderValues=processMemoryDumps.every(function(processMemoryDump){if(processMemoryDump===undefined)return true;return!processMemoryDump.hasOwnVmRegions;});if(allOlderValues){return UsedMemoryColumn.OLDER_COLOR;}
+return UsedMemoryColumn.COLOR;},addInfos(numerics,processMemoryDumps,infos){if(processMemoryDumps===undefined)return;let olderValueCount=0;for(let i=0;i<numerics.length;i++){const processMemoryDump=processMemoryDumps[i];if(processMemoryDump!==undefined&&!processMemoryDump.hasOwnVmRegions){olderValueCount++;}}
+if(olderValueCount===0){return;}
+const infoQuantifier=olderValueCount<numerics.length?' '+SOME_TIMESTAMPS_INFO_QUANTIFIER:'';infos.push({message:'Older value'+infoQuantifier+' (only heavy (purple) memory dumps contain memory maps).',icon:UNMARRIED_PARTNERSHIP_SYMBOL});}};UsedMemoryColumn.RULES=[{condition:'Total resident',importance:10,columnConstructor:UsedMemoryColumn},{condition:'Peak total resident',importance:9,columnConstructor:PeakMemoryColumn},{condition:'PSS',importance:8,columnConstructor:ByteStatColumn},{condition:'Private dirty',importance:7,columnConstructor:ByteStatColumn},{condition:'Swapped',importance:6,columnConstructor:ByteStatColumn},{importance:0,columnConstructor:UsedMemoryColumn}];UsedMemoryColumn.TOTALS_MAP={'residentBytes':'Total resident','peakResidentBytes':'Peak total resident','privateFootprintBytes':'Private footprint',};UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP={'vm':'Total virtual','swp':'Swapped','pc':'Private clean','pd':'Private dirty','sc':'Shared clean','sd':'Shared dirty','gpu_egl':'GPU EGL','gpu_egl_pss':'GPU EGL PSS','gpu_gl':'GPU GL','gpu_gl_pss':'GPU GL PSS','gpu_etc':'GPU Other','gpu_etc_pss':'GPU Other PSS',};UsedMemoryColumn.BYTE_STAT_MAP={'proportionalResident':'PSS','privateDirtyResident':'Private dirty','swapped':'Swapped'};function AllocatorColumn(name,cellPath,aggregationMode){tr.ui.analysis.NumericMemoryColumn.call(this,name,cellPath,aggregationMode);}
+AllocatorColumn.prototype={__proto__:tr.ui.analysis.NumericMemoryColumn.prototype,get title(){const titleEl=document.createElement('tr-ui-b-color-legend');titleEl.label=this.name;return titleEl;},getFormattingContext(unit){return{unitPrefix:tr.b.UnitPrefixScale.BINARY.MEBI};},addInfos(numerics,processMemoryDumps,infos){if(processMemoryDumps===undefined)return;let heapDumpCount=0;let missingSizeCount=0;for(let i=0;i<processMemoryDumps.length;i++){const processMemoryDump=processMemoryDumps[i];if(processMemoryDump===undefined)continue;const heapDumps=processMemoryDump.heapDumps;if(heapDumps!==undefined&&heapDumps[this.name]!==undefined){heapDumpCount++;}
+const allocatorDump=processMemoryDump.getMemoryAllocatorDumpByFullName(this.name);if(allocatorDump!==undefined&&allocatorDump.numerics[DISPLAYED_SIZE_NUMERIC_NAME]===undefined){missingSizeCount++;}}
+if(heapDumpCount>0){const infoQuantifier=heapDumpCount<numerics.length?' '+SOME_TIMESTAMPS_INFO_QUANTIFIER:'';infos.push({message:'Heap dump provided'+infoQuantifier+'.',icon:TRIGRAM_FOR_HEAVEN});}
+if(missingSizeCount>0){const infoQuantifier=missingSizeCount<numerics.length?' '+SOME_TIMESTAMPS_INFO_QUANTIFIER:'';infos.push(tr.ui.analysis.createWarningInfo('Size was not provided'+infoQuantifier+'.'));}},getChildPaneBuilder(processMemoryDumps){if(processMemoryDumps===undefined)return undefined;const memoryAllocatorDumps=lazyMap(processMemoryDumps,function(pmd){if(pmd===undefined)return undefined;return pmd.getMemoryAllocatorDumpByFullName(this.name);},this);if(memoryAllocatorDumps===undefined)return undefined;const heapDumps=lazyMap(processMemoryDumps,function(pmd){if(pmd===undefined||pmd.heapDumps===undefined)return undefined;return pmd.heapDumps[this.name];},this);return function(){const pane=document.createElement('tr-ui-a-memory-dump-allocator-details-pane');pane.memoryAllocatorDumps=memoryAllocatorDumps;pane.heapDumps=heapDumps;pane.aggregationMode=this.aggregationMode;return pane;}.bind(this);}};function TracingColumn(name,cellPath,aggregationMode){AllocatorColumn.call(this,name,cellPath,aggregationMode);}
+TracingColumn.COLOR=MemoryColumnColorScheme.getColor('tracing_memory_column').toString();TracingColumn.prototype={__proto__:AllocatorColumn.prototype,get title(){return tr.ui.b.createSpan({textContent:this.name,color:TracingColumn.COLOR});},color(numerics,processMemoryDumps){return TracingColumn.COLOR;}};AllocatorColumn.RULES=[{condition:'tracing',importance:0,columnConstructor:TracingColumn},{importance:1,columnConstructor:AllocatorColumn}];Polymer({is:'tr-ui-a-memory-dump-overview-pane',behaviors:[tr.ui.analysis.StackedPane],created(){this.processMemoryDumps_=undefined;this.aggregationMode_=undefined;},ready(){this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.CELL;this.$.table.addEventListener('selection-changed',function(tableEvent){tableEvent.stopPropagation();this.changeChildPane_();}.bind(this));},set processMemoryDumps(processMemoryDumps){this.processMemoryDumps_=processMemoryDumps;this.scheduleRebuild_();},get processMemoryDumps(){return this.processMemoryDumps_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},get selectedMemoryCell(){if(this.processMemoryDumps_===undefined||this.processMemoryDumps_.length===0){return undefined;}
+const selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow)return undefined;const selectedColumnIndex=this.$.table.selectedColumnIndex;if(selectedColumnIndex===undefined)return undefined;const selectedColumn=this.$.table.tableColumns[selectedColumnIndex];const selectedMemoryCell=selectedColumn.cell(selectedTableRow);return selectedMemoryCell;},changeChildPane_(){this.storeSelection_();this.childPaneBuilder=this.determineChildPaneBuilderFromSelection_();},determineChildPaneBuilderFromSelection_(){if(this.processMemoryDumps_===undefined||this.processMemoryDumps_.length===0){return undefined;}
+const selectedTableRow=this.$.table.selectedTableRow;if(!selectedTableRow)return undefined;const selectedColumnIndex=this.$.table.selectedColumnIndex;if(selectedColumnIndex===undefined)return undefined;const selectedColumn=this.$.table.tableColumns[selectedColumnIndex];return selectedColumn.getChildPaneBuilder(selectedTableRow.contexts);},onRebuild_(){if(this.processMemoryDumps_===undefined||this.processMemoryDumps_.length===0){this.$.info_text.style.display='block';this.$.table.style.display='none';this.$.table.clear();this.$.table.rebuild();return;}
+this.$.info_text.style.display='none';this.$.table.style.display='block';const rows=this.createRows_();const columns=this.createColumns_(rows);const footerRows=this.createFooterRows_(rows,columns);this.$.table.tableRows=rows;this.$.table.footerRows=footerRows;this.$.table.tableColumns=columns;this.$.table.rebuild();this.restoreSelection_();},createRows_(){const timeToPidToProcessMemoryDump=this.processMemoryDumps_;const pidToTimeToProcessMemoryDump=tr.b.invertArrayOfDicts(timeToPidToProcessMemoryDump);const rows=[];for(const[pid,timeToDump]of
+Object.entries(pidToTimeToProcessMemoryDump)){const process=timeToDump.find(x=>x).process;const usedMemoryCells=tr.ui.analysis.createCells(timeToDump,function(dump){const sizes={};const totals=dump.totals;if(totals!==undefined){for(const[totalName,cellName]of
+Object.entries(UsedMemoryColumn.TOTALS_MAP)){const total=totals[totalName];if(total===undefined)continue;sizes[cellName]=new Scalar(sizeInBytes_smallerIsBetter,total);}
+const platformSpecific=totals.platformSpecific;if(platformSpecific!==undefined){for(const[name,size]of Object.entries(platformSpecific)){let newName=name;if(UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP[name]===undefined){if(name.endsWith(PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX)){newName=name.substring(0,name.length-
+PLATFORM_SPECIFIC_TOTAL_NAME_SUFFIX.length);}
+newName=newName.replace('_',' ').trim();newName=newName.charAt(0).toUpperCase()+newName.slice(1);}else{newName=UsedMemoryColumn.PLATFORM_SPECIFIC_TOTALS_MAP[name];}
+sizes[newName]=new Scalar(sizeInBytes_smallerIsBetter,size);}}}
+const vmRegions=dump.mostRecentVmRegions;if(vmRegions!==undefined){for(const[byteStatName,cellName]of
+Object.entries(UsedMemoryColumn.BYTE_STAT_MAP)){const byteStat=vmRegions.byteStats[byteStatName];if(byteStat===undefined)continue;sizes[cellName]=new Scalar(sizeInBytes_smallerIsBetter,byteStat);}}
+return sizes;});const allocatorCells=tr.ui.analysis.createCells(timeToDump,function(dump){const memoryAllocatorDumps=dump.memoryAllocatorDumps;if(memoryAllocatorDumps===undefined)return undefined;const sizes={};memoryAllocatorDumps.forEach(function(allocatorDump){let rootDisplayedSizeNumeric=allocatorDump.numerics[DISPLAYED_SIZE_NUMERIC_NAME];if(rootDisplayedSizeNumeric===undefined){rootDisplayedSizeNumeric=new Scalar(sizeInBytes_smallerIsBetter,0);}
+sizes[allocatorDump.fullName]=rootDisplayedSizeNumeric;});return sizes;});rows.push({title:process.userFriendlyName,contexts:timeToDump,usedMemoryCells,allocatorCells});}
+return rows;},createFooterRows_(rows,columns){if(rows.length<=1)return[];const totalRow={title:'Total'};tr.ui.analysis.aggregateTableRowCells(totalRow,rows,columns);return[totalRow];},createColumns_(rows){const titleColumn=new ProcessNameColumn();titleColumn.width='200px';const usedMemorySizeColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'usedMemoryCells',aggregationMode:this.aggregationMode_,rules:UsedMemoryColumn.RULES});const allocatorSizeColumns=tr.ui.analysis.MemoryColumn.fromRows(rows,{cellKey:'allocatorCells',aggregationMode:this.aggregationMode_,rules:AllocatorColumn.RULES});const sizeColumns=usedMemorySizeColumns.concat(allocatorSizeColumns);tr.ui.analysis.MemoryColumn.spaceEqually(sizeColumns);const columns=[titleColumn].concat(sizeColumns);return columns;},storeSelection_(){let selectedRowTitle;const selectedRow=this.$.table.selectedTableRow;if(selectedRow!==undefined){selectedRowTitle=selectedRow.title;}
+let selectedColumnName;const selectedColumnIndex=this.$.table.selectedColumnIndex;if(selectedColumnIndex!==undefined){const selectedColumn=this.$.table.tableColumns[selectedColumnIndex];selectedColumnName=selectedColumn.name;}
+this.$.state.set({rowTitle:selectedRowTitle,columnName:selectedColumnName});},restoreSelection_(){const settings=this.$.state.get();if(settings===undefined||settings.rowTitle===undefined||settings.columnName===undefined){return;}
+const selectedColumnIndex=this.$.table.tableColumns.findIndex(col=>col.name===settings.columnName);if(selectedColumnIndex===-1)return;const selectedRowTitle=settings.rowTitle;const selectedRow=this.$.table.tableRows.find(row=>row.title===selectedRowTitle);if(selectedRow===undefined)return;this.$.table.selectedTableRow=selectedRow;this.$.table.selectedColumnIndex=selectedColumnIndex;}});return{ProcessNameColumn,UsedMemoryColumn,PeakMemoryColumn,ByteStatColumn,AllocatorColumn,TracingColumn,};});'use strict';tr.exportTo('tr.ui.analysis',function(){Polymer({is:'tr-ui-a-memory-dump-header-pane',behaviors:[tr.ui.analysis.StackedPane],created(){this.containerMemoryDumps_=undefined;},ready(){Polymer.dom(this.$.aggregation_mode_container).appendChild(tr.ui.b.createSelector(this,'aggregationMode','memoryDumpHeaderPane.aggregationMode',tr.ui.analysis.MemoryColumn.AggregationMode.DIFF,[{label:'Diff',value:tr.ui.analysis.MemoryColumn.AggregationMode.DIFF},{label:'Max',value:tr.ui.analysis.MemoryColumn.AggregationMode.MAX}]));},set containerMemoryDumps(containerMemoryDumps){this.containerMemoryDumps_=containerMemoryDumps;this.scheduleRebuild_();},get containerMemoryDumps(){return this.containerMemoryDumps_;},set aggregationMode(aggregationMode){this.aggregationMode_=aggregationMode;this.scheduleRebuild_();},get aggregationMode(){return this.aggregationMode_;},onRebuild_(){this.updateLabel_();this.updateAggregationModeSelector_();this.changeChildPane_();},updateLabel_(){Polymer.dom(this.$.label).textContent='';if(this.containerMemoryDumps_===undefined||this.containerMemoryDumps_.length<=0){Polymer.dom(this.$.label).textContent='No memory dumps selected';return;}
+const containerDumpCount=this.containerMemoryDumps_.length;const isMultiSelection=containerDumpCount>1;Polymer.dom(this.$.label).appendChild(document.createTextNode('Selected '+containerDumpCount+' memory dump'+
+(isMultiSelection?'s':'')+' in '+this.containerMemoryDumps_[0].containerName+' at '));Polymer.dom(this.$.label).appendChild(document.createTextNode(tr.b.Unit.byName.timeStampInMs.format(this.containerMemoryDumps_[0].start)));if(isMultiSelection){const ELLIPSIS=String.fromCharCode(8230);Polymer.dom(this.$.label).appendChild(document.createTextNode(ELLIPSIS));Polymer.dom(this.$.label).appendChild(document.createTextNode(tr.b.Unit.byName.timeStampInMs.format(this.containerMemoryDumps_[containerDumpCount-1].start)));}},updateAggregationModeSelector_(){let displayStyle;if(this.containerMemoryDumps_===undefined||this.containerMemoryDumps_.length<=1){displayStyle='none';}else{displayStyle='initial';}
+this.$.aggregation_mode_container.style.display=displayStyle;},changeChildPane_(){this.childPaneBuilder=function(){if(this.containerMemoryDumps_===undefined||this.containerMemoryDumps_.length<=0){return undefined;}
+const overviewPane=document.createElement('tr-ui-a-memory-dump-overview-pane');overviewPane.processMemoryDumps=this.containerMemoryDumps_.map(function(containerDump){return containerDump.processMemoryDumps;});overviewPane.aggregationMode=this.aggregationMode;return overviewPane;}.bind(this);}});return{};});'use strict';Polymer({is:'tr-ui-a-stacked-pane-view',setPaneBuilder(paneBuilder,opt_parentPane){const paneContainer=this.$.pane_container;if(opt_parentPane){if(!(opt_parentPane instanceof HTMLElement)){throw new Error('Parent pane must be an HTML element');}
+if(opt_parentPane.parentElement!==paneContainer){throw new Error('Parent pane must be a child of the pane container');}}
+while(Polymer.dom(paneContainer).lastElementChild!==null&&Polymer.dom(paneContainer).lastElementChild!==opt_parentPane){const removedPane=Polymer.dom(this.$.pane_container).lastElementChild;const listener=this.listeners_.get(removedPane);if(listener===undefined){throw new Error('No listener associated with pane');}
+this.listeners_.delete(removedPane);removedPane.removeEventListener('request-child-pane-change',listener);Polymer.dom(paneContainer).removeChild(removedPane);}
+if(opt_parentPane&&opt_parentPane.parentElement!==paneContainer){throw new Error('Parent pane was removed from the pane container');}
+if(!paneBuilder)return;const pane=paneBuilder();if(!pane)return;if(!(pane instanceof HTMLElement)){throw new Error('Pane must be an HTML element');}
+const listener=function(event){this.setPaneBuilder(pane.childPaneBuilder,pane);}.bind(this);if(!this.listeners_){this.listeners_=new WeakMap();}
+this.listeners_.set(pane,listener);pane.addEventListener('request-child-pane-change',listener);Polymer.dom(paneContainer).appendChild(pane);pane.appended();},rebuild(){let currentPane=Polymer.dom(this.$.pane_container).firstElementChild;while(currentPane){currentPane.rebuild();currentPane=currentPane.nextElementSibling;}},get panesForTesting(){const panes=[];let currentChild=Polymer.dom(this.$.pane_container).firstElementChild;while(currentChild){panes.push(currentChild);currentChild=currentChild.nextElementSibling;}
+return panes;}});'use strict';tr.exportTo('tr.ui.analysis',function(){Polymer({is:'tr-ui-a-container-memory-dump-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],set selection(selection){if(selection===undefined){this.currentSelection_=undefined;this.dumpsByContainerName_=undefined;this.updateContents_();return;}
+selection.forEach(function(event){if(!(event instanceof tr.model.ContainerMemoryDump)){throw new Error('Memory dump sub-view only supports container memory dumps');}});this.currentSelection_=selection;this.dumpsByContainerName_=tr.b.groupIntoMap(this.currentSelection_.toArray(),dump=>dump.containerName);for(const dumps of this.dumpsByContainerName_.values()){dumps.sort((a,b)=>a.start-b.start);}
+this.updateContents_();},get selection(){return this.currentSelection_;},get requiresTallView(){return true;},updateContents_(){Polymer.dom(this.$.content).textContent='';if(this.dumpsByContainerName_===undefined)return;const containerNames=Array.from(this.dumpsByContainerName_.keys());if(containerNames.length===0)return;if(containerNames.length>1){this.buildViewForMultipleContainerNames_();}else{this.buildViewForSingleContainerName_();}},buildViewForSingleContainerName_(){const containerMemoryDumps=tr.b.getFirstElement(this.dumpsByContainerName_.values());const dumpView=unwrap(this.ownerDocument).createElement('tr-ui-a-stacked-pane-view');Polymer.dom(this.$.content).appendChild(dumpView);dumpView.setPaneBuilder(function(){const headerPane=document.createElement('tr-ui-a-memory-dump-header-pane');headerPane.containerMemoryDumps=containerMemoryDumps;return headerPane;});},buildViewForMultipleContainerNames_(){const ownerDocument=this.ownerDocument;const rows=[];for(const[containerName,dumps]of this.dumpsByContainerName_){rows.push({containerName,subRows:dumps,isExpanded:true,});}
+rows.sort(function(a,b){return a.containerName.localeCompare(b.containerName);});const columns=[{title:'Dump',value(row){if(row.subRows===undefined){return this.singleDumpValue_(row);}
+return this.groupedDumpValue_(row);},singleDumpValue_(row){const linkEl=unwrap(ownerDocument).createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet([row]));Polymer.dom(linkEl).appendChild(tr.v.ui.createScalarSpan(row.start,{unit:tr.b.Unit.byName.timeStampInMs,ownerDocument}));return linkEl;},groupedDumpValue_(row){const linkEl=unwrap(ownerDocument).createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet(row.subRows));Polymer.dom(linkEl).appendChild(tr.ui.b.createSpan({ownerDocument,textContent:row.subRows.length+' memory dump'+
+(row.subRows.length===1?'':'s')+' in '}));Polymer.dom(linkEl).appendChild(tr.ui.b.createSpan({ownerDocument,textContent:row.containerName,bold:true}));return linkEl;}}];const table=unwrap(this.ownerDocument).createElement('tr-ui-b-table');table.tableColumns=columns;table.tableRows=rows;table.showHeader=false;table.rebuild();Polymer.dom(this.$.content).appendChild(table);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-container-memory-dump-sub-view',tr.model.GlobalMemoryDump,{multi:false,title:'Global Memory Dump',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-container-memory-dump-sub-view',tr.model.GlobalMemoryDump,{multi:true,title:'Global Memory Dumps',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-container-memory-dump-sub-view',tr.model.ProcessMemoryDump,{multi:false,title:'Process Memory Dump',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-container-memory-dump-sub-view',tr.model.ProcessMemoryDump,{multi:true,title:'Process Memory Dumps',});return{};});'use strict';(function(){const COUNTER_SAMPLE_TABLE_COLUMNS=[{title:'Counter',width:'150px',value(row){return row.counter;}},{title:'Series',width:'150px',value(row){return row.series;}},{title:'Time',width:'150px',value(row){return row.start;}},{title:'Value',width:'100%',value(row){return row.value;}}];Polymer({is:'tr-ui-a-counter-sample-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;this.$.table.tableColumns=COUNTER_SAMPLE_TABLE_COLUMNS;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},updateContents_(){this.$.table.tableRows=this.selection?this.getRows_(this.selection.toArray()):[];this.$.table.rebuild();},getRows_(samples){const samplesByCounter=tr.b.groupIntoMap(samples,sample=>sample.series.counter.guid);const rows=[];for(const counterSamples of samplesByCounter.values()){const samplesBySeries=tr.b.groupIntoMap(counterSamples,sample=>sample.series.guid);for(const seriesSamples of samplesBySeries.values()){const seriesRows=this.getRowsForSamples_(seriesSamples);seriesRows[0].counter=seriesSamples[0].series.counter.name;seriesRows[0].series=seriesSamples[0].series.name;if(seriesRows.length>1){seriesRows[0].subRows=seriesRows.slice(1);seriesRows[0].isExpanded=true;}
+rows.push(seriesRows[0]);}}
+return rows;},getRowsForSamples_(samples){return samples.map(function(sample){return{start:sample.timestamp,value:sample.value};});}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-counter-sample-sub-view',tr.model.CounterSample,{multi:false,title:'Counter Sample',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-counter-sample-sub-view',tr.model.CounterSample,{multi:true,title:'Counter Samples',});})();'use strict';tr.exportTo('tr.ui.analysis',function(){function MultiEventSummary(title,events){this.title=title;this.duration_=undefined;this.selfTime_=undefined;this.events_=events;this.cpuTimesComputed_=false;this.cpuSelfTime_=undefined;this.cpuDuration_=undefined;this.maxDuration_=undefined;this.maxCpuDuration_=undefined;this.maxSelfTime_=undefined;this.maxCpuSelfTime_=undefined;this.untotallableArgs_=[];this.totalledArgs_=undefined;}
+MultiEventSummary.prototype={set title(title){if(title==='Totals'){this.totalsRow=true;}
+this.title_=title;},get title(){return this.title_;},get duration(){if(this.duration_===undefined){this.duration_=tr.b.math.Statistics.sum(this.events_,function(event){return event.duration;});}
+return this.duration_;},get cpuSelfTime(){this.computeCpuTimesIfNeeded_();return this.cpuSelfTime_;},get cpuDuration(){this.computeCpuTimesIfNeeded_();return this.cpuDuration_;},computeCpuTimesIfNeeded_(){if(this.cpuTimesComputed_)return;this.cpuTimesComputed_=true;let cpuSelfTime=0;let cpuDuration=0;let hasCpuData=false;for(const event of this.events_){if(event.cpuDuration!==undefined){cpuDuration+=event.cpuDuration;hasCpuData=true;}
+if(event.cpuSelfTime!==undefined){cpuSelfTime+=event.cpuSelfTime;hasCpuData=true;}}
+if(hasCpuData){this.cpuDuration_=cpuDuration;this.cpuSelfTime_=cpuSelfTime;}},get selfTime(){if(this.selfTime_===undefined){this.selfTime_=0;for(const event of this.events_){if(event.selfTime!==undefined){this.selfTime_+=event.selfTime;}}}
+return this.selfTime_;},get events(){return this.events_;},get numEvents(){return this.events_.length;},get numAlerts(){if(this.numAlerts_===undefined){this.numAlerts_=tr.b.math.Statistics.sum(this.events_,event=>event.associatedAlerts.length);}
+return this.numAlerts_;},get untotallableArgs(){this.updateArgsIfNeeded_();return this.untotallableArgs_;},get totalledArgs(){this.updateArgsIfNeeded_();return this.totalledArgs_;},get maxDuration(){if(this.maxDuration_===undefined){this.maxDuration_=tr.b.math.Statistics.max(this.events_,function(event){return event.duration;});}
+return this.maxDuration_;},get maxCpuDuration(){if(this.maxCpuDuration_===undefined){this.maxCpuDuration_=tr.b.math.Statistics.max(this.events_,function(event){return event.cpuDuration;});}
+return this.maxCpuDuration_;},get maxSelfTime(){if(this.maxSelfTime_===undefined){this.maxSelfTime_=tr.b.math.Statistics.max(this.events_,function(event){return event.selfTime;});}
+return this.maxSelfTime_;},get maxCpuSelfTime(){if(this.maxCpuSelfTime_===undefined){this.maxCpuSelfTime_=tr.b.math.Statistics.max(this.events_,function(event){return event.cpuSelfTime;});}
+return this.maxCpuSelfTime_;},updateArgsIfNeeded_(){if(this.totalledArgs_!==undefined)return;const untotallableArgs={};const totalledArgs={};for(const event of this.events_){for(const argName in event.args){const argVal=event.args[argName];const type=typeof argVal;if(type!=='number'){untotallableArgs[argName]=true;delete totalledArgs[argName];continue;}
+if(untotallableArgs[argName]){continue;}
+if(totalledArgs[argName]===undefined){totalledArgs[argName]=0;}
+totalledArgs[argName]+=argVal;}}
+this.untotallableArgs_=Object.keys(untotallableArgs);this.totalledArgs_=totalledArgs;}};return{MultiEventSummary,};});'use strict';Polymer({is:'tr-ui-a-multi-event-summary-table',ready(){this.showTotals_=false;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;this.eventsByTitle_=undefined;},updateTableColumns_(rows,maxValues){let hasCpuData=false;let hasAlerts=false;rows.forEach(function(row){if(row.cpuDuration!==undefined){hasCpuData=true;}
+if(row.cpuSelfTime!==undefined){hasCpuData=true;}
+if(row.numAlerts){hasAlerts=true;}});const ownerDocument=this.ownerDocument;const columns=[];columns.push({title:'Name',value(row){if(row.title==='Totals')return'Totals';const container=document.createElement('div');const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.model.EventSet(row.events);},row.title);container.appendChild(linkEl);if(tr.isExported('tr-ui-e-chrome-codesearch')){const link=document.createElement('tr-ui-e-chrome-codesearch');link.searchPhrase=row.title;container.appendChild(link);}
+return container;},width:'350px',cmp(rowA,rowB){return rowA.title.localeCompare(rowB.title);}});if(this.eventsHaveDuration_){columns.push({title:'Wall Duration',value(row){return tr.v.ui.createScalarSpan(row.duration,{unit:tr.b.Unit.byName.timeDurationInMs,customContextRange:row.totalsRow?undefined:tr.b.math.Range.fromExplicitRange(0,maxValues.duration),ownerDocument,});},width:'<upated further down>',cmp(rowA,rowB){return rowA.duration-rowB.duration;}});}
+if(this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Duration',value(row){return tr.v.ui.createScalarSpan(row.cpuDuration,{unit:tr.b.Unit.byName.timeDurationInMs,customContextRange:row.totalsRow?undefined:tr.b.math.Range.fromExplicitRange(0,maxValues.cpuDuration),ownerDocument,});},width:'<upated further down>',cmp(rowA,rowB){return rowA.cpuDuration-rowB.cpuDuration;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_){columns.push({title:'Self time',value(row){return tr.v.ui.createScalarSpan(row.selfTime,{unit:tr.b.Unit.byName.timeDurationInMs,customContextRange:row.totalsRow?undefined:tr.b.math.Range.fromExplicitRange(0,maxValues.selfTime),ownerDocument,});},width:'<upated further down>',cmp(rowA,rowB){return rowA.selfTime-rowB.selfTime;}});}
+if(this.eventsHaveSubRows_&&this.eventsHaveDuration_&&hasCpuData){columns.push({title:'CPU Self Time',value(row){return tr.v.ui.createScalarSpan(row.cpuSelfTime,{unit:tr.b.Unit.byName.timeDurationInMs,customContextRange:row.totalsRow?undefined:tr.b.math.Range.fromExplicitRange(0,maxValues.cpuSelfTime),ownerDocument,});},width:'<upated further down>',cmp(rowA,rowB){return rowA.cpuSelfTime-rowB.cpuSelfTime;}});}
+if(this.eventsHaveDuration_){columns.push({title:'Average '+(hasCpuData?'CPU':'Wall')+' Duration',value(row){const totalDuration=hasCpuData?row.cpuDuration:row.duration;return tr.v.ui.createScalarSpan(totalDuration/row.numEvents,{unit:tr.b.Unit.byName.timeDurationInMs,customContextRange:row.totalsRow?undefined:tr.b.math.Range.fromExplicitRange(0,maxValues.duration),ownerDocument,});},width:'<upated further down>',cmp(rowA,rowB){if(hasCpuData){return rowA.cpuDuration/rowA.numEvents-
+rowB.cpuDuration/rowB.numEvents;}
+return rowA.duration/rowA.numEvents-
+rowB.duration/rowB.numEvents;}});}
+columns.push({title:'Occurrences',value(row){return row.numEvents;},width:'<upated further down>',cmp(rowA,rowB){return rowA.numEvents-rowB.numEvents;}});let alertsColumnIndex;if(hasAlerts){columns.push({title:'Num Alerts',value(row){return row.numAlerts;},width:'<upated further down>',cmp(rowA,rowB){return rowA.numAlerts-rowB.numAlerts;}});alertsColumnIndex=columns.length-1;}
+let colWidthPercentage;if(columns.length===1){colWidthPercentage='100%';}else{colWidthPercentage=(100/(columns.length-1)).toFixed(3)+'%';}
+for(let i=1;i<columns.length;i++){columns[i].width=colWidthPercentage;}
+this.$.table.tableColumns=columns;if(hasAlerts){this.$.table.sortColumnIndex=alertsColumnIndex;this.$.table.sortDescending=true;}},configure(config){if(config.eventsByTitle===undefined){throw new Error('Required: eventsByTitle');}
+if(config.showTotals!==undefined){this.showTotals_=config.showTotals;}else{this.showTotals_=true;}
+if(config.eventsHaveDuration!==undefined){this.eventsHaveDuration_=config.eventsHaveDuration;}else{this.eventsHaveDuration_=true;}
+if(config.eventsHaveSubRows!==undefined){this.eventsHaveSubRows_=config.eventsHaveSubRows;}else{this.eventsHaveSubRows_=true;}
+this.eventsByTitle_=config.eventsByTitle;this.updateContents_();},get showTotals(){return this.showTotals_;},set showTotals(showTotals){this.showTotals_=showTotals;this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;this.updateContents_();},get eventsByTitle(){return this.eventsByTitle_;},set eventsByTitle(eventsByTitle){this.eventsByTitle_=eventsByTitle;this.updateContents_();},get selectionBounds(){return this.selectionBounds_;},set selectionBounds(selectionBounds){this.selectionBounds_=selectionBounds;this.updateContents_();},updateContents_(){let eventsByTitle;if(this.eventsByTitle_!==undefined){eventsByTitle=this.eventsByTitle_;}else{eventsByTitle=[];}
+const allEvents=new tr.model.EventSet();const rows=[];for(const[title,eventsOfSingleTitle]of Object.entries(eventsByTitle)){for(const event of eventsOfSingleTitle)allEvents.push(event);const row=new tr.ui.analysis.MultiEventSummary(title,eventsOfSingleTitle);rows.push(row);}
+this.updateTableColumns_(rows);this.$.table.tableRows=rows;const maxValues={duration:undefined,selfTime:undefined,cpuSelfTime:undefined,cpuDuration:undefined};if(this.eventsHaveDuration){for(const column in maxValues){maxValues[column]=tr.b.math.Statistics.max(rows,function(event){return event[column];});}}
+const footerRows=[];if(this.showTotals_){const multiEventSummary=new tr.ui.analysis.MultiEventSummary('Totals',allEvents);footerRows.push(multiEventSummary);}
+this.updateTableColumns_(rows,maxValues);this.$.table.tableRows=rows;this.$.table.footerRows=footerRows;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-ui-a-selection-summary-table',created(){this.selection_=new tr.b.math.Range();},ready(){this.$.table.showHeader=false;this.$.table.tableColumns=[{title:'Name',value(row){return row.title;},width:'350px'},{title:'Value',width:'100%',value(row){return row.value;}}];},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},updateContents_(){const selection=this.selection_;const rows=[];let hasRange;if(this.selection_&&(!selection.bounds.isEmpty)){hasRange=true;}else{hasRange=false;}
+rows.push({title:'Selection start',value:hasRange?tr.v.ui.createScalarSpan(selection.bounds.min,{unit:tr.b.Unit.byName.timeStampInMs,ownerDocument:this.ownerDocument}):'<empty>'});rows.push({title:'Selection extent',value:hasRange?tr.v.ui.createScalarSpan(selection.bounds.range,{unit:tr.b.Unit.byName.timeDurationInMs,ownerDocument:this.ownerDocument}):'<empty>'});this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-ui-b-radio-picker',created(){this.needsInit_=true;this.settingsKey_=undefined;this.isReady_=false;this.radioButtons_=undefined;this.selectedKey_=undefined;},ready(){this.isReady_=true;this.maybeInit_();this.maybeRenderRadioButtons_();},get vertical(){return this.getAttribute('vertical');},set vertical(vertical){if(vertical){this.setAttribute('vertical',true);}else{this.removeAttribute('vertical');}},get settingsKey(){return this.settingsKey_;},set settingsKey(settingsKey){if(!this.needsInit_){throw new Error('Already initialized.');}
+this.settingsKey_=settingsKey;this.maybeInit_();},maybeInit_(){if(!this.needsInit_)return;if(this.settingsKey_===undefined)return;this.needsInit_=false;this.select(tr.b.Settings.get(this.settingsKey_));},set items(items){this.radioButtons_={};items.forEach(function(e){if(e.key in this.radioButtons_){throw new Error(e.key+' already exists');}
+const radioButton=document.createElement('div');const input=document.createElement('input');const label=document.createElement('label');input.type='radio';input.id=e.label;input.addEventListener('click',function(){this.select(e.key);}.bind(this));Polymer.dom(label).innerHTML=e.label;label.htmlFor=e.label;label.style.display='inline';Polymer.dom(radioButton).appendChild(input);Polymer.dom(radioButton).appendChild(label);this.radioButtons_[e.key]=input;}.bind(this));this.maybeInit_();this.maybeRenderRadioButtons_();},maybeRenderRadioButtons_(){if(!this.isReady_)return;if(this.radioButtons_===undefined)return;for(const key in this.radioButtons_){Polymer.dom(this.$.container).appendChild(this.radioButtons_[key].parentElement);}
+if(this.selectedKey_!==undefined){this.select(this.selectedKey_);}},select(key){if(key===undefined||key===this.selectedKey_){return;}
+if(this.radioButtons_===undefined){this.selectedKey_=key;return;}
+if(!(key in this.radioButtons_)){throw new Error(key+' does not exists');}
+if(this.selectedKey_!==undefined){this.radioButtons_[this.selectedKey_].checked=false;}
+this.selectedKey_=key;tr.b.Settings.set(this.settingsKey_,this.selectedKey_);if(this.selectedKey_!==undefined){this.radioButtons_[this.selectedKey_].checked=true;}
+this.dispatchEvent(new tr.b.Event('change',false));},get selectedKey(){return this.selectedKey_;},});'use strict';tr.exportTo('tr.ui.b',function(){const MIN_GUIDELINE_HEIGHT_PX=3;const CHECKBOX_WIDTH_PX=18;const NameColumnChart=tr.ui.b.define('name-column-chart',tr.ui.b.ColumnChart);NameColumnChart.prototype={__proto__:tr.ui.b.ColumnChart.prototype,get xAxisHeight(){return 5+(this.textHeightPx_*this.data_.length);},updateMargins_(){super.updateMargins_();let xAxisTickOverhangPx=0;for(let i=0;i<this.data_.length;++i){const datum=this.data_[i];xAxisTickOverhangPx=Math.max(xAxisTickOverhangPx,this.xScale_(i)+tr.ui.b.getSVGTextSize(this,datum.x).width-
+this.graphWidth);}
+this.margin.right=Math.max(this.margin.right,xAxisTickOverhangPx);},getXForDatum_(datum,index){return index;},get xAxisTickOffset(){return 0.5;},updateXAxis_(xAxis){xAxis.selectAll('*').remove();if(this.hideXAxis)return;const nameTexts=xAxis.selectAll('text').data(this.data_);nameTexts.enter().append('text').attr('transform',(d,index)=>'translate(0, '+
+this.textHeightPx_*(this.data_.length-index)+')').attr('x',(d,index)=>this.xScale_(index)).attr('y',d=>this.graphHeight).text(d=>d.x);nameTexts.exit().remove();const guideLines=xAxis.selectAll('line.guide').data(this.data_);guideLines.enter().append('line').attr('x1',(d,index)=>this.xScale_(index+this.xAxisTickOffset)).attr('x2',(d,index)=>this.xScale_(index+this.xAxisTickOffset)).attr('y1',()=>this.graphHeight).attr('y2',(d,index)=>this.graphHeight+Math.max(MIN_GUIDELINE_HEIGHT_PX,(this.textHeightPx_*(this.data_.length-index-1))));}};return{NameColumnChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const LineChart=tr.ui.b.LineChart;const NameLineChart=tr.ui.b.define('name-line-chart',LineChart);NameLineChart.prototype={__proto__:LineChart.prototype,getXForDatum_(datum,index){return index;},get xAxisHeight(){return 5+(this.textHeightPx_*this.data_.length);},get xAxisTickOffset(){return 0;},updateMargins_(){tr.ui.b.NameColumnChart.prototype.updateMargins_.call(this);},updateXAxis_(xAxis){xAxis.selectAll('*').remove();if(this.hideXAxis)return;tr.ui.b.NameColumnChart.prototype.updateXAxis_.call(this,xAxis);const baseline=xAxis.selectAll('path').data([this]);baseline.enter().append('line').attr('stroke','black').attr('x1',this.xScale_(0)).attr('x2',this.xScale_(this.data_.length-1)).attr('y1',this.graphHeight).attr('y2',this.graphHeight);baseline.exit().remove();}};return{NameLineChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const BoxChart=tr.ui.b.define('box-chart',tr.ui.b.NameLineChart);BoxChart.prototype={__proto__:tr.ui.b.NameLineChart.prototype,get hideLegend(){return true;},updateDataRange_(){if(this.overrideDataRange_!==undefined){return;}
+this.autoDataRange_.reset();for(const datum of this.data_){this.autoDataRange_.addValue(datum.percentile_0);this.autoDataRange_.addValue(datum.percentile_100);}},updateScales_(){super.updateScales_();this.xScale_.domain([0,this.data_.length]);},get xAxisTickOffset(){return 0.5;},updateDataRange_(){if(this.overrideDataRange_!==undefined)return;this.autoDataRange_.reset();for(const datum of this.data_){this.autoDataRange_.addValue(datum.percentile_0);this.autoDataRange_.addValue(datum.percentile_100);}},updateXAxis_(xAxis){xAxis.selectAll('*').remove();if(this.hideXAxis)return;tr.ui.b.NameColumnChart.prototype.updateXAxis_.call(this,xAxis);const baseline=xAxis.selectAll('path').data([this]);baseline.enter().append('line').attr('stroke','black').attr('x1',this.xScale_(0)).attr('x2',this.xScale_(this.data_.length)).attr('y1',this.graphHeight).attr('y2',this.graphHeight);baseline.exit().remove();},updateDataContents_(dataSel){dataSel.selectAll('*').remove();const boxesSel=dataSel.selectAll('path');for(let index=0;index<this.data_.length;++index){const datum=this.data_[index];const color=datum.color||'black';let sel=boxesSel.data([datum]);sel.enter().append('rect').attr('fill',color).attr('x',this.xScale_(index+0.2)).attr('width',this.xScale_(index+0.8)-this.xScale_(index+0.2)).attr('y',this.yScale_(datum.percentile_75)).attr('height',this.yScale_(datum.percentile_25)-
+this.yScale_(datum.percentile_75));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index)).attr('x2',this.xScale_(index+1)).attr('y1',this.yScale_(datum.percentile_50)).attr('y2',this.yScale_(datum.percentile_50));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.4)).attr('x2',this.xScale_(index+0.6)).attr('y1',this.yScale_(datum.percentile_0)).attr('y2',this.yScale_(datum.percentile_0));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.4)).attr('x2',this.xScale_(index+0.6)).attr('y1',this.yScale_(datum.percentile_100)).attr('y2',this.yScale_(datum.percentile_100));sel.exit().remove();sel=boxesSel.data([datum]);sel.enter().append('line').attr('stroke',color).attr('x1',this.xScale_(index+0.5)).attr('x2',this.xScale_(index+0.5)).attr('y1',this.yScale_(datum.percentile_100)).attr('y2',this.yScale_(datum.percentile_0));sel.exit().remove();}}};return{BoxChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const BarChart=tr.ui.b.define('bar-chart',tr.ui.b.ColumnChart);BarChart.prototype={__proto__:tr.ui.b.ColumnChart.prototype,decorate(){super.decorate();this.verticalScale_=undefined;this.horizontalScale_=undefined;this.isWaterfall_=false;},updateScales_(){super.updateScales_();this.yScale_.range([this.graphWidth,0]);this.xScale_.range([0,this.graphHeight]);this.verticalScale_=this.isYLogScale_?d3.scale.log(10):d3.scale.linear();this.verticalScale_.domain(this.xScale_.domain());this.verticalScale_.range([this.graphHeight,0]);this.horizontalScale_=d3.scale.linear();this.horizontalScale_.domain(this.yScale_.domain());this.horizontalScale_.range([0,this.graphWidth]);},set isWaterfall(waterfall){this.isWaterfall_=waterfall;if(waterfall){this.getDataSeries('hide').color='transparent';}
+this.updateContents_();},get isWaterfall(){return this.isWaterfall_;},get defaultGraphHeight(){return Math.max(20,10*this.data_.length);},get defaultGraphWidth(){return 100;},get barHeight(){return this.graphHeight/this.data.length;},drawBrush_(brushRectsSel){brushRectsSel.attr('x',0).attr('width',this.graphWidth).attr('y',d=>this.verticalScale_(d.max)).attr('height',d=>this.verticalScale_(d.min)-this.verticalScale_(d.max)).attr('fill','rgb(213, 236, 229)');},getDataPointAtChartPoint_(chartPoint){const flippedPoint={x:this.graphHeight-chartPoint.y,y:this.graphWidth-chartPoint.x};return super.getDataPointAtChartPoint_(flippedPoint);},drawXAxis_(xAxis){xAxis.attr('transform','translate(0,'+this.graphHeight+')').call(d3.svg.axis().scale(this.horizontalScale_).orient('bottom'));},get yAxisWidth(){return this.computeScaleTickWidth_(this.verticalScale_);},drawYAxis_(yAxis){const axisModifier=d3.svg.axis().scale(this.verticalScale_).orient('left');yAxis.call(axisModifier);},drawHoverValueBox_(rect){const rectHoverEvent=new tr.b.Event('rect-mouseenter');rectHoverEvent.rect=rect;this.dispatchEvent(rectHoverEvent);if(!this.enableHoverBox||(this.isWaterfall_&&rect.key==='hide')){return;}
+const seriesKeys=[...this.seriesByKey_.keys()];const chartAreaSel=d3.select(this.chartAreaElement);chartAreaSel.selectAll('.hover').remove();let keyWidthPx=0;let keyHeightPx=0;let xWidthPx=0;let xHeightPx=0;let groupWidthPx=0;let groupHeightPx=0;if(seriesKeys.length>1&&!this.isGrouped&&!this.isWaterfall_){keyWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.key).width;keyHeightPx=this.textHeightPx_;}
+if(this.data.length>1&&!this.isWaterfall_){xWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,''+rect.datum.x).width;xHeightPx=this.textHeightPx_;}
+if(this.isGrouped&&rect.datum.group!==undefined){groupWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.datum.group).width;groupHeightPx=this.textHeightPx_;}
+const valueWidthPx=tr.ui.b.getSVGTextSize(this.chartAreaElement,rect.value).width;const valueHeightPx=this.textHeightPx_;const maxWidthPx=Math.max(keyWidthPx,xWidthPx,groupWidthPx,valueWidthPx)+5;const hoverWidthPx=this.isGrouped?maxWidthPx:Math.min(maxWidthPx,Math.max(50,rect.widthPx));let hoverTopPx=rect.topPx;hoverTopPx=Math.min(hoverTopPx,this.getBoundingClientRect().height-
+valueHeightPx);let hoverLeftPx=rect.leftPx+(rect.widthPx/2);hoverLeftPx=Math.max(hoverLeftPx-hoverWidthPx,-this.margin.left);chartAreaSel.append('rect').attr('class','hover').attr('fill','white').attr('x',hoverLeftPx).attr('y',hoverTopPx).attr('width',hoverWidthPx).attr('height',keyHeightPx+xHeightPx+
+valueHeightPx+groupHeightPx);if(seriesKeys.length>1&&!this.isGrouped&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx-3).text(rect.key);}
+if(this.data.length>1&&!this.isWaterfall_){chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+valueHeightPx-3).text(''+rect.datum.x);}
+if(this.isGrouped&&rect.datum.group!==undefined){chartAreaSel.append('text').on('mouseleave',()=>this.clearHoverValueBox_(rect)).attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+keyHeightPx+xHeightPx+groupHeightPx-3).text(rect.datum.group);}
+chartAreaSel.append('text').attr('class','hover').attr('fill',rect.color==='transparent'?'#000000':rect.color).attr('x',hoverLeftPx+2).attr('y',hoverTopPx+xHeightPx+keyHeightPx+
+groupHeightPx+valueHeightPx-3).text(rect.value);},flipRect_(rect){return{datum:rect.datum,index:rect.index,key:rect.key,value:rect.value,color:rect.color,topPx:this.graphHeight-rect.leftPx-rect.widthPx,leftPx:this.graphWidth-rect.topPx-rect.heightPx,widthPx:rect.heightPx,heightPx:rect.widthPx,underflow:rect.underflow,overflow:rect.overflow,};},drawRect_(rect,sel){super.drawRect_(this.flipRect_(rect),sel);},drawUnderflow_(rect,rectsSel){let sel=rectsSel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',0).attr('y',this.graphHeight-rect.leftPx+
+3+(rect.widthPx/2));sel.exit().remove();sel=rectsSel.data([rect]);sel.enter().append('rect').attr('fill','rgba(0, 0, 0, 0)').attr('x',0).attr('y',this.graphHeight-rect.leftPx-rect.widthPx).attr('width',10).attr('height',rect.widthPx).on('mouseenter',()=>this.drawHoverValueBox_(this.flipRect_(rect))).on('mouseleave',()=>this.clearHoverValueBox_(rect));sel.exit().remove();},drawOverflow_(rect,sel){sel=sel.data([rect]);sel.enter().append('text').text('*').attr('fill',rect.color).attr('x',this.graphWidth).attr('y',this.graphHeight-rect.leftPx+
+3+(rect.widthPx/2));sel.exit().remove();}};return{BarChart,};});'use strict';tr.exportTo('tr.ui.b',function(){const NameBarChart=tr.ui.b.define('name-bar-chart',tr.ui.b.BarChart);const Y_AXIS_PADDING=2;NameBarChart.prototype={__proto__:tr.ui.b.BarChart.prototype,getDataPointAtChartPoint_(chartPoint){return{x:tr.ui.b.BarChart.prototype.getDataPointAtChartPoint_.call(this,chartPoint).x,y:parseInt(Math.floor((this.graphHeight-chartPoint.y)/this.barHeight))};},getXForDatum_(datum,index){return index;},get yAxisWidth(){if(this.data.length===0)return 0;return Y_AXIS_PADDING+tr.b.math.Statistics.max(this.data_,d=>tr.ui.b.getSVGTextSize(this,d.x).width);},get defaultGraphHeight(){return(3+this.textHeightPx_)*this.data.length;},updateYAxis_(yAxis){if(tr.ui.b.getSVGTextSize(this,'test').width===0){tr.b.requestAnimationFrame(()=>this.updateYAxis_(yAxis));return;}
+yAxis.selectAll('*').remove();if(this.hideYAxis)return;const nameTexts=yAxis.selectAll('text').data(this.data_);nameTexts.enter().append('text').attr('x',d=>-(tr.ui.b.getSVGTextSize(this,d.x).width+Y_AXIS_PADDING)).attr('y',(d,index)=>this.verticalScale_(index)).text(d=>d.x);nameTexts.exit().remove();let previousTop=undefined;for(const text of nameTexts[0]){const bbox=text.getBBox();if((previousTop===undefined)||(previousTop>(bbox.y+bbox.height))){previousTop=bbox.y;}else{text.style.opacity=0;}}}};return{NameBarChart,};});'use strict';tr.exportTo('tr.v.ui',function(){const DIAGNOSTIC_SPAN_BEHAVIOR={created(){this.diagnostic_=undefined;this.name_=undefined;this.histogram_=undefined;},attached(){if(this.diagnostic_)this.updateContents_();},get diagnostic(){return this.diagnostic_;},build(diagnostic,name,histogram){this.diagnostic_=diagnostic;this.name_=name;this.histogram_=histogram;if(this.isAttached)this.updateContents_();},updateContents_(){throw new Error('dom-modules must override updateContents_()');}};return{DIAGNOSTIC_SPAN_BEHAVIOR,};});'use strict';tr.exportTo('tr.v.ui',function(){const DEFAULT_COLOR_SCHEME=new tr.b.SinebowColorGenerator();function getHistogramName(histogram,diagnosticName,key){if(histogram===undefined)return undefined;const nameMap=histogram.diagnostics.get(diagnosticName);if(nameMap===undefined)return undefined;return nameMap.get(key);}
+class BreakdownTableSummaryRow{constructor(displayElement,histogramNames){this.displayElement_=displayElement;this.histogramNames_=histogramNames;this.keySpan_=undefined;}
+get numberValue(){return undefined;}
+get keySpan(){if(this.keySpan_===undefined){if(this.histogramNames_.length){this.keySpan_=document.createElement('tr-ui-a-analysis-link');this.keySpan_.setSelectionAndContent(this.histogramNames_,'Select All');}else{this.keySpan_='Sum';}}
+return this.keySpan_;}
+get name(){return'Sum';}
+get displayElement(){return this.displayElement_;}
+get stringPercent(){return'100%';}}
+class BreakdownTableRow{constructor(name,value,histogramName,unit,color){this.name_=name;this.value_=value;this.histogramName_=histogramName;this.unit_=unit;if(typeof value!=='number'){throw new Error('unsupported value '+value);}
+this.tableSum_=undefined;this.keySpan_=undefined;this.color_=color;const hsl=this.color.toHSL();hsl.l*=0.85;this.highlightedColor_=tr.b.Color.fromHSL(hsl);if(this.unit_){this.displayElement_=tr.v.ui.createScalarSpan(this.numberValue,{unit:this.unit_,});}else{this.displayElement_=tr.ui.b.createSpan({textContent:this.stringValue,});}}
+get name(){return this.name_;}
+get color(){return this.color_;}
+get highlightedColor(){return this.highlightedColor_;}
+get keySpan(){if(this.keySpan_===undefined){if(this.histogramName_){this.keySpan_=document.createElement('tr-ui-a-analysis-link');this.keySpan_.setSelectionAndContent([this.histogramName_],this.name);this.keySpan_.color=this.color;this.keySpan_.title=this.histogramName_;}else{this.keySpan_=document.createElement('span');this.keySpan_.innerText=this.name;this.keySpan_.style.color=this.color;}}
+return this.keySpan_;}
+get numberValue(){if(!isNaN(this.value_)&&(this.value_!==Infinity)&&(this.value_!==-Infinity)&&(this.value_>0))return this.value_;return undefined;}
+get stringValue(){if((this.unit_!==undefined)&&!isNaN(this.value_)&&(this.value_!==Infinity)&&(this.value_!==-Infinity)){return this.unit_.format(this.value_);}
+return this.value_.toString();}
+set tableSum(s){this.tableSum_=s;}
+get stringPercent(){if(this.tableSum_===undefined)return'';const num=this.numberValue;if(num===undefined)return'';return Math.floor(num*100.0/this.tableSum_)+'%';}
+get displayElement(){return this.displayElement_;}
+compare(other){if(this.numberValue===undefined){if(other.numberValue===undefined){return this.name.localeCompare(other.name);}
+return 1;}
+if(other.numberValue===undefined){return-1;}
+if(this.numberValue===other.numberValue){return this.name.localeCompare(other.name);}
+return other.numberValue-this.numberValue;}}
+Polymer({is:'tr-v-ui-breakdown-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],created(){this.chart_=new tr.ui.b.ColumnChart();this.chart_.graphHeight=130;this.chart_.isStacked=true;this.chart_.hideXAxis=true;this.chart_.hideLegend=true;this.chart_.enableHoverBox=false;this.chart_.addEventListener('rect-mouseenter',event=>this.onRectMouseEnter_(event));this.chart_.addEventListener('rect-mouseleave',event=>this.onRectMouseLeave_(event));},onRectMouseEnter_(event){for(const row of this.$.table.tableRows){if(row.name===event.rect.key){row.displayElement.style.background=event.rect.color;row.keySpan.scrollIntoViewIfNeeded();}else{row.displayElement.style.background='';}}},onRectMouseLeave_(event){for(const row of this.$.table.tableRows){row.displayElement.style.background='';}},ready(){Polymer.dom(this.$.container).appendChild(this.chart_);this.$.table.zebra=true;this.$.table.showHeader=false;this.$.table.tableColumns=[{value:row=>row.keySpan,},{value:row=>row.displayElement,align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,},{value:row=>row.stringPercent,align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,},];},updateContents_(){this.$.container.style.display='none';this.$.table.style.display='none';this.$.empty.style.display='block';if(!this.diagnostic_){this.chart_.data=[];return;}
+if(this.histogram_)this.chart_.unit=this.histogram_.unit;let colorScheme=undefined;if(this.diagnostic.colorScheme===tr.v.d.COLOR_SCHEME_CHROME_USER_FRIENDLY_CATEGORY_DRIVER){colorScheme=(name)=>{let cat=name.split(' ');cat=cat[cat.length-1];return tr.e.chrome.ChromeUserFriendlyCategoryDriver.getColor(cat);};}else if(this.diagnostic.colorScheme){colorScheme=(name)=>tr.b.FixedColorSchemeRegistry.lookUp(this.diagnostic.colorScheme).getColor(name);}else{colorScheme=(name)=>DEFAULT_COLOR_SCHEME.colorForKey(name);}
+const tableRows=[];let tableSum=0;const histogramNames=[];for(const[key,value]of this.diagnostic){const histogramName=getHistogramName(this.histogram_,this.name_,key);const row=new BreakdownTableRow(key,value,histogramName,this.chart_.unit,colorScheme(key));tableRows.push(row);if(row.numberValue!==undefined)tableSum+=row.numberValue;if(histogramName){histogramNames.push(histogramName);}}
+tableRows.sort((x,y)=>x.compare(y));if(tableSum>0){let summaryDisplayElement=tableSum;if(this.chart_.unit!==undefined){summaryDisplayElement=this.chart_.unit.format(tableSum);}
+summaryDisplayElement=tr.ui.b.createSpan({textContent:summaryDisplayElement,});tableRows.unshift(new BreakdownTableSummaryRow(summaryDisplayElement,histogramNames));}
+const chartData={x:0};for(const row of tableRows){if(row.numberValue===undefined)continue;row.tableSum=tableSum;chartData[row.name]=row.numberValue;const dataSeries=this.chart_.getDataSeries(row.name);dataSeries.color=row.color;dataSeries.highlightedColor=row.highlightedColor;}
+if(tableRows.length>0){this.$.table.style.display='block';this.$.empty.style.display='none';this.$.table.tableRows=tableRows;this.$.table.rebuild();}
+if(Object.keys(chartData).length>1){this.$.container.style.display='block';this.$.empty.style.display='none';this.chart_.data=[chartData];}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-collected-related-event-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';for(const[canonicalUrl,events]of this.diagnostic){const link=document.createElement('a');if(events.length===1){const event=tr.b.getOnlyElement(events);link.textContent=event.title+' '+
+tr.b.Unit.byName.timeDurationInMs.format(event.duration);}else{link.textContent=events.length+' events';}
+link.href=canonicalUrl;Polymer.dom(this).appendChild(link);Polymer.dom(this).appendChild(document.createElement('br'));}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-date-range-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){if(this.diagnostic===undefined){Polymer.dom(this).textContent='';return;}
+Polymer.dom(this).textContent=this.diagnostic.toString();}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){function isLinkTuple(value){return((value instanceof Array)&&(value.length===2)&&(typeof value[0]==='string')&&tr.b.isUrl(value[1]));}
+Polymer({is:'tr-v-ui-generic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.generic.style.display='none';this.$.links.textContent='';if(this.diagnostic===undefined)return;const values=Array.from(this.diagnostic);let areAllStrings=true;let areAllNumbers=true;for(const value of values){if(typeof value!=='number'){areAllNumbers=false;if(typeof value!=='string'&&!isLinkTuple(value)){areAllStrings=false;break;}}}
+if(!areAllStrings){this.$.generic.style.display='';this.$.generic.object=values;return;}
+if(areAllNumbers){values.sort((x,y)=>x-y);}else{values.sort();}
+for(const value of values){const link={textContent:''+value};if(isLinkTuple(value)){link.textContent=value[0];link.href=value[1];}else if(tr.b.isUrl(value)){link.href=value;}
+if(this.name_===tr.v.d.RESERVED_NAMES.TRACE_URLS){link.textContent=value.substr(1+value.lastIndexOf('/'));}
+const linkEl=tr.ui.b.createLink(link);if(link.href){linkEl.target='_blank';linkEl.addEventListener('click',e=>e.stopPropagation());}
+this.$.links.appendChild(linkEl);}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-related-event-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';const events=new tr.model.EventSet([...this.diagnostic]);const link=document.createElement('tr-ui-a-analysis-link');let label=events.length+' events';if(events.length===1){const event=tr.b.getOnlyElement(events);label=event.title+' ';label+=tr.b.Unit.byName.timeDurationInMs.format(event.duration);}
+link.setSelectionAndContent(events,label);Polymer.dom(this).appendChild(link);}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-scalar-diagnostic-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){this.$.scalar.setValueAndUnit(this.diagnostic.value.value,this.diagnostic.value.unit);}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-unmergeable-diagnostic-set-span',behaviors:[tr.v.ui.DIAGNOSTIC_SPAN_BEHAVIOR],updateContents_(){Polymer.dom(this).textContent='';for(const diagnostic of this.diagnostic){if(diagnostic instanceof tr.v.d.RelatedNameMap)continue;const div=document.createElement('div');div.appendChild(tr.v.ui.createDiagnosticSpan(diagnostic,this.name_,this.histogram_));Polymer.dom(this).appendChild(div);}}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){function findElementNameForDiagnostic(diagnostic){let typeInfo=undefined;let curProto=diagnostic.constructor.prototype;while(curProto){typeInfo=tr.v.d.Diagnostic.findTypeInfo(curProto.constructor);if(typeInfo&&typeInfo.metadata.elementName)break;typeInfo=undefined;curProto=curProto.__proto__;}
+if(typeInfo===undefined){throw new Error(diagnostic.constructor.name+' or a base class must have a registered elementName');}
+const tagName=typeInfo.metadata.elementName;if(tr.ui.b.isUnknownElementName(tagName)){throw new Error('Element not registered: '+tagName);}
+return tagName;}
+function createDiagnosticSpan(diagnostic,name,histogram){const tagName=findElementNameForDiagnostic(diagnostic);const span=document.createElement(tagName);if(span.build===undefined)throw new Error(tagName);span.build(diagnostic,name,histogram);return span;}
+return{createDiagnosticSpan,};});'use strict';tr.exportTo('tr.v.ui',function(){function makeColumn(title,histogram){return{title,value(map){const diagnostic=map.get(title);if(!diagnostic)return'';return tr.v.ui.createDiagnosticSpan(diagnostic,title,histogram);}};}
+Polymer({is:'tr-v-ui-diagnostic-map-table',created(){this.diagnosticMaps_=undefined;this.histogram_=undefined;this.isMetadata_=false;},set histogram(h){this.histogram_=h;},set isMetadata(m){this.isMetadata_=m;this.$.table.showHeader=!this.isMetadata_;},set diagnosticMaps(maps){this.diagnosticMaps_=maps;this.updateContents_();},get diagnosticMaps(){return this.diagnosticMaps_;},updateContents_(){if(this.isMetadata_&&this.diagnosticMaps_.length!==1){throw new Error('Metadata diagnostic-map-tables require exactly 1 DiagnosticMap');}
+if(this.diagnosticMaps_===undefined||this.diagnosticMaps_.length===0){this.$.table.tableRows=[];this.$.table.tableColumns=[];return;}
+let names=new Set();for(const map of this.diagnosticMaps_){for(const[name,diagnostic]of map){if(diagnostic instanceof tr.v.d.UnmergeableDiagnosticSet)continue;if(diagnostic instanceof tr.v.d.CollectedRelatedEventSet)continue;names.add(name);}}
+names=Array.from(names).sort();const histogram=this.histogram_;if(this.isMetadata_){const diagnosticMap=this.diagnosticMaps_[0];this.$.table.tableColumns=[{value(name){return name.name;}},{value(name){const diagnostic=diagnosticMap.get(name.name);if(!diagnostic)return'';return tr.v.ui.createDiagnosticSpan(diagnostic,name.name,histogram);}},];this.$.table.tableRows=names.map(name=>{return{name};});}else{this.$.table.tableColumns=names.map(name=>makeColumn(name,histogram));this.$.table.tableRows=this.diagnosticMaps_;}
+this.$.table.rebuild();}});return{};});'use strict';tr.exportTo('tr.b',function(){class Serializable{constructor(){Object.defineProperty(this,'properties_',{configurable:false,enumerable:false,value:new Map(),});}
+define(name,initialValue){if(this[name]!==undefined){throw new Error(`"${name}" is already defined.`);}
+if(name[name.length-1]==='_'){throw new Error(`"${name}" cannot end with an underscore.`);}
+this.properties_.set(name,initialValue);Object.defineProperty(this,name,{configurable:false,enumerable:true,get:()=>this.properties_.get(name),set:value=>this.setProperty_(name,value),});}
+setProperty_(name,value){this.properties_.set(name,value);}
+clone(){return Serializable.fromDict(this.asDict());}
+asDict(){function visit(obj){if(obj instanceof Serializable)return obj.asDict();if(obj instanceof Set)return Array.from(obj);if(obj instanceof Array)return obj.map(visit);if(!(obj instanceof Map))return obj;const result={};for(const[name,value]of obj){result[name]=visit(value);}
+return result;}
+const dict={type:this.constructor.name};for(const[name,value]of this.properties_){dict[name.replace(/_$/,'')]=visit(value);}
+return dict;}
+static fromDict(dict){function visit(d){if(d instanceof Array)return d.map(visit);if(!(d instanceof Object))return d;if(typeof d.type==='string')return Serializable.fromDict(d);const result=new Map();for(const[name,value]of Object.entries(d)){result.set(name,visit(value));}
+return result;}
+const typeInfo=Serializable.findTypeInfoWithName(dict.type);const result=new typeInfo.constructor();for(const[name,value]of Object.entries(dict)){result[name]=visit(value);}
+return result;}}
+const options=new tr.b.ExtensionRegistryOptions(tr.b.BASIC_REGISTRY_MODE);options.defaultMetadata={};options.mandatoryBaseClass=Serializable;tr.b.decorateExtensionRegistry(Serializable,options);return{Serializable,};});'use strict';tr.exportTo('tr.b',function(){class ViewState extends tr.b.Serializable{constructor(){super();tr.b.EventTarget.decorate(this);}
+setProperty_(name,value){this.update(new Map([[name,value]]));}
+async updateFromViewState(other){await this.update(other.properties_);}
+async update(delta){if(!(delta instanceof Map))delta=new Map(Object.entries(delta));const actualDelta={};for(const[name,current]of delta){const previous=this[name];if(previous===current)continue;actualDelta[name]={previous,current};tr.b.Serializable.prototype.setProperty_.call(this,name,current);}
+if(Object.keys(actualDelta).length===0)return;await tr.b.dispatchSimpleEventAsync(this,this.updateEventName_,{delta:actualDelta});}
+get updateEventName_(){return this.constructor.name+'.update';}
+addUpdateListener(listener){this.addEventListener(this.updateEventName_,listener);}
+removeUpdateListener(listener){this.removeEventListener(this.updateEventName_,listener);}}
+return{ViewState,};});'use strict';tr.exportTo('tr.v.ui',function(){class HistogramSetViewState extends tr.b.ViewState{constructor(){super();this.define('searchQuery','');this.define('referenceDisplayLabel','');this.define('displayStatisticName','');this.define('showAll',true);this.define('groupings',[]);this.define('sortColumnIndex',0);this.define('sortDescending',false);this.define('constrainNameColumn',true);this.define('tableRowStates',new Map());this.define('alpha',0.01);}}
+tr.b.ViewState.register(HistogramSetViewState);class HistogramSetTableRowState extends tr.b.ViewState{constructor(){super();this.define('isExpanded',false);this.define('isOverviewed',false);this.define('cells',new Map());this.define('subRows',new Map());this.define('diagnosticsTab','');}
+asCompactDict(){const result={};if(this.isExpanded)result.e='1';if(this.isOverviewed)result.o='1';if(this.diagnosticsTab)result.d=this.diagnosticsTab;const cells={};for(const[name,cell]of this.cells){const cellDict=cell.asCompactDict();if(cellDict===undefined)continue;cells[name]=cellDict;}
+if(Object.keys(cells).length>0)result.c=cells;const subRows={};for(const[name,row]of this.subRows){const rowDict=row.asCompactDict();if(rowDict===undefined)continue;subRows[name]=rowDict;}
+if(Object.keys(subRows).length>0)result.r=subRows;if(Object.keys(result).length===0)return undefined;return result;}
+async updateFromCompactDict(dict){await this.update({isExpanded:dict.e==='1',isOverviewed:dict.o==='1',diagnosticsTab:dict.d||'',});for(const[name,cellDict]of Object.entries(dict.c||{})){const cell=this.cells.get(name);if(cell===undefined)continue;await cell.updateFromCompactDict(cellDict);}
+for(const[name,subRowDict]of Object.entries(dict.r||{})){const subRow=this.subRows.get(name);if(subRow===undefined)continue;await subRow.updateFromCompactDict(subRowDict);}}*walk(){yield this;for(const row of this.subRows.values())yield*row.walk();}
+static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}}
+tr.b.ViewState.register(HistogramSetTableRowState);class HistogramSetTableCellState extends tr.b.ViewState{constructor(){super();this.define('isOpen',false);this.define('brushedBinRange',new tr.b.math.Range());this.define('mergeSampleDiagnostics',true);}
+asCompactDict(){const result={};if(this.isOpen)result.o='1';if(!this.mergeSampleDiagnostics)result.m='0';if(!this.brushedBinRange.isEmpty){result.b=this.brushedBinRange.min+'_'+this.brushedBinRange.max;}
+if(Object.keys(result).length===0)return undefined;return result;}
+async updateFromCompactDict(dict){let binRange=this.brushedBinRange;if(dict.b){let[bMin,bMax]=dict.b.split('_');bMin=parseInt(bMin);bMax=parseInt(bMax);if(bMin!==binRange.min||bMax!==binRange.max){binRange=tr.b.math.Range.fromExplicitRange(bMin,bMax);}}
+await this.update({isOpen:dict.o==='1',brushedBinRange:binRange,mergeSampleDiagnostics:dict.m!=='0',});}}
+tr.b.ViewState.register(HistogramSetTableCellState);return{HistogramSetTableCellState,HistogramSetTableRowState,HistogramSetViewState,};});'use strict';Polymer({is:'tr-v-ui-scalar-map-table',created(){this.scalarMap_=new Map();this.significance_=new Map();},ready(){this.$.table.showHeader=false;this.$.table.tableColumns=[{value(row){return row.name;}},{value(row){const span=tr.v.ui.createScalarSpan(row.value);if(row.significance!==undefined){span.significance=row.significance;}else if(row.anyRowsHaveSignificance){span.style.marginRight='18px';}
+span.style.whiteSpace='nowrap';return span;}}];},get scalarMap(){return this.scalarMap_;},set scalarMap(map){this.scalarMap_=map;this.updateContents_();},setSignificanceForKey(key,significance){this.significance_.set(key,significance);this.updateContents_();},updateContents_(){const rows=[];for(const[key,scalar]of this.scalarMap){rows.push({name:key,value:scalar,significance:this.significance_.get(key),anyRowsHaveSignificance:(this.significance_.size>0)});}
+this.$.table.tableRows=rows;this.$.table.rebuild();}});'use strict';tr.exportTo('tr.v.ui',function(){const DEFAULT_BAR_HEIGHT_PX=5;const TRUNCATE_BIN_MARGIN=0.15;const IGNORE_DELTA_STATISTICS_NAMES=[`${tr.v.DELTA}min`,`%${tr.v.DELTA}min`,`${tr.v.DELTA}max`,`%${tr.v.DELTA}max`,`${tr.v.DELTA}sum`,`%${tr.v.DELTA}sum`,`${tr.v.DELTA}count`,`%${tr.v.DELTA}count`,];Polymer({is:'tr-v-ui-histogram-span',created(){this.viewStateListener_=this.onViewStateUpdate_.bind(this);this.viewState=new tr.v.ui.HistogramSetTableCellState();this.rowStateListener_=this.onRowStateUpdate_.bind(this);this.rowState=new tr.v.ui.HistogramSetTableRowState();this.rootStateListener_=this.onRootStateUpdate_.bind(this);this.rootState=new tr.v.ui.HistogramSetViewState();this.histogram_=undefined;this.referenceHistogram_=undefined;this.graphWidth_=undefined;this.graphHeight_=undefined;this.mouseDownBin_=undefined;this.prevBrushedBinRange_=new tr.b.math.Range();this.anySampleDiagnostics_=false;this.canMergeSampleDiagnostics_=true;this.mwuResult_=undefined;},get rowState(){return this.rowState_;},set rowState(rs){if(this.rowState){this.rowState.removeUpdateListener(this.rowStateListener_);}
+this.rowState_=rs;this.rowState.addUpdateListener(this.rowStateListener_);if(this.isAttached)this.updateContents_();},get viewState(){return this.viewState_;},set viewState(vs){if(this.viewState){this.viewState.removeUpdateListener(this.viewStateListener_);}
+this.viewState_=vs;this.viewState.addUpdateListener(this.viewStateListener_);if(this.isAttached)this.updateContents_();},get rootState(){return this.rootState_;},set rootState(vs){if(this.rootState){this.rootState.removeUpdateListener(this.rootStateListener_);}
+this.rootState_=vs;this.rootState.addUpdateListener(this.rootStateListener_);if(this.isAttached)this.updateContents_();},build(histogram,opt_referenceHistogram){this.histogram_=histogram;this.$.metric_diagnostics.histogram=histogram;this.$.sample_diagnostics.histogram=histogram;this.referenceHistogram_=opt_referenceHistogram;if(this.histogram.canCompare(this.referenceHistogram)){this.mwuResult_=tr.b.math.Statistics.mwu(this.histogram.sampleValues,this.referenceHistogram.sampleValues,this.rootState.alpha);}
+this.anySampleDiagnostics_=false;for(const bin of this.histogram.allBins){if(bin.diagnosticMaps.length>0){this.anySampleDiagnostics_=true;break;}}
+if(this.isAttached)this.updateContents_();},onViewStateUpdate_(event){if(event.delta.brushedBinRange){if(this.chart_!==undefined){this.chart_.brushedRange=this.viewState.brushedBinRange;}
+this.updateDiagnostics_();}
+if(event.delta.mergeSampleDiagnostics&&(this.viewState.mergeSampleDiagnostics!==this.$.merge_sample_diagnostics.checked)){this.$.merge_sample_diagnostics.checked=this.canMergeSampleDiagnostics&&this.viewState.mergeSampleDiagnostics;this.updateDiagnostics_();}},updateSignificance_(){if(!this.mwuResult_)return;this.$.stats.setSignificanceForKey(`${tr.v.DELTA}avg`,this.mwuResult_.significance);},onRootStateUpdate_(event){if(event.delta.alpha&&this.mwuResult_){this.mwuResult_.compare(this.rootState.alpha);this.updateSignificance_();}},onRowStateUpdate_(event){if(event.delta.diagnosticsTab){if(this.rowState.diagnosticsTab===this.$.sample_diagnostics_container.tabLabel){this.updateDiagnostics_();}else{for(const tab of this.$.diagnostics.subViews){if(this.rowState.diagnosticsTab===tab.tabLabel){this.$.diagnostics.selectedSubView=tab;break;}}}}},ready(){this.$.metric_diagnostics.tabLabel='histogram diagnostics';this.$.sample_diagnostics_container.tabLabel='sample diagnostics';this.$.metadata_diagnostics.tabLabel='metadata';this.$.metadata_diagnostics.isMetadata=true;this.$.diagnostics.addEventListener('selected-tab-change',this.onSelectedDiagnosticsChanged_.bind(this));this.$.drag_handle.target=this.$.container;this.$.drag_handle.addEventListener('drag-handle-resize',this.onResize_.bind(this));},attached(){if(this.histogram_!==undefined)this.updateContents_();},get canMergeSampleDiagnostics(){return this.canMergeSampleDiagnostics_;},set canMergeSampleDiagnostics(merge){this.canMergeSampleDiagnostics_=merge;if(!merge)this.viewState.mergeSampleDiagnostics=false;this.$.merge_sample_diagnostics_container.style.display=(merge?'':'none');},onResize_(event){event.stopPropagation();let heightPx=parseInt(this.$.container.style.height);if(heightPx<this.defaultGraphHeight){heightPx=this.defaultGraphHeight;this.$.container.style.height=this.defaultGraphHeight+'px';}
+this.chart_.graphHeight=heightPx-(this.chart_.margin.top+
+this.chart_.margin.bottom);this.$.stats_container.style.maxHeight=this.chart_.getBoundingClientRect().height+'px';},get graphWidth(){return this.graphWidth_||this.defaultGraphWidth;},set graphWidth(width){this.graphWidth_=width;},get graphHeight(){return this.graphHeight_||this.defaultGraphHeight;},set graphHeight(height){this.graphHeight_=height;},get barHeight(){return this.chart_.barHeight;},set barHeight(px){this.graphHeight=this.computeChartHeight_(px);},computeChartHeight_(barHeightPx){return(this.chart_.margin.top+
+this.chart_.margin.bottom+
+(barHeightPx*this.histogram.allBins.length));},get defaultGraphHeight(){if(this.histogram&&this.histogram.allBins.length===1){return 150;}
+return this.computeChartHeight_(DEFAULT_BAR_HEIGHT_PX);},get defaultGraphWidth(){if(this.histogram.allBins.length===1){return 100;}
+return 300;},get brushedBins(){const bins=[];if(this.histogram&&!this.viewState.brushedBinRange.isEmpty){for(let i=this.viewState.brushedBinRange.min;i<this.viewState.brushedBinRange.max;++i){bins.push(this.histogram.allBins[i]);}}
+return bins;},async updateBrushedRange_(binIndex){const brushedBinRange=new tr.b.math.Range();brushedBinRange.addValue(tr.b.math.clamp(this.mouseDownBinIndex_,0,this.histogram.allBins.length-1));brushedBinRange.addValue(tr.b.math.clamp(binIndex,0,this.histogram.allBins.length-1));brushedBinRange.max+=1;await this.viewState.update({brushedBinRange});},onMouseDown_(chartEvent){chartEvent.stopPropagation();if(!this.histogram)return;this.prevBrushedBinRange_=this.viewState.brushedBinRange;this.mouseDownBinIndex_=chartEvent.y;this.updateBrushedRange_(chartEvent.y);},onMouseMove_(chartEvent){chartEvent.stopPropagation();if(!this.histogram)return;this.updateBrushedRange_(chartEvent.y);},onMouseUp_(chartEvent){chartEvent.stopPropagation();if(!this.histogram)return;this.updateBrushedRange_(chartEvent.y);if(this.prevBrushedBinRange_.range===1&&this.viewState.brushedBinRange.range===1&&(this.prevBrushedBinRange_.min===this.viewState.brushedBinRange.min)){tr.b.Timing.instant('histogram-span','clearBrushedBins');this.viewState.update({brushedBinRange:new tr.b.math.Range()});}else{tr.b.Timing.instant('histogram-span','brushBins');}
+this.mouseDownBinIndex_=undefined;},async onSelectedDiagnosticsChanged_(){await this.rowState.update({diagnosticsTab:this.$.diagnostics.selectedSubView.tabLabel,});if((this.$.diagnostics.selectedSubView===this.$.sample_diagnostics_container)&&this.histogram&&this.viewState.brushedBinRange.isEmpty){const brushedBinRange=tr.b.math.Range.fromExplicitRange(0,this.histogram.allBins.length);await this.viewState.update({brushedBinRange});this.updateDiagnostics_();}},updateDiagnostics_(){let maps=[];for(const bin of this.brushedBins){for(const map of bin.diagnosticMaps){maps.push(map);}}
+if(this.$.merge_sample_diagnostics.checked!==this.viewState.mergeSampleDiagnostics){this.viewState.update({mergeSampleDiagnostics:this.$.merge_sample_diagnostics.checked});}
+if(this.viewState.mergeSampleDiagnostics){const merged=new tr.v.d.DiagnosticMap();for(const map of maps){merged.addDiagnostics(map);}
+maps=[merged];}
+const mark=tr.b.Timing.mark('histogram-span',(this.viewState.mergeSampleDiagnostics?'merge':'split')+'SampleDiagnostics');this.$.sample_diagnostics.diagnosticMaps=maps;mark.end();if(this.anySampleDiagnostics_){this.$.diagnostics.selectedSubView=this.$.sample_diagnostics_container;}},get histogram(){return this.histogram_;},get referenceHistogram(){return this.referenceHistogram_;},getDeltaScalars_(statNames,scalarMap){if(!this.histogram.canCompare(this.referenceHistogram))return;for(const deltaStatName of tr.v.Histogram.getDeltaStatisticsNames(statNames)){if(IGNORE_DELTA_STATISTICS_NAMES.includes(deltaStatName))continue;const scalar=this.histogram.getStatisticScalar(deltaStatName,this.referenceHistogram,this.mwuResult_);if(scalar===undefined)continue;scalarMap.set(deltaStatName,scalar);}},set isYLogScale(logScale){this.chart_.isYLogScale=logScale;},async updateContents_(){this.$.chart.style.display='none';this.$.drag_handle.style.display='none';this.$.container.style.justifyContent='';while(Polymer.dom(this.$.chart).lastChild){Polymer.dom(this.$.chart).removeChild(Polymer.dom(this.$.chart).lastChild);}
+if(!this.histogram)return;this.$.container.style.display='';const scalarMap=new Map();this.getDeltaScalars_(this.histogram.statisticsNames,scalarMap);for(const[name,scalar]of this.histogram.statisticsScalars){scalarMap.set(name,scalar);}
+this.$.stats.scalarMap=scalarMap;this.updateSignificance_();const metricDiagnosticMap=new tr.v.d.DiagnosticMap();const metadataDiagnosticMap=new tr.v.d.DiagnosticMap();for(const[key,diagnostic]of this.histogram.diagnostics){if(diagnostic instanceof tr.v.d.RelatedNameMap)continue;if(tr.v.d.RESERVED_NAMES_SET.has(key)){metadataDiagnosticMap.set(key,diagnostic);}else{metricDiagnosticMap.set(key,diagnostic);}}
+const diagnosticTabs=[];if(metricDiagnosticMap.size){this.$.metric_diagnostics.diagnosticMaps=[metricDiagnosticMap];diagnosticTabs.push(this.$.metric_diagnostics);}
+if(this.anySampleDiagnostics_){diagnosticTabs.push(this.$.sample_diagnostics_container);}
+if(metadataDiagnosticMap.size){this.$.metadata_diagnostics.diagnosticMaps=[metadataDiagnosticMap];diagnosticTabs.push(this.$.metadata_diagnostics);}
+this.$.diagnostics.resetSubViews(diagnosticTabs);this.$.diagnostics.set('tabsHidden',diagnosticTabs.length<2);if(this.histogram.numValues<=1){await this.viewState.update({brushedBinRange:tr.b.math.Range.fromExplicitRange(0,this.histogram.allBins.length)});this.$.container.style.justifyContent='flex-end';return;}
+this.$.chart.style.display='block';this.$.drag_handle.style.display='block';if(this.histogram.allBins.length===1){if(this.histogram.min!==this.histogram.max){this.chart_=new tr.ui.b.BoxChart();Polymer.dom(this.$.chart).appendChild(this.chart_);this.chart_.graphWidth=this.graphWidth;this.chart_.graphHeight=this.graphHeight;this.chart_.hideXAxis=true;this.chart_.data=[{x:'',color:'blue',percentile_0:this.histogram.running.min,percentile_25:this.histogram.getApproximatePercentile(0.25),percentile_50:this.histogram.getApproximatePercentile(0.5),percentile_75:this.histogram.getApproximatePercentile(0.75),percentile_100:this.histogram.running.max,}];}
+this.$.stats_container.style.maxHeight=this.chart_.getBoundingClientRect().height+'px';await this.viewState.update({brushedBinRange:tr.b.math.Range.fromExplicitRange(0,this.histogram.allBins.length)});return;}
+this.chart_=new tr.ui.b.NameBarChart();Polymer.dom(this.$.chart).appendChild(this.chart_);this.chart_.graphWidth=this.graphWidth;this.chart_.graphHeight=this.graphHeight;this.chart_.addEventListener('item-mousedown',this.onMouseDown_.bind(this));this.chart_.addEventListener('item-mousemove',this.onMouseMove_.bind(this));this.chart_.addEventListener('item-mouseup',this.onMouseUp_.bind(this));this.chart_.hideLegend=true;this.chart_.getDataSeries('y').color='blue';this.chart_.xAxisLabel='#';this.chart_.brushedRange=this.viewState.brushedBinRange;if(!this.viewState.brushedBinRange.isEmpty){this.updateDiagnostics_();}
+const chartData=[];const binCounts=[];for(const bin of this.histogram.allBins){let x=bin.range.min;if(x===-Number.MAX_VALUE){x='<'+new tr.b.Scalar(this.histogram.unit,bin.range.max).toString();}else{x=new tr.b.Scalar(this.histogram.unit,x).toString();}
+chartData.push({x,y:bin.count});binCounts.push(bin.count);}
+binCounts.sort((x,y)=>y-x);const dataRange=tr.b.math.Range.fromExplicitRange(0,binCounts[0]);if(binCounts[1]>0&&binCounts[0]>(binCounts[1]*2)){dataRange.max=binCounts[1]*(1+TRUNCATE_BIN_MARGIN);}
+if(binCounts[2]>0&&binCounts[1]>(binCounts[2]*2)){dataRange.max=binCounts[2]*(1+TRUNCATE_BIN_MARGIN);}
+this.chart_.overrideDataRange=dataRange;this.chart_.data=chartData;this.$.stats_container.style.maxHeight=this.chart_.getBoundingClientRect().height+'px';}});});'use strict';tr.exportTo('tr.ui.analysis',function(){const EVENT_FIELD=[{key:'start',label:'Start'},{key:'cpuDuration',label:'CPU Duration'},{key:'duration',label:'Duration'},{key:'cpuSelfTime',label:'CPU Self Time'},{key:'selfTime',label:'Self Time'}];function buildDiagnostics_(slice){const diagnostics={};for(const item of EVENT_FIELD){const fieldName=item.key;if(slice[fieldName]===undefined)continue;diagnostics[fieldName]=new tr.v.d.Scalar(new tr.b.Scalar(tr.b.Unit.byName.timeDurationInMs,slice[fieldName]));}
+diagnostics.args=new tr.v.d.GenericSet([slice.args]);diagnostics.event=new tr.v.d.RelatedEventSet(slice);return diagnostics;}
+Polymer({is:'tr-ui-a-multi-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;this.eventsHaveDuration_=true;this.eventsHaveSubRows_=true;},ready(){this.$.radioPicker.style.display='none';this.$.radioPicker.items=EVENT_FIELD;this.$.radioPicker.select('cpuSelfTime');this.$.radioPicker.addEventListener('change',()=>{if(this.isAttached)this.updateContents_();});this.$.histogramSpan.graphWidth=400;this.$.histogramSpan.canMergeSampleDiagnostics=false;this.$.histogramContainer.style.display='none';},attached(){if(this.currentSelection_!==undefined)this.updateContents_();},set selection(selection){if(selection.length<=1){throw new Error('Only supports multiple items');}
+this.setSelectionWithoutErrorChecks(selection);},get selection(){return this.currentSelection_;},setSelectionWithoutErrorChecks(selection){this.currentSelection_=selection;if(this.isAttached)this.updateContents_();},get eventsHaveDuration(){return this.eventsHaveDuration_;},set eventsHaveDuration(eventsHaveDuration){this.eventsHaveDuration_=eventsHaveDuration;if(this.isAttached)this.updateContents_();},get eventsHaveSubRows(){return this.eventsHaveSubRows_;},set eventsHaveSubRows(eventsHaveSubRows){this.eventsHaveSubRows_=eventsHaveSubRows;if(this.isAttached)this.updateContents_();},buildHistogram_(selectedKey){let leftBoundary=Number.MAX_VALUE;let rightBoundary=tr.b.math.Statistics.percentile(this.currentSelection_,0.95,function(value){leftBoundary=Math.min(leftBoundary,value[selectedKey]);return value[selectedKey];});if(leftBoundary===rightBoundary)rightBoundary+=1;const histogram=new tr.v.Histogram('',tr.b.Unit.byName.timeDurationInMs,tr.v.HistogramBinBoundaries.createLinear(leftBoundary,rightBoundary,Math.ceil(Math.sqrt(this.currentSelection_.length))));histogram.customizeSummaryOptions({sum:false,percentile:[0.5,0.9],});for(const slice of this.currentSelection_){histogram.addSample(slice[selectedKey],buildDiagnostics_(slice));}
+return histogram;},updateContents_(){const selection=this.currentSelection_;if(!selection)return;const eventsByTitle=selection.getEventsOrganizedByTitle();const numTitles=Object.keys(eventsByTitle).length;this.$.eventSummaryTable.configure({showTotals:numTitles>1,eventsByTitle,eventsHaveDuration:this.eventsHaveDuration_,eventsHaveSubRows:this.eventsHaveSubRows_});this.$.selectionSummaryTable.selection=this.currentSelection_;if(numTitles===1){this.$.radioPicker.style.display='block';this.$.histogramContainer.style.display='flex';this.$.histogramSpan.build(this.buildHistogram_(this.$.radioPicker.selectedKey));if(this.$.histogramSpan.histogram.numValues===0){this.$.histogramContainer.style.display='none';}}else{this.$.radioPicker.style.display='none';this.$.histogramContainer.style.display='none';}}});return{};});'use strict';tr.exportTo('tr.ui.analysis',function(){const FLOW_IN=0x1;const FLOW_OUT=0x2;const FLOW_IN_OUT=FLOW_IN|FLOW_OUT;function FlowClassifier(){this.numEvents_=0;this.eventsByGUID_={};}
+FlowClassifier.prototype={getFS_(event){let fs=this.eventsByGUID_[event.guid];if(fs===undefined){this.numEvents_++;fs={state:0,event};this.eventsByGUID_[event.guid]=fs;}
+return fs;},addInFlow(event){const fs=this.getFS_(event);fs.state|=FLOW_IN;return event;},addOutFlow(event){const fs=this.getFS_(event);fs.state|=FLOW_OUT;return event;},hasEvents(){return this.numEvents_>0;},get inFlowEvents(){const selection=new tr.model.EventSet();for(const guid in this.eventsByGUID_){const fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN){selection.push(fs.event);}}
+return selection;},get outFlowEvents(){const selection=new tr.model.EventSet();for(const guid in this.eventsByGUID_){const fs=this.eventsByGUID_[guid];if(fs.state===FLOW_OUT){selection.push(fs.event);}}
+return selection;},get internalFlowEvents(){const selection=new tr.model.EventSet();for(const guid in this.eventsByGUID_){const fs=this.eventsByGUID_[guid];if(fs.state===FLOW_IN_OUT){selection.push(fs.event);}}
+return selection;}};return{FlowClassifier,};});'use strict';function*getEventInFlowEvents(event){if(!event.inFlowEvents)return;yield*event.inFlowEvents;}
+function*getEventOutFlowEvents(event){if(!event.outFlowEvents)return;yield*event.outFlowEvents;}
+function*getEventAncestors(event){if(!event.enumerateAllAncestors)return;yield*event.enumerateAllAncestors();}
+function*getEventDescendents(event){if(!event.enumerateAllDescendents)return;yield*event.enumerateAllDescendents();}
+Polymer({is:'tr-ui-a-related-events',ready(){this.eventGroups_=[];this.cancelFunctions_=[];this.$.table.tableColumns=[{title:'Event(s)',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.type;if(row.tooltip){typeEl.title=row.tooltip;}
+return typeEl;},width:'150px'},{title:'Link',width:'100%',value(row){const linkEl=document.createElement('tr-ui-a-analysis-link');if(row.name){linkEl.setSelectionAndContent(row.selection,row.name);}else{linkEl.selection=row.selection;}
+return linkEl;}}];},hasRelatedEvents(){return(this.eventGroups_&&this.eventGroups_.length>0);},setRelatedEvents(eventSet){this.cancelAllTasks_();this.eventGroups_=[];this.addRuntimeCallStats_(eventSet);this.addOverlappingV8ICStats_(eventSet);this.addV8GCObjectStats_(eventSet);this.addV8Slices_(eventSet);this.addConnectedFlows_(eventSet);this.addConnectedEvents_(eventSet);this.addOverlappingSamples_(eventSet);this.updateContents_();},addConnectedFlows_(eventSet){const classifier=new tr.ui.analysis.FlowClassifier();eventSet.forEach(function(slice){if(slice.inFlowEvents){slice.inFlowEvents.forEach(function(flow){classifier.addInFlow(flow);});}
+if(slice.outFlowEvents){slice.outFlowEvents.forEach(function(flow){classifier.addOutFlow(flow);});}});if(!classifier.hasEvents())return;const addToEventGroups=function(type,flowEvent){this.eventGroups_.push({type,selection:new tr.model.EventSet(flowEvent),name:flowEvent.title});};classifier.inFlowEvents.forEach(addToEventGroups.bind(this,'Incoming flow'));classifier.outFlowEvents.forEach(addToEventGroups.bind(this,'Outgoing flow'));classifier.internalFlowEvents.forEach(addToEventGroups.bind(this,'Internal flow'));},cancelAllTasks_(){this.cancelFunctions_.forEach(function(cancelFunction){cancelFunction();});this.cancelFunctions_=[];},addConnectedEvents_(eventSet){this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('Preceding events','Add all events that have led to the selected one(s), connected by '+'flow arrows or by call stack.',eventSet,function*(event){yield*getEventInFlowEvents(event);yield*getEventAncestors(event);if(event.startSlice){yield event.startSlice;}}.bind(this)));this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('Following events','Add all events that have been caused by the selected one(s), '+'connected by flow arrows or by call stack.',eventSet,function*(event){yield*getEventOutFlowEvents(event);yield*getEventDescendents(event);if(event.endSlice){yield event.endSlice;}}.bind(this)));this.cancelFunctions_.push(this.createEventsLinkIfNeeded_('All connected events','Add all events connected to the selected one(s) by flow arrows or '+'by call stack.',eventSet,function*(event){yield*getEventInFlowEvents(event);yield*getEventOutFlowEvents(event);yield*getEventAncestors(event);yield*getEventDescendents(event);if(event.startSlice){yield event.startSlice;}
+if(event.endSlice){yield event.endSlice;}}.bind(this)));},createEventsLinkIfNeeded_(title,tooltip,events,connectedFn){events=new tr.model.EventSet(events);const eventsToProcess=new Set(events);let wasChanged=false;let task;let isCanceled=false;function addEventsUntilTimeout(){if(isCanceled)return;const timeout=window.performance.now()+8;while(eventsToProcess.size>0&&window.performance.now()<=timeout){const nextEvent=tr.b.getFirstElement(eventsToProcess);eventsToProcess.delete(nextEvent);for(const eventToAdd of connectedFn(nextEvent)){if(!events.contains(eventToAdd)){events.push(eventToAdd);eventsToProcess.add(eventToAdd);wasChanged=true;}}}
+if(eventsToProcess.size>0){const newTask=new tr.b.Task(addEventsUntilTimeout.bind(this),this);task.after(newTask);task=newTask;return;}
+if(!wasChanged)return;this.eventGroups_.push({type:title,tooltip,selection:events});this.updateContents_();}
+function cancelTask(){isCanceled=true;}
+task=new tr.b.Task(addEventsUntilTimeout.bind(this),this);tr.b.Task.RunWhenIdle(task);return cancelTask;},addOverlappingSamples_(eventSet){const samples=new tr.model.EventSet();for(const slice of eventSet){if(!slice.parentContainer||!slice.parentContainer.samples){continue;}
+const candidates=slice.parentContainer.samples;const range=tr.b.math.Range.fromExplicitRange(slice.start,slice.start+slice.duration);const filteredSamples=range.filterArray(candidates,function(value){return value.start;});for(const sample of filteredSamples){samples.push(sample);}}
+if(samples.length>0){this.eventGroups_.push({type:'Overlapping samples',tooltip:'All samples overlapping the selected slice(s).',selection:samples});}},addV8Slices_(eventSet){const v8Slices=new tr.model.EventSet();for(const slice of eventSet){if(slice.category==='v8'){v8Slices.push(slice);}}
+if(v8Slices.length>0){this.eventGroups_.push({type:'V8 Slices',tooltip:'All V8 slices in the selected slice(s).',selection:v8Slices});}},addRuntimeCallStats_(eventSet){const slices=eventSet.filter(function(slice){return(slice.category==='v8'||slice.category==='disabled-by-default-v8.runtime_stats')&&slice.runtimeCallStats;});if(slices.length>0){this.eventGroups_.push({type:'Runtime call stats table',tooltip:'All V8 slices containing runtime call stats table in the selected slice(s).',selection:slices});}},addV8GCObjectStats_(eventSet){const slices=new tr.model.EventSet();for(const slice of eventSet){if(slice.title==='V8.GC_Objects_Stats'){slices.push(slice);}}
+if(slices.length>0){this.eventGroups_.push({type:'V8 GC stats table',tooltip:'All V8 GC statistics slices in the selected set.',selection:slices});}},addOverlappingV8ICStats_(eventSet){const slices=new tr.model.EventSet();for(const slice of eventSet){if(!slice.parentContainer||!slice.parentContainer.sliceGroup){continue;}
+const sliceGroup=slice.parentContainer.sliceGroup.slices;const range=tr.b.math.Range.fromExplicitRange(slice.start,slice.start+slice.duration);const filteredSlices=range.filterArray(sliceGroup,value=>value.start);const icSlices=filteredSlices.filter(x=>x.title==='V8.ICStats');for(const icSlice of icSlices){slices.push(icSlice);}}
+if(slices.length>0){this.eventGroups_.push({type:'Overlapping V8 IC stats',tooltip:'All V8 IC statistics overlapping the selected set.',selection:slices});}},updateContents_(){const table=this.$.table;if(this.eventGroups_===undefined){table.tableRows=[];}else{table.tableRows=this.eventGroups_.slice();}
+table.rebuild();}});'use strict';Polymer({is:'tr-ui-a-multi-async-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;this.$.relatedEvents.setRelatedEvents(selection);if(this.$.relatedEvents.hasRelatedEvents()){this.$.relatedEvents.style.display='';}else{this.$.relatedEvents.style.display='none';}},get relatedEventsToHighlight(){if(!this.$.content.selection)return undefined;const selection=new tr.model.EventSet();this.$.content.selection.forEach(function(asyncEvent){if(!asyncEvent.associatedEvents)return;asyncEvent.associatedEvents.forEach(function(event){selection.push(event);});});if(selection.length)return selection;return undefined;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-async-slice-sub-view',tr.model.AsyncSlice,{multi:true,title:'Async Slices',});'use strict';Polymer({is:'tr-ui-a-multi-cpu-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-cpu-slice-sub-view',tr.model.CpuSlice,{multi:true,title:'CPU Slices',});'use strict';Polymer({is:'tr-ui-a-multi-flow-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.$.content.eventsHaveDuration=false;this.$.content.eventsHaveSubRows=false;},set selection(selection){this.$.content.selection=selection;},get selection(){return this.$.content.selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-flow-event-sub-view',tr.model.FlowEvent,{multi:true,title:'Flow Events',});'use strict';Polymer({is:'tr-ui-a-multi-frame-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},set selection(selection){Polymer.dom(this).textContent='';const realView=document.createElement('tr-ui-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;Polymer.dom(this).appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;const selection=new tr.model.EventSet();this.currentSelection_.forEach(function(frameEvent){frameEvent.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-frame-sub-view',tr.model.Frame,{multi:true,title:'Frames',});'use strict';Polymer({is:'tr-ui-a-multi-instant-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},set selection(selection){Polymer.dom(this.$.content).textContent='';const realView=document.createElement('tr-ui-a-multi-event-sub-view');realView.eventsHaveDuration=false;realView.eventsHaveSubRows=false;Polymer.dom(this.$.content).appendChild(realView);realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});'use strict';Polymer({is:'tr-ui-a-multi-object-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},ready(){this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;const objectEvents=Array.from(selection).sort(tr.b.math.Range.compareByMinTimes);const timeSpanConfig={unit:tr.b.Unit.byName.timeStampInMs,ownerDocument:this.ownerDocument};const table=this.$.content;table.tableColumns=[{title:'First',value(event){if(event instanceof tr.model.ObjectSnapshot){return tr.v.ui.createScalarSpan(event.ts,timeSpanConfig);}
+const spanEl=document.createElement('span');Polymer.dom(spanEl).appendChild(tr.v.ui.createScalarSpan(event.creationTs,timeSpanConfig));Polymer.dom(spanEl).appendChild(tr.ui.b.createSpan({textContent:'-',marginLeft:'4px',marginRight:'4px'}));if(event.deletionTs!==Number.MAX_VALUE){Polymer.dom(spanEl).appendChild(tr.v.ui.createScalarSpan(event.deletionTs,timeSpanConfig));}
+return spanEl;},width:'200px'},{title:'Second',value(event){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(function(){return new tr.model.EventSet(event);},event.userFriendlyName);return linkEl;},width:'100%'}];table.tableRows=objectEvents;table.rebuild();}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-object-sub-view',tr.model.ObjectInstance,{multi:true,title:'Object Instances',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-object-sub-view',tr.model.ObjectSnapshot,{multi:true,title:'Object Snapshots',});'use strict';const EventSet=tr.model.EventSet;const CHART_TITLE='Power (W) by ms since vertical sync';Polymer({is:'tr-ui-a-frame-power-usage-chart',ready(){this.chart_=undefined;this.samples_=new EventSet();this.vSyncTimestamps_=[];},attached(){if(this.samples_)this.updateContents_();},get chart(){return this.chart_;},get samples(){return this.samples_;},get vSyncTimestamps(){return this.vSyncTimestamps_;},setData(samples,vSyncTimestamps){this.samples_=(samples===undefined)?new EventSet():samples;this.vSyncTimestamps_=(vSyncTimestamps===undefined)?[]:vSyncTimestamps;if(this.isAttached)this.updateContents_();},updateContents_(){this.clearChart_();const data=this.getDataForLineChart_();if(data.length===0)return;this.chart_=new tr.ui.b.LineChart();Polymer.dom(this.$.content).appendChild(this.chart_);this.chart_.chartTitle=CHART_TITLE;this.chart_.data=data;},clearChart_(){const content=this.$.content;while(Polymer.dom(content).firstChild){Polymer.dom(content).removeChild(Polymer.dom(content).firstChild);}
+this.chart_=undefined;},getDataForLineChart_(){const sortedSamples=this.sortSamplesByTimestampAscending_(this.samples);const vSyncTimestamps=this.vSyncTimestamps.slice();let lastVSyncTimestamp=undefined;const points=[];let frameNumber=0;sortedSamples.forEach(function(sample){while(vSyncTimestamps.length>0&&vSyncTimestamps[0]<=sample.start){lastVSyncTimestamp=vSyncTimestamps.shift();frameNumber++;}
+if(lastVSyncTimestamp===undefined)return;const point={x:sample.start-lastVSyncTimestamp};point['f'+frameNumber]=sample.powerInW;points.push(point);});return points;},sortSamplesByTimestampAscending_(samples){return samples.toArray().sort(function(smpl1,smpl2){return smpl1.start-smpl2.start;});}});'use strict';Polymer({is:'tr-ui-a-power-sample-summary-table',ready(){this.$.table.tableColumns=[{title:'Min power',width:'100px',value(row){return tr.b.Unit.byName.powerInWatts.format(row.min);}},{title:'Max power',width:'100px',value(row){return tr.b.Unit.byName.powerInWatts.format(row.max);}},{title:'Time-weighted average',width:'100px',value(row){return tr.b.Unit.byName.powerInWatts.format(row.timeWeightedAverageInW);}},{title:'Energy consumed',width:'100px',value(row){return tr.b.Unit.byName.energyInJoules.format(row.energyConsumedInJ);}},{title:'Sample count',width:'100%',value(row){return row.sampleCount;}}];this.samples=new tr.model.EventSet();},get samples(){return this.samples_;},set samples(samples){if(samples===this.samples)return;this.samples_=(samples===undefined)?new tr.model.EventSet():samples;this.updateContents_();},updateContents_(){if(this.samples.length===0){this.$.table.tableRows=[];}else{this.$.table.tableRows=[{min:this.getMin(),max:this.getMax(),timeWeightedAverageInW:this.getTimeWeightedAverageInW(),energyConsumedInJ:this.getEnergyConsumedInJ(),sampleCount:this.samples.length}];}
+this.$.table.rebuild();},getMin(){return Math.min.apply(null,this.samples.map(function(sample){return sample.powerInW;}));},getMax(){return Math.max.apply(null,this.samples.map(function(sample){return sample.powerInW;}));},getTimeWeightedAverageInW(){const energyConsumedInJ=this.getEnergyConsumedInJ();if(energyConsumedInJ==='N/A')return'N/A';const durationInS=tr.b.convertUnit(this.samples.bounds.duration,tr.b.UnitPrefixScale.METRIC.MILLI,tr.b.UnitPrefixScale.METRIC.NONE);return energyConsumedInJ/durationInS;},getEnergyConsumedInJ(){if(this.samples.length<2)return'N/A';const bounds=this.samples.bounds;const series=tr.b.getFirstElement(this.samples).series;return series.getEnergyConsumedInJ(bounds.min,bounds.max);}});'use strict';Polymer({is:'tr-ui-a-multi-power-sample-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},updateContents_(){const samples=this.selection;const vSyncTimestamps=(!samples?[]:tr.b.getFirstElement(samples).series.device.vSyncTimestamps);this.$.summaryTable.samples=samples;this.$.chart.setData(this.selection,vSyncTimestamps);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-power-sample-sub-view',tr.model.PowerSample,{multi:true,title:'Power Samples',});'use strict';(function(){const MultiDimensionalViewBuilder=tr.b.MultiDimensionalViewBuilder;Polymer({is:'tr-ui-a-multi-sample-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.viewOption_=undefined;this.selection_=undefined;},ready(){const viewSelector=tr.ui.b.createSelector(this,'viewOption','tracing.ui.analysis.multi_sample_sub_view',MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW,[{label:'Top-down (Tree)',value:MultiDimensionalViewBuilder.ViewType.TOP_DOWN_TREE_VIEW},{label:'Top-down (Heavy)',value:MultiDimensionalViewBuilder.ViewType.TOP_DOWN_HEAVY_VIEW},{label:'Bottom-up (Heavy)',value:MultiDimensionalViewBuilder.ViewType.BOTTOM_UP_HEAVY_VIEW}]);Polymer.dom(this.$.control).appendChild(viewSelector);this.$.table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;this.updateContents_();},get viewOption(){return this.viewOption_;},set viewOption(viewOption){this.viewOption_=viewOption;this.updateContents_();},createSamplingSummary_(selection,viewOption){const builder=new MultiDimensionalViewBuilder(1,1);const samples=selection.filter(event=>event instanceof tr.model.Sample);samples.forEach(function(sample){builder.addPath([sample.userFriendlyStack.reverse()],[1],MultiDimensionalViewBuilder.ValueKind.SELF);});return builder.buildView(viewOption);},processSampleRows_(rows){for(const row of rows){let title=row.title[0];let results=/(.*) (Deoptimized reason: .*)/.exec(title);if(results!==null){row.deoptReason=results[2];title=results[1];}
+results=/(.*) url: (.*)/.exec(title);if(results!==null){row.functionName=results[1];row.url=results[2];if(row.functionName===''){row.functionName='(anonymous function)';}
+if(row.url===''){row.url='unknown';}}else{row.functionName=title;row.url='unknown';}
+this.processSampleRows_(row.subRows);}},updateContents_(){if(this.selection===undefined){this.$.table.tableColumns=[];this.$.table.tableRows=[];this.$.table.rebuild();return;}
+const samplingData=this.createSamplingSummary_(this.selection,this.viewOption);const total=samplingData.values[0].total;const columns=[this.createPercentColumn_('Total',total),this.createSamplesColumn_('Total'),this.createPercentColumn_('Self',total),this.createSamplesColumn_('Self'),{title:'Function Name',value(row){if(row.deoptReason!==undefined){const spanEl=tr.ui.b.createSpan({italic:true,color:'#F44336',tooltip:row.deoptReason});spanEl.innerText=row.functionName;return spanEl;}
+return row.functionName;},width:'150px',cmp:(a,b)=>a.functionName.localeCompare(b.functionName),showExpandButtons:true},{title:'Location',value(row){return row.url;},width:'250px',cmp:(a,b)=>a.url.localeCompare(b.url),}];this.processSampleRows_(samplingData.subRows);this.$.table.tableColumns=columns;this.$.table.sortColumnIndex=1;this.$.table.sortDescending=true;this.$.table.tableRows=samplingData.subRows;this.$.table.rebuild();},createPercentColumn_(title,samplingDataTotal){const field=title.toLowerCase();return{title:title+' percent',value(row){return tr.v.ui.createScalarSpan(row.values[0][field]/samplingDataTotal,{customContextRange:tr.b.math.Range.PERCENT_RANGE,unit:tr.b.Unit.byName.normalizedPercentage,context:{minimumFractionDigits:2,maximumFractionDigits:2},});},width:'60px',cmp:(a,b)=>a.values[0][field]-b.values[0][field]};},createSamplesColumn_(title){const field=title.toLowerCase();return{title:title+' samples',value(row){return tr.v.ui.createScalarSpan(row.values[0][field],{unit:tr.b.Unit.byName.unitlessNumber,context:{maximumFractionDigits:0},});},width:'60px',cmp:(a,b)=>a.values[0][field]-b.values[0][field]};}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-sample-sub-view',tr.model.Sample,{multi:true,title:'Samples',});})();'use strict';Polymer({is:'tr-ui-a-multi-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.selection_=undefined;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;if(tr.isExported('tr.ui.e.chrome.cc.RasterTaskSelection')){if(tr.ui.e.chrome.cc.RasterTaskSelection.supports(selection)){const ltvSelection=new tr.ui.e.chrome.cc.RasterTaskSelection(selection);const ltv=new tr.ui.e.chrome.cc.LayerTreeHostImplSnapshotView();ltv.objectSnapshot=ltvSelection.containingSnapshot;ltv.selection=ltvSelection;ltv.extraHighlightsByLayerId=ltvSelection.extraHighlightsByLayerId;Polymer.dom(this.$.content).textContent='';Polymer.dom(this.$.content).appendChild(ltv);this.requiresTallView_=true;return;}}
+Polymer.dom(this.$.content).textContent='';const mesv=document.createElement('tr-ui-a-multi-event-sub-view');mesv.selection=selection;Polymer.dom(this.$.content).appendChild(mesv);const relatedEvents=document.createElement('tr-ui-a-related-events');relatedEvents.setRelatedEvents(selection);if(relatedEvents.hasRelatedEvents()){Polymer.dom(this.$.content).appendChild(relatedEvents);}},get requiresTallView(){if(this.$.content.children.length===0)return false;const childTagName=this.$.content.children[0].tagName;if(childTagName==='TR-UI-A-MULTI-EVENT-SUB-VIEW'){return false;}
+return true;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-thread-slice-sub-view',tr.model.ThreadSlice,{multi:true,title:'Slices',});'use strict';Polymer({is:'tr-ui-a-multi-thread-time-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.$.content.eventsHaveSubRows=false;},get selection(){return this.$.content.selection;},set selection(selection){this.$.content.setSelectionWithoutErrorChecks(selection);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-thread-time-slice-sub-view',tr.model.ThreadTimeSlice,{multi:true,title:'Thread Timeslices',});'use strict';Polymer({is:'tr-ui-a-user-expectation-related-samples-table',ready(){this.samples_=[];this.$.table.tableColumns=[{title:'Event(s)',value(row){const typeEl=document.createElement('span');typeEl.innerText=row.type;if(row.tooltip){typeEl.title=row.tooltip;}
+return typeEl;},width:'150px'},{title:'Link',width:'100%',value(row){const linkEl=document.createElement('tr-ui-a-analysis-link');if(row.name){linkEl.setSelectionAndContent(row.selection,row.name);}else{linkEl.selection=row.selection;}
+return linkEl;}}];},hasRelatedSamples(){return(this.samples_&&this.samples_.length>0);},set selection(eventSet){this.samples_=[];const samples=new tr.model.EventSet;eventSet.forEach(function(ue){samples.addEventSet(ue.associatedSamples);}.bind(this));if(samples.length>0){this.samples_.push({type:'Overlapping samples',tooltip:'All samples overlapping the selected user expectation(s).',selection:samples});}
+this.updateContents_();},updateContents_(){const table=this.$.table;if(this.samples_&&this.samples_.length>0){table.tableRows=this.samples_.slice();}else{table.tableRows=[];}
+table.rebuild();}});'use strict';Polymer({is:'tr-ui-a-multi-interaction-record-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},set selection(selection){this.currentSelection_=selection;this.$.realView.setSelectionWithoutErrorChecks(selection);this.currentSelection_=selection;this.$.relatedSamples.selection=selection;if(this.$.relatedSamples.hasRelatedSamples()){this.$.events.style.display='';}else{this.$.events.style.display='none';}},get selection(){return this.currentSelection_;},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;const selection=new tr.model.EventSet();this.currentSelection_.forEach(function(ir){ir.associatedEvents.forEach(function(event){selection.push(event);});});return selection;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-user-expectation-sub-view',tr.model.um.UserExpectation,{multi:true,title:'User Expectations',});'use strict';Polymer({is:'tr-ui-a-single-async-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){if(selection.length!==1){throw new Error('Only supports single slices');}
+this.$.content.setSelectionWithoutErrorChecks(selection);this.$.relatedEvents.setRelatedEvents(selection);if(this.$.relatedEvents.hasRelatedEvents()){this.$.relatedEvents.style.display='';}else{this.$.relatedEvents.style.display='none';}},getEventRows_(event){const rows=this.__proto__.__proto__.getEventRows_(event);rows.splice(0,0,{name:'ID',value:event.id});return rows;},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-async-slice-sub-view',tr.model.AsyncSlice,{multi:false,title:'Async Slice',});'use strict';Polymer({is:'tr-ui-a-single-cpu-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){const cpuSlice=tr.b.getOnlyElement(selection);if(!(cpuSlice instanceof tr.model.CpuSlice)){throw new Error('Only supports thread time slices');}
+this.currentSelection_=selection;const thread=cpuSlice.threadThatWasRunning;const root=Polymer.dom(this.root);if(thread){Polymer.dom(root.querySelector('#process-name')).textContent=thread.parent.userFriendlyName;Polymer.dom(root.querySelector('#thread-name')).textContent=thread.userFriendlyName;}else{root.querySelector('#process-name').parentElement.style.display='none';Polymer.dom(root.querySelector('#thread-name')).textContent=cpuSlice.title;}
+root.querySelector('#start').setValueAndUnit(cpuSlice.start,tr.b.Unit.byName.timeStampInMs);root.querySelector('#duration').setValueAndUnit(cpuSlice.duration,tr.b.Unit.byName.timeDurationInMs);const runningThreadEl=root.querySelector('#running-thread');const timeSlice=cpuSlice.getAssociatedTimeslice();if(!timeSlice){runningThreadEl.parentElement.style.display='none';}else{const threadLink=document.createElement('tr-ui-a-analysis-link');threadLink.selection=new tr.model.EventSet(timeSlice);Polymer.dom(threadLink).textContent='Click to select';runningThreadEl.parentElement.style.display='';Polymer.dom(runningThreadEl).textContent='';Polymer.dom(runningThreadEl).appendChild(threadLink);}
+root.querySelector('#args').object=cpuSlice.args;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-cpu-slice-sub-view',tr.model.CpuSlice,{multi:false,title:'CPU Slice',});'use strict';function createAnalysisLinkTo(event){const linkEl=document.createElement('tr-ui-a-analysis-link');linkEl.setSelectionAndContent(new tr.model.EventSet(event),event.userFriendlyName);return linkEl;}
+Polymer({is:'tr-ui-a-single-flow-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],listeners:{'singleEventSubView.customize-rows':'onCustomizeRows_'},set selection(selection){this.currentSelection_=selection;this.$.singleEventSubView.setSelectionWithoutErrorChecks(selection);},get selection(){return this.currentSelection_;},onCustomizeRows_(e){const event=tr.b.getOnlyElement(this.currentSelection_);const rows=e.rows;rows.unshift({name:'ID',value:event.id});rows.push({name:'From',value:createAnalysisLinkTo(event.startSlice)});rows.push({name:'To',value:createAnalysisLinkTo(event.endSlice)});}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-flow-event-sub-view',tr.model.FlowEvent,{multi:false,title:'Flow Event',});'use strict';Polymer({is:'tr-ui-a-single-frame-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.$.asv.selection=tr.b.getOnlyElement(selection).associatedAlerts;},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-frame-sub-view',tr.model.Frame,{multi:false,title:'Frame',});'use strict';Polymer({is:'tr-ui-a-single-instant-event-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},set selection(selection){Polymer.dom(this.$.content).textContent='';const realView=document.createElement('tr-ui-a-single-event-sub-view');realView.setSelectionWithoutErrorChecks(selection);Polymer.dom(this.$.content).appendChild(realView);this.currentSelection_=selection;},get selection(){return this.currentSelection_;}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-instant-event-sub-view',tr.model.InstantEvent,{multi:false,title:'Instant Event',});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-multi-instant-event-sub-view',tr.model.InstantEvent,{multi:true,title:'Instant Events',});'use strict';tr.exportTo('tr.ui.analysis',function(){const ObjectInstanceView=tr.ui.b.define('object-instance-view');ObjectInstanceView.prototype={__proto__:HTMLDivElement.prototype,decorate(){this.objectInstance_=undefined;},get requiresTallView(){return true;},set modelEvent(obj){this.objectInstance=obj;},get modelEvent(){return this.objectInstance;},get objectInstance(){return this.objectInstance_;},set objectInstance(i){this.objectInstance_=i;this.updateContents();},updateContents(){throw new Error('Not implemented');}};const options=new tr.b.ExtensionRegistryOptions(tr.b.TYPE_BASED_REGISTRY_MODE);options.mandatoryBaseClass=ObjectInstanceView;options.defaultMetadata={showInTrackView:true};tr.b.decorateExtensionRegistry(ObjectInstanceView,options);return{ObjectInstanceView,};});'use strict';Polymer({is:'tr-ui-a-single-object-instance-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},get requiresTallView(){if(this.$.content.children.length===0){return false;}
+if(this.$.content.children[0]instanceof
+tr.ui.analysis.ObjectInstanceView){return this.$.content.children[0].requiresTallView;}},get selection(){return this.currentSelection_;},set selection(selection){const instance=tr.b.getOnlyElement(selection);if(!(instance instanceof tr.model.ObjectInstance)){throw new Error('Only supports object instances');}
+Polymer.dom(this.$.content).textContent='';this.currentSelection_=selection;const typeInfo=tr.ui.analysis.ObjectInstanceView.getTypeInfo(instance.category,instance.typeName);if(typeInfo){const customView=new typeInfo.constructor();Polymer.dom(this.$.content).appendChild(customView);customView.modelEvent=instance;}else{this.appendGenericAnalysis_(instance);}},appendGenericAnalysis_(instance){let html='';html+='<div class="title">'+
+instance.typeName+' '+
+instance.id+'</div>\n';html+='<table>';html+='<tr>';html+='<tr><td>creationTs:</td><td>'+
+instance.creationTs+'</td></tr>\n';if(instance.deletionTs!==Number.MAX_VALUE){html+='<tr><td>deletionTs:</td><td>'+
+instance.deletionTs+'</td></tr>\n';}else{html+='<tr><td>deletionTs:</td><td>not deleted</td></tr>\n';}
+html+='<tr><td>snapshots:</td><td id="snapshots"></td></tr>\n';html+='</table>';Polymer.dom(this.$.content).innerHTML=html;const snapshotsEl=Polymer.dom(this.$.content).querySelector('#snapshots');instance.snapshots.forEach(function(snapshot){const snapshotLink=document.createElement('tr-ui-a-analysis-link');snapshotLink.selection=new tr.model.EventSet(snapshot);Polymer.dom(snapshotsEl).appendChild(snapshotLink);});}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-object-instance-sub-view',tr.model.ObjectInstance,{multi:false,title:'Object Instance',});'use strict';Polymer({is:'tr-ui-a-single-object-snapshot-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},get requiresTallView(){if(this.children.length===0){return false;}
+if(this.children[0]instanceof tr.ui.analysis.ObjectSnapshotView){return this.children[0].requiresTallView;}},get selection(){return this.currentSelection_;},set selection(selection){const snapshot=tr.b.getOnlyElement(selection);if(!(snapshot instanceof tr.model.ObjectSnapshot)){throw new Error('Only supports object instances');}
+Polymer.dom(this).textContent='';this.currentSelection_=selection;const typeInfo=tr.ui.analysis.ObjectSnapshotView.getTypeInfo(snapshot.objectInstance.category,snapshot.objectInstance.typeName);if(typeInfo){const customView=new typeInfo.constructor();Polymer.dom(this).appendChild(customView);customView.modelEvent=snapshot;}else{this.appendGenericAnalysis_(snapshot);}},appendGenericAnalysis_(snapshot){const instance=snapshot.objectInstance;Polymer.dom(this).textContent='';const titleEl=document.createElement('div');Polymer.dom(titleEl).classList.add('title');Polymer.dom(titleEl).appendChild(document.createTextNode('Snapshot of '));Polymer.dom(this).appendChild(titleEl);const instanceLinkEl=document.createElement('tr-ui-a-analysis-link');instanceLinkEl.selection=new tr.model.EventSet(instance);Polymer.dom(titleEl).appendChild(instanceLinkEl);Polymer.dom(titleEl).appendChild(document.createTextNode(' @ '));Polymer.dom(titleEl).appendChild(tr.v.ui.createScalarSpan(snapshot.ts,{unit:tr.b.Unit.byName.timeStampInMs,ownerDocument:this.ownerDocument,inline:true,}));const tableEl=document.createElement('table');Polymer.dom(this).appendChild(tableEl);const rowEl=document.createElement('tr');Polymer.dom(tableEl).appendChild(rowEl);const labelEl=document.createElement('td');Polymer.dom(labelEl).textContent='args:';Polymer.dom(rowEl).appendChild(labelEl);const argsEl=document.createElement('td');argsEl.id='args';Polymer.dom(rowEl).appendChild(argsEl);const objectViewEl=document.createElement('tr-ui-a-generic-object-view');objectViewEl.object=snapshot.args;Polymer.dom(argsEl).appendChild(objectViewEl);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-object-snapshot-sub-view',tr.model.ObjectSnapshot,{multi:false,title:'Object Snapshot',});'use strict';Polymer({is:'tr-ui-a-power-sample-table',ready(){this.$.table.tableColumns=[{title:'Time',width:'100px',value(row){return tr.v.ui.createScalarSpan(row.start,{unit:tr.b.Unit.byName.timeStampInMs});}},{title:'Power',width:'100%',value(row){return tr.v.ui.createScalarSpan(row.powerInW,{unit:tr.b.Unit.byName.powerInWatts});}}];this.sample=undefined;},get sample(){return this.sample_;},set sample(sample){this.sample_=sample;this.updateContents_();},updateContents_(){if(this.sample===undefined){this.$.table.tableRows=[];}else{this.$.table.tableRows=[this.sample];}
+this.$.table.rebuild();}});'use strict';Polymer({is:'tr-ui-a-single-power-sample-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],ready(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;this.updateContents_();},updateContents_(){if(this.selection.length!==1){throw new Error('Cannot pass multiple samples to sample table.');}
+this.$.samplesTable.sample=tr.b.getOnlyElement(this.selection);}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-power-sample-sub-view',tr.model.PowerSample,{multi:false,title:'Power Sample',});'use strict';Polymer({is:'tr-ui-a-single-sample-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},ready(){this.$.content.tableColumns=[{title:'',value:row=>row.title,width:'100px'},{title:'',value:row=>row.value,width:'100%'}];this.$.content.showHeader=false;},get selection(){return this.currentSelection_;},set selection(selection){this.currentSelection_=selection;if(this.currentSelection_===undefined){this.$.content.tableRows=[];return;}
+const sample=tr.b.getOnlyElement(this.currentSelection_);const table=this.$.content;const rows=[];rows.push({title:'Title',value:sample.title});rows.push({title:'Sample time',value:tr.v.ui.createScalarSpan(sample.start,{unit:tr.b.Unit.byName.timeStampInMs,ownerDocument:this.ownerDocument})});const callStackTableEl=document.createElement('tr-ui-b-table');callStackTableEl.tableRows=sample.getNodesAsArray().reverse();callStackTableEl.tableColumns=[{title:'function name',value:row=>row.functionName||'(anonymous function)'},{title:'location',value:row=>row.url}];callStackTableEl.rebuild();rows.push({title:'Call stack',value:callStackTableEl});table.tableRows=rows;table.rebuild();}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-sample-sub-view',tr.model.Sample,{multi:false,title:'Sample',});'use strict';Polymer({is:'tr-ui-a-single-thread-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],get selection(){return this.$.content.selection;},set selection(selection){this.$.content.selection=selection;this.$.relatedEvents.setRelatedEvents(selection);if(this.$.relatedEvents.hasRelatedEvents()){this.$.relatedEvents.style.display='';}else{this.$.relatedEvents.style.display='none';}}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-thread-slice-sub-view',tr.model.ThreadSlice,{multi:false,title:'Slice',});'use strict';Polymer({is:'tr-ui-a-single-thread-time-slice-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){const timeSlice=tr.b.getOnlyElement(selection);if(!(timeSlice instanceof tr.model.ThreadTimeSlice)){throw new Error('Only supports thread time slices');}
+this.currentSelection_=selection;const thread=timeSlice.thread;const root=Polymer.dom(this.root);Polymer.dom(root.querySelector('#state')).textContent=timeSlice.title;const stateColor=tr.b.ColorScheme.colorsAsStrings[timeSlice.colorId];root.querySelector('#state').style.backgroundColor=stateColor;Polymer.dom(root.querySelector('#process-name')).textContent=thread.parent.userFriendlyName;Polymer.dom(root.querySelector('#thread-name')).textContent=thread.userFriendlyName;root.querySelector('#start').setValueAndUnit(timeSlice.start,tr.b.Unit.byName.timeStampInMs);root.querySelector('#duration').setValueAndUnit(timeSlice.duration,tr.b.Unit.byName.timeDurationInMs);const onCpuEl=root.querySelector('#on-cpu');Polymer.dom(onCpuEl).textContent='';const runningInsteadEl=root.querySelector('#running-instead');if(timeSlice.cpuOnWhichThreadWasRunning){Polymer.dom(runningInsteadEl.parentElement).removeChild(runningInsteadEl);const cpuLink=document.createElement('tr-ui-a-analysis-link');cpuLink.selection=new tr.model.EventSet(timeSlice.getAssociatedCpuSlice());Polymer.dom(cpuLink).textContent=timeSlice.cpuOnWhichThreadWasRunning.userFriendlyName;Polymer.dom(onCpuEl).appendChild(cpuLink);}else{Polymer.dom(onCpuEl.parentElement).removeChild(onCpuEl);const cpuSliceThatTookCpu=timeSlice.getCpuSliceThatTookCpu();if(cpuSliceThatTookCpu){const cpuLink=document.createElement('tr-ui-a-analysis-link');cpuLink.selection=new tr.model.EventSet(cpuSliceThatTookCpu);if(cpuSliceThatTookCpu.thread){Polymer.dom(cpuLink).textContent=cpuSliceThatTookCpu.thread.userFriendlyName;}else{Polymer.dom(cpuLink).textContent=cpuSliceThatTookCpu.title;}
+Polymer.dom(runningInsteadEl).appendChild(cpuLink);}else{Polymer.dom(runningInsteadEl.parentElement).removeChild(runningInsteadEl);}}
+const argsEl=root.querySelector('#args');if(Object.keys(timeSlice.args).length>0){const argsView=document.createElement('tr-ui-a-generic-object-view');argsView.object=timeSlice.args;argsEl.parentElement.style.display='';Polymer.dom(argsEl).textContent='';Polymer.dom(argsEl).appendChild(argsView);}else{argsEl.parentElement.style.display='none';}}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-thread-time-slice-sub-view',tr.model.ThreadTimeSlice,{multi:false,title:'Thread Timeslice',});'use strict';Polymer({is:'tr-ui-a-single-user-expectation-sub-view',behaviors:[tr.ui.analysis.AnalysisSubView],created(){this.currentSelection_=undefined;},get selection(){return this.currentSelection_;},set selection(selection){this.$.realView.addEventListener('customize-rows',this.onCustomizeRows_.bind(this));this.currentSelection_=selection;this.$.realView.setSelectionWithoutErrorChecks(selection);this.$.relatedSamples.selection=selection;if(this.$.relatedSamples.hasRelatedSamples()){this.$.events.style.display='';}else{this.$.events.style.display='none';}},get relatedEventsToHighlight(){if(!this.currentSelection_)return undefined;return tr.b.getOnlyElement(this.currentSelection_).associatedEvents;},onCustomizeRows_(event){const ue=tr.b.getOnlyElement(this.selection);if(ue.rawCpuMs){event.rows.push({name:'Total CPU',value:tr.v.ui.createScalarSpan(ue.totalCpuMs,{unit:tr.b.Unit.byName.timeDurationInMs})});}}});tr.ui.analysis.AnalysisSubView.register('tr-ui-a-single-user-expectation-sub-view',tr.model.um.UserExpectation,{multi:false,title:'User Expectation',});'use strict';(function(){const EventRegistry=tr.model.EventRegistry;function getTabStripLabel(numEvents){if(numEvents===0){return'Nothing selected. Tap stuff.';}else if(numEvents===1){return'1 item selected.';}
+return numEvents+' items selected.';}
+function createSubView(subViewTypeInfo,selection){let tagName;if(selection.length===1){tagName=subViewTypeInfo.singleTagName;}else{tagName=subViewTypeInfo.multiTagName;}
+if(tagName===undefined){throw new Error('No view registered for '+
+subViewTypeInfo.eventConstructor.name);}
+const subView=document.createElement(tagName);let title;if(selection.length===1){title=subViewTypeInfo.singleTitle;}else{title=subViewTypeInfo.multiTitle;}
+title+=' ('+selection.length+')';subView.tabLabel=title;subView.selection=selection;return subView;}
+Polymer({is:'tr-ui-a-analysis-view',ready(){this.brushingStateController_=undefined;this.lastSelection_=undefined;this.tabView_=document.createElement('tr-ui-b-tab-view');this.tabView_.addEventListener('selected-tab-change',this.onSelectedSubViewChanged_.bind(this));Polymer.dom(this).appendChild(this.tabView_);},set tallMode(value){Polymer.dom(this).classList.toggle('tall-mode',value);},get tallMode(){return Polymer.dom(this).classList.contains('tall-mode');},get tabView(){return this.tabView_;},get brushingStateController(){return this.brushingStateController_;},set brushingStateController(brushingStateController){if(this.brushingStateController_){this.brushingStateController_.removeEventListener('change',this.onSelectionChanged_.bind(this));}
+this.brushingStateController_=brushingStateController;if(this.brushingStateController){this.brushingStateController_.addEventListener('change',this.onSelectionChanged_.bind(this));}
+this.onSelectionChanged_();},get selection(){return this.brushingStateController_.selection;},onSelectionChanged_(e){if(this.lastSelection_&&this.selection.equals(this.lastSelection_)){return;}
+this.lastSelection_=this.selection;this.tallMode=false;this.tabView_.label=getTabStripLabel(this.selection.length);const eventsByBaseTypeName=this.selection.getEventsOrganizedByBaseType(true);const ASV=tr.ui.analysis.AnalysisSubView;const eventsByTagName=ASV.getEventsOrganizedByTypeInfo(this.selection);const newSubViews=[];eventsByTagName.forEach(function(events,typeInfo){newSubViews.push(createSubView(typeInfo,events));});this.tabView_.resetSubViews(newSubViews);},onSelectedSubViewChanged_(){const selectedSubView=this.tabView_.selectedSubView;if(!selectedSubView){this.tallMode=false;this.maybeChangeRelatedEvents_(undefined);return;}
+this.tallMode=selectedSubView.requiresTallView;this.maybeChangeRelatedEvents_(selectedSubView.relatedEventsToHighlight);},maybeChangeRelatedEvents_(events){if(this.brushingStateController){this.brushingStateController.changeAnalysisViewRelatedEvents(events);}}});})();'use strict';tr.exportTo('tr.ui.b',function(){Polymer({is:'tr-ui-b-dropdown',properties:{label:{type:String,value:'',},},open(){if(this.isOpen)return;Polymer.dom(this.$.button).classList.add('open');const buttonRect=this.$.button.getBoundingClientRect();this.$.dialog.style.top=buttonRect.bottom-1+'px';this.$.dialog.style.left=buttonRect.left+'px';this.$.dialog.showModal();const dialogRect=this.$.dialog.getBoundingClientRect();if(dialogRect.right>window.innerWidth){this.$.dialog.style.left=Math.max(0,buttonRect.right-
+dialogRect.width)+'px';}},onDialogTap_(event){if(event.detail.sourceEvent.srcElement!==unwrap(this.$.dialog))return;const dialogRect=this.$.dialog.getBoundingClientRect();let inside=true;inside&=event.detail.x>=dialogRect.left;inside&=event.detail.x<dialogRect.right;inside&=event.detail.y>=dialogRect.top;inside&=event.detail.y<dialogRect.bottom;if(inside)return;event.preventDefault();this.close();},close(){if(!this.isOpen)return;this.$.dialog.close();Polymer.dom(this.$.button).classList.remove('open');this.$.button.focus();},get isOpen(){return this.$.button.classList.contains('open');}});return{};});'use strict';tr.exportTo('tr.ui.b',function(){const FaviconsByHue={blue:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAlrklEQVR4Ae2dCXwdVb3H5265yc3SpEk3ukEXCqVUBLT4Wm19oFKtaN0fKijy9CMguPBarIJsIiA8qsjTh7SllAoFeVBaEARkLV1ooXtL0yRdkqZp9u3uy/v/5uY/OZm75y659+acdnLOnP385zv/+58zZ2YMinTplIAhzsoDceaT2RKUQLwHIMFqh0V2ll0kn4XA6byv9/Vw834kX19e7keRQCzhRyk6bJJYRvD1YTXuhRdeqDj77LPPtNls400mU7HRaCzFFggEVJ/iSqhsicFgKIXUKL6bvB6fz9fj9/u7Kb4bPjaK67Xb7Q0HDhw49IUvfKEd2XUb7WpxHIYvXRgJ8AELkzRso1gmKrwkBfjG7373u5Zly5ZNKS8vn2G1Ws80m83YphPI0wnQUemQFp0IzQR9tdfrxXbI5XId6ujo+PCuu+6qXbNmjYfa9NMmngDoBmt+hIe944M53AUhwqwCvXTp0qJrr732opKSkk8XFhZ+imC+gIAryAZB0QnlJuB3OJ3Ot3p6el5/6KGHttxzzz0O6pse+GEP+3AGnKE2EhgG0tAFt99++4WkoT9tsVgW0DaH4guzAeg4+uD0eDxbaXuDNPzrt9xyy3bS8G4qB8BF6OOoKr+yDDfAB0B91VVXFf72t7+9lLT05QUFBZfQoYWtnA+ux+12v0ra/W+/+tWvXlq5cqWTBjUsYR8OgDPU8KGtjR9++OHHx4wZ8+2ioqKv0X4lbfnsWh0Ox9+bmprWzpgxYxsNFBpd1Op5bcbkM+AMtgr11q1bTz/zzDP/gy4Qv02zGtPzmehIY6MZmmq6UF176NChJ+bMmXOkD3QR9khFczY+HwEXwTbV1NTMI229FCYIXSTm43gTho8uUgMwYUir3zN16tR3qAIfbXkJej4dcIxF1dbkm44ePfqZqqqqpTT7MZf2pYsgAZqN2dTS0nLP5MmTX6EsDDrDHqFU7kTnA+Aa2BMmTDBv2bLliyNHjlxCZsgFuXMYhr6nZL7saGtru/eiiy7aUF9f76UeAfKcBz2XAUffVbgJbAuB/Y3KysoldONl5tDjkrs9oBtL+1tbWwH6UwS6/mZSzg0sVwHXTJG9e/deOGXKlOWksS/MOelncYdJo2+vra396axZs7ZTN0XTJYt7Hdq1XANc1dg0DNOqVatGLl68+DZa/3E1XTwCeOn6JLCly6ncU9+mNLnBZRLOYPAHHI5H2l5/8TdHbl3SRjUx6DkztZgrgKOfDLf5xIkT36moqLiLzJG0rAFJAomsKDp1W51S74IZnSIX8DcrXV3LlK/Oe5xqZPsckGc96LkAOPpowrZ79+5ZNK31BzkzQtKI4qxvV0dJTSLJ592kHKu7QfnPxXupFmhzbFkNeTb/tGsae/bs2Va6wr/lrLPO2izhTgLQZIuaaMp1yvTNyvNbb1HomFB1ZtrAUNYqymztGMNt2rhx44T58+evohs1n0r2+AyX8mnT4KIAvZ63lA82f1/55TX1FJ21tnk2As4zJObq6urP0BTgCmlri2TFDmcEcHQDtnlz4w+Uyz+Hm0Rsm2PuPGtcNpkomtZesGBBYXNz8210d+05CXfWsBLaEQNd5I+e8JyyYettCh0zyoBrpawyWbJFg2twv/jiixPnzZu3mhZFzQ2VqIyJRwIZ0+BiZzyeTcqebVcqS350nKKzxmTJBsDRB3WWZN++fXPpps060tpVouxkODEJDAng6GIg0KI0Hv+mcsXnN9FeVsyyDLWJwnCbadXfomnTpm2UcCcGc1blNhiqlNMmblT+9soi6hdmWKC4hlSJDiXgaBsCsNDKvysnTpz4JIWLaJMupyVgKFLGjHtSefrNK2kYFtpwjIeMs6FqWIOb7kr+Yty4cX+m2+0446XLBwkESHuPrPqz8uymX9BwhhTyoQBchZseQiigdcj30grAO+SDCPlAtW4MeLikdMQdyvqt9yp0rCl1SDR5pgFX4V64cGERvdhmRWlp6XU6scjdfJNAcfF1ysqNK5Q5C2F+ZhzyTF4AqHCPGjXKSjdwHqUHfr+ab8cyW8YzZLMo0QTgcj2jfO/S7ynNzS7KxtOI0UqkJC1TGlyFm3pccPDgwfsk3Ck5drlVidX6VWXFxvvAAG0Z0+SZAJzhtjQ2Ni6ld5D8KLeOjOxtyiRgK/6R8uy7S6m+jF14phtwmEBow3L8+PGr6FnJm1MmLFlRbkqgtOxm5am3rgITtIGNtJrJ6QQcHcdPkYUuKL9MsybLKSydlICijKxcrjz+0pdJFKzJ0wZ5ugBnuM27du2aT7ffV9JUIGCXTkqAJEAsjJ2wQlm1fj7tpPWOZzoAB9yo1/zSSy/NoLdJraMwFsdLJyUgSqBQGX/GOuX+FTMoEpCDmZRr8nQBbqIHgovnzp27mtaWlImjkmEpAU0CYGPmR1crF19cTHH4hU854KmuECcMOmo9derUAyNGjLiawtJlWAJZOQ8eTQb27keUyz7xM8qS8jnyVGpwNk0s+/fv/4qEO9oRlWkDJGArvVpZ89JXKC7lMyupApzhNm/YsGH6GWec8eCAAcgdKYFYEhhz2oPK3X+ZTtlSao+nEnDzxWRL0eNmj0q7O9bRlOkhEoA9ft6cR5WPq/Y4IE+J+ZyKSjS7m56jvK+srEzeqQw5epmNyDkbXBRPT8//Kl++6EaKSok9nqwG10yTHTt2fJpWB0q4xYMlw4lLoJhu5z/y3KepYEpMlWQBV7U3mSXFNN99H71YPfEByRJSAqIEwND4yfcpFyzgqcOkGE2mMGtvy2OPPXY9vZjnTLGfMiwlMGgJWCxnKktv/QmVT3pWZbCAM9zmxx9//IzRo0fj0STppARSJ4HykTcqN//3GVRhUqZKMoCrC6no6Zy7yTSxpW5ksiYpAZKA0WhTPj73dxRKakHWYABn7W3Zs2cPvjH5eXlApATSIoGi4i8oK56/tA9ysAr2EnKDARxlzJdddlkJ3dC5N6HWZGYpgUQlMH7SvbRWpYSKsamSUA2JAs7a2/ynP/3pOvrc9eSEWpOZpQQSlYDZPFn54a/xcDoDnpAWTxRw5DfRJ7DL6HUPP060rzK/lMCgJFA+8sfKZd/CqlRc9yXEbCKZWXtbli1b9gN6EX3loDorC0kJJCoBk6lS+ebVP6BiCU8bJgI48ppxU2fs2LHXJNpHmV9KICkJVFZdo3zsY7j5w6ZKXNXFCzhrb/PDDz/8HbK9x8ZVu8wkJZAqCZjNY5Wf3vkdqo4Bj8sWjxdw5DPRt3KKTjvtNNxhkk5KIPMSqBz1E2Xq7ITekBUP4Ky9LevWrfsGae9JmR+ZbFFKgCRgLpik3HL3NygUty0eD+Cq9h4/fnwBbTdIQUsJDKkERo+9QSkr47ubMfmNlQHaG5v56aef/ndaUDVtSAcnG5cSMFumKXc/fDGYpI35jCiXeADH3KOZ7lp+Sy6HjShHmZApCWA57dgJ3wKTtIFNQB7RxQIc6abLL7+cniEesTBiLTJBSiCTEiguWah8/isjqEkAHpXhaIk4M5BuXrp06ZfoOUtcvUonJTD0EjCaipSvff9L1JGYU4bRAEeaCjh9P+fr0jwZ+uMqe9AnAZgpo0Z/nfYY8IgcR0qA9sZmeuCBBybZbLZ/66taelIC2SEBKzF5zTJMWbMdDl5DXDTAVe29aNGib5D2jpQvpEIZISWQEQkYicm5C0QtnjDg6uwJPY72tYx0WDYiJZCoBMorGXDW4iE1hNPMOBMQb1qzZs0MmvueHlJKRmS1BCZYYZoOA2exTFd+dT/eTsuzKSFaPJwkNMDPO++8+fLiMvdA+Z8JJcqPN+9RGnocoZ0PBELjFF2cbjdYIEykvq4wWehd4APb05dBari4gaWCe/p8AT+uFOdT4j7aoJTB7oAGowFurqqqmicBV5QPmgLKX3b7lVbHANmRLLPVVSjnGT6hzFRa44dHHEqIHhQThXC8+YQiqQ66K9rnvakoD1O9DPiAJvSAo8vYjMXFxWZ6U9VFA3IP052fv+5VGntzBW4+SCYl4KtQ/L3tpCBJ0+WpC/hKLgKrvb29DDj41Q4WIvUOcaZHH310lslkGqlPHI77uQd38CgZTBbSVBVKXk+CGYwjS758/ywwS1sIz/oI1uCmmTNnflKaJ7l/OmuQG3migQ9xnvg0W2gaN/2TfYDzoLQDFw5wVYOT/T1XAq7JKacDKuS2csVg1B/unB6W2nkwaiiumEs7rMEBueZEG5zpN9Gt+QKyv+douWQg5yXAkPvtHYO78MxiCZisJXNsVRML7C3HndRN5li1w/WnNPaNDz744Ll0ZpRm8Zhk1wYhAYacjPJBlM7eIgHFUFryxZvPpR6q/Io9DavBJ0yYcJY0T0Qx5U84CDnNrtjb82dQZHqZysefRQPaRltEDc4JRlr7PS1/Ri9HopeAwWRWjLYKQiF/NLnBWgpmocGZY3XYoomCBOybaPXgNKnBVfnk7R8V8qLyvIAcrBoLiqaCXdoYcvXYMeB8KmPfSIBPUVPln7yWQD/kjEEOD7fABsBVfvtGoTIdYoOPHDnSXFhYODmHhyq7noAEgpCPUPyOTiql3QBMoIbsyGo0F04uInYdbW3RTZRbb711AnXZmh3dlr3IhAQYcpooz0RzaWmDTk1r0YLrwS4GwRaJuoMGmXrjOeecI5fHQiLDzKmQF9ILXFXIGYfc8q2jZ4JdBlyFnE9ZHolx1KhR8gJzmMHNw9Ugz8U7nrijWToyZCZFtMEBu7GoqGgiD1j6w08CKuTWUsXv6s65O56GApVdlWM+cnoNbqB3D+JzEdINYwkw5DlnkxvNYJetEdVEETU4Ioy0RLZEzoEPY7r7hh6EvIQ0eQ/FZP/sCpilPgNwKG0VbgyFdzTqCXC8ZFw6KQEAoxgLS3NoPbkR7GosIyxqcBxSgwQcYpCOJWDAOnIrKUbS5AH9M5GcKUt8OiEZcK1HbIMjQiVfAq7JRgb6JADIDQR5tpuuAaMGuGaisAbXIiTgkutwEujX5L2UnJ02uSEIOHdfZVpqcBaH9GNKIKjJQ6yAmOUylYHsa+6cprBZg3MfpA3OkpB+WAkENXmxEnDbs2+e3KABrvU9RINTih56LbMMSAlAAqomL7BRQFOU2SGYgMouOqV1jGHWIrxer50+8iofV8uOQ5a1vVA1OUEecOPtWdlhkxsUH/2saE5lmufBtVifz4erCOmkBGJKIKjJ8V0ETT/GLJPODAG/X8+uOg+O0087BaHB09kJWXd+SSCoyYuUgIceaB/qeXL/AA2uci3a4JB8QGrw/AIwE6NRNbmlcMht8oBftT40ZY2xsw2OsJogAYcopEtUAqomt5Am9w6dJg8ENPNagzysBs/2W7KJCl/mz4wE8OYsg3loNLnKbNAG1+DGqFmDI1LdpA2eGRjytRX19XAEecDr6kMqcyM1BNTrR41ltCxqcAYc6yOlkxIYtASCmhyP9WZ2doVmUXhtL1hWHWtw3lccDkcb1H22L6zROiwDWSmBoCa39mnyDHSRmPV7nG36lliDs1r3t7e31+kzyX0pgcFIQNPkGbrj6be3gV287Z95Vk0U7MCpkdXV1bXyIjMoEPk3eQmokJsKglOIAD1tm6J4Wo7UMsd9PQ+wBse+CvgzzzwjAe+TjvRSIwGGnB4qS02F4WohE8W58zk94CGzKP6XX3652+VyNdN6lFHh6pFxUgKDkQAgDygWxeDzDKZ47DJeV3PvvtfpVQChJgoKs80C+8Xf09NzRJopEIt0qZQAIFfou0GpXoUIVv0uxxHqq8ov+cxzyDShmsFut9elcmCyLikBloAKuZEm71Jsi/vdKrMi4GqTbIMz8cjgw0yK1OB8SKSfagkMgDwVlZMGDzg6oJR9tIFh5lmzwdEMR/pPnjxZiwjppATSJQHVJg/QRaffm3wT9Gvg624GswPgRsXhNLh//fr1u2nRFYCXTkogbRJQbybCXEl2diXgCzh2bthNFQHwAZAz4BgEgEaijz4C29zZ2VkjzRSIRbp0SiAIOT7MgCnExDeyThS/s7uma+vaZqpANFHUbusBZ8i9ra2tWyXgqozknzRLQIMcF56JOiLc19O6lYrB1hmgvVGVCDj2VQ1Ovq+mpmaLBBwikS4TElAhx7vJE55dIWhb6rZQH6G9WYNrXRYBh/ZmDe5buXLlVj85LacMSAmkWQIa5Im0Q4x2bXkUGpzhZo7VWsIBrp4JGzZsaCc7/KDU4olIW+ZNVgL9kMe2x4P2d+dB+86X8NFP1uARAUffWIPDnvHSdOE2CTjEIl0mJRCEPA57nAj3dzXj468qr+SzDa51V9TgiGTAcTZ4yQ7fLAHXZCUDGZSABnlUm5wgba3dDFZpE00Uraf6Bx5YveNM8C5fvnzbJZdc4iwuLqYH7Yavq+ytURq70rRIKIvEGlmZAYswDjZCRBchLUJ0ULeGqYzaQL8AfEj/PA5nz8u/Zw3O2ntAC+EAR0bVnnn33Xe7Gxsb35gyZcqlxhR9mGj/oU7liWfrlPZOd5jRZGfUbK9bmUnPGIYIeEB3B8i1PyUKBHTo+vPFEYrcfpR6orYfR6NZmiUQ8Cs9XU1vbDiyEysI2f5myLVe6wFHAqSlanDyPTt37nz+9NNPTxngv/3DHqW5lV4tkGPO67ErPi+9pgw/mYAGfjyO8zJo+vL6dH2dmc6vb1/fP31/9Pn1+7HK69P15fXt9eUP+LxKR/OB5yk7flrFOfABNehtcCSKgHuvu+66t2n5bGtk7TGgvpg7uQg3BmW22BSTGa8pIwehx+s4L3wxzOXFOM4j+sjHecSwmEcMi3nEsJhHDIt5ENY75IXjMhxWI+P4E6u8Pp3bYV/fHsWDRb/f1Vq3b9XblBzxAhNFowEOte+hlYWO+vr6f6QKcDSaq06F3FQYdeUEow9fDGfLmMU+ieFI/RPziOFU5Y9UT/T4gOJ2tP/D7e7Bmz+hwcNeYKKOcIAjHiaKZqa8+uqr6+l9KYgf9g6QG/sgxwHXbxAQgyCG9fmGal/skxiO1B8xjxhOVf5I9USLV8j+7mjd/Rz1RzRPwGuIiwQ4zBScFaDas3Tp0r0dHR2HpRYPyo8hD+7Jv5mUABj0eeyHjx58Yh+1y4CDVTAb4qIBzpCjEjfNiW+Qd+775dcPeTRdI9NCf+OSlQl98M3RvAFM0sbmCVhNCHAcSah8TYuvXr16PT2MjAql65OAapPjXXzRnP4iCnk5Llw5ToMvhsPlzYU4cQxiOFLfxTxiuC+/3+/xNB9/cz3tito7rHmCIpE0ONJwRrAd7l61alXjkSNHXpBaHKLpd5hZMfELJ3FA9Buy8oESw/p8vC/mEcOcnmu+OAYxHGkcYh4xTPlx38DtaHnhZP3rjZQEDR5xehBF4eIFXDVT1q5d+whp8YhnS7DK4fdXhdyEd/FJl04J+ANef3PDpkeoDTZPkgIcfR2gxe+7776aY8eO/VNq8dDD2A95sjamLE8/eSTggRsuLj2Otn821D5fQ4lxaW8cpWgaHOnQ1pqZQmHXU0899VePxxPWoEeB4ewYchwadhzmw4V4jhPDnJ6oL9YhhuOtRywjhuMtr88n1iGGOZ8YJ4Y5PZKv+H2BthOb/0pl8F5mEfCoFkUswNEHVICLTdVMufPOOw+QFn9TanGIJtTBHjeSucIHCjkQZsfhSOmcL14/2fqSLa/vZ6z6YqXr68M+1p24nK1vHq3++wHaZfMETEaFG2XjARzaWgOcwq4XX3zxYdLiKC9dGAkw5Pqf2czso0OMkRhGXG5u9N5vpb3p/YdpAKy9AR+YjGlJxAs4a3GcPa4lS5bsOnHixGapxUkaEVwQcnqrasYdw80wowMcl/HOJN0gtLfb1bH5yMHHd1FlDDhr75QAjk6yFsdVKyB3bty48UE5owLRRHYa5JgSY8dhniZDPMeJYU5P1BfrEMOR6hHzIBzLcV8j1aePR31cRgxzPjFODPel+xWvv6N5x4OUhCWoYA8MxqW9KV9cJgryAXBocQbcdeONN+6kd4k/J9eoQDyRnQq5se+Fk3yg2UcxDvcdULUmjotcbeQULhtvffr8XC6Sj5a5TORe9KdwXq5PXz5KOn0WUHH2nnyudt/qnVSMtXfMqcH+xuMHHGVYi6sXm2jwpptuWk4PJrfLNSqiSEPDGuShSTImggTUNSdee/uxA2uXUxaGO27bm6uNxwbnvKzF8fOABp2vvfZa89atW/8oLzhZRJF9zVyJnEWmCBKgb14qPZ01f2xv3o03VsE8AXNx295cVSKAo4yoxVXIFy9e/Aw91rZLXnCySCP7Jpo+NNLnPMQvHXAYfjz/UDuXEcNcVowTw5yeal9sQwxHakfMI4bF/HhiyuPq2LV/293PUB6GO2HtjfoHA7g4o4LGnWvWrLnL6XT6pKkCkUZ3gNxAL4HnA4rcCMfrOG+k8rHS420n3nyJthcrPxgK+D2+5oa37qI+qHyRj4vLhLU3xpAo4CjDgOOMUrX4HXfcse/AgQPr6I20SJcuhgQYcvVijS++pN938RpQHD0n1h378Cms99Zrb7CXkBsM4GiAIVenDGnfccMNNzzU0tLSKE2V+OSvmiuYXZFOkwDmvD2e7saa/X99iCLxOBoAF7W3ljfewGABZ1ucpw2d7733XusTTzxxE33+xCNNlfjED3vcqELON2WGr0+WCS03cXtaTmy6qbutppUkyHAnNO+tl/xgAUc9DLmmxWnacAeB/hDdANK3I/cjSCAIebi3d0QokKfRZHcrvZ01D9XtW72DhqjX3mBtUC5ZwGGqaFqcws5LL7109dGjR9+WN4DiPx7DHXLc0HE5Wt7es/m21WCob4PiTOimTjiJJwM46gPg2PiCE2ee/Wc/+9lvyB5vkvY4SSNO12+uxFkgT7LB7vZ6uptq9678DQ3JThsYggkAppgvCg7OJQs4WkUnMH2CMw6dc9ANoJNPPvnkL8ke90p7nCQSpzPS9CFscryHbzhsEEvA7/a2NLzzy46WXSdpV+WH/KQuLFEvu1QAzrY4mypqJ+lVE9u3bdv2Z9jjEnIWd2wfkBsM+W+T9813093K6j/X7l+9nSQjwp3UhaUo5VQAjvoY8gGmysKFC1fSgqxX3G6ckNLFKwEVcu3rY/k5swK729Hb9Mqed29fSXLRmyawCAZ9YSnKOVWAo06GHDTjQgGdti9atOjXdNH5noScpJGAU00VI74+ln+OXv2gOJ0t7x3cduevaXQqJ+TztGDK4IbkUg24aI+rkNNXIrquuOKKG+kBiYNyURZEHr/LR8j99OFXt6v94KH377/R4WjtImkAcBFuMJQS7Q1Jp0NFoHNiBw0Eube2tnbT/PnzFzz3UtMIA76mJV1cEjAYcIhInLgTkuMOZonH3XW8dvdff9zZur+JhtNLGwMO8zal2hviSgfgqBduAOhki7u6u7u3NHWO+yxNidkk5EEhxfM3CHmfSHN0zQq98Fjxunta6w+v+9GphneO0Wj0cKdUc7Nc0wW4qG608AcffNBrMlvfLx0x5XMGo7lAQs6HIbbfLytNnLELZUkOrO2mF2b2nDz64rX1hzccpG7p4YbmBuApd+kCHB3lI8G+2vnOlr0dBYVV+4tKxl1MswWW/gOX8rHlXYUsq+C8ChaeZv8/vOqYvo5hb2l48+d1+9fiNrwId8rmuyMd7HQCLrYJyDXQ20/tOGUxF+6wlU1aYDQWFPGBEwvIcHgJ9MtKE2f4jFkQq9rcnu72xrp//OTIgccx181wY8477XBDBJkGXAO9o2VPm+JzbioZMXWewVRQ2n/g0C3poklgoKyyc57cTxeUXnfHCVrXfU1D7fr9NJ4e2gA4w530OpNoMuK0TAGO9ljlaJB3tVd3u1yNb5ZVzPy40Wyt7L+Y4u5JP5IE+iFnsUbKmfl4zHN7nG3VdXtWXNvU8GYd9QBgZxxujDyTgKM9OAZc9e1dDY6ejoOvl1fNnm0yFY1TaApR/QhoMK/8G0UCGuQGEmUWKHK83jhA89z0gvoPDu1cfn1b864T1H29WZIRzc1iyzTgA+CmTqj7Lkeru6156xsVoy+cQk+fn44DJyHnQxTd1yBXRRk9bzpTsSrQ7/MoLvvJN/a/d9uSno5jLdQew40bOVghmFG4Md5MA4424UJA97rtvub6f71VPupcq9lSNttgNBLj8oZQUFzR/w6UU+ZVOeD2eV2B3u7ax/a9e/PvXI7OTuqxCDcuKDMON6Q2VICjbYacJ/jpHYte/8mjr35gtVUdLCwaPYfmyunDlFKbQ1ixXBByiDRzTl0RGPBiPXd7S8Pbyw68d+/TdAz5YlK8QzkkcEMSQwk42mfI4Wugt53c3uB0nHyttHz6THo4dywOnjRZIK7ojiHPxOw4lg4EYJI4mnfW7V95ff3h9bupd9DarLlhkohTgZk9+/pElS2AA27eVOjt3fW9p4699kr5qFkmc0HZR6TJ0nfEYngDzZUYmQeZrN6ZhEnSeXj1nk2/vr2nsw5vn4LGZrj1i6cG2VLyxYYacIyAz2zW4hro9HPnO3nstZ2FhZX7Cm1j5tCDAEWkyqU2j3HctV+7FJvjWE+CWRKvt6utpeGtX+7f/vv/6zNJGG7McfPFZNpuv8cY/oDkbAAcHRIhF0FXw21N2084HfWv2UonjaHPhEwJaikJ+oAjqdvRINfFD2ZXfSILF5I+Fz2kUP/akT0rlhyv2bCX6mKNDcD1N3CgqIbc4RzPJof+YOoEJx7eioNPl+FDlHSxqdgQnj77h5+oGPeJXxQUlE3Cg7qZ+EmmdnPWYYYjGRec/nMrbnfnsbaT2+6v2f3wZqoPJghDzVOAvNwVDbLCSqbplJTNNsAxKP5hBeR4OBGfSQDkDHpRYWFFyYzzf/Gd4oqpV5JGt+IZxlRqLGorr1zwmdjEmOMZEp/X4erpqFld/f4Djzud7ZghgabGBrDZ1sYsCa/lTqwhKphOly0min6MLCT42KAV2Kbzeb1Ob9Pxf+32utteLSqZOJ4++jRJmi16Efbv95/8rDsi++pzFX3mCM1kvXPkw7X/Vbd31eskc3H6D9pbhBvHJ7mfiv7upjSUjRpcHCD6xyYLa3PW6DBbVM0+4/yffKq88iPXmq0jJuOdf/J2vyjC/nBQk/fviyHRzva6u462N+96qHrng29RHtbUrLUx9cc3bljpsEISq8yKcLYDzkIC5Aw6bHNAzva5CrnZbC6c/pHrLykbefYVZmv5NAk6iy66PwBsV8fhrrYDj1Xv+uOr9GYyBpt9ntcWbe2s1NriiHMFcPSZtTlAhzZn0AE4ww7fOuP86z45ovLcKyzWkecEL0RN0kYnwYguaGP78MJLetl8277O1j2Pffj+n96mPAAZG8BmHxobYPMdSYCdtVqb+qa5XAKcO40+49qBQYc2Z42uAk77qj919tUfqxh1wZXWosrz6cEKslxQbPhOLwZNFKz4I7D9broL2fp+e/OO1TW7H3mPBMNgi75ojgBqvpCkYG64XAQckkW/sYlmCzQ6Ty2KoBeccc53Z5eP/uiXrIWjFpjNRTaD+no0FM1/2DWo6cIRb3D1eh12l7P5jY5TH6yv27cGt9cBsQg1wtDWvIl2dk5obeq75nIVcB4AQ86gs+nCoLNmV7V8YcnY4ikzvr3ANuKMz1mLqi4k0E3q+7nVu6OoIn+cOv9NUyJ4+ACfBKG3t263d9a9XPvh2jecPSdxg4a1M4BmyBlqnvaD1s4ZcyTc0ct1wHlMetBhi7CNziYM+6qmrzrtwtHjJi/6rK1k/OfoiblpAJ1hz0XNzpoai6AANTafu/uwvafh5cajG//ZcmL7KZIJA8xwiz7SoK1ZY+c02DQO1eUL4OJ4grZH0E6HRmetDsAZetE3T5q6eHr5mPPmWQurzjcXls8i0K20VFcx4iWYeA9JFpoyA4CmJatYI0JQu7zOjr0uZ8v7HU073zlW82w1dR7aGPAC5nA+0llj8z2HnDNFaAxhXb4BzoMMUtlvo0Ojs1bXA69qdEqHby4sLLeOm7p4Vln5tAsshRXnFxSMOJseirbgAhXPjAZvmrDYgn7/jRRuPjV+EGLUxbzRBSKWqdJ7RnChGKBPftAt9AMeZ/v7XR2HdzTWPLvX6eyAycFQA2jeGHBOY23NGhuNcEMUzA/HRyo/RhM6ChF0aHbRVhe1O0POceybiovH28ZNW/SR4pJJ55oLiieZzLZJJottPFY2BoHHWnWAT1Wr0owkUn18JJYoHv9xUQiQNd/roJfnNPi89mNed++x3p5jexoPb9zV29uAu4qAlDUx+ww2fI6Dz0CL9nWkzlD23HZ6qef2aKL3HmNl84VBZ83OQEfyOR98lDWOnjB3dFnFOZOttjGTLIWlk81m20RaMlBpUEw2Ay2QoRPARg1SffQXF7F9vtpFaOEgxbSrhuhDAV57gBZ+BBSf3e9ztXq99uMeZ/dRl73pWFf7vqOn6jfBhmYoRe0rwhsuLOZlu5p9tTv5/Gc4Ac7HEWMWN4ZW9AE6Q83Q8z6fHKKvQq+r10DmjrmoZEKx1Ta6yGItK7aYy7AiUvF4u+weV1evy37K4eip7yWzAmBCi4obwwyfta7oI8xAM8TYF/NwWbHevNXWNPYQNxwBF4Uggo4wg8q+CL0IuAg350Ec18H1oi0xjH3RMXiI4zBrVwZcDyxDy1DzPudnn+tjX2x32IQhfOmCEmBZMJDwGXQxLMYBbqSxz5AjDg4+b7wPH9DBMXz6fUCKOEAs+gwv+0gTw9jHBsd+cG+Y/uUDMUyHH3XYLBsGNJIvQq3PgwbEesQGGUDRR1i/Mez6eHEf9WJfOp0EWPi6aLkbQQIsLwYZ2aLFiekRqhwAJkPK8KJMtLhIdcr4PgnwwZECSU4Cejnq91G7Po7BFVvWx+n3xbwyHIcE/h9VLWRYHWXC/QAAAABJRU5ErkJggg==',green:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAltklEQVR4Ae2dCXQcxZnHR3NoNDp8SD7kU7bxFXCchBhMYoLNmhCcOBBykGw2gYTkPV6AhGXD2sTZJQcJG3jsgw3hscuCsTEsOAQW1sbY+MAHxpYtHzI+5EOy5UMStnWPZkZzab9/j75WTWt6NKO5Z6r82lVdXV1d9e/ffPq6uro7zyBDIhXIi7DyngjLyWJRKhDpCYiy2pwoztrpxSwCb+d1bayFm9f1Yu3+cj2MAgOJH2bXnNnEGiHWppW8d999d/inPvWp6YWFheNMJlOR0WgswdLT06PElFdM+xbn5eWVQDXK76TI7vP57H6/v5PyOxFjobwuh8Nx4dixYye+9rWvtaK4ZqFVNY/TiGUIoQCfsBCbcjaLNVHgJRUQG3/4wx9ali1bNmXYsGEzrFbrdLPZjGUagTyNAB2ZCLXoh3CJoD/p9XqxnOju7j7R1tZ2/LHHHqtbtWqVh47pp0X8AaAZbPmRzvnAJzPXhRBhVoBeunSp7b777ruuuLj4xoKCghsI5s8TcPnpIBT9oNwE/D6Xy7Xdbrd/8Oyzz+5+/PHHndQ2LfA5D3suA85QGwmMPLLQ+b///e/nkIW+0WKxLKBlLuUXpAPQEbTB5fF4KmnZShb+g0ceeaSKLLyb9gPgIvQRVJVdRXIN8CCo77777oI//vGPt5CV/n5+fv5NdGrhK2dDsLvd7k1k3f/n17/+9frly5e7qFM5CXsuAM5QI4a1Nh4/fvza0aNH/4PNZvs2rZfRks2h2el0/u2TTz55dcaMGXuoo7DoolXPajcmmwFnsBWoKysrJ02fPv3v6QLxH2hUY1o2E63XNxqhOUkXqq+eOHHitblz557pBV2EXW/XjM3PRsBFsE21tbXXk7VeCheELhKzsb9Rw0cXqT1wYciqP37FFVd8SBX4aMlK0LPphKMvirWm2FRfX//lESNGLKXRj3m0LoOOAjQas/Py5cuPV1RUbKQiDDrDrrNX5mRnA+Aq2OPHjzfv3r3766WlpUvIDfl85pyG1LeU3Jd9LS0tT1x33XVrzp8/76UWAfKMBz2TAUfbFbgJbAuBfUdZWdkSuvFyZepxydwW0I2lo83NzQD9rwS69mZSxnUsUwFXXZHDhw/PmTJlytNksedknPpp3GCy6FV1dXX/OGvWrCpqpui6pHGr+zct0wBXLDZ1w/TSSy+V3n777b+j+R8/pYtHAC9DrwIO9xHD5c5XDF5fS0ya0MWo3+nwvrBx47nfLLlvKypj0DNmaDFTAEc7GW5zQ0PDD4YPH/4YuSMJmQMSExVpsPPxhjsMHt/FuLWkp8dwqb3dt2zhnD2vUKXsnwPytAc9EwBHG01YDh06NIuGtf5DjoyQGmHC4XMLwmwd/Caft2fnmXr3A3d8Zf9hqgXWHEtaQ57Of9pViz179mwrXeE/MnPmzF0S7sEDGuueJnPevCuusO76sPq6R2bPHm2l+sy0gKG0NZTp2jCG27R27drx8+fPf4lu1NwQ6wnKlf0TZcFF/bwe//Z9uxw/vvfuj89Tftr65ukIOI+QmE+ePPllGgJ8UfraIloDp5MBOFoB37zxQvdPvr5gP24SsW+OsfO0CenkoqhWe8GCBQWXLl36Hd1de1vCnTas9GtIXp5h5LgJ1re3H7z2dwsWjMTUYlwrpZXLki4WXIV73bp1E66//vqVNClK3mLvh1RkGcmy4GJr3B7/zkOVXXfd86PD5yg/bVyWdAAcbVBGSY4cOTKPbtqsJqs9QhRPpqNTIBWAo4U0l+1yw1nXd29duH8nrabFKEuqXRSG20yz/hZPnTp1rYQ7OpjTqTRNUhwxtsK69t3tcxZTuzDCAsOVUiOaSsBxbAhgoZl/d02YMOF1SttokSGDFSCabeVj819/v3LOXdQNCy04xynjLFUHVuGmu5K/HDNmzHN0ux2/eBmyQoEe84gRluc2V13zS+pOSiFPBeAK3PQQQj7NQ36CZgA+Kh9EyAqqgzpBQ4h5w4aZH6URlidwrmljSix5sgFX4F60aJGNXmzzYklJyf1BqsiVrFOgqNh0/5ubJr24aFEp3M+kQ57MCwAF7pEjR1rpBs4KeuD3W1l3NtOkQ6kaRQnXfZfL/+Y3bqz7Ed3f6KZyPIwYbpe4bEuWBVfgphbn19TUPCnhjsu5y6hKCgqM33pr4+QnwQAtSbPkyQCc4bY0NjYupXeQ3JNRZ0Y2Nm4KFBab7tlSdc1SqjBpF56JBhwuEI5hOXfu3N30rOS/xk0tWVFGKjB0mPlfN1bOuRtM0AI2EuomJxJwNBx/iix0QfkNupJ+mtIySAUMpSPyn16z5fPfICnYkicM8kQBznCbq6ur59Pt9+U0FAjYZZAK4J6+aczE/BffWn/1fJIjoXc8EwE44Ea95vXr18+gt0mtpjQmx8sgFVAVIEgKJkzJX/2fq66aQZmAHMzE3ZInCnATPRBcNG/evJU0t2SI2iuZkAoIChiNeUM+O6d45cLbxxVRNv7Cxx3weFeIHwwaar148eJTQ4cO/SmlZUiyAuk4Dh5Ogs5O3wsLPrfnQSoT9zHyeFpw/FhQn+Xo0aPflHCHO6Vym6hASYnpp29v+dw3wQ4tYChuhjdegDPc5jVr1kybPHnyM2IHZFoqMJAC48Zbn/nzi1dNo3Jx9cfjCbh54cKFRfS42Qrpdw90OuV2rQLwx6/9QvGKhQsVfxyQx8WKx6MS/EgUv5vmGTw5ZMgQeadSe/aSvJ5pPrgoj73D91/zr97zEOXFxR+P1YKrrsm+fftupNmBEm7xbMl01AoUlRjvWb1u9o20Y1xclVgBV6w3uSVFNN79JL3LLuoOyR2kAqICYKhisu3JBQvG8tBhTIzGsjNbb8vLL7/8C3oxz3SxoTItFRisAhaLcfqyP435Oe0f86jKYAFnuM2vvPLK5FGjRuHRJBmkAnFToLTM8tCfnpk5mSqMyVWJBXBcWFro6Zw/0Z+Vwrj1TFYkFSAFwNQX5w/5N0rGNCFrMICz9bZ8/PHH+MbkV+UZkQokQoGiQtPX/rb+M7f0Qg5WwV5UYTCAYx/zrbfeWkw3dJ6I6miysFQgSgXGV9ieWHjrqGLajV2VqGqIFnC23ua//OUv99PnriuiOposLBWIUgGLJa9iya8q8HA6Ax6VFY8WcJQ30Sewh9DrHn4WZVtlcanAoBQYXmr62fe+NwGzUnHdFxWz0RRm621ZtmzZT+hF9GWDaq3cSSoQpQImU17ZnfeO+gntFvWwYTSAo6wZN3XKy8vvjbKNsrhUICYFykZa7r1mwUjc/GFXJaL6IgWcrbf5+eef/wH53uUR1S4LSQXipIDZklf+m99N/AFVx4BH5ItHCjjKmehbObaxY8fiDpMMUoGkK0BW/OezZxdH9YasSABn621ZvXr1HWS9Jya9Z/KAUgFSID8/b+KjT02/g5IR++KRAK5Y73HjxuXT8oBUWiqQSgVGlVseoCnZfHdzQH4HKgDrjcX8xhtv/B1NqJqays7JY0sFLPl5U59bVbEQTNLCfOoKEwngGHs0013L78npsLo6yg1JUgAMjhlb8D0wSQvYBOS6YSDAsd30/e9/n54hHrpItxa5QSqQRAWKh5gWffWbY4bSIQF4WIbDbcQvA9vNS5cuvY2es8TVqwxSgZQrYDQabHffU34bNWTAIcNwgGObAjh9P+c70j1J+XmVDehVACyOLs//Dq0y4Loc621g59301FNPTSwsLPyiVFcqkE4K2ArzvvjPv52GIWv2w0P64uEAV6z34sWL76BfjF65dOqzbEsOKQAm5/9diWjFowZcGT2hx9G+nUO6ya5mkAL0WBsDzla8X+tDWWa+uDStWrVqBo19T+u3l8xIawUsplFp3b54NY7mik/703/MxNtpeTSlnxWHk64NKuCf/exn58uLS6086b8+3Pqg4WDNHw0O5yf9Gkuf9+sX6N3twXmaVWwMkUWv+Q7eLVShHk1mv310Kg9Vrt/h/PStQoN/PlVxhBYYa7AbVCwc4PQxzxHXS8ANhkZ7jaGq8W8Gh6ed9MuM4C2ebrD7Jhp6CIJsDr481/UGw4nnqY8MeFB3tYDjF6BY8KKiIjO9qeq6oNI5urL+1L8bOt2XM673PrPf4OjwZDXk/p6e68BqV1cXAx5kxUP54MgzrVixYpbJZCrNuLOagAZnItyQwWQ2GgppXlKeEec8OwON75V+/YErZlHv2A8P6qieBTddeeWVX5LuSZBWGbnCkDs7PQa/PyO7EL7RZI5HTCj+EhXaTwt7IKpfprXgintCBU3kf8+TgIfXNlO2AnJbicVAt7izLoBR2xDLPOoYW/CgP1eiBWf6TXRrPp/877lZp0YOd4ghhyUPNUKRydJYbaa5IyYU5l8+53BRP5hjxYprf9NYNz7zzDOfpl9GSSZ3Wra9vwIMORm9rArUn5Kbfzzt09QphV+xcyEt+Pjx42dK90SUKXvSDDksedYEwnrYyIKZ1J89tOhacN5gpLnfU7Om87Ij/RRgyLPJiFlsZjALC84cK/1GBgdswLqJZg9OzabOcwdl3KcAIC8oNuMtrn2ZGZpCHyxW0xXU/H4Xmgw49xLrRgJ8Sob2VTY7CgVUyLNgnLwXcIXfXgkUpvv54KWlpeaCgoKKKHSSRTNYAQXyIrPB1eXVzOLIrE5ZrcaK0lKbuaXFCbDZYCsuCfcEmcbf/va34ym2cqaMs18BhjyTZ/3TmKB17ncngV1Y8X6AM/XGq65SPsaZ/WdV9jBIAUBuLSSfnPFgIjIoHj2pCFO7xR6oFpy7YRw5cqS8wAw69bmz0gc5cMiwQE0uKrH0G0kRfXDFQbfZbBMyrGuyuXFUQIGc3p/Q7fSRT65O6YjjERJXVX6hCewqHPNRsILAFjyP3j2Iz0XIkMMKBCA3ZdwQosloBLsqyziFogXHBiNNkS3OhrFRdE6GwSsAyPPJkrvJkmeCHVeYNeUBcPbBlc7ziko9AY6XjMsgFVDmkysXnqAjAwIN54NdlWWkRQuOLuRJwCGDDKyA0ZRnsNrM5JOn/zi5yZzHgHPz1VEUZCjkS8BVbWSiVwGGXCEkjVUxGlXA1b85bMHVDAl4Gp/BFDaNIXe7vGk7uEL+iOheK0zzKAqkkxY8hQBlwqEBeX4BJmilZ2uNRuX6UeGYW8gWnNelD85KyDikAgy5uzv9xslNRvUiU217PwtOW7TQq4VlQioABRTIrTQzNc1MeU9eD9gNacHVPzper9dBH3mVj6tJlsMqwJB7yJKnyzg5vTXAITRaYZrHwdV8n8/Xpa7IhFQgjAKAnOZhp83gSo/foGVXGQfHD1D9EcKCh+mT3CQVCFKAIfe6yZKrFAUVSdqK39cjsqtwLfrgaEiPtOBJOx9ZcyBAbs7H3JUUd8mnWPCgn5l4QalskICn+CRl6OEVyMld8brp9VkpMuU9fj+7KCrkIS14v9fpZqjostnJVYDuJJIlJ6RSYMrBrK9HAVyFG71nC45MZZE+eHKhyLajMeQ+jz/phtzvy4MPrrIMbUULzoDbs0102Z/kKgDITRZj0g253+8Huwy40mm24KoCTqezBeZezglXJZGJQSgAyA0EOSx5MgLcfp+7p0V7LLbgTL2/tbX1tLaQXJcKDEYBtuSD2Xcw+zg6u8EuflHMs+KiYAVByTx58mSdvMgMCCL/j12BpEFO9Laed9Yxx70t72ELjnUF8DfffFMC3quOjOKjAEOeyMEVfOyqevtFLeD9RlH8GzZs6Ozu7r5E81FGxqd7shapAI1mwCen5zz93sT45H5Pz6UTey52ktb9XBTor1jv3o1+u91+RropkEWGeCoAyI0EebyHV8Bqt8t7htoKuEMCjn4AcqWAw+E4jQwZpALxVkCBnG7tK5DDZ4nT4nb5wawIuNJ09sFFC+7DSIq04PE+tbI+VoAhj5dPjiHCbrsXgNNTGMEWXBwHVyFvamqq48bIWCqQCAUAeQ8ZcJoBGHP1+KF0NHvALCw4c6zUG8qC+995551DNOkq9iPH3HRZQTYrgJuJmKQVa6CvOffUfNhwiOoRXRSFXwYcx0AGCvjoI7CX2tvba6WbAllkSKQCsUKuXGB2eWsr37twidopuihKs7WAM+Te5ubmSgl4Ik+trJsVYMgHMz0E/ndXm6eS6qI3E+m7KHwsxYLTiq+2tna3BJxlkXGiFQDceDe5EiMd6UIPzLU0OneD2d4FDKtBz4L7li9fXkmzs4IKq3vJhFQgAQow5NFUTYT696w5DwsuuieK/416QgGu/BLWrFnTSn54jbTi0cgty8aqgAo5rj0HWHB7vtvhqTnyUVMrlWYLDrhDAo62YQOsNvwZLw0X7pGAkxIyJFWBgHsy8CHhf9tb3Pj4q8IrxWBXhRs1iBYc6ww4fg1e8sN3ScAhiwzJVoAhJ1dc/2YnNaq5oWsXRQBcdFHU5oo3epAJwBly79NPP73npptuchUVFRWoe+RgwnXRZmh3YBQqu4OuMQuyiX0a6GQHCuhs1D1GX7VBKVhp7APgtfvSS4dcm1bUsQVn6x105FCAo6Diz3z00UedjY2NW6dMmXKL0ag19kHtiHil9nyj4b2dVYaOLvEVFhHvnpKCXs9XDUa3m44dpF1QW7TiB23UWdHdR+cw8DlDBlCgE/S30A5h9tOpLubsaG/r6JWnJ+gNrtbmrRdO7sYMQva/GXK1nVrAsQGaoCDMvufgwYP/N2nSpLgB/sJb6w0tHWhTZgV3t4teidBNjYbkkEhPem2/uCyjpt1fu127f7LLa4+vbZ+2Pdry2vWB9tdu1+6vPV6gvN/vMzTUHv8/Ku2hBaz2gxs1hTLLqIEB995///07aPpss661QS1RhEyEG93LtxbQKxH4+7gQPdLAZRGLad5fzOMyYoxyXEZMi2XEtFhGTItlxLRYBmltQFkE3ofTSmYE/w20v3Y7H4dj7fECrorP42mu2rZhB23VvcDEnuEAh9n30MxC5/nz59+LF+A4aKaGAOT5wbxpO6M9X9jOedqyqVjntujxo21Tostrjxfheldnx3tuu91JxWHBQ15goqpQgCMfFpytuGfTpk3v0PtSkJ/zAZBbLL2QMyRiDIUYCjEtlkllWmyTmNZrk1hGTMervF49YfL99JbNpvrat6k5onsCXvsFPcDhpuBXofjhS5cuPdzW1nZKWvGAfhaGvJ+cMiPRCoBBj8t16tCOTUfoWAw4WAWz/UKoi0wUQmGGHJW4aUx8TVlZ2YP0DR9sz/kAyBG8HsgjQ7IUAOD2jvY1dDwMa0F8hjsk4HoWHO2FyVet+MqVK9+hh5Hl2YQyvQGQm/PJXQkXcKcCge9YcFrJDPFftOVDVJFWWdH2Z4Dy9PpjT92R/e9QH8EiPAwwGtI9oXxdHxzb8ItgP9z90ksvNZ45c+ZdOf8K0vQFC42sKJAzwNoYRfmkiWltOV4Xy4hp3p5psdgHMa3XD7GMmKbyALKrs/3dMx8faKQkLDgAB6MhrTflRww4fi3uV1999QWy4rq/FlSYi0GB3GLJxa4ntc9+r9d/5tjHL9BB2T2JCXA0PsiKP/nkk7Vnz559X1rx/ueVIQ9z8a+OJMsygYGmaHTAXVdnZ+f7x/bsqO0FfEC4cZbC+eDYDmutuimU7v7rX//63x6PR/dPAnbK1QDITcoQYq/fDSHwp5hjMR3I7b9d70+3Xj7XPdj6Yt1f266B6htou7a+3nW6c9lTf/Lwf9PuuJ0suidhPYqBAEdzUAEcecVN+cMf/nCMrPg2acUhTf9goYtOk5ncFT5RKII0B07rbedykcax1hfr/tp2DlTfQNu19dE6Rk4c9o5th3d+cIxW2T0Je3HJ1UQCOKy1Cjilu9etW/c8WXGuQ8YaBVTINflydXAK+H007+TUyedpb7begA9MDuhJRAo4W3H8erqXLFlS3dDQsEtacVJDJ0jIdYSJMhvW29nVuevAtvXVtCsDztY7LoCjSWzF4dgDctfatWufkSMqkEY/AHIzja5gLjMHTgcm9AfyOQ9lOM3bo43FOsS0Xj1iGaQHCtG2D/XxPmKa2yPmiWne3uP3+Zvqjj9D21y0gD0wGJH1pnIDXmSiDAIAD7rYfOihhw7Su8TflnNUFH10/zPTRafJbFZOMp9ojrETp/mEinm6lYbZEG192vLcDr042vZp69fuH247psR2tDS/XbVl/UHaj613RKMnLFEkLgqXZSuuXGzigA8//PDT9GByK/6MyKCvAEOuX0Ju0SoAprzd3a3VO9Y/TdsY7oh9b64vWsDZF8cBXZs3b75UWVn5Z3nByXLqxwHI5c0gfYWCt8B6Nzde+HPj6dN4VhDuCZiL2Pfm2qIBHPuIVlyB/Pbbb3+THmurlhecLKl+DH9cHULkYuyfI45kwX68j5jmfcU8Mc3b4x2LxxDTescRy4hpoTwezXN1dVVvfeuVN6kIwx219Ub1gwGcrbhysYkGrFq16jGXy+WTrgokDR8UyE00iZNPKIojHWngsnr7D7Q90uNEWi7a4w1QHgz5vF5f3ZEDj1ETADdfXEZtvdGFaAHHPgw4flGKFX/00UePHDt2bDW9kRbbZRhAAYYcWMslWAMDPcxgb768mm7qYL631nqDvajCYADHARhytuLOBx544NnLly83SlclMv0BuZFGV2ToU6CH4HY7nI37Nr/3LOXicTSt9e4rHGFqsICzL66Oi+/du7f5tddee5g+f+KRrkpk6pvplr4CObsbORwDKBpy9pyuqX74YkN9M60y3FGNe2uVHyzgqIchV604DRvuI9CfpRtA2uPIdR0FFMjlU1L0pQcvjZo0PHvggw37SCqt9QZrgwqxAg5XRbXilHbdcsstK+vr63fIG0CRnw+GPFf9cbpbaejqaNuxZfXylWCod+G7lmAsJYDjDOLgWPiCE788x4MPPvgb8sc/kf44qRFhCECeez45/O5up/OTqo3v/oakwuvOwBBcADDFfFFycCEWC85HRCMwfIJfHBrnpBtATa+//vqvyB/3Sn+cFIkw4Ja+URxCzHKfHGaZ/tJ76SmdX9FrIJpoVeGHYrDEw4KUHHyIB+BoJxrDrorSSHrVRNWePXuegz8uIY/8BCmQG7P/zQVgAn735aYLz+3fsq6KFBLhjunCUlQ7HoCjPoY8yFVZtGjRcpqQtdGtvLhSPKxMh1MgYMkBefZ65TRJ0NDZ1rpxy2vLl1NHta4JDCaYijnEC3A0hCHnURU02rF48eJ/oYvOvRLy6M6ViVwVoymepye64yeytI8sd1dH+94tb6z4FzDSu/CwYNzgRh/iqSAAF/1xNNhBX4nouPPOOx+iByRq5KQsSB55YMizyRXHiEm3vbNm99o3HnJ2dHSQGgBchBsMxcV6Q+lEOHtonNjAPILcW1dXt3P+/PkLPth/eGgePqclQ0QK4L3synvBs2BKMmYIuhz2c/s2rf1ZY33tJyRAFy0MONzbuFpvCJwIwFEvQhDo5It3d3Z27naYCm6mGXWFPNE9UFT+H04B/vhAgPHM9Mv9fvpglNPZfGjnpntOHzl0lvqrhTuulpv1TBTgogVX0wcOHOiix7j2Dx899is0HJYvIefTMHCc1/uFjUwckcL9EHphpv34gY/uq9nzUU0IuGG5AXjcQ6IAR0MZbI6VxjfV17UVlQw5OqR0xEKah2GRkEd+TlXIIW2GGHK86tjtcjnqjx74pwNb38dteNFyx228W0/FRAIuHhOQq6BfqD1+0WIp2Dds1KgFNCRmkz65KFX4tAp5Bvjk8LndDkfriQN7fn5g6waMdTPcGPNOONxQMtmAq6DTnasWn8e1s7R8wvVkyEv4xKFRMoRXQDUIiiGnz16n4b8eGud2d9kbqnd+cC+9bu0o9chOCwBnuHEzJyF+N9WrhmQBjgOyBVchv9xwobOro3XbqPGTrjVZLGV8MaW2TiZ0FQhATlKyqrolk78B49z0HsGT+zatua/uyMHT1AKAnXS40fNkAo7jITDgStx++aKz+cLZD8onTZ1NryEeA59c+uUBoQb6X4UcBdPAJ8dwJt5CRTMDD+xY88YvGs+caqCWad2SpFhu1i7ZgAfBTY1Q1umdz+7zp45uHXfFjCn0AstJeUYJOZ+ggWLVXUmxKcesQHqWkm6/t2zd+saKJW0Xmy5T2xlu3MjBDMGkwg3tkg04jonQD3S60vbVVh/cPmbyFGu+rXA2+eRkyGGWZBhIAdYpYMST75H30Bg3fcqlp62p4eWNry7/N3rVWju1WYQbF5RJhxu6pQpwHJsh5wsN+nit13+quupA4ZChNSVDh881mkw0wiKtOcQaKEAnCJrMoMwIpJESj6Orlaa8Ltv2v6++QeeQLybFO5QpgRtapBJwHJ8hR6yCfuFUzQX6U7d5RPn4K8kvL5cuC6QaOKiQJ8EfJ2/bgItJR3vbwb1b1v3iaOX2Q9RCWG223HBJxKHAZP/+FMHSBXDAzYsCPV18dp06eGBjecVkk7Ww6DPSZVHO14D/sbsyYMEYCuDOpNfj7mlpOL9yw6oXf996sQFvn4LFZri1k6diOFpsu6YacLSef9lsxVXQ6c+d79ShqoN05/NI0TByWYxwWWjAQPrmYc96nz7xNeWBhxRofNvpbDl7rPpX2/73f97qdUkYboxx88Vkwm6/h+28ZmM6AI4miZCLoCvp86eON9ibWzYPHVk+mlyWKXBZMC7WdyI1vZKrvdqwrLEJArAxSoJvgna0XNpctXntkqOVHx6mWtliA3DtDRwYqpQHkJJOAe3BXFr88PCmSist+OKqjZZCpK+55bYvVEy78pcFRcUT8eRL3zAZbZWhnwIAM5bAw3/dXfaz9SeO/vve99fsovrggjDUPATI011xwPj8smJpeO++6QY4mhUwzwHI8Zg5vrQKyBl0W0FJSfENt/39D0pHj73LYrVayXWR1pwE0guBGYjRMaeOkNBDtc1NDSs/XLP6FVdnJ0ZIYKmxAGz2tTFKwnO5ozsQ7ZjIkC4uiraPLBJiLLAK7NP5vG63t/bQvkMOR8emoWWjx9Fr0CZKt0UrYd96nyvHtkM/xhwudkfsra0fHtz6/j/v2/zuB6S5OPwH6y3CjfMT25+KvubGNZWOFlzsINrHLgtbc7bocFsUyz7vq9+6oXzK9PsKCgsraE6L4rb0nVSxutxOByx5aA3Yz/aRn+1yOOobT598dte6N7dTabbUbLUx9Mc3btjosEEKXXkKc9MdcJYGkDPo8M0BOfvnCuRms7lg7uJv31Q+ruJOa1HxVLzcEv65BJ0lDB0z2LiAJD/7VNOF+pcr1/5tE72uhMHmmMe1RV87La222NNMARxtZmsO0GHNGXQAzrAjtn5x0Te/VD556p0FxSVX4Y1RmIorQSdlhKCAjfFsL1lse+eRptOnXv7ovbd2UBGAjAVgcwyLDbD5jiTATlurTW1TQyYBzo1Gm3HtwKDDmrNFVwCndSW+5uavXzNu8oy7CocMuRpfVgi8hiF3hxcDLgpm/GFilMfg6OjYf+H08ZU0MrKXNGOwxVh0RwA1X0hSMjNCJgIOZdFuLKLbAovOQ4si6PlXz7959tipM28rKhm2wGzNL8TrGHLlopShxoQo3Fr3drsdXZ1tWxtO1byzf9v7uL0OiEWokYa15kX0szPCalPb1ZCpgHMHGHIGnV0XBp0tu2Lli4eNKPrc/C8vKC0v/0phybA5NI5uogldivuSbePpGAkB3JifjU+CODrbqlqamjYc2LZxq73tMm7QsHUG0Aw5Q83DfrDaGeOOMBRinOmAc1+0oPONInZfxFix9BOmXjVq+py5Nw8rG/kVmp47lV+XFvDVM8+NUS11H9R0S91xqq350oYTVZXvnzt15CKJxQAz3GKMbbDWbLEzGmwRDE5nQ8ygIwbksOhs1QE54NbG5qu+cMO0cZOmXW8bMvTqgsLiWQS7FW95hc+ersAHA+1XXmRJlrqbXqxz2NnRvv/CmZMfHtm1/ST1F9YY8ALmUDG2s8WGC5IVYFM/lJAtFpz7wzH6xbADdF4AuBZ4xaJTvrKtoLjYOuvaL80qGzPx8wVDSq622Yo/ZTSbLLhbqjwzqsxPp9JKCMiXqBGaAMQ4UMD1xU0Y8jsMmM2HJ9ZpLprH6bQfc3V07m9uPLvv8J4dh112O1wOhhpA88KA8za21myxldqpfFaFbAWcT5IIOvx00VcXrTtDznkcm4aWlRXOuGbeZ4aXjfm0xVYwMT/fOtFsLRhnwsMYyvCjUQG/76KVD62NtVIHoNWWUiAmoHFRCJAVX5pi+oKdk+zzBbe7+6zH6Trb2tz48fG9O6vbm5txVxGQsiXmmMFGzHmIGWjRvw7dGCqc6UGreqb3J1z70VcAzjFbddGVYbC1sVhW+aFUzPzMqNETJ1YUDyubaLUVVeRbrRNMFnOZyWguzAvAj9fToZ6AmwPLjxUKCk1EMltoir30OJOjhyD2+b0On8fb7O7uPtft7Kq3tzWf/eTs2fr6mmr40AylaH1FeEOlxbLsfnCstCeb/2PNs7mP2r6hz+ICeNmycwwwGWqGnde5jBgjjUWsN4/cHfPQ0lFF9PidzVpUWFRgK8KMSIPL2eXo7qLRuvZWZ3vLxS5yKwAmuwgcM8yI2eqKMdIMNEOMdbEM78t1ckzFciPkIuDimQ0CkjYwqByL8IuAY7u4jcujPqS5XkoGpbEuBhE4TrN1ZcC1wDK0DDWvc3mOuT6OxePmTDrXARdPNGvBcCLWgsvrDDEgRzmOOT9UXTgW5wM6BIZPuw5IkQeIxZjh5RjbxDTWsSBwHFjL0f9Z8BztfthuszaIwy0i1NpyOIBYj3hABlCMkdYuDLs2X1xHvViXQaMAi6/Jlqs6CrBeDDKKhcsTt+tUGQQmQ8rwYp9weXp1yvxeBfjkSEFiU0Cro3YdtWvzGFzxyNo87bpYVqYjUOD/AZrbm7Ts1rpFAAAAAElFTkSuQmCC',red:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALgAAAC4CAYAAABQMybHAAAk/0lEQVR4Ae2dCZxUxZ3Hq8/pnhkGmOEQuQS5VCTxWHEDBlyNkciakMMkxujGuOvHO24IKCae0UQlKwmyroocoqtozGpA4oFiVAQU5IaRcchwDsPczNF39/5/b+bfVL/p7ume6bur+DyqXt31r2//5//q1XvPIJRLpgQMMVYeiDGfyhanBGKdgDirzYvsLLtIPguB0/lc7+vh5vNIvr68Oo8ige6EH6Vo3iSxjODrw1rcm2++2f+MM84YV1hYONRkMhUZjcY+OAKBgOZTXDGVLTYYDH0gNYpvIa/V5/O1+v3+FopvgY+D4tra29uP7N27d98VV1zRiOy6g06DcRyGr1wYCfCEhUnK2yiWiQYvSQG+8ac//all3rx5o/v16ze+oKBgnNlsxjGWQB5LgA5MhrToh1BL0Fd4vV4c+1wu176mpqYvHnnkkf0rVqzwUJt+OuQfALrBmh/hvHc8mfkuCBlmDei5c+fab7nllguLi4svttlsXyeYzyPgrJkgKPpBuQn4LU6n88PW1tZ1ixYt2vjoo486qG964PMe9nwGnKE2EhgG0tDWBx988HzS0BdbLJbpdEymeFsmAB1DH5wej2cTHR+Qhl937733biYN76ZyAFyGPoaqcitLvgEeAvX1119ve/jhhy8nLX211Wq9lKYWtnIuuFa3272WtPv/3nPPPW8tWbLESYPKS9jzAXCGGj60tfGLL764YPDgwT+x2+3fp/MyOnLZ1Tscjj/X1NS8OH78+E9poNDoslbPaTMmlwFnsDWoN23adNq4ceN+TBeIP6FVjbG5THSksdEKTQVdqL64b9++lyZPnlzVCboMe6SiWRufi4DLYJsqKyunkraeCxOELhJzcbxxw0cXqQGYMKTVHz399NM/pgp8dOQk6Lk04RiLpq3JNx04cOAbAwYMmEurH1PoXLkIEqDVmPV1dXWPjhw58l3KwqAz7BFKZU90LgAeBHvYsGHmjRs3/mtpaekcMkPOy55pSH9PyXzZ0tDQ8NiFF1646vDhw17qESDPetCzGXD0XYObwLYQ2FeVlZXNoRsvZ6Yfl+ztAd1Y2lNfXw/QXyHQ9TeTsm5g2Qp40BTZtWvX+aNHj15AGvv8rJN+BneYNPrm/fv3/2LixImbqZuy6ZLBve7atWwDXNPYNAzT0qVLS2fNmvUA7f+4gS4eAbxynRIwHN8ozDseFQZHTW9l4m/3BBa/8nnDfT97vKqBKmPQs2ZpMVsARz8ZbvPRo0ev6d+//yNkjiRlD0hvqUh3ecsrpwtD2+GEdcMfELUNbWLewNniBaqU7XNAnvGgZwPg6KMJx44dOybSstYf1coISSOKsy4tiJLa8ySPX6wvrxN3TLpX7KJaoM1xZDTkmfynPaixJ02aVEBX+PdOmDBhg4K754D2tqTFKKacPVhsOPEnce+kSQK/IjMdYChjFWWmdozhNq1evXrYtGnTltKNmq/3doLypXyyNLgsP49XfPhOpfjZzCcEbKGMtc0zEXBeITFXVFR8g5YAn1O2toxW9+FUAI5ewDY/UC9+PvrXAjeJ2DbH2nnGuEwyUYJae/r06bba2toH6O7a6wrujGGlS0eMBjFw1ADxetMT4oHpZ2lbi3GtlFEmS6Zo8CDca9asGT516tTltClK3WLvglRsEanS4HJvXF6x/v0vxHXfWigOUXzGmCyZADj6oK2S7N69ewrdtFlJWnuALDwVjk8C6QAcPSSTpa6iTvxwwm/EejrNiFWWdJsoDLeZdv3NHDNmzGoFd3wwZ1JuMlkGjBsoVlf9TsykfmGFBYorrUo0nYCjbQjAQjv/rhs+fPjLFLbToVwWS4Boto/sL14++ri4joZhoQNznDbO0tVwEG66K/nLIUOGPEW32/GLVy43JGAeUiKeqvsv8UsaTlohTwfgGtz0EIKV9iE/RjsAH1IPIuQG1SGjCAhDWaF4qHmBeGzwYIG3EaRFk6cacA3uGTNm2OnFNs/16dPn1hChqJOck0CJTdxaeY94bsZkzfxMOeSpvADQ4B44cGAB3cBZRg/8fi/nZjNDBpSuVZRow3d4xGsjHxT/VlsrXJSPlxGjFUlIWqo0uAY39dhaXl4+X8GdkLnLqkrsFvE90uTzwQAdKdPkqQCc4bZUV1fPpXeQ3JhVM6M6mzAJ9LGJG+v/IOZShSm78Ew24DCB0Ibl0KFD19Ozkr9JmLRURVkpgdIi8Zvqx8X1YIIOsJFUMzmZgKPj+FNkoQvK79CqyQIKK6ckIE4pEQsqHxbfIVGwJk8a5MkCnOE2b9++fRrdfl9CS4GAXTklATwiYRpVJp7bfb+YRuJI6h3PZAAOuFGv+a233hpPb5NaSeHkPGJCFSuXnRIgSGwTBomVb/2nGE8jAORgJuGaPFmAm+iB4KIpU6Ysp70lJdk5BarXyZaA0ShKLh4tls+6QBRRW/gLn3DAE10hfjDoaMHx48ef6Nu37w0UVi7FEsjEdfBoImh2iMX97hR3Up6Er5EnUoPjx4L6LHv27PmugjvalKo0WQJ97eKGLx8U3wU7dIChhCneRAHOcJtXrVo1dtSoUQvlAaiwkkB3EqAngxauuk2MpXwJtccTCbj5kksuKaLHzZYpu7u76VTpegnAHr9svFh2yQTNHgfkCdHiiagEPxLN7qbnKOeXlJSoO5X62UvxebbZ4LJ4yB5/muzx2RSXEHu8txo8aJps2bLlYtodqOCWZ0uF45YA7T68cfu94mIqmBBTpbeAa9qbzJIiWu+eTy9Wj3tAqoCSgCwBIETr4/OnjwsuHfaK0d4UZu1tef7552+nF/OMkzuqwkoCPZWA1SzGvXS9uI3K93pVpaeAM9zmF154YdSgQYPwaJJySgIJk8DgvmL2C/8hRlGFvTJVegM4Liwt9HTO78k0KUzYyFRFSgIkATJVCq88S/yOgr3akNUTwFl7W3bu3IlvTH5LzYiSQDIk0KdAXEEbsi7vhBysgr24XE8ARxnzlVdeWUw3dB6LqzWVWUkgTgmMHSgeu3Ky9oFeNlXiqiFewFl7m5988slb6XPXI+NqTWVWEohTAhaTGPnMLIGH0xnwuLR4vIAjv4k+gV1Cr3u4Kc6+quxKAj2SwIA+4qbrpwjsSsV1X1zMxpOZtbdl3rx5P6cX0Zf1qLeqkJJAnBIwmUTZ/TPFz6lY3MuG8QCOvGbc1DnllFNujrOPKruSQK8kQG/Kuple0Yx942yqxFRfrICz9jY/88wz15DtfUpMtatMSgIJkoDZJE5Z9mNxDVXHgMdki8cKOPKZ6Fs59lNPPRV3mJRTEki5BIb0FbdNOj2+N2TFAjhrb8vKlSuvIu09IuUjUw0qCZAErBYx4i/XiasoGLMtHgvgmvYeOnSolY47lKSVBNIpgWH9xR0lJcG7m93y210GaG8c5ldfffVfaEPVmHQOTrWtJEAbsca8f7O4BEzSwXxGFEwsgGPt0Ux3LX+ktsNGlKNKSJEEsJ121CDxIzBJB9gE5BFdd4Aj3XT11VfTM8R9Z0SsRSUoCaRQAn0LxIyrvyb6UpMAPCrD0RLxy0C6ee7cud+m5yzV50VIGMqlXwL0/Kb9nsvEt6kn3S4ZRgMcaRrg9P2cHyjzJP0Tq3rQIQGYKSP6iR/QGQMekeNICdDeOExPPPHEiMLCwq91VK3+VxLIDAkUWcXXnrhaYMma7XDw2sVFA1zT3jNnzryKtHekfF0qVBFKAqmQABFpnDUxRIvHDbi2ekKPo30/FR1WbSgJxCuBwcVBwFmLd6kinGbGLwHxphUrVoynte+xXUqpiIyWQKBoWEb3L1GdozXxsS/9u/Z2Wl5N6aLFYaTrXRDwr371q9PUxaVePJl/3nzef4uaN28S7hNHunQ2EOgSRa/r1rkuEXild1enr6unecJVHktd9OlwaOJp1LPddEApg92QotEANw8YMGCqApwktmen8K9cIURTI8kv810BdXGI72JR73LR9+ND5jvzOx9nD80u11QhVj1DxRjwkBr0gOMXoGnwoqIiM72p6sKQ3Hl64nv0fhGoPZ5Vo8ff7P5+v2jw+Eil5S7kfQKBC8FqW1sbAx6ixRGpd4gzLVu2bKLJZCrVJ+bjebbBzXNkoTsipfRQo0HTWRybWz7BWvqHkYMn0qjYDg8ZoB5w1uCmM8888yJlnoTIKitPGHIj3R3hyc0lHwCPLbRdRB4A56EF5yoc4Igzkf09RQEelFNWBwB5f3okJhfnE2MqNZumgFk6wC4gDzoZcKbfRLfmrWR/Tw7mUoGsl0Ao5DzVueEXmUyThxcW8heUeVDanMmAIwLnxoULF55Nv4w+Wg71X85IgCE3AoEccjScPr8ZderZNCSNX3lo8ioKk28aNmzYhFz8cyYPPF/DHZAbRKPXmzNrK6B6qM0ygbxP6WCOtaUjWYNzgpH2fo/JVwDyYdxmUuH9zWZN3eXKePuYjGAWPDPH2tD0GhwZTLR7cIzS4Jp8cvY/QN6PIG/KAU0OVouMxtPBLh0MuTZ3rMFBPRzOjQT4aO1M/ZfTEmDIc8Emt5s0wDV+OydNY5oBR5ym2ktLS802m21kTs+sGlxQAoC8r4nMFZp9DQAGIct8m9EwstRuh0XCw9DGqAfceP/992MrGrYzKJcnEjgJOdjIUhcQBbcPHQx2wXRwIGyDM/XGs846S22PzdI57k23AXkJmbAnfNm5dwUAn1mkbe3+ohNwRAVYgwcBHzhwoLrA7A0pWVxWg5xe5Wo8qQCzZjQAuNRs7rKSwhocAwHsRrvdPhwnyuWnBAB5H9LkLZomzy4ZFJmNYFfjmHuu1+AGevdgMScqPz8loEGuafLsGr/ZYAC7bI3A1x6751EgwkhbZIvVGjiLJH99QF5Mmrw1SzQ5mKVFcAAOpa3BjdnjkyD1BDheMq6ckoDQNDntQsQSYjY4ghzsBllGWLbBMQaDAhxiUI4lYCLNWEzmiqbJM/zBIKvByIBz9zUNzica+QpwFofyWQIMObGe0c4kAgx4sKeswYMRCvCMnsO0dY4hb/P5M/YZT7NJ0+AsI41pXkVBJCKUicLiUX4XCQDyIhNWyYP6sEuedEZE0+DcLwU4S0L5YSXAkLdrmjxslrRFGmOxwal3bLakraOq4cyWACAv1DR5ZvWTVlHArmaJcM/YRAn+zfF6ve2cqHwlgUgSYMi7rDNTASYs1b7PH5DZ1Zjm/gXH4fP52oInKqAkEEUCgJz2YWeMRU6Xv3p2NZWO1c3gCqfS4FFmVCV1kQBD7qS3aKX7LXE+v1/W4BrXbKJwxwNKg7MolB+rBAC5jd69Ql5anS8goMGDyhqdkS8otQQFeFrnKGsb1zQ5Qa5p8jSNwm8ImihByMNq8EC6/9akSUCq2d5JAK+H0zR576rpUWkwSyuXETW4Zq9QzQFlg/dIvqpQpwQYche9vDvVb7X1BgRs8CDL6JKswbUEAry1s6/KUxLokQQAeQFtQUz1HU96FzrYZcC1vss2uBbhcDgaoO7VnvAeza0q1CmBDsiFcPlTIxJQ7aTXoetbYw3O1PsbGxv/oc+kzpUEeiKBk5q8J6XjL9Pk9YBd/KSYZ81EwQmcFllRUbFfXWR2CET933sJAHKrZq4k9w4nelrldOwnLwg3wqzBka4lvPbaawpwSEO5hEkgCHkS18kB72v1zXrAg+vgTL3/7bffbnG5XLVms3lgwkaoKsp7CQByC0nBo+nRxIvD7ffXrjve1EI1dzFR0FoQcGRobW2tUmYKxKJcIiWgQU6gJ1qRg9U2X6CK+gq4wwKOcQByLUN7e/s/EKGckkCiJQDI6fUOCd9x2O7zgVkZcK3rbIPLGtyHlRSlwRM9tao+loAMOcf1xge8TT4vAPfREaLB5XXwIOTHjh3b35sGVVklge4kAMhhqngTsC0E9dR6fGA2BG70IZwG97/xxhs7aNMVgFdOSSBpEsDNxA5zpXdWuY/MjVW1zTuoowA8BHIGHIMA0Ej00Udga5ubmyuVmQKxKJdMCQByE/ENfd6Tf6C2xR+ofPFITS31UzZRtG7rAWfIvfX19ZsU4MmcWlU3SyAIeQ8UOYCt93g3keelI0R7o34ZcJxrGpx8X2Vl5UYFOESiXCokAMgBI3lxHTDkqxyujVQU2ps1eLDLMuD4MbAG9y1ZsmSTn1wwpwooCSRZAgx5PM3Qg3L+JTX10OAMN3OsVRMOcO2XsGrVqkayw8uVFo9H3CpvbyXAkMNa6e7AQ6DNXl/5W8fqGyk7a/CIgKNvrMFhz3hpufBTBTjEolwqJQDIAXd3DrDWuj34+KvGK/lsgweLyhockQw4fg1essM3KMCDslKBFEqAIY+mxdGdynbPBvIAuGyiIElz8o0eRLB6xy/Bu2DBgk8vvfRSZ1FRkU3Lnaf/VRaVCM/xmpwffSRlBijCuUjxyBsxLUJCpMfbkB39AvD6/jn8fufjh46wBmftHdJCOMCRUbNnPvnkk5bq6uoPRo8efbmRnphOhGvbWiGO/c9fhaeuORHVpaQOt+8rwlmCb7uHyC6k7UgpUctEKBStTEijnSf6iZfzRGhCyxJvO3K96Q7T42mi2nnig21N5dhByPY3Qx7snh5wJEAmmgYn37Nt27a/nnbaaQkDfP+dTwp3dT3aySrn9HtEu9+r2YYQUCw2IgbIeRk0lOO4cOmIk12q88ttI8x9jdR/fX79eXfl9en68pHG7w34xW5nzV8pv4cOeQ08pIpwahltMuDeW2+99SPaPlsfTUuE1NjNSTbCjSEVGS2i0NihD2KFG+U4L3w5jDQ4OY7zyL6cRw7LeeSwnEcOy3nksJwHYb1DXjguw2EtMob/uiuvT+d22Ne3h3iw6Az46he37PyITiNeYKJsNMCh9j20s9Bx+PDhvyUKcDSarQ6Q2wnyaNf4nMa3nTFWjsuEcXNfYu1fsvP3RCbQwLU+598a3W4HBaHBw15gou5wgCMeGpy1uGft2rVv0OskEJ/3DpDbjCYNWoZE9iEghkIOy3nSGZb7JIcj9UnOI4cTlT9SPdHiAeZ2Z93r5MnmCaK7uEiA40eCXwWo9sydO3dXU1PTl0qLd8iPIe84U/+nUgJgsC3g+XJJ8+7d1C4DDlbBbBcX7iITmZCZIUclbloTX1VWVnYnfcMH6XnvADmcKwDZKpcqCUBN13jbVpHnpoPNE+a1SzciaXBkRF1BLb58+fI36GFkVKhcpwQ0Td7lS4xKPMmUgFv4PG+3HXmD2pC1d1jzBP2IBjh+FSgIM8W9dOnS6qqqqjfV/iuShuSwsmJTkEsSSV4Qa9+1Pseb77ZWVVMr0OBgE4yC1bAuVsA1M+XFF19cTFo84q8lbAt5EKkgT80kuwMB/7q2I4upNTZPegU4eh2ixefPn1958ODBd5QW7zqhDHm0q3+V1nMJkPIW9f72d149UVHZCXi3cGOWomlwpENbB80UCrteeeWVZz0eT8Q/CSiUr64DciwhnnQcjnbjArk5PV6fy3KL+va6q6+35fX1d1dfd+n6+vjcL/yBjx3Vz1J5Fx2yeRLVougOcPQHFeBiUzNTfvvb3+4lLf53pcUhmq4ON4IKDB2QY3Lg2JfDPHFyHMLxOq67p/X1try+v93V1126vj6cd9jezr+vaCrfS6dsnoDJqHCjbCyAQ1sHAaewa82aNc+QFkd55cJIQA85w5cKH91hiORwKtpOVhs+4nij89gzNB7W3oAPTHZrScQKOGtx/Hpcc+bM2X706NENSouTNCI4QG4lTZ5qx3AzbGif41Ldl0S0B+1d73dtWNy4ezvVx4Cz9k4I4Ogna3EY9oDcuXr16oVqRQWiiexOavKTiOEyC44vtzisRXbGcxznicfnsrHWp8/P5SL5+v531zd9/fry3aV7aOVkk+P4QsrnpAPsgcGYtDfli8lEQT4ADi3OgLtmz569jd4l/rraowLxRHY2TZPjY6kd/5CTJ1kOR0qPXHP4FK471vr0+blcJF/uc/gehMbq69eXj5buoy2xR31trz/duGMblWPtHdPqCfciFhOF87IW1y420eBdd921gB5MblR7VFhE4X2GPHyqig0ngY49J97GxU27FlA6wx2z7c11xgs42+Jo0Pnee+/Vbtq06U/qgpPFGdkH5FhdUS42CeD5qb2exj997qzFG6tgnoC5mG1vbiUewFFG1uIa5LNmzXqNHmvbri44WaSR/QLaZstLiJyLrXP4sRwox2XkMJeV4+Qwpyfal9uQw5HakfPIYTk/tHej37X9vuMbX6M8DHfc2hv19wRw1uLaxSY6sGLFikecTifegYg6lYsiAUCO1RWeUGRFOFbHeSOV7y491nZizRdve93lB0Nu+qD8O22HH6E+AG6+uIxbe2MM8QKOMgw4flGaFn/ooYd27927dyW9kRbpynUjgSDkeP+HOkJkEKBfwCF/68oXmvdgv7dee4O9uFxPAEcDDDlrcccdd9yxqK6urlqZKrHJH5BbeqRfYqs/G3NhzftEwF39ZNPORdR/PI6m195xD6ungLMtzsuGzs8++6z+pZdeuos+f0JLl8pUiWUmGHL82c73A69hcwm/5/3WQ3eVOxrw2gWGO651b73cewo46mHIg1qclg23EOiL6AaQvh11HkECgNysNDltdPKLfe6GRU837d5CotJr7x5rzN4CDlMlqMUp7Lz88suXHzhw4CN1AygC0WGi8x1y3NCp8To++lXN+uVgqPPgu5ZgLC2AY6rQOA6+4MQvr/3OO++8j+zxGmWPkzRidJq5YuiNvomxoQzLBru72e+pWdS46z7qWjsdYAgmAJhivijYM5cIiaITWD7BLw6dc9ANoGMvv/zy3WSP0zeGevzjo6ryy2H50EKQR7pNnmvx0MvugN/7vuPw3Vucx47RbGv8kA+WeFmwVxAkAnAQjM6wqaJ1kl41sfnTTz99Cva4gjz2OQLk+DBTrjswAbt7r6fhqacbdm6m8cpw9+rCUpZdIgBHfQx5iKkyY8aMJbQh6123Gz9I5WKVwElNnrurK16C+4i39d05NeuXkFz0pgkUZkL+9CcKcMwdQw6acaGATrfPnDnz13TR+ZmCnKQRh4OpYs5Rm9yjXVS2f3ZX3YZfk0g0TsjnZcGEwQ1xJxpw2R7XIKevRJy49tprZ9MDEuVqUxZEHrtjyHNpjRwrJvU+R/nDjZtn13scJ0gaAFyGGwwlRHtD0snY3obOyR00EOTe/fv3r582bdr0pmXv9MVXbpWLTQImklWHQGWRxlY203IB7kaf69CC5p037XDU4osCbXQw4DBvE6q9Mf5kAI564UJAJ1vc1dLSsnFUZctltKOuUEHeIaRY/gfkcBBotq6k+KnzJwKe+mUnym9c13roIA1FD3dCNTfkBZcswGV1Ewxv3bq1rcBk+Xycpd836c+vVUHeMQmx/M+yCgozlkIZkoe2mYrWgKf19ROVt/y55cty6pYebmhuAJ5wlyzA0VGeC/a1zm9z1jaVme17hluKL6HVAgtPXMJHloMVsqxCBJrh4+yA292+tv3Ifz7btAu34WW4E7beHUkMyQRcbhNzEpyXTY5jx+kJly2jrSXTSZPbeeLkAiocXgIsq6Aww2fLiFjY3Cf8nsbX2/bf9mzjLqx1M9xY80463BBCqgEPgr7VWdvQbvCuH28tnUo2eR+eOHRKuegSCMqKTHOY55l44F0mDQHn0eXNX9z8yomKPTSiVjoAOMONmzlJsbup3qBLFeBokJVOEPJyV2PLUW/738+2DbjAZjCV8cVUsHcqEFECgDwoyIi50pOAde46n6NiYePuW9a2HfgH9QJgpxxujD6VgKM9OJ4XzT/gOeHY7W5Yd65t0CS70TRE24nRuWrQkV39H0kCDHmmrK1gZnH7/ZjXsfWRhs23b3HUHKW+682SlGhullmqAQ+Bmzqhndd6He5PHDUfTC48ZXShwXyagpynp3ufzRUIMp0OuwLpWUq6/d72wd21G+fsdzfVUX8YbtzIwQ7BlMINeaQacLQJ1wX0Fr/b9zfnwQ/PKxhUUGKyTjIJo4Enr6OI+j+SBGQ5YcU81Qfgdga8gQpP0/O/qP/4d41eB77yK8ONC8qUww15pQtwtM2Q84VGwEsbyN9srdo60FRYPsRin2wxmOzYS4AHc5WLLoGT5kr0fIlMxY5AvL+k2e9ufK/98Lz7aje9SnPIF5PyHcq0wI2xphNwtM+Qww+CvsFRfaTa2/beuILSM+0G0ynKZIGounephJxNkhpf+7aFjTtvp5WSHdRDaG3W3DBJ5KVAzHHKXaYADrj50KCv8rS0rXFUvXtOwSBTX5P1K8pkiY0NNleSSRNu3sAkKfc0L7+j9sMH97ua8fYpaGyGW795KrbOJyFXugHHkHgu4DPkmjanP3e+Na1V2waa7buHmAsn0/ZRu7YXQ5ksUVE4adIlducKcU0mCW7euBvWOo7c/UDtxr90miQMN9a4+WIyabffow5el5gJgKNLMuQy6Fp4g+PY0cNksoyylgymz4SM7nioS9nmurkMOT0JeUh0j05ga/toiuj78OKQr/W9RY3b57x64stdVBlrbACuv4EDJZV2l2lXb+gPrivxw8OXVgvosNFhp6MQ4TvKzvnni+yn/rLUaB2BJ1/4TzKlKRdGArCVe+PY1m70uw9+7Kz+wx/rt26g+mCCMNS8BMjbXbW/vr1pM5FlMw1wjA19wgHI8SVmKx2AnEG39zfbiu8vu+CasdZ+19HHWAvM2ESqzBYSUXgHDRwv5rxC0ub3uCrI1n6w/tMXGr1OrJBAU+MA2GxrY5WE93LH2xQVTZ7LFBNFP0IWEnwc0Aps0/mcfq/3rbYDO+r9zrUjLMVDaePWCGW26EV48px//Kw5ovl4wxSbI/Ty+Y+fa97zq0WNO9aRzOXlP2hvGW7MT0aYJCdH3RHCWDPZoX9ssrA2Z40Os0XT7HMGnP/1C2yDbulrtI7E64nx7lae1EweXKr7Bq0cybGd7SI7m9a1D3zmqln0WN3nH1J+1tSstbH0xzduWOlErjhSgymKz3TAWQyAnEGHbQ7I2T7XIDebzba7+p1z6STbgGv7GwvGKNBZdNF9GWx6J/eXO5x1z/++aetaejMZg80+r2vLtnZGam15xNkCOPrM2hygQ5sz6ACcYYdf8Kuy8y86zz7g2jKj7SwFOkkkjJPBJlNv9xZH3fOP12/+iLICZBwAm31obIDNdyQBdsZqbepb0GUT4Nxp9BnXDgw6tDlrdA1wOtf828rO+afJtkHXDTLZz7XiNQxUBIXz1XwB1KASa9n0Rilx3Of4fJPz+PKF9Vs/o2gGW/ZlcwRQ84UkBbPDZSPgkKzGKfmy2QKNzkuLMujWG0rPmnRhwZBvDzbbp9sN5kLAni8XpQy1n9AG1I6At51edPnBRlf1G4sbduP2OiCWoUYY2poP2c7OCq1NfQ+6bAWcB4D+A3IGnU0XBp01u6blh5qLi27od8b0Mdb+3xxosp9PoJvwch3Anmvr6Vi/BtRegprA9tX6HJu/dDe+vbhp7wf0RincoGHtDKAZcoaal/2gtbPGHKG+dnHZDjgPSA86TBi20dmEYV/T9FMKTx00q3j0ZSOsfb5ZYrCO0UyYLNbssqbuhBpfS/jyoLvl7f9r3f/O+vajx0kmDDDDLftIg7ZmjZ3VYNM4NJcrgMvjgTbHuAA5NDprdQDO0Mu++Yf9xo2dXDB4Kmn1c/uZCibShWkBPi+CR+gy1ZSRgcbmJzxJQ0t8riafaxdp6883uWo+Xtm0r4LGDG0MeAFzOB/prLFhguQE2DQOzeUa4PK4WKsDdD4Ath54TaNTvJbWz2wr+FHfsRMnWErPG2iyndvfVHAGwW7BBSqA7/jX0QwLL1kXrYAYjg1f+LhMBNC4UCSoPfSmqL21Pufn5Z6GLS83V+xq8jphcjDUAJoPBpzTWFuzxu6ongrkkuM5yqUxyWPB+Bh0va0ua3eGnOPYNw21FRX+oHDcV06zlpxdQvtfCg2mEYVGy1CrMNpZw7Mvwy93AmG9oBlafT6GGPYzQGbfLfyOdr/nSHvAd5B28x2scp/Y+Wr7vu1HnG24qwhIWROzz2DD5zj4DLRsX0fqDmXPbqeXe3aPJnrvGXT2WavLpgyDrfflvNoP5eLiYYMmWctGDjEVj+hrtowsMliG01cayugppEK6k2qnbWCFlNGMxhh81vRsXkAbgywizUuvWWinW+QOT8DX7vL76tsCnkPNXs+Bal/rwR3u+gPrWg/DhmYoZe0rwxsuLOdl84P96BLLgdR8Apynq4O5DqWKMOAFtLIPwBlqhp3P9Xk14DvrCKmbzB3zSGtx0RBjob2fuaCoj8GKHZGiJeBub/K62qr97Y4D7tY2MisAZofyPukzzPBZ68o+wgw0Q4xzOQ+X1ddN2fLD5SPg8syGAEkJMqx6kGXA9WlcDvUhzPWiLTmMc9kxeIjjMGtXBlwPLEPLUPM552ef62NfbjdvwhC+ch0SYFkwkPD14PI5QwzokY99jg9XF1rheEAHx/DpzwEp4gCx7DO87CNNDuMcBxz7HWd5+j8LPE+HH3XYLBv40Q4Zan0+NCDXIzfIAMo+wvqDYdfHy+eoF+fK6STAwtdFq9MIEmB5McjIFi1OTo9QZQiYDCnDizLR4iLVqeI7JcCTowTSOwno5ag/R+36OAZXblkfpz+X86pwDBL4fwN/IZwMBwH5AAAAAElFTkSuQmCC',yellow:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAALcAAAC4CAYAAAChOH1KAAAlaElEQVR4Ae2dCZhUxbXHTy+zL8ywDDsSVhEVJQoCkoSIIr4kvohLxO2ZfC8an0mQrCQm+uJ7qHkv5hE/xSQaNokBogkxigaUuLDIpsiOMA4MOwyz7zPd7/yLOZfqnu7p7umeXut83+2qW7du3apTv3v63Lr31rWRkUhowOZViPc6Nutpbq/8WPVO8173sYtJ6kgDusI7yme2nYdTdIZQj0NH1vrgwYNtc+bMyb344otzCgsL87KysnLT0tKym5ub6+rr62vKy8urd+7cWfv444/XlJSUAGSB2VfoKw3HM9KBBqQzOsiSspsEXgmhCMTtDGT2TTfdNDwvL28kQzvC6XSOcDgcQ2w2Wzfenme323M5nuN2uwPql/O5OF+dy+Wq4X2rOV7Z2tpa3NLSsp9Pgv3V1dX7XnnllU/4RKnj7S5edNARl4WjRnQNBFS+njnJ4wKxHtp37NgxpG/fvlPY6l7CAI/kZTgv/YMBN1L64hPAzcAf5eUTXvax9d9x/PjxtZdcckkxH0OAF8gljNThE7acVIdbQLZzDyJuX7du3YChQ4dOycnJ+QJb5M+zFR4Qr73L1v4IW/h3amtr/3nw4MG1kyZNOsJ1FdglBOwpKakItwfQTz31VN4dd9wxnd2LL7J1/hzDPCxRSWDYD7BVf5fdmbeXLl26avbs2dXcFsCdkqCnCtwCNEL7gAEDnBs2bPh8QUHBnenp6TdyWi4vySY1TU1NKysqKl6cMGHCO0eOHGnhBuqQJ71FT3a4FczcqQgdu3btGtWvX787MzMzv8YWun+y0eyvPWzRjzY0NPzp2LFjL44ePXoP52vlRbfo/nZN6PRkhdvyoX/7299245GNe9iHvoMvBC9P6N6KQOX5gvRD9tGX8gjMovvuu6+SixRrjjCpJJngRluwAGz78uXLu0+dOvXbDPW3eL2QFyOeGihnyOevWbPm6VtvvfUsbwLcAnpSuCzJALcH1KtXr+4zduzYWbm5uf/OnZWMvrQnouGv1bD8ftu2bf937bXXnmgDPCkgT3S4lZXmDrGvX79+0EUXXTSbRz3u5fXM8Ps85Upo4FGWBbt3735q4sSJh7n1YskRJqQkKtyoN8B2vPzyyz2uueaaX2RnZ9/NN1bSE7IX4qjSfMOoqa6ubvFbb7318xkzZpRx1XDxKZY8jmoauCqJBjfqi8WB4bzNmzf/W/fu3R/j9R6Bm5o6OWyuErK1fMiKwuhfJ8VNZWUVtT/77MTHFrYNI8oIS8L444kEt7ggju3bt182bNiweXwHcXwnuy5pdwPYzrofMdiR8SaaW9wffFLc+N3RE/7xEStNrHhkCu/iXkgEuFFHBfb8+fMLb7vttkf4YvGb7II4u1g3CVm8vXEpORtfiGzdbbaWmpqW3724ou4/v/WDj8u5cMAd965KvMMt1tp56NCh24qKip7gmy99IttzyVWao3ERYekKcbnpxKmy5h/3HbVpGZcvdzzj1ooDnngUnHQOLI8++mhBZWXlC3369FlowI5tV9lt1KdPz7SFdaUTXnj00REF0kccxqWRjMdKWWBv2rTpUn7YfwnfWRwZ225NnKN3peXWtdDion0799TedfkXPvqY0+GLywWnni2m8Xiz3KgPLLbz6NGj3xgzZsw7BuyY8uH34E47jRxzUc47J/eN/wb6ixf0W1zxFC+VEWvtnDt3biE/ybagZ8+ez7CysngxEqcasNkoq6i785m6w1ctmDt3GB5xEMjjwiOIh0qgDjjJMG49hp9ae5Gt9fA47c+4r1a03BJvRbS43J/s3FN3R5ubIhebMR0Tj7XlFoudtm/fvmsuvfTSNQZsb2wSY91ptw0fMzrnrYObr7iGa5zGC9yUmBrPWMItYGOY7xZ+W/wvrIw8XowkqAa4Q/M+MzjjL0d2jL+FmxBzFyVWcOO4OLPT+AH6b/ELuAs5bp4LYSUkujDg6f37Ohee3ncVHjUWCx4TzmJxUAE7/eTJk4/06NHjKb7bGIt6JDpH8Vt/N9l7dnc8dfaTcY9wJWG0YjKSEm2oFNh80ZhRVlb2NL/D+KP47SFTs3A1UFiQ9qOakglPjx7dKyMWgEcTbgX2+PHjs3j6hCX8fMjXw1We2T/+NZCTY//65jeGLRk/vjuGdaNqwaN1NavA5salnz179jl+9evO+O+WxKxhrIYCA2mrtq71xdwLNt7P+Zp4kacLA+0W1vZoWG4BO4197McM2GH1V8LunJPtuLP84FWPcQOidpHZ1XCjfCxppaWl32Ef+6GE7R1T8bA1UJDveOjUnvHfAQ+8CBthl+uvgK6EGy6PAru4uPj23r17z/VXCZOeOhro1cs5t3T7uNu5xQJ4l7nGXQU3KqzGsfmF0+v79+8/P5oTR6YOKgnYUjfZ+vdLm7/vg7HXtwEOTroE8K6AWyy2kx9ZHTdkyJAlbY1IwJ4wVe4KDTAgacMHZy3Z9vbl47h83MkEhxEHvCvgRpnOefPmFfF49lLMU83rRowGPDRgs1POpRdlLZ33xJAi3iCAe+QJdyXSZ4sCmyuVwY+truA5RKaFW0Gzf2gaiNehQH+tqKt3vZkzaAOeRWnkRZ4m9Jc9pPRIWm6cKMrPPnz48HcN2CH1Q8pmzs6yTzux+8rvsgJkiDBiBjdScAvY8LOv4hd58UyBEaOBoDRQ1DPtEfa/r+LMEX2SMFJwoxzHE0880Yv97AXsZ6OSRowGgtIAeLl0VNaCJx4d0ot3wL9/RLiMxF8AKgKY4WcvY3dkOseNxEgDieZz62qqq29dlTNo422cFhH/O9wzBCeHgptfOHjAgK13lYmHqoHsLMf0ozvHPcD7yehJWMY3HLgtsBcvXnwB34F8ONTGmPxGA94a6FuU9vDiZy6+gNPDBjxcuNXoyA033PA4+01mLmzvnjLrIWuA36jP/dcb8h7nHcMePeks3JbV3rp167X8sVF8NMmI0UBENJCXa7/xo3fGXsuFhWW9Ows39nNed911uRdeeOEvI9IiU4jRgKaBi0Zk/vK663rDGxDAta3BRTsDt2W1n3/++Vk8jfDQ4A5lchkNBK+BNKdt6OJfD5rFewjcIV9chgq3BTZ/UGkY36wxz2cH318mZ4ga4Js7Dy1fMHpYZwHvDNzqIpI/1fEkX0Sab8+E2GEme/AasNltmdO/kP8k79Gpi8tQ4Las9rvvvjuBXxe7LvhqmpxGA53TQE6O7bp1r4+RW/PgNWj3JFS4ldXmW+zfY6vdudqavYwGQtAAOONb89/nXUK23sHCbVnt119//TKelmFqCPUzWY0GwtJAbq596j9eueQyLiSki8tQ4IbVdl555ZWzOTRmO6zuMjuHpgGbbfxlOeAOcIPDoPgLBm7LavM3H0fl5+d/KbSKmdxGA+FrID/P/qWXXxw1iksK2noHC7ey2pMnT8bQXzD7hN8aU4LRgIcGbPYpV3UDf0Fb70CgitV2LFq0aAhb7RkexzMrRgNR1ADPezJj0fyLhvAhYWzBbofuSbBwO6dOnfogX7miUCNGAzHRAA+cOP5lSt6DfPCgXJNg4HawO5LDs0XdFJMWmYMaDWgaKChw3DR5ck/MqBDwwrIjuMUlwTQN0/lzHvjuoBGjgZhqwG6ngmfnDsTbXgGtd0dwY5u6kBwwYMCt5qZNTPvUHLxNA+BwYP/0W3lVLiz9MuxvA6w2FsecOXN68fPaX2wr2wRGAzHXQF6O44tzZlsvEwur7erVEdzY5rz77rtv5s9S49anEaOBuNCA3W5L+/rt3W/mynTomnQEt3JJ+JvrmA3IiNFAXGmgX1FawC+m+YJbzLxjyZIlI/mNdtzTN2I0EFcayMqyXfbS7y4cyZWSURNw6yH+4MYOjokTJ95iLiQ99BX3K271Tx331Qy7guBy0vg8WG/FKoft4IbP4i3IpPztwsLCz3tvNOvxrYEW23iqKPs9VxKfnUlc4fncPSrvtUpYb2lygU+/frc33JZLcs899xSwS3KpxxFSdMVWv4dsle+Qzd0c9xqAGevm/AJVVBSTy+ViCDwhQQN8JLVLc1P7/bz39VXOuTye+/rK5zvNcz+U1ZG4XO5Lb5teWbBs1QHMUCXsWoV4w42yYLUd99133yQ2/dBVSoutbhc5997MmkscS4hOK2hxU1mlb7h9daj3f7r3uq99Yp3GJ67jnqktk5atopVcF3Dr0UnecKNNCu5+/fpNNv42m4PyN8jWdDTW/Rjy8TF22yPLTWeriFyWLQu5mLjeAbD26eaezMHfeQG3SLJaiwRdsK7g5icAJ+kbUjVuc+OziYkpPD0Cdc/nDk0EM9xJFedn2ybyrvizEnatknS4oQIsjlmzZvXMzs6+0MplIgmrAQHcwT0tHZxMYXaGe9QDX03vCW55kaap/vIFt33mzJlXt2VUmcxPYmsAgBfmsWkD4Nz9SbbYvnq1G7yC5Q7hRgYH35W82vjbiQ20d+11wL23JfI6OO1TSIBbXBMArsTbciu4eU4Sc1dSNJREoQKcZ9+DBY+U4F8AIv8GEleJUfrJyiTw2g5uGS0R2hXcPL79mSjVyxwmyhpwwkXJdVNFTeRGUQRwNEXiEkajedkZBF4FblUN/nHr5zDi9p/85Cd92NSzh2YkWTUAwAtgwcWkJXhD+UTKm3VLWh9uhmJYmiNwo5lY7Pw8yXDZaMLk1YAArkZRuOdhaRN5mXSxDdyCZ2FZrUgPKrj55s1QczEpKknuEIB347cRYcGFiEQMUf++3V1DubcEbtVx7Sw3v3UzLLm71LRO14AADqudyJKbaQO3ArdqjQ434naeB3CIsdyJ3M2h110Aj+QoSui16Pwe4DUnm4ZwCYphDhXcGC2Rcxahg0dKkMlIimkAgOdnu6mqzvdTg/Gujqx0G7jFiInFM0iHIME+atSo9MzMzAEqxfyknAbOAc4gMBWJdnGZke4eMOozmengmBcFuA63bdq0aYV4jDDletU02NIAAM/LOge3lZgYEceUMa2FXFWAbcEtKzaen4RHP42kugYE8M6Mg8uFqVh+6FLSfOlVtnU2v+yHcFCRG/xaPOt3KG29evUyN2989UAKpgHwXH4evKZee0A6SD0IsMgucQl9FaFvk7iEgfLr27vnucGvwK38E9lu42FAY7lFGyYkZcGz2YkFLgkg+TkOsdyqtjJaomjnZ7gN3AnQidGsosOhWXDrHZdo1iC4YwHgzEzfbglKsBm4g1NkquUSwGsb4neYEG5MTjp5WG6P0RIeBswxN3BSDd3g2gvAc/irox35wsGV1DW5UK/0DDemNlZeCI5ijQkikT91jY1GjAZ8asAX4AI7Qj3us4BOJOpl6nFfRaU77AI3Ntv00RK+gDBw+1KaSTuvgXOAu6mOZwqRuUcEOuSSuITn9+x8TC9L4hLqpTqdynIjCdbbc+6t1tbWFiQaMRroSAMAnF/MpXoA3lHGKG9rddk8+BWfG9WwNTU11fqaoSjKdTSHSwANAPCsjDYTGQf1xb9IYzPVclWU1UaVdLipoaEBG40YDQSlAR1wuYrzDlGQRZuPUmWb937+1r3L0/fnuQM9+NXhdhu4fWjfJHWoAQtwocwrtyQHC6vX7u1WvctDBkmrb7YBbstTErhVQl1dHb82asRoIDQNAHA8j+frIi+0ksLLzRe5wq/iGaMlQrq7oqLCw6yHdyizdypp4JwFd1MDzz4noyjRbD9OrMpaD8vtlqFAAO4uLy8X8qNZL3OsJNEAf6uGLfg5wKPdJMBdXuMCv4plHF/cElWX06dPV5vREqUK89NJDZwDPPouCv4tTpVTtV5tgVvRvnv37hoDt64eE++MBgB4Bs+hDGvqvaA8pIlIXPIhXdIkjx7KNskvIa4q9xyyA24Py40ViHvlypXVPNbNMzobMRoITwMW4F7FeMOJzZKmxwVa71DPg7hIczNVvba+SdwSJFszTgntbh4xKTHWW1RmwnA0AMDTYcG5kK5ccAXLIyUlfBiLY9Rb3BLEscFVW1tbghUjRgOR0IAFuOaKRKJc7zJqG2wlnObiRTwRBbfQjg0uHg781Fhu1oSRiGkAgKfxuJy3ixGpdVS0qtb9KQeKYQ4V02K5BXA3j5gUI7MRo4FIakAAj2SZelmnKuggr1scYxvg1hNaecTkoLHcUI2RSGtAAI+UxZZyUM89h1wwyviamcWzWG5sVyZ94cKFn/L3CxE3YjQQcQ0AcCfPjAMwIyVMq2vhasenXJ5iWMoVuIV2165duxp4xOSYZDCh0UCkNaADLtY3nLC+yXZs14EmfsPTuqAEz9ZoiQU3p7XW1NQY1wTaMdJlGsC7urDg4Qpc6JoGN/xtuCSw3MKyB9xi0l0nTpzYbPzucNVu9g+kAQE8lDFwlOnh0TDKJ8tsmznZ4pfjHpYb+yABGVq3bNmywbjdUImRrtYAAHeE4IML2HJC4OvIW/e3buB66pZbVbudz41MP/3pT3fziwvmNnxX96wpX2kAgHd2ZtnGFqr68QuO3eCWF59uCQ5iWe7q6uqms2fPbjWuCdRiJBoaEMBDORb4LKugLYwrvmGuw62KEcuNFQtujrccO3bsAwO30pH5iZIGBPBgR05QrWNltk0c4K33gHADcGRq2bBhw3rjd7MmjERVAwAccAcj8LfX7Wxdz3kFbvCLRYleDOIYnOEX9tWca93OnDmznmd+7aFypuiP48jjhMVIdDUQjNdQVecuK7iheSLXrJIXPO7KM6ko46wAl9fMOE0Rj0Q1YsJhC8O9mT+Vfb09Ub8EhFaFKc2taVReYRmDMEszu4eigY4Ad7HZPnyKMAQoVtvjYhLH0eHGusCNHVr27du3euDAgRGF21axm2zH1pLN3Yzjxb3YG89Qel02PzIM3bUXf9jjtSdf4i8def3s4veFW39l+StHHaODjaGW5zd/R8fw08pQy2ppddOuva2rGVPFKrdN4EYzlehuCRKwDuB5Pk/KGzlyZM/169e/z5/vi8gXFwC28x9fZrDh1ieOVNW7cBcscSqcAjWtbXRXf/l/K6/ed6rpDDcXr5fh9jtAtzrKl+XGRtDXzJa77siRI6tHjBhxUyRcE9vhV8lWe4SLTizJR3XZLtRiwMlIzDWAx/qOn6HV+04Rf1iQ4AKAV3Brgc1x6/Y74iIw71hwFjTxqMlKniBTtoUV2lyJS0c+f+GLJzc3EgcaYI+EthyilVwVAAVOhVmP2unj3LJBLLfyZe6///5NVVVVRzty7mXHZA8BeC6PJcF3M0tsdADbzF94OPq9P5OMb4NTsdweCPqDWwCHyW8uKSl5zcB9Tm95fDWSg8FSIzHRAC48SyvoNT64YpNDARvMeogvuJEBZh474axo5ikf/trM784bOacBATzYO2kmH1t5/quLxNLCCK/aSX8Fl7yI1Qav7cQf3DgLLL/7ySefLC4rK9turPd5/QHwbOODn1dIFGKw2uW1tP3/3qZiPpzub7ez2qhOMHDj7GjasWPHSy1qSBG7GYEGlAVnwI3/HR0dtLK53XWCXmLVC9hgE0Y4JLg5v9oBO8L8N82cOfM1nvah1FhvqOa85BoLfl4ZXRiD1a6sp9L7lil/G3CDS79goyr+LDe24Wyw/G5+9axh+/btf4jUsCAOkCwigEfCpzRl+PbN8ZDUzhP0h5oadbNG97d9Wm2wFQhuAVxZ729+85t/raysPGmsd/vTEoBn8dRhRiKvAWW1G+jk7OXqQlKstt9REqlBR3AjD8w+CgHcjUePHq3duXPnImO9WRs+xFhw31Y33H8jWO29J2jR0Qr1QSc8+QcewSX49CuB4IblRgHqopLDxm9/+9sr+E2dMmO9fesUY+DGgvvWTWdSYbVrmqjsxytpBfjjRS4mO/S3caxAcCOPWG8FOD9vUrVnz54XjfWGanyLAG5GUcIfRcFzJPtP0ov7jhPe6RWwA1pt9EwwcIv1Vn4379M4Z86cl9h6VxrrDRX6FgW4GQf3rZwgU2G1qxup8ud/V8N/YrXBYUCrjUMEAzfyifVWvvfGjRvLN2/e/LS5awnV+Bfc5MnCOHiE7s6lWjktTN22Unp6awmVs5aD9rWlR4KF29t6N8yYMWMFT96z07xnKar0HQLwTDOK4ls5HaTCHTlVTTvvWqR8bTyrLaMkQVltFB0s3MjrYb358yL1y5Ytm8vzm7iMewL1+BcB3PjgwfnguMPC85G4Xt5Gc3nShnrWbMhWG70RCtztrPfDDz/88f79+/9sLi79gy1bBHBZN6F/DeA2+4Ez9OdfvE4fc65OWW2UHgrcyC/WG38ROJsavv/97/+Gb8ufNdYb6ulY4H/DRUk13zmU9kKDlY109sd/pd9wFGDLhWRQIyTYXyRUuGG9cRAMC+Kg9e+9914ZX2D+mt0UXjUSSAMAPMP75b5AO6XQ9iama0sJ/XrjQSrjZotLAt7AHfgLWkKFGwUL4GrkhNfr+eJyJd+93Gbck+D0LoCHYtFSIS/uRJ6oom23v6BeIROwwVnIYKMnOgs33BPrriXHG+bNm/cIv45WY0ZPoNbAIoAHznk+By5IIXJhKnGV2JYuaXpe2R4o1PfR4/720/PocX/5O0rH6EhlA9U88096hPPp7gg4A28hWW0cqzNwYz/xvS3r/dxzzx1cvXr1L3j0hOfZCLkeKDPlBP43XBSAEcwCBQlEelz21dP0uGwPFOr76HF/++l59Li//P7S20ZHaO0++sXv31cfbvK22uAtZOks3DgQDijWG2da/V133fXm3r17l5ubO1BPcALA01PcB29mp4OnaVj+jcX0JmsNYMsIiVjt4JTplSscuGGeAbhYb1So7pZbbvnV8ePH9xr/20vTHaxaFpxNWyr41nob4WefrKG9dy6kX4EfXsQlAVfgq9NuQAS+SsKHPy829rt5gquWDydMmPCVjIyMdMzaKWI/8S5hMdJeA+r7MNyN6GwR0Zy/v/NIp+O4ckw9LsfR0/S4bA81xAx1VQ1U+8s19K1/7qVjXGYtL7Dc8oCUpg0cMTQJx3LjSDi4t3tSN3/+fPjfjxn/O7TOyGAXJQ2f0ODdsEAkPLfWtb9yLH/HD7Q9lNrhsqyBnY639tJjv39X+dlitQXssKw26hIu3ChDABf3BGdeHfvfq/jR2BVm/BsqCl4E8OD3SMycGM/ec4JW3LuYVnELADa4wb2TsN0RLkNJJOBGQTjLMBbpAfj06dOfLC4uft8ADhUFLwAcF5m6b5pMcVxAlpyl9298jp5krXiDDY7AU9gSKbhREVhwffSkjt+3rLn55pt/WFpa+rEZQQmtrwA3XJRkE4B9pJw+/trz9MPKOjVhvLc7Ao4iIpGGW/xv/L2o0ZMDBw5U8HyDD/HjscUteEDXSNAaEMCTxWrjgaiT1VT84Ev00IFTVMGKELDBiwz7RQzurrYNqqKHDh1q4tvzGyZfmHVNbsUHufz5byNBasDRZn7kvpiuOokj9LXgEJJHj/vKK/kk7Ex+7KOLlIUQdyBP19CJOa/Q/W/soSOchJERwB1RP5vLs6Qr4PZ55vHFZb2r1b1lXNHRa/muXKYB3OqDgBFfgOvg+CtAz6PHuyo/jqEvOA7WYbF5GrSKX71NDyzaQAc4SYb88O+O67SI+dlcliVdATcKB+CyyMFsH+w6WsnTAO+8pD9dx4CnGcBFNYFDAVwfBw+8V+xzAGyeKar+D+vpu798k7ZzjWCtxR3Rh/0iXtmugluvqECO0MbPD5zpmUs7RvamKQx4Rgp/S0rXUVBxAVwpkk1ivPviAPtsPVUv2Uizfvaq+jgToBarDbBhsdGcLpFowo0GqIas3kOnud0fjBlAk/nWc450Wpe0MMkKFV3BB9ddgHiLtzC27GOfmvcWPTj3DfqIuwFQY4ErolvshIab22KdnWiIasyGYqrkZwreu/ICmsivYBVIpyGzkY41IP92cpHZce7ob23icY/jVXToZ3+jB55fR59wDfCNSN1iR3xkxFcro2G55bhyhlqAf3yEanccp7WfG05j+XszRQAcf7VGAmsgHgHHyQawedqzXQ8up/949WNrVEQHO2J3IANpKZpwS10EbhV+eoYaV++lt68dRaPyM2mAAVzUFDgUwJEz1v436oBb6p+W0cZbX6CHNn1KpzkJUMPP1h+GYo/U+ifnaNdJtOHWwZZGus/UUMufPqS114+mfvkZNNxpLHjQPS6Ax9JFwRh2Hdtjnqzy9WnP0k9Ky9QNmpiCDQVGG27pNB1yxF31jeT63Xu07ooLqLx3N7oy3UFO6TjZyYS+NaAPqUbbgquhvkZq5FGwX13/ND3L/YgPnsLH9jXch76OmsQKbjRQQd0WWrAv30r7bXbaOLIPXZHppG7GTQmOBQ/AeZeuHj1B7/HEOXSikg4/vZZmzV5Ba/mwsNbiX8uoiNygQR9HVWIJtzQUjYaLYrkp6w5QOfvhb04aSn3YDx9m3BRRVcehAN7VFCk3hAfz9p6kN29fQD9Y+REd4poJ2GKx9TuPXV0ln4qJNdxotPeiQD9dTc3sprw39gI60zufxsFNkb9cny0xiUoDMtrUFTTBr1e30huo8e399D/TfkPPcj9V8oF1/1qeFRGLHbOeiTXcaLj0g1hvPXSv2EqfuG20bngRXc43fAod/H8rHRgzrcX5gS39tOlKjEI4IcDGmzPHKql43ts0i7/g+y6rQe44yoiIgC19GFNNwTWLF0FdcLJh4cf1Cd/p5Q9SqyW7ex7lLL2X7vjsILq3WyZ/vIBzWZ3ImYy01wDch3AFUOMZbJ5TpH7rYVrAs64uPVvtYan1N2hgrbGIwQr38GHtHw+WW28AlCKLnP0IW+ubyLX0A9pxqIzWXNib+vLk7oPlYtNArqvwfDwcvYgLUsu2eP9pemfOSvrBwyvpHe4HuCAyGgKwvZ/siwuwoYV4styojwieYsaCGT14dj1lxfl7YZYlz3j2drr6Xy6m2T3zqD+PqpAZNmTt+BGAiiVYgcWHC8L3H46+toOeenAZvc/7wuUAzAI01vVnRCLwP8ElRlDiFW40EXUTwAVyAG4tA3tR3oI76J4xA+mOvHTKgKtiIIfq2kswcANquCDVTdTIj0YsvXcpLSo9rcatYZ31RaDmU8Aa5Wp/0BinxDPcUA3qhwXuEwCHLw5LbgGO+MyraNCDk+nuEb1pOrsr6TyyYiBnxXiLP8ABNW6dswvStP8UrXrmPVr8x410mPfXgUYcUGOID1CLbx3CfwLvFUWJd7hFFagnrLhALq4KLjoF9IyvXkb9Zk+lmSOK6Cv8XfZMfl7cQC4a9BECatyIqW6gBob6b0+toT/+5SM1OQ5cDgEbcd0FAdRwQeIWaq6bkkSBG5VFXQVyWHFxVQC4QK7iU4ZTr4e/RLeN7kdfzcugXAU57xnOBRYfIykE1htv8yioG6lm1zH6y3/9nZat/UQ96CQgA2yJ+3JB4h5sdFYiwS1wCeDe/jjAFosOa57+2c9Q4X9/mW4Z3Zdm8J3OQszJJ3c7Uwl0AI0Fkw80sFPBU5iV7zpOL//0VVqx9VP1pTAALEAjrltq8asTwlpz3S1JRLil8gI5XBUs8MdlfFwgV8AX5lHW4zfSxCsG0vUDu9NEfnY8Xax5Ml+Awu0QK13bRE2lZ2n9llJ6g4f11pdXW4+h6hYacfjUcus8YVwQrnM7SWS40RjUXyAXn1wgB+ACucTTxw2mbj+cRlNH9aZp/QroYobcpmZ3QkFcUiJbdLHQ8Bnw0gC7Hu5jFbRzDz8Dwi/nrtlUom6VwzLLIhYa6zrUsNJiqRPCBeH6tpNEh1sa5AtyfXQFcAN6gVydAHdNoAF3j6PpQ3rQlIIcGoxRFoCubg5x5niHXYcZz3wAaIx6VNRSSXEZrV28iVYt2UBHuCkCrkCNdT0O10OsdMJDzW1Rkixw6+0R0MVd0V0WuQgV0MXKO798CRV9bRxdMbQHje3TjS7n0Za+cF0wdq7DjgPFwroDZIgCmkPAjDHpttGO4/zo6YcHy2jbnzbRlld30CnOAmB1qAVoPR1Ay4IjyMLRxJdkg1vvEbQNroq4KwI7ABeovUNsQz7nzHHU78YxdMWQnjSWn0q8LDuNemIObVyQAnbrwpQzQ3Tg9fi5rYF/BV7klLgijX9wIQiYEeKtcn7r5czJKvqo+AxtW7mdtvxxkxq+E+urwytwSyh5BGgu0XI/AlcywXIkM9zSFWLJBXSEFsQcB+BYF+glriBvS7dPGU6FUy+iwcOKaFBRPg3qlkUD89NpIFv4fmzdnQAez1OLK6POLK91bBPLq0IGFxd8AjHSsN5mlVt4/PlYVROV8qQ2paeq6DDPr3d4zW4q4WE7fAsdYAJWAVbiANk7DpiRJjAjVIflMGkFfZAqgrbqC+AF6Ahl8QU20mS7vo86WXIzyfm1K6jfZQNpQEEm5fP0w1lZaZTNw47Z7L9ns4XPZl8+i61+NsOdwQA3svWtY9+4ni1xHfvJdTw8V1fPS2Mz1Vc0UNVHpXTkT1voWE2DB5AAFFCK1RVgBWR9Xc8j+wjMEnJRyS2pBLfekzrkiCtQOdThFaB9wS0nhYRShne5so5jIy4CwCACmncolhWQCpwIJS7wAmyJ+8rrXS5nTx3RFZ46rfZsqQCohwK7Hgr4HaXpZUgcR9PjWBfo9LikIRSQBWZ93V8a0vUyJI5jpKRA6UY8NSAgeoeAGmmBQu/9UDrSvAXwQQRCPRRQA4X6PhI/V6r59al0oxZPDQisSPUVlzQ9lLx6iLi3AEiIHgqk3qHk886rCjA/7TWADjESugZ0vUncO5RSJV3W9VBAlTRZ9w6xXdIkrwkDaKAjxQfY1WwOoIFQdGvADaDMzmz+f6SMYEX4z7hMAAAAAElFTkSuQmCC'};return{FaviconsByHue,};});'use strict';Polymer({is:'tr-ui-b-info-bar-group',ready(){this.messages_=[];},get messageCount(){return this.messages_.length;},clearMessages(){this.messages_=[];this.updateContents_();},addMessage(text,opt_buttons){opt_buttons=opt_buttons||[];for(let i=0;i<opt_buttons.length;i++){if(opt_buttons[i].buttonText===undefined){throw new Error('buttonText must be provided');}
+if(opt_buttons[i].onClick===undefined){throw new Error('onClick must be provided');}}
+this.messages_.push({text,buttons:opt_buttons||[]});this.updateContents_();},updateContents_(){Polymer.dom(this.$.messages).textContent='';this.messages_.forEach(function(message){const bar=document.createElement('tr-ui-b-info-bar');bar.message=message.text;bar.visible=true;message.buttons.forEach(function(button){bar.addButton(button.buttonText,button.onClick);},this);Polymer.dom(this.$.messages).appendChild(bar);},this);}});'use strict';Polymer({is:'tr-ui-b-toolbar-button'});'use strict';tr.exportTo('tr.ui',function(){const Task=tr.b.Task;function FindController(brushingStateController){this.brushingStateController_=brushingStateController;this.filterHits_=[];this.currentHitIndex_=-1;this.activePromise_=Promise.resolve();this.activeTask_=undefined;}
+FindController.prototype={__proto__:Object.prototype,get model(){return this.brushingStateController_.model;},get brushingStateController(){return this.brushingStateController_;},enqueueOperation_(operation){let task;if(operation instanceof tr.b.Task){task=operation;}else{task=new tr.b.Task(operation,this);}
+if(this.activeTask_){this.activeTask_=this.activeTask_.enqueue(task);}else{this.activeTask_=task;this.activePromise_=Task.RunWhenIdle(this.activeTask_);this.activePromise_.then(function(){this.activePromise_=undefined;this.activeTask_=undefined;}.bind(this));}},startFiltering(filterText){const sc=this.brushingStateController_;if(!sc)return;this.enqueueOperation_(function(){this.filterHits_=[];this.currentHitIndex_=-1;}.bind(this));let stateFromString;try{stateFromString=sc.uiStateFromString(filterText);}catch(e){this.enqueueOperation_(function(){const overlay=new tr.ui.b.Overlay();Polymer.dom(overlay).textContent=e.message;overlay.title='UI State Navigation Error';overlay.visible=true;});return this.activePromise_;}
+if(stateFromString!==undefined){this.enqueueOperation_(sc.navToPosition.bind(this,stateFromString,true));}else{if(filterText.length===0){this.enqueueOperation_(sc.findTextCleared.bind(sc));}else{const filter=new tr.c.FullTextFilter(filterText);const filterHitSet=new tr.model.EventSet();this.enqueueOperation_(sc.addAllEventsMatchingFilterToSelectionAsTask(filter,filterHitSet));this.enqueueOperation_(function(){this.filterHits_=filterHitSet.toArray();sc.findTextChangedTo(filterHitSet);}.bind(this));}}
+return this.activePromise_;},get filterHits(){return this.filterHits_;},get currentHitIndex(){return this.currentHitIndex_;},find_(dir){const firstHit=this.currentHitIndex_===-1;if(firstHit&&dir<0){this.currentHitIndex_=0;}
+const N=this.filterHits.length;this.currentHitIndex_=(this.currentHitIndex_+dir+N)%N;if(!this.brushingStateController_)return;this.brushingStateController_.findFocusChangedTo(new tr.model.EventSet(this.filterHits[this.currentHitIndex]));},findNext(){this.find_(1);},findPrevious(){this.find_(-1);}};return{FindController,};});'use strict';tr.exportTo('tr.ui.b',function(){function TimingTool(viewport,targetElement){this.viewport_=viewport;this.onMouseMove_=this.onMouseMove_.bind(this);this.onDblClick_=this.onDblClick_.bind(this);this.targetElement_=targetElement;this.isMovingLeftEdge_=false;}
+TimingTool.prototype={onEnterTiming(e){this.targetElement_.addEventListener('mousemove',this.onMouseMove_);this.targetElement_.addEventListener('dblclick',this.onDblClick_);},onBeginTiming(e){if(!this.isTouchPointInsideTrackBounds_(e.clientX,e.clientY)){return;}
+const pt=this.getSnappedToEventPosition_(e);this.mouseDownAt_(pt.x,pt.y);this.updateSnapIndicators_(pt);},updateSnapIndicators_(pt){if(!pt.snapped)return;const ir=this.viewport_.interestRange;if(ir.min===pt.x){ir.leftSnapIndicator=new tr.ui.SnapIndicator(pt.y,pt.height);}
+if(ir.max===pt.x){ir.rightSnapIndicator=new tr.ui.SnapIndicator(pt.y,pt.height);}},onUpdateTiming(e){const pt=this.getSnappedToEventPosition_(e);this.mouseMoveAt_(pt.x,pt.y,true);this.updateSnapIndicators_(pt);},onEndTiming(e){this.mouseUp_();},onExitTiming(e){this.targetElement_.removeEventListener('mousemove',this.onMouseMove_);this.targetElement_.removeEventListener('dblclick',this.onDblClick_);},onMouseMove_(e){if(e.button)return;const worldX=this.getWorldXFromEvent_(e);this.mouseMoveAt_(worldX,e.clientY,false);},onDblClick_(e){},isTouchPointInsideTrackBounds_(clientX,clientY){if(!this.viewport_||!this.viewport_.modelTrackContainer||!this.viewport_.modelTrackContainer.canvas){return false;}
+const canvas=this.viewport_.modelTrackContainer.canvas;const canvasRect=canvas.getBoundingClientRect();if(clientX>=canvasRect.left&&clientX<=canvasRect.right&&clientY>=canvasRect.top&&clientY<=canvasRect.bottom){return true;}
+return false;},mouseDownAt_(worldX,y){const ir=this.viewport_.interestRange;const dt=this.viewport_.currentDisplayTransform;const pixelRatio=window.devicePixelRatio||1;const nearnessThresholdWorld=dt.xViewVectorToWorld(6*pixelRatio);if(ir.isEmpty){ir.setMinAndMax(worldX,worldX);ir.rightSelected=true;this.isMovingLeftEdge_=false;return;}
+if(Math.abs(worldX-ir.min)<nearnessThresholdWorld){ir.leftSelected=true;ir.min=worldX;this.isMovingLeftEdge_=true;return;}
+if(Math.abs(worldX-ir.max)<nearnessThresholdWorld){ir.rightSelected=true;ir.max=worldX;this.isMovingLeftEdge_=false;return;}
+ir.setMinAndMax(worldX,worldX);ir.rightSelected=true;this.isMovingLeftEdge_=false;},mouseMoveAt_(worldX,y,mouseDown){if(mouseDown){this.updateMovingEdge_(worldX);return;}
+const ir=this.viewport_.interestRange;const dt=this.viewport_.currentDisplayTransform;const pixelRatio=window.devicePixelRatio||1;const nearnessThresholdWorld=dt.xViewVectorToWorld(6*pixelRatio);if(Math.abs(worldX-ir.min)<nearnessThresholdWorld){ir.leftSelected=true;ir.rightSelected=false;return;}
+if(Math.abs(worldX-ir.max)<nearnessThresholdWorld){ir.leftSelected=false;ir.rightSelected=true;return;}
+ir.leftSelected=false;ir.rightSelected=false;return;},updateMovingEdge_(newWorldX){const ir=this.viewport_.interestRange;let a=ir.min;let b=ir.max;if(this.isMovingLeftEdge_){a=newWorldX;}else{b=newWorldX;}
+if(a<=b){ir.setMinAndMax(a,b);}else{ir.setMinAndMax(b,a);}
+if(ir.min===newWorldX){this.isMovingLeftEdge_=true;ir.leftSelected=true;ir.rightSelected=false;}else{this.isMovingLeftEdge_=false;ir.leftSelected=false;ir.rightSelected=true;}},mouseUp_(){const dt=this.viewport_.currentDisplayTransform;const ir=this.viewport_.interestRange;ir.leftSelected=false;ir.rightSelected=false;const pixelRatio=window.devicePixelRatio||1;const minWidthValue=dt.xViewVectorToWorld(2*pixelRatio);if(ir.range<minWidthValue){ir.reset();}},getWorldXFromEvent_(e){const pixelRatio=window.devicePixelRatio||1;const canvas=this.viewport_.modelTrackContainer.canvas;const worldOffset=canvas.getBoundingClientRect().left;const viewX=(e.clientX-worldOffset)*pixelRatio;return this.viewport_.currentDisplayTransform.xViewToWorld(viewX);},getSnappedToEventPosition_(e){const pixelRatio=window.devicePixelRatio||1;const EVENT_SNAP_RANGE=16*pixelRatio;const modelTrackContainer=this.viewport_.modelTrackContainer;const modelTrackContainerRect=modelTrackContainer.getBoundingClientRect();const viewport=this.viewport_;const dt=viewport.currentDisplayTransform;const worldMaxDist=dt.xViewVectorToWorld(EVENT_SNAP_RANGE);const worldX=this.getWorldXFromEvent_(e);const mouseY=e.clientY;const selection=new tr.model.EventSet();modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,mouseY,mouseY,selection);if(!selection.length){modelTrackContainer.addClosestEventToSelection(worldX,worldMaxDist,modelTrackContainerRect.top,modelTrackContainerRect.bottom,selection);}
+let minDistX=worldMaxDist;let minDistY=Infinity;const pixWidth=dt.xViewVectorToWorld(1);const result={x:worldX,y:mouseY-modelTrackContainerRect.top,height:0,snapped:false};const eventBounds=new tr.b.math.Range();for(const event of selection){const track=viewport.trackForEvent(event);const trackRect=track.getBoundingClientRect();eventBounds.reset();event.addBoundsToRange(eventBounds);let eventX;if(Math.abs(eventBounds.min-worldX)<Math.abs(eventBounds.max-worldX)){eventX=eventBounds.min;}else{eventX=eventBounds.max;}
+const distX=eventX-worldX;const eventY=trackRect.top;const eventHeight=trackRect.height;const distY=Math.abs(eventY+eventHeight/2-mouseY);if((distX<=minDistX||Math.abs(distX-minDistX)<pixWidth)&&distY<minDistY){minDistX=distX;minDistY=distY;result.x=eventX;result.y=eventY+
+modelTrackContainer.scrollTop-modelTrackContainerRect.top;result.height=eventHeight;result.snapped=true;}}
+return result;}};return{TimingTool,};});'use strict';tr.exportTo('tr.ui',function(){const kDefaultPanAnimationDurationMs=100.0;const lerp=tr.b.math.lerp;function TimelineDisplayTransformPanAnimation(deltaX,deltaY,opt_durationMs){this.deltaX=deltaX;this.deltaY=deltaY;if(opt_durationMs===undefined){this.durationMs=kDefaultPanAnimationDurationMs;}else{this.durationMs=opt_durationMs;}
+this.startPanX=undefined;this.startPanY=undefined;this.startTimeMs=undefined;}
+TimelineDisplayTransformPanAnimation.prototype={__proto__:tr.ui.b.Animation.prototype,get affectsPanY(){return this.deltaY!==0;},canTakeOverFor(existingAnimation){return existingAnimation instanceof TimelineDisplayTransformPanAnimation;},takeOverFor(existing,timestamp,target){const remainingDeltaXOnExisting=existing.goalPanX-target.panX;const remainingDeltaYOnExisting=existing.goalPanY-target.panY;let remainingTimeOnExisting=timestamp-(existing.startTimeMs+existing.durationMs);remainingTimeOnExisting=Math.max(remainingTimeOnExisting,0);this.deltaX+=remainingDeltaXOnExisting;this.deltaY+=remainingDeltaYOnExisting;this.durationMs+=remainingTimeOnExisting;},start(timestamp,target){this.startTimeMs=timestamp;this.startPanX=target.panX;this.startPanY=target.panY;},tick(timestamp,target){let percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tr.b.math.clamp(percentDone,0,1);target.panX=lerp(percentDone,this.startPanX,this.goalPanX);if(this.affectsPanY){target.panY=lerp(percentDone,this.startPanY,this.goalPanY);}
+return timestamp>=this.startTimeMs+this.durationMs;},get goalPanX(){return this.startPanX+this.deltaX;},get goalPanY(){return this.startPanY+this.deltaY;}};function TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,goalFocalPointY,zoomInRatioX,opt_durationMs){this.goalFocalPointXWorld=goalFocalPointXWorld;this.goalFocalPointXView=goalFocalPointXView;this.goalFocalPointY=goalFocalPointY;this.zoomInRatioX=zoomInRatioX;if(opt_durationMs===undefined){this.durationMs=kDefaultPanAnimationDurationMs;}else{this.durationMs=opt_durationMs;}
+this.startTimeMs=undefined;this.startScaleX=undefined;this.goalScaleX=undefined;this.startPanY=undefined;}
+TimelineDisplayTransformZoomToAnimation.prototype={__proto__:tr.ui.b.Animation.prototype,get affectsPanY(){return this.startPanY!==this.goalFocalPointY;},canTakeOverFor(existingAnimation){return false;},takeOverFor(existingAnimation,timestamp,target){this.goalScaleX=target.scaleX*this.zoomInRatioX;},start(timestamp,target){this.startTimeMs=timestamp;this.startScaleX=target.scaleX;this.goalScaleX=this.zoomInRatioX*target.scaleX;this.startPanY=target.panY;},tick(timestamp,target){let percentDone=(timestamp-this.startTimeMs)/this.durationMs;percentDone=tr.b.math.clamp(percentDone,0,1);target.scaleX=lerp(percentDone,this.startScaleX,this.goalScaleX);if(this.affectsPanY){target.panY=lerp(percentDone,this.startPanY,this.goalFocalPointY);}
+target.xPanWorldPosToViewPos(this.goalFocalPointXWorld,this.goalFocalPointXView);return timestamp>=this.startTimeMs+this.durationMs;}};return{TimelineDisplayTransformPanAnimation,TimelineDisplayTransformZoomToAnimation,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const DrawType={GENERAL_EVENT:1,INSTANT_EVENT:2,BACKGROUND:3,GRID:4,FLOW_ARROWS:5,MARKERS:6,HIGHLIGHTS:7,ANNOTATIONS:8};const MAX_OVERSIZE_MULTIPLE=3.0;const REDRAW_SLOP=(MAX_OVERSIZE_MULTIPLE-1)/2;const DrawingContainer=tr.ui.b.define('drawing-container',tr.ui.tracks.Track);DrawingContainer.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('drawing-container');this.canvas_=document.createElement('canvas');this.canvas_.className='drawing-container-canvas';this.canvas_.style.left=tr.ui.b.constants.HEADING_WIDTH+'px';Polymer.dom(this).appendChild(this.canvas_);this.ctx_=this.canvas_.getContext('2d');this.offsetY_=0;this.viewportChange_=this.viewportChange_.bind(this);this.viewport.addEventListener('change',this.viewportChange_);window.addEventListener('resize',this.windowResized_.bind(this));this.addEventListener('scroll',this.scrollChanged_.bind(this));},get canvas(){return this.canvas_;},context(){return this.ctx_;},viewportChange_(){this.invalidate();},windowResized_(){this.invalidate();},scrollChanged_(){if(this.updateOffsetY_()){this.invalidate();}},invalidate(){if(this.rafPending_)return;this.rafPending_=true;tr.b.requestPreAnimationFrame(this.preDraw_,this);},preDraw_(){this.rafPending_=false;this.updateCanvasSizeIfNeeded_();tr.b.requestAnimationFrameInThisFrameIfPossible(this.draw_,this);},draw_(){this.ctx_.clearRect(0,0,this.canvas_.width,this.canvas_.height);const typesToDraw=[DrawType.BACKGROUND,DrawType.HIGHLIGHTS,DrawType.GRID,DrawType.INSTANT_EVENT,DrawType.GENERAL_EVENT,DrawType.MARKERS,DrawType.ANNOTATIONS,DrawType.FLOW_ARROWS];const children=this.children;for(const idx in typesToDraw){for(let i=0;i<children.length;++i){if(!(children[i]instanceof tr.ui.tracks.Track)){continue;}
+children[i].drawTrack(typesToDraw[idx]);}}
+const pixelRatio=window.devicePixelRatio||1;const bounds=this.canvas_.getBoundingClientRect();const dt=this.viewport.currentDisplayTransform;const viewLWorld=dt.xViewToWorld(0);const viewRWorld=dt.xViewToWorld(bounds.width*pixelRatio);const viewHeight=bounds.height*pixelRatio;this.viewport.drawGridLines(this.ctx_,viewLWorld,viewRWorld,viewHeight);},updateOffsetY_(){const maxYDelta=window.innerHeight*REDRAW_SLOP;let newOffset=this.scrollTop-maxYDelta;if(Math.abs(newOffset-this.offsetY_)<=maxYDelta)return false;const maxOffset=this.scrollHeight-
+this.canvas_.getBoundingClientRect().height;newOffset=Math.max(0,Math.min(newOffset,maxOffset));if(newOffset!==this.offsetY_){this.offsetY_=newOffset;return true;}
+return false;},updateCanvasSizeIfNeeded_(){const visibleChildTracks=Array.from(this.children).filter(this.visibleFilter_);if(visibleChildTracks.length===0){return;}
+const thisBounds=this.getBoundingClientRect();const firstChildTrackBounds=visibleChildTracks[0].getBoundingClientRect();const lastChildTrackBounds=visibleChildTracks[visibleChildTracks.length-1].getBoundingClientRect();const innerWidth=firstChildTrackBounds.width-
+tr.ui.b.constants.HEADING_WIDTH;const innerHeight=Math.min(lastChildTrackBounds.bottom-firstChildTrackBounds.top,Math.floor(window.innerHeight*MAX_OVERSIZE_MULTIPLE));const pixelRatio=window.devicePixelRatio||1;if(this.canvas_.width!==innerWidth*pixelRatio){this.canvas_.width=innerWidth*pixelRatio;this.canvas_.style.width=innerWidth+'px';}
+if(this.canvas_.height!==innerHeight*pixelRatio){this.canvas_.height=innerHeight*pixelRatio;this.canvas_.style.height=innerHeight+'px';}
+if(this.canvas_.top!==this.offsetY_){this.canvas_.top=this.offsetY_;this.canvas_.style.top=this.offsetY_+'px';}},visibleFilter_(element){if(!(element instanceof tr.ui.tracks.Track))return false;return window.getComputedStyle(element).display!=='none';},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){const children=this.children;for(let i=0;i<children.length;++i){if(!(children[i]instanceof tr.ui.tracks.Track)){continue;}
+const trackClientRect=children[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){children[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
+tr.ui.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);},addEventsToTrackMap(eventToTrackMap){const children=this.children;for(let i=0;i<children.length;++i){if(!(children[i]instanceof tr.ui.tracks.Track)){continue;}
+children[i].addEventsToTrackMap(eventToTrackMap);}}};return{DrawingContainer,DrawType,};});'use strict';tr.exportTo('tr.model',function(){const SelectableItem=tr.model.SelectableItem;const SelectionState=tr.model.SelectionState;function ProxySelectableItem(modelItem){SelectableItem.call(this,modelItem);}
+ProxySelectableItem.prototype={__proto__:SelectableItem.prototype,get selectionState(){const modelItem=this.modelItem_;if(modelItem===undefined){return SelectionState.NONE;}
+return modelItem.selectionState;}};return{ProxySelectableItem,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const EventPresenter=tr.ui.b.EventPresenter;const SelectionState=tr.model.SelectionState;const LetterDotTrack=tr.ui.b.define('letter-dot-track',tr.ui.tracks.Track);LetterDotTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('letter-dot-track');this.items_=undefined;this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},set heading(heading){this.heading_.heading=heading;},get heading(){return this.heading_.heading;},set tooltip(tooltip){this.heading_.tooltip=tooltip;},get items(){return this.items_;},set items(items){this.items_=items;this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;},get dumpRadiusView(){return 7*(window.devicePixelRatio||1);},draw(type,viewLWorld,viewRWorld,viewHeight){if(this.items_===undefined)return;switch(type){case tr.ui.tracks.DrawType.GENERAL_EVENT:this.drawLetterDots_(viewLWorld,viewRWorld);break;}},drawLetterDots_(viewLWorld,viewRWorld){const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const height=bounds.height*pixelRatio;const halfHeight=height*0.5;const twoPi=Math.PI*2;const dt=this.viewport.currentDisplayTransform;const dumpRadiusView=this.dumpRadiusView;const itemRadiusWorld=dt.xViewVectorToWorld(height);const items=this.items_;const loI=tr.b.findLowIndexInSortedArray(items,function(item){return item.start;},viewLWorld);const oldFont=ctx.font;ctx.font='400 '+Math.floor(9*pixelRatio)+'px Arial';ctx.strokeStyle='rgb(0,0,0)';ctx.textBaseline='middle';ctx.textAlign='center';const drawItems=function(selected){for(let i=loI;i<items.length;++i){const item=items[i];const x=item.start;if(x-itemRadiusWorld>viewRWorld)break;if(item.selected!==selected)continue;const xView=dt.xWorldToView(x);ctx.fillStyle=EventPresenter.getSelectableItemColorAsString(item);ctx.beginPath();ctx.arc(xView,halfHeight,dumpRadiusView+0.5,0,twoPi);ctx.fill();if(item.selected){ctx.lineWidth=3;ctx.strokeStyle='rgb(100,100,0)';ctx.stroke();ctx.beginPath();ctx.arc(xView,halfHeight,dumpRadiusView,0,twoPi);ctx.lineWidth=1.5;ctx.strokeStyle='rgb(255,255,0)';ctx.stroke();}else{ctx.lineWidth=1;ctx.strokeStyle='rgb(0,0,0)';ctx.stroke();}
+ctx.fillStyle='rgb(255, 255, 255)';ctx.fillText(item.dotLetter,xView,halfHeight);}};drawItems(false);drawItems(true);ctx.lineWidth=1;ctx.font=oldFont;},addEventsToTrackMap(eventToTrackMap){if(this.items_===undefined)return;this.items_.forEach(function(item){item.addToTrackMap(eventToTrackMap,this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){if(this.items_===undefined)return;const itemRadiusWorld=viewPixWidthWorld*this.dumpRadiusView;tr.b.iterateOverIntersectingIntervals(this.items_,function(x){return x.start-itemRadiusWorld;},function(x){return 2*itemRadiusWorld;},loWX,hiWX,function(item){item.addToSelection(selection);}.bind(this));},addEventNearToProvidedEventToSelection(event,offset,selection){if(this.items_===undefined)return;const index=this.items_.findIndex(item=>item.modelItem===event);if(index===-1)return false;const newIndex=index+offset;if(newIndex>=0&&newIndex<this.items_.length){this.items_[newIndex].addToSelection(selection);return true;}
+return false;},addAllEventsMatchingFilterToSelection(filter,selection){},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){if(this.items_===undefined)return;const item=tr.b.findClosestElementInSortedArray(this.items_,function(x){return x.start;},worldX,worldMaxDist);if(!item)return;item.addToSelection(selection);}};function LetterDot(modelItem,dotLetter,colorId,start){tr.model.ProxySelectableItem.call(this,modelItem);this.dotLetter=dotLetter;this.colorId=colorId;this.start=start;}
+LetterDot.prototype={__proto__:tr.model.ProxySelectableItem.prototype};return{LetterDotTrack,LetterDot,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const AlertTrack=tr.ui.b.define('alert-track',tr.ui.tracks.LetterDotTrack);AlertTrack.prototype={__proto__:tr.ui.tracks.LetterDotTrack.prototype,decorate(viewport){tr.ui.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Alerts';this.alerts_=undefined;},get alerts(){return this.alerts_;},set alerts(alerts){this.alerts_=alerts;if(alerts===undefined){this.items=undefined;return;}
+this.items=this.alerts_.map(function(alert){return new tr.ui.tracks.LetterDot(alert,String.fromCharCode(9888),alert.colorId,alert.start);});}};return{AlertTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const Task=tr.b.Task;const ContainerTrack=tr.ui.b.define('container-track',tr.ui.tracks.Track);ContainerTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);},detach(){Polymer.dom(this).textContent='';},get tracks_(){const tracks=[];const children=this.children;for(let i=0;i<children.length;i++){if(children[i]instanceof tr.ui.tracks.Track){tracks.push(children[i]);}}
+return tracks;},drawTrack(type){this.tracks_.forEach(function(track){track.drawTrack(type);});},addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection){const tracks=this.tracks_;for(let i=0;i<tracks.length;i++){const trackClientRect=tracks[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){tracks[i].addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection);}}
+tr.ui.tracks.Track.prototype.addIntersectingEventsInRangeToSelection.apply(this,arguments);},addEventsToTrackMap(eventToTrackMap){for(const track of this.tracks_){track.addEventsToTrackMap(eventToTrackMap);}},addAllEventsMatchingFilterToSelection(filter,selection){const tracks=this.tracks_;for(let i=0;i<tracks.length;i++){tracks[i].addAllEventsMatchingFilterToSelection(filter,selection);}},addAllEventsMatchingFilterToSelectionAsTask(filter,selection){const task=new Task();const tracks=this.tracks_;for(let i=0;i<tracks.length;i++){task.subTask(function(i){return function(){tracks[i].addAllEventsMatchingFilterToSelection(filter,selection);};}(i),this);}
+return task;},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){const tracks=this.tracks_;for(let i=0;i<tracks.length;i++){const trackClientRect=tracks[i].getBoundingClientRect();const a=Math.max(loY,trackClientRect.top);const b=Math.min(hiY,trackClientRect.bottom);if(a<=b){tracks[i].addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);}}
+tr.ui.tracks.Track.prototype.addClosestEventToSelection.apply(this,arguments);},addContainersToTrackMap(containerToTrackMap){this.tracks_.forEach(function(track){track.addContainersToTrackMap(containerToTrackMap);});},clearTracks_(){this.tracks_.forEach(function(track){Polymer.dom(this).removeChild(track);},this);}};return{ContainerTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){function ChartPoint(modelItem,x,y,opt_yBase){tr.model.ProxySelectableItem.call(this,modelItem);this.x=x;this.y=y;this.dotLetter=undefined;this.yBase=opt_yBase;}
+ChartPoint.prototype={__proto__:tr.model.ProxySelectableItem.prototype,};return{ChartPoint,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const EventPresenter=tr.ui.b.EventPresenter;const SelectionState=tr.model.SelectionState;const ChartSeriesType={LINE:0,AREA:1};const DEFAULT_RENDERING_CONFIG={chartType:ChartSeriesType.LINE,selectedPointSize:4,unselectedPointSize:3,solidSelectedDots:false,colorId:0,lineWidth:1,skipDistance:1,unselectedPointDensityTransparent:0.10,unselectedPointDensityOpaque:0.05,backgroundOpacity:0.5,stepGraph:true};const LAST_POINT_WIDTH=16;const DOT_LETTER_RADIUS_PX=7;const DOT_LETTER_RADIUS_PADDING_PX=0.5;const DOT_LETTER_SELECTED_OUTLINE_WIDTH_PX=3;const DOT_LETTER_SELECTED_OUTLINE_DETAIL_WIDTH_PX=1.5;const DOT_LETTER_UNSELECTED_OUTLINE_WIDTH_PX=1;const DOT_LETTER_FONT_WEIGHT=400;const DOT_LETTER_FONT_SIZE_PX=9;const DOT_LETTER_FONT='Arial';const ChartSeriesComponent={BACKGROUND:0,LINE:1,DOTS:2};function ChartSeries(points,seriesYAxis,opt_renderingConfig){this.points=points;this.seriesYAxis=seriesYAxis;this.useRenderingConfig_(opt_renderingConfig);}
+ChartSeries.prototype={useRenderingConfig_(opt_renderingConfig){const config=opt_renderingConfig||{};for(const[key,defaultValue]of
+Object.entries(DEFAULT_RENDERING_CONFIG)){let value=config[key];if(value===undefined){value=defaultValue;}
+this[key+'_']=value;}
+this.topPadding=this.bottomPadding=Math.max(this.selectedPointSize_,this.unselectedPointSize_)/2;},get range(){const range=new tr.b.math.Range();this.points.forEach(function(point){range.addValue(point.y);},this);return range;},draw(ctx,transform,highDetails){if(this.points===undefined||this.points.length===0){return;}
+if(this.chartType_===ChartSeriesType.AREA){this.drawComponent_(ctx,transform,ChartSeriesComponent.BACKGROUND,highDetails);}
+if(this.chartType_===ChartSeriesType.LINE||highDetails){this.drawComponent_(ctx,transform,ChartSeriesComponent.LINE,highDetails);}
+this.drawComponent_(ctx,transform,ChartSeriesComponent.DOTS,highDetails);},drawComponent_(ctx,transform,component,highDetails){let extraPixels=0;if(component===ChartSeriesComponent.DOTS){extraPixels=Math.max(this.selectedPointSize_,this.unselectedPointSize_);}
+const pixelRatio=transform.pixelRatio;const leftViewX=transform.leftViewX-extraPixels*pixelRatio;const rightViewX=transform.rightViewX+extraPixels*pixelRatio;const leftTimestamp=transform.leftTimestamp-extraPixels;const rightTimestamp=transform.rightTimestamp+extraPixels;const firstVisibleIndex=tr.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},leftTimestamp);let lastVisibleIndex=tr.b.findLowIndexInSortedArray(this.points,function(point){return point.x;},rightTimestamp);if(lastVisibleIndex>=this.points.length||this.points[lastVisibleIndex].x>rightTimestamp){lastVisibleIndex--;}
+const viewSkipDistance=this.skipDistance_*pixelRatio;let selectedCircleRadius;let letterDotRadius;let squareSize;let squareHalfSize;let squareOpacity;let unselectedSeriesColor;let currentStateSeriesColor;ctx.save();ctx.font=DOT_LETTER_FONT_WEIGHT+' '+
+Math.floor(DOT_LETTER_FONT_SIZE_PX*pixelRatio)+'px '+
+DOT_LETTER_FONT;ctx.textBaseline='middle';ctx.textAlign='center';switch(component){case ChartSeriesComponent.DOTS:{selectedCircleRadius=(this.selectedPointSize_/2)*pixelRatio;letterDotRadius=Math.max(selectedCircleRadius,DOT_LETTER_RADIUS_PX*pixelRatio);squareSize=this.unselectedPointSize_*pixelRatio;squareHalfSize=squareSize/2;unselectedSeriesColor=EventPresenter.getCounterSeriesColor(this.colorId_,SelectionState.NONE);if(!highDetails){squareOpacity=0;break;}
+const visibleIndexRange=lastVisibleIndex-firstVisibleIndex;if(visibleIndexRange<=0){squareOpacity=1;break;}
+const visibleViewXRange=transform.worldXToViewX(this.points[lastVisibleIndex].x)-
+transform.worldXToViewX(this.points[firstVisibleIndex].x);if(visibleViewXRange===0){squareOpacity=1;break;}
+const density=visibleIndexRange/visibleViewXRange;const clampedDensity=tr.b.math.clamp(density,this.unselectedPointDensityOpaque_,this.unselectedPointDensityTransparent_);const densityRange=this.unselectedPointDensityTransparent_-
+this.unselectedPointDensityOpaque_;squareOpacity=(this.unselectedPointDensityTransparent_-clampedDensity)/densityRange;break;}
+case ChartSeriesComponent.LINE:ctx.strokeStyle=EventPresenter.getCounterSeriesColor(this.colorId_,SelectionState.NONE);ctx.lineWidth=this.lineWidth_*pixelRatio;break;case ChartSeriesComponent.BACKGROUND:break;default:throw new Error('Invalid component: '+component);}
+let previousViewX=undefined;let previousViewY=undefined;let previousViewYBase=undefined;let lastSelectionState=undefined;let baseSteps=undefined;const startIndex=Math.max(firstVisibleIndex-1,0);let currentViewX;for(let i=startIndex;i<this.points.length;i++){const currentPoint=this.points[i];currentViewX=transform.worldXToViewX(currentPoint.x);if(currentViewX>rightViewX){if(previousViewX!==undefined){previousViewX=currentViewX=rightViewX;if(component===ChartSeriesComponent.BACKGROUND||component===ChartSeriesComponent.LINE){ctx.lineTo(currentViewX,previousViewY);}}
+break;}
+if(i+1<this.points.length){const nextPoint=this.points[i+1];const nextViewX=transform.worldXToViewX(nextPoint.x);if(previousViewX!==undefined&&nextViewX-previousViewX<=viewSkipDistance&&nextViewX<rightViewX){continue;}
+if(currentViewX<leftViewX){currentViewX=leftViewX;}}
+if(previousViewX!==undefined&&currentViewX-previousViewX<viewSkipDistance){currentViewX=previousViewX+viewSkipDistance;}
+const currentViewY=Math.round(transform.worldYToViewY(currentPoint.y));let currentViewYBase;if(currentPoint.yBase===undefined){currentViewYBase=transform.outerBottomViewY;}else{currentViewYBase=Math.round(transform.worldYToViewY(currentPoint.yBase));}
+const currentSelectionState=currentPoint.selectionState;if(currentSelectionState!==lastSelectionState){const opacity=currentSelectionState===SelectionState.SELECTED?1:squareOpacity;currentStateSeriesColor=EventPresenter.getCounterSeriesColor(this.colorId_,currentSelectionState,opacity);}
+switch(component){case ChartSeriesComponent.DOTS:if(currentPoint.dotLetter){ctx.fillStyle=unselectedSeriesColor;ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('black');ctx.beginPath();ctx.arc(currentViewX,currentViewY,letterDotRadius+DOT_LETTER_RADIUS_PADDING_PX,0,2*Math.PI);ctx.fill();if(currentSelectionState===SelectionState.SELECTED){ctx.lineWidth=DOT_LETTER_SELECTED_OUTLINE_WIDTH_PX;ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('olive');ctx.stroke();ctx.beginPath();ctx.arc(currentViewX,currentViewY,letterDotRadius,0,2*Math.PI);ctx.lineWidth=DOT_LETTER_SELECTED_OUTLINE_DETAIL_WIDTH_PX;ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('yellow');ctx.stroke();}else{ctx.lineWidth=DOT_LETTER_UNSELECTED_OUTLINE_WIDTH_PX;ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('black');ctx.stroke();}
+ctx.fillStyle=ColorScheme.getColorForReservedNameAsString('white');ctx.fillText(currentPoint.dotLetter,currentViewX,currentViewY);}else{ctx.strokeStyle=unselectedSeriesColor;ctx.lineWidth=pixelRatio;if(currentSelectionState===SelectionState.SELECTED){if(this.solidSelectedDots_){ctx.fillStyle=ctx.strokeStyle;}else{ctx.fillStyle=currentStateSeriesColor;}
+ctx.beginPath();ctx.arc(currentViewX,currentViewY,selectedCircleRadius,0,2*Math.PI);ctx.fill();ctx.stroke();}else if(squareOpacity>0){ctx.fillStyle=currentStateSeriesColor;ctx.fillRect(currentViewX-squareHalfSize,currentViewY-squareHalfSize,squareSize,squareSize);}}
+break;case ChartSeriesComponent.LINE:if(previousViewX===undefined){ctx.beginPath();ctx.moveTo(currentViewX,currentViewY);}else if(this.stepGraph_){ctx.lineTo(currentViewX,previousViewY);}
+ctx.lineTo(currentViewX,currentViewY);break;case ChartSeriesComponent.BACKGROUND:if(previousViewX!==undefined&&this.stepGraph_){ctx.lineTo(currentViewX,previousViewY);}else{ctx.lineTo(currentViewX,currentViewY);}
+if(currentSelectionState!==lastSelectionState){if(previousViewX!==undefined){let previousBaseStepViewX=currentViewX;for(let j=baseSteps.length-1;j>=0;j--){const baseStep=baseSteps[j];const baseStepViewX=baseStep.viewX;const baseStepViewY=baseStep.viewY;ctx.lineTo(previousBaseStepViewX,baseStepViewY);ctx.lineTo(baseStepViewX,baseStepViewY);previousBaseStepViewX=baseStepViewX;}
+ctx.closePath();ctx.fill();}
+ctx.beginPath();ctx.fillStyle=EventPresenter.getCounterSeriesColor(this.colorId_,currentSelectionState,this.backgroundOpacity_);ctx.moveTo(currentViewX,currentViewYBase);baseSteps=[];}
+if(currentViewYBase!==previousViewYBase||currentSelectionState!==lastSelectionState){baseSteps.push({viewX:currentViewX,viewY:currentViewYBase});}
+ctx.lineTo(currentViewX,currentViewY);break;default:throw new Error('Not reachable');}
+previousViewX=currentViewX;previousViewY=currentViewY;previousViewYBase=currentViewYBase;lastSelectionState=currentSelectionState;}
+if(previousViewX!==undefined){switch(component){case ChartSeriesComponent.DOTS:break;case ChartSeriesComponent.LINE:ctx.stroke();break;case ChartSeriesComponent.BACKGROUND:{let previousBaseStepViewX=currentViewX;for(let j=baseSteps.length-1;j>=0;j--){const baseStep=baseSteps[j];const baseStepViewX=baseStep.viewX;const baseStepViewY=baseStep.viewY;ctx.lineTo(previousBaseStepViewX,baseStepViewY);ctx.lineTo(baseStepViewX,baseStepViewY);previousBaseStepViewX=baseStepViewX;}
+ctx.closePath();ctx.fill();break;}
+default:throw new Error('Not reachable');}}
+ctx.restore();},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){const points=this.points;function getPointWidth(point,i){if(i===points.length-1){return LAST_POINT_WIDTH*viewPixWidthWorld;}
+const nextPoint=points[i+1];return nextPoint.x-point.x;}
+function selectPoint(point){point.addToSelection(selection);}
+tr.b.iterateOverIntersectingIntervals(this.points,function(point){return point.x;},getPointWidth,loWX,hiWX,selectPoint);},addEventNearToProvidedEventToSelection(event,offset,selection){if(this.points===undefined)return false;const index=this.points.findIndex(point=>point.modelItem===event);if(index===-1)return false;const newIndex=index+offset;if(newIndex<0||newIndex>=this.points.length)return false;this.points[newIndex].addToSelection(selection);return true;},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){if(this.points===undefined)return;const item=tr.b.findClosestElementInSortedArray(this.points,function(point){return point.x;},worldX,worldMaxDist);if(!item)return;item.addToSelection(selection);}};return{ChartSeries,ChartSeriesType,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const IDEAL_MAJOR_MARK_HEIGHT_PX=30;const AXIS_LABLE_MARGIN_PX=10;const AXIS_LABLE_FONT_SIZE_PX=9;const AXIS_LABLE_FONT='Arial';function ChartSeriesYAxis(opt_min,opt_max){this.guid_=tr.b.GUID.allocateSimple();this.bounds=new tr.b.math.Range();if(opt_min!==undefined)this.bounds.addValue(opt_min);if(opt_max!==undefined)this.bounds.addValue(opt_max);}
+ChartSeriesYAxis.prototype={get guid(){return this.guid_;},valueToUnitRange(value){if(this.bounds.isEmpty){throw new Error('Chart series y-axis bounds are empty');}
+const bounds=this.bounds;if(bounds.range===0)return 0;return(value-bounds.min)/bounds.range;},unitRangeToValue(unitRange){if(this.bounds.isEmpty){throw new Error('Chart series y-axis bounds are empty');}
+return unitRange*this.bounds.range+this.bounds.min;},autoSetFromSeries(series,opt_config){const range=new tr.b.math.Range();series.forEach(function(s){range.addRange(s.range);},this);this.autoSetFromRange(range,opt_config);},autoSetFromRange(range,opt_config){if(range.isEmpty)return;const bounds=this.bounds;if(bounds.isEmpty){bounds.addRange(range);return;}
+if(!opt_config)return;const useRangeMin=(opt_config.expandMin&&range.min<bounds.min||opt_config.shrinkMin&&range.min>bounds.min);const useRangeMax=(opt_config.expandMax&&range.max>bounds.max||opt_config.shrinkMax&&range.max<bounds.max);if(!useRangeMin&&!useRangeMax)return;if(useRangeMin&&useRangeMax){bounds.min=range.min;bounds.max=range.max;return;}
+if(useRangeMin){bounds.min=Math.min(range.min,bounds.max);}else{bounds.max=Math.max(range.max,bounds.min);}},majorMarkHeightWorld_(transform,pixelRatio){const idealMajorMarkHeightPx=IDEAL_MAJOR_MARK_HEIGHT_PX*pixelRatio;const idealMajorMarkHeightWorld=transform.vectorToWorldDistance(idealMajorMarkHeightPx);return tr.b.math.preferredNumberLargerThanMin(idealMajorMarkHeightWorld);},draw(ctx,transform,showYAxisLabels,showYGridLines){if(!showYAxisLabels&&!showYGridLines)return;const pixelRatio=transform.pixelRatio;const viewTop=transform.outerTopViewY;const worldTop=transform.viewYToWorldY(viewTop);const viewBottom=transform.outerBottomViewY;const viewHeight=viewBottom-viewTop;const viewLeft=transform.leftViewX;const viewRight=transform.rightViewX;const labelLeft=transform.leftYLabel;ctx.save();ctx.lineWidth=pixelRatio;ctx.fillStyle=ColorScheme.getColorForReservedNameAsString('black');ctx.textAlign='left';ctx.textBaseline='center';ctx.font=(AXIS_LABLE_FONT_SIZE_PX*pixelRatio)+'px '+AXIS_LABLE_FONT;ctx.beginPath();ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('black');tr.ui.b.drawLine(ctx,viewLeft,viewTop,viewLeft,viewBottom,viewLeft);ctx.stroke();ctx.closePath();ctx.beginPath();ctx.strokeStyle=ColorScheme.getColorForReservedNameAsString('grey');const majorMarkHeight=this.majorMarkHeightWorld_(transform,pixelRatio);const maxMajorMark=Math.max(transform.viewYToWorldY(viewTop),Math.abs(transform.viewYToWorldY(viewBottom)));for(let curWorldY=0;curWorldY<=maxMajorMark;curWorldY+=majorMarkHeight){const roundedUnitValue=Math.floor(curWorldY*1000000)/1000000;const curViewYPositive=transform.worldYToViewY(curWorldY);if(curViewYPositive>=viewTop){if(showYAxisLabels){ctx.fillText(roundedUnitValue,viewLeft+AXIS_LABLE_MARGIN_PX,curViewYPositive-AXIS_LABLE_MARGIN_PX);}
+if(showYGridLines){tr.ui.b.drawLine(ctx,viewLeft,curViewYPositive,viewRight,curViewYPositive);}}
+const curViewYNegative=transform.worldYToViewY(-1*curWorldY);if(curViewYNegative<=viewBottom){if(showYAxisLabels){ctx.fillText(roundedUnitValue,viewLeft+AXIS_LABLE_MARGIN_PX,curViewYNegative-AXIS_LABLE_MARGIN_PX);}
+if(showYGridLines){tr.ui.b.drawLine(ctx,viewLeft,curViewYNegative,viewRight,curViewYNegative);}}}
+ctx.stroke();ctx.restore();}};return{ChartSeriesYAxis,};});'use strict';tr.exportTo('tr.ui.tracks',function(){function ChartTransform(displayTransform,axis,trackWidth,trackHeight,topPadding,bottomPadding,pixelRatio){this.pixelRatio=pixelRatio;this.leftViewX=0;this.rightViewX=trackWidth;this.leftTimestamp=displayTransform.xViewToWorld(this.leftViewX);this.rightTimestamp=displayTransform.xViewToWorld(this.rightViewX);this.displayTransform_=displayTransform;this.outerTopViewY=0;this.innerTopViewY=topPadding;this.innerBottomViewY=trackHeight-bottomPadding;this.outerBottomViewY=trackHeight;this.axis_=axis;this.innerHeight_=this.innerBottomViewY-this.innerTopViewY;}
+ChartTransform.prototype={worldXToViewX(worldX){return this.displayTransform_.xWorldToView(worldX);},viewXToWorldX(viewX){return this.displayTransform_.xViewToWorld(viewX);},vectorToWorldDistance(viewY){return this.axis_.bounds.range*Math.abs(viewY/this.innerHeight_);},viewYToWorldY(viewY){return this.axis_.unitRangeToValue(1-(viewY-this.innerTopViewY)/this.innerHeight_);},worldYToViewY(worldY){const innerHeightCoefficient=1-this.axis_.valueToUnitRange(worldY);return innerHeightCoefficient*this.innerHeight_+this.innerTopViewY;}};return{ChartTransform,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ChartTrack=tr.ui.b.define('chart-track',tr.ui.tracks.Track);ChartTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('chart-track');this.series_=undefined;this.axes_=undefined;this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;this.showYAxisLabels_=undefined;this.showGridLines_=undefined;this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},set heading(heading){this.heading_.heading=heading;},get heading(){return this.heading_.heading;},set tooltip(tooltip){this.heading_.tooltip=tooltip;},get series(){return this.series_;},set series(series){this.series_=series;this.calculateAxisDataAndPadding_();this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get showYAxisLabels(){return this.showYAxisLabels_;},set showYAxisLabels(showYAxisLabels){this.showYAxisLabels_=showYAxisLabels;this.invalidateDrawingContainer();},get showGridLines(){return this.showGridLines_;},set showGridLines(showGridLines){this.showGridLines_=showGridLines;this.invalidateDrawingContainer();},get hasVisibleContent(){return!!this.series&&this.series.length>0;},calculateAxisDataAndPadding_(){if(!this.series_){this.axes_=undefined;this.axisGuidToAxisData_=undefined;this.topPadding_=undefined;this.bottomPadding_=undefined;return;}
+const axisGuidToAxisData={};let topPadding=0;let bottomPadding=0;this.series_.forEach(function(series){const seriesYAxis=series.seriesYAxis;const axisGuid=seriesYAxis.guid;if(!(axisGuid in axisGuidToAxisData)){axisGuidToAxisData[axisGuid]={axis:seriesYAxis,series:[]};if(!this.axes_)this.axes_=[];this.axes_.push(seriesYAxis);}
+axisGuidToAxisData[axisGuid].series.push(series);topPadding=Math.max(topPadding,series.topPadding);bottomPadding=Math.max(bottomPadding,series.bottomPadding);},this);this.axisGuidToAxisData_=axisGuidToAxisData;this.topPadding_=topPadding;this.bottomPadding_=bottomPadding;},draw(type,viewLWorld,viewRWorld,viewHeight){switch(type){case tr.ui.tracks.DrawType.GENERAL_EVENT:this.drawChart_(viewLWorld,viewRWorld);break;}},drawChart_(viewLWorld,viewRWorld){if(!this.series_)return;const ctx=this.context();const displayTransform=this.viewport.currentDisplayTransform;const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const highDetails=this.viewport.highDetails;const width=bounds.width*pixelRatio;const height=bounds.height*pixelRatio;const topPadding=this.topPadding_*pixelRatio;const bottomPadding=this.bottomPadding_*pixelRatio;ctx.save();ctx.beginPath();ctx.rect(0,0,width,height);ctx.clip();if(this.axes_){if((this.showGridLines_||this.showYAxisLabels_)&&this.axes_.length>1){throw new Error('Only one axis allowed when showing grid lines.');}
+for(const yAxis of this.axes_){const chartTransform=new tr.ui.tracks.ChartTransform(displayTransform,yAxis,width,height,topPadding,bottomPadding,pixelRatio);yAxis.draw(ctx,chartTransform,this.showYAxisLabels_,this.showGridLines_);}}
+for(const series of this.series){const chartTransform=new tr.ui.tracks.ChartTransform(displayTransform,series.seriesYAxis,width,height,topPadding,bottomPadding,pixelRatio);series.draw(ctx,chartTransform,highDetails);}
+ctx.restore();},addEventsToTrackMap(eventToTrackMap){this.series_.forEach(function(series){series.points.forEach(function(point){point.addToTrackMap(eventToTrackMap,this);},this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){this.series_.forEach(function(series){series.addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection);},this);},addEventNearToProvidedEventToSelection(event,offset,selection){let foundItem=false;this.series_.forEach(function(series){foundItem=foundItem||series.addEventNearToProvidedEventToSelection(event,offset,selection);},this);return foundItem;},addAllEventsMatchingFilterToSelection(filter,selection){},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){this.series_.forEach(function(series){series.addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection);},this);},autoSetAllAxes(opt_config){for(const axisData of Object.values(this.axisGuidToAxisData_)){const seriesYAxis=axisData.axis;const series=axisData.series;seriesYAxis.autoSetFromSeries(series,opt_config);}},autoSetAxis(seriesYAxis,opt_config){const series=this.axisGuidToAxisData_[seriesYAxis.guid].series;seriesYAxis.autoSetFromSeries(series,opt_config);}};return{ChartTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const ChartTrack=tr.ui.tracks.ChartTrack;const CpuUsageTrack=tr.ui.b.define('cpu-usage-track',ChartTrack);CpuUsageTrack.prototype={__proto__:ChartTrack.prototype,decorate(viewport){ChartTrack.prototype.decorate.call(this,viewport);this.classList.add('cpu-usage-track');this.heading='CPU usage';this.cpuUsageSeries_=undefined;},initialize(model){if(model!==undefined){this.cpuUsageSeries_=model.device.cpuUsageSeries;}else{this.cpuUsageSeries_=undefined;}
+this.series=this.buildChartSeries_();this.autoSetAllAxes({expandMax:true});},get hasVisibleContent(){return!!this.cpuUsageSeries_&&this.cpuUsageSeries_.samples.length>0;},addContainersToTrackMap(containerToTrackMap){containerToTrackMap.addContainer(this.series_,this);},buildChartSeries_(yAxis,color){if(!this.hasVisibleContent)return[];yAxis=new tr.ui.tracks.ChartSeriesYAxis(0,undefined);const usageSamples=this.cpuUsageSeries_.samples;const pts=new Array(usageSamples.length+1);for(let i=0;i<usageSamples.length;i++){pts[i]=new tr.ui.tracks.ChartPoint(undefined,usageSamples[i].start,usageSamples[i].usage);}
+pts[usageSamples.length]=new tr.ui.tracks.ChartPoint(undefined,usageSamples[usageSamples.length-1].start,0);const renderingConfig={chartType:tr.ui.tracks.ChartSeriesType.AREA,colorId:color};return[new tr.ui.tracks.ChartSeries(pts,yAxis,renderingConfig)];},};return{CpuUsageTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const ChartTrack=tr.ui.tracks.ChartTrack;const PowerSeriesTrack=tr.ui.b.define('power-series-track',ChartTrack);PowerSeriesTrack.prototype={__proto__:ChartTrack.prototype,decorate(viewport){ChartTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('power-series-track');this.heading='Power';this.powerSeries_=undefined;},set powerSeries(powerSeries){this.powerSeries_=powerSeries;this.series=this.buildChartSeries_();this.autoSetAllAxes({expandMax:true});},get hasVisibleContent(){return(this.powerSeries_&&this.powerSeries_.samples.length>0);},addContainersToTrackMap(containerToTrackMap){containerToTrackMap.addContainer(this.powerSeries_,this);},buildChartSeries_(){if(!this.hasVisibleContent)return[];const seriesYAxis=new tr.ui.tracks.ChartSeriesYAxis(0,undefined);const pts=this.powerSeries_.samples.map(function(smpl){return new tr.ui.tracks.ChartPoint(smpl,smpl.start,smpl.powerInW);});const renderingConfig={chartType:tr.ui.tracks.ChartSeriesType.AREA,colorId:ColorScheme.getColorIdForGeneralPurposeString(this.heading)};return[new tr.ui.tracks.ChartSeries(pts,seriesYAxis,renderingConfig)];}};return{PowerSeriesTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SpacingTrack=tr.ui.b.define('spacing-track',tr.ui.tracks.Track);SpacingTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('spacing-track');this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},addAllEventsMatchingFilterToSelection(filter,selection){}};return{SpacingTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ContainerTrack=tr.ui.tracks.ContainerTrack;const DeviceTrack=tr.ui.b.define('device-track',ContainerTrack);DeviceTrack.prototype={__proto__:ContainerTrack.prototype,decorate(viewport){ContainerTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('device-track');this.device_=undefined;this.powerSeriesTrack_=undefined;},get device(){return this.device_;},set device(device){this.device_=device;this.updateContents_();},get powerSeriesTrack(){return this.powerSeriesTrack_;},get hasVisibleContent(){return(this.powerSeriesTrack_&&this.powerSeriesTrack_.hasVisibleContent);},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.ContainerTrack.prototype.addContainersToTrackMap.call(this,containerToTrackMap);containerToTrackMap.addContainer(this.device,this);},addEventsToTrackMap(eventToTrackMap){this.tracks_.forEach(function(track){track.addEventsToTrackMap(eventToTrackMap);});},appendPowerSeriesTrack_(){this.powerSeriesTrack_=new tr.ui.tracks.PowerSeriesTrack(this.viewport);this.powerSeriesTrack_.powerSeries=this.device.powerSeries;if(this.powerSeriesTrack_.hasVisibleContent){Polymer.dom(this).appendChild(this.powerSeriesTrack_);Polymer.dom(this).appendChild(new tr.ui.tracks.SpacingTrack(this.viewport));}},updateContents_(){this.clearTracks_();this.appendPowerSeriesTrack_();}};return{DeviceTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const DISPLAYED_SIZE_NUMERIC_NAME=tr.model.MemoryAllocatorDump.DISPLAYED_SIZE_NUMERIC_NAME;const BACKGROUND=tr.model.ContainerMemoryDump.LevelOfDetail.BACKGROUND;const LIGHT=tr.model.ContainerMemoryDump.LevelOfDetail.LIGHT;const DETAILED=tr.model.ContainerMemoryDump.LevelOfDetail.DETAILED;const SYSTEM_MEMORY_CHART_RENDERING_CONFIG={chartType:tr.ui.tracks.ChartSeriesType.AREA,colorId:ColorScheme.getColorIdForGeneralPurposeString('systemMemory'),backgroundOpacity:0.8};const SYSTEM_MEMORY_SERIES_NAMES=['Used (KB)','Swapped (KB)'];function extractGlobalMemoryDumpUsedSizes(globalMemoryDump,addSize){for(const[pid,pmd]of
+Object.entries(globalMemoryDump.processMemoryDumps)){const mostRecentVmRegions=pmd.mostRecentVmRegions;if(mostRecentVmRegions===undefined)continue;addSize(pid,mostRecentVmRegions.byteStats.proportionalResident||0,pmd.process.userFriendlyName);}}
+function extractProcessMemoryDumpAllocatorSizes(processMemoryDump,addSize){const allocatorDumps=processMemoryDump.memoryAllocatorDumps;if(allocatorDumps===undefined)return;allocatorDumps.forEach(function(allocatorDump){if(allocatorDump.fullName==='tracing')return;const allocatorSize=allocatorDump.numerics[DISPLAYED_SIZE_NUMERIC_NAME];if(allocatorSize===undefined)return;const allocatorSizeValue=allocatorSize.value;if(allocatorSizeValue===undefined)return;addSize(allocatorDump.fullName,allocatorSizeValue);});}
+function extractGlobalMemoryDumpAllocatorSizes(globalMemoryDump,addSize){for(const pmd of Object.values(globalMemoryDump.processMemoryDumps)){extractProcessMemoryDumpAllocatorSizes(pmd,addSize);}}
+function buildMemoryChartSeries(memoryDumps,dumpSizeExtractor){const dumpCount=memoryDumps.length;const idToTimestampToPoint={};const idToName={};memoryDumps.forEach(function(dump,index){dumpSizeExtractor(dump,function addSize(id,size,opt_name){let timestampToPoint=idToTimestampToPoint[id];if(timestampToPoint===undefined){idToTimestampToPoint[id]=timestampToPoint=new Array(dumpCount);for(let i=0;i<dumpCount;i++){const modelItem=memoryDumps[i];timestampToPoint[i]=new tr.ui.tracks.ChartPoint(modelItem,modelItem.start,0);}}
+timestampToPoint[index].y+=size;if(opt_name!==undefined)idToName[id]=opt_name;});});const ids=Object.keys(idToTimestampToPoint);if(ids.length===0)return undefined;ids.sort();for(let i=0;i<dumpCount;i++){let baseSize=0;for(let j=ids.length-1;j>=0;j--){const point=idToTimestampToPoint[ids[j]][i];point.yBase=baseSize;point.y+=baseSize;baseSize=point.y;}}
+const seriesYAxis=new tr.ui.tracks.ChartSeriesYAxis(0);const series=ids.map(function(id){const colorId=ColorScheme.getColorIdForGeneralPurposeString(idToName[id]||id);const renderingConfig={chartType:tr.ui.tracks.ChartSeriesType.AREA,colorId,backgroundOpacity:0.8};return new tr.ui.tracks.ChartSeries(idToTimestampToPoint[id],seriesYAxis,renderingConfig);});series.reverse();return series;}
+function buildMemoryLetterDots(memoryDumps){const backgroundMemoryColorId=ColorScheme.getColorIdForReservedName('background_memory_dump');const lightMemoryColorId=ColorScheme.getColorIdForReservedName('light_memory_dump');const detailedMemoryColorId=ColorScheme.getColorIdForReservedName('detailed_memory_dump');return memoryDumps.map(function(memoryDump){let memoryColorId;switch(memoryDump.levelOfDetail){case BACKGROUND:memoryColorId=backgroundMemoryColorId;break;case DETAILED:memoryColorId=detailedMemoryColorId;break;case LIGHT:default:memoryColorId=lightMemoryColorId;}
+return new tr.ui.tracks.LetterDot(memoryDump,'M',memoryColorId,memoryDump.start);});}
+function buildGlobalUsedMemoryChartSeries(globalMemoryDumps){return buildMemoryChartSeries(globalMemoryDumps,extractGlobalMemoryDumpUsedSizes);}
+function buildProcessAllocatedMemoryChartSeries(processMemoryDumps){return buildMemoryChartSeries(processMemoryDumps,extractProcessMemoryDumpAllocatorSizes);}
+function buildGlobalAllocatedMemoryChartSeries(globalMemoryDumps){return buildMemoryChartSeries(globalMemoryDumps,extractGlobalMemoryDumpAllocatorSizes);}
+function buildSystemMemoryChartSeries(model){if(model.kernel.counters===undefined)return;const memoryCounter=model.kernel.counters['global.SystemMemory'];if(memoryCounter===undefined)return;const tracks=[];for(const name of SYSTEM_MEMORY_SERIES_NAMES){const series=memoryCounter.series.find(series=>series.name===name);if(series===undefined||series.samples.length===0)return;const chartPoints=[];const valueRange=new tr.b.math.Range();for(const sample of series.samples){chartPoints.push(new tr.ui.tracks.ChartPoint(sample,sample.timestamp,sample.value,0));valueRange.addValue(sample.value);}
+const baseLine=Math.max(0,valueRange.min-valueRange.range);const axisY=new tr.ui.tracks.ChartSeriesYAxis(baseLine,valueRange.max);const chartSeries=[new tr.ui.tracks.ChartSeries(chartPoints,axisY,SYSTEM_MEMORY_CHART_RENDERING_CONFIG)];tracks.push({name:'System Memory '+name,series:chartSeries});}
+return tracks;}
+return{buildMemoryLetterDots,buildGlobalUsedMemoryChartSeries,buildProcessAllocatedMemoryChartSeries,buildGlobalAllocatedMemoryChartSeries,buildSystemMemoryChartSeries,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const USED_MEMORY_TRACK_HEIGHT=50;const ALLOCATED_MEMORY_TRACK_HEIGHT=50;const GlobalMemoryDumpTrack=tr.ui.b.define('global-memory-dump-track',tr.ui.tracks.ContainerTrack);GlobalMemoryDumpTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_(){this.clearTracks_();if(!this.memoryDumps_||!this.memoryDumps_.length)return;this.appendDumpDotsTrack_();this.appendUsedMemoryTrack_();this.appendAllocatedMemoryTrack_();},appendDumpDotsTrack_(){const items=tr.ui.tracks.buildMemoryLetterDots(this.memoryDumps_);if(!items)return;const track=new tr.ui.tracks.LetterDotTrack(this.viewport);track.heading='Memory Dumps';track.items=items;Polymer.dom(this).appendChild(track);},appendUsedMemoryTrack_(){const tracks=[];const perProcessSeries=tr.ui.tracks.buildGlobalUsedMemoryChartSeries(this.memoryDumps_);if(perProcessSeries!==undefined){tracks.push({name:'Memory per process',series:perProcessSeries});}else{tracks.push.apply(tracks,tr.ui.tracks.buildSystemMemoryChartSeries(this.memoryDumps_[0].model));}
+for(const{name,series}of tracks){const track=new tr.ui.tracks.ChartTrack(this.viewport);track.heading=name;track.height=USED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});Polymer.dom(this).appendChild(track);}},appendAllocatedMemoryTrack_(){const series=tr.ui.tracks.buildGlobalAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)return;const track=new tr.ui.tracks.ChartTrack(this.viewport);track.heading='Memory per component';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});Polymer.dom(this).appendChild(track);}};return{GlobalMemoryDumpTrack,};});'use strict';tr.exportTo('tr.ui.b',function(){function FastRectRenderer(ctx,xMin,xMax,minRectSize,maxMergeDist,palette){this.ctx_=ctx;this.xMin_=xMin;this.xMax_=xMax;this.minRectSize_=minRectSize;this.maxMergeDist_=maxMergeDist;this.palette_=palette;}
+FastRectRenderer.prototype={y_:0,h_:0,merging_:false,mergeStartX_:0,mergeCurRight_:0,mergedColorId_:0,mergedAlpha_:0,setYandH(y,h){if(this.y_===y&&this.h_===h){return;}
+this.flush();this.y_=y;this.h_=h;},fillRect(x,w,colorId,alpha){const r=x+w;if(w<this.minRectSize_){if(r-this.mergeStartX_>this.maxMergeDist_){this.flush();}
+if(!this.merging_){this.merging_=true;this.mergeStartX_=x;this.mergeCurRight_=r;this.mergedColorId_=colorId;this.mergedAlpha_=alpha;}else{this.mergeCurRight_=r;if(this.mergedAlpha_<alpha||(this.mergedAlpha_===alpha&&this.mergedColorId_<colorId)){this.mergedAlpha_=alpha;this.mergedColorId_=colorId;}}}else{if(this.merging_){this.flush();}
+this.ctx_.fillStyle=this.palette_[colorId];this.ctx_.globalAlpha=alpha;const xLeft=Math.max(x,this.xMin_);const xRight=Math.min(r,this.xMax_);if(xLeft<xRight){this.ctx_.fillRect(xLeft,this.y_,xRight-xLeft,this.h_);}}},flush(){if(this.merging_){this.ctx_.fillStyle=this.palette_[this.mergedColorId_];this.ctx_.globalAlpha=this.mergedAlpha_;const xLeft=Math.max(this.mergeStartX_,this.xMin_);const xRight=Math.min(this.mergeCurRight_,this.xMax_);if(xLeft<xRight){this.ctx_.fillRect(xLeft,this.y_,xRight-xLeft,this.h_);}
+this.merging_=false;}}};return{FastRectRenderer,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const RectTrack=tr.ui.b.define('rect-track',tr.ui.tracks.Track);RectTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('rect-track');this.asyncStyle_=false;this.rects_=null;this.heading_=document.createElement('tr-ui-b-heading');Polymer.dom(this).appendChild(this.heading_);},set heading(heading){this.heading_.heading=heading;},get heading(){return this.heading_.heading;},set tooltip(tooltip){this.heading_.tooltip=tooltip;},set selectionGenerator(generator){this.heading_.selectionGenerator=generator;},set expanded(expanded){this.heading_.expanded=!!expanded;},set arrowVisible(arrowVisible){this.heading_.arrowVisible=!!arrowVisible;},get expanded(){return this.heading_.expanded;},get asyncStyle(){return this.asyncStyle_;},set asyncStyle(v){this.asyncStyle_=!!v;},get rects(){return this.rects_;},set rects(rects){this.rects_=rects||[];this.invalidateDrawingContainer();},get height(){return window.getComputedStyle(this).height;},set height(height){this.style.height=height;this.invalidateDrawingContainer();},get hasVisibleContent(){return this.rects_.length>0;},draw(type,viewLWorld,viewRWorld,viewHeight){switch(type){case tr.ui.tracks.DrawType.GENERAL_EVENT:this.drawRects_(viewLWorld,viewRWorld);break;}},drawRects_(viewLWorld,viewRWorld){const ctx=this.context();ctx.save();const bounds=this.getBoundingClientRect();tr.ui.b.drawSlices(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.rects_,this.asyncStyle_);ctx.restore();if(bounds.height<=6)return;let fontSize;let yOffset;if(bounds.height<15){fontSize=6;yOffset=1.0;}else{fontSize=10;yOffset=2.5;}
+tr.ui.b.drawLabels(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,this.rects_,this.asyncStyle_,fontSize,yOffset);},addEventsToTrackMap(eventToTrackMap){if(this.rects_===undefined||this.rects_===null){return;}
+this.rects_.forEach(function(rect){rect.addToTrackMap(eventToTrackMap,this);},this);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){function onRect(rect){rect.addToSelection(selection);}
+onRect=onRect.bind(this);const instantEventWidth=2*viewPixWidthWorld;tr.b.iterateOverIntersectingIntervals(this.rects_,function(x){return x.start;},function(x){return x.duration===0?x.duration+instantEventWidth:x.duration;},loWX,hiWX,onRect);},addEventNearToProvidedEventToSelection(event,offset,selection){const index=this.rects_.findIndex(rect=>rect.modelItem===event);if(index===-1)return false;const newIndex=index+offset;if(newIndex<0||newIndex>=this.rects_.length)return false;this.rects_[newIndex].addToSelection(selection);return true;},addAllEventsMatchingFilterToSelection(filter,selection){for(let i=0;i<this.rects_.length;++i){const modelItem=this.rects_[i].modelItem;if(!modelItem)continue;if(filter.matchSlice(modelItem)){selection.push(modelItem);}}},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){const rect=tr.b.findClosestIntervalInSortedIntervals(this.rects_,function(x){return x.start;},function(x){return x.end;},worldX,worldMaxDist);if(!rect)return;rect.addToSelection(selection);}};function Rect(modelItem,title,colorId,start,duration){tr.model.ProxySelectableItem.call(this,modelItem);this.title=title;this.colorId=colorId;this.start=start;this.duration=duration;this.end=start+duration;}
+Rect.prototype={__proto__:tr.model.ProxySelectableItem.prototype};return{RectTrack,Rect,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SliceTrack=tr.ui.b.define('slice-track',tr.ui.tracks.RectTrack);SliceTrack.prototype={__proto__:tr.ui.tracks.RectTrack.prototype,decorate(viewport){tr.ui.tracks.RectTrack.prototype.decorate.call(this,viewport);},get slices(){return this.rects;},set slices(slices){this.rects=slices;}};return{SliceTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const CpuTrack=tr.ui.b.define('cpu-track',tr.ui.tracks.ContainerTrack);CpuTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('cpu-track');this.detailedMode_=true;},get cpu(){return this.cpu_;},set cpu(cpu){this.cpu_=cpu;this.updateContents_();},get detailedMode(){return this.detailedMode_;},set detailedMode(detailedMode){this.detailedMode_=detailedMode;this.updateContents_();},get tooltip(){return this.tooltip_;},set tooltip(value){this.tooltip_=value;this.updateContents_();},get hasVisibleContent(){if(this.cpu_===undefined)return false;const cpu=this.cpu_;if(cpu.slices.length)return true;if(cpu.samples&&cpu.samples.length)return true;if(Object.keys(cpu.counters).length>0)return true;return false;},updateContents_(){this.detach();if(!this.cpu_)return;const slices=this.cpu_.slices;if(slices.length){const track=new tr.ui.tracks.SliceTrack(this.viewport);track.slices=slices;track.heading=this.cpu_.userFriendlyName+':';Polymer.dom(this).appendChild(track);}
+if(this.detailedMode_){this.appendSamplesTracks_();for(const counterName in this.cpu_.counters){const counter=this.cpu_.counters[counterName];const track=new tr.ui.tracks.CounterTrack(this.viewport);track.heading=this.cpu_.userFriendlyName+' '+
+counter.name+':';track.counter=counter;Polymer.dom(this).appendChild(track);}}},appendSamplesTracks_(){const samples=this.cpu_.samples;if(samples===undefined||samples.length===0){return;}
+const samplesByTitle={};samples.forEach(function(sample){if(samplesByTitle[sample.title]===undefined){samplesByTitle[sample.title]=[];}
+samplesByTitle[sample.title].push(sample);});const sampleTitles=Object.keys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){const samples=samplesByTitle[sampleTitle];const samplesTrack=new tr.ui.tracks.SliceTrack(this.viewport);samplesTrack.group=this.cpu_;samplesTrack.slices=samples;samplesTrack.heading=this.cpu_.userFriendlyName+': '+
+sampleTitle;samplesTrack.tooltip=this.cpu_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){const selection=new tr.model.EventSet();for(let i=0;i<samplesTrack.slices.length;i++){selection.push(samplesTrack.slices[i]);}
+return selection;};Polymer.dom(this).appendChild(samplesTrack);},this);}};return{CpuTrack,};});'use strict';tr.exportTo('tr.model',function(){const Settings=tr.b.Settings;function ModelSettings(model){this.model=model;this.objectsByKey_=[];this.nonuniqueKeys_=[];this.buildObjectsByKeyMap_();this.removeNonuniqueKeysFromSettings_();this.ephemeralSettingsByGUID_={};}
+ModelSettings.prototype={buildObjectsByKeyMap_(){const objects=[];this.model.iterateAllPersistableObjects(function(o){objects.push(o);});const objectsByKey={};const NONUNIQUE_KEY='nonuniqueKey';for(let i=0;i<objects.length;i++){const object=objects[i];const objectKey=object.getSettingsKey();if(!objectKey)continue;if(objectsByKey[objectKey]===undefined){objectsByKey[objectKey]=object;continue;}
+objectsByKey[objectKey]=NONUNIQUE_KEY;}
+const nonuniqueKeys={};Object.keys(objectsByKey).forEach(function(objectKey){if(objectsByKey[objectKey]!==NONUNIQUE_KEY){return;}
+delete objectsByKey[objectKey];nonuniqueKeys[objectKey]=true;});this.nonuniqueKeys=nonuniqueKeys;this.objectsByKey_=objectsByKey;},removeNonuniqueKeysFromSettings_(){const settings=Settings.get('trace_model_settings',{});let settingsChanged=false;Object.keys(settings).forEach(function(objectKey){if(!this.nonuniqueKeys[objectKey]){return;}
+settingsChanged=true;delete settings[objectKey];},this);if(settingsChanged){Settings.set('trace_model_settings',settings);}},hasUniqueSettingKey(object){const objectKey=object.getSettingsKey();if(!objectKey)return false;return this.objectsByKey_[objectKey]!==undefined;},getSettingFor(object,objectLevelKey,defaultValue){const objectKey=object.getSettingsKey();if(!objectKey||!this.objectsByKey_[objectKey]){const settings=this.getEphemeralSettingsFor_(object);const ephemeralValue=settings[objectLevelKey];if(ephemeralValue!==undefined){return ephemeralValue;}
+return defaultValue;}
+const settings=Settings.get('trace_model_settings',{});if(!settings[objectKey]){settings[objectKey]={};}
+const value=settings[objectKey][objectLevelKey];if(value!==undefined){return value;}
+return defaultValue;},setSettingFor(object,objectLevelKey,value){const objectKey=object.getSettingsKey();if(!objectKey||!this.objectsByKey_[objectKey]){this.getEphemeralSettingsFor_(object)[objectLevelKey]=value;return;}
+const settings=Settings.get('trace_model_settings',{});if(!settings[objectKey]){settings[objectKey]={};}
+if(settings[objectKey][objectLevelKey]===value){return;}
+settings[objectKey][objectLevelKey]=value;Settings.set('trace_model_settings',settings);},getEphemeralSettingsFor_(object){if(object.guid===undefined){throw new Error('Only objects with GUIDs can be persisted');}
+if(this.ephemeralSettingsByGUID_[object.guid]===undefined){this.ephemeralSettingsByGUID_[object.guid]={};}
+return this.ephemeralSettingsByGUID_[object.guid];}};return{ModelSettings,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const CounterTrack=tr.ui.b.define('counter-track',tr.ui.tracks.ChartTrack);CounterTrack.prototype={__proto__:tr.ui.tracks.ChartTrack.prototype,decorate(viewport){tr.ui.tracks.ChartTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('counter-track');},get counter(){return this.chart;},set counter(counter){this.heading=counter.name+': ';this.series=CounterTrack.buildChartSeriesFromCounter(counter);this.autoSetAllAxes({expandMax:true});},getModelEventFromItem(chartValue){return chartValue;}};CounterTrack.buildChartSeriesFromCounter=function(counter){const numSeries=counter.series.length;const totals=counter.totals;const seriesYAxis=new tr.ui.tracks.ChartSeriesYAxis(0,undefined);const chartSeries=counter.series.map(function(series,seriesIndex){const chartPoints=series.samples.map(function(sample,sampleIndex){const total=totals[sampleIndex*numSeries+seriesIndex];return new tr.ui.tracks.ChartPoint(sample,sample.timestamp,total);});const renderingConfig={chartType:tr.ui.tracks.ChartSeriesType.AREA,colorId:series.color};return new tr.ui.tracks.ChartSeries(chartPoints,seriesYAxis,renderingConfig);});chartSeries.reverse();return chartSeries;};return{CounterTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const startCompare=function(x,y){return x.start-y.start;};const FrameTrack=tr.ui.b.define('frame-track',tr.ui.tracks.LetterDotTrack);FrameTrack.prototype={__proto__:tr.ui.tracks.LetterDotTrack.prototype,decorate(viewport){tr.ui.tracks.LetterDotTrack.prototype.decorate.call(this,viewport);this.heading='Frames';this.frames_=undefined;this.items=undefined;},get frames(){return this.frames_;},set frames(frames){this.frames_=frames;if(frames===undefined)return;this.frames_=this.frames_.slice();this.frames_.sort(startCompare);this.items=this.frames_.map(function(frame){return new FrameDot(frame);});}};function FrameDot(frame){tr.ui.tracks.LetterDot.call(this,frame,'F',frame.colorId,frame.start);}
+FrameDot.prototype={__proto__:tr.ui.tracks.LetterDot.prototype};return{FrameTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const MultiRowTrack=tr.ui.b.define('multi-row-track',tr.ui.tracks.ContainerTrack);MultiRowTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.tooltip_='';this.heading_='';this.groupingSource_=undefined;this.itemsToGroup_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=1;this.currentSubRowsWithHeadings_=undefined;this.expanded_=true;},get itemsToGroup(){return this.itemsToGroup_;},setItemsToGroup(itemsToGroup,opt_groupingSource){this.itemsToGroup_=itemsToGroup;this.groupingSource_=opt_groupingSource;this.currentSubRowsWithHeadings_=undefined;this.updateContents_();this.updateExpandedStateFromGroupingSource_();},setPrebuiltSubRows(groupingSource,subRowsWithHeadings){this.itemsToGroup_=undefined;this.groupingSource_=groupingSource;this.currentSubRowsWithHeadings_=subRowsWithHeadings;this.updateContents_();this.updateExpandedStateFromGroupingSource_();},get heading(){return this.heading_;},set heading(h){this.heading_=h;this.updateHeadingAndTooltip_();},get tooltip(){return this.tooltip_;},set tooltip(t){this.tooltip_=t;this.updateHeadingAndTooltip_();},get subRows(){return this.currentSubRowsWithHeadings_.map(elem=>elem.row);},get hasVisibleContent(){return this.children.length>0;},get expanded(){return this.expanded_;},set expanded(expanded){if(this.expanded_===expanded)return;this.expanded_=expanded;this.expandedStateChanged_();},onHeadingClicked_(e){if(this.subRows.length<=1)return;this.expanded=!this.expanded;if(this.groupingSource_){const modelSettings=new tr.model.ModelSettings(this.groupingSource_.model);modelSettings.setSettingFor(this.groupingSource_,'expanded',this.expanded);}
+e.stopPropagation();},updateExpandedStateFromGroupingSource_(){if(this.groupingSource_){const numSubRows=this.subRows.length;const modelSettings=new tr.model.ModelSettings(this.groupingSource_.model);if(numSubRows>1){let defaultExpanded;if(numSubRows>this.defaultToCollapsedWhenSubRowCountMoreThan){defaultExpanded=false;}else{defaultExpanded=true;}
+this.expanded=modelSettings.getSettingFor(this.groupingSource_,'expanded',defaultExpanded);}else{this.expanded=undefined;}}},expandedStateChanged_(){const children=this.children;const minH=Math.max(2,Math.ceil(18/children.length));const h=(this.expanded_?18:minH)+'px';for(let i=0;i<children.length;i++){children[i].height=h;if(i===0){children[i].arrowVisible=true;}
+children[i].expanded=this.expanded;}
+if(children.length===1){children[0].expanded=true;children[0].arrowVisible=false;}},updateContents_(){tr.ui.tracks.ContainerTrack.prototype.updateContents_.call(this);this.detach();if(this.currentSubRowsWithHeadings_===undefined){if(this.itemsToGroup_===undefined){return;}
+const subRows=this.buildSubRows_(this.itemsToGroup_);this.currentSubRowsWithHeadings_=subRows.map(row=>{return{row,heading:undefined};});}
+if(this.currentSubRowsWithHeadings_===undefined||this.currentSubRowsWithHeadings_.length===0){return;}
+const addSubTrackEx=(items,opt_heading)=>{const track=this.addSubTrack_(items);if(opt_heading!==undefined){track.heading=opt_heading;}
+track.addEventListener('heading-clicked',this.onHeadingClicked_.bind(this));};if(this.currentSubRowsWithHeadings_[0].heading!==undefined&&this.currentSubRowsWithHeadings_[0].heading!==this.heading_){addSubTrackEx([]);}
+for(const subRowWithHeading of this.currentSubRowsWithHeadings_){const subRow=subRowWithHeading.row;if(subRow.length===0){continue;}
+addSubTrackEx(subRow,subRowWithHeading.heading);}
+this.updateHeadingAndTooltip_();this.expandedStateChanged_();},updateHeadingAndTooltip_(){if(!Polymer.dom(this).firstChild)return;Polymer.dom(this).firstChild.heading=this.heading_;Polymer.dom(this).firstChild.tooltip=this.tooltip_;},buildSubRows_(itemsToGroup){throw new Error('Not implemented');},addSubTrack_(subRowItems){throw new Error('Not implemented');},areArrayContentsSame_(a,b){if(!a||!b)return false;if(!a.length||!b.length)return false;if(a.length!==b.length)return false;for(let i=0;i<a.length;++i){if(a[i]!==b[i])return false;}
+return true;}};return{MultiRowTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ObjectInstanceGroupTrack=tr.ui.b.define('object-instance-group-track',tr.ui.tracks.MultiRowTrack);ObjectInstanceGroupTrack.prototype={__proto__:tr.ui.tracks.MultiRowTrack.prototype,decorate(viewport){tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('object-instance-group-track');this.objectInstances_=undefined;},get objectInstances(){return this.itemsToGroup;},set objectInstances(objectInstances){this.setItemsToGroup(objectInstances);},addSubTrack_(objectInstances){const hasMultipleRows=this.subRows.length>1;const track=new tr.ui.tracks.ObjectInstanceTrack(this.viewport);track.objectInstances=objectInstances;Polymer.dom(this).appendChild(track);return track;},buildSubRows_(objectInstances){objectInstances.sort(function(x,y){return x.creationTs-y.creationTs;});const subRows=[];for(let i=0;i<objectInstances.length;i++){const objectInstance=objectInstances[i];let found=false;for(let j=0;j<subRows.length;j++){const subRow=subRows[j];const lastItemInSubRow=subRow[subRow.length-1];if(objectInstance.creationTs>=lastItemInSubRow.deletionTs){found=true;subRow.push(objectInstance);break;}}
+if(!found){subRows.push([objectInstance]);}}
+return subRows;},updateHeadingAndTooltip_(){}};return{ObjectInstanceGroupTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const AsyncSliceGroupTrack=tr.ui.b.define('async-slice-group-track',tr.ui.tracks.MultiRowTrack);AsyncSliceGroupTrack.prototype={__proto__:tr.ui.tracks.MultiRowTrack.prototype,decorate(viewport){tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('async-slice-group-track');this.group_=undefined;},addSubTrack_(slices){const track=new tr.ui.tracks.SliceTrack(this.viewport);track.slices=slices;Polymer.dom(this).appendChild(track);track.asyncStyle=true;return track;},get group(){return this.group_;},set group(group){this.group_=group;this.buildAndSetSubRows_();},get eventContainer(){return this.group;},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply(this,arguments);containerToTrackMap.addContainer(this.group,this);},buildAndSetSubRows_(){if(this.group_.viewSubGroups.length<=1){const rows=groupAsyncSlicesIntoSubRows(this.group_.slices);const rowsWithHeadings=rows.map(row=>{return{row,heading:undefined};});this.setPrebuiltSubRows(this.group_,rowsWithHeadings);return;}
+const rowsWithHeadings=[];for(const subGroup of this.group_.viewSubGroups){const subGroupRows=groupAsyncSlicesIntoSubRows(subGroup.slices);if(subGroupRows.length===0){continue;}
+for(let i=0;i<subGroupRows.length;i++){rowsWithHeadings.push({row:subGroupRows[i],heading:(i===0?subGroup.title:'')});}}
+this.setPrebuiltSubRows(this.group_,rowsWithHeadings);}};function stripSlice_(slice){if(slice.subSlices!==undefined&&slice.subSlices.length===1){const subSlice=slice.subSlices[0];if(tr.b.math.approximately(subSlice.start,slice.start,1)&&tr.b.math.approximately(subSlice.duration,slice.duration,1)){return subSlice;}}
+return slice;}
+function makeLevelSubRows_(slices){const rows=[];const putSlice=(slice,level)=>{while(rows.length<=level){rows.push([]);}
+rows[level].push(slice);};const putSliceRecursively=(slice,level)=>{putSlice(slice,level);if(slice.subSlices!==undefined){for(const subSlice of slice.subSlices){putSliceRecursively(subSlice,level+1);}}};for(const slice of slices){putSliceRecursively(stripSlice_(slice),0);}
+return rows;}
+function groupAsyncSlicesIntoSubRows(slices,opt_skipSort){if(!opt_skipSort){slices.sort((x,y)=>x.start-y.start);}
+const rows=[];let slicesLeft=slices;while(slicesLeft.length!==0){const fit=[];const unfit=[];let levelEndTime=-1;for(const slice of slicesLeft){if(slice.start>=levelEndTime){levelEndTime=slice.end;fit.push(slice);}else{unfit.push(slice);}}
+rows.push(...makeLevelSubRows_(fit));slicesLeft=unfit;}
+return rows;}
+return{AsyncSliceGroupTrack,groupAsyncSlicesIntoSubRows,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SampleTrack=tr.ui.b.define('sample-track',tr.ui.tracks.RectTrack);SampleTrack.prototype={__proto__:tr.ui.tracks.RectTrack.prototype,decorate(viewport){tr.ui.tracks.RectTrack.prototype.decorate.call(this,viewport);},get samples(){return this.rects;},set samples(samples){this.rects=samples;}};return{SampleTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SliceGroupTrack=tr.ui.b.define('slice-group-track',tr.ui.tracks.MultiRowTrack);SliceGroupTrack.prototype={__proto__:tr.ui.tracks.MultiRowTrack.prototype,decorate(viewport){tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('slice-group-track');this.group_=undefined;this.defaultToCollapsedWhenSubRowCountMoreThan=100;},addSubTrack_(slices){const track=new tr.ui.tracks.SliceTrack(this.viewport);track.slices=slices;Polymer.dom(this).appendChild(track);return track;},get group(){return this.group_;},set group(group){this.group_=group;this.setItemsToGroup(this.group_.slices,this.group_);},get eventContainer(){return this.group;},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply(this,arguments);containerToTrackMap.addContainer(this.group,this);},buildSubRows_(slices){const precisionUnit=this.group.model.intrinsicTimeUnit;if(!slices.length)return[];const ops=[];for(let i=0;i<slices.length;i++){if(slices[i].subSlices){slices[i].subSlices.splice(0,slices[i].subSlices.length);}
+ops.push(i);}
+ops.sort(function(ix,iy){const x=slices[ix];const y=slices[iy];if(x.start!==y.start)return x.start-y.start;return ix-iy;});const subRows=[[]];this.badSlices_=[];for(let i=0;i<ops.length;i++){const op=ops[i];const slice=slices[op];let inserted=false;for(let j=subRows.length-1;j>=0;j--){if(subRows[j].length===0)continue;const insertedSlice=subRows[j][subRows[j].length-1];if(slice.start<insertedSlice.start){this.badSlices_.push(slice);inserted=true;}
+if(insertedSlice.bounds(slice,precisionUnit)){while(subRows.length<=j+1){subRows.push([]);}
+subRows[j+1].push(slice);if(insertedSlice.subSlices){insertedSlice.subSlices.push(slice);}
+inserted=true;break;}}
+if(inserted)continue;subRows[0].push(slice);}
+return subRows;}};return{SliceGroupTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ThreadTrack=tr.ui.b.define('thread-track',tr.ui.tracks.ContainerTrack);ThreadTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('thread-track');this.heading_=document.createElement('tr-ui-b-heading');},get thread(){return this.thread_;},set thread(thread){this.thread_=thread;this.updateContents_();},get hasVisibleContent(){return this.tracks_.length>0;},get hasSlices(){return this.thread_.asyncSliceGroup.length>0||this.thread_.sliceGroup.length>0;},get hasTimeSlices(){return this.thread_.timeSlices;},get eventContainer(){return this.thread;},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.ContainerTrack.prototype.addContainersToTrackMap.apply(this,arguments);containerToTrackMap.addContainer(this.thread,this);},updateContents_(){this.detach();if(!this.thread_)return;this.heading_.heading=this.thread_.userFriendlyName;this.heading_.tooltip=this.thread_.userFriendlyDetails;if(this.thread_.asyncSliceGroup.length){this.appendAsyncSliceTracks_();}
+this.appendThreadSamplesTracks_();let needsHeading=false;if(this.thread_.timeSlices){const timeSlicesTrack=new tr.ui.tracks.SliceTrack(this.viewport);timeSlicesTrack.heading='';timeSlicesTrack.height=tr.ui.b.THIN_SLICE_HEIGHT+'px';timeSlicesTrack.slices=this.thread_.timeSlices;if(timeSlicesTrack.hasVisibleContent){needsHeading=true;Polymer.dom(this).appendChild(timeSlicesTrack);}}
+if(this.thread_.sliceGroup.length){const track=new tr.ui.tracks.SliceGroupTrack(this.viewport);track.heading=this.thread_.userFriendlyName;track.tooltip=this.thread_.userFriendlyDetails;track.group=this.thread_.sliceGroup;if(track.hasVisibleContent){needsHeading=false;Polymer.dom(this).appendChild(track);}}
+if(needsHeading){Polymer.dom(this).appendChild(this.heading_);}},appendAsyncSliceTracks_(){const subGroups=this.thread_.asyncSliceGroup.viewSubGroups;subGroups.forEach(function(subGroup){const asyncTrack=new tr.ui.tracks.AsyncSliceGroupTrack(this.viewport);asyncTrack.group=subGroup;asyncTrack.heading=subGroup.title;if(asyncTrack.hasVisibleContent){Polymer.dom(this).appendChild(asyncTrack);}},this);},appendThreadSamplesTracks_(){const threadSamples=this.thread_.samples;if(threadSamples===undefined||threadSamples.length===0){return;}
+const samplesByTitle={};threadSamples.forEach(function(sample){if(samplesByTitle[sample.title]===undefined){samplesByTitle[sample.title]=[];}
+samplesByTitle[sample.title].push(sample);});const sampleTitles=Object.keys(samplesByTitle);sampleTitles.sort();sampleTitles.forEach(function(sampleTitle){const samples=samplesByTitle[sampleTitle];const samplesTrack=new tr.ui.tracks.SampleTrack(this.viewport);samplesTrack.group=this.thread_;samplesTrack.samples=samples;samplesTrack.heading=this.thread_.userFriendlyName+': '+
+sampleTitle;samplesTrack.tooltip=this.thread_.userFriendlyDetails;samplesTrack.selectionGenerator=function(){const selection=new tr.model.EventSet();for(let i=0;i<samplesTrack.samples.length;i++){selection.push(samplesTrack.samples[i]);}
+return selection;};Polymer.dom(this).appendChild(samplesTrack);},this);},collapsedDidChange(collapsed){if(collapsed){let h=parseInt(this.tracks[0].height);for(let i=0;i<this.tracks.length;++i){if(h>2){this.tracks[i].height=Math.floor(h)+'px';}else{this.tracks[i].style.display='none';}
+h=h*0.5;}}else{for(let i=0;i<this.tracks.length;++i){this.tracks[i].height=this.tracks[0].height;this.tracks[i].style.display='';}}}};return{ThreadTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const OtherThreadsTrack=tr.ui.b.define('other-threads-track',tr.ui.tracks.OtherThreadsTrack);const SpacingTrack=tr.ui.tracks.SpacingTrack;OtherThreadsTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.header_=document.createElement('tr-ui-b-heading');this.header_.addEventListener('click',this.onHeaderClick_.bind(this));this.header_.heading='Other Threads';this.header_.tooltip='Threads with only scheduling information';this.header_.arrowVisible=true;this.threads_=[];this.expanded=false;this.collapsible_=true;},set threads(threads){this.threads_=threads;this.updateContents_();},set collapsible(collapsible){this.collapsible_=collapsible;this.updateContents_();},onHeaderClick_(e){e.stopPropagation();e.preventDefault();this.expanded=!this.expanded;},get expanded(){return this.header_.expanded;},set expanded(expanded){expanded=!!expanded;if(this.expanded===expanded)return;this.header_.expanded=expanded;this.viewport_.dispatchChangeEvent();this.updateContents_();},updateContents_(){this.detach();if(this.collapsible_){Polymer.dom(this).appendChild(this.header_);}
+if(this.expanded||!this.collapsible_){for(const thread of this.threads_){const track=new tr.ui.tracks.ThreadTrack(this.viewport);track.thread=thread;if(!track.hasVisibleContent)return;Polymer.dom(this).appendChild(track);Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));}}}};return{OtherThreadsTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const ProcessSummaryTrack=tr.ui.b.define('process-summary-track',tr.ui.tracks.RectTrack);ProcessSummaryTrack.buildRectsFromProcess=function(process){if(!process)return[];const ops=[];const pushOp=function(isStart,time,slice){ops.push({isStart,time,slice});};for(const tid in process.threads){const sliceGroup=process.threads[tid].sliceGroup;sliceGroup.topLevelSlices.forEach(function(slice){pushOp(true,slice.start,undefined);pushOp(false,slice.end,undefined);});sliceGroup.slices.forEach(function(slice){if(slice.important){pushOp(true,slice.start,slice);pushOp(false,slice.end,slice);}});}
+ops.sort(function(a,b){return a.time-b.time;});const rects=[];const genericColorId=ColorScheme.getColorIdForReservedName('generic_work');const pushRect=function(start,end,slice){rects.push(new tr.ui.tracks.Rect(slice,slice?slice.title:'',slice?slice.colorId:genericColorId,start,end-start));};let depth=0;let currentSlice=undefined;let lastStart=undefined;ops.forEach(function(op){depth+=op.isStart?1:-1;if(currentSlice){if(!op.isStart&&op.slice===currentSlice){pushRect(lastStart,op.time,currentSlice);lastStart=depth>=1?op.time:undefined;currentSlice=undefined;}}else{if(op.isStart){if(depth===1){lastStart=op.time;currentSlice=op.slice;}else if(op.slice){if(op.time!==lastStart){pushRect(lastStart,op.time,undefined);lastStart=op.time;}
+currentSlice=op.slice;}}else{if(depth===0){pushRect(lastStart,op.time,undefined);lastStart=undefined;}}}});return rects;};ProcessSummaryTrack.prototype={__proto__:tr.ui.tracks.RectTrack.prototype,decorate(viewport){tr.ui.tracks.RectTrack.prototype.decorate.call(this,viewport);},get process(){return this.process_;},set process(process){this.process_=process;this.rects=ProcessSummaryTrack.buildRectsFromProcess(process);}};return{ProcessSummaryTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ObjectSnapshotView=tr.ui.analysis.ObjectSnapshotView;const ObjectInstanceView=tr.ui.analysis.ObjectInstanceView;const SpacingTrack=tr.ui.tracks.SpacingTrack;const ProcessTrackBase=tr.ui.b.define('process-track-base',tr.ui.tracks.ContainerTrack);ProcessTrackBase.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.processBase_=undefined;Polymer.dom(this).classList.add('process-track-base');Polymer.dom(this).classList.add('expanded');this.processNameEl_=tr.ui.b.createSpan();Polymer.dom(this.processNameEl_).classList.add('process-track-name');this.closeEl_=tr.ui.b.createSpan();Polymer.dom(this.closeEl_).classList.add('process-track-close');this.closeEl_.textContent='X';this.headerEl_=tr.ui.b.createDiv({className:'process-track-header'});Polymer.dom(this.headerEl_).appendChild(this.processNameEl_);Polymer.dom(this.headerEl_).appendChild(this.closeEl_);this.headerEl_.addEventListener('click',this.onHeaderClick_.bind(this));Polymer.dom(this).appendChild(this.headerEl_);},get processBase(){return this.processBase_;},set processBase(processBase){this.processBase_=processBase;if(this.processBase_){const modelSettings=new tr.model.ModelSettings(this.processBase_.model);const defaultValue=this.processBase_.important;this.expanded=modelSettings.getSettingFor(this.processBase_,'expanded',defaultValue);}
+this.updateContents_();},get expanded(){return Polymer.dom(this).classList.contains('expanded');},set expanded(expanded){expanded=!!expanded;if(this.expanded===expanded)return;Polymer.dom(this).classList.toggle('expanded');this.viewport_.dispatchChangeEvent();if(!this.processBase_)return;const modelSettings=new tr.model.ModelSettings(this.processBase_.model);modelSettings.setSettingFor(this.processBase_,'expanded',expanded);this.updateContents_();this.viewport.rebuildEventToTrackMap();this.viewport.rebuildContainerToTrackMap();},set visible(visible){if(visible===this.visible)return;this.hidden=!visible;tr.b.dispatchSimpleEvent(this,'visibility');this.viewport_.dispatchChangeEvent();if(!this.processBase_)return;this.updateContents_();this.viewport.rebuildEventToTrackMap();this.viewport.rebuildContainerToTrackMap();},get visible(){return!this.hidden;},get hasVisibleContent(){if(this.expanded){return this.children.length>1;}
+return true;},onHeaderClick_(e){e.stopPropagation();e.preventDefault();if(e.target===this.closeEl_){this.visible=false;}else{this.expanded=!this.expanded;}},updateContents_(){this.clearTracks_();if(!this.processBase_)return;if(!this.visible)return;Polymer.dom(this.processNameEl_).textContent=this.processBase_.userFriendlyName;this.headerEl_.title=this.processBase_.userFriendlyDetails;this.willAppendTracks_();if(this.expanded){this.appendMemoryDumpTrack_();this.appendObjectInstanceTracks_();this.appendCounterTracks_();this.appendFrameTrack_();this.appendThreadTracks_();}else{this.appendSummaryTrack_();}
+this.didAppendTracks_();},willAppendTracks_(){},didAppendTracks_(){},appendMemoryDumpTrack_(){},appendSummaryTrack_(){const track=new tr.ui.tracks.ProcessSummaryTrack(this.viewport);track.process=this.process;if(!track.hasVisibleContent)return;Polymer.dom(this).appendChild(track);},appendFrameTrack_(){const frames=this.process?this.process.frames:undefined;if(!frames||!frames.length)return;const track=new tr.ui.tracks.FrameTrack(this.viewport);track.frames=frames;Polymer.dom(this).appendChild(track);},appendObjectInstanceTracks_(){const instancesByTypeName=this.processBase_.objects.getAllInstancesByTypeName();const instanceTypeNames=Object.keys(instancesByTypeName);instanceTypeNames.sort();let didAppendAtLeastOneTrack=false;instanceTypeNames.forEach(function(typeName){const allInstances=instancesByTypeName[typeName];let instanceViewInfo=ObjectInstanceView.getTypeInfo(undefined,typeName);let snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(instanceViewInfo&&!instanceViewInfo.metadata.showInTrackView){instanceViewInfo=undefined;}
+if(snapshotViewInfo&&!snapshotViewInfo.metadata.showInTrackView){snapshotViewInfo=undefined;}
+const hasViewInfo=instanceViewInfo||snapshotViewInfo;const visibleInstances=[];for(let i=0;i<allInstances.length;i++){const instance=allInstances[i];if(instance.snapshots.length===0)continue;if(instance.hasImplicitSnapshots&&!hasViewInfo)continue;visibleInstances.push(instance);}
+if(visibleInstances.length===0)return;let trackConstructor=tr.ui.tracks.ObjectInstanceTrack.getConstructor(undefined,typeName);if(!trackConstructor){snapshotViewInfo=ObjectSnapshotView.getTypeInfo(undefined,typeName);if(snapshotViewInfo&&snapshotViewInfo.metadata.showInstances){trackConstructor=tr.ui.tracks.ObjectInstanceGroupTrack;}else{trackConstructor=tr.ui.tracks.ObjectInstanceTrack;}}
+const track=new trackConstructor(this.viewport);track.objectInstances=visibleInstances;Polymer.dom(this).appendChild(track);didAppendAtLeastOneTrack=true;},this);if(didAppendAtLeastOneTrack){Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));}},appendCounterTracks_(){const counters=Object.values(this.processBase.counters);counters.sort(tr.model.Counter.compare);counters.forEach(function(counter){const track=new tr.ui.tracks.CounterTrack(this.viewport);track.counter=counter;Polymer.dom(this).appendChild(track);Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));}.bind(this));},appendThreadTracks_(){const threads=Object.values(this.processBase.threads);threads.sort(tr.model.Thread.compare);const otherThreads=[];let hasVisibleThreads=false;threads.forEach(function(thread){const track=new tr.ui.tracks.ThreadTrack(this.viewport);track.thread=thread;if(!track.hasVisibleContent)return;if(track.hasSlices){hasVisibleThreads=true;Polymer.dom(this).appendChild(track);Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));}else if(track.hasTimeSlices){otherThreads.push(thread);}}.bind(this));if(otherThreads.length>0){const track=new tr.ui.tracks.OtherThreadsTrack(this.viewport);track.threads=otherThreads;track.collapsible=otherThreads.length>1&&hasVisibleThreads;Polymer.dom(this).appendChild(track);}}};return{ProcessTrackBase,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const Cpu=tr.model.Cpu;const CpuTrack=tr.ui.tracks.cpu_track;const ProcessTrackBase=tr.ui.tracks.ProcessTrackBase;const SpacingTrack=tr.ui.tracks.SpacingTrack;const KernelTrack=tr.ui.b.define('kernel-track',ProcessTrackBase);KernelTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate(viewport){ProcessTrackBase.prototype.decorate.call(this,viewport);},set kernel(kernel){this.processBase=kernel;},get kernel(){return this.processBase;},get eventContainer(){return this.kernel;},get hasVisibleContent(){return this.children.length>1;},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.ProcessTrackBase.prototype.addContainersToTrackMap.call(this,containerToTrackMap);containerToTrackMap.addContainer(this.kernel,this);},willAppendTracks_(){const cpus=Object.values(this.kernel.cpus);cpus.sort(tr.model.Cpu.compare);let didAppendAtLeastOneTrack=false;for(let i=0;i<cpus.length;++i){const cpu=cpus[i];const track=new tr.ui.tracks.CpuTrack(this.viewport);track.detailedMode=this.expanded;track.cpu=cpu;if(!track.hasVisibleContent)continue;Polymer.dom(this).appendChild(track);didAppendAtLeastOneTrack=true;}
+if(didAppendAtLeastOneTrack){Polymer.dom(this).appendChild(new SpacingTrack(this.viewport));}}};return{KernelTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const InteractionTrack=tr.ui.b.define('interaction-track',tr.ui.tracks.MultiRowTrack);InteractionTrack.prototype={__proto__:tr.ui.tracks.MultiRowTrack.prototype,decorate(viewport){tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this,viewport);this.heading='Interactions';this.subRows_=[];},set model(model){this.setItemsToGroup(model.userModel.expectations,{guid:tr.b.GUID.allocateSimple(),model,getSettingsKey(){return undefined;}});},buildSubRows_(slices){if(this.subRows_.length){return this.subRows_;}
+this.subRows_.push(...tr.ui.tracks.groupAsyncSlicesIntoSubRows(slices,true));return this.subRows_;},addSubTrack_(slices){const track=new tr.ui.tracks.SliceTrack(this.viewport);track.slices=slices;Polymer.dom(this).appendChild(track);return track;}};return{InteractionTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ColorScheme=tr.b.ColorScheme;const LetterDotTrack=tr.ui.tracks.LetterDotTrack;const MemoryTrack=tr.ui.b.define('memory-track',LetterDotTrack);MemoryTrack.prototype={__proto__:LetterDotTrack.prototype,decorate(viewport){LetterDotTrack.prototype.decorate.call(this,viewport);this.classList.add('memory-track');this.heading='Memory Events';this.lowMemoryEvents_=undefined;},initialize(model){if(model!==undefined){this.lowMemoryEvents_=model.device.lowMemoryEvents;}else{this.lowMemoryEvents_=undefined;}
+if(this.hasVisibleContent){this.items=this.buildMemoryLetterDots_(this.lowMemoryEvents_);}},get hasVisibleContent(){return!!this.lowMemoryEvents_&&this.lowMemoryEvents_.length!==0;},buildMemoryLetterDots_(memoryEvents){return memoryEvents.map(memoryEvent=>new tr.ui.tracks.LetterDot(memoryEvent,'K',ColorScheme.getColorIdForReservedName('background_memory_dump'),memoryEvent.start));},};return{MemoryTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ALLOCATED_MEMORY_TRACK_HEIGHT=50;const ProcessMemoryDumpTrack=tr.ui.b.define('process-memory-dump-track',tr.ui.tracks.ContainerTrack);ProcessMemoryDumpTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);this.memoryDumps_=undefined;},get memoryDumps(){return this.memoryDumps_;},set memoryDumps(memoryDumps){this.memoryDumps_=memoryDumps;this.updateContents_();},updateContents_(){this.clearTracks_();if(!this.memoryDumps_||!this.memoryDumps_.length)return;this.appendAllocatedMemoryTrack_();},appendAllocatedMemoryTrack_(){const series=tr.ui.tracks.buildProcessAllocatedMemoryChartSeries(this.memoryDumps_);if(!series)return;const track=new tr.ui.tracks.ChartTrack(this.viewport);track.heading='Memory per component';track.height=ALLOCATED_MEMORY_TRACK_HEIGHT+'px';track.series=series;track.autoSetAllAxes({expandMax:true});Polymer.dom(this).appendChild(track);}};return{ProcessMemoryDumpTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const ProcessTrackBase=tr.ui.tracks.ProcessTrackBase;const ProcessTrack=tr.ui.b.define('process-track',ProcessTrackBase);ProcessTrack.prototype={__proto__:ProcessTrackBase.prototype,decorate(viewport){tr.ui.tracks.ProcessTrackBase.prototype.decorate.call(this,viewport);},drawTrack(type){switch(type){case tr.ui.tracks.DrawType.INSTANT_EVENT:{if(!this.processBase.instantEvents||this.processBase.instantEvents.length===0){break;}
+const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));const dt=this.viewport.currentDisplayTransform;const viewLWorld=dt.xViewToWorld(0);const viewRWorld=dt.xViewToWorld(canvasBounds.width*pixelRatio);tr.ui.b.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.processBase.instantEvents,2);ctx.restore();break;}
+case tr.ui.tracks.DrawType.BACKGROUND:this.drawBackground_();return;}
+tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawBackground_(){const ctx=this.context();const canvasBounds=ctx.canvas.getBoundingClientRect();const pixelRatio=window.devicePixelRatio||1;const children=this.children;let draw=false;ctx.fillStyle='#eee';for(let i=0;i<children.length;++i){if(!(children[i]instanceof tr.ui.tracks.Track)||(children[i]instanceof tr.ui.tracks.SpacingTrack)){continue;}
+draw=!draw;if(!draw)continue;const bounds=children[i].getBoundingClientRect();ctx.fillRect(0,pixelRatio*(bounds.top-canvasBounds.top),ctx.canvas.width,pixelRatio*bounds.height);}},set process(process){this.processBase=process;},get process(){return this.processBase;},get eventContainer(){return this.process;},addContainersToTrackMap(containerToTrackMap){tr.ui.tracks.ProcessTrackBase.prototype.addContainersToTrackMap.apply(this,arguments);containerToTrackMap.addContainer(this.process,this);},appendMemoryDumpTrack_(){const processMemoryDumps=this.process.memoryDumps;if(processMemoryDumps.length){const pmdt=new tr.ui.tracks.ProcessMemoryDumpTrack(this.viewport_);pmdt.memoryDumps=processMemoryDumps;Polymer.dom(this).appendChild(pmdt);}},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){function onPickHit(instantEvent){selection.push(instantEvent);}
+const instantEventWidth=2*viewPixWidthWorld;tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,function(x){return x.start;},function(x){return x.duration+instantEventWidth;},loWX,hiWX,onPickHit.bind(this));tr.ui.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.processBase.instantEvents,worldX,worldMaxDist,selection);tr.ui.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ProcessTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const SelectionState=tr.model.SelectionState;const ColorScheme=tr.b.ColorScheme;const EventPresenter=tr.ui.b.EventPresenter;const ModelTrack=tr.ui.b.define('model-track',tr.ui.tracks.ContainerTrack);ModelTrack.VSYNC_HIGHLIGHT_ALPHA=0.1;ModelTrack.VSYNC_DENSITY_TRANSPARENT=0.20;ModelTrack.VSYNC_DENSITY_OPAQUE=0.10;ModelTrack.VSYNC_DENSITY_RANGE=ModelTrack.VSYNC_DENSITY_TRANSPARENT-ModelTrack.VSYNC_DENSITY_OPAQUE;ModelTrack.generateStripes_=function(times,minTime,maxTime){if(times.length===0)return[];const lowIndex=tr.b.findLowIndexInSortedArray(times,(x=>x),minTime);let highIndex=lowIndex-1;while(times[highIndex+1]<=maxTime){highIndex++;}
+const stripes=[];for(let i=lowIndex-(lowIndex%2);i<=highIndex;i+=2){const left=i<lowIndex?minTime:times[i];const right=i+1>highIndex?maxTime:times[i+1];stripes.push(tr.b.math.Range.fromExplicitRange(left,right));}
+return stripes;};ModelTrack.prototype={__proto__:tr.ui.tracks.ContainerTrack.prototype,decorate(viewport){tr.ui.tracks.ContainerTrack.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('model-track');this.upperMode_=false;this.annotationViews_=[];this.vSyncTimes_=[];},get processViews(){return Polymer.dom(this).querySelectorAll('.process-track-base');},get upperMode(){return this.upperMode_;},set upperMode(upperMode){this.upperMode_=upperMode;this.updateContents_();},detach(){tr.ui.tracks.ContainerTrack.prototype.detach.call(this);},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();this.model_.addEventListener('annotationChange',this.updateAnnotations_.bind(this));},get hasVisibleContent(){return this.children.length>0;},updateContents_(){Polymer.dom(this).textContent='';if(!this.model_)return;if(this.upperMode_){this.updateContentsForUpperMode_();}else{this.updateContentsForLowerMode_();}},updateContentsForUpperMode_(){},updateContentsForLowerMode_(){if(this.model_.userModel.expectations.length>1){const mrt=new tr.ui.tracks.InteractionTrack(this.viewport_);mrt.model=this.model_;Polymer.dom(this).appendChild(mrt);}
+if(this.model_.alerts.length){const at=new tr.ui.tracks.AlertTrack(this.viewport_);at.alerts=this.model_.alerts;Polymer.dom(this).appendChild(at);}
+if(this.model_.globalMemoryDumps.length){const gmdt=new tr.ui.tracks.GlobalMemoryDumpTrack(this.viewport_);gmdt.memoryDumps=this.model_.globalMemoryDumps;Polymer.dom(this).appendChild(gmdt);}
+this.appendDeviceTrack_();this.appendCpuUsageTrack_();this.appendMemoryTrack_();this.appendKernelTrack_();const processes=this.model_.getAllProcesses();processes.sort(tr.model.Process.compare);for(let i=0;i<processes.length;++i){const process=processes[i];const track=new tr.ui.tracks.ProcessTrack(this.viewport);track.process=process;if(!track.hasVisibleContent)continue;Polymer.dom(this).appendChild(track);}
+this.viewport_.rebuildEventToTrackMap();this.viewport_.rebuildContainerToTrackMap();this.vSyncTimes_=this.model_.device.vSyncTimestamps;this.updateAnnotations_();},getContentBounds(){return this.model.bounds;},addAnnotation(annotation){this.model.addAnnotation(annotation);},removeAnnotation(annotation){this.model.removeAnnotation(annotation);},updateAnnotations_(){this.annotationViews_=[];const annotations=this.model_.getAllAnnotations();for(let i=0;i<annotations.length;i++){this.annotationViews_.push(annotations[i].getOrCreateView(this.viewport_));}
+this.invalidateDrawingContainer();},addEventsToTrackMap(eventToTrackMap){if(!this.model_)return;const tracks=this.children;for(let i=0;i<tracks.length;++i){tracks[i].addEventsToTrackMap(eventToTrackMap);}
+if(this.instantEvents===undefined)return;const vp=this.viewport_;this.instantEvents.forEach(function(ev){eventToTrackMap.addEvent(ev,this);}.bind(this));},appendDeviceTrack_(){const device=this.model.device;const track=new tr.ui.tracks.DeviceTrack(this.viewport);track.device=this.model.device;if(!track.hasVisibleContent)return;Polymer.dom(this).appendChild(track);},appendKernelTrack_(){const kernel=this.model.kernel;const track=new tr.ui.tracks.KernelTrack(this.viewport);track.kernel=this.model.kernel;if(!track.hasVisibleContent)return;Polymer.dom(this).appendChild(track);},appendCpuUsageTrack_(){const track=new tr.ui.tracks.CpuUsageTrack(this.viewport);track.initialize(this.model);if(!track.hasVisibleContent)return;this.appendChild(track);},appendMemoryTrack_(){const track=new tr.ui.tracks.MemoryTrack(this.viewport);track.initialize(this.model);if(!track.hasVisibleContent)return;Polymer.dom(this).appendChild(track);},drawTrack(type){const ctx=this.context();if(!this.model_)return;const pixelRatio=window.devicePixelRatio||1;const bounds=this.getBoundingClientRect();const canvasBounds=ctx.canvas.getBoundingClientRect();ctx.save();ctx.translate(0,pixelRatio*(bounds.top-canvasBounds.top));const dt=this.viewport.currentDisplayTransform;const viewLWorld=dt.xViewToWorld(0);const viewRWorld=dt.xViewToWorld(canvasBounds.width*pixelRatio);const viewHeight=bounds.height*pixelRatio;switch(type){case tr.ui.tracks.DrawType.GRID:this.viewport.drawMajorMarkLines(ctx,viewHeight);ctx.restore();return;case tr.ui.tracks.DrawType.FLOW_ARROWS:if(this.model_.flowIntervalTree.size===0){ctx.restore();return;}
+this.drawFlowArrows_(viewLWorld,viewRWorld);ctx.restore();return;case tr.ui.tracks.DrawType.INSTANT_EVENT:if(!this.model_.instantEvents||this.model_.instantEvents.length===0){break;}
+tr.ui.b.drawInstantSlicesAsLines(ctx,this.viewport.currentDisplayTransform,viewLWorld,viewRWorld,bounds.height,this.model_.instantEvents,4);break;case tr.ui.tracks.DrawType.MARKERS:if(!this.viewport.interestRange.isEmpty){this.viewport.interestRange.draw(ctx,viewLWorld,viewRWorld,viewHeight);this.viewport.interestRange.drawIndicators(ctx,viewLWorld,viewRWorld);}
+ctx.restore();return;case tr.ui.tracks.DrawType.HIGHLIGHTS:this.drawVSyncHighlight(ctx,dt,viewLWorld,viewRWorld,viewHeight);ctx.restore();return;case tr.ui.tracks.DrawType.ANNOTATIONS:for(let i=0;i<this.annotationViews_.length;i++){this.annotationViews_[i].draw(ctx);}
+ctx.restore();return;}
+ctx.restore();tr.ui.tracks.ContainerTrack.prototype.drawTrack.call(this,type);},drawFlowArrows_(viewLWorld,viewRWorld){const ctx=this.context();ctx.strokeStyle='rgba(0, 0, 0, 0.4)';ctx.fillStyle='rgba(0, 0, 0, 0.4)';ctx.lineWidth=1;const events=this.model_.flowIntervalTree.findIntersection(viewLWorld,viewRWorld);const canvasBounds=ctx.canvas.getBoundingClientRect();for(let i=0;i<events.length;++i){const onlyHighlighted=!tr.b.getCategoryParts(events[i].category).some((x)=>this.viewport.selectedFlowEvents.has(x));if(onlyHighlighted&&events[i].selectionState!==SelectionState.SELECTED&&events[i].selectionState!==SelectionState.HIGHLIGHTED){continue;}
+this.drawFlowArrow_(ctx,events[i],canvasBounds);}},drawFlowArrow_(ctx,flowEvent,canvasBounds){const dt=this.viewport.currentDisplayTransform;const pixelRatio=window.devicePixelRatio||1;const startTrack=this.viewport.trackForEvent(flowEvent.startSlice);const endTrack=this.viewport.trackForEvent(flowEvent.endSlice);if(startTrack===undefined||endTrack===undefined)return;const startBounds=startTrack.getBoundingClientRect();const endBounds=endTrack.getBoundingClientRect();if(flowEvent.selectionState===SelectionState.SELECTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else if(flowEvent.selectionState===SelectionState.HIGHLIGHTED){ctx.shadowBlur=1;ctx.shadowColor='red';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else if(flowEvent.selectionState===SelectionState.DIMMED){ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];}else{let hasBoost=false;const startSlice=flowEvent.startSlice;hasBoost|=startSlice.selectionState===SelectionState.SELECTED;hasBoost|=startSlice.selectionState===SelectionState.HIGHLIGHTED;const endSlice=flowEvent.endSlice;hasBoost|=endSlice.selectionState===SelectionState.SELECTED;hasBoost|=endSlice.selectionState===SelectionState.HIGHLIGHTED;if(hasBoost){ctx.shadowBlur=1;ctx.shadowColor='rgba(255, 0, 0, 0.4)';ctx.shadowOffsety=2;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[tr.b.ColorScheme.getVariantColorId(flowEvent.colorId,tr.b.ColorScheme.properties.brightenedOffsets[0])];}else{ctx.shadowBlur=0;ctx.shadowOffsetX=0;ctx.strokeStyle=tr.b.ColorScheme.colorsAsStrings[flowEvent.colorId];}}
+const startSize=startBounds.left+startBounds.top+
+startBounds.bottom+startBounds.right;const endSize=endBounds.left+endBounds.top+
+endBounds.bottom+endBounds.right;if(startSize===0&&endSize===0)return;const startY=this.calculateTrackY_(startTrack,canvasBounds);const endY=this.calculateTrackY_(endTrack,canvasBounds);const worldOffset=this.getBoundingClientRect().top-canvasBounds.top;const pixelStartY=pixelRatio*(startY-worldOffset);const pixelEndY=pixelRatio*(endY-worldOffset);const startXView=dt.xWorldToView(flowEvent.start);const endXView=dt.xWorldToView(flowEvent.end);const midXView=(startXView+endXView)/2;ctx.beginPath();ctx.moveTo(startXView,pixelStartY);ctx.bezierCurveTo(midXView,pixelStartY,midXView,pixelEndY,endXView,pixelEndY);ctx.stroke();const arrowWidth=5*pixelRatio;const distance=endXView-startXView;if(distance<=(2*arrowWidth))return;const tipX=endXView;const tipY=pixelEndY;const arrowHeight=(endBounds.height/4)*pixelRatio;tr.ui.b.drawTriangle(ctx,tipX,tipY,tipX-arrowWidth,tipY-arrowHeight,tipX-arrowWidth,tipY+arrowHeight);ctx.fill();},drawVSyncHighlight(ctx,dt,viewLWorld,viewRWorld,viewHeight){if(!this.viewport_.highlightVSync){return;}
+const stripes=ModelTrack.generateStripes_(this.vSyncTimes_,viewLWorld,viewRWorld);if(stripes.length===0){return;}
+const vSyncHighlightColor=new tr.b.Color(ColorScheme.getColorForReservedNameAsString('vsync_highlight_color'));const stripeRange=stripes[stripes.length-1].max-stripes[0].min;const stripeDensity=stripeRange?stripes.length/(dt.scaleX*stripeRange):0;const clampedStripeDensity=tr.b.math.clamp(stripeDensity,ModelTrack.VSYNC_DENSITY_OPAQUE,ModelTrack.VSYNC_DENSITY_TRANSPARENT);const opacity=(ModelTrack.VSYNC_DENSITY_TRANSPARENT-clampedStripeDensity)/ModelTrack.VSYNC_DENSITY_RANGE;if(opacity===0){return;}
+ctx.fillStyle=vSyncHighlightColor.toStringWithAlphaOverride(ModelTrack.VSYNC_HIGHLIGHT_ALPHA*opacity);for(let i=0;i<stripes.length;i++){const xLeftView=dt.xWorldToView(stripes[i].min);const xRightView=dt.xWorldToView(stripes[i].max);ctx.fillRect(xLeftView,0,xRightView-xLeftView,viewHeight);}},calculateTrackY_(track,canvasBounds){const bounds=track.getBoundingClientRect();const size=bounds.left+bounds.top+bounds.bottom+bounds.right;if(size===0){return this.calculateTrackY_(Polymer.dom(track).parentNode,canvasBounds);}
+return bounds.top-canvasBounds.top+(bounds.height/2);},addIntersectingEventsInRangeToSelectionInWorldSpace(loWX,hiWX,viewPixWidthWorld,selection){function onPickHit(instantEvent){selection.push(instantEvent);}
+const instantEventWidth=3*viewPixWidthWorld;tr.b.iterateOverIntersectingIntervals(this.model_.instantEvents,function(x){return x.start;},function(x){return x.duration+instantEventWidth;},loWX,hiWX,onPickHit.bind(this));tr.ui.tracks.ContainerTrack.prototype.addIntersectingEventsInRangeToSelectionInWorldSpace.apply(this,arguments);},addClosestEventToSelection(worldX,worldMaxDist,loY,hiY,selection){this.addClosestInstantEventToSelection(this.model_.instantEvents,worldX,worldMaxDist,selection);tr.ui.tracks.ContainerTrack.prototype.addClosestEventToSelection.apply(this,arguments);}};return{ModelTrack,};});'use strict';tr.exportTo('tr.ui.tracks',function(){const XAxisTrack=tr.ui.b.define('x-axis-track',tr.ui.tracks.Track);XAxisTrack.prototype={__proto__:tr.ui.tracks.Track.prototype,decorate(viewport){tr.ui.tracks.Track.prototype.decorate.call(this,viewport);Polymer.dom(this).classList.add('x-axis-track');this.strings_secs_=[];this.strings_msecs_=[];this.strings_usecs_=[];this.strings_nsecs_=[];this.viewportChange_=this.viewportChange_.bind(this);viewport.addEventListener('change',this.viewportChange_);const heading=document.createElement('tr-ui-b-heading');heading.arrowVisible=false;Polymer.dom(this).appendChild(heading);},detach(){tr.ui.tracks.Track.prototype.detach.call(this);this.viewport.removeEventListener('change',this.viewportChange_);},viewportChange_(){if(this.viewport.interestRange.isEmpty){Polymer.dom(this).classList.remove('tall-mode');}else{Polymer.dom(this).classList.add('tall-mode');}},draw(type,viewLWorld,viewRWorld,viewHeight){switch(type){case tr.ui.tracks.DrawType.GRID:this.drawGrid_(viewLWorld,viewRWorld);break;case tr.ui.tracks.DrawType.MARKERS:this.drawMarkers_(viewLWorld,viewRWorld);break;}},drawGrid_(viewLWorld,viewRWorld){const ctx=this.context();const pixelRatio=window.devicePixelRatio||1;const canvasBounds=ctx.canvas.getBoundingClientRect();const trackBounds=this.getBoundingClientRect();const width=canvasBounds.width*pixelRatio;const height=trackBounds.height*pixelRatio;const hasInterestRange=!this.viewport.interestRange.isEmpty;const xAxisHeightPx=hasInterestRange?(height*2)/5:height;const vp=this.viewport;const dt=vp.currentDisplayTransform;vp.updateMajorMarkData(viewLWorld,viewRWorld);const majorMarkDistanceWorld=vp.majorMarkWorldPositions.length>1?vp.majorMarkWorldPositions[1]-vp.majorMarkWorldPositions[0]:0;const numTicksPerMajor=5;const minorMarkDistanceWorld=majorMarkDistanceWorld/numTicksPerMajor;const minorMarkDistancePx=dt.xWorldVectorToView(minorMarkDistanceWorld);const minorTickHeight=Math.floor(xAxisHeightPx*0.25);ctx.save();ctx.lineWidth=Math.round(pixelRatio);const crispLineCorrection=(ctx.lineWidth%2)/2;ctx.translate(crispLineCorrection,-crispLineCorrection);ctx.fillStyle='rgb(0, 0, 0)';ctx.strokeStyle='rgb(0, 0, 0)';ctx.textAlign='left';ctx.textBaseline='top';ctx.font=(9*pixelRatio)+'px sans-serif';const tickLabels=[];ctx.beginPath();for(let i=0;i<vp.majorMarkWorldPositions.length;i++){const curXWorld=vp.majorMarkWorldPositions[i];const curXView=dt.xWorldToView(curXWorld);const displayText=vp.majorMarkUnit.format(curXWorld,{deltaValue:majorMarkDistanceWorld});ctx.fillText(displayText,curXView+(2*pixelRatio),0);tr.ui.b.drawLine(ctx,curXView,0,curXView,xAxisHeightPx);if(minorMarkDistancePx){for(let j=1;j<numTicksPerMajor;++j){const xView=Math.floor(curXView+minorMarkDistancePx*j);tr.ui.b.drawLine(ctx,xView,xAxisHeightPx-minorTickHeight,xView,xAxisHeightPx);}}}
+ctx.strokeStyle='rgb(0, 0, 0)';tr.ui.b.drawLine(ctx,0,height,width,height);ctx.stroke();if(!hasInterestRange)return;tr.ui.b.drawLine(ctx,0,xAxisHeightPx,width,xAxisHeightPx);ctx.stroke();let displayDistance;const displayTextColor='rgb(0,0,0)';const arrowSpacing=10*pixelRatio;const arrowColor='rgb(128,121,121)';const arrowPosY=xAxisHeightPx*1.75;const arrowWidthView=3*pixelRatio;const arrowLengthView=10*pixelRatio;const spaceForArrowsView=2*(arrowWidthView+arrowSpacing);ctx.textBaseline='middle';ctx.font=(14*pixelRatio)+'px sans-serif';const textPosY=arrowPosY;const interestRange=vp.interestRange;if(interestRange.range===0){const markerWorld=interestRange.min;const markerView=dt.xWorldToView(markerWorld);const textToDraw=vp.majorMarkUnit.format(markerWorld);let textLeftView=markerView+4*pixelRatio;const textWidthView=ctx.measureText(textToDraw).width;if(textLeftView+textWidthView>width){textLeftView=markerView-4*pixelRatio-textWidthView;}
+ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);return;}
+const leftMarker=interestRange.min;const rightMarker=interestRange.max;const leftMarkerView=dt.xWorldToView(leftMarker);const rightMarkerView=dt.xWorldToView(rightMarker);const distanceBetweenMarkers=interestRange.range;const distanceBetweenMarkersView=dt.xWorldVectorToView(distanceBetweenMarkers);const positionInMiddleOfMarkersView=leftMarkerView+(distanceBetweenMarkersView/2);const textToDraw=vp.majorMarkUnit.format(distanceBetweenMarkers);const textWidthView=ctx.measureText(textToDraw).width;const spaceForArrowsAndTextView=textWidthView+spaceForArrowsView+arrowSpacing;let textLeftView=positionInMiddleOfMarkersView-textWidthView/2;const textRightView=textLeftView+textWidthView;if(spaceForArrowsAndTextView>distanceBetweenMarkersView){textLeftView=rightMarkerView+2*arrowSpacing;if(textLeftView+textWidthView>width){textLeftView=leftMarkerView-2*arrowSpacing-textWidthView;}
+ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);ctx.strokeStyle=arrowColor;ctx.beginPath();tr.ui.b.drawLine(ctx,leftMarkerView,arrowPosY,rightMarkerView,arrowPosY);ctx.stroke();ctx.fillStyle=arrowColor;tr.ui.b.drawArrow(ctx,leftMarkerView-1.5*arrowSpacing,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tr.ui.b.drawArrow(ctx,rightMarkerView+1.5*arrowSpacing,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}else if(spaceForArrowsView<=distanceBetweenMarkersView){let leftArrowStart;let rightArrowStart;if(spaceForArrowsAndTextView<=distanceBetweenMarkersView){ctx.fillStyle=displayTextColor;ctx.fillText(textToDraw,textLeftView,textPosY);leftArrowStart=textLeftView-arrowSpacing;rightArrowStart=textRightView+arrowSpacing;}else{leftArrowStart=positionInMiddleOfMarkersView;rightArrowStart=positionInMiddleOfMarkersView;}
+ctx.strokeStyle=arrowColor;ctx.fillStyle=arrowColor;tr.ui.b.drawArrow(ctx,leftArrowStart,arrowPosY,leftMarkerView,arrowPosY,arrowLengthView,arrowWidthView);tr.ui.b.drawArrow(ctx,rightArrowStart,arrowPosY,rightMarkerView,arrowPosY,arrowLengthView,arrowWidthView);}
+ctx.restore();},drawMarkers_(viewLWorld,viewRWorld){const pixelRatio=window.devicePixelRatio||1;const trackBounds=this.getBoundingClientRect();const viewHeight=trackBounds.height*pixelRatio;if(!this.viewport.interestRange.isEmpty){this.viewport.interestRange.draw(this.context(),viewLWorld,viewRWorld,viewHeight);}},addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection){},addAllEventsMatchingFilterToSelection(filter,selection){}};return{XAxisTrack,};});'use strict';Polymer({is:'tr-ui-timeline-track-view',ready(){this.displayTransform_=new tr.ui.TimelineDisplayTransform();this.model_=undefined;this.timelineView_=undefined;this.pollIfViewportAttachedInterval_=undefined;this.viewport_=new tr.ui.TimelineViewport(this);this.viewportDisplayTransformAtMouseDown_=undefined;this.brushingStateController_=undefined;this.rulerTrackContainer_=new tr.ui.tracks.DrawingContainer(this.viewport_);Polymer.dom(this).appendChild(this.rulerTrackContainer_);this.rulerTrackContainer_.invalidate();this.rulerTrackContainer_.style.overflowY='hidden';this.rulerTrackContainer_.style.flexShrink='0';this.rulerTrack_=new tr.ui.tracks.XAxisTrack(this.viewport_);Polymer.dom(this.rulerTrackContainer_).appendChild(this.rulerTrack_);this.upperModelTrack_=new tr.ui.tracks.ModelTrack(this.viewport_);this.upperModelTrack_.upperMode=true;Polymer.dom(this.rulerTrackContainer_).appendChild(this.upperModelTrack_);this.modelTrackContainer_=new tr.ui.tracks.DrawingContainer(this.viewport_);Polymer.dom(this).appendChild(this.modelTrackContainer_);this.modelTrackContainer_.style.display='block';this.modelTrackContainer_.style.flexGrow='1';this.modelTrackContainer_.invalidate();this.viewport_.modelTrackContainer=this.modelTrackContainer_;this.modelTrack_=new tr.ui.tracks.ModelTrack(this.viewport_);Polymer.dom(this.modelTrackContainer_).appendChild(this.modelTrack_);this.timingTool_=new tr.ui.b.TimingTool(this.viewport_,this);this.initMouseModeSelector();this.hideDragBox_();this.initHintText_();this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.onDblClick_=this.onDblClick_.bind(this);this.addEventListener('dblclick',this.onDblClick_);this.onMouseWheel_=this.onMouseWheel_.bind(this);this.addEventListener('mousewheel',this.onMouseWheel_);this.onMouseDown_=this.onMouseDown_.bind(this);this.addEventListener('mousedown',this.onMouseDown_);this.onMouseMove_=this.onMouseMove_.bind(this);this.addEventListener('mousemove',this.onMouseMove_);this.onTouchStart_=this.onTouchStart_.bind(this);this.addEventListener('touchstart',this.onTouchStart_);this.onTouchMove_=this.onTouchMove_.bind(this);this.addEventListener('touchmove',this.onTouchMove_);this.onTouchEnd_=this.onTouchEnd_.bind(this);this.addEventListener('touchend',this.onTouchEnd_);this.addHotKeys_();this.mouseViewPosAtMouseDown_={x:0,y:0};this.lastMouseViewPos_={x:0,y:0};this.lastTouchViewPositions_=[];this.alert_=undefined;this.isPanningAndScanning_=false;this.isZooming_=false;},initMouseModeSelector(){this.mouseModeSelector_=document.createElement('tr-ui-b-mouse-mode-selector');this.mouseModeSelector_.targetElement=this;Polymer.dom(this).appendChild(this.mouseModeSelector_);this.mouseModeSelector_.addEventListener('beginpan',this.onBeginPanScan_.bind(this));this.mouseModeSelector_.addEventListener('updatepan',this.onUpdatePanScan_.bind(this));this.mouseModeSelector_.addEventListener('endpan',this.onEndPanScan_.bind(this));this.mouseModeSelector_.addEventListener('beginselection',this.onBeginSelection_.bind(this));this.mouseModeSelector_.addEventListener('updateselection',this.onUpdateSelection_.bind(this));this.mouseModeSelector_.addEventListener('endselection',this.onEndSelection_.bind(this));this.mouseModeSelector_.addEventListener('beginzoom',this.onBeginZoom_.bind(this));this.mouseModeSelector_.addEventListener('updatezoom',this.onUpdateZoom_.bind(this));this.mouseModeSelector_.addEventListener('endzoom',this.onEndZoom_.bind(this));this.mouseModeSelector_.addEventListener('entertiming',this.timingTool_.onEnterTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('begintiming',this.timingTool_.onBeginTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('updatetiming',this.timingTool_.onUpdateTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('endtiming',this.timingTool_.onEndTiming.bind(this.timingTool_));this.mouseModeSelector_.addEventListener('exittiming',this.timingTool_.onExitTiming.bind(this.timingTool_));const m=tr.ui.b.MOUSE_SELECTOR_MODE;this.mouseModeSelector_.supportedModeMask=m.SELECTION|m.PANSCAN|m.ZOOM|m.TIMING;this.mouseModeSelector_.settingsKey='timelineTrackView.mouseModeSelector';this.mouseModeSelector_.setKeyCodeForMode(m.PANSCAN,'2'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.SELECTION,'1'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.ZOOM,'3'.charCodeAt(0));this.mouseModeSelector_.setKeyCodeForMode(m.TIMING,'4'.charCodeAt(0));this.mouseModeSelector_.setModifierForAlternateMode(m.SELECTION,tr.ui.b.MODIFIER.SHIFT);this.mouseModeSelector_.setModifierForAlternateMode(m.PANSCAN,tr.ui.b.MODIFIER.SPACE);},get brushingStateController(){return this.brushingStateController_;},set brushingStateController(brushingStateController){if(this.brushingStateController_){this.brushingStateController_.removeEventListener('change',this.onSelectionChanged_);}
+this.brushingStateController_=brushingStateController;if(this.brushingStateController_){this.brushingStateController_.addEventListener('change',this.onSelectionChanged_);}},set timelineView(view){this.timelineView_=view;},get processViews(){return this.modelTrack_.processViews;},onSelectionChanged_(){this.showHintText_('Press \'m\' to mark current selection');this.viewport_.dispatchChangeEvent();},set selection(selection){throw new Error('DO NOT CALL THIS');},set highlight(highlight){throw new Error('DO NOT CALL THIS');},detach(){this.modelTrack_.detach();this.upperModelTrack_.detach();if(this.pollIfViewportAttachedInterval_){window.clearInterval(this.pollIfViewportAttachedInterval_);this.pollIfViewportAttachedInterval_=undefined;}
+this.viewport_.detach();},get viewport(){return this.viewport_;},get model(){return this.model_;},set model(model){if(!model){throw new Error('Model cannot be undefined');}
+const modelInstanceChanged=this.model_!==model;this.model_=model;this.modelTrack_.model=model;this.upperModelTrack_.model=model;if(modelInstanceChanged){this.pollIfViewportAttachedInterval_=window.setInterval(this.pollIfViewportAttached_.bind(this),250);}},get hasVisibleContent(){return this.modelTrack_.hasVisibleContent||this.upperModelTrack_.hasVisibleContent;},pollIfViewportAttached_(){if(!this.viewport_.isAttachedToDocumentOrInTestMode||this.viewport_.clientWidth===0){return;}
+window.addEventListener('resize',this.viewport_.dispatchChangeEvent);window.clearInterval(this.pollIfViewportAttachedInterval_);this.pollIfViewportAttachedInterval_=undefined;this.setInitialViewport_();},setInitialViewport_(){this.modelTrackContainer_.updateCanvasSizeIfNeeded_();const w=this.modelTrackContainer_.canvas.width;let min;let range;if(this.model_.bounds.isEmpty){min=0;range=1000;}else if(this.model_.bounds.range===0){min=this.model_.bounds.min;range=1000;}else{min=this.model_.bounds.min;range=this.model_.bounds.range;}
+const boost=range*0.15;this.displayTransform_.set(this.viewport_.currentDisplayTransform);this.displayTransform_.xSetWorldBounds(min-boost,min+range+boost,w);this.viewport_.setDisplayTransformImmediately(this.displayTransform_);},addAllEventsMatchingFilterToSelectionAsTask(filter,selection){const modelTrack=this.modelTrack_;const firstT=modelTrack.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);const lastT=firstT.after(function(){this.upperModelTrack_.addAllEventsMatchingFilterToSelection(filter,selection);},this);return firstT;},onMouseMove_(e){if(this.isZooming_)return;this.storeLastMousePos_(e);},onTouchStart_(e){this.storeLastTouchPositions_(e);this.focusElements_();},onTouchMove_(e){e.preventDefault();this.onUpdateTransformForTouch_(e);},onTouchEnd_(e){this.storeLastTouchPositions_(e);this.focusElements_();},addHotKeys_(){this.addKeyDownHotKeys_();this.addKeyPressHotKeys_();},addKeyPressHotKey(dict){dict.eventType='keypress';dict.useCapture=false;dict.thisArg=this;const binding=new tr.ui.b.HotKey(dict);this.$.hotkey_controller.addHotKey(binding);},addKeyPressHotKeys_(){this.addKeyPressHotKey({keyCodes:['w'.charCodeAt(0),','.charCodeAt(0)],callback(e){this.zoomBy_(1.5,true);e.stopPropagation();}});this.addKeyPressHotKey({keyCodes:['s'.charCodeAt(0),'o'.charCodeAt(0)],callback(e){this.zoomBy_(1/1.5,true);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'g'.charCodeAt(0),callback(e){this.onGridToggle_(true);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'G'.charCodeAt(0),callback(e){this.onGridToggle_(false);e.stopPropagation();}});this.addKeyPressHotKey({keyCodes:['W'.charCodeAt(0),'<'.charCodeAt(0)],callback(e){this.zoomBy_(10,true);e.stopPropagation();}});this.addKeyPressHotKey({keyCodes:['S'.charCodeAt(0),'O'.charCodeAt(0)],callback(e){this.zoomBy_(1/10,true);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'a'.charCodeAt(0),callback(e){this.queueSmoothPan_(this.viewWidth_*0.3,0);e.stopPropagation();}});this.addKeyPressHotKey({keyCodes:['d'.charCodeAt(0),'e'.charCodeAt(0)],callback(e){this.queueSmoothPan_(this.viewWidth_*-0.3,0);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'A'.charCodeAt(0),callback(e){this.queueSmoothPan_(viewWidth*0.5,0);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'D'.charCodeAt(0),callback(e){this.queueSmoothPan_(viewWidth*-0.5,0);e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'0'.charCodeAt(0),callback(e){this.setInitialViewport_();e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'f'.charCodeAt(0),callback(e){this.zoomToSelection();e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'m'.charCodeAt(0),callback(e){this.setCurrentSelectionAsInterestRange_();e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'p'.charCodeAt(0),callback(e){this.selectPowerSamplesInCurrentTimeRange_();e.stopPropagation();}});this.addKeyPressHotKey({keyCode:'h'.charCodeAt(0),callback(e){this.toggleHighDetails_();e.stopPropagation();}});},get viewWidth_(){return this.modelTrackContainer_.canvas.clientWidth;},addKeyDownHotKeys_(){const addBinding=function(dict){dict.eventType='keydown';dict.useCapture=false;dict.thisArg=this;const binding=new tr.ui.b.HotKey(dict);this.$.hotkey_controller.addHotKey(binding);}.bind(this);addBinding({keyCode:37,callback(e){const curSel=this.brushingStateController_.selection;const sel=this.viewport.getShiftedSelection(curSel,-1);if(sel){this.brushingStateController.changeSelectionFromTimeline(sel);this.panToSelection();}else{this.queueSmoothPan_(this.viewWidth_*0.3,0);}
+e.preventDefault();e.stopPropagation();}});addBinding({keyCode:39,callback(e){const curSel=this.brushingStateController_.selection;const sel=this.viewport.getShiftedSelection(curSel,1);if(sel){this.brushingStateController.changeSelectionFromTimeline(sel);this.panToSelection();}else{this.queueSmoothPan_(-this.viewWidth_*0.3,0);}
+e.preventDefault();e.stopPropagation();}});},onDblClick_(e){if(this.mouseModeSelector_.mode!==tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION){return;}
+const curSelection=this.brushingStateController_.selection;if(!curSelection.length||!tr.b.getOnlyElement(curSelection).title){return;}
+const selection=new tr.model.EventSet();const filter=new tr.c.ExactTitleFilter(tr.b.getOnlyElement(curSelection).title);this.modelTrack_.addAllEventsMatchingFilterToSelection(filter,selection);this.brushingStateController.changeSelectionFromTimeline(selection);},onMouseWheel_(e){if(!e.altKey)return;const delta=e.wheelDelta/120;const zoomScale=Math.pow(1.5,delta);this.zoomBy_(zoomScale);e.preventDefault();},onMouseDown_(e){if(this.mouseModeSelector_.mode!==tr.ui.b.MOUSE_SELECTOR_MODE.SELECTION){return;}
+if(e.target!==this.rulerTrack_)return;this.dragBeginEvent_=undefined;if(this.xNavStringMarker_){this.model.removeAnnotation(this.xNavStringMarker_);this.xNavStringMarker_=undefined;}
+const dt=this.viewport_.currentDisplayTransform;tr.ui.b.trackMouseMovesUntilMouseUp(function(e){if(e.target===this.rulerTrack_)return;const relativePosition=this.extractRelativeMousePosition_(e);const loc=tr.model.Location.fromViewCoordinates(this.viewport_,relativePosition.x,relativePosition.y);if(!loc)return;if(this.guideLineAnnotation_===undefined){this.guideLineAnnotation_=new tr.model.XMarkerAnnotation(loc.xWorld);this.model.addAnnotation(this.guideLineAnnotation_);}else{this.guideLineAnnotation_.timestamp=loc.xWorld;this.modelTrackContainer_.invalidate();}
+const state=new tr.ui.b.UIState(loc,this.viewport_.currentDisplayTransform.scaleX);this.timelineView_.setFindCtlText(state.toUserFriendlyString(this.viewport_));}.bind(this),undefined,function onKeyUpDuringDrag(){if(this.dragBeginEvent_){this.setDragBoxPosition_(this.dragBoxXStart_,this.dragBoxYStart_,this.dragBoxXEnd_,this.dragBoxYEnd_);}}.bind(this));},queueSmoothPan_(viewDeltaX,deltaY){const deltaX=this.viewport_.currentDisplayTransform.xViewVectorToWorld(viewDeltaX);const animation=new tr.ui.TimelineDisplayTransformPanAnimation(deltaX,deltaY);this.viewport_.queueDisplayTransformAnimation(animation);},zoomBy_(scale,smooth){if(scale<=0){return;}
+smooth=!!smooth;const vp=this.viewport_;const pixelRatio=window.devicePixelRatio||1;const goalFocalPointXView=this.lastMouseViewPos_.x*pixelRatio;const goalFocalPointXWorld=vp.currentDisplayTransform.xViewToWorld(goalFocalPointXView);if(smooth){const animation=new tr.ui.TimelineDisplayTransformZoomToAnimation(goalFocalPointXWorld,goalFocalPointXView,vp.currentDisplayTransform.panY,scale);vp.queueDisplayTransformAnimation(animation);}else{this.displayTransform_.set(vp.currentDisplayTransform);this.displayTransform_.scaleX*=scale;this.displayTransform_.xPanWorldPosToViewPos(goalFocalPointXWorld,goalFocalPointXView,this.viewWidth_);vp.setDisplayTransformImmediately(this.displayTransform_);}},zoomToSelection(){if(!this.brushingStateController.selectionOfInterest.length)return;const bounds=this.brushingStateController.selectionOfInterest.bounds;if(!bounds.range)return;const worldCenter=bounds.center;const viewCenter=this.modelTrackContainer_.canvas.width/2;const adjustedWorldRange=bounds.range*1.25;const newScale=this.modelTrackContainer_.canvas.width/adjustedWorldRange;const zoomInRatio=newScale/this.viewport_.currentDisplayTransform.scaleX;const animation=new tr.ui.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);},panToSelection(){if(!this.brushingStateController.selectionOfInterest.length)return;const bounds=this.brushingStateController.selectionOfInterest.bounds;const worldCenter=bounds.center;const viewWidth=this.viewWidth_;const dt=this.viewport_.currentDisplayTransform;if(false&&!bounds.range){if(dt.xWorldToView(bounds.center)<0||dt.xWorldToView(bounds.center)>viewWidth){this.displayTransform_.set(dt);this.displayTransform_.xPanWorldPosToViewPos(worldCenter,'center',viewWidth);const deltaX=this.displayTransform_.panX-dt.panX;const animation=new tr.ui.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);}
+return;}
+this.displayTransform_.set(dt);this.displayTransform_.xPanWorldBoundsIntoView(bounds.min,bounds.max,viewWidth);const deltaX=this.displayTransform_.panX-dt.panX;const animation=new tr.ui.TimelineDisplayTransformPanAnimation(deltaX,0);this.viewport_.queueDisplayTransformAnimation(animation);},navToPosition(uiState,showNavLine){const location=uiState.location;const scaleX=uiState.scaleX;const track=location.getContainingTrack(this.viewport_);const worldCenter=location.xWorld;const viewCenter=this.modelTrackContainer_.canvas.width/5;const zoomInRatio=scaleX/this.viewport_.currentDisplayTransform.scaleX;track.scrollIntoViewIfNeeded();const animation=new tr.ui.TimelineDisplayTransformZoomToAnimation(worldCenter,viewCenter,this.viewport_.currentDisplayTransform.panY,zoomInRatio);this.viewport_.queueDisplayTransformAnimation(animation);if(!showNavLine)return;if(this.xNavStringMarker_){this.model.removeAnnotation(this.xNavStringMarker_);}
+this.xNavStringMarker_=new tr.model.XMarkerAnnotation(worldCenter);this.model.addAnnotation(this.xNavStringMarker_);},selectPowerSamplesInCurrentTimeRange_(){const selectionBounds=this.brushingStateController_.selection.bounds;if(this.model.device.powerSeries&&!selectionBounds.empty){const events=this.model.device.powerSeries.getSamplesWithinRange(selectionBounds.min,selectionBounds.max);const selection=new tr.model.EventSet(events);this.brushingStateController_.changeSelectionFromTimeline(selection);}},setCurrentSelectionAsInterestRange_(){const selectionBounds=this.brushingStateController_.selection.bounds;if(selectionBounds.empty){this.viewport_.interestRange.reset();return;}
+if(this.viewport_.interestRange.min===selectionBounds.min&&this.viewport_.interestRange.max===selectionBounds.max){this.viewport_.interestRange.reset();}else{this.viewport_.interestRange.set(selectionBounds);}},toggleHighDetails_(){this.viewport_.highDetails=!this.viewport_.highDetails;},hideDragBox_(){this.$.drag_box.style.left='-1000px';this.$.drag_box.style.top='-1000px';this.$.drag_box.style.width=0;this.$.drag_box.style.height=0;},setDragBoxPosition_(xStart,yStart,xEnd,yEnd){const loY=Math.min(yStart,yEnd);const hiY=Math.max(yStart,yEnd);const loX=Math.min(xStart,xEnd);const hiX=Math.max(xStart,xEnd);const modelTrackRect=this.modelTrack_.getBoundingClientRect();const dragRect={left:loX,top:loY,width:hiX-loX,height:hiY-loY};dragRect.right=dragRect.left+dragRect.width;dragRect.bottom=dragRect.top+dragRect.height;const modelTrackContainerRect=this.modelTrackContainer_.getBoundingClientRect();const clipRect={left:modelTrackContainerRect.left,top:modelTrackContainerRect.top,right:modelTrackContainerRect.right,bottom:modelTrackContainerRect.bottom};const headingWidth=window.getComputedStyle(Polymer.dom(this).querySelector('tr-ui-b-heading')).width;const trackTitleWidth=parseInt(headingWidth);clipRect.left=clipRect.left+trackTitleWidth;const intersectRect_=function(r1,r2){if(r2.left>r1.right||r2.right<r1.left||r2.top>r1.bottom||r2.bottom<r1.top){return false;}
+const results={};results.left=Math.max(r1.left,r2.left);results.top=Math.max(r1.top,r2.top);results.right=Math.min(r1.right,r2.right);results.bottom=Math.min(r1.bottom,r2.bottom);results.width=results.right-results.left;results.height=results.bottom-results.top;return results;};const finalDragBox=intersectRect_(clipRect,dragRect);this.$.drag_box.style.left=finalDragBox.left+'px';this.$.drag_box.style.width=finalDragBox.width+'px';this.$.drag_box.style.top=finalDragBox.top+'px';this.$.drag_box.style.height=finalDragBox.height+'px';this.$.drag_box.style.whiteSpace='nowrap';const pixelRatio=window.devicePixelRatio||1;const canv=this.modelTrackContainer_.canvas;const dt=this.viewport_.currentDisplayTransform;const loWX=dt.xViewToWorld((loX-canv.offsetLeft)*pixelRatio);const hiWX=dt.xViewToWorld((hiX-canv.offsetLeft)*pixelRatio);Polymer.dom(this.$.drag_box).textContent=tr.b.Unit.byName.timeDurationInMs.format(hiWX-loWX);const e=new tr.b.Event('selectionChanging');e.loWX=loWX;e.hiWX=hiWX;this.dispatchEvent(e);},onGridToggle_(left){const selection=this.brushingStateController_.selection;const tb=left?selection.bounds.min:selection.bounds.max;if(this.viewport_.gridEnabled&&this.viewport_.gridSide===left&&this.viewport_.gridInitialTimebase===tb){this.viewport_.gridside=undefined;this.viewport_.gridEnabled=false;this.viewport_.gridInitialTimebase=undefined;return;}
+const numIntervalsSinceStart=Math.ceil((tb-this.model_.bounds.min)/this.viewport_.gridStep_);this.viewport_.gridEnabled=true;this.viewport_.gridSide=left;this.viewport_.gridInitialTimebase=tb;this.viewport_.gridTimebase=tb-
+(numIntervalsSinceStart+1)*this.viewport_.gridStep_;},storeLastMousePos_(e){this.lastMouseViewPos_=this.extractRelativeMousePosition_(e);},storeLastTouchPositions_(e){this.lastTouchViewPositions_=this.extractRelativeTouchPositions_(e);},extractRelativeMousePosition_(e){const canv=this.modelTrackContainer_.canvas;return{x:e.clientX-canv.offsetLeft,y:e.clientY-canv.offsetTop};},extractRelativeTouchPositions_(e){const canv=this.modelTrackContainer_.canvas;const touches=[];for(let i=0;i<e.touches.length;++i){touches.push({x:e.touches[i].clientX-canv.offsetLeft,y:e.touches[i].clientY-canv.offsetTop});}
+return touches;},storeInitialMouseDownPos_(e){const position=this.extractRelativeMousePosition_(e);this.mouseViewPosAtMouseDown_.x=position.x;this.mouseViewPosAtMouseDown_.y=position.y;},focusElements_(){this.$.hotkey_controller.childRequestsGeneralFocus(this);},storeInitialInteractionPositionsAndFocus_(e){this.storeInitialMouseDownPos_(e);this.storeLastMousePos_(e);this.focusElements_();},onBeginPanScan_(e){const vp=this.viewport_;this.viewportDisplayTransformAtMouseDown_=vp.currentDisplayTransform.clone();this.isPanningAndScanning_=true;this.storeInitialInteractionPositionsAndFocus_(e);e.preventDefault();},onUpdatePanScan_(e){if(!this.isPanningAndScanning_)return;const viewWidth=this.viewWidth_;const pixelRatio=window.devicePixelRatio||1;const xDeltaView=pixelRatio*(this.lastMouseViewPos_.x-
+this.mouseViewPosAtMouseDown_.x);const yDelta=this.lastMouseViewPos_.y-
+this.mouseViewPosAtMouseDown_.y;this.displayTransform_.set(this.viewportDisplayTransformAtMouseDown_);this.displayTransform_.incrementPanXInViewUnits(xDeltaView);this.displayTransform_.panY-=yDelta;this.viewport_.setDisplayTransformImmediately(this.displayTransform_);e.preventDefault();e.stopPropagation();this.storeLastMousePos_(e);},onEndPanScan_(e){this.isPanningAndScanning_=false;this.storeLastMousePos_(e);if(!e.isClick){e.preventDefault();}},onBeginSelection_(e){const canv=this.modelTrackContainer_.canvas;const rect=this.modelTrack_.getBoundingClientRect();const canvRect=canv.getBoundingClientRect();const inside=rect&&e.clientX>=rect.left&&e.clientX<rect.right&&e.clientY>=rect.top&&e.clientY<rect.bottom&&e.clientX>=canvRect.left&&e.clientX<canvRect.right;if(!inside)return;this.dragBeginEvent_=e;this.storeInitialInteractionPositionsAndFocus_(e);e.preventDefault();},onUpdateSelection_(e){if(!this.dragBeginEvent_)return;this.dragBoxXStart_=this.dragBeginEvent_.clientX;this.dragBoxXEnd_=e.clientX;this.dragBoxYStart_=this.dragBeginEvent_.clientY;this.dragBoxYEnd_=e.clientY;this.setDragBoxPosition_(this.dragBoxXStart_,this.dragBoxYStart_,this.dragBoxXEnd_,this.dragBoxYEnd_);},onEndSelection_(e){e.preventDefault();if(!this.dragBeginEvent_)return;this.hideDragBox_();const eDown=this.dragBeginEvent_;this.dragBeginEvent_=undefined;const loY=Math.min(eDown.clientY,e.clientY);const hiY=Math.max(eDown.clientY,e.clientY);const loX=Math.min(eDown.clientX,e.clientX);const hiX=Math.max(eDown.clientX,e.clientX);const canv=this.modelTrackContainer_.canvas;const worldOffset=canv.getBoundingClientRect().left;const loVX=loX-worldOffset;const hiVX=hiX-worldOffset;const selection=new tr.model.EventSet();if(eDown.appendSelection){const previousSelection=this.brushingStateController_.selection;if(previousSelection!==undefined){selection.addEventSet(previousSelection);}}
+this.modelTrack_.addIntersectingEventsInRangeToSelection(loVX,hiVX,loY,hiY,selection);this.brushingStateController_.changeSelectionFromTimeline(selection);},onBeginZoom_(e){this.isZooming_=true;this.storeInitialInteractionPositionsAndFocus_(e);e.preventDefault();},onUpdateZoom_(e){if(!this.isZooming_)return;const newPosition=this.extractRelativeMousePosition_(e);const zoomScaleValue=1+(this.lastMouseViewPos_.y-
+newPosition.y)*0.01;this.zoomBy_(zoomScaleValue,false);this.storeLastMousePos_(e);},onEndZoom_(e){this.isZooming_=false;if(!e.isClick){e.preventDefault();}},computeTouchCenter_(positions){let xSum=0;let ySum=0;for(let i=0;i<positions.length;++i){xSum+=positions[i].x;ySum+=positions[i].y;}
+return{x:xSum/positions.length,y:ySum/positions.length};},computeTouchSpan_(positions){let xMin=Number.MAX_VALUE;let yMin=Number.MAX_VALUE;let xMax=Number.MIN_VALUE;let yMax=Number.MIN_VALUE;for(let i=0;i<positions.length;++i){xMin=Math.min(xMin,positions[i].x);yMin=Math.min(yMin,positions[i].y);xMax=Math.max(xMax,positions[i].x);yMax=Math.max(yMax,positions[i].y);}
+return Math.sqrt((xMin-xMax)*(xMin-xMax)+
+(yMin-yMax)*(yMin-yMax));},onUpdateTransformForTouch_(e){const newPositions=this.extractRelativeTouchPositions_(e);const currentPositions=this.lastTouchViewPositions_;const newCenter=this.computeTouchCenter_(newPositions);const currentCenter=this.computeTouchCenter_(currentPositions);const newSpan=this.computeTouchSpan_(newPositions);const currentSpan=this.computeTouchSpan_(currentPositions);const vp=this.viewport_;const viewWidth=this.viewWidth_;const pixelRatio=window.devicePixelRatio||1;const xDelta=pixelRatio*(newCenter.x-currentCenter.x);const yDelta=newCenter.y-currentCenter.y;const zoomScaleValue=currentSpan>10?newSpan/currentSpan:1;const viewFocus=pixelRatio*newCenter.x;const worldFocus=vp.currentDisplayTransform.xViewToWorld(viewFocus);this.displayTransform_.set(vp.currentDisplayTransform);this.displayTransform_.scaleX*=zoomScaleValue;this.displayTransform_.xPanWorldPosToViewPos(worldFocus,viewFocus,viewWidth);this.displayTransform_.incrementPanXInViewUnits(xDelta);this.displayTransform_.panY-=yDelta;vp.setDisplayTransformImmediately(this.displayTransform_);this.storeLastTouchPositions_(e);},initHintText_(){this.$.hint_text.style.display='none';this.pendingHintTextClearTimeout_=undefined;},showHintText_(text){if(this.pendingHintTextClearTimeout_){window.clearTimeout(this.pendingHintTextClearTimeout_);this.pendingHintTextClearTimeout_=undefined;}
+this.pendingHintTextClearTimeout_=setTimeout(this.hideHintText_.bind(this),1000);Polymer.dom(this.$.hint_text).textContent=text;this.$.hint_text.style.display='';},hideHintText_(){this.pendingHintTextClearTimeout_=undefined;this.$.hint_text.style.display='none';}});'use strict';Polymer({is:'tr-ui-find-control',filterKeyDown(e){if(e.keyCode===27){const hkc=tr.b.getHotkeyControllerForElement(this);if(hkc){hkc.childRequestsBlur(this);}else{this.blur();}
+e.preventDefault();e.stopPropagation();return;}else if(e.keyCode===13){if(e.shiftKey){this.findPrevious();}else{this.findNext();}}},filterBlur(e){this.updateHitCountEl();},filterFocus(e){this.$.filter.select();},filterMouseUp(e){e.preventDefault();},get controller(){return this.controller_;},set controller(c){this.controller_=c;this.updateHitCountEl();},focus(){this.$.filter.focus();},get hasFocus(){return this===document.activeElement;},filterTextChanged(){Polymer.dom(this.$.hitCount).textContent='';this.$.spinner.style.visibility='visible';this.$.spinner.style.animation='spin 1s linear infinite';this.controller.startFiltering(this.$.filter.value).then(function(){this.$.spinner.style.visibility='hidden';this.$.spinner.style.animation='';this.updateHitCountEl();}.bind(this));},findNext(){if(this.controller){this.controller.findNext();}
+this.updateHitCountEl();},findPrevious(){if(this.controller){this.controller.findPrevious();}
+this.updateHitCountEl();},updateHitCountEl(){if(!this.controller||this.$.filter.value.length===0){Polymer.dom(this.$.hitCount).textContent='';return;}
+const n=this.controller.filterHits.length;const i=n===0?-1:this.controller.currentHitIndex;Polymer.dom(this.$.hitCount).textContent=(i+1)+' of '+n;},setText(string){this.$.filter.value=string;}});'use strict';tr.exportTo('tr.e.tquery',function(){function Context(){this.event=undefined;this.ancestors=[];}
+Context.prototype={push(event){const ctx=new Context();ctx.ancestors=this.ancestors.slice();ctx.ancestors.push(event);return ctx;},pop(event){const ctx=new Context();ctx.event=this.ancestors[this.ancestors.length-1];ctx.ancestors=this.ancestors.slice(0,this.ancestors.length-1);return ctx;}};return{Context,};});'use strict';tr.exportTo('tr.e.tquery',function(){function Filter(){tr.c.ScriptingObject.call(this);}
+Filter.normalizeFilterExpression=function(filterExpression){if(filterExpression instanceof String||typeof(filterExpression)==='string'||filterExpression instanceof RegExp){const filter=new tr.e.tquery.FilterHasTitle(filterExpression);return filter;}
+return filterExpression;};Filter.prototype={__proto__:tr.c.ScriptingObject.prototype,evaluate(context){throw new Error('Not implemented');},matchValue_(value,expected){if(expected instanceof RegExp){return expected.test(value);}else if(expected instanceof Function){return expected(value);}
+return value===expected;}};return{Filter,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterAllOf(opt_subExpressions){tr.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];}
+FilterAllOf.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(let i=0;i<exprs.length;i++){this.subExpressions_.push(tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate(context){if(!this.subExpressions.length)return true;for(let i=0;i<this.subExpressions.length;i++){if(!this.subExpressions[i].evaluate(context)){return false;}}
+return true;}};tr.c.ScriptingObjectRegistry.register(function(){const exprs=[];for(let i=0;i<arguments.length;i++){exprs.push(arguments[i]);}
+return new FilterAllOf(exprs);},{name:'allOf'});return{FilterAllOf,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterNot(subExpression){tr.e.tquery.Filter.call(this);this.subExpression=subExpression;}
+FilterNot.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tr.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate(context){return!this.subExpression.evaluate(context);}};tr.c.ScriptingObjectRegistry.register(function(){const exprs=Array.prototype.slice.call(arguments);if(exprs.length!==1){throw new Error('not() must have exactly one subexpression');}
+return new FilterNot(exprs[0]);},{name:'not'});return{FilterNot,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterAnyOf(opt_subExpressions){tr.e.tquery.Filter.call(this);this.subExpressions=opt_subExpressions||[];}
+FilterAnyOf.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpressions(exprs){this.subExpressions_=[];for(let i=0;i<exprs.length;i++){this.subExpressions_.push(tr.e.tquery.Filter.normalizeFilterExpression(exprs[i]));}},get subExpressions(){return this.subExpressions_;},evaluate(context){if(!this.subExpressions.length)return true;for(let i=0;i<this.subExpressions.length;i++){if(this.subExpressions[i].evaluate(context))return true;}
+return false;}};tr.c.ScriptingObjectRegistry.register(function(){const exprs=Array.prototype.slice.call(arguments);return new FilterAnyOf(exprs);},{name:'anyOf'});tr.c.ScriptingObjectRegistry.register(function(){const exprs=Array.prototype.slice.call(arguments);return new tr.e.tquery.FilterNot(new FilterAnyOf(exprs));},{name:'noneOf'});return{FilterAnyOf,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasAncestor(opt_subExpression){this.subExpression=opt_subExpression;}
+FilterHasAncestor.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tr.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate(context){if(!this.subExpression){return context.ancestors.length>0;}
+while(context.ancestors.length){context=context.pop();if(this.subExpression.evaluate(context))return true;}
+return false;}};tr.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterHasAncestor(subExpression);},{name:'hasAncestor'});return{FilterHasAncestor,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasDuration(minValueOrExpected,opt_maxValue){if(minValueOrExpected!==undefined&&opt_maxValue!==undefined){this.minValue=minValueOrExpected;this.maxValue=opt_maxValue;}else{this.expected=minValueOrExpected;}}
+FilterHasDuration.prototype={__proto__:tr.e.tquery.Filter.prototype,evaluate(context){if(context.event.duration===undefined)return false;if(this.minValue!==undefined&&this.maxValue!==undefined){return context.event.duration>=this.minValue&&context.event.duration<=this.maxValue;}
+return this.matchValue_(context.event.duration,this.expected);}};tr.c.ScriptingObjectRegistry.register(function(minValueOrExpected,opt_maxValue){return new FilterHasDuration(minValueOrExpected,opt_maxValue);},{name:'hasDuration'});return{FilterHasDuration,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterHasTitle(expected){tr.e.tquery.Filter.call(this);this.expected=expected;}
+FilterHasTitle.prototype={__proto__:tr.e.tquery.Filter.prototype,evaluate(context){return this.matchValue_(context.event.title,this.expected);}};tr.c.ScriptingObjectRegistry.register(function(expected){const filter=new tr.e.tquery.FilterHasTitle(expected);return filter;},{name:'hasTitle'});return{FilterHasTitle,};});'use strict';tr.exportTo('tr.e.tquery',function(){function FilterIsTopLevel(opt_subExpression){this.subExpression=opt_subExpression;}
+FilterIsTopLevel.prototype={__proto__:tr.e.tquery.Filter.prototype,set subExpression(expr){this.subExpression_=tr.e.tquery.Filter.normalizeFilterExpression(expr);},get subExpression(){return this.subExpression_;},evaluate(context){if(context.ancestors.length>0)return false;if(!this.subExpression)return true;return this.subExpression.evaluate(context);}};tr.c.ScriptingObjectRegistry.register(function(subExpression){return new FilterIsTopLevel(subExpression);},{name:'isTopLevel'});return{FilterIsTopLevel,};});'use strict';tr.exportTo('tr.e.tquery',function(){function addEventTreeToSelection(selection,event){selection.push(event);if(!event.subSlices)return;event.subSlices.forEach(addEventTreeToSelection.bind(undefined,selection));}
+function TQuery(model){tr.c.ScriptingObject.call(this);this.model_=model;this.parent_=undefined;this.filterExpression_=undefined;this.selection_=undefined;}
+TQuery.prototype={__proto__:tr.c.ScriptingObject.prototype,onModelChanged(model){this.model_=model;this.selection_=undefined;},get brushingStateController(){return this.brushingStateController_;},filter(filterExpression){const result=new TQuery(this.model_);result.parent_=this;result.filterExpression_=tr.e.tquery.Filter.normalizeFilterExpression(filterExpression);return result;},createFilterTaskGraph_(){const nodes=[this];while(nodes[nodes.length-1].parent_){nodes.push(nodes[nodes.length-1].parent_);}
+const rootTask=new tr.b.Task();let lastTask=rootTask;let node;for(let i=nodes.length-1;i>=0;i--){node=nodes[i];if(node.selection_!==undefined)continue;node.selection_=new tr.model.EventSet();if(node.parent_===undefined){lastTask=lastTask.after(this.selectEverythingAsTask_(node.selection_));}else{const prevNode=nodes[i+1];lastTask=this.createFilterTaskForNode_(lastTask,node,prevNode);}}
+return{rootTask,lastTask,lastNode:node};},createFilterTaskForNode_(lastTask,node,prevNode){return lastTask.after(function(){node.evaluateFilterExpression_(prevNode.selection_,node.selection_);},this);},evaluateFilterExpression_(inputSelection,outputSelection){const seenEvents={};inputSelection.forEach(function(event){const context=new tr.e.tquery.Context();context.event=event;this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}.bind(this));},evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents){const event=context.event;if(inputSelection.contains(event)&&!seenEvents[event.guid]){seenEvents[event.guid]=true;if(!this.filterExpression_||this.filterExpression_.evaluate(context)){outputSelection.push(event);}}
+if(!event.subSlices)return;context=context.push(event);for(let i=0;i<event.subSlices.length;i++){context.event=event.subSlices[i];this.evaluateFilterExpressionForEvent_(context,inputSelection,outputSelection,seenEvents);}},selectEverythingAsTask_(selection){const filterTask=new tr.b.Task();for(const container of this.model_.getDescendantEventContainers()){filterTask.subTask(()=>{for(const event of container.childEvents()){addEventTreeToSelection(selection,event);}},this);}
+return filterTask;},ready(){return new Promise(function(resolve,reject){const graph=this.createFilterTaskGraph_();graph.lastTask=graph.lastTask.after(function(){resolve(this.selection_);},this);tr.b.Task.RunWhenIdle(graph.rootTask);}.bind(this));},get selection(){if(this.selection_===undefined){const graph=this.createFilterTaskGraph_();tr.b.Task.RunSynchronously(graph.rootTask);}
+return this.selection_;}};tr.c.ScriptingObjectRegistry.register(new TQuery(),{name:'$t'});return{TQuery,};});'use strict';Polymer({is:'tr-ui-scripting-control',isEnterKey_(event){return event.keyCode!==229&&(event.key==='Enter'||event.keyIdentifier==='Enter');},setFocus_(focused){const promptEl=this.$.prompt;if(focused){promptEl.focus();Polymer.dom(this.$.root).classList.add('focused');if(promptEl.value.length>0){const sel=window.getSelection();sel.collapse(Polymer.dom(promptEl).firstChild,promptEl.value.length);}}else{promptEl.blur();Polymer.dom(this.$.root).classList.remove('focused');const parent=promptEl.parentElement;const nextEl=Polymer.dom(promptEl).nextSibling;promptEl.remove();Polymer.dom(parent).insertBefore(promptEl,nextEl);}},onConsoleFocus(e){e.stopPropagation();this.setFocus_(true);},onConsoleBlur(e){e.stopPropagation();this.setFocus_(false);},promptKeyDown(e){e.stopPropagation();if(!this.isEnterKey_(e))return;e.preventDefault();const promptEl=this.$.prompt;const command=promptEl.value;if(command.length===0)return;promptEl.value='';this.addLine_(String.fromCharCode(187)+' '+command);let result;try{result=this.controller_.executeCommand(command);}catch(e){result=e.stack||e.stackTrace;}
+if(result instanceof tr.e.tquery.TQuery){result.ready().then(function(selection){this.addLine_(selection.length+' matches');this.controller_.brushingStateController.showScriptControlSelection(selection);}.bind(this));}else{this.addLine_(result);}
+promptEl.scrollIntoView();},addLine_(line){const historyEl=this.$.history;if(historyEl.innerText.length!==0){historyEl.innerText+='\n';}
+historyEl.innerText+=line;},promptKeyPress(e){e.stopPropagation();},toggleVisibility(){const root=this.$.root;if(!this.visible){Polymer.dom(root).classList.remove('hidden');this.setFocus_(true);}else{Polymer.dom(root).classList.add('hidden');this.setFocus_(false);}},get hasFocus(){return this===document.activeElement;},get visible(){const root=this.$.root;return!Polymer.dom(root).classList.contains('hidden');},get controller(){return this.controller_;},set controller(c){this.controller_=c;}});'use strict';Polymer({is:'tr-ui-side-panel-container',ready(){this.activePanelContainer_=this.$.active_panel_container;this.tabStrip_=this.$.tab_strip;this.dragHandle_=this.$.side_panel_drag_handle;this.dragHandle_.horizontal=false;this.dragHandle_.target=this.activePanelContainer_;this.rangeOfInterest_=new tr.b.math.Range();this.brushingStateController_=undefined;this.onSelectionChanged_=this.onSelectionChanged_.bind(this);this.onModelChanged_=this.onModelChanged_.bind(this);},get brushingStateController(){return this.brushingStateController_;},set brushingStateController(brushingStateController){if(this.brushingStateController){this.brushingStateController_.removeEventListener('change',this.onSelectionChanged_);this.brushingStateController_.removeEventListener('model-changed',this.onModelChanged_);}
+this.brushingStateController_=brushingStateController;if(this.brushingStateController){this.brushingStateController_.addEventListener('change',this.onSelectionChanged_);this.brushingStateController_.addEventListener('model-changed',this.onModelChanged_);if(this.model){this.onModelChanged_();}}},onSelectionChanged_(){if(this.activePanel){this.activePanel.selection=this.selection;}},get model(){return this.brushingStateController_.model;},onModelChanged_(){this.activePanelType_=undefined;this.updateContents_();},get expanded(){this.hasAttribute('expanded');},get activePanel(){return this.activePanelContainer_.children[0];},get activePanelType(){return this.activePanelType_;},set activePanelType(panelType){if(this.model===undefined){throw new Error('Cannot activate panel without a model');}
+let panel=undefined;if(panelType){panel=document.createElement(panelType);}
+if(panel!==undefined&&!panel.supportsModel(this.model)){throw new Error('Cannot activate panel: does not support this model');}
+if(this.activePanelType){Polymer.dom(this.getLabelElementForPanelType_(this.activePanelType)).removeAttribute('selected');}
+if(this.activePanelType){this.getLabelElementForPanelType_(this.activePanelType).removeAttribute('selected');}
+if(this.activePanel){this.activePanelContainer_.removeChild(this.activePanel);}
+if(panelType===undefined){Polymer.dom(this).removeAttribute('expanded');this.activePanelType_=undefined;return;}
+Polymer.dom(this.getLabelElementForPanelType_(panelType)).setAttribute('selected',true);Polymer.dom(this).setAttribute('expanded',true);Polymer.dom(this.activePanelContainer_).appendChild(panel);panel.rangeOfInterest=this.rangeOfInterest_;panel.selection=this.selection_;panel.model=this.model;this.activePanelType_=panelType;},getPanelTypeForConstructor_(constructor){for(let i=0;i<this.tabStrip_.children.length;i++){if(this.tabStrip_.children[i].panelType.constructor===constructor){return this.tabStrip_.children[i].panelType;}}},getLabelElementForPanelType_(panelType){for(let i=0;i<this.tabStrip_.children.length;i++){if(this.tabStrip_.children[i].panelType===panelType){return this.tabStrip_.children[i];}}
+return undefined;},updateContents_(){const previouslyActivePanelType=this.activePanelType;Polymer.dom(this.tabStrip_).textContent='';const supportedPanelTypes=[];const panelTypeInfos=tr.ui.side_panel.SidePanelRegistry.getAllRegisteredTypeInfos();const unsupportedLabelEls=[];for(const panelTypeInfo of panelTypeInfos){const labelEl=document.createElement('tab-strip-label');const panel=panelTypeInfo.constructor();const panelType=panel.tagName;Polymer.dom(labelEl).textContent=panel.textLabel;labelEl.panelType=panelType;const supported=panel.supportsModel(this.model);if(this.model&&supported.supported){supportedPanelTypes.push(panelType);Polymer.dom(labelEl).setAttribute('enabled',true);labelEl.addEventListener('click',function(panelType){this.activePanelType=this.activePanelType===panelType?undefined:panelType;}.bind(this,panelType));Polymer.dom(this.tabStrip_).appendChild(labelEl);}else{if(this.activePanel){this.activePanelContainer_.removeChild(this.activePanel);}
+this.removeAttribute('expanded');unsupportedLabelEls.push(labelEl);}}
+for(const labelEl of unsupportedLabelEls){Polymer.dom(this.tabStrip_).appendChild(labelEl);}
+if(previouslyActivePanelType&&supportedPanelTypes.includes(previouslyActivePanelType)){this.activePanelType=previouslyActivePanelType;Polymer.dom(this).setAttribute('expanded',true);}else{if(this.activePanel){Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);}
+Polymer.dom(this).removeAttribute('expanded');}},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){if(range===undefined){throw new Error('Must not be undefined');}
+this.rangeOfInterest_=range;if(this.activePanel){this.activePanel.rangeOfInterest=range;}}});'use strict';Polymer({is:'tr-ui-timeline-view-help-overlay',ready(){const mod=tr.isMac?'cmd ':'ctrl';const spans=Polymer.dom(this.root).querySelectorAll('span.mod');for(let i=0;i<spans.length;i++){Polymer.dom(spans[i]).textContent=mod;}}});'use strict';Polymer({is:'tr-ui-timeline-view-metadata-overlay',created(){this.metadata_=undefined;},ready(){this.$.table.tableColumns=[{title:'name',value:d=>d.name,},{title:'value',value:d=>{const gov=document.createElement('tr-ui-a-generic-object-view');gov.object=d.value;return gov;},}];},get metadata(){return this.metadata_;},set metadata(metadata){this.metadata_=metadata;this.$.table.tableRows=this.metadata_;this.$.table.rebuild();}});'use strict';Polymer({is:'tr-v-ui-preferred-display-unit',ready(){this.preferredTimeDisplayMode_=undefined;},attached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},detached(){tr.b.Unit.didPreferredTimeDisplayUnitChange();},get preferredTimeDisplayMode(){return this.preferredTimeDisplayMode_;},set preferredTimeDisplayMode(v){if(this.preferredTimeDisplayMode_===v)return;this.preferredTimeDisplayMode_=v;tr.b.Unit.didPreferredTimeDisplayUnitChange();}});'use strict';const POLYFILL_WARNING_MESSAGE='Trace Viewer is running with WebComponentsV0 polyfill, and some '+'features may be broken. As a workaround, you may try running chrome '+'with "--enable-blink-features=ShadowDOMV0,CustomElementsV0,HTMLImports" '+'flag. See crbug.com/1036492.';Polymer({is:'tr-ui-timeline-view',created(){this.trackViewContainer_=undefined;this.queuedModel_=undefined;this.builtPromise_=undefined;this.doneBuilding_=undefined;},attached(){this.async(function(){this.trackViewContainer_=Polymer.dom(this).querySelector('#track_view_container');if(!this.trackViewContainer_){throw new Error('missing trackviewContainer');}
+if(this.queuedModel_)this.updateContents_();});},ready(){this.tabIndex=0;this.polyfillWarnedOnce_=false;this.titleEl_=this.$.title;this.leftControlsEl_=this.$.left_controls;this.rightControlsEl_=this.$.right_controls;this.collapsingControlsEl_=this.$.collapsing_controls;this.sidePanelContainer_=this.$.side_panel_container;this.brushingStateController_=new tr.c.BrushingStateController(this);this.findCtl_=this.$.view_find_control;this.findCtl_.controller=new tr.ui.FindController(this.brushingStateController_);this.scriptingCtl_=document.createElement('tr-ui-scripting-control');this.scriptingCtl_.controller=new tr.c.ScriptingController(this.brushingStateController_);this.sidePanelContainer_.brushingStateController=this.brushingStateController_;if(window.tr.metrics&&window.tr.metrics.sh&&window.tr.metrics.sh.SystemHealthMetric){this.railScoreSpan_=document.createElement('tr-metrics-ui-sh-system-health-span');Polymer.dom(this.rightControls).appendChild(this.railScoreSpan_);}else{this.railScoreSpan_=undefined;}
+this.flowEventFilter_=this.$.flow_event_filter_dropdown;this.processFilter_=this.$.process_filter_dropdown;this.optionsDropdown_=this.$.view_options_dropdown;this.selectedFlowEvents_=new Set();this.highlightVSync_=false;this.highlightVSyncCheckbox_=tr.ui.b.createCheckBox(this,'highlightVSync','tr.ui.TimelineView.highlightVSync',false,'Highlight VSync');Polymer.dom(this.optionsDropdown_).appendChild(this.highlightVSyncCheckbox_);this.initMetadataButton_();this.initConsoleButton_();this.initHelpButton_();Polymer.dom(this.collapsingControls).appendChild(this.scriptingCtl_);this.dragEl_=this.$.drag_handle;this.analysisEl_=this.$.analysis;this.analysisEl_.brushingStateController=this.brushingStateController_;this.addEventListener('requestSelectionChange',function(e){const sc=this.brushingStateController_;sc.changeSelectionFromRequestSelectionChangeEvent(e.selection);}.bind(this));this.onViewportChanged_=this.onViewportChanged_.bind(this);this.bindKeyListeners_();this.dragEl_.target=this.analysisEl_;},get globalMode(){return this.hotkeyController.globalMode;},set globalMode(globalMode){globalMode=!!globalMode;this.brushingStateController_.historyEnabled=globalMode;this.hotkeyController.globalMode=globalMode;},get hotkeyController(){return this.$.hkc;},warnPolyfill(){if(this.polyfillWarnedOnce_)return;console.warn(POLYFILL_WARNING_MESSAGE);this.polyfillWarnedOnce_=true;if(!window.__hideTraceViewerPolyfillWarning){const polyfillWarningsEl=Polymer.dom(this.root).querySelector('#polyfill-warning');polyfillWarningsEl.addMessage(POLYFILL_WARNING_MESSAGE,[{buttonText:'Hide',onClick:()=>polyfillWarningsEl.clearMessages()}]);}},updateDocumentFavicon(){let hue;if(!this.model){hue='blue';}else{hue=this.model.faviconHue;}
+let faviconData=tr.ui.b.FaviconsByHue[hue];if(faviconData===undefined){faviconData=tr.ui.b.FaviconsByHue.blue;}
+let link=Polymer.dom(document.head).querySelector('link[rel="shortcut icon"]');if(!link){link=document.createElement('link');link.rel='shortcut icon';Polymer.dom(document.head).appendChild(link);}
+link.href=faviconData;},get selectedFlowEvents(){return this.selectedFlowEvents_;},set selectedFlowEvents(selectedFlowEvents){this.selectedFlowEvents_=selectedFlowEvents;},get highlightVSync(){return this.highlightVSync_;},set highlightVSync(highlightVSync){this.highlightVSync_=highlightVSync;if(!this.trackView_)return;this.trackView_.viewport.highlightVSync=highlightVSync;},initHelpButton_(){const helpButtonEl=this.$.view_help_button;const dlg=new tr.ui.b.Overlay();dlg.title='Chrome Tracing Help';dlg.visible=false;dlg.appendChild(document.createElement('tr-ui-timeline-view-help-overlay'));function onClick(e){dlg.visible=!dlg.visible;e.stopPropagation();}
+helpButtonEl.addEventListener('click',onClick.bind(this));},initConsoleButton_(){const toggleEl=this.$.view_console_button;function onClick(e){this.scriptingCtl_.toggleVisibility();e.stopPropagation();return false;}
+toggleEl.addEventListener('click',onClick.bind(this));},initMetadataButton_(){const showEl=this.$.view_metadata_button;function onClick(e){const dlg=new tr.ui.b.Overlay();dlg.title='Metadata for trace';const metadataOverlay=document.createElement('tr-ui-timeline-view-metadata-overlay');metadataOverlay.metadata=this.model.metadata;Polymer.dom(dlg).appendChild(metadataOverlay);dlg.visible=true;e.stopPropagation();return false;}
+showEl.addEventListener('click',onClick.bind(this));this.updateMetadataButtonVisibility_();},updateMetadataButtonVisibility_(){const showEl=this.$.view_metadata_button;showEl.style.display=(this.model&&this.model.metadata.length)?'':'none';},updateFlowEventList_(){const dropdown=Polymer.dom(this.flowEventFilter_);while(dropdown.firstChild){dropdown.removeChild(dropdown.firstChild);}
+if(!this.model)return;const cboxes=[];const updateAll=(checked)=>{for(const cbox of cboxes){cbox.checked=checked;}};dropdown.appendChild(tr.ui.b.createButton('All',()=>updateAll(true)));dropdown.appendChild(tr.ui.b.createButton('None',()=>updateAll(false)));const categories=new Set();for(const event of this.model.flowEvents){for(const category of tr.b.getCategoryParts(event.category)){categories.add(category);}}
+const sortedCategories=[...categories].sort((a,b)=>a.localeCompare(b,'en',{sensitivity:'base'}));for(const category of sortedCategories){const cbox=tr.ui.b.createCheckBox(undefined,undefined,'tr.ui.TimelineView.selectedFlowEvents.'+category,false,category,()=>{if(cbox.checked){this.selectedFlowEvents.add(category);}else{this.selectedFlowEvents.delete(category);}
+if(this.trackView_){this.trackView_.viewport.dispatchChangeEvent();}});if(cbox.checked){this.selectedFlowEvents.add(category);}
+cboxes.push(cbox);dropdown.appendChild(cbox);}},updateProcessList_(){const dropdown=Polymer.dom(this.processFilter_);while(dropdown.firstChild){dropdown.removeChild(dropdown.firstChild);}
+if(!this.model)return;const trackView=this.trackViewContainer_.querySelector('tr-ui-timeline-track-view');const processViews=trackView.processViews;const cboxes=[];const updateAll=(checked)=>{for(const cbox of cboxes){cbox.checked=checked;}};dropdown.appendChild(tr.ui.b.createButton('All',()=>updateAll(true)));dropdown.appendChild(tr.ui.b.createButton('None',()=>updateAll(false)));for(const view of processViews){const cbox=tr.ui.b.createCheckBox(undefined,undefined,undefined,true,view.processBase.userFriendlyName,()=>view.visible=cbox.checked);cbox.checked=view.visible;cboxes.push(cbox);view.addEventListener('visibility',()=>cbox.checked=view.visible);dropdown.appendChild(cbox);}},get leftControls(){return this.leftControlsEl_;},get rightControls(){return this.rightControlsEl_;},get collapsingControls(){return this.collapsingControlsEl_;},get viewTitle(){return Polymer.dom(this.titleEl_).textContent.substring(Polymer.dom(this.titleEl_).textContent.length-2);},set viewTitle(text){if(text===undefined){Polymer.dom(this.titleEl_).textContent='';this.titleEl_.hidden=true;return;}
+this.titleEl_.hidden=false;Polymer.dom(this.titleEl_).textContent=text;},get model(){if(this.trackView_){return this.trackView_.model;}
+return undefined;},set model(model){this.build(model);},async build(model){this.queuedModel_=model;this.builtPromise_=new Promise((resolve,reject)=>{this.doneBuilding_=resolve;});if(this.trackViewContainer_)await this.updateContents_();},get builtPromise(){return this.builtPromise_;},async updateContents_(){if(this.trackViewContainer_===undefined){throw new Error('timeline-view.updateContents_ requires trackViewContainer_');}
+const model=this.queuedModel_;this.queuedModel_=undefined;const modelInstanceChanged=model!==this.model;const modelValid=model&&!model.bounds.isEmpty;const importWarningsEl=Polymer.dom(this.root).querySelector('#import-warnings');Polymer.dom(importWarningsEl).textContent='';if(modelInstanceChanged){if(this.railScoreSpan_){this.railScoreSpan_.model=undefined;}
+Polymer.dom(this.trackViewContainer_).textContent='';if(this.trackView_){this.trackView_.viewport.removeEventListener('change',this.onViewportChanged_);this.trackView_.brushingStateController=undefined;this.trackView_.detach();this.trackView_=undefined;}
+this.brushingStateController_.modelWillChange();}
+if(modelValid&&!this.trackView_){this.trackView_=document.createElement('tr-ui-timeline-track-view');this.trackView_.timelineView=this;this.trackView.brushingStateController=this.brushingStateController_;Polymer.dom(this.trackViewContainer_).appendChild(this.trackView_);this.trackView_.viewport.addEventListener('change',this.onViewportChanged_);}
+if(modelValid){this.trackView_.model=model;this.trackView_.viewport.selectedFlowEvents=this.selectedFlowEvents;this.trackView_.viewport.highlightVSync=this.highlightVSync;if(this.railScoreSpan_){this.railScoreSpan_.model=model;}
+this.$.display_unit.preferredTimeDisplayMode=model.intrinsicTimeUnit;}
+if(window.CustomElements&&!window.CustomElements.hasNative){this.warnPolyfill();}
+if(model){for(const warning of model.importWarningsThatShouldBeShownToUser){importWarningsEl.addMessage(`Import Warning: ${warning.type}: ${warning.message}`,[{buttonText:'Dismiss',onClick(event,infobar){infobar.visible=false;}}]);}}
+if(modelInstanceChanged){this.updateFlowEventList_();this.updateProcessList_();this.updateMetadataButtonVisibility_();this.brushingStateController_.modelDidChange();this.onViewportChanged_();}
+this.doneBuilding_();},get brushingStateController(){return this.brushingStateController_;},get trackView(){return this.trackView_;},get settings(){if(!this.settings_){this.settings_=new tr.b.Settings();}
+return this.settings_;},set focusElement(value){throw new Error('This is deprecated. Please set globalMode to true.');},bindKeyListeners_(){const hkc=this.hotkeyController;hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'`'.charCodeAt(0),useCapture:true,thisArg:this,callback(e){this.scriptingCtl_.toggleVisibility();if(!this.scriptingCtl_.hasFocus){this.focus();}
+e.stopPropagation();}}));hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'/'.charCodeAt(0),useCapture:true,thisArg:this,callback(e){if(this.scriptingCtl_.hasFocus)return;if(this.findCtl_.hasFocus){this.focus();}else{this.findCtl_.focus();}
+e.preventDefault();e.stopPropagation();}}));hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'?'.charCodeAt(0),useCapture:false,thisArg:this,callback(e){this.$.view_help_button.click();e.stopPropagation();}}));hkc.addHotKey(new tr.ui.b.HotKey({eventType:'keypress',keyCode:'v'.charCodeAt(0),useCapture:false,thisArg:this,callback(e){this.toggleHighlightVSync_();e.stopPropagation();}}));},onViewportChanged_(e){const spc=this.sidePanelContainer_;if(!this.trackView_){spc.rangeOfInterest.reset();return;}
+const vr=this.trackView_.viewport.interestRange.asRangeObject();if(!spc.rangeOfInterest.equals(vr)){spc.rangeOfInterest=vr;}
+if(this.railScoreSpan_&&this.model){this.railScoreSpan_.model=this.model;}},toggleHighlightVSync_(){this.highlightVSyncCheckbox_.checked=!this.highlightVSyncCheckbox_.checked;},setFindCtlText(string){this.findCtl_.setText(string);}});'use strict';tr.exportTo('tr.ui.b',function(){function Row(title,data,groupingKeyFuncs,rowStatsConstructor){this.title=title;this.data_=data;if(groupingKeyFuncs===undefined){groupingKeyFuncs=[];}
+this.groupingKeyFuncs_=groupingKeyFuncs;this.rowStatsConstructor_=rowStatsConstructor;this.subRowsBuilt_=false;this.subRows_=undefined;this.rowStats_=undefined;}
+Row.prototype={getCurrentGroupingKeyFunc_(){if(this.groupingKeyFuncs_.length===0)return undefined;return this.groupingKeyFuncs_[0];},get data(){return this.data_;},get rowStats(){if(this.rowStats_===undefined){this.rowStats_=new this.rowStatsConstructor_(this);}
+return this.rowStats_;},rebuildSubRowsIfNeeded_(){if(this.subRowsBuilt_)return;this.subRowsBuilt_=true;const groupingKeyFunc=this.getCurrentGroupingKeyFunc_();if(groupingKeyFunc===undefined){this.subRows_=undefined;return;}
+const dataByKey={};let hasValues=false;this.data_.forEach(function(datum){const key=groupingKeyFunc(datum);hasValues=hasValues||(key!==undefined);if(dataByKey[key]===undefined){dataByKey[key]=[];}
+dataByKey[key].push(datum);});if(!hasValues){this.subRows_=undefined;return;}
+this.subRows_=[];for(const key in dataByKey){const row=new Row(key,dataByKey[key],this.groupingKeyFuncs_.slice(1),this.rowStatsConstructor_);this.subRows_.push(row);}},get isExpanded(){return(this.subRows&&(this.subRows.length>0)&&(this.subRows.length<5));},get subRows(){this.rebuildSubRowsIfNeeded_();return this.subRows_;}};Polymer({is:'tr-ui-b-grouping-table',created(){this.dataToGroup_=undefined;this.groupBy_=undefined;this.rowStatsConstructor_=undefined;},get tableColumns(){return this.$.table.tableColumns;},set tableColumns(tableColumns){this.$.table.tableColumns=tableColumns;},get tableRows(){return this.$.table.tableRows;},get sortColumnIndex(){return this.$.table.sortColumnIndex;},set sortColumnIndex(sortColumnIndex){this.$.table.sortColumnIndex=sortColumnIndex;},get sortDescending(){return this.$.table.sortDescending;},set sortDescending(sortDescending){this.$.table.sortDescending=sortDescending;},get selectionMode(){return this.$.table.selectionMode;},set selectionMode(selectionMode){this.$.table.selectionMode=selectionMode;},get rowHighlightStyle(){return this.$.table.rowHighlightStyle;},set rowHighlightStyle(rowHighlightStyle){this.$.table.rowHighlightStyle=rowHighlightStyle;},get cellHighlightStyle(){return this.$.table.cellHighlightStyle;},set cellHighlightStyle(cellHighlightStyle){this.$.table.cellHighlightStyle=cellHighlightStyle;},get selectedColumnIndex(){return this.$.table.selectedColumnIndex;},set selectedColumnIndex(selectedColumnIndex){this.$.table.selectedColumnIndex=selectedColumnIndex;},get selectedTableRow(){return this.$.table.selectedTableRow;},set selectedTableRow(selectedTableRow){this.$.table.selectedTableRow=selectedTableRow;},get groupBy(){return this.groupBy_;},set groupBy(groupBy){this.groupBy_=groupBy;this.updateContents_();},get dataToGroup(){return this.dataToGroup_;},set dataToGroup(dataToGroup){this.dataToGroup_=dataToGroup;this.updateContents_();},get rowStatsConstructor(){return this.rowStatsConstructor_;},set rowStatsConstructor(rowStatsConstructor){this.rowStatsConstructor_=rowStatsConstructor;this.updateContents_();},rebuild(){this.$.table.rebuild();},updateContents_(){const groupBy=this.groupBy_||[];const dataToGroup=this.dataToGroup_||[];const rowStatsConstructor=this.rowStatsConstructor_||function(){};const superRow=new Row('',dataToGroup,groupBy,rowStatsConstructor);this.$.table.tableRows=superRow.subRows||[];}});return{};});'use strict';tr.exportTo('tr.ui.b',function(){const THIS_DOC=document.currentScript.ownerDocument;Polymer({is:'tr-ui-b-grouping-table-groupby-picker-group',created(){this.picker_=undefined;this.group_=undefined;},get picker(){return this.picker_;},set picker(picker){this.picker_=picker;},get group(){return this.group_;},set group(g){this.group_=g;this.$.label.textContent=g.label;},get enabled(){return this.$.enabled.checked;},set enabled(enabled){this.$.enabled.checked=enabled;if(!this.enabled){this.$.left.style.display='none';this.$.right.style.display='none';}},set isFirst(isFirst){this.$.left.style.display=(!this.enabled||isFirst)?'none':'inline';},set isLast(isLast){this.$.right.style.display=(!this.enabled||isLast)?'none':'inline';},moveLeft_(){this.picker.moveLeft_(this);},moveRight_(){this.picker.moveRight_(this);},onEnableChanged_(){if(!this.enabled){this.$.left.style.display='none';this.$.right.style.display='none';}
+this.picker.onEnableChanged_(this);}});Polymer({is:'tr-ui-b-grouping-table-groupby-picker',created(){this.settingsKey_=undefined;},get settingsKey(){return this.settingsKey_;},set settingsKey(settingsKey){this.settingsKey_=settingsKey;if(this.$.container.children.length){this.restoreSetting_();}},restoreSetting_(){if(this.settingsKey_===undefined)return;this.currentGroupKeys=tr.b.Settings.get(this.settingsKey_,this.currentGroupKeys);},get possibleGroups(){return Array.from(this.$.container.children).map(groupEl=>groupEl.group);},set possibleGroups(possibleGroups){Polymer.dom(this.$.container).textContent='';for(let i=0;i<possibleGroups.length;++i){const groupEl=document.createElement('tr-ui-b-grouping-table-groupby-picker-group');groupEl.picker=this;groupEl.group=possibleGroups[i];Polymer.dom(this.$.container).appendChild(groupEl);}
+this.restoreSetting_();this.updateFirstLast_();},updateFirstLast_(){const groupEls=Array.from(this.$.container.children);const enabledGroupEls=groupEls.filter(el=>el.enabled);for(let i=0;i<enabledGroupEls.length;++i){enabledGroupEls[i].isFirst=i===0;enabledGroupEls[i].isLast=i===enabledGroupEls.length-1;}},get currentGroupKeys(){return this.currentGroups.map(group=>group.key);},get currentGroups(){const groups=[];for(const groupEl of Array.from(this.$.container.children)){if(groupEl.enabled){groups.push(groupEl.group);}}
+return groups;},set currentGroupKeys(newKeys){if(!tr.b.compareArrays(this.currentGroupKeys,newKeys,(x,y)=>x.localeCompare(y))){return;}
+const possibleGroups=new Map();for(const group of this.possibleGroups){possibleGroups.set(group.key,group);}
+const groupEls=this.$.container.children;let i=0;for(i=0;i<newKeys.length;++i){const group=possibleGroups.get(newKeys[i]);if(group===undefined){newKeys.splice(i,1);--i;continue;}
+groupEls[i].group=group;groupEls[i].enabled=true;possibleGroups.delete(newKeys[i]);}
+for(const group of possibleGroups.values()){groupEls[i].group=group;groupEls[i].enabled=false;++i;}
+this.updateFirstLast_();this.onCurrentGroupsChanged_();},moveLeft_(groupEl){const reference=groupEl.previousSibling;Polymer.dom(this.$.container).removeChild(groupEl);Polymer.dom(this.$.container).insertBefore(groupEl,reference);this.updateFirstLast_();if(groupEl.enabled){this.onCurrentGroupsChanged_();}},moveRight_(groupEl){const reference=groupEl.nextSibling.nextSibling;Polymer.dom(this.$.container).removeChild(groupEl);if(reference){Polymer.dom(this.$.container).insertBefore(groupEl,reference);}else{Polymer.dom(this.$.container).appendChild(groupEl);}
+this.updateFirstLast_();if(groupEl.enabled){this.onCurrentGroupsChanged_();}},onCurrentGroupsChanged_(){this.dispatchEvent(new tr.b.Event('current-groups-changed'));tr.b.Settings.set(this.settingsKey_,this.currentGroupKeys);},onEnableChanged_(groupEl){this.updateFirstLast_();this.onCurrentGroupsChanged_();}});return{};});'use strict';(function(){Polymer({is:'tr-ui-sp-file-size-stats-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.selection_=new tr.model.EventSet();this.$.picker.settingsKey='tr-ui-sp-file-size-stats-side-panel-picker';this.$.picker.possibleGroups=[{key:'phase',label:'Event Type',dataFn(eventStat){return eventStat.phase;}},{key:'category',label:'Category',dataFn(eventStat){return eventStat.category;}},{key:'title',label:'Title',dataFn(eventStat){return eventStat.title;}}];if(this.$.picker.currentGroupKeys.length===0){this.$.picker.currentGroupKeys=['phase','title'];}
+this.$.picker.addEventListener('current-groups-changed',this.updateContents_.bind(this));},get textLabel(){return'File Size Stats';},supportsModel(m){if(!m){return{supported:false,reason:'No stats were collected for this file.'};}
+if(m.stats.allTraceEventStats.length===0){return{supported:false,reason:'No stats were collected for this file.'};}
+return{supported:true};},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(rangeOfInterest){this.rangeOfInterest_=rangeOfInterest;},get selection(){return this.selection_;},set selection(selection){this.selection_=selection;},createColumns_(stats){const columns=[{title:'Title',value(row){const titleEl=document.createElement('span');Polymer.dom(titleEl).textContent=row.title;titleEl.style.textOverflow='ellipsis';return titleEl;},cmp(a,b){return a.title.localeCompare(b.title);},width:'400px'},{title:'Num Events',align:tr.ui.b.TableFormat.ColumnAlignment.RIGHT,value(row){return row.rowStats.numEvents;},cmp(a,b){return a.rowStats.numEvents-b.rowStats.numEvents;},width:'80px'}];if(stats&&stats.hasEventSizesinBytes){columns.push({title:'Bytes',value(row){const value=new tr.b.Scalar(tr.b.Unit.byName.sizeInBytes,row.rowStats.totalEventSizeinBytes);const spanEl=tr.v.ui.createScalarSpan(value);return spanEl;},cmp(a,b){return a.rowStats.totalEventSizeinBytes-
+b.rowStats.totalEventSizeinBytes;},width:'80px'});}
+return columns;},updateContents_(){const table=this.$.table;const columns=this.createColumns_(this.model.stats);table.rowStatsConstructor=function ModelStatsRowStats(row){const sum=tr.b.math.Statistics.sum(row.data,function(x){return x.numEvents;});const totalEventSizeinBytes=tr.b.math.Statistics.sum(row.data,x=>x.totalEventSizeinBytes);return{numEvents:sum,totalEventSizeinBytes};};table.tableColumns=columns;table.sortColumnIndex=1;table.sortDescending=true;table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;table.groupBy=this.$.picker.currentGroups.map(function(group){return group.dataFn;});if(!this.model){table.dataToGroup=[];}else{table.dataToGroup=this.model.stats.allTraceEventStats;}
+this.$.table.rebuild();}});tr.ui.side_panel.SidePanelRegistry.register(function(){return document.createElement('tr-ui-sp-file-size-stats-side-panel');});})();'use strict';tr.exportTo('tr.mre',function(){function Failure(job,functionHandleString,traceCanonicalUrl,failureTypeName,description,stack){this.job=job;this.functionHandleString=functionHandleString;this.traceCanonicalUrl=traceCanonicalUrl;this.failureTypeName=failureTypeName;this.description=description;this.stack=stack;}
+Failure.prototype={asDict(){return{function_handle_string:this.functionHandleString,trace_canonical_url:this.traceCanonicalUrl,type:this.failureTypeName,description:this.description,stack:this.stack};}};Failure.fromDict=function(failureDict){return new Failure(undefined,failureDict.function_handle_string,failureDict.trace_canonical_url,failureDict.type,failureDict.description,failureDict.stack);};return{Failure,};});'use strict';tr.exportTo('tr.mre',function(){const FunctionRegistry={allFunctions_:[],allFunctionsByName_:{},get allFunctions(){return this.allFunctions_;},get allFunctionsByName(){return this.allFunctionsByName_;}};FunctionRegistry.getFunction=function(name){return this.allFunctionsByName_[name];};FunctionRegistry.register=function(func){if(func.name===''){throw new Error('Registered functions must not be anonymous');}
+if(this.allFunctionsByName[func.name]!==undefined){throw new Error('Function named '+func.name+'is already registered.');}
+this.allFunctionsByName[func.name]=func;this.allFunctions.push(func);};function ModuleToLoad(href,filename){if((href!==undefined)?(filename!==undefined):(filename===undefined)){throw new Error('ModuleToLoad must specify exactly one of href or '+'filename');}
+this.href=href;this.filename=filename;}
+ModuleToLoad.prototype={asDict(){if(this.href!==undefined){return{'href':this.href};}
+return{'filename':this.filename};},toString(){if(this.href!==undefined){return'ModuleToLoad(href="'+this.href+'")';}
+return'ModuleToLoad(filename="'+this.filename+'")';}};ModuleToLoad.fromDict=function(moduleDict){return new ModuleToLoad(moduleDict.href,moduleDict.filename);};function FunctionHandle(modulesToLoad,functionName,opt_options){if(!(modulesToLoad instanceof Array)){throw new Error('modulesToLoad in FunctionHandle must be an array');}
+if(typeof(functionName)!=='string'){throw new Error('functionName in FunctionHandle must be a string');}
+this.modulesToLoad=modulesToLoad;this.functionName=functionName;this.options_=opt_options;}
+FunctionHandle.prototype={get options(){return this.options_;},asDict(){return{'modules_to_load':this.modulesToLoad.map(function(m){return m.asDict();}),'function_name':this.functionName,'options':this.options_};},asUserFriendlyString(){const parts=this.modulesToLoad.map(mtl=>mtl.filename);parts.push(this.functionName);parts.push(JSON.stringify(this.options_));return parts.join(',');},hasHrefs(){for(const module in this.modulesToLoad){if(this.modulesToLoad[module].href!==undefined){return true;}}
+return false;},load(){if(this.hasHrefs()){const err=new Error('FunctionHandle named '+this.functionName+' specifies hrefs, which cannot be loaded.');err.name='FunctionLoadingError';throw err;}
+for(const module in this.modulesToLoad){const filename=this.modulesToLoad[module].filename;try{HTMLImportsLoader.loadHTMLFile(filename);}catch(err){err.name='FunctionLoadingError';throw err;}}
+const func=FunctionRegistry.getFunction(this.functionName);if(func===undefined){const err=new Error('No registered function named '+this.functionName);err.name='FunctionNotDefinedError';throw err;}
+return func;},toString(){const modulesToLoadStr=this.modulesToLoad.map(function(module){return module.toString();});return'FunctionHandle(modulesToLoad=['+modulesToLoadStr+'], '+'functionName="'+this.functionName+'", options="'+
+JSON.stringify(this.options_)+'")';}};FunctionHandle.loadFromFilename_=function(filename){try{const numFunctionsBefore=FunctionRegistry.allFunctions.length;HTMLImportsLoader.loadHTMLFile(filename);}catch(err){err.name='FunctionLoadingError';throw err;}
+const numFunctionsNow=FunctionRegistry.allFunctions.length;if(numFunctionsNow!==(numFunctionsBefore+1)){const err=new Error(filename+' didn\'t call FunctionRegistry.register');err.name='FunctionNotDefinedError';throw err;}
+return FunctionRegistry.allFunctions[numFunctionsNow-1];};FunctionHandle.fromDict=function(handleDict){const options=handleDict.options;let modulesToLoad;if(handleDict.modules_to_load!==undefined){modulesToLoad=handleDict.modules_to_load.map(function(module){return ModuleToLoad.fromDict(module);});}
+return new FunctionHandle(modulesToLoad,handleDict.function_name,options);};return{FunctionHandle,ModuleToLoad,FunctionRegistry,};});'use strict';tr.exportTo('tr.metrics',function(){function runMetrics(model,options,addFailureCb){if(options===undefined){throw new Error('Options are required.');}
+const metricNames=options.metrics;if(!metricNames){throw new Error('Metric names should be specified.');}
+const allMetricsStart=new Date();const durationBreakdown=new tr.v.d.Breakdown();const categories=getTraceCategories(model);const histograms=new tr.v.HistogramSet();histograms.createHistogram('trace_import_duration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,model.stats.traceImportDurationMs,{binBoundaries:tr.v.HistogramBinBoundaries.createExponential(1e-3,1e5,30),description:'Duration that trace viewer required to import the trace',summaryOptions:tr.v.Histogram.AVERAGE_ONLY_SUMMARY_OPTIONS,});for(const metricName of metricNames){const metricStart=new Date();const metric=tr.metrics.MetricRegistry.findTypeInfoWithName(metricName);if(metric===undefined){throw new Error(`"${metricName}" is not a registered metric.`);}
+validateTraceCategories(metric.metadata.requiredCategories,categories);try{metric.constructor(histograms,model,options);}catch(e){const err=tr.b.normalizeException(e);addFailureCb(new tr.mre.Failure(undefined,'metricMapFunction',model.canonicalUrl,err.typeName,err.message,err.stack));}
+const metricMs=new Date()-metricStart;histograms.createHistogram(metricName+'_duration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[metricMs]);durationBreakdown.set(metricName,metricMs);}
+validateDiagnosticNames(histograms);const allMetricsMs=new Date()-allMetricsStart+
+model.stats.traceImportDurationMs;durationBreakdown.set('traceImport',model.stats.traceImportDurationMs);durationBreakdown.set('other',allMetricsMs-tr.b.math.Statistics.sum(durationBreakdown,([metricName,metricMs])=>metricMs));const breakdownNames=tr.v.d.RelatedNameMap.fromEntries(new Map(metricNames.map(metricName=>[metricName,metricName+'_duration'])));breakdownNames.set('traceImport','trace_import_duration');histograms.createHistogram('metrics_duration',tr.b.Unit.byName.timeDurationInMs_smallerIsBetter,[{value:allMetricsMs,diagnostics:{breakdown:durationBreakdown},},],{diagnostics:{breakdown:breakdownNames},});return histograms;}
+function getTraceCategories(model){for(const metadata of model.metadata){let config;if(metadata.name==='TraceConfig'&&metadata.value){config=metadata.value;}
+if(metadata.name==='metadata'&&metadata.value&&metadata.value['trace-config']&&metadata.value['trace-config']!=='__stripped__'){config=JSON.parse(metadata.value['trace-config']);}
+if(config){return{excluded:config.excluded_categories||[],included:config.included_categories||[],};}}}
+function validateTraceCategories(requiredCategories,categories){if(!requiredCategories)return;if(!categories)throw new Error('Missing trace config metadata');for(const cat of requiredCategories){const isDisabledByDefault=(cat.indexOf('disabled-by-default')===0);let missing=false;if(isDisabledByDefault){if(!categories.included.includes(cat)){missing=true;}}else if(categories.excluded.includes(cat)){missing=true;}
+if(missing){throw new Error(`Trace is missing required category "${cat}"`);}}}
+function validateDiagnosticNames(histograms){for(const hist of histograms){for(const name of hist.diagnostics.keys()){if(tr.v.d.RESERVED_NAMES_SET.has(name)){throw new Error(`Illegal diagnostic name "${name}" on Histogram "${hist.name}"`);}}}}
+function addTelemetryInfo(histograms,model){for(const metadata of model.metadata){if(!metadata.value||!metadata.value.telemetry)continue;for(const[name,value]of Object.entries(metadata.value.telemetry)){const type=tr.v.d.RESERVED_NAMES_TO_TYPES.get(name);if(type===undefined){throw new Error(`Unexpected telemetry.${name}`);}
+histograms.addSharedDiagnosticToAllHistograms(name,new type(value));}}}
+function metricMapFunction(result,model,options){const histograms=runMetrics(model,options,result.addFailure.bind(result));addTelemetryInfo(histograms,model);if(model.canonicalUrl!==undefined){const info=tr.v.d.RESERVED_INFOS.TRACE_URLS;histograms.addSharedDiagnosticToAllHistograms(info.name,new info.type([model.canonicalUrl]));}
+result.addPair('histograms',histograms.asDicts());const scalarDicts=[];for(const value of histograms){for(const[statName,scalar]of value.statisticsScalars){scalarDicts.push({name:value.name+'_'+statName,numeric:scalar.asDict(),description:value.description,});}}
+result.addPair('scalars',scalarDicts);}
+tr.mre.FunctionRegistry.register(metricMapFunction);return{metricMapFunction,runMetrics,};});'use strict';tr.exportTo('tr.mre',function(){class MreResult{constructor(failures,pairs){if(failures===undefined){failures=[];}
+if(pairs===undefined){pairs={};}
+this.failures=failures;this.pairs=pairs;}
+addFailure(failure){this.failures.push(failure);}
+addPair(key,value){if(key in this.pairs){throw new Error('Key '+key+' already exists in result.');}
+this.pairs[key]=value;}
+asDict(){const d={pairs:this.pairs};if(this.failures){d.failures=this.failures.map(function(f){return f.asDict();});}
+return d;}
+hadFailures(){return this.failures.length>0;}
+static fromDict(resultDict){const failures=(resultDict.failures!==undefined)?resultDict.failures.map(tr.mre.Failure.fromDict):undefined;const pairs=resultDict.pairs;return new MreResult(failures,pairs);}}
+return{MreResult,};});'use strict';tr.exportTo('tr.ui',function(){class NullBrushingStateController extends tr.c.BrushingStateController{constructor(){super(undefined);this.parentController=undefined;}
+dispatchChangeEvent_(){if(this.parentController)this.parentController.dispatchChangeEvent_();}
+get model(){if(!this.parentController)return undefined;return this.parentController.model;}
+get trackView(){if(!this.parentController)return undefined;return this.parentController.trackView;}
+get viewport(){if(!this.parentController)return undefined;return this.parentController.viewport;}
+get historyEnabled(){if(!this.parentController)return undefined;return this.parentController.historyEnabled;}
+set historyEnabled(historyEnabled){if(this.parentController){this.parentController.historyEnabled=historyEnabled;}}
+modelWillChange(){if(this.parentController)this.parentController.modelWillChange();}
+modelDidChange(){if(this.parentController)this.parentController.modelDidChange();}
+onUserInitiatedSelectionChange_(){if(this.parentController){this.parentController.onUserInitiatedSelectionChange_();}}
+onPopState_(e){if(this.parentController)this.parentController.onPopState_(e);}
+get selection(){if(!this.parentController)return undefined;return this.parentController.selection;}
+get findMatches(){if(!this.parentController)return undefined;return this.parentController.findMatches;}
+get selectionOfInterest(){if(!this.parentController)return undefined;return this.parentController.selectionOfInterest;}
+get currentBrushingState(){if(!this.parentController)return undefined;return this.parentController.currentBrushingState;}
+set currentBrushingState(newBrushingState){if(this.parentController){this.parentController.currentBrushingState=newBrushingState;}}
+addAllEventsMatchingFilterToSelectionAsTask(filter,selection){if(this.parentController){this.parentController.addAllEventsMatchingFilterToSelectionAsTask(filter,selection);}}
+findTextChangedTo(allPossibleMatches){if(this.parentController){this.parentController.findTextChangedTo(allPossibleMatches);}}
+findFocusChangedTo(currentFocus){if(this.parentController){this.parentController.findFocusChangedTo(currentFocus);}}
+findTextCleared(){if(this.parentController){this.parentController.findTextCleared();}}
+uiStateFromString(string){if(this.parentController){this.parentController.uiStateFromString(string);}}
+navToPosition(uiState,showNavLine){if(this.parentController){this.parentController.navToPosition(uiState,showNavLine);}}
+changeSelectionFromTimeline(selection){if(this.parentController){this.parentController.changeSelectionFromTimeline(selection);}}
+showScriptControlSelection(selection){if(this.parentController){this.parentController.showScriptControlSelection(selection);}}
+changeSelectionFromRequestSelectionChangeEvent(selection){if(this.parentController){this.parentController.changeSelectionFromRequestSelectionChangeEvent(selection);}}
+changeAnalysisViewRelatedEvents(eventSet){if(this.parentController&&(eventSet instanceof tr.model.EventSet)){this.parentController.changeAnalysisViewRelatedEvents(eventSet);}}
+changeAnalysisLinkHoveredEvents(eventSet){if(this.parentController&&(eventSet instanceof tr.model.EventSet)){this.parentController.changeAnalysisLinkHoveredEvents(eventSet);}}
+getViewSpecificBrushingState(viewId){if(this.parentController){this.parentController.getViewSpecificBrushingState(viewId);}}
+changeViewSpecificBrushingState(viewId,newState){if(this.parentController){this.parentController.changeViewSpecificBrushingState(viewId,newState);}}}
+return{NullBrushingStateController,};});'use strict';tr.exportTo('tr.v',function(){const IGNORE_GROUPING_KEYS=['name','storyTags','testPath',];class CSVBuilder{constructor(histograms){this.histograms_=histograms;this.table_=[];this.statisticsNames_=new Set();this.groupings_=[];}
+build(){this.prepare_();this.buildHeader_();this.buildTable_();}
+prepare_(){for(const[key,grouping]of tr.v.HistogramGrouping.BY_KEY){if(IGNORE_GROUPING_KEYS.includes(key))continue;this.groupings_.push(grouping);}
+this.groupings_.push(new tr.v.GenericSetGrouping(tr.v.d.RESERVED_NAMES.TRACE_URLS));this.groupings_.sort((a,b)=>a.key.localeCompare(b.key));for(const hist of this.histograms_){for(const name of hist.statisticsNames){this.statisticsNames_.add(name);}}
+this.statisticsNames_=Array.from(this.statisticsNames_);this.statisticsNames_.sort();}
+buildHeader_(){const header=['name','unit'];for(const name of this.statisticsNames_){header.push(name);}
+for(const grouping of this.groupings_){header.push(grouping.key);}
+this.table_.push(header);}
+buildTable_(){for(const hist of this.histograms_){const row=[hist.name,hist.unit.unitString];this.table_.push(row);for(const name of this.statisticsNames_){const stat=hist.getStatisticScalar(name);if(stat){row.push(stat.value);}else{row.push('');}}
+for(const grouping of this.groupings_){row.push(grouping.callback(hist));}}}
+toString(){let str='';for(const row of this.table_){for(let i=0;i<row.length;++i){if(i>0){str+=',';}
+let cell=''+row[i];cell=cell.replace(/\n/g,' ');if(cell.indexOf(',')>=0||cell.indexOf('"')>=0){cell='"'+cell.replace(/"/g,'""')+'"';}
+str+=cell;}
+str+='\n';}
+return str;}}
+return{CSVBuilder,};});'use strict';tr.exportTo('tr.v',function(){const getDisplayLabel=tr.v.HistogramGrouping.DISPLAY_LABEL.callback;const DEFAULT_POSSIBLE_GROUPS=[];const EXCLUDED_GROUPING_KEYS=[tr.v.HistogramGrouping.DISPLAY_LABEL.key,];for(const group of tr.v.HistogramGrouping.BY_KEY.values()){if(EXCLUDED_GROUPING_KEYS.includes(group.key))continue;DEFAULT_POSSIBLE_GROUPS.push(group);}
+class HistogramParameterCollector{constructor(){this.statisticNames_=new Set(['avg']);this.labelsToStartTimes_=new Map();this.keysToGroupings_=new Map(DEFAULT_POSSIBLE_GROUPS.map(g=>[g.key,g]));this.keysToValues_=new Map(DEFAULT_POSSIBLE_GROUPS.map(g=>[g.key,new Set()]));this.keysToValues_.delete(tr.v.HistogramGrouping.HISTOGRAM_NAME.key);}
+process(histograms){const allStoryTags=new Set();let maxSampleCount=0;for(const hist of histograms){maxSampleCount=Math.max(maxSampleCount,hist.numValues);for(const statName of hist.statisticsNames){this.statisticNames_.add(statName);}
+let startTime=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);if(startTime!==undefined)startTime=startTime.minDate.getTime();const displayLabel=getDisplayLabel(hist);if(this.labelsToStartTimes_.has(displayLabel)){startTime=Math.min(startTime,this.labelsToStartTimes_.get(displayLabel));}
+this.labelsToStartTimes_.set(displayLabel,startTime);for(const[groupingKey,values]of this.keysToValues_){const grouping=this.keysToGroupings_.get(groupingKey);const value=grouping.callback(hist);if(!value)continue;values.add(value);if(values.size>1){this.keysToValues_.delete(groupingKey);}}
+const storyTags=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.STORY_TAGS);for(const tag of(storyTags||[])){allStoryTags.add(tag);}}
+tr.b.Timing.instant('HistogramParameterCollector','maxSampleCount',maxSampleCount);for(const tagGrouping of tr.v.HistogramGrouping.buildFromTags(allStoryTags,tr.v.d.RESERVED_NAMES.STORY_TAGS)){const values=new Set();for(const hist of histograms){values.add(tagGrouping.callback(hist));}
+if(values.size>1){this.keysToGroupings_.set(tagGrouping.key,tagGrouping);this.keysToValues_.set(tagGrouping.key,values);}}
+this.statisticNames_.add('pct_090');}
+get statisticNames(){return Array.from(this.statisticNames_);}
+get labels(){const displayLabels=Array.from(this.labelsToStartTimes_.keys());displayLabels.sort((x,y)=>this.labelsToStartTimes_.get(x)-this.labelsToStartTimes_.get(y));return displayLabels;}
+get possibleGroupings(){for(const[key,values]of this.keysToValues_){if(values.size>=2)continue;this.keysToGroupings_.delete(key);}
+return Array.from(this.keysToGroupings_.values());}}
+return{HistogramParameterCollector,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-controls-export',exportRawCsv_(){this.export_(false,'csv');},exportRawJson_(){this.export_(false,'json');},exportMergedCsv_(){this.export_(true,'csv');},exportMergedJson_(){this.export_(true,'json');},export_(merged,format){tr.b.dispatchSimpleEvent(this,'export',true,true,{merged,format});},});return{};});'use strict';tr.exportTo('tr.v.ui',function(){const ALPHA_OPTIONS=[];for(let i=1;i<10;++i)ALPHA_OPTIONS.push(i*1e-3);for(let i=1;i<10;++i)ALPHA_OPTIONS.push(i*1e-2);ALPHA_OPTIONS.push(0.1);Polymer({is:'tr-v-ui-histogram-set-controls',properties:{searchQuery:{type:String,value:'',observer:'onSearchQueryChange_',},showAll:{type:Boolean,value:true,observer:'onUserChange_',},referenceDisplayLabel:{type:String,value:'',observer:'onUserChange_',},displayStatisticName:{type:String,value:'',observer:'onUserChange_',},alphaString:{type:String,computed:'getAlphaString_(alphaIndex)',},alphaIndex:{type:Number,value:9,observer:'onUserChange_',},},created(){this.viewState_=undefined;this.rowListener_=this.onRowViewStateUpdate_.bind(this);this.baseStatisticNames_=[];this.isInOnViewStateUpdate_=false;this.searchQueryDebounceMs=200;},ready(){this.$.picker.addEventListener('current-groups-changed',this.onGroupsChanged_.bind(this));},get viewState(){return this.viewState_;},set viewState(vs){if(this.viewState_){throw new Error('viewState must be set exactly once.');}
+this.viewState_=vs;this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));},async onSearchQueryChange_(){if(this.searchQueryDebounceMs===0)return this.onUserChange_();this.debounce('onSearchQueryDebounce',this.onUserChange_,this.searchQueryDebounceMs);},async onUserChange_(){if(!this.viewState)return;if(this.isInOnViewStateUpdate_)return;const marks=[];if(this.searchQuery!==this.viewState.searchQuery){marks.push(tr.b.Timing.mark('histogram-set-controls','search'));}
+if(this.showAll!==this.viewState.showAll){marks.push(tr.b.Timing.mark('histogram-set-controls','showAll'));}
+if(this.referenceDisplayLabel!==this.viewState.referenceDisplayLabel){marks.push(tr.b.Timing.mark('histogram-set-controls','referenceColumn'));}
+if(this.displayStatisticName!==this.viewState.displayStatisticName){marks.push(tr.b.Timing.mark('histogram-set-controls','statistic'));}
+if(parseInt(this.alphaIndex)!==this.getAlphaIndexFromViewState_()){marks.push(tr.b.Timing.mark('histogram-set-controls','alpha'));}
+this.$.clear_search.style.visibility=this.searchQuery?'visible':'hidden';let displayStatisticName=this.displayStatisticName;if(this.viewState.referenceDisplayLabel===''&&this.referenceDisplayLabel!==''&&this.baseStatisticNames.length){displayStatisticName=`%${tr.v.DELTA}${this.displayStatisticName}`;}
+if(this.referenceDisplayLabel===''&&this.viewState.referenceDisplayLabel!==''&&this.baseStatisticNames.length){const deltaIndex=displayStatisticName.indexOf(tr.v.DELTA);if(deltaIndex>=0){displayStatisticName=displayStatisticName.slice(deltaIndex+1);}else if(!this.baseStatisticNames.includes(displayStatisticName)){displayStatisticName='avg';}}
+await this.viewState.update({searchQuery:this.searchQuery,showAll:this.showAll,referenceDisplayLabel:this.referenceDisplayLabel,displayStatisticName,alpha:ALPHA_OPTIONS[this.alphaIndex],});if(this.referenceDisplayLabel&&this.statisticNames.length===this.baseStatisticNames.length){this.statisticNames=this.baseStatisticNames.concat(tr.v.Histogram.getDeltaStatisticsNames(this.baseStatisticNames));}else if(!this.referenceDisplayLabel&&this.statisticNames.length>this.baseStatisticNames.length){this.statisticNames=this.baseStatisticNames;}
+for(const mark of marks)mark.end();},onViewStateUpdate_(event){this.isInOnViewStateUpdate_=true;if(event.delta.searchQuery){this.searchQuery=this.viewState.searchQuery;}
+if(event.delta.showAll)this.showAll=this.viewState.showAll;if(event.delta.displayStatisticName){this.displayStatisticName=this.viewState.displayStatisticName;}
+if(event.delta.referenceDisplayLabel){this.referenceDisplayLabel=this.viewState.referenceDisplayLabel;this.$.alpha.style.display=this.referenceDisplayLabel?'inline':'';}
+if(event.delta.groupings){this.$.picker.currentGroupKeys=this.viewState.groupings.map(g=>g.key);}
+if(event.delta.tableRowStates){for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){row.addUpdateListener(this.rowListener_);}
+const anyShowing=this.anyOverviewCharts_;this.$.hide_overview.style.display=anyShowing?'inline':'none';this.$.show_overview.style.display=anyShowing?'none':'inline';}
+if(event.delta.alpha){this.alphaIndex=this.getAlphaIndexFromViewState_();}
+this.isInOnViewStateUpdate_=false;this.onUserChange_();},onRowViewStateUpdate_(event){if(event.delta.isOverviewed){const anyShowing=event.delta.isOverviewed.current||this.anyOverviewCharts_;this.$.hide_overview.style.display=anyShowing?'inline':'none';this.$.show_overview.style.display=anyShowing?'none':'inline';}
+if(event.delta.subRows){for(const subRow of event.delta.subRows.previous){subRow.removeUpdateListener(this.rowListener_);}
+for(const subRow of event.delta.subRows.current){subRow.addUpdateListener(this.rowListener_);}}},onGroupsChanged_(){if(this.$.picker.currentGroups.length===0&&this.$.picker.possibleGroups.length>0){this.$.picker.currentGroupKeys=[this.$.picker.possibleGroups[0].key];}
+this.viewState.groupings=this.$.picker.currentGroups;},set showAllEnabled(enable){if(!enable)this.$.show_all.checked=true;this.$.show_all.disabled=!enable;},set possibleGroupings(groupings){this.$.picker.possibleGroups=groupings;this.$.picker.style.display=(groupings.length<2)?'none':'block';this.onGroupsChanged_();},set displayLabels(labels){this.$.reference_display_label.style.display=(labels.length<2)?'none':'inline';while(this.$.reference_display_label.children.length>1){this.$.reference_display_label.removeChild(this.$.reference_display_label.lastChild);}
+for(const displayLabel of labels){const option=document.createElement('option');option.textContent=displayLabel;option.value=displayLabel;this.$.reference_display_label.appendChild(option);}
+if(labels.includes(this.viewState.referenceDisplayLabel)){this.referenceDisplayLabel=this.viewState.referenceDisplayLabel;}else{this.viewState.referenceDisplayLabel='';}},get baseStatisticNames(){return this.baseStatisticNames_;},set baseStatisticNames(names){this.baseStatisticNames_=names;this.statisticNames=names;},get statisticNames(){return Array.from(this.$.statistic.options).map(o=>o.value);},set statisticNames(names){this.$.statistic.style.display=(names.length<2)?'none':'inline';while(this.$.statistic.children.length){this.$.statistic.removeChild(this.$.statistic.lastChild);}
+for(const name of names){const option=document.createElement('option');option.textContent=name;this.$.statistic.appendChild(option);}
+if(names.includes(this.viewState.displayStatisticName)){this.displayStatisticName=this.viewState.displayStatisticName;this.$.statistic.value=this.displayStatisticName;}else{this.viewState.displayStatisticName=names[0]||'';}},get anyOverviewCharts_(){for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){if(row.isOverviewed)return true;}
+return false;},async toggleOverviewLineCharts_(){const showOverviews=!this.anyOverviewCharts_;const mark=tr.b.Timing.mark('histogram-set-controls',(showOverviews?'show':'hide')+'OverviewCharts');for(const row of tr.v.ui.HistogramSetTableRowState.walkAll(this.viewState.tableRowStates.values())){await row.update({isOverviewed:showOverviews});}
+this.$.hide_overview.style.display=showOverviews?'inline':'none';this.$.show_overview.style.display=showOverviews?'none':'inline';await tr.b.animationFrame();mark.end();},set helpHref(href){this.$.help.href=href;this.$.help.style.display='inline';},set feedbackHref(href){this.$.feedback.href=href;this.$.feedback.style.display='inline';},clearSearch_(){this.set('searchQuery','');this.$.search.focus();},getAlphaString_(alphaIndex){return(''+ALPHA_OPTIONS[alphaIndex]).substr(0,5);},openAlphaSlider_(){const alphaButtonRect=this.$.alpha.getBoundingClientRect();this.$.alpha_slider_container.style.display='flex';this.$.alpha_slider_container.style.top=alphaButtonRect.bottom+'px';this.$.alpha_slider_container.style.left=alphaButtonRect.left+'px';this.$.alpha_slider.focus();},closeAlphaSlider_(){this.$.alpha_slider_container.style.display='';},updateAlpha_(){this.alphaIndex=this.$.alpha_slider.value;},getAlphaIndexFromViewState_(){for(let i=0;i<ALPHA_OPTIONS.length;++i){if(ALPHA_OPTIONS[i]>=this.viewState.alpha)return i;}
+return ALPHA_OPTIONS.length-1;},set enableVisualization(enable){this.$.show_visualization.style.display=enable?'inline':'none';},loadVisualization_(){tr.b.dispatchSimpleEvent(this,'loadVisualization',true,true,{});},});return{};});'use strict';tr.exportTo('tr.v',function(){class HistogramSetHierarchy{constructor(name){this.name=name;this.description='';this.depth=0;this.subRows=[];this.columns=new Map();}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
+static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}
+static build(histogramArrayMap){const rootRows=[];HistogramSetHierarchy.buildInternal_(histogramArrayMap,[],rootRows);const histograms=new tr.v.HistogramSet();for(const row of HistogramSetHierarchy.walkAll(rootRows)){for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
+histograms.deduplicateDiagnostics();for(const row of HistogramSetHierarchy.walkAll(rootRows)){row.maybeRebin_();}
+return rootRows;}
+maybeRebin_(){const dataRange=new tr.b.math.Range();for(const hist of this.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;if(hist.allBins.length>1)return;if(hist.numValues===0)continue;dataRange.addValue(hist.min);dataRange.addValue(hist.max);}
+dataRange.addValue(tr.b.math.lesserWholeNumber(dataRange.min));dataRange.addValue(tr.b.math.greaterWholeNumber(dataRange.max));if(dataRange.min===dataRange.max)return;const boundaries=tr.v.HistogramBinBoundaries.createLinear(dataRange.min,dataRange.max,tr.v.DEFAULT_REBINNED_COUNT);for(const[name,hist]of this.columns){if(!(hist instanceof tr.v.Histogram))continue;this.columns.set(name,hist.rebin(boundaries));}}
+static mergeHistogramDownHierarchy_(histogram,hierarchy,columnName){for(const row of hierarchy){if(!row.description){row.description=histogram.description;}
+const existing=row.columns.get(columnName);if(existing===undefined){row.columns.set(columnName,histogram.clone());continue;}
+if(existing instanceof tr.v.HistogramSet){existing.addHistogram(histogram);continue;}
+if(!existing.canAddHistogram(histogram)){const unmergeableHistograms=new tr.v.HistogramSet([histogram]);row.columns.set(columnName,unmergeableHistograms);continue;}
+existing.addHistogram(histogram);}}
+static buildInternal_(histogramArrayMap,hierarchy,rootRows){for(const[name,histograms]of histogramArrayMap){if(histograms instanceof Array){for(const histogram of histograms){HistogramSetHierarchy.mergeHistogramDownHierarchy_(histogram,hierarchy,name);}}else if(histograms instanceof Map){const row=new HistogramSetHierarchy(name);row.depth=hierarchy.length;hierarchy.push(row);HistogramSetHierarchy.buildInternal_(histograms,hierarchy,rootRows);hierarchy.pop();if(hierarchy.length===0){rootRows.push(row);}else{const parentRow=hierarchy[hierarchy.length-1];parentRow.subRows.push(row);}}}}}
+return{HistogramSetHierarchy};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-table-cell',created(){this.viewState_=undefined;this.rootListener_=this.onRootStateUpdate_.bind(this);this.row_=undefined;this.displayLabel_='';this.histogram_=undefined;this.histogramSpan_=undefined;this.overviewChart_=undefined;this.mwuResult_=undefined;},ready(){this.addEventListener('click',this.onClick_.bind(this));},attached(){if(this.row){this.row.rootViewState.addUpdateListener(this.rootListener_);}},detached(){this.row.rootViewState.removeUpdateListener(this.rootListener_);},updateMwu_(){const referenceHistogram=this.referenceHistogram;this.mwuResult_=undefined;if(!(this.histogram instanceof tr.v.Histogram))return;if(!this.histogram.canCompare(referenceHistogram))return;this.mwuResult_=tr.b.math.Statistics.mwu(this.histogram.sampleValues,referenceHistogram.sampleValues,this.row.rootViewState.alpha);},build(row,displayLabel,viewState){this.row_=row;this.displayLabel_=displayLabel;this.viewState_=viewState;this.histogram_=this.row.columns.get(displayLabel);if(this.viewState){this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));}
+this.row.viewState.addUpdateListener(this.onRowStateUpdate_.bind(this));if(this.isAttached){this.row.rootViewState.addUpdateListener(this.rootListener_);}
+this.updateMwu_();this.updateContents_();},updateSignificance_(){if(!this.mwuResult_)return;this.$.scalar.significance=this.mwuResult_.significance;},get viewState(){return this.viewState_;},get row(){return this.row_;},get histogram(){return this.histogram_;},get referenceHistogram(){const referenceDisplayLabel=this.row.rootViewState.referenceDisplayLabel;if(!referenceDisplayLabel)return undefined;if(referenceDisplayLabel===this.displayLabel_)return undefined;return this.row.columns.get(referenceDisplayLabel);},get isHistogramOpen(){return(this.histogramSpan_!==undefined)&&(this.$.histogram.style.display==='block');},set isHistogramOpen(open){if(!(this.histogram instanceof tr.v.Histogram)||(this.histogram.numValues===0)){return;}
+this.$.scalar.style.display=open?'none':'flex';this.$.open_histogram.style.display=open?'none':'block';this.$.close_histogram.style.display=open?'block':'none';this.$.histogram.style.display=open?'block':'none';if(open&&this.histogramSpan_===undefined){this.histogramSpan_=document.createElement('tr-v-ui-histogram-span');this.histogramSpan_.viewState=this.viewState;this.histogramSpan_.rowState=this.row.viewState;this.histogramSpan_.rootState=this.row.rootViewState;this.histogramSpan_.build(this.histogram,this.referenceHistogram);this.$.histogram.appendChild(this.histogramSpan_);}
+this.viewState.isOpen=open;},onViewStateUpdate_(event){if(event.delta.isOpen){this.isHistogramOpen=this.viewState.isOpen;}},onRowStateUpdate_(event){if(event.delta.isOverviewed===undefined)return;if(this.row.viewState.isOverviewed){this.showOverview();}else{this.hideOverview();}},onRootStateUpdate_(event){if(event.delta.referenceDisplayLabel&&this.histogramSpan_){this.histogramSpan_.build(this.histogram,this.referenceHistogram);}
+if(event.delta.displayStatisticName||event.delta.referenceDisplayLabel){this.updateMwu_();this.updateContents_();}else if(event.delta.alpha&&this.mwuResult_){this.mwuResult_.compare(this.row.rootViewState.alpha);this.updateSignificance_();}
+if(this.row.viewState.isOverviewed&&(event.delta.sortColumnIndex||event.delta.sortDescending||event.delta.displayStatisticName||event.delta.referenceDisplayLabel)){if(this.overviewChart_!==undefined){this.$.overview_container.removeChild(this.overviewChart_);this.overviewChart_=undefined;}
+this.showOverview();}},onClick_(event){event.stopPropagation();},openHistogram_(){this.isHistogramOpen=true;tr.b.Timing.instant('histogram-set-table-cell','open');},closeHistogram_(){this.isHistogramOpen=false;tr.b.Timing.instant('histogram-set-table-cell','close');},updateContents_(){const isOpen=this.isHistogramOpen;this.$.empty.style.display='none';this.$.unmergeable.style.display='none';this.$.scalar.style.display='none';this.$.histogram.style.display='none';this.$.close_histogram.style.display='none';this.$.open_histogram.style.visibility='hidden';if(!this.histogram){this.$.missing.style.display='block';return;}
+this.$.missing.style.display='none';if(this.histogram instanceof tr.v.HistogramSet){this.$.unmergeable.style.display='block';return;}
+if(!(this.histogram instanceof tr.v.Histogram)){throw new Error('Invalid Histogram: '+this.histogram);}
+if(this.histogram.numValues===0){this.$.empty.style.display='block';return;}
+this.$.open_histogram.style.display='block';this.$.open_histogram.style.visibility='visible';this.$.scalar.style.display='flex';this.updateSignificance_();const referenceHistogram=this.referenceHistogram;const statName=this.histogram.getAvailableStatisticName(this.row.rootViewState.displayStatisticName,referenceHistogram);const statisticScalar=this.histogram.getStatisticScalar(statName,referenceHistogram);this.$.scalar.setValueAndUnit(statisticScalar.value,statisticScalar.unit);this.isHistogramOpen=isOpen;},showOverview(){this.$.overview_container.style.display='block';if(this.overviewChart_!==undefined)return;this.row.sortSubRows();let referenceDisplayLabel=this.row.rootViewState.referenceDisplayLabel;if(referenceDisplayLabel===this.displayLabel_){referenceDisplayLabel=undefined;}
+const displayStatisticName=this.row.rootViewState.displayStatisticName;const data=[];let unit;for(const subRow of this.row.subRows){const subHist=subRow.columns.get(this.displayLabel_);if(!(subHist instanceof tr.v.Histogram))continue;if(unit===undefined){unit=subHist.unit;}else if(unit!==subHist.unit){data.splice(0);break;}
+const refHist=subRow.columns.get(referenceDisplayLabel);const statName=subHist.getAvailableStatisticName(displayStatisticName,refHist);const statScalar=subHist.getStatisticScalar(statName,refHist);if(statScalar!==undefined){data.push({x:subRow.name,y:statScalar.value,});}}
+if(data.length<2)return;this.overviewChart_=new tr.ui.b.NameLineChart();this.$.overview_container.appendChild(this.overviewChart_);this.overviewChart_.displayXInHover=true;this.overviewChart_.hideLegend=true;this.overviewChart_.unit=unit;this.overviewChart_.overrideDataRange=this.row.overviewDataRange;this.overviewChart_.data=data;},hideOverview(){this.$.overview_container.style.display='none';}});return{};});'use strict';tr.exportTo('tr.v.ui',function(){const NAME_COLUMN_WIDTH_PX=300;Polymer({is:'tr-v-ui-histogram-set-table-name-cell',created(){this.row_=undefined;this.overviewChart_=undefined;this.cellListener_=this.onCellStateUpdate_.bind(this);this.rootListener_=this.onRootStateUpdate_.bind(this);},attached(){if(this.row){this.row.rootViewState.addUpdateListener(this.rootListener_);}},detached(){this.row.rootViewState.removeUpdateListener(this.rootListener_);},get row(){return this.row_;},build(row){if(this.row_!==undefined){throw new Error('row must be set exactly once.');}
+this.row_=row;this.row.viewState.addUpdateListener(this.onRowStateUpdate_.bind(this));this.constrainWidth=this.row.rootViewState.constrainNameColumn;if(this.isAttached){this.row.rootViewState.addUpdateListener(this.rootListener_);}
+for(const cellState of this.row.viewState.cells.values()){cellState.addUpdateListener(this.cellListener_);}
+Polymer.dom(this.$.name).textContent=this.row.name;this.title=this.row.name;if(this.row.description){this.title+='\n'+this.row.description;}
+if(this.row.overviewDataRange.isEmpty||this.row.overviewDataRange.min===this.row.overviewDataRange.max){this.$.show_overview.style.display='none';}
+let histogramCount=0;for(const cell of this.row.columns.values()){if(cell instanceof tr.v.Histogram&&cell.numValues>0){++histogramCount;}}
+if(histogramCount<=1){this.$.open_histograms.style.display='none';}},set constrainWidth(constrain){this.$.name.style.maxWidth=constrain?(this.nameWidthPx+'px'):'none';},get nameWidthPx(){return NAME_COLUMN_WIDTH_PX-(16*this.row.depth);},get isOverflowing(){return this.$.name.style.maxWidth!=='none'&&this.$.name.getBoundingClientRect().width===this.nameWidthPx;},get isOverviewed(){return this.$.overview_container.style.display==='block';},set isOverviewed(isOverviewed){if(isOverviewed===this.isOverviewed)return;if(isOverviewed){this.showOverview_();}else{this.hideOverview_();}},hideOverview_(opt_event){this.$.overview_container.style.display='none';this.$.hide_overview.style.display='none';this.$.show_overview.style.display='block';if(opt_event!==undefined){opt_event.stopPropagation();tr.b.Timing.instant('histogram-set-table-name-cell','hideOverview');this.row.viewState.isOverviewed=this.isOverviewed;}},showOverview_(opt_event){if(opt_event!==undefined){opt_event.stopPropagation();tr.b.Timing.instant('histogram-set-table-name-cell','showOverview');this.row.viewState.isOverviewed=true;}
+this.$.overview_container.style.display='block';this.$.hide_overview.style.display='block';this.$.show_overview.style.display='none';if(this.overviewChart_===undefined){const displayStatisticName=this.row.rootViewState.displayStatisticName;const data=[];let unit;for(const[displayLabel,hist]of this.row.sortedColumns()){if(!(hist instanceof tr.v.Histogram))continue;if(unit===undefined){unit=hist.unit;}else if(unit!==hist.unit){data.splice(0);break;}
+const statName=hist.getAvailableStatisticName(displayStatisticName);const statScalar=hist.getStatisticScalar(statName);if(statScalar!==undefined){data.push({x:displayLabel,y:statScalar.value,});}}
+if(data.length<2){return;}
+this.overviewChart_=new tr.ui.b.NameLineChart();this.$.overview_container.appendChild(this.overviewChart_);this.overviewChart_.displayXInHover=true;this.overviewChart_.hideLegend=true;this.overviewChart_.unit=unit;this.overviewChart_.overrideDataRange=this.row.overviewDataRange;this.overviewChart_.data=data;}},openHistograms_(event){event.stopPropagation();tr.b.Timing.instant('histogram-set-table-name-cell','openHistograms');for(const cell of this.row.cells.values()){cell.isHistogramOpen=true;}
+this.$.close_histograms.style.display='block';this.$.open_histograms.style.display='none';},closeHistograms_(event){event.stopPropagation();tr.b.Timing.instant('histogram-set-table-name-cell','closeHistograms');for(const cell of this.row.cells.values()){cell.isHistogramOpen=false;}
+this.$.open_histograms.style.display='block';this.$.close_histograms.style.display='none';},onRootStateUpdate_(event){if(event.delta.constrainNameColumn){this.constrainWidth=this.row.rootViewState.constrainNameColumn;}
+if(this.row.viewState.isOverviewed&&event.delta.displayStatisticName){this.row.resetOverviewDataRange();if(this.overviewChart_!==undefined){this.$.overview_container.removeChild(this.overviewChart_);this.overviewChart_=undefined;}
+this.showOverview_();}},onRowStateUpdate_(event){if(event.delta.isOverviewed){this.isOverviewed=this.row.viewState.isOverviewed;}},onCellStateUpdate_(event){if(!event.delta.isOpen)return;let cellCount=0;let openCellCount=0;for(const cell of this.row.cells.values()){if(!(cell.histogram instanceof tr.v.Histogram)||(cell.histogram.numValues===0)){continue;}
+++cellCount;if(cell.isHistogramOpen)++openCellCount;}
+if(cellCount<=1)return;const mostlyOpen=openCellCount>(cellCount/2);this.$.open_histograms.style.display=mostlyOpen?'none':'block';this.$.close_histograms.style.display=mostlyOpen?'block':'none';}});return{NAME_COLUMN_WIDTH_PX,};});'use strict';tr.exportTo('tr.v.ui',function(){class HistogramSetTableRow{constructor(hierarchy,baseTable,rootViewState){this.hierarchy_=hierarchy;this.baseTable_=baseTable;this.rootViewState_=rootViewState;this.viewState_=new tr.v.ui.HistogramSetTableRowState();this.viewState_.addUpdateListener(this.onViewStateUpdate_.bind(this));this.overviewDataRange_=undefined;this.nameCell_=undefined;this.cells_=new Map();this.subRows_=[];for(const subHierarchy of hierarchy.subRows){const subRow=new HistogramSetTableRow(subHierarchy,baseTable,rootViewState);this.subRows_.push(subRow);this.viewState.subRows.set(subRow.name,subRow.viewState);}
+for(const columnName of this.columns.keys()){this.viewState.cells.set(columnName,new tr.v.ui.HistogramSetTableCellState());}}
+get name(){return this.hierarchy_.name;}
+get depth(){return this.hierarchy_.depth;}
+get description(){return this.hierarchy_.description;}
+get columns(){return this.hierarchy_.columns;}*sortedColumns(){for(const col of this.baseTable_.tableColumns){yield[col.displayLabel,this.hierarchy_.columns.get(col.displayLabel),];}}
+get overviewDataRange(){if(this.overviewDataRange_===undefined){this.overviewDataRange_=new tr.b.math.Range();const displayStatisticName=this.rootViewState.displayStatisticName;const referenceDisplayLabel=this.rootViewState.referenceDisplayLabel;for(const[displayLabel,hist]of this.columns){if(hist instanceof tr.v.Histogram){const statName=hist.getAvailableStatisticName(displayStatisticName);const statScalar=hist.getStatisticScalar(statName);if(statScalar!==undefined){this.overviewDataRange_.addValue(statScalar.value);}}
+for(const subRow of this.subRows){const subHist=subRow.columns.get(displayLabel);if(!(subHist instanceof tr.v.Histogram))continue;const refHist=subRow.columns.get(referenceDisplayLabel);const statName=subHist.getAvailableStatisticName(displayStatisticName,refHist);const statScalar=subHist.getStatisticScalar(statName,refHist);if(statScalar!==undefined){this.overviewDataRange_.addValue(statScalar.value);}}}}
+return this.overviewDataRange_;}
+resetOverviewDataRange(){this.overviewDataRange_=undefined;}
+get rootViewState(){return this.rootViewState_;}
+get cells(){return this.cells_;}
+get subRows(){return this.subRows_;}
+get viewState(){return this.viewState_;}*walk(){yield this;for(const row of this.subRows)yield*row.walk();}
+static*walkAll(rootRows){for(const rootRow of rootRows)yield*rootRow.walk();}
+get nameCell(){if(this.nameCell_===undefined){this.nameCell_=document.createElement('tr-v-ui-histogram-set-table-name-cell');this.nameCell_.build(this);}
+return this.nameCell_;}
+getCell(columnName){if(this.cells.has(columnName))return this.cells.get(columnName);const cell=document.createElement('tr-v-ui-histogram-set-table-cell');cell.build(this,columnName,this.viewState.cells.get(columnName));this.cells.set(columnName,cell);return cell;}
+compareNames(other){return this.name.localeCompare(other.name);}
+compareCells(other,displayLabel){const referenceDisplayLabel=this.rootViewState.referenceDisplayLabel;let referenceCellA;let referenceCellB;if(referenceDisplayLabel&&referenceDisplayLabel!==displayLabel){referenceCellA=this.columns.get(referenceDisplayLabel);referenceCellB=other.columns.get(referenceDisplayLabel);}
+const cellA=this.columns.get(displayLabel);let valueA=0;if(cellA instanceof tr.v.Histogram){const statisticA=cellA.getAvailableStatisticName(this.rootViewState.displayStatisticName,referenceCellA);const scalarA=cellA.getStatisticScalar(statisticA,referenceCellA);if(scalarA){valueA=scalarA.value;}}
+const cellB=other.columns.get(displayLabel);let valueB=0;if(cellB instanceof tr.v.Histogram){const statisticB=cellB.getAvailableStatisticName(this.rootViewState.displayStatisticName,referenceCellB);const scalarB=cellB.getStatisticScalar(statisticB,referenceCellB);if(scalarB){valueB=scalarB.value;}}
+return valueA-valueB;}
+onViewStateUpdate_(event){if(event.delta.isExpanded){this.baseTable_.setExpandedForTableRow(this,this.viewState.isExpanded);}
+if(event.delta.subRows){throw new Error('HistogramSetTableRow.subRows must not be reassigned.');}
+if(event.delta.cells){for(const[displayLabel,cell]of this.cells){if(cell.viewState!==this.viewState.cells.get(displayLabel)){throw new Error('Only HistogramSetTableRow may update cells');}}}}
+async restoreState(vs){await this.viewState.update({isExpanded:vs.isExpanded,isOverviewed:vs.isOverviewed,});for(const[displayLabel,cell]of this.cells){const previousState=vs.cells.get(displayLabel);if(!previousState)continue;await cell.viewState.updateFromViewState(previousState);}
+for(const row of this.subRows){const previousState=vs.subRows.get(row.name);if(!previousState)continue;await row.restoreState(previousState);}}
+sortSubRows(){const sortColumn=this.baseTable_.tableColumns[this.rootViewState_.sortColumnIndex];if(sortColumn===undefined)return;this.subRows_.sort(sortColumn.cmp);if(this.rootViewState_.sortDescending){this.subRows_.reverse();}}}
+return{HistogramSetTableRow,};});'use strict';tr.exportTo('tr.v.ui',function(){const MIDLINE_HORIZONTAL_ELLIPSIS=String.fromCharCode(0x22ef);function escapeRegExp(str){return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,'\\$&');}
+Polymer({is:'tr-v-ui-histogram-set-table',created(){this.viewState_=undefined;this.progress_=()=>Promise.resolve();this.nameColumnTitle_=undefined;this.displayLabels_=[];this.histograms_=undefined;this.sourceHistograms_=undefined;this.filteredHistograms_=undefined;this.groupedHistograms_=undefined;this.hierarchies_=undefined;this.tableRows_=undefined;this.sortColumnChangedListener_=e=>this.onSortColumnChanged_(e);},ready(){this.$.table.zebra=true;this.addEventListener('sort-column-changed',this.sortColumnChangedListener_);this.addEventListener('requestSelectionChange',this.onRequestSelectionChange_.bind(this));this.addEventListener('row-expanded-changed',this.onRowExpandedChanged_.bind(this));},get viewState(){return this.viewState_;},set viewState(vs){if(this.viewState_){throw new Error('viewState must be set exactly once.');}
+this.viewState_=vs;this.viewState.addUpdateListener(this.onViewStateUpdate_.bind(this));},get histograms(){return this.histograms_;},async build(histograms,sourceHistograms,displayLabels,opt_progress){this.histograms_=histograms;this.sourceHistograms_=sourceHistograms;this.filteredHistograms_=undefined;this.groupedHistograms_=undefined;this.displayLabels_=displayLabels;if(opt_progress!==undefined)this.progress_=opt_progress;if(histograms.length===0){throw new Error('histogram-set-table requires non-empty HistogramSet.');}
+await this.progress_('Building columns...');this.$.table.tableColumns=[{title:this.buildNameColumnTitle_(),value:row=>row.nameCell,cmp:(a,b)=>a.compareNames(b),}].concat(displayLabels.map(l=>this.buildColumn_(l)));tr.b.Timing.instant('histogram-set-table','columnCount',this.$.table.tableColumns.length);await this.updateContents_();this.fire('display-ready');this.progress_=()=>Promise.resolve();this.checkNameColumnOverflow_(tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows));},buildNameColumnTitle_(){this.nameColumnTitle_=document.createElement('span');this.nameColumnTitle_.style.display='inline-flex';const nameEl=document.createElement('span');nameEl.textContent='Name';this.nameColumnTitle_.appendChild(nameEl);const toggleWidthEl=document.createElement('span');toggleWidthEl.style.fontWeight='bold';toggleWidthEl.style.background='#bbb';toggleWidthEl.style.color='#333';toggleWidthEl.style.padding='0px 3px';toggleWidthEl.style.marginRight='8px';toggleWidthEl.style.display='none';toggleWidthEl.textContent=MIDLINE_HORIZONTAL_ELLIPSIS;toggleWidthEl.addEventListener('click',this.toggleNameColumnWidth_.bind(this));this.nameColumnTitle_.appendChild(toggleWidthEl);return this.nameColumnTitle_;},toggleNameColumnWidth_(opt_event){this.viewState.update({constrainNameColumn:!this.viewState.constrainNameColumn,});if(opt_event!==undefined){opt_event.stopPropagation();opt_event.preventDefault();tr.b.Timing.instant('histogram-set-table','nameColumn'+
+(this.viewState.constrainNameColumn?'Constrained':'Unconstrained'));}},buildColumn_(displayLabel){const title=document.createElement('span');title.textContent=displayLabel;title.style.whiteSpace='pre';return{displayLabel,title,value:row=>row.getCell(displayLabel),cmp:(rowA,rowB)=>rowA.compareCells(rowB,displayLabel),};},async updateContents_(){const previousRowStates=this.viewState.tableRowStates;if(!this.filteredHistograms_){await this.progress_('Filtering rows...');this.filteredHistograms_=this.viewState.showAll?this.histograms:this.sourceHistograms_;if(this.viewState.searchQuery){let query;try{query=new RegExp(this.viewState.searchQuery);}catch(e){}
+if(query!==undefined){this.filteredHistograms_=new tr.v.HistogramSet([...this.filteredHistograms_].filter(hist=>hist.name.match(query)));if(this.filteredHistograms_.length===0&&!this.viewState.showAll){await this.viewState.update({showAll:true});return;}}}
+this.groupedHistograms_=undefined;}
+if(!this.groupedHistograms_){await this.progress_('Grouping Histograms...');this.groupHistograms_();}
+if(!this.hierarchies_){await this.progress_('Merging Histograms...');this.hierarchies_=tr.v.HistogramSetHierarchy.build(this.groupedHistograms_);this.tableRows_=undefined;}
+const tableRowsDirty=this.tableRows_===undefined;if(tableRowsDirty){this.tableRows_=this.hierarchies_.map(hierarchy=>new tr.v.ui.HistogramSetTableRow(hierarchy,this.$.table,this.viewState));tr.b.Timing.instant('histogram-set-table','rootRowCount',this.tableRows_.length);const namesToRowStates=new Map();for(const row of this.tableRows_){namesToRowStates.set(row.name,row.viewState);}
+await this.viewState.update({tableRowStates:namesToRowStates});}
+await this.progress_('Configuring table...');this.nameColumnTitle_.children[1].style.filter=this.viewState.constrainNameColumn?'invert(100%)':'';const referenceDisplayLabelIndex=this.displayLabels_.indexOf(this.viewState.referenceDisplayLabel);this.$.table.selectedTableColumnIndex=(referenceDisplayLabelIndex<0)?undefined:(1+referenceDisplayLabelIndex);this.removeEventListener('sort-column-changed',this.sortColumnChangedListener_);this.$.table.sortColumnIndex=this.viewState.sortColumnIndex;this.$.table.sortDescending=this.viewState.sortDescending;this.addEventListener('sort-column-changed',this.sortColumnChangedListener_);if(tableRowsDirty){await this.progress_('Building DOM...');this.$.table.tableRows=this.tableRows_;for(const row of this.tableRows_){const previousState=previousRowStates.get(row.name);if(!previousState)continue;await row.restoreState(previousState);}}
+this.$.table.rebuild();},async onRowExpandedChanged_(event){event.row.viewState.isExpanded=this.$.table.getExpandedForTableRow(event.row);tr.b.Timing.instant('histogram-set-table','row'+(event.row.viewState.isExpanded?'Expanded':'Collapsed'));if(this.nameColumnTitle_.children[1].style.display==='block')return;await tr.b.animationFrame();this.checkNameColumnOverflow_(event.row.subRows);},checkNameColumnOverflow_(rows){for(const row of rows){if(!row.nameCell.isOverflowing)continue;const[nameSpan,dots]=Array.from(this.nameColumnTitle_.children);dots.style.display='block';const labelWidthPx=tr.v.ui.NAME_COLUMN_WIDTH_PX-
+dots.getBoundingClientRect().width;nameSpan.style.width=labelWidthPx+'px';return;}},groupHistograms_(){const groupings=this.viewState.groupings.slice();groupings.push(tr.v.HistogramGrouping.DISPLAY_LABEL);function canSkipGrouping(grouping,groupedHistograms){if(groupedHistograms.size>1)return false;if(grouping.key===groupings[0].key)return false;if(grouping.key===tr.v.HistogramGrouping.DISPLAY_LABEL.key){return false;}
+return true;}
+this.groupedHistograms_=this.filteredHistograms_.groupHistogramsRecursively(groupings,canSkipGrouping);this.hierarchies_=undefined;},async onViewStateUpdate_(event){if(this.histograms_===undefined)return;if(event.delta.searchQuery!==undefined||event.delta.showAll!==undefined){this.filteredHistograms_=undefined;}
+if(event.delta.groupings!==undefined){this.groupedHistograms_=undefined;}
+if(event.delta.displayStatistic!==undefined&&this.$.table.sortColumnIndex>0){this.$.table.sortColumnIndex=undefined;}
+if(event.delta.referenceDisplayLabel!==undefined||event.delta.displayStatisticName!==undefined){this.$.table.tableRows=this.$.table.tableRows;}
+if(event.delta.tableRowStates){if(this.tableRows_.length!==this.viewState.tableRowStates.size){throw new Error('Only histogram-set-table may update tableRowStates');}
+for(const row of this.tableRows_){if(this.viewState.tableRowStates.get(row.name)!==row.viewState){throw new Error('Only histogram-set-table may update tableRowStates');}}
+return;}
+await this.updateContents_();},onSortColumnChanged_(event){tr.b.Timing.instant('histogram-set-table','sortColumn');this.viewState.update({sortColumnIndex:event.sortColumnIndex,sortDescending:event.sortDescending,});},onRequestSelectionChange_(event){if(event.selection instanceof tr.model.EventSet)return;event.stopPropagation();tr.b.Timing.instant('histogram-set-table','selectHistogramNames');let histogramNames=event.selection;histogramNames.sort();histogramNames=histogramNames.map(escapeRegExp).join('|');this.viewState.update({showAll:true,searchQuery:`^(${histogramNames})$`,});},get leafHistograms(){const histograms=new tr.v.HistogramSet();for(const row of
+tr.v.ui.HistogramSetTableRow.walkAll(this.$.table.tableRows)){if(row.subRows.length)continue;for(const hist of row.columns.values()){if(!(hist instanceof tr.v.Histogram))continue;histograms.addHistogram(hist);}}
+return histograms;}});return{MIDLINE_HORIZONTAL_ELLIPSIS,};});'use strict';tr.exportTo('tr.v.ui',function(){const PAGE_BREAKDOWN_KEY='pageBreakdown';Polymer({is:'tr-v-ui-metrics-visualization',created(){this.charts_=new Map();},ready(){this.$.start.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.end.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.filterByPercentile_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});},build(chartData){this.title_=chartData.title;this.aggregateData_=chartData.aggregate;this.data_=chartData.page;this.submetricsData_=chartData.submetrics;this.benchmarkCount_=chartData.aggregate.length;const aggregateChart=this.initializeColumnChart(this.title_);Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);this.charts_.set(tr.v.ui.AGGREGATE_KEY,aggregateChart);this.setChartColors_(tr.v.ui.AGGREGATE_KEY);aggregateChart.data=chartData.aggregate;this.setChartSize_(tr.v.ui.AGGREGATE_KEY);const newChart=this.initializeColumnChart(this.title_+' Breakdown');newChart.enableToolTip=true;newChart.toolTipCallBack=(rect)=>this.openChildChart_(rect);Polymer.dom(this.$.pageByPageContainer).appendChild(newChart);this.charts_.set(PAGE_BREAKDOWN_KEY,newChart);this.setChartColors_(PAGE_BREAKDOWN_KEY);newChart.data=this.data_;this.setChartSize_(PAGE_BREAKDOWN_KEY);},setChartSize_(page){const chart=this.charts_.get(page);const pageCount=chart.data.length;chart.graphHeight=tr.b.math.clamp(pageCount*20,400,600);chart.graphWidth=tr.b.math.clamp(pageCount*30,200,1000);},setChartColors_(page){const chart=this.charts_.get(page);const metrics=tr.v.ui.METRICS.get(this.title_);for(let i=0;i<this.benchmarkCount_;++i){for(let j=0;j<metrics.length;++j){const mainColorIndex=j%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;const color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];const series=metrics[j]+'-'+this.aggregateData_[i].x;chart.getDataSeries(series).color=color;if(i===0){chart.getDataSeries(series).title=metrics[j];}else{chart.getDataSeries(series).title='';}}}},initializeColumnChart(title){const newChart=new tr.ui.b.NameColumnChart();newChart.hideLegend=false;newChart.isStacked=true;newChart.yAxisLabel='ms';newChart.hideXAxis=true;newChart.displayXInHover=true;newChart.isGrouped=true;newChart.showTitleInLegend=true;newChart.chartTitle=title;newChart.titleHeight='14pt';return newChart;},initializeChildChart_(title,height,width){const div=document.createElement('div');div.classList.add('container');Polymer.dom(this.$.submetricsContainer).insertBefore(div,this.$.submetricsContainer.firstChild);const childChart=new tr.ui.b.NameBarChart();childChart.xAxisLabel='ms';childChart.chartTitle=title;childChart.graphHeight=height;childChart.graphWidth=width;childChart.titleHeight='14pt';childChart.isStacked=true;childChart.hideLegend=true;childChart.isGrouped=true;childChart.isWaterfall=true;div.appendChild(childChart);const button=this.initializeCloseButton_(div,this.$.submetricsContainer);div.appendChild(button);return childChart;},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},openChildChart_(rect){const metrics=tr.v.ui.METRICS.get(this.title_);let metric;let metricIndex;for(let i=0;i<metrics.length;++i){if(rect.key.startsWith(metrics[i])){metric=metrics[i];metricIndex=i;break;}}
+const page=rect.datum.group;const title=this.title_+' '+metric+': '+page;const submetrics=this.submetricsData_.get(page).get(metric);const width=tr.b.math.clamp(submetrics.size*150,300,700);const height=tr.b.math.clamp(submetrics.size*this.benchmarkCount_*50,300,700);const childChart=this.initializeChildChart_(title,height,width);childChart.data=this.processSubmetrics_(childChart,submetrics,0,metricIndex).data;},processSubmetrics_(chart,submetrics,hideValue,metricIndex){const finalData=[];let submetricIndex=0;for(const submetric of submetrics.values()){let benchmarkIndex=0;for(const benchmark of submetric.values()){benchmark.hide=!hideValue?0:hideValue;const series=benchmark.x+'-'+benchmark.group;const mainColorIndex=metricIndex%tr.v.ui.COLORS.length;const subColorIndex=benchmarkIndex%tr.v.ui.COLORS[mainColorIndex].length;chart.getDataSeries(series).color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];if(benchmarkIndex===(this.benchmarkCount_-1)){hideValue+=benchmark[series];}
+finalData.push(benchmark);benchmarkIndex++;}
+submetricIndex++;}
+return{data:finalData,hide:hideValue};},filterByPercentile_(){const startPercentile=this.$.start.value;const endPercentile=this.$.end.value;if(startPercentile===''||endPercentile==='')return;const length=this.data_.length/(this.benchmarkCount_+1);const startIndex=this.getPercentileIndex_(startPercentile,length);const endIndex=this.getPercentileIndex_(endPercentile,length);this.charts_.get(PAGE_BREAKDOWN_KEY).data=this.data_.slice(startIndex,endIndex);},getPercentileIndex_(percentile,arrayLength){const index=Math.ceil(arrayLength*(percentile/100.0));if(index===-1)return 0;if(index>=arrayLength)return arrayLength;return index*this.benchmarkCount_;},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_].filter(group=>{if(group.group)return group.group.match(query);return false;});if(filteredData.length<1){this.$.search_error.style.display='block';return;}
+const page=filteredData[0].group;const title=this.title_+' Breakdown: '+page;const metricToSubmetricMap=this.submetricsData_.get(page);let totalSubmetrics=0;for(const submetrics of metricToSubmetricMap.values()){for(const benchmark of submetrics.values()){totalSubmetrics+=benchmark.length;}}
+const width=tr.b.math.clamp(totalSubmetrics*150,300,700);const height=tr.b.math.clamp(totalSubmetrics*this.benchmarkCount_*30,300,700);const childChart=this.initializeChildChart_(title,height,width);const childData=[];let hide=0;let metricIndex=0;for(const submetrics of metricToSubmetricMap.values()){const submetricsData=this.processSubmetrics_(childChart,submetrics,hide,metricIndex);childData.push(...submetricsData.data);hide=submetricsData.hide;metricIndex++;}
+childChart.data=childData;},});});'use strict';Polymer({is:'tr-v-ui-raster-visualization',ready(){this.$.pageSelector.addEventListener('click',()=>{this.selectPage_();});this.$.search_page.addEventListener('keydown',(e)=>{if(e.key==='Enter')this.searchByPage_();});this.$.search_button.addEventListener('click',()=>{this.searchByPage_();});},build(chartData){this.data_=chartData;const aggregateChart=this.createChart_('Aggregate Data by Run');Polymer.dom(this.$.aggregateContainer).appendChild(aggregateChart);aggregateChart.enableToolTip=true;aggregateChart.toolTipCallBack=(rect)=>this.openBenchmarkChart_(rect);this.setChartColors_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY));aggregateChart.data=this.data_.get(tr.v.ui.AGGREGATE_KEY);this.setChartSize_(aggregateChart,this.data_.get(tr.v.ui.AGGREGATE_KEY).length);for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;const option=document.createElement('option');option.textContent=page;option.value=page;this.$.pageSelector.appendChild(option);}},setChartSize_(chart,pageCount,dataLength){chart.graphHeight=tr.b.math.clamp(pageCount*25,175,1000);chart.graphWidth=tr.b.math.clamp(pageCount*25,500,1000);},setChartColors_(chart,data){const metrics=new Map();let count=0;for(const thread of tr.v.ui.FRAME.values()){for(const metric of thread.keys()){metrics.set(metric,count);count++;}}
+for(let i=0;i<Math.floor(data.length/tr.v.ui.FRAME.length);++i){let j=0;for(const[threadName,thread]of tr.v.ui.FRAME.entries()){for(const metric of thread.keys()){let color='transparent';if(thread.get(metric)){const mainColorIndex=metrics.get(metric)%tr.v.ui.COLORS.length;const subColorIndex=i%tr.v.ui.COLORS[mainColorIndex].length;color=tr.v.ui.COLORS[mainColorIndex][subColorIndex];}
+const series=metric+'-'+data[i*2+j].x+'-'+threadName;chart.getDataSeries(series).color=color;chart.getDataSeries(series).title=!i?metric:'';}
+j++;}}},createChart_(title){const newChart=new tr.ui.b.NameBarChart();newChart.chartTitle=title;newChart.xAxisLabel='ms';newChart.hideLegend=false;newChart.showTitleInLegend=true;newChart.hideYAxis=true;newChart.isStacked=true;newChart.displayXInHover=true;newChart.isGrouped=true;return newChart;},openBenchmarkChart_(rect){const benchmarkIndex=Math.floor(rect.index/tr.v.ui.FRAME.length);const title=rect.datum.x;const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const chart=this.createChart_(title);div.appendChild(chart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const newDataSet=[];for(const page of this.data_.keys()){if(page===tr.v.ui.AGGREGATE_KEY)continue;for(let i=0;i<tr.v.ui.FRAME.length;i++){newDataSet.push(this.data_.get(page)[benchmarkIndex*tr.v.ui.FRAME.length+i]);}}
+this.setChartColors_(chart,newDataSet);chart.data=newDataSet;this.setChartSize_(chart,newDataSet.length);},selectPage_(){const div=document.createElement('div');const page=this.$.pageSelector.value;if(page==='')return;Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},searchByPage_(){const criteria=this.$.search_page.value;if(criteria==='')return;const query=new RegExp(criteria);const filteredData=[...this.data_.keys()].filter(page=>page.match(query));if(filteredData.length<1){this.$.search_error.style.display='block';return;}
+const page=filteredData[0];const div=document.createElement('div');Polymer.dom(this.$.pageContainer).insertBefore(div,this.$.pageContainer.firstChild);const pageChart=this.createChart_(page);div.appendChild(pageChart);const button=this.initializeCloseButton_(div,this.$.pageContainer);div.appendChild(button);const pageData=this.data_.get(page);this.setChartColors_(pageChart,pageData);pageChart.data=pageData;this.setChartSize_(pageChart,pageData.length);},initializeCloseButton_(div,parent){const button=this.$.close.cloneNode(true);button.style.display='inline-block';button.addEventListener('click',()=>{Polymer.dom(parent).removeChild(div);});return button;},});'use strict';tr.exportTo('tr.v.ui',function(){const STATISTICS_KEY='statistics';const SUBMETRICS_KEY='submetrics';const AGGREGATE_KEY='aggregate';const RASTER_START_METRIC_KEY='pipeline:begin_frame_to_raster_start';const COLORS=[['#FFD740','#FFC400','#FFAB00','#E29800'],['#FF6E40','#FF3D00','#DD2C00','#A32000'],['#40C4FF','#00B0FF','#0091EA','#006DAF'],['#89C641','#54B503','#4AA510','#377A0D'],['#B388FF','#7C4DFF','#651FFF','#6200EA'],['#FF80AB','#FF4081','#F50057','#C51162'],['#FFAB40','#FF9100','#FF6D00','#D65C02'],['#8C9EFF','#536DFE','#3D5AFE','#304FFE']];const FRAME=[new Map([['pipeline:begin_frame_to_raster_start',false],['pipeline:begin_frame_to_raster_end',true]]),new Map([['pipeline:begin_frame_transport',true],['pipeline:begin_frame_to_frame_submission',true],['pipeline:frame_submission_to_display',true],['pipeline:draw',true]])];const METRICS=new Map([['Pipeline',['pipeline:begin_frame_transport','pipeline:begin_frame_to_frame_submission','pipeline:frame_submission_to_display','pipeline:draw']],['Thread',['thread_browser_cpu_time_per_frame','thread_display_compositor_cpu_time_per_frame','thread_GPU_cpu_time_per_frame','thread_IO_cpu_time_per_frame','thread_other_cpu_time_per_frame','thread_raster_cpu_time_per_frame','thread_renderer_compositor_cpu_time_per_frame','thread_renderer_main_cpu_time_per_frame']]]);function getValueFromMap(key,map){let retrievedValue=map.get(key);if(!retrievedValue){retrievedValue=new Map();map.set(key,retrievedValue);}
+return retrievedValue;}
+Polymer({is:'tr-v-ui-visualizations-data-container',created(){this.orderedBenchmarks_=[];this.groupedData_=new Map();},build(leafHistograms,histograms){if(!leafHistograms||leafHistograms.length<1||!histograms||histograms.length<1){this.$.data_error.style.display='block';return;}
+this.processHistograms_(this.groupHistograms_(histograms),this.groupHistograms_(leafHistograms));this.buildCharts_();},processHistograms_(histograms,leafHistograms){const benchmarkStartGrouping=tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.BENCHMARK_START);const benchmarkToStartTime=new Map();for(const[metric,benchmarks]of histograms.entries()){for(const[benchmark,pages]of leafHistograms.get(metric).entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){const aggregateToBenchmarkMap=getValueFromMap(AGGREGATE_KEY,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,aggregateToBenchmarkMap);benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running]]));}}}
+for(const[benchmark,pages]of benchmarks.entries()){for(const[page,histograms]of pages.entries()){for(const histogram of histograms){if(!benchmarkToStartTime.get(benchmark)){benchmarkToStartTime.set(benchmark,benchmarkStartGrouping.callback(histogram));}
+const pageToBenchmarkMap=getValueFromMap(page,this.groupedData_);const benchmarkToMetricMap=getValueFromMap(benchmark,pageToBenchmarkMap);const mergedSubmetrics=new tr.v.d.DiagnosticMap();for(const bin of histogram.allBins){for(const map of bin.diagnosticMaps){mergedSubmetrics.addDiagnostics(map);}}
+if(benchmarkToMetricMap.get(metric))continue;benchmarkToMetricMap.set(metric,new Map([[STATISTICS_KEY,histogram.running],[SUBMETRICS_KEY,mergedSubmetrics.get('breakdown')]]));}}}}
+this.orderedBenchmarks_=this.sortBenchmarks_(benchmarkToStartTime);},groupHistograms_(histograms){const groupings=[tr.v.HistogramGrouping.HISTOGRAM_NAME,tr.v.HistogramGrouping.DISPLAY_LABEL,tr.v.HistogramGrouping.BY_KEY.get(tr.v.d.RESERVED_NAMES.STORIES)];return histograms.groupHistogramsRecursively(groupings);},sortBenchmarks_(benchmarks){return Array.from(benchmarks.keys()).sort((a,b)=>{Date.parse(benchmarks.get(a))-Date.parse(benchmarks.get(b));});},getSeriesKey_(metric,benchmark){return metric+'-'+benchmark;},buildCharts_(){const rasterDataToBePassed=this.buildRasterChart_();this.$.rasterVisualization.build(rasterDataToBePassed);for(const chartName of METRICS.keys()){const metricsDataToBePassed=this.buildMetricsData_(chartName);const newChart=this.$.metricsVisualization.cloneNode(true);newChart.style.display='block';Polymer.dom(this.$.metrics_container).appendChild(newChart);newChart.build(metricsDataToBePassed);}},buildRasterChart_(){const orderedPages=[...this.groupedData_.keys()].filter((page)=>this.filterPagesWithoutRasterMetric_(page)).sort((a,b)=>this.sortByRasterStart_(a,b));const allChartData=new Map();for(const page of orderedPages){const pageMap=this.groupedData_.get(page);let chartData=[];for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const benchmarkMap=pageMap.get(benchmark);const benchmarkData=[];if(benchmarkMap.get(RASTER_START_METRIC_KEY)===undefined){continue;}
+for(const[threadName,thread]of FRAME.entries()){const data={x:benchmark,hide:0};if(page!==AGGREGATE_KEY)data.group=page;let rasterBegin=0;for(const metric of thread.keys()){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,data.x+'-'+threadName);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;let roundedMean=Math.round(mean*100)/100;if(metric===RASTER_START_METRIC_KEY){rasterBegin=roundedMean;}else if(metric==='pipeline:begin_frame_to_raster_end'){roundedMean-=rasterBegin;}
+data[key]=roundedMean;}
+benchmarkData.push(data);}
+chartData=chartData.concat(benchmarkData);}
+allChartData.set(page,chartData);}
+return allChartData;},buildMetricsData_(chartName){const orderedPages=[...this.groupedData_.keys()].sort((a,b)=>this.sortByTotal_(a,b,chartName));const chartData=[];const aggregateChart=[];for(const page of orderedPages){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){if(!pageMap.has(benchmark))continue;const data={x:benchmark,group:page};const benchmarkMap=pageMap.get(benchmark);for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const key=this.getSeriesKey_(metric,benchmark);const stats=metricMap.get(STATISTICS_KEY);const mean=stats?stats.mean:0;data[key]=Math.round(mean*100)/100;}
+if(page===AGGREGATE_KEY){aggregateChart.push(data);}else{chartData.push(data);}}
+chartData.push({});}
+chartData.shift();return{title:chartName,aggregate:aggregateChart,page:chartData,submetrics:this.processSubmetricsData_(chartName)};},submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap){let submetricToBenchmarkMap=metricToSubmetricMap.get(submetric);if(!submetricToBenchmarkMap){submetricToBenchmarkMap=[];metricToSubmetricMap.set(submetric,submetricToBenchmarkMap);}
+const data={x:submetric,hide:0,group:benchmark};const mean=value;const roundedMean=Math.round(mean*100)/100;if(!roundedMean)return;data[this.getSeriesKey_(submetric,benchmark)]=roundedMean;submetricToBenchmarkMap.push(data);},processSubmetricsData_(chartName){const submetrics=new Map();for(const[page,pageMap]of this.groupedData_.entries()){if(page===AGGREGATE_KEY)continue;const pageToMetricMap=getValueFromMap(page,submetrics);for(const benchmark of this.orderedBenchmarks_){const benchmarkMap=pageMap.get(benchmark);if(!benchmarkMap)continue;for(const metric of METRICS.get(chartName)){const metricMap=benchmarkMap.get(metric);const metricToSubmetricMap=getValueFromMap(metric,pageToMetricMap);const submetrics=metricMap.get(SUBMETRICS_KEY);if(!submetrics){this.submetricsHelper_(metric,metricMap.get(STATISTICS_KEY),benchmark,metricToSubmetricMap);continue;}
+for(const[submetric,value]of[...submetrics]){this.submetricsHelper_(submetric,value,benchmark,metricToSubmetricMap);}}}}
+return submetrics;},sortByTotal_(a,b,chartName){if(a===AGGREGATE_KEY)return-1;if(b===AGGREGATE_KEY)return 1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(metric);const aStats=aMetricMap.get(STATISTICS_KEY);aValue+=aStats?aStats.mean:0;}}
+let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){for(const metric of METRICS.get(chartName)){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(metric);const bStats=bMetricMap.get(STATISTICS_KEY);bValue+=bStats?bStats.mean:0;}}
+return aValue-bValue;},filterPagesWithoutRasterMetric_(page){const pageMap=this.groupedData_.get(page);for(const benchmark of this.orderedBenchmarks_){const pageMetricMap=pageMap.get(benchmark);if(!pageMetricMap)continue;const wantedMetric=pageMetricMap.get(RASTER_START_METRIC_KEY);if(wantedMetric!==undefined)return true;}
+return false;},sortByRasterStart_(a,b){if(a===AGGREGATE_KEY)return 1;if(b===AGGREGATE_KEY)return-1;let aValue=0;const aMap=this.groupedData_.get(a);if(aMap.get(this.orderedBenchmarks_[0])!==undefined){const aMetricMap=aMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const aStats=aMetricMap.get(STATISTICS_KEY);aValue=aStats?aStats.mean:0;}
+let bValue=0;const bMap=this.groupedData_.get(b);if(bMap.get(this.orderedBenchmarks_[0])!==undefined){const bMetricMap=bMap.get(this.orderedBenchmarks_[0]).get(RASTER_START_METRIC_KEY);const bStats=bMetricMap.get(STATISTICS_KEY);bValue=bStats?bStats.mean:0;}
+return bValue-aValue;},});return{STATISTICS_KEY,SUBMETRICS_KEY,AGGREGATE_KEY,COLORS,FRAME,METRICS,getValueFromMap,};});'use strict';tr.exportTo('tr.v.ui',function(){Polymer({is:'tr-v-ui-histogram-set-view',listeners:{export:'onExport_',loadVisualization:'onLoadVisualization_'},created(){this.brushingStateController_=new tr.ui.NullBrushingStateController();this.viewState_=new tr.v.ui.HistogramSetViewState();this.visualizationLoaded_=false;},ready(){this.$.table.viewState=this.viewState;this.$.controls.viewState=this.viewState;},attached(){this.brushingStateController.parentController=tr.c.BrushingStateController.getControllerForElement(this.parentNode);},get brushingStateController(){return this.brushingStateController_;},get viewState(){return this.viewState_;},get histograms(){return this.$.table.histograms;},async build(histograms,opt_options){const options=opt_options||{};const progress=options.progress||(()=>Promise.resolve());if(options.helpHref)this.$.controls.helpHref=options.helpHref;if(options.feedbackHref){this.$.controls.feedbackHref=options.feedbackHref;}
+if(histograms===undefined||histograms.length===0){this.$.container.style.display='none';this.$.zero.style.display='block';this.style.display='block';return;}
+this.$.zero.style.display='none';this.$.container.style.display='block';this.$.container.style.maxHeight=(window.innerHeight-16)+'px';const buildMark=tr.b.Timing.mark('histogram-set-view','build');await progress('Finding important Histograms...');const sourceHistogramsMark=tr.b.Timing.mark('histogram-set-view','sourceHistograms');const sourceHistograms=histograms.sourceHistograms;sourceHistogramsMark.end();this.$.controls.showAllEnabled=(sourceHistograms.length!==histograms.length);await progress('Collecting parameters...');const collectParametersMark=tr.b.Timing.mark('histogram-set-view','collectParameters');const parameterCollector=new tr.v.HistogramParameterCollector();parameterCollector.process(histograms);this.$.controls.baseStatisticNames=parameterCollector.statisticNames;this.$.controls.possibleGroupings=parameterCollector.possibleGroupings;const displayLabels=parameterCollector.labels;this.$.controls.displayLabels=displayLabels;collectParametersMark.end();const hist=[...histograms][0];const benchmarks=hist.diagnostics.get(tr.v.d.RESERVED_NAMES.BENCHMARKS);let enable=false;if(benchmarks!==undefined&&benchmarks.length>0){for(const benchmark of benchmarks){if(benchmark.includes('rendering')){enable=true;break;}}}
+this.$.controls.enableVisualization=enable;await this.$.table.build(histograms,sourceHistograms,displayLabels,progress);buildMark.end();},onExport_(event){const mark=tr.b.Timing.mark('histogram-set-view','export'+
+(event.merged?'Merged':'Raw')+event.format.toUpperCase());const histograms=event.merged?this.$.table.leafHistograms:this.histograms;let blob;if(event.format==='csv'){const csv=new tr.v.CSVBuilder(histograms);csv.build();blob=new window.Blob([csv.toString()],{type:'text/csv'});}else if(event.format==='json'){blob=new window.Blob([JSON.stringify(histograms.asDicts())],{type:'text/json'});}else{throw new Error(`Unable to export format "${event.format}"`);}
+const path=window.location.pathname.split('/');const basename=path[path.length-1].split('.')[0]||'histograms';const anchor=document.createElement('a');anchor.download=`${basename}.${event.format}`;anchor.href=window.URL.createObjectURL(blob);anchor.click();mark.end();},onLoadVisualization_(event){if(!this.visualizationLoaded_){this.$.visualizations.style.display='block';this.$.visualizations.build(this.$.table.leafHistograms,this.histograms);this.visualizationLoaded_=true;}else if(this.$.visualizations.style.display==='none'){this.$.visualizations.style.display='block';}else{this.$.visualizations.style.display='none';}},});return{};});'use strict';tr.exportTo('tr.ui',function(){Polymer({is:'tr-ui-sp-metrics-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.model_=undefined;this.rangeOfInterest_=undefined;this.metricLatenciesMs_=[];this.metrics_=[];tr.metrics.MetricRegistry.getAllRegisteredTypeInfos().forEach(function(m){if(m.constructor.name==='sampleMetric')return;this.metrics_.push({label:m.constructor.name,value:m.constructor.name});},this);this.metrics_.sort((x,y)=>x.label.localeCompare(y.label));this.settingsKey_='metrics-side-panel-metric-name';this.currentMetricName_='responsivenessMetric';const metricSelector=tr.ui.b.createSelector(this,'currentMetricName_',this.settingsKey_,this.currentMetricName_,this.metrics_);Polymer.dom(this.$.top_left_controls).appendChild(metricSelector);metricSelector.addEventListener('change',this.onMetricChange_.bind(this));this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.recomputeButton_=tr.ui.b.createButton('Recompute',this.onRecompute_,this);Polymer.dom(this.$.top_left_controls).appendChild(this.recomputeButton_);this.$.results.addEventListener('display-ready',()=>{this.$.results.style.display='';});},async build(model){this.model_=model;await this.updateContents_();},get metricLatencyMs(){return tr.b.math.Statistics.mean(this.metricLatenciesMs_);},onMetricChange_(){this.currentMetricTypeInfo_=tr.metrics.MetricRegistry.findTypeInfoWithName(this.currentMetricName_);this.metricLatenciesMs_=[];this.updateContents_();},onRecompute_(){this.updateContents_();},get textLabel(){return'Metrics';},supportsModel(m){if(!m){return{supported:false,reason:'No model available'};}
+return{supported:true};},get model(){return this.model_;},set model(model){this.build(model);},get selection(){},set selection(_){},get rangeOfInterest(){return this.rangeOfInterest_;},set rangeOfInterest(range){this.rangeOfInterest_=range;if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest){if((this.metricLatencyMs===undefined)||(this.metricLatencyMs<100)){this.updateContents_();}else{this.recomputeButton_.style.background='red';}}},async updateContents_(){Polymer.dom(this.$.error).textContent='';this.$.results.style.display='none';if(!this.model_){Polymer.dom(this.$.error).textContent='Missing model';return;}
+const options={metrics:[this.currentMetricName_]};if(this.currentMetricTypeInfo_&&this.currentMetricTypeInfo_.metadata.supportsRangeOfInterest&&this.rangeOfInterest&&!this.rangeOfInterest.isEmpty){options.rangeOfInterest=this.rangeOfInterest;}
+const startDate=new Date();const addFailureCb=failure=>{Polymer.dom(this.$.error).textContent=failure.description;};const histograms=tr.metrics.runMetrics(this.model_,options,addFailureCb);this.metricLatenciesMs_.push(new Date()-startDate);while(this.metricLatenciesMs_.length>20){this.metricLatenciesMs_.shift();}
+this.recomputeButton_.style.background='';await this.$.results.build(histograms);}});tr.ui.side_panel.SidePanelRegistry.register(function(){return document.createElement('tr-ui-sp-metrics-side-panel');});return{};});'use strict';Polymer({is:'tr-ui-e-s-alerts-side-panel',behaviors:[tr.ui.behaviors.SidePanel],ready(){this.rangeOfInterest_=new tr.b.math.Range();this.selection_=undefined;},get model(){return this.model_;},set model(model){this.model_=model;this.updateContents_();},set selection(selection){},set rangeOfInterest(rangeOfInterest){},selectAlertsOfType(alertTypeString){const alertsOfType=this.model_.alerts.filter(function(alert){return alert.title===alertTypeString;});const event=new tr.model.RequestSelectionChangeEvent();event.selection=new tr.model.EventSet(alertsOfType);this.dispatchEvent(event);},alertsByType_(alerts){const alertsByType={};alerts.forEach(function(alert){if(!alertsByType[alert.title]){alertsByType[alert.title]=[];}
+alertsByType[alert.title].push(alert);});return alertsByType;},alertsTableRows_(alertsByType){return Object.keys(alertsByType).map(function(key){return{alertType:key,count:alertsByType[key].length};});},alertsTableColumns_(){return[{title:'Alert type',value(row){return row.alertType;},width:'180px'},{title:'Count',width:'100%',value(row){return row.count;}}];},createAlertsTable_(alerts){const alertsByType=this.alertsByType_(alerts);const table=document.createElement('tr-ui-b-table');table.tableColumns=this.alertsTableColumns_();table.tableRows=this.alertsTableRows_(alertsByType);table.selectionMode=tr.ui.b.TableFormat.SelectionMode.ROW;table.addEventListener('selection-changed',function(e){const row=table.selectedTableRow;if(row){this.selectAlertsOfType(row.alertType);}}.bind(this));return table;},updateContents_(){Polymer.dom(this.$.result_area).textContent='';if(this.model_===undefined)return;const panel=this.createAlertsTable_(this.model_.alerts);Polymer.dom(this.$.result_area).appendChild(panel);},supportsModel(m){if(m===undefined){return{supported:false,reason:'Unknown tracing model'};}else if(m.alerts.length===0){return{supported:false,reason:'No alerts in tracing model'};}
+return{supported:true};},get textLabel(){return'Alerts';}});tr.ui.side_panel.SidePanelRegistry.register(function(){return document.createElement('tr-ui-e-s-alerts-side-panel');});
+</script>
+</head>
+  <body>
+  </body>
+</html>
diff --git a/runtime/observatory_2/web/third_party/webcomponents.min.js b/runtime/observatory_2/web/third_party/webcomponents.min.js
new file mode 100644
index 0000000..ad8196b
--- /dev/null
+++ b/runtime/observatory_2/web/third_party/webcomponents.min.js
@@ -0,0 +1,14 @@
+/**
+ * @license
+ * Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
+ * This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
+ * The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
+ * The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
+ * Code distributed by Google as part of the polymer project is also
+ * subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
+ */
+// @version 0.7.24
+!function(){window.WebComponents=window.WebComponents||{flags:{}};var e="webcomponents.js",t=document.querySelector('script[src*="'+e+'"]'),n={};if(!n.noOpts){if(location.search.slice(1).split("&").forEach(function(e){var t,r=e.split("=");r[0]&&(t=r[0].match(/wc-(.+)/))&&(n[t[1]]=r[1]||!0)}),t)for(var r,o=0;r=t.attributes[o];o++)"src"!==r.name&&(n[r.name]=r.value||!0);if(n.log&&n.log.split){var i=n.log.split(",");n.log={},i.forEach(function(e){n.log[e]=!0})}else n.log={}}n.shadow=n.shadow||n.shadowdom||n.polyfill,"native"===n.shadow?n.shadow=!1:n.shadow=n.shadow||!HTMLElement.prototype.createShadowRoot,n.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=n.register),WebComponents.flags=n}(),WebComponents.flags.shadow&&("undefined"==typeof WeakMap&&!function(){var e=Object.defineProperty,t=Date.now()%1e9,n=function(){this.name="__st"+(1e9*Math.random()>>>0)+(t++ +"__")};n.prototype={set:function(t,n){var r=t[this.name];return r&&r[0]===t?r[1]=n:e(t,this.name,{value:[t,n],writable:!0}),this},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0},"delete":function(e){var t=e[this.name];return!(!t||t[0]!==e)&&(t[0]=t[1]=void 0,!0)},has:function(e){var t=e[this.name];return!!t&&t[0]===e}},window.WeakMap=n}(),window.ShadowDOMPolyfill={},function(e){"use strict";function t(){if("undefined"!=typeof chrome&&chrome.app&&chrome.app.runtime)return!1;if(navigator.getDeviceStorage)return!1;try{var e=new Function("return true;");return e()}catch(t){return!1}}function n(e){if(!e)throw new Error("Assertion failed")}function r(e,t){for(var n=W(t),r=0;r<n.length;r++){var o=n[r];A(e,o,F(t,o))}return e}function o(e,t){for(var n=W(t),r=0;r<n.length;r++){var o=n[r];switch(o){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":continue}A(e,o,F(t,o))}return e}function i(e,t){for(var n=0;n<t.length;n++)if(t[n]in e)return t[n]}function a(e,t,n){U.value=n,A(e,t,U)}function s(e,t){var n=e.__proto__||Object.getPrototypeOf(e);if(q)try{W(n)}catch(r){n=n.__proto__}var o=R.get(n);if(o)return o;var i=s(n),a=E(i);return g(n,a,t),a}function c(e,t){w(e,t,!0)}function l(e,t){w(t,e,!1)}function u(e){return/^on[a-z]+$/.test(e)}function d(e){return/^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test(e)}function p(e){return k&&d(e)?new Function("return this.__impl4cf1e782hg__."+e):function(){return this.__impl4cf1e782hg__[e]}}function h(e){return k&&d(e)?new Function("v","this.__impl4cf1e782hg__."+e+" = v"):function(t){this.__impl4cf1e782hg__[e]=t}}function f(e){return k&&d(e)?new Function("return this.__impl4cf1e782hg__."+e+".apply(this.__impl4cf1e782hg__, arguments)"):function(){return this.__impl4cf1e782hg__[e].apply(this.__impl4cf1e782hg__,arguments)}}function m(e,t){try{return e===window&&"showModalDialog"===t?B:Object.getOwnPropertyDescriptor(e,t)}catch(n){return B}}function w(t,n,r,o){for(var i=W(t),a=0;a<i.length;a++){var s=i[a];if("polymerBlackList_"!==s&&!(s in n||t.polymerBlackList_&&t.polymerBlackList_[s])){q&&t.__lookupGetter__(s);var c,l,d=m(t,s);if("function"!=typeof d.value){var w=u(s);c=w?e.getEventHandlerGetter(s):p(s),(d.writable||d.set||V)&&(l=w?e.getEventHandlerSetter(s):h(s));var v=V||d.configurable;A(n,s,{get:c,set:l,configurable:v,enumerable:d.enumerable})}else r&&(n[s]=f(s))}}}function v(e,t,n){if(null!=e){var r=e.prototype;g(r,t,n),o(t,e)}}function g(e,t,r){var o=t.prototype;n(void 0===R.get(e)),R.set(e,t),I.set(o,e),c(e,o),r&&l(o,r),a(o,"constructor",t),t.prototype=o}function b(e,t){return R.get(t.prototype)===e}function y(e){var t=Object.getPrototypeOf(e),n=s(t),r=E(n);return g(t,r,e),r}function E(e){function t(t){e.call(this,t)}var n=Object.create(e.prototype);return n.constructor=t,t.prototype=n,t}function _(e){return e&&e.__impl4cf1e782hg__}function S(e){return!_(e)}function T(e){if(null===e)return null;n(S(e));var t=e.__wrapper8e3dd93a60__;return null!=t?t:e.__wrapper8e3dd93a60__=new(s(e,e))(e)}function M(e){return null===e?null:(n(_(e)),e.__impl4cf1e782hg__)}function O(e){return e.__impl4cf1e782hg__}function L(e,t){t.__impl4cf1e782hg__=e,e.__wrapper8e3dd93a60__=t}function N(e){return e&&_(e)?M(e):e}function C(e){return e&&!_(e)?T(e):e}function j(e,t){null!==t&&(n(S(e)),n(void 0===t||_(t)),e.__wrapper8e3dd93a60__=t)}function D(e,t,n){G.get=n,A(e.prototype,t,G)}function H(e,t){D(e,t,function(){return T(this.__impl4cf1e782hg__[t])})}function x(e,t){e.forEach(function(e){t.forEach(function(t){e.prototype[t]=function(){var e=C(this);return e[t].apply(e,arguments)}})})}var R=new WeakMap,I=new WeakMap,P=Object.create(null),k=t(),A=Object.defineProperty,W=Object.getOwnPropertyNames,F=Object.getOwnPropertyDescriptor,U={value:void 0,configurable:!0,enumerable:!1,writable:!0};W(window);var q=/Firefox/.test(navigator.userAgent),B={get:function(){},set:function(e){},configurable:!0,enumerable:!0},V=function(){var e=Object.getOwnPropertyDescriptor(Node.prototype,"nodeType");return e&&!e.get&&!e.set}(),G={get:void 0,configurable:!0,enumerable:!0};e.addForwardingProperties=c,e.assert=n,e.constructorTable=R,e.defineGetter=D,e.defineWrapGetter=H,e.forwardMethodsToWrapper=x,e.isIdentifierName=d,e.isWrapper=_,e.isWrapperFor=b,e.mixin=r,e.nativePrototypeTable=I,e.oneOf=i,e.registerObject=y,e.registerWrapper=v,e.rewrap=j,e.setWrapper=L,e.unsafeUnwrap=O,e.unwrap=M,e.unwrapIfNeeded=N,e.wrap=T,e.wrapIfNeeded=C,e.wrappers=P}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t,n){return{index:e,removed:t,addedCount:n}}function n(){}var r=0,o=1,i=2,a=3;n.prototype={calcEditDistances:function(e,t,n,r,o,i){for(var a=i-o+1,s=n-t+1,c=new Array(a),l=0;l<a;l++)c[l]=new Array(s),c[l][0]=l;for(var u=0;u<s;u++)c[0][u]=u;for(var l=1;l<a;l++)for(var u=1;u<s;u++)if(this.equals(e[t+u-1],r[o+l-1]))c[l][u]=c[l-1][u-1];else{var d=c[l-1][u]+1,p=c[l][u-1]+1;c[l][u]=d<p?d:p}return c},spliceOperationsFromEditDistances:function(e){for(var t=e.length-1,n=e[0].length-1,s=e[t][n],c=[];t>0||n>0;)if(0!=t)if(0!=n){var l,u=e[t-1][n-1],d=e[t-1][n],p=e[t][n-1];l=d<p?d<u?d:u:p<u?p:u,l==u?(u==s?c.push(r):(c.push(o),s=u),t--,n--):l==d?(c.push(a),t--,s=d):(c.push(i),n--,s=p)}else c.push(a),t--;else c.push(i),n--;return c.reverse(),c},calcSplices:function(e,n,s,c,l,u){var d=0,p=0,h=Math.min(s-n,u-l);if(0==n&&0==l&&(d=this.sharedPrefix(e,c,h)),s==e.length&&u==c.length&&(p=this.sharedSuffix(e,c,h-d)),n+=d,l+=d,s-=p,u-=p,s-n==0&&u-l==0)return[];if(n==s){for(var f=t(n,[],0);l<u;)f.removed.push(c[l++]);return[f]}if(l==u)return[t(n,[],s-n)];for(var m=this.spliceOperationsFromEditDistances(this.calcEditDistances(e,n,s,c,l,u)),f=void 0,w=[],v=n,g=l,b=0;b<m.length;b++)switch(m[b]){case r:f&&(w.push(f),f=void 0),v++,g++;break;case o:f||(f=t(v,[],0)),f.addedCount++,v++,f.removed.push(c[g]),g++;break;case i:f||(f=t(v,[],0)),f.addedCount++,v++;break;case a:f||(f=t(v,[],0)),f.removed.push(c[g]),g++}return f&&w.push(f),w},sharedPrefix:function(e,t,n){for(var r=0;r<n;r++)if(!this.equals(e[r],t[r]))return r;return n},sharedSuffix:function(e,t,n){for(var r=e.length,o=t.length,i=0;i<n&&this.equals(e[--r],t[--o]);)i++;return i},calculateSplices:function(e,t){return this.calcSplices(e,0,e.length,t,0,t.length)},equals:function(e,t){return e===t}},e.ArraySplice=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(){a=!1;var e=i.slice(0);i=[];for(var t=0;t<e.length;t++)(0,e[t])()}function n(e){i.push(e),a||(a=!0,r(t,0))}var r,o=window.MutationObserver,i=[],a=!1;if(o){var s=1,c=new o(t),l=document.createTextNode(s);c.observe(l,{characterData:!0}),r=function(){s=(s+1)%2,l.data=s}}else r=window.setTimeout;e.setEndOfMicrotask=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.scheduled_||(e.scheduled_=!0,f.push(e),m||(u(n),m=!0))}function n(){for(m=!1;f.length;){var e=f;f=[],e.sort(function(e,t){return e.uid_-t.uid_});for(var t=0;t<e.length;t++){var n=e[t];n.scheduled_=!1;var r=n.takeRecords();i(n),r.length&&n.callback_(r,n)}}}function r(e,t){this.type=e,this.target=t,this.addedNodes=new p.NodeList,this.removedNodes=new p.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function o(e,t){for(;e;e=e.parentNode){var n=h.get(e);if(n)for(var r=0;r<n.length;r++){var o=n[r];o.options.subtree&&o.addTransientObserver(t)}}}function i(e){for(var t=0;t<e.nodes_.length;t++){var n=e.nodes_[t],r=h.get(n);if(!r)return;for(var o=0;o<r.length;o++){var i=r[o];i.observer===e&&i.removeTransientObservers()}}}function a(e,n,o){for(var i=Object.create(null),a=Object.create(null),s=e;s;s=s.parentNode){var c=h.get(s);if(c)for(var l=0;l<c.length;l++){var u=c[l],d=u.options;if((s===e||d.subtree)&&("attributes"!==n||d.attributes)&&("attributes"!==n||!d.attributeFilter||null===o.namespace&&d.attributeFilter.indexOf(o.name)!==-1)&&("characterData"!==n||d.characterData)&&("childList"!==n||d.childList)){var p=u.observer;i[p.uid_]=p,("attributes"===n&&d.attributeOldValue||"characterData"===n&&d.characterDataOldValue)&&(a[p.uid_]=o.oldValue)}}}for(var f in i){var p=i[f],m=new r(n,e);"name"in o&&"namespace"in o&&(m.attributeName=o.name,m.attributeNamespace=o.namespace),o.addedNodes&&(m.addedNodes=o.addedNodes),o.removedNodes&&(m.removedNodes=o.removedNodes),o.previousSibling&&(m.previousSibling=o.previousSibling),o.nextSibling&&(m.nextSibling=o.nextSibling),void 0!==a[f]&&(m.oldValue=a[f]),t(p),p.records_.push(m)}}function s(e){if(this.childList=!!e.childList,this.subtree=!!e.subtree,"attributes"in e||!("attributeOldValue"in e||"attributeFilter"in e)?this.attributes=!!e.attributes:this.attributes=!0,"characterDataOldValue"in e&&!("characterData"in e)?this.characterData=!0:this.characterData=!!e.characterData,!this.attributes&&(e.attributeOldValue||"attributeFilter"in e)||!this.characterData&&e.characterDataOldValue)throw new TypeError;if(this.characterData=!!e.characterData,this.attributeOldValue=!!e.attributeOldValue,this.characterDataOldValue=!!e.characterDataOldValue,"attributeFilter"in e){if(null==e.attributeFilter||"object"!=typeof e.attributeFilter)throw new TypeError;this.attributeFilter=w.call(e.attributeFilter)}else this.attributeFilter=null}function c(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++v,this.scheduled_=!1}function l(e,t,n){this.observer=e,this.target=t,this.options=n,this.transientObservedNodes=[]}var u=e.setEndOfMicrotask,d=e.wrapIfNeeded,p=e.wrappers,h=new WeakMap,f=[],m=!1,w=Array.prototype.slice,v=0;c.prototype={constructor:c,observe:function(e,t){e=d(e);var n,r=new s(t),o=h.get(e);o||h.set(e,o=[]);for(var i=0;i<o.length;i++)o[i].observer===this&&(n=o[i],n.removeTransientObservers(),n.options=r);n||(n=new l(this,e,r),o.push(n),this.nodes_.push(e))},disconnect:function(){this.nodes_.forEach(function(e){for(var t=h.get(e),n=0;n<t.length;n++){var r=t[n];if(r.observer===this){t.splice(n,1);break}}},this),this.records_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}},l.prototype={addTransientObserver:function(e){if(e!==this.target){t(this.observer),this.transientObservedNodes.push(e);var n=h.get(e);n||h.set(e,n=[]),n.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[];for(var t=0;t<e.length;t++)for(var n=e[t],r=h.get(n),o=0;o<r.length;o++)if(r[o]===this){r.splice(o,1);break}}},e.enqueueMutation=a,e.registerTransientObservers=o,e.wrappers.MutationObserver=c,e.wrappers.MutationRecord=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){this.root=e,this.parent=t}function n(e,t){if(e.treeScope_!==t){e.treeScope_=t;for(var r=e.shadowRoot;r;r=r.olderShadowRoot)r.treeScope_.parent=t;for(var o=e.firstChild;o;o=o.nextSibling)n(o,t)}}function r(n){if(n instanceof e.wrappers.Window,n.treeScope_)return n.treeScope_;var o,i=n.parentNode;return o=i?r(i):new t(n,null),n.treeScope_=o}t.prototype={get renderer(){return this.root instanceof e.wrappers.ShadowRoot?e.getRendererForHost(this.root.host):null},contains:function(e){for(;e;e=e.parent)if(e===this)return!0;return!1}},e.TreeScope=t,e.getTreeScope=r,e.setTreeScope=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e instanceof G.ShadowRoot}function n(e){return A(e).root}function r(e,r){var s=[],c=e;for(s.push(c);c;){var l=a(c);if(l&&l.length>0){for(var u=0;u<l.length;u++){var p=l[u];if(i(p)){var h=n(p),f=h.olderShadowRoot;f&&s.push(f)}s.push(p)}c=l[l.length-1]}else if(t(c)){if(d(e,c)&&o(r))break;c=c.host,s.push(c)}else c=c.parentNode,c&&s.push(c)}return s}function o(e){if(!e)return!1;switch(e.type){case"abort":case"error":case"select":case"change":case"load":case"reset":case"resize":case"scroll":case"selectstart":return!0}return!1}function i(e){return e instanceof HTMLShadowElement}function a(t){return e.getDestinationInsertionPoints(t)}function s(e,t){if(0===e.length)return t;t instanceof G.Window&&(t=t.document);for(var n=A(t),r=e[0],o=A(r),i=l(n,o),a=0;a<e.length;a++){var s=e[a];if(A(s)===i)return s}return e[e.length-1]}function c(e){for(var t=[];e;e=e.parent)t.push(e);return t}function l(e,t){for(var n=c(e),r=c(t),o=null;n.length>0&&r.length>0;){var i=n.pop(),a=r.pop();if(i!==a)break;o=i}return o}function u(e,t,n){t instanceof G.Window&&(t=t.document);var o,i=A(t),a=A(n),s=r(n,e),o=l(i,a);o||(o=a.root);for(var c=o;c;c=c.parent)for(var u=0;u<s.length;u++){var d=s[u];if(A(d)===c)return d}return null}function d(e,t){return A(e)===A(t)}function p(e){if(!K.get(e)&&(K.set(e,!0),f(V(e),V(e.target)),P)){var t=P;throw P=null,t}}function h(e){switch(e.type){case"load":case"beforeunload":case"unload":return!0}return!1}function f(t,n){if($.get(t))throw new Error("InvalidStateError");$.set(t,!0),e.renderAllPending();var o,i,a;if(h(t)&&!t.bubbles){var s=n;s instanceof G.Document&&(a=s.defaultView)&&(i=s,o=[])}if(!o)if(n instanceof G.Window)a=n,o=[];else if(o=r(n,t),!h(t)){var s=o[o.length-1];s instanceof G.Document&&(a=s.defaultView)}return ne.set(t,o),m(t,o,a,i)&&w(t,o,a,i)&&v(t,o,a,i),J.set(t,re),Y["delete"](t,null),$["delete"](t),t.defaultPrevented}function m(e,t,n,r){var o=oe;if(n&&!g(n,e,o,t,r))return!1;for(var i=t.length-1;i>0;i--)if(!g(t[i],e,o,t,r))return!1;return!0}function w(e,t,n,r){var o=ie,i=t[0]||n;return g(i,e,o,t,r)}function v(e,t,n,r){for(var o=ae,i=1;i<t.length;i++)if(!g(t[i],e,o,t,r))return;n&&t.length>0&&g(n,e,o,t,r)}function g(e,t,n,r,o){var i=z.get(e);if(!i)return!0;var a=o||s(r,e);if(a===e){if(n===oe)return!0;n===ae&&(n=ie)}else if(n===ae&&!t.bubbles)return!0;if("relatedTarget"in t){var c=B(t),l=c.relatedTarget;if(l){if(l instanceof Object&&l.addEventListener){var d=V(l),p=u(t,e,d);if(p===a)return!0}else p=null;Z.set(t,p)}}J.set(t,n);var h=t.type,f=!1;X.set(t,a),Y.set(t,e),i.depth++;for(var m=0,w=i.length;m<w;m++){var v=i[m];if(v.removed)f=!0;else if(!(v.type!==h||!v.capture&&n===oe||v.capture&&n===ae))try{if("function"==typeof v.handler?v.handler.call(e,t):v.handler.handleEvent(t),ee.get(t))return!1}catch(g){P||(P=g)}}if(i.depth--,f&&0===i.depth){var b=i.slice();i.length=0;for(var m=0;m<b.length;m++)b[m].removed||i.push(b[m])}return!Q.get(t)}function b(e,t,n){this.type=e,this.handler=t,this.capture=Boolean(n)}function y(e,t){if(!(e instanceof se))return V(T(se,"Event",e,t));var n=e;return be||"beforeunload"!==n.type||this instanceof M?void U(n,this):new M(n)}function E(e){return e&&e.relatedTarget?Object.create(e,{relatedTarget:{value:B(e.relatedTarget)}}):e}function _(e,t,n){var r=window[e],o=function(t,n){return t instanceof r?void U(t,this):V(T(r,e,t,n))};if(o.prototype=Object.create(t.prototype),n&&W(o.prototype,n),r)try{F(r,o,new r("temp"))}catch(i){F(r,o,document.createEvent(e))}return o}function S(e,t){return function(){arguments[t]=B(arguments[t]);var n=B(this);n[e].apply(n,arguments)}}function T(e,t,n,r){if(ve)return new e(n,E(r));var o=B(document.createEvent(t)),i=we[t],a=[n];return Object.keys(i).forEach(function(e){var t=null!=r&&e in r?r[e]:i[e];"relatedTarget"===e&&(t=B(t)),a.push(t)}),o["init"+t].apply(o,a),o}function M(e){y.call(this,e)}function O(e){return"function"==typeof e||e&&e.handleEvent}function L(e){switch(e){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function N(e){U(e,this)}function C(e){return e instanceof G.ShadowRoot&&(e=e.host),B(e)}function j(e,t){var n=z.get(e);if(n)for(var r=0;r<n.length;r++)if(!n[r].removed&&n[r].type===t)return!0;return!1}function D(e,t){for(var n=B(e);n;n=n.parentNode)if(j(V(n),t))return!0;return!1}function H(e){k(e,Ee)}function x(t,n,o,i){e.renderAllPending();var a=V(_e.call(q(n),o,i));if(!a)return null;var c=r(a,null),l=c.lastIndexOf(t);return l==-1?null:(c=c.slice(0,l),s(c,t))}function R(e){return function(){var t=te.get(this);return t&&t[e]&&t[e].value||null}}function I(e){var t=e.slice(2);return function(n){var r=te.get(this);r||(r=Object.create(null),te.set(this,r));var o=r[e];if(o&&this.removeEventListener(t,o.wrapped,!1),"function"==typeof n){var i=function(t){var r=n.call(this,t);r===!1?t.preventDefault():"onbeforeunload"===e&&"string"==typeof r&&(t.returnValue=r)};this.addEventListener(t,i,!1),r[e]={value:n,wrapped:i}}}}var P,k=e.forwardMethodsToWrapper,A=e.getTreeScope,W=e.mixin,F=e.registerWrapper,U=e.setWrapper,q=e.unsafeUnwrap,B=e.unwrap,V=e.wrap,G=e.wrappers,z=(new WeakMap,new WeakMap),K=new WeakMap,$=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,J=new WeakMap,Q=new WeakMap,ee=new WeakMap,te=new WeakMap,ne=new WeakMap,re=0,oe=1,ie=2,ae=3;b.prototype={equals:function(e){return this.handler===e.handler&&this.type===e.type&&this.capture===e.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var se=window.Event;se.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},y.prototype={get target(){return X.get(this)},get currentTarget(){return Y.get(this)},get eventPhase(){return J.get(this)},get path(){var e=ne.get(this);return e?e.slice():[]},stopPropagation:function(){Q.set(this,!0)},stopImmediatePropagation:function(){Q.set(this,!0),ee.set(this,!0)}};var ce=function(){var e=document.createEvent("Event");return e.initEvent("test",!0,!0),e.preventDefault(),e.defaultPrevented}();ce||(y.prototype.preventDefault=function(){this.cancelable&&(q(this).preventDefault(),Object.defineProperty(this,"defaultPrevented",{get:function(){return!0},configurable:!0}))}),F(se,y,document.createEvent("Event"));var le=_("UIEvent",y),ue=_("CustomEvent",y),de={get relatedTarget(){var e=Z.get(this);return void 0!==e?e:V(B(this).relatedTarget)}},pe=W({initMouseEvent:S("initMouseEvent",14)},de),he=W({initFocusEvent:S("initFocusEvent",5)},de),fe=_("MouseEvent",le,pe),me=_("FocusEvent",le,he),we=Object.create(null),ve=function(){try{new window.FocusEvent("focus")}catch(e){return!1}return!0}();if(!ve){var ge=function(e,t,n){if(n){var r=we[n];t=W(W({},r),t)}we[e]=t};ge("Event",{bubbles:!1,cancelable:!1}),ge("CustomEvent",{detail:null},"Event"),ge("UIEvent",{view:null,detail:0},"Event"),ge("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),ge("FocusEvent",{relatedTarget:null},"UIEvent")}var be=window.BeforeUnloadEvent;M.prototype=Object.create(y.prototype),W(M.prototype,{get returnValue(){return q(this).returnValue},set returnValue(e){q(this).returnValue=e}}),be&&F(be,M);var ye=window.EventTarget,Ee=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(e){var t=e.prototype;Ee.forEach(function(e){Object.defineProperty(t,e+"_",{value:t[e]})})}),N.prototype={addEventListener:function(e,t,n){if(O(t)&&!L(e)){var r=new b(e,t,n),o=z.get(this);if(o){for(var i=0;i<o.length;i++)if(r.equals(o[i]))return}else o=[],o.depth=0,z.set(this,o);o.push(r);var a=C(this);a.addEventListener_(e,p,!0)}},removeEventListener:function(e,t,n){n=Boolean(n);var r=z.get(this);if(r){for(var o=0,i=!1,a=0;a<r.length;a++)r[a].type===e&&r[a].capture===n&&(o++,r[a].handler===t&&(i=!0,r[a].remove()));if(i&&1===o){var s=C(this);s.removeEventListener_(e,p,!0)}}},dispatchEvent:function(t){var n=B(t),r=n.type;K.set(n,!1),e.renderAllPending();var o;D(this,r)||(o=function(){},this.addEventListener(r,o,!0));try{return B(this).dispatchEvent_(n)}finally{o&&this.removeEventListener(r,o,!0)}}},ye&&F(ye,N);var _e=document.elementFromPoint;e.elementFromPoint=x,e.getEventHandlerGetter=R,e.getEventHandlerSetter=I,e.wrapEventTargetMethods=H,e.wrappers.BeforeUnloadEvent=M,e.wrappers.CustomEvent=ue,e.wrappers.Event=y,e.wrappers.EventTarget=N,e.wrappers.FocusEvent=me,e.wrappers.MouseEvent=fe,e.wrappers.UIEvent=le}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){Object.defineProperty(e,t,m)}function n(e){l(e,this)}function r(){this.length=0,t(this,"length")}function o(e){for(var t=new r,o=0;o<e.length;o++)t[o]=new n(e[o]);return t.length=o,t}function i(e){a.call(this,e)}var a=e.wrappers.UIEvent,s=e.mixin,c=e.registerWrapper,l=e.setWrapper,u=e.unsafeUnwrap,d=e.wrap,p=window.TouchEvent;if(p){var h;try{h=document.createEvent("TouchEvent")}catch(f){return}var m={enumerable:!1};n.prototype={get target(){return d(u(this).target)}};var w={configurable:!0,enumerable:!0,get:null};["clientX","clientY","screenX","screenY","pageX","pageY","identifier","webkitRadiusX","webkitRadiusY","webkitRotationAngle","webkitForce"].forEach(function(e){w.get=function(){return u(this)[e]},Object.defineProperty(n.prototype,e,w)}),r.prototype={item:function(e){return this[e]}},i.prototype=Object.create(a.prototype),s(i.prototype,{get touches(){return o(u(this).touches)},get targetTouches(){return o(u(this).targetTouches)},get changedTouches(){return o(u(this).changedTouches)},initTouchEvent:function(){throw new Error("Not implemented")}}),c(p,i,h),e.wrappers.Touch=n,e.wrappers.TouchEvent=i,e.wrappers.TouchList=r}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e,t){Object.defineProperty(e,t,s)}function n(){this.length=0,t(this,"length")}function r(e){if(null==e)return e;for(var t=new n,r=0,o=e.length;r<o;r++)t[r]=a(e[r]);return t.length=o,t}function o(e,t){e.prototype[t]=function(){return r(i(this)[t].apply(i(this),arguments))}}var i=e.unsafeUnwrap,a=e.wrap,s={enumerable:!1};n.prototype={item:function(e){return this[e]}},t(n.prototype,"item"),e.wrappers.NodeList=n,e.addWrapNodeListMethod=o,e.wrapNodeList=r}(window.ShadowDOMPolyfill),function(e){"use strict";e.wrapHTMLCollection=e.wrapNodeList,e.wrappers.HTMLCollection=e.wrappers.NodeList}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){O(e instanceof _)}function n(e){var t=new T;return t[0]=e,t.length=1,t}function r(e,t,n){N(t,"childList",{removedNodes:n,previousSibling:e.previousSibling,nextSibling:e.nextSibling})}function o(e,t){N(e,"childList",{removedNodes:t})}function i(e,t,r,o){if(e instanceof DocumentFragment){var i=s(e);U=!0;for(var a=i.length-1;a>=0;a--)e.removeChild(i[a]),i[a].parentNode_=t;U=!1;for(var a=0;a<i.length;a++)i[a].previousSibling_=i[a-1]||r,i[a].nextSibling_=i[a+1]||o;return r&&(r.nextSibling_=i[0]),o&&(o.previousSibling_=i[i.length-1]),i}var i=n(e),c=e.parentNode;return c&&c.removeChild(e),e.parentNode_=t,e.previousSibling_=r,e.nextSibling_=o,r&&(r.nextSibling_=e),o&&(o.previousSibling_=e),i}function a(e){if(e instanceof DocumentFragment)return s(e);var t=n(e),o=e.parentNode;return o&&r(e,o,t),t}function s(e){for(var t=new T,n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t.length=n,o(e,t),t}function c(e){return e}function l(e,t){R(e,t),e.nodeIsInserted_()}function u(e,t){for(var n=C(t),r=0;r<e.length;r++)l(e[r],n)}function d(e){R(e,new M(e,null))}function p(e){for(var t=0;t<e.length;t++)d(e[t])}function h(e,t){var n=e.nodeType===_.DOCUMENT_NODE?e:e.ownerDocument;n!==t.ownerDocument&&n.adoptNode(t)}function f(t,n){if(n.length){var r=t.ownerDocument;if(r!==n[0].ownerDocument)for(var o=0;o<n.length;o++)e.adoptNodeNoRemove(n[o],r)}}function m(e,t){f(e,t);var n=t.length;if(1===n)return P(t[0]);for(var r=P(e.ownerDocument.createDocumentFragment()),o=0;o<n;o++)r.appendChild(P(t[o]));return r}function w(e){if(void 0!==e.firstChild_)for(var t=e.firstChild_;t;){var n=t;t=t.nextSibling_,n.parentNode_=n.previousSibling_=n.nextSibling_=void 0}e.firstChild_=e.lastChild_=void 0}function v(e){if(e.invalidateShadowRenderer()){for(var t=e.firstChild;t;){O(t.parentNode===e);var n=t.nextSibling,r=P(t),o=r.parentNode;o&&X.call(o,r),t.previousSibling_=t.nextSibling_=t.parentNode_=null,t=n}e.firstChild_=e.lastChild_=null}else for(var n,i=P(e),a=i.firstChild;a;)n=a.nextSibling,X.call(i,a),a=n}function g(e){var t=e.parentNode;return t&&t.invalidateShadowRenderer()}function b(e){for(var t,n=0;n<e.length;n++)t=e[n],t.parentNode.removeChild(t)}function y(e,t,n){var r;if(r=A(n?q.call(n,I(e),!1):B.call(I(e),!1)),t){for(var o=e.firstChild;o;o=o.nextSibling)r.appendChild(y(o,!0,n));if(e instanceof F.HTMLTemplateElement)for(var i=r.content,o=e.content.firstChild;o;o=o.nextSibling)i.appendChild(y(o,!0,n))}return r}function E(e,t){if(!t||C(e)!==C(t))return!1;for(var n=t;n;n=n.parentNode)if(n===e)return!0;return!1}function _(e){O(e instanceof V),S.call(this,e),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0,this.treeScope_=void 0}var S=e.wrappers.EventTarget,T=e.wrappers.NodeList,M=e.TreeScope,O=e.assert,L=e.defineWrapGetter,N=e.enqueueMutation,C=e.getTreeScope,j=e.isWrapper,D=e.mixin,H=e.registerTransientObservers,x=e.registerWrapper,R=e.setTreeScope,I=e.unsafeUnwrap,P=e.unwrap,k=e.unwrapIfNeeded,A=e.wrap,W=e.wrapIfNeeded,F=e.wrappers,U=!1,q=document.importNode,B=window.Node.prototype.cloneNode,V=window.Node,G=window.DocumentFragment,z=(V.prototype.appendChild,V.prototype.compareDocumentPosition),K=V.prototype.isEqualNode,$=V.prototype.insertBefore,X=V.prototype.removeChild,Y=V.prototype.replaceChild,Z=/Trident|Edge/.test(navigator.userAgent),J=Z?function(e,t){try{X.call(e,t)}catch(n){if(!(e instanceof G))throw n}}:function(e,t){X.call(e,t)};_.prototype=Object.create(S.prototype),D(_.prototype,{appendChild:function(e){return this.insertBefore(e,null)},insertBefore:function(e,n){t(e);var r;n?j(n)?r=P(n):(r=n,n=A(r)):(n=null,r=null),n&&O(n.parentNode===this);var o,s=n?n.previousSibling:this.lastChild,c=!this.invalidateShadowRenderer()&&!g(e);if(o=c?a(e):i(e,this,s,n),c)h(this,e),w(this),$.call(I(this),P(e),r);else{s||(this.firstChild_=o[0]),n||(this.lastChild_=o[o.length-1],void 0===this.firstChild_&&(this.firstChild_=this.firstChild));var l=r?r.parentNode:I(this);l?$.call(l,m(this,o),r):f(this,o)}return N(this,"childList",{addedNodes:o,nextSibling:n,previousSibling:s}),u(o,this),e},removeChild:function(e){if(t(e),e.parentNode!==this){for(var r=!1,o=(this.childNodes,this.firstChild);o;o=o.nextSibling)if(o===e){r=!0;break}if(!r)throw new Error("NotFoundError")}var i=P(e),a=e.nextSibling,s=e.previousSibling;if(this.invalidateShadowRenderer()){var c=this.firstChild,l=this.lastChild,u=i.parentNode;u&&J(u,i),c===e&&(this.firstChild_=a),l===e&&(this.lastChild_=s),s&&(s.nextSibling_=a),a&&(a.previousSibling_=s),e.previousSibling_=e.nextSibling_=e.parentNode_=void 0}else w(this),J(I(this),i);return U||N(this,"childList",{removedNodes:n(e),nextSibling:a,previousSibling:s}),H(this,e),e},replaceChild:function(e,r){t(e);var o;if(j(r)?o=P(r):(o=r,r=A(o)),r.parentNode!==this)throw new Error("NotFoundError");var s,c=r.nextSibling,l=r.previousSibling,p=!this.invalidateShadowRenderer()&&!g(e);return p?s=a(e):(c===e&&(c=e.nextSibling),s=i(e,this,l,c)),p?(h(this,e),w(this),Y.call(I(this),P(e),o)):(this.firstChild===r&&(this.firstChild_=s[0]),this.lastChild===r&&(this.lastChild_=s[s.length-1]),r.previousSibling_=r.nextSibling_=r.parentNode_=void 0,o.parentNode&&Y.call(o.parentNode,m(this,s),o)),N(this,"childList",{addedNodes:s,removedNodes:n(r),nextSibling:c,previousSibling:l}),d(r),u(s,this),r},nodeIsInserted_:function(){for(var e=this.firstChild;e;e=e.nextSibling)e.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:A(I(this).parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:A(I(this).firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:A(I(this).lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:A(I(this).nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:A(I(this).previousSibling)},get parentElement(){for(var e=this.parentNode;e&&e.nodeType!==_.ELEMENT_NODE;)e=e.parentNode;return e},get textContent(){for(var e="",t=this.firstChild;t;t=t.nextSibling)t.nodeType!=_.COMMENT_NODE&&(e+=t.textContent);return e},set textContent(e){null==e&&(e="");var t=c(this.childNodes);if(this.invalidateShadowRenderer()){if(v(this),""!==e){var n=I(this).ownerDocument.createTextNode(e);this.appendChild(n)}}else w(this),I(this).textContent=e;var r=c(this.childNodes);N(this,"childList",{addedNodes:r,removedNodes:t}),p(t),u(r,this)},get childNodes(){for(var e=new T,t=0,n=this.firstChild;n;n=n.nextSibling)e[t++]=n;return e.length=t,e},cloneNode:function(e){return y(this,e)},contains:function(e){return E(this,W(e))},compareDocumentPosition:function(e){return z.call(I(this),k(e))},isEqualNode:function(e){return K.call(I(this),k(e))},normalize:function(){for(var e,t,n=c(this.childNodes),r=[],o="",i=0;i<n.length;i++)t=n[i],t.nodeType===_.TEXT_NODE?e||t.data.length?e?(o+=t.data,r.push(t)):e=t:this.removeChild(t):(e&&r.length&&(e.data+=o,b(r)),r=[],o="",e=null,t.childNodes.length&&t.normalize());e&&r.length&&(e.data+=o,b(r))}}),L(_,"ownerDocument"),x(V,_,document.createDocumentFragment()),delete _.prototype.querySelector,delete _.prototype.querySelectorAll,_.prototype=D(Object.create(S.prototype),_.prototype),e.cloneNode=y,e.nodeWasAdded=l,e.nodeWasRemoved=d,e.nodesWereAdded=u,e.nodesWereRemoved=p,e.originalInsertBefore=$,e.originalRemoveChild=X,e.snapshotNodeList=c,e.wrappers.Node=_}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n,r,o){for(var i=null,a=null,s=0,c=t.length;s<c;s++)i=b(t[s]),!o&&(a=v(i).root)&&a instanceof e.wrappers.ShadowRoot||(r[n++]=i);return n}function n(e){return String(e).replace(/\/deep\/|::shadow|>>>/g," ")}function r(e){return String(e).replace(/:host\(([^\s]+)\)/g,"$1").replace(/([^\s]):host/g,"$1").replace(":host","*").replace(/\^|\/shadow\/|\/shadow-deep\/|::shadow|\/deep\/|::content|>>>/g," ")}function o(e,t){for(var n,r=e.firstElementChild;r;){if(r.matches(t))return r;if(n=o(r,t))return n;r=r.nextElementSibling}return null}function i(e,t){return e.matches(t)}function a(e,t,n){var r=e.localName;return r===t||r===n&&e.namespaceURI===j}function s(){return!0}function c(e,t,n){return e.localName===n}function l(e,t){return e.namespaceURI===t}function u(e,t,n){return e.namespaceURI===t&&e.localName===n}function d(e,t,n,r,o,i){for(var a=e.firstElementChild;a;)r(a,o,i)&&(n[t++]=a),t=d(a,t,n,r,o,i),a=a.nextElementSibling;return t}function p(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,null);if(c instanceof N)s=S.call(c,i);else{if(!(c instanceof C))return d(this,r,o,n,i,null);s=_.call(c,i)}return t(s,r,o,a)}function h(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=M.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=T.call(c,i,a)}return t(s,r,o,!1)}function f(n,r,o,i,a){var s,c=g(this),l=v(this).root;if(l instanceof e.wrappers.ShadowRoot)return d(this,r,o,n,i,a);if(c instanceof N)s=L.call(c,i,a);else{if(!(c instanceof C))return d(this,r,o,n,i,a);s=O.call(c,i,a)}return t(s,r,o,!1)}var m=e.wrappers.HTMLCollection,w=e.wrappers.NodeList,v=e.getTreeScope,g=e.unsafeUnwrap,b=e.wrap,y=document.querySelector,E=document.documentElement.querySelector,_=document.querySelectorAll,S=document.documentElement.querySelectorAll,T=document.getElementsByTagName,M=document.documentElement.getElementsByTagName,O=document.getElementsByTagNameNS,L=document.documentElement.getElementsByTagNameNS,N=window.Element,C=window.HTMLDocument||window.Document,j="http://www.w3.org/1999/xhtml",D={
+querySelector:function(t){var r=n(t),i=r!==t;t=r;var a,s=g(this),c=v(this).root;if(c instanceof e.wrappers.ShadowRoot)return o(this,t);if(s instanceof N)a=b(E.call(s,t));else{if(!(s instanceof C))return o(this,t);a=b(y.call(s,t))}return a&&!i&&(c=v(a).root)&&c instanceof e.wrappers.ShadowRoot?o(this,t):a},querySelectorAll:function(e){var t=n(e),r=t!==e;e=t;var o=new w;return o.length=p.call(this,i,0,o,e,r),o}},H={matches:function(t){return t=r(t),e.originalMatches.call(g(this),t)}},x={getElementsByTagName:function(e){var t=new m,n="*"===e?s:a;return t.length=h.call(this,n,0,t,e,e.toLowerCase()),t},getElementsByClassName:function(e){return this.querySelectorAll("."+e)},getElementsByTagNameNS:function(e,t){var n=new m,r=null;return r="*"===e?"*"===t?s:c:"*"===t?l:u,n.length=f.call(this,r,0,n,e||null,t),n}};e.GetElementsByInterface=x,e.SelectorsInterface=D,e.MatchesInterface=H}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;return e}function n(e){for(;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.previousSibling;return e}var r=e.wrappers.NodeList,o={get firstElementChild(){return t(this.firstChild)},get lastElementChild(){return n(this.lastChild)},get childElementCount(){for(var e=0,t=this.firstElementChild;t;t=t.nextElementSibling)e++;return e},get children(){for(var e=new r,t=0,n=this.firstElementChild;n;n=n.nextElementSibling)e[t++]=n;return e.length=t,e},remove:function(){var e=this.parentNode;e&&e.removeChild(this)}},i={get nextElementSibling(){return t(this.nextSibling)},get previousElementSibling(){return n(this.previousSibling)}},a={getElementById:function(e){return/[ \t\n\r\f]/.test(e)?null:this.querySelector('[id="'+e+'"]')}};e.ChildNodeInterface=i,e.NonElementParentNodeInterface=a,e.ParentNodeInterface=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}var n=e.ChildNodeInterface,r=e.wrappers.Node,o=e.enqueueMutation,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=window.CharacterData;t.prototype=Object.create(r.prototype),i(t.prototype,{get nodeValue(){return this.data},set nodeValue(e){this.data=e},get textContent(){return this.data},set textContent(e){this.data=e},get data(){return s(this).data},set data(e){var t=s(this).data;o(this,"characterData",{oldValue:t}),s(this).data=e}}),i(t.prototype,n),a(c,t,document.createTextNode("")),e.wrappers.CharacterData=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e>>>0}function n(e){r.call(this,e)}var r=e.wrappers.CharacterData,o=(e.enqueueMutation,e.mixin),i=e.registerWrapper,a=window.Text;n.prototype=Object.create(r.prototype),o(n.prototype,{splitText:function(e){e=t(e);var n=this.data;if(e>n.length)throw new Error("IndexSizeError");var r=n.slice(0,e),o=n.slice(e);this.data=r;var i=this.ownerDocument.createTextNode(o);return this.parentNode&&this.parentNode.insertBefore(i,this.nextSibling),i}}),i(a,n,document.createTextNode("")),e.wrappers.Text=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return i(e).getAttribute("class")}function n(e,t){a(e,"attributes",{name:"class",namespace:null,oldValue:t})}function r(t){e.invalidateRendererBasedOnAttribute(t,"class")}function o(e,o,i){var a=e.ownerElement_;if(null==a)return o.apply(e,i);var s=t(a),c=o.apply(e,i);return t(a)!==s&&(n(a,s),r(a)),c}if(!window.DOMTokenList)return void console.warn("Missing DOMTokenList prototype, please include a compatible classList polyfill such as http://goo.gl/uTcepH.");var i=e.unsafeUnwrap,a=e.enqueueMutation,s=DOMTokenList.prototype.add;DOMTokenList.prototype.add=function(){o(this,s,arguments)};var c=DOMTokenList.prototype.remove;DOMTokenList.prototype.remove=function(){o(this,c,arguments)};var l=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(){return o(this,l,arguments)}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t,n){var r=t.parentNode;if(r&&r.shadowRoot){var o=e.getRendererForHost(r);o.dependsOnAttribute(n)&&o.invalidate()}}function n(e,t,n){u(e,"attributes",{name:t,namespace:null,oldValue:n})}function r(e){a.call(this,e)}var o=e.ChildNodeInterface,i=e.GetElementsByInterface,a=e.wrappers.Node,s=e.ParentNodeInterface,c=e.SelectorsInterface,l=e.MatchesInterface,u=(e.addWrapNodeListMethod,e.enqueueMutation),d=e.mixin,p=(e.oneOf,e.registerWrapper),h=e.unsafeUnwrap,f=e.wrappers,m=window.Element,w=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(e){return m.prototype[e]}),v=w[0],g=m.prototype[v],b=new WeakMap;r.prototype=Object.create(a.prototype),d(r.prototype,{createShadowRoot:function(){var t=new f.ShadowRoot(this);h(this).polymerShadowRoot_=t;var n=e.getRendererForHost(this);return n.invalidate(),t},get shadowRoot(){return h(this).polymerShadowRoot_||null},setAttribute:function(e,r){var o=h(this).getAttribute(e);h(this).setAttribute(e,r),n(this,e,o),t(this,e)},removeAttribute:function(e){var r=h(this).getAttribute(e);h(this).removeAttribute(e),n(this,e,r),t(this,e)},get classList(){var e=b.get(this);if(!e){if(e=h(this).classList,!e)return;e.ownerElement_=this,b.set(this,e)}return e},get className(){return h(this).className},set className(e){this.setAttribute("class",e)},get id(){return h(this).id},set id(e){this.setAttribute("id",e)}}),w.forEach(function(e){"matches"!==e&&(r.prototype[e]=function(e){return this.matches(e)})}),m.prototype.webkitCreateShadowRoot&&(r.prototype.webkitCreateShadowRoot=r.prototype.createShadowRoot),d(r.prototype,o),d(r.prototype,i),d(r.prototype,s),d(r.prototype,c),d(r.prototype,l),p(m,r,document.createElementNS(null,"x")),e.invalidateRendererBasedOnAttribute=t,e.matchesNames=w,e.originalMatches=g,e.wrappers.Element=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case" ":return"&nbsp;"}}function n(e){return e.replace(L,t)}function r(e){return e.replace(N,t)}function o(e){for(var t={},n=0;n<e.length;n++)t[e[n]]=!0;return t}function i(e){if(e.namespaceURI!==D)return!0;var t=e.ownerDocument.doctype;return t&&t.publicId&&t.systemId}function a(e,t){switch(e.nodeType){case Node.ELEMENT_NODE:for(var o,a=e.tagName.toLowerCase(),c="<"+a,l=e.attributes,u=0;o=l[u];u++)c+=" "+o.name+'="'+n(o.value)+'"';return C[a]?(i(e)&&(c+="/"),c+">"):c+">"+s(e)+"</"+a+">";case Node.TEXT_NODE:var d=e.data;return t&&j[t.localName]?d:r(d);case Node.COMMENT_NODE:return"<!--"+e.data+"-->";default:throw console.error(e),new Error("not implemented")}}function s(e){e instanceof O.HTMLTemplateElement&&(e=e.content);for(var t="",n=e.firstChild;n;n=n.nextSibling)t+=a(n,e);return t}function c(e,t,n){var r=n||"div";e.textContent="";var o=T(e.ownerDocument.createElement(r));o.innerHTML=t;for(var i;i=o.firstChild;)e.appendChild(M(i))}function l(e){m.call(this,e)}function u(e,t){var n=T(e.cloneNode(!1));n.innerHTML=t;for(var r,o=T(document.createDocumentFragment());r=n.firstChild;)o.appendChild(r);return M(o)}function d(t){return function(){return e.renderAllPending(),S(this)[t]}}function p(e){w(l,e,d(e))}function h(t){Object.defineProperty(l.prototype,t,{get:d(t),set:function(n){e.renderAllPending(),S(this)[t]=n},configurable:!0,enumerable:!0})}function f(t){Object.defineProperty(l.prototype,t,{value:function(){return e.renderAllPending(),S(this)[t].apply(S(this),arguments)},configurable:!0,enumerable:!0})}var m=e.wrappers.Element,w=e.defineGetter,v=e.enqueueMutation,g=e.mixin,b=e.nodesWereAdded,y=e.nodesWereRemoved,E=e.registerWrapper,_=e.snapshotNodeList,S=e.unsafeUnwrap,T=e.unwrap,M=e.wrap,O=e.wrappers,L=/[&\u00A0"]/g,N=/[&\u00A0<>]/g,C=o(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),j=o(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D="http://www.w3.org/1999/xhtml",H=/MSIE/.test(navigator.userAgent),x=window.HTMLElement,R=window.HTMLTemplateElement;l.prototype=Object.create(m.prototype),g(l.prototype,{get innerHTML(){return s(this)},set innerHTML(e){if(H&&j[this.localName])return void(this.textContent=e);var t=_(this.childNodes);this.invalidateShadowRenderer()?this instanceof O.HTMLTemplateElement?c(this.content,e):c(this,e,this.tagName):!R&&this instanceof O.HTMLTemplateElement?c(this.content,e):S(this).innerHTML=e;var n=_(this.childNodes);v(this,"childList",{addedNodes:n,removedNodes:t}),y(t),b(n,this)},get outerHTML(){return a(this,this.parentNode)},set outerHTML(e){var t=this.parentNode;if(t){t.invalidateShadowRenderer();var n=u(t,e);t.replaceChild(n,this)}},insertAdjacentHTML:function(e,t){var n,r;switch(String(e).toLowerCase()){case"beforebegin":n=this.parentNode,r=this;break;case"afterend":n=this.parentNode,r=this.nextSibling;break;case"afterbegin":n=this,r=this.firstChild;break;case"beforeend":n=this,r=null;break;default:return}var o=u(n,t);n.insertBefore(o,r)},get hidden(){return this.hasAttribute("hidden")},set hidden(e){e?this.setAttribute("hidden",""):this.removeAttribute("hidden")}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(p),["scrollLeft","scrollTop"].forEach(h),["focus","getBoundingClientRect","getClientRects","scrollIntoView"].forEach(f),E(x,l,document.createElement("b")),e.wrappers.HTMLElement=l,e.getInnerHTML=s,e.setInnerHTML=c}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.HTMLCanvasElement;t.prototype=Object.create(n.prototype),r(t.prototype,{getContext:function(){var e=i(this).getContext.apply(i(this),arguments);return e&&a(e)}}),o(s,t,document.createElement("canvas")),e.wrappers.HTMLCanvasElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=window.HTMLContentElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get select(){return this.getAttribute("select")},set select(e){this.setAttribute("select",e)},setAttribute:function(e,t){n.prototype.setAttribute.call(this,e,t),"select"===String(e).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),i&&o(i,t),e.wrappers.HTMLContentElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=window.HTMLFormElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get elements(){return i(a(this).elements)}}),o(s,t,document.createElement("form")),e.wrappers.HTMLFormElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e,t){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var o=i(document.createElement("img"));r.call(this,o),a(o,this),void 0!==e&&(o.width=e),void 0!==t&&(o.height=t)}var r=e.wrappers.HTMLElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLImageElement;t.prototype=Object.create(r.prototype),o(s,t,document.createElement("img")),n.prototype=t.prototype,e.wrappers.HTMLImageElement=t,e.wrappers.Image=n}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=(e.mixin,e.wrappers.NodeList,e.registerWrapper),o=window.HTMLShadowElement;t.prototype=Object.create(n.prototype),t.prototype.constructor=t,o&&r(o,t),e.wrappers.HTMLShadowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){if(!e.defaultView)return e;var t=d.get(e);if(!t){for(t=e.implementation.createHTMLDocument("");t.lastChild;)t.removeChild(t.lastChild);d.set(e,t)}return t}function n(e){for(var n,r=t(e.ownerDocument),o=c(r.createDocumentFragment());n=e.firstChild;)o.appendChild(n);return o}function r(e){if(o.call(this,e),!p){var t=n(e);u.set(this,l(t))}}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.wrap,u=new WeakMap,d=new WeakMap,p=window.HTMLTemplateElement;r.prototype=Object.create(o.prototype),i(r.prototype,{constructor:r,get content(){return p?l(s(this).content):u.get(this)}}),p&&a(p,r),e.wrappers.HTMLTemplateElement=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.registerWrapper,o=window.HTMLMediaElement;o&&(t.prototype=Object.create(n.prototype),r(o,t,document.createElement("audio")),e.wrappers.HTMLMediaElement=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r.call(this,e)}function n(e){if(!(this instanceof n))throw new TypeError("DOM object constructor cannot be called as a function.");var t=i(document.createElement("audio"));r.call(this,t),a(t,this),t.setAttribute("preload","auto"),void 0!==e&&t.setAttribute("src",e)}var r=e.wrappers.HTMLMediaElement,o=e.registerWrapper,i=e.unwrap,a=e.rewrap,s=window.HTMLAudioElement;s&&(t.prototype=Object.create(r.prototype),o(s,t,document.createElement("audio")),n.prototype=t.prototype,e.wrappers.HTMLAudioElement=t,e.wrappers.Audio=n)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){return e.replace(/\s+/g," ").trim()}function n(e){o.call(this,e)}function r(e,t,n,i){if(!(this instanceof r))throw new TypeError("DOM object constructor cannot be called as a function.");var a=c(document.createElement("option"));o.call(this,a),s(a,this),void 0!==e&&(a.text=e),void 0!==t&&a.setAttribute("value",t),n===!0&&a.setAttribute("selected",""),a.selected=i===!0}var o=e.wrappers.HTMLElement,i=e.mixin,a=e.registerWrapper,s=e.rewrap,c=e.unwrap,l=e.wrap,u=window.HTMLOptionElement;n.prototype=Object.create(o.prototype),i(n.prototype,{get text(){return t(this.textContent)},set text(e){this.textContent=t(String(e))},get form(){return l(c(this).form)}}),a(u,n,document.createElement("option")),r.prototype=n.prototype,e.wrappers.HTMLOptionElement=n,e.wrappers.Option=r}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=window.HTMLSelectElement;t.prototype=Object.create(n.prototype),r(t.prototype,{add:function(e,t){"object"==typeof t&&(t=i(t)),i(this).add(i(e),t)},remove:function(e){return void 0===e?void n.prototype.remove.call(this):("object"==typeof e&&(e=i(e)),void i(this).remove(e))},get form(){return a(i(this).form)}}),o(s,t,document.createElement("select")),e.wrappers.HTMLSelectElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.unwrap,a=e.wrap,s=e.wrapHTMLCollection,c=window.HTMLTableElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get caption(){return a(i(this).caption)},createCaption:function(){return a(i(this).createCaption())},get tHead(){return a(i(this).tHead)},createTHead:function(){return a(i(this).createTHead())},createTFoot:function(){return a(i(this).createTFoot())},get tFoot(){return a(i(this).tFoot)},get tBodies(){return s(i(this).tBodies)},createTBody:function(){return a(i(this).createTBody())},get rows(){return s(i(this).rows)},insertRow:function(e){return a(i(this).insertRow(e))}}),o(c,t,document.createElement("table")),e.wrappers.HTMLTableElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableSectionElement;t.prototype=Object.create(n.prototype),r(t.prototype,{constructor:t,get rows(){return i(a(this).rows)},insertRow:function(e){return s(a(this).insertRow(e))}}),o(c,t,document.createElement("thead")),e.wrappers.HTMLTableSectionElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.HTMLElement,r=e.mixin,o=e.registerWrapper,i=e.wrapHTMLCollection,a=e.unwrap,s=e.wrap,c=window.HTMLTableRowElement;t.prototype=Object.create(n.prototype),r(t.prototype,{get cells(){return i(a(this).cells)},insertCell:function(e){return s(a(this).insertCell(e))}}),o(c,t,document.createElement("tr")),e.wrappers.HTMLTableRowElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){switch(e.localName){case"content":return new n(e);case"shadow":return new o(e);case"template":return new i(e)}r.call(this,e)}var n=e.wrappers.HTMLContentElement,r=e.wrappers.HTMLElement,o=e.wrappers.HTMLShadowElement,i=e.wrappers.HTMLTemplateElement,a=(e.mixin,e.registerWrapper),s=window.HTMLUnknownElement;t.prototype=Object.create(r.prototype),a(s,t),e.wrappers.HTMLUnknownElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Element,r=e.wrappers.HTMLElement,o=e.registerWrapper,i=(e.defineWrapGetter,e.unsafeUnwrap),a=e.wrap,s=e.mixin,c="http://www.w3.org/2000/svg",l=window.SVGElement,u=document.createElementNS(c,"title");if(!("classList"in u)){var d=Object.getOwnPropertyDescriptor(n.prototype,"classList");Object.defineProperty(r.prototype,"classList",d),delete n.prototype.classList}t.prototype=Object.create(n.prototype),s(t.prototype,{get ownerSVGElement(){return a(i(this).ownerSVGElement)}}),o(l,t,document.createElementNS(c,"title")),e.wrappers.SVGElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){p.call(this,e)}var n=e.mixin,r=e.registerWrapper,o=e.unwrap,i=e.wrap,a=window.SVGUseElement,s="http://www.w3.org/2000/svg",c=i(document.createElementNS(s,"g")),l=document.createElementNS(s,"use"),u=c.constructor,d=Object.getPrototypeOf(u.prototype),p=d.constructor;t.prototype=Object.create(d),"instanceRoot"in l&&n(t.prototype,{get instanceRoot(){return i(o(this).instanceRoot)},get animatedInstanceRoot(){return i(o(this).animatedInstanceRoot)}}),r(a,t,l),e.wrappers.SVGUseElement=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.mixin,o=e.registerWrapper,i=e.unsafeUnwrap,a=e.wrap,s=window.SVGElementInstance;s&&(t.prototype=Object.create(n.prototype),r(t.prototype,{get correspondingElement(){return a(i(this).correspondingElement)},get correspondingUseElement(){return a(i(this).correspondingUseElement)},get parentNode(){return a(i(this).parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return a(i(this).firstChild)},get lastChild(){return a(i(this).lastChild)},get previousSibling(){return a(i(this).previousSibling)},get nextSibling(){return a(i(this).nextSibling)}}),o(s,t),e.wrappers.SVGElementInstance=t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){o(e,this)}var n=e.mixin,r=e.registerWrapper,o=e.setWrapper,i=e.unsafeUnwrap,a=e.unwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.CanvasRenderingContext2D;n(t.prototype,{get canvas(){return c(i(this).canvas)},drawImage:function(){arguments[0]=s(arguments[0]),i(this).drawImage.apply(i(this),arguments)},createPattern:function(){return arguments[0]=a(arguments[0]),i(this).createPattern.apply(i(this),arguments)}}),r(l,t,document.createElement("canvas").getContext("2d")),e.wrappers.CanvasRenderingContext2D=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){i(e,this)}var n=e.addForwardingProperties,r=e.mixin,o=e.registerWrapper,i=e.setWrapper,a=e.unsafeUnwrap,s=e.unwrapIfNeeded,c=e.wrap,l=window.WebGLRenderingContext;if(l){r(t.prototype,{get canvas(){return c(a(this).canvas)},texImage2D:function(){arguments[5]=s(arguments[5]),a(this).texImage2D.apply(a(this),arguments)},texSubImage2D:function(){arguments[6]=s(arguments[6]),a(this).texSubImage2D.apply(a(this),arguments)}});var u=Object.getPrototypeOf(l.prototype);u!==Object.prototype&&n(u,t.prototype);var d=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};o(l,t,d),e.wrappers.WebGLRenderingContext=t}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.Node,r=e.GetElementsByInterface,o=e.NonElementParentNodeInterface,i=e.ParentNodeInterface,a=e.SelectorsInterface,s=e.mixin,c=e.registerObject,l=e.registerWrapper,u=window.DocumentFragment;t.prototype=Object.create(n.prototype),s(t.prototype,i),s(t.prototype,a),s(t.prototype,r),s(t.prototype,o),l(u,t,document.createDocumentFragment()),e.wrappers.DocumentFragment=t;var d=c(document.createComment(""));e.wrappers.Comment=d}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(u(e).ownerDocument.createDocumentFragment());n.call(this,t),c(t,this);var o=e.shadowRoot;f.set(this,o),this.treeScope_=new r(this,a(o||e)),h.set(this,e)}var n=e.wrappers.DocumentFragment,r=e.TreeScope,o=e.elementFromPoint,i=e.getInnerHTML,a=e.getTreeScope,s=e.mixin,c=e.rewrap,l=e.setInnerHTML,u=e.unsafeUnwrap,d=e.unwrap,p=e.wrap,h=new WeakMap,f=new WeakMap;t.prototype=Object.create(n.prototype),s(t.prototype,{constructor:t,get innerHTML(){return i(this)},set innerHTML(e){l(this,e),this.invalidateShadowRenderer()},get olderShadowRoot(){return f.get(this)||null},get host(){return h.get(this)||null},invalidateShadowRenderer:function(){return h.get(this).invalidateShadowRenderer()},elementFromPoint:function(e,t){return o(this,this.ownerDocument,e,t)},getSelection:function(){return document.getSelection()},get activeElement(){var e=d(this).ownerDocument.activeElement;if(!e||!e.nodeType)return null;for(var t=p(e);!this.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}}),e.wrappers.ShadowRoot=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=d(e).root;return t instanceof h?t.host:null}function n(t,n){if(t.shadowRoot){n=Math.min(t.childNodes.length-1,n);var r=t.childNodes[n];if(r){var o=e.getDestinationInsertionPoints(r);if(o.length>0){var i=o[0].parentNode;i.nodeType==Node.ELEMENT_NODE&&(t=i)}}}return t}function r(e){return e=u(e),t(e)||e}function o(e){a(e,this)}var i=e.registerWrapper,a=e.setWrapper,s=e.unsafeUnwrap,c=e.unwrap,l=e.unwrapIfNeeded,u=e.wrap,d=e.getTreeScope,p=window.Range,h=e.wrappers.ShadowRoot;o.prototype={get startContainer(){return r(s(this).startContainer)},get endContainer(){return r(s(this).endContainer)},get commonAncestorContainer(){return r(s(this).commonAncestorContainer)},setStart:function(e,t){e=n(e,t),s(this).setStart(l(e),t)},setEnd:function(e,t){e=n(e,t),s(this).setEnd(l(e),t)},setStartBefore:function(e){s(this).setStartBefore(l(e))},setStartAfter:function(e){s(this).setStartAfter(l(e))},setEndBefore:function(e){s(this).setEndBefore(l(e))},setEndAfter:function(e){s(this).setEndAfter(l(e))},selectNode:function(e){s(this).selectNode(l(e))},selectNodeContents:function(e){s(this).selectNodeContents(l(e))},compareBoundaryPoints:function(e,t){return s(this).compareBoundaryPoints(e,c(t))},extractContents:function(){return u(s(this).extractContents())},cloneContents:function(){return u(s(this).cloneContents())},insertNode:function(e){s(this).insertNode(l(e))},surroundContents:function(e){s(this).surroundContents(l(e))},cloneRange:function(){return u(s(this).cloneRange())},isPointInRange:function(e,t){return s(this).isPointInRange(l(e),t)},comparePoint:function(e,t){return s(this).comparePoint(l(e),t)},intersectsNode:function(e){return s(this).intersectsNode(l(e))},toString:function(){return s(this).toString()}},p.prototype.createContextualFragment&&(o.prototype.createContextualFragment=function(e){return u(s(this).createContextualFragment(e))}),i(window.Range,o,document.createRange()),e.wrappers.Range=o}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){e.previousSibling_=e.previousSibling,e.nextSibling_=e.nextSibling,e.parentNode_=e.parentNode}function n(n,o,i){var a=x(n),s=x(o),c=i?x(i):null;if(r(o),t(o),i)n.firstChild===i&&(n.firstChild_=i),i.previousSibling_=i.previousSibling;else{n.lastChild_=n.lastChild,n.lastChild===n.firstChild&&(n.firstChild_=n.firstChild);var l=R(a.lastChild);l&&(l.nextSibling_=l.nextSibling)}e.originalInsertBefore.call(a,s,c)}function r(n){var r=x(n),o=r.parentNode;if(o){var i=R(o);t(n),n.previousSibling&&(n.previousSibling.nextSibling_=n),n.nextSibling&&(n.nextSibling.previousSibling_=n),i.lastChild===n&&(i.lastChild_=n),i.firstChild===n&&(i.firstChild_=n),e.originalRemoveChild.call(o,r)}}function o(e){P.set(e,[])}function i(e){var t=P.get(e);return t||P.set(e,t=[]),t}function a(e){for(var t=[],n=0,r=e.firstChild;r;r=r.nextSibling)t[n++]=r;return t}function s(){for(var e=0;e<F.length;e++){var t=F[e],n=t.parentRenderer;n&&n.dirty||t.render()}F=[]}function c(){T=null,s()}function l(e){var t=A.get(e);return t||(t=new h(e),A.set(e,t)),t}function u(e){var t=j(e).root;return t instanceof C?t:null}function d(e){return l(e.host)}function p(e){this.skip=!1,this.node=e,this.childNodes=[]}function h(e){this.host=e,this.dirty=!1,this.invalidateAttributes(),this.associateNode(e)}function f(e){for(var t=[],n=e.firstChild;n;n=n.nextSibling)E(n)?t.push.apply(t,i(n)):t.push(n);return t}function m(e){if(e instanceof L)return e;if(e instanceof O)return null;for(var t=e.firstChild;t;t=t.nextSibling){var n=m(t);if(n)return n}return null}function w(e,t){i(t).push(e);var n=k.get(e);n?n.push(t):k.set(e,[t])}function v(e){return k.get(e)}function g(e){k.set(e,void 0)}function b(e,t){var n=t.getAttribute("select");if(!n)return!0;if(n=n.trim(),!n)return!0;if(!(e instanceof M))return!1;if(!q.test(n))return!1;try{return e.matches(n)}catch(r){return!1}}function y(e,t){var n=v(t);return n&&n[n.length-1]===e}function E(e){return e instanceof O||e instanceof L}function _(e){return e.shadowRoot}function S(e){for(var t=[],n=e.shadowRoot;n;n=n.olderShadowRoot)t.push(n);return t}var T,M=e.wrappers.Element,O=e.wrappers.HTMLContentElement,L=e.wrappers.HTMLShadowElement,N=e.wrappers.Node,C=e.wrappers.ShadowRoot,j=(e.assert,e.getTreeScope),D=(e.mixin,e.oneOf),H=e.unsafeUnwrap,x=e.unwrap,R=e.wrap,I=e.ArraySplice,P=new WeakMap,k=new WeakMap,A=new WeakMap,W=D(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),F=[],U=new I;U.equals=function(e,t){return x(e.node)===t},p.prototype={append:function(e){var t=new p(e);return this.childNodes.push(t),t},sync:function(e){if(!this.skip){for(var t=this.node,o=this.childNodes,i=a(x(t)),s=e||new WeakMap,c=U.calculateSplices(o,i),l=0,u=0,d=0,p=0;p<c.length;p++){for(var h=c[p];d<h.index;d++)u++,o[l++].sync(s);for(var f=h.removed.length,m=0;m<f;m++){var w=R(i[u++]);s.get(w)||r(w)}for(var v=h.addedCount,g=i[u]&&R(i[u]),m=0;m<v;m++){var b=o[l++],y=b.node;n(t,y,g),s.set(y,!0),b.sync(s)}d+=v}for(var p=d;p<o.length;p++)o[p].sync(s)}}},h.prototype={render:function(e){if(this.dirty){this.invalidateAttributes();var t=this.host;this.distribution(t);var n=e||new p(t);this.buildRenderTree(n,t);var r=!e;r&&n.sync(),this.dirty=!1}},get parentRenderer(){return j(this.host).renderer},invalidate:function(){if(!this.dirty){this.dirty=!0;var e=this.parentRenderer;if(e&&e.invalidate(),F.push(this),T)return;T=window[W](c,0)}},distribution:function(e){this.resetAllSubtrees(e),this.distributionResolution(e)},resetAll:function(e){E(e)?o(e):g(e),this.resetAllSubtrees(e)},resetAllSubtrees:function(e){for(var t=e.firstChild;t;t=t.nextSibling)this.resetAll(t);e.shadowRoot&&this.resetAll(e.shadowRoot),e.olderShadowRoot&&this.resetAll(e.olderShadowRoot)},distributionResolution:function(e){if(_(e)){for(var t=e,n=f(t),r=S(t),o=0;o<r.length;o++)this.poolDistribution(r[o],n);for(var o=r.length-1;o>=0;o--){var i=r[o],a=m(i);if(a){var s=i.olderShadowRoot;s&&(n=f(s));for(var c=0;c<n.length;c++)w(n[c],a)}this.distributionResolution(i)}}for(var l=e.firstChild;l;l=l.nextSibling)this.distributionResolution(l)},poolDistribution:function(e,t){if(!(e instanceof L))if(e instanceof O){var n=e;this.updateDependentAttributes(n.getAttribute("select"));for(var r=!1,o=0;o<t.length;o++){var e=t[o];e&&b(e,n)&&(w(e,n),t[o]=void 0,r=!0)}if(!r)for(var i=n.firstChild;i;i=i.nextSibling)w(i,n)}else for(var i=e.firstChild;i;i=i.nextSibling)this.poolDistribution(i,t)},buildRenderTree:function(e,t){for(var n=this.compose(t),r=0;r<n.length;r++){var o=n[r],i=e.append(o);this.buildRenderTree(i,o)}if(_(t)){var a=l(t);a.dirty=!1}},compose:function(e){for(var t=[],n=e.shadowRoot||e,r=n.firstChild;r;r=r.nextSibling)if(E(r)){this.associateNode(n);for(var o=i(r),a=0;a<o.length;a++){var s=o[a];y(r,s)&&t.push(s)}}else t.push(r);return t},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(e){if(e){var t=this.attributes;/\.\w+/.test(e)&&(t["class"]=!0),/#\w+/.test(e)&&(t.id=!0),e.replace(/\[\s*([^\s=\|~\]]+)/g,function(e,n){t[n]=!0})}},dependsOnAttribute:function(e){return this.attributes[e]},associateNode:function(e){H(e).polymerShadowRenderer_=this}};var q=/^(:not\()?[*.#[a-zA-Z_|]/;N.prototype.invalidateShadowRenderer=function(e){var t=H(this).polymerShadowRenderer_;return!!t&&(t.invalidate(),!0)},O.prototype.getDistributedNodes=L.prototype.getDistributedNodes=function(){return s(),i(this)},M.prototype.getDestinationInsertionPoints=function(){return s(),v(this)||[]},O.prototype.nodeIsInserted_=L.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var e,t=u(this);t&&(e=d(t)),H(this).polymerShadowRenderer_=e,e&&e.invalidate()},e.getRendererForHost=l,e.getShadowTrees=S,e.renderAllPending=s,e.getDestinationInsertionPoints=v,e.visual={insertBefore:n,remove:r}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(t){if(window[t]){r(!e.wrappers[t]);var c=function(e){n.call(this,e)};c.prototype=Object.create(n.prototype),o(c.prototype,{get form(){return s(a(this).form)}}),i(window[t],c,document.createElement(t.slice(4,-7))),e.wrappers[t]=c}}var n=e.wrappers.HTMLElement,r=e.assert,o=e.mixin,i=e.registerWrapper,a=e.unwrap,s=e.wrap,c=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLTextAreaElement"];c.forEach(t)}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r(e,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unsafeUnwrap,i=e.unwrap,a=e.unwrapIfNeeded,s=e.wrap,c=window.Selection;t.prototype={get anchorNode(){return s(o(this).anchorNode)},get focusNode(){return s(o(this).focusNode)},addRange:function(e){o(this).addRange(a(e))},collapse:function(e,t){o(this).collapse(a(e),t)},containsNode:function(e,t){return o(this).containsNode(a(e),t)},getRangeAt:function(e){return s(o(this).getRangeAt(e))},removeRange:function(e){o(this).removeRange(i(e))},selectAllChildren:function(e){o(this).selectAllChildren(e instanceof ShadowRoot?o(e.host):a(e))},toString:function(){return o(this).toString()}},c.prototype.extend&&(t.prototype.extend=function(e,t){o(this).extend(a(e),t)}),n(window.Selection,t,window.getSelection()),e.wrappers.Selection=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){r(e,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unsafeUnwrap,i=e.unwrapIfNeeded,a=e.wrap,s=window.TreeWalker;t.prototype={get root(){return a(o(this).root)},get currentNode(){return a(o(this).currentNode)},set currentNode(e){o(this).currentNode=i(e)},get filter(){return o(this).filter},parentNode:function(){return a(o(this).parentNode())},firstChild:function(){return a(o(this).firstChild())},lastChild:function(){return a(o(this).lastChild())},previousSibling:function(){return a(o(this).previousSibling())},previousNode:function(){return a(o(this).previousNode())},nextNode:function(){return a(o(this).nextNode())}},n(s,t),e.wrappers.TreeWalker=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){u.call(this,e),this.treeScope_=new w(this,null)}function n(e){var n=document[e];t.prototype[e]=function(){return j(n.apply(N(this),arguments))}}function r(e,t){x.call(N(t),C(e)),o(e,t)}function o(e,t){e.shadowRoot&&t.adoptNode(e.shadowRoot),e instanceof m&&i(e,t);for(var n=e.firstChild;n;n=n.nextSibling)o(n,t)}function i(e,t){var n=e.olderShadowRoot;n&&t.adoptNode(n)}function a(e){L(e,this)}function s(e,t){var n=document.implementation[t];e.prototype[t]=function(){
+return j(n.apply(N(this),arguments))}}function c(e,t){var n=document.implementation[t];e.prototype[t]=function(){return n.apply(N(this),arguments)}}var l=e.GetElementsByInterface,u=e.wrappers.Node,d=e.ParentNodeInterface,p=e.NonElementParentNodeInterface,h=e.wrappers.Selection,f=e.SelectorsInterface,m=e.wrappers.ShadowRoot,w=e.TreeScope,v=e.cloneNode,g=e.defineGetter,b=e.defineWrapGetter,y=e.elementFromPoint,E=e.forwardMethodsToWrapper,_=e.matchesNames,S=e.mixin,T=e.registerWrapper,M=e.renderAllPending,O=e.rewrap,L=e.setWrapper,N=e.unsafeUnwrap,C=e.unwrap,j=e.wrap,D=e.wrapEventTargetMethods,H=(e.wrapNodeList,new WeakMap);t.prototype=Object.create(u.prototype),b(t,"documentElement"),b(t,"body"),b(t,"head"),g(t,"activeElement",function(){var e=C(this).activeElement;if(!e||!e.nodeType)return null;for(var t=j(e);!this.contains(t);){for(;t.parentNode;)t=t.parentNode;if(!t.host)return null;t=t.host}return t}),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode"].forEach(n);var x=document.adoptNode,R=document.getSelection;S(t.prototype,{adoptNode:function(e){return e.parentNode&&e.parentNode.removeChild(e),r(e,this),e},elementFromPoint:function(e,t){return y(this,this,e,t)},importNode:function(e,t){return v(e,t,N(this))},getSelection:function(){return M(),new h(R.call(C(this)))},getElementsByName:function(e){return f.querySelectorAll.call(this,"[name="+JSON.stringify(String(e))+"]")}});var I=document.createTreeWalker,P=e.wrappers.TreeWalker;if(t.prototype.createTreeWalker=function(e,t,n,r){var o=null;return n&&(n.acceptNode&&"function"==typeof n.acceptNode?o={acceptNode:function(e){return n.acceptNode(j(e))}}:"function"==typeof n&&(o=function(e){return n(j(e))})),new P(I.call(C(this),C(e),t,o,r))},document.registerElement){var k=document.registerElement;t.prototype.registerElement=function(t,n){function r(e){return e?void L(e,this):i?document.createElement(i,t):document.createElement(t)}var o,i;if(void 0!==n&&(o=n.prototype,i=n["extends"]),o||(o=Object.create(HTMLElement.prototype)),e.nativePrototypeTable.get(o))throw new Error("NotSupportedError");for(var a,s=Object.getPrototypeOf(o),c=[];s&&!(a=e.nativePrototypeTable.get(s));)c.push(s),s=Object.getPrototypeOf(s);if(!a)throw new Error("NotSupportedError");for(var l=Object.create(a),u=c.length-1;u>=0;u--)l=Object.create(l);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(e){var t=o[e];t&&(l[e]=function(){j(this)instanceof r||O(this),t.apply(j(this),arguments)})});var d={prototype:l};i&&(d["extends"]=i),r.prototype=o,r.prototype.constructor=r,e.constructorTable.set(l,r),e.nativePrototypeTable.set(o,l);k.call(C(this),t,d);return r},E([window.HTMLDocument||window.Document],["registerElement"])}E([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"]),E([window.HTMLBodyElement,window.HTMLHeadElement,window.HTMLHtmlElement],_),E([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","createTreeWalker","elementFromPoint","getElementById","getElementsByName","getSelection"]),S(t.prototype,l),S(t.prototype,d),S(t.prototype,f),S(t.prototype,p),S(t.prototype,{get implementation(){var e=H.get(this);return e?e:(e=new a(C(this).implementation),H.set(this,e),e)},get defaultView(){return j(C(this).defaultView)}}),T(window.Document,t,document.implementation.createHTMLDocument("")),window.HTMLDocument&&T(window.HTMLDocument,t),D([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]);var A=document.implementation.createDocument;a.prototype.createDocument=function(){return arguments[2]=C(arguments[2]),j(A.apply(N(this),arguments))},s(a,"createDocumentType"),s(a,"createHTMLDocument"),c(a,"hasFeature"),T(window.DOMImplementation,a),E([window.DOMImplementation],["createDocument","createDocumentType","createHTMLDocument","hasFeature"]),e.adoptNodeNoRemove=r,e.wrappers.DOMImplementation=a,e.wrappers.Document=t}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){n.call(this,e)}var n=e.wrappers.EventTarget,r=e.wrappers.Selection,o=e.mixin,i=e.registerWrapper,a=e.renderAllPending,s=e.unwrap,c=e.unwrapIfNeeded,l=e.wrap,u=window.Window,d=window.getComputedStyle,p=window.getDefaultComputedStyle,h=window.getSelection;t.prototype=Object.create(n.prototype),u.prototype.getComputedStyle=function(e,t){return l(this||window).getComputedStyle(c(e),t)},p&&(u.prototype.getDefaultComputedStyle=function(e,t){return l(this||window).getDefaultComputedStyle(c(e),t)}),u.prototype.getSelection=function(){return l(this||window).getSelection()},delete window.getComputedStyle,delete window.getDefaultComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(e){u.prototype[e]=function(){var t=l(this||window);return t[e].apply(t,arguments)},delete window[e]}),o(t.prototype,{getComputedStyle:function(e,t){return a(),d.call(s(this),c(e),t)},getSelection:function(){return a(),new r(h.call(s(this)))},get document(){return l(s(this).document)}}),p&&(t.prototype.getDefaultComputedStyle=function(e,t){return a(),p.call(s(this),c(e),t)}),i(u,t,window),e.wrappers.Window=t}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrap,n=window.DataTransfer||window.Clipboard,r=n.prototype.setDragImage;r&&(n.prototype.setDragImage=function(e,n,o){r.call(this,t(e),n,o)})}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t;t=e instanceof i?e:new i(e&&o(e)),r(t,this)}var n=e.registerWrapper,r=e.setWrapper,o=e.unwrap,i=window.FormData;i&&(n(i,t,new i),e.wrappers.FormData=t)}(window.ShadowDOMPolyfill),function(e){"use strict";var t=e.unwrapIfNeeded,n=XMLHttpRequest.prototype.send;XMLHttpRequest.prototype.send=function(e){return n.call(this,t(e))}}(window.ShadowDOMPolyfill),function(e){"use strict";function t(e){var t=n[e],r=window[t];if(r){var o=document.createElement(e),i=o.constructor;window[t]=i}}var n=(e.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(n).forEach(t),Object.getOwnPropertyNames(e.wrappers).forEach(function(t){window[t]=e.wrappers[t]})}(window.ShadowDOMPolyfill),function(e){function t(e,t){var n="";return Array.prototype.forEach.call(e,function(e){n+=e.textContent+"\n\n"}),t||(n=n.replace(d,"")),n}function n(e){var t=document.createElement("style");return t.textContent=e,t}function r(e){var t=n(e);document.head.appendChild(t);var r=[];if(t.sheet)try{r=t.sheet.cssRules}catch(o){}else console.warn("sheet not found",t);return t.parentNode.removeChild(t),r}function o(){C.initialized=!0,document.body.appendChild(C);var e=C.contentDocument,t=e.createElement("base");t.href=document.baseURI,e.head.appendChild(t)}function i(e){C.initialized||o(),document.body.appendChild(C),e(C.contentDocument),document.body.removeChild(C)}function a(e,t){if(t){var o;if(e.match("@import")&&D){var a=n(e);i(function(e){e.head.appendChild(a.impl),o=Array.prototype.slice.call(a.sheet.cssRules,0),t(o)})}else o=r(e),t(o)}}function s(e){e&&l().appendChild(document.createTextNode(e))}function c(e,t){var r=n(e);r.setAttribute(t,""),r.setAttribute(x,""),document.head.appendChild(r)}function l(){return j||(j=document.createElement("style"),j.setAttribute(x,""),j[x]=!0),j}var u={strictStyling:!1,registry:{},shimStyling:function(e,n,r){var o=this.prepareRoot(e,n,r),i=this.isTypeExtension(r),a=this.makeScopeSelector(n,i),s=t(o,!0);s=this.scopeCssText(s,a),e&&(e.shimmedStyle=s),this.addCssToDocument(s,n)},shimStyle:function(e,t){return this.shimCssText(e.textContent,t)},shimCssText:function(e,t){return e=this.insertDirectives(e),this.scopeCssText(e,t)},makeScopeSelector:function(e,t){return e?t?"[is="+e+"]":e:""},isTypeExtension:function(e){return e&&e.indexOf("-")<0},prepareRoot:function(e,t,n){var r=this.registerRoot(e,t,n);return this.replaceTextInStyles(r.rootStyles,this.insertDirectives),this.removeStyles(e,r.rootStyles),this.strictStyling&&this.applyScopeToContent(e,t),r.scopeStyles},removeStyles:function(e,t){for(var n,r=0,o=t.length;r<o&&(n=t[r]);r++)n.parentNode.removeChild(n)},registerRoot:function(e,t,n){var r=this.registry[t]={root:e,name:t,extendsName:n},o=this.findStyles(e);r.rootStyles=o,r.scopeStyles=r.rootStyles;var i=this.registry[r.extendsName];return i&&(r.scopeStyles=i.scopeStyles.concat(r.scopeStyles)),r},findStyles:function(e){if(!e)return[];var t=e.querySelectorAll("style");return Array.prototype.filter.call(t,function(e){return!e.hasAttribute(R)})},applyScopeToContent:function(e,t){e&&(Array.prototype.forEach.call(e.querySelectorAll("*"),function(e){e.setAttribute(t,"")}),Array.prototype.forEach.call(e.querySelectorAll("template"),function(e){this.applyScopeToContent(e.content,t)},this))},insertDirectives:function(e){return e=this.insertPolyfillDirectivesInCssText(e),this.insertPolyfillRulesInCssText(e)},insertPolyfillDirectivesInCssText:function(e){return e=e.replace(p,function(e,t){return t.slice(0,-2)+"{"}),e.replace(h,function(e,t){return t+" {"})},insertPolyfillRulesInCssText:function(e){return e=e.replace(f,function(e,t){return t.slice(0,-1)}),e.replace(m,function(e,t,n,r){var o=e.replace(t,"").replace(n,"");return r+o})},scopeCssText:function(e,t){var n=this.extractUnscopedRulesFromCssText(e);if(e=this.insertPolyfillHostInCssText(e),e=this.convertColonHost(e),e=this.convertColonHostContext(e),e=this.convertShadowDOMSelectors(e),t){var e,r=this;a(e,function(n){e=r.scopeRules(n,t)})}return e=e+"\n"+n,e.trim()},extractUnscopedRulesFromCssText:function(e){for(var t,n="";t=w.exec(e);)n+=t[1].slice(0,-1)+"\n\n";for(;t=v.exec(e);)n+=t[0].replace(t[2],"").replace(t[1],t[3])+"\n\n";return n},convertColonHost:function(e){return this.convertColonRule(e,E,this.colonHostPartReplacer)},convertColonHostContext:function(e){return this.convertColonRule(e,_,this.colonHostContextPartReplacer)},convertColonRule:function(e,t,n){return e.replace(t,function(e,t,r,o){if(t=O,r){for(var i,a=r.split(","),s=[],c=0,l=a.length;c<l&&(i=a[c]);c++)i=i.trim(),s.push(n(t,i,o));return s.join(",")}return t+o})},colonHostContextPartReplacer:function(e,t,n){return t.match(g)?this.colonHostPartReplacer(e,t,n):e+t+n+", "+t+" "+e+n},colonHostPartReplacer:function(e,t,n){return e+t.replace(g,"")+n},convertShadowDOMSelectors:function(e){for(var t=0;t<N.length;t++)e=e.replace(N[t]," ");return e},scopeRules:function(e,t){var n="";return e&&Array.prototype.forEach.call(e,function(e){if(e.selectorText&&e.style&&void 0!==e.style.cssText)n+=this.scopeSelector(e.selectorText,t,this.strictStyling)+" {\n\t",n+=this.propertiesFromRule(e)+"\n}\n\n";else if(e.type===CSSRule.MEDIA_RULE)n+="@media "+e.media.mediaText+" {\n",n+=this.scopeRules(e.cssRules,t),n+="\n}\n\n";else try{e.cssText&&(n+=e.cssText+"\n\n")}catch(r){e.type===CSSRule.KEYFRAMES_RULE&&e.cssRules&&(n+=this.ieSafeCssTextFromKeyFrameRule(e))}},this),n},ieSafeCssTextFromKeyFrameRule:function(e){var t="@keyframes "+e.name+" {";return Array.prototype.forEach.call(e.cssRules,function(e){t+=" "+e.keyText+" {"+e.style.cssText+"}"}),t+=" }"},scopeSelector:function(e,t,n){var r=[],o=e.split(",");return o.forEach(function(e){e=e.trim(),this.selectorNeedsScoping(e,t)&&(e=n&&!e.match(O)?this.applyStrictSelectorScope(e,t):this.applySelectorScope(e,t)),r.push(e)},this),r.join(", ")},selectorNeedsScoping:function(e,t){if(Array.isArray(t))return!0;var n=this.makeScopeMatcher(t);return!e.match(n)},makeScopeMatcher:function(e){return e=e.replace(/\[/g,"\\[").replace(/\]/g,"\\]"),new RegExp("^("+e+")"+S,"m")},applySelectorScope:function(e,t){return Array.isArray(t)?this.applySelectorScopeList(e,t):this.applySimpleSelectorScope(e,t)},applySelectorScopeList:function(e,t){for(var n,r=[],o=0;n=t[o];o++)r.push(this.applySimpleSelectorScope(e,n));return r.join(", ")},applySimpleSelectorScope:function(e,t){return e.match(L)?(e=e.replace(O,t),e.replace(L,t+" ")):t+" "+e},applyStrictSelectorScope:function(e,t){t=t.replace(/\[is=([^\]]*)\]/g,"$1");var n=[" ",">","+","~"],r=e,o="["+t+"]";return n.forEach(function(e){var t=r.split(e);r=t.map(function(e){var t=e.trim().replace(L,"");return t&&n.indexOf(t)<0&&t.indexOf(o)<0&&(e=t.replace(/([^:]*)(:*)(.*)/,"$1"+o+"$2$3")),e}).join(e)}),r},insertPolyfillHostInCssText:function(e){return e.replace(M,b).replace(T,g)},propertiesFromRule:function(e){var t=e.style.cssText;e.style.content&&!e.style.content.match(/['"]+|attr/)&&(t=t.replace(/content:[^;]*;/g,"content: '"+e.style.content+"';"));var n=e.style;for(var r in n)"initial"===n[r]&&(t+=r+": initial; ");return t},replaceTextInStyles:function(e,t){e&&t&&(e instanceof Array||(e=[e]),Array.prototype.forEach.call(e,function(e){e.textContent=t.call(this,e.textContent)},this))},addCssToDocument:function(e,t){e.match("@import")?c(e,t):s(e)}},d=/\/\*[^*]*\*+([^\/*][^*]*\*+)*\//gim,p=/\/\*\s*@polyfill ([^*]*\*+([^\/*][^*]*\*+)*\/)([^{]*?){/gim,h=/polyfill-next-selector[^}]*content\:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim,f=/\/\*\s@polyfill-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,m=/(polyfill-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,w=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^\/*][^*]*\*+)*)\//gim,v=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,g="-shadowcsshost",b="-shadowcsscontext",y=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)",E=new RegExp("("+g+y,"gim"),_=new RegExp("("+b+y,"gim"),S="([>\\s~+[.,{:][\\s\\S]*)?$",T=/\:host/gim,M=/\:host-context/gim,O=g+"-no-combinator",L=new RegExp(g,"gim"),N=(new RegExp(b,"gim"),[/>>>/g,/::shadow/g,/::content/g,/\/deep\//g,/\/shadow\//g,/\/shadow-deep\//g,/\^\^/g,/\^(?!=)/g]),C=document.createElement("iframe");C.style.display="none";var j,D=navigator.userAgent.match("Chrome"),H="shim-shadowdom",x="shim-shadowdom-css",R="no-shim";if(window.ShadowDOMPolyfill){s("style { display: none !important; }\n");var I=ShadowDOMPolyfill.wrap(document),P=I.querySelector("head");P.insertBefore(l(),P.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){e.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var t="link[rel=stylesheet]["+H+"]",n="style["+H+"]";HTMLImports.importer.documentPreloadSelectors+=","+t,HTMLImports.importer.importsPreloadSelectors+=","+t,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,t,n].join(",");var r=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(e){if(!e[x]){var t=e.__importElement||e;if(!t.hasAttribute(H))return void r.call(this,e);e.__resource&&(t=e.ownerDocument.createElement("style"),t.textContent=e.__resource),HTMLImports.path.resolveUrlsInStyle(t,e.href),t.textContent=u.shimStyle(t),t.removeAttribute(H,""),t.setAttribute(x,""),t[x]=!0,t.parentNode!==P&&(e.parentNode===P?P.replaceChild(t,e):this.addElementToDocument(t)),t.__importParsed=!0,this.markParsingComplete(e),this.parseNext()}};var o=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(e){return"link"===e.localName&&"stylesheet"===e.rel&&e.hasAttribute(H)?e.__resource:o.call(this,e)}}})}e.ShadowCSS=u}(window.WebComponents)),function(e){window.ShadowDOMPolyfill?(window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}}(window.WebComponents),function(e){"use strict";function t(e){return void 0!==p[e]}function n(){s.call(this),this._isInvalid=!0}function r(e){return""==e&&n.call(this),e.toLowerCase()}function o(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,63,96].indexOf(t)==-1?e:encodeURIComponent(e)}function i(e){var t=e.charCodeAt(0);return t>32&&t<127&&[34,35,60,62,96].indexOf(t)==-1?e:encodeURIComponent(e)}function a(e,a,s){function c(e){b.push(e)}var l=a||"scheme start",u=0,d="",v=!1,g=!1,b=[];e:for(;(e[u-1]!=f||0==u)&&!this._isInvalid;){var y=e[u];switch(l){case"scheme start":if(!y||!m.test(y)){if(a){c("Invalid scheme.");break e}d="",l="no scheme";continue}d+=y.toLowerCase(),l="scheme";break;case"scheme":if(y&&w.test(y))d+=y.toLowerCase();else{if(":"!=y){if(a){if(f==y)break e;c("Code point not allowed in scheme: "+y);break e}d="",u=0,l="no scheme";continue}if(this._scheme=d,d="",a)break e;t(this._scheme)&&(this._isRelative=!0),l="file"==this._scheme?"relative":this._isRelative&&s&&s._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==y?(this._query="?",l="query"):"#"==y?(this._fragment="#",l="fragment"):f!=y&&"\t"!=y&&"\n"!=y&&"\r"!=y&&(this._schemeData+=o(y));break;case"no scheme":if(s&&t(s._scheme)){l="relative";continue}c("Missing scheme."),n.call(this);break;case"relative or authority":if("/"!=y||"/"!=e[u+1]){c("Expected /, got: "+y),l="relative";continue}l="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=s._scheme),f==y){this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._username=s._username,this._password=s._password;break e}if("/"==y||"\\"==y)"\\"==y&&c("\\ is an invalid code point."),l="relative slash";else if("?"==y)this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query="?",this._username=s._username,this._password=s._password,l="query";else{if("#"!=y){var E=e[u+1],_=e[u+2];("file"!=this._scheme||!m.test(y)||":"!=E&&"|"!=E||f!=_&&"/"!=_&&"\\"!=_&&"?"!=_&&"#"!=_)&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password,this._path=s._path.slice(),this._path.pop()),l="relative path";continue}this._host=s._host,this._port=s._port,this._path=s._path.slice(),this._query=s._query,this._fragment="#",this._username=s._username,this._password=s._password,l="fragment"}break;case"relative slash":if("/"!=y&&"\\"!=y){"file"!=this._scheme&&(this._host=s._host,this._port=s._port,this._username=s._username,this._password=s._password),l="relative path";continue}"\\"==y&&c("\\ is an invalid code point."),l="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=y){c("Expected '/', got: "+y),l="authority ignore slashes";continue}l="authority second slash";break;case"authority second slash":if(l="authority ignore slashes","/"!=y){c("Expected '/', got: "+y);continue}break;case"authority ignore slashes":if("/"!=y&&"\\"!=y){l="authority";continue}c("Expected authority, got: "+y);break;case"authority":if("@"==y){v&&(c("@ already seen."),d+="%40"),v=!0;for(var S=0;S<d.length;S++){var T=d[S];if("\t"!=T&&"\n"!=T&&"\r"!=T)if(":"!=T||null!==this._password){var M=o(T);null!==this._password?this._password+=M:this._username+=M}else this._password="";else c("Invalid whitespace in authority.")}d=""}else{if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){u-=d.length,d="",l="host";continue}d+=y}break;case"file host":if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){2!=d.length||!m.test(d[0])||":"!=d[1]&&"|"!=d[1]?0==d.length?l="relative path start":(this._host=r.call(this,d),d="",l="relative path start"):l="relative path";continue}"\t"==y||"\n"==y||"\r"==y?c("Invalid whitespace in file host."):d+=y;break;case"host":case"hostname":if(":"!=y||g){if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y){if(this._host=r.call(this,d),d="",l="relative path start",a)break e;continue}"\t"!=y&&"\n"!=y&&"\r"!=y?("["==y?g=!0:"]"==y&&(g=!1),d+=y):c("Invalid code point in host/hostname: "+y)}else if(this._host=r.call(this,d),d="",l="port","hostname"==a)break e;break;case"port":if(/[0-9]/.test(y))d+=y;else{if(f==y||"/"==y||"\\"==y||"?"==y||"#"==y||a){if(""!=d){var O=parseInt(d,10);O!=p[this._scheme]&&(this._port=O+""),d=""}if(a)break e;l="relative path start";continue}"\t"==y||"\n"==y||"\r"==y?c("Invalid code point in port: "+y):n.call(this)}break;case"relative path start":if("\\"==y&&c("'\\' not allowed in path."),l="relative path","/"!=y&&"\\"!=y)continue;break;case"relative path":if(f!=y&&"/"!=y&&"\\"!=y&&(a||"?"!=y&&"#"!=y))"\t"!=y&&"\n"!=y&&"\r"!=y&&(d+=o(y));else{"\\"==y&&c("\\ not allowed in relative path.");var L;(L=h[d.toLowerCase()])&&(d=L),".."==d?(this._path.pop(),"/"!=y&&"\\"!=y&&this._path.push("")):"."==d&&"/"!=y&&"\\"!=y?this._path.push(""):"."!=d&&("file"==this._scheme&&0==this._path.length&&2==d.length&&m.test(d[0])&&"|"==d[1]&&(d=d[0]+":"),this._path.push(d)),d="","?"==y?(this._query="?",l="query"):"#"==y&&(this._fragment="#",l="fragment")}break;case"query":a||"#"!=y?f!=y&&"\t"!=y&&"\n"!=y&&"\r"!=y&&(this._query+=i(y)):(this._fragment="#",l="fragment");break;case"fragment":f!=y&&"\t"!=y&&"\n"!=y&&"\r"!=y&&(this._fragment+=y)}u++}}function s(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function c(e,t){void 0===t||t instanceof c||(t=new c(String(t))),this._url=e,s.call(this);var n=e.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");a.call(this,n,null,t)}var l=!1;if(!e.forceJURL)try{var u=new URL("b","http://a");u.pathname="c%20d",l="http://a/c%20d"===u.href}catch(d){}if(!l){var p=Object.create(null);p.ftp=21,p.file=0,p.gopher=70,p.http=80,p.https=443,p.ws=80,p.wss=443;var h=Object.create(null);h["%2e"]=".",h[".%2e"]="..",h["%2e."]="..",h["%2e%2e"]="..";var f=void 0,m=/[a-zA-Z]/,w=/[a-zA-Z0-9\+\-\.]/;c.prototype={toString:function(){return this.href},get href(){if(this._isInvalid)return this._url;var e="";return""==this._username&&null==this._password||(e=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+e+this.host:"")+this.pathname+this._query+this._fragment},set href(e){s.call(this),a.call(this,e)},get protocol(){return this._scheme+":"},set protocol(e){this._isInvalid||a.call(this,e+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"host")},get hostname(){return this._host},set hostname(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"hostname")},get port(){return this._port},set port(e){!this._isInvalid&&this._isRelative&&a.call(this,e,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(e){!this._isInvalid&&this._isRelative&&(this._path=[],a.call(this,e,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(e){!this._isInvalid&&this._isRelative&&(this._query="?","?"==e[0]&&(e=e.slice(1)),a.call(this,e,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment},set hash(e){this._isInvalid||(this._fragment="#","#"==e[0]&&(e=e.slice(1)),a.call(this,e,"fragment"))},get origin(){var e;if(this._isInvalid||!this._scheme)return"";switch(this._scheme){case"data":case"file":case"javascript":case"mailto":return"null"}return e=this.host,e?this._scheme+"://"+e:""}};var v=e.URL;v&&(c.createObjectURL=function(e){return v.createObjectURL.apply(v,arguments)},c.revokeObjectURL=function(e){v.revokeObjectURL(e)}),e.URL=c}}(self),function(e){function t(e){y.push(e),b||(b=!0,m(r))}function n(e){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(e)||e}function r(){b=!1;var e=y;y=[],e.sort(function(e,t){return e.uid_-t.uid_});var t=!1;e.forEach(function(e){var n=e.takeRecords();o(e),n.length&&(e.callback_(n,e),t=!0)}),t&&r()}function o(e){e.nodes_.forEach(function(t){var n=w.get(t);n&&n.forEach(function(t){t.observer===e&&t.removeTransientObservers()})})}function i(e,t){for(var n=e;n;n=n.parentNode){var r=w.get(n);if(r)for(var o=0;o<r.length;o++){var i=r[o],a=i.options;if(n===e||a.subtree){var s=t(a);s&&i.enqueue(s)}}}}function a(e){this.callback_=e,this.nodes_=[],this.records_=[],this.uid_=++E}function s(e,t){this.type=e,this.target=t,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function c(e){var t=new s(e.type,e.target);return t.addedNodes=e.addedNodes.slice(),t.removedNodes=e.removedNodes.slice(),t.previousSibling=e.previousSibling,t.nextSibling=e.nextSibling,t.attributeName=e.attributeName,t.attributeNamespace=e.attributeNamespace,t.oldValue=e.oldValue,t}function l(e,t){return _=new s(e,t)}function u(e){return S?S:(S=c(_),S.oldValue=e,S)}function d(){_=S=void 0}function p(e){return e===S||e===_}function h(e,t){return e===t?e:S&&p(e)?S:null}function f(e,t,n){this.observer=e,this.target=t,this.options=n,this.transientObservedNodes=[]}if(!e.JsMutationObserver){var m,w=new WeakMap;if(/Trident|Edge/.test(navigator.userAgent))m=setTimeout;else if(window.setImmediate)m=window.setImmediate;else{var v=[],g=String(Math.random());window.addEventListener("message",function(e){if(e.data===g){var t=v;v=[],t.forEach(function(e){e()})}}),m=function(e){v.push(e),window.postMessage(g,"*")}}var b=!1,y=[],E=0;a.prototype={observe:function(e,t){if(e=n(e),!t.childList&&!t.attributes&&!t.characterData||t.attributeOldValue&&!t.attributes||t.attributeFilter&&t.attributeFilter.length&&!t.attributes||t.characterDataOldValue&&!t.characterData)throw new SyntaxError;var r=w.get(e);r||w.set(e,r=[]);for(var o,i=0;i<r.length;i++)if(r[i].observer===this){o=r[i],o.removeListeners(),o.options=t;break}o||(o=new f(this,e,t),r.push(o),this.nodes_.push(e)),o.addListeners()},disconnect:function(){this.nodes_.forEach(function(e){for(var t=w.get(e),n=0;n<t.length;n++){var r=t[n];if(r.observer===this){r.removeListeners(),t.splice(n,1);break}}},this),this.records_=[]},takeRecords:function(){var e=this.records_;return this.records_=[],e}};var _,S;f.prototype={enqueue:function(e){var n=this.observer.records_,r=n.length;if(n.length>0){var o=n[r-1],i=h(o,e);if(i)return void(n[r-1]=i)}else t(this.observer);n[r]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.addEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=w.get(e);t||w.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=w.get(e),n=0;n<t.length;n++)if(t[n]===this){t.splice(n,1);break}},this)},handleEvent:function(e){switch(e.stopImmediatePropagation(),e.type){case"DOMAttrModified":var t=e.attrName,n=e.relatedNode.namespaceURI,r=e.target,o=new l("attributes",r);o.attributeName=t,o.attributeNamespace=n;var a=e.attrChange===MutationEvent.ADDITION?null:e.prevValue;i(r,function(e){if(e.attributes&&(!e.attributeFilter||!e.attributeFilter.length||e.attributeFilter.indexOf(t)!==-1||e.attributeFilter.indexOf(n)!==-1))return e.attributeOldValue?u(a):o});break;case"DOMCharacterDataModified":var r=e.target,o=l("characterData",r),a=e.prevValue;i(r,function(e){if(e.characterData)return e.characterDataOldValue?u(a):o});break;case"DOMNodeRemoved":this.addTransientObserver(e.target);case"DOMNodeInserted":var s,c,p=e.target;"DOMNodeInserted"===e.type?(s=[p],c=[]):(s=[],c=[p]);var h=p.previousSibling,f=p.nextSibling,o=l("childList",e.target.parentNode);o.addedNodes=s,o.removedNodes=c,o.previousSibling=h,o.nextSibling=f,i(e.relatedNode,function(e){if(e.childList)return o})}d()}},e.JsMutationObserver=a,e.MutationObserver||(e.MutationObserver=a,a._isPolyfilled=!0)}}(self),function(e){"use strict";if(!window.performance||!window.performance.now){var t=Date.now();window.performance={now:function(){return Date.now()-t}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var e=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return e?function(t){return e(function(){t(performance.now())})}:function(e){return window.setTimeout(e,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(e){clearTimeout(e)}}());var n=function(){var e=document.createEvent("Event");return e.initEvent("foo",!0,!0),e.preventDefault(),e.defaultPrevented}();if(!n){var r=Event.prototype.preventDefault;Event.prototype.preventDefault=function(){this.cancelable&&(r.call(this),Object.defineProperty(this,"defaultPrevented",{get:function(){return!0},configurable:!0}))}}var o=/Trident/.test(navigator.userAgent);if((!window.CustomEvent||o&&"function"!=typeof window.CustomEvent)&&(window.CustomEvent=function(e,t){t=t||{};var n=document.createEvent("CustomEvent");return n.initCustomEvent(e,Boolean(t.bubbles),Boolean(t.cancelable),t.detail),n},window.CustomEvent.prototype=window.Event.prototype),!window.Event||o&&"function"!=typeof window.Event){var i=window.Event;window.Event=function(e,t){t=t||{};var n=document.createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelable)),n},window.Event.prototype=i.prototype}}(window.WebComponents),window.HTMLImports=window.HTMLImports||{flags:{}},function(e){function t(e,t){t=t||f,r(function(){i(e,t)},t)}function n(e){return"complete"===e.readyState||e.readyState===v}function r(e,t){if(n(t))e&&e();else{var o=function(){"complete"!==t.readyState&&t.readyState!==v||(t.removeEventListener(g,o),r(e,t))};t.addEventListener(g,o)}}function o(e){e.target.__loaded=!0}function i(e,t){function n(){c==l&&e&&e({allImports:s,loadedImports:u,errorImports:d})}function r(e){o(e),u.push(this),c++,n()}function i(e){
+d.push(this),c++,n()}var s=t.querySelectorAll("link[rel=import]"),c=0,l=s.length,u=[],d=[];if(l)for(var p,h=0;h<l&&(p=s[h]);h++)a(p)?(u.push(this),c++,n()):(p.addEventListener("load",r),p.addEventListener("error",i));else n()}function a(e){return d?e.__loaded||e["import"]&&"loading"!==e["import"].readyState:e.__importParsed}function s(e){for(var t,n=0,r=e.length;n<r&&(t=e[n]);n++)c(t)&&l(t)}function c(e){return"link"===e.localName&&"import"===e.rel}function l(e){var t=e["import"];t?o({target:e}):(e.addEventListener("load",o),e.addEventListener("error",o))}var u="import",d=Boolean(u in document.createElement("link")),p=Boolean(window.ShadowDOMPolyfill),h=function(e){return p?window.ShadowDOMPolyfill.wrapIfNeeded(e):e},f=h(document),m={get:function(){var e=window.HTMLImports.currentScript||document.currentScript||("complete"!==document.readyState?document.scripts[document.scripts.length-1]:null);return h(e)},configurable:!0};Object.defineProperty(document,"_currentScript",m),Object.defineProperty(f,"_currentScript",m);var w=/Trident/.test(navigator.userAgent),v=w?"complete":"interactive",g="readystatechange";d&&(new MutationObserver(function(e){for(var t,n=0,r=e.length;n<r&&(t=e[n]);n++)t.addedNodes&&s(t.addedNodes)}).observe(document.head,{childList:!0}),function(){if("loading"===document.readyState)for(var e,t=document.querySelectorAll("link[rel=import]"),n=0,r=t.length;n<r&&(e=t[n]);n++)l(e)}()),t(function(e){window.HTMLImports.ready=!0,window.HTMLImports.readyTime=(new Date).getTime();var t=f.createEvent("CustomEvent");t.initCustomEvent("HTMLImportsLoaded",!0,!0,e),f.dispatchEvent(t)}),e.IMPORT_LINK_TYPE=u,e.useNative=d,e.rootDocument=f,e.whenReady=t,e.isIE=w}(window.HTMLImports),function(e){var t=[],n=function(e){t.push(e)},r=function(){t.forEach(function(t){t(e)})};e.addModule=n,e.initializeModules=r}(window.HTMLImports),window.HTMLImports.addModule(function(e){var t=/(url\()([^)]*)(\))/g,n=/(@import[\s]+(?!url\())([^;]*)(;)/g,r={resolveUrlsInStyle:function(e,t){var n=e.ownerDocument,r=n.createElement("a");return e.textContent=this.resolveUrlsInCssText(e.textContent,t,r),e},resolveUrlsInCssText:function(e,r,o){var i=this.replaceUrls(e,o,r,t);return i=this.replaceUrls(i,o,r,n)},replaceUrls:function(e,t,n,r){return e.replace(r,function(e,r,o,i){var a=o.replace(/["']/g,"");return n&&(a=new URL(a,n).href),t.href=a,a=t.href,r+"'"+a+"'"+i})}};e.path=r}),window.HTMLImports.addModule(function(e){var t={async:!0,ok:function(e){return e.status>=200&&e.status<300||304===e.status||0===e.status},load:function(n,r,o){var i=new XMLHttpRequest;return(e.flags.debug||e.flags.bust)&&(n+="?"+Math.random()),i.open("GET",n,t.async),i.addEventListener("readystatechange",function(e){if(4===i.readyState){var n=null;try{var a=i.getResponseHeader("Location");a&&(n="/"===a.substr(0,1)?location.origin+a:a)}catch(e){console.error(e.message)}r.call(o,!t.ok(i)&&i,i.response||i.responseText,n)}}),i.send(),i},loadDocument:function(e,t,n){this.load(e,t,n).responseType="document"}};e.xhr=t}),window.HTMLImports.addModule(function(e){var t=e.xhr,n=e.flags,r=function(e,t){this.cache={},this.onload=e,this.oncomplete=t,this.inflight=0,this.pending={}};r.prototype={addNodes:function(e){this.inflight+=e.length;for(var t,n=0,r=e.length;n<r&&(t=e[n]);n++)this.require(t);this.checkDone()},addNode:function(e){this.inflight++,this.require(e),this.checkDone()},require:function(e){var t=e.src||e.href;e.__nodeUrl=t,this.dedupe(t,e)||this.fetch(t,e)},dedupe:function(e,t){if(this.pending[e])return this.pending[e].push(t),!0;return this.cache[e]?(this.onload(e,t,this.cache[e]),this.tail(),!0):(this.pending[e]=[t],!1)},fetch:function(e,r){if(n.load&&console.log("fetch",e,r),e)if(e.match(/^data:/)){var o=e.split(","),i=o[0],a=o[1];a=i.indexOf(";base64")>-1?atob(a):decodeURIComponent(a),setTimeout(function(){this.receive(e,r,null,a)}.bind(this),0)}else{var s=function(t,n,o){this.receive(e,r,t,n,o)}.bind(this);t.load(e,s)}else setTimeout(function(){this.receive(e,r,{error:"href must be specified"},null)}.bind(this),0)},receive:function(e,t,n,r,o){this.cache[e]=r;for(var i,a=this.pending[e],s=0,c=a.length;s<c&&(i=a[s]);s++)this.onload(e,i,r,n,o),this.tail();this.pending[e]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},e.Loader=r}),window.HTMLImports.addModule(function(e){var t=function(e){this.addCallback=e,this.mo=new MutationObserver(this.handler.bind(this))};t.prototype={handler:function(e){for(var t,n=0,r=e.length;n<r&&(t=e[n]);n++)"childList"===t.type&&t.addedNodes.length&&this.addedNodes(t.addedNodes)},addedNodes:function(e){this.addCallback&&this.addCallback(e);for(var t,n=0,r=e.length;n<r&&(t=e[n]);n++)t.children&&t.children.length&&this.addedNodes(t.children)},observe:function(e){this.mo.observe(e,{childList:!0,subtree:!0})}},e.Observer=t}),window.HTMLImports.addModule(function(e){function t(e){return"link"===e.localName&&e.rel===u}function n(e){var t=r(e);return"data:text/javascript;charset=utf-8,"+encodeURIComponent(t)}function r(e){return e.textContent+o(e)}function o(e){var t=e.ownerDocument;t.__importedScripts=t.__importedScripts||0;var n=e.ownerDocument.baseURI,r=t.__importedScripts?"-"+t.__importedScripts:"";return t.__importedScripts++,"\n//# sourceURL="+n+r+".js\n"}function i(e){var t=e.ownerDocument.createElement("style");return t.textContent=e.textContent,a.resolveUrlsInStyle(t),t}var a=e.path,s=e.rootDocument,c=e.flags,l=e.isIE,u=e.IMPORT_LINK_TYPE,d="link[rel="+u+"]",p={documentSelectors:d,importsSelectors:[d,"link[rel=stylesheet]:not([type])","style:not([type])","script:not([type])",'script[type="application/javascript"]','script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},dynamicElements:[],parseNext:function(){var e=this.nextToParse();e&&this.parse(e)},parse:function(e){if(this.isParsed(e))return void(c.parse&&console.log("[%s] is already parsed",e.localName));var t=this[this.map[e.localName]];t&&(this.markParsing(e),t.call(this,e))},parseDynamic:function(e,t){this.dynamicElements.push(e),t||this.parseNext()},markParsing:function(e){c.parse&&console.log("parsing",e),this.parsingElement=e},markParsingComplete:function(e){e.__importParsed=!0,this.markDynamicParsingComplete(e),e.__importElement&&(e.__importElement.__importParsed=!0,this.markDynamicParsingComplete(e.__importElement)),this.parsingElement=null,c.parse&&console.log("completed",e)},markDynamicParsingComplete:function(e){var t=this.dynamicElements.indexOf(e);t>=0&&this.dynamicElements.splice(t,1)},parseImport:function(e){if(e["import"]=e.__doc,window.HTMLImports.__importsParsingHook&&window.HTMLImports.__importsParsingHook(e),e["import"]&&(e["import"].__importParsed=!0),this.markParsingComplete(e),e.__resource&&!e.__error?e.dispatchEvent(new CustomEvent("load",{bubbles:!1})):e.dispatchEvent(new CustomEvent("error",{bubbles:!1})),e.__pending)for(var t;e.__pending.length;)t=e.__pending.shift(),t&&t({target:e});this.parseNext()},parseLink:function(e){t(e)?this.parseImport(e):(e.href=e.href,this.parseGeneric(e))},parseStyle:function(e){var t=e;e=i(e),t.__appliedElement=e,e.__importElement=t,this.parseGeneric(e)},parseGeneric:function(e){this.trackElement(e),this.addElementToDocument(e)},rootImportForElement:function(e){for(var t=e;t.ownerDocument.__importLink;)t=t.ownerDocument.__importLink;return t},addElementToDocument:function(e){var t=this.rootImportForElement(e.__importElement||e);t.parentNode.insertBefore(e,t)},trackElement:function(e,t){var n=this,r=function(o){e.removeEventListener("load",r),e.removeEventListener("error",r),t&&t(o),n.markParsingComplete(e),n.parseNext()};if(e.addEventListener("load",r),e.addEventListener("error",r),l&&"style"===e.localName){var o=!1;if(e.textContent.indexOf("@import")==-1)o=!0;else if(e.sheet){o=!0;for(var i,a=e.sheet.cssRules,s=a?a.length:0,c=0;c<s&&(i=a[c]);c++)i.type===CSSRule.IMPORT_RULE&&(o=o&&Boolean(i.styleSheet))}o&&setTimeout(function(){e.dispatchEvent(new CustomEvent("load",{bubbles:!1}))})}},parseScript:function(t){var r=document.createElement("script");r.__importElement=t,r.src=t.src?t.src:n(t),e.currentScript=t,this.trackElement(r,function(t){r.parentNode&&r.parentNode.removeChild(r),e.currentScript=null}),this.addElementToDocument(r)},nextToParse:function(){return this._mayParse=[],!this.parsingElement&&(this.nextToParseInDoc(s)||this.nextToParseDynamic())},nextToParseInDoc:function(e,n){if(e&&this._mayParse.indexOf(e)<0){this._mayParse.push(e);for(var r,o=e.querySelectorAll(this.parseSelectorsForNode(e)),i=0,a=o.length;i<a&&(r=o[i]);i++)if(!this.isParsed(r))return this.hasResource(r)?t(r)?this.nextToParseInDoc(r.__doc,r):r:void 0}return n},nextToParseDynamic:function(){return this.dynamicElements[0]},parseSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===s?this.documentSelectors:this.importsSelectors},isParsed:function(e){return e.__importParsed},needsDynamicParsing:function(e){return this.dynamicElements.indexOf(e)>=0},hasResource:function(e){return!t(e)||void 0!==e.__doc}};e.parser=p,e.IMPORT_SELECTOR=d}),window.HTMLImports.addModule(function(e){function t(e){return n(e,a)}function n(e,t){return"link"===e.localName&&e.getAttribute("rel")===t}function r(e){return!!Object.getOwnPropertyDescriptor(e,"baseURI")}function o(e,t){var n=document.implementation.createHTMLDocument(a);n._URL=t;var o=n.createElement("base");o.setAttribute("href",t),n.baseURI||r(n)||Object.defineProperty(n,"baseURI",{value:t});var i=n.createElement("meta");return i.setAttribute("charset","utf-8"),n.head.appendChild(i),n.head.appendChild(o),n.body.innerHTML=e,window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(n),n}var i=e.flags,a=e.IMPORT_LINK_TYPE,s=e.IMPORT_SELECTOR,c=e.rootDocument,l=e.Loader,u=e.Observer,d=e.parser,p={documents:{},documentPreloadSelectors:s,importsPreloadSelectors:[s].join(","),loadNode:function(e){h.addNode(e)},loadSubtree:function(e){var t=this.marshalNodes(e);h.addNodes(t)},marshalNodes:function(e){return e.querySelectorAll(this.loadSelectorsForNode(e))},loadSelectorsForNode:function(e){var t=e.ownerDocument||e;return t===c?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(e,n,r,a,s){if(i.load&&console.log("loaded",e,n),n.__resource=r,n.__error=a,t(n)){var c=this.documents[e];void 0===c&&(c=a?null:o(r,s||e),c&&(c.__importLink=n,this.bootDocument(c)),this.documents[e]=c),n.__doc=c}d.parseNext()},bootDocument:function(e){this.loadSubtree(e),this.observer.observe(e),d.parseNext()},loadedAll:function(){d.parseNext()}},h=new l(p.loaded.bind(p),p.loadedAll.bind(p));if(p.observer=new u,!document.baseURI){var f={get:function(){var e=document.querySelector("base");return e?e.href:window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",f),Object.defineProperty(c,"baseURI",f)}e.importer=p,e.importLoader=h}),window.HTMLImports.addModule(function(e){var t=e.parser,n=e.importer,r={added:function(e){for(var r,o,i,a,s=0,c=e.length;s<c&&(a=e[s]);s++)r||(r=a.ownerDocument,o=t.isParsed(r)),i=this.shouldLoadNode(a),i&&n.loadNode(a),this.shouldParseNode(a)&&o&&t.parseDynamic(a,i)},shouldLoadNode:function(e){return 1===e.nodeType&&o.call(e,n.loadSelectorsForNode(e))},shouldParseNode:function(e){return 1===e.nodeType&&o.call(e,t.parseSelectorsForNode(e))}};n.observer.addCallback=r.added.bind(r);var o=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector}),function(e){function t(){window.HTMLImports.importer.bootDocument(r)}var n=e.initializeModules;e.isIE;if(!e.useNative){n();var r=e.rootDocument;"complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?t():document.addEventListener("DOMContentLoaded",t)}}(window.HTMLImports),window.CustomElements=window.CustomElements||{flags:{}},function(e){var t=e.flags,n=[],r=function(e){n.push(e)},o=function(){n.forEach(function(t){t(e)})};e.addModule=r,e.initializeModules=o,e.hasNative=Boolean(document.registerElement),e.isIE=/Trident/.test(navigator.userAgent),e.useNative=!t.register&&e.hasNative&&!window.ShadowDOMPolyfill&&(!window.HTMLImports||window.HTMLImports.useNative)}(window.CustomElements),window.CustomElements.addModule(function(e){function t(e,t){n(e,function(e){return!!t(e)||void r(e,t)}),r(e,t)}function n(e,t,r){var o=e.firstElementChild;if(!o)for(o=e.firstChild;o&&o.nodeType!==Node.ELEMENT_NODE;)o=o.nextSibling;for(;o;)t(o,r)!==!0&&n(o,t,r),o=o.nextElementSibling;return null}function r(e,n){for(var r=e.shadowRoot;r;)t(r,n),r=r.olderShadowRoot}function o(e,t){i(e,t,[])}function i(e,t,n){if(e=window.wrap(e),!(n.indexOf(e)>=0)){n.push(e);for(var r,o=e.querySelectorAll("link[rel="+a+"]"),s=0,c=o.length;s<c&&(r=o[s]);s++)r["import"]&&i(r["import"],t,n);t(e)}}var a=window.HTMLImports?window.HTMLImports.IMPORT_LINK_TYPE:"none";e.forDocumentTree=o,e.forSubtree=t}),window.CustomElements.addModule(function(e){function t(e,t){return n(e,t)||r(e,t)}function n(t,n){return!!e.upgrade(t,n)||void(n&&a(t))}function r(e,t){b(e,function(e){if(n(e,t))return!0})}function o(e){S.push(e),_||(_=!0,setTimeout(i))}function i(){_=!1;for(var e,t=S,n=0,r=t.length;n<r&&(e=t[n]);n++)e();S=[]}function a(e){E?o(function(){s(e)}):s(e)}function s(e){e.__upgraded__&&!e.__attached&&(e.__attached=!0,e.attachedCallback&&e.attachedCallback())}function c(e){l(e),b(e,function(e){l(e)})}function l(e){E?o(function(){u(e)}):u(e)}function u(e){e.__upgraded__&&e.__attached&&(e.__attached=!1,e.detachedCallback&&e.detachedCallback())}function d(e){for(var t=e,n=window.wrap(document);t;){if(t==n)return!0;t=t.parentNode||t.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&t.host}}function p(e){if(e.shadowRoot&&!e.shadowRoot.__watched){g.dom&&console.log("watching shadow-root for: ",e.localName);for(var t=e.shadowRoot;t;)m(t),t=t.olderShadowRoot}}function h(e,n){if(g.dom){var r=n[0];if(r&&"childList"===r.type&&r.addedNodes&&r.addedNodes){for(var o=r.addedNodes[0];o&&o!==document&&!o.host;)o=o.parentNode;var i=o&&(o.URL||o._URL||o.host&&o.host.localName)||"";i=i.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",n.length,i||"")}var a=d(e);n.forEach(function(e){"childList"===e.type&&(T(e.addedNodes,function(e){e.localName&&t(e,a)}),T(e.removedNodes,function(e){e.localName&&c(e)}))}),g.dom&&console.groupEnd()}function f(e){for(e=window.wrap(e),e||(e=window.wrap(document));e.parentNode;)e=e.parentNode;var t=e.__observer;t&&(h(e,t.takeRecords()),i())}function m(e){if(!e.__observer){var t=new MutationObserver(h.bind(this,e));t.observe(e,{childList:!0,subtree:!0}),e.__observer=t}}function w(e){e=window.wrap(e),g.dom&&console.group("upgradeDocument: ",e.baseURI.split("/").pop());var n=e===window.wrap(document);t(e,n),m(e),g.dom&&console.groupEnd()}function v(e){y(e,w)}var g=e.flags,b=e.forSubtree,y=e.forDocumentTree,E=window.MutationObserver._isPolyfilled&&g["throttle-attached"];e.hasPolyfillMutations=E,e.hasThrottledAttached=E;var _=!1,S=[],T=Array.prototype.forEach.call.bind(Array.prototype.forEach),M=Element.prototype.createShadowRoot;M&&(Element.prototype.createShadowRoot=function(){var e=M.call(this);return window.CustomElements.watchShadow(this),e}),e.watchShadow=p,e.upgradeDocumentTree=v,e.upgradeDocument=w,e.upgradeSubtree=r,e.upgradeAll=t,e.attached=a,e.takeRecords=f}),window.CustomElements.addModule(function(e){function t(t,r){if("template"===t.localName&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t),!t.__upgraded__&&t.nodeType===Node.ELEMENT_NODE){var o=t.getAttribute("is"),i=e.getRegisteredDefinition(t.localName)||e.getRegisteredDefinition(o);if(i&&(o&&i.tag==t.localName||!o&&!i["extends"]))return n(t,i,r)}}function n(t,n,o){return a.upgrade&&console.group("upgrade:",t.localName),n.is&&t.setAttribute("is",n.is),r(t,n),t.__upgraded__=!0,i(t),o&&e.attached(t),e.upgradeSubtree(t,o),a.upgrade&&console.groupEnd(),t}function r(e,t){Object.__proto__?e.__proto__=t.prototype:(o(e,t.prototype,t["native"]),e.__proto__=t.prototype)}function o(e,t,n){for(var r={},o=t;o!==n&&o!==HTMLElement.prototype;){for(var i,a=Object.getOwnPropertyNames(o),s=0;i=a[s];s++)r[i]||(Object.defineProperty(e,i,Object.getOwnPropertyDescriptor(o,i)),r[i]=1);o=Object.getPrototypeOf(o)}}function i(e){e.createdCallback&&e.createdCallback()}var a=e.flags;e.upgrade=t,e.upgradeWithDefinition=n,e.implementPrototype=r}),window.CustomElements.addModule(function(e){function t(t,r){var c=r||{};if(!t)throw new Error("document.registerElement: first argument `name` must not be empty");if(t.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(t)+"'.");if(o(t))throw new Error("Failed to execute 'registerElement' on 'Document': Registration failed for type '"+String(t)+"'. The type name is invalid.");if(l(t))throw new Error("DuplicateDefinitionError: a type with name '"+String(t)+"' is already registered");return c.prototype||(c.prototype=Object.create(HTMLElement.prototype)),c.__name=t.toLowerCase(),c["extends"]&&(c["extends"]=c["extends"].toLowerCase()),c.lifecycle=c.lifecycle||{},c.ancestry=i(c["extends"]),a(c),s(c),n(c.prototype),u(c.__name,c),c.ctor=d(c),c.ctor.prototype=c.prototype,c.prototype.constructor=c.ctor,e.ready&&w(document),c.ctor}function n(e){if(!e.setAttribute._polyfilled){var t=e.setAttribute;e.setAttribute=function(e,n){r.call(this,e,n,t)};var n=e.removeAttribute;e.removeAttribute=function(e){r.call(this,e,null,n)},e.setAttribute._polyfilled=!0}}function r(e,t,n){e=e.toLowerCase();var r=this.getAttribute(e);n.apply(this,arguments);var o=this.getAttribute(e);this.attributeChangedCallback&&o!==r&&this.attributeChangedCallback(e,r,o)}function o(e){for(var t=0;t<E.length;t++)if(e===E[t])return!0}function i(e){var t=l(e);return t?i(t["extends"]).concat([t]):[]}function a(e){for(var t,n=e["extends"],r=0;t=e.ancestry[r];r++)n=t.is&&t.tag;e.tag=n||e.__name,n&&(e.is=e.__name)}function s(e){if(!Object.__proto__){var t=HTMLElement.prototype;if(e.is){var n=document.createElement(e.tag);t=Object.getPrototypeOf(n)}for(var r,o=e.prototype,i=!1;o;)o==t&&(i=!0),r=Object.getPrototypeOf(o),r&&(o.__proto__=r),o=r;i||console.warn(e.tag+" prototype not found in prototype chain for "+e.is),e["native"]=t}}function c(e){return g(T(e.tag),e)}function l(e){if(e)return _[e.toLowerCase()]}function u(e,t){_[e]=t}function d(e){return function(){return c(e)}}function p(e,t,n){return e===S?h(t,n):M(e,t)}function h(e,t){e&&(e=e.toLowerCase()),t&&(t=t.toLowerCase());var n=l(t||e);if(n){if(e==n.tag&&t==n.is)return new n.ctor;if(!t&&!n.is)return new n.ctor}var r;return t?(r=h(e),r.setAttribute("is",t),r):(r=T(e),e.indexOf("-")>=0&&b(r,HTMLElement),r)}function f(e,t){var n=e[t];e[t]=function(){var e=n.apply(this,arguments);return v(e),e}}var m,w=(e.isIE,e.upgradeDocumentTree),v=e.upgradeAll,g=e.upgradeWithDefinition,b=e.implementPrototype,y=e.useNative,E=["annotation-xml","color-profile","font-face","font-face-src","font-face-uri","font-face-format","font-face-name","missing-glyph"],_={},S="http://www.w3.org/1999/xhtml",T=document.createElement.bind(document),M=document.createElementNS.bind(document);m=Object.__proto__||y?function(e,t){return e instanceof t}:function(e,t){if(e instanceof t)return!0;for(var n=e;n;){if(n===t.prototype)return!0;n=n.__proto__}return!1},f(Node.prototype,"cloneNode"),f(document,"importNode"),document.registerElement=t,document.createElement=h,document.createElementNS=p,e.registry=_,e["instanceof"]=m,e.reservedTagList=E,e.getRegisteredDefinition=l,document.register=document.registerElement}),function(e){function t(){i(window.wrap(document)),window.CustomElements.ready=!0;var e=window.requestAnimationFrame||function(e){setTimeout(e,16)};e(function(){setTimeout(function(){window.CustomElements.readyTime=Date.now(),window.HTMLImports&&(window.CustomElements.elapsed=window.CustomElements.readyTime-window.HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})})}var n=e.useNative,r=e.initializeModules;e.isIE;if(n){var o=function(){};e.watchShadow=o,e.upgrade=o,e.upgradeAll=o,e.upgradeDocumentTree=o,e.upgradeSubtree=o,e.takeRecords=o,e["instanceof"]=function(e,t){return e instanceof t}}else r();var i=e.upgradeDocumentTree,a=e.upgradeDocument;if(window.wrap||(window.ShadowDOMPolyfill?(window.wrap=window.ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=window.ShadowDOMPolyfill.unwrapIfNeeded):window.wrap=window.unwrap=function(e){return e}),window.HTMLImports&&(window.HTMLImports.__importsParsingHook=function(e){e["import"]&&a(wrap(e["import"]))}),"complete"===document.readyState||e.flags.eager)t();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var s=window.HTMLImports&&!window.HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(s,t)}else t()}(window.CustomElements),function(e){Function.prototype.bind||(Function.prototype.bind=function(e){var t=this,n=Array.prototype.slice.call(arguments,1);return function(){var r=n.slice();return r.push.apply(r,arguments),t.apply(e,r)}})}(window.WebComponents),function(e){var t=document.createElement("style");t.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; position: relative; } \n";var n=document.querySelector("head");n.insertBefore(t,n.firstChild)}(window.WebComponents),function(e){window.Platform=e}(window.WebComponents);
\ No newline at end of file
diff --git a/runtime/observatory_2/web/timeline.html b/runtime/observatory_2/web/timeline.html
new file mode 100644
index 0000000..4bbc396
--- /dev/null
+++ b/runtime/observatory_2/web/timeline.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html style="height: 100%; width: 100%">
+<head>
+  <meta charset="utf-8">
+  <title>Dart VM Observatory Timeline</title>
+  <script src="timeline_message_handler.js"></script>
+  <script src="third_party/webcomponents.min.js"></script>
+  <link rel="import" href="third_party/trace_viewer_full.html">
+  <script src="timeline.js"></script>
+  <style>
+html, body {
+  box-sizing: border-box;
+  overflow: hidden;
+  margin: 0px;
+  padding: 0;
+  width: 100%;
+  height: 100%;
+}
+#trace-viewer {
+  width: 100%;
+  height: 100%;
+}
+#trace-viewer:focus {
+  outline: none;
+}
+  </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/runtime/observatory_2/web/timeline.js b/runtime/observatory_2/web/timeline.js
new file mode 100644
index 0000000..5b431f6
--- /dev/null
+++ b/runtime/observatory_2/web/timeline.js
@@ -0,0 +1,667 @@
+// 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
+// BSD-style license that can be found in the LICENSE file.
+
+// See also timeline_message_handler.js.
+
+var pendingRequests;
+var loadingOverlay;
+
+function onModelLoaded(model) {
+  viewer.globalMode = true;
+  viewer.model = model;
+}
+
+function clearTimeline() {
+  viewer.model = undefined;
+}
+
+function onImportFail(err) {
+  var overlay = new tr.ui.b.Overlay();
+  overlay.textContent = tr.b.normalizeException(err).message;
+  overlay.title = 'Import error';
+  overlay.visible = true;
+  console.log('import failed');
+}
+
+function compareTimestamp(a, b) { return a.ts - b.ts; }
+function compareBeginTimestamp(a, b) { return a.begin.ts - b.begin.ts; }
+function compareEndTimestamp(a, b) { return a.end.ts - b.end.ts; }
+
+var basicModelEventsWaterfall = [
+  // Sort events and remove orphan async ends.
+  function filterUnwantedEvents(events) {
+    events = events.slice();
+    events.sort(compareTimestamp);
+    var threads = {};
+    return events.filter(function (event) {
+      if (event.ph === 'E') {
+        return threads[event.tid] && threads[event.tid].pop();
+      }
+      var result = event.args && event.args.mode === 'basic';
+      if (event.ph === 'B') {
+        threads[event.tid] = threads[event.tid] || [];
+        threads[event.tid].push(result);
+      }
+      return result;
+    });
+  }
+];
+
+var frameModelEventsWaterfall = [
+  // Sort events and remove orphan async ends.
+  function filterUnwantedEvents(events) {
+    events = events.slice();
+    events.sort(compareTimestamp);
+    var threads = {};
+    return events.filter(function (event) {
+      if (event.ph === 'E') {
+        if (!threads[event.tid]) {
+          return false
+        }
+        threads[event.tid] -= 1;
+      } else if (event.ph === 'B') {
+        threads[event.tid] = (threads[event.tid] || 0) + 1;
+      }
+      return true;
+    });
+  },
+  // Clone the events (we want to preserve them for dumps).
+  function cloneDeep(input) {
+    if (typeof input === 'object') {
+      if (Array.isArray(input)) {
+        return input.map(cloneDeep);
+      } else {
+        var clone = {};
+        Object.keys(input).forEach(function (key) {
+          clone[key] = cloneDeep(input[key]);
+        });
+        return clone;
+      }
+    }
+    return input;
+  },
+  // Group nested sync begin end sequences on every thread.
+  //
+  // Example:
+  // Input = [B,B,E,B,E,E,B,E,B,B,E,E]
+  // Output = [[B,B,E,B,E,E],[B,E],[B,B,E,E]]
+  function groupIsolatedPerThreadSequences(events) {
+    var sequences = [],
+      timeless = [],
+      threadOpen = {};
+      threadSequences = {};
+    events.forEach(function (event) {
+      if (event.ph === 'M') {
+        timeless.push(event);
+      } else if (event.ph === 'B') {
+        threadOpen[event.tid] = Math.max(threadOpen[event.tid] || 0) + 1;
+        threadSequences[event.tid] = threadSequences[event.tid] || [];
+        threadSequences[event.tid].push(event);
+      } else if (event.ph === 'E') {
+        threadSequences[event.tid].push(event);
+        threadOpen[event.tid] -= 1;
+        if (threadOpen[event.tid] == 0) {
+          threadSequences[event.tid].sort()
+          sequences.push(threadSequences[event.tid]);
+          threadSequences[event.tid] = [];
+        }
+      } else if (threadSequences[event.tid]){
+        threadSequences[event.tid] = threadSequences[event.tid] || [];
+        threadSequences[event.tid].push(event);
+      }
+    })
+    return {
+      timeless: timeless,
+      sequences: sequences
+    };
+  },
+  // Transform every sequence into an object for rapid begin end analysis and
+  // block types lookup.
+  //
+  // Example:
+  // Input = [B1,B2,E2,B3,E3,E1]
+  // Output = {
+  //   begin: B1,
+  //   end: E1,
+  //   events: [B1,B2,E2,B3,E3,E1],
+  //   isGPU: ...,
+  //   isVSync: ...,
+  //   isFramework: ...,
+  //   isShiftable: ...,
+  // }
+  function sequenceToBlockDescriptor(input) {
+    return {
+      timeless: input.timeless,
+      blocks: input.sequences.map(function (events) {
+        var begin,
+            end,
+            isGPU,
+            isVSync,
+            isFramework;
+        events.forEach(function (event) {
+          if (event.ph === 'B') {
+            begin = begin || event;
+          } else if (event.ph === 'E') {
+            end = event;
+          }
+        });
+        isGPU = begin.name === 'GPU Workload';
+        isVSync = begin.name === 'VSYNC';
+        isFramework = begin.name === 'Framework Workload';
+        return {
+          begin: begin,
+          end: end,
+          events: events,
+          isGPU: isGPU,
+          isVSync: isVSync,
+          isFramework: isFramework,
+          isShiftable: !(isGPU || isVSync || isFramework)
+        };
+      })
+    };
+  },
+  // Remove all the blocks that ended before the first VSYNC.
+  // These events do not give any information to the analysis.
+  function removePreVSyncBlocks(input) {
+    input.blocks.sort(compareEndTimestamp);
+    var sawVSyncBlock = false;
+    return {
+      timeless: input.timeless,
+      blocks: input.blocks.filter(function (block) {
+        sawVSyncBlock = sawVSyncBlock || block.isVSync;
+        return sawVSyncBlock;
+      })
+    };
+  },
+  // Remove all the GPU blocks that started before the first Framework block.
+  // They are orphans of other frames.
+  function removePreFrameworkGPUBlocks(input) {
+    input.blocks.sort(compareBeginTimestamp);
+    var firstFrameworkBlockBeginTimestamp = 0;
+    return {
+      timeless: input.timeless,
+      blocks: input.blocks.filter(function (block) {
+        if (block.isFramework) {
+          firstFrameworkBlockBeginTimestamp =
+              firstFrameworkBlockBeginTimestamp || block.begin.ts;
+        } else if (block.isGPU) {
+          if (!firstFrameworkBlockBeginTimestamp) {
+            return false;
+          } else if (block.begin.ts < firstFrameworkBlockBeginTimestamp) {
+            return false;
+          }
+        }
+        return true;
+      })
+    };
+  },
+  // Merge all shiftable blocks that are between two Framework blocks.
+  // By merging them we preserve their relative timing.
+  function mergeShiftableBlocks(input) {
+    input.blocks.sort(compareEndTimestamp);
+    var begin,
+        end,
+        events = [],
+        shiftableBlocks = [],
+        blocks;
+    blocks = input.blocks.filter(function (block) {
+      if (block.isShiftable) {
+        begin = begin || block.begin;
+        end = block.end;
+        events = events.concat(block.events);
+        return false;
+      } else if (block.isFramework) {
+        if (events.length) {
+          shiftableBlocks.push({
+            begin: begin,
+            end: end,
+            events: events
+          });
+        }
+      }
+      return true;
+    });
+    if (events.length) {
+      shiftableBlocks.push({
+        begin: begin,
+        end: end,
+        events: events
+      });
+    }
+    return {
+      timeless: input.timeless,
+      blocks: blocks.concat(shiftableBlocks)
+    };
+  },
+  // Remove all VSyncs that didn't started an actual frame.
+  function filterFramelessVSyncs(input) {
+    input.blocks.sort(compareBeginTimestamp);
+    var lastVSyncBlock,
+      blocks,
+      vSyncBlocks = [];
+    blocks = input.blocks.filter(function (block) {
+      if (block.isVSync) {
+        lastVSyncBlock = block;
+        return false;
+      } else if (block.isFramework) {
+        vSyncBlocks.push(lastVSyncBlock);
+      }
+      return true;
+    });
+    return {
+      timeless: input.timeless,
+      blocks: blocks.concat(vSyncBlocks)
+    };
+  },
+  // Group blocks by type.
+  //
+  // Example:
+  // Input = [S1, V1, F1, V2, G1, F2, V3, G2, F3]
+  // Output = {
+  //   gpu: [G1, G2],
+  //   vsync: [V1, V2, V3],
+  //   framework: [F1, F2, F3],
+  //   shiftable: [S1]
+  // }
+  function groupBlocksByFrames(input) {
+    return {
+      timeless: input.timeless,
+      gpu: input.blocks.filter(function (b) { return b.isGPU; }),
+      vsync: input.blocks.filter(function (b) { return b.isVSync; }),
+      framework: input.blocks.filter(function (b) { return b.isFramework; }),
+      shiftable: input.blocks.filter(function (b) { return b.isShiftable; })
+    };
+  },
+  // Remove possible out of sync GPU Blocks.
+  // If the buffer has already delete the VSync and the Framework, but not the
+  // GPU it can potentially be still alive.
+  function groupBlocksByFrames(input) {
+    var gpu = input.gpu,
+        framework = input.framework;
+    while (gpu.length &&
+           gpu[0].begin.args.frame !== framework[0].begin.args.frame) {
+      gpu.shift();
+    }
+    return input;
+  },
+  // Group blocks related to the same frame.
+  // Input = {
+  //   gpu: [G1, G2],
+  //   vsync: [V1, V2],
+  //   framework: [F1, F2],
+  //   shiftable: [S1]
+  // }
+  // Output = [{V1, F1, G1, S1}, {V2, F2, G2}, {V3, F3, G3}]
+  function groupBlocksByFrames(input) {
+    var shiftable = input.shiftable.slice();
+    return {
+      timeless: input.timeless,
+      frames: input.vsync.map(function (vsync, i) {
+        var frame = {
+          begin: vsync.begin,
+          vsync: vsync,
+          framework: input.framework[i],
+          deadline: parseInt(vsync.begin.args.deadline) + 1000
+        };
+        if (i < input.gpu.length) {
+          frame.gpu = input.gpu[i];
+        }
+        if (shiftable.length && shiftable[0].begin.ts < framework.begin.ts ) {
+          frame.shiftable = shiftable.shift();
+        }
+        return frame;
+      })
+    };
+  },
+  // Move Framework and GPU as back in time as possible
+  //
+  // Example:
+  // Before
+  //                               [GPU]
+  //     [VSYNC]
+  //  [SHIFTABLE]     [FRAMEWORK]
+  // After
+  //             |[GPU]
+  //     [VSYNC] |
+  //  [SHIFTABLE]|[FRAMEWORK]
+  function shiftEvents(input) {
+    input.frames.forEach(function (frame) {
+      var earlierTimestamp = frame.vsync.end.ts,
+          shift;
+      if (frame.shiftable) {
+        frame.shiftable.events.forEach(function (event) {
+          if (event.tid === frame.framework.begin.tid) {
+            earlierTimestamp = Math.max(earlierTimestamp, event.ts);
+          }
+        });
+      }
+      if (frame.gpu) {
+        if (frame.shiftable) {
+          frame.shiftable.events.forEach(function (event) {
+            if (event.tid === frame.gpu.begin.tid) {
+              earlierTimestamp = Math.max(earlierTimestamp, event.ts);
+            }
+          });
+        }
+        shift = earlierTimestamp - frame.gpu.begin.ts;
+        frame.gpu.events.forEach(function (event) {
+          event.ts += shift;
+        });
+      }
+      shift = earlierTimestamp - frame.framework.begin.ts;
+      frame.framework.events.forEach(function (event) {
+        event.ts += shift;
+      });
+      frame.end = frame.framework.end;
+      if (frame.gpu && frame.framework.end.ts < frame.gpu.end.ts) {
+        frame.end = frame.gpu.end;
+      }
+    });
+    return input;
+  },
+  // Group events in frame (precomputation for next stage).
+  function groupEventsInFrame(input) {
+    input.frames.forEach(function (frame) {
+      var events = frame.vsync.events;
+      events = events.concat(frame.framework.events);
+      if (frame.gpu) {
+        events = events.concat(frame.gpu.events);
+      }
+      if (frame.shiftable) {
+        events = events.concat(frame.shiftable.events);
+      }
+      events.sort(compareTimestamp);
+      frame.events = events;
+    });
+    return input;
+  },
+  // Move frames in order to do not overlap.
+  //
+  // Example:
+  // Before
+  //              |[GPU1--------------------]
+  //                                     |[GPU2----]
+  //     [VSYNC1] |             [VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]          |[FRAMEWORK2]
+  // After
+  //              |[GPU1--------------------]|         |[GPU2-----]
+  //     [VSYNC1] |                          |[VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]              |         |[FRAMEWORK2]
+  // OtherExample:
+  // Before
+  //     {FRAME BUDGET1-------------------------}
+  //                            {FRAME BUDGET2-------------------------}
+  //              |[GPU1]
+  //                                     |[GPU2]
+  //     [VSYNC1] |             [VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]          |[FRAMEWORK2]
+  // After
+  //     {FRAME BUDGET1-------------------------}|{FRAME BUDGET2----------------
+  //              |[GPU1]                        |         |[GPU2-----]
+  //     [VSYNC1] |                              |[VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]                  |         |[FRAMEWORK2]
+  function shiftBlocks(input) {
+    function minThreadtimestamps(frame) {
+      var timestamps = {};
+      frame.events.forEach(function (event) {
+        if (event.tid != undefined) {
+          timestamps[event.tid] = timestamps[event.tid] || event.ts;
+        }
+      });
+      return timestamps;
+    }
+    function maxThreadTimestamps(frame) {
+      var timestamps = {};
+      frame.events.forEach(function (event) {
+        if (event.tid != undefined) {
+          timestamps[event.tid] = event.ts;
+        }
+      });
+      return timestamps;
+    }
+    input.frames.slice(1).forEach(function (current, index) {
+      var previous = input.frames[index],
+        shift = Math.max(previous.end.ts, previous.deadline) - current.begin.ts,
+        maxThreadTimestamp = maxThreadTimestamps(previous),
+        minThreadTimestamp = minThreadtimestamps(current);
+      Object.keys(maxThreadTimestamp).forEach(function (tid) {
+        if (minThreadTimestamp[tid]) {
+          var delta = maxThreadTimestamp[tid] - minThreadTimestamp[tid];
+          shift = Math.max(shift, delta);
+        }
+      });
+      current.events.forEach(function (event) {
+        event.ts += shift;
+      });
+      current.deadline += shift;
+    });
+    return input;
+  },
+  // Add auxilary events to frame (Frame Budget and Frame Length).
+  // Example:
+  // Before
+  //              |[GPU1--------------------]|         |[GPU2-----]
+  //     [VSYNC1] |                          |[VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]              |         |[FRAMEWORK2]
+  // After
+  //     [Budget1---------------------------]|[Budget2--------------------------
+  //     [Length1---------------------------]|[Length2------------]
+  //              |[GPU1--------------------]|         |[GPU2-----]
+  //     [VSYNC1] |                          |[VSYNC2] |
+  //  [SHIFTABLE1]|[FRAMEWORK1]              |         |[FRAMEWORK2]
+  function addAuxilaryEvents(input) {
+    input.frames.forEach(function (frame) {
+      frame.events.unshift({
+        args: {name: "Frame Budgets"},
+        name: "thread_name",
+        ph: "M",
+        pid: frame.begin.pid,
+        tid: "budgets",
+      });
+      frame.events.unshift({
+        args: {name: "Frames"},
+        name: "thread_name",
+        ph: "M",
+        pid: frame.begin.pid,
+        tid: "frames",
+      });
+      var duration = Math.floor((frame.end.ts - frame.begin.ts) / 1000),
+          frameName = "Frame " + duration + "ms";
+      frame.events = frame.events.concat({
+          ph: "B",
+          name: "Frame Budget",
+          cat: "budgets",
+          pid: frame.begin.pid,
+          tid: "budgets",
+          ts: frame.begin.ts
+        }, {
+          ph: "E",
+          name: "Frame Budget",
+          cat: "budgets",
+          pid: frame.begin.pid,
+          tid: "budgets",
+          ts: frame.deadline,
+          cname: 'rail_response'
+        }, {
+          ph: "B",
+          name: frameName,
+          cat: "frames",
+          pid: frame.begin.pid,
+          tid: "frames",
+          ts: frame.begin.ts
+        }, {
+          ph: "E",
+          name: frameName,
+          cat: "frames",
+          pid: frame.begin.pid,
+          tid: "frames",
+          ts: frame.end.ts,
+          cname: frame.end.ts > frame.deadline ? 'terrible' : 'good'
+        });
+    });
+    return input;
+  },
+  // Restore the events array used by catapult.
+  function linearizeBlocks(input) {
+    return input.frames.reduce(function (events, frame) {
+      return events.concat(frame.events);
+    }, input.timeless);
+  }
+];
+
+function basicModelEventsMap(events) {
+  return basicModelEventsWaterfall.reduce(function (input, step) {
+    return step(input);
+  }, events);
+}
+
+function frameModelEventsMap(events) {
+  return frameModelEventsWaterfall.reduce(function (input, step) {
+    return step(input);
+  }, events);
+}
+
+function updateTimeline(events) {
+  if (window.location.hash.indexOf('mode=basic') > -1) {
+    events = {
+      'stackFrames': events['stackFrames'],
+      'traceEvents': basicModelEventsMap(events['traceEvents'])
+    };
+  }
+  if (window.location.hash.indexOf('view=frame') > -1) {
+    events = {
+      'stackFrames': events['stackFrames'],
+      'traceEvents': frameModelEventsMap(events['traceEvents'])
+    };
+  }
+  var model = new tr.Model();
+  var importer = new tr.importer.Import(model);
+  var p = importer.importTracesWithProgressDialog([events]);
+  p.then(onModelLoaded.bind(undefined, model), onImportFail);
+}
+
+function showLoadingOverlay(msg) {
+  if (!loadingOverlay) {
+    loadingOverlay = new tr.ui.b.Overlay();
+  }
+  loadingOverlay.textContent = msg;
+  loadingOverlay.title = 'Loading...';
+  loadingOverlay.visible = true;
+}
+
+function hideLoadingOverlay() {
+  if (!loadingOverlay) {
+    return;
+  }
+  loadingOverlay.visible = false;
+  loadingOverlay = undefined;
+}
+
+function populateTimeline() {
+  updateTimeline(traceObject);
+  hideLoadingOverlay();
+}
+
+function saveTimeline() {
+  if (pendingRequests > 0) {
+    var overlay = new tr.ui.b.Overlay();
+    overlay.textContent = 'Cannot save timeline while fetching one.';
+    overlay.title = 'Save error';
+    overlay.visible = true;
+    console.log('cannot save timeline while fetching one.');
+    return;
+  }
+  if (!traceObject ||
+      !traceObject.traceEvents ||
+      (traceObject.traceEvents.length === 0)) {
+    var overlay = new tr.ui.b.Overlay();
+    overlay.textContent = 'Cannot save an empty timeline.';
+    overlay.title = 'Save error';
+    overlay.visible = true;
+    console.log('Cannot save an empty timeline.');
+    return;
+  }
+  var blob = new Blob([JSON.stringify(traceObject)],
+                      {type: 'application/json'});
+  var blobUrl = URL.createObjectURL(blob);
+  var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
+  link.href = blobUrl;
+  var now = new Date();
+  var defaultFilename = 'dart-timeline-' +
+                        now.getFullYear() +
+                        '-' +
+                        (now.getMonth() + 1) +
+                        '-' +
+                        now.getDate() +
+                        '.json';
+  var filename = window.prompt('Save as', defaultFilename);
+  if (filename) {
+    link.download = filename;
+    link.click();
+  }
+}
+
+function loadTimeline() {
+  if (pendingRequests > 0) {
+    var overlay = new tr.ui.b.Overlay();
+    overlay.textContent = 'Cannot load timeline while fetching one.';
+    overlay.title = 'Save error';
+    overlay.visible = true;
+    console.log('Cannot load timeline while fetching one.');
+    return;
+  }
+  var inputElement = document.createElement('input');
+  inputElement.type = 'file';
+  inputElement.multiple = false;
+
+  var changeFired = false;
+  inputElement.addEventListener('change', function(e) {
+    if (changeFired)
+      return;
+    changeFired = true;
+
+    var file = inputElement.files[0];
+    var reader = new FileReader();
+    reader.onload = function(event) {
+      try {
+        traceObject = JSON.parse(event.target.result);
+        updateTimeline(traceObject);
+      } catch (error) {
+        tr.ui.b.Overlay.showError('Error while loading file: ' + error);
+      }
+    };
+    reader.onerror = function(event) {
+      tr.ui.b.Overlay.showError('Error while loading file: ' + event);
+    };
+    reader.onabort = function(event) {
+      tr.ui.b.Overlay.showError('Error while loading file: ' + event);
+    }
+    reader.readAsText(file);
+  });
+  inputElement.click();
+}
+
+function refreshTimeline() {
+  updateTimeline(traceObject);
+}
+
+window.addEventListener('DOMContentLoaded', function() {
+  var container = document.createElement('track-view-container');
+  container.id = 'track_view_container';
+  viewer = document.createElement('tr-ui-timeline-view');
+  viewer.track_view_container = container;
+  viewer.appendChild(container);
+  viewer.id = 'trace-viewer';
+  viewer.globalMode = true;
+  document.body.appendChild(viewer);
+  timeline_loaded = true;
+  console.log('DOMContentLoaded');
+  document.getElementById('trace-viewer').highlightVSync = true;
+  if (traceObject != undefined) {
+    refreshTimeline();
+    traceObject = undefined;
+  }
+});
+
+console.log('timeline.js loaded');
diff --git a/runtime/observatory_2/web/timeline_message_handler.js b/runtime/observatory_2/web/timeline_message_handler.js
new file mode 100644
index 0000000..4b3f11a
--- /dev/null
+++ b/runtime/observatory_2/web/timeline_message_handler.js
@@ -0,0 +1,52 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file is loaded before the about:tracing code is loaded so that we have
+// an event listener registered early.
+
+var traceObject;
+
+function registerForMessages() {
+  window.addEventListener("message", onMessage, false);
+  window.addEventListener("hashchange", onHashChange, false);
+}
+
+registerForMessages();
+
+function onMessage(event) {
+  var request = JSON.parse(event.data);
+  var method = request['method'];
+  var params = request['params'];
+  console.log('method: ' + method)
+  switch (method) {
+    case 'loading':
+      showLoadingOverlay('Fetching timeline...');
+    break;
+    case 'refresh':
+      traceObject = params;
+      if (typeof populateTimeline != 'undefined') {
+        populateTimeline();
+      } else {
+        console.log('populateTimeline is not yet defined');
+      }
+    break;
+    case 'clear':
+      clearTimeline();
+    break;
+    case 'save':
+      saveTimeline();
+    break;
+    case 'load':
+      loadTimeline();
+    break;
+    default:
+      console.log('Unknown method:' + method + '.');
+  }
+}
+
+function onHashChange() {
+  refreshTimeline();
+}
+
+console.log('message handler registered');
diff --git a/runtime/platform/assert.h b/runtime/platform/assert.h
index 6b5d634..c31c1cc 100644
--- a/runtime/platform/assert.h
+++ b/runtime/platform/assert.h
@@ -208,7 +208,15 @@
 
 }  // namespace dart
 
-#define FATAL(error) dart::Assert(__FILE__, __LINE__).Fail("%s", error)
+#if defined(_MSC_VER)
+#define FATAL(format, ...)                                                     \
+  dart::Assert(__FILE__, __LINE__).Fail(format, __VA_ARGS__);
+#else
+#define FATAL(format, ...)                                                     \
+  dart::Assert(__FILE__, __LINE__).Fail(format, ##__VA_ARGS__);
+#endif
+
+// Leaving old non-varargs versions to avoid having to rewrite all uses.
 
 #define FATAL1(format, p1) dart::Assert(__FILE__, __LINE__).Fail(format, (p1))
 
diff --git a/runtime/platform/elf.h b/runtime/platform/elf.h
index 42c2f87..8f58005 100644
--- a/runtime/platform/elf.h
+++ b/runtime/platform/elf.h
@@ -189,11 +189,29 @@
 static const intptr_t STB_LOCAL = 0;
 static const intptr_t STB_GLOBAL = 1;
 
+static const intptr_t STT_NOTYPE = 0;
 static const intptr_t STT_OBJECT = 1;  // I.e., data.
 static const intptr_t STT_FUNC = 2;
 static const intptr_t STT_SECTION = 3;
 
-static constexpr const char* ELF_NOTE_GNU = "GNU";
+static constexpr const char ELF_NOTE_GNU[] = "GNU";
+
+// Creates symbol info from the given STB and STT values.
+constexpr decltype(Symbol::info) SymbolInfo(intptr_t binding, intptr_t type) {
+  // Take the low nibble of each value in case, though the upper bits should
+  // all be zero as long as STB/STT constants are used.
+  return (binding & 0xf) << 4 | (type & 0xf);
+}
+
+// Retrieves the STB binding value for the given symbol info.
+constexpr intptr_t SymbolBinding(const decltype(Symbol::info) info) {
+  return (info >> 4) & 0xf;
+}
+
+// Retrieves the STT type value for the given symbol info.
+constexpr intptr_t SymbolType(const decltype(Symbol::info) info) {
+  return info & 0xf;
+}
 
 }  // namespace elf
 }  // namespace dart
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 91d062b..1796c33 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -449,112 +449,136 @@
 #define strtoll _strtoi64
 #endif
 
+// Byte sizes.
+constexpr int kInt8SizeLog2 = 0;
+constexpr int kInt8Size = 1 << kInt8SizeLog2;
+static_assert(kInt8Size == sizeof(int8_t), "Mismatched int8 size constant");
+constexpr int kInt16SizeLog2 = 1;
+constexpr int kInt16Size = 1 << kInt16SizeLog2;
+static_assert(kInt16Size == sizeof(int16_t), "Mismatched int16 size constant");
+constexpr int kInt32SizeLog2 = 2;
+constexpr int kInt32Size = 1 << kInt32SizeLog2;
+static_assert(kInt32Size == sizeof(int32_t), "Mismatched int32 size constant");
+constexpr int kInt64SizeLog2 = 3;
+constexpr int kInt64Size = 1 << kInt64SizeLog2;
+static_assert(kInt64Size == sizeof(int64_t), "Mismatched int64 size constant");
+
+constexpr int kDoubleSize = sizeof(double);
+constexpr int kFloatSize = sizeof(float);
+constexpr int kQuadSize = 4 * kFloatSize;
+constexpr int kSimd128Size = sizeof(simd128_value_t);
+
+// Bit sizes.
+constexpr int kBitsPerByteLog2 = 3;
+constexpr int kBitsPerByte = 1 << kBitsPerByteLog2;
+constexpr int kBitsPerInt8 = kInt8Size * kBitsPerByte;
+constexpr int kBitsPerInt16 = kInt16Size * kBitsPerByte;
+constexpr int kBitsPerInt32 = kInt32Size * kBitsPerByte;
+constexpr int kBitsPerInt64 = kInt64Size * kBitsPerByte;
+
 // The following macro works on both 32 and 64-bit platforms.
 // Usage: instead of writing 0x1234567890123456ULL
 //      write DART_2PART_UINT64_C(0x12345678,90123456);
 #define DART_2PART_UINT64_C(a, b)                                              \
-  (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+  (((static_cast<uint64_t>(a) << kBitsPerInt32) + 0x##b##u))
 
 // Integer constants.
-const int8_t kMinInt8 = 0x80;
-const int8_t kMaxInt8 = 0x7F;
-const uint8_t kMaxUint8 = 0xFF;
-const int16_t kMinInt16 = 0x8000;
-const int16_t kMaxInt16 = 0x7FFF;
-const uint16_t kMaxUint16 = 0xFFFF;
-const int32_t kMinInt32 = 0x80000000;
-const int32_t kMaxInt32 = 0x7FFFFFFF;
-const uint32_t kMaxUint32 = 0xFFFFFFFF;
-const int64_t kMinInt64 = DART_INT64_C(0x8000000000000000);
-const int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF);
-const int kMinInt = INT_MIN;
-const int kMaxInt = INT_MAX;
-const int64_t kMinInt64RepresentableAsDouble = kMinInt64;
-const int64_t kMaxInt64RepresentableAsDouble = DART_INT64_C(0x7FFFFFFFFFFFFC00);
-const uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
-const int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000);
+constexpr int8_t kMinInt8 = 0x80;
+constexpr int8_t kMaxInt8 = 0x7F;
+constexpr uint8_t kMaxUint8 = 0xFF;
+constexpr int16_t kMinInt16 = 0x8000;
+constexpr int16_t kMaxInt16 = 0x7FFF;
+constexpr uint16_t kMaxUint16 = 0xFFFF;
+constexpr int32_t kMinInt32 = 0x80000000;
+constexpr int32_t kMaxInt32 = 0x7FFFFFFF;
+constexpr uint32_t kMaxUint32 = 0xFFFFFFFF;
+constexpr int64_t kMinInt64 = DART_INT64_C(0x8000000000000000);
+constexpr int64_t kMaxInt64 = DART_INT64_C(0x7FFFFFFFFFFFFFFF);
+constexpr uint64_t kMaxUint64 = DART_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
+
+constexpr int kMinInt = INT_MIN;
+constexpr int kMaxInt = INT_MAX;
+constexpr int kMaxUint = UINT_MAX;
+
+constexpr int64_t kMinInt64RepresentableAsDouble = kMinInt64;
+constexpr int64_t kMaxInt64RepresentableAsDouble =
+    DART_INT64_C(0x7FFFFFFFFFFFFC00);
+constexpr int64_t kSignBitDouble = DART_INT64_C(0x8000000000000000);
 
 // Types for native machine words. Guaranteed to be able to hold pointers and
 // integers.
 typedef intptr_t word;
 typedef uintptr_t uword;
 
+// Byte sizes for native machine words.
+#ifdef ARCH_IS_32_BIT
+constexpr int kWordSizeLog2 = kInt32SizeLog2;
+#else
+constexpr int kWordSizeLog2 = kInt64SizeLog2;
+#endif
+constexpr int kWordSize = 1 << kWordSizeLog2;
+static_assert(kWordSize == sizeof(word), "Mismatched word size constant");
+
+// Bit sizes for native machine words.
+constexpr int kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
+constexpr int kBitsPerWord = 1 << kBitsPerWordLog2;
+
+// Integer constants for native machine words.
+constexpr word kWordMin = static_cast<uword>(1) << (kBitsPerWord - 1);
+constexpr word kWordMax = (static_cast<uword>(1) << (kBitsPerWord - 1)) - 1;
+constexpr uword kUwordMax = static_cast<uword>(-1);
+
 // Size of a class id assigned to concrete, abstract and top-level classes.
 //
 // We use a signed integer type here to make it comparable with intptr_t.
 typedef int32_t classid_t;
 
-// Byte sizes.
-const int kWordSize = sizeof(word);
-const int kDoubleSize = sizeof(double);  // NOLINT
-const int kFloatSize = sizeof(float);    // NOLINT
-const int kQuadSize = 4 * kFloatSize;
-const int kSimd128Size = sizeof(simd128_value_t);  // NOLINT
-const int kInt64Size = sizeof(int64_t);            // NOLINT
-const int kInt32Size = sizeof(int32_t);            // NOLINT
-const int kInt16Size = sizeof(int16_t);            // NOLINT
-#ifdef ARCH_IS_32_BIT
-const int kWordSizeLog2 = 2;
-const uword kUwordMax = kMaxUint32;
-#else
-const int kWordSizeLog2 = 3;
-const uword kUwordMax = kMaxUint64;
-#endif
-
-// Bit sizes.
-const int kBitsPerByte = 8;
-const int kBitsPerByteLog2 = 3;
-const int kBitsPerInt32 = kInt32Size * kBitsPerByte;
-const int kBitsPerInt64 = kInt64Size * kBitsPerByte;
-const int kBitsPerWord = kWordSize * kBitsPerByte;
-const int kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
-
 // System-wide named constants.
-const intptr_t KB = 1024;
-const intptr_t KBLog2 = 10;
-const intptr_t MB = KB * KB;
-const intptr_t MBLog2 = KBLog2 + KBLog2;
-const intptr_t GB = MB * KB;
-const intptr_t GBLog2 = MBLog2 + KBLog2;
+constexpr intptr_t KBLog2 = 10;
+constexpr intptr_t KB = 1 << KBLog2;
+constexpr intptr_t MBLog2 = KBLog2 + KBLog2;
+constexpr intptr_t MB = 1 << MBLog2;
+constexpr intptr_t GBLog2 = MBLog2 + KBLog2;
+constexpr intptr_t GB = 1 << GBLog2;
 
-const intptr_t KBInWords = KB >> kWordSizeLog2;
-const intptr_t KBInWordsLog2 = KBLog2 - kWordSizeLog2;
-const intptr_t MBInWords = KB * KBInWords;
-const intptr_t MBInWordsLog2 = KBLog2 + KBInWordsLog2;
-const intptr_t GBInWords = MB * KBInWords;
-const intptr_t GBInWordsLog2 = MBLog2 + KBInWordsLog2;
+constexpr intptr_t KBInWordsLog2 = KBLog2 - kWordSizeLog2;
+constexpr intptr_t KBInWords = 1 << KBInWordsLog2;
+constexpr intptr_t MBInWordsLog2 = KBLog2 + KBInWordsLog2;
+constexpr intptr_t MBInWords = 1 << MBInWordsLog2;
+constexpr intptr_t GBInWordsLog2 = MBLog2 + KBInWordsLog2;
+constexpr intptr_t GBInWords = 1 << GBInWordsLog2;
 
 // Helpers to round memory sizes to human readable values.
-inline intptr_t RoundWordsToKB(intptr_t size_in_words) {
+constexpr intptr_t RoundWordsToKB(intptr_t size_in_words) {
   return (size_in_words + (KBInWords >> 1)) >> KBInWordsLog2;
 }
-inline intptr_t RoundWordsToMB(intptr_t size_in_words) {
+constexpr intptr_t RoundWordsToMB(intptr_t size_in_words) {
   return (size_in_words + (MBInWords >> 1)) >> MBInWordsLog2;
 }
-inline intptr_t RoundWordsToGB(intptr_t size_in_words) {
+constexpr intptr_t RoundWordsToGB(intptr_t size_in_words) {
   return (size_in_words + (GBInWords >> 1)) >> GBInWordsLog2;
 }
 
-const intptr_t kIntptrOne = 1;
-const intptr_t kIntptrMin = (kIntptrOne << (kBitsPerWord - 1));
-const intptr_t kIntptrMax = ~kIntptrMin;
+constexpr intptr_t kIntptrOne = 1;
+constexpr intptr_t kIntptrMin = (kIntptrOne << (kBitsPerWord - 1));
+constexpr intptr_t kIntptrMax = ~kIntptrMin;
 
 // Time constants.
-const int kMillisecondsPerSecond = 1000;
-const int kMicrosecondsPerMillisecond = 1000;
-const int kMicrosecondsPerSecond =
+constexpr int kMillisecondsPerSecond = 1000;
+constexpr int kMicrosecondsPerMillisecond = 1000;
+constexpr int kMicrosecondsPerSecond =
     (kMicrosecondsPerMillisecond * kMillisecondsPerSecond);
-const int kNanosecondsPerMicrosecond = 1000;
-const int kNanosecondsPerMillisecond =
+constexpr int kNanosecondsPerMicrosecond = 1000;
+constexpr int kNanosecondsPerMillisecond =
     (kNanosecondsPerMicrosecond * kMicrosecondsPerMillisecond);
-const int kNanosecondsPerSecond =
+constexpr int kNanosecondsPerSecond =
     (kNanosecondsPerMicrosecond * kMicrosecondsPerSecond);
 
 // Helpers to scale micro second times to human understandable values.
-inline double MicrosecondsToSeconds(int64_t micros) {
+constexpr double MicrosecondsToSeconds(int64_t micros) {
   return static_cast<double>(micros) / kMicrosecondsPerSecond;
 }
-inline double MicrosecondsToMilliseconds(int64_t micros) {
+constexpr double MicrosecondsToMilliseconds(int64_t micros) {
   return static_cast<double>(micros) / kMicrosecondsPerMillisecond;
 }
 
@@ -598,7 +622,7 @@
 // The USE(x) template is used to silence C++ compiler warnings issued
 // for unused variables.
 template <typename T>
-static inline void USE(T) {}
+static inline void USE(T&&) {}
 
 // The type-based aliasing rule allows the compiler to assume that
 // pointers of different types (for some definition of different)
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 57bb31a..baa4ff4 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -387,29 +387,6 @@
     return ((mask >> position) & 1) != 0;
   }
 
-  // Decode integer in SLEB128 format from |data| and update |byte_index|.
-  template <typename ValueType>
-  static ValueType DecodeSLEB128(const uint8_t* data,
-                                 const intptr_t data_length,
-                                 intptr_t* byte_index) {
-    using Unsigned = typename std::make_unsigned<ValueType>::type;
-    ASSERT(*byte_index < data_length);
-    uword shift = 0;
-    Unsigned value = 0;
-    uint8_t part = 0;
-    do {
-      part = data[(*byte_index)++];
-      value |= static_cast<Unsigned>(part & 0x7f) << shift;
-      shift += 7;
-    } while ((part & 0x80) != 0);
-
-    if ((shift < (sizeof(ValueType) * CHAR_BIT)) && ((part & 0x40) != 0)) {
-      const Unsigned kMax = std::numeric_limits<Unsigned>::max();
-      value |= static_cast<Unsigned>(kMax << shift);
-    }
-    return static_cast<ValueType>(value);
-  }
-
   static char* StrError(int err, char* buffer, size_t bufsize);
 
   // Not all platforms support strndup.
diff --git a/runtime/tests/vm/dart/appjit_bytecode_simple_test.dart b/runtime/tests/vm/dart/appjit_bytecode_simple_test.dart
deleted file mode 100644
index d936339..0000000
--- a/runtime/tests/vm/dart/appjit_bytecode_simple_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=appjit_bytecode_simple_test_body.dart
-
-// Verify that app-jit snapshot contains dependencies between classes and CHA
-// optimized code.
-
-import 'dart:async';
-import 'dart:io' show Platform;
-
-import 'snapshot_test_helper.dart';
-
-Future<void> main() => runAppJitBytecodeTest(
-    Platform.script.resolve('appjit_bytecode_simple_test_body.dart'));
diff --git a/runtime/tests/vm/dart/appjit_bytecode_simple_test_body.dart b/runtime/tests/vm/dart/appjit_bytecode_simple_test_body.dart
deleted file mode 100644
index a882e9a..0000000
--- a/runtime/tests/vm/dart/appjit_bytecode_simple_test_body.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-void main(List<String> args) {
-  final isTraining = args.contains("--train");
-  print(isTraining ? 'OK(Trained)' : 'OK(Run)');
-}
diff --git a/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart b/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart
deleted file mode 100644
index 72f6b76..0000000
--- a/runtime/tests/vm/dart/bytecode_and_ast_mix_test.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=bytecode_and_ast_mix_test_body.dart
-
-// Tests the mix of kernel AST (test) and bytecode dill files (core libraries).
-// Verifies that kernel AST can reference a not yet loaded bytecode class
-// through a constant in metadata.
-
-import 'dart:io' show Platform;
-
-import 'package:path/path.dart' as path;
-import 'snapshot_test_helper.dart';
-
-main() async {
-  final testScriptUri =
-      Platform.script.resolve('bytecode_and_ast_mix_test_body.dart');
-  await withTempDir((String temp) async {
-    final dillPath = path.join(temp, 'ast.dill');
-    final testPath = testScriptUri.toFilePath();
-
-    final buildResult = await runGenKernel('BUILD AST DILL FILE', [
-      '--no-gen-bytecode',
-      '--output=$dillPath',
-      testPath,
-    ]);
-    print(buildResult);
-    final runResult = await runDart('RUN FROM AST DILL FILE', [dillPath]);
-    expectOutput("OK", runResult);
-  });
-}
diff --git a/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart b/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart
deleted file mode 100644
index 703a2cc..0000000
--- a/runtime/tests/vm/dart/bytecode_and_ast_mix_test_body.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:mirrors';
-import 'package:expect/expect.dart';
-
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  @override
-  void foo() {}
-}
-
-main() {
-  ClassMirror classB = reflectClass(B);
-  MethodMirror foo = classB.declarations[#foo] as MethodMirror;
-  final annotation = foo.metadata[0].reflectee;
-  Expect.isTrue(annotation.toString().contains('_Override'));
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart
deleted file mode 100644
index a44f8f2..0000000
--- a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=bytecode_with_ast_in_aot_test_body1.dart
-// OtherResources=bytecode_with_ast_in_aot_test_body2.dart
-
-// Tests that gen_kernel is able to produce dill file with both bytecode
-// and AST in AOT mode, and gen_snapshot is able to consume them.
-// Two test cases are only different in number of entry points, so
-// obfuscation prohibitions metadata has different size, causing
-// different alignment of bytecode metadata.
-
-import 'dart:io' show Platform;
-
-import 'package:path/path.dart' as path;
-import 'snapshot_test_helper.dart';
-
-testAOTOnBytecodeWithAST(String temp, String source) async {
-  final sourcePath = Platform.script.resolve(source).toFilePath();
-  final dillPath = path.join(temp, '${source}.dill');
-  final snapshotPath = path.join(temp, '${source}.so');
-
-  final genKernelResult = await runGenKernel('BUILD DILL FILE', [
-    '--aot',
-    '--gen-bytecode',
-    '--no-drop-ast',
-    '--output=$dillPath',
-    sourcePath,
-  ]);
-  print(genKernelResult);
-  final genSnapshotResult = await runGenSnapshot('GENERATE SNAPSHOT', [
-    '--use-bytecode-compiler',
-    '--snapshot-kind=app-aot-elf',
-    '--elf=$snapshotPath',
-    dillPath,
-  ]);
-  print(genSnapshotResult);
-  final runResult =
-      await runBinary('RUN SNAPSHOT', dartPrecompiledRuntime, [snapshotPath]);
-  expectOutput("OK", runResult);
-}
-
-main() async {
-  await withTempDir((String temp) async {
-    await testAOTOnBytecodeWithAST(
-        temp, 'bytecode_with_ast_in_aot_test_body1.dart');
-    await testAOTOnBytecodeWithAST(
-        temp, 'bytecode_with_ast_in_aot_test_body2.dart');
-  });
-}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart
deleted file mode 100644
index 18ae42b..0000000
--- a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body1.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test case for bytecode_with_ast_in_aot_test.dart.
-// Contains 1 entry point.
-
-import 'package:expect/expect.dart';
-
-class A {
-  // Make sure obfuscation prohibitions metadata is generated.
-  @pragma('vm:entry-point')
-  void foofoo1() {}
-}
-
-main() {
-  new A();
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart b/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart
deleted file mode 100644
index c3a1e7e..0000000
--- a/runtime/tests/vm/dart/bytecode_with_ast_in_aot_test_body2.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test case for bytecode_with_ast_in_aot_test.dart.
-// Contains 2 entry points.
-
-import 'package:expect/expect.dart';
-
-class A {
-  // Make sure obfuscation prohibitions metadata is generated.
-  @pragma('vm:entry-point')
-  void foofoo1() {}
-
-  // One more entry for obfuscation prohibitions metadata,
-  // raises the chances that subsequent bytecode metadata is misaligned.
-  @pragma('vm:entry-point')
-  void foofoo2() {}
-}
-
-main() {
-  new A();
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart/causal_stacks/utils.dart b/runtime/tests/vm/dart/causal_stacks/utils.dart
index 4a56ae7..0b14b5c 100644
--- a/runtime/tests/vm/dart/causal_stacks/utils.dart
+++ b/runtime/tests/vm/dart/causal_stacks/utils.dart
@@ -187,7 +187,7 @@
   final decodeTrace = frames.first.startsWith('Warning:');
   if (decodeTrace) {
     Expect.isNotNull(debugInfoFilename);
-    final dwarf = Dwarf.fromFile(debugInfoFilename!);
+    final dwarf = Dwarf.fromFile(debugInfoFilename!)!;
     frames = await Stream.fromIterable(original)
         .transform(DwarfStackTraceDecoder(dwarf))
         .where(_lineRE.hasMatch)
diff --git a/runtime/tests/vm/dart/minimal_kernel_bytecode_test.dart b/runtime/tests/vm/dart/minimal_kernel_bytecode_test.dart
deleted file mode 100644
index 417f129..0000000
--- a/runtime/tests/vm/dart/minimal_kernel_bytecode_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=minimal_kernel_script.dart
-
-// Tests that dill file produced with --minimal-kernel --gen-bytecode
-// options works as expected.
-
-import 'minimal_kernel_test.dart' as test;
-
-main() async {
-  await test.compileAndRunMinimalDillTest(['--gen-bytecode']);
-}
diff --git a/runtime/tests/vm/dart/regress43666_test.dart b/runtime/tests/vm/dart/regress43666_test.dart
new file mode 100644
index 0000000..49bb218
--- /dev/null
+++ b/runtime/tests/vm/dart/regress43666_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  void bar() {}
+}
+
+void main(List<String> arguments) {
+  dynamic exception = null;
+  try {
+    final typeObject = Foo as dynamic;
+    print(typeObject.bar);
+  } catch (e) {
+    exception = e;
+  }
+  Expect.isNotNull(exception);
+  Expect.isTrue(exception is NoSuchMethodError);
+  // The NoSuchMethodError.toString() in the regression caused a crash.
+  Expect.isTrue(exception.toString().contains('NoSuchMethodError'));
+}
diff --git a/runtime/tests/vm/dart/regress_42799_test.dart b/runtime/tests/vm/dart/regress_42799_test.dart
new file mode 100644
index 0000000..c091da7
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_42799_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that AOT compiler doesn't crash when constant folding 'is'
+// test for a value which is a result of unreachable code
+// (result of inlined call of a method which doesn't return).
+// Regression test for https://github.com/dart-lang/sdk/issues/42799.
+
+import "package:expect/expect.dart";
+
+@pragma('vm:prefer-inline')
+dynamic foo0(int par1) {
+  if (par1 >= 39) {
+    return <String>[];
+  }
+  if (par1 >= 37) {
+    return <int>[];
+  }
+  throw 'hi';
+}
+
+main() {
+  Expect.throws(() {
+    if (foo0(0) is List<int>) {
+      print('not reachable');
+    }
+  }, (e) => e == 'hi');
+}
diff --git a/runtime/tests/vm/dart/regress_43464_test.dart b/runtime/tests/vm/dart/regress_43464_test.dart
new file mode 100644
index 0000000..43a3c113
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_43464_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+abstract class B<T> {
+  dynamic foo(T a);
+}
+
+class C extends B<A> {
+  dynamic foo(A a) {
+    return () => a;
+  }
+}
+
+main() {
+  Expect.throws(() => (C().foo as dynamic)(1));
+}
diff --git a/runtime/tests/vm/dart/regress_43679_test.dart b/runtime/tests/vm/dart/regress_43679_test.dart
new file mode 100644
index 0000000..9738391
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_43679_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--deterministic --optimization_counter_threshold=80
+
+// Verifies that JIT compiler doesn't crash when typed data allocation is
+// used in unreachable LoadField(Array.length) due to polymorphic inlining.
+// Regression test for https://github.com/dart-lang/sdk/issues/43679.
+
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+
+main() {
+  List<List> lists = [];
+  for (int i = 0; i < 100; ++i) {
+    lists.add(Uint32List.fromList(List<int>.filled(0, 0)));
+    lists.add(Uint32List.fromList(Uint8List(3)));
+  }
+  for (int i = 0; i < lists.length; i += 2) {
+    Expect.equals(0, lists[i].length);
+    Expect.equals(3, lists[i + 1].length);
+  }
+}
diff --git a/runtime/tests/vm/dart/regress_43682_test.dart b/runtime/tests/vm/dart/regress_43682_test.dart
new file mode 100644
index 0000000..63ef705
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_43682_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--deterministic --optimization_counter_threshold=20
+
+// Verifies that SSA construction doesn't crash when handling a Phi
+// corresponding to an expression temp in case of OSR with non-empty
+// expression stack.
+// Regression test for https://github.com/dart-lang/sdk/issues/43682.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  List<Object> data;
+  Foo(this.data);
+}
+
+Map<String, Foo> foo(List<Object> objects) {
+  Map<String, Foo> map = {};
+  // OSR happens during '...objects' spread, and Foo instance is already
+  // allocated and remains on the stack during OSR.
+  // OSR Phi corresponding to that value is stored into 'foo' local and
+  // then loaded from it, but it doesn't correspond to 'foo' environment slot.
+  final foo = new Foo([...objects]);
+  map['hi'] = foo;
+  return map;
+}
+
+main() {
+  Expect.equals(30, foo(List.filled(30, Object()))['hi']!.data.length);
+}
diff --git a/runtime/tests/vm/dart/regress_big_regexp_test.dart b/runtime/tests/vm/dart/regress_big_regexp_test.dart
new file mode 100644
index 0000000..09a7aa4
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_big_regexp_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that RegExp compilation doesn't crash on a huge source string.
+
+import 'package:expect/expect.dart';
+
+void testBigRegExp(String source) {
+  try {
+    var re = new RegExp(source);
+    Expect.isTrue(re.hasMatch(source));
+  } catch (e) {
+    // May throw a compile-time error, but shouldn't crash.
+    Expect.isTrue(e.toString().contains('RegExp too big'));
+  }
+}
+
+main() {
+  testBigRegExp("a" * (0x10000 - 128));
+  testBigRegExp(
+      String.fromCharCodes(List.generate(0x10000 - 128, (x) => x + 128)));
+}
diff --git a/runtime/tests/vm/dart/send_instantiated_fun_test.dart b/runtime/tests/vm/dart/send_instantiated_fun_test.dart
new file mode 100644
index 0000000..ab58c88
--- /dev/null
+++ b/runtime/tests/vm/dart/send_instantiated_fun_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that partially instantiated generic function remains instantiated
+// after received via ReceivePort.
+
+import 'dart:isolate';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_minitest.dart';
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+class Dog {}
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+List<T> decodeFrom<T>(String s) {
+  return [];
+}
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+List<Dog> Function(String s) decodeFromDog = decodeFrom;
+
+void main() async {
+  final receivePort = ReceivePort();
+  receivePort.listen(expectAsync1((data) {
+    print("Received $data");
+    Expect.equals('$data',
+        "[Closure: (String) => List<Dog> from Function 'decodeFrom': static.]");
+    receivePort.close();
+  }));
+  print("Sending $decodeFromDog");
+  receivePort.sendPort.send(<dynamic>[decodeFromDog]);
+}
diff --git a/runtime/tests/vm/dart/sendandexit_test.dart b/runtime/tests/vm/dart/sendandexit_test.dart
index f1fb1db..58e02c6 100644
--- a/runtime/tests/vm/dart/sendandexit_test.dart
+++ b/runtime/tests/vm/dart/sendandexit_test.dart
@@ -25,83 +25,93 @@
 }
 
 verifyCantSendAnonymousClosure() async {
-  final result = await spawnWorker(doNothingWorker, () {});
-  Expect.equals(
-      "Invalid argument(s): Illegal argument in isolate message :"
-      " (object is a closure - Function '<anonymous closure>': static.)",
-      result.toString());
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, () {}),
+      (e) =>
+          e.toString() ==
+          'Invalid argument: "Illegal argument in isolate message : '
+              '(object is a closure - Function \'<anonymous closure>\': static.)"');
+  receivePort.close();
 }
 
 class NativeWrapperClass extends NativeFieldWrapperClass1 {}
 
 verifyCantSendNative() async {
-  final result = await spawnWorker(doNothingWorker, NativeWrapperClass());
-  Expect.isTrue(result.toString().startsWith("Invalid argument(s): "
-      "Illegal argument in isolate message : "
-      "(object extends NativeWrapper"));
-}
-
-verifyCantSendRegexp() async {
-  var receivePort = ReceivePort();
-  final result = await spawnWorker(doNothingWorker, receivePort);
-  Expect.equals(
-      "Invalid argument(s): Illegal argument in isolate message : "
-      "(object is a ReceivePort)",
-      result.toString());
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, NativeWrapperClass()),
+      (e) => e.toString().startsWith('Invalid argument: '
+          '"Illegal argument in isolate message : '
+          '(object extends NativeWrapper'));
   receivePort.close();
 }
 
-class Message {
-  SendPort sendPort;
-  Function closure;
+verifyCantSendReceivePort() async {
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, receivePort),
+      // closure is encountered first before we reach ReceivePort instance
+      (e) => e.toString().startsWith(
+          'Invalid argument: "Illegal argument in isolate message : '
+          '(object is a closure - Function \''));
+  receivePort.close();
+}
 
-  Message(this.sendPort, this.closure);
+verifyCantSendRegexp() async {
+  final receivePort = ReceivePort();
+  final regexp = RegExp("");
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, regexp),
+      (e) =>
+          e.toString() ==
+          'Invalid argument: '
+              '"Illegal argument in isolate message : (object is a RegExp)"');
+  receivePort.close();
 }
 
 add(a, b) => a + b;
 
-worker(Message message) async {
-  final port = new ReceivePort();
-  final inbox = new StreamIterator<dynamic>(port);
-  message.sendPort.send(message.closure(2, 3));
-  port.close();
+worker(SendPort sendPort) async {
+  sendAndExit(sendPort, add);
 }
 
 verifyCanSendStaticMethod() async {
   final port = ReceivePort();
   final inbox = StreamIterator<dynamic>(port);
-  final isolate = await Isolate.spawn(worker, Message(port.sendPort, add));
+  final isolate = await Isolate.spawn(worker, port.sendPort);
 
   await inbox.moveNext();
-  Expect.equals(inbox.current, 5);
+  Expect.equals(5, (inbox.current)(2, 3));
   port.close();
 }
 
 verifyExitMessageIsPostedLast() async {
   final port = ReceivePort();
   final inbox = new StreamIterator<dynamic>(port);
-  final isolate = await Isolate.spawn(worker, Message(port.sendPort, add),
-      onExit: port.sendPort);
+  final isolate =
+      await Isolate.spawn(worker, port.sendPort, onExit: port.sendPort);
 
   final receivedData = Completer<dynamic>();
   final isolateExited = Completer<bool>();
   port.listen((dynamic resultData) {
     if (receivedData.isCompleted) {
       Expect.equals(
-          resultData, null); // exit message comes after data is receivedData
+          null, resultData); // exit message comes after data is receivedData
       isolateExited.complete(true);
     } else {
       receivedData.complete(resultData);
     }
   });
-  Expect.equals(await isolateExited.future, true);
-  Expect.equals(await receivedData.future, 5);
+  Expect.equals(true, await isolateExited.future);
+  Expect.equals(5, (await receivedData.future)(2, 3));
   port.close();
 }
 
 main() async {
   await verifyCantSendAnonymousClosure();
   await verifyCantSendNative();
+  await verifyCantSendReceivePort();
   await verifyCantSendRegexp();
   await verifyCanSendStaticMethod();
   await verifyExitMessageIsPostedLast();
diff --git a/runtime/tests/vm/dart/snapshot_test_helper.dart b/runtime/tests/vm/dart/snapshot_test_helper.dart
index 00d1afe..1b578b9 100644
--- a/runtime/tests/vm/dart/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart/snapshot_test_helper.dart
@@ -188,22 +188,3 @@
     expectOutput("OK(Run)", runResult);
   });
 }
-
-Future<void> runAppJitBytecodeTest(Uri testScriptUri) async {
-  await withTempDir((String temp) async {
-    final snapshotPath = p.join(temp, 'app.jit');
-    final testPath = testScriptUri.toFilePath();
-
-    final trainingResult = await runDart('TRAINING RUN', [
-      '--enable_interpreter',
-      '--snapshot=$snapshotPath',
-      '--snapshot-kind=app-jit',
-      testPath,
-      '--train'
-    ]);
-    expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDart(
-        'RUN FROM SNAPSHOT', ['--enable_interpreter', snapshotPath]);
-    expectOutput("OK(Run)", runResult);
-  });
-}
diff --git a/runtime/tests/vm/dart/split_aot_kernel_generation2_test.dart b/runtime/tests/vm/dart/split_aot_kernel_generation2_test.dart
index 32b4f00..b54e3cb 100644
--- a/runtime/tests/vm/dart/split_aot_kernel_generation2_test.dart
+++ b/runtime/tests/vm/dart/split_aot_kernel_generation2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// OtherResources=../../../../tests/language/vm/regress_flutter_55345_test.dart
+// OtherResources=../../../../tests/language/mixin/regress_flutter_55345_test.dart
 
 // Runs regress_flutter_55345_test.dart using AOT kernel generation split into
 // 2 steps using '--from-dill' option.
@@ -14,5 +14,5 @@
 
 main() async {
   await runSplitAOTKernelGenerationTest(Platform.script.resolve(
-      '../../../../tests/language/vm/regress_flutter_55345_test.dart'));
+      '../../../../tests/language/mixin/regress_flutter_55345_test.dart'));
 }
diff --git a/runtime/tests/vm/dart/thread_priority_macos_test.dart b/runtime/tests/vm/dart/thread_priority_macos_test.dart
index b466eb0..b7c8280 100644
--- a/runtime/tests/vm/dart/thread_priority_macos_test.dart
+++ b/runtime/tests/vm/dart/thread_priority_macos_test.dart
@@ -29,7 +29,7 @@
 //  struct sched_param { int sched_priority; }
 class SchedParam extends Struct {
   @Int32()
-  int schedPriority;
+  external int schedPriority;
 }
 
 main(args) {
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
index 07a40c0..052ddda 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
@@ -112,8 +112,20 @@
 
     // Check that translating the DWARF stack trace (without internal frames)
     // matches the symbolic stack trace.
-    final dwarf = Dwarf.fromFile(scriptDwarfDebugInfo);
-    assert(dwarf != null);
+    final dwarf = Dwarf.fromFile(scriptDwarfDebugInfo)!;
+
+    // Check that build IDs match for traces.
+    Expect.isNotNull(dwarf.buildId);
+    print('Dwarf build ID: "${dwarf.buildId!}"');
+    final buildId1 = buildId(dwarfTrace1);
+    Expect.isFalse(buildId1.isEmpty);
+    print('Trace 1 build ID: "${buildId1}"');
+    Expect.equals(dwarf.buildId, buildId1);
+    final buildId2 = buildId(dwarfTrace2);
+    Expect.isFalse(buildId2.isEmpty);
+    print('Trace 2 build ID: "${buildId2}"');
+    Expect.equals(dwarf.buildId, buildId2);
+
     final translatedDwarfTrace1 = await Stream.fromIterable(dwarfTrace1)
         .transform(DwarfStackTraceDecoder(dwarf))
         .toList();
@@ -178,6 +190,17 @@
   });
 }
 
+final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
+String buildId(Iterable<String> lines) {
+  for (final line in lines) {
+    final match = _buildIdRE.firstMatch(line);
+    if (match != null) {
+      return match.group(1)!;
+    }
+  }
+  return '';
+}
+
 final _symbolicFrameRE = RegExp(r'^#\d+\s+');
 
 Iterable<String> onlySymbolicFrameLines(Iterable<String> lines) {
diff --git a/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart b/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
index 5ed1c3a..091087d 100644
--- a/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
+++ b/runtime/tests/vm/dart/use_save_debugging_info_flag_test.dart
@@ -114,20 +114,20 @@
     print("Original stack trace:");
     strippedTrace.forEach(print);
 
-    final debugDwarf = Dwarf.fromFile(scriptDebuggingInfo);
-    final wholeDwarf = Dwarf.fromFile(scriptWholeSnapshot);
+    final debugDwarf = Dwarf.fromFile(scriptDebuggingInfo)!;
+    final wholeDwarf = Dwarf.fromFile(scriptWholeSnapshot)!;
 
     final fromDebug = await Stream.fromIterable(strippedTrace)
         .transform(DwarfStackTraceDecoder(debugDwarf))
         .toList();
     print("\nStack trace converted using separate debugging info:");
-    print(fromDebug.join());
+    print(fromDebug.join('\n'));
 
     final fromWhole = await Stream.fromIterable(strippedTrace)
         .transform(DwarfStackTraceDecoder(wholeDwarf))
         .toList();
     print("\nStack trace converted using unstripped ELF file:");
-    print(fromWhole.join());
+    print(fromWhole.join('\n'));
 
     Expect.deepEquals(fromDebug, fromWhole);
   });
diff --git a/runtime/tests/vm/dart/write_barrier_register_clobber_test.dart b/runtime/tests/vm/dart/write_barrier_register_clobber_test.dart
new file mode 100644
index 0000000..ceff211
--- /dev/null
+++ b/runtime/tests/vm/dart/write_barrier_register_clobber_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test attempts to verify that write barrier slow path does not
+// clobber any live values.
+
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+class Old {
+  var f;
+  Old(this.f);
+}
+
+@pragma('vm:never-inline')
+int crashy(int v, List<Old> oldies) {
+  // This test attempts to create a lot of live values which would live across
+  // write barrier invocation so that when write-barrier calls runtime and
+  // clobbers a register this is detected.
+  var young = Object();
+  var len = oldies.length;
+  var i = 0;
+  var v00 = v + 0;
+  var v01 = v + 1;
+  var v02 = v + 2;
+  var v03 = v + 3;
+  var v04 = v + 4;
+  var v05 = v + 5;
+  var v06 = v + 6;
+  var v07 = v + 7;
+  var v08 = v + 8;
+  var v09 = v + 9;
+  var v10 = v + 10;
+  var v11 = v + 11;
+  var v12 = v + 12;
+  var v13 = v + 13;
+  var v14 = v + 14;
+  var v15 = v + 15;
+  var v16 = v + 16;
+  var v17 = v + 17;
+  var v18 = v + 18;
+  var v19 = v + 19;
+  while (i < len) {
+    // Eventually this will overflow store buffer and call runtime to acquire
+    // a new block.
+    oldies[i++].f = young;
+  }
+  return v00 +
+      v01 +
+      v02 +
+      v03 +
+      v04 +
+      v05 +
+      v06 +
+      v07 +
+      v08 +
+      v09 +
+      v10 +
+      v11 +
+      v12 +
+      v13 +
+      v14 +
+      v15 +
+      v16 +
+      v17 +
+      v18 +
+      v19;
+}
+
+void main(List<String> args) {
+  final init = args.contains('impossible') ? 1 : 0;
+  final oldies = List<Old>.generate(100000, (i) => Old(""));
+  VMInternalsForTesting.collectAllGarbage();
+  VMInternalsForTesting.collectAllGarbage();
+  Expect.equals(crashy(init, oldies), 190);
+  for (var o in oldies) {
+    Expect.isTrue(o.f is! String);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/appjit_bytecode_simple_test.dart b/runtime/tests/vm/dart_2/appjit_bytecode_simple_test.dart
deleted file mode 100644
index d936339..0000000
--- a/runtime/tests/vm/dart_2/appjit_bytecode_simple_test.dart
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=appjit_bytecode_simple_test_body.dart
-
-// Verify that app-jit snapshot contains dependencies between classes and CHA
-// optimized code.
-
-import 'dart:async';
-import 'dart:io' show Platform;
-
-import 'snapshot_test_helper.dart';
-
-Future<void> main() => runAppJitBytecodeTest(
-    Platform.script.resolve('appjit_bytecode_simple_test_body.dart'));
diff --git a/runtime/tests/vm/dart_2/appjit_bytecode_simple_test_body.dart b/runtime/tests/vm/dart_2/appjit_bytecode_simple_test_body.dart
deleted file mode 100644
index a882e9a..0000000
--- a/runtime/tests/vm/dart_2/appjit_bytecode_simple_test_body.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-void main(List<String> args) {
-  final isTraining = args.contains("--train");
-  print(isTraining ? 'OK(Trained)' : 'OK(Run)');
-}
diff --git a/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test.dart b/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test.dart
deleted file mode 100644
index 72f6b76..0000000
--- a/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=bytecode_and_ast_mix_test_body.dart
-
-// Tests the mix of kernel AST (test) and bytecode dill files (core libraries).
-// Verifies that kernel AST can reference a not yet loaded bytecode class
-// through a constant in metadata.
-
-import 'dart:io' show Platform;
-
-import 'package:path/path.dart' as path;
-import 'snapshot_test_helper.dart';
-
-main() async {
-  final testScriptUri =
-      Platform.script.resolve('bytecode_and_ast_mix_test_body.dart');
-  await withTempDir((String temp) async {
-    final dillPath = path.join(temp, 'ast.dill');
-    final testPath = testScriptUri.toFilePath();
-
-    final buildResult = await runGenKernel('BUILD AST DILL FILE', [
-      '--no-gen-bytecode',
-      '--output=$dillPath',
-      testPath,
-    ]);
-    print(buildResult);
-    final runResult = await runDart('RUN FROM AST DILL FILE', [dillPath]);
-    expectOutput("OK", runResult);
-  });
-}
diff --git a/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test_body.dart b/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test_body.dart
deleted file mode 100644
index dac3c07..0000000
--- a/runtime/tests/vm/dart_2/bytecode_and_ast_mix_test_body.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:mirrors';
-import 'package:expect/expect.dart';
-
-class A {
-  void foo() {}
-}
-
-class B extends A {
-  @override
-  void foo() {}
-}
-
-main() {
-  ClassMirror classB = reflectClass(B);
-  MethodMirror foo = classB.declarations[#foo];
-  final annotation = foo.metadata[0].reflectee;
-  Expect.isTrue(annotation.toString().contains('_Override'));
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test.dart b/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test.dart
deleted file mode 100644
index a44f8f2..0000000
--- a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=bytecode_with_ast_in_aot_test_body1.dart
-// OtherResources=bytecode_with_ast_in_aot_test_body2.dart
-
-// Tests that gen_kernel is able to produce dill file with both bytecode
-// and AST in AOT mode, and gen_snapshot is able to consume them.
-// Two test cases are only different in number of entry points, so
-// obfuscation prohibitions metadata has different size, causing
-// different alignment of bytecode metadata.
-
-import 'dart:io' show Platform;
-
-import 'package:path/path.dart' as path;
-import 'snapshot_test_helper.dart';
-
-testAOTOnBytecodeWithAST(String temp, String source) async {
-  final sourcePath = Platform.script.resolve(source).toFilePath();
-  final dillPath = path.join(temp, '${source}.dill');
-  final snapshotPath = path.join(temp, '${source}.so');
-
-  final genKernelResult = await runGenKernel('BUILD DILL FILE', [
-    '--aot',
-    '--gen-bytecode',
-    '--no-drop-ast',
-    '--output=$dillPath',
-    sourcePath,
-  ]);
-  print(genKernelResult);
-  final genSnapshotResult = await runGenSnapshot('GENERATE SNAPSHOT', [
-    '--use-bytecode-compiler',
-    '--snapshot-kind=app-aot-elf',
-    '--elf=$snapshotPath',
-    dillPath,
-  ]);
-  print(genSnapshotResult);
-  final runResult =
-      await runBinary('RUN SNAPSHOT', dartPrecompiledRuntime, [snapshotPath]);
-  expectOutput("OK", runResult);
-}
-
-main() async {
-  await withTempDir((String temp) async {
-    await testAOTOnBytecodeWithAST(
-        temp, 'bytecode_with_ast_in_aot_test_body1.dart');
-    await testAOTOnBytecodeWithAST(
-        temp, 'bytecode_with_ast_in_aot_test_body2.dart');
-  });
-}
diff --git a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body1.dart b/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body1.dart
deleted file mode 100644
index 18ae42b..0000000
--- a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body1.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test case for bytecode_with_ast_in_aot_test.dart.
-// Contains 1 entry point.
-
-import 'package:expect/expect.dart';
-
-class A {
-  // Make sure obfuscation prohibitions metadata is generated.
-  @pragma('vm:entry-point')
-  void foofoo1() {}
-}
-
-main() {
-  new A();
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body2.dart b/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body2.dart
deleted file mode 100644
index c3a1e7e..0000000
--- a/runtime/tests/vm/dart_2/bytecode_with_ast_in_aot_test_body2.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test case for bytecode_with_ast_in_aot_test.dart.
-// Contains 2 entry points.
-
-import 'package:expect/expect.dart';
-
-class A {
-  // Make sure obfuscation prohibitions metadata is generated.
-  @pragma('vm:entry-point')
-  void foofoo1() {}
-
-  // One more entry for obfuscation prohibitions metadata,
-  // raises the chances that subsequent bytecode metadata is misaligned.
-  @pragma('vm:entry-point')
-  void foofoo2() {}
-}
-
-main() {
-  new A();
-  print('OK');
-}
diff --git a/runtime/tests/vm/dart_2/minimal_kernel_bytecode_test.dart b/runtime/tests/vm/dart_2/minimal_kernel_bytecode_test.dart
deleted file mode 100644
index 417f129..0000000
--- a/runtime/tests/vm/dart_2/minimal_kernel_bytecode_test.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// OtherResources=minimal_kernel_script.dart
-
-// Tests that dill file produced with --minimal-kernel --gen-bytecode
-// options works as expected.
-
-import 'minimal_kernel_test.dart' as test;
-
-main() async {
-  await test.compileAndRunMinimalDillTest(['--gen-bytecode']);
-}
diff --git a/runtime/tests/vm/dart_2/regress43666_test.dart b/runtime/tests/vm/dart_2/regress43666_test.dart
new file mode 100644
index 0000000..49bb218
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress43666_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  void bar() {}
+}
+
+void main(List<String> arguments) {
+  dynamic exception = null;
+  try {
+    final typeObject = Foo as dynamic;
+    print(typeObject.bar);
+  } catch (e) {
+    exception = e;
+  }
+  Expect.isNotNull(exception);
+  Expect.isTrue(exception is NoSuchMethodError);
+  // The NoSuchMethodError.toString() in the regression caused a crash.
+  Expect.isTrue(exception.toString().contains('NoSuchMethodError'));
+}
diff --git a/runtime/tests/vm/dart_2/regress_42799_test.dart b/runtime/tests/vm/dart_2/regress_42799_test.dart
new file mode 100644
index 0000000..c091da7
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_42799_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that AOT compiler doesn't crash when constant folding 'is'
+// test for a value which is a result of unreachable code
+// (result of inlined call of a method which doesn't return).
+// Regression test for https://github.com/dart-lang/sdk/issues/42799.
+
+import "package:expect/expect.dart";
+
+@pragma('vm:prefer-inline')
+dynamic foo0(int par1) {
+  if (par1 >= 39) {
+    return <String>[];
+  }
+  if (par1 >= 37) {
+    return <int>[];
+  }
+  throw 'hi';
+}
+
+main() {
+  Expect.throws(() {
+    if (foo0(0) is List<int>) {
+      print('not reachable');
+    }
+  }, (e) => e == 'hi');
+}
diff --git a/runtime/tests/vm/dart_2/regress_43464_test.dart b/runtime/tests/vm/dart_2/regress_43464_test.dart
new file mode 100644
index 0000000..43a3c113
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_43464_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+abstract class B<T> {
+  dynamic foo(T a);
+}
+
+class C extends B<A> {
+  dynamic foo(A a) {
+    return () => a;
+  }
+}
+
+main() {
+  Expect.throws(() => (C().foo as dynamic)(1));
+}
diff --git a/runtime/tests/vm/dart_2/regress_43679_test.dart b/runtime/tests/vm/dart_2/regress_43679_test.dart
new file mode 100644
index 0000000..9738391
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_43679_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--deterministic --optimization_counter_threshold=80
+
+// Verifies that JIT compiler doesn't crash when typed data allocation is
+// used in unreachable LoadField(Array.length) due to polymorphic inlining.
+// Regression test for https://github.com/dart-lang/sdk/issues/43679.
+
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+
+main() {
+  List<List> lists = [];
+  for (int i = 0; i < 100; ++i) {
+    lists.add(Uint32List.fromList(List<int>.filled(0, 0)));
+    lists.add(Uint32List.fromList(Uint8List(3)));
+  }
+  for (int i = 0; i < lists.length; i += 2) {
+    Expect.equals(0, lists[i].length);
+    Expect.equals(3, lists[i + 1].length);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/regress_43682_test.dart b/runtime/tests/vm/dart_2/regress_43682_test.dart
new file mode 100644
index 0000000..15924b1
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_43682_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--deterministic --optimization_counter_threshold=20
+
+// Verifies that SSA construction doesn't crash when handling a Phi
+// corresponding to an expression temp in case of OSR with non-empty
+// expression stack.
+// Regression test for https://github.com/dart-lang/sdk/issues/43682.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  List<Object> data;
+  Foo(this.data);
+}
+
+Map<String, Foo> foo(List<Object> objects) {
+  Map<String, Foo> map = {};
+  // OSR happens during '...objects' spread, and Foo instance is already
+  // allocated and remains on the stack during OSR.
+  // OSR Phi corresponding to that value is stored into 'foo' local and
+  // then loaded from it, but it doesn't correspond to 'foo' environment slot.
+  final foo = new Foo([...objects]);
+  map['hi'] = foo;
+  return map;
+}
+
+main() {
+  Expect.equals(30, foo(List.filled(30, Object()))['hi'].data.length);
+}
diff --git a/runtime/tests/vm/dart_2/regress_big_regexp_test.dart b/runtime/tests/vm/dart_2/regress_big_regexp_test.dart
new file mode 100644
index 0000000..13e2689
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_big_regexp_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that RegExp compilation doesn't crash on a huge source string.
+
+import 'package:expect/expect.dart';
+
+void testBigRegExp(String source) {
+  try {
+    var re = new RegExp(source);
+    Expect.isTrue(re.hasMatch(source));
+  } catch (e) {
+    // May throw an error containing
+    Expect.isTrue(e.toString().contains('RegExp too big'));
+  }
+}
+
+main() {
+  testBigRegExp("a" * (0x10000 - 128));
+  testBigRegExp(
+      String.fromCharCodes(List.generate(0x10000 - 128, (x) => x + 128)));
+}
diff --git a/runtime/tests/vm/dart_2/send_instantiated_fun_test.dart b/runtime/tests/vm/dart_2/send_instantiated_fun_test.dart
new file mode 100644
index 0000000..751e8f8
--- /dev/null
+++ b/runtime/tests/vm/dart_2/send_instantiated_fun_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify that partially instantiated generic function remains instantiated
+// after received via ReceivePort.
+
+import 'dart:isolate';
+import 'package:expect/expect.dart';
+import 'package:async_helper/async_minitest.dart';
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+class Dog {}
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+List<T> decodeFrom<T>(String s) {
+  return List();
+}
+
+// Prevent obfuscation.
+@pragma('vm:entry-point')
+List<Dog> Function(String s) decodeFromDog = decodeFrom;
+
+void main() async {
+  final receivePort = ReceivePort();
+  receivePort.listen(expectAsync1((data) {
+    print("Received $data");
+    Expect.equals('$data',
+        "[Closure: (String) => List<Dog> from Function 'decodeFrom': static.]");
+    receivePort.close();
+  }));
+  print("Sending $decodeFromDog");
+  receivePort.sendPort.send(<dynamic>[decodeFromDog]);
+}
diff --git a/runtime/tests/vm/dart_2/sendandexit_test.dart b/runtime/tests/vm/dart_2/sendandexit_test.dart
index f1fb1db..58e02c6 100644
--- a/runtime/tests/vm/dart_2/sendandexit_test.dart
+++ b/runtime/tests/vm/dart_2/sendandexit_test.dart
@@ -25,83 +25,93 @@
 }
 
 verifyCantSendAnonymousClosure() async {
-  final result = await spawnWorker(doNothingWorker, () {});
-  Expect.equals(
-      "Invalid argument(s): Illegal argument in isolate message :"
-      " (object is a closure - Function '<anonymous closure>': static.)",
-      result.toString());
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, () {}),
+      (e) =>
+          e.toString() ==
+          'Invalid argument: "Illegal argument in isolate message : '
+              '(object is a closure - Function \'<anonymous closure>\': static.)"');
+  receivePort.close();
 }
 
 class NativeWrapperClass extends NativeFieldWrapperClass1 {}
 
 verifyCantSendNative() async {
-  final result = await spawnWorker(doNothingWorker, NativeWrapperClass());
-  Expect.isTrue(result.toString().startsWith("Invalid argument(s): "
-      "Illegal argument in isolate message : "
-      "(object extends NativeWrapper"));
-}
-
-verifyCantSendRegexp() async {
-  var receivePort = ReceivePort();
-  final result = await spawnWorker(doNothingWorker, receivePort);
-  Expect.equals(
-      "Invalid argument(s): Illegal argument in isolate message : "
-      "(object is a ReceivePort)",
-      result.toString());
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, NativeWrapperClass()),
+      (e) => e.toString().startsWith('Invalid argument: '
+          '"Illegal argument in isolate message : '
+          '(object extends NativeWrapper'));
   receivePort.close();
 }
 
-class Message {
-  SendPort sendPort;
-  Function closure;
+verifyCantSendReceivePort() async {
+  final receivePort = ReceivePort();
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, receivePort),
+      // closure is encountered first before we reach ReceivePort instance
+      (e) => e.toString().startsWith(
+          'Invalid argument: "Illegal argument in isolate message : '
+          '(object is a closure - Function \''));
+  receivePort.close();
+}
 
-  Message(this.sendPort, this.closure);
+verifyCantSendRegexp() async {
+  final receivePort = ReceivePort();
+  final regexp = RegExp("");
+  Expect.throws(
+      () => sendAndExit(receivePort.sendPort, regexp),
+      (e) =>
+          e.toString() ==
+          'Invalid argument: '
+              '"Illegal argument in isolate message : (object is a RegExp)"');
+  receivePort.close();
 }
 
 add(a, b) => a + b;
 
-worker(Message message) async {
-  final port = new ReceivePort();
-  final inbox = new StreamIterator<dynamic>(port);
-  message.sendPort.send(message.closure(2, 3));
-  port.close();
+worker(SendPort sendPort) async {
+  sendAndExit(sendPort, add);
 }
 
 verifyCanSendStaticMethod() async {
   final port = ReceivePort();
   final inbox = StreamIterator<dynamic>(port);
-  final isolate = await Isolate.spawn(worker, Message(port.sendPort, add));
+  final isolate = await Isolate.spawn(worker, port.sendPort);
 
   await inbox.moveNext();
-  Expect.equals(inbox.current, 5);
+  Expect.equals(5, (inbox.current)(2, 3));
   port.close();
 }
 
 verifyExitMessageIsPostedLast() async {
   final port = ReceivePort();
   final inbox = new StreamIterator<dynamic>(port);
-  final isolate = await Isolate.spawn(worker, Message(port.sendPort, add),
-      onExit: port.sendPort);
+  final isolate =
+      await Isolate.spawn(worker, port.sendPort, onExit: port.sendPort);
 
   final receivedData = Completer<dynamic>();
   final isolateExited = Completer<bool>();
   port.listen((dynamic resultData) {
     if (receivedData.isCompleted) {
       Expect.equals(
-          resultData, null); // exit message comes after data is receivedData
+          null, resultData); // exit message comes after data is receivedData
       isolateExited.complete(true);
     } else {
       receivedData.complete(resultData);
     }
   });
-  Expect.equals(await isolateExited.future, true);
-  Expect.equals(await receivedData.future, 5);
+  Expect.equals(true, await isolateExited.future);
+  Expect.equals(5, (await receivedData.future)(2, 3));
   port.close();
 }
 
 main() async {
   await verifyCantSendAnonymousClosure();
   await verifyCantSendNative();
+  await verifyCantSendReceivePort();
   await verifyCantSendRegexp();
   await verifyCanSendStaticMethod();
   await verifyExitMessageIsPostedLast();
diff --git a/runtime/tests/vm/dart_2/snapshot_test_helper.dart b/runtime/tests/vm/dart_2/snapshot_test_helper.dart
index 56472f1..eef877f 100644
--- a/runtime/tests/vm/dart_2/snapshot_test_helper.dart
+++ b/runtime/tests/vm/dart_2/snapshot_test_helper.dart
@@ -188,22 +188,3 @@
     expectOutput("OK(Run)", runResult);
   });
 }
-
-Future<void> runAppJitBytecodeTest(Uri testScriptUri) async {
-  await withTempDir((String temp) async {
-    final snapshotPath = p.join(temp, 'app.jit');
-    final testPath = testScriptUri.toFilePath();
-
-    final trainingResult = await runDart('TRAINING RUN', [
-      '--enable_interpreter',
-      '--snapshot=$snapshotPath',
-      '--snapshot-kind=app-jit',
-      testPath,
-      '--train'
-    ]);
-    expectOutput("OK(Trained)", trainingResult);
-    final runResult = await runDart(
-        'RUN FROM SNAPSHOT', ['--enable_interpreter', snapshotPath]);
-    expectOutput("OK(Run)", runResult);
-  });
-}
diff --git a/runtime/tests/vm/dart_2/split_aot_kernel_generation2_test.dart b/runtime/tests/vm/dart_2/split_aot_kernel_generation2_test.dart
index da7925a..5d49f2c 100644
--- a/runtime/tests/vm/dart_2/split_aot_kernel_generation2_test.dart
+++ b/runtime/tests/vm/dart_2/split_aot_kernel_generation2_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// OtherResources=../../../../tests/language_2/vm/regress_flutter_55345_test.dart
+// OtherResources=../../../../tests/language_2/mixin/regress_flutter_55345_test.dart
 
 // Runs regress_flutter_55345_test.dart using AOT kernel generation split into
 // 2 steps using '--from-dill' option.
@@ -14,5 +14,5 @@
 
 main() async {
   await runSplitAOTKernelGenerationTest(Platform.script.resolve(
-      '../../../../tests/language_2/vm/regress_flutter_55345_test.dart'));
+      '../../../../tests/language_2/mixin/regress_flutter_55345_test.dart'));
 }
diff --git a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
index 40aa94a..967c027 100644
--- a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
@@ -113,7 +113,20 @@
     // Check that translating the DWARF stack trace (without internal frames)
     // matches the symbolic stack trace.
     final dwarf = Dwarf.fromFile(scriptDwarfDebugInfo);
-    assert(dwarf != null);
+    Expect.isNotNull(dwarf);
+
+    // Check that build IDs match for traces.
+    Expect.isNotNull(dwarf.buildId);
+    print('Dwarf build ID: "${dwarf.buildId}"');
+    final buildId1 = buildId(dwarfTrace1);
+    Expect.isFalse(buildId1.isEmpty);
+    print('Trace 1 build ID: "${buildId1}"');
+    Expect.equals(dwarf.buildId, buildId1);
+    final buildId2 = buildId(dwarfTrace2);
+    Expect.isFalse(buildId2.isEmpty);
+    print('Trace 2 build ID: "${buildId2}"');
+    Expect.equals(dwarf.buildId, buildId2);
+
     final translatedDwarfTrace1 = await Stream.fromIterable(dwarfTrace1)
         .transform(DwarfStackTraceDecoder(dwarf))
         .toList();
@@ -178,6 +191,17 @@
   });
 }
 
+final _buildIdRE = RegExp(r"build_id: '([a-f\d]+)'");
+String buildId(Iterable<String> lines) {
+  for (final line in lines) {
+    final match = _buildIdRE.firstMatch(line);
+    if (match != null) {
+      return match.group(1);
+    }
+  }
+  return '';
+}
+
 final _symbolicFrameRE = RegExp(r'^#\d+\s+');
 
 Iterable<String> onlySymbolicFrameLines(Iterable<String> lines) {
diff --git a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart b/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
index e098c5a..1a21971 100644
--- a/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_save_debugging_info_flag_test.dart
@@ -121,13 +121,13 @@
         .transform(DwarfStackTraceDecoder(debugDwarf))
         .toList();
     print("\nStack trace converted using separate debugging info:");
-    print(fromDebug.join());
+    print(fromDebug.join('\n'));
 
     final fromWhole = await Stream.fromIterable(strippedTrace)
         .transform(DwarfStackTraceDecoder(wholeDwarf))
         .toList();
     print("\nStack trace converted using unstripped ELF file:");
-    print(fromWhole.join());
+    print(fromWhole.join('\n'));
 
     Expect.deepEquals(fromDebug, fromWhole);
   });
diff --git a/runtime/tests/vm/dart_2/write_barrier_register_clobber_test.dart b/runtime/tests/vm/dart_2/write_barrier_register_clobber_test.dart
new file mode 100644
index 0000000..ceff211
--- /dev/null
+++ b/runtime/tests/vm/dart_2/write_barrier_register_clobber_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test attempts to verify that write barrier slow path does not
+// clobber any live values.
+
+import 'dart:_internal' show VMInternalsForTesting;
+
+import 'package:expect/expect.dart';
+
+class Old {
+  var f;
+  Old(this.f);
+}
+
+@pragma('vm:never-inline')
+int crashy(int v, List<Old> oldies) {
+  // This test attempts to create a lot of live values which would live across
+  // write barrier invocation so that when write-barrier calls runtime and
+  // clobbers a register this is detected.
+  var young = Object();
+  var len = oldies.length;
+  var i = 0;
+  var v00 = v + 0;
+  var v01 = v + 1;
+  var v02 = v + 2;
+  var v03 = v + 3;
+  var v04 = v + 4;
+  var v05 = v + 5;
+  var v06 = v + 6;
+  var v07 = v + 7;
+  var v08 = v + 8;
+  var v09 = v + 9;
+  var v10 = v + 10;
+  var v11 = v + 11;
+  var v12 = v + 12;
+  var v13 = v + 13;
+  var v14 = v + 14;
+  var v15 = v + 15;
+  var v16 = v + 16;
+  var v17 = v + 17;
+  var v18 = v + 18;
+  var v19 = v + 19;
+  while (i < len) {
+    // Eventually this will overflow store buffer and call runtime to acquire
+    // a new block.
+    oldies[i++].f = young;
+  }
+  return v00 +
+      v01 +
+      v02 +
+      v03 +
+      v04 +
+      v05 +
+      v06 +
+      v07 +
+      v08 +
+      v09 +
+      v10 +
+      v11 +
+      v12 +
+      v13 +
+      v14 +
+      v15 +
+      v16 +
+      v17 +
+      v18 +
+      v19;
+}
+
+void main(List<String> args) {
+  final init = args.contains('impossible') ? 1 : 0;
+  final oldies = List<Old>.generate(100000, (i) => Old(""));
+  VMInternalsForTesting.collectAllGarbage();
+  VMInternalsForTesting.collectAllGarbage();
+  Expect.equals(crashy(init, oldies), 190);
+  for (var o in oldies) {
+    Expect.isTrue(o.f is! String);
+  }
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 7f379ab..2d7c568 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -14,7 +14,6 @@
 dart/data_uri_import_test/none: SkipByDesign
 dart/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
 dart/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
-dart/minimal_kernel_bytecode_test: Pass, Slow # Spawns several subprocesses
 dart/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
 dart/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
 dart/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -24,7 +23,6 @@
 dart_2/data_uri_import_test/none: SkipByDesign
 dart_2/emit_aot_size_info_flag_test: Pass, Slow # Spawns several subprocesses
 dart_2/isolates/*: Pass, Slow # Tests use many isolates and take a longer time.
-dart_2/minimal_kernel_bytecode_test: Pass, Slow # Spawns several subprocesses
 dart_2/minimal_kernel_test: Pass, Slow # Spawns several subprocesses
 dart_2/null_safety_autodetection_in_kernel_compiler_test: Pass, Slow # Spawns several subprocesses
 dart_2/slow_path_shared_stub_test: Pass, Slow # Uses --shared-slow-path-triggers-gc flag.
@@ -50,12 +48,10 @@
 cc/*: Skip # Many tests want see unoptimized code running
 dart/appjit*: SkipByDesign # Test needs to a particular opt-counter value
 dart/kernel_determinism_test: SkipSlow
-dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 dart_2/appjit*: SkipByDesign # Test needs to a particular opt-counter value
 dart_2/kernel_determinism_test: SkipSlow
-dart_2/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow with optimization_counter_threshold
 
@@ -67,25 +63,31 @@
 dart_2/regress_40462_test: SkipSlow
 dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
 
-[ $builder_tag == vm_nnbd ]
-dart_2/*: SkipByDesign # Legacy tests are not supposed to run on NNBD bots.
-
-[ $builder_tag != vm_nnbd ]
-dart/*: SkipByDesign # Migrated tests are not supposed to run on non-NNBD bots.
-
 [ $compiler == app_jitk ]
 dart/redirection_type_shuffling_test/none: RuntimeError
 dart/snapshot_version_test: RuntimeError
 dart_2/redirection_type_shuffling_test/none: RuntimeError
 dart_2/snapshot_version_test: RuntimeError
 
-[ $compiler != dartk ]
-dart/b162922506_test: SkipByDesign # Only run in JIT
-dart_2/b162922506_test: SkipByDesign # Only run in JIT
+[ $compiler == dartk ]
+cc/DartAPI_New: Fail # Issue #33041
+cc/IsolateReload_LibraryLookup: Fail, Crash # Issue 32190
+dart/redirection_type_shuffling_test/00: RuntimeError, Pass
+dart/redirection_type_shuffling_test/none: RuntimeError
+dart_2/redirection_type_shuffling_test/00: RuntimeError, Pass
+dart_2/redirection_type_shuffling_test/none: RuntimeError
 
-[ $compiler == dartkb ]
-dart/generic_field_invocation_test: SkipByDesign # KBC interpreters do not support --no_lazy_dispatchers
-dart_2/generic_field_invocation_test: SkipByDesign # KBC interpreters do not support --no_lazy_dispatchers
+[ $compiler != dartk ]
+cc/IsolateReload_KernelIncrementalCompile: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileAppAndLib: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileExpression: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileGenerics: SkipByDesign
+cc/Mixin_PrivateSuperResolution: Skip
+cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
+dart/b162922506_test: SkipByDesign # Only run in JIT
+dart/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
+dart_2/b162922506_test: SkipByDesign # Only run in JIT
+dart_2/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
 
 [ $compiler == dartkp ]
 dart/causal_stacks/async_throws_stack_no_causal_non_symbolic_test: SkipByDesign # --no-lazy... does nothing on precompiler.
@@ -117,13 +119,12 @@
 cc/VerifyImplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
 dart/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 dart/b162922506_test: SkipSlow # Generates very large input file
-dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in debug mode
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
 dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
+dart/type_casts_with_null_safety_autodetection_test: Pass, Slow # Very slow in debug mode, uses --optimization-counter-threshold=10
 dart_2/appjit_cha_deopt_test: Pass, Slow # Quite slow in debug mode, uses --optimization-counter-threshold=100
 dart_2/b162922506_test: SkipSlow # Generates very large input file
-dart_2/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in debug mode
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in debug mode
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in debug mode
 dart_2/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
@@ -135,6 +136,9 @@
 dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
 dart_2/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
 
+[ $nnbd == legacy ]
+dart/*: SkipByDesign # Migrated tests are not supposed to run on non-NNBD bots.
+
 [ $system == android ]
 dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
@@ -157,16 +161,14 @@
 cc/GenKernelKernelLoadKernel: Skip # Issue 34542.
 cc/GenKernelKernelMaxRSS: Skip # Issue 34393.
 cc/GenKernelKernelReadAllBytecode: Skip # Issue 34393.
-dart/appjit_bytecode_simple_test: Skip # Issue 34393.
 dart/disassemble_determinism_test: Slow, Pass # Times out on slower bots.
-dart_2/appjit_bytecode_simple_test: Skip # Issue 34393.
 dart_2/disassemble_determinism_test: Slow, Pass # Times out on slower bots.
 
 [ $arch == ia32 && $mode == debug && $system == windows ]
 dart/transferable_test: Skip # This is performance test and somehow debug win ia32 bot's performance is unpredictable
 dart_2/transferable_test: Skip # This is performance test and somehow debug win ia32 bot's performance is unpredictable
 
-[ $arch != simarm && $arch != simarm64 && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch != simarm && $arch != simarm64 && $compiler == dartk && $hot_reload ]
 dart/data_uri_import_test/base64: Crash
 dart/data_uri_import_test/nocharset: Crash
 dart/data_uri_import_test/nomime: Crash
@@ -192,74 +194,19 @@
 dart_2/optimized_stacktrace_line_test: SkipByDesign # Looks for filenames in stacktrace output
 dart_2/regress_37382_test: SkipByDesign # Matches the type arguments names
 
-[ $compiler == dartk && $mode == product && $runtime == vm ]
-cc/CorelibIsolateStartup: Timeout, Pass
-
-[ $compiler != dartk && $compiler != dartkb ]
-cc/IsolateReload_KernelIncrementalCompile: SkipByDesign
-cc/IsolateReload_KernelIncrementalCompileAppAndLib: SkipByDesign
-cc/IsolateReload_KernelIncrementalCompileExpression: SkipByDesign
-cc/IsolateReload_KernelIncrementalCompileGenerics: SkipByDesign
-cc/Mixin_PrivateSuperResolution: Skip
-cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
-dart/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
-dart_2/entrypoints/jit/*: SkipByDesign # These tests should only run on JIT.
-
-[ $compiler != dartk && $compiler != dartkb && $compiler != none ]
-dart/appjit*: SkipByDesign # Test needs to run from source
-dart/bytecode_and_ast_mix_test: SkipByDesign # Test needs to run from source
-dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
-dart/minimal_kernel_bytecode_test: SkipByDesign # Test needs to run from source
-dart/minimal_kernel_test: SkipByDesign # Test needs to run from source
-dart/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
-dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
-dart/type_casts_with_null_safety_autodetection_test: SkipByDesign # Test needs to run from source
-dart_2/appjit*: SkipByDesign # Test needs to run from source
-dart_2/bytecode_and_ast_mix_test: SkipByDesign # Test needs to run from source
-dart_2/kernel_determinism_test: SkipByDesign # Test needs to run from source
-dart_2/minimal_kernel_bytecode_test: SkipByDesign # Test needs to run from source
-dart_2/minimal_kernel_test: SkipByDesign # Test needs to run from source
-dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
-dart_2/snapshot_depfile_test: SkipByDesign # Test needs to run from source
-
-[ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
-dart/redirection_type_shuffling_test: SkipByDesign # Includes dart:mirrors.
-dart/spawn_shutdown_test: SkipSlow
-dart_2/redirection_type_shuffling_test: SkipByDesign # Includes dart:mirrors.
-dart_2/spawn_shutdown_test: SkipSlow
-
-[ $mode == debug && $system == windows ]
-dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
-dart_2/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
-
 # Enabling of dartk for sim{arm,arm64} revelaed these test failures, which
 # are to be triaged.  Isolate tests are skipped on purpose due to the usage of
 # batch mode.
-[ $mode == debug && ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $mode == debug && ($arch == simarm || $arch == simarm64) ]
 cc/StackTraceMallocHookLengthTest: Fail # Please triage.
 
-[ $mode == product && $runtime == vm ]
-cc/DartAPI_IsolateSetCheckedMode: Fail, OK # Checked mode disabled in product mode.
-
-[ $mode == release && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $mode == product && $runtime == vm ]
 cc/CorelibIsolateStartup: Timeout, Pass
 
-[ $runtime == dart_precompiled && $minified ]
-dart/inline_stack_frame_test: Skip
-dart/optimized_stacktrace_line_test: Skip
-dart_2/inline_stack_frame_test: Skip
-dart_2/optimized_stacktrace_line_test: Skip
+[ $compiler == dartk && $mode == release && $runtime == vm ]
+cc/CorelibIsolateStartup: Timeout, Pass
 
-[ $runtime != dart_precompiled && $runtime != vm ]
-dart/*: SkipByDesign # VM specific tests
-dart/catch_entry_state: SkipByDesign
-dart_2/*: SkipByDesign # VM specific tests
-dart_2/catch_entry_state: SkipByDesign
-
-[ $runtime == vm && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
-cc/IsolateReload_LibraryLookup: Fail, Crash
-
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm ]
 cc/DartAPI_LoadLibrary: Fail, Crash # Issue 33048.
 cc/DebuggerAPI_BreakpointStubPatching: Fail
 cc/DebuggerAPI_GetClosureInfo: Fail
@@ -275,44 +222,83 @@
 dart/spawn_shutdown_test: SkipSlow
 dart_2/spawn_shutdown_test: SkipSlow
 
-[ $system != fuchsia && ($arch != x64 || $system != linux) ]
-cc/CodeExecutability: SkipByDesign # --dual-map-code not supported on non-Linux/Fuchsia
-
-[ $system == linux && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm && $system == macos ]
 cc/IsolateReload_LibraryLookup: Fail, Crash
 
-[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $system == linux ]
 cc/IsolateReload_LibraryLookup: Fail, Crash
 
-[ $checked && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $system == windows ]
+cc/IsolateReload_LibraryLookup: Fail, Crash
+
+[ $compiler == dartk && $checked ]
 dart/redirection_type_shuffling_test/00: Pass # Works in --checked mode but not in --strong mode.
 dart_2/redirection_type_shuffling_test/00: Pass # Works in --checked mode but not in --strong mode.
 
-[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
 dart/appjit*: SkipSlow # DFE too slow
 dart/b162922506_test: SkipSlow # Generates large input file
 dart/data_uri_spawn_test: Skip # Please triage.
-dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart/snapshot_version_test: RuntimeError # Please triage.
 dart_2/appjit*: SkipSlow # DFE too slow
 dart_2/b162922506_test: SkipSlow # Generates large input file
 dart_2/data_uri_spawn_test: Skip # Please triage.
-dart_2/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow on simulated architectures
 dart_2/snapshot_version_test: RuntimeError # Please triage.
 
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
 dart/data_uri_spawn_test: Skip # Timeout
 dart/kernel_determinism_test: SkipSlow
 dart_2/data_uri_spawn_test: Skip # Timeout
 dart_2/kernel_determinism_test: SkipSlow
 
-[ $arch == arm || $arch == arm64 || $builder_tag == crossword || $builder_tag == crossword_ast || $compiler != dartkp ]
-dart/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host).
-dart_2/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host).
+[ $compiler != dartk && $compiler != none ]
+dart/appjit*: SkipByDesign # Test needs to run from source
+dart/kernel_determinism_test: SkipByDesign # Test needs to run from source
+dart/minimal_kernel_test: SkipByDesign # Test needs to run from source
+dart/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
+dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
+dart/type_casts_with_null_safety_autodetection_test: SkipByDesign # Test needs to run from source
+dart_2/appjit*: SkipByDesign # Test needs to run from source
+dart_2/kernel_determinism_test: SkipByDesign # Test needs to run from source
+dart_2/minimal_kernel_test: SkipByDesign # Test needs to run from source
+dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
+dart_2/snapshot_depfile_test: SkipByDesign # Test needs to run from source
+
+[ $compiler == dartkp && ($runtime == dart_precompiled || $runtime == vm) ]
+dart/redirection_type_shuffling_test: SkipByDesign # Includes dart:mirrors.
+dart/spawn_shutdown_test: SkipSlow
+dart_2/redirection_type_shuffling_test: SkipByDesign # Includes dart:mirrors.
+dart_2/spawn_shutdown_test: SkipSlow
+
+[ $mode == debug && $system == windows ]
+dart/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
+dart_2/spawn_shutdown_test: Skip # Flaky crashes unable to start thread; likely low memory on the bot.
+
+[ $mode == product && $runtime == vm ]
+cc/DartAPI_IsolateSetCheckedMode: Fail, OK # Checked mode disabled in product mode.
+
+[ $runtime == dart_precompiled && $minified ]
+dart/inline_stack_frame_test: Skip
+dart/optimized_stacktrace_line_test: Skip
+dart_2/inline_stack_frame_test: Skip
+dart_2/optimized_stacktrace_line_test: Skip
+
+[ $runtime != dart_precompiled && $runtime != vm ]
+dart/*: SkipByDesign # VM specific tests
+dart/catch_entry_state: SkipByDesign
+dart_2/*: SkipByDesign # VM specific tests
+dart_2/catch_entry_state: SkipByDesign
+
+[ $system != fuchsia && ($arch != x64 || $system != linux) ]
+cc/CodeExecutability: SkipByDesign # --dual-map-code not supported on non-Linux/Fuchsia
+
+[ $arch == arm || $arch == arm64 || $builder_tag == crossword || $builder_tag == crossword_ast || $compiler != dartkp || $system == linux && ($arch == simarm || $arch == simarm64) ]
+dart/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host). On Linux/simarm64 and Linux/simarm this test requires buildtools/clang which is not always available on testing shards.
+dart_2/v8_snapshot_profile_writer_test: SkipByDesign # Only relevant for AOT. Doesn't work in cross-compilation (has to run on the host). On Linux/simarm64 and Linux/simarm this test requires buildtools/clang which is not always available on testing shards.
 
 [ $arch == arm || $arch == ia32 || $arch == simarm ]
 cc/GenKernelKernelCombined: SkipByDesign # No interpreter support.
@@ -375,17 +361,11 @@
 dart/thread_priority_linux_test: SkipByDesign
 dart_2/thread_priority_linux_test: SkipByDesign
 
-[ $builder_tag == bytecode_interpreter || $hot_reload || $hot_reload_rollback || $compiler != dartk && $compiler != dartkb && $compiler != dartkp ]
-dart/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensitive to when functions are optimized, so they are disabled on hotreload and optcounter bots.
-dart_2/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensitive to when functions are optimized, so they are disabled on hotreload and optcounter bots.
-
 [ $builder_tag == crossword || $builder_tag == crossword_ast ]
-dart/bytecode_with_ast_in_aot_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
 dart/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart/split_aot_kernel_generation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
-dart_2/bytecode_with_ast_in_aot_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
 dart_2/sdk_hash_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
 dart_2/split_aot_kernel_generation2_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
@@ -399,21 +379,11 @@
 dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 dart_2/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
 
-[ $compiler == dartk || $compiler == dartkb ]
-cc/DartAPI_New: Fail # Issue #33041
-cc/IsolateReload_LibraryLookup: Fail, Crash # Issue 32190
-dart/redirection_type_shuffling_test/00: RuntimeError, Pass
-dart/redirection_type_shuffling_test/none: RuntimeError
-dart_2/redirection_type_shuffling_test/00: RuntimeError, Pass
-dart_2/redirection_type_shuffling_test/none: RuntimeError
-
 [ $mode == debug || $runtime != dart_precompiled || $system == android ]
-dart/bytecode_with_ast_in_aot_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart/emit_aot_size_info_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart/split_aot_kernel_generation2_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart/split_aot_kernel_generation_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart/use_bare_instructions_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
-dart_2/bytecode_with_ast_in_aot_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart_2/emit_aot_size_info_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart_2/split_aot_kernel_generation2_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
 dart_2/split_aot_kernel_generation_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
@@ -422,6 +392,9 @@
 [ $mode != debug || $runtime != dart_precompiled ]
 in_memory_elf_test: Skip # Tests a debug-mode flag to dart_precompiled_runtime.
 
+[ $nnbd == strong || $nnbd == weak ]
+dart_2/*: SkipByDesign # Legacy tests are not supposed to run on NNBD bots.
+
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
@@ -464,7 +437,6 @@
 dart/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
 dart/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
 dart/issue_31959_31960_test: SkipSlow
-dart/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart/print_flow_graph_determinism_test: SkipSlow
@@ -479,7 +451,6 @@
 dart_2/disassemble_determinism_test: SkipSlow # Runs expensive fibonacci(32) computation in 2 subprocesses
 dart_2/isolates/spawn_function_test: Skip # This test explicitly enables isolate groups (off-by-default atm). It will be enabled once full IG reloading is implemented.
 dart_2/issue_31959_31960_test: SkipSlow
-dart_2/minimal_kernel_bytecode_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart_2/minimal_kernel_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart_2/null_safety_autodetection_in_kernel_compiler_test: SkipSlow # gen_kernel is too slow in hot reload testing mode
 dart_2/print_flow_graph_determinism_test: SkipSlow
@@ -489,3 +460,7 @@
 dart_2/splay_test: SkipSlow
 dart_2/stack_overflow_shared_test: SkipSlow # Too slow with --shared-slow-path-triggers-gc flag and not relevant outside precompiled.
 dart_2/type_feedback_test: Pass, Slow
+
+[ $hot_reload || $hot_reload_rollback || $compiler != dartk && $compiler != dartkp ]
+dart/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensitive to when functions are optimized, so they are disabled on hotreload and optcounter bots.
+dart_2/entrypoints/*: SkipByDesign # These tests are for compiler optimizations and very sensitive to when functions are optimized, so they are disabled on hotreload and optcounter bots.
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index c7a33f1..8acf95e 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -109,10 +109,6 @@
     }
   }
   public_configs = [ ":libdart_vm_config" ]
-  set_sources_assignment_filter([
-                                  "*_test.cc",
-                                  "*_test.h",
-                                ])
   sources = vm_sources + rebase_path(compiler_api_sources, ".", "./compiler/") +
             rebase_path(disassembler_sources, ".", "./compiler/") +
             rebase_path(heap_sources, ".", "./heap/")
@@ -122,10 +118,6 @@
 library_for_all_configs_with_compiler("libdart_compiler") {
   target_type = "source_set"
   public_configs = [ ":libdart_vm_config" ]
-  set_sources_assignment_filter([
-                                  "*_test.cc",
-                                  "*_test.h",
-                                ])
   sources = rebase_path(compiler_sources, ".", "./compiler/")
   include_dirs = [ ".." ]
   if (is_fuchsia) {
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 1d00e78..f7b1266 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -17,6 +17,7 @@
 
 #include "vm/clustered_snapshot.h"
 #include "vm/dart_api_impl.h"
+#include "vm/datastream.h"
 #include "vm/stack_frame.h"
 #include "vm/timer.h"
 
@@ -500,12 +501,6 @@
   benchmark->set_score(elapsed_time);
 }
 
-static uint8_t* malloc_allocator(uint8_t* ptr,
-                                 intptr_t old_size,
-                                 intptr_t new_size) {
-  return reinterpret_cast<uint8_t*>(realloc(ptr, new_size));
-}
-
 BENCHMARK_SIZE(CoreSnapshotSize) {
   const char* kScriptChars =
       "import 'dart:async';\n"
@@ -519,8 +514,6 @@
       "\n";
 
   // Start an Isolate, load a script and create a full snapshot.
-  uint8_t* vm_snapshot_data_buffer;
-  uint8_t* isolate_snapshot_data_buffer;
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
@@ -532,17 +525,16 @@
   Api::CheckAndFinalizePendingClasses(thread);
 
   // Write snapshot with object content.
-  FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
-                            &isolate_snapshot_data_buffer, &malloc_allocator,
-                            NULL, NULL /* image_writer */);
+  MallocWriteStream vm_snapshot_data(FullSnapshotWriter::kInitialSize);
+  MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
+  FullSnapshotWriter writer(
+      Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
+      /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
   writer.WriteFullSnapshot();
   const Snapshot* snapshot =
-      Snapshot::SetupFromBuffer(isolate_snapshot_data_buffer);
-  ASSERT(snapshot->kind() == Snapshot::kFull);
+      Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
+  ASSERT(snapshot->kind() == Snapshot::kFullCore);
   benchmark->set_score(snapshot->length());
-
-  free(vm_snapshot_data_buffer);
-  free(isolate_snapshot_data_buffer);
 }
 
 BENCHMARK_SIZE(StandaloneSnapshotSize) {
@@ -560,8 +552,6 @@
       "\n";
 
   // Start an Isolate, load a script and create a full snapshot.
-  uint8_t* vm_snapshot_data_buffer;
-  uint8_t* isolate_snapshot_data_buffer;
   // Need to load the script into the dart: core library due to
   // the import of dart:_internal.
   TestCase::LoadCoreTestScript(kScriptChars, NULL);
@@ -573,17 +563,16 @@
   Api::CheckAndFinalizePendingClasses(thread);
 
   // Write snapshot with object content.
-  FullSnapshotWriter writer(Snapshot::kFull, &vm_snapshot_data_buffer,
-                            &isolate_snapshot_data_buffer, &malloc_allocator,
-                            NULL, NULL /* image_writer */);
+  MallocWriteStream vm_snapshot_data(FullSnapshotWriter::kInitialSize);
+  MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
+  FullSnapshotWriter writer(
+      Snapshot::kFullCore, &vm_snapshot_data, &isolate_snapshot_data,
+      /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
   writer.WriteFullSnapshot();
   const Snapshot* snapshot =
-      Snapshot::SetupFromBuffer(isolate_snapshot_data_buffer);
-  ASSERT(snapshot->kind() == Snapshot::kFull);
+      Snapshot::SetupFromBuffer(isolate_snapshot_data.buffer());
+  ASSERT(snapshot->kind() == Snapshot::kFullCore);
   benchmark->set_score(snapshot->length());
-
-  free(vm_snapshot_data_buffer);
-  free(isolate_snapshot_data_buffer);
 }
 
 BENCHMARK(CreateMirrorSystem) {
diff --git a/runtime/vm/bitmap.cc b/runtime/vm/bitmap.cc
index d5e25dd..334c46b 100644
--- a/runtime/vm/bitmap.cc
+++ b/runtime/vm/bitmap.cc
@@ -77,7 +77,7 @@
   }
 }
 
-void BitmapBuilder::AppendAsBytesTo(GrowableArray<uint8_t>* bytes) const {
+void BitmapBuilder::AppendAsBytesTo(BaseWriteStream* stream) const {
   // Early return if there are no bits in the payload to copy.
   if (Length() == 0) return;
 
@@ -94,19 +94,20 @@
     payload_size = total_size;
     extra_size = 0;
   }
+#if defined(DEBUG)
+  // Make sure any bits in the payload beyond the bit length if we're not
+  // appending trailing zeroes are cleared to ensure deterministic snapshots.
+  if (extra_size == 0 && Length() % kBitsPerByte != 0) {
+    const int8_t mask = (1 << (Length() % kBitsPerByte)) - 1;
+    ASSERT_EQUAL(data_[payload_size - 1], (data_[payload_size - 1] & mask));
+  }
+#endif
   for (intptr_t i = 0; i < payload_size; i++) {
-    bytes->Add(data_[i]);
+    stream->WriteByte(data_[i]);
   }
   for (intptr_t i = 0; i < extra_size; i++) {
-    bytes->Add(0U);
+    stream->WriteByte(0U);
   }
-  // Make sure any bits in the payload beyond the bit length are cleared to
-  // ensure deterministic snapshots.
-#if defined(DEBUG)
-  if (Length() % kBitsPerByte == 0) return;
-  const int8_t mask = (1 << (Length() % kBitsPerByte)) - 1;
-  ASSERT(bytes->Last() == (bytes->Last() & mask));
-#endif
 }
 
 bool BitmapBuilder::GetBit(intptr_t bit_offset) const {
diff --git a/runtime/vm/bitmap.h b/runtime/vm/bitmap.h
index 878a834..ed08009 100644
--- a/runtime/vm/bitmap.h
+++ b/runtime/vm/bitmap.h
@@ -6,7 +6,7 @@
 #define RUNTIME_VM_BITMAP_H_
 
 #include "vm/allocation.h"
-#include "vm/growable_array.h"
+#include "vm/datastream.h"
 #include "vm/thread_state.h"
 #include "vm/zone.h"
 
@@ -44,7 +44,7 @@
   void SetRange(intptr_t min, intptr_t max, bool value);
 
   void Print() const;
-  void AppendAsBytesTo(GrowableArray<uint8_t>* bytes) const;
+  void AppendAsBytesTo(BaseWriteStream* stream) const;
 
  private:
   static const intptr_t kInitialSizeInBytes = 16;
diff --git a/runtime/vm/bitmap_test.cc b/runtime/vm/bitmap_test.cc
index 2c7f3d9..c3cd203 100644
--- a/runtime/vm/bitmap_test.cc
+++ b/runtime/vm/bitmap_test.cc
@@ -16,8 +16,8 @@
 static const uint32_t kTestPcOffset = 0x4;
 static const intptr_t kTestSpillSlotBitCount = 0;
 
-static CompressedStackMapsPtr MapsFromBuilder(BitmapBuilder* bmap) {
-  CompressedStackMapsBuilder builder;
+static CompressedStackMapsPtr MapsFromBuilder(Zone* zone, BitmapBuilder* bmap) {
+  CompressedStackMapsBuilder builder(zone);
   builder.AddEntry(kTestPcOffset, bmap, kTestSpillSlotBitCount);
   return builder.Finalize();
 }
@@ -51,8 +51,9 @@
   }
 
   // Create a CompressedStackMaps object and verify its contents.
-  const auto& maps1 = CompressedStackMaps::Handle(MapsFromBuilder(builder1));
-  CompressedStackMapsIterator it1(maps1);
+  const auto& maps1 = CompressedStackMaps::Handle(
+      thread->zone(), MapsFromBuilder(thread->zone(), builder1));
+  CompressedStackMaps::Iterator it1(thread, maps1);
   EXPECT(it1.MoveNext());
 
   EXPECT_EQ(kTestPcOffset, it1.pc_offset());
@@ -83,8 +84,9 @@
     EXPECT(!builder1->Get(i));
   }
 
-  const auto& maps2 = CompressedStackMaps::Handle(MapsFromBuilder(builder1));
-  CompressedStackMapsIterator it2(maps2);
+  const auto& maps2 = CompressedStackMaps::Handle(
+      thread->zone(), MapsFromBuilder(thread->zone(), builder1));
+  CompressedStackMaps::Iterator it2(thread, maps2);
   EXPECT(it2.MoveNext());
 
   EXPECT_EQ(kTestPcOffset, it2.pc_offset());
diff --git a/runtime/vm/bss_relocs.cc b/runtime/vm/bss_relocs.cc
index 80f50f5..867d82a 100644
--- a/runtime/vm/bss_relocs.cc
+++ b/runtime/vm/bss_relocs.cc
@@ -31,8 +31,8 @@
   auto const instructions = reinterpret_cast<uword>(
       current->isolate_group()->source()->snapshot_instructions);
   uword dso_base;
-  // For non-natively loaded snapshots, this is instead initialized in
-  // LoadedElf::ResolveSymbols().
+  // Needed for assembly snapshots. For ELF snapshots, we set up the relocated
+  // address information directly in the text segment InstructionsSection.
   if (NativeSymbolResolver::LookupSharedObject(instructions, &dso_base)) {
     InitializeBSSEntry(Relocation::InstructionsRelocatedAddress,
                        instructions - dso_base, bss_start);
diff --git a/runtime/vm/canonical_tables.h b/runtime/vm/canonical_tables.h
new file mode 100644
index 0000000..69b79eb
--- /dev/null
+++ b/runtime/vm/canonical_tables.h
@@ -0,0 +1,259 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_CANONICAL_TABLES_H_
+#define RUNTIME_VM_CANONICAL_TABLES_H_
+
+#include "platform/assert.h"
+#include "vm/hash_table.h"
+#include "vm/object.h"
+
+namespace dart {
+
+template <typename CharType>
+class CharArray {
+ public:
+  CharArray(const CharType* data, intptr_t len) : data_(data), len_(len) {
+    hash_ = String::Hash(data, len);
+  }
+  StringPtr ToSymbol() const {
+    String& result = String::Handle(StringFrom(data_, len_, Heap::kOld));
+    result.SetCanonical();
+    result.SetHash(hash_);
+    return result.raw();
+  }
+  bool Equals(const String& other) const {
+    ASSERT(other.HasHash());
+    if (other.Hash() != hash_) {
+      return false;
+    }
+    return other.Equals(data_, len_);
+  }
+  intptr_t Hash() const { return hash_; }
+
+ private:
+  const CharType* data_;
+  intptr_t len_;
+  intptr_t hash_;
+};
+typedef CharArray<uint8_t> Latin1Array;
+typedef CharArray<uint16_t> UTF16Array;
+typedef CharArray<int32_t> UTF32Array;
+
+class StringSlice {
+ public:
+  StringSlice(const String& str, intptr_t begin_index, intptr_t length)
+      : str_(str), begin_index_(begin_index), len_(length) {
+    hash_ = is_all() ? str.Hash() : String::Hash(str, begin_index, length);
+  }
+  StringPtr ToSymbol() const;
+  bool Equals(const String& other) const {
+    ASSERT(other.HasHash());
+    if (other.Hash() != hash_) {
+      return false;
+    }
+    return other.Equals(str_, begin_index_, len_);
+  }
+  intptr_t Hash() const { return hash_; }
+
+ private:
+  bool is_all() const { return begin_index_ == 0 && len_ == str_.Length(); }
+  const String& str_;
+  intptr_t begin_index_;
+  intptr_t len_;
+  intptr_t hash_;
+};
+
+class ConcatString {
+ public:
+  ConcatString(const String& str1, const String& str2)
+      : str1_(str1), str2_(str2), hash_(String::HashConcat(str1, str2)) {}
+  StringPtr ToSymbol() const;
+  bool Equals(const String& other) const {
+    ASSERT(other.HasHash());
+    if (other.Hash() != hash_) {
+      return false;
+    }
+    return other.EqualsConcat(str1_, str2_);
+  }
+  intptr_t Hash() const { return hash_; }
+
+ private:
+  const String& str1_;
+  const String& str2_;
+  intptr_t hash_;
+};
+
+class SymbolTraits {
+ public:
+  static const char* Name() { return "SymbolTraits"; }
+  static bool ReportStats() { return false; }
+
+  static bool IsMatch(const Object& a, const Object& b) {
+    const String& a_str = String::Cast(a);
+    const String& b_str = String::Cast(b);
+    ASSERT(a_str.HasHash());
+    ASSERT(b_str.HasHash());
+    if (a_str.Hash() != b_str.Hash()) {
+      return false;
+    }
+    intptr_t a_len = a_str.Length();
+    if (a_len != b_str.Length()) {
+      return false;
+    }
+    // Use a comparison which does not consider the state of the canonical bit.
+    return a_str.Equals(b_str, 0, a_len);
+  }
+  template <typename CharType>
+  static bool IsMatch(const CharArray<CharType>& array, const Object& obj) {
+    return array.Equals(String::Cast(obj));
+  }
+  static bool IsMatch(const StringSlice& slice, const Object& obj) {
+    return slice.Equals(String::Cast(obj));
+  }
+  static bool IsMatch(const ConcatString& concat, const Object& obj) {
+    return concat.Equals(String::Cast(obj));
+  }
+  static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
+  template <typename CharType>
+  static uword Hash(const CharArray<CharType>& array) {
+    return array.Hash();
+  }
+  static uword Hash(const StringSlice& slice) { return slice.Hash(); }
+  static uword Hash(const ConcatString& concat) { return concat.Hash(); }
+  template <typename CharType>
+  static ObjectPtr NewKey(const CharArray<CharType>& array) {
+    return array.ToSymbol();
+  }
+  static ObjectPtr NewKey(const StringSlice& slice) { return slice.ToSymbol(); }
+  static ObjectPtr NewKey(const ConcatString& concat) {
+    return concat.ToSymbol();
+  }
+};
+typedef UnorderedHashSet<SymbolTraits> CanonicalStringSet;
+
+class CanonicalTypeKey {
+ public:
+  explicit CanonicalTypeKey(const Type& key) : key_(key) {}
+  bool Matches(const Type& arg) const { return key_.Equals(arg); }
+  uword Hash() const { return key_.Hash(); }
+  const Type& key_;
+
+ private:
+  DISALLOW_ALLOCATION();
+};
+
+// Traits for looking up Canonical Type based on its hash.
+class CanonicalTypeTraits {
+ public:
+  static const char* Name() { return "CanonicalTypeTraits"; }
+  static bool ReportStats() { return false; }
+
+  // Called when growing the table.
+  static bool IsMatch(const Object& a, const Object& b) {
+    ASSERT(a.IsType() && b.IsType());
+    const Type& arg1 = Type::Cast(a);
+    const Type& arg2 = Type::Cast(b);
+    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
+  }
+  static bool IsMatch(const CanonicalTypeKey& a, const Object& b) {
+    ASSERT(b.IsType());
+    return a.Matches(Type::Cast(b));
+  }
+  static uword Hash(const Object& key) {
+    ASSERT(key.IsType());
+    return Type::Cast(key).Hash();
+  }
+  static uword Hash(const CanonicalTypeKey& key) { return key.Hash(); }
+  static ObjectPtr NewKey(const CanonicalTypeKey& obj) {
+    return obj.key_.raw();
+  }
+};
+typedef UnorderedHashSet<CanonicalTypeTraits> CanonicalTypeSet;
+
+class CanonicalTypeParameterKey {
+ public:
+  explicit CanonicalTypeParameterKey(const TypeParameter& key) : key_(key) {}
+  bool Matches(const TypeParameter& arg) const { return key_.Equals(arg); }
+  uword Hash() const { return key_.Hash(); }
+  const TypeParameter& key_;
+
+ private:
+  DISALLOW_ALLOCATION();
+};
+
+// Traits for looking up Canonical TypeParameter based on its hash.
+class CanonicalTypeParameterTraits {
+ public:
+  static const char* Name() { return "CanonicalTypeParameterTraits"; }
+  static bool ReportStats() { return false; }
+
+  // Called when growing the table.
+  static bool IsMatch(const Object& a, const Object& b) {
+    ASSERT(a.IsTypeParameter() && b.IsTypeParameter());
+    const TypeParameter& arg1 = TypeParameter::Cast(a);
+    const TypeParameter& arg2 = TypeParameter::Cast(b);
+    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
+  }
+  static bool IsMatch(const CanonicalTypeParameterKey& a, const Object& b) {
+    ASSERT(b.IsTypeParameter());
+    return a.Matches(TypeParameter::Cast(b));
+  }
+  static uword Hash(const Object& key) {
+    ASSERT(key.IsTypeParameter());
+    return TypeParameter::Cast(key).Hash();
+  }
+  static uword Hash(const CanonicalTypeParameterKey& key) { return key.Hash(); }
+  static ObjectPtr NewKey(const CanonicalTypeParameterKey& obj) {
+    return obj.key_.raw();
+  }
+};
+typedef UnorderedHashSet<CanonicalTypeParameterTraits>
+    CanonicalTypeParameterSet;
+
+class CanonicalTypeArgumentsKey {
+ public:
+  explicit CanonicalTypeArgumentsKey(const TypeArguments& key) : key_(key) {}
+  bool Matches(const TypeArguments& arg) const {
+    return key_.Equals(arg) && (key_.Hash() == arg.Hash());
+  }
+  uword Hash() const { return key_.Hash(); }
+  const TypeArguments& key_;
+
+ private:
+  DISALLOW_ALLOCATION();
+};
+
+// Traits for looking up Canonical TypeArguments based on its hash.
+class CanonicalTypeArgumentsTraits {
+ public:
+  static const char* Name() { return "CanonicalTypeArgumentsTraits"; }
+  static bool ReportStats() { return false; }
+
+  // Called when growing the table.
+  static bool IsMatch(const Object& a, const Object& b) {
+    ASSERT(a.IsTypeArguments() && b.IsTypeArguments());
+    const TypeArguments& arg1 = TypeArguments::Cast(a);
+    const TypeArguments& arg2 = TypeArguments::Cast(b);
+    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
+  }
+  static bool IsMatch(const CanonicalTypeArgumentsKey& a, const Object& b) {
+    ASSERT(b.IsTypeArguments());
+    return a.Matches(TypeArguments::Cast(b));
+  }
+  static uword Hash(const Object& key) {
+    ASSERT(key.IsTypeArguments());
+    return TypeArguments::Cast(key).Hash();
+  }
+  static uword Hash(const CanonicalTypeArgumentsKey& key) { return key.Hash(); }
+  static ObjectPtr NewKey(const CanonicalTypeArgumentsKey& obj) {
+    return obj.key_.raw();
+  }
+};
+typedef UnorderedHashSet<CanonicalTypeArgumentsTraits>
+    CanonicalTypeArgumentsSet;
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_CANONICAL_TABLES_H_
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 34cc58e..8d02cbb 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -7,6 +7,7 @@
 
 #include "vm/class_finalizer.h"
 
+#include "vm/canonical_tables.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/flags.h"
 #include "vm/hash_table.h"
@@ -21,7 +22,6 @@
 #include "vm/runtime_entry.h"
 #include "vm/symbols.h"
 #include "vm/timeline.h"
-#include "vm/type_table.h"
 #include "vm/type_testing_stubs.h"
 
 namespace dart {
@@ -626,22 +626,26 @@
           if (super_type_arg.IsBeingFinalized()) {
             // The super_type_arg was instantiated from a type being finalized.
             // We need to finish finalizing its type arguments.
-            ASSERT(super_type_arg.IsTypeRef());
-            AbstractType& ref_super_type_arg =
-                AbstractType::Handle(TypeRef::Cast(super_type_arg).type());
-            if (FLAG_trace_type_finalization) {
-              THR_Print("Instantiated TypeRef '%s': '%s'\n",
-                        String::Handle(super_type_arg.Name()).ToCString(),
-                        ref_super_type_arg.ToCString());
+            AbstractType& unfinalized_type = AbstractType::Handle();
+            if (super_type_arg.IsTypeRef()) {
+              unfinalized_type = TypeRef::Cast(super_type_arg).type();
+            } else {
+              ASSERT(super_type_arg.IsType());
+              unfinalized_type = super_type_arg.raw();
             }
-            CheckRecursiveType(cls, ref_super_type_arg, pending_types);
-            pending_types->Add(ref_super_type_arg);
+            if (FLAG_trace_type_finalization) {
+              THR_Print("Instantiated unfinalized '%s': '%s'\n",
+                        String::Handle(unfinalized_type.Name()).ToCString(),
+                        unfinalized_type.ToCString());
+            }
+            CheckRecursiveType(cls, unfinalized_type, pending_types);
+            pending_types->Add(unfinalized_type);
             const Class& super_cls =
-                Class::Handle(ref_super_type_arg.type_class());
+                Class::Handle(unfinalized_type.type_class());
             const TypeArguments& super_args =
-                TypeArguments::Handle(ref_super_type_arg.arguments());
+                TypeArguments::Handle(unfinalized_type.arguments());
             // Mark as finalized before finalizing to avoid cycles.
-            ref_super_type_arg.SetIsFinalized();
+            unfinalized_type.SetIsFinalized();
             // Although the instantiator is different between cls and super_cls,
             // we still need to pass the current instantiation trail as to avoid
             // divergence. Finalizing the type arguments of super_cls may indeed
@@ -652,9 +656,9 @@
                 super_cls.NumTypeArguments() - super_cls.NumTypeParameters(),
                 pending_types, trail);
             if (FLAG_trace_type_finalization) {
-              THR_Print("Finalized instantiated TypeRef '%s': '%s'\n",
-                        String::Handle(super_type_arg.Name()).ToCString(),
-                        ref_super_type_arg.ToCString());
+              THR_Print("Finalized instantiated '%s': '%s'\n",
+                        String::Handle(unfinalized_type.Name()).ToCString(),
+                        unfinalized_type.ToCString());
             }
           }
         }
@@ -676,7 +680,7 @@
   if (type.IsFinalized()) {
     // Ensure type is canonical if canonicalization is requested.
     if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
-      return type.Canonicalize();
+      return type.Canonicalize(Thread::Current(), nullptr);
     }
     return type.raw();
   }
@@ -733,7 +737,7 @@
       ASSERT(type_parameter.IsCanonical());
       return type_parameter.raw();
     }
-    return type_parameter.Canonicalize();
+    return type_parameter.Canonicalize(Thread::Current(), nullptr);
   }
 
   // At this point, we can only have a Type.
@@ -817,13 +821,13 @@
     if (FLAG_trace_type_finalization) {
       THR_Print("Canonicalizing type '%s'\n",
                 String::Handle(zone, type.Name()).ToCString());
-      AbstractType& canonical_type =
-          AbstractType::Handle(zone, type.Canonicalize());
+      AbstractType& canonical_type = AbstractType::Handle(
+          zone, type.Canonicalize(Thread::Current(), nullptr));
       THR_Print("Done canonicalizing type '%s'\n",
                 String::Handle(zone, canonical_type.Name()).ToCString());
       return canonical_type.raw();
     }
-    return type.Canonicalize();
+    return type.Canonicalize(Thread::Current(), nullptr);
   } else {
     return type.raw();
   }
@@ -1269,8 +1273,7 @@
   enum_value = Instance::New(enum_cls, Heap::kOld);
   enum_value.SetField(index_field, Smi::Handle(zone, Smi::New(-1)));
   enum_value.SetField(name_field, enum_ident);
-  const char* error_msg = NULL;
-  enum_value = enum_value.CheckAndCanonicalize(thread, &error_msg);
+  enum_value = enum_value.Canonicalize(thread);
   ASSERT(!enum_value.IsNull());
   ASSERT(enum_value.IsCanonical());
   const Field& sentinel = Field::Handle(
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index a973ce7..27d263a 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -9,6 +9,7 @@
 #include "platform/assert.h"
 #include "vm/bootstrap.h"
 #include "vm/bss_relocs.h"
+#include "vm/canonical_tables.h"
 #include "vm/class_id.h"
 #include "vm/code_observers.h"
 #include "vm/compiler/api/print_filter.h"
@@ -143,6 +144,40 @@
   size_ += (stop - start);
 }
 
+static UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(
+    Serializer* s,
+    intptr_t class_id) {
+  const auto unboxed_fields_bitmap_host =
+      s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
+          class_id);
+
+  UnboxedFieldBitmap unboxed_fields_bitmap;
+  if (unboxed_fields_bitmap_host.IsEmpty() ||
+      kWordSize == compiler::target::kWordSize) {
+    unboxed_fields_bitmap = unboxed_fields_bitmap_host;
+  } else {
+    ASSERT(kWordSize == 8 && compiler::target::kWordSize == 4);
+    // A new bitmap is built if the word sizes in the target and
+    // host are different
+    unboxed_fields_bitmap.Reset();
+    intptr_t target_i = 0, host_i = 0;
+
+    while (host_i < UnboxedFieldBitmap::Length()) {
+      // Each unboxed field has constant length, therefore the number of
+      // words used by it should double when compiling from 64-bit to 32-bit.
+      if (unboxed_fields_bitmap_host.Get(host_i++)) {
+        unboxed_fields_bitmap.Set(target_i++);
+        unboxed_fields_bitmap.Set(target_i++);
+      } else {
+        // For object pointers, the field is always one word length
+        target_i++;
+      }
+    }
+  }
+
+  return unboxed_fields_bitmap;
+}
+
 class ClassSerializationCluster : public SerializationCluster {
  public:
   explicit ClassSerializationCluster(intptr_t num_cids)
@@ -210,7 +245,8 @@
       s->UnexpectedObject(cls, "Class with illegal cid");
     }
     s->WriteCid(class_id);
-    if (s->kind() == Snapshot::kFull && RequireLegacyErasureOfConstants(cls)) {
+    if (s->kind() == Snapshot::kFullCore &&
+        RequireLegacyErasureOfConstants(cls)) {
       s->UnexpectedObject(cls, "Class with non mode agnostic constants");
     }
     if (s->kind() != Snapshot::kFullAOT) {
@@ -235,46 +271,13 @@
   GrowableArray<ClassPtr> predefined_;
   GrowableArray<ClassPtr> objects_;
 
-  UnboxedFieldBitmap CalculateTargetUnboxedFieldsBitmap(Serializer* s,
-                                                        intptr_t class_id) {
-    const auto unboxed_fields_bitmap_host =
-        s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            class_id);
-
-    UnboxedFieldBitmap unboxed_fields_bitmap;
-    if (unboxed_fields_bitmap_host.IsEmpty() ||
-        kWordSize == compiler::target::kWordSize) {
-      unboxed_fields_bitmap = unboxed_fields_bitmap_host;
-    } else {
-      ASSERT(kWordSize == 8 && compiler::target::kWordSize == 4);
-      // A new bitmap is built if the word sizes in the target and
-      // host are different
-      unboxed_fields_bitmap.Reset();
-      intptr_t target_i = 0, host_i = 0;
-
-      while (host_i < UnboxedFieldBitmap::Length()) {
-        // Each unboxed field has constant length, therefore the number of
-        // words used by it should double when compiling from 64-bit to 32-bit.
-        if (unboxed_fields_bitmap_host.Get(host_i++)) {
-          unboxed_fields_bitmap.Set(target_i++);
-          unboxed_fields_bitmap.Set(target_i++);
-        } else {
-          // For object pointers, the field is always one word length
-          target_i++;
-        }
-      }
-    }
-
-    return unboxed_fields_bitmap;
-  }
-
   bool RequireLegacyErasureOfConstants(ClassPtr cls) {
     // Do not generate a core snapshot containing constants that would require
     // a legacy erasure of their types if loaded in an isolate running in weak
     // mode.
     if (cls->ptr()->host_type_arguments_field_offset_in_words_ ==
             Class::kNoTypeArguments ||
-        cls->ptr()->constants_ == Object::empty_array().raw()) {
+        cls->ptr()->constants_ == Array::null()) {
       return false;
     }
     Zone* zone = Thread::Current()->zone();
@@ -289,7 +292,7 @@
   ClassDeserializationCluster() {}
   ~ClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     predefined_start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     intptr_t count = d->ReadUnsigned();
@@ -311,7 +314,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     ClassTable* table = d->isolate()->class_table();
 
     for (intptr_t id = predefined_start_index_; id < predefined_stop_index_;
@@ -442,7 +445,6 @@
       AutoTraceObject(type_args);
       const intptr_t length = Smi::Value(type_args->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(type_args->ptr()->IsCanonical());
       intptr_t hash = Smi::Value(type_args->ptr()->hash_);
       s->Write<int32_t>(hash);
       const intptr_t nullability = Smi::Value(type_args->ptr()->nullability_);
@@ -464,7 +466,7 @@
   TypeArgumentsDeserializationCluster() {}
   ~TypeArgumentsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -476,11 +478,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeArgumentsPtr type_args = static_cast<TypeArgumentsPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(type_args, kTypeArgumentsCid,
                                      TypeArguments::InstanceSize(length),
                                      is_canonical);
@@ -494,6 +495,24 @@
       }
     }
   }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeArgumentsSet table(
+          d->zone(), d->isolate()->object_store()->canonical_type_arguments());
+      TypeArguments& type_arg = TypeArguments::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type_arg ^= refs.At(i);
+        ASSERT(type_arg.IsCanonical());
+        bool present = table.Insert(type_arg);
+        // Two recursive types with different topology (and hashes) may be
+        // equal.
+        ASSERT(!present || type_arg.IsRecursive());
+      }
+      d->isolate()->object_store()->set_canonical_type_arguments(
+          table.Release());
+    }
+  }
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -540,7 +559,7 @@
   PatchClassDeserializationCluster() {}
   ~PatchClassDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -551,7 +570,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       PatchClassPtr cls = static_cast<PatchClassPtr>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kPatchClassCid,
@@ -578,7 +597,7 @@
     objects_.Add(func);
 
     PushFromTo(func);
-    if (kind == Snapshot::kFull) {
+    if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
       NOT_IN_PRECOMPILED(s->Push(func->ptr()->bytecode_));
     } else if (kind == Snapshot::kFullAOT) {
       s->Push(func->ptr()->code_);
@@ -607,7 +626,7 @@
       FunctionPtr func = objects_[i];
       AutoTraceObjectName(func, MakeDisambiguatedFunctionName(s, func));
       WriteFromTo(func);
-      if (kind == Snapshot::kFull) {
+      if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
         NOT_IN_PRECOMPILED(WriteField(func, bytecode_));
       } else if (kind == Snapshot::kFullAOT) {
         WriteField(func, code_);
@@ -655,7 +674,7 @@
   FunctionDeserializationCluster() {}
   ~FunctionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -665,7 +684,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -674,7 +693,7 @@
                                      Function::InstanceSize());
       ReadFromTo(func);
 
-      if (kind == Snapshot::kFull) {
+      if ((kind == Snapshot::kFull) || (kind == Snapshot::kFullCore)) {
         NOT_IN_PRECOMPILED(func->ptr()->bytecode_ =
                                static_cast<BytecodePtr>(d->ReadRef()));
       } else if (kind == Snapshot::kFullAOT) {
@@ -718,7 +737,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     if (d->kind() == Snapshot::kFullAOT) {
       Function& func = Function::Handle(d->zone());
       for (intptr_t i = start_index_; i < stop_index_; i++) {
@@ -807,7 +826,7 @@
   ClosureDataDeserializationCluster() {}
   ~ClosureDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -818,7 +837,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosureDataPtr data = static_cast<ClosureDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kClosureDataCid,
@@ -877,7 +896,7 @@
   SignatureDataDeserializationCluster() {}
   ~SignatureDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -888,7 +907,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       SignatureDataPtr data = static_cast<SignatureDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kSignatureDataCid,
@@ -946,7 +965,7 @@
   FfiTrampolineDataDeserializationCluster() {}
   ~FfiTrampolineDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -957,7 +976,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       FfiTrampolineDataPtr data = static_cast<FfiTrampolineDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kFfiTrampolineDataCid,
@@ -1011,7 +1030,7 @@
   RedirectionDataDeserializationCluster() {}
   ~RedirectionDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1022,7 +1041,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RedirectionDataPtr data = static_cast<RedirectionDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(data, kRedirectionDataCid,
@@ -1148,7 +1167,7 @@
   FieldDeserializationCluster() {}
   ~FieldDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1158,7 +1177,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     Snapshot::Kind kind = d->kind();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1203,7 +1222,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Field& field = Field::Handle(d->zone());
     if (!Isolate::Current()->use_field_guards()) {
       for (intptr_t i = start_index_; i < stop_index_; i++) {
@@ -1270,7 +1289,7 @@
   ScriptDeserializationCluster() {}
   ~ScriptDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1280,7 +1299,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ScriptPtr script = static_cast<ScriptPtr>(d->Ref(id));
       Deserializer::InitializeHeader(script, kScriptCid,
@@ -1343,7 +1362,7 @@
   LibraryDeserializationCluster() {}
   ~LibraryDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1353,7 +1372,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPtr lib = static_cast<LibraryPtr>(d->Ref(id));
       Deserializer::InitializeHeader(lib, kLibraryCid, Library::InstanceSize());
@@ -1415,7 +1434,7 @@
   NamespaceDeserializationCluster() {}
   ~NamespaceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1425,7 +1444,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       NamespacePtr ns = static_cast<NamespacePtr>(d->Ref(id));
       Deserializer::InitializeHeader(ns, kNamespaceCid,
@@ -1480,7 +1499,7 @@
   KernelProgramInfoDeserializationCluster() {}
   ~KernelProgramInfoDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -1491,7 +1510,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       KernelProgramInfoPtr info = static_cast<KernelProgramInfoPtr>(d->Ref(id));
       Deserializer::InitializeHeader(info, kKernelProgramInfoCid,
@@ -1501,7 +1520,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Array& array = Array::Handle(d->zone());
     KernelProgramInfo& info = KernelProgramInfo::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -1841,7 +1860,7 @@
   CodeDeserializationCluster() {}
   ~CodeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
     start_index_ = d->next_index();
     const intptr_t count = d->ReadUnsigned();
@@ -1859,7 +1878,7 @@
     deferred_stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ReadFill(d, id, false);
     }
@@ -1892,26 +1911,26 @@
     code->ptr()->code_source_map_ = static_cast<CodeSourceMapPtr>(d->ReadRef());
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-      if (d->kind() == Snapshot::kFullJIT) {
-        code->ptr()->deopt_info_array_ = static_cast<ArrayPtr>(d->ReadRef());
-        code->ptr()->static_calls_target_table_ =
-            static_cast<ArrayPtr>(d->ReadRef());
-      }
+    if (d->kind() == Snapshot::kFullJIT) {
+      code->ptr()->deopt_info_array_ = static_cast<ArrayPtr>(d->ReadRef());
+      code->ptr()->static_calls_target_table_ =
+          static_cast<ArrayPtr>(d->ReadRef());
+    }
 #endif  // !DART_PRECOMPILED_RUNTIME
 
 #if !defined(PRODUCT)
-      code->ptr()->return_address_metadata_ = d->ReadRef();
-      code->ptr()->var_descriptors_ = LocalVarDescriptors::null();
-      code->ptr()->comments_ = FLAG_code_comments
-                                   ? static_cast<ArrayPtr>(d->ReadRef())
-                                   : Array::null();
-      code->ptr()->compile_timestamp_ = 0;
+    code->ptr()->return_address_metadata_ = d->ReadRef();
+    code->ptr()->var_descriptors_ = LocalVarDescriptors::null();
+    code->ptr()->comments_ = FLAG_code_comments
+                                 ? static_cast<ArrayPtr>(d->ReadRef())
+                                 : Array::null();
+    code->ptr()->compile_timestamp_ = 0;
 #endif
 
-      code->ptr()->state_bits_ = d->Read<int32_t>();
+    code->ptr()->state_bits_ = d->Read<int32_t>();
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     d->EndInstructions(refs, start_index_, stop_index_);
 
 #if !defined(PRODUCT)
@@ -1993,7 +2012,7 @@
   BytecodeDeserializationCluster() {}
   virtual ~BytecodeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2003,7 +2022,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     ASSERT(d->kind() != Snapshot::kFullAOT);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -2019,7 +2038,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     Bytecode& bytecode = Bytecode::Handle(d->zone());
     ExternalTypedData& binary = ExternalTypedData::Handle(d->zone());
 
@@ -2131,7 +2150,7 @@
   ObjectPoolDeserializationCluster() {}
   ~ObjectPoolDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2143,7 +2162,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       ObjectPoolPtr pool = static_cast<ObjectPoolPtr>(d->Ref(id + 0));
@@ -2206,14 +2225,14 @@
     s->WriteUnsigned(WrittenCount());
 
     // Set up references for those objects that will be written.
-    for (auto const ref : canonical_wsrs_) {
+    for (auto const& ref : canonical_wsrs_) {
       s->AssignRef(ref);
     }
 
     // In precompiled mode, set the object ID of each non-canonical WSR to
     // its canonical counterpart's object ID. This ensures that any reference to
     // it is serialized as a reference to the canonicalized one.
-    for (auto const ref : objects_) {
+    for (auto const& ref : objects_) {
       ASSERT(IsReachableReference(heap_->GetObjectId(ref)));
       if (ShouldDrop(ref)) {
         // For dropped references, reset their ID to be the unreachable
@@ -2238,7 +2257,7 @@
 
   void WriteFill(Serializer* s) {
     ASSERT(s->kind() == Snapshot::kFullAOT);
-    for (auto const ref : canonical_wsrs_) {
+    for (auto const& ref : canonical_wsrs_) {
       AutoTraceObject(ref);
 
       // In precompiled mode, we drop the reference to the target and only
@@ -2295,7 +2314,7 @@
   WeakSerializationReferenceDeserializationCluster() {}
   ~WeakSerializationReferenceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2309,7 +2328,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       auto const ref = static_cast<WeakSerializationReferencePtr>(d->Ref(id));
       Deserializer::InitializeHeader(
@@ -2367,7 +2386,7 @@
   PcDescriptorsDeserializationCluster() {}
   ~PcDescriptorsDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2379,7 +2398,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id += 1) {
       const intptr_t length = d->ReadUnsigned();
       PcDescriptorsPtr desc = static_cast<PcDescriptorsPtr>(d->Ref(id));
@@ -2460,7 +2479,7 @@
   RODataDeserializationCluster() {}
   ~RODataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     intptr_t count = d->ReadUnsigned();
     uint32_t running_offset = 0;
     for (intptr_t i = 0; i < count; i++) {
@@ -2469,7 +2488,7 @@
     }
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     // No-op.
   }
 };
@@ -2530,7 +2549,7 @@
   ExceptionHandlersDeserializationCluster() {}
   ~ExceptionHandlersDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2542,7 +2561,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ExceptionHandlersPtr handlers =
           static_cast<ExceptionHandlersPtr>(d->Ref(id));
@@ -2618,7 +2637,7 @@
   ContextDeserializationCluster() {}
   ~ContextDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2630,7 +2649,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextPtr context = static_cast<ContextPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
@@ -2694,7 +2713,7 @@
   ContextScopeDeserializationCluster() {}
   ~ContextScopeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2706,7 +2725,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ContextScopePtr scope = static_cast<ContextScopePtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
@@ -2761,7 +2780,7 @@
   ParameterTypeCheckDeserializationCluster() {}
   ~ParameterTypeCheckDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2772,7 +2791,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ParameterTypeCheckPtr check =
           static_cast<ParameterTypeCheckPtr>(d->Ref(id));
@@ -2826,7 +2845,7 @@
   UnlinkedCallDeserializationCluster() {}
   ~UnlinkedCallDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2837,7 +2856,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnlinkedCallPtr unlinked = static_cast<UnlinkedCallPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unlinked, kUnlinkedCallCid,
@@ -2894,7 +2913,7 @@
   ICDataDeserializationCluster() {}
   ~ICDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2904,7 +2923,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ICDataPtr ic = static_cast<ICDataPtr>(d->Ref(id));
       Deserializer::InitializeHeader(ic, kICDataCid, ICData::InstanceSize());
@@ -2958,7 +2977,7 @@
   MegamorphicCacheDeserializationCluster() {}
   ~MegamorphicCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -2969,7 +2988,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       MegamorphicCachePtr cache = static_cast<MegamorphicCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kMegamorphicCacheCid,
@@ -2980,7 +2999,7 @@
   }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     if (FLAG_use_bare_instructions) {
       // By default, every megamorphic call site will load the target
       // [Function] from the hash table and call indirectly via loading the
@@ -3048,7 +3067,7 @@
   SubtypeTestCacheDeserializationCluster() {}
   ~SubtypeTestCacheDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3059,7 +3078,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       SubtypeTestCachePtr cache = static_cast<SubtypeTestCachePtr>(d->Ref(id));
       Deserializer::InitializeHeader(cache, kSubtypeTestCacheCid,
@@ -3111,7 +3130,7 @@
   LoadingUnitDeserializationCluster() {}
   ~LoadingUnitDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3122,7 +3141,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LoadingUnitPtr unit = static_cast<LoadingUnitPtr>(d->Ref(id));
       Deserializer::InitializeHeader(unit, kLoadingUnitCid,
@@ -3180,7 +3199,7 @@
   LanguageErrorDeserializationCluster() {}
   ~LanguageErrorDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3191,7 +3210,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LanguageErrorPtr error = static_cast<LanguageErrorPtr>(d->Ref(id));
       Deserializer::InitializeHeader(error, kLanguageErrorCid,
@@ -3246,7 +3265,7 @@
   UnhandledExceptionDeserializationCluster() {}
   ~UnhandledExceptionDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3257,7 +3276,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       UnhandledExceptionPtr exception =
           static_cast<UnhandledExceptionPtr>(d->Ref(id));
@@ -3329,13 +3348,14 @@
     intptr_t next_field_offset = host_next_field_offset_in_words_
                                  << kWordSizeLog2;
     const intptr_t count = objects_.length();
+    s->WriteUnsigned64(CalculateTargetUnboxedFieldsBitmap(s, cid_).Value());
     const auto unboxed_fields_bitmap =
         s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
             cid_);
+
     for (intptr_t i = 0; i < count; i++) {
       InstancePtr instance = objects_[i];
       AutoTraceObject(instance);
-      s->Write<bool>(instance->ptr()->IsCanonical());
       intptr_t offset = Instance::NextFieldOffset();
       while (offset < next_field_offset) {
         if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
@@ -3369,7 +3389,7 @@
   explicit InstanceDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~InstanceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3383,17 +3403,14 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t next_field_offset = next_field_offset_in_words_ << kWordSizeLog2;
     intptr_t instance_size =
         Object::RoundedAllocationSize(instance_size_in_words_ * kWordSize);
+    const UnboxedFieldBitmap unboxed_fields_bitmap(d->ReadUnsigned64());
 
-    const auto unboxed_fields_bitmap =
-        d->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cid_);
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       InstancePtr instance = static_cast<InstancePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(instance, cid_, instance_size,
                                      is_canonical);
       intptr_t offset = Instance::NextFieldOffset();
@@ -3469,7 +3486,7 @@
   LibraryPrefixDeserializationCluster() {}
   ~LibraryPrefixDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3480,7 +3497,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LibraryPrefixPtr prefix = static_cast<LibraryPrefixPtr>(d->Ref(id));
       Deserializer::InitializeHeader(prefix, kLibraryPrefixCid,
@@ -3505,11 +3522,7 @@
 
   void Trace(Serializer* s, ObjectPtr object) {
     TypePtr type = Type::RawCast(object);
-    if (type->ptr()->IsCanonical()) {
-      canonical_objects_.Add(type);
-    } else {
-      objects_.Add(type);
-    }
+    objects_.Add(type);
 
     PushFromTo(type);
 
@@ -3526,13 +3539,7 @@
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeCid);
-    intptr_t count = canonical_objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      TypePtr type = canonical_objects_[i];
-      s->AssignRef(type);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       TypePtr type = objects_[i];
@@ -3541,11 +3548,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = canonical_objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      WriteType(s, canonical_objects_[i]);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       WriteType(s, objects_[i]);
     }
@@ -3568,7 +3571,6 @@
     s->Write<uint8_t>(combined);
   }
 
-  GrowableArray<TypePtr> canonical_objects_;
   GrowableArray<TypePtr> objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -3578,59 +3580,55 @@
   TypeDeserializationCluster() {}
   ~TypeDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
-    canonical_start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
-    }
-    canonical_stop_index_ = d->next_index();
-
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
-    count = d->ReadUnsigned();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(AllocateUninitialized(old_space, Type::InstanceSize()));
     }
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
-    for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-         id++) {
-      TypePtr type = static_cast<TypePtr>(d->Ref(id));
-      ReadType(d, type, /*is_canonical=*/true);
-    }
-
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypePtr type = static_cast<TypePtr>(d->Ref(id));
-      ReadType(d, type, /*is_canonical=*/false);
+      Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
+                                     is_canonical);
+      ReadFromTo(type);
+      type->ptr()->token_pos_ = d->ReadTokenPosition();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->type_state_ = combined >> kNullabilityBitSize;
+      type->ptr()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeSet table(d->zone(),
+                             d->isolate()->object_store()->canonical_types());
+      Type& type = Type::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type ^= refs.At(i);
+        ASSERT(type.IsCanonical());
+        bool present = table.Insert(type);
+        // Two recursive types with different topology (and hashes) may be
+        // equal.
+        ASSERT(!present || type.IsRecursive());
+      }
+      d->isolate()->object_store()->set_canonical_types(table.Release());
+    }
+
     Type& type = Type::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
     if (Snapshot::IncludesCode(d->kind())) {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type ^= refs.At(id);
-        stub = type.type_test_stub();
-        type.SetTypeTestingStub(stub);  // Update type_test_stub_entry_point_
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type ^= refs.At(id);
         stub = type.type_test_stub();
         type.SetTypeTestingStub(stub);  // Update type_test_stub_entry_point_
       }
     } else {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type ^= refs.At(id);
-        stub = TypeTestingStubGenerator::DefaultCodeForType(type);
-        type.SetTypeTestingStub(stub);
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type ^= refs.At(id);
         stub = TypeTestingStubGenerator::DefaultCodeForType(type);
@@ -3638,20 +3636,6 @@
       }
     }
   }
-
- private:
-  void ReadType(Deserializer* d, TypePtr type, bool is_canonical) {
-    Deserializer::InitializeHeader(type, kTypeCid, Type::InstanceSize(),
-                                   is_canonical);
-    ReadFromTo(type);
-    type->ptr()->token_pos_ = d->ReadTokenPosition();
-    const uint8_t combined = d->Read<uint8_t>();
-    type->ptr()->type_state_ = combined >> kNullabilityBitSize;
-    type->ptr()->nullability_ = combined & kNullabilityBitMask;
-  }
-
-  intptr_t canonical_start_index_;
-  intptr_t canonical_stop_index_;
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -3695,7 +3679,7 @@
   TypeRefDeserializationCluster() {}
   ~TypeRefDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3705,7 +3689,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeRefPtr type = static_cast<TypeRefPtr>(d->Ref(id));
       Deserializer::InitializeHeader(type, kTypeRefCid,
@@ -3714,7 +3698,7 @@
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     TypeRef& type_ref = TypeRef::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
@@ -3743,24 +3727,14 @@
 
   void Trace(Serializer* s, ObjectPtr object) {
     TypeParameterPtr type = TypeParameter::RawCast(object);
-    if (type->ptr()->IsCanonical()) {
-      canonical_objects_.Add(type);
-    } else {
-      objects_.Add(type);
-    }
+    objects_.Add(type);
 
     PushFromTo(type);
   }
 
   void WriteAlloc(Serializer* s) {
     s->WriteCid(kTypeParameterCid);
-    intptr_t count = canonical_objects_.length();
-    s->WriteUnsigned(count);
-    for (intptr_t i = 0; i < count; i++) {
-      TypeParameterPtr type = canonical_objects_[i];
-      s->AssignRef(type);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     s->WriteUnsigned(count);
     for (intptr_t i = 0; i < count; i++) {
       TypeParameterPtr type = objects_[i];
@@ -3769,11 +3743,7 @@
   }
 
   void WriteFill(Serializer* s) {
-    intptr_t count = canonical_objects_.length();
-    for (intptr_t i = 0; i < count; i++) {
-      WriteTypeParameter(s, canonical_objects_[i]);
-    }
-    count = objects_.length();
+    intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       WriteTypeParameter(s, objects_[i]);
     }
@@ -3798,7 +3768,6 @@
     s->Write<uint8_t>(combined);
   }
 
-  GrowableArray<TypeParameterPtr> canonical_objects_;
   GrowableArray<TypeParameterPtr> objects_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -3808,18 +3777,10 @@
   TypeParameterDeserializationCluster() {}
   ~TypeParameterDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
-    canonical_start_index_ = d->next_index();
-    PageSpace* old_space = d->heap()->old_space();
-    intptr_t count = d->ReadUnsigned();
-    for (intptr_t i = 0; i < count; i++) {
-      d->AssignRef(
-          AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
-    }
-    canonical_stop_index_ = d->next_index();
-
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
-    count = d->ReadUnsigned();
+    PageSpace* old_space = d->heap()->old_space();
+    const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
       d->AssignRef(
           AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
@@ -3827,31 +3788,42 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
-    for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-         id++) {
-      TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
-      ReadTypeParameter(d, type, /* is_canonical = */ true);
-    }
-
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
-      ReadTypeParameter(d, type, /* is_canonical = */ false);
+      Deserializer::InitializeHeader(
+          type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
+      ReadFromTo(type);
+      type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
+      type->ptr()->token_pos_ = d->ReadTokenPosition();
+      type->ptr()->index_ = d->Read<int16_t>();
+      const uint8_t combined = d->Read<uint8_t>();
+      type->ptr()->flags_ = combined >> kNullabilityBitSize;
+      type->ptr()->nullability_ = combined & kNullabilityBitMask;
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalTypeParameterSet table(
+          d->zone(), d->isolate()->object_store()->canonical_type_parameters());
+      TypeParameter& type_param = TypeParameter::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        type_param ^= refs.At(i);
+        ASSERT(type_param.IsCanonical());
+        if (!type_param.IsDeclaration()) {
+          bool present = table.Insert(type_param);
+          ASSERT(!present);
+        }
+      }
+      d->isolate()->object_store()->set_canonical_type_parameters(
+          table.Release());
+    }
+
     TypeParameter& type_param = TypeParameter::Handle(d->zone());
     Code& stub = Code::Handle(d->zone());
 
     if (Snapshot::IncludesCode(d->kind())) {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type_param ^= refs.At(id);
-        stub = type_param.type_test_stub();
-        type_param.SetTypeTestingStub(
-            stub);  // Update type_test_stub_entry_point_
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type_param ^= refs.At(id);
         stub = type_param.type_test_stub();
@@ -3859,12 +3831,6 @@
             stub);  // Update type_test_stub_entry_point_
       }
     } else {
-      for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
-           id++) {
-        type_param ^= refs.At(id);
-        stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
-        type_param.SetTypeTestingStub(stub);
-      }
       for (intptr_t id = start_index_; id < stop_index_; id++) {
         type_param ^= refs.At(id);
         stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
@@ -3872,24 +3838,6 @@
       }
     }
   }
-
- private:
-  void ReadTypeParameter(Deserializer* d,
-                         TypeParameterPtr type,
-                         bool is_canonical) {
-    Deserializer::InitializeHeader(type, kTypeParameterCid,
-                                   TypeParameter::InstanceSize(), is_canonical);
-    ReadFromTo(type);
-    type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
-    type->ptr()->token_pos_ = d->ReadTokenPosition();
-    type->ptr()->index_ = d->Read<int16_t>();
-    const uint8_t combined = d->Read<uint8_t>();
-    type->ptr()->flags_ = combined >> kNullabilityBitSize;
-    type->ptr()->nullability_ = combined & kNullabilityBitMask;
-  }
-
-  intptr_t canonical_start_index_;
-  intptr_t canonical_stop_index_;
 };
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -3919,7 +3867,6 @@
     for (intptr_t i = 0; i < count; i++) {
       ClosurePtr closure = objects_[i];
       AutoTraceObject(closure);
-      s->Write<bool>(closure->ptr()->IsCanonical());
       WriteFromTo(closure);
     }
   }
@@ -3934,7 +3881,7 @@
   ClosureDeserializationCluster() {}
   ~ClosureDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -3944,10 +3891,9 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClosurePtr closure = static_cast<ClosurePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(closure, kClosureCid,
                                      Closure::InstanceSize(), is_canonical);
       ReadFromTo(closure);
@@ -3979,14 +3925,12 @@
       SmiPtr smi = smis_[i];
       s->AssignRef(smi);
       AutoTraceObject(smi);
-      s->Write<bool>(true);
       s->Write<int64_t>(Smi::Value(smi));
     }
     for (intptr_t i = 0; i < mints_.length(); i++) {
       MintPtr mint = mints_[i];
       s->AssignRef(mint);
       AutoTraceObject(mint);
-      s->Write<bool>(mint->ptr()->IsCanonical());
       s->Write<int64_t>(mint->ptr()->value_);
     }
   }
@@ -4004,13 +3948,12 @@
   MintDeserializationCluster() {}
   ~MintDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     start_index_ = d->next_index();
     const intptr_t count = d->ReadUnsigned();
     for (intptr_t i = 0; i < count; i++) {
-      bool is_canonical = d->Read<bool>();
       int64_t value = d->Read<int64_t>();
       if (Smi::IsValid(value)) {
         d->AssignRef(Smi::New(value));
@@ -4026,17 +3969,20 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {}
+  void ReadFill(Deserializer* d, bool is_canonical) {}
 
-  void PostLoad(Deserializer* d, const Array& refs) {
-    const Class& mint_cls = Class::Handle(
-        d->zone(), Isolate::Current()->object_store()->mint_class());
-    mint_cls.set_constants(Object::empty_array());
-    Object& number = Object::Handle(d->zone());
-    for (intptr_t i = start_index_; i < stop_index_; i++) {
-      number = refs.At(i);
-      if (number.IsMint() && number.IsCanonical()) {
-        mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number));
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      const Class& mint_cls = Class::Handle(
+          d->zone(), Isolate::Current()->object_store()->mint_class());
+      mint_cls.set_constants(Object::null_array());
+      Object& number = Object::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        number = refs.At(i);
+        if (number.IsMint()) {
+          ASSERT(number.IsCanonical());
+          mint_cls.InsertCanonicalMint(d->zone(), Mint::Cast(number));
+        }
       }
     }
   }
@@ -4068,7 +4014,6 @@
     for (intptr_t i = 0; i < count; i++) {
       DoublePtr dbl = objects_[i];
       AutoTraceObject(dbl);
-      s->Write<bool>(dbl->ptr()->IsCanonical());
       s->Write<double>(dbl->ptr()->value_);
     }
   }
@@ -4083,7 +4028,7 @@
   DoubleDeserializationCluster() {}
   ~DoubleDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4093,10 +4038,9 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       DoublePtr dbl = static_cast<DoublePtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(dbl, kDoubleCid, Double::InstanceSize(),
                                      is_canonical);
       dbl->ptr()->value_ = d->Read<double>();
@@ -4132,7 +4076,6 @@
     for (intptr_t i = 0; i < count; i++) {
       GrowableObjectArrayPtr array = objects_[i];
       AutoTraceObject(array);
-      s->Write<bool>(array->ptr()->IsCanonical());
       WriteFromTo(array);
     }
   }
@@ -4148,7 +4091,7 @@
   GrowableObjectArrayDeserializationCluster() {}
   ~GrowableObjectArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4159,11 +4102,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       GrowableObjectArrayPtr list =
           static_cast<GrowableObjectArrayPtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(list, kGrowableObjectArrayCid,
                                      GrowableObjectArray::InstanceSize(),
                                      is_canonical);
@@ -4205,7 +4147,6 @@
       AutoTraceObject(data);
       const intptr_t length = Smi::Value(data->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(data->ptr()->IsCanonical());
       uint8_t* cdata = reinterpret_cast<uint8_t*>(data->ptr()->data());
       s->WriteBytes(cdata, length * element_size);
     }
@@ -4222,7 +4163,7 @@
   explicit TypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~TypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4235,13 +4176,12 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t element_size = TypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataPtr data = static_cast<TypedDataPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       const intptr_t length_in_bytes = length * element_size;
       Deserializer::InitializeHeader(
           data, cid_, TypedData::InstanceSize(length_in_bytes), is_canonical);
@@ -4285,7 +4225,6 @@
     for (intptr_t i = 0; i < count; i++) {
       TypedDataViewPtr view = objects_[i];
       AutoTraceObject(view);
-      s->Write<bool>(view->ptr()->IsCanonical());
       WriteFromTo(view);
     }
   }
@@ -4301,7 +4240,7 @@
   explicit TypedDataViewDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~TypedDataViewDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4312,17 +4251,16 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TypedDataViewPtr view = static_cast<TypedDataViewPtr>(d->Ref(id));
-      const bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(view, cid_, TypedDataView::InstanceSize(),
                                      is_canonical);
       ReadFromTo(view);
     }
   }
 
-  void PostLoad(Deserializer* d, const Array& refs) {
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     auto& view = TypedDataView::Handle(d->zone());
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       view ^= refs.At(id);
@@ -4344,7 +4282,6 @@
   void Trace(Serializer* s, ObjectPtr object) {
     ExternalTypedDataPtr data = ExternalTypedData::RawCast(object);
     objects_.Add(data);
-    ASSERT(!data->ptr()->IsCanonical());
   }
 
   void WriteAlloc(Serializer* s) {
@@ -4382,7 +4319,7 @@
   explicit ExternalTypedDataDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~ExternalTypedDataDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4393,7 +4330,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     intptr_t element_size = ExternalTypedData::ElementSizeInBytes(cid_);
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
@@ -4454,7 +4391,7 @@
   StackTraceDeserializationCluster() {}
   ~StackTraceDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4465,7 +4402,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       StackTracePtr trace = static_cast<StackTracePtr>(d->Ref(id));
       Deserializer::InitializeHeader(trace, kStackTraceCid,
@@ -4519,7 +4456,7 @@
   RegExpDeserializationCluster() {}
   ~RegExpDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4529,7 +4466,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       RegExpPtr regexp = static_cast<RegExpPtr>(d->Ref(id));
       Deserializer::InitializeHeader(regexp, kRegExpCid,
@@ -4583,7 +4520,7 @@
   WeakPropertyDeserializationCluster() {}
   ~WeakPropertyDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4594,7 +4531,7 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       WeakPropertyPtr property = static_cast<WeakPropertyPtr>(d->Ref(id));
       Deserializer::InitializeHeader(property, kWeakPropertyCid,
@@ -4644,7 +4581,6 @@
     for (intptr_t i = 0; i < count; i++) {
       LinkedHashMapPtr map = objects_[i];
       AutoTraceObject(map);
-      s->Write<bool>(map->ptr()->IsCanonical());
 
       WriteField(map, type_arguments_);
 
@@ -4678,7 +4614,7 @@
   LinkedHashMapDeserializationCluster() {}
   ~LinkedHashMapDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4689,12 +4625,11 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     PageSpace* old_space = d->heap()->old_space();
 
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       LinkedHashMapPtr map = static_cast<LinkedHashMapPtr>(d->Ref(id));
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(
           map, kLinkedHashMapCid, LinkedHashMap::InstanceSize(), is_canonical);
 
@@ -4766,7 +4701,6 @@
       AutoTraceObject(array);
       const intptr_t length = Smi::Value(array->ptr()->length_);
       s->WriteUnsigned(length);
-      s->Write<bool>(array->ptr()->IsCanonical());
       WriteField(array, type_arguments_);
       for (intptr_t j = 0; j < length; j++) {
         s->WriteElementRef(array->ptr()->data()[j], j);
@@ -4785,7 +4719,7 @@
   explicit ArrayDeserializationCluster(intptr_t cid) : cid_(cid) {}
   ~ArrayDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4797,11 +4731,10 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ArrayPtr array = static_cast<ArrayPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(array, cid_, Array::InstanceSize(length),
                                      is_canonical);
       array->ptr()->type_arguments_ =
@@ -4847,10 +4780,8 @@
       OneByteStringPtr str = objects_[i];
       AutoTraceObject(str);
       const intptr_t length = Smi::Value(str->ptr()->length_);
+      ASSERT(length <= compiler::target::kSmiMax);
       s->WriteUnsigned(length);
-      s->Write<bool>(str->ptr()->IsCanonical());
-      intptr_t hash = String::GetCachedHash(str);
-      s->Write<int32_t>(hash);
       s->WriteBytes(str->ptr()->data(), length);
     }
   }
@@ -4865,7 +4796,7 @@
   OneByteStringDeserializationCluster() {}
   ~OneByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4877,19 +4808,36 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       OneByteStringPtr str = static_cast<OneByteStringPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kOneByteStringCid,
                                      OneByteString::InstanceSize(length),
                                      is_canonical);
       str->ptr()->length_ = Smi::New(length);
-      String::SetCachedHash(str, d->Read<int32_t>());
+      StringHasher hasher;
       for (intptr_t j = 0; j < length; j++) {
-        str->ptr()->data()[j] = d->Read<uint8_t>();
+        uint8_t code_unit = d->Read<uint8_t>();
+        str->ptr()->data()[j] = code_unit;
+        hasher.Add(code_unit);
       }
+      String::SetCachedHash(str, hasher.Finalize());
+    }
+  }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalStringSet table(d->zone(),
+                               d->isolate()->object_store()->symbol_table());
+      String& str = String::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        str ^= refs.At(i);
+        ASSERT(str.IsCanonical());
+        bool present = table.Insert(str);
+        ASSERT(!present);
+      }
+      d->isolate()->object_store()->set_symbol_table(table.Release());
     }
   }
 };
@@ -4924,10 +4872,8 @@
       TwoByteStringPtr str = objects_[i];
       AutoTraceObject(str);
       const intptr_t length = Smi::Value(str->ptr()->length_);
+      ASSERT(length <= (compiler::target::kSmiMax / 2));
       s->WriteUnsigned(length);
-      s->Write<bool>(str->ptr()->IsCanonical());
-      intptr_t hash = String::GetCachedHash(str);
-      s->Write<int32_t>(hash);
       s->WriteBytes(reinterpret_cast<uint8_t*>(str->ptr()->data()), length * 2);
     }
   }
@@ -4942,7 +4888,7 @@
   TwoByteStringDeserializationCluster() {}
   ~TwoByteStringDeserializationCluster() {}
 
-  void ReadAlloc(Deserializer* d) {
+  void ReadAlloc(Deserializer* d, bool is_canonical) {
     start_index_ = d->next_index();
     PageSpace* old_space = d->heap()->old_space();
     const intptr_t count = d->ReadUnsigned();
@@ -4954,18 +4900,37 @@
     stop_index_ = d->next_index();
   }
 
-  void ReadFill(Deserializer* d) {
+  void ReadFill(Deserializer* d, bool is_canonical) {
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       TwoByteStringPtr str = static_cast<TwoByteStringPtr>(d->Ref(id));
       const intptr_t length = d->ReadUnsigned();
-      bool is_canonical = d->Read<bool>();
       Deserializer::InitializeHeader(str, kTwoByteStringCid,
                                      TwoByteString::InstanceSize(length),
                                      is_canonical);
       str->ptr()->length_ = Smi::New(length);
-      String::SetCachedHash(str, d->Read<int32_t>());
-      uint8_t* cdata = reinterpret_cast<uint8_t*>(str->ptr()->data());
-      d->ReadBytes(cdata, length * 2);
+      StringHasher hasher;
+      for (intptr_t j = 0; j < length; j++) {
+        uint16_t code_unit = d->Read<uint8_t>();
+        code_unit = code_unit | (d->Read<uint8_t>() << 8);
+        str->ptr()->data()[j] = code_unit;
+        hasher.Add(code_unit);
+      }
+      String::SetCachedHash(str, hasher.Finalize());
+    }
+  }
+
+  void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
+    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+      CanonicalStringSet table(d->zone(),
+                               d->isolate()->object_store()->symbol_table());
+      String& str = String::Handle(d->zone());
+      for (intptr_t i = start_index_; i < stop_index_; i++) {
+        str ^= refs.At(i);
+        ASSERT(str.IsCanonical());
+        bool present = table.Insert(str);
+        ASSERT(!present);
+      }
+      d->isolate()->object_store()->set_symbol_table(table.Release());
     }
   }
 };
@@ -5194,14 +5159,43 @@
 
 class ProgramSerializationRoots : public SerializationRoots {
  public:
-  ProgramSerializationRoots(intptr_t num_base_objects,
+  ProgramSerializationRoots(ZoneGrowableArray<Object*>* base_objects,
                             ObjectStore* object_store)
-      : num_base_objects_(num_base_objects),
+      : base_objects_(base_objects),
         object_store_(object_store),
-        dispatch_table_entries_(Array::Handle()) {}
+        saved_symbol_table_(Array::Handle()),
+        saved_canonical_types_(Array::Handle()),
+        saved_canonical_type_parameters_(Array::Handle()),
+        saved_canonical_type_arguments_(Array::Handle()),
+        dispatch_table_entries_(Array::Handle()) {
+    saved_symbol_table_ = object_store->symbol_table();
+    object_store->set_symbol_table(
+        Array::Handle(HashTables::New<CanonicalStringSet>(4)));
+
+    saved_canonical_types_ = object_store->canonical_types();
+    object_store->set_canonical_types(
+        Array::Handle(HashTables::New<CanonicalTypeSet>(4)));
+
+    saved_canonical_type_parameters_ =
+        object_store->canonical_type_parameters();
+    object_store->set_canonical_type_parameters(
+        Array::Handle(HashTables::New<CanonicalTypeParameterSet>(4)));
+
+    saved_canonical_type_arguments_ = object_store->canonical_type_arguments();
+    object_store->set_canonical_type_arguments(
+        Array::Handle(HashTables::New<CanonicalTypeArgumentsSet>(4)));
+  }
+  ~ProgramSerializationRoots() {
+    object_store_->set_symbol_table(saved_symbol_table_);
+    object_store_->set_canonical_types(saved_canonical_types_);
+    object_store_->set_canonical_type_parameters(
+        saved_canonical_type_parameters_);
+    object_store_->set_canonical_type_arguments(
+        saved_canonical_type_arguments_);
+  }
 
   void AddBaseObjects(Serializer* s) {
-    if (num_base_objects_ == 0) {
+    if (base_objects_ == nullptr) {
       // Not writing a new vm isolate: use the one this VM was loaded from.
       const Array& base_objects = Object::vm_isolate_snapshot_object_table();
       for (intptr_t i = kFirstReference; i < base_objects.Length(); i++) {
@@ -5209,7 +5203,9 @@
       }
     } else {
       // Base objects carried over from WriteVMSnapshot.
-      s->CarryOverBaseObjects(num_base_objects_);
+      for (intptr_t i = 0; i < base_objects_->length(); i++) {
+        s->AddBaseObject((*base_objects_)[i]->raw());
+      }
     }
   }
 
@@ -5249,8 +5245,12 @@
   }
 
  private:
-  intptr_t num_base_objects_;
+  ZoneGrowableArray<Object*>* base_objects_;
   ObjectStore* object_store_;
+  Array& saved_symbol_table_;
+  Array& saved_canonical_types_;
+  Array& saved_canonical_type_parameters_;
+  Array& saved_canonical_type_arguments_;
   Array& dispatch_table_entries_;
 };
 #endif  // !DART_PRECOMPILED_RUNTIME
@@ -5309,9 +5309,10 @@
       : unit_(unit) {}
 
   void AddBaseObjects(Serializer* s) {
-    intptr_t num_base_objects = unit_->parent()->num_objects();
-    ASSERT(num_base_objects != 0);
-    s->CarryOverBaseObjects(num_base_objects);
+    ZoneGrowableArray<Object*>* objects = unit_->parent()->objects();
+    for (intptr_t i = 0; i < objects->length(); i++) {
+      s->AddBaseObject(objects->At(i)->raw());
+    }
   }
 
   void PushRoots(Serializer* s) {
@@ -5420,9 +5421,7 @@
 
 Serializer::Serializer(Thread* thread,
                        Snapshot::Kind kind,
-                       uint8_t** buffer,
-                       ReAlloc alloc,
-                       intptr_t initial_size,
+                       NonStreamingWriteStream* stream,
                        ImageWriter* image_writer,
                        bool vm,
                        V8SnapshotProfileWriter* profile_writer)
@@ -5430,9 +5429,10 @@
       heap_(thread->isolate()->heap()),
       zone_(thread->zone()),
       kind_(kind),
-      stream_(buffer, alloc, initial_size),
+      stream_(stream),
       image_writer_(image_writer),
-      clusters_by_cid_(NULL),
+      canonical_clusters_by_cid_(nullptr),
+      clusters_by_cid_(nullptr),
       stack_(),
       num_cids_(0),
       num_tlc_cids_(0),
@@ -5455,9 +5455,13 @@
 {
   num_cids_ = thread->isolate()->class_table()->NumCids();
   num_tlc_cids_ = thread->isolate()->class_table()->NumTopLevelCids();
+  canonical_clusters_by_cid_ = new SerializationCluster*[num_cids_];
+  for (intptr_t i = 0; i < num_cids_; i++) {
+    canonical_clusters_by_cid_[i] = nullptr;
+  }
   clusters_by_cid_ = new SerializationCluster*[num_cids_];
   for (intptr_t i = 0; i < num_cids_; i++) {
-    clusters_by_cid_[i] = NULL;
+    clusters_by_cid_[i] = nullptr;
   }
   if (profile_writer_ != nullptr) {
     offsets_table_ = new (zone_) OffsetsTable(zone_);
@@ -5465,9 +5469,62 @@
 }
 
 Serializer::~Serializer() {
+  delete[] canonical_clusters_by_cid_;
   delete[] clusters_by_cid_;
 }
 
+void Serializer::AddBaseObject(ObjectPtr base_object,
+                               const char* type,
+                               const char* name) {
+  intptr_t ref = AssignRef(base_object);
+  num_base_objects_++;
+
+  if ((profile_writer_ != nullptr) && (type != nullptr)) {
+    if (name == nullptr) {
+      name = "<base object>";
+    }
+    profile_writer_->SetObjectTypeAndName(
+        {V8SnapshotProfileWriter::kSnapshot, ref}, type, name);
+    profile_writer_->AddRoot({V8SnapshotProfileWriter::kSnapshot, ref});
+  }
+}
+
+intptr_t Serializer::AssignRef(ObjectPtr object) {
+  ASSERT(IsAllocatedReference(next_ref_index_));
+  if (object->IsHeapObject()) {
+    // The object id weak table holds image offsets for Instructions instead
+    // of ref indices.
+    ASSERT(!object->IsInstructions());
+    heap_->SetObjectId(object, next_ref_index_);
+    ASSERT(heap_->GetObjectId(object) == next_ref_index_);
+  } else {
+    SmiPtr smi = Smi::RawCast(object);
+    SmiObjectIdPair* existing_pair = smi_ids_.Lookup(smi);
+    if (existing_pair != NULL) {
+      ASSERT(existing_pair->id_ == kUnallocatedReference);
+      existing_pair->id_ = next_ref_index_;
+    } else {
+      SmiObjectIdPair new_pair;
+      new_pair.smi_ = smi;
+      new_pair.id_ = next_ref_index_;
+      smi_ids_.Insert(new_pair);
+    }
+  }
+
+  objects_->Add(&Object::ZoneHandle(object));
+
+  return next_ref_index_++;
+}
+
+intptr_t Serializer::AssignArtificialRef(ObjectPtr object) {
+  ASSERT(object.IsHeapObject());
+  const intptr_t ref = -(next_ref_index_++);
+  ASSERT(IsArtificialReference(ref));
+  heap_->SetObjectId(object, ref);
+  ASSERT(heap_->GetObjectId(object) == ref);
+  return ref;
+}
+
 void Serializer::FlushBytesWrittenToRoot() {
 #if defined(DART_PRECOMPILER)
   if (profile_writer_ != nullptr) {
@@ -5475,8 +5532,8 @@
     // All bytes between objects are attributed into root node.
     profile_writer_->AttributeBytesTo(
         V8SnapshotProfileWriter::ArtificialRootId(),
-        stream_.Position() - object_currently_writing_.stream_start_);
-    object_currently_writing_.stream_start_ = stream_.Position();
+        stream_->Position() - object_currently_writing_.stream_start_);
+    object_currently_writing_.stream_start_ = stream_->Position();
   }
 #endif
 }
@@ -5519,7 +5576,7 @@
   FlushBytesWrittenToRoot();
   object_currently_writing_.object_ = obj;
   object_currently_writing_.id_ = id;
-  object_currently_writing_.stream_start_ = stream_.Position();
+  object_currently_writing_.stream_start_ = stream_->Position();
   object_currently_writing_.cid_ = cid;
   profile_writer_->SetObjectTypeAndName(
       {V8SnapshotProfileWriter::kSnapshot, id}, type, name);
@@ -5530,9 +5587,9 @@
     ASSERT(IsAllocatedReference(object_currently_writing_.id_));
     profile_writer_->AttributeBytesTo(
         {V8SnapshotProfileWriter::kSnapshot, object_currently_writing_.id_},
-        stream_.Position() - object_currently_writing_.stream_start_);
+        stream_->Position() - object_currently_writing_.stream_start_);
     object_currently_writing_ = ProfilingObject();
-    object_currently_writing_.stream_start_ = stream_.Position();
+    object_currently_writing_.stream_start_ = stream_->Position();
   }
 }
 
@@ -5622,10 +5679,6 @@
       return "CodeSourceMap";
     case kCompressedStackMapsCid:
       return "CompressedStackMaps";
-    case kOneByteStringCid:
-      return "OneByteString";
-    case kTwoByteStringCid:
-      return "TwoByteString";
     default:
       return nullptr;
   }
@@ -5908,23 +5961,31 @@
 
 void Serializer::Trace(ObjectPtr object) {
   intptr_t cid;
+  bool is_canonical;
   if (!object->IsHeapObject()) {
     // Smis are merged into the Mint cluster because Smis for the writer might
     // become Mints for the reader and vice versa.
     cid = kMintCid;
+    is_canonical = true;
   } else {
     cid = object->GetClassId();
+    is_canonical = object->ptr()->IsCanonical();
   }
 
-  SerializationCluster* cluster = clusters_by_cid_[cid];
-  if (cluster == NULL) {
+  SerializationCluster* cluster =
+      is_canonical ? canonical_clusters_by_cid_[cid] : clusters_by_cid_[cid];
+  if (cluster == nullptr) {
     cluster = NewClusterForClass(cid);
-    if (cluster == NULL) {
+    if (cluster == nullptr) {
       UnexpectedObject(object, "No serialization cluster defined");
     }
-    clusters_by_cid_[cid] = cluster;
+    if (is_canonical) {
+      canonical_clusters_by_cid_[cid] = cluster;
+    } else {
+      clusters_by_cid_[cid] = cluster;
+    }
   }
-  ASSERT(cluster != NULL);
+  ASSERT(cluster != nullptr);
 
 #if defined(SNAPSHOT_BACKTRACE)
   current_parent_ = object;
@@ -5994,7 +6055,7 @@
   }
 }
 
-intptr_t Serializer::Serialize(SerializationRoots* roots) {
+ZoneGrowableArray<Object*>* Serializer::Serialize(SerializationRoots* roots) {
   roots->AddBaseObjects(this);
 
   NoSafepointScope no_safepoint;
@@ -6005,11 +6066,16 @@
     Trace(stack_.RemoveLast());
   }
 
-  intptr_t num_clusters = 0;
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      num_clusters++;
+  GrowableArray<SerializationCluster*> canonical_clusters;
+  for (intptr_t cid = 0; cid < num_cids_; cid++) {
+    if (canonical_clusters_by_cid_[cid] != nullptr) {
+      canonical_clusters.Add(canonical_clusters_by_cid_[cid]);
+    }
+  }
+  GrowableArray<SerializationCluster*> clusters;
+  for (intptr_t cid = 0; cid < num_cids_; cid++) {
+    if (clusters_by_cid_[cid] != nullptr) {
+      clusters.Add(clusters_by_cid_[cid]);
     }
   }
 
@@ -6036,27 +6102,27 @@
 
   WriteUnsigned(num_base_objects_);
   WriteUnsigned(num_objects);
-  WriteUnsigned(num_clusters);
+  WriteUnsigned(canonical_clusters.length());
+  WriteUnsigned(clusters.length());
   WriteUnsigned(field_table_->NumFieldIds());
 
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      cluster->WriteAndMeasureAlloc(this);
+  for (SerializationCluster* cluster : canonical_clusters) {
+    cluster->WriteAndMeasureAlloc(this);
 #if defined(DEBUG)
-      Write<int32_t>(next_ref_index_);
+    Write<int32_t>(next_ref_index_);
 #endif
-    }
+  }
+  for (SerializationCluster* cluster : clusters) {
+    cluster->WriteAndMeasureAlloc(this);
+#if defined(DEBUG)
+    Write<int32_t>(next_ref_index_);
+#endif
   }
 
   // We should have assigned a ref to every object we pushed.
   ASSERT((next_ref_index_ - 1) == num_objects);
-
-  if (loading_units_ != nullptr) {
-    LoadingUnitSerializationData* unit =
-        (*loading_units_)[current_loading_unit_id_];
-    unit->set_num_objects(num_objects);
-  }
+  // And recorded them all in [objects_].
+  ASSERT(objects_->length() == num_objects);
 
 #if defined(DART_PRECOMPILER)
   // When writing snapshot profile, we want to retain some of the program
@@ -6068,14 +6134,17 @@
   }
 #endif
 
-  for (intptr_t cid = 1; cid < num_cids_; cid++) {
-    SerializationCluster* cluster = clusters_by_cid_[cid];
-    if (cluster != NULL) {
-      cluster->WriteAndMeasureFill(this);
+  for (SerializationCluster* cluster : canonical_clusters) {
+    cluster->WriteAndMeasureFill(this);
 #if defined(DEBUG)
-      Write<int32_t>(kSectionMarker);
+    Write<int32_t>(kSectionMarker);
 #endif
-    }
+  }
+  for (SerializationCluster* cluster : clusters) {
+    cluster->WriteAndMeasureFill(this);
+#if defined(DEBUG)
+    Write<int32_t>(kSectionMarker);
+#endif
   }
 
   roots->WriteRoots(this);
@@ -6085,16 +6154,12 @@
 #endif
 
   FlushBytesWrittenToRoot();
-  object_currently_writing_.stream_start_ = stream_.Position();
+  object_currently_writing_.stream_start_ = stream_->Position();
 
   PrintSnapshotSizes();
 
-  // Note we are not clearing the object id table. The full ref table
-  // of the vm isolate snapshot serves as the base objects for the
-  // regular isolate snapshot.
-
-  // Return the number of objects, -1 accounts for unused ref 0.
-  return next_ref_index_ - kFirstReference;
+  heap()->ResetObjectIdTable();
+  return objects_;
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -6216,7 +6281,7 @@
   }
   dispatch_table_size_ = bytes_written() - bytes_before;
 
-  object_currently_writing_.stream_start_ = stream_.Position();
+  object_currently_writing_.stream_start_ = stream_->Position();
   // If any bytes were written for the dispatch table, add it to the profile.
   if (dispatch_table_size_ > 0 && profile_writer_ != nullptr) {
     // Grab an unused ref index for a unique object id for the dispatch table.
@@ -6313,21 +6378,23 @@
       zone_(thread->zone()),
       kind_(kind),
       stream_(buffer, size),
-      image_reader_(NULL),
+      image_reader_(nullptr),
       refs_(nullptr),
       next_ref_index_(kFirstReference),
       previous_text_offset_(0),
-      clusters_(NULL),
+      canonical_clusters_(nullptr),
+      clusters_(nullptr),
       field_table_(thread->isolate()->field_table()) {
   if (Snapshot::IncludesCode(kind)) {
-    ASSERT(instructions_buffer != NULL);
-    ASSERT(data_buffer != NULL);
+    ASSERT(instructions_buffer != nullptr);
+    ASSERT(data_buffer != nullptr);
     image_reader_ = new (zone_) ImageReader(data_buffer, instructions_buffer);
   }
   stream_.SetPosition(offset);
 }
 
 Deserializer::~Deserializer() {
+  delete[] canonical_clusters_;
   delete[] clusters_;
 }
 
@@ -6352,8 +6419,6 @@
       case kPcDescriptorsCid:
       case kCodeSourceMapCid:
       case kCompressedStackMapsCid:
-      case kOneByteStringCid:
-      case kTwoByteStringCid:
         return new (Z) RODataDeserializationCluster();
     }
   }
@@ -6766,9 +6831,11 @@
   Array& refs = Array::Handle(zone_);
   num_base_objects_ = ReadUnsigned();
   num_objects_ = ReadUnsigned();
+  num_canonical_clusters_ = ReadUnsigned();
   num_clusters_ = ReadUnsigned();
   const intptr_t field_table_len = ReadUnsigned();
 
+  canonical_clusters_ = new DeserializationCluster*[num_canonical_clusters_];
   clusters_ = new DeserializationCluster*[num_clusters_];
   refs_ = Array::New(num_objects_ + kFirstReference, Heap::kOld);
   if (field_table_len > 0) {
@@ -6788,9 +6855,17 @@
              num_base_objects_, next_ref_index_ - kFirstReference);
     }
 
+    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+      canonical_clusters_[i] = ReadCluster();
+      canonical_clusters_[i]->ReadAlloc(this, /*is_canonical*/ true);
+#if defined(DEBUG)
+      intptr_t serializers_next_ref_index_ = Read<int32_t>();
+      ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
+#endif
+    }
     for (intptr_t i = 0; i < num_clusters_; i++) {
       clusters_[i] = ReadCluster();
-      clusters_[i]->ReadAlloc(this);
+      clusters_[i]->ReadAlloc(this, /*is_canonical*/ false);
 #if defined(DEBUG)
       intptr_t serializers_next_ref_index_ = Read<int32_t>();
       ASSERT_EQUAL(serializers_next_ref_index_, next_ref_index_);
@@ -6800,11 +6875,18 @@
     // We should have completely filled the ref array.
     ASSERT_EQUAL(next_ref_index_ - kFirstReference, num_objects_);
 
-    for (intptr_t i = 0; i < num_clusters_; i++) {
-      clusters_[i]->ReadFill(this);
+    for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+      canonical_clusters_[i]->ReadFill(this, /*is_canonical*/ true);
 #if defined(DEBUG)
-    int32_t section_marker = Read<int32_t>();
-    ASSERT(section_marker == kSectionMarker);
+      int32_t section_marker = Read<int32_t>();
+      ASSERT(section_marker == kSectionMarker);
+#endif
+    }
+    for (intptr_t i = 0; i < num_clusters_; i++) {
+      clusters_[i]->ReadFill(this, /*is_canonical*/ false);
+#if defined(DEBUG)
+      int32_t section_marker = Read<int32_t>();
+      ASSERT(section_marker == kSectionMarker);
 #endif
     }
 
@@ -6829,23 +6911,30 @@
   }
 #endif
 
+  // TODO(rmacnak): When splitting literals, load clusters requiring
+  // canonicalization first, canonicalize and update the ref array, the load
+  // the remaining clusters to avoid a full heap walk to update references to
+  // the losers of any canonicalization races.
+  for (intptr_t i = 0; i < num_canonical_clusters_; i++) {
+    canonical_clusters_[i]->PostLoad(this, refs, /*is_canonical*/ true);
+  }
+
   for (intptr_t i = 0; i < num_clusters_; i++) {
-    clusters_[i]->PostLoad(this, refs);
+    clusters_[i]->PostLoad(this, refs, /*is_canonical*/ false);
   }
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-FullSnapshotWriter::FullSnapshotWriter(Snapshot::Kind kind,
-                                       uint8_t** vm_snapshot_data_buffer,
-                                       uint8_t** isolate_snapshot_data_buffer,
-                                       ReAlloc alloc,
-                                       ImageWriter* vm_image_writer,
-                                       ImageWriter* isolate_image_writer)
+FullSnapshotWriter::FullSnapshotWriter(
+    Snapshot::Kind kind,
+    NonStreamingWriteStream* vm_snapshot_data,
+    NonStreamingWriteStream* isolate_snapshot_data,
+    ImageWriter* vm_image_writer,
+    ImageWriter* isolate_image_writer)
     : thread_(Thread::Current()),
       kind_(kind),
-      vm_snapshot_data_buffer_(vm_snapshot_data_buffer),
-      isolate_snapshot_data_buffer_(isolate_snapshot_data_buffer),
-      alloc_(alloc),
+      vm_snapshot_data_(vm_snapshot_data),
+      isolate_snapshot_data_(isolate_snapshot_data),
       vm_isolate_snapshot_size_(0),
       isolate_snapshot_size_(0),
       vm_image_writer_(vm_image_writer),
@@ -6854,7 +6943,6 @@
       clustered_isolate_size_(0),
       mapped_data_size_(0),
       mapped_text_size_(0) {
-  ASSERT(alloc_ != NULL);
   ASSERT(isolate() != NULL);
   ASSERT(heap() != NULL);
   ObjectStore* object_store = isolate()->object_store();
@@ -6874,19 +6962,18 @@
 
 FullSnapshotWriter::~FullSnapshotWriter() {}
 
-intptr_t FullSnapshotWriter::WriteVMSnapshot() {
+ZoneGrowableArray<Object*>* FullSnapshotWriter::WriteVMSnapshot() {
   TIMELINE_DURATION(thread(), Isolate, "WriteVMSnapshot");
 
-  ASSERT(vm_snapshot_data_buffer_ != NULL);
-  Serializer serializer(thread(), kind_, vm_snapshot_data_buffer_, alloc_,
-                        kInitialSize, vm_image_writer_, /*vm=*/true,
-                        profile_writer_);
+  ASSERT(vm_snapshot_data_ != nullptr);
+  Serializer serializer(thread(), kind_, vm_snapshot_data_, vm_image_writer_,
+                        /*vm=*/true, profile_writer_);
 
   serializer.ReserveHeader();
   serializer.WriteVersionAndFeatures(true);
   VMSerializationRoots roots(
       Array::Handle(Dart::vm_isolate()->object_store()->symbol_table()));
-  intptr_t num_objects = serializer.Serialize(&roots);
+  ZoneGrowableArray<Object*>* objects = serializer.Serialize(&roots);
   serializer.FillHeader(serializer.kind());
   clustered_vm_size_ = serializer.bytes_written();
 
@@ -6901,17 +6988,17 @@
 
   // The clustered part + the direct mapped data part.
   vm_isolate_snapshot_size_ = serializer.bytes_written();
-  return num_objects;
+  return objects;
 }
 
 void FullSnapshotWriter::WriteProgramSnapshot(
-    intptr_t num_base_objects,
+    ZoneGrowableArray<Object*>* objects,
     GrowableArray<LoadingUnitSerializationData*>* units) {
   TIMELINE_DURATION(thread(), Isolate, "WriteProgramSnapshot");
 
-  Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
-                        kInitialSize, isolate_image_writer_, /*vm=*/false,
-                        profile_writer_);
+  ASSERT(isolate_snapshot_data_ != nullptr);
+  Serializer serializer(thread(), kind_, isolate_snapshot_data_,
+                        isolate_image_writer_, /*vm=*/false, profile_writer_);
   serializer.set_loading_units(units);
   serializer.set_current_loading_unit_id(LoadingUnit::kRootId);
   ObjectStore* object_store = isolate()->object_store();
@@ -6926,8 +7013,11 @@
 
   serializer.ReserveHeader();
   serializer.WriteVersionAndFeatures(false);
-  ProgramSerializationRoots roots(num_base_objects, object_store);
-  serializer.Serialize(&roots);
+  ProgramSerializationRoots roots(objects, object_store);
+  objects = serializer.Serialize(&roots);
+  if (units != nullptr) {
+    (*units)[LoadingUnit::kRootId]->set_objects(objects);
+  }
   serializer.FillHeader(serializer.kind());
   clustered_isolate_size_ = serializer.bytes_written();
 
@@ -6954,9 +7044,8 @@
     uint32_t program_hash) {
   TIMELINE_DURATION(thread(), Isolate, "WriteUnitSnapshot");
 
-  Serializer serializer(thread(), kind_, isolate_snapshot_data_buffer_, alloc_,
-                        kInitialSize, isolate_image_writer_, /*vm=*/false,
-                        profile_writer_);
+  Serializer serializer(thread(), kind_, isolate_snapshot_data_,
+                        isolate_image_writer_, /*vm=*/false, profile_writer_);
   serializer.set_loading_units(units);
   serializer.set_current_loading_unit_id(unit->id());
 
@@ -6965,7 +7054,8 @@
   serializer.Write(program_hash);
 
   UnitSerializationRoots roots(unit);
-  serializer.Serialize(&roots);
+  unit->set_objects(serializer.Serialize(&roots));
+
   serializer.FillHeader(serializer.kind());
   clustered_isolate_size_ = serializer.bytes_written();
 
@@ -6988,16 +7078,15 @@
 
 void FullSnapshotWriter::WriteFullSnapshot(
     GrowableArray<LoadingUnitSerializationData*>* data) {
-  intptr_t num_base_objects;
-  if (vm_snapshot_data_buffer() != NULL) {
-    num_base_objects = WriteVMSnapshot();
-    ASSERT(num_base_objects != 0);
+  ZoneGrowableArray<Object*>* objects;
+  if (vm_snapshot_data_ != nullptr) {
+    objects = WriteVMSnapshot();
   } else {
-    num_base_objects = 0;
+    objects = nullptr;
   }
 
-  if (isolate_snapshot_data_buffer() != NULL) {
-    WriteProgramSnapshot(num_base_objects, data);
+  if (isolate_snapshot_data_ != nullptr) {
+    WriteProgramSnapshot(objects, data);
   }
 
   if (FLAG_print_snapshot_sizes) {
@@ -7026,8 +7115,7 @@
       buffer_(snapshot->Addr()),
       size_(snapshot->length()),
       data_image_(snapshot->DataImage()),
-      instructions_image_(instructions_buffer) {
-}
+      instructions_image_(instructions_buffer) {}
 
 char* SnapshotHeaderReader::InitializeGlobalVMFlagsFromSnapshot(
     const Snapshot* snapshot) {
@@ -7217,12 +7305,8 @@
   // Initialize entries in the VM portion of the BSS segment.
   ASSERT(Snapshot::IncludesCode(kind_));
   Image image(instructions_image_);
-  if (image.bss_offset() != 0) {
-    // The const cast is safe because we're translating from the start of the
-    // instructions (read-only) to the start of the BSS (read-write).
-    uword* const bss_start = const_cast<uword*>(reinterpret_cast<const uword*>(
-        instructions_image_ + image.bss_offset()));
-    BSS::Initialize(thread_, bss_start, /*vm=*/true);
+  if (auto const bss = image.bss()) {
+    BSS::Initialize(thread_, bss, /*vm=*/true);
   }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
@@ -7353,12 +7437,8 @@
   // Initialize entries in the isolate portion of the BSS segment.
   ASSERT(Snapshot::IncludesCode(kind_));
   Image image(instructions_image_);
-  if (image.bss_offset() != 0) {
-    // The const cast is safe because we're translating from the start of the
-    // instructions (read-only) to the start of the BSS (read-write).
-    uword* const bss_start = const_cast<uword*>(reinterpret_cast<const uword*>(
-        instructions_image_ + image.bss_offset()));
-    BSS::Initialize(thread_, bss_start, /*vm=*/false);
+  if (auto const bss = image.bss()) {
+    BSS::Initialize(thread_, bss, /*vm=*/false);
   }
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index 2dd7253..56ba846 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -54,22 +54,28 @@
  public:
   LoadingUnitSerializationData(intptr_t id,
                                LoadingUnitSerializationData* parent)
-      : id_(id), parent_(parent), deferred_objects_(), num_objects_(0) {}
+      : id_(id), parent_(parent), deferred_objects_(), objects_(nullptr) {}
 
   intptr_t id() const { return id_; }
   LoadingUnitSerializationData* parent() const { return parent_; }
-  intptr_t num_objects() const { return num_objects_; }
-  void set_num_objects(intptr_t value) { num_objects_ = value; }
   void AddDeferredObject(CodePtr obj) {
     deferred_objects_.Add(&Code::ZoneHandle(obj));
   }
   GrowableArray<Code*>* deferred_objects() { return &deferred_objects_; }
+  ZoneGrowableArray<Object*>* objects() {
+    ASSERT(objects_ != nullptr);
+    return objects_;
+  }
+  void set_objects(ZoneGrowableArray<Object*>* objects) {
+    ASSERT(objects_ == nullptr);
+    objects_ = objects;
+  }
 
  private:
   intptr_t id_;
   LoadingUnitSerializationData* parent_;
   GrowableArray<Code*> deferred_objects_;
-  intptr_t num_objects_;
+  ZoneGrowableArray<Object*>* objects_;
 };
 
 class SerializationCluster : public ZoneAllocated {
@@ -109,14 +115,16 @@
 
   // Allocate memory for all objects in the cluster and write their addresses
   // into the ref array. Do not touch this memory.
-  virtual void ReadAlloc(Deserializer* deserializer) = 0;
+  virtual void ReadAlloc(Deserializer* deserializer, bool is_canonical) = 0;
 
   // Initialize the cluster's objects. Do not touch the memory of other objects.
-  virtual void ReadFill(Deserializer* deserializer) = 0;
+  virtual void ReadFill(Deserializer* deserializer, bool is_canonical) = 0;
 
   // Complete any action that requires the full graph to be deserialized, such
   // as rehashing.
-  virtual void PostLoad(Deserializer* deserializer, const Array& refs) {}
+  virtual void PostLoad(Deserializer* deserializer,
+                        const Array& refs,
+                        bool is_canonical) {}
 
  protected:
   // The range of the ref array that belongs to this cluster.
@@ -192,9 +200,7 @@
  public:
   Serializer(Thread* thread,
              Snapshot::Kind kind,
-             uint8_t** buffer,
-             ReAlloc alloc,
-             intptr_t initial_size,
+             NonStreamingWriteStream* stream,
              ImageWriter* image_writer_,
              bool vm_,
              V8SnapshotProfileWriter* profile_writer = nullptr);
@@ -202,59 +208,9 @@
 
   void AddBaseObject(ObjectPtr base_object,
                      const char* type = nullptr,
-                     const char* name = nullptr) {
-    intptr_t ref = AssignRef(base_object);
-    num_base_objects_++;
-
-    if (profile_writer_ != nullptr) {
-      if (type == nullptr) {
-        type = "Unknown";
-      }
-      if (name == nullptr) {
-        name = "<base object>";
-      }
-      profile_writer_->SetObjectTypeAndName(
-          {V8SnapshotProfileWriter::kSnapshot, ref}, type, name);
-      profile_writer_->AddRoot({V8SnapshotProfileWriter::kSnapshot, ref});
-    }
-  }
-  void CarryOverBaseObjects(intptr_t num_base_objects) {
-    num_base_objects_ = num_base_objects;
-    next_ref_index_ = num_base_objects + 1;
-  }
-
-  intptr_t AssignRef(ObjectPtr object) {
-    ASSERT(IsAllocatedReference(next_ref_index_));
-    if (object->IsHeapObject()) {
-      // The object id weak table holds image offsets for Instructions instead
-      // of ref indices.
-      ASSERT(!object->IsInstructions());
-      heap_->SetObjectId(object, next_ref_index_);
-      ASSERT(heap_->GetObjectId(object) == next_ref_index_);
-    } else {
-      SmiPtr smi = Smi::RawCast(object);
-      SmiObjectIdPair* existing_pair = smi_ids_.Lookup(smi);
-      if (existing_pair != NULL) {
-        ASSERT(existing_pair->id_ == kUnallocatedReference);
-        existing_pair->id_ = next_ref_index_;
-      } else {
-        SmiObjectIdPair new_pair;
-        new_pair.smi_ = smi;
-        new_pair.id_ = next_ref_index_;
-        smi_ids_.Insert(new_pair);
-      }
-    }
-    return next_ref_index_++;
-  }
-
-  intptr_t AssignArtificialRef(ObjectPtr object) {
-    ASSERT(object.IsHeapObject());
-    const intptr_t ref = -(next_ref_index_++);
-    ASSERT(IsArtificialReference(ref));
-    heap_->SetObjectId(object, ref);
-    ASSERT(heap_->GetObjectId(object) == ref);
-    return ref;
-  }
+                     const char* name = nullptr);
+  intptr_t AssignRef(ObjectPtr object);
+  intptr_t AssignArtificialRef(ObjectPtr object);
 
   void Push(ObjectPtr object);
 
@@ -271,25 +227,25 @@
 
   void ReserveHeader() {
     // Make room for recording snapshot buffer size.
-    stream_.SetPosition(Snapshot::kHeaderSize);
+    stream_->SetPosition(Snapshot::kHeaderSize);
   }
 
   void FillHeader(Snapshot::Kind kind) {
-    Snapshot* header = reinterpret_cast<Snapshot*>(stream_.buffer());
+    Snapshot* header = reinterpret_cast<Snapshot*>(stream_->buffer());
     header->set_magic();
-    header->set_length(stream_.bytes_written());
+    header->set_length(stream_->bytes_written());
     header->set_kind(kind);
   }
 
   void WriteVersionAndFeatures(bool is_vm_snapshot);
 
-  intptr_t Serialize(SerializationRoots* roots);
+  ZoneGrowableArray<Object*>* Serialize(SerializationRoots* roots);
   void PrintSnapshotSizes();
 
   FieldTable* field_table() { return field_table_; }
 
-  WriteStream* stream() { return &stream_; }
-  intptr_t bytes_written() { return stream_.bytes_written(); }
+  NonStreamingWriteStream* stream() { return stream_; }
+  intptr_t bytes_written() { return stream_->bytes_written(); }
 
   void FlushBytesWrittenToRoot();
   void TraceStartWritingObject(const char* type, ObjectPtr obj, StringPtr name);
@@ -302,19 +258,19 @@
   // sizeof(T) must be in {1,2,4,8}.
   template <typename T>
   void Write(T value) {
-    WriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
+    BaseWriteStream::Raw<sizeof(T), T>::Write(stream_, value);
   }
-  void WriteUnsigned(intptr_t value) { stream_.WriteUnsigned(value); }
-  void WriteUnsigned64(uint64_t value) { stream_.WriteUnsigned(value); }
+  void WriteUnsigned(intptr_t value) { stream_->WriteUnsigned(value); }
+  void WriteUnsigned64(uint64_t value) { stream_->WriteUnsigned(value); }
 
   void WriteWordWith32BitWrites(uword value) {
-    stream_.WriteWordWith32BitWrites(value);
+    stream_->WriteWordWith32BitWrites(value);
   }
 
   void WriteBytes(const uint8_t* addr, intptr_t len) {
-    stream_.WriteBytes(addr, len);
+    stream_->WriteBytes(addr, len);
   }
-  void Align(intptr_t alignment) { stream_.Align(alignment); }
+  void Align(intptr_t alignment) { stream_->Align(alignment); }
 
   void WriteRootRef(ObjectPtr object, const char* name = nullptr) {
     intptr_t id = RefId(object);
@@ -498,8 +454,9 @@
   Heap* heap_;
   Zone* zone_;
   Snapshot::Kind kind_;
-  WriteStream stream_;
+  NonStreamingWriteStream* stream_;
   ImageWriter* image_writer_;
+  SerializationCluster** canonical_clusters_by_cid_;
   SerializationCluster** clusters_by_cid_;
   GrowableArray<ObjectPtr> stack_;
   intptr_t num_cids_;
@@ -536,6 +493,7 @@
 
   intptr_t current_loading_unit_id_ = 0;
   GrowableArray<LoadingUnitSerializationData*>* loading_units_ = nullptr;
+  ZoneGrowableArray<Object*>* objects_ = new ZoneGrowableArray<Object*>();
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Serializer);
 };
@@ -725,10 +683,12 @@
   ImageReader* image_reader_;
   intptr_t num_base_objects_;
   intptr_t num_objects_;
+  intptr_t num_canonical_clusters_;
   intptr_t num_clusters_;
   ArrayPtr refs_;
   intptr_t next_ref_index_;
   intptr_t previous_text_offset_;
+  DeserializationCluster** canonical_clusters_;
   DeserializationCluster** clusters_;
   FieldTable* field_table_;
 };
@@ -739,19 +699,12 @@
  public:
   static const intptr_t kInitialSize = 64 * KB;
   FullSnapshotWriter(Snapshot::Kind kind,
-                     uint8_t** vm_snapshot_data_buffer,
-                     uint8_t** isolate_snapshot_data_buffer,
-                     ReAlloc alloc,
+                     NonStreamingWriteStream* vm_snapshot_data,
+                     NonStreamingWriteStream* isolate_snapshot_data,
                      ImageWriter* vm_image_writer,
                      ImageWriter* iso_image_writer);
   ~FullSnapshotWriter();
 
-  uint8_t** vm_snapshot_data_buffer() const { return vm_snapshot_data_buffer_; }
-
-  uint8_t** isolate_snapshot_data_buffer() const {
-    return isolate_snapshot_data_buffer_;
-  }
-
   Thread* thread() const { return thread_; }
   Zone* zone() const { return thread_->zone(); }
   Isolate* isolate() const { return thread_->isolate(); }
@@ -769,17 +722,16 @@
 
  private:
   // Writes a snapshot of the VM Isolate.
-  intptr_t WriteVMSnapshot();
+  ZoneGrowableArray<Object*>* WriteVMSnapshot();
 
   // Writes a full snapshot of regular Dart isolate group.
-  void WriteProgramSnapshot(intptr_t num_base_objects,
+  void WriteProgramSnapshot(ZoneGrowableArray<Object*>* objects,
                             GrowableArray<LoadingUnitSerializationData*>* data);
 
   Thread* thread_;
   Snapshot::Kind kind_;
-  uint8_t** vm_snapshot_data_buffer_;
-  uint8_t** isolate_snapshot_data_buffer_;
-  ReAlloc alloc_;
+  NonStreamingWriteStream* const vm_snapshot_data_;
+  NonStreamingWriteStream* const isolate_snapshot_data_;
   intptr_t vm_isolate_snapshot_size_;
   intptr_t isolate_snapshot_size_;
   ImageWriter* vm_image_writer_;
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index a462905..edce815 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -35,14 +35,13 @@
         PcDescriptorsLayout::KindAndMetadata::Encode(kind, try_index,
                                                      yield_index);
 
-    PcDescriptors::EncodeInteger(&encoded_data_, kind_and_metadata);
-    PcDescriptors::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset);
+    encoded_data_.WriteSLEB128(kind_and_metadata);
+    encoded_data_.WriteSLEB128(pc_offset - prev_pc_offset);
     prev_pc_offset = pc_offset;
 
     if (!FLAG_precompiled_mode) {
-      PcDescriptors::EncodeInteger(&encoded_data_, deopt_id - prev_deopt_id);
-      PcDescriptors::EncodeInteger(&encoded_data_,
-                                   token_pos.value() - prev_token_pos);
+      encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id);
+      encoded_data_.WriteSLEB128(token_pos.value() - prev_token_pos);
       prev_deopt_id = deopt_id;
       prev_token_pos = token_pos.value();
     }
@@ -50,22 +49,11 @@
 }
 
 PcDescriptorsPtr DescriptorList::FinalizePcDescriptors(uword entry_point) {
-  if (encoded_data_.length() == 0) {
+  if (encoded_data_.bytes_written() == 0) {
     return Object::empty_descriptors().raw();
   }
-  return PcDescriptors::New(&encoded_data_);
-}
-
-// Encode unsigned integer |value| in LEB128 format and store into |data|.
-void CompressedStackMapsBuilder::EncodeLEB128(GrowableArray<uint8_t>* data,
-                                              uintptr_t value) {
-  while (true) {
-    uint8_t part = value & 0x7f;
-    value >>= 7;
-    if (value != 0) part |= 0x80;
-    data->Add(part);
-    if (value == 0) break;
-  }
+  return PcDescriptors::New(encoded_data_.buffer(),
+                            encoded_data_.bytes_written());
 }
 
 void CompressedStackMapsBuilder::AddEntry(intptr_t pc_offset,
@@ -74,179 +62,22 @@
   ASSERT(bitmap != nullptr);
   ASSERT(pc_offset > last_pc_offset_);
   ASSERT(spill_slot_bit_count >= 0 && spill_slot_bit_count <= bitmap->Length());
-  auto const pc_delta = pc_offset - last_pc_offset_;
-  auto const non_spill_slot_bit_count = bitmap->Length() - spill_slot_bit_count;
-  EncodeLEB128(&encoded_bytes_, pc_delta);
-  EncodeLEB128(&encoded_bytes_, spill_slot_bit_count);
-  EncodeLEB128(&encoded_bytes_, non_spill_slot_bit_count);
+  const uword pc_delta = pc_offset - last_pc_offset_;
+  const uword non_spill_slot_bit_count =
+      bitmap->Length() - spill_slot_bit_count;
+  encoded_bytes_.WriteLEB128(pc_delta);
+  encoded_bytes_.WriteLEB128(spill_slot_bit_count);
+  encoded_bytes_.WriteLEB128(non_spill_slot_bit_count);
   bitmap->AppendAsBytesTo(&encoded_bytes_);
   last_pc_offset_ = pc_offset;
 }
 
 CompressedStackMapsPtr CompressedStackMapsBuilder::Finalize() const {
-  if (encoded_bytes_.length() == 0) return CompressedStackMaps::null();
-  return CompressedStackMaps::NewInlined(encoded_bytes_);
-}
-
-CompressedStackMapsIterator::CompressedStackMapsIterator(
-    const CompressedStackMaps& maps,
-    const CompressedStackMaps& global_table)
-    : maps_(maps),
-      bits_container_(maps_.UsesGlobalTable() ? global_table : maps_) {
-  ASSERT(!maps_.IsGlobalTable());
-  ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
-}
-
-CompressedStackMapsIterator::CompressedStackMapsIterator(
-    const CompressedStackMaps& maps)
-    : CompressedStackMapsIterator(
-          maps,
-          // Only look up the global table if the map will end up using it.
-          maps.UsesGlobalTable() ? CompressedStackMaps::Handle(
-                                       Thread::Current()
-                                           ->isolate()
-                                           ->object_store()
-                                           ->canonicalized_stack_map_entries())
-                                 : Object::null_compressed_stack_maps()) {}
-
-CompressedStackMapsIterator::CompressedStackMapsIterator(
-    const CompressedStackMapsIterator& it)
-    : maps_(it.maps_),
-      bits_container_(it.bits_container_),
-      next_offset_(it.next_offset_),
-      current_pc_offset_(it.current_pc_offset_),
-      current_global_table_offset_(it.current_global_table_offset_),
-      current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
-      current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
-      current_bits_offset_(it.current_bits_offset_) {}
-
-// Decode unsigned integer in LEB128 format from the payload of |maps| and
-// update |byte_index|.
-uintptr_t CompressedStackMapsIterator::DecodeLEB128(
-    const CompressedStackMaps& maps,
-    uintptr_t* byte_index) {
-  uword shift = 0;
-  uintptr_t value = 0;
-  uint8_t part = 0;
-  do {
-    ASSERT(*byte_index < maps.payload_size());
-    part = maps.PayloadByte((*byte_index)++);
-    value |= static_cast<uintptr_t>(part & 0x7f) << shift;
-    shift += 7;
-  } while ((part & 0x80) != 0);
-
-  return value;
-}
-
-bool CompressedStackMapsIterator::MoveNext() {
-  // Empty CompressedStackMaps are represented as null values.
-  if (maps_.IsNull() || next_offset_ >= maps_.payload_size()) return false;
-  uintptr_t offset = next_offset_;
-
-  auto const pc_delta = DecodeLEB128(maps_, &offset);
-  ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
-  current_pc_offset_ += pc_delta;
-
-  // Table-using CSMs have a table offset after the PC offset delta, whereas
-  // the post-delta part of inlined entries has the same information as
-  // global table entries.
-  if (maps_.UsesGlobalTable()) {
-    current_global_table_offset_ = DecodeLEB128(maps_, &offset);
-    ASSERT(current_global_table_offset_ < bits_container_.payload_size());
-
-    // Since generally we only use entries in the GC and the GC only needs
-    // the rest of the entry information if the PC offset matches, we lazily
-    // load and cache the information stored in the global object when it is
-    // actually requested.
-    current_spill_slot_bit_count_ = -1;
-    current_non_spill_slot_bit_count_ = -1;
-    current_bits_offset_ = -1;
-  } else {
-    current_spill_slot_bit_count_ = DecodeLEB128(maps_, &offset);
-    ASSERT(current_spill_slot_bit_count_ >= 0);
-
-    current_non_spill_slot_bit_count_ = DecodeLEB128(maps_, &offset);
-    ASSERT(current_non_spill_slot_bit_count_ >= 0);
-
-    const auto stackmap_bits =
-        current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
-    const uintptr_t stackmap_size =
-        Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
-    ASSERT(stackmap_size <= (maps_.payload_size() - offset));
-
-    current_bits_offset_ = offset;
-    offset += stackmap_size;
+  if (encoded_bytes_.bytes_written() == 0) {
+    return Object::empty_compressed_stackmaps().raw();
   }
-
-  next_offset_ = offset;
-  return true;
-}
-
-intptr_t CompressedStackMapsIterator::Length() {
-  EnsureFullyLoadedEntry();
-  return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
-}
-intptr_t CompressedStackMapsIterator::SpillSlotBitCount() {
-  EnsureFullyLoadedEntry();
-  return current_spill_slot_bit_count_;
-}
-
-bool CompressedStackMapsIterator::IsObject(intptr_t bit_index) {
-  EnsureFullyLoadedEntry();
-  ASSERT(!bits_container_.IsNull());
-  ASSERT(bit_index >= 0 && bit_index < Length());
-  const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
-  const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
-  uint8_t byte_mask = 1U << bit_remainder;
-  const intptr_t byte_offset = current_bits_offset_ + byte_index;
-  return (bits_container_.PayloadByte(byte_offset) & byte_mask) != 0;
-}
-
-void CompressedStackMapsIterator::LazyLoadGlobalTableEntry() {
-  ASSERT(maps_.UsesGlobalTable() && bits_container_.IsGlobalTable());
-  ASSERT(HasLoadedEntry());
-  ASSERT(current_global_table_offset_ < bits_container_.payload_size());
-
-  uintptr_t offset = current_global_table_offset_;
-  current_spill_slot_bit_count_ = DecodeLEB128(bits_container_, &offset);
-  ASSERT(current_spill_slot_bit_count_ >= 0);
-
-  current_non_spill_slot_bit_count_ = DecodeLEB128(bits_container_, &offset);
-  ASSERT(current_non_spill_slot_bit_count_ >= 0);
-
-  const auto stackmap_bits = Length();
-  const uintptr_t stackmap_size =
-      Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
-  ASSERT(stackmap_size <= (bits_container_.payload_size() - offset));
-
-  current_bits_offset_ = offset;
-}
-
-const char* CompressedStackMapsIterator::ToCString(Zone* zone) const {
-  ZoneTextBuffer b(zone, 100);
-  CompressedStackMapsIterator it(*this);
-  // If we haven't loaded an entry yet, do so (but don't skip the current
-  // one if we have!)
-  if (!it.HasLoadedEntry()) {
-    if (!it.MoveNext()) return b.buffer();
-  }
-  bool first_entry = true;
-  do {
-    if (first_entry) {
-      first_entry = false;
-    } else {
-      b.AddString("\n");
-    }
-    b.Printf("0x%08x: ", it.pc_offset());
-    for (intptr_t i = 0, n = it.Length(); i < n; i++) {
-      b.AddString(it.IsObject(i) ? "1" : "0");
-    }
-  } while (it.MoveNext());
-  return b.buffer();
-}
-
-const char* CompressedStackMapsIterator::ToCString() const {
-  return ToCString(Thread::Current()->zone());
+  return CompressedStackMaps::NewInlined(encoded_bytes_.buffer(),
+                                         encoded_bytes_.bytes_written());
 }
 
 ExceptionHandlersPtr ExceptionHandlerList::FinalizeExceptionHandlers(
@@ -281,13 +112,6 @@
   return handlers.raw();
 }
 
-static uint8_t* ZoneAllocator(uint8_t* ptr,
-                              intptr_t old_size,
-                              intptr_t new_size) {
-  Zone* zone = Thread::Current()->zone();
-  return zone->Realloc<uint8_t>(ptr, old_size, new_size);
-}
-
 #if !defined(DART_PRECOMPILED_RUNTIME)
 class CatchEntryMovesMapBuilder::TrieNode : public ZoneAllocated {
  public:
@@ -319,8 +143,7 @@
     : zone_(Thread::Current()->zone()),
       root_(new TrieNode()),
       current_pc_offset_(0),
-      buffer_(NULL),
-      stream_(&buffer_, ZoneAllocator, 64) {}
+      stream_(zone_, 64) {}
 
 void CatchEntryMovesMapBuilder::Append(const CatchEntryMove& move) {
   moves_.Add(move);
@@ -344,7 +167,7 @@
   intptr_t length = moves_.length() - suffix_length;
   intptr_t current_offset = stream_.bytes_written();
 
-  typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
+  typedef ZoneWriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
   Writer::Write(&stream_, current_pc_offset_);
   Writer::Write(&stream_, length);
   Writer::Write(&stream_, suffix_length);
@@ -378,6 +201,7 @@
     TokenPosition(TokenPosition::kDartCodeProloguePos);
 
 CodeSourceMapBuilder::CodeSourceMapBuilder(
+    Zone* zone,
     bool stack_traces_only,
     const GrowableArray<intptr_t>& caller_inline_id,
     const GrowableArray<TokenPosition>& inline_id_to_token_pos,
@@ -393,8 +217,7 @@
       inline_id_to_function_(inline_id_to_function),
       inlined_functions_(
           GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld))),
-      buffer_(NULL),
-      stream_(&buffer_, ZoneAllocator, 64),
+      stream_(zone, 64),
       stack_traces_only_(stack_traces_only) {
   buffered_inline_id_stack_.Add(0);
   buffered_token_pos_stack_.Add(kInitialPosition);
@@ -567,7 +390,7 @@
   intptr_t length = stream_.bytes_written();
   const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length));
   NoSafepointScope no_safepoint;
-  memmove(map.Data(), buffer_, length);
+  memmove(map.Data(), stream_.buffer(), length);
   return map.raw();
 }
 
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 6f89c91..f42190b 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -18,8 +18,8 @@
 
 class DescriptorList : public ZoneAllocated {
  public:
-  explicit DescriptorList(intptr_t initial_capacity)
-      : encoded_data_(initial_capacity),
+  explicit DescriptorList(Zone* zone)
+      : encoded_data_(zone, kInitialStreamSize),
         prev_pc_offset(0),
         prev_deopt_id(0),
         prev_token_pos(0) {}
@@ -36,7 +36,9 @@
   PcDescriptorsPtr FinalizePcDescriptors(uword entry_point);
 
  private:
-  GrowableArray<uint8_t> encoded_data_;
+  static constexpr intptr_t kInitialStreamSize = 64;
+
+  ZoneWriteStream encoded_data_;
 
   intptr_t prev_pc_offset;
   intptr_t prev_deopt_id;
@@ -47,9 +49,8 @@
 
 class CompressedStackMapsBuilder : public ZoneAllocated {
  public:
-  CompressedStackMapsBuilder() : encoded_bytes_() {}
-
-  static void EncodeLEB128(GrowableArray<uint8_t>* data, uintptr_t value);
+  explicit CompressedStackMapsBuilder(Zone* zone)
+      : encoded_bytes_(zone, kInitialStreamSize) {}
 
   void AddEntry(intptr_t pc_offset,
                 BitmapBuilder* bitmap,
@@ -58,82 +59,13 @@
   CompressedStackMapsPtr Finalize() const;
 
  private:
+  static constexpr intptr_t kInitialStreamSize = 16;
+
+  ZoneWriteStream encoded_bytes_;
   intptr_t last_pc_offset_ = 0;
-  GrowableArray<uint8_t> encoded_bytes_;
   DISALLOW_COPY_AND_ASSIGN(CompressedStackMapsBuilder);
 };
 
-class CompressedStackMapsIterator : public ValueObject {
- public:
-  // We use the null value to represent CompressedStackMaps with no
-  // entries, so any CompressedStackMaps arguments to constructors can be null.
-  CompressedStackMapsIterator(const CompressedStackMaps& maps,
-                              const CompressedStackMaps& global_table);
-  explicit CompressedStackMapsIterator(const CompressedStackMaps& maps);
-
-  explicit CompressedStackMapsIterator(const CompressedStackMapsIterator& it);
-
-  // Loads the next entry from [maps_], if any. If [maps_] is the null
-  // value, this always returns false.
-  bool MoveNext();
-
-  // Finds the entry with the given PC offset starting at the current
-  // position of the iterator. If [maps_] is the null value, this always
-  // returns false.
-  bool Find(uint32_t pc_offset) {
-    // We should never have an entry with a PC offset of 0 inside an
-    // non-empty CSM, so fail.
-    if (pc_offset == 0) return false;
-    do {
-      if (current_pc_offset_ >= pc_offset) break;
-    } while (MoveNext());
-    return current_pc_offset_ == pc_offset;
-  }
-
-  // Methods for accessing parts of an entry should not be called until
-  // a successful MoveNext() or Find() call has been made.
-
-  uint32_t pc_offset() const {
-    ASSERT(HasLoadedEntry());
-    return current_pc_offset_;
-  }
-  // We lazily load and cache information from the global table if the
-  // CSM uses it, so these methods cannot be const.
-  intptr_t Length();
-  intptr_t SpillSlotBitCount();
-  bool IsObject(intptr_t bit_offset);
-
-  void EnsureFullyLoadedEntry() {
-    ASSERT(HasLoadedEntry());
-    if (current_spill_slot_bit_count_ < 0) {
-      LazyLoadGlobalTableEntry();
-    }
-    ASSERT(current_spill_slot_bit_count_ >= 0);
-  }
-
-  const char* ToCString(Zone* zone) const;
-  const char* ToCString() const;
-
- private:
-  static uintptr_t DecodeLEB128(const CompressedStackMaps& data,
-                                uintptr_t* byte_index);
-  bool HasLoadedEntry() const { return next_offset_ > 0; }
-  void LazyLoadGlobalTableEntry();
-
-  const CompressedStackMaps& maps_;
-  const CompressedStackMaps& bits_container_;
-
-  uintptr_t next_offset_ = 0;
-  uint32_t current_pc_offset_ = 0;
-  // Only used when looking up non-PC information in the global table.
-  uintptr_t current_global_table_offset_ = 0;
-  intptr_t current_spill_slot_bit_count_ = -1;
-  intptr_t current_non_spill_slot_bit_count_ = -1;
-  intptr_t current_bits_offset_ = -1;
-
-  friend class StackMapEntry;
-};
-
 class ExceptionHandlerList : public ZoneAllocated {
  public:
   struct HandlerDesc {
@@ -226,8 +158,7 @@
   TrieNode* root_;
   intptr_t current_pc_offset_;
   GrowableArray<CatchEntryMove> moves_;
-  uint8_t* buffer_;
-  WriteStream stream_;
+  ZoneWriteStream stream_;
 
   DISALLOW_COPY_AND_ASSIGN(CatchEntryMovesMapBuilder);
 };
@@ -246,6 +177,7 @@
 class CodeSourceMapBuilder : public ZoneAllocated {
  public:
   CodeSourceMapBuilder(
+      Zone* zone,
       bool stack_traces_only,
       const GrowableArray<intptr_t>& caller_inline_id,
       const GrowableArray<TokenPosition>& inline_id_to_token_pos,
@@ -336,8 +268,7 @@
 
   const GrowableObjectArray& inlined_functions_;
 
-  uint8_t* buffer_;
-  WriteStream stream_;
+  ZoneWriteStream stream_;
 
   const bool stack_traces_only_;
 
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index 8c192b5..d8e2c41 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -100,7 +100,7 @@
   int call_count = 0;
   PcDescriptors::Iterator iter(descriptors,
                                PcDescriptorsLayout::kUnoptStaticCall);
-  CompressedStackMapsBuilder compressed_maps_builder;
+  CompressedStackMapsBuilder compressed_maps_builder(thread->zone());
   while (iter.MoveNext()) {
     compressed_maps_builder.AddEntry(iter.PcOffset(), stack_bitmap, 0);
     ++call_count;
@@ -121,7 +121,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(DescriptorList_TokenPositions) {
-  DescriptorList* descriptors = new DescriptorList(64);
+  DescriptorList* descriptors = new DescriptorList(thread->zone());
   ASSERT(descriptors != NULL);
   const intptr_t token_positions[] = {
       kMinInt32,
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 173652f..0db337d 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -429,7 +429,7 @@
   }
 }
 
-TypeFeedbackSaver::TypeFeedbackSaver(WriteStream* stream)
+TypeFeedbackSaver::TypeFeedbackSaver(BaseWriteStream* stream)
     : stream_(stream),
       cls_(Class::Handle()),
       lib_(Library::Handle()),
diff --git a/runtime/vm/compilation_trace.h b/runtime/vm/compilation_trace.h
index cf26611..80d671e 100644
--- a/runtime/vm/compilation_trace.h
+++ b/runtime/vm/compilation_trace.h
@@ -67,7 +67,7 @@
 
 class TypeFeedbackSaver : public FunctionVisitor {
  public:
-  explicit TypeFeedbackSaver(WriteStream* stream);
+  explicit TypeFeedbackSaver(BaseWriteStream* stream);
 
   void WriteHeader();
   void SaveClasses();
@@ -79,7 +79,7 @@
   void WriteString(const String& value);
   void WriteInt(intptr_t value) { stream_->Write(static_cast<int32_t>(value)); }
 
-  WriteStream* const stream_;
+  BaseWriteStream* const stream_;
   Class& cls_;
   Library& lib_;
   String& str_;
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 878ce4a..62c6dd0 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -5,6 +5,7 @@
 #include "vm/compiler/aot/precompiler.h"
 
 #include "platform/unicode.h"
+#include "vm/canonical_tables.h"
 #include "vm/class_finalizer.h"
 #include "vm/code_patcher.h"
 #include "vm/compiler/aot/aot_call_specializer.h"
@@ -48,7 +49,6 @@
 #include "vm/tags.h"
 #include "vm/timeline.h"
 #include "vm/timer.h"
-#include "vm/type_table.h"
 #include "vm/type_testing_stubs.h"
 #include "vm/version.h"
 #include "vm/zone_text_buffer.h"
@@ -449,8 +449,6 @@
     Symbols::GetStats(I, &symbols_before, &capacity);
   }
 
-  Symbols::Compact();
-
   if (FLAG_trace_precompiler) {
     Symbols::GetStats(I, &symbols_after, &capacity);
     THR_Print("Precompiled %" Pd " functions,", function_count_);
@@ -2075,31 +2073,33 @@
 
       constants = cls.constants();
       retained_constants = GrowableObjectArray::New();
-      for (intptr_t j = 0; j < constants.Length(); j++) {
-        constant ^= constants.At(j);
-        bool retain = consts_to_retain_.HasKey(&constant);
-        if (retain) {
-          retained_constants.Add(constant);
+      if (!constants.IsNull()) {
+        for (intptr_t j = 0; j < constants.Length(); j++) {
+          constant ^= constants.At(j);
+          bool retain = consts_to_retain_.HasKey(&constant);
+          if (retain) {
+            retained_constants.Add(constant);
+          }
         }
       }
       intptr_t cid = cls.id();
       if (cid == kDoubleCid) {
         // Rehash.
-        cls.set_constants(Object::empty_array());
+        cls.set_constants(Object::null_array());
         for (intptr_t j = 0; j < retained_constants.Length(); j++) {
           constant ^= retained_constants.At(j);
           cls.InsertCanonicalDouble(Z, Double::Cast(constant));
         }
       } else if (cid == kMintCid) {
         // Rehash.
-        cls.set_constants(Object::empty_array());
+        cls.set_constants(Object::null_array());
         for (intptr_t j = 0; j < retained_constants.Length(); j++) {
           constant ^= retained_constants.At(j);
           cls.InsertCanonicalMint(Z, Mint::Cast(constant));
         }
       } else {
         // Rehash.
-        cls.set_constants(Object::empty_array());
+        cls.set_constants(Object::null_array());
         for (intptr_t j = 0; j < retained_constants.Length(); j++) {
           constant ^= retained_constants.At(j);
           cls.InsertCanonicalConstant(Z, constant);
@@ -2273,7 +2273,7 @@
 
     ASSERT(!cls.is_allocated());
     constants = cls.constants();
-    ASSERT(constants.Length() == 0);
+    ASSERT(constants.IsNull() || (constants.Length() == 0));
 
     dropped_class_count_++;
     if (FLAG_trace_precompiler) {
diff --git a/runtime/vm/compiler/asm_intrinsifier.h b/runtime/vm/compiler/asm_intrinsifier.h
index 01fd20d..58a97e0 100644
--- a/runtime/vm/compiler/asm_intrinsifier.h
+++ b/runtime/vm/compiler/asm_intrinsifier.h
@@ -24,6 +24,7 @@
 
 namespace compiler {
 class Assembler;
+class Intrinsifier;
 class Label;
 
 class AsmIntrinsifier : public AllStatic {
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 7a5bd68..22eff5a 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -83,123 +83,6 @@
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_shift)                      \
-  Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 0 * target::kWordSize;              \
-  NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R2, cid));                      \
-  NOT_IN_PRODUCT(__ MaybeTraceAllocation(R2, normal_ir_body));                 \
-  __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
-  /* Check that length is a positive Smi. */                                   \
-  /* R2: requested array length argument. */                                   \
-  __ tst(R2, Operand(kSmiTagMask));                                            \
-  __ b(normal_ir_body, NE);                                                    \
-  __ CompareImmediate(R2, 0);                                                  \
-  __ b(normal_ir_body, LT);                                                    \
-  __ SmiUntag(R2);                                                             \
-  /* Check for maximum allowed length. */                                      \
-  /* R2: untagged array length. */                                             \
-  __ CompareImmediate(R2, max_len);                                            \
-  __ b(normal_ir_body, GT);                                                    \
-  __ mov(R2, Operand(R2, LSL, scale_shift));                                   \
-  const intptr_t fixed_size_plus_alignment_padding =                           \
-      target::TypedData::InstanceSize() +                                      \
-      target::ObjectAlignment::kObjectAlignment - 1;                           \
-  __ AddImmediate(R2, fixed_size_plus_alignment_padding);                      \
-  __ bic(R2, R2, Operand(target::ObjectAlignment::kObjectAlignment - 1));      \
-  __ ldr(R0, Address(THR, target::Thread::top_offset()));                      \
-                                                                               \
-  /* R2: allocation size. */                                                   \
-  __ adds(R1, R0, Operand(R2));                                                \
-  __ b(normal_ir_body, CS); /* Fail on unsigned overflow. */                   \
-                                                                               \
-  /* Check if the allocation fits into the remaining space. */                 \
-  /* R0: potential new object start. */                                        \
-  /* R1: potential next object start. */                                       \
-  /* R2: allocation size. */                                                   \
-  __ ldr(IP, Address(THR, target::Thread::end_offset()));                      \
-  __ cmp(R1, Operand(IP));                                                     \
-  __ b(normal_ir_body, CS);                                                    \
-                                                                               \
-  __ str(R1, Address(THR, target::Thread::top_offset()));                      \
-  __ AddImmediate(R0, kHeapObjectTag);                                         \
-  /* Initialize the tags. */                                                   \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  /* R2: allocation size. */                                                   \
-  {                                                                            \
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);         \
-    __ mov(R3,                                                                 \
-           Operand(R2, LSL,                                                    \
-                   target::ObjectLayout::kTagBitsSizeTagPos -                  \
-                       target::ObjectAlignment::kObjectAlignmentLog2),         \
-           LS);                                                                \
-    __ mov(R3, Operand(0), HI);                                                \
-                                                                               \
-    /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags =                                                            \
-        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
-    __ LoadImmediate(TMP, tags);                                               \
-    __ orr(R3, R3, Operand(TMP));                                              \
-    __ str(R3, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */   \
-  }                                                                            \
-  /* Set the length field. */                                                  \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  /* R2: allocation size. */                                                   \
-  __ ldr(R3, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, target::TypedDataBase::length_offset()), R3);       \
-  /* Initialize all array elements to 0. */                                    \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  /* R2: allocation size. */                                                   \
-  /* R3: iterator which initially points to the start of the variable */       \
-  /* R8, R9: zero. */                                                          \
-  /* data area to be initialized. */                                           \
-  __ LoadImmediate(R8, 0);                                                     \
-  __ mov(R9, Operand(R8));                                                     \
-  __ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1);              \
-  __ StoreInternalPointer(                                                     \
-      R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R3);   \
-  Label init_loop;                                                             \
-  __ Bind(&init_loop);                                                         \
-  __ AddImmediate(R3, 2 * target::kWordSize);                                  \
-  __ cmp(R3, Operand(R1));                                                     \
-  __ strd(R8, R9, R3, -2 * target::kWordSize, LS);                             \
-  __ b(&init_loop, CC);                                                        \
-  __ str(R8, Address(R3, -2 * target::kWordSize), HI);                         \
-                                                                               \
-  __ Ret();                                                                    \
-  __ Bind(normal_ir_body);
-
-static int GetScaleFactor(intptr_t size) {
-  switch (size) {
-    case 1:
-      return 0;
-    case 2:
-      return 1;
-    case 4:
-      return 2;
-    case 8:
-      return 3;
-    case 16:
-      return 4;
-  }
-  UNREACHABLE();
-  return -1;
-}
-
-#define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
-                                                    Label* normal_ir_body) {   \
-    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
-    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
-    int shift = GetScaleFactor(size);                                          \
-    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, shift);            \
-  }
-CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
-#undef TYPED_DATA_ALLOCATOR
-
 // Loads args from stack into R0 and R1
 // Tests if they are smis, jumps to label not_smi if not.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index a6247f9..7552c3c 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -87,120 +87,6 @@
   __ Bind(normal_ir_body);
 }
 
-static int GetScaleFactor(intptr_t size) {
-  switch (size) {
-    case 1:
-      return 0;
-    case 2:
-      return 1;
-    case 4:
-      return 2;
-    case 8:
-      return 3;
-    case 16:
-      return 4;
-  }
-  UNREACHABLE();
-  return -1;
-}
-
-#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_shift)                      \
-  Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 0 * target::kWordSize;              \
-  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, R2, normal_ir_body));            \
-  __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
-  /* Check that length is a positive Smi. */                                   \
-  /* R2: requested array length argument. */                                   \
-  __ BranchIfNotSmi(R2, normal_ir_body);                                       \
-  __ CompareRegisters(R2, ZR);                                                 \
-  __ b(normal_ir_body, LT);                                                    \
-  __ SmiUntag(R2);                                                             \
-  /* Check for maximum allowed length. */                                      \
-  /* R2: untagged array length. */                                             \
-  __ CompareImmediate(R2, max_len);                                            \
-  __ b(normal_ir_body, GT);                                                    \
-  __ LslImmediate(R2, R2, scale_shift);                                        \
-  const intptr_t fixed_size_plus_alignment_padding =                           \
-      target::TypedData::InstanceSize() +                                      \
-      target::ObjectAlignment::kObjectAlignment - 1;                           \
-  __ AddImmediate(R2, fixed_size_plus_alignment_padding);                      \
-  __ andi(R2, R2,                                                              \
-          Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));        \
-  __ ldr(R0, Address(THR, target::Thread::top_offset()));                      \
-                                                                               \
-  /* R2: allocation size. */                                                   \
-  __ adds(R1, R0, Operand(R2));                                                \
-  __ b(normal_ir_body, CS); /* Fail on unsigned overflow. */                   \
-                                                                               \
-  /* Check if the allocation fits into the remaining space. */                 \
-  /* R0: potential new object start. */                                        \
-  /* R1: potential next object start. */                                       \
-  /* R2: allocation size. */                                                   \
-  __ ldr(R6, Address(THR, target::Thread::end_offset()));                      \
-  __ cmp(R1, Operand(R6));                                                     \
-  __ b(normal_ir_body, CS);                                                    \
-                                                                               \
-  /* Successfully allocated the object(s), now update top to point to */       \
-  /* next object start and initialize the object. */                           \
-  __ str(R1, Address(THR, target::Thread::top_offset()));                      \
-  __ AddImmediate(R0, kHeapObjectTag);                                         \
-  /* Initialize the tags. */                                                   \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  /* R2: allocation size. */                                                   \
-  {                                                                            \
-    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);         \
-    __ LslImmediate(R2, R2,                                                    \
-                    target::ObjectLayout::kTagBitsSizeTagPos -                 \
-                        target::ObjectAlignment::kObjectAlignmentLog2);        \
-    __ csel(R2, ZR, R2, HI);                                                   \
-                                                                               \
-    /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags =                                                            \
-        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
-    __ LoadImmediate(TMP, tags);                                               \
-    __ orr(R2, R2, Operand(TMP));                                              \
-    __ str(R2, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */   \
-  }                                                                            \
-  /* Set the length field. */                                                  \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, target::TypedDataBase::length_offset()), R2);       \
-  /* Initialize all array elements to 0. */                                    \
-  /* R0: new object start as a tagged pointer. */                              \
-  /* R1: new object end address. */                                            \
-  /* R2: iterator which initially points to the start of the variable */       \
-  /* R3: scratch register. */                                                  \
-  /* data area to be initialized. */                                           \
-  __ mov(R3, ZR);                                                              \
-  __ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1);              \
-  __ StoreInternalPointer(                                                     \
-      R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R2);   \
-  Label init_loop, done;                                                       \
-  __ Bind(&init_loop);                                                         \
-  __ cmp(R2, Operand(R1));                                                     \
-  __ b(&done, CS);                                                             \
-  __ str(R3, Address(R2, 0));                                                  \
-  __ add(R2, R2, Operand(target::kWordSize));                                  \
-  __ b(&init_loop);                                                            \
-  __ Bind(&done);                                                              \
-                                                                               \
-  __ ret();                                                                    \
-  __ Bind(normal_ir_body);
-
-#define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
-                                                    Label* normal_ir_body) {   \
-    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
-    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
-    int shift = GetScaleFactor(size);                                          \
-    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, shift);            \
-  }
-CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
-#undef TYPED_DATA_ALLOCATOR
-
 // Loads args from stack into R0 and R1
 // Tests if they are smis, jumps to label not_smi if not.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 47ba761..c1e0863 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -83,132 +83,6 @@
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_factor)                     \
-  const intptr_t kArrayLengthStackOffset = 1 * target::kWordSize;              \
-  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, EDI, normal_ir_body, false));    \
-  __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */     \
-  /* Check that length is a positive Smi. */                                   \
-  /* EDI: requested array length argument. */                                  \
-  __ testl(EDI, Immediate(kSmiTagMask));                                       \
-  __ j(NOT_ZERO, normal_ir_body);                                              \
-  __ cmpl(EDI, Immediate(0));                                                  \
-  __ j(LESS, normal_ir_body);                                                  \
-  __ SmiUntag(EDI);                                                            \
-  /* Check for maximum allowed length. */                                      \
-  /* EDI: untagged array length. */                                            \
-  __ cmpl(EDI, Immediate(max_len));                                            \
-  __ j(GREATER, normal_ir_body);                                               \
-  /* Special case for scaling by 16. */                                        \
-  if (scale_factor == TIMES_16) {                                              \
-    /* double length of array. */                                              \
-    __ addl(EDI, EDI);                                                         \
-    /* only scale by 8. */                                                     \
-    scale_factor = TIMES_8;                                                    \
-  }                                                                            \
-  const intptr_t fixed_size_plus_alignment_padding =                           \
-      target::TypedData::InstanceSize() +                                      \
-      target::ObjectAlignment::kObjectAlignment - 1;                           \
-  __ leal(EDI, Address(EDI, scale_factor, fixed_size_plus_alignment_padding)); \
-  __ andl(EDI, Immediate(-target::ObjectAlignment::kObjectAlignment));         \
-  __ movl(EAX, Address(THR, target::Thread::top_offset()));                    \
-  __ movl(EBX, EAX);                                                           \
-                                                                               \
-  /* EDI: allocation size. */                                                  \
-  __ addl(EBX, EDI);                                                           \
-  __ j(CARRY, normal_ir_body);                                                 \
-                                                                               \
-  /* Check if the allocation fits into the remaining space. */                 \
-  /* EAX: potential new object start. */                                       \
-  /* EBX: potential next object start. */                                      \
-  /* EDI: allocation size. */                                                  \
-  __ cmpl(EBX, Address(THR, target::Thread::end_offset()));                    \
-  __ j(ABOVE_EQUAL, normal_ir_body);                                           \
-                                                                               \
-  /* Successfully allocated the object(s), now update top to point to */       \
-  /* next object start and initialize the object. */                           \
-  __ movl(Address(THR, target::Thread::top_offset()), EBX);                    \
-  __ addl(EAX, Immediate(kHeapObjectTag));                                     \
-                                                                               \
-  /* Initialize the tags. */                                                   \
-  /* EAX: new object start as a tagged pointer. */                             \
-  /* EBX: new object end address. */                                           \
-  /* EDI: allocation size. */                                                  \
-  {                                                                            \
-    Label size_tag_overflow, done;                                             \
-    __ cmpl(EDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));         \
-    __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);                     \
-    __ shll(EDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -          \
-                           target::ObjectAlignment::kObjectAlignmentLog2));    \
-    __ jmp(&done, Assembler::kNearJump);                                       \
-                                                                               \
-    __ Bind(&size_tag_overflow);                                               \
-    __ movl(EDI, Immediate(0));                                                \
-    __ Bind(&done);                                                            \
-                                                                               \
-    /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags =                                                            \
-        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
-    __ orl(EDI, Immediate(tags));                                              \
-    __ movl(FieldAddress(EAX, target::Object::tags_offset()),                  \
-            EDI); /* Tags. */                                                  \
-  }                                                                            \
-  /* Set the length field. */                                                  \
-  /* EAX: new object start as a tagged pointer. */                             \
-  /* EBX: new object end address. */                                           \
-  __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */     \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      EAX, FieldAddress(EAX, target::TypedDataBase::length_offset()), EDI);    \
-  /* Initialize all array elements to 0. */                                    \
-  /* EAX: new object start as a tagged pointer. */                             \
-  /* EBX: new object end address. */                                           \
-  /* EDI: iterator which initially points to the start of the variable */      \
-  /* ECX: scratch register. */                                                 \
-  /* data area to be initialized. */                                           \
-  __ xorl(ECX, ECX); /* Zero. */                                               \
-  __ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize()));          \
-  __ StoreInternalPointer(                                                     \
-      EAX, FieldAddress(EAX, target::TypedDataBase::data_field_offset()),      \
-      EDI);                                                                    \
-  Label done, init_loop;                                                       \
-  __ Bind(&init_loop);                                                         \
-  __ cmpl(EDI, EBX);                                                           \
-  __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);                              \
-  __ movl(Address(EDI, 0), ECX);                                               \
-  __ addl(EDI, Immediate(target::kWordSize));                                  \
-  __ jmp(&init_loop, Assembler::kNearJump);                                    \
-  __ Bind(&done);                                                              \
-                                                                               \
-  __ ret();                                                                    \
-  __ Bind(normal_ir_body);
-
-static ScaleFactor GetScaleFactor(intptr_t size) {
-  switch (size) {
-    case 1:
-      return TIMES_1;
-    case 2:
-      return TIMES_2;
-    case 4:
-      return TIMES_4;
-    case 8:
-      return TIMES_8;
-    case 16:
-      return TIMES_16;
-  }
-  UNREACHABLE();
-  return static_cast<ScaleFactor>(0);
-}
-
-#define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
-                                                    Label* normal_ir_body) {   \
-    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
-    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
-    ScaleFactor scale = GetScaleFactor(size);                                  \
-    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, scale);            \
-  }
-CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
-#undef TYPED_DATA_ALLOCATOR
-
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in EAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 003c256..9ee661c 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -84,133 +84,6 @@
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_factor)                     \
-  Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 1 * target::kWordSize;              \
-  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, normal_ir_body, false));         \
-  __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */     \
-  /* Check that length is a positive Smi. */                                   \
-  /* RDI: requested array length argument. */                                  \
-  __ testq(RDI, Immediate(kSmiTagMask));                                       \
-  __ j(NOT_ZERO, normal_ir_body);                                              \
-  __ cmpq(RDI, Immediate(0));                                                  \
-  __ j(LESS, normal_ir_body);                                                  \
-  __ SmiUntag(RDI);                                                            \
-  /* Check for maximum allowed length. */                                      \
-  /* RDI: untagged array length. */                                            \
-  __ cmpq(RDI, Immediate(max_len));                                            \
-  __ j(GREATER, normal_ir_body);                                               \
-  /* Special case for scaling by 16. */                                        \
-  if (scale_factor == TIMES_16) {                                              \
-    /* double length of array. */                                              \
-    __ addq(RDI, RDI);                                                         \
-    /* only scale by 8. */                                                     \
-    scale_factor = TIMES_8;                                                    \
-  }                                                                            \
-  const intptr_t fixed_size_plus_alignment_padding =                           \
-      target::TypedData::InstanceSize() +                                      \
-      target::ObjectAlignment::kObjectAlignment - 1;                           \
-  __ leaq(RDI, Address(RDI, scale_factor, fixed_size_plus_alignment_padding)); \
-  __ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));         \
-  __ movq(RAX, Address(THR, target::Thread::top_offset()));                    \
-  __ movq(RCX, RAX);                                                           \
-                                                                               \
-  /* RDI: allocation size. */                                                  \
-  __ addq(RCX, RDI);                                                           \
-  __ j(CARRY, normal_ir_body);                                                 \
-                                                                               \
-  /* Check if the allocation fits into the remaining space. */                 \
-  /* RAX: potential new object start. */                                       \
-  /* RCX: potential next object start. */                                      \
-  /* RDI: allocation size. */                                                  \
-  __ cmpq(RCX, Address(THR, target::Thread::end_offset()));                    \
-  __ j(ABOVE_EQUAL, normal_ir_body);                                           \
-                                                                               \
-  /* Successfully allocated the object(s), now update top to point to */       \
-  /* next object start and initialize the object. */                           \
-  __ movq(Address(THR, target::Thread::top_offset()), RCX);                    \
-  __ addq(RAX, Immediate(kHeapObjectTag));                                     \
-  /* Initialize the tags. */                                                   \
-  /* RAX: new object start as a tagged pointer. */                             \
-  /* RCX: new object end address. */                                           \
-  /* RDI: allocation size. */                                                  \
-  /* R13: scratch register. */                                                 \
-  {                                                                            \
-    Label size_tag_overflow, done;                                             \
-    __ cmpq(RDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));         \
-    __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);                     \
-    __ shlq(RDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -          \
-                           target::ObjectAlignment::kObjectAlignmentLog2));    \
-    __ jmp(&done, Assembler::kNearJump);                                       \
-                                                                               \
-    __ Bind(&size_tag_overflow);                                               \
-    __ LoadImmediate(RDI, Immediate(0));                                       \
-    __ Bind(&done);                                                            \
-                                                                               \
-    /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags =                                                            \
-        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
-    __ orq(RDI, Immediate(tags));                                              \
-    __ movq(FieldAddress(RAX, target::Object::tags_offset()),                  \
-            RDI); /* Tags. */                                                  \
-  }                                                                            \
-  /* Set the length field. */                                                  \
-  /* RAX: new object start as a tagged pointer. */                             \
-  /* RCX: new object end address. */                                           \
-  __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */     \
-  __ StoreIntoObjectNoBarrier(                                                 \
-      RAX, FieldAddress(RAX, target::TypedDataBase::length_offset()), RDI);    \
-  /* Initialize all array elements to 0. */                                    \
-  /* RAX: new object start as a tagged pointer. */                             \
-  /* RCX: new object end address. */                                           \
-  /* RDI: iterator which initially points to the start of the variable */      \
-  /* RBX: scratch register. */                                                 \
-  /* data area to be initialized. */                                           \
-  __ xorq(RBX, RBX); /* Zero. */                                               \
-  __ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize()));          \
-  __ StoreInternalPointer(                                                     \
-      RAX, FieldAddress(RAX, target::TypedDataBase::data_field_offset()),      \
-      RDI);                                                                    \
-  Label done, init_loop;                                                       \
-  __ Bind(&init_loop);                                                         \
-  __ cmpq(RDI, RCX);                                                           \
-  __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);                              \
-  __ movq(Address(RDI, 0), RBX);                                               \
-  __ addq(RDI, Immediate(target::kWordSize));                                  \
-  __ jmp(&init_loop, Assembler::kNearJump);                                    \
-  __ Bind(&done);                                                              \
-                                                                               \
-  __ ret();                                                                    \
-  __ Bind(normal_ir_body);
-
-static ScaleFactor GetScaleFactor(intptr_t size) {
-  switch (size) {
-    case 1:
-      return TIMES_1;
-    case 2:
-      return TIMES_2;
-    case 4:
-      return TIMES_4;
-    case 8:
-      return TIMES_8;
-    case 16:
-      return TIMES_16;
-  }
-  UNREACHABLE();
-  return static_cast<ScaleFactor>(0);
-}
-
-#define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
-                                                    Label* normal_ir_body) {   \
-    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
-    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
-    ScaleFactor scale = GetScaleFactor(size);                                  \
-    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, scale);            \
-  }
-CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
-#undef TYPED_DATA_ALLOCATOR
-
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in RAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 2118d49..4699f5d 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1485,7 +1485,7 @@
   StoreToOffset(state, THR, target::Thread::exit_through_ffi_offset());
 }
 
-void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) {
+void Assembler::EnterCallRuntimeFrame(intptr_t frame_size, bool is_leaf) {
   Comment("EnterCallRuntimeFrame");
   EnterFrame(0);
   if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
@@ -1510,19 +1510,30 @@
     Push(reg);
   }
 
-  ReserveAlignedFrameSpace(frame_size);
+  if (!is_leaf) {  // Leaf calling sequence aligns the stack itself.
+    ReserveAlignedFrameSpace(frame_size);
+  } else {
+    PushPair(kCallLeafRuntimeCalleeSaveScratch1,
+             kCallLeafRuntimeCalleeSaveScratch2);
+  }
 }
 
-void Assembler::LeaveCallRuntimeFrame() {
+void Assembler::LeaveCallRuntimeFrame(bool is_leaf) {
   // SP might have been modified to reserve space for arguments
   // and ensure proper alignment of the stack frame.
   // We need to restore it before restoring registers.
+  const intptr_t fixed_frame_words_without_pc_and_fp =
+      target::frame_layout.dart_fixed_frame_size - 2;
   const intptr_t kPushedRegistersSize =
-      kDartVolatileCpuRegCount * target::kWordSize +
-      kDartVolatileFpuRegCount * target::kWordSize +
-      (target::frame_layout.dart_fixed_frame_size - 2) *
-          target::kWordSize;  // From EnterStubFrame (excluding PC / FP)
+      kDartVolatileFpuRegCount * sizeof(double) +
+      (kDartVolatileCpuRegCount + (is_leaf ? 2 : 0) +
+       fixed_frame_words_without_pc_and_fp) *
+          target::kWordSize;
   AddImmediate(SP, FP, -kPushedRegistersSize);
+  if (is_leaf) {
+    PopPair(kCallLeafRuntimeCalleeSaveScratch1,
+            kCallLeafRuntimeCalleeSaveScratch2);
+  }
   for (int i = kDartLastVolatileCpuReg; i >= kDartFirstVolatileCpuReg; i--) {
     const Register reg = static_cast<Register>(i);
     Pop(reg);
@@ -1547,6 +1558,37 @@
   entry.Call(this, argument_count);
 }
 
+void Assembler::CallRuntimeScope::Call(intptr_t argument_count) {
+  assembler_->CallRuntime(entry_, argument_count);
+}
+
+Assembler::CallRuntimeScope::~CallRuntimeScope() {
+  if (preserve_registers_) {
+    assembler_->LeaveCallRuntimeFrame(entry_.is_leaf());
+    if (restore_code_reg_) {
+      assembler_->Pop(CODE_REG);
+    }
+  }
+}
+
+Assembler::CallRuntimeScope::CallRuntimeScope(Assembler* assembler,
+                                              const RuntimeEntry& entry,
+                                              intptr_t frame_size,
+                                              bool preserve_registers,
+                                              const Address* caller)
+    : assembler_(assembler),
+      entry_(entry),
+      preserve_registers_(preserve_registers),
+      restore_code_reg_(caller != nullptr) {
+  if (preserve_registers_) {
+    if (caller != nullptr) {
+      assembler_->Push(CODE_REG);
+      assembler_->ldr(CODE_REG, *caller);
+    }
+    assembler_->EnterCallRuntimeFrame(frame_size, entry.is_leaf());
+  }
+}
+
 void Assembler::EnterStubFrame() {
   EnterDartFrame(0);
 }
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 5c1fb60..c9bd624 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1651,10 +1651,51 @@
   void EnterOsrFrame(intptr_t extra_size, Register new_pp = kNoRegister);
   void LeaveDartFrame(RestorePP restore_pp = kRestoreCallerPP);
 
-  void EnterCallRuntimeFrame(intptr_t frame_size);
-  void LeaveCallRuntimeFrame();
   void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
 
+  // Helper method for performing runtime calls from callers requiring manual
+  // register preservation is required (e.g. outside IL instructions marked
+  // as calling).
+  class CallRuntimeScope : public ValueObject {
+   public:
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     bool preserve_registers = true)
+        : CallRuntimeScope(assembler,
+                           entry,
+                           frame_size,
+                           preserve_registers,
+                           /*caller=*/nullptr) {}
+
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     Address caller,
+                     bool preserve_registers = true)
+        : CallRuntimeScope(assembler,
+                           entry,
+                           frame_size,
+                           preserve_registers,
+                           &caller) {}
+
+    void Call(intptr_t argument_count);
+
+    ~CallRuntimeScope();
+
+   private:
+    CallRuntimeScope(Assembler* assembler,
+                     const RuntimeEntry& entry,
+                     intptr_t frame_size,
+                     bool preserve_registers,
+                     const Address* caller);
+
+    Assembler* const assembler_;
+    const RuntimeEntry& entry_;
+    const bool preserve_registers_;
+    const bool restore_code_reg_;
+  };
+
   // Set up a stub frame so that the stack traversal code can easily identify
   // a stub frame.
   void EnterStubFrame();
@@ -2402,6 +2443,11 @@
                              CanBeSmi can_be_smi,
                              BarrierFilterMode barrier_filter_mode);
 
+  // Note: leaf call sequence uses some abi callee save registers as scratch
+  // so they should be manually preserved.
+  void EnterCallRuntimeFrame(intptr_t frame_size, bool is_leaf);
+  void LeaveCallRuntimeFrame(bool is_leaf);
+
   friend class dart::FlowGraphCompiler;
   std::function<void(Register reg)> generate_invoke_write_barrier_wrapper_;
   std::function<void()> generate_invoke_array_write_barrier_;
diff --git a/runtime/vm/compiler/assembler/disassembler.cc b/runtime/vm/compiler/assembler/disassembler.cc
index 0edfb70..e7e73a5 100644
--- a/runtime/vm/compiler/assembler/disassembler.cc
+++ b/runtime/vm/compiler/assembler/disassembler.cc
@@ -220,7 +220,8 @@
                                          const char* function_info,
                                          const Code& code,
                                          bool optimized) {
-  Zone* zone = Thread::Current()->zone();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   LocalVarDescriptors& var_descriptors = LocalVarDescriptors::Handle(zone);
   if (FLAG_print_variable_descriptors) {
     var_descriptors = code.GetLocalVarDescriptors();
@@ -290,13 +291,16 @@
   }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-  THR_Print("StackMaps for function '%s' {\n", function_fullname);
-  if (code.compressed_stackmaps() != CompressedStackMaps::null()) {
+  {
     const auto& stackmaps =
         CompressedStackMaps::Handle(zone, code.compressed_stackmaps());
-    THR_Print("%s\n", stackmaps.ToCString());
+    CompressedStackMaps::Iterator it(thread, stackmaps);
+    TextBuffer buffer(100);
+    buffer.Printf("StackMaps for function '%s' {\n", function_fullname);
+    it.WriteToBuffer(&buffer, "\n");
+    buffer.AddString("}\n");
+    THR_Print("%s", buffer.buffer());
   }
-  THR_Print("}\n");
 
   if (FLAG_print_variable_descriptors) {
     THR_Print("Variable Descriptors for function '%s' {\n", function_fullname);
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 4fc79f6..fc4cfbf 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -438,29 +438,33 @@
 
   if (IsNonConstant(value) || IsNonConstant(dst_type)) {
     SetValue(instr, non_constant_);
-  } else if (IsConstant(value) && IsConstant(dst_type)) {
+    return;
+  } else if (IsUnknown(value) || IsUnknown(dst_type)) {
+    return;
+  }
+  ASSERT(IsConstant(value) && IsConstant(dst_type));
+  if (dst_type.IsAbstractType()) {
     // We are ignoring the instantiator and instantiator_type_arguments, but
     // still monotonic and safe.
     if (instr->value()->Type()->IsAssignableTo(AbstractType::Cast(dst_type))) {
       SetValue(instr, value);
-    } else {
-      SetValue(instr, non_constant_);
+      return;
     }
   }
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitAssertSubtype(AssertSubtypeInstr* instr) {}
 
 void ConstantPropagator::VisitAssertBoolean(AssertBooleanInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsBool()) {
+    SetValue(instr, value);
+  } else {
     SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    if (value.IsBool()) {
-      SetValue(instr, value);
-    } else {
-      SetValue(instr, non_constant_);
-    }
   }
 }
 
@@ -500,7 +504,7 @@
       // Otherwise evaluate string compare with propagated constants.
       const Object& o1 = instr->ArgumentAt(0)->constant_value();
       const Object& o2 = instr->ArgumentAt(1)->constant_value();
-      if (IsConstant(o1) && IsConstant(o2) && o1.IsString() && o2.IsString()) {
+      if (o1.IsString() && o2.IsString()) {
         SetValue(instr, Bool::Get(String::Cast(o1).Equals(String::Cast(o2))));
         return;
       }
@@ -511,7 +515,7 @@
       ASSERT(instr->FirstArgIndex() == 0);
       // Otherwise evaluate string length with propagated constants.
       const Object& o = instr->ArgumentAt(0)->constant_value();
-      if (IsConstant(o) && o.IsString()) {
+      if (o.IsString()) {
         const auto& str = String::Cast(o);
         if (kind == MethodRecognizer::kStringBaseLength) {
           SetValue(instr, Integer::ZoneHandle(Z, Integer::New(str.Length())));
@@ -551,14 +555,16 @@
 void ConstantPropagator::VisitIfThenElse(IfThenElseInstr* instr) {
   instr->comparison()->Accept(this);
   const Object& value = instr->comparison()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    ASSERT(!value.IsNull());
-    ASSERT(value.IsBool());
+  ASSERT(!value.IsNull());
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsBool()) {
     bool result = Bool::Cast(value).value();
     SetValue(instr, Smi::Handle(Z, Smi::New(result ? instr->if_true()
                                                    : instr->if_false())));
+  } else {
+    SetValue(instr, non_constant_);
   }
 }
 
@@ -649,17 +655,20 @@
   const Object& right = instr->right()->definition()->constant_value();
   if (IsNonConstant(left) || IsNonConstant(right)) {
     SetValue(instr, non_constant_);
-  } else if (IsConstant(left) && IsConstant(right)) {
-    if (left.IsInteger() && right.IsInteger()) {
-      const bool result = CompareIntegers(
-          instr->kind(),
-          Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND,
-                                                       Integer::Cast(right))),
-          Object::smi_zero());
-      SetValue(instr, result ? Bool::True() : Bool::False());
-    } else {
-      SetValue(instr, non_constant_);
-    }
+    return;
+  } else if (IsUnknown(left) || IsUnknown(right)) {
+    return;
+  }
+  ASSERT(IsConstant(left) && IsConstant(right));
+  if (left.IsInteger() && right.IsInteger()) {
+    const bool result = CompareIntegers(
+        instr->kind(),
+        Integer::Handle(Z, Integer::Cast(left).BitOp(Token::kBIT_AND,
+                                                     Integer::Cast(right))),
+        Object::smi_zero());
+    SetValue(instr, result ? Bool::True() : Bool::False());
+  } else {
+    SetValue(instr, non_constant_);
   }
 }
 
@@ -758,29 +767,33 @@
 void ConstantPropagator::VisitOneByteStringFromCharCode(
     OneByteStringFromCharCodeInstr* instr) {
   const Object& o = instr->char_code()->definition()->constant_value();
-  if (o.IsNull() || IsNonConstant(o)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(o)) {
+  if (IsUnknown(o)) {
+    return;
+  }
+  if (o.IsSmi()) {
     const intptr_t ch_code = Smi::Cast(o).Value();
     ASSERT(ch_code >= 0);
     if (ch_code < Symbols::kMaxOneCharCodeSymbol) {
       StringPtr* table = Symbols::PredefinedAddress();
       SetValue(instr, String::ZoneHandle(Z, table[ch_code]));
-    } else {
-      SetValue(instr, non_constant_);
+      return;
     }
   }
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitStringToCharCode(StringToCharCodeInstr* instr) {
   const Object& o = instr->str()->definition()->constant_value();
-  if (o.IsNull() || IsNonConstant(o)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(o)) {
+  if (IsUnknown(o)) {
+    return;
+  }
+  if (o.IsString()) {
     const String& str = String::Cast(o);
     const intptr_t result =
         (str.Length() == 1) ? static_cast<intptr_t>(str.CharAt(0)) : -1;
     SetValue(instr, Smi::ZoneHandle(Z, Smi::New(result)));
+  } else {
+    SetValue(instr, non_constant_);
   }
 }
 
@@ -858,11 +871,14 @@
 
 void ConstantPropagator::VisitBooleanNegate(BooleanNegateInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsBool()) {
     bool val = value.raw() != Bool::True().raw();
     SetValue(instr, Bool::Get(val));
+  } else {
+    SetValue(instr, non_constant_);
   }
 }
 
@@ -892,7 +908,7 @@
       SetValue(instr, non_constant_);
     }
   } else if (IsConstant(value)) {
-    if (value.IsInstance()) {
+    if (value.IsInstance() && (value.raw() != Object::sentinel().raw())) {
       const Instance& instance = Instance::Cast(value);
       if (instr->instantiator_type_arguments()->BindsToConstantNull() &&
           instr->function_type_arguments()->BindsToConstantNull()) {
@@ -911,6 +927,10 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitAllocateTypedData(AllocateTypedDataInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 void ConstantPropagator::VisitAllocateObject(AllocateObjectInstr* instr) {
   SetValue(instr, non_constant_);
 }
@@ -997,13 +1017,13 @@
     // Type refers to class type parameters.
     const Object& instantiator_type_args_obj =
         instr->instantiator_type_arguments()->definition()->constant_value();
-    if (IsNonConstant(instantiator_type_args_obj)) {
-      SetValue(instr, non_constant_);
+    if (IsUnknown(instantiator_type_args_obj)) {
       return;
     }
-    if (IsConstant(instantiator_type_args_obj)) {
+    if (instantiator_type_args_obj.IsTypeArguments()) {
       instantiator_type_args ^= instantiator_type_args_obj.raw();
     } else {
+      SetValue(instr, non_constant_);
       return;
     }
   }
@@ -1011,13 +1031,13 @@
     // Type refers to function type parameters.
     const Object& function_type_args_obj =
         instr->function_type_arguments()->definition()->constant_value();
-    if (IsNonConstant(function_type_args_obj)) {
-      SetValue(instr, non_constant_);
+    if (IsUnknown(function_type_args_obj)) {
       return;
     }
-    if (IsConstant(function_type_args_obj)) {
+    if (function_type_args_obj.IsTypeArguments()) {
       function_type_args ^= function_type_args_obj.raw();
     } else {
+      SetValue(instr, non_constant_);
       return;
     }
   }
@@ -1028,57 +1048,72 @@
     result = TypeRef::Cast(result).type();
   }
   ASSERT(result.IsInstantiated());
-  result = result.Canonicalize();
+  result = result.Canonicalize(T, nullptr);
   SetValue(instr, result);
 }
 
 void ConstantPropagator::VisitInstantiateTypeArguments(
     InstantiateTypeArgumentsInstr* instr) {
-  TypeArguments& instantiator_type_args = TypeArguments::Handle(Z);
-  TypeArguments& function_type_args = TypeArguments::Handle(Z);
-  if (!instr->type_arguments().IsInstantiated(kCurrentClass)) {
+  const auto& type_arguments_obj =
+      instr->type_arguments()->definition()->constant_value();
+  ASSERT(!type_arguments_obj.IsNull());
+  if (IsUnknown(type_arguments_obj)) {
+    return;
+  }
+  if (!type_arguments_obj.IsTypeArguments()) {
+    SetValue(instr, non_constant_);
+    return;
+  }
+  const auto& type_arguments = TypeArguments::Cast(type_arguments_obj);
+  if (type_arguments.IsInstantiated()) {
+    ASSERT(type_arguments.IsCanonical());
+    SetValue(instr, type_arguments);
+    return;
+  }
+  auto& instantiator_type_args = TypeArguments::Handle(Z);
+  if (!type_arguments.IsInstantiated(kCurrentClass)) {
     // Type arguments refer to class type parameters.
     const Object& instantiator_type_args_obj =
         instr->instantiator_type_arguments()->definition()->constant_value();
-    if (IsNonConstant(instantiator_type_args_obj)) {
+    if (IsUnknown(instantiator_type_args_obj)) {
+      return;
+    }
+    if (!instantiator_type_args_obj.IsTypeArguments()) {
       SetValue(instr, non_constant_);
       return;
     }
-    if (IsConstant(instantiator_type_args_obj)) {
-      instantiator_type_args ^= instantiator_type_args_obj.raw();
-      if (instr->type_arguments().CanShareInstantiatorTypeArguments(
-              instr->instantiator_class())) {
-        SetValue(instr, instantiator_type_args);
-        return;
-      }
-    } else {
+    instantiator_type_args ^= instantiator_type_args_obj.raw();
+    ASSERT(!instr->instantiator_class().IsNull());
+    if (type_arguments.CanShareInstantiatorTypeArguments(
+            instr->instantiator_class())) {
+      SetValue(instr, instantiator_type_args);
       return;
     }
   }
-  if (!instr->type_arguments().IsInstantiated(kFunctions)) {
+  auto& function_type_args = TypeArguments::Handle(Z);
+  if (!type_arguments.IsInstantiated(kFunctions)) {
     // Type arguments refer to function type parameters.
     const Object& function_type_args_obj =
         instr->function_type_arguments()->definition()->constant_value();
-    if (IsNonConstant(function_type_args_obj)) {
+    if (IsUnknown(function_type_args_obj)) {
+      return;
+    }
+    if (!function_type_args_obj.IsTypeArguments()) {
       SetValue(instr, non_constant_);
       return;
     }
-    if (IsConstant(function_type_args_obj)) {
-      function_type_args ^= function_type_args_obj.raw();
-      if (instr->type_arguments().CanShareFunctionTypeArguments(
-              instr->function())) {
-        SetValue(instr, function_type_args);
-        return;
-      }
-    } else {
+    function_type_args ^= function_type_args_obj.raw();
+    ASSERT(!instr->function().IsNull());
+    if (type_arguments.CanShareFunctionTypeArguments(instr->function())) {
+      SetValue(instr, function_type_args);
       return;
     }
   }
-  TypeArguments& result = TypeArguments::Handle(
-      Z, instr->type_arguments().InstantiateFrom(
+  auto& result = TypeArguments::Handle(
+      Z, type_arguments.InstantiateFrom(
              instantiator_type_args, function_type_args, kAllFree, Heap::kOld));
   ASSERT(result.IsInstantiated());
-  result = result.Canonicalize();
+  result = result.Canonicalize(T, nullptr);
   SetValue(instr, result);
 }
 
@@ -1098,7 +1133,14 @@
 void ConstantPropagator::VisitBinaryIntegerOp(BinaryIntegerOpInstr* binary_op) {
   const Object& left = binary_op->left()->definition()->constant_value();
   const Object& right = binary_op->right()->definition()->constant_value();
-  if (IsConstant(left) && IsConstant(right)) {
+  if (IsNonConstant(left) || IsNonConstant(right)) {
+    SetValue(binary_op, non_constant_);
+    return;
+  } else if (IsUnknown(left) || IsUnknown(right)) {
+    return;
+  }
+  ASSERT(IsConstant(left) && IsConstant(right));
+  if (left.IsInteger() && right.IsInteger()) {
     const Integer& result = Integer::Handle(
         Z, Evaluator::BinaryIntegerEvaluate(left, right, binary_op->op_kind(),
                                             binary_op->is_truncating(),
@@ -1166,7 +1208,10 @@
 
 void ConstantPropagator::VisitUnaryIntegerOp(UnaryIntegerOpInstr* unary_op) {
   const Object& value = unary_op->value()->definition()->constant_value();
-  if (IsConstant(value)) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsInteger()) {
     const Integer& result = Integer::Handle(
         Z, Evaluator::UnaryIntegerEvaluate(value, unary_op->op_kind(),
                                            unary_op->representation(), T));
@@ -1175,7 +1220,6 @@
       return;
     }
   }
-
   SetValue(unary_op, non_constant_);
 }
 
@@ -1188,44 +1232,48 @@
 }
 
 void ConstantPropagator::VisitUnaryDoubleOp(UnaryDoubleOpInstr* instr) {
-  const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    // TODO(kmillikin): Handle unary operations.
-    SetValue(instr, non_constant_);
-  }
+  // TODO(kmillikin): Handle unary operations.
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitSmiToDouble(SmiToDoubleInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
-  if (IsConstant(value) && value.IsInteger()) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsInteger()) {
     SetValue(instr,
              Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(),
                                            Heap::kOld)));
-  } else if (!IsUnknown(value)) {
+  } else {
     SetValue(instr, non_constant_);
   }
 }
 
 void ConstantPropagator::VisitInt64ToDouble(Int64ToDoubleInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
-  if (IsConstant(value) && value.IsInteger()) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsInteger()) {
     SetValue(instr,
              Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(),
                                            Heap::kOld)));
-  } else if (!IsUnknown(value)) {
+  } else {
     SetValue(instr, non_constant_);
   }
 }
 
 void ConstantPropagator::VisitInt32ToDouble(Int32ToDoubleInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
-  if (IsConstant(value) && value.IsInteger()) {
+  if (IsUnknown(value)) {
+    return;
+  }
+  if (value.IsInteger()) {
     SetValue(instr,
              Double::Handle(Z, Double::New(Integer::Cast(value).AsDoubleValue(),
                                            Heap::kOld)));
-  } else if (!IsUnknown(value)) {
+  } else {
     SetValue(instr, non_constant_);
   }
 }
@@ -1300,23 +1348,30 @@
 void ConstantPropagator::VisitBinaryDoubleOp(BinaryDoubleOpInstr* instr) {
   const Object& left = instr->left()->definition()->constant_value();
   const Object& right = instr->right()->definition()->constant_value();
-  if (IsConstant(left) && IsConstant(right)) {
-    const bool both_are_integers = left.IsInteger() && right.IsInteger();
-    if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
-        !both_are_integers) {
-      const double result_val = Evaluator::EvaluateDoubleOp(
-          ToDouble(left), ToDouble(right), instr->op_kind());
-      const Double& result =
-          Double::ZoneHandle(Double::NewCanonical(result_val));
-      SetValue(instr, result);
-      return;
-    }
+  if (IsNonConstant(left) || IsNonConstant(right)) {
+    SetValue(instr, non_constant_);
+    return;
+  } else if (IsUnknown(left) || IsUnknown(right)) {
+    return;
+  }
+  ASSERT(IsConstant(left) && IsConstant(right));
+  const bool both_are_integers = left.IsInteger() && right.IsInteger();
+  if (IsIntegerOrDouble(left) && IsIntegerOrDouble(right) &&
+      !both_are_integers) {
+    const double result_val = Evaluator::EvaluateDoubleOp(
+        ToDouble(left), ToDouble(right), instr->op_kind());
+    const Double& result = Double::ZoneHandle(Double::NewCanonical(result_val));
+    SetValue(instr, result);
+    return;
   }
   SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitDoubleTestOp(DoubleTestOpInstr* instr) {
   const Object& value = instr->value()->definition()->constant_value();
+  if (IsUnknown(value)) {
+    return;
+  }
   const bool is_negated = instr->kind() != Token::kEQ;
   if (value.IsInteger()) {
     SetValue(instr, is_negated ? Bool::True() : Bool::False());
@@ -1345,24 +1400,13 @@
 }
 
 void ConstantPropagator::VisitMathUnary(MathUnaryInstr* instr) {
-  const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin).
-    SetValue(instr, non_constant_);
-  }
+  // TODO(kmillikin): Handle Math's unary operations (sqrt, cos, sin).
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitMathMinMax(MathMinMaxInstr* instr) {
-  const Object& left = instr->left()->definition()->constant_value();
-  const Object& right = instr->right()->definition()->constant_value();
-  if (IsNonConstant(left) || IsNonConstant(right)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(left) && IsConstant(right)) {
-    // TODO(srdjan): Handle min and max.
-    SetValue(instr, non_constant_);
-  }
+  // TODO(srdjan): Handle min and max.
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitCaseInsensitiveCompare(
@@ -1371,23 +1415,13 @@
 }
 
 void ConstantPropagator::VisitUnbox(UnboxInstr* instr) {
-  const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    // TODO(kmillikin): Handle conversion.
-    SetValue(instr, non_constant_);
-  }
+  // TODO(kmillikin): Handle conversion.
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitBox(BoxInstr* instr) {
-  const Object& value = instr->value()->definition()->constant_value();
-  if (IsNonConstant(value)) {
-    SetValue(instr, non_constant_);
-  } else if (IsConstant(value)) {
-    // TODO(kmillikin): Handle conversion.
-    SetValue(instr, non_constant_);
-  }
+  // TODO(kmillikin): Handle conversion.
+  SetValue(instr, non_constant_);
 }
 
 void ConstantPropagator::VisitBoxUint32(BoxUint32Instr* instr) {
@@ -1675,10 +1709,8 @@
     if ((constant_value_.IsString() || constant_value_.IsMint() ||
          constant_value_.IsDouble()) &&
         !constant_value_.IsCanonical()) {
-      const char* error_str = nullptr;
-      constant_value_ =
-          Instance::Cast(constant_value_).CheckAndCanonicalize(T, &error_str);
-      ASSERT(!constant_value_.IsNull() && (error_str == nullptr));
+      constant_value_ = Instance::Cast(constant_value_).Canonicalize(T);
+      ASSERT(!constant_value_.IsNull());
     }
     if (auto call = defn->AsStaticCall()) {
       ASSERT(!call->HasPushArguments());
diff --git a/runtime/vm/compiler/backend/evaluator.cc b/runtime/vm/compiler/backend/evaluator.cc
index 18e9856..ce4660c 100644
--- a/runtime/vm/compiler/backend/evaluator.cc
+++ b/runtime/vm/compiler/backend/evaluator.cc
@@ -115,11 +115,7 @@
       // specialized instructions that use this value under this assumption.
       return Integer::null();
     }
-    const char* error_str = NULL;
-    result ^= result.CheckAndCanonicalize(thread, &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
+    result ^= result.Canonicalize(thread);
   }
 
   return result.raw();
@@ -148,11 +144,7 @@
       return Integer::null();
     }
 
-    const char* error_str = NULL;
-    result ^= result.CheckAndCanonicalize(thread, &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
+    result ^= result.Canonicalize(thread);
   }
 
   return result.raw();
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 9196b2d..82430b4 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1453,13 +1453,23 @@
           // there as incoming value by renaming or it was stored there by
           // StoreLocal which took this Phi from another local via LoadLocal,
           // to which this reasoning applies recursively.
+          //
           // This means that we are guaranteed to process LoadLocal for a
-          // matching variable first.
+          // matching variable first, unless there was an OSR with a non-empty
+          // expression stack. In the latter case, Phi inserted by
+          // FlowGraph::AddSyntheticPhis for expression temp will not have an
+          // assigned type and may be accessed by StoreLocal and subsequent
+          // LoadLocal.
+          //
           if (!phi->HasType()) {
-            ASSERT((index < phi->block()->phis()->length()) &&
-                   ((*phi->block()->phis())[index] == phi));
-            phi->UpdateType(
-                CompileType::FromAbstractType(load->local().type()));
+            // Check if phi corresponds to the same slot.
+            auto* phis = phi->block()->phis();
+            if ((index < phis->length()) && (*phis)[index] == phi) {
+              phi->UpdateType(
+                  CompileType::FromAbstractType(load->local().type()));
+            } else {
+              ASSERT(IsCompiledForOsr() && (phi->block()->stack_depth() > 0));
+            }
           }
         }
         break;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 9c7eabc..6a01f8a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -164,7 +164,7 @@
   const bool stack_traces_only = false;
 #endif
   code_source_map_builder_ = new (zone_)
-      CodeSourceMapBuilder(stack_traces_only, caller_inline_id,
+      CodeSourceMapBuilder(zone_, stack_traces_only, caller_inline_id,
                            inline_id_to_token_pos, inline_id_to_function);
 
   ArchSpecificInitialization();
@@ -195,7 +195,9 @@
 }
 
 void FlowGraphCompiler::InitCompiler() {
-  pc_descriptors_list_ = new (zone()) DescriptorList(64);
+  compressed_stackmaps_builder_ =
+      new (zone()) CompressedStackMapsBuilder(zone());
+  pc_descriptors_list_ = new (zone()) DescriptorList(zone());
   exception_handlers_list_ = new (zone()) ExceptionHandlerList();
 #if defined(DART_PRECOMPILER)
   catch_entry_moves_maps_builder_ = new (zone()) CatchEntryMovesMapBuilder();
@@ -1001,8 +1003,8 @@
       bitmap->Set(bitmap->Length(), true);
     }
 
-    compressed_stackmaps_builder()->AddEntry(assembler()->CodeSize(), bitmap,
-                                             spill_area_size);
+    compressed_stackmaps_builder_->AddEntry(assembler()->CodeSize(), bitmap,
+                                            spill_area_size);
   }
 }
 
@@ -1157,15 +1159,11 @@
 }
 
 void FlowGraphCompiler::FinalizeStackMaps(const Code& code) {
-  if (compressed_stackmaps_builder_ == NULL) {
-    code.set_compressed_stackmaps(
-        CompressedStackMaps::Handle(CompressedStackMaps::null()));
-  } else {
-    // Finalize the compressed stack maps and add it to the code object.
-    const auto& maps =
-        CompressedStackMaps::Handle(compressed_stackmaps_builder_->Finalize());
-    code.set_compressed_stackmaps(maps);
-  }
+  ASSERT(compressed_stackmaps_builder_ != NULL);
+  // Finalize the compressed stack maps and add it to the code object.
+  const auto& maps =
+      CompressedStackMaps::Handle(compressed_stackmaps_builder_->Finalize());
+  code.set_compressed_stackmaps(maps);
 }
 
 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 9b1764e..cff19a26 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -1108,13 +1108,6 @@
 
   intptr_t GetOptimizationThreshold() const;
 
-  CompressedStackMapsBuilder* compressed_stackmaps_builder() {
-    if (compressed_stackmaps_builder_ == NULL) {
-      compressed_stackmaps_builder_ = new CompressedStackMapsBuilder();
-    }
-    return compressed_stackmaps_builder_;
-  }
-
 #if defined(DEBUG)
   void FrameStateUpdateWith(Instruction* instr);
   void FrameStatePush(Definition* defn);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index aa5891d..cf1fd3a 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -997,6 +997,26 @@
   ASSERT(!CompilerState::Current().is_aot());
 }
 
+LocationSummary* AllocateTypedDataInstr::MakeLocationSummary(Zone* zone,
+                                                             bool opt) const {
+  const intptr_t kNumInputs = 1;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(kLengthPos, Location::RegisterLocation(
+                               AllocateTypedDataArrayABI::kLengthReg));
+  locs->set_out(
+      0, Location::RegisterLocation(AllocateTypedDataArrayABI::kResultReg));
+  return locs;
+}
+
+void AllocateTypedDataInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  const Code& stub = Code::ZoneHandle(
+      compiler->zone(), StubCode::GetAllocationStubForTypedData(class_id()));
+  compiler->GenerateStubCall(token_pos(), stub, PcDescriptorsLayout::kOther,
+                             locs());
+}
+
 bool StoreInstanceFieldInstr::IsUnboxedStore() const {
   return slot().IsDartField() &&
          FlowGraphCompiler::IsUnboxedField(slot().field());
@@ -2896,6 +2916,11 @@
       if (slot().kind() == Slot::Kind::kArray_length) {
         return create_array->num_elements()->definition();
       }
+    } else if (AllocateTypedDataInstr* alloc_typed_data =
+                   array->AsAllocateTypedData()) {
+      if (slot().kind() == Slot::Kind::kTypedDataBase_length) {
+        return alloc_typed_data->num_elements()->definition();
+      }
     } else if (LoadFieldInstr* load_array = array->AsLoadField()) {
       // For arrays with guarded lengths, replace the length load
       // with a constant.
@@ -3085,7 +3110,7 @@
     if (new_dst_type.IsTypeRef()) {
       new_dst_type = TypeRef::Cast(new_dst_type).type();
     }
-    new_dst_type = new_dst_type.Canonicalize();
+    new_dst_type = new_dst_type.Canonicalize(Thread::Current(), nullptr);
 
     // Successfully instantiated destination type: update the type attached
     // to this instruction and set type arguments to null because we no
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 2d73e68..3cab656 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -426,6 +426,7 @@
   M(InstanceOf, _)                                                             \
   M(CreateArray, _)                                                            \
   M(AllocateObject, _)                                                         \
+  M(AllocateTypedData, _)                                                      \
   M(LoadField, _)                                                              \
   M(LoadUntagged, kNoGC)                                                       \
   M(StoreUntagged, kNoGC)                                                      \
@@ -6243,6 +6244,52 @@
   DISALLOW_COPY_AND_ASSIGN(CreateArrayInstr);
 };
 
+class AllocateTypedDataInstr : public TemplateAllocation<1, Throws> {
+ public:
+  AllocateTypedDataInstr(TokenPosition token_pos,
+                         classid_t class_id,
+                         Value* num_elements,
+                         intptr_t deopt_id)
+      : TemplateAllocation(deopt_id),
+        token_pos_(token_pos),
+        class_id_(class_id),
+        identity_(AliasIdentity::Unknown()) {
+    SetInputAt(kLengthPos, num_elements);
+  }
+
+  enum { kLengthPos = 0 };
+
+  DECLARE_INSTRUCTION(AllocateTypedData)
+  virtual CompileType ComputeType() const;
+
+  virtual TokenPosition token_pos() const { return token_pos_; }
+  classid_t class_id() const { return class_id_; }
+  Value* num_elements() const { return inputs_[kLengthPos]; }
+
+  // Throw needs environment, which is created only if instruction can
+  // deoptimize.
+  virtual bool ComputeCanDeoptimize() const {
+    return !CompilerState::Current().is_aot();
+  }
+
+  virtual bool HasUnknownSideEffects() const { return false; }
+
+  virtual AliasIdentity Identity() const { return identity_; }
+  virtual void SetIdentity(AliasIdentity identity) { identity_ = identity; }
+
+  virtual bool WillAllocateNewOrRemembered() const {
+    // No write barriers are generated for typed data accesses.
+    return false;
+  }
+
+ private:
+  const TokenPosition token_pos_;
+  classid_t class_id_;
+  AliasIdentity identity_;
+
+  DISALLOW_COPY_AND_ASSIGN(AllocateTypedDataInstr);
+};
+
 // Note: This instruction must not be moved without the indexed access that
 // depends on it (e.g. out of loops). GC may collect the array while the
 // external data-array is still accessed.
@@ -6497,32 +6544,38 @@
   DISALLOW_COPY_AND_ASSIGN(InstantiateTypeInstr);
 };
 
-class InstantiateTypeArgumentsInstr : public TemplateDefinition<2, Throws> {
+class InstantiateTypeArgumentsInstr : public TemplateDefinition<3, Throws> {
  public:
   InstantiateTypeArgumentsInstr(TokenPosition token_pos,
-                                const TypeArguments& type_arguments,
-                                const Class& instantiator_class,
-                                const Function& function,
                                 Value* instantiator_type_arguments,
                                 Value* function_type_arguments,
+                                Value* type_arguments,
+                                const Class& instantiator_class,
+                                const Function& function,
                                 intptr_t deopt_id)
       : TemplateDefinition(deopt_id),
         token_pos_(token_pos),
-        type_arguments_(type_arguments),
         instantiator_class_(instantiator_class),
         function_(function) {
-    ASSERT(type_arguments.IsZoneHandle());
+    // These asserts hold for current uses.
+    ASSERT(type_arguments->BindsToConstant());
+    // Note: Non-dynamic uses never provide a null TypeArguments value.
+    ASSERT(!type_arguments->BoundConstant().IsNull());
+    ASSERT(type_arguments->BoundConstant().IsTypeArguments());
     ASSERT(instantiator_class.IsZoneHandle());
+    ASSERT(!instantiator_class.IsNull());
     ASSERT(function.IsZoneHandle());
+    ASSERT(!function.IsNull());
     SetInputAt(0, instantiator_type_arguments);
     SetInputAt(1, function_type_arguments);
+    SetInputAt(2, type_arguments);
   }
 
   DECLARE_INSTRUCTION(InstantiateTypeArguments)
 
   Value* instantiator_type_arguments() const { return inputs_[0]; }
   Value* function_type_arguments() const { return inputs_[1]; }
-  const TypeArguments& type_arguments() const { return type_arguments_; }
+  Value* type_arguments() const { return inputs_[2]; }
   const Class& instantiator_class() const { return instantiator_class_; }
   const Function& function() const { return function_; }
   virtual TokenPosition token_pos() const { return token_pos_; }
@@ -6537,12 +6590,18 @@
 
   const Code& GetStub() const {
     bool with_runtime_check;
-    if (type_arguments().CanShareInstantiatorTypeArguments(
-            instantiator_class(), &with_runtime_check)) {
+    ASSERT(!instantiator_class().IsNull());
+    ASSERT(!function().IsNull());
+    ASSERT(type_arguments()->BindsToConstant());
+    ASSERT(type_arguments()->BoundConstant().IsTypeArguments());
+    const auto& type_args =
+        TypeArguments::Cast(type_arguments()->BoundConstant());
+    if (type_args.CanShareInstantiatorTypeArguments(instantiator_class(),
+                                                    &with_runtime_check)) {
       ASSERT(with_runtime_check);
       return StubCode::InstantiateTypeArgumentsMayShareInstantiatorTA();
-    } else if (type_arguments().CanShareFunctionTypeArguments(
-                   function(), &with_runtime_check)) {
+    } else if (type_args.CanShareFunctionTypeArguments(function(),
+                                                       &with_runtime_check)) {
       ASSERT(with_runtime_check);
       return StubCode::InstantiateTypeArgumentsMayShareFunctionTA();
     }
@@ -6553,7 +6612,6 @@
 
  private:
   const TokenPosition token_pos_;
-  const TypeArguments& type_arguments_;
   const Class& instantiator_class_;
   const Function& function_;
 
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index 8aec81f..f678487 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -3492,7 +3492,7 @@
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
-  const intptr_t kNumInputs = 2;
+  const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
@@ -3500,6 +3500,8 @@
                       InstantiationABI::kInstantiatorTypeArgumentsReg));
   locs->set_in(1, Location::RegisterLocation(
                       InstantiationABI::kFunctionTypeArgumentsReg));
+  locs->set_in(2, Location::RegisterLocation(
+                      InstantiationABI::kUninstantiatedTypeArgumentsReg));
   locs->set_out(
       0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
   return locs;
@@ -3514,14 +3516,19 @@
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
 
+  compiler::Label type_arguments_instantiated;
+  ASSERT(!instantiator_class().IsNull());
+  ASSERT(type_arguments()->BindsToConstant());
+  const auto& type_args =
+      TypeArguments::Cast(type_arguments()->BoundConstant());
+
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
-  compiler::Label type_arguments_instantiated;
   const bool can_function_type_args_be_null =
       function_type_arguments()->CanBe(Object::null_object());
-  const intptr_t len = type_arguments().Length();
-  if (type_arguments().IsRawWhenInstantiatedFromRaw(len) &&
+  const intptr_t len = type_args.Length();
+  if (type_args.IsRawWhenInstantiatedFromRaw(len) &&
       can_function_type_args_be_null) {
     ASSERT(result_reg != instantiator_type_args_reg &&
            result_reg != function_type_args_reg);
@@ -3533,8 +3540,6 @@
     __ b(&type_arguments_instantiated, EQ);
   }
   // Lookup cache in stub before calling runtime.
-  __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
-                type_arguments());
   compiler->GenerateStubCall(token_pos(), GetStub(),
                              PcDescriptorsLayout::kOther, locs());
   __ Bind(&type_arguments_instantiated);
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 563bbe7..d67b7ad 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -1170,8 +1170,8 @@
                THR, compiler::target::Thread::
                         call_native_through_safepoint_entry_point_offset()));
 
-    // Calls R8 and clobbers R19 (along with volatile registers).
-    ASSERT(branch == R8 && temp == R19);
+    // Calls R9 and clobbers R19 (along with volatile registers).
+    ASSERT(branch == R9 && temp == R19);
     __ blr(TMP);
   }
 
@@ -2982,7 +2982,7 @@
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
-  const intptr_t kNumInputs = 2;
+  const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
@@ -2990,6 +2990,8 @@
                       InstantiationABI::kInstantiatorTypeArgumentsReg));
   locs->set_in(1, Location::RegisterLocation(
                       InstantiationABI::kFunctionTypeArgumentsReg));
+  locs->set_in(2, Location::RegisterLocation(
+                      InstantiationABI::kUninstantiatedTypeArgumentsReg));
   locs->set_out(
       0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
   return locs;
@@ -3001,17 +3003,21 @@
   const Register function_type_args_reg = locs()->in(1).reg();
   const Register result_reg = locs()->out(0).reg();
 
+  compiler::Label type_arguments_instantiated;
+  ASSERT(!instantiator_class().IsNull());
+  ASSERT(type_arguments()->BindsToConstant());
+  const auto& type_args =
+      TypeArguments::Cast(type_arguments()->BoundConstant());
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
 
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
-  compiler::Label type_arguments_instantiated;
-  const intptr_t len = type_arguments().Length();
+  const intptr_t len = type_args.Length();
   const bool can_function_type_args_be_null =
       function_type_arguments()->CanBe(Object::null_object());
-  if (type_arguments().IsRawWhenInstantiatedFromRaw(len) &&
+  if (type_args.IsRawWhenInstantiatedFromRaw(len) &&
       can_function_type_args_be_null) {
     compiler::Label non_null_type_args;
     ASSERT(result_reg != instantiator_type_args_reg &&
@@ -3026,8 +3032,6 @@
     __ Bind(&non_null_type_args);
   }
   // Lookup cache in stub before calling runtime.
-  __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
-                type_arguments());
   compiler->GenerateStubCall(token_pos(), GetStub(),
                              PcDescriptorsLayout::kOther, locs());
   __ Bind(&type_arguments_instantiated);
diff --git a/runtime/vm/compiler/backend/il_deserializer.cc b/runtime/vm/compiler/backend/il_deserializer.cc
index ca7bd32..f84b7e5 100644
--- a/runtime/vm/compiler/backend/il_deserializer.cc
+++ b/runtime/vm/compiler/backend/il_deserializer.cc
@@ -1529,16 +1529,11 @@
                                                  Object* out) {
   ASSERT(out != nullptr);
   if (!out->IsInstance()) return true;
-  const char* error_str = nullptr;
-  // CheckAndCanonicalize uses the current zone for the passed in thread,
+  // Instance::Canonicalize uses the current zone for the passed in thread,
   // not an explicitly provided zone. This means we cannot be run in a context
   // where [thread()->zone()] does not match [zone()] (e.g., due to StackZone)
   // until this is addressed.
-  *out = Instance::Cast(*out).CheckAndCanonicalize(thread(), &error_str);
-  if (error_str != nullptr) {
-    StoreError(sexp, "error during canonicalization: %s", error_str);
-    return false;
-  }
+  *out = Instance::Cast(*out).Canonicalize(thread());
   return true;
 }
 
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 767fb3f..a7bc3b3 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2766,7 +2766,7 @@
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
-  const intptr_t kNumInputs = 2;
+  const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
@@ -2774,6 +2774,8 @@
                       InstantiationABI::kInstantiatorTypeArgumentsReg));
   locs->set_in(1, Location::RegisterLocation(
                       InstantiationABI::kFunctionTypeArgumentsReg));
+  locs->set_in(2, Location::RegisterLocation(
+                      InstantiationABI::kUninstantiatedTypeArgumentsReg));
   locs->set_out(
       0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
   return locs;
@@ -2785,17 +2787,21 @@
   Register function_type_args_reg = locs()->in(1).reg();
   Register result_reg = locs()->out(0).reg();
 
+  compiler::Label type_arguments_instantiated;
+  ASSERT(!instantiator_class().IsNull());
+  ASSERT(type_arguments()->BindsToConstant());
+  const auto& type_args =
+      TypeArguments::Cast(type_arguments()->BoundConstant());
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
 
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
-  compiler::Label type_arguments_instantiated;
-  const intptr_t len = type_arguments().Length();
+  const intptr_t len = type_args.Length();
   const bool can_function_type_args_be_null =
       function_type_arguments()->CanBe(Object::null_object());
-  if (type_arguments().IsRawWhenInstantiatedFromRaw(len) &&
+  if (type_args.IsRawWhenInstantiatedFromRaw(len) &&
       can_function_type_args_be_null) {
     compiler::Label non_null_type_args;
     ASSERT(result_reg != instantiator_type_args_reg &&
@@ -2810,8 +2816,6 @@
     __ Bind(&non_null_type_args);
   }
   // Lookup cache in stub before calling runtime.
-  __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
-                type_arguments());
   compiler->GenerateStubCall(token_pos(), GetStub(),
                              PcDescriptorsLayout::kOther, locs());
   __ Bind(&type_arguments_instantiated);
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 3f921d2..62b7000 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -688,13 +688,15 @@
 }
 
 void InstantiateTypeArgumentsInstr::PrintOperandsTo(BaseTextBuffer* f) const {
-  const String& type_args = String::Handle(type_arguments().Name());
-  f->Printf("%s,", type_args.ToCString());
-  f->AddString(" instantiator_type_args(");
+  type_arguments()->PrintTo(f);
+  f->AddString(", instantiator_type_args(");
   instantiator_type_arguments()->PrintTo(f);
   f->AddString("), function_type_args(");
   function_type_arguments()->PrintTo(f);
-  f->Printf("), instantiator_class(%s)", instantiator_class().ToCString());
+  f->Printf(")");
+  if (!instantiator_class().IsNull()) {
+    f->Printf(", instantiator_class(%s)", instantiator_class().ToCString());
+  }
 }
 
 void AllocateContextInstr::PrintOperandsTo(BaseTextBuffer* f) const {
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 9c5788a..f4d002b 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -307,6 +307,13 @@
     }
   }
 
+  if (opcode == kMoveDebugStepChecks) {
+    while (cursor != nullptr && cursor->IsDebugStepCheck()) {
+      cursor = cursor->next();
+    }
+    return cursor;
+  }
+
   if (opcode == kMatchAndMoveGoto) {
     if (auto goto_instr = cursor->AsGoto()) {
       return goto_instr->successor();
@@ -362,6 +369,9 @@
   if (opcode == kMoveGlob) {
     return "kMoveGlob";
   }
+  if (opcode == kMoveDebugStepChecks) {
+    return "kMoveDebugStepChecks";
+  }
 
   switch (opcode) {
 #define EMIT_CASE(Instruction, _)                                              \
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index ec00bb7..01da0c3 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -122,6 +122,9 @@
   // Moves forward until the next match code matches.
   kMoveGlob,
 
+  // Moves over any DebugStepChecks.
+  kMoveDebugStepChecks,
+
   // Invalid match opcode used as default [insert_before] argument to TryMatch
   // to signal that no insertions should occur.
   kInvalidMatchOpCode,
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 70f492c..d3842d1 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -3016,7 +3016,7 @@
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
-  const intptr_t kNumInputs = 2;
+  const intptr_t kNumInputs = 3;
   const intptr_t kNumTemps = 0;
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
@@ -3024,6 +3024,8 @@
                       InstantiationABI::kInstantiatorTypeArgumentsReg));
   locs->set_in(1, Location::RegisterLocation(
                       InstantiationABI::kFunctionTypeArgumentsReg));
+  locs->set_in(2, Location::RegisterLocation(
+                      InstantiationABI::kUninstantiatedTypeArgumentsReg));
   locs->set_out(
       0, Location::RegisterLocation(InstantiationABI::kResultTypeArgumentsReg));
   return locs;
@@ -3035,17 +3037,21 @@
   Register function_type_args_reg = locs()->in(1).reg();
   Register result_reg = locs()->out(0).reg();
 
+  compiler::Label type_arguments_instantiated;
+  ASSERT(!instantiator_class().IsNull());
+  ASSERT(type_arguments()->BindsToConstant());
+  const auto& type_args =
+      TypeArguments::Cast(type_arguments()->BoundConstant());
   // 'instantiator_type_args_reg' is a TypeArguments object (or null).
   // 'function_type_args_reg' is a TypeArguments object (or null).
 
   // If both the instantiator and function type arguments are null and if the
   // type argument vector instantiated from null becomes a vector of dynamic,
   // then use null as the type arguments.
-  compiler::Label type_arguments_instantiated;
-  const intptr_t len = type_arguments().Length();
+  const intptr_t len = type_args.Length();
   const bool can_function_type_args_be_null =
       function_type_arguments()->CanBe(Object::null_object());
-  if (type_arguments().IsRawWhenInstantiatedFromRaw(len) &&
+  if (type_args.IsRawWhenInstantiatedFromRaw(len) &&
       can_function_type_args_be_null) {
     compiler::Label non_null_type_args;
     ASSERT(result_reg != instantiator_type_args_reg &&
@@ -3059,8 +3065,7 @@
     __ j(EQUAL, &type_arguments_instantiated, compiler::Assembler::kNearJump);
     __ Bind(&non_null_type_args);
   }
-  __ LoadObject(InstantiationABI::kUninstantiatedTypeArgumentsReg,
-                type_arguments());
+  // Lookup cache in stub before calling runtime.
   compiler->GenerateStubCall(token_pos(), GetStub(),
                              PcDescriptorsLayout::kOther, locs());
   __ Bind(&type_arguments_instantiated);
diff --git a/runtime/vm/compiler/backend/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index 1a4d8af..4ab46bc 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination.cc
@@ -443,6 +443,7 @@
   static bool IsAllocation(Definition* defn) {
     return (defn != NULL) &&
            (defn->IsAllocateObject() || defn->IsCreateArray() ||
+            defn->IsAllocateTypedData() ||
             defn->IsAllocateUninitializedContext() ||
             (defn->IsStaticCall() &&
              defn->AsStaticCall()->IsRecognizedFactory()));
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index 01c3fbd..2225ab8 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -732,7 +732,7 @@
   auto entry = flow_graph->graph_entry()->normal_entry();
   EXPECT(entry != nullptr);
 
-  StaticCallInstr* list_factory = nullptr;
+  AllocateTypedDataInstr* alloc_typed_data = nullptr;
   UnboxedConstantInstr* double_one = nullptr;
   StoreIndexedInstr* first_store = nullptr;
   StoreIndexedInstr* second_store = nullptr;
@@ -742,7 +742,7 @@
   ILMatcher cursor(flow_graph, entry);
   RELEASE_ASSERT(cursor.TryMatch(
       {
-          {kMatchAndMoveStaticCall, &list_factory},
+          {kMatchAndMoveAllocateTypedData, &alloc_typed_data},
           {kMatchAndMoveUnboxedConstant, &double_one},
           {kMatchAndMoveStoreIndexed, &first_store},
           {kMatchAndMoveStoreIndexed, &second_store},
@@ -752,8 +752,8 @@
       },
       /*insert_before=*/kMoveGlob));
 
-  EXPECT(first_store->array()->definition() == list_factory);
-  EXPECT(second_store->array()->definition() == list_factory);
+  EXPECT(first_store->array()->definition() == alloc_typed_data);
+  EXPECT(second_store->array()->definition() == alloc_typed_data);
   EXPECT(boxed_result->value()->definition() != double_one);
   EXPECT(boxed_result->value()->definition() == final_load);
 }
@@ -855,7 +855,7 @@
   auto entry = flow_graph->graph_entry()->normal_entry();
   EXPECT(entry != nullptr);
 
-  StaticCallInstr* list_factory = nullptr;
+  AllocateTypedDataInstr* alloc_typed_data = nullptr;
   UnboxedConstantInstr* double_one = nullptr;
   StoreIndexedInstr* first_store = nullptr;
   StoreIndexedInstr* second_store = nullptr;
@@ -865,7 +865,7 @@
   ILMatcher cursor(flow_graph, entry);
   RELEASE_ASSERT(cursor.TryMatch(
       {
-          {kMatchAndMoveStaticCall, &list_factory},
+          {kMatchAndMoveAllocateTypedData, &alloc_typed_data},
           kMatchAndMoveBranchTrue,
           kMatchAndMoveBranchTrue,
           kMatchAndMoveBranchFalse,
@@ -880,8 +880,8 @@
       },
       /*insert_before=*/kMoveGlob));
 
-  EXPECT(first_store->array()->definition() == list_factory);
-  EXPECT(second_store->array()->definition() == list_factory);
+  EXPECT(first_store->array()->definition() == alloc_typed_data);
+  EXPECT(second_store->array()->definition() == alloc_typed_data);
   EXPECT(boxed_result->value()->definition() != double_one);
   EXPECT(boxed_result->value()->definition() == final_load);
 }
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index eab2e16..3877f45 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1405,6 +1405,12 @@
 }
 
 CompileType LoadLocalInstr::ComputeType() const {
+  if (local().needs_covariant_check_in_method()) {
+    // We may not yet have checked the actual type of the parameter value.
+    // Assuming that the value has the required type can lead to unsound
+    // optimizations. See dartbug.com/43464.
+    return CompileType::FromCid(kDynamicCid);
+  }
   const AbstractType& local_type = local().type();
   TraceStrongModeType(this, local_type);
   return CompileType::FromAbstractType(local_type);
@@ -1467,6 +1473,10 @@
   return CompileType::FromCid(kArrayCid);
 }
 
+CompileType AllocateTypedDataInstr::ComputeType() const {
+  return CompileType::FromCid(class_id());
+}
+
 CompileType AllocateObjectInstr::ComputeType() const {
   if (!closure_function().IsNull()) {
     ASSERT(cls().id() == kClosureCid);
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index d978e86..30d58db 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -451,6 +451,61 @@
   }
 }
 
+ISOLATE_UNIT_TEST_CASE(IRTest_TypedDataAOT_Regress43534) {
+  const char* kScript =
+      R"(
+      import 'dart:typed_data';
+
+      @pragma('vm:never-inline')
+      void callWith<T>(void Function(T arg) fun, T arg) {
+        fun(arg);
+      }
+
+      void test() {
+        callWith<Uint8List>((Uint8List list) {
+          if (list[0] != 0) throw 'a';
+        }, Uint8List(10));
+      }
+      )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  Invoke(root_library, "test");
+  const auto& test_function =
+      Function::Handle(GetFunction(root_library, "test"));
+  const auto& closures = GrowableObjectArray::Handle(
+      Isolate::Current()->object_store()->closure_functions());
+  auto& function = Function::Handle();
+  for (intptr_t i = closures.Length() - 1; 0 <= i; ++i) {
+    function ^= closures.At(i);
+    if (function.parent_function() == test_function.raw()) {
+      break;
+    }
+    function = Function::null();
+  }
+  RELEASE_ASSERT(!function.IsNull());
+  TestPipeline pipeline(function, CompilerPass::kAOT);
+  FlowGraph* flow_graph = pipeline.RunPasses({});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true);
+  RELEASE_ASSERT(cursor.TryMatch(
+      {
+          kMatchAndMoveGoto,
+          kMatchAndMoveBranchFalse,
+          kMatchAndMoveAssertAssignable,
+          kMatchAndMoveGoto,
+          kMatchAndMoveLoadField,
+          kMatchAndMoveGenericCheckBound,
+          kMatchAndMoveLoadUntagged,
+          kMatchAndMoveLoadIndexed,
+          kMatchAndMoveBranchFalse,
+          kMoveGlob,
+          kMatchReturn,
+      },
+      kMoveGlob));
+}
+
 #endif  // defined(DART_PRECOMPILER)
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 2c7f4dc..d1ad68b 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1571,16 +1571,17 @@
 
     const intptr_t receiver_index = call->FirstArgIndex();
 
-    CompileType* receiver_type = call->ArgumentAt(receiver_index + 0)->Type();
+    CompileType* receiver_type =
+        call->ArgumentValueAt(receiver_index + 0)->Type();
 
     CompileType* index_type = nullptr;
     if (is_index_get || is_index_set) {
-      index_type = call->ArgumentAt(receiver_index + 1)->Type();
+      index_type = call->ArgumentValueAt(receiver_index + 1)->Type();
     }
 
     CompileType* value_type = nullptr;
     if (is_index_set) {
-      value_type = call->ArgumentAt(receiver_index + 2)->Type();
+      value_type = call->ArgumentValueAt(receiver_index + 2)->Type();
     }
 
     auto& type_class = Class::Handle(zone_);
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index 3c72125..0efb336 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -187,6 +187,8 @@
   "backend/typed_data_aot_test.cc",
   "backend/yield_position_test.cc",
   "cha_test.cc",
+  "frontend/kernel_binary_flowgraph_test.cc",
+  "frontend/multiple_entrypoints_test.cc",
   "write_barrier_elimination_test.cc",
 ]
 
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index fdcd957..7bb9096 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
@@ -682,10 +682,15 @@
   return instructions;
 }
 
-LocalVariable* BaseFlowGraphBuilder::MakeTemporary() {
-  char name[64];
+LocalVariable* BaseFlowGraphBuilder::MakeTemporary(const char* suffix) {
+  static constexpr intptr_t kTemporaryNameLength = 64;
+  char name[kTemporaryNameLength];
   intptr_t index = stack_->definition()->temp_index();
-  Utils::SNPrint(name, 64, ":t%" Pd, index);
+  if (suffix != nullptr) {
+    Utils::SNPrint(name, kTemporaryNameLength, ":t_%s", suffix);
+  } else {
+    Utils::SNPrint(name, kTemporaryNameLength, ":t%" Pd, index);
+  }
   const String& symbol_name =
       String::ZoneHandle(Z, Symbols::New(thread_, name));
   LocalVariable* variable =
@@ -707,6 +712,16 @@
   return variable;
 }
 
+Fragment BaseFlowGraphBuilder::DropTemporary(LocalVariable** temp) {
+  ASSERT(temp != nullptr && *temp != nullptr && (*temp)->HasIndex());
+  // Check that the temporary matches the current stack definition.
+  ASSERT_EQUAL(
+      stack_->definition()->temp_index(),
+      -(*temp)->index().value() - parsed_function_->num_stack_locals());
+  *temp = nullptr;  // Clear to avoid inadvertent usage after dropping.
+  return Drop();
+}
+
 void BaseFlowGraphBuilder::SetTempIndex(Definition* definition) {
   definition->set_temp_index(
       stack_ == NULL ? 0 : stack_->definition()->temp_index() + 1);
@@ -915,6 +930,15 @@
   return Fragment(array);
 }
 
+Fragment BaseFlowGraphBuilder::AllocateTypedData(TokenPosition position,
+                                                 classid_t class_id) {
+  Value* num_elements = Pop();
+  auto* instr = new (Z) AllocateTypedDataInstr(position, class_id, num_elements,
+                                               GetNextDeoptId());
+  Push(instr);
+  return Fragment(instr);
+}
+
 Fragment BaseFlowGraphBuilder::InstantiateType(const AbstractType& type) {
   Value* function_type_args = Pop();
   Value* instantiator_type_args = Pop();
@@ -926,15 +950,20 @@
 }
 
 Fragment BaseFlowGraphBuilder::InstantiateTypeArguments(
-    const TypeArguments& type_arguments) {
+    const TypeArguments& type_arguments_value) {
+  Fragment instructions;
+  instructions += Constant(type_arguments_value);
+
+  Value* type_arguments = Pop();
   Value* function_type_args = Pop();
   Value* instantiator_type_args = Pop();
   const Class& instantiator_class = Class::ZoneHandle(Z, function_.Owner());
   InstantiateTypeArgumentsInstr* instr = new (Z) InstantiateTypeArgumentsInstr(
-      TokenPosition::kNoSource, type_arguments, instantiator_class, function_,
-      instantiator_type_args, function_type_args, GetNextDeoptId());
+      TokenPosition::kNoSource, instantiator_type_args, function_type_args,
+      type_arguments, instantiator_class, function_, GetNextDeoptId());
   Push(instr);
-  return Fragment(instr);
+  instructions += Fragment(instr);
+  return instructions;
 }
 
 Fragment BaseFlowGraphBuilder::LoadClassId() {
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.h b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
index 6cfd0b8..4753533 100644
--- a/runtime/vm/compiler/frontend/base_flow_graph_builder.h
+++ b/runtime/vm/compiler/frontend/base_flow_graph_builder.h
@@ -183,6 +183,9 @@
   void SetTempIndex(Definition* definition);
 
   Fragment LoadLocal(LocalVariable* variable);
+  Fragment StoreLocal(LocalVariable* variable) {
+    return StoreLocal(TokenPosition::kNoSource, variable);
+  }
   Fragment StoreLocal(TokenPosition position, LocalVariable* variable);
   Fragment StoreLocalRaw(TokenPosition position, LocalVariable* variable);
   Fragment LoadContextAt(int depth);
@@ -242,8 +245,8 @@
   //       goto B3
   //     B3:
   //       LoadLocal(t)
-  //
-  LocalVariable* MakeTemporary();
+  LocalVariable* MakeTemporary(const char* suffix = nullptr);
+  Fragment DropTemporary(LocalVariable** temp);
 
   InputsArray* GetArguments(int count);
 
@@ -333,6 +336,7 @@
   Fragment AllocateClosure(TokenPosition position,
                            const Function& closure_function);
   Fragment CreateArray();
+  Fragment AllocateTypedData(TokenPosition position, classid_t class_id);
   Fragment InstantiateType(const AbstractType& type);
   Fragment InstantiateTypeArguments(const TypeArguments& type_arguments);
   Fragment LoadClassId();
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 3d9cb93..f130a7a 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -7,6 +7,7 @@
 #include "vm/bit_vector.h"
 #include "vm/bootstrap.h"
 #include "vm/class_finalizer.h"
+#include "vm/class_id.h"
 #include "vm/code_descriptors.h"
 #include "vm/compiler/aot/precompiler.h"  // For Obfuscator
 #include "vm/compiler/assembler/disassembler_kbc.h"
@@ -199,26 +200,18 @@
   const bool has_local_variables = (flags & Code::kHasLocalVariablesFlag) != 0;
   const bool has_nullable_fields = (flags & Code::kHasNullableFieldsFlag) != 0;
   const bool has_closures = (flags & Code::kHasClosuresFlag) != 0;
-  const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
+  const bool has_parameter_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
   const bool has_forwarding_stub_target =
       (flags & Code::kHasForwardingStubTargetFlag) != 0;
   const bool has_default_function_type_args =
       (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
-  if (has_parameters_flags) {
-    intptr_t num_params = reader_.ReadUInt();
-    ASSERT(num_params ==
-           function.NumParameters() - function.NumImplicitParameters());
-    for (intptr_t i = function.NumImplicitParameters();
-         i < function.NumParameters(); ++i) {
-      const intptr_t flags = reader_.ReadUInt();
-      if ((flags & Parameter::kIsRequiredFlag) != 0) {
-        RELEASE_ASSERT(i >= function.num_fixed_parameters());
-        function.SetIsRequiredAt(i);
-      }
+  if (has_parameter_flags) {
+    intptr_t num_flags = reader_.ReadUInt();
+    for (intptr_t i = 0; i < num_flags; ++i) {
+      reader_.ReadUInt();
     }
   }
-  function.TruncateUnusedParameterFlags();
   if (has_forwarding_stub_target) {
     reader_.ReadUInt();
   }
@@ -353,22 +346,19 @@
     AlternativeReadingScope alt(&reader_, function.bytecode_offset());
 
     const intptr_t flags = reader_.ReadUInt();
-    const bool has_parameters_flags =
+    const bool has_parameter_flags =
         (flags & Code::kHasParameterFlagsFlag) != 0;
     const bool has_forwarding_stub_target =
         (flags & Code::kHasForwardingStubTargetFlag) != 0;
     const bool has_default_function_type_args =
         (flags & Code::kHasDefaultFunctionTypeArgsFlag) != 0;
 
-    if (has_parameters_flags) {
-      intptr_t num_params = reader_.ReadUInt();
-      ASSERT(num_params ==
-             function.NumParameters() - function.NumImplicitParameters());
-      for (intptr_t i = 0; i < num_params; ++i) {
+    if (has_parameter_flags) {
+      intptr_t num_flags = reader_.ReadUInt();
+      for (intptr_t i = 0; i < num_flags; ++i) {
         reader_.ReadUInt();
       }
     }
-
     if (has_forwarding_stub_target) {
       reader_.ReadUInt();
     }
@@ -983,7 +973,7 @@
     const ObjectPool& pool = ObjectPool::Handle(Z, bytecode.object_pool());
     AbstractType& handler_type = AbstractType::Handle(Z);
     Array& handler_types = Array::Handle(Z);
-    DescriptorList* pc_descriptors_list = new (Z) DescriptorList(64);
+    DescriptorList* pc_descriptors_list = new (Z) DescriptorList(Z);
     ExceptionHandlerList* exception_handlers_list =
         new (Z) ExceptionHandlerList();
 
@@ -1101,6 +1091,10 @@
     case MethodRecognizer::kLinkedHashMap_getDeletedKeys:
     case MethodRecognizer::kLinkedHashMap_setDeletedKeys:
     case MethodRecognizer::kFfiAbi:
+#define TYPED_DATA_FACTORY(clazz)                                              \
+  case MethodRecognizer::kTypedData_##clazz##_factory:
+      CLASS_LIST_TYPED_DATA(TYPED_DATA_FACTORY)
+#undef TYPED_DATA_FACTORY
       break;
     case MethodRecognizer::kAsyncStackTraceHelper:
       // If causal async stacks are disabled the interpreter.cc will handle this
@@ -1757,7 +1751,7 @@
           Type::Handle(Z, Type::New(cls, type_arguments,
                                     TokenPosition::kNoSource, nullability));
       type.SetIsFinalized();
-      return type.Canonicalize();
+      return type.Canonicalize(thread_, nullptr);
     }
     case kRecursiveGenericType: {
       const intptr_t id = reader_.ReadUInt();
@@ -1795,7 +1789,7 @@
         // as not all TypeRef objects are filled up at this point.
         return type.raw();
       }
-      return type.Canonicalize();
+      return type.Canonicalize(thread_, nullptr);
     }
     case kRecursiveTypeRef: {
       const intptr_t id = reader_.ReadUInt();
@@ -1943,7 +1937,7 @@
     ASSERT(pending_recursive_types_ != nullptr);
     return type_arguments.raw();
   }
-  return type_arguments.Canonicalize();
+  return type_arguments.Canonicalize(thread_, nullptr);
 }
 
 void BytecodeReaderHelper::ReadAttributes(const Object& key) {
@@ -2245,6 +2239,7 @@
   const int kHasCustomScriptFlag = 1 << 22;
   const int kHasAttributesFlag = 1 << 23;
   const int kIsExtensionMemberFlag = 1 << 24;
+  const int kHasParameterFlagsFlag = 1 << 25;
 
   const intptr_t num_functions = reader_.ReadListLength();
   ASSERT(function_index_ + num_functions == functions_->Length());
@@ -2395,6 +2390,20 @@
       function.SetParameterTypeAt(param_index, type);
     }
 
+    if ((flags & kHasParameterFlagsFlag) != 0) {
+      const intptr_t length = reader_.ReadUInt();
+      const intptr_t offset = function.NumImplicitParameters();
+      for (intptr_t i = 0; i < length; i++) {
+        const intptr_t param_flags = reader_.ReadUInt();
+        if ((param_flags & Parameter::kIsRequiredFlag) != 0) {
+          RELEASE_ASSERT(function.HasOptionalNamedParameters());
+          RELEASE_ASSERT(i + offset >= function.num_fixed_parameters());
+          function.SetIsRequiredAt(i + offset);
+        }
+      }
+    }
+    function.TruncateUnusedParameterFlags();
+
     type ^= ReadObject();
     function.set_result_type(type);
 
@@ -3054,7 +3063,7 @@
   AlternativeReadingScope alt(&reader_, target.bytecode_offset());
 
   const intptr_t flags = reader_.ReadUInt();
-  const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
+  const bool has_parameter_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
   const bool has_forwarding_stub_target =
       (flags & Code::kHasForwardingStubTargetFlag) != 0;
   const bool has_default_function_type_args =
@@ -3066,22 +3075,15 @@
   const bool body_has_generic_covariant_impl_type_checks =
       proc_attrs.has_non_this_uses || proc_attrs.has_tearoff_uses;
 
-  if (has_parameters_flags) {
+  if (has_parameter_flags) {
     const intptr_t num_params = reader_.ReadUInt();
     const intptr_t num_implicit_params = function.NumImplicitParameters();
-    const intptr_t num_fixed_params = function.num_fixed_parameters();
     for (intptr_t i = 0; i < num_params; ++i) {
       const intptr_t flags = reader_.ReadUInt();
 
       bool is_covariant = (flags & Parameter::kIsCovariantFlag) != 0;
       bool is_generic_covariant_impl =
           (flags & Parameter::kIsGenericCovariantImplFlag) != 0;
-      bool is_required = (flags & Parameter::kIsRequiredFlag) != 0;
-
-      if (is_required) {
-        RELEASE_ASSERT(num_implicit_params + i >= num_fixed_params);
-        function.SetIsRequiredAt(num_implicit_params + i);
-      }
 
       LocalVariable* variable =
           parsed_function->ParameterVariable(num_implicit_params + i);
@@ -3101,7 +3103,6 @@
       }
     }
   }
-  function.TruncateUnusedParameterFlags();
 
   if (has_forwarding_stub_target) {
     const intptr_t cp_index = reader_.ReadUInt();
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index 243478f..981790a 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -278,7 +278,7 @@
       for (intptr_t j = 0; j < number_of_type_arguments; ++j) {
         type_arguments.SetTypeAt(j, type_translator.BuildType());
       }
-      type_arguments = type_arguments.Canonicalize();
+      type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
       // Make a copy of the old closure, and set delayed type arguments.
       Closure& closure = Closure::Handle(Z, Closure::RawCast(constant.raw()));
       Function& function = Function::Handle(Z, closure.function());
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index c2d252c..148a24a 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -479,7 +479,7 @@
     }
     helper.Finish();
   }
-  default_types = default_types.Canonicalize();
+  default_types = default_types.Canonicalize(thread(), nullptr);
   parsed_function()->SetDefaultFunctionTypeArguments(default_types);
 }
 
@@ -1284,10 +1284,6 @@
       return BuildPropertyGet(position);
     case kPropertySet:
       return BuildPropertySet(position);
-    case kDirectPropertyGet:
-      return BuildDirectPropertyGet(position);
-    case kDirectPropertySet:
-      return BuildDirectPropertySet(position);
     case kSuperPropertyGet:
       return BuildSuperPropertyGet(position);
     case kSuperPropertySet:
@@ -1300,8 +1296,6 @@
       return BuildMethodInvocation(position);
     case kSuperMethodInvocation:
       return BuildSuperMethodInvocation(position);
-    case kDirectMethodInvocation:
-      return BuildDirectMethodInvocation(position);
     case kStaticInvocation:
       return BuildStaticInvocation(position);
     case kConstructorInvocation:
@@ -2668,92 +2662,6 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildDirectPropertyGet(TokenPosition* p) {
-  const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
-  const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
-
-  const InferredTypeMetadata result_type =
-      inferred_type_metadata_helper_.GetInferredType(offset);
-
-  const Tag receiver_tag = PeekTag();         // peek tag for receiver.
-  Fragment instructions = BuildExpression();  // read receiver.
-  const NameIndex kernel_name =
-      ReadInterfaceMemberNameReference();  // read target_reference.
-
-  Function& target = Function::ZoneHandle(Z);
-  if (H.IsProcedure(kernel_name)) {
-    if (H.IsGetter(kernel_name)) {
-      target =
-          H.LookupMethodByMember(kernel_name, H.DartGetterName(kernel_name));
-    } else if (receiver_tag == kThisExpression) {
-      // Undo stack change for the BuildExpression.
-      Pop();
-
-      target =
-          H.LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name));
-      target = target.ImplicitClosureFunction();
-      ASSERT(!target.IsNull());
-
-      // Generate inline code for allocating closure object with context which
-      // captures `this`.
-      return BuildImplicitClosureCreation(target);
-    } else {
-      // Need to create implicit closure (tear-off), receiver != this.
-      // Ensure method extractor exists and call it directly.
-      const Function& target_method = Function::ZoneHandle(
-          Z,
-          H.LookupMethodByMember(kernel_name, H.DartMethodName(kernel_name)));
-      const String& getter_name = H.DartGetterName(kernel_name);
-      target = target_method.GetMethodExtractor(getter_name);
-    }
-  } else {
-    ASSERT(H.IsField(kernel_name));
-    const String& getter_name = H.DartGetterName(kernel_name);
-    target = H.LookupMethodByMember(kernel_name, getter_name);
-    ASSERT(target.IsGetterFunction() || target.IsImplicitGetterFunction());
-  }
-
-  // Static calls are marked as "no-rebind", which is currently safe because
-  // DirectPropertyGet are only used in enums (index in toString) and enums
-  // can't change their structure during hot reload.
-  // If there are other sources of DirectPropertyGet in the future, this code
-  // have to be adjusted.
-  return instructions + StaticCall(position, target, 1, Array::null_array(),
-                                   ICData::kNoRebind, &result_type);
-}
-
-Fragment StreamingFlowGraphBuilder::BuildDirectPropertySet(TokenPosition* p) {
-  const TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
-
-  Fragment instructions(MakeTemp());
-  LocalVariable* value = MakeTemporary();
-
-  instructions += BuildExpression();  // read receiver.
-
-  const NameIndex target_reference =
-      ReadInterfaceMemberNameReference();  // read target_reference.
-  const String& method_name = H.DartSetterName(target_reference);
-  const Function& target = Function::ZoneHandle(
-      Z, H.LookupMethodByMember(target_reference, method_name));
-  ASSERT(target.IsSetterFunction() || target.IsImplicitSetterFunction());
-
-  instructions += BuildExpression();  // read value.
-  instructions += StoreLocal(TokenPosition::kNoSource, value);
-
-  // Static calls are marked as "no-rebind", which is currently safe because
-  // DirectPropertyGet are only used in enums (index in toString) and enums
-  // can't change their structure during hot reload.
-  // If there are other sources of DirectPropertyGet in the future, this code
-  // have to be adjusted.
-  instructions +=
-      StaticCall(position, target, 2, Array::null_array(), ICData::kNoRebind,
-                 /* result_type = */ NULL);
-
-  return instructions + Drop();
-}
-
 Fragment StreamingFlowGraphBuilder::BuildStaticGet(TokenPosition* p) {
   ASSERT(Error::Handle(Z, H.thread()->sticky_error()).IsNull());
   const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
@@ -3063,72 +2971,6 @@
   return instructions;
 }
 
-Fragment StreamingFlowGraphBuilder::BuildDirectMethodInvocation(
-    TokenPosition* p) {
-  const intptr_t offset = ReaderOffset() - 1;  // Include the tag.
-  TokenPosition position = ReadPosition();     // read offset.
-  if (p != NULL) *p = position;
-
-  const InferredTypeMetadata result_type =
-      inferred_type_metadata_helper_.GetInferredType(offset);
-
-  Tag receiver_tag = PeekTag();  // peek tag for receiver.
-
-  Fragment instructions;
-  intptr_t type_args_len = 0;
-  {
-    AlternativeReadingScope alt(&reader_);
-    SkipExpression();                         // skip receiver
-    ReadInterfaceMemberNameReference();       // skip target reference
-    ReadUInt();                               // read argument count.
-    intptr_t list_length = ReadListLength();  // read types list length.
-    if (list_length > 0) {
-      const TypeArguments& type_arguments =
-          T.BuildTypeArguments(list_length);  // read types.
-      instructions += TranslateInstantiatedTypeArguments(type_arguments);
-    }
-    type_args_len = list_length;
-  }
-
-  instructions += BuildExpression();  // read receiver.
-
-  NameIndex kernel_name =
-      ReadInterfaceMemberNameReference();  // read target_reference.
-  const String& method_name = H.DartProcedureName(kernel_name);
-  const Token::Kind token_kind =
-      MethodTokenRecognizer::RecognizeTokenKind(method_name);
-
-  // Detect comparison with null.
-  if ((token_kind == Token::kEQ || token_kind == Token::kNE) &&
-      PeekArgumentsCount() == 1 &&
-      (receiver_tag == kNullLiteral ||
-       PeekArgumentsFirstPositionalTag() == kNullLiteral)) {
-    ASSERT(type_args_len == 0);
-    // "==" or "!=" with null on either side.
-    instructions +=
-        BuildArguments(NULL /* names */, NULL /* arg count */,
-                       NULL /* positional arg count */);  // read arguments.
-    Token::Kind strict_cmp_kind =
-        token_kind == Token::kEQ ? Token::kEQ_STRICT : Token::kNE_STRICT;
-    return instructions +
-           StrictCompare(position, strict_cmp_kind, /*number_check = */ true);
-  }
-
-  const Function& target =
-      Function::ZoneHandle(Z, H.LookupMethodByMember(kernel_name, method_name));
-
-  Array& argument_names = Array::ZoneHandle(Z);
-  intptr_t argument_count, positional_argument_count;
-  instructions +=
-      BuildArguments(&argument_names, &argument_count,
-                     &positional_argument_count);  // read arguments.
-  ++argument_count;
-
-  return instructions + StaticCall(position, target, argument_count,
-                                   argument_names, ICData::kNoRebind,
-                                   &result_type, type_args_len);
-}
-
 Fragment StreamingFlowGraphBuilder::BuildSuperMethodInvocation(
     TokenPosition* p) {
   const intptr_t offset = ReaderOffset() - 1;     // Include the tag.
@@ -3417,7 +3259,7 @@
       TypeArguments& canonicalized_type_arguments =
           TypeArguments::ZoneHandle(Z, type.arguments());
       canonicalized_type_arguments =
-          canonicalized_type_arguments.Canonicalize();
+          canonicalized_type_arguments.Canonicalize(thread(), nullptr);
       instructions += Constant(canonicalized_type_arguments);
     } else {
       const TypeArguments& type_arguments =
@@ -3613,34 +3455,87 @@
          LoadLocal(parsed_function()->expression_temp_var());
 }
 
-Fragment StreamingFlowGraphBuilder::BuildStringConcatenation(TokenPosition* p) {
-  TokenPosition position = ReadPosition();  // read position.
-  if (p != NULL) *p = position;
+void StreamingFlowGraphBuilder::FlattenStringConcatenation(
+    PiecesCollector* collector) {
+  const auto length = ReadListLength();
+  for (intptr_t i = 0; i < length; ++i) {
+    const auto offset = reader_.offset();
+    switch (PeekTag()) {
+      case kStringLiteral: {
+        ReadTag();
+        const String& s = H.DartSymbolPlain(ReadStringReference());
+        // Skip empty strings.
+        if (!s.Equals("")) {
+          collector->Add({-1, &s});
+        }
+        break;
+      }
+      case kStringConcatenation: {
+        // Flatten by hoisting nested expressions up into the outer concat.
+        ReadTag();
+        ReadPosition();
+        FlattenStringConcatenation(collector);
+        break;
+      }
+      default: {
+        collector->Add({offset, nullptr});
+        SkipExpression();
+      }
+    }
+  }
+}
 
-  intptr_t length = ReadListLength();  // read list length.
-  // Note: there will be "length" expressions.
+Fragment StreamingFlowGraphBuilder::BuildStringConcatenation(TokenPosition* p) {
+  TokenPosition position = ReadPosition();
+  if (p != nullptr) {
+    *p = position;
+  }
+
+  // Collect and flatten all pieces of this and any nested StringConcats.
+  // The result is a single sequence of pieces, potentially flattened to
+  // a single String.
+  // The collector will hold concatenated strings and Reader offsets of
+  // non-string pieces.
+  PiecesCollector collector(Z, &H);
+  FlattenStringConcatenation(&collector);
+  collector.FlushRun();
+
+  if (collector.pieces.length() == 1) {
+    // No need to Interp. a single string, so return string as a Constant:
+    if (collector.pieces[0].literal != nullptr) {
+      return Constant(*collector.pieces[0].literal);
+    }
+    // A single non-string piece is handle by StringInterpolateSingle:
+    AlternativeReadingScope scope(&reader_, collector.pieces[0].offset);
+    Fragment instructions;
+    instructions += BuildExpression();
+    instructions += StringInterpolateSingle(position);
+    return instructions;
+  }
 
   Fragment instructions;
-  if (length == 1) {
-    instructions += BuildExpression();  // read expression.
-    instructions += StringInterpolateSingle(position);
-  } else {
-    // The type arguments for CreateArray.
-    instructions += Constant(TypeArguments::ZoneHandle(Z));
-    instructions += IntConstant(length);
-    instructions += CreateArray();
-    LocalVariable* array = MakeTemporary();
-
-    for (intptr_t i = 0; i < length; ++i) {
+  instructions += Constant(TypeArguments::ZoneHandle(Z));
+  instructions += IntConstant(collector.pieces.length());
+  instructions += CreateArray();
+  LocalVariable* array = MakeTemporary();
+  for (intptr_t i = 0; i < collector.pieces.length(); ++i) {
+    // All pieces are now either a concat'd string or an expression we can
+    // read at a given offset.
+    if (collector.pieces[i].literal != nullptr) {
       instructions += LoadLocal(array);
       instructions += IntConstant(i);
-      instructions += BuildExpression();  // read ith expression.
-      instructions += StoreIndexed(kArrayCid);
+      instructions += Constant(*collector.pieces[i].literal);
+    } else {
+      AlternativeReadingScope scope(&reader_, collector.pieces[i].offset);
+      instructions += LoadLocal(array);
+      instructions += IntConstant(i);
+      instructions += BuildExpression();
     }
-
-    instructions += StringInterpolate(position);
+    instructions += StoreIndexed(kArrayCid);
   }
 
+  instructions += StringInterpolate(position);
+
   return instructions;
 }
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index f3a2fee..2f4b90f 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -295,12 +295,9 @@
                                              Fragment build_rest_of_actuals);
   Fragment BuildSuperPropertyGet(TokenPosition* position);
   Fragment BuildSuperPropertySet(TokenPosition* position);
-  Fragment BuildDirectPropertyGet(TokenPosition* position);
-  Fragment BuildDirectPropertySet(TokenPosition* position);
   Fragment BuildStaticGet(TokenPosition* position);
   Fragment BuildStaticSet(TokenPosition* position);
   Fragment BuildMethodInvocation(TokenPosition* position);
-  Fragment BuildDirectMethodInvocation(TokenPosition* position);
   Fragment BuildSuperMethodInvocation(TokenPosition* position);
   Fragment BuildStaticInvocation(TokenPosition* position);
   Fragment BuildConstructorInvocation(TokenPosition* position);
@@ -366,6 +363,53 @@
   // Kernel buffer and pushes the resulting Function object.
   Fragment BuildFfiNativeCallbackFunction();
 
+  // Piece of a StringConcatenation.
+  // Represents either a StringLiteral, or a Reader offset to the expression.
+  struct ConcatPiece {
+    intptr_t offset;
+    const String* literal;
+  };
+
+  // Collector that automatically concatenates adjacent string ConcatPieces.
+  struct PiecesCollector {
+    explicit PiecesCollector(Zone* z, TranslationHelper* translation_helper)
+        : pieces(5),
+          literal_run(z, 1),
+          translation_helper(translation_helper) {}
+
+    GrowableArray<ConcatPiece> pieces;
+    GrowableHandlePtrArray<const String> literal_run;
+    TranslationHelper* translation_helper;
+
+    void Add(const ConcatPiece& piece) {
+      if (piece.literal != nullptr) {
+        literal_run.Add(*piece.literal);
+      } else {
+        FlushRun();
+        pieces.Add(piece);
+      }
+    }
+
+    void FlushRun() {
+      switch (literal_run.length()) {
+        case 0:
+          return;
+        case 1:
+          pieces.Add({-1, &literal_run[0]});
+          break;
+        default:
+          pieces.Add({-1, &translation_helper->DartString(literal_run)});
+      }
+      literal_run.Clear();
+    }
+  };
+
+  // Flattens and collects pieces of StringConcatenations such that:
+  //   ["a", "", "b"] => ["ab"]
+  //   ["a", StringConcat("b", "c")] => ["abc"]
+  //   ["a", "", StringConcat("b", my_var), "c"] => ["ab", my_var, "c"]
+  void FlattenStringConcatenation(PiecesCollector* collector);
+
   FlowGraphBuilder* flow_graph_builder_;
   ActiveClass* const active_class_;
   ConstantReader constant_reader_;
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
new file mode 100644
index 0000000..80ddd91
--- /dev/null
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph_test.cc
@@ -0,0 +1,250 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/frontend/kernel_binary_flowgraph.h"
+
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/object.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+ISOLATE_UNIT_TEST_CASE(StreamingFlowGraphBuilder_ConstFoldStringConcats) {
+  // According to the Dart spec:
+  // "Adjacent strings are implicitly concatenated to form a single string
+  // literal."
+  const char* kScript = R"(
+    test() {
+      var s = 'aaaa'
+          'bbbb'
+          'cccc';
+      return s;
+    }
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  Invoke(root_library, "test");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  ReturnInstr* ret = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  // clang-format off
+  RELEASE_ASSERT(cursor.TryMatch({
+    kMatchAndMoveFunctionEntry,
+    kMatchAndMoveCheckStackOverflow,
+    kMoveDebugStepChecks,
+    {kMatchReturn, &ret},
+  }));
+  // clang-format on
+
+  EXPECT(ret->value()->BindsToConstant());
+  EXPECT(ret->value()->BoundConstant().IsString());
+  const String& ret_str = String::Cast(ret->value()->BoundConstant());
+  EXPECT(ret_str.Equals("aaaabbbbcccc"));
+}
+
+ISOLATE_UNIT_TEST_CASE(StreamingFlowGraphBuilder_FlattenNestedStringInterp) {
+  // We should collapse nested StringInterpolates:
+  const char* kScript = R"(
+    test(String s) {
+      return '$s' '${'d' 'e'}';
+    }
+    main() => test('u');
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreIndexedInstr* store1 = nullptr;
+  StoreIndexedInstr* store2 = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  // clang-format off
+  RELEASE_ASSERT(cursor.TryMatch({
+    kMatchAndMoveFunctionEntry,
+    kMatchAndMoveCheckStackOverflow,
+    kMoveDebugStepChecks,
+    kMatchAndMoveCreateArray,
+    {kMatchAndMoveStoreIndexed, &store1},
+    {kMatchAndMoveStoreIndexed, &store2},
+    kMatchAndMoveStringInterpolate,
+    kMoveDebugStepChecks,
+    kMatchReturn,
+  }));
+  // clang-format on
+
+  // StoreIndexed(tmp_array, 0, s)
+  EXPECT(store1->index()->BindsToConstant());
+  EXPECT(store1->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store1->index()->BoundConstant()).AsInt64Value() == 0);
+
+  EXPECT(!store1->value()->BindsToConstant());
+
+  // StoreIndexed(tmp_array, 1, "de")
+  EXPECT(store2->index()->BindsToConstant());
+  EXPECT(store2->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store2->index()->BoundConstant()).AsInt64Value() == 1);
+
+  EXPECT(store2->value()->BindsToConstant());
+  EXPECT(store2->value()->BoundConstant().IsString());
+  EXPECT(String::Cast(store2->value()->BoundConstant()).Equals("de"));
+}
+
+ISOLATE_UNIT_TEST_CASE(StreamingFlowGraphBuilder_DropEmptyStringInterp) {
+  // We should drop empty strings from StringInterpolates:
+  const char* kScript = R"(
+    test(s) {
+      return '' 'a' '$s' '' 'b' '';
+    }
+    main() => test('u');
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreIndexedInstr* store1 = nullptr;
+  StoreIndexedInstr* store2 = nullptr;
+  StoreIndexedInstr* store3 = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  // clang-format off
+  RELEASE_ASSERT(cursor.TryMatch({
+    kMatchAndMoveFunctionEntry,
+    kMatchAndMoveCheckStackOverflow,
+    kMoveDebugStepChecks,
+    kMatchAndMoveCreateArray,
+    {kMatchAndMoveStoreIndexed, &store1},
+    {kMatchAndMoveStoreIndexed, &store2},
+    {kMatchAndMoveStoreIndexed, &store3},
+    kMatchAndMoveStringInterpolate,
+    kMoveDebugStepChecks,
+    kMatchReturn,
+  }));
+  // clang-format on
+
+  // StoreIndexed(tmp_array, 0, "ab")
+  EXPECT(store1->index()->BindsToConstant());
+  EXPECT(store1->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store1->index()->BoundConstant()).AsInt64Value() == 0);
+
+  EXPECT(store1->value()->BindsToConstant());
+  EXPECT(store1->value()->BoundConstant().IsString());
+  EXPECT(String::Cast(store1->value()->BoundConstant()).Equals("a"));
+
+  // StoreIndexed(tmp_array, 1, s)
+  EXPECT(store2->index()->BindsToConstant());
+  EXPECT(store2->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store2->index()->BoundConstant()).AsInt64Value() == 1);
+
+  EXPECT(!store2->value()->BindsToConstant());
+
+  // StoreIndexed(tmp_array, 2, "b")
+  EXPECT(store3->index()->BindsToConstant());
+  EXPECT(store3->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store3->index()->BoundConstant()).AsInt64Value() == 2);
+
+  EXPECT(store3->value()->BindsToConstant());
+  EXPECT(store3->value()->BoundConstant().IsString());
+  EXPECT(String::Cast(store3->value()->BoundConstant()).Equals("b"));
+}
+
+ISOLATE_UNIT_TEST_CASE(StreamingFlowGraphBuilder_ConcatStringLits) {
+  // We should drop empty strings from StringInterpolates:
+  const char* kScript = R"(
+    test(s) {
+      return '' 'a' '' 'b' '$s' '' 'c' '' 'd' '';
+    }
+    main() => test('u');
+  )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  const auto& function = Function::Handle(GetFunction(root_library, "test"));
+
+  Invoke(root_library, "main");
+
+  TestPipeline pipeline(function, CompilerPass::kJIT);
+  FlowGraph* flow_graph = pipeline.RunPasses({
+      CompilerPass::kComputeSSA,
+  });
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  StoreIndexedInstr* store1 = nullptr;
+  StoreIndexedInstr* store2 = nullptr;
+  StoreIndexedInstr* store3 = nullptr;
+
+  ILMatcher cursor(flow_graph, entry);
+  // clang-format off
+  RELEASE_ASSERT(cursor.TryMatch({
+    kMatchAndMoveFunctionEntry,
+    kMatchAndMoveCheckStackOverflow,
+    kMoveDebugStepChecks,
+    kMatchAndMoveCreateArray,
+    {kMatchAndMoveStoreIndexed, &store1},
+    {kMatchAndMoveStoreIndexed, &store2},
+    {kMatchAndMoveStoreIndexed, &store3},
+    kMatchAndMoveStringInterpolate,
+    kMoveDebugStepChecks,
+    kMatchReturn,
+  }));
+  // clang-format on
+
+  // StoreIndexed(tmp_array, 0, "ab")
+  EXPECT(store1->index()->BindsToConstant());
+  EXPECT(store1->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store1->index()->BoundConstant()).AsInt64Value() == 0);
+
+  EXPECT(store1->value()->BindsToConstant());
+  EXPECT(store1->value()->BoundConstant().IsString());
+  EXPECT(String::Cast(store1->value()->BoundConstant()).Equals("ab"));
+
+  // StoreIndexed(tmp_array, 1, s)
+  EXPECT(store2->index()->BindsToConstant());
+  EXPECT(store2->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store2->index()->BoundConstant()).AsInt64Value() == 1);
+
+  EXPECT(!store2->value()->BindsToConstant());
+
+  // StoreIndexed(tmp_array, 2, "cd")
+  EXPECT(store3->index()->BindsToConstant());
+  EXPECT(store3->index()->BoundConstant().IsInteger());
+  EXPECT(Integer::Cast(store3->index()->BoundConstant()).AsInt64Value() == 2);
+
+  EXPECT(store3->value()->BindsToConstant());
+  EXPECT(store3->value()->BoundConstant().IsString());
+  EXPECT(String::Cast(store3->value()->BoundConstant()).Equals("cd"));
+}
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 1b53cde..51ddf29 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -400,17 +400,6 @@
       CalculateExpressionFingerprint();          // read value.
       CalculateSetterNameFingerprint();  // read interface_target_reference.
       return;
-    case kDirectPropertyGet:
-      ReadPosition();                       // read position.
-      CalculateExpressionFingerprint();     // read receiver.
-      CalculateInterfaceMemberNameFingerprint();  // read target_reference.
-      return;
-    case kDirectPropertySet:
-      ReadPosition();                       // read position.
-      CalculateExpressionFingerprint();     // read receiver.
-      CalculateInterfaceMemberNameFingerprint();  // read target_reference.
-      CalculateExpressionFingerprint();     // read value·
-      return;
     case kStaticGet:
       ReadPosition();                       // read position.
       CalculateCanonicalNameFingerprint();  // read target_reference.
@@ -433,12 +422,6 @@
       CalculateArgumentsFingerprint();           // read arguments.
       CalculateInterfaceMemberNameFingerprint();  // read target_reference.
       return;
-    case kDirectMethodInvocation:
-      ReadPosition();                       // read position.
-      CalculateExpressionFingerprint();     // read receiver.
-      CalculateInterfaceMemberNameFingerprint();  // read target_reference.
-      CalculateArgumentsFingerprint();      // read arguments.
-      return;
     case kStaticInvocation:
       ReadPosition();                       // read position.
       CalculateCanonicalNameFingerprint();  // read target_reference.
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 396cef9..87a3298 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -795,6 +795,20 @@
     case MethodRecognizer::kTypedData_Float32x4ArrayView_factory:
     case MethodRecognizer::kTypedData_Int32x4ArrayView_factory:
     case MethodRecognizer::kTypedData_Float64x2ArrayView_factory:
+    case MethodRecognizer::kTypedData_Int8Array_factory:
+    case MethodRecognizer::kTypedData_Uint8Array_factory:
+    case MethodRecognizer::kTypedData_Uint8ClampedArray_factory:
+    case MethodRecognizer::kTypedData_Int16Array_factory:
+    case MethodRecognizer::kTypedData_Uint16Array_factory:
+    case MethodRecognizer::kTypedData_Int32Array_factory:
+    case MethodRecognizer::kTypedData_Uint32Array_factory:
+    case MethodRecognizer::kTypedData_Int64Array_factory:
+    case MethodRecognizer::kTypedData_Uint64Array_factory:
+    case MethodRecognizer::kTypedData_Float32Array_factory:
+    case MethodRecognizer::kTypedData_Float64Array_factory:
+    case MethodRecognizer::kTypedData_Float32x4Array_factory:
+    case MethodRecognizer::kTypedData_Int32x4Array_factory:
+    case MethodRecognizer::kTypedData_Float64x2Array_factory:
     case MethodRecognizer::kFfiLoadInt8:
     case MethodRecognizer::kFfiLoadInt16:
     case MethodRecognizer::kFfiLoadInt32:
@@ -943,6 +957,63 @@
       body += BuildTypedDataViewFactoryConstructor(
           function, kTypedDataFloat64x2ArrayViewCid);
       break;
+    case MethodRecognizer::kTypedData_Int8Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataInt8ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint8Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataUint8ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint8ClampedArray_factory:
+      body += BuildTypedDataFactoryConstructor(function,
+                                               kTypedDataUint8ClampedArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Int16Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataInt16ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint16Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataUint16ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Int32Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataInt32ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint32Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataUint32ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Int64Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataInt64ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Uint64Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataUint64ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Float32Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataFloat32ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Float64Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataFloat64ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Float32x4Array_factory:
+      body += BuildTypedDataFactoryConstructor(function,
+                                               kTypedDataFloat32x4ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Int32x4Array_factory:
+      body +=
+          BuildTypedDataFactoryConstructor(function, kTypedDataInt32x4ArrayCid);
+      break;
+    case MethodRecognizer::kTypedData_Float64x2Array_factory:
+      body += BuildTypedDataFactoryConstructor(function,
+                                               kTypedDataFloat64x2ArrayCid);
+      break;
+
     case MethodRecognizer::kObjectEquals:
       ASSERT(function.NumParameters() == 2);
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
@@ -1444,6 +1515,23 @@
   return body;
 }
 
+Fragment FlowGraphBuilder::BuildTypedDataFactoryConstructor(
+    const Function& function,
+    classid_t cid) {
+  const auto token_pos = function.token_pos();
+  ASSERT(Thread::Current()->isolate()->class_table()->HasValidClassAt(cid));
+
+  ASSERT(function.IsFactory() && (function.NumParameters() == 2));
+  LocalVariable* length = parsed_function_->RawParameterVariable(1);
+
+  Fragment instructions;
+  instructions += LoadLocal(length);
+  // AllocateTypedData instruction checks that length is valid (a non-negative
+  // Smi below maximum allowed length).
+  instructions += AllocateTypedData(token_pos, cid);
+  return instructions;
+}
+
 static const LocalScope* MakeImplicitClosureScope(Zone* Z, const Class& klass) {
   ASSERT(!klass.IsNull());
   // Note that if klass is _Closure, DeclarationType will be _Closure,
@@ -1734,8 +1822,10 @@
     Fragment* checks = is_covariant ? explicit_checks : implicit_checks;
 
     *checks += LoadLocal(param);
-    *checks += CheckAssignable(*target_type, name,
-                               AssertAssignableInstr::kParameterCheck);
+    *checks += AssertAssignableLoadTypeArguments(
+        TokenPosition::kNoSource, *target_type, name,
+        AssertAssignableInstr::kParameterCheck);
+    *checks += StoreLocal(param);
     *checks += Drop();
 
     if (!is_covariant && implicit_redefinitions != nullptr && optimizing_) {
@@ -1929,84 +2019,124 @@
                            prologue_info);
 }
 
-Fragment FlowGraphBuilder::BuildDynamicCallVarsInit(LocalVariable* closure) {
-  auto const vars = parsed_function_->dynamic_closure_call_vars();
-  ASSERT(vars != nullptr);
-  ASSERT(has_saved_args_desc_array());
-  const ArgumentsDescriptor descriptor(saved_args_desc_array());
-  auto const rep = Slot::Function_packed_fields().representation();
+// Information used by the various dynamic closure call fragment builders.
+struct FlowGraphBuilder::ClosureCallInfo {
+  ClosureCallInfo(LocalVariable* closure,
+                  JoinEntryInstr* throw_no_such_method,
+                  const Array& arguments_descriptor_array,
+                  ParsedFunction::DynamicClosureCallVars* const vars)
+      : closure(ASSERT_NOTNULL(closure)),
+        throw_no_such_method(ASSERT_NOTNULL(throw_no_such_method)),
+        descriptor(arguments_descriptor_array),
+        vars(ASSERT_NOTNULL(vars)) {}
 
-  // We extract all the packed fields here so code generation that puts unboxed
-  // integers on the expression stack even in unoptimized code is in one place.
+  LocalVariable* const closure;
+  JoinEntryInstr* const throw_no_such_method;
+  const ArgumentsDescriptor descriptor;
+  ParsedFunction::DynamicClosureCallVars* const vars;
 
-  Fragment init;
-  init += LoadLocal(closure);
-  init += LoadNativeField(Slot::Closure_function());
-  init += LoadNativeField(Slot::Function_packed_fields());
-  init +=
-      BuildExtractPackedFieldIntoSmi<Function::PackedNumFixedParameters>(rep);
-  init += StoreLocal(TokenPosition::kNoSource, vars->num_fixed_params);
-  // Not dropping as we'll use the value to get the max number of parameters.
+  // Set up by BuildDynamicCallChecks() when needed. These values are
+  // read-only, so they don't need real local variables and are created
+  // using MakeTemporary().
+  LocalVariable* function = nullptr;
+  LocalVariable* num_fixed_params = nullptr;
+  LocalVariable* num_opt_params = nullptr;
+  LocalVariable* num_max_params = nullptr;
+  LocalVariable* has_named_params = nullptr;
+  LocalVariable* parameter_names = nullptr;
+  LocalVariable* type_parameters = nullptr;
+};
 
-  init += LoadLocal(closure);
-  init += LoadNativeField(Slot::Closure_function());
-  init += LoadNativeField(Slot::Function_packed_fields());
-  init += BuildExtractPackedFieldIntoSmi<Function::PackedNumOptionalParameters>(
-      rep);
-  init += StoreLocal(TokenPosition::kNoSource, vars->num_opt_params);
-  init += SmiBinaryOp(Token::kADD);
-  init += StoreLocal(TokenPosition::kNoSource, vars->num_max_params);
-  init += Drop();
+Fragment FlowGraphBuilder::TestClosureFunctionNamedParameterRequired(
+    const ClosureCallInfo& info,
+    Fragment set,
+    Fragment not_set) {
+  // Required named arguments only exist if null_safety is enabled.
+  if (!I->null_safety()) return not_set;
 
-  // Currently, we only need this initialized to either check provided optional
-  // names, if any, or to check for missing required parameters if null safe.
-  if (Isolate::Current()->null_safety() || descriptor.NamedCount() > 0) {
-    init += LoadLocal(closure);
-    init += LoadNativeField(Slot::Closure_function());
-    init += LoadNativeField(Slot::Function_parameter_names());
-    init += StoreLocal(TokenPosition::kNoSource, vars->parameter_names);
-    init += Drop();
-  }
+  Fragment check_required;
+  // First, we convert the index to be in terms of the number of optional
+  // parameters, not total parameters (to calculate the flag index and shift).
+  check_required += LoadLocal(info.vars->current_param_index);
+  check_required += LoadLocal(info.num_fixed_params);
+  check_required += SmiBinaryOp(Token::kSUB, /*is_truncating=*/true);
+  LocalVariable* opt_index = MakeTemporary("opt_index");  // Read-only.
 
-  init += LoadLocal(closure);
-  init += LoadNativeField(Slot::Closure_function());
-  init += LoadNativeField(Slot::Function_packed_fields());
-  init += BuildExtractPackedFieldIntoSmi<
-      Function::PackedHasNamedOptionalParameters>(rep);
-  init += IntConstant(0);
-  TargetEntryInstr *is_true, *is_false;
-  init += BranchIfEqual(&is_false, &is_true);
+  // Next, we calculate the index to dereference in the parameter names array.
+  check_required += LoadLocal(opt_index);
+  check_required +=
+      IntConstant(compiler::target::kNumParameterFlagsPerElementLog2);
+  check_required += SmiBinaryOp(Token::kSHR);
+  check_required += LoadLocal(info.num_max_params);
+  check_required += SmiBinaryOp(Token::kADD);
+  LocalVariable* flags_index = MakeTemporary("flags_index");  // Read-only.
 
-  JoinEntryInstr* join = BuildJoinEntry();
-  init.current = join;
+  // Two read-only stack values (opt_index, flag_index) that must be dropped
+  // after we rejoin at after_check.
+  JoinEntryInstr* after_check = BuildJoinEntry();
 
-  Fragment true_branch(is_true);
-  true_branch += Constant(Object::bool_true());
-  true_branch += StoreLocal(TokenPosition::kNoSource, vars->has_named_params);
-  true_branch += Drop();
-  true_branch += Goto(join);
+  // Now we check to see if the flags index is within the bounds of the
+  // parameters names array. If not, it cannot be required.
+  check_required += LoadLocal(flags_index);
+  check_required += LoadLocal(info.parameter_names);
+  check_required += LoadNativeField(Slot::Array_length());
+  check_required += SmiRelationalOp(Token::kLT);
+  TargetEntryInstr *valid_index, *invalid_index;
+  check_required += BranchIfTrue(&valid_index, &invalid_index);
 
-  Fragment false_branch(is_false);
-  false_branch += Constant(Object::bool_false());
-  false_branch += StoreLocal(TokenPosition::kNoSource, vars->has_named_params);
-  false_branch += Drop();
-  false_branch += Goto(join);
+  JoinEntryInstr* join_not_set = BuildJoinEntry();
 
-  return init;
+  Fragment(invalid_index) + Goto(join_not_set);
+
+  // Otherwise, we need to retrieve the value. We're guaranteed the Smis in
+  // the flag slots are non-null, so after loading we can immediate check
+  // the required flag bit for the given named parameter.
+  check_required.current = valid_index;
+  check_required += LoadLocal(info.parameter_names);
+  check_required += LoadLocal(flags_index);
+  check_required += LoadIndexed(compiler::target::kWordSize);
+  check_required += LoadLocal(opt_index);
+  check_required +=
+      IntConstant(compiler::target::kNumParameterFlagsPerElement - 1);
+  check_required += SmiBinaryOp(Token::kBIT_AND);
+  // If the below changes, we'll need to multiply by the number of parameter
+  // flags before shifting.
+  static_assert(compiler::target::kNumParameterFlags == 1,
+                "IL builder assumes only one flag bit per parameter");
+  check_required += SmiBinaryOp(Token::kSHR);
+  check_required +=
+      IntConstant(1 << compiler::target::kRequiredNamedParameterFlag);
+  check_required += SmiBinaryOp(Token::kBIT_AND);
+  check_required += IntConstant(0);
+  TargetEntryInstr *is_not_set, *is_set;
+  check_required += BranchIfEqual(&is_not_set, &is_set);
+
+  Fragment(is_not_set) + Goto(join_not_set);
+
+  set.Prepend(is_set);
+  set += Goto(after_check);
+
+  not_set.Prepend(join_not_set);
+  not_set += Goto(after_check);
+
+  // After rejoining, drop the introduced temporaries.
+  check_required.current = after_check;
+  check_required += DropTemporary(&flags_index);
+  check_required += DropTemporary(&opt_index);
+  return check_required;
 }
 
-Fragment FlowGraphBuilder::BuildClosureCallHasRequiredNamedArgumentsCheck(
-    LocalVariable* closure,
-    JoinEntryInstr* nsm) {
-  auto const vars = parsed_function_->dynamic_closure_call_vars();
-  ASSERT(vars != nullptr);
-  ASSERT(has_saved_args_desc_array());
-  const ArgumentsDescriptor descriptor(saved_args_desc_array());
-
-  // Required named arguments only exist if null_safety is enabled.
-  if (!Isolate::Current()->null_safety()) return Fragment();
-
-  if (descriptor.NamedCount() == 0) {
+Fragment FlowGraphBuilder::BuildClosureCallNamedArgumentsCheck(
+    const ClosureCallInfo& info) {
+  // When no named arguments are provided, we just need to check for possible
+  // required named arguments.
+  if (info.descriptor.NamedCount() == 0) {
+    // No work to do if there are no possible required named parameters.
+    if (!I->null_safety()) {
+      return Fragment();
+    }
+    // If the below changes, we can no longer assume that flag slots existing
+    // means there are required parameters.
     static_assert(compiler::target::kNumParameterFlags == 1,
                   "IL builder assumes only one flag bit per parameter");
     // No named args were provided, so check for any required named params.
@@ -2014,193 +2144,177 @@
     // for named parameters. If this changes, we'll need to check each flag
     // entry appropriately for any set required bits.
     Fragment has_any;
-    has_any += LoadLocal(vars->num_max_params);
-    has_any += LoadLocal(vars->parameter_names);
+    has_any += LoadLocal(info.num_max_params);
+    has_any += LoadLocal(info.parameter_names);
     has_any += LoadNativeField(Slot::Array_length());
     TargetEntryInstr *no_required, *has_required;
     has_any += BranchIfEqual(&no_required, &has_required);
 
-    Fragment(has_required) + Goto(nsm);
+    Fragment(has_required) + Goto(info.throw_no_such_method);
 
     return Fragment(has_any.entry, no_required);
   }
 
-  // Loop over the indexes of the named parameters of the function, checking
-  // whether the named parameter at that index is required. If it is, then
-  // check whether it matches any of the names in the ArgumentsDescriptor.
-  JoinEntryInstr* loop = BuildJoinEntry();
+  // Otherwise, we need to loop through the parameter names to check the names
+  // of named arguments for validity (and possibly missing required ones).
+  Fragment check_names;
+  check_names += LoadLocal(info.vars->current_param_index);
+  LocalVariable* old_index = MakeTemporary("old_index");  // Read-only.
+  check_names += LoadLocal(info.vars->current_num_processed);
+  LocalVariable* old_processed = MakeTemporary("old_processed");  // Read-only.
 
-  // We iterate from [0, num_named), not [num_fixed, num_named) because the
-  // flag mask and index is based off the named index, not the param index.
-  Fragment check_required;
-  check_required += IntConstant(0);
-  check_required +=
-      StoreLocal(TokenPosition::kNoSource, vars->current_param_index);
-  check_required += Drop();
-  check_required += Goto(loop);
+  // Two local stack values (old_index, old_processed) to drop after rejoining
+  // at done.
+  JoinEntryInstr* loop = BuildJoinEntry();
+  JoinEntryInstr* done = BuildJoinEntry();
+
+  check_names += IntConstant(0);
+  check_names += StoreLocal(info.vars->current_num_processed);
+  check_names += Drop();
+  check_names += LoadLocal(info.num_fixed_params);
+  check_names += StoreLocal(info.vars->current_param_index);
+  check_names += Drop();
+  check_names += Goto(loop);
 
   Fragment loop_check(loop);
-  loop_check += LoadLocal(vars->current_param_index);
-  loop_check += LoadLocal(vars->num_opt_params);
+  loop_check += LoadLocal(info.vars->current_param_index);
+  loop_check += LoadLocal(info.num_max_params);
   loop_check += SmiRelationalOp(Token::kLT);
   TargetEntryInstr *no_more, *more;
   loop_check += BranchIfTrue(&more, &no_more);
 
-  JoinEntryInstr* done = BuildJoinEntry();
   Fragment(no_more) + Goto(done);
 
   Fragment loop_body(more);
-  // First, we calculate the index to dereference into the parameter names
-  // array and store it in :expr_temp.
-  loop_body += LoadLocal(vars->num_max_params);
-  loop_body += LoadLocal(vars->current_param_index);
-  loop_body += IntConstant(compiler::target::kNumParameterFlagsPerElementLog2);
-  loop_body += SmiBinaryOp(Token::kSHR);
-  loop_body += SmiBinaryOp(Token::kADD);
-  LocalVariable* temp = parsed_function_->expression_temp_var();
-  loop_body += StoreLocal(TokenPosition::kNoSource, temp);
-  // Now we check to see if it is within the bounds of the parameters names
-  // array. If not, we're done, as this and later indices cannot be required.
-  loop_body += LoadLocal(vars->parameter_names);
-  loop_body += LoadNativeField(Slot::Array_length());
-  loop_body += SmiRelationalOp(Token::kLT);
-  TargetEntryInstr *valid_index, *invalid_index;
-  loop_body += BranchIfTrue(&valid_index, &invalid_index);
-
-  Fragment(invalid_index) + Goto(done);
-
-  // Otherwise, we need to retrieve the value and check the appropriate bit.
-  loop_body.current = valid_index;
-  loop_body += LoadLocal(vars->parameter_names);
-  loop_body += LoadLocal(temp);  // Index into parameter names array.
+  // First load the name we need to check against.
+  loop_body += LoadLocal(info.parameter_names);
+  loop_body += LoadLocal(info.vars->current_param_index);
   loop_body += LoadIndexed(compiler::target::kWordSize);
-  loop_body += LoadLocal(vars->current_param_index);
-  loop_body += IntConstant(compiler::target::kNumParameterFlagsPerElement - 1);
-  loop_body += SmiBinaryOp(Token::kBIT_AND);
-  if (compiler::target::kNumParameterFlags > 1) {
-    loop_body += IntConstant(compiler::target::kNumParameterFlags);
-    loop_body += SmiBinaryOp(Token::kMUL, /*is_truncating=*/false);
+  LocalVariable* param_name = MakeTemporary("param_name");  // Read only.
+
+  // One additional local value on the stack within the loop body (param_name)
+  // that should be dropped after rejoining at loop_incr.
+  JoinEntryInstr* loop_incr = BuildJoinEntry();
+
+  // Now iterate over the ArgumentsDescriptor names and check for a match.
+  for (intptr_t i = 0; i < info.descriptor.NamedCount(); i++) {
+    const auto& name = String::ZoneHandle(Z, info.descriptor.NameAt(i));
+    loop_body += Constant(name);
+    loop_body += LoadLocal(param_name);
+    TargetEntryInstr *match, *mismatch;
+    loop_body += BranchIfEqual(&match, &mismatch);
+    loop_body.current = mismatch;
+
+    // We have a match, so go to the next name after incrementing the number
+    // of matched arguments. (No need to check for the required bit, as this
+    // parameter was provided.)
+    Fragment matched(match);
+    matched += LoadLocal(info.vars->current_num_processed);
+    matched += IntConstant(1);
+    matched += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
+    matched += StoreLocal(info.vars->current_num_processed);
+    matched += Drop();
+    matched += Goto(loop_incr);
   }
-  loop_body += SmiBinaryOp(Token::kSHR);
-  loop_body += IntConstant(1 << compiler::target::kRequiredNamedParameterFlag);
-  loop_body += SmiBinaryOp(Token::kBIT_AND);
-  loop_body += IntConstant(0);
-  TargetEntryInstr *not_set, *set;
-  loop_body += BranchIfEqual(&not_set, &set);
 
-  // Make a join entry for the increment at the end of the loop, so we can jump
-  // to it if we match one of the names in the ArgumentsDescriptor.
-  JoinEntryInstr* incr_index = BuildJoinEntry();
-  Fragment(not_set) + Goto(incr_index);
+  // None of the names in the arguments descriptor matched, so check if this
+  // is a required parameter.
+  loop_body += TestClosureFunctionNamedParameterRequired(
+      info,
+      /*set=*/Goto(info.throw_no_such_method),
+      /*not_set=*/{});
 
-  Fragment check_names(set);
-  if (descriptor.NamedCount() > 0) {
-    // First load the name we need to check against into :expr_temp.
-    check_names += LoadLocal(vars->parameter_names);
-    check_names += LoadLocal(vars->current_param_index);
-    check_names += LoadLocal(vars->num_fixed_params);
-    check_names += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
-    check_names += LoadIndexed(compiler::target::kWordSize);
-    check_names += StoreLocal(TokenPosition::kNoSource, temp);
-    check_names += Drop();
-    // Now iterate over the names in the ArgumentsDescriptor and add a check
-    // against each that goes to t he next loop iteration if the name is found.
-    for (intptr_t i = 0; i < descriptor.NamedCount(); i++) {
-      const auto& name = String::ZoneHandle(Z, descriptor.NameAt(i));
-      check_names += LoadLocal(temp);
-      check_names += Constant(name);
-      TargetEntryInstr *str_equal, *str_neq;
-      check_names += BranchIfEqual(&str_equal, &str_neq);
-      check_names.current = str_neq;
+  loop_body += Goto(loop_incr);
 
-      Fragment(str_equal) + Goto(incr_index);
-    }
-  }
-  // None of the names in the arguments descriptor matched, so throw NSM.
-  check_names += Goto(nsm);
+  Fragment incr_index(loop_incr);
+  incr_index += DropTemporary(&param_name);
+  incr_index += LoadLocal(info.vars->current_param_index);
+  incr_index += IntConstant(1);
+  incr_index += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
+  incr_index += StoreLocal(info.vars->current_param_index);
+  incr_index += Drop();
+  incr_index += Goto(loop);
 
-  // Increment the counter if the current parameter wasn't required or was
-  // required but provided.
-  loop_body.current = incr_index;
-  loop_body += LoadLocal(vars->current_param_index);
-  loop_body += IntConstant(1);
-  loop_body += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
-  loop_body += StoreLocal(TokenPosition::kNoSource, vars->current_param_index);
-  loop_body += Drop();
-  loop_body += Goto(loop);
+  Fragment check_processed(done);
+  check_processed += LoadLocal(info.vars->current_num_processed);
+  check_processed += IntConstant(info.descriptor.NamedCount());
+  TargetEntryInstr *all_processed, *bad_name;
+  check_processed += BranchIfEqual(&all_processed, &bad_name);
 
-  check_required.current = done;
-  return check_required;
+  // Didn't find a matching parameter name for at least one argument name.
+  Fragment(bad_name) + Goto(info.throw_no_such_method);
+
+  // Drop the temporaries at the end of the fragment.
+  check_names.current = all_processed;
+  check_names += LoadLocal(old_processed);
+  check_names += StoreLocal(info.vars->current_num_processed);
+  check_names += Drop();
+  check_names += DropTemporary(&old_processed);
+  check_names += LoadLocal(old_index);
+  check_names += StoreLocal(info.vars->current_param_index);
+  check_names += Drop();
+  check_names += DropTemporary(&old_index);
+  return check_names;
 }
 
 Fragment FlowGraphBuilder::BuildClosureCallArgumentsValidCheck(
-    LocalVariable* closure,
-    JoinEntryInstr* nsm) {
-  auto const vars = parsed_function_->dynamic_closure_call_vars();
-  ASSERT(vars != nullptr);
-  ASSERT(has_saved_args_desc_array());
-  const ArgumentsDescriptor descriptor(saved_args_desc_array());
-
-  LocalVariable* temp = parsed_function_->expression_temp_var();
-
+    const ClosureCallInfo& info) {
   Fragment check_entry;
   // We only need to check the length of any explicitly provided type arguments.
-  if (descriptor.TypeArgsLen() > 0) {
+  if (info.descriptor.TypeArgsLen() > 0) {
     Fragment check_type_args_length;
-    check_type_args_length += LoadLocal(closure);
-    check_type_args_length += LoadNativeField(Slot::Closure_function());
-    check_type_args_length += LoadNativeField(Slot::Function_type_parameters());
-    check_type_args_length += StoreLocal(TokenPosition::kNoSource, temp);
+    check_type_args_length += LoadLocal(info.type_parameters);
     TargetEntryInstr *null, *not_null;
     check_type_args_length += BranchIfNull(&null, &not_null);
     check_type_args_length.current = not_null;  // Continue in non-error case.
-
-    // The function is not generic.
-    Fragment(null) + Goto(nsm);
-
-    check_type_args_length += LoadLocal(temp);
+    check_type_args_length += LoadLocal(info.type_parameters);
     check_type_args_length += LoadNativeField(Slot::TypeArguments_length());
-    check_type_args_length += IntConstant(descriptor.TypeArgsLen());
+    check_type_args_length += IntConstant(info.descriptor.TypeArgsLen());
     TargetEntryInstr *equal, *not_equal;
     check_type_args_length += BranchIfEqual(&equal, &not_equal);
     check_type_args_length.current = equal;  // Continue in non-error case.
 
-    Fragment(not_equal) + Goto(nsm);
+    // The function is not generic.
+    Fragment(null) + Goto(info.throw_no_such_method);
+
+    // An incorrect number of type arguments were passed.
+    Fragment(not_equal) + Goto(info.throw_no_such_method);
 
     // Type arguments should not be provided if there are delayed type
     // arguments, as then the closure itself is not generic.
-    check_entry += TestDelayedTypeArgs(closure, /*present=*/Goto(nsm),
-                                       /*absent=*/check_type_args_length);
+    check_entry += TestDelayedTypeArgs(
+        info.closure, /*present=*/Goto(info.throw_no_such_method),
+        /*absent=*/check_type_args_length);
   }
 
-  check_entry += LoadLocal(vars->has_named_params);
+  check_entry += LoadLocal(info.has_named_params);
   TargetEntryInstr *has_named, *has_positional;
   check_entry += BranchIfTrue(&has_named, &has_positional);
   JoinEntryInstr* join_after_optional = BuildJoinEntry();
   check_entry.current = join_after_optional;
 
-  if (descriptor.NamedCount() > 0) {
+  if (info.descriptor.NamedCount() > 0) {
     // No reason to continue checking, as this function doesn't take named args.
-    Fragment(has_positional) + Goto(nsm);
+    Fragment(has_positional) + Goto(info.throw_no_such_method);
   } else {
     Fragment check_pos(has_positional);
-    check_pos += LoadLocal(vars->num_fixed_params);
-    check_pos += IntConstant(descriptor.PositionalCount());
+    check_pos += LoadLocal(info.num_fixed_params);
+    check_pos += IntConstant(info.descriptor.PositionalCount());
     check_pos += SmiRelationalOp(Token::kLTE);
     TargetEntryInstr *enough, *too_few;
     check_pos += BranchIfTrue(&enough, &too_few);
     check_pos.current = enough;
 
-    Fragment(too_few) + Goto(nsm);
+    Fragment(too_few) + Goto(info.throw_no_such_method);
 
-    check_pos += IntConstant(descriptor.PositionalCount());
-    check_pos += LoadLocal(vars->num_max_params);
+    check_pos += IntConstant(info.descriptor.PositionalCount());
+    check_pos += LoadLocal(info.num_max_params);
     check_pos += SmiRelationalOp(Token::kLTE);
     TargetEntryInstr *valid, *too_many;
     check_pos += BranchIfTrue(&valid, &too_many);
     check_pos.current = valid;
 
-    Fragment(too_many) + Goto(nsm);
+    Fragment(too_many) + Goto(info.throw_no_such_method);
 
     check_pos += Goto(join_after_optional);
   }
@@ -2208,90 +2322,114 @@
   Fragment check_named(has_named);
 
   TargetEntryInstr *same, *different;
-  check_named += LoadLocal(vars->num_fixed_params);
-  check_named += IntConstant(descriptor.PositionalCount());
+  check_named += LoadLocal(info.num_fixed_params);
+  check_named += IntConstant(info.descriptor.PositionalCount());
   check_named += BranchIfEqual(&same, &different);
   check_named.current = same;
 
-  Fragment(different) + Goto(nsm);
+  Fragment(different) + Goto(info.throw_no_such_method);
 
-  if (descriptor.NamedCount() > 0) {
-    check_named += IntConstant(descriptor.NamedCount());
-    check_named += LoadLocal(vars->num_opt_params);
+  if (info.descriptor.NamedCount() > 0) {
+    check_named += IntConstant(info.descriptor.NamedCount());
+    check_named += LoadLocal(info.num_opt_params);
     check_named += SmiRelationalOp(Token::kLTE);
     TargetEntryInstr *valid, *too_many;
     check_named += BranchIfTrue(&valid, &too_many);
     check_named.current = valid;
 
-    Fragment(too_many) + Goto(nsm);
+    Fragment(too_many) + Goto(info.throw_no_such_method);
   }
 
-  check_named += BuildClosureCallHasRequiredNamedArgumentsCheck(closure, nsm);
+  // Check the names for optional arguments. If applicable, also check that all
+  // required named parameters are provided.
+  check_named += BuildClosureCallNamedArgumentsCheck(info);
   check_named += Goto(join_after_optional);
 
+  check_entry.current = join_after_optional;
   return check_entry;
 }
 
-Fragment FlowGraphBuilder::BuildClosureCallNamedArgumentCheck(
-    LocalVariable* closure,
-    intptr_t pos,
-    JoinEntryInstr* nsm) {
-  auto const vars = parsed_function_->dynamic_closure_call_vars();
-  ASSERT(vars != nullptr);
-  ASSERT(has_saved_args_desc_array());
-  const ArgumentsDescriptor descriptor(saved_args_desc_array());
+Fragment FlowGraphBuilder::BuildDynamicClosureCallChecks(
+    LocalVariable* closure) {
+  ClosureCallInfo info(closure, BuildThrowNoSuchMethod(),
+                       saved_args_desc_array(),
+                       parsed_function_->dynamic_closure_call_vars());
 
-  // If this isn't a named argument, then don't build anything.
-  if (pos < descriptor.PositionalCount()) return Fragment();
-  const intptr_t named_pos = pos - descriptor.PositionalCount();
-  ASSERT(named_pos < descriptor.NamedCount());
+  // We extract all the packed fields here so code generation that puts unboxed
+  // integers on the expression stack even in unoptimized code is in one place.
+  auto const rep = Slot::Function_packed_fields().representation();
 
-  // Loop over the indexes of the named parameters of the function, checking
-  // whether the named parameter at that index is required. If it is, then
-  // check whether it matches any of the names in the ArgumentsDescriptor.
-  JoinEntryInstr* loop = BuildJoinEntry();
+  Fragment body;
+  body += LoadLocal(info.closure);
+  body += LoadNativeField(Slot::Closure_function());
+  info.function = MakeTemporary("function");
 
-  // We iterate from [0, num_named), not [num_fixed, num_named) because the
-  // flag mask and index is based off the named index, not the param index.
-  Fragment check_arg_name;
-  check_arg_name += LoadLocal(vars->num_fixed_params);
-  check_arg_name +=
-      StoreLocal(TokenPosition::kNoSource, vars->current_param_index);
-  check_arg_name += Drop();
-  check_arg_name += Goto(loop);
+  body += LoadLocal(info.function);
+  body += LoadNativeField(Slot::Function_packed_fields());
+  body +=
+      BuildExtractPackedFieldIntoSmi<Function::PackedNumFixedParameters>(rep);
+  info.num_fixed_params = MakeTemporary("num_fixed_params");
 
-  Fragment loop_check(loop);
-  loop_check += LoadLocal(vars->current_param_index);
-  loop_check += LoadLocal(vars->num_max_params);
-  loop_check += SmiRelationalOp(Token::kLT);
-  TargetEntryInstr *no_more, *more;
-  loop_check += BranchIfTrue(&more, &no_more);
+  body += LoadLocal(info.function);
+  body += LoadNativeField(Slot::Function_packed_fields());
+  body += BuildExtractPackedFieldIntoSmi<Function::PackedNumOptionalParameters>(
+      rep);
+  info.num_opt_params = MakeTemporary("num_opt_params");
 
-  JoinEntryInstr* done = BuildJoinEntry();
-  // None of the parameter names matched.
-  Fragment(no_more) + Goto(nsm);
+  body += LoadLocal(info.num_fixed_params);
+  body += LoadLocal(info.num_opt_params);
+  body += SmiBinaryOp(Token::kADD);
+  info.num_max_params = MakeTemporary("num_max_params");
 
-  Fragment loop_body(more);
-  loop_body += LoadLocal(vars->parameter_names);
-  loop_body += LoadLocal(vars->current_param_index);
-  loop_body += LoadIndexed(compiler::target::kWordSize);
-  loop_body += Constant(String::ZoneHandle(Z, descriptor.NameAt(named_pos)));
-  TargetEntryInstr *str_equal, *str_neq;
-  loop_body += BranchIfEqual(&str_equal, &str_neq);
+  body += LoadLocal(info.function);
+  body += LoadNativeField(Slot::Function_packed_fields());
+  body += BuildExtractPackedFieldIntoSmi<
+      Function::PackedHasNamedOptionalParameters>(rep);
+  body += IntConstant(0);
+  body += StrictCompare(Token::kNE_STRICT);
+  info.has_named_params = MakeTemporary("has_named_params");
 
-  Fragment(str_equal) + Goto(done);
+  if (I->null_safety() || info.descriptor.NamedCount() > 0) {
+    body += LoadLocal(info.function);
+    body += LoadNativeField(Slot::Function_parameter_names());
+    info.parameter_names = MakeTemporary("parameter_names");
+  }
 
-  // Increment the index and jump back to the loop check.
-  loop_body.current = str_neq;
-  loop_body += LoadLocal(vars->current_param_index);
-  loop_body += IntConstant(1);
-  loop_body += SmiBinaryOp(Token::kADD, /*is_truncating=*/true);
-  loop_body += StoreLocal(TokenPosition::kNoSource, vars->current_param_index);
-  loop_body += Drop();
-  loop_body += Goto(loop);
+  if (info.descriptor.TypeArgsLen() > 0) {
+    body += LoadLocal(info.function);
+    body += LoadNativeField(Slot::Function_type_parameters());
+    info.type_parameters = MakeTemporary("type_parameters");
+  }
 
-  check_arg_name.current = done;
-  return check_arg_name;
+  // Check that the shape of the arguments generally matches what the
+  // closure function expects. The only remaining non-type check after this
+  // is that the names for optional arguments are valid.
+  body += BuildClosureCallArgumentsValidCheck(info);
+
+  // TODO(dartbug.com/40813): Move checks that are currently compiled
+  // in the closure body to here, using the dynamic versions of
+  // AssertSubtype to typecheck the type arguments using the runtime types
+  // available in the closure object.
+
+  // TODO(dartbug.com/40813): Move checks that are currently compiled
+  // in the closure body to here, using the dynamic versions of
+  // AssertAssignable to typecheck the parameters using the runtime types
+  // available in the closure object.
+
+  // Drop all the read-only temporaries at the end of the fragment.
+  if (info.type_parameters != nullptr) {
+    body += DropTemporary(&info.type_parameters);
+  }
+  if (info.parameter_names != nullptr) {
+    body += DropTemporary(&info.parameter_names);
+  }
+  body += DropTemporary(&info.has_named_params);
+  body += DropTemporary(&info.num_max_params);
+  body += DropTemporary(&info.num_opt_params);
+  body += DropTemporary(&info.num_fixed_params);
+  body += DropTemporary(&info.function);
+
+  return body;
 }
 
 FlowGraph* FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher(
@@ -2334,7 +2472,7 @@
 
   // Build any dynamic closure call checks before pushing arguments to the
   // final call on the stack to make debugging easier.
-  LocalVariable* closure = NULL;
+  LocalVariable* closure = nullptr;
   if (is_closure_call) {
     closure = parsed_function_->ParameterVariable(0);
     if (is_dynamic_call) {
@@ -2344,30 +2482,7 @@
       InlineBailout(
           "kernel::FlowGraphBuilder::BuildGraphOfInvokeFieldDispatcher");
 
-      // Init the variables we'll be using for dynamic call checking.
-      body += BuildDynamicCallVarsInit(closure);
-
-      JoinEntryInstr* nsm = BuildThrowNoSuchMethod();
-      // Check that the shape of the arguments generally matches what the
-      // closure function expects. The only remaining non-type check after this
-      // is that the names for optional arguments are valid.
-      body += BuildClosureCallArgumentsValidCheck(closure, nsm);
-
-      // TODO(dartbug.com/40813): Move checks that are currently compiled
-      // in the closure body to here, using the dynamic versions of
-      // AssertSubtype to typecheck the type arguments using the runtime types
-      // available in the closure object.
-
-      // TODO(dartbug.com/40813): Move checks that are currently compiled
-      // in the closure body to here, using the dynamic versions of
-      // AssertAssignable to typecheck the parameters using the runtime types
-      // available in the closure object.
-      //
-      // For now, we check that any named arguments have valid names.
-      for (intptr_t pos = descriptor.PositionalCount();
-           pos < descriptor.Count(); pos++) {
-        body += BuildClosureCallNamedArgumentCheck(closure, pos, nsm);
-      }
+      body += BuildDynamicClosureCallChecks(closure);
     }
   }
 
@@ -3258,7 +3373,7 @@
   // do not appear in the type arguments to a any Pointer classes in an FFI
   // signature.
   ASSERT(args.IsNull() || args.IsInstantiated());
-  args = args.Canonicalize();
+  args = args.Canonicalize(thread_, nullptr);
 
   Fragment code;
   code += Constant(args);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 957807b..173db75 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -80,31 +80,32 @@
   FlowGraph* BuildGraphOfMethodExtractor(const Function& method);
   FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
 
-  Fragment BuildDynamicCallVarsInit(LocalVariable* closure);
+  struct ClosureCallInfo;
+
+  // Tests whether the function parameter at the given index is required and
+  // branches to the appropriate fragment. Loads the parameter index to
+  // check from info.vars->current_param_index.
+  Fragment TestClosureFunctionNamedParameterRequired(
+      const ClosureCallInfo& info,
+      Fragment set,
+      Fragment not_set);
 
   // The BuildClosureCall...Check methods differs from the checks built in the
   // PrologueBuilder in that they are built for invoke field dispatchers,
   // where the ArgumentsDescriptor is known at compile time but the specific
   // closure function is retrieved at runtime.
 
-  // Builds checks that all required arguments are provided. Generates an empty
-  // fragment if null safety is not enabled.
-  Fragment BuildClosureCallHasRequiredNamedArgumentsCheck(
-      LocalVariable* closure,
-      JoinEntryInstr* nsm);
+  // Builds checks that the given named arguments have valid argument names
+  // and, in the case of null safe code, that all required named parameters
+  // are provided.
+  Fragment BuildClosureCallNamedArgumentsCheck(const ClosureCallInfo& info);
 
   // Builds checks for checking the arguments of a call are valid for the
-  // function retrieved at runtime from the closure. Checks almost all the
-  // same cases as Function::AreArgumentsValid, leaving only name checking
-  // for optional named arguments to be checked during argument type checking.
-  Fragment BuildClosureCallArgumentsValidCheck(LocalVariable* closure,
-                                               JoinEntryInstr* nsm);
+  // function retrieved at runtime from the closure.
+  Fragment BuildClosureCallArgumentsValidCheck(const ClosureCallInfo& info);
 
-  // Builds checks that the given named argument has a valid argument name.
-  // Returns the empty fragment for positional arguments.
-  Fragment BuildClosureCallNamedArgumentCheck(LocalVariable* closure,
-                                              intptr_t pos,
-                                              JoinEntryInstr* nsm);
+  // Main entry point for building checks.
+  Fragment BuildDynamicClosureCallChecks(LocalVariable* closure);
 
   FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
   FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
@@ -120,6 +121,8 @@
 
   Fragment BuildTypedDataViewFactoryConstructor(const Function& function,
                                                 classid_t cid);
+  Fragment BuildTypedDataFactoryConstructor(const Function& function,
+                                            classid_t cid);
 
   Fragment EnterScope(intptr_t kernel_offset,
                       const LocalScope** scope = nullptr);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index d70966c..ff40a8b 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -340,12 +340,7 @@
 InstancePtr TranslationHelper::Canonicalize(const Instance& instance) {
   if (instance.IsNull()) return instance.raw();
 
-  const char* error_str = NULL;
-  InstancePtr result = instance.CheckAndCanonicalize(thread(), &error_str);
-  if (result == Object::null()) {
-    ReportError("Invalid const object %s", error_str);
-  }
-  return result;
+  return instance.Canonicalize(thread());
 }
 
 const String& TranslationHelper::DartString(const char* content,
@@ -370,6 +365,11 @@
   return String::ZoneHandle(Z, String::FromUTF8(utf8_array, len, space));
 }
 
+const String& TranslationHelper::DartString(
+    const GrowableHandlePtrArray<const String>& pieces) {
+  return String::ZoneHandle(Z, Symbols::FromConcatAll(thread_, pieces));
+}
+
 const String& TranslationHelper::DartSymbolPlain(const char* content) const {
   return String::ZoneHandle(Z, Symbols::New(thread_, content));
 }
@@ -1821,13 +1821,13 @@
   AlternativeReadingScopeWithNewData alt(&helper_->reader_,
                                          &H.metadata_payloads(), md_offset);
 
-  Thread* T = Thread::Current();
-  Zone* Z = T->zone();
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
   intptr_t unit_count = helper_->ReadUInt();
-  Array& loading_units = Array::Handle(Z, Array::New(unit_count + 1));
-  LoadingUnit& unit = LoadingUnit::Handle(Z);
-  LoadingUnit& parent = LoadingUnit::Handle(Z);
-  Library& lib = Library::Handle(Z);
+  Array& loading_units = Array::Handle(zone, Array::New(unit_count + 1));
+  LoadingUnit& unit = LoadingUnit::Handle(zone);
+  LoadingUnit& parent = LoadingUnit::Handle(zone);
+  Library& lib = Library::Handle(zone);
 
   for (int i = 0; i < unit_count; i++) {
     intptr_t id = helper_->ReadUInt();
@@ -1844,7 +1844,7 @@
     for (intptr_t j = 0; j < library_count; j++) {
       const String& uri =
           translation_helper_.DartSymbolPlain(helper_->ReadStringReference());
-      lib = Library::LookupLibrary(T, uri);
+      lib = Library::LookupLibrary(thread, uri);
       if (lib.IsNull()) {
         FATAL1("Missing library: %s\n", uri.ToCString());
       }
@@ -2332,17 +2332,6 @@
       SkipExpression();              // read value.
       SkipInterfaceMemberNameReference();  // read interface_target_reference.
       return;
-    case kDirectPropertyGet:
-      ReadPosition();                // read position.
-      SkipExpression();              // read receiver.
-      SkipInterfaceMemberNameReference();  // read target_reference.
-      return;
-    case kDirectPropertySet:
-      ReadPosition();                // read position.
-      SkipExpression();              // read receiver.
-      SkipInterfaceMemberNameReference();  // read target_reference.
-      SkipExpression();              // read value·
-      return;
     case kStaticGet:
       ReadPosition();                // read position.
       SkipCanonicalNameReference();  // read target_reference.
@@ -2365,12 +2354,6 @@
       SkipArguments();               // read arguments.
       SkipInterfaceMemberNameReference();  // read interface_target_reference.
       return;
-    case kDirectMethodInvocation:
-      ReadPosition();                // read position.
-      SkipExpression();              // read receiver.
-      SkipInterfaceMemberNameReference();  // read target_reference.
-      SkipArguments();               // read arguments.
-      return;
     case kStaticInvocation:
       ReadPosition();                // read position.
       SkipCanonicalNameReference();  // read procedure_reference.
@@ -3258,7 +3241,7 @@
     }
 
     if (finalize_) {
-      type_arguments = type_arguments.Canonicalize();
+      type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
     }
   }
   return type_arguments;
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index f05d261..cec43d5 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -129,6 +129,8 @@
                      intptr_t len,
                      Heap::Space space);
 
+  const String& DartString(const GrowableHandlePtrArray<const String>& pieces);
+
   const String& DartSymbolPlain(const char* content) const;
   String& DartSymbolPlain(StringIndex string_index) const;
   const String& DartSymbolObfuscate(const char* content) const;
diff --git a/runtime/vm/compiler/frontend/multiple_entrypoints_test.cc b/runtime/vm/compiler/frontend/multiple_entrypoints_test.cc
new file mode 100644
index 0000000..9ae1679
--- /dev/null
+++ b/runtime/vm/compiler/frontend/multiple_entrypoints_test.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/compiler/backend/il_test_helper.h"
+#include "vm/compiler/compiler_pass.h"
+#include "vm/object.h"
+#include "vm/unit_test.h"
+
+namespace dart {
+
+#if defined(DART_PRECOMPILER)
+
+ISOLATE_UNIT_TEST_CASE(IRTest_MultilpeEntryPoints_Regress43534) {
+  const char* kScript =
+      R"(
+      import 'dart:typed_data';
+
+      @pragma('vm:never-inline')
+      void callWith<T>(void Function(T arg) fun, T arg) {
+        fun(arg);
+      }
+
+      @pragma('vm:never-inline')
+      void use(dynamic arg) {}
+
+      void test() {
+        callWith<Uint8List>((Uint8List list) {
+          use(list);
+        }, Uint8List(10));
+      }
+      )";
+
+  const auto& root_library = Library::Handle(LoadTestScript(kScript));
+  Invoke(root_library, "test");
+  const auto& test_function =
+      Function::Handle(GetFunction(root_library, "test"));
+  const auto& closures = GrowableObjectArray::Handle(
+      Isolate::Current()->object_store()->closure_functions());
+  auto& function = Function::Handle();
+  for (intptr_t i = closures.Length() - 1; 0 <= i; ++i) {
+    function ^= closures.At(i);
+    if (function.parent_function() == test_function.raw()) {
+      break;
+    }
+    function = Function::null();
+  }
+  RELEASE_ASSERT(!function.IsNull());
+  TestPipeline pipeline(function, CompilerPass::kAOT);
+  FlowGraph* flow_graph = pipeline.RunPasses({CompilerPass::kComputeSSA});
+
+  auto entry = flow_graph->graph_entry()->normal_entry();
+  EXPECT(entry != nullptr);
+
+  auto unchecked_entry = flow_graph->graph_entry()->unchecked_entry();
+  EXPECT(unchecked_entry != nullptr);
+
+  AssertAssignableInstr* assert_assignable = nullptr;
+  StaticCallInstr* static_call = nullptr;
+
+  // Normal entry
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true);
+  RELEASE_ASSERT(cursor.TryMatch(
+      {
+          kMatchAndMoveGoto,
+          kMatchAndMoveBranchFalse,
+          {kMatchAndMoveAssertAssignable, &assert_assignable},
+          kMatchAndMoveGoto,
+          {kMatchAndMoveStaticCall, &static_call},
+          kMatchReturn,
+      },
+      kMoveGlob));
+
+  RedefinitionInstr* redefinition = nullptr;
+  StaticCallInstr* static_call2 = nullptr;
+
+  // Unchecked entry
+  ILMatcher cursor2(flow_graph, entry, /*trace=*/true);
+  RELEASE_ASSERT(cursor2.TryMatch(
+      {
+          kMatchAndMoveGoto,
+          kMatchAndMoveBranchTrue,
+          {kMatchAndMoveRedefinition, &redefinition},
+          kMatchAndMoveGoto,
+          {kMatchAndMoveStaticCall, &static_call2},
+          kMatchReturn,
+      },
+      kMoveGlob));
+
+  // Ensure the value the static call uses is a Phi node with 2 inputs:
+  //   a) Normal entry: AssertAssignable
+  //   b) Unchecked entry: Redefinition
+  RELEASE_ASSERT(static_call->ArgumentAt(0)->IsPhi());
+  auto phi = static_call->ArgumentAt(0)->AsPhi();
+  auto input_a = phi->InputAt(0)->definition();
+  auto input_b = phi->InputAt(1)->definition();
+  RELEASE_ASSERT(input_a->IsRedefinition());
+  RELEASE_ASSERT(input_b->IsAssertAssignable());
+  RELEASE_ASSERT(input_a == redefinition);
+  RELEASE_ASSERT(input_b == assert_assignable);
+  RELEASE_ASSERT(static_call == static_call2);
+}
+
+#endif  // defined(DART_PRECOMPILER)
+
+}  // namespace dart
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index b91b32a..56e1dda 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -148,8 +148,8 @@
           (parent.num_fixed_parameters() != target.num_fixed_parameters())) {
         needs_expr_temp_ = true;
       }
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case FunctionLayout::kClosureFunction:
     case FunctionLayout::kRegularFunction:
     case FunctionLayout::kGetterFunction:
@@ -441,10 +441,9 @@
 #define ADD_VAR(Name, _, __) scope_->AddVariable(vars->Name);
         FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(ADD_VAR);
 #undef ADD_VAR
-        needs_expr_temp_ = true;
       }
-      FALL_THROUGH;
     }
+      FALL_THROUGH;
     case FunctionLayout::kNoSuchMethodDispatcher: {
       for (intptr_t i = 0; i < function.NumParameters(); ++i) {
         LocalVariable* variable = MakeVariable(
@@ -756,17 +755,6 @@
       // read interface_target_reference.
       helper_.SkipInterfaceMemberNameReference();
       return;
-    case kDirectPropertyGet:
-      helper_.ReadPosition();                // read position.
-      VisitExpression();                     // read receiver.
-      helper_.SkipInterfaceMemberNameReference();  // read target_reference.
-      return;
-    case kDirectPropertySet:
-      helper_.ReadPosition();                // read position.
-      VisitExpression();                     // read receiver.
-      helper_.SkipInterfaceMemberNameReference();  // read target_reference.
-      VisitExpression();                     // read value·
-      return;
     case kSuperPropertyGet:
       HandleLoadReceiver();
       helper_.ReadPosition();                // read position.
@@ -797,12 +785,6 @@
       // read interface_target_reference.
       helper_.SkipInterfaceMemberNameReference();
       return;
-    case kDirectMethodInvocation:
-      helper_.ReadPosition();                // read position.
-      VisitExpression();                     // read receiver.
-      helper_.SkipInterfaceMemberNameReference();  // read target_reference.
-      VisitArguments();                      // read arguments.
-      return;
     case kSuperMethodInvocation:
       HandleLoadReceiver();
       helper_.ReadPosition();  // read position.
@@ -1581,6 +1563,7 @@
   VariableDeclarationHelper helper(&helper_);
   helper.ReadUntilExcluding(VariableDeclarationHelper::kType);
   String& name = H.DartSymbolObfuscate(helper.name_index_);
+  ASSERT(name.Length() > 0);
   AbstractType& type = BuildAndVisitVariableType();  // read type.
   helper.SetJustRead(VariableDeclarationHelper::kType);
   helper.ReadUntilExcluding(VariableDeclarationHelper::kInitializer);
@@ -1601,6 +1584,9 @@
       helper.IsCovariant() ||
       (helper.IsGenericCovariantImpl() &&
        (attrs.has_non_this_uses || attrs.has_tearoff_uses));
+  if (needs_covariant_check_in_method) {
+    variable->set_needs_covariant_check_in_method();
+  }
 
   switch (type_check_mode) {
     case kTypeCheckAllParameters:
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 7277c21..a1f21f1 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -181,7 +181,6 @@
 };
 
 static IntrinsicDesc typed_data_intrinsics[] = {
-  TYPED_DATA_LIB_INTRINSIC_LIST(DEFINE_INTRINSIC)
   GRAPH_TYPED_DATA_INTRINSICS_LIST(DEFINE_INTRINSIC)
   {nullptr, nullptr},
 };
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 1139cdc..72e16f6 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -179,6 +179,10 @@
   RegExpEngine::CompilationResult result =
       RegExpEngine::CompileIR(parsed_function->regexp_compile_data(),
                               parsed_function, *ic_data_array, osr_id);
+  if (result.error_message != nullptr) {
+    Report::LongJump(LanguageError::Handle(
+        LanguageError::New(String::Handle(String::New(result.error_message)))));
+  }
   backtrack_goto_ = result.backtrack_goto;
 
   // Allocate variables now that we know the number of locals.
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
index a75c847..c89ff54 100644
--- a/runtime/vm/compiler/offsets_extractor.cc
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -38,6 +38,16 @@
 class OffsetsExtractor : public AllStatic {
  public:
   static void DumpOffsets() {
+// Currently we have two different axes for offset generation:
+//
+//  * Target architecture
+//  * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT)
+//
+// TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis.
+
+// This doesn't use any special constants, just method calls, so no output.
+#define PRINT_PAYLOAD_SIZEOF(Class, Name, HeaderSize)
+
 #if defined(DART_PRECOMPILED_RUNTIME)
 
 #define PRINT_FIELD_OFFSET(Class, Name)                                        \
@@ -119,18 +129,19 @@
             << Class::Name << ";\n";
 
     JIT_OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT, PRINT_SIZEOF,
-                     PRINT_RANGE, PRINT_CONSTANT)
+                     PRINT_PAYLOAD_SIZEOF, PRINT_RANGE, PRINT_CONSTANT)
 
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
     COMMON_OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT, PRINT_SIZEOF,
-                        PRINT_RANGE, PRINT_CONSTANT)
+                        PRINT_PAYLOAD_SIZEOF, PRINT_RANGE, PRINT_CONSTANT)
 
 #undef PRINT_FIELD_OFFSET
 #undef PRINT_ARRAY_LAYOUT
 #undef PRINT_SIZEOF
 #undef PRINT_RANGE
 #undef PRINT_CONSTANT
+#undef PRINT_PAYLOAD_SIZEOF
   }
 };
 
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index c05d57b..e9f8516a 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -64,10 +64,24 @@
   V(_Float32x4ArrayView, ._, TypedData_Float32x4ArrayView_factory, 0x5bb7771d) \
   V(_Int32x4ArrayView, ._, TypedData_Int32x4ArrayView_factory, 0x30b9f2a2)     \
   V(_Float64x2ArrayView, ._, TypedData_Float64x2ArrayView_factory, 0x96490d01) \
+  V(Int8List, ., TypedData_Int8Array_factory, 0x80ad83e1)                      \
+  V(Uint8List, ., TypedData_Uint8Array_factory, 0x252e6768)                    \
+  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 0x1ed931ee)      \
+  V(Int16List, ., TypedData_Int16Array_factory, 0x7ea8630c)                    \
+  V(Uint16List, ., TypedData_Uint16Array_factory, 0x2764f743)                  \
+  V(Int32List, ., TypedData_Int32Array_factory, 0x54a56479)                    \
+  V(Uint32List, ., TypedData_Uint32Array_factory, 0xac4deaa4)                  \
+  V(Int64List, ., TypedData_Int64Array_factory, 0x02d4c748)                    \
+  V(Uint64List, ., TypedData_Uint64Array_factory, 0x08669751)                  \
+  V(Float32List, ., TypedData_Float32Array_factory, 0x8b65b9d7)                \
+  V(Float64List, ., TypedData_Float64Array_factory, 0x09ede82a)                \
+  V(Float32x4List, ., TypedData_Float32x4Array_factory, 0xb2a9e6e1)            \
+  V(Int32x4List, ., TypedData_Int32x4Array_factory, 0xa5292147)                \
+  V(Float64x2List, ., TypedData_Float64x2Array_factory, 0x20eafb43)            \
   V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x143ed675)                 \
   V(::, copyRangeFromUint8ListToOneByteString,                                 \
     CopyRangeFromUint8ListToOneByteString, 0x89d6a60a)                         \
-  V(_StringBase, _interpolate, StringBaseInterpolate, 0xbf682f1c)              \
+  V(_StringBase, _interpolate, StringBaseInterpolate, 0xd5a58efc)              \
   V(_IntegerImplementation, toDouble, IntegerToDouble, 0x5f8db5f5)             \
   V(_Double, _add, DoubleAdd, 0x4326962a)                                      \
   V(_Double, _sub, DoubleSub, 0x81077f31)                                      \
@@ -178,7 +192,7 @@
   V(::, reachabilityFence, ReachabilityFence, 0xad39d0a6)                      \
   V(_Utf8Decoder, _scan, Utf8DecoderScan, 0x78f44c3c)                          \
   V(_Future, timeout, FutureTimeout, 0x010f8ad4)                               \
-  V(Future, wait, FutureWait, 0x486414a9)                                      \
+  V(Future, wait, FutureWait, 0x6c0c3295)                                      \
 
 // List of intrinsics:
 // (class-name, function-name, intrinsification method, fingerprint).
@@ -281,22 +295,6 @@
   V(::, atan, MathAtan, 0x35d5ecd7)                                            \
   V(::, atan2, MathAtan2, 0xb4e03ae8)                                          \
 
-#define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
-  V(Int8List, ., TypedData_Int8Array_factory, 0x80ad83c2)                      \
-  V(Uint8List, ., TypedData_Uint8Array_factory, 0x252e6749)                    \
-  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 0x1ed931cf)      \
-  V(Int16List, ., TypedData_Int16Array_factory, 0x7ea862ed)                    \
-  V(Uint16List, ., TypedData_Uint16Array_factory, 0x2764f724)                  \
-  V(Int32List, ., TypedData_Int32Array_factory, 0x54a5645a)                    \
-  V(Uint32List, ., TypedData_Uint32Array_factory, 0xac4dea85)                  \
-  V(Int64List, ., TypedData_Int64Array_factory, 0x02d4c729)                    \
-  V(Uint64List, ., TypedData_Uint64Array_factory, 0x08669732)                  \
-  V(Float32List, ., TypedData_Float32Array_factory, 0x8b65b9b8)                \
-  V(Float64List, ., TypedData_Float64Array_factory, 0x09ede80b)                \
-  V(Float32x4List, ., TypedData_Float32x4Array_factory, 0xb2a9e6c2)            \
-  V(Int32x4List, ., TypedData_Int32x4Array_factory, 0xa5292128)                \
-  V(Float64x2List, ., TypedData_Float64x2Array_factory, 0x20eafb24)            \
-
 #define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
   V(_Int8List, [], Int8ArrayGetIndexed, 0xd61e79bd)                            \
   V(_Int8List, []=, Int8ArraySetIndexed, 0x6e0b2e72)                           \
@@ -401,7 +399,6 @@
   DEVELOPER_LIB_INTRINSIC_LIST(V)                                              \
   INTERNAL_LIB_INTRINSIC_LIST(V)                                               \
   MATH_LIB_INTRINSIC_LIST(V)                                                   \
-  TYPED_DATA_LIB_INTRINSIC_LIST(V)                                             \
 
 #define ALL_INTRINSICS_LIST(V)                                                 \
   ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                        \
@@ -456,22 +453,22 @@
     kGrowableObjectArrayCid, 0xf6fbbee3)                                       \
   V(_GrowableListWithData, _GrowableList, ._withData, kGrowableObjectArrayCid, \
     0x00be5928)                                                                \
-  V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x80ad83c2)        \
-  V(_Uint8ArrayFactory, Uint8List, ., kTypedDataUint8ArrayCid, 0x252e6749)     \
+  V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x80ad83e1)        \
+  V(_Uint8ArrayFactory, Uint8List, ., kTypedDataUint8ArrayCid, 0x252e6768)     \
   V(_Uint8ClampedArrayFactory, Uint8ClampedList, .,                            \
-    kTypedDataUint8ClampedArrayCid, 0x1ed931cf)                                \
-  V(_Int16ArrayFactory, Int16List, ., kTypedDataInt16ArrayCid, 0x7ea862ed)     \
-  V(_Uint16ArrayFactory, Uint16List, ., kTypedDataUint16ArrayCid, 0x2764f724)  \
-  V(_Int32ArrayFactory, Int32List, ., kTypedDataInt32ArrayCid, 0x54a5645a)     \
-  V(_Uint32ArrayFactory, Uint32List, ., kTypedDataUint32ArrayCid, 0xac4dea85)  \
-  V(_Int64ArrayFactory, Int64List, ., kTypedDataInt64ArrayCid, 0x02d4c729)     \
-  V(_Uint64ArrayFactory, Uint64List, ., kTypedDataUint64ArrayCid, 0x08669732)  \
+    kTypedDataUint8ClampedArrayCid, 0x1ed931ee)                                \
+  V(_Int16ArrayFactory, Int16List, ., kTypedDataInt16ArrayCid, 0x7ea8630c)     \
+  V(_Uint16ArrayFactory, Uint16List, ., kTypedDataUint16ArrayCid, 0x2764f743)  \
+  V(_Int32ArrayFactory, Int32List, ., kTypedDataInt32ArrayCid, 0x54a56479)     \
+  V(_Uint32ArrayFactory, Uint32List, ., kTypedDataUint32ArrayCid, 0xac4deaa4)  \
+  V(_Int64ArrayFactory, Int64List, ., kTypedDataInt64ArrayCid, 0x02d4c748)     \
+  V(_Uint64ArrayFactory, Uint64List, ., kTypedDataUint64ArrayCid, 0x08669751)  \
   V(_Float64ArrayFactory, Float64List, ., kTypedDataFloat64ArrayCid,           \
-    0x09ede80b)                                                                \
+    0x09ede82a)                                                                \
   V(_Float32ArrayFactory, Float32List, ., kTypedDataFloat32ArrayCid,           \
-    0x8b65b9b8)                                                                \
+    0x8b65b9d7)                                                                \
   V(_Float32x4ArrayFactory, Float32x4List, ., kTypedDataFloat32x4ArrayCid,     \
-    0xb2a9e6c2)
+    0xb2a9e6e1)
 
 // clang-format on
 
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index d84a679..a14f615 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -22,7 +22,7 @@
 
 const intptr_t kTrampolineSize =
     Utils::RoundUp(PcRelativeTrampolineJumpPattern::kLengthInBytes,
-                   ImageWriter::kBareInstructionsAlignment);
+                   compiler::target::Instructions::kBarePayloadAlignment);
 
 CodeRelocator::CodeRelocator(Thread* thread,
                              GrowableArray<CodePtr>* code_objects,
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 8a16400..d3627d0 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -278,6 +278,10 @@
   return target::Thread::OffsetFromThread(runtime_entry_);
 }
 
+bool RuntimeEntry::is_leaf() const {
+  return runtime_entry_->is_leaf();
+}
+
 namespace target {
 
 const word kOldPageSize = dart::kOldPageSize;
@@ -508,8 +512,21 @@
   return TranslateOffsetInWords(dart::Context::variable_offset(n));
 }
 
+// Currently we have two different axes for offset generation:
+//
+//  * Target architecture
+//  * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT)
+//
+// TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis.
+
 #define DEFINE_CONSTANT(Class, Name) const word Class::Name = Class##_##Name;
 
+#define DEFINE_PAYLOAD_SIZEOF(clazz, name, header)                             \
+  word clazz::name() { return 0; }                                             \
+  word clazz::name(word payload_size) {                                        \
+    return RoundedAllocationSize(clazz::header() + payload_size);              \
+  }
+
 #if defined(TARGET_ARCH_IA32)
 
 #define DEFINE_FIELD(clazz, name)                                              \
@@ -532,12 +549,14 @@
 JIT_OFFSETS_LIST(DEFINE_FIELD,
                  DEFINE_ARRAY,
                  DEFINE_SIZEOF,
+                 DEFINE_PAYLOAD_SIZEOF,
                  DEFINE_RANGE,
                  DEFINE_CONSTANT)
 
 COMMON_OFFSETS_LIST(DEFINE_FIELD,
                     DEFINE_ARRAY,
                     DEFINE_SIZEOF,
+                    DEFINE_PAYLOAD_SIZEOF,
                     DEFINE_RANGE,
                     DEFINE_CONSTANT)
 
@@ -582,6 +601,7 @@
 JIT_OFFSETS_LIST(DEFINE_JIT_FIELD,
                  DEFINE_JIT_ARRAY,
                  DEFINE_JIT_SIZEOF,
+                 DEFINE_PAYLOAD_SIZEOF,
                  DEFINE_JIT_RANGE,
                  DEFINE_CONSTANT)
 
@@ -624,6 +644,7 @@
 COMMON_OFFSETS_LIST(DEFINE_FIELD,
                     DEFINE_ARRAY,
                     DEFINE_SIZEOF,
+                    DEFINE_PAYLOAD_SIZEOF,
                     DEFINE_RANGE,
                     DEFINE_CONSTANT)
 
@@ -633,19 +654,44 @@
 #undef DEFINE_ARRAY
 #undef DEFINE_SIZEOF
 #undef DEFINE_RANGE
+#undef DEFINE_PAYLOAD_SIZEOF
 #undef DEFINE_CONSTANT
 
 const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;
 
 const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
 
+// For InstructionsSections and Instructions, we define these by hand, because
+// they depend on flags or #defines.
+
+// Used for InstructionsSection and Instructions methods, since we don't
+// serialize Instructions objects in bare instructions mode, just payloads.
+DART_FORCE_INLINE static bool BareInstructionsPayloads() {
+  return FLAG_precompiled_mode && FLAG_use_bare_instructions;
+}
+
 word InstructionsSection::HeaderSize() {
+  // We only create InstructionsSections in precompiled mode.
+  ASSERT(FLAG_precompiled_mode);
   return Utils::RoundUp(InstructionsSection::UnalignedHeaderSize(),
-                        target::kWordSize);
+                        Instructions::kBarePayloadAlignment);
 }
 
 word Instructions::HeaderSize() {
-  return Utils::RoundUp(Instructions::UnalignedHeaderSize(), target::kWordSize);
+  return BareInstructionsPayloads()
+             ? 0
+             : Utils::RoundUp(UnalignedHeaderSize(), kNonBarePayloadAlignment);
+}
+
+word Instructions::InstanceSize() {
+  return 0;
+}
+
+word Instructions::InstanceSize(word payload_size) {
+  const intptr_t alignment = BareInstructionsPayloads()
+                                 ? kBarePayloadAlignment
+                                 : ObjectAlignment::kObjectAlignment;
+  return Utils::RoundUp(Instructions::HeaderSize() + payload_size, alignment);
 }
 
 word Thread::stack_overflow_shared_stub_entry_point_offset(bool fpu_regs) {
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 4d70b77..ac5ff81 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -68,9 +68,16 @@
 extern InvalidClass kWordSize;
 extern InvalidClass kWordSizeLog2;
 extern InvalidClass kBitsPerWord;
+extern InvalidClass kBitsPerWordLog2;
+extern InvalidClass kWordMin;
+extern InvalidClass kWordMax;
+extern InvalidClass kUWordMax;
 extern InvalidClass kNewObjectAlignmentOffset;
 extern InvalidClass kOldObjectAlignmentOffset;
 extern InvalidClass kNewObjectBitPosition;
+extern InvalidClass kOldPageSize;
+extern InvalidClass kOldPageSizeInWords;
+extern InvalidClass kOldPageMask;
 extern InvalidClass kObjectAlignment;
 extern InvalidClass kObjectAlignmentLog2;
 extern InvalidClass kObjectAlignmentMask;
@@ -233,6 +240,8 @@
 
   word OffsetFromThread() const;
 
+  bool is_leaf() const;
+
  protected:
   RuntimeEntry(const dart::RuntimeEntry* runtime_entry,
                RuntimeEntryCallInternal call)
@@ -278,6 +287,9 @@
 #endif
 static constexpr int kWordSize = 1 << kWordSizeLog2;
 static_assert(kWordSize == sizeof(word), "kWordSize should match sizeof(word)");
+// Our compiler code currently assumes this, so formally check it.
+static_assert(dart::kWordSize >= kWordSize,
+              "Host word size smaller than target word size");
 
 static constexpr word kBitsPerWordLog2 = kWordSizeLog2 + kBitsPerByteLog2;
 static constexpr word kBitsPerWord = 1 << kBitsPerWordLog2;
@@ -800,13 +812,17 @@
 
 class PcDescriptors : public AllStatic {
  public:
+  static word HeaderSize();
   static word InstanceSize();
+  static word InstanceSize(word payload_size);
   static word NextFieldOffset();
 };
 
 class CodeSourceMap : public AllStatic {
  public:
+  static word HeaderSize();
   static word InstanceSize();
+  static word InstanceSize(word payload_size);
   static word NextFieldOffset();
 };
 
@@ -814,6 +830,7 @@
  public:
   static word HeaderSize();
   static word InstanceSize();
+  static word InstanceSize(word payload_size);
   static word NextFieldOffset();
 };
 
@@ -1145,9 +1162,10 @@
 
 class InstructionsSection : public AllStatic {
  public:
-  static word HeaderSize();
   static word UnalignedHeaderSize();
+  static word HeaderSize();
   static word InstanceSize();
+  static word InstanceSize(word payload_size);
   static word NextFieldOffset();
 };
 
@@ -1157,9 +1175,12 @@
   static const word kPolymorphicEntryOffsetJIT;
   static const word kMonomorphicEntryOffsetAOT;
   static const word kPolymorphicEntryOffsetAOT;
-  static word HeaderSize();
+  static const word kBarePayloadAlignment;
+  static const word kNonBarePayloadAlignment;
   static word UnalignedHeaderSize();
+  static word HeaderSize();
   static word InstanceSize();
+  static word InstanceSize(word payload_size);
   static word NextFieldOffset();
 };
 
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 1c8cd1c2fd..4a6d9e0 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -36,6 +36,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 12;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -207,9 +211,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     724;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    728;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -234,7 +238,7 @@
     Thread_allocate_object_slow_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 200;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 756;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
@@ -247,7 +251,7 @@
     Thread_call_to_runtime_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 764;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 768;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -265,7 +269,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    744;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -285,7 +289,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    732;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -293,7 +297,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    752;
+    756;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
@@ -332,11 +336,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    748;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -369,7 +373,7 @@
     Thread_write_barrier_entry_point_offset = 264;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -415,7 +419,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -426,9 +430,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word Code_InstanceSize = 96;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 8;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
 static constexpr dart::compiler::target::word Context_InstanceSize = 12;
@@ -455,13 +457,10 @@
     16;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    8;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 8;
+    InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -487,7 +486,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     24;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 8;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 16;
@@ -542,6 +541,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 22;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -715,9 +718,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1448;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1456;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1464;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -743,7 +746,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1520;
+    1528;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
@@ -756,7 +759,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1536;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1544;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -774,7 +777,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1488;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -794,7 +797,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -802,7 +805,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
@@ -841,11 +844,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1472;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1480;
+    Thread_saved_shadow_call_stack_offset = 1488;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -879,7 +882,7 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -926,8 +929,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, -1,   -1,   1392, 1400,
-        1408, 1416, 1424, -1,   1432, 1440, -1,   -1};
+        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
+        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -938,9 +941,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word Code_InstanceSize = 176;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 16;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    12;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     12;
 static constexpr dart::compiler::target::word Context_InstanceSize = 24;
@@ -967,13 +968,10 @@
     32;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    16;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 16;
+    InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -999,7 +997,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     48;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 16;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 32;
@@ -1054,6 +1052,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 0;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -1225,9 +1227,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    688;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     692;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    696;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -1252,7 +1254,7 @@
     Thread_allocate_object_slow_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 200;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 724;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 728;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
@@ -1265,7 +1267,7 @@
     Thread_call_to_runtime_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 732;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 736;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1283,7 +1285,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    708;
+    712;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -1303,7 +1305,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    696;
+    700;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -1311,7 +1313,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    720;
+    724;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
@@ -1350,11 +1352,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 700;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 704;
+    Thread_saved_shadow_call_stack_offset = 708;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    712;
+    716;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -1387,7 +1389,7 @@
     Thread_write_barrier_entry_point_offset = 264;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 716;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -1441,9 +1443,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word Code_InstanceSize = 96;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 8;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
 static constexpr dart::compiler::target::word Context_InstanceSize = 12;
@@ -1470,13 +1470,10 @@
     16;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    8;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 8;
+    InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -1502,7 +1499,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     24;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 8;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 16;
@@ -1557,6 +1554,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 20;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -1730,9 +1731,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -1758,7 +1759,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
@@ -1771,7 +1772,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1608;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -1789,7 +1790,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -1809,7 +1810,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -1817,7 +1818,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1584;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
@@ -1856,11 +1857,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -1894,7 +1895,7 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -1941,9 +1942,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440,
-        1448, 1456, 1464, 1472, -1,   -1,   -1,   -1,   1480, 1488, -1,
-        -1,   1496, 1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
+        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
+        -1,   1504, 1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -1954,9 +1955,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word Code_InstanceSize = 176;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 16;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    12;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     12;
 static constexpr dart::compiler::target::word Context_InstanceSize = 24;
@@ -1983,13 +1982,10 @@
     32;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    16;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 16;
+    InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -2015,7 +2011,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     48;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 16;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 32;
@@ -2072,6 +2068,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 12;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -2240,9 +2240,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    720;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     724;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    728;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -2267,7 +2267,7 @@
     Thread_allocate_object_slow_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 200;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 756;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 760;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
@@ -2280,7 +2280,7 @@
     Thread_call_to_runtime_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 764;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 768;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2298,7 +2298,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    740;
+    744;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -2318,7 +2318,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    728;
+    732;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -2326,7 +2326,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    752;
+    756;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
@@ -2365,11 +2365,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 736;
+    Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    744;
+    748;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -2402,7 +2402,7 @@
     Thread_write_barrier_entry_point_offset = 264;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 752;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -2445,7 +2445,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word Array_header_size = 12;
@@ -2456,9 +2456,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word Code_InstanceSize = 76;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 8;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
 static constexpr dart::compiler::target::word Context_InstanceSize = 12;
@@ -2485,13 +2483,10 @@
     16;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    8;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 8;
+    InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -2517,7 +2512,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     24;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 8;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 16;
@@ -2572,6 +2567,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 22;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -2742,9 +2741,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1448;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1456;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1464;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -2770,7 +2769,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1520;
+    1528;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
@@ -2783,7 +2782,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1536;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1544;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -2801,7 +2800,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1488;
+    1496;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -2821,7 +2820,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1464;
+    1472;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -2829,7 +2828,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1512;
+    1520;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
@@ -2868,11 +2867,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1472;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1480;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1480;
+    Thread_saved_shadow_call_stack_offset = 1488;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1496;
+    1504;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -2906,7 +2905,7 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -2950,8 +2949,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, -1,   -1,   1392, 1400,
-        1408, 1416, 1424, -1,   1432, 1440, -1,   -1};
+        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
+        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -2962,9 +2961,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word Code_InstanceSize = 144;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 16;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    12;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     12;
 static constexpr dart::compiler::target::word Context_InstanceSize = 24;
@@ -2991,13 +2988,10 @@
     32;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    16;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 16;
+    InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -3023,7 +3017,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     48;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 16;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 32;
@@ -3078,6 +3072,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 0;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -3246,9 +3244,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    688;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     692;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    696;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -3273,7 +3271,7 @@
     Thread_allocate_object_slow_entry_point_offset = 292;
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 200;
-static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 724;
+static constexpr dart::compiler::target::word Thread_api_top_scope_offset = 728;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     96;
 static constexpr dart::compiler::target::word
@@ -3286,7 +3284,7 @@
     Thread_call_to_runtime_entry_point_offset = 272;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 148;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 732;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 736;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3304,7 +3302,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    708;
+    712;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -3324,7 +3322,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    696;
+    700;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -3332,7 +3330,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    720;
+    724;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     68;
@@ -3371,11 +3369,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 112;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 700;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 704;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 704;
+    Thread_saved_shadow_call_stack_offset = 708;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    712;
+    716;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -3408,7 +3406,7 @@
     Thread_write_barrier_entry_point_offset = 264;
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     40;
-static constexpr dart::compiler::target::word Thread_callback_code_offset = 716;
+static constexpr dart::compiler::target::word Thread_callback_code_offset = 720;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 12;
 static constexpr dart::compiler::target::word Type_arguments_offset = 16;
@@ -3459,9 +3457,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word Code_InstanceSize = 76;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 8;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     8;
 static constexpr dart::compiler::target::word Context_InstanceSize = 12;
@@ -3488,13 +3484,10 @@
     16;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 32;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     8;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    8;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 8;
+    InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -3520,7 +3513,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     24;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 24;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 8;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 16;
@@ -3575,6 +3568,10 @@
     Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     Instructions_kPolymorphicEntryOffsetAOT = 20;
+static constexpr dart::compiler::target::word
+    Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word OldPage_kBytesPerCardLog2 = 10;
 static constexpr dart::compiler::target::word
     NativeEntry_kNumCallWrapperArguments = 2;
@@ -3745,9 +3742,9 @@
 static constexpr dart::compiler::target::word
     Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word Thread_active_exception_offset =
-    1520;
-static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
     1528;
+static constexpr dart::compiler::target::word Thread_active_stacktrace_offset =
+    1536;
 static constexpr dart::compiler::target::word
     Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -3773,7 +3770,7 @@
 static constexpr dart::compiler::target::word
     Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word Thread_api_top_scope_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word Thread_async_stack_trace_offset =
     192;
 static constexpr dart::compiler::target::word
@@ -3786,7 +3783,7 @@
     Thread_call_to_runtime_entry_point_offset = 528;
 static constexpr dart::compiler::target::word
     Thread_call_to_runtime_stub_offset = 280;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1608;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
 static constexpr dart::compiler::target::word
     Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word Thread_optimize_entry_offset =
@@ -3804,7 +3801,7 @@
 static constexpr dart::compiler::target::word
     Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word Thread_execution_state_offset =
-    1560;
+    1568;
 static constexpr dart::compiler::target::word
     Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -3824,7 +3821,7 @@
 static constexpr dart::compiler::target::word
     Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word Thread_global_object_pool_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -3832,7 +3829,7 @@
 static constexpr dart::compiler::target::word
     Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
-    1584;
+    1592;
 static constexpr dart::compiler::target::word Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word Thread_field_table_values_offset =
     136;
@@ -3871,11 +3868,11 @@
 static constexpr dart::compiler::target::word Thread_object_null_offset = 208;
 static constexpr dart::compiler::target::word
     Thread_predefined_symbols_address_offset = 672;
-static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1544;
+static constexpr dart::compiler::target::word Thread_resume_pc_offset = 1552;
 static constexpr dart::compiler::target::word
-    Thread_saved_shadow_call_stack_offset = 1552;
+    Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word Thread_safepoint_state_offset =
-    1568;
+    1576;
 static constexpr dart::compiler::target::word
     Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -3909,7 +3906,7 @@
 static constexpr dart::compiler::target::word Thread_write_barrier_mask_offset =
     80;
 static constexpr dart::compiler::target::word Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word TimelineStream_enabled_offset =
     16;
 static constexpr dart::compiler::target::word TwoByteString_data_offset = 16;
@@ -3953,9 +3950,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440,
-        1448, 1456, 1464, 1472, -1,   -1,   -1,   -1,   1480, 1488, -1,
-        -1,   1496, 1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
+        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
+        -1,   1504, 1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word Array_header_size = 24;
@@ -3966,9 +3963,7 @@
 static constexpr dart::compiler::target::word Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word Code_InstanceSize = 144;
-static constexpr dart::compiler::target::word CodeSourceMap_InstanceSize = 16;
-static constexpr dart::compiler::target::word CompressedStackMaps_InstanceSize =
-    12;
+static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word CompressedStackMaps_HeaderSize =
     12;
 static constexpr dart::compiler::target::word Context_InstanceSize = 24;
@@ -3995,13 +3990,10 @@
     32;
 static constexpr dart::compiler::target::word ICData_InstanceSize = 56;
 static constexpr dart::compiler::target::word Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word Instructions_InstanceSize = 12;
 static constexpr dart::compiler::target::word Instructions_UnalignedHeaderSize =
     12;
-static constexpr dart::compiler::target::word InstructionsSection_InstanceSize =
-    16;
 static constexpr dart::compiler::target::word
-    InstructionsSection_UnalignedHeaderSize = 16;
+    InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word KernelProgramInfo_InstanceSize =
@@ -4027,7 +4019,7 @@
 static constexpr dart::compiler::target::word ParameterTypeCheck_InstanceSize =
     48;
 static constexpr dart::compiler::target::word PatchClass_InstanceSize = 48;
-static constexpr dart::compiler::target::word PcDescriptors_InstanceSize = 16;
+static constexpr dart::compiler::target::word PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word RedirectionData_InstanceSize = 32;
@@ -4083,6 +4075,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 12;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     AOT_NativeEntry_kNumCallWrapperArguments = 2;
@@ -4275,9 +4271,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 720;
+    AOT_Thread_active_exception_offset = 724;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 724;
+    AOT_Thread_active_stacktrace_offset = 728;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -4303,7 +4299,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 200;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    756;
+    760;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 96;
 static constexpr dart::compiler::target::word
@@ -4318,7 +4314,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 148;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    764;
+    768;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -4337,7 +4333,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 740;
+    AOT_Thread_execution_state_offset = 744;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -4357,7 +4353,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 728;
+    AOT_Thread_global_object_pool_offset = 732;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -4365,7 +4361,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 752;
+    AOT_Thread_exit_through_ffi_offset = 756;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
@@ -4405,11 +4401,11 @@
     112;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 736;
+    AOT_Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 744;
+    AOT_Thread_safepoint_state_offset = 748;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -4445,7 +4441,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    748;
+    752;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -4500,7 +4496,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
@@ -4511,10 +4507,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 88;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    8;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 12;
@@ -4543,13 +4536,10 @@
     AOT_GrowableObjectArray_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 8;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 8;
+    AOT_InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word
@@ -4581,8 +4571,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 20;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
@@ -4643,6 +4632,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 22;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
     10;
 static constexpr dart::compiler::target::word
@@ -4836,9 +4829,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1448;
+    AOT_Thread_active_exception_offset = 1456;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1456;
+    AOT_Thread_active_stacktrace_offset = 1464;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -4864,7 +4857,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1520;
+    1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
@@ -4879,7 +4872,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 280;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -4898,7 +4891,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1488;
+    AOT_Thread_execution_state_offset = 1496;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -4918,7 +4911,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1464;
+    AOT_Thread_global_object_pool_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -4926,7 +4919,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1512;
+    AOT_Thread_exit_through_ffi_offset = 1520;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
@@ -4967,11 +4960,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1480;
+    AOT_Thread_saved_shadow_call_stack_offset = 1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1496;
+    AOT_Thread_safepoint_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5007,7 +5000,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -5062,8 +5055,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, -1,   -1,   1392, 1400,
-        1408, 1416, 1424, -1,   1432, 1440, -1,   -1};
+        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
+        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
@@ -5074,10 +5067,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 152;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    16;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 24;
@@ -5106,14 +5096,10 @@
     AOT_GrowableObjectArray_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 16;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 16;
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -5145,8 +5131,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    16;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
@@ -5210,6 +5195,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 20;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
     10;
 static constexpr dart::compiler::target::word
@@ -5403,9 +5392,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -5431,7 +5420,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
@@ -5446,7 +5435,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 280;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1608;
+    1616;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -5465,7 +5454,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -5485,7 +5474,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -5493,7 +5482,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1584;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
@@ -5534,11 +5523,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -5574,7 +5563,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -5629,9 +5618,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440,
-        1448, 1456, 1464, 1472, -1,   -1,   -1,   -1,   1480, 1488, -1,
-        -1,   1496, 1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
+        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
+        -1,   1504, 1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
@@ -5642,10 +5631,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 152;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    16;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 24;
@@ -5674,14 +5660,10 @@
     AOT_GrowableObjectArray_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 16;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 16;
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -5713,8 +5695,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    16;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
@@ -5777,6 +5758,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 0;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 12;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 4;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 = 9;
 static constexpr dart::compiler::target::word
     AOT_NativeEntry_kNumCallWrapperArguments = 2;
@@ -5965,9 +5950,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 376;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 720;
+    AOT_Thread_active_exception_offset = 724;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 724;
+    AOT_Thread_active_stacktrace_offset = 728;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 128;
 static constexpr dart::compiler::target::word
@@ -5993,7 +5978,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 200;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    756;
+    760;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 96;
 static constexpr dart::compiler::target::word
@@ -6008,7 +5993,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 148;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    764;
+    768;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 48;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6027,7 +6012,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 252;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 740;
+    AOT_Thread_execution_state_offset = 744;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 256;
 static constexpr dart::compiler::target::word
@@ -6047,7 +6032,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 372;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 728;
+    AOT_Thread_global_object_pool_offset = 732;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 340;
 static constexpr dart::compiler::target::word
@@ -6055,7 +6040,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 140;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 752;
+    AOT_Thread_exit_through_ffi_offset = 756;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 44;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 68;
@@ -6095,11 +6080,11 @@
     112;
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 344;
-static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 732;
+static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 736;
+    AOT_Thread_saved_shadow_call_stack_offset = 740;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 744;
+    AOT_Thread_safepoint_state_offset = 748;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 244;
 static constexpr dart::compiler::target::word
@@ -6135,7 +6120,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 40;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    748;
+    752;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 8;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -6187,7 +6172,7 @@
     4, 12, 8, 16};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        688, 692, 696, 700, 704, -1, 708, -1, 712, 716, -1, -1, -1, -1, -1, -1};
+        692, 696, 700, 704, 708, -1, 712, -1, 716, 720, -1, -1, -1, -1, -1, -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 8;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 12;
@@ -6198,10 +6183,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 20;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 64;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    8;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 8;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 8;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 12;
@@ -6230,13 +6212,10 @@
     AOT_GrowableObjectArray_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 4;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 8;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 8;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 8;
+    AOT_InstructionsSection_UnalignedHeaderSize = 20;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 4;
 static constexpr dart::compiler::target::word
@@ -6268,8 +6247,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 20;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    8;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 8;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 12;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
@@ -6330,6 +6308,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 22;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
     10;
 static constexpr dart::compiler::target::word
@@ -6519,9 +6501,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1448;
+    AOT_Thread_active_exception_offset = 1456;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1456;
+    AOT_Thread_active_stacktrace_offset = 1464;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -6547,7 +6529,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1520;
+    1528;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
@@ -6562,7 +6544,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 280;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1536;
+    1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -6581,7 +6563,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1488;
+    AOT_Thread_execution_state_offset = 1496;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -6601,7 +6583,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1464;
+    AOT_Thread_global_object_pool_offset = 1472;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -6609,7 +6591,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1512;
+    AOT_Thread_exit_through_ffi_offset = 1520;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
@@ -6650,11 +6632,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1472;
+    1480;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1480;
+    AOT_Thread_saved_shadow_call_stack_offset = 1488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1496;
+    AOT_Thread_safepoint_state_offset = 1504;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -6690,7 +6672,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1504;
+    1512;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -6742,8 +6724,8 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, -1,   -1,   1392, 1400,
-        1408, 1416, 1424, -1,   1432, 1440, -1,   -1};
+        1368, 1376, 1384, 1392, -1,   -1,   1400, 1408,
+        1416, 1424, 1432, -1,   1440, 1448, -1,   -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
@@ -6754,10 +6736,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    16;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 24;
@@ -6786,14 +6765,10 @@
     AOT_GrowableObjectArray_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 16;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 16;
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -6825,8 +6800,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    16;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
@@ -6890,6 +6864,10 @@
     AOT_Instructions_kMonomorphicEntryOffsetAOT = 8;
 static constexpr dart::compiler::target::word
     AOT_Instructions_kPolymorphicEntryOffsetAOT = 20;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kBarePayloadAlignment = 4;
+static constexpr dart::compiler::target::word
+    AOT_Instructions_kNonBarePayloadAlignment = 8;
 static constexpr dart::compiler::target::word AOT_OldPage_kBytesPerCardLog2 =
     10;
 static constexpr dart::compiler::target::word
@@ -7079,9 +7057,9 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_AllocateArray_entry_point_offset = 736;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_exception_offset = 1520;
+    AOT_Thread_active_exception_offset = 1528;
 static constexpr dart::compiler::target::word
-    AOT_Thread_active_stacktrace_offset = 1528;
+    AOT_Thread_active_stacktrace_offset = 1536;
 static constexpr dart::compiler::target::word
     AOT_Thread_array_write_barrier_code_offset = 240;
 static constexpr dart::compiler::target::word
@@ -7107,7 +7085,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_allocate_object_slow_stub_offset = 384;
 static constexpr dart::compiler::target::word AOT_Thread_api_top_scope_offset =
-    1592;
+    1600;
 static constexpr dart::compiler::target::word
     AOT_Thread_async_stack_trace_offset = 192;
 static constexpr dart::compiler::target::word
@@ -7122,7 +7100,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_call_to_runtime_stub_offset = 280;
 static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
-    1608;
+    1616;
 static constexpr dart::compiler::target::word
     AOT_Thread_dispatch_table_array_offset = 96;
 static constexpr dart::compiler::target::word AOT_Thread_optimize_entry_offset =
@@ -7141,7 +7119,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_enter_safepoint_stub_offset = 488;
 static constexpr dart::compiler::target::word
-    AOT_Thread_execution_state_offset = 1560;
+    AOT_Thread_execution_state_offset = 1568;
 static constexpr dart::compiler::target::word
     AOT_Thread_exit_safepoint_stub_offset = 496;
 static constexpr dart::compiler::target::word
@@ -7161,7 +7139,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_float_zerow_address_offset = 728;
 static constexpr dart::compiler::target::word
-    AOT_Thread_global_object_pool_offset = 1536;
+    AOT_Thread_global_object_pool_offset = 1544;
 static constexpr dart::compiler::target::word
     AOT_Thread_interpret_call_entry_point_offset = 664;
 static constexpr dart::compiler::target::word
@@ -7169,7 +7147,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_invoke_dart_code_stub_offset = 264;
 static constexpr dart::compiler::target::word
-    AOT_Thread_exit_through_ffi_offset = 1584;
+    AOT_Thread_exit_through_ffi_offset = 1592;
 static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 88;
 static constexpr dart::compiler::target::word
     AOT_Thread_field_table_values_offset = 136;
@@ -7210,11 +7188,11 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_predefined_symbols_address_offset = 672;
 static constexpr dart::compiler::target::word AOT_Thread_resume_pc_offset =
-    1544;
+    1552;
 static constexpr dart::compiler::target::word
-    AOT_Thread_saved_shadow_call_stack_offset = 1552;
+    AOT_Thread_saved_shadow_call_stack_offset = 1560;
 static constexpr dart::compiler::target::word
-    AOT_Thread_safepoint_state_offset = 1568;
+    AOT_Thread_safepoint_state_offset = 1576;
 static constexpr dart::compiler::target::word
     AOT_Thread_slow_type_test_stub_offset = 472;
 static constexpr dart::compiler::target::word
@@ -7250,7 +7228,7 @@
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_mask_offset = 80;
 static constexpr dart::compiler::target::word AOT_Thread_callback_code_offset =
-    1576;
+    1584;
 static constexpr dart::compiler::target::word
     AOT_TimelineStream_enabled_offset = 16;
 static constexpr dart::compiler::target::word AOT_TwoByteString_data_offset =
@@ -7302,9 +7280,9 @@
     8, 24, 16, 32};
 static constexpr dart::compiler::target::word
     AOT_Thread_write_barrier_wrappers_thread_offset[] = {
-        1360, 1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440,
-        1448, 1456, 1464, 1472, -1,   -1,   -1,   -1,   1480, 1488, -1,
-        -1,   1496, 1504, 1512, -1,   -1,   -1,   -1,   -1,   -1};
+        1368, 1376, 1384, 1392, 1400, 1408, 1416, 1424, 1432, 1440, 1448,
+        1456, 1464, 1472, 1480, -1,   -1,   -1,   -1,   1488, 1496, -1,
+        -1,   1504, 1512, 1520, -1,   -1,   -1,   -1,   -1,   -1};
 static constexpr dart::compiler::target::word AOT_ApiError_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_Array_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Array_header_size = 24;
@@ -7315,10 +7293,7 @@
 static constexpr dart::compiler::target::word AOT_Closure_InstanceSize = 56;
 static constexpr dart::compiler::target::word AOT_ClosureData_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_Code_InstanceSize = 120;
-static constexpr dart::compiler::target::word AOT_CodeSourceMap_InstanceSize =
-    16;
-static constexpr dart::compiler::target::word
-    AOT_CompressedStackMaps_InstanceSize = 12;
+static constexpr dart::compiler::target::word AOT_CodeSourceMap_HeaderSize = 16;
 static constexpr dart::compiler::target::word
     AOT_CompressedStackMaps_HeaderSize = 12;
 static constexpr dart::compiler::target::word AOT_Context_InstanceSize = 24;
@@ -7347,14 +7322,10 @@
     AOT_GrowableObjectArray_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_ICData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Instance_InstanceSize = 8;
-static constexpr dart::compiler::target::word AOT_Instructions_InstanceSize =
-    12;
 static constexpr dart::compiler::target::word
     AOT_Instructions_UnalignedHeaderSize = 12;
 static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_InstanceSize = 16;
-static constexpr dart::compiler::target::word
-    AOT_InstructionsSection_UnalignedHeaderSize = 16;
+    AOT_InstructionsSection_UnalignedHeaderSize = 40;
 static constexpr dart::compiler::target::word AOT_Int32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Integer_InstanceSize = 8;
 static constexpr dart::compiler::target::word
@@ -7386,8 +7357,7 @@
 static constexpr dart::compiler::target::word
     AOT_ParameterTypeCheck_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_PatchClass_InstanceSize = 40;
-static constexpr dart::compiler::target::word AOT_PcDescriptors_InstanceSize =
-    16;
+static constexpr dart::compiler::target::word AOT_PcDescriptors_HeaderSize = 16;
 static constexpr dart::compiler::target::word AOT_Pointer_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_ReceivePort_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_RedirectionData_InstanceSize =
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 6f1dcb6..76eb49f 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -21,7 +21,11 @@
 // FIELD(Class, Name) Offset of a field within a class.
 // ARRAY(Class, Name) Offset of the first element and the size of the elements
 //     in an array of this class.
-// SIZEOF(Class, Name, What) Size of an object.
+// SIZEOF(Class, Name, What) Class::Name() is defined as sizeof(What).
+// PAYLOAD_SIZEOF(Class, Name, HeaderSize) Instance size for a payload object.
+//     Defines Class::Name(word payload_size) and uses Class::HeaderSize(),
+//     which should give the size of the header before the payload. Also
+//     defines Class::Name() (with no payload size argument) to be 0.
 // RANGE(Class, Name, Type, First, Last, Filter) An array of offsets generated
 //     by passing a value of the given Type in the range from First to Last to
 //     Class::Name() if Filter returns true for that value.
@@ -31,7 +35,11 @@
 // JIT_OFFSETS_LIST is for declarations that are only valid in JIT mode.
 // A declaration that is not valid in product mode can be wrapped with
 // NOT_IN_PRODUCT().
-#define COMMON_OFFSETS_LIST(FIELD, ARRAY, SIZEOF, RANGE, CONSTANT)             \
+//
+// TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis.
+
+#define COMMON_OFFSETS_LIST(FIELD, ARRAY, SIZEOF, PAYLOAD_SIZEOF, RANGE,       \
+                            CONSTANT)                                          \
   ARRAY(ObjectPool, element_offset)                                            \
   CONSTANT(Array, kMaxElements)                                                \
   CONSTANT(Array, kMaxNewSpaceElements)                                        \
@@ -39,6 +47,8 @@
   CONSTANT(Instructions, kPolymorphicEntryOffsetJIT)                           \
   CONSTANT(Instructions, kMonomorphicEntryOffsetAOT)                           \
   CONSTANT(Instructions, kPolymorphicEntryOffsetAOT)                           \
+  CONSTANT(Instructions, kBarePayloadAlignment)                                \
+  CONSTANT(Instructions, kNonBarePayloadAlignment)                             \
   CONSTANT(OldPage, kBytesPerCardLog2)                                         \
   CONSTANT(NativeEntry, kNumCallWrapperArguments)                              \
   CONSTANT(String, kMaxElements)                                               \
@@ -286,8 +296,7 @@
   SIZEOF(Closure, InstanceSize, ClosureLayout)                                 \
   SIZEOF(ClosureData, InstanceSize, ClosureDataLayout)                         \
   SIZEOF(Code, InstanceSize, CodeLayout)                                       \
-  SIZEOF(CodeSourceMap, InstanceSize, CodeSourceMapLayout)                     \
-  SIZEOF(CompressedStackMaps, InstanceSize, CompressedStackMapsLayout)         \
+  SIZEOF(CodeSourceMap, HeaderSize, CodeSourceMapLayout)                       \
   SIZEOF(CompressedStackMaps, HeaderSize, CompressedStackMapsLayout)           \
   SIZEOF(Context, InstanceSize, ContextLayout)                                 \
   SIZEOF(Context, header_size, ContextLayout)                                  \
@@ -307,9 +316,7 @@
   SIZEOF(GrowableObjectArray, InstanceSize, GrowableObjectArrayLayout)         \
   SIZEOF(ICData, InstanceSize, ICDataLayout)                                   \
   SIZEOF(Instance, InstanceSize, InstanceLayout)                               \
-  SIZEOF(Instructions, InstanceSize, InstructionsLayout)                       \
   SIZEOF(Instructions, UnalignedHeaderSize, InstructionsLayout)                \
-  SIZEOF(InstructionsSection, InstanceSize, InstructionsSectionLayout)         \
   SIZEOF(InstructionsSection, UnalignedHeaderSize, InstructionsSectionLayout)  \
   SIZEOF(Int32x4, InstanceSize, Int32x4Layout)                                 \
   SIZEOF(Integer, InstanceSize, IntegerLayout)                                 \
@@ -331,7 +338,7 @@
   SIZEOF(OneByteString, InstanceSize, OneByteStringLayout)                     \
   SIZEOF(ParameterTypeCheck, InstanceSize, ParameterTypeCheckLayout)           \
   SIZEOF(PatchClass, InstanceSize, PatchClassLayout)                           \
-  SIZEOF(PcDescriptors, InstanceSize, PcDescriptorsLayout)                     \
+  SIZEOF(PcDescriptors, HeaderSize, PcDescriptorsLayout)                       \
   SIZEOF(Pointer, InstanceSize, PointerLayout)                                 \
   SIZEOF(ReceivePort, InstanceSize, ReceivePortLayout)                         \
   SIZEOF(RedirectionData, InstanceSize, RedirectionDataLayout)                 \
@@ -360,9 +367,14 @@
   SIZEOF(UserTag, InstanceSize, UserTagLayout)                                 \
   SIZEOF(WeakProperty, InstanceSize, WeakPropertyLayout)                       \
   SIZEOF(WeakSerializationReference, InstanceSize,                             \
-         WeakSerializationReferenceLayout)
+         WeakSerializationReferenceLayout)                                     \
+  PAYLOAD_SIZEOF(CodeSourceMap, InstanceSize, HeaderSize)                      \
+  PAYLOAD_SIZEOF(CompressedStackMaps, InstanceSize, HeaderSize)                \
+  PAYLOAD_SIZEOF(InstructionsSection, InstanceSize, HeaderSize)                \
+  PAYLOAD_SIZEOF(PcDescriptors, InstanceSize, HeaderSize)
 
-#define JIT_OFFSETS_LIST(FIELD, ARRAY, SIZEOF, RANGE, CONSTANT)                \
+#define JIT_OFFSETS_LIST(FIELD, ARRAY, SIZEOF, PAYLOAD_SIZEOF, RANGE,          \
+                         CONSTANT)                                             \
   FIELD(Function, usage_counter_offset)                                        \
   FIELD(ICData, receivers_static_type_offset)
 
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 87f0a60..dfa4d4f 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -197,6 +197,13 @@
                                  Code::Handle(Code::null()));
 }
 
+#define TYPED_DATA_ALLOCATION_STUB(clazz)                                      \
+  void StubCodeCompiler::GenerateAllocate##clazz##Stub(Assembler* assembler) { \
+    GenerateAllocateTypedDataArrayStub(assembler, kTypedData##clazz##Cid);     \
+  }
+CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATION_STUB)
+#undef TYPED_DATA_ALLOCATION_STUB
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index 875ea17..d4a6fd0 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -142,6 +142,10 @@
   // InitLateFinalInstanceField stubs.
   static void GenerateInitLateInstanceFieldStub(Assembler* assembler,
                                                 bool is_final);
+
+  // Common function for generating Allocate<TypedData>Array stubs.
+  static void GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                 intptr_t cid);
 };
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 1669dc6..0969032 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -3904,6 +3904,131 @@
   GenerateInstantiateTypeArgumentsStub(assembler);
 }
 
+static int GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1:
+      return 0;
+    case 2:
+      return 1;
+    case 4:
+      return 2;
+    case 8:
+      return 3;
+    case 16:
+      return 4;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                          intptr_t cid) {
+  const intptr_t element_size = TypedDataElementSizeInBytes(cid);
+  const intptr_t max_len = TypedDataMaxNewSpaceElements(cid);
+  const intptr_t scale_shift = GetScaleFactor(element_size);
+
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kLengthReg == R4);
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kResultReg == R0);
+
+  Label call_runtime;
+  NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R2, cid));
+  NOT_IN_PRODUCT(__ MaybeTraceAllocation(R2, &call_runtime));
+  __ mov(R2, Operand(AllocateTypedDataArrayABI::kLengthReg));
+  /* Check that length is a positive Smi. */
+  /* R2: requested array length argument. */
+  __ tst(R2, Operand(kSmiTagMask));
+  __ b(&call_runtime, NE);
+  __ CompareImmediate(R2, 0);
+  __ b(&call_runtime, LT);
+  __ SmiUntag(R2);
+  /* Check for maximum allowed length. */
+  /* R2: untagged array length. */
+  __ CompareImmediate(R2, max_len);
+  __ b(&call_runtime, GT);
+  __ mov(R2, Operand(R2, LSL, scale_shift));
+  const intptr_t fixed_size_plus_alignment_padding =
+      target::TypedData::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
+  __ AddImmediate(R2, fixed_size_plus_alignment_padding);
+  __ bic(R2, R2, Operand(target::ObjectAlignment::kObjectAlignment - 1));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
+
+  /* R2: allocation size. */
+  __ adds(R1, R0, Operand(R2));
+  __ b(&call_runtime, CS); /* Fail on unsigned overflow. */
+
+  /* Check if the allocation fits into the remaining space. */
+  /* R0: potential new object start. */
+  /* R1: potential next object start. */
+  /* R2: allocation size. */
+  __ ldr(IP, Address(THR, target::Thread::end_offset()));
+  __ cmp(R1, Operand(IP));
+  __ b(&call_runtime, CS);
+
+  __ str(R1, Address(THR, target::Thread::top_offset()));
+  __ AddImmediate(R0, kHeapObjectTag);
+  /* Initialize the tags. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  /* R2: allocation size. */
+  {
+    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ mov(R3,
+           Operand(R2, LSL,
+                   target::ObjectLayout::kTagBitsSizeTagPos -
+                       target::ObjectAlignment::kObjectAlignmentLog2),
+           LS);
+    __ mov(R3, Operand(0), HI);
+
+    /* Get the class index and insert it into the tags. */
+    uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+    __ LoadImmediate(TMP, tags);
+    __ orr(R3, R3, Operand(TMP));
+    __ str(R3, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */
+  }
+  /* Set the length field. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  /* R2: allocation size. */
+  __ mov(R3,
+         Operand(AllocateTypedDataArrayABI::kLengthReg)); /* Array length. */
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::TypedDataBase::length_offset()), R3);
+  /* Initialize all array elements to 0. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  /* R2: allocation size. */
+  /* R3: iterator which initially points to the start of the variable */
+  /* R8, R9: zero. */
+  /* data area to be initialized. */
+  __ LoadImmediate(R8, 0);
+  __ mov(R9, Operand(R8));
+  __ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1);
+  __ StoreInternalPointer(
+      R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R3);
+  Label init_loop;
+  __ Bind(&init_loop);
+  __ AddImmediate(R3, 2 * target::kWordSize);
+  __ cmp(R3, Operand(R1));
+  __ strd(R8, R9, R3, -2 * target::kWordSize, LS);
+  __ b(&init_loop, CC);
+  __ str(R8, Address(R3, -2 * target::kWordSize), HI);
+
+  __ Ret();
+
+  __ Bind(&call_runtime);
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());            // Make room for the result.
+  __ PushImmediate(target::ToRawSmi(cid));         // Cid
+  __ Push(AllocateTypedDataArrayABI::kLengthReg);  // Array length
+  __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
+  __ Drop(2);  // Drop arguments.
+  __ Pop(AllocateTypedDataArrayABI::kResultReg);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 6ff81a8..84c1a04 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -49,16 +49,12 @@
   Label done;
   __ tbnz(&done, R0, target::ObjectAlignment::kNewObjectBitPosition);
 
-  if (preserve_registers) {
-    __ EnterCallRuntimeFrame(0);
-  } else {
-    __ ReserveAlignedFrameSpace(0);
-  }
-  // [R0] already contains first argument.
-  __ mov(R1, THR);
-  __ CallRuntime(kEnsureRememberedAndMarkingDeferredRuntimeEntry, 2);
-  if (preserve_registers) {
-    __ LeaveCallRuntimeFrame();
+  {
+    Assembler::CallRuntimeScope scope(
+        assembler, kEnsureRememberedAndMarkingDeferredRuntimeEntry,
+        /*frame_size=*/0, /*preserve_registers=*/preserve_registers);
+    __ mov(R1, THR);
+    scope.Call(/*argument_count=*/2);
   }
 
   __ Bind(&done);
@@ -295,7 +291,7 @@
 // Calls native code within a safepoint.
 //
 // On entry:
-//   R8: target to call
+//   R9: target to call
 //   Stack: set up for native call (SP), aligned, CSP < SP
 //
 // On exit:
@@ -306,29 +302,29 @@
   COMPILE_ASSERT((1 << R19) & kAbiPreservedCpuRegs);
 
   __ mov(R19, LR);
-  __ LoadImmediate(R9, target::Thread::exit_through_ffi());
-  __ TransitionGeneratedToNative(R8, FPREG, R9 /*volatile*/,
+  __ LoadImmediate(R10, target::Thread::exit_through_ffi());
+  __ TransitionGeneratedToNative(R9, FPREG, R10 /*volatile*/,
                                  /*enter_safepoint=*/true);
   __ mov(R25, CSP);
   __ mov(CSP, SP);
 
 #if defined(DEBUG)
   // Check CSP alignment.
-  __ andi(R10 /*volatile*/, SP,
+  __ andi(R11 /*volatile*/, SP,
           Immediate(~(OS::ActivationFrameAlignment() - 1)));
-  __ cmp(R10, Operand(SP));
+  __ cmp(R11, Operand(SP));
   Label done;
   __ b(&done, EQ);
   __ Breakpoint();
   __ Bind(&done);
 #endif
 
-  __ blr(R8);
+  __ blr(R9);
 
   __ mov(SP, CSP);
   __ mov(CSP, R25);
 
-  __ TransitionNativeToGenerated(R9, /*leave_safepoint=*/true);
+  __ TransitionNativeToGenerated(R10, /*leave_safepoint=*/true);
   __ ret(R19);
 }
 
@@ -342,8 +338,8 @@
 #else
   Label done;
 
-  // R8 is volatile and not used for passing any arguments.
-  COMPILE_ASSERT(!IsCalleeSavedRegister(R8) && !IsArgumentRegister(R8));
+  // R9 is volatile and not used for passing any arguments.
+  COMPILE_ASSERT(!IsCalleeSavedRegister(R9) && !IsArgumentRegister(R9));
   for (intptr_t i = 0;
        i < NativeCallbackTrampolines::NumCallbackTrampolinesPerPage(); ++i) {
     // We don't use LoadImmediate because we need the trampoline size to be
@@ -351,7 +347,7 @@
     //
     // Instead we paste the callback ID directly in the code load it
     // PC-relative.
-    __ ldr(R8, compiler::Address::PC(2 * Instr::kInstrSize));
+    __ ldr(R9, compiler::Address::PC(2 * Instr::kInstrSize));
     __ b(&done);
     __ Emit(next_callback_id + i);
   }
@@ -366,7 +362,7 @@
 
   // The load of the callback ID might have incorrect higher-order bits, since
   // we only emit a 32-bit callback ID.
-  __ uxtw(R8, R8);
+  __ uxtw(R9, R9);
 
   // Save THR (callee-saved) and LR on real real C stack (CSP). Keeps it
   // aligned.
@@ -378,8 +374,8 @@
   RegisterSet all_registers;
   all_registers.AddAllArgumentRegisters();
 
-  // The call below might clobber R8 (volatile, holding callback_id).
-  all_registers.Add(Location::RegisterLocation(R8));
+  // The call below might clobber R9 (volatile, holding callback_id).
+  all_registers.Add(Location::RegisterLocation(R9));
 
   // Load the thread, verify the callback ID and exit the safepoint.
   //
@@ -400,7 +396,7 @@
     // loaded anywhere, we use the same trick as before to ensure a predictable
     // instruction sequence.
     Label call;
-    __ mov(R0, R8);
+    __ mov(R0, R9);
     __ ldr(R1, compiler::Address::PC(2 * Instr::kInstrSize));
     __ b(&call);
 
@@ -419,29 +415,30 @@
     __ mov(CSP, SP);
   }
 
-  COMPILE_ASSERT(!IsCalleeSavedRegister(R9) && !IsArgumentRegister(R9));
+  COMPILE_ASSERT(!IsCalleeSavedRegister(R10) && !IsArgumentRegister(R10));
 
   // Load the code object.
-  __ LoadFromOffset(R9, THR, compiler::target::Thread::callback_code_offset());
-  __ LoadFieldFromOffset(R9, R9,
+  __ LoadFromOffset(R10, THR, compiler::target::Thread::callback_code_offset());
+  __ LoadFieldFromOffset(R10, R10,
                          compiler::target::GrowableObjectArray::data_offset());
-  __ ldr(R9, __ ElementAddressForRegIndex(
-                 /*external=*/false,
-                 /*array_cid=*/kArrayCid,
-                 /*index, smi-tagged=*/compiler::target::kWordSize * 2,
-                 /*index_unboxed=*/false,
-                 /*array=*/R9,
-                 /*index=*/R8,
-                 /*temp=*/TMP));
-  __ LoadFieldFromOffset(R9, R9, compiler::target::Code::entry_point_offset());
+  __ ldr(R10, __ ElementAddressForRegIndex(
+                  /*external=*/false,
+                  /*array_cid=*/kArrayCid,
+                  /*index, smi-tagged=*/compiler::target::kWordSize * 2,
+                  /*index_unboxed=*/false,
+                  /*array=*/R10,
+                  /*index=*/R9,
+                  /*temp=*/TMP));
+  __ LoadFieldFromOffset(R10, R10,
+                         compiler::target::Code::entry_point_offset());
 
-  // Clobbers all volatile registers, including the callback ID in R8.
+  // Clobbers all volatile registers, including the callback ID in R9.
   // Resets CSP and SP, important for EnterSafepoint below.
-  __ blr(R9);
+  __ blr(R10);
 
-  // EnterSafepoint clobbers TMP, TMP2 and R8 -- all volatile and not holding
+  // EnterSafepoint clobbers TMP, TMP2 and R9 -- all volatile and not holding
   // return values.
-  __ EnterSafepoint(/*scratch=*/R8);
+  __ EnterSafepoint(/*scratch=*/R9);
 
   // Pop LR and THR from the real stack (CSP).
   __ ldp(THR, LR, Address(CSP, 2 * target::kWordSize, Address::PairPostIndex));
@@ -1973,16 +1970,13 @@
 
   // Handle overflow: Call the runtime leaf function.
   __ Bind(&overflow);
-  // Setup frame, push callee-saved registers.
-
-  __ Push(CODE_REG);
-  __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * target::kWordSize);
-  __ mov(R0, THR);
-  __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
-  // Restore callee-saved registers, tear down frame.
-  __ LeaveCallRuntimeFrame();
-  __ Pop(CODE_REG);
+  {
+    Assembler::CallRuntimeScope scope(assembler,
+                                      kStoreBufferBlockProcessRuntimeEntry,
+                                      /*frame_size=*/0, stub_code);
+    __ mov(R0, THR);
+    scope.Call(/*argument_count=*/1);
+  }
   __ ret();
 
   __ Bind(&add_to_mark_stack);
@@ -2020,13 +2014,13 @@
   __ ret();
 
   __ Bind(&marking_overflow);
-  __ Push(CODE_REG);
-  __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * target::kWordSize);
-  __ mov(R0, THR);
-  __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
-  __ LeaveCallRuntimeFrame();
-  __ Pop(CODE_REG);
+  {
+    Assembler::CallRuntimeScope scope(assembler,
+                                      kMarkingStackBlockProcessRuntimeEntry,
+                                      /*frame_size=*/0, stub_code);
+    __ mov(R0, THR);
+    scope.Call(/*argument_count=*/1);
+  }
   __ ret();
 
   __ Bind(&lost_race);
@@ -2059,16 +2053,13 @@
 
     // Card table not yet allocated.
     __ Bind(&remember_card_slow);
-    __ Push(CODE_REG);
-    __ PushPair(R0, R1);
-    __ ldr(CODE_REG, stub_code);
-    __ mov(R0, R1);   // Arg0 = Object
-    __ mov(R1, R25);  // Arg1 = Slot
-    __ EnterCallRuntimeFrame(0);
-    __ CallRuntime(kRememberCardRuntimeEntry, 2);
-    __ LeaveCallRuntimeFrame();
-    __ PopPair(R0, R1);
-    __ Pop(CODE_REG);
+    {
+      Assembler::CallRuntimeScope scope(assembler, kRememberCardRuntimeEntry,
+                                        /*frame_size=*/0, stub_code);
+      __ mov(R0, R1);   // Arg0 = Object
+      __ mov(R1, R25);  // Arg1 = Slot
+      scope.Call(/*argument_count=*/2);
+    }
     __ ret();
   }
 }
@@ -4079,6 +4070,126 @@
   GenerateInstantiateTypeArgumentsStub(assembler);
 }
 
+static int GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1:
+      return 0;
+    case 2:
+      return 1;
+    case 4:
+      return 2;
+    case 8:
+      return 3;
+    case 16:
+      return 4;
+  }
+  UNREACHABLE();
+  return -1;
+}
+
+void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                          intptr_t cid) {
+  const intptr_t element_size = TypedDataElementSizeInBytes(cid);
+  const intptr_t max_len = TypedDataMaxNewSpaceElements(cid);
+  const intptr_t scale_shift = GetScaleFactor(element_size);
+
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kLengthReg == R4);
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kResultReg == R0);
+
+  Label call_runtime;
+  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, R2, &call_runtime));
+  __ mov(R2, AllocateTypedDataArrayABI::kLengthReg);
+  /* Check that length is a positive Smi. */
+  /* R2: requested array length argument. */
+  __ BranchIfNotSmi(R2, &call_runtime);
+  __ CompareRegisters(R2, ZR);
+  __ b(&call_runtime, LT);
+  __ SmiUntag(R2);
+  /* Check for maximum allowed length. */
+  /* R2: untagged array length. */
+  __ CompareImmediate(R2, max_len);
+  __ b(&call_runtime, GT);
+  __ LslImmediate(R2, R2, scale_shift);
+  const intptr_t fixed_size_plus_alignment_padding =
+      target::TypedData::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
+  __ AddImmediate(R2, fixed_size_plus_alignment_padding);
+  __ andi(R2, R2, Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
+
+  /* R2: allocation size. */
+  __ adds(R1, R0, Operand(R2));
+  __ b(&call_runtime, CS); /* Fail on unsigned overflow. */
+
+  /* Check if the allocation fits into the remaining space. */
+  /* R0: potential new object start. */
+  /* R1: potential next object start. */
+  /* R2: allocation size. */
+  __ ldr(R6, Address(THR, target::Thread::end_offset()));
+  __ cmp(R1, Operand(R6));
+  __ b(&call_runtime, CS);
+
+  /* Successfully allocated the object(s), now update top to point to */
+  /* next object start and initialize the object. */
+  __ str(R1, Address(THR, target::Thread::top_offset()));
+  __ AddImmediate(R0, kHeapObjectTag);
+  /* Initialize the tags. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  /* R2: allocation size. */
+  {
+    __ CompareImmediate(R2, target::ObjectLayout::kSizeTagMaxSizeTag);
+    __ LslImmediate(R2, R2,
+                    target::ObjectLayout::kTagBitsSizeTagPos -
+                        target::ObjectAlignment::kObjectAlignmentLog2);
+    __ csel(R2, ZR, R2, HI);
+
+    /* Get the class index and insert it into the tags. */
+    uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+    __ LoadImmediate(TMP, tags);
+    __ orr(R2, R2, Operand(TMP));
+    __ str(R2, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */
+  }
+  /* Set the length field. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  __ mov(R2, AllocateTypedDataArrayABI::kLengthReg); /* Array length. */
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::TypedDataBase::length_offset()), R2);
+  /* Initialize all array elements to 0. */
+  /* R0: new object start as a tagged pointer. */
+  /* R1: new object end address. */
+  /* R2: iterator which initially points to the start of the variable */
+  /* R3: scratch register. */
+  /* data area to be initialized. */
+  __ mov(R3, ZR);
+  __ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1);
+  __ StoreInternalPointer(
+      R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R2);
+  Label init_loop, done;
+  __ Bind(&init_loop);
+  __ cmp(R2, Operand(R1));
+  __ b(&done, CS);
+  __ str(R3, Address(R2, 0));
+  __ add(R2, R2, Operand(target::kWordSize));
+  __ b(&init_loop);
+  __ Bind(&done);
+
+  __ Ret();
+
+  __ Bind(&call_runtime);
+  __ EnterStubFrame();
+  __ Push(ZR);                                     // Result slot.
+  __ PushImmediate(target::ToRawSmi(cid));         // Cid
+  __ Push(AllocateTypedDataArrayABI::kLengthReg);  // Array length
+  __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
+  __ Drop(2);  // Drop arguments.
+  __ Pop(AllocateTypedDataArrayABI::kResultReg);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 9ce50a1..369f95b 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -3089,6 +3089,143 @@
   GenerateInstantiateTypeArgumentsStub(assembler);
 }
 
+static ScaleFactor GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1:
+      return TIMES_1;
+    case 2:
+      return TIMES_2;
+    case 4:
+      return TIMES_4;
+    case 8:
+      return TIMES_8;
+    case 16:
+      return TIMES_16;
+  }
+  UNREACHABLE();
+  return static_cast<ScaleFactor>(0);
+}
+
+void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                          intptr_t cid) {
+  const intptr_t element_size = TypedDataElementSizeInBytes(cid);
+  const intptr_t max_len = TypedDataMaxNewSpaceElements(cid);
+  ScaleFactor scale_factor = GetScaleFactor(element_size);
+
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kLengthReg == EAX);
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kResultReg == EAX);
+
+  // Save length argument for possible runtime call, as
+  // EAX is clobbered.
+  Label call_runtime;
+  __ pushl(AllocateTypedDataArrayABI::kLengthReg);
+
+  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, ECX, &call_runtime, false));
+  __ movl(EDI, AllocateTypedDataArrayABI::kLengthReg);
+  /* Check that length is a positive Smi. */
+  /* EDI: requested array length argument. */
+  __ testl(EDI, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &call_runtime);
+  __ cmpl(EDI, Immediate(0));
+  __ j(LESS, &call_runtime);
+  __ SmiUntag(EDI);
+  /* Check for maximum allowed length. */
+  /* EDI: untagged array length. */
+  __ cmpl(EDI, Immediate(max_len));
+  __ j(GREATER, &call_runtime);
+  /* Special case for scaling by 16. */
+  if (scale_factor == TIMES_16) {
+    /* double length of array. */
+    __ addl(EDI, EDI);
+    /* only scale by 8. */
+    scale_factor = TIMES_8;
+  }
+
+  const intptr_t fixed_size_plus_alignment_padding =
+      target::TypedData::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
+  __ leal(EDI, Address(EDI, scale_factor, fixed_size_plus_alignment_padding));
+  __ andl(EDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
+  __ movl(EAX, Address(THR, target::Thread::top_offset()));
+  __ movl(EBX, EAX);
+  /* EDI: allocation size. */
+  __ addl(EBX, EDI);
+  __ j(CARRY, &call_runtime);
+
+  /* Check if the allocation fits into the remaining space. */
+  /* EAX: potential new object start. */
+  /* EBX: potential next object start. */
+  /* EDI: allocation size. */
+  __ cmpl(EBX, Address(THR, target::Thread::end_offset()));
+  __ j(ABOVE_EQUAL, &call_runtime);
+
+  /* Successfully allocated the object(s), now update top to point to */
+  /* next object start and initialize the object. */
+  __ movl(Address(THR, target::Thread::top_offset()), EBX);
+  __ addl(EAX, Immediate(kHeapObjectTag));
+
+  /* Initialize the tags. */
+  /* EAX: new object start as a tagged pointer. */
+  /* EBX: new object end address. */
+  /* EDI: allocation size. */
+  {
+    Label size_tag_overflow, done;
+    __ cmpl(EDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
+    __ shll(EDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
+    __ jmp(&done, Assembler::kNearJump);
+    __ Bind(&size_tag_overflow);
+    __ movl(EDI, Immediate(0));
+    __ Bind(&done);
+    /* Get the class index and insert it into the tags. */
+    uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+    __ orl(EDI, Immediate(tags));
+    __ movl(FieldAddress(EAX, target::Object::tags_offset()), EDI); /* Tags. */
+  }
+
+  /* Set the length field. */
+  /* EAX: new object start as a tagged pointer. */
+  /* EBX: new object end address. */
+  __ popl(EDI); /* Array length. */
+  __ StoreIntoObjectNoBarrier(
+      EAX, FieldAddress(EAX, target::TypedDataBase::length_offset()), EDI);
+
+  /* Initialize all array elements to 0. */
+  /* EAX: new object start as a tagged pointer. */
+  /* EBX: new object end address. */
+  /* EDI: iterator which initially points to the start of the variable */
+  /* ECX: scratch register. */
+  /* data area to be initialized. */
+  __ xorl(ECX, ECX); /* Zero. */
+  __ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize()));
+  __ StoreInternalPointer(
+      EAX, FieldAddress(EAX, target::TypedDataBase::data_field_offset()), EDI);
+  Label done, init_loop;
+  __ Bind(&init_loop);
+  __ cmpl(EDI, EBX);
+  __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
+  __ movl(Address(EDI, 0), ECX);
+  __ addl(EDI, Immediate(target::kWordSize));
+  __ jmp(&init_loop, Assembler::kNearJump);
+  __ Bind(&done);
+
+  __ ret();
+
+  __ Bind(&call_runtime);
+  __ popl(EDI);  // Array length
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ pushl(Immediate(target::ToRawSmi(cid)));
+  __ pushl(EDI);  // Array length
+  __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
+  __ Drop(2);  // Drop arguments.
+  __ popl(AllocateTypedDataArrayABI::kResultReg);
+  __ LeaveStubFrame();
+  __ ret();
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index e7011d0..c5eeb8a 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -4007,6 +4007,143 @@
   GenerateInstantiateTypeArgumentsStub(assembler);
 }
 
+static ScaleFactor GetScaleFactor(intptr_t size) {
+  switch (size) {
+    case 1:
+      return TIMES_1;
+    case 2:
+      return TIMES_2;
+    case 4:
+      return TIMES_4;
+    case 8:
+      return TIMES_8;
+    case 16:
+      return TIMES_16;
+  }
+  UNREACHABLE();
+  return static_cast<ScaleFactor>(0);
+}
+
+void StubCodeCompiler::GenerateAllocateTypedDataArrayStub(Assembler* assembler,
+                                                          intptr_t cid) {
+  const intptr_t element_size = TypedDataElementSizeInBytes(cid);
+  const intptr_t max_len = TypedDataMaxNewSpaceElements(cid);
+  ScaleFactor scale_factor = GetScaleFactor(element_size);
+
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kLengthReg == RAX);
+  COMPILE_ASSERT(AllocateTypedDataArrayABI::kResultReg == RAX);
+
+  // Save length argument for possible runtime call, as
+  // RAX is clobbered.
+  Label call_runtime;
+  __ pushq(AllocateTypedDataArrayABI::kLengthReg);
+
+  NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, &call_runtime, false));
+  __ movq(RDI, AllocateTypedDataArrayABI::kLengthReg);
+  /* Check that length is a positive Smi. */
+  /* RDI: requested array length argument. */
+  __ testq(RDI, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &call_runtime);
+  __ cmpq(RDI, Immediate(0));
+  __ j(LESS, &call_runtime);
+  __ SmiUntag(RDI);
+  /* Check for maximum allowed length. */
+  /* RDI: untagged array length. */
+  __ cmpq(RDI, Immediate(max_len));
+  __ j(GREATER, &call_runtime);
+  /* Special case for scaling by 16. */
+  if (scale_factor == TIMES_16) {
+    /* double length of array. */
+    __ addq(RDI, RDI);
+    /* only scale by 8. */
+    scale_factor = TIMES_8;
+  }
+  const intptr_t fixed_size_plus_alignment_padding =
+      target::TypedData::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
+  __ leaq(RDI, Address(RDI, scale_factor, fixed_size_plus_alignment_padding));
+  __ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
+  __ movq(RAX, Address(THR, target::Thread::top_offset()));
+  __ movq(RCX, RAX);
+
+  /* RDI: allocation size. */
+  __ addq(RCX, RDI);
+  __ j(CARRY, &call_runtime);
+
+  /* Check if the allocation fits into the remaining space. */
+  /* RAX: potential new object start. */
+  /* RCX: potential next object start. */
+  /* RDI: allocation size. */
+  __ cmpq(RCX, Address(THR, target::Thread::end_offset()));
+  __ j(ABOVE_EQUAL, &call_runtime);
+
+  /* Successfully allocated the object(s), now update top to point to */
+  /* next object start and initialize the object. */
+  __ movq(Address(THR, target::Thread::top_offset()), RCX);
+  __ addq(RAX, Immediate(kHeapObjectTag));
+  /* Initialize the tags. */
+  /* RAX: new object start as a tagged pointer. */
+  /* RCX: new object end address. */
+  /* RDI: allocation size. */
+  /* R13: scratch register. */
+  {
+    Label size_tag_overflow, done;
+    __ cmpq(RDI, Immediate(target::ObjectLayout::kSizeTagMaxSizeTag));
+    __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
+    __ shlq(RDI, Immediate(target::ObjectLayout::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
+    __ jmp(&done, Assembler::kNearJump);
+
+    __ Bind(&size_tag_overflow);
+    __ LoadImmediate(RDI, Immediate(0));
+    __ Bind(&done);
+
+    /* Get the class index and insert it into the tags. */
+    uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+    __ orq(RDI, Immediate(tags));
+    __ movq(FieldAddress(RAX, target::Object::tags_offset()), RDI); /* Tags. */
+  }
+  /* Set the length field. */
+  /* RAX: new object start as a tagged pointer. */
+  /* RCX: new object end address. */
+  __ popq(RDI); /* Array length. */
+  __ StoreIntoObjectNoBarrier(
+      RAX, FieldAddress(RAX, target::TypedDataBase::length_offset()), RDI);
+  /* Initialize all array elements to 0. */
+  /* RAX: new object start as a tagged pointer. */
+  /* RCX: new object end address. */
+  /* RDI: iterator which initially points to the start of the variable */
+  /* RBX: scratch register. */
+  /* data area to be initialized. */
+  __ xorq(RBX, RBX); /* Zero. */
+  __ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize()));
+  __ StoreInternalPointer(
+      RAX, FieldAddress(RAX, target::TypedDataBase::data_field_offset()), RDI);
+  Label done, init_loop;
+  __ Bind(&init_loop);
+  __ cmpq(RDI, RCX);
+  __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
+  __ movq(Address(RDI, 0), RBX);
+  __ addq(RDI, Immediate(target::kWordSize));
+  __ jmp(&init_loop, Assembler::kNearJump);
+  __ Bind(&done);
+
+  __ ret();
+
+  __ Bind(&call_runtime);
+  __ popq(RDI);  // Array length
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());  // Make room for the result.
+  __ PushImmediate(Immediate(target::ToRawSmi(cid)));
+  __ pushq(RDI);  // Array length
+  __ CallRuntime(kAllocateTypedDataRuntimeEntry, 2);
+  __ Drop(2);  // Drop arguments.
+  __ popq(AllocateTypedDataArrayABI::kResultReg);
+  __ LeaveStubFrame();
+  __ ret();
+}
+
 }  // namespace compiler
 
 }  // namespace dart
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 2c62815..d7f79a7 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -285,11 +285,11 @@
 // Register aliases.
 const Register TMP = IP;            // Used as scratch register by assembler.
 const Register TMP2 = kNoRegister;  // There is no second assembler temporary.
-const Register PP = R5;     // Caches object pool pointer in generated code.
+const Register PP = R5;  // Caches object pool pointer in generated code.
 const Register DISPATCH_TABLE_REG = NOTFP;  // Dispatch table register.
-const Register SPREG = SP;  // Stack pointer register.
-const Register FPREG = FP;  // Frame pointer register.
-const Register LRREG = LR;  // Link register.
+const Register SPREG = SP;                  // Stack pointer register.
+const Register FPREG = FP;                  // Frame pointer register.
+const Register LRREG = LR;                  // Link register.
 const Register ARGS_DESC_REG = R4;
 const Register CODE_REG = R6;
 const Register THR = R10;  // Caches current thread in generated code.
@@ -394,6 +394,12 @@
   static const Register kTempReg = R1;
 };
 
+// ABI for Allocate<TypedData>ArrayStub.
+struct AllocateTypedDataArrayABI {
+  static const Register kLengthReg = R4;
+  static const Register kResultReg = R0;
+};
+
 // TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
 // of reusing the constants of the instantiation stubs ABI.
 
@@ -447,6 +453,7 @@
   static const intptr_t kArgumentRegisters = kAbiArgumentCpuRegs;
   static const Register ArgumentRegisters[];
   static const intptr_t kNumArgRegs = 4;
+  static const Register kPointerToReturnStructRegister = R0;
 
   static const intptr_t kFpuArgumentRegisters = 0;
 
@@ -492,6 +499,10 @@
   static constexpr Register kSecondNonArgumentRegister = R9;
   static constexpr Register kFirstCalleeSavedCpuReg = R4;
   static constexpr Register kStackPointerRegister = SPREG;
+
+  COMPILE_ASSERT(
+      ((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
+       (kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
 };
 
 #undef R
@@ -968,7 +979,7 @@
 float ReciprocalSqrtEstimate(float op);
 float ReciprocalSqrtStep(float op1, float op2);
 
-constexpr uword kBreakInstructionFiller = 0xE1200070;  // bkpt #0
+constexpr uword kBreakInstructionFiller = 0xE1200070;   // bkpt #0
 constexpr uword kDataMemoryBarrier = 0xf57ff050 | 0xb;  // dmb ish
 
 }  // namespace dart
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index 1c71baa..87dbb7f 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -226,6 +226,12 @@
   static const Register kTempReg = R1;
 };
 
+// ABI for Allocate<TypedData>ArrayStub.
+struct AllocateTypedDataArrayABI {
+  static const Register kLengthReg = R4;
+  static const Register kResultReg = R0;
+};
+
 // TODO(regis): Add ABIs for type testing stubs and is-type test stubs instead
 // of reusing the constants of the instantiation stubs ABI.
 
@@ -242,21 +248,22 @@
 // See "Procedure Call Standard for the ARM 64-bit Architecture", document
 // number "ARM IHI 0055B", May 22 2013.
 
+#define R(REG) (1 << REG)
+
 // C++ ABI call registers.
-const RegList kAbiArgumentCpuRegs = (1 << R0) | (1 << R1) | (1 << R2) |
-                                    (1 << R3) | (1 << R4) | (1 << R5) |
-                                    (1 << R6) | (1 << R7);
+const RegList kAbiArgumentCpuRegs =
+    R(R0) | R(R1) | R(R2) | R(R3) | R(R4) | R(R5) | R(R6) | R(R7);
 #if defined(TARGET_OS_FUCHSIA)
-const RegList kAbiPreservedCpuRegs =
-    (1 << R18) | (1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) |
-    (1 << R23) | (1 << R24) | (1 << R25) | (1 << R26) | (1 << R27) | (1 << R28);
+const RegList kAbiPreservedCpuRegs = R(R18) | R(R19) | R(R20) | R(R21) |
+                                     R(R22) | R(R23) | R(R24) | R(R25) |
+                                     R(R26) | R(R27) | R(R28);
 const Register kAbiFirstPreservedCpuReg = R18;
 const Register kAbiLastPreservedCpuReg = R28;
 const int kAbiPreservedCpuRegCount = 11;
 #else
-const RegList kAbiPreservedCpuRegs =
-    (1 << R19) | (1 << R20) | (1 << R21) | (1 << R22) | (1 << R23) |
-    (1 << R24) | (1 << R25) | (1 << R26) | (1 << R27) | (1 << R28);
+const RegList kAbiPreservedCpuRegs = R(R19) | R(R20) | R(R21) | R(R22) |
+                                     R(R23) | R(R24) | R(R25) | R(R26) |
+                                     R(R27) | R(R28);
 const Register kAbiFirstPreservedCpuReg = R19;
 const Register kAbiLastPreservedCpuReg = R28;
 const int kAbiPreservedCpuRegCount = 10;
@@ -265,11 +272,11 @@
 const VRegister kAbiLastPreservedFpuReg = V15;
 const int kAbiPreservedFpuRegCount = 8;
 
-const intptr_t kReservedCpuRegisters =
-    (1 << SPREG) |  // Dart SP
-    (1 << FPREG) | (1 << TMP) | (1 << TMP2) | (1 << PP) | (1 << THR) |
-    (1 << LR) | (1 << BARRIER_MASK) | (1 << NULL_REG) | (1 << R31) |  // C++ SP
-    (1 << R18) | (1 << DISPATCH_TABLE_REG);
+const intptr_t kReservedCpuRegisters = R(SPREG) |  // Dart SP
+                                       R(FPREG) | R(TMP) | R(TMP2) | R(PP) |
+                                       R(THR) | R(LR) | R(BARRIER_MASK) |
+                                       R(NULL_REG) | R(R31) |  // C++ SP
+                                       R(R18) | R(DISPATCH_TABLE_REG);
 constexpr intptr_t kNumberOfReservedCpuRegisters = 12;
 // CPU registers available to Dart allocator.
 const RegList kDartAvailableCpuRegs =
@@ -284,15 +291,27 @@
 const int kDartVolatileCpuRegCount = 15;
 const int kDartVolatileFpuRegCount = 24;
 
-constexpr int kStoreBufferWrapperSize = 32;
+// Two callee save scratch registers used by leaf runtime call sequence.
+const Register kCallLeafRuntimeCalleeSaveScratch1 = R23;
+const Register kCallLeafRuntimeCalleeSaveScratch2 = R25;
+static_assert((R(kCallLeafRuntimeCalleeSaveScratch1) & kAbiPreservedCpuRegs) !=
+                  0,
+              "Need callee save scratch register for leaf runtime calls.");
+static_assert((R(kCallLeafRuntimeCalleeSaveScratch2) & kAbiPreservedCpuRegs) !=
+                  0,
+              "Need callee save scratch register for leaf runtime calls.");
 
-#define R(REG) (1 << REG)
+constexpr int kStoreBufferWrapperSize = 32;
 
 class CallingConventions {
  public:
   static const intptr_t kArgumentRegisters = kAbiArgumentCpuRegs;
   static const Register ArgumentRegisters[];
   static const intptr_t kNumArgRegs = 8;
+  // The native ABI uses R8 to pass the pointer to the memory preallocated for
+  // struct return values. Arm64 is the only ABI in which this pointer is _not_
+  // in ArgumentRegisters[0] or on the stack.
+  static const Register kPointerToReturnStructRegister = R8;
 
   static const FpuRegister FpuArgumentRegisters[];
   static const intptr_t kFpuArgumentRegisters =
@@ -335,9 +354,13 @@
   static constexpr FpuRegister kReturnFpuReg = V0;
 
   static constexpr Register kFirstCalleeSavedCpuReg = kAbiFirstPreservedCpuReg;
-  static constexpr Register kFirstNonArgumentRegister = R8;
-  static constexpr Register kSecondNonArgumentRegister = R9;
+  static constexpr Register kFirstNonArgumentRegister = R9;
+  static constexpr Register kSecondNonArgumentRegister = R10;
   static constexpr Register kStackPointerRegister = SPREG;
+
+  COMPILE_ASSERT(
+      ((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
+       (kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
 };
 
 #undef R
diff --git a/runtime/vm/constants_ia32.h b/runtime/vm/constants_ia32.h
index ff82b2f..02ac81d 100644
--- a/runtime/vm/constants_ia32.h
+++ b/runtime/vm/constants_ia32.h
@@ -158,6 +158,12 @@
   static const Register kIndexReg = EBX;
 };
 
+// ABI for Allocate<TypedData>ArrayStub.
+struct AllocateTypedDataArrayABI {
+  static const Register kLengthReg = EAX;
+  static const Register kResultReg = EAX;
+};
+
 typedef uint32_t RegList;
 const RegList kAllCpuRegistersList = 0xFF;
 
@@ -209,6 +215,7 @@
   static const intptr_t kArgumentRegisters = 0;
   static const intptr_t kFpuArgumentRegisters = 0;
   static const intptr_t kNumArgRegs = 0;
+  static const Register kPointerToReturnStructRegister = kNoRegister;
 
   static const XmmRegister FpuArgumentRegisters[];
   static const intptr_t kXmmArgumentRegisters = 0;
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 218823e..b74b2b6 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -207,6 +207,12 @@
   static const Register kTempReg = RBX;
 };
 
+// ABI for Allocate<TypedData>ArrayStub.
+struct AllocateTypedDataArrayABI {
+  static const Register kLengthReg = RAX;
+  static const Register kResultReg = RAX;
+};
+
 // Registers used inside the implementation of type testing stubs.
 struct TTSInternalRegs {
   static const Register kInstanceTypeArgumentsReg = RSI;
@@ -265,6 +271,7 @@
   static const intptr_t kFpuArgumentRegisters =
       R(XMM0) | R(XMM1) | R(XMM2) | R(XMM3);
   static const intptr_t kNumFpuArgRegs = 4;
+  static const intptr_t kPointerToReturnStructRegister = kArg1Reg;
 
   // can ArgumentRegisters[i] and XmmArgumentRegisters[i] both be used at the
   // same time? (Windows no, rest yes)
@@ -324,6 +331,7 @@
                                              R(kArg3Reg) | R(kArg4Reg) |
                                              R(kArg5Reg) | R(kArg6Reg);
   static const intptr_t kNumArgRegs = 6;
+  static const Register kPointerToReturnStructRegister = kArg1Reg;
 
   static const XmmRegister FpuArgumentRegisters[];
   static const intptr_t kFpuArgumentRegisters = R(XMM0) | R(XMM1) | R(XMM2) |
@@ -388,9 +396,9 @@
 
   COMPILE_ASSERT(((R(kFirstCalleeSavedCpuReg)) & kCalleeSaveCpuRegisters) != 0);
 
-  COMPILE_ASSERT(((R(kFirstNonArgumentRegister) |
-                   R(kSecondNonArgumentRegister)) &
-                  kArgumentRegisters) == 0);
+  COMPILE_ASSERT(
+      ((R(kFirstNonArgumentRegister) | R(kSecondNonArgumentRegister)) &
+       (kArgumentRegisters | R(kPointerToReturnStructRegister))) == 0);
 };
 
 #undef R
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 60a36ec..dac8c18 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -69,6 +69,7 @@
 Dart_FileWriteCallback Dart::file_write_callback_ = NULL;
 Dart_FileCloseCallback Dart::file_close_callback_ = NULL;
 Dart_EntropySource Dart::entropy_source_callback_ = NULL;
+Dart_GCEventCallback Dart::gc_event_callback_ = nullptr;
 
 // Structure for managing read-only global handles allocation used for
 // creating global read-only handles that are pre created and initialized
@@ -106,6 +107,9 @@
     ok = false;                                                                \
   }
 
+// No consistency checks needed for this construct.
+#define CHECK_PAYLOAD_SIZEOF(Class, Name, HeaderSize)
+
 #if defined(DART_PRECOMPILED_RUNTIME)
 #define CHECK_FIELD(Class, Name)                                               \
   CHECK_OFFSET(Class::Name(), AOT_##Class##_##Name);
@@ -143,11 +147,12 @@
 #define CHECK_CONSTANT(Class, Name) CHECK_OFFSET(Class::Name, Class##_##Name);
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 
-  COMMON_OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF, CHECK_RANGE,
-                      CHECK_CONSTANT)
+  COMMON_OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF,
+                      CHECK_PAYLOAD_SIZEOF, CHECK_RANGE, CHECK_CONSTANT)
 
-  NOT_IN_PRECOMPILED_RUNTIME(JIT_OFFSETS_LIST(
-      CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF, CHECK_RANGE, CHECK_CONSTANT))
+  NOT_IN_PRECOMPILED_RUNTIME(
+      JIT_OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_SIZEOF,
+                       CHECK_PAYLOAD_SIZEOF, CHECK_RANGE, CHECK_CONSTANT))
 
   if (!ok) {
     FATAL(
@@ -161,6 +166,7 @@
 #undef CHECK_RANGE
 #undef CHECK_CONSTANT
 #undef CHECK_OFFSET
+#undef CHECK_PAYLOAD_SIZEOF
 #endif  // !defined(IS_SIMARM_X64)
 }
 
@@ -186,11 +192,6 @@
     return Utils::StrDup("VM already initialized or flags not initialized.");
   }
 
-  if (FLAG_causal_async_stacks && FLAG_lazy_async_stacks) {
-    return Utils::StrDup(
-        "To use --lazy-async-stacks, please disable --causal-async-stacks!");
-  }
-
   const Snapshot* snapshot = nullptr;
   if (vm_isolate_snapshot != nullptr) {
     snapshot = Snapshot::SetupFromBuffer(vm_isolate_snapshot);
@@ -210,6 +211,10 @@
       return error;
     }
   }
+  if (FLAG_causal_async_stacks && FLAG_lazy_async_stacks) {
+    return Utils::StrDup(
+        "To use --lazy-async-stacks, please disable --causal-async-stacks!");
+  }
 
   FrameLayout::Init();
 
@@ -777,12 +782,12 @@
   //   when generating the snapshot.
   ASSERT(FLAG_sound_null_safety == kNullSafetyOptionUnspecified);
 
-  // If snapshot is an appJIT/AOT snapshot we will figure out the mode by
+  // If snapshot is not a core snapshot we will figure out the mode by
   // sniffing the feature string in the snapshot.
   if (snapshot_data != nullptr) {
     // Read the snapshot and check for null safety option.
     const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_data);
-    if (Snapshot::IncludesCode(snapshot->kind())) {
+    if (!Snapshot::IsAgnosticToNullSafety(snapshot->kind())) {
       return SnapshotHeaderReader::NullSafetyFromSnapshot(snapshot);
     }
   }
@@ -1029,7 +1034,9 @@
 #else
 #error What architecture?
 #endif
+  }
 
+  if (!Snapshot::IsAgnosticToNullSafety(kind)) {
     if (isolate != NULL) {
       if (isolate->null_safety()) {
         buffer.AddString(" null-safety");
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index 78f7547..27ad70d 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -6,6 +6,7 @@
 #define RUNTIME_VM_DART_H_
 
 #include "include/dart_api.h"
+#include "include/dart_tools_api.h"
 #include "vm/allocation.h"
 #include "vm/snapshot.h"
 
@@ -140,6 +141,11 @@
     return entropy_source_callback_;
   }
 
+  static void set_gc_event_callback(Dart_GCEventCallback gc_event) {
+    gc_event_callback_ = gc_event;
+  }
+  static Dart_GCEventCallback gc_event_callback() { return gc_event_callback_; }
+
  private:
   static constexpr const char* kVmIsolateName = "vm-isolate";
 
@@ -158,6 +164,7 @@
   static Dart_FileWriteCallback file_write_callback_;
   static Dart_FileCloseCallback file_close_callback_;
   static Dart_EntropySource entropy_source_callback_;
+  static Dart_GCEventCallback gc_event_callback_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 1440eaa..6fdb197 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1415,6 +1415,8 @@
     BackgroundCompiler::Stop(isolate);
     isolate->heap()->WaitForMarkerTasks(thread);
     isolate->heap()->WaitForSweeperTasks(thread);
+    SafepointOperationScope safepoint_operation(thread);
+    isolate->group()->ReleaseStoreBuffers();
     RELEASE_ASSERT(isolate->heap()->old_space()->tasks() == 0);
   }
 
@@ -1928,29 +1930,20 @@
   Thread::ExitIsolate();
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
-static uint8_t* ApiReallocate(uint8_t* ptr,
-                              intptr_t old_size,
-                              intptr_t new_size) {
-  return Api::TopScope(Thread::Current())
-      ->zone()
-      ->Realloc<uint8_t>(ptr, old_size, new_size);
-}
-#endif
-
 DART_EXPORT Dart_Handle
 Dart_CreateSnapshot(uint8_t** vm_snapshot_data_buffer,
                     intptr_t* vm_snapshot_data_size,
                     uint8_t** isolate_snapshot_data_buffer,
-                    intptr_t* isolate_snapshot_data_size) {
+                    intptr_t* isolate_snapshot_data_size,
+                    bool is_core) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   return Api::NewError("Cannot create snapshots on an AOT runtime.");
 #else
   DARTSCOPE(Thread::Current());
   API_TIMELINE_DURATION(T);
   Isolate* I = T->isolate();
-  if (vm_snapshot_data_buffer != NULL && vm_snapshot_data_size == NULL) {
-    RETURN_NULL_ERROR(vm_snapshot_data_size);
+  if (vm_snapshot_data_buffer != nullptr) {
+    CHECK_NULL(vm_snapshot_data_size);
   }
   CHECK_NULL(isolate_snapshot_data_buffer);
   CHECK_NULL(isolate_snapshot_data_size);
@@ -1970,16 +1963,21 @@
   }
 #endif  // #if defined(DEBUG)
 
-  Symbols::Compact();
-
-  FullSnapshotWriter writer(Snapshot::kFull, vm_snapshot_data_buffer,
-                            isolate_snapshot_data_buffer, ApiReallocate,
-                            NULL /* vm_image_writer */,
-                            NULL /* isolate_image_writer */);
+  ZoneWriteStream vm_snapshot_data(Api::TopScope(T)->zone(),
+                                   FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
+                                        FullSnapshotWriter::kInitialSize);
+  const Snapshot::Kind snapshot_kind =
+      is_core ? Snapshot::kFullCore : Snapshot::kFull;
+  FullSnapshotWriter writer(
+      snapshot_kind, &vm_snapshot_data, &isolate_snapshot_data,
+      nullptr /* vm_image_writer */, nullptr /* isolate_image_writer */);
   writer.WriteFullSnapshot();
-  if (vm_snapshot_data_buffer != NULL) {
+  if (vm_snapshot_data_buffer != nullptr) {
+    *vm_snapshot_data_buffer = vm_snapshot_data.buffer();
     *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
   }
+  *isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
   *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
   return Api::Success();
 #endif
@@ -2554,7 +2552,7 @@
   }
   const AbstractType& type =
       AbstractType::Handle(Instance::Cast(obj).GetType(Heap::kNew));
-  return Api::NewHandle(T, type.Canonicalize());
+  return Api::NewHandle(T, type.Canonicalize(T, nullptr));
 }
 
 DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
@@ -4451,7 +4449,7 @@
       ASSERT(redirect_type.IsInstantiated(kFunctions));
       redirect_type ^= redirect_type.InstantiateFrom(
           type_arguments, Object::null_type_arguments(), kNoneFree, Heap::kNew);
-      redirect_type ^= redirect_type.Canonicalize();
+      redirect_type ^= redirect_type.Canonicalize(T, nullptr);
     }
 
     type_obj = redirect_type.raw();
@@ -6380,7 +6378,7 @@
 }
 
 DART_EXPORT void Dart_SetGCEventCallback(Dart_GCEventCallback callback) {
-  Isolate::Current()->heap()->SetGCEventCallback(callback);
+  Dart::set_gc_event_callback(callback);
 }
 
 DART_EXPORT char* Dart_SetFileModifiedCallback(
@@ -6546,12 +6544,13 @@
   CHECK_NULL(buffer);
   CHECK_NULL(buffer_length);
 
-  WriteStream stream(buffer, ApiReallocate, MB);
+  ZoneWriteStream stream(Api::TopScope(thread)->zone(), MB);
   TypeFeedbackSaver saver(&stream);
   saver.WriteHeader();
   saver.SaveClasses();
   saver.SaveFields();
   ProgramVisitor::WalkProgram(thread->zone(), thread->isolate(), &saver);
+  *buffer = stream.buffer();
   *buffer_length = stream.bytes_written();
 
   return Api::Success();
@@ -6648,6 +6647,7 @@
 
 // Used for StreamingWriteStream/BlobImageWriter sizes for ELF and blobs.
 #if !defined(TARGET_ARCH_IA32) && defined(DART_PRECOMPILER)
+static const intptr_t kAssemblyInitialSize = 512 * KB;
 static const intptr_t kInitialSize = 2 * MB;
 static const intptr_t kInitialDebugSize = 1 * MB;
 
@@ -6665,10 +6665,11 @@
   NOT_IN_PRODUCT(TimelineBeginEndScope tbes2(T, Timeline::GetIsolateStream(),
                                              "WriteAppAOTSnapshot"));
 
-  uint8_t* vm_snapshot_data_buffer = nullptr;
-  uint8_t* vm_snapshot_instructions_buffer = nullptr;
-  uint8_t* isolate_snapshot_data_buffer = nullptr;
-  uint8_t* isolate_snapshot_instructions_buffer = nullptr;
+  ZoneWriteStream vm_snapshot_data(T->zone(), FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream vm_snapshot_instructions(T->zone(), kInitialSize);
+  ZoneWriteStream isolate_snapshot_data(T->zone(),
+                                        FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream isolate_snapshot_instructions(T->zone(), kInitialSize);
 
   const bool generate_debug = debug_callback_data != nullptr;
 
@@ -6685,15 +6686,12 @@
                                      strip ? new (Z) Dwarf(Z) : dwarf)
                        : nullptr;
 
-    BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
-                                    ApiReallocate, kInitialSize, debug_elf,
-                                    elf);
-    BlobImageWriter isolate_image_writer(
-        T, &isolate_snapshot_instructions_buffer, ApiReallocate, kInitialSize,
-        debug_elf, elf);
-    FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
-                              &isolate_snapshot_data_buffer, ApiReallocate,
-                              &vm_image_writer, &isolate_image_writer);
+    BlobImageWriter image_writer(T, &vm_snapshot_instructions,
+                                 &isolate_snapshot_instructions, debug_elf,
+                                 elf);
+    FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data,
+                              &isolate_snapshot_data, &image_writer,
+                              &image_writer);
 
     if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
       writer.WriteFullSnapshot(units);
@@ -6706,6 +6704,8 @@
       debug_elf->Finalize();
     }
   } else {
+    StreamingWriteStream assembly_stream(kAssemblyInitialSize, callback,
+                                         callback_data);
     StreamingWriteStream debug_stream(generate_debug ? kInitialDebugSize : 0,
                                       callback, debug_callback_data);
 
@@ -6714,12 +6714,10 @@
                                        new (Z) Dwarf(Z))
                          : nullptr;
 
-    AssemblyImageWriter image_writer(T, callback, callback_data, strip, elf);
-    uint8_t* vm_snapshot_data_buffer = NULL;
-    uint8_t* isolate_snapshot_data_buffer = NULL;
-    FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
-                              &isolate_snapshot_data_buffer, ApiReallocate,
-                              &image_writer, &image_writer);
+    AssemblyImageWriter image_writer(T, &assembly_stream, strip, elf);
+    FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data,
+                              &isolate_snapshot_data, &image_writer,
+                              &image_writer);
 
     if (unit == nullptr || unit->id() == LoadingUnit::kRootId) {
       writer.WriteFullSnapshot(units);
@@ -6849,10 +6847,12 @@
   CHECK_NULL(callback);
 
   TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
-  AssemblyImageWriter image_writer(T, callback, callback_data);
-  uint8_t* vm_snapshot_data_buffer = nullptr;
-  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
-                            nullptr, ApiReallocate, &image_writer, nullptr);
+  StreamingWriteStream assembly_stream(kAssemblyInitialSize, callback,
+                                       callback_data);
+  AssemblyImageWriter image_writer(T, &assembly_stream);
+  ZoneWriteStream vm_snapshot_data(T->zone(), FullSnapshotWriter::kInitialSize);
+  FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data, nullptr,
+                            &image_writer, nullptr);
 
   writer.WriteFullSnapshot();
 
@@ -7021,24 +7021,34 @@
   DropRegExpMatchCode(Z);
 
   ProgramVisitor::Dedup(T);
-  Symbols::Compact();
 
   TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
-  BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
-                                  ApiReallocate, 2 * MB /* initial_size */);
-  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       2 * MB /* initial_size */);
-  FullSnapshotWriter writer(Snapshot::kFullJIT, vm_snapshot_data_buffer,
-                            isolate_snapshot_data_buffer, ApiReallocate,
-                            &vm_image_writer, &isolate_image_writer);
+  ZoneWriteStream vm_snapshot_data(Api::TopScope(T)->zone(),
+                                   FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream vm_snapshot_instructions(Api::TopScope(T)->zone(),
+                                           FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
+                                        FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream isolate_snapshot_instructions(
+      Api::TopScope(T)->zone(), FullSnapshotWriter::kInitialSize);
+
+  BlobImageWriter image_writer(T, &vm_snapshot_instructions,
+                               &isolate_snapshot_instructions);
+  FullSnapshotWriter writer(Snapshot::kFullJIT, &vm_snapshot_data,
+                            &isolate_snapshot_data, &image_writer,
+                            &image_writer);
   writer.WriteFullSnapshot();
 
-  *vm_snapshot_data_size = writer.VmIsolateSnapshotSize();
-  *vm_snapshot_instructions_size = vm_image_writer.InstructionsBlobSize();
-  *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
+  *vm_snapshot_data_buffer = vm_snapshot_data.buffer();
+  *vm_snapshot_data_size = vm_snapshot_data.bytes_written();
+  *vm_snapshot_instructions_buffer = vm_snapshot_instructions.buffer();
+  *vm_snapshot_instructions_size = vm_snapshot_instructions.bytes_written();
+  *isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
+  *isolate_snapshot_data_size = isolate_snapshot_data.bytes_written();
+  *isolate_snapshot_instructions_buffer =
+      isolate_snapshot_instructions.buffer();
   *isolate_snapshot_instructions_size =
-      isolate_image_writer.InstructionsBlobSize();
+      isolate_snapshot_instructions.bytes_written();
 
   return Api::Success();
 #endif
@@ -7097,7 +7107,6 @@
   DropRegExpMatchCode(Z);
 
   ProgramVisitor::Dedup(T);
-  Symbols::Compact();
 
   if (FLAG_dump_tables) {
     Symbols::DumpTable(I);
@@ -7107,17 +7116,22 @@
   }
 
   TIMELINE_DURATION(T, Isolate, "WriteAppJITSnapshot");
-  BlobImageWriter isolate_image_writer(T, isolate_snapshot_instructions_buffer,
-                                       ApiReallocate,
-                                       2 * MB /* initial_size */);
-  FullSnapshotWriter writer(Snapshot::kFullJIT, NULL,
-                            isolate_snapshot_data_buffer, ApiReallocate, NULL,
-                            &isolate_image_writer);
+  ZoneWriteStream isolate_snapshot_data(Api::TopScope(T)->zone(),
+                                        FullSnapshotWriter::kInitialSize);
+  ZoneWriteStream isolate_snapshot_instructions(
+      Api::TopScope(T)->zone(), FullSnapshotWriter::kInitialSize);
+  BlobImageWriter image_writer(T, /*vm_instructions=*/nullptr,
+                               &isolate_snapshot_instructions);
+  FullSnapshotWriter writer(Snapshot::kFullJIT, nullptr, &isolate_snapshot_data,
+                            nullptr, &image_writer);
   writer.WriteFullSnapshot();
 
-  *isolate_snapshot_data_size = writer.IsolateSnapshotSize();
+  *isolate_snapshot_data_buffer = isolate_snapshot_data.buffer();
+  *isolate_snapshot_data_size = isolate_snapshot_data.bytes_written();
+  *isolate_snapshot_instructions_buffer =
+      isolate_snapshot_instructions.buffer();
   *isolate_snapshot_instructions_size =
-      isolate_image_writer.InstructionsBlobSize();
+      isolate_snapshot_instructions.bytes_written();
 
   return Api::Success();
 #endif
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 08b0c79..0046562 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3133,10 +3133,6 @@
 }
 
 TEST_CASE(DartAPI_WeakPersistentHandle) {
-  // GCs due to allocations or weak handle creation can cause early promotion
-  // and interfer with the scenario this test is verifying.
-  NoHeapGrowthControlScope force_growth;
-
   Dart_Handle local_new_ref = Dart_Null();
   weak_new_ref = Dart_NewWeakPersistentHandle(local_new_ref, NULL, 0,
                                               WeakPersistentHandleCallback);
@@ -3148,25 +3144,32 @@
   {
     Dart_EnterScope();
 
-    // Create an object in new space.
-    Dart_Handle new_ref = AllocateNewString("new string");
-    EXPECT_VALID(new_ref);
+    Dart_Handle new_ref, old_ref;
+    {
+      // GCs due to allocations or weak handle creation can cause early
+      // promotion and interfere with the scenario this test is verifying.
+      NoHeapGrowthControlScope force_growth;
 
-    // Create an object in old space.
-    Dart_Handle old_ref = AllocateOldString("old string");
-    EXPECT_VALID(old_ref);
+      // Create an object in new space.
+      new_ref = AllocateNewString("new string");
+      EXPECT_VALID(new_ref);
 
-    // Create a weak ref to the new space object.
-    weak_new_ref = Dart_NewWeakPersistentHandle(new_ref, NULL, 0,
-                                                WeakPersistentHandleCallback);
-    EXPECT_VALID(AsHandle(weak_new_ref));
-    EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
+      // Create an object in old space.
+      old_ref = AllocateOldString("old string");
+      EXPECT_VALID(old_ref);
 
-    // Create a weak ref to the old space object.
-    weak_old_ref = Dart_NewWeakPersistentHandle(old_ref, NULL, 0,
-                                                WeakPersistentHandleCallback);
-    EXPECT_VALID(AsHandle(weak_old_ref));
-    EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
+      // Create a weak ref to the new space object.
+      weak_new_ref = Dart_NewWeakPersistentHandle(new_ref, NULL, 0,
+                                                  WeakPersistentHandleCallback);
+      EXPECT_VALID(AsHandle(weak_new_ref));
+      EXPECT(!Dart_IsNull(AsHandle(weak_new_ref)));
+
+      // Create a weak ref to the old space object.
+      weak_old_ref = Dart_NewWeakPersistentHandle(old_ref, NULL, 0,
+                                                  WeakPersistentHandleCallback);
+      EXPECT_VALID(AsHandle(weak_old_ref));
+      EXPECT(!Dart_IsNull(AsHandle(weak_old_ref)));
+    }
 
     {
       TransitionNativeToVM transition(thread);
@@ -3264,10 +3267,6 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandle) {
-  // GCs due to allocations or weak handle creation can cause early promotion
-  // and interfer with the scenario this test is verifying.
-  NoHeapGrowthControlScope force_growth;
-
   void* peer = reinterpret_cast<void*>(0);
   Dart_Handle local_new_ref = Dart_Null();
   finalizable_new_ref = Dart_NewFinalizableHandle(local_new_ref, peer, 0,
@@ -3283,25 +3282,32 @@
   {
     Dart_EnterScope();
 
-    // Create an object in new space.
-    Dart_Handle new_ref = AllocateNewString("new string");
-    EXPECT_VALID(new_ref);
+    Dart_Handle new_ref, old_ref;
+    {
+      // GCs due to allocations or weak handle creation can cause early
+      // promotion and interfere with the scenario this test is verifying.
+      NoHeapGrowthControlScope force_growth;
 
-    // Create an object in old space.
-    Dart_Handle old_ref = AllocateOldString("old string");
-    EXPECT_VALID(old_ref);
+      // Create an object in new space.
+      new_ref = AllocateNewString("new string");
+      EXPECT_VALID(new_ref);
 
-    // Create a weak ref to the new space object.
-    peer = reinterpret_cast<void*>(2);
-    finalizable_new_ref =
-        Dart_NewFinalizableHandle(new_ref, peer, 0, FinalizableHandleCallback);
-    finalizable_new_ref_peer = peer;
+      // Create an object in old space.
+      old_ref = AllocateOldString("old string");
+      EXPECT_VALID(old_ref);
 
-    // Create a weak ref to the old space object.
-    peer = reinterpret_cast<void*>(3);
-    finalizable_old_ref =
-        Dart_NewFinalizableHandle(old_ref, peer, 0, FinalizableHandleCallback);
-    finalizable_old_ref_peer = peer;
+      // Create a weak ref to the new space object.
+      peer = reinterpret_cast<void*>(2);
+      finalizable_new_ref = Dart_NewFinalizableHandle(
+          new_ref, peer, 0, FinalizableHandleCallback);
+      finalizable_new_ref_peer = peer;
+
+      // Create a weak ref to the old space object.
+      peer = reinterpret_cast<void*>(3);
+      finalizable_old_ref = Dart_NewFinalizableHandle(
+          old_ref, peer, 0, FinalizableHandleCallback);
+      finalizable_old_ref_peer = peer;
+    }
 
     {
       TransitionNativeToVM transition(thread);
@@ -3522,14 +3528,12 @@
 }
 
 TEST_CASE(DartAPI_FinalizableHandleCallback) {
-  Dart_FinalizableHandle weak_ref = nullptr;
   int peer = 0;
   {
     Dart_EnterScope();
     Dart_Handle obj = NewString("new string");
     EXPECT_VALID(obj);
-    weak_ref = Dart_NewFinalizableHandle(obj, &peer, 0,
-                                         FinalizableHandlePeerFinalizer);
+    Dart_NewFinalizableHandle(obj, &peer, 0, FinalizableHandlePeerFinalizer);
     EXPECT(peer == 0);
     Dart_ExitScope();
   }
@@ -3670,26 +3674,22 @@
   Heap* heap = Isolate::Current()->heap();
   EXPECT(heap->ExternalInWords(Heap::kNew) == 0);
   EXPECT(heap->ExternalInWords(Heap::kOld) == 0);
-  Dart_FinalizableHandle weak1 = nullptr;
   static const intptr_t kWeak1ExternalSize = 1 * KB;
   {
     Dart_EnterScope();
     Dart_Handle obj = NewString("weakly referenced string");
     EXPECT_VALID(obj);
-    weak1 = Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize,
-                                      NopCallback);
+    Dart_NewFinalizableHandle(obj, nullptr, kWeak1ExternalSize, NopCallback);
     Dart_ExitScope();
   }
   Dart_PersistentHandle strong_ref = nullptr;
-  Dart_FinalizableHandle weak2 = nullptr;
   static const intptr_t kWeak2ExternalSize = 2 * KB;
   {
     Dart_EnterScope();
     Dart_Handle obj = NewString("strongly referenced string");
     EXPECT_VALID(obj);
     strong_ref = Dart_NewPersistentHandle(obj);
-    weak2 = Dart_NewFinalizableHandle(obj, nullptr, kWeak2ExternalSize,
-                                      NopCallback);
+    Dart_NewFinalizableHandle(obj, nullptr, kWeak2ExternalSize, NopCallback);
     EXPECT_VALID(AsHandle(strong_ref));
     Dart_ExitScope();
   }
@@ -3804,7 +3804,6 @@
   Dart_Handle live = AllocateOldString("live");
   EXPECT_VALID(live);
   Dart_WeakPersistentHandle weak = NULL;
-  Dart_WeakPersistentHandle weak2 = NULL;
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
@@ -3828,8 +3827,7 @@
   }
   // Large enough to trigger GC in old space. Not actually allocated.
   const intptr_t kHugeExternalSize = (kWordSize == 4) ? 513 * MB : 1025 * MB;
-  weak2 =
-      Dart_NewWeakPersistentHandle(live, NULL, kHugeExternalSize, NopCallback);
+  Dart_NewWeakPersistentHandle(live, NULL, kHugeExternalSize, NopCallback);
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
@@ -3846,7 +3844,6 @@
   Dart_EnterScope();
   Dart_Handle live = AllocateOldString("live");
   EXPECT_VALID(live);
-  Dart_FinalizableHandle weak = NULL;
   {
     TransitionNativeToVM transition(thread);
     GCTestHelper::WaitForGCTasks();  // Finalize GC for accurate live size.
@@ -3857,8 +3854,7 @@
     Dart_EnterScope();
     Dart_Handle dead = AllocateOldString("dead");
     EXPECT_VALID(dead);
-    weak = Dart_NewFinalizableHandle(dead, nullptr, kSmallExternalSize,
-                                     NopCallback);
+    Dart_NewFinalizableHandle(dead, nullptr, kSmallExternalSize, NopCallback);
     Dart_ExitScope();
   }
   {
@@ -5542,7 +5538,13 @@
       "  factory MyInterface.named(value) = MyExtraHop.hop;\n"
       "  factory MyInterface.multiply(value) = MyClass.multiply;\n"
       "  MyInterface.notfound(value);\n"
-      "}\n";
+      "}\n"
+      "\n"
+      "class _MyClass {\n"
+      "  _MyClass._() : foo = 7 {}\n"
+      "  var foo;\n"
+      "}\n"
+      "\n";
 
   Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
   Dart_Handle type =
@@ -5551,6 +5553,10 @@
   Dart_Handle intf =
       Dart_GetNonNullableType(lib, NewString("MyInterface"), 0, NULL);
   EXPECT_VALID(intf);
+  Dart_Handle private_type =
+      Dart_GetNonNullableType(lib, NewString("_MyClass"), 0, NULL);
+  EXPECT_VALID(private_type);
+
   Dart_Handle args[1];
   args[0] = Dart_NewInteger(11);
   Dart_Handle bad_args[1];
@@ -5641,6 +5647,14 @@
   EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
   EXPECT_EQ(-11, int_value);
 
+  // Invoke a hidden named constructor on a hidden type.
+  result = Dart_New(private_type, NewString("_"), 0, NULL);
+  EXPECT_VALID(result);
+  int_value = 0;
+  foo = Dart_GetField(result, NewString("foo"));
+  EXPECT_VALID(Dart_IntegerToInt64(foo, &int_value));
+  EXPECT_EQ(7, int_value);
+
   // Allocate object and invoke a hidden named constructor.
   obj = Dart_Allocate(type);
   EXPECT_VALID(obj);
diff --git a/runtime/vm/dart_api_message.cc b/runtime/vm/dart_api_message.cc
index 613614e..bc83266 100644
--- a/runtime/vm/dart_api_message.cc
+++ b/runtime/vm/dart_api_message.cc
@@ -774,15 +774,8 @@
   return NULL;
 }
 
-static uint8_t* malloc_allocator(uint8_t* ptr,
-                                 intptr_t old_size,
-                                 intptr_t new_size) {
-  void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
-  return reinterpret_cast<uint8_t*>(new_ptr);
-}
-
 ApiMessageWriter::ApiMessageWriter()
-    : BaseWriter(malloc_allocator, NULL, kInitialSize),
+    : BaseWriter(kInitialSize),
       object_id_(0),
       forward_list_(NULL),
       forward_list_length_(0),
@@ -1170,7 +1163,8 @@
   bool success = WriteCObject(object);
   if (!success) {
     UnmarkAllCObjects(object);
-    free(buffer());
+    intptr_t unused;
+    free(Steal(&unused));
     return nullptr;
   }
 
@@ -1181,16 +1175,18 @@
     success = WriteForwardedCObject(forward_list_[i]);
     if (!success) {
       UnmarkAllCObjects(object);
-      free(buffer());
+      intptr_t unused;
+      free(Steal(&unused));
       return nullptr;
     }
   }
 
   UnmarkAllCObjects(object);
   MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = NULL;
-  return Message::New(dest_port, buffer(), BytesWritten(), finalizable_data,
-                      priority);
+  finalizable_data_ = nullptr;
+  intptr_t size;
+  uint8_t* buffer = Steal(&size);
+  return Message::New(dest_port, buffer, size, finalizable_data, priority);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 96081a8..0cb0bd6 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -526,11 +526,7 @@
 
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
-  const char* error_str = NULL;
-  descriptor ^= descriptor.CheckAndCanonicalize(thread, &error_str);
-  if (error_str != NULL) {
-    FATAL1("Failed to canonicalize: %s", error_str);
-  }
+  descriptor ^= descriptor.Canonicalize(thread);
   ASSERT(!descriptor.IsNull());
   return descriptor.raw();
 }
@@ -584,11 +580,7 @@
   // Share the immutable descriptor when possible by canonicalizing it.
   descriptor.MakeImmutable();
   if (canonicalize) {
-    const char* error_str = NULL;
-    descriptor ^= descriptor.CheckAndCanonicalize(thread, &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
+    descriptor ^= descriptor.Canonicalize(thread);
   }
   ASSERT(!descriptor.IsNull());
   return descriptor.raw();
diff --git a/runtime/vm/datastream.cc b/runtime/vm/datastream.cc
index de77937..6d398fe 100644
--- a/runtime/vm/datastream.cc
+++ b/runtime/vm/datastream.cc
@@ -4,18 +4,33 @@
 
 #include "vm/datastream.h"
 
+#include "vm/compiler/runtime_api.h"
+#include "vm/zone.h"
+
 namespace dart {
 
-StreamingWriteStream::StreamingWriteStream(intptr_t initial_capacity,
-                                           Dart_StreamingWriteCallback callback,
-                                           void* callback_data)
-    : flushed_size_(0), callback_(callback), callback_data_(callback_data) {
-  buffer_ = reinterpret_cast<uint8_t*>(malloc(initial_capacity));
-  if (buffer_ == NULL) {
-    OUT_OF_MEMORY();
-  }
-  cursor_ = buffer_;
-  limit_ = buffer_ + initial_capacity;
+void BaseWriteStream::WriteTargetWord(word value) {
+  ASSERT(compiler::target::kBitsPerWord == kBitsPerWord ||
+         Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value));
+  WriteFixed(static_cast<compiler::target::word>(value));
+}
+
+MallocWriteStream::~MallocWriteStream() {
+  free(buffer_);
+}
+
+void MallocWriteStream::Realloc(intptr_t new_size) {
+  const intptr_t old_offset = current_ - buffer_;
+  buffer_ = reinterpret_cast<uint8_t*>(realloc(buffer_, new_size));
+  capacity_ = buffer_ != nullptr ? new_size : 0;
+  current_ = buffer_ != nullptr ? buffer_ + old_offset : nullptr;
+}
+
+void ZoneWriteStream::Realloc(intptr_t new_size) {
+  const intptr_t old_offset = current_ - buffer_;
+  buffer_ = zone_->Realloc(buffer_, capacity_, new_size);
+  capacity_ = buffer_ != nullptr ? new_size : 0;
+  current_ = buffer_ != nullptr ? buffer_ + old_offset : nullptr;
 }
 
 StreamingWriteStream::~StreamingWriteStream() {
@@ -23,46 +38,23 @@
   free(buffer_);
 }
 
-void StreamingWriteStream::VPrint(const char* format, va_list args) {
-  // Measure.
-  va_list measure_args;
-  va_copy(measure_args, args);
-  intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
-  va_end(measure_args);
-
-  // Alloc.
-  EnsureAvailable(len + 1);
-
-  // Print.
-  va_list print_args;
-  va_copy(print_args, args);
-  Utils::VSNPrint(reinterpret_cast<char*>(cursor_), len + 1, format,
-                  print_args);
-  va_end(print_args);
-  cursor_ += len;  // Not len + 1 to swallow the terminating NUL.
-}
-
-void StreamingWriteStream::EnsureAvailableSlowPath(intptr_t needed) {
+void StreamingWriteStream::Realloc(intptr_t new_size) {
   Flush();
-
-  intptr_t available = limit_ - cursor_;
-  if (available >= needed) return;
-
-  intptr_t new_capacity = Utils::RoundUp(needed, 64 * KB);
-  free(buffer_);
-  buffer_ = reinterpret_cast<uint8_t*>(malloc(new_capacity));
-  if (buffer_ == NULL) {
-    OUT_OF_MEMORY();
+  // Check whether resetting the internal buffer by flushing gave enough space.
+  if (new_size <= capacity_) {
+    return;
   }
-  cursor_ = buffer_;
-  limit_ = buffer_ + new_capacity;
+  const intptr_t new_capacity = Utils::RoundUp(new_size, 64 * KB);
+  buffer_ = reinterpret_cast<uint8_t*>(realloc(buffer_, new_capacity));
+  capacity_ = buffer_ != nullptr ? new_capacity : 0;
+  current_ = buffer_;  // Flushing reset the internal buffer offset to 0.
 }
 
 void StreamingWriteStream::Flush() {
-  intptr_t size = cursor_ - buffer_;
+  intptr_t size = current_ - buffer_;
   callback_(callback_data_, buffer_, size);
   flushed_size_ += size;
-  cursor_ = buffer_;
+  current_ = buffer_;
 }
 
 }  // namespace dart
diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h
index a844493..7da4532 100644
--- a/runtime/vm/datastream.h
+++ b/runtime/vm/datastream.h
@@ -5,13 +5,13 @@
 #ifndef RUNTIME_VM_DATASTREAM_H_
 #define RUNTIME_VM_DATASTREAM_H_
 
-#include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/utils.h"
 #include "vm/allocation.h"
 #include "vm/exceptions.h"
 #include "vm/globals.h"
 #include "vm/os.h"
+#include "vm/zone.h"
 
 namespace dart {
 
@@ -23,8 +23,27 @@
 static const uint8_t kEndByteMarker = (255 - kMaxDataPerByte);
 static const uint8_t kEndUnsignedByteMarker = (255 - kMaxUnsignedDataPerByte);
 
-typedef uint8_t* (*ReAlloc)(uint8_t* ptr, intptr_t old_size, intptr_t new_size);
-typedef void (*DeAlloc)(uint8_t* ptr);
+struct LEB128Constants : AllStatic {
+  // Convenience template for ensuring non-signed types trigger SFINAE.
+  template <typename T, typename S>
+  using only_if_signed =
+      typename std::enable_if<std::is_signed<T>::value, S>::type;
+
+  // Convenience template for ensuring signed types trigger SFINAE.
+  template <typename T, typename S>
+  using only_if_unsigned =
+      typename std::enable_if<std::is_unsigned<T>::value, S>::type;
+
+  // (S)LEB128 encodes 7 bits of data per byte (hence 128).
+  static constexpr uint8_t kDataBitsPerByte = 7;
+  static constexpr uint8_t kDataByteMask = (1 << kDataBitsPerByte) - 1;
+  // If more data follows a given data byte, the high bit is set.
+  static constexpr uint8_t kMoreDataMask = (1 << kDataBitsPerByte);
+  // For SLEB128, the high bit in the data of the last byte is the sign bit.
+  static constexpr uint8_t kSignMask = (1 << (kDataBitsPerByte - 1));
+};
+
+class NonStreamingWriteStream;
 
 // Stream for reading various types from a buffer.
 class ReadStream : public ValueObject {
@@ -32,10 +51,10 @@
   ReadStream(const uint8_t* buffer, intptr_t size)
       : buffer_(buffer), current_(buffer), end_(buffer + size) {}
 
-  void SetStream(const uint8_t* buffer, intptr_t size) {
-    buffer_ = buffer;
-    current_ = buffer;
-    end_ = buffer + size;
+  // Creates a ReadStream that starts at a given position in the buffer.
+  ReadStream(const uint8_t* buffer, intptr_t size, intptr_t pos)
+      : ReadStream(buffer, size) {
+    SetPosition(pos);
   }
 
   template <int N, typename T>
@@ -81,7 +100,7 @@
 
   intptr_t Position() const { return current_ - buffer_; }
   void SetPosition(intptr_t value) {
-    ASSERT((end_ - buffer_) > value);
+    ASSERT((end_ - buffer_) >= value);
     current_ = buffer_ + value;
   }
 
@@ -109,19 +128,72 @@
   }
 
   uword ReadWordWith32BitReads() {
-    constexpr intptr_t kNumBytesPerRead32 = sizeof(uint32_t);
-    constexpr intptr_t kNumRead32PerWord = sizeof(uword) / kNumBytesPerRead32;
-    constexpr intptr_t kNumBitsPerRead32 = kNumBytesPerRead32 * kBitsPerByte;
+    constexpr intptr_t kNumRead32PerWord = kBitsPerWord / kBitsPerInt32;
 
     uword value = 0;
     for (intptr_t j = 0; j < kNumRead32PerWord; j++) {
-      const auto partial_value = Raw<kNumBytesPerRead32, uint32_t>::Read(this);
-      value |= (static_cast<uword>(partial_value) << (j * kNumBitsPerRead32));
+      const auto partial_value = Raw<kInt32Size, uint32_t>::Read(this);
+      value |= (static_cast<uword>(partial_value) << (j * kBitsPerInt32));
     }
     return value;
   }
 
  private:
+  using C = LEB128Constants;
+
+ public:
+  template <typename T = uintptr_t>
+  C::only_if_unsigned<T, T> ReadLEB128() {
+    constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T);
+    T r = 0;
+    uint8_t s = 0;
+    uint8_t b;
+    do {
+      ASSERT(s < kBitsPerT);
+      b = ReadByte();
+      r |= static_cast<T>(b & C::kDataByteMask) << s;
+      s += C::kDataBitsPerByte;
+    } while ((b & C::kMoreDataMask) != 0);
+    ASSERT(s < C::kDataBitsPerByte + kBitsPerT);
+    return r;
+  }
+
+  template <typename T>
+  C::only_if_signed<T, T> ReadLEB128() {
+    return bit_cast<T>(ReadLEB128<typename std::make_unsigned<T>::type>());
+  }
+
+  template <typename T>
+  C::only_if_unsigned<T, T> ReadSLEB128() {
+    constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T);
+    T r = 0;
+    uint8_t s = 0;
+    uint8_t b;
+    do {
+      ASSERT(s < kBitsPerT);
+      b = ReadByte();
+      r |= static_cast<T>(b & C::kDataByteMask) << s;
+      s += C::kDataBitsPerByte;
+    } while ((b & C::kMoreDataMask) != 0);
+    ASSERT(s < C::kDataBitsPerByte + kBitsPerT);
+    // At this point, [s] contains how many data bits have made it into the
+    // value. If the value is negative and the count of data bits is less than
+    // the size of the value, then we need to extend the sign by setting the
+    // remaining (unset) most significant bits (MSBs).
+    T sign_bits = 0;
+    if ((b & C::kSignMask) != 0 && s < kBitsPerT) {
+      // Create a bitmask for the current data bits and invert it.
+      sign_bits = ~((static_cast<T>(1) << s) - 1);
+    }
+    return r | sign_bits;
+  }
+
+  template <typename T = intptr_t>
+  C::only_if_signed<T, T> ReadSLEB128() {
+    return bit_cast<T>(ReadSLEB128<typename std::make_unsigned<T>::type>());
+  }
+
+ private:
   uint16_t Read16() { return Read16(kEndByteMarker); }
 
   uint32_t Read32() { return Read32(kEndByteMarker); }
@@ -131,11 +203,8 @@
   template <typename T>
   T Read(uint8_t end_byte_marker) {
     using Unsigned = typename std::make_unsigned<T>::type;
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    Unsigned b = *c++;
+    Unsigned b = ReadByte();
     if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
       return b - end_byte_marker;
     }
     T r = 0;
@@ -143,159 +212,78 @@
     do {
       r |= static_cast<Unsigned>(b) << s;
       s += kDataBitsPerByte;
-      ASSERT(c < end_);
-      b = *c++;
+      b = ReadByte();
     } while (b <= kMaxUnsignedDataPerByte);
-    current_ = c;
     return r | (static_cast<Unsigned>(b - end_byte_marker) << s);
   }
 
-  uint16_t Read16(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint16_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-    uint16_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint16_t>(b - end_byte_marker) << 7);
-    }
+// Setting up needed variables for the unrolled loop sections below.
+#define UNROLLED_INIT()                                                        \
+  using Unsigned = typename std::make_unsigned<T>::type;                       \
+  Unsigned b = ReadByte();                                                     \
+  if (b > kMaxUnsignedDataPerByte) {                                           \
+    return b - end_byte_marker;                                                \
+  }                                                                            \
+  T r = b;
 
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint16_t>(b - end_byte_marker) << 14);
+// Part of the unrolled loop where the loop may stop, having read the last part,
+// or continue reading.
+#define UNROLLED_BODY(bit_start)                                               \
+  static_assert(bit_start % kDataBitsPerByte == 0,                             \
+                "Bit start must be a multiple of the data bits per byte");     \
+  static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T),        \
+                "Starting unrolled body at invalid bit position");             \
+  static_assert(bit_start + kDataBitsPerByte < kBitsPerByte * sizeof(T),       \
+                "Unrolled body should not contain final bits in value");       \
+  b = ReadByte();                                                              \
+  if (b > kMaxUnsignedDataPerByte) {                                           \
+    return r | (static_cast<T>(b - end_byte_marker) << bit_start);             \
+  }                                                                            \
+  r |= b << bit_start;
+
+// The end of the unrolled loop.
+#define UNROLLED_END(bit_start)                                                \
+  static_assert(bit_start % kDataBitsPerByte == 0,                             \
+                "Bit start must be a multiple of the data bits per byte");     \
+  static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T),        \
+                "Starting unrolled end at invalid bit position");              \
+  static_assert(bit_start + kDataBitsPerByte >= kBitsPerByte * sizeof(T),      \
+                "Unrolled end does not contain final bits in value");          \
+  b = ReadByte();                                                              \
+  ASSERT(b > kMaxUnsignedDataPerByte);                                         \
+  return r | (static_cast<T>(b - end_byte_marker) << bit_start);
+
+  uint16_t Read16(uint8_t end_byte_marker) {
+    using T = uint16_t;
+    UNROLLED_INIT();
+    UNROLLED_BODY(7);
+    UNROLLED_END(14);
   }
 
   uint32_t Read32(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint32_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-
-    uint32_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 7);
-    }
-
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 14);
-    }
-
-    r |= b << 14;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint32_t>(b - end_byte_marker) << 21);
-    }
-
-    r |= b << 21;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint32_t>(b - end_byte_marker) << 28);
+    using T = uint32_t;
+    UNROLLED_INIT();
+    UNROLLED_BODY(7);
+    UNROLLED_BODY(14);
+    UNROLLED_BODY(21);
+    UNROLLED_END(28);
   }
 
   uint64_t Read64(uint8_t end_byte_marker) {
-    const uint8_t* c = current_;
-    ASSERT(c < end_);
-    uint64_t b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return b - end_byte_marker;
-    }
-    uint64_t r = b;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 7);
-    }
-
-    r |= b << 7;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 14);
-    }
-
-    r |= b << 14;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 21);
-    }
-
-    r |= b << 21;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 28);
-    }
-
-    r |= b << 28;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 35);
-    }
-
-    r |= b << 35;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 42);
-    }
-
-    r |= b << 42;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 49);
-    }
-
-    r |= b << 49;
-    ASSERT(c < end_);
-    b = *c++;
-    if (b > kMaxUnsignedDataPerByte) {
-      current_ = c;
-      return r | (static_cast<uint64_t>(b - end_byte_marker) << 56);
-    }
-
-    r |= b << 56;
-    ASSERT(c < end_);
-    b = *c++;
-    ASSERT(b > kMaxUnsignedDataPerByte);
-    current_ = c;
-    return r | (static_cast<uint64_t>(b - end_byte_marker) << 63);
+    using T = uint64_t;
+    UNROLLED_INIT();
+    UNROLLED_BODY(7);
+    UNROLLED_BODY(14);
+    UNROLLED_BODY(21);
+    UNROLLED_BODY(28);
+    UNROLLED_BODY(35);
+    UNROLLED_BODY(42);
+    UNROLLED_BODY(49);
+    UNROLLED_BODY(56);
+    UNROLLED_END(63);
   }
 
-  uint8_t ReadByte() {
+  DART_FORCE_INLINE uint8_t ReadByte() {
     ASSERT(current_ < end_);
     return *current_++;
   }
@@ -308,39 +296,27 @@
   DISALLOW_COPY_AND_ASSIGN(ReadStream);
 };
 
-// Stream for writing various types into a buffer.
-class WriteStream : public ValueObject {
+// Base class for streams that writing various types into a buffer, possibly
+// flushing data out periodically to a more permanent store.
+class BaseWriteStream : public ValueObject {
  public:
-  WriteStream(uint8_t** buffer, ReAlloc alloc, intptr_t initial_size)
-      : buffer_(buffer),
-        end_(NULL),
-        current_(NULL),
-        current_size_(0),
-        alloc_(alloc),
-        initial_size_(initial_size) {
-    ASSERT(buffer != NULL);
-    ASSERT(alloc != NULL);
-    *buffer_ = reinterpret_cast<uint8_t*>(alloc_(NULL, 0, initial_size_));
-    if (*buffer_ == NULL) {
-      Exceptions::ThrowOOM();
+  explicit BaseWriteStream(intptr_t initial_size)
+      : initial_size_(Utils::RoundUpToPowerOfTwo(initial_size)) {}
+  virtual ~BaseWriteStream() {}
+
+  DART_FORCE_INLINE intptr_t bytes_written() const { return Position(); }
+  virtual intptr_t Position() const { return current_ - buffer_; }
+
+  intptr_t Align(intptr_t alignment) {
+    const intptr_t position_before = Position();
+    const intptr_t position_after = Utils::RoundUp(position_before, alignment);
+    const intptr_t length = position_after - position_before;
+    if (length != 0) {
+      EnsureSpace(length);
+      memset(current_, 0, length);
+      SetPosition(position_after);
     }
-    current_ = *buffer_;
-    current_size_ = initial_size_;
-    end_ = *buffer_ + initial_size_;
-  }
-
-  uint8_t* buffer() const { return *buffer_; }
-  void set_buffer(uint8_t* value) { *buffer_ = value; }
-  intptr_t bytes_written() const { return current_ - *buffer_; }
-
-  intptr_t Position() const { return current_ - *buffer_; }
-  void SetPosition(intptr_t value) { current_ = *buffer_ + value; }
-
-  void Align(intptr_t alignment) {
-    intptr_t position_before = Position();
-    intptr_t position_after = Utils::RoundUp(position_before, alignment);
-    memset(current_, 0, position_after - position_before);
-    SetPosition(position_after);
+    return length;
   }
 
   template <int N, typename T>
@@ -349,15 +325,15 @@
   template <typename T>
   class Raw<1, T> {
    public:
-    static void Write(WriteStream* st, T value) {
-      st->WriteByte(bit_cast<int8_t>(value));
+    static void Write(BaseWriteStream* st, T value) {
+      st->WriteByte(bit_cast<uint8_t>(value));
     }
   };
 
   template <typename T>
   class Raw<2, T> {
    public:
-    static void Write(WriteStream* st, T value) {
+    static void Write(BaseWriteStream* st, T value) {
       st->Write<int16_t>(bit_cast<int16_t>(value));
     }
   };
@@ -365,7 +341,7 @@
   template <typename T>
   class Raw<4, T> {
    public:
-    static void Write(WriteStream* st, T value) {
+    static void Write(BaseWriteStream* st, T value) {
       st->Write<int32_t>(bit_cast<int32_t>(value));
     }
   };
@@ -373,20 +349,18 @@
   template <typename T>
   class Raw<8, T> {
    public:
-    static void Write(WriteStream* st, T value) {
+    static void Write(BaseWriteStream* st, T value) {
       st->Write<int64_t>(bit_cast<int64_t>(value));
     }
   };
 
   void WriteWordWith32BitWrites(uword value) {
-    constexpr intptr_t kNumBytesPerWrite32 = sizeof(uint32_t);
-    constexpr intptr_t kNumWrite32PerWord = sizeof(uword) / kNumBytesPerWrite32;
-    constexpr intptr_t kNumBitsPerWrite32 = kNumBytesPerWrite32 * kBitsPerByte;
+    constexpr intptr_t kNumWrite32PerWord = kBitsPerWord / kBitsPerInt32;
 
-    const uint32_t mask = Utils::NBitMask(kNumBitsPerWrite32);
+    const uint32_t mask = Utils::NBitMask(kBitsPerInt32);
     for (intptr_t j = 0; j < kNumWrite32PerWord; j++) {
-      const uint32_t shifted_value = (value >> (j * kNumBitsPerWrite32));
-      Raw<kNumBytesPerWrite32, uint32_t>::Write(this, shifted_value & mask);
+      const uint32_t shifted_value = (value >> (j * kBitsPerInt32));
+      Raw<kInt32Size, uint32_t>::Write(this, shifted_value & mask);
     }
   }
 
@@ -401,60 +375,33 @@
   }
 
   void WriteBytes(const void* addr, intptr_t len) {
-    if ((end_ - current_) < len) {
-      Resize(len);
-    }
-    ASSERT((end_ - current_) >= len);
     if (len != 0) {
+      EnsureSpace(len);
       memmove(current_, addr, len);
+      current_ += len;
     }
-    current_ += len;
   }
 
-  void WriteWord(uword value) {
-    const intptr_t len = sizeof(uword);
-    if ((end_ - current_) < len) {
-      Resize(len);
-    }
-    ASSERT((end_ - current_) >= len);
-    *reinterpret_cast<uword*>(current_) = value;
-    current_ += len;
-  }
+  void WriteWord(uword value) { WriteFixed(value); }
 
-  void WriteTargetWord(uword value) {
-#if defined(IS_SIMARM_X64)
-    RELEASE_ASSERT(Utils::IsInt(32, static_cast<word>(value)));
-    const intptr_t len = sizeof(uint32_t);
-    if ((end_ - current_) < len) {
-      Resize(len);
-    }
-    ASSERT((end_ - current_) >= len);
-    *reinterpret_cast<uint32_t*>(current_) = static_cast<uint32_t>(value);
-    current_ += len;
-#else   // defined(IS_SIMARM_X64)
-    WriteWord(value);
-#endif  // defined(IS_SIMARM_X64)
-  }
+  void WriteTargetWord(word value);
 
-  void Print(const char* format, ...) {
+  void Printf(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
     va_list args;
     va_start(args, format);
-    VPrint(format, args);
+    VPrintf(format, args);
     va_end(args);
   }
 
-  void VPrint(const char* format, va_list args) {
+  void VPrintf(const char* format, va_list args) {
     // Measure.
     va_list measure_args;
     va_copy(measure_args, args);
-    intptr_t len = Utils::VSNPrint(NULL, 0, format, measure_args);
+    intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
     va_end(measure_args);
 
     // Alloc.
-    if ((end_ - current_) < (len + 1)) {
-      Resize(len + 1);
-    }
-    ASSERT((end_ - current_) >= (len + 1));
+    EnsureSpace(len + 1);
 
     // Print.
     va_list print_args;
@@ -477,102 +424,231 @@
 
   template <typename T>
   void WriteFixed(T value) {
-    const intptr_t len = sizeof(T);
-    if ((end_ - current_) < len) {
-      Resize(len);
-    }
-    ASSERT((end_ - current_) >= len);
-    *reinterpret_cast<T*>(current_) = static_cast<T>(value);
-    current_ += len;
+    WriteBytes(&value, sizeof(value));
   }
 
- private:
   DART_FORCE_INLINE void WriteByte(uint8_t value) {
-    if (current_ >= end_) {
-      Resize(1);
-    }
-    ASSERT(current_ < end_);
+    EnsureSpace(1);
     *current_++ = value;
   }
 
-  void Resize(intptr_t size_needed) {
-    intptr_t position = current_ - *buffer_;
-    intptr_t increment_size = current_size_;
+  void WriteString(const char* cstr) { WriteBytes(cstr, strlen(cstr)); }
+
+ private:
+  using C = LEB128Constants;
+
+ public:
+  template <typename T>
+  C::only_if_unsigned<T, void> WriteLEB128(T value) {
+    T remainder = value;
+    bool is_last_part;
+    do {
+      uint8_t part = static_cast<uint8_t>(remainder & C::kDataByteMask);
+      remainder >>= C::kDataBitsPerByte;
+      // For unsigned types, we're done when the remainder has no bits set.
+      is_last_part = remainder == static_cast<T>(0);
+      if (!is_last_part) {
+        // Mark this part as a non-final part for this value.
+        part |= C::kMoreDataMask;
+      }
+      WriteByte(part);
+    } while (!is_last_part);
+  }
+
+  template <typename T>
+  C::only_if_signed<T, void> WriteLEB128(T value) {
+    // If we're trying to LEB128 encode a negative value, chances are we should
+    // be using SLEB128 instead.
+    ASSERT(value >= 0);
+    return WriteLEB128(bit_cast<typename std::make_unsigned<T>::type>(value));
+  }
+
+  template <typename T>
+  C::only_if_signed<T, void> WriteSLEB128(T value) {
+    constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T);
+    using Unsigned = typename std::make_unsigned<T>::type;
+    // Record whether the original value was negative.
+    const bool is_negative = value < 0;
+    T remainder = value;
+    bool is_last_part;
+    do {
+      uint8_t part = static_cast<uint8_t>(remainder & C::kDataByteMask);
+      remainder >>= C::kDataBitsPerByte;
+      // For signed types, we're done when either:
+      // - the remainder has all bits set and the part's sign bit is set
+      //   for negative values, or
+      // - the remainder has no bits set and the part's sign bit is unset for
+      //   non-negative values.
+      // If the remainder matches but the sign bit does not, we need one more
+      // part to set the sign bit correctly when decoding.
+      if (is_negative) {
+        // Right shifts of negative values in C are not guaranteed to be
+        // arithmetic. For negative values, set the [kDataBitsPerByte] most
+        // significant bits after shifting to ensure the value stays negative.
+        constexpr intptr_t preserved_bits = kBitsPerT - C::kDataBitsPerByte;
+        // The sign extension mask is the inverse of the preserved bits mask.
+        constexpr T sign_extend =
+            ~static_cast<T>((static_cast<Unsigned>(1) << preserved_bits) - 1);
+        // Sign extend for negative values just in case a non-arithmetic right
+        // shift is used by the compiler.
+        remainder |= sign_extend;
+        ASSERT(remainder < 0);  // Remainder should still be negative.
+        is_last_part =
+            remainder == ~static_cast<T>(0) && (part & C::kSignMask) != 0;
+      } else {
+        ASSERT(remainder >= 0);  // Remainder should still be non-negative.
+        is_last_part =
+            (remainder == static_cast<T>(0) && (part & C::kSignMask) == 0);
+      }
+      if (!is_last_part) {
+        // Mark this part as a non-final part for this value.
+        part |= C::kMoreDataMask;
+      }
+      WriteByte(part);
+    } while (!is_last_part);
+  }
+
+  template <typename T>
+  C::only_if_unsigned<T, void> WriteSLEB128(T value) {
+    return WriteSLEB128(bit_cast<typename std::make_signed<T>::type>(value));
+  }
+
+ protected:
+  void EnsureSpace(intptr_t size_needed) {
+    if (Remaining() >= size_needed) return;
+    intptr_t increment_size = capacity_;
     if (size_needed > increment_size) {
       increment_size = Utils::RoundUp(size_needed, initial_size_);
     }
-    intptr_t new_size = current_size_ + increment_size;
-    ASSERT(new_size > current_size_);
-    *buffer_ =
-        reinterpret_cast<uint8_t*>(alloc_(*buffer_, current_size_, new_size));
-    if (*buffer_ == NULL) {
+    intptr_t new_size = capacity_ + increment_size;
+    ASSERT(new_size > capacity_);
+    Realloc(new_size);
+    if (buffer_ == nullptr) {
       Exceptions::ThrowOOM();
     }
-    current_ = *buffer_ + position;
-    current_size_ = new_size;
-    end_ = *buffer_ + new_size;
-    ASSERT(end_ > *buffer_);
+    ASSERT(Remaining() >= size_needed);
+  }
+
+  virtual void SetPosition(intptr_t value) {
+    EnsureSpace(value - BaseWriteStream::Position());
+    current_ = buffer_ + value;
+  }
+
+  DART_FORCE_INLINE intptr_t Remaining() const {
+    return capacity_ - BaseWriteStream::Position();
+  }
+
+  // Resizes the internal buffer to the requested new capacity. Should set
+  // buffer_, capacity_, and current_ appropriately.
+  //
+  // Instead of templating over an Allocator (which would then cause users
+  // of the templated class to need to be templated, etc.), we just add an
+  // Realloc method to override appropriately in subclasses. Less flexible,
+  // but requires less changes throughout the codebase.
+  virtual void Realloc(intptr_t new_capacity) = 0;
+
+  const intptr_t initial_size_;
+  uint8_t* buffer_ = nullptr;
+  uint8_t* current_ = nullptr;
+  intptr_t capacity_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(BaseWriteStream);
+};
+
+// A base class for non-streaming write streams. Since these streams are
+// not flushed periodically, the internal buffer contains all written data
+// and can be retrieved via buffer(). NonStreamingWriteStream also provides
+// SetPosition as part of its public API for non-sequential writing.
+class NonStreamingWriteStream : public BaseWriteStream {
+ public:
+  explicit NonStreamingWriteStream(intptr_t initial_size)
+      : BaseWriteStream(initial_size) {}
+
+ public:
+  uint8_t* buffer() const { return buffer_; }
+
+  // Sets the position of the buffer
+  DART_FORCE_INLINE void SetPosition(intptr_t value) {
+    BaseWriteStream::SetPosition(value);
+  }
+};
+
+// A non-streaming write stream that uses realloc for reallocation, and frees
+// the buffer when destructed unless ownership is transfered using Steal().
+class MallocWriteStream : public NonStreamingWriteStream {
+ public:
+  explicit MallocWriteStream(intptr_t initial_size)
+      : NonStreamingWriteStream(initial_size) {}
+  ~MallocWriteStream();
+
+  // Resets the stream and returns the original buffer, which is now considered
+  // owned by the caller. Sets [*length] to the length of the returned buffer.
+  uint8_t* Steal(intptr_t* length) {
+    ASSERT(length != nullptr);
+    *length = bytes_written();
+    uint8_t* const old_buffer = buffer_;
+    // We don't immediately reallocate a new space just in case this steal
+    // is the last use of this stream.
+    current_ = buffer_ = nullptr;
+    capacity_ = 0;
+    return old_buffer;
   }
 
  private:
-  uint8_t** const buffer_;
-  uint8_t* end_;
-  uint8_t* current_;
-  intptr_t current_size_;
-  ReAlloc alloc_;
-  intptr_t initial_size_;
+  virtual void Realloc(intptr_t new_size);
 
-  DISALLOW_COPY_AND_ASSIGN(WriteStream);
+  DISALLOW_COPY_AND_ASSIGN(MallocWriteStream);
 };
 
-class StreamingWriteStream : public ValueObject {
+// A non-streaming write stream that uses a zone for reallocation.
+class ZoneWriteStream : public NonStreamingWriteStream {
+ public:
+  ZoneWriteStream(Zone* zone, intptr_t initial_size)
+      : NonStreamingWriteStream(initial_size), zone_(zone) {}
+
+ private:
+  virtual void Realloc(intptr_t new_size);
+
+  Zone* const zone_;
+
+  DISALLOW_COPY_AND_ASSIGN(ZoneWriteStream);
+};
+
+// A streaming write stream that uses the internal buffer only for non-flushed
+// data. Like MallocWriteStream, uses realloc for reallocation, and flushes and
+// frees the internal buffer when destructed. Since part or all of the written
+// data may be flushed and no longer in the internal buffer, it does not provide
+// a way to retrieve the written contents.
+class StreamingWriteStream : public BaseWriteStream {
  public:
   explicit StreamingWriteStream(intptr_t initial_capacity,
                                 Dart_StreamingWriteCallback callback,
-                                void* callback_data);
+                                void* callback_data)
+      : BaseWriteStream(initial_capacity),
+        callback_(callback),
+        callback_data_(callback_data) {}
   ~StreamingWriteStream();
 
-  intptr_t position() const { return flushed_size_ + (cursor_ - buffer_); }
-
-  void Align(intptr_t alignment) {
-    intptr_t padding = Utils::RoundUp(position(), alignment) - position();
-    EnsureAvailable(padding);
-    memset(cursor_, 0, padding);
-    cursor_ += padding;
-  }
-
-  void Print(const char* format, ...) {
-    va_list args;
-    va_start(args, format);
-    VPrint(format, args);
-    va_end(args);
-  }
-  void VPrint(const char* format, va_list args);
-
-  void WriteBytes(const uint8_t* buffer, intptr_t size) {
-    EnsureAvailable(size);
-    if (size != 0) {
-      memmove(cursor_, buffer, size);
-    }
-    cursor_ += size;
-  }
-
  private:
-  void EnsureAvailable(intptr_t needed) {
-    intptr_t available = limit_ - cursor_;
-    if (available >= needed) return;
-    EnsureAvailableSlowPath(needed);
+  // Flushes any unflushed data to callback_data and resets the internal
+  // buffer. Changes current_ and flushed_size_ accordingly.
+  virtual void Flush();
+
+  virtual void Realloc(intptr_t new_size);
+
+  virtual intptr_t Position() const {
+    return flushed_size_ + BaseWriteStream::Position();
   }
 
-  void EnsureAvailableSlowPath(intptr_t needed);
-  void Flush();
+  virtual void SetPosition(intptr_t value) {
+    // Make sure we're not trying to set the position to already-flushed data.
+    ASSERT(value >= flushed_size_);
+    BaseWriteStream::SetPosition(value - flushed_size_);
+  }
 
-  uint8_t* buffer_;
-  uint8_t* cursor_;
-  uint8_t* limit_;
-  intptr_t flushed_size_;
-  Dart_StreamingWriteCallback callback_;
-  void* callback_data_;
+  const Dart_StreamingWriteCallback callback_;
+  void* const callback_data_;
+  intptr_t flushed_size_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(StreamingWriteStream);
 };
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 7f385cb..d9f462b 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -4470,37 +4470,6 @@
   ActivationFrame* frame = TopDartFrame();
   ASSERT(frame != NULL);
 
-  // Since lazy async stacks doesn't use the _asyncStackTraceHelper runtime
-  // entry, we need to manually set a synthetic breakpoint for async_op before
-  // we enter it.
-  if (FLAG_lazy_async_stacks) {
-    // async and async* functions always contain synthetic async_ops.
-    if ((frame->function().IsAsyncFunction() ||
-         frame->function().IsAsyncGenerator())) {
-      ASSERT(!frame->GetSavedCurrentContext().IsNull());
-      ASSERT(frame->GetSavedCurrentContext().num_variables() >
-             Context::kAsyncCompleterIndex);
-
-      const Object& jump_var = Object::Handle(
-          frame->GetSavedCurrentContext().At(Context::kAsyncCompleterIndex));
-
-      // Only set breakpoint when entering async_op the first time.
-      // :async_completer_var should be uninitialised at this point:
-      if (jump_var.IsNull()) {
-        const Function& async_op =
-            Function::Handle(frame->function().GetGeneratedClosure());
-        if (!async_op.IsNull()) {
-          SetBreakpointAtAsyncOp(async_op);
-          // After setting the breakpoint we stop stepping and continue the
-          // debugger until the next breakpoint, to step over all the
-          // synthetic code.
-          Continue();
-          return Error::null();
-        }
-      }
-    }
-  }
-
   if (FLAG_async_debugger) {
     if ((async_stepping_fp_ != 0) && (top_frame_awaiter_ != Object::null())) {
       // Check if the user has single stepped out of an async function with
@@ -4539,6 +4508,37 @@
     }
   }
 
+  // Since lazy async stacks doesn't use the _asyncStackTraceHelper runtime
+  // entry, we need to manually set a synthetic breakpoint for async_op before
+  // we enter it.
+  if (FLAG_lazy_async_stacks) {
+    // async and async* functions always contain synthetic async_ops.
+    if ((frame->function().IsAsyncFunction() ||
+         frame->function().IsAsyncGenerator())) {
+      ASSERT(!frame->GetSavedCurrentContext().IsNull());
+      ASSERT(frame->GetSavedCurrentContext().num_variables() >
+             Context::kAsyncCompleterIndex);
+
+      const Object& async_completer = Object::Handle(
+          frame->GetSavedCurrentContext().At(Context::kAsyncCompleterIndex));
+
+      // Only set breakpoint when entering async_op the first time.
+      // :async_completer_var should be uninitialised at this point:
+      if (async_completer.IsNull()) {
+        const Function& async_op =
+            Function::Handle(frame->function().GetGeneratedClosure());
+        if (!async_op.IsNull()) {
+          SetBreakpointAtAsyncOp(async_op);
+          // After setting the breakpoint we stop stepping and continue the
+          // debugger until the next breakpoint, to step over all the
+          // synthetic code.
+          Continue();
+          return Error::null();
+        }
+      }
+    }
+  }
+
   if (!frame->IsDebuggable()) {
     return Error::null();
   }
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc
index 360929b..f194067 100644
--- a/runtime/vm/deopt_instructions.cc
+++ b/runtime/vm/deopt_instructions.cc
@@ -1231,12 +1231,6 @@
   return -1;
 }
 
-static uint8_t* ZoneReAlloc(uint8_t* ptr,
-                            intptr_t old_size,
-                            intptr_t new_size) {
-  return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size);
-}
-
 TypedDataPtr DeoptInfoBuilder::CreateDeoptInfo(const Array& deopt_table) {
   intptr_t length = instructions_.length();
 
@@ -1260,9 +1254,8 @@
     length -= (suffix_length - 1);
   }
 
-  uint8_t* buffer;
-  typedef WriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
-  WriteStream stream(&buffer, ZoneReAlloc, 2 * length * kWordSize);
+  typedef ZoneWriteStream::Raw<sizeof(intptr_t), intptr_t> Writer;
+  ZoneWriteStream stream(zone(), 2 * length * kWordSize);
 
   Writer::Write(&stream, FrameSize());
 
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index da8bb08..cfafd48 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -115,66 +115,33 @@
     : zone_(zone),
       reverse_obfuscation_trie_(CreateReverseObfuscationTrie(zone)),
       codes_(zone, 1024),
-      code_to_address_(zone),
+      code_to_name_(zone),
       functions_(zone, 1024),
       function_to_index_(zone),
       scripts_(zone, 1024),
       script_to_index_(zone),
       temp_(0) {}
 
-SegmentRelativeOffset Dwarf::CodeAddress(const Code& code) const {
-  const auto& pair = code_to_address_.LookupValue(&code);
-  // This is only used by Elf::Finalize(), and the image writers always give a
-  // text offset when calling AddCode() for an Elf object's Dwarf object. Thus,
-  // we should have known code offsets for each code object in the map.
-  ASSERT(pair.offset != SegmentRelativeOffset::kUnknownOffset);
-  return pair;
-}
-
-intptr_t Dwarf::AddCode(const Code& orig_code,
-                        const SegmentRelativeOffset& offset) {
+void Dwarf::AddCode(const Code& orig_code, const char* name) {
   ASSERT(!orig_code.IsNull());
-  // We should never get the no-argument constructed version here.
-  ASSERT(offset.offset != SegmentRelativeOffset::kInvalidOffset);
-  // Generate an appropriately zoned ZoneHandle for storing.
-  const auto& code = Code::ZoneHandle(zone_, orig_code.raw());
+  ASSERT(name != nullptr);
 
-  // For now, we assume one of two flows for a given code object:
-  // ELF: Calls to AddCode(code, vm, offset), vm and offset are the same over
-  //      all calls.
-  // Assembly: An initial call to AddCode(code, vm) (assembly), possibly
-  //     followed by a later call to AddCode(code, vm, offset)
-  //     (separate debugging info ELF)
-  if (offset.offset == SegmentRelativeOffset::kUnknownOffset) {
-    // A call without an address should always come before any calls with
-    // addresses.
-    ASSERT(code_to_address_.Lookup(&code) == nullptr);
-    // Insert a marker so on later calls, we know we've already added to codes_.
-    code_to_address_.Insert(CodeAddressPair(&code, offset));
-  } else {
-    const auto& old_value = code_to_address_.LookupValue(&code);
-    // ELF does not need to know the index. If we've already added this Code
-    // object to codes_ in a previous call, don't bother scanning codes_ to find
-    // the corresponding index, just return -1 instead.
-    switch (old_value.offset) {
-      case SegmentRelativeOffset::kInvalidOffset:
-        code_to_address_.Insert(CodeAddressPair(&code, offset));
-        break;  // Still need to add to codes_.
-      case SegmentRelativeOffset::kUnknownOffset:
-        // Code objects should only be associated with either the VM or isolate.
-        ASSERT_EQUAL(old_value.vm, offset.vm);
-        code_to_address_.Update(CodeAddressPair(&code, offset));
-        return -1;
-      default:
-        // The information for the code object shouldn't have changed since the
-        // previous update.
-        ASSERT(old_value == offset);
-        return -1;
-    }
+  if (auto const old_pair = code_to_name_.Lookup(&orig_code)) {
+    // Dwarf objects can be shared, so we may get the same information for a
+    // given code object in different calls. In DEBUG mode, make sure the
+    // information is the same before returning.
+    ASSERT(old_pair->value != nullptr);
+    ASSERT_EQUAL(strcmp(old_pair->value, name), 0);
+    return;
   }
 
-  const intptr_t index = codes_.length();
+  // Generate an appropriately zoned ZoneHandle for storing.
+  const auto& code = Code::ZoneHandle(zone_, orig_code.raw());
   codes_.Add(&code);
+  // Currently assumes the name has the same lifetime as the Zone of the
+  // Dwarf object (which is currently true).  Otherwise, need to copy.
+  code_to_name_.Insert({&code, name});
+
   if (code.IsFunctionCode()) {
     const Function& function = Function::Handle(zone_, code.function());
     AddFunction(function);
@@ -188,7 +155,6 @@
       AddFunction(function);
     }
   }
-  return index;
 }
 
 intptr_t Dwarf::AddFunction(const Function& function) {
@@ -309,8 +275,6 @@
 }
 
 void Dwarf::WriteDebugInfo(DwarfWriteStream* stream) {
-  SnapshotTextObjectNamer namer(zone_);
-
   // 7.5.1.1 Compilation Unit Header
 
   // Unit length.
@@ -343,10 +307,15 @@
   // The highest instruction address in this object file that is part of our
   // compilation unit. Dwarf consumers use this to quickly decide which
   // compilation unit DIE to consult for a given pc.
-  intptr_t last_code_index = codes_.length() - 1;
-  const Code& last_code = *(codes_[last_code_index]);
-  auto const last_code_name = namer.SnapshotNameFor(last_code_index, last_code);
-  stream->OffsetFromSymbol(last_code_name, last_code.Size());
+  if (codes_.is_empty()) {
+    // No code objects in this program, so set high_pc to same as low_pc.
+    stream->OffsetFromSymbol(kIsolateSnapshotInstructionsAsmSymbol, 0);
+  } else {
+    const Code& last_code = *codes_.Last();
+    auto const last_code_name = code_to_name_.LookupValue(&last_code);
+    ASSERT(last_code_name != nullptr);
+    stream->OffsetFromSymbol(last_code_name, last_code.Size());
+  }
 
   // DW_AT_stmt_list (offset into .debug_line)
   // Indicates which line number program is associated with this compilation
@@ -388,7 +357,6 @@
 void Dwarf::WriteConcreteFunctions(DwarfWriteStream* stream) {
   Function& function = Function::Handle(zone_);
   Script& script = Script::Handle(zone_);
-  SnapshotTextObjectNamer namer(zone_);
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
     RELEASE_ASSERT(!code.IsNull());
@@ -399,7 +367,8 @@
     function = code.function();
     intptr_t function_index = LookupFunction(function);
     script = function.script();
-    const char* asm_name = namer.SnapshotNameFor(i, code);
+    const char* asm_name = code_to_name_.LookupValue(&code);
+    ASSERT(asm_name != nullptr);
 
     stream->uleb128(kConcreteFunction);
     // DW_AT_abstract_origin
@@ -415,7 +384,7 @@
     if (node != NULL) {
       for (InliningNode* child = node->children_head; child != NULL;
            child = child->children_next) {
-        WriteInliningNode(stream, child, asm_name, script, &namer);
+        WriteInliningNode(stream, child, asm_name, script);
       }
     }
 
@@ -514,8 +483,7 @@
 void Dwarf::WriteInliningNode(DwarfWriteStream* stream,
                               InliningNode* node,
                               const char* root_asm_name,
-                              const Script& parent_script,
-                              SnapshotTextObjectNamer* namer) {
+                              const Script& parent_script) {
   intptr_t file = LookupScript(parent_script);
   intptr_t function_index = LookupFunction(node->function);
   const Script& script = Script::Handle(zone_, node->function.script());
@@ -538,7 +506,7 @@
 
   for (InliningNode* child = node->children_head; child != NULL;
        child = child->children_next) {
-    WriteInliningNode(stream, child, root_asm_name, script, namer);
+    WriteInliningNode(stream, child, root_asm_name, script);
   }
 
   stream->uleb128(0);  // End of children.
@@ -617,11 +585,11 @@
   Array& functions = Array::Handle(zone_);
   GrowableArray<const Function*> function_stack(zone_, 8);
   GrowableArray<DwarfPosition> token_positions(zone_, 8);
-  SnapshotTextObjectNamer namer(zone_);
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
     const Code& code = *(codes_[i]);
-    auto const asm_name = namer.SnapshotNameFor(i, code);
+    auto const asm_name = code_to_name_.LookupValue(&code);
+    ASSERT(asm_name != nullptr);
 
     map = code.code_source_map();
     if (map.IsNull()) {
@@ -731,8 +699,8 @@
     const intptr_t last_code_index = codes_.length() - 1;
     const Code& last_code = *(codes_[last_code_index]);
     const intptr_t last_pc_offset = last_code.Size();
-    const char* last_asm_name =
-        namer.SnapshotNameFor(last_code_index, last_code);
+    const char* last_asm_name = code_to_name_.LookupValue(&last_code);
+    ASSERT(last_asm_name != nullptr);
 
     stream->u1(DW_LNS_advance_pc);
     if (previous_asm_name != nullptr) {
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index 65d612c..22df262 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -6,6 +6,7 @@
 #define RUNTIME_VM_DWARF_H_
 
 #include "vm/allocation.h"
+#include "vm/hash.h"
 #include "vm/hash_map.h"
 #include "vm/object.h"
 #include "vm/zone.h"
@@ -15,7 +16,6 @@
 #ifdef DART_PRECOMPILER
 
 class InliningNode;
-class SnapshotTextObjectNamer;
 
 struct ScriptIndexPair {
   // Typedefs needed for the DirectChainedHashMap template.
@@ -82,64 +82,46 @@
 
 typedef DirectChainedHashMap<FunctionIndexPair> FunctionIndexMap;
 
-struct SegmentRelativeOffset {
-  // Used for the empty constructor (for hash map usage).
-  static constexpr intptr_t kInvalidOffset = -2;
-  // Used for cases where we know which segment, but don't know the offset.
-  static constexpr intptr_t kUnknownOffset = -1;
-
-  SegmentRelativeOffset(bool vm, intptr_t offset) : vm(vm), offset(offset) {
-    ASSERT(offset >= 0);
-  }
-  explicit SegmentRelativeOffset(bool vm) : vm(vm), offset(kUnknownOffset) {}
-  SegmentRelativeOffset() : vm(false), offset(kInvalidOffset) {}
-
-  bool operator==(const SegmentRelativeOffset& b) const {
-    return vm == b.vm && offset == b.offset;
-  }
-  bool operator==(const SegmentRelativeOffset& b) {
-    return *const_cast<const SegmentRelativeOffset*>(this) == b;
-  }
-  bool operator!=(const SegmentRelativeOffset& b) { return !(*this == b); }
-
-  // Whether or not this is an offset into the VM text segment.
-  bool vm;
-  // The byte offset into the segment contents.
-  intptr_t offset;
-};
-
-struct CodeAddressPair {
+// Assumes T has a copy constructor and is CopyAssignable.
+template <typename T>
+struct DwarfCodeKeyValueTrait {
   // Typedefs needed for the DirectChainedHashMap template.
   typedef const Code* Key;
-  typedef SegmentRelativeOffset Value;
-  typedef CodeAddressPair Pair;
+  typedef T Value;
+
+  struct Pair {
+    Pair(const Code* c, const T v) : code(c), value(v) {
+      ASSERT(c != nullptr);
+      ASSERT(!c->IsNull());
+      ASSERT(c->IsNotTemporaryScopedHandle());
+    }
+    Pair() : code(nullptr), value{} {}
+
+    // Don't implcitly delete copy and copy assigment constructors.
+    Pair(const Pair& other) = default;
+    Pair& operator=(const Pair& other) = default;
+
+    const Code* code;
+    T value;
+  };
 
   static Key KeyOf(Pair kv) { return kv.code; }
 
-  static Value ValueOf(Pair kv) { return kv.segment_offset; }
+  static Value ValueOf(Pair kv) { return kv.value; }
 
   static inline intptr_t Hashcode(Key key) {
-    // Code objects are always allocated in old space, so they don't move.
-    return key->PayloadStart();
+    // Instructions are always allocated in old space, so they don't move.
+    return FinalizeHash(key->PayloadStart(), 32);
   }
 
   static inline bool IsKeyEqual(Pair pair, Key key) {
+    // Code objects are always allocated in old space, so they don't move.
     return pair.code->raw() == key->raw();
   }
-
-  CodeAddressPair(const Code* c, const SegmentRelativeOffset& o)
-      : code(c), segment_offset(o) {
-    ASSERT(!c->IsNull());
-    ASSERT(c->IsNotTemporaryScopedHandle());
-    ASSERT(o.offset == SegmentRelativeOffset::kUnknownOffset || o.offset >= 0);
-  }
-  CodeAddressPair() : code(nullptr), segment_offset() {}
-
-  const Code* code;
-  SegmentRelativeOffset segment_offset;
 };
 
-typedef DirectChainedHashMap<CodeAddressPair> CodeAddressMap;
+template <typename T>
+using DwarfCodeMap = DirectChainedHashMap<DwarfCodeKeyValueTrait<T>>;
 
 template <typename T>
 class Trie : public ZoneAllocated {
@@ -256,15 +238,7 @@
   const ZoneGrowableArray<const Code*>& codes() const { return codes_; }
 
   // Stores the code object for later creating the line number program.
-  //
-  // Returns the stored index of the code object when the relocated address
-  // is not known at snapshot generation time (that is, when offset.offset is
-  // SegmentRelativeOffset::kUnknownOffset).
-  intptr_t AddCode(const Code& code, const SegmentRelativeOffset& offset);
-
-  // Returns the stored segment offset for the given Code object. If no
-  // address is stored, the second element will be kNoCodeAddressPairOffset.
-  SegmentRelativeOffset CodeAddress(const Code& code) const;
+  void AddCode(const Code& code, const char* name);
 
   intptr_t AddFunction(const Function& function);
   intptr_t AddScript(const Script& script);
@@ -331,8 +305,7 @@
   void WriteInliningNode(DwarfWriteStream* stream,
                          InliningNode* node,
                          const char* root_code_name,
-                         const Script& parent_script,
-                         SnapshotTextObjectNamer* namer);
+                         const Script& parent_script);
 
   const char* Deobfuscate(const char* cstr);
   static Trie<const char>* CreateReverseObfuscationTrie(Zone* zone);
@@ -340,7 +313,7 @@
   Zone* const zone_;
   Trie<const char>* const reverse_obfuscation_trie_;
   ZoneGrowableArray<const Code*> codes_;
-  CodeAddressMap code_to_address_;
+  DwarfCodeMap<const char*> code_to_name_;
   ZoneGrowableArray<const Function*> functions_;
   FunctionIndexMap function_to_index_;
   ZoneGrowableArray<const Script*> scripts_;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index 606ef61..138d02e 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -14,14 +14,14 @@
 
 namespace dart {
 
-// A wrapper around StreamingWriteStream that provides methods useful for
+// A wrapper around BaseWriteStream that provides methods useful for
 // writing ELF files (e.g., using ELF definitions of data sizes).
 class ElfWriteStream : public ValueObject {
  public:
-  explicit ElfWriteStream(StreamingWriteStream* stream)
+  explicit ElfWriteStream(BaseWriteStream* stream)
       : stream_(ASSERT_NOTNULL(stream)) {}
 
-  intptr_t position() const { return stream_->position(); }
+  intptr_t Position() const { return stream_->Position(); }
   void Align(const intptr_t alignment) {
     ASSERT(Utils::IsPowerOfTwo(alignment));
     stream_->Align(alignment);
@@ -29,29 +29,17 @@
   void WriteBytes(const uint8_t* b, intptr_t size) {
     stream_->WriteBytes(b, size);
   }
-  void WriteByte(uint8_t value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
-  void WriteHalf(uint16_t value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
-  void WriteWord(uint32_t value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
-  void WriteAddr(compiler::target::uword value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
-  void WriteOff(compiler::target::uword value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
+  void WriteByte(uint8_t value) { stream_->WriteByte(value); }
+  void WriteHalf(uint16_t value) { stream_->WriteFixed(value); }
+  void WriteWord(uint32_t value) { stream_->WriteFixed(value); }
+  void WriteAddr(compiler::target::uword value) { stream_->WriteFixed(value); }
+  void WriteOff(compiler::target::uword value) { stream_->WriteFixed(value); }
 #if defined(TARGET_ARCH_IS_64_BIT)
-  void WriteXWord(uint64_t value) {
-    stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
-  }
+  void WriteXWord(uint64_t value) { stream_->WriteFixed(value); }
 #endif
 
  private:
-  StreamingWriteStream* const stream_;
+  BaseWriteStream* const stream_;
 };
 
 static constexpr intptr_t kLinearInitValue = -1;
@@ -108,10 +96,6 @@
   intptr_t info = 0;
   intptr_t entry_size = 0;
 
-  // Stores the name for the symbol that should be created in the dynamic (and
-  // static, if unstripped) tables for this section.
-  const char* symbol_name = nullptr;
-
 #define FOR_EACH_SECTION_LINEAR_FIELD(M)                                       \
   M(name)                                                                      \
   M(index)                                                                     \
@@ -127,7 +111,7 @@
   FOR_EACH_SEGMENT_LINEAR_FIELD(DEFINE_LINEAR_FIELD_METHODS);
 
   // Each section belongs to at most one PT_LOAD segment.
-  const Segment* load_segment = nullptr;
+  Segment* load_segment = nullptr;
 
   virtual intptr_t MemorySize() const = 0;
 
@@ -234,6 +218,9 @@
     // a memory offset since we use it to determine the segment memory offset.
     ASSERT(initial_section->IsAllocated());
     ASSERT(initial_section->memory_offset_is_set());
+    // Make sure the memory offset chosen for the initial section is consistent
+    // with the alignment for the segment.
+    ASSERT(Utils::IsAligned(initial_section->memory_offset(), Alignment(type)));
     sections_.Add(initial_section);
     if (type == elf::ProgramHeaderType::PT_LOAD) {
       ASSERT(initial_section->load_segment == nullptr);
@@ -245,6 +232,7 @@
 
   static intptr_t Alignment(elf::ProgramHeaderType segment_type) {
     switch (segment_type) {
+      case elf::ProgramHeaderType::PT_PHDR:
       case elf::ProgramHeaderType::PT_DYNAMIC:
         return compiler::target::kWordSize;
       case elf::ProgramHeaderType::PT_NOTE:
@@ -319,6 +307,30 @@
     return true;
   }
 
+  void Replace(Section* old_section, Section* new_section) {
+    ASSERT(old_section->load_segment == this);
+    // All these must be true for replacement to be safe.
+    ASSERT_EQUAL(static_cast<uint32_t>(old_section->type),
+                 static_cast<uint32_t>(new_section->type));
+    ASSERT_EQUAL(old_section->MemorySize(), new_section->MemorySize());
+    ASSERT_EQUAL(old_section->IsExecutable(), new_section->IsExecutable());
+    ASSERT_EQUAL(old_section->IsWritable(), new_section->IsWritable());
+    ASSERT(old_section->memory_offset_is_set());
+    ASSERT(!new_section->memory_offset_is_set());
+    for (intptr_t i = 0; i < sections_.length(); i++) {
+      auto const section = sections_[i];
+      if (section != old_section) {
+        continue;
+      }
+      new_section->set_memory_offset(old_section->memory_offset());
+      sections_[i] = new_section;
+      new_section->load_segment = this;
+      old_section->load_segment = nullptr;
+      return;
+    }
+    UNREACHABLE();
+  }
+
   intptr_t FileOffset() const { return sections_[0]->file_offset(); }
 
   intptr_t FileSize() const {
@@ -477,17 +489,17 @@
                       alignment) {}
 
   // For BitsContainers used as segments whose type differ on the type of the
-  // ELF file. Creates an elf::SHT_NOBITS section if type is DebugInfo,
-  // otherwise creates an elf::SHT_PROGBITS section.
+  // ELF file. Creates an elf::SHT_PROGBITS section if type is Snapshot,
+  // otherwise creates an elf::SHT_NOBITS section.
   BitsContainer(Elf::Type t,
                 bool executable,
                 bool writable,
                 intptr_t size,
                 const uint8_t* bytes,
                 intptr_t alignment = kDefaultAlignment)
-      : BitsContainer(t == Elf::Type::DebugInfo
-                          ? elf::SectionHeaderType::SHT_NOBITS
-                          : elf::SectionHeaderType::SHT_PROGBITS,
+      : BitsContainer(t == Elf::Type::Snapshot
+                          ? elf::SectionHeaderType::SHT_PROGBITS
+                          : elf::SectionHeaderType::SHT_NOBITS,
                       /*allocate=*/true,
                       executable,
                       writable,
@@ -536,6 +548,7 @@
   }
 
   intptr_t AddString(const char* str) {
+    ASSERT(str != nullptr);
     if (auto const kv = text_indices_.Lookup(str)) return kv->value - 1;
     intptr_t offset = text_.length();
     text_.AddString(str);
@@ -562,38 +575,41 @@
  public:
   Symbol(const char* cstr,
          intptr_t name,
-         intptr_t info,
+         intptr_t binding,
+         intptr_t type,
          intptr_t section,
          intptr_t offset,
          intptr_t size)
       : name_index(name),
-        info(info),
+        binding(binding),
+        type(type),
         section_index(section),
         offset(offset),
         size(size),
         cstr_(cstr) {}
 
   void Write(ElfWriteStream* stream) const {
-    const intptr_t start = stream->position();
+    const intptr_t start = stream->Position();
     stream->WriteWord(name_index);
 #if defined(TARGET_ARCH_IS_32_BIT)
     stream->WriteAddr(offset);
     stream->WriteWord(size);
-    stream->WriteByte(info);
+    stream->WriteByte(elf::SymbolInfo(binding, type));
     stream->WriteByte(0);
     stream->WriteHalf(section_index);
 #else
-    stream->WriteByte(info);
+    stream->WriteByte(elf::SymbolInfo(binding, type));
     stream->WriteByte(0);
     stream->WriteHalf(section_index);
     stream->WriteAddr(offset);
     stream->WriteXWord(size);
 #endif
-    ASSERT_EQUAL(stream->position() - start, sizeof(elf::Symbol));
+    ASSERT_EQUAL(stream->Position() - start, sizeof(elf::Symbol));
   }
 
   const intptr_t name_index;
-  const intptr_t info;
+  const intptr_t binding;
+  const intptr_t type;
   const intptr_t section_index;
   const intptr_t offset;
   const intptr_t size;
@@ -606,19 +622,22 @@
 
 class SymbolTable : public Section {
  public:
-  SymbolTable(Zone* zone, bool dynamic)
+  SymbolTable(Zone* zone, StringTable* table, bool dynamic)
       : Section(dynamic ? elf::SectionHeaderType::SHT_DYNSYM
                         : elf::SectionHeaderType::SHT_SYMTAB,
                 dynamic,
                 /*executable=*/false,
                 /*writable=*/false),
+        zone_(zone),
+        table_(table),
         dynamic_(dynamic),
-        reserved_("", 0, 0, 0, 0, 0),
-        symbols_(zone, 1) {
+        symbols_(zone, 1),
+        by_name_index_(zone) {
     entry_size = sizeof(elf::Symbol);
     // The first symbol table entry is reserved and must be all zeros.
-    symbols_.Add(&reserved_);
-    info = 1;  // One "local" symbol, the reserved first entry.
+    // (String tables always have the empty string at the 0th index.)
+    AddSymbol("", elf::STB_LOCAL, elf::STT_NOTYPE, elf::SHN_UNDEF, /*offset=*/0,
+              /*size=*/0);
   }
 
   intptr_t FileSize() const { return Length() * entry_size; }
@@ -627,28 +646,55 @@
   void Write(ElfWriteStream* stream) {
     for (intptr_t i = 0; i < Length(); i++) {
       auto const symbol = At(i);
-      const intptr_t start = stream->position();
+      const intptr_t start = stream->Position();
       symbol->Write(stream);
-      ASSERT_EQUAL(stream->position() - start, entry_size);
+      ASSERT_EQUAL(stream->Position() - start, entry_size);
     }
   }
 
-  void AddSymbol(const Symbol* symbol) { symbols_.Add(symbol); }
+  void AddSymbol(const char* name,
+                 intptr_t binding,
+                 intptr_t type,
+                 intptr_t section_index,
+                 intptr_t offset,
+                 intptr_t size) {
+    ASSERT(!table_->HasBeenFinalized());
+    auto const name_index = table_->AddString(name);
+    ASSERT(by_name_index_.Lookup(name_index) == nullptr);
+    auto const symbol = new (zone_)
+        Symbol(name, name_index, binding, type, section_index, offset, size);
+    symbols_.Add(symbol);
+    by_name_index_.Insert(name_index, symbol);
+    // The info field on a symbol table section holds the index of the first
+    // non-local symbol, so they can be skipped if desired. Thus, we need to
+    // make sure local symbols are before any non-local ones.
+    if (binding == elf::STB_LOCAL) {
+      if (info != symbols_.length() - 1) {
+        // There are non-local symbols, as otherwise [info] would be the
+        // index of the new symbol. Since the order doesn't otherwise matter,
+        // swap the new local symbol with the value at index [info], so when
+        // [info] is incremented it will point just past the new local symbol.
+        ASSERT(symbols_[info]->binding != elf::STB_LOCAL);
+        symbols_.Swap(info, symbols_.length() - 1);
+      }
+      info += 1;
+    }
+  }
   intptr_t Length() const { return symbols_.length(); }
   const Symbol* At(intptr_t i) const { return symbols_[i]; }
 
-  const Symbol* FindSymbolWithNameIndex(intptr_t name_index) const {
-    for (intptr_t i = 0; i < Length(); i++) {
-      auto const symbol = At(i);
-      if (symbol->name_index == name_index) return symbol;
-    }
-    return nullptr;
+  const Symbol* Find(const char* name) const {
+    ASSERT(name != nullptr);
+    auto const name_index = table_->Lookup(name);
+    return by_name_index_.Lookup(name_index);
   }
 
  private:
+  Zone* const zone_;
+  StringTable* const table_;
   const bool dynamic_;
-  const Symbol reserved_;
   GrowableArray<const Symbol*> symbols_;
+  mutable IntMap<const Symbol*> by_name_index_;
 };
 
 static uint32_t ElfHash(const unsigned char* name) {
@@ -749,7 +795,7 @@
     Entry(elf::DynamicEntryType tag, intptr_t value) : tag(tag), value(value) {}
 
     void Write(ElfWriteStream* stream) {
-      const intptr_t start = stream->position();
+      const intptr_t start = stream->Position();
 #if defined(TARGET_ARCH_IS_32_BIT)
       stream->WriteWord(static_cast<uint32_t>(tag));
       stream->WriteAddr(value);
@@ -757,7 +803,7 @@
       stream->WriteXWord(static_cast<uint64_t>(tag));
       stream->WriteAddr(value);
 #endif
-      ASSERT_EQUAL(stream->position() - start, sizeof(elf::DynamicEntry));
+      ASSERT_EQUAL(stream->Position() - start, sizeof(elf::DynamicEntry));
     }
 
     elf::DynamicEntryType tag;
@@ -792,7 +838,8 @@
   }
 };
 
-static const intptr_t kProgramTableSegmentSize = Elf::kPageSize;
+// We assume that the final program table fits in a single page of memory.
+static constexpr intptr_t kProgramTableSegmentSize = Elf::kPageSize;
 
 // Here, both VM and isolate will be compiled into a single snapshot.
 // In assembly generation, each serialized text section gets a separate
@@ -800,13 +847,29 @@
 // we may not serialize both VM and isolate. Here, we always serialize both,
 // so make a BSS segment large enough for both, with the VM entries coming
 // first.
-static constexpr const char* kSnapshotBssAsmSymbol = "_kDartBSSData";
-static const intptr_t kBssIsolateOffset =
+static constexpr intptr_t kBssVmSize =
     BSS::kVmEntryCount * compiler::target::kWordSize;
-static const intptr_t kBssSize =
-    kBssIsolateOffset + BSS::kIsolateEntryCount * compiler::target::kWordSize;
+static constexpr intptr_t kBssIsolateSize =
+    BSS::kIsolateEntryCount * compiler::target::kWordSize;
+static constexpr intptr_t kBssSize = kBssVmSize + kBssIsolateSize;
 
-Elf::Elf(Zone* zone, StreamingWriteStream* stream, Type type, Dwarf* dwarf)
+// For the build ID, we generate a 128-bit hash, where each 32 bits is a hash of
+// the contents of the following segments in order:
+//
+// .text(VM) | .text(Isolate) | .rodata(VM) | .rodata(Isolate)
+static constexpr const char* kBuildIdSegmentNames[]{
+    kVmSnapshotInstructionsAsmSymbol,
+    kIsolateSnapshotInstructionsAsmSymbol,
+    kVmSnapshotDataAsmSymbol,
+    kIsolateSnapshotDataAsmSymbol,
+};
+static constexpr intptr_t kBuildIdSegmentNamesLength =
+    ARRAY_SIZE(kBuildIdSegmentNames);
+// Includes the note name, but not the description.
+static constexpr intptr_t kBuildIdHeaderSize =
+    sizeof(elf::Note) + sizeof(elf::ELF_NOTE_GNU);
+
+Elf::Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf)
     : zone_(zone),
       unwrapped_stream_(stream),
       type_(type),
@@ -814,18 +877,18 @@
       bss_(CreateBSS(zone, type, kBssSize)),
       shstrtab_(new (zone) StringTable(zone, /*allocate=*/false)),
       dynstrtab_(new (zone) StringTable(zone, /*allocate=*/true)),
-      dynsym_(new (zone) SymbolTable(zone, /*dynamic=*/true)) {
+      dynsym_(new (zone) SymbolTable(zone, dynstrtab_, /*dynamic=*/true)) {
   // Separate debugging information should always have a Dwarf object.
   ASSERT(type_ == Type::Snapshot || dwarf_ != nullptr);
   // Assumed by various offset logic in this file.
-  ASSERT_EQUAL(unwrapped_stream_->position(), 0);
+  ASSERT_EQUAL(unwrapped_stream_->Position(), 0);
   // The first section in the section header table is always a reserved
   // entry containing only 0 values.
   sections_.Add(new (zone_) ReservedSection());
   if (!IsStripped()) {
     // Not a stripped ELF file, so allocate static string and symbol tables.
     strtab_ = new (zone_) StringTable(zone_, /* allocate= */ false);
-    symtab_ = new (zone_) SymbolTable(zone, /*dynamic=*/false);
+    symtab_ = new (zone_) SymbolTable(zone, strtab_, /*dynamic=*/false);
   }
   // We add an initial segment to represent reserved space for the program
   // header, and so we can always assume there's at least one segment in the
@@ -834,22 +897,73 @@
   auto const start_segment =
       new (zone_) ProgramTableLoadSegment(zone_, kProgramTableSegmentSize);
   segments_.Add(start_segment);
-  // Note that the BSS segment must be the first user-defined segment because
+  // We allocate an initial build ID of all zeroes, since we need the build ID
+  // memory offset for the InstructionsSection (see BlobImageWriter::WriteText).
+  // We replace it with the real build ID during finalization. (We add this
+  // prior to BSS because we make the BuildID section writable also, so they are
+  // placed in the same segment before any non-writable ones, and if we add it
+  // after, then in separate debugging information, it'll go into a separate
+  // segment because the BSS section for debugging info is NOBITS.)
+  {
+    uint32_t zeroes[kBuildIdSegmentNamesLength] = {0};
+    build_id_ = CreateBuildIdNote(&zeroes, sizeof(zeroes));
+    AddSection(build_id_, kBuildIdNoteName, kSnapshotBuildIdAsmSymbol);
+  }
+  // Note that the BSS segment must be in the first user-defined segment because
   // it cannot be placed in between any two non-writable segments, due to a bug
-  // in Jelly Bean's ELF loader. See also Elf::WriteProgramTable().
+  // in Jelly Bean's ELF loader. (For this reason, the program table segments
+  // generated during finalization are marked as writable.) See also
+  // Elf::WriteProgramTable().
   //
   // We add it in all cases, even to the separate debugging information ELF,
   // to ensure that relocated addresses are consistent between ELF snapshots
   // and ELF separate debugging information.
-  AddSection(bss_, ".bss", kSnapshotBssAsmSymbol);
+  auto const bss_start = AddSection(bss_, ".bss");
+  // For the BSS section, we add two local symbols to the static symbol table,
+  // one for each isolate. We use local symbols because these addresses are only
+  // used for relocation. (This matches the behavior in the assembly output,
+  // where these symbols are also local.)
+  AddStaticSymbol(kVmSnapshotBssAsmSymbol, elf::STB_LOCAL, elf::STT_SECTION,
+                  bss_->index(), bss_start, kBssVmSize);
+  AddStaticSymbol(kIsolateSnapshotBssAsmSymbol, elf::STB_LOCAL,
+                  elf::STT_SECTION, bss_->index(), bss_start + kBssVmSize,
+                  kBssIsolateSize);
 }
 
-intptr_t Elf::NextMemoryOffset() const {
-  return Utils::RoundUp(LastLoadSegment()->MemoryEnd(), Elf::kPageSize);
+intptr_t Elf::NextMemoryOffset(intptr_t alignment) const {
+  // Without more information, we won't know whether we might create a new
+  // segment or put the section into the current one. Thus, for now, only allow
+  // the offset to be queried ahead of time if it matches the load segment
+  // alignment.
+  auto const type = elf::ProgramHeaderType::PT_LOAD;
+  ASSERT_EQUAL(alignment, Segment::Alignment(type));
+  return Utils::RoundUp(LastLoadSegment()->MemoryEnd(), alignment);
 }
 
-uword Elf::BssStart(bool vm) const {
-  return bss_->memory_offset() + (vm ? 0 : kBssIsolateOffset);
+uword Elf::SymbolAddress(const char* name) const {
+  ASSERT(name != nullptr);
+  // Check the static symbol table first if it exists, since the dynamic
+  // table is a subset of it. Fall back on the dynamic otherwise.
+  if (symtab_ != nullptr) {
+    if (auto const symbol = symtab_->Find(name)) {
+      return symbol->offset;
+    }
+  } else if (auto const symbol = dynsym_->Find(name)) {
+    return symbol->offset;
+  }
+  // If stripping, then we won't have symbols for the BSS sections because
+  // they're only added to the static symbol table. Check for these special
+  // cases before returning kNoSectionStart.
+  if (strcmp(name, kVmSnapshotBssAsmSymbol) == 0) {
+    ASSERT(bss_ != nullptr);
+    ASSERT(bss_->memory_offset_is_set());
+    return bss_->memory_offset();
+  } else if (strcmp(name, kIsolateSnapshotBssAsmSymbol) == 0) {
+    ASSERT(bss_ != nullptr);
+    ASSERT(bss_->memory_offset_is_set());
+    return bss_->memory_offset() + kBssVmSize;
+  }
+  return kNoSectionStart;
 }
 
 intptr_t Elf::AddSection(Section* section,
@@ -870,31 +984,52 @@
     // We can't add this section to the last load segment, so create a new one.
     // The new segment starts at the next aligned address.
     auto const type = elf::ProgramHeaderType::PT_LOAD;
+    intptr_t alignment =
+        Utils::Maximum(section->alignment, Segment::Alignment(type));
     auto const start_address =
-        Utils::RoundUp(last_load->MemoryEnd(), Segment::Alignment(type));
+        Utils::RoundUp(last_load->MemoryEnd(), alignment);
     section->set_memory_offset(start_address);
     auto const segment = new (zone_) Segment(zone_, section, type);
     segments_.Add(segment);
   }
   if (symbol_name != nullptr) {
-    section->symbol_name = symbol_name;
+    // While elf::STT_SECTION might seem more appropriate, section symbols are
+    // usually local and dlsym won't return them.
+    AddDynamicSymbol(symbol_name, elf::STB_GLOBAL, elf::STT_FUNC,
+                     section->index(), section->memory_offset(),
+                     section->MemorySize());
   }
   return section->memory_offset();
 }
 
+void Elf::ReplaceSection(Section* old_section, Section* new_section) {
+  ASSERT(section_table_file_size_ < 0);
+  ASSERT(old_section->index_is_set());
+  ASSERT(!new_section->index_is_set());
+  ASSERT_EQUAL(new_section->IsAllocated(), old_section->IsAllocated());
+  new_section->set_name(old_section->name());
+  new_section->set_index(old_section->index());
+  sections_[old_section->index()] = new_section;
+
+  if (!old_section->IsAllocated()) {
+    return;
+  }
+
+  ASSERT(program_table_file_size_ < 0);
+  ASSERT(old_section->load_segment != nullptr);
+  old_section->load_segment->Replace(old_section, new_section);
+}
+
 intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
-  // When making a separate debugging info file for assembly, we don't have
-  // the binary text segment contents.
-  ASSERT(type_ == Type::DebugInfo || bytes != nullptr);
-  auto const image = new (zone_)
-      BitsContainer(type_, /*executable=*/true,
-                    /*writable=*/false, size, bytes, Elf::kPageSize);
+  auto const image = new (zone_) BitsContainer(type_, /*executable=*/true,
+                                               /*writable=*/false, size, bytes,
+                                               ImageWriter::kTextAlignment);
   return AddSection(image, ".text", name);
 }
 
 Section* Elf::CreateBSS(Zone* zone, Type type, intptr_t size) {
   uint8_t* bytes = nullptr;
-  if (type != Type::DebugInfo) {
+  if (type == Type::Snapshot) {
     // Ideally the BSS segment would take no space in the object, but Android's
     // "strip" utility truncates the memory-size of our segments to their
     // file-size.
@@ -904,14 +1039,13 @@
     memset(bytes, 0, size);
   }
   return new (zone) BitsContainer(type, /*executable=*/false, /*writable=*/true,
-                                  kBssSize, bytes, Image::kBssAlignment);
+                                  kBssSize, bytes, ImageWriter::kBssAlignment);
 }
 
 intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) {
-  ASSERT(bytes != nullptr);
-  auto const image = new (zone_)
-      BitsContainer(type_, /*executable=*/false,
-                    /*writable=*/false, size, bytes, kMaxObjectAlignment);
+  auto const image = new (zone_) BitsContainer(type_, /*executable=*/false,
+                                               /*writable=*/false, size, bytes,
+                                               ImageWriter::kRODataAlignment);
   return AddSection(image, ".rodata", name);
 }
 
@@ -923,112 +1057,91 @@
   AddSection(image, name);
 }
 
+void Elf::AddLocalSymbol(const char* name,
+                         intptr_t type,
+                         intptr_t offset,
+                         intptr_t size) {
+  const intptr_t section_index = sections_.length();
+  // Assume the next section will go into its own segment (currently true
+  // because we write writable sections, data vm (non-writable, non-executable),
+  // text vm (executable), data isolate (non-executable), text isolate
+  // (executable), and we only call this for data and text sections).
+  const intptr_t address =
+      NextMemoryOffset(ImageWriter::kTextAlignment) + offset;
+  AddStaticSymbol(name, elf::STB_LOCAL, type, section_index, address, size);
+}
+
 void Elf::AddDynamicSymbol(const char* name,
-                           intptr_t info,
+                           intptr_t binding,
+                           intptr_t type,
                            intptr_t section_index,
                            intptr_t address,
                            intptr_t size) {
-  ASSERT(!dynstrtab_->HasBeenFinalized() && !dynsym_->HasBeenFinalized());
-  auto const name_index = dynstrtab_->AddString(name);
-  auto const symbol =
-      new (zone_) Symbol(name, name_index, info, section_index, address, size);
-  dynsym_->AddSymbol(symbol);
+  ASSERT(!dynsym_->HasBeenFinalized());
+  dynsym_->AddSymbol(name, binding, type, section_index, address, size);
 
   // Some tools assume the static symbol table is a superset of the dynamic
   // symbol table when it exists (see dartbug.com/41783).
-  AddStaticSymbol(name, info, section_index, address, size);
+  AddStaticSymbol(name, binding, type, section_index, address, size);
 }
 
 void Elf::AddStaticSymbol(const char* name,
-                          intptr_t info,
+                          intptr_t binding,
+                          intptr_t type,
                           intptr_t section_index,
                           intptr_t address,
                           intptr_t size) {
   if (IsStripped()) return;  // No static info kept in stripped ELF files.
-  ASSERT(!symtab_->HasBeenFinalized() && !strtab_->HasBeenFinalized());
-  auto const name_index = strtab_->AddString(name);
-  auto const symbol =
-      new (zone_) Symbol(name, name_index, info, section_index, address, size);
-  symtab_->AddSymbol(symbol);
+  ASSERT(!symtab_->HasBeenFinalized());
+  symtab_->AddSymbol(name, binding, type, section_index, address, size);
 }
 
 #if defined(DART_PRECOMPILER)
 class DwarfElfStream : public DwarfWriteStream {
  public:
   explicit DwarfElfStream(Zone* zone,
-                          WriteStream* stream,
-                          const CStringMap<intptr_t>& address_map)
-      : zone_(zone),
+                          NonStreamingWriteStream* stream,
+                          const SymbolTable* table)
+      : zone_(ASSERT_NOTNULL(zone)),
         stream_(ASSERT_NOTNULL(stream)),
-        address_map_(address_map) {}
+        table_(table) {}
 
-  void sleb128(intptr_t value) {
-    bool is_last_part = false;
-    while (!is_last_part) {
-      uint8_t part = value & 0x7F;
-      value >>= 7;
-      if ((value == 0 && (part & 0x40) == 0) ||
-          (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
-        is_last_part = true;
-      } else {
-        part |= 0x80;
-      }
-      stream_->WriteFixed(part);
-    }
-  }
-
-  void uleb128(uintptr_t value) {
-    bool is_last_part = false;
-    while (!is_last_part) {
-      uint8_t part = value & 0x7F;
-      value >>= 7;
-      if (value == 0) {
-        is_last_part = true;
-      } else {
-        part |= 0x80;
-      }
-      stream_->WriteFixed(part);
-    }
-  }
-
-  void u1(uint8_t value) { stream_->WriteFixed(value); }
-  // Can't use WriteFixed for these, as we may not be at aligned positions.
-  void u2(uint16_t value) { stream_->WriteBytes(&value, sizeof(value)); }
-  void u4(uint32_t value) { stream_->WriteBytes(&value, sizeof(value)); }
-  void u8(uint64_t value) { stream_->WriteBytes(&value, sizeof(value)); }
+  void sleb128(intptr_t value) { stream_->WriteSLEB128(value); }
+  void uleb128(uintptr_t value) { stream_->WriteLEB128(value); }
+  void u1(uint8_t value) { stream_->WriteByte(value); }
+  void u2(uint16_t value) { stream_->WriteFixed(value); }
+  void u4(uint32_t value) { stream_->WriteFixed(value); }
+  void u8(uint64_t value) { stream_->WriteFixed(value); }
   void string(const char* cstr) {  // NOLINT
-    stream_->WriteBytes(reinterpret_cast<const uint8_t*>(cstr),
-                        strlen(cstr) + 1);
+    // Unlike stream_->WriteString(), we want the null terminator written.
+    stream_->WriteBytes(cstr, strlen(cstr) + 1);
   }
-  intptr_t position() { return stream_->Position(); }
   intptr_t ReserveSize(const char* prefix, intptr_t* start) {
     ASSERT(start != nullptr);
-    intptr_t fixup = position();
+    intptr_t fixup = stream_->Position();
     // We assume DWARF v2, so all sizes are 32-bit.
     u4(0);
     // All sizes for DWARF sections measure the size of the section data _after_
     // the size value.
-    *start = position();
+    *start = stream_->Position();
     return fixup;
   }
   void SetSize(intptr_t fixup, const char* prefix, intptr_t start) {
-    const uint32_t value = position() - start;
-    memmove(stream_->buffer() + fixup, &value, sizeof(value));
+    const intptr_t old_position = stream_->Position();
+    stream_->SetPosition(fixup);
+    stream_->WriteFixed(static_cast<uint32_t>(old_position - start));
+    stream_->SetPosition(old_position);
   }
   void OffsetFromSymbol(const char* symbol, intptr_t offset) {
-    auto const address = address_map_.LookupValue(symbol);
-    ASSERT(address != 0);
-    addr(address + offset);
+    addr(RelocatedAddress(symbol, offset));
   }
   void DistanceBetweenSymbolOffsets(const char* symbol1,
                                     intptr_t offset1,
                                     const char* symbol2,
                                     intptr_t offset2) {
-    auto const address1 = address_map_.LookupValue(symbol1);
-    ASSERT(address1 != 0);
-    auto const address2 = address_map_.LookupValue(symbol2);
-    ASSERT(address2 != 0);
-    auto const delta = (address1 + offset1) - (address2 + offset2);
+    auto const address1 = RelocatedAddress(symbol1, offset1);
+    auto const address2 = RelocatedAddress(symbol2, offset2);
+    auto const delta = address1 - address2;
     RELEASE_ASSERT(delta >= 0);
     uleb128(delta);
   }
@@ -1039,11 +1152,17 @@
   void RegisterAbstractOrigin(intptr_t index) {
     ASSERT(abstract_origins_ != nullptr);
     ASSERT(index < abstract_origins_size_);
-    abstract_origins_[index] = position();
+    abstract_origins_[index] = stream_->Position();
   }
   void AbstractOrigin(intptr_t index) { u4(abstract_origins_[index]); }
 
  private:
+  uword RelocatedAddress(const char* name, intptr_t offset) {
+    auto const symbol = table_->Find(name);
+    ASSERT(symbol != nullptr);
+    return symbol->offset + offset;
+  }
+
   void addr(uword value) {
 #if defined(TARGET_ARCH_IS_32_BIT)
     u4(value);
@@ -1053,8 +1172,8 @@
   }
 
   Zone* const zone_;
-  WriteStream* const stream_;
-  const CStringMap<intptr_t>& address_map_;
+  NonStreamingWriteStream* const stream_;
+  const SymbolTable* table_;
   uint32_t* abstract_origins_ = nullptr;
   intptr_t abstract_origins_size_ = -1;
 
@@ -1064,10 +1183,6 @@
 static constexpr intptr_t kInitialDwarfBufferSize = 64 * KB;
 #endif
 
-static uint8_t* ZoneReallocate(uint8_t* ptr, intptr_t len, intptr_t new_len) {
-  return Thread::Current()->zone()->Realloc<uint8_t>(ptr, len, new_len);
-}
-
 Segment* Elf::LastLoadSegment() const {
   for (intptr_t i = segments_.length() - 1; i >= 0; i--) {
     auto const segment = segments_.At(i);
@@ -1091,109 +1206,41 @@
   return nullptr;
 }
 
-void Elf::AddSectionSymbols() {
-  for (auto const section : sections_) {
-    if (section->symbol_name == nullptr) continue;
-    ASSERT(section->memory_offset_is_set());
-    // While elf::STT_SECTION might seem more appropriate, those symbols are
-    // usually local and dlsym won't return them.
-    auto const info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
-    AddDynamicSymbol(section->symbol_name, info, section->index(),
-                     section->memory_offset(), section->MemorySize());
-  }
-}
-
 void Elf::FinalizeDwarfSections() {
   if (dwarf_ == nullptr) return;
 #if defined(DART_PRECOMPILER)
-  // Add all the static symbols for Code objects. We'll keep a table of
-  // symbol names to relocated addresses for use in the DwarfElfStream.
-  // The default kNoValue of 0 is okay here, as no symbols are defined for
-  // relocated address 0.
-  CStringMap<intptr_t> symbol_to_address_map;
-  // Prime the map with any existing static symbols.
-  if (symtab_ != nullptr) {
-    ASSERT(strtab_ != nullptr);
-    // Skip the initial reserved entry in the symbol table.
-    for (intptr_t i = 1; i < symtab_->Length(); i++) {
-      auto const symbol = symtab_->At(i);
-      auto const name = strtab_->At(symbol->name_index);
-      symbol_to_address_map.Insert({name, symbol->offset});
-    }
-  }
-
-  // Need these to turn offsets into relocated addresses.
-  auto const vm_start =
-      symbol_to_address_map.LookupValue(kVmSnapshotInstructionsAsmSymbol);
-  // vm_start is absent in deferred loading peices.
-  auto const isolate_start =
-      symbol_to_address_map.LookupValue(kIsolateSnapshotInstructionsAsmSymbol);
-  ASSERT(isolate_start > 0);
-  auto const vm_text = FindSectionForAddress(vm_start);
-  // vm_text is absent in deferred loading peices.
-  auto const isolate_text = FindSectionForAddress(isolate_start);
-  ASSERT(isolate_text != nullptr);
-
-  SnapshotTextObjectNamer namer(zone_);
-  const auto& codes = dwarf_->codes();
-  if (codes.length() == 0) {
-    return;
-  }
-  for (intptr_t i = 0; i < codes.length(); i++) {
-    const auto& code = *codes[i];
-    auto const name = namer.SnapshotNameFor(i, code);
-    const auto& pair = dwarf_->CodeAddress(code);
-    ASSERT(pair.offset > 0);
-    auto const section = pair.vm ? vm_text : isolate_text;
-    const intptr_t address = section->memory_offset() + pair.offset;
-    auto const info = (elf::STB_GLOBAL << 4) | elf::STT_FUNC;
-    AddStaticSymbol(name, info, section->index(), address, code.Size());
-    symbol_to_address_map.Insert({name, address});
-  }
-
-  // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
-  // provide unwinding information.
-
   {
-    uint8_t* buffer = nullptr;
-    WriteStream stream(&buffer, ZoneReallocate, kInitialDwarfBufferSize);
-    DwarfElfStream dwarf_stream(zone_, &stream, symbol_to_address_map);
+    ZoneWriteStream stream(zone(), kInitialDwarfBufferSize);
+    // We can use symtab_ without checking because this is an unstripped
+    // snapshot or separate debugging information, both of which have static
+    // symbol tables, and the static symbol table is a superset of the dynamic.
+    DwarfElfStream dwarf_stream(zone_, &stream, symtab_);
     dwarf_->WriteAbbreviations(&dwarf_stream);
-    AddDebug(".debug_abbrev", buffer, stream.bytes_written());
+    AddDebug(".debug_abbrev", stream.buffer(), stream.bytes_written());
   }
 
   {
-    uint8_t* buffer = nullptr;
-    WriteStream stream(&buffer, ZoneReallocate, kInitialDwarfBufferSize);
-    DwarfElfStream dwarf_stream(zone_, &stream, symbol_to_address_map);
+    ZoneWriteStream stream(zone(), kInitialDwarfBufferSize);
+    DwarfElfStream dwarf_stream(zone_, &stream, symtab_);
     dwarf_->WriteDebugInfo(&dwarf_stream);
-    AddDebug(".debug_info", buffer, stream.bytes_written());
+    AddDebug(".debug_info", stream.buffer(), stream.bytes_written());
   }
 
   {
-    uint8_t* buffer = nullptr;
-    WriteStream stream(&buffer, ZoneReallocate, kInitialDwarfBufferSize);
-    DwarfElfStream dwarf_stream(zone_, &stream, symbol_to_address_map);
+    ZoneWriteStream stream(zone(), kInitialDwarfBufferSize);
+    DwarfElfStream dwarf_stream(zone_, &stream, symtab_);
     dwarf_->WriteLineNumberProgram(&dwarf_stream);
-    AddDebug(".debug_line", buffer, stream.bytes_written());
+    AddDebug(".debug_line", stream.buffer(), stream.bytes_written());
   }
 #endif
 }
 
 void Elf::Finalize() {
-  AddSectionSymbols();
-
-  // The Build ID depends on the symbols being in place, so must be run after
-  // AddSectionSymbols(). Unfortunately, it currently depends on the contents
-  // of the .text and .rodata sections, so it can't come earlier in the file
-  // without changing how we add the .text and .rodata sections (since we
-  // determine memory offsets for those sections when we add them, and the
-  // text sections must have the memory offsets to do BSS relocations).
-  if (auto const build_id = GenerateBuildId()) {
-    AddSection(build_id, ".note.gnu.build-id", kSnapshotBuildIdAsmSymbol);
+  if (auto const new_build_id = GenerateFinalBuildId()) {
+    ReplaceSection(build_id_, new_build_id);
 
     // Add a PT_NOTE segment for the build ID.
-    segments_.Add(new (zone_) NoteSegment(zone_, build_id));
+    segments_.Add(new (zone_) NoteSegment(zone_, new_build_id));
   }
 
   // Adding the dynamic symbol table and associated sections.
@@ -1221,13 +1268,13 @@
   // extra padding _or_ determine file offsets before memory offsets. The
   // latter would require us to handle BSS relocations during ELF finalization,
   // instead of while writing the .text section content.
-  FinalizeDwarfSections();
   if (!IsStripped()) {
     AddSection(strtab_, ".strtab");
     AddSection(symtab_, ".symtab");
     symtab_->link = strtab_->index();
   }
   AddSection(shstrtab_, ".shstrtab");
+  FinalizeDwarfSections();
 
   // At this point, all non-programmatically calculated sections and segments
   // have been added. Add any programatically calculated sections and segments
@@ -1243,39 +1290,13 @@
   WriteSectionTable(&wrapped);
 }
 
-// Need to include the final \0 terminator in both byte count and byte output.
-static const uint32_t kBuildIdNameLength = strlen(elf::ELF_NOTE_GNU) + 1;
-// We generate a 128-bit hash, where each 32 bits is a hash of the contents of
-// the following segments in order:
-//
-// .text(VM) | .text(Isolate) | .rodata(VM) | .rodata(Isolate)
-static constexpr intptr_t kBuildIdSegmentNamesLength = 4;
-static constexpr const char* kBuildIdSegmentNames[kBuildIdSegmentNamesLength]{
-    kVmSnapshotInstructionsAsmSymbol,
-    kIsolateSnapshotInstructionsAsmSymbol,
-    kVmSnapshotDataAsmSymbol,
-    kIsolateSnapshotDataAsmSymbol,
-};
-static constexpr uint32_t kBuildIdDescriptionLength =
-    kBuildIdSegmentNamesLength * sizeof(uint32_t);
-static const intptr_t kBuildIdDescriptionOffset =
-    sizeof(elf::Note) + kBuildIdNameLength;
-static const intptr_t kBuildIdSize =
-    kBuildIdDescriptionOffset + kBuildIdDescriptionLength;
-
-static const Symbol* LookupSymbol(StringTable* strings,
-                                  SymbolTable* symbols,
-                                  const char* name) {
-  ASSERT(strings != nullptr);
-  ASSERT(symbols != nullptr);
-  auto const name_index = strings->Lookup(name);
-  if (name_index < 0) return nullptr;
-  return symbols->FindSymbolWithNameIndex(name_index);
-}
-
 static uint32_t HashBitsContainer(const BitsContainer* bits) {
   uint32_t hash = 0;
   auto const size = bits->MemorySize();
+  if (bits->bytes() == nullptr) {
+    // Just hash the size as a fallback if this section has no contents.
+    return FinalizeHash(size, 32);
+  }
   auto const end = bits->bytes() + size;
   auto const non_word_size = size % kWordSize;
   auto const end_of_words =
@@ -1291,37 +1312,59 @@
   return FinalizeHash(hash, 32);
 }
 
-Section* Elf::GenerateBuildId() {
-  uint8_t* notes_buffer = nullptr;
-  WriteStream stream(&notes_buffer, ZoneReallocate, kBuildIdSize);
-  stream.WriteFixed(kBuildIdNameLength);
-  stream.WriteFixed(kBuildIdDescriptionLength);
-  stream.WriteFixed(static_cast<uint32_t>(elf::NoteType::NT_GNU_BUILD_ID));
-  stream.WriteBytes(elf::ELF_NOTE_GNU, kBuildIdNameLength);
-  const intptr_t description_start = stream.bytes_written();
+Section* Elf::GenerateFinalBuildId() {
+  uint32_t hashes[kBuildIdSegmentNamesLength];
   for (intptr_t i = 0; i < kBuildIdSegmentNamesLength; i++) {
     auto const name = kBuildIdSegmentNames[i];
-    auto const symbol = LookupSymbol(dynstrtab_, dynsym_, name);
+    auto const symbol = dynsym_->Find(name);
     if (symbol == nullptr) {
-      stream.WriteFixed(static_cast<uint32_t>(0));
-      continue;
+      // If we're missing a section, then we don't generate a final build ID.
+      return nullptr;
     }
     auto const bits = sections_[symbol->section_index]->AsBitsContainer();
     if (bits == nullptr) {
       FATAL1("Section for symbol %s is not a BitsContainer", name);
     }
+    if (bits->bytes() == nullptr) {
+      // For now, if we don't have section contents (because we're generating
+      // assembly), don't generate a final build ID, as we'll have different
+      // build IDs in the snapshot and the separate debugging information.
+      //
+      // TODO(dartbug.com/43274): Change once we generate consistent build IDs
+      // between assembly snapshots and their debugging information.
+      return nullptr;
+    }
     ASSERT_EQUAL(bits->MemorySize(), symbol->size);
-    // We don't actually have the bytes (i.e., this is a separate debugging
-    // info file for an assembly snapshot), so we can't calculate the build ID.
-    if (bits->bytes() == nullptr) return nullptr;
-
-    stream.WriteFixed(HashBitsContainer(bits));
+    hashes[i] = HashBitsContainer(bits);
   }
-  ASSERT_EQUAL(stream.bytes_written() - description_start,
-               kBuildIdDescriptionLength);
-  return new (zone_) BitsContainer(
-      elf::SectionHeaderType::SHT_NOTE, /*allocate=*/true, /*executable=*/false,
-      /*writable=*/false, stream.bytes_written(), notes_buffer, kNoteAlignment);
+  // To ensure we can quickly check for a final build ID, we ensure the first
+  // byte contains a non-zero value.
+  auto const bytes = reinterpret_cast<uint8_t*>(hashes);
+  if (bytes[0] == 0) {
+    bytes[0] = 1;
+  }
+  return CreateBuildIdNote(&hashes, sizeof(hashes));
+}
+
+Section* Elf::CreateBuildIdNote(const void* description_bytes,
+                                intptr_t description_length) {
+  ASSERT(description_length == 0 || description_bytes != nullptr);
+  ZoneWriteStream stream(zone(), kBuildIdHeaderSize + description_length);
+  stream.WriteFixed<decltype(elf::Note::name_size)>(sizeof(elf::ELF_NOTE_GNU));
+  stream.WriteFixed<decltype(elf::Note::description_size)>(description_length);
+  stream.WriteFixed<decltype(elf::Note::type)>(elf::NoteType::NT_GNU_BUILD_ID);
+  ASSERT_EQUAL(stream.Position(), sizeof(elf::Note));
+  stream.WriteBytes(elf::ELF_NOTE_GNU, sizeof(elf::ELF_NOTE_GNU));
+  ASSERT_EQUAL(stream.bytes_written(), kBuildIdHeaderSize);
+  stream.WriteBytes(description_bytes, description_length);
+  // While the build ID section does not need to be writable, it and the
+  // BSS section are allocated segments at the same time. Having the same flags
+  // ensures they will be combined in the same segment and not unnecessarily
+  // aligned into a new page.
+  return new (zone_) BitsContainer(elf::SectionHeaderType::SHT_NOTE,
+                                   /*allocate=*/true, /*executable=*/false,
+                                   /*writable=*/true, stream.bytes_written(),
+                                   stream.buffer(), kNoteAlignment);
 }
 
 void Elf::FinalizeProgramTable() {
@@ -1458,12 +1501,12 @@
   stream->WriteHalf(sections_.length());
   stream->WriteHalf(shstrtab_->index());
 
-  ASSERT_EQUAL(stream->position(), sizeof(elf::ElfHeader));
+  ASSERT_EQUAL(stream->Position(), sizeof(elf::ElfHeader));
 }
 
 void Elf::WriteProgramTable(ElfWriteStream* stream) {
   ASSERT(program_table_file_size_ >= 0);  // Check for finalization.
-  ASSERT(stream->position() == program_table_file_offset_);
+  ASSERT(stream->Position() == program_table_file_offset_);
 #if defined(DEBUG)
   // Here, we count the number of times that a PT_LOAD writable segment is
   // followed by a non-writable segment. We initialize last_writable to true so
@@ -1480,9 +1523,9 @@
       last_writable = segment->IsWritable();
     }
 #endif
-    const intptr_t start = stream->position();
+    const intptr_t start = stream->Position();
     segment->WriteProgramHeader(stream);
-    const intptr_t end = stream->position();
+    const intptr_t end = stream->Position();
     ASSERT_EQUAL(end - start, sizeof(elf::ProgramHeader));
   }
 #if defined(DEBUG)
@@ -1496,12 +1539,12 @@
 void Elf::WriteSectionTable(ElfWriteStream* stream) {
   ASSERT(section_table_file_size_ >= 0);  // Check for finalization.
   stream->Align(kElfSectionTableAlignment);
-  ASSERT_EQUAL(stream->position(), section_table_file_offset_);
+  ASSERT_EQUAL(stream->Position(), section_table_file_offset_);
 
   for (auto const section : sections_) {
-    const intptr_t start = stream->position();
+    const intptr_t start = stream->Position();
     section->WriteSectionHeader(stream);
-    const intptr_t end = stream->position();
+    const intptr_t end = stream->Position();
     ASSERT_EQUAL(end - start, sizeof(elf::SectionHeader));
   }
 }
@@ -1524,9 +1567,9 @@
       stream->Align(load_align);
       current_segment = section->load_segment;
     }
-    ASSERT_EQUAL(stream->position(), section->file_offset());
+    ASSERT_EQUAL(stream->Position(), section->file_offset());
     section->Write(stream);
-    ASSERT_EQUAL(stream->position(),
+    ASSERT_EQUAL(stream->Position(),
                  section->file_offset() + section->FileSize());
   }
 }
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
index da0af3c..d0f8a96 100644
--- a/runtime/vm/elf.h
+++ b/runtime/vm/elf.h
@@ -30,12 +30,10 @@
     DebugInfo,
   };
 
-  Elf(Zone* zone,
-      StreamingWriteStream* stream,
-      Type type,
-      Dwarf* dwarf = nullptr);
+  Elf(Zone* zone, BaseWriteStream* stream, Type type, Dwarf* dwarf = nullptr);
 
-  static const intptr_t kPageSize = 4096;
+  static constexpr intptr_t kPageSize = 4096;
+  static constexpr uword kNoSectionStart = 0;
 
   bool IsStripped() const { return dwarf_ == nullptr; }
 
@@ -43,21 +41,30 @@
   const Dwarf* dwarf() const { return dwarf_; }
   Dwarf* dwarf() { return dwarf_; }
 
-  uword BssStart(bool vm) const;
+  // Returns the relocated address for the symbol with the given name or
+  // kNoSectionStart if the symbol was not found.
+  uword SymbolAddress(const char* name) const;
 
-  // What the next memory offset for a kPageSize-aligned section would be.
+  // What the next memory offset for an appropriately aligned section would be.
   //
-  // Only used by BlobImageWriter::WriteText() to determine the memory offset
-  // for the text section before it is added.
-  intptr_t NextMemoryOffset() const;
-  intptr_t AddNoBits(const char* name, const uint8_t* bytes, intptr_t size);
+  // Only used by AssemblyImageWriter and BlobImageWriter methods.
+  intptr_t NextMemoryOffset(intptr_t alignment) const;
   intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
   intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
   void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
 
+  // Adds a local symbol for the given offset and size in the "current" section,
+  // that is, the section index for the symbol is for the next added section.
+  void AddLocalSymbol(const char* name,
+                      intptr_t type,
+                      intptr_t offset,
+                      intptr_t size);
+
   void Finalize();
 
  private:
+  static constexpr const char* kBuildIdNoteName = ".note.gnu.build-id";
+
   static Section* CreateBSS(Zone* zone, Type type, intptr_t size);
 
   // Adds the section and also creates a PT_LOAD segment for the section if it
@@ -71,20 +78,29 @@
   intptr_t AddSection(Section* section,
                       const char* name,
                       const char* symbol_name = nullptr);
+  // Replaces [old_section] with [new_section] in all appropriate places. If the
+  // section is allocated, the memory size of the section must be the same as
+  // the original to ensure any already-calculated memory offsets are unchanged.
+  void ReplaceSection(Section* old_section, Section* new_section);
+
   void AddStaticSymbol(const char* name,
-                       intptr_t info,
+                       intptr_t binding,
+                       intptr_t type,
                        intptr_t section_index,
                        intptr_t address,
                        intptr_t size);
   void AddDynamicSymbol(const char* name,
-                        intptr_t info,
+                        intptr_t binding,
+                        intptr_t type,
                         intptr_t section_index,
                         intptr_t address,
                         intptr_t size);
 
   Segment* LastLoadSegment() const;
   const Section* FindSectionForAddress(intptr_t address) const;
-  Section* GenerateBuildId();
+  Section* CreateBuildIdNote(const void* description_bytes,
+                             intptr_t description_length);
+  Section* GenerateFinalBuildId();
 
   void AddSectionSymbols();
   void FinalizeDwarfSections();
@@ -97,7 +113,7 @@
   void WriteSections(ElfWriteStream* stream);
 
   Zone* const zone_;
-  StreamingWriteStream* const unwrapped_stream_;
+  BaseWriteStream* const unwrapped_stream_;
   const Type type_;
 
   // If nullptr, then the ELF file should be stripped of static information like
@@ -118,6 +134,12 @@
   StringTable* strtab_ = nullptr;
   SymbolTable* symtab_ = nullptr;
 
+  // We always create a GNU build ID for all Elf files. In order to create
+  // the appropriate offset to it in an InstructionsSection object, we create an
+  // initial build ID section as a placeholder and then replace that section
+  // during finalization once we have the information to calculate the real one.
+  Section* build_id_;
+
   GrowableArray<Section*> sections_;
   GrowableArray<Segment*> segments_;
   intptr_t memory_offset_;
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 3bcb484..9cba5d4 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -252,7 +252,7 @@
   void ExecuteCatchEntryMoves(const CatchEntryMoves& moves) {
     Zone* zone = Thread::Current()->zone();
     auto& value = Object::Handle(zone);
-    auto& dst_values = Array::Handle(zone, Array::New(moves.count()));
+    GrowableArray<Object*> dst_values;
 
     uword fp = handler_fp;
     ObjectPool* pool = nullptr;
@@ -309,7 +309,7 @@
           UNREACHABLE();
       }
 
-      dst_values.SetAt(j, value);
+      dst_values.Add(&Object::Handle(zone, value.raw()));
     }
 
     {
@@ -317,8 +317,7 @@
 
       for (int j = 0; j < moves.count(); j++) {
         const CatchEntryMove& move = moves.At(j);
-        value = dst_values.At(j);
-        *TaggedSlotAt(fp, move.dest_slot()) = value.raw();
+        *TaggedSlotAt(fp, move.dest_slot()) = dst_values[j]->raw();
       }
     }
   }
@@ -384,8 +383,8 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-void CatchEntryMove::WriteTo(WriteStream* stream) {
-  using Writer = WriteStream::Raw<sizeof(int32_t), int32_t>;
+void CatchEntryMove::WriteTo(BaseWriteStream* stream) {
+  using Writer = BaseWriteStream::Raw<sizeof(int32_t), int32_t>;
   Writer::Write(stream, src_);
   Writer::Write(stream, dest_and_kind_);
 }
@@ -879,7 +878,10 @@
     // the isolate etc.). This can happen in the compiler, which is not
     // allowed to allocate in new space, so we pass the kOld argument.
     const UnhandledException& unhandled_exception = UnhandledException::Handle(
-        zone, UnhandledException::New(exception, stacktrace, Heap::kOld));
+        zone, exception.raw() == isolate->object_store()->out_of_memory()
+                  ? isolate->isolate_object_store()
+                        ->preallocated_unhandled_exception()
+                  : UnhandledException::New(exception, stacktrace, Heap::kOld));
     stacktrace = StackTrace::null();
     JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp,
                            unhandled_exception, stacktrace);
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 7a44cd8..e7b52e5 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -21,7 +21,7 @@
 class Instance;
 class Integer;
 class ReadStream;
-class WriteStream;
+class BaseWriteStream;
 class String;
 class Thread;
 class TypedData;
@@ -203,7 +203,7 @@
   static CatchEntryMove ReadFrom(ReadStream* stream);
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  void WriteTo(WriteStream* stream);
+  void WriteTo(BaseWriteStream* stream);
 #endif
 
 #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
diff --git a/runtime/vm/flags.cc b/runtime/vm/flags.cc
index ee2708f..901856c 100644
--- a/runtime/vm/flags.cc
+++ b/runtime/vm/flags.cc
@@ -95,11 +95,13 @@
   Flag(const char* name, const char* comment, FlagHandler handler)
       : name_(name),
         comment_(comment),
+        string_value_("false"),
         flag_handler_(handler),
         type_(kFlagHandler) {}
   Flag(const char* name, const char* comment, OptionHandler handler)
       : name_(name),
         comment_(comment),
+        string_value_(nullptr),
         option_handler_(handler),
         type_(kOptionHandler) {}
 
@@ -148,6 +150,7 @@
 
   const char* name_;
   const char* comment_;
+  const char* string_value_;
   union {
     void* addr_;
     bool* bool_ptr_;
@@ -332,9 +335,11 @@
       } else {
         return false;
       }
+      flag->string_value_ = argument;
       break;
     }
     case Flag::kOptionHandler: {
+      flag->string_value_ = argument;
       (flag->option_handler_)(argument);
       break;
     }
@@ -487,8 +492,7 @@
 
 #ifndef PRODUCT
 void Flags::PrintFlagToJSONArray(JSONArray* jsarr, const Flag* flag) {
-  if (flag->IsUnrecognized() || flag->type_ == Flag::kFlagHandler ||
-      flag->type_ == Flag::kOptionHandler) {
+  if (flag->IsUnrecognized()) {
     return;
   }
   JSONObject jsflag(jsarr);
@@ -521,6 +525,20 @@
       }
       break;
     }
+    case Flag::kFlagHandler: {
+      jsflag.AddProperty("_flagType", "Bool");
+      jsflag.AddProperty("valueAsString", flag->string_value_);
+      break;
+    }
+    case Flag::kOptionHandler: {
+      jsflag.AddProperty("_flagType", "String");
+      if (flag->string_value_ != nullptr) {
+        jsflag.AddProperty("valueAsString", flag->string_value_);
+      } else {
+        // valueAsString missing means NULL.
+      }
+      break;
+    }
     default:
       UNREACHABLE();
       break;
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index 5cd2d0b..85bfedc 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -66,6 +66,8 @@
 
   intptr_t length() const { return array_.length(); }
 
+  void Clear() { array_.Clear(); }
+
   const GrowableArray<T*>& growable_array() const { return array_; }
 
  private:
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index dad7079..0d2ac0c 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -10,6 +10,7 @@
 #include "platform/assert.h"
 #include "platform/utils.h"
 #include "vm/compiler/jit/compiler.h"
+#include "vm/dart.h"
 #include "vm/flags.h"
 #include "vm/heap/pages.h"
 #include "vm/heap/safepoint.h"
@@ -67,8 +68,7 @@
       read_only_(false),
       last_gc_was_old_space_(false),
       assume_scavenge_will_fail_(false),
-      gc_on_nth_allocation_(kNoForcedGarbageCollection),
-      gc_event_callback_(nullptr) {
+      gc_on_nth_allocation_(kNoForcedGarbageCollection) {
   UpdateGlobalMaxUsed();
   for (int sel = 0; sel < kNumWeakSelectors; sel++) {
     new_weak_tables_[sel] = new WeakTable();
@@ -111,15 +111,13 @@
 
 uword Heap::AllocateOld(intptr_t size, OldPage::PageType type) {
   ASSERT(Thread::Current()->no_safepoint_scope_depth() == 0);
-  CollectForDebugging();
-  uword addr = old_space_.TryAllocate(size, type);
-  if (addr != 0) {
-    return addr;
-  }
-  // If we are in the process of running a sweep, wait for the sweeper to free
-  // memory.
-  Thread* thread = Thread::Current();
   if (old_space_.GrowthControlState()) {
+    CollectForDebugging();
+    uword addr = old_space_.TryAllocate(size, type);
+    if (addr != 0) {
+      return addr;
+    }
+    Thread* thread = Thread::Current();
     // Wait for any GC tasks that are in progress.
     WaitForSweeperTasks(thread);
     addr = old_space_.TryAllocate(size, type);
@@ -148,7 +146,7 @@
     CollectAllGarbage(kLowMemory);
     WaitForSweeperTasks(thread);
   }
-  addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth);
+  uword addr = old_space_.TryAllocate(size, type, PageSpace::kForceGrowth);
   if (addr != 0) {
     return addr;
   }
@@ -725,6 +723,16 @@
     new_weak_tables_[i]->MergeFrom(donor->new_weak_tables_[i]);
     old_weak_tables_[i]->MergeFrom(donor->old_weak_tables_[i]);
   }
+
+  StoreBufferBlock* block =
+      donor->isolate_group()->store_buffer()->TakeBlocks();
+  while (block != nullptr) {
+    StoreBufferBlock* next = block->next();
+    block->set_next(nullptr);
+    isolate_group()->store_buffer()->PushBlock(block,
+                                               StoreBuffer::kIgnoreThreshold);
+    block = next;
+  }
 }
 
 void Heap::CollectForDebugging() {
@@ -1026,7 +1034,7 @@
     });
   }
 #endif  // !PRODUCT
-  if (gc_event_callback_ != nullptr) {
+  if (Dart::gc_event_callback() != nullptr) {
     isolate_group_->ForEachIsolate([&](Isolate* isolate) {
       if (!Isolate::IsSystemIsolate(isolate)) {
         Dart_GCEvent event;
@@ -1072,7 +1080,7 @@
               AvgCollectionPeriod(isolate_uptime_micros, old_space_collections);
         }
 
-        (*gc_event_callback_)(&event);
+        (*Dart::gc_event_callback())(&event);
       }
     });
   }
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 0ea8e09..7e42b75 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -322,10 +322,6 @@
 
   void MergeFrom(Heap* donor);
 
-  void SetGCEventCallback(Dart_GCEventCallback callback) {
-    gc_event_callback_ = callback;
-  }
-
  private:
   class GCStats : public ValueObject {
    public:
@@ -422,8 +418,6 @@
   // sensitive codepaths.
   intptr_t gc_on_nth_allocation_;
 
-  Dart_GCEventCallback gc_event_callback_;
-
   friend class Become;       // VisitObjectPointers
   friend class GCCompactor;  // VisitObjectPointers
   friend class Precompiler;  // VisitObjects
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index e0f10cb..3c73952 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -452,6 +452,7 @@
 
 void PageSpace::EvaluateConcurrentMarking(GrowthPolicy growth_policy) {
   if (growth_policy != kForceGrowth) {
+    ASSERT(GrowthControlState());
     if (heap_ != NULL) {  // Some unit tests.
       Thread* thread = Thread::Current();
       if (thread->CanCollectGarbage()) {
@@ -1020,6 +1021,8 @@
 }
 
 void PageSpace::CollectGarbage(bool compact, bool finalize) {
+  ASSERT(GrowthControlState());
+
   if (!finalize) {
 #if defined(TARGET_ARCH_IA32)
     return;  // Barrier not implemented.
diff --git a/runtime/vm/heap/pages_test.cc b/runtime/vm/heap/pages_test.cc
index 1db6113..fed0a88 100644
--- a/runtime/vm/heap/pages_test.cc
+++ b/runtime/vm/heap/pages_test.cc
@@ -10,6 +10,7 @@
 
 TEST_CASE(Pages) {
   PageSpace* space = new PageSpace(NULL, 4 * MBInWords);
+  space->InitGrowthControl();
   EXPECT(!space->Contains(reinterpret_cast<uword>(&space)));
   uword block = space->TryAllocate(8 * kWordSize);
   EXPECT(block != 0);
diff --git a/runtime/vm/heap/pointer_block.h b/runtime/vm/heap/pointer_block.h
index 73cf03b..4a40cd1 100644
--- a/runtime/vm/heap/pointer_block.h
+++ b/runtime/vm/heap/pointer_block.h
@@ -28,6 +28,7 @@
   }
 
   PointerBlock<Size>* next() const { return next_; }
+  void set_next(PointerBlock<Size>* next) { next_ = next; }
 
   intptr_t Count() const { return top_; }
   bool IsFull() const { return Count() == kSize; }
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index cfed7d7..41f1f99 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -50,7 +50,8 @@
 
 // If the forwarded bit and pointer tag bit are the same, we can avoid a few
 // conversions.
-COMPILE_ASSERT(kForwarded == kHeapObjectTag);
+COMPILE_ASSERT(static_cast<uword>(kForwarded) ==
+               static_cast<uword>(kHeapObjectTag));
 
 static inline bool IsForwarding(uword header) {
   uword bits = header & kForwardingMask;
diff --git a/runtime/vm/heap/verifier.cc b/runtime/vm/heap/verifier.cc
index 48610f8..4c2da50 100644
--- a/runtime/vm/heap/verifier.cc
+++ b/runtime/vm/heap/verifier.cc
@@ -53,8 +53,8 @@
             allocated_set_->Contains(OldPage::ToWritable(raw_obj))) {
           continue;
         }
-        uword raw_addr = ObjectLayout::ToAddr(raw_obj);
-        FATAL1("Invalid object pointer encountered %#" Px "\n", raw_addr);
+        FATAL2("Invalid object pointer encountered %#" Px ": %#" Px "\n",
+               reinterpret_cast<uword>(current), static_cast<uword>(raw_obj));
       }
     }
   }
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 7c8ba6a..4e53de4 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -6,6 +6,8 @@
 
 #include "include/dart_api.h"
 #include "platform/assert.h"
+#include "platform/elf.h"
+#include "vm/bss_relocs.h"
 #include "vm/class_id.h"
 #include "vm/compiler/runtime_api.h"
 #include "vm/dwarf.h"
@@ -36,10 +38,110 @@
 
 DEFINE_FLAG(charp,
             print_instructions_sizes_to,
-            NULL,
+            nullptr,
             "Print sizes of all instruction objects to the given file");
 #endif
 
+const InstructionsSectionLayout* Image::ExtraInfo(const uword raw_memory,
+                                                  const uword size) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  auto const raw_value =
+      FieldValue(raw_memory, HeaderField::InstructionsSectionOffset);
+  if (raw_value != kNoInstructionsSection) {
+    ASSERT(raw_value >= kHeaderSize);
+    ASSERT(raw_value <= size - InstructionsSection::HeaderSize());
+    auto const layout = reinterpret_cast<const InstructionsSectionLayout*>(
+        raw_memory + raw_value);
+    // The instructions section is likely non-empty in bare instructions mode
+    // (unless splitting into multiple outputs and there are no Code objects
+    // in this particular output), but is guaranteed empty otherwise (the
+    // instructions follow the InstructionsSection object instead).
+    ASSERT(FLAG_use_bare_instructions || layout->payload_length_ == 0);
+    ASSERT(raw_value <=
+           size - InstructionsSection::InstanceSize(layout->payload_length_));
+    return layout;
+  }
+#endif
+  return nullptr;
+}
+
+uword* Image::bss() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(extra_info_ != nullptr);
+  // There should always be a non-zero BSS offset.
+  ASSERT(extra_info_->bss_offset_ != 0);
+  // Returning a non-const uword* is safe because we're translating from
+  // the start of the instructions (read-only) to the start of the BSS
+  // (read-write).
+  return reinterpret_cast<uword*>(raw_memory_ + extra_info_->bss_offset_);
+#else
+  return nullptr;
+#endif
+}
+
+uword Image::instructions_relocated_address() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(extra_info_ != nullptr);
+  // For assembly snapshots, we need to retrieve this from the initialized BSS.
+  const uword address =
+      compiled_to_elf() ? extra_info_->instructions_relocated_address_
+                        : bss()[BSS::RelocationIndex(
+                              BSS::Relocation::InstructionsRelocatedAddress)];
+  ASSERT(address != kNoRelocatedAddress);
+  return address;
+#else
+  return kNoRelocatedAddress;
+#endif
+}
+
+const uint8_t* Image::build_id() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(extra_info_ != nullptr);
+  if (extra_info_->build_id_offset_ != kNoBuildId) {
+    auto const note = reinterpret_cast<elf::Note*>(
+        raw_memory_ + extra_info_->build_id_offset_);
+    // Check that we have a final build ID. A non-final build ID will either
+    // have a description length of 0 or an initial byte of 0.
+    auto const description = note->data + note->name_size;
+    auto const length = note->description_size;
+    if (length != 0 && description[0] != 0) {
+      return description;
+    }
+  }
+#endif
+  return nullptr;
+}
+
+intptr_t Image::build_id_length() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(extra_info_ != nullptr);
+  if (extra_info_->build_id_offset_ != kNoBuildId) {
+    auto const note = reinterpret_cast<elf::Note*>(
+        raw_memory_ + extra_info_->build_id_offset_);
+    // Check that we have a final build ID. A non-final build ID will either
+    // have a description length of 0 or an initial byte of 0.
+    auto const description = note->data + note->name_size;
+    auto const length = note->description_size;
+    if (length != 0 && description[0] != 0) {
+      return length;
+    }
+  }
+#endif
+  return 0;
+}
+
+bool Image::compiled_to_elf() const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(extra_info_ != nullptr);
+  // Since assembly snapshots can't set up this field correctly (instead,
+  // it's initialized in BSS at snapshot load time), we use it to detect
+  // direct-to-ELF snapshots.
+  return extra_info_->instructions_relocated_address_ != kNoRelocatedAddress;
+#else
+  return false;
+#endif
+}
+
 intptr_t ObjectOffsetTrait::Hashcode(Key key) {
   ObjectPtr obj = key;
   ASSERT(!obj->IsSmi());
@@ -88,6 +190,7 @@
       next_text_offset_(0),
       objects_(),
       instructions_(),
+      image_type_(TagObjectTypeAsReadOnly(t->zone(), "Image")),
       instructions_section_type_(
           TagObjectTypeAsReadOnly(t->zone(), "InstructionsSection")),
       instructions_type_(TagObjectTypeAsReadOnly(t->zone(), "Instructions")),
@@ -144,104 +247,37 @@
   return offset;
 }
 
-static intptr_t InstructionsSizeInSnapshot(InstructionsPtr raw) {
-  if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    // Currently, we align bare instruction payloads on 4 byte boundaries.
-    //
-    // If we later decide to align on larger boundaries to put entries at the
-    // start of cache lines, make sure to account for entry points that are
-    // _not_ at the start of the payload.
-    return Utils::RoundUp(Instructions::Size(raw),
-                          ImageWriter::kBareInstructionsAlignment);
-  }
-#if defined(IS_SIMARM_X64)
-  return Utils::RoundUp(
-      compiler::target::Instructions::HeaderSize() + Instructions::Size(raw),
-      compiler::target::ObjectAlignment::kObjectAlignment);
-#else
-  return raw->ptr()->HeapSize();
-#endif
-}
-
-#if defined(IS_SIMARM_X64)
-static intptr_t CompressedStackMapsSizeInSnapshot(intptr_t payload_size) {
-  const intptr_t unrounded_size_in_bytes =
-      compiler::target::CompressedStackMaps::HeaderSize() + payload_size;
-  return Utils::RoundUp(unrounded_size_in_bytes,
-                        compiler::target::ObjectAlignment::kObjectAlignment);
-}
-
-static intptr_t StringPayloadSize(intptr_t len, bool isOneByteString) {
-  return len * (isOneByteString ? OneByteString::kBytesPerElement
-                                : TwoByteString::kBytesPerElement);
-}
-
-static intptr_t StringSizeInSnapshot(intptr_t len, bool isOneByteString) {
-  const intptr_t unrounded_size_in_bytes =
-      (String::kSizeofRawString / 2) + StringPayloadSize(len, isOneByteString);
-  return Utils::RoundUp(unrounded_size_in_bytes,
-                        compiler::target::ObjectAlignment::kObjectAlignment);
-}
-
-static intptr_t CodeSourceMapSizeInSnapshot(intptr_t len) {
-  const intptr_t unrounded_size_in_bytes =
-      2 * compiler::target::kWordSize + len;
-  return Utils::RoundUp(unrounded_size_in_bytes,
-                        compiler::target::ObjectAlignment::kObjectAlignment);
-}
-
-static intptr_t PcDescriptorsSizeInSnapshot(intptr_t len) {
-  const intptr_t unrounded_size_in_bytes =
-      2 * compiler::target::kWordSize + len;
-  return Utils::RoundUp(unrounded_size_in_bytes,
-                        compiler::target::ObjectAlignment::kObjectAlignment);
-}
-
 intptr_t ImageWriter::SizeInSnapshot(ObjectPtr raw_object) {
   const classid_t cid = raw_object->GetClassId();
 
   switch (cid) {
     case kCompressedStackMapsCid: {
-      CompressedStackMapsPtr raw_maps =
-          static_cast<CompressedStackMapsPtr>(raw_object);
-      auto const payload_size = CompressedStackMaps::PayloadSizeOf(raw_maps);
-      return CompressedStackMapsSizeInSnapshot(payload_size);
-    }
-    case kOneByteStringCid:
-    case kTwoByteStringCid: {
-      StringPtr raw_str = static_cast<StringPtr>(raw_object);
-      return StringSizeInSnapshot(Smi::Value(raw_str->ptr()->length_),
-                                  cid == kOneByteStringCid);
+      auto raw_maps = CompressedStackMaps::RawCast(raw_object);
+      return compiler::target::CompressedStackMaps::InstanceSize(
+          CompressedStackMaps::PayloadSizeOf(raw_maps));
     }
     case kCodeSourceMapCid: {
-      CodeSourceMapPtr raw_map = static_cast<CodeSourceMapPtr>(raw_object);
-      return CodeSourceMapSizeInSnapshot(raw_map->ptr()->length_);
+      auto raw_map = CodeSourceMap::RawCast(raw_object);
+      return compiler::target::CodeSourceMap::InstanceSize(
+          raw_map->ptr()->length_);
     }
     case kPcDescriptorsCid: {
-      PcDescriptorsPtr raw_desc = static_cast<PcDescriptorsPtr>(raw_object);
-      return PcDescriptorsSizeInSnapshot(raw_desc->ptr()->length_);
+      auto raw_desc = PcDescriptors::RawCast(raw_object);
+      return compiler::target::PcDescriptors::InstanceSize(
+          raw_desc->ptr()->length_);
     }
     case kInstructionsCid: {
-      InstructionsPtr raw_insns = static_cast<InstructionsPtr>(raw_object);
-      return InstructionsSizeInSnapshot(raw_insns);
+      auto raw_insns = Instructions::RawCast(raw_object);
+      return compiler::target::Instructions::InstanceSize(
+          Instructions::Size(raw_insns));
     }
     default: {
       const Class& clazz = Class::Handle(Object::Handle(raw_object).clazz());
-      FATAL1("Unsupported class %s in rodata section.\n", clazz.ToCString());
+      FATAL("Unsupported class %s in rodata section.\n", clazz.ToCString());
       return 0;
     }
   }
 }
-#else   // defined(IS_SIMARM_X64)
-intptr_t ImageWriter::SizeInSnapshot(ObjectPtr raw) {
-  switch (raw->GetClassId()) {
-    case kInstructionsCid:
-      return InstructionsSizeInSnapshot(static_cast<InstructionsPtr>(raw));
-    default:
-      return raw->ptr()->HeapSize();
-  }
-}
-#endif  // defined(IS_SIMARM_X64)
 
 uint32_t ImageWriter::GetDataOffsetFor(ObjectPtr raw_object) {
   intptr_t snap_size = SizeInSnapshot(raw_object);
@@ -259,7 +295,7 @@
   ASSERT(count != nullptr && size != nullptr);
   *count = 0;
   *size = 0;
-  for (auto const data : instructions_) {
+  for (auto const& data : instructions_) {
     if (data.trampoline_length != 0) {
       *count += 1;
       *size += data.trampoline_length;
@@ -386,7 +422,7 @@
 }
 #endif
 
-void ImageWriter::Write(WriteStream* clustered_stream, bool vm) {
+void ImageWriter::Write(NonStreamingWriteStream* clustered_stream, bool vm) {
   Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Heap* heap = thread->isolate()->heap();
@@ -412,34 +448,37 @@
     data.obj_ = &Object::Handle(zone, data.raw_obj_);
   }
 
-  // Append the direct-mapped RO data objects after the clustered snapshot.
-  // We need to do this before WriteText because WriteText currently adds the
-  // finalized contents of the clustered_stream as data sections.
-  offset_space_ = vm ? V8SnapshotProfileWriter::kVmData
-                     : V8SnapshotProfileWriter::kIsolateData;
-  WriteROData(clustered_stream);
+  // Needs to happen before WriteText, as we add information about the
+  // BSSsection in the text section as an initial InstructionsSection object.
+  WriteBss(vm);
 
   offset_space_ = vm ? V8SnapshotProfileWriter::kVmText
                      : V8SnapshotProfileWriter::kIsolateText;
-  // Needs to happen after WriteROData, because all image writers currently
-  // add the clustered data information to their output in WriteText().
-  WriteText(clustered_stream, vm);
+  WriteText(vm);
+
+  // Append the direct-mapped RO data objects after the clustered snapshot
+  // and then for ELF and assembly outputs, add appropriate sections with
+  // that combined data.
+  offset_space_ = vm ? V8SnapshotProfileWriter::kVmData
+                     : V8SnapshotProfileWriter::kIsolateData;
+  WriteROData(clustered_stream, vm);
 }
 
-void ImageWriter::WriteROData(WriteStream* stream) {
+void ImageWriter::WriteROData(NonStreamingWriteStream* stream, bool vm) {
 #if defined(DART_PRECOMPILER)
   const intptr_t start_position = stream->Position();
 #endif
-  stream->Align(kMaxObjectAlignment);
+  stream->Align(ImageWriter::kRODataAlignment);
 
   // Heap page starts here.
 
   intptr_t section_start = stream->Position();
 
   stream->WriteWord(next_data_offset_);  // Data length.
-  // Zero values for other image header fields.
-  stream->Align(kMaxObjectAlignment);
-  ASSERT(stream->Position() - section_start == Image::kHeaderSize);
+  stream->WriteWord(Image::kNoInstructionsSection);
+  // Zero values for the rest of the Image object header bytes.
+  stream->Align(Image::kHeaderSize);
+  ASSERT_EQUAL(stream->Position() - section_start, Image::kHeaderSize);
 #if defined(DART_PRECOMPILER)
   if (profile_writer_ != nullptr) {
     const intptr_t end_position = stream->Position();
@@ -453,116 +492,412 @@
 
   for (intptr_t i = 0; i < objects_.length(); i++) {
     const Object& obj = *objects_[i].obj_;
+#if defined(DART_PRECOMPILER)
     AutoTraceImage(obj, section_start, stream);
+#endif
+    auto const object_start = stream->Position();
 
     NoSafepointScope no_safepoint;
-    uword start = static_cast<uword>(obj.raw()) - kHeapObjectTag;
 
     // Write object header with the mark and read-only bits set.
-    uword marked_tags = obj.raw()->ptr()->tags_;
-    marked_tags = ObjectLayout::OldBit::update(true, marked_tags);
-    marked_tags = ObjectLayout::OldAndNotMarkedBit::update(false, marked_tags);
-    marked_tags =
-        ObjectLayout::OldAndNotRememberedBit::update(true, marked_tags);
-    marked_tags = ObjectLayout::NewBit::update(false, marked_tags);
-#if defined(HASH_IN_OBJECT_HEADER)
-    marked_tags |= static_cast<uword>(obj.raw()->ptr()->hash_) << 32;
-#endif
-
-#if defined(IS_SIMARM_X64)
+    stream->WriteTargetWord(GetMarkedTags(obj));
     if (obj.IsCompressedStackMaps()) {
       const CompressedStackMaps& map = CompressedStackMaps::Cast(obj);
-      auto const object_start = stream->Position();
-
       const intptr_t payload_size = map.payload_size();
-      const intptr_t size_in_bytes =
-          CompressedStackMapsSizeInSnapshot(payload_size);
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-
-      stream->WriteTargetWord(marked_tags);
       stream->WriteFixed<uint32_t>(map.raw()->ptr()->flags_and_size_);
       ASSERT_EQUAL(stream->Position() - object_start,
                    compiler::target::CompressedStackMaps::HeaderSize());
       stream->WriteBytes(map.raw()->ptr()->data(), payload_size);
-      stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
-    } else if (obj.IsString()) {
-      const String& str = String::Cast(obj);
-      RELEASE_ASSERT(String::GetCachedHash(str.raw()) != 0);
-      RELEASE_ASSERT(str.IsOneByteString() || str.IsTwoByteString());
-      const intptr_t size_in_bytes =
-          StringSizeInSnapshot(str.Length(), str.IsOneByteString());
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-
-      stream->WriteTargetWord(marked_tags);
-      stream->WriteTargetWord(static_cast<uword>(str.raw()->ptr()->length_));
-      stream->WriteTargetWord(static_cast<uword>(str.raw()->ptr()->hash_));
-      stream->WriteBytes(
-          reinterpret_cast<const void*>(start + String::kSizeofRawString),
-          StringPayloadSize(str.Length(), str.IsOneByteString()));
-      stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
     } else if (obj.IsCodeSourceMap()) {
       const CodeSourceMap& map = CodeSourceMap::Cast(obj);
-      const intptr_t size_in_bytes = CodeSourceMapSizeInSnapshot(map.Length());
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-
-      stream->WriteTargetWord(marked_tags);
       stream->WriteTargetWord(map.Length());
+      ASSERT_EQUAL(stream->Position() - object_start,
+                   compiler::target::CodeSourceMap::HeaderSize());
       stream->WriteBytes(map.Data(), map.Length());
-      stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
     } else if (obj.IsPcDescriptors()) {
       const PcDescriptors& desc = PcDescriptors::Cast(obj);
-
-      const intptr_t size_in_bytes = PcDescriptorsSizeInSnapshot(desc.Length());
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-
-      stream->WriteTargetWord(marked_tags);
       stream->WriteTargetWord(desc.Length());
+      ASSERT_EQUAL(stream->Position() - object_start,
+                   compiler::target::PcDescriptors::HeaderSize());
       stream->WriteBytes(desc.raw()->ptr()->data(), desc.Length());
-      stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
     } else {
       const Class& clazz = Class::Handle(obj.clazz());
-      FATAL1("Unsupported class %s in rodata section.\n", clazz.ToCString());
+      FATAL("Unsupported class %s in rodata section.\n", clazz.ToCString());
     }
-#else   // defined(IS_SIMARM_X64)
-    const uword end = start + obj.raw()->ptr()->HeapSize();
-
-    stream->WriteWord(marked_tags);
-    start += sizeof(uword);
-    for (uword* cursor = reinterpret_cast<uword*>(start);
-         cursor < reinterpret_cast<uword*>(end); cursor++) {
-      stream->WriteWord(*cursor);
-    }
-#endif  // defined(IS_SIMARM_X64)
+    stream->Align(compiler::target::ObjectAlignment::kObjectAlignment);
+    ASSERT_EQUAL(stream->Position() - object_start, SizeInSnapshot(obj));
   }
 }
 
+static UNLESS_DEBUG(constexpr) const uword kReadOnlyGCBits =
+    ObjectLayout::OldBit::encode(true) |
+    ObjectLayout::OldAndNotMarkedBit::encode(false) |
+    ObjectLayout::OldAndNotRememberedBit::encode(true) |
+    ObjectLayout::NewBit::encode(false);
+
+uword ImageWriter::GetMarkedTags(classid_t cid, intptr_t size) {
+  // ObjectLayout::SizeTag expects a size divisible by kObjectAlignment and
+  // checks this in debug mode, but the size on the target machine may not be
+  // divisible by the host machine's object alignment if they differ.
+  //
+  // We define [adjusted_size] as [size] * m, where m is the host alignment
+  // divided by the target alignment. This means [adjusted_size] encodes on the
+  // host machine to the same bits that decode to [size] on the target machine.
+  // That is,
+  //    [adjusted_size] / host align ==
+  //    [size] * (host align / target align) / host align ==
+  //    [size] / target align
+  //
+  // Since alignments are always powers of 2, we use shifts and logs.
+  const intptr_t adjusted_size =
+      size << (kObjectAlignmentLog2 -
+               compiler::target::ObjectAlignment::kObjectAlignmentLog2);
+
+  return kReadOnlyGCBits | ObjectLayout::ClassIdTag::encode(cid) |
+         ObjectLayout::SizeTag::encode(adjusted_size);
+}
+
+uword ImageWriter::GetMarkedTags(const Object& obj) {
+  return
+#if defined(HASH_IN_OBJECT_HEADER)
+      static_cast<uword>(obj.raw()->ptr()->hash_) << kBitsPerInt32 |
+#endif
+      GetMarkedTags(obj.raw()->GetClassId(), SizeInSnapshot(obj));
+}
+
+const char* ImageWriter::SectionSymbol(ProgramSection section, bool vm) const {
+  switch (section) {
+    case ProgramSection::Text:
+      return vm ? kVmSnapshotInstructionsAsmSymbol
+                : kIsolateSnapshotInstructionsAsmSymbol;
+    case ProgramSection::Data:
+      return vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
+    case ProgramSection::Bss:
+      return vm ? kVmSnapshotBssAsmSymbol : kIsolateSnapshotBssAsmSymbol;
+    case ProgramSection::BuildId:
+      return kSnapshotBuildIdAsmSymbol;
+  }
+  return nullptr;
+}
+
+void ImageWriter::WriteText(bool vm) {
+  Zone* zone = Thread::Current()->zone();
+
+  const bool bare_instruction_payloads =
+      FLAG_precompiled_mode && FLAG_use_bare_instructions;
+
+  // Start snapshot at page boundary.
+  ASSERT(ImageWriter::kTextAlignment >= VirtualMemory::PageSize());
+  if (!EnterSection(ProgramSection::Text, vm, ImageWriter::kTextAlignment)) {
+    return;
+  }
+
+  intptr_t text_offset = 0;
 #if defined(DART_PRECOMPILER)
+  // Parent used for later profile objects. Starts off as the Image. When
+  // writing bare instructions payloads, this is later updated with the
+  // InstructionsSection object which contains all the bare payloads.
+  V8SnapshotProfileWriter::ObjectId parent_id(offset_space_, text_offset);
+#endif
+
+  // This head also provides the gap to make the instructions snapshot
+  // look like a OldPage.
+  const intptr_t image_size = Utils::RoundUp(
+      next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
+  text_offset += WriteTargetWord(image_size);
+  // Output the offset to the InstructionsSection object from the start of the
+  // image, if any.
+  text_offset +=
+      WriteTargetWord(FLAG_precompiled_mode ? Image::kHeaderSize
+                                            : Image::kNoInstructionsSection);
+  // Zero values for the rest of the Image object header bytes.
+  text_offset += Align(Image::kHeaderSize, text_offset);
+  ASSERT_EQUAL(text_offset, Image::kHeaderSize);
+
+#if defined(DART_PRECOMPILER)
+  const char* instructions_symbol = SectionSymbol(ProgramSection::Text, vm);
+  ASSERT(instructions_symbol != nullptr);
+  const char* bss_symbol = SectionSymbol(ProgramSection::Bss, vm);
+  ASSERT(bss_symbol != nullptr);
+
+  if (FLAG_precompiled_mode) {
+    if (profile_writer_ != nullptr) {
+      profile_writer_->SetObjectTypeAndName(parent_id, image_type_,
+                                            instructions_symbol);
+      profile_writer_->AttributeBytesTo(parent_id, Image::kHeaderSize);
+      profile_writer_->AddRoot(parent_id);
+    }
+
+    const intptr_t section_header_length =
+        compiler::target::InstructionsSection::HeaderSize();
+    // Calculated using next_text_offset_, which doesn't include post-payload
+    // padding to object alignment. Note that if not in bare instructions mode,
+    // the section has no contents, instead the instructions objects follow it.
+    const intptr_t section_payload_length =
+        bare_instruction_payloads
+            ? next_text_offset_ - text_offset - section_header_length
+            : 0;
+    const intptr_t section_size =
+        compiler::target::InstructionsSection::InstanceSize(
+            section_payload_length);
+
+    const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
+    if (profile_writer_ != nullptr) {
+      profile_writer_->SetObjectTypeAndName(id, instructions_section_type_,
+                                            instructions_symbol);
+      profile_writer_->AttributeBytesTo(id,
+                                        section_size - section_payload_length);
+      const intptr_t element_offset = id.second - parent_id.second;
+      profile_writer_->AttributeReferenceTo(
+          parent_id,
+          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
+      // Later objects will have the InstructionsSection as a parent if in
+      // bare instructions mode, otherwise the image.
+      if (bare_instruction_payloads) {
+        parent_id = id;
+      }
+    }
+
+    // Add the RawInstructionsSection header.
+    text_offset +=
+        WriteTargetWord(GetMarkedTags(kInstructionsSectionCid, section_size));
+    // An InstructionsSection has five fields:
+    // 1) The length of the payload.
+    text_offset += WriteTargetWord(section_payload_length);
+    // 2) The BSS offset from this section.
+    text_offset += Relocation(text_offset, instructions_symbol, bss_symbol);
+    // 3) The relocated address of the instructions.
+    text_offset += WriteTargetWord(RelocatedAddress(instructions_symbol));
+    // 4) The GNU build ID note offset from this section.
+    text_offset += Relocation(text_offset, instructions_symbol,
+                              SectionSymbol(ProgramSection::BuildId, vm));
+
+    const intptr_t section_contents_alignment =
+        bare_instruction_payloads
+            ? compiler::target::Instructions::kBarePayloadAlignment
+            : compiler::target::ObjectAlignment::kObjectAlignment;
+    const intptr_t expected_size =
+        bare_instruction_payloads
+            ? compiler::target::InstructionsSection::HeaderSize()
+            : compiler::target::InstructionsSection::InstanceSize(0);
+    text_offset += Align(section_contents_alignment, text_offset);
+    ASSERT_EQUAL(text_offset - id.second, expected_size);
+  }
+#endif
+
+  FrameUnwindPrologue();
+
+  PcDescriptors& descriptors = PcDescriptors::Handle(zone);
+#if defined(DART_PRECOMPILER)
+  SnapshotTextObjectNamer namer(zone);
+#endif
+
+  ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
+  for (intptr_t i = 0; i < instructions_.length(); i++) {
+    auto& data = instructions_[i];
+    const bool is_trampoline = data.trampoline_bytes != nullptr;
+    ASSERT_EQUAL(data.text_offset_, text_offset);
+
+#if defined(DART_PRECOMPILER)
+    // We won't add trampolines as symbols, so their name need not be unique
+    // across different WriteText() calls.
+    const char* object_name = namer.SnapshotNameFor(
+        is_trampoline ? i : unique_symbol_counter_++, data);
+
+    if (profile_writer_ != nullptr) {
+      const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
+      auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
+      const intptr_t size = is_trampoline ? data.trampoline_length
+                                          : SizeInSnapshot(data.insns_->raw());
+      profile_writer_->SetObjectTypeAndName(id, type, object_name);
+      profile_writer_->AttributeBytesTo(id, size);
+      const intptr_t element_offset = id.second - parent_id.second;
+      profile_writer_->AttributeReferenceTo(
+          parent_id,
+          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
+    }
+#endif
+
+    if (is_trampoline) {
+      text_offset += WriteBytes(data.trampoline_bytes, data.trampoline_length);
+      delete[] data.trampoline_bytes;
+      data.trampoline_bytes = nullptr;
+      continue;
+    }
+
+    const intptr_t instr_start = text_offset;
+    const auto& code = *data.code_;
+    const auto& insns = *data.insns_;
+
+    // 1. Write from the object start to the payload start. This includes the
+    // object header and the fixed fields.  Not written for AOT snapshots using
+    // bare instructions.
+    if (!bare_instruction_payloads) {
+      NoSafepointScope no_safepoint;
+
+      // Write Instructions with the mark and read-only bits set.
+      text_offset += WriteTargetWord(GetMarkedTags(insns));
+      text_offset += WriteFixed(insns.raw_ptr()->size_and_flags_);
+      text_offset +=
+          Align(compiler::target::Instructions::kNonBarePayloadAlignment,
+                text_offset);
+    }
+
+    ASSERT_EQUAL(text_offset - instr_start,
+                 compiler::target::Instructions::HeaderSize());
+
+#if defined(DART_PRECOMPILER)
+    // 2. Add a symbol for the code at the entry point in precompiled snapshots.
+    // Linux's perf uses these labels.
+    AddCodeSymbol(code, object_name, text_offset);
+#endif
+
+    {
+      NoSafepointScope no_safepoint;
+
+      // 3. Write from the payload start to payload end. For AOT snapshots
+      // with bare instructions, this is the only part serialized other than
+      // any padding needed for alignment.
+      auto const payload_start =
+          reinterpret_cast<const uint8_t*>(insns.PayloadStart());
+      // Double-check the payload alignment, since we will load and write
+      // target-sized words starting from that address.
+      ASSERT(Utils::IsAligned(payload_start, compiler::target::kWordSize));
+      const uword payload_size = insns.Size();
+      descriptors = code.pc_descriptors();
+      PcDescriptors::Iterator iterator(
+          descriptors, /*kind_mask=*/PcDescriptorsLayout::kBSSRelocation);
+
+      auto const payload_end = payload_start + payload_size;
+      auto cursor = payload_start;
+      while (iterator.MoveNext()) {
+        ASSERT(FLAG_precompiled_mode);
+        auto const next_reloc_offset = iterator.PcOffset();
+        auto const next_reloc_address = payload_start + next_reloc_offset;
+        // We only generate BSS relocations that are target word-sized and at
+        // target word-aligned offsets in the payload. Double-check this..
+        ASSERT(
+            Utils::IsAligned(next_reloc_address, compiler::target::kWordSize));
+        text_offset += WriteBytes(cursor, next_reloc_address - cursor);
+
+#if defined(DART_PRECOMPILER)
+        // The instruction stream at the relocation position holds an offset
+        // into BSS corresponding to the symbol being resolved. This addend is
+        // factored into the relocation.
+        const auto addend = *reinterpret_cast<const compiler::target::word*>(
+            next_reloc_address);
+        text_offset += Relocation(text_offset, instructions_symbol, text_offset,
+                                  bss_symbol, /*target_offset=*/0, addend);
+#endif
+        cursor = next_reloc_address + compiler::target::kWordSize;
+      }
+      text_offset += WriteBytes(cursor, payload_end - cursor);
+    }
+
+    // 4. Add appropriate padding. Note we can't simply copy from the object
+    // because the host object may have less alignment filler than the target
+    // object in the cross-word case.
+    const intptr_t alignment =
+        bare_instruction_payloads
+            ? compiler::target::Instructions::kBarePayloadAlignment
+            : compiler::target::ObjectAlignment::kObjectAlignment;
+    text_offset += AlignWithBreakInstructions(alignment, text_offset);
+
+    ASSERT_EQUAL(text_offset - instr_start, SizeInSnapshot(insns.raw()));
+  }
+
+  // Should be a no-op unless writing bare instruction payloads, in which case
+  // we need to add post-payload padding for the InstructionsSection object.
+  // Since this follows instructions, we'll use break instructions for padding.
+  ASSERT(bare_instruction_payloads ||
+         Utils::IsAligned(text_offset,
+                          compiler::target::ObjectAlignment::kObjectAlignment));
+  text_offset += AlignWithBreakInstructions(
+      compiler::target::ObjectAlignment::kObjectAlignment, text_offset);
+
+  ASSERT_EQUAL(text_offset, image_size);
+
+  FrameUnwindEpilogue();
+
+  ExitSection(ProgramSection::Text, vm, text_offset);
+}
+
+intptr_t ImageWriter::AlignWithBreakInstructions(intptr_t alignment,
+                                                 intptr_t offset) {
+  intptr_t bytes_written = 0;
+  uword remaining;
+  for (remaining = Utils::RoundUp(offset, alignment) - offset;
+       remaining >= compiler::target::kWordSize;
+       remaining -= compiler::target::kWordSize) {
+    bytes_written += WriteTargetWord(kBreakInstructionFiller);
+  }
+#if defined(TARGET_ARCH_ARM)
+  // All instructions are 4 bytes long on ARM architectures, so on 32-bit ARM
+  // there won't be any padding.
+  ASSERT_EQUAL(remaining, 0);
+#elif defined(TARGET_ARCH_ARM64)
+  // All instructions are 4 bytes long on ARM architectures, so on 64-bit ARM
+  // there is only 0 or 4 bytes of padding.
+  if (remaining != 0) {
+    ASSERT_EQUAL(remaining, 4);
+    bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
+  }
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_IA32)
+  // The break instruction is a single byte, repeated to fill a word.
+  bytes_written += WriteBytes(&kBreakInstructionFiller, remaining);
+#else
+#error Unexpected architecture.
+#endif
+  ASSERT_EQUAL(bytes_written, Utils::RoundUp(offset, alignment) - offset);
+  return bytes_written;
+}
+
+#if defined(DART_PRECOMPILER)
+
+// Indices are log2(size in bytes).
+static constexpr const char* kSizeDirectives[] = {".byte", ".2byte", ".long",
+                                                  ".quad"};
+
+static constexpr const char* kWordDirective =
+    kSizeDirectives[compiler::target::kWordSizeLog2];
+
 class DwarfAssemblyStream : public DwarfWriteStream {
  public:
-  explicit DwarfAssemblyStream(StreamingWriteStream* stream)
+  explicit DwarfAssemblyStream(BaseWriteStream* stream)
       : stream_(ASSERT_NOTNULL(stream)) {}
 
-  void sleb128(intptr_t value) { Print(".sleb128 %" Pd "\n", value); }
-  void uleb128(uintptr_t value) { Print(".uleb128 %" Pd "\n", value); }
-  void u1(uint8_t value) { Print(".byte %u\n", value); }
-  void u2(uint16_t value) { Print(".2byte %u\n", value); }
-  void u4(uint32_t value) { Print(".4byte %" Pu32 "\n", value); }
-  void u8(uint64_t value) { Print(".8byte %" Pu64 "\n", value); }
-  void string(const char* cstr) {     // NOLINT
-    Print(".string \"%s\"\n", cstr);  // NOLINT
+  void sleb128(intptr_t value) { stream_->Printf(".sleb128 %" Pd "\n", value); }
+  void uleb128(uintptr_t value) {
+    stream_->Printf(".uleb128 %" Pd "\n", value);
+  }
+  void u1(uint8_t value) {
+    stream_->Printf("%s %u\n", kSizeDirectives[kInt8SizeLog2], value);
+  }
+  void u2(uint16_t value) {
+    stream_->Printf("%s %u\n", kSizeDirectives[kInt16SizeLog2], value);
+  }
+  void u4(uint32_t value) {
+    stream_->Printf("%s %" Pu32 "\n", kSizeDirectives[kInt32SizeLog2], value);
+  }
+  void u8(uint64_t value) {
+    stream_->Printf("%s %" Pu64 "\n", kSizeDirectives[kInt64SizeLog2], value);
+  }
+  void string(const char* cstr) {               // NOLINT
+    stream_->Printf(".string \"%s\"\n", cstr);  // NOLINT
   }
   // Uses labels, so doesn't output to start or return a useful fixup position.
   intptr_t ReserveSize(const char* prefix, intptr_t* start) {
     // Assignment to temp works around buggy Mac assembler.
-    Print("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix, prefix);
-    Print(".4byte L%s_size\n", prefix);
-    Print(".L%s_start:\n", prefix);
+    stream_->Printf("L%s_size = .L%s_end - .L%s_start\n", prefix, prefix,
+                    prefix);
+    stream_->Printf("%s L%s_size\n", kSizeDirectives[kInt32SizeLog2], prefix);
+    stream_->Printf(".L%s_start:\n", prefix);
     return -1;
   }
   // Just need to label the end so the assembler can calculate the size, so
   // start and the fixup position is unused.
   void SetSize(intptr_t fixup, const char* prefix, intptr_t start) {
-    Print(".L%s_end:\n", prefix);
+    stream_->Printf(".L%s_end:\n", prefix);
   }
   void OffsetFromSymbol(const char* symbol, intptr_t offset) {
     if (offset == 0) {
@@ -575,51 +910,54 @@
                                     intptr_t offset1,
                                     const char* symbol2,
                                     intptr_t offset2) {
-    Print(".uleb128 %s - %s + %" Pd "\n", symbol1, symbol2, offset1 - offset2);
+    stream_->Printf(".uleb128 %s - %s + %" Pd "\n", symbol1, symbol2,
+                    offset1 - offset2);
   }
 
   // No-op, we'll be using labels.
   void InitializeAbstractOrigins(intptr_t size) {}
   void RegisterAbstractOrigin(intptr_t index) {
     // Label for DW_AT_abstract_origin references
-    Print(".Lfunc%" Pd ":\n", index);
+    stream_->Printf(".Lfunc%" Pd ":\n", index);
   }
   void AbstractOrigin(intptr_t index) {
     // Assignment to temp works around buggy Mac assembler.
-    Print("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index, kDebugInfoLabel);
-    Print(".4byte Ltemp%" Pd "\n", temp_);
+    stream_->Printf("Ltemp%" Pd " = .Lfunc%" Pd " - %s\n", temp_, index,
+                    kDebugInfoLabel);
+    stream_->Printf("%s Ltemp%" Pd "\n", kSizeDirectives[kInt32SizeLog2],
+                    temp_);
     temp_++;
   }
 
   // Methods for writing the assembly prologues for various DWARF sections.
   void AbbreviationsPrologue() {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-    Print(".section __DWARF,__debug_abbrev,regular,debug\n");
+    stream_->WriteString(".section __DWARF,__debug_abbrev,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-    Print(".section .debug_abbrev,\"\"\n");
+    stream_->WriteString(".section .debug_abbrev,\"\"\n");
 #else
     UNIMPLEMENTED();
 #endif
   }
   void DebugInfoPrologue() {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-    Print(".section __DWARF,__debug_info,regular,debug\n");
+    stream_->WriteString(".section __DWARF,__debug_info,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-    Print(".section .debug_info,\"\"\n");
+    stream_->WriteString(".section .debug_info,\"\"\n");
 #else
     UNIMPLEMENTED();
 #endif
     // Used to calculate abstract origin values.
-    Print("%s:\n", kDebugInfoLabel);
+    stream_->Printf("%s:\n", kDebugInfoLabel);
   }
   void LineNumberProgramPrologue() {
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-    Print(".section __DWARF,__debug_line,regular,debug\n");
+    stream_->WriteString(".section __DWARF,__debug_line,regular,debug\n");
 #elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                \
     defined(TARGET_OS_FUCHSIA)
-    Print(".section .debug_line,\"\"\n");
+    stream_->WriteString(".section .debug_line,\"\"\n");
 #else
     UNIMPLEMENTED();
 #endif
@@ -628,35 +966,20 @@
  private:
   static constexpr const char* kDebugInfoLabel = ".Ldebug_info";
 
-  void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3) {
-    va_list args;
-    va_start(args, format);
-    stream_->VPrint(format, args);
-    va_end(args);
+  void PrintNamedAddress(const char* name) {
+    stream_->Printf("%s %s\n", kWordDirective, name);
   }
-
-#if defined(TARGET_ARCH_IS_32_BIT)
-#define FORM_ADDR ".4byte"
-#elif defined(TARGET_ARCH_IS_64_BIT)
-#define FORM_ADDR ".8byte"
-#endif
-
-  void PrintNamedAddress(const char* name) { Print(FORM_ADDR " %s\n", name); }
   void PrintNamedAddressWithOffset(const char* name, intptr_t offset) {
-    Print(FORM_ADDR " %s + %" Pd "\n", name, offset);
+    stream_->Printf("%s %s + %" Pd "\n", kWordDirective, name, offset);
   }
 
-#undef FORM_ADDR
-
-  StreamingWriteStream* const stream_;
+  BaseWriteStream* const stream_;
   intptr_t temp_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(DwarfAssemblyStream);
 };
-#endif
 
 static inline Dwarf* AddDwarfIfUnstripped(Zone* zone, bool strip, Elf* elf) {
-#if defined(DART_PRECOMPILER)
   if (!strip) {
     if (elf != nullptr) {
       // Reuse the existing DWARF object.
@@ -665,24 +988,21 @@
     }
     return new (zone) Dwarf(zone);
   }
-#endif
   return nullptr;
 }
 
 AssemblyImageWriter::AssemblyImageWriter(Thread* thread,
-                                         Dart_StreamingWriteCallback callback,
-                                         void* callback_data,
+                                         BaseWriteStream* stream,
                                          bool strip,
                                          Elf* debug_elf)
     : ImageWriter(thread),
-      assembly_stream_(512 * KB, callback, callback_data),
+      assembly_stream_(stream),
       assembly_dwarf_(AddDwarfIfUnstripped(thread->zone(), strip, debug_elf)),
       debug_elf_(debug_elf) {}
 
 void AssemblyImageWriter::Finalize() {
-#if defined(DART_PRECOMPILER)
   if (assembly_dwarf_ != nullptr) {
-    DwarfAssemblyStream dwarf_stream(&assembly_stream_);
+    DwarfAssemblyStream dwarf_stream(assembly_stream_);
     dwarf_stream.AbbreviationsPrologue();
     assembly_dwarf_->WriteAbbreviations(&dwarf_stream);
     dwarf_stream.DebugInfoPrologue();
@@ -693,10 +1013,8 @@
   if (debug_elf_ != nullptr) {
     debug_elf_->Finalize();
   }
-#endif
 }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
 static void EnsureAssemblerIdentifier(char* label) {
   for (char c = *label; c != '\0'; c = *++label) {
     if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) ||
@@ -706,7 +1024,6 @@
     *label = '_';
   }
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 const char* SnapshotTextObjectNamer::SnapshotNameFor(intptr_t code_index,
                                                      const Code& code) {
@@ -751,356 +1068,188 @@
   return SnapshotNameFor(index, *data.code_);
 }
 
-void AssemblyImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
-#if defined(DART_PRECOMPILED_RUNTIME)
-  UNREACHABLE();
-#else
-  Zone* zone = Thread::Current()->zone();
-
-  const bool bare_instruction_payloads =
-      FLAG_precompiled_mode && FLAG_use_bare_instructions;
-
-#if defined(DART_PRECOMPILER)
-  const char* bss_symbol =
-      vm ? "_kDartVmSnapshotBss" : "_kDartIsolateSnapshotBss";
-  intptr_t debug_segment_base = 0;
-  if (debug_elf_ != nullptr) {
-    debug_segment_base = debug_elf_->NextMemoryOffset();
-  }
-#endif
-
-  const char* instructions_symbol = vm ? kVmSnapshotInstructionsAsmSymbol
-                                       : kIsolateSnapshotInstructionsAsmSymbol;
-  assembly_stream_.Print(".text\n");
-  assembly_stream_.Print(".globl %s\n", instructions_symbol);
-
-  // Start snapshot at page boundary.
-  ASSERT(VirtualMemory::PageSize() >= kMaxObjectAlignment);
-  ASSERT(VirtualMemory::PageSize() >= Image::kBssAlignment);
-  Align(VirtualMemory::PageSize());
-  assembly_stream_.Print("%s:\n", instructions_symbol);
-
-  intptr_t text_offset = 0;
-#if defined(DART_PRECOMPILER)
-  // Parent used for later profile objects. Starts off as the Image. When
-  // writing bare instructions payloads, this is later updated with the
-  // InstructionsSection object which contains all the bare payloads.
-  V8SnapshotProfileWriter::ObjectId parent_id(offset_space_, text_offset);
-#endif
-
-  // This head also provides the gap to make the instructions snapshot
-  // look like a OldPage.
-  const intptr_t image_size = Utils::RoundUp(
-      next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
-  text_offset += WriteWordLiteralText(image_size);
-
-#if defined(DART_PRECOMPILER)
-  assembly_stream_.Print("%s %s - %s\n", kLiteralPrefix, bss_symbol,
-                         instructions_symbol);
-  text_offset += compiler::target::kWordSize;
-#else
-  text_offset += WriteWordLiteralText(0);  // No relocations.
-#endif
-
-  text_offset += Align(kMaxObjectAlignment, text_offset);
-  ASSERT_EQUAL(text_offset, Image::kHeaderSize);
-#if defined(DART_PRECOMPILER)
-  if (profile_writer_ != nullptr) {
-    profile_writer_->SetObjectTypeAndName(parent_id, "Image",
-                                          instructions_symbol);
-    // Assign post-instruction padding to the Image, unless we're writing bare
-    // instruction payloads, in which case we'll assign it to the
-    // InstructionsSection object.
-    const intptr_t padding =
-        bare_instruction_payloads ? 0 : image_size - next_text_offset_;
-    profile_writer_->AttributeBytesTo(parent_id, Image::kHeaderSize + padding);
-    profile_writer_->AddRoot(parent_id);
-  }
-#endif
-
-  if (bare_instruction_payloads) {
-#if defined(DART_PRECOMPILER)
-    if (profile_writer_ != nullptr) {
-      const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
-      profile_writer_->SetObjectTypeAndName(id, instructions_section_type_,
-                                            instructions_symbol);
-      const intptr_t padding = image_size - next_text_offset_;
-      profile_writer_->AttributeBytesTo(
-          id, compiler::target::InstructionsSection::HeaderSize() + padding);
-      const intptr_t element_offset = id.second - parent_id.second;
-      profile_writer_->AttributeReferenceTo(
-          parent_id,
-          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
-      // Later objects will have the InstructionsSection as a parent.
-      parent_id = id;
-    }
-#endif
-    const intptr_t section_size = image_size - text_offset;
-    // Add the RawInstructionsSection header.
-    const compiler::target::uword marked_tags =
-        ObjectLayout::OldBit::encode(true) |
-        ObjectLayout::OldAndNotMarkedBit::encode(false) |
-        ObjectLayout::OldAndNotRememberedBit::encode(true) |
-        ObjectLayout::NewBit::encode(false) |
-        ObjectLayout::SizeTag::encode(AdjustObjectSizeForTarget(section_size)) |
-        ObjectLayout::ClassIdTag::encode(kInstructionsSectionCid);
-    text_offset += WriteWordLiteralText(marked_tags);
-    // Calculated using next_text_offset_, which doesn't include post-payload
-    // padding to object alignment.
-    const intptr_t instructions_length =
-        next_text_offset_ - (text_offset + compiler::target::kWordSize);
-    text_offset += WriteWordLiteralText(instructions_length);
-  }
-
-  FrameUnwindPrologue();
-
-  PcDescriptors& descriptors = PcDescriptors::Handle(zone);
-  SnapshotTextObjectNamer namer(zone);
-
-  ASSERT(offset_space_ != V8SnapshotProfileWriter::kSnapshot);
-  for (intptr_t i = 0; i < instructions_.length(); i++) {
-    auto& data = instructions_[i];
-    const bool is_trampoline = data.trampoline_bytes != nullptr;
-    ASSERT_EQUAL(data.text_offset_, text_offset);
-
-    intptr_t dwarf_index = i;
-#if defined(DART_PRECOMPILER)
-    if (!is_trampoline && assembly_dwarf_ != nullptr) {
-      dwarf_index =
-          assembly_dwarf_->AddCode(*data.code_, SegmentRelativeOffset(vm));
-    }
-#endif
-
-    const auto object_name = namer.SnapshotNameFor(dwarf_index, data);
-
-#if defined(DART_PRECOMPILER)
-    if (profile_writer_ != nullptr) {
-      const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
-      auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
-      const intptr_t size = is_trampoline ? data.trampoline_length
-                                          : SizeInSnapshot(data.insns_->raw());
-      profile_writer_->SetObjectTypeAndName(id, type, object_name);
-      profile_writer_->AttributeBytesTo(id, size);
-      const intptr_t element_offset = id.second - parent_id.second;
-      profile_writer_->AttributeReferenceTo(
-          parent_id,
-          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
-    }
-#endif
-
-    if (is_trampoline) {
-      const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
-      const auto end = start + data.trampoline_length;
-      text_offset += WriteByteSequence(start, end);
-      delete[] data.trampoline_bytes;
-      data.trampoline_bytes = nullptr;
-      continue;
-    }
-
-    const intptr_t instr_start = text_offset;
-
-    const auto& code = *data.code_;
-    const auto& insns = *data.insns_;
-    descriptors = code.pc_descriptors();
-
-    const uword payload_start = insns.PayloadStart();
-
-    // 1. Write from the object start to the payload start. This includes the
-    // object header and the fixed fields.  Not written for AOT snapshots using
-    // bare instructions.
-    if (!bare_instruction_payloads) {
-      NoSafepointScope no_safepoint;
-
-      // Write Instructions with the mark and read-only bits set.
-      uword marked_tags = insns.raw_ptr()->tags_;
-      marked_tags = ObjectLayout::OldBit::update(true, marked_tags);
-      marked_tags =
-          ObjectLayout::OldAndNotMarkedBit::update(false, marked_tags);
-      marked_tags =
-          ObjectLayout::OldAndNotRememberedBit::update(true, marked_tags);
-      marked_tags = ObjectLayout::NewBit::update(false, marked_tags);
-#if defined(HASH_IN_OBJECT_HEADER)
-      // Can't use GetObjectTagsAndHash because the update methods discard the
-      // high bits.
-      marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
-#endif
-
-#if defined(IS_SIMARM_X64)
-      const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-      WriteWordLiteralText(marked_tags);
-      text_offset += sizeof(compiler::target::uword);
-      WriteWordLiteralText(insns.raw_ptr()->size_and_flags_);
-      text_offset += sizeof(compiler::target::uword);
-#else   // defined(IS_SIMARM_X64)
-      uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
-      WriteWordLiteralText(marked_tags);
-      object_start += sizeof(uword);
-      text_offset += sizeof(uword);
-      text_offset += WriteByteSequence(object_start, payload_start);
-#endif  // defined(IS_SIMARM_X64)
-
-      ASSERT((text_offset - instr_start) ==
-             compiler::target::Instructions::HeaderSize());
-    }
-
-#if defined(DART_PRECOMPILER)
-    if (debug_elf_ != nullptr) {
-      debug_elf_->dwarf()->AddCode(code, {vm, text_offset});
-    }
-#endif
-    // 2. Write a label at the entry point.
-    // Linux's perf uses these labels.
-    assembly_stream_.Print("%s:\n", object_name);
-
-    {
-      // 3. Write from the payload start to payload end. For AOT snapshots
-      // with bare instructions, this is the only part serialized.
-      NoSafepointScope no_safepoint;
-      assert(kBareInstructionsAlignment <=
-             compiler::target::ObjectAlignment::kObjectAlignment);
-      const auto payload_align = bare_instruction_payloads
-                                     ? kBareInstructionsAlignment
-                                     : sizeof(compiler::target::uword);
-      const uword payload_size = Utils::RoundUp(insns.Size(), payload_align);
-      const uword payload_end = payload_start + payload_size;
-
-      ASSERT(Utils::IsAligned(text_offset, payload_align));
-
-#if defined(DART_PRECOMPILER)
-      PcDescriptors::Iterator iterator(descriptors,
-                                       PcDescriptorsLayout::kBSSRelocation);
-      uword next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
-
-      // We only generate BSS relocations that are word-sized and at
-      // word-aligned offsets in the payload.
-      auto const possible_relocations_end =
-          Utils::RoundDown(payload_end, sizeof(compiler::target::uword));
-      for (uword cursor = payload_start; cursor < possible_relocations_end;
-           cursor += sizeof(compiler::target::uword)) {
-        compiler::target::uword data =
-            *reinterpret_cast<compiler::target::uword*>(cursor);
-        if ((cursor - payload_start) == next_reloc_offset) {
-          assembly_stream_.Print("%s %s - (.) + %" Pd "\n", kLiteralPrefix,
-                                 bss_symbol, /*addend=*/data);
-          text_offset += compiler::target::kWordSize;
-          next_reloc_offset = iterator.MoveNext() ? iterator.PcOffset() : -1;
-        } else {
-          text_offset += WriteWordLiteralText(data);
-        }
-      }
-      assert(next_reloc_offset != (possible_relocations_end - payload_start));
-      text_offset += WriteByteSequence(possible_relocations_end, payload_end);
-#else
-      text_offset += WriteByteSequence(payload_start, payload_end);
-#endif
-
-      // 4. Write from the payload end to object end. Note we can't simply copy
-      // from the object because the host object may have less alignment filler
-      // than the target object in the cross-word case. Not written for AOT
-      // snapshots using bare instructions.
-      if (!bare_instruction_payloads) {
-        uword unaligned_size =
-            compiler::target::Instructions::HeaderSize() + payload_size;
-        uword alignment_size =
-            Utils::RoundUp(
-                unaligned_size,
-                compiler::target::ObjectAlignment::kObjectAlignment) -
-            unaligned_size;
-        while (alignment_size > 0) {
-          text_offset += WriteWordLiteralText(kBreakInstructionFiller);
-          alignment_size -= sizeof(compiler::target::uword);
-        }
-
-        ASSERT(kWordSize != compiler::target::kWordSize ||
-               (text_offset - instr_start) == insns.raw()->ptr()->HeapSize());
-      }
-    }
-
-    ASSERT((text_offset - instr_start) == SizeInSnapshot(insns.raw()));
-  }
-
-  // Should be a no-op unless writing bare instruction payloads, in which case
-  // we need to add post-payload padding to the object alignment. The alignment
-  // needs to match the one we used for image_size above.
-  text_offset +=
-      Align(compiler::target::ObjectAlignment::kObjectAlignment, text_offset);
-
-  ASSERT_EQUAL(text_offset, image_size);
-
-  FrameUnwindEpilogue();
-
-#if defined(DART_PRECOMPILER)
-  if (debug_elf_ != nullptr) {
-    // We need to generate a text segment of the appropriate size in the ELF
-    // for two reasons:
-    //
-    // * We need unique virtual addresses for each text section in the DWARF
-    //   file and that the virtual addresses for payloads within those sections
-    //   do not overlap.
-    //
-    // * Our tools for converting DWARF stack traces back to "normal" Dart
-    //   stack traces calculate an offset into the appropriate instructions
-    //   section, and then add that offset to the virtual address of the
-    //   corresponding segment to get the virtual address for the frame.
-    //
-    // Since we don't want to add the actual contents of the segment in the
-    // separate debugging information, we pass nullptr for the bytes, which
-    // creates an appropriate NOBITS section instead of PROGBITS.
-    auto const debug_segment_base2 = debug_elf_->AddText(
-        instructions_symbol, /*bytes=*/nullptr, text_offset);
-    // Double-check that no other ELF sections were added in the middle of
-    // writing the text section.
-    ASSERT(debug_segment_base2 == debug_segment_base);
-  }
-
-  assembly_stream_.Print(".bss\n");
-  // Align the BSS contents as expected by the Image class.
-  Align(Image::kBssAlignment);
-  assembly_stream_.Print("%s:\n", bss_symbol);
-
+void AssemblyImageWriter::WriteBss(bool vm) {
+  EnterSection(ProgramSection::Bss, vm, ImageWriter::kBssAlignment);
   auto const entry_count = vm ? BSS::kVmEntryCount : BSS::kIsolateEntryCount;
   for (intptr_t i = 0; i < entry_count; i++) {
-    WriteWordLiteralText(0);
+    // All bytes in the .bss section must be zero.
+    WriteTargetWord(0);
   }
-#endif
+  ExitSection(ProgramSection::Bss, vm,
+              entry_count * compiler::target::kWordSize);
+}
 
+void AssemblyImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream,
+                                      bool vm) {
+  ImageWriter::WriteROData(clustered_stream, vm);
+  if (!EnterSection(ProgramSection::Data, vm, ImageWriter::kRODataAlignment)) {
+    return;
+  }
+  WriteBytes(clustered_stream->buffer(), clustered_stream->bytes_written());
+  ExitSection(ProgramSection::Data, vm, clustered_stream->bytes_written());
+}
+
+bool AssemblyImageWriter::EnterSection(ProgramSection section,
+                                       bool vm,
+                                       intptr_t alignment) {
+  ASSERT(FLAG_precompiled_mode);
+  ASSERT(current_section_symbol_ == nullptr);
+  bool global_symbol = false;
+  switch (section) {
+    case ProgramSection::Text:
+      assembly_stream_->WriteString(".text\n");
+      global_symbol = true;
+      break;
+    case ProgramSection::Data:
 #if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) ||                  \
     defined(TARGET_OS_FUCHSIA)
-  assembly_stream_.Print(".section .rodata\n");
+      assembly_stream_->WriteString(".section .rodata\n");
 #elif defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  assembly_stream_.Print(".const\n");
+      assembly_stream_->WriteString(".const\n");
 #else
-  UNIMPLEMENTED();
+      UNIMPLEMENTED();
 #endif
-
-  const char* data_symbol =
-      vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
-  assembly_stream_.Print(".globl %s\n", data_symbol);
-  Align(kMaxObjectAlignment);
-  assembly_stream_.Print("%s:\n", data_symbol);
-  const uword buffer = reinterpret_cast<uword>(clustered_stream->buffer());
-  const intptr_t length = clustered_stream->bytes_written();
-  WriteByteSequence(buffer, buffer + length);
-#if defined(DART_PRECOMPILER)
-  if (debug_elf_ != nullptr) {
-    // Add a NoBits section for the ROData as well.
-    debug_elf_->AddROData(data_symbol, clustered_stream->buffer(), length);
+      global_symbol = true;
+      break;
+    case ProgramSection::Bss:
+      assembly_stream_->WriteString(".bss\n");
+      break;
+    case ProgramSection::BuildId:
+      break;
   }
-#endif  // defined(DART_PRECOMPILER)
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  current_section_symbol_ = SectionSymbol(section, vm);
+  ASSERT(current_section_symbol_ != nullptr);
+  if (global_symbol) {
+    assembly_stream_->Printf(".globl %s\n", current_section_symbol_);
+  }
+  Align(alignment);
+  assembly_stream_->Printf("%s:\n", current_section_symbol_);
+  return true;
+}
+
+static void ElfAddSection(Elf* elf,
+                          ImageWriter::ProgramSection section,
+                          const char* symbol,
+                          const uint8_t* bytes,
+                          intptr_t size) {
+  if (elf == nullptr) return;
+  switch (section) {
+    case ImageWriter::ProgramSection::Text:
+      elf->AddText(symbol, bytes, size);
+      break;
+    case ImageWriter::ProgramSection::Data:
+      elf->AddROData(symbol, bytes, size);
+      break;
+    default:
+      // Other sections are handled by the Elf object internally.
+      break;
+  }
+}
+
+void AssemblyImageWriter::ExitSection(ProgramSection name,
+                                      bool vm,
+                                      intptr_t size) {
+  // We should still be in the same section as the last EnterSection.
+  ASSERT(current_section_symbol_ != nullptr);
+  ASSERT_EQUAL(strcmp(SectionSymbol(name, vm), current_section_symbol_), 0);
+  // We need to generate a text segment of the appropriate size in the ELF
+  // for two reasons:
+  //
+  // * We need unique virtual addresses for each text section in the DWARF
+  //   file and that the virtual addresses for payloads within those sections
+  //   do not overlap.
+  //
+  // * Our tools for converting DWARF stack traces back to "normal" Dart
+  //   stack traces calculate an offset into the appropriate instructions
+  //   section, and then add that offset to the virtual address of the
+  //   corresponding segment to get the virtual address for the frame.
+  //
+  // Since we don't want to add the actual contents of the segment in the
+  // separate debugging information, we pass nullptr for the bytes, which
+  // creates an appropriate NOBITS section instead of PROGBITS.
+  ElfAddSection(debug_elf_, name, current_section_symbol_, /*bytes=*/nullptr,
+                size);
+  current_section_symbol_ = nullptr;
+}
+
+intptr_t AssemblyImageWriter::WriteTargetWord(word value) {
+  ASSERT(compiler::target::kBitsPerWord == kBitsPerWord ||
+         Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value));
+  // Padding is helpful for comparing the .S with --disassemble.
+  assembly_stream_->Printf("%s 0x%0.*" Px "\n", kWordDirective,
+                           2 * compiler::target::kWordSize, value);
+  return compiler::target::kWordSize;
+}
+
+intptr_t AssemblyImageWriter::Relocation(intptr_t section_offset,
+                                         const char* source_symbol,
+                                         intptr_t source_offset,
+                                         const char* target_symbol,
+                                         intptr_t target_offset,
+                                         intptr_t target_addend) {
+  ASSERT(source_symbol != nullptr);
+  ASSERT(target_symbol != nullptr);
+
+  // TODO(dartbug.com/43274): Remove once we generate consistent build IDs
+  // between assembly snapshots and their debugging information.
+  const char* build_id_symbol =
+      SectionSymbol(ProgramSection::BuildId, /*vm=*/false);
+  if (strcmp(target_symbol, build_id_symbol) == 0) {
+    return WriteTargetWord(Image::kNoBuildId);
+  }
+
+  // All relocations are word-sized.
+  assembly_stream_->Printf("%s ", kWordDirective);
+  if (strcmp(target_symbol, current_section_symbol_) == 0 &&
+      target_offset == section_offset) {
+    assembly_stream_->WriteString("(.)");
+  } else {
+    assembly_stream_->Printf("%s", target_symbol);
+    if (target_offset != 0) {
+      assembly_stream_->Printf(" + %" Pd "", target_offset);
+    }
+  }
+  if (target_addend != 0) {
+    assembly_stream_->Printf(" + %" Pd "", target_addend);
+  }
+  if (strcmp(source_symbol, current_section_symbol_) == 0 &&
+      source_offset == section_offset) {
+    assembly_stream_->WriteString(" - (.)");
+  } else {
+    assembly_stream_->Printf(" - %s", source_symbol);
+    if (source_offset != 0) {
+      assembly_stream_->Printf(" - %" Pd "", source_offset);
+    }
+  }
+  assembly_stream_->WriteString("\n");
+  return compiler::target::kWordSize;
+}
+
+void AssemblyImageWriter::AddCodeSymbol(const Code& code,
+                                        const char* symbol,
+                                        intptr_t offset) {
+  if (assembly_dwarf_ != nullptr) {
+    assembly_dwarf_->AddCode(code, symbol);
+  }
+  if (debug_elf_ != nullptr) {
+    debug_elf_->dwarf()->AddCode(code, symbol);
+    debug_elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
+  }
+  assembly_stream_->Printf("%s:\n", symbol);
 }
 
 void AssemblyImageWriter::FrameUnwindPrologue() {
   // Creates DWARF's .debug_frame
   // CFI = Call frame information
   // CFA = Canonical frame address
-  assembly_stream_.Print(".cfi_startproc\n");
+  assembly_stream_->WriteString(".cfi_startproc\n");
 
 #if defined(TARGET_ARCH_X64)
-  assembly_stream_.Print(".cfi_def_cfa rbp, 0\n");  // CFA is fp+0
-  assembly_stream_.Print(".cfi_offset rbp, 0\n");   // saved fp is *(CFA+0)
-  assembly_stream_.Print(".cfi_offset rip, 8\n");   // saved pc is *(CFA+8)
+  assembly_stream_->WriteString(".cfi_def_cfa rbp, 0\n");  // CFA is fp+0
+  assembly_stream_->WriteString(
+      ".cfi_offset rbp, 0\n");  // saved fp is *(CFA+0)
+  assembly_stream_->WriteString(
+      ".cfi_offset rip, 8\n");  // saved pc is *(CFA+8)
   // saved sp is CFA+16
   // Should be ".cfi_value_offset rsp, 16", but requires gcc newer than late
   // 2016 and not supported by Android's libunwind.
@@ -1109,14 +1258,16 @@
   // uleb128 size of operation     2
   // DW_OP_plus_uconst          0x23
   // uleb128 addend               16
-  assembly_stream_.Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
+  assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
 
 #elif defined(TARGET_ARCH_ARM64)
   COMPILE_ASSERT(FP == R29);
   COMPILE_ASSERT(LR == R30);
-  assembly_stream_.Print(".cfi_def_cfa x29, 0\n");  // CFA is fp+0
-  assembly_stream_.Print(".cfi_offset x29, 0\n");   // saved fp is *(CFA+0)
-  assembly_stream_.Print(".cfi_offset x30, 8\n");   // saved pc is *(CFA+8)
+  assembly_stream_->WriteString(".cfi_def_cfa x29, 0\n");  // CFA is fp+0
+  assembly_stream_->WriteString(
+      ".cfi_offset x29, 0\n");  // saved fp is *(CFA+0)
+  assembly_stream_->WriteString(
+      ".cfi_offset x30, 8\n");  // saved pc is *(CFA+8)
   // saved sp is CFA+16
   // Should be ".cfi_value_offset sp, 16", but requires gcc newer than late
   // 2016 and not supported by Android's libunwind.
@@ -1125,19 +1276,20 @@
   // uleb128 size of operation     2
   // DW_OP_plus_uconst          0x23
   // uleb128 addend               16
-  assembly_stream_.Print(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
+  assembly_stream_->WriteString(".cfi_escape 0x10, 31, 2, 0x23, 16\n");
 
 #elif defined(TARGET_ARCH_ARM)
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
   COMPILE_ASSERT(FP == R7);
-  assembly_stream_.Print(".cfi_def_cfa r7, 0\n");  // CFA is fp+j0
-  assembly_stream_.Print(".cfi_offset r7, 0\n");   // saved fp is *(CFA+0)
+  assembly_stream_->WriteString(".cfi_def_cfa r7, 0\n");  // CFA is fp+j0
+  assembly_stream_->WriteString(".cfi_offset r7, 0\n");  // saved fp is *(CFA+0)
 #else
   COMPILE_ASSERT(FP == R11);
-  assembly_stream_.Print(".cfi_def_cfa r11, 0\n");  // CFA is fp+0
-  assembly_stream_.Print(".cfi_offset r11, 0\n");   // saved fp is *(CFA+0)
+  assembly_stream_->WriteString(".cfi_def_cfa r11, 0\n");  // CFA is fp+0
+  assembly_stream_->WriteString(
+      ".cfi_offset r11, 0\n");  // saved fp is *(CFA+0)
 #endif
-  assembly_stream_.Print(".cfi_offset lr, 4\n");   // saved pc is *(CFA+4)
+  assembly_stream_->WriteString(".cfi_offset lr, 4\n");  // saved pc is *(CFA+4)
   // saved sp is CFA+8
   // Should be ".cfi_value_offset sp, 8", but requires gcc newer than late
   // 2016 and not supported by Android's libunwind.
@@ -1146,382 +1298,203 @@
   // uleb128 size of operation     2
   // DW_OP_plus_uconst          0x23
   // uleb128 addend                8
-  assembly_stream_.Print(".cfi_escape 0x10, 13, 2, 0x23, 8\n");
+  assembly_stream_->WriteString(".cfi_escape 0x10, 13, 2, 0x23, 8\n");
 
 // libunwind on ARM may use .ARM.exidx instead of .debug_frame
 #if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
   COMPILE_ASSERT(FP == R11);
-  assembly_stream_.Print(".fnstart\n");
-  assembly_stream_.Print(".save {r11, lr}\n");
-  assembly_stream_.Print(".setfp r11, sp, #0\n");
+  assembly_stream_->WriteString(".fnstart\n");
+  assembly_stream_->WriteString(".save {r11, lr}\n");
+  assembly_stream_->WriteString(".setfp r11, sp, #0\n");
 #endif
-
 #endif
 }
 
 void AssemblyImageWriter::FrameUnwindEpilogue() {
 #if defined(TARGET_ARCH_ARM)
 #if !defined(TARGET_OS_MACOS) && !defined(TARGET_OS_MACOS_IOS)
-  assembly_stream_.Print(".fnend\n");
+  assembly_stream_->WriteString(".fnend\n");
 #endif
 #endif
-  assembly_stream_.Print(".cfi_endproc\n");
+  assembly_stream_->WriteString(".cfi_endproc\n");
 }
 
-intptr_t AssemblyImageWriter::WriteByteSequence(uword start, uword end) {
-  assert(end >= start);
+intptr_t AssemblyImageWriter::WriteBytes(const void* bytes, intptr_t size) {
+  ASSERT(size >= 0);
+  auto const start = reinterpret_cast<const uint8_t*>(bytes);
   auto const end_of_words =
-      Utils::RoundDown(end, sizeof(compiler::target::uword));
-  for (auto cursor = reinterpret_cast<compiler::target::uword*>(start);
-       cursor < reinterpret_cast<compiler::target::uword*>(end_of_words);
+      start + Utils::RoundDown(size, compiler::target::kWordSize);
+  for (auto cursor = reinterpret_cast<const compiler::target::word*>(start);
+       cursor < reinterpret_cast<const compiler::target::word*>(end_of_words);
        cursor++) {
-    WriteWordLiteralText(*cursor);
+    WriteTargetWord(*cursor);
   }
+  auto const end = start + size;
   if (end != end_of_words) {
-    auto start_of_rest = reinterpret_cast<const uint8_t*>(end_of_words);
-    assembly_stream_.Print(".byte ");
-    for (auto cursor = start_of_rest;
-         cursor < reinterpret_cast<const uint8_t*>(end); cursor++) {
-      if (cursor != start_of_rest) assembly_stream_.Print(", ");
-      assembly_stream_.Print("0x%0.2" Px "", *cursor);
+    assembly_stream_->WriteString(kSizeDirectives[kInt8SizeLog2]);
+    for (auto cursor = end_of_words; cursor < end; cursor++) {
+      assembly_stream_->Printf("%s 0x%0.2x", cursor != end_of_words ? "," : "",
+                               *cursor);
     }
-    assembly_stream_.Print("\n");
+    assembly_stream_->WriteString("\n");
   }
-  return end - start;
+  return size;
 }
 
-intptr_t AssemblyImageWriter::Align(intptr_t alignment, uword position) {
-  const uword next_position = Utils::RoundUp(position, alignment);
-  assembly_stream_.Print(".balign %" Pd ", 0\n", alignment);
+intptr_t AssemblyImageWriter::Align(intptr_t alignment, intptr_t position) {
+  const intptr_t next_position = Utils::RoundUp(position, alignment);
+  assembly_stream_->Printf(".balign %" Pd ", 0\n", alignment);
   return next_position - position;
 }
+#endif  // defined(DART_PRECOMPILER)
 
 BlobImageWriter::BlobImageWriter(Thread* thread,
-                                 uint8_t** instructions_blob_buffer,
-                                 ReAlloc alloc,
-                                 intptr_t initial_size,
+                                 NonStreamingWriteStream* vm_instructions,
+                                 NonStreamingWriteStream* isolate_instructions,
                                  Elf* debug_elf,
                                  Elf* elf)
     : ImageWriter(thread),
-      instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
+      vm_instructions_(vm_instructions),
+      isolate_instructions_(isolate_instructions),
       elf_(elf),
       debug_elf_(debug_elf) {
 #if defined(DART_PRECOMPILER)
+  ASSERT_EQUAL(FLAG_precompiled_mode, elf_ != nullptr);
   ASSERT(debug_elf_ == nullptr || debug_elf_->dwarf() != nullptr);
 #else
   RELEASE_ASSERT(elf_ == nullptr);
 #endif
 }
 
-intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) {
-  const uword size = end - start;
-  instructions_blob_stream_.WriteBytes(reinterpret_cast<const void*>(start),
-                                       size);
+intptr_t BlobImageWriter::WriteBytes(const void* bytes, intptr_t size) {
+  current_section_stream_->WriteBytes(bytes, size);
   return size;
 }
 
-void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
-  const bool bare_instruction_payloads =
-      FLAG_precompiled_mode && FLAG_use_bare_instructions;
-  auto const zone = Thread::Current()->zone();
-
+void BlobImageWriter::WriteBss(bool vm) {
 #if defined(DART_PRECOMPILER)
-  auto const instructions_symbol = vm ? kVmSnapshotInstructionsAsmSymbol
-                                      : kIsolateSnapshotInstructionsAsmSymbol;
-  intptr_t segment_base = 0;
-  if (elf_ != nullptr) {
-    segment_base = elf_->NextMemoryOffset();
-  }
-  intptr_t debug_segment_base = 0;
-  if (debug_elf_ != nullptr) {
-    debug_segment_base = debug_elf_->NextMemoryOffset();
-    // If we're also generating an ELF snapshot, we want the virtual addresses
-    // in it and the separately saved DWARF information to match.
-    ASSERT(elf_ == nullptr || segment_base == debug_segment_base);
-  }
-#endif
-
-  intptr_t text_offset = 0;
-#if defined(DART_PRECOMPILER)
-  // Parent used for later profile objects. Starts off as the Image. When
-  // writing bare instructions payloads, this is later updated with the
-  // InstructionsSection object which contains all the bare payloads.
-  V8SnapshotProfileWriter::ObjectId parent_id(offset_space_, text_offset);
-#endif
-
-  // This header provides the gap to make the instructions snapshot look like a
-  // OldPage.
-  const intptr_t image_size = Utils::RoundUp(
-      next_text_offset_, compiler::target::ObjectAlignment::kObjectAlignment);
-  instructions_blob_stream_.WriteTargetWord(image_size);
-#if defined(DART_PRECOMPILER)
-  // Store the offset of the BSS section from the instructions section here.
-  // If not compiling to ELF (and thus no BSS segment), write 0.
-  const word bss_offset =
-      elf_ != nullptr ? elf_->BssStart(vm) - segment_base : 0;
-  ASSERT_EQUAL(Utils::RoundDown(bss_offset, Image::kBssAlignment), bss_offset);
-  // Set the lowest bit if we are compiling to ELF.
-  const word compiled_to_elf = elf_ != nullptr ? 0x1 : 0x0;
-  instructions_blob_stream_.WriteTargetWord(bss_offset | compiled_to_elf);
-#else
-  instructions_blob_stream_.WriteTargetWord(0);  // No relocations.
-#endif
-  instructions_blob_stream_.Align(kMaxObjectAlignment);
-  ASSERT_EQUAL(instructions_blob_stream_.Position(), Image::kHeaderSize);
-  text_offset += Image::kHeaderSize;
-#if defined(DART_PRECOMPILER)
-  if (profile_writer_ != nullptr) {
-    profile_writer_->SetObjectTypeAndName(parent_id, "Image",
-                                          instructions_symbol);
-    // Assign post-instruction padding to the Image, unless we're writing bare
-    // instruction payloads, in which case we'll assign it to the
-    // InstructionsSection object.
-    const intptr_t padding =
-        bare_instruction_payloads ? 0 : image_size - next_text_offset_;
-    profile_writer_->AttributeBytesTo(parent_id, Image::kHeaderSize + padding);
-    profile_writer_->AddRoot(parent_id);
-  }
-#endif
-
-  if (bare_instruction_payloads) {
-#if defined(DART_PRECOMPILER)
-    if (profile_writer_ != nullptr) {
-      const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
-      profile_writer_->SetObjectTypeAndName(id, instructions_section_type_,
-                                            instructions_symbol);
-      const intptr_t padding = image_size - next_text_offset_;
-      profile_writer_->AttributeBytesTo(
-          id, compiler::target::InstructionsSection::HeaderSize() + padding);
-      const intptr_t element_offset = id.second - parent_id.second;
-      profile_writer_->AttributeReferenceTo(
-          parent_id,
-          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
-      // Later objects will have the InstructionsSection as a parent.
-      parent_id = id;
-    }
-#endif
-    const intptr_t section_size = image_size - Image::kHeaderSize;
-    // Add the RawInstructionsSection header.
-    const compiler::target::uword marked_tags =
-        ObjectLayout::OldBit::encode(true) |
-        ObjectLayout::OldAndNotMarkedBit::encode(false) |
-        ObjectLayout::OldAndNotRememberedBit::encode(true) |
-        ObjectLayout::NewBit::encode(false) |
-        ObjectLayout::SizeTag::encode(AdjustObjectSizeForTarget(section_size)) |
-        ObjectLayout::ClassIdTag::encode(kInstructionsSectionCid);
-    instructions_blob_stream_.WriteTargetWord(marked_tags);
-    // Uses next_text_offset_ to avoid any post-payload padding.
-    const intptr_t instructions_length =
-        next_text_offset_ - Image::kHeaderSize -
-        compiler::target::InstructionsSection::HeaderSize();
-    instructions_blob_stream_.WriteTargetWord(instructions_length);
-    ASSERT_EQUAL(instructions_blob_stream_.Position() - text_offset,
-                 compiler::target::InstructionsSection::HeaderSize());
-    text_offset += compiler::target::InstructionsSection::HeaderSize();
-  }
-
-  ASSERT_EQUAL(text_offset, instructions_blob_stream_.Position());
-
-#if defined(DART_PRECOMPILER)
-  auto& descriptors = PcDescriptors::Handle(zone);
-#endif
-  SnapshotTextObjectNamer namer(zone);
-
-  NoSafepointScope no_safepoint;
-  for (intptr_t i = 0; i < instructions_.length(); i++) {
-    auto& data = instructions_[i];
-    const bool is_trampoline = data.trampoline_bytes != nullptr;
-    ASSERT(data.text_offset_ == text_offset);
-
-#if defined(DART_PRECOMPILER)
-    const auto object_name = namer.SnapshotNameFor(i, data);
-    if (profile_writer_ != nullptr) {
-      const V8SnapshotProfileWriter::ObjectId id(offset_space_, text_offset);
-      auto const type = is_trampoline ? trampoline_type_ : instructions_type_;
-      const intptr_t size = is_trampoline ? data.trampoline_length
-                                          : SizeInSnapshot(data.insns_->raw());
-      profile_writer_->SetObjectTypeAndName(id, type, object_name);
-      profile_writer_->AttributeBytesTo(id, size);
-      // If the object is wrapped in an InstructionSection, then add an
-      // element reference.
-      const intptr_t element_offset = id.second - parent_id.second;
-      profile_writer_->AttributeReferenceTo(
-          parent_id,
-          {id, V8SnapshotProfileWriter::Reference::kElement, element_offset});
-    }
-#endif
-
-    if (is_trampoline) {
-      const auto start = reinterpret_cast<uword>(data.trampoline_bytes);
-      const auto end = start + data.trampoline_length;
-      text_offset += WriteByteSequence(start, end);
-      delete[] data.trampoline_bytes;
-      data.trampoline_bytes = nullptr;
-      continue;
-    }
-
-    const intptr_t instr_start = text_offset;
-
-    const auto& insns = *data.insns_;
-    const uword payload_start = insns.PayloadStart();
-
-    ASSERT(Utils::IsAligned(payload_start, sizeof(compiler::target::uword)));
-
-    // Write Instructions with the mark and read-only bits set.
-    uword marked_tags = insns.raw_ptr()->tags_;
-    marked_tags = ObjectLayout::OldBit::update(true, marked_tags);
-    marked_tags = ObjectLayout::OldAndNotMarkedBit::update(false, marked_tags);
-    marked_tags =
-        ObjectLayout::OldAndNotRememberedBit::update(true, marked_tags);
-    marked_tags = ObjectLayout::NewBit::update(false, marked_tags);
-#if defined(HASH_IN_OBJECT_HEADER)
-    // Can't use GetObjectTagsAndHash because the update methods discard the
-    // high bits.
-    marked_tags |= static_cast<uword>(insns.raw_ptr()->hash_) << 32;
-#endif
-
-#if defined(IS_SIMARM_X64)
-    const intptr_t start_offset = instructions_blob_stream_.bytes_written();
-
-    if (!bare_instruction_payloads) {
-      const intptr_t size_in_bytes = InstructionsSizeInSnapshot(insns.raw());
-      marked_tags = UpdateObjectSizeForTarget(size_in_bytes, marked_tags);
-      instructions_blob_stream_.WriteTargetWord(marked_tags);
-      instructions_blob_stream_.WriteFixed<uint32_t>(
-          insns.raw_ptr()->size_and_flags_);
-    } else {
-      ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
-                              kBareInstructionsAlignment));
-    }
-    const intptr_t payload_offset = instructions_blob_stream_.Position();
-    instructions_blob_stream_.WriteBytes(
-        reinterpret_cast<const void*>(insns.PayloadStart()), insns.Size());
-    const intptr_t alignment =
-        bare_instruction_payloads
-            ? kBareInstructionsAlignment
-            : compiler::target::ObjectAlignment::kObjectAlignment;
-    instructions_blob_stream_.Align(alignment);
-    const intptr_t end_offset = instructions_blob_stream_.bytes_written();
-    text_offset += (end_offset - start_offset);
-#else   // defined(IS_SIMARM_X64)
-    // Only payload is output in AOT snapshots.
-    const uword header_size =
-        bare_instruction_payloads
-            ? 0
-            : compiler::target::Instructions::HeaderSize();
-    const uword payload_size = SizeInSnapshot(insns.raw()) - header_size;
-    const uword object_end = payload_start + payload_size;
-    if (!bare_instruction_payloads) {
-      uword object_start = reinterpret_cast<uword>(insns.raw_ptr());
-      instructions_blob_stream_.WriteWord(marked_tags);
-      text_offset += sizeof(uword);
-      object_start += sizeof(uword);
-      text_offset += WriteByteSequence(object_start, payload_start);
-    } else {
-      ASSERT(Utils::IsAligned(instructions_blob_stream_.Position(),
-                              kBareInstructionsAlignment));
-    }
-    const intptr_t payload_offset = instructions_blob_stream_.Position();
-    text_offset += WriteByteSequence(payload_start, object_end);
-#endif
-
-#if defined(DART_PRECOMPILER)
-    const auto& code = *data.code_;
-    if (elf_ != nullptr && elf_->dwarf() != nullptr) {
-      elf_->dwarf()->AddCode(code, {vm, payload_offset});
-    }
-    if (debug_elf_ != nullptr) {
-      debug_elf_->dwarf()->AddCode(code, {vm, payload_offset});
-    }
-
-    // Don't patch the relocation if we're not generating ELF. The regular blobs
-    // format does not yet support these relocations. Use
-    // Code::VerifyBSSRelocations to check whether the relocations are patched
-    // or not after loading.
-    if (elf_ != nullptr) {
-      const intptr_t current_stream_position =
-          instructions_blob_stream_.Position();
-
-      descriptors = code.pc_descriptors();
-
-      PcDescriptors::Iterator iterator(
-          descriptors, /*kind_mask=*/PcDescriptorsLayout::kBSSRelocation);
-
-      while (iterator.MoveNext()) {
-        const intptr_t reloc_offset = iterator.PcOffset();
-
-        // The instruction stream at the relocation position holds an offset
-        // into BSS corresponding to the symbol being resolved. This addend is
-        // factored into the relocation.
-        const auto addend = *reinterpret_cast<compiler::target::word*>(
-            insns.PayloadStart() + reloc_offset);
-
-        // Overwrite the relocation position in the instruction stream with the
-        // offset of the BSS segment from the relocation position plus the
-        // addend in the relocation.
-        auto const reloc_pos = payload_offset + reloc_offset;
-        instructions_blob_stream_.SetPosition(reloc_pos);
-
-        const compiler::target::word offset = bss_offset - reloc_pos + addend;
-        instructions_blob_stream_.WriteTargetWord(offset);
-      }
-
-      // Restore stream position after the relocation was patched.
-      instructions_blob_stream_.SetPosition(current_stream_position);
-    }
-#else
-    USE(payload_offset);
-#endif
-
-    ASSERT((text_offset - instr_start) ==
-           ImageWriter::SizeInSnapshot(insns.raw()));
-  }
-
-  // Should be a no-op unless writing bare instruction payloads, in which case
-  // we need to add post-payload padding to the object alignment. The alignment
-  // should match the alignment used in image_size above.
-  instructions_blob_stream_.Align(
-      compiler::target::ObjectAlignment::kObjectAlignment);
-  text_offset = Utils::RoundUp(
-      text_offset, compiler::target::ObjectAlignment::kObjectAlignment);
-
-  ASSERT_EQUAL(text_offset, instructions_blob_stream_.bytes_written());
-  ASSERT_EQUAL(text_offset, image_size);
-
-#ifdef DART_PRECOMPILER
-  auto const data_symbol =
-      vm ? kVmSnapshotDataAsmSymbol : kIsolateSnapshotDataAsmSymbol;
-  if (elf_ != nullptr) {
-    auto const segment_base2 =
-        elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
-                      instructions_blob_stream_.bytes_written());
-    ASSERT_EQUAL(segment_base2, segment_base);
-    // Write the .rodata section here like the AssemblyImageWriter.
-    elf_->AddROData(data_symbol, clustered_stream->buffer(),
-                    clustered_stream->bytes_written());
-  }
-  if (debug_elf_ != nullptr) {
-    // To keep memory addresses consistent, we create elf::SHT_NOBITS sections
-    // in the debugging information. We still pass along the buffers because
-    // we'll need the buffer bytes at generation time to calculate the build ID
-    // so it'll match the one in the snapshot.
-    auto const debug_segment_base2 = debug_elf_->AddText(
-        instructions_symbol, instructions_blob_stream_.buffer(),
-        instructions_blob_stream_.bytes_written());
-    ASSERT_EQUAL(debug_segment_base2, debug_segment_base);
-    debug_elf_->AddROData(data_symbol, clustered_stream->buffer(),
-                          clustered_stream->bytes_written());
-  }
+  // We don't actually write a BSS segment, it's created as part of the
+  // Elf constructor, but make sure it has an non-zero start.
+  ASSERT(elf_ == nullptr ||
+         elf_->SymbolAddress(vm ? kVmSnapshotBssAsmSymbol
+                                : kIsolateSnapshotBssAsmSymbol) != 0);
 #endif
 }
+
+void BlobImageWriter::WriteROData(NonStreamingWriteStream* clustered_stream,
+                                  bool vm) {
+  ImageWriter::WriteROData(clustered_stream, vm);
+  current_section_stream_ = clustered_stream;
+  if (!EnterSection(ProgramSection::Data, vm, ImageWriter::kRODataAlignment)) {
+    return;
+  }
+  ExitSection(ProgramSection::Data, vm, clustered_stream->bytes_written());
+}
+
+bool BlobImageWriter::EnterSection(ProgramSection section,
+                                   bool vm,
+                                   intptr_t alignment) {
+#if defined(DART_PRECOMPILER)
+  ASSERT_EQUAL(elf_ != nullptr, FLAG_precompiled_mode);
+#endif
+  // For now, we set current_section_stream_ in ::WriteData.
+  ASSERT(section == ProgramSection::Data || current_section_stream_ == nullptr);
+  ASSERT(current_section_symbol_ == nullptr);
+  switch (section) {
+    case ProgramSection::Text:
+      current_section_stream_ =
+          ASSERT_NOTNULL(vm ? vm_instructions_ : isolate_instructions_);
+      break;
+    case ProgramSection::Data:
+      break;
+    case ProgramSection::Bss:
+      // The BSS section is pre-made in the Elf object for precompiled snapshots
+      // and unused otherwise, so there's no work that needs doing here.
+      return false;
+    case ProgramSection::BuildId:
+      // The GNU build ID is handled specially in the Elf object, and does not
+      // get used for non-precompiled snapshots.
+      return false;
+  }
+  current_section_symbol_ = SectionSymbol(section, vm);
+  current_section_stream_->Align(alignment);
+  return true;
+}
+
+void BlobImageWriter::ExitSection(ProgramSection name, bool vm, intptr_t size) {
+  // We should still be in the same section as the last EnterSection.
+  ASSERT(current_section_symbol_ != nullptr);
+  ASSERT_EQUAL(strcmp(SectionSymbol(name, vm), current_section_symbol_), 0);
+#if defined(DART_PRECOMPILER)
+  ElfAddSection(elf_, name, current_section_symbol_,
+                current_section_stream_->buffer(), size);
+  // We create the corresponding segment in the debugging information as well,
+  // since it needs the contents to create the correct build ID.
+  ElfAddSection(debug_elf_, name, current_section_symbol_,
+                current_section_stream_->buffer(), size);
+#endif
+  current_section_symbol_ = nullptr;
+  current_section_stream_ = nullptr;
+}
+
+intptr_t BlobImageWriter::WriteTargetWord(word value) {
+  current_section_stream_->WriteTargetWord(value);
+  return compiler::target::kWordSize;
+}
+
+intptr_t BlobImageWriter::Align(intptr_t alignment, intptr_t offset) {
+  const intptr_t stream_padding = current_section_stream_->Align(alignment);
+  // Double-check that the offset has the same alignment.
+  ASSERT_EQUAL(Utils::RoundUp(offset, alignment) - offset, stream_padding);
+  return stream_padding;
+}
+
+#if defined(DART_PRECOMPILER)
+intptr_t BlobImageWriter::Relocation(intptr_t section_offset,
+                                     const char* source_symbol,
+                                     intptr_t source_offset,
+                                     const char* target_symbol,
+                                     intptr_t target_offset,
+                                     intptr_t target_addend) {
+  ASSERT(FLAG_precompiled_mode);
+  const uword source_address = RelocatedAddress(source_symbol) + source_offset;
+  const uword target_address = RelocatedAddress(target_symbol) + target_offset;
+  return WriteTargetWord(target_address + target_addend - source_address);
+}
+
+uword BlobImageWriter::RelocatedAddress(const char* symbol) {
+  ASSERT(FLAG_precompiled_mode);
+  ASSERT(symbol != nullptr);
+  if (strcmp(symbol, current_section_symbol_) == 0) {
+    // Cheating a bit here, assuming that the current section will go into its
+    // own load segment (and that the load segment alignment is the same as
+    // the text section alignment).
+    return elf_->NextMemoryOffset(ImageWriter::kTextAlignment);
+  }
+  const uword start = elf_->SymbolAddress(symbol);
+  ASSERT(start != Elf::kNoSectionStart);
+  return start;
+}
+
+void BlobImageWriter::AddCodeSymbol(const Code& code,
+                                    const char* symbol,
+                                    intptr_t offset) {
+  if (elf_ != nullptr && elf_->dwarf() != nullptr) {
+    elf_->dwarf()->AddCode(code, symbol);
+    elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
+  }
+  if (debug_elf_ != nullptr) {
+    debug_elf_->dwarf()->AddCode(code, symbol);
+    debug_elf_->AddLocalSymbol(symbol, elf::STT_FUNC, offset, code.Size());
+  }
+}
+#endif  // defined(DART_PRECOMPILER)
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 ImageReader::ImageReader(const uint8_t* data_image,
                          const uint8_t* instructions_image)
-    : data_image_(data_image), instructions_image_(instructions_image) {
-  ASSERT(data_image != NULL);
-  ASSERT(instructions_image != NULL);
-}
+    : data_image_(ASSERT_NOTNULL(data_image)),
+      instructions_image_(ASSERT_NOTNULL(instructions_image)) {}
 
 ApiErrorPtr ImageReader::VerifyAlignment() const {
   if (!Utils::IsAligned(data_image_, kObjectAlignment) ||
@@ -1535,17 +1508,20 @@
 
 #if defined(DART_PRECOMPILED_RUNTIME)
 uword ImageReader::GetBareInstructionsAt(uint32_t offset) const {
-  ASSERT(Utils::IsAligned(offset, ImageWriter::kBareInstructionsAlignment));
+  ASSERT(FLAG_use_bare_instructions);
+  ASSERT(Utils::IsAligned(offset, Instructions::kBarePayloadAlignment));
   return reinterpret_cast<uword>(instructions_image_) + offset;
 }
 
 uword ImageReader::GetBareInstructionsEnd() const {
+  ASSERT(FLAG_use_bare_instructions);
   Image image(instructions_image_);
   return reinterpret_cast<uword>(image.object_start()) + image.object_size();
 }
 #endif
 
 InstructionsPtr ImageReader::GetInstructionsAt(uint32_t offset) const {
+  ASSERT(!FLAG_precompiled_mode || !FLAG_use_bare_instructions);
   ASSERT(Utils::IsAligned(offset, kObjectAlignment));
 
   ObjectPtr result = ObjectLayout::FromAddr(
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 6727ca0..060f3a9 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -13,6 +13,7 @@
 #include "vm/allocation.h"
 #include "vm/compiler/runtime_api.h"
 #include "vm/datastream.h"
+#include "vm/elf.h"
 #include "vm/globals.h"
 #include "vm/growable_array.h"
 #include "vm/hash_map.h"
@@ -26,65 +27,117 @@
 // Forward declarations.
 class Code;
 class Dwarf;
-class Elf;
 class Instructions;
 class Object;
 
 class Image : ValueObject {
  public:
-  explicit Image(const void* raw_memory) : raw_memory_(raw_memory) {
+  explicit Image(const void* raw_memory)
+      : Image(reinterpret_cast<uword>(raw_memory)) {}
+  explicit Image(const uword raw_memory)
+      : raw_memory_(raw_memory),
+        snapshot_size_(FieldValue(raw_memory, HeaderField::ImageSize)),
+        extra_info_(ExtraInfo(raw_memory_, snapshot_size_)) {
     ASSERT(Utils::IsAligned(raw_memory, kMaxObjectAlignment));
   }
 
+  // Even though an Image is read-only memory, we must return a void* here.
+  // All objects in an Image are pre-marked, though, so the GC will not attempt
+  // to change the returned memory.
   void* object_start() const {
-    return reinterpret_cast<void*>(reinterpret_cast<uword>(raw_memory_) +
-                                   kHeaderSize);
+    return reinterpret_cast<void*>(raw_memory_ + kHeaderSize);
   }
 
-  uword object_size() const {
-    uword snapshot_size = *reinterpret_cast<const uword*>(raw_memory_);
-    return snapshot_size - kHeaderSize;
-  }
+  uword object_size() const { return snapshot_size_ - kHeaderSize; }
 
   bool contains(uword address) const {
     uword start = reinterpret_cast<uword>(object_start());
     return address >= start && (address - start < object_size());
   }
 
-  // Returns the offset of the BSS section from this image. Only has meaning for
-  // instructions images.
-  word bss_offset() const {
-    auto const raw_value = *(reinterpret_cast<const word*>(raw_memory_) + 1);
-    return Utils::RoundDown(raw_value, kBssAlignment);
-  }
+  // Returns the address of the BSS section, or nullptr if one is not available.
+  // Only has meaning for instructions images from precompiled snapshots.
+  uword* bss() const;
 
-  // Returns true if the image was compiled directly to ELF. Only has meaning
-  // for instructions images.
-  bool compiled_to_elf() const {
-    auto const raw_value = *(reinterpret_cast<const word*>(raw_memory_) + 1);
-    return (raw_value & 0x1) == 0x1;
-  }
+  // Returns the relocated address of the isolate's instructions, or 0 if
+  // one is not available. Only has meaning for instructions images from
+  // precompiled snapshots.
+  uword instructions_relocated_address() const;
+
+  // Returns the GNU build ID, or nullptr if not available. See
+  // build_id_length() for the length of the returned buffer. Only has meaning
+  // for instructions images from precompiled snapshots.
+  const uint8_t* build_id() const;
+
+  // Returns the length of the GNU build ID returned by build_id(). Only has
+  // meaning for instructions images from precompiled snapshots.
+  intptr_t build_id_length() const;
+
+  // Returns whether this instructions section was compiled to ELF. Only has
+  // meaning for instructions images from precompiled snapshots.
+  bool compiled_to_elf() const;
 
  private:
-  static constexpr intptr_t kHeaderFields = 2;
+  // Word-sized fields in an Image object header.
+  enum class HeaderField : intptr_t {
+    // The size of the image (total of header and payload).
+    ImageSize,
+    // The offset of the InstructionsSection object in the image. Note this
+    // offset is from the start of the _image_, _not_ from its payload start,
+    // so we can detect images without an InstructionsSection by a 0 value here.
+    InstructionsSectionOffset,
+    // If adding more fields, updating kHeaderFields below. (However, more
+    // fields _can't_ be added on 64-bit architectures, see the restrictions
+    // on kHeaderSize below.)
+  };
+
+  // Number of fields described by the HeaderField enum.
+  static constexpr intptr_t kHeaderFields =
+      static_cast<intptr_t>(HeaderField::InstructionsSectionOffset) + 1;
+
+  static uword FieldValue(uword raw_memory, HeaderField field) {
+    return reinterpret_cast<const uword*>(
+        raw_memory)[static_cast<intptr_t>(field)];
+  }
+
+  // Constants used to denote special values for the offsets in the Image
+  // object header and the fields of the InstructionsSection object.
+  static constexpr intptr_t kNoInstructionsSection = 0;
+  static constexpr intptr_t kNoBssSection = 0;
+  static constexpr intptr_t kNoRelocatedAddress = 0;
+  static constexpr intptr_t kNoBuildId = 0;
+
+  // The size of the Image object header.
+  //
+  // Note: Image::kHeaderSize is _not_ an architecture-dependent constant,
+  // and so there is no compiler::target::Image::kHeaderSize.
   static constexpr intptr_t kHeaderSize = kMaxObjectAlignment;
   // Explicitly double-checking kHeaderSize is never changed. Increasing the
   // Image header size would mean objects would not start at a place expected
   // by parts of the VM (like the GC) that use Image pages as HeapPages.
   static_assert(kHeaderSize == kMaxObjectAlignment,
                 "Image page cannot be used as HeapPage");
+  // Make sure that the number of fields in the Image header fit both on the
+  // host and target architectures.
+  static_assert(kHeaderFields * kWordSize <= kHeaderSize,
+                "Too many fields in Image header for host architecture");
+  static_assert(kHeaderFields * compiler::target::kWordSize <= kHeaderSize,
+                "Too many fields in Image header for target architecture");
 
-  // Determines how many bits we have for encoding any extra information in
-  // the BSS offset.
-  static constexpr intptr_t kBssAlignment = compiler::target::kWordSize;
+  // We don't use a handle or the tagged pointer because this object cannot be
+  // moved in memory by the GC.
+  static const InstructionsSectionLayout* ExtraInfo(const uword raw_memory,
+                                                    const uword size);
 
-  const void* raw_memory_;  // The symbol kInstructionsSnapshot.
+  // Most internal uses would cast this to uword, so just store it as such.
+  const uword raw_memory_;
+  const intptr_t snapshot_size_;
+  const InstructionsSectionLayout* const extra_info_;
 
   // For access to private constants.
   friend class AssemblyImageWriter;
   friend class BlobImageWriter;
   friend class ImageWriter;
-  friend class Elf;
 
   DISALLOW_COPY_AND_ASSIGN(Image);
 };
@@ -178,12 +231,35 @@
   explicit ImageWriter(Thread* thread);
   virtual ~ImageWriter() {}
 
+  // Alignment constants used in writing ELF or assembly snapshots.
+
+  // BSS sections contain word-sized data.
+  static constexpr intptr_t kBssAlignment = compiler::target::kWordSize;
+  // ROData sections contain objects wrapped in an Image object.
+  static constexpr intptr_t kRODataAlignment = kMaxObjectAlignment;
+  // Text sections contain objects (even in bare instructions mode) wrapped
+  // in an Image object, and for now we also align them to the same page
+  // size assumed by Elf objects.
+  static_assert(Elf::kPageSize >= kMaxObjectAlignment,
+                "Page alignment must be consistent with max object alignment");
+  static constexpr intptr_t kTextAlignment = Elf::kPageSize;
+
   void ResetOffsets() {
     next_data_offset_ = Image::kHeaderSize;
     next_text_offset_ = Image::kHeaderSize;
-    if (FLAG_use_bare_instructions && FLAG_precompiled_mode) {
-      next_text_offset_ += compiler::target::InstructionsSection::HeaderSize();
+#if defined(DART_PRECOMPILER)
+    if (FLAG_precompiled_mode) {
+      // We reserve space for the initial InstructionsSection object. It is
+      // manually serialized since it includes offsets to other snapshot parts.
+      // In bare instructions mode, it contains all the payloads and so we
+      // start after the header, whereas in non-bare mode, it contains no
+      // payload and Instructions start after it.
+      next_text_offset_ +=
+          FLAG_use_bare_instructions
+              ? compiler::target::InstructionsSection::HeaderSize()
+              : compiler::target::InstructionsSection::InstanceSize(0);
     }
+#endif
     objects_.Clear();
     instructions_.Clear();
   }
@@ -201,7 +277,7 @@
   int32_t GetTextOffsetFor(InstructionsPtr instructions, CodePtr code);
   uint32_t GetDataOffsetFor(ObjectPtr raw_object);
 
-  void Write(WriteStream* clustered_stream, bool vm);
+  void Write(NonStreamingWriteStream* clustered_stream, bool vm);
   intptr_t data_size() const { return next_data_offset_; }
   intptr_t text_size() const { return next_text_offset_; }
   intptr_t GetTextObjectCount() const;
@@ -218,44 +294,33 @@
   void TraceInstructions(const Instructions& instructions);
 
   static intptr_t SizeInSnapshot(ObjectPtr object);
-  static const intptr_t kBareInstructionsAlignment = 4;
-
-  static_assert(
-      (kObjectAlignmentLog2 -
-       compiler::target::ObjectAlignment::kObjectAlignmentLog2) >= 0,
-      "Target object alignment is larger than the host object alignment");
-
-  // Converts the target object size (in bytes) to an appropriate argument for
-  // ObjectLayout::SizeTag methods on the host machine.
-  //
-  // ObjectLayout::SizeTag expects a size divisible by kObjectAlignment and
-  // checks this in debug mode, but the size on the target machine may not be
-  // divisible by the host machine's object alignment if they differ.
-  //
-  // If target_size = n, we convert it to n * m, where m is the host alignment
-  // divided by the target alignment. This means AdjustObjectSizeForTarget(n)
-  // encodes on the host machine to the same bits that decode to n on the target
-  // machine. That is:
-  //    n * (host align / target align) / host align => n / target align
-  static constexpr intptr_t AdjustObjectSizeForTarget(intptr_t target_size) {
-    return target_size
-           << (kObjectAlignmentLog2 -
-               compiler::target::ObjectAlignment::kObjectAlignmentLog2);
-  }
-
-  static UNLESS_DEBUG(constexpr) compiler::target::uword
-      UpdateObjectSizeForTarget(intptr_t size, uword marked_tags) {
-    return ObjectLayout::SizeTag::update(AdjustObjectSizeForTarget(size),
-                                         marked_tags);
+  static intptr_t SizeInSnapshot(const Object& object) {
+    return SizeInSnapshot(object.raw());
   }
 
   // Returns nullptr if there is no profile writer.
   const char* ObjectTypeForProfile(const Object& object) const;
   static const char* TagObjectTypeAsReadOnly(Zone* zone, const char* type);
 
+  enum class ProgramSection {
+    Text,     // Instructions.
+    Data,     // Read-only data.
+    Bss,      // Statically allocated variables initialized at load.
+    BuildId,  // GNU build ID (when applicable)
+  };
+
  protected:
-  void WriteROData(WriteStream* stream);
-  virtual void WriteText(WriteStream* clustered_stream, bool vm) = 0;
+  virtual void WriteBss(bool vm) = 0;
+  virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
+  void WriteText(bool vm);
+
+  // Returns the standard Dart dynamic symbol name for the given VM isolate (if
+  // vm is true) or application isolate (otherwise) section. Some sections are
+  // shared by both.
+  const char* SectionSymbol(ProgramSection section, bool vm) const;
+
+  static uword GetMarkedTags(classid_t cid, intptr_t size);
+  static uword GetMarkedTags(const Object& obj);
 
   void DumpInstructionStats();
   void DumpInstructionsSizes();
@@ -300,6 +365,69 @@
     };
   };
 
+  // Methods abstracting out the particulars of the underlying concrete writer.
+
+  // Marks the entrance into a particular ProgramSection for either the VM
+  // isolate (if vm is true) or application isolate (if not). Returns false if
+  // this section should not be written.
+  virtual bool EnterSection(ProgramSection name,
+                            bool vm,
+                            intptr_t alignment) = 0;
+  // Marks the exit from a particular ProgramSection, allowing subclasses to
+  // do any post-writing work.
+  virtual void ExitSection(ProgramSection name, bool vm, intptr_t size) = 0;
+  // Writes a prologue to the text section that describes how to interpret
+  // Dart stack frames using DWARF's Call Frame Information (CFI).
+  virtual void FrameUnwindPrologue() = 0;
+  // Writes an epilogue to the text section that marks the end of instructions
+  // covered by the CFI information in the prologue.
+  virtual void FrameUnwindEpilogue() = 0;
+  // Writes a target uword-sized value to the section contents.
+  virtual intptr_t WriteTargetWord(word value) = 0;
+  // Writes a sequence of bytes of length [size] from address [bytes] to the
+  // section contents.
+  virtual intptr_t WriteBytes(const void* bytes, intptr_t size) = 0;
+  // Pads the section contents to a given alignment with zeroes.
+  virtual intptr_t Align(intptr_t alignment, intptr_t offset) = 0;
+#if defined(DART_PRECOMPILER)
+  // Writes a target word-sized value that depends on the final relocated
+  // addresses of the sections named by the two symbols. If T is the final
+  // relocated address of the target section and S is the final relocated
+  // address of the source, the final value is:
+  //   (T + target_offset + target_addend) - (S + source_offset)
+  virtual intptr_t Relocation(intptr_t section_offset,
+                              const char* source_symbol,
+                              intptr_t source_offset,
+                              const char* target_symbol,
+                              intptr_t target_offset,
+                              intptr_t target_addend) = 0;
+  // Returns the final relocated address for the section represented by the
+  // symbol. May not be supported by some writers.
+  virtual uword RelocatedAddress(const char* symbol) = 0;
+  // Creates a static symbol for the given Code object when appropriate.
+  virtual void AddCodeSymbol(const Code& code,
+                             const char* symbol,
+                             intptr_t section_offset) = 0;
+
+  // Overloaded convenience versions of the above virtual methods.
+
+  // An overload of Relocation where the target and source offsets and
+  // target addend are 0.
+  intptr_t Relocation(intptr_t section_offset,
+                      const char* source_symbol,
+                      const char* target_symbol) {
+    return Relocation(section_offset, source_symbol, 0, target_symbol, 0, 0);
+  }
+#endif
+  // Writes a fixed-sized value of type T to the section contents.
+  template <typename T>
+  intptr_t WriteFixed(T value) {
+    return WriteBytes(&value, sizeof(value));
+  }
+  // Like Align, but instead of padding with zeroes, the appropriate break
+  // instruction for the target architecture is used.
+  intptr_t AlignWithBreakInstructions(intptr_t alignment, intptr_t offset);
+
   Heap* heap_;  // Used for mapping RawInstructiosn to object ids.
   intptr_t next_data_offset_;
   intptr_t next_text_offset_;
@@ -309,10 +437,14 @@
   V8SnapshotProfileWriter::IdSpace offset_space_ =
       V8SnapshotProfileWriter::kSnapshot;
   V8SnapshotProfileWriter* profile_writer_ = nullptr;
+  const char* const image_type_;
   const char* const instructions_section_type_;
   const char* const instructions_type_;
   const char* const trampoline_type_;
 
+  // Used to make sure Code symbols are unique across text sections.
+  intptr_t unique_symbol_counter_ = 0;
+
   template <class T>
   friend class TraceImageObjectScope;
   friend class SnapshotTextObjectNamer;  // For InstructionsData.
@@ -321,13 +453,14 @@
   DISALLOW_COPY_AND_ASSIGN(ImageWriter);
 };
 
+#if defined(DART_PRECOMPILER)
 #define AutoTraceImage(object, section_offset, stream)                         \
-  auto AutoTraceImagObjectScopeVar##__COUNTER__ =                              \
-      TraceImageObjectScope<std::remove_pointer<decltype(stream)>::type>(      \
-          this, section_offset, stream, object);
+  TraceImageObjectScope<std::remove_pointer<decltype(stream)>::type>           \
+      AutoTraceImageObjectScopeVar##__COUNTER__(this, section_offset, stream,  \
+                                                object);
 
 template <typename T>
-class TraceImageObjectScope {
+class TraceImageObjectScope : ValueObject {
  public:
   TraceImageObjectScope(ImageWriter* writer,
                         intptr_t section_offset,
@@ -337,14 +470,13 @@
         stream_(ASSERT_NOTNULL(stream)),
         section_offset_(section_offset),
         start_offset_(stream_->Position() - section_offset),
-        object_(object) {}
+        object_type_(writer->ObjectTypeForProfile(object)) {}
 
   ~TraceImageObjectScope() {
     if (writer_->profile_writer_ == nullptr) return;
     ASSERT(writer_->IsROSpace());
     writer_->profile_writer_->SetObjectTypeAndName(
-        {writer_->offset_space_, start_offset_},
-        writer_->ObjectTypeForProfile(object_), nullptr);
+        {writer_->offset_space_, start_offset_}, object_type_, nullptr);
     writer_->profile_writer_->AttributeBytesTo(
         {writer_->offset_space_, start_offset_},
         stream_->Position() - section_offset_ - start_offset_);
@@ -355,13 +487,15 @@
   const T* const stream_;
   const intptr_t section_offset_;
   const intptr_t start_offset_;
-  const Object& object_;
+  const char* const object_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(TraceImageObjectScope);
 };
 
-class SnapshotTextObjectNamer {
+class SnapshotTextObjectNamer : ValueObject {
  public:
   explicit SnapshotTextObjectNamer(Zone* zone)
-      : zone_(zone),
+      : zone_(ASSERT_NOTNULL(zone)),
         owner_(Object::Handle(zone)),
         string_(String::Handle(zone)),
         insns_(Instructions::Handle(zone)),
@@ -380,70 +514,106 @@
   Instructions& insns_;
   ObjectStore* const store_;
   TypeTestingStubNamer namer_;
+
+  DISALLOW_COPY_AND_ASSIGN(SnapshotTextObjectNamer);
 };
 
 class AssemblyImageWriter : public ImageWriter {
  public:
   AssemblyImageWriter(Thread* thread,
-                      Dart_StreamingWriteCallback callback,
-                      void* callback_data,
+                      BaseWriteStream* stream,
                       bool strip = false,
                       Elf* debug_elf = nullptr);
   void Finalize();
 
-  virtual void WriteText(WriteStream* clustered_stream, bool vm);
-
  private:
-  void FrameUnwindPrologue();
-  void FrameUnwindEpilogue();
-  intptr_t WriteByteSequence(uword start, uword end);
-  intptr_t Align(intptr_t alignment, uword position = 0);
+  virtual void WriteBss(bool vm);
+  virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
 
-#if defined(TARGET_ARCH_IS_64_BIT)
-  const char* kLiteralPrefix = ".quad";
-#else
-  const char* kLiteralPrefix = ".long";
-#endif
-
-  intptr_t WriteWordLiteralText(compiler::target::uword value) {
-    // Padding is helpful for comparing the .S with --disassemble.
-#if defined(TARGET_ARCH_IS_64_BIT)
-    assembly_stream_.Print(".quad 0x%0.16" Px "\n", value);
-#else
-    assembly_stream_.Print(".long 0x%0.8" Px "\n", value);
-#endif
-    return compiler::target::kWordSize;
+  virtual bool EnterSection(ProgramSection section,
+                            bool vm,
+                            intptr_t alignment);
+  virtual void ExitSection(ProgramSection name, bool vm, intptr_t size);
+  virtual intptr_t WriteTargetWord(word value);
+  virtual intptr_t WriteBytes(const void* bytes, intptr_t size);
+  virtual intptr_t Align(intptr_t alignment, intptr_t offset = 0);
+  virtual intptr_t Relocation(intptr_t section_offset,
+                              const char* source_symbol,
+                              intptr_t source_offset,
+                              const char* target_symbol,
+                              intptr_t target_offset,
+                              intptr_t target_addend);
+  // We can't generate the relocated address in assembly, so it'll be
+  // retrieved and stored in the BSS during BSS initialization instead.
+  virtual uword RelocatedAddress(const char* symbol) {
+    return Image::kNoRelocatedAddress;
   }
+  virtual void FrameUnwindPrologue();
+  virtual void FrameUnwindEpilogue();
+  virtual void AddCodeSymbol(const Code& code,
+                             const char* symbol,
+                             intptr_t offset);
 
-  StreamingWriteStream assembly_stream_;
-  Dwarf* assembly_dwarf_;
-  Elf* debug_elf_;
+  BaseWriteStream* const assembly_stream_;
+  Dwarf* const assembly_dwarf_;
+  Elf* const debug_elf_;
+
+  // Used in Relocation to output "(.)" for relocations involving the current
+  // section position and creating local symbols in AddCodeSymbol.
+  const char* current_section_symbol_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(AssemblyImageWriter);
 };
+#endif
 
 class BlobImageWriter : public ImageWriter {
  public:
   BlobImageWriter(Thread* thread,
-                  uint8_t** instructions_blob_buffer,
-                  ReAlloc alloc,
-                  intptr_t initial_size,
+                  NonStreamingWriteStream* vm_instructions,
+                  NonStreamingWriteStream* isolate_instructions,
                   Elf* debug_elf = nullptr,
                   Elf* elf = nullptr);
 
-  virtual void WriteText(WriteStream* clustered_stream, bool vm);
-
-  intptr_t InstructionsBlobSize() const {
-    return instructions_blob_stream_.bytes_written();
-  }
-
  private:
-  intptr_t WriteByteSequence(uword start, uword end);
+  virtual void WriteBss(bool vm);
+  virtual void WriteROData(NonStreamingWriteStream* clustered_stream, bool vm);
 
-  WriteStream instructions_blob_stream_;
+  virtual bool EnterSection(ProgramSection section,
+                            bool vm,
+                            intptr_t alignment);
+  virtual void ExitSection(ProgramSection name, bool vm, intptr_t size);
+  virtual intptr_t WriteTargetWord(word value);
+  virtual intptr_t WriteBytes(const void* bytes, intptr_t size);
+  virtual intptr_t Align(intptr_t alignment, intptr_t offset);
+  // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
+  // provide unwinding information.
+  virtual void FrameUnwindPrologue() {}
+  virtual void FrameUnwindEpilogue() {}
+#if defined(DART_PRECOMPILER)
+  virtual intptr_t Relocation(intptr_t section_offset,
+                              const char* source_symbol,
+                              intptr_t source_offset,
+                              const char* target_symbol,
+                              intptr_t target_offset,
+                              intptr_t target_addend);
+  virtual uword RelocatedAddress(const char* symbol);
+  virtual void AddCodeSymbol(const Code& code,
+                             const char* symbol,
+                             intptr_t offset);
+#endif
+
+  NonStreamingWriteStream* const vm_instructions_;
+  NonStreamingWriteStream* const isolate_instructions_;
   Elf* const elf_;
   Elf* const debug_elf_;
 
+  // Used to detect relocations or relocated address requests involving the
+  // current section and creating local symbols in AddCodeSymbol.
+  const char* current_section_symbol_ = nullptr;
+  // Set on section entrance to the stream that should be used by the writing
+  // methods.
+  NonStreamingWriteStream* current_section_stream_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
 };
 
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 97b58f5..38a0159 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -10,6 +10,7 @@
 
 #include "vm/interpreter.h"
 
+#include "vm/class_id.h"
 #include "vm/compiler/api/type_check_mode.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler_kbc.h"
@@ -2282,6 +2283,17 @@
       case MethodRecognizer::kFfiAbi: {
         *++SP = Smi::New(static_cast<int64_t>(compiler::ffi::TargetAbi()));
       } break;
+#define TYPED_DATA_FACTORY(clazz)                                              \
+  case MethodRecognizer::kTypedData_##clazz##_factory: {                       \
+    ObjectPtr length = SP[0];                                                  \
+    SP[1] = Smi::New(kTypedData##clazz##Cid);                                  \
+    SP[2] = length;                                                            \
+    Exit(thread, FP, SP + 3, pc);                                              \
+    INVOKE_RUNTIME(DRT_AllocateTypedData,                                      \
+                   NativeArguments(thread, 2, SP + 1, SP));                    \
+  } break;
+        CLASS_LIST_TYPED_DATA(TYPED_DATA_FACTORY)
+#undef TYPED_DATA_FACTORY
       default: {
         NativeEntryData::Payload* payload =
             NativeEntryData::FromTypedArray(data);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 50cba71..5aa297b 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -133,6 +133,12 @@
   }
 }
 
+static std::unique_ptr<Message> SerializeMessage(Dart_Port dest_port,
+                                                 Dart_CObject* obj) {
+  ApiMessageWriter writer;
+  return writer.WriteCMessage(obj, dest_port, Message::kNormalPriority);
+}
+
 static InstancePtr DeserializeMessage(Thread* thread, Message* message) {
   if (message == NULL) {
     return Instance::null();
@@ -1447,34 +1453,38 @@
 
   NoReloadScope no_reload_scope(T->isolate(), T);
   // Generate the error and stacktrace strings for the error message.
-  String& exc_str = String::Handle(T->zone());
-  String& stacktrace_str = String::Handle(T->zone());
+  const char* exception_cstr = nullptr;
+  const char* stacktrace_cstr = nullptr;
   if (result.IsUnhandledException()) {
     Zone* zone = T->zone();
     const UnhandledException& uhe = UnhandledException::Cast(result);
     const Instance& exception = Instance::Handle(zone, uhe.exception());
-    Object& tmp = Object::Handle(zone);
-    tmp = DartLibraryCalls::ToString(exception);
-    if (!tmp.IsString()) {
-      tmp = String::New(exception.ToCString());
+    if (exception.raw() == I->object_store()->out_of_memory()) {
+      exception_cstr = "Out of Memory";  // Cf. OutOfMemoryError.toString().
+    } else if (exception.raw() == I->object_store()->stack_overflow()) {
+      exception_cstr = "Stack Overflow";  // Cf. StackOverflowError.toString().
+    } else {
+      const Object& exception_str =
+          Object::Handle(zone, DartLibraryCalls::ToString(exception));
+      if (!exception_str.IsString()) {
+        exception_cstr = exception.ToCString();
+      } else {
+        exception_cstr = exception_str.ToCString();
+      }
     }
-    exc_str ^= tmp.raw();
 
     const Instance& stacktrace = Instance::Handle(zone, uhe.stacktrace());
-    tmp = DartLibraryCalls::ToString(stacktrace);
-    if (!tmp.IsString()) {
-      tmp = String::New(stacktrace.ToCString());
-    }
-    stacktrace_str ^= tmp.raw();
+    stacktrace_cstr = stacktrace.ToCString();
   } else {
-    exc_str = String::New(result.ToErrorCString());
+    exception_cstr = result.ToErrorCString();
   }
   if (result.IsUnwindError()) {
     // When unwinding we don't notify error listeners and we ignore
     // whether errors are fatal for the current isolate.
     return StoreError(T, result);
   } else {
-    bool has_listener = I->NotifyErrorListeners(exc_str, stacktrace_str);
+    bool has_listener =
+        I->NotifyErrorListeners(exception_cstr, stacktrace_cstr);
     if (I->ErrorsFatal()) {
       if (has_listener) {
         T->ClearStickyError();
@@ -1511,29 +1521,24 @@
   api_flags->version = DART_FLAGS_CURRENT_VERSION;
 #define INIT_FROM_FLAG(when, name, bitname, isolate_flag, flag)                \
   api_flags->isolate_flag = flag;
-  ISOLATE_FLAG_LIST(INIT_FROM_FLAG)
+  BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FLAG)
 #undef INIT_FROM_FLAG
   api_flags->entry_points = NULL;
-  api_flags->load_vmservice_library = false;
   api_flags->copy_parent_code = false;
-  api_flags->null_safety = false;
-  api_flags->is_system_isolate = false;
 }
 
 void Isolate::FlagsCopyTo(Dart_IsolateFlags* api_flags) const {
   api_flags->version = DART_FLAGS_CURRENT_VERSION;
 #define INIT_FROM_FIELD(when, name, bitname, isolate_flag, flag)               \
   api_flags->isolate_flag = name();
-  ISOLATE_FLAG_LIST(INIT_FROM_FIELD)
+  BOOL_ISOLATE_FLAG_LIST(INIT_FROM_FIELD)
 #undef INIT_FROM_FIELD
   api_flags->entry_points = NULL;
-  api_flags->load_vmservice_library = should_load_vmservice();
   api_flags->copy_parent_code = false;
-  api_flags->null_safety = null_safety();
-  api_flags->is_system_isolate = is_system_isolate();
 }
 
 void Isolate::FlagsCopyFrom(const Dart_IsolateFlags& api_flags) {
+  const bool copy_parent_code_ = copy_parent_code();
 #if defined(DART_PRECOMPILER)
 #define FLAG_FOR_PRECOMPILER(action) action
 #else
@@ -1552,16 +1557,16 @@
   FLAG_FOR_##when(isolate_flags_ = bitname##Bit::update(                       \
                       api_flags.isolate_flag, isolate_flags_));
 
-  ISOLATE_FLAG_LIST(SET_FROM_FLAG)
-
+  BOOL_ISOLATE_FLAG_LIST(SET_FROM_FLAG)
+  isolate_flags_ = CopyParentCodeBit::update(copy_parent_code_, isolate_flags_);
+  // Needs to be called manually, otherwise we don't set the null_safety_set
+  // bit.
+  set_null_safety(api_flags.null_safety);
 #undef FLAG_FOR_NONPRODUCT
 #undef FLAG_FOR_PRECOMPILER
 #undef FLAG_FOR_PRODUCT
 #undef SET_FROM_FLAG
 
-  set_should_load_vmservice(api_flags.load_vmservice_library);
-  set_null_safety(api_flags.null_safety);
-  set_is_system_isolate(api_flags.is_system_isolate);
   // Copy entry points list.
   ASSERT(embedder_entry_points_ == NULL);
   if (api_flags.entry_points != NULL) {
@@ -2281,21 +2286,32 @@
   }
 }
 
-bool Isolate::NotifyErrorListeners(const String& msg,
-                                   const String& stacktrace) {
+bool Isolate::NotifyErrorListeners(const char* message,
+                                   const char* stacktrace) {
   const GrowableObjectArray& listeners = GrowableObjectArray::Handle(
       current_zone(), isolate_object_store()->error_listeners());
   if (listeners.IsNull()) return false;
 
-  const Array& arr = Array::Handle(current_zone(), Array::New(2));
-  arr.SetAt(0, msg);
-  arr.SetAt(1, stacktrace);
+  Dart_CObject arr;
+  Dart_CObject* arr_values[2];
+  arr.type = Dart_CObject_kArray;
+  arr.value.as_array.length = 2;
+  arr.value.as_array.values = arr_values;
+  Dart_CObject msg;
+  msg.type = Dart_CObject_kString;
+  msg.value.as_string = const_cast<char*>(message);
+  arr_values[0] = &msg;
+  Dart_CObject stack;
+  stack.type = Dart_CObject_kString;
+  stack.value.as_string = const_cast<char*>(stacktrace);
+  arr_values[1] = &stack;
+
   SendPort& listener = SendPort::Handle(current_zone());
   for (intptr_t i = 0; i < listeners.Length(); i++) {
     listener ^= listeners.At(i);
     if (!listener.IsNull()) {
       Dart_Port port_id = listener.Id();
-      PortMap::PostMessage(SerializeMessage(port_id, arr));
+      PortMap::PostMessage(SerializeMessage(port_id, &arr));
     }
   }
   return listeners.Length() > 0;
@@ -2736,7 +2752,9 @@
   }
 
   // Visit objects in the field table.
-  field_table()->VisitObjectPointers(visitor);
+  if (!visitor->trace_values_through_fields()) {
+    field_table()->VisitObjectPointers(visitor);
+  }
 
   visitor->clear_gc_root_type();
   // Visit the objects directly referenced from the isolate structure.
@@ -3086,6 +3104,25 @@
     heap()->PrintToJSONObject(Heap::kOld, &jsheap);
   }
 
+  {
+// Stringification macros
+// See https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html
+#define TO_STRING(s) STR(s)
+#define STR(s) #s
+
+#define ADD_ISOLATE_FLAGS(when, name, bitname, isolate_flag_name, flag_name)   \
+  {                                                                            \
+    JSONObject jsflag(&jsflags);                                               \
+    jsflag.AddProperty("name", TO_STRING(name));                               \
+    jsflag.AddProperty("valueAsString", name() ? "true" : "false");            \
+  }
+    JSONArray jsflags(&jsobj, "isolateFlags");
+    BOOL_ISOLATE_FLAG_LIST(ADD_ISOLATE_FLAGS)
+#undef ADD_ISOLATE_FLAGS
+#undef TO_STRING
+#undef STR
+  }
+
   jsobj.AddProperty("runnable", is_runnable());
   jsobj.AddProperty("livePorts", message_handler()->live_ports());
   jsobj.AddProperty("pauseOnExit", message_handler()->should_pause_on_exit());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index f59147d..51d50d91 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -177,15 +177,33 @@
 
 // List of Isolate flags with corresponding members of Dart_IsolateFlags and
 // corresponding global command line flags.
+#define BOOL_ISOLATE_FLAG_LIST(V)                                              \
+  BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                                     \
+  BOOL_ISOLATE_FLAG_LIST_CUSTOM_GETTER(V)
+
+// List of Isolate flags with default getters.
 //
-//       V(when, name, bit-name, Dart_IsolateFlags-name, command-line-flag-name)
+//     V(when, name, bit-name, Dart_IsolateFlags-name, command-line-flag-name)
 //
-#define ISOLATE_FLAG_LIST(V)                                                   \
+#define BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(V)                               \
   V(NONPRODUCT, asserts, EnableAsserts, enable_asserts, FLAG_enable_asserts)   \
   V(NONPRODUCT, use_field_guards, UseFieldGuards, use_field_guards,            \
     FLAG_use_field_guards)                                                     \
   V(NONPRODUCT, use_osr, UseOsr, use_osr, FLAG_use_osr)                        \
-  V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false_by_default)
+  V(PRECOMPILER, obfuscate, Obfuscate, obfuscate, false_by_default)            \
+  V(PRODUCT, should_load_vmservice_library, ShouldLoadVmService,               \
+    load_vmservice_library, false_by_default)                                  \
+  V(PRODUCT, copy_parent_code, CopyParentCode, copy_parent_code,               \
+    false_by_default)                                                          \
+  V(PRODUCT, is_system_isolate, IsSystemIsolate, is_system_isolate,            \
+    false_by_default)
+
+// List of Isolate flags with custom getters named #name().
+//
+//     V(when, name, bit-name, Dart_IsolateFlags-name, default_value)
+//
+#define BOOL_ISOLATE_FLAG_LIST_CUSTOM_GETTER(V)                                \
+  V(PRODUCT, null_safety, NullSafety, null_safety, false_by_default)
 
 // Represents the information used for spawning the first isolate within an
 // isolate group.
@@ -986,7 +1004,7 @@
 
   void AddErrorListener(const SendPort& listener);
   void RemoveErrorListener(const SendPort& listener);
-  bool NotifyErrorListeners(const String& msg, const String& stacktrace);
+  bool NotifyErrorListeners(const char* msg, const char* stacktrace);
 
   bool ErrorsFatal() const { return ErrorsFatalBit::decode(isolate_flags_); }
   void SetErrorsFatal(bool val) {
@@ -1275,7 +1293,7 @@
     USE(false_by_default);                                                     \
     return FLAG_FOR_##when(bitname##Bit::decode(isolate_flags_), flag_name);   \
   }
-  ISOLATE_FLAG_LIST(DECLARE_GETTER)
+  BOOL_ISOLATE_FLAG_LIST_DEFAULT_GETTER(DECLARE_GETTER)
 #undef FLAG_FOR_NONPRODUCT
 #undef FLAG_FOR_PRECOMPILER
 #undef FLAG_FOR_PRODUCT
@@ -1297,6 +1315,7 @@
     ASSERT(!null_safety_not_set());
     return NullSafetyBit::decode(isolate_flags_);
   }
+
   void set_null_safety(bool null_safety) {
     isolate_flags_ = NullSafetySetBit::update(true, isolate_flags_);
     isolate_flags_ = NullSafetyBit::update(null_safety, isolate_flags_);
@@ -1404,7 +1423,6 @@
   void set_is_system_isolate(bool is_system_isolate) {
     is_system_isolate_ = is_system_isolate;
   }
-  bool is_system_isolate() const { return is_system_isolate_; }
 
 #if !defined(PRODUCT)
   GrowableObjectArrayPtr GetAndClearPendingServiceExtensionCalls();
@@ -1478,9 +1496,11 @@
   V(UseFieldGuards)                                                            \
   V(UseOsr)                                                                    \
   V(Obfuscate)                                                                 \
+  V(CopyParentCode)                                                            \
   V(ShouldLoadVmService)                                                       \
   V(NullSafety)                                                                \
-  V(NullSafetySet)
+  V(NullSafetySet)                                                             \
+  V(IsSystemIsolate)
 
   // Isolate specific flags.
   enum FlagBits {
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index bc9203b..1b53aaa 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,8 +20,8 @@
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
 
 // Both version numbers are inclusive.
-static const uint32_t kMinSupportedKernelFormatVersion = 45;
-static const uint32_t kMaxSupportedKernelFormatVersion = 45;
+static const uint32_t kMinSupportedKernelFormatVersion = 46;
+static const uint32_t kMaxSupportedKernelFormatVersion = 46;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
@@ -42,9 +42,6 @@
   V(AssertInitializer, 12)                                                     \
   V(CheckLibraryIsLoaded, 13)                                                  \
   V(LoadLibrary, 14)                                                           \
-  V(DirectPropertyGet, 15)                                                     \
-  V(DirectPropertySet, 16)                                                     \
-  V(DirectMethodInvocation, 17)                                                \
   V(ConstStaticInvocation, 18)                                                 \
   V(InvalidExpression, 19)                                                     \
   V(VariableGet, 20)                                                           \
@@ -293,13 +290,17 @@
   }
 
   intptr_t ReadSLEB128() {
-    const uint8_t* buffer = this->buffer();
-    return Utils::DecodeSLEB128<intptr_t>(buffer, size_, &offset_);
+    ReadStream stream(this->buffer(), size_, offset_);
+    const intptr_t result = stream.ReadSLEB128();
+    offset_ = stream.Position();
+    return result;
   }
 
   int64_t ReadSLEB128AsInt64() {
-    const uint8_t* buffer = this->buffer();
-    return Utils::DecodeSLEB128<int64_t>(buffer, size_, &offset_);
+    ReadStream stream(this->buffer(), size_, offset_);
+    const int64_t result = stream.ReadSLEB128<int64_t>();
+    offset_ = stream.Position();
+    return result;
   }
 
   /**
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 8fdc9d0..d2cdbb5 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -1055,17 +1055,11 @@
                                      const char* original_working_directory) {
   // Start the kernel Isolate if it is not already running.
   if (!Start()) {
-    Dart_KernelCompilationResult result = {};
-    result.status = Dart_KernelCompilationStatus_Unknown;
-    result.error = Utils::StrDup("Error while starting Kernel isolate task");
     return false;
   }
   // Wait for Kernel isolate to finish initialization.
   Dart_Port kernel_port = WaitForKernelPort();
   if (kernel_port == ILLEGAL_PORT) {
-    Dart_KernelCompilationResult result = {};
-    result.status = Dart_KernelCompilationStatus_Unknown;
-    result.error = Utils::StrDup("Error while initializing Kernel isolate");
     return false;
   }
   KernelCompilationRequest request;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index e19f14e..bbbca69 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -13,6 +13,7 @@
 #include "platform/unicode.h"
 #include "vm/bit_vector.h"
 #include "vm/bootstrap.h"
+#include "vm/canonical_tables.h"
 #include "vm/class_finalizer.h"
 #include "vm/code_comments.h"
 #include "vm/code_descriptors.h"
@@ -57,7 +58,6 @@
 #include "vm/tags.h"
 #include "vm/thread_registry.h"
 #include "vm/timeline.h"
-#include "vm/type_table.h"
 #include "vm/type_testing_stubs.h"
 #include "vm/zone_text_buffer.h"
 
@@ -550,6 +550,7 @@
     null_ = static_cast<InstancePtr>(address + kHeapObjectTag);
     // The call below is using 'null_' to initialize itself.
     InitializeObject(address, kNullCid, Instance::InstanceSize());
+    null_->ptr()->SetCanonical();
   }
 
   // Allocate and initialize the bool instances.
@@ -706,7 +707,7 @@
   *null_type_arguments_ = TypeArguments::null();
   *empty_type_arguments_ = TypeArguments::null();
   *null_abstract_type_ = AbstractType::null();
-  *null_compressed_stack_maps_ = CompressedStackMaps::null();
+  *null_compressed_stackmaps_ = CompressedStackMaps::null();
   *bool_true_ = true_;
   *bool_false_ = false_;
 
@@ -998,6 +999,19 @@
     empty_object_pool_->SetCanonical();
   }
 
+  // Allocate and initialize the empty_compressed_stackmaps instance.
+  {
+    const intptr_t instance_size = CompressedStackMaps::InstanceSize(0);
+    uword address = heap->Allocate(instance_size, Heap::kOld);
+    InitializeObject(address, kCompressedStackMapsCid, instance_size);
+    CompressedStackMaps::initializeHandle(
+        empty_compressed_stackmaps_,
+        static_cast<CompressedStackMapsPtr>(address + kHeapObjectTag));
+    empty_compressed_stackmaps_->StoreNonPointer(
+        &empty_compressed_stackmaps_->raw_ptr()->flags_and_size_, 0);
+    empty_compressed_stackmaps_->SetCanonical();
+  }
+
   // Allocate and initialize the empty_descriptors instance.
   {
     uword address = heap->Allocate(PcDescriptors::InstanceSize(0), Heap::kOld);
@@ -1183,14 +1197,16 @@
   ASSERT(null_function_->IsFunction());
   ASSERT(!null_type_arguments_->IsSmi());
   ASSERT(null_type_arguments_->IsTypeArguments());
-  ASSERT(!null_compressed_stack_maps_->IsSmi());
-  ASSERT(null_compressed_stack_maps_->IsCompressedStackMaps());
+  ASSERT(!null_compressed_stackmaps_->IsSmi());
+  ASSERT(null_compressed_stackmaps_->IsCompressedStackMaps());
   ASSERT(!empty_array_->IsSmi());
   ASSERT(empty_array_->IsArray());
   ASSERT(!zero_array_->IsSmi());
   ASSERT(zero_array_->IsArray());
   ASSERT(!empty_context_scope_->IsSmi());
   ASSERT(empty_context_scope_->IsContextScope());
+  ASSERT(!empty_compressed_stackmaps_->IsSmi());
+  ASSERT(empty_compressed_stackmaps_->IsCompressedStackMaps());
   ASSERT(!empty_descriptors_->IsSmi());
   ASSERT(empty_descriptors_->IsPcDescriptors());
   ASSERT(!empty_var_descriptors_->IsSmi());
@@ -1740,7 +1756,7 @@
         Type::New(Class::Handle(zone, cls.raw()), TypeArguments::Handle(zone),
                   TokenPosition::kNoSource, Nullability::kNonNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     object_store->set_array_type(type);
     type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
     object_store->set_legacy_array_type(type);
@@ -2195,7 +2211,7 @@
     type = Type::New(cls, Object::null_type_arguments(),
                      TokenPosition::kNoSource, Nullability::kNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     object_store->set_null_type(type);
     ASSERT(type.IsNullable());
 
@@ -2207,7 +2223,7 @@
     type = Type::New(cls, Object::null_type_arguments(),
                      TokenPosition::kNoSource, Nullability::kNonNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     object_store->set_never_type(type);
 
     // Create and cache commonly used type arguments <int>, <double>,
@@ -2215,87 +2231,87 @@
     type_args = TypeArguments::New(1);
     type = object_store->int_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_int(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->legacy_int_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_legacy_int(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->non_nullable_int_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_non_nullable_int(type_args);
 
     type_args = TypeArguments::New(1);
     type = object_store->double_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_double(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->legacy_double_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_legacy_double(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->non_nullable_double_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_non_nullable_double(type_args);
 
     type_args = TypeArguments::New(1);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_string(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->legacy_string_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_legacy_string(type_args);
     type_args = TypeArguments::New(1);
     type = object_store->non_nullable_string_type();
     type_args.SetTypeAt(0, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_non_nullable_string(type_args);
 
     type_args = TypeArguments::New(2);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, Object::dynamic_type());
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_string_dynamic(type_args);
     type_args = TypeArguments::New(2);
     type = object_store->legacy_string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, Object::dynamic_type());
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_legacy_string_dynamic(type_args);
     type_args = TypeArguments::New(2);
     type = object_store->non_nullable_string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, Object::dynamic_type());
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_non_nullable_string_dynamic(type_args);
 
     type_args = TypeArguments::New(2);
     type = object_store->string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_string_string(type_args);
     type_args = TypeArguments::New(2);
     type = object_store->legacy_string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_legacy_string_legacy_string(type_args);
     type_args = TypeArguments::New(2);
     type = object_store->non_nullable_string_type();
     type_args.SetTypeAt(0, type);
     type_args.SetTypeAt(1, type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(thread, nullptr);
     object_store->set_type_argument_non_nullable_string_non_nullable_string(
         type_args);
 
@@ -2900,7 +2916,7 @@
     return;
   }
   StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw());
-  StorePointer(&raw_ptr()->constants_, Object::empty_array().raw());
+  StorePointer(&raw_ptr()->constants_, Object::null_array().raw());
   StorePointer(&raw_ptr()->functions_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->fields_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->invocation_dispatcher_cache_,
@@ -4992,7 +5008,6 @@
 }
 
 void Class::set_constants(const Array& value) const {
-  ASSERT(!value.IsNull());
   StorePointer(&raw_ptr()->constants_, value.raw());
 }
 
@@ -5654,7 +5669,7 @@
 // Returns an instance of Double or Double::null().
 DoublePtr Class::LookupCanonicalDouble(Zone* zone, double value) const {
   ASSERT(this->raw() == Isolate::Current()->object_store()->double_class());
-  if (this->constants() == Object::empty_array().raw()) return Double::null();
+  if (this->constants() == Array::null()) return Double::null();
 
   Double& canonical_value = Double::Handle(zone);
   CanonicalDoubleSet constants(zone, this->constants());
@@ -5666,7 +5681,7 @@
 // Returns an instance of Mint or Mint::null().
 MintPtr Class::LookupCanonicalMint(Zone* zone, int64_t value) const {
   ASSERT(this->raw() == Isolate::Current()->object_store()->mint_class());
-  if (this->constants() == Object::empty_array().raw()) return Mint::null();
+  if (this->constants() == Array::null()) return Mint::null();
 
   Mint& canonical_value = Mint::Handle(zone);
   CanonicalMintSet constants(zone, this->constants());
@@ -5727,7 +5742,7 @@
   ASSERT(this->raw() == value.clazz());
   ASSERT(is_finalized() || is_prefinalized());
   Instance& canonical_value = Instance::Handle(zone);
-  if (this->constants() != Object::empty_array().raw()) {
+  if (this->constants() != Array::null()) {
     CanonicalInstancesSet constants(zone, this->constants());
     canonical_value ^= constants.GetOrNull(CanonicalInstanceKey(value));
     this->set_constants(constants.Release());
@@ -5739,7 +5754,7 @@
                                            const Instance& constant) const {
   ASSERT(this->raw() == constant.clazz());
   Instance& canonical_value = Instance::Handle(zone);
-  if (this->constants() == Object::empty_array().raw()) {
+  if (this->constants() == Array::null()) {
     CanonicalInstancesSet constants(
         HashTables::New<CanonicalInstancesSet>(128, Heap::kOld));
     canonical_value ^= constants.InsertNewOrGet(CanonicalInstanceKey(constant));
@@ -5754,7 +5769,7 @@
 }
 
 void Class::InsertCanonicalDouble(Zone* zone, const Double& constant) const {
-  if (this->constants() == Object::empty_array().raw()) {
+  if (this->constants() == Array::null()) {
     this->set_constants(Array::Handle(
         zone, HashTables::New<CanonicalDoubleSet>(128, Heap::kOld)));
   }
@@ -5764,7 +5779,7 @@
 }
 
 void Class::InsertCanonicalMint(Zone* zone, const Mint& constant) const {
-  if (this->constants() == Object::empty_array().raw()) {
+  if (this->constants() == Array::null()) {
     this->set_constants(Array::Handle(
         zone, HashTables::New<CanonicalMintSet>(128, Heap::kOld)));
   }
@@ -5782,9 +5797,9 @@
   }
 
   const Array& old_constants = Array::Handle(zone, constants());
-  if (old_constants.Length() == 0) return;
+  if (old_constants.IsNull()) return;
 
-  set_constants(Object::empty_array());
+  set_constants(Object::null_array());
 
   CanonicalInstancesSet set(zone, old_constants.raw());
   Instance& constant = Instance::Handle(zone);
@@ -5915,7 +5930,7 @@
     type = IsNull() ? Type::DynamicType() : TypeAt(i - other_length);
     result.SetTypeAt(i, type);
   }
-  return result.Canonicalize();
+  return result.Canonicalize(Thread::Current(), nullptr);
 }
 
 TypeArgumentsPtr TypeArguments::ConcatenateTypeParameters(
@@ -6397,7 +6412,7 @@
   result = InstantiateFrom(instantiator_type_arguments, function_type_arguments,
                            kAllFree, Heap::kOld);
   // Canonicalize type arguments.
-  result = result.Canonicalize();
+  result = result.Canonicalize(thread, nullptr);
   // InstantiateAndCanonicalizeFrom is not reentrant. It cannot have been called
   // indirectly, so the prior_instantiations array cannot have grown.
   ASSERT(prior_instantiations.raw() == instantiations());
@@ -6476,7 +6491,8 @@
   StoreSmi(&raw_ptr()->length_, Smi::New(value));
 }
 
-TypeArgumentsPtr TypeArguments::Canonicalize(TrailPtr trail) const {
+TypeArgumentsPtr TypeArguments::Canonicalize(Thread* thread,
+                                             TrailPtr trail) const {
   if (IsNull() || IsCanonical()) {
     ASSERT(IsOld());
     return this->raw();
@@ -6485,7 +6501,6 @@
   if (IsRaw(0, num_types)) {
     return TypeArguments::null();
   }
-  Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
   ObjectStore* object_store = isolate->object_store();
@@ -6502,7 +6517,7 @@
     AbstractType& type_arg = AbstractType::Handle(zone);
     for (intptr_t i = 0; i < num_types; i++) {
       type_arg = TypeAt(i);
-      type_arg = type_arg.Canonicalize(trail);
+      type_arg = type_arg.Canonicalize(thread, trail);
       if (IsCanonical()) {
         // Canonicalizing this type_arg canonicalized this type.
         ASSERT(IsRecursive());
@@ -9361,6 +9376,13 @@
   return Symbols::New(thread, printer.buffer());
 }
 
+const char* Function::QualifiedUserVisibleNameCString() const {
+  Thread* thread = Thread::Current();
+  ZoneTextBuffer printer(thread->zone());
+  PrintName(NameFormattingParams(kUserVisibleName), &printer);
+  return printer.buffer();
+}
+
 void Function::PrintName(const NameFormattingParams& params,
                          BaseTextBuffer* printer) const {
   // If |this| is the generated asynchronous body closure, use the
@@ -14078,10 +14100,6 @@
   all_libs.Add(&Library::ZoneHandle(Library::MathLibrary()));
   MATH_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
 
-  all_libs.Clear();
-  all_libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
-  TYPED_DATA_LIB_INTRINSIC_LIST(CHECK_FINGERPRINTS2);
-
 #undef CHECK_FINGERPRINTS
 #undef CHECK_FINGERPRINTS2
 
@@ -14095,7 +14113,9 @@
         func.CheckSourceFingerprint(fp) && fingerprints_match;                 \
   }
 
+  all_libs.Clear();
   all_libs.Add(&Library::ZoneHandle(Library::CoreLibrary()));
+  all_libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary()));
   RECOGNIZED_LIST_FACTORY_LIST(CHECK_FACTORY_FINGERPRINTS);
 
 #undef CHECK_FACTORY_FINGERPRINTS
@@ -14154,35 +14174,6 @@
   return "InstructionsSection";
 }
 
-// Encode integer |value| in SLEB128 format and store into |data|.
-static void EncodeSLEB128(GrowableArray<uint8_t>* data, intptr_t value) {
-  bool is_last_part = false;
-  while (!is_last_part) {
-    uint8_t part = value & 0x7f;
-    value >>= 7;
-    if ((value == 0 && (part & 0x40) == 0) ||
-        (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
-      is_last_part = true;
-    } else {
-      part |= 0x80;
-    }
-    data->Add(part);
-  }
-}
-
-// Encode integer in SLEB128 format.
-void PcDescriptors::EncodeInteger(GrowableArray<uint8_t>* data,
-                                  intptr_t value) {
-  return EncodeSLEB128(data, value);
-}
-
-// Decode SLEB128 encoded integer. Update byte_index to the next integer.
-intptr_t PcDescriptors::DecodeInteger(intptr_t* byte_index) const {
-  NoSafepointScope no_safepoint;
-  const uint8_t* data = raw_ptr()->data();
-  return Utils::DecodeSLEB128<intptr_t>(data, Length(), byte_index);
-}
-
 ObjectPoolPtr ObjectPool::New(intptr_t len) {
   ASSERT(Object::object_pool_class() != Class::null());
   if (len < 0 || len > kMaxElements) {
@@ -14295,25 +14286,25 @@
   StoreNonPointer(&raw_ptr()->length_, value);
 }
 
-void PcDescriptors::CopyData(GrowableArray<uint8_t>* delta_encoded_data) {
+void PcDescriptors::CopyData(const void* bytes, intptr_t size) {
   NoSafepointScope no_safepoint;
   uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
-  for (intptr_t i = 0; i < delta_encoded_data->length(); ++i) {
-    data[i] = (*delta_encoded_data)[i];
-  }
+  // We're guaranted these memory spaces do not overlap.
+  memcpy(data, bytes, size);  // NOLINT
 }
 
-PcDescriptorsPtr PcDescriptors::New(GrowableArray<uint8_t>* data) {
+PcDescriptorsPtr PcDescriptors::New(const void* delta_encoded_data,
+                                    intptr_t size) {
   ASSERT(Object::pc_descriptors_class() != Class::null());
   Thread* thread = Thread::Current();
   PcDescriptors& result = PcDescriptors::Handle(thread->zone());
   {
-    uword size = PcDescriptors::InstanceSize(data->length());
-    ObjectPtr raw = Object::Allocate(PcDescriptors::kClassId, size, Heap::kOld);
+    ObjectPtr raw = Object::Allocate(
+        PcDescriptors::kClassId, PcDescriptors::InstanceSize(size), Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.SetLength(data->length());
-    result.CopyData(data);
+    result.SetLength(size);
+    result.CopyData(delta_encoded_data, size);
   }
   return result.raw();
 }
@@ -14469,45 +14460,195 @@
 }
 
 intptr_t CompressedStackMaps::Hashcode() const {
+  NoSafepointScope scope;
+  uint8_t* data = UnsafeMutableNonPointer(&raw_ptr()->data()[0]);
+  uint8_t* end = data + payload_size();
   uint32_t hash = payload_size();
-  for (uintptr_t i = 0; i < payload_size(); i++) {
-    uint8_t byte = PayloadByte(i);
-    hash = CombineHashes(hash, byte);
+  for (uint8_t* cursor = data; cursor < end; cursor++) {
+    hash = CombineHashes(hash, *cursor);
   }
   return FinalizeHash(hash, kHashBits);
 }
 
-CompressedStackMapsPtr CompressedStackMaps::New(
-    const GrowableArray<uint8_t>& payload,
-    bool is_global_table,
-    bool uses_global_table) {
+CompressedStackMaps::Iterator::Iterator(const CompressedStackMaps& maps,
+                                        const CompressedStackMaps& global_table)
+    : maps_(maps),
+      bits_container_(maps_.UsesGlobalTable() ? global_table : maps_) {
+  ASSERT(!maps_.IsNull());
+  ASSERT(!bits_container_.IsNull());
+  ASSERT(!maps_.IsGlobalTable());
+  ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
+}
+
+CompressedStackMaps::Iterator::Iterator(Thread* thread,
+                                        const CompressedStackMaps& maps)
+    : CompressedStackMaps::Iterator(
+          maps,
+          // Only look up the global table if the map will end up using it.
+          maps.UsesGlobalTable() ? CompressedStackMaps::Handle(
+                                       thread->zone(),
+                                       thread->isolate()
+                                           ->object_store()
+                                           ->canonicalized_stack_map_entries())
+                                 : Object::null_compressed_stackmaps()) {}
+
+CompressedStackMaps::Iterator::Iterator(const CompressedStackMaps::Iterator& it)
+    : maps_(it.maps_),
+      bits_container_(it.bits_container_),
+      next_offset_(it.next_offset_),
+      current_pc_offset_(it.current_pc_offset_),
+      current_global_table_offset_(it.current_global_table_offset_),
+      current_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
+      current_non_spill_slot_bit_count_(it.current_spill_slot_bit_count_),
+      current_bits_offset_(it.current_bits_offset_) {}
+
+bool CompressedStackMaps::Iterator::MoveNext() {
+  if (next_offset_ >= maps_.payload_size()) {
+    return false;
+  }
+
+  NoSafepointScope scope;
+  ReadStream stream(maps_.raw_ptr()->data(), maps_.payload_size(),
+                    next_offset_);
+
+  auto const pc_delta = stream.ReadLEB128();
+  ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_));
+  current_pc_offset_ += pc_delta;
+
+  // Table-using CSMs have a table offset after the PC offset delta, whereas
+  // the post-delta part of inlined entries has the same information as
+  // global table entries.
+  if (maps_.UsesGlobalTable()) {
+    current_global_table_offset_ = stream.ReadLEB128();
+    ASSERT(current_global_table_offset_ < bits_container_.payload_size());
+
+    // Since generally we only use entries in the GC and the GC only needs
+    // the rest of the entry information if the PC offset matches, we lazily
+    // load and cache the information stored in the global object when it is
+    // actually requested.
+    current_spill_slot_bit_count_ = -1;
+    current_non_spill_slot_bit_count_ = -1;
+    current_bits_offset_ = -1;
+
+    next_offset_ = stream.Position();
+  } else {
+    current_spill_slot_bit_count_ = stream.ReadLEB128();
+    ASSERT(current_spill_slot_bit_count_ >= 0);
+
+    current_non_spill_slot_bit_count_ = stream.ReadLEB128();
+    ASSERT(current_non_spill_slot_bit_count_ >= 0);
+
+    const auto stackmap_bits =
+        current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
+    const uintptr_t stackmap_size =
+        Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
+    ASSERT(stackmap_size <= (maps_.payload_size() - stream.Position()));
+
+    current_bits_offset_ = stream.Position();
+    next_offset_ = current_bits_offset_ + stackmap_size;
+  }
+
+  return true;
+}
+
+intptr_t CompressedStackMaps::Iterator::Length() const {
+  EnsureFullyLoadedEntry();
+  return current_spill_slot_bit_count_ + current_non_spill_slot_bit_count_;
+}
+intptr_t CompressedStackMaps::Iterator::SpillSlotBitCount() const {
+  EnsureFullyLoadedEntry();
+  return current_spill_slot_bit_count_;
+}
+
+bool CompressedStackMaps::Iterator::IsObject(intptr_t bit_index) const {
+  EnsureFullyLoadedEntry();
+  ASSERT(bit_index >= 0 && bit_index < Length());
+  const intptr_t byte_index = bit_index >> kBitsPerByteLog2;
+  const intptr_t bit_remainder = bit_index & (kBitsPerByte - 1);
+  uint8_t byte_mask = 1U << bit_remainder;
+  const intptr_t byte_offset = current_bits_offset_ + byte_index;
+  NoSafepointScope scope;
+  return (bits_container_.raw_ptr()->data()[byte_offset] & byte_mask) != 0;
+}
+
+void CompressedStackMaps::Iterator::LazyLoadGlobalTableEntry() const {
+  ASSERT(maps_.UsesGlobalTable());
+  ASSERT(HasLoadedEntry());
+  ASSERT(current_global_table_offset_ < bits_container_.payload_size());
+
+  NoSafepointScope scope;
+  ReadStream stream(bits_container_.raw_ptr()->data(),
+                    bits_container_.payload_size(),
+                    current_global_table_offset_);
+
+  current_spill_slot_bit_count_ = stream.ReadLEB128();
+  ASSERT(current_spill_slot_bit_count_ >= 0);
+
+  current_non_spill_slot_bit_count_ = stream.ReadLEB128();
+  ASSERT(current_non_spill_slot_bit_count_ >= 0);
+
+  const auto stackmap_bits = Length();
+  const uintptr_t stackmap_size =
+      Utils::RoundUp(stackmap_bits, kBitsPerByte) >> kBitsPerByteLog2;
+  ASSERT(stackmap_size <= (bits_container_.payload_size() - stream.Position()));
+
+  current_bits_offset_ = stream.Position();
+}
+
+void CompressedStackMaps::Iterator::WriteToBuffer(BaseTextBuffer* buffer,
+                                                  const char* separator) const {
+  CompressedStackMaps::Iterator it(*this);
+  // If we haven't loaded an entry yet, do so (but don't skip the current
+  // one if we have!)
+  if (!it.HasLoadedEntry()) {
+    if (!it.MoveNext()) return;
+  }
+  bool first_entry = true;
+  do {
+    if (!first_entry) {
+      buffer->AddString(separator);
+    }
+    buffer->Printf("0x%0.8" Px32 ": ", it.pc_offset());
+    for (intptr_t i = 0, n = it.Length(); i < n; i++) {
+      buffer->AddString(it.IsObject(i) ? "1" : "0");
+    }
+    first_entry = false;
+  } while (it.MoveNext());
+}
+
+CompressedStackMapsPtr CompressedStackMaps::New(const void* payload,
+                                                intptr_t size,
+                                                bool is_global_table,
+                                                bool uses_global_table) {
   ASSERT(Object::compressed_stackmaps_class() != Class::null());
   // We don't currently allow both flags to be true.
   ASSERT(!is_global_table || !uses_global_table);
-  auto& result = CompressedStackMaps::Handle();
+  // The canonical empty instance should be used instead.
+  ASSERT(size != 0);
 
-  const uintptr_t payload_size = payload.length();
-  if (!CompressedStackMapsLayout::SizeField::is_valid(payload_size)) {
+  if (!CompressedStackMapsLayout::SizeField::is_valid(size)) {
     FATAL1(
         "Fatal error in CompressedStackMaps::New: "
         "invalid payload size %" Pu "\n",
-        payload_size);
+        size);
   }
+
+  auto& result = CompressedStackMaps::Handle();
   {
     // CompressedStackMaps data objects are associated with a code object,
     // allocate them in old generation.
-    ObjectPtr raw = Object::Allocate(
-        CompressedStackMaps::kClassId,
-        CompressedStackMaps::InstanceSize(payload_size), Heap::kOld);
+    ObjectPtr raw =
+        Object::Allocate(CompressedStackMaps::kClassId,
+                         CompressedStackMaps::InstanceSize(size), Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
     result.StoreNonPointer(
         &result.raw_ptr()->flags_and_size_,
         CompressedStackMapsLayout::GlobalTableBit::encode(is_global_table) |
             CompressedStackMapsLayout::UsesTableBit::encode(uses_global_table) |
-            CompressedStackMapsLayout::SizeField::encode(payload_size));
+            CompressedStackMapsLayout::SizeField::encode(size));
     auto cursor = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
-    memcpy(cursor, payload.data(), payload.length());  // NOLINT
+    memcpy(cursor, payload, size);  // NOLINT
   }
 
   ASSERT(!result.IsGlobalTable() || !result.UsesGlobalTable());
@@ -14517,12 +14658,16 @@
 
 const char* CompressedStackMaps::ToCString() const {
   ASSERT(!IsGlobalTable());
+  if (payload_size() == 0) {
+    return "CompressedStackMaps()";
+  }
   auto const t = Thread::Current();
-  auto zone = t->zone();
-  const auto& global_table = CompressedStackMaps::Handle(
-      zone, t->isolate()->object_store()->canonicalized_stack_map_entries());
-  CompressedStackMapsIterator it(*this, global_table);
-  return it.ToCString(zone);
+  CompressedStackMaps::Iterator it(t, *this);
+  ZoneTextBuffer buffer(t->zone(), 100);
+  buffer.AddString("CompressedStackMaps(");
+  it.WriteToBuffer(&buffer, ", ");
+  buffer.AddString(")");
+  return buffer.buffer();
 }
 
 StringPtr LocalVarDescriptors::GetName(intptr_t var_index) const {
@@ -16474,6 +16619,7 @@
     NOT_IN_PRODUCT(result.set_comments(Comments::New(0)));
     NOT_IN_PRODUCT(result.set_compile_timestamp(0));
     result.set_pc_descriptors(Object::empty_descriptors());
+    result.set_compressed_stackmaps(Object::empty_compressed_stackmaps());
   }
   return result.raw();
 }
@@ -18338,42 +18484,26 @@
 };
 #endif  // DEBUG
 
-bool Instance::CheckAndCanonicalizeFields(Thread* thread,
-                                          const char** error_str) const {
-  ASSERT(error_str != NULL);
-  ASSERT(*error_str == NULL);
+void Instance::CanonicalizeFieldsLocked(Thread* thread) const {
   const intptr_t class_id = GetClassId();
   if (class_id >= kNumPredefinedCids) {
     // Iterate over all fields, canonicalize numbers and strings, expect all
     // other instances to be canonical otherwise report error (return false).
     Zone* zone = thread->zone();
-    Object& obj = Object::Handle(zone);
+    Instance& obj = Instance::Handle(zone);
     const intptr_t instance_size = SizeFromClass();
     ASSERT(instance_size != 0);
     const auto unboxed_fields_bitmap =
         thread->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            GetClassId());
+            class_id);
     for (intptr_t offset = Instance::NextFieldOffset(); offset < instance_size;
          offset += kWordSize) {
       if (unboxed_fields_bitmap.Get(offset / kWordSize)) {
         continue;
       }
-      obj = *this->FieldAddrAtOffset(offset);
-      if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
-        if (obj.IsNumber() || obj.IsString()) {
-          obj = Instance::Cast(obj).CheckAndCanonicalize(thread, error_str);
-          if (*error_str != NULL) {
-            return false;
-          }
-          ASSERT(!obj.IsNull());
-          this->SetFieldAtOffset(offset, obj);
-        } else {
-          char* chars = OS::SCreate(zone, "field: %s, owner: %s\n",
-                                    obj.ToCString(), ToCString());
-          *error_str = chars;
-          return false;
-        }
-      }
+      obj ^= *this->FieldAddrAtOffset(offset);
+      obj = obj.CanonicalizeLocked(thread);
+      this->SetFieldAtOffset(offset, obj);
     }
   } else {
 #if defined(DEBUG)
@@ -18383,45 +18513,40 @@
     ASSERT(!has_pointers.has_pointers());
 #endif  // DEBUG
   }
-  return true;
 }
 
 InstancePtr Instance::CopyShallowToOldSpace(Thread* thread) const {
   return Instance::RawCast(Object::Clone(*this, Heap::kOld));
 }
 
-InstancePtr Instance::CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const {
-  ASSERT(error_str != NULL);
-  ASSERT(*error_str == NULL);
-  ASSERT(!IsNull());
+InstancePtr Instance::Canonicalize(Thread* thread) const {
+  SafepointMutexLocker ml(thread->isolate()->constant_canonicalization_mutex());
+  return CanonicalizeLocked(thread);
+}
+
+InstancePtr Instance::CanonicalizeLocked(Thread* thread) const {
   if (this->IsCanonical()) {
     return this->raw();
   }
-  if (!CheckAndCanonicalizeFields(thread, error_str)) {
-    return Instance::null();
-  }
+  ASSERT(!IsNull());
+  CanonicalizeFieldsLocked(thread);
   Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  Instance& result = Instance::Handle(zone);
   const Class& cls = Class::Handle(zone, this->clazz());
-  {
-    SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
-    result = cls.LookupCanonicalInstance(zone, *this);
-    if (!result.IsNull()) {
-      return result.raw();
-    }
-    if (IsNew()) {
-      ASSERT((isolate == Dart::vm_isolate()) || !InVMIsolateHeap());
-      // Create a canonical object in old space.
-      result ^= Object::Clone(*this, Heap::kOld);
-    } else {
-      result = this->raw();
-    }
-    ASSERT(result.IsOld());
-    result.SetCanonical();
-    return cls.InsertCanonicalConstant(zone, result);
+  Instance& result =
+      Instance::Handle(zone, cls.LookupCanonicalInstance(zone, *this));
+  if (!result.IsNull()) {
+    return result.raw();
   }
+  if (IsNew()) {
+    ASSERT((thread->isolate() == Dart::vm_isolate()) || !InVMIsolateHeap());
+    // Create a canonical object in old space.
+    result ^= Object::Clone(*this, Heap::kOld);
+  } else {
+    result = this->raw();
+  }
+  ASSERT(result.IsOld());
+  result.SetCanonical();
+  return cls.InsertCanonicalConstant(zone, result);
 }
 
 #if defined(DEBUG)
@@ -18495,7 +18620,9 @@
   if (IsNull()) {
     return Type::NullType();
   }
-  const Class& cls = Class::Handle(clazz());
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const Class& cls = Class::Handle(zone, clazz());
   if (!cls.is_finalized()) {
     // Various predefined classes can be instantiated by the VM or
     // Dart_NewString/Integer/TypedData/... before the class is finalized.
@@ -18503,29 +18630,28 @@
     cls.EnsureDeclarationLoaded();
   }
   if (cls.IsClosureClass()) {
-    Function& signature =
-        Function::Handle(Closure::Cast(*this).GetInstantiatedSignature(
-            Thread::Current()->zone()));
-    Type& type = Type::Handle(signature.SignatureType());
+    Function& signature = Function::Handle(
+        zone, Closure::Cast(*this).GetInstantiatedSignature(zone));
+    Type& type = Type::Handle(zone, signature.SignatureType());
     if (!type.IsFinalized()) {
       type.SetIsFinalized();
     }
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     return type.raw();
   }
-  Type& type = Type::Handle();
+  Type& type = Type::Handle(zone);
   if (!cls.IsGeneric()) {
     type = cls.DeclarationType();
   }
   if (type.IsNull()) {
-    TypeArguments& type_arguments = TypeArguments::Handle();
+    TypeArguments& type_arguments = TypeArguments::Handle(zone);
     if (cls.NumTypeArguments() > 0) {
       type_arguments = GetTypeArguments();
     }
     type = Type::New(cls, type_arguments, TokenPosition::kNoSource,
                      Nullability::kNonNullable, space);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
   }
   return type.raw();
 }
@@ -19153,7 +19279,8 @@
   return NULL;
 }
 
-AbstractTypePtr AbstractType::Canonicalize(TrailPtr trail) const {
+AbstractTypePtr AbstractType::Canonicalize(Thread* thread,
+                                           TrailPtr trail) const {
   // AbstractType is an abstract class.
   UNREACHABLE();
   return NULL;
@@ -19806,7 +19933,7 @@
                      Object::null_type_arguments(), TokenPosition::kNoSource,
                      Nullability::kNonNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(Thread::Current(), nullptr);
     type_class.set_declaration_type(type);
   }
   ASSERT(type.IsFinalized());
@@ -19860,7 +19987,7 @@
   if (IsCanonical()) {
     // Object::Clone does not clone canonical bit.
     ASSERT(!type.IsCanonical());
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(Thread::Current(), nullptr);
   }
   return type.raw();
 }
@@ -20191,13 +20318,12 @@
   return nullability() == Nullability::kNonNullable;
 }
 
-AbstractTypePtr Type::Canonicalize(TrailPtr trail) const {
+AbstractTypePtr Type::Canonicalize(Thread* thread, TrailPtr trail) const {
   ASSERT(IsFinalized());
   if (IsCanonical()) {
     ASSERT(TypeArguments::Handle(arguments()).IsOld());
     return this->raw();
   }
-  Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
 
@@ -20224,7 +20350,7 @@
              (isolate == Dart::vm_isolate()));
       // Canonicalize the type arguments of the supertype, if any.
       TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
-      type_args = type_args.Canonicalize(trail);
+      type_args = type_args.Canonicalize(thread, trail);
       if (IsCanonical()) {
         // Canonicalizing type_args canonicalized this type.
         ASSERT(IsRecursive());
@@ -20290,7 +20416,7 @@
         SetHash(0);  // Flush cached hash value.
       }
     }
-    type_args = type_args.Canonicalize(trail);
+    type_args = type_args.Canonicalize(thread, trail);
     if (IsCanonical()) {
       // Canonicalizing type_args canonicalized this type as a side effect.
       ASSERT(IsRecursive());
@@ -20617,7 +20743,7 @@
 // Consider the type Derived, where class Derived extends Base<Derived>.
 // The first type argument of its flattened type argument vector is Derived,
 // represented by a TypeRef pointing to itself.
-AbstractTypePtr TypeRef::Canonicalize(TrailPtr trail) const {
+AbstractTypePtr TypeRef::Canonicalize(Thread* thread, TrailPtr trail) const {
   if (TestAndAddToTrail(&trail)) {
     return raw();
   }
@@ -20625,7 +20751,7 @@
   // referenced recursive type.
   AbstractType& ref_type = AbstractType::Handle(type());
   ASSERT(!ref_type.IsNull());
-  ref_type = ref_type.Canonicalize(trail);
+  ref_type = ref_type.Canonicalize(thread, trail);
   set_type(ref_type);
   return raw();
 }
@@ -20733,7 +20859,7 @@
     // Object::Clone does not clone canonical bit.
     ASSERT(!type_parameter.IsCanonical());
     if (IsFinalized()) {
-      type_parameter ^= type_parameter.Canonicalize();
+      type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
     }
   }
   return type_parameter.raw();
@@ -20953,12 +21079,12 @@
   return result.NormalizeFutureOrType(space);
 }
 
-AbstractTypePtr TypeParameter::Canonicalize(TrailPtr trail) const {
+AbstractTypePtr TypeParameter::Canonicalize(Thread* thread,
+                                            TrailPtr trail) const {
   ASSERT(IsFinalized());
   if (IsCanonical()) {
     return this->raw();
   }
-  Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
 
@@ -21157,16 +21283,15 @@
   return printer.buffer();
 }
 
-InstancePtr Number::CheckAndCanonicalize(Thread* thread,
-                                         const char** error_str) const {
+InstancePtr Number::CanonicalizeLocked(Thread* thread) const {
   intptr_t cid = GetClassId();
   switch (cid) {
     case kSmiCid:
       return static_cast<SmiPtr>(raw_value());
     case kMintCid:
-      return Mint::NewCanonical(Mint::Cast(*this).value());
+      return Mint::NewCanonicalLocked(thread, Mint::Cast(*this).value());
     case kDoubleCid:
-      return Double::NewCanonical(Double::Cast(*this).value());
+      return Double::NewCanonicalLocked(thread, Double::Cast(*this).value());
     default:
       UNREACHABLE();
   }
@@ -21539,33 +21664,28 @@
 }
 
 MintPtr Mint::NewCanonical(int64_t value) {
+  Thread* thread = Thread::Current();
+  SafepointMutexLocker ml(thread->isolate()->constant_canonicalization_mutex());
+  return NewCanonicalLocked(thread, value);
+}
+
+MintPtr Mint::NewCanonicalLocked(Thread* thread, int64_t value) {
   // Do not allocate a Mint if Smi would do.
   ASSERT(!Smi::IsValid(value));
-  Thread* thread = Thread::Current();
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
   const Class& cls = Class::Handle(zone, isolate->object_store()->mint_class());
-  Mint& canonical_value = Mint::Handle(zone);
-  canonical_value = cls.LookupCanonicalMint(zone, value);
+  Mint& canonical_value =
+      Mint::Handle(zone, cls.LookupCanonicalMint(zone, value));
   if (!canonical_value.IsNull()) {
     return canonical_value.raw();
   }
-  {
-    SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
-    // Retry lookup.
-    {
-      canonical_value = cls.LookupCanonicalMint(zone, value);
-      if (!canonical_value.IsNull()) {
-        return canonical_value.raw();
-      }
-    }
-    canonical_value = Mint::New(value, Heap::kOld);
-    canonical_value.SetCanonical();
-    // The value needs to be added to the constants list. Grow the list if
-    // it is full.
-    cls.InsertCanonicalMint(zone, canonical_value);
-    return canonical_value.raw();
-  }
+  canonical_value = Mint::New(value, Heap::kOld);
+  canonical_value.SetCanonical();
+  // The value needs to be added to the constants list. Grow the list if
+  // it is full.
+  cls.InsertCanonicalMint(zone, canonical_value);
+  return canonical_value.raw();
 }
 
 bool Mint::Equals(const Instance& other) const {
@@ -21672,32 +21792,27 @@
 
 DoublePtr Double::NewCanonical(double value) {
   Thread* thread = Thread::Current();
+  SafepointMutexLocker ml(thread->isolate()->constant_canonicalization_mutex());
+  return NewCanonicalLocked(thread, value);
+}
+
+DoublePtr Double::NewCanonicalLocked(Thread* thread, double value) {
   Zone* zone = thread->zone();
   Isolate* isolate = thread->isolate();
-  const Class& cls = Class::Handle(isolate->object_store()->double_class());
+  const Class& cls =
+      Class::Handle(zone, isolate->object_store()->double_class());
   // Linear search to see whether this value is already present in the
   // list of canonicalized constants.
-  Double& canonical_value = Double::Handle(zone);
-
-  canonical_value = cls.LookupCanonicalDouble(zone, value);
+  Double& canonical_value =
+      Double::Handle(zone, cls.LookupCanonicalDouble(zone, value));
   if (!canonical_value.IsNull()) {
     return canonical_value.raw();
   }
-  {
-    SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
-    // Retry lookup.
-    {
-      canonical_value = cls.LookupCanonicalDouble(zone, value);
-      if (!canonical_value.IsNull()) {
-        return canonical_value.raw();
-      }
-    }
-    canonical_value = Double::New(value, Heap::kOld);
-    canonical_value.SetCanonical();
-    // The value needs to be added to the constants list.
-    cls.InsertCanonicalDouble(zone, canonical_value);
-    return canonical_value.raw();
-  }
+  canonical_value = Double::New(value, Heap::kOld);
+  canonical_value.SetCanonical();
+  // The value needs to be added to the constants list.
+  cls.InsertCanonicalDouble(zone, canonical_value);
+  return canonical_value.raw();
 }
 
 DoublePtr Double::NewCanonical(const String& str) {
@@ -21736,25 +21851,6 @@
   return buffer;
 }
 
-// Synchronize with implementation in compiler (intrinsifier).
-class StringHasher : ValueObject {
- public:
-  StringHasher() : hash_(0) {}
-  void Add(int32_t ch) { hash_ = CombineHashes(hash_, ch); }
-  void Add(const String& str, intptr_t begin_index, intptr_t len);
-
-  // Return a non-zero hash of at most 'bits' bits.
-  intptr_t Finalize(int bits) {
-    ASSERT(1 <= bits && bits <= (kBitsPerWord - 1));
-    hash_ = FinalizeHash(hash_, bits);
-    ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
-    return hash_;
-  }
-
- private:
-  uint32_t hash_;
-};
-
 void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) {
   ASSERT(begin_index >= 0);
   ASSERT(len >= 0);
@@ -21764,48 +21860,32 @@
   }
   if (str.IsOneByteString()) {
     NoSafepointScope no_safepoint;
-    uint8_t* str_addr = OneByteString::CharAddr(str, begin_index);
-    for (intptr_t i = 0; i < len; i++) {
-      Add(*str_addr);
-      str_addr++;
-    }
+    Add(OneByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsExternalOneByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(ExternalOneByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsTwoByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(TwoByteString::CharAddr(str, begin_index), len);
+  } else if (str.IsExternalOneByteString()) {
+    NoSafepointScope no_safepoint;
+    Add(ExternalTwoByteString::CharAddr(str, begin_index), len);
   } else {
-    String::CodePointIterator it(str, begin_index, len);
-    while (it.Next()) {
-      Add(it.Current());
-    }
+    UNREACHABLE();
   }
 }
 
 intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
   StringHasher hasher;
   hasher.Add(str, begin_index, len);
-  return hasher.Finalize(kHashBits);
+  return hasher.Finalize();
 }
 
 intptr_t String::HashConcat(const String& str1, const String& str2) {
-  intptr_t len1 = str1.Length();
-  // Since String::Hash works at the code point (rune) level, a surrogate pair
-  // that crosses the boundary between str1 and str2 must be composed.
-  if (str1.IsTwoByteString() && Utf16::IsLeadSurrogate(str1.CharAt(len1 - 1))) {
-    const String& temp = String::Handle(String::Concat(str1, str2));
-    return temp.Hash();
-  } else {
-    StringHasher hasher;
-    hasher.Add(str1, 0, len1);
-    hasher.Add(str2, 0, str2.Length());
-    return hasher.Finalize(kHashBits);
-  }
-}
-
-template <typename T>
-static intptr_t HashImpl(const T* characters, intptr_t len) {
-  ASSERT(len >= 0);
   StringHasher hasher;
-  for (intptr_t i = 0; i < len; i++) {
-    hasher.Add(characters[i]);
-  }
-  return hasher.Finalize(String::kHashBits);
+  hasher.Add(str1, 0, str1.Length());
+  hasher.Add(str2, 0, str2.Length());
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(StringPtr raw) {
@@ -21835,24 +21915,21 @@
 }
 
 intptr_t String::Hash(const char* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  StringHasher hasher;
+  hasher.Add(reinterpret_cast<const uint8_t*>(characters), len);
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(const uint8_t* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  StringHasher hasher;
+  hasher.Add(characters, len);
+  return hasher.Finalize();
 }
 
 intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
   StringHasher hasher;
-  intptr_t i = 0;
-  while (i < len) {
-    hasher.Add(Utf16::Next(characters, &i, len));
-  }
-  return hasher.Finalize(kHashBits);
-}
-
-intptr_t String::Hash(const int32_t* characters, intptr_t len) {
-  return HashImpl(characters, len);
+  hasher.Add(characters, len);
+  return hasher.Finalize();
 }
 
 intptr_t String::CharSize() const {
@@ -22034,8 +22111,7 @@
   return true;
 }
 
-InstancePtr String::CheckAndCanonicalize(Thread* thread,
-                                         const char** error_str) const {
+InstancePtr String::CanonicalizeLocked(Thread* thread) const {
   if (IsCanonical()) {
     return this->raw();
   }
@@ -22650,8 +22726,13 @@
     int32_t ch = T1::CharAt(str1, pos);
     pos++;
 
+    if ((str2_pos < str2_len) && (ch == T2::CharAt(str2, str2_pos))) {
+      str2_pos++;
+      continue;
+    }
+
     if (ch == Library::kPrivateKeySeparator) {
-      // Consume a private key separator.
+      // Consume a private key separator if str1 has it but str2 does not.
       while ((pos < len) && (T1::CharAt(str1, pos) != '.') &&
              (T1::CharAt(str1, pos) != '&')) {
         pos++;
@@ -22659,10 +22740,8 @@
       // Resume matching characters.
       continue;
     }
-    if ((str2_pos == str2_len) || (ch != T2::CharAt(str2, str2_pos))) {
-      return false;
-    }
-    str2_pos++;
+
+    return false;
   }
 
   // We have reached the end of mangled_name string.
@@ -23306,7 +23385,7 @@
   if (!element_type.IsDynamicType()) {
     TypeArguments& type_args = TypeArguments::Handle(TypeArguments::New(1));
     type_args.SetTypeAt(0, element_type);
-    type_args = type_args.Canonicalize();
+    type_args = type_args.Canonicalize(Thread::Current(), nullptr);
     result.SetTypeArguments(type_args);
   }
   return result.raw();
@@ -23467,36 +23546,17 @@
   return array.raw();
 }
 
-bool Array::CheckAndCanonicalizeFields(Thread* thread,
-                                       const char** error_str) const {
-  ASSERT(error_str != NULL);
-  ASSERT(*error_str == NULL);
+void Array::CanonicalizeFieldsLocked(Thread* thread) const {
   intptr_t len = Length();
   if (len > 0) {
     Zone* zone = thread->zone();
-    Object& obj = Object::Handle(zone);
-    // Iterate over all elements, canonicalize numbers and strings, expect all
-    // other instances to be canonical otherwise report error (return false).
+    Instance& obj = Instance::Handle(zone);
     for (intptr_t i = 0; i < len; i++) {
-      obj = At(i);
-      if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
-        if (obj.IsNumber() || obj.IsString()) {
-          obj = Instance::Cast(obj).CheckAndCanonicalize(thread, error_str);
-          if (*error_str != NULL) {
-            return false;
-          }
-          ASSERT(!obj.IsNull());
-          this->SetAt(i, obj);
-        } else {
-          char* chars = OS::SCreate(zone, "element at index %" Pd ": %s\n", i,
-                                    obj.ToCString());
-          *error_str = chars;
-          return false;
-        }
-      }
+      obj ^= At(i);
+      obj = obj.CanonicalizeLocked(thread);
+      this->SetAt(i, obj);
     }
   }
-  return true;
 }
 
 ImmutableArrayPtr ImmutableArray::New(intptr_t len, Heap::Space space) {
@@ -24068,7 +24128,7 @@
   TypeArguments& type_args = TypeArguments::Handle(zone);
   type_args = TypeArguments::New(1);
   type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
-  type_args = type_args.Canonicalize();
+  type_args = type_args.Canonicalize(thread, nullptr);
 
   const Class& cls =
       Class::Handle(Isolate::Current()->class_table()->At(kFfiPointerCid));
@@ -24437,8 +24497,7 @@
 static void PrintNonSymbolicStackFrameBody(BaseTextBuffer* buffer,
                                            uword call_addr,
                                            uword isolate_instructions,
-                                           uword vm_instructions,
-                                           uword isolate_relocated_address) {
+                                           uword vm_instructions) {
   const Image vm_image(reinterpret_cast<const void*>(vm_instructions));
   const Image isolate_image(
       reinterpret_cast<const void*>(isolate_instructions));
@@ -24449,7 +24508,9 @@
     // Only print the relocated address of the call when we know the saved
     // debugging information (if any) will have the same relocated address.
     if (isolate_image.compiled_to_elf()) {
-      buffer->Printf(" virt %" Pp "", isolate_relocated_address + offset);
+      const uword relocated_section_start =
+          isolate_image.instructions_relocated_address();
+      buffer->Printf(" virt %" Pp "", relocated_section_start + offset);
     }
     buffer->Printf(" %s+0x%" Px "", symbol_name, offset);
   } else if (vm_image.contains(call_addr)) {
@@ -24497,10 +24558,10 @@
                                     intptr_t frame_index) {
   ASSERT(!function.IsNull());
   const auto& script = Script::Handle(zone, function.script());
-  auto& handle = String::Handle(zone, function.QualifiedUserVisibleName());
-  auto const function_name = handle.ToCString();
-  handle = script.IsNull() ? String::New("Kernel") : script.url();
-  auto url = handle.ToCString();
+  const char* function_name = function.QualifiedUserVisibleNameCString();
+  const char* url = script.IsNull()
+                        ? "Kernel"
+                        : String::Handle(zone, script.url()).ToCString();
 
   // If the URI starts with "data:application/dart;" this is a URI encoded
   // script so we shouldn't print the entire URI because it could be very long.
@@ -24521,16 +24582,6 @@
   PrintSymbolicStackFrameBody(buffer, function_name, url, line, column);
 }
 
-// Find the relocated base of the given instructions section.
-uword InstructionsRelocatedAddress(uword instructions_start) {
-  Image image(reinterpret_cast<const uint8_t*>(instructions_start));
-  auto const bss_start =
-      reinterpret_cast<const uword*>(instructions_start + image.bss_offset());
-  auto const index =
-      BSS::RelocationIndex(BSS::Relocation::InstructionsRelocatedAddress);
-  return bss_start[index];
-}
-
 const char* StackTrace::ToCString() const {
   auto const T = Thread::Current();
   auto const zone = T->zone();
@@ -24540,6 +24591,7 @@
   auto& code = Code::Handle(zone);
   auto& bytecode = Bytecode::Handle(zone);
 
+  NoSafepointScope no_allocation;
   GrowableArray<const Function*> inlined_functions;
   GrowableArray<TokenPosition> inlined_token_positions;
   ZoneTextBuffer buffer(zone, 1024);
@@ -24549,11 +24601,15 @@
       T->isolate_group()->source()->snapshot_instructions);
   auto const vm_instructions = reinterpret_cast<uword>(
       Dart::vm_isolate()->group()->source()->snapshot_instructions);
-  auto const vm_relocated_address =
-      InstructionsRelocatedAddress(vm_instructions);
-  auto const isolate_relocated_address =
-      InstructionsRelocatedAddress(isolate_instructions);
   if (FLAG_dwarf_stack_traces_mode) {
+    const Image isolate_instructions_image(
+        reinterpret_cast<const void*>(isolate_instructions));
+    const Image vm_instructions_image(
+        reinterpret_cast<const void*>(vm_instructions));
+    auto const isolate_relocated_address =
+        isolate_instructions_image.instructions_relocated_address();
+    auto const vm_relocated_address =
+        vm_instructions_image.instructions_relocated_address();
     // The Dart standard requires the output of StackTrace.toString to include
     // all pending activations with precise source locations (i.e., to expand
     // inlined frames and provide line and column numbers).
@@ -24567,6 +24623,14 @@
     OSThread* thread = OSThread::Current();
     buffer.Printf("pid: %" Pd ", tid: %" Pd ", name %s\n", OS::ProcessId(),
                   OSThread::ThreadIdToIntPtr(thread->id()), thread->name());
+    if (auto const build_id = isolate_instructions_image.build_id()) {
+      const intptr_t length = isolate_instructions_image.build_id_length();
+      buffer.Printf("build_id: '");
+      for (intptr_t i = 0; i < length; i++) {
+        buffer.Printf("%02.2x", build_id[i]);
+      }
+      buffer.Printf("'\n");
+    }
     // Print the dso_base of the VM and isolate_instructions. We print both here
     // as the VM and isolate may be loaded from different snapshot images.
     buffer.Printf("isolate_dso_base: %" Px "",
@@ -24628,8 +24692,7 @@
             // prints call addresses instead of return addresses.
             buffer.Printf("    #%02" Pd " abs %" Pp "", frame_index, call_addr);
             PrintNonSymbolicStackFrameBody(
-                &buffer, call_addr, isolate_instructions, vm_instructions,
-                isolate_relocated_address);
+                &buffer, call_addr, isolate_instructions, vm_instructions);
             frame_index++;
             continue;
           } else if (function.IsNull()) {
@@ -24638,8 +24701,7 @@
             // non-symbolic stack traces.
             PrintSymbolicStackFrameIndex(&buffer, frame_index);
             PrintNonSymbolicStackFrameBody(
-                &buffer, call_addr, isolate_instructions, vm_instructions,
-                isolate_relocated_address);
+                &buffer, call_addr, isolate_instructions, vm_instructions);
             frame_index++;
             continue;
           }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 46144d1b..230312a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -417,12 +417,13 @@
   V(Instance, null_instance)                                                   \
   V(Function, null_function)                                                   \
   V(TypeArguments, null_type_arguments)                                        \
-  V(CompressedStackMaps, null_compressed_stack_maps)                           \
+  V(CompressedStackMaps, null_compressed_stackmaps)                            \
   V(TypeArguments, empty_type_arguments)                                       \
   V(Array, empty_array)                                                        \
   V(Array, zero_array)                                                         \
   V(ContextScope, empty_context_scope)                                         \
   V(ObjectPool, empty_object_pool)                                             \
+  V(CompressedStackMaps, empty_compressed_stackmaps)                           \
   V(PcDescriptors, empty_descriptors)                                          \
   V(LocalVarDescriptors, empty_var_descriptors)                                \
   V(ExceptionHandlers, empty_exception_handlers)                               \
@@ -2482,6 +2483,7 @@
                  BaseTextBuffer* printer) const;
   StringPtr QualifiedScrubbedName() const;
   StringPtr QualifiedUserVisibleName() const;
+  const char* QualifiedUserVisibleNameCString() const;
 
   virtual StringPtr DictionaryName() const { return name(); }
 
@@ -4923,8 +4925,8 @@
 
   intptr_t index() const { return raw_ptr()->index_; }
   void set_index(intptr_t value) const {
-    ASSERT(value == -1 ||
-           value >= 0 && value < std::numeric_limits<classid_t>::max());
+    ASSERT((value == -1) ||
+           ((value >= 0) && (value < std::numeric_limits<classid_t>::max())));
     StoreNonPointer(&raw_ptr()->index_, value);
   }
 
@@ -5510,21 +5512,50 @@
       (kMaxInt32 - (sizeof(InstructionsLayout) + sizeof(ObjectLayout) +
                     (2 * kMaxObjectAlignment)));
 
+  // Currently, we align bare instruction payloads on 4 byte boundaries.
+  //
+  // If we later decide to align on larger boundaries to put entries at the
+  // start of cache lines, make sure to account for entry points that are
+  // _not_ at the start of the payload.
+  static const intptr_t kBarePayloadAlignment = 4;
+
+  // In non-bare mode, we align the payloads on word boundaries.
+  static const intptr_t kNonBarePayloadAlignment = kWordSize;
+
+  // In the precompiled runtime when running in bare instructions mode,
+  // Instructions objects don't exist, just their bare payloads, so we
+  // mark them as unreachable in that case.
+
+  static intptr_t HeaderSize() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    if (FLAG_use_bare_instructions) {
+      UNREACHABLE();
+    }
+#endif
+    return Utils::RoundUp(sizeof(InstructionsLayout), kNonBarePayloadAlignment);
+  }
+
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(InstructionsLayout) ==
-           OFFSET_OF_RETURNED_VALUE(InstructionsLayout, data));
+    ASSERT_EQUAL(sizeof(InstructionsLayout),
+                 OFFSET_OF_RETURNED_VALUE(InstructionsLayout, data));
     return 0;
   }
 
   static intptr_t InstanceSize(intptr_t size) {
-    return Utils::RoundUp(HeaderSize() + size, kObjectAlignment);
-  }
-
-  static intptr_t HeaderSize() {
-    return Utils::RoundUp(sizeof(InstructionsLayout), kWordSize);
+#if defined(DART_PRECOMPILED_RUNTIME)
+    if (FLAG_use_bare_instructions) {
+      UNREACHABLE();
+    }
+#endif
+    return RoundedAllocationSize(HeaderSize() + size);
   }
 
   static InstructionsPtr FromPayloadStart(uword payload_start) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+    if (FLAG_use_bare_instructions) {
+      UNREACHABLE();
+    }
+#endif
     return static_cast<InstructionsPtr>(payload_start - HeaderSize() +
                                         kHeapObjectTag);
   }
@@ -5572,12 +5603,19 @@
   friend class ImageWriter;
 };
 
-// Used only to provide memory accounting for the bare instruction payloads
-// we serialize, since they are no longer part of RawInstructions objects.
+// An InstructionsSection contains extra information about serialized AOT
+// snapshots.
+//
+// To avoid changing the embedder to return more information about an AOT
+// snapshot and possibly disturbing existing clients of that interface, we
+// serialize a single InstructionsSection object at the start of any text
+// segments. In bare instructions mode, it also has the benefit of providing
+// memory accounting for the instructions payloads and avoiding special casing
+// Images with bare instructions payloads in the GC. Otherwise, it is empty
+// and the Instructions objects come after it in the Image.
 class InstructionsSection : public Object {
  public:
   // Excludes HeaderSize().
-  intptr_t Size() const { return raw_ptr()->payload_length_; }
   static intptr_t Size(const InstructionsSectionPtr instr) {
     return instr->ptr()->payload_length_;
   }
@@ -5592,10 +5630,18 @@
   }
 
   static intptr_t HeaderSize() {
-    return Utils::RoundUp(sizeof(InstructionsSectionLayout), kWordSize);
+    return Utils::RoundUp(sizeof(InstructionsSectionLayout),
+                          Instructions::kBarePayloadAlignment);
   }
 
+  // There are no public instance methods for the InstructionsSection class, as
+  // all access to the contents is handled by methods on the Image class.
+
  private:
+  // Note there are no New() methods for InstructionsSection. Instead, the
+  // serializer writes the InstructionsSectionLayout object manually at the
+  // start of instructions Images in precompiled snapshots.
+
   FINAL_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection, Object);
   friend class Class;
 };
@@ -5645,15 +5691,14 @@
   static const intptr_t kBytesPerElement = 1;
   static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
 
+  static intptr_t HeaderSize() { return sizeof(PcDescriptorsLayout); }
   static intptr_t UnroundedSize(PcDescriptorsPtr desc) {
     return UnroundedSize(desc->ptr()->length_);
   }
-  static intptr_t UnroundedSize(intptr_t len) {
-    return sizeof(PcDescriptorsLayout) + len;
-  }
+  static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(PcDescriptorsLayout) ==
-           OFFSET_OF_RETURNED_VALUE(PcDescriptorsLayout, data));
+    ASSERT_EQUAL(sizeof(PcDescriptorsLayout),
+                 OFFSET_OF_RETURNED_VALUE(PcDescriptorsLayout, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
@@ -5661,7 +5706,7 @@
     return RoundedAllocationSize(UnroundedSize(len));
   }
 
-  static PcDescriptorsPtr New(GrowableArray<uint8_t>* delta_encoded_data);
+  static PcDescriptorsPtr New(const void* delta_encoded_data, intptr_t size);
 
   // Verify (assert) assumptions about pc descriptors in debug mode.
   void Verify(const Function& function) const;
@@ -5670,12 +5715,6 @@
 
   void PrintToJSONObject(JSONObject* jsobj, bool ref) const;
 
-  // Encode integer in SLEB128 format.
-  static void EncodeInteger(GrowableArray<uint8_t>* data, intptr_t value);
-
-  // Decode SLEB128 encoded integer. Update byte_index to the next integer.
-  intptr_t DecodeInteger(intptr_t* byte_index) const;
-
   // We would have a VisitPointers function here to traverse the
   // pc descriptors table to visit objects if any in the table.
   // Note: never return a reference to a PcDescriptorsLayout::PcDescriptorRec
@@ -5694,10 +5733,12 @@
           cur_yield_index_(PcDescriptorsLayout::kInvalidYieldIndex) {}
 
     bool MoveNext() {
+      NoSafepointScope scope;
+      ReadStream stream(descriptors_.raw_ptr()->data(), descriptors_.Length(),
+                        byte_index_);
       // Moves to record that matches kind_mask_.
       while (byte_index_ < descriptors_.Length()) {
-        const int32_t kind_and_metadata =
-            descriptors_.DecodeInteger(&byte_index_);
+        const int32_t kind_and_metadata = stream.ReadSLEB128<int32_t>();
         cur_kind_ =
             PcDescriptorsLayout::KindAndMetadata::DecodeKind(kind_and_metadata);
         cur_try_index_ = PcDescriptorsLayout::KindAndMetadata::DecodeTryIndex(
@@ -5706,12 +5747,13 @@
             PcDescriptorsLayout::KindAndMetadata::DecodeYieldIndex(
                 kind_and_metadata);
 
-        cur_pc_offset_ += descriptors_.DecodeInteger(&byte_index_);
+        cur_pc_offset_ += stream.ReadSLEB128();
 
         if (!FLAG_precompiled_mode) {
-          cur_deopt_id_ += descriptors_.DecodeInteger(&byte_index_);
-          cur_token_pos_ += descriptors_.DecodeInteger(&byte_index_);
+          cur_deopt_id_ += stream.ReadSLEB128();
+          cur_token_pos_ += stream.ReadSLEB128();
         }
+        byte_index_ = stream.Position();
 
         if ((cur_kind_ & kind_mask_) != 0) {
           return true;  // Current is valid.
@@ -5772,7 +5814,7 @@
   static PcDescriptorsPtr New(intptr_t length);
 
   void SetLength(intptr_t value) const;
-  void CopyData(GrowableArray<uint8_t>* data);
+  void CopyData(const void* bytes, intptr_t size);
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(PcDescriptors, Object);
   friend class Class;
@@ -5784,15 +5826,14 @@
   static const intptr_t kBytesPerElement = 1;
   static const intptr_t kMaxElements = kMaxInt32 / kBytesPerElement;
 
+  static intptr_t HeaderSize() { return sizeof(CodeSourceMapLayout); }
   static intptr_t UnroundedSize(CodeSourceMapPtr map) {
     return UnroundedSize(map->ptr()->length_);
   }
-  static intptr_t UnroundedSize(intptr_t len) {
-    return sizeof(CodeSourceMapLayout) + len;
-  }
+  static intptr_t UnroundedSize(intptr_t len) { return HeaderSize() + len; }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(CodeSourceMapLayout) ==
-           OFFSET_OF_RETURNED_VALUE(CodeSourceMapLayout, data));
+    ASSERT_EQUAL(sizeof(CodeSourceMapLayout),
+                 OFFSET_OF_RETURNED_VALUE(CodeSourceMapLayout, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t len) {
@@ -5849,61 +5890,133 @@
   bool Equals(const CompressedStackMaps* other) const { return Equals(*other); }
   intptr_t Hashcode() const;
 
+  static intptr_t HeaderSize() { return sizeof(CompressedStackMapsLayout); }
   static intptr_t UnroundedSize(CompressedStackMapsPtr maps) {
     return UnroundedSize(CompressedStackMaps::PayloadSizeOf(maps));
   }
   static intptr_t UnroundedSize(intptr_t length) {
-    return sizeof(CompressedStackMapsLayout) + length;
+    return HeaderSize() + length;
   }
   static intptr_t InstanceSize() {
-    ASSERT(sizeof(CompressedStackMapsLayout) ==
-           OFFSET_OF_RETURNED_VALUE(CompressedStackMapsLayout, data));
+    ASSERT_EQUAL(sizeof(CompressedStackMapsLayout),
+                 OFFSET_OF_RETURNED_VALUE(CompressedStackMapsLayout, data));
     return 0;
   }
   static intptr_t InstanceSize(intptr_t length) {
     return RoundedAllocationSize(UnroundedSize(length));
   }
 
-  bool UsesGlobalTable() const { return !IsNull() && UsesGlobalTable(raw()); }
+  bool UsesGlobalTable() const { return UsesGlobalTable(raw()); }
   static bool UsesGlobalTable(const CompressedStackMapsPtr raw) {
     return CompressedStackMapsLayout::UsesTableBit::decode(
         raw->ptr()->flags_and_size_);
   }
 
-  bool IsGlobalTable() const { return !IsNull() && IsGlobalTable(raw()); }
+  bool IsGlobalTable() const { return IsGlobalTable(raw()); }
   static bool IsGlobalTable(const CompressedStackMapsPtr raw) {
     return CompressedStackMapsLayout::GlobalTableBit::decode(
         raw->ptr()->flags_and_size_);
   }
 
-  static CompressedStackMapsPtr NewInlined(
-      const GrowableArray<uint8_t>& bytes) {
-    return New(bytes, /*is_global_table=*/false, /*uses_global_table=*/false);
+  static CompressedStackMapsPtr NewInlined(const void* payload, intptr_t size) {
+    return New(payload, size, /*is_global_table=*/false,
+               /*uses_global_table=*/false);
   }
-  static CompressedStackMapsPtr NewUsingTable(
-      const GrowableArray<uint8_t>& bytes) {
-    return New(bytes, /*is_global_table=*/false, /*uses_global_table=*/true);
+  static CompressedStackMapsPtr NewUsingTable(const void* payload,
+                                              intptr_t size) {
+    return New(payload, size, /*is_global_table=*/false,
+               /*uses_global_table=*/true);
   }
 
-  static CompressedStackMapsPtr NewGlobalTable(
-      const GrowableArray<uint8_t>& bytes) {
-    return New(bytes, /*is_global_table=*/true, /*uses_global_table=*/false);
+  static CompressedStackMapsPtr NewGlobalTable(const void* payload,
+                                               intptr_t size) {
+    return New(payload, size, /*is_global_table=*/true,
+               /*uses_global_table=*/false);
   }
 
+  class Iterator : public ValueObject {
+   public:
+    Iterator(const CompressedStackMaps& maps,
+             const CompressedStackMaps& global_table);
+    Iterator(Thread* thread, const CompressedStackMaps& maps);
+
+    explicit Iterator(const CompressedStackMaps::Iterator& it);
+
+    // Loads the next entry from [maps_], if any. If [maps_] is the null value,
+    // this always returns false.
+    bool MoveNext();
+
+    // Finds the entry with the given PC offset starting at the current position
+    // of the iterator. If [maps_] is the null value, this always returns false.
+    bool Find(uint32_t pc_offset) {
+      // We should never have an entry with a PC offset of 0 inside an
+      // non-empty CSM, so fail.
+      if (pc_offset == 0) return false;
+      do {
+        if (current_pc_offset_ >= pc_offset) break;
+      } while (MoveNext());
+      return current_pc_offset_ == pc_offset;
+    }
+
+    // Methods for accessing parts of an entry should not be called until
+    // a successful MoveNext() or Find() call has been made.
+
+    // Returns the PC offset of the loaded entry.
+    uint32_t pc_offset() const {
+      ASSERT(HasLoadedEntry());
+      return current_pc_offset_;
+    }
+
+    // Returns the bit length of the loaded entry.
+    intptr_t Length() const;
+    // Returns the number of spill slot bits of the loaded entry.
+    intptr_t SpillSlotBitCount() const;
+    // Returns whether the stack entry represented by the offset contains
+    // a tagged objecet.
+    bool IsObject(intptr_t bit_offset) const;
+
+    void WriteToBuffer(BaseTextBuffer* buffer, const char* separator) const;
+
+   private:
+    bool HasLoadedEntry() const { return next_offset_ > 0; }
+
+    // Caches the corresponding values from the global table in the mutable
+    // fields. We lazily load these as some clients only need the PC offset.
+    void LazyLoadGlobalTableEntry() const;
+
+    void EnsureFullyLoadedEntry() const {
+      ASSERT(HasLoadedEntry());
+      if (current_spill_slot_bit_count_ < 0) {
+        LazyLoadGlobalTableEntry();
+        ASSERT(current_spill_slot_bit_count_ >= 0);
+      }
+    }
+
+    const CompressedStackMaps& maps_;
+    const CompressedStackMaps& bits_container_;
+
+    uintptr_t next_offset_ = 0;
+    uint32_t current_pc_offset_ = 0;
+    // Only used when looking up non-PC information in the global table.
+    uintptr_t current_global_table_offset_ = 0;
+    // Marked as mutable as these fields may be updated with lazily loaded
+    // values from the global table when their associated accessor is called,
+    // but those values will never change for a given entry once loaded..
+    mutable intptr_t current_spill_slot_bit_count_ = -1;
+    mutable intptr_t current_non_spill_slot_bit_count_ = -1;
+    mutable intptr_t current_bits_offset_ = -1;
+
+    friend class StackMapEntry;
+  };
+
  private:
-  static CompressedStackMapsPtr New(const GrowableArray<uint8_t>& bytes,
+  static CompressedStackMapsPtr New(const void* payload,
+                                    intptr_t size,
                                     bool is_global_table,
                                     bool uses_global_table);
 
-  uint8_t PayloadByte(uintptr_t offset) const {
-    ASSERT(offset < payload_size());
-    return raw_ptr()->data()[offset];
-  }
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(CompressedStackMaps, Object);
   friend class Class;
-  friend class CompressedStackMapsIterator;  // For PayloadByte
-  friend class StackMapEntry;                // For PayloadByte
 };
 
 class ExceptionHandlers : public Object {
@@ -7328,17 +7441,10 @@
     return (clazz()->ptr()->host_instance_size_in_words_ * kWordSize);
   }
 
-  // Returns Instance::null() if instance cannot be canonicalized.
-  // Any non-canonical number of string will be canonicalized here.
-  // An instance cannot be canonicalized if it still contains non-canonical
-  // instances in its fields.
-  // Returns error in error_str, pass NULL if an error cannot occur.
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const;
-
-  // Returns true if all fields are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Thread* thread,
-                                          const char** error_str) const;
+  InstancePtr Canonicalize(Thread* thread) const;
+  // Caller must hold Isolate::constant_canonicalization_mutex_.
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
+  virtual void CanonicalizeFieldsLocked(Thread* thread) const;
 
   InstancePtr CopyShallowToOldSpace(Thread* thread) const;
 
@@ -7709,13 +7815,13 @@
   // Return true if this vector contains a recursive type argument.
   bool IsRecursive() const;
 
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const {
-    return Canonicalize();
+  // Caller must hold Isolate::constant_canonicalization_mutex_.
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
+    return Canonicalize(thread, nullptr);
   }
 
   // Canonicalize only if instantiated, otherwise returns 'this'.
-  TypeArgumentsPtr Canonicalize(TrailPtr trail = nullptr) const;
+  TypeArgumentsPtr Canonicalize(Thread* thread, TrailPtr trail = nullptr) const;
 
   // Add the class name and URI of each type argument of this vector to the uris
   // list and mark ambiguous triplets to be printed.
@@ -7902,13 +8008,13 @@
       Heap::Space space,
       TrailPtr trail = nullptr) const;
 
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const {
-    return Canonicalize();
+  // Caller must hold Isolate::constant_canonicalization_mutex_.
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
+    return Canonicalize(thread, nullptr);
   }
 
   // Return the canonical version of this type.
-  virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const;
+  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
 
 #if defined(DEBUG)
   // Check if abstract type is canonical.
@@ -8165,7 +8271,7 @@
       intptr_t num_free_fun_type_params,
       Heap::Space space,
       TrailPtr trail = nullptr) const;
-  virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const;
+  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
 #if defined(DEBUG)
   // Check if type is canonical.
   virtual bool CheckIsCanonical(Thread* thread) const;
@@ -8322,7 +8428,7 @@
       intptr_t num_free_fun_type_params,
       Heap::Space space,
       TrailPtr trail = nullptr) const;
-  virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const;
+  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
 #if defined(DEBUG)
   // Check if typeref is canonical.
   virtual bool CheckIsCanonical(Thread* thread) const;
@@ -8414,7 +8520,7 @@
       intptr_t num_free_fun_type_params,
       Heap::Space space,
       TrailPtr trail = nullptr) const;
-  virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const;
+  virtual AbstractTypePtr Canonicalize(Thread* thread, TrailPtr trail) const;
 #if defined(DEBUG)
   // Check if type parameter is canonical.
   virtual bool CheckIsCanonical(Thread* thread) const;
@@ -8469,8 +8575,8 @@
   StringPtr ToString(Heap::Space space) const;
 
   // Numbers are canonicalized differently from other instances/strings.
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const;
+  // Caller must hold Isolate::constant_canonicalization_mutex_.
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
 
 #if defined(DEBUG)
   // Check if number is canonical.
@@ -8675,6 +8781,7 @@
   static MintPtr New(int64_t value, Heap::Space space = Heap::kNew);
 
   static MintPtr NewCanonical(int64_t value);
+  static MintPtr NewCanonicalLocked(Thread* thread, int64_t value);
 
  private:
   void set_value(int64_t value) const;
@@ -8701,6 +8808,7 @@
 
   // Returns a canonical double object allocated in the old gen space.
   static DoublePtr NewCanonical(double d);
+  static DoublePtr NewCanonicalLocked(Thread* thread, double d);
 
   // Returns a canonical double object (allocated in the old gen space) or
   // Double::null() if str points to a string that does not convert to a
@@ -8859,8 +8967,8 @@
   bool EndsWith(const String& other) const;
 
   // Strings are canonicalized using the symbol table.
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const;
+  // Caller must hold Isolate::constant_canonicalization_mutex_.
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const;
 
 #if defined(DEBUG)
   // Check if string is canonical.
@@ -9065,6 +9173,32 @@
   friend class Pass2Visitor;                // Stack "handle"
 };
 
+// Synchronize with implementation in compiler (intrinsifier).
+class StringHasher : ValueObject {
+ public:
+  StringHasher() : hash_(0) {}
+  void Add(uint16_t code_unit) { hash_ = CombineHashes(hash_, code_unit); }
+  void Add(const uint8_t* code_units, intptr_t len) {
+    while (len > 0) {
+      Add(*code_units);
+      code_units++;
+      len--;
+    }
+  }
+  void Add(const uint16_t* code_units, intptr_t len) {
+    while (len > 0) {
+      Add(LoadUnaligned(code_units));
+      code_units++;
+      len--;
+    }
+  }
+  void Add(const String& str, intptr_t begin_index, intptr_t len);
+  intptr_t Finalize() { return FinalizeHash(hash_, String::kHashBits); }
+
+ private:
+  uint32_t hash_;
+};
+
 class OneByteString : public AllStatic {
  public:
   static uint16_t CharAt(const String& str, intptr_t index) {
@@ -9327,6 +9461,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
 };
@@ -9424,6 +9559,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
   friend class Utf8;
@@ -9518,6 +9654,7 @@
 
   friend class Class;
   friend class String;
+  friend class StringHasher;
   friend class SnapshotReader;
   friend class Symbols;
 };
@@ -9665,9 +9802,7 @@
                                  (len * kBytesPerElement));
   }
 
-  // Returns true if all elements are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Thread* thread,
-                                          const char** error_str) const;
+  virtual void CanonicalizeFieldsLocked(Thread* thread) const;
 
   // Make the array immutable to Dart code by switching the class pointer
   // to ImmutableArray.
@@ -9842,8 +9977,7 @@
   }
 
   // We don't expect a growable object array to be canonicalized.
-  virtual InstancePtr CheckAndCanonicalize(Thread* thread,
-                                           const char** error_str) const {
+  virtual InstancePtr CanonicalizeLocked(Thread* thread) const {
     UNREACHABLE();
     return Instance::null();
   }
@@ -10212,7 +10346,6 @@
 
   FINAL_HEAP_OBJECT_IMPLEMENTATION(TypedData, TypedDataBase);
   friend class Class;
-  friend class CompressedStackMapsIterator;
   friend class ExternalTypedData;
   friend class TypedDataView;
 };
@@ -10644,10 +10777,8 @@
   }
 
   // Returns true if all elements are OK for canonicalization.
-  virtual bool CheckAndCanonicalizeFields(Thread* thread,
-                                          const char** error_str) const {
+  virtual void CanonicalizeFieldsLocked(Thread* thread) const {
     // None of the fields of a closure are instances.
-    return true;
   }
   virtual uint32_t CanonicalizeHash() const {
     return Function::Handle(function()).Hash();
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index e127267..2cd2590 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -48,6 +48,8 @@
     object_ids_ = nullptr;
   }
 
+  virtual bool trace_values_through_fields() const { return true; }
+
   // Marks and pushes. Used to initialize this stack with roots.
   // We can use ObjectIdTable normally used by serializers because it
   // won't be in use while handling a service request (ObjectGraph's only use).
@@ -472,6 +474,8 @@
     ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
   }
 
+  virtual bool trace_values_through_fields() const { return true; }
+
   intptr_t length() const { return length_; }
 
   virtual void VisitObject(ObjectPtr raw_obj) {
@@ -765,6 +769,8 @@
         HandleVisitor(Thread::Current()),
         writer_(writer) {}
 
+  virtual bool trace_values_through_fields() const { return true; }
+
   void VisitObject(ObjectPtr obj) {
     if (obj->IsPseudoObject()) return;
 
@@ -819,6 +825,8 @@
         isolate_(thread()->isolate()),
         writer_(writer) {}
 
+  virtual bool trace_values_through_fields() const { return true; }
+
   void VisitObject(ObjectPtr obj) {
     if (obj->IsPseudoObject()) return;
 
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 847d1a4..7cde5c3 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -296,7 +296,7 @@
   {
     // Class has no canonical constants allocated.
     const Array& my_constants = Array::Handle(constants());
-    ASSERT(my_constants.Length() == 0);
+    ASSERT(my_constants.IsNull() || my_constants.Length() == 0);
   }
 #endif  // defined(DEBUG).
   // Copy old constants into new class.
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 319cff6..c70282b 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+#include "vm/canonical_tables.h"
 #include "vm/compiler/assembler/disassembler.h"
 #include "vm/debugger.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/stub_code.h"
 #include "vm/symbols.h"
-#include "vm/type_table.h"
 
 namespace dart {
 
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 37b39ac..36705f7 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -55,17 +55,6 @@
 }
 #endif  // !PRODUCT
 
-static UnhandledExceptionPtr CreatePreallocatedUnandledException(
-    Zone* zone,
-    const Object& out_of_memory) {
-  // Allocate pre-allocated unhandled exception object initialized with the
-  // pre-allocated OutOfMemoryError.
-  const UnhandledException& unhandled_exception =
-      UnhandledException::Handle(UnhandledException::New(
-          Instance::Cast(out_of_memory), StackTrace::Handle(zone)));
-  return unhandled_exception.raw();
-}
-
 static StackTracePtr CreatePreallocatedStackTrace(Zone* zone) {
   const Array& code_array = Array::Handle(
       zone, Array::New(StackTrace::kPreallocatedStackdepth, Heap::kOld));
@@ -93,10 +82,12 @@
   // pre-allocated OutOfMemoryError.
   const Object& out_of_memory =
       Object::Handle(zone, object_store_->out_of_memory());
+  const StackTrace& preallocated_stack_trace =
+      StackTrace::Handle(zone, CreatePreallocatedStackTrace(zone));
+  set_preallocated_stack_trace(preallocated_stack_trace);
   set_preallocated_unhandled_exception(UnhandledException::Handle(
-      CreatePreallocatedUnandledException(zone, out_of_memory)));
-  set_preallocated_stack_trace(
-      StackTrace::Handle(CreatePreallocatedStackTrace(zone)));
+      zone, UnhandledException::New(Instance::Cast(out_of_memory),
+                                    preallocated_stack_trace)));
 
   return Error::null();
 }
@@ -378,7 +369,7 @@
     type = Type::New(cls, type_args, TokenPosition::kNoSource,
                      Nullability::kNonNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     set_non_nullable_future_never_type(type);
     type = null_type();
     ASSERT(!type.IsNull());
@@ -387,7 +378,7 @@
     type = Type::New(cls, type_args, TokenPosition::kNoSource,
                      Nullability::kNullable);
     type.SetIsFinalized();
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(thread, nullptr);
     set_nullable_future_null_type(type);
     type ^= cls.RareType();
     set_non_nullable_future_rare_type(type);
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index f8046bd..fa649a5 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -193,6 +193,20 @@
   RW(Code, stack_overflow_stub_with_fpu_regs_stub)                             \
   RW(Code, stack_overflow_stub_without_fpu_regs_stub)                          \
   RW(Code, allocate_array_stub)                                                \
+  RW(Code, allocate_int8_array_stub)                                           \
+  RW(Code, allocate_uint8_array_stub)                                          \
+  RW(Code, allocate_uint8_clamped_array_stub)                                  \
+  RW(Code, allocate_int16_array_stub)                                          \
+  RW(Code, allocate_uint16_array_stub)                                         \
+  RW(Code, allocate_int32_array_stub)                                          \
+  RW(Code, allocate_uint32_array_stub)                                         \
+  RW(Code, allocate_int64_array_stub)                                          \
+  RW(Code, allocate_uint64_array_stub)                                         \
+  RW(Code, allocate_float32_array_stub)                                        \
+  RW(Code, allocate_float64_array_stub)                                        \
+  RW(Code, allocate_float32x4_array_stub)                                      \
+  RW(Code, allocate_int32x4_array_stub)                                        \
+  RW(Code, allocate_float64x2_array_stub)                                      \
   RW(Code, allocate_context_stub)                                              \
   RW(Code, allocate_object_stub)                                               \
   RW(Code, allocate_object_parametrized_stub)                                  \
@@ -244,6 +258,20 @@
   DO(stack_overflow_stub_without_fpu_regs_stub,                                \
      StackOverflowSharedWithoutFPURegs)                                        \
   DO(allocate_array_stub, AllocateArray)                                       \
+  DO(allocate_int8_array_stub, AllocateInt8Array)                              \
+  DO(allocate_uint8_array_stub, AllocateUint8Array)                            \
+  DO(allocate_uint8_clamped_array_stub, AllocateUint8ClampedArray)             \
+  DO(allocate_int16_array_stub, AllocateInt16Array)                            \
+  DO(allocate_uint16_array_stub, AllocateUint16Array)                          \
+  DO(allocate_int32_array_stub, AllocateInt32Array)                            \
+  DO(allocate_uint32_array_stub, AllocateUint32Array)                          \
+  DO(allocate_int64_array_stub, AllocateInt64Array)                            \
+  DO(allocate_uint64_array_stub, AllocateUint64Array)                          \
+  DO(allocate_float32_array_stub, AllocateFloat32Array)                        \
+  DO(allocate_float64_array_stub, AllocateFloat64Array)                        \
+  DO(allocate_float32x4_array_stub, AllocateFloat32x4Array)                    \
+  DO(allocate_int32x4_array_stub, AllocateInt32x4Array)                        \
+  DO(allocate_float64x2_array_stub, AllocateFloat64x2Array)                    \
   DO(allocate_context_stub, AllocateContext)                                   \
   DO(allocate_object_stub, AllocateObject)                                     \
   DO(allocate_object_parametrized_stub, AllocateObjectParameterized)           \
@@ -451,6 +479,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
         return reinterpret_cast<ObjectPtr*>(&global_object_pool_);
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 68f2de9..b0eff0e 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -251,8 +251,8 @@
   OS::PrintErr("2: %s\n", type_arguments2.ToCString());
   EXPECT(type_arguments1.Equals(type_arguments2));
   TypeArguments& type_arguments3 = TypeArguments::Handle();
-  type_arguments1.Canonicalize();
-  type_arguments3 ^= type_arguments2.Canonicalize();
+  type_arguments1.Canonicalize(thread, nullptr);
+  type_arguments3 ^= type_arguments2.Canonicalize(thread, nullptr);
   EXPECT_EQ(type_arguments1.raw(), type_arguments3.raw());
 }
 
@@ -1338,7 +1338,7 @@
   const String& clef = String::Handle(String::FromUTF16(clef_utf16, 2));
   int32_t clef_utf32[] = {0x1D11E};
   EXPECT(clef.Equals(clef_utf32, 1));
-  intptr_t hash32 = String::Hash(clef_utf32, 1);
+  intptr_t hash32 = String::Hash(String::FromUTF32(clef_utf32, 1));
   EXPECT_EQ(hash32, clef.Hash());
   EXPECT_EQ(hash32, String::HashConcat(
                         String::Handle(String::FromUTF16(clef_utf16, 1)),
@@ -1817,7 +1817,8 @@
   uint16_t char16[] = {'E', 'l', 'f'};
   String& elf1 = String::Handle(Symbols::FromUTF16(thread, char16, 3));
   int32_t char32[] = {'E', 'l', 'f'};
-  String& elf2 = String::Handle(Symbols::FromUTF32(thread, char32, 3));
+  String& elf2 = String::Handle(
+      Symbols::New(thread, String::Handle(String::FromUTF32(char32, 3))));
   EXPECT(elf1.IsSymbol());
   EXPECT(elf2.IsSymbol());
   EXPECT_EQ(elf1.raw(), Symbols::New(thread, "Elf"));
@@ -1832,13 +1833,14 @@
   EXPECT_EQ(monkey.raw(), Symbols::New(thread, monkey_utf8));
 
   int32_t kMonkeyFace = 0x1f435;
-  String& monkey2 = String::Handle(Symbols::FromCharCode(thread, kMonkeyFace));
+  String& monkey2 = String::Handle(
+      Symbols::New(thread, String::Handle(String::FromUTF32(&kMonkeyFace, 1))));
   EXPECT_EQ(monkey.raw(), monkey2.raw());
 
   // Unicode cat face with tears of joy.
   int32_t kCatFaceWithTearsOfJoy = 0x1f639;
-  String& cat =
-      String::Handle(Symbols::FromCharCode(thread, kCatFaceWithTearsOfJoy));
+  String& cat = String::Handle(Symbols::New(
+      thread, String::Handle(String::FromUTF32(&kCatFaceWithTearsOfJoy, 1))));
 
   uint16_t cat_utf16[] = {0xd83d, 0xde39};
   String& cat2 = String::Handle(Symbols::FromUTF16(thread, cat_utf16, 2));
@@ -2786,7 +2788,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(PcDescriptors) {
-  DescriptorList* builder = new DescriptorList(0);
+  DescriptorList* builder = new DescriptorList(thread->zone());
 
   // kind, pc_offset, deopt_id, token_pos, try_index, yield_index
   builder->AddDescriptor(PcDescriptorsLayout::kOther, 10, 1, TokenPosition(20),
@@ -2856,7 +2858,7 @@
 }
 
 ISOLATE_UNIT_TEST_CASE(PcDescriptorsLargeDeltas) {
-  DescriptorList* builder = new DescriptorList(0);
+  DescriptorList* builder = new DescriptorList(thread->zone());
 
   // kind, pc_offset, deopt_id, token_pos, try_index
   builder->AddDescriptor(PcDescriptorsLayout::kOther, 100, 1,
@@ -3208,6 +3210,12 @@
   bare_name = OneByteString::New("foo.named");
   EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
 
+  // Named double-private constructor match where the caller knows the private
+  // key.  Yes, this also happens.
+  mangled_name = OneByteString::New("foo@12345.named@12345");
+  bare_name = OneByteString::New("foo@12345.named");
+  EXPECT(String::EqualsIgnoringPrivateKey(mangled_name, bare_name));
+
   // Named double-private constructor mismatch.
   mangled_name = OneByteString::New("foo@12345.name@12345");
   bare_name = OneByteString::New("foo.named");
diff --git a/runtime/vm/os_thread.cc b/runtime/vm/os_thread.cc
index 61b929c..a3d8b32 100644
--- a/runtime/vm/os_thread.cc
+++ b/runtime/vm/os_thread.cc
@@ -135,6 +135,7 @@
 }
 
 static void DeleteThread(void* thread) {
+  MSAN_UNPOISON(&thread, sizeof(thread));
   delete reinterpret_cast<OSThread*>(thread);
 }
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index d3e0e47..9902dc6 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -211,6 +211,9 @@
       if (variable->is_explicit_covariant_parameter()) {
         raw_parameter->set_is_explicit_covariant_parameter();
       }
+      if (variable->needs_covariant_check_in_method()) {
+        raw_parameter->set_needs_covariant_check_in_method();
+      }
       raw_parameter->set_type_check_mode(variable->type_check_mode());
       if (function().HasOptionalParameters()) {
         bool ok = scope->AddVariable(raw_parameter);
@@ -345,8 +348,6 @@
   if (dynamic_closure_call_vars_ != nullptr) return dynamic_closure_call_vars_;
   dynamic_closure_call_vars_ = new (zone()) DynamicClosureCallVars();
 
-  const auto& type_Array = Type::ZoneHandle(zone(), Type::ArrayType());
-  const auto& type_Bool = Type::ZoneHandle(zone(), Type::BoolType());
   const auto& type_Smi = Type::ZoneHandle(zone(), Type::SmiType());
 #define INIT_FIELD(Name, TypeName, Symbol)                                     \
   dynamic_closure_call_vars_->Name = new (zone())                              \
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 6ea6d2a..9c56692 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -243,15 +243,12 @@
   // method.
   bool IsGenericCovariantImplParameter(intptr_t i) const;
 
-  // Variables needed for the InvokeFieldDispatcher for dynamic closure calls.
+  // Variables needed for the InvokeFieldDispatcher for dynamic closure calls,
+  // because they are both read and written to by the builders.
   struct DynamicClosureCallVars : ZoneAllocated {
 #define FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(V)                              \
-  V(current_param_index, Smi, CurrentParamIndex)                               \
-  V(has_named_params, Bool, HasNamed)                                          \
-  V(num_fixed_params, Smi, NumFixed)                                           \
-  V(num_opt_params, Smi, NumOpt)                                               \
-  V(num_max_params, Smi, MaxParams)                                            \
-  V(parameter_names, Array, ParameterNames)
+  V(current_num_processed, Smi, CurrentNumProcessed)                           \
+  V(current_param_index, Smi, CurrentParamIndex)
 
 #define DEFINE_FIELD(Name, _, __) LocalVariable* Name = nullptr;
     FOR_EACH_DYNAMIC_CLOSURE_CALL_VARIABLE(DEFINE_FIELD)
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index e3dfb07..1ff4b49 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -1203,13 +1203,15 @@
     EXPECT_EQ(1, profile.sample_count());
     ProfileStackWalker walker(&profile);
 
-    EXPECT_STREQ("TypedData_Float32Array_new", walker.VMTagName());
+    EXPECT_STREQ("DRT_AllocateTypedData", walker.VMTagName());
     if (FLAG_enable_interpreter) {
       EXPECT_STREQ("[Bytecode] new Float32List", walker.CurrentName());
       EXPECT(walker.Down());
       EXPECT_STREQ("[Bytecode] foo", walker.CurrentName());
       EXPECT(!walker.Down());
     } else {
+      EXPECT_STREQ("[Stub] AllocateFloat32Array", walker.CurrentName());
+      EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] new Float32List", walker.CurrentName());
       EXPECT(walker.Down());
       EXPECT_STREQ("[Unoptimized] foo", walker.CurrentName());
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index d2e13d2..483ce9b 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -451,20 +451,18 @@
 
 class StackMapEntry : public ZoneAllocated {
  public:
-  StackMapEntry(Zone* zone, const CompressedStackMapsIterator& it)
+  StackMapEntry(Zone* zone, const CompressedStackMaps::Iterator& it)
       : maps_(CompressedStackMaps::Handle(zone, it.maps_.raw())),
         bits_container_(
             CompressedStackMaps::Handle(zone, it.bits_container_.raw())),
-        spill_slot_bit_count_(it.current_spill_slot_bit_count_),
-        non_spill_slot_bit_count_(it.current_non_spill_slot_bit_count_),
+        // If the map uses the global table, this accessor call ensures the
+        // entry is fully loaded before we retrieve [it.current_bits_offset_].
+        spill_slot_bit_count_(it.SpillSlotBitCount()),
+        non_spill_slot_bit_count_(it.Length() - it.SpillSlotBitCount()),
         bits_offset_(it.current_bits_offset_) {
     ASSERT(!maps_.IsNull() && !maps_.IsGlobalTable());
     ASSERT(!bits_container_.IsNull());
     ASSERT(!maps_.UsesGlobalTable() || bits_container_.IsGlobalTable());
-    // Check that the iterator was fully loaded when we ran the initializing
-    // expressions above. By this point we enter the body of the constructor,
-    // it's too late to run EnsureFullyLoadedEntry().
-    ASSERT(it.HasLoadedEntry());
     ASSERT(it.current_spill_slot_bit_count_ >= 0);
   }
 
@@ -475,8 +473,13 @@
     uint32_t hash = 0;
     hash = CombineHashes(hash, spill_slot_bit_count_);
     hash = CombineHashes(hash, non_spill_slot_bit_count_);
-    for (intptr_t i = 0; i < PayloadLength(); i++) {
-      hash = CombineHashes(hash, PayloadByte(i));
+    {
+      NoSafepointScope scope;
+      auto const start = PayloadData();
+      auto const end = start + PayloadLength();
+      for (auto cursor = start; cursor < end; cursor++) {
+        hash = CombineHashes(hash, *cursor);
+      }
     }
     hash_ = FinalizeHash(hash, kHashBits);
     return hash_;
@@ -490,20 +493,19 @@
     // Since we ensure that bits in the payload that are not part of the
     // actual stackmap data are cleared, we can just compare payloads by byte
     // instead of calling IsObject for each bit.
-    for (intptr_t i = 0; i < PayloadLength(); i++) {
-      if (PayloadByte(i) != other->PayloadByte(i)) return false;
-    }
-    return true;
+    NoSafepointScope scope;
+    return memcmp(PayloadData(), other->PayloadData(), PayloadLength()) == 0;
   }
 
   // Encodes this StackMapEntry to the given array of bytes and returns the
   // initial offset of the entry in the array.
-  intptr_t EncodeTo(GrowableArray<uint8_t>* array) {
-    auto const current_offset = array->length();
-    CompressedStackMapsBuilder::EncodeLEB128(array, spill_slot_bit_count_);
-    CompressedStackMapsBuilder::EncodeLEB128(array, non_spill_slot_bit_count_);
-    for (intptr_t i = 0; i < PayloadLength(); i++) {
-      array->Add(PayloadByte(i));
+  intptr_t EncodeTo(NonStreamingWriteStream* stream) {
+    auto const current_offset = stream->Position();
+    stream->WriteLEB128(spill_slot_bit_count_);
+    stream->WriteLEB128(non_spill_slot_bit_count_);
+    {
+      NoSafepointScope scope;
+      stream->WriteBytes(PayloadData(), PayloadLength());
     }
     return current_offset;
   }
@@ -518,8 +520,9 @@
   intptr_t PayloadLength() const {
     return Utils::RoundUp(Length(), kBitsPerByte) >> kBitsPerByteLog2;
   }
-  intptr_t PayloadByte(intptr_t offset) const {
-    return bits_container_.PayloadByte(bits_offset_ + offset);
+  const uint8_t* PayloadData() const {
+    ASSERT(!Thread::Current()->IsAtSafepoint());
+    return bits_container_.raw()->ptr()->data() + bits_offset_;
   }
 
   const CompressedStackMaps& maps_;
@@ -577,9 +580,9 @@
 
     void VisitCode(const Code& code) {
       compressed_stackmaps_ = code.compressed_stackmaps();
-      CompressedStackMapsIterator it(compressed_stackmaps_, old_global_table_);
+      CompressedStackMaps::Iterator it(compressed_stackmaps_,
+                                       old_global_table_);
       while (it.MoveNext()) {
-        it.EnsureFullyLoadedEntry();
         auto const entry = new (zone_) StackMapEntry(zone_, it);
         auto const index = entry_indices_.LookupValue(entry);
         if (index < 0) {
@@ -598,7 +601,9 @@
     CompressedStackMapsPtr CreateGlobalTable(
         StackMapEntryIntMap* entry_offsets) {
       ASSERT(entry_offsets->IsEmpty());
-      if (collected_entries_.length() == 0) return CompressedStackMaps::null();
+      if (collected_entries_.length() == 0) {
+        return CompressedStackMaps::null();
+      }
       // First, sort the entries from most used to least used. This way,
       // the most often used CSMs will have the lowest offsets, which means
       // they will be smaller when LEB128 encoded.
@@ -606,16 +611,17 @@
           [](StackMapEntry* const* e1, StackMapEntry* const* e2) {
             return static_cast<int>((*e2)->UsageCount() - (*e1)->UsageCount());
           });
-      GrowableArray<uint8_t> bytes;
+      MallocWriteStream stream(128);
       // Encode the entries and record their offset in the payload. Sorting the
       // entries may have changed their indices, so update those as well.
       for (intptr_t i = 0, n = collected_entries_.length(); i < n; i++) {
         auto const entry = collected_entries_.At(i);
         entry_indices_.Update({entry, i});
-        entry_offsets->Insert({entry, entry->EncodeTo(&bytes)});
+        entry_offsets->Insert({entry, entry->EncodeTo(&stream)});
       }
       const auto& data = CompressedStackMaps::Handle(
-          zone_, CompressedStackMaps::NewGlobalTable(bytes));
+          zone_, CompressedStackMaps::NewGlobalTable(stream.buffer(),
+                                                     stream.bytes_written()));
       return data.raw();
     }
 
@@ -690,19 +696,23 @@
    private:
     // Creates a normalized CSM from the given non-normalized CSM.
     CompressedStackMapsPtr NormalizeEntries(const CompressedStackMaps& maps) {
-      GrowableArray<uint8_t> new_payload;
-      CompressedStackMapsIterator it(maps, old_global_table_);
+      if (maps.payload_size() == 0) {
+        // No entries, so use the canonical empty map.
+        return Object::empty_compressed_stackmaps().raw();
+      }
+      MallocWriteStream new_payload(maps.payload_size());
+      CompressedStackMaps::Iterator it(maps, old_global_table_);
       intptr_t last_offset = 0;
       while (it.MoveNext()) {
-        it.EnsureFullyLoadedEntry();
         StackMapEntry entry(zone_, it);
-        auto const entry_offset = entry_offsets_.LookupValue(&entry);
-        auto const pc_delta = it.pc_offset() - last_offset;
-        CompressedStackMapsBuilder::EncodeLEB128(&new_payload, pc_delta);
-        CompressedStackMapsBuilder::EncodeLEB128(&new_payload, entry_offset);
+        const intptr_t entry_offset = entry_offsets_.LookupValue(&entry);
+        const intptr_t pc_delta = it.pc_offset() - last_offset;
+        new_payload.WriteLEB128(pc_delta);
+        new_payload.WriteLEB128(entry_offset);
         last_offset = it.pc_offset();
       }
-      return CompressedStackMaps::NewUsingTable(new_payload);
+      return CompressedStackMaps::NewUsingTable(new_payload.buffer(),
+                                                new_payload.bytes_written());
     }
 
     const CompressedStackMaps& old_global_table_;
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 9797fc2..3dfd910 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -516,7 +516,6 @@
 REGULAR_VISITOR(SignatureData)
 REGULAR_VISITOR(RedirectionData)
 REGULAR_VISITOR(FfiTrampolineData)
-REGULAR_VISITOR(Field)
 REGULAR_VISITOR(Script)
 REGULAR_VISITOR(Library)
 REGULAR_VISITOR(LibraryPrefix)
@@ -592,6 +591,26 @@
 REGULAR_VISITOR(WeakSerializationReference)
 #endif
 
+intptr_t FieldLayout::VisitFieldPointers(FieldPtr raw_obj,
+                                         ObjectPointerVisitor* visitor) {
+  ASSERT(raw_obj->IsHeapObject());
+  ASSERT_UNCOMPRESSED(Field);
+  visitor->VisitPointers(raw_obj->ptr()->from(), raw_obj->ptr()->to());
+
+  if (visitor->trace_values_through_fields()) {
+    if (Field::StaticBit::decode(raw_obj->ptr()->kind_bits_)) {
+      visitor->isolate_group()->ForEachIsolate(
+          [&](Isolate* isolate) {
+            intptr_t index =
+                Smi::Value(raw_obj->ptr()->host_offset_or_field_id_);
+            visitor->VisitPointer(&isolate->field_table()->table()[index]);
+          },
+          /*at_safepoint=*/true);
+    }
+  }
+  return Field::InstanceSize();
+}
+
 bool CodeLayout::ContainsPC(const ObjectPtr raw_obj, uword pc) {
   if (!raw_obj->IsCode()) return false;
   auto const raw_code = static_cast<const CodePtr>(raw_obj);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 39e0254..498fd5d 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -23,6 +23,17 @@
 #include "vm/token.h"
 #include "vm/token_position.h"
 
+// Currently we have two different axes for offset generation:
+//
+//  * Target architecture
+//  * DART_PRECOMPILED_RUNTIME (i.e, AOT vs. JIT)
+//
+// That is, fields in ObjectLayout and its subclasses should only be included or
+// excluded conditionally based on these factors. Otherwise, the generated
+// offsets can be wrong (which should be caught by offset checking in dart.cc).
+//
+// TODO(dartbug.com/43646): Add DART_PRECOMPILER as another axis.
+
 namespace dart {
 
 // For now there are no compressed pointers.
@@ -751,6 +762,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&allocation_stub_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
         return reinterpret_cast<ObjectPtr*>(&direct_subclasses_);
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&dependent_code_);
@@ -825,6 +837,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&script_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&library_kernel_data_);
       case Snapshot::kMessage:
@@ -1015,6 +1028,7 @@
     switch (kind) {
       case Snapshot::kFullAOT:
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&data_);
       case Snapshot::kMessage:
@@ -1183,6 +1197,7 @@
   ObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&initializer_function_);
@@ -1259,6 +1274,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&url_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&kernel_program_info_);
       case Snapshot::kMessage:
@@ -1332,6 +1348,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&exports_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&kernel_data_);
       case Snapshot::kMessage:
@@ -1619,17 +1636,29 @@
   friend class BlobImageWriter;
 };
 
-// Used only to provide memory accounting for the bare instruction payloads
-// we serialize, since they are no longer part of RawInstructions objects.
+// Used to carry extra information to the VM without changing the embedder
+// interface, to provide memory accounting for the bare instruction payloads
+// we serialize, since they are no longer part of RawInstructions objects,
+// and to avoid special casing bare instructions payload Images in the GC.
 class InstructionsSectionLayout : public ObjectLayout {
   RAW_HEAP_OBJECT_IMPLEMENTATION(InstructionsSection);
   VISIT_NOTHING();
 
   // Instructions section payload length in bytes.
   uword payload_length_;
+  // The offset of the corresponding BSS section from this text section.
+  word bss_offset_;
+  // The relocated address of this text section in the shared object. Properly
+  // filled for ELF snapshots, always 0 in assembly snapshots. (For the latter,
+  // we instead get the value during BSS initialization and store it there.)
+  uword instructions_relocated_address_;
+  // The offset of the GNU build ID note section from this text section.
+  word build_id_offset_;
 
   // Variable length data follows here.
   uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+  friend class Image;
 };
 
 class PcDescriptorsLayout : public ObjectLayout {
@@ -1818,7 +1847,9 @@
                                     sizeof(flags_and_size_) * kBitsPerByte -
                                         UsesTableBit::kNextBit> {};
 
+  friend class Object;
   friend class ImageWriter;
+  friend class StackMapEntry;
 };
 
 class LocalVarDescriptorsLayout : public ObjectLayout {
@@ -2044,6 +2075,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&entries_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return to();
       case Snapshot::kMessage:
@@ -2151,6 +2183,7 @@
       case Snapshot::kFullAOT:
         return reinterpret_cast<ObjectPtr*>(&imports_);
       case Snapshot::kFull:
+      case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
         return reinterpret_cast<ObjectPtr*>(&importer_);
       case Snapshot::kMessage:
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 2ef43f3..2f36c97 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -110,7 +110,7 @@
   type.SetTypeTestingStub(code);
 
   if (is_canonical) {
-    type ^= type.Canonicalize();
+    type ^= type.Canonicalize(Thread::Current(), nullptr);
   }
 
   return type.raw();
@@ -262,7 +262,7 @@
   type_parameter.SetTypeTestingStub(code);
 
   if (is_canonical) {
-    type_parameter ^= type_parameter.Canonicalize();
+    type_parameter ^= type_parameter.Canonicalize(Thread::Current(), nullptr);
   }
 
   return type_parameter.raw();
@@ -333,7 +333,7 @@
 
   // Set the canonical bit.
   if (is_canonical) {
-    type_arguments = type_arguments.Canonicalize();
+    type_arguments = type_arguments.Canonicalize(Thread::Current(), nullptr);
   }
 
   return type_arguments.raw();
@@ -399,8 +399,8 @@
   // Check if closure is serializable, throw an exception otherwise.
   FunctionPtr func = writer->IsSerializableClosure(ClosurePtr(this));
   if (func != Function::null()) {
-    writer->WriteStaticImplicitClosure(object_id, func,
-                                       writer->GetObjectTags(this));
+    writer->WriteStaticImplicitClosure(
+        object_id, func, writer->GetObjectTags(this), delayed_type_arguments_);
     return;
   }
 
@@ -717,11 +717,7 @@
   Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
   obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew);
   if (ObjectLayout::IsCanonical(tags)) {
-    const char* error_str = NULL;
-    obj = obj.CheckAndCanonicalize(reader->thread(), &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
+    obj = obj.Canonicalize(reader->thread());
   }
   reader->AddBackRef(object_id, &obj, kIsDeserialized);
 
@@ -1041,11 +1037,7 @@
     // Read all the individual elements for inlined objects.
     reader->ArrayReadFrom(object_id, *array, len, tags);
     if (ObjectLayout::IsCanonical(tags)) {
-      const char* error_str = NULL;
-      *array ^= array->CheckAndCanonicalize(reader->thread(), &error_str);
-      if (error_str != NULL) {
-        FATAL1("Failed to canonicalize: %s", error_str);
-      }
+      *array ^= array->Canonicalize(reader->thread());
     }
   }
   return raw(*array);
@@ -1354,11 +1346,7 @@
   // When reading a script snapshot or a message snapshot we always have
   // to canonicalize the object.
   if (ObjectLayout::IsCanonical(tags)) {
-    const char* error_str = NULL;
-    result ^= result.CheckAndCanonicalize(reader->thread(), &error_str);
-    if (error_str != NULL) {
-      FATAL1("Failed to canonicalize: %s", error_str);
-    }
+    result ^= result.Canonicalize(reader->thread());
     ASSERT(!result.IsNull());
     ASSERT(result.IsCanonical());
   }
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index a7e2ff3..6db75e3 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -452,6 +452,9 @@
 
     RegExpEngine::CompilationResult result = RegExpEngine::CompileBytecode(
         compile_data, regexp, is_one_byte, sticky, zone);
+    if (result.error_message != nullptr) {
+      Exceptions::ThrowUnsupportedError(result.error_message);
+    }
     ASSERT(result.bytecode != NULL);
     ASSERT(regexp.num_registers(is_one_byte) == -1 ||
            regexp.num_registers(is_one_byte) == result.num_registers);
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1d18cae..685c039 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -303,6 +303,32 @@
   array.SetTypeArguments(element_type);  // May be null.
 }
 
+// Allocate typed data array of given class id and length.
+// Arg0: class id.
+// Arg1: number of elements.
+// Return value: newly allocated typed data array.
+DEFINE_RUNTIME_ENTRY(AllocateTypedData, 2) {
+  const intptr_t cid = Smi::CheckedHandle(zone, arguments.ArgAt(0)).Value();
+  const auto& length = Instance::CheckedHandle(zone, arguments.ArgAt(1));
+  if (!length.IsInteger()) {
+    const Array& args = Array::Handle(zone, Array::New(1));
+    args.SetAt(0, length);
+    Exceptions::ThrowByType(Exceptions::kArgument, args);
+  }
+  const int64_t len = Integer::Cast(length).AsInt64Value();
+  const intptr_t max = TypedData::MaxElements(cid);
+  if (len < 0) {
+    Exceptions::ThrowRangeError("length", Integer::Cast(length), 0, max);
+  } else if (len > max) {
+    const Instance& exception = Instance::Handle(
+        zone, thread->isolate()->object_store()->out_of_memory());
+    Exceptions::Throw(thread, exception);
+  }
+  const auto& typed_data =
+      TypedData::Handle(zone, TypedData::New(cid, static_cast<intptr_t>(len)));
+  arguments.SetReturn(typed_data);
+}
+
 // Helper returning the token position of the Dart caller.
 static TokenPosition GetCallerLocation() {
   DartFrameIterator iterator(Thread::Current(),
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 129dae3..5fd14b5 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -57,12 +57,12 @@
     // call.
     // This sequence may occur in an intrinsic, so don't use registers an
     // intrinsic must preserve.
-    COMPILE_ASSERT(R23 != CODE_REG);
-    COMPILE_ASSERT(R25 != CODE_REG);
-    COMPILE_ASSERT(R23 != ARGS_DESC_REG);
-    COMPILE_ASSERT(R25 != ARGS_DESC_REG);
-    __ mov(R23, CSP);
-    __ mov(R25, SP);
+    COMPILE_ASSERT(kCallLeafRuntimeCalleeSaveScratch1 != CODE_REG);
+    COMPILE_ASSERT(kCallLeafRuntimeCalleeSaveScratch2 != CODE_REG);
+    COMPILE_ASSERT(kCallLeafRuntimeCalleeSaveScratch1 != ARGS_DESC_REG);
+    COMPILE_ASSERT(kCallLeafRuntimeCalleeSaveScratch2 != ARGS_DESC_REG);
+    __ mov(kCallLeafRuntimeCalleeSaveScratch1, CSP);
+    __ mov(kCallLeafRuntimeCalleeSaveScratch2, SP);
     __ ReserveAlignedFrameSpace(0);
     __ mov(CSP, SP);
     __ ldr(TMP,
@@ -71,8 +71,8 @@
     __ blr(TMP);
     __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
     __ str(TMP, compiler::Address(THR, Thread::vm_tag_offset()));
-    __ mov(SP, R25);
-    __ mov(CSP, R23);
+    __ mov(SP, kCallLeafRuntimeCalleeSaveScratch2);
+    __ mov(CSP, kCallLeafRuntimeCalleeSaveScratch1);
     ASSERT((kAbiPreservedCpuRegs & (1 << THR)) != 0);
     ASSERT((kAbiPreservedCpuRegs & (1 << PP)) != 0);
   } else {
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index c514b573..394c01d 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -9,6 +9,7 @@
 
 #define RUNTIME_ENTRY_LIST(V)                                                  \
   V(AllocateArray)                                                             \
+  V(AllocateTypedData)                                                         \
   V(AllocateContext)                                                           \
   V(AllocateObject)                                                            \
   V(AllocateSubtypeTestCache)                                                  \
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index a9761d7..b003324 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -91,7 +91,7 @@
         is_invisible_(false),
         is_captured_parameter_(false),
         is_forced_stack_(false),
-        is_explicit_covariant_parameter_(false),
+        covariance_mode_(kNotCovariant),
         is_late_(false),
         is_chained_future_(false),
         expected_context_index_(-1),
@@ -147,10 +147,17 @@
   }
 
   bool is_explicit_covariant_parameter() const {
-    return is_explicit_covariant_parameter_;
+    return covariance_mode_ == kExplicit;
   }
-  void set_is_explicit_covariant_parameter() {
-    is_explicit_covariant_parameter_ = true;
+  void set_is_explicit_covariant_parameter() { covariance_mode_ = kExplicit; }
+
+  bool needs_covariant_check_in_method() const {
+    return covariance_mode_ != kNotCovariant;
+  }
+  void set_needs_covariant_check_in_method() {
+    if (covariance_mode_ == kNotCovariant) {
+      covariance_mode_ = kImplicit;
+    }
   }
 
   enum TypeCheckMode {
@@ -208,6 +215,12 @@
   bool Equals(const LocalVariable& other) const;
 
  private:
+  enum CovarianceMode {
+    kNotCovariant,
+    kImplicit,
+    kExplicit,
+  };
+
   static const int kUninitializedIndex = INT_MIN;
 
   const TokenPosition declaration_pos_;
@@ -228,7 +241,7 @@
   bool is_invisible_;
   bool is_captured_parameter_;
   bool is_forced_stack_;
-  bool is_explicit_covariant_parameter_;
+  CovarianceMode covariance_mode_;
   bool is_late_;
   bool is_chained_future_;
   intptr_t expected_context_index_;
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e20e9a9..820e53f 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -13,6 +13,7 @@
 
 #include "platform/unicode.h"
 #include "vm/base64.h"
+#include "vm/canonical_tables.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/cpu.h"
 #include "vm/dart_api_impl.h"
@@ -45,7 +46,6 @@
 #include "vm/stack_frame.h"
 #include "vm/symbols.h"
 #include "vm/timeline.h"
-#include "vm/type_table.h"
 #include "vm/version.h"
 
 namespace dart {
@@ -986,7 +986,6 @@
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   ASSERT(isolate != NULL);
-  ASSERT(!Isolate::IsSystemIsolate(isolate));
 
   if (FLAG_trace_service) {
     OS::PrintErr(
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index a3cf970..bf1d99b 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 39
+#define SERVICE_PROTOCOL_MINOR_VERSION 40
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 69dde47..b8d0906 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.39
+# Dart VM Service Protocol 3.40
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.39_ of the Dart VM Service Protocol. This
+This document describes of _version 3.40_ 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.
@@ -102,6 +102,7 @@
   - [Instance](#instance)
   - [InstanceSet](#instanceset)
   - [Isolate](#isolate)
+  - [IsolateFlag](#isolateflag)
   - [IsolateGroup](#isolategroup)
   - [Library](#library)
   - [LibraryDependency](#librarydependency)
@@ -2785,6 +2786,10 @@
   // internal use. If `false`, this isolate is likely running user code.
   bool isSystemIsolate;
 
+  // The list of isolate flags provided to this isolate. See Dart_IsolateFlags
+  // in dart_api.h for the list of accepted isolate flags.
+  IsolateFlag[] isolateFlags;
+
   // The time that the VM started in milliseconds since the epoch.
   //
   // Suitable to pass to DateTime.fromMillisecondsSinceEpoch.
@@ -2830,6 +2835,20 @@
 
 An _Isolate_ object provides information about one isolate in the VM.
 
+### IsolateFlag
+
+```
+class IsolateFlag {
+  // The name of the flag.
+  string name;
+
+  // The value of this flag as a string.
+  string valueAsString;
+}
+```
+
+Represents the value of a single isolate flag. See [Isolate](#isolate).
+
 ### IsolateGroup
 
 ```
@@ -2845,7 +2864,7 @@
 
   // Specifies whether the isolate group was spawned by the VM or embedder for
   // internal use. If `false`, this isolate group is likely running user code.
-  bool isSystemIsolateGroup;  
+  bool isSystemIsolateGroup;
 }
 ```
 
@@ -2865,7 +2884,7 @@
 
   // Specifies whether the isolate group was spawned by the VM or embedder for
   // internal use. If `false`, this isolate group is likely running user code.
-  bool isSystemIsolateGroup;  
+  bool isSystemIsolateGroup;
 
   // A list of all isolates in this isolate group.
   @Isolate[] isolates;
@@ -3835,5 +3854,6 @@
 3.37 | Added `getWebSocketTarget` RPC and `WebSocketTarget` object.
 3.38 | Added `isSystemIsolate` property to `@Isolate` and `Isolate`, `isSystemIsolateGroup` property to `@IsolateGroup` and `IsolateGroup`, and properties `systemIsolates` and `systemIsolateGroups` to `VM`.
 3.39 | Removed the following deprecated RPCs and objects: `getClientName`, `getWebSocketTarget`, `setClientName`, `requireResumeApproval`, `ClientName`, and `WebSocketTarget`.
+3.40 | Added `IsolateFlag` object and `isolateFlags` property to `Isolate`.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_extension.md b/runtime/vm/service/service_extension.md
index 64de58a..5cb05ff 100644
--- a/runtime/vm/service/service_extension.md
+++ b/runtime/vm/service/service_extension.md
@@ -1,4 +1,4 @@
-# Dart VM Service Protocol Extension 1.1
+# Dart VM Service Protocol Extension 1.4
 
 This protocol describes service extensions that are made available through
 the Dart core libraries, but are not part of the core
@@ -10,7 +10,7 @@
 
 ## dart:io Extensions
 
-This section describes _version 1.1_ of the dart:io service protocol extensions.
+This section describes _version 1.4_ of the dart:io service protocol extensions.
 
 ### getVersion
 
@@ -52,6 +52,50 @@
 
 See [Success](#success).
 
+### getOpenFileById
+
+```
+OpenFile getOpenFileById(string isolateId, int id);
+```
+
+The _getOpenFileById_ RPC is used to retrieve information about files currently
+opened by `dart:io` from a given isolate.
+
+See [getOpenFiles](#getopenfiles) and [File](#file).
+
+### getOpenFiles
+
+```
+FileList getOpenFiles(string isolateId);
+```
+
+The _getOpenFiles_ RPC is used to retrieve the list of files currently opened
+files by `dart:io` from a given isolate.
+
+See [FileList](#filelist) and [File](#file).
+
+### getSpawnedProcessById
+
+```
+SpawnedProcess getSpawnedProcessById(string isolateId, int id);
+```
+
+The _getSpawnedProcessById_ RPC is used to retrieve information about a process spawned
+by `dart:io` from a given isolate.
+
+See [getSpawnedProcesses](#getspawnedprocesses) and [SpawnedProcess](#spawnedprocess).
+
+### getSpawnedProcesses
+
+```
+SpawnedProcessList getSpawnedProcesses(string isolateId);
+```
+
+The _getSpawnedProcesses_ RPC is used to retrieve the list of processed opened by
+`dart:io` from a given isolate.
+
+See [SpawnedProcessList](#spawnedprocesslist) and [SpawnedProcess](#spawnedprocess).
+
 ### getSocketProfile
 
 ```
@@ -64,6 +108,7 @@
 ### getHttpEnableTimelineLogging
 
 ```
+@Deprecated
 HttpTimelineLoggingState getHttpEnableTimelineLogging(string isolateId)
 ```
 
@@ -76,6 +121,7 @@
 ### setHttpEnableTimelineLogging
 
 ```
+@Deprecated
 Success setHttpEnableTimelineLogging(string isolateId, bool enable)
 ```
 
@@ -86,8 +132,126 @@
 
 See [Success](#success).
 
+### httpEnableTimelineLogging
+
+```
+HttpTimelineLoggingState httpEnableTimelineLogging(string isolateId, bool enabled [optional])
+```
+
+The _httpEnableTimelineLogging_ RPC is used to set and inspect the value of
+`HttpClient.enableTimelineLogging`, which determines if HTTP client requests
+should be logged to the timeline. If `enabled` is provided, the state of
+`HttpClient.enableTimelineLogging` will be updated to the value of `enabled`.
+
+If the value of `HttpClient.enableTimelineLogging` is changed, a
+`HttpTimelineLoggingStateChange` event will be sent on the `Extension` stream.
+
+See [HttpTimelineLoggingState](#httptimelineloggingstate).
+
 ## Public Types
 
+### File
+
+```
+class @OpenFile extends Response {
+  // The unique ID associated with this file.
+  int id;
+
+  // The path of the file.
+  string name;
+}
+```
+
+_@File_ is a reference to a _File_.
+
+```
+class OpenFile extends Response {
+  // The unique ID associated with this file.
+  int id;
+
+  // The path of the file.
+  string name;
+
+  // The total number of bytes read from this file.
+  int readBytes;
+
+  // The total number of bytes written to this file.
+  int writeBytes;
+
+  // The number of reads made from this file.
+  int readCount;
+
+  // The number of writes made to this file.
+  int writeCount;
+
+  // The time at which this file was last read by this process in milliseconds
+  // since epoch.
+  int lastReadTime;
+
+  // The time at which this file was last written to by this process in
+  // milliseconds since epoch.
+  int lastWriteTime;
+}
+```
+
+A _OpenFile_ contains information about reads and writes to a currently opened file.
+
+### OpenFileList
+
+```
+class OpenFileList extends Response {
+  // A list of all files opened through dart:io.
+  @OpenFile[] files;
+}
+```
+
+### SpawnedProcess
+
+```
+class @SpawnedProcess {
+  // The unique ID associated with this process.
+  int id;
+
+  // The name of the executable.
+  string name;
+}
+```
+
+_@SpawnedProcess_ is a reference to a _SpawnedProcess_.
+
+```
+class SpawnedProcess extends Response {
+  // The unique ID associated with this process.
+  int id;
+
+  // The name of the executable.
+  string name;
+
+  // The process ID associated with the process.
+  int pid;
+
+  // The time the process was started in milliseconds since epoch.
+  int startedAt;
+
+  // The list of arguments provided to the process at launch.
+  string[] arguments;
+
+  // The working directory of the process at launch.
+  string workingDirectory;
+}
+```
+
+A _Process_ contains startup information of a spawned process.
+
+### SpawnedProcessList
+
+```
+class SpawnedProcessList extends Response {
+  // A list of processes spawned through dart:io on a given isolate.
+  @SpawnedProcess[] processes;
+}
+```
+
 ### Response
 
 ```
@@ -178,3 +342,6 @@
 ------- | --------
 1.0 | Initial revision.
 1.1 | Added `lastReadTime` and `lastWriteTime` properties to `SocketStatistic`.
+1.2 | Added `getOpenFiles`, `getOpenFileById`, `getSpawnedProcesses`, and `getSpawnedProcessById` RPCs and added `OpenFile` and `SpawnedProcess` objects.
+1.3 | Added `httpEnableTimelineLogging` RPC and `HttpTimelineLoggingStateChange` event, deprecated `getHttpEnableTimelineLogging` and `setHttpEnableTimelineLogging`.
+1.4 | Updated `httpEnableTimelineLogging` parameter `enable` to `enabled`. `enable` will continue to be accepted.
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index dc77907..5c0d911 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -229,6 +229,8 @@
   switch (kind) {
     case kFull:
       return "full";
+    case kFullCore:
+      return "full-core";
     case kFullJIT:
       return "full-jit";
     case kFullAOT:
@@ -458,11 +460,25 @@
   if (func.IsNull()) {
     SetReadException("Invalid function object found in message.");
   }
+  TypeArguments& delayed_type_arguments = TypeArguments::Handle(zone());
+  delayed_type_arguments ^= ReadObjectImpl(kAsInlinedObject);
+
   func = func.ImplicitClosureFunction();
   ASSERT(!func.IsNull());
 
-  // Return the associated implicit static closure.
-  obj = func.ImplicitStaticClosure();
+  // If delayedtype arguments were provided, create and return new closure with
+  // those, otherwise return associated implicit static closure.
+  // Note that static closures can't have instantiator or function types since
+  // statics can't refer to class type arguments, don't have outer functions.
+  if (!delayed_type_arguments.IsNull()) {
+    const Context& context = Context::Handle(zone());
+    obj = Closure::New(
+        /*instantiator_type_arguments=*/Object::null_type_arguments(),
+        /*function_type_arguments=*/Object::null_type_arguments(),
+        delayed_type_arguments, func, context, Heap::kOld);
+  } else {
+    obj = func.ImplicitStaticClosure();
+  }
   return obj.raw();
 }
 
@@ -662,11 +678,7 @@
       offset += kWordSize;
     }
     if (ObjectLayout::IsCanonical(tags)) {
-      const char* error_str = NULL;
-      *result = result->CheckAndCanonicalize(thread(), &error_str);
-      if (error_str != NULL) {
-        FATAL1("Failed to canonicalize %s\n", error_str);
-      }
+      *result = result->Canonicalize(thread());
       ASSERT(!result->IsNull());
     }
   }
@@ -893,12 +905,10 @@
 
 SnapshotWriter::SnapshotWriter(Thread* thread,
                                Snapshot::Kind kind,
-                               ReAlloc alloc,
-                               DeAlloc dealloc,
                                intptr_t initial_size,
                                ForwardList* forward_list,
                                bool can_send_any_object)
-    : BaseWriter(alloc, dealloc, initial_size),
+    : BaseWriter(initial_size),
       thread_(thread),
       kind_(kind),
       object_store_(isolate()->object_store()),
@@ -1313,9 +1323,11 @@
   WriteObjectImpl(cls->name_, kAsInlinedObject);
 }
 
-void SnapshotWriter::WriteStaticImplicitClosure(intptr_t object_id,
-                                                FunctionPtr func,
-                                                intptr_t tags) {
+void SnapshotWriter::WriteStaticImplicitClosure(
+    intptr_t object_id,
+    FunctionPtr func,
+    intptr_t tags,
+    TypeArgumentsPtr delayed_type_arguments) {
   // Write out the serialization header value for this object.
   WriteInlinedObjectHeader(object_id);
 
@@ -1333,6 +1345,7 @@
   WriteObjectImpl(library->ptr()->url_, kAsInlinedObject);
   WriteObjectImpl(cls->ptr()->name_, kAsInlinedObject);
   WriteObjectImpl(func->ptr()->name_, kAsInlinedObject);
+  WriteObjectImpl(delayed_type_arguments, kAsInlinedObject);
 }
 
 void SnapshotWriter::ArrayWriteTo(intptr_t object_id,
@@ -1559,22 +1572,9 @@
   }
 }
 
-static uint8_t* malloc_allocator(uint8_t* ptr,
-                                 intptr_t old_size,
-                                 intptr_t new_size) {
-  void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
-  return reinterpret_cast<uint8_t*>(new_ptr);
-}
-
-static void malloc_deallocator(uint8_t* ptr) {
-  free(reinterpret_cast<void*>(ptr));
-}
-
 MessageWriter::MessageWriter(bool can_send_any_object)
     : SnapshotWriter(Thread::Current(),
                      Snapshot::kMessage,
-                     malloc_allocator,
-                     malloc_deallocator,
                      kInitialSize,
                      &forward_list_,
                      can_send_any_object),
@@ -1612,9 +1612,10 @@
   }
 
   MessageFinalizableData* finalizable_data = finalizable_data_;
-  finalizable_data_ = NULL;
-  return Message::New(dest_port, buffer(), BytesWritten(), finalizable_data,
-                      priority);
+  finalizable_data_ = nullptr;
+  intptr_t size;
+  uint8_t* buffer = Steal(&size);
+  return Message::New(dest_port, buffer, size, finalizable_data, priority);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index db0775c..94aa3e7 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -91,11 +91,12 @@
 class Snapshot {
  public:
   enum Kind {
-    kFull,     // Full snapshot of core libraries or an application.
-    kFullJIT,  // Full + JIT code
-    kFullAOT,  // Full + AOT code
-    kMessage,  // A partial snapshot used only for isolate messaging.
-    kNone,     // gen_snapshot
+    kFull,      // Full snapshot of an application.
+    kFullCore,  // Full snapshot of core libraries. Agnostic to null safety.
+    kFullJIT,   // Full + JIT code
+    kFullAOT,   // Full + AOT code
+    kMessage,   // A partial snapshot used only for isolate messaging.
+    kNone,      // gen_snapshot
     kInvalid
   };
   static const char* KindToCString(Kind kind);
@@ -130,13 +131,15 @@
   void set_kind(Kind value) { return Write<int64_t>(kKindOffset, value); }
 
   static bool IsFull(Kind kind) {
-    return (kind == kFull) || (kind == kFullJIT) || (kind == kFullAOT);
+    return (kind == kFull) || (kind == kFullCore) || (kind == kFullJIT) ||
+           (kind == kFullAOT);
   }
+  static bool IsAgnosticToNullSafety(Kind kind) { return (kind == kFullCore); }
   static bool IncludesCode(Kind kind) {
     return (kind == kFullJIT) || (kind == kFullAOT);
   }
   static bool IncludesBytecode(Kind kind) {
-    return (kind == kFull) || (kind == kFullJIT);
+    return (kind == kFull) || (kind == kFullCore) || (kind == kFullJIT);
   }
 
   const uint8_t* Addr() const { return reinterpret_cast<const uint8_t*>(this); }
@@ -171,7 +174,8 @@
 inline static bool IsSnapshotCompatible(Snapshot::Kind vm_kind,
                                         Snapshot::Kind isolate_kind) {
   if (vm_kind == isolate_kind) return true;
-  if (vm_kind == Snapshot::kFull && isolate_kind == Snapshot::kFullJIT)
+  if (((vm_kind == Snapshot::kFull) || (vm_kind == Snapshot::kFullCore)) &&
+      isolate_kind == Snapshot::kFullJIT)
     return true;
   return Snapshot::IsFull(isolate_kind);
 }
@@ -429,14 +433,14 @@
 
 class BaseWriter : public StackResource {
  public:
-  uint8_t* buffer() { return stream_.buffer(); }
+  uint8_t* Steal(intptr_t* length) { return stream_.Steal(length); }
   intptr_t BytesWritten() const { return stream_.bytes_written(); }
 
   // Writes raw data to the stream (basic type).
   // sizeof(T) must be in {1,2,4,8}.
   template <typename T>
   void Write(T value) {
-    WriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
+    MallocWriteStream::Raw<sizeof(T), T>::Write(&stream_, value);
   }
 
   void WriteClassIDValue(classid_t value) { Write<uint32_t>(value); }
@@ -491,13 +495,8 @@
   }
 
  protected:
-  BaseWriter(ReAlloc alloc, DeAlloc dealloc, intptr_t initial_size)
-      : StackResource(Thread::Current()),
-        buffer_(NULL),
-        stream_(&buffer_, alloc, initial_size),
-        dealloc_(dealloc) {
-    ASSERT(alloc != NULL);
-  }
+  explicit BaseWriter(intptr_t initial_size)
+      : StackResource(Thread::Current()), stream_(initial_size) {}
   ~BaseWriter() {}
 
   void ReserveHeader() {
@@ -506,21 +505,20 @@
   }
 
   void FillHeader(Snapshot::Kind kind) {
-    Snapshot* header = reinterpret_cast<Snapshot*>(stream_.buffer());
+    intptr_t length;
+    Snapshot* header = reinterpret_cast<Snapshot*>(Steal(&length));
     header->set_magic();
-    header->set_length(stream_.bytes_written());
+    header->set_length(length);
     header->set_kind(kind);
   }
 
   void FreeBuffer() {
-    dealloc_(stream_.buffer());
-    stream_.set_buffer(NULL);
+    intptr_t unused;
+    free(Steal(&unused));
   }
 
  private:
-  uint8_t* buffer_;
-  WriteStream stream_;
-  DeAlloc dealloc_;
+  MallocWriteStream stream_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(BaseWriter);
 };
@@ -586,8 +584,6 @@
  protected:
   SnapshotWriter(Thread* thread,
                  Snapshot::Kind kind,
-                 ReAlloc alloc,
-                 DeAlloc dealloc,
                  intptr_t initial_size,
                  ForwardList* forward_list,
                  bool can_send_any_object);
@@ -623,7 +619,8 @@
 
   void WriteStaticImplicitClosure(intptr_t object_id,
                                   FunctionPtr func,
-                                  intptr_t tags);
+                                  intptr_t tags,
+                                  TypeArgumentsPtr delayed_type_arguments);
 
  protected:
   bool CheckAndWritePredefinedObject(ObjectPtr raw);
@@ -668,7 +665,6 @@
 
   friend class ArrayLayout;
   friend class ClassLayout;
-  friend class ClosureDataLayout;
   friend class CodeLayout;
   friend class ContextScopeLayout;
   friend class DynamicLibraryLayout;
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index ed50a53..ed0383c 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -52,12 +52,6 @@
   return false;
 }
 
-static uint8_t* malloc_allocator(uint8_t* ptr,
-                                 intptr_t old_size,
-                                 intptr_t new_size) {
-  return reinterpret_cast<uint8_t*>(realloc(ptr, new_size));
-}
-
 // Compare two Dart_CObject object graphs rooted in first and
 // second. The second graph will be destroyed by this operation no matter
 // whether the graphs are equal or not.
@@ -755,10 +749,14 @@
     OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
 
     // Write snapshot with object content.
-    FullSnapshotWriter writer(Snapshot::kFull, NULL,
-                              &isolate_snapshot_data_buffer, &malloc_allocator,
-                              NULL, /*image_writer*/ nullptr);
+    MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
+    FullSnapshotWriter writer(
+        Snapshot::kFull, /*vm_snapshot_data=*/nullptr, &isolate_snapshot_data,
+        /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
     writer.WriteFullSnapshot();
+    // Take ownership so it doesn't get freed by the stream destructor.
+    intptr_t unused;
+    isolate_snapshot_data_buffer = isolate_snapshot_data.Steal(&unused);
   }
 
   // Now Create another isolate using the snapshot and execute a method
@@ -2019,8 +2017,6 @@
   // For performance, we'd like single-byte headers when ids are omitted.
   // If this starts failing, consider renumbering the snapshot ids.
   EXPECT_EQ(1, writer.BytesWritten());
-
-  free(writer.buffer());
 }
 
 TEST_CASE(IsKernelNegative) {
@@ -2075,12 +2071,12 @@
     // Verify that snapshot writing succeeds if erasure is not required.
     if (!required) {
       // Write snapshot with object content.
-      uint8_t* isolate_snapshot_data_buffer;
+      MallocWriteStream isolate_snapshot_data(FullSnapshotWriter::kInitialSize);
       FullSnapshotWriter writer(
-          Snapshot::kFull, NULL, &isolate_snapshot_data_buffer,
-          &malloc_allocator, NULL, /*image_writer*/ nullptr);
+          Snapshot::kFullCore, /*vm_snapshot_data=*/nullptr,
+          &isolate_snapshot_data,
+          /*vm_image_writer=*/nullptr, /*iso_image_writer=*/nullptr);
       writer.WriteFullSnapshot();
-      free(isolate_snapshot_data_buffer);
     }
   }
 }
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 9c14f6e..9df6e3c 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -284,7 +284,7 @@
     auto isolate = isolate_group()->isolates_.First();
 
     global_table = isolate->object_store()->canonicalized_stack_map_entries();
-    CompressedStackMapsIterator it(maps, global_table);
+    CompressedStackMaps::Iterator it(maps, global_table);
     const uword start = code.PayloadStart();
     const uint32_t pc_offset = pc() - start;
     if (it.Find(pc_offset)) {
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 1c9ff6c6..92d8c6c 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -260,6 +260,42 @@
   return stub.raw();
 }
 
+CodePtr StubCode::GetAllocationStubForTypedData(classid_t class_id) {
+  auto object_store = Thread::Current()->isolate()->object_store();
+  switch (class_id) {
+    case kTypedDataInt8ArrayCid:
+      return object_store->allocate_int8_array_stub();
+    case kTypedDataUint8ArrayCid:
+      return object_store->allocate_uint8_array_stub();
+    case kTypedDataUint8ClampedArrayCid:
+      return object_store->allocate_uint8_clamped_array_stub();
+    case kTypedDataInt16ArrayCid:
+      return object_store->allocate_int16_array_stub();
+    case kTypedDataUint16ArrayCid:
+      return object_store->allocate_uint16_array_stub();
+    case kTypedDataInt32ArrayCid:
+      return object_store->allocate_int32_array_stub();
+    case kTypedDataUint32ArrayCid:
+      return object_store->allocate_uint32_array_stub();
+    case kTypedDataInt64ArrayCid:
+      return object_store->allocate_int64_array_stub();
+    case kTypedDataUint64ArrayCid:
+      return object_store->allocate_uint64_array_stub();
+    case kTypedDataFloat32ArrayCid:
+      return object_store->allocate_float32_array_stub();
+    case kTypedDataFloat64ArrayCid:
+      return object_store->allocate_float64_array_stub();
+    case kTypedDataFloat32x4ArrayCid:
+      return object_store->allocate_float32x4_array_stub();
+    case kTypedDataInt32x4ArrayCid:
+      return object_store->allocate_int32x4_array_stub();
+    case kTypedDataFloat64x2ArrayCid:
+      return object_store->allocate_float64x2_array_stub();
+  }
+  UNREACHABLE();
+  return Code::null();
+}
+
 #if !defined(TARGET_ARCH_IA32)
 CodePtr StubCode::GetBuildMethodExtractorStub(
     compiler::ObjectPoolBuilder* pool) {
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index 19fd413..016b845 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -62,6 +62,7 @@
 #undef STUB_CODE_ACCESSOR
 
   static CodePtr GetAllocationStubForClass(const Class& cls);
+  static CodePtr GetAllocationStubForTypedData(classid_t class_id);
 
 #if !defined(TARGET_ARCH_IA32)
   static CodePtr GetBuildMethodExtractorStub(compiler::ObjectPoolBuilder* pool);
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index e38740c..395676c 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -18,6 +18,20 @@
   V(WriteBarrierWrappers)                                                      \
   V(ArrayWriteBarrier)                                                         \
   V(AllocateArray)                                                             \
+  V(AllocateInt8Array)                                                         \
+  V(AllocateUint8Array)                                                        \
+  V(AllocateUint8ClampedArray)                                                 \
+  V(AllocateInt16Array)                                                        \
+  V(AllocateUint16Array)                                                       \
+  V(AllocateInt32Array)                                                        \
+  V(AllocateUint32Array)                                                       \
+  V(AllocateInt64Array)                                                        \
+  V(AllocateUint64Array)                                                       \
+  V(AllocateFloat32Array)                                                      \
+  V(AllocateFloat64Array)                                                      \
+  V(AllocateFloat32x4Array)                                                    \
+  V(AllocateInt32x4Array)                                                      \
+  V(AllocateFloat64x2Array)                                                    \
   V(AllocateMintSharedWithFPURegs)                                             \
   V(AllocateMintSharedWithoutFPURegs)                                          \
   V(AllocateContext)                                                           \
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 10424d1..fac122b 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -5,6 +5,7 @@
 #include "vm/symbols.h"
 
 #include "platform/unicode.h"
+#include "vm/canonical_tables.h"
 #include "vm/handles.h"
 #include "vm/hash_table.h"
 #include "vm/heap/safepoint.h"
@@ -14,7 +15,6 @@
 #include "vm/raw_object.h"
 #include "vm/reusable_handles.h"
 #include "vm/snapshot_ids.h"
-#include "vm/type_table.h"
 #include "vm/visitor.h"
 
 namespace dart {
@@ -44,64 +44,6 @@
   return String::FromUTF16(data, len, space);
 }
 
-StringPtr StringFrom(const int32_t* data, intptr_t len, Heap::Space space) {
-  return String::FromUTF32(data, len, space);
-}
-
-template <typename CharType>
-class CharArray {
- public:
-  CharArray(const CharType* data, intptr_t len) : data_(data), len_(len) {
-    hash_ = String::Hash(data, len);
-  }
-  StringPtr ToSymbol() const {
-    String& result = String::Handle(StringFrom(data_, len_, Heap::kOld));
-    result.SetCanonical();
-    result.SetHash(hash_);
-    return result.raw();
-  }
-  bool Equals(const String& other) const {
-    ASSERT(other.HasHash());
-    if (other.Hash() != hash_) {
-      return false;
-    }
-    return other.Equals(data_, len_);
-  }
-  intptr_t Hash() const { return hash_; }
-
- private:
-  const CharType* data_;
-  intptr_t len_;
-  intptr_t hash_;
-};
-typedef CharArray<uint8_t> Latin1Array;
-typedef CharArray<uint16_t> UTF16Array;
-typedef CharArray<int32_t> UTF32Array;
-
-class StringSlice {
- public:
-  StringSlice(const String& str, intptr_t begin_index, intptr_t length)
-      : str_(str), begin_index_(begin_index), len_(length) {
-    hash_ = is_all() ? str.Hash() : String::Hash(str, begin_index, length);
-  }
-  StringPtr ToSymbol() const;
-  bool Equals(const String& other) const {
-    ASSERT(other.HasHash());
-    if (other.Hash() != hash_) {
-      return false;
-    }
-    return other.Equals(str_, begin_index_, len_);
-  }
-  intptr_t Hash() const { return hash_; }
-
- private:
-  bool is_all() const { return begin_index_ == 0 && len_ == str_.Length(); }
-  const String& str_;
-  intptr_t begin_index_;
-  intptr_t len_;
-  intptr_t hash_;
-};
-
 StringPtr StringSlice::ToSymbol() const {
   if (is_all() && str_.IsOld()) {
     str_.SetCanonical();
@@ -115,26 +57,6 @@
   }
 }
 
-class ConcatString {
- public:
-  ConcatString(const String& str1, const String& str2)
-      : str1_(str1), str2_(str2), hash_(String::HashConcat(str1, str2)) {}
-  StringPtr ToSymbol() const;
-  bool Equals(const String& other) const {
-    ASSERT(other.HasHash());
-    if (other.Hash() != hash_) {
-      return false;
-    }
-    return other.EqualsConcat(str1_, str2_);
-  }
-  intptr_t Hash() const { return hash_; }
-
- private:
-  const String& str1_;
-  const String& str2_;
-  intptr_t hash_;
-};
-
 StringPtr ConcatString::ToSymbol() const {
   String& result = String::Handle(String::Concat(str1_, str2_, Heap::kOld));
   result.SetCanonical();
@@ -142,53 +64,6 @@
   return result.raw();
 }
 
-class SymbolTraits {
- public:
-  static const char* Name() { return "SymbolTraits"; }
-  static bool ReportStats() { return false; }
-
-  static bool IsMatch(const Object& a, const Object& b) {
-    const String& a_str = String::Cast(a);
-    const String& b_str = String::Cast(b);
-    ASSERT(a_str.HasHash());
-    ASSERT(b_str.HasHash());
-    if (a_str.Hash() != b_str.Hash()) {
-      return false;
-    }
-    intptr_t a_len = a_str.Length();
-    if (a_len != b_str.Length()) {
-      return false;
-    }
-    // Use a comparison which does not consider the state of the canonical bit.
-    return a_str.Equals(b_str, 0, a_len);
-  }
-  template <typename CharType>
-  static bool IsMatch(const CharArray<CharType>& array, const Object& obj) {
-    return array.Equals(String::Cast(obj));
-  }
-  static bool IsMatch(const StringSlice& slice, const Object& obj) {
-    return slice.Equals(String::Cast(obj));
-  }
-  static bool IsMatch(const ConcatString& concat, const Object& obj) {
-    return concat.Equals(String::Cast(obj));
-  }
-  static uword Hash(const Object& key) { return String::Cast(key).Hash(); }
-  template <typename CharType>
-  static uword Hash(const CharArray<CharType>& array) {
-    return array.Hash();
-  }
-  static uword Hash(const StringSlice& slice) { return slice.Hash(); }
-  static uword Hash(const ConcatString& concat) { return concat.Hash(); }
-  template <typename CharType>
-  static ObjectPtr NewKey(const CharArray<CharType>& array) {
-    return array.ToSymbol();
-  }
-  static ObjectPtr NewKey(const StringSlice& slice) { return slice.ToSymbol(); }
-  static ObjectPtr NewKey(const ConcatString& concat) {
-    return concat.ToSymbol();
-  }
-};
-typedef UnorderedHashSet<SymbolTraits> SymbolTable;
 
 const char* Symbols::Name(SymbolId symbol) {
   ASSERT((symbol > kIllegal) && (symbol < kNullCharId));
@@ -216,7 +91,7 @@
   // Create all predefined symbols.
   ASSERT((sizeof(names) / sizeof(const char*)) == Symbols::kNullCharId);
 
-  SymbolTable table(zone, vm_isolate->object_store()->symbol_table());
+  CanonicalStringSet table(zone, vm_isolate->object_store()->symbol_table());
 
   // First set up all the predefined string symbols.
   // Create symbols for language keywords. Some keywords are equal to
@@ -256,7 +131,7 @@
   ASSERT(vm_isolate == Dart::vm_isolate());
   Zone* zone = Thread::Current()->zone();
 
-  SymbolTable table(zone, vm_isolate->object_store()->symbol_table());
+  CanonicalStringSet table(zone, vm_isolate->object_store()->symbol_table());
 
   // Lookup all the predefined string symbols and language keyword symbols
   // and cache them in the read only handles for fast access.
@@ -297,140 +172,14 @@
   const intptr_t initial_size = (isolate == Dart::vm_isolate())
                                     ? kInitialVMIsolateSymtabSize
                                     : kInitialSymtabSize;
-  Array& array =
-      Array::Handle(HashTables::New<SymbolTable>(initial_size, Heap::kOld));
+  Array& array = Array::Handle(
+      HashTables::New<CanonicalStringSet>(initial_size, Heap::kOld));
   isolate->object_store()->set_symbol_table(array);
 }
 
-void Symbols::Compact() {
-  Thread* thread = Thread::Current();
-  ASSERT(thread->isolate() != Dart::vm_isolate());
-  HANDLESCOPE(thread);
-  Zone* zone = thread->zone();
-  ObjectStore* object_store = thread->isolate()->object_store();
-
-  // 1. Drop the tables and do a full garbage collection.
-  object_store->set_symbol_table(Object::empty_array());
-  object_store->set_canonical_types(Object::empty_array());
-  object_store->set_canonical_type_parameters(Object::empty_array());
-  object_store->set_canonical_type_arguments(Object::empty_array());
-  thread->heap()->CollectAllGarbage();
-
-  // 2. Walk the heap to find surviving canonical objects.
-  GrowableArray<String*> symbols;
-  GrowableArray<class Type*> types;
-  GrowableArray<class TypeParameter*> type_params;
-  GrowableArray<class TypeArguments*> type_args;
-  class SymbolCollector : public ObjectVisitor {
-   public:
-    SymbolCollector(Thread* thread,
-                    GrowableArray<String*>* symbols,
-                    GrowableArray<class Type*>* types,
-                    GrowableArray<class TypeParameter*>* type_params,
-                    GrowableArray<class TypeArguments*>* type_args)
-        : symbols_(symbols),
-          types_(types),
-          type_params_(type_params),
-          type_args_(type_args),
-          zone_(thread->zone()) {}
-
-    void VisitObject(ObjectPtr obj) {
-      if (obj->ptr()->IsCanonical()) {
-        if (obj->IsStringInstance()) {
-          symbols_->Add(&String::Handle(zone_, String::RawCast(obj)));
-        } else if (obj->IsType()) {
-          types_->Add(&Type::Handle(zone_, Type::RawCast(obj)));
-        } else if (obj->IsTypeParameter()) {
-          type_params_->Add(
-              &TypeParameter::Handle(zone_, TypeParameter::RawCast(obj)));
-        } else if (obj->IsTypeArguments()) {
-          type_args_->Add(
-              &TypeArguments::Handle(zone_, TypeArguments::RawCast(obj)));
-        }
-      }
-    }
-
-   private:
-    GrowableArray<String*>* symbols_;
-    GrowableArray<class Type*>* types_;
-    GrowableArray<class TypeParameter*>* type_params_;
-    GrowableArray<class TypeArguments*>* type_args_;
-    Zone* zone_;
-  };
-
-  {
-    HeapIterationScope iteration(thread);
-    SymbolCollector visitor(thread, &symbols, &types, &type_params, &type_args);
-    iteration.IterateObjects(&visitor);
-  }
-
-  // 3. Build new tables from the surviving canonical objects.
-  {
-    Array& array = Array::Handle(
-        zone,
-        HashTables::New<SymbolTable>(symbols.length() * 4 / 3, Heap::kOld));
-    SymbolTable table(zone, array.raw());
-    for (intptr_t i = 0; i < symbols.length(); i++) {
-      String& symbol = *symbols[i];
-      ASSERT(symbol.IsString());
-      ASSERT(symbol.IsCanonical());
-      bool present = table.Insert(symbol);
-      ASSERT(!present);
-    }
-    object_store->set_symbol_table(table.Release());
-  }
-
-  {
-    Array& array = Array::Handle(zone, HashTables::New<CanonicalTypeSet>(
-                                           types.length() * 4 / 3, Heap::kOld));
-    CanonicalTypeSet table(zone, array.raw());
-    for (intptr_t i = 0; i < types.length(); i++) {
-      class Type& type = *types[i];
-      ASSERT(type.IsType());
-      ASSERT(type.IsCanonical());
-      bool present = table.Insert(type);
-      // Two recursive types with different topology (and hashes) may be equal.
-      ASSERT(!present || type.IsRecursive());
-    }
-    object_store->set_canonical_types(table.Release());
-  }
-
-  {
-    Array& array =
-        Array::Handle(zone, HashTables::New<CanonicalTypeParameterSet>(
-                                type_params.length() * 4 / 3, Heap::kOld));
-    CanonicalTypeParameterSet table(zone, array.raw());
-    for (intptr_t i = 0; i < type_params.length(); i++) {
-      class TypeParameter& type_param = *type_params[i];
-      ASSERT(type_param.IsTypeParameter());
-      ASSERT(type_param.IsCanonical());
-      if (type_param.IsDeclaration()) continue;
-      bool present = table.Insert(type_param);
-      ASSERT(!present);
-    }
-    object_store->set_canonical_type_parameters(table.Release());
-  }
-
-  {
-    Array& array =
-        Array::Handle(zone, HashTables::New<CanonicalTypeArgumentsSet>(
-                                type_args.length() * 4 / 3, Heap::kOld));
-    CanonicalTypeArgumentsSet table(zone, array.raw());
-    for (intptr_t i = 0; i < type_args.length(); i++) {
-      class TypeArguments& type_arg = *type_args[i];
-      ASSERT(type_arg.IsTypeArguments());
-      ASSERT(type_arg.IsCanonical());
-      bool present = table.Insert(type_arg);
-      // Two recursive types with different topology (and hashes) may be equal.
-      ASSERT(!present || type_arg.IsRecursive());
-    }
-    object_store->set_canonical_type_arguments(table.Release());
-  }
-}
-
 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) {
   ASSERT(isolate != NULL);
-  SymbolTable table(isolate->object_store()->symbol_table());
+  CanonicalStringSet table(isolate->object_store()->symbol_table());
   *size = table.NumOccupied();
   *capacity = table.NumEntries();
   table.Release();
@@ -481,12 +230,6 @@
   return NewSymbol(thread, UTF16Array(utf16_array, len));
 }
 
-StringPtr Symbols::FromUTF32(Thread* thread,
-                             const int32_t* utf32_array,
-                             intptr_t len) {
-  return NewSymbol(thread, UTF32Array(utf32_array, len));
-}
-
 StringPtr Symbols::FromConcat(Thread* thread,
                               const String& str1,
                               const String& str2) {
@@ -586,7 +329,7 @@
   }
 }
 
-// StringType can be StringSlice, ConcatString, or {Latin1,UTF16,UTF32}Array.
+// StringType can be StringSlice, ConcatString, or {Latin1,UTF16}Array.
 template <typename StringType>
 StringPtr Symbols::NewSymbol(Thread* thread, const StringType& str) {
   REUSABLE_OBJECT_HANDLESCOPE(thread);
@@ -599,7 +342,7 @@
   {
     Isolate* vm_isolate = Dart::vm_isolate();
     data = vm_isolate->object_store()->symbol_table();
-    SymbolTable table(&key, &value, &data);
+    CanonicalStringSet table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
@@ -628,7 +371,7 @@
       // Uncommon case: We are at a safepoint, all mutators are stopped and we
       // have therefore exclusive access to the symbol table.
       data = object_store->symbol_table();
-      SymbolTable table(&key, &value, &data);
+      CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.InsertNewOrGet(str);
       object_store->set_symbol_table(table.Release());
     } else {
@@ -637,7 +380,7 @@
       {
         SafepointReadRwLocker sl(thread, group->symbols_lock());
         data = object_store->symbol_table();
-        SymbolTable table(&key, &value, &data);
+        CanonicalStringSet table(&key, &value, &data);
         symbol ^= table.GetOrNull(str);
         table.Release();
       }
@@ -646,7 +389,7 @@
       if (symbol.IsNull()) {
         auto insert_or_get = [&]() {
           data = object_store->symbol_table();
-          SymbolTable table(&key, &value, &data);
+          CanonicalStringSet table(&key, &value, &data);
           symbol ^= table.InsertNewOrGet(str);
           object_store->set_symbol_table(table.Release());
         };
@@ -683,7 +426,7 @@
   {
     Isolate* vm_isolate = Dart::vm_isolate();
     data = vm_isolate->object_store()->symbol_table();
-    SymbolTable table(&key, &value, &data);
+    CanonicalStringSet table(&key, &value, &data);
     symbol ^= table.GetOrNull(str);
     table.Release();
   }
@@ -704,13 +447,13 @@
       RELEASE_ASSERT(FLAG_enable_isolate_groups || !USING_PRODUCT);
 #endif
       data = object_store->symbol_table();
-      SymbolTable table(&key, &value, &data);
+      CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.GetOrNull(str);
       table.Release();
     } else {
       SafepointReadRwLocker sl(thread, group->symbols_lock());
       data = object_store->symbol_table();
-      SymbolTable table(&key, &value, &data);
+      CanonicalStringSet table(&key, &value, &data);
       symbol ^= table.GetOrNull(str);
       table.Release();
     }
@@ -782,9 +525,9 @@
   return Symbols::New(thread, buffer);
 }
 
-StringPtr Symbols::FromCharCode(Thread* thread, int32_t char_code) {
+StringPtr Symbols::FromCharCode(Thread* thread, uint16_t char_code) {
   if (char_code > kMaxOneCharCodeSymbol) {
-    return FromUTF32(thread, &char_code, 1);
+    return FromUTF16(thread, &char_code, 1);
   }
   return predefined_[char_code];
 }
@@ -806,7 +549,7 @@
 
 void Symbols::DumpTable(Isolate* isolate) {
   OS::PrintErr("symbols:\n");
-  SymbolTable table(isolate->object_store()->symbol_table());
+  CanonicalStringSet table(isolate->object_store()->symbol_table());
   table.Dump();
   table.Release();
 }
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 9010987..84b028b 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -108,12 +108,8 @@
   V(Double, "double")                                                          \
   V(Dynamic, "dynamic")                                                        \
   V(DynamicCall, "dyn:call")                                                   \
+  V(DynamicCallCurrentNumProcessedVar, ":dyn_call_current_num_processed")      \
   V(DynamicCallCurrentParamIndexVar, ":dyn_call_current_param_index")          \
-  V(DynamicCallHasNamedVar, ":dyn_call_has_named")                             \
-  V(DynamicCallMaxParamsVar, ":dyn_call_max_params")                           \
-  V(DynamicCallNumFixedVar, ":dyn_call_num_fixed")                             \
-  V(DynamicCallNumOptVar, ":dyn_call_num_opt")                                 \
-  V(DynamicCallParameterNamesVar, ":dyn_call_parameter_names")                 \
   V(DynamicPrefix, "dyn:")                                                     \
   V(EntryPointsTemp, ":entry_points_temp")                                     \
   V(EqualOperator, "==")                                                       \
@@ -658,9 +654,6 @@
   // Initialize and setup a symbol table for the isolate.
   static void SetupSymbolTable(Isolate* isolate);
 
-  // Treat the symbol table as weak and collect garbage.
-  static void Compact();
-
   // Creates a Symbol given a C string that is assumed to contain
   // UTF-8 encoded characters and '\0' is considered a termination character.
   // TODO(7123) - Rename this to FromCString(....).
@@ -684,11 +677,6 @@
                              const uint16_t* utf16_array,
                              intptr_t len);
 
-  // Creates a new Symbol from an array of UTF-32 encoded characters.
-  static StringPtr FromUTF32(Thread* thread,
-                             const int32_t* utf32_array,
-                             intptr_t len);
-
   static StringPtr New(Thread* thread, const String& str);
   static StringPtr New(Thread* thread,
                        const String& str,
@@ -716,7 +704,7 @@
   // Returns char* of predefined symbol.
   static const char* Name(SymbolId symbol);
 
-  static StringPtr FromCharCode(Thread* thread, int32_t char_code);
+  static StringPtr FromCharCode(Thread* thread, uint16_t char_code);
 
   static StringPtr* PredefinedAddress() {
     return reinterpret_cast<StringPtr*>(&predefined_);
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index b81e29d..6a8ce03 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -127,12 +127,12 @@
   constexpr bool operator!=(const ObjectPtr& other) const {
     return tagged_pointer_ != other.tagged_pointer_;
   }
-  bool operator==(const nullptr_t& other) { return tagged_pointer_ == 0; }
-  bool operator!=(const nullptr_t& other) { return tagged_pointer_ != 0; }
-  constexpr bool operator==(const nullptr_t& other) const {
+  bool operator==(const std::nullptr_t& other) { return tagged_pointer_ == 0; }
+  bool operator!=(const std::nullptr_t& other) { return tagged_pointer_ != 0; }
+  constexpr bool operator==(const std::nullptr_t& other) const {
     return tagged_pointer_ == 0;
   }
-  constexpr bool operator!=(const nullptr_t& other) const {
+  constexpr bool operator!=(const std::nullptr_t& other) const {
     return tagged_pointer_ != 0;
   }
 
@@ -183,7 +183,7 @@
   ObjectPtr() : tagged_pointer_(0) {}
   explicit constexpr ObjectPtr(uword tagged) : tagged_pointer_(tagged) {}
   explicit constexpr ObjectPtr(intptr_t tagged) : tagged_pointer_(tagged) {}
-  constexpr ObjectPtr(nullptr_t) : tagged_pointer_(0) {}  // NOLINT
+  constexpr ObjectPtr(std::nullptr_t) : tagged_pointer_(0) {}  // NOLINT
   explicit ObjectPtr(ObjectLayout* heap_object)
       : tagged_pointer_(reinterpret_cast<uword>(heap_object) + kHeapObjectTag) {
   }
@@ -224,8 +224,7 @@
         : base##Ptr(other) {}                                                  \
     klass##Ptr() : base##Ptr() {}                                              \
     explicit constexpr klass##Ptr(uword tagged) : base##Ptr(tagged) {}         \
-    explicit constexpr klass##Ptr(intptr_t tagged) : base##Ptr(tagged) {}      \
-    constexpr klass##Ptr(nullptr_t) : base##Ptr(nullptr) {} /* NOLINT */       \
+    constexpr klass##Ptr(std::nullptr_t) : base##Ptr(nullptr) {} /* NOLINT */  \
     explicit klass##Ptr(const ObjectLayout* untagged)                          \
         : base##Ptr(reinterpret_cast<uword>(untagged) + kHeapObjectTag) {}     \
   };
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index a5618c6..41e3374 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -176,8 +176,6 @@
   Monitor sync[kTaskCount];
   bool done[kTaskCount];
   Isolate* isolate = thread->isolate();
-  EXPECT(isolate->heap()->GrowthControlState());
-  isolate->heap()->DisableGrowthControl();
   for (int i = 0; i < kTaskCount; i++) {
     done[i] = false;
     Dart::thread_pool()->Run<TaskWithZoneAllocation>(isolate, &sync[i],
diff --git a/runtime/vm/type_table.h b/runtime/vm/type_table.h
deleted file mode 100644
index 99fad9f..0000000
--- a/runtime/vm/type_table.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_VM_TYPE_TABLE_H_
-#define RUNTIME_VM_TYPE_TABLE_H_
-
-#include "platform/assert.h"
-#include "vm/hash_table.h"
-#include "vm/object.h"
-
-namespace dart {
-
-class CanonicalTypeKey {
- public:
-  explicit CanonicalTypeKey(const Type& key) : key_(key) {}
-  bool Matches(const Type& arg) const { return key_.Equals(arg); }
-  uword Hash() const { return key_.Hash(); }
-  const Type& key_;
-
- private:
-  DISALLOW_ALLOCATION();
-};
-
-// Traits for looking up Canonical Type based on its hash.
-class CanonicalTypeTraits {
- public:
-  static const char* Name() { return "CanonicalTypeTraits"; }
-  static bool ReportStats() { return false; }
-
-  // Called when growing the table.
-  static bool IsMatch(const Object& a, const Object& b) {
-    ASSERT(a.IsType() && b.IsType());
-    const Type& arg1 = Type::Cast(a);
-    const Type& arg2 = Type::Cast(b);
-    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
-  }
-  static bool IsMatch(const CanonicalTypeKey& a, const Object& b) {
-    ASSERT(b.IsType());
-    return a.Matches(Type::Cast(b));
-  }
-  static uword Hash(const Object& key) {
-    ASSERT(key.IsType());
-    return Type::Cast(key).Hash();
-  }
-  static uword Hash(const CanonicalTypeKey& key) { return key.Hash(); }
-  static ObjectPtr NewKey(const CanonicalTypeKey& obj) {
-    return obj.key_.raw();
-  }
-};
-typedef UnorderedHashSet<CanonicalTypeTraits> CanonicalTypeSet;
-
-class CanonicalTypeParameterKey {
- public:
-  explicit CanonicalTypeParameterKey(const TypeParameter& key) : key_(key) {}
-  bool Matches(const TypeParameter& arg) const { return key_.Equals(arg); }
-  uword Hash() const { return key_.Hash(); }
-  const TypeParameter& key_;
-
- private:
-  DISALLOW_ALLOCATION();
-};
-
-// Traits for looking up Canonical TypeParameter based on its hash.
-class CanonicalTypeParameterTraits {
- public:
-  static const char* Name() { return "CanonicalTypeParameterTraits"; }
-  static bool ReportStats() { return false; }
-
-  // Called when growing the table.
-  static bool IsMatch(const Object& a, const Object& b) {
-    ASSERT(a.IsTypeParameter() && b.IsTypeParameter());
-    const TypeParameter& arg1 = TypeParameter::Cast(a);
-    const TypeParameter& arg2 = TypeParameter::Cast(b);
-    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
-  }
-  static bool IsMatch(const CanonicalTypeParameterKey& a, const Object& b) {
-    ASSERT(b.IsTypeParameter());
-    return a.Matches(TypeParameter::Cast(b));
-  }
-  static uword Hash(const Object& key) {
-    ASSERT(key.IsTypeParameter());
-    return TypeParameter::Cast(key).Hash();
-  }
-  static uword Hash(const CanonicalTypeParameterKey& key) { return key.Hash(); }
-  static ObjectPtr NewKey(const CanonicalTypeParameterKey& obj) {
-    return obj.key_.raw();
-  }
-};
-typedef UnorderedHashSet<CanonicalTypeParameterTraits>
-    CanonicalTypeParameterSet;
-
-class CanonicalTypeArgumentsKey {
- public:
-  explicit CanonicalTypeArgumentsKey(const TypeArguments& key) : key_(key) {}
-  bool Matches(const TypeArguments& arg) const {
-    return key_.Equals(arg) && (key_.Hash() == arg.Hash());
-  }
-  uword Hash() const { return key_.Hash(); }
-  const TypeArguments& key_;
-
- private:
-  DISALLOW_ALLOCATION();
-};
-
-// Traits for looking up Canonical TypeArguments based on its hash.
-class CanonicalTypeArgumentsTraits {
- public:
-  static const char* Name() { return "CanonicalTypeArgumentsTraits"; }
-  static bool ReportStats() { return false; }
-
-  // Called when growing the table.
-  static bool IsMatch(const Object& a, const Object& b) {
-    ASSERT(a.IsTypeArguments() && b.IsTypeArguments());
-    const TypeArguments& arg1 = TypeArguments::Cast(a);
-    const TypeArguments& arg2 = TypeArguments::Cast(b);
-    return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
-  }
-  static bool IsMatch(const CanonicalTypeArgumentsKey& a, const Object& b) {
-    ASSERT(b.IsTypeArguments());
-    return a.Matches(TypeArguments::Cast(b));
-  }
-  static uword Hash(const Object& key) {
-    ASSERT(key.IsTypeArguments());
-    return TypeArguments::Cast(key).Hash();
-  }
-  static uword Hash(const CanonicalTypeArgumentsKey& key) { return key.Hash(); }
-  static ObjectPtr NewKey(const CanonicalTypeArgumentsKey& obj) {
-    return obj.key_.raw();
-  }
-};
-typedef UnorderedHashSet<CanonicalTypeArgumentsTraits>
-    CanonicalTypeArgumentsSet;
-
-}  // namespace dart
-
-#endif  // RUNTIME_VM_TYPE_TABLE_H_
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index 8f5f57c..60328d7 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -23,7 +23,6 @@
     : lib_(Library::Handle()),
       klass_(Class::Handle()),
       type_(AbstractType::Handle()),
-      type_arguments_(TypeArguments::Handle()),
       string_(String::Handle()) {}
 
 const char* TypeTestingStubNamer::StubNameForType(
@@ -56,16 +55,18 @@
         OS::SCreate(Z, "%s_%s", curl, klass_.ScrubbedNameCString()));
 
     const intptr_t type_parameters = klass_.NumTypeParameters();
+    auto& type_arguments = TypeArguments::Handle();
     if (type.arguments() != TypeArguments::null() && type_parameters > 0) {
-      type_arguments_ = type.arguments();
-      ASSERT(type_arguments_.Length() >= type_parameters);
-      const intptr_t length = type_arguments_.Length();
+      type_arguments = type.arguments();
+      ASSERT(type_arguments.Length() >= type_parameters);
+      const intptr_t length = type_arguments.Length();
       for (intptr_t i = 0; i < type_parameters; ++i) {
-        type_ = type_arguments_.TypeAt(length - type_parameters + i);
+        type_ = type_arguments.TypeAt(length - type_parameters + i);
         concatenated =
             OS::SCreate(Z, "%s__%s", concatenated, StringifyType(type_));
       }
     }
+
     return concatenated;
   } else if (type.IsTypeParameter()) {
     string_ = TypeParameter::Cast(type).name();
@@ -523,8 +524,8 @@
   //      type_arguments <- Constant(#TypeArguments: [ ... ])
   //
   //   Case b)
-  //      type_arguments <- InstantiateTypeArguments(
-  //          <type-expr-with-parameters>, ita, fta)
+  //      type_arguments <- InstantiateTypeArguments(ita, fta, uta)
+  //      (where uta may or may not be a constant TypeArguments object)
   //
   //   Case c)
   //      type_arguments <- LoadField(vx)
@@ -543,8 +544,10 @@
     type_usage_info->UseTypeArgumentsInInstanceCreation(klass, type_arguments);
   } else if (InstantiateTypeArgumentsInstr* instantiate =
                  type_arguments->AsInstantiateTypeArguments()) {
-    const TypeArguments& ta = instantiate->type_arguments();
-    ASSERT(!ta.IsNull());
+    ASSERT(instantiate->type_arguments()->BindsToConstant());
+    ASSERT(!instantiate->type_arguments()->BoundConstant().IsNull());
+    const auto& ta =
+        TypeArguments::Cast(instantiate->type_arguments()->BoundConstant());
     type_usage_info->UseTypeArgumentsInInstanceCreation(klass, ta);
   } else if (LoadFieldInstr* load_field = type_arguments->AsLoadField()) {
     Definition* instance = load_field->instance()->definition();
@@ -641,7 +644,7 @@
             AbstractType::Handle(TypeRef::Cast(type_).type()).IsCanonical()));
   }
   *instantiated_type_arguments =
-      instantiated_type_arguments->Canonicalize(NULL);
+      instantiated_type_arguments->Canonicalize(Thread::Current(), nullptr);
   return *instantiated_type_arguments;
 }
 
@@ -684,7 +687,7 @@
     *to_type_arguments = from.arguments();
     to->set_arguments(InstantiateTypeArguments(klass_, *to_type_arguments));
     to->SetIsFinalized();
-    *to ^= to->Canonicalize(NULL);
+    *to ^= to->Canonicalize(Thread::Current(), nullptr);
 
     return to->raw();
   }
diff --git a/runtime/vm/type_testing_stubs.h b/runtime/vm/type_testing_stubs.h
index b602c6a..09c6f1d 100644
--- a/runtime/vm/type_testing_stubs.h
+++ b/runtime/vm/type_testing_stubs.h
@@ -32,7 +32,6 @@
   Library& lib_;
   Class& klass_;
   AbstractType& type_;
-  TypeArguments& type_arguments_;
   String& string_;
 };
 
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 0a218cb..c035bdf 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -24,7 +24,7 @@
 }
 
 static void CanonicalizeTAV(TypeArguments* tav) {
-  *tav = tav->Canonicalize();
+  *tav = tav->Canonicalize(Thread::Current(), nullptr);
 }
 
 static void RunTTSTest(
@@ -679,6 +679,8 @@
 
   const auto& root_library = Library::Handle(LoadTestScript(kScript));
   const auto& class_a = Class::Handle(GetClass(root_library, "A"));
+  ClassFinalizer::FinalizeTypesInClass(class_a);
+
   const auto& fun_generic =
       Function::Handle(GetFunction(root_library, "genericFun"));
 
diff --git a/runtime/vm/visitor.h b/runtime/vm/visitor.h
index 93baf0d..eb9d343 100644
--- a/runtime/vm/visitor.h
+++ b/runtime/vm/visitor.h
@@ -52,6 +52,11 @@
 
   virtual bool visit_weak_persistent_handles() const { return false; }
 
+  // When visiting objects to build retaining paths, trace field values
+  // through fields.
+  // Otherwise trace field values through isolate's field_table.
+  virtual bool trace_values_through_fields() const { return false; }
+
   const SharedClassTable* shared_class_table() const {
     return shared_class_table_;
   }
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index a919b39..2cd70b1 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -21,6 +21,7 @@
   "bootstrap_natives.h",
   "bss_relocs.cc",
   "bss_relocs.h",
+  "canonical_tables.h",
   "class_finalizer.cc",
   "class_finalizer.h",
   "class_id.h",
@@ -341,7 +342,6 @@
   "token.h",
   "token_position.cc",
   "token_position.h",
-  "type_table.h",
   "type_testing_stubs.cc",
   "type_testing_stubs.h",
   "unibrow-inl.h",
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index 72f9851..9444e50 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -586,15 +586,16 @@
   visibility = [ ":create_common_sdk" ]
   deps = [
     ":copy_libraries",
-    "../third_party/wasmer:wasmer_lib",
+    "../third_party/wasmer:wasmer_wrapper",
   ]
-  outputs = [ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ]
+  outputs =
+      [ "$root_out_dir/dart-sdk/bin/third_party/wasmer/{{source_file_part}}" ]
   if (is_win) {
-    sources = [ "$target_out_dir/../third_party/wasmer/wasmer.dll" ]
+    sources = [ "$root_out_dir/wasmer_wrapper.dll" ]
   } else if (is_mac) {
-    sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.dylib" ]
+    sources = [ "$root_out_dir/libwasmer_wrapper.dylib" ]
   } else {
-    sources = [ "$target_out_dir/../third_party/wasmer/libwasmer.so" ]
+    sources = [ "$root_out_dir/libwasmer_wrapper.so" ]
   }
 }
 
@@ -754,13 +755,16 @@
   visibility = [ ":create_common_sdk" ]
   sources = [
     "../runtime/include/dart_api.h",
+    "../runtime/include/dart_api_dl.c",
     "../runtime/include/dart_api_dl.h",
     "../runtime/include/dart_native_api.h",
     "../runtime/include/dart_tools_api.h",
     "../runtime/include/dart_version.h",
     "../runtime/include/internal/dart_api_dl_impl.h",
   ]
-  outputs = [ "$root_out_dir/dart-sdk/include/{{source_file_part}}" ]
+
+  # Some magic to recover the folder structure inside the include folder.
+  outputs = [ "$root_out_dir/dart-sdk/include/{{source_root_relative_dir}}/../../{{source_file_part}}" ]
 }
 
 # This rule copies libraries.json files to lib/
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index 151dae4..76d2c68 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -18,6 +18,7 @@
 import 'dart:developer' hide log;
 import 'dart:_internal'
     show Since, valueOfNonNullableParamWithDefault, HttpStatus;
+import 'dart:isolate' show Isolate;
 import 'dart:math';
 import 'dart:io';
 import 'dart:typed_data';
@@ -1473,8 +1474,14 @@
   ///
   /// Default is `false`.
   static set enableTimelineLogging(bool value) {
-    _enableTimelineLogging =
-        valueOfNonNullableParamWithDefault<bool>(value, false);
+    final enabled = valueOfNonNullableParamWithDefault<bool>(value, false);
+    if (enabled != _enableTimelineLogging) {
+      postEvent('HttpTimelineLoggingStateChange', {
+        'isolateId': Service.getIsolateID(Isolate.current),
+        'enabled': enabled,
+      });
+    }
+    _enableTimelineLogging = enabled;
   }
 
   /// Current state of HTTP request logging from all [HttpClient]s to the
@@ -1938,8 +1945,9 @@
    * and only for the status codes [HttpStatus.movedPermanently]
    * (301), [HttpStatus.found] (302),
    * [HttpStatus.movedTemporarily] (302, alias for
-   * [HttpStatus.found]), [HttpStatus.seeOther] (303) and
-   * [HttpStatus.temporaryRedirect] (307). For
+   * [HttpStatus.found]), [HttpStatus.seeOther] (303),
+   * [HttpStatus.temporaryRedirect] (307) and
+   * [HttpStatus.permanentRedirect] (308). For
    * [HttpStatus.seeOther] (303) automatic redirect will also happen
    * for "POST" requests with the method changed to "GET" when
    * following the redirect.
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 3cf75d9..eac06c4 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -252,7 +252,9 @@
     var proto = headers['x-forwarded-proto'];
     var scheme = proto != null
         ? proto.first
-        : _httpConnection._socket is SecureSocket ? "https" : "http";
+        : _httpConnection._socket is SecureSocket
+            ? "https"
+            : "http";
     var hostList = headers['x-forwarded-host'];
     String host;
     if (hostList != null) {
@@ -348,6 +350,7 @@
   bool get isRedirect {
     if (_httpRequest.method == "GET" || _httpRequest.method == "HEAD") {
       return statusCode == HttpStatus.movedPermanently ||
+          statusCode == HttpStatus.permanentRedirect ||
           statusCode == HttpStatus.found ||
           statusCode == HttpStatus.seeOther ||
           statusCode == HttpStatus.temporaryRedirect;
@@ -1120,6 +1123,7 @@
   final _HttpClient _httpClient;
   final _HttpClientConnection _httpClientConnection;
   final TimelineTask? _timeline;
+  final TimelineTask? _responseTimeline;
 
   final Completer<HttpClientResponse> _responseCompleter =
       new Completer<HttpClientResponse>();
@@ -1137,10 +1141,17 @@
 
   bool _aborted = false;
 
-  _HttpClientRequest(_HttpOutgoing outgoing, Uri uri, this.method, this._proxy,
-      this._httpClient, this._httpClientConnection, this._timeline)
+  _HttpClientRequest(
+      _HttpOutgoing outgoing,
+      Uri uri,
+      this.method,
+      this._proxy,
+      this._httpClient,
+      this._httpClientConnection,
+      this._timeline,
+      this._responseTimeline)
       : uri = uri,
-        super(uri, "1.1", outgoing, _timeline) {
+        super(uri, "1.1", outgoing, _responseTimeline) {
     _timeline?.instant('Request initiated');
     // GET and HEAD have 'content-length: 0' by default.
     if (method == "GET" || method == "HEAD") {
@@ -1194,7 +1205,8 @@
       });
 
       // Start the timeline for response.
-      _timeline?.start('HTTP CLIENT response of ${method.toUpperCase()}',
+      _responseTimeline?.start(
+          'HTTP CLIENT response of ${method.toUpperCase()}',
           arguments: {
             'requestUri': uri.toString(),
             'statusCode': response.statusCode,
@@ -1235,7 +1247,7 @@
       return;
     }
     final response =
-        _HttpClientResponse(incoming, this, _httpClient, _timeline);
+        _HttpClientResponse(incoming, this, _httpClient, _responseTimeline);
     Future<HttpClientResponse> future;
     if (followRedirects && response.isRedirect) {
       if (response.redirects.length < maxRedirects) {
@@ -1859,9 +1871,16 @@
     _ProxyCredentials? proxyCreds; // Credentials used to authorize proxy.
     _SiteCredentials? creds; // Credentials used to authorize this request.
     var outgoing = new _HttpOutgoing(_socket);
+
+    final responseTimeline = timeline == null
+        ? null
+        : TimelineTask(
+            parent: timeline,
+            filterKey: 'HTTP/client',
+          );
     // Create new request object, wrapping the outgoing connection.
-    var request = new _HttpClientRequest(
-        outgoing, uri, method, proxy, _httpClient, this, timeline);
+    var request = new _HttpClientRequest(outgoing, uri, method, proxy,
+        _httpClient, this, timeline, responseTimeline);
     // For the Host header an IPv6 address must be enclosed in []'s.
     var host = uri.host;
     if (host.contains(':')) host = "[$host]";
@@ -2412,6 +2431,9 @@
     }
 
     bool isSecure = uri.isScheme("https");
+    if (!isSecure && !isInsecureConnectionAllowed(uri.host)) {
+      throw new StateError("Insecure HTTP is not allowed by platform: $uri");
+    }
     int port = uri.port;
     if (port == 0) {
       port =
diff --git a/sdk/lib/_internal/allowed_experiments.json b/sdk/lib/_internal/allowed_experiments.json
index 235e683..aadacfe 100644
--- a/sdk/lib/_internal/allowed_experiments.json
+++ b/sdk/lib/_internal/allowed_experiments.json
@@ -58,6 +58,9 @@
     "flutter": {
       "experimentSet": "nullSafety"
     },
+    "flutter_driver": {
+      "experimentSet": "nullSafety"
+    },
     "flutter_test": {
       "experimentSet": "nullSafety"
     },
@@ -67,15 +70,30 @@
     "flutter_goldens_client": {
       "experimentSet": "nullSafety"
     },
+    "http": {
+      "experimentSet": "nullSafety"
+    },
+    "http_parser": {
+      "experimentSet": "nullSafety"
+    },
+    "intl": {
+      "experimentSet": "nullSafety"
+    },
     "js": {
       "experimentSet": "nullSafety"
     },
+    "logging": {
+      "experimentSet": "nullSafety"
+    },
     "matcher": {
       "experimentSet": "nullSafety"
     },
     "meta": {
       "experimentSet": "nullSafety"
     },
+    "native_stack_traces": {
+      "experimentSet": "nullSafety"
+    },
     "path": {
       "experimentSet": "nullSafety"
     },
@@ -91,6 +109,9 @@
     "process": {
       "experimentSet": "nullSafety"
     },
+    "pub_semver": {
+      "experimentSet": "nullSafety"
+    },
     "sky_engine": {
       "experimentSet": "nullSafety"
     },
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
index 2171a9f..5916674 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/core_patch.dart
@@ -732,8 +732,8 @@
   @patch
   String toString() => Primitives.flattenString(_contents);
 
-  void _writeString(String str) {
-    _contents = Primitives.stringConcatUnchecked(_contents, str);
+  void _writeString(@notNull String str) {
+    _contents = JS<String>('!', '# + #', _contents, str);
   }
 
   static String _writeAll(String string, Iterable objects, String separator) {
@@ -753,8 +753,8 @@
     return string;
   }
 
-  static String _writeOne(String string, Object? obj) {
-    return Primitives.stringConcatUnchecked(string, '$obj');
+  static String _writeOne(@notNull String string, Object? obj) {
+    return JS<String>('!', '# + #', string, '$obj');
   }
 }
 
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
index 66c6bb1..f4ab556 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/internal_patch.dart
@@ -56,3 +56,9 @@
 @patch
 Object? extractTypeArguments<T>(T instance, Function extract) =>
     dart.extractTypeArguments<T>(instance, extract);
+
+@patch
+T createSentinel<T>() => throw UnsupportedError('createSentinel');
+
+@patch
+bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel');
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
index 6b33186..13ab061 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart
@@ -43,6 +43,10 @@
   }
 }
 
+throwLateInitializationError(String name) {
+  throw internal.LateInitializationErrorImpl(name);
+}
+
 throwCyclicInitializationError([String? field]) {
   throw CyclicInitializationError(field);
 }
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
index 489795f..6fcd3d1 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart
@@ -785,22 +785,38 @@
 // performance in other projects (e.g. webcomponents.js ShadowDOM polyfill).
 defineLazyField(to, name, desc) => JS('', '''(() => {
   const initializer = $desc.get;
+  const final = $desc.set == null;
+  // Tracks if the initializer has been called.
+  let initialized = false;
   let init = initializer;
   let value = null;
-  let executed = false;
+  // Tracks if these local variables have been saved so they can be restored
+  // after a hot restart.
+  let savedLocals = false;
   $desc.get = function() {
     if (init == null) return value;
-    if (!executed) {
+    if (final && initialized) $throwLateInitializationError($name);
+    if (!savedLocals) {
       // Record the field on first execution so we can reset it later if
       // needed (hot restart).
       $_resetFields.push(() => {
         init = initializer;
         value = null;
-        executed = false;
+        savedLocals = false;
+        initialized = false;
       });
-      executed = true;
+      savedLocals = true;
     }
-    value = init();
+    // Must set before calling init in case it is recursive.
+    initialized = true;
+    try {
+      value = init();
+    } catch (e) {
+      // Reset to false so the initializer can be executed again if the
+      // exception was caught.
+      initialized = false;
+      throw e;
+    }
     init = null;
     return value;
   };
@@ -809,7 +825,7 @@
     $desc.set = function(x) {
       init = null;
       value = x;
-      // executed is dead since init is set to null
+      // savedLocals and initialized are dead since init is set to null
     };
   }
   return ${defineProperty(to, name, desc)};
@@ -854,3 +870,10 @@
   }
   return ${defineProperty(to, name, desc)};
 })()''');
+
+checkNativeNonNull(dynamic variable) {
+  if (_nativeNonNullAsserts) {
+    return nullCheck(variable);
+  }
+  return variable;
+}
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index f07c4d8..3738a3d 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -11,7 +11,7 @@
 import 'dart:_debugger' show stackTraceMapper, trackCall;
 import 'dart:_foreign_helper' show JS, JSExportName, rest, spread;
 import 'dart:_interceptors' show JSArray, jsNull, JSFunction, NativeError;
-import 'dart:_internal' as internal show Symbol;
+import 'dart:_internal' as internal show LateInitializationErrorImpl, Symbol;
 import 'dart:_js_helper'
     show
         AssertionErrorImpl,
@@ -179,8 +179,8 @@
 /// A list of functions to reset static fields back to their uninitialized
 /// state.
 ///
-/// This is populated by [defineLazyField], and only contains the list of fields
-/// that have actually been initialized.
+/// This is populated by [defineLazyField] and [LazyJSType] and only contains
+/// fields that have been initialized.
 @notNull
 final List<void Function()> _resetFields = JS('', '[]');
 
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index 2a6c61e..31e7e91 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -44,6 +44,15 @@
   _nonNullAsserts = enable;
 }
 
+@notNull
+bool _nativeNonNullAsserts = false;
+
+/// Enables null assertions on native APIs to make sure value returned from the
+/// browser is sound. These apply to dart:html and similar web libraries.
+void nativeNonNullAsserts(bool enable) {
+  _nativeNonNullAsserts = enable;
+}
+
 final metadata = JS('', 'Symbol("metadata")');
 
 /// Types in dart are represented internally at runtime as follows.
@@ -168,7 +177,7 @@
 /// we disable type checks for in these cases, and allow any JS object to work
 /// as if it were an instance of this JS type.
 class LazyJSType extends DartType {
-  Function()? _getRawJSTypeFn;
+  Function() _getRawJSTypeFn;
   @notNull
   final String _dartName;
   Object? _rawJSType;
@@ -190,14 +199,14 @@
     // overhead, especially if exceptions are being thrown. Also it means the
     // behavior of a given type check can change later on.
     try {
-      raw = _getRawJSTypeFn!();
+      raw = _getRawJSTypeFn();
     } catch (e) {}
 
     if (raw == null) {
       _warn('Cannot find native JavaScript type ($_dartName) for type check');
     } else {
       _rawJSType = raw;
-      _getRawJSTypeFn = null; // Free the function that computes the JS type.
+      JS('', '#.push(() => # = null)', _resetFields, _rawJSType);
     }
     return raw;
   }
@@ -369,7 +378,7 @@
   NullableType(@notNull this.type);
 
   @override
-  String get name => '$type?';
+  String get name => _jsInstanceOf(type, FunctionType) ? '($type)?' : '$type?';
 
   @override
   String toString() => name;
diff --git a/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
index 7f11505..6551c93 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/foreign_helper.dart
@@ -259,15 +259,6 @@
   const JS_CONST(this.code);
 }
 
-/**
- * JavaScript string concatenation. Inputs must be Strings.  Corresponds to the
- * HStringConcat SSA instruction and may be constant-folded.
- */
-String JS_STRING_CONCAT(String a, String b) {
-  // This body is unused, only here for type analysis.
-  return JS<String>('!', '# + #', a, b);
-}
-
 /// Same `@rest` annotation and `spread` function as in
 /// `package:js/src/varargs.dart`.
 ///
diff --git a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
index 11a3a8e..772263c 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/js_helper.dart
@@ -6,7 +6,7 @@
 
 import 'dart:collection';
 
-import 'dart:_foreign_helper' show JS, JS_STRING_CONCAT, JSExportName;
+import 'dart:_foreign_helper' show JS, JSExportName;
 
 import 'dart:_interceptors';
 import 'dart:_internal'
@@ -70,9 +70,9 @@
 class Primitives {
   static int? parseInt(@nullCheck String source, int? _radix) {
     var re = JS('', r'/^\s*[+-]?((0x[a-f0-9]+)|(\d+)|([a-z0-9]+))\s*$/i');
-    // TODO(jmesserly): this isn't reified List<String>, but it's safe to use as
-    // long as we use it locally and don't expose it to user code.
-    List<String>? match = JS('', '#.exec(#)', re, source);
+    // This isn't reified List<String?>?, but it's safe to use as long as we use
+    // it locally and don't expose it to user code.
+    var match = JS<List<String?>?>('', '#.exec(#)', re, source);
     int digitsIndex = 1;
     int hexIndex = 2;
     int decimalIndex = 3;
@@ -82,7 +82,7 @@
       // again.
       return null;
     }
-    String? decimalMatch = match[decimalIndex];
+    var decimalMatch = match[decimalIndex];
     if (_radix == null) {
       if (decimalMatch != null) {
         // Cannot fail because we know that the digits are all decimal.
@@ -295,10 +295,6 @@
     throw RangeError.range(charCode, 0, 0x10ffff);
   }
 
-  static String stringConcatUnchecked(String string1, String string2) {
-    return JS_STRING_CONCAT(string1, string2);
-  }
-
   static String flattenString(String str) {
     return JS<String>('!', "#.charCodeAt(0) == 0 ? # : #", str, str, str);
   }
@@ -308,13 +304,17 @@
     // Example: "Wed May 16 2012 21:13:00 GMT+0200 (CEST)".
     // We extract this name using a regexp.
     var d = lazyAsJsDate(receiver);
-    List? match = JS('JSArray|Null', r'/\((.*)\)/.exec(#.toString())', d);
+    // In this method all calls to `exec()` include a single capture group and
+    // it is only read if there is a match so a value will be present. To avoid
+    // extra null checks or casts from dynamic we type the return type of
+    // `exec()` to always contain non-nullable Strings.
+    var match = JS<List<String>?>('', r'/\((.*)\)/.exec(#.toString())', d);
     if (match != null) return match[1];
 
     // Internet Explorer 10+ emits the zone name without parenthesis:
     // Example: Thu Oct 31 14:07:44 PDT 2013
-    match = JS(
-        'JSArray|Null',
+    match = JS<List<String>?>(
+        '',
         // Thu followed by a space.
         r'/^[A-Z,a-z]{3}\s'
             // Oct 31 followed by space.
@@ -333,7 +333,8 @@
     // UTC/GMT offset.
     // Example (IE9): Wed Nov 20 09:51:00 UTC+0100 2013
     //       (Opera): Wed Nov 20 2013 11:03:38 GMT+0100
-    match = JS('JSArray|Null', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d);
+    match =
+        JS<List<String>?>('', r'/(?:GMT|UTC)[+-]\d{4}/.exec(#.toString())', d);
     if (match != null) return match[0];
     return "";
   }
@@ -354,6 +355,14 @@
       @nullCheck bool isUtc) {
     final int MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
     var jsMonth = month - 1;
+    // The JavaScript Date constructor 'corrects' year NN to 19NN. Sidestep that
+    // correction by adjusting years out of that range and compensating with an
+    // adjustment of months. This hack should not be sensitive to leap years but
+    // use 400 just in case.
+    if (0 <= years && years < 100) {
+      years += 400;
+      jsMonth -= 400 * 12;
+    }
     int value;
     if (isUtc) {
       value = JS<int>('!', r'Date.UTC(#, #, #, #, #, #, #)', years, jsMonth,
diff --git a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
index 6ce53ac..73f95fb 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/regexp_helper.dart
@@ -116,8 +116,9 @@
   }
 
   RegExpMatch? firstMatch(@nullCheck String string) {
-    List<String>? m =
-        JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, string);
+    // This isn't reified List<String?>?, but it's safe to use as long as we use
+    // it locally and don't expose it to user code.
+    var m = JS<List<String?>?>('', r'#.exec(#)', _nativeRegExp, string);
     if (m == null) return null;
     return _MatchImplementation(this, m);
   }
@@ -144,8 +145,9 @@
   RegExpMatch? _execGlobal(String string, int start) {
     Object regexp = _nativeGlobalVersion;
     JS("void", "#.lastIndex = #", regexp, start);
-    List<String>? match =
-        JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
+    // This isn't reified List<String?>?, but it's safe to use as long as we use
+    // it locally and don't expose it to user code.
+    var match = JS<List<String?>?>("", "#.exec(#)", regexp, string);
     if (match == null) return null;
     return _MatchImplementation(this, match);
   }
@@ -153,8 +155,9 @@
   RegExpMatch? _execAnchored(String string, int start) {
     Object regexp = _nativeAnchoredVersion;
     JS("void", "#.lastIndex = #", regexp, start);
-    List<String>? match =
-        JS("JSExtendableArray|Null", "#.exec(#)", regexp, string);
+    // This isn't reified List<String?>?, but it's safe to use as long as we use
+    // it locally and don't expose it to user code.
+    var match = JS<List<String?>?>("", "#.exec(#)", regexp, string);
     if (match == null) return null;
     // If the last capture group participated, the original regexp did not
     // match at the start position.
@@ -178,9 +181,12 @@
 
 class _MatchImplementation implements RegExpMatch {
   final Pattern pattern;
-  // Contains a JS RegExp match object.
-  // It is an Array of String values with extra "index" and "input" properties.
-  final List<String> _match;
+  // Contains a JS RegExp match object that is an Array with extra "index" and
+  // "input" properties. The array contains Strings but the values at indices
+  // related to capture groups can be undefined.
+  // This isn't reified List<String?>, but it's safe to use as long as we use
+  // it locally and don't expose it to user code.
+  final List<String?> _match;
 
   _MatchImplementation(this.pattern, this._match) {
     assert(JS("var", "#.input", _match) is String);
@@ -189,7 +195,7 @@
 
   String get input => JS("String", "#.input", _match);
   int get start => JS("int", "#.index", _match);
-  int get end => start + _match[0].length;
+  int get end => start + _match[0]!.length;
 
   String? group(int index) => _match[index];
   String? operator [](int index) => group(index);
diff --git a/sdk/lib/_internal/js_runtime/lib/async_patch.dart b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
index 4faeb51..9c09d3d 100644
--- a/sdk/lib/_internal/js_runtime/lib/async_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/async_patch.dart
@@ -228,6 +228,7 @@
 /// Creates a Completer for an `async` function.
 ///
 /// Used as part of the runtime support for the async/await transformation.
+@pragma('dart2js:assumeDynamic') // Global type inference can't see call site.
 Completer<T> _makeAsyncAwaitCompleter<T>() {
   return new _AsyncAwaitCompleter<T>();
 }
@@ -524,6 +525,7 @@
 /// Creates a stream controller for an `async*` function.
 ///
 /// Used as part of the runtime support for the async/await transformation.
+@pragma('dart2js:assumeDynamic') // Global type inference can't see call site.
 _makeAsyncStarStreamController<T>(_WrappedAsyncBody body) {
   return new _AsyncStarStreamController<T>(body);
 }
@@ -681,6 +683,7 @@
 /// Creates an Iterable for a `sync*` function.
 ///
 /// Used as part of the runtime support for the async/await transformation.
+@pragma('dart2js:assumeDynamic') // Global type inference can't see call site.
 _SyncStarIterable<T> _makeSyncStarIterable<T>(body) {
   return new _SyncStarIterable<T>(body);
 }
diff --git a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
index 88ca3d2..3c9aed9 100644
--- a/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/foreign_helper.dart
@@ -277,3 +277,11 @@
   // This body is unused, only here for type analysis.
   return JS('String', '# + #', a, b);
 }
+
+/// Creates a JavaScript value that can be used as a sentinel for uninitialized
+/// late fields and variables.
+external T createJsSentinel<T>();
+
+/// Returns `true` if [value] is the sentinel JavaScript value created through
+/// [createJsSentinel].
+external bool isJsSentinel(dynamic value);
diff --git a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
index 2dc838d..9bf6da6 100644
--- a/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/internal_patch.dart
@@ -7,7 +7,8 @@
 import 'dart:_js_primitives' show printString;
 import 'dart:_js_helper' show patch;
 import 'dart:_interceptors' show JSArray;
-import 'dart:_foreign_helper' show JS, JS_GET_FLAG;
+import 'dart:_foreign_helper'
+    show JS, JS_GET_FLAG, createJsSentinel, isJsSentinel;
 
 @patch
 @pragma('dart2js:tryInline')
@@ -64,3 +65,11 @@
   // the returned value flows to the result of extractTypeArguments.
   return extract();
 }
+
+@patch
+@pragma('dart2js:tryInline')
+T createSentinel<T>() => createJsSentinel<T>();
+
+@patch
+@pragma('dart2js:tryInline')
+bool isSentinel(dynamic value) => isJsSentinel(value);
diff --git a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
index 4c7f5c5..228fc3a 100644
--- a/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/isolate_patch.dart
@@ -41,7 +41,8 @@
       {bool paused = false,
       bool errorsAreFatal = true,
       SendPort? onExit,
-      SendPort? onError}) {
+      SendPort? onError,
+      String? debugName}) {
     throw new UnsupportedError("Isolate.spawn");
   }
 
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index b1a7f44..542f18b 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -48,6 +48,7 @@
 import 'dart:_internal'
     show
         EfficientLengthIterable,
+        LateInitializationErrorImpl,
         MappedIterable,
         IterableElementError,
         SubListIterable;
@@ -2415,22 +2416,28 @@
         "${Primitives.objectToHumanReadableString(receiver)}";
   }
 
+  @pragma('dart2js:parameter:trust')
   static evalRecipe(BoundClosure closure, String recipe) {
     return newRti.evalInInstance(closure._self, recipe);
   }
 
+  @pragma('dart2js:parameter:trust')
   static evalRecipeIntercepted(BoundClosure closure, String recipe) {
     return newRti.evalInInstance(closure._receiver, recipe);
   }
 
   @pragma('dart2js:noInline')
+  @pragma('dart2js:parameter:trust')
   static selfOf(BoundClosure closure) => closure._self;
 
+  @pragma('dart2js:parameter:trust')
   static targetOf(BoundClosure closure) => closure._target;
 
   @pragma('dart2js:noInline')
+  @pragma('dart2js:parameter:trust')
   static receiverOf(BoundClosure closure) => closure._receiver;
 
+  @pragma('dart2js:parameter:trust')
   static nameOf(BoundClosure closure) => closure._name;
 
   static String? selfFieldNameCache;
@@ -3017,3 +3024,7 @@
 
 const kRequiredSentinel = const _Required();
 bool isRequired(Object? value) => identical(kRequiredSentinel, value);
+
+/// Called by generated code to throw a LateInitializationError.
+void throwLateInitializationError(String name) =>
+    throw LateInitializationErrorImpl(name);
diff --git a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
index 6e19c50..6a7b7b3 100644
--- a/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
+++ b/sdk/lib/_internal/js_runtime/lib/native_typed_data.dart
@@ -1297,7 +1297,7 @@
   /// Extract the sign bit from each lane return them in the first 4 bits.
   int get signMask {
     var view = _uint32view;
-    var mx, my, mz, mw;
+    int mx, my, mz, mw;
     _list[0] = x;
     _list[1] = y;
     _list[2] = z;
diff --git a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
index 4f182d0..16ab9b0 100644
--- a/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/regexp_helper.dart
@@ -249,7 +249,7 @@
 
   _AllMatchesIterator(this._regExp, this._string, this._nextIndex);
 
-  RegExpMatch get current => _current!;
+  RegExpMatch get current => _current as RegExpMatch;
 
   static bool _isLeadSurrogate(int c) {
     return c >= 0xd800 && c <= 0xdbff;
diff --git a/sdk/lib/_internal/js_runtime/lib/rti.dart b/sdk/lib/_internal/js_runtime/lib/rti.dart
index 2f59b9d..376e39a 100644
--- a/sdk/lib/_internal/js_runtime/lib/rti.dart
+++ b/sdk/lib/_internal/js_runtime/lib/rti.dart
@@ -935,9 +935,11 @@
 
 bool _nullIs(Rti testRti) {
   int kind = Rti._getKind(testRti);
-  return isTopType(testRti) ||
+  return isStrongTopType(testRti) ||
+      isLegacyObjectType(testRti) ||
       _Utils.isIdentical(testRti, LEGACY_TYPE_REF<Never>()) ||
       kind == Rti.kindQuestion ||
+      kind == Rti.kindFutureOr && _nullIs(Rti._getFutureOrArgument(testRti)) ||
       isNullType(testRti);
 }
 
@@ -1068,7 +1070,7 @@
 /// Specialization for 'is Object'.
 /// Called from generated code via Rti `_is` method.
 bool _isObject(Object? object) {
-  return !JS_GET_FLAG('NNBD') || object != null;
+  return object != null;
 }
 
 /// Specialization for 'as Object'.
@@ -1890,9 +1892,7 @@
       } else if (baseKind == Rti.kindNever) {
         return _lookupFutureRti(universe, baseType);
       } else if (isNullType(baseType)) {
-        return JS_GET_FLAG('NNBD')
-            ? TYPE_REF<Future<Null>?>()
-            : TYPE_REF<Future<Null>>();
+        return TYPE_REF<Future<Null>?>();
       }
     }
     Rti rti = Rti.allocate();
diff --git a/sdk/lib/_internal/js_runtime/pubspec.yaml b/sdk/lib/_internal/js_runtime/pubspec.yaml
index 96abf65..f42b2cd 100644
--- a/sdk/lib/_internal/js_runtime/pubspec.yaml
+++ b/sdk/lib/_internal/js_runtime/pubspec.yaml
@@ -2,5 +2,3 @@
 # make it easier to develop on dart2js.
 name: js_runtime
 publish_to: none
-environment:
-  sdk: '>=2.10.0-0.0 <3.0.0'
diff --git a/sdk/lib/_internal/sdk_library_metadata/pubspec.yaml b/sdk/lib/_internal/sdk_library_metadata/pubspec.yaml
index 8f46e53..79b69ee 100644
--- a/sdk/lib/_internal/sdk_library_metadata/pubspec.yaml
+++ b/sdk/lib/_internal/sdk_library_metadata/pubspec.yaml
@@ -2,5 +2,3 @@
 # make it easer to depend on libraries.dart from sdk packages like dart2js.
 name: sdk_library_metadata
 publish_to: none
-environment:
-  sdk: '>=2.10.0-0.0 <3.0.0'
diff --git a/sdk/lib/_internal/vm/bin/process_patch.dart b/sdk/lib/_internal/vm/bin/process_patch.dart
index bb86a0d..97426b8 100644
--- a/sdk/lib/_internal/vm/bin/process_patch.dart
+++ b/sdk/lib/_internal/vm/bin/process_patch.dart
@@ -225,10 +225,10 @@
     ArgumentError.checkNotNull(_mode, "mode");
 
     if (!connectedResourceHandler) {
-      registerExtension(
-          'ext.dart.io.getProcesses', _ProcessResourceInfo.getStartedProcesses);
-      registerExtension('ext.dart.io.getProcessById',
-          _ProcessResourceInfo.getProcessInfoMapById);
+      registerExtension('ext.dart.io.getSpawnedProcesses',
+          _SpawnedProcessResourceInfo.getStartedProcesses);
+      registerExtension('ext.dart.io.getSpawnedProcessById',
+          _SpawnedProcessResourceInfo.getProcessInfoMapById);
       connectedResourceHandler = true;
     }
 
@@ -413,7 +413,7 @@
       }
 
       _started = true;
-      final resourceInfo = new _ProcessResourceInfo(this);
+      final resourceInfo = new _SpawnedProcessResourceInfo(this);
 
       // Setup an exit handler to handle internal cleanup and possible
       // callback when a process terminates.
@@ -474,7 +474,7 @@
           _path, _arguments, status._errorMessage!, status._errorCode!);
     }
 
-    final resourceInfo = new _ProcessResourceInfo(this);
+    final resourceInfo = new _SpawnedProcessResourceInfo(this);
 
     var result = _wait(_stdinNativeSocket, _stdoutNativeSocket,
         _stderrNativeSocket, _exitHandler._nativeSocket);
diff --git a/sdk/lib/_internal/vm/bin/secure_socket_patch.dart b/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
index 9a0586d..5989763 100644
--- a/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/secure_socket_patch.dart
@@ -98,7 +98,61 @@
 
   void _destroy() native "SecureSocket_Destroy";
 
-  void handshake() native "SecureSocket_Handshake";
+  int _handshake(SendPort replyPort) native "SecureSocket_Handshake";
+
+  void _markAsTrusted(int certificatePtr, bool isTrusted)
+      native "SecureSocket_MarkAsTrusted";
+
+  static X509Certificate _newX509CertificateWrapper(int certificatePtr)
+      native "SecureSocket_NewX509CertificateWrapper";
+
+  Future<bool> handshake() {
+    Completer<bool> evaluatorCompleter = Completer<bool>();
+
+    ReceivePort rpEvaluateResponse = ReceivePort();
+    rpEvaluateResponse.listen((data) {
+      List list = data as List;
+      // incoming messages (bool isTrusted, int certificatePtr) is
+      // sent by TrustEvaluator native port after system evaluates
+      // the certificate chain
+      if (list.length != 2) {
+        throw Exception("Invalid number of arguments in evaluate response");
+      }
+      bool isTrusted = list[0] as bool;
+      int certificatePtr = list[1] as int;
+      if (!isTrusted) {
+        if (badCertificateCallback != null) {
+          try {
+            isTrusted = badCertificateCallback!(
+                _newX509CertificateWrapper(certificatePtr));
+          } catch (e, st) {
+            evaluatorCompleter.completeError(e, st);
+            rpEvaluateResponse.close();
+            return;
+          }
+        }
+      }
+      _markAsTrusted(certificatePtr, isTrusted);
+      evaluatorCompleter.complete(true);
+      rpEvaluateResponse.close();
+    });
+
+    const int kSslErrorWantCertificateVerify = 16; // ssl.h:558
+    int handshakeResult;
+    try {
+      handshakeResult = _handshake(rpEvaluateResponse.sendPort);
+    } catch (e, st) {
+      rpEvaluateResponse.close();
+      rethrow;
+    }
+    if (handshakeResult == kSslErrorWantCertificateVerify) {
+      return evaluatorCompleter.future;
+    } else {
+      // Response is ready, no need for evaluate response receive port
+      rpEvaluateResponse.close();
+      return Future<bool>.value(false);
+    }
+  }
 
   void rehandshake() => throw new UnimplementedError();
 
@@ -113,9 +167,16 @@
 
   X509Certificate? get peerCertificate native "SecureSocket_PeerCertificate";
 
-  void registerBadCertificateCallback(Function callback)
+  void _registerBadCertificateCallback(Function callback)
       native "SecureSocket_RegisterBadCertificateCallback";
 
+  Function? badCertificateCallback;
+
+  void registerBadCertificateCallback(Function callback) {
+    badCertificateCallback = callback;
+    _registerBadCertificateCallback(callback);
+  }
+
   void registerHandshakeCompleteCallback(Function handshakeCompleteHandler)
       native "SecureSocket_RegisterHandshakeCompleteCallback";
 
@@ -205,7 +266,7 @@
 class _X509CertificateImpl extends NativeFieldWrapperClass1
     implements X509Certificate {
   // The native field must be set manually on a new object, in native code.
-  // This is done by WrappedX509 in secure_socket.cc.
+  // This is done by WrappedX509Certificate in security_context.cc.
   _X509CertificateImpl._();
 
   Uint8List get _der native "X509_Der";
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index abd886f..976b1f1 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -487,9 +487,6 @@
   bool writeEventIssued = false;
   bool writeAvailable = false;
 
-  static bool connectedResourceHandler = false;
-  _SocketResourceInfo? resourceInfo;
-
   // The owner object is the object that the Socket is being used by, e.g.
   // a HttpServer, a WebSocket connection, a process pipe, etc.
   Object? owner;
@@ -658,7 +655,6 @@
           var duration =
               address.isLoopback ? _retryDurationLoopback : _retryDuration;
           var timer = new Timer(duration, connectNext);
-          setupResourceInfo(socket);
 
           connecting[socket] = timer;
           // Setup handlers for receiving the first write event which
@@ -775,15 +771,10 @@
           osError: result, address: address, port: port);
     }
     if (port != 0) socket.localPort = port;
-    setupResourceInfo(socket);
     socket.connectToEventHandler();
     return socket;
   }
 
-  static void setupResourceInfo(_NativeSocket socket) {
-    socket.resourceInfo = new _SocketResourceInfo(socket);
-  }
-
   static Future<_NativeSocket> bindDatagram(
       host, int port, bool reuseAddress, bool reusePort, int ttl) async {
     _throwOnBadPort(port);
@@ -799,7 +790,6 @@
           osError: result, address: address, port: port);
     }
     if (port != 0) socket.localPort = port;
-    setupResourceInfo(socket);
     return socket;
   }
 
@@ -868,19 +858,6 @@
           list = builder.toBytes();
         }
       }
-      final resourceInformation = resourceInfo;
-      assert(resourceInformation != null ||
-          isPipe ||
-          isInternal ||
-          isInternalSignal);
-      if (list != null) {
-        if (resourceInformation != null) {
-          resourceInformation.totalRead += list.length;
-        }
-      }
-      if (resourceInformation != null) {
-        resourceInformation.didRead();
-      }
       if (!const bool.fromEnvironment("dart.vm.product")) {
         _SocketProfile.collectStatistic(
             nativeGetSocketId(), _SocketProfileType.readBytes, list?.length);
@@ -896,16 +873,6 @@
     if (isClosing || isClosed) return null;
     try {
       Datagram? result = nativeRecvFrom();
-      if (result != null) {
-        final resourceInformation = resourceInfo;
-        if (resourceInformation != null) {
-          resourceInformation.totalRead += result.data.length;
-        }
-      }
-      final resourceInformation = resourceInfo;
-      if (resourceInformation != null) {
-        resourceInformation.didRead();
-      }
       if (!const bool.fromEnvironment("dart.vm.product")) {
         _SocketProfile.collectStatistic(nativeGetSocketId(),
             _SocketProfileType.readBytes, result?.data.length);
@@ -955,14 +922,6 @@
       }
       // Negate the result, as stated above.
       if (result < 0) result = -result;
-      final resourceInformation = resourceInfo;
-      assert(resourceInformation != null ||
-          isPipe ||
-          isInternal ||
-          isInternalSignal);
-      if (resourceInformation != null) {
-        resourceInformation.addWrite(result);
-      }
       return result;
     } catch (e) {
       StackTrace st = StackTrace.current;
@@ -986,14 +945,6 @@
       }
       int result = nativeSendTo(bufferAndStart.buffer, bufferAndStart.start,
           bytes, (address as _InternetAddress)._in_addr, port);
-      final resourceInformation = resourceInfo;
-      assert(resourceInformation != null ||
-          isPipe ||
-          isInternal ||
-          isInternalSignal);
-      if (resourceInformation != null) {
-        resourceInformation.addWrite(result);
-      }
       return result;
     } catch (e) {
       StackTrace st = StackTrace.current;
@@ -1012,16 +963,6 @@
     var socket = new _NativeSocket.normal(address);
     if (nativeAccept(socket) != true) return null;
     socket.localPort = localPort;
-    setupResourceInfo(socket);
-    final resourceInformation = resourceInfo;
-    assert(resourceInformation != null ||
-        isPipe ||
-        isInternal ||
-        isInternalSignal);
-    if (resourceInformation != null) {
-      // We track this as read one byte.
-      resourceInformation.addRead(1);
-    }
     return socket;
   }
 
@@ -1149,14 +1090,6 @@
         if (i == destroyedEvent) {
           assert(isClosing);
           assert(!isClosed);
-          final resourceInformation = resourceInfo;
-          assert(resourceInformation != null ||
-              isPipe ||
-              isInternal ||
-              isInternalSignal);
-          if (resourceInformation != null) {
-            _SocketResourceInfo.SocketClosed(resourceInformation);
-          }
           isClosed = true;
           closeCompleter.complete();
           disconnectFromEventHandler();
@@ -1275,14 +1208,6 @@
     if (eventPort == null) {
       eventPort = new RawReceivePort(multiplex);
     }
-    if (!connectedResourceHandler) {
-      registerExtension(
-          'ext.dart.io.getOpenSockets', _SocketResourceInfo.getOpenSockets);
-      registerExtension('ext.dart.io.getSocketByID',
-          _SocketResourceInfo.getSocketInfoMapByID);
-
-      connectedResourceHandler = true;
-    }
   }
 
   void disconnectFromEventHandler() {
diff --git a/sdk/lib/_internal/vm/bin/sync_socket_patch.dart b/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
index f602449..6554c11 100644
--- a/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/sync_socket_patch.dart
@@ -60,9 +60,6 @@
   // Holds the port of the socket, 0 if not known.
   int localPort = 0;
 
-  // Always set by setupResourceInfo called by connectSync.
-  late _SocketResourceInfo resourceInfo;
-
   static _NativeSynchronousSocket connectSync(host, int port) {
     if (host == null) {
       throw new ArgumentError("Parameter host cannot be null");
@@ -108,7 +105,6 @@
           }
           return connectNext();
         }
-        setupResourceInfo(socket);
       }
       return socket;
     }
@@ -164,7 +160,6 @@
   void closeSync() {
     if (!isClosed) {
       _nativeCloseSync();
-      _SocketResourceInfo.SocketClosed(resourceInfo);
       isClosed = true;
     }
   }
@@ -210,7 +205,6 @@
     if (result is OSError) {
       throw new SocketException("readIntoSync failed", osError: result);
     }
-    resourceInfo.addRead(result);
     return result;
   }
 
@@ -230,17 +224,9 @@
     if (result is OSError) {
       throw result;
     }
-    if (result is List<int>) {
-      resourceInfo.totalRead += result.length;
-    }
-    resourceInfo.didRead();
     return result;
   }
 
-  static void setupResourceInfo(_NativeSynchronousSocket socket) {
-    socket.resourceInfo = new _SocketResourceInfo(socket);
-  }
-
   void shutdown(SocketDirection direction) {
     if (isClosed) {
       return;
@@ -303,7 +289,6 @@
     if (result is OSError) {
       throw new SocketException("writeFromSync failed", osError: result);
     }
-    resourceInfo.addWrite(result);
   }
 
   void _checkAvailable() {
diff --git a/sdk/lib/_internal/vm/bin/vmservice_server.dart b/sdk/lib/_internal/vm/bin/vmservice_server.dart
index 383b19b..69aa7f8 100644
--- a/sdk/lib/_internal/vm/bin/vmservice_server.dart
+++ b/sdk/lib/_internal/vm/bin/vmservice_server.dart
@@ -369,11 +369,8 @@
           WebSocketClient(webSocket, _service);
         });
       } else {
-        request.response.statusCode = HttpStatus.forbidden;
-        request.response.write('Cannot connect directly to the VM service as '
-            'a Dart Development Service (DDS) instance has taken control and '
-            'can be found at ${_service.ddsUri}.');
-        request.response.close();
+        // Attempt to redirect client to the DDS instance.
+        request.response.redirect(_service.ddsUri!);
       }
       return;
     }
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index fa16bc6..812f18f 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -188,3 +188,9 @@
   // This function can be used by tests to enforce garbage collection.
   static void collectAllGarbage() native "Internal_collectAllGarbage";
 }
+
+@patch
+T createSentinel<T>() => throw UnsupportedError('createSentinel');
+
+@patch
+bool isSentinel(dynamic value) => throw UnsupportedError('isSentinel');
diff --git a/sdk/lib/_internal/vm/lib/regexp_patch.dart b/sdk/lib/_internal/vm/lib/regexp_patch.dart
index 7a57583..153080b 100644
--- a/sdk/lib/_internal/vm/lib/regexp_patch.dart
+++ b/sdk/lib/_internal/vm/lib/regexp_patch.dart
@@ -376,7 +376,7 @@
 
   _AllMatchesIterator(this._re, this._str, this._nextIndex);
 
-  RegExpMatch get current => _current!;
+  RegExpMatch get current => _current as RegExpMatch;
 
   static bool _isLeadSurrogate(int c) {
     return c >= 0xd800 && c <= 0xdbff;
diff --git a/sdk/lib/_internal/vm/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
index 6d0cc5a..ccd3183 100644
--- a/sdk/lib/_internal/vm/lib/typed_data_patch.dart
+++ b/sdk/lib/_internal/vm/lib/typed_data_patch.dart
@@ -2146,6 +2146,7 @@
 class Int8List {
   @patch
   @pragma("vm:exact-result-type", _Int8List)
+  @pragma("vm:prefer-inline")
   factory Int8List(int length) native "TypedData_Int8Array_new";
 
   @patch
@@ -2194,6 +2195,7 @@
 class Uint8List {
   @patch
   @pragma("vm:exact-result-type", _Uint8List)
+  @pragma("vm:prefer-inline")
   factory Uint8List(int length) native "TypedData_Uint8Array_new";
 
   @patch
@@ -2242,6 +2244,7 @@
 class Uint8ClampedList {
   @patch
   @pragma("vm:exact-result-type", _Uint8ClampedList)
+  @pragma("vm:prefer-inline")
   factory Uint8ClampedList(int length) native "TypedData_Uint8ClampedArray_new";
 
   @patch
@@ -2290,6 +2293,7 @@
 class Int16List {
   @patch
   @pragma("vm:exact-result-type", _Int16List)
+  @pragma("vm:prefer-inline")
   factory Int16List(int length) native "TypedData_Int16Array_new";
 
   @patch
@@ -2358,6 +2362,7 @@
 class Uint16List {
   @patch
   @pragma("vm:exact-result-type", _Uint16List)
+  @pragma("vm:prefer-inline")
   factory Uint16List(int length) native "TypedData_Uint16Array_new";
 
   @patch
@@ -2426,6 +2431,7 @@
 class Int32List {
   @patch
   @pragma("vm:exact-result-type", _Int32List)
+  @pragma("vm:prefer-inline")
   factory Int32List(int length) native "TypedData_Int32Array_new";
 
   @patch
@@ -2481,6 +2487,7 @@
 class Uint32List {
   @patch
   @pragma("vm:exact-result-type", _Uint32List)
+  @pragma("vm:prefer-inline")
   factory Uint32List(int length) native "TypedData_Uint32Array_new";
 
   @patch
@@ -2536,6 +2543,7 @@
 class Int64List {
   @patch
   @pragma("vm:exact-result-type", _Int64List)
+  @pragma("vm:prefer-inline")
   factory Int64List(int length) native "TypedData_Int64Array_new";
 
   @patch
@@ -2591,6 +2599,7 @@
 class Uint64List {
   @patch
   @pragma("vm:exact-result-type", _Uint64List)
+  @pragma("vm:prefer-inline")
   factory Uint64List(int length) native "TypedData_Uint64Array_new";
 
   @patch
@@ -2646,6 +2655,7 @@
 class Float32List {
   @patch
   @pragma("vm:exact-result-type", _Float32List)
+  @pragma("vm:prefer-inline")
   factory Float32List(int length) native "TypedData_Float32Array_new";
 
   @patch
@@ -2702,6 +2712,7 @@
 class Float64List {
   @patch
   @pragma("vm:exact-result-type", _Float64List)
+  @pragma("vm:prefer-inline")
   factory Float64List(int length) native "TypedData_Float64Array_new";
 
   @patch
@@ -2758,6 +2769,7 @@
 class Float32x4List {
   @patch
   @pragma("vm:exact-result-type", _Float32x4List)
+  @pragma("vm:prefer-inline")
   factory Float32x4List(int length) native "TypedData_Float32x4Array_new";
 
   @patch
@@ -2813,6 +2825,7 @@
 class Int32x4List {
   @patch
   @pragma("vm:exact-result-type", _Int32x4List)
+  @pragma("vm:prefer-inline")
   factory Int32x4List(int length) native "TypedData_Int32x4Array_new";
 
   @patch
@@ -2868,6 +2881,7 @@
 class Float64x2List {
   @patch
   @pragma("vm:exact-result-type", _Float64x2List)
+  @pragma("vm:prefer-inline")
   factory Float64x2List(int length) native "TypedData_Float64x2Array_new";
 
   @patch
diff --git a/sdk/lib/async/future.dart b/sdk/lib/async/future.dart
index bb6ed77..0e1d703 100644
--- a/sdk/lib/async/future.dart
+++ b/sdk/lib/async/future.dart
@@ -433,7 +433,7 @@
         remaining++;
       }
       if (remaining == 0) {
-        return new Future<List<T>>.value(const <Never>[]);
+        return _future.._completeWithValue(<T>[]);
       }
       values = new List<T?>.filled(remaining, null);
     } catch (e, st) {
diff --git a/sdk/lib/async/stream.dart b/sdk/lib/async/stream.dart
index 76ced6e..150a759 100644
--- a/sdk/lib/async/stream.dart
+++ b/sdk/lib/async/stream.dart
@@ -483,11 +483,13 @@
    * On errors from this stream, the [onError] handler is called with the
    * error object and possibly a stack trace.
    *
-   * The [onError] callback must be of type `void onError(Object error)` or
-   * `void onError(Object error, StackTrace stackTrace)`. If [onError] accepts
-   * two arguments it is called with the error object and the stack trace
-   * (which could be `null` if this stream itself received an error without
-   * stack trace).
+   * The [onError] callback must be of type `void Function(Object error)` or
+   * `void Function(Object error, StackTrace)`.
+   * The function type determines whether [onError] is invoked with a stack
+   * trace argument.
+   * The stack trace argument may be [StackTrace.empty] if this stream received
+   * an error without a stack trace.
+   *
    * Otherwise it is called with just the error object.
    * If [onError] is omitted, any errors on this stream are considered unhandled,
    * and will be passed to the current [Zone]'s error handler.
@@ -667,12 +669,12 @@
    * If this stream sends an error that matches [test], then it is intercepted
    * by the [onError] function.
    *
-   * The [onError] callback must be of type `void onError(Object error)` or
-   * `void onError(Object error, StackTrace stackTrace)`.
+   * The [onError] callback must be of type `void Function(Object error)` or
+   * `void Function(Object error, StackTrace)`.
    * The function type determines whether [onError] is invoked with a stack
    * trace argument.
-   * The stack trace argument may be `null` if this stream received an error
-   * without a stack trace.
+   * The stack trace argument may be [StackTrace.empty] if this stream received
+   * an error without a stack trace.
    *
    * An asynchronous error `error` is matched by a test function if
    *`test(error)` returns true. If [test] is omitted, every error is considered
diff --git a/sdk/lib/collection/set.dart b/sdk/lib/collection/set.dart
index 1eb7491..0a6ccbf 100644
--- a/sdk/lib/collection/set.dart
+++ b/sdk/lib/collection/set.dart
@@ -294,7 +294,7 @@
 /// Implementations of `Set` using this base should consider also implementing
 /// `clear` in constant time. The default implementation works by removing every
 /// element.
-abstract class SetBase<E> extends Object with SetMixin<E> {
+abstract class SetBase<E> with SetMixin<E> {
   /// Converts a [Set] to a [String].
   ///
   /// Converts [set] to a string by converting each element to a string (by
@@ -308,10 +308,7 @@
 }
 
 /// Common internal implementation of some [Set] methods.
-// TODO(35548): Make this mix-in SetMixin, by adding `with SetMixin<E>`
-// and removing the copied members below,
-// when analyzer supports const constructors for mixin applications.
-abstract class _SetBase<E> implements Set<E> {
+abstract class _SetBase<E> with SetMixin<E> {
   // The following two methods override the ones in SetBase.
   // It's possible to be more efficient if we have a way to create an empty
   // set of the correct type.
@@ -341,228 +338,6 @@
 
   // Subclasses can optimize this further.
   Set<E> toSet() => _newSet()..addAll(this);
-
-  /// TODO(35548): Remove the following declarations again when the analyzer
-  /// supports mixins with const constructors, and mix in `SetMixin` instead.
-
-  bool get isEmpty => length == 0;
-
-  bool get isNotEmpty => length != 0;
-
-  Iterable<E> followedBy(Iterable<E> other) =>
-      FollowedByIterable<E>.firstEfficient(this, other);
-
-  Iterable<T> whereType<T>() => WhereTypeIterable<T>(this);
-
-  void clear() {
-    removeAll(toList());
-  }
-
-  void addAll(Iterable<E> elements) {
-    for (E element in elements) add(element);
-  }
-
-  void removeAll(Iterable<Object?> elements) {
-    for (Object? element in elements) remove(element);
-  }
-
-  void retainAll(Iterable<Object?> elements) {
-    // Create a copy of the set, remove all of elements from the copy,
-    // then remove all remaining elements in copy from this.
-    Set<E> toRemove = toSet();
-    for (Object? o in elements) {
-      toRemove.remove(o);
-    }
-    removeAll(toRemove);
-  }
-
-  void removeWhere(bool test(E element)) {
-    List<Object?> toRemove = [];
-    for (E element in this) {
-      if (test(element)) toRemove.add(element);
-    }
-    removeAll(toRemove);
-  }
-
-  void retainWhere(bool test(E element)) {
-    List<Object?> toRemove = [];
-    for (E element in this) {
-      if (!test(element)) toRemove.add(element);
-    }
-    removeAll(toRemove);
-  }
-
-  bool containsAll(Iterable<Object?> other) {
-    for (Object? o in other) {
-      if (!contains(o)) return false;
-    }
-    return true;
-  }
-
-  Set<E> union(Set<E> other) {
-    return toSet()..addAll(other);
-  }
-
-  List<E> toList({bool growable = true}) =>
-      List<E>.of(this, growable: growable);
-
-  Iterable<T> map<T>(T f(E element)) =>
-      EfficientLengthMappedIterable<E, T>(this, f);
-
-  E get single {
-    if (length > 1) throw IterableElementError.tooMany();
-    Iterator<E> it = iterator;
-    if (!it.moveNext()) throw IterableElementError.noElement();
-    E result = it.current;
-    return result;
-  }
-
-  String toString() => IterableBase.iterableToFullString(this, '{', '}');
-
-  Iterable<E> where(bool f(E element)) => WhereIterable<E>(this, f);
-
-  Iterable<T> expand<T>(Iterable<T> f(E element)) =>
-      ExpandIterable<E, T>(this, f);
-
-  void forEach(void f(E element)) {
-    for (E element in this) f(element);
-  }
-
-  E reduce(E combine(E value, E element)) {
-    Iterator<E> iterator = this.iterator;
-    if (!iterator.moveNext()) {
-      throw IterableElementError.noElement();
-    }
-    E value = iterator.current;
-    while (iterator.moveNext()) {
-      value = combine(value, iterator.current);
-    }
-    return value;
-  }
-
-  T fold<T>(T initialValue, T combine(T previousValue, E element)) {
-    var value = initialValue;
-    for (E element in this) value = combine(value, element);
-    return value;
-  }
-
-  bool every(bool f(E element)) {
-    for (E element in this) {
-      if (!f(element)) return false;
-    }
-    return true;
-  }
-
-  String join([String separator = ""]) {
-    Iterator<E> iterator = this.iterator;
-    if (!iterator.moveNext()) return "";
-    StringBuffer buffer = StringBuffer();
-    if (separator == null || separator == "") {
-      do {
-        buffer.write(iterator.current);
-      } while (iterator.moveNext());
-    } else {
-      buffer.write(iterator.current);
-      while (iterator.moveNext()) {
-        buffer.write(separator);
-        buffer.write(iterator.current);
-      }
-    }
-    return buffer.toString();
-  }
-
-  bool any(bool test(E element)) {
-    for (E element in this) {
-      if (test(element)) return true;
-    }
-    return false;
-  }
-
-  Iterable<E> take(int n) {
-    return TakeIterable<E>(this, n);
-  }
-
-  Iterable<E> takeWhile(bool test(E value)) {
-    return TakeWhileIterable<E>(this, test);
-  }
-
-  Iterable<E> skip(int n) {
-    return SkipIterable<E>(this, n);
-  }
-
-  Iterable<E> skipWhile(bool test(E value)) {
-    return SkipWhileIterable<E>(this, test);
-  }
-
-  E get first {
-    Iterator<E> it = iterator;
-    if (!it.moveNext()) {
-      throw IterableElementError.noElement();
-    }
-    return it.current;
-  }
-
-  E get last {
-    Iterator<E> it = iterator;
-    if (!it.moveNext()) {
-      throw IterableElementError.noElement();
-    }
-    E result;
-    do {
-      result = it.current;
-    } while (it.moveNext());
-    return result;
-  }
-
-  E firstWhere(bool test(E value), {E Function()? orElse}) {
-    for (E element in this) {
-      if (test(element)) return element;
-    }
-    if (orElse != null) return orElse();
-    throw IterableElementError.noElement();
-  }
-
-  E lastWhere(bool test(E value), {E Function()? orElse}) {
-    late E result;
-    bool foundMatching = false;
-    for (E element in this) {
-      if (test(element)) {
-        result = element;
-        foundMatching = true;
-      }
-    }
-    if (foundMatching) return result;
-    if (orElse != null) return orElse();
-    throw IterableElementError.noElement();
-  }
-
-  E singleWhere(bool test(E value), {E Function()? orElse}) {
-    late E result;
-    bool foundMatching = false;
-    for (E element in this) {
-      if (test(element)) {
-        if (foundMatching) {
-          throw IterableElementError.tooMany();
-        }
-        result = element;
-        foundMatching = true;
-      }
-    }
-    if (foundMatching) return result;
-    if (orElse != null) return orElse();
-    throw IterableElementError.noElement();
-  }
-
-  E elementAt(int index) {
-    ArgumentError.checkNotNull(index, "index");
-    RangeError.checkNotNegative(index, "index");
-    int elementIndex = 0;
-    for (E element in this) {
-      if (index == elementIndex) return element;
-      elementIndex++;
-    }
-    throw RangeError.index(index, this, "index", null, elementIndex);
-  }
 }
 
 /// Class used to implement const sets.
diff --git a/sdk/lib/core/iterator.dart b/sdk/lib/core/iterator.dart
index e9a6284..13c76b4 100644
--- a/sdk/lib/core/iterator.dart
+++ b/sdk/lib/core/iterator.dart
@@ -38,7 +38,7 @@
    * Advances the iterator to the next element of the iteration.
    *
    * Should be called before reading [current].
-   * It the call to `moveNext` returns `true`,
+   * If the call to `moveNext` returns `true`,
    * then [current] will contain the next element of the iteration
    * until `moveNext` is called again.
    * If the call returns `false`, there are no further elements
diff --git a/sdk/lib/ffi/annotations.dart b/sdk/lib/ffi/annotations.dart
index f68e525..1a4bcde 100644
--- a/sdk/lib/ffi/annotations.dart
+++ b/sdk/lib/ffi/annotations.dart
@@ -32,6 +32,5 @@
 /// This [NativeType] does not have predefined size.
 ///
 /// Unsized NativeTypes do not support [sizeOf] because their size is unknown.
-/// Consequently, [allocate], [Pointer.load], [Pointer.store], and
-/// [Pointer.elementAt] are not available.
+/// Consequently, [Pointer.elementAt] is not available.
 const unsized = const Unsized();
diff --git a/sdk/lib/ffi/struct.dart b/sdk/lib/ffi/struct.dart
index c6605d8..f4cb315 100644
--- a/sdk/lib/ffi/struct.dart
+++ b/sdk/lib/ffi/struct.dart
@@ -29,7 +29,7 @@
   Struct._fromPointer(this._addressOf);
 }
 
-/// Extension on [Struct] specialized for it's subtypes.
+/// Extension on [Struct] specialized for its subtypes.
 extension StructAddressOf<T extends Struct> on T {
   /// Returns the address backing the reference.
   Pointer<T> get addressOf => _addressOf as Pointer<T>;
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 0d5160f..a79aff6 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -665,7 +665,7 @@
   set effect(AnimationEffectReadOnly? value) native;
 
   Future<Animation> get finished =>
-      promiseToFuture<Animation>(JS("", "#.finished", this));
+      promiseToFuture<Animation>(JS("creates:Animation;", "#.finished", this));
 
   String? get id native;
 
@@ -678,7 +678,7 @@
   set playbackRate(num? value) native;
 
   Future<Animation> get ready =>
-      promiseToFuture<Animation>(JS("", "#.ready", this));
+      promiseToFuture<Animation>(JS("creates:Animation;", "#.ready", this));
 
   num? get startTime native;
 
@@ -1354,13 +1354,18 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture<BackgroundFetchRegistration>(
-        JS("", "#.fetch(#, #, #)", this, id, requests, options_dict));
+    return promiseToFuture<BackgroundFetchRegistration>(JS(
+        "creates:BackgroundFetchRegistration;",
+        "#.fetch(#, #, #)",
+        this,
+        id,
+        requests,
+        options_dict));
   }
 
   Future<BackgroundFetchRegistration> get(String id) =>
       promiseToFuture<BackgroundFetchRegistration>(
-          JS("", "#.get(#)", this, id));
+          JS("creates:BackgroundFetchRegistration;", "#.get(#)", this, id));
 
   Future<List<dynamic>> getIds() =>
       promiseToFuture<List<dynamic>>(JS("", "#.getIds()", this));
@@ -1676,10 +1681,11 @@
 
   Future arrayBuffer() => promiseToFuture(JS("", "#.arrayBuffer()", this));
 
-  Future<Blob> blob() => promiseToFuture<Blob>(JS("", "#.blob()", this));
+  Future<Blob> blob() =>
+      promiseToFuture<Blob>(JS("creates:Blob;", "#.blob()", this));
 
   Future<FormData> formData() =>
-      promiseToFuture<FormData>(JS("", "#.formData()", this));
+      promiseToFuture<FormData>(JS("creates:FormData;", "#.formData()", this));
 
   Future json() => promiseToFuture(JS("", "#.json()", this));
 
@@ -2020,11 +2026,11 @@
       options_dict = convertDartToNative_Dictionary(options);
     }
     return promiseToFuture(
-        JS("", "#.match(#, #)", this, request, options_dict));
+        JS("creates:_Response;", "#.match(#, #)", this, request, options_dict));
   }
 
   Future open(String cacheName) =>
-      promiseToFuture(JS("", "#.open(#)", this, cacheName));
+      promiseToFuture(JS("creates:_Cache;", "#.open(#)", this, cacheName));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3065,8 +3071,8 @@
         JS("", "#.matchAll(#)", this, options_dict));
   }
 
-  Future<WindowClient> openWindow(String url) =>
-      promiseToFuture<WindowClient>(JS("", "#.openWindow(#)", this, url));
+  Future<WindowClient> openWindow(String url) => promiseToFuture<WindowClient>(
+      JS("creates:WindowClient;", "#.openWindow(#)", this, url));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -3318,7 +3324,8 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture(JS("", "#.create(#)", this, options_dict));
+    return promiseToFuture(
+        JS("creates:Credential;", "#.create(#)", this, options_dict));
   }
 
   Future get([Map? options]) {
@@ -3326,7 +3333,8 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture(JS("", "#.get(#)", this, options_dict));
+    return promiseToFuture(
+        JS("creates:Credential;", "#.get(#)", this, options_dict));
   }
 
   Future preventSilentAccess() =>
@@ -3335,8 +3343,8 @@
   Future requireUserMediation() =>
       promiseToFuture(JS("", "#.requireUserMediation()", this));
 
-  Future store(Credential credential) =>
-      promiseToFuture(JS("", "#.store(#)", this, credential));
+  Future store(Credential credential) => promiseToFuture(
+      JS("creates:Credential;", "#.store(#)", this, credential));
 }
 // 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
@@ -13731,7 +13739,7 @@
       contextElement = _parseDocument!.createElement(tagName);
       _parseDocument!.body!.append(contextElement);
     }
-    var fragment;
+    DocumentFragment fragment;
     if (Range.supportsCreateContextualFragment &&
         _canBeUsedToCreateContextualFragment) {
       _parseRange!.selectNodeContents(contextElement);
@@ -16488,7 +16496,7 @@
   set featureSettings(String? value) native;
 
   Future<FontFace> get loaded =>
-      promiseToFuture<FontFace>(JS("", "#.loaded", this));
+      promiseToFuture<FontFace>(JS("creates:FontFace;", "#.loaded", this));
 
   String? get status native;
 
@@ -16513,7 +16521,7 @@
   set weight(String? value) native;
 
   Future<FontFace> load() =>
-      promiseToFuture<FontFace>(JS("", "#.load()", this));
+      promiseToFuture<FontFace>(JS("creates:FontFace;", "#.load()", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -18864,13 +18872,13 @@
 
   Future<PhotoCapabilities> getPhotoCapabilities() =>
       promiseToFuture<PhotoCapabilities>(
-          JS("", "#.getPhotoCapabilities()", this));
+          JS("creates:PhotoCapabilities;", "#.getPhotoCapabilities()", this));
 
   Future<Map<String, dynamic>?> getPhotoSettings() =>
       promiseToFutureAsMap(JS("", "#.getPhotoSettings()", this));
 
-  Future<ImageBitmap> grabFrame() =>
-      promiseToFuture<ImageBitmap>(JS("", "#.grabFrame()", this));
+  Future<ImageBitmap> grabFrame() => promiseToFuture<ImageBitmap>(
+      JS("creates:ImageBitmap;", "#.grabFrame()", this));
 
   Future setOptions(Map photoSettings) {
     var photoSettings_dict = convertDartToNative_Dictionary(photoSettings);
@@ -18883,7 +18891,7 @@
       photoSettings_dict = convertDartToNative_Dictionary(photoSettings);
     }
     return promiseToFuture<Blob>(
-        JS("", "#.takePhoto(#)", this, photoSettings_dict));
+        JS("creates:Blob;", "#.takePhoto(#)", this, photoSettings_dict));
   }
 }
 // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
@@ -20468,14 +20476,20 @@
 
   Future<MediaCapabilitiesInfo> decodingInfo(Map configuration) {
     var configuration_dict = convertDartToNative_Dictionary(configuration);
-    return promiseToFuture<MediaCapabilitiesInfo>(
-        JS("", "#.decodingInfo(#)", this, configuration_dict));
+    return promiseToFuture<MediaCapabilitiesInfo>(JS(
+        "creates:MediaCapabilitiesInfo;",
+        "#.decodingInfo(#)",
+        this,
+        configuration_dict));
   }
 
   Future<MediaCapabilitiesInfo> encodingInfo(Map configuration) {
     var configuration_dict = convertDartToNative_Dictionary(configuration);
-    return promiseToFuture<MediaCapabilitiesInfo>(
-        JS("", "#.encodingInfo(#)", this, configuration_dict));
+    return promiseToFuture<MediaCapabilitiesInfo>(JS(
+        "creates:MediaCapabilitiesInfo;",
+        "#.encodingInfo(#)",
+        this,
+        configuration_dict));
   }
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -20540,8 +20554,8 @@
     if (constraints != null) {
       constraints_dict = convertDartToNative_Dictionary(constraints);
     }
-    return promiseToFuture<MediaStream>(
-        JS("", "#.getUserMedia(#)", this, constraints_dict));
+    return promiseToFuture<MediaStream>(JS(
+        "creates:MediaStream;", "#.getUserMedia(#)", this, constraints_dict));
   }
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -20849,7 +20863,7 @@
   String? get keySystem native;
 
   Future createMediaKeys() =>
-      promiseToFuture(JS("", "#.createMediaKeys()", this));
+      promiseToFuture(JS("creates:MediaKeys;", "#.createMediaKeys()", this));
 
   Map getConfiguration() {
     return convertNativeToDart_Dictionary(_getConfiguration_1())!;
@@ -22741,10 +22755,11 @@
   List<Gamepad?> _getGamepads() native;
 
   Future<RelatedApplication> getInstalledRelatedApps() =>
-      promiseToFuture<RelatedApplication>(
-          JS("", "#.getInstalledRelatedApps()", this));
+      promiseToFuture<RelatedApplication>(JS(
+          "creates:RelatedApplication;", "#.getInstalledRelatedApps()", this));
 
-  Future getVRDisplays() => promiseToFuture(JS("", "#.getVRDisplays()", this));
+  Future getVRDisplays() =>
+      promiseToFuture(JS("creates:VRDisplay;", "#.getVRDisplays()", this));
 
   @Unstable()
   void registerProtocolHandler(String scheme, String url, String title) native;
@@ -22776,8 +22791,12 @@
 
   Future requestMediaKeySystemAccess(
           String keySystem, List<Map> supportedConfigurations) =>
-      promiseToFuture(JS("", "#.requestMediaKeySystemAccess(#, #)", this,
-          keySystem, supportedConfigurations));
+      promiseToFuture(JS(
+          "creates:MediaKeySystemAccess;",
+          "#.requestMediaKeySystemAccess(#, #)",
+          this,
+          keySystem,
+          supportedConfigurations));
 
   bool sendBeacon(String url, Object? data) native;
 
@@ -23981,7 +24000,7 @@
       options_dict = convertDartToNative_Dictionary(options);
     }
     return promiseToFuture<Blob>(
-        JS("", "#.convertToBlob(#)", this, options_dict));
+        JS("creates:Blob;", "#.convertToBlob(#)", this, options_dict));
   }
 
   Object? getContext(String contextType, [Map? attributes]) {
@@ -24990,8 +25009,8 @@
   Future<bool> canMakePayment() =>
       promiseToFuture<bool>(JS("", "#.canMakePayment()", this));
 
-  Future<PaymentResponse> show() =>
-      promiseToFuture<PaymentResponse>(JS("", "#.show()", this));
+  Future<PaymentResponse> show() => promiseToFuture<PaymentResponse>(
+      JS("creates:PaymentResponse;", "#.show()", this));
 }
 
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -25029,8 +25048,8 @@
 
   Object? get total native;
 
-  Future<WindowClient> openWindow(String url) =>
-      promiseToFuture<WindowClient>(JS("", "#.openWindow(#)", this, url));
+  Future<WindowClient> openWindow(String url) => promiseToFuture<WindowClient>(
+      JS("creates:WindowClient;", "#.openWindow(#)", this, url));
 
   void respondWith(Future response) native;
 }
@@ -25463,23 +25482,23 @@
   Future<PermissionStatus> query(Map permission) {
     var permission_dict = convertDartToNative_Dictionary(permission);
     return promiseToFuture<PermissionStatus>(
-        JS("", "#.query(#)", this, permission_dict));
+        JS("creates:PermissionStatus;", "#.query(#)", this, permission_dict));
   }
 
   Future<PermissionStatus> request(Map permissions) {
     var permissions_dict = convertDartToNative_Dictionary(permissions);
-    return promiseToFuture<PermissionStatus>(
-        JS("", "#.request(#)", this, permissions_dict));
+    return promiseToFuture<PermissionStatus>(JS(
+        "creates:PermissionStatus;", "#.request(#)", this, permissions_dict));
   }
 
   Future<PermissionStatus> requestAll(List<Map> permissions) =>
-      promiseToFuture<PermissionStatus>(
-          JS("", "#.requestAll(#)", this, permissions));
+      promiseToFuture<PermissionStatus>(JS(
+          "creates:PermissionStatus;", "#.requestAll(#)", this, permissions));
 
   Future<PermissionStatus> revoke(Map permission) {
     var permission_dict = convertDartToNative_Dictionary(permission);
     return promiseToFuture<PermissionStatus>(
-        JS("", "#.revoke(#)", this, permission_dict));
+        JS("creates:PermissionStatus;", "#.revoke(#)", this, permission_dict));
   }
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -25898,7 +25917,7 @@
 
   Future<PresentationConnectionList> get connectionList =>
       promiseToFuture<PresentationConnectionList>(
-          JS("", "#.connectionList", this));
+          JS("creates:PresentationConnectionList;", "#.connectionList", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -25928,14 +25947,15 @@
 
   Future<PresentationAvailability> getAvailability() =>
       promiseToFuture<PresentationAvailability>(
-          JS("", "#.getAvailability()", this));
+          JS("creates:PresentationAvailability;", "#.getAvailability()", this));
 
   Future<PresentationConnection> reconnect(String id) =>
       promiseToFuture<PresentationConnection>(
-          JS("", "#.reconnect(#)", this, id));
+          JS("creates:PresentationConnection;", "#.reconnect(#)", this, id));
 
   Future<PresentationConnection> start() =>
-      promiseToFuture<PresentationConnection>(JS("", "#.start()", this));
+      promiseToFuture<PresentationConnection>(
+          JS("creates:PresentationConnection;", "#.start()", this));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -26102,7 +26122,8 @@
   static List<String>? get supportedContentEncodings native;
 
   Future<PushSubscription> getSubscription() =>
-      promiseToFuture<PushSubscription>(JS("", "#.getSubscription()", this));
+      promiseToFuture<PushSubscription>(
+          JS("creates:PushSubscription;", "#.getSubscription()", this));
 
   Future permissionState([Map? options]) {
     var options_dict = null;
@@ -26118,7 +26139,7 @@
       options_dict = convertDartToNative_Dictionary(options);
     }
     return promiseToFuture<PushSubscription>(
-        JS("", "#.subscribe(#)", this, options_dict));
+        JS("creates:PushSubscription;", "#.subscribe(#)", this, options_dict));
   }
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
@@ -26936,8 +26957,11 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture<RtcSessionDescription>(
-        JS("", "#.createAnswer(#)", this, options_dict));
+    return promiseToFuture<RtcSessionDescription>(JS(
+        "creates:RtcSessionDescription;",
+        "#.createAnswer(#)",
+        this,
+        options_dict));
   }
 
   @JSName('createDTMFSender')
@@ -26961,8 +26985,11 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture<RtcSessionDescription>(
-        JS("", "#.createOffer(#)", this, options_dict));
+    return promiseToFuture<RtcSessionDescription>(JS(
+        "creates:RtcSessionDescription;",
+        "#.createOffer(#)",
+        this,
+        options_dict));
   }
 
   List<MediaStream> getLocalStreams() native;
@@ -26973,8 +27000,8 @@
 
   List<RtcRtpSender> getSenders() native;
 
-  Future<RtcStatsReport> getStats() =>
-      promiseToFuture<RtcStatsReport>(JS("", "#.getStats()", this));
+  Future<RtcStatsReport> getStats() => promiseToFuture<RtcStatsReport>(
+      JS("creates:RtcStatsReport;", "#.getStats()", this));
 
   void removeStream(MediaStream? stream) native;
 
@@ -27762,11 +27789,15 @@
   ServiceWorker? get controller native;
 
   Future<ServiceWorkerRegistration> get ready =>
-      promiseToFuture<ServiceWorkerRegistration>(JS("", "#.ready", this));
+      promiseToFuture<ServiceWorkerRegistration>(
+          JS("creates:ServiceWorkerRegistration;", "#.ready", this));
 
   Future<ServiceWorkerRegistration> getRegistration([String? documentURL]) =>
-      promiseToFuture<ServiceWorkerRegistration>(
-          JS("", "#.getRegistration(#)", this, documentURL));
+      promiseToFuture<ServiceWorkerRegistration>(JS(
+          "creates:ServiceWorkerRegistration;",
+          "#.getRegistration(#)",
+          this,
+          documentURL));
 
   Future<List<dynamic>> getRegistrations() =>
       promiseToFuture<List<dynamic>>(JS("", "#.getRegistrations()", this));
@@ -27776,8 +27807,12 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture<ServiceWorkerRegistration>(
-        JS("", "#.register(#, #)", this, url, options_dict));
+    return promiseToFuture<ServiceWorkerRegistration>(JS(
+        "creates:ServiceWorkerRegistration;",
+        "#.register(#, #)",
+        this,
+        url,
+        options_dict));
   }
 
   Stream<MessageEvent> get onMessage => messageEvent.forTarget(this);
@@ -31207,8 +31242,8 @@
     if (options != null) {
       options_dict = convertDartToNative_Dictionary(options);
     }
-    return promiseToFuture(
-        JS("", "#.requestFrameOfReference(#, #)", this, type, options_dict));
+    return promiseToFuture(JS("creates:VRFrameOfReference;",
+        "#.requestFrameOfReference(#, #)", this, type, options_dict));
   }
 
   Stream<Event> get onBlur => blurEvent.forTarget(this);
@@ -32854,7 +32889,8 @@
     if (init != null) {
       init_dict = convertDartToNative_Dictionary(init);
     }
-    return promiseToFuture(JS("", "#.fetch(#, #)", this, input, init_dict));
+    return promiseToFuture(
+        JS("creates:_Response;", "#.fetch(#, #)", this, input, init_dict));
   }
 
   /**
@@ -33759,11 +33795,11 @@
 
   String? get visibilityState native;
 
-  Future<WindowClient> focus() =>
-      promiseToFuture<WindowClient>(JS("", "#.focus()", this));
+  Future<WindowClient> focus() => promiseToFuture<WindowClient>(
+      JS("creates:WindowClient;", "#.focus()", this));
 
-  Future<WindowClient> navigate(String url) =>
-      promiseToFuture<WindowClient>(JS("", "#.navigate(#)", this, url));
+  Future<WindowClient> navigate(String url) => promiseToFuture<WindowClient>(
+      JS("creates:WindowClient;", "#.navigate(#)", this, url));
 }
 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
@@ -33923,7 +33959,8 @@
     if (init != null) {
       init_dict = convertDartToNative_Dictionary(init);
     }
-    return promiseToFuture(JS("", "#.fetch(#, #)", this, input, init_dict));
+    return promiseToFuture(
+        JS("creates:_Response;", "#.fetch(#, #)", this, input, init_dict));
   }
 
   void importScripts(String urls) native;
@@ -34334,8 +34371,8 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Future<BudgetState> getBudget() =>
-      promiseToFuture<BudgetState>(JS("", "#.getBudget()", this));
+  Future<BudgetState> getBudget() => promiseToFuture<BudgetState>(
+      JS("creates:BudgetState;", "#.getBudget()", this));
 
   Future<double> getCost(String operation) =>
       promiseToFuture<double>(JS("", "#.getCost(#)", this, operation));
@@ -34375,8 +34412,8 @@
     throw new UnsupportedError("Not supported");
   }
 
-  Future<DataTransfer> read() =>
-      promiseToFuture<DataTransfer>(JS("", "#.read()", this));
+  Future<DataTransfer> read() => promiseToFuture<DataTransfer>(
+      JS("creates:DataTransfer;", "#.read()", this));
 
   Future<String> readText() =>
       promiseToFuture<String>(JS("", "#.readText()", this));
@@ -40123,7 +40160,7 @@
   //    ...
   //    var e = document.createElement('x-foo');
 
-  var extendsTagName = '';
+  String? extendsTagName = '';
   Type? type;
   if (options != null) {
     extendsTagName = options['extends'];
diff --git a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
index 21640b2..1b501e9 100644
--- a/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
+++ b/sdk/lib/indexed_db/dart2js/indexed_db_dart2js.dart
@@ -473,7 +473,7 @@
           'version and onUpgradeNeeded must be specified together'));
     }
     try {
-      var request;
+      OpenDBRequest request;
       if (version != null) {
         request = _open(name, version);
       } else {
diff --git a/sdk/lib/internal/errors.dart b/sdk/lib/internal/errors.dart
index 9010622..93c01f1 100644
--- a/sdk/lib/internal/errors.dart
+++ b/sdk/lib/internal/errors.dart
@@ -17,3 +17,16 @@
         : "LateInitializationError";
   }
 }
+
+class ReachabilityError extends Error {
+  final String? _message;
+
+  ReachabilityError([this._message]);
+
+  String toString() {
+    var message = _message;
+    return (message != null)
+        ? "ReachabilityError: $message"
+        : "ReachabilityError";
+  }
+}
diff --git a/sdk/lib/internal/internal_sources.gni b/sdk/lib/internal/internal_sources.gni
index c35e678..25b98b9 100644
--- a/sdk/lib/internal/internal_sources.gni
+++ b/sdk/lib/internal/internal_sources.gni
@@ -14,6 +14,7 @@
   "iterable.dart",
   "linked_list.dart",
   "list.dart",
+  "lowering.dart",
   "print.dart",
   "sort.dart",
   "symbol.dart",
diff --git a/sdk/lib/internal/lowering.dart b/sdk/lib/internal/lowering.dart
new file mode 100644
index 0000000..30a0cea
--- /dev/null
+++ b/sdk/lib/internal/lowering.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart._internal;
+
+external T createSentinel<T>();
+
+external bool isSentinel(dynamic value);
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index ee34b7d..75f78b1 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -679,7 +679,7 @@
 
   void _maybePerformCleanup() {
     if (closed) {
-      _FileResourceInfo.FileClosed(_resourceInfo);
+      _FileResourceInfo.fileClosed(_resourceInfo);
     }
   }
 
@@ -691,8 +691,8 @@
       // open.
       registerExtension(
           'ext.dart.io.getOpenFiles', _FileResourceInfo.getOpenFiles);
-      registerExtension(
-          'ext.dart.io.getFileByID', _FileResourceInfo.getFileInfoMapByID);
+      registerExtension('ext.dart.io.getOpenFileById',
+          _FileResourceInfo.getOpenFileInfoMapByID);
       _connectedResourceHandler = true;
     }
   }
diff --git a/sdk/lib/io/io_resource_info.dart b/sdk/lib/io/io_resource_info.dart
index b916dd8..3ba76c9 100644
--- a/sdk/lib/io/io_resource_info.dart
+++ b/sdk/lib/io/io_resource_info.dart
@@ -10,10 +10,10 @@
   String get name;
   static int _count = 0;
 
-  static final Stopwatch _sw = new Stopwatch()..start();
-  static final _startTime = new DateTime.now().millisecondsSinceEpoch;
+  static final Stopwatch _sw = Stopwatch()..start();
+  static final _startTime = DateTime.now().millisecondsSinceEpoch;
 
-  static double get timestamp => _startTime + _sw.elapsedMicroseconds / 1000;
+  static int get timestamp => _startTime + _sw.elapsedMicroseconds ~/ 1000;
 
   _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID();
 
@@ -34,20 +34,20 @@
 }
 
 abstract class _ReadWriteResourceInfo extends _IOResourceInfo {
-  int totalRead;
-  int totalWritten;
+  int readBytes;
+  int writeBytes;
   int readCount;
   int writeCount;
-  double lastRead;
-  double lastWrite;
+  int lastReadTime;
+  int lastWriteTime;
 
   // Not all call sites use this. In some cases, e.g., a socket, a read does
   // not always mean that we actually read some bytes (we may do a read to see
   // if there are some bytes available).
   void addRead(int bytes) {
-    totalRead += bytes;
+    readBytes += bytes;
     readCount++;
-    lastRead = _IOResourceInfo.timestamp;
+    lastReadTime = _IOResourceInfo.timestamp;
   }
 
   // In cases where we read but did not necessarily get any bytes, use this to
@@ -58,102 +58,100 @@
   }
 
   void addWrite(int bytes) {
-    totalWritten += bytes;
+    writeBytes += bytes;
     writeCount++;
-    lastWrite = _IOResourceInfo.timestamp;
+    lastWriteTime = _IOResourceInfo.timestamp;
   }
 
   _ReadWriteResourceInfo(String type)
-      : totalRead = 0,
-        totalWritten = 0,
+      : readBytes = 0,
+        writeBytes = 0,
         readCount = 0,
         writeCount = 0,
-        lastRead = 0.0,
-        lastWrite = 0.0,
+        lastReadTime = 0,
+        lastWriteTime = 0,
         super(type);
 
   Map<String, dynamic> get fullValueMap => {
         'type': type,
         'id': id,
         'name': name,
-        'totalRead': totalRead,
-        'totalWritten': totalWritten,
+        'readBytes': readBytes,
+        'writeBytes': writeBytes,
         'readCount': readCount,
         'writeCount': writeCount,
-        'lastRead': lastRead,
-        'lastWrite': lastWrite
+        'lastReadTime': lastReadTime,
+        'lastWriteTime': lastWriteTime
       };
 }
 
 class _FileResourceInfo extends _ReadWriteResourceInfo {
-  static const String _type = '_file';
+  static const String _type = 'OpenFile';
 
   final file;
 
-  static Map<int, _FileResourceInfo> openFiles =
-      new Map<int, _FileResourceInfo>();
+  static Map<int, _FileResourceInfo> openFiles = {};
 
   _FileResourceInfo(this.file) : super(_type) {
-    FileOpened(this);
+    fileOpened(this);
   }
 
-  static FileOpened(_FileResourceInfo info) {
+  static fileOpened(_FileResourceInfo info) {
     assert(!openFiles.containsKey(info.id));
     openFiles[info.id] = info;
   }
 
-  static FileClosed(_FileResourceInfo info) {
+  static fileClosed(_FileResourceInfo info) {
     assert(openFiles.containsKey(info.id));
     openFiles.remove(info.id);
   }
 
   static Iterable<Map<String, dynamic>> getOpenFilesList() {
-    return new List.from(openFiles.values.map((e) => e.referenceValueMap));
+    return List.from(openFiles.values.map(
+      (e) => e.referenceValueMap,
+    ));
   }
 
   static Future<ServiceExtensionResponse> getOpenFiles(function, params) {
     assert(function == 'ext.dart.io.getOpenFiles');
-    var data = {'type': '_openfiles', 'data': getOpenFilesList()};
-    var jsonValue = json.encode(data);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
+    final data = {
+      'type': 'OpenFileList',
+      'files': getOpenFilesList(),
+    };
+    final jsonValue = json.encode(data);
+    return Future.value(ServiceExtensionResponse.result(jsonValue));
   }
 
-  Map<String, dynamic> getFileInfoMap() {
-    return fullValueMap;
+  Map<String, dynamic> get fileInfoMap => fullValueMap;
+
+  static Future<ServiceExtensionResponse> getOpenFileInfoMapByID(
+      function, params) {
+    final id = int.parse(params['id']!);
+    final result = openFiles.containsKey(id) ? openFiles[id]!.fileInfoMap : {};
+    final jsonValue = json.encode(result);
+    return Future.value(ServiceExtensionResponse.result(jsonValue));
   }
 
-  static Future<ServiceExtensionResponse> getFileInfoMapByID(function, params) {
-    var id = int.parse(params['id']!);
-    var result =
-        openFiles.containsKey(id) ? openFiles[id]!.getFileInfoMap() : {};
-    var jsonValue = json.encode(result);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
-  }
-
-  String get name {
-    return '${file.path}';
-  }
+  String get name => file.path;
 }
 
-class _ProcessResourceInfo extends _IOResourceInfo {
-  static const String _type = '_process';
+class _SpawnedProcessResourceInfo extends _IOResourceInfo {
+  static const String _type = 'SpawnedProcess';
   final process;
-  final double startedAt;
+  final int startedAt;
 
-  static Map<int, _ProcessResourceInfo> startedProcesses =
-      new Map<int, _ProcessResourceInfo>();
+  static Map<int, _SpawnedProcessResourceInfo> startedProcesses =
+      Map<int, _SpawnedProcessResourceInfo>();
 
-  _ProcessResourceInfo(this.process)
+  _SpawnedProcessResourceInfo(this.process)
       : startedAt = _IOResourceInfo.timestamp,
         super(_type) {
-    ProcessStarted(this);
+    processStarted(this);
   }
 
   String get name => process._path;
 
-  void stopped() {
-    ProcessStopped(this);
-  }
+  void stopped() => processStopped(this);
 
   Map<String, dynamic> get fullValueMap => {
         'type': type,
@@ -166,115 +164,39 @@
             process._workingDirectory == null ? '.' : process._workingDirectory,
       };
 
-  static ProcessStarted(_ProcessResourceInfo info) {
+  static processStarted(_SpawnedProcessResourceInfo info) {
     assert(!startedProcesses.containsKey(info.id));
     startedProcesses[info.id] = info;
   }
 
-  static ProcessStopped(_ProcessResourceInfo info) {
+  static processStopped(_SpawnedProcessResourceInfo info) {
     assert(startedProcesses.containsKey(info.id));
     startedProcesses.remove(info.id);
   }
 
   static Iterable<Map<String, dynamic>> getStartedProcessesList() =>
-      new List.from(startedProcesses.values.map((e) => e.referenceValueMap));
+      List.from(startedProcesses.values.map(
+        (e) => e.referenceValueMap,
+      ));
 
   static Future<ServiceExtensionResponse> getStartedProcesses(
       String function, Map<String, String> params) {
-    assert(function == 'ext.dart.io.getProcesses');
-    var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()};
-    var jsonValue = json.encode(data);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
+    assert(function == 'ext.dart.io.getSpawnedProcesses');
+    final data = {
+      'type': 'SpawnedProcessList',
+      'processes': getStartedProcessesList(),
+    };
+    final jsonValue = json.encode(data);
+    return Future.value(ServiceExtensionResponse.result(jsonValue));
   }
 
   static Future<ServiceExtensionResponse> getProcessInfoMapById(
       String function, Map<String, String> params) {
-    var id = int.parse(params['id']!);
-    var result = startedProcesses.containsKey(id)
+    final id = int.parse(params['id']!);
+    final result = startedProcesses.containsKey(id)
         ? startedProcesses[id]!.fullValueMap
         : {};
-    var jsonValue = json.encode(result);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
-  }
-}
-
-class _SocketResourceInfo extends _ReadWriteResourceInfo {
-  static const String _tcpString = 'TCP';
-  static const String _udpString = 'UDP';
-  static const String _type = '_socket';
-
-  final /*_NativeSocket|*/ socket;
-
-  static Map<int, _SocketResourceInfo> openSockets =
-      new Map<int, _SocketResourceInfo>();
-
-  _SocketResourceInfo(this.socket) : super(_type) {
-    SocketOpened(this);
-  }
-
-  String get name {
-    if (socket.isListening) {
-      return 'listening:${socket.address.host}:${socket.port}';
-    }
-    var remote = '';
-    try {
-      var remoteHost = socket.remoteAddress.host;
-      var remotePort = socket.remotePort;
-      remote = ' -> $remoteHost:$remotePort';
-    } catch (e) {} // ignored if we can't get the information
-    return '${socket.address.host}:${socket.port}$remote';
-  }
-
-  static Iterable<Map<String, dynamic>> getOpenSocketsList() {
-    return new List.from(openSockets.values.map((e) => e.referenceValueMap));
-  }
-
-  Map<String, dynamic> getSocketInfoMap() {
-    var result = fullValueMap;
-    result['socketType'] = socket.isTcp ? _tcpString : _udpString;
-    result['listening'] = socket.isListening;
-    result['host'] = socket.address.host;
-    result['port'] = socket.port;
-    if (!socket.isListening) {
-      try {
-        result['remoteHost'] = socket.remoteAddress.host;
-        result['remotePort'] = socket.remotePort;
-      } catch (e) {
-        // UDP.
-        result['remotePort'] = 'NA';
-        result['remoteHost'] = 'NA';
-      }
-    } else {
-      result['remotePort'] = 'NA';
-      result['remoteHost'] = 'NA';
-    }
-    result['addressType'] = socket.address.type.name;
-    return result;
-  }
-
-  static Future<ServiceExtensionResponse> getSocketInfoMapByID(
-      String function, Map<String, String> params) {
-    var id = int.parse(params['id']!);
-    var result =
-        openSockets.containsKey(id) ? openSockets[id]!.getSocketInfoMap() : {};
-    var jsonValue = json.encode(result);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
-  }
-
-  static Future<ServiceExtensionResponse> getOpenSockets(function, params) {
-    assert(function == 'ext.dart.io.getOpenSockets');
-    var data = {'type': '_opensockets', 'data': getOpenSocketsList()};
-    var jsonValue = json.encode(data);
-    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
-  }
-
-  static SocketOpened(_SocketResourceInfo info) {
-    assert(!openSockets.containsKey(info.id));
-    openSockets[info.id] = info;
-  }
-
-  static SocketClosed(_SocketResourceInfo info) {
-    assert(openSockets.containsKey(info.id));
-    openSockets.remove(info.id);
+    final jsonValue = json.encode(result);
+    return Future.value(ServiceExtensionResponse.result(jsonValue));
   }
 }
diff --git a/sdk/lib/io/network_profiling.dart b/sdk/lib/io/network_profiling.dart
index 5032d72..5c1c620 100644
--- a/sdk/lib/io/network_profiling.dart
+++ b/sdk/lib/io/network_profiling.dart
@@ -4,8 +4,9 @@
 
 part of dart.io;
 
+// TODO(bkonyi): refactor into io_resource_info.dart
 const int _versionMajor = 1;
-const int _versionMinor = 1;
+const int _versionMinor = 4;
 
 const String _tcpSocket = 'tcp';
 const String _udpSocket = 'udp';
@@ -13,10 +14,14 @@
 @pragma('vm:entry-point', !const bool.fromEnvironment("dart.vm.product"))
 abstract class _NetworkProfiling {
   // Http relative RPCs
+  @Deprecated('Use httpEnableTimelineLogging instead')
   static const _kGetHttpEnableTimelineLogging =
       'ext.dart.io.getHttpEnableTimelineLogging';
+  @Deprecated('Use httpEnableTimelineLogging instead')
   static const _kSetHttpEnableTimelineLogging =
       'ext.dart.io.setHttpEnableTimelineLogging';
+  static const _kHttpEnableTimelineLogging =
+      'ext.dart.io.httpEnableTimelineLogging';
   // Socket relative RPCs
   static const _kClearSocketProfileRPC = 'ext.dart.io.clearSocketProfile';
   static const _kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
@@ -32,6 +37,7 @@
   static void _registerServiceExtension() {
     registerExtension(_kGetHttpEnableTimelineLogging, _serviceExtensionHandler);
     registerExtension(_kSetHttpEnableTimelineLogging, _serviceExtensionHandler);
+    registerExtension(_kHttpEnableTimelineLogging, _serviceExtensionHandler);
     registerExtension(_kGetSocketProfileRPC, _serviceExtensionHandler);
     registerExtension(_kStartSocketProfilingRPC, _serviceExtensionHandler);
     registerExtension(_kPauseSocketProfilingRPC, _serviceExtensionHandler);
@@ -50,6 +56,20 @@
         case _kSetHttpEnableTimelineLogging:
           responseJson = _setHttpEnableTimelineLogging(parameters);
           break;
+        case _kHttpEnableTimelineLogging:
+          if (parameters.containsKey('enabled') ||
+              parameters.containsKey('enable')) {
+            // TODO(bkonyi): Backwards compatibility.
+            // See https://github.com/dart-lang/sdk/issues/43638.
+            assert(_versionMajor == 1,
+                "'enable' is deprecated and should be removed (See #43638)");
+            if (parameters.containsKey('enabled')) {
+              parameters['enable'] = parameters['enabled']!;
+            }
+            _setHttpEnableTimelineLogging(parameters);
+          }
+          responseJson = _getHttpEnableTimelineLogging();
+          break;
         case _kGetSocketProfileRPC:
           responseJson = _SocketProfile.toJson();
           break;
@@ -107,7 +127,7 @@
   if (enable != 'true' && enable != 'false') {
     throw _invalidArgument(kEnable, enable);
   }
-  HttpClient.enableTimelineLogging = (enable == 'true');
+  HttpClient.enableTimelineLogging = enable == 'true';
   return _success();
 }
 
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 08e9bf7..98d2dcf 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -812,11 +812,19 @@
 
   void _secureHandshake() {
     try {
-      _secureFilter!.handshake();
-      _filterStatus.writeEmpty = false;
-      _readSocket();
-      _writeSocket();
-      _scheduleFilter();
+      _secureFilter!.handshake().then((needRetryHandshake) {
+        if (needRetryHandshake) {
+          // Some certificates have been evaluated, need to rety handshake.
+          _secureHandshake();
+        } else {
+          _filterStatus.writeEmpty = false;
+          _readSocket();
+          _writeSocket();
+          _scheduleFilter();
+        }
+      }).catchError((e, stackTrace) {
+        _reportError(e, stackTrace);
+      });
     } catch (e, stackTrace) {
       _reportError(e, stackTrace);
     }
@@ -1235,7 +1243,7 @@
       bool requireClientCertificate,
       Uint8List protocols);
   void destroy();
-  void handshake();
+  Future<bool> handshake();
   String? selectedProtocol();
   void rehandshake();
   void renegotiate(bool useSessionCache, bool requestClientCertificate,
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 6b6667a..03a6811 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -75,14 +75,6 @@
   _Evaluator(this._message, this._isolate, this._service);
 
   Future<Response> run() async {
-    if (_service.ddsUri != null) {
-      return Response.from(encodeRpcError(
-        _message,
-        kInternalError,
-        details: 'Fell through to VM Service expression evaluation when a DDS '
-            'instance was connected. Please file an issue on GitHub.',
-      ));
-    }
     final buildScopeResponse = await _buildScope();
     final responseJson = buildScopeResponse.decodeJson();
 
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index e0ccfaa..755e934 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -239,6 +239,12 @@
           details:
               'Embedder does not support yielding to a VM service intermediary.');
     }
+
+    if (_ddsUri != null) {
+      return encodeRpcError(message, kFeatureDisabled,
+          details: 'A DDS instance is already connected at ${_ddsUri!}.');
+    }
+
     final uri = message.params['uri'];
     if (uri == null) {
       return encodeMissingParamError(message, 'uri');
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index da12ab3..a12d2fe 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -682,8 +682,13 @@
   Future<AudioBuffer> decodeAudioData(ByteBuffer audioData,
           [DecodeSuccessCallback? successCallback,
           DecodeErrorCallback? errorCallback]) =>
-      promiseToFuture<AudioBuffer>(JS("", "#.decodeAudioData(#, #, #)", this,
-          audioData, successCallback, errorCallback));
+      promiseToFuture<AudioBuffer>(JS(
+          "creates:AudioBuffer;",
+          "#.decodeAudioData(#, #, #)",
+          this,
+          audioData,
+          successCallback,
+          errorCallback));
 
   Future resume() => promiseToFuture(JS("", "#.resume()", this));
 }
@@ -1075,8 +1080,8 @@
 
   int? get length native;
 
-  Future<AudioBuffer> startRendering() =>
-      promiseToFuture<AudioBuffer>(JS("", "#.startRendering()", this));
+  Future<AudioBuffer> startRendering() => promiseToFuture<AudioBuffer>(
+      JS("creates:AudioBuffer;", "#.startRendering()", this));
 
   @JSName('suspend')
   Future suspendFor(num suspendTime) =>
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status
index 4bfc333..8970fe8 100644
--- a/tests/co19/co19-co19.status
+++ b/tests/co19/co19-co19.status
@@ -23,38 +23,17 @@
 Language/Reference/Operator_Precedence/precedence_01_assignment_t14: Skip # Triple shift is not implemented yet
 Language/Reference/Operator_Precedence/precedence_12_Shift_t04: Skip # Triple shift is not implemented yet
 Language/Reference/Operator_Precedence/precedence_t05: Skip # Triple shift is not implemented yet
-Language/Statements/Assert/*: Skip # Not migrated to NNBD
 Language/Statements/Expression_Statements/syntax_t06: Skip # Type aliases are not fully implemented
 Language/Types/Type_Aliases/built-in_types_t11: Skip # Triple shift is not implemented yet
 LanguageFeatures/Extension-methods/explicit_extension_member_invocation_A15_t09: Skip # Triple shift is not implemented yet
-LanguageFeatures/Instantiate-to-bound/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/class/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/class/dynamic/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/class/static/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/dynamic/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/static/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/typedef/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/typedef/dynamic/*: Skip # Not migrated to NNBD
-LanguageFeatures/Instantiate-to-bound/typedef/static/*: Skip # Not migrated to NNBD
-LanguageFeatures/Simple-bounds/*: Skip # Not migrated to NNBD
-LanguageFeatures/Simple-bounds/dynamic/*: Skip # Not migrated to NNBD
-LanguageFeatures/Simple-bounds/dynamic/type-aliases/*: Skip # Not migrated to NNBD
-LanguageFeatures/Simple-bounds/static/*: Skip # Not migrated to NNBD
-LanguageFeatures/Simple-bounds/static/type-aliases/*: Skip # Not migrated to NNBD
-LanguageFeatures/Spread-collections/*: Skip # Not migrated to NNBD
+LanguageFeatures/Instantiate-to-bound/nonfunction_typedef/static/*: Skip # Type aliases are not fully implemented
+LanguageFeatures/Simple-bounds/dynamic/type-aliases/*: Skip # Type aliases are not fully implemented
+LanguageFeatures/Simple-bounds/static/type-aliases/*: Skip # Type aliases are not fully implemented
 LanguageFeatures/Triple-Shift/*: Skip # Triple shift is not implemented yet
-LanguageFeatures/int-to-double/*: Skip # Not migrated to NNBD
+LanguageFeatures/nnbd/local_variable_read_A01_t03: Skip # Triple shift is not implemented yet
+LanguageFeatures/nnbd/local_variable_read_A02_t03: Skip # Triple shift is not implemented yet
+LanguageFeatures/nnbd/local_variable_read_A03_t03: Skip # Triple shift is not implemented yet
 LanguageFeatures/regression/34560_t02/01: Skip # Type aliases are not fully implemented
-LibTest/html/CanvasRenderingContext2D/*: Skip # Not migrated to NNBD
-LibTest/html/Document/*: Skip # Not migrated to NNBD
-LibTest/html/Element/*: Skip # Not migrated to NNBD
-LibTest/html/Event/*: Skip # Not migrated to NNBD
-LibTest/html/HttpRequest/*: Skip # Not migrated to NNBD
-LibTest/html/HttpRequestUpload/*: Skip # Not migrated to NNBD
-LibTest/html/IFrameElement/*: Skip # Not migrated to NNBD
-LibTest/html/Node/*: Skip # Not migrated to NNBD
-LibTest/html/Window/*: Skip # Not migrated to NNBD
 LibTest/io/RawDatagramSocket/*: Skip # https://github.com/dart-lang/co19/issues/195
 
 [ $compiler == dart2analyzer ]
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 2cf6be3..8319487 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -30,6 +30,8 @@
 LibTest/core/int/operator_truncating_division_A01_t02: SkipByDesign # Division by zero is not an error in JavaScript
 LibTest/core/int/parse_A01_t02: SkipByDesign # big integers cannot be represented in JavaScript
 LibTest/core/int/remainder_A01_t03: SkipByDesign # Division by zero is not an error in JavaScript
+LibTest/html/HttpRequest/*: Skip # https://github.com/dart-lang/co19/issues/932
+LibTest/html/HttpRequestUpload/*: Skip # https://github.com/dart-lang/co19/issues/932
 LibTest/io/*: SkipByDesign # dart:io not supported.
 LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
 LibTest/mirrors/*: SkipByDesign # dart:mirrors is not supported
diff --git a/tests/co19/co19-dartdevc.status b/tests/co19/co19-dartdevc.status
index 23dd0d4..50a7573 100644
--- a/tests/co19/co19-dartdevc.status
+++ b/tests/co19/co19-dartdevc.status
@@ -83,26 +83,12 @@
 LibTest/core/int/operator_truncating_division_A01_t02: SkipByDesign # Division by zero is not an error in JavaScript
 LibTest/core/int/parse_A01_t02: SkipByDesign # big integers cannot be represented in JavaScript
 LibTest/core/int/remainder_A01_t03: SkipByDesign # Division by zero is not an error in JavaScript
-LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t03: Skip # Times out
 LibTest/html/Element/blur_A01_t01: Skip # Times out
 LibTest/html/Element/focus_A01_t01: Skip # Times out
-LibTest/html/Element/loadEvent_A01_t01: Skip # Times out
-LibTest/html/Element/mouseWheelEvent_A01_t01: Skip # Times out
-LibTest/html/Element/onLoad_A01_t01: Skip # Times out
-LibTest/html/Element/onMouseWheel_A01_t01: Skip # Times out
-LibTest/html/Element/onTransitionEnd_A01_t01: Skip # Times out
-LibTest/html/Element/transitionEndEvent_A01_t01: Skip # Times out
-LibTest/html/HttpRequest/onError_A01_t02: Skip # Times out
-LibTest/html/HttpRequest/responseText_A01_t02: Skip # Times out
-LibTest/html/HttpRequestUpload/onError_A01_t02: Skip # Times out
-LibTest/html/HttpRequestUpload/onLoadEnd_A01_t01: Skip # Times out
-LibTest/html/HttpRequestUpload/onLoadStart_A01_t01: Skip # Times out
-LibTest/html/HttpRequestUpload/onLoad_A01_t01: Skip # Times out
+LibTest/html/HttpRequest/*: Skip # https://github.com/dart-lang/co19/issues/932
+LibTest/html/HttpRequestUpload/*: Skip # https://github.com/dart-lang/co19/issues/932
 LibTest/html/IFrameElement/blur_A01_t01: Skip # Times out
-LibTest/html/IFrameElement/enteredView_A01_t01: Skip # Times out
 LibTest/html/IFrameElement/focus_A01_t01: Skip # Times out
-LibTest/html/IFrameElement/onMouseWheel_A01_t01: Skip # Times out
-LibTest/html/IFrameElement/onTransitionEnd_A01_t01: Skip # Times out
 LibTest/io/*: SkipByDesign # dart:io not supported.
 LibTest/isolate/*: SkipByDesign # dart:isolate not supported.
 LibTest/mirrors/*: SkipByDesign # dart:mirrors is not supported
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index d25eeaa..ee639b0 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -2,15 +2,10 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $builder_tag == bytecode_interpreter ]
-LibTest/collection/ListBase/ListBase_class_A01_t04: Slow, Pass
-LibTest/collection/ListBase/ListBase_class_A01_t05: Slow, Pass
-LibTest/collection/ListBase/ListBase_class_A01_t06: Slow, Pass
-
-[ $compiler == dartkb ]
-LibTest/isolate/Isolate/kill_A01_t01: Skip # Issue 37699
-LibTest/isolate/Isolate/pause_A01_t01: Skip # Issue 37699
-LibTest/isolate/Isolate/pause_A01_t02: Skip # Issue 37699
+[ $compiler == dartk ]
+Language/Libraries_and_Scripts/Scripts/top_level_main_t01: Crash
+LibTest/isolate/SendPort/send_A01_t02: Crash
+LibTest/isolate/SendPort/send_A01_t03: Crash
 
 [ $compiler == fasta ]
 Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
@@ -334,10 +329,10 @@
 LibTest/collection/ListBase/ListBase_class_A01_t01: Skip # Issue 43036
 LibTest/collection/ListMixin/ListMixin_class_A01_t01: Skip # Issue 43036
 
-[ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm && $system == linux ]
 LibTest/isolate/Isolate/spawn_A06_t03: Crash
 
-[ $runtime == vm && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm && $system == macos ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Slow, Pass
 LibTest/collection/ListBase/ListBase_class_A01_t03: Slow, Pass
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Slow, Pass
@@ -345,14 +340,9 @@
 LibTest/core/List/List_class_A01_t02: Slow, Pass
 LibTest/core/List/List_class_A01_t03: Slow, Pass
 
-[ $runtime != vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime != vm ]
 Language/Classes/Constructors/Constant_Constructors/potentially_constant_expression_t01: Crash
 
-[ $compiler == dartk || $compiler == dartkb ]
-Language/Libraries_and_Scripts/Scripts/top_level_main_t01: Crash
-LibTest/isolate/SendPort/send_A01_t02: Crash
-LibTest/isolate/SendPort/send_A01_t03: Crash
-
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index f34b3eb..0a91266 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -12,5 +12,8 @@
 [ $compiler != dart2js && $runtime != none && $runtime != vm && !$checked ]
 LibTest/async/Future/catchError_A03_t05: RuntimeError
 
+[ $mode == debug && $nnbd != legacy && $runtime == dart_precompiled ]
+LibTest/collection/ListMixin/ListMixin_class_A01_t05: SkipSlow # Issue 43614
+
 [ $compiler == fasta || $runtime == dart_precompiled || $runtime == vm ]
 LibTest/html/*: SkipByDesign # dart:html not supported on VM.
diff --git a/tests/co19/update.sh b/tests/co19/update.sh
index 940db04..d06c153 100755
--- a/tests/co19/update.sh
+++ b/tests/co19/update.sh
@@ -32,32 +32,32 @@
 # Update DEPS:
 gclient setdep --var=co19_rev=$NEW
 
+BUILDERS=$(jq -r '.builder_configurations
+  | map(select(.steps
+    | any(.arguments
+      | select(.!=null)
+        | any(test("co19($|(/.*))")))))
+  | map(.builders)
+  | flatten
+  | sort
+  | .[] += "-try"
+  | join(",")' \
+  tools/bots/test_matrix.json)
+
 # Make a nice commit. Don't include the '#' character to avoid referencing Dart
 # SDK issues.
 git commit DEPS -m \
-  "$(printf "[co19] Roll co19 to $NEW\n\n" &&
-     cd $CO19 &&
-     git log --date='format:%Y-%m-%d' --pretty='format:%ad %ae %s' \
-       $OLD..$NEW | tr -d '#')"
+  "$(printf "[co19] Roll co19 to $NEW\n\n" \
+  && cd $CO19 \
+  && git log --date='format:%Y-%m-%d' --pretty='format:%ad %ae %s' $OLD..$NEW \
+  && printf "\nCq-Include-Trybots: dart/try:$BUILDERS\n" \
+  | tr -d '#')"
 
 rm -rf tests/co19/src.git
 
 GIT_EDITOR=true git cl upload
 ISSUE=$(git config --get branch.cl-co19-roll-co19-to-$NEW.gerritissue)
 
-BUILDERS=$(jq '.builder_configurations|
-                map(select(.steps|
-                           any(.arguments|
-                               select(.!=null)|
-                               any(test("co19($|(/.*))")))))|
-                map(.builders)|
-                flatten|
-                sort' \
-                tools/bots/test_matrix.json \
-             | tr -d '[",]')
-
-git cl try -B dart/try $(for BUILDER in $BUILDERS; do echo -b $BUILDER-try; done)
-
 git cl web
 
 set +x
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 8aa80ab..3a0f103 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -2,15 +2,10 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE file.
 
-[ $builder_tag == bytecode_interpreter ]
-LibTest/collection/ListBase/ListBase_class_A01_t04: Slow, Pass
-LibTest/collection/ListBase/ListBase_class_A01_t05: Slow, Pass
-LibTest/collection/ListBase/ListBase_class_A01_t06: Slow, Pass
-
-[ $compiler == dartkb ]
-LibTest/isolate/Isolate/kill_A01_t01: Skip # Issue 37699
-LibTest/isolate/Isolate/pause_A01_t01: Skip # Issue 37699
-LibTest/isolate/Isolate/pause_A01_t02: Skip # Issue 37699
+[ $compiler == dartk ]
+Language/Libraries_and_Scripts/Scripts/top_level_main_t01: Crash
+LibTest/isolate/SendPort/send_A01_t02: Crash
+LibTest/isolate/SendPort/send_A01_t03: Crash
 
 [ $compiler == fasta ]
 Language/Statements/For/syntax_t13: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
@@ -178,10 +173,10 @@
 LanguageFeatures/regression/34803_t01: Crash
 LanguageFeatures/regression/34803_t02: Crash
 
-[ $runtime == vm && $system == linux && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm && $system == linux ]
 LibTest/isolate/Isolate/spawn_A06_t03: Crash
 
-[ $runtime == vm && $system == macos && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime == vm && $system == macos ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Slow, Pass
 LibTest/collection/ListBase/ListBase_class_A01_t03: Slow, Pass
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Slow, Pass
@@ -189,14 +184,9 @@
 LibTest/core/List/List_class_A01_t02: Slow, Pass
 LibTest/core/List/List_class_A01_t03: Slow, Pass
 
-[ $runtime != vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $compiler == dartk && $runtime != vm ]
 Language/Classes/Constructors/Constant_Constructors/potentially_constant_expression_t01: Crash
 
-[ $compiler == dartk || $compiler == dartkb ]
-Language/Libraries_and_Scripts/Scripts/top_level_main_t01: Crash
-LibTest/isolate/SendPort/send_A01_t02: Crash
-LibTest/isolate/SendPort/send_A01_t03: Crash
-
 # It makes no sense to run any test that uses spawnURI under the simulator
 # as that would involve running CFE (the front end) in simulator mode
 # to compile the URI file specified in spawnURI code.
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 0e59aaa..d2b5d94 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -45,7 +45,7 @@
 uri_parse_test: Slow, Pass
 uri_test: Slow, Pass
 
-[ $compiler == dartkb || $compiler == dartkp ]
+[ $compiler == dartkp ]
 bigint_parse_radix_test: Slow, Pass # --no_intrinsify
 bigint_test/03: SkipSlow # --no_intrinsify
 bigint_test/15: SkipSlow # --no_intrinsify
diff --git a/tests/corelib/date_time_js_modified_test.dart b/tests/corelib/date_time_js_modified_test.dart
new file mode 100644
index 0000000..92f4b77
--- /dev/null
+++ b/tests/corelib/date_time_js_modified_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// The JavaScript Date constructor 'corrects' 2-digit years NN to 19NN.
+// Verify that a DateTime with year 1 is created correctly.
+// Regression test for https://github.com/dart-lang/sdk/issues/42894
+
+main() {
+  var d = new DateTime(1, 0, 1, 0, 0, 0, 0);
+  var d2 = new DateTime(0, 12, 1, 0, 0, 0, 0);
+
+  Expect.equals(d, d2);
+}
diff --git a/tests/corelib/reg_exp_all_matches_test.dart b/tests/corelib/reg_exp_all_matches_test.dart
index 59996ff..54fbf10 100644
--- a/tests/corelib/reg_exp_all_matches_test.dart
+++ b/tests/corelib/reg_exp_all_matches_test.dart
@@ -10,6 +10,11 @@
   static testIterator() {
     var matches = new RegExp("foo").allMatches("foo foo");
     Iterator it = matches.iterator;
+    if (isStrongMode) {
+      Expect.throws(() => it.current);
+    } else {
+      Expect.isNull(it.current);
+    }
     Expect.isTrue(it.moveNext());
     Expect.equals('foo', it.current.group(0));
     Expect.isTrue(it.moveNext());
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 5226c43..316928f 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -5,6 +5,11 @@
 [ $compiler == dartdevk ]
 regexp/lookbehind_test/01: Skip # Flaky in uncatchable way.  Issue 36280
 
+[ $compiler == dartkp ]
+bigint_parse_radix_test: Slow, Pass # --no_intrinsify
+bigint_test/03: SkipSlow # --no_intrinsify
+bigint_test/15: SkipSlow # --no_intrinsify
+
 [ $mode == debug ]
 regexp/pcre_test: Slow, Pass # Issue 22008
 
@@ -51,11 +56,6 @@
 uri_parse_test: Slow, Pass
 uri_test: Slow, Pass
 
-[ $compiler == dartkb || $compiler == dartkp ]
-bigint_parse_radix_test: Slow, Pass # --no_intrinsify
-bigint_test/03: SkipSlow # --no_intrinsify
-bigint_test/15: SkipSlow # --no_intrinsify
-
 [ $runtime == dart_precompiled || $runtime == vm ]
 regexp/global_test: Skip # Issue 21709
 regexp/pcre_test: Slow, Pass
diff --git a/tests/corelib_2/date_time_js_modified_test.dart b/tests/corelib_2/date_time_js_modified_test.dart
new file mode 100644
index 0000000..92f4b77
--- /dev/null
+++ b/tests/corelib_2/date_time_js_modified_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// The JavaScript Date constructor 'corrects' 2-digit years NN to 19NN.
+// Verify that a DateTime with year 1 is created correctly.
+// Regression test for https://github.com/dart-lang/sdk/issues/42894
+
+main() {
+  var d = new DateTime(1, 0, 1, 0, 0, 0, 0);
+  var d2 = new DateTime(0, 12, 1, 0, 0, 0, 0);
+
+  Expect.equals(d, d2);
+}
diff --git a/tests/corelib_2/reg_exp_all_matches_test.dart b/tests/corelib_2/reg_exp_all_matches_test.dart
index 72a2344..3cb966d 100644
--- a/tests/corelib_2/reg_exp_all_matches_test.dart
+++ b/tests/corelib_2/reg_exp_all_matches_test.dart
@@ -10,6 +10,7 @@
   static testIterator() {
     var matches = new RegExp("foo").allMatches("foo foo");
     Iterator it = matches.iterator;
+    Expect.isNull(it.current);
     Expect.isTrue(it.moveNext());
     Expect.equals('foo', it.current.group(0));
     Expect.isTrue(it.moveNext());
diff --git a/tests/dart2js/async_stacktrace_test.dart b/tests/dart2js/async_stacktrace_test.dart
index fffb946..74a85fd 100644
--- a/tests/dart2js/async_stacktrace_test.dart
+++ b/tests/dart2js/async_stacktrace_test.dart
@@ -26,10 +26,8 @@
   }
 }
 
-Future test1(Tracer tracer) {
-  foo() async
-      * //# asyncStar: ok
-  {
+Future<void> test1(Tracer tracer) {
+  Future<void> foo() async {
     var savedStackTrace;
     try {
       try {
@@ -49,16 +47,36 @@
     tracer.trace("f");
   }
 
-  return foo()
-      .toList() //# asyncStar: continued
-      ;
+  return foo();
 }
 
-Future test2(Tracer tracer) {
+Future<List<void>> test1star(Tracer tracer) {
+  Stream<void> foo() async* {
+    var savedStackTrace;
+    try {
+      try {
+        tracer.trace("a");
+        throw "Error";
+      } catch (e, st) {
+        tracer.trace("b");
+        savedStackTrace = st;
+      }
+      tracer.trace("c");
+      await new Future.error("Error 2", savedStackTrace);
+      tracer.trace("d");
+    } catch (e, st) {
+      tracer.trace("e");
+      Expect.equals(savedStackTrace.toString(), st.toString());
+    }
+    tracer.trace("f");
+  }
+
+  return foo().toList();
+}
+
+Future<void> test2(Tracer tracer) {
   var savedStackTrace;
-  foo() async
-      * //# asyncStar: continued
-  {
+  Future<void> foo() async {
     try {
       tracer.trace("a");
       throw "Error";
@@ -71,19 +89,37 @@
     tracer.trace("d");
   }
 
-  return foo()
-      .toList() //# asyncStar: continued
-      .catchError((e, st) {
+  return foo().catchError((e, st) {
     tracer.trace("e");
     Expect.equals(savedStackTrace.toString(), st.toString());
   });
 }
 
-Future test3(Tracer tracer) {
+Future<List<void>> test2star(Tracer tracer) {
   var savedStackTrace;
-  foo() async
-      * //# asyncStar: continued
-  {
+  Stream<void> foo() async* {
+    try {
+      tracer.trace("a");
+      throw "Error";
+    } catch (e, st) {
+      tracer.trace("b");
+      savedStackTrace = st;
+    }
+    tracer.trace("c");
+    await new Future.error("Error 2", savedStackTrace);
+    tracer.trace("d");
+  }
+
+  return foo().toList().catchError((e, st) {
+    tracer.trace("e");
+    Expect.equals(savedStackTrace.toString(), st.toString());
+    return [];
+  });
+}
+
+Future<void> test3(Tracer tracer) {
+  var savedStackTrace;
+  Future<void> foo() async {
     try {
       tracer.trace("a");
       throw "Error";
@@ -94,14 +130,32 @@
     }
   }
 
-  return foo()
-      .toList() //# asyncStar: continued
-      .catchError((e, st) {
+  return foo().catchError((e, st) {
     tracer.trace("c");
     Expect.equals(savedStackTrace.toString(), st.toString());
   });
 }
 
+Future<List<void>> test3star(Tracer tracer) {
+  var savedStackTrace;
+  Stream<void> foo() async* {
+    try {
+      tracer.trace("a");
+      throw "Error";
+    } catch (e, st) {
+      tracer.trace("b");
+      savedStackTrace = st;
+      rethrow;
+    }
+  }
+
+  return foo().toList().catchError((e, st) {
+    tracer.trace("c");
+    Expect.equals(savedStackTrace.toString(), st.toString());
+    return [];
+  });
+}
+
 runTest(String expectedTrace, Future test(Tracer tracer)) async {
   Tracer tracer = new Tracer(expectedTrace);
   await test(tracer);
@@ -110,8 +164,11 @@
 
 runTests() async {
   await runTest("abcef", test1);
+  await runTest("abcef", test1star);
   await runTest("abce", test2);
+  await runTest("abce", test2star);
   await runTest("abc", test3);
+  await runTest("abc", test3star);
 }
 
 main() {
diff --git a/tests/dart2js/jsinterop_test.dart b/tests/dart2js/jsinterop_test.dart
index 397f5e2..34784e4 100644
--- a/tests/dart2js/jsinterop_test.dart
+++ b/tests/dart2js/jsinterop_test.dart
@@ -21,16 +21,16 @@
 
 topLevelFunction() {}
 
-@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED       //# 01: compile-time error
+@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED  //# 01: compile-time error
 var topLevelJsInteropField; //# 01: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 02: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 02: compile-time error
 get topLevelJsInteropGetter => null; //# 02: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 03: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 03: compile-time error
 set topLevelJsInteropSetter(_) {} //# 03: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 04: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 04: compile-time error
 topLevelJsInteropFunction() {} //# 04: continued
 
 external get externalTopLevelGetter;
@@ -58,7 +58,7 @@
   // NON_NATIVE_EXTERNAL                 //# 09: compile-time error
   external factory Class.externalFact(); //# 09: continued
 
-  @JS('a') // GENERIC, GENERIC  //# 10: compile-time error
+  @JS('a') // GENERIC  //# 10: compile-time error
   Class.jsInteropGenerative(); //# 10: continued
 
   @JS('a') // GENERIC  //# 11: compile-time error
@@ -95,7 +95,7 @@
   @JS('a') // GENERIC  //# 18: compile-time error
   static var staticJsInteropField; //# 18: continued
 
-  @JS('a') // GENERIC  //# 19: compile-time error
+  @JS('a') // GENERIC //# 19: compile-time error
   static get staticJsInteropGetter => null; //# 19: continued
 
   @JS('a') // GENERIC  //# 20: compile-time error
@@ -167,13 +167,13 @@
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
   var instanceField; //# 38: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
+  // GENERIC //# 39: compile-time error
   get instanceGetter => null; //# 39: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
+  // GENERIC //# 40: compile-time error
   set instanceSetter(_) {} //# 40: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
+  // GENERIC //# 41: compile-time error
   instanceMethod() {} //# 41: continued
 
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
@@ -188,16 +188,16 @@
   // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 45: compile-time error
   static staticMethod() {} //# 45: continued
 
-  @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
+  @JS('a') // GENERIC //# 46: compile-time error
   var instanceJsInteropField; //# 46: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
+  @JS('a') // GENERIC //# 48: compile-time error
   get instanceJsInteropGetter => null; //# 48: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
+  @JS('a') // GENERIC //# 49: compile-time error
   set instanceJsInteropSetter(_) {} //# 49: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
+  @JS('a') // GENERIC //# 50: compile-time error
   instanceJsInteropMethod() {} //# 50: continued
 
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
diff --git a/tests/dart2js/native/native_null_assertions/flag_disabled_test.dart b/tests/dart2js/native/native_null_assertions/flag_disabled_test.dart
new file mode 100644
index 0000000..e307833
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/flag_disabled_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'null_assertions_test_lib.dart';
+
+void main() {
+  var flagEnabled = false;
+  testNativeNullAssertions(flagEnabled);
+  testJSInvocationNullAssertions(flagEnabled);
+}
diff --git a/tests/dart2js/native/native_null_assertions/flag_enabled_test.dart b/tests/dart2js/native/native_null_assertions/flag_enabled_test.dart
new file mode 100644
index 0000000..0eb3965
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/flag_enabled_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// dart2jsOptions=--native-null-assertions
+
+import 'null_assertions_test_lib.dart';
+
+void main() {
+  var flagEnabled = true;
+  testNativeNullAssertions(flagEnabled);
+  testJSInvocationNullAssertions(flagEnabled);
+}
diff --git a/tests/dart2js/native/native_null_assertions/js_invocations_in_non_web_library.dart b/tests/dart2js/native/native_null_assertions/js_invocations_in_non_web_library.dart
new file mode 100644
index 0000000..9dd2be1
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/js_invocations_in_non_web_library.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../native_testing.dart';
+import 'null_assertions_lib.dart';
+
+// Implementation of `JSInterface` except in a folder that is not part of the
+// allowlist for the `--native-null-assertions` flag. This file is not treated
+// as a web library, and therefore the `JS()` invocations should not be checked.
+
+@Native('CCCInNonWebLibrary')
+class CCCInNonWebLibrary implements JSInterface {
+  String get name => JS('String', '#.name', this);
+  String? get optName => JS('String|Null', '#.optName', this);
+}
diff --git a/tests/dart2js/native/native_null_assertions/js_invocations_in_web_library.dart b/tests/dart2js/native/native_null_assertions/js_invocations_in_web_library.dart
new file mode 100644
index 0000000..0554ab4
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/js_invocations_in_web_library.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../native_testing.dart';
+import 'null_assertions_lib.dart';
+
+// Implementation of `JSInterface` in a folder that is explicitly part of the
+// allowlist for the `--native-null-assertions` flag. This file is treated as a
+// web library, and therefore the `JS()` invocations should be checked.
+
+@Native('CCCInWebLibrary')
+class CCCInWebLibrary implements JSInterface {
+  String get name => JS('String', '#.name', this);
+  String? get optName => JS('String|Null', '#.optName', this);
+}
diff --git a/tests/dart2js/native/native_null_assertions/null_assertions_lib.dart b/tests/dart2js/native/native_null_assertions/null_assertions_lib.dart
new file mode 100644
index 0000000..894fdf0
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/null_assertions_lib.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../native_testing.dart';
+
+abstract class NativeInterface {
+  int get size;
+  String get name;
+  String? get optName;
+  int method1();
+  String method2();
+  String? optMethod();
+}
+
+@Native("AAA")
+class AAA implements NativeInterface {
+  int get size native;
+  String get name native;
+  String? get optName native;
+  int method1() native;
+  String method2() native;
+  String? optMethod() native;
+}
+
+abstract class JSInterface {
+  String get name;
+  String? get optName;
+}
+
+class BBB implements NativeInterface {
+  int get size => 300;
+  String get name => 'Brenda';
+  String? get optName => name;
+  int method1() => 400;
+  String method2() => 'brilliant!';
+  String? optMethod() => method2();
+}
diff --git a/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart b/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart
new file mode 100644
index 0000000..3f1f540
--- /dev/null
+++ b/tests/dart2js/native/native_null_assertions/null_assertions_test_lib.dart
@@ -0,0 +1,193 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../native_testing.dart';
+import 'js_invocations_in_non_web_library.dart';
+import 'js_invocations_in_web_library.dart';
+import 'null_assertions_lib.dart';
+
+/// Returns an 'AAA' object that satisfies the interface.
+AAA makeA() native;
+
+/// Returns an 'AAA' object where each method breaks the interface's contract.
+AAA makeAX() native;
+
+/// Returns a 'JSInterface' object whose `JS()` invocations exist in a library
+/// that is part of the allowlist.
+CCCInWebLibrary makeWebC() native;
+
+/// Returns the same as above but where each method breaks the interface's
+/// contract.
+CCCInWebLibrary makeWebCX() native;
+
+/// Returns a 'JSInterface' object whose `JS()` invocations exist in a library
+/// that is not part of the allowlist.
+CCCInNonWebLibrary makeNonWebC() native;
+
+/// Returns the same as above but where each method breaks the interface's
+/// contract.
+CCCInNonWebLibrary makeNonWebCX() native;
+
+void setup() {
+  JS('', r"""
+(function(){
+  function AAA(s,n,m1,m2) {
+    this.size = s;
+    this.name = n;
+    this.optName = n;
+    this._m1 = m1;
+    this._m2 = m2;
+  }
+  AAA.prototype.method1 = function(){return this._m1};
+  AAA.prototype.method2 = function(){return this._m2};
+  AAA.prototype.optMethod = function(){return this._m2};
+
+  makeA = function() {
+    return new AAA(100, 'Albert', 200, 'amazing!');
+  };
+  makeAX = function() {
+    return new AAA(void 0, void 0, void 0, void 0);
+  };
+
+  self.nativeConstructor(AAA);
+
+  function CCCInWebLibrary(n) {
+    this.name = n;
+    this.optName = n;
+  }
+  function CCCInNonWebLibrary(n) {
+    this.name = n;
+    this.optName = n;
+  }
+
+  makeWebC = function() {
+    return new CCCInWebLibrary('Carol');
+  };
+  makeWebCX = function() {
+    return new CCCInWebLibrary(void 0);
+  };
+  makeNonWebC = function() {
+    return new CCCInNonWebLibrary('Carol');
+  };
+  makeNonWebCX = function() {
+    return new CCCInNonWebLibrary(void 0);
+  };
+
+  self.nativeConstructor(CCCInWebLibrary);
+  self.nativeConstructor(CCCInNonWebLibrary);
+})()""");
+}
+
+// The 'NativeInterface' version of the code is passed both native and Dart
+// objects, so there will be an interceptor dispatch to the method. This tests
+// that the null-check exists in the forwarding method.
+//
+// The 'AAA' version of the code is passed only objects of a single native
+// class, so the native method can be inlined (which happens in the optimizer).
+// This tests that the null-check exists in the 'inlined' code.
+
+@pragma('dart2js:noInline')
+String describeNativeInterface(NativeInterface o) {
+  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
+}
+
+@pragma('dart2js:noInline')
+String describeAAA(AAA o) {
+  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
+}
+
+@pragma('dart2js:noInline')
+String describeOptNativeInterface(NativeInterface o) {
+  return '${o.optName} ${o.optMethod()}';
+}
+
+@pragma('dart2js:noInline')
+String describeOptAAA(AAA o) {
+  return '${o.optName} ${o.optMethod()}';
+}
+
+@pragma('dart2js:noInline')
+String describeJSInterface(JSInterface o) {
+  return '${o.name}';
+}
+
+@pragma('dart2js:noInline')
+String describeOptJSInterface(JSInterface o) {
+  return '${o.optName}';
+}
+
+const expectedA = 'Albert amazing! 100 200';
+const expectedB = 'Brenda brilliant! 300 400';
+const expectedOptA = 'Albert amazing!';
+const expectedOptB = 'Brenda brilliant!';
+const expectedOptX = 'null null';
+
+const expectedC = 'Carol';
+const expectedOptC = 'Carol';
+const expectedOptCX = 'null';
+
+// Test that `--native-null-assertions` injects null-checks on the returned
+// value of native methods with a non-nullable return type in an opt-in library.
+void testNativeNullAssertions(bool flagEnabled) {
+  nativeTesting();
+  setup();
+  AAA a = makeA();
+  BBB b = BBB();
+
+  Expect.equals(expectedA, describeNativeInterface(a));
+  Expect.equals(expectedB, describeNativeInterface(b));
+
+  Expect.equals(expectedA, describeAAA(a));
+
+  AAA x = makeAX(); // This object returns `null`!
+  var checkExpectation = flagEnabled ? Expect.throws : (f) => f();
+  checkExpectation(() => describeNativeInterface(x));
+  checkExpectation(() => describeAAA(x));
+
+  checkExpectation(() => x.name);
+  checkExpectation(() => x.size);
+  checkExpectation(() => x.method1());
+  checkExpectation(() => x.method2());
+
+  // Now test that a nullable return type does not have a check.
+  Expect.equals(expectedOptA, describeOptNativeInterface(a));
+  Expect.equals(expectedOptB, describeOptNativeInterface(b));
+  Expect.equals(expectedOptX, describeOptNativeInterface(x));
+
+  Expect.equals(expectedOptA, describeOptAAA(a));
+  Expect.equals(expectedOptX, describeOptAAA(x));
+}
+
+// Test that `--native-null-assertions` injects null-checks on the returned
+// value of `JS()` invocations with a non-nullable static type in an opt-in
+// library.
+void testJSInvocationNullAssertions(bool flagEnabled) {
+  nativeTesting();
+  setup();
+
+  CCCInWebLibrary webC = makeWebC();
+  CCCInWebLibrary webCX = makeWebCX();
+
+  CCCInNonWebLibrary nonWebC = makeNonWebC();
+  CCCInNonWebLibrary nonWebCX = makeNonWebCX();
+
+  Expect.equals(expectedC, describeJSInterface(webC));
+  Expect.equals(expectedC, describeJSInterface(nonWebC));
+
+  // If invocations are in a web library, this should throw if null checks are
+  // enabled.
+  var checkExpectationWeb = flagEnabled ? Expect.throws : (f) => f();
+  checkExpectationWeb(() => describeJSInterface(webCX));
+
+  // If invocations are not in a web library, there should not be a null check
+  // regardless if the flag is enabled or not.
+  var checkExpectationNonWeb = (f) => f();
+  checkExpectationNonWeb(() => describeJSInterface(nonWebCX));
+
+  // Test that invocations with a nullable static type do not have checks.
+  Expect.equals(expectedOptC, describeOptJSInterface(webC));
+  Expect.equals(expectedOptC, describeOptJSInterface(nonWebC));
+  Expect.equals(expectedOptCX, describeOptJSInterface(webCX));
+  Expect.equals(expectedOptCX, describeOptJSInterface(nonWebCX));
+}
diff --git a/tests/dart2js/native/null_assertions_opt_in_lib.dart b/tests/dart2js/native/null_assertions_opt_in_lib.dart
deleted file mode 100644
index e08c788..0000000
--- a/tests/dart2js/native/null_assertions_opt_in_lib.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'native_testing.dart';
-
-abstract class Interface {
-  int get size;
-  String get name;
-  String? get optName;
-  int method1();
-  String method2();
-}
-
-@Native("AAA")
-class AAA implements Interface {
-  int get size native;
-  String get name native;
-  String? get optName native;
-  int method1() native;
-  String method2() native;
-}
-
-/// Returns an 'AAA' object that satisfies the interface.
-AAA makeA() native;
-
-/// Returns an 'AAA' object where each method breaks the interface's contract.
-AAA makeAX() native;
-
-void setup() {
-  JS('', r"""
-(function(){
-  function AAA(s,n,m1,m2) {
-    this.size = s;
-    this.name = n;
-    this.optName = n;
-    this._m1 = m1;
-    this._m2 = m2;
-  }
-  AAA.prototype.method1 = function(){return this._m1};
-  AAA.prototype.method2 = function(){return this._m2};
-
-  makeA = function() {return new AAA(100, 'Albert', 200, 'amazing!')};
-  makeAX = function() {return new AAA(void 0, void 0, void 0, void 0)};
-
-  self.nativeConstructor(AAA);
-})()""");
-}
-
-class BBB implements Interface {
-  int get size => 300;
-  String get name => 'Brenda';
-  String? get optName => name;
-  int method1() => 400;
-  String method2() => 'brilliant!';
-}
-
-List<Interface> items = [makeA(), BBB()];
diff --git a/tests/dart2js/native/null_assertions_test.dart b/tests/dart2js/native/null_assertions_test.dart
deleted file mode 100644
index 0a07785..0000000
--- a/tests/dart2js/native/null_assertions_test.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Requirements=nnbd-weak
-// dart2jsOptions=--null-assertions
-
-// @dart=2.8
-
-// Test that `--null-assertions` injects null-checks on the returned value of
-// native methods with a non-nullable return type in an opt-in library.
-
-import 'native_testing.dart';
-import 'null_assertions_opt_in_lib.dart' as lib;
-
-// The 'Interface' version of the code is passed both native and Dart objects,
-// so there will be an interceptor dispatch to the method. This tests that the
-// null-check exists in the forwarding method.
-//
-// The 'AAA' version of the code is passed only objects of a single native
-// class, so the native method can be inlined (which happens in the optimizer).
-// This tests that the null-check exists in the 'inlined' code.
-
-@pragma('dart2js:noInline')
-String describeInterface(lib.Interface o) {
-  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
-}
-
-@pragma('dart2js:noInline')
-String describeAAA(lib.AAA o) {
-  return '${o.name} ${o.method2()} ${o.size} ${o.method1()}';
-}
-
-@pragma('dart2js:noInline')
-void checkOptNameInterface(lib.Interface o, dynamic expected) {
-  Expect.equals(expected, o.optName);
-}
-
-@pragma('dart2js:noInline')
-void checkOptNameAAA(lib.AAA o, dynamic expected) {
-  Expect.equals(expected, o.optName);
-}
-
-const expectedA = 'Albert amazing! 100 200';
-const expectedB = 'Brenda brilliant! 300 400';
-
-void main() {
-  nativeTesting();
-  lib.setup();
-  lib.AAA a = lib.makeA();
-  lib.BBB b = lib.BBB();
-
-  Expect.equals(expectedA, describeInterface(a));
-  Expect.equals(expectedB, describeInterface(b));
-
-  Expect.equals(expectedA, describeAAA(a));
-
-  lib.AAA x = lib.makeAX(); // This object returns `null`!
-  Expect.throws(() => describeInterface(x));
-  Expect.throws(() => describeAAA(x));
-
-  Expect.throws(() => x.name);
-  Expect.throws(() => x.size);
-  Expect.throws(() => x.method1());
-  Expect.throws(() => x.method2());
-
-  // Now test that a nullable return type does not have a check.
-  checkOptNameInterface(a, 'Albert');
-  checkOptNameInterface(b, 'Brenda');
-  checkOptNameInterface(x, null);
-
-  checkOptNameAAA(a, 'Albert');
-  checkOptNameAAA(x, null);
-}
diff --git a/tests/dart2js/non_jsinterop_test.dart b/tests/dart2js/non_jsinterop_test.dart
index 68eebe7..91af080 100644
--- a/tests/dart2js/non_jsinterop_test.dart
+++ b/tests/dart2js/non_jsinterop_test.dart
@@ -20,16 +20,16 @@
 
 topLevelFunction() {}
 
-@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED       //# 01: compile-time error
+@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED  //# 01: compile-time error
 var topLevelJsInteropField; //# 01: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 02: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 02: compile-time error
 get topLevelJsInteropGetter => null; //# 02: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 03: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 03: compile-time error
 set topLevelJsInteropSetter(_) {} //# 03: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 04: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 04: compile-time error
 topLevelJsInteropFunction() {} //# 04: continued
 
 // NON_NATIVE_EXTERNAL               //# 05: compile-time error
@@ -60,9 +60,6 @@
   // NON_NATIVE_EXTERNAL                 //# 09: compile-time error
   external factory Class.externalFact(); //# 09: continued
 
-  @JS('a') // GENERIC, GENERIC  //# 10: compile-time error
-  Class.jsInteropGenerative(); //# 10: continued
-
   @JS('a') // GENERIC  //# 11: compile-time error
   factory Class.jsInteropFact() => null; //# 11: continued
 
@@ -169,13 +166,13 @@
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
   var instanceField; //# 38: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
+  // GENERIC //# 39: compile-time error
   get instanceGetter => null; //# 39: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
+  // GENERIC //# 40: compile-time error
   set instanceSetter(_) {} //# 40: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
+  // GENERIC //# 41: compile-time error
   instanceMethod() {} //# 41: continued
 
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
@@ -193,13 +190,13 @@
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
   var instanceJsInteropField; //# 46: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
+  @JS('a') // GENERIC //# 48: compile-time error
   get instanceJsInteropGetter => null; //# 48: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
+  @JS('a') // GENERIC //# 49: compile-time error
   set instanceJsInteropSetter(_) {} //# 49: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
+  @JS('a') // GENERIC //# 50: compile-time error
   instanceJsInteropMethod() {} //# 50: continued
 
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
diff --git a/tests/dart2js/sync_star_element_rti_need_test.dart b/tests/dart2js/sync_star_element_rti_need_test.dart
new file mode 100644
index 0000000..d82ee28
--- /dev/null
+++ b/tests/dart2js/sync_star_element_rti_need_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  var x = [1, 2, 3];
+  Expect.listEquals(x, nop(x).toList());
+}
+
+Iterable<T> nop<T>(Iterable<T> values) {
+  Iterable<T> inner() sync* {
+    yield* values;
+    return;
+  }
+
+  return inner();
+}
diff --git a/tests/dart2js_2/jsinterop_test.dart b/tests/dart2js_2/jsinterop_test.dart
index 2db564c..ea9d508 100644
--- a/tests/dart2js_2/jsinterop_test.dart
+++ b/tests/dart2js_2/jsinterop_test.dart
@@ -23,16 +23,16 @@
 
 topLevelFunction() {}
 
-@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED       //# 01: compile-time error
+@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED  //# 01: compile-time error
 var topLevelJsInteropField; //# 01: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 02: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 02: compile-time error
 get topLevelJsInteropGetter => null; //# 02: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 03: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 03: compile-time error
 set topLevelJsInteropSetter(_) {} //# 03: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 04: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 04: compile-time error
 topLevelJsInteropFunction() {} //# 04: continued
 
 external get externalTopLevelGetter;
@@ -52,7 +52,7 @@
 
 class Class {
   Class.generative();
-  factory Class.fact() => null;
+  factory Class.fact() => null as dynamic;
 
   // NON_NATIVE_EXTERNAL               //# 08: compile-time error
   external Class.externalGenerative(); //# 08: continued
@@ -60,7 +60,7 @@
   // NON_NATIVE_EXTERNAL                 //# 09: compile-time error
   external factory Class.externalFact(); //# 09: continued
 
-  @JS('a') // GENERIC, GENERIC  //# 10: compile-time error
+  @JS('a') // GENERIC  //# 10: compile-time error
   Class.jsInteropGenerative(); //# 10: continued
 
   @JS('a') // GENERIC  //# 11: compile-time error
@@ -97,7 +97,7 @@
   @JS('a') // GENERIC  //# 18: compile-time error
   static var staticJsInteropField; //# 18: continued
 
-  @JS('a') // GENERIC  //# 19: compile-time error
+  @JS('a') // GENERIC //# 19: compile-time error
   static get staticJsInteropGetter => null; //# 19: continued
 
   @JS('a') // GENERIC  //# 20: compile-time error
@@ -169,13 +169,13 @@
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
   var instanceField; //# 38: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
+  // GENERIC //# 39: compile-time error
   get instanceGetter => null; //# 39: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
+  // GENERIC //# 40: compile-time error
   set instanceSetter(_) {} //# 40: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
+  // GENERIC //# 41: compile-time error
   instanceMethod() {} //# 41: continued
 
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
@@ -190,16 +190,16 @@
   // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 45: compile-time error
   static staticMethod() {} //# 45: continued
 
-  @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
+  @JS('a') // GENERIC //# 46: compile-time error
   var instanceJsInteropField; //# 46: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
+  @JS('a') // GENERIC //# 48: compile-time error
   get instanceJsInteropGetter => null; //# 48: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
+  @JS('a') // GENERIC //# 49: compile-time error
   set instanceJsInteropSetter(_) {} //# 49: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
+  @JS('a') // GENERIC //# 50: compile-time error
   instanceJsInteropMethod() {} //# 50: continued
 
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
diff --git a/tests/dart2js_2/non_jsinterop_test.dart b/tests/dart2js_2/non_jsinterop_test.dart
index 1bac858..7b533ac 100644
--- a/tests/dart2js_2/non_jsinterop_test.dart
+++ b/tests/dart2js_2/non_jsinterop_test.dart
@@ -22,16 +22,16 @@
 
 topLevelFunction() {}
 
-@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED       //# 01: compile-time error
+@JS('a') // JS_INTEROP_FIELD_NOT_SUPPORTED  //# 01: compile-time error
 var topLevelJsInteropField; //# 01: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 02: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 02: compile-time error
 get topLevelJsInteropGetter => null; //# 02: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 03: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 03: compile-time error
 set topLevelJsInteropSetter(_) {} //# 03: continued
 
-@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER       //# 04: compile-time error
+@JS('a') // JS_INTEROP_NON_EXTERNAL_MEMBER  //# 04: compile-time error
 topLevelJsInteropFunction() {} //# 04: continued
 
 // NON_NATIVE_EXTERNAL               //# 05: compile-time error
@@ -54,7 +54,7 @@
 
 class Class {
   Class.generative();
-  factory Class.fact() => null;
+  factory Class.fact() => null as dynamic;
 
   // NON_NATIVE_EXTERNAL               //# 08: compile-time error
   external Class.externalGenerative(); //# 08: continued
@@ -62,9 +62,6 @@
   // NON_NATIVE_EXTERNAL                 //# 09: compile-time error
   external factory Class.externalFact(); //# 09: continued
 
-  @JS('a') // GENERIC, GENERIC  //# 10: compile-time error
-  Class.jsInteropGenerative(); //# 10: continued
-
   @JS('a') // GENERIC  //# 11: compile-time error
   factory Class.jsInteropFact() => null; //# 11: continued
 
@@ -171,13 +168,13 @@
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 38: compile-time error
   var instanceField; //# 38: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 39: compile-time error
+  // GENERIC //# 39: compile-time error
   get instanceGetter => null; //# 39: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 40: compile-time error
+  // GENERIC //# 40: compile-time error
   set instanceSetter(_) {} //# 40: continued
 
-  // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 41: compile-time error
+  // GENERIC //# 41: compile-time error
   instanceMethod() {} //# 41: continued
 
   // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 42: compile-time error
@@ -195,13 +192,13 @@
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 46: compile-time error
   var instanceJsInteropField; //# 46: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 48: compile-time error
+  @JS('a') // GENERIC //# 48: compile-time error
   get instanceJsInteropGetter => null; //# 48: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 49: compile-time error
+  @JS('a') // GENERIC //# 49: compile-time error
   set instanceJsInteropSetter(_) {} //# 49: continued
 
-  @JS('a') // JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER //# 50: compile-time error
+  @JS('a') // GENERIC //# 50: compile-time error
   instanceJsInteropMethod() {} //# 50: continued
 
   @JS('a') // IMPLICIT_JS_INTEROP_FIELD_NOT_SUPPORTED //# 51: compile-time error
diff --git a/tests/dart2js_2/sync_star_element_rti_need_test.dart b/tests/dart2js_2/sync_star_element_rti_need_test.dart
new file mode 100644
index 0000000..d82ee28
--- /dev/null
+++ b/tests/dart2js_2/sync_star_element_rti_need_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+main() {
+  var x = [1, 2, 3];
+  Expect.listEquals(x, nop(x).toList());
+}
+
+Iterable<T> nop<T>(Iterable<T> values) {
+  Iterable<T> inner() sync* {
+    yield* values;
+    return;
+  }
+
+  return inner();
+}
diff --git a/tests/dartdevc/hot_restart_js_interop_test.dart b/tests/dartdevc/hot_restart_js_interop_test.dart
new file mode 100644
index 0000000..e3899df
--- /dev/null
+++ b/tests/dartdevc/hot_restart_js_interop_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests that JS interop works with hot restart.
+
+// Requirements=nnbd
+
+@JS()
+library hot_restart_js_interop_test;
+
+import 'dart:js' show context;
+import 'dart:js_util';
+import 'dart:_foreign_helper' as helper show JS;
+import 'dart:_runtime' as dart;
+
+import 'package:expect/expect.dart';
+import 'package:js/js.dart';
+
+@JS()
+external void eval(String code);
+
+@JS('window.MyClass')
+class MyClass {
+  external MyClass();
+}
+
+abstract class Wrapper<T> {
+  T? rawObject;
+
+  Wrapper() {
+    final T defaultObject = createDefault();
+    rawObject = defaultObject;
+  }
+
+  T createDefault();
+}
+
+class WrappedClass extends Wrapper<MyClass> {
+  @override
+  MyClass createDefault() => MyClass();
+}
+
+void main() {
+  // See: https://github.com/flutter/flutter/issues/66361
+  eval("self.MyClass = function MyClass() {}");
+  var c = WrappedClass();
+  dart.hotRestart();
+  eval("self.MyClass = function MyClass() {}");
+  c = WrappedClass();
+}
diff --git a/tests/ffi/regress_43693_test.dart b/tests/ffi/regress_43693_test.dart
new file mode 100644
index 0000000..a34e8f8
--- /dev/null
+++ b/tests/ffi/regress_43693_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:expect/expect.dart';
+
+import 'dylib_utils.dart';
+
+class Struct43693 extends Struct {
+  external Pointer<Void> somePtr;
+
+  @Uint64()
+  external int someValue;
+}
+
+final int Function(Pointer<Struct43693>) readMyStructSomeValue =
+    ffiTestFunctions
+        .lookup<NativeFunction<Uint64 Function(Pointer<Struct43693>)>>(
+            "Regress43693")
+        .asFunction<int Function(Pointer<Struct43693>)>();
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+void main() {
+  final myStructs = allocate<Struct43693>();
+  myStructs[0].somePtr = nullptr;
+  myStructs[0].someValue = 0xAAAAAAAABBBBBBBB;
+  final result = readMyStructSomeValue(myStructs);
+  Expect.equals(0xAAAAAAAABBBBBBBB, result);
+  free(myStructs);
+}
diff --git a/tests/ffi_2/regress_43693_test.dart b/tests/ffi_2/regress_43693_test.dart
new file mode 100644
index 0000000..a30a118
--- /dev/null
+++ b/tests/ffi_2/regress_43693_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import 'package:ffi/ffi.dart';
+import 'package:expect/expect.dart';
+
+import 'dylib_utils.dart';
+
+class Struct43693 extends Struct {
+  Pointer<Void> somePtr;
+
+  @Uint64()
+  int someValue;
+}
+
+final int Function(Pointer<Struct43693>) readMyStructSomeValue =
+    ffiTestFunctions
+        .lookup<NativeFunction<Uint64 Function(Pointer<Struct43693>)>>(
+            "Regress43693")
+        .asFunction<int Function(Pointer<Struct43693>)>();
+
+final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+void main() {
+  final myStructs = allocate<Struct43693>();
+  myStructs[0].somePtr = nullptr;
+  myStructs[0].someValue = 0xAAAAAAAABBBBBBBB;
+  final result = readMyStructSomeValue(myStructs);
+  Expect.equals(0xAAAAAAAABBBBBBBB, result);
+  free(myStructs);
+}
diff --git a/tests/kernel/kernel.status b/tests/kernel/kernel.status
deleted file mode 100644
index 00f926c..0000000
--- a/tests/kernel/kernel.status
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-# for details. All rights reserved. Use of this source code is governed by a
-# BSD-style license that can be found in the LICENSE file.
-
-[ $compiler == dart2js ]
-unsorted/nsm_dispatcher_test: Skip # The test uses Symbol without MirrorsUsed
-unsorted/simple_literal_test/01: Skip # The test expects error for large integer literal.
-
-[ !$fasta ]
-unsorted/loop_test: Skip # This test uses optional new/const.
diff --git a/tests/kernel/unsorted/as_is_test.dart b/tests/kernel/unsorted/as_is_test.dart
deleted file mode 100644
index 846fdf1..0000000
--- a/tests/kernel/unsorted/as_is_test.dart
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of class literals, is, and as expressions.
-
-import 'package:expect/expect.dart';
-
-class C {}
-
-class D extends C {}
-
-test0() => C;
-test1() => D;
-
-main() {
-  var c = new C();
-  var d = new D();
-  Expect.isTrue(test0() == C);
-  Expect.isTrue(test1() == D);
-  Expect.isTrue(c is C);
-  Expect.isTrue(c is! D);
-  Expect.isTrue(d is C);
-  Expect.isTrue(d is D);
-  Expect.isTrue(c as C == c);
-  Expect.isTrue(d as C == d);
-  Expect.isTrue(d as D == d);
-}
diff --git a/tests/kernel/unsorted/block_scope_test.dart b/tests/kernel/unsorted/block_scope_test.dart
deleted file mode 100644
index 7a70e16..0000000
--- a/tests/kernel/unsorted/block_scope_test.dart
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of block scoping.
-
-import 'package:expect/expect.dart';
-
-bool oracle() => true;
-
-test0() {
-  var x = 'outer', y = x;
-  Expect.isTrue(x == 'outer');
-  Expect.isTrue(y == 'outer');
-  {
-    var x = 'inner';
-    Expect.isTrue(x == 'inner');
-    Expect.isTrue(y == 'outer');
-  }
-  Expect.isTrue(x == 'outer');
-  Expect.isTrue(y == 'outer');
-
-  if (oracle()) {
-    var y = 'inner';
-    Expect.isTrue(x == 'outer');
-    Expect.isTrue(y == 'inner');
-  } else {
-    Expect.isTrue(false);
-  }
-  Expect.isTrue(x == 'outer');
-  Expect.isTrue(y == 'outer');
-}
-
-var x = 'toplevel';
-
-test1() {
-  var y = 'outer';
-  Expect.isTrue(x == 'toplevel');
-  Expect.isTrue(y == 'outer');
-  {
-    var x = 'inner';
-    Expect.isTrue(x == 'inner');
-    Expect.isTrue(y == 'outer');
-  }
-  Expect.isTrue(x == 'toplevel');
-  Expect.isTrue(y == 'outer');
-
-  if (oracle()) {
-    var y = 'inner';
-    Expect.isTrue(x == 'toplevel');
-    Expect.isTrue(y == 'inner');
-  } else {
-    Expect.isTrue(false);
-  }
-  Expect.isTrue(x == 'toplevel');
-  Expect.isTrue(y == 'outer');
-}
-
-main() {
-  test0();
-  test1();
-}
diff --git a/tests/kernel/unsorted/breakable_statement_test.dart b/tests/kernel/unsorted/breakable_statement_test.dart
deleted file mode 100644
index eb07239..0000000
--- a/tests/kernel/unsorted/breakable_statement_test.dart
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-testFor() {
-  int current;
-  for (int i = 0; i < 100; i++) {
-    current = i;
-    if (i > 41) break;
-  }
-  Expect.isTrue(current == 42);
-}
-
-testWhile() {
-  int i = 0;
-  while (i < 100) {
-    if (++i > 41) break;
-  }
-  Expect.isTrue(i == 42);
-}
-
-testDoWhile() {
-  int i = 0;
-  do {
-    if (++i > 41) break;
-  } while (i < 100);
-  Expect.isTrue(i == 42);
-}
-
-testLabledBreakOutermost() {
-  int i = 0;
-  outer:
-  {
-    middle:
-    {
-      while (i < 100) {
-        if (++i > 41) break outer;
-      }
-      i++;
-    }
-    i++;
-  }
-  Expect.isTrue(i == 42);
-}
-
-testLabledBreakMiddle() {
-  int i = 0;
-  outer:
-  {
-    middle:
-    {
-      while (i < 100) {
-        if (++i > 41) break middle;
-      }
-      i++;
-    }
-    i++;
-  }
-  Expect.isTrue(i == 43);
-}
-
-testLabledBreakInner() {
-  int i = 0;
-  outer:
-  {
-    middle:
-    {
-      while (i < 100) {
-        if (++i > 41) break;
-      }
-      i++;
-    }
-    i++;
-  }
-  Expect.isTrue(i == 44);
-}
-
-main() {
-  testFor();
-  testWhile();
-  testDoWhile();
-  testLabledBreakOutermost();
-  testLabledBreakMiddle();
-  testLabledBreakInner();
-}
diff --git a/tests/kernel/unsorted/closures_regression_test.dart b/tests/kernel/unsorted/closures_regression_test.dart
deleted file mode 100644
index 9721385..0000000
--- a/tests/kernel/unsorted/closures_regression_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-f(fun) => fun();
-
-class A {
-  identity(arg) {
-    return f(() {
-      print(this);
-      return f(() {
-        return this;
-      });
-    });
-  }
-}
-
-main() {
-  var a = new A();
-  Expect.isTrue(identical(a.identity(42), a));
-}
diff --git a/tests/kernel/unsorted/closures_test.dart b/tests/kernel/unsorted/closures_test.dart
deleted file mode 100644
index df3430f..0000000
--- a/tests/kernel/unsorted/closures_test.dart
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class Base {
-  int constant1000() => 1000;
-}
-
-class Foo extends Base {
-  final int base;
-  Foo(this.base);
-
-  nestedAdderFunction(a, b, c, d, e) {
-    var result = a + b;
-    return () {
-      var result2 = c + d;
-      return () {
-        return base + result + result2 + e;
-      };
-    };
-  }
-
-  nestedAdderFunction2(a, b, c, d, e) {
-    var result = a + b;
-    return () {
-      var base = super.constant1000;
-      var result2 = c + d;
-      return () {
-        return base() + result + result2 + e;
-      };
-    };
-  }
-}
-
-nestedAdderFunction(a, b, c, d, e) {
-  var result = a + b;
-  return () {
-    var result2 = c + d;
-    return () {
-      return result + result2 + e;
-    };
-  };
-}
-
-main() {
-  Expect.isTrue(nestedAdderFunction(1, 2, 3, 4, 5)()() == 15);
-
-  var foo = new Foo(100);
-  Expect.isTrue(foo.nestedAdderFunction(1, 2, 3, 4, 5)()() == 115);
-  Expect.isTrue(foo.nestedAdderFunction2(1, 2, 3, 4, 5)()() == 1015);
-
-  var funs = [];
-  for (int i = 0; i < 3; i++) {
-    funs.add(() => i);
-  }
-  Expect.isTrue((funs[0]() + funs[1]() + funs[2]()) == 3);
-
-  var funs2 = [];
-  for (var i in [0, 1, 2]) {
-    funs2.add(() => i);
-  }
-  Expect.isTrue((funs2[0]() + funs2[1]() + funs2[2]()) == 3);
-}
diff --git a/tests/kernel/unsorted/conditional_test.dart b/tests/kernel/unsorted/conditional_test.dart
deleted file mode 100644
index 3bf30a3..0000000
--- a/tests/kernel/unsorted/conditional_test.dart
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of conditional expressions and statements and negation.
-
-import 'package:expect/expect.dart';
-
-mkTrue() => true;
-mkFalse() => false;
-
-check(b) {
-  Expect.isTrue(b);
-  return b;
-}
-
-main() {
-  // Check that ?: gets the right answer.
-  Expect.isTrue((mkTrue() ? 0 : 1) == 0);
-  Expect.isTrue((mkFalse() ? 0 : 1) == 1);
-  // Check that it doesn't evaluate all subexpressions.
-  mkTrue() ? Expect.isTrue(true) : Expect.isTrue(false);
-  mkFalse() ? Expect.isTrue(false) : Expect.isTrue(true);
-
-  // Check that && and || get the right answers.
-  Expect.isTrue(mkTrue() && mkTrue());
-  Expect.isTrue(!(mkTrue() && mkFalse()));
-  Expect.isTrue(!(mkFalse() && mkTrue()));
-  Expect.isTrue(!(mkFalse() && mkFalse()));
-  Expect.isTrue(mkTrue() || mkTrue());
-  Expect.isTrue(mkTrue() || mkFalse());
-  Expect.isTrue(mkFalse() || mkTrue());
-  Expect.isTrue(!(mkFalse() || mkFalse()));
-
-  // Check that they don't evaluate both subexpressions.
-  mkTrue() && check(true);
-  mkFalse() && check(false);
-  mkTrue() || check(true);
-  mkFalse() || check(true);
-
-  // Check that if works.
-  if (mkTrue()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkFalse()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (!mkTrue()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (!mkFalse()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-
-  // Check that ?:, &&, and || work for control flow.
-  if (mkTrue() ? mkTrue() : mkFalse()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkTrue() ? mkFalse() : mkTrue()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (mkFalse() ? mkTrue() : mkFalse()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (mkFalse() ? mkFalse() : mkTrue()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkTrue() && mkTrue()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkTrue() && mkFalse()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (mkFalse() && mkTrue()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (mkFalse() && mkFalse()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-  if (mkTrue() || mkTrue()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkTrue() || mkFalse()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkFalse() || mkTrue()) {
-    Expect.isTrue(true);
-  } else {
-    Expect.isTrue(false);
-  }
-  if (mkFalse() || mkFalse()) {
-    Expect.isTrue(false);
-  } else {
-    Expect.isTrue(true);
-  }
-
-  // Test empty else branches.
-  if (mkTrue()) {
-    Expect.isTrue(true);
-  }
-  if (mkFalse()) {
-    Expect.isTrue(false);
-  }
-
-  var x = 0;
-  if (mkTrue()) {
-    x = 1;
-  }
-  Expect.isTrue(x == 1);
-  if (mkFalse()) {
-    x = 2;
-  }
-  Expect.isTrue(x == 1);
-}
diff --git a/tests/kernel/unsorted/constant_evaluator_regression_test.dart b/tests/kernel/unsorted/constant_evaluator_regression_test.dart
deleted file mode 100644
index e5c79c6..0000000
--- a/tests/kernel/unsorted/constant_evaluator_regression_test.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-const X = const bool.fromEnvironment('foobar');
-
-main() {
-  Expect.isTrue(X == false);
-}
diff --git a/tests/kernel/unsorted/constant_expressions_test.dart b/tests/kernel/unsorted/constant_expressions_test.dart
deleted file mode 100644
index 2dbec48..0000000
--- a/tests/kernel/unsorted/constant_expressions_test.dart
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-const int42 = 40 + 2;
-const stringAB = 'a' + 'b';
-const stringAB2 = 'a' + 'b';
-const list123 = const [1, 2, 3];
-const mapABC = const {'a': 'b', 'b': 'c'};
-
-const boxInt42 = const Box(int42);
-const boxStringAB = const Box(stringAB);
-
-class Box {
-  final value;
-  const Box(this.value);
-}
-
-returnPositional([a = const Box('posi' + 'tional')]) => a;
-
-returnNamed({a: const Box('nam' + 'ed')}) => a;
-
-returnSwitchCasedValue(value) {
-  switch (value) {
-    case const Box(42):
-      return 42;
-    case const Box('abc'):
-      return 'abc';
-    case const Box(const Box('abc')):
-      return const Box('abc');
-    default:
-      return 'default';
-  }
-}
-
-testConstantExpressions() {
-  Expect.isTrue(identical(const Box(40 + 2), const Box(40 + 2)));
-  Expect.isTrue(identical(const Box('a' + 'b'), const Box('ab')));
-  Expect.isTrue(
-      identical(const Box(const Box(40 + 2)), const Box(const Box(42))));
-  Expect.isTrue(
-      identical(const Box(const Box('a' + 'b')), const Box(const Box('ab'))));
-}
-
-testConstantFieldValues() {
-  Expect.isTrue(identical(42, int42));
-  Expect.isTrue(identical(stringAB, stringAB2));
-  Expect.isTrue(identical(const Box(42), boxInt42));
-  Expect.isTrue(identical(const Box('ab'), boxStringAB));
-}
-
-testConstantFunctionParameters() {
-  Expect.isTrue(identical(const Box('positional'), returnPositional()));
-  Expect.isTrue(identical(const Box('named'), returnNamed()));
-  Expect
-      .isTrue(identical(const Box('abc'), returnPositional(const Box('abc'))));
-  Expect.isTrue(identical(const Box('def'), returnNamed(a: const Box('def'))));
-}
-
-testConstantSwitchExpressions() {
-  Expect.isTrue(returnSwitchCasedValue(const Box(42)) == 42);
-  Expect.isTrue(returnSwitchCasedValue(const Box('abc')) == 'abc');
-  Expect.isTrue(
-      returnSwitchCasedValue(const Box(const Box('abc'))) == const Box('abc'));
-  Expect
-      .isTrue(returnSwitchCasedValue(const Box('go-to-default')) == 'default');
-}
-
-testConstantLocalVariables() {
-  const a = 'a';
-  const b = a + 'b';
-  const c = b + 'c';
-  const box = const Box(c);
-  Expect.isTrue(identical(const Box('abc'), box));
-}
-
-testComplextConstLiterals() {
-  Expect.isTrue(identical(const [1, 2, 3], const [1, 2, 3]));
-  Expect.isTrue(identical(const [1, 2, 3], list123));
-  Expect.isTrue(
-      identical(const {'a': 'b', 'b': 'c'}, const {'a': 'b', 'b': 'c'}));
-  Expect.isTrue(identical(const {'a': 'b', 'b': 'c'}, mapABC));
-
-  Expect.isTrue(mapABC['a'] == 'b');
-  Expect.isTrue(mapABC['b'] == 'c');
-  Expect.isTrue(mapABC.length == 2);
-
-  Expect.isTrue(list123[0] == 1);
-  Expect.isTrue(list123[1] == 2);
-  Expect.isTrue(list123[2] == 3);
-  Expect.isTrue(list123.length == 3);
-}
-
-main() {
-  testConstantExpressions();
-  testConstantFieldValues();
-  testConstantFunctionParameters();
-  testConstantSwitchExpressions();
-  testComplextConstLiterals();
-  testConstantExpressions();
-  testConstantLocalVariables();
-}
diff --git a/tests/kernel/unsorted/factory_regression_test.dart b/tests/kernel/unsorted/factory_regression_test.dart
deleted file mode 100644
index efccf81..0000000
--- a/tests/kernel/unsorted/factory_regression_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:typed_data';
-
-import 'package:expect/expect.dart';
-
-var list = [1, 2, 3];
-
-class Foo {
-  final value;
-  Foo(this.value) {}
-
-  factory Foo.fac(value) {
-    return new Foo(value);
-  }
-}
-
-main() {
-  Expect.isTrue(new Uint8List.fromList(list)[1] == 2);
-  Expect.isTrue(new Foo.fac(10).value == 10);
-}
diff --git a/tests/kernel/unsorted/field_dispatcher_test.dart b/tests/kernel/unsorted/field_dispatcher_test.dart
deleted file mode 100644
index cddba91..0000000
--- a/tests/kernel/unsorted/field_dispatcher_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  Function fun;
-  A(this.fun);
-}
-
-globalFunctionPositional(int a, [int b = 42]) => a + b;
-
-globalFunctionNamed(int a, {int b: 42}) => a + b;
-
-class Foo {
-  int base;
-
-  Foo(this.base);
-
-  methodFunctionPositional(int a, [int b = 42]) => base + a + b;
-
-  methodFunctionNamed(int a, {int b: 42}) => base + a + b;
-}
-
-main() {
-  Expect.isTrue(new A(globalFunctionPositional).fun(1, 2) == 3);
-  Expect.isTrue(new A(globalFunctionPositional).fun(1) == 43);
-  Expect.isTrue(new A(globalFunctionNamed).fun(1, b: 2) == 3);
-  Expect.isTrue(new A(globalFunctionNamed).fun(1) == 43);
-
-  var foo = new Foo(100);
-  Expect.isTrue(new A(foo.methodFunctionPositional).fun(1, 2) == 103);
-  Expect.isTrue(new A(foo.methodFunctionPositional).fun(1) == 143);
-  Expect.isTrue(new A(foo.methodFunctionNamed).fun(1, b: 2) == 103);
-  Expect.isTrue(new A(foo.methodFunctionNamed).fun(1) == 143);
-}
diff --git a/tests/kernel/unsorted/finally_contexts_test.dart b/tests/kernel/unsorted/finally_contexts_test.dart
deleted file mode 100644
index 2385916..0000000
--- a/tests/kernel/unsorted/finally_contexts_test.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-// Test that the context depth is correct in the presence of control flow,
-// specifically branching and joining in the presence of break.  The
-// implementation uses the context depth after the else block of an if/then/else
-// as the context depth at the join point.  This test has an extra context
-// allocated in the (untaken) else branch so it tests that compiling the
-// (untaken) break properly tracks the context depth.
-
-test(list) {
-  // The loops force creation of a new context, otherwise context allocated
-  // variables might be hoisted to an outer context.
-  do {
-    if (list.length > 1) {
-      do {
-        var sum = 0;
-        addem() {
-          for (var x in list) sum += x;
-        }
-
-        addem();
-        Expect.isTrue(sum == 15);
-        L:
-        if (sum != 15) {
-          // Unreachable.
-          do {
-            var product = 1;
-            multiplyem() {
-              for (var x in list) product *= x;
-            }
-
-            multiplyem();
-            Expect.isTrue(false);
-            break L;
-          } while (false);
-        }
-      } while (false);
-    }
-  } while (false);
-  Expect.isTrue(list.length == 5);
-}
-
-main() {
-  test([1, 2, 3, 4, 5]);
-}
diff --git a/tests/kernel/unsorted/for_in_loop_test.dart b/tests/kernel/unsorted/for_in_loop_test.dart
deleted file mode 100644
index 635d72f..0000000
--- a/tests/kernel/unsorted/for_in_loop_test.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of for-in loops and list literals.
-
-import 'package:expect/expect.dart';
-
-fact4() {
-  var f = 1;
-  for (var n in [1, 2, 3, 4]) {
-    f *= n;
-  }
-  return f;
-}
-
-fact5() {
-  var f = 1, n;
-  for (n in [1, 2, 3, 4, 5]) {
-    f *= n;
-  }
-  return f;
-}
-
-var global;
-fact6() {
-  var f = 1;
-  for (global in [1, 2, 3, 4, 5, 6]) {
-    f *= global;
-  }
-  return f;
-}
-
-main() {
-  Expect.isTrue(fact4() == 24);
-  Expect.isTrue(fact5() == 120);
-  Expect.isTrue(fact6() == 720);
-}
diff --git a/tests/kernel/unsorted/generic_function_test.dart b/tests/kernel/unsorted/generic_function_test.dart
deleted file mode 100644
index 126f863..0000000
--- a/tests/kernel/unsorted/generic_function_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of generic functions.
-
-import 'package:expect/expect.dart';
-
-typedef R Foo<R>();
-
-bar<R>(int body()) {
-  var function = () {
-    if (body is Foo<R>) {
-      return body();
-    }
-    return 42;
-  };
-  return function();
-}
-
-main() {
-  Expect.isTrue(bar(() => 43) == 43);
-}
diff --git a/tests/kernel/unsorted/getters_and_setters_test.dart b/tests/kernel/unsorted/getters_and_setters_test.dart
deleted file mode 100644
index 816a0e0..0000000
--- a/tests/kernel/unsorted/getters_and_setters_test.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-var field;
-
-get getField {
-  print('B.getField');
-  return field;
-}
-
-set setField(value) {
-  print('B.setField');
-  field = value;
-  return null;
-}
-
-main() {
-  var result;
-
-  result = (field = 42);
-  Expect.isTrue(result == 42);
-  Expect.isTrue(field == 42);
-  Expect.isTrue(getField == 42);
-
-  result = (setField = 99);
-  Expect.isTrue(result == 99);
-  Expect.isTrue(field == 99);
-  Expect.isTrue(getField == 99);
-}
diff --git a/tests/kernel/unsorted/global_field_initializer_test.dart b/tests/kernel/unsorted/global_field_initializer_test.dart
deleted file mode 100644
index a19fe34..0000000
--- a/tests/kernel/unsorted/global_field_initializer_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-var intField = 1;
-var doubleField = 3.1415;
-var stringField = "hello";
-var nullField = null;
-var nullField2;
-var composed = "hello" + " " + "world";
-
-class A {
-  static var intField = 1;
-  static var doubleField = 3.1415;
-  static var stringField = "hello";
-  static var nullField = null;
-  static var nullField2;
-  static var composed = "hello" + " " + "world";
-}
-
-main() {
-  Expect.isTrue(intField == 1);
-  Expect.isTrue(doubleField == 3.1415);
-  Expect.isTrue(stringField == "hello");
-  Expect.isTrue(nullField == null);
-  Expect.isTrue(nullField2 == null);
-  Expect.isTrue(composed == "hello world");
-
-  Expect.isTrue(A.intField == 1);
-  Expect.isTrue(A.doubleField == 3.1415);
-  Expect.isTrue(A.stringField == "hello");
-  Expect.isTrue(A.nullField == null);
-  Expect.isTrue(A.nullField2 == null);
-  Expect.isTrue(A.composed == "hello world");
-}
diff --git a/tests/kernel/unsorted/global_function_test.dart b/tests/kernel/unsorted/global_function_test.dart
deleted file mode 100644
index 16ede5f..0000000
--- a/tests/kernel/unsorted/global_function_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-main() {
-  foo(1, 2);
-  print('---');
-  foo(1, 2, d: 12);
-  print('---');
-  foo(1, 2, c: 11, e: 13);
-
-  print('=====');
-
-  bar(1, 2);
-  print('---');
-  bar(1, 2, 3);
-  print('---');
-  bar(1, 2, 3, 4);
-}
-
-foo(a, b, {c, d, e}) {
-  print(a);
-  print(b);
-  print(c);
-  print(d);
-  print(e);
-}
-
-bar(a, b, [c, d]) {
-  print(a);
-  print(b);
-  print(c);
-  print(d);
-}
diff --git a/tests/kernel/unsorted/instance_getters_and_setters_test.dart b/tests/kernel/unsorted/instance_getters_and_setters_test.dart
deleted file mode 100644
index 4430a62..0000000
--- a/tests/kernel/unsorted/instance_getters_and_setters_test.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  var field;
-
-  get getField {
-    return field;
-  }
-
-  set setField(value) {
-    field = value;
-    return null;
-  }
-}
-
-main() {
-  var result;
-  var a = new A();
-
-  Expect.isTrue(a.field == null);
-  Expect.isTrue(a.getField == null);
-
-  result = (a.field = 42);
-  Expect.isTrue(result == 42);
-  Expect.isTrue(a.field == 42);
-  Expect.isTrue(a.getField == 42);
-
-  result = (a.setField = 99);
-  Expect.isTrue(result == 99);
-  Expect.isTrue(a.field == 99);
-  Expect.isTrue(a.getField == 99);
-}
diff --git a/tests/kernel/unsorted/invocation_errors_test.dart b/tests/kernel/unsorted/invocation_errors_test.dart
deleted file mode 100644
index 95e3106..0000000
--- a/tests/kernel/unsorted/invocation_errors_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Erroneous cases of invocations.
-
-import 'package:expect/expect.dart';
-
-test0(x) {
-  print('test0');
-}
-
-main() {
-  test0(0, 1); //# 00: compile-time error
-}
diff --git a/tests/kernel/unsorted/invocation_test.dart b/tests/kernel/unsorted/invocation_test.dart
deleted file mode 100644
index dbf862c..0000000
--- a/tests/kernel/unsorted/invocation_test.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of invocations.
-
-import 'package:expect/expect.dart';
-
-test0(x) {
-  Expect.isTrue(x == 'argument0');
-  return 'return0';
-}
-
-class C0 {
-  static test1(x) {
-    Expect.isTrue(x == 'argument1');
-    return 'return1';
-  }
-}
-
-class C1 {
-  test2(x) {
-    Expect.isTrue(x == 'argument2');
-    return 'return2';
-  }
-}
-
-class C2 {
-  C2.test3(x) {
-    Expect.isTrue(x == 'argument3');
-  }
-}
-
-main() {
-  Expect.isTrue(test0('argument0') == 'return0');
-  Expect.isTrue(C0.test1('argument1') == 'return1');
-  Expect.isTrue(new C1().test2('argument2') == 'return2');
-  var c = new C2.test3('argument3');
-  Expect.isTrue(c is C2);
-}
diff --git a/tests/kernel/unsorted/klass_field_initializer_test.dart b/tests/kernel/unsorted/klass_field_initializer_test.dart
deleted file mode 100644
index 11c51af6..0000000
--- a/tests/kernel/unsorted/klass_field_initializer_test.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  var intField = 1;
-  var doubleField = 3.1415;
-  var stringField = "hello";
-  var o;
-
-  A(this.o);
-}
-
-class B extends A {
-  var nullField = null;
-  var nullField2;
-
-  var n;
-  var m;
-
-  B(this.n, o)
-      : m = "m",
-        super(o);
-}
-
-main() {
-  var o = new B("n", "o");
-  Expect.isTrue(o.intField == 1);
-  Expect.isTrue(o.doubleField == 3.1415);
-  Expect.isTrue(o.stringField == "hello");
-  Expect.isTrue(o.nullField == null);
-  Expect.isTrue(o.nullField2 == null);
-  Expect.isTrue(o.m == 'm');
-  Expect.isTrue(o.n == 'n');
-  Expect.isTrue(o.o == 'o');
-}
diff --git a/tests/kernel/unsorted/klass_test.dart b/tests/kernel/unsorted/klass_test.dart
deleted file mode 100644
index 24ef76a..0000000
--- a/tests/kernel/unsorted/klass_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-class A {
-  A() {
-    print("A");
-  }
-
-  hello() {
-    print("A.hello()");
-  }
-
-  hello1(a) {
-    print("A.hello1()");
-    print(a);
-  }
-
-  foo(a, [b]) {
-    print("A.foo()");
-    print(a);
-    print(b);
-  }
-
-  bar(a, {b}) {
-    print("A.bar()");
-    print(a);
-    print(b);
-  }
-}
-
-main() {
-  print("before constructor");
-  var a = new A();
-  print("============");
-  a.hello();
-  print('-----(obj):');
-  print(a);
-  print('-----');
-  a.hello1(1);
-  print('-----');
-  a.foo(1);
-  print('-----');
-  a.foo(1, 2);
-  print('-----');
-  print("============");
-  a.bar(1);
-  print('-----');
-  a.bar(1, b: 2);
-  print("============");
-}
diff --git a/tests/kernel/unsorted/let_test.dart b/tests/kernel/unsorted/let_test.dart
deleted file mode 100644
index 7687966..0000000
--- a/tests/kernel/unsorted/let_test.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-main() {
-  var a = [1];
-  Expect.isTrue((a..add(42))[1] == 42);
-}
diff --git a/tests/kernel/unsorted/load_store_test.dart b/tests/kernel/unsorted/load_store_test.dart
deleted file mode 100644
index d19f87b..0000000
--- a/tests/kernel/unsorted/load_store_test.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of reading and writing to variables.
-
-import 'package:expect/expect.dart';
-
-test0() {
-  var x0 = 0, x1;
-  Expect.isTrue(x0 == 0);
-  Expect.isTrue(x1 == null);
-  x0 = 1;
-  Expect.isTrue(x0 == 1);
-  Expect.isTrue((x0 = 2) == 2);
-  Expect.isTrue(x0 == 2);
-}
-
-var x2 = 0, x3;
-
-test1() {
-  Expect.isTrue(x2 == 0);
-  Expect.isTrue(x3 == null);
-  x2 = 1;
-  Expect.isTrue(x2 == 1);
-  Expect.isTrue((x2 = 2) == 2);
-  Expect.isTrue(x2 == 2);
-}
-
-class C {
-  static var x4 = 0;
-  static var x5;
-}
-
-test3() {
-  Expect.isTrue(C.x4 == 0);
-  Expect.isTrue(C.x5 == null);
-  C.x4 = 1;
-  Expect.isTrue(C.x4 == 1);
-  Expect.isTrue((C.x4 = 2) == 2);
-  Expect.isTrue(C.x4 == 2);
-}
-
-class D {
-  var x6 = 0;
-  var x7;
-}
-
-test4() {
-  var d = new D();
-  Expect.isTrue(d.x6 == 0);
-  Expect.isTrue(d.x7 == null);
-  d.x6 = 1;
-  Expect.isTrue(d.x6 == 1);
-  Expect.isTrue((d.x6 = 2) == 2);
-  Expect.isTrue(d.x6 == 2);
-}
-
-main() {
-  test0();
-  test1();
-  test3();
-  test4();
-}
diff --git a/tests/kernel/unsorted/local_function_test.dart b/tests/kernel/unsorted/local_function_test.dart
deleted file mode 100644
index 536c96a..0000000
--- a/tests/kernel/unsorted/local_function_test.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of function expressions and function statements.
-
-import 'package:expect/expect.dart';
-
-main() {
-  var even;
-  odd(n) => n > 0 && even(n - 1);
-  even = (n) => n == 0 || odd(n - 1);
-
-  Expect.isTrue(even(0));
-  Expect.isTrue(!odd(0));
-
-  Expect.isTrue(odd(1));
-  Expect.isTrue(!even(1));
-
-  Expect.isTrue(even(42));
-  Expect.isTrue(!odd(42));
-
-  Expect.isTrue(odd(101));
-  Expect.isTrue(!even(101));
-}
diff --git a/tests/kernel/unsorted/loop_test.dart b/tests/kernel/unsorted/loop_test.dart
deleted file mode 100644
index c9b2617..0000000
--- a/tests/kernel/unsorted/loop_test.dart
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of loops.
-
-import 'package:expect/expect.dart';
-
-fact(n) {
-  var f = BigInt.one;
-  while (n > 1) {
-    f *= BigInt.from(n);
-    --n;
-  }
-  return f;
-}
-
-fib(n) {
-  if (n == 0) return 0;
-  var previous = 0, current = 1;
-  while (n > 1) {
-    var temp = current;
-    current += previous;
-    previous = temp;
-    --n;
-  }
-  return current;
-}
-
-mkTrue() => true;
-mkFalse() => false;
-
-check(b) {
-  Expect.isTrue(b);
-  return b;
-}
-
-test0() {
-  while (mkTrue()) {
-    Expect.isTrue(true);
-    return;
-  }
-  Expect.isTrue(false);
-}
-
-test1() {
-  while (mkFalse()) {
-    Expect.isTrue(false);
-  }
-  Expect.isTrue(true);
-}
-
-test2() {
-  do {
-    Expect.isTrue(true);
-  } while (mkFalse());
-  Expect.isTrue(true);
-}
-
-test3() {
-  do {
-    Expect.isTrue(true);
-    return;
-  } while (check(false));
-  Expect.isTrue(false);
-}
-
-main() {
-  Expect.isTrue(fact(0) == BigInt.one);
-  Expect.isTrue(fact(1) == BigInt.one);
-  Expect.isTrue(fact(5) == BigInt.from(120));
-  Expect.isTrue(fact(42) ==
-      BigInt.parse("1405006117752879898543142606244511569936384000000000"));
-  Expect.isTrue(fact(3.14159) == BigInt.from(6));
-
-  Expect.isTrue(fib(0) == 0);
-  Expect.isTrue(fib(1) == 1);
-  Expect.isTrue(fib(2) == 1);
-  Expect.isTrue(fib(3) == 2);
-  Expect.isTrue(fib(4) == 3);
-  Expect.isTrue(fib(5) == 5);
-  Expect.isTrue(fib(6) == 8);
-  Expect.isTrue(fib(7) == 13);
-  Expect.isTrue(fib(42) == 267914296);
-  Expect.isTrue(fib(3.14159) == 3);
-
-  test0();
-  test1();
-  test2();
-  test3();
-}
diff --git a/tests/kernel/unsorted/mapliteral_test.dart b/tests/kernel/unsorted/mapliteral_test.dart
deleted file mode 100644
index 9651402..0000000
--- a/tests/kernel/unsorted/mapliteral_test.dart
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-main() {
-  var map = {
-    'k1': 'v1',
-    'k2': 'v2',
-    1: 2,
-    1.5: 1.2,
-    3: 3.14,
-  };
-
-  Expect.isTrue(map.length == 5);
-
-  map['foo'] = 'bar';
-
-  Expect.isTrue(map['k1'] == 'v1');
-  Expect.isTrue(map['k2'] == 'v2');
-  Expect.isTrue(map[1] == 2);
-  Expect.isTrue(map[1.5] == 1.2);
-  Expect.isTrue(map[3] == 3.14);
-  Expect.isTrue(map['foo'] == 'bar');
-  Expect.isTrue(map.length == 6);
-}
diff --git a/tests/kernel/unsorted/mixin_test.dart b/tests/kernel/unsorted/mixin_test.dart
deleted file mode 100644
index 9c49ee8..0000000
--- a/tests/kernel/unsorted/mixin_test.dart
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class Base {
-  baseFoo() {
-    print('Base.baseFoo()');
-    return 1;
-  }
-
-  foo() {
-    print('Base.foo()');
-    return 1;
-  }
-}
-
-class Mixin {
-  mixinFoo() {
-    print('Mixin.mixinFoo()');
-    return 2;
-  }
-
-  foo() {
-    print('Mixin.foo()');
-    return 2;
-  }
-}
-
-class Mixin2 {
-  mixin2Foo() {
-    print('Mixin2.mixin2Foo()');
-    return 3;
-  }
-
-  foo() {
-    print('Mixin2.foo()');
-    return 3;
-  }
-}
-
-class Sub extends Base with Mixin, Mixin2 {
-  subFoo() {
-    print('Sub.subFoo()');
-    return 4;
-  }
-
-  foo() {
-    print('Sub.foo()');
-    return 4;
-  }
-}
-
-main() {
-  var o = new Sub();
-
-  Expect.isTrue(o.baseFoo() == 1);
-  Expect.isTrue(o.mixinFoo() == 2);
-  Expect.isTrue(o.mixin2Foo() == 3);
-  Expect.isTrue(o.subFoo() == 4);
-  Expect.isTrue(o.foo() == 4);
-}
diff --git a/tests/kernel/unsorted/nsm_dispatcher_test.dart b/tests/kernel/unsorted/nsm_dispatcher_test.dart
deleted file mode 100644
index 8a0722a..0000000
--- a/tests/kernel/unsorted/nsm_dispatcher_test.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  noSuchMethod(Invocation invocation) {
-    var s = '|${invocation.memberName}|';
-    for (var a in invocation.positionalArguments) {
-      s = '$s$a|';
-    }
-    invocation.namedArguments.forEach((Symbol k, v) {
-      s = '$s$k/$v|';
-    });
-    print(s);
-    return s;
-  }
-}
-
-main() {
-  dynamic o = new A();
-  Expect.isTrue(o.fun() == '|${#fun}|');
-  Expect.isTrue(o.fun(1) == '|${#fun}|1|');
-  Expect.isTrue(o.fun(1, 2) == '|${#fun}|1|2|');
-  Expect.isTrue(o.fun(1, b: 2) == '|${#fun}|1|${#b}/2|');
-  Expect.isTrue(o.fun(1, a: 1, b: 2) == '|${#fun}|1|${#a}/1|${#b}/2|');
-  Expect.isTrue(o.fun(1, b: 2, a: 1) == '|${#fun}|1|${#a}/1|${#b}/2|');
-}
diff --git a/tests/kernel/unsorted/nullable_operator_test.dart b/tests/kernel/unsorted/nullable_operator_test.dart
deleted file mode 100644
index 9bf1bcb7..0000000
--- a/tests/kernel/unsorted/nullable_operator_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-mkOne() => 1;
-mkNull() => null;
-
-main() {
-  Expect.isTrue((mkOne() ?? 2) == 1);
-  Expect.isTrue((mkNull() ?? 2) == 2);
-}
diff --git a/tests/kernel/unsorted/optimize_noncached_constant_test.dart b/tests/kernel/unsorted/optimize_noncached_constant_test.dart
deleted file mode 100644
index 2023293..0000000
--- a/tests/kernel/unsorted/optimize_noncached_constant_test.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// VMOptions=--optimization_counter_threshold=5 --no-background-compilation
-
-void foo(int i) {
-  try {
-    print(42 ~/ 0 + i);
-  } catch (e) {
-    return;
-  }
-  throw "Should have gotten an exception";
-}
-
-main() {
-  for (int i = 0; i < 10; ++i) {
-    foo(i);
-  }
-}
diff --git a/tests/kernel/unsorted/rethrow_test.dart b/tests/kernel/unsorted/rethrow_test.dart
deleted file mode 100644
index c8f31d1..0000000
--- a/tests/kernel/unsorted/rethrow_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-testNormalRethrow() {
-  var x = 0;
-  try {
-    try {
-      throw x++;
-    } catch (e) {
-      Expect.isTrue(e == 0);
-      x++;
-      rethrow;
-    }
-  } catch (e) {
-    Expect.isTrue(e == 0);
-    x++;
-  }
-  Expect.isTrue(x == 3);
-}
-
-testNormalRethrow2() {
-  var x = 0;
-  try {
-    try {
-      throw x++;
-    } on int catch (e) {
-      Expect.isTrue(e == 0);
-      x++;
-      rethrow;
-    }
-  } catch (e) {
-    Expect.isTrue(e == 0);
-    x++;
-  }
-  Expect.isTrue(x == 3);
-}
-
-testRethrowWithinTryRethrow() {
-  var x = 0;
-  try {
-    try {
-      throw x++;
-    } on int catch (e) {
-      Expect.isTrue(e == 0);
-      x++;
-      try {
-        x++;
-        rethrow;
-      } finally {
-        x++;
-      }
-    }
-  } catch (e) {
-    Expect.isTrue(e == 0);
-    x++;
-  }
-  Expect.isTrue(x == 5);
-}
-
-main() {
-  testNormalRethrow();
-  testNormalRethrow2();
-  testRethrowWithinTryRethrow();
-}
diff --git a/tests/kernel/unsorted/return_test.dart b/tests/kernel/unsorted/return_test.dart
deleted file mode 100644
index ebe7e78..0000000
--- a/tests/kernel/unsorted/return_test.dart
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of return (and imports, literals, ==, and static methods).
-
-import 'package:expect/expect.dart';
-
-test0() {}
-
-test1() {
-  return;
-}
-
-test3() {
-  return 3;
-}
-
-test4() => 4;
-
-test5() {
-  return 5;
-  Expect.isTrue(false);
-}
-
-main() {
-  Expect.isTrue(test0() == null);
-  Expect.isTrue(test1() == null);
-  Expect.isTrue(test3() == 3);
-  Expect.isTrue(test4() == 4);
-  Expect.isTrue(test5() == 5);
-}
diff --git a/tests/kernel/unsorted/simple_literal_test.dart b/tests/kernel/unsorted/simple_literal_test.dart
deleted file mode 100644
index c4b8a42..0000000
--- a/tests/kernel/unsorted/simple_literal_test.dart
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Tests of literals (and imports, return, ==, and static methods).
-import 'package:expect/expect.dart';
-
-test0() {
-  return 'Hello, world!';
-}
-
-test1() {
-  return 42;
-}
-
-test2() {
-  return 2.71828;
-}
-
-test3() {
-  return 6.022e23;
-}
-
-test4() {
-  return true;
-}
-
-test5() {
-  return false;
-}
-
-test6() {
-  return 1405006117752879898543142606244511569936384000000000; //# 01: compile-time error
-}
-
-main() {
-  Expect.isTrue(test0() == 'Hello, world!');
-  Expect.isTrue(test1() == 42);
-  Expect.isTrue(test2() == 2.71828);
-  Expect.isTrue(test3() == 6.022e23);
-  Expect.isTrue(test4());
-  Expect.isTrue(test5() == false);
-  Expect.isTrue(test6() == //                                //# 01: continued
-      1405006117752879898543142606244511569936384000000000); //# 01: continued
-}
diff --git a/tests/kernel/unsorted/string_buffer_test.dart b/tests/kernel/unsorted/string_buffer_test.dart
deleted file mode 100644
index a89aee6..0000000
--- a/tests/kernel/unsorted/string_buffer_test.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-main() {
-  var sb = new StringBuffer();
-  sb.writeln('hello world :)');
-  print(sb);
-}
diff --git a/tests/kernel/unsorted/string_concatenation_test.dart b/tests/kernel/unsorted/string_concatenation_test.dart
deleted file mode 100644
index be6543a..0000000
--- a/tests/kernel/unsorted/string_concatenation_test.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  toString() => 'hello';
-}
-
-main() {
-  Expect.isTrue('begin ${new A()} end' == 'begin hello end');
-}
diff --git a/tests/kernel/unsorted/super_mixin_test.dart b/tests/kernel/unsorted/super_mixin_test.dart
deleted file mode 100644
index f70b888..0000000
--- a/tests/kernel/unsorted/super_mixin_test.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class BaseMixin {
-  method(x) {
-    print(x);
-    return x + 'error';
-  }
-
-  set setter(x) {
-    print(x);
-  }
-}
-
-class Base {
-  var field;
-
-  method(x) {
-    print(x);
-    return x;
-  }
-
-  set setter(x) {
-    print(x);
-    field = x;
-  }
-}
-
-class Mixin extends BaseMixin {
-  method(x) {
-    return super.method(x + 'Mixin');
-  }
-
-  set setter(x) {
-    super.setter = x + 'Mixin';
-  }
-}
-
-class Sub extends Base with Mixin {}
-
-main() {
-  var object = new Sub();
-  Expect.isTrue(object.method('x') == 'xMixin');
-  object.setter = 'y';
-  Expect.isTrue(object.field == 'yMixin');
-}
diff --git a/tests/kernel/unsorted/super_test.dart b/tests/kernel/unsorted/super_test.dart
deleted file mode 100644
index 54f5d99..0000000
--- a/tests/kernel/unsorted/super_test.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  var field = 9;
-  var called = false;
-
-  superMethod() {
-    Expect.isTrue(field == 10);
-    called = true;
-    return true;
-  }
-}
-
-class B extends A {
-  doit() {
-    Expect.isTrue((super.field = 10) == 10);
-    Expect.isTrue(super.superMethod());
-    if (called) {
-      Expect.isTrue((super.field = 11) == 11);
-    }
-    return super.field;
-  }
-}
-
-class C extends B {
-  set field(v) {
-    throw 'should not happen';
-  }
-}
-
-main() {
-  var c = new C();
-  Expect.isTrue(c.field == 9);
-  Expect.isTrue(c.doit() == 11);
-  Expect.isTrue(c.field == 11);
-}
diff --git a/tests/kernel/unsorted/superclass_test.dart b/tests/kernel/unsorted/superclass_test.dart
deleted file mode 100644
index 15f1f56..0000000
--- a/tests/kernel/unsorted/superclass_test.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  A() {
-    print("A");
-  }
-
-  hello() {
-    print("A.hello()");
-    return 1;
-  }
-
-  hello1(a) {
-    print("A.hello1()");
-    print(a);
-    return 1;
-  }
-
-  foo(a, [b]) {
-    print("A.foo()");
-    print(a);
-    print(b);
-    return 1;
-  }
-
-  bar(a, {b}) {
-    print("A.bar()");
-    print(a);
-    print(b);
-    return 1;
-  }
-}
-
-class B extends A {
-  hello() {
-    print("B.hello()");
-    return 2;
-  }
-
-  bar(a, {b}) {
-    print("B.bar()");
-    print(a);
-    print(b);
-    return 2;
-  }
-}
-
-main() {
-  var o = new B();
-
-  // Base class methods.
-  Expect.isTrue(o.hello1(1) == 1);
-  Expect.isTrue(o.foo(1) == 1);
-  Expect.isTrue(o.foo(1, 2) == 1);
-
-  // Overwritten methods.
-  Expect.isTrue(o.hello() == 2);
-  Expect.isTrue(o.bar(1) == 2);
-  Expect.isTrue(o.bar(1, b: 2) == 2);
-}
diff --git a/tests/kernel/unsorted/switch_case_test.dart b/tests/kernel/unsorted/switch_case_test.dart
deleted file mode 100644
index 509a373..0000000
--- a/tests/kernel/unsorted/switch_case_test.dart
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-mkOne() => 1;
-mkTwo() => 2;
-
-testNormal() {
-  int result;
-  switch (mkOne()) {
-    case 0:
-      result = 0;
-      break;
-    case 1:
-      result = 1;
-      break;
-    case 2:
-      result = 2;
-      break;
-    default:
-      result = 3;
-      break;
-  }
-  Expect.isTrue(result == 1);
-}
-
-testDefault() {
-  int result;
-  switch (null) {
-    case 0:
-      result = 0;
-      break;
-    case 1:
-      result = 1;
-      break;
-    case 2:
-      result = 2;
-      break;
-    default:
-      result = 3;
-      break;
-  }
-  Expect.isTrue(result == 3);
-}
-
-testFallThrough() {
-  int result;
-  switch (mkOne()) {
-    case 0:
-      result = 0;
-      break;
-    case 1:
-    case 2:
-      result = 2;
-      break;
-    default:
-      result = 3;
-      break;
-  }
-  Expect.isTrue(result == 2);
-}
-
-testContinue() {
-  int result;
-  switch (mkTwo()) {
-    case 0:
-      result = 0;
-      break;
-
-    setitto1:
-    case 1:
-      result = 1;
-      continue setitto3;
-
-    case 2:
-      result = 2;
-      continue setitto1;
-
-    setitto3:
-    default:
-      result = 3;
-      break;
-  }
-  Expect.isTrue(result == 3);
-}
-
-testOnlyDefault() {
-  int result;
-  switch (mkTwo()) {
-    default:
-      result = 42;
-  }
-  Expect.isTrue(result == 42);
-}
-
-testOnlyDefaultWithBreak() {
-  int result;
-  switch (mkTwo()) {
-    default:
-      result = 42;
-  }
-  Expect.isTrue(result == 42);
-}
-
-String testReturn() {
-  switch (mkOne()) {
-    case 0:
-      return "bad";
-    case 1:
-      return "good";
-    default:
-      return "bad";
-  }
-}
-
-regressionTest() {
-  Expect.isTrue(regressionTestHelper(0, 0) == -1);
-  Expect.isTrue(regressionTestHelper(4, 0) == -1);
-  Expect.isTrue(regressionTestHelper(4, 1) == 42);
-}
-
-regressionTestHelper(i, j) {
-  switch (i) {
-    case 4:
-      switch (j) {
-        case 1:
-          return 42;
-      }
-  }
-  return -1;
-}
-
-regressionTest2() {
-  var state = 1;
-  while (state < 2) {
-    switch (state) {
-      case 1:
-        state++;
-        break;
-      case 3:
-      case 4:
-        // We will translate this currently to an empty [Fragment] which can
-        // cause issues if we would like to append/prepend to it.
-        assert(false);
-    }
-  }
-  return [1];
-}
-
-regressionTest3() {
-  f(x) {
-    switch (x) {
-      case 1:
-        return 2;
-      case 2:
-    }
-    throw new UnsupportedError("Unexpected constant kind.");
-  }
-
-  Expect.isTrue(f(1) == 2);
-}
-
-main() {
-  testNormal();
-  testDefault();
-  testFallThrough();
-  testContinue();
-  testOnlyDefault();
-  testOnlyDefaultWithBreak();
-  regressionTest();
-  regressionTest2();
-  regressionTest3();
-
-  var result = testReturn();
-  Expect.isTrue(result == "good");
-}
diff --git a/tests/kernel/unsorted/symbol_literal_test.dart b/tests/kernel/unsorted/symbol_literal_test.dart
deleted file mode 100644
index 6a3cc8a..0000000
--- a/tests/kernel/unsorted/symbol_literal_test.dart
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-main() {
-  Expect.isTrue('${#abc}' == 'Symbol("abc")');
-  Expect.isTrue('${#abc.xzy}' == 'Symbol("abc.xzy")');
-}
diff --git a/tests/kernel/unsorted/this_capture_test.dart b/tests/kernel/unsorted/this_capture_test.dart
deleted file mode 100644
index ea296d6..0000000
--- a/tests/kernel/unsorted/this_capture_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class Foo {
-  capture() {
-    return () {
-      return this;
-    };
-  }
-
-  captureFirst(a, b) {
-    return () {
-      print(a);
-      return this;
-    };
-  }
-
-  captureLast(a, b) {
-    return () {
-      print(b);
-      return this;
-    };
-  }
-}
-
-main() {
-  var foo = new Foo();
-  Expect.isTrue(identical(foo, (foo.capture())()));
-  Expect.isTrue(identical(foo, (foo.captureFirst(1, 2))()));
-  Expect.isTrue(identical(foo, (foo.captureLast(1, 2))()));
-}
diff --git a/tests/kernel/unsorted/this_test.dart b/tests/kernel/unsorted/this_test.dart
deleted file mode 100644
index 666da97..0000000
--- a/tests/kernel/unsorted/this_test.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class A {
-  getThis() => this;
-}
-
-main() {
-  var a = new A();
-  Expect.isTrue(a == a.getThis());
-  Expect.isTrue(identical(a, a.getThis()));
-}
diff --git a/tests/kernel/unsorted/throw_try_catch_test.dart b/tests/kernel/unsorted/throw_try_catch_test.dart
deleted file mode 100644
index d76cba7..0000000
--- a/tests/kernel/unsorted/throw_try_catch_test.dart
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-testSimpleThrowCatch() {
-  var x = 1;
-  try {
-    throw x++;
-  } on int catch (e) {
-    Expect.isTrue(e == 1);
-    Expect.isTrue(x == 2);
-    x++;
-  }
-  Expect.isTrue(x == 3);
-}
-
-testNestedThrowCatch() {
-  var x = 1;
-  try {
-    throw x++;
-  } catch (e) {
-    Expect.isTrue(e == 1);
-    Expect.isTrue(x == 2);
-    x++;
-
-    try {
-      throw x++;
-    } catch (e) {
-      Expect.isTrue(e == 3);
-      Expect.isTrue(x == 4);
-      x++;
-    }
-  }
-  Expect.isTrue(x == 5);
-}
-
-testNestedThrowCatch2() {
-  var x = 1;
-  try {
-    try {
-      throw x++;
-    } catch (e) {
-      Expect.isTrue(e == 1);
-      Expect.isTrue(x == 2);
-      x++;
-    }
-    throw x++;
-  } catch (e) {
-    Expect.isTrue(e == 3);
-    Expect.isTrue(x == 4);
-    x++;
-  }
-  Expect.isTrue(x == 5);
-}
-
-testSiblingThrowCatch() {
-  var x = 1;
-  try {
-    throw x++;
-  } catch (e) {
-    Expect.isTrue(e == 1);
-    Expect.isTrue(x == 2);
-    x++;
-  }
-  try {
-    throw x++;
-  } catch (e) {
-    Expect.isTrue(e == 3);
-    Expect.isTrue(x == 4);
-    x++;
-  }
-
-  Expect.isTrue(x == 5);
-}
-
-testTypedCatch() {
-  var good = false;
-  try {
-    throw 1;
-  } on int catch (e) {
-    Expect.isTrue(e == 1);
-    good = true;
-  } on String catch (_) {
-    Expect.isTrue(false);
-  }
-  Expect.isTrue(good);
-}
-
-testTypedCatch2() {
-  var good = false;
-  try {
-    throw 'a';
-  } on int catch (_) {
-    Expect.isTrue(false);
-  } on String catch (e) {
-    Expect.isTrue(e == 'a');
-    good = true;
-  }
-  Expect.isTrue(good);
-}
-
-testThrowNull() {
-  var good = false;
-  try {
-    throw null;
-  } on NullThrownError catch (_) {
-    good = true;
-  }
-  Expect.isTrue(good);
-}
-
-testFinally() {
-  var x = 0;
-  try {
-    throw x++;
-  } catch (_) {
-    x++;
-  } finally {
-    x++;
-  }
-  Expect.isTrue(x == 3);
-}
-
-testFinally2() {
-  var x = 0;
-  try {
-    try {
-      throw x++;
-    } catch (_) {
-      x++;
-    } finally {
-      x++;
-    }
-  } finally {
-    x++;
-  }
-  Expect.isTrue(x == 4);
-}
-
-testFinally3() {
-  try {
-    var x = 0;
-    try {
-      throw x++;
-    } finally {
-      x++;
-    }
-    Expect.isTrue(x == 2);
-  } catch (_) {}
-}
-
-testSuccessfulBody() {
-  var x = 0;
-  try {
-    x++;
-  } finally {
-    x++;
-  }
-  Expect.isTrue(x == 2);
-}
-
-testSuccessfulBody2() {
-  var x = 0;
-  try {
-    try {
-      x++;
-    } finally {
-      x++;
-      throw 1;
-    }
-  } on int {}
-  Expect.isTrue(x == 2);
-}
-
-main() {
-  testSimpleThrowCatch();
-  testNestedThrowCatch();
-  testNestedThrowCatch2();
-  testSiblingThrowCatch();
-  testTypedCatch();
-  testTypedCatch2();
-  testThrowNull();
-  testFinally();
-  testFinally2();
-  testFinally3();
-  testSuccessfulBody();
-  testSuccessfulBody2();
-}
diff --git a/tests/kernel/unsorted/try_context_test.dart b/tests/kernel/unsorted/try_context_test.dart
deleted file mode 100644
index 0676f41..0000000
--- a/tests/kernel/unsorted/try_context_test.dart
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-throwValue(val) => throw val;
-
-f1() {
-  var a = 0;
-  var b = 0;
-  var c = 0;
-  var d = 0;
-  for (var i = 0; i < 10; i++) {
-    try {
-      for (var j = 0; j < 11; j++) {
-        try {
-          capture() => [i, j, a, b, c, d];
-          throwValue(j == 10 ? "${j}" : j);
-        } on num catch (e) {
-          a += j;
-          b -= e;
-        }
-      }
-    } catch (e) {
-      c++;
-      d += int.parse(e);
-    }
-  }
-  return [a, b, c, d];
-}
-
-f2() {
-  var a = 0;
-  var b = 0;
-  var c = 0;
-  var d = 0;
-  for (var i = 0; i < 10; i++) {
-    try {
-      for (var j = 0; j < 11; j++) {
-        try {
-          capture() => [i, j, a, b, c, d];
-          throwValue(j == 10 ? "${j}" : j);
-        } on num catch (e) {
-          a += j;
-          b -= e;
-        }
-      }
-    } catch (e) {
-      capture() => e;
-      c++;
-      d += int.parse(e);
-    }
-  }
-  return [a, b, c, d];
-}
-
-f3() {
-  var a = 0;
-  var b = 0;
-  var c = 0;
-  var d = 0;
-  for (var i = 0; i < 10; i++) {
-    try {
-      for (var j = 0; j < 11; j++) {
-        try {
-          capture() => [i, j, a, b, c, d];
-          throwValue(j == 10 ? "${j}" : j);
-        } on num catch (e) {
-          a += j;
-          b -= e;
-        }
-      }
-    } catch (e) {
-      capture() => e;
-      c++;
-      d += int.parse(e);
-      continue;
-    }
-  }
-  return [a, b, c, d];
-}
-
-main() {
-  Expect.listEquals([450, -450, 10, 100], f1());
-  Expect.listEquals([450, -450, 10, 100], f2());
-  Expect.listEquals([450, -450, 10, 100], f3());
-}
diff --git a/tests/kernel/unsorted/try_finally_test.dart b/tests/kernel/unsorted/try_finally_test.dart
deleted file mode 100644
index 91ccf58..0000000
--- a/tests/kernel/unsorted/try_finally_test.dart
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-testSimpleBreak() {
-  var x = 1;
-  while (true) {
-    try {
-      x++;
-      break;
-    } finally {
-      x++;
-      break;
-    }
-  }
-  return x;
-}
-
-testReturnFinally() {
-  try {
-    return 1;
-  } finally {
-    return 42;
-  }
-}
-
-testNestedReturnFinally() {
-  try {
-    try {
-      return 1;
-    } finally {
-      return 2;
-    }
-  } finally {
-    return 42;
-  }
-}
-
-testReturnInsideLoop() {
-  while (true) {
-    try {
-      print("hello");
-    } finally {
-      return 42;
-    }
-  }
-}
-
-testStopContinueInsideLoop() {
-  while (true) {
-    try {
-      continue;
-    } finally {
-      return 42;
-    }
-  }
-}
-
-testStopBreakInsideLoop() {
-  var foo = 1;
-  while (true) {
-    try {
-      if (foo == 1) {
-        // 1st iteration we break.
-        break;
-      } else if (foo == 2) {
-        // 2nd iteration we return.
-        return 42;
-      }
-    } finally {
-      // 1st iteration we overrwrite break with continue.
-      if (foo == 1) {
-        foo++;
-        continue;
-      } else {
-        // Let return work
-      }
-    }
-  }
-  return foo;
-}
-
-testStopBreakInsideLoop2() {
-  var foo = 1;
-  while (true) {
-    try {
-      if (foo == 1) {
-        // 1st iteration we break.
-        break;
-      } else if (foo == 2) {
-        // 2nd iteration we return.
-        return -1;
-      }
-    } finally {
-      // 1st iteration we overrwrite break with continue.
-      if (foo == 1) {
-        foo++;
-        continue;
-      } else {
-        // 2nd iteration we overrwrite return with break.
-        foo = 42;
-        break;
-      }
-    }
-  }
-  return foo;
-}
-
-testStopContinueInsideSwitch() {
-  var foo = 1;
-  switch (foo) {
-    jump5:
-    case 5:
-      return -1;
-
-    case 1:
-      try {
-        continue jump5;
-      } finally {
-        return 42;
-      }
-  }
-}
-
-testStopContinueInsideSwitch2() {
-  var foo = 1;
-  switch (foo) {
-    jump5:
-    case 5:
-      return -1;
-
-    jump42:
-    case 5:
-      return 42;
-
-    case 1:
-      try {
-        continue jump5;
-      } finally {
-        continue jump42;
-      }
-  }
-}
-
-testNestedFinally() {
-  var events = '';
-  try {
-    try {
-      events = '$events|start';
-    } finally {
-      events = '$events|start-catch';
-    }
-    try {
-      try {
-        return;
-      } finally {
-        events = '$events|inner';
-        throw 0;
-      }
-    } finally {
-      events = '$events|middle';
-    }
-  } catch (e) {
-    events = '$events|outer-catch';
-  } finally {
-    events = '$events|outer-finally';
-  }
-  Expect.equals(
-      events, '|start|start-catch|inner|middle|outer-catch|outer-finally');
-}
-
-main() {
-  Expect.isTrue(testSimpleBreak() == 3);
-  Expect.isTrue(testReturnFinally() == 42);
-  Expect.isTrue(testNestedReturnFinally() == 42);
-  Expect.isTrue(testReturnInsideLoop() == 42);
-  Expect.isTrue(testStopContinueInsideLoop() == 42);
-  Expect.isTrue(testStopBreakInsideLoop() == 42);
-  Expect.isTrue(testStopBreakInsideLoop2() == 42);
-  Expect.isTrue(testStopContinueInsideLoop() == 42);
-  Expect.isTrue(testStopContinueInsideSwitch() == 42);
-  Expect.isTrue(testStopContinueInsideSwitch2() == 42);
-  testNestedFinally();
-}
diff --git a/tests/kernel/unsorted/type_args_regression_test.dart b/tests/kernel/unsorted/type_args_regression_test.dart
deleted file mode 100644
index 0b88bd7..0000000
--- a/tests/kernel/unsorted/type_args_regression_test.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class Box<T> {
-  T value;
-
-  Box(this.value);
-
-  factory Box.a(T v) => new Box(v);
-  factory Box.b(T v) = Box<T>;
-  factory Box.c(T v) => new Box(v);
-}
-
-main() {
-  Expect.isTrue(new Box<int>(1).value == 1);
-  Expect.isTrue(new Box<int>.a(1).value == 1);
-  Expect.isTrue(new Box<int>.b(1).value == 1);
-  Expect.isTrue(new Box<int>.c(1).value == 1);
-}
diff --git a/tests/kernel/unsorted/types_test.dart b/tests/kernel/unsorted/types_test.dart
deleted file mode 100644
index 0b989a1..0000000
--- a/tests/kernel/unsorted/types_test.dart
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:expect/expect.dart';
-
-class TypeTester<T> {
-  const TypeTester();
-  bool isCorrectType(object) => object is T;
-}
-
-class ClosureTypeTester<T> {
-  const ClosureTypeTester();
-  bool isCorrectType(object) => (() => object is T)();
-}
-
-class Base<A, B> {
-  final A a;
-  final B b;
-  const Base(this.a, this.b);
-  const factory Base.fac(A a, B b) = Base<A, B>;
-}
-
-class Sub1<C, D> extends Base<C, C> {
-  final D d;
-  const Sub1(C a, this.d) : super(a, a);
-  const factory Sub1.fac(C a, D d) = Sub1<C, D>;
-}
-
-class Sub2<C, D> extends Base<D, C> {
-  const Sub2(C a, D b) : super(b, a);
-  const factory Sub2.fac(C a, D b) = Sub2<C, D>;
-}
-
-class G<T> {}
-
-class I {}
-
-class A implements I {}
-
-class B extends A {}
-
-class C {}
-
-testConstantLiteralTypes() {
-  Expect.isTrue(const [1] is List);
-  Expect.isTrue(const [1] is List<int>);
-  Expect.isTrue(const ["1"] is List<String>);
-  Expect.isTrue(!(const [1] is List<String>));
-  Expect.isTrue(const <int>[1] is List);
-  Expect.isTrue(const <int>[1] is List<int>);
-  Expect.isTrue(!(const <int>[1] is List<String>));
-  Expect.isTrue(const {"a": 1} is Map);
-  Expect.isTrue(const {"a": 1} is Map<String, int>);
-  Expect.isTrue(const {1: "a"} is Map<int, String>);
-  Expect.isTrue(const <String, int>{"a": 1} is Map);
-  Expect.isTrue(const <String, int>{"a": 1} is Map<String, int>);
-  Expect.isTrue(!(const <String, int>{"a": 1} is Map<int, String>));
-}
-
-testNonConstantLiteralTypes() {
-  Expect.isTrue([1] is List);
-  Expect.isTrue([1] is List<int>);
-  Expect.isTrue(["1"] is List<String>);
-  Expect.isTrue(!([1] is List<String>));
-  Expect.isTrue(<int>[1] is List);
-  Expect.isTrue(<int>[1] is List<int>);
-  Expect.isTrue(!(<int>[1] is List<String>));
-}
-
-testParametrizedClass() {
-  Expect.isTrue(new Base<int, int>(1, 1) is Base<int, int>);
-  Expect.isTrue(new Base<int, int>(1, 1) is Base);
-  Expect.isTrue(new Base<int, int>(1, 1) is Base<Object, Object>);
-  Expect.isTrue(!(new Base<int, int>(1, 1) is Base<int, String>));
-  Expect.isTrue(!(new Base<int, int>(1, 1) is Base<String, int>));
-  Expect.isTrue(new Sub1<int, String>(1, "1") is Base<int, int>);
-  Expect.isTrue(new Sub1<int, String>(1, "1") is Base);
-  Expect.isTrue(new Sub1<int, String>(1, "1") is Sub1<int, String>);
-  Expect.isTrue(new Sub1<int, String>(1, "1") is Sub1);
-  Expect.isTrue(!(new Sub1<int, String>(1, "1") is Base<String, int>));
-  Expect.isTrue(!(new Sub1<int, String>(1, "1") is Base<int, String>));
-  Expect.isTrue(!(new Sub1<int, String>(1, "1") is Sub1<String, String>));
-  Expect.isTrue(new Sub2<int, String>(1, "1") is Base<String, int>);
-  Expect.isTrue(new Sub2<int, String>(1, "1") is Base);
-  Expect.isTrue(new Sub2<int, String>(1, "1") is Sub2<int, String>);
-  Expect.isTrue(new Sub2<int, String>(1, "1") is Sub2);
-  Expect.isTrue(!(new Sub2<int, String>(1, "1") is Base<int, int>));
-  Expect.isTrue(!(new Sub2<int, String>(1, "1") is Base<int, String>));
-  Expect.isTrue(!(new Sub2<int, String>(1, "1") is Sub2<String, String>));
-}
-
-testTypeTester() {
-  Expect.isTrue(new TypeTester<int>().isCorrectType(10));
-  Expect.isTrue(!new TypeTester<int>().isCorrectType("abc"));
-  Expect.isTrue(new TypeTester<List<int>>().isCorrectType([1]));
-  Expect.isTrue(new TypeTester<List<int>>().isCorrectType(<int>[1]));
-  Expect.isTrue(!new TypeTester<List<int>>().isCorrectType(<String>["1"]));
-  Expect.isTrue(new TypeTester<Base<String, int>>()
-      .isCorrectType(new Sub2<int, String>(1, "1")));
-  Expect.isTrue(new TypeTester<Sub2<int, String>>()
-      .isCorrectType(new Sub2<int, String>(1, "1")));
-}
-
-testClosureTypeTester() {
-  Expect.isTrue(new ClosureTypeTester<int>().isCorrectType(10));
-  Expect.isTrue(!new ClosureTypeTester<int>().isCorrectType("abc"));
-  Expect.isTrue(new ClosureTypeTester<List<int>>().isCorrectType([1]));
-  Expect.isTrue(new ClosureTypeTester<List<int>>().isCorrectType(<int>[1]));
-  Expect
-      .isTrue(!new ClosureTypeTester<List<int>>().isCorrectType(<String>["1"]));
-  Expect.isTrue(new ClosureTypeTester<Base<String, int>>()
-      .isCorrectType(new Sub2<int, String>(1, "1")));
-  Expect.isTrue(new ClosureTypeTester<Sub2<int, String>>()
-      .isCorrectType(new Sub2<int, String>(1, "1")));
-}
-
-testConstTypeArguments() {
-  Expect.isTrue(const Sub1<int, String>(1, "1") is Sub1<int, String>);
-  Expect.isTrue(const Sub1<int, String>.fac(1, "1") is Sub1<int, String>);
-  Expect.isTrue(!(const Sub1<int, String>(1, "1") is Sub1<String, String>));
-  Expect.isTrue(!(const Sub1<int, String>.fac(1, "1") is Sub1<String, String>));
-
-  Expect.isTrue(const ClosureTypeTester<List<Base<int, String>>>()
-      .isCorrectType(
-          const <Base<int, String>>[const Base<int, String>(1, "2")]));
-  Expect.isTrue(const ClosureTypeTester<List<Base<int, String>>>()
-      .isCorrectType(
-          const <Base<int, String>>[const Base<int, String>.fac(1, "2")]));
-  Expect.isTrue(!const ClosureTypeTester<List<Base<int, String>>>()
-      .isCorrectType(
-          const <Base<String, String>>[const Base<String, String>("1", "2")]));
-  Expect.isTrue(!const ClosureTypeTester<List<Base<int, String>>>()
-      .isCorrectType(const <Base<String, String>>[
-    const Base<String, String>.fac("1", "2")
-  ]));
-
-  Expect.isTrue(const TypeTester<Sub2<int, String>>()
-      .isCorrectType(const Sub2<int, String>(1, "1")));
-  Expect.isTrue(const TypeTester<Sub2<int, String>>()
-      .isCorrectType(const Sub2<int, String>.fac(1, "1")));
-  Expect.isTrue(!const TypeTester<Sub2<int, String>>()
-      .isCorrectType(const Sub2<String, String>("a", "b")));
-  Expect.isTrue(!const TypeTester<Sub2<int, String>>()
-      .isCorrectType(const Sub2<String, String>.fac("a", "b")));
-}
-
-testNoBound() {
-  new G<int>();
-  new G<num>();
-  new G<Function>();
-  new G<Object>();
-  new G();
-  new G();
-  new G<G>();
-}
-
-testSubtypeChecker() {
-  Expect.isTrue(new TypeTester<num>().isCorrectType(1));
-  Expect.isTrue(new TypeTester<num>().isCorrectType(1.0));
-  Expect.isTrue(new TypeTester<A>().isCorrectType(new B()));
-  Expect.isTrue(new TypeTester<Object>().isCorrectType(new C()));
-  Expect.isTrue(new TypeTester<I>().isCorrectType(new A()));
-}
-
-testFunctionTypes() {
-  fun(int x, String y) => "${x}${y}";
-  Expect.isTrue(!(fun is FunctionType));
-
-  fun1(num x, Pattern y) => 123;
-  Expect.isTrue(fun1 is FunctionType);
-
-  fun2(num x, String y) => 123;
-  Expect.isTrue(!(fun2 is FunctionType));
-
-  Expect.isTrue(!(nan is FunctionType));
-  Expect.isTrue(nan is Function);
-}
-
-num nan(double d, Pattern p) => double.nan;
-
-typedef int FunctionType(num _, Pattern __);
-
-testLiteralTypeArguments() {
-  Expect.isTrue(new Foo<String, int>().foo() is List<String>);
-  Expect.isTrue(new Foo<int, String>().bar() is Map<int, String>);
-}
-
-class Foo<T1, T2> {
-  foo() => <T1>[];
-  bar() => <T1, T2>{};
-}
-
-regressionTest1() {
-  Expect.isTrue(!StaticTypeTester.isInt('abc'));
-}
-
-class StaticTypeTester<T> {
-  static isInt(x) => x is int;
-}
-
-main() {
-  testConstantLiteralTypes();
-  testNonConstantLiteralTypes();
-  testParametrizedClass();
-  testTypeTester();
-  testClosureTypeTester();
-  testConstTypeArguments();
-  testNoBound();
-  testSubtypeChecker();
-  testFunctionTypes();
-  testLiteralTypeArguments();
-  regressionTest1();
-}
diff --git a/tests/language/argument/assignability_function_typed_test.dart b/tests/language/argument/assignability_function_typed_test.dart
index fe17a15..b2d6e26 100644
--- a/tests/language/argument/assignability_function_typed_test.dart
+++ b/tests/language/argument/assignability_function_typed_test.dart
@@ -31,15 +31,15 @@
   f(intToObject);
   //^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-  // [cfe] The top level function has type 'Object Function(int)' that isn't of expected type 'num Function(num)'.
+  // [cfe] The argument type 'Object Function(int)' can't be assigned to the parameter type 'num Function(num)'.
   f(intToNum);
   //^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-  // [cfe] The top level function has type 'num Function(int)' that isn't of expected type 'num Function(num)'.
+  // [cfe] The argument type 'num Function(int)' can't be assigned to the parameter type 'num Function(num)'.
   f(numToObject);
   //^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-  // [cfe] The top level function has type 'Object Function(num)' that isn't of expected type 'num Function(num)'.
+  // [cfe] The argument type 'Object Function(num)' can't be assigned to the parameter type 'num Function(num)'.
 
   // Ok.
   f(numToNum);
diff --git a/tests/language/async/await_test.dart b/tests/language/async/await_test.dart
index eca75a8..07c3dad 100644
--- a/tests/language/async/await_test.dart
+++ b/tests/language/async/await_test.dart
@@ -1367,7 +1367,7 @@
 
   group("if", () {
     test("await in test", () {
-      f(v) async {
+      f(bool v) async {
         if (await new Future.value(v)) {
           return 42;
         } else {
@@ -1379,7 +1379,7 @@
     });
 
     test("await err in test", () {
-      f(v) async {
+      f(bool v) async {
         if (await new Future.error("err")) {
           return 42;
         } else {
@@ -1391,7 +1391,7 @@
     });
 
     test("await in then", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return await new Future.value(42);
         }
@@ -1402,7 +1402,7 @@
     });
 
     test("await err in then", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return await new Future.error("err");
         }
@@ -1413,7 +1413,7 @@
     });
 
     test("await in then with else", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return await new Future.value(42);
         } else {
@@ -1426,7 +1426,7 @@
     });
 
     test("await err in then with else", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return await new Future.error("err");
         } else {
@@ -1439,7 +1439,7 @@
     });
 
     test("await in else", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return 37;
         } else {
@@ -1452,7 +1452,7 @@
     });
 
     test("await err in else", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return 37;
         } else {
@@ -1465,7 +1465,7 @@
     });
 
     test("await in else-if test", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return 37;
         } else if (!await new Future.value(v)) {
@@ -1480,7 +1480,7 @@
     });
 
     test("await in else-if then", () {
-      f(v) async {
+      f(bool v) async {
         if (v) {
           return 37;
         } else if (!v) {
@@ -1497,7 +1497,7 @@
 
   group("conditional operator", () {
     test("await in test", () {
-      f(v) async {
+      f(bool v) async {
         return (await new Future.value(v)) ? 42 : 37;
       }
 
@@ -1505,7 +1505,7 @@
     });
 
     test("await err in test", () {
-      f(v) async {
+      f(bool v) async {
         return (await new Future.error("err")) ? 42 : 37;
       }
 
@@ -1513,7 +1513,7 @@
     });
 
     test("await in then", () {
-      f(v) async {
+      f(bool v) async {
         return v ? (await new Future.value(42)) : 37;
       }
 
@@ -1521,7 +1521,7 @@
     });
 
     test("await err in then", () {
-      f(v) async {
+      f(bool v) async {
         return v ? (await new Future.error("err")) : 37;
       }
 
@@ -1529,7 +1529,7 @@
     });
 
     test("await in else", () {
-      f(v) async {
+      f(bool v) async {
         return v ? 37 : (await new Future.value(42));
       }
 
@@ -1537,7 +1537,7 @@
     });
 
     test("await err in else", () {
-      f(v) async {
+      f(bool v) async {
         return v ? 37 : (await new Future.error("err"));
       }
 
diff --git a/tests/language/async/return_types_test.dart b/tests/language/async/return_types_test.dart
index f378549..3de5491 100644
--- a/tests/language/async/return_types_test.dart
+++ b/tests/language/async/return_types_test.dart
@@ -19,7 +19,7 @@
   return "String";
   //     ^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.RETURN_OF_INVALID_TYPE
-  // [cfe] A value of type 'String' can't be assigned to a variable of type 'FutureOr<int>'.
+  // [cfe] A value of type 'String' can't be returned from an async function with return type 'Future<int>'.
 }
 
 Future<int, String>
@@ -34,7 +34,7 @@
 // [error line 33, column 1, length 3]
 // [analyzer] COMPILE_TIME_ERROR.ILLEGAL_ASYNC_RETURN_TYPE
 foo5() async {
-// [error line 36, column 1, length 3]
+// [error line 36, column 1]
 // [cfe] Functions marked 'async' must have a return type assignable to 'Future'.
   return 3;
 }
diff --git a/tests/language/await/null_aware_test.dart b/tests/language/await/null_aware_test.dart
index 819de12..88f16f0 100644
--- a/tests/language/await/null_aware_test.dart
+++ b/tests/language/await/null_aware_test.dart
@@ -13,11 +13,11 @@
 }
 
 main() async {
-  int? x = 1;
+  var x = 1 as int?;
   x ??= await f();
   Expect.equals(1, x);
 
-  int? y = 1;
+  var y = 1 as int?;
   y = y ?? await f();
   Expect.equals(1, y);
 }
diff --git a/tests/language/class/cyclic_hierarchy_test.dart b/tests/language/class/cyclic_hierarchy_test.dart
new file mode 100644
index 0000000..0a892f3
--- /dev/null
+++ b/tests/language/class/cyclic_hierarchy_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for cyclic class hierarchy seen in: https://github.com/flutter/flutter/issues/64011
+
+class A extends B<C> {}
+
+class C extends A {}
+
+class B<T> {}
+
+main() => print(A());
diff --git a/tests/language/class/keyword_test.dart b/tests/language/class/keyword_test.dart
index 5a89f2e..8b07fec 100644
--- a/tests/language/class/keyword_test.dart
+++ b/tests/language/class/keyword_test.dart
@@ -13,15 +13,15 @@
 // [cfe] Expected ';' after this.
 //    ^^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-// [cfe] Expected an identifier, but got 'class'.
+// [cfe] 'class' can't be used as an identifier because it's a keyword.
 //    ^^^^^
-// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
 // [cfe] Setter not found: 'class'.
   print("$class");
   //      ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-  // [cfe] Expected an identifier, but got 'class'.
+  // [cfe] 'class' can't be used as an identifier because it's a keyword.
   //      ^^^^^
-  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
   // [cfe] Getter not found: 'class'.
 }
diff --git a/tests/language/const/syntax_test.dart b/tests/language/const/syntax_test.dart
index 138d30c..aa33723 100644
--- a/tests/language/const/syntax_test.dart
+++ b/tests/language/const/syntax_test.dart
@@ -59,7 +59,11 @@
 const int F3;
 //        ^^
 // [analyzer] COMPILE_TIME_ERROR.CONST_NOT_INITIALIZED
+// [cfe] Field 'F3' should be initialized because its type 'int' doesn't allow null.
+//        ^
 // [cfe] The const variable 'F3' must be initialized.
+//          ^
+// [cfe] A value of type 'Null' can't be assigned to a variable of type 'int'.
 
 class Point {
   final x, y;
diff --git a/tests/language/constructor/missing_initializer_test.dart b/tests/language/constructor/missing_initializer_test.dart
index 3736c5f..2de088e 100644
--- a/tests/language/constructor/missing_initializer_test.dart
+++ b/tests/language/constructor/missing_initializer_test.dart
@@ -12,7 +12,7 @@
   final dynamic n;
   //            ^
   // [analyzer] COMPILE_TIME_ERROR.FINAL_NOT_INITIALIZED
-  // [cfe] unspecified
+  // [cfe] Final field 'n' is not initialized.
 
   // Uninitialized, but no errors.
   abstract final int x1;
@@ -34,6 +34,7 @@
 class C = Object with A;
   //  ^
   // [analyzer] COMPILE_TIME_ERROR.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER
+  // [cfe] The non-abstract class 'C' is missing implementations for these members:
 
 // Has a generative constructor: default.
 abstract class D {
diff --git a/tests/language/enum/is_keyword_test.dart b/tests/language/enum/is_keyword_test.dart
index 5e7d0b5..4d37239 100644
--- a/tests/language/enum/is_keyword_test.dart
+++ b/tests/language/enum/is_keyword_test.dart
@@ -8,6 +8,6 @@
 main() {
   var enum;
   //  ^^^^
-  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
-  // [cfe] Expected an identifier, but got 'enum'.
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+  // [cfe] 'enum' can't be used as an identifier because it's a keyword.
 }
diff --git a/tests/language/export/dual_export_triangle_a.dart b/tests/language/export/dual_export_triangle_a.dart
deleted file mode 100644
index eb99e69..0000000
--- a/tests/language/export/dual_export_triangle_a.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'dual_export_triangle_b.dart';
-
-class A extends B {}
diff --git a/tests/language/export/dual_export_triangle_b.dart b/tests/language/export/dual_export_triangle_b.dart
deleted file mode 100644
index c4d56e1..0000000
--- a/tests/language/export/dual_export_triangle_b.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'dual_export_triangle_c.dart';
-
-class B extends C {}
diff --git a/tests/language/export/dual_export_triangle_c.dart b/tests/language/export/dual_export_triangle_c.dart
deleted file mode 100644
index 705e6daa..0000000
--- a/tests/language/export/dual_export_triangle_c.dart
+++ /dev/null
@@ -1,5 +0,0 @@
-import 'dual_export_triangle_a.dart';
-
-class C0<T> {}
-
-class C extends C0<A> {}
diff --git a/tests/language/export/dual_export_triangle_entrypoint.dart b/tests/language/export/dual_export_triangle_entrypoint.dart
deleted file mode 100644
index 47d048d..0000000
--- a/tests/language/export/dual_export_triangle_entrypoint.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-import 'dual_export_triangle_a.dart';
-
-class Entrypoint {}
diff --git a/tests/language/export/dual_export_triangle_test.dart b/tests/language/export/dual_export_triangle_test.dart
deleted file mode 100644
index 0d64571..0000000
--- a/tests/language/export/dual_export_triangle_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test for cyclic export regression seen in: https://github.com/flutter/flutter/issues/64011
-
-// dual_export_triangle_entrypoint imports dual_export_triangle_a.
-// dual_export_triangle_a defines A (extends B).
-// dual_export_triangle_b defines B (extends C).
-// dual_export_triangle_c defines C (with type parameter A).
-// dual_export_triangle_test exports both dual_export_triangle_entrypoint and
-// either dual_export_triangle_b or dual_export_triangle_c.
-
-library dual_export_triangle_test;
-
-import 'dual_export_triangle_entrypoint.dart';
-
-export 'dual_export_triangle_entrypoint.dart';
-export 'dual_export_triangle_b.dart';
-
-main() {
-  print(Entrypoint());
-}
diff --git a/tests/language/extension_methods/static_extension_resolution_7_test.dart b/tests/language/extension_methods/static_extension_resolution_7_test.dart
new file mode 100644
index 0000000..96c1712
--- /dev/null
+++ b/tests/language/extension_methods/static_extension_resolution_7_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Tests the resolution of a bare type variable with bounded or promoted type.
+
+extension E<T> on T {
+  T Function(T) get f => (_) => this;
+}
+
+class A<S extends num> {
+  void testBoundedTypeVariable(S s) {
+    // Check that `num` has no `f` so E is applicable, then bind `T` to `S`.
+    S Function(S) f = s.f;
+  }
+
+  void testPromotedTypeVariable(S s) {
+    if (s is int) {
+      // Check that `int` has no `f`, erase `S & int` to `S`, bind `T` to `S`.
+      S Function(S) f = s.f;
+    }
+  }
+}
+
+class B<S extends dynamic> {
+  void testBoundedTypeVariable(S s) {
+    // `dynamic` considered to have `f`, E not applicable, dynamic invocation.
+    Expect.throws(() => s.f);
+  }
+
+  void testPromotedType(S s) {
+    if (s is int) {
+      // Check that `int` has no `f`, bind `T` to `int`.
+      int Function(int) f = s.f;
+    }
+  }
+}
+
+class C<S> {
+  void testBoundedTypeVariable(S s) {
+    // Check that `Object?` has no `f` so E is applicable, then bind `T` to `S`.
+    S Function(S) f = s.f;
+  }
+
+  void testPromotedType(S s) {
+    if (s is int) {
+      // Check that `int` has no `f`, bind `T` to `S`.
+      S Function(S) f = s.f;
+    }
+  }
+}
+
+void main() {
+  A<int>()
+    ..testBoundedTypeVariable(1)
+    ..testPromotedTypeVariable(2);
+  B<int>()
+    ..testBoundedTypeVariable(1)
+    ..testPromotedType(2);
+  C<int>()
+    ..testBoundedTypeVariable(1)
+    ..testPromotedType(2);
+}
diff --git a/tests/language/function/call_generic_test.dart b/tests/language/function/call_generic_test.dart
index de3b0bd..19ea8ba 100644
--- a/tests/language/function/call_generic_test.dart
+++ b/tests/language/function/call_generic_test.dart
@@ -35,7 +35,7 @@
 }
 
 main() {
-  check([dynamic, 1, 2, 3, null, null], staticFn(1 as dynamic, 2, 3));
+  check([Object, 1, 2, 3, null, null], staticFn(1 as dynamic, 2, 3));
 
   check([Object, 'Z', 2, 4, null, null], staticFn('Z', 2, 4));
 
@@ -53,13 +53,13 @@
 
   var c = new C();
 
-  check([dynamic, 8, 2, 3, null, null], c.memberFn(8 as dynamic, 2, 3));
+  check([Object, 8, 2, 3, null, null], c.memberFn(8 as dynamic, 2, 3));
 
   check([Object, 'A', 2, 3, null, null], c.memberFn('A', 2, 3));
 
   check([int, 9, 2, 3, null, null], c.memberFn<int>(9, 2, 3));
 
-  check([dynamic, 10, 2, 3, null, null], c.map(10 as dynamic, 2, 3));
+  check([Object, 10, 2, 3, null, null], c.map(10 as dynamic, 2, 3));
 
   check([Object, 'B', 2, 3, null, null], c.map('B', 2, 3));
 
diff --git a/tests/language/if_null/assignment_behavior_test.dart b/tests/language/if_null/assignment_behavior_test.dart
index b17afd1..9bbfe18 100644
--- a/tests/language/if_null/assignment_behavior_test.dart
+++ b/tests/language/if_null/assignment_behavior_test.dart
@@ -123,6 +123,8 @@
     finalOne ??= null;
 //  ^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL
+// [cfe] Operand of null-aware operation '??=' has type 'int' which excludes null.
+//  ^
 // [cfe] The setter 'finalOne' isn't defined for the class 'C'.
 //               ^^^^
 // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
@@ -162,6 +164,8 @@
   h.xGetValue = 1; check(1, () => h.x ??= bad(), ['h.x']);
   yGetValue = 1; check(1, () => h.x ??= y, ['h.x', 'y', 'h.x=1']);
   { var l = 1; check(1, () => l ??= bad(), []); }
+  //                          ^
+  // [cfe] Operand of null-aware operation '??=' has type 'int' which excludes null.
   //                                ^^^^^
   // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
   { var l; yGetValue = 1; check(1, () => l ??= y, ['y']); Expect.equals(1, l); }
@@ -169,6 +173,8 @@
   //             ^
   // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
   // [cfe] Can't assign to the final variable 'l'.
+  //             ^
+  // [cfe] Operand of null-aware operation '??=' has type 'int' which excludes null.
   //                   ^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   //                   ^^^^
@@ -177,6 +183,8 @@
 //^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
 // [cfe] Can't assign to a type literal.
+//^
+// [cfe] Operand of null-aware operation '??=' has type 'Type' which excludes null.
   h ??= null;
 //^
 // [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
diff --git a/tests/language/if_null/assignment_static_test.dart b/tests/language/if_null/assignment_static_test.dart
index 14edd3c..7eee56b 100644
--- a/tests/language/if_null/assignment_static_test.dart
+++ b/tests/language/if_null/assignment_static_test.dart
@@ -141,7 +141,7 @@
   // The static type of e1?.v op= e2 is the static type of e1.v op e2,
   // therefore the static type of e1?.v ??= e2 is the static type of
   // e1.v ?? e2, which is the LUB of NonNull(typeof(e1?.v)) and typeof(e2).
-  ClassWithInstanceGetters? c = new ClassWithInstanceGetters();
+  var c = new ClassWithInstanceGetters() as ClassWithInstanceGetters?;
   (c?.a ??= theA)!.a; //# 36: ok
   (c?.a ??= theA)!.b; //# 37: compile-time error
   (c?.a ??= theB)!.a; //# 38: ok
diff --git a/tests/language/if_null/behavior_test.dart b/tests/language/if_null/behavior_test.dart
index a679108..a55d7f5 100644
--- a/tests/language/if_null/behavior_test.dart
+++ b/tests/language/if_null/behavior_test.dart
@@ -32,8 +32,8 @@
 C? nullC() => null;
 
 main() {
-  int? one = 1;
-  B? b = B('B');
+  var one = 1 as int?;
+  var b = B('B') as B?;
   Expect.equals(1, one ?? 2);
   Expect.equals(1, one ?? null);
   Expect.equals(2, null ?? 2);
diff --git a/tests/language/if_null/evaluation_order_test.dart b/tests/language/if_null/evaluation_order_test.dart
index ca78ab4..c4da142 100644
--- a/tests/language/if_null/evaluation_order_test.dart
+++ b/tests/language/if_null/evaluation_order_test.dart
@@ -27,7 +27,7 @@
 }
 
 main() {
-  int? one = 1;
+  var one = 1 as int?;
   Expect.equals(1, one ?? bad());
   Expect.equals(2, first() ?? second());
 }
diff --git a/tests/language/if_null/precedence_test.dart b/tests/language/if_null/precedence_test.dart
index eeb9570..abc0755 100644
--- a/tests/language/if_null/precedence_test.dart
+++ b/tests/language/if_null/precedence_test.dart
@@ -41,6 +41,8 @@
   // type warning if b doesn't have type bool.  An incorrect parse of
   // "a || (b ?? c)" would allow b to have any type provided that c is bool.
   falsity || 1 ?? true;
+//        ^
+// [cfe] Operand of null-aware operation '??' has type 'bool' which excludes null.
 //           ^
 // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_OPERAND
 // [cfe] A value of type 'int' can't be assigned to a variable of type 'bool'.
@@ -50,6 +52,8 @@
   // An incorrect parse of "a || (b ?? c)" would result in no checked-mode
   // error.
   Expect.throwsAssertionError(() => false || null ?? true);
+  //                                      ^
+  // [cfe] Operand of null-aware operation '??' has type 'bool' which excludes null.
   //                                         ^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_OPERAND
   // [cfe] A value of type 'Null' can't be assigned to a variable of type 'bool'.
diff --git a/tests/language/implicit_downcast_during/if_null_assignment_test.dart b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
index 7c91b32..c29d634 100644
--- a/tests/language/implicit_downcast_during/if_null_assignment_test.dart
+++ b/tests/language/implicit_downcast_during/if_null_assignment_test.dart
@@ -8,7 +8,7 @@
 
 void main() {
   B? b;
-  A? a = new B();
+  var a = new B() as A?;
   b ??= a;
 //      ^
 // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
diff --git a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
index 535c7db..59c115e 100644
--- a/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
+++ b/tests/language/implicit_downcast_during/null_aware_method_invocation_test.dart
@@ -11,7 +11,7 @@
 }
 
 main() {
-  C? c = new C();
+  var c = new C() as C?;
   A a = new B();
   c?.f(a);
 //     ^
diff --git a/tests/language/inference/dynamic_nullable_test.dart b/tests/language/inference/dynamic_nullable_test.dart
index 6bcb121..46b6591 100644
--- a/tests/language/inference/dynamic_nullable_test.dart
+++ b/tests/language/inference/dynamic_nullable_test.dart
@@ -55,7 +55,7 @@
 
     var c = C.list(o);
     var f = bar(o);
-    var l = o.whereNotNull;
+    var l = o.whereNotNull();
 
     c.expectStaticType<Exactly<C<Object>>>();
     Expect.type<C<Object>>(c); // Run-time type is subtype of C<Object>.
diff --git a/tests/language/inference/inconsistent_inheritance_test.dart b/tests/language/inference/inconsistent_inheritance_test.dart
index 8ff26eb..beff18f 100644
--- a/tests/language/inference/inconsistent_inheritance_test.dart
+++ b/tests/language/inference/inconsistent_inheritance_test.dart
@@ -4,10 +4,14 @@
 
 class A {
   void f(Object x) {}
+
+  void g(Object x, String y) {}
 }
 
 class B {
   void f(String x) {}
+
+  void g(String x, Object y) {}
 }
 
 class C extends A implements B {
@@ -19,6 +23,16 @@
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
     // [cfe] A value of type 'Object' can't be assigned to a variable of type 'String'.
   }
+
+  // No combined signature.
+  void g(x, y) {
+    // ^
+    // [analyzer] COMPILE_TIME_ERROR.NO_COMBINED_SUPER_SIGNATURE
+    //   ^
+    // [cfe] Can't infer a type for 'x' as the overridden members don't have a combined signature.
+    //      ^
+    // [cfe] Can't infer a type for 'y' as the overridden members don't have a combined signature.
+  }
 }
 
 void main() {}
diff --git a/tests/language/label/label8_test.dart b/tests/language/label/label8_test.dart
index 89c6efb6..5d37693 100644
--- a/tests/language/label/label8_test.dart
+++ b/tests/language/label/label8_test.dart
@@ -14,12 +14,12 @@
     case 111:
 //  ^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
+// [cfe] 'case' can't be used as an identifier because it's a keyword.
+//  ^^^^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
 // [cfe] Expected ';' after this.
 //  ^^^^
 // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
-// [cfe] Expected an identifier, but got 'case'.
-//  ^^^^
-// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
 // [cfe] Getter not found: 'case'.
 //  ^^^^
 // [analyzer] SYNTACTIC_ERROR.MISSING_STATEMENT
diff --git a/tests/language/language.status b/tests/language/language.status
index 277066a..09e7d9e 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -42,7 +42,7 @@
 [ $compiler != dart2js && $compiler != dartdevc && !$checked ]
 function_type/*: Skip # Needs checked mode.
 
-[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $mode == debug && $runtime == vm ]
+[ $compiler != dartk && $compiler != dartkp && $mode == debug && $runtime == vm ]
 identifier/built_in_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
 
 [ $hot_reload || $hot_reload_rollback ]
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index 9ff89b0..c3aae5e 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -218,9 +218,44 @@
 vm/no_such_method_error_message_vm_test: SkipByDesign # Looks for unobfuscated name in error message
 vm/regress_28325_test: SkipByDesign # Looks for filename in stack trace
 
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+async_star/async_star2_test/01: Crash
+async_star/async_star2_test/05: Crash
+
 [ $compiler == dartk && $mode == debug && ($hot_reload || $hot_reload_rollback) ]
+enum/duplicate_test/02: Crash # Issue 34606
+enum/duplicate_test/none: Crash # Issue 34606
+enum/private_test/01: Crash # Issue 34606
+enum/test: Crash # Issue 34606
 unsorted/inference_enum_list_test: Skip # Issue 35885
 
+[ $compiler == dartk && $mode == product && $runtime == vm ]
+vm/causal_async_exception_stack2_test: SkipByDesign
+vm/causal_async_exception_stack_test: SkipByDesign
+
+# ===== dartk + vm status lines =====
+[ $compiler == dartk && $runtime == vm ]
+const/const2_test: Crash # Flaky
+main/no_main_test/01: Skip
+mixin/illegal_super_use_test: Skip # Issues 24478 and 23773
+mixin/illegal_superclass_test: Skip # Issues 24478 and 23773
+unsorted/disassemble_test: Slow, Crash # dartbug.com/34971
+vm/closure_memory_retention_test: Skip # KernelVM bug: Hits OOM
+vm/regress_29145_test: Skip # Issue 29145
+web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
+
+[ $compiler == dartk && $hot_reload_rollback ]
+symbol/conflict_test: Slow, Pass
+
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+async_star/async_star2_test/01: Skip # Timeout
+async_star/async_star2_test/02: Skip # Timeout
+async_star/async_star2_test/03: Skip # Timeout
+async_star/async_star2_test/04: Skip # Timeout
+async_star/async_star2_test/05: Skip # Timeout
+async_star/async_star2_test/none: Skip # Timeout
+type_constants_test/none: Skip # Deferred libraries and hot reload.
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 vm/precompiled_static_initializer_test: Slow, Pass
 
@@ -280,42 +315,5 @@
 [ $compiler == dartkp && $system == windows ]
 unsorted/disassemble_test: Slow, Pass
 
-[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
+[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk) ]
 optimize/deopt_inlined_function_lazy_test: Skip
-
-[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-async_star/async_star2_test/01: Crash
-async_star/async_star2_test/05: Crash
-
-[ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-enum/duplicate_test/02: Crash # Issue 34606
-enum/duplicate_test/none: Crash # Issue 34606
-enum/private_test/01: Crash # Issue 34606
-enum/test: Crash # Issue 34606
-
-[ $mode == product && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-vm/causal_async_exception_stack2_test: SkipByDesign
-vm/causal_async_exception_stack_test: SkipByDesign
-
-# ===== dartk + vm status lines =====
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-const/const2_test: Crash # Flaky
-main/no_main_test/01: Skip
-mixin/illegal_super_use_test: Skip # Issues 24478 and 23773
-mixin/illegal_superclass_test: Skip # Issues 24478 and 23773
-unsorted/disassemble_test: Slow, Crash # dartbug.com/34971
-vm/closure_memory_retention_test: Skip # KernelVM bug: Hits OOM
-vm/regress_29145_test: Skip # Issue 29145
-web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
-
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-symbol/conflict_test: Slow, Pass
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-async_star/async_star2_test/01: Skip # Timeout
-async_star/async_star2_test/02: Skip # Timeout
-async_star/async_star2_test/03: Skip # Timeout
-async_star/async_star2_test/04: Skip # Timeout
-async_star/async_star2_test/05: Skip # Timeout
-async_star/async_star2_test/none: Skip # Timeout
-type_constants_test/none: Skip # Deferred libraries and hot reload.
diff --git a/tests/language/least_upper_bound/least_upper_bound_fbound_test.dart b/tests/language/least_upper_bound/least_upper_bound_fbound_test.dart
new file mode 100644
index 0000000..9fb032f
--- /dev/null
+++ b/tests/language/least_upper_bound/least_upper_bound_fbound_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../static_type_helper.dart';
+
+// Test least upper bound for a type variable with an F-bound.
+
+bool condition = true;
+
+class A<X extends A<X, X>?, Y extends A<Y, Y>?> {
+  X x;
+  late Y y;
+
+  A(this.x);
+
+  void m(X x, Y y) {
+    // UP(X extends A<X, X>?, Y extends A<Y, Y>?) ==
+    // A<Object?, Object?>?.
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<A<Object?, Object?>?>>();
+
+    // Distinguish top types.
+    if (z == null) throw 0;
+    var zx = z.x, zy = z.y;
+
+    // Not `dynamic`, not `void`.
+    zx?.whatever;
+    //  ^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+    // [cfe] The getter 'whatever' isn't defined for the class 'Object'.
+    zy?.whatever;
+    //  ^^^^^^^^
+    // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+    // [cfe] The getter 'whatever' isn't defined for the class 'Object'.
+
+    if (zx == null || zy == null) throw 0;
+    zx.expectStaticType<Exactly<Object>>();
+    zy.expectStaticType<Exactly<Object>>();
+  }
+}
+
+class B<X> extends A<B<X>?, B<X>?> {
+  B() : super(null);
+}
+
+void main() {
+  var b = B<Null>();
+  b.m(b, null);
+}
diff --git a/tests/language/least_upper_bound/least_upper_bound_function_test.dart b/tests/language/least_upper_bound/least_upper_bound_function_test.dart
new file mode 100644
index 0000000..0ae3e16
--- /dev/null
+++ b/tests/language/least_upper_bound/least_upper_bound_function_test.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test least upper bound for a Function type and a type that doesn't match
+// any of the cases for function types being subtypes of each other.
+
+import 'dart:async';
+import '../static_type_helper.dart';
+
+bool condition = true;
+
+void main() {
+  void f1(void Function() x, Object y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Object>>();
+  }
+
+  void f2(int x, void Function<X>() y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Object>>();
+  }
+
+  void f3(double Function(int, int) x, FutureOr<Function> y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Object>>();
+  }
+
+  void f4(FutureOr<Function?> x, Function(int i, {int j}) y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Object?>>();
+  }
+
+  void f5(Function Function<Y>([Y y]) x, dynamic y) {
+    var z = condition ? x : y;
+    // Check that the type is a top type.
+    z.expectStaticType<Exactly<dynamic>>();
+    // Check that the type is `dynamic`.
+    z.unknownMember;
+  }
+
+  void f6(Never x, Never Function() y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Never Function()>>();
+  }
+
+  void f7(Function(Function) x, Null y) {
+    var z = condition ? x : y;
+    z.expectStaticType<Exactly<Function(Function)?>>();
+  }
+}
diff --git a/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart b/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart
new file mode 100644
index 0000000..02569eb
--- /dev/null
+++ b/tests/language/least_upper_bound/least_upper_bound_futureor_test.dart
@@ -0,0 +1,527 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import '../static_type_helper.dart';
+
+// Test least upper bound for types involving `FutureOr`.
+
+bool condition = true;
+
+class A {}
+
+class B {}
+
+class C extends B {}
+
+class D extends B {}
+
+class E<T> {}
+
+class F<T> extends E<T> {}
+
+void main() {
+  // Approach: First test operand types (with no occurrence of `FutureOr`)
+  // then test those operands used as type arguments according to the
+  // rules about **UP**(T1, T2) where T1 or T2 is of the form `FutureOr<S>`.
+
+  void f1(int a, String b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<Object>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<Object>>();
+  }
+
+  void f2(FutureOr<int> a, FutureOr<String> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f3(Future<int> a, FutureOr<String> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f4(int a, FutureOr<String> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f5(int a, num b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<num>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<num>>();
+  }
+
+  void f6(FutureOr<int> a, FutureOr<num> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<num>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<num>>>();
+  }
+
+  void f7(Future<int> a, FutureOr<num> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<num>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<num>>>();
+  }
+
+  void f8(int a, FutureOr<num> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<num>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<num>>>();
+  }
+
+  void f9(List<int> a, List<String> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<List<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<List<Object>>>();
+  }
+
+  void f10(FutureOr<List<int>> a, FutureOr<List<String>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+  }
+
+  void f11(Future<List<int>> a, FutureOr<List<String>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+  }
+
+  void f12(List<int> a, FutureOr<List<String>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>>>>();
+  }
+
+  void f13(List<int> a, List<num> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<List<num>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<List<num>>>();
+  }
+
+  void f14(FutureOr<List<int>> a, FutureOr<List<num>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<num>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<num>>>>();
+  }
+
+  void f15(Future<List<int>> a, FutureOr<List<num>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<num>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<num>>>>();
+  }
+
+  void f16(List<int> a, FutureOr<List<num>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<num>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<num>>>>();
+  }
+
+  void f17(dynamic a, void b) {
+    var x = condition ? a : b;
+    /**/ x.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+
+    var y = condition ? b : a;
+    /**/ y.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+  }
+
+  void f18(FutureOr<dynamic> a, FutureOr<void> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<void>>>();
+    if (x is Future) throw 0;
+    /**/ x.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<void>>>();
+    if (y is Future) throw 0;
+    /**/ y.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+  }
+
+  void f19(Future<dynamic> a, FutureOr<void> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<void>>>();
+    if (x is Future) throw 0;
+    /**/ x.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<void>>>();
+    if (y is Future) throw 0;
+    /**/ y.toString();
+    //   ^
+    // [analyzer] COMPILE_TIME_ERROR.USE_OF_VOID_RESULT
+    // [cfe] This expression has type 'void' and can't be used.
+  }
+
+  void f20(dynamic a, FutureOr<void> b) {
+    var x = condition ? a : b;
+    // Verify that the type of `x` is a top type.
+    x.expectStaticType<Exactly<dynamic>>();
+    // Verify that it is `dynamic`.
+    x.unknownMember();
+
+    var y = condition ? b : a;
+    // Verify that the type of `y` is a top type.
+    y.expectStaticType<Exactly<dynamic>>();
+    // Verify that it is `dynamic`.
+    y.unknownMember();
+  }
+
+  void f21(A a, B b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<Object>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<Object>>();
+  }
+
+  void f22(FutureOr<A> a, FutureOr<B> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f23(Future<A> a, FutureOr<B> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f24(A a, FutureOr<B> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f25(B a, C b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<B>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<B>>();
+  }
+
+  void f26(FutureOr<B> a, FutureOr<C> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f27(Future<B> a, FutureOr<C> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f28(B a, FutureOr<C> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f29(C a, D b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<B>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<B>>();
+  }
+
+  void f30(FutureOr<C> a, FutureOr<D> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f31(Future<C> a, FutureOr<D> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f32(C a, FutureOr<D> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<B>>>();
+  }
+
+  void f33(E<B> a, E<C> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<E<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<E<B>>>();
+  }
+
+  void f34(FutureOr<E<B>> a, FutureOr<E<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f35(Future<E<B>> a, FutureOr<E<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f36(E<B> a, FutureOr<E<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f37(E<B> a, F<C> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<E<B>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<E<B>>>();
+  }
+
+  void f38(FutureOr<E<B>> a, FutureOr<F<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f39(Future<E<B>> a, FutureOr<F<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f40(E<B> a, FutureOr<F<C>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<E<B>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<E<B>>>>();
+  }
+
+  void f41(int a, String? b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<Object?>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<Object?>>();
+  }
+
+  void f42(FutureOr<int> a, FutureOr<String?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object?>>>();
+  }
+
+  void f43(Future<int> a, FutureOr<String?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object?>>>();
+  }
+
+  void f44(int a, FutureOr<String?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object?>>>();
+  }
+
+  void f45(List<int> a, List<String>? b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<List<Object>?>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<List<Object>?>>();
+  }
+
+  void f46(FutureOr<List<int>> a, FutureOr<List<String>?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+  }
+
+  void f47(Future<List<int>> a, FutureOr<List<String>?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+  }
+
+  void f48(List<int> a, FutureOr<List<String>?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<List<Object>?>>>();
+  }
+
+  void f49(E<C> a, F<B> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<Object>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<Object>>();
+  }
+
+  void f50(FutureOr<E<C>> a, FutureOr<F<B>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f51(Future<E<C>> a, FutureOr<F<B>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f52(E<C> a, FutureOr<F<B>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  // A sample of cases involving nested futures and nullable types.
+
+  void f53(int a, FutureOr<Future<int>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  // Could soundly have been `FutureOr<Future<int>>`.
+  void f54(Future<int> a, FutureOr<Future<int>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Object>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Object>>>();
+  }
+
+  void f55(Future<Future<int>> a, FutureOr<Future<int>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<Future<int>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<Future<int>>>>();
+  }
+
+  void f56(Future<FutureOr<int>> a, FutureOr<Future<int>> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<FutureOr<int>>>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<FutureOr<int>>>>();
+  }
+
+  void f57(Future<int?> a, FutureOr<int>? b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<int?>?>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<int?>?>>();
+  }
+
+  void f58(Future<int>? a, FutureOr<int?> b) {
+    var x = condition ? a : b;
+    x.expectStaticType<Exactly<FutureOr<int?>?>>();
+
+    var y = condition ? b : a;
+    y.expectStaticType<Exactly<FutureOr<int?>?>>();
+  }
+}
diff --git a/tests/language/main/main_test.dart b/tests/language/main/main_test.dart
index da3b57e..6b5c24c 100644
--- a/tests/language/main/main_test.dart
+++ b/tests/language/main/main_test.dart
@@ -6,7 +6,7 @@
 
 a //        //# 01: ok
 a, b //     //# 02: ok
-a, b, c //  //# 03: ok
+a, b, c //  //# 03: compile-time error
 a, b, {c}   //# 04: ok
 a, b, [c]   //# 05: ok
 
diff --git a/tests/language/mixin/implicit_covariance_test.dart b/tests/language/mixin/implicit_covariance_test.dart
index 5606bd7..87d3ddd 100644
--- a/tests/language/mixin/implicit_covariance_test.dart
+++ b/tests/language/mixin/implicit_covariance_test.dart
@@ -13,7 +13,7 @@
 class C {
   foo(num x) {
     if (x is! num) {
-      throw "Soudness issue: expected x to be num, got ${x.runtimeType}.";
+      throw "Soundness issue: expected x to be num, got ${x.runtimeType}.";
     }
   }
 }
diff --git a/tests/language/mixin/regress_flutter_55345_const_test.dart b/tests/language/mixin/regress_flutter_55345_const_test.dart
new file mode 100644
index 0000000..ccf04a9
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_55345_const_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that references to deduplicated mixins are properly updated
+// in types which are only accessible through constants.
+// Regression test for https://github.com/flutter/flutter/issues/55345.
+
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {
+  const State();
+}
+
+class StateA extends State {
+  const StateA();
+}
+
+class StateB extends State<int> {
+  const StateB();
+}
+
+const c1 = StateA() as dynamic;
+const c2 = StateB();
+
+main() {
+  print(const [
+    {
+      (c1 ?? c2): [
+        [c1 ?? c2]
+      ]
+    },
+    'abc'
+  ]);
+  // No compile time or runtime errors.
+}
diff --git a/tests/language/mixin/regress_flutter_55345_test.dart b/tests/language/mixin/regress_flutter_55345_test.dart
new file mode 100644
index 0000000..70df054
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_55345_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that references to deduplicated mixins are properly updated.
+// Regression test for https://github.com/flutter/flutter/issues/55345.
+
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {}
+
+class StateA extends State {}
+
+class StateB extends State<int> {}
+
+StateA? a = StateA();
+StateB? b = StateB();
+
+List<T> foo<T>(T x) {
+  print(T);
+  return <T>[x];
+}
+
+T Function<S extends T>(T) bar<T>(T x) {
+  print(T);
+
+  return <S extends T>(T y) {
+    print(S);
+    print(y);
+    return y;
+  };
+}
+
+main() {
+  var x2 = a ?? b;
+  var x3 = foo(x2);
+  var x4 = bar(x3);
+  x4(x3);
+  // No compile time or runtime errors.
+}
diff --git a/tests/language/mixin/regress_flutter_66859_1_test.dart b/tests/language/mixin/regress_flutter_66859_1_test.dart
new file mode 100644
index 0000000..544da53
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_66859_1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin M {}
+
+mixin N {}
+
+class A extends B<C> with M, N {}
+
+class B<T> {}
+
+class C extends A {}
+
+class Z extends B<Z> with M {}
+
+main() {
+  var z = Z();
+  Expect.isTrue(z is B<Z>);
+  Expect.isTrue(z is M);
+  var a = A();
+  Expect.isTrue(a is M);
+  Expect.isTrue(a is N);
+  Expect.isTrue(a is B<C>);
+}
diff --git a/tests/language/mixin/regress_flutter_66859_2_test.dart b/tests/language/mixin/regress_flutter_66859_2_test.dart
new file mode 100644
index 0000000..7a3ee64
--- /dev/null
+++ b/tests/language/mixin/regress_flutter_66859_2_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin X {}
+mixin Y {}
+mixin Z {}
+
+class A extends B<C> with X {}
+
+class C extends A with Z {}
+
+class B<T> extends Object with Y {}
+
+main() {
+  var a = A();
+  var b = B();
+  var c = C();
+  Expect.isTrue(a is A);
+  Expect.isTrue(a is B<C>);
+  Expect.isTrue(a is X);
+  Expect.isTrue(a is Y);
+  Expect.isTrue(c is C);
+  Expect.isTrue(c is A);
+  Expect.isTrue(c is B<C>);
+  Expect.isTrue(c is X);
+  Expect.isTrue(c is Y);
+  Expect.isTrue(c is Z);
+  Expect.isTrue(b is B);
+  Expect.isTrue(b is Y);
+}
diff --git a/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart b/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart
index c8b0167..e728691 100644
--- a/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart
+++ b/tests/language/nnbd/boolean_conversion/boolean_conversion_weak_test.dart
@@ -13,7 +13,7 @@
 import 'boolean_conversion_lib1.dart';
 
 void main() {
-  check(neverAsBoolean, null, Expect.throwsAssertionError);
+  check(neverAsBoolean, null, Expect.throwsReachabilityError);
 
   check(booleanAsBoolean, null, Expect.throwsAssertionError);
   check(booleanAsBoolean, true, expectOk);
diff --git a/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart b/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart
index e7934e5..69e40c7 100644
--- a/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart
+++ b/tests/language/nnbd/definite_assignment/definite_assignment_error_test.dart
@@ -38,7 +38,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Unreachable code inherits the state from the paths leading into it
@@ -54,7 +54,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // An empty conditional does not change unassignment state
@@ -69,7 +69,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Assignments in a branch that returns do not change unassignment state.
@@ -88,7 +88,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   //  Assignments in a different branch do not change unassignment state.
@@ -106,7 +106,7 @@
       use(y);
       //  ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+      // [cfe] Late variable 'y' without initializer is definitely unassigned.
     }
   }
 
@@ -123,7 +123,7 @@
     y ??= 3;
 //  ^
 // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-// [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+// [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // A while loop which does no assignments does not change unassignment state.
@@ -138,7 +138,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Uses inside a while loop which does no assignments are definitely
@@ -154,7 +154,7 @@
       use(y);
       //  ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+      // [cfe] Late variable 'y' without initializer is definitely unassigned.
     }
   }
 
@@ -171,7 +171,7 @@
       use(y);
       //  ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+      // [cfe] Late variable 'y' without initializer is definitely unassigned.
     } while (b);
   }
 
@@ -193,7 +193,7 @@
         use(y);
       //    ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+      // [cfe] Late variable 'y' without initializer is definitely unassigned.
     }
   }
 
@@ -217,7 +217,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Assignments in a closure do not affect definite unassignment before the
@@ -232,7 +232,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
     var f = () {
       x = 3;
       y = 3;
@@ -252,7 +252,7 @@
       use(y);
       //  ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+      // [cfe] Late variable 'y' without initializer is definitely unassigned.
     };
   }
 
@@ -268,7 +268,7 @@
     use(y);
     //  ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
     late int z1 = x = 3;
     late int z2 = y = 3;
   }
@@ -285,7 +285,7 @@
     for (; y < 0;) {}
     //     ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Uses in a for loop element test which are not assigned before or in the
@@ -300,7 +300,7 @@
     [for (; y < 0;) 0];
     //      ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Uses in a for loop increment which are not assigned before or in the loop
@@ -315,7 +315,7 @@
     for (;; y) {}
     //      ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 
   // Uses in a for loop element increment which are not assigned before or in
@@ -330,7 +330,7 @@
     [for (;; y) 0];
     //       ^
     // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-    // [cfe] Non-nullable late variable 'y' without initializer is definitely unassigned.
+    // [cfe] Late variable 'y' without initializer is definitely unassigned.
   }
 }
 
diff --git a/tests/language/nnbd/definite_assignment/read_error_test.dart b/tests/language/nnbd/definite_assignment/read_error_test.dart
index 2f08ad1..2747df3 100644
--- a/tests/language/nnbd/definite_assignment/read_error_test.dart
+++ b/tests/language/nnbd/definite_assignment/read_error_test.dart
@@ -1024,6 +1024,7 @@
     x++;
 //  ^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Final variable 'x' might already be assigned at this point.
   }
 
   {
@@ -1032,6 +1033,7 @@
     ++x;
 //    ^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Final variable 'x' might already be assigned at this point.
   }
 
   {
@@ -1046,6 +1048,7 @@
     x += 3;
 //  ^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Final variable 'x' might already be assigned at this point.
   }
 
   {
@@ -1054,6 +1057,7 @@
     x ??= 3;
 //  ^
 // [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_FINAL_LOCAL
+// [cfe] Final variable 'x' might already be assigned at this point.
   }
 
   {
@@ -1066,8 +1070,10 @@
     final dynamic x;
     x = 3;
     3 ?? x;
-    //   ^
-    // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
+//  ^
+// [cfe] Operand of null-aware operation '??' has type 'int' which excludes null.
+//       ^
+// [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
   }
 }
 
diff --git a/tests/language/nnbd/flow_analysis/issue41981_error_test.dart b/tests/language/nnbd/flow_analysis/issue41981_error_test.dart
index 1ff4339..6fc5ceb 100644
--- a/tests/language/nnbd/flow_analysis/issue41981_error_test.dart
+++ b/tests/language/nnbd/flow_analysis/issue41981_error_test.dart
@@ -19,5 +19,5 @@
   i; // Variable is definitely unassigned
 //^
 // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-// [cfe] Non-nullable late variable 'i' without initializer is definitely unassigned.
+// [cfe] Late variable 'i' without initializer is definitely unassigned.
 }
diff --git a/tests/language/nnbd/flow_analysis/late_var_used_before_assignment_in_switch_error_test.dart b/tests/language/nnbd/flow_analysis/late_var_used_before_assignment_in_switch_error_test.dart
index 59b5a20..b8f5e63 100644
--- a/tests/language/nnbd/flow_analysis/late_var_used_before_assignment_in_switch_error_test.dart
+++ b/tests/language/nnbd/flow_analysis/late_var_used_before_assignment_in_switch_error_test.dart
@@ -18,7 +18,7 @@
       Expect.equals(x, 10);
       //            ^
       // [analyzer] COMPILE_TIME_ERROR.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE
-      // [cfe] Non-nullable late variable 'x' without initializer is definitely unassigned.
+      // [cfe] Late variable 'x' without initializer is definitely unassigned.
       break;
     case 1:
       x = 10;
diff --git a/tests/language/nnbd/flow_analysis/never_runtime_check_nnbd.dart b/tests/language/nnbd/flow_analysis/never_runtime_check_nnbd.dart
index 78681be..a59bdd2 100644
--- a/tests/language/nnbd/flow_analysis/never_runtime_check_nnbd.dart
+++ b/tests/language/nnbd/flow_analysis/never_runtime_check_nnbd.dart
@@ -12,18 +12,64 @@
 class C {
   static int staticField = 0;
 
+  static int get staticGetterSetter => staticField;
+
+  static set staticGetterSetter(int? value) {}
+
   int instanceField;
 
+  int get instanceGetterSetter => instanceField;
+
+  set instanceGetterSetter(int? value) {}
+
+  int operator [](int index) => instanceField;
+
+  operator []=(int index, int? value) {}
+
+  static late String error;
+
+  get throwingGetter => throw 'Null access';
+
   C(this.instanceField);
 }
 
 class D extends C {
   D(int field) : super(field);
 
-  void ifNullAssignSuper(int f()) {
-    super.instanceField ??= f(); // ignore: dead_null_aware_expression
-    // Should throw if `instanceField` returns null (rather than calling `f`).
+  int ifNullAssignSuper(int f()) {
+    return super.instanceField ??= f(); // ignore: dead_null_aware_expression
   }
+
+  int ifNullAssignSuper_nullableSetter(int f()) {
+    return super.instanceGetterSetter ??=
+        f(); // ignore: dead_null_aware_expression
+  }
+
+  int ifNullAssignSuperIndex(int f()) {
+    return super[0] ??= f(); // ignore: dead_null_aware_expression
+  }
+}
+
+class E {
+  int instanceField;
+
+  E(this.instanceField);
+}
+
+extension EExt on E {
+  int get instanceGetterSetter => instanceField;
+
+  set instanceGetterSetter(int? value) {}
+
+  int operator [](int index) => instanceField;
+
+  operator []=(int index, int? value) {}
+}
+
+extension IntQExt on int? {
+  int extendedMethod(int value) => value;
+
+  int get extendedGetter => 0;
 }
 
 class NeverField {
@@ -37,89 +83,217 @@
 
 late Never topLevelNever;
 
-void neverParameter(Never n) {
-  // Should throw before getting here.
+int neverParameter(Never n) {
+  return 42;
 }
 
-void neverInitializingFormal(Never n) {
-  // Should throw before getting here.
+int neverInitializingFormal(Never n) {
+  return 42;
 }
 
-void isPromoteToNever(int i) {
-  if (i is int) return;
-  // Should throw if `i` is null.
+bool isPromoteToNever(int i) {
+  if (i is int) return true;
+  return false;
 }
 
-void isNotPromoteToNever(int i) {
+bool isPromoteToNever_noIf(int i) {
+  return i is int;
+}
+
+bool isNotPromoteToNever(int i) {
   if (i is! int) {
-    // Should throw if `i` is null.
+    return true;
   }
+  return false;
 }
 
-void equalNullPromoteToNever(int f()) {
-  if (f() == null) { // ignore: unnecessary_null_comparison
-    // Should throw if `f` returns null.
+bool isNotPromoteToNever_noIf(int i) {
+  return i is! int;
+}
+
+int equalNullPromoteToNever(int f()) {
+  if (f() == null) {
+    // ignore: unnecessary_null_comparison
+    return 42;
   }
+  return 0;
 }
 
-void notEqualNullPromoteToNever(int f()) {
-  if (f() != null) return; // ignore: unnecessary_null_comparison
-  // Should throw if `f` returns null.
+int equalNullPromoteToNever_noIf(int f()) {
+  f() == null; // ignore: unnecessary_null_comparison
+  return 42;
 }
 
-void nullEqualPromoteToNever(int f()) {
-  if (null == f()) { // ignore: unnecessary_null_comparison
-    // Should throw if `f` returns null.
+int notEqualNullPromoteToNever(int f()) {
+  if (f() != null) return 0; // ignore: unnecessary_null_comparison
+  return 42;
+}
+
+int notEqualNullPromoteToNever_noIf(int f()) {
+  f() != null; // ignore: unnecessary_null_comparison
+  return 42;
+}
+
+int nullEqualPromoteToNever(int f()) {
+  if (null == f()) {
+    // ignore: unnecessary_null_comparison
+    return 42;
   }
+  return 0;
 }
 
-void nullNotEqualPromoteToNever(int f()) {
-  if (null != f()) return; // ignore: unnecessary_null_comparison
-  // Should throw if `f` returns null.
+int nullEqualPromoteToNever_noIf(int f()) {
+  null == f(); // ignore: unnecessary_null_comparison
+  return 42;
+}
+
+int nullNotEqualPromoteToNever(int f()) {
+  if (null != f()) return 0; // ignore: unnecessary_null_comparison
+  return 42;
+}
+
+int nullNotEqualPromoteToNever_noIf(int f()) {
+  null != f(); // ignore: unnecessary_null_comparison
+  return 42;
 }
 
 int unnecessaryIfNull(int f(), int g()) {
   return f() ?? g(); // ignore: dead_null_aware_expression
-  // Should throw if `f` returns null (rather than calling `g`).
 }
 
-void ifNullAssignLocal(int local, int f()) {
-  local ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `local` returns null (rather than calling `f`).
+int ifNullAssignLocal(int local, int f()) {
+  return local ??= f(); // ignore: dead_null_aware_expression
 }
 
-void ifNullAssignStatic(int f()) {
-  C.staticField ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `staticField` returns null (rather than calling `f`).
+int ifNullAssignStatic(int f()) {
+  return C.staticField ??= f(); // ignore: dead_null_aware_expression
 }
 
-void ifNullAssignField(C c, int f()) {
-  c.instanceField ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `instanceField` returns null (rather than calling `f`).
+int ifNullAssignStaticGetter_nullableSetter(int f()) {
+  return C.staticGetterSetter ??= f(); // ignore: dead_null_aware_expression
 }
 
-void ifNullAssignIndex(List<int> x, int f()) {
-  x[0] ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `x[0]` returns null (rather than calling `f`).
+int ifNullAssignField(C c, int f()) {
+  return c.instanceField ??= f(); // ignore: dead_null_aware_expression
 }
 
-void ifNullAssignSuper(D d, int f()) {
-  d.ifNullAssignSuper(f);
+int ifNullAssignGetter_nullableSetter(C c, int f()) {
+  return c.instanceGetterSetter ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignGetter_implicitExtension(E e, int f()) {
+  return e.instanceGetterSetter ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignGetter_explicitExtension(E e, int f()) {
+  return EExt(e).instanceGetterSetter ??=
+      f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignIndex(List<int> x, int f()) {
+  return x[0] ??= f(); // ignore: dead_null_aware_expression
+}
+
+int? ifNullAssignIndex_nullAware(List<int>? x, int f()) {
+  return x?[0] ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignIndex_nullableSetter(C x, int f()) {
+  return x[0] ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignIndex_implicitExtension(E x, int f()) {
+  return x[0] ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignIndex_explicitExtension(E x, int f()) {
+  return EExt(x)[0] ??= f(); // ignore: dead_null_aware_expression
+}
+
+int ifNullAssignSuper(D d, int f()) {
+  return d.ifNullAssignSuper(f);
+}
+
+int ifNullAssignSuper_nullableSetter(D d, int f()) {
+  return d.ifNullAssignSuper_nullableSetter(f);
+}
+
+int ifNullAssignSuperIndex(D d, int f()) {
+  return d.ifNullAssignSuperIndex(f);
 }
 
 int? ifNullAssignNullAwareField(C? c, int f()) {
   return c?.instanceField ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `instanceField` returns null (rather than calling `f`).
 }
 
-void ifNullAssignNullAwareStatic(int f()) {
-  C?.staticField ??= f(); // ignore: dead_null_aware_expression
-  // Should throw if `staticField` returns null (rather than calling `f`).
+int ifNullAssignNullAwareStatic(int f()) {
+  return C?.staticField ??= f(); // ignore: dead_null_aware_expression
 }
 
-void unnecessaryNullAwareAccess(int f(), String error) {
-  f()?.gcd(throw error); // ignore: invalid_null_aware_operator
-  // Should throw if `f` returns null.
+void unnecessaryNullAwareAccess(int f()) {
+  f()?.gcd(throw 'Null access'); // ignore: invalid_null_aware_operator
+}
+
+void unnecessaryNullAwareAccess_cascaded(int f()) {
+  f()?..gcd(throw 'Null access'); // ignore: invalid_null_aware_operator
+}
+
+void unnecessaryNullAwareAccess_methodOnObject(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?.toString().compareTo(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_cascaded_methodOnObject(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?..toString().compareTo(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_methodOnExtension(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?.extendedMethod(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_cascaded_methodOnExtension(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?..extendedMethod(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_methodOnExtension_explicit(int f()) {
+  // ignore: invalid_null_aware_operator
+  IntQExt(f())?.extendedMethod(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_getter(C f()) {
+  f()?.throwingGetter; // ignore: invalid_null_aware_operator
+}
+
+void unnecessaryNullAwareAccess_cascaded_getter(C f()) {
+  f()?..throwingGetter; // ignore: invalid_null_aware_operator
+}
+
+void unnecessaryNullAwareAccess_getterOnObject(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?.hashCode.remainder(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_cascaded_getterOnObject(int f()) {
+// ignore: invalid_null_aware_operator
+  f()?..hashCode.remainder(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_getterOnExtension(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?.extendedGetter.remainder(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_cascaded_getterOnExtension(int f()) {
+  // ignore: invalid_null_aware_operator
+  f()?..extendedGetter.remainder(throw 'Null access');
+}
+
+void unnecessaryNullAwareAccess_getterOnExtension_explicit(int f()) {
+  // ignore: invalid_null_aware_operator
+  IntQExt(f())?.extendedGetter.remainder(throw 'Null access');
 }
 
 void getterReturnsNever(A a) {
@@ -152,19 +326,22 @@
   // Should throw if `method` completes normally.
 }
 
-
-void switchOnBool(bool b) {
+int switchOnBool(bool b) {
   switch (b) {
-    case true: return;
-    case false: return;
+    case true:
+      return 0;
+    case false:
+      return 1;
   }
-  // Should throw if the implicit `default` branch is taken.
+  return 42;
 }
 
 void switchOnEnum(Hand hand) {
   switch (hand) {
-    case Hand.left: return;
-    case Hand.right: return;
+    case Hand.left:
+      return;
+    case Hand.right:
+      return;
   }
   // Should throw if the implicit `default` branch is taken.
-}
\ No newline at end of file
+}
diff --git a/tests/language/nnbd/flow_analysis/never_runtime_check_test.dart b/tests/language/nnbd/flow_analysis/never_runtime_check_test.dart
index c50d3a4..810a435 100644
--- a/tests/language/nnbd/flow_analysis/never_runtime_check_test.dart
+++ b/tests/language/nnbd/flow_analysis/never_runtime_check_test.dart
@@ -22,92 +22,72 @@
 }
 
 main() {
-  Expect.throws(() {
-    neverParameter(null);
-  });
+  Expect.equals(42, neverParameter(null));
 
-  Expect.throws(() {
-    NeverField().n = null;
-  });
+  var neverField = NeverField.initializingFormal(null);
+  // Write.
+  Expect.equals(null, neverField.n = null);
+  // Read.
+  Expect.equals(null, neverField.n);
 
-  Expect.throws(() {
-    // Write.
-    topLevelNever = null;
-  });
+  // Write.
+  Expect.equals(null, topLevelNever = null);
+  // Read.
+  Expect.equals(null, topLevelNever);
 
-  Expect.throws(() {
-    // Read.
-    topLevelNever;
-  });
+  Expect.isFalse(isPromoteToNever(null));
+  Expect.isFalse(isPromoteToNever_noIf(null));
+  Expect.isTrue(isNotPromoteToNever(null));
+  Expect.isTrue(isNotPromoteToNever_noIf(null));
+  Expect.equals(42, equalNullPromoteToNever(() => null));
+  Expect.equals(42, equalNullPromoteToNever_noIf(() => null));
+  Expect.equals(42, notEqualNullPromoteToNever(() => null));
+  Expect.equals(42, notEqualNullPromoteToNever_noIf(() => null));
+  Expect.equals(42, nullEqualPromoteToNever(() => null));
+  Expect.equals(42, nullEqualPromoteToNever_noIf(() => null));
+  Expect.equals(42, nullNotEqualPromoteToNever(() => null));
+  Expect.equals(42, nullNotEqualPromoteToNever_noIf(() => null));
+  Expect.equals(42, unnecessaryIfNull(() => null, () => 42));
+  Expect.equals(42, ifNullAssignLocal(null, () => 42));
 
-  Expect.throws(() {
-    NeverField.initializingFormal(null);
-  });
+  // Write.
+  Expect.equals(null, C.staticField = null);
 
-  Expect.throws(() {
-    isPromoteToNever(null);
-  });
+  // Read.
+  Expect.equals(null, C.staticField);
 
-  Expect.throws(() {
-    isNotPromoteToNever(null);
-  });
+  Expect.equals(42, ifNullAssignStatic(() => 42));
+  Expect.equals(42, ifNullAssignStaticGetter_nullableSetter(() => 42));
+  Expect.equals(42, ifNullAssignField(C(null), () => 42));
+  Expect.equals(42, ifNullAssignGetter_nullableSetter(C(null), () => 42));
+  Expect.equals(42, ifNullAssignGetter_implicitExtension(E(null), () => 42));
+  Expect.equals(42, ifNullAssignGetter_explicitExtension(E(null), () => 42));
+  Expect.equals(42, ifNullAssignIndex(<int>[null], () => 42));
+  Expect.equals(42, ifNullAssignIndex_nullAware(<int>[null], () => 42));
+  Expect.equals(42, ifNullAssignIndex_nullableSetter(C(null), () => 42));
+  Expect.equals(42, ifNullAssignIndex_implicitExtension(E(null), () => 42));
+  Expect.equals(42, ifNullAssignIndex_explicitExtension(E(null), () => 42));
+  Expect.equals(42, ifNullAssignSuper(D(null), () => 42));
+  Expect.equals(42, ifNullAssignSuper_nullableSetter(D(null), () => 42));
+  Expect.equals(42, ifNullAssignSuperIndex(D(null), () => 42));
+  Expect.equals(42, ifNullAssignNullAwareField(C(null), () => 42));
+  Expect.equals(null, ifNullAssignNullAwareField(null, () => 42));
+  Expect.equals(42, ifNullAssignNullAwareStatic(() => 42));
 
-  Expect.throws(() {
-    equalNullPromoteToNever(() => null);
-  });
-
-  Expect.throws(() {
-    notEqualNullPromoteToNever(() => null);
-  });
-
-  Expect.throws(() {
-    nullEqualPromoteToNever(() => null);
-  });
-
-  Expect.throws(() {
-    nullNotEqualPromoteToNever(() => null);
-  });
-
-  Expect.throws(() {
-    unnecessaryIfNull(() => null, () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    ifNullAssignLocal(null, () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  C.staticField = null;
-  Expect.throws(() {
-    ifNullAssignStatic(() => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    ifNullAssignField(C(null), () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    ifNullAssignIndex(<int>[null], () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    ifNullAssignSuper(D(null), () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    ifNullAssignNullAwareField(C(null), () => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.equals(
-      ifNullAssignNullAwareField(null, () => throw "should not reach"), null);
-
-  C.staticField = null;
-  Expect.throws(() {
-    ifNullAssignNullAwareStatic(() => throw "should not reach");
-  }, (error) => error != "should not reach");
-
-  Expect.throws(() {
-    unnecessaryNullAwareAccess(() => null, "should not reach");
-  }, (error) => error != "should not reach");
+  unnecessaryNullAwareAccess(() => null);
+  unnecessaryNullAwareAccess_methodOnObject(() => null);
+  unnecessaryNullAwareAccess_cascaded_methodOnObject(() => null);
+  unnecessaryNullAwareAccess_methodOnExtension(() => null);
+  unnecessaryNullAwareAccess_cascaded_methodOnExtension(() => null);
+  unnecessaryNullAwareAccess_methodOnExtension_explicit(() => null);
+  unnecessaryNullAwareAccess_getter(() => null);
+  unnecessaryNullAwareAccess_cascaded(() => null);
+  unnecessaryNullAwareAccess_cascaded_getter(() => null);
+  unnecessaryNullAwareAccess_getterOnObject(() => null);
+  unnecessaryNullAwareAccess_cascaded_getterOnObject(() => null);
+  unnecessaryNullAwareAccess_getterOnExtension(() => null);
+  unnecessaryNullAwareAccess_cascaded_getterOnExtension(() => null);
+  unnecessaryNullAwareAccess_getterOnExtension_explicit(() => null);
 
   Expect.throws(() {
     getterReturnsNever(AImpl());
@@ -133,11 +113,22 @@
     returnsNeverInVariable(AImpl());
   });
 
-  Expect.throws(() {
-    switchOnBool(null);
-  });
+  Expect.equals(42, switchOnBool(null));
 
   Expect.throws(() {
     switchOnEnum(null);
   });
 }
+
+bool isCalled;
+
+registerCallAndReturnNull() {
+  isCalled = true;
+  return null;
+}
+
+expectCall(void Function() f) {
+  isCalled = false;
+  f();
+  Expect.isTrue(isCalled);
+}
diff --git a/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart b/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart
new file mode 100644
index 0000000..d6223d5
--- /dev/null
+++ b/tests/language/nnbd/inference/late_variable_type_for_promotion_test.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../static_type_helper.dart';
+
+/// Test that promotion logic properly understands the type of a late variable.
+/// In particular, make sure that CFE late lowering doesn't cause flow analysis
+/// to treat the type as nullable when it's non-nullable.
+
+void nonNullableInitializedWithType() {
+  late num x = 0;
+  x.expectStaticType<Exactly<num>>();
+  // Attempting to promote to `int?` should do nothing, since `int?` is not a
+  // subtype of `num`.
+  if (x is int?) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int` should be ok, though.
+  if (x is int) {
+    x.expectStaticType<Exactly<int>>();
+  }
+}
+
+void nullableInitializedWithType() {
+  late num? x = 0 as num?; // Cast to prevent promotion
+  x.expectStaticType<Exactly<num?>>();
+  // Attempting to promote to `num` should be ok, since `num` is a subtype of
+  // `num?`.
+  if (x is num) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int?` should be ok too.
+  if (x is int?) {
+    x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+void nonNullableInitializedUntyped() {
+  late var x = 0 as num;
+  x.expectStaticType<Exactly<num>>();
+  // Attempting to promote to `int?` should do nothing, since `int?` is not a
+  // subtype of `num`.
+  if (x is int?) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int` should be ok, though.
+  if (x is int) {
+    x.expectStaticType<Exactly<int>>();
+  }
+}
+
+void nullableInitializedUntyped() {
+  late var x = 0 as num?;
+  x.expectStaticType<Exactly<num?>>();
+  // Attempting to promote to `num` should be ok, since `num` is a subtype of
+  // `num?`.
+  if (x is num) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int?` should be ok too.
+  if (x is int?) {
+    x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+void nonNullableUninitializedWithType() {
+  late num x;
+  x = 0;
+  x.expectStaticType<Exactly<num>>();
+  // Attempting to promote to `int?` should do nothing, since `int?` is not a
+  // subtype of `num`.
+  if (x is int?) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int` should be ok, though.
+  if (x is int) {
+    x.expectStaticType<Exactly<int>>();
+  }
+}
+
+void nullableUninitializedWithType() {
+  late num? x;
+  x = 0 as num?; // Cast to prevent promotion
+  x.expectStaticType<Exactly<num?>>();
+  // Attempting to promote to `num` should be ok, since `num` is a subtype of
+  // `num?`.
+  if (x is num) {
+    x.expectStaticType<Exactly<num>>();
+  }
+  // Attempting to promote to `int?` should be ok too.
+  if (x is int?) {
+    x.expectStaticType<Exactly<int?>>();
+  }
+}
+
+void uninitializedUntyped() {
+  late x;
+  x = 0;
+  x.expectStaticType<Exactly<dynamic>>();
+  // Attempting to promote to `int?` should be ok, since `int?` is a subtype of
+  // `dynamic`.
+  if (x is int?) {
+    x.expectStaticType<Exactly<int?>>();
+  }
+  // Attempting to promote to `int` should be ok too.
+  if (x is int) {
+    x.expectStaticType<Exactly<int>>();
+  }
+}
+
+main() {
+  nonNullableInitializedWithType();
+  nullableInitializedWithType();
+  nonNullableInitializedUntyped();
+  nullableInitializedUntyped();
+  nonNullableUninitializedWithType();
+  nullableUninitializedWithType();
+  uninitializedUntyped();
+}
diff --git a/tests/language/nnbd/inference/variable_initialization_promotion_test.dart b/tests/language/nnbd/inference/variable_initialization_promotion_test.dart
new file mode 100644
index 0000000..78d947a
--- /dev/null
+++ b/tests/language/nnbd/inference/variable_initialization_promotion_test.dart
@@ -0,0 +1,340 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import '../../static_type_helper.dart';
+
+/// Test that the type of a local variable is treated as a "type of interest"
+/// for the variable, and that for non-final variables, the initialization (if
+/// any) is treated as an assignment for the purposes of promotion.
+
+/// Verify that the declared type of a local variable is a type of interest.
+void declaredTypeIsATypeOfInterest() {
+  // Check that a variable declared with a non-nullable type can be assignment
+  // demoted back to its declared type after being promoted.
+  {
+    num x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a variable declared with a nullable type can be assignment
+  // promoted to the non-nullable variant of its type, and demoted back to both
+  // the non-nullable variant and the declared type after being promoted.
+  {
+    num? x = (3 as num?);
+    x.expectStaticType<Exactly<num?>>();
+    // This should promote to num, since num and num? should both be types of
+    // interest.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+    // Verify that demotion back to num? works
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+  }
+
+  // Check that a late variable declared with a non-nullable type can be
+  // assignment demoted back to its declared type after being promoted.
+  {
+    late num x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a late variable declared with a nullable type can be assignment
+  // promoted to the non-nullable variant of its type, and demoted back to both
+  // the non-nullable variant and the declared type after being promoted.
+  {
+    late num? x = (3 as num?);
+    x.expectStaticType<Exactly<num?>>();
+    // This should promote to num, since num and num? should both be types of
+    // interest.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+    // Verify that demotion back to num? works
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+  }
+
+  // Final variables are not re-assignable, but can still be subject to
+  // to assignment based promotion and demotion in a few situations.
+
+  // Check that a late final variable declared with a non-nullable type can be
+  // assignment demoted back to its declared type after being promoted.
+  {
+    late final num x;
+    // Make x potentially assigned, and initialize it
+    if (num == num) {
+      x = 3.5;
+    }
+    // Branch will not be taken to avoid a double initialization error
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      x = 3.5; // Demote to num.
+      x.expectStaticType<Exactly<num>>();
+    }
+  }
+
+  // Check that a final variable declared with a non-nullable type can be
+  // assignment promoted to the non-nullable variant of its type.
+  {
+    final num? x;
+    // Promote to num, since num is a type of interest
+    x = 3;
+    // Verify that we have promoted to num
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a late final variable declared with a non-nullable type can be
+  // assignment promoted to the non-nullable variant of its type.
+  {
+    late final num? x;
+    // Promote to num, since num is a type of interest
+    x = 3;
+    // Verify that we have promoted to num
+    x.expectStaticType<Exactly<num>>();
+  }
+}
+
+/// Verify that the inferred type of a local variable is a type of interest.
+void inferredTypeIsATypeOfInterest() {
+  // Check that a variable inferred with a non-nullable type can be
+  // assignment demoted back to its declared type after being promoted.
+  {
+    var x = (3 as num);
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a variable inferred to have a nullable type can be assignment
+  // promoted to the non-nullable variant of its type, and demoted back to both
+  // the non-nullable variant and the declared type after being promoted.
+  {
+    var x = (3 as num?);
+    x.expectStaticType<Exactly<num?>>();
+    // This should promote to num, since num and num? should both be types of
+    // interest.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+    // Verify that demotion back to num? works
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+  }
+
+  // Check that a variable inferred with a non-nullable type can be
+  // assignment demoted back to its declared type after being promoted.
+  {
+    late var x = (3 as num);
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a late variable inferred to have a nullable type can be
+  // assignment promoted to the non-nullable variant of its type, and demoted
+  // back to both the non-nullable variant and the declared type after being
+  // promoted.
+  {
+    late var x = (3 as num?);
+    x.expectStaticType<Exactly<num?>>();
+    // This should promote to num, since num and num? should both be types of
+    // interest.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+    // Promote x to int
+    if (x is int) {
+      x.expectStaticType<Exactly<int>>();
+      // Verify that demotion back to num works
+      x = 3.5;
+      x.expectStaticType<Exactly<num>>();
+    }
+    x.expectStaticType<Exactly<num>>();
+    // Verify that demotion back to num? works
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+  }
+}
+
+/// Verify that the initializer on a mutable variable is treated as if it were
+/// an assignment for the purposes of promotion, and therefore assigning a
+/// non-nullable value can promote to a non-nullable variant of the declared
+/// type.
+void initializersOnVarPromote() {
+  // Check that a variable declared to have a nullable type can be promoted on
+  // initialization to the non-nullable variant of its type, demoted back to the
+  // declared type, and assignment promoted to the non-nullable variant of the
+  // declared type.
+  {
+    num? x = 3;
+    // Verify that we have promoted to num
+    x.expectStaticType<Exactly<num>>();
+    // Verify that num? is a type of interest by demoting to it
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+    // Verify that num is a type of interest by promoting to it.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+  }
+
+  // Check that a late variable declared to have a nullable type can be promoted
+  // on initialization to the non-nullable variant of its type, demoted back to
+  // the declared type, and assignment promoted to the non-nullable variant of
+  // the declared type.
+  {
+    late num? x = 3;
+    // Verify that we have promoted to num
+    x.expectStaticType<Exactly<num>>();
+    // Verify that num? is a type of interest by demoting to it
+    x = null;
+    x.expectStaticType<Exactly<num?>>();
+    // Verify that num is a type of interest by promoting to it.
+    x = 3;
+    x.expectStaticType<Exactly<num>>();
+  }
+}
+
+/// Verify that the initializer on a final variable is not treated as if it were
+/// an assignment for the purposes of promotion, and therefore assigning a
+/// non-nullable value does not promote to a non-nullable variant of the
+/// declared type.
+void initializersOnFinalDoNotPromote() {
+  // Check that a final nullable variable initialized with a non-nullable value
+  // does not get promoted by the initializer to the non-nullable variant of the
+  // type.
+  {
+    final num? x = 3;
+    // Verify that we have not promoted to num
+    x.expectStaticType<Exactly<num?>>();
+  }
+
+  // Check that a late final nullable variable initialized with a non-nullable
+  // value does not get promoted by the initializer to the non-nullable variant
+  // of the type.
+  {
+    late final num? x = 3;
+    // Verify that we have not promoted to num
+    x.expectStaticType<Exactly<num?>>();
+  }
+}
+
+/// Check that when an initializer is a promoted type variable `X & T`, the
+/// inferred type of the variable is `X`, but that the variable is immediately
+/// promoted to `X & T`.
+void typeVariableTypedVariableInferencePromotes<T>(T x0, T x1, bool b) {
+  if (x0 is num) {
+    // Promote `x0` to T & num
+
+    {
+      // Declare y, which should have inferred type T, and be promoted to T &
+      // num
+      var y = x0;
+      // Check that y is assignable to z, and hence that y is still promoted to
+      // T & num
+      num z = y;
+      // Check that y can be demoted to T, but do it conditionally so that T &
+      // num remains a type of interest.
+      if (b) y = x1;
+      // T & num is still a type of interest, and hence this assignment should
+      // promote to T & num.
+      y = x0;
+      // Check that y is assignable to z, and hence that y has been promoted T &
+      // num
+      z = y;
+    }
+
+    {
+      // Declare y, which should have inferred type T, and be promoted to T &
+      // num
+      late var y = x0;
+      // Check that y is assignable to z, and hence that y is still promoted to
+      // T & num
+      num z = y;
+      // Check that y can be demoted to T, but do it conditionally so that T &
+      // num remains a type of interest.
+      if (b) y = x1;
+      // T & num is still a type of interest, and hence this assignment should
+      // promote to T & num.
+      y = x0;
+      // Check that y is assignable to z, and hence that y has been promoted T &
+      // num
+      z = y;
+    }
+
+    {
+      // Declare y, which should have inferred type T, and be promoted to T &
+      // num
+      final y = x0;
+      // Check that y is assignable to z, and hence that y is still promoted to
+      // T & num
+      num z = y;
+    }
+
+    {
+      // Declare y, which should have inferred type T, and be promoted to T &
+      // num
+      late final y = x0;
+      // Check that y is assignable to z, and hence that y is still promoted to
+      // T & num
+      num z = y;
+    }
+  }
+}
+
+void main() {
+  declaredTypeIsATypeOfInterest();
+  inferredTypeIsATypeOfInterest();
+  initializersOnVarPromote();
+  initializersOnFinalDoNotPromote();
+  typeVariableTypedVariableInferencePromotes<num>(3, 3.5, true);
+}
diff --git a/tests/language/nnbd/inference/variables_initialized_to_null_test.dart b/tests/language/nnbd/inference/variables_initialized_to_null_test.dart
new file mode 100644
index 0000000..77ffaa9
--- /dev/null
+++ b/tests/language/nnbd/inference/variables_initialized_to_null_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+/// Test that variables which are initialized to Null are inferred at type
+/// `dynamic`.
+
+var global0 = null;
+var global1 = null as Null;
+
+class Test {
+  static var static0 = null;
+  static var static1 = null as Null;
+
+  var instance0 = null;
+  var instance1 = null as Null;
+}
+
+/// For each category of variable and each style of initialization, we test that
+/// the variable verify that the type is not `Never` by verifying that a value
+/// of type `Object` may be assigned to it, and then check that the type is
+/// `dynamic` (or `Never` which has been eliminated) by verifying that an
+/// arbitrary method may be called on it.
+
+void test() {
+  final Object three = 3;
+  {
+    global0 = three;
+    Expect.isFalse(global0.isEven);
+    global1 = three;
+    Expect.isFalse(global1.isEven);
+  }
+  {
+    Test.static0 = three;
+    Expect.isFalse(Test.static0.isEven);
+    Test.static1 = three;
+    Expect.isFalse(Test.static1.isEven);
+  }
+  {
+    var o = new Test();
+    o.instance0 = three;
+    Expect.isFalse(o.instance0.isEven);
+    o.instance1 = three;
+    Expect.isFalse(o.instance1.isEven);
+  }
+  {
+    var local0 = null;
+    var local1 = null as Null;
+
+    local0 = three;
+    Expect.isFalse(local0.isEven);
+    local1 = three;
+    Expect.isFalse(local1.isEven);
+  }
+}
+
+void main() {
+  test();
+}
diff --git a/tests/language/nnbd/never/never_null_assignability_lib1.dart b/tests/language/nnbd/never/never_null_assignability_lib1.dart
index b006476..ff19ad5 100644
--- a/tests/language/nnbd/never/never_null_assignability_lib1.dart
+++ b/tests/language/nnbd/never/never_null_assignability_lib1.dart
@@ -25,9 +25,9 @@
 }
 
 void takesNever(Never n) {
-  // In weak mode, we may get null.  Throw AssertionError so that this
-  // can be distinguished from a dynamic call failure.
-  if (n != null) throw AssertionError("Not null");
+  // In weak mode, we may get null.  However, we can't observe it (because
+  // evaluating an expression of type `Never` causes an exception to be
+  // thrown).  So do nothing.
 }
 
 void applyTakesNull(void Function(Null) fn, dynamic arg) {
@@ -36,8 +36,9 @@
 }
 
 void applyTakesNever(void Function(Never) fn, dynamic arg) {
-  // Make the cast explicit for clarity.
-  fn(arg as Never);
+  // We can't make the cast explicit, because `arg as Never` has static type
+  // `Never`, which would cause an exception to be thrown.
+  fn(arg);
 }
 
 void applyTakesNullDynamically(void Function(Null) fn, dynamic arg) {
diff --git a/tests/language/nnbd/operator_type_test.dart b/tests/language/nnbd/operator_type_test.dart
index 2885ffd..d9024fc 100644
--- a/tests/language/nnbd/operator_type_test.dart
+++ b/tests/language/nnbd/operator_type_test.dart
@@ -27,97 +27,99 @@
   _ = bq && b;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = b && bq;
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = bq || b;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = b || bq;
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = !bq;
   //   ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = bq ? "a" : "b";
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   if (bq) {}
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   while (bq) {}
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   do {} while (bq);
   //           ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   for (; bq;) {}
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   try {
     throw bq;
     //    ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] Can't throw a value of 'bool?' since it is neither dynamic nor non-nullable.
   } catch (e) {}
 
   assert(bq);
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = [if (bq) 1];
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   _ = [for (; bq;) 1];
   //         ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //          ^
+  // [cfe] A value of type 'bool?' can't be assigned to a variable of type 'bool'.
 
   Iterable<int>? iq = maybeNullable([1]);
   for (var v in iq) {}
   //            ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
 
   _ = [...iq];
+  //      ^
+  // [cfe] An expression whose value can be 'null' must be null-checked before it can be dereferenced.
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
 
   Stream<Object?> foo() async* {
     Stream<int>? sq = maybeNullable(Stream<int>.fromIterable([1]));
     await for (var v in sq) {}
     //                  ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] The type 'Stream<int>?' used in the 'for' loop must implement 'Stream<dynamic>'.
 
     yield* sq;
     //     ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] A value of type 'Stream<int>?' can't be assigned to a variable of type 'Stream<Object?>'.
   }
 
   foo().toList();
@@ -138,97 +140,98 @@
   _ = bq && b;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = b && bq;
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = bq || b;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = b || bq;
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = !bq;
   //   ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = bq ? "a" : "b";
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   if (bq) {}
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   while (bq) {}
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   do {} while (bq);
   //           ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   for (; bq;) {}
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   try {
     throw bq;
     //    ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] Can't throw a value of 'BQ' since it is neither dynamic nor non-nullable.
   } catch (e) {}
 
   assert(bq);
   //     ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = [if (bq) 1];
   //       ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   _ = [for (; bq;) 1];
   //         ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //          ^
+  // [cfe] A value of type 'BQ' can't be assigned to a variable of type 'bool'.
 
   Iterable<int>? iq = maybeNullable([1]);
   for (var v in iq) {}
   //            ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] The type 'Iterable<int>?' used in the 'for' loop must implement 'Iterable<dynamic>'.
 
   _ = [...iq];
   //      ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] An expression whose value can be 'null' must be null-checked before it can be dereferenced.
 
   Stream<Object?> foo<SQ extends Stream<Object?>?>() async* {
     SQ sq = maybeNotNullable<SQ>(Stream<int>.fromIterable([1]));
     await for (var v in sq) {}
     //                  ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] The type 'Stream<Object?>?' used in the 'for' loop must implement 'Stream<dynamic>'.
 
     yield* sq;
     //     ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] A value of type 'SQ' can't be assigned to a variable of type 'Stream<Object?>'.
   }
 
   foo<Stream<Object?>>().toList();
@@ -250,7 +253,7 @@
     return cq;
     //     ^^
     // [analyzer] unspecified
-    // [cfe] unspecified
+    // [cfe] A value of type 'C?' can't be returned from a function with return type 'C'.
   }
 }
 
@@ -265,38 +268,38 @@
   _ = nn ?? 1;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '??' has type 'int' which excludes null.
 
   _ = nn ??= 1;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '??=' has type 'int' which excludes null.
 
   _ = nn?.toRadixString(16);
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '?.' has type 'int' which excludes null.
 
   _ = nn?..toRadixString(16);
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '?..' has type 'int' which excludes null.
 
   _ = nn!;
   //  ^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '!' has type 'int' which excludes null.
 
   List<int> nni = [1];
   _ = [...?nni];
   //       ^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '...?' has type 'List<int>' which excludes null.
 
   _ = nni?[0];
   //  ^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Operand of null-aware operation '?.' has type 'List<int>' which excludes null.
 
   return _;
 }
diff --git a/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_lib.dart b/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_lib.dart
new file mode 100644
index 0000000..3b05578
--- /dev/null
+++ b/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class NullSafe {
+  final int i;
+  final String s;
+  NullSafe({required int i, required this.s}) : i = i;
+}
diff --git a/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_test.dart b/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_test.dart
new file mode 100644
index 0000000..76e3d6f
--- /dev/null
+++ b/tests/language/nnbd/required_named_parameters/legacy_implicit_super_constructor_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+// Requirements=nnbd-weak
+
+/// Test that a legacy class with an implicit superclass constructor is allowed
+/// to call a null safe class's constructor with required named parameters.
+import 'package:expect/expect.dart';
+import 'legacy_implicit_super_constructor_lib.dart';
+
+class Legacy extends NullSafe {}
+
+main() {
+  var legacy = Legacy();
+  Expect.isNull(legacy.i);
+  Expect.isNull(legacy.s);
+}
diff --git a/tests/language/nnbd/resolution/question_question_lub_test.dart b/tests/language/nnbd/resolution/question_question_lub_test.dart
index 73dab4a..beae0f8 100644
--- a/tests/language/nnbd/resolution/question_question_lub_test.dart
+++ b/tests/language/nnbd/resolution/question_question_lub_test.dart
@@ -17,14 +17,20 @@
   (nullableInt ?? nullableInt) + 1;
 //^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
-// [cfe] unspecified
+//                             ^
+// [cfe] Operator '+' cannot be called on 'int?' because it is potentially null.
   (nonNullInt ?? nullableInt) + 1;
-//               ^^^^^^^^^^^
-// [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
 //^^^^^^^^^^^^^^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
-// [cfe] unspecified
+// ^
+// [cfe] Operand of null-aware operation '??' has type 'int' which excludes null.
+//               ^^^^^^^^^^^
+// [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
+//                            ^
+// [cfe] Operator '+' cannot be called on 'int?' because it is potentially null.
   (nonNullInt ?? nonNullInt) + 1;
+// ^
+// [cfe] Operand of null-aware operation '??' has type 'int' which excludes null.
 //               ^^^^^^^^^^
 // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
 }
diff --git a/tests/language/nnbd/static_errors/await_in_late_local_variable_initializer_test.dart b/tests/language/nnbd/static_errors/await_in_late_local_variable_initializer_test.dart
index 6f5c2c0..4f39726 100644
--- a/tests/language/nnbd/static_errors/await_in_late_local_variable_initializer_test.dart
+++ b/tests/language/nnbd/static_errors/await_in_late_local_variable_initializer_test.dart
@@ -10,9 +10,9 @@
 import 'dart:core';
 
 main() async {
-  late a = 0; //# 01: ok
-  late b = await 0; //# 02: compile-time error
-  late c = () async => await 42; //# 03: ok
-  late d = () async { await 42; }; //# 04: ok
-  var e = () async { late e2 = await 42; }; //# 05: compile-time error
+  late final a = 0; //# 01: ok
+  late var b = await 0; //# 02: compile-time error
+  late Function c = () async => await 42; //# 03: ok
+  late var d = () async { await 42; }; //# 04: ok
+  var e = () async { late final e2 = await 42; }; //# 05: compile-time error
 }
diff --git a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
index 4366065..a2a8182 100644
--- a/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
+++ b/tests/language/nnbd/static_errors/super_equals_disallows_non_matching_type_error_test.dart
@@ -24,7 +24,7 @@
 class Derived extends Base {
   void test() {
     String string = 'foo';
-    String? stringQuestion = 'foo';
+    var stringQuestion = 'foo' as String?;
     super == string;
     //       ^^^^^^
     // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
diff --git a/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart b/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
index cfcf46e..976fdce 100644
--- a/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
+++ b/tests/language/nnbd/subtyping/function_type_bounds_weak_test.dart
@@ -13,9 +13,13 @@
   // Should pass with weak checking because when the nullability information on
   // Object and Object? are erased the type bounds are equivalent.
   Expect.isTrue(fnWithNonNullObjectBound is fnTypeWithNullableObjectBound);
+  const test1 = fnWithNonNullObjectBound is fnTypeWithNullableObjectBound;
+  Expect.isTrue(test1);
 
   // void fn<T extends Null>() is void Function<T extends Never>()
   // Should pass with weak checking because because Null becomes equivalent to
   // the bottom type.
   Expect.isTrue(fnWithNullBound is fnTypeWithNeverBound);
+  const test2 = fnWithNullBound is fnTypeWithNeverBound;
+  Expect.isTrue(test2);
 }
diff --git a/tests/language/nnbd/syntax/class_member_declarations_error_test.dart b/tests/language/nnbd/syntax/class_member_declarations_error_test.dart
index d06b113..607e46f 100644
--- a/tests/language/nnbd/syntax/class_member_declarations_error_test.dart
+++ b/tests/language/nnbd/syntax/class_member_declarations_error_test.dart
@@ -8,11 +8,13 @@
   static late x1;
   //     ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //          ^
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   static late x5 = 0;
   //     ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //          ^
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
 
   static final late x9;
   //           ^^^^
@@ -32,15 +34,18 @@
   // [cfe] The modifier 'late' should be before the modifier 'final'.
   //                        ^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
+  // [cfe] A value of type 'Null' can't be assigned to a variable of type 'A'.
 
   covariant late x15;
   //        ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //             ^
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   covariant late x16 = '';
   //        ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  //             ^
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
 
   late covariant var x17;
   //   ^^^^^^^^^
@@ -56,12 +61,14 @@
   // [cfe] The modifier 'covariant' should be before the modifier 'late'.
   //             ^^^
   // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   late covariant x20 = '';
   //   ^^^^^^^^^
   // [analyzer] SYNTACTIC_ERROR.MODIFIER_OUT_OF_ORDER
   // [cfe] The modifier 'covariant' should be before the modifier 'late'.
   //             ^^^
   // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   
   covariant var late x21;
   //            ^^^^
@@ -78,6 +85,7 @@
   // [cfe] Expected ';' after this.
   //               ^^^^
   // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+  // [cfe] Field 'late' should be initialized because its type 'double' doesn't allow null.
   //                    ^^^
   // [analyzer] SYNTACTIC_ERROR.MISSING_CONST_FINAL_VAR_OR_TYPE
   // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
@@ -97,11 +105,11 @@
   late x25;
   //   ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
   late x29 = 0;
   //   ^^^^
   // [analyzer] unspecified
-  // [cfe] unspecified
+  // [cfe] Variables must be declared using the keywords 'const', 'final', 'var' or a type name.
 
   final late x33;
   //    ^^^^
@@ -160,7 +168,7 @@
       required p2 = null,
       //       ^^
       // [analyzer] COMPILE_TIME_ERROR.DEFAULT_VALUE_ON_REQUIRED_PARAMETER
-      // [cfe] unspecified
+      // [cfe] Named parameter 'p2' is required and can't have a default value.
       required covariant p3,
       required covariant int p4,
   });
diff --git a/tests/language/nnbd/syntax/class_member_declarations_test.dart b/tests/language/nnbd/syntax/class_member_declarations_test.dart
index 3aa7d26..a6c8efd 100644
--- a/tests/language/nnbd/syntax/class_member_declarations_test.dart
+++ b/tests/language/nnbd/syntax/class_member_declarations_test.dart
@@ -46,7 +46,7 @@
 
 main() {
   A? a;
-  String? s = '';
+  var s = '' as String?;
   a
     ?..foo().length
     ..x27 = s!.toString().length;
diff --git a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
index b4b357e..131631e 100644
--- a/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
+++ b/tests/language/nnbd/syntax/null_assertion_ambiguous_test.dart
@@ -43,7 +43,7 @@
   Expect.throws(() {
       x3 = a!;
   });
-  Object? x4 = 0;
+  var x4 = 0 as Object?;
   Expect.throws(() {
       x4 = a!;
   });
@@ -62,7 +62,7 @@
   // ignores its argument, and verify that the appropriate exception is still
   // thrown.
   var x6 = 2;
-  int? i = 2;
+  var i = 2 as int?;
   x6 * i!;
   var x7 = new C();
   i = null;
@@ -73,9 +73,9 @@
   // `-x!` means `-(x!)`, not `(-x)!`.  We check the compile-time behavior by
   // checking that the negation is accepted even though x is nullable.  We check
   // the runtime behavior by using an object whose operator- returns null.
-  int? x8 = 2;
+  var x8 = 2 as int?;
   -x8!;
-  C? x9 = new C();
+  var x9 = new C() as C?;
   var x10 = -x9!;
   Expect.isNull(x10);
 
diff --git a/tests/language/nnbd/syntax/nullable_type_ambiguous_test.dart b/tests/language/nnbd/syntax/nullable_type_ambiguous_test.dart
index 753cff9..23565da 100644
--- a/tests/language/nnbd/syntax/nullable_type_ambiguous_test.dart
+++ b/tests/language/nnbd/syntax/nullable_type_ambiguous_test.dart
@@ -37,6 +37,8 @@
   // { a is bool ?? true : 3 } is parsed as a map literal { ((a is bool) ?? true) : 3 }.
   a = true;
   var x5 = {a is bool ?? true : 3};
+  //          ^
+  // [cfe] Operand of null-aware operation '??' has type 'bool' which excludes null.
   //                     ^^^^
   // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
   Expect.type<Map<dynamic, dynamic>>(x5);
diff --git a/tests/language/null_aware/access_runtime_2_test.dart b/tests/language/null_aware/access_runtime_2_test.dart
index b67de99..a1ade72 100644
--- a/tests/language/null_aware/access_runtime_2_test.dart
+++ b/tests/language/null_aware/access_runtime_2_test.dart
@@ -28,7 +28,7 @@
 
   // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
 
-  C? c = new C(1);
+  var c = new C(1) as C?;
   Expect.equals(1, c?.v);
 
   // C?.id is equivalent to C.id.
diff --git a/tests/language/null_aware/access_runtime_5_test.dart b/tests/language/null_aware/access_runtime_5_test.dart
index 5984802..6db60ce3 100644
--- a/tests/language/null_aware/access_runtime_5_test.dart
+++ b/tests/language/null_aware/access_runtime_5_test.dart
@@ -35,7 +35,7 @@
 
 
   // The static type of e1?.d is the static type of e1.id.
-  C? c = new C(1);
+  var c = new C(1) as C?;
   { int? i = c?.v; Expect.equals(1, i); }
 
 
diff --git a/tests/language/null_aware/access_test.dart b/tests/language/null_aware/access_test.dart
index 4ee967e..b2d1bc0 100644
--- a/tests/language/null_aware/access_test.dart
+++ b/tests/language/null_aware/access_test.dart
@@ -26,6 +26,8 @@
   // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
   Expect.equals(null, nullC()?.v);
   Expect.equals(1, new C(1)?.v);
+  //                   ^
+  // [cfe] Operand of null-aware operation '?.' has type 'C' which excludes null.
   //                       ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
 
@@ -35,6 +37,8 @@
 
   // The static type of e1?.d is the static type of e1.id.
   { int? i = new C(1)?.v; Expect.equals(1, i); }
+  //             ^
+  // [cfe] Operand of null-aware operation '?.' has type 'C' which excludes null.
   //                 ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   { String? s = new C(null)?.v; Expect.equals(null, s); }
@@ -42,6 +46,8 @@
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   //                ^
   // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  //                ^
+  // [cfe] Operand of null-aware operation '?.' has type 'C' which excludes null.
   //                       ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   { C.staticInt = 1; int? i = C?.staticInt; Expect.equals(1, i); }
@@ -64,8 +70,8 @@
   //                           ^^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
   // [cfe] The getter 'bad' isn't defined for the class 'C'.
-  { B? b = new C(1); Expect.equals(1, b?.v); }
-  //                                     ^
+  { var b = new C(1) as B?; Expect.equals(1, b?.v); }
+  //                                            ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
   // [cfe] The getter 'v' isn't defined for the class 'B'.
 
diff --git a/tests/language/null_aware/assignment_runtime_11_test.dart b/tests/language/null_aware/assignment_runtime_11_test.dart
index 05b84a6..ca60103 100644
--- a/tests/language/null_aware/assignment_runtime_11_test.dart
+++ b/tests/language/null_aware/assignment_runtime_11_test.dart
@@ -77,7 +77,7 @@
 
 
   // The static type of e1?.v op= e2 is the static type of e1.v op e2.
-  { D? d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = (d?.v += 1); Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/assignment_runtime_2_test.dart b/tests/language/null_aware/assignment_runtime_2_test.dart
index 825bfc6..bc0cdb6 100644
--- a/tests/language/null_aware/assignment_runtime_2_test.dart
+++ b/tests/language/null_aware/assignment_runtime_2_test.dart
@@ -50,7 +50,7 @@
 
   // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
 
-  { C? c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
 
   // C?.v = e2 is equivalent to C.v = e2.
 
diff --git a/tests/language/null_aware/assignment_runtime_5_test.dart b/tests/language/null_aware/assignment_runtime_5_test.dart
index abcf60a..9507557 100644
--- a/tests/language/null_aware/assignment_runtime_5_test.dart
+++ b/tests/language/null_aware/assignment_runtime_5_test.dart
@@ -57,7 +57,7 @@
 
 
   // The static type of e1?.v = e2 is the static type of e2.
-  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+  { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
 
 
 
diff --git a/tests/language/null_aware/assignment_runtime_9_test.dart b/tests/language/null_aware/assignment_runtime_9_test.dart
index 3c2d6c0..0a16c52 100644
--- a/tests/language/null_aware/assignment_runtime_9_test.dart
+++ b/tests/language/null_aware/assignment_runtime_9_test.dart
@@ -71,7 +71,7 @@
 
   // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
 
-  { C? c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
 
   // C?.v op= e2 is equivalent to C.v op= e2.
 
diff --git a/tests/language/null_aware/assignment_test.dart b/tests/language/null_aware/assignment_test.dart
index 79f566c..d7bf2f4 100644
--- a/tests/language/null_aware/assignment_test.dart
+++ b/tests/language/null_aware/assignment_test.dart
@@ -49,6 +49,8 @@
   // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
   Expect.equals(null, nullC()?.v = bad());
   { C c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c.v); }
+  //                                 ^
+  // [cfe] Operand of null-aware operation '?.' has type 'C' which excludes null.
   //                                  ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
 
@@ -57,11 +59,10 @@
   { h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); }
 
   // The static type of e1?.v = e2 is the static type of e2.
-  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
-  { D? d = new D(new E()); E e = new G(); F? f = (d?.v = e); }
-  //                                              ^^^^^^^^
+  { var d = new D(new E()) as D?; G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+  { var d = new D(new E()) as D?; E e = new G(); F? f = (d?.v = e); }
+  //                                                     ^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                                              ^
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { D.staticE = new E(); G g = new G(); F? f = (D?.staticE = g); Expect.identical(f, g); }
   { h.D.staticE = new h.E(); h.G g = new h.G(); h.F? f = (h.D?.staticE = g); Expect.identical(f, g); }
@@ -83,6 +84,8 @@
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_SETTER
   // [cfe] The setter 'bad' isn't defined for the class 'C'.
   { B b = new C(1); Expect.equals(2, b?.v = 2); }
+  //                                 ^
+  // [cfe] Operand of null-aware operation '?.' has type 'B' which excludes null.
   //                                  ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   //                                    ^
@@ -92,6 +95,8 @@
   // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
   Expect.equals(null, nullC()?.v += bad());
   { C c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c.v); }
+  //                                 ^
+  // [cfe] Operand of null-aware operation '?.' has type 'C' which excludes null.
   //                                  ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
 
@@ -100,6 +105,8 @@
 
   // The static type of e1?.v op= e2 is the static type of e1.v op e2.
   { D d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d.v, f); }
+  //                              ^
+  // [cfe] Operand of null-aware operation '?.' has type 'D' which excludes null.
   //                               ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   { D.staticE = new E(); F? f = (D?.staticE += 1); Expect.identical(D.staticE, f); }
@@ -113,6 +120,8 @@
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_SETTER
   // [cfe] The setter 'bad' isn't defined for the class 'C'.
   { B b = new C(1); b?.v += 2; }
+  //                ^
+  // [cfe] Operand of null-aware operation '?.' has type 'B' which excludes null.
   //                 ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   //                   ^
@@ -122,6 +131,8 @@
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_SETTER
   // [cfe] The setter 'v' isn't defined for the class 'B'.
   { D d = new D(new E()); F? f = (d?.v += nullC()); }
+  //                              ^
+  // [cfe] Operand of null-aware operation '?.' has type 'D' which excludes null.
   //                               ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   //                                      ^^^^^^^
@@ -130,8 +141,9 @@
   { D d = new D(new E()); H? h = (d?.v += 1); }
   //                              ^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                              ^
   // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
+  //                              ^
+  // [cfe] Operand of null-aware operation '?.' has type 'D' which excludes null.
   //                               ^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
   { D.staticE = new E(); F? f = (D?.staticE += nullC()); }
diff --git a/tests/language/null_aware/increment_decrement_runtime_12_test.dart b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
index 03986fb..4e9c166 100644
--- a/tests/language/null_aware/increment_decrement_runtime_12_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
@@ -68,7 +68,7 @@
 
 
   // The static type of e1?.v-- is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_16_test.dart b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
index 1016d22..cfd1b8b 100644
--- a/tests/language/null_aware/increment_decrement_runtime_16_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
@@ -77,7 +77,7 @@
 
   // ++e1?.v is equivalent to e1?.v += 1.
 
-  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
 
   // ++C?.v is equivalent to C?.v += 1.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_19_test.dart b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
index bb8c565..0677ac7 100644
--- a/tests/language/null_aware/increment_decrement_runtime_19_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
@@ -84,7 +84,7 @@
 
 
   // The static type of ++e1?.v is the same as the static type of e1.v + 1.
-  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_23_test.dart b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
index b2dc6b5..2927351 100644
--- a/tests/language/null_aware/increment_decrement_runtime_23_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
@@ -93,7 +93,7 @@
 
   // --e1?.v is equivalent to e1?.v -= 1.
 
-  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
 
   // --C?.v is equivalent to C?.v -= 1.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_26_test.dart b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
index 4201d15..903c33a 100644
--- a/tests/language/null_aware/increment_decrement_runtime_26_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
@@ -100,7 +100,7 @@
 
 
   // The static type of --e1?.v is the same as the static type of e1.v - 1.
-  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_2_test.dart b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
index 67bca4a..3a29ccc 100644
--- a/tests/language/null_aware/increment_decrement_runtime_2_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
@@ -45,7 +45,7 @@
 
   // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
 
-  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
 
   // C?.v++ is equivalent to C.v++.
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_5_test.dart b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
index 8ca6c72..0cc85fb 100644
--- a/tests/language/null_aware/increment_decrement_runtime_5_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
@@ -52,7 +52,7 @@
 
 
   // The static type of e1?.v++ is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
 
 
 
diff --git a/tests/language/null_aware/increment_decrement_runtime_9_test.dart b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
index cd3bd72..7b42679 100644
--- a/tests/language/null_aware/increment_decrement_runtime_9_test.dart
+++ b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
@@ -61,7 +61,7 @@
 
   // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
 
-  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
 
   // C?.v-- is equivalent to C.v--.
 
diff --git a/tests/language/null_aware/increment_decrement_test.dart b/tests/language/null_aware/increment_decrement_test.dart
index 0b620fc..7e80690 100644
--- a/tests/language/null_aware/increment_decrement_test.dart
+++ b/tests/language/null_aware/increment_decrement_test.dart
@@ -42,16 +42,16 @@
 
   // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
   Expect.equals(null, nullC()?.v++);
-  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
 
   // C?.v++ is equivalent to C.v++.
   { C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); }
 
   // The static type of e1?.v++ is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
-  { G g = new G(); D? d = new D(g); F? f = d?.v++; Expect.identical(f, g); }
-  //                                       ^^^^^^
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v++; Expect.identical(e1, e2); }
+  { G g = new G(); var d = new D(g) as D?; F? f = d?.v++; Expect.identical(f, g); }
+  //                                              ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE++; Expect.identical(e1, e2); }
@@ -69,16 +69,16 @@
 
   // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
   Expect.equals(null, nullC()?.v--);
-  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
 
   // C?.v-- is equivalent to C.v--.
   { C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); }
 
   // The static type of e1?.v-- is the same as the static type of e1.v.
-  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
-  { G g = new G(); D? d = new D(g); F? f = d?.v--; Expect.identical(f, g); }
-  //                                       ^^^^^^
+  { E e1 = new E(); var d = new D(e1) as D?; E? e2 = d?.v--; Expect.identical(e1, e2); }
+  { G g = new G(); var d = new D(g) as D?; F? f = d?.v--; Expect.identical(f, g); }
+  //                                              ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
   // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
   { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE--; Expect.identical(e1, e2); }
@@ -96,18 +96,18 @@
 
   // ++e1?.v is equivalent to e1?.v += 1.
   Expect.equals(null, ++nullC()?.v);
-  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
 
   // ++C?.v is equivalent to C?.v += 1.
   { C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); }
 
   // The static type of ++e1?.v is the same as the static type of e1.v + 1.
-  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
-  { D? d = new D(new E()); H? h = ++d?.v; Expect.identical(d!.v, h); }
-  //                              ^^^^^^
+  { var d = new D(new E()) as D?; F? f = ++d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; H? h = ++d?.v; Expect.identical(d!.v, h); }
+  //                                     ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                                ^
+  //                                       ^
   // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
   { D.staticE = new E(); F? f = ++D?.staticE; Expect.identical(D.staticE, f); }
   { h.D.staticE = new h.E(); h.F? f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); }
@@ -124,18 +124,18 @@
 
   // --e1?.v is equivalent to e1?.v -= 1.
   Expect.equals(null, --nullC()?.v);
-  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+  { var c = new C(1) as C?; Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
 
   // --C?.v is equivalent to C?.v -= 1.
   { C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); }
   { h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); }
 
   // The static type of --e1?.v is the same as the static type of e1.v - 1.
-  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
-  { D? d = new D(new E()); H? h = --d?.v; Expect.identical(d!.v, h); }
-  //                              ^^^^^^
+  { var d = new D(new E()) as D?; F? f = --d?.v; Expect.identical(d!.v, f); }
+  { var d = new D(new E()) as D?; H? h = --d?.v; Expect.identical(d!.v, h); }
+  //                                     ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //                                ^
+  //                                       ^
   // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
   { D.staticE = new E(); F? f = --D?.staticE; Expect.identical(D.staticE, f); }
   { h.D.staticE = new h.E(); h.F? f = --h.D?.staticE; Expect.identical(h.D.staticE, f); }
diff --git a/tests/language/null_aware/invocation_runtime_2_test.dart b/tests/language/null_aware/invocation_runtime_2_test.dart
index 70a36d1..8c11b27 100644
--- a/tests/language/null_aware/invocation_runtime_2_test.dart
+++ b/tests/language/null_aware/invocation_runtime_2_test.dart
@@ -32,7 +32,7 @@
 
   // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
 
-  C? c = C();
+  var c = C() as C?;
   Expect.equals(1, c?.f(() => 1));
 
   // C?.m(...) is equivalent to C.m(...).
diff --git a/tests/language/null_aware/invocation_runtime_6_test.dart b/tests/language/null_aware/invocation_runtime_6_test.dart
index 23559d8..bbabd59 100644
--- a/tests/language/null_aware/invocation_runtime_6_test.dart
+++ b/tests/language/null_aware/invocation_runtime_6_test.dart
@@ -41,7 +41,7 @@
   // The static type of o?.m(...) is the same as the static type of
   // o.m(...).
 
-  C? c = new C();
+  var c = new C() as C?;
   { int? i = c?.g(() => 1); Expect.equals(1, i); }
 
 
diff --git a/tests/language/null_aware/invocation_test.dart b/tests/language/null_aware/invocation_test.dart
index a1515fa..b1f38e6 100644
--- a/tests/language/null_aware/invocation_test.dart
+++ b/tests/language/null_aware/invocation_test.dart
@@ -23,7 +23,7 @@
 C? nullC() => null;
 
 main() {
-  C? c = C();
+  var c = C() as C?;
 
   // Make sure the "none" test fails if method invocation using "?." is not
   // implemented.  This makes status files easier to maintain.
@@ -66,12 +66,12 @@
   // Let T be the static type of o and let y be a fresh variable of type T.
   // Exactly the same static warnings that would be caused by y.m(...) are also
   // generated in the case of o?.m(...).
-  { B? b = new C(); Expect.equals(1, b?.f(() => 1)); }
-  //                                    ^
+  { var b = new C() as B?; Expect.equals(1, b?.f(() => 1)); }
+  //                                           ^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_METHOD
   // [cfe] The method 'f' isn't defined for the class 'B'.
-  { int? i = 1; Expect.equals(null, nullC()?.f(i)); }
-  //                                           ^
+  { var i = 1 as int?; Expect.equals(null, nullC()?.f(i)); }
+  //                                                  ^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
   // [cfe] The argument type 'int?' can't be assigned to the parameter type 'dynamic Function()?'.
 
diff --git a/tests/language/null_aware/null_shortening_test.dart b/tests/language/null_aware/null_shortening_test.dart
new file mode 100644
index 0000000..625bc08
--- /dev/null
+++ b/tests/language/null_aware/null_shortening_test.dart
@@ -0,0 +1,172 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check null-shortening semantics of `?.` and `?[]`
+
+import "package:expect/expect.dart";
+
+import "../static_type_helper.dart";
+
+class C1 {
+  C1 get c => this;
+  C1? get cq => this;
+  C1? get cn => null;
+  C1 get getterThrows => unreachable;
+  void method(Object? v) {}
+  void methodThrows() => unreachable;
+  set setter(Object? v) {}
+  set setterThrows(Object? v) {
+    unreachable;
+  }
+
+  C1 operator [](Object? _) => this;
+  operator []=(Object? _, Object? __) {}
+  int n = 0;
+}
+
+extension<T> on T {
+  T get id => this;
+}
+
+extension on C1 {
+  C1 get extThrows => unreachable;
+
+  // ignore: unused_element
+  C1 operator +(Object? other) => unreachable;
+  // ignore: unused_element
+  C1 operator ~() => unreachable;
+}
+
+extension on C1? {
+  C1? operator +(Object? other) => this;
+  C1? operator ~() => this;
+}
+
+class C2 {
+  C2? operator [](int n) => n.isEven ? this : null;
+  operator []=(int n, C2? value) {}
+}
+
+main() {
+  C1 c1 = C1();
+  var c1q = c1 as C1?;
+  C1? c1n = null;
+
+  C2 c2 = C2();
+  var c2q = c2 as C2?;
+
+  // All selector operations short on null.
+  // .foo
+  // ?.foo
+  // .foo=
+  // ?.foo=
+  // .foo()
+  // ?.foo()
+  // []
+  // ?[]
+  // []=
+  // ?[]=
+  // !
+  // !.foo
+  // ![]
+
+  c1n?.getterThrows;
+  c1n?.setterThrows = 0;
+  c1n?.setter = unreachable;
+  c1n?.method(unreachable);
+  c1n?.methodThrows();
+  c1n?[unreachable];
+  c1n?[unreachable] = 0;
+  c1n?[0] = unreachable;
+  c1n?.extThrows;
+
+  c1n?.c.getterThrows;
+  c1n?.c.setterThrows = 0;
+  c1n?.c.setter = unreachable;
+  c1n?.c.method(unreachable);
+  c1n?.c.methodThrows();
+  c1n?.c[unreachable];
+  c1n?.c[unreachable] = 0;
+  c1n?.c[0] = unreachable;
+  c1n?.c.extThrows;
+
+  c1n?.cn!;
+  c1n?.cn!.getterThrows;
+  c1n?.cn!.setterThrows = 0;
+  c1n?.cn!.setter = unreachable;
+  c1n?.cn!.method(unreachable);
+  c1n?.cn!.methodThrows();
+  c1n?.cn![unreachable];
+  c1n?.cn![unreachable] = 0;
+  c1n?.cn![0] = unreachable;
+  c1n?.cn!.extThrows;
+
+  // Binary and prefix operators in general
+  // do not participate in null shortening.
+  var i = 0;
+  c1q?.c + (i++);
+  Expect.equals(i, 1);
+  ~c1q?.c; // Would throw if hitting extension on C1
+
+  // ++ and -- participates in null shortening!
+  c1q?.n++;
+  ++c1q?.n;
+  c1n?.n++;
+  ++c1n?.n;
+
+  // Cascades do not participate in null shortening.
+
+  c1q?.c..id.expectStaticType<Exactly<C1?>>();
+  c1q?.c?..id.expectStaticType<Exactly<C1>>();
+
+  // Null shortening works the same below cascades
+  c1..cn?.getterThrows;
+  c1..cn?.setterThrows = 0;
+  c1..cn?.setter = unreachable;
+  c1..cn?.method(unreachable);
+  c1..cn?.methodThrows();
+  c1..cn?[unreachable];
+  c1..cn?[unreachable] = 0;
+  c1..cn?[0] = unreachable;
+  c1..cn?.extThrows;
+
+  c1..cn?.c.getterThrows;
+  c1..cn?.c.setterThrows = 0;
+  c1..cn?.c.setter = unreachable;
+  c1..cn?.c.method(unreachable);
+  c1..cn?.c.methodThrows();
+  c1..cn?.c[unreachable];
+  c1..cn?.c[unreachable] = 0;
+  c1..cn?.c[0] = unreachable;
+  c1..cn?.c.extThrows;
+
+  c1..cn?.cn!;
+  c1..cn?.cn!.getterThrows;
+  c1..cn?.cn!.setterThrows = 0;
+  c1..cn?.cn!.setter = unreachable;
+  c1..cn?.cn!.method(unreachable);
+  c1..cn?.cn!.methodThrows();
+  c1..cn?.cn![unreachable];
+  c1..cn?.cn![unreachable] = 0;
+  c1..cn?.cn![0] = unreachable;
+  c1..cn?.cn!.extThrows;
+
+  // The static types depend on whether the check is part of the
+  // null shortening.
+  c1q?.c.expectStaticType<Exactly<C1>>();
+  (c1q?.c).expectStaticType<Exactly<C1?>>();
+  c1q?.cq!.expectStaticType<Exactly<C1>>();
+  (c1q?.cq!).expectStaticType<Exactly<C1?>>();
+  (c1q?.cq)!.expectStaticType<Exactly<C1>>();
+  c1q?.cq!.c.expectStaticType<Exactly<C1>>();
+  (c1q?.cq!.c).expectStaticType<Exactly<C1?>>();
+  c1q?[1].expectStaticType<Exactly<C1>>();
+  (c1q?[1]).expectStaticType<Exactly<C1?>>();
+
+  c2q?[1].expectStaticType<Exactly<C2?>>();
+  (c2q?[1]).expectStaticType<Exactly<C2?>>();
+}
+
+// TODO(lrn): Change Expect.fail to return Never.
+Never get unreachable => Expect.fail("Unreachable") as Never;
diff --git a/tests/language/null_aware/opt_test.dart b/tests/language/null_aware/opt_test.dart
index c5bb8a7..57f3848 100644
--- a/tests/language/null_aware/opt_test.dart
+++ b/tests/language/null_aware/opt_test.dart
@@ -23,17 +23,17 @@
 
 test() {
   var c;
-  C? d = new C(5);
+  var d = new C(5) as C?;
   Expect.equals(null, c?.m(bomb()));
   Expect.equals(null, getNull()?.anything(bomb()));
   Expect.equals(1, d?.m(1));
 
-  C? c2 = new C(1);
+  var c2 = new C(1) as C?;
   Expect.equals(1, c2?.f);
   Expect.equals(null, c?.v);
   Expect.equals(10, c ?? 10);
   Expect.equals(d, d ?? bomb());
-  List<List<int>>? list = [[3]];
+  var list = [[3]] as List<List<int>>?;
   Expect.equals(
       3,
       list?.expand((i) => i).toList()[0]);
@@ -58,7 +58,7 @@
   e?.f++;
   Expect.equals(201, e.f);
 
-  int? five = 5;
+  var five = 5 as int?;
   var x = five ?? bomb();
 }
 
diff --git a/tests/language/null_aware/prefix_not_shortening_test.dart b/tests/language/null_aware/prefix_not_shortening_test.dart
new file mode 100644
index 0000000..20ef1af
--- /dev/null
+++ b/tests/language/null_aware/prefix_not_shortening_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class C {
+  C e() => this;
+  C operator -() => this;
+  C operator ~() => this;
+}
+
+void main() {
+  final C? c = new C();
+  /**/ -c?.e();
+  //    ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+  //   ^
+  // [cfe] Operator 'unary-' cannot be called on 'C?' because it is potentially null.
+
+  /**/ ~c?.e();
+  //    ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
+  //   ^
+  // [cfe] Operator '~' cannot be called on 'C?' because it is potentially null.
+}
diff --git a/tests/language/operator/invalid_operators_test.dart b/tests/language/operator/invalid_operators_test.dart
index 52eae80..badafb5 100644
--- a/tests/language/operator/invalid_operators_test.dart
+++ b/tests/language/operator/invalid_operators_test.dart
@@ -572,13 +572,15 @@
   operator ==<T>(a) => true;
   //       ^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_OVERRIDE
-  // [cfe] Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
+  // [cfe] Can't infer a return type for '==' as the overridden members don't have a combined signature.
   //       ^
-  // [cfe] The return type of the method 'Operators7.==' is 'dynamic', which does not match the return type, 'bool', of the overridden method, 'Object.=='.
+  // [cfe] Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
   //         ^^^
   // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETERS_ON_OPERATOR
   //          ^
   // [cfe] Types parameters aren't allowed when defining an operator.
+  //             ^
+  // [cfe] Can't infer a type for 'a' as the overridden members don't have a combined signature.
   operator ><T>(a) => true;
   //        ^^^
   // [analyzer] SYNTACTIC_ERROR.TYPE_PARAMETERS_ON_OPERATOR
@@ -675,7 +677,7 @@
   /*space*/ int operator []=(a, b) => 1;
   //        ^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_OPERATOR
-  // [cfe] unspecified
+  // [cfe] The return type of the operator []= must be 'void'.
 }
 
 main() {}
diff --git a/tests/language/operator/number_operator_context_test.dart b/tests/language/operator/number_operator_context_test.dart
index 898f139..3c587d8 100644
--- a/tests/language/operator/number_operator_context_test.dart
+++ b/tests/language/operator/number_operator_context_test.dart
@@ -4,7 +4,7 @@
 
 // Test the new context type rules for number operators,
 // as modified by Null Safety
-import "static_type_helper.dart";
+import "../static_type_helper.dart";
 
 // The context rules for `e` of the form:
 // For e1 + e2, e1 - e2, e1 * e2, e1 % e2 or e1.remainder(e2),,
diff --git a/tests/language/operator/number_operator_error_test.dart b/tests/language/operator/number_operator_error_test.dart
index 90e4cf0..aaa32c3 100644
--- a/tests/language/operator/number_operator_error_test.dart
+++ b/tests/language/operator/number_operator_error_test.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // Test the new context type rules for number operators,
-import "static_type_helper.dart";
+import "../static_type_helper.dart";
 
 // as modified by Null Safety
 void main() {
@@ -34,128 +34,128 @@
   // [cfe] A value of type 'String' can't be assigned to a variable of type 'num'.
 
   i += d;
+  //^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'int'.
   //   ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'int'.
 
   i += n;
+  //^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
   //   ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
 
   i += never;
+  //^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
   //   ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
 
   i += dyn; // type of `i + dyn` is `num`, not assignable to `int`.
+  //^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
   //   ^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  //^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'int'.
 
   ti += i; // Type of expression is `int`, not `I`.
+  // ^
+  // [cfe] A value of type 'int' can't be assigned to a variable of type 'I'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'int' can't be assigned to a variable of type 'I'.
 
   ti += d; // Type of expression is `num`, not `I`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'I'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'I'.
 
   ti += n; // Type of expression is `num`, not `I`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
 
   ti += never; // Type of expression is `num`, not `I`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
   //    ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
 
   ti += dyn; // type of `i + dyn` is `num`, not assignable to `int`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
   //    ^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'I'.
 
   td += i; // Type of expression is `double`, not `D`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
 
   td += d; // Type of expression is `double`, not `D`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
 
   td += n; // Type of expression is `double`, not `D`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
 
   td += dyn; // Type of expression is `double`, not `D`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
   //    ^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
 
   td += never; // Type of expression is `double`, not `D`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
   //    ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
 
   tn += i; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   tn += d; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'double' can't be assigned to a variable of type 'N'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   tn += n; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   tn += dyn; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   tn += never; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   O oi1 = to; // New variable to avoid demoting `oi`.
   if (oi1 is int) {
     // Promote oi1 to O&int
     oi1 + d; // Valid
     oi1 += d;
+    //  ^
+    // [cfe] A value of type 'double' can't be assigned to a variable of type 'O'.
     //     ^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'double' can't be assigned to a variable of type 'O'.
   }
 
   O oi2 = to;
@@ -163,10 +163,10 @@
     // Promote oi2 to O&int.
     oi2 + n; // Valid
     oi2 += n;
+    //  ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
     //     ^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
   }
 
   O oi3 = to;
@@ -174,10 +174,10 @@
     // Promote oi3 to O&int.
     oi3 + dyn; // Valid
     oi3 += dyn;
+    //  ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
     //     ^^^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
   }
 
   O oi4 = to;
@@ -185,23 +185,23 @@
     // Promote oi4 to O&int.
     oi4 + never; // Valid.
     oi4 += never;
+    //  ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
     //     ^^^^^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
   }
 
   context<D>(i + td); // Type of expression is `double`, not `D`.
   //         ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
   //           ^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
+  // [cfe] The argument type 'double' can't be assigned to the parameter type 'D'.
 
   context<D>(n + td); // Type of expression is `double`, not `D`.
   //         ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
   //           ^
-  // [cfe] A value of type 'double' can't be assigned to a variable of type 'D'.
+  // [cfe] The argument type 'double' can't be assigned to the parameter type 'D'.
 
   context<D>(1.0 + td); // Type of expression is `double`, not `D`.
   //         ^^^^^^^^
@@ -210,35 +210,35 @@
   // [cfe] The argument type 'double' can't be assigned to the parameter type 'D'.
 
   tn += n; // Type of expression is `num`, not `N`.
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   tn += dyn;
+  // ^
+  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
   //    ^^^
   // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-  // ^^
-  // [cfe] A value of type 'num' can't be assigned to a variable of type 'N'.
 
   O on1 = to;
   if (on1 is num) {
     // Promote on1 to O&num.
     on1 += n; // Type of expression is `num`, not `N` or `O`.
+    //  ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
     //     ^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
   }
 
   O on2 = to;
   if (on2 is num) {
     // Promote on2 to O&num.
     on2 += dyn; // Type of expression is `num`, not `N` or `O`.
+    //  ^
+    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
     //     ^^^
     // [analyzer] COMPILE_TIME_ERROR.INVALID_ASSIGNMENT
-    //  ^^
-    // [cfe] A value of type 'num' can't be assigned to a variable of type 'O'.
   }
 }
 
diff --git a/tests/language/operator/number_operator_typing_test.dart b/tests/language/operator/number_operator_typing_test.dart
index 62e452a..c650e61 100644
--- a/tests/language/operator/number_operator_typing_test.dart
+++ b/tests/language/operator/number_operator_typing_test.dart
@@ -4,7 +4,7 @@
 
 // Test the rules for static types of number operators,
 // as modified by Null Safety
-import "static_type_helper.dart";
+import "../static_type_helper.dart";
 
 // ignore_for_file: receiver_of_type_never
 
diff --git a/tests/language/operator/static_type_helper.dart b/tests/language/operator/static_type_helper.dart
deleted file mode 100644
index 50cdace..0000000
--- a/tests/language/operator/static_type_helper.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Ensures a context type of [T] for the operand.
-void context<T>(T x) {}
-
-/// Captures the context type of the call and returns the same type.
-///
-/// Can be used to check the context type as:
-/// ```dart
-/// int x = contextType(1 /* valid value */)..expectStaticType<Exactly<int>>;
-/// ```
-T contextType<T>(Object result) => result as T;
-
-extension StaticType<T> on T {
-  /// Check the static type.
-  ///
-  /// Use as follows (assuming `e` has static type `num`):
-  /// ```dart
-  ///   e.expectStaticType<Exactly<num>>()  // No context type.
-  ///   e.expectStaticType<SubtypeOf<Object>>()  // No context type.
-  ///   e.expectStaticType<SupertypeOf<int>>()  // No context type.
-  /// ```
-  /// or
-  /// ```dart
-  ///   e..expectStaticType<Exactly<num>>()  // Preserve context type.
-  ///   e..expectStaticType<SubtypeOf<Object>>()  // Preserve context type.
-  ///   e..expectStaticType<SupertypeOf<int>>()  // Preserve context type.
-  /// ```
-  /// This will be a *compile-time error* if the static type is not
-  /// as required by the constraints type (the one passed to [Exactly],
-  /// [SubtypeOf] or [SupertypeOf].)
-  T expectStaticType<R extends Exactly<T>>() {
-    return this;
-  }
-}
-
-/// Use with [StaticType.expectStaticType] to expect precisely the type [T].
-///
-/// Example use:
-/// ```dart
-/// "abc".expectStaticType<Exactly<String>>();
-/// ```
-typedef Exactly<T> = T Function(T);
-
-/// Use with [StaticType.expectStaticType] to expect a subtype of [T].
-///
-/// Example use:
-/// ```dart
-/// num x = 1;
-/// x.expectStaticType<SubtypeOf<Object>>();
-/// ```
-typedef SubtypeOf<T> = Never Function(T);
-
-/// Use with [StaticType.expectStaticType] to expect a supertype of [T].
-///
-/// Example use:
-/// ```dart
-/// num x = 1;
-/// x.expectStaticType<SupertypeOf<int>>();
-/// ```
-typedef SupertypeOf<T> = T Function(Object?);
-
-/// Checks that an expression is assignable to [T1], [T2] and [Object].
-///
-/// This ensures that the type of the expression is a non-`dynamic`
-/// type assignable to both [T1] and [T2], and if those are unrelated,
-/// it must be an intersection type.
-void checkIntersectionType<T1, T2>(T1 v1, T2 v2, Object v3) {}
diff --git a/tests/language/parameter/named_aggregated_test.dart b/tests/language/parameter/named_aggregated_test.dart
index 61de489f..87e6140 100644
--- a/tests/language/parameter/named_aggregated_test.dart
+++ b/tests/language/parameter/named_aggregated_test.dart
@@ -27,8 +27,6 @@
   // Expect compile-time error as no default values
   // are allowed in closure type.
   void InstallCallback(void cb({String? msg : null})?) {
-  //                            ^^^^^^^^^^^^^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
   //                                        ^
   // [analyzer] SYNTACTIC_ERROR.DEFAULT_VALUE_IN_FUNCTION_TYPE
   // [cfe] Can't have a default value in a function type.
diff --git a/tests/language/parameter/named_with_conversions_test.dart b/tests/language/parameter/named_with_conversions_test.dart
index 58e85f5..8818036 100644
--- a/tests/language/parameter/named_with_conversions_test.dart
+++ b/tests/language/parameter/named_with_conversions_test.dart
@@ -29,9 +29,9 @@
 }
 
 class HasMethod {
-  int calls;
+  int calls = 0;
 
-  HasMethod() : calls = 0 {}
+  HasMethod();
 
   foo(tag, [a = 10, b = 20]) {
     calls += 1;
@@ -46,7 +46,7 @@
 
 class HasField {
   int calls = 0;
-  var foo, foo2;
+  late final dynamic foo, foo2;
 
   HasField() {
     foo = makeFoo(this);
@@ -71,16 +71,6 @@
 }
 
 class NamedParametersWithConversionsTest {
-  static checkException(thunk) {
-    bool threw = false;
-    try {
-      thunk();
-    } catch (e) {
-      threw = true;
-    }
-    Expect.isTrue(threw);
-  }
-
   static testMethodCallSyntax(a) {
     a.foo('');
     a.foo('a', 111);
@@ -92,10 +82,12 @@
 
     Expect.equals(7, a.calls);
 
-    checkException(() => a.foo()); //                  Too few arguments.
-    checkException(() => a.foo('abc', 1, 2, 3)); //    Too many arguments.
-    checkException(() => a.foo2('c', c: 1)); //        Bad name.
-    checkException(() => a.foo2('c', a: 111, c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(() => a.foo()); // Too few arguments.
+    Expect.throwsNoSuchMethodError(
+        () => a.foo('abc', 1, 2, 3)); //              Too many arguments.
+    Expect.throwsNoSuchMethodError(() => a.foo2('c', c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(
+        () => a.foo2('c', a: 111, c: 1)); //                    Bad name.
 
     Expect.equals(7, a.calls);
   }
@@ -113,10 +105,11 @@
 
     Expect.equals(7, a.calls);
 
-    checkException(() => f()); //                   Too few arguments.
-    checkException(() => f('abc', 1, 2, 3)); //     Too many arguments.
-    checkException(() => f2('c', c: 1)); //         Bad name.
-    checkException(() => f2('c', a: 111, c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(() => f()); // Too few arguments.
+    Expect.throwsNoSuchMethodError(
+        () => f('abc', 1, 2, 3)); //              Too many arguments.
+    Expect.throwsNoSuchMethodError(() => f2('c', c: 1)); //         Bad name.
+    Expect.throwsNoSuchMethodError(() => f2('c', a: 111, c: 1)); // Bad name.
 
     Expect.equals(7, a.calls);
   }
diff --git a/tests/language/regress/regress29784_test.dart b/tests/language/regress/regress29784_test.dart
index 0df166f..37db686 100644
--- a/tests/language/regress/regress29784_test.dart
+++ b/tests/language/regress/regress29784_test.dart
@@ -16,6 +16,7 @@
   // [cfe] Can't access 'this' in a field initializer to read 'a'.
   A.ko() : assert(a == null);
   //              ^
+  // [analyzer] COMPILE_TIME_ERROR.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
   // [cfe] Can't access 'this' in a field initializer to read 'a'.
   var a, b;
 }
diff --git a/tests/language/regress/regress65278_test.dart b/tests/language/regress/regress65278_test.dart
new file mode 100644
index 0000000..9edf22c
--- /dev/null
+++ b/tests/language/regress/regress65278_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main() {
+  ContentTabsWidget();
+}
+
+class StatefulWidget {}
+
+class State<T> {}
+
+class WidgetsBindingObserver {}
+
+class IBase {}
+
+class ContentTabsWidget extends BaseStatefulWidget<ContentTabsState, dynamic> {}
+
+class ContentTabsState<W extends ContentTabsWidget>
+    extends BaseState<W, dynamic> {}
+
+class BaseStatefulWidget<ST extends SuperState, T>
+    extends SuperStatefulWidget<ST, T, IBase> {}
+
+class BaseState<W extends StatefulWidget, T> extends SuperState<W, T, IBase> {}
+
+class SuperStatefulWidget<S extends SuperState, T, B> extends StatefulWidget {}
+
+class SuperState<W extends StatefulWidget, T, B> extends State<W>
+    with WidgetsBindingObserver {}
diff --git a/tests/language/setter/declaration_test.dart b/tests/language/setter/declaration_test.dart
index 617fc2c..78d5e81 100644
--- a/tests/language/setter/declaration_test.dart
+++ b/tests/language/setter/declaration_test.dart
@@ -21,119 +21,119 @@
 /*space*/ int? set wrongReturnType1(_) => 1;
 //        ^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-// [cfe] unspecified
+// [cfe] The return type of the setter must be 'void' or absent.
 
 /*space*/ FutureOr<void> set wrongReturnType2(_) {}
 //        ^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-// [cfe] unspecified
+// [cfe] The return type of the setter must be 'void' or absent.
 
 /*space*/ Never set wrongReturnType3(_) => throw 1;
 //        ^^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-// [cfe] unspecified
+// [cfe] The return type of the setter must be 'void' or absent.
 
 int get nonSubtypes1 => 1;
 //      ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-// [cfe] unspecified
+// [cfe] The type 'int' of the getter 'nonSubtypes1' is not a subtype of the type 'String' of the setter 'nonSubtypes1'.
 set nonSubtypes1(String _) {}
 
 int? get nonSubtypes2 => 1;
 //       ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-// [cfe] unspecified
+// [cfe] The type 'int?' of the getter 'nonSubtypes2' is not a subtype of the type 'int' of the setter 'nonSubtypes2'.
 set nonSubtypes2(int _) {}
 
 FutureOr<int> get nonSubtypes3 => 1;
 //                ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-// [cfe] unspecified
+// [cfe] The type 'FutureOr<int>' of the getter 'nonSubtypes3' is not a subtype of the type 'int' of the setter 'nonSubtypes3'.
 set nonSubtypes3(int _) {}
 
 dynamic get nonSubtypes4 => 1;
 //          ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-// [cfe] unspecified
+// [cfe] The type 'dynamic' of the getter 'nonSubtypes4' is not a subtype of the type 'int' of the setter 'nonSubtypes4'.
 set nonSubtypes4(int _) {}
 
 class C {
   static int? set staticWrongReturnType1(_) => 1;
   //     ^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   static FutureOr<void> set staticWrongReturnType2(_) {}
   //     ^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   static Never set staticWrongReturnType3(_) => throw 1;
   //     ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   /*space*/ int? set wrongReturnType1(_) => 1;
   //        ^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   /*space*/ FutureOr<void> set wrongReturnType2(_) {}
   //        ^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   /*space*/ Never set wrongReturnType3(_) => throw 1;
   //        ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.NON_VOID_RETURN_FOR_SETTER
-  // [cfe] unspecified
+  // [cfe] The return type of the setter must be 'void' or absent.
 
   static int get staticNonSubtypes1 => 1;
   //             ^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'int' of the getter 'C.staticNonSubtypes1' is not a subtype of the type 'String' of the setter 'C.staticNonSubtypes1'.
   static set staticNonSubtypes1(String _) {}
 
   static int? get staticNonSubtypes2 => 1;
   //              ^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'int?' of the getter 'C.staticNonSubtypes2' is not a subtype of the type 'int' of the setter 'C.staticNonSubtypes2'.
   static set staticNonSubtypes2(int _) {}
 
   static FutureOr<int> get staticNonSubtypes3 => 1;
   //                       ^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'FutureOr<int>' of the getter 'C.staticNonSubtypes3' is not a subtype of the type 'int' of the setter 'C.staticNonSubtypes3'.
   static set staticNonSubtypes3(int _) {}
 
   static dynamic get staticNonSubtypes4 => 1;
   //                 ^^^^^^^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'dynamic' of the getter 'C.staticNonSubtypes4' is not a subtype of the type 'int' of the setter 'C.staticNonSubtypes4'.
   static set staticNonSubtypes4(int _) {}
 
   int get nonSubtypes1 => 1;
   //      ^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'int' of the getter 'C.nonSubtypes1' is not a subtype of the type 'String' of the setter 'C.nonSubtypes1'.
   set nonSubtypes1(String _) {}
 
   int? get nonSubtypes2 => 1;
   //       ^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'int?' of the getter 'C.nonSubtypes2' is not a subtype of the type 'int' of the setter 'C.nonSubtypes2'.
   set nonSubtypes2(int _) {}
 
   FutureOr<int> get nonSubtypes3 => 1;
   //                ^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'FutureOr<int>' of the getter 'C.nonSubtypes3' is not a subtype of the type 'int' of the setter 'C.nonSubtypes3'.
   set nonSubtypes3(int _) {}
 
   dynamic get nonSubtypes4 => 1;
   //          ^^^^^^^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_SUBTYPE_SETTER_TYPES
-  // [cfe] unspecified
+  // [cfe] The type 'dynamic' of the getter 'C.nonSubtypes4' is not a subtype of the type 'int' of the setter 'C.nonSubtypes4'.
   set nonSubtypes4(int _) {}
 }
 
diff --git a/tests/language/spread_collections/const_test.dart b/tests/language/spread_collections/const_test.dart
index 1eb4d76..cab125f 100644
--- a/tests/language/spread_collections/const_test.dart
+++ b/tests/language/spread_collections/const_test.dart
@@ -43,8 +43,8 @@
       const <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
 
   // Null-aware.
-  const List<int>? list23 = <int>[2, 3];
-  const List<int>? list4 = <int>[4];
+  const list23 = <int>[2, 3] as List<int>?;
+  const list4 = <int>[4] as List<int>?;
   Expect.identical(list,
       const <int>[1, ...?list23, ...?(null), ...?list4]);
 
@@ -98,8 +98,8 @@
   });
 
   // Null-aware.
-  const Map<int, int>? map23 = <int, int>{2: 2, 3: 3};
-  const Map<int, int>? map4 = <int, int>{4: 4};
+  const map23 = <int, int>{2: 2, 3: 3} as Map<int, int>?;
+  const map4 = <int, int>{4: 4} as Map<int, int>?;
   Expect.identical(map, const <int, int>{
     1: 1,
     ...?map23,
@@ -155,8 +155,8 @@
   Expect.identical(set, const <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
 
   // Null-aware.
-  const List<int>? list23 = <int>[2, 3];
-  const List<int>? list4 = <int>[4];
+  const list23 = <int>[2, 3] as List<int>?;
+  const list4 = <int>[4] as List<int>?;
   Expect.identical(set,
       const <int>{1, ...?list23, ...?(null), ...?list4});
 
diff --git a/tests/language/spread_collections/null_spread_test.dart b/tests/language/spread_collections/null_spread_test.dart
index 777378d..aad1331 100644
--- a/tests/language/spread_collections/null_spread_test.dart
+++ b/tests/language/spread_collections/null_spread_test.dart
@@ -21,6 +21,8 @@
   var l3 = [...?myNever];
   //        ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //            ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   List<Never> l3b = l3;
   var s1 = {...?x, if (false) throw 1};
   Set<Never> s1b = s1;
@@ -29,6 +31,8 @@
   var s3 = {...?myNever, if (false) throw 1};
   //        ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //            ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   Set<Never> s3b = s3;
   var m1 = {...?x, if (false) throw 1: throw 1};
   Map<Never, Never> m1b = m1;
@@ -37,6 +41,8 @@
   var m3 = {...?myNever, if (false) throw 1: throw 1};
   //        ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //            ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   Map<Never, Never> m3b = m3;
 
   // Test non-empty collection of `Never` and `int`.
@@ -47,6 +53,8 @@
   var li3 = [...?myNever, 1];
   //         ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //             ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   List<int> li3b = li3;
   var si1 = {1, ...?x};
   Set<int> si1b = si1;
@@ -55,6 +63,8 @@
   var si3 = {1, ...?myNever};
   //            ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //                ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   Set<int> si3b = si3;
   var mi1 = {1: 1, ...?x};
   Map<int, int> mi1b = mi1;
@@ -63,6 +73,8 @@
   var mi3 = {1: 1, ...?myNever};
   //               ^^^^
   // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //                   ^
+  // [cfe] Operand of null-aware operation '...?' has type 'Never' which excludes null.
   Map<int, int> mi3b = mi3;
 }
 
diff --git a/tests/language/spread_collections/spread_test.dart b/tests/language/spread_collections/spread_test.dart
index 2a19168..baee04c 100644
--- a/tests/language/spread_collections/spread_test.dart
+++ b/tests/language/spread_collections/spread_test.dart
@@ -43,8 +43,8 @@
   Expect.listEquals(list, <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
 
   // Null-aware.
-  List<int>? list23 = [2, 3];
-  List<int>? list4 = [4];
+  var list23 = [2, 3] as List<int>?;
+  var list4 = [4] as List<int>?;
   Expect.listEquals(list, <int>[1, ...?list23, ...?(null), ...?list4]);
 
   // Does not deep flatten.
@@ -94,8 +94,8 @@
   });
 
   // Null-aware.
-  Map<int, int>? map23 = {2: 2, 3: 3};
-  Map<int, int>? map4 = {4: 4};
+  var map23 = {2: 2, 3: 3} as Map<int, int>?;
+  var map4 = {4: 4} as Map<int, int>?;
   Expect.mapEquals(map, <int, int>{
     1: 1,
     ...?map23,
@@ -147,8 +147,8 @@
   Expect.setEquals(set, <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
 
   // Null-aware.
-  List<int>? list23 = [2, 3];
-  List<int>? list4 = [4];
+  var list23 = [2, 3] as List<int>?;
+  var list4 = [4] as List<int>?;
   Expect.setEquals(set, <int>{1, ...?list23, ...?(null), ...?list4});
 
   // Does not deep flatten.
diff --git a/tests/language/spread_collections/syntax_test.dart b/tests/language/spread_collections/syntax_test.dart
index aa6a51f..ed6676f 100644
--- a/tests/language/spread_collections/syntax_test.dart
+++ b/tests/language/spread_collections/syntax_test.dart
@@ -17,11 +17,11 @@
 
   var a = [0];
   Expect.listEquals([1, 2, 3], [1, ...a = [2], 3]);
-  List<int>? nullableA = [0];
+  var nullableA = [0] as List<int>?;
   Expect.listEquals([1, 3], [1, ...?nullableA = null, 3]);
 
   var b = [2];
   Expect.listEquals([1, 2, 3, 4], [1, ...b..add(3), 4]);
-  List<int>? nullableB = [2];
+  var nullableB = [2] as List<int>?;
   Expect.listEquals([1, 2, 3, 4], [1, ...?nullableB?..add(3), 4]);
 }
diff --git a/tests/language/spread_collections/type_error_test.dart b/tests/language/spread_collections/type_error_test.dart
index ccfc61a..3fe731a 100644
--- a/tests/language/spread_collections/type_error_test.dart
+++ b/tests/language/spread_collections/type_error_test.dart
@@ -20,7 +20,7 @@
   var _ = <int>{...<String>[]}; //# 09: compile-time error
 
   // Downcast element.
-  var _ = <int>[...<num>[1, 2]]); //# 10: compile-time error
-  var _ = <int, int>{...<num, num>{1: 1, 2: 2}}); //# 11: compile-time error
-  var _ = <int>{...<num>[1, 2]}); //# 12: compile-time error
+  var _ = <int>[...<num>[1, 2]]; //# 10: compile-time error
+  var _ = <int, int>{...<num, num>{1: 1, 2: 2}}; //# 11: compile-time error
+  var _ = <int>{...<num>[1, 2]}; //# 12: compile-time error
 }
diff --git a/tests/language/static/final_field2_test.dart b/tests/language/static/final_field2_test.dart
index 6430471..da8ea37 100644
--- a/tests/language/static/final_field2_test.dart
+++ b/tests/language/static/final_field2_test.dart
@@ -19,9 +19,8 @@
 
 main() {
   A.x = 2;
-//^^^
-// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_CONST
 //  ^
+// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_CONST
 // [cfe] Setter not found: 'x'.
   new B();
   print(B.b);
diff --git a/tests/language/static_type_helper.dart b/tests/language/static_type_helper.dart
new file mode 100644
index 0000000..9484387
--- /dev/null
+++ b/tests/language/static_type_helper.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Ensures a context type of [T] for the operand.
+void context<T>(T x) {}
+
+/// Captures the context type of the call and returns the same type.
+///
+/// Can be used to check the context type as:
+/// ```dart
+/// int x = contextType(1 /* valid value */)..expectStaticType<Exactly<int>>;
+/// ```
+T contextType<T>(Object result) => result as T;
+
+extension StaticType<T> on T {
+  /// Check the static type.
+  ///
+  /// Use as follows (assuming `e` has static type `num`):
+  /// ```dart
+  ///   e.expectStaticType<Exactly<num>>()  // No context type.
+  ///   e.expectStaticType<SubtypeOf<Object>>()  // No context type.
+  ///   e.expectStaticType<SupertypeOf<int>>()  // No context type.
+  /// ```
+  /// or
+  /// ```dart
+  ///   e..expectStaticType<Exactly<num>>()  // Preserve context type.
+  ///   e..expectStaticType<SubtypeOf<Object>>()  // Preserve context type.
+  ///   e..expectStaticType<SupertypeOf<int>>()  // Preserve context type.
+  /// ```
+  /// This will be a *compile-time error* if the static type is not
+  /// as required by the constraints type (the one passed to [Exactly],
+  /// [SubtypeOf] or [SupertypeOf].)
+  T expectStaticType<R extends Exactly<T>>() {
+    return this;
+  }
+}
+
+/// Use with [StaticType.expectStaticType] to expect precisely the type [T].
+///
+/// Example use:
+/// ```dart
+/// "abc".expectStaticType<Exactly<String>>();
+/// ```
+typedef Exactly<T> = T Function(T);
+
+/// Use with [StaticType.expectStaticType] to expect a subtype of [T].
+///
+/// Example use:
+/// ```dart
+/// num x = 1;
+/// x.expectStaticType<SubtypeOf<Object>>();
+/// ```
+typedef SubtypeOf<T> = Never Function(T);
+
+/// Use with [StaticType.expectStaticType] to expect a supertype of [T].
+///
+/// Example use:
+/// ```dart
+/// num x = 1;
+/// x.expectStaticType<SupertypeOf<int>>();
+/// ```
+typedef SupertypeOf<T> = T Function(Object?);
+
+/// Checks that an expression is assignable to [T1], [T2] and [Object].
+///
+/// This ensures that the static type of the expression is either dynamic,
+/// Never, or a type assignable to both [T1] and [T2], and if those are
+/// unrelated, it must be an intersection type.
+void checkIntersectionType<T1, T2>(T1 v1, T2 v2, Object v3) {}
diff --git a/tests/language/string/substring_test.dart b/tests/language/string/substring_test.dart
index 6f33829..6d7943f 100644
--- a/tests/language/string/substring_test.dart
+++ b/tests/language/string/substring_test.dart
@@ -13,7 +13,7 @@
     // [cfe] The argument type 'double' can't be assigned to the parameter type 'int'.
     //                            ^^^
     // [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-    // [cfe] The argument type 'double' can't be assigned to the parameter type 'int'.
+    // [cfe] The argument type 'double' can't be assigned to the parameter type 'int?'.
     Expect.fail("Should have thrown an exception");
   } on TypeError catch (e) {
     // OK.
diff --git a/tests/language/super/conditional_operator_test.dart b/tests/language/super/conditional_operator_test.dart
index c93ed77..dcbc633 100644
--- a/tests/language/super/conditional_operator_test.dart
+++ b/tests/language/super/conditional_operator_test.dart
@@ -34,6 +34,8 @@
     //   ^^
     // [analyzer] SYNTACTIC_ERROR.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
     // [cfe] The operator '?.' cannot be used with 'super' because 'super' cannot be null.
+    //     ^
+    // [cfe] Operand of null-aware operation '??=' has type 'int' which excludes null.
     //               ^
     // [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
     super?.field;
@@ -47,17 +49,17 @@
     // [analyzer] SYNTACTIC_ERROR.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
     // [cfe] The operator '?.' cannot be used with 'super' because 'super' cannot be null.
     -super?.field;
+//   ^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
     //    ^^
     // [analyzer] SYNTACTIC_ERROR.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
     // [cfe] The operator '?.' cannot be used with 'super' because 'super' cannot be null.
-//   ^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
     ~super?.field;
+//   ^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
     //    ^^
     // [analyzer] SYNTACTIC_ERROR.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
     // [cfe] The operator '?.' cannot be used with 'super' because 'super' cannot be null.
-//   ^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.UNCHECKED_USE_OF_NULLABLE_VALUE
     !super?.field;
 //   ^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.NON_BOOL_NEGATION_EXPRESSION
diff --git a/tests/language/unsorted/external_test.dart b/tests/language/unsorted/external_test.dart
index 12d6306c..00c7f42 100644
--- a/tests/language/unsorted/external_test.dart
+++ b/tests/language/unsorted/external_test.dart
@@ -37,6 +37,8 @@
   //  ^^^^^^^^
   // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
   // [cfe] Expected ';' after this.
+  //  ^
+  // [cfe] Field 'external' should be initialized because its type 'int' doesn't allow null.
   //           ^^^^^^
   // [analyzer] COMPILE_TIME_ERROR.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER
 
@@ -67,13 +69,13 @@
 }
 
 external int t06(int i) { return 1; }
-// [error line 69, column 1, length 8]
+// [error line 71, column 1, length 8]
 // [analyzer] SYNTACTIC_ERROR.EXTERNAL_METHOD_WITH_BODY
 // [cfe] An external or native method can't have a body.
 //                      ^
 // [cfe] An external or native method can't have a body.
 external int t07(int i) => i + 1;
-// [error line 75, column 1, length 8]
+// [error line 77, column 1, length 8]
 // [analyzer] SYNTACTIC_ERROR.EXTERNAL_METHOD_WITH_BODY
 // [cfe] An external or native method can't have a body.
 //                         ^
diff --git a/tests/language/variable/duplicate_field_with_initializer_test.dart b/tests/language/variable/duplicate_field_with_initializer_test.dart
index 68bd560..929fc64 100644
--- a/tests/language/variable/duplicate_field_with_initializer_test.dart
+++ b/tests/language/variable/duplicate_field_with_initializer_test.dart
@@ -3,9 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 class Repeated {
-  var a = '', b = 'Something';
-  var b;
-  //  ^
+  dynamic a = '', b = 'Something';
+  dynamic b;
+  //      ^
   // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
   // [cfe] 'b' is already declared in this scope.
 }
diff --git a/tests/language/variance/variance_downwards_inference_test.dart b/tests/language/variance/variance_downwards_inference_test.dart
index b6cd329..6e531b1 100644
--- a/tests/language/variance/variance_downwards_inference_test.dart
+++ b/tests/language/variance/variance_downwards_inference_test.dart
@@ -10,7 +10,7 @@
   final T _x;
   A(T x):_x = x;
   T get x => _x;
-  void set x(Object value) {}
+  void set x(Object? value) {}
 }
 
 class B<in T> {
@@ -22,7 +22,7 @@
   final T _x;
   C(T x, S y):_x = x;
   T get x => _x;
-  void set x(Object value) {}
+  void set x(Object? value) {}
   void set y(S _value) {}
 }
 
diff --git a/tests/language/variance/variance_in_inference_error_test.dart b/tests/language/variance/variance_in_inference_error_test.dart
index d73f8b0..34c6fb3 100644
--- a/tests/language/variance/variance_in_inference_error_test.dart
+++ b/tests/language/variance/variance_in_inference_error_test.dart
@@ -47,41 +47,31 @@
   inferCovContra(Covariant<int>(), Contravariant<String>());
 //^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
-//                                 ^^^^^^^^^^^^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-// [cfe] The argument type 'Contravariant<String>' can't be assigned to the parameter type 'Contravariant<int>'.
+// [cfe] unspecified
 
   // String <: T <: int is not a valid constraint.
   inferCovContra(Covariant<String>(), Contravariant<int>());
 //^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
-//                                    ^^^^^^^^^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.ARGUMENT_TYPE_NOT_ASSIGNABLE
-// [cfe] The argument type 'Contravariant<int>' can't be assigned to the parameter type 'Contravariant<String>'.
+// [cfe] unspecified
 
   // Middle <: T <: Lower is not a valid constraint
   inferCovContra(Covariant<Middle>(), Contravariant<Lower>());
 //^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
-//                                    ^^^^^^^^^^^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
-// [cfe] The argument type 'Contravariant<Lower>' can't be assigned to the parameter type 'Contravariant<Middle>'.
+// [cfe] unspecified
 
   // Upper <: T <: Lower is not a valid constraint
   inferCovContra(Covariant<Upper>(), Contravariant<Lower>());
 //^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
-//                                   ^^^^^^^^^^^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
-// [cfe] The argument type 'Contravariant<Lower>' can't be assigned to the parameter type 'Contravariant<Upper>'.
+// [cfe] unspecified
 
   // Upper <: T <: Middle is not a valid constraint
   inferCovContra(Covariant<Upper>(), Contravariant<Middle>());
 //^^^^^^^^^^^^^^
 // [analyzer] COMPILE_TIME_ERROR.COULD_NOT_INFER
-//                                   ^^^^^^^^^^^^^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.INVALID_CAST_NEW_EXPR
-// [cfe] The argument type 'Contravariant<Middle>' can't be assigned to the parameter type 'Contravariant<Upper>'.
+// [cfe] unspecified
 
   // Inference for Contrabound(...) produces Lower <: T <: Upper.
   // Since T is contravariant, we choose Upper as the solution.
diff --git a/tests/language/vm/regress_flutter_55345_const_test.dart b/tests/language/vm/regress_flutter_55345_const_test.dart
deleted file mode 100644
index a30bb11..0000000
--- a/tests/language/vm/regress_flutter_55345_const_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Verifies that references to deduplicated mixins are properly updated
-// in types which are only accessible through constants.
-// Regression test for https://github.com/flutter/flutter/issues/55345.
-
-class Diagnosticable {}
-
-class SomeClass with Diagnosticable {}
-
-class State<T> with Diagnosticable {
-  const State();
-}
-
-class StateA extends State {
-  const StateA();
-}
-
-class StateB extends State<int> {
-  const StateB();
-}
-
-const c1 = StateA() as dynamic;
-const c2 = StateB();
-
-main() {
-  print(const [
-    {
-      (c1 ?? c2): [
-        [c1 ?? c2]
-      ]
-    },
-    'abc'
-  ]);
-}
diff --git a/tests/language/vm/regress_flutter_55345_test.dart b/tests/language/vm/regress_flutter_55345_test.dart
deleted file mode 100644
index 3fbe990..0000000
--- a/tests/language/vm/regress_flutter_55345_test.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Verifies that references to deduplicated mixins are properly updated.
-// Regression test for https://github.com/flutter/flutter/issues/55345.
-
-class Diagnosticable {}
-
-class SomeClass with Diagnosticable {}
-
-class State<T> with Diagnosticable {}
-
-class StateA extends State {}
-
-class StateB extends State<int> {}
-
-StateA? a = StateA();
-StateB? b = StateB();
-
-List<T> foo<T>(T x) {
-  print(T);
-  return <T>[x];
-}
-
-T Function<S extends T>(T) bar<T>(T x) {
-  print(T);
-
-  return <S extends T>(T y) {
-    print(S);
-    print(y);
-    return y;
-  };
-}
-
-main() {
-  var x2 = a ?? b;
-  var x3 = foo(x2);
-  var x4 = bar(x3);
-  x4(x3);
-}
diff --git a/tests/language_2/class/keyword_test.dart b/tests/language_2/class/keyword_test.dart
index 5a89f2e..8b07fec 100644
--- a/tests/language_2/class/keyword_test.dart
+++ b/tests/language_2/class/keyword_test.dart
@@ -13,15 +13,15 @@
 // [cfe] Expected ';' after this.
 //    ^^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-// [cfe] Expected an identifier, but got 'class'.
+// [cfe] 'class' can't be used as an identifier because it's a keyword.
 //    ^^^^^
-// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
 // [cfe] Setter not found: 'class'.
   print("$class");
   //      ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
-  // [cfe] Expected an identifier, but got 'class'.
+  // [cfe] 'class' can't be used as an identifier because it's a keyword.
   //      ^^^^^
-  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
   // [cfe] Getter not found: 'class'.
 }
diff --git a/tests/language_2/enum/is_keyword_test.dart b/tests/language_2/enum/is_keyword_test.dart
index 5e7d0b5..4d37239 100644
--- a/tests/language_2/enum/is_keyword_test.dart
+++ b/tests/language_2/enum/is_keyword_test.dart
@@ -8,6 +8,6 @@
 main() {
   var enum;
   //  ^^^^
-  // [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
-  // [cfe] Expected an identifier, but got 'enum'.
+  // [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
+  // [cfe] 'enum' can't be used as an identifier because it's a keyword.
 }
diff --git a/tests/language_2/getter/setter2_test.dart b/tests/language_2/getter/setter2_test.dart
index a533c41..ad8700b 100644
--- a/tests/language_2/getter/setter2_test.dart
+++ b/tests/language_2/getter/setter2_test.dart
@@ -38,6 +38,7 @@
   A get field {
   //    ^^^^^
   // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_ASSIGNABLE_SETTER_TYPES
+  // [cfe] The type 'A' of the getter 'T2.field' is not assignable to the type 'C' of the setter 'T2.field'.
     return getterField;
   }
 
diff --git a/tests/language_2/getter/setter_type_test.dart b/tests/language_2/getter/setter_type_test.dart
index a7caee4..c813ca8 100644
--- a/tests/language_2/getter/setter_type_test.dart
+++ b/tests/language_2/getter/setter_type_test.dart
@@ -11,6 +11,7 @@
 int get foo => bar;
 //      ^^^
 // [analyzer] COMPILE_TIME_ERROR.GETTER_NOT_ASSIGNABLE_SETTER_TYPES
+// [cfe] The type 'int' of the getter 'foo' is not assignable to the type 'String' of the setter 'foo'.
 
 void set foo(String str) {
   bar = str.length;
diff --git a/tests/language_2/label/label8_test.dart b/tests/language_2/label/label8_test.dart
index a40c1b7..5e71b10 100644
--- a/tests/language_2/label/label8_test.dart
+++ b/tests/language_2/label/label8_test.dart
@@ -14,12 +14,12 @@
     case 111:
 //  ^^^^
 // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_IDENTIFIER
+// [cfe] 'case' can't be used as an identifier because it's a keyword.
+//  ^^^^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD
 // [cfe] Expected ';' after this.
 //  ^^^^
 // [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
-// [cfe] Expected an identifier, but got 'case'.
-//  ^^^^
-// [analyzer] SYNTACTIC_ERROR.MISSING_IDENTIFIER
 // [cfe] Getter not found: 'case'.
 //  ^^^^
 // [analyzer] SYNTACTIC_ERROR.MISSING_STATEMENT
diff --git a/tests/language_2/language_2.status b/tests/language_2/language_2.status
index c602c82..80846fb 100644
--- a/tests/language_2/language_2.status
+++ b/tests/language_2/language_2.status
@@ -41,7 +41,7 @@
 [ $compiler != dart2js && $compiler != dartdevc && !$checked ]
 function_type/*: Skip # Needs checked mode.
 
-[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp && $mode == debug && $runtime == vm ]
+[ $compiler != dartk && $compiler != dartkp && $mode == debug && $runtime == vm ]
 identifier/built_in_type_annotation_test/set: Crash # Not supported by legacy VM front-end.
 
 [ $hot_reload || $hot_reload_rollback ]
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 65d883a..8c0d481 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -108,21 +108,21 @@
 [ $compiler == dartkp && $system == windows ]
 unsorted/disassemble_test: Slow, Pass
 
-[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk || $compiler == dartkb) ]
+[ $mode == debug && $runtime == vm && ($compiler == app_jitk || $compiler == dartk) ]
 optimize/deopt_inlined_function_lazy_test: Skip
 
-[ $mode == debug && ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+[ $mode == debug && ($compiler == dartk) && ($hot_reload || $hot_reload_rollback) ]
 enum/duplicate_test/02: Crash # Issue 34606
 enum/duplicate_test/none: Crash # Issue 34606
 enum/private_test/01: Crash # Issue 34606
 enum/test: Crash # Issue 34606
 
-[ $mode == product && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $mode == product && $runtime == vm && ($compiler == dartk) ]
 vm/causal_async_exception_stack2_test: SkipByDesign
 vm/causal_async_exception_stack_test: SkipByDesign
 
 # ===== dartk + vm status lines =====
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $runtime == vm && ($compiler == dartk) ]
 const/const2_test: Crash # Flaky
 main/no_main_test/01: Skip
 mixin/illegal_super_use_test: Skip # Issues 24478 and 23773
@@ -132,8 +132,8 @@
 vm/regress_29145_test: Skip # Issue 29145
 web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
 
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
+[ $hot_reload_rollback && ($compiler == dartk) ]
 symbol/conflict_test: Slow, Pass
 
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
+[ ($compiler == dartk) && ($hot_reload || $hot_reload_rollback) ]
 type_constants_test/none: Skip # Deferred libraries and hot reload.
diff --git a/tests/language_2/mixin/implicit_covariance_test.dart b/tests/language_2/mixin/implicit_covariance_test.dart
index 5606bd7..87d3ddd 100644
--- a/tests/language_2/mixin/implicit_covariance_test.dart
+++ b/tests/language_2/mixin/implicit_covariance_test.dart
@@ -13,7 +13,7 @@
 class C {
   foo(num x) {
     if (x is! num) {
-      throw "Soudness issue: expected x to be num, got ${x.runtimeType}.";
+      throw "Soundness issue: expected x to be num, got ${x.runtimeType}.";
     }
   }
 }
diff --git a/tests/language_2/mixin/regress_flutter_55345_const_test.dart b/tests/language_2/mixin/regress_flutter_55345_const_test.dart
new file mode 100644
index 0000000..9c9551d
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_55345_const_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that references to deduplicated mixins are properly updated
+// in types which are only accessible through constants.
+// Regression test for https://github.com/flutter/flutter/issues/55345.
+
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {
+  const State();
+}
+
+class StateA extends State {
+  const StateA();
+}
+
+class StateB extends State<int> {
+  const StateB();
+}
+
+const c1 = StateA();
+const c2 = StateB();
+
+main() {
+  print(const [
+    {
+      (c1 ?? c2): [
+        [c1 ?? c2]
+      ]
+    },
+    'abc'
+  ]);
+  // No compile time or runtime errors.
+}
diff --git a/tests/language_2/mixin/regress_flutter_55345_test.dart b/tests/language_2/mixin/regress_flutter_55345_test.dart
new file mode 100644
index 0000000..0cb0441
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_55345_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that references to deduplicated mixins are properly updated.
+// Regression test for https://github.com/flutter/flutter/issues/55345.
+
+class Diagnosticable {}
+
+class SomeClass with Diagnosticable {}
+
+class State<T> with Diagnosticable {}
+
+class StateA extends State {}
+
+class StateB extends State<int> {}
+
+StateA a = StateA();
+StateB b = StateB();
+
+List<T> foo<T>(T x) {
+  print(T);
+  return <T>[x];
+}
+
+T Function<S extends T>(T) bar<T>(T x) {
+  print(T);
+
+  return <S extends T>(T y) {
+    print(S);
+    print(y);
+    return y;
+  };
+}
+
+main() {
+  State x1 = a ?? b;
+  print(x1);
+
+  var x2 = a ?? b;
+  var x3 = foo(x2);
+  var x4 = bar(x3);
+  x4(x3);
+  // No compile time or runtime errors.
+}
diff --git a/tests/language_2/mixin/regress_flutter_66859_1_test.dart b/tests/language_2/mixin/regress_flutter_66859_1_test.dart
new file mode 100644
index 0000000..544da53
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_66859_1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin M {}
+
+mixin N {}
+
+class A extends B<C> with M, N {}
+
+class B<T> {}
+
+class C extends A {}
+
+class Z extends B<Z> with M {}
+
+main() {
+  var z = Z();
+  Expect.isTrue(z is B<Z>);
+  Expect.isTrue(z is M);
+  var a = A();
+  Expect.isTrue(a is M);
+  Expect.isTrue(a is N);
+  Expect.isTrue(a is B<C>);
+}
diff --git a/tests/language_2/mixin/regress_flutter_66859_2_test.dart b/tests/language_2/mixin/regress_flutter_66859_2_test.dart
new file mode 100644
index 0000000..7a3ee64
--- /dev/null
+++ b/tests/language_2/mixin/regress_flutter_66859_2_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verifies that mixin supertypes are properly maintained even if marked as
+// deferred (e.g., in a circular hierarchy).
+// Regression test for: https://github.com/flutter/flutter/issues/66859
+
+import "package:expect/expect.dart";
+
+mixin X {}
+mixin Y {}
+mixin Z {}
+
+class A extends B<C> with X {}
+
+class C extends A with Z {}
+
+class B<T> extends Object with Y {}
+
+main() {
+  var a = A();
+  var b = B();
+  var c = C();
+  Expect.isTrue(a is A);
+  Expect.isTrue(a is B<C>);
+  Expect.isTrue(a is X);
+  Expect.isTrue(a is Y);
+  Expect.isTrue(c is C);
+  Expect.isTrue(c is A);
+  Expect.isTrue(c is B<C>);
+  Expect.isTrue(c is X);
+  Expect.isTrue(c is Y);
+  Expect.isTrue(c is Z);
+  Expect.isTrue(b is B);
+  Expect.isTrue(b is Y);
+}
diff --git a/tests/language_2/parameter/named_aggregated_test.dart b/tests/language_2/parameter/named_aggregated_test.dart
index 82c7c8c..1b506df 100644
--- a/tests/language_2/parameter/named_aggregated_test.dart
+++ b/tests/language_2/parameter/named_aggregated_test.dart
@@ -27,8 +27,6 @@
   // Expect compile-time error as no default values
   // are allowed in closure type.
   void InstallCallback(void cb({String msg : null})) {
-  //                            ^^^^^^^^^^^^^^^^^
-  // [analyzer] COMPILE_TIME_ERROR.DEFAULT_VALUE_IN_FUNCTION_TYPED_PARAMETER
   //                                       ^
   // [analyzer] SYNTACTIC_ERROR.DEFAULT_VALUE_IN_FUNCTION_TYPE
   // [cfe] Can't have a default value in a function type.
diff --git a/tests/language_2/parameter/named_with_conversions_test.dart b/tests/language_2/parameter/named_with_conversions_test.dart
index 14849e6..5b949e6 100644
--- a/tests/language_2/parameter/named_with_conversions_test.dart
+++ b/tests/language_2/parameter/named_with_conversions_test.dart
@@ -29,9 +29,9 @@
 }
 
 class HasMethod {
-  int calls;
+  int calls = 0;
 
-  HasMethod() : calls = 0 {}
+  HasMethod();
 
   foo(tag, [a = 10, b = 20]) {
     calls += 1;
@@ -45,11 +45,10 @@
 }
 
 class HasField {
-  int calls;
-  var foo, foo2;
+  int calls = 0;
+  dynamic foo, foo2;
 
   HasField() {
-    calls = 0;
     foo = makeFoo(this);
     foo2 = makeFoo2(this);
   }
@@ -72,16 +71,6 @@
 }
 
 class NamedParametersWithConversionsTest {
-  static checkException(thunk) {
-    bool threw = false;
-    try {
-      thunk();
-    } catch (e) {
-      threw = true;
-    }
-    Expect.isTrue(threw);
-  }
-
   static testMethodCallSyntax(a) {
     a.foo('');
     a.foo('a', 111);
@@ -93,10 +82,12 @@
 
     Expect.equals(7, a.calls);
 
-    checkException(() => a.foo()); //                  Too few arguments.
-    checkException(() => a.foo('abc', 1, 2, 3)); //    Too many arguments.
-    checkException(() => a.foo2('c', c: 1)); //        Bad name.
-    checkException(() => a.foo2('c', a: 111, c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(() => a.foo()); // Too few arguments.
+    Expect.throwsNoSuchMethodError(
+        () => a.foo('abc', 1, 2, 3)); //              Too many arguments.
+    Expect.throwsNoSuchMethodError(() => a.foo2('c', c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(
+        () => a.foo2('c', a: 111, c: 1)); //                    Bad name.
 
     Expect.equals(7, a.calls);
   }
@@ -114,10 +105,11 @@
 
     Expect.equals(7, a.calls);
 
-    checkException(() => f()); //                   Too few arguments.
-    checkException(() => f('abc', 1, 2, 3)); //     Too many arguments.
-    checkException(() => f2('c', c: 1)); //         Bad name.
-    checkException(() => f2('c', a: 111, c: 1)); // Bad name.
+    Expect.throwsNoSuchMethodError(() => f()); // Too few arguments.
+    Expect.throwsNoSuchMethodError(
+        () => f('abc', 1, 2, 3)); //              Too many arguments.
+    Expect.throwsNoSuchMethodError(() => f2('c', c: 1)); //         Bad name.
+    Expect.throwsNoSuchMethodError(() => f2('c', a: 111, c: 1)); // Bad name.
 
     Expect.equals(7, a.calls);
   }
diff --git a/tests/language_2/regress/regress29784_test.dart b/tests/language_2/regress/regress29784_test.dart
index 0df166f..37db686 100644
--- a/tests/language_2/regress/regress29784_test.dart
+++ b/tests/language_2/regress/regress29784_test.dart
@@ -16,6 +16,7 @@
   // [cfe] Can't access 'this' in a field initializer to read 'a'.
   A.ko() : assert(a == null);
   //              ^
+  // [analyzer] COMPILE_TIME_ERROR.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER
   // [cfe] Can't access 'this' in a field initializer to read 'a'.
   var a, b;
 }
diff --git a/tests/language_2/regress/regress65278_test.dart b/tests/language_2/regress/regress65278_test.dart
new file mode 100644
index 0000000..9edf22c
--- /dev/null
+++ b/tests/language_2/regress/regress65278_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+void main() {
+  ContentTabsWidget();
+}
+
+class StatefulWidget {}
+
+class State<T> {}
+
+class WidgetsBindingObserver {}
+
+class IBase {}
+
+class ContentTabsWidget extends BaseStatefulWidget<ContentTabsState, dynamic> {}
+
+class ContentTabsState<W extends ContentTabsWidget>
+    extends BaseState<W, dynamic> {}
+
+class BaseStatefulWidget<ST extends SuperState, T>
+    extends SuperStatefulWidget<ST, T, IBase> {}
+
+class BaseState<W extends StatefulWidget, T> extends SuperState<W, T, IBase> {}
+
+class SuperStatefulWidget<S extends SuperState, T, B> extends StatefulWidget {}
+
+class SuperState<W extends StatefulWidget, T, B> extends State<W>
+    with WidgetsBindingObserver {}
diff --git a/tests/language_2/static/final_field2_test.dart b/tests/language_2/static/final_field2_test.dart
index 6430471..da8ea37 100644
--- a/tests/language_2/static/final_field2_test.dart
+++ b/tests/language_2/static/final_field2_test.dart
@@ -19,9 +19,8 @@
 
 main() {
   A.x = 2;
-//^^^
-// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_CONST
 //  ^
+// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_CONST
 // [cfe] Setter not found: 'x'.
   new B();
   print(B.b);
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_and_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_and_test.dart
new file mode 100644
index 0000000..c47460b
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_and_test.dart
@@ -0,0 +1,240 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment on the right hand side of `&&` defeats promotion
+// after the entire `&&` expression, not just in the right hand side.
+
+class A {}
+
+class B extends A {
+  // An invocation of the form `x.checkB()` verifies that the static type of `x`
+  // is `B`, since this method is not defined anywhere else.
+  dynamic checkB() => null;
+}
+
+class C extends A {}
+
+class D extends B {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+dynamic checkNotB(C c) => null;
+
+// An invocation of the form `alwaysTrue(x)` always returns `true` regardless of
+// `x`.
+bool alwaysTrue(dynamic x) => true;
+
+ifSimple([A a]) {
+  if (a is B && alwaysTrue(a = null)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsUnparenthesizedUnrelated([A a, Object x]) {
+  if (a is B && alwaysTrue(a = null) && x is int) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsUnparenthesizedRePromote([A a]) {
+  if (a is B && alwaysTrue(a = null) && a is B) {
+    a.checkB();
+  }
+}
+
+ifChainedAndsUnparenthesizedAssignLast([A a, Object x]) {
+  if (a is B && x is int && alwaysTrue(a = null)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsUnparenthesizedDeeperPromote([A a]) {
+  if (a is B && a is D && alwaysTrue(a = null)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenLeftUnrelated([A a, Object x]) {
+  if ((a is B && alwaysTrue(a = null)) && x is int) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenLeftRePromote([A a]) {
+  if ((a is B && alwaysTrue(a = null)) && a is B) {
+    a.checkB();
+  }
+}
+
+ifChainedAndsParenLeftAssignLast([A a, Object x]) {
+  if ((a is B && x is int) && alwaysTrue(a = null)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenLeftDeeperPromote([A a]) {
+  if ((a is B && a is D) && alwaysTrue(a = null)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenRightUnrelated([A a, Object x]) {
+  if (a is B && (alwaysTrue(a = null) && x is int)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenRightRePromote([A a]) {
+  if (a is B && (alwaysTrue(a = null) && a is B)) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenRightAssignLast([A a, Object x]) {
+  if (a is B && (x is int && alwaysTrue(a = null))) {
+    checkNotB(a);
+  }
+}
+
+ifChainedAndsParenRightDeeperPromote([A a]) {
+  if (a is B && (a is D && alwaysTrue(a = null))) {
+    checkNotB(a);
+  }
+}
+
+conditionalSimple([A a]) {
+  a is B && alwaysTrue(a = null) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsUnparenthesizedUnrelated([A a, Object x]) {
+  a is B && alwaysTrue(a = null) && x is int ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsUnparenthesizedRePromote([A a]) {
+  a is B && alwaysTrue(a = null) && a is B ? a.checkB() : null;
+}
+
+conditionalChainedAndsUnparenthesizedAssignLast([A a, Object x]) {
+  a is B && x is int && alwaysTrue(a = null) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsUnparenthesizedDeeperPromote([A a]) {
+  a is B && a is D && alwaysTrue(a = null) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenLeftUnrelated([A a, Object x]) {
+  (a is B && alwaysTrue(a = null)) && x is int ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenLeftRePromote([A a]) {
+  (a is B && alwaysTrue(a = null)) && a is B ? a.checkB() : null;
+}
+
+conditionalChainedAndsParenLeftAssignLast([A a, Object x]) {
+  (a is B && x is int) && alwaysTrue(a = null) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenLeftDeeperPromote([A a]) {
+  (a is B && a is D) && alwaysTrue(a = null) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenRightUnrelated([A a, Object x]) {
+  a is B && (alwaysTrue(a = null) && x is int) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenRightRePromote([A a]) {
+  a is B && (alwaysTrue(a = null) && a is B) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenRightAssignLast([A a, Object x]) {
+  a is B && (x is int && alwaysTrue(a = null)) ? checkNotB(a) : null;
+}
+
+conditionalChainedAndsParenRightDeeperPromote([A a]) {
+  a is B && (a is D && alwaysTrue(a = null)) ? checkNotB(a) : null;
+}
+
+andSimple([A a]) {
+  a is B && alwaysTrue(a = null) && checkNotB(a);
+}
+
+andChainedAndsUnparenthesizedUnrelated([A a, Object x]) {
+  a is B && alwaysTrue(a = null) && x is int && checkNotB(a);
+}
+
+andChainedAndsUnparenthesizedAssignLast([A a, Object x]) {
+  a is B && x is int && alwaysTrue(a = null) && checkNotB(a);
+}
+
+andChainedAndsUnparenthesizedDeeperPromote([A a]) {
+  a is B && a is D && alwaysTrue(a = null) && checkNotB(a);
+}
+
+andChainedAndsParenLeftUnrelated([A a, Object x]) {
+  (a is B && alwaysTrue(a = null)) && x is int && checkNotB(a);
+}
+
+andChainedAndsParenLeftAssignLast([A a, Object x]) {
+  (a is B && x is int) && alwaysTrue(a = null) && checkNotB(a);
+}
+
+andChainedAndsParenLeftDeeperPromote([A a]) {
+  (a is B && a is D) && alwaysTrue(a = null) && checkNotB(a);
+}
+
+andChainedAndsParenRightUnrelated([A a, Object x]) {
+  a is B && (alwaysTrue(a = null) && x is int) && checkNotB(a);
+}
+
+andChainedAndsParenRightRePromote([A a]) {
+  a is B && (alwaysTrue(a = null) && a is B) && checkNotB(a);
+}
+
+andChainedAndsParenRightAssignLast([A a, Object x]) {
+  a is B && (x is int && alwaysTrue(a = null)) && checkNotB(a);
+}
+
+andChainedAndsParenRightDeeperPromote([A a]) {
+  a is B && (a is D && alwaysTrue(a = null)) && checkNotB(a);
+}
+
+main() {
+  ifSimple();
+  ifChainedAndsUnparenthesizedUnrelated();
+  ifChainedAndsUnparenthesizedRePromote();
+  ifChainedAndsUnparenthesizedAssignLast();
+  ifChainedAndsUnparenthesizedDeeperPromote();
+  ifChainedAndsParenLeftUnrelated();
+  ifChainedAndsParenLeftRePromote();
+  ifChainedAndsParenLeftAssignLast();
+  ifChainedAndsParenLeftDeeperPromote();
+  ifChainedAndsParenRightUnrelated();
+  ifChainedAndsParenRightRePromote();
+  ifChainedAndsParenRightAssignLast();
+  ifChainedAndsParenRightDeeperPromote();
+  conditionalSimple();
+  conditionalChainedAndsUnparenthesizedUnrelated();
+  conditionalChainedAndsUnparenthesizedRePromote();
+  conditionalChainedAndsUnparenthesizedAssignLast();
+  conditionalChainedAndsUnparenthesizedDeeperPromote();
+  conditionalChainedAndsParenLeftUnrelated();
+  conditionalChainedAndsParenLeftRePromote();
+  conditionalChainedAndsParenLeftAssignLast();
+  conditionalChainedAndsParenLeftDeeperPromote();
+  conditionalChainedAndsParenRightUnrelated();
+  conditionalChainedAndsParenRightRePromote();
+  conditionalChainedAndsParenRightAssignLast();
+  conditionalChainedAndsParenRightDeeperPromote();
+  andSimple();
+  andChainedAndsUnparenthesizedUnrelated();
+  andChainedAndsUnparenthesizedAssignLast();
+  andChainedAndsUnparenthesizedDeeperPromote();
+  andChainedAndsParenLeftUnrelated();
+  andChainedAndsParenLeftAssignLast();
+  andChainedAndsParenLeftDeeperPromote();
+  andChainedAndsParenRightUnrelated();
+  andChainedAndsParenRightRePromote();
+  andChainedAndsParenRightAssignLast();
+  andChainedAndsParenRightDeeperPromote();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_cascaded_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_cascaded_test.dart
new file mode 100644
index 0000000..9b65f00
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_cascaded_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment inside a complex promotion scope defeats all pending
+// promotions, whether introduced directly or through LHS or RHS of a logical
+// and expression.
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+class D extends B {}
+
+class E extends D {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+dynamic checkNotB(C c) => null;
+
+test([A a]) {
+  if (a is B && a is D) {
+    if (a is E) {
+      checkNotB(a);
+      a = null;
+    }
+  }
+}
+
+main() {
+  test();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_immediate_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_immediate_test.dart
new file mode 100644
index 0000000..f128749
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_immediate_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment inside a promotion scope defeats the promotion, even
+// if the assignment fills the scope (there are no intervening syntactic
+// constructs).
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+dynamic checkNotB(C c) => null;
+
+conditional([A a]) {
+  a is B ? a = checkNotB(a) : null;
+}
+
+ifStatementWithoutElse([A a]) {
+  if (a is B) a = checkNotB(a);
+}
+
+ifStatementWithElse([A a]) {
+  if (a is B)
+    a = checkNotB(a);
+  else
+    null;
+}
+
+ifElementWithoutElseList([A a]) {
+  [if (a is B) a = checkNotB(a)];
+}
+
+ifElementWithoutElseSet([A a]) {
+  ({if (a is B) a = checkNotB(a)});
+}
+
+ifElementWithoutElseMapKey([A a]) {
+  ({if (a is B) a = checkNotB(a): null});
+}
+
+ifElementWithoutElseMapValue([A a]) {
+  ({if (a is B) null: a = checkNotB(a)});
+}
+
+ifElementWithElseList([A a]) {
+  [if (a is B) a = checkNotB(a) else null];
+}
+
+ifElementWithElseSet([A a]) {
+  ({if (a is B) a = checkNotB(a) else null});
+}
+
+ifElementWithElseMapKey([A a]) {
+  ({if (a is B) a = checkNotB(a): null else null: null});
+}
+
+ifElementWithElseMapValue([A a]) {
+  ({if (a is B) null: a = checkNotB(a) else null: null});
+}
+
+logicalAnd([A a]) {
+  a is B && (a = checkNotB(a));
+}
+
+main() {
+  conditional();
+  ifStatementWithoutElse();
+  ifStatementWithElse();
+  ifElementWithoutElseList();
+  ifElementWithoutElseSet();
+  ifElementWithoutElseMapKey();
+  ifElementWithoutElseMapValue();
+  ifElementWithElseList();
+  ifElementWithElseSet();
+  ifElementWithElseMapKey();
+  ifElementWithElseMapValue();
+  logicalAnd();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_lhs_and_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_lhs_and_test.dart
new file mode 100644
index 0000000..f917dd4
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_lhs_and_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment on the left hand side of `&&` defeats promotion after
+// the entire `&&` expression, even if the promotion is on the right hand side
+// of `&&`.
+//
+// Note that it is not strictly necessary for soundness to defeat promotion
+// under this circumstance, but it is in the spec.
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+dynamic checkNotB(C c) => null;
+
+// An invocation of the form `alwaysTrue(x)` always returns `true` regardless of
+// `x`.
+bool alwaysTrue(dynamic x) => true;
+
+andChainedAndsUnparenthesizedRePromote([A a]) {
+  a is B && alwaysTrue(a = null) && a is B && checkNotB(a);
+}
+
+andChainedAndsParenLeftRePromote([A a]) {
+  (a is B && alwaysTrue(a = null)) && a is B && checkNotB(a);
+}
+
+main() {
+  andChainedAndsUnparenthesizedRePromote();
+  andChainedAndsParenLeftRePromote();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_bool_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_bool_test.dart
new file mode 100644
index 0000000..4df8b11
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_bool_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment inside a promotion scope defeats the promotion, even
+// if it is nested inside another unrelated promotion scope.
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+checkNotB(C c) {}
+
+// An invocation of the form `alwaysTrue(x)` always returns `true` regardless of
+// `x`.
+bool alwaysTrue(dynamic x) => true;
+
+noNesting([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a = null;
+  }
+}
+
+nestedInsideConditionalExpressionThen([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    b ? a = null : null;
+  }
+}
+
+nestedInsideConditionalExpressionElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    b ? null : a = null;
+  }
+}
+
+nestedInsideIfStatementThenNoElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    if (b) {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfStatementThenWithElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    if (b) {
+      a = null;
+    } else {}
+  }
+}
+
+nestedInsideIfStatementElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    if (b) {
+    } else {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfElementThenNoElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (b) alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideIfElementThenWithElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (b) alwaysTrue(a = null) else 0];
+  }
+}
+
+nestedInsideIfElementElse([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (b) 0 else alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideRhsOfAnd([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    b && alwaysTrue(a = null);
+  }
+}
+
+nestedInsideRhsOfOr([A a, bool b = true]) {
+  if (a is B) {
+    checkNotB(a);
+    b || alwaysTrue(a = null);
+  }
+}
+
+main() {
+  noNesting();
+  nestedInsideConditionalExpressionThen();
+  nestedInsideConditionalExpressionElse();
+  nestedInsideIfStatementThenNoElse();
+  nestedInsideIfStatementThenWithElse();
+  nestedInsideIfStatementElse();
+  nestedInsideIfElementThenNoElse();
+  nestedInsideIfElementThenWithElse();
+  nestedInsideIfElementElse();
+  nestedInsideRhsOfAnd();
+  nestedInsideRhsOfOr();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_test.dart
new file mode 100644
index 0000000..c87a85d
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_other_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment inside a promotion scope defeats the promotion, even
+// if it is nested inside another unrelated promotion scope.
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+checkNotB(C c) {}
+
+// An invocation of the form `alwaysTrue(x)` always returns `true` regardless of
+// `x`.
+bool alwaysTrue(dynamic x) => true;
+
+noNesting([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a = null;
+  }
+}
+
+nestedInsideConditionalExpressionThen([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    x is int ? a = null : null;
+  }
+}
+
+nestedInsideConditionalExpressionElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    x is int ? null : a = null;
+  }
+}
+
+nestedInsideIfStatementThenNoElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    if (x is int) {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfStatementThenWithElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    if (x is int) {
+      a = null;
+    } else {}
+  }
+}
+
+nestedInsideIfStatementElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    if (x is int) {
+    } else {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfElementThenNoElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (x is int) alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideIfElementThenWithElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (x is int) alwaysTrue(a = null) else 0];
+  }
+}
+
+nestedInsideIfElementElse([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (x is int) 0 else alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideRhsOfAnd([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    x is int && alwaysTrue(a = null);
+  }
+}
+
+nestedInsideRhsOfOr([A a, Object x]) {
+  if (a is B) {
+    checkNotB(a);
+    x is int || alwaysTrue(a = null);
+  }
+}
+
+main() {
+  noNesting();
+  nestedInsideConditionalExpressionThen();
+  nestedInsideConditionalExpressionElse();
+  nestedInsideIfStatementThenNoElse();
+  nestedInsideIfStatementThenWithElse();
+  nestedInsideIfStatementElse();
+  nestedInsideIfElementThenNoElse();
+  nestedInsideIfElementThenWithElse();
+  nestedInsideIfElementElse();
+  nestedInsideRhsOfAnd();
+  nestedInsideRhsOfOr();
+}
diff --git a/tests/language_2/type_promotion/assignment_defeats_promotion_nested_same_test.dart b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_same_test.dart
new file mode 100644
index 0000000..09a3785
--- /dev/null
+++ b/tests/language_2/type_promotion/assignment_defeats_promotion_nested_same_test.dart
@@ -0,0 +1,121 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that an assignment inside a promotion scope defeats the promotion, even
+// if it is nested inside another promotion scope that promotes the same
+// variable.
+
+class A {}
+
+class B extends A {}
+
+class C extends A {}
+
+class D extends B {}
+
+// An invocation of the form `checkNotB(x)` verifies that the static type of `x`
+// is not `B`, since `B` is not assignable to `C`.
+checkNotB(C c) {}
+
+// An invocation of the form `alwaysTrue(x)` always returns `true` regardless of
+// `x`.
+bool alwaysTrue(dynamic x) => true;
+
+noNesting([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a = null;
+  }
+}
+
+nestedInsideConditionalExpressionThen([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a is D ? a = null : null;
+  }
+}
+
+nestedInsideConditionalExpressionElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a is D ? null : a = null;
+  }
+}
+
+nestedInsideIfStatementThenNoElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    if (a is D) {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfStatementThenWithElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    if (a is D) {
+      a = null;
+    } else {}
+  }
+}
+
+nestedInsideIfStatementElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    if (a is D) {
+    } else {
+      a = null;
+    }
+  }
+}
+
+nestedInsideIfElementThenNoElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (a is D) alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideIfElementThenWithElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (a is D) alwaysTrue(a = null) else 0];
+  }
+}
+
+nestedInsideIfElementElse([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    [if (a is D) 0 else alwaysTrue(a = null)];
+  }
+}
+
+nestedInsideRhsOfAnd([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a is D && alwaysTrue(a = null);
+  }
+}
+
+nestedInsideRhsOfOr([A a]) {
+  if (a is B) {
+    checkNotB(a);
+    a is D || alwaysTrue(a = null);
+  }
+}
+
+main() {
+  noNesting();
+  nestedInsideConditionalExpressionThen();
+  nestedInsideConditionalExpressionElse();
+  nestedInsideIfStatementThenNoElse();
+  nestedInsideIfStatementThenWithElse();
+  nestedInsideIfStatementElse();
+  nestedInsideIfElementThenNoElse();
+  nestedInsideIfElementThenWithElse();
+  nestedInsideIfElementElse();
+  nestedInsideRhsOfAnd();
+  nestedInsideRhsOfOr();
+}
diff --git a/tests/language_2/type_promotion/logical_and_test.dart b/tests/language_2/type_promotion/logical_and_test.dart
index 79945ba..8168615 100644
--- a/tests/language_2/type_promotion/logical_and_test.dart
+++ b/tests/language_2/type_promotion/logical_and_test.dart
@@ -34,6 +34,7 @@
     b = a.d;
     //    ^
     // [analyzer] COMPILE_TIME_ERROR.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'A'.
   }
   if (a is D && (b = a.d)) {
     b = a.d;
diff --git a/tests/language_2/vm/regress_flutter_55345_const_test.dart b/tests/language_2/vm/regress_flutter_55345_const_test.dart
deleted file mode 100644
index 9b548ff..0000000
--- a/tests/language_2/vm/regress_flutter_55345_const_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Verifies that references to deduplicated mixins are properly updated
-// in types which are only accessible through constants.
-// Regression test for https://github.com/flutter/flutter/issues/55345.
-
-class Diagnosticable {}
-
-class SomeClass with Diagnosticable {}
-
-class State<T> with Diagnosticable {
-  const State();
-}
-
-class StateA extends State {
-  const StateA();
-}
-
-class StateB extends State<int> {
-  const StateB();
-}
-
-const c1 = StateA();
-const c2 = StateB();
-
-main() {
-  print(const [
-    {
-      (c1 ?? c2): [
-        [c1 ?? c2]
-      ]
-    },
-    'abc'
-  ]);
-}
diff --git a/tests/language_2/vm/regress_flutter_55345_test.dart b/tests/language_2/vm/regress_flutter_55345_test.dart
deleted file mode 100644
index f5ee00a..0000000
--- a/tests/language_2/vm/regress_flutter_55345_test.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Verifies that references to deduplicated mixins are properly updated.
-// Regression test for https://github.com/flutter/flutter/issues/55345.
-
-class Diagnosticable {}
-
-class SomeClass with Diagnosticable {}
-
-class State<T> with Diagnosticable {}
-
-class StateA extends State {}
-
-class StateB extends State<int> {}
-
-StateA a = StateA();
-StateB b = StateB();
-
-List<T> foo<T>(T x) {
-  print(T);
-  return <T>[x];
-}
-
-T Function<S extends T>(T) bar<T>(T x) {
-  print(T);
-
-  return <S extends T>(T y) {
-    print(S);
-    print(y);
-    return y;
-  };
-}
-
-main() {
-  State x1 = a ?? b;
-  print(x1);
-
-  var x2 = a ?? b;
-  var x3 = foo(x2);
-  var x4 = bar(x3);
-  x4(x3);
-}
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart
index b084c86..f2d9710 100644
--- a/tests/lib/async/future_test.dart
+++ b/tests/lib/async/future_test.dart
@@ -143,6 +143,17 @@
     Expect.equals(3, after2);
     asyncEnd();
   });
+
+  // Regression test for fix to issue:
+  // https://github.com/dart-lang/sdk/issues/43445
+  asyncStart();
+  Future.wait<int>(<Future<int>>[]).then((list) {
+    Expect.equals(0, list.length);
+    Expect.type<List<int>>(list);
+    Expect.notType<List<Null>>(list);
+    Expect.notType<List<Never>>(list);
+    asyncEnd();
+  });
 }
 
 // Tests for [catchError]
diff --git a/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart b/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart
deleted file mode 100644
index 2c827b8..0000000
--- a/tests/lib/html/js_typed_interop_anonymous2_exp_test.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous2, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous2_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class A {
-  external factory A({B? b});
-
-  external B? get b;
-}
-
-@JS()
-@anonymous
-class B {
-  external factory B({C? c});
-
-  external C? get c;
-}
-
-@JS()
-@anonymous
-class C {
-  external factory C();
-}
-
-// D is unreachable, and that is OK
-@JS()
-@anonymous
-class D {
-  external factory D();
-}
-
-main() {
-  test('simple', () {
-    var b = new B();
-    var a = new A(b: b);
-    expect(a.b, equals(b));
-    expect(b.c, isNull);
-  });
-}
diff --git a/tests/lib/html/js_typed_interop_anonymous_exp_test.dart b/tests/lib/html/js_typed_interop_anonymous_exp_test.dart
deleted file mode 100644
index e160bdd..0000000
--- a/tests/lib/html/js_typed_interop_anonymous_exp_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class Literal {
-  external factory Literal({int? x, String? y, num? z});
-
-  external int? get x;
-  external String? get y;
-  external num? get z;
-}
-
-main() {
-  test('simple', () {
-    var l = new Literal(x: 3, y: "foo");
-    expect(l.x, equals(3));
-    expect(l.y, equals("foo"));
-    expect(l.z, isNull);
-  });
-}
diff --git a/tests/lib/html/js_typed_interop_anonymous_unreachable_exp_test.dart b/tests/lib/html/js_typed_interop_anonymous_unreachable_exp_test.dart
deleted file mode 100644
index 046dcff..0000000
--- a/tests/lib/html/js_typed_interop_anonymous_unreachable_exp_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous_unreachable, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous_unreachable_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class Literal {
-  external factory Literal({required int x, required String y, required num z});
-
-  external int get x;
-  external String get y;
-  external num get z;
-}
-
-main() {
-  test('nothing to do', () {
-    // This test is empty, but it is a regression for Issue# 24974: dart2js
-    // would crash trying to compile code that used @anonymous and that was
-    // not reachable from main.
-  });
-}
diff --git a/tests/lib/html/js_typed_interop_side_cast_exp_test.dart b/tests/lib/html/js_typed_interop_side_cast_exp_test.dart
deleted file mode 100644
index be112c8..0000000
--- a/tests/lib/html/js_typed_interop_side_cast_exp_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Similar test to js_typed_interop_side_cast, but because we are using the
-// --experimental-trust-js-interop-type-annotations flag, we test a slightly
-// different behavior.
-@JS()
-library js_typed_interop_side_cast_exp_test;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class A {
-  external int get x;
-  external factory A({required int x});
-}
-
-@JS()
-@anonymous
-class B {
-  external int get x;
-  external factory B({required int x});
-}
-
-@JS()
-@anonymous
-class C {
-  external int get x;
-  external factory C({required int x});
-}
-
-main() {
-  test('side-casts work for reachable types', () {
-    new C(x: 3); // make C reachable
-    dynamic a = new A(x: 3);
-    expect(a is C, isTrue);
-    C c = a;
-    expect(c.x, equals(3));
-  });
-
-  // Note: this test would fail without the experimental flag.
-  test('side-casts do not work for unreachable types', () {
-    dynamic a = new A(x: 3);
-    expect(a is B, isFalse); //# 01: ok
-  });
-}
diff --git a/tests/lib/isolate/detect_nullsafety_helper.dart b/tests/lib/isolate/detect_nullsafety_helper.dart
index c8c263c..7f66ab8 100644
--- a/tests/lib/isolate/detect_nullsafety_helper.dart
+++ b/tests/lib/isolate/detect_nullsafety_helper.dart
@@ -28,6 +28,8 @@
   args.add("--enable-experiment=non-nullable");
   args.add(sourcePath);
   var result = Process.runSync(exec, args);
+  print('snapshot $type stdout: ${result.stdout}');
+  print('snapshot $type stderr: ${result.stderr}');
 }
 
 void generateKernel(String sourcePath, String outPath) {
@@ -44,6 +46,8 @@
   args.add("--enable-experiment=non-nullable");
   args.add(filePath);
   var result = Process.runSync(exec, args);
+  print('test stdout: ${result.stdout}');
+  print('test stderr: ${result.stderr}');
   expect(result.stdout.contains('$expected'), true);
 }
 
diff --git a/tests/lib/isolate/nnbd_spawn_autodetect_helper.dart b/tests/lib/isolate/nnbd_spawn_autodetect_helper.dart
index e689636..d0eaeac 100644
--- a/tests/lib/isolate/nnbd_spawn_autodetect_helper.dart
+++ b/tests/lib/isolate/nnbd_spawn_autodetect_helper.dart
@@ -54,6 +54,8 @@
   args.add("--enable-experiment=non-nullable");
   args.add(sourcePath);
   var result = Process.runSync(exec, args);
+  print('snapshot $type stdout: ${result.stdout}');
+  print('snapshot $type stderr: ${result.stderr}');
 }
 
 void generateKernel(String sourcePath, String outPath) {
@@ -70,5 +72,7 @@
   args.add("--enable-experiment=non-nullable");
   args.add(filePath);
   var result = Process.runSync(exec, args);
+  print('test stdout: ${result.stdout}');
+  print('test stderr: ${result.stderr}');
   expect(result.stdout.contains('$expected'), true);
 }
diff --git a/tests/lib/js/external_member_static_test.dart b/tests/lib/js/external_member_static_test.dart
new file mode 100644
index 0000000..f0fcdf7
--- /dev/null
+++ b/tests/lib/js/external_member_static_test.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Tests static errors for JS interop members without an external keyword.
+
+@JS()
+library external_member_static_test;
+
+import 'package:js/js.dart';
+
+@JS()
+class JSClass {
+  int? field;
+
+  @JS()
+  int? fieldWithJS;
+
+  static int? staticField;
+
+  @JS()
+  static int? staticFieldWithJS;
+
+  JSClass.constructor();
+//^
+// [web] JS interop classes do not support non-external constructors.
+  @JS()
+  JSClass.constructorWithJS();
+//^
+// [web] JS interop classes do not support non-external constructors.
+
+  // Dart factories of a JS interop class are allowed.
+  factory JSClass.fact() => JSClass.constructor();
+
+  factory JSClass.redirectingFactory() = JSClass.constructor;
+
+  external factory JSClass.externalFactory();
+
+  @JS()
+  factory JSClass.factoryWithJS() => JSClass.fact();
+
+  int get getSet => 0;
+  //      ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  int get getSetWithJS => 0;
+  //      ^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  set getSet(int val) {}
+  //  ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  set getSetWithJS(int val) {}
+  //  ^^^^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  int method() => 0;
+  //  ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  int methodWithJS() => 0;
+  //  ^^^^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+
+  // Static methods on JS interop classes are allowed.
+  static int staticMethod() => 0;
+
+  @JS()
+  static int staticMethodWithJS() => 0;
+}
+
+@JS()
+@anonymous
+class JSAnonymousClass {
+  int? field;
+
+  @JS()
+  int? fieldWithJS;
+
+  static int? staticField;
+
+  @JS()
+  static int? staticFieldWithJS;
+
+  JSAnonymousClass.constructor();
+//^
+// [web] JS interop classes do not support non-external constructors.
+  @JS()
+  JSAnonymousClass.constructorWithJS();
+//^
+// [web] JS interop classes do not support non-external constructors.
+
+  factory JSAnonymousClass.fact() => JSAnonymousClass.constructor();
+
+  factory JSAnonymousClass.redirectingFactory() = JSAnonymousClass.fact;
+
+  external factory JSAnonymousClass.externalFactory();
+
+  @JS()
+  factory JSAnonymousClass.factoryWithJS() => JSAnonymousClass.fact();
+
+  int get getSet => 0;
+  //      ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  int get getSetWithJS => 0;
+  //      ^^^^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  set getSet(int val) {}
+  //  ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  set getSetWithJS(int val) {}
+  //  ^^^^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  int method() => 0;
+  //  ^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+  @JS()
+  int methodWithJS() => 0;
+  //  ^^^^^^^^^^^^
+  // [web] This JS interop member must be annotated with `external`. Only factories and static methods can be non-external.
+
+  static int staticMethod() => 0;
+
+  @JS()
+  static int staticMethodWithJS() => 0;
+}
+
+@JS()
+abstract class JSAbstractClass {
+  int? field;
+
+  @JS()
+  int? fieldWithJS;
+
+  static int? staticField;
+
+  @JS()
+  static int? staticFieldWithJS;
+
+  JSAbstractClass.constructor();
+//^
+// [web] JS interop classes do not support non-external constructors.
+  @JS()
+  JSAbstractClass.constructorWithJS();
+//^
+// [web] JS interop classes do not support non-external constructors.
+
+  factory JSAbstractClass.fact() => JSAbstractClass.factoryWithJS();
+
+  factory JSAbstractClass.redirectingFactory() = JSAbstractClass.fact;
+
+  external factory JSAbstractClass.externalFactory();
+
+  @JS()
+  factory JSAbstractClass.factoryWithJS() => JSAbstractClass.fact();
+
+  // Members in an abstract class are allowed.
+  int get getSet;
+
+  @JS()
+  int get getSetWithJS;
+
+  set getSet(int val);
+
+  @JS()
+  set getSetWithJS(int val);
+
+  int method();
+
+  @JS()
+  int methodWithJS();
+
+  static int staticMethod() => 0;
+
+  @JS()
+  static int staticMethodWithJS() => 0;
+}
+
+@JS()
+class JSClassWithSyntheticConstructor {}
+
+@JS()
+int? globalWithJS;
+@JS()
+int get getSetWithJS => 0;
+@JS()
+set getSetWithJS(int val) {}
+@JS()
+int methodWithJS() => 0;
+
+external int get getSet;
+external set getSet(int val);
+external int method();
+
+main() {}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 8d88c56..43d6d0e 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -61,7 +61,7 @@
 [ $arch == simarm || $arch == simarmv6 ]
 convert/utf85_test: Skip # Pass, Slow Issue 12644.
 
-[ $arch != x64 || $compiler == dartkb || $runtime != vm ]
+[ $arch != x64 || $runtime != vm ]
 isolate/int32_length_overflow_test: SkipSlow
 
 [ $mode == product || $runtime != vm ]
diff --git a/tests/lib/lib_kernel.status b/tests/lib/lib_kernel.status
index 8151fcf..03ac748 100644
--- a/tests/lib/lib_kernel.status
+++ b/tests/lib/lib_kernel.status
@@ -6,20 +6,17 @@
 
 isolate/ping_pause_test: Skip # Issue https://dartbug.com/37787
 
-[ $compiler == dartkb ]
-isolate/isolate_complex_messages_test: Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
-
 [ $compiler == fasta ]
 html/*: Skip # TODO(ahe): Make dart:html available.
 js/*: Skip # TODO(ahe): Make dart:js available.
 
-[ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == x64 && $compiler == dartk && $mode == debug && $runtime == vm ]
 mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
 
 [ $arch == x64 && ($hot_reload || $hot_reload_rollback) ]
 convert/base64_test/01: Crash # http://dartbug.com/35948
 
-[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
 mirrors/invocation_fuzz_test/emptyarray: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
 mirrors/invocation_fuzz_test/false: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
 mirrors/invocation_fuzz_test/none: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
@@ -29,6 +26,33 @@
 [ $compiler == app_jitk && ($mode == product || $mode == release) ]
 isolate/spawn_uri_nested_vm_test: Skip # Timeout, Issue 33385
 
+[ $compiler == dartk && $mode == debug && $runtime == vm ]
+mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
+
+[ $compiler == dartk && $mode == debug && $hot_reload_rollback ]
+isolate/message3_test/constList_identical: Skip # Timeout
+
+# ===== dartk + vm status lines =====
+[ $compiler == dartk && $runtime == vm ]
+html/*: SkipByDesign # dart:html not supported on VM.
+isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/static_function_test: Skip # Times out. Issue 31855. CompileTimeError. Issue 31402
+mirrors/invocation_fuzz_test: Crash
+mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
+mirrors/native_class_test: SkipByDesign # Imports dart:html
+
+[ $compiler == dartk && $hot_reload_rollback ]
+isolate/illegal_msg_function_test: Skip # Timeout
+isolate/pause_test: Skip # Timeout
+
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+isolate/message4_test: Crash # Timeout and sporadic crash (issue 33824)
+mirrors/dynamic_load_test: Skip # Reload has an effect similar to deleting the dynamically loaded library
+mirrors/immutable_collections_test: Pass, Slow
+mirrors/mirrors_reader_test: Pass, Slow
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/issues/30063).
 
@@ -40,34 +64,7 @@
 isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
 mirrors/*: SkipByDesign # Mirrors are not supported in AOT mode.
 
-[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
-
-[ $mode == debug && $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-isolate/message3_test/constList_identical: Skip # Timeout
-
-# ===== dartk + vm status lines =====
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-html/*: SkipByDesign # dart:html not supported on VM.
-isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/static_function_test: Skip # Times out. Issue 31855. CompileTimeError. Issue 31402
-mirrors/invocation_fuzz_test: Crash
-mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
-mirrors/native_class_test: SkipByDesign # Imports dart:html
-
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-isolate/illegal_msg_function_test: Skip # Timeout
-isolate/pause_test: Skip # Timeout
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-isolate/message4_test: Crash # Timeout and sporadic crash (issue 33824)
-mirrors/dynamic_load_test: Skip # Reload has an effect similar to deleting the dynamically loaded library
-mirrors/immutable_collections_test: Pass, Slow
-mirrors/mirrors_reader_test: Pass, Slow
-
-[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
 html/*: SkipByDesign
 js/*: SkipByDesign
 
diff --git a/tests/lib/lib_vm.status b/tests/lib/lib_vm.status
index ae42a72..77a53e5 100644
--- a/tests/lib/lib_vm.status
+++ b/tests/lib/lib_vm.status
@@ -17,7 +17,7 @@
 [ $arch == simarm64 && $runtime == vm ]
 convert/utf85_test: Skip # Pass, Slow Issue 20111.
 
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm ]
 async/future_or_only_in_async_test/00: MissingCompileTimeError
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
 html/*: SkipByDesign # dart:html not supported on VM.
@@ -34,7 +34,7 @@
 mirrors/redirecting_factory_test/01: RuntimeError
 mirrors/redirecting_factory_test/none: RuntimeError
 
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && !$checked ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm && !$checked ]
 mirrors/inference_and_no_such_method_test: RuntimeError
 
 [ $runtime == vm && $system == fuchsia ]
@@ -75,6 +75,16 @@
 mirrors/library_uri_io_test: RuntimeError
 mirrors/library_uri_package_test: RuntimeError
 
+[ $runtime == vm && $system == windows ]
+isolate/detect_nullsafety_1_test: Skip # Issue 43583
+isolate/detect_nullsafety_2_test: Skip # Issue 43583
+isolate/nnbd_spawn_autodetect_1_test: Skip # Issue 43583
+isolate/nnbd_spawn_autodetect_2_test: Skip # Issue 43583
+isolate/nnbd_spawnuri_autodetect_1_test: Skip # Issue 43583
+isolate/nnbd_spawnuri_autodetect_2_test: Skip # Issue 43583
+isolate/nnbd_spawnuri_autodetect_3_test: Skip # Issue 43583
+isolate/nnbd_spawnuri_autodetect_4_test: Skip # Issue 43583
+
 [ $runtime == vm && ($arch == simarm || $arch == simarmv6) ]
 convert/utf85_test: Skip # Pass, Slow Issue 12644.
 
diff --git a/tests/lib/mirrors/library_uri_package_test.dart b/tests/lib/mirrors/library_uri_package_test.dart
index 0116005..e546722 100644
--- a/tests/lib/mirrors/library_uri_package_test.dart
+++ b/tests/lib/mirrors/library_uri_package_test.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// Test library uri for a library read as a package .
+// Test library uri for a library read as a package.
 
 library MirrorsTest;
 
 import 'dart:mirrors';
-import 'package:args/args.dart';
+import 'package:expect/expect.dart';
 import 'package:async_helper/async_minitest.dart';
 
 testLibraryUri(var value, Uri expectedUri) {
@@ -26,6 +26,6 @@
   var mirrors = currentMirrorSystem();
   test("Test package library uri", () {
     testLibraryUri(
-        new ArgParser(), Uri.parse('package:args/src/arg_parser.dart'));
+        ExpectException(""), Uri.parse('package:expect/expect.dart'));
   });
 }
diff --git a/tests/lib/wasm/basic_test.dart b/tests/lib/wasm/basic_test.dart
index b6dfaa9..da2fb9a 100644
--- a/tests/lib/wasm/basic_test.dart
+++ b/tests/lib/wasm/basic_test.dart
@@ -5,7 +5,7 @@
 // Test that we can load a wasm module, find a function, and call it.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -21,8 +21,10 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
-  int n = fn.call([1234]);
+  var fn = inst.lookupFunction("square");
+  int n = fn(1234);
 
   Expect.equals(1234 * 1234, n);
+
+  Expect.isNull(inst.lookupFunction("not_a_function"));
 }
diff --git a/tests/lib/wasm/corrupted_error_test.dart b/tests/lib/wasm/corrupted_error_test.dart
index fcc4085..2b8d3fa 100644
--- a/tests/lib/wasm/corrupted_error_test.dart
+++ b/tests/lib/wasm/corrupted_error_test.dart
@@ -5,7 +5,7 @@
 // Test error thrown when the wasm module is corrupted.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -16,5 +16,5 @@
     0x7e, 0x0b,
   ]);
 
-  Expect.throwsArgumentError(() => WasmModule(data));
+  Expect.throws(() => WasmModule(data));
 }
diff --git a/tests/lib/wasm/fn_call_error_test.dart b/tests/lib/wasm/fn_call_error_test.dart
index 932afa3..0c74768 100644
--- a/tests/lib/wasm/fn_call_error_test.dart
+++ b/tests/lib/wasm/fn_call_error_test.dart
@@ -5,7 +5,7 @@
 // Test error thrown when a function is called with the wrong args.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -21,9 +21,9 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+  var fn = inst.lookupFunction("square");
 
-  Expect.throwsArgumentError(() => fn.call([]));
-  Expect.throwsArgumentError(() => fn.call([1, 2, 3]));
-  Expect.throwsArgumentError(() => fn.call([1.23]));
+  Expect.throwsArgumentError(() => fn());
+  Expect.throwsArgumentError(() => fn(1, 2, 3));
+  Expect.throwsArgumentError(() => fn(1.23));
 }
diff --git a/tests/lib/wasm/fn_mismatch_error_test.dart b/tests/lib/wasm/fn_mismatch_error_test.dart
deleted file mode 100644
index 413260e..0000000
--- a/tests/lib/wasm/fn_mismatch_error_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test error thrown when the loaded function can't be found.
-
-import "package:expect/expect.dart";
-import "dart:wasm";
-import "dart:typed_data";
-
-void main() {
-  // int64_t square(int64_t n) { return n * n; }
-  var data = Uint8List.fromList([
-    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
-    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
-    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
-    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
-    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
-    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
-    0x7e, 0x0b,
-  ]);
-
-  var inst = WasmModule(data).instantiate(WasmImports());
-  Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Int64)>("blah"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function()>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Int64, Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Void Function(Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Void Function(dynamic)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Float)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Float Function(Int64)>("square"));
-}
diff --git a/tests/lib/wasm/memory_error_test.dart b/tests/lib/wasm/memory_error_test.dart
index e866bf0..3a172d8 100644
--- a/tests/lib/wasm/memory_error_test.dart
+++ b/tests/lib/wasm/memory_error_test.dart
@@ -5,11 +5,13 @@
 // Test errors thrown by WasmMemory.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
-  Expect.throwsArgumentError(() => WasmMemory(1000000000));
-  var mem = WasmMemory(1000);
-  Expect.throwsArgumentError(() => mem.grow(1000000000));
+  Expect.throws(() => WasmMemory(1000000000));
+  var mem = WasmMemory(100);
+  Expect.throws(() => mem.grow(1000000000));
+  mem = WasmMemory(100, 200);
+  Expect.throws(() => mem.grow(300));
 }
diff --git a/tests/lib/wasm/memory_test.dart b/tests/lib/wasm/memory_test.dart
index 52d12c3..ecaf433 100644
--- a/tests/lib/wasm/memory_test.dart
+++ b/tests/lib/wasm/memory_test.dart
@@ -5,22 +5,19 @@
 // Test that we can create a WasmMemory, edit it, and grow it.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
-  var mem = WasmMemory(1000);
-  Expect.equals(1000, mem.lengthInPages);
-  Expect.equals(1000 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  var mem = WasmMemory(100);
+  Expect.equals(100, mem.lengthInPages);
+  Expect.equals(100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
 
   mem[123] = 45;
   Expect.equals(45, mem[123]);
 
-  mem.grow(100);
-  Expect.equals(1100, mem.lengthInPages);
-  Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  mem.grow(10);
+  Expect.equals(110, mem.lengthInPages);
+  Expect.equals(110 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
   Expect.equals(45, mem[123]);
-
-  Expect.throwsArgumentError(() => WasmMemory(1000000000));
-  Expect.throwsArgumentError(() => mem.grow(1000000000));
 }
diff --git a/tests/lib/wasm/numerics_test.dart b/tests/lib/wasm/numerics_test.dart
index 8651caa..158549a 100644
--- a/tests/lib/wasm/numerics_test.dart
+++ b/tests/lib/wasm/numerics_test.dart
@@ -5,7 +5,7 @@
 // Test numeric types.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -30,20 +30,20 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var addI64 = inst.lookupFunction<Int64 Function(Int64, Int64)>("addI64");
-  var addI32 = inst.lookupFunction<Int32 Function(Int32, Int32)>("addI32");
-  var addF64 = inst.lookupFunction<Double Function(Double, Double)>("addF64");
-  var addF32 = inst.lookupFunction<Float Function(Float, Float)>("addF32");
+  var addI64 = inst.lookupFunction("addI64");
+  var addI32 = inst.lookupFunction("addI32");
+  var addF64 = inst.lookupFunction("addF64");
+  var addF32 = inst.lookupFunction("addF32");
 
-  int i64 = addI64.call([0x123456789ABCDEF, 0xFEDCBA987654321]);
+  int i64 = addI64(0x123456789ABCDEF, 0xFEDCBA987654321);
   Expect.equals(0x1111111111111110, i64);
 
-  int i32 = addI32.call([0xABCDEF, 0xFEDCBA]);
+  int i32 = addI32(0xABCDEF, 0xFEDCBA);
   Expect.equals(0x1aaaaa9, i32);
 
-  double f64 = addF64.call([1234.5678, 8765.4321]);
+  double f64 = addF64(1234.5678, 8765.4321);
   Expect.approxEquals(9999.9999, f64, 1e-6);
 
-  double f32 = addF32.call([1234.5678, 8765.4321]);
+  double f32 = addF32(1234.5678, 8765.4321);
   Expect.approxEquals(9999.9999, f32, 1e-3);
 }
diff --git a/tests/lib/wasm/void_test.dart b/tests/lib/wasm/void_test.dart
index fe3bd94..fe94693 100644
--- a/tests/lib/wasm/void_test.dart
+++ b/tests/lib/wasm/void_test.dart
@@ -5,7 +5,7 @@
 // Test functions with void return type, and functions that take no args.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -26,9 +26,9 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var setFn = inst.lookupFunction<Void Function(Int64, Int64)>("set");
-  var getFn = inst.lookupFunction<Int64 Function()>("get");
-  Expect.isNull(setFn.call([123, 456]));
-  int n = getFn.call([]);
+  var setFn = inst.lookupFunction("set");
+  var getFn = inst.lookupFunction("get");
+  Expect.isNull(setFn(123, 456));
+  int n = getFn();
   Expect.equals(123 + 456, n);
 }
diff --git a/tests/lib_2/async/future_test.dart b/tests/lib_2/async/future_test.dart
index 3a4f09d..6c227cf 100644
--- a/tests/lib_2/async/future_test.dart
+++ b/tests/lib_2/async/future_test.dart
@@ -140,6 +140,17 @@
     Expect.equals(3, after2);
     asyncEnd();
   });
+
+  // Regression test for fix to issue:
+  // https://github.com/dart-lang/sdk/issues/43445
+  asyncStart();
+  Future.wait<int>(<Future<int>>[]).then((list) {
+    Expect.equals(0, list.length);
+    Expect.type<List<int>>(list);
+    Expect.notType<List<Null>>(list);
+    Expect.notType<List<Never>>(list);
+    asyncEnd();
+  });
 }
 
 // Tests for [catchError]
diff --git a/tests/lib_2/html/js_typed_interop_anonymous2_exp_test.dart b/tests/lib_2/html/js_typed_interop_anonymous2_exp_test.dart
deleted file mode 100644
index ba4afc2..0000000
--- a/tests/lib_2/html/js_typed_interop_anonymous2_exp_test.dart
+++ /dev/null
@@ -1,54 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-//
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous2, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous2_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class A {
-  external factory A({B b});
-
-  external B get b;
-}
-
-@JS()
-@anonymous
-class B {
-  external factory B({C c});
-
-  external C get c;
-}
-
-@JS()
-@anonymous
-class C {
-  external factory C();
-}
-
-// D is unreachable, and that is OK
-@JS()
-@anonymous
-class D {
-  external factory D();
-}
-
-main() {
-  test('simple', () {
-    var b = new B();
-    var a = new A(b: b);
-    expect(a.b, equals(b));
-    expect(b.c, isNull);
-  });
-}
diff --git a/tests/lib_2/html/js_typed_interop_anonymous_exp_test.dart b/tests/lib_2/html/js_typed_interop_anonymous_exp_test.dart
deleted file mode 100644
index 362a41c..0000000
--- a/tests/lib_2/html/js_typed_interop_anonymous_exp_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-//
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class Literal {
-  external factory Literal({int x, String y, num z});
-
-  external int get x;
-  external String get y;
-  external num get z;
-}
-
-main() {
-  test('simple', () {
-    var l = new Literal(x: 3, y: "foo");
-    expect(l.x, equals(3));
-    expect(l.y, equals("foo"));
-    expect(l.z, isNull);
-  });
-}
diff --git a/tests/lib_2/html/js_typed_interop_anonymous_unreachable_exp_test.dart b/tests/lib_2/html/js_typed_interop_anonymous_unreachable_exp_test.dart
deleted file mode 100644
index 95c6141..0000000
--- a/tests/lib_2/html/js_typed_interop_anonymous_unreachable_exp_test.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-//
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Same test as js_typed_interop_anonymous_unreachable, but using the
-// --experimental-trust-js-interop-type-annotations flag.
-@JS()
-library js_typed_interop_anonymous_unreachable_exp_test;
-
-import 'dart:html';
-import 'dart:js' as js;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class Literal {
-  external factory Literal({int x, String y, num z});
-
-  external int get x;
-  external String get y;
-  external num get z;
-}
-
-main() {
-  test('nothing to do', () {
-    // This test is empty, but it is a regression for Issue# 24974: dart2js
-    // would crash trying to compile code that used @anonymous and that was
-    // not reachable from main.
-  });
-}
diff --git a/tests/lib_2/html/js_typed_interop_side_cast_exp_test.dart b/tests/lib_2/html/js_typed_interop_side_cast_exp_test.dart
deleted file mode 100644
index a5061fb..0000000
--- a/tests/lib_2/html/js_typed_interop_side_cast_exp_test.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-// 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
-// BSD-style license that can be found in the LICENSE file.
-//
-// SharedOptions=--experimental-trust-js-interop-type-annotations
-
-// Similar test to js_typed_interop_side_cast, but because we are using the
-// --experimental-trust-js-interop-type-annotations flag, we test a slightly
-// different behavior.
-@JS()
-library js_typed_interop_side_cast_exp_test;
-
-import 'package:js/js.dart';
-import 'package:expect/minitest.dart';
-
-@JS()
-@anonymous
-class A {
-  external int get x;
-  external factory A({int x});
-}
-
-@JS()
-@anonymous
-class B {
-  external int get x;
-  external factory B({int x});
-}
-
-@JS()
-@anonymous
-class C {
-  external int get x;
-  external factory C({int x});
-}
-
-main() {
-  test('side-casts work for reachable types', () {
-    new C(x: 3); // make C reachable
-    dynamic a = new A(x: 3);
-    expect(a is C, isTrue);
-    C c = a;
-    expect(c.x, equals(3));
-  });
-
-  // Note: this test would fail without the experimental flag.
-  test('side-casts do not work for unreachable types', () {
-    dynamic a = new A(x: 3);
-    expect(a is B, isFalse); //# 01: ok
-  });
-}
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 843b50a..535b366 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -61,7 +61,7 @@
 [ $arch == simarm || $arch == simarmv6 ]
 convert/utf85_test: Skip # Pass, Slow Issue 12644.
 
-[ $arch != x64 || $compiler == dartkb || $runtime != vm ]
+[ $arch != x64 || $runtime != vm ]
 isolate/int32_length_overflow_test: SkipSlow
 
 [ $mode == product || $runtime != vm ]
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index a1866a5..03ac748 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -6,21 +6,17 @@
 
 isolate/ping_pause_test: Skip # Issue https://dartbug.com/37787
 
-[ $compiler == dartkb ]
-async/stream_state_nonzero_timer_test: Skip # Issues 42331, 42073
-isolate/isolate_complex_messages_test: Crash # runtime/vm/object.cc: 17395: error: expected: type_arguments.IsNull() || type_arguments.IsCanonical()
-
 [ $compiler == fasta ]
 html/*: Skip # TODO(ahe): Make dart:html available.
 js/*: Skip # TODO(ahe): Make dart:js available.
 
-[ $arch == x64 && $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == x64 && $compiler == dartk && $mode == debug && $runtime == vm ]
 mirrors/invocation_fuzz_test: Skip # Because it times out, issue 29439.
 
 [ $arch == x64 && ($hot_reload || $hot_reload_rollback) ]
 convert/base64_test/01: Crash # http://dartbug.com/35948
 
-[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
 mirrors/invocation_fuzz_test/emptyarray: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
 mirrors/invocation_fuzz_test/false: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
 mirrors/invocation_fuzz_test/none: Crash # Flaky on vm-kernel-optcounter-threshold-linux-release-x64, bug #31838
@@ -30,6 +26,33 @@
 [ $compiler == app_jitk && ($mode == product || $mode == release) ]
 isolate/spawn_uri_nested_vm_test: Skip # Timeout, Issue 33385
 
+[ $compiler == dartk && $mode == debug && $runtime == vm ]
+mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
+
+[ $compiler == dartk && $mode == debug && $hot_reload_rollback ]
+isolate/message3_test/constList_identical: Skip # Timeout
+
+# ===== dartk + vm status lines =====
+[ $compiler == dartk && $runtime == vm ]
+html/*: SkipByDesign # dart:html not supported on VM.
+isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
+isolate/static_function_test: Skip # Times out. Issue 31855. CompileTimeError. Issue 31402
+mirrors/invocation_fuzz_test: Crash
+mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
+mirrors/native_class_test: SkipByDesign # Imports dart:html
+
+[ $compiler == dartk && $hot_reload_rollback ]
+isolate/illegal_msg_function_test: Skip # Timeout
+isolate/pause_test: Skip # Timeout
+
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+isolate/message4_test: Crash # Timeout and sporadic crash (issue 33824)
+mirrors/dynamic_load_test: Skip # Reload has an effect similar to deleting the dynamically loaded library
+mirrors/immutable_collections_test: Pass, Slow
+mirrors/mirrors_reader_test: Pass, Slow
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 isolate/static_function_test: Skip # Flaky (https://github.com/dart-lang/sdk/issues/30063).
 
@@ -41,34 +64,7 @@
 isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
 mirrors/*: SkipByDesign # Mirrors are not supported in AOT mode.
 
-[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-mirrors/other_declarations_location_test: Crash # Issue 33325 (assertion error, TypeParameter not having position).
-
-[ $mode == debug && $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-isolate/message3_test/constList_identical: Skip # Timeout
-
-# ===== dartk + vm status lines =====
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-html/*: SkipByDesign # dart:html not supported on VM.
-isolate/deferred_in_isolate2_test: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/deferred_in_isolate_test: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/issue_21398_parent_isolate2_test/01: Skip # Times out. Deferred loading kernel issue 28335.
-isolate/static_function_test: Skip # Times out. Issue 31855. CompileTimeError. Issue 31402
-mirrors/invocation_fuzz_test: Crash
-mirrors/metadata_allowed_values_test/16: Skip # Flaky, crashes.
-mirrors/native_class_test: SkipByDesign # Imports dart:html
-
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-isolate/illegal_msg_function_test: Skip # Timeout
-isolate/pause_test: Skip # Timeout
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-isolate/message4_test: Crash # Timeout and sporadic crash (issue 33824)
-mirrors/dynamic_load_test: Skip # Reload has an effect similar to deleting the dynamically loaded library
-mirrors/immutable_collections_test: Pass, Slow
-mirrors/mirrors_reader_test: Pass, Slow
-
-[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkb || $compiler == dartkp ]
+[ $compiler == app_jitk || $compiler == dartk || $compiler == dartkp ]
 html/*: SkipByDesign
 js/*: SkipByDesign
 
diff --git a/tests/lib_2/lib_2_vm.status b/tests/lib_2/lib_2_vm.status
index 65cb43c..68e3420 100644
--- a/tests/lib_2/lib_2_vm.status
+++ b/tests/lib_2/lib_2_vm.status
@@ -8,7 +8,7 @@
 [ $arch == arm64 && $runtime == vm ]
 mirrors/immutable_collections_test: Pass, Slow # http://dartbug.com/33057
 
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm ]
 async/future_or_only_in_async_test/00: MissingCompileTimeError
 convert/streamed_conversion_json_utf8_decode_test: Pass, Slow # Infrequent timeouts.
 html/*: SkipByDesign # dart:html not supported on VM.
@@ -25,7 +25,7 @@
 mirrors/redirecting_factory_test/01: RuntimeError
 mirrors/redirecting_factory_test/none: RuntimeError
 
-[ $compiler != app_jitk && $compiler != dartk && $compiler != dartkb && $runtime == vm && !$checked ]
+[ $compiler != app_jitk && $compiler != dartk && $runtime == vm && !$checked ]
 mirrors/inference_and_no_such_method_test: RuntimeError
 
 [ $runtime == vm && $system == fuchsia ]
diff --git a/tests/lib_2/wasm/basic_test.dart b/tests/lib_2/wasm/basic_test.dart
index b6dfaa9..72f4c6c 100644
--- a/tests/lib_2/wasm/basic_test.dart
+++ b/tests/lib_2/wasm/basic_test.dart
@@ -5,7 +5,7 @@
 // Test that we can load a wasm module, find a function, and call it.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -21,8 +21,10 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
-  int n = fn.call([1234]);
+  var fn = inst.lookupFunction("square");
+  int n = fn.call(1234);
 
   Expect.equals(1234 * 1234, n);
+
+  Expect.isNull(inst.lookupFunction("not_a_function"));
 }
diff --git a/tests/lib_2/wasm/corrupted_error_test.dart b/tests/lib_2/wasm/corrupted_error_test.dart
index fcc4085..2b8d3fa 100644
--- a/tests/lib_2/wasm/corrupted_error_test.dart
+++ b/tests/lib_2/wasm/corrupted_error_test.dart
@@ -5,7 +5,7 @@
 // Test error thrown when the wasm module is corrupted.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -16,5 +16,5 @@
     0x7e, 0x0b,
   ]);
 
-  Expect.throwsArgumentError(() => WasmModule(data));
+  Expect.throws(() => WasmModule(data));
 }
diff --git a/tests/lib_2/wasm/fn_call_error_test.dart b/tests/lib_2/wasm/fn_call_error_test.dart
index 932afa3..0c74768 100644
--- a/tests/lib_2/wasm/fn_call_error_test.dart
+++ b/tests/lib_2/wasm/fn_call_error_test.dart
@@ -5,7 +5,7 @@
 // Test error thrown when a function is called with the wrong args.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -21,9 +21,9 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var fn = inst.lookupFunction<Int64 Function(Int64)>("square");
+  var fn = inst.lookupFunction("square");
 
-  Expect.throwsArgumentError(() => fn.call([]));
-  Expect.throwsArgumentError(() => fn.call([1, 2, 3]));
-  Expect.throwsArgumentError(() => fn.call([1.23]));
+  Expect.throwsArgumentError(() => fn());
+  Expect.throwsArgumentError(() => fn(1, 2, 3));
+  Expect.throwsArgumentError(() => fn(1.23));
 }
diff --git a/tests/lib_2/wasm/fn_mismatch_error_test.dart b/tests/lib_2/wasm/fn_mismatch_error_test.dart
deleted file mode 100644
index 413260e..0000000
--- a/tests/lib_2/wasm/fn_mismatch_error_test.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Test error thrown when the loaded function can't be found.
-
-import "package:expect/expect.dart";
-import "dart:wasm";
-import "dart:typed_data";
-
-void main() {
-  // int64_t square(int64_t n) { return n * n; }
-  var data = Uint8List.fromList([
-    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60,
-    0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70,
-    0x01, 0x01, 0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f,
-    0x01, 0x41, 0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65,
-    0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x73, 0x71, 0x75, 0x61, 0x72,
-    0x65, 0x00, 0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x20, 0x00, 0x20, 0x00,
-    0x7e, 0x0b,
-  ]);
-
-  var inst = WasmModule(data).instantiate(WasmImports());
-  Expect.isNotNull(inst.lookupFunction<Int64 Function(Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Int64)>("blah"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function()>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Int64, Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Void Function(Int64)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Void Function(dynamic)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Int64 Function(Float)>("square"));
-  Expect.throwsArgumentError(
-      () => inst.lookupFunction<Float Function(Int64)>("square"));
-}
diff --git a/tests/lib_2/wasm/memory_error_test.dart b/tests/lib_2/wasm/memory_error_test.dart
index e866bf0..3a172d8 100644
--- a/tests/lib_2/wasm/memory_error_test.dart
+++ b/tests/lib_2/wasm/memory_error_test.dart
@@ -5,11 +5,13 @@
 // Test errors thrown by WasmMemory.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
-  Expect.throwsArgumentError(() => WasmMemory(1000000000));
-  var mem = WasmMemory(1000);
-  Expect.throwsArgumentError(() => mem.grow(1000000000));
+  Expect.throws(() => WasmMemory(1000000000));
+  var mem = WasmMemory(100);
+  Expect.throws(() => mem.grow(1000000000));
+  mem = WasmMemory(100, 200);
+  Expect.throws(() => mem.grow(300));
 }
diff --git a/tests/lib_2/wasm/memory_test.dart b/tests/lib_2/wasm/memory_test.dart
index 52d12c3..ecaf433 100644
--- a/tests/lib_2/wasm/memory_test.dart
+++ b/tests/lib_2/wasm/memory_test.dart
@@ -5,22 +5,19 @@
 // Test that we can create a WasmMemory, edit it, and grow it.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
-  var mem = WasmMemory(1000);
-  Expect.equals(1000, mem.lengthInPages);
-  Expect.equals(1000 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  var mem = WasmMemory(100);
+  Expect.equals(100, mem.lengthInPages);
+  Expect.equals(100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
 
   mem[123] = 45;
   Expect.equals(45, mem[123]);
 
-  mem.grow(100);
-  Expect.equals(1100, mem.lengthInPages);
-  Expect.equals(1100 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
+  mem.grow(10);
+  Expect.equals(110, mem.lengthInPages);
+  Expect.equals(110 * WasmMemory.kPageSizeInBytes, mem.lengthInBytes);
   Expect.equals(45, mem[123]);
-
-  Expect.throwsArgumentError(() => WasmMemory(1000000000));
-  Expect.throwsArgumentError(() => mem.grow(1000000000));
 }
diff --git a/tests/lib_2/wasm/numerics_test.dart b/tests/lib_2/wasm/numerics_test.dart
index 8651caa..158549a 100644
--- a/tests/lib_2/wasm/numerics_test.dart
+++ b/tests/lib_2/wasm/numerics_test.dart
@@ -5,7 +5,7 @@
 // Test numeric types.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -30,20 +30,20 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var addI64 = inst.lookupFunction<Int64 Function(Int64, Int64)>("addI64");
-  var addI32 = inst.lookupFunction<Int32 Function(Int32, Int32)>("addI32");
-  var addF64 = inst.lookupFunction<Double Function(Double, Double)>("addF64");
-  var addF32 = inst.lookupFunction<Float Function(Float, Float)>("addF32");
+  var addI64 = inst.lookupFunction("addI64");
+  var addI32 = inst.lookupFunction("addI32");
+  var addF64 = inst.lookupFunction("addF64");
+  var addF32 = inst.lookupFunction("addF32");
 
-  int i64 = addI64.call([0x123456789ABCDEF, 0xFEDCBA987654321]);
+  int i64 = addI64(0x123456789ABCDEF, 0xFEDCBA987654321);
   Expect.equals(0x1111111111111110, i64);
 
-  int i32 = addI32.call([0xABCDEF, 0xFEDCBA]);
+  int i32 = addI32(0xABCDEF, 0xFEDCBA);
   Expect.equals(0x1aaaaa9, i32);
 
-  double f64 = addF64.call([1234.5678, 8765.4321]);
+  double f64 = addF64(1234.5678, 8765.4321);
   Expect.approxEquals(9999.9999, f64, 1e-6);
 
-  double f32 = addF32.call([1234.5678, 8765.4321]);
+  double f32 = addF32(1234.5678, 8765.4321);
   Expect.approxEquals(9999.9999, f32, 1e-3);
 }
diff --git a/tests/lib_2/wasm/void_test.dart b/tests/lib_2/wasm/void_test.dart
index fe3bd94..fe94693 100644
--- a/tests/lib_2/wasm/void_test.dart
+++ b/tests/lib_2/wasm/void_test.dart
@@ -5,7 +5,7 @@
 // Test functions with void return type, and functions that take no args.
 
 import "package:expect/expect.dart";
-import "dart:wasm";
+import "package:wasm/wasm.dart";
 import "dart:typed_data";
 
 void main() {
@@ -26,9 +26,9 @@
   ]);
 
   var inst = WasmModule(data).instantiate(WasmImports());
-  var setFn = inst.lookupFunction<Void Function(Int64, Int64)>("set");
-  var getFn = inst.lookupFunction<Int64 Function()>("get");
-  Expect.isNull(setFn.call([123, 456]));
-  int n = getFn.call([]);
+  var setFn = inst.lookupFunction("set");
+  var getFn = inst.lookupFunction("get");
+  Expect.isNull(setFn(123, 456));
+  int n = getFn();
   Expect.equals(123 + 456, n);
 }
diff --git a/tests/modular/constant_with_mixin/a.dart b/tests/modular/constant_with_mixin/a.dart
new file mode 100644
index 0000000..a8bc4c0
--- /dev/null
+++ b/tests/modular/constant_with_mixin/a.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class A {
+  const A({
+    this.d = 3.14,
+    this.s = 'default',
+  });
+
+  final double d;
+  final String s;
+}
+
+class B extends A with M {
+  const B({double d = 2.71}) : super(d: d);
+}
+
+mixin M on A {
+  m1() {}
+}
+
+const sameModule = B();
diff --git a/tests/modular/constant_with_mixin/main.dart b/tests/modular/constant_with_mixin/main.dart
new file mode 100644
index 0000000..f06eafc
--- /dev/null
+++ b/tests/modular/constant_with_mixin/main.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+import 'a.dart';
+
+const crossModule = B();
+main() {
+  Expect.equals(2.71, sameModule.d);
+  Expect.equals('default', sameModule.s);
+
+  Expect.equals(2.71, crossModule.d);
+  Expect.equals('default', crossModule.s);
+}
diff --git a/tests/modular/constant_with_mixin/modules.yaml b/tests/modular/constant_with_mixin/modules.yaml
new file mode 100644
index 0000000..61acd63
--- /dev/null
+++ b/tests/modular/constant_with_mixin/modules.yaml
@@ -0,0 +1,7 @@
+# Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Regression test: https://github.com/dart-lang/sdk/issues/43528
+dependencies:
+  main: [a, expect]
diff --git a/tests/standalone/check_for_aot_snapshot_jit_test.dart b/tests/standalone/check_for_aot_snapshot_jit_test.dart
index 851dc0c5..a1dd29d 100644
--- a/tests/standalone/check_for_aot_snapshot_jit_test.dart
+++ b/tests/standalone/check_for_aot_snapshot_jit_test.dart
@@ -20,7 +20,7 @@
   final kernelOutput = d.uri.resolve('pow_test.dill').path;
   final aotOutput = d.uri.resolve('pow_test.aot').path;
 
-  final genKernelResult = Process.runSync(
+  final genKernelResult = runAndPrintOutput(
     'pkg/vm/tool/gen_kernel',
     [
       '--aot',
@@ -31,8 +31,9 @@
     ],
   );
   Expect.equals(genKernelResult.exitCode, 0);
+  print("Ran successfully.\n");
 
-  final genAotResult = Process.runSync(
+  final genAotResult = runAndPrintOutput(
     genSnapshot,
     [
       '--snapshot_kind=app-aot-elf',
@@ -41,8 +42,9 @@
     ],
   );
   Expect.equals(genAotResult.exitCode, 0);
+  print("Ran successfully.\n");
 
-  final runAotResult = Process.runSync(
+  final runAotResult = runAndPrintOutput(
     exePath,
     [
       'run',
@@ -56,4 +58,19 @@
       "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
     ],
   );
+  print('Got expected error result.');
+}
+
+ProcessResult runAndPrintOutput(String command, List<String> args) {
+  print('Running $command ${args.join(' ')}...');
+  final result = Process.runSync(command, args);
+  if (result.stdout.isNotEmpty) {
+    print("stdout: ");
+    print(result.stdout);
+  }
+  if (result.stderr.isNotEmpty) {
+    print("stderr: ");
+    print(result.stderr);
+  }
+  return result;
 }
diff --git a/tests/standalone/dwarf_stack_trace_obfuscate_test.dart b/tests/standalone/dwarf_stack_trace_obfuscate_test.dart
index 5750ab5..f6b3360 100644
--- a/tests/standalone/dwarf_stack_trace_obfuscate_test.dart
+++ b/tests/standalone/dwarf_stack_trace_obfuscate_test.dart
@@ -40,7 +40,7 @@
     return; // Generated dwarf.so not available on the test device.
   }
 
-  final dwarf = Dwarf.fromFile("dwarf_obfuscate.so");
+  final dwarf = Dwarf.fromFile("dwarf_obfuscate.so")!;
 
   await base.checkStackTrace(rawStack, dwarf, expectedCallsInfo);
 }
diff --git a/tests/standalone/dwarf_stack_trace_test.dart b/tests/standalone/dwarf_stack_trace_test.dart
index 9cf2cb0..236a21e 100644
--- a/tests/standalone/dwarf_stack_trace_test.dart
+++ b/tests/standalone/dwarf_stack_trace_test.dart
@@ -40,7 +40,7 @@
     return; // Generated dwarf.so not available on the test device.
   }
 
-  final dwarf = Dwarf.fromFile("dwarf.so");
+  final dwarf = Dwarf.fromFile("dwarf.so")!;
 
   await checkStackTrace(rawStack, dwarf, expectedCallsInfo);
 }
@@ -86,7 +86,7 @@
     Expect.isNotNull(externalCallInfo);
     final allCallInfo = dwarf.callInfoFor(addr, includeInternalFrames: true);
     Expect.isNotNull(allCallInfo);
-    for (final call in allCallInfo) {
+    for (final call in allCallInfo!) {
       Expect.isTrue(call is DartCallInfo, "got non-Dart call info ${call}");
     }
     Expect.deepEquals(externalCallInfo, allCallInfo);
diff --git a/tests/standalone/http_launch_test.dart b/tests/standalone/http_launch_test.dart
index 1c9f8ab..07d6c13 100644
--- a/tests/standalone/http_launch_test.dart
+++ b/tests/standalone/http_launch_test.dart
@@ -9,6 +9,7 @@
 // OtherResources=http_launch_data/http_launch_main.dart
 // OtherResources=http_launch_data/http_spawn_main.dart
 // OtherResources=http_launch_data/the_packages/simple/simple.dart
+// OtherResources=http_launch_data/.dart_tool/package_config.json
 // OtherResources=http_launch_data/.packages
 //
 // Test:
diff --git a/tests/standalone/io/file_long_path_test.dart b/tests/standalone/io/file_long_path_test.dart
new file mode 100644
index 0000000..454e633d
--- /dev/null
+++ b/tests/standalone/io/file_long_path_test.dart
@@ -0,0 +1,247 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This test is Windows-only.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+const maxPath = 260;
+const maxDirectoryPath = maxPath - 12;
+String longName = '${'x' * 248}';
+
+Directory createLongPathDir(Directory tmp) {
+  if (tmp.path.length <= maxDirectoryPath) {
+    var path = tmp.path;
+    path += '\\${'t' * 248}';
+    var dir = Directory(path);
+    dir.createSync(recursive: true);
+    // Test the rename() of directory
+    dir = dir.renameSync(tmp.path + '\\$longName');
+    Expect.isTrue(dir.existsSync());
+    Expect.isFalse(Directory(path).existsSync());
+    return dir;
+  } else {
+    return tmp;
+  }
+}
+
+void testCreate(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  Expect.isTrue(file.existsSync());
+  file.deleteSync();
+}
+
+void testCopy(String dir) {
+  final src = '${dir}\\a_long_path_filename_1';
+  final dest = '${dir}\\a_long_path_filename_2';
+  Expect.isTrue(src.length > maxPath);
+  final file1 = File(src);
+  file1.createSync();
+
+  final file2 = file1.copySync(dest);
+  Expect.isTrue(file2.existsSync());
+  file1.deleteSync();
+  file2.deleteSync();
+}
+
+void testRename(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  Expect.isTrue(file.existsSync());
+
+  final renamedFile = file.renameSync('${path}_copy');
+
+  Expect.isFalse(file.existsSync());
+  Expect.isTrue(renamedFile.existsSync());
+  renamedFile.deleteSync();
+}
+
+void testReadWrite(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+
+  final content = "testReadWrite";
+  file.writeAsStringSync(content);
+  Expect.isTrue(file.existsSync());
+
+  int length = file.lengthSync();
+  Expect.equals(content.length, length);
+
+  final string = file.readAsStringSync();
+  Expect.equals(content, string);
+  file.deleteSync();
+}
+
+void testOpen(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  final access = file.openSync();
+  access.closeSync();
+}
+
+void testFileStat(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  final stat = FileStat.statSync(file.path);
+
+  final dateTime = DateTime.utc(2020);
+
+  file.setLastModifiedSync(dateTime);
+  Expect.notEquals(
+      stat.modified.toString(), file.lastModifiedSync().toString());
+
+  file.setLastAccessedSync(dateTime);
+  Expect.notEquals(
+      stat.accessed.toString(), file.lastAccessedSync().toString());
+}
+
+void testCreateLinkToDir(String dir) {
+  final path = '${dir}\\a_long_path_linkname';
+  Expect.isTrue(path.length > maxPath);
+  var target = '$dir\\a_long_path_target';
+  final link = Link(path)..createSync(target);
+
+  final dest = Directory(target)..createSync();
+  Expect.isTrue(dest.existsSync());
+
+  Expect.isTrue(link.existsSync());
+  Expect.isTrue(link.targetSync().contains('a_long_path_target'));
+
+  // Rename link
+  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
+  Expect.isTrue(renamedLink.existsSync());
+  Expect.isFalse(link.existsSync());
+  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));
+
+  // Update link target
+  target = '$dir\\an_updated_target';
+  final renamedDest = Directory(target)..createSync();
+  renamedLink.updateSync(target);
+  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));
+
+  dest.deleteSync();
+  renamedDest.deleteSync();
+  renamedLink.deleteSync();
+}
+
+void testCreateLinkToFile(String dir) {
+  final path = '${dir}\\a_long_path_linkname';
+  Expect.isTrue(path.length > maxPath);
+  var target = '$dir\\a_long_path_target';
+  final link = Link(path)..createSync(target);
+
+  final dest = File(target)..createSync();
+  Expect.isTrue(dest.existsSync());
+
+  Expect.isTrue(link.existsSync());
+  Expect.isTrue(link.targetSync().contains('a_long_path_target'));
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('a_long_path_target'));
+
+  // Rename link
+  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
+  Expect.isTrue(renamedLink.existsSync());
+  Expect.isFalse(link.existsSync());
+  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));
+
+  // Update link target
+  target = '$dir\\an_updated_target';
+  final renamedDest = File(target)..createSync();
+  renamedLink.updateSync(target);
+  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));
+
+  dest.deleteSync();
+  renamedDest.deleteSync();
+  renamedLink.deleteSync();
+}
+
+testNormalLinkToLongPath(String short, String long) {
+  var target = File('$long\\file_target')..createSync();
+  final link = Link('$short\\link')..createSync(target.path);
+  Expect.isTrue(target.path.length > maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().length > maxPath);
+  Expect.isTrue(link.path.length < maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));
+
+  Expect.isTrue(link.existsSync());
+  Expect.equals(target.path, link.targetSync());
+
+  var targetDir = Directory('$long\\dir_target')..createSync();
+  link.updateSync(targetDir.path);
+  Expect.equals(targetDir.path, link.targetSync());
+
+  link.deleteSync();
+  target.deleteSync();
+  targetDir.deleteSync();
+}
+
+testLongPathLinkToNormal(String short, String long) {
+  var target = File('$short\\file_target')..createSync();
+  final link = Link('$long\\link')..createSync(target.path);
+
+  Expect.isTrue(target.path.length < maxPath);
+  Expect.isTrue(link.path.length > maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));
+
+  Expect.isTrue(link.existsSync());
+  Expect.equals(target.path, link.targetSync());
+
+  var targetDir = Directory('$short\\dir_target')..createSync();
+  link.updateSync(targetDir.path);
+  Expect.equals(targetDir.path, link.targetSync());
+
+  link.deleteSync();
+  target.deleteSync();
+  targetDir.deleteSync();
+}
+
+testDirectorySetCurrent(String dir) {
+  // This tests setting a long path directory to current directory.
+  // This will fail.
+  Expect.isTrue(dir.length > maxPath);
+  Expect.throws<FileSystemException>(() {
+    Directory.current = dir;
+  }, (e) => e.toString().contains('extension is too long'));
+}
+
+void main() {
+  if (!Platform.isWindows) {
+    return;
+  }
+  final tmp = Directory.systemTemp.createTempSync('dart-file-long-path');
+  final oldCurrent = Directory.current;
+  Directory.current = tmp;
+  try {
+    String dir = createLongPathDir(tmp).path;
+    testDirectorySetCurrent(dir);
+    for (final path in [dir, ".\\$longName", ".\\$longName\\..\\$longName"]) {
+      testCreate(path);
+      testCopy(path);
+      testRename(path);
+      testReadWrite(path);
+      testOpen(path);
+      testFileStat(path);
+      testCreateLinkToDir(path);
+      testCreateLinkToFile(path);
+    }
+
+    testNormalLinkToLongPath(tmp.path, dir);
+    testLongPathLinkToNormal(tmp.path, dir);
+  } finally {
+    // Reset the current Directory.
+    Directory.current = oldCurrent;
+    tmp.deleteSync(recursive: true);
+  }
+}
diff --git a/tests/standalone/io/file_relative_long_path_test.dart b/tests/standalone/io/file_relative_long_path_test.dart
new file mode 100644
index 0000000..0c53ab3
--- /dev/null
+++ b/tests/standalone/io/file_relative_long_path_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This test is Windows-only. It tests a short (shorter than 260) relative path
+// representing a long absolute path cannot be used by Windows API. Running this
+// test without proper support on long path will get an error.
+
+import 'dart:io';
+
+const maxPath = 260;
+
+void main(args) {
+  if (!Platform.isWindows) {
+    return;
+  }
+  final dir = Directory.systemTemp.createTempSync('test');
+
+  if (dir.path.length >= maxPath) {
+    return;
+  }
+
+  // Make sure oldpath is shorter than MAX_PATH (260).
+  int length = (maxPath - dir.path.length) ~/ 2;
+  final oldpath = Directory('${dir.path}\\${'x' * length}}');
+  oldpath.createSync(recursive: true);
+  final temp = Directory.current;
+
+  Directory.current = oldpath.path;
+
+  // The length of relative path is always shorter than maxPath, but it
+  // represents a path exceeding the maxPath.
+  final newpath = Directory('.\\${'y' * 2 * length}');
+  newpath.createSync();
+
+  // Reset current directory before deletion.
+  Directory.current = temp.path;
+  dir.deleteSync(recursive: true);
+}
diff --git a/tests/standalone/io/http_ban_http_allowed_cases_test.dart b/tests/standalone/io/http_ban_http_allowed_cases_test.dart
new file mode 100644
index 0000000..92e23c7
--- /dev/null
+++ b/tests/standalone/io/http_ban_http_allowed_cases_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test file disallows VM from accepting insecure connections to all
+// domains and tests that HTTP connections to non-localhost targets fail.
+// HTTPS connections and localhost connections should still succeed.
+
+// SharedOptions=-Ddart.library.io.may_insecurely_connect_to_all_domains=false
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+import "http_bind_test.dart";
+
+Future<String> getLocalHostIP() async {
+  final interfaces = await NetworkInterface.list(
+      includeLoopback: false, type: InternetAddressType.IPv4);
+  return interfaces.first.addresses.first.address;
+}
+
+Future<void> testBanHttp(String serverHost,
+    Future<void> testCode(HttpClient client, Uri uri)) async {
+  final httpClient = new HttpClient();
+  final server = await HttpServer.bind(serverHost, 0);
+  final uri = Uri(scheme: 'http', host: serverHost, port: server.port);
+  try {
+    await testCode(httpClient, uri);
+  } finally {
+    httpClient.close(force: true);
+    await server.close();
+  }
+}
+
+Future<void> testWithLoopback() async {
+  await testBanHttp("127.0.0.1", (httpClient, uri) async {
+    await asyncTest(() async =>
+        await httpClient.getUrl(Uri.parse('http://localhost:${uri.port}')));
+    await asyncTest(() async =>
+        await httpClient.getUrl(Uri.parse('http://127.0.0.1:${uri.port}')));
+  });
+}
+
+Future<void> testWithIPv6() async {
+  if (await supportsIPV6()) {
+    await testBanHttp("::1", (httpClient, uri) async {
+      await asyncTest(() => httpClient.getUrl(uri));
+    });
+  }
+}
+
+Future<void> testWithHttps() async {
+  await testBanHttp(await getLocalHostIP(), (httpClient, uri) async {
+    asyncExpectThrows(
+        () => httpClient.getUrl(Uri(
+              scheme: 'https',
+              host: uri.host,
+              port: uri.port,
+            )),
+        (e) => e is SocketException || e is HandshakeException);
+  });
+}
+
+main() {
+  asyncStart();
+  Future.wait(<Future>[
+    testWithLoopback(),
+    testWithIPv6(),
+    testWithHttps(),
+  ]).then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/http_ban_insecure_connections_test.dart b/tests/standalone/io/http_ban_insecure_connections_test.dart
new file mode 100644
index 0000000..ae51a37
--- /dev/null
+++ b/tests/standalone/io/http_ban_insecure_connections_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test file disallows VM from accepting insecure connections to all
+// domains and tests that HTTP connections to non-localhost targets fail.
+// HTTPS connections and localhost connections should still succeed.
+
+// SharedOptions=-Ddart.library.io.may_insecurely_connect_to_all_domains=false
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+Future<void> testWithHostname() async {
+  final httpClient = new HttpClient();
+  final uri = Uri(scheme: 'http', host: 'domain.invalid', port: 12345);
+  asyncExpectThrows(
+      () async => await httpClient.getUrl(uri),
+      (e) =>
+          e is StateError &&
+          e.message.contains("Insecure HTTP is not allowed by platform"));
+}
+
+main() {
+  asyncStart();
+  testWithHostname().then((_) => asyncEnd());
+}
diff --git a/tests/standalone/io/http_redirect_test.dart b/tests/standalone/io/http_redirect_test.dart
index c008a34..f68e32f 100644
--- a/tests/standalone/io/http_redirect_test.dart
+++ b/tests/standalone/io/http_redirect_test.dart
@@ -106,6 +106,7 @@
     addRedirectHandler(n++, HttpStatus.movedTemporarily);
     addRedirectHandler(n++, HttpStatus.seeOther);
     addRedirectHandler(n++, HttpStatus.temporaryRedirect);
+    addRedirectHandler(n++, HttpStatus.permanentRedirect);
     for (int i = n; i < 10; i++) {
       addRedirectHandler(i, HttpStatus.movedPermanently);
     }
diff --git a/tests/standalone/io/raw_datagram_socket_test.dart b/tests/standalone/io/raw_datagram_socket_test.dart
index 2585edd..6e91f95 100644
--- a/tests/standalone/io/raw_datagram_socket_test.dart
+++ b/tests/standalone/io/raw_datagram_socket_test.dart
@@ -73,14 +73,14 @@
     RawDatagramSocket.bind(address, 0,
             reuseAddress: reuseAddress,
             reusePort: Platform.isMacOS && reuseAddress)
-        .then((socket) {
+        .then((socket) async {
       if (reuseAddress) {
         RawDatagramSocket.bind(address, socket.port,
                 reusePort: Platform.isMacOS)
             .then((s) => Expect.isTrue(s is RawDatagramSocket))
             .then(asyncSuccess);
       } else {
-        FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
+        await FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
             .then(asyncSuccess);
       }
     });
diff --git a/tests/standalone/io/socket_connect_consume_write_close_test.dart b/tests/standalone/io/socket_connect_consume_write_close_test.dart
index 8b021abd..f593c79 100644
--- a/tests/standalone/io/socket_connect_consume_write_close_test.dart
+++ b/tests/standalone/io/socket_connect_consume_write_close_test.dart
@@ -18,7 +18,12 @@
   // without listening on the stream.
   asyncStart();
   ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
-    server.listen((_) {});
+    late Socket ref;
+    server.listen((socket) {
+      // Create a reference to the connected socket so it's not prematurely
+      // collected.
+      ref = socket;
+    });
     Socket.connect("127.0.0.1", server.port).then((socket) {
       socket.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
       socket.close();
diff --git a/tests/standalone/out_of_memory_slow_growth_test.dart b/tests/standalone/out_of_memory_slow_growth_test.dart
new file mode 100644
index 0000000..e534dc6
--- /dev/null
+++ b/tests/standalone/out_of_memory_slow_growth_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--old_gen_heap_size=20
+// VMOptions=--old_gen_heap_size=20 --enable_vm_service --pause_isolates_on_unhandled_exceptions
+
+import "package:expect/expect.dart";
+
+main() {
+  var leak;
+  var exceptionThrown = false;
+  try {
+    leak = [];
+    while (true) {
+      leak = [leak];
+    }
+  } on OutOfMemoryError catch (exception) {
+    leak = null;
+    exceptionThrown = true;
+    print("Okay");
+  }
+  Expect.isTrue(exceptionThrown);
+}
diff --git a/tests/standalone/out_of_memory_unhandled_exception_test.dart b/tests/standalone/out_of_memory_unhandled_exception_test.dart
new file mode 100644
index 0000000..7a5935d
--- /dev/null
+++ b/tests/standalone/out_of_memory_unhandled_exception_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+main(args) async {
+  if (args.contains("--child")) {
+    var leak = [];
+    while (true) {
+      leak = [leak];
+    }
+  } else {
+    var exec = Platform.resolvedExecutable;
+    var args = <String>[];
+    args.addAll(Platform.executableArguments);
+    args.add("--old_gen_heap_size=20");
+    args.add(Platform.script.toFilePath());
+    args.add("--child");
+
+    // Should report an unhandled out of memory exception without crashing.
+    print("+ $exec " + args.join(" "));
+    var result = await Process.run(exec, args);
+
+    print("exit: ${result.exitCode}");
+    print("stdout:");
+    print(result.stdout);
+    print("stderr:");
+    print(result.stderr);
+
+    Expect.equals(255, result.exitCode, "Unhandled exception, not crash");
+    Expect.isTrue(result.stderr.contains("Out of Memory"));
+  }
+}
diff --git a/tests/standalone/regress_41329_absolute_test.dart b/tests/standalone/regress_41329_absolute_test.dart
index e35e126..5798cbc 100644
--- a/tests/standalone/regress_41329_absolute_test.dart
+++ b/tests/standalone/regress_41329_absolute_test.dart
@@ -19,7 +19,7 @@
 
   // /usr/local/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
   Directory.current = a;
-  final linkLocation = '../Cellar/dart/2.8.0-dev.20.0/bin/dart';
+  final linkLocation = '${d.path}/usr/local/bin/Cellar/dart/2.8.0-dev.20.0/bin/dart';
   final link = Link(linkLocation);
   link.createSync(exePath, recursive: true);
 
@@ -27,6 +27,6 @@
   final link2 = Link('dart')..createSync(linkLocation, recursive: true);
   final path = Uri.parse(link2.absolute.path).path;
   Directory.current = origDir;
-  final result = await Process.run('${path}', ['help']);
+  final result = await Process.run('$path', ['help']);
   Expect.equals(result.exitCode, 0);
 }
diff --git a/tests/standalone/standalone_kernel.status b/tests/standalone/standalone_kernel.status
index aa8621f..bc9439c 100644
--- a/tests/standalone/standalone_kernel.status
+++ b/tests/standalone/standalone_kernel.status
@@ -4,18 +4,13 @@
 # Sections in this file should contain "$compiler == dartk" or
 # "$compiler == dartkp".
 
-fragmentation_test: Pass, Slow # GC heavy
 fragmentation_typed_data_test: Pass, Slow # GC heavy
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
-
-[ $builder_tag == bytecode_interpreter ]
-io/http_big_header_test: SkipSlow # Timeout
-
-[ $compiler == dartkb ]
-no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
+out_of_memory_unhandled_exception_test: Pass, Slow
 
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
+io/http_ban_http_allowed_cases_test: Skip # Depends on grabbing local hostname which isn't supported.
 io/network_policy_configuration_test: Skip # Can't pass -D params containing quotes to adb.
 io/network_policy_invalid_domain_test: Skip # Can't pass -D params containing quotes to adb.
 io/network_policy_tie_breaker_test: Skip # Can't pass -D params containing quotes to adb.
@@ -23,12 +18,62 @@
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 io/file_lock_test: SkipSlow # Timeout
 
-[ $arch == simarm64 && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == simarm64 && $compiler == dartk ]
 io/http_bind_test: Slow, Pass
 
-[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
 map_insert_remove_oom_test: Skip # Heap limit too low.
 
+[ $compiler == dartk && $mode == debug && $runtime == vm ]
+io/file_lock_test: Slow, Pass
+io/raw_socket_test: Crash
+io/socket_exception_test: Crash
+io/socket_finalizer_test: Crash
+io/socket_info_ipv4_test: Crash
+io/socket_info_ipv6_test: Crash
+io/socket_port_test: Crash
+
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+io/web_socket_ping_test: Crash
+
+[ $compiler == dartk && $runtime == vm ]
+no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
+
+[ $compiler == dartk && $system == windows ]
+io/dart_std_io_pipe_test: Slow, Pass
+io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
+io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $compiler == dartk && $hot_reload ]
+io/http_no_reason_phrase_test: Crash
+io/http_outgoing_size_test: Crash
+
+[ $compiler == dartk && $hot_reload_rollback ]
+io/directory_chdir_test: Skip # Timeout
+io/echo_server_stream_test: Slow, Pass
+
+# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
+# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
+# batch mode.
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
+io/file_blocking_lock_test: Crash # Please triage.
+io/file_lock_test: Slow, Pass
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+io/addlatexhash_test: Skip # Timeout
+io/http_advanced_test: Skip # Timeout
+io/http_auth_digest_test: Crash
+io/http_auth_test: Skip # Timeout
+io/http_proxy_advanced_test: Skip # Timeout
+io/http_read_test: Skip # Timeout
+io/pipe_server_test: Skip # Timeout
+io/socket_close_test: Skip # Timeout
+io/socket_many_connections_test: Skip # Timeout
+io/web_socket_compression_test: Skip # Timeout
+io/web_socket_test: Skip # Timeout
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 io/raw_socket_test: Crash
 io/socket_exception_test: Crash
@@ -63,55 +108,5 @@
 map_insert_remove_oom_test: Skip # Heap limit too low.
 no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
 
-[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-io/file_lock_test: Slow, Pass
-io/raw_socket_test: Crash
-io/socket_exception_test: Crash
-io/socket_finalizer_test: Crash
-io/socket_info_ipv4_test: Crash
-io/socket_info_ipv6_test: Crash
-io/socket_port_test: Crash
-
-[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-io/web_socket_ping_test: Crash
-
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
-
-[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
-io/dart_std_io_pipe_test: Slow, Pass
-io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
-io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
-map_insert_remove_oom_test: Skip # Heap limit too low.
-
-[ $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-io/http_no_reason_phrase_test: Crash
-io/http_outgoing_size_test: Crash
-
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-io/directory_chdir_test: Skip # Timeout
-io/echo_server_stream_test: Slow, Pass
-
-# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
-io/file_blocking_lock_test: Crash # Please triage.
-io/file_lock_test: Slow, Pass
-map_insert_remove_oom_test: Skip # Heap limit too low.
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-io/addlatexhash_test: Skip # Timeout
-io/http_advanced_test: Skip # Timeout
-io/http_auth_digest_test: Crash
-io/http_auth_test: Skip # Timeout
-io/http_proxy_advanced_test: Skip # Timeout
-io/http_read_test: Skip # Timeout
-io/pipe_server_test: Skip # Timeout
-io/socket_close_test: Skip # Timeout
-io/socket_many_connections_test: Skip # Timeout
-io/web_socket_compression_test: Skip # Timeout
-io/web_socket_test: Skip # Timeout
-
-[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
+[ $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
 entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone/standalone_precompiled.status b/tests/standalone/standalone_precompiled.status
index 6953302..5e5ec81 100644
--- a/tests/standalone/standalone_precompiled.status
+++ b/tests/standalone/standalone_precompiled.status
@@ -54,6 +54,7 @@
 package/scenarios/packages_file_strange_formatting/mixed_line_ends_test: Skip
 package/scenarios/packages_option_only/packages_option_only_noimports_test: Skip
 package/scenarios/packages_option_only/packages_option_only_test: Skip
+regress_41329_*: SkipByDesign # Expects to find the test directory relative to the script.
 
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/socket_cancel_connect_test: RuntimeError # Issue 34142
diff --git a/tests/standalone/standalone_vm.status b/tests/standalone/standalone_vm.status
index 93e314f..bc1e1fb 100644
--- a/tests/standalone/standalone_vm.status
+++ b/tests/standalone/standalone_vm.status
@@ -47,9 +47,6 @@
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
 
-[ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
-io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
-
 [ $arch == x64 && $mode == release && $runtime == vm && $system == linux ]
 io/http_bind_test: Pass, Timeout # Issue 35192
 
diff --git a/tests/standalone_2/check_for_aot_snapshot_jit_test.dart b/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
index 851dc0c5..a1dd29d 100644
--- a/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
+++ b/tests/standalone_2/check_for_aot_snapshot_jit_test.dart
@@ -20,7 +20,7 @@
   final kernelOutput = d.uri.resolve('pow_test.dill').path;
   final aotOutput = d.uri.resolve('pow_test.aot').path;
 
-  final genKernelResult = Process.runSync(
+  final genKernelResult = runAndPrintOutput(
     'pkg/vm/tool/gen_kernel',
     [
       '--aot',
@@ -31,8 +31,9 @@
     ],
   );
   Expect.equals(genKernelResult.exitCode, 0);
+  print("Ran successfully.\n");
 
-  final genAotResult = Process.runSync(
+  final genAotResult = runAndPrintOutput(
     genSnapshot,
     [
       '--snapshot_kind=app-aot-elf',
@@ -41,8 +42,9 @@
     ],
   );
   Expect.equals(genAotResult.exitCode, 0);
+  print("Ran successfully.\n");
 
-  final runAotResult = Process.runSync(
+  final runAotResult = runAndPrintOutput(
     exePath,
     [
       'run',
@@ -56,4 +58,19 @@
       "pow_test.aot is an AOT snapshot and should be run with 'dartaotruntime'",
     ],
   );
+  print('Got expected error result.');
+}
+
+ProcessResult runAndPrintOutput(String command, List<String> args) {
+  print('Running $command ${args.join(' ')}...');
+  final result = Process.runSync(command, args);
+  if (result.stdout.isNotEmpty) {
+    print("stdout: ");
+    print(result.stdout);
+  }
+  if (result.stderr.isNotEmpty) {
+    print("stderr: ");
+    print(result.stderr);
+  }
+  return result;
 }
diff --git a/tests/standalone_2/io/file_long_path_test.dart b/tests/standalone_2/io/file_long_path_test.dart
new file mode 100644
index 0000000..454e633d
--- /dev/null
+++ b/tests/standalone_2/io/file_long_path_test.dart
@@ -0,0 +1,247 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This test is Windows-only.
+
+import 'dart:io';
+
+import "package:expect/expect.dart";
+
+const maxPath = 260;
+const maxDirectoryPath = maxPath - 12;
+String longName = '${'x' * 248}';
+
+Directory createLongPathDir(Directory tmp) {
+  if (tmp.path.length <= maxDirectoryPath) {
+    var path = tmp.path;
+    path += '\\${'t' * 248}';
+    var dir = Directory(path);
+    dir.createSync(recursive: true);
+    // Test the rename() of directory
+    dir = dir.renameSync(tmp.path + '\\$longName');
+    Expect.isTrue(dir.existsSync());
+    Expect.isFalse(Directory(path).existsSync());
+    return dir;
+  } else {
+    return tmp;
+  }
+}
+
+void testCreate(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  Expect.isTrue(file.existsSync());
+  file.deleteSync();
+}
+
+void testCopy(String dir) {
+  final src = '${dir}\\a_long_path_filename_1';
+  final dest = '${dir}\\a_long_path_filename_2';
+  Expect.isTrue(src.length > maxPath);
+  final file1 = File(src);
+  file1.createSync();
+
+  final file2 = file1.copySync(dest);
+  Expect.isTrue(file2.existsSync());
+  file1.deleteSync();
+  file2.deleteSync();
+}
+
+void testRename(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  Expect.isTrue(file.existsSync());
+
+  final renamedFile = file.renameSync('${path}_copy');
+
+  Expect.isFalse(file.existsSync());
+  Expect.isTrue(renamedFile.existsSync());
+  renamedFile.deleteSync();
+}
+
+void testReadWrite(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+
+  final content = "testReadWrite";
+  file.writeAsStringSync(content);
+  Expect.isTrue(file.existsSync());
+
+  int length = file.lengthSync();
+  Expect.equals(content.length, length);
+
+  final string = file.readAsStringSync();
+  Expect.equals(content, string);
+  file.deleteSync();
+}
+
+void testOpen(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  final access = file.openSync();
+  access.closeSync();
+}
+
+void testFileStat(String dir) {
+  final path = '${dir}\\a_long_path_filename';
+  Expect.isTrue(path.length > maxPath);
+  final file = File(path);
+  file.createSync();
+  final stat = FileStat.statSync(file.path);
+
+  final dateTime = DateTime.utc(2020);
+
+  file.setLastModifiedSync(dateTime);
+  Expect.notEquals(
+      stat.modified.toString(), file.lastModifiedSync().toString());
+
+  file.setLastAccessedSync(dateTime);
+  Expect.notEquals(
+      stat.accessed.toString(), file.lastAccessedSync().toString());
+}
+
+void testCreateLinkToDir(String dir) {
+  final path = '${dir}\\a_long_path_linkname';
+  Expect.isTrue(path.length > maxPath);
+  var target = '$dir\\a_long_path_target';
+  final link = Link(path)..createSync(target);
+
+  final dest = Directory(target)..createSync();
+  Expect.isTrue(dest.existsSync());
+
+  Expect.isTrue(link.existsSync());
+  Expect.isTrue(link.targetSync().contains('a_long_path_target'));
+
+  // Rename link
+  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
+  Expect.isTrue(renamedLink.existsSync());
+  Expect.isFalse(link.existsSync());
+  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));
+
+  // Update link target
+  target = '$dir\\an_updated_target';
+  final renamedDest = Directory(target)..createSync();
+  renamedLink.updateSync(target);
+  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));
+
+  dest.deleteSync();
+  renamedDest.deleteSync();
+  renamedLink.deleteSync();
+}
+
+void testCreateLinkToFile(String dir) {
+  final path = '${dir}\\a_long_path_linkname';
+  Expect.isTrue(path.length > maxPath);
+  var target = '$dir\\a_long_path_target';
+  final link = Link(path)..createSync(target);
+
+  final dest = File(target)..createSync();
+  Expect.isTrue(dest.existsSync());
+
+  Expect.isTrue(link.existsSync());
+  Expect.isTrue(link.targetSync().contains('a_long_path_target'));
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('a_long_path_target'));
+
+  // Rename link
+  var renamedLink = link.renameSync('${dir}\\a_renamed_long_path_link');
+  Expect.isTrue(renamedLink.existsSync());
+  Expect.isFalse(link.existsSync());
+  Expect.isTrue(renamedLink.targetSync().contains('a_long_path_target'));
+
+  // Update link target
+  target = '$dir\\an_updated_target';
+  final renamedDest = File(target)..createSync();
+  renamedLink.updateSync(target);
+  Expect.isTrue(renamedLink.targetSync().contains('an_updated_target'));
+
+  dest.deleteSync();
+  renamedDest.deleteSync();
+  renamedLink.deleteSync();
+}
+
+testNormalLinkToLongPath(String short, String long) {
+  var target = File('$long\\file_target')..createSync();
+  final link = Link('$short\\link')..createSync(target.path);
+  Expect.isTrue(target.path.length > maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().length > maxPath);
+  Expect.isTrue(link.path.length < maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));
+
+  Expect.isTrue(link.existsSync());
+  Expect.equals(target.path, link.targetSync());
+
+  var targetDir = Directory('$long\\dir_target')..createSync();
+  link.updateSync(targetDir.path);
+  Expect.equals(targetDir.path, link.targetSync());
+
+  link.deleteSync();
+  target.deleteSync();
+  targetDir.deleteSync();
+}
+
+testLongPathLinkToNormal(String short, String long) {
+  var target = File('$short\\file_target')..createSync();
+  final link = Link('$long\\link')..createSync(target.path);
+
+  Expect.isTrue(target.path.length < maxPath);
+  Expect.isTrue(link.path.length > maxPath);
+  Expect.isTrue(link.resolveSymbolicLinksSync().contains('file_target'));
+
+  Expect.isTrue(link.existsSync());
+  Expect.equals(target.path, link.targetSync());
+
+  var targetDir = Directory('$short\\dir_target')..createSync();
+  link.updateSync(targetDir.path);
+  Expect.equals(targetDir.path, link.targetSync());
+
+  link.deleteSync();
+  target.deleteSync();
+  targetDir.deleteSync();
+}
+
+testDirectorySetCurrent(String dir) {
+  // This tests setting a long path directory to current directory.
+  // This will fail.
+  Expect.isTrue(dir.length > maxPath);
+  Expect.throws<FileSystemException>(() {
+    Directory.current = dir;
+  }, (e) => e.toString().contains('extension is too long'));
+}
+
+void main() {
+  if (!Platform.isWindows) {
+    return;
+  }
+  final tmp = Directory.systemTemp.createTempSync('dart-file-long-path');
+  final oldCurrent = Directory.current;
+  Directory.current = tmp;
+  try {
+    String dir = createLongPathDir(tmp).path;
+    testDirectorySetCurrent(dir);
+    for (final path in [dir, ".\\$longName", ".\\$longName\\..\\$longName"]) {
+      testCreate(path);
+      testCopy(path);
+      testRename(path);
+      testReadWrite(path);
+      testOpen(path);
+      testFileStat(path);
+      testCreateLinkToDir(path);
+      testCreateLinkToFile(path);
+    }
+
+    testNormalLinkToLongPath(tmp.path, dir);
+    testLongPathLinkToNormal(tmp.path, dir);
+  } finally {
+    // Reset the current Directory.
+    Directory.current = oldCurrent;
+    tmp.deleteSync(recursive: true);
+  }
+}
diff --git a/tests/standalone_2/io/file_relative_long_path_test.dart b/tests/standalone_2/io/file_relative_long_path_test.dart
new file mode 100644
index 0000000..0c53ab3
--- /dev/null
+++ b/tests/standalone_2/io/file_relative_long_path_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// This test is Windows-only. It tests a short (shorter than 260) relative path
+// representing a long absolute path cannot be used by Windows API. Running this
+// test without proper support on long path will get an error.
+
+import 'dart:io';
+
+const maxPath = 260;
+
+void main(args) {
+  if (!Platform.isWindows) {
+    return;
+  }
+  final dir = Directory.systemTemp.createTempSync('test');
+
+  if (dir.path.length >= maxPath) {
+    return;
+  }
+
+  // Make sure oldpath is shorter than MAX_PATH (260).
+  int length = (maxPath - dir.path.length) ~/ 2;
+  final oldpath = Directory('${dir.path}\\${'x' * length}}');
+  oldpath.createSync(recursive: true);
+  final temp = Directory.current;
+
+  Directory.current = oldpath.path;
+
+  // The length of relative path is always shorter than maxPath, but it
+  // represents a path exceeding the maxPath.
+  final newpath = Directory('.\\${'y' * 2 * length}');
+  newpath.createSync();
+
+  // Reset current directory before deletion.
+  Directory.current = temp.path;
+  dir.deleteSync(recursive: true);
+}
diff --git a/tests/standalone_2/io/http_ban_http_allowed_cases_test.dart b/tests/standalone_2/io/http_ban_http_allowed_cases_test.dart
new file mode 100644
index 0000000..92e23c7
--- /dev/null
+++ b/tests/standalone_2/io/http_ban_http_allowed_cases_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test file disallows VM from accepting insecure connections to all
+// domains and tests that HTTP connections to non-localhost targets fail.
+// HTTPS connections and localhost connections should still succeed.
+
+// SharedOptions=-Ddart.library.io.may_insecurely_connect_to_all_domains=false
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+import "http_bind_test.dart";
+
+Future<String> getLocalHostIP() async {
+  final interfaces = await NetworkInterface.list(
+      includeLoopback: false, type: InternetAddressType.IPv4);
+  return interfaces.first.addresses.first.address;
+}
+
+Future<void> testBanHttp(String serverHost,
+    Future<void> testCode(HttpClient client, Uri uri)) async {
+  final httpClient = new HttpClient();
+  final server = await HttpServer.bind(serverHost, 0);
+  final uri = Uri(scheme: 'http', host: serverHost, port: server.port);
+  try {
+    await testCode(httpClient, uri);
+  } finally {
+    httpClient.close(force: true);
+    await server.close();
+  }
+}
+
+Future<void> testWithLoopback() async {
+  await testBanHttp("127.0.0.1", (httpClient, uri) async {
+    await asyncTest(() async =>
+        await httpClient.getUrl(Uri.parse('http://localhost:${uri.port}')));
+    await asyncTest(() async =>
+        await httpClient.getUrl(Uri.parse('http://127.0.0.1:${uri.port}')));
+  });
+}
+
+Future<void> testWithIPv6() async {
+  if (await supportsIPV6()) {
+    await testBanHttp("::1", (httpClient, uri) async {
+      await asyncTest(() => httpClient.getUrl(uri));
+    });
+  }
+}
+
+Future<void> testWithHttps() async {
+  await testBanHttp(await getLocalHostIP(), (httpClient, uri) async {
+    asyncExpectThrows(
+        () => httpClient.getUrl(Uri(
+              scheme: 'https',
+              host: uri.host,
+              port: uri.port,
+            )),
+        (e) => e is SocketException || e is HandshakeException);
+  });
+}
+
+main() {
+  asyncStart();
+  Future.wait(<Future>[
+    testWithLoopback(),
+    testWithIPv6(),
+    testWithHttps(),
+  ]).then((_) => asyncEnd());
+}
diff --git a/tests/standalone_2/io/http_ban_insecure_connections_test.dart b/tests/standalone_2/io/http_ban_insecure_connections_test.dart
new file mode 100644
index 0000000..ae51a37
--- /dev/null
+++ b/tests/standalone_2/io/http_ban_insecure_connections_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This test file disallows VM from accepting insecure connections to all
+// domains and tests that HTTP connections to non-localhost targets fail.
+// HTTPS connections and localhost connections should still succeed.
+
+// SharedOptions=-Ddart.library.io.may_insecurely_connect_to_all_domains=false
+
+import "dart:async";
+import "dart:io";
+
+import "package:async_helper/async_helper.dart";
+
+Future<void> testWithHostname() async {
+  final httpClient = new HttpClient();
+  final uri = Uri(scheme: 'http', host: 'domain.invalid', port: 12345);
+  asyncExpectThrows(
+      () async => await httpClient.getUrl(uri),
+      (e) =>
+          e is StateError &&
+          e.message.contains("Insecure HTTP is not allowed by platform"));
+}
+
+main() {
+  asyncStart();
+  testWithHostname().then((_) => asyncEnd());
+}
diff --git a/tests/standalone_2/io/http_redirect_test.dart b/tests/standalone_2/io/http_redirect_test.dart
index 1e54bb9..ccb95c5 100644
--- a/tests/standalone_2/io/http_redirect_test.dart
+++ b/tests/standalone_2/io/http_redirect_test.dart
@@ -106,6 +106,7 @@
     addRedirectHandler(n++, HttpStatus.movedTemporarily);
     addRedirectHandler(n++, HttpStatus.seeOther);
     addRedirectHandler(n++, HttpStatus.temporaryRedirect);
+    addRedirectHandler(n++, HttpStatus.permanentRedirect);
     for (int i = n; i < 10; i++) {
       addRedirectHandler(i, HttpStatus.movedPermanently);
     }
diff --git a/tests/standalone_2/io/raw_datagram_socket_test.dart b/tests/standalone_2/io/raw_datagram_socket_test.dart
index 5061d18..848861b 100644
--- a/tests/standalone_2/io/raw_datagram_socket_test.dart
+++ b/tests/standalone_2/io/raw_datagram_socket_test.dart
@@ -73,14 +73,14 @@
     RawDatagramSocket.bind(address, 0,
             reuseAddress: reuseAddress,
             reusePort: Platform.isMacOS && reuseAddress)
-        .then((socket) {
+        .then((socket) async {
       if (reuseAddress) {
         RawDatagramSocket.bind(address, socket.port,
                 reusePort: Platform.isMacOS)
             .then((s) => Expect.isTrue(s is RawDatagramSocket))
             .then(asyncSuccess);
       } else {
-        FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
+        await FutureExpect.throws(RawDatagramSocket.bind(address, socket.port))
             .then(asyncSuccess);
       }
     });
diff --git a/tests/standalone_2/io/socket_connect_consume_write_close_test.dart b/tests/standalone_2/io/socket_connect_consume_write_close_test.dart
index 8b021abd..3dc0ab5 100644
--- a/tests/standalone_2/io/socket_connect_consume_write_close_test.dart
+++ b/tests/standalone_2/io/socket_connect_consume_write_close_test.dart
@@ -18,7 +18,12 @@
   // without listening on the stream.
   asyncStart();
   ServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
-    server.listen((_) {});
+    Socket ref;
+    server.listen((socket) {
+      // Create a reference to the connected socket so it's not prematurely
+      // collected.
+      ref = socket;
+    });
     Socket.connect("127.0.0.1", server.port).then((socket) {
       socket.add([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
       socket.close();
diff --git a/tests/standalone_2/out_of_memory_slow_growth_test.dart b/tests/standalone_2/out_of_memory_slow_growth_test.dart
new file mode 100644
index 0000000..e534dc6
--- /dev/null
+++ b/tests/standalone_2/out_of_memory_slow_growth_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--old_gen_heap_size=20
+// VMOptions=--old_gen_heap_size=20 --enable_vm_service --pause_isolates_on_unhandled_exceptions
+
+import "package:expect/expect.dart";
+
+main() {
+  var leak;
+  var exceptionThrown = false;
+  try {
+    leak = [];
+    while (true) {
+      leak = [leak];
+    }
+  } on OutOfMemoryError catch (exception) {
+    leak = null;
+    exceptionThrown = true;
+    print("Okay");
+  }
+  Expect.isTrue(exceptionThrown);
+}
diff --git a/tests/standalone_2/out_of_memory_unhandled_exception_test.dart b/tests/standalone_2/out_of_memory_unhandled_exception_test.dart
new file mode 100644
index 0000000..7a5935d
--- /dev/null
+++ b/tests/standalone_2/out_of_memory_unhandled_exception_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+main(args) async {
+  if (args.contains("--child")) {
+    var leak = [];
+    while (true) {
+      leak = [leak];
+    }
+  } else {
+    var exec = Platform.resolvedExecutable;
+    var args = <String>[];
+    args.addAll(Platform.executableArguments);
+    args.add("--old_gen_heap_size=20");
+    args.add(Platform.script.toFilePath());
+    args.add("--child");
+
+    // Should report an unhandled out of memory exception without crashing.
+    print("+ $exec " + args.join(" "));
+    var result = await Process.run(exec, args);
+
+    print("exit: ${result.exitCode}");
+    print("stdout:");
+    print(result.stdout);
+    print("stderr:");
+    print(result.stderr);
+
+    Expect.equals(255, result.exitCode, "Unhandled exception, not crash");
+    Expect.isTrue(result.stderr.contains("Out of Memory"));
+  }
+}
diff --git a/tests/standalone_2/regress_41329_absolute_test.dart b/tests/standalone_2/regress_41329_absolute_test.dart
index e35e126..5798cbc 100644
--- a/tests/standalone_2/regress_41329_absolute_test.dart
+++ b/tests/standalone_2/regress_41329_absolute_test.dart
@@ -19,7 +19,7 @@
 
   // /usr/local/Cellar/dart/2.8.0-dev.20.0/bin/dart -> $DART_SDK/bin/dart
   Directory.current = a;
-  final linkLocation = '../Cellar/dart/2.8.0-dev.20.0/bin/dart';
+  final linkLocation = '${d.path}/usr/local/bin/Cellar/dart/2.8.0-dev.20.0/bin/dart';
   final link = Link(linkLocation);
   link.createSync(exePath, recursive: true);
 
@@ -27,6 +27,6 @@
   final link2 = Link('dart')..createSync(linkLocation, recursive: true);
   final path = Uri.parse(link2.absolute.path).path;
   Directory.current = origDir;
-  final result = await Process.run('${path}', ['help']);
+  final result = await Process.run('$path', ['help']);
   Expect.equals(result.exitCode, 0);
 }
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index aa8621f..cf0367e 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -7,15 +7,11 @@
 fragmentation_test: Pass, Slow # GC heavy
 fragmentation_typed_data_test: Pass, Slow # GC heavy
 io/process_sync_test: Pass, Slow # Spawns synchronously subprocesses in sequence.
-
-[ $builder_tag == bytecode_interpreter ]
-io/http_big_header_test: SkipSlow # Timeout
-
-[ $compiler == dartkb ]
-no_lazy_dispatchers_test: SkipByDesign # KBC interpreter doesn't support --no_lazy_dispatchers
+out_of_memory_unhandled_exception_test: Pass, Slow
 
 [ $system == android ]
 entrypoints_verification_test: Skip # Requires shared objects which the test script doesn't "adb push".
+io/http_ban_http_allowed_cases_test: Skip # Depends on grabbing local hostname which isn't supported.
 io/network_policy_configuration_test: Skip # Can't pass -D params containing quotes to adb.
 io/network_policy_invalid_domain_test: Skip # Can't pass -D params containing quotes to adb.
 io/network_policy_tie_breaker_test: Skip # Can't pass -D params containing quotes to adb.
@@ -23,12 +19,62 @@
 [ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
 io/file_lock_test: SkipSlow # Timeout
 
-[ $arch == simarm64 && ($compiler == dartk || $compiler == dartkb) ]
+[ $arch == simarm64 && $compiler == dartk ]
 io/http_bind_test: Slow, Pass
 
-[ $builder_tag == optimization_counter_threshold && ($compiler == dartk || $compiler == dartkb) ]
+[ $builder_tag == optimization_counter_threshold && $compiler == dartk ]
 map_insert_remove_oom_test: Skip # Heap limit too low.
 
+[ $compiler == dartk && $mode == debug && $runtime == vm ]
+io/file_lock_test: Slow, Pass
+io/raw_socket_test: Crash
+io/socket_exception_test: Crash
+io/socket_finalizer_test: Crash
+io/socket_info_ipv4_test: Crash
+io/socket_info_ipv6_test: Crash
+io/socket_port_test: Crash
+
+[ $compiler == dartk && $mode == debug && $hot_reload ]
+io/web_socket_ping_test: Crash
+
+[ $compiler == dartk && $runtime == vm ]
+no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
+
+[ $compiler == dartk && $system == windows ]
+io/dart_std_io_pipe_test: Slow, Pass
+io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
+io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $compiler == dartk && $hot_reload ]
+io/http_no_reason_phrase_test: Crash
+io/http_outgoing_size_test: Crash
+
+[ $compiler == dartk && $hot_reload_rollback ]
+io/directory_chdir_test: Skip # Timeout
+io/echo_server_stream_test: Slow, Pass
+
+# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
+# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
+# batch mode.
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
+io/file_blocking_lock_test: Crash # Please triage.
+io/file_lock_test: Slow, Pass
+map_insert_remove_oom_test: Skip # Heap limit too low.
+
+[ $compiler == dartk && ($hot_reload || $hot_reload_rollback) ]
+io/addlatexhash_test: Skip # Timeout
+io/http_advanced_test: Skip # Timeout
+io/http_auth_digest_test: Crash
+io/http_auth_test: Skip # Timeout
+io/http_proxy_advanced_test: Skip # Timeout
+io/http_read_test: Skip # Timeout
+io/pipe_server_test: Skip # Timeout
+io/socket_close_test: Skip # Timeout
+io/socket_many_connections_test: Skip # Timeout
+io/web_socket_compression_test: Skip # Timeout
+io/web_socket_test: Skip # Timeout
+
 [ $compiler == dartkp && $mode == debug && $runtime == dart_precompiled ]
 io/raw_socket_test: Crash
 io/socket_exception_test: Crash
@@ -63,55 +109,5 @@
 map_insert_remove_oom_test: Skip # Heap limit too low.
 no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
 
-[ $mode == debug && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-io/file_lock_test: Slow, Pass
-io/raw_socket_test: Crash
-io/socket_exception_test: Crash
-io/socket_finalizer_test: Crash
-io/socket_info_ipv4_test: Crash
-io/socket_info_ipv6_test: Crash
-io/socket_port_test: Crash
-
-[ $mode == debug && $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-io/web_socket_ping_test: Crash
-
-[ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
-
-[ $system == windows && ($compiler == dartk || $compiler == dartkb) ]
-io/dart_std_io_pipe_test: Slow, Pass
-io/secure_builtin_roots_test: Skip # Issues 32137 and 32138.
-io/wait_for_event_isolate_test: Skip # Issues 32137 and 32138.
-map_insert_remove_oom_test: Skip # Heap limit too low.
-
-[ $hot_reload && ($compiler == dartk || $compiler == dartkb) ]
-io/http_no_reason_phrase_test: Crash
-io/http_outgoing_size_test: Crash
-
-[ $hot_reload_rollback && ($compiler == dartk || $compiler == dartkb) ]
-io/directory_chdir_test: Skip # Timeout
-io/echo_server_stream_test: Slow, Pass
-
-# Enabling of dartk for sim{arm,arm64} revealed these test failures, which
-# are to be triaged.  Isolate tests are skipped on purpose due to the usage of
-# batch mode.
-[ ($arch == simarm || $arch == simarm64) && ($compiler == dartk || $compiler == dartkb) ]
-io/file_blocking_lock_test: Crash # Please triage.
-io/file_lock_test: Slow, Pass
-map_insert_remove_oom_test: Skip # Heap limit too low.
-
-[ ($compiler == dartk || $compiler == dartkb) && ($hot_reload || $hot_reload_rollback) ]
-io/addlatexhash_test: Skip # Timeout
-io/http_advanced_test: Skip # Timeout
-io/http_auth_digest_test: Crash
-io/http_auth_test: Skip # Timeout
-io/http_proxy_advanced_test: Skip # Timeout
-io/http_read_test: Skip # Timeout
-io/pipe_server_test: Skip # Timeout
-io/socket_close_test: Skip # Timeout
-io/socket_many_connections_test: Skip # Timeout
-io/web_socket_compression_test: Skip # Timeout
-io/web_socket_test: Skip # Timeout
-
-[ $compiler != dartk && $compiler != dartkb && $compiler != dartkp || $compiler == dartkp && $system == windows ]
+[ $compiler != dartk && $compiler != dartkp || $compiler == dartkp && $system == windows ]
 entrypoints_verification_test: SkipByDesign # Requires VM to run. Cannot run in precompiled Windows because the DLL is linked against dart.exe instead of dart_precompiled_runtime.exe.
diff --git a/tests/standalone_2/standalone_2_precompiled.status b/tests/standalone_2/standalone_2_precompiled.status
index 829aafc..1e00e12 100644
--- a/tests/standalone_2/standalone_2_precompiled.status
+++ b/tests/standalone_2/standalone_2_precompiled.status
@@ -51,6 +51,7 @@
 package/scenarios/packages_file_strange_formatting/mixed_line_ends_test: Skip
 package/scenarios/packages_option_only/packages_option_only_noimports_test: Skip
 package/scenarios/packages_option_only/packages_option_only_test: Skip
+regress_41329_*: SkipByDesign # Expects to be running from 'dart' instead of 'dart_precompiled_runtime'
 
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/socket_cancel_connect_test: RuntimeError # Issue 34142
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 2bd998d..478da0f 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -47,9 +47,6 @@
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
 
-[ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
-io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
-
 [ $arch == x64 && $mode == release && $runtime == vm && $system == linux ]
 io/http_bind_test: Pass, Timeout # Issue 35192
 
diff --git a/third_party/tcmalloc/BUILD.gn b/third_party/tcmalloc/BUILD.gn
index a2a925a..7238772 100644
--- a/third_party/tcmalloc/BUILD.gn
+++ b/third_party/tcmalloc/BUILD.gn
@@ -119,22 +119,20 @@
     cflags += [ "-Wno-format" ]
   }
 
-  set_sources_assignment_filter([
-                                  # No debug allocator.
-                                  "gperftools/src/debugallocation.cc",
+  sources = tcmalloc_sources - [
+              # No debug allocator.
+              "gperftools/src/debugallocation.cc",
 
-                                  # Not needed when using emergency malloc.
-                                  "gperftools/src/fake_stacktrace_scope.cc",
+              # Not needed when using emergency malloc.
+              "gperftools/src/fake_stacktrace_scope.cc",
 
-                                  # Not using the cpuprofiler
-                                  "gperftools/src/base/thread_lister.c",
-                                  "gperftools/src/base/thread_lister.h",
-                                  "gperftools/src/profile-handler.cc",
-                                  "gperftools/src/profile-handler.h",
-                                  "gperftools/src/profiledata.cc",
-                                  "gperftools/src/profiledata.h",
-                                  "gperftools/src/profiler.cc",
-                                ])
-
-  sources = tcmalloc_sources
+              # Not using the cpuprofiler
+              "gperftools/src/base/thread_lister.c",
+              "gperftools/src/base/thread_lister.h",
+              "gperftools/src/profile-handler.cc",
+              "gperftools/src/profile-handler.h",
+              "gperftools/src/profiledata.cc",
+              "gperftools/src/profiledata.h",
+              "gperftools/src/profiler.cc",
+            ]
 }
diff --git a/third_party/wasmer/BUILD.gn b/third_party/wasmer/BUILD.gn
index 5549fc6..afd36a8 100644
--- a/third_party/wasmer/BUILD.gn
+++ b/third_party/wasmer/BUILD.gn
@@ -1,11 +1,17 @@
 import("../../build/rust/rust.gni")
 
-component("wasmer") {
-  public = [ "wasmer.hh" ]
+shared_library("wasmer_wrapper") {
+  sources = [
+    "wasmer.hh",
+    "wasmer_wrapper.cc",
+  ]
   deps = [ ":wasmer_lib" ]
+  if (is_linux) {
+    libs = [ "rt" ]
+  }
+  ldflags = [ "-Wl,--no-as-needed" ]  # Force linking of all wasmer symbols.
 }
 
 rust_library("wasmer_lib") {
   lib_name = "wasmer"
-  shared = true
 }
diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml
index 67c601b..bfe6172 100644
--- a/third_party/wasmer/Cargo.toml
+++ b/third_party/wasmer/Cargo.toml
@@ -4,7 +4,7 @@
 
 [lib]
 name = "wasmer"
-crate-type = ["dylib"]
+crate-type = ["staticlib"]
 path = "wasmer.rs"
 
 [dependencies]
diff --git a/third_party/wasmer/wasmer_wrapper.cc b/third_party/wasmer/wasmer_wrapper.cc
new file mode 100644
index 0000000..cdfaa69
--- /dev/null
+++ b/third_party/wasmer/wasmer_wrapper.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Wraps several functions from wasmer.hh, so that they take and return all
+// structs by pointer, rather than by value. This is necessary because Dart FFI
+// doesn't support passing structs by value yet (once it does, we can delete
+// this wrapper).
+
+#include "wasmer.hh"
+
+extern "C" {
+// Wraps wasmer_export_name.
+void wasmer_export_name_ptr(wasmer_export_t* export_,
+                            wasmer_byte_array* out_name) {
+  *out_name = wasmer_export_name(export_);
+}
+
+// Wraps wasmer_export_descriptor_name.
+void wasmer_export_descriptor_name_ptr(
+    wasmer_export_descriptor_t* export_descriptor,
+    wasmer_byte_array* out_name) {
+  *out_name = wasmer_export_descriptor_name(export_descriptor);
+}
+
+// Wraps wasmer_import_descriptor_module_name.
+void wasmer_import_descriptor_module_name_ptr(
+    wasmer_import_descriptor_t* import_descriptor,
+    wasmer_byte_array* out_name) {
+  *out_name = wasmer_import_descriptor_module_name(import_descriptor);
+}
+
+// Wraps wasmer_import_descriptor_name.
+void wasmer_import_descriptor_name_ptr(
+    wasmer_import_descriptor_t* import_descriptor,
+    wasmer_byte_array* out_name) {
+  *out_name = wasmer_import_descriptor_name(import_descriptor);
+}
+
+// Wraps wasmer_memory_new.
+wasmer_result_t wasmer_memory_new_ptr(wasmer_memory_t** memory,
+                                      wasmer_limits_t* limits) {
+  return wasmer_memory_new(memory, *limits);
+}
+}
diff --git a/tools/VERSION b/tools/VERSION
index 96d1078..a469e53 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL beta
 MAJOR 2
-MINOR 10
+MINOR 11
 PATCH 0
-PRERELEASE 110
-PRERELEASE_PATCH 5
+PRERELEASE 213
+PRERELEASE_PATCH 1
\ No newline at end of file
diff --git a/tools/bots/dart_sdk.py b/tools/bots/dart_sdk.py
index f152233..77daa10 100755
--- a/tools/bots/dart_sdk.py
+++ b/tools/bots/dart_sdk.py
@@ -41,13 +41,16 @@
     dart_exe = os.path.join(dart_sdk, 'bin', 'dart')
     dartdoc_dart = os.path.join(bot_utils.DART_DIR, 'third_party', 'pkg',
                                 'dartdoc', 'bin', 'dartdoc.dart')
+    footer_text_file = os.path.join(bot_utils.DART_DIR, 'tools', 'bots',
+                                    'dartdoc_footer_text.html')
     footer_file = os.path.join(bot_utils.DART_DIR, 'tools', 'bots',
                                'dartdoc_footer.html')
     url = 'https://api.dartlang.org/stable'
     with bot.BuildStep('Build API docs by dartdoc'):
         bot_utils.run([
             dart_exe, dartdoc_dart, '--sdk-docs', '--output', dirname,
-            '--enable-experiment', 'non-nullable', '--footer', footer_file,
+            '--enable-experiment', 'non-nullable', '--footer-text',
+            footer_text_file, '--footer', footer_file,
             '--rel-canonical-prefix=' + url
         ])
 
diff --git a/tools/bots/dartdoc_footer_text.html b/tools/bots/dartdoc_footer_text.html
new file mode 100644
index 0000000..6664882
--- /dev/null
+++ b/tools/bots/dartdoc_footer_text.html
@@ -0,0 +1,5 @@
+&bull;
+<span class="copyright no-break">
+  <a href="http://creativecommons.org/licenses/by/4.0/">Site CC BY 4.0</a>
+</span>
+
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index d540f0f..6f1f168 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -365,6 +365,7 @@
       "pkg/status_file/",
       "pkg/test_runner/",
       "pkg/vm/",
+      "pkg/vm_snapshot_analysis/",
       "runtime/",
       "sdk/",
       ".dart_tool/package_config.json",
@@ -397,10 +398,7 @@
         "enable-asserts": true,
         "mode": "release",
         "runtime": "vm",
-        "timeout": 240,
-        "enable-experiment": [
-          "non-nullable"
-        ]
+        "timeout": 240
       }
     },
     "analyzer-unittest-asserts-(debug|product|release)-(linux|mac|win)": {
@@ -515,12 +513,6 @@
     "dart2js-weak-(linux|mac|win)-x64-d8": {
       "options": {
         "builder-tag": "dart2js-weak",
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "dart2js-options": [
-          "--no-sound-null-safety"
-        ],
         "use-sdk": true
       }
     },
@@ -575,11 +567,7 @@
     "dart2js-hostasserts-weak-(linux|win)-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-weak",
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "dart2js-options": [
-          "--no-sound-null-safety",
           "--libraries-spec=sdk/lib/libraries.json",
           "--platform-binaries=out/ReleaseX64/"
         ],
@@ -590,11 +578,7 @@
     "dart2js-hostasserts-weak-mac-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-weak",
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "dart2js-options": [
-          "--no-sound-null-safety",
           "--libraries-spec=sdk/lib/libraries.json",
           "--platform-binaries=xcodebuild/ReleaseX64/"
         ],
@@ -605,11 +589,7 @@
     "dart2js-hostasserts-strong-(linux|win)-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-strong",
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "dart2js-options": [
-          "--sound-null-safety",
           "--libraries-spec=sdk/lib/libraries.json",
           "--platform-binaries=out/ReleaseX64/"
         ],
@@ -620,11 +600,7 @@
     "dart2js-hostasserts-strong-mac-x64-(d8|chrome)": {
       "options": {
         "builder-tag": "dart2js-strong",
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "dart2js-options": [
-          "--sound-null-safety",
           "--libraries-spec=sdk/lib/libraries.json",
           "--platform-binaries=xcodebuild/ReleaseX64/"
         ],
@@ -654,6 +630,16 @@
         "builder-tag": "crossword"
       }
     },
+    "dartkp-weak-asserts-linux-(debug|product|release)-simarm-crossword": {
+      "options": {
+        "builder-tag": "crossword"
+      }
+    },
+    "dartkp-strong-linux-(debug|product|release)-simarm-crossword": {
+      "options": {
+        "builder-tag": "crossword"
+      }
+    },
     "dartkp-(win|mac)-(debug|product|release)-simarm-crossword": {
       "options": {
         "builder-tag": "crossword",
@@ -709,151 +695,52 @@
     },
     "dartkp-weak-asserts-(linux|mac)-(debug|product|release)-x64": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--no-sound-null-safety"
-        ],
         "enable-asserts": true,
-        "vm-options": [
-          "--no-sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
     "dartkp-weak-asserts-(linux|mac)-(debug|product|release)-simarm64": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--no-sound-null-safety"
-        ],
         "enable-asserts": true,
         "use-elf": true,
-        "vm-options": [
-          "--no-sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
     "dartkp-weak-asserts-win-(debug|product|release)-(simarm64|x64)": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--no-sound-null-safety"
-        ],
         "enable-asserts": true,
         "use-elf": true,
-        "vm-options": [
-          "--no-sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartk-weak-asserts-(linux|mac|win)-(debug|product|release)-x64": {
+    "dartk-weak-asserts-(linux|mac|win)-(debug|product|release)-(ia32|simarm|simarm64|x64)": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "enable-asserts": true,
-        "vm-options": [
-          "--no-sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartk-strong-(linux|mac|win)-(debug|product|release)-x64": {
+    "dartk-strong-(linux|mac|win)-(debug|product|release)-(ia32|simarm|simarm64|x64)": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "vm-options": [
-          "--sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
     "dartkp-strong-(linux|mac)-(debug|product|release)-x64": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--sound-null-safety"
-        ],
-        "vm-options": [
-          "--sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
     "dartkp-strong-(linux|mac)-(debug|product|release)-simarm64": {
       "options": {
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--sound-null-safety"
-        ],
         "use-elf": true,
-        "vm-options": [
-          "--sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
     "dartkp-strong-win-(debug|product|release)-(simarm64|x64)": {
       "options": {
         "use-elf": true,
-        "enable-experiment": [
-          "non-nullable"
-        ],
-        "gen-kernel-options": [
-          "--sound-null-safety"
-        ],
-        "vm-options": [
-          "--sound-null-safety"
-        ],
         "builder-tag": "vm_nnbd"
       }
     },
-    "dartk-(linux|mac|win)-(debug|product|release)-(ia32|simarm|simarm64|x64)-ast": {
-      "options": {
-        "builder-tag": "ast",
-        "gen-kernel-options": [
-          "--no-gen-bytecode"
-        ]
-      }
-    },
-    "dartkp-(linux|mac)-(debug|product|release)-x64-ast": {
-      "options": {
-        "builder-tag": "ast",
-        "gen-kernel-options": [
-          "--no-gen-bytecode"
-        ]
-      }
-    },
-    "dartkp-(linux|mac)-(debug|product|release)-simarm64-ast": {
-      "options": {
-        "builder-tag": "ast",
-        "use-elf": true,
-        "gen-kernel-options": [
-          "--no-gen-bytecode"
-        ]
-      }
-    },
-    "dartkp-linux-(debug|product|release)-simarm-crossword-ast": {
-      "options": {
-        "builder-tag": "crossword_ast",
-        "gen-kernel-options": [
-          "--no-gen-bytecode"
-        ]
-      }
-    },
     "dartk-checked-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {
       "options": {
         "enable-asserts": true
@@ -890,60 +777,6 @@
       }
     },
     "app_jitk-(linux|mac|win)-(debug|product|release)-(ia32|x64)": {},
-    "dartkb-interpret-(linux|mac|win)-product-(ia32|x64|arm|arm64|simarm|simarm64)": {
-      "options": {
-        "builder-tag": "bytecode_interpreter",
-        "gen-kernel-options": [
-          "--gen-bytecode",
-          "--drop-ast",
-          "--bytecode-options=source-positions,annotations"
-        ],
-        "vm-options": [
-          "--enable_interpreter",
-          "--compilation-counter-threshold=-1"
-        ]
-      }
-    },
-    "dartkb-interpret-(linux|mac|win)-(debug|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
-      "options": {
-        "builder-tag": "bytecode_interpreter",
-        "gen-kernel-options": [
-          "--gen-bytecode",
-          "--drop-ast",
-          "--bytecode-options=source-positions,annotations,local-var-info,debugger-stops"
-        ],
-        "vm-options": [
-          "--enable_interpreter",
-          "--compilation-counter-threshold=-1"
-        ]
-      }
-    },
-    "dartkb-mixed-(linux|mac|win)-(debug|release)-(ia32|x64|arm|arm64|simarm|simarm64)": {
-      "options": {
-        "builder-tag": "bytecode_mixed",
-        "gen-kernel-options": [
-          "--gen-bytecode",
-          "--drop-ast",
-          "--bytecode-options=source-positions,annotations,local-var-info,debugger-stops"
-        ],
-        "vm-options": [
-          "--enable_interpreter"
-        ]
-      }
-    },
-    "dartkb-mixed-(linux|mac|win)-product-(ia32|x64|arm|arm64|simarm|simarm64)": {
-      "options": {
-        "builder-tag": "bytecode_mixed",
-        "gen-kernel-options": [
-          "--gen-bytecode",
-          "--drop-ast",
-          "--bytecode-options=source-positions,annotations"
-        ],
-        "vm-options": [
-          "--enable_interpreter"
-        ]
-      }
-    },
     "dartdevk-checked-(linux|mac|win)-(debug|product|release)-(chrome|firefox)": {
       "options": {
         "checked": true,
@@ -954,9 +787,6 @@
       "options": {
         "checked": true,
         "use-sdk": true,
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "enable-asserts": true
       }
     },
@@ -964,9 +794,6 @@
       "options": {
         "checked": true,
         "use-sdk": true,
-        "enable-experiment": [
-          "non-nullable"
-        ],
         "enable-asserts": true
       }
     },
@@ -977,18 +804,12 @@
     },
     "cfe-weak-(linux|mac|win)": {
       "options": {
-        "compiler": "fasta",
-        "enable-experiment": [
-          "non-nullable"
-        ]
+        "compiler": "fasta"
       }
     },
     "cfe-strong-(linux|mac|win)": {
       "options": {
-        "compiler": "fasta",
-        "enable-experiment": [
-          "non-nullable"
-        ]
+        "compiler": "fasta"
       }
     },
     "analyzer-(linux|mac|win)": {
@@ -1008,20 +829,14 @@
       "options": {
         "compiler": "dart2analyzer",
         "enable-asserts": true,
-        "use-sdk": true,
-        "enable-experiment": [
-          "non-nullable"
-        ]
+        "use-sdk": true
       }
     },
     "analyzer-asserts-weak-(linux|mac|win)": {
       "options": {
         "compiler": "dart2analyzer",
         "enable-asserts": true,
-        "use-sdk": true,
-        "enable-experiment": [
-          "non-nullable"
-        ]
+        "use-sdk": true
       }
     }
   },
@@ -1076,15 +891,16 @@
           "testRunner": true,
           "arguments": [
             "pkg/front_end/test/unit_test_suites.dart",
-            "-ncfe-unittest-asserts-${mode}-${system}",
-            "--verbose"
+            "-ncfe-unittest-asserts-${mode}-${system}"
           ]
         }
       ]
     },
     {
       "builders": [
-        "front-end-nnbd-linux-release-x64"
+        "front-end-nnbd-linux-release-x64",
+        "front-end-nnbd-mac-release-x64",
+        "front-end-nnbd-win-release-x64"
       ],
       "meta": {
         "description": "Runs the front-end tests with NNBD"
@@ -1107,7 +923,7 @@
             "co19"
           ],
           "fileset": "front-end",
-          "shards": 1
+          "shards": 2
         },
         {
           "name": "strong co19 tests",
@@ -1116,7 +932,7 @@
             "co19"
           ],
           "fileset": "front-end",
-          "shards": 1
+          "shards": 2
         },
         {
           "name": "weak sdk tests",
@@ -1142,59 +958,6 @@
     },
     {
       "builders": [
-        "vm-dartkb-linux-release-x64",
-        "vm-dartkb-linux-release-simarm64"
-      ],
-      "meta": {
-        "description": "This configuration is used by the vm kbc builders."
-      },
-      "steps": [
-        {
-          "name": "build dart",
-          "script": "tools/build.py",
-          "arguments": [
-            "--bytecode",
-            "runtime"
-          ]
-        },
-        {
-          "name": "vm mixed mode tests",
-          "arguments": [
-            "-ndartkb-mixed-linux-${mode}-${arch}"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        },
-        {
-          "name": "vm mixed mode co19 tests",
-          "arguments": [
-            "-ndartkb-mixed-linux-${mode}-${arch}",
-            "co19_2"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        },
-        {
-          "name": "vm interpreter tests",
-          "arguments": [
-            "-ndartkb-interpret-linux-${mode}-${arch}"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        },
-        {
-          "name": "vm interpreter co19 tests",
-          "arguments": [
-            "-ndartkb-interpret-linux-${mode}-${arch}",
-            "co19_2"
-          ],
-          "fileset": "vm-kernel",
-          "shards": 4
-        }
-      ]
-    },
-    {
-      "builders": [
         "vm-canary-linux-debug"
       ],
       "meta": {
@@ -1323,8 +1086,11 @@
     },
     {
       "builders": [
+        "vm-kernel-precomp-nnbd-linux-debug-x64",
         "vm-kernel-precomp-nnbd-linux-release-simarm64",
-        "vm-kernel-precomp-nnbd-linux-release-x64"
+        "vm-kernel-precomp-nnbd-linux-release-x64",
+        "vm-kernel-precomp-nnbd-mac-release-simarm64",
+        "vm-kernel-precomp-nnbd-win-release-x64"
       ],
       "meta": {
         "description": "This configuration is for the VM AOT nnbd builder group."
@@ -1342,29 +1108,35 @@
           "name": "vm nnbd tests in weak mode with asserts",
           "arguments": [
             "-ndartkp-weak-asserts-${system}-${mode}-${arch}",
+            "benchmark_smoke",
             "corelib",
             "ffi",
             "language",
             "lib",
-            "standalone/io",
+            "samples",
+            "standalone",
+            "utils",
             "vm"
           ],
           "fileset": "vm-kernel",
-          "shards": 4
+          "shards": 6
         },
         {
           "name": "vm nnbd tests in strong mode",
           "arguments": [
             "-ndartkp-strong-${system}-${mode}-${arch}",
+            "benchmark_smoke",
             "corelib",
             "ffi",
             "language",
             "lib",
-            "standalone/io",
+            "samples",
+            "standalone",
+            "utils",
             "vm"
           ],
           "fileset": "vm-kernel",
-          "shards": 4
+          "shards": 6
         },
         {
           "name": "co19 nnbd tests in strong mode",
@@ -1373,7 +1145,7 @@
             "co19"
           ],
           "fileset": "vm-kernel",
-          "shards": 6
+          "shards": 10
         },
         {
           "name": "co19 nnbd tests in weak mode with asserts",
@@ -1382,7 +1154,7 @@
             "co19"
           ],
           "fileset": "vm-kernel",
-          "shards": 6
+          "shards": 10
         }
       ]
     },
@@ -1693,8 +1465,17 @@
     },
     {
       "builders": [
+        "vm-kernel-nnbd-linux-debug-ia32",
+        "vm-kernel-nnbd-linux-debug-x64",
+        "vm-kernel-nnbd-linux-release-ia32",
+        "vm-kernel-nnbd-linux-release-simarm",
+        "vm-kernel-nnbd-linux-release-simarm64",
         "vm-kernel-nnbd-linux-release-x64",
-        "vm-kernel-nnbd-linux-debug-x64"
+        "vm-kernel-nnbd-mac-debug-x64",
+        "vm-kernel-nnbd-mac-release-x64",
+        "vm-kernel-nnbd-win-release-ia32",
+        "vm-kernel-nnbd-win-debug-x64",
+        "vm-kernel-nnbd-win-release-x64"
       ],
       "meta": {
         "description": "This configuration is for the VM nnbd builder group."
@@ -1709,34 +1490,56 @@
           ]
         },
         {
-          "name": "vm nnbd test in weak mode with asserts",
+          "name": "vm nnbd tests in weak mode with asserts",
           "arguments": [
             "-ndartk-weak-asserts-${system}-${mode}-${arch}",
+            "benchmark_smoke",
             "corelib",
             "ffi",
             "language",
             "lib",
-            "co19",
-            "standalone/io",
+            "samples",
+            "standalone",
+            "utils",
             "vm"
           ],
           "fileset": "vm-kernel",
-          "shards": 2
+          "shards": 6
+        },
+        {
+          "name": "vm co19 nnbd tests in weak mode with asserts",
+          "arguments": [
+            "-ndartk-weak-asserts-${system}-${mode}-${arch}",
+            "co19"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 8
         },
         {
           "name": "vm nnbd tests in strong mode",
           "arguments": [
             "-ndartk-strong-${system}-${mode}-${arch}",
+            "benchmark_smoke",
             "corelib",
             "ffi",
             "language",
             "lib",
-            "co19",
-            "standalone/io",
+            "samples",
+            "standalone",
+            "utils",
             "vm"
           ],
           "fileset": "vm-kernel",
-          "shards": 2
+          "shards": 6
+        },
+        {
+          "name": "vm co19 nnbd tests in strong mode",
+          "arguments": [
+            "-ndartk-strong-${system}-${mode}-${arch}",
+            "co19"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 8
         }
       ]
     },
@@ -2895,10 +2698,12 @@
     },
     {
       "builders": [
-        "analyzer-nnbd-linux-release"
+        "analyzer-nnbd-linux-release",
+        "analyzer-nnbd-mac-release",
+        "analyzer-nnbd-win-release"
       ],
       "meta": {
-        "description": "This configuration is used by the nnbd analyzer builder."
+        "description": "This configuration is used by the nnbd analyzer builders."
       },
       "steps": [
         {
@@ -3539,7 +3344,6 @@
           "name": "build dart for simarm_x64",
           "script": "tools/build.py",
           "arguments": [
-            "--bytecode",
             "gen_snapshot"
           ]
         },
@@ -3548,7 +3352,6 @@
           "script": "tools/build.py",
           "arguments": [
             "--arch=simarm",
-            "--bytecode",
             "dart_precompiled_runtime",
             "vm_platform"
           ]
@@ -3562,6 +3365,67 @@
           "shards": 10
         }
       ]
+    },
+    {
+      "builders": [
+        "vm-kernel-precomp-nnbd-linux-debug-simarm_x64",
+        "vm-kernel-precomp-nnbd-linux-release-simarm_x64"
+      ],
+      "meta": {
+        "description": "This configuration runs tests for the simarm_x64 architecture."
+      },
+      "steps": [
+        {
+          "name": "build dart for simarm_x64",
+          "script": "tools/build.py",
+          "arguments": [
+            "gen_snapshot"
+          ]
+        },
+        {
+          "name": "build dart for simarm",
+          "script": "tools/build.py",
+          "arguments": [
+            "--arch=simarm",
+            "dart_precompiled_runtime",
+            "vm_platform"
+          ]
+        },
+        {
+          "name": "vm weak tests",
+          "arguments": [
+            "-ndartkp-weak-asserts-${system}-${mode}-simarm-crossword",
+            "benchmark_smoke",
+            "corelib",
+            "ffi",
+            "language",
+            "lib",
+            "samples",
+            "standalone",
+            "utils",
+            "vm"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 10
+        },
+        {
+          "name": "vm tests",
+          "arguments": [
+            "-ndartkp-strong-${system}-${mode}-simarm-crossword",
+            "benchmark_smoke",
+            "corelib",
+            "ffi",
+            "language",
+            "lib",
+            "samples",
+            "standalone",
+            "utils",
+            "vm"
+          ],
+          "fileset": "vm-kernel",
+          "shards": 10
+        }
+      ]
     }
   ],
   "sanitizer_options": {
diff --git a/tools/bots/try_benchmarks.sh b/tools/bots/try_benchmarks.sh
index 920e30a..0c0ed78 100755
--- a/tools/bots/try_benchmarks.sh
+++ b/tools/bots/try_benchmarks.sh
@@ -146,7 +146,6 @@
       out/ReleaseIA32/vm_platform_strong.dill \
       out/ReleaseIA32/gen/kernel_service.dill \
       out/ReleaseIA32/dart-sdk \
-      tools/dart2js/angular2_testing_deps \
       out/ReleaseIA32/dart \
       out/ReleaseIA32/gen_snapshot \
       out/ReleaseIA32/gen_kernel_bytecode.dill \
@@ -159,8 +158,6 @@
       .packages \
       .dart_tool/package_config.json \
       pkg \
-      runtime/bin \
-      runtime/lib \
       benchmarks \
       || (rm -f linux-ia32.tar.gz; exit 1)
   elif [ "$command" = linux-ia32-benchmark ]; then
@@ -310,8 +307,6 @@
       .packages \
       .dart_tool/package_config.json \
       pkg \
-      runtime/bin \
-      runtime/lib \
       benchmarks \
       || (rm -f linux-x64.tar.gz; exit 1)
   elif [ "$command" = linux-x64-benchmark ]; then
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 0761fe6..3b35750 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -890,53 +890,64 @@
 promise_attributes = monitored.Dict(
     'systemhtml.promise_attr_type', {
         "Animation.finished": {
-            "type": "Animation"
+            "type": "Animation",
+            "creates": "Animation"
         },
         "Animation.ready": {
-            "type": "Animation"
+            "type": "Animation",
+            "creates": "Animation"
         },
         "BeforeInstallPromptEvent.userChoice": {
             "type": "dictionary"
         },
         "FontFace.loaded": {
-            "type": "FontFace"
+            "type": "FontFace",
+            "creates": "FontFace"
         },
         "FontFaceSet.ready": {
-            "type": "FontFaceSet"
+            "type": "FontFaceSet",
+            "creates": "FontFaceSet"
         },
         "MediaKeySession.closed": {
             "type": "void"
         },
         "PresentationReceiver.connectionList": {
-            "type": "PresentationConnectionList"
+            "type": "PresentationConnectionList",
+            "creates": "PresentationConnectionList"
         },
         "ServiceWorkerContainer.ready": {
-            "type": "ServiceWorkerRegistration"
+            "type": "ServiceWorkerRegistration",
+            "creates": "ServiceWorkerRegistration"
         },
     })
 
 promise_operations = monitored.Dict(
     'systemhtml.promise_oper_type', {
         "Clipboard.read": {
-            "type": "DataTransfer"
+            "type": "DataTransfer",
+            "creates": "DataTransfer"
         },
         "Clipboard.readText": {
             "type": "String"
         },
         "FontFace.load": {
-            "type": "FontFace"
+            "type": "FontFace",
+            "creates": "FontFace"
         },
         "FontFaceSet.load": {
             "type": "List<dynamic>"
         },
         "OffscreenCanvas.load": {
-            "type": "Blob"
+            "type": "Blob",
+            "creates": "Blob"
         },
         "BackgroundFetchManager.fetch": {
-            "type": "BackgroundFetchRegistration"
+            "type": "BackgroundFetchRegistration",
+            "creates": "BackgroundFetchRegistration"
         },
         "BackgroundFetchManager.get": {
-            "type": "BackgroundFetchRegistration"
+            "type": "BackgroundFetchRegistration",
+            "creates": "BackgroundFetchRegistration"
         },
         "BackgroundFetchManager.getIds": {
             "type": "List<dynamic>"
@@ -951,49 +962,60 @@
             "type": "double"
         },
         "BudgetService.getBudget": {
-            "type": "BudgetState"
+            "type": "BudgetState",
+            "creates": "BudgetState"
         },
         "BudgetService.reserve": {
             "type": "bool"
         },
         "Body.blob": {
-            "type": "Blob"
+            "type": "Blob",
+            "creates": "Blob"
         },
         "Body.formData": {
-            "type": "FormData"
+            "type": "FormData",
+            "creates": "FormData"
         },
         "Body.text": {
             "type": "String"
         },
         "ImageCapture.getPhotoCapabilities": {
-            "type": "PhotoCapabilities"
+            "type": "PhotoCapabilities",
+            "creates": "PhotoCapabilities"
         },
         "ImageCapture.getPhotoSettings": {
             "type": "dictionary"
         },
         "ImageCapture.takePhoto": {
-            "type": "Blob"
+            "type": "Blob",
+            "creates": "Blob"
         },
         "ImageCapture.grabFrame": {
-            "type": "ImageBitmap"
+            "type": "ImageBitmap",
+            "creates": "ImageBitmap"
         },
         "Navigator.getInstalledRelatedApps": {
-            "type": "RelatedApplication"
+            "type": "RelatedApplication",
+            "creates": "RelatedApplication"
         },
         "OffscreenCanvas.convertToBlob": {
-            "type": "Blob"
+            "type": "Blob",
+            "creates": "Blob"
         },
         "MediaCapabilities.decodingInfo": {
-            "type": "MediaCapabilitiesInfo"
+            "type": "MediaCapabilitiesInfo",
+            "creates": "MediaCapabilitiesInfo"
         },
         "MediaCapabilities.encodingInfo": {
-            "type": "MediaCapabilitiesInfo"
+            "type": "MediaCapabilitiesInfo",
+            "creates": "MediaCapabilitiesInfo"
         },
         "MediaDevices.enumerateDevices": {
             "type": "List<dynamic>"
         },
         "MediaDevices.getUserMedia": {
-            "type": "MediaStream"
+            "type": "MediaStream",
+            "creates": "MediaStream"
         },
         "ServiceWorkerRegistration.getNotifications": {
             "type": "List<dynamic>"
@@ -1011,53 +1033,68 @@
             "type": "bool"
         },
         "PaymentRequest.show": {
-            "type": "PaymentResponse"
+            "type": "PaymentResponse",
+            "creates": "PaymentResponse"
         },
         "PaymentRequest.canMakePayment": {
             "type": "bool"
         },
         "PaymentRequestEvent.openWindow": {
-            "type": "WindowClient"
+            "type": "WindowClient",
+            "creates": "WindowClient"
         },
         "RTCPeerConnection.createOffer": {
-            "type": "RtcSessionDescription"
+            "type": "RtcSessionDescription",
+            "creates": "RtcSessionDescription"
         },
         "RTCPeerConnection.createAnswer": {
-            "type": "RtcSessionDescription"
+            "type": "RtcSessionDescription",
+            "creates": "RtcSessionDescription"
         },
         "RTCPeerConnection.getStats": {
             "type": "RtcStatsReport",
-            "maplike": "RTCStatsReport"
+            "maplike": "RTCStatsReport",
+            "creates": "RtcStatsReport"
         },
         "RTCPeerConnection.generateCertificate": {
-            "type": "RtcCertificate"
+            "type": "RtcCertificate",
+            "creates": "RtcCertificate"
         },
         "Permissions.query": {
-            "type": "PermissionStatus"
+            "type": "PermissionStatus",
+            "creates": "PermissionStatus"
         },
         "Permissions.request": {
-            "type": "PermissionStatus"
+            "type": "PermissionStatus",
+            "creates": "PermissionStatus"
         },
         "Permissions.revoke": {
-            "type": "PermissionStatus"
+            "type": "PermissionStatus",
+            "creates": "PermissionStatus"
         },
         "Permissions.requestAll": {
-            "type": "PermissionStatus"
+            "type": "PermissionStatus",
+            "creates": "PermissionStatus"
         },
         "PresentationRequest.start": {
-            "type": "PresentationConnection"
+            "type": "PresentationConnection",
+            "creates": "PresentationConnection"
         },
         "PresentationRequest.reconnect": {
-            "type": "PresentationConnection"
+            "type": "PresentationConnection",
+            "creates": "PresentationConnection"
         },
         "PresentationRequest.getAvailability": {
-            "type": "PresentationAvailability"
+            "type": "PresentationAvailability",
+            "creates": "PresentationAvailability"
         },
         "PushManager.subscribe": {
-            "type": "PushSubscription"
+            "type": "PushSubscription",
+            "creates": "PushSubscription"
         },
         "PushManager.getSubscription": {
-            "type": "PushSubscription"
+            "type": "PushSubscription",
+            "creates": "PushSubscription"
         },
         "PushSubscription.unsubscribe": {
             "type": "bool"
@@ -1078,31 +1115,36 @@
             "type": "List<dynamic>"
         },
         "Clients.openWindow": {
-            "type": "WindowClient"
+            "type": "WindowClient",
+            "creates": "WindowClient"
         },
         "NavigationPreloadManager.getState": {
             "type": "dictionary"
         },
         "ServiceWorkerContainer.register": {
-            "type": "ServiceWorkerRegistration"
+            "type": "ServiceWorkerRegistration",
+            "creates": "ServiceWorkerRegistration"
         },
         "ServiceWorkerContainer.getRegistration": {
-            "type": "ServiceWorkerRegistration"
+            "type": "ServiceWorkerRegistration",
+            "creates": "ServiceWorkerRegistration"
         },
         "ServiceWorkerContainer.getRegistrations": {
             "type": "List<dynamic>"
         },
         "ServiceWorkerGlobalScope.fetch": {
-            "type": "Response"
+            "creates": "_Response"
         },
         "ServiceWorkerRegistration.unregister": {
             "type": "bool"
         },
         "WindowClient.focus": {
-            "type": "WindowClient"
+            "type": "WindowClient",
+            "creates": "WindowClient"
         },
         "WindowClient.navigate": {
-            "type": "WindowClient"
+            "type": "WindowClient",
+            "creates": "WindowClient"
         },
         "BarcodeDetector.detect": {
             "type": "List<dynamic>"
@@ -1114,10 +1156,48 @@
             "type": "List<dynamic>"
         },
         "BaseAudioContext.decodeAudioData": {
-            "type": "AudioBuffer"
+            "type": "AudioBuffer",
+            "creates": "AudioBuffer"
         },
         "OfflineAudioContext.startRendering": {
-            "type": "AudioBuffer"
+            "type": "AudioBuffer",
+            "creates": "AudioBuffer"
+        },
+        "CacheStorage.match": {
+            "creates": "_Response"
+        },
+        "CacheStorage.open": {
+            "creates": "_Cache"
+        },
+        "CredentialsContainer.create": {
+            "creates": "Credential"
+        },
+        "CredentialsContainer.get": {
+            "creates": "Credential"
+        },
+        "CredentialsContainer.store": {
+            "creates": "Credential"
+        },
+        "FetchEvent.preloadResponse": {
+            "creates": "_Response"
+        },
+        "MediaKeySystemAccess.createMediaKeys": {
+            "creates": "MediaKeys"
+        },
+        "Navigator.getVRDisplays": {
+            "creates": "VRDisplay"
+        },
+        "Navigator.requestMediaKeySystemAccess": {
+            "creates": "MediaKeySystemAccess"
+        },
+        "VRSession.requestFrameOfReference": {
+            "creates": "VRFrameOfReference"
+        },
+        "Window.fetch": {
+            "creates": "_Response"
+        },
+        "WorkerGlobalScope.fetch": {
+            "creates": "_Response"
         },
     })
 
@@ -1492,11 +1572,13 @@
                 promiseFound = _GetPromiseAttributeType(lookupOp)
                 promiseType = 'Future'
                 promiseCall = 'promiseToFuture'
+                type_description = ''
                 if promiseFound is not (None):
+                    paramType = promiseFound.get('type')
                     if 'maplike' in promiseFound:
                         promiseCall = 'promiseToFuture<dynamic>'
                         promiseType = 'Future'
-                    elif promiseFound['type'] == 'dictionary':
+                    elif paramType == 'dictionary':
                         # It's a dictionary so return as a Map.
                         promiseCall = 'promiseToFutureAsMap'
                         output_conversion = self._OutputConversion("Dictionary",
@@ -1505,15 +1587,18 @@
                             else ''
                         promiseType = 'Future<Map<String, dynamic>' + \
                             nullability + '>'
-                    else:
-                        paramType = promiseFound['type']
+                    elif paramType:
                         promiseCall = 'promiseToFuture<%s>' % paramType
                         promiseType = 'Future<%s>' % paramType
 
+                    if 'creates' in promiseFound:
+                        createsType = promiseFound['creates']
+                        type_description = 'creates:%s;' % createsType
+
                 if attribute.type.nullable:
                     promiseType += '?'
 
-                template = '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
+                template = '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("$TYPE_DESC", "#.$NAME", this));\n'
 
                 self._members_emitter.Emit(
                     template,
@@ -1521,7 +1606,8 @@
                     ANNOTATIONS=metadata,
                     TYPE=promiseType,
                     PROMISE_CALL=promiseCall,
-                    NAME=html_name)
+                    TYPE_DESC=type_description,
+                    NAME=html_name,)
             else:
                 # Need to use a getter for list.length properties so we can
                 # add a setter which throws an exception, satisfying List
@@ -1733,11 +1819,12 @@
         return resultType
 
     def _zeroArgs(self, argsNames):
-        return 'JS("", "#.$JSNAME()", this)'
+        return 'JS("$TYPE_DESC", "#.$JSNAME()", this)'
 
     def _manyArgs(self, numberArgs, argsNames):
         argsPound = "#" if numberArgs == 1 else ("#, " * numberArgs)[:-2]
-        return '    JS("", "#.$JSNAME(%s)", this, %s)' % (argsPound, argsNames)
+        template = '    JS("$TYPE_DESC", "#.$JSNAME(%s)", this, %s)'
+        return template % (argsPound, argsNames)
 
     """ If argument conversionsMapToDictionary is a list first entry is argument
       name and second entry signals if argument is optional (True). """
@@ -1812,13 +1899,14 @@
             promiseFound = _GetPromiseOperationType(lookupOp)
             promiseType = 'Future'
             promiseCall = 'promiseToFuture'
+            type_description = ''
             if promiseFound is not (None):
-                paramType = promiseFound['type']
+                paramType = promiseFound.get('type')
                 if 'maplike' in promiseFound:
                     if paramType == 'dictionary':
                         promiseCall = 'promiseToFuture<dynamic>'
                         promiseType = 'Future'
-                    else:
+                    elif paramType:
                         promiseCall = 'promiseToFuture<%s>' % paramType
                         promiseType = 'Future<%s>' % paramType
                 elif paramType == 'dictionary':
@@ -1830,10 +1918,14 @@
                         else ''
                     promiseType = 'Future<Map<String, dynamic>' + \
                         nullability + '>'
-                else:
+                elif paramType:
                     promiseCall = 'promiseToFuture<%s>' % paramType
                     promiseType = 'Future<%s>' % paramType
 
+                if 'creates' in promiseFound:
+                    createsType = promiseFound['creates']
+                    type_description = 'creates:%s;' % createsType
+
             argsNames = info.ParametersAsArgumentList()
             dictionary_argument = info.dictionaryArgumentName()
             codeTemplate = self._promiseToFutureCode(argsNames,
@@ -1851,6 +1943,7 @@
                 TYPE=promiseType,
                 PROMISE_CALL=promiseCall,
                 NAME=html_name,
+                TYPE_DESC=type_description,
                 JSNAME=info.declared_name,
                 PARAMS=info.ParametersAsDeclaration(self._NarrowInputType,
                                                     force_optional))
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index bbe6a37..aea853a 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -81,7 +81,7 @@
   //    ...
   //    var e = document.createElement('x-foo');
 
-  var extendsTagName = '';
+  String? extendsTagName = '';
   Type? type;
   if (options != null) {
     extendsTagName = options['extends'];
diff --git a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
index f7f535e..dc05346 100644
--- a/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/indexed_db_dart2js.darttemplate
@@ -70,7 +70,7 @@
  * and where both the keys and the values are strings.
  *
  * * [dart:web_sql]&mdash;a database that can be queried with SQL.
- * 
+ *
  * MDN provides [API
  * documentation](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).
  *
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 935f5d8..4368af2 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1390,7 +1390,7 @@
       contextElement = _parseDocument$NULLASSERT.createElement(tagName);
       _parseDocument$NULLASSERT.body$NULLASSERT.append(contextElement);
     }
-    var fragment;
+    DocumentFragment fragment;
     if (Range.supportsCreateContextualFragment &&
         _canBeUsedToCreateContextualFragment) {
       _parseRange$NULLASSERT.selectNodeContents(contextElement);
diff --git a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
index 8a49bc8..b046771 100644
--- a/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
+++ b/tools/dom/templates/html/impl/impl_IDBFactory.darttemplate
@@ -24,7 +24,7 @@
           'version and onUpgradeNeeded must be specified together'));
     }
     try {
-      var request;
+      OpenDBRequest request;
       if (version != null) {
         request = _open(name, version);
       } else {
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index ebeec9c..d750f93 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -93,7 +93,7 @@
 # default 'language' "category" with code generated for both CFE and Analyzer,
 # while other categories can be tailored more specifically.
 
-current-version: '2.10.0'
+current-version: '2.11.0'
 
 features:
   non-nullable:
@@ -126,20 +126,20 @@
 
   constant-update-2018:
     help: "Enhanced constant expressions"
-    enabledIn: '2.4.1'
+    enabledIn: '2.0.0'
     expired: true
 
   control-flow-collections:
     help: "Control Flow Collections"
-    enabledIn: '2.2.2'
+    enabledIn: '2.0.0'
     expired: true
 
   set-literals:
     help: "Set Literals"
-    enabledIn: 2.2
+    enabledIn: '2.0.0'
     expired: true
 
   spread-collections:
     help: "Spread Collections"
-    enabledIn: '2.2.2'
+    enabledIn: '2.0.0'
     expired: true
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 7c5daf2..28de041 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -20,6 +20,9 @@
     packageDirectory('runtime/observatory'),
     packageDirectory(
         'runtime/observatory/tests/service/observatory_test_package'),
+    packageDirectory('runtime/observatory_2'),
+    packageDirectory(
+        'runtime/observatory_2/tests/service_2/observatory_test_package_2'),
     packageDirectory('sdk/lib/_internal/sdk_library_metadata'),
     packageDirectory('sdk/lib/_internal/js_runtime'),
     packageDirectory('third_party/pkg/protobuf/protobuf'),
@@ -85,12 +88,6 @@
     var version = pubspecLanguageVersion(packageDir);
     var hasLibDirectory = Directory(p.join(packageDir, 'lib')).existsSync();
 
-    // TODO(rnystrom): Currently, the pre-built SDK does not allow language
-    // version 2.9.0. Until that's fixed, if we see that version, just write
-    // no version at all so that implementations use the current language
-    // version.
-    if (version.toString() == '2.9.0') version = null;
-
     yield {
       'name': p.basename(packageDir),
       'rootUri': p
diff --git a/tools/gn.py b/tools/gn.py
index fbd3a2f..11bf8a4 100755
--- a/tools/gn.py
+++ b/tools/gn.py
@@ -265,6 +265,9 @@
         gn_args['use_goma'] = False
         gn_args['goma_dir'] = None
 
+    if gn_args['target_os'] == 'mac' and gn_args['use_goma']:
+        gn_args['mac_use_goma_rbe'] = True
+
     # Code coverage requires -O0 to be set.
     if enable_code_coverage:
         gn_args['dart_debug_optimization_level'] = 0
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
index 8675fea..d3fd6ec9 100755
--- a/tools/run_offsets_extractor.sh
+++ b/tools/run_offsets_extractor.sh
@@ -14,13 +14,17 @@
   exit 1
 fi
 
-# We're regenerating the file, but we want to keep all the comments etc at the
-# top of the file. So just delete everything after the first "#if defined".
-LINE=$(grep "#if " "$FILE" -n | head -n 1 | sed "s/^\([0-9]*\):.*/\1/")
 TEMP="${FILE}.temp"
 TEMP_HEADER="${FILE}.header.temp"
 TEMP_JIT="${FILE}.jit.temp"
 TEMP_AOT="${FILE}.aot.temp"
+
+# Remove old temp files if the previous run was stopped prematurely.
+rm -rf "${TEMP}" "${TEMP_HEADER}" "${TEMP_JIT}" "${TEMP_AOT}"
+
+# We're regenerating the file, but we want to keep all the comments etc at the
+# top of the file. So just delete everything after the first "#if defined".
+LINE=$(grep "#if " "$FILE" -n | head -n 1 | sed "s/^\([0-9]*\):.*/\1/")
 head -n $(expr $LINE - 1) "$FILE" >"$TEMP_HEADER"
 
 # Run offsets_extractor for every architecture and append the results.
diff --git a/tools/sdks/README b/tools/sdks/README
index 88e40d8..b7d766a5 100644
--- a/tools/sdks/README
+++ b/tools/sdks/README
@@ -3,9 +3,8 @@
 
 The DEPS use CIPD's ${platform} syntax find the right SDK for the platform.
 
-We are currently using the 32-bit ia32 build as the default on Windows, and the
-64-bit x64 build as the default on Linux and Mac. arm and arm64 CIPD packages
-are used on Linux.
+We use the x64 build as the default on Linux, Mac and Windows. Builds for Linux
+on ARM and ARM64 are also provided.
 
 To upload new versions of these CIPD packages, run "./update.sh" in this
 directory. Because these SDKs are used for the presubmit dartfmt check on
diff --git a/tools/sdks/update.sh b/tools/sdks/update.sh
index dc96ef1..df63b09 100755
--- a/tools/sdks/update.sh
+++ b/tools/sdks/update.sh
@@ -61,9 +61,8 @@
   -ref $channel
 rm -rf sdk
 
-# We currently use the ia32 SDK on x64 Windows as well, see also README.
-gsutil.py cp "gs://dart-archive/channels/$channel/release/$1/sdk/dartsdk-windows-ia32-release.zip" .
-unzip -q dartsdk-windows-ia32-release.zip -d sdk
+gsutil.py cp "gs://dart-archive/channels/$channel/release/$1/sdk/dartsdk-windows-x64-release.zip" .
+unzip -q dartsdk-windows-x64-release.zip -d sdk
 cipd create \
   -name dart/dart-sdk/windows-amd64 \
   -in sdk \
@@ -72,16 +71,6 @@
   -ref $channel
 rm -rf sdk
 
-gsutil.py cp "gs://dart-archive/channels/$channel/release/$1/sdk/dartsdk-windows-ia32-release.zip" .
-unzip -q dartsdk-windows-ia32-release.zip -d sdk
-cipd create \
-  -name dart/dart-sdk/windows-386 \
-  -in sdk \
-  -install-mode copy \
-  -tag version:$1 \
-  -ref $channel
-rm -rf sdk
-
 popd
 
 gclient setdep --var="sdk_tag=version:$1"
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 194fe55..a056905 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -198,7 +198,9 @@
   // compatible while we migrate existing clients of this tool.
   var targetName =
       (parsedArgs['target'] as String) ?? (summaryOnly ? 'ddc' : 'vm');
-  var targetFlags = new TargetFlags(trackWidgetCreation: trackWidgetCreation);
+  var targetFlags = new TargetFlags(
+      trackWidgetCreation: trackWidgetCreation,
+      enableNullSafety: nnbdMode == fe.NnbdMode.Strong);
   Target target;
   switch (targetName) {
     case 'vm':